Tensorflow笔记之搭建神经网络NN

目录

一、基本概念:

1、基于Tensorflow的NN:   

2、张量:

3、数据类型:

4、计算图:

5、会话(Session):

二、神经网络的参数

1、神经网络的参数:

2、神经网络的搭建

3、前向传播(以全连接网络为例子)

4、反向传播:目的就是优化模型参数

三、搭建神经网络的8股

四、实战演练

1.导入模块,生成数据集;

2.定义神经网络的输入,参数和输出,定义前向传播过程。

3. 定义损失函数以及反向传播算法

4. 生成会话,训练STEPS轮


一、基本概念:

1、基于Tensorflow的NN:   

 张量表示数据,用计算图搭建神经网络,用会话执行计算图,优化线上的权重(参数),得到模型。

2、张量:

张量就是多维数组(列表),用表示张量的维度。

1. 0阶张量称作标量,表示一个单独的数;eg:  S=123

2. 1阶张量称作向量,表示一个一维数组; eg: V=[1,2,3]

3. 2阶张量称作矩阵,表示一个二维数组,它表示可以有i行j列个元素,每个元素可以用行号和列号共同索引得到;

    eg:  m=[[1,2,3],[4,5,6],[7,8,9]]

注意点:判断张量是几阶的,就通过张量右边的方括号数,0个事0阶,n个事n阶,张量可以表示0阶到n阶数组(列表)

              eg:t=[[[...]]]为三阶

3、数据类型:

在tensorflow的数据类型有tf.float32,tf.int32等等。

eg:我们实现tensorflow的加法:

import tensorflow as tf
a=tf.constant([1.0,2.0])
b=tf.constant([3.0,4.0])
result=a+b
print result

#输入结果
(tf1.5) zhangkf@Ubuntu2:~/tf$ python zhang.py 
Tensor("add:0", shape=(2,), dtype=float32)
#意思为result是一个名称为add:0的张量,
shape(2,)表示一维数组的长度为2,dtpye=float32表示数据类型为#浮点型。

4、计算图:

搭建神经网络的计算过程,是承载一个或者多个计算节点的一张图,只搭建网络,不运算。

我们实现上述计算图:

import tensorflow as tf
x=tf.constant([[1.0,2.0]])    #定义一个二阶张量等于[[1.0,2.0]]
w=tf.constant([[3.0],[4.0]])  #定义一个二阶张量
y=tf.matmul(x,w)              #实现xw矩阵的乘法
print y


#输出结果
(tf1.5) zhangkf@Ubuntu2:~/tf$ python zhang.py 
Tensor("MatMul:0", shape=(1, 1), dtype=float32)

从这里的显示可以看出来:print的结果显示y是一个张量,只搭建承载计算过程的计算图,并没有运算,如果我们想得到运算结果就要用到“会话Session()”了。

5、会话(Session):

执行计算图中的节点运算

我们用with结构实现,语法如下:

with tf.Session() as sess:    #tensorflow中的类Session
    print sess.run(y)

对于刚刚所述计算图,我们执行Session()会话可得到矩阵相乘结果:

import tensorflow as tf
x=tf.constant([[1.0,2.0]])   #定义一个二阶张量等于[[1.0,2.0]]
w=tf.constant([[3.0],[4.0]]) #定义一个二阶张量
y=tf.matmul(x,w)             #实现xw矩阵的乘法
print y

with tf.Session() as sess:
    print sess.run(y)        #执行会话并打印执行后的结果


#输出结构:
(tf1.5) zhangkf@Ubuntu2:~/tf$ python zhang.py 
Tensor("MatMul:0", shape=(1, 1), dtype=float32)
[[11.]]

我们可以看到,运行Session()会话前只打印出y是个张量的提示,运行Session()会话后打印出了y的结果1.0*3.0 + 2.0*4.0 = 11.0

二、神经网络的参数

1、神经网络的参数:

是指神经元线上的权重w,用变量表示,一般会先随机生成这些参数。生成参数的方法是让w等于tf.Variable,把生成的方式写在括号里。神经网络中常用的生成随机数、数组的函数有:

tf.random_normal()            #生成正态分布随机数 
f.truncated_normal()          #生成去掉过大偏离点的正态分布随机数 truncate缩短
tf.random_uniform()           #生成均匀分布随机数 
tf.zeros                      #表示生成全0数组
tf.ones                       #表示生成全1数组
tf.fill                       #表示生成全定值数组   
tf.constant                   #表示生成直接给定值的数组
1、w=tf.Variable(tf.random_normal([2,3],stddev=2,mean=0,seed=1))
#表示生成正态分布的随机数,形成2行3列,标准差为2,均值为0,随机种子是1.


2、w=tf.Variable(tf.truncated_normal([2,3],stddev=2,mean=0,seed=1))
#表示去掉偏离过大的正太分布,也就是若果随机出来的数据偏离平均值超过2个标准差,这个数据将重新生成。

3、t=tf.random_uniform(shape=7,minval=0,maxmal=1,dtype=tf.int32,seed=1)
#表示生成一个均匀分布【minval,maxval)中随机采样,注意定义域是左闭区有开,即是包含minval,不含#maxval

4、除了生成随机数,还可以生成常量,tf.zeros([3,2],int32)表示生成3行2列的矩阵全为0;
tf.ones([3,2],int32)表示生成3行2列全为1的矩阵,
tf.fill([3,2],6)表示生成[[6,6],[6,6],[6,6]]\
tf.constant([3,2,1])表示生成[3,2,1]

注意:①随机种子如果去掉每次生成的随机数将不一致。

           ②如果没有特殊要求标准差、均值、随机种子是可以不写的。 

2、神经网络的搭建

当我们知道张量,计算图,会话和参数后,我们可以讨论神经网络的实现过程啦。

1、神经网络的实现过程:

1. 准备数据集,提取特征(eg:零件的体积和重量,还包括这组特征所对应的标签,如零件是合格还是不合格)作为输入喂给神经网络(NN)

2. 搭建神经网络NN结构,从输入到输出(先搭建计算图,再用会话执行)

           (NN前向传播算法——>>>计算输出)

3. 大量特征数据喂给神经网络NN,迭代优化NN参数

          (NN反向传播算法——>>>优化参数训练模型)

4. 使用训练好的模型预测和分类。

由此可见,基于神经网络的机器学习主要分为两个过程,即训练过程和使用过程。  训练过程是第一步、第二步、第三步的循环迭代,使用过程是第四步,一旦参数优化完成就可以固定这些参数,实现特定应用了。

很多实际应用中,我们会先使用现有的成熟网络结构,喂入新的数据,训练相应模型,判断是否能对喂入的从未见过的新数据作出正确响应,再适当更改网络结构,反复迭代,让机器自动训练参数找出最优结构和参数,以固定专用模型。 

3、前向传播(以全连接网络为例子)

前向传播就是搭建模型的计算过程,让模型具有推理能力,可以针对一组输入给出相应的输出。

举例子:

假如生成一批零件,体积为x1,重量为x2,体积和重量就是我们选择的特征,把他们喂给神经网络,当体积和重量这组数据走过神经网络得到一个输出。假如输入的特征值是:体积为0.7   重量为0.5

由搭建的神经网络可得,隐藏层节点a11=x1* w11+x2*w21=0.14+0.15=0.29,同理算得节点a12=0.32,a13=0.38,最终计算得到输出层Y=-0.015,这便实现了前向传播过程。

2. 推导过程

第一层:

  • X是输入为1*2矩阵:用x表示输入,是一个1行2列的矩阵,表示一次输入一组特征,这组特征包含了体积和重量2个元素。

  • 为待优化的参数 :

        对于第一层的w节点前面有2个节点,后面有3个节点w应该是个2行3列的矩阵,我们这样表示:

  • 神经网络共有几层(或当前是第几层网络)都是指的计算层,输入不是计算层,所以a为第一层网络,a是一个一行三列矩阵。 我们可以这样表示:

