chapter3:TensorFlow入门
date:2018.04.15下午
1、创建会话的三种方式E:\Workspace\PycharmProjects\test\ch3_1_2_tf_graph
a.
sess = tf.Session()
sess.run(……)
sess.close()
b.
with tf.Session() as sess:
sess.run(……)
c.
sess = tf.Session()
print(…….eval())
2、 with tf.variable_scope("",reuse = True):
为了节约变量存储空间,通过共享变量作用域(variable_scope) 来实现共享变量。设置 reuse=True 来 再次调用该共享变量作用域(variable_scope)
3、矩阵乘法:tf.matmul()
4、变量(tf.Variable)的作用:保存和更新神经网络的参数E:\Workspace\PycharmProjects\test\
tf.random_normal([2,3],stddev = 2):产生一个2*3的矩阵,矩阵中的元素均值为0,标准差为2的平均数
tf.truncated_normal()
tf.random_uniform()
tf.random_gamma()
tf.zeros()
tf.ones()
tf.fill()
tf.constant()
5、初始化所有变量
init_op = tf.initialize_all_variables()
sess.run(init_op)
6、tensorflow所有变量会被自动加入到GraphKeys.VARIABLES集合中,通过tf.all_variables函数可以拿到当前计算图上的所有变量,
通过tf.trainable_variables函数得到所有需要优化的参数,tensorflow中提供的神经网络优化算法会将GraphKeys.TRAINABLE_VARIABLES集合中的变量作为默认的优化对象
7、变量的类型不可更改,维度通过tf.assign(validate_shape=False)可以更改,但比较少见。
8、placeholder相当于定义了一个位置,这个位置中的数据在程序运行时指定,减少计算图中的节点数。
placeholder定义是需要制定数据类型(不可变),维度可变不必给出(但如果维度确定,给出可降低错误概率),name也可不必给出
在运行时print(sess.run(y,feed_dict = {x:[[0.7,0.9]]})),用feed_dict来指定x的取值,feed_dict是一个字典
9、cross_entropy真实值和预测值之间的交叉熵,常用 cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y,1e-10,1.0)))
learning_rate:学习率
train_step定义反响传播的优化方法,常用的有tf.train.GradientDescentOptimizer
、tf.train.AdamOptimizer
、tf.train.MomentumOptimizer
chapter4:深层神经网络
date:2018.04.24上午队值、晚饭后
1、激活函数去线性化
2、多层网络有组合特赠提取的功能,解决异或问题
3、损失函数(通过损失函数优化神经网络效果)
A.交叉熵(刻画两个概率分布之间的距离)
(一)分类问题
不对称H(p,q)≠H(q,p)前者通过概率分布q表达概率分布p的困难程度,p代表正确答案,q代表预测值。交叉熵值越小,概率分布越接近。
"""
y_表示正确结果,y表示预测结果。tf.clip_by_value可以将一个张量中的数值限制在一个范围内tf.clip_by_value(A, min, max):
输入一个张量A,把A中的每一个元素的值都压缩在min和max之间。小于min的让它等于min,大于max的元素的值等于max。
tf.log():对张量中所有元素依次求对数
交叉熵中的乘法直接通过*相称,是元素之间的乘法
y_ * tf.log(tf.clip_by_value(y,1e-10,1.0))得到的是n*m的二维矩阵,n为一个batch中的样例数量,m为分类类别的数量。
根据交叉熵的公式,应该将每行中的m个结果相加得到所有样例的交叉熵,然后对这n行取平均得到一个batch的平均交叉熵。
但是,分类问题的类别数不变,可以对整个矩阵做平均tf.reduce_mean()
Tensorflow将交叉熵和softmax做了封装,tf.nn.softmax_cross_entropy_with_logits(y,y_):softmax回归之后的交叉熵损失函数
"""
cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y,1e-10,1.0)))
(二)回归问题
预测,一般只有一个输出节点,最常用的损失函数是均方误差
mse=tf.reduce_mean(tf.square(y_-y))
B.softmax层(将神经网络的输出变成一个概率分布)
softmax(y)=y'=e^y/(Σe^y)
原始网络的输出被作为置信度生成新的输出,这个输出满足概率分布的要求
C.自定义损失函数
(一)tf.greater()和tf.where()见ch_4_2_2_loss.py
import tensorflow as tf
v1 = tf.constant([1.0,2.0,3.0,4.0])
v2 = tf.constant([4.0,3.0,2.0,1.0])
#交互式环境下直接构建默认会话
sess=tf.InteractiveSession()
#tf.greater()输入的是两个张量,比较大小,并返回结果(true/false)
#[False False True True]
print(tf.greater(v1,v2).eval())
#tf.where()输入三个参数,第一个为选择条件,为true时,结果为第二个参数的值,false时,结果为第三个参数的值
#[4. 3. 3. 4.]
print(tf.where(tf.greater(v1,v2),v1,v2).eval())
sess.close()
(二)样例
见ch_4_2_2_loss_example.py
4、优化算法
A.神经网络的优化过程
step1:通过前向算法得到预测值
step2:通过反向传播算法计算损失函数对每一个参数的梯度,再根据梯度和学习率使用SGD更新参数
Note:
Note1:GD并不能保证达到全局最优解,只有损失函数为凸函数时才能
Note2:梯度下降计算量太大,一般采用SGD每次只优化某一条数据上的损失函数,但是因为数量小了,甚至不能保证达到局部最优
因此,在实际操作中一般每次计算一个batch的损失函数
5、学习率(控制参数更新的速度)
A.指数衰减方法设置学习率
在训练前期快速接近较优解,后期又不会有很大的波动,从而接近局部最优
decayed_learning_rate = learning_rate * decay_rate^(global_step / decay_steps)
1、decayed_learning_rate:每一轮优化时使用的学习率
2、learning_rate:初始学习率
3、decay_rate:衰减系数
4、decay_steps:衰减速度,通常代表完整的使用一遍训练数据所需要的迭代轮数,即总训练样本数除以每一个batch中的训练样本数
每训练完一遍,学习率就减小一次,是的训练数据集中的所有数据对模型训练有相同的作用
B.tf.train.exponential_decay函数介绍:
global_step = tf.Variable(0)
learning_rate = tf.train.exponential_decay(0.1,global_step,100,0.96,staircase = True)
#初始学习率0.1,因为staircase = True(使学习率成为阶梯函数),每训练100轮后,学习率*0.96,衰减系数和衰减速度一般根据经验设置
6、过拟合问题
A.正则化(在损失函数中加入刻画模型复杂度的指标)
优化损失函数J(θ)+λR(w),其中R(w)刻画模型复杂程度,λ表示模型复杂损失在总损失中的比例
一般θ为一个神经网络中所有参数,但是模型复杂度一般只由权重决定
R(w)一般有两种:(思想:通过限制权重的大小,是的模型不能任意拟合训练数据中的随机噪音)
L1正则化:让参数变得更细数,即更多参数变为0;不可导;更复杂;tf.contrib.layers.l1_regularizer()
L2正则化:不会让参数更稀疏tf.contrib.layers.l2_regularizer()
原因:两种 regularization 能不能把最优的 x 变成 0,取决于原先的费用函数在 0 点处的导数。
如果本来导数不为 0,那么施加 L2 regularization 后导数依然不为 0,最优的 x 也不会变成 0。
而施加 L1 regularization 时,只要 regularization 项的系数 C 大于原先费用函数在 0 点处的导数的绝对值,x = 0 就会变成一个极小值点
链接:https://www.zhihu.com/question/37096933/answer/70426653
eg:loss = tf.reduce_mean(tf.square(y_-y))+tf.contrib.layers.l2_regularizer(lambda)(w)
第一部分是均方误差损失函数,刻画了模型在训练数据上的表现
第二部分是正则化,其中lambda代表λ,为正则化项的权重,w为需要计算正则化损失的参数
B.集合(collection):增加复杂网络损失函数正则化部分的可读性
代码:ch4_4_2_l2_regularizer_collection.py
7、滑动平均模型
在使用SGD训练神经网络时,使用滑动平均模型有利于提高模型在训练集上的表现
A. tf.train.ExponentialMovingAverage():
衰减率decay:控制模型更新性能的速度
tf.train.ExponentialMovingAverage()对每一个变量会维护一个影子变量(shadow_variable),
其初始值就是变量的初始值,每次运行变量更新时,影子变量会更新为:
shadow_variable = decay*shadow_variable+(1-daecay)*variable
shadow_variable:影子变量
variable:待更新的变量
decay:衰减率(决定模型的更新速度,越大模型越稳定)
tf.train.ExponentialMovingAverage()还提供了num_updates来动态设置decay的大小,每次的衰减率为:
min{decay,(1+num_updates)/(10+num_updates)}
B.代码:
ch_4_4_3_exponential_moving_average.py
chapter5 mnist数字识别问题
date:2018.04.24晚上
1、代码:mnist.py
主要步骤:
A.配置神经网络参数(输入输出节点数、初始学习率、学习率衰减率、正则化损失系数、训练轮数、滑动平均衰减率……)
B.训练:
1、定义输入、正确标签、权重、偏置项等
2、计算前向传播结果
如果有滑动平均的话(globa_step不可训练、初始化滑动平均类、训练列表、计算前向传播结果)
3、损失函数
a.计算交叉熵
b.计算正则化项损失
c.学习率
d.优化损失函数
4、更新滑动平均的变量和反向传播更新参数(tf.group)
5、判断是否正确,正确率
6、建立会话开始训练,计算训练正确率,训练结束后计算测试正确率
主要的方法:滑动平均、正则化、指数衰减学习率、隐藏层、激活函数
2、
chapter6 图像识别与卷积神经网络
date:2018.04.23晚上
1、基础知识:
(1)CNN与全连接
卷积神经网络相邻两层之间只有部分节点相连,为了展示每一层神经元的维度,一般会将每一层卷积层的节点组织成一个三维矩阵。
全连接处理图像,参数太多。而参数过多会导致计算速度减慢,过拟合
(2)结构
输入层
卷积层(一般通过卷积层的节点矩阵会变得更深,得到更高抽象的特征)
A.过滤器filter:
每一个卷积层中使用的过滤器参数一样(参数共享)
将当前层神经网络上的子节点转为下一层上的一个单位节点矩阵(长宽=1深度不限);
尺寸一般为3*3或5*5(过滤器输入节点矩阵大小),还有另外一个参数深度(输出单位节点矩阵的深度)
B.zero-padding(避免尺寸变化)
C.参数个数
和图片大小无关,之和过滤器的尺寸、深度、但当前层节点矩阵的深度有关
D.tensorflow实现卷积层
import tensorflow as tf
"""
通过tf.get_variable的方式创建filter的权重变量和偏置项变量。
由于卷积层的参数个数只与过滤器的尺寸、深度以及当前层节点矩阵的深度有关,所以声明的filter_weight是一个四维矩阵。
前面两个维度代表了过滤器尺寸,第三个维度代表当前层深度,第四个维度代表过滤器深度(下一层单位节点矩阵深度)
"""
filter_weight = tf.get_variable('weights',[5,5,3,16],initializer=tf.truncated_normal_initializer(stddev=0.1))
#偏置项第二个参数代表过滤器深度
biases = tf.get_variable('biases',[16],initializer=tf.constant_initializer(0.1))
"""
tf.nn.conv2d实现卷积层前向传播算法。四个参数:
1、当前层的节点矩阵(四维矩阵,后面三个维度对应一个节点矩阵,第一个维度代表一个输入batch。)
如input[0,:,:,:]表示第一张图片,input[1,:,:,:]表示第二张图片
2、卷积层权重参数
3、步长(长度为4的数组,但是因为步长只与矩阵的长和宽有关,所以第一个和第四个数字必须是1)
4、zero-padding类型(SAME表示全0填充,VALID表示不填充)
"""
conv = tf.nn.conv2d(input,filter_weight,strides=[1,1,1,1],padding = 'SAME')
"""
tf.nn.bias_add给每一个节点加上偏置项。
注意:不能直接用加法,因为矩阵不同位置上的节点都需要加上同样的偏置项
"""
bias = tf.nn.bias_add(conv,biases)
#通过relu激活对结果去线性化
actived_conv = tf.nn.relu(bias)
池化层(不改变三维矩阵的深度,但可以缩小矩阵大小,缩小最后全连接层中节点个数,加快速度,减少过拟合)
A.常用方法:
max pooling、average pooling、mean pooling, hybrid pooling、sum-pooled convolutional features(SPoC)、cross-dimensional weighting and pooling features(CroW)
B.过滤器(filter)
也需要人工设定过滤器的尺寸、是否使用全0填充、过滤器移动的步长等
区别:卷积层的过滤器横跨整个深度,但是池化层的过滤器只影响一个深度上的节点,还需要在深度上移动
C.tensorflow实现池化层
"""
tf.nn.max_pool与tf.nn.conv2d类似,实现了最大池化层的前向传播过程(或者tf.nn.avg_pool)
1、当前层的节点矩阵(参数是一个四维矩阵),类似于tf.nn.conv2d
后面三个维度对应一个节点矩阵,第一个维度代表一个输入batch。
如input[0,:,:,:]表示第一张图片,input[1,:,:,:]表示第二张图片
2、过滤器尺寸(第一个和第四个数字必须是1)
因为池化层的过滤器不能横跨深度,一般是[1,2,2,1]或[1,3,3,1]
3、步长(长度为4的数组,但是因为步长只与矩阵的长和宽有关,所以第一个和第四个数字必须是1)
所以池化层不能减少节点矩阵的深度
4、zero-padding类型(SAME表示全0填充,VALID表示不填充)
"""
pool = tf.nn.max_pool(actived_conv,ksize=[1,3,3,1],strides=[1,2,2,1],padding= 'SAME')
全连接层
softmax层
3、LeNet-5模型(应用于mnist)
Page149-150
link knowledge:
其他模型卷积神经网络架构:
A.卷积层
convX-Y:过滤器的边长为X,深度为Y,边长一般选1或3,少有5
过滤器深度逐层递增,一般每经过一次池化层深度*2
卷积层步长一般为1
B.池化层
最多用到max pooling
过滤器边长一般为2或3,步长一般也为2或3
4、inception架构(将不同的卷积层通过并联的方式结合在一起)
先用不同尺寸的过滤器处理输入矩阵,都经过全0填充且步长为1,则输出矩阵与输入矩阵大小相同,拼接成一个更深的输出矩阵
tensorflow-slim工具的用法如158页,大大减少冗余代码