【问题标题】:Tensorflow 2.0: How are metrics computed when the ouput is sequential?Tensorflow 2.0:当输出是连续的时,指标是如何计算的?
【发布时间】:2023-04-08 19:25:02
【问题描述】:

我一直在使用 Tensorflow 2.0 处理二进制顺序输入和输出,我一直想知道 Tensorflow 使用哪种方法来计算这些场景中训练期间的召回率或准确性等指标。

我网络的每个样本都包含 60 个时间步,每个时间步有 300 个特征,因此我的预期输出是一个由 1 和 0 组成的 (60, 1) 数组。假设我有 2000 个验证样本。在评估每个 epoch 的验证集时,tensorflow 是否将 所有 的 2000 个样本连接到单个 (2000*60=120000, 1) 数组中,然后与连接的 groundtruth 标签进行比较,还是评估每个 (60, 1)单独然后返回这些值的平均值?有没有办法修改这种行为?

【问题讨论】:

    标签: python tensorflow machine-learning keras tensorflow2.0


    【解决方案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))
    

    拟合模型

    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')
    

    我们可以看到训练数据(第一个图)的准确性在默认方法和我们的回调之间是不同的。这意味着训练数据的准确性是分批计算的。 我们的回调计算的验证准确率(第二个图)和默认方法是一样的!这意味着验证数据的分数是一次性计算的

    【讨论】:

      猜你喜欢
      • 2015-09-21
      • 2020-03-27
      • 2020-09-08
      • 1970-01-01
      • 2018-10-28
      • 1970-01-01
      • 2016-01-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多