• 3.4 TensorFlow实现神经网络

    • 3.4.1 TensorFlow游乐场
    • 3.4.2 前向传播
    • 3.4.3 神经网络参数与TensorFlow变量
      • 变量和张量的关系

        • 变量的三个属性:张量、维度、类型
    • 3.4.4通过TensorFlow训练神经网络模型
    • 3.4.5 完整的神经网络样例程序
    • 从程序中总结生成神经网络的步骤
    • 第三章小结

3.4 TensorFlow实现神经网络

3.4.1 TensorFlow游乐场

 https://playground.tensorflow.org

3.4.2 前向传播

神经网络的输出是通过前向传播的方法得到的,前向传播需要三部分信息:

  • 其一,神经网络的输入(从实体中提取的特征向量)

  • 其二,神经网络的连接结构(不同神经元间输入输出的连接关系)

  • 其三,神经网络中每个神经元的参数(网络层数、权值、偏置、节点数等)
    前向传播算法可以表示为矩阵的乘法

TensorFlow矩阵的乘法实现:tf.matmul

a = tf.matmul(x, w1)
y = tf.matmul(a, w2)

3.4.3 神经网络参数与TensorFlow变量

  • tf.Variable —>保存和更新神经网络中的参数

TensorFlow中的变量也需要指定初始值,一般使用随机数给其中的变量初始化

#声明一个2*3矩阵变量
import tensorflow as tf
weights=tf.Variable(tf.random_normal([2,3],stddev=2))
#2*3的矩阵,矩阵中元素为均值为0,标准差为2的随机数,可以用mean指定平均值,默认为0(正态分布)
<tf.Variable 'Variable:0' shape=(2, 3) dtype=float32_ref>
  • TensorFlow目前支持的所有随机数生成器

表3-2 TensorFlow随机数生成器

函数名称 随机数分布 主要参数
tf.random_normal 正态分布 平均值、标准差、取值类型
tf.truncated_normal 正态分布,如果随机出来的值偏离均值超过2个标准差,重新随机 平均值、标准差、取值类型
tf.random_uniform 平均分布 最小、最大取值、取值类型
tf.random_gamma Gamma分布 形状参数alpha、尺度参数beta、取值类型

函数完整介绍:

1)tf.random_normal使用方法

tf.random_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None) 

解释:

从正态分布中输出随机值。

参数:

 shape: 一维的张量,也是输出的张量。mean: 正态分布的均值。 stddev: 正态分布的标准差。dtype: 输出的类型。seed: 一个整数,当设置之后,每次生成的随机数都一样。name: 操作的名字。

2)tf.truncated_normal使用方法

tf.truncated_normal(shape,mean=0.0,stddev=1.0,dtype=tf.float32,seed=None,name=None)

解释:

从截断的正态分布中输出随机值。

生成的值服从具有指定平均值和标准偏差的正态分布,如果生成的值大于平均值2个标准偏差的值则丢弃重新选择。

tf.truncated_normal中如果x的取值在区间(μ-2σ,μ+2σ)之外则重新进行选择。这样保证了生成的值都在均值附近。

代码示例:

a = tf.Variable(tf.random_normal([2,2],seed=1))
b = tf.Variable(tf.truncated_normal([2,2],seed=2))
# 变量初始化
init = tf.global_variables_initializer()
with tf.Session() as sess:sess.run(init)print(sess.run(a))print(sess.run(b))输出:
[[-0.81131822  1.48459876][ 0.06532937 -2.44270396]][[-0.85811085 -0.19662298][ 0.13895047 -1.22127688]]

TensorFlow支持通过常数初始化变量,下表列出了常用常数声明方法

表3-3 TensorFlow常数生成函数

