多标签计算类权重 - 不可散列的类型

Posted

技术标签:

【中文标题】多标签计算类权重 - 不可散列的类型【英文标题】:Multi-label compute class weight - unhashable type 【发布时间】:2019-07-19 03:04:43 【问题描述】:

使用 Keras、sklearn 等在我的神经网络中处理具有 13 个可能输出多标签分类问题...

每个输出可以是一个数组,如 [0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1 ,0]。

我有一个不平衡的数据集,我尝试应用 compute_class_weight 方法,例如:

class_weight = compute_class_weight('balanced', np.unique(Y_train), Y_train)

当我尝试运行我的代码时,我得到 Unhashable Type: 'numpy.ndarray':

Traceback (most recent call last):
  File "main.py", line 115, in <module>
    train(dataset, labels)
  File "main.py", line 66, in train
    class_weight = compute_class_weight('balanced', np.unique(Y_train), Y_train)
  File "/home/python-env/env/lib/python3.6/site-packages/sklearn/utils/class_weight.py", line 41, in compute_class_weight
if set(y) - set(classes):
  TypeError: unhashable type: 'numpy.ndarray'

我知道那是因为我使用数组,已经尝试添加一些字典,

即:

class_weight_dict = dict(enumerate(np.unique(y_train), class_weight))

好吧,我不知道该怎么办,尝试了其他策略,但没有成功... 有什么想法吗?

提前致谢!

【问题讨论】:

可以上传数据吗?或发布一个工作示例? 【参考方案1】:

最近遇到了类似的问题,分享一下自己的思路。

如果您的“类别不平衡”意味着某些标签组合出现的频率高于其他标签组合,例如有 10 个 [0,1,0,0,1] 但只有 1 个 [0,1,0,0,0],您可以使用compute_sample_weight("balanced", Y_train) 代替compute_class_weight()。如果我是对的,这个函数会为训练数据集中的每个数据赋予权重。返回元组的长度是训练数据集的长度(即输入数据的数量)。该样本权重可以与 X_train 和 y_train 一起作为第三个参数添加到您的训练集中。

如果您的“类不平衡”指的是预测标签中的负数多于正数(0 多于 1)——这种情况会在训练过程中给出不切实际的高准确度分数,我认为上面@Prateek 的答案可以是一个解,函数给出的权重是0和1。

有人在这里出色地构建了一个代码 Multi-label classification with class weights in Keras 来回答这个问题。

如果您的“类别不平衡”是指某些类别的外观比其他类别多,例如,在 10 个样本中,其中 9 个包含标签 2,但其中只有 1 个包含标签 3,我不知道如何使用 class_weight 或 sample_weight 解决它。也许你可以尝试硬编码,统计每个类的出现次数,然后通过以下公式计算每个类的权重:

# weight_of_class_1 = n_samples/n_class*n_freq_class_1

# n_sample: total number of data
# n_class: number of class
# n_freq_class_1: number of appearance of class 1 in all your labels.

compute_class_weight 中使用了这个公式,但我不确定计算出的权重是否适合您的情况。

【讨论】:

【参考方案2】:

这主要是因为您的 Ytrain 是 2D 数组而不是 1D。 试试看:

class_weights = class_weight.compute_class_weight('balanced',
                                                 np.unique(np.ravel(y_train,order='C')),
                                                 np.ravel(y_train,order='C'))

【讨论】:

没用,对于多标签输入,它会将问题变为二进制 他遇到了维度问题,简单地给出 Y_train 并不能让库计算权重。解开它并使其成为一维不会将其更改为二进制,而只是将其从 2d 转换为 1。我遇到了同样的问题,这为我解决了! 我不同意。像 [[0, 0, 1, 0, 0],[0, 1, 0, 0, 0]] 之类的数据是否多,是二进制的。 np。 ravel 会将其转换为 [0, 0, 1, 0, 0, 0, 1, 0, 0, 0],并且 class_weight 将仅加权“零”和“一”而不是“2”和“3”,即是二进制格式的真正目标。

以上是关于多标签计算类权重 - 不可散列的类型的主要内容,如果未能解决你的问题,请参考以下文章

将权重分配给多标签 SVM 以平衡类别

Keras - 带权重的多标签分类

Keras 如何在多标签学习中更新权重(实现方式)

Keras如何在多标签学习中更新权重(实现方式)

如何在pytorch中计算BCEWithLogitsLoss的不平衡权重

Python字典:TypeError:不可散列的类型:'list'