tensorflow入门
介绍
谷歌出品的第二代机器学习系统,
表达了高层次的机器学习计算.
(换言之比较方便,最方便的地方在于无需自行给出梯度的计算公式)
还可以运行一些非机器学习的程序.
对python的支持较为及时,C的支持稍微落后.
基础概念
-
图: 所有的操作放在一个由节点和边组成的有向图中
-
节点: 意义上是各种数学操作,简称op(operation),也有的是源节点,不是操作而是常数
-
边:象征着数据的流动方向
-
Tensor:节点间流动的数据,是多维数组
-
session: 一个上下文(context),可以将图中的计算分配到CPU,GPU等设备中,
因此图中定义的运算不会立即运行而是由session运行
基础操作
构建图
完整的构造方法
1 | import tensorflow as tf |
tensorflow有一个默认的图,一般用不到多个图的情况下可以不在图的范围内定义代码
1 | import tensorflow as tf |
运行图
使用Session对象的run方法,
指定一个节点的变量,运行以求值.
Session对象初始化时不指定参数则使用默认图.
sess需要关闭,有时也使用with环境来及时关闭session.
个人认为方式2更整洁.
1 | a=tf.constant([1,2,3,4]) |
还可以指定具体的硬件,
如果系统安装有多个GPU,默认只使用第一个GPU,
可以使用语句指定GPU
1 | with tf.Session() as sess: |
可以使用的设备举例
/cpu:0
/gpu:0
/gpu:1
交互使用
在脚本程序中使用session.run()方法,
在ipython等环境中可以使用 Tensor.eval()
, Operation.run()
等方法交互地运行
1 | import tensorflow as tf |
fetch
即查看某一个变量的状态,可以同时查看多个
1 | input1 = tf.constant(3.0) |
feed
可以在运算过程中替换Tensor
不过常常只是用于为placeholder数据类型填入数据
1 | input1 = tf.placeholder(tf.types.float32) |
变量类型
-
常量(constant)
定义后值和维度不可变,
一定会成为图的节点
过多的节点导致程序运行缓慢1
2
3
4
5
6
7a = tf.constant(2, tf.int16)
b = tf.constant(4, tf.float32)
c = tf.constant(8, tf.float32)
h = tf.zeros([11], tf.int16)
i = tf.ones([2,2], tf.float32)
j = tf.zeros([1000,4,3], tf.float64) -
变量(Variable)
定义后维度不可变,值可变.
常常用于表示权重
还可以包装一个常量变成变量?1
2
3
4
5
6
7
8d = tf.Variable(2, tf.int16)
e = tf.Variable(4, tf.float32)
f = tf.Variable(8, tf.float32)
k = tf.Variable(tf.zeros([2,2], tf.float32))
l = tf.Variable(tf.zeros([5,6,5], tf.float32))
w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1)) -
占位符(placeholder)
没有初始值,只会分配内存
常常用于训练时一个批次的数据的位置
会和feed~dict搭配~
不过由于feed~dict的存在使程序的调试变得比较困难~1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19w1=tf.Variable(tf.random_normal([1,2],stddev=1,seed=1))
# 因为需要重复输入x,而每建一个x常量就会生成一个结点,
# 计算图的效率会低所以使用占位符.
x=tf.placeholder(tf.float32,shape=(1,2))
x1=tf.constant([[0.7,0.9]])
a=x+w1
b=x1+w1
sess=tf.Session()
sess.run(tf.global_variables_initializer())
#运行y时将占位符填上,feed_dict为字典,变量名不可变
y_1=sess.run(a,feed_dict={x:[[0.7,0.9]]})
y_2=sess.run(b)
print(y_1)
print(y_2)
sess.close
常用的数据预处理函数
1 | # Tool functions |
常用的正确率处理函数
1 | # accuracy function |
常用的批次数据生成函数
1 | offset = (step * BATCH_SIZE) % train_labels.shape[0] |
Hello Worlds
过程总结
- 定义常量参数,学习率,patch size等
- 权重的定义
- 网络结构的定义
- 在session中训练
- 准备批次数据
- 训练
- 到一定次数后显示当前状态
人工神经网络ANN
三层全连接网络,无bias
输入层2节点
隐藏层3节点
输出层1节点
1 | import tensorflow as tf |
ANN衰减的学习率
1 | import tensorflow as tf |
类LeNet5网络
重要的是网络的结构,也会在另外的文件中说明
网络的结构(一张图片来说)
- 输入: [IMAGE~HEIGHT~,IMAGE~WIDTH~,IMAGE~DEPTH~]
- 第一层
- 卷积层: 卷积核大小: [PATCH~SIZE1~,PATCH~SIZE1~],数量:PATCH~DEPTH1~,滑动时的步长:宽高各1
- 激活: relu(conv + bias1),由于使用SAME的padding方法,会填充空白使卷积层的大小等于输入图像大小
- 池化: 池化窗口大小: 2 x 2,移动步长: 宽高各2 x 2,导致池化后大小只有原有的1/2.即 [IMAGE~HEIGHT~/2,IMAGE~WIDTH~/2,PATCH~DEPTH1~]
- 第二层
- 卷积层: 卷积核大小: PATCH~SIZE2~ x PATCH~SIZE2~,数量:PATCH~DEPTH2~,滑动时的步长:宽高各1
- 激活,所有层都需要激活
- 池化,结果大小为[IMAGE~HEIGHT~/4,IMAGE~WIDTH~/4,PATCH~DEPTH2~]
- 中间层
将第二层得到的池化后的多层数据摊平 - 第三层
- 全连接层: HIDDEN~SIZE1个神经元~,计算则使用w3 * a3 + b3
- 激活
- 可以选择dropout
- 第四层
- 全连接层: HIDDEN~SIZE2个神经元~
- 激活
- 可选的dropout
- 输出层
- NUM~LABEL个神经元~
1 | graph = tf.Graph() |
其中的 model_lenet5
用于定义网络结构
1 | # Model function |
原版的LeNet5网络使用的是
sigmoid激活函数,不过在有些时候表脸不好
1 | layer1_actv = tf.nn.simoid(layer1_conv + bias['bc1']) |
遇到sigmod函数计算的结果超出了0到1.0范围时,可以使用函数截断
1 | tf.clip_by_value(yhat,1e-10,1.0) |
conv2d函数
参数:
- 输入图像,一个张量,[batch size, height, weight, image depth]
- 权重矩阵,主要表示卷积核的大小,是一个张量
[patch height, patch weight, image depth, patch numbers] - 在图像维度([batch size, height, weight, image depth])上的步长
- padding,处理边缘的方法,只有SAME和VALID两种方法,
- SAME: 卷积的小窗口在图像上滑动时,使用0填充图像的边缘以时卷积图像与输入图像的大小相同
- VALID:
不在边缘填充0,得到的图像大小为:- 输出尺寸O
- 图像尺寸W
- 滤波器尺寸K
- padding尺寸P
- 步长S
avg~pool函数~
配置时与conv2d相似
参数:
- 输入
- 权重矩阵,主要表示池化窗口的大小,注意patch depth与输入匹配
- 在四个维度上的步长
- padding方法