一、神经网络的实现过程

  1、准备数据集,提取特征,作为输入喂给神经网络
       2、搭建神经网络结构,从输入到输出
       3、大量特征数据喂给 NN,迭代优化 NN 参数
       4、使用训练好的模型预测和分类

二、前向传播  

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

  举例:假如生产一批零件, 体积为 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, 这便实现了前向传播过程。

  再来推导图中的代码实现过程。

  第一层:

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

  (2)W前节点编号,后节点编号(层数)为待优化的参数:前面两个节点,后面三个节点。所以w应该是个两行三列的矩阵。表示为

      

    注意:神经网络共有几层是指计算层, 输入不算作计算层,所以 上图中a 为第一层网络,a 是一个一行三列矩阵。

  第二层:

  (1)参数要满足前面三个节点,后面一个节点,所以W(2)是三行一列矩阵。表示为

  

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

下面讨论这其中的细节问题。

1、神经网络的参数

       显然权重w是很重要的参数,我们刚开始设置w变量的时候,一般会先随机生成这些参数,当然肯定是变量形式。

所以这里介绍一下 tf 常用的生成随机数/数组的函数:

(1)tf.random_normal()     生成正态分布随机数

w=tf.Variable(tf.random_normal([2,3],stddev=2, mean=0, seed=1))
# 表示生成正态分布随机数,形状两行三列,标准差是2,均值是0,随机种子是1

(2)tf.truncated_normal()  生成去掉过大偏离点的正态分布随机数,也就是如果随机生成的数据偏离平均值超过两个标准差,这个数据将重新生成

w=tf.Variable(tf.Truncated_normal([2,3],stddev=2, mean=0, seed=1))

(3)tf.random_uniform()    生成均匀分布随机数

w=tf.Variable(tf.random_uniform([2,3],minval=0,maxval=1,dtype=tf.float32,seed=1))
# 表示从一个均匀分布[minval maxval)中随机采样,产生的数是均匀分布的,注意定义域是左闭右开,即包含 minval,不包含 maxval。

以上这些函数,如果没有特殊要求标准差、 均值、 随机种子是可以不写的。看具体使用情况。

(4)其它函数:tf.zeros             表示生成全 0 数组
         tf.ones              表示生成全 1 数组
         tf.fill                  表示生成全定值数组
         tf.constant        表示生成直接给定值的数组

tf.zeros([3,2],int32)  # 表示生成[[0,0],[0,0],[0,0]]
tf.ones([3,2],int32) # 表示生成[[1,1],[1,1],[1,1]
tf.fill([3,2],6) # 表示生成[[6,6],[6,6],[6,6]]
tf.constant([3,2,1]) # 表示生成[3,2,1]

 2、placeholder占位,输入多组数据

      不做赘述,直接在代码里面注释这样的操作

细节讨论完,下面就是用代码实现前向传播

 # (1) 用placeholder 实现输入定义(sess.run 中喂入一组数据)的情况,特征有体积和重量,数据为体积 0.7、重量 0.5

 import tensorflow as tf

 x = tf.placeholder(tf.float32,shape=(1,2))  # placeholder占位,首先要指定数据类型,然后可以指定形状,因为我们现在只需要占一组数据,且有两个特征值,所以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) # 矩阵乘法op
y = tf.matmul(a,w2) with tf.Session() as sess:
init = tf.global_variables_initializer() # 初始化以后就放在这里,不容易忘记
sess.run(init)
print("y is",sess.run(y,feed_dict={x:[[0.7,0.5]]})) # 以字典形式给feed_dict赋值,赋的是一个一行两列的矩阵,注意张量的阶数。这里只执行了y的op,因为执行了y也就执行了a这个op

运行显示结果为:

y is: [[ 3.0904665]]
# (2) 用 placeholder 实现输入定义(sess.run 中喂入多组数据)的情况
import tensorflow as tf #定义输入和参数
x=tf.placeholder(tf.float32,shape=(None,2)) # 这里占位因为不知道要输入多少组数据,但还是两个特征,所以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 is:",sess.run(y,feed_dict={x:[[0.7,0.5],
[0.2,0.3],
[0.3,0.4],
[0.4,0.5]]})) # 输入数据,4行2列的矩阵

  运行显示结果为:

y is: [[ 3.0904665 ]
[ 1.2236414 ]
[ 1.72707319]
[ 2.23050475]]

以上就是最简单的神经网络前向传播过程。

三、后向传播

  反向传播:训练模型参数,以减小loss值为目的,使用优化方法,使得 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)

  train_step=tf.train.MomentumOptimizer(learning_rate, momentum).minimize(loss)

  train_step=tf.train.AdamOptimizer(learning_rate).minimize(loss)

