TensorFlow初学梗概
该文章作为TensorFlow初学者笔记记录,属个人经验总结,仅供参考。
一、前言
有在学习人工智能相关,在做深度强化学习方向的应用。因无相关基础,又GitHub上许多项目多以TensorFlow为纲,故习之。参考书目:《TensorFlow实战Google深度学习框架》(第二版)。
二、TensorFlow简介
TensorFlow是当前人工智能主流开发工具之一,是谷歌于2015年11月9日正式开源的计算框架,是基于由 Jeff Dean 领头的谷歌大脑团队基于谷歌内部第一代深度学习系统 DistBelief 改进来的通用计算框架,在GitHub和工业界有较高的应用程度和实用度。
三、TensorFlow入门
计算图是TensorFlow中最基本的一个概念,是TensorFlow的计算模型,TensorFlow中所有的计算都被转化为计算图上的节点,而节点之间的边描述了计算之间的依赖关系。
张量(tensor)是TensorFlow基础的数据模型。TensorFlow的名字已经说明了它最重要的两个概念——Tensor和Flow。Tensor就是张量,我们可以理解成多维数组,零阶张量表示标量(scalar),也就是一个数;第一阶张量为一个向量(vector),也就是一个一维数组;第n阶张量可以理解为一个n维数组。Flow翻译成中文就是“流”,它直观地表达了张量之间通过计算相互转化的过程。TensorFlow中对张量的实现并不是直接采用数组的形式,它只是对TensorFlow中运算结果的引用。
import tensorflow as tf
# TensorFlow使用时非常常用的技巧,即用tf代指tensorflow。
a = tf.constant([1.0, 2.0], name="a")
b = tf.constant([2.0, 3.0], name="b")
result = tf.add(a, b, name="add")
print result
'''
输出:
Tensor("add:0", shape=(2,), dtype=float32)
'''
从以上代码可以看出,TensorFlow计算的结果不是一个具体的数字,而是一个张量的结构,其保存了三个属性:名字(name)、维度(shape)和类型(type)。add:0
说明了张量result是计算节点“aad”输出的第一个结果(编号从0开始),shape=(2,)
说明了张量result这个张量是一个一维数组,长度为2,dtype=float32
指明了其数值的数据类型。
如上图,add节点为计算图的的一个节点,其依赖读取两个常量的取值,result作为对add计算结果的引用,这就是TensorFlow基本的计算模型。
TensorFlow在对张量和计算的定义时要注意数据类型与数据维度的指定,相同数据类型和有合适维度的数据才可以相互计算。TensorFlow支持14中不同的类型,主要包括了实数(tf.float32、tf.float64)、整数(tf.int8、tf.int16、tf.int32、tf.int64、tf.uint8)、布尔型(tf.bool)和复数(tf.complex64、tf.complex128)。
会话(session)是TensorFlow的运行模型。TensorFlow中的计算被定义后需要使用session来执行。
# 创建一个会话。
sess = tf.Session()
# 使用这个创建好的会话来计算关心的结果。比如可以调用sess.run(result),
# 来得到执行定义的result的取值。
sess.run(...)
# 关闭对话框使得本次运行中使用到的资源可以被释放。
sess.close()
四、TensorFlow实现神经网络
基于反向传播算法的神经网络流程图如下:
步骤如下:
- 定义神经网的络结构和前向传播的输出结果;
- 定义损失函数以及选择反向传播优化的算法;
- 生成会话(tf.Session)并且在训练数据上反复运行反向传播优化算法。
实现样例:
import tensorflow as tf
from numpy.random import RandomState
# 定义训练数据batch的大小
batch_size = 8
# 定义两层网络结构
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=(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)
# 定义损失函数与反向传播算法
y = tf.sigmoid(y)
cross_entropy = -tf.reduce_mean(
y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0))
+ (1-y_) * tf.log(tf.clip_by_value(1-y, 1e-10, 1.0))
)
tran_step = tf.train.AdadeltaOptimizer(0.01).minimize(cross_entropy)
# 通过随机数生成一个模拟数据集
rdm = RandomState(1)
dataset_size = 128
X = rdm.rand(dataset_size, 2)
# 定义模拟标签规则
Y = [[int(x1 + x2 < 1)] for (x1, x2) in X]
# 创建一个会话来运行TensorFlow程序
sess = tf.Session()
init_op = tf.global_variables_initializer()
sess.run(init_op)
# 打印训练之前的参数
print(sess.run(w1))
print(sess.run(w2))
# 定义轮数和数据选取方并进行训练
STEPS = 50000
for i in range(STEPS):
start = (i * batch_size) % dataset_size
end = min(start + batch_size, dataset_size)
sess.run(tran_step, feed_dict={x: X[start:end], y_: Y[start:end]})
# 每10000轮打印一次神经网络在总的数据集上的损失函数
if i % 10000 == 0:
total_cross_entropy = sess.run(
cross_entropy, feed_dict={x: X, y_: Y}
)
print(i)
print(total_cross_entropy)
# 打印训练之后的参数
print(sess.run(w1))
print(sess.run(w2))
sess.close()
深度神经网络分析:
- 常用的激活函数有:
tf.nn.relu
、tf.sigmoid
、tf.tanh
; - 交叉熵实现:
cross_entropy = -tf.reduce_mean( y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)))
; - MSE:
tf.reduce_mean(tf.square(y_ - y))
; - 常用优化算法:
tf.train.GradientDescentOptimizer(learning_rate).minmize(loss_fuction)
、tf.train.AdamOptimizer
、tf.train.MomentumOptimizer
; - 学习率衰减方法:
tf.train.exponential_decay
; - 正则化公式:
tf.contrib.layers.l1_regularizer(lambda)(w)
、tf.contrib.layers.l2_regularizer(lambda)(w)
; - 滑动平均模型实现方法:
tf.trian.ExponentialMovingAverage(decay, num_updates)
;
五、学习小结
总的来说TensorFlow还是挺容易上手的,没有传闻的那么不堪。我省略了TensorFLow的下载与环境配置的步骤,因为那一部分实在繁琐,不同版本之间兼容性较差,具体解决问题的办法是从网上东拼西凑找到的,不值得参考。
TensorFlow的核心观念很是新颖,以计算为轴而不是以数据为轴,这充分体现了计算对于人工智能的重要程度,在神经网络的构建与算法的实现上提供了新的观点与角度。至于比较的部分,未上手过PyTorch或其他构建工具,故不做评价。
很期待下一步上手项目实践。
(感谢阅读,如有错误,欢迎指正。)