函数名称 功能 样例
tf.zeros 产生全0数组 tf.zeros([2,3],int32)–>[[0,0,0],[0,0,0]]
tf.ones 产生全1数组 tf.ones(2,3],int32)–>[[1,1,1],[1,1,1]]
tf.fill 产生一个给定值的数组 tf.fill([2,3],9)–>[[9,9,9],[9,9,9]]
tf.constant 产生一个给定值常量 tf.constant([1,2,3])–>[1,2,3]

注意:

c1 = tf.constant([3])   #代表向量,shape=(1, )的一维constant
c2 = tf.constant([[3]]) #代表1*1的矩阵,shape=(1, 1)的二维constant

偏置项(bias):

偏置项通常会使用常数来设定初始值

biases=tf.Variable(tf.zeros([3]))
<tf.Variable 'Variable_1:0' shape=(3,) dtype=float32_ref>

除过使用随机数或者常数,TensorFlow也支持其他变量的初始值来初始化新变量

import tensorflow as tf
weights=tf.Variable(tf.random_normal([2,3],stddev=2))
w2=tf.Variable(weights.initialized_value())
w3=tf.Variable(weights.initialized_value()*2.0)
#w2的初始值设置成了与weights变量相同,w3的初始值是weights初始值的两倍
#TensorFlow中一个变量的值被使用之前,该变量的值需要被明确的调用
<tf.Variable 'Variable_1:0' shape=(2, 3) dtype=float32_ref>
<tf.Variable 'Variable_2:0' shape=(2, 3) dtype=float32_ref>

简单的神经网络

import tensorflow as tf
# 声明w1和w2两个变量,这里还通过seed设定了随机种子,保证每次运行的结果一样
w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1))
w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=1))#暂时将输入的特征向量定义为一个常量,x是一个1*2的矩阵
x=tf.constant([[0.7,0.9]])
#通过前向传播算法获得神经网络的输出
a=tf.matmul(x,w1)
y=tf.matmul(a,w2)#调用会话输出结果
sess=tf.Session()
#初始化w1和w2(未初始化不能直接获取值)
sess.run(w1.initializer)  #初始化w1
sess.run(w2.initializer)  #初始化w2
#输出
print(sess.run(y))
sess.close()
# 也可以使用下面的初始化和会话方法
init=tf.global_variables_initializer()
# with tf.Session() as sess:
#     sess.run(init)
#     print(sess.run(y))
[[ 3.95757794]]

程序解析:

  • 第一步:定义TensorFlow计算图中的所有计算,但这些被定义的运算并不需要真正的运行
  • 第二步:声明一个会话,并通过会话计算结果,但在计算y之前,需要将所有用到的变量初始化,也就是说在定义的时候给出了变量初始化的方法,但并没有真正运行。
    • 但当变量数目增多或存在依赖关系时,可以用更加快捷的方法来初始化过程
    • tf.global_variables_initializer(),【原始tf.initialize_all_variables()会报错】
sess=tf.Session()
init_op=tf.global_variables_initializer()
#init_op=tf.initialize_all_variables()->报错
sess.run(init_op)

变量和张量的关系

变量的三个属性:张量、维度、类型

1.张量

TensorFlow中所有的数据都是通过张量的形式来组织的,变量声明函数tf.Variable()是一个运算,该运算会产生一个张量,该张量也就是本节所介绍的变量,所以变量就是特殊的张量。

构建机器学习模型时,可以通过变量声明函数中的trainable函数来区分需要优化的参数(神经网络的参数)和其他参数(如迭代次数),如果trainableTrue,则变量会被加入 集合 GraphKeys.TRAINBALE_VARIABLES中,TensorFlow可以通过tf.variable_variables来得到所有需要优化的参数,TensorFlow的神经网络优化算法将tf.variable_variables集合中的变量默认为优化对象。

2.维度

维度在程序运行过程中是可变的,但需要通过设置参数:validate_shape=False

import tensorflow as tf
# 声明w1和w2两个变量,这里还通过seed设定了随机种子,保证每次运行的结果一样
w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1))
w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=1))
#下面会报错:维度不匹配
tf.assign(w1,w2)
#下面会正确执行
tf.assign(w1,w2,validate_shape=False)
#tf.assign(A, new_number): 这个函数的功能主要是把A的值变为new_number

