简介
这节课主要的内容其实就是简单的介绍了 TensorFlow 的一些基本理念,和一些简单的用法,并用半节课的时间实现了之前我们做过的实验 Skipgram。
什么是 Tensorflow
- 是一个来自 Google Brain Team 的开源软件
- 是以流图的方式进行数值计算的库
- 用于部署机器学习算法,并执行算法
其他的话:现在学术界很多老师是相当不喜欢 Tensorflow 的,他们更加推崇 Theano 或者 Pytorch,不过 Tensorflow 不论是在 Github 的 Star 数量还是在论文中再现算法的使用量上都占据着比较大的优势。
TensorFlow 的基本使用
前言
这一部分,我将简单的讲课堂上的内容做以笔记,由于今后会大量的使用 Tensorflow,所以之后会另其栏目专门记录学习 TensorFlow 以及其源码的笔记。
TensorFlow 的理念
- 表达计算流程的方式是一个图
- 图的节点代表的是计算(operations)
- 图的边代表的是张量(tensors),可以简单理解为多维数组。
简单使用
一、Variable & Placeholder
- Variable
Variable 是保存图的运算状态的,也就是说模型会保留这些变量,不会删除他们,同时在反向传播中会更新他们。更加具体的来讲,他们就是在我们下载别人训练好的模型时的参数,类似于算法模型这个骨架内的血肉。
1
tf.Variable(tf.zeros((N,))) # 使用有点像numpy
- Placeholder
Placeholder 在中文的教程中很多称之为占位符,他们和 Variable 的不同在于两点:
- 定义的时候不需要指定初始值,它只起占位作用
- 在每个节点运算结束后不会保留或更改它的值
鉴于它的特性,我们很容易想到,Placeholder 的主要作用在于用来存储数据集和标签等操作。它是在运行模型的时候,即执行 session 的时候从外部数据导入的。
1
2
3tf.placeholder(data_type, shape) # eg input_placeholder = tf.placeholder(tf.float32, shape=(batch_size, n_features))
- Operations
我们现在有了变量,那么我们就可以使用他们来计算了。TensorFlow 中有很多计算模块,我们可以十分直观的进行使用,方法如下:
1
2tf.matmul(x, W) tf.nn.relu(tf.matmul(x, W) + b)
注:值得注意的是这里的 + 仍然指代的是 tensorflow 的加法操作,在 tensorflow 中对于直接用符号
+-*/
的加减乘除操作都会自动转换乘相应的 tensorflow 操作。 - 描述图运算 需要强调下,在这里讲课的清秀小哥说,这里的 h 和最终的那个 ReLu 操作的计算单元其实是一样的。这里需要特别注意,因为之后我们用 session 其实本质来讲就是通过类似这种 h 来定位到计算节点来获得输出的。
二、Session
之前我们其实是画出了一个图,我觉得更准确的说法是之前画的是图纸,但是并没有根据图纸进行施工。而 Session 就是做这样一个工作的。
那么第一个问题就 session 调用的图在哪里,其实是有一个默认的 graph 的。我们可以通过 tf.get_default_graph()
得到。其中值得注意的是,在斯坦福的 TensorFlow 课中,讲师特别强调不建议自己定义多个图,使用默认的图就好了1。
使用 session 运行图的步骤:
- 创建一个 session
1
sess = tf.Session()
- 初始化变量
1
2
3
4sess.run(tf,initialize_all_variables()) # 后来清秀小哥使用的方法是 init= tf.global_variables_initializer() sess.run(init)
- 运算
1
sess.run(fetches, feeds)
feches 是图的节点,由于图是一个连通图,所以通过一个节点总能找到所有的节点。而 feeds 则指的是 placeholder 和喂入的数据之间的映射关系。
三、训练神经网络
之前我们可以说是定义了一个图,但是没有定义如何训练它,接下来是将训练部分的内容。
- 定义损失函数
tensorflow 中有很多 API 来定义损失函数,下面是一个例子。
1
2
3
4prediction = tf.nn.softmax(...) #Output of neural network label = tf.placeholder(tf.float32, [100, 10]) cross_entropy = -tf.reduce_sum(label * tf.log(prediction), axis=1)
-
规定如何计算梯度 我们初始化一个 optimizer, 然后在调用 tensorflow 来执行一些梯度下降算法等。由于我们之前学到梯度下降算法是遵循链式法则的,所以每个节点就计算自己的损失就好了,这也是为什么这个库选择使用数据流图来设计的原因之一。
就像大多特定的函数都具有自己特定的导数一样,图中运算节点都附带了梯度操作。在反向传播中,用户不需要编写梯度计算与参数更新的代码,而是交给 optimizer 自动完成。
调用方法如下:
1
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
- 训练 每次执行梯度下降就是一次 epoch,所以简单的来说就是用 session 调用梯度下降的这个计算单元就好了。
四、变量共享
当我们使用不同机子不同GPU来训练同一个模型的时候,我们需要共享一些变量。 TF 给出的解决方案是,使用字典建立变量名到 Variable 的映射:
1 |
|
有了变量名,那么肯定就有命名空间咯,使用方法如下:
1 |
|
参考资料
-
https://github.com/learning511/cs224n-learning-camp/blob/master/cs20is/1-graphs%20and%20Sessions.pdf ↩