目录结构:
- 深度学习简介
- Tensorflow系统介绍
- Hello TensorFlow
- CNN 看懂 世界
- RNN 能说会道
- CNN+LSTM看图说话
- 损失函数与优化算法
这本书很适合有一定机器学习基础的人阅读, 书中首先第一章会介绍深度学习是什么、发展趋势如何,第二章介绍了Tensorflow是如何通过 “图” 来简单方便地构建一个神经网络,第三章简单介绍了安装以及相关的python库,然后使用kaggle经典题目Titanic,结合代码进行讲解如何使用。后面几章是关于CNN ,RNN, LSTM 、等介绍,深入了解的话还是需要看技术博客。
这本书是使用的tf1,当然现在已经是tf2了,不过目前中文的tf2书籍不多(我是没找到) ,这本书对了解框架是如何实现神经网络是很有帮助的。1~4章总体来说还是很适合入门的,后面的酌情看吧…我是有点看不太懂,需要翻博客补充知识。
下面是一开始记的笔记(就是截图加码字),后面因为是看一页就要翻一堆的博客就没再记了(太菜了)。
第二章 Tensorflow系统介绍
计算图
Tensorflow是一个基于数据流图的数值计算开源软件
数据流图是有向图,图中的点表示各种数学计算操作的算子(operations, 简称op),
边表示操作与操作之间传递的高维数组数据,称为tensor
计算图的执行可以看作数据 tensor按照图的拓扑顺序,从输入节点逐步流过所有中间节点,最后流到输出节点的过程, Tensorflow的名字由此而来。
算子(op) 是参与计算的基本单位, 每个算子对应一种数学运算(如: 矩阵加法,矩阵乘法等),算子接收0或多个tensor作为输入,进行一定的计算,输出0个或多个tensor结果。Tensorflow内置了多种算子
在tensorflow中,以变量(Variable) 来存储参数,变量可以与tensor一样参与各种运算, 区别在于tensor的值在每次计算图执行完成之后立即被丢弃, 而变量的值在通过反向传播计算更新后会保留下来,带入到下一轮训练迭代。
Session会话
Session是驱动 Tensorflow系统执行计算交互的入口。 Session负责完成多计算设备或集群分布式的节点布置和数据传输节点的添加,并负责将子图分配给相应的执行器单元来运行。
触发计算图的执行通过Run接口, 也就是Python的tf.Session.run()方法, 通过这个接口, 可以将数据带入模型, 执行计算, 并得到执行结果, 训练过程由客户端的循环来控制.
Session管理了运行时的一系列资源的申请和分配,所以在计算完成后,必须要关闭 Session以释放资源。
系统架构
Tensorflow是拥有" client→ master→ worker’”架构的分布式系统。在一般的执行流程中,客户端通过会话 tf Session接口与 master进行通信,并向 master提交触发执行的请求, master将执行任务分配到一个或多个 worker进程上,执行的结果通过 master返回给客户端。其中, worker是最终负责执行计算的角色,每一个 worker进程都会管理和使用计算机上的计算硬件设备资源,包括一块或多块CPU和GPU来处理计算子图( subgraph)的运算过程.
在单机多设备模式下, 为了提高计算机性能, 会将计算图分解成若干个子图, 每个子图被分配到不同的设备上执行, tensorflow通过布置算法决定 算子的安置在某个设备上。
当算子被布置到不同的设备上时系统会自动在跨设备的操作之间加入数据传输算子。
源码结构
Tensorflow的系统实现采用了分层的结构,核心是由C语言实现的后端执行系统,前端则提供了基于多种语言的编程接口。在保证了执行性能的同时,又降低了学习门槛和应用集成的代价。
Tensorflo 的系统实现采用了分层的结构,核心是由C源是先的后端执行系统,前端则提供了局域多种语言的编程结构,在保证了执行小路的同时,又降低了学习门槛和应用继承的的代价。
第三章: 初识Tensorflow
使用kaggle上的Titanic数据进行学习
数据读入与预处理
首先,使用 pandas内置的数据文件解析器读入数据。 pandas内置了多种解析器可以直接处理csv、 pickle、json、excel、html等常用的数据文件格式,甚至还可以从
MYSQL数据库或者操作系统的剪切板中读入数据。读入操作非常简单,只需要用
read csv)函数读取" train.csv"文件,读入的数据为一个 Dataframe类型的对象。然后 ,需要对数据进行预处理 ,如空值填充 ,one-hot转换, 特征选择 等
通过 sklearn工具包, 可以很容易的将训练数据划分为 训练集(training set) 和验证集(validation set)
from sklearn.model_selection import train_test_split
# split training data and validation set data
X_train, X_val, y_train, y_val = train_test_split(dataset_X.as_matrix(), dataset_Y.as_matrix(),
test_size=0.2,
random_state=42)
构建计算图
使用逻辑回归作为分类器
y = softmax(xW + b)
- 使用placeholder 声明输入占位符
# 声明输入数据占位符
# shape参数的第一个元素为None,表示可以同时放入任意条记录
# 参数为元素的类型 ,维度形状和占位符名称表示name
X = tf.placeholder(tf.float32, shape=[None, 6], name='input')
y = tf.placeholder(tf.float32, shape=[None, 2], name='label')
- 声明参数变量
weights = tf.Variable(tf.random_normal([6, 2]), name='weights')
bias = tf.Variable(tf.zeros([2]), name='bias')
- 构造前向传播计算图
y_pred = tf.nn.softmax(tf.matmul(X, weights) + bias)
- 声明代价函数
使用交叉熵作为代价函数
# 使用交叉熵作为代价函数
cross_entropy = - tf.reduce_sum(y * tf.log(y_pred + 1e-10),
reduction_indices=1)
# 批量样本的代价值为所有样本交叉熵的平均值
cost = tf.reduce_mean(cross_entropy)
- 加入优化算法
计算出代价函数后,选择一种方式来优化参数,这里选择使用梯度下降算法 优化器内部会自动构建梯度计算和反向传播部分的计算图
train_op = tf.train.GradientDescentOptimizer(0.001).minimize(cost)
- 计算准确率( 用于展示数据,可选)
# 计算准确率
correct_pred = tf.equal(tf.argmax(y, 1), tf.argmax(y_pred, 1))
acc_op = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
构建训练迭代,执行训练
如下示例代码,首先会启动Session. 然后 对op, tensor进行初始化。
接下来就是两层for循环语句 ,外层的for循环是训练的轮数,内层的for循环调用了会话的run方法,每次都向其发送一组训练数据(第二个参数) , 当整个run方法结束后(误差反向传播结束),将指定的返回参数进行返回( 第一个参数 ,返回的数据用来进行输出打印loss)
with tf.Session() as sess:
# variables have to be initialized at the first place
tf.global_variables_initializer().run()
# training loop
for epoch in range(100):
total_loss = 0.
for i in range(len(X_train)):
# prepare feed data and run
feed_dict = {X: [X_train[i]], y: [y_train[i]]}
_, loss = sess.run([train_op, cost], feed_dict=feed_dict)
total_loss += loss
# display loss per epoch
print('Epoch: %04d, total loss=%.9f' % (epoch + 1, total_loss))
print ("Training complete!")
- session 管理了上下文的各种资源, 因此在计算执行结束后需要关闭,以释放对资源的占用。
- session启动后就正式进入了训练过程,首先需要做的是使用tf.global_variables_initializer().run()初始化所有的op和tesnor
- session.run() 的两个关键参数 fetches 和feed_dict ,fetches可以理解为需要从计算图中获取的数据 ,feed_dict 顾名思义是要"喂" 给流程图的数据。
模型保存
模型保存可以理解为
- 保存整个计算图结构
- 保存训练好的变量(Variable)
具体代码
saver = tf.train.Saver() # 用于保存模型以及加载已有的模型
saver.save() # 指定会话,保存文件名等 保存模型
saver.restore() #指定会话 模型文件 加载模型到会话中
CNN
CNN中的卷积层
从网络结构来说,卷积层节点与全连接层节点有三点主要的不同,一是局部感知域,二是权值共享,三是多核卷积。
局部感知
对于每一个计算单元来说 , 只需要考虑像素位置附近的输入。
权值共享
处理每一个像素点的参数都相同( 共用卷积核)
多核卷积
每个卷积核是一个特征提取器, 若只有一个卷积核的话,就只能提取一种特征。
在tensorflow中加入卷积核
import tensorflow as tf
x=tf.placeholder(tf.float32,shape=[None,256,256,3])
#卷积层,卷积核为3x3,输出32通道,滑动步长为2,边缘向外填充
conv=tf.nn.conv2d(x,filter=[3,3,3,32],strides=[1,2,2,1],padding='SAME')
tf.nn.conv2d (input, filter, strides, padding, use_cudnn_on_gpu=None, data_format=None, name=None)
input: 输入的图片 [ batch, in_height, in_weight, in_channel ]
fileter: 卷积核 [ filter_height, filter_weight, in_channel, out_channels ] out_channels 指定卷积核的数量。
strides: 卷积时在图像每一维的步长,这是一个一维的向量,[ 1, strides, strides, 1],第一位和最后一位固定必须是1
padding: string类型,值为“SAME” 和 “VALID”,表示的是卷积的形式,是否考虑边界。"SAME"是考虑边界,不足的时候用0去填充周围,"VALID"则不考虑
池化
池化是将图像按窗口大小划分成不重叠的区域,然后对每一个区域内的元素进行聚合。一般采用2×2的窗口大小,聚合方法有两种,一种是取最大值,则称为最大池化( max pooling),如图46所示,另一种是取平均值,称为平均池化(averagepooling)。对于窗口为2×2的池化操作,处理完的图像长和宽都是原图的一半,也就是说输出图的尺寸是原图的1/4
pool=tf.nn.max_pool(conv,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
k_size : 池化窗口的大小,取一个四维向量,一般是[1, height, width, 1],
strides : 窗口在每一个维度上滑动的步长,一般也是[1, stride,stride, 1]
ReLU
进行非线性变换.
激活函数
ReLU特点
分类效果好,收敛速度快,计算速度快
多层卷积
卷积网络的每一个阶段都由三种操作组成: 卷积, 池化,和非线性激活函数(ReLu),组成。
由卷积的操作的定义可知, 在不填充输入数据的情况下, 卷积操作后图像输出结果尺寸将变小,通道数会因为多个卷积核的特征提取逐渐增多
随着层数的深入 , 计算机会提取 像素 线条 区域 整体的特征 。 最终由全连接分类器依照最抽象的特征进行分类。
Dropout
Dropout是深度学习领域的泰斗级科学家多伦多大学的 Hinton教授提出的去过拟合技术。以极小的额外代价也能达到集成学习效果的方法。具体来说,就是在每一轮训练的过程中,随机让一部分隐层节点失效,这样就达到了改变网络结构的目的,但每个节点的权值都会被保留下来。在最终预测时,打开全部隐层节点,使用完整的网络进行计算,就相当于把多个不同结构的网络组合在了一起.