Python 反变换时,多LabelBinarizer会混淆数据

Python 反变换时,多LabelBinarizer会混淆数据,python,pandas,machine-learning,sklearn-pandas,multilabel-classification,Python,Pandas,Machine Learning,Sklearn Pandas,Multilabel Classification,我正在使用sklearn的multilabelbinarizer在我的机器学习中训练多个列,我用它来训练我的模型 在使用它之后,我注意到当它对数据进行逆变换时,它会混淆我的数据。我创建了一个随机值的测试集,在这里我对数据进行拟合、变换,然后对数据进行逆变换以返回原始数据 我在jupyter笔记本中运行了一个简单的测试来显示错误: 在逆_变换的值中,它在第1行中弄乱了状态和月份 首先,我如何使用multilabelbinarizer有错误吗?是否有不同的方法实现相同的输出 编辑: 感谢@Nicol

我正在使用sklearn的multilabelbinarizer在我的机器学习中训练多个列,我用它来训练我的模型

在使用它之后,我注意到当它对数据进行逆变换时,它会混淆我的数据。我创建了一个随机值的测试集,在这里我对数据进行拟合、变换,然后对数据进行逆变换以返回原始数据

我在jupyter笔记本中运行了一个简单的测试来显示错误:

在逆_变换的值中,它在第1行中弄乱了状态和月份

首先,我如何使用multilabelbinarizer有错误吗?是否有不同的方法实现相同的输出

编辑: 感谢@Nicolas M.帮助我解决问题。我就这样解决了这个问题

请原谅这个粗略的解释,但结果比我原来想象的要复杂得多。我转而使用label_二值化器而不是multi_label_二值化器,因为它

最后我对标签\u binarizer defaultdict进行了酸洗,这样我就可以加载它并在我的机器学习项目的不同模块中使用它

有一件事可能并不简单,那就是我为每列创建的数据框架添加了新的头。它的形式是列名称+列编号。我这样做是因为我需要对数据进行逆变换。为此,我搜索了包含原始列名的列,原始列名将较大的数据帧分隔为各个列块

以下是我使用的一些变量及其参考意义: lb_dict-存储不同标签二进制程序的默认dict。 binarize_df-存储二值化数据的数据帧。 binarized_label-label对列中的一个标签进行二值化。 标题-创建一个新的标题表单:列名+数字列

逆_df-存储逆_变换数据的数据帧。 one_label_list-查找带有原始列标记的列名列表。 one_label_df-创建一个新的数据框,该数据框仅存储一列的二进制数据。 single_label—将反向_转换为一列的二进制数据

在这段代码中,数据是我传递给函数的数据帧

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_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创建数据帧,您将拥有:

您可以看到,所有列都是按升序排序的。当您要求重建时,模型将通过按行扫描值来重建它

因此,如果你选择第一条线,你有:

1000-加利福尼亚-一月

现在,如果你选择第二个,你有:

750-2月-纽约

等等

因此,由于排序顺序,您的月份被交换。如果你用ZFebrury来代替这个月,一切都会好的,但仍然是靠运气

您应该做的是为每个分类特征训练1个模型,并堆叠每个矩阵以获得最终矩阵。要还原它,您应该提取两个子矩阵并进行逆变换

要为每个特征创建一个模型,您可以参考本手册中Napitupulu Jon的答案

编辑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
我希望这会有帮助,而且解释得足够清楚


Nicolas

为什么你的问题中的代码在图片中而不是文本?我当然更喜欢复制粘贴代码,而不是打印出来,我相信其他人也有同样的感觉。你需要让人们更容易帮助你。非常感谢。我来试一试。