【问题标题】:XGBoost difference in train and test features after converting to DMatrix转换为 DMatrix 后训练和测试特征的 XGBoost 差异
【发布时间】:2016-12-09 00:22:01
【问题描述】:

只是想知道下一个案例怎么可能:

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

我将训练数据集作为具有 5233 列的 csr_matrix 传递,转换为 DMatrix 后,我得到了 5322 个特征。

后来在预测步骤中,我收到了一个错误,原因是上述错误:(

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

错误:...训练数据没有以下字段:f5232

如何保证正确地将我的 train/test 数据集转换为 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) 

【问题讨论】:

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


    【解决方案1】:

    这种情况可能发生在 one-hot 编码之后。例如,

    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】:

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

      1. 如果专用于训练:模型对象将在模型方程中引用此特征。评分时会抛出错误,提示我无法找到此列。
      2. 如果专用于测试(不太可能,因为测试数据通常小于训练数据):模型对象将不会在模型方程中引用此特征。在评分时会抛出错误,说我得到了这个列,但模型方程没有这个列。这也不太可能,因为大多数实现都知道这种情况。

      解决方案:

      1. 最好的“自动化”解决方案是只保留那些在一次热编码后训练和测试都通用的列。
      2. 对于临时分析,如果您不能因为其重要性而降低特征级别,请进行分层抽样,以确保将所有级别的特征分布到训练和测试数据中。

      【讨论】:

        【解决方案3】:

        当 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 方法的输出并从中创建一个 Pandas DataFrame,其中列名来自作为 RUS 方法输入的原始 X_train 数据。

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

        【讨论】:

          猜你喜欢
          • 2022-08-11
          • 1970-01-01
          • 1970-01-01
          • 2018-03-25
          • 1970-01-01
          • 2016-11-01
          • 1970-01-01
          • 1970-01-01
          • 2021-03-30
          相关资源
          最近更新 更多