tensorflow saver_Tensorflow入门教程及模型保存和恢复(一)

这篇博客介绍了TensorFlow 1.x的基础知识,包括神经网络构建、训练过程和模型保存。通过一个简单的BP神经网络拟合一元函数的例子,详细解释了网络结构、损失函数、优化器的选择以及训练步骤。最后,展示了如何使用Saver保存模型,以便后续恢复使用。
摘要由CSDN通过智能技术生成

687e06bf7255e33ddac860bf4f0d656a.png

近来看网上一些tf入门教程,都是先讲下道理,然后搭建图,然后训练,然后结束。
然后读者一般是看懂了的就看懂了,没看懂的就像看了一篇软文 训练模型的教程,训练好的模型就是要用来用的,跟着训练了一遍模型,而读者却没有得到模型
有些教程体贴一点,教你训练好自己的模型之后如何保存,然后就没有然后了,因为没有教你如何恢复

tips: 该系列教程tensorflow版本皆为1.x

当然,最先讲的还是会话(Sesssion)
Python是一门效率比较低的语言,而TensorFlow底层是使用C++实现,以保证计算效率,上层的Python、Java、甚至JavaScript等代码用来设计、定义模型和构建的Graph,而编程语言之间的通信是比较耗时的,特别是在分布式并行计算中,所以Tensorflow使用Session来管理,只有当Session.run()的时候才会传到底层进行计算

定义一个Session

sess = tf.Session()
各种导包操作我就不一一阐述了,常用包的命名缩写都是大家约定俗成的,该导哪些包大家都懂

定义图结构

为了代码的工整,也为了我前面提到的模型的恢复,我们将整个神经网络专门定义到一个Network类中
考虑到这篇文章只是个Tensorflow入门而已,就讲一个用传统BP神经网络来拟合一个一元多次函数吧先定义一个类
不专门定义到一个类中后续恢复时又要重新定义结构。

劳神费力,虽千万人,吾肯定不往矣

class Network():
    ...
    ...
    ...

既然时一元函数,那么输入和输出层都只有一个神经元,放置一个隐藏层,隐藏层那就随便来10神经元吧
所以整个网络的结构就是:1个神经元的输入层+10个神经元的隐藏层+1个神经元的输出层
懒得画图了,大家脑补下,还望见谅

一个很简单的神经网络,简单到直接写出表达式:


就是用这个去拟合一个一元函数(是不是感觉有点大材小用了)

本小节所有代码皆在此类中,注意缩进

先定义训练数据输入的占位符

    x = tf.placeholder(shape=[1,None],dtype=tf.float32)
    y = tf.placeholder(shape=[1,None],dtype=tf.float32)

x和y就是训练数据的占位符(如其函数名),而训练数据就是 y = f(x) 的数据

定义输入层权重和偏置

Tensorflow张量的定义一般有这几种

  • tf.Variable 定义变量
  • tf.constant 定义常量
  • 还有上面的tf.placeholder 输入占位符

而权重和偏置自然是变量啦,反向传播梯度下降时它们都是要不断变化的

    inputW = tf.Variable(tf.random_normal([10,1]))
    inputB = tf.Variable(tf.random_normal([10,1]))

大家可能会问,为什么权重是10x1的矩阵而不是1x10,这个和个人习惯有关,我习惯用权重乘以输入,输入为列向量,也可以定义为1x10,用输入乘以权重,输入行向量。反正这个就是要把x原来的1维变成10维。如果大家对神经网络不特别熟悉的话还是不要改啦,按我的来嘛。

同理定义隐藏层权重和偏置

    hideW = tf.Variable(tf.random_normal([1,10]))
    hideB = tf.Variable(tf.random_normal([1,1]))

构建网络

    h1 = tf.nn.sigmoid(tf.add(tf.matmul(inputW,x),inputB))
    output = tf.add(tf.matmul(hideW,h1),hideB)

采用sigmoid激励函数

tf.matmul(a,b)就是将张量a乘以张量b,tf.add(a,b)就是将张量a加上张量b
得到最终的output

输出层按理应当也采用激励函数,但我这为了省略数据归一化和还原,不对其采用激励函数,数据不归一化会导致梯度更新慢,网络收敛很慢,至于为什么,大家就要参考吴叔叔的课程和Rosenbrock函数了

定义loss和train_step

    loss= tf.reduce_mean(tf.reduce_sum(tf.square(y-output)))
    opt = tf.train.AdamOptimizer(1.0)
    train_step = opt.minimize(loss)

