MultiLabelBinarizer 在逆变换时混淆了数据
MultiLabelBinarizer mixes up data when inverse transforming
我正在使用 sklearn
的 multilabelbinarizer()
来训练我用来训练模型的机器学习中的多个列。
使用它后,我注意到它在反转 t运行s 时混淆了我的数据。我创建了一个 运行dom 值的测试集,其中我适合数据,t运行sform 它,inverse_transform
数据以返回原始数据。
我 运行 在 jupyter
笔记本中进行了简单测试以显示错误:
在 inverse_transformed
值中,第 1 行混淆了州和月份。
jupyter notebook code
首先,我使用multilabelbinarizer
的方式有没有错误?是否有不同的方法来实现相同的输出?
编辑:
感谢@Nicolas M. 帮助我解决了我的问题。我最终像这样解决了这个问题。
原谅粗略的解释,但结果比我原先想象的要复杂。我改用 label_binarizer
而不是 multi_label_binarizer
因为它
我最终对 label_binarizer
defaultdict
进行了 pickle,这样我就可以加载它并在我的机器学习项目的不同模块中使用它。
有一件事可能不是微不足道的,那就是我将新的 header 添加到我为每一列制作的数据框中。它采用 column_name + 列号的形式。我这样做是因为我需要反转 t运行sform 数据。为此,我搜索了包含原始列名的列,这些列将较大的数据框分隔成单独的列块。
这里是我使用的一些变量及其含义供参考:
lb_dict
- 存储不同标签二值化器的默认字典。
binarize_df
- 存储二值化数据的数据框。
binarized_label
- 标签将列中的一个标签二值化。
header
- 创建一个新的 header 表单:列名 + 数字列。
inverse_df
- 存储 inverse_transformed 数据的数据框。
one_label_list
- 查找具有原始列标记的列名列表。
one_label_df
- 创建一个只存储一列二值化数据的新数据框。
single_label
- 将 inverse_transformed 放入一列的二值化数据。
在此代码中数据是我传递给函数的数据帧。
lb_dict = defaultdict(LabelBinarizer)
# create a place holder dataframe to join new binarized data to
binarize_df = pd.DataFrame(['x'] * len(data.index), columns=['place_holder'])
# loop through each column and create a binarizer and fit/transform the data
# add new data to the binarize_df dataframe
for column in data.columns.values.tolist():
lb_dict[column].fit(data[column])
binarized_label = lb_dict[column].transform(data[column])
header = [column + str(i) for i in range(0, len(binarized_label[0]))]
binarize_df = binarize_df.join(pd.DataFrame(binarized_label, columns=header))
# drop the place holder value
binarize_df.drop(labels=['place_holder'], axis=1, inplace=True)
这是我写的 inverse_transform 函数:
inverse_df = pd.DataFrame(['x'] * len(output.index), columns=['place_holder'])
# use a for loop to run through the different output columns that need to be inverse_transformed
for column in output_cols:
# create a list of the different headers based on if the name contains the original output column name
one_label_list = [x for x in output.columns.values.tolist() if column in x]
one_label_df = output[one_label_list]
# inverse transform the data frame for one label
single_label = label_binarizer[column].inverse_transform(one_label_df.values)
# join the output of the single label df to the entire output df
inverse_df = inverse_df.join(pd.DataFrame(single_label, columns=[column]))
inverse_df.drop(labels=['place_holder'], axis=1, inplace=True)
问题来自数据(在本例中是模型使用不当)。如果您为 MultiLabelBinarizer
创建一个 Dataframe,您将拥有:
您可以看到所有列都按升序排序。当你要求重建时,模型将按行重建"scanning"个值。
因此,如果您乘坐第一线,您将拥有:
1000 - California - January
现在如果你拿第二个,你有:
750 - February - New York
等等...
所以你的月份因为排序顺序被调换了。如果您将月份替换为 "ZFebrury",就可以了,但仍然只能替换为 "luck"
您应该做的是为每个分类特征训练 1 个模型,然后堆叠每个矩阵以获得最终矩阵。要还原它,您应该同时提取 "sub_matrix" 并执行 inverse_transform
.
每个特征创建1个模型,可以参考Napitupulu Jon在这个SO question[=中的回答17=]
编辑 1:
我尝试了 SO 问题中的代码,但它不起作用,因为列数发生了变化。这就是我现在所拥有的(但你仍然必须在某处保存每个功能的列)
import pandas as pd
import numpy as np
from sklearn.preprocessing import MultiLabelBinarizer
from collections import defaultdict
data = {
"State" : ["California", "New York", "Alaska", "Arizona", "Alaska", "Arizona"],
"Month" : ["January", "February", "May", "February", "January", "February" ],
"Number" : ["1000", "750", "500", "25000", "2000", "1"]
}
df = pd.DataFrame(data)
d = defaultdict(MultiLabelBinarizer) # dict of Features => model
list_encoded = [] # store single matrices
for column in df:
d[column].fit(df[column])
list_encoded.append(d[column].transform(df[column]))
merged = np.hstack(list_encoded) # matrix of 6 x 32
希望对您有所帮助并且解释清楚,
尼古拉斯
我正在使用 sklearn
的 multilabelbinarizer()
来训练我用来训练模型的机器学习中的多个列。
使用它后,我注意到它在反转 t运行s 时混淆了我的数据。我创建了一个 运行dom 值的测试集,其中我适合数据,t运行sform 它,inverse_transform
数据以返回原始数据。
我 运行 在 jupyter
笔记本中进行了简单测试以显示错误:
在 inverse_transformed
值中,第 1 行混淆了州和月份。
jupyter notebook code
首先,我使用multilabelbinarizer
的方式有没有错误?是否有不同的方法来实现相同的输出?
编辑: 感谢@Nicolas M. 帮助我解决了我的问题。我最终像这样解决了这个问题。
原谅粗略的解释,但结果比我原先想象的要复杂。我改用 label_binarizer
而不是 multi_label_binarizer
因为它
我最终对 label_binarizer
defaultdict
进行了 pickle,这样我就可以加载它并在我的机器学习项目的不同模块中使用它。
有一件事可能不是微不足道的,那就是我将新的 header 添加到我为每一列制作的数据框中。它采用 column_name + 列号的形式。我这样做是因为我需要反转 t运行sform 数据。为此,我搜索了包含原始列名的列,这些列将较大的数据框分隔成单独的列块。
这里是我使用的一些变量及其含义供参考:
lb_dict
- 存储不同标签二值化器的默认字典。
binarize_df
- 存储二值化数据的数据框。
binarized_label
- 标签将列中的一个标签二值化。
header
- 创建一个新的 header 表单:列名 + 数字列。
inverse_df
- 存储 inverse_transformed 数据的数据框。
one_label_list
- 查找具有原始列标记的列名列表。
one_label_df
- 创建一个只存储一列二值化数据的新数据框。
single_label
- 将 inverse_transformed 放入一列的二值化数据。
在此代码中数据是我传递给函数的数据帧。
lb_dict = defaultdict(LabelBinarizer)
# create a place holder dataframe to join new binarized data to
binarize_df = pd.DataFrame(['x'] * len(data.index), columns=['place_holder'])
# loop through each column and create a binarizer and fit/transform the data
# add new data to the binarize_df dataframe
for column in data.columns.values.tolist():
lb_dict[column].fit(data[column])
binarized_label = lb_dict[column].transform(data[column])
header = [column + str(i) for i in range(0, len(binarized_label[0]))]
binarize_df = binarize_df.join(pd.DataFrame(binarized_label, columns=header))
# drop the place holder value
binarize_df.drop(labels=['place_holder'], axis=1, inplace=True)
这是我写的 inverse_transform 函数:
inverse_df = pd.DataFrame(['x'] * len(output.index), columns=['place_holder'])
# use a for loop to run through the different output columns that need to be inverse_transformed
for column in output_cols:
# create a list of the different headers based on if the name contains the original output column name
one_label_list = [x for x in output.columns.values.tolist() if column in x]
one_label_df = output[one_label_list]
# inverse transform the data frame for one label
single_label = label_binarizer[column].inverse_transform(one_label_df.values)
# join the output of the single label df to the entire output df
inverse_df = inverse_df.join(pd.DataFrame(single_label, columns=[column]))
inverse_df.drop(labels=['place_holder'], axis=1, inplace=True)
问题来自数据(在本例中是模型使用不当)。如果您为 MultiLabelBinarizer
创建一个 Dataframe,您将拥有:
您可以看到所有列都按升序排序。当你要求重建时,模型将按行重建"scanning"个值。
因此,如果您乘坐第一线,您将拥有:
1000 - California - January
现在如果你拿第二个,你有:
750 - February - New York
等等...
所以你的月份因为排序顺序被调换了。如果您将月份替换为 "ZFebrury",就可以了,但仍然只能替换为 "luck"
您应该做的是为每个分类特征训练 1 个模型,然后堆叠每个矩阵以获得最终矩阵。要还原它,您应该同时提取 "sub_matrix" 并执行 inverse_transform
.
每个特征创建1个模型,可以参考Napitupulu Jon在这个SO question[=中的回答17=]
编辑 1:
我尝试了 SO 问题中的代码,但它不起作用,因为列数发生了变化。这就是我现在所拥有的(但你仍然必须在某处保存每个功能的列)
import pandas as pd
import numpy as np
from sklearn.preprocessing import MultiLabelBinarizer
from collections import defaultdict
data = {
"State" : ["California", "New York", "Alaska", "Arizona", "Alaska", "Arizona"],
"Month" : ["January", "February", "May", "February", "January", "February" ],
"Number" : ["1000", "750", "500", "25000", "2000", "1"]
}
df = pd.DataFrame(data)
d = defaultdict(MultiLabelBinarizer) # dict of Features => model
list_encoded = [] # store single matrices
for column in df:
d[column].fit(df[column])
list_encoded.append(d[column].transform(df[column]))
merged = np.hstack(list_encoded) # matrix of 6 x 32
希望对您有所帮助并且解释清楚,
尼古拉斯