Tensorflow DataSet Shuffle 影响验证训练的准确性和模棱两可的行为

Posted

技术标签:

【中文标题】Tensorflow DataSet Shuffle 影响验证训练的准确性和模棱两可的行为【英文标题】:Tensorflow DataSet Shuffle Impact the validation training accuracy and ambiguous behavior 【发布时间】:2021-07-06 02:39:40 【问题描述】:

我正在努力训练一个使用 tf.data.DataSet 作为输入的神经网络。

我发现,如果我在将整个数据集拆分为 train、val、test set 之前调用 .shuffle(),则 val(在训练中)和 test(在评估中)的准确度为 91%,但是当我运行 @987654322 时@ 在测试集上多次准确率和损失指标每次都发生变化。测试集上的.predict() 也会发生相同的行为,并且类每次都会更改。

这是训练的输出,评估结束预测过程

    total_record: 93166 - trainin_size: 74534 - val_size: 9316 - test_size: 9316
Epoch 1/5
145/145 [==============================] - 42s 273ms/step - loss: 1.7143 - sparse_categorical_accuracy: 0.4051 - val_loss: 1.4997 - val_sparse_categorical_accuracy: 0.4885
Epoch 2/5
145/145 [==============================] - 40s 277ms/step - loss: 0.7571 - sparse_categorical_accuracy: 0.7505 - val_loss: 1.1634 - val_sparse_categorical_accuracy: 0.6050
Epoch 3/5
145/145 [==============================] - 41s 281ms/step - loss: 0.4894 - sparse_categorical_accuracy: 0.8223 - val_loss: 0.7628 - val_sparse_categorical_accuracy: 0.7444
Epoch 4/5
145/145 [==============================] - 38s 258ms/step - loss: 0.3417 - sparse_categorical_accuracy: 0.8656 - val_loss: 0.4236 - val_sparse_categorical_accuracy: 0.8579
Epoch 5/5
145/145 [==============================] - 40s 271ms/step - loss: 0.2660 - sparse_categorical_accuracy: 0.8926 - val_loss: 0.2807 - val_sparse_categorical_accuracy: 0.9105

accr = model.evaluate(test_set)
19/19 [==============================] - 1s 39ms/step - loss: 0.2622 - sparse_categorical_accuracy: 0.9153

accr = model.evaluate(test_set)
19/19 [==============================] - 1s 40ms/step - loss: 0.2649 - sparse_categorical_accuracy: 0.9170

accr = model.evaluate(test_set)
19/19 [==============================] - 1s 40ms/step - loss: 0.2726 - sparse_categorical_accuracy: 0.9141

accr = model.evaluate(test_set)
19/19 [==============================] - 1s 40ms/step - loss: 0.2692 - sparse_categorical_accuracy: 0.9166

pred = model.predict(test_set)
pred_class = np.argmax(pred, axis=1)
pred_class
Out[41]: array([0, 1, 5, ..., 2, 0, 1])

pred = model.predict(test_set)
pred_class = np.argmax(pred, axis=1)
pred_class
Out[42]: array([2, 3, 1, ..., 1, 2, 0])

pred = model.predict(test_set)
pred_class = np.argmax(pred, axis=1)
pred_class
Out[43]: array([1, 2, 4, ..., 1, 3, 0])

pred = model.predict(test_set)
pred_class = np.argmax(pred, axis=1)
pred_class
Out[44]: array([0, 3, 1, ..., 0, 5, 4])

因此,我尝试在拆分后应用.shuffle(),并且仅在训练和验证上应用(注释主 .shuffle() 并取消注释 train_set 和 val_set 中的 shuffle)。

但在这种情况下,我发现网络仅在 5 个 epoch 之后就进入了过度拟合(之前的训练过程回调以 94% 的 val 准确度阻止了 30° epoch 的训练),自 2° 以来的准确率为 75%验证集上的纪元。

但是,在这种情况下,如果我在未应用 .shuffle () 的测试集上运行 .evaluate().predict(),则每次调用的指标和类都保持不变。

为什么会有这种行为? 但是特别是什么是好方法,模型的真正准确度是多少?

谢谢

这是进程的代码

""" ### Make tf.data.Dataset """

dataset = tf.data.Dataset.from_tensor_slices(( "features_emb_subj": features_emb_subj,
                                            "features_emb_snip": features_emb_snip,
                                            "features_emb_fromcat": features_emb_fromcat,
                                            "features_dense": features_dense,
                                            "features_emb_user": features_emb_user, cat_labels))

dataset = dataset.shuffle(int(len(features_dense)), reshuffle_each_iteration=True)


""" ### Split in train,val,test """

train_size = int(0.8 * len(features_dense))
val_size = int(0.10 * len(features_dense))
test_size = int(0.10 * len(features_dense))

test_set = dataset.take(test_size)
validation_set = dataset.skip(test_size).take(val_size)
training_set = dataset.skip(test_size + val_size)

test_set = test_set.batch(BATCH_SIZE, drop_remainder=False)
#validation_set = validation_set.shuffle(val_size, reshuffle_each_iteration=True)
validation_set = validation_set.batch(BATCH_SIZE, drop_remainder=False)
#training_set = training_set.shuffle(train_size, reshuffle_each_iteration=True)
training_set = training_set.batch(BATCH_SIZE, drop_remainder=True)


"""### Train model """

callbacks = [EarlyStopping(monitor='val_loss', patience=3, min_delta=0.0001, restore_best_weights=True)]

history = model.fit(  training_set,
                      epochs = 5,
                      validation_data = validation_set,
                      callbacks=callbacks,
                      class_weight = setClassWeight(cat_labels),
                      verbose = 1)

"""### Evaluate model """
accr = model.evaluate(test_set)

"""### Predict test_test """
pred = model.predict(test_set)
pred_class = np.argmax(pred, axis=1)
pred_class

【问题讨论】:

【参考方案1】:

在 Question 的 cmets 中,您可以看到 shuffle 适用于基础数据集,并且会传播到训练、测试和验证集中的引用。

我建议创建 3 个不同的数据集,在原始数据上使用(例如)sklearn.model_selection.train_test_split,然后在那些拆分张量切片上使用tf.data.Dataset.from_tensor_slices,因此您只能在训练数据集上使用shuffle

【讨论】:

以上是关于Tensorflow DataSet Shuffle 影响验证训练的准确性和模棱两可的行为的主要内容,如果未能解决你的问题,请参考以下文章

『TensorFlow』数据读取类_data.Dataset

tensorflow dataset.shuffle dataset.batch dataset.repeat 理解 注意点

tensorflow的keras实现搭配dataset 之一

在tensorflow中使用`dataset.map()`访问张量numpy数组

TensorFlow:dataset.train.next_batch 是如何定义的?

Google老师亲授 TensorFlow2.0入门到进阶笔记- (dataset)