如何处理分类数据以在机器学习中进行预处理
How to handle categorical data for preprocessing in Machine Learning
这可能是一个基本问题,我有一个分类数据,我想将其输入到我的机器学习模型中。我的 ML 模型只接受数字数据。将此分类数据转换为数值数据的正确方法是什么。
我的样本 DF:
T-size Gender Label
0 L M 1
1 L M 1
2 M F 1
3 S F 0
4 M M 1
5 L M 0
6 S F 1
7 S F 0
8 M M 1
我知道以下代码将我的分类数据转换为数值
类型 1:
df['T-size'] = df['T-size'].cat.codes
上一行只是将类别从 0 转换为 N-1。它不遵循它们之间的任何关系。
对于这个例子,我知道S < M < L。当我想像上面那样转换数据时,我应该怎么做。
类型 2:
在这种类型中,M 和 F 之间没有关系。但是我可以看出 M
的概率比 F
大。即,样本为 1 / 样本总数
对于男性,
(4/5)
对于女性,
(2/4)
WKT,
(4/5) > (2/4)
这种柱子应该怎么替换?
我可以将 M 替换为 (4/5),将 F 替换为 (2/4) 来解决这个问题吗?
处理列的正确方法是什么?
帮助我更好地理解这一点。
对于第一个问题,如果您的类别数量较少,您可以map
带有字典的列。这样就可以设置顺序了:
d = {'L':2, 'M':1, 'S':0}
df['T-size'] = df['T-size'].map(d)
输出:
T-size Gender Label
0 2 M 1
1 2 M 1
2 1 F 1
3 0 F 0
4 1 M 1
5 2 M 0
6 0 F 1
7 0 F 0
8 1 M 1
对于第二个问题,您可以使用相同的方法,但我会保留男性和女性的 2 个值 0
和 1
。如果您只需要类别而不必对值进行操作,则一个值等于另一个值。
如果你想在你的大小参数中有一个层次结构,你可以考虑使用线性映射。这将是:
size_mapping = {"S": 1, "M":2 , "L":3}
#mapping to the DataFrame
df['T-size_num'] = df['T-size'].map(size_mapping)
这允许您在保留层次结构的同时将输入视为数值数据
关于性别,你对重新分区和预处理有误解。如果您已经将重新分区作为输入,则会在数据中引入偏差。您必须将男性和女性视为两个不同的类别,而不管它们现有的重新分配。你应该用两个不同的数字来映射它,但不要引入比例。
df['Gender_num'] = df['Gender'].map({'M':0 , 'F':1})
要获得比你的问题更详细的解释和更多的具体内容,我建议阅读 this article regarding categorical data in Machine Learning
有很多方法可以对分类数据进行编码,其中一些方法完全取决于您打算用它做什么。例如,如果您打算使用决策树/随机森林/GBM,那么很容易成为最受欢迎选择的单热编码是extremely poor choice。
关于你上面的T恤,你可以给pandas分类类型下单:
df['T-size'].astype(pd.api.types.CategoricalDtype(['S','M','L'],ordered=True)).
如果你像那样设置你的 T 恤,那么你的 .cat.codes
方法将完美运行。这也意味着您可以轻松使用 scikit-learn 的 LabelEconder
,它非常适合管道。
关于性别编码,在使用目标变量(Label
)时需要非常小心。您不想在训练-测试拆分之前进行此编码,否则您将使用未见数据的知识,使其并非真正未见。如果您使用交叉验证,这会变得更加复杂,因为您需要在每次 CV 迭代中进行编码(即每次折叠新编码)。如果你想这样做,我建议你从 skcontribs Category Encoders 查看 TargetEncoder 但同样,一定要在 sklearn Pipeline
中使用它,否则你会弄乱训练测试拆分和泄漏信息从你的测试集到你的训练集。
对于 M/F 示例来说可能有些矫枉过正,因为它是二进制的 - 但如果您担心将分类映射到数字形式,请考虑 one hot encoding。它基本上将包含 n 类别的单列扩展为 n 二进制列。
所以一个数据集:
Gender
M
F
M
M
F
会变成
Gender_M Gender_F
1 0
0 1
1 0
1 0
0 1
这消除了任何关于一件事比另一件事多 "positive" 的概念 - 对于具有 2 个以上选项的分类数据来说绝对必须,其中没有传递 A > B > C 关系,你也没有想通过强制将一个输入到您的编码方案中来抹黑您的结果。
这可能是一个基本问题,我有一个分类数据,我想将其输入到我的机器学习模型中。我的 ML 模型只接受数字数据。将此分类数据转换为数值数据的正确方法是什么。
我的样本 DF:
T-size Gender Label
0 L M 1
1 L M 1
2 M F 1
3 S F 0
4 M M 1
5 L M 0
6 S F 1
7 S F 0
8 M M 1
我知道以下代码将我的分类数据转换为数值
类型 1:
df['T-size'] = df['T-size'].cat.codes
上一行只是将类别从 0 转换为 N-1。它不遵循它们之间的任何关系。
对于这个例子,我知道S < M < L。当我想像上面那样转换数据时,我应该怎么做。
类型 2:
在这种类型中,M 和 F 之间没有关系。但是我可以看出 M
的概率比 F
大。即,样本为 1 / 样本总数
对于男性,
(4/5)
对于女性,
(2/4)
WKT,
(4/5) > (2/4)
这种柱子应该怎么替换?
我可以将 M 替换为 (4/5),将 F 替换为 (2/4) 来解决这个问题吗?
处理列的正确方法是什么?
帮助我更好地理解这一点。
对于第一个问题,如果您的类别数量较少,您可以map
带有字典的列。这样就可以设置顺序了:
d = {'L':2, 'M':1, 'S':0}
df['T-size'] = df['T-size'].map(d)
输出:
T-size Gender Label
0 2 M 1
1 2 M 1
2 1 F 1
3 0 F 0
4 1 M 1
5 2 M 0
6 0 F 1
7 0 F 0
8 1 M 1
对于第二个问题,您可以使用相同的方法,但我会保留男性和女性的 2 个值 0
和 1
。如果您只需要类别而不必对值进行操作,则一个值等于另一个值。
如果你想在你的大小参数中有一个层次结构,你可以考虑使用线性映射。这将是:
size_mapping = {"S": 1, "M":2 , "L":3}
#mapping to the DataFrame
df['T-size_num'] = df['T-size'].map(size_mapping)
这允许您在保留层次结构的同时将输入视为数值数据
关于性别,你对重新分区和预处理有误解。如果您已经将重新分区作为输入,则会在数据中引入偏差。您必须将男性和女性视为两个不同的类别,而不管它们现有的重新分配。你应该用两个不同的数字来映射它,但不要引入比例。
df['Gender_num'] = df['Gender'].map({'M':0 , 'F':1})
要获得比你的问题更详细的解释和更多的具体内容,我建议阅读 this article regarding categorical data in Machine Learning
有很多方法可以对分类数据进行编码,其中一些方法完全取决于您打算用它做什么。例如,如果您打算使用决策树/随机森林/GBM,那么很容易成为最受欢迎选择的单热编码是extremely poor choice。
关于你上面的T恤,你可以给pandas分类类型下单:
df['T-size'].astype(pd.api.types.CategoricalDtype(['S','M','L'],ordered=True)).
如果你像那样设置你的 T 恤,那么你的 .cat.codes
方法将完美运行。这也意味着您可以轻松使用 scikit-learn 的 LabelEconder
,它非常适合管道。
关于性别编码,在使用目标变量(Label
)时需要非常小心。您不想在训练-测试拆分之前进行此编码,否则您将使用未见数据的知识,使其并非真正未见。如果您使用交叉验证,这会变得更加复杂,因为您需要在每次 CV 迭代中进行编码(即每次折叠新编码)。如果你想这样做,我建议你从 skcontribs Category Encoders 查看 TargetEncoder 但同样,一定要在 sklearn Pipeline
中使用它,否则你会弄乱训练测试拆分和泄漏信息从你的测试集到你的训练集。
对于 M/F 示例来说可能有些矫枉过正,因为它是二进制的 - 但如果您担心将分类映射到数字形式,请考虑 one hot encoding。它基本上将包含 n 类别的单列扩展为 n 二进制列。
所以一个数据集:
Gender
M
F
M
M
F
会变成
Gender_M Gender_F
1 0
0 1
1 0
1 0
0 1
这消除了任何关于一件事比另一件事多 "positive" 的概念 - 对于具有 2 个以上选项的分类数据来说绝对必须,其中没有传递 A > B > C 关系,你也没有想通过强制将一个输入到您的编码方案中来抹黑您的结果。