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

文本分类中训练测试数据集分离时如何避免特征数量不匹配?

问题描述

我正在开展文本分类任务,计划使用两个独立数据集分别训练与测试,不希望合并数据集以防数据泄漏(data leakage)。训练数据集约16000行,测试数据集仅约1000行。

使用CountVectorizer进行文本向量化时,因两个数据集词汇表不同,生成的特征列数量不一致,预测阶段出现以下错误:

ValueError: X has 55229 features, but DecisionTreeClassifier is expecting 387964 features as input.

现有两种解决思路:1. 为较小的x_test添加零填充列;2. 使用scikit-learn pipeline。我的代码片段如下:

# read dfs
df_1 = pd.read_csv("data1.csv",header=0) # for training, has text, and class columns
df_2 = pd.read_csv("data2.csv",header=0) # for testing,  has text, and class columns

# vectorise
CV1 = CountVectorizer(ngram_range=(1,3), stop_words="english").fit(df_1['text']) 
x_train = CV1.transform(df_1['text'])
y_train = df_1['class']

CV2 = CountVectorizer(ngram_range=(1,3), stop_words="english").fit(df_2['text']) 
x_test = CV2.transform(df_2['text'])
y_test = df_test['class']

## shapes of objects
## x_test (1589, 55229), y_test(1589,)
## x_train (16716, 387964), y_train(16716,)

# build classifier and predict
classifier = DecisionTreeClassifier(random_state=1234)
model = classifier.fit(x_train,y_train)
y_pred = model.predict(x_test)

# error ValueError: X has 55229 features, but DecisionTreeClassifier is expecting 387964 features as input.

解决方案

方法1:基于训练集词汇表对齐测试集特征

核心逻辑是仅用训练集拟合CountVectorizer,测试集直接使用这个已拟合的转换器做转换——这样测试集会自动对齐训练集的特征维度,训练集中未出现的词汇会被忽略,对应特征列自动填充0,无需手动处理。

修改后的代码:

# 读取数据
df_1 = pd.read_csv("data1.csv", header=0)
df_2 = pd.read_csv("data2.csv", header=0)

# 仅用训练集拟合CountVectorizer
cv = CountVectorizer(ngram_range=(1,3), stop_words="english").fit(df_1['text'])

# 转换训练集和测试集
x_train = cv.transform(df_1['text'])
y_train = df_1['class']
x_test = cv.transform(df_2['text'])  # 复用训练集的词汇表转换测试集
y_test = df_2['class']  # 修正原代码中df_test的拼写错误

# 训练模型并预测
classifier = DecisionTreeClassifier(random_state=1234)
model = classifier.fit(x_train, y_train)
y_pred = model.predict(x_test)

方法2:使用scikit-learn Pipeline(推荐)

Pipeline可以将特征工程和模型训练打包成一个整体,确保整个流程中只有训练集数据用于拟合转换器,从根源避免数据泄漏,同时代码更简洁、可复用性更强。

代码示例:

from sklearn.pipeline import Pipeline

# 读取数据
df_1 = pd.read_csv("data1.csv", header=0)
df_2 = pd.read_csv("data2.csv", header=0)

x_train = df_1['text']
y_train = df_1['class']
x_test = df_2['text']
y_test = df_2['class']

# 构建Pipeline,串联特征工程和模型
pipeline = Pipeline([
    ('vectorizer', CountVectorizer(ngram_range=(1,3), stop_words="english")),
    ('classifier', DecisionTreeClassifier(random_state=1234))
])

# 训练Pipeline(仅用训练集拟合所有组件)
pipeline.fit(x_train, y_train)

# 直接用Pipeline完成测试集的特征转换与预测
y_pred = pipeline.predict(x_test)

关键注意事项

  • 绝对不能用测试集拟合任何特征工程组件(比如CountVectorizer),这是数据泄漏的典型场景,会导致模型泛化能力严重下降。
  • 两种方法中,Pipeline是更推荐的工业级方案,它能避免手动操作中可能出现的疏漏,同时便于后续扩展(比如添加TF-IDF、模型调参等步骤)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 06:55:24