赵工的个人空间


专业技术部分转网页计算转业余爱好部分


 编程语言

常用的编程语言
C#编程语言基础
C#面向对象与多线程
C#数据及文件操作
JavaScript基础
JavaScript的数据类型和变量
JavaScript的运算符和表达式
JavaScript的基本流程控制
JavaScript的函数
JavaScript对象编程
JavaScript内置对象和方法
JavaScript的浏览器对象和方法
JavaScript访问HTML DOM对象
JavaScript事件驱动编程
JavaScript与CSS样式表
Ajax与PHP
ECMAScript6的新特性
Vue.js前端开发
PHP的常量与变量
PHP的数据类型与转换
PHP的运算符和优先规则
PHP程序的流程控制语句
PHP的数组操作及函数
PHP的字符串处理与函数
PHP自定义函数
PHP的常用系统函数
PHP的图像处理函数
PHP类编程
PHP的DataTime类
PHP处理XML和JSON
PHP的正则表达式
PHP文件和目录处理
PHP表单处理
PHP处理Cookie和Session
PHP文件上传和下载
PHP加密技术
PHP的Socket编程
PHP国际化编码
MySQL数据库基础
MySQL数据库函数
MySQL数据库账户管理
MySQL数据库基本操作
MySQL数据查询
MySQL存储过程和存储函数
MySQL事务处理和触发器
PHP操作MySQL数据库
数据库抽象层PDO
Smarty模板
ThinkPHP框架
Python语言基础
Python语言结构与控制
Python的函数和模块
Python的复合数据类型
Python面向对象编程
Python的文件操作
Python的异常处理
Python的绘图模块
Python的NumPy模块
Python的SciPy模块
Python的SymPy模块
Python的数据处理
Python操作数据库
Python网络编程
Python图像处理
Python机器学习
TensorFlow深度学习
Tensorflow常用函数
TensorFlow用于卷积网络
生成对抗网络GAN


首页 > 专业技术 > 编程语言 > TensorFlow深度学习
TensorFlow深度学习

神经网络是一种受到生物神经细胞结构启发而研究出的一种算法体系。所谓深度学习指的是基于深度神经网络的学习,也就是深度神经网络所进行的学习过程,称为Deep Learning。深度指的是神经网络的层次多,一般超过一个隐藏层的网络都算深度神经网络。
一些常见的机器学习和神经网络软件库有TensorFlow、Caffe、Chainer、CNTK、Deeplearning4j、Nervana Neo、Theano、Torch等,其中TensorFlow、Chainer、Nervana Neo、Theano是Python软件库,Torch使用Lua但有Python版本的PyTorch,而Deeplearning4j是Java库,CNTK只支持C++。

一、TensorFlow基础:

TensorFlow是一个采用数据流图,用于数值计算的开源软件库,最初由Google的研究人员开发出来,用于机器学习和深度神经网络方面的研究,也可用于其他计算领域。TensorFlow支持在多个计算单元上进行计算,有可视化组件。TensorFlow采用符号式编程,一般先定义各种变量,然后建立一个数据流图,在数据流图中规定各个变量之间的计算关系,最后需要对数据流图进行编译。但此时数据流图还是一个壳,其中没有数据,需要将运算数据输入,才能在整个模型中形成数据流,从而形成输出值。

1. 基本概念:

Tenson的意思是张量,Flow意思是流,任意维度的数据都可以称为张量。TensonFlow的含义是保持计算节点不变,让数据在不同的计算设备上传输并计算。
1)张量:
TensorFlow采用张量的数据结构来表示它内部的所有数据,每个张量都有自己的静态类型,以及张量的形状(各个维度的长度)。TensorFlow的核心是一套用非Python实现的科学计算或深度学习库,其内部运行的变量就是自己封装的Tensor。
TensorFlow主要用于深度学习方面,在深度学习的计算过程中有前向计算和后向传播的过程,在深度学习过程的每个节点基本上都要执行前向的数值计算,以及后向的残差传播的参数更新。TensorFlow把内部的数据包装成Tensor的类型,并且在Tensor中包含了前向计算和反向传播时的残差计算,让所有的计算过程都连起来。
每个张量的维度用阶来描述,零阶张量是一个标量,一阶张量是一个向量,二阶张量是一个矩阵。
import tensorflow as tf
scalar=tf.constant(100)
vector=tf.constant([1,2,3,4,5])
matrix=tf.constant([[1,2,3],[4,5,6]])
cube_matrix=tf.constant([[[1],[2],[3]],[[4],[5],[6]],[[7],[8],[9]]])
print(scalar.get_shape()) # ()
print(vector.get_shape()) # (5,)
print(matrix.get_shape()) # (2, 3)
print(cube_matrix.get_shape()) #(3, 3, 1)
张量的形状指的是其行数和列数。
2)图:
TensorFlow通过一个叫数据流图的方式来组织它的数据和运算。在使用TensorFlow实现深度学习算法时,先将所有操作表达成一张图。张量从算法的开始走到结束完成一次向前计算,而残差从后往前就完成了一次后向传播来更新要训练的参数。
3)操作:
在图中描述计算顺序,图中的节点就是操作operation,比如加法、乘法,构建一些变量的初始值也是一个操作。每个运算操作都有属性,在构建图的时候就需要确定下来。操作可以和计算设备绑定,可以指定操作在某个设备上执行。计算设备指的是CPU、GPU,或者同一个集群的其他机器上的CPU、GPU。
操作之间存在顺序关系,有的操作在其他操作执行完成后才能执行,这些操作之间的依赖就是边。这些操作之间的顺序关系的定义很简单,在代码编程上表现出来的就是操作A的输入是操作B执行的结果,那么这个操作A就依赖操作B。
4)会话:
TensorFlow的计算需要在会话中执行。当创建一个会话时,如果没有传递参数,默认情况下它会启动默认的图来构造图结构,并且会将图中定义的op根据定义的情况分发到CPU或GPU的设备上。
设计好计算,图的实际计算必须在会话中执行。示例:
import tensorflow as tf # 导入TensorFlow
v1=tf.constant(1, name="value1") # 定义常量v1
v2=tf.constant(1, name="value2") # 定义常量v2
add_op=tf.add(v1, v2, name="add_op_name") # 定义加法操作
定义操作后,如果想知晓图中添加了多少运算操作,可以通过graph.get_operations()来获取:
graph=tf.get_default_graph() # 获取默认的图
operations=graph.get_operations() # 获取图中的所有操作
for op in operations: # 遍历所有的操作
    print(op) # 输出
定义好运算操作并且将操作添加到图中后,就可以构建会话,并在会话中执行操作:
with tf.Session() as sess: # 在会话中执行操作
    result=sess.run(add_op) # 执行运算,将运算结果赋值给变量
    print("1+1=%.0f" %result)
代码中采用with语句包装,可以在结束with语句块时自动销毁会话资源。其中在sess.run中运算的所有操作都是在TensorFlow内部进行的计算,这些运算可能会在CPU或GPU上计算,也可能在一个分布式集群中的另外一个节点上计算。TensorFlow深度学习的计算,大部分是矩阵和向量的运算,直接采用Python计算效率较低,而采用GPU计算会有数量级上的提升,所以会使用会话在Python之外独立运行。

