类别的一位有效编码

3

我有一个类似于这样的列表:

list = ['Opinion, Journal, Editorial',
        'Opinion, Magazine, Evidence-based',
        'Evidence-based']

逗号在类别之间分割,例如“Opinion”和“Journal”是两个不同的类别。实际列表更大,具有更多可能的类别。我想使用一位有效编码来转换该列表,以便可以用于机器学习。例如,从该列表中,我希望生成一个包含数据的稀疏矩阵:

list = [[1, 1, 1, 0, 0],
        [1, 0, 0, 0, 1],
        [0, 0, 0, 0, 1]]

理想情况下,我希望使用scikit-learn的独热编码器,因为我认为这将是最有效的。

回应@nbrayns的评论:

这个想法是将类别列表从文本转换为向量,如果它属于该类别,则分配为1,否则为0。对于上面的示例,标题将是:

headings = ['Opinion', 'Journal', 'Editorial', 'Magazine', 'Evidence-based']

哪些值应该是1,哪些应该是0? - nbryans
@nbryans 已经编辑了问题。 - user7347576
4个回答

10

如果你能使用Pandas,那么这个功能基本上就内置在那里了:

import pandas as pd

l = ['Opinion, Journal, Editorial', 'Opinion, Magazine, Evidence-based', 'Evidence-based']
pd.Series(l).str.get_dummies(', ')
   Editorial  Evidence-based  Journal  Magazine  Opinion
0          1               0        1         0        1
1          0               1        0         1        1
2          0               1        0         0        0
如果你想使用 sklearn 系统,你需要使用 MultiLabelBinarizer,而不是 OneHotEncoder。正如其名称所示,OneHotEncoder 只支持每个类别每个样本的一级别,而你的数据集有多个级别。
from sklearn.preprocessing import MultiLabelBinarizer

mlb = MultiLabelBinarizer()  # pass sparse_output=True if you'd like
mlb.fit_transform(s.split(', ') for s in l)
[[1 0 1 0 1]
 [0 1 0 1 1]
 [0 1 0 0 0]]

要将列映射回类别级别,可以访问mlb.classes_。 对于上面的示例,这将给出['Editorial' 'Evidence-based' 'Journal' 'Magazine' 'Opinion']


无论分类的顺序如何,这个会起作用吗? - user7347576
2
是的,如果您在询问“Opinion, Journal”或“Journal, Opinion”是否有区别,那么答案是否定的。 - Igor Raush

1

还有一种方法:

l = ['Opinion, Journal, Editorial', 'Opinion, Magazine, Evidence-based', 'Evidence-based']

# Get list of unique classes
classes = list(set([j for i in l for j in i.split(', ')]))
=> ['Journal', 'Opinion', 'Editorial', 'Evidence-based', 'Magazine']

# Get indices in the matrix
indices = np.array([[k, classes.index(j)] for k, i in enumerate(l) for j in i.split(', ')])
=> array([[0, 1],
          [0, 0],
          [0, 2],
          [1, 1],
          [1, 4],
          [1, 3],
          [2, 3]])

# Generate output
output = np.zeros((len(l), len(classes)), dtype=int)
output[indices[:, 0], indices[:, 1]]=1
=> array([[ 1,  1,  1,  0,  0],
          [ 0,  1,  0,  1,  1],
          [ 0,  0,  0,  1,  0]])

0

这可能不是最有效的方法,但很容易理解。
如果您还没有所有可能单词的列表,则需要创建该列表。在下面的代码中,它被称为unique。然后,输出矩阵s的列将对应于那些唯一的单词;行将是列表中的项目。

import numpy as np

lis = ['Opinion, Journal, Editorial','Opinion, Magazine, Evidence-based','Evidence-based']

unique=list(set(", ".join(lis).split(", ")))
print unique
# prints ['Opinion', 'Journal', 'Magazine', 'Editorial', 'Evidence-based']

s = np.zeros((len(lis), len(unique)))
for i, item in enumerate(lis):
    for j, notion in enumerate(unique):
        if notion in item:
            s[i,j] = 1

print s
# prints [[ 1.  1.  0.  1.  0.]
#         [ 1.  0.  1.  0.  1.]
#         [ 0.  0.  0.  0.  1.]]

-1
非常容易在 pandas 中实现:
import pandas as pd
s = pd.Series(['a','b','c'])
pd.get_dummies(s)

输出:

   a  b  c
0  1  0  0
1  0  1  0
2  0  0  1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接