第二层:

  • 参数要满足前面3个节点,后面一个节点,所以是一个3行1列的矩阵,我们可以这样表

我们把每层输入乘以线上的权重w,这样用矩阵乘法可以计算输出y啦。

a=tf.matmul(x,w1)
y=tf.matmul(a,w2)

由于需要计算结果,就要用with结构实现,所有变量初始化过程,计算过程都要 放到sess.run()函数中,对于变量初始化,在sess.run()函数中写入:tf.global_variables_initializer 实现对所有变量初始化,也就是赋初值。对于计算图中的运算,我们直接把运算节点填入sess.run 即可,比如要计算输出y,直接写 sess.run(y) 即可。 

注意:在实际的应用中,我们可以一次喂给神经网络一组或者多组数据,让神经网络计算输出y,可以先用 tf.placeholder给输入占位。如果一次喂一组数据shape的第一维位置写1,第二维位置写有几个输入特征,如果一次喂入多组特征,shape的第一维写None表示先空着,第二维写有几个输入特征,这样在feed_dict中可以喂入若干组体积重量啦。

3. 前向传播过程的tensorflow描述

  • 变量初始化、计算图节点运算都要用会话(with结构)实现
with tf.Session() as sess:
     sess.run() 
  • 变量初始化:在sess.run函数中用 tf.global_variables_initializer()汇总所有待优化变量
init_op = tf.global_variables_initializer() 
sess.run(init_op) 
  • 计算图节点运算:在sess.run函数中写入待运算的节点 
sess.run(y) 
  • 用 tf.placeholder 占位,在 sess.run 函数中用 feed_dict喂数据 

喂一组数据:

x = tf.placeholder(tf.float32, shape=(1, 2))

喂多组数据:

x = tf.placeholder(tf.float32, shape=(None, 2))
sess.run(y, feed_dict={x: [[0.1,0.2],[0.2,0.3],[0.3,0.4],[0.4,0.5]]}) 

下面进行一个举例分析:

#这是实现一个神经网络前向传播过程,网络可以自动推理出y的值
# 1、用placeholder实现输入定义(sess.run中喂入一组数据)的情况 
# 第一组喂体积0.7、重量0.5

#coding:utf-8
import tensorflow as tf
# 定义输入和参数
x=tf.placeholder(tf.float32,shape=(1,2))
w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1))
w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=1))

# 定义前向传播过程
a=tf.matmul(x,w1)
y=tf.matmul(a,w2)

# 用会话计算结果
with tf.Session() as sess:
    init_op=tf.global_variables_initializer() # 初始化变量
    sess.run(init_op)
    print"y in tf3_3.py is :\n",sess.run(y,feed_dict={x:[[0.7,0.5]]})

 #输出结果: 

(tf1.5) zhangkf@Ubuntu2:~/tf$ python tf3_1.py 
y in tf3_3.py is :
[[3.0904665]]

# 2、用placeholder实现输入定义(sess.run中喂入多组数据)的情况 
# 第一组喂体积0.7、重量0.5。#第二组喂体积0.2、重量0.3。#第二组喂体积0.3、重量0.4。第四组喂体积0.4、重量0.5

#coding:utf-8
import tensorflow as tf
# 定义输入和参数
x=tf.placeholder(tf.float32,shape=(None,2))  #这里区别
w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1))
w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=1))

# 定义前向传播过程
a=tf.matmul(x,w1)
y=tf.matmul(a,w2)

# 用会话计算结果
with tf.Session() as sess:
    init_op=tf.global_variables_initializer() # 初始化变量
    sess.run(init_op)
    print"y in tf3_4.py is :\n",sess.run(y,feed_dict={x:[[0.7,0.5],[0.2,0.3],[0.3,0.4],[0.4,0.5]]})

运行结果:

(tf1.5) zhangkf@Ubuntu2:~/tf$ python tf3_1.py 
y in tf3_4.py is :
[[3.0904665]
 [1.2236414]
 [1.7270732]
 [2.2305048]]