三种优化方法的区别

  学习率:决定每次参数更新的幅度。

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

  Python代码实现加上反向传播的NN

  随机产生 32 组生产出的零件的体积和重量,训练 3000 轮,每 500 轮输出一次损失函数。

 import tensorflow as tf
import numpy as np BATCH_SIZE = 8 # 一次输入网络的数据,称为batch。一次不能喂太多数据
SEED = 23455 # 产生统一的随机数 # 基于seed产生随机数,这是根据随机种子产生随机数的一种常用方法,要熟练运用
rdm = np.random.RandomState(SEED)
# 随机数返回32行2列的矩阵 表示32组 体积和重量 作为输入数据集。因为这里没用真实的数据集,所以这样操作。
X = rdm.rand(32, 2)
# 从X这个32行2列的矩阵中 取出一行 判断如果和小于1 给Y赋值1 如果和不小于1 给Y赋值0 (这里只是人为的定义),作为输入数据集的标签(正确答案)
Y_ = [[int(x0 + x1 < 1)] for (x0, x1) in X]
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.001).minimize(loss) # 三种优化方法选择一个就可以
# train_step = tf.train.MomentumOptimizer(0.001,0.9).minimize(loss_mse)
# train_step = tf.train.AdamOptimizer(0.001).minimize(loss_mse) # 3生成会话,训练STEPS轮
with tf.Session() as sess:
init = tf.global_variables_initializer()
sess.run(init)
# 输出目前(未经训练)的参数取值。
print("w1:\n", sess.run(w1))
print("w2:\n", sess.run(w2))
print("\n") # 训练模型。
STEPS = 3000
for i in range(STEPS): #0-2999
start = (i * BATCH_SIZE) % 32 #i=0,start=0,end=8;i=1,start=8,end=16;i=2,start=16,end=24;i=3,start=24,end=32;i=4,start=0,end=8。也就是说每次训练8组数据,一共训练3000次。
end = start + BATCH_SIZE
sess.run(train_step, feed_dict={x: X[start:end], y_: Y_[start:end]})
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))

  运行显示结果为

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.81131822 1.48459876 0.06532937]
[-2.4427042 0.0992484 0.59122431]]
w2:
[[-0.81131822]
[ 1.48459876]
[ 0.06532937]] After 0 training step(s), loss_mse on all data is 5.13118
After 500 training step(s), loss_mse on all data is 0.429111
After 1000 training step(s), loss_mse on all data is 0.409789
After 1500 training step(s), loss_mse on all data is 0.399923
After 2000 training step(s), loss_mse on all data is 0.394146
After 2500 training step(s), loss_mse on all data is 0.390597 w1:
[[-0.70006633 0.9136318 0.08953571]
[-2.3402493 -0.14641267 0.58823055]]
w2:
[[-0.06024267]
[ 0.91956186]
[-0.0682071 ]]

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

针对上面的代码,做出如下思考。首先最终的目的是使得loss值减小,那么:

1、如果增大训练次数,loss会不会继续减小?如果减小,会不会一直在减小?

增大了训练次数后,发现随着次数增加,loss值确实会慢慢减小,但是减小的幅度越来越小,直至训练了16500次之后,loss值保持不变。

after 3000 training step(s) ,loss on all data is 0.388336
after 3500 training step(s) ,loss on all data is 0.386855
after 4000 training step(s) ,loss on all data is 0.385863
after 4500 training step(s) ,loss on all data is 0.385186
after 5000 training step(s) ,loss on all data is 0.384719
after 5500 training step(s) ,loss on all data is 0.384391
after 6000 training step(s) ,loss on all data is 0.38416
after 6500 training step(s) ,loss on all data is 0.383995
after 7000 training step(s) ,loss on all data is 0.383877
after 7500 training step(s) ,loss on all data is 0.383791
after 8000 training step(s) ,loss on all data is 0.383729
after 8500 training step(s) ,loss on all data is 0.383684
after 9000 training step(s) ,loss on all data is 0.383652
after 9500 training step(s) ,loss on all data is 0.383628
after 10000 training step(s) ,loss on all data is 0.38361
after 10500 training step(s) ,loss on all data is 0.383597
after 11000 training step(s) ,loss on all data is 0.383587
after 11500 training step(s) ,loss on all data is 0.38358
after 12000 training step(s) ,loss on all data is 0.383575
after 12500 training step(s) ,loss on all data is 0.383571
after 13000 training step(s) ,loss on all data is 0.383568
after 13500 training step(s) ,loss on all data is 0.383566
after 14000 training step(s) ,loss on all data is 0.383565
after 14500 training step(s) ,loss on all data is 0.383564
after 15000 training step(s) ,loss on all data is 0.383563
after 15500 training step(s) ,loss on all data is 0.383562
after 16000 training step(s) ,loss on all data is 0.383562
after 16500 training step(s) ,loss on all data is 0.383561
after 17000 training step(s) ,loss on all data is 0.383561
after 17500 training step(s) ,loss on all data is 0.383561
after 18000 training step(s) ,loss on all data is 0.383561

 2、既然上面的问题是这样,那么随机梯度下降算法的学习率对loss减小有着怎样的影响?