2.编程模型:

TensorFlow是用数据流图做计算的,需要先创建一个数据流图。数据流图中包含输入input、塑形reshape、Relu层、Logit层、Softmax、交叉熵cross entropy、梯度gradient、SGD训练等部分,是一个简单的回归模型。
计算过程是从输入开始,经过塑形后,一层层进行前向传播计算。Relu层有Whl和bhl两个参数,使用ReLu激活函数做非线性处理输出;然后进入Logit输出层,有Wsm和bsm两个参数;用Softmax计算输出结果中各个类别的概率分布,用交叉熵来度量两个概率分布之间的相似性,然后开始计算梯度,这里需要用参数Whl、bhl、Wsm、bsm以及交叉熵的结果;随后进入SGD训练,即反向传播过程,从上向下计算每一层的参数,依次进行更新,计算和更新bsm、Wsm、bhl、Whl。
TensorFlow字面含义是张量的流动,其中的数据流图是由节点node和边edge组成的有向无环图directed acycline graph。
1)边:
TensorFlow的边有两种连接关系,数据依赖和控制依赖。其中实线边表示数据依赖,代表数据,即张量,任意维度的数据称为张量。张量在数据流图中从前向后流动以遍就完成了一次前向传播,而残差从后向前流动一遍就完成反向传播。
另一种依赖,控制依赖一遍画为虚线边,可以用于控制操作的运行,这类边上没有数据流过,但源节点必须在目的节点开始执行前完成执行。常用代码:
tf.Graph.control_dependencies(control_inputs)
TensorFlow支持的张量数据类型有:

TensorFlow数据类型

Python中的表示

说明

DT_FLOAT

tf.float32

32位浮点数

DT_DOUBLE

tf.float64

64位浮点数

DT_INT8

tf.int8

8位有符号整数

DT_INT16

tf.int16

16位有符号整数

DT_INT32

tf.int32

32位有符号整数

DT_INT64

tf.int64

64位有符号整数

DT_UINT8

tf.uint8

8位无符号整数

DT_UINT16

tf.uint16

16位无符号整数

DT_STRING

tf.string

byte类型数组

DT_BOOL

tf.bool

布尔型

DT_COMPLEX64

tf.complex64

复数类型,由32位浮点数的实部和虚部组成

DT_COMPLEX128

tf.complex128

复数类型,由64位浮点数的实部和虚部组成

DT_QINT8

tf.qint8

量化操作的8位有符号整数

DT_QINT32

tf.qint32

量化操作的32位有符号整数

DT_QUINT8

tf.quint8

量化操作的8位无符号整数

有关图及张量的源代码在tensorflow/python/framework/ops.py中。
TensorFlow中数据传递常常需要通过其API与Numpy数组的交互来完成。若要使用常量数构建张量,需要将一个Numpy数组传入tf.constant()操作符,得到一个该值的TensorFlow张量:
tensorx=np.array([1,2,3,4,5,6,7,8,9])
tensorz=tf.contant(tensorx)
若要使用变量构建张量,将变量定义为Numpy数组形式,并将其传入tf.Variable()函数,得到一个带有初始值的变量张量:
tensorx=np.array([(1,2,3),(4,5,6),(7,8,9)])
tensorz=tf.Varialble(tensorx)
with tf.Session() as sess:
sess.rum(tf.global_variables_initializer())
print(sess.run(tensorx))
使用变量时,首先要使用tf.global_variables_initializer()对变量初始化。
为了方便程序在Python交互环境下使用,可以采用InteractiveSession类,并在所有Tesnsor. eval()和Operation.run()调用中使用该类:
import tensorflow as tf
import numpy as np
interact=tf.InteractiveSession()
tensor=np.array([1,2,3,4,5,6])
tensor=tf.constant(tensor)
print(tensor.eval())
interact.close()
这个类为交换环境的使用提供了方便,编写代码时无需不停传递Session对象。
TensorFlow中另一种张量方式是使用tf.convert_to_tensor命令:
import tensorflow as tf
import numpy as np
tensor=np.array([1,2,3,4,5,6])
tensor=tf.convert_to_tensor(tensor,dtype=tf.float32)
with tf.Session() as sess:
print(sess.run(tensor))
2)节点:
流图中的节点又称为算子,代表一个操作operation,一般用来表示施加的数学运算,也可以表示数据输入的起点以及输出的终点,或是读取/写入持久变量的终点。TensorFlow实现的算子有:

类别

示例

数学运算操作

Add、Subtract、Multiply、Div、Exp、Log、Greater、Less、Equal......

数组运算操作

Concat、Slice、Split、Constant、Rank、Shape、Shuffle......

矩阵运算操作

MatMul、MatrixInverse、AssignDeterminant......

有状态的操作

Variable、Assign、AssignAdd......

神经网络构建操作

SoftMax、Sigmoid、ReLU、Convolution2D、MaxPool......

检查点操作

Save、Restore

队列和同步操作

Enqueue、Dequeue、MutexAcquire、MutexRelease......

控制张量流动的操作

Merge、Switch、Enter、Leave、NextIteration

与操作相关的代码位于tensorflow/python/ops/目录下,数学运算在math_ops.py中,其中定义了add、subtract、multiply、scalar_mul、div、divide、truediv、floordiv等数学运算,每个函数中调用了gen_math_ops.py中的方法。数组运算代码在array_ops.py中,其中定义了concat、split、slice、size、rank等运算,每个函数都调用了gen_array_ops.py中的方法。这些代码也会调用核函数来实现。
3)图:
把操作任务描述成有向无环图。构建图的第一步是创建各个节点。示例:
import tensorflow as tf
#创建一个常量运算操作,产生一个1x2矩阵
matrix1=tf.constant([[3.],[3.]])
#创建另一个常量运算操作,产生一个2x1矩阵
matrix2=tf.constant([[2.],[2.]])
#创建一个矩阵乘法运算,把两个矩阵作为输入,返回乘法结果
product=tf.matmul(matrix1,matrix2)
4)会话:
启动图的第一步是创建一个会话Session对象,会话提供在图中执行操作的一些方法。建立会话,会生成一个空图,在会话中添加节点和边,形成一张图,然后执行。创建一张图并运行操作的类,使用tf.Session。示例:
with tf.Session() as sess:
    result=sess.run([product])
    print(result)
