You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

特征提取与ML模型组合代码报错:特征数量不匹配问题求助

特征数量不匹配错误排查:多特征提取+多模型组合实现问题

我有4种特征提取方法和3种机器学习模型,需要实现所有12种组合(如M1+Feat1)。编写了Ensemble类后运行出现特征数量不匹配错误:

ValueError: X has 3077 features, but LogisticRegression is expecting 423 features as input.

代码实现

class Ensemble:
    def __init__(self):
        pass

    def fit_transform(self,X, index):
        if index == 0:
            vec = DictVectorizer()
            return vec.fit_transform(X), vec
        elif index == 1:
            hashed_data = []
            for instance in X:
                hashed_instance = {}
                for key, value in instance.items():
                    hashed_key = "_".join(key)
                    hashed_instance[hashed_key] = value
                hashed_data.append(hashed_instance)

            hasher = FeatureHasher(n_features=10, input_type="dict")
            return hasher.fit_transform(hashed_data), hasher
        elif index == 2:
            flattened_data = [list(d.keys()) for d in X]
            encoder = MultiLabelBinarizer()
            return encoder.fit_transform(flattened_data), encoder
        elif index == 3:
            flattened_data = [" ".join(["_".join(key) for key in d.keys()]) for d in X]
            vectorizer = CountVectorizer()
            return vectorizer.fit_transform(flattened_data), vectorizer
    
    def transform(self,X, index,feat):
        if index == 0:
            return feat.transform(X)
        elif index == 1:
            hashed_data = []
            for instance in X:
                hashed_instance = {}
                for key, value in instance.items():
                    hashed_key = "_".join(key)
                    hashed_instance[hashed_key] = value
                hashed_data.append(hashed_instance)

            return feat.transform(hashed_data)
        elif index == 2:
            flattened_data = [list(d.keys()) for d in X]
            return feat.transform(flattened_data)
        elif index == 3:
            flattened_data = [" ".join(["_".join(key) for key in d.keys()]) for d in X]
            return feat.transform(flattened_data)

    def fit(self,X, y_train):
        models = [LogisticRegression(),KNeighborsClassifier(),RandomForestClassifier()]
        feats = list(range(4))
        fmodels = list(itertools.product(models, feats))
        self.fitted_models = []
        for model, feat_ex in fmodels:
            X_train, feat = self.fit_transform(X, feat_ex)
            self.fitted_models.append((model.fit(X_train, y_train),feat_ex ,feat))
    
    def predict(self,X):
        self.predictions = []
        for model, feat_ex ,feat in self.fitted_models:
            X_test = self.transform(X, feat_ex,feat)
            self.predictions.append(model.predict(X_test))

        print(self.predictions)


model = Ensemble()
model.fit(X,y_train)
model.predict(X_val)

完整错误栈

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[174], line 74
     72 model = Ensemble()
     73 model.fit(X,y_train)
---> 74 model.predict(X_val)

Cell In[174], line 67, in Ensemble.predict(self, X)
     65     X_test = self.transform(X, feat_ex,feat)
     66     # print("---test--",X_test.shape)
---> 67     self.predictions.append(model.predict(X_test))
     69 print(self.predictions)

File c:\Users\Admin'\Desktop\Course exercises\fokg_miniproject_final\.env\lib\site-packages\sklearn\linear_model\_base.py:451, in LinearClassifierMixin.predict(self, X)
    437 """
    438 Predict class labels for samples in X.
    439 
   (...)
    448     Vector containing the class labels for each sample.
    449 """
    450 xp, _ = get_namespace(X)
--> 451 scores = self.decision_function(X)
    452 if len(scores.shape) == 1:
    453     indices = xp.astype(scores > 0, int)
...
    415         f"X has {n_features} features, but {self.__class__.__name__} "
    416         f"is expecting {self.n_features_in_} features as input."
    417     )

ValueError: X has 3077 features, but LogisticRegression is expecting 423 features as input.

问题根源

核心错误是同一个模型实例被重复用于不同特征提取器的拟合,导致模型的特征数记录被覆盖:

  • 在fit方法中,提前创建的3个模型实例会被itertools.product重复配对4种特征提取器,比如LogisticRegression()实例会被连续拟合4次,每次拟合都会覆盖模型内部的n_features_in_(训练时的特征数)
  • 最终fitted_models里的多个条目指向同一个模型实例,其n_features_in_是最后一次拟合的特征数;但预测时用的是对应特征提取器转换后的特征(特征数为训练该组合时的数量),两者不匹配就会报错

解决方法

修改fit方法,每次循环创建新的模型实例,避免重复使用同一个实例:

def fit(self,X, y_train):
    # 存储模型类,而非提前创建实例
    model_classes = [LogisticRegression, KNeighborsClassifier, RandomForestClassifier]
    feats = list(range(4))
    fmodels = list(itertools.product(model_classes, feats))
    self.fitted_models = []
    for model_cls, feat_ex in fmodels:
        # 每次循环生成新的模型实例
        model = model_cls()
        X_train, feat = self.fit_transform(X, feat_ex)
        self.fitted_models.append((model.fit(X_train, y_train), feat_ex, feat))

调试建议

可以在predict方法中添加特征数验证,方便排查:

def predict(self,X):
    self.predictions = []
    for model, feat_ex ,feat in self.fitted_models:
        X_test = self.transform(X, feat_ex,feat)
        # 打印特征数信息,验证是否匹配
        print(f"模型类型: {type(model).__name__}, 特征索引: {feat_ex}, 测试特征数: {X_test.shape[1]}, 期望特征数: {model.n_features_in_}")
        self.predictions.append(model.predict(X_test))

额外检查项

  • 确保训练集X和验证集X_val的原始数据结构完全一致(比如都是字典列表,键的类型统一)
  • 确认FeatureHasher的n_features参数在训练和预测时保持一致(当前代码已固定为10,无需修改)
  • 对于MultiLabelBinarizer和CountVectorizer,训练时的特征集合需覆盖测试集的所有可能特征,避免转换时出现异常

内容的提问来源于stack exchange,提问作者Aryman Deshwal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 05:44:53