2016-08-03 65 views
3

只是想知道是如何可能的未來情況後,差異訓練和測試功能:XGBoost轉換爲DMatrix

def fit(self, train, target): 
    xgtrain = xgb.DMatrix(train, label=target, missing=np.nan) 
    self.model = xgb.train(self.params, xgtrain, self.num_rounds) 

enter image description here 我通過訓練集爲csr_matrix有5233列,並且轉換成DMatrix我後獲得了5322個功能。

後來預測一步,我得到了一個錯誤如上錯誤:(

def predict(self, test): 
    if not self.model: 
     return -1 
    xgtest = xgb.DMatrix(test) 
    return self.model.predict(xgtest) 

enter image description here

Error: ... training data did not have the following fields: f5232

我怎樣才能保證正確的轉換我火車/測試的原因數據集DMatrix ?

有沒有機會在Python中使用類似於R的東西?

# get same columns for test/train sparse matrixes 
col_order <- intersect(colnames(X_train_sparse), colnames(X_test_sparse)) 
X_train_sparse <- X_train_sparse[,col_order] 
X_test_sparse <- X_test_sparse[,col_order] 

我的方法是行不通的,不幸的是:

def _normalize_columns(self): 
    columns = (set(self.xgtest.feature_names) - set(self.xgtrain.feature_names)) | \ 
      (set(self.xgtrain.feature_names) - set(self.xgtest.feature_names)) 
    for item in columns: 
     if item in self.xgtest.feature_names: 
      self.xgtest.feature_names.remove(item) 
     else: 
      # seems, it's immutable structure and can not add any new item!!! 
      self.xgtest.feature_names.append(item) 

回答

3

另一種可能性是隻有一個特徵級別用於訓練不在測試數據中的數據。這種情況大多發生在發佈一個熱門編碼,其結果是大矩陣對於每個分類特徵級別具有級別。在你的情況下,它看起來像「f5232」是在培訓或測試數據獨佔。如果任一案例模型得分可能會導致錯誤(在ML包的大多數實現中),因爲:

  1. 如果排除訓練:模型對象將在模型方程中引用此特徵。雖然得分它會拋出錯誤,說我無法找到這一列。
  2. 如果是排他性測試(通常測試數據通常小於訓練數據):模型對象在模型方程中將不具有此特徵的參考。雖然得分它會拋出錯誤說我得到了這一列,但模型方程沒有這一欄。這也不太可能,因爲大多數實現都認識到這種情況。

解決方案:

  1. 最好的「自動化」解決方案是隻保留那些列,這是共同的訓練和測試後一個熱編碼。
  2. 對於即席分析,如果您因爲其重要性而無法降低功能級別,請執行分層抽樣以確保將所有級別的功能分配到培訓和測試數據。
2

可能發生這種情況後,一個熱編碼。例如,

ar = np.array([ 
     [1, 2], 
     [1, 0] 
]) 

enc = OneHotEncoder().fit(ar) 
ar2 = enc.transform(ar) 
b = np.array([[1, 0]]) 
b2 = enc.transform(b) 
xgb_ar = xgb.DMatrix(ar2) 
xgb_b = xgb.DMatrix(b2) 

print(b2.shape) # (1, 3) 
print(xgb_b.num_col()) # 2 

所以,當你在稀疏矩陣中的所有零列,DMatrix刪除此列(我想,因爲此列是無用的XGBoost)

通常情況下,我添加了一個假的行在所有列中都包含1的矩陣。