首页 > 解决方案 > Keras weighted_metrics 在计算中不包括样本权重

问题描述

我正在训练一个形状为 (400,22) 的二维张量作为输入和输出的 CNN 模型。我使用 categorical_crossentropy 作为损失和度量。然而,损失/指标值非常不同。

我的模型有点像这样:

1. 使用样本权重,并通过metrics=in传递指标model.compile

# Imports
import tensorflow as tf
from tensorflow.keras.layers import *
from tensorflow.keras.optimizers import *
from tensorflow.keras.regularizers import *
from tensorflow.keras import *
import numpy as np

# Build the model
X_input = Input(shape=(400,22))
X = Conv1D(filters=32, kernel_size=2, activation='elu', 
           kernel_regularizer=L2(1e-4), bias_regularizer=L2(1e-4), 
           padding='same')(X_input)
X = Dropout(0.2)(X)
X = Conv1D(filters=32, kernel_size=2, activation='elu', 
           kernel_regularizer=L2(1e-4), bias_regularizer=L2(1e-4), 
           padding='same')(X)
X = Dropout(0.2)(X)
y = Conv1D(filters=22, kernel_size=1, activation='softmax', 
           kernel_regularizer=L2(1e-4), bias_regularizer=L2(1e-4), 
           padding='same')(X)
model = Model(X_input, y, name='mymodel')


# Compile and train the model (with metrics=[])
model.compile(optimizer=Adam(1e-3),
              loss=tf.keras.losses.categorical_crossentropy,
               metrics=[tf.keras.losses.categorical_crossentropy])
Xtrain = np.random.rand(20,400,22)
ytrain = np.random.rand(20,400,22)
np.random.seed(0)
sample_weight = np.random.choice([0.01, 0.1, 1], size=20)
history = model.fit(x=Xtrain, y=ytrain, sample_weight=sample_weight, epochs=4)
Epoch 1/4
1/1 [==============================] - 0s 824us/step - loss: 10.2952 - categorical_crossentropy: 34.9296
Epoch 2/4
1/1 [==============================] - 0s 785us/step - loss: 10.2538 - categorical_crossentropy: 34.7858
Epoch 3/4
1/1 [==============================] - 0s 772us/step - loss: 10.2181 - categorical_crossentropy: 34.6719
Epoch 4/4
1/1 [==============================] - 0s 766us/step - loss: 10.1903 - categorical_crossentropy: 34.5797

从结果可以看出,Keras 在计算度量时没有使用样本权重,因此它大于损失。如果我们将样本权重更改为 1,我们将得到以下结果:

2. 样本权重 = 个,metrics=在 `model.compile 中传递指标。

# Compile and train the model
model.compile(optimizer=Adam(1e-3),
              loss=tf.keras.losses.categorical_crossentropy,
               metrics=[tf.keras.losses.categorical_crossentropy])
Xtrain = np.random.rand(20,400,22)
ytrain = np.random.rand(20,400,22)
np.random.seed(0)
sample_weight = np.ones((20,))
history = model.fit(x=Xtrain, y=ytrain, sample_weight=sample_weight, epochs=4)
Epoch 1/4
1/1 [==============================] - 0s 789us/step - loss: 35.2659 - categorical_crossentropy: 35.2573
Epoch 2/4
1/1 [==============================] - 0s 792us/step - loss: 35.0647 - categorical_crossentropy: 35.0562
Epoch 3/4
1/1 [==============================] - 0s 778us/step - loss: 34.9301 - categorical_crossentropy: 34.9216
Epoch 4/4
1/1 [==============================] - 0s 736us/step - loss: 34.8076 - categorical_crossentropy: 34.7991

现在指标和损失与样本权重非常接近。我知道,由于 dropout、正则化的影响,以及在每个 epoch 结束时计算度量的事实,损失比指标略大,而损失是训练中批次的平均值。

如何获得包含样本权重的指标?

3. 更新:使用样本权重,并通过weighted_metrics=in传递指标model.compile

有人建议我使用weighted_metrics=[...]而不是metrics=[...]in model.compile。然而,Keras 仍然没有将样本权重包含在指标的评估中。

# Compile and train the model
model.compile(optimizer=Adam(1e-3),
              loss=tf.keras.losses.categorical_crossentropy,
               weighted_metrics=[tf.keras.losses.categorical_crossentropy])
Xtrain = np.random.rand(20,400,22)
ytrain = np.random.rand(20,400,22)
np.random.seed(0)
sample_weight = np.random.choice([0.01, 0.1, 1], size=20)
history = model.fit(x=Xtrain, y=ytrain, sample_weight=sample_weight, epochs=4)
Epoch 1/4
1/1 [==============================] - 0s 764us/step - loss: 10.2581 - categorical_crossentropy: 34.9224
Epoch 2/4
1/1 [==============================] - 0s 739us/step - loss: 10.2251 - categorical_crossentropy: 34.8100
Epoch 3/4
1/1 [==============================] - 0s 755us/step - loss: 10.1854 - categorical_crossentropy: 34.6747
Epoch 4/4
1/1 [==============================] - 0s 746us/step - loss: 10.1631 - categorical_crossentropy: 34.5990

可以做些什么来确保在指标中评估样本权重?

标签: pythontensorflowkerasdeep-learningloss-function

解决方案


Keras 不会在评估指标时自动包含样本权重。这就是为什么损失和指标之间存在巨大差异的原因。

如果您希望在评估指标时包含样本权重,请将它们作为weighted_metrics而不是指标传递。

model.compile(optimizer=Adam(1e-3), 
              loss=tf.keras.losses.categorical_crossentropy,
              weighted_metrics=[tf.keras.losses.categorical_crossentropy]))

推荐阅读