在调用Session对象的run()方法来执行图时,传入Tensor,这个过程称为填充feed,返回的结果类型根据输入的类型而定,这个过程称为取回fetch。
与会话相关的代码位于/tensorflow/python/client/session.py中。一个会话可以有多个图,会话可以修改图的结构,也可以向图中注入数据进行计算。会话主要有两个接口,Extend和Run,Extend是在Graph中添加节点和边,Run操作是输入计算得节点和填充必要的数据后进行计算,并输出运算结果。
5)设备:
设备device是指一块可以用来运算并且拥有自己的地址空间的硬件,如GPU和CPU。TensorFlow为了实现分布式操作,充分利用计算资源,可以明确指定操作在某个设备上。
with tf.Session() as sess:
    with tf.device("/gpu:1):
        matrix1=tf.constant([[3.],[3.]])
        matrix2=tf.constant([[2.],[2.]])
        product=tf.matmul(matrix1,matrix2)
与设备相关的源代码在/tensorflow/python/framework/device.py中。
6)变量:
变量Variable是一种特殊的数据,它在图中有固定的位置,不像普通张量那样可以流动。创建一个变量张量,使用tf.Variable()构造函数,这个构造函数需要一个初始值,初始值的形状和类型决定了这个变量的形状和类型。示例:
#创建一个变量,初始化为标量0
state=tf.Variable(0,name="counter"(
创建一个常量张量:
input1=tf.contant(3.0)
TensorFlow提供了填充机制,可以在构建图时使用tf.placeholder()临时替代任意张量,在调用Session对象的run()方法去执行图时,使用填充数据作为调用的参数,调用结束后,填充数据消失。代码为:
input1=tf.placeholder(tf.float32)
input2=tf.placeholder(tf.float32)
output=tf.multiply(input2,input2)
with tf.Session() as sess:
    print sess.run([output],feed_dict={input1:[7.],input2:[2:]})
与变量相关的代码在/tensorflow/python/ops/variables.py中。
⑴常量与变量:
TensorFlow中使用tf.constant()定义常量,使用tf.Variable()定义变量。常量的值在执行过程中不会发生改变,变量的值在执行过程在可以修改。
使用tf.Variable()定义变量,需要一个初始化的值,这个初始值可以是任意类型和任意维度大小的张量:
tensor=tf.Varialble(0,name="value")
如果要在一个变量初始化时,借用另外一个变量的初始化的值,可以通过initialized_value()获取其他变量的值:
weight1=tf.Variable(0.001)
weight2=tf.Variable(weight1.initialized_value()*2)
默认情况下,定义的所有变量,TensorFlow都会自动加入到图收集器的GraphKeys.GLOBAL_VARIABLES中。通过global_variables()函数,可以获取所有变量的集合:
init=tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
print(sess.run(weight1),sess.run(weight1))
变量在使用前必须初始化,TensorFlow提供了tf.global_variables_initializer()操作来快速初始化所有变量。
变量在定义时有一个name参数,并不是必须的,但在使用可视化TensorBoard查看图的结构时会更方便,运行时出错也可以在错误日志中容易定位变量。
⑵变量的trainable参数:
当进行神经网络训练时,有些变量是学习训练的参数,它们的值会在训练过程中在梯度更新时发生改变,而有些值不是训练参数,不希望这些值在梯度更新时改变。变量声明时,指定参数trainable是True还是False来实现训练过程中变量的值是否被更新。
如果参数trainable的值是True,变量的值在训练过程中可以被修改,变量会被添加到GraphKeys.GLOBAL_VARIABLES中,可以通过trainable_variables()方法来获取所有的trainable为True的变量;如果trainable的值是False,则训练过程中变量的值不能被改变。在使用TensorFlow的优化器对神经网络的参数进行优化时,只会优化trainable为True的变量。
变量的trainable参数默认为True。示例:
step=tf.Variable(0, trainable=False, name="step")
⑶变量的变形:
构建完变量后,变量的类型和维度大小就固定了。如果此后如果要强制改变变量的维度大小,可以采用reshape操作来改变变量的维度。示例:
reshaped_v=tf.reshape(v, [3,3])
⑷变量的取回:
为取回操作的输出,需要调用Session对象的run()方法,并传入需要取回的张量。可以取回多个张量。示例:
import tensotflow as tf
constantA=tf.constant([100.0])
constantB=tf.constant([200.0])
constantC=tf.constant([2.0])
suma=tf.add(constantA,constantB)
mula=tf.multiply(constanta,constantC)
with tf.Session() as sess:
result=sess.run([suma,mula])
print(result)
⑸注入机制:
注入机制将张量插入节点,它用一个张量值暂时替代操作的输出。注入机制只用于在调用run()方法时,通过feed_dict传递函数。最常用的是使用tf.placeholder()创建feed操作,并继承其他特定操作作为注入操作。示例:
import tensorflow as tf
import numpy as np
a=3;b=2;
x=tf.placeholder(tf.float32, shape=(a,b))
y=tf.add(x,x)
data=np.random.rand(a,b)
sess=tf.Session()
print(sess.run(y,feed_dict={x:data}))
7)一个简单的创建图、运行会话、输出数据的流程:
import tensorflow as tf # 导入TensorFlow库
with tf.Session() as session: # 创建一个session对象
    x=tf.placeholder(tf.float32,[1],name="x") # 通过占位符定义变量
    y=tf.placeholder(tf.float32,[1],name="y")
    z=tf.constant(1.0) # 定义一个常数
    y=x*z # 引入计算模型
x_in=[100]
y_output=session.run(y,{x:x_in}) # 执行定义的计算图
print(y_output) # 输出计算结果
通过占位符placeholder可以定义输入/输出变量,占位符作为计算图中元素和运算数据之间的接口,只需要对数据的引用,就可以创建操作并建立计算图。用placeholder定义数据需要3个参数,第1个是数据类型,第2个是占位符形状,第3个是变量名。
使用session.run()执行计算图,其中第1个参数是待计算的图元素列表,第2个参数表示参与运算的参数及真正取值,返回值为每个图元素的输出值。
TensorFlow的数据类型由张量表示,张量指的是多维数值阵列,由3个参数描述,阶rank、形状shape和数据类型type。

3.常用API:

1)图、操作和张量:
tf.Grapg类中包含一系列表示计算的操作对象tf.Operation,以及在操作之间流动的数据--张量对象tf.Tensor。与图相关的API均位于tf.Graph类中:

操作

描述

tf.Graph.__init__()

创建一个空图

tf.Graph.as_default()

将某图设置为默认图,并返回一个上下文管理器。如果不显式添加一个默认图,系统会自动设置一个全局得默认图。

tf.Graph.device(device_name_or_function)

定义运行图所使用的设备,并返回一个上下文管理器

tf.Graph.name_scope(name)

为节点创建层次化名称,并返回一个上下文管理器

tf.Operation类代表图中的一个节点,用于计算张量数据。该类型由节点构造器产生,如tf.matmul()或Graph.create_op()。例如c=tf.matmul(a,b)创建一个Operation类,其类型为MatMul的操作类。与操作相关的API均位于tf.Operation类中:

操作

描述

tf.Operation.name

操作的名称

tf.Operation.type

操作的类型,如MatMul

tf.Operation.inputs
tf.Operation.outputs

操作的输入与输出

tf.Operation.control_inputs

操作的依赖

tf.Operation.run(feed_dict=None,session=None)

在会话中运行该操作

tf.Operation.get_attr(name)

获取操作的属性值

