转载请注明作者:梦里风林

Github工程地址:https://github.com/ahangchen/GDLnotes

欢迎star,有问题可以到Issue区讨论

官方教程地址

视频/字幕下载

全连接神经网络

辅助阅读:TensorFlow中文社区教程 - 英文官方教程

代码见:full_connect.py

Linear Model

  • 加载lesson 1中的数据集
  • 将Data降维成一维,将label映射为one-hot encoding
def reformat(dataset, labels):
dataset = dataset.reshape((-1, image_size * image_size)).astype(np.float32)
# Map 0 to [1.0, 0.0, 0.0 ...], 1 to [0.0, 1.0, 0.0 ...]
labels = (np.arange(num_labels) == labels[:, None]).astype(np.float32)
return dataset, labels

TensorFlow Graph

  • 使用梯度计算train_loss,用tf.Graph()创建一个计算单元

    • 用tf.constant将dataset和label转为tensorflow可用的训练格式(训练中不可修改)
    • 用tf.truncated_normal生成正太分布的数据,作为W的初始值,初始化b为可变的0矩阵
    • 用tf.variable将上面的矩阵转为tensorflow可用的训练格式(训练中可以修改)
    • 用tf.matmul实现矩阵相乘,计算WX+b,这里实际上logit只是一个变量,而非结果
    • 用tf.nn.softmax_cross_entropy_with_logits计算WX+b的结果相较于原来的label的train_loss,并求均值
    • 使用梯度找到最小train_loss
  optimizer = tf.train.GradientDescentOptimizer(0.5).minimize(loss)
  • 计算相对valid_dataset和test_dataset对应的label的train_loss

上面这些变量都是一种Tensor的概念,它们是一个个的计算单元,我们在Graph中设置了这些计算单元,规定了它们的组合方式,就好像把一个个门电路串起来那样

TensorFLow Session

Session用来执行Graph里规定的计算,就好像给一个个门电路通上电,我们在Session里,给计算单元冲上数据,That’s Flow.

  • 重复计算单元反复训练800次,提高其准确度

    • 为了快速查看训练效果,每轮训练只给10000个训练数据(subset),恩,每次都是相同的训练数据
    • 将计算单元graph传给session
    • 初始化参数
    • 传给session优化器 - train_loss的梯度optimizer,训练损失 - train_loss,每次的预测结果,循环执行训练
  with tf.Session(graph=graph) as session:
tf.initialize_all_variables().run()
for step in range(num_steps):
_, l, predictions = session.run([optimizer, loss, train_prediction])
  • 在循环过程中,W和b会保留,并不断得到修正
  • 在每100次循环后,会用验证集进行验证一次,验证也同时修正了一部分参数
  valid_prediction.eval()
  • 最后用测试集进行测试
  • 注意如果lesson 1中没有对数据进行乱序化,可能训练集预测准确度很高,验证集和测试集准确度会很低

这样训练的准确度为83.2%

SGD

  • 每次只取一小部分数据做训练,计算loss时,也只取一小部分数据计算loss

    • 对应到程序中,即修改计算单元中的训练数据,

      • 每次输入的训练数据只有128个,随机取起点,取连续128个数据:
  offset = (step * batch_size) % (train_labels.shape[0] - batch_size)
batch_data = train_dataset[offset:(offset + batch_size), :]
batch_labels = train_labels[offset:(offset + batch_size), :]
  • 由于这里的数据是会变化的,因此用tf.placeholder来存放这块空间
  tf_train_dataset = tf.placeholder(tf.float32,
shape=(batch_size, image_size * image_size))
tf_train_labels = tf.placeholder(tf.float32, shape=(batch_size, num_labels))
  • 计算3000次,训练总数据量为384000,比之前8000000少

准确率提高到86.5%,而且准确率随训练次数增加而提高的速度变快了