4、反向传播:目的就是优化模型参数

反向传播:训练模型参数,在所有参数上用梯度下降,使NN模型在训练数据上损失函数最小。

  • 损失函数(loss):计算得到的预测值y与已知答案y_的差距。 

损失函数的计算有很多方法,均方误差MSE是比较常用的方法之一。

  • ​​​​​​​均方误差MSE: 求前向传播计算结果与已知答案之差的平方再求平均。

用tensorflow函数表示为:

loss_mse=tf.reduce_mean(tf.square(y_-y))
  • 反向传播训练方法:以减小loss值为优化目标,有梯度下降,momentum优化器adam优化器等优化方法。

​​​​​​​这三种优化方法用tensorflow的函数可以表示为:

# 梯度下降
train_step=tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)

# momentum优化器
train_step=tf.train.MomentumOptimizer(learning_rate,momentum).minimize(loss)

# adam优化器
train_step=tf.train.AdamOptimizer(learn_rate).minimizer(loss)
  • 三种优化方法区别如下: 

①、tf.train.GradientDescentOptimizer()使用随机梯度下降算法,使参数沿着梯度的反方向,即总损失减小的方向移动,实现更新参数。参数的更新公式为:

②tf.train.MomentumOptimizer()在更新参数时,利用了超参数,参数更新公式是 

③tf.train.AdamOptimizer()是利用自适应学习率的优化算法,Adam算法和随机梯度下降算法不同。随机梯度下降算法保持单一的学习率更新所有的参数,学习率在训练过程中并不会改变。而 Adam 算法通过计算梯度的一阶矩估计和二阶矩估计而为不同的参数设计独立的自适应性学习率。 

  • 学习率​​​​​​​

优化器中都需要一个叫做学习率的参数,使用时,如果学习率选择过大会出现震荡不收敛的情况,如果学习率选择过小,会出现收敛速度慢的情况。我们可以选个比较小的值填入,比如0.01、0.001。 

  • 进阶(省略)可以参看我之前的深入理解BP算法。

三、搭建神经网络的8股​​​​​​​

我们最后梳理出神经网络搭建的八股,神经网络的搭建课分四步完成:准备工作、前向传播、反向传播和循环迭代。

 

with tf.Session() as sess:
    init_op=tf.global_variables_initializer()
    sess.run(init_op)
    STEPS=3000
    for i in range(STEPS):
        start=
        end=
        sess.run(train_step,feed_dict:)

四、实战演练

题目:随机产生32组生产出的零件的体积和重量,训练3000轮,每500轮输出一次损失函数,下面这个我们通过源代码进一步理解神经网络的实现过程:

1.导入模块,生成数据集;

#coding:utf-8
# 0导入模块,生成模拟数据集。
import tensorflow as tf
import numpy as np
BATCH_SIZE=8     #一次喂入神经网络多少组数据,不能太大,一次吃太多容易噎到
seed=23455

#基于seed产生随机数
rng=np.random.RandomState(seed)
#随机数返回32行2列的矩阵,表示32组,体积和重量,作为输入数据集。
X=rng.rand(32,2)

#从X这个32行2列的矩阵中,取出1行,判断如果和小于1给Y赋值为1,如果和不小于1给Y赋值为0
#作为数据集的输入标签(正确答案)
Y=[[int(x0+x1<1)] for (x0,x1) in X] #先用for循环从列表中抽取1行,也就是x0和x1,再判断x0+x1,
                                    #如果和小于1,就为真,把1赋值为y,否则把0赋值给y.
print"X:\n",X
print"Y:\n",Y

运行结果:

