针对少量数据的模型训练

"""如何在小型数据集上进行卷积神经网络的训练
小型数据集:在实际应用场景中,可能会遇到数据量不够的情况
    这里的小可能是几百张图像,也可能是几万张图像
面临的问题:
    小型数据集由于数据量不够,网络训练过程中记忆容易出现过拟合

常见的解决方案:
①从头开始自己训练一个小型模型
②使用预训练的网络做特征提取
③对预训练的网络进行微调"""

"""本次实验,我们使用kaggle竞赛中的猫狗分类数据集,我们从中抽取:
        猫狗各1000张作为训练集,猫狗各500张作为验证集,猫狗各500张作为测试集
我们从头开始训练一个小型网络:4层卷积+2层全连接"""

from tensorflow.keras import layers
from tensorflow.keras import models

model=models.Sequential()
model.add(layers.Conv2D(32,(3,3),activation="relu",input_shape=(150,150,3)))  #注意图片尺寸不统一,在输入网络之前,我们将尺寸统一至150*150
model.add(layers.MaxPool2D((2,2)))
model.add(layers.Conv2D(64,(3,3),activation="relu"))
model.add(layers.MaxPool2D((2,2)))
model.add(layers.Conv2D(128,(3,3),activation="relu"))
model.add(layers.MaxPool2D((2,2)))
model.add(layers.Conv2D(128,(3,3),activation="relu"))
model.add(layers.MaxPool2D((2,2)))
model.add(layers.Flatten())
model.add(layers.Dense(512,activation="relu"))
model.add(layers.Dense(1,activation="sigmoid"))

# print(model.summary())
"""数据预处理:
keras内部具有从文夹中读取图片,并将对其进行预处理(缩放,数据类型转换等),并对其进行批量化的生成器"""
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import os

#查看对应文件夹的文件数
new_data_dir="cat_and_dog_small" #存放小数据集路径
#构建小数据集中的训练,验证,测试数据文件夹
train_data_dir=os.path.join(new_data_dir,"train")
val_data_dir=os.path.join(new_data_dir,'val')
test_data_dir=os.path.join(new_data_dir,"test")

#猫的训练数据存储
train_cats_dir=os.path.join(train_data_dir,"cats")
val_cats_dir=os.path.join(val_data_dir,"cats")
test_cats_dir=os.path.join(test_data_dir,"cats")

#狗的训练数据存储
train_dogs_dir=os.path.join(train_data_dir,"dogs")
val_dogs_dir=os.path.join(val_data_dir,'dogs')
test_dogs_dir=os.path.join(test_data_dir,"dogs")
#构建生成器
train_data_gen=ImageDataGenerator(rescale=1.0/255)
test_data_gen=ImageDataGenerator(rescale=1.0/255)

#生成器配置,加载数据
train_generator=train_data_gen.flow_from_directory(train_data_dir,target_size=(150,150),batch_size=20,class_mode="binary")
val_generator=test_data_gen.flow_from_directory(val_data_dir,target_size=(150,150),batch_size=20,class_mode="binary")

# for data,target in train_generator:
#     print(data.shape)
#     print(target.shape)
#     break

"""训练过程配置"""
from tensorflow.keras import optimizers
from tensorflow.keras import losses
model.compile(optimizer=optimizers.RMSprop(lr=1e-4),loss=losses.binary_crossentropy,metrics=["acc"])

"""训练,对于批量数据生成器,我们可以使用fit_generator
steps_per_epoch:根据数据量/batch_size 算出
validation_steps:验证数据量/batch_Size算出"""

history=model.fit_generator(train_generator,steps_per_epoch=100,epochs=30,validation_data=val_generator,validation_steps=50)

"""模型的保存"""
model.save("cats_and_dogs_smallNet_1.h5")  #keras权重保存文件以h5为后缀

"""绘制训练过程,训练集和验证集上损失值和准确率曲线"""
import matplotlib.pyplot as plt
import numpy as np

