赞
踩
TensorFlow是由谷歌公司推出的一个人工智能学习系统,也是当前最为流行的深度学习框架之一。学习Tensorflow最好的资料就是其官网上的文档(参加文献【1】)。本文是“TensorFlow简明入门宝典”系列文章的第一篇,希望可以帮助对TensorFlow感到既陌生又神秘的朋友快速上手。
对于安装配置TensorFlow请参考【Ubuntu上安装配置Tensorflow及Jupyter详解】
TensorFlow中的核心数据单位就是tensor(张量),张量在编程语言中最straightforward的解释就是多维数组。一个张量的rank就是指其维数。例如:
- # a rank 0 tensor; this is a scalar with shape []
- 3
-
- # a rank 1 tensor; this is a vector with shape [3], 3表示拆掉最外层的[], 剩下的元素有3个
- [1., 2., 3.]
-
- # a rank 2 tensor; a matrix with shape [2, 3]
- # 2表示拆掉最外层的[],剩下的元素有2个,再拆掉一层[],每组剩下的元素都是3个
- [[1., 2., 3.], [4., 5., 6.]]
-
- # a rank 3 tensor with shape [2, 1, 3], 可以拆3次[],每次剩下的元素分别是2, 1, 3
- [[[1., 2., 3.]], [[7., 8., 9.]]]
- import tensorflow as tf
- import numpy as np
一、计算图、节点、操作、常量、变量,以及占位符
TensorFlow是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。TensorFlow的核心编程可以分解为两个离散的部分:
计算图(computational graph)是一系列被安排成图(graph)中节点(node)的TensorFlow操作。每个节点都以0或多个张量作为输入,并产生一个张量作为输出。节点的一种类型就是constant。例如,下面的语句构建了一个非常简单的计算图,其中创建了两个浮点数张量node1和node2。
- node1 = tf.constant(3.0, dtype=tf.float32)
- node2 = tf.constant(4.0) # also tf.float32 implicitly
注意node1和node2是两个节点(张量),要取得它们的值就必须对它们进行evaluate,而要对node进行evaluate,我们就必须在一个session中执行计算图。一个session是对TensorFlow运行时的状态和控制所进行的封装。
下面的代码创建了一个Session对象,并调用它的run方法。
- sess = tf.Session()
- print(sess.run([node1, node2]))
执行上述代码,会得到结果如下:
[3.0, 4.0]
- node3 = tf.add(node1, node2)
- print("node3:", node3)
- print("sess.run(node3):", sess.run(node3))
- node3: Tensor("Add:0", shape=(), dtype=float32)
- sess.run(node3): 7.0
- a = tf.placeholder(tf.float32)
- b = tf.placeholder(tf.float32)
- adder_node = a + b # + provides a shortcut for tf.add(a, b)
- print(sess.run(adder_node, {a: 3, b: 4.5}))
- print(sess.run(adder_node, {a: [1, 3], b: [2, 4]}))
- 7.5
- [ 3. 7.]
- add_and_triple = adder_node * 3.
- print(sess.run(add_and_triple, {a: 3, b: 4.5}))
22.5
- W = tf.Variable([.3], dtype=tf.float32)
- b = tf.Variable([-.3], dtype=tf.float32)
- x = tf.placeholder(tf.float32)
- linear_model = W * x + b
Variable和constant的一个区别就在于constant在你调用tf.constant时就会被初始化,而且它们的值不会再改变。相反,在你调用tf.Variable时,Variable并不会被初始化。为了初始化你程序中的Variables,你必须显式地调用下面这个特殊的语句:
- init = tf.global_variables_initializer()
- 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来计算最小二乘误差:
- y = tf.placeholder(tf.float32)
- squared_deltas = tf.square(linear_model - y)
- loss = tf.reduce_sum(squared_deltas)
-
- fixW = tf.assign(W, [-1.])
- fixb = tf.assign(b, [1.])
- sess.run([fixW, fixb])
- 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可以帮我们完成模型训练的过程。
- optimizer = tf.train.GradientDescentOptimizer(0.01)
- train = optimizer.minimize(loss)
- init = tf.global_variables_initializer()
- sess = tf.Session()
- sess.run(init)
-
- for i in range(1000):
- sess.run(train, {x: [1, 2, 3, 4], y: [0, -1, -2, -3]})
-
- 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来简化之前的线性回归。
- import tensorflow as tf
- import numpy as np
-
- # Declare list of features. We only have one numeric feature. There are many
- # other types of columns that are more complicated and useful.
- feature_columns = [tf.feature_column.numeric_column("x", shape=[1])]
-
- # An estimator is the front end to invoke training (fitting) and evaluation
- # (inference). There are many predefined types like linear regression,
- # linear classification, and many neural network classifiers and regressors.
- # The following code provides an estimator that does linear regression.
- estimator = tf.estimator.LinearRegressor(feature_columns=feature_columns)
-
- # TensorFlow provides many helper methods to read and set up data sets.
- # Here we use two data sets: one for training and one for evaluation
- # We have to tell the function how many batches
- # of data (num_epochs) we want and how big each batch should be.
- x_train = np.array([1., 2., 3., 4.])
- y_train = np.array([0., -1., -2., -3.])
- x_eval = np.array([2., 5., 8., 1.])
- y_eval = np.array([-1.01, -4.1, -7, 0.])
- input_fn = tf.estimator.inputs.numpy_input_fn(
- {"x": x_train}, y_train, batch_size=4, num_epochs=None, shuffle=True)
- train_input_fn = tf.estimator.inputs.numpy_input_fn(
- {"x": x_train}, y_train, batch_size=4, num_epochs=1000, shuffle=False)
- eval_input_fn = tf.estimator.inputs.numpy_input_fn(
- {"x": x_eval}, y_eval, batch_size=4, num_epochs=1000, shuffle=False)
-
- # We can invoke 1000 training steps by invoking the method and passing the
- # training data set.
- estimator.train(input_fn=input_fn, steps=1000)
-
- # Here we evaluate how well our model did.
- train_metrics = estimator.evaluate(input_fn=train_input_fn)
- eval_metrics = estimator.evaluate(input_fn=eval_input_fn)
- print("train metrics: %r"% train_metrics)
- print("eval metrics: %r"% eval_metrics)
- train metrics: {'loss': 1.2712867e-09, 'global_step': 1000}
- 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 预测, 训练步骤以及损失即可。来看下面这个例子:
- import numpy as np
- import tensorflow as tf
-
- # Declare list of features, we only have one real-valued feature
- def model_fn(features, labels, mode):
- # Build a linear model and predict values
- W = tf.get_variable("W", [1], dtype=tf.float64)
- b = tf.get_variable("b", [1], dtype=tf.float64)
- y = W * features['x'] + b
- # Loss sub-graph
- loss = tf.reduce_sum(tf.square(y - labels))
- # Training sub-graph
- global_step = tf.train.get_global_step()
- optimizer = tf.train.GradientDescentOptimizer(0.01)
- train = tf.group(optimizer.minimize(loss),
- tf.assign_add(global_step, 1))
- # EstimatorSpec connects subgraphs we built to the
- # appropriate functionality.
- return tf.estimator.EstimatorSpec(
- mode=mode,
- predictions=y,
- loss=loss,
- train_op=train)
-
- estimator = tf.estimator.Estimator(model_fn=model_fn)
- # define our data sets
- x_train = np.array([1., 2., 3., 4.])
- y_train = np.array([0., -1., -2., -3.])
- x_eval = np.array([2., 5., 8., 1.])
- y_eval = np.array([-1.01, -4.1, -7, 0.])
- input_fn = tf.estimator.inputs.numpy_input_fn(
- {"x": x_train}, y_train, batch_size=4, num_epochs=None, shuffle=True)
- train_input_fn = tf.estimator.inputs.numpy_input_fn(
- {"x": x_train}, y_train, batch_size=4, num_epochs=1000, shuffle=False)
- eval_input_fn = tf.estimator.inputs.numpy_input_fn(
- {"x": x_eval}, y_eval, batch_size=4, num_epochs=1000, shuffle=False)
-
- # train
- estimator.train(input_fn=input_fn, steps=1000)
- # Here we evaluate how well our model did.
- train_metrics = estimator.evaluate(input_fn=train_input_fn)
- eval_metrics = estimator.evaluate(input_fn=eval_input_fn)
- print("train metrics: %r"% train_metrics)
- print("eval metrics: %r"% eval_metrics)
执行上述代码,结果如下:
- train metrics: {'loss': 1.227995e-11, 'global_step': 1000}
- eval metrics: {'loss': 0.01010036, 'global_step': 1000}
参考文献
【1】https://www.tensorflow.org/get_started/get_started
【2】http://pan.baidu.com/s/1c1Ofiak
(本文完)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。