Pseudo Labeling(擬似ラベリング)を使ってみる
Kaggle Instant Gratificationで使われていた Pseudo Labeling(擬似ラベリング)について紹介します。参考: Pseudo Labeling - QDA - [0.969]
Pseudo Labeling(擬似ラベリング)とは?
Pseudo Labelingとは、ラベルのついたデータ(trainデータ)で学習したモデルを利用して、未ラベルのデータ(testデータ)を推論した結果のうち、確度の高いものをラベル付きのデータとして追加して再度モデルを学習させるプロセスを指します。
今回のコンペでは40の特徴量に対して、512行のデータセットを使ってモデルを学習させる必要があり明らかにデータ数が足りないため、擬似ラベリングを行い学習データを増やすことでスコアを伸ばすことができました。
実際のコード
データは こちら から。
ラベルのついたデータ(trainデータ)でモデルを学習
import numpy as np import pandas as pd import os from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis from sklearn.model_selection import StratifiedKFold from sklearn.feature_selection import VarianceThreshold from sklearn.metrics import roc_auc_score train = pd.read_csv('../input/train.csv') test = pd.read_csv('../input/test.csv') cols = [c for c in train.columns if c not in ['id', 'target', 'wheezy-copper-turtle-magic']] oof = np.zeros(len(train)) preds = np.zeros(len(test)) for i in range(512): train2 = train[train['wheezy-copper-turtle-magic']==i] test2 = test[test['wheezy-copper-turtle-magic']==i] idx1 = train2.index idx2 = test2.index train2.reset_index(drop=True, inplace=True) sel = VarianceThreshold(threshold=1.5).fit(train2[cols]) train3 = sel.transform(train2[cols]) test3 = sel.transform(test2[cols]) skf = StratifiedKFold(n_splits=11, random_state=42, shuffle=True) for train_index, test_index in skf.split(train3, train2['target']): clf = QuadraticDiscriminantAnalysis(reg_param=0.5) clf.fit(train3[train_index,:],train2.loc[train_index]['target']) oof[idx1[test_index]] = clf.predict_proba(train3[test_index,:])[:,1] preds[idx2] += clf.predict_proba(test3)[:,1] / skf.n_splits print('QDA scores CV =',round(roc_auc_score(train['target'], oof) ,5))
QDA scores CV = 0.96532
未ラベルのデータ(testデータ)を推論した結果を擬似ラベルとして追加
test['target'] = preds
擬似ラベルのうち、予測確度の高いものを学習データに追加してモデルを学習
oof = np.zeros(len(train)) preds = np.zeros(len(test)) for k in range(512): train2 = train[train['wheezy-copper-turtle-magic']==k] train2p = train2.copy() idx1 = train2.index test2 = test[test['wheezy-copper-turtle-magic']==k] # 擬似ラベルのうち、予測確度の高いものを学習データに追加する test2p = test2[ (test2['target']<=0.01) | (test2['target']>=0.99) ].copy() test2p.loc[ test2p['target']>=0.5, 'target' ] = 1 test2p.loc[ test2p['target']<0.5, 'target' ] = 0 train2p = pd.concat([train2p,test2p],axis=0) train2p.reset_index(drop=True,inplace=True) sel = VarianceThreshold(threshold=1.5).fit(train2p[cols]) train3p = sel.transform(train2p[cols]) train3 = sel.transform(train2[cols]) test3 = sel.transform(test2[cols]) skf = StratifiedKFold(n_splits=11, random_state=42, shuffle=True) for train_index, test_index in skf.split(train3p, train2p['target']): test_index3 = test_index[ test_index<len(train3) ] clf = QuadraticDiscriminantAnalysis(reg_param=0.5) clf.fit(train3p[train_index,:],train2p.loc[train_index]['target']) oof[idx1[test_index3]] = clf.predict_proba(train3[test_index3,:])[:,1] preds[test2.index] += clf.predict_proba(test3)[:,1] / skf.n_splits print('Pseudo Labeled QDA scores CV =',round(roc_auc_score(train['target'], oof) ,5))
Pseudo Labeled QDA scores CV = 0.96769
CVスコアがわずかながら上がっていることが確認できました。