iT邦幫忙

2025 iThome 鐵人賽

DAY 13
0
AI & Data

咖狗報到-30天玩轉Kaggle競賽系列 第 13

一起來參加Kaggle競賽-提升實戰經驗13(Word2Vec+xgboost)

  • 分享至 

  • xImage
  •  

昨天我們完成了用 Target Encoding + RandomForest baseline model ,分數只有 0.533,雖然低(大概1600名,第一名分數高達0.93),但至少我們成功確認了資料處理流程沒有問題。

今天我們要試試更有語意理解能力的特徵表示:Word2Vec + XGBoost,看看能不能把分數提高!


1. 為什麼用 Word2Vec?

前幾天我使用的是 One-Hot 、 Frequency Encoding 跟 Target Encoding 之後接 RandomForest。
雖然這樣能快速得到一個基準分數,但它其實沒有理解文字的「語意」,只是把「類別」去做編號轉成數字而已。下面在複習一次這三個編碼方式:

1. One-Hot Encoding

把每個類別拆成一個新的欄位,用 0/1 表示是否屬於該類別。

原始顏色
1 0 0
0 1 0
0 0 1

2. Frequency Encoding

把每個類別替換成「它出現的頻率」或比例

原始顏色 Frequency Encoding
0.50
0.30
0.20

3. Target Encoding

用每個類別的目標變數平均值來取代類別

原始顏色 違規率
0.7
0.3
0.1

於是今天我們換個想法來思考:

  • 用預訓練的 Word2Vec 向量,把每個詞轉成 300 維向量。
  • 對句子做平均池化(mean pooling),得到每個樣本的語意向量。
  • 再用 XGBoost 來做分類,看能不能學到更複雜的非線性關係。

2.Word2Vec

Word2Vec 是一個 NLP 的經典模型,他可以讓電腦真的開始理解語意!


問題出在哪?

想像一下,One-Hot Encoding 只會告訴電腦:

  • 「蘋果」 = (1, 0, 0, 0, ...)
  • 「香蕉」 = (0, 1, 0, 0, ...)

對電腦來說,蘋果和香蕉一點關係都沒有,它們只是不同的位置亮了一個燈。
電腦完全不知道這兩個字都是水果。


Word2Vec 的想法

Word2Vec 做了什麼呢?
它把每個詞都變成一個向量,這個向量有幾百個維度,並且這些向量會有語意上的關係

舉例來說:

  • vec("蘋果")vec("香蕉") 會很接近,因為它們都出現在「吃水果」、「剝皮」這些語境。
  • 像是 Word2Vec 最經典的示範是:國王(king)減掉男人(man)加上女人(woman)會變皇后(queen)

換句話說,Word2Vec 不只是數字化,而是讓電腦學到「哪個詞跟哪個詞比較像」。


它是怎麼學到的?

Word2Vec 的核心想法叫 「你是誰,取決於你的鄰居」
也就是說:如果兩個詞經常出現在類似的上下文裡,這兩個詞就應該有相似的向量表示。

  • CBOW (Continuous Bag-of-Words):看前後文,猜中間的詞。
  • Skip-Gram:看一個詞,猜它的前後文。

這樣訓練下來,模型就會讓語意相近的詞,向量也靠得更近。


為什麼這對分類有幫助?

當我們把句子裡的每個詞轉成向量,然後取平均或做 pooling(池化),我們就得到一句話的「語意向量」。
這時候,模型就不只看到詞頻,還能理解整句話的語境。

舉例:

  • 「我喜歡吃蘋果」 → 跟「我喜歡吃香蕉」的向量會很接近。
  • 「我要去銀行提款」 → 跟「銀行貸款」會比較接近,而不是跟「河的兩岸」。

3. 程式碼實作

以下用 gensim 載入 Google News 的預訓練 Word2Vec ,然後用 xgboost 訓練分類器。
如果有套件沒有下載,記得要去當初建立的虛擬環境中下載並且所有套件的版本需要相容。

#下載預訓練 Word2Vec (Google News 300d)
import kagglehub

# Download latest version
path = kagglehub.dataset_download("leadbest/googlenewsvectorsnegative300")

print("Path to dataset files:", path)

import numpy as np
import pandas as pd
from gensim.models import KeyedVectors
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import xgboost as xgb

# 1) 載入預訓練 Word2Vec (Google News 300d)
# 因為 Kaggle 執行上傳檔案會沒網路,要先把模型上傳成 Dataset 然後從本地路徑載入
w2v_path = "要改成前面Path to dataset files中有一個.bin檔的路徑"
w2v = KeyedVectors.load_word2vec_format(w2v_path, binary=True)


# 2) 把句子轉成向量(平均池化)
def sentence_to_vec(sentence, model, dim=300):
    words = [w for w in sentence.split() if w in model]
    if len(words) == 0:
        return np.zeros(dim)
    return np.mean(model[words], axis=0)


#使用 body 欄位(主文字內容)作為輸入特徵。
X_text = train["body"].astype(str).tolist()
y = train["rule_violation"].values
X_vec = np.vstack([sentence_to_vec(text, w2v) for text in X_text])

# 切割資料
X_tr, X_val, y_tr, y_val = train_test_split(
    X_vec, y, test_size=0.2, random_state=42, stratify=y
)

# 訓練 XGBoost 分類器
clf = xgb.XGBClassifier(
    n_estimators=500,
    max_depth=6,
    learning_rate=0.05,
    subsample=0.8,
    colsample_bytree=0.8,
    random_state=42,
    n_jobs=-1,
    use_label_encoder=False,
    eval_metric="logloss"
)
clf.fit(X_tr, y_tr)

# 5) 驗證
y_pred = clf.predict(X_val)
print("Word2Vec + XGBoost Accuracy:", accuracy_score(y_val, y_pred))

Word2Vec + XGBoost Accuracy


4.小結

今天的分數是0.736,雖然還沒有上傳到 kaggle ,但確實比之前嘗試的 baseline model 還高分,我們已經從單純的類別編碼,進階到「語意向量 」,算是真正邁入了 NLP 特徵工程世界。
雖然這只是第一步,分數也沒有上升到讓人驚豔的程度,但可以看出向量化的威力。
明天我們會把這次訓練上傳到 kaggle ,確定分數是真的有進步的,再繼續把特徵做得更好,讓模型更接近人類理解語意的方式,也會嘗試更多模型,希望能提高分數。


上一篇
一起來參加Kaggle競賽-提升實戰經驗12(out-of-fold predictions)
下一篇
一起來參加Kaggle競賽-提升實戰經驗14(本地 Validation 有 0.736,上傳 Kaggle ......)
系列文
咖狗報到-30天玩轉Kaggle競賽15
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言