python算法专项(七)——Tensorflow三层网络(进阶),训练手写字数据集、模型保存、tensorboard可视化

基于算法专项六,的tensorflow原理,用三层网络结构进行训练手写字数据集

目录

1-手写数字数据集

手写数字数据集是一个公开的数据集,可以网上下载,也可以通过tensorflow包进行下载,下面我也提供了下载方式

1.1数据集下载

点击链接进行下载(粉丝免费下载)
下载后解压到一个目录下,我的是解压在“E:/03_study/FangTeacher/PythonCode/2021.2.28/MNIST_data”路径下,如下图:
python算法专项(七)——Tensorflow三层网络(进阶),训练手写字数据集、模型保存、tensorboard可视化

1.2数据集读取

使用下面tensorflow的方法进行读取

from tensorflow.examples.tutorials.mnist.input_data import read_data_sets
dss = read_data_sets("E:/03_study/FangTeacher/PythonCode/2021.2.28/MNIST_data")#传入数据集解压目录
print(dss.train.num_examples)#返回集合大小,训练集
print(dss.validation.num_examples)#验证集
print(dss.test.num_examples)#测试集数据
imgs,labels = dss.train.next_batch(100)#imgs:[100,784],labels:[100]取出了100张图片,每个图片大小是784(28*28)个像素的数组;有100个标签,标签是0~9之间的一个数,取出是随机取的
print(labels)#输出标签,标签是0~9之间的一个数;同时获取了100个就依次装在列表里

1.3进行各种样式的显示测试

按照上面代码来看,因为通过next_batch(100)方法读取到的图片格式是[100,784]的形状,我们如果只显示其中某一张可以对他按照imgs[i]来取,但是取到的只是784长度的一维数组,所以需要用numpy来进行变换成二维图像,然后才能显示

1.3.1显示单张样本

#利用numpy变化和opencv进行图片数据显示

import numpy as np
import cv2
dss = read_data_sets("E:/03_study/FangTeacher/PythonCode/2021.2.28/MNIST_data")#传入数据集解压目录
imgs,labels = dss.train.next_batch(100)#imgs:[100,784],labels:[100]取出了100张图片,每个图片大小是784(28*28)
img = np.reshape(imgs[0],[28,28])
cv2.imshow("Src_Img",img)
cv2.waitKey(0)

成功显示,如下图
python算法专项(七)——Tensorflow三层网络(进阶),训练手写字数据集、模型保存、tensorboard可视化

1.3.1显示多张样本在一张影像上

#利用numpy变化和opencv进行图片数据显示
#把100张样本显示在一张图片上,横着10个图,竖着10个图

import numpy as np
import cv2
dss = read_data_sets("E:/03_study/FangTeacher/PythonCode/2021.2.28/MNIST_data")#传入数据集解压目录
imgs,labels = dss.train.next_batch(100)#imgs:[100,784],labels:[100]取出了100张图片,每个图片大小是784(28*28)
cols = 10
imgs = np.reshape(imgs,[-1,cols,28,28])#1-改编形状
imgs = np.transpose(imgs,[0,2,1,3])#2-进行轴变换,使得像素在正确位置上
imgs = np.reshape(imgs,[-1,28*cols])#每行高度28个像素,最后依次resize

cv2.imshow("Src_Imgs",imgs)
cv2.waitKey(0)

python算法专项(七)——Tensorflow三层网络(进阶),训练手写字数据集、模型保存、tensorboard可视化

1.3.1显示多张样本在一张影像上并且在每张影像外面加白框

#利用numpy变化和opencv进行图片数据显示
#把100张样本显示在一张图片上,横着10个图,竖着10个图

import numpy as np
import cv2
dss = read_data_sets("E:/03_study/FangTeacher/PythonCode/2021.2.28/MNIST_data")#传入数据集解压目录
imgs,labels = dss.train.next_batch(100)#imgs:[100,784],labels:[100]取出了100张图片,每个图片大小是784(28*28)
cols = 10
imgs = np.reshape(imgs,[-1,cols,28,28])#1-改编形状