3.类型
变量的类型不可变,一个变量构建之后类型已经固定。

3.4.4通过TensorFlow训练神经网络模型

本节主要介绍使用监督学习的方式更合理的设置参数的取值

设置神经网络参数的过程就是神经网络的训练过程,只有经过有效训练的神经网络才能真正的解决分类或者回归问题。

使用监督学习的方式设置神经网络参数需要有一个标注好的训练数据集

监督学习的思想:

在已知答案的标注数据集上,模型给出的预测结果要尽可能的接近真实的答案,通过调整神经网络中的参数对训练数据进行拟合,可以使得模型对未知样本提供预测能力。

通过反向传播算法训练神经网络:


反向传播过程实现了一个迭代的过程:

  1. 迭代开始,首先选取一小部分训练数据(称为batch);
  2. 该batch样例通过前向传播算法得到神经网络的预测结果;
  3. 计算预测结果和正确答案见的差距;
  4. 基于上述差距,利用反向传播算法更新神经网络参数,使得在该batch上的神经网络模型预测结果和真实答案更加接近;

通过TensorFlow实现反向传播:

1.实现一个样例(batch)的前向传播

表达一个batch的数据:placeholder

已知可以利用常量来表达选取的数据,但是这样一来计算图会太大,因为每生成一个常量,TensorFlow都会在计算图中增加一个节点,所以TensorFlow引入placeholder机制用于提供数据。

placeholder:定义一个位置,该位置的数据在程序运行时再指定,只需要将数据通过placeholder来传入计算图中,而不用大量的常量来提供输入数据。

placeholder: 中文意思是占位符,在tensorflow中类似于函数参数,运行时必须传入值,经常会有一些待输入的参数,但是在建立模型时,需要使用到它,那么就需要使用占用符的方式来写入计算公式里,也就是建立到模型里的关系。

import tensorflow as tf# 声明w1和w2两个变量,这里还通过seed设定了随机种子,保证每次运行的结果一样
w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1))
w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=1))#定义placeholder作为存放输入数据的地方,维度不一定要定义,但如果是确定的维度,可以降低出错概率
x=tf.placeholder(tf.float32,shape=(1,2),name="input")
a=tf.matmul(x,w1)
y=tf.matmul(a,w2)sess=tf.Session()
init_op=tf.global_variables_initializer()
sess.run(init_op)
print(sess.run(y,feed_dict={x:[[0.7,0.9]]}))
[[ 3.95757794]]

程序中替换了原理通过常量定义的输入x,计算前向传播时需要提供一个feed_dict来指定x的取值,feed_dict是一个字典,字典中需要给出每个用到的placeholder的取值。

2.实现n个样例的前向传播

将上述输入的1∗2 1∗21*2矩阵改为n∗2 n∗2n*2矩阵,其中每一行都为一个样例数据,这样得到的前向传播结果为n∗1 n∗1n*1的矩阵。

import tensorflow as tf
# 声明w1和w2两个变量,这里还通过seed设定了随机种子,保证每次运行的结果一样
w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1))
w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=1))
#定义placeholder作为存放输入数据的地方,维度不一定要定义,但如果是确定的维度,可以降低出错概率
x=tf.placeholder(tf.float32,shape=(3,2),name="input")
a=tf.matmul(x,w1)
y=tf.matmul(a,w2)sess=tf.Session()
init_op=tf.global_variables_initializer()
sess.run(init_op)
print(sess.run(y,feed_dict={x:[[0.7,0.9],[0.1,0.4],[0.5,0.8]]}))
[[ 3.95757794][ 1.15376544][ 3.16749239]]

上面例子中,一次性计算多个batch的前向传播结果,运行时需要将3个样例[0.7,0.9],[0.1,0.4],[0.5,0.8]组成一个3*2的矩阵传入placeholder中,计算得到3*1的矩阵。

