【发布时间】:2019-01-07 10:14:34
【问题描述】:
我正在尝试将包含数千个样本和大约 41 个特征的数据集 (KDD-cup-99) 用于我的一个机器学习项目。这实质上是使用 TCP DUMP 收集的特定网络的数据包捕获。
我使用 scikit-learn train_test_split 函数如下
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3,
random_state=42)
拆分后,上面的每一个都有下面的形状。
X_train : (444618, 41)
y_train : (444618,)
X_test : (49403, 41)
y_test : (49403,)
在 41 个特征中,3 个特征是字符串类型的。使用这些数据的人可以理解这些。这三个是:protocol_type、service和flag。
我将这三个特征数组从训练样本和测试样本中分离出来,分别对训练样本和测试样本进行标签编码和 1hot 编码。现在这三个特征的数组大小如下:
X_train_obj1: (444618, 3)
X_train_obj2: (444618, 65)
X_train_obj3: (444618, 11)
X_test_obj1: (49403, 3)
X_test_obj2: (49403, 64)
X_test_obj3: (49403, 11)
这就是我的问题所在。出于某种原因,train_obj2 有 65 个特征/列,而 test_obj2 数组有 64 个特征/列。这会导致应用任何标准算法(如 KNeighborClassifier、SVM 等)的拟合/预测方法时出现问题,然后将它们与各自的训练集和测试集合并并开始使用它们。 API 失败,错误指示大小不一致..
对应代码:
label_encoder = LabelEncoder()
train_proto_label_encoded =
label_encoder.fit_transform(X_train_obj['protocol_type'])
train_srv_label_encoded =
label_encoder.fit_transform(X_train_obj['service'])
train_flag_label_encoded =
label_encoder.fit_transform(X_train_obj['flag'])
test_proto_label_encoded =
label_encoder.fit_transform(X_test_obj['protocol_type'])
test_srv_label_encoded =
label_encoder.fit_transform(X_test_obj['service'])
test_flag_label_encoded =
label_encoder.fit_transform(X_test_obj['flag'])
hot_encoder = OneHotEncoder()
train_proto_1hot_encoded =
hot_encoder.fit_transform(train_proto_label_encoded.reshape(-1, 1))
train_srv_1hot_encoded =
hot_encoder.fit_transform(train_srv_label_encoded.reshape(-1, 1))
train_flag_1hot_encoded =
hot_encoder.fit_transform(train_flag_label_encoded.reshape(-1, 1))
test_proto_1hot_encoded =
hot_encoder.fit_transform(test_proto_label_encoded.reshape(-1, 1))
test_srv_1hot_encoded =
hot_encoder.fit_transform(test_srv_label_encoded.reshape(-1, 1))
test_flag_1hot_encoded =
hot_encoder.fit_transform(test_flag_label_encoded.reshape(-1, 1))
我对打印语句进行了一些调试,基本上训练集获取所有 65 种不同类型服务的样本,而测试集仅获取 64 种不同类型服务的样本。
你能帮我理解和解决这个问题吗?
1) 当我们使用 scikit-learn API 进行标签编码和 1_hot_encoding 时,这种行为是预期的吗?
2) 在这种情况下,如何修复并确保训练和测试数据集都具有所有服务类型或字符串类型?
如果需要,我可以将完整代码添加到问题中。
【问题讨论】:
-
你永远不会在测试数据上调用
fit(或fit_transform)。仅致电transform()。在测试中进行拟合只会记住测试中存在的那些值,因此也会记住列数的变化。 -
我并不是说适合测试数据。当我对测试数据调用预测时,问题就出现了
-
您在测试数据上从 LabelEncoder 和 OnehotEncoder 调用 fit_transform。您需要为每个列维护单独的
LabelEncoders,然后从相同的 labelencoder 对象调用 transform() 测试数据。 -
查看我的其他答案中的代码,了解需要做什么:stackoverflow.com/a/48079345/3374996
-
Vivek,感谢您的意见。它们很有用。上面的链接帮助我了解出了什么问题,但是,我仍然面临一个问题,即训练数据中不存在一些标签,而只存在于测试数据中。 Gabriel 的回答帮助我解决了这个问题。
标签: machine-learning scikit-learn svm knn