#下面几行是白框效果核心代码
imgs[:,:,27,:]=1.0#在每行下面增加一条白线,就是在行的纬度第27行都设置为1即可
imgs[:,:,0,:]=1.0#在每行下面增加一条白线,就是在行的纬度第0行都设置为1即可
imgs[:,:,:,0] = 1.0#竖直方向设置白线
imgs[:,:,:,27] = 1.0

imgs = np.transpose(imgs,[0,2,1,3])#2-进行轴变换,使得像素在正确位置上
imgs = np.reshape(imgs,[-1,28*cols])#每行高度28个像素,最后依次resize

cv2.imshow("Src_Imgs",imgs)
cv2.waitKey(0)

显示效果:
python算法专项(七)——Tensorflow三层网络(进阶),训练手写字数据集、模型保存、tensorboard可视化

2-用tensorflow框架搭建三层网络,训练手写字数据集

2.1技巧1,用全连接方法代替专项六中的矩阵相乘并加上偏置项操作

专项六中的全连接代码
python算法专项(七)——Tensorflow三层网络(进阶),训练手写字数据集、模型保存、tensorboard可视化
上图红框中的矩阵相乘,和相加操作用tensorflow中的层全连接一行代码搞定

t = tf.layers.dense(x,Mid_Num,activation=tf.nn.relu)#全连接层,包含了矩阵相乘,相加,和激活,最后的形状[-1,Mid_Num]

2.2tensorflow补充知识

1、tf.one_hot()使用

功能:将输入的列表变成向量形式的独热编码
输入:第一个参数是输入要转换的数据,第二个参数是编码长度。编码长度应该要大于等于输入数据长度,否则会表达不全。
输出:dure向量形式的独热编码
程序运行样例:

编码长度过长,如下图代码测试,感觉还是可以的,每个数据都具有唯一的编码
python算法专项(七)——Tensorflow三层网络(进阶),训练手写字数据集、模型保存、tensorboard可视化

编码长度设置过短,如下图代码测试,感觉不行,有些编码重复了
python算法专项(七)——Tensorflow三层网络(进阶),训练手写字数据集、模型保存、tensorboard可视化

2、tf.nn.softmax()使用

功能:将float类型的数据转换为概率。
输入:float类型的数组数据
输出:0~1之间的浮点型数据,每个数据占总样本的概率。(个人理解应该是将输入的数都归一化到0~1之间,而这个值可以作为概率使用,后面公式可以说明这点)

转换公式:
若输入数据为[a1,a2,a3,a4]
1、分别对每个元素求解以e为底的数,[e^a1,e^a2,e^a3,e^a4](目的是将列表中所有数都转换为正数)
2、求出上述四个数的和   All_Sum = e^a1+e^a2+e^a3+e^a4
3、用第一步列表中的每个元素除以All_Sum的值就是输出概率。

为验证上述公式的正确性,举个例子:
题目:输入数据为[-1.0,2.0,-2.0,0]四个数据

公式代码测试

# 输入数据为[-1.0,2.0,-2.0,0]四个数据
import math
a = [-1.0,2.0,-2.0,0]
a_e = [(math.e**i) for i in a ]
print("e^a list :",a_e)
All_Sum = sum(a_e)
P = [(i/All_Sum) for i in a_e]
print("最后概率列表:",P)

python算法专项(七)——Tensorflow三层网络(进阶),训练手写字数据集、模型保存、tensorboard可视化

用tf.nn.softmax()程序运行样例:
python算法专项(七)——Tensorflow三层网络(进阶),训练手写字数据集、模型保存、tensorboard可视化
通过上面两个测试代码可以发现,softmax函数输出的结果和公式方法验证的结果一致,如果进行排序会发现输入的数据越小,则处理后的结果也越小,如最小的是-2对应的是0.0152,也是这一串数字中最小的,所以我认为这个公式也是归一化的一种处理形式,只不过结果可以用来当概率进行使用。

3、tf.argmax()

功能:返回列表中最大值的位置标签
输入:numpy数组列表
输出:一个标量值

程序运行样例:

测试程序1:
python算法专项(七)——Tensorflow三层网络(进阶),训练手写字数据集、模型保存、tensorboard可视化
测试程序2:
python算法专项(七)——Tensorflow三层网络(进阶),训练手写字数据集、模型保存、tensorboard可视化
程序1中最大值为2,它所在位置为1,所以返回是1
程序2中最大值为7,它所在位置为7,所以返回是7

4、tf.square()

功能:对数组中每个元素进行平方
输入:numpy数组数据
输出:平方后的数组
例如:输入[1,2,3,4,5] 输出则是[1^2,2^2,3^2,4^2,5^2] ==> [1,4,9,16,25]

程序运行样例:
python算法专项(七)——Tensorflow三层网络(进阶),训练手写字数据集、模型保存、tensorboard可视化

5、tf.reduce_mean()

功能:对列表中元素求平均值
输入:numpy列表元素
输出:所有元素的平均值,一个标量值
公式:
a = [1,2,3,4,5]
sum_all = sum(a)
reduce_mean = sum_all/len(a)

例如1:
输入列表[1,2,3,4,5]
sum_all = 15
reduce_mean = 15/5 = 3
例2:
输入列表[11,14,15,20,31]
sum_all = 11+14+15+20+31 = 91
len(a) = 5
reduce_mean = 91/5 = 18.2(由于输入的是整型,输出的就是18,如下验证代码)

程序运行验证代码
例1:
python算法专项(七)——Tensorflow三层网络(进阶),训练手写字数据集、模型保存、tensorboard可视化

例2:输入的是整型数据,所以结果输出平均值的是浮点类型
python算法专项(七)——Tensorflow三层网络(进阶),训练手写字数据集、模型保存、tensorboard可视化
例3:输入的是浮点数,所以结果输出平均值的是浮点类型
python算法专项(七)——Tensorflow三层网络(进阶),训练手写字数据集、模型保存、tensorboard可视化

3-用tensorflow框架搭建三层神经网络来训练、预测手写字数据集

from tensorflow.examples.tutorials.mnist.input_data import read_data_sets
import tensorflow as tf
import os


class Tesnsors():#搭建网络模型
    def __init__(self,mid_units = 2000):
        self.imgs = tf.placeholder(tf.float32,[None,28*28],"imgs")
        self.lable = tf.placeholder(tf.int32,[None],"lable")
        self.lr = tf.placeholder(tf.float32,[],"lr")

        t = tf.layers.dense(self.imgs,mid_units,activation=tf.nn.relu)
        t = tf.layers.dense(t,10)

        self.predict = tf.argmax(t,axis=1,output_type=tf.int32)
        p = tf.nn.softmax(t)#默认是第0纬度
        lables = tf.one_hot(self.lable,10)
        self.loss = tf.reduce_mean(tf.square(p-lables))
        self.output = tf.sqrt(self.loss)#对loss开方
        # opt = tf.train.AdamOptimizer(self.lr)
        opt = tf.train.GradientDescentOptimizer(self.lr)

        self.train_opt = opt.minimize(self.loss)

        temp = tf.equal(self.predict,self.lable,"zhibiao")
        temp = tf.cast(temp,tf.float32)#数据转换
        self.predicsion = tf.reduce_mean(temp)#求平均值,作为精度
        tf.summary.scalar("loss",self.output)
        tf.summary.scalar("pression",self.predicsion)
        self.summary_op = tf.summary.merge_all()