3. 定义损失函数来刻画当前预测值和真实答案的差距

cross_entropy=-tf.reduce_mean(y_ *tf.log(tf.clip_by_value(y,1e-10,1.0)))
#定义学习率
learning_rate=0.001
#定义反向传播算法来优化神经网络中的参数
train_step=tf.train.AdamOptimizer(learning_rate).minimize(cross_entropy)

cross_entropy:定义了真实值和预测值之间的交叉熵(分类中的常用损失函数)
train_step:定义了反向传播的优化算法

代码中的交叉熵损失函数解释:

交叉熵用于衡量原始分布p(x) p(x)p(x)和预测分布q(x) q(x)q(x)之间的距离,CH(p,q)=−∑ x p(x)logq(x) CH(p,q)=−∑xp(x)logq(x)CH(p,q)=-\sum_xp(x)logq(x)。

p(x) p(x)p(x):就是真实的标签y yy
q(x)'>q(x) q(x)q(x):就是预测的值y ^  y^\hat y
logq(x) logq(x)logq(x):tf.log(tf.clip_by_value(y, 1e-10, 1.0))

  • 常用优化算法:

    tf.train.GradientDescentOptimizer
    tf.train.AdamOptimizer
    tf.train.MomentumOptimizer

3.4.5 完整的神经网络样例程序

# 3.5.5 神经网络样例程序
import tensorflow as tf
from numpy.random import RandomState# 定义训练数据batch的大小
batch_size = 8# 定义神经网络参数
# random_normal 产生一个正态随机矩阵,shape=[2,3],stddev是正太分布的标准差,seed随机数种子,设置后每次产生的数字都相同
w1 = tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1))
w2 = tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1))# 在shape的一个维度上使用None可以方便使用不大的batch大小,
# 在训练时需要将数据分成较小的batch,但在测试时,可以一次性使用全部的数据,
# 数据集较小时方便测试,但是数据集较大时,大量的数据放入一个batch可能会导致数据溢出。
# placeholder占位符,执行时,在通过feed_dict将值传入,dtype:数据类型,shape:数据形状,name:名称
# 如果在定义占位符时,不能确定值的形状时,用None表示
x = tf.placeholder(tf.float32, shape=[None, 2], name='x-input')
y_ = tf.placeholder(tf.float32, shape=[None, 1], name='y-input')# 定义前向传播的过程
a = tf.matmul(x, w1)
y = tf.matmul(a, w2)# 定义损失函数和反向传播算法
# cross_entropy是交叉熵
# tf.clip_by_value(A, min, max):输入一个张量A,把A中的每一个元素的值都压缩在min和max之间。小于min的让它等于min,大于max的元素的值等于max
# reduce_mean 求均值
cross_entropy = -tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)))
# train_step 就是每次可训练出一组w就是一次反向传播
# 下面给出里三种反向传播的算法传入的是学习率
# train_step = tf.train.AdamOptimizer(0.001).minimise(cross_entropy)
# train_step=tf.train.GradientDescentOptimizer(0.001).minimize(cross_entropy)
train_step = tf.train.MomentumOptimizer(0.001, 0.9).minimize(cross_entropy)# 通过随机数生成一个模拟数据集rdm = RandomState(1)  # 1为伪随机数产生的种子
dataset_size = 128
X = rdm.rand(dataset_size, 2)# 此处使用0表示负样本,1表示正样本
Y = [[int(x1 + x2 < 1)] for (x1, x2) in X]# 创建一个会话来运行Tensorflow程序,反复运行反向传播
# tf中运行必须放在session对象中,且运行过后,要关闭session
with tf.Session() as sess:init_op = tf.global_variables_initializer()# 初始化变量,也就是上面的Variable变量sess.run(init_op)print(sess.run(w1))print(sess.run(w2))# 设定训练的轮数STEPS = 5000for i in range(STEPS):# 每次选取batch_size个样本进行训练start = (i * batch_size) % dataset_sizeend = min(start + batch_size, dataset_size)# 通过选取的样本训练神经网络并进行参数更新# feed_dict的作用是给使用placeholder创建出来的tensor赋值sess.run(train_step, feed_dict={x: X[start: end], y_: Y[start:end]})if i % 1000 == 0:total_cross_entropy = sess.run(cross_entropy, feed_dict={x: X, y_: Y})print("After %d training steps,cross entropy on all data is %g" % (i, total_cross_entropy))print(sess.run(w1))print(sess.run(w2))
训练之前神经网络的参数:
w1=[[-0.81131822  1.48459876  0.06532937][-2.4427042   0.0992484   0.59122431]]
w2=[[-0.81131822],[ 1.48459876],[ 0.06532937]]输出结果:
After 0 training steps,cross entropy on all data is 0.0677127
After 1000 training steps,cross entropy on all data is 0.0299578
After 2000 training steps,cross entropy on all data is 0.0226611
After 3000 training steps,cross entropy on all data is 0.0178286
After 4000 training steps,cross entropy on all data is 0.0143322
训练之后神经网络的参数:
w1=[[-1.14571726  1.92318034  0.107902  ][-2.79355311  0.57146555  0.63480443]]
w2=[[-1.77604687],[ 2.00357008],[ 0.25552016]]

