我的环境是ubuntu18.04+python3.6+tensorflow-1.5.0-gpu,gpu版本的tensorflow需要安装对应的cuda和cudnn,麻烦一点,但配好以后用其他框架就不用再配置了。tensorflow-1.5.0对应的cuda版本是9.0,cudnn版本是7.0,cpu版本的tensorflow则不需要安装cuda和cudnn。
搭建神经八股,这里的八股指的是搭建神经网络有一个固定的步骤,即
- 准备数据集,提取特征,作为输入喂入神经网络NN(Netural Network)
- 搭建NN 结构,从输入到输出(先搭建计算图,再用会话执行)
- 大量特征数据喂给神经网络,迭代优化参数
- 使用训练好的模型预测和分类
- 一些基本概念
张量:张量就是多维数组(列表),“阶”表示张量的维度
- 0阶张量:又叫标量,是一个单独的数 例如:a=123
- 1阶张量:称作向量,表示一个一维数组 例如:b=[1,2,3]
- 2阶张量:称作矩阵,表示一个二维数组 例如:c=[[1,2,3],[4,5,6]]
- n阶张量就是看方括号的层数,有几层就是几阶
我们把上面的例子在tensorflow中打印出来看结果如何
import tensorflow as tf #引入tensorflow模块
a=tf.constant(123) #tf.constant 表示这是一个常量
b=tf.constant([1,2,3])
c=tf.constant([[1.0,2.0,3.0],[4.0,5.0,6.0]])
print(a)
print(b)
print(c)
- a的打印结果为Tensor("Const:0", shape=(), dtype=int32)
- b的打印结果为Tensor("Const_1:0", shape=(3,), dtype=int32)
- c的打印结果为Tensor("Const_2:0", shape=(2, 3), dtype=float32)
第一项是张量的名字
第二项中a的shape什么都没有,这是一个标量,b的shape表示一个长度为3的一维数组,c的shape表示这是一个2行3列的矩阵
最后一项是数据类型,可以看到tensorflow中有两种数据类型,tf.int32和tf.float32。
神经网络的计算过程是基本的乘加运算,下图表示一个神经元
x1和x2表示输入,w1、w2分别是x1到y和x2到y的权重,y=x1*w1+x2*w2
用代码实现以上过程
import tensorflow as tf
x=tf.constant([[1.0,2.0]]) #x是一个一行两列的矩阵
w=tf.constant([[3.0],[4.0]]) #w是一个两行一列的矩阵
y=tf.matmul(x,w) #用tf.matmul实现矩阵相乘,得出的应该是一个一行一列的矩阵
print(y)
打印出结果:Tensor("MatMul:0", shape=(1, 1), dtype=float32)
可以看到结果显示这是一个张量,只搭建了计算过程,没有计算结果,如果想要运算,需要引入会话(Session)模块,
引入的方式为
with tf.Session() as sess:
print(sess.run(y)) #这里需要缩进
或者
sess=tf.Session()
print(sess.run(y))
看一下实现过程
import tensorflow as tf
x=tf.constant([[1.0,2.0]]) #x是一个一行两列的矩阵
w=tf.constant([[3.0],[4.0]]) #w是一个两行一列的矩阵
y=tf.matmul(x,w) #用tf.matmul实现矩阵相乘,得出的应该是一个一行一列的矩阵
print(y)
sess=tf.Session()
print(sess.run(y))
打印出计算结果[[11.]]
神经网络的参数
神经网络的参数是指神经元线上的权重w,用变量表示,一般会先随机生成这些参数。生成参数的方法是让w等于tf.Variable,把生成的方式写在括号里。神经网络中常用的生成随机数的函数有:
tf.random_normal() | 生成正态分布随机数 |
tf.truncated_normal() | 生成去掉过大偏离点的正态分布随机数 |
tf.random_uniform() | 生成均匀分布随机数 |
tf.zeros | 生成全0数组 |
tf.ones | 生成全1数组 |
tf.fill | 生成全定值随机数组 |
tf.constant | 生成直接给定值的随机数组 |
w1=tf.Variable(tf.random_normal([2,3],stddev=2,mean=0,seed=1))
#生成正态分布随机数,形状两行三列,标准差是2,均值是0,随机种子是1
w2=tf.Variable(tf.truncated_normal([2,3],stddev=2,mean=0,seed=1))
#生成去掉偏离过大的正态分布,即随机生成的数超过两个标准差,这个数据将重新生成
w3=tf.Variable(tf.random_uniform(shape=7,minval=0,maxval=1,dtype=tf.int32,seed=1))
#从一个均匀分布[minval,maxval]中随机采样,定义域是前闭后开,和python的切片一样,包前不包后
w4=tf.zeros([3,2])#生成[[0,0],[0,0],[0,0]]
w5=tf.ones([3,2])#生成[[1,1],[1,1],[1,1]]
w6=tf.fill([3,2],6)#生成[[6,6],[6,6],[6,6]]
w7=tf.constant([3,2,1])#生成[3,2,1]
注意:
- 随机种子去掉每次生成的随机数将不一样
- 如果没有特殊要求,标准差、均值、随机种子都可以不写
了解了基本的知识,现在可以搭建神经网络了
前向传播:前向传播就是搭建模型的计算过程,让模型具有推理能力,可以针对一组输入给出相应的输出
假如生产一批零件,体积为x1,重量为x2,体积和重量就是我们所选的特征,把它们喂入神经网络,当体积和重量这组数据走过神经网络后会得到一个输出,假设输入的特征值是:体积0.7,重量0.5
上面是一个两层的神经网络,为什么是两层?因为神经网络的层数指的是计算层,不包括输入层。
X是输入为1x2的矩阵,表示一次输入两个特征,这组特征包含了体积和重量两个元素。
W为待优化的参数,对于第一层的w前面有两个节点,后面有三个节点,w应该是两行三列的矩阵,这样表示
括号里的1表示第一层,下标为:前节点编号,后节点编号
a=X*W1,a表示第一层网络,
在tensorflow中这样表示:
a=tf.matmul(X,W1)
W2为三行一列的矩阵
输出y=a*W2
y=tf.matmul(a,W2)
反向传播:训练模型参数,在所有参数上使用梯度下降,使NN模型在训练数据上的损失函数最小
损失函数(loss):计算得到的预测值y与已知答案y_的差距,比较常见的损失函数是均方误差,即误差的平方和求平均
反向传播训练方法:以减少loss为优化目标,有梯度下降,momentum优化器、adam优化器等方法。
这三种优化方法用tensorflow的函数表示为:
train_step=tf.GradientDescentOptimizer(learning_rate).minimize(loss)
train_step=tf.MomentumOptimizer(learning_rate,momentum).minimize(loss)
train_step=tf.AdamOptimizer(learning_rate).minimize(loss)
学习率:即参数更新的幅度,学习率选择过大会造成震荡不收敛,过小会造成收敛速度慢,可以填一个较小的值填入,如0.01,0.001。
梯度下降的基本原理这里讲的比较好,以后再进行深入理解和公式的推导。
下面是搭建神经八股的完整代码
#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)
#从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)
#定义神经网络的输入、参数和输出,定义前向传播过程
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)
#定义损失函数及反向传播方法
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)
#train_step=tf.train.AdadeltaOptimizer(0.001).minimize(loss)
#生成会话,训练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))
#训练模型
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]})
if i %500==0:
total_loss=sess.run(loss,feed_dict={x:X,y_:Y})
print("After %d training steps(s),loss on all data is %g"%(i,total_loss))
#输出训练后的参数
print('\n')
print('w1:\n',sess.run(w1))
print('w2:\n', sess.run(w2))
输出的结果为