人工智能实践:Tensorflow笔记
课程源码下载链接:https://pan.baidu.com/s/19XC28Hz_TwnSQeuVifg1UQ 提取码:mocm
网上搜索
我之前安装了pytorch所以已经安装了cuda11.1以及cudnn8.8.1,
但是安装完tensorflow-gpu2.4.0
(我的cudnn 版本位置 D:\CUDNN\cuda\include\cudnn_version.h
(我的cuda版本位置 C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.1
(tensorflow-gpu版本 激活anaconda环境输入
准备数据:采集大量的“特征/标签”数据
搭建网络:搭建神经网络结构(前向传播)
优化参数:训练数据网络获取最佳参数(反向传播)
应用网络:将网络封装为模型,输入未曾见过的数据(测试集),输出预测结果(前向传播)
准备数据,采集(花瓣长宽,花萼长宽,对应的类别)数据对构成数据集
搭建网络,输入层 1 ∗ 4 1*4 1∗4的矩阵,输出为 1 ∗ 3 1*3 1∗3的矩阵,由图可见,参数为 4 ∗ 3 4*3 4∗3的矩阵以及一个偏置项,就是一个全连接网络
优化参数:
通过将 1 ∗ 4 1*4 1∗4的数据喂入网络,通过计算会得到一个结果 y y y,这就是前向传播, y y y应该是一个 1 ∗ 3 1*3 1∗3的矩阵,这里的三个数就代表这三种分类的概率了,当然现在的结果都是蒙的,因为参数都是随机出来的嘛。
因此引出损失函数(loss function)用来表示预测值 y y y与标准答案 y y y_之间的差距。可以定量地判断参数的好坏,当损失函数最小时参数 达到最优值。
现在,就需要找到一组参数使得损失函数最小啦。梯度以及梯度下降法介绍。简单来说,梯度就是函数对各个参数求偏导后的向量,其下降方向是函数减少方向。而梯度下降法就是沿着损失函数梯度下降的方向寻找其最小值,从而得到最优参数的方法。那么每次沿着梯度下降的方向走多远呢,可以通过学习率来控制( l e a r n i n g r a t e , l r learning rate, lr learningrate,lr):当学习率过小,收敛满,当学习率过大可能会在最小值附近震荡。
反向传播就是从后向前,逐层求出偏导,并更新参数的过程。
w t + 1 = w t − l r ∗ ∂ l o s s / ∂ w t w_{t+1}=w_t-lr*\partial loss/\partial w_t wt+1=wt−lr∗∂loss/∂wt
例如: l o s s = ( w + 1 ) 2 loss = (w+1)^2 loss=(w+1)2 那么导数就是 2 w + 2 2w+2 2w+2
参数 w w w初始化为5,学习率为0.2,则
1次 参数 w w w:5 5-0.2*(2+5+2)=2.6
2次 参数 w w w:2.6 2.6-0.2*(2*2.6+2)=1.16
…
好,理论存在,开始实践,打开源码中的/class1/p13试试看。
应用网络,…
tf.constant(张量内容,dtype = 数据类型(可选)或者tf.zeros(维度) #创建张量:
tf.convert_to_tensor() # numpy与tensor转换得到
tf.cast(张量名,dtype=数据类型) #强制tensor转化为该数据类型
tf.reduce_min(张量名) #计算张量维度上元素的最小值
tf.reduce_max(张量名) #计算张量维度上元素的最大值
tf.reduce_mean(张量名,axis=操作轴) #计算张量沿着指定维度的平均值
tf.variable(初始值)#将变量标记为“可训练”,变量会在反向传播中会被记录梯度信息
w = tf.variable(tf.random.normal([2,2],mean = 0, stddev = 1))
tf.subtract(张量1,张量2) #实现两个张量的对应元素相减
tf.multiply(张量1,张量2) #实现两个张量的对应元素相乘
tf.add(张量1,张量2) #实现两个张量的对应元素相加
tf.divide(张量1,张量2) #实现两个张量的对应元素相除
tf.square(张量名) #计算某个张量的平方
tf.pow(张量名,n次方数) #计算某个张量的n次方
tf.sqrt(张量名) #计算某个张量的开方
tf.matmul(矩阵1,矩阵2) #矩阵乘
# with 结构记录计算过程,gradient求出张量的梯度
with tf.GradientTape() as tape:
若干个计算过程
grad = tape.gradient(函数,对谁求导)
# 将待转换数据,转换为one-hot形式的数据输出(独热码:就是有多少状态有多少比特,且只有一个比特为1,其余都为0)
tf.one_hot(待转换数据,depth=几分类)
tf.nn.softmax(x) #n分类的结果符合概率分布,也就是全部大于等于0并且和为1
tf.where(条件语句,真返回A,假返回B)
np.random.RandomState.rand(维度) #返回一个[0,1]之间的随机数,若维度为空,则返回标量
np.vstack(数组1,数组2) #将两个数组按垂直方向叠加
#下面三个一起用生成网格坐标线
np.mgrid[起始值:结束值:步长 , 起始值:结束值:步长 , ...] #返回若干组维度相同的等差数组,
x.ravel() #把多维数组变成一维数组,相当于把点前的数组拉直
np.c_[数组1 , 数组2 , ...] #使返回的间隔数值点配对
实际应用中,可以先用较大的学习率,快速找到较优值,然后逐步减小学习率,使模型找到最优解
例如指数衰减学习率:指数衰减学习率=初始学习率*学习率衰减率(当前轮次/几轮衰减一次)
[激活函数的作用](https://www.zhihu.com/question/22334626)
激活函数就是用来给模型引入非线性因素,解决线性模型所不能解决的问题
[常见的激活函数](https://zhuanlan.zhihu.com/p/73214810)
Sigmoid函数,tanh ,ReLU,LeakyReLU,PReLU
Sigmoid这种一看就是非线性,但是RELU为什么是非线性呢?我是这么理解的,ReLU本身是分段线性函数,但是可以通过ReLu的线性组合去逼近一个非线性函数。
激活函数总结
视频中的老师对于初学者的建议:
首选relu激活函数;
学习率设置较小值
对输入特征进行标准化,即让输入特征满足以0为均值,1为标准差的正态分布
对网络的初始参数进行中心化,即让随机生成的参数满足以0为均值,√(2/当前层输入特征个数)为标准差的正态分布
定量表示预测值与已知答案的差距
loss_m = tf.reduce_mean(tf.square(y_-y)) #均方误差
loss_c = tf.losses.categorical_crossentropy(y_,y) #交叉熵损失函数
tf.nn.softmax_cross_entropy_with_logits(y_,y) #结合softmax的交叉熵,就是先做softmax再求交叉熵损失(和softmax后面接categorical_crossentropy结果一样)
loss = tf.reduce_sum(tf.where(tf.greater(y, y_), (y - y_)*COST, (y_ - y)*PROFIT))或者loss =1 #自定义损失函数,自己写一个,当成损失函数值做反向传播
欠拟合:模型不能有效拟合数据集,对现有数据集学习的不够彻底
过拟合:模型对当前数据拟合的太好,但对从未见过的新数据,难以做出正确的判断,模型缺乏泛化力。
解决方法
欠拟合解决方法
增加输入特征项
增加网络参数
减少正则化参数
过拟合解决方法
数据清洗
增大训练集
采用正则化
增大正则化参数
正则化缓解过拟合
就是在损失函数中引入模型复杂度指标,利用给参数加权值,弱化了训练数据的噪声。
新的损失函数loss_n= 原损失函数loss_o+(超参数R*需要正则化的参数loss(w))
loss(w)的计算方法有两种,一种L1,一种L2
# 导入所需模块
import tensorflow as tf
from matplotlib import pyplot as plt
import numpy as np
import pandas as pd
# 读入数据/标签 生成x_train y_train
df = pd.read_csv('dot.csv')
x_data = np.array(df[['x1', 'x2']])
y_data = np.array(df['y_c'])
x_train = x_data
y_train = y_data.reshape(-1, 1)
Y_c = [['red' if y else 'blue'] for y in y_train]
# 转换x的数据类型,否则后面矩阵相乘时会因数据类型问题报错
x_train = tf.cast(x_train, tf.float32)
y_train = tf.cast(y_train, tf.float32)
# from_tensor_slices函数切分传入的张量的第一个维度,生成相应的数据集,使输入特征和标签值一一对应
train_db = tf.data.Dataset.from_tensor_slices((x_train, y_train)).batch(32)
# 生成神经网络的参数,输入层为4个神经元,隐藏层为32个神经元,2层隐藏层,输出层为3个神经元
# 用tf.Variable()保证参数可训练
w1 = tf.Variable(tf.random.normal([2, 11]), dtype=tf.float32)
b1 = tf.Variable(tf.constant(0.01, shape=[11]))
w2 = tf.Variable(tf.random.normal([11, 1]), dtype=tf.float32)
b2 = tf.Variable(tf.constant(0.01, shape=[1]))
lr = 0.01 # 学习率为
epoch = 400 # 循环轮数
# 训练部分
for epoch in range(epoch):
for step, (x_train, y_train) in enumerate(train_db):
with tf.GradientTape() as tape: # 记录梯度信息
h1 = tf.matmul(x_train, w1) + b1 # 记录神经网络乘加运算
h1 = tf.nn.relu(h1)
y = tf.matmul(h1, w2) + b2
# 采用均方误差损失函数mse = mean(sum(y-out)^2)
loss_mse = tf.reduce_mean(tf.square(y_train - y))
# 添加l2正则化####################################################################################
loss_regularization = []
# tf.nn.l2_loss(w)=sum(w ** 2) / 2
loss_regularization.append(tf.nn.l2_loss(w1))
loss_regularization.append(tf.nn.l2_loss(w2))
# 求和
# 例:x=tf.constant(([1,1,1],[1,1,1]))
# tf.reduce_sum(x)
# >>>6
# loss_regularization = tf.reduce_sum(tf.stack(loss_regularization))
loss_regularization = tf.reduce_sum(loss_regularization)
loss = loss_mse + 0.03 * loss_regularization #REGULARIZER = 0.03
# 计算loss对各个参数的梯度
variables = [w1, b1, w2, b2]
grads = tape.gradient(loss, variables)
# 实现梯度更新
# w1 = w1 - lr * w1_grad
w1.assign_sub(lr * grads[0])
b1.assign_sub(lr * grads[1])
w2.assign_sub(lr * grads[2])
b2.assign_sub(lr * grads[3])
# 每200个epoch,打印loss信息
if epoch % 20 == 0:
print('epoch:', epoch, 'loss:', float(loss))
# 预测部分
print("*******predict*******")
# xx在-3到3之间以步长为0.01,yy在-3到3之间以步长0.01,生成间隔数值点
xx, yy = np.mgrid[-3:3:.1, -3:3:.1]
# 将xx, yy拉直,并合并配对为二维张量,生成二维坐标点
grid = np.c_[xx.ravel(), yy.ravel()]
grid = tf.cast(grid, tf.float32)
# 将网格坐标点喂入神经网络,进行预测,probs为输出
probs = []
for x_predict in grid:
# 使用训练好的参数进行预测
h1 = tf.matmul([x_predict], w1) + b1
h1 = tf.nn.relu(h1)
y = tf.matmul(h1, w2) + b2 # y为预测结果
probs.append(y)
# 取第0列给x1,取第1列给x2
x1 = x_data[:, 0]
x2 = x_data[:, 1]
# probs的shape调整成xx的样子
probs = np.array(probs).reshape(xx.shape)
plt.scatter(x1, x2, color=np.squeeze(Y_c))
# 把坐标xx yy和对应的值probs放入contour<[‘kɑntʊr]>函数,给probs值为0.5的所有点上色 plt点show后 显示的是红蓝点的分界线
plt.contour(xx, yy, probs, levels=[.5])
plt.show()
# 读入红蓝点,画出分割线,包含正则化
# 不清楚的数据,建议print出来查看
首先明确几个参数
待优化参数w
损失函数loss
学习率lr
每次迭代一个batch
t表示当前batch迭代的总次数
#sgd
w1.assign_sub(lr * grads[0]) #参数w自更新
b1.assign_sub(lr * grads[1]) #参数b自更新
SGDM:在SGD基础上增加了一阶动量
m_w,m_b = 0,0
beta = 0.9
# sgd-momentun
m_w = beta * m_w + (1 - beta) * grads[0]
m_b = beta * m_b + (1 - beta) * grads[1]
w1.assign_sub(lr * m_w)
b1.assign_sub(lr * m_b)
Adagrad:在SGD基础上增加了二阶动量
v_w,v_b = 0,0
# adagrad
v_w += tf.square(grads[0])
v_b += tf.square(grads[1])
w1.assign_sub(lr * grads[0] / tf.sqrt(v_w))
b1.assign_sub(lr * grads[1] / tf.sqrt(v_b))
RMSProp:在SGD基础上增加了二阶动量
v_w,v_b = 0,0
beta = 0.9
# rmsprop
v_w = beta * v_w + (1 - beta) * tf.square(grads[0])
v_b = beta * v_b + (1 - beta) * tf.square(grads[1])
w1.assign_sub(lr * grads[0] / tf.sqrt(v_w))
b1.assign_sub(lr * grads[1] / tf.sqrt(v_b))
Adam:同时结合SGDM一阶动量和RMSProp二阶动量,还有修正公式
m_w,m_b = 0,0
v_w,v_b = 0,0
beta1,beta2 = 0.9,0.999
delta_w,delta_b = 0,0
global_step = 0
# adam
m_w = beta1 * m_w + (1 - beta1) * grads[0]
m_b = beta1 * m_b + (1 - beta1) * grads[1]
v_w = beta2 * v_w + (1 - beta2) * tf.square(grads[0])
v_b = beta2 * v_b + (1 - beta2) * tf.square(grads[1])
m_w_correction = m_w / (1 - tf.pow(beta1,int(global_step)))
m_b_correction = m_b / (1 - tf.pow(beta1,int(global_step)))
v_w_correction = v_w / (1 - tf.pow(beta2,int(global_step)))
v_b_correction = v_b / (1 - tf.pow(beta2,int(global_step)))
w1.assign_sub(lr * m_w_correction / tf.sqrt(v_w_correction))
b1.assign_sub(lr * m_b_correction / tf.sqrt(v_b_correction))
import #导入包
train , test #自制数据集,数据增强
model = tf.leras.models.Sequential/class MyModel(Model)
model.compile #配置训练方法
model.fit #执行训练过程,断点续训
model.summary #参数提取
#共六步
网络结构搭建
model = tf.keras.models.Sequential([网络结构]) #添加网络结构
tf.keras.layers.Flatten() #拉直层
tf.keras.layers.Dense(神经元个数,activation="激活函数",kernel_regularizer=哪种正则化) #全连接层
# activation(字符串给出)可选:relu、softmax、sigmoid、tanh
# kernel_regularizer可选:tf.keras.regularizers.l1()、tf.keras.regularizers.l2()
tf.keras.layers.Conv2D(filters=卷积核个数,kernel_size=卷积核尺寸,strides=卷积步长,padding="valid"or"same") #卷积层
tf.keras.layers.LSTM() #LSTM层
优化器参数选择
model.compile(optimizer=优化器,loss=损失函数,metrics=["准确率"])
#optimizer可选项
'sgd' or tf.keras.optimizers.SGD(lr=学习率,momentum=动量参数)
'adagrad' or tf.keras.optimizers.Adagrad(lr=学习率)
'adadelta' or tf.keras.optimizers.Adadelta(lr=学习率)
'adam' or tf.keras.optimizers.Adam(lr=学习率,beta_1=O.9,beta_2=0.999)
# loss可选项
'mse' or tf.keras.losses.MeanSquaredError()
'sparse_categorical_crossentropy' or tf.keras,losses.SparseCategoricalCrossentropy(from_logits=False)
# Metrics可选项:
'accuracy':y_和y都是数值,如y_=[1] y=[1]
'categorical_accuracy':y_和y都是独热码(概率分布),如y_=[0,1,0] y=[0.256,0.695,0.048]
'sparse_categorical_accuracy':y-是数值,y是独热码(概率分布),如y_=[1] y=[0.256,0.695,0.048]
model.fit
model.fit(训练集的输入特征,训练集的标签,batch_size= ,epoch= ,validation_data=(测试集的输入特征,测试集的标签),validation_split=从训练集划分多少比例给测试集,validation_freq=多少次epoch测试一次)
model.summary
#写上这个就可以打印网络了
用Sequential搭建鸢尾花分类网络
import tensorflow as tf
from sklearn import datasets
import numpy as np
x_train = datasets.load_iris().data
y_train = datasets.load_iris().target
np.random.seed(116)
np.random.shuffle(x_train)
np.random.seed(116)
np.random.shuffle(y_train)
tf.random.set_seed(116)
model = tf.keras.models.Sequential([
tf.keras.layers.Dense(3, activation='softmax', kernel_regularizer=tf.keras.regularizers.l2())
])
model.compile(optimizer=tf.keras.optimizers.SGD(lr=0.1),
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics=['sparse_categorical_accuracy'])
model.fit(x_train, y_train, batch_size=32, epochs=500, validation_split=0.2, validation_freq=20)
model.summary()
这样的搭建方式是上层输出就是下层输入,但是无法写出一些带有跳连的非顺序网络结构,这是可以用类class搭建
class MyModel(Model):
def__init__(self):
super(MyModel,self).__init__()
#定义网络结构块
#准备积木
def call(self,x):
#调用网络结构块,实现前向传播
#调用搭建积木
return y
model = MyModel()
用class代替Sequrntial搭建网络结构
import tensorflow as tf
from tensorflow.keras.layers import Dense
from tensorflow.keras import Model
from sklearn import datasets
import numpy as np
x_train = datasets.load_iris().data
y_train = datasets.load_iris().target
np.random.seed(116)
np.random.shuffle(x_train)
np.random.seed(116)
np.random.shuffle(y_train)
tf.random.set_seed(116)
class IrisModel(Model):
def __init__(self):
super(IrisModel, self).__init__()
self.d1 = Dense(3, activation='softmax', kernel_regularizer=tf.keras.regularizers.l2())
def call(self, x):
y = self.d1(x)
return y
model = IrisModel()
model.compile(optimizer=tf.keras.optimizers.SGD(lr=0.1),
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics=['sparse_categorical_accuracy'])
model.fit(x_train, y_train, batch_size=32, epochs=500, validation_split=0.2, validation_freq=20)
model.summary()
使用本地数据集:
def generateds(path):
#处理一下,读取数据。
return 特征x,标签y
import tensorflow as tf
from PIL import Image
import numpy as np
import os
# 添加训练集图片和标签文件路径
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'
# generateds()函数,用于制作数据集
def generateds(path, txt):
f = open(txt, 'r') # 以只读形式打开txt文件
contents = f.readlines() # 读取文件中所有行
f.close() # 关闭txt文件
x, y_ = [], [] # 建立空列表
for content in contents: # 逐行取出
value = content.split() # 以空格分开,图片路径为value[0] , 标签为value[1] , 存入列表
img_path = path + value[0] # 拼出图片路径和文件名
img = Image.open(img_path) # 读入图片
img = np.array(img.convert('L')) # 图片变为8位宽灰度值的np.array格式
img = img / 255. # 数据归一化 (实现预处理)
x.append(img) # 归一化后的数据,贴到列表x
y_.append(value[1]) # 标签贴到列表y_
print('loading : ' + content) # 打印状态提示
x = np.array(x) # 变为np.array格式
y_ = np.array(y_) # 变为np.array格式
y_ = y_.astype(np.int64) # 变为64位整型
return x, y_ # 返回输入特征x,返回标签y_
# 判断训练集特征x_train,训练集标签y_train,测试集输入特征x_test,测试集标签y_test是不是已经存在
# 如果存在,直接读取
# 如果不存在,调用generateds()函数制作数据集
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):
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)
# reshape()是数组array中的方法,作用是将数据重新组织,这里可以理解为将数据组织成len(x_train_save), 28, 28的三维数组
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:
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)
# 下面的和之前六步法的完全一样
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics=['sparse_categorical_accuracy'])
model.fit(x_train, y_train, batch_size=32, epochs=5, validation_data=(x_test, y_test), validation_freq=1)
model.summary()
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])
image_gen_train.fit(x_train)
测试代码:
import tensorflow as tf
# 增加了ImageDataGenerator模块
from tensorflow.keras.preprocessing.image import ImageDataGenerator
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
# 给数据增加一个维度,从(60000, 28, 28)reshape为(60000, 28, 28, 1)
# 因为后面image_gen_train.fit需要输入四维数据,因此需要reshape,将数据变为60000张28行28列单通道数据,这个单通道是灰度值
x_train = x_train.reshape(x_train.shape[0], 28, 28, 1)
# 把x_train送入数据增强操作
image_gen_train = 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%
)
# fit执行增强操作
image_gen_train.fit(x_train)
# 搭建网络结构
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
# 配置训练方法
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics=['sparse_categorical_accuracy'])
# 执行训练过程
# fit这里以flow形式按照batch打包后执行训练过程
model.fit(image_gen_train.flow(x_train, y_train, batch_size=32), epochs=5, validation_data=(x_test, y_test),
validation_freq=1)
model.summary()
#读取模型
checkpoint_save_path = "./checkpoint/mnist.ckpt"
if os.path.exists(checkpoint_save_path + '.index'):
print('-------------load the model-----------------')
# 如果有索引表,就说明保存过模型,则可以调用load_weights读取模型参数
model.load_weights(checkpoint_save_path)
#保存模型
tf.keras.callbacks.ModelCheckpoint(
filepath=路径文件名, save_weights_only=True/False, save_best_only=True/False)
# 执行训练过程时,加入callbacks选项,记录到history中
history = model.fit(callbacks=[cp_callback])
# 使用举例
import tensorflow as tf
# 为了判断保存的模型参数是否存在,引入os模块
import os
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics=['sparse_categorical_accuracy'])
# 先定义出存放模型的路径和文件名,命名为ckpt文件
# 生成ckpt文件时,会同步生成索引表,所以通过判断是否已经有索引表,就知道是不是已经保存过模型参数
checkpoint_save_path = "./checkpoint/mnist.ckpt"
if os.path.exists(checkpoint_save_path + '.index'):
print('-------------load the model-----------------')
# 如果有索引表,就说明保存过模型,则可以调用load_weights读取模型参数
model.load_weights(checkpoint_save_path)
# 加入回调函数,返回给cp_callback
# 三个参数分别为:文件存储路径/是否只保留模型参数/是否只保留最优结果
cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_save_path,
save_weights_only=True,
save_best_only=True)
# 执行训练过程时,加入callbacks选项,记录到history中
history = model.fit(x_train, y_train, batch_size=32, epochs=5, validation_data=(x_test, y_test), validation_freq=1,
callbacks=[cp_callback])
model.summary()
# 显示网络结构和结果等
model.summary()
# 打印所有可训练参数,并存入weights文件
print(model.trainable_variables)
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()
import tensorflow as tf
import os
import numpy as np
from matplotlib import pyplot as plt
np.set_printoptions(threshold=np.inf)
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
metrics=['sparse_categorical_accuracy'])
checkpoint_save_path = "./checkpoint/mnist.ckpt"
if os.path.exists(checkpoint_save_path + '.index'):
print('-------------load the model-----------------')
model.load_weights(checkpoint_save_path)
cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_save_path,
save_weights_only=True,
save_best_only=True)
history = model.fit(x_train, y_train, batch_size=32, epochs=5, validation_data=(x_test, y_test), validation_freq=1,
callbacks=[cp_callback])
model.summary()
print(model.trainable_variables)
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()
############################################### show ###############################################
# 显示训练集和验证集的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']
# subplot将图像分为1行2列,这段代码画第1列
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()