训练集准确率高但是验证集准确率非常低
本人尝试用花朵图像识别分类的代码,改出解决一个关于植物生长阶段分类的代码。但是训练完成后,训练集准确率率可以达到90%,但验证集准确率只有40%而且震荡严重。损失曲线也有很大问题,目前尝试改了dropout参数,数据增强参数,希望能帮忙看看问题。其中总共是6个分类,每个分类大概100张图片。
import matplotlib.pyplot as plt
import numpy as np
import os
import PIL
import tensorflow as tf
import torch
import shutil
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.models import Sequential
# 下载数据集
import pathlib
# dataset_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz"
data_dir = pathlib.Path("D:/shujuji")
# data_dir = tf.keras.utils.get_file('flower_photos', origin=dataset_url, untar=True)
# data_url = pathlib.Path(dataset_url)
# data_dir = tf.keras.utils.get_file('shujuji', origin=dataset_url, untar=True)
# data_dir = pathlib.Path(data_dir)
# 查看数据集图片的总数量
image_count = len(list(data_dir.glob('*/*.jpg')))
print(image_count)
# 查看郁金香tulips目录下的第1张图片;
# tulips = list(data_dir.glob('tulips/*'))
# PIL.Image.open(str(tulips[0]))
# 定义加载图片的一些参数,包括:批量大小、图像高度、图像宽度
batch_size = 32
img_height = 800
img_width = 800
# 将80%的图像用于训练
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="training",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
# 将20%的图像用于验证
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
data_dir,
validation_split=0.2,
subset="validation",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
# 打印数据集中的类别名称,字母顺序对应于目录名称
class_names = train_ds.class_names
print(class_names)
# 将像素的值标准化至0到1的区间内。
normalization_layer = layers.experimental.preprocessing.Rescaling(1. / 255)
# 调用map将其应用于数据集:
normalized_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))
image_batch, labels_batch = next(iter(normalized_ds))
first_image = image_batch[0]
# Notice the pixels values are now in `[0,1]`.
print(np.min(first_image), np.max(first_image))
# 数据增强 通过对已有的训练集图片 随机转换(反转、旋转、缩放等),来生成其它训练数据
data_augmentation = keras.Sequential(
[
layers.experimental.preprocessing.RandomFlip("horizontal",input_shape=(img_height,img_width,3)),
layers.experimental.preprocessing.RandomRotation(0.1),
layers.experimental.preprocessing.RandomZoom(0.1),
]
)
# 搭建 网络模型
model = Sequential([
data_augmentation,
layers.experimental.preprocessing.Rescaling(1. / 255),
layers.Conv2D(16, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Conv2D(32, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Conv2D(64, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Dropout(0.2),
layers.Flatten(),
layers.Dense(128, activation='relu'),
layers.Dense(64, activation='relu')
# layers.Dense(1,activation="sigmoid")
# layers.Dense(5,activation='softmax')
# layers.Dense(num_classes)
])
# 编译模型
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
# 查看网络结构
model.summary()
# 训练模型
epochs = 100
history = model.fit(
train_ds,
validation_data=val_ds,
epochs=epochs
)
# 在训练和验证集上查看损失值和准确性
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs_range = range(epochs)
# torch.save(model,'C:\\Users\\admin\\PycharmProjects\\pythonProject\\model0.h5')
model.save('model0.h5')
#绘图
plt.figure(figsize=(8, 8))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')
plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()
更新问题
加入了l1l2混合正则化层,有一定效果
针对这个问题,我会提供以下解决方案:
增加数据量 我们可以看到该数据集每个分类只有100张图片,这样的数量可能不足以训练一个具有很好泛化性的模型。因此,我们需要尽量扩充数据量,这可以通过数据增强来实现。该数据集的特点是不同生长阶段的植物,我们可以利用不同时期内的植物图片进行组合,产生的数据量可以增加到1,000张以上。同时,如果有条件可以通过网络搜索收集更多的植物图片。
调整网络架构 为了更好地解决训练集准确率高但验证集准确率低这一问题,我们可能需要调整网络架构。尝试添加或移除某些层,或者调整各层参数,可以找到一个更好的模型。可以尝试一下调整以下网络架构: 增加卷积层:卷积层可以将输入的特征数据进行特征提取,增加卷积层有可能提高泛化性。可以尝试增加或调整现有层结构。 增加池化层:池化层能够减少特征数据量,使训练过程更加高效。 使用Batch Normalization层:Batch Normalization能够使每个神经元的输出都满足零均值和适当方差的分布,有助于训练和提高模型的泛化能力。 根据实际情况选择合适的激活函数。
调整训练参数 调整训练参数可以帮助我们优化模型。可以尝试以下方法: 增加Dropout的概率:这样可以增加一些随机性,减少神经元节点间的联合适应性,增强泛化能力。 调整学习率:学习率可能需要进行调整,以更好地收敛模型。 使用不同的优化算法:可以尝试不同的优化算法(如Adam,SGD等),找到更好的优化方案。 增加正则化参数:L1L2混合正则化层可以减少参数,使得模型可以更好的泛化。
进行更多的模型测试和分析 需要对模型进行更全面的分析,可以尝试以下方法: 使用交叉验证:我们可以使用交叉验证来验证我们的模型,在一定程度上减小过拟合的现象。 可视化损失和准确率:使用可视化工具可以更好地帮助我们了解训练过程中的变化,找到问题。 检查数据集:检查一遍数据集,看是否有标签错误的情况以及数据的质量问题。这可能是导致验证集准确率低的一个原因。