从程序中总结生成神经网络的步骤

训练神经网络过程可以分为以下三个步骤:

  1. 定义神经网络的结构和前向传播的输出结果;
  2. 定义损失函数以及选择反向传播优化的算法;
  3. 生成会话(tf.Session),并且在训练数据上反复运行反向传播优化算法;

第三章小结

  1. TensorFlow计算模型——计算图

    1. 所有的程序都会通过计算图的形式表示;
    2. 节点:都表示一个运算
    3. 边:表示了运算之间数据的传递关系,
    4. 计算图还保存了运行每个计算的设备信息以及运算的依赖关系
    5. 计算图还有管理不同集合的功能,并且TensorFlow会自动维护五个默认的计算图
  2. TensorFlow数据模型——张量

    1. 所有运算的输入输出都是张量
    2. 张量本身不存储任何数据,只是对运算结果的引用
    3. 通过张量可以更好的组织TensorFlow程序
  3. TensorFlow运算模型——会话

    1. 管理了TensorFlow程序所拥有的系统资源,所有的运算通过会话执行

TensorFlow:实战Google深度学习框架(二)实现简单神经网络相关推荐

  1. 免费教材丨第55期:Python机器学习实践指南、Tensorflow 实战Google深度学习框架

    小编说  时间过的好快啊,小伙伴们是不是都快进入寒假啦?但是学习可不要落下哦!  本期教材  本期为大家发放的教材为:<Python机器学习实践指南>.<Tensorflow 实战G ...

  2. 06.图像识别与卷积神经网络------《Tensorflow实战Google深度学习框架》笔记

    一.图像识别问题简介及经典数据集 图像识别问题希望借助计算机程序来处理.分析和理解图片中的内容,使得计算机可以从图片中自动识别各种不同模式的目标和对象.图像识别问题作为人工智能的一个重要领域,在最近几 ...

  3. (转)Tensorflow 实战Google深度学习框架 读书笔记

    本文大致脉络: 读书笔记的自我说明 对读书笔记的摘要 具体章节的摘要: 第一章 深度学习简介 第二章 TensorFlow环境搭建 第三章 TensorFlow入门 第四章 深层神经网络 第五章 MN ...

  4. 《Tensorflow 实战google深度学习框架》第二版源代码

    <<Tensorflow 实战google深度学习框架–第二版>> 完整资料github地址: https://github.com/caicloud/tensorflow-t ...

  5. 学习《TensorFlow实战Google深度学习框架 (第2版) 》中文PDF和代码

    TensorFlow是谷歌2015年开源的主流深度学习框架,目前已得到广泛应用.<TensorFlow:实战Google深度学习框架(第2版)>为TensorFlow入门参考书,帮助快速. ...

  6. 说说TensorFlow实战Google深度学习框架

    说说TensorFlow实战Google深度学习框架 事情是这样的,博主买了这本书,但是碍于想在电脑上边看边码,想找找PDF版本,然后各种百度,Google,百度网盘,最后找到的都是很多200M的,百 ...

  7. TensorFlow实战Google深度学习框架

    TensorFlow是谷歌2015年开源的主流深度学习框架.科技届的聚光灯已经从"互联网+"转到了"AI+": 掌握深度学习需要较强的理论功底,用好Tensor ...

  8. Tensorflow【实战Google深度学习框架】用卷积神经网络打造图片识别应用

    文章目录 1 Tensorflow model 2 卷积神经网络的基础单元 2.1 卷积 2.2 激活函数 2.3 池化 2.4 批归一化 2.5 Dropout 3 主流的25个深度学习模型 4 训 ...

  9. TensorFlow实战Google深度学习框架5-7章学习笔记

    目录 第5章 MNIST数字识别问题 第6章 图像识别与卷积神经网络 第7章 图像数据处理 第5章 MNIST数字识别问题 MNIST是一个非常有名的手写体数字识别数据集,在很多资料中,这个数据集都会 ...

  10. Tensorflow【实战Google深度学习框架】全连接神经网络以及可视化

    文章目录 1 可视化 神经网络的二元分类效果 2 全连接神经网络 3 TensorFlow搭建一个全连接神经网络 3.1 读取MNIST数据 3.2 建立占位符 3.3 建立模型 3.4 正确率 3. ...