tf.Tensor类是操作的符号句柄,它不包括操作输出的值,而是提供了一种在tf.Session中计算这些值的方法,这样就可以在操作之间构建一个数据流连接,使TensorFlow能够执行一个表示大量多步计算的图形。与张量相关的API均位于tf.Tensor类中。

操作

描述

tf.Tensor.dtype

张量的数据类型

tf.Tensor.name

张量的名称

tf.Tensor.value_index

张量在操作输出中的索引

tf.Tensor.graph

张量所在的图

tf.Tensor.op

产生该张量的操作

tf.Tensor.consumers()

返回使用该张量的操作列表

tf.Tensor.eval(feed_dict=None,session=None)

在会话中求张量的值,需要使用sess.as_default()或者eval(session=sess)

tf.Tensor.get_shape()

返回用于表示张量的形状的类TensorShape

tf.Tensor.set_shape(shape)

更新张量的形状

tf.Tensor.device

设置计算该张量的设备

2)可视化:
可视化时,需要在程序中给必要的节点添加摘要summary,摘要会收集该节点的数据,并标上第几步、时间戳等标识,写入文件event file中。tf.summary.FileWrite类用于在目录中创建事件文件,并且向文件在添加摘要和事件,用来在TensorBoard中展示。

操作

描述

tf.summary.FileWrite.__init__(logdir,graph=None,max_queur=10,flush_secs=120,graph_def=None)

创建FileWrite和事件文件,会在logdir在创建一个新的事件文件

tf.summary.add_summary(summary,global_step=None)

将摘要添加到事件文件

tf.summary.FileWrite.add_event(event)

向事件文件中添加一个事件

tf.summary.FileWrite.add_graph(graph,global_step=None,graph_def=None)

向事件文件中添加一个图

tf.summary.FileWrite.get_logdir()

获取事件文件的路径

tf.summary.FileWrite.flush()

将所有事件都写入磁盘

tf.summary.FileWrite.close()

将事件写入磁盘,并关闭文件操作符

tf.summary.scalar(name,tensor,collections=None)

输出包含单个标量值的摘要

tf.summary.histograme(name,tensor,sample_rate,max_outputs=3,collections=None)

输出包含直方图的摘要

tf.summary.image(name,tensor,max_outputs=3,collections=None)

输出包含图片的摘要

tf.summary.merge(inputs,collections=None,name=None)

合并摘要,包含所有输入摘要的值

4.变量作用域:

在TensorFlow中有两个作用域scope,一个是name_scope,另一个是variable_scope。在实际的使用过程中,特别在使用递归神经网络时,当创建一些比较复杂的模块时,通常会共享一些变量的值,这时就需要变量可以共享。
1)variable_scope:
variable_scope变量作用域机制在TensorFlow中主要由两部分组成:
v=tf.get_variable(name,shape,dtype,initializer) #通过所给的名字或是返回一个变量
tf.varialble_scope(<scope_name>) #为变量指定命名空间
当tf.get_variable_scope().reuse==False时,varialble_scope作用域只能用来创建新变量;当tf.get_variable_scope().reuse==True时作用域可以共享变量:
with tf.variable_scope("foo") as scope:
    v=tf.get_variable("v",[1])
with tf.variable_scope("foo",reuse=True):
    v1=tf.get_variable("v",[1])
asset v1==v
2)name_scope:
TensorFlow在常常有很多节点,在可视化过程中很难一下子展示出来,因此使用name_scope为变量划分范围,可视化中表示计算图中的一个层级。name_scope会影响op_name,不会影响用get_variable()创建的变量,而会影响通过Variable()创建的变量。
with tf.variable_scope("foo"):
   with tf.name_scope("bar"):
       v=tf.get_variable("v",[1])
       b=tf.Variable(tf.zeros([1]),name='b')
       x=1.0+v
assert v.name=="foo/v:0"
assert b.name=="foo/bar/b:0"
assert v.op.name=="foo/bar/add"
tf.name_scope()返回的是一个字符串,如"bar"。name_scope对用get_variable()创建的变量的名字不会有任何影响,而Variable()创建的操作会被加上前缀,并且会给操作加上名字前缀。
3)get_variable():
tf.get_variable()可能会新定义一个变量,也可能共享前面已经出现的变量,这取决于当前位置的变量作用域是否是重用的。
·如果当前位置变量的作用域不可重用,并且前面已经有重名的变量,则报错
·如果当前位置变量的作用域不可重用,并且前面没有重名的变量,则新建一个变量
·如果当前位置变量的作用域可重用,但是前面没有出现过同样名字的变量,则报错
·如果当前位置变量的作用域可重用,前面也出现过相同名字的变量,则共享前面的变量
调用tf.get_variable()创建变量时,必须给变量指定一个名字,将指定的这个名字加在变量所处的变量命名空间名后,作为这个变量实际的名字,只有实际的名字相同,才认为两个变量的名字相同。所以,不同变量作用域下名字相同的变量,认为是不同的变量名字。示例:
weight=tf.get_variable("weight",[1])
变量的reuse属性的作用范围可以向它的子作用域传递。当跳出作用域范围时,变量的reuse会变成上一层作用域的reuse的值。
with tf.variable_scope("root"):
assert tf.get_variable_scope().reuse==False
with tf.variable_scope("foo"):
    assert tf.get_variable_scope().reuse==False
with tf.variable_scope("foo", reuse=True):
    assert tf.get_variable_scope().reuse==True
    with tf.variable_scope("bar"):
    assert tf.get_variable_scope().reuse==True
assert tf.get_variable_scope().reuse=False
此外,也可以修改目前变量作用域为之前已经存在的变量作用域:
with tf.variable_scope("foo") as foo_scope:
v=tf.get_variable("v", [1])
with tf.variable_scope(foo_scope)
v=tf.get_variable("w", [1])
with tf.variable_scope(foo_scope, reuse=True)
v1=tf.get_variable("v", [1])
w1=tf.get_variable("w", [1])

5.批标准化:

批标准化BN(batch normalization)是为了克服神经网络层数加深导致难以训练而诞生的,通过标准化来规范化某些层或者所有层的输入,从而固定每层输入信号的均值与方差。
批标准化一般用在非线性映射之前,对x=Wu+b做规范化,使结果的均值为0,方差为1.让每一层的输入有一个稳定的分布会有利于网络的训练。批标准化通过规范化让激活函数分布在线性区间,结果就是加大了梯度,让模型更好地进行梯度下降。在遇到神经网络收敛速度很慢或梯度爆炸等无法训练情况下,都可以尝试使用批标准化来解决,示例:
fc_mean,fc_var=tf.nn.moments(Wx_plus_b,axes=[0],)
scale=tf.Variable(tf.ones([out_size]))
shift=tf.Variable(tf.ones([out_size]))
epsilon=0.001
Wx_plus_b=tf.nn.batch_normalization(Wx_plus_b,fc_mean,fc_var,shift,scale,epsilon)
规范化,也称标准化,是将数据按比例缩放,使之落入一个小的特定区间,这里是将数据减去平均值再除以标准差。

6.神经元函数:

1)激活函数:
激活函数用于运行时激活神经网络中某一部分神经元,将激活信息向后传入下一层的神经网络。因为神经网络的数学基础是处处可微的,选取的激活函数要能保证数据输入与输出也是可微的。TensorFlow中激活函数在/tensorflow/python/ops/nn.py中,包括处处可微的sigmoid、tanh、elu、softplus和softsign,也包括连续但不是处处可微的relu、relu6、crelu和relu_x,以及随机正则化函数dropput。常用的是sigmoid、tanh、relu和softplus。
relu是目前最受欢迎的激活函数,softplus可以看作是relu的平滑版本。relu能够保证x>0时保持梯度不衰减。示例:
a=tf.contant([-1.0,2.0])
with tf.Session() as sess:
    b=tf.nn.relu(a)
    print(sess.run(b))
2)卷积函数:
卷积函数是在一批图像上扫描的二维过滤器,定义在/tensorflow/python/ops/nn_impl.py和nn_ops.py中。包括convolution、conv2d、depthwise_conv2d、separable_conv2d、atrous_conv2d、conv2d_transpose、conv1d、conv3d、conv3d_transpose等。如:
tf.nn.convolution(input,filter,padding,strides=None,dilation_rate=None,name=None,data_format=None)
这个函数计算N维卷积的和。
3)池化函数:
池化函数一般跟在卷积函数的下一层,定义在/tensorflow/python/ops/nn.py和gen_nn_ops.py中,有avg_pool、max_pool、max_pool_with_argmax、avg_pool3d、max_pool3d、fractional_avg _pool、fractional_max_pool、pool。如:
tf.nn.avg_pool(value,ksize,strides,padding,data_format='NHWC',name=None)
4)分类函数:
TensorFlow常用的分类函数主要有sigmoid_cross_entropy_with_logits、softmax、log_softmax、
softmax_cross_entropy_with_logits等,主要定义在/tensorflow/python/ops/nn.py和nn_ops.py文件中。如:
tf.nn.softmax(logits,dim=-1,name=None)
5)优化方法:
目前加速训练的优化方法基本都是基于梯度下降的,梯度下降是求函数极值的一种方法。TensorFlow提供了很多优化器,常用的有GradientDescentOptimizer、AdadeltaOptimizer、AdagradOptimizer、AdagradDAOptimizer、MomentumOptimizer、AdamOptimizer、FtrlOptimizer、RMSPropOptimizer。
在不调整参数情况下AdagradOptimizer比GradientDescentOptimizer和MomentumOptimizer法更稳定,性能更优;精调参数的GradientDescentOptimizer和MomentumOptimizer法在收敛速度和准确性上要优于AdagradOptimizer法。

7.模型的存储与加载:

当训练完一个模型时,想下一次再用,就需要在训练完成时把训练参数保存起来,在下次要使用时重新把参数装载进TensorFlow。TensorFlow提供了存储和加载模型的API。
1)模型的保存:
模型的保存实际上就是TensorFlow中变量的保存,TensorFlow提供了tf.train.Saver类的save()方法来保存变量,生成的检查点文件扩展名.ckpt,包含权重和其他在程序中定义的变量,不包含图结构。如果需要在另一个程序中使用,需要重新创建图结构,并告知怎样处理这些权重。
import tensorflow as tf
# 定义变量
v1=tf.Variable(...,name="v1")
v2=tf.Variable(...,name="v2")
step=0
init_op=tf.global_variables_initializer()
# 定义保存参数的saver
saver=tf.train.Saver()
with tf.Session() as sess:
sess.run(init_op)
while True:
        step+=1
        # 接下去做模型的训练过程
        ......
        if step % 10000 == 0:
            # 保存模型参数
            save_path=saver.save(sess, "./model/model.ckpt", global_step=step)
            print("Model saved in file: %s" % save_path)
tf.train.Saver()默认是对所有变量进行操作,也可以通过传入变量作为参数,指定只对一部分变量进行保存。在save操作的时候,如果传入globe_step参数的值,会在保存文件名后面添加一个global_step值的数字,这样可以区分是训练到第几步时保存的模型。
2)模型的载入:
模型的装载就是将在save操作中保存的文件重新装载到TensorFlow中,TensorFlow提供了tf.train.Saver类的restore()方法来将变量的值重新载入模型。
在TensorFlow中,模型文件中保存的变量必须和要被装载的变量一致,否则会提示在模型文件中缺少对应的变量。
import tensorflow as tf
# 定义变量
v1=tf.Variable(..., name="v1")
v2=tf.Variable(..., name="v2")
init_op=tf.global_variables_initializer()
# 处理保存和装载参数的saver
saver=tf.train.Saver()
with tf.Session() as sess:
    # 载入模型
saver.restore(sess, "/tmp/model.ckpt")
# 接下来去做其他训练的逻辑
在成功载入模型后,把变量的值初始化为模型中保存的值,所以就不需要再执行变量的初始化操作了。
如果有训练好的模型变量文件,可以使用saver.restore进行模型加载:
with tf.Session() as sess:
    tf.initialize_all_variables().run()
    ckpt=tf.train.get_checkpoint_state(ckpt_dir)
    if ckpt and ckpt.model_checkpoint_path:
        print(ckpt.model_checkpoint_path)
        saver.restore(sess,ckpt.model_checkpoint_path)
3)图文件保存和加载:
生成图协议文件扩展名一般为.pb,这是一个二进制文件,用tf.train.write_graph()保存,只包含图结构,不包含权重,然后使用tf.import_graph_def()来加载图形。
v=tf.Variable(0,name='my_variable')
sess=tf.Session()
tf.train.write_graph(sess.graph_def,'/tmp/tfmodel','train.pbtxt')
读取时,从协议文件中读取出来:
with tf.Session as _sess:
with gfile.FastGFile("/tmp/tfmodel/train.pbtxt",'rb') as f:
graph_def=tf.GraphDef()
graph_def.ParseFromString(f.read())
_sess.graph.as_default()
tf.import_graph_def(graph_def,name='tfgraph')

8.队列和线程:

1)队列:
TensorFlow中主要有两种队列,FIFOQueue和RandomShuffleQueue,源代码在/tensorflow /python/ops/data_flow_ops.py中,其中FIFOQueu是先入先出队列,在语音、文字样本训练中常用。RandomShuffleQueue是随机队列,使用CNN时可以无序读入训练样本。TensorFlow的会话是支持多线程的,可以在主线程中执行训练操作,使用RandomShuffleQueue作为训练输入,开多线程来准备训练样本,将样本压入队列后,主线程会从队列中每次取出mini-batch的样本进行训练。
2)线程:
使用coordinator来管理线程。

9.使用GPU:

在使用TensorFlow进行计算的时候,既可以将计算放到本机的CPU上,也可以放到本机的任意一个GPU上。在分布式计算时,可以将计算放到同属一个集群的另外一台机器的GPU上。
1)指定GPU设备:
默认情况下,TensorFlow在启动时,会占用这台机器上所有可见的GPU。有时候想让不同的计算分布到不同的计算设备上,有些操作想让其在CPU上计算,有的计算想让它在第一块GPU上计算,有的操作想让它在第二块GPU上计算。
TensorFlow通过with tf.device()语句将包含在自己作用域下的变量和操作派到特定的CPU或GPU上。示例:
with tf.device("/cpu:0"):
    # 这个with语句下的变量和操作会分配到CPU上
    v1=tf.constant(1)
    v2=tf.constant(2)
with tf.device("/gpu:0"):
    # 这个with语句下的变量和操作会分配到第一个GPU上
    v3=tf.constant(3)
    v4=tf.constant(4)
with tf.device("/gpu:1"):
    # 这个with语句下的变量和操作会分配到第二个GPU上
    v5=tf.constant(5)
可以通过设置Session的配置参数log_device_placement为True来显示变量的分配情况:
with tf.Session(config=tf.ConfigProto(log_device_placement=True)) as sess:
    print(sess.run(v5))
这里会在会话启动后,打印各个变量被分配给了哪个设备。当指定的设备不存在时,TensorFlow会报错,为了方便处理这种情况,可以将Session的配置参数allow_soft_placement设置成True,当分配的设备不存在时,允许TensorFlow自动分配到其他存在的设备。示例:
with tf.Session(config=tf.ConfigProto(log_device_placement=True, allow_soft_placement=True)) as sess:
通过with tf.device()语句,在一个具有多个GPU的机器上,就可以将操作根据需求分配到各个GPU上,再加以灵活运用就可以实现单机多GPU的训练。
2)指定GPU显存占用:
默认情况下,不管程序实际运行会占用多少显存,为了在后续计算中提高显存的使用效率,TensorFlow在Session一启动时,就会预先将实际显存的95%分配完,这在参数规模小的时候非常浪费。当程序用不完那么多显存,又不想一次性占用95%的显存时,可以通过配置Session的参数gpu_options.per_process_gpu_memory_fraction来指定分配显存的百分比。
config=tf.ConfigProto()
config.gpu_options.per_process_gpu_momery_fraction=0.5
with tf.Session(config=config) as sess:
......
如果不想提前分配好显存,而是按实际使用分配显存,可以通过指定Session的配置参数gpu_options.allow_growth的值为True来实现。示例:
config=tf.ConfigProto()
config.gpu_options.allow_growth=True
with tf.Session(config=config) as sess:
......

10.数据读取:

TensorFlow的实际计算在会话中完成,读取数据的方式主要有以下3种:
·使用placeholder填充读入数据的方式
·从文件读入数据的方式
·预先读入数据到内存的方式
1)使用placeholder填充方式读取数据:
在构建计算图时,在要输入的数据的变量的位置采用占位的方式先保留一个placeholder的张量,表示在构建图的时候并不知道实际值,需要在图执行时填充进来。
如果构建了一个包含placeholder操作的图,当在session中调用run方法时,placeholder占用的变量必须通过feed_dict参数传递进去,否则执行会报错。
2)从文件中读入数据的方式:
采用placeholder方式,可以手动读取文件的内容。但是在整个计算过程中,每次需要先将数据从文件读入到内存,然后根据变量定义在CPU还是GPU上,再将内容传送到内存中的变量或者显存的变量。在计算过程中,有一部分时间GPU并没有在计算,而是等待从硬盘读入数据。从硬盘中读取数据在整个过程中效率最低,需要高效的数据读取方式。
TensorFlow提供了很多方便的接口支持从文件中读取数据,实现了从文件中读取数据到内存与将内存中的数据进行计算这两个操作的分离。计算操作不用等待数据从硬盘读入,而是直接读取存在内存中的数据。TensorFlow还提供了从多个文件同时读取数据,并将数据随机打乱等功能。
⑴读取CSV格式的文件数据:
TensorFlow目前默认支持三种文件格式的文件读取,CSV格式文件、二进制格式文件、TFRecords格式文件。CSV格式的文件,每个字段之间采用逗号或者其他自定义的分隔符分开。对于CSV格式的文件,先采用文本方式的tf.TextLineReader()读取文本,然后通过reader. read()从输入文件读取数据,read()函数的返回值是key和value,其中value中包含了实际的数据,然后采用tf.decode_csv()方法进行解码,解码出来的结果就是从文件中读出的数据。
会话中运行tf.train.start_queue_runners会启动为输入数据服务的线程,将样本数据填入到队列,为训练读取数据做好准备,否则训练过程会一直阻塞,处于等待数据的状态。采用tf.train.Coordinator对象的方式是为了在这些线程发生异常时,更好地关闭这些线程。在会话的sess.run()中执行计算时,在从队列中读取数据的同时,负责从文件中读取数据的线程会不断往队列中塞入数据,保持读写分离。
要从3个文件A、B、C中读取数据,先对文件名进行打乱并放入文件名队列,然后设置了两个读文件的Reader线程以便从文件队列中读取数据,在读取了数据之后交给解码器来解析得到样本的值并放入样本队列里。会话中使用数据的线程从样本队列中读取数据,同时Reader线程可以从文件队列里读取数据并填补到样本队列里。采用这种文件读取数据的方式,在训练模型中读取数据时,读取数据的操作一直从内存中进行,这样可以加快训练速度。
TensorFlow通过捕获异常方式来结束文件的读取,当读取文件的迭代次数到达定义的num_epoche的次数时,就会抛出tf.errors.OutOfRangeError异常,表示数据已经读取完毕,这时退出计算过程。
⑵读取二进制格式文件:
除了可以按行的方式读取文本数据以外,TensorFlow还可以读取二进制文件数据。读取二进制文件数据的读取器是tf.FixedLengthRecordReader(),它每次从文件中读取固定长度的数据,所以要求在文件中保存的每个样本所占的空间一样。读取完数据之后,采用tf.decode_raw进行解码,将数据转成指定的张量格式。
⑶读取TFRecord格式的文件:
更加结构化的数据格式是TensorFlow标准格式,即TFRecord格式。使用TFRecord格式的数据时,需要先使用tf.python_io.TFRecordWriter将数据序列化成tf.train.Example类型的protocol buffer数据,然后在程序运行计算时,通过tf.TFRecordReader读取文件,再用tf.parse_single_ example进行解码。
在TFRecord中保存的数据也是按照样本一个一个保存的,根据样本中各个数据的类型,采用不同的数据组合方式,构建tf.train.Features,其结构按照protocol buffer。示例中v1和v2都是int类型的,按照protocol构造Int64List类型的数据,然后再根据Feature结构的定义构造tf.train.Feature。由Features构建Example,将Example序列化后写入文件,序列化的样本数据采用SequenceExample类。
⑷数据打包:
深度学习训练中,通常将多个样本放到一起进行,这样可以加快训练深度和让梯度下降更加平稳。可以采用如下方法将读取的v1和v2打包成batch_size大小的数据,并且将数据随机打乱。示例:
batch_v1, batch_v2=tf.train.shuffle_batch([v1,v2], batch_size=10, num_threads=16,
            capacity=100, min_after_dequeue=20)