我调整了学习率和训练次数,得到这样的规律,目前的学习率为0.001

当学习率为0.003时,5500次训练,loss就可以下降到0.383561

当学习率为0.005时,3500次训练,loss只能下降到0.383562

当学习率为0.007时,2500次训练,loss只能下降到0.383563

当学习率为0.01时,2500次训练,loss只能下降到0.383566

由此可以看出,当学习率增大时,优点是训练次数较少,缺点是可能参数在最小值附近波动,不收敛

当学习率为0.0007时,23500次训练,loss能下降到0.383561

当学习率为0.0003时,50000次训练,loss才能下降到0.383563

显然,学习率过小的缺点就是训练次数太多

3、如果不用随机梯度下降算法,换用其他的优化器,会产生什么样的变化?

(1)换用Momentum优化器,可以发现,当学习率也为0.001时,2000次训练,loss值就下降到了0.383561。

after 0 training step(s) ,loss on all data is 5.13118
after 500 training step(s) ,loss on all data is 0.384391
after 1000 training step(s) ,loss on all data is 0.383592
after 1500 training step(s) ,loss on all data is 0.383562
after 2000 training step(s) ,loss on all data is 0.383561
after 2500 training step(s) ,loss on all data is 0.383561
after 3000 training step(s) ,loss on all data is 0.383561

同样的增加和减小学习率,得到的现象和上文分析的是一样的。但是当学习率较大时,出现了loss值增大的现象

所以暂时可以得出这样的结论:Momentum优化器的优点是可以快速收敛到最小值,相同的学习率,需要的训练次数较少

(2)换用Adam优化器,可以发现,当学习率也为0.001时,3500次训练,loss值下降到了0.383561

变化学习率,现象和Momentum差不多,也出现loss值增大的现象。

after 0 training step(s) ,loss on all data is 5.20999
after 500 training step(s) ,loss on all data is 0.617026
after 1000 training step(s) ,loss on all data is 0.392288
after 1500 training step(s) ,loss on all data is 0.386432
after 2000 training step(s) ,loss on all data is 0.384254
after 2500 training step(s) ,loss on all data is 0.383676
after 3000 training step(s) ,loss on all data is 0.383573
after 3500 training step(s) ,loss on all data is 0.383561
after 4000 training step(s) ,loss on all data is 0.383561
after 4500 training step(s) ,loss on all data is 0.383561

 4、更改batch的值,会不会对结果有影响?

我把batch改为12,训练了35000次,最后loss值是下降到了0.384388和0.384447,也就是说未收敛

改为15,训练了50000次,最后还是下降到某几个固定的值,仍然未收敛

可以看得出,batch值增大时,训练次数增大,不收敛的可能性也增加。

将batch改为7和5,训练了35000次,也是不收敛。

这地方就很纳闷了,为啥8效果是最好的呢,这地方留点问题吧。以后再来看看

注:以上问题的结论只是暂时性的总结,由于目前水平有限,不知道结论正确与否。

四、搭建神经网络的过程

  通过以上的内容,我们可以梳理一下搭建简单神经网络的步骤:

  (1)导入模块,生成模拟数据集

          import

          常量定义

          生成数据集

  (2)前向传播:定义输入、参数和输出

          x=              y_=

          w1=            w2=

          a=              y=

  (3)后向传播:定义损失函数、反向传播方法

          loss=

          train_step=

  (4)生成会话,训练STEPS轮

        with tf.Session as sess:

          init_op = tf.global_variables_initializer()

          sess.run(init_op)

          STEPS =

            for i in range(STEPS):

            start =

            end =

            sess.run(train_step, feed_dict={ })

  以上是搭建简单神经网络的笔记

  本人初学者,有任何错误欢迎指出,谢谢。

