Eth*_*lla -3 python machine-learning pandas multilabel-classification sklearn-pandas
我正在使用sklearn的multilabelbinarizer()来训练我的机器学习中的多个列,我用它来训练我的模型。
使用它后,我注意到它在逆变换时混淆了我的数据。我创建了一组随机值的测试集,在其中拟合数据、对其进行转换,然后inverse_transform将数据恢复为原始数据。
我进行了一个简单的测试jupyter笔记本上进行了一个简单的测试以显示错误:
在inverse_transformed第 1 行的值中,它混淆了州和月份。
首先,我的使用方式是否有错误multilabelbinarizer?有没有不同的方法来实现相同的输出?
编辑: 感谢@Nicolas M. 帮助我解决我的问题。我最终像这样解决了这个问题。
请原谅我的粗略解释,但结果比我最初想象的要复杂。我改用 thelabel_binarizer而不是multi_label_binarizer因为它
我最终腌制了label_binarizer defaultdict以便我可以加载它并在我的机器学习项目的不同模块中使用它。
一件可能不简单的事情是我向为每一列制作的数据帧添加新标题。它采用列名+列号的形式。我这样做是因为我需要对数据进行逆变换。为此,我搜索了包含原始列名称的列,该列名称将较大的数据帧分隔成各个列块。
这里是我使用的一些变量及其含义供参考:
lb_dict- 存储不同标签二值化器的默认字典。
binarize_df- 存储二进制数据的数据框。
binarized_label- label 将列中的一个标签二值化。
header- 创建一个新的标题形式:列名+数字列。
inverse_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)
Run Code Online (Sandbox Code Playgroud)
这是我编写的 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)
Run Code Online (Sandbox Code Playgroud)
问题来自数据(在本例中是模型的错误使用)。如果您创建一个数据框,MultiLabelBinarizer您将拥有:
您可以看到所有列均按升序排序。当您要求重建时,模型将通过按行“扫描”值来重建它。
因此,如果您乘坐第一线,您将拥有:
1000 - 加利福尼亚州 - 一月
现在,如果您选择第二个,您将得到:
750 - 二月 - 纽约
等等...
所以你的月份因为排序顺序而被交换。如果你用“ZFebrury”替换月份,那就没问题了,但仍然只能靠“运气”
您应该做的是为每个分类特征训练 1 个模型,然后堆叠每个矩阵以获得最终矩阵。要恢复它,您应该提取“sub_matrix”并执行inverse_transform.
要为每个功能创建 1 个模型,您可以参考Napitupulu Jon在这个SO 问题中的答案
我尝试了 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
Run Code Online (Sandbox Code Playgroud)
我希望它能有所帮助,并且解释足够清楚,
尼古拉斯
| 归档时间: |
|
| 查看次数: |
1097 次 |
| 最近记录: |