神经网络

  • 上面SGD的模型只有一层WX+b,现在使用一个RELU作为中间的隐藏层,连接两个WX+b

    • 仍然只需要修改Graph计算单元为
      Y = W2 * RELU(W1*X + b1) + b2
  • 为了在数学上满足矩阵运算,我们需要这样的矩阵运算:
      [n * 10] = RELU([n * 784] · [784 * N] + [n * N]) · [N * 10] + [n * 10]
  • 这里N取1024,即1024个隐藏结点
  • 于是四个参数被修改
  weights1 = tf.Variable(
tf.truncated_normal([image_size * image_size, hidden_node_count]))
biases1 = tf.Variable(tf.zeros([hidden_node_count]))
weights2 = tf.Variable(
tf.truncated_normal([hidden_node_count, num_labels]))
biases2 = tf.Variable(tf.zeros([num_labels]))
  • 预测值计算方法改为
  ys = tf.matmul(tf_train_dataset, weights1) + biases1
hidden = tf.nn.relu(ys)
logits = tf.matmul(hidden, weights2) + biases2
  • 计算3000次,可以发现准确率一开始提高得很快,后面提高速度变缓,最终测试准确率提高到88.8%

深度神经网络实践

代码见nn_overfit.py

优化

Regularization

在前面实现的RELU连接的两层神经网络中,加Regularization进行约束,采用加l2 norm的方法,进行调节:

代码实现上,只需要对tf_sgd_relu_nn中train_loss做修改即可:

  • 可以用tf.nn.l2_loss(t)对一个Tensor对象求l2 norm
  • 需要对我们使用的各个W都做这样的计算(参考tensorflow官方example
l2_loss = tf.nn.l2_loss(weights1) + tf.nn.l2_loss(weights2)
  • 添加到train_loss上
  • 这里还有一个重要的点,Hyper Parameter: β
    • 我觉得这是一个拍脑袋参数,取什么值都行,但效果会不同,我这里解释一下我取β=0.001的理由
    • 如果直接将l2_loss加到train_loss上,每次的train_loss都特别大,几乎只取决于l2_loss
    • 为了让原本的train_loss与l2_loss都能较好地对参数调整方向起作用,它们应当至少在同一个量级
    • 观察不加l2_loss,step 0 时,train_loss在300左右
    • 加l2_loss后, step 0 时,train_loss在300000左右
    • 因此给l2_loss乘0.0001使之降到同一个量级
  loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits, tf_train_labels)) + 0.001 * l2_loss
  • 所有其他参数不变,训练3000次,准确率提高到92.7%
  • 黑魔法之所以为黑魔法就在于,这个参数可以很容易地影响准确率,如果β = 0.002,准确率提高到93.5%

OverFit问题

在训练数据很少的时候,会出现训练结果准确率高,但测试结果准确率低的情况

  • 缩小训练数据范围:将把batch数据的起点offset的可选范围变小(只能选择0-1128之间的数据):
offset_range = 1000
offset = (step * batch_size) % offset_range
  • 可以看到,在step500后,训练集就一直是100%,验证集一直是77.6%,准确度无法随训练次数上升,最后的测试准确度是85.4%

DropOut

采取Dropout方式强迫神经网络学习更多知识

参考aymericdamien/TensorFlow-Examples中dropout的使用

  • 我们需要丢掉RELU出来的部分结果
  • 调用tf.nn.dropout达到我们的目的:
keep_prob = tf.placeholder(tf.float32)
if drop_out:
hidden_drop = tf.nn.dropout(hidden, keep_prob)
h_fc = hidden_drop
  • 这里的keep_prob是保留概率,即我们要保留的RELU的结果所占比例,tensorflow建议的语法是,让它作为一个placeholder,在run时传入
  • 当然我们也可以不用placeholder,直接传一个0.5:
if drop_out:
hidden_drop = tf.nn.dropout(hidden, 0.5)
h_fc = hidden_drop
  • 这种训练的结果就是,虽然在step 500对训练集预测没能达到100%(起步慢),但训练集预测率达到100%后,验证集的预测正确率仍然在上升
  • 这就是Dropout的好处,每次丢掉随机的数据,让神经网络每次都学习到更多,但也需要知道,这种方式只在我们有的训练数据比较少时很有效
  • 最后预测准确率为88.0%

