[英]Tensorflow 2.0: How are metrics computed when the ouput is sequential?
我一直在使用 Tensorflow 2.0 处理二进制顺序输入和输出,我一直想知道 Tensorflow 使用哪种方法来计算这些场景中训练期间的召回率或准确性等指标。
我网络的每个样本都包含 60 个时间步长,每个时间步长有 300 个特征,因此我预期的 output 是 1 和 0 的(60, 1)
数组。 假设我有 2000 个验证样本。 在评估每个时期的验证集时,tensorflow 是否将所有2000 个样本连接到一个(2000*60=120000, 1)
数组中,然后与连接的 groundtruth 标签进行比较,还是评估(60, 1)
单独然后返回这些值的平均值? 有没有办法修改这种行为?
默认情况下,Tensorflow/Keras 会为训练数据批量计算指标,同时它会在fit
方法中通过validation_data
参数传递的所有数据上计算相同的指标。
这意味着在拟合训练数据期间打印的指标是在所有批次上计算的分数的平均值。 换句话说,对于 trainset keras 单独评估每个 bach,然后返回这些值的平均值。 由于验证数据不同,keras 获取所有验证样本,然后将它们与“连接的”groundtruth 标签进行比较。
为了用代码证明这种行为,我提出了一个虚拟示例。 我提供了一个自定义回调,它可以确定在 epoch 结束时传递的所有数据的准确度得分(用于训练和可选的验证)。 这有助于我们了解 tensorflow 在训练期间的行为。
import numpy as np
from sklearn.metrics import accuracy_score
import tensorflow as tf
from tensorflow.keras.layers import *
from tensorflow.keras.models import *
from tensorflow.keras.callbacks import *
class ACC_custom(tf.keras.callbacks.Callback):
def __init__(self, train, validation=None):
super(ACC_custom, self).__init__()
self.validation = validation
self.train = train
def on_epoch_end(self, epoch, logs={}):
logs['ACC_score_train'] = float('-inf')
X_train, y_train = self.train[0], self.train[1]
y_pred = (self.model.predict(X_train).ravel()>0.5)+0
score = accuracy_score(y_train.ravel(), y_pred)
if (self.validation):
logs['ACC_score_val'] = float('-inf')
X_valid, y_valid = self.validation[0], self.validation[1]
y_val_pred = (self.model.predict(X_valid).ravel()>0.5)+0
val_score = accuracy_score(y_valid.ravel(), y_val_pred)
logs['ACC_score_train'] = np.round(score, 5)
logs['ACC_score_val'] = np.round(val_score, 5)
else:
logs['ACC_score_train'] = np.round(score, 5)
创建虚拟数据
x_train = np.random.uniform(0,1, (1000,60,10))
y_train = np.random.randint(0,2, (1000,60,1))
x_val = np.random.uniform(0,1, (500,60,10))
y_val = np.random.randint(0,2, (500,60,1))
适合model
inp = Input(shape=((60,10)), dtype='float32')
x = Dense(32, activation='relu')(inp)
out = Dense(1, activation='sigmoid')(x)
model = Model(inp, out)
es = EarlyStopping(patience=10, verbose=1, min_delta=0.001,
monitor='ACC_score_val', mode='max', restore_best_weights=True)
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
history = model.fit(x_train,y_train, epochs=10, verbose=2,
callbacks=[ACC_custom(train=(x_train,y_train),validation=(x_val,y_val)),es],
validation_data=(x_val,y_val))
在下图中,我比较了我们的回调计算的精度和 keras 计算的精度
plt.plot(history.history['ACC_score_train'], label='accuracy_callback_train')
plt.plot(history.history['accuracy'], label='accuracy_default_train')
plt.legend(); plt.title('train accuracy')
plt.plot(history.history['ACC_score_val'], label='accuracy_callback_valid')
plt.plot(history.history['val_accuracy'], label='accuracy_default_valid')
plt.legend(); plt.title('validation accuracy')
正如我们所看到的,训练数据(第一个图)的准确性在默认方法和我们的回调之间是不同的。 这意味着训练数据的准确性是分批计算的。 我们的回调计算的验证准确率(第二个图)和默认方法是一样的! 这意味着验证数据的分数是一次性计算的
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.