[tensorflow2笔记七] 网络八股扩展
1.自制数据集,解决本领域应用
(1)数据集结构
两个包含图片的文件夹:
mnist_train_jpg_60000:60000张图片
mnist_test_jpg_10000:10000张图片
0_5.jpg,1_7.jpg等图片都是黑底白字灰度图,28x28个像素点,每个像素点都是0-255之间的整数,纯黑色0,纯白色255。
两个标签文本:
mnist_train_jpg_60000.txt
mnist_test_jpg_10000.txt
文本中有两列:图片名 标签
0_5.jpg 5
2_9.jpg 9
(2)构造函数,替换load_data(),给x_train,y_train,x_test,y_test赋值
def generateds(图片路径,标签文件)
将图片灰度值数据拼接到图片列表,把标签数据拼接到标签列表,顺序一致就可以。
(3)制作并使用数据集的demo
# 1.导入一些模块
import tensorflow as tf
from PIL import Image # 用于打开一张图片
import numpy as np # 用于数据格式转换
import os # 路径
# 2.路径和存储文件
train_path = './mnist_image_label/mnist_train_jpg_60000/' # 训练集图片路径
train_txt = './mnist_image_label/mnist_train_jpg_60000.txt' # 训练集标签文件
x_train_savepath = './mnist_image_label/mnist_x_train.npy' # 训练集输入特征存储文件
y_train_savepath = './mnist_image_label/mnist_y_train.npy' # 训练集标签存储文件
test_path = './mnist_image_label/mnist_test_jpg_10000/' # 测试集图片路径
test_txt = './mnist_image_label/mnist_test_jpg_10000.txt' # 测试集标签文件
x_test_savepath = './mnist_image_label/mnist_x_test.npy' # 测试集输入特征存储文件
y_test_savepath = './mnist_image_label/mnist_y_test.npy' # 测试集标签存储文件
# 3.制作数据集的函数
def generateds(path, txt): # 图片路径,标签文件
f = open(txt, 'r') # 以只读的形式打开txt
contents = f.readlines() # 读取文件中所有的行,每行为一个单位
f.close()
x, y_ = [], []
for content in contents: # 逐行读出
value = content.split() # 以空格分开
img_path = path + value[0]
img = Image.open(img_path)
img = np.array(img.convert('L')) # 图片变为8位宽度的灰度值
img = img / 255. # 数据归一化
x.append(img)
y_.append(value[1])
print('load:' + content)
x = np.array(x)
y_ = np.array(y_)
y_ = y_.astype(np.int64)
return x, y_
# 4.加载数据
if os.path.exists(x_train_savepath) and os.path.exists(y_train_savepath) and os.path.exists(
x_test_savepath) and os.path.exists(y_test_savepath): # 判断x_train,y_train,x_test,y_test是否存在
print("----------------Load Datasets-------------")
x_train_save = np.load(x_train_savepath)
y_train = np.load(y_train_savepath)
x_test_save = np.load(x_test_savepath)
y_test = np.load(y_test_savepath)
x_train = np.reshape(x_train_save, (len(x_train_save), 28, 28))
x_test = np.reshape(x_test_save, (len(x_test_save), 28, 28))
else: # 不存在,则调用generateds()函数制作数据集
print('----------------Generate Datasets--------------')
x_train, y_train = generateds(train_path, train_txt)
x_test, y_test = generateds(test_path, test_txt)
# 保存制作好的数据集,下次训练可以直接使用
print('----------------Save Datasets------------------')
x_train_save = np.reshape(x_train, (len(x_train), -1))
x_test_save = np.reshape(x_test, (len(x_test), -1))
np.save(x_train_savepath, x_train_save)
np.save(y_train_savepath, y_train)
np.save(x_test_savepath, x_test_save)
np.save(y_test_savepath, y_test)
# 5.搭建网络
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
# 6.配置参数
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics=['sparse_categorical_accuracy'])
# 7.训练
model.fit(x_train, y_train,batch_size=32,epochs=5,validation_data=(x_test, y_test),validation_freq=1)
# 8.打印网络参数
model.summary()
2.数据增强,扩充数据集
(1)理解
对图像的增强,就是对图像的简单形变,用来应对因拍照角度不同引起的图片变形。
数据增强在小数据量上可以增加模型泛化性。
(2)函数
# 1.设置数据增强参数
image_gen_train = tf.keras.preprocessing.image.ImageDataGenerator(
rescale=所有数据乘以该数值
rotation_range=随机旋转角度数范围
width_shift_range=随机宽度偏移量
height_shift_range=随机高度偏移量
horizontal_flip=是否随机水平翻转
zoom_range=随机缩放的范围[1-n, 1+n]
)
# 2.对输入特征进行数据增强
x_train = x_train.reshape(x_train.shape[0], 28, 28 ,1) # 增加一个维度,使数据与网络结构匹配
image_gen_train.fit(x_train) # 此处的x_train要输入一个四维数据
# 3.变动model.fit
# 将x_train,y_train,batch打包,其余相同
model.fit(image_gen_train.flow(x_train,y_train,batch=32),...)
例子:
image_gen_train = tf.keras.preprocessing.image.ImageDataGenerator(
rescale=1. / 1., # 如果是图像,分母为255,可以归一化到0-1
rotation_range=45, # 随机45度旋转
width_shift_range=.15, # 宽度偏移
height_shift_range=.15, # 高度偏移
horizontal_flip=False, # 水平翻转
zoom_range=0.5 # 将图像随机缩放阈量50%
)
3.断点续训,存取模型
(1)读取模型:model.load_weights(路径文件名)
checkpoint_save_path = "./mnist.ckpt" # 定义存放模型的路径和文件名
if os.path.exists(checkpoint_save_path + '.index'): # 判断是否有索引表 因为生成ckpt文件时,会同步生成索引表
print('--------load the model---------')
model.load_weights(checkpoint_save_path)
(2)保存模型:使用回调函数
# 1.设置保存方法
cp_callback = tf.keras.callbacks.ModelCheckpoint(
filepath=路径文件名,
save_weights_only=True/False # 是否只保留模型参数
save_best_only=True/False) # 是否只保留最有结果
# 2.训练时加入callbacks选项,记录到history中
history = model.fit(...,callbacks=[cp_callback])
4.参数提取,把参数存入文本
(1)理解:将模型的参数保存在文本中。
(2)函数:model.trainable_variables可以返回模型中可训练的参数,使用print函数打印出来。
但是,直接print中间很多数据会被省略号代替,所以要设置print输出格式。
np.set_printoptions(threshold=超出多少省略显示)
例子:
# 1.设置print格式
import numpy as np
np.set_printoptions(threshold=np.inf) # np.inf表示无限大,打印所有内容
# 2.打印参数
print(model.trainable_variables)
# 3.将参数写入文本
file = open('./weights.txt', 'w')
for v in model.trainable_variables:
file.write(str(v.name) + '\n')
file.write(str(v.shape) + '\n')
file.write(str(v.numpy()) + '\n')
file.close()
5.acc/loss可视化,查看训练效果
(1)说明:
history = model.fit()。其实,在执行训练过程中,同步记录了
训练集loss(loss)、
测试集loss(val_loss)、
训练集准确率(sparse_categorical_accuracy)、
测试集准确率(val_sparse_categorical_accuracy)。
可以使用history.history[]提取出来。
(2)方法:
# 提取acc和loss
acc = history.history['sparse_categorical_accuracy']
val_acc = history.history['val_sparse_categorical_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
# 绘制acc和loss曲线
plt.subplot(1, 2, 1)
plt.plot(acc, label='Training Accuracy')
plt.plot(val_acc, label='Validation Accuracy')
plt.title('Training and Validation Accuracy')
plt.legend()
plt.subplot(1, 2, 2)
plt.plot(loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.title('Training and Validation Loss')
plt.legend()
plt.show()
6.应用程序,给图识物
(1)说明:编写一个前向传播算法,使用训练好的模型,将输入图片识别出来。
(2)函数:predict(输入特征,batch_size=整数),可以返回前向传播的计算结果。
(3)程序
# 1.复现模型(前向传播)
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128,activation='relu'),
tf.keras.layers.Dense(10,activation='softmax')
])
# 2.加载参数
model.load_weights(model_save_path)
# 3.预测结果
result = model.predict(x_predict)