Scikit-learn 标签编码后跟一种热编码,导致训练和测试数据集的不同特征集。如何解决这个问题?
Scikit-learn Label Encoding followed by one hot encoding resulting in different feature set for train and test data sets. How to fix this?
我正在尝试为我的一个机器学习项目使用一个数据集 (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、服务和标志。
我将这三个特征数组从训练样本和测试样本中分离出来,分别对训练样本和测试样本进行标签编码和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 个 features/columns,而 test_obj2 数组有 64 个 features/columns。这会导致应用标准算法(如 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))
我用 print 语句进行了一些调试,实际上训练集正在获取包含所有 65 种不同服务类型的样本,而测试集仅获取包含 64 种不同类型服务的样本。
你能帮我理解和解决这个问题吗?
1) 当我们使用 scikit-learn APIs 进行标签编码和 1_hot_encoding 时,是否会出现这种行为?
2) 在这种情况下,如何修复并确保训练和测试数据集都具有所有服务类型或字符串类型?
如果需要,我可以将完整代码添加到问题中。
1) 当我们使用 scikit-learn API 进行标签编码和 1_hot_encoding 时,是否会出现这种行为?
是的,但这是因为你fit_transform的使用方式不对
2) 在这种情况下,如何修复并确保训练和测试数据集都具有所有服务类型或字符串类型?
如果不是所有列车上的 caregories 都在测试中,反之亦然,您必须在列车和测试数据上都安装编码器。
以便编码器考虑所有类别。
一旦编码器适合,您就可以在训练和测试中分别调用变换。您将获得相同数量的功能。
还有最后一个细节。如果您有仅用于测试的类别,使用这些类别训练模型可能会导致一些意外行为。
我正在尝试为我的一个机器学习项目使用一个数据集 (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、服务和标志。
我将这三个特征数组从训练样本和测试样本中分离出来,分别对训练样本和测试样本进行标签编码和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 个 features/columns,而 test_obj2 数组有 64 个 features/columns。这会导致应用标准算法(如 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))
我用 print 语句进行了一些调试,实际上训练集正在获取包含所有 65 种不同服务类型的样本,而测试集仅获取包含 64 种不同类型服务的样本。
你能帮我理解和解决这个问题吗?
1) 当我们使用 scikit-learn APIs 进行标签编码和 1_hot_encoding 时,是否会出现这种行为?
2) 在这种情况下,如何修复并确保训练和测试数据集都具有所有服务类型或字符串类型?
如果需要,我可以将完整代码添加到问题中。
1) 当我们使用 scikit-learn API 进行标签编码和 1_hot_encoding 时,是否会出现这种行为?
是的,但这是因为你fit_transform的使用方式不对
2) 在这种情况下,如何修复并确保训练和测试数据集都具有所有服务类型或字符串类型?
如果不是所有列车上的 caregories 都在测试中,反之亦然,您必须在列车和测试数据上都安装编码器。 以便编码器考虑所有类别。
一旦编码器适合,您就可以在训练和测试中分别调用变换。您将获得相同数量的功能。
还有最后一个细节。如果您有仅用于测试的类别,使用这些类别训练模型可能会导致一些意外行为。