(tf1.5) zhangkf@Ubuntu2:~/tf$ python tf3_1.py 
X:
[[0.83494319 0.11482951]
 [0.66899751 0.46594987]
 [0.60181666 0.58838408]
 [0.31836656 0.20502072]
 [0.87043944 0.02679395]
 [0.41539811 0.43938369]
 [0.68635684 0.24833404]
 [0.97315228 0.68541849]
 [0.03081617 0.89479913]
 [0.24665715 0.28584862]
 [0.31375667 0.47718349]
 [0.56689254 0.77079148]
 [0.7321604  0.35828963]
 [0.15724842 0.94294584]
 [0.34933722 0.84634483]
 [0.50304053 0.81299619]
 [0.23869886 0.9895604 ]
 [0.4636501  0.32531094]
 [0.36510487 0.97365522]
 [0.73350238 0.83833013]
 [0.61810158 0.12580353]
 [0.59274817 0.18779828]
 [0.87150299 0.34679501]
 [0.25883219 0.50002932]
 [0.75690948 0.83429824]
 [0.29316649 0.05646578]
 [0.10409134 0.88235166]
 [0.06727785 0.57784761]
 [0.38492705 0.48384792]
 [0.69234428 0.19687348]
 [0.42783492 0.73416985]
 [0.09696069 0.04883936]]
Y:
[[1], [0], [0], [1], [1], [1], [1], [0], [1], [1], [1], [0], [0], [0], [0], [0], [0], [1], [0], [0], [1], [1], [0], [1], [0], [1], [1], [1], [1], [1], [0], [1]]

2.定义神经网络的输入,参数和输出,定义前向传播过程。

# 1定义神经网络的输入,参数和输出,定义前向传播过程。
x=tf.placeholder(tf.float32,shape(None,2))
y_=tf.placeholder(tf.float32,shape(None,1))

w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1))
w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=1))

a=tf.matmul(x,w1)
y=tf.matmul(a,w2)

3. 定义损失函数以及反向传播算法

# 2定义损失函数以及反向传播算法
loss=tf.reduce_mean(tf.square(y-y_))
train_step=tf.train.GradientDescentOptimizer(0.001).minimize(loss)
#train_step=tf.train.MomentumOptimizer(0.001).minimize(loss)
#train_step=tf.train.AdamOptimizer(0.001).minimize(loss)

4. 生成会话,训练STEPS轮

# 3生成会话,训练STEPS轮
with tf.Session() as sess:
    init_op=tf.global_variables_initialzer()
    sess.run(init_op)
    
    #输出目前(没有训练)的参数值
    print"w1: \n",sess.run(w1)
    print"w2: \n",sess.run(w2)
    print"\n"

    #训练模型
    STEPS=3000
    for in in range(STEPS):
        start=(i*BATCH_SIZE) % 32
        end=start+BATCH_SIZE
        sess.run(train_steps,feed_dict={x:X[start:end], y_:Y[start:end]}) #8组数据,执行优化
        if i% 500==0:
            total_loss=sess.run(loss,feed_dict={x:X,y_:Y})
            print"after %d training step(s), loss on all data is %g" %(i,total_loss) #损失

#输出训练后的参数取值
print"\n"
print"w1: \n",sess.run(w1)
print"w2: \n",sess.rum(w2)          

由神经网络的实现结果,我们可以看出,总共训练3000轮,每轮从X的数据集和Y的标签中抽取相对应的从start 开始到end结束个特征值和标签,喂入神经网络,用sess.run求出loss,每500轮打印一次loss的值,经过3000轮之后,我们打印出最终训练好的参数w1和w2.

最后程序代码:

#coding:utf-8
#导入模块,生成模拟数据集 
import tensorflow as tf 
import numpy as np
BATCH_SIZE=8			#一次喂入神经网络多少组数据,不能太大,吃多了会噎着的。
seed=23455

#基于seed产生随机数
rng=np.random.RandomState(seed)	#为随机数产生器的种子,里面的数字一样,则产生的随机数相同。
#随机数返回32行2列的矩阵,表示32组 体积和重量,作为数据输入集
X=rng.rand(32,2)

#从32行2列的矩阵中,取出一行,判断如果小于1 给Y赋值1,如果小于给Y赋值为0。
Y=[[int(x0+x1<1)] for (x0,x1) in X ]   #先用for循环从列表X中抽取一行,也就是x0,x1,在判断x0,x1,如果之和小于1,就为真
                                       #会把1赋值给y,否则赋值为0
