我正在尝试使用一个数据集(KDD-cup-99),该数据集有数千个样本和大约41个特征,用于我的一个机器学习项目。这本质上是使用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。
我从训练和测试样本中分别分离出这三个特征数组,对训练和测试样本分别进行了标签编码和独热编码。现在,这三个特征的数组大小如下:
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等的fit/predict方法时出现问题。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进行标签编码和独热编码时,这种行为是预期的吗?
2) 如何修复并确保训练和测试数据集都包含所有服务类型或在这种情况下所有字符串类型?
如果需要,我可以添加完整的代码到问题中。
回答:
1) 使用scikit-learn API进行标签编码和独热编码时,这种行为是预期的吗?
是的,但这是因为您错误地使用了fit_transform函数。
2) 如何修复并确保训练和测试数据集都包含所有服务类型或在这种情况下所有字符串类型?
如果训练集中不包含测试集中的所有类别,反之亦然,您必须对训练和测试数据都进行编码器的拟合。这样编码器就能考虑到所有类别。
一旦编码器拟合完毕,您可以分别对训练和测试集调用transform函数。这样您将得到相同数量的特征。
最后一个细节。如果测试集中有仅有的类别,使用这些类别训练模型可能会导致一些意外的行为。