其中,batch_size为batch的大小,num_threads为处理线程数,capacity为队列大小,min_after_ dequeue为出队队列最少保留样本数。
通过v1.get_shape()和batch_v1.get_shape()查看各个变量的形状,batch_v1的形状比v1的形状多了一个维度,这个维度的大小是batch_size。
3)预先读入内存的方式:
如果训练数据的数据量比较小,可以采用一次性将数据载入内存的方式。一次性将数据载入内存有两种方式:
⑴将数据载入常量Tensor:
train_data=read_train_data()
with tf.Session() as sess:
    input_data=tf.constant(train_data)
⑵将数据载入变量Tensor:
将数据载入变量中,要初始化后才能使用。示例:
train_data=read_train_data()
with tf.Session() as sess:
train_data_initializer=tf.placeholder(dtype=train_data.dtype, shape=train_data.shape)
input_data=tf.Variable(train_data_initializer, trainable=False, collection=[])
......
sess.run(input_data.initializer, feed_dict={train_data_initializer:train_data})
因为训练数据不需要改变,也不需要保存到模型,所以在对输入训练数据进行处理时,设置tf.Variable()的参数trainable=False,这样数据的值在训练过程中就不会被更新。
⑶打乱预读入数据:
将数据读入常量或变量后,可以采用tf.train.slice_input_producer()方法一次取出一个样本数据,因为所有的数据都已经载入了内存,默认情况下这个方法会预先对整个数据集做打乱处理。如果要读取一个batch大小的数据,可以使用tf.train.batch()方法读取batch_size大小的数据。示例:
train_data=read_train_data()
with tf.Session() as sess:
    input_data=tf.constant(train_data)
    input_data_slice=tf.train.slice_input_producer([input_data], num_epochs=10)
    # 将输入数据打包成batch_size大小的样本集合
input_batch_data=tf.train.batch([input_data_slice], batch_size=32)

11.利用TensorBoard进行数据可视化:

TensorFlow提供了TensorBoard工具可视化数据,帮助理解、调试、优化神经网络训练。
1)查看图的结构:
运行一段代码,其中包含file=tf.summary.FileWrite(path)和file.add_graph(graph)语句。然后在命令行中输入tensorboard --logdir=path。命令成功后会显示一个网页链接,一般端口使用6006。在浏览器打开此链接就可以看到Graph。
因为tensorboard是以Python包引入的,所以可以在Anaconda的命令行中运行,但无法在IDEL及DOS命令行中运行。
2)查看数据变化趋势:
使用tf.summary.scalar(name,tensor)收集训练过程中的数据,如果要收集多项数据,使用方法tf.summary.merge_all(),将所有收集数据的操作整合起来。
3)训练过程数据分布可视化:
还可以使用tf.summary.histogram来查看一个任意维度的Tensor中包含的所有数据分布。使用的变量为矩阵方式。通过tf.summary.histogram将多维张量的数据分布记录到event文件中:
tf.summary.histogram("weight",weight)
tf.summary.histogram("bias",bias)
4)使用技巧:
⑴tf.summary.image:
使用tf.summary.image可以在进行图像训练过程中辅助记录一些图片信息,记录信息可以在TensorBoard的IMAGES菜单中查看。语法:
tf.summary.image(name,tensor,max_outputs=3,collections=Mone):
其中,name为自定义名称;tensor保存了要记录的图像数据,为4维,[batch_size, height, width, channels],batch_size表示batch大小,height为图像高度,width为图像宽度,channels为图像的通道数量;max_outputs为TensorBoard中展示的图片个数;collections为可选项,默认None。
⑵tf.summary.audio:
使用tf.summary.audio可以在音频训练过程中辅助记录音频信息,记录的信息可以在AUDIO菜单中查看。语法:
tf.summary.audio(name,tensor,sample_rate,max_outputs=3,collections=Mone):
其中,保存记录的音频数据的tensor必须是3维,[batch_size,frames,channels],其中batch_size表示batch的大小,frames表示帧数,channels表示声道数;sample_rate为音频采样率。
⑶两个训练过程的数据对比:
通过在TensorBoard命令的参数中指定两个不同event数据的文件夹,可以让相同名字的数据在同一表中展示出来,方便对比。示例:
tensorboard --logdir=model1:model1_event_dir,model2:model2_event_dir
其中,model1是自定义的第一个图表名,model1_event_dir是保存event数据的文件夹,model2是自定义的第二个图表名,mode21_event_dir是保存event数据的文件夹。

12. 示例:实现一个单输入神经元

1)定义神经网络模型:
单神经元包含一个输入值、一个权重和一个输出,权重与输入相乘产生输出。输入是一个常数;权重在网络训练中会改变,所以用变量定义;期望值指完成网络学习后期望的输出值,定义为常量。通过输入、权重、期望值就定义了一个神经元的模型model:
model=tf.multiply(input_value, weight, "model")
2)定义学习元素:
神经网络中很重要的是学习,是通过学习过程来获取适宜的权重。学习过程需要定义度量标准和优化方法。度量标准是实际得到的输出与期望输出之间的差别,即损失函数,一般可以定义为模型输出与期望输出之差的平方:
loss_func=tf.pow(expected_output-model, 2, name="loss_function")
训练神经元过程中,优化损失函数或最小化其值有多种优化方法,常用的是梯度下降法。TensorFlow中梯度优化函数为tf.train.GradientDescentOptimizer:
optimizer=tf.train.GradientDescentOptimizer(learning_rate=0.025)
此函数需要设定一个学习率learning_rate,此处赋值为0.025。这样就定义完成了一个单神经元模型需要的所有参数。
3)定义TensorBoard显示需要的参数:
为了在TensorBoard中显示神经网络的结构及参数,还设置了要显示的参数:
for value in [input_value, weight, expected_output, model, loss_func]:
tf.summary.scalar(value.op.name, value)
每一个需要显示的值都被传给tf.summary.scalar函数,该函数包含两个参数,value.op.name为汇总的标签,value为汇总的值,函数输出一个summary记录。后面要将计算图中收集到的所有汇总数据合并:
summaries=tf.summary.merge_all()
4)计算图:
创建Session会话。
sess=tf.Session()
因为需要把数据汇总到TensorBoard显示,要创建SummaryWriter:
summary_write=tf.summary.FileWriter('log_simple_stats', sess.graph)
SummaryWriter提供了一种机制,用于在每条路径中创建事件记录文件,并向其中添加汇总和事件。该类对文件内容的更新是非同步的,因此在训练过程中向日志文件添加数据,不需要放慢训练过程。
然后运行定义的模型:
sess.run(tf.global_variables_initializer())
最后进行100次训练,每次训练都会监视summary_writer中定义的参数:
运行完成后可以在TensorBoard创建的日志中看到可视化的设置参数数据。全部代码示例为:
import tensorflow as tf
input_value=tf.constant(0.5,name="input_value")
weight=tf.Variable(1.0,name="weight")
expected_output=tf.constant(0.0,name="expected_output")
model=tf.multiply(input_value, weight, "model")
loss_func=tf.pow(expected_output-model, 2, name="loss_function")
optimizer=tf.train.GradientDescentOptimizer(0.025).minimize(loss_func)
for value in [input_value, weight, expected_output, model, loss_func]:
    tf.summary.scalar(value.op.name, value)
