多标签分类:keras自定义指标

时间:2018-04-23 18:24:23

标签: python tensorflow machine-learning keras

情境
我正在研究图像的multi_label分类问题。我试图预测39个标签。换句话说,我试图确定给定图像中存在39个特征中的哪一个(在一个图像中可以找到许多特征,这就是我在多标签分类情况下的原因。) 数据
我的输入数据是(X,Y):X是形状(1814,204,204,3),Y是形状(1814,39)。因此,基本上X是图像集,Y是与每个图像相关联的标签,将用于监督学习过程。

模型
我正在构建卷积神经网络以进行预测。对于这项任务,我使用Keras来创建我的模型。

我做了什么
为了验证我的模型,我需要选择指标。但是,Keras中提供的指标在我的情况下是不敬的,因为我处于多标签分类状态,因此无法帮助我验证我的模型。这就是我决定创建自定义指标的原因。我创建了应用于Y和Y_predict列的召回和精确度指标。换句话说,我将计算39个班级中每个班级的召回率和精确度。所以这是我的指标的代码:

def recall(y_true, y_pred):
    #Recall metric.

    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)),axis=0)
    possible_positives = K.sum(K.round(K.clip(y_true, 0, 1)),axis=0)
    recall = true_positives / (possible_positives + K.epsilon())
    return recall

def precision(y_true, y_pred):
    #Precision metric.

    true_positives = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)),axis=0)
    predicted_positives = K.sum(K.round(K.clip(y_pred, 0, 1)),axis=1)
    precision = true_positives / (predicted_positives + K.epsilon())
    return precision

我的矢量Y具有形状(n,39),这就是我在轴= 0上进行操作的原因。换句话说,对于每个标签,我都在计算精确度和召回率。

下一步,我通过将其调整到keras拟合函数来调用这两个指标。换句话说,我使用了这行代码:

model.compile(loss='binary_crossentropy', optimizer=sgd, metrics=[precision,recall])

构建,编译和拟合模型的代码:
这是我用于构建模型的代码,以及它的结果。 (我没有把代码的一部分放在我将数据分成训练和验证的地方:训练1269个样本,验证545个样本

# Model: CNN
model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=(204, 204, 3), padding='same', activation='relu', kernel_constraint=maxnorm(3)))
model.add(Dropout(0.2))
model.add(Conv2D(32, (3, 3), activation='relu', padding='same', kernel_constraint=maxnorm(3)))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(512, activation='relu', kernel_constraint=maxnorm(3)))
model.add(Dropout(0.5))
model.add(Dense(39))
model.add(Activation('sigmoid'))
# Compile model
epochs = 5
lrate = 0.001
decay = lrate/epochs
sgd = SGD(lr=lrate, momentum=0.9, decay=decay, nesterov=False)
model.compile(loss='binary_crossentropy', optimizer=sgd, metrics=[precision,recall])

# fitting the model 
model.fit(X_train, Y_train, epochs=epochs, batch_size=32,validation_data=(X_valid,Y_valid))

结果

Train on 1269 samples, validate on 545 samples
Epoch 1/5
  96/1269 [=>............................] - ETA: 6:40 - loss: 0.6668 - precision: 0.1031 - recall: 0.2493

问题/问题
问题1: 在结果部分的日志中,有精确值和召回值。我不知道为什么我得到了真正的价值而不是价值向量。我构建我的两个指标的方式应该给我一个形状(1,39)用于精度和(1,39)用于调用的数组,其中应该包含每个类的精度和调用,仍然输出只是一个数字? /> 问题2: 这些由日志给出的精度和召回值,它们代表size = batch数据的度量计算?如何计算一个时期的度量标准(这比作为一个批处理的计算信息更有用?有人可能会说,只计算所有批次的平均值?当然,这就是我的想法但是我不知道怎么做,因为KERAS对我来说是一个黑盒子,我不知道幕后发生了什么''''''''''''''为了遵循/修改适当的代码部分?

2 个答案:

答案 0 :(得分:0)

我认为您正在使用tensorflow后端。您实际上可以sklearn.metrics使用keras,只需通过sklearn调用tf.py_func指标,它会将python函数转换为tf函数。

对于Q1,您看到的实际值实际上是度量向量的平均值。

对于Q2。它应该是整个时期的平均得分以进行验证。

答案 1 :(得分:0)

要补充说明,Keras会在每个验证批次结束时计算指标,因此您的召回率和准确性会产生误导。这就是为什么将它们从Keras 2中删除的原因。您将需要创建一个Keras回调,该回调将传递整个验证数据并在每个时期结束时计算指标(在代码中,这位于Callback的on_epoch_end部分内) )。 A simple example of this can be found hereeven simpler here,但代码可能已过时。 Here is a final example (at the bottom edit),他们使用on_epoch_end方法附加许多指标。

对于您有关向量以浮点数返回的问题,Keras documentation states that metrics automatically averages vector output

  

返回值:单个张量值,表示输出数组的平均值   跨所有数据点。

我假设这样做是为了方便和简单,因为绝大多数指标都需要对结果矢量进行平均,但这可能是Keras团队进行的修改。