转换为DMatrix后,XGBoost在训练和测试功能方面存在差异

时间:2016-08-03 10:23:37

标签: python python-2.7 numpy machine-learning xgboost

只是想知道下一个案例的可能性如何:

 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

  

错误:...训练数据没有以下字段: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 个答案:

答案 0 :(得分:4)

另一种可能性是仅在训练数据中具有一个特征级别而不在测试数据中。这种情况主要发生在发布一个热编码时,其结果是大矩阵具有针对每个级别的分类特征的级别。在你的情况下它看起来像&#34; f5232&#34;在培训或测试数据中是独占的。如果任何一个案例模型评分都可能抛出错误(在大多数ML包的实现中),因为:

  1. 如果专用于训练:模型对象将在模型方程中引用此特征。虽然得分会引发错误,说我无法找到这个专栏。
  2. 如果排他性测试(测试数据通常小于训练数据的可能性较小):模型对象将不会在模型方程中引用此特征。虽然得分会引起错误,说我得到了这个专栏,但是模型方程没有这个专栏。这也不太可能,因为大多数实现都认识到这种情况。
  3. 解决方案:

    1. 最好的&#34;自动化&#34;解决方案是仅保留那些训练和测试一个热编码共同的列。
    2. 对于特殊分析,如果由于其重要性而无法降低功能级别,则应进行分层抽样,以确保将所有级别的功能分配给培训和测试数据。

答案 1 :(得分:3)

这种情况可能发生在一次热编码之后。例如,

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。

答案 2 :(得分:0)

RandomUnderSampler(RUS)方法返回一个np.array而不是带有列名称的Pandas DataFrame时,发生了我这样的问题。

from imblearn.under_sampling import RandomUnderSampler
rus = RandomUnderSampler(return_indices=True)
X_rus, y_rus, id_rus = rus.fit_sample(X_train, y_train)

我通过以下方法解决了这个问题:

X_rus = pd.DataFrame(X_rus, columns = X_train.columns)

基本上从RUS方法的输出中提取一个原始的X_train数据中的列名作为Pandas DataFrame,这是RUS方法的输入。

这可以推广到XGBoost希望读取列名但不能读取列名的任何类似问题。只需创建一个Pandas DataFrame并相应地分配列名即可。