当前位置:   article > 正文

TensorFlow简明入门宝典_已知两个张量node1和node2的值分别为[[3.0,1.5],[2.5,6.0]]和[[4.0,

已知两个张量node1和node2的值分别为[[3.0,1.5],[2.5,6.0]]和[[4.0,1.0],[5.0

TensorFlow是由谷歌公司推出的一个人工智能学习系统,也是当前最为流行的深度学习框架之一。学习Tensorflow最好的资料就是其官网上的文档(参加文献【1】)。本文是“TensorFlow简明入门宝典”系列文章的第一篇,希望可以帮助对TensorFlow感到既陌生又神秘的朋友快速上手。


对于安装配置TensorFlow请参考【Ubuntu上安装配置Tensorflow及Jupyter详解】


TensorFlow中的核心数据单位就是tensor(张量),张量在编程语言中最straightforward的解释就是多维数组。一个张量的rank就是指其维数。例如:

  1. # a rank 0 tensor; this is a scalar with shape []
  2. 3
  3. # a rank 1 tensor; this is a vector with shape [3], 3表示拆掉最外层的[], 剩下的元素有3个
  4. [1., 2., 3.]
  5. # a rank 2 tensor; a matrix with shape [2, 3]
  6. # 2表示拆掉最外层的[],剩下的元素有2个,再拆掉一层[],每组剩下的元素都是3个
  7. [[1., 2., 3.], [4., 5., 6.]]
  8. # a rank 3 tensor with shape [2, 1, 3], 可以拆3次[],每次剩下的元素分别是2, 1, 3
  9. [[[1., 2., 3.]], [[7., 8., 9.]]]

同样,在使用TensorFlow之前需要先引用它,用于线性代数计算的NumPy也常常会被用到,这里一并引入。

  1. import tensorflow as tf
  2. import numpy as np

一、计算图、节点、操作、常量、变量,以及占位符

TensorFlow是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。TensorFlow的核心编程可以分解为两个离散的部分:

  • 构建计算图
  • 执行计算图

计算图(computational graph)是一系列被安排成图(graph)中节点(node)的TensorFlow操作。每个节点都以0或多个张量作为输入,并产生一个张量作为输出。节点的一种类型就是constant。例如,下面的语句构建了一个非常简单的计算图,其中创建了两个浮点数张量node1和node2。

  1. node1 = tf.constant(3.0, dtype=tf.float32)
  2. node2 = tf.constant(4.0) # also tf.float32 implicitly

注意node1和node2是两个节点(张量),要取得它们的值就必须对它们进行evaluate,而要对node进行evaluate,我们就必须在一个session中执行计算图。一个session是对TensorFlow运行时的状态和控制所进行的封装。


下面的代码创建了一个Session对象,并调用它的run方法。

  1. sess = tf.Session()
  2. print(sess.run([node1, node2]))
执行上述代码,会得到结果如下:

[3.0, 4.0]

我还可以通过把操作(操作也是节点)组合成张量节点的方法来实现更加复杂的计算。例如,把两个constant节点相加并生成一个新图的代码如下:

  1. node3 = tf.add(node1, node2)
  2. print("node3:", node3)
  3. print("sess.run(node3):", sess.run(node3))

输出的结果如下:

  1. node3: Tensor("Add:0", shape=(), dtype=float32)
  2. sess.run(node3): 7.0

一个计算图还可以通过接受外部输入的方法来进行参数化,这被称为placeholders(占位符),一个placeholder可以理解为一种承诺,即后面会提供数值。例如:

  1. a = tf.placeholder(tf.float32)
  2. b = tf.placeholder(tf.float32)
  3. adder_node = a + b # + provides a shortcut for tf.add(a, b)

然后就像函数调用一样,当我们evaluate这个图的时候,就要为placeholders提供输入值:

  1. print(sess.run(adder_node, {a: 3, b: 4.5}))
  2. print(sess.run(adder_node, {a: [1, 3], b: [2, 4]}))

输出的结果如下:

  1. 7.5
  2. [ 3. 7.]

向图中继续加入一个新的操作会产生一个更加复杂的图:

  1. add_and_triple = adder_node * 3.
  2. print(sess.run(add_and_triple, {a: 3, b: 4.5}))

跟预想的一样,上述代码会输出:

22.5

既然有Constant,很自然地会设想应该也会有Variable。的确如此,Variables允许我们向图中增加可训练的参数。构建Variables一般要指定类型和初始值,例如:

  1. W = tf.Variable([.3], dtype=tf.float32)
  2. b = tf.Variable([-.3], dtype=tf.float32)
  3. x = tf.placeholder(tf.float32)
  4. linear_model = W * x + b
Variable和constant的一个区别就在于constant在你调用tf.constant时就会被初始化,而且它们的值不会再改变。相反,在你调用tf.Variable时,Variable并不会被初始化。为了初始化你程序中的Variables,你必须显式地调用下面这个特殊的语句:
  1. init = tf.global_variables_initializer()
  2. sess.run(init)
因为x是一个placeholder,所以我们可以(通过同时给出几个x的值)来评估前面定义的linear_model,即
print(sess.run(linear_model, {x: [1, 2, 3, 4]}))
输出的结果如下:

[ 0.          0.30000001  0.60000002  0.90000004]


二、利用TensorFlow求解线性回归


我们已经越来越接近线性回归问题的求解了。在通常的线性回归问题中,我们需要在一些形如(x,y)这样的train data训练linear_model。因此,再启用一个新的placeholder y。然后把最小二乘误差(linear_model-y)2作为损失函数(loss function),下面的代码中调用了tf.square来计算最小二乘误差

  1. y = tf.placeholder(tf.float32)
  2. squared_deltas = tf.square(linear_model - y)
  3. loss = tf.reduce_sum(squared_deltas)
  4. fixW = tf.assign(W, [-1.])
  5. fixb = tf.assign(b, [1.])
  6. sess.run([fixW, fixb])
  7. print(sess.run(loss, {x: [1, 2, 3, 4], y: [0, -1, -2, -3]}))
当我们为参数W和b分别赋值-1和1时,损失为0。输出如下:
0.0

但是机器学习的任务是在给定任意的初始W和b时,让算法自行不断调整参数,以获得使损失最小化的参数。这里最为常用的优化算法就是梯度下降。在TensorFlow中提供的API tf.train可以帮我们完成模型训练的过程。

  1. optimizer = tf.train.GradientDescentOptimizer(0.01)
  2. train = optimizer.minimize(loss)

注意要把参数的初始值重新初始化到一个随机值。

  1. init = tf.global_variables_initializer()
  2. sess = tf.Session()
  3. sess.run(init)
  4. for i in range(1000):
  5. sess.run(train, {x: [1, 2, 3, 4], y: [0, -1, -2, -3]})
  6. print(sess.run([W, b]))

最终输出的参数如下,可见已经非常接近标准答案了。(误差是不可避免的)

[array([-0.9999969], dtype=float32), array([ 0.99999082], dtype=float32)]

这部分的Jupyter notebook文件可以从链接【2】中获取。


三、tf.estimator


tf.estimator是一个高层的TensorFlow库,它可以简化机器学习的机制,完成包括:

执行训练循环;执行evaluation循环;管理数据集。tf.estimator还定义了很多一般模型。


下面这个例子演示了如何利用tf.estimator来简化之前的线性回归。

  1. import tensorflow as tf
  2. import numpy as np
  3. # Declare list of features. We only have one numeric feature. There are many
  4. # other types of columns that are more complicated and useful.
  5. feature_columns = [tf.feature_column.numeric_column("x", shape=[1])]
  6. # An estimator is the front end to invoke training (fitting) and evaluation
  7. # (inference). There are many predefined types like linear regression,
  8. # linear classification, and many neural network classifiers and regressors.
  9. # The following code provides an estimator that does linear regression.
  10. estimator = tf.estimator.LinearRegressor(feature_columns=feature_columns)
  11. # TensorFlow provides many helper methods to read and set up data sets.
  12. # Here we use two data sets: one for training and one for evaluation
  13. # We have to tell the function how many batches
  14. # of data (num_epochs) we want and how big each batch should be.
  15. x_train = np.array([1., 2., 3., 4.])
  16. y_train = np.array([0., -1., -2., -3.])
  17. x_eval = np.array([2., 5., 8., 1.])
  18. y_eval = np.array([-1.01, -4.1, -7, 0.])
  19. input_fn = tf.estimator.inputs.numpy_input_fn(
  20. {"x": x_train}, y_train, batch_size=4, num_epochs=None, shuffle=True)
  21. train_input_fn = tf.estimator.inputs.numpy_input_fn(
  22. {"x": x_train}, y_train, batch_size=4, num_epochs=1000, shuffle=False)
  23. eval_input_fn = tf.estimator.inputs.numpy_input_fn(
  24. {"x": x_eval}, y_eval, batch_size=4, num_epochs=1000, shuffle=False)
  25. # We can invoke 1000 training steps by invoking the method and passing the
  26. # training data set.
  27. estimator.train(input_fn=input_fn, steps=1000)
  28. # Here we evaluate how well our model did.
  29. train_metrics = estimator.evaluate(input_fn=train_input_fn)
  30. eval_metrics = estimator.evaluate(input_fn=eval_input_fn)
  31. print("train metrics: %r"% train_metrics)
  32. print("eval metrics: %r"% eval_metrics)

执行上述代码,结果如下:

  1. train metrics: {'loss': 1.2712867e-09, 'global_step': 1000}
  2. eval metrics: {'loss': 0.0025279333, 'global_step': 1000}

前面我们提到tf.estimator还定义了很多一般模型,例如上述代码中就使用了tf.estimator.LinearRegressor。但是,tf.estimator并没有将你锁定在预定义的模型中。假设我们想创造一个个性化的而且没有被内置于TensorFlow中的模型,我们还是可以使用它。这时就需要使用tf.estimator.Estimator,而且事实上,tf.estimator.LinearRegressor其实是tf.estimator.Estimator的一个子类。


假设现在我们要自己实现线性回归,这里我们并不打算为tf.estimator.Estimator的创建一个子类,其实只要为这个类提供一个model_fn的方法来告知tf.estimator 如何 evaluate 预测, 训练步骤以及损失即可。来看下面这个例子:

  1. import numpy as np
  2. import tensorflow as tf
  3. # Declare list of features, we only have one real-valued feature
  4. def model_fn(features, labels, mode):
  5. # Build a linear model and predict values
  6. W = tf.get_variable("W", [1], dtype=tf.float64)
  7. b = tf.get_variable("b", [1], dtype=tf.float64)
  8. y = W * features['x'] + b
  9. # Loss sub-graph
  10. loss = tf.reduce_sum(tf.square(y - labels))
  11. # Training sub-graph
  12. global_step = tf.train.get_global_step()
  13. optimizer = tf.train.GradientDescentOptimizer(0.01)
  14. train = tf.group(optimizer.minimize(loss),
  15. tf.assign_add(global_step, 1))
  16. # EstimatorSpec connects subgraphs we built to the
  17. # appropriate functionality.
  18. return tf.estimator.EstimatorSpec(
  19. mode=mode,
  20. predictions=y,
  21. loss=loss,
  22. train_op=train)
  23. estimator = tf.estimator.Estimator(model_fn=model_fn)
  24. # define our data sets
  25. x_train = np.array([1., 2., 3., 4.])
  26. y_train = np.array([0., -1., -2., -3.])
  27. x_eval = np.array([2., 5., 8., 1.])
  28. y_eval = np.array([-1.01, -4.1, -7, 0.])
  29. input_fn = tf.estimator.inputs.numpy_input_fn(
  30. {"x": x_train}, y_train, batch_size=4, num_epochs=None, shuffle=True)
  31. train_input_fn = tf.estimator.inputs.numpy_input_fn(
  32. {"x": x_train}, y_train, batch_size=4, num_epochs=1000, shuffle=False)
  33. eval_input_fn = tf.estimator.inputs.numpy_input_fn(
  34. {"x": x_eval}, y_eval, batch_size=4, num_epochs=1000, shuffle=False)
  35. # train
  36. estimator.train(input_fn=input_fn, steps=1000)
  37. # Here we evaluate how well our model did.
  38. train_metrics = estimator.evaluate(input_fn=train_input_fn)
  39. eval_metrics = estimator.evaluate(input_fn=eval_input_fn)
  40. print("train metrics: %r"% train_metrics)
  41. print("eval metrics: %r"% eval_metrics)
执行上述代码,结果如下:
  1. train metrics: {'loss': 1.227995e-11, 'global_step': 1000}
  2. eval metrics: {'loss': 0.01010036, 'global_step': 1000}

你会注意到的一点是我们编写的函数model_fn()与之前手动首先的线性回归训练模型非常类似。这里就不再多做解释了。



参考文献

【1】https://www.tensorflow.org/get_started/get_started

【2】http://pan.baidu.com/s/1c1Ofiak


(本文完)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/301358
推荐阅读
相关标签
  

闽ICP备14008679号