CS224n 笔记07 TensorFlow 入门

简介

这节课主要的内容其实就是简单的介绍了 TensorFlow 的一些基本理念,和一些简单的用法,并用半节课的时间实现了之前我们做过的实验 Skipgram。

什么是 Tensorflow

  1. 是一个来自 Google Brain Team 的开源软件
  2. 是以流图的方式进行数值计算的库
  3. 用于部署机器学习算法,并执行算法

其他的话:现在学术界很多老师是相当不喜欢 Tensorflow 的,他们更加推崇 Theano 或者 Pytorch,不过 Tensorflow 不论是在 Github 的 Star 数量还是在论文中再现算法的使用量上都占据着比较大的优势。

TensorFlow 的基本使用

前言

这一部分,我将简单的讲课堂上的内容做以笔记,由于今后会大量的使用 Tensorflow,所以之后会另其栏目专门记录学习 TensorFlow 以及其源码的笔记。

TensorFlow 的理念

  1. 表达计算流程的方式是一个图
  2. 图的节点代表的是计算(operations)
  3. 图的边代表的是张量(tensors),可以简单理解为多维数组。

    简单使用

一、Variable & Placeholder

  1. Variable Variable 是保存图的运算状态的,也就是说模型会保留这些变量,不会删除他们,同时在反向传播中会更新他们。更加具体的来讲,他们就是在我们下载别人训练好的模型时的参数,类似于算法模型这个骨架内的血肉。
    1
     tf.Variable(tf.zeros((N,))) # 使用有点像numpy
    
  2. Placeholder Placeholder 在中文的教程中很多称之为占位符,他们和 Variable 的不同在于两点:
    • 定义的时候不需要指定初始值,它只起占位作用
    • 在每个节点运算结束后不会保留或更改它的值 鉴于它的特性,我们很容易想到,Placeholder 的主要作用在于用来存储数据集和标签等操作。它是在运行模型的时候,即执行 session 的时候从外部数据导入的。
      1
      2
      3
       tf.placeholder(data_type, shape)
       # eg
       input_placeholder = tf.placeholder(tf.float32, shape=(batch_size, n_features))
      
  3. Operations 我们现在有了变量,那么我们就可以使用他们来计算了。TensorFlow 中有很多计算模块,我们可以十分直观的进行使用,方法如下:
    1
    2
     tf.matmul(x, W)
     tf.nn.relu(tf.matmul(x, W) + b)
    

    注:值得注意的是这里的 + 仍然指代的是 tensorflow 的加法操作,在 tensorflow 中对于直接用符号+-*/ 的加减乘除操作都会自动转换乘相应的 tensorflow 操作。

  4. 描述图运算 需要强调下,在这里讲课的清秀小哥说,这里的 h 和最终的那个 ReLu 操作的计算单元其实是一样的。这里需要特别注意,因为之后我们用 session 其实本质来讲就是通过类似这种 h 来定位到计算节点来获得输出的。

二、Session

之前我们其实是画出了一个图,我觉得更准确的说法是之前画的是图纸,但是并没有根据图纸进行施工。而 Session 就是做这样一个工作的。

那么第一个问题就 session 调用的图在哪里,其实是有一个默认的 graph 的。我们可以通过 tf.get_default_graph() 得到。其中值得注意的是,在斯坦福的 TensorFlow 课中,讲师特别强调不建议自己定义多个图,使用默认的图就好了1

使用 session 运行图的步骤:

  1. 创建一个 session
    1
     sess = tf.Session()
    
  2. 初始化变量
    1
    2
    3
    4
     sess.run(tf,initialize_all_variables())
     # 后来清秀小哥使用的方法是
     init= tf.global_variables_initializer()
     sess.run(init)
    
  3. 运算
    1
     sess.run(fetches, feeds)
    

    feches 是图的节点,由于图是一个连通图,所以通过一个节点总能找到所有的节点。而 feeds 则指的是 placeholder 和喂入的数据之间的映射关系。

三、训练神经网络

之前我们可以说是定义了一个图,但是没有定义如何训练它,接下来是将训练部分的内容。

  1. 定义损失函数 tensorflow 中有很多 API 来定义损失函数,下面是一个例子。
    1
    2
    3
    4
     prediction = 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)
    
  2. 规定如何计算梯度 我们初始化一个 optimizer, 然后在调用 tensorflow 来执行一些梯度下降算法等。由于我们之前学到梯度下降算法是遵循链式法则的,所以每个节点就计算自己的损失就好了,这也是为什么这个库选择使用数据流图来设计的原因之一。

    就像大多特定的函数都具有自己特定的导数一样,图中运算节点都附带了梯度操作。在反向传播中,用户不需要编写梯度计算与参数更新的代码,而是交给 optimizer 自动完成。

    调用方法如下:

    1
     train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
    
  3. 训练 每次执行梯度下降就是一次 epoch,所以简单的来说就是用 session 调用梯度下降的这个计算单元就好了。

四、变量共享

当我们使用不同机子不同GPU来训练同一个模型的时候,我们需要共享一些变量。 TF 给出的解决方案是,使用字典建立变量名到 Variable 的映射:

1
2
3
4
5
6
variables_dict = {
	"weights": tf.Variable(tf.random_normal([782, 100]),
						 	name="weights"
							),
	"biases": tf.Variable(tf.zeros([100]), name="biases")
}

有了变量名,那么肯定就有命名空间咯,使用方法如下:

1
2
3
4
5
6
7
8
9
with tf.variable_scope("foo"):
    v = tf.get_variable("v", shape=[1])  # v.name == "foo/v:0"
with tf.variable_scope("foo", reuse=True):
    v1 = tf.get_variable("v"
                         # Shared variable found!
                         ) )
with tf.variable_scope("foo", reuse=False):
    v1 = tf.get_variable("v"
# CRASH foo/v:0 already exists!

参考资料

  1. https://github.com/learning511/cs224n-learning-camp/blob/master/cs20is/1-graphs%20and%20Sessions.pdf 

  • 本文作者: Author:DeamoV
  • Github:https://github.com/Duan-JM
  • Email:vincent.duan95@outlook.com
  • 本文链接: Artical: CS224n 笔记07 TensorFlow 入门
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!
  • 版权声明: 原创文章如转载,请注明出处