2016-11-16 35 views
1

我在這裏問這個問題,儘管我猶豫是否將它發佈在CrossValidated(或DataScience)StackExchange上。我有一個包含60個標記對象(用於訓練)和150個未標記對象(用於測試)的數據集。問題的目的是預測150個對象的標籤(這是作爲一個家庭作業問題給出的)。對於每個對象,我計算了258個特徵。考慮到每個對象作爲示例,我有X_train : (60,258)y_train : (60,)(用於訓練的對象的標籤)和X_test : (150,258)。由於給出了作業問題的解決方案,因此我也有y_test : (150,)中的150個對象的標籤。如何解釋測試數據的性能下降?

爲了預測150個對象的標籤,我選擇使用LogisticRegression(Scikit-learn實現)。分類器在(X_train, y_train)上進行了訓練,數據經過歸一化後,用於對150個對象進行預測。這些預測與y_test進行比較以評估模型的性能。爲了再現性,我複製了我用過的代碼。

from sklearn import metrics 
from sklearn.preprocessing import StandardScaler 
from sklearn.linear_model import LogisticRegression 
from sklearn.pipeline import make_pipeline 
from sklearn.model_selection import cross_val_score, crosss_val_predict 

# Fit classifier 
LogReg = LogisticRegression(C=1, class_weight='balanced') 
scaler = StandardScaler() 
clf = make_pipeline(StandardScaler(), LogReg) 
LogReg.fit(X_train, y_train) 

# Performance on training data 
CV_score = cross_val_score(clf, X_train, y_train, cv=10, scoring='roc_auc') 
print(CV_score) 

# Performance on test data 
probas = LogReg.predict_proba(X_test)[:, 1] 
AUC = metrics.roc_auc_score(y_test, probas) 
print(AUC) 

矩陣X_trainy_trainX_testy_test保存在可用this link一個.MAT文件。我的問題如下:

使用這種方法,我在訓練數據(CV_score = 0.8)上獲得了很好的性能,但測試數據的性能更差:對於LogReg中的C = 1,AUC = 0.54 =對於C = 0.01,爲0.40。如果一個天真的分類器應該得到AUC = 0.5,我怎樣才能得到0.5的AUC?這是因爲我有少量訓練樣本? 我注意到,如果我改變的代碼上的測試數據的性能提高:

y_pred = cross_val_predict(clf, X_test, y_test, cv=5) 
AUC = metrics.roc_auc_score(y_test, y_pred) 
print(AUC) 

事實上,AUC = 0.87 C = 1和0.9 C = 0.01。爲什麼使用交叉驗證預測的AUC得分更好?是否因爲交叉驗證允許對不包含降低AUC的對象/樣本的測試數據的子集進行預測?

回答

0

首先,爲60個訓練項目提供258個特徵是沒有意義的。其次,對於60個項目,CV = 10表示將數據分成10個列車/測試集。其中每個只有6個項目在測試集中。所以你獲得的任何結果都是無用的。您需要更多的培訓數據和更少的功能。

1

看起來您正遇到過度擬合問題,即使用訓練數據訓練的分類器過度訓練數據。泛化能力差。這就是測試數據集的性能不佳的原因。

cross_val_predict實際上是使用部分測試數據對分類器進行訓練,然後對其餘部分進行預測。所以表現要好得多。

總的來說,你的訓練和測試數據集似乎有一些差異。所以具有最高訓練精度的分類器在您的測試集上運行得並不好。

另一點與您的問題沒有直接關係:由於訓練樣本的數量遠小於特徵尺寸,因此在輸入分類器之前執行降維可能會有幫助。

1

它看起來像你的訓練和測試過程不一致。儘管從您的代碼中您打算將您的數據標準化,但是在測試過程中您沒有這樣做。我的意思是:

clf = make_pipeline(StandardScaler(), LogReg) LogReg.fit(X_train, y_train) 雖然您定義了一個管道,但您不適合管道(clf.fit),但只適用Logistic迴歸。這很重要,因爲您的交叉驗證分數是使用管道(CV_score = cross_val_score(clf, X_train, y_train, cv=10, scoring='roc_auc'))計算得出的,但是在測試期間(而不是預期使用的管線)可以預測,因此僅使用LogReg,因此測試數據不是標準化的。

你提出的第二點是不同的。在y_pred = cross_val_predict(clf, X_test, y_test, cv=5) 中,您可以通過對測試數據進行交叉驗證來預測,而忽略列車數據。在這裏,你使用clf進行數據標準化,因此你的分數很高;這是標準化步驟很重要的證據。

總之,標準化測試數據,我相信會提高你的測試分數。