一、神经网络的实现过程
1、准备数据集,提取特征,作为输入喂给神经网络(Neural Network, NN)
2、搭建 NN 结构,从输入到输出(先搭建计算图,再用会话执行)
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,前面有两个节点,后面有三个节点。所以w应该是个两行三列的矩阵。表示为
注意:神经网络共有几层(或当前是第几层网络)都是指的计算层, 输入不是计算层,所以 a 为第一层网络, a 是一个一行三列矩阵。表示为:a(1) = [a11,a12,a13]=XW(1)
第二层:
(1)参数要满足前面三个节点,后面一个节点,所以W(2)是三行一列矩阵。表示为
我们把每层输入乘以线上的权重w,这样就可以用矩阵乘法输出y了。
Python代码实现:
1 # (1) 用placeholder 实现输入定义(sess.run 中喂入一组数据)的情况,第一组喂体积 0.7、重量 0.5 2 import tensorflow as tf 3 4 #定义输入和参数 5 x=tf.placeholder(tf.float32,shape=(1,2)) 6 w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1)) 7 w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=1)) 8 9 #定义前向传播过程 10 a=tf.matmul(x,w1) 11 y=tf.matmul(a,w2) 12 13 #用会话计算结果 14 with tf.Session() as sess: 15 init_op=tf.global_variables_initializer() 16 sess.run(init_op) 17 print("y is:",sess.run(y,feed_dict={x:[[0.7,0.5]]}))
运行显示结果为:
y is: [[ 3.0904665]]
1 # (2) 用 placeholder 实现输入定义(sess.run 中喂入多组数据)的情况 2 import tensorflow as tf 3 4 #定义输入和参数 5 x=tf.placeholder(tf.float32,shape=(None,2)) 6 w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1)) 7 w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=1)) 8 9 #定义前向传播过程 10 a=tf.matmul(x,w1) 11 y=tf.matmul(a,w2) 12 13 #用会话计算结果 14 with tf.Session() as sess: 15 init_op=tf.global_variables_initializer() 16 sess.run(init_op) 17 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]]})
运行显示结果为:
y is: [[ 3.0904665 ] [ 1.2236414 ] [ 1.72707319] [ 2.23050475]]
三、后向传播
反向传播:训练模型参数,在所有参数上使用梯度下降,使 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。
以上是后向传播中常用的概念,更多详细优化方法见后续随笔。其中几种反向传播训练方法的区别、反向传播参数更新推导过程 见MOOC北大tensorflow课程,第三讲 Tensorflow框架的助教笔记。
Python代码实现:
随机产生 32 组生产出的零件的体积和重量,训练 3000 轮,每 500 轮输出一次损失函数。
1 import tensorflow as tf 2 import numpy as np 3 BATCH_SIZE = 8 # 一次不能喂太多数据 4 SEED = 23455 # 产生与视频教程中统一的随机数 5 6 #基于seed产生随机数 7 rdm = np.random.RandomState(SEED) 8 #随机数返回32行2列的矩阵 表示32组 体积和重量 作为输入数据集 9 X = rdm.rand(32,2) 10 #从X这个32行2列的矩阵中 取出一行 判断如果和小于1 给Y赋值1 如果和不小于1 给Y赋值0 (这里只是人为的定义) 11 #作为输入数据集的标签(正确答案) 12 Y_ = [[int(x0 + x1 < 1)] for (x0, x1) in X] 13 print "X:\n",X 14 print "Y_:\n",Y_ 15 16 #1定义神经网络的输入、参数和输出,定义前向传播过程。 17 x = tf.placeholder(tf.float32, shape=(None, 2)) 18 y_= tf.placeholder(tf.float32, shape=(None, 1)) 19 20 w1= tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1)) 21 w2= tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1)) 22 23 a = tf.matmul(x, w1) 24 y = tf.matmul(a, w2) 25 26 #2定义损失函数及反向传播方法。 27 loss_mse = tf.reduce_mean(tf.square(y-y_)) 28 train_step = tf.train.GradientDescentOptimizer(0.001).minimize(loss_mse) # 三种优化方法选择一个就可以 29 #train_step = tf.train.MomentumOptimizer(0.001,0.9).minimize(loss_mse) 30 #train_step = tf.train.AdamOptimizer(0.001).minimize(loss_mse) 31 32 #3生成会话,训练STEPS轮 33 with tf.Session() as sess: 34 init_op = tf.global_variables_initializer() 35 sess.run(init_op) 36 # 输出目前(未经训练)的参数取值。 37 print "w1:\n", sess.run(w1) 38 print "w2:\n", sess.run(w2) 39 print "\n" 40 41 # 训练模型。 42 STEPS = 3000 43 for i in range(STEPS): 44 start = (i*BATCH_SIZE) % 32 45 end = start + BATCH_SIZE 46 sess.run(train_step, feed_dict={x: X[start:end], y_: Y_[start:end]}) 47 if i % 500 == 0: 48 total_loss = sess.run(loss_mse, feed_dict={x: X, y_: Y_}) 49 print("After %d training step(s), loss_mse on all data is %g" % (i, total_loss)) 50 51 # 输出训练后的参数取值。 52 print "\n" 53 print "w1:\n", sess.run(w1) 54 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。
四、搭建神经网络的过程
通过以上的内容,我们可以梳理一下搭建简单神经网络的步骤:
(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={ })
以上是搭建简单神经网络的笔记
本人初学者,有任何错误欢迎指出,谢谢。