"""损失函数绘制"""
history_dict=history.history
train_loss_values=history_dict["loss"]
val_loss_values=history_dict["val_loss"]
epochs=np.arange(1,len(train_loss_values)+1)

plt.figure(1)
plt.plot(epochs,train_loss_values,label="training loss")
plt.plot(epochs,val_loss_values,label="val loss")
plt.title("Training and Val Loss")
plt.xlabel("Epoch")
plt.ylabel("Loss")
plt.legend()

"""精度(准确率)绘制"""
train_acc=history_dict["acc"]
val_acc=history_dict["val_acc"]

plt.figure(2)
plt.plot(epochs,train_acc,label="Training Acc")
plt.plot(epochs,val_acc,label="Val Acc")
plt.title("Training and Val Acc")
plt.xlabel("Epoch")
plt.ylabel("Acc")
plt.legend()

plt.show()

图片数据存放方式:
在这里插入图片描述

训练结果:

在这里插入图片描述
观察上图结果,很明显模型训练过程中出现了过拟合,这是因为训练数据太少的原因,本次实验中训练样本仅仅为2000个,可以尝试采用数据增强(data agumentation)的方式解决过拟合问题

"""model.py中,由于训练样本数目过少,导致在训练过程中出现了过拟合现象,下面尝试使用数据增强方式解决过拟合问题
数据增强:
    从现有的训练样本中生成更多的训练数据
    其方法是利用多种能够生成可信图像的随机变换来增加样本
    其目标是模型在训练时不会两次查看完全相同的图像,让模型能够观察到数据更多的内容,从而具有更好的泛化能力"""

"""keras中的数据增强:
使用ImageDataGenerator自动进行数据增强"""

from tensorflow.keras.preprocessing import image
import os
import matplotlib.pyplot as plt

datagen=image.ImageDataGenerator(
    rotation_range=40 #图像随机旋转的角度范围,取值可以为0~180
    ,width_shift_range=0.2 #图像在水平方向上平移的范围,其值代表平移的距离与图像尺寸的比例
    ,height_shift_range=0.2 ##图像在垂直方向上平移的范围,其值代表平移的距离与图像尺寸的比例
    ,shear_range=0.2 #随机错切变换的角度
    ,zoom_range=0.2 #图像随机缩放的范围
    ,horizontal_flip=True #随机将一半图像进行水平翻转
    ,fill_mode='nearest' #用于填充新像素的方法,新像素由平移或旋转产生
)

"""观察进行图像增强后的数据
随机选择一张图片,这种图像增强的机制是无限的,可以生成多种图像"""
#对应文件夹
new_data_dir="cat_and_dog_small" #存放小数据集路径
#构建小数据集中的训练,验证,测试数据文件夹
train_data_dir=os.path.join(new_data_dir,"train")
val_data_dir=os.path.join(new_data_dir,'val')
test_data_dir=os.path.join(new_data_dir,"test")

#猫的训练数据存储
train_cats_dir=os.path.join(train_data_dir,"cats")
val_cats_dir=os.path.join(val_data_dir,"cats")
test_cats_dir=os.path.join(test_data_dir,"cats")

#狗的训练数据存储
train_dogs_dir=os.path.join(train_data_dir,"dogs")
val_dogs_dir=os.path.join(val_data_dir,'dogs')
test_dogs_dir=os.path.join(test_data_dir,"dogs")

fnames=[os.path.join(train_cats_dir,file) for file in os.listdir(train_cats_dir)]
img_path=fnames[3]  #随机挑选一张图片
img=image.load_img(img_path,target_size=(150,150))
img=image.img_to_array(img) #转换为numpy数组
img=img.reshape((1,)+img.shape)
i=0
for x in datagen.flow(img,batch_size=1):  #每次数据增强生成1张图片,且无休止的迭代,所以后面要加中止条件
    plt.figure(i)
    plt.imshow(image.array_to_img(x[0]))
    i+=1
    if i%4==0:
        break
plt.show()


结果:
在这里插入图片描述

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值