最新文章

  1. ACL Fellow 2021名单出炉!华为刘群、中科院自动化所宗成庆当选!
  2. android 导入开源项目代码常见问题
  3. alert点击确定后跳转_公众号/h5 跳转到小程序填坑指南
  4. Windows phone 8 学习笔记(4) 应用的启动
  5. mr图像翻转的原因_MRI图像常见问题及对策
  6. C/C++脚本接口神器:Lua
  7. PHP超级全局变量总结
  8. 数学之美:45幅耀眼夺目的分形艺术作品欣赏
  9. Android 对话框黑色边框的解决
  10. 前脚修复,后脚放 PoC:马上修复这个严重的SAP Recon 漏洞!
  11. 实验3-3 比较大小 (10 分)
  12. 已修复的bug: 简书文章长标题换行异常,标题配图异常,首页配图异常
  13. python基础代码大全-Python基础汇总
  14. 【hdu3183】A Magic Lamp(思维+st表(含模版))
  15. 华为NP课程笔记22-防火墙
  16. ccrpipa6.ocx 和mswinsck.ocx 等文件缺失问题解决(用于TCP调试助手)
  17. 离散数学课后习题答案
  18. 五十三、微信小程序云开发豆瓣电影小项目
  19. 老域名及用户行为习惯.
  20. 3D游戏开源引擎分析

热门文章

  1. TODO:Laravel增加验证码
  2. 面向对象和面向过程的区别个人觉得是目前解释最好的
  3. 关于js获取radio和select的属性并控制
  4. mellanox 网卡驱动_收购Mellanox之后 NVIDIA发布全球首款25G安全智能网卡
  5. 用innerHTML给textarea的value赋值,IE下丢失换行
  6. 缓存系统MemCached的Java客户端优化历程
  7. 专科计算机网络期末考试,计算机网络(专科)期末练习题.doc
  8. html5能实现网络游戏吗,kbengine + cocos2d_js实现html5网络游戏mmorpg(全套代码+资源)...
  9. mysql affected rows_mysql_affected_rows函数定义与用法汇总
  10. 后台接收数组_微信小程序如何与后台api接口进行数据交互(微信报修小程序源码讲解七)...