Keras中具有类权重的多标签分类

Mah*_*bir 9 multilabel-classification keras

我一直坚持使用多标签分类(我必须说我对神经网络很新).首先,我将解释我正在努力训练的网络.我在网络中有1000个类,它们有多标签输出.对于每个训练示例,正输出的数量相同(即10),但是它们可以分配给1000个类中的任何一个.所以10个类有输出1而其余990有输出0.对于多标签分类,我使用'二进制交叉熵'作为成本函数,'sigmoid'作为激活函数.当我尝试0.5的这个规则作为1或0的截止时.所有这些都是0.我明白这是一个类不平衡问题.从这个链接,我理解,我可能不得不创建额外的输出标签.遗憾的是,我还没有弄清楚如何将其纳入keras中的简单神经网络.

nclasses = 1000

# if we wanted to maximize an imbalance problem!
#class_weight = {k: len(Y_train)/(nclasses*(Y_train==k).sum()) for k in range(nclasses)}

#print(class_weight)
# building neural network model
inp = Input(shape=[X_train.shape[1]])
x = Dense(5000, activation='relu')(inp)

x = Dense(4000, activation='relu')(x)

x = Dense(3000, activation='relu')(x)
x = Dense(2000, activation='relu')(x)
x = Dense(nclasses, activation='sigmoid')(x)
model = Model(inputs=[inp], outputs=[x])
print(model.summary())

adam=keras.optimizers.adam(lr=0.00001)
model.compile('adam', 'binary_crossentropy')
history = model.fit(
    X_train, Y_train, batch_size=32, epochs=50,verbose=0,shuffle=False)

plt.plot(history.history['loss'])
#plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()

model.save('model2.h5')
Run Code Online (Sandbox Code Playgroud)

任何人都可以帮我处理这里的代码,如果你能为这个问题提出一个好的"准确度"指标,我也非常感谢你们.

非常感谢 :) :)

den*_*s-w 11

我有类似的问题,遗憾的是大多数问题没有答案.尤其是班级不平衡问题.

在度量方面,有几种可能性:在我的情况下,我使用前1/2/3/4/5结果,并检查其中一个是否正确.因为在您的情况下,您总是拥有相同数量的标签= 1,您可以获得前10个结果并查看其中有多少是正确的,并将此结果与批量大小相比较.我没有发现将此算法包含为keras指标的可能性.相反,我写了一个回调,它在我的验证数据集上计算纪元结束时的指标.

此外,如果您预测测试数据集的前n个结果,请查看每个类的预测次数.该计数器类是用于此目的真是太方便了.

编辑:如果找到一个方法来包括类权重而不分割输出.你需要一个numpy 2d数组,其中包含有形状的权重[要预测的数字类别,2(背景和信号)].可以使用此函数计算这样的数组:

def calculating_class_weights(y_true):
    from sklearn.utils.class_weight import compute_class_weight
    number_dim = np.shape(y_true)[1]
    weights = np.empty([number_dim, 2])
    for i in range(number_dim):
        weights[i] = compute_class_weight('balanced', [0.,1.], y_true[:, i])
    return weights
Run Code Online (Sandbox Code Playgroud)

解决方案现在是构建您自己的二进制crossentropy损失函数,您可以在其中自己乘以权重:

def get_weighted_loss(weights):
    def weighted_loss(y_true, y_pred):
        return K.mean((weights[:,0]**(1-y_true))*(weights[:,1]**(y_true))*K.binary_crossentropy(y_true, y_pred), axis=-1)
    return weighted_loss
Run Code Online (Sandbox Code Playgroud)

权重[:,0]是一个包含所有背景权重和权重的数组[:,1]包含所有信号权重.

剩下的就是将这种损失包含在编译函数中:

model.compile(optimizer=Adam(), loss=get_weighted_loss(class_weights))
Run Code Online (Sandbox Code Playgroud)

  • 我真的很喜欢这个答案!顺便说一句,万一其他人遇到这个问题:如果你保存一个使用这个自定义丢失函数训练的模型,并想再次加载它,你将得到一个"未知丢失函数"错误.这可以通过设置"custom_objects"参数来克服,例如model = load_model("path/to/model.hd5f",custom_objects = {"weighted_loss":get_weighted_loss(weights)} (2认同)