loss函数的定义相信大家有了对tf.matmul和tf.add的了解,就能一眼看出其被定义为预测值和实际值的最小二乘
优化器opt我选择了一个强大的Adam优化器,要用就要用牛逼的,优化速率定位1.0
让优化器最小化loss就是我们训练模型需要做的事情了

到此,类Network编写完毕

主函数

先得到我们用来训练的所谓的大量数据其实是自己编的,没错就是自己编的

x_data = np.linspace(-1,1,100).reshape(1,100)
noise = np.random.normal(0,0.05,x_data.shape)
y_data = x_data**3+1+noise

现在就知道我们要拟合的函数为 y = x^3+1 了noise为白噪声,来点噪声的目的主要是为了告诉大家数据不是我编的(啪啪!)

定义Session

net = Network()
sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init)

先实例化我们刚刚辛辛苦苦写的Network对象,然后定义一个sess,光定义一个sess还不够,要进行初始化Tensorflow才会承认我们刚刚辛辛苦苦写的一堆变量(Variable)

然后就是训练网络了

非常简单,一个循环搞定!

简单是简单,但就是运行时看不到训练过程,所以我用matplotlib库加了动态更新的图在上面,具体什么样我就不附上了,源码在本文最末尾,大家自个去运行看看呗
train_step = 200
for step in range(train_step):
    print('第',step+1,'次训练')
    sess.run(net.train_step,feed_dict={net.x:x_data,net.y:y_data})
    pre = sess.run(net.output,feed_dict={net.x:x_data})

训练次数为200次
pre即我们模型此次训练后预测到的结果
重点要讲的是,当某个变量的计算要设计输入数据时,要用feeddict将数据传进去,如上面代 码所示

最终拟合效果如下:

010d546dbc12ea5e82d9a2986bf8f24f.png
拟合效果

拟合效果还行,还看得过去

保存模型

接上开头的话,大家学习要的不就是个成就感么,很多教程就是到上一步,然后让大家看看训练的精确度有多高,然后表示对CPU或GPU的工作给予高度的肯定,让其能够再接再厉发光发热,然后就没了,然后就真的没了,训练半天没得到能用模型,就是仅仅让自己的CPU或GPU发了下光和热,

saver = tf.train.Saver()
saver.save(sess, "./tmp/model.ckpt")

Tensorflow有专门保存模型的tf.train.Saver()

将模型保存到当前目录下的tmp文件夹下

6760c1cd0ae4b2ba489020d3455f81c2.png


保存后有4个文件,然而没有一个是.ckpt后缀的,至于为什么加个ckpt,官方是如是说的

即使模型的预测值和实际值大相径庭,但比较时自个亲自训练的模型,自己养大的孩子,也比那些预测得很好但预测完之后什么都没了的好

Note: There is not a physical file called /tmp/model.ckpt. It is the prefix of filenames created for the checkpoint. Users only interact with the prefix instead of physical checkpoint files.

模型的恢复放到下一篇文讲:

Tensorflow入门教程及模型保存和恢复(二)


最后附上全部代码:

import numpy as np
import tensorflow as tf
import pylab as pl



class Network():

    x = tf.placeholder(shape=[1,None],dtype=tf.float32)
    y = tf.placeholder(shape=[1,None],dtype=tf.float32)

    inputW = tf.Variable(tf.random_normal([10,1]))
    inputB = tf.Variable(tf.random_normal([10,1]))

    hideW = tf.Variable(tf.random_normal([1,10]))
    hideB = tf.Variable(tf.random_normal([1,1]))

    h1 = tf.nn.sigmoid(tf.add(tf.matmul(inputW,x),inputB))
    output = tf.add(tf.matmul(hideW,h1),hideB)

    loss= tf.reduce_mean(tf.reduce_sum(tf.square(y-output)))

    opt = tf.train.AdamOptimizer(1)

    train_step = opt.minimize(loss)


if __name__ == '__main__':

    x_data = np.linspace(-1,1,100).reshape(1,100)
    noise = np.random.normal(0,0.05,x_data.shape)
    y_data = x_data**3+1+noise
    
    net = Network()
    sess = tf.Session()
    init = tf.global_variables_initializer()
    
    sess.run(init)
    saver = tf.train.Saver()

    
    fig = pl.figure(1)
    pl.ion()

    train_step = 200
    for step in range(train_step):
        print('第',step+1,'次训练')
        sess.run(net.train_step,feed_dict={net.x:x_data,net.y:y_data})
        pre = sess.run(net.output,feed_dict={net.x:x_data})

        
        pl.clf()
        pl.scatter(x_data,y_data)
        pl.plot(x_data.T,pre.T,'r')
        pl.pause(0.01)


    saver.save(sess, "./tmp/model.ckpt")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值