print "X:\n",X
print "Y:\n",Y

# 1定义神经网络的输入,参数和输出,定义前向传播过程;
x=tf.placeholder(tf.float32,shape=(None,2))
y_=tf.placeholder(tf.float32,shape=(None,1))

w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1))
w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=1))

a=tf.matmul(x,w1)
y=tf.matmul(a,w2)

# 2 定义损失函数即反向传播方法
loss=tf.reduce_mean(tf.square(y-y_))
train_step=tf.train.GradientDescentOptimizer(0.01).minimize(loss)


# 3 生成会话,训练STEPS轮
with tf.Session() as sess:
	init_op=tf.global_variables_initializer()
	sess.run(init_op)
	#输出目前(未经训练)的参数取值。
	print "w1:\n",sess.run(w1)
	print "w2:\n",sess.run(w2)
	print "\n"

	#训练模型s
	STEPS=3000
	for i in range(STEPS):
		start=(i*BATCH_SIZE)%32
		end=start+BATCH_SIZE
		sess.run(train_step,feed_dict={x:X[start:end],y_:Y[start:end]})		##8组数据,执行优化
		if i%500==0:
			total_loss=sess.run(loss,feed_dict={x:X,y_:Y})
			print"after %d training step(s),loss on all data is %g" %(i,total_loss)	#损失
			
	#输出训练后的参数取值。优化后。
	print"\n"
	print"w1:\n",sess.run(w1)
	print"w2:\n",sess.run(w2)

 运行结果:

(tf1.5) zhangkf@Ubuntu2:~/tf$ python tf3_6.py 
X:
[[0.83494319 0.11482951]
 [0.66899751 0.46594987]
 [0.60181666 0.58838408]
 [0.31836656 0.20502072]
 [0.87043944 0.02679395]
 [0.41539811 0.43938369]
 [0.68635684 0.24833404]
 [0.97315228 0.68541849]
 [0.03081617 0.89479913]
 [0.24665715 0.28584862]
 [0.31375667 0.47718349]
 [0.56689254 0.77079148]
 [0.7321604  0.35828963]
 [0.15724842 0.94294584]
 [0.34933722 0.84634483]
 [0.50304053 0.81299619]
 [0.23869886 0.9895604 ]
 [0.4636501  0.32531094]
 [0.36510487 0.97365522]
 [0.73350238 0.83833013]
 [0.61810158 0.12580353]
 [0.59274817 0.18779828]
 [0.87150299 0.34679501]
 [0.25883219 0.50002932]
 [0.75690948 0.83429824]
 [0.29316649 0.05646578]
 [0.10409134 0.88235166]
 [0.06727785 0.57784761]
 [0.38492705 0.48384792]
 [0.69234428 0.19687348]
 [0.42783492 0.73416985]
 [0.09696069 0.04883936]]
Y:
[[1], [0], [0], [1], [1], [1], [1], [0], [1], [1], [1], [0], [0], [0], [0], [0], [0], [1], [0], [0], [1], [1], [0], [1], [0], [1], [1], [1], [1], [1], [0], [1]]
w1:
[[-0.8113182   1.4845988   0.06532937]
 [-2.4427042   0.0992484   0.5912243 ]]
w2:
[[-0.8113182 ]
 [ 1.4845988 ]
 [ 0.06532937]]


after 0 training step(s),loss on all data is 4.27092
after 500 training step(s),loss on all data is 0.384598
after 1000 training step(s),loss on all data is 0.383598
after 1500 training step(s),loss on all data is 0.383565
after 2000 training step(s),loss on all data is 0.383565
after 2500 training step(s),loss on all data is 0.383566


w1:
[[-0.67919636  0.80567193  0.094153  ]
 [-2.3313076  -0.10339051  0.5821425 ]]
w2:
[[-0.09453004]
 [ 0.7987898 ]
 [-0.04888064]]

这样4步就可以实现神经网络啦。

猜你喜欢

转载自blog.csdn.net/abc13526222160/article/details/84757698
今日推荐