Tensorflow学习:(二)搭建神经网络的更多相关文章

  1. TensorFlow学习笔记——深层神经网络的整理

    维基百科对深度学习的精确定义为“一类通过多层非线性变换对高复杂性数据建模算法的合集”.因为深层神经网络是实现“多层非线性变换”最常用的一种方法,所以在实际中可以认为深度学习就是深度神经网络的代名词.从 ...

  2. tensorflow学习之搭建最简单的神经网络

    这几天在B站看莫烦的视频,学习一波,给出视频地址:https://www.bilibili.com/video/av16001891/?p=22 先放出代码 #####搭建神经网络测试 def add ...

  3. Tensorflow学习教程------普通神经网络对mnist数据集分类

    首先是不含隐层的神经网络, 输入层是784个神经元 输出层是10个神经元 代码如下 #coding:utf-8 import tensorflow as tf from tensorflow.exam ...

  4. swoole学习(二)----搭建server和client

    1.搭建server 1.1搭建server.php 1.搭建websocket服务器,首先建立 server.php 文件, <?php $server = new swoole_websoc ...

  5. tensorflow学习笔记六----------神经网络

    使用mnist数据集进行神经网络的构建 import numpy as np import tensorflow as tf import matplotlib.pyplot as plt from ...

  6. Tensorflow 2.0 搭建神经网络(局部)

    前向传播 tensorflow.keras 搭建网络时,内部的网络可以直接完成所有层的前向计算.全连接Dense() 层,最后一层的神经元的个数需要和最后一层线性函数 w x + b 的维度对应上,中 ...

  7. 深度学习(TensorFlow)环境搭建:(二)Ubuntu16.04+1080Ti显卡驱动

    前几天把刚拿到了2台GPU机器组装好了,也写了篇硬件配置清单的文章——<深度学习(TensorFlow)环境搭建:(一)硬件选购和主机组装>.这两台也在安装Ubuntu 16.04和108 ...

  8. TensorFlow学习笔记(二)深层神经网络

    一.深度学习与深层神经网络 深层神经网络是实现“多层非线性变换”的一种方法. 深层神经网络有两个非常重要的特性:深层和非线性. 1.1线性模型的局限性 线性模型:y =wx+b 线性模型的最大特点就是 ...

  9. 深度学习(TensorFlow)环境搭建:(三)Ubuntu16.04+CUDA8.0+cuDNN7+Anaconda4.4+Python3.6+TensorFlow1.3

    紧接着上一篇的文章<深度学习(TensorFlow)环境搭建:(二)Ubuntu16.04+1080Ti显卡驱动>,这篇文章,主要讲解如何安装CUDA+CUDNN,不过前提是我们是已经把N ...

随机推荐

  1. 令assignment操作符返回一个reference to *this

    [令assignment操作符返回一个reference to *this] 关于赋值,可以把它们写成连锁形式: int x, y, z; x =y =z =15; II赋值连锁形式 上述连锁赋值被解 ...

  2. 好的MongoDB学习文章链接

    1.MongoDB 极简实践入门 2.MongoDB中文社区 3.极客学院Mongodb 教程

  3. Spring MVC表单防重复提交

    利用Spring MVC的过滤器及token传递验证来实现表单防重复提交. 创建注解 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RU ...

  4. HDU 6096 String (AC自动机)

    题目链接 Problem Description Bob has a dictionary with N words in it. Now there is a list of words in wh ...

  5. POJ 1240 Pre-Post-erous! && East Central North America 2002 (由前序后序遍历序列推出M叉树的种类)

    题目链接 问题描述 : We are all familiar with pre-order, in-order and post-order traversals of binary trees. ...

  6. [转]KMP 算法

    KMP 算法,俗称“看毛片”算法,是字符串匹配中的很强大的一个算法,不过,对于初学者来说,要弄懂它确实不易.整个寒假,因为家里没有网,为了理解这个算法,那可是花了九牛二虎之力!不过,现在我基本上对这个 ...

  7. 【codeforces】【比赛题解】#920 Educational CF Round 37

    [A]浇花 题意: 一个线段上每个整点都有花,有的点有自动浇花的喷水器,有问几秒能浇完所有的花. 题解: 大模拟 #include<cstdio> #include<cstring& ...

  8. 【四校联考】【比赛题解】FJ NOIP 四校联考 2017 Round 7

    此次比赛为厦门一中出题.都是聚劳,不敢恭维. 莫名爆了个0,究其原因,竟然是快读炸了……很狗,很难受. 话不多说,来看看题: [T1] 题意: 样例: PS:1<=h[i]<=100000 ...

  9. 【Python】POST上传APK检测是否存在ZipperDown漏洞

    前言 用POST的方式上传文件,检测APK是否存在ZipperDown漏洞. 代码 # authour:zzzhhh # 2018.08.08 # check ZipperDown # -*- cod ...

  10. Django 1.10中文文档-模型参考

    模型字段 本文档包含了Django提供的全部模型 Field 包括 字段选项 和 字段类型 的API参考. 参见 如果内建的字段不能满足你的需求, 你可以蚕食 django-localflavor ( ...