Learning Rate Decay

随着训练次数增加,自动调整步长

  • 在之前单纯两层神经网络基础上,添加Learning Rate Decay算法
  • 使用tf.train.exponential_decay方法,指数下降调整步长,具体使用方法官方文档说的特别清楚
  • 注意这里面的cur_step传给优化器,优化器在训练中对其做自增计数
  • 与之前单纯两层神经网络对比,准确率直接提高到90.6%

Deep Network

增加神经网络层数,增加训练次数到20000

  • 为了避免修改网络层数需要重写代码,用循环实现中间层
# middle layer
for i in range(layer_cnt - 2):
y1 = tf.matmul(hidden_drop, weights[i]) + biases[i]
hidden_drop = tf.nn.relu(y1)
if drop_out:
keep_prob += 0.5 * i / (layer_cnt + 1)
hidden_drop = tf.nn.dropout(hidden_drop, keep_prob)
  • 初始化weight在迭代中使用
for i in range(layer_cnt - 2):
if hidden_cur_cnt > 2:
hidden_next_cnt = int(hidden_cur_cnt / 2)
else:
hidden_next_cnt = 2
hidden_stddev = np.sqrt(2.0 / hidden_cur_cnt)
weights.append(tf.Variable(tf.truncated_normal([hidden_cur_cnt, hidden_next_cnt], stddev=hidden_stddev)))
biases.append(tf.Variable(tf.zeros([hidden_next_cnt])))
hidden_cur_cnt = hidden_next_cnt
  • 第一次测试时,用正太分布设置所有W的数值,将标准差设置为1,由于网络增加了一层,寻找step调整方向时具有更大的不确定性,很容易导致loss变得很大
  • 因此需要用stddev调整其标准差到一个较小的范围(怎么调整有许多研究,这里直接找了一个来用)
  stddev = np.sqrt(2.0 / n)
  • 启用regular时,也要适当调一下β,不要让它对原本的loss造成过大的影响
  • DropOut时,因为后面的layer得到的信息越重要,需要动态调整丢弃的比例,到后面的layer,丢弃的比例要减小
keep_prob += 0.5 * i / (layer_cnt + 1)
  • 训练时,调节参数,你可能遇到消失(或爆炸)的梯度问题

    训练到一定程度后,梯度优化器没有什么作用,loss和准确率总是在一定范围内徘徊
  • 官方教程表示最好的训练结果是,准确率97.5%,
  • 我的nn_overfit.py开启六层神经网络,

    启用Regularization、DropOut、Learning Rate Decay,

    训练次数20000(应该还有再训练的希望,在这里虽然loss下降很慢了,但仍然在下降),训练结果是,准确率95.2%

觉得我的文章对您有帮助的话,给个star可好?

土豪可以打赏支持,一分也是爱:

TensorFlow 深度学习笔记 TensorFlow实现与优化深度神经网络的更多相关文章

  1. TensorFlow 深度学习笔记 从线性分类器到深度神经网络

    转载请注明作者:梦里风林 Github工程地址:https://github.com/ahangchen/GDLnotes 欢迎star,有问题可以到Issue区讨论 官方教程地址 视频/字幕下载 L ...

  2. TensorFlow深度学习笔记 文本与序列的深度模型

    Deep Models for Text and Sequence 转载请注明作者:梦里风林 Github工程地址:https://github.com/ahangchen/GDLnotes 欢迎st ...

  3. 吴恩达深度学习笔记(五) —— 优化算法:Mini-Batch GD、Momentum、RMSprop、Adam、学习率衰减

    主要内容: 一.Mini-Batch Gradient descent 二.Momentum 四.RMSprop 五.Adam 六.优化算法性能比较 七.学习率衰减 一.Mini-Batch Grad ...

  4. 深度学习笔记:优化方法总结(BGD,SGD,Momentum,AdaGrad,RMSProp,Adam)

    深度学习笔记:优化方法总结(BGD,SGD,Momentum,AdaGrad,RMSProp,Adam) 深度学习笔记(一):logistic分类 深度学习笔记(二):简单神经网络,后向传播算法及实现 ...

  5. CUDA上深度学习模型量化的自动化优化

    CUDA上深度学习模型量化的自动化优化 深度学习已成功应用于各种任务.在诸如自动驾驶汽车推理之类的实时场景中,模型的推理速度至关重要.网络量化是加速深度学习模型的有效方法.在量化模型中,数据和模型参数 ...

  6. Google TensorFlow深度学习笔记

    Google Deep Learning Notes Google 深度学习笔记 由于谷歌机器学习教程更新太慢,所以一边学习Deep Learning教程,经常总结是个好习惯,笔记目录奉上. Gith ...

  7. 截图:【炼数成金】深度学习框架Tensorflow学习与应用

    创建图.启动图 Shift+Tab Tab 变量介绍: F etch Feed 简单的模型构造 :线性回归 MNIST数据集 Softmax函数 非线性回归神经网络   MINIST数据集分类器简单版 ...

  8. 深度学习之TensorFlow构建神经网络层

    深度学习之TensorFlow构建神经网络层 基本法 深度神经网络是一个多层次的网络模型,包含了:输入层,隐藏层和输出层,其中隐藏层是最重要也是深度最多的,通过TensorFlow,python代码可 ...

  9. 【原创 深度学习与TensorFlow 动手实践系列 - 4】第四课:卷积神经网络 - 高级篇

    [原创 深度学习与TensorFlow 动手实践系列 - 4]第四课:卷积神经网络 - 高级篇 提纲: 1. AlexNet:现代神经网络起源 2. VGG:AlexNet增强版 3. GoogleN ...

随机推荐

  1. 【转】ubuntu下putty的复制粘贴 -- 不错

    原文网址:http://www.nwber.com/?p=165 今天在ubutnu下想用putty玩玩,突然发现在windows里直接点击右键的复制居然不管用了,调设置也没有用.这可麻烦了,要是手动 ...

  2. LeeCode-Majority Element

    Given an array of size n, find the majority element. The majority element is the element that appear ...

  3. tangible T4 Editor 2.2.3 plus modeling tools for VS 2012 扩展名

    tangible T4 Editor 2.2.3 plus modeling tools for VS 2012 扩展名 tangible T4 Editor 2.2.3 plus modeling ...

  4. 《如何让TT T4模板输出多个文件(VS2010中)》-- access911.net 文章

    <如何让TT T4模板输出多个文件(VS2010中)>-- access911.net 文章   问题:   VS2010中自带的 TT 模板功能挺好用,但是如何定义其输出的目录,或者如何 ...

  5. iOS Get方式带中文不能请求网络

    今天发现一个蛋疼的问题,使用ASIHTTPRequest Get方式请求数据时候带中文,iOS客户端不能正确进行网络请求. NSURL *url = [NSURL URLWithString:@htt ...

  6. ajax+json+java

    1.首先下载json所以依赖的包, Json-lib 最新版 json-lib-2.3-jdk15.jar,其官方网站是:http://json-lib.sourceforge.net/可以直接dow ...

  7. java笔记之String的应用

    说来这String字符串也是运用广泛了,但是String的一些使用方法你是否能够了解清楚呢? 这是我这几天来整理的String笔记,其实这也是不全面的,要想深入了解,还得自己去oracle官网看JDK ...

  8. 熬之滴水穿石:Spring--精简的J2EE(5)

                                   47--Spring的MVC 在Spring的框架中也存在MVC这样的模式,在Spring下有2个这样的控制器一个叫Controller, ...

  9. Servlet页面间对象传递的方法

    Servlet页面间对象传递的方法 1.request 2.session 3.application 4.cookie 5.其它的

  10. MonoDevelop with Visual Studio to Linux and Mac OSX maintaining a single code base for all platforms.

    Home | Screenshots | Download | Contact | FAQ | Documentation | Development | Search   MonoDevelop i ...