MultiLabelBinarizer 在逆变换时混淆了数据

MultiLabelBinarizer mixes up data when inverse transforming

我正在使用 sklearnmultilabelbinarizer() 来训练我用来训练模型的机器学习中的多个列。

使用它后,我注意到它在反转 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

希望对您有所帮助并且解释清楚,

尼古拉斯