多标签计算类权重 - 不可哈希类型

问题描述 投票:0回答:4

在我的神经网络中使用 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))

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

提前致谢!

python keras scikit-learn neural-network
4个回答
3
投票

发生这种情况主要是因为您的 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'))

3
投票

我最近遇到了类似的问题,分享一下我的思考过程。

如果你的“类不平衡”意味着某些标签组合比其他标签组合出现得更频繁,例如有 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。

有人在这里巧妙地构造了一个代码在 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中使用了这个公式,但我不确定计算出的权重是否适合你的情况。


0
投票

你可以试试这个:

    # Frequencies by class labels
    unique, counts = np.unique(Y_train, return_counts=True)
    # Print the frequencies
    print(np.asarray((unique, counts)).T)

    num_samples = len(Y_train)
    n_classes = len(unique)

    print(num_samples)
    print(n_classes)

    weights = num_samples / (n_classes * counts)
    print(weights)

0
投票

我也遇到了同样的问题。我让它为我工作的方法是,首先我将

y_train
数据框转换为
numpy.array
。但由于形状不同,它显示出错误。因此用
numpy.reshape(y_train, -1)
重塑了数组。但它仍然不起作用。我在 github 问题中发现了一个建议。。之后,它对我来说完全没问题。

我的最终代码是,

y_train = np.reshape(y_train.values, -1) weights = compute_class_weight('balanced', classes=classes, y=y_train) d_weights = dict(enumerate(weights)) model.fit(x_train, y_train, epochs=200, batch_size=3000, validation_data=(x_test, y_test), class_weight=d_weights)
    
© www.soinside.com 2019 - 2024. All rights reserved.