summaries=tf.summary.merge_all()
sess=tf.Session()
summary_writer=tf.summary.FileWriter('log_simple_stats', sess.graph)
sess.run(tf.global_variables_initializer())
for i in range(100):
    summary_writer.add_summary(see.run(summaries),i)
sess.run(optimizer)

二、TensorFlow框架:

1.TFLearn:

TFLearn是建立在TensorFlow顶部的模块化深度学习框架。使用Flower Dataset数据集构建AlexNet网络模型的方法:
import tflearn
from tflearn.layers.core import input_data,dropout,fully_connected
from tflearn.layers.conv import conv_2d,max_pool_2d
from tflearn.layers.normalization import local_response_normalization
from tflearn.layers.estimator import regression
omport tflearn.datasets.oxflower17 as oxflower17
X,Y=oxflower17.load_data(one_hot=True,resize_pics=(227,227))
#构建AlexNet网络
network=input_data(shape=[None,227,227,3])
network=conv_2d(network,96,11,strides=4,activation='relu')
network=max_pool_2d(network,3,strides=2)
network=local_response_normalization(network)
network=conv_2d(network,3,strides=2)
network=max_pool_2d(network,3,strides=2)
network=local_response_normalization(network)
network=conv_2d(network,384,3,activation='relu')
network=conv_2d(network,384,3,activation='relu')
network=conv_2d(network,256,3,activation='relu')
network=max_pool_2d(network,3,strides=2)
network=local_response_normalization(network)
network=fully_connected(network,4096,activation='tanh')
network=dropout(network,0.5)
network=fully_connected(network,4096,activation='tanh')
network=dropout(network,0.5)
network=fully_connected(network,4096,activation='softmax')
network=regression(network,optimizer='momentum',loss='categorical_crossentropy',learning_rate=0.001)
#训练模型
model=tflearm.DNN(network,checkpoint_path='Model_alexnet',max_checkpoints=1,tensorboard_verbose=2)
model.fit(X,Y,n_epoch=1000,validation_set=0.1,shuffle=True,show_metric=True,batch_size=64,snapshot_step=200,snapshot_epoch=False,run_id='alexnet_oxflowers17')
2.Keras:

Keras是TensorFlow的默认框架,可用来快速搭建网络,而且兼容Theano。Keras的核心数据结构是模型,模型有Sequential和Model两种,Sequential模型是一系列网络层按顺序构成的栈,单输入单输出,层与层之间只有相邻关系,是一种最简模型;Model用于搭建更复杂的模型。使用pip3安装keras后,需要选择依赖的后端,修改~/.keras/keras.json中内容:
{
  "image_dim_ordering":"tf",
  "epsilon":1e-07,
  "floatx":"float32",
  "backend":"tensorflow"
}
1)Sequential模型:
from keras.models import Sequential
from leras.layers import Dense,Activation
model=Sequential()
model.add(Dense(output_dim=64,input_dim=100))
model.add(Activation("relu"))
model.add(Dense(output_dim=10))
model.add(Activation("softmax"))
然后编译:
model.compile(loss='categorical_crossentropy',optimizer='sgd',metrics=['accuracy'])
最后训练模型和评估模型:
model.fit(X_train,Y_train,nb_epoch=5,batch_size=32)
loss_and_metrics=model.evaluate(X_test,Y_test,batch_size=32)
2)卷积神经网络:
先定义参数及加载数据:
batch_size=128
nb_classes=10 #分类数
nb_epoch=12 #训练轮数
img_rows,img_cols=28,28 #输入图片维度
nb_filters=32 #卷积滤镜的个数
pool_size=(2,2) #最大池化,池化核大小
kernel_size=(3,3) #卷积核大小
(X_train,Y_train),(X_test,y_test)=mnist.load_data()
if K.image_dim_ordering()=='th':
  # 使用Theano的顺序:(conv_dim1,channels,conv_dim2,conv_dim3)
  X_train=X_train.reshape(X_train.shape[0],1,img_rows,img_cols)
  X_test=X_test.reshape(X_test.shape[0],1,img_rows,img_cols)
  input_shape=(1,img_rows,img_cols)
else:
  # 使用TensorFlow的顺序:(conv_dim1,conv_dim2,conv_dim3,channels)
  X_train=X_train.reshape(X_train.shape[0],img_rows,img_cols,1)
  X_test=X_test.reshape(X_test.shape[0],img_rows,img_cols,1)
  input_shape=(img_rows,img_cols,1)
X_train=X_train.astype('float32')
X_test=X_test.astype('float32')
X_train/=255
X_test/=255
#将类向量转换为二进制类矩阵
Y_train=np_utils.to_categorical(y_train,nb_classes)
Y_test=np_utils.to_categorical(y_test,nb_classes)
然后构建模型,使用2个卷积层、1个池化层和2个全连接层:
model=Sequential()
model.add(Convolution2D(nb_filters,kernel_size[0],kernel_size[1],border_mode='valid',input_shape=input_shape))
model.add(Activation('relu'))
model.add(Convolution2D(nb_filters,kernel_size[0],kernel_size[1]))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=pool_size))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(nb_classes))
model.add(Activation('softmax'))
编译模型,采用多分类的损失函数,用Adadelta算法做优化:
model.compile(loss='categorical_crossentropt',optimizer='adadelta',metrics=['accuracy'])
训练模型,输入训练集和测试数据,及batch_size和nb_epoch参数:
model.fit(X_train,Y_train,batch_size=batch_size,nb_epoch=nb_epoth,verbose=1,validation_data=(X_test,Y_test))
评估模型,输出测试集损失值和准确率:
score=model.evaluate(X_test,Y_test,verbose=0)
print('Test score: ',score[0])
print('Test accuracy: ',score[1])
3)模型的加载及保存:
Keras的savce_model和load_model方法可以将Keras模型和权重保存在一个HDF5文件中,包括模型的结构、权重、训练配置等。如果训练意外中止,可用这个HDF5文件从上次训练的地方重新开始训练。
keras/tests目录中的test_model_saving.py文件中给出了加载和保存模型的方式。如果只是希望保存模型的结构,而不包含其权重好及训练的配置,可以将模型序列化成json或yaml:
json_string=model.to_json()
json_string=model.to_yaml()
保存完成后,还可以手动编辑,并且使用下面语句加载:
from keras.models import model_from_json
model=model_from_json(json_string)
model=model_from_yaml(yaml_string)
如果仅需要保存模型的权重,而不包含模型的结构,可以使用save_weights和load_weights:
model.save_weights('my_model_weights.h5')
model.load_weights('my_model_weights.h5')

Copyright@dwenzhao.cn All Rights Reserved   备案号:粤ICP备15026949号
联系邮箱:dwenzhao@163.com  QQ:1608288659