class Modle:#定义模型类,包含训练、预测、可视化
    def __init__(self,session,batch_size = 200,epoch = 200,lr = 0.001):
        self.dss = read_data_sets("E:/03_study/FangTeacher/PythonCode/2021.2.28/MNIST_data")#读取数据
        self.tensor = Tesnsors()
        self.batch_size = batch_size
        self.lr = lr
        self.epoch = epoch
        self.session = session
        self.logdir = "./logs/p31/"
        # self.savePath = make_dirs("./Model/P31_Mnist/p31")
        self.savePath = "./Model/P31_Mnist/p31"
        self.saver = tf.train.Saver()
        try:
            self.saver.restore(self.session,save_path=self.savePath)
            print("restore success %s modle"%self.savePath)
        except:
            self.session.run(tf.global_variables_initializer())
            print("restore fail %s modle"%self.savePath)

    def train(self):
        batchs = self.dss.train.num_examples//self.batch_size
        ts = self.tensor
        loss = 0
        fw = tf.summary.FileWriter(self.logdir,graph=tf.get_default_graph())
        global_step = 0
        with fw:
            print("Start train...")
            for epoch in range(self.epoch):
                for _ in range(batchs):
                    img,lable = self.dss.train.next_batch(self.batch_size)
                    _ ,loss,summary = self.session.run((ts.train_opt,ts.loss,ts.summary_op),{ts.imgs:img,ts.lr:self.lr,ts.lable:lable})
                    fw.add_summary(summary,global_step)
                    global_step +=1


                print("epoch:%s ,loss:%s"%(epoch,loss))
                self.saver.save(self.session,self.savePath)
                print("Save the model into %s sucession"%self.savePath)
        print("Train finish!")
    def test(self):
        imgs, lable = self.dss.test.next_batch(self.batch_size)
        _,prediision = self.session.run((self.tensor.predict,self.tensor.predicsion),{self.tensor.imgs:imgs,self.tensor.lable:lable})

# def make_dirs(path_and_name:str):#如果文件夹不存在则进行新建
#     pos = path_and_name.rfind(os.sep)
#     if pos >=0:
#         path = path_and_name[:pos+1]
#         os.makedirs(path,exist_ok=True)#重复创建不报错
#         print("The path %s is made."%path)
#     return path_and_name

if __name__ == '__main__':
    with tf.Session() as session:
        modle = Modle(session)
        modle.train()
        modle.test()

4-用tensorflow模型保存方法

上面代码解析,模型保存方法:
1、设置模型保存路径,需设置模型保存文件名,例如:
self.savePath = “./Model/P31_Mnist/p31” "./Model/P31_Mnist/"为模型文件保存路径,p31为保存的模型名称
2、定义模型保存方法为成员变量 self.saver = tf.train.Server()
3、加载模型 self.saver.restor(self.session,save_path = self.savePath)#把模型加载到self.session变量中
4、保存模型 self.saver.save(self.session,self.savePath)#训练一段时间后将session进行保存,保存后会自动覆盖上一次结果

5-用tensorboard训练过程的可视化

上面代码解析,tensorboard可视化步骤:
第一步设置日志目录
tensorboard --logdir=path(path为数据所在文件夹路径) --host=127.0.0.1 --port 6006
–logdir:日志文件的位置(如果不存在,则要单独新建一个日志目录)
–host:主机名(如果给出的网站打不开,则需要设置主机名)
–port:端口,可以使用默认的,也可以使用指定的端口
设置完成后会弹出你可以访问的网站,从这个网站上进行监视你要监控的变量

第二步骤:
从代码中进行设置哪些变量要进行监控,在搭建网络的时候把loss损失和进度分别加入到summary中,最后进行汇总成summary_op,便于一次计算得出,下面只监控了两个变量(output和precision)

tf.summary.scalar(“loss”,self.output)#输出output,本质也是loss
tf.summary.scalar(“precision”,self.precision)#输出验证精度
self.summary_op = tf.summary.merge_all()#把前面两步操作合并到一步操作,可以在输出的时候计算summary_op就行了

第三步:
在训练过程中把summary_op计算出来,然后添加进去
fw = tf.summary.FileWriter(self.logdir)
global_step = 0

第四步
在tran的过程中,计算出summary_op
_,loss,summary = self.session.run([ts.train_op,ts.loss,ts.summary_op],{ts.lr:self.lr,ts.img:imgs,ts.label:labels})
fw.add_summary(summary,global_step)#把日志写进去
global_step+=1

模型监视界面:
python算法专项(七)——Tensorflow三层网络(进阶),训练手写字数据集、模型保存、tensorboard可视化

上一篇:20201324 2020-2021-2 《Python程序设计》实验四报告


下一篇:程序员高频英语汇总1Programmer high frequency English summary(一看就懂) 不断更新版