特征提取与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
相关产品推荐
相关产品推荐

