python - 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
可以做些什么来确保在指标中评估样本权重?
解决方案
Keras 不会在评估指标时自动包含样本权重。这就是为什么损失和指标之间存在巨大差异的原因。
如果您希望在评估指标时包含样本权重,请将它们作为weighted_metrics
而不是指标传递。
model.compile(optimizer=Adam(1e-3),
loss=tf.keras.losses.categorical_crossentropy,
weighted_metrics=[tf.keras.losses.categorical_crossentropy]))
推荐阅读
- c# - 从 appsettings.json 读取 List<(string,string[])>
- google-cloud-platform - 撤销 1 个令牌会撤销相同 OAuth 客户端 ID + 用户同意对的所有令牌
- javascript - mapbox gl js,用线连接点
- python - cx_oracle 禁用来自控制台的语句回显
- javascript - 在 react native (js) 中为 python cli 编写 ui
- .net - 如何为 Blazor Web Assembly 实现缓存清除
- c++ - 使用共享指针来自另一个线程的纯虚拟调用
- flutter - 为什么我看不到 useTextEditingController 值的更新?
- superpowered - 如何使用 Superpowerd sdk loopBetween 函数识别循环数
- reactjs - 模型通用 Typescript 类型以强制多个道具具有相同的键集