TensorFlow 新手入门

刚装上TensorFlow,还是不太会用,主要去官网还要翻墙太麻烦了。。随手翻一下教程备用


初识TensorFlow

初期准备:

  • 安装好TensorFlow
  • 知道如何在Python中编程
  • 懂一点数组知识
  • 最好了解机器学习(不必要)

TensorFLow提供多种APIs,从低级到高级,满足不同使用需求,越高级越容易学习和使用。下面的一些模型都可以用tf.contrib.learn高级API实现。

Tensors

TensorFlow最重要的数据单元就是tensor(张量)。一个tensor包括了任意维度的数组的原始值。tensor的rank代表其维度,如:

3 # a rank 0 tensor; this is a scalar with shape []
[1. ,2., 3.] # a rank 1 tensor; this is a vector with shape [3]
[[1., 2., 3.], [4., 5., 6.]] # a rank 2 tensor; a matrix with shape [2, 3]
[[[1., 2., 3.]], [[7., 8., 9.]]] # a rank 3 tensor with shape [2, 1, 3]

直观感觉有几层[]括号就有几个rank。而shape是从括号外向里,数,的个数。

TensorFlow 核心教程


导入TensorFlow

python下基本的导入声明:

import tensorflow as tf

大多数的文档都假设已经导入了tf模块。

计算图(The Computational Graph)

你可以把TensorFlow核心程序想成两个独立的模块:

  1. 搭建计算图
  2. 运行计算图

计算图computational graph是一系列布置为节点图的TensorFlow操作。每个节点将0个或更多张量作为输入并产生一个张量作为输出。常数是其中一个节点类型,他没有输入,输出其储存的常量,建立两个浮点数张量node1node2

node1 = tf.constant(3.0, tf.float32)
node2 = tf.constant(4.0) # also tf.float32 implicitly
print(node1, node2)

打印为:

Tensor("Const:0", shape=(), dtype=float32) Tensor("Const_1:0", shape=(), dtype=float32)

注意其输出并不是3.04.0。相反,他们是节点,当被评价(when evaluated)时,就会输出3.04.0。为了确切评价节点,我们必须用session运行一个计算图。一个session封装了TensorFlow运行时的控件和状态。

下面是一个使用Session运行的例子:

sess = tf.Session()
print(sess.run([node1, node2]))

得到输出:

[3.0, 4.0]

我们可以将Tensor节点与运算(运算操作也是节点)结合搭建更为复杂的计算图。比如我们可以将两个常数相加:

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

输出:

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

TensorFlow提供了一个名为TensorBoard的工具用来显示计算图,上面的计算过程可以可视化表示为下图:
add

由于输入是常数,这张图的输出结果是恒定的。一个图可以参数化为接受外部输入,称为placeholders(占位符),用于为之后的数据占取空间。

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

下面三行有点像一个函数或一个lambda,其中我们定义两个输入参数(a和b),然后对它们进行操作。 我们可以通过使用feed_dict参数指定为这些占位符提供具体值的Tensors,使用多个输入来评估此图:

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.]

在TensorBoard,图看起来是这样的:
add_node
我们可以使用计算图做一些更复杂的操作:

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

结果:

22.5

可视化之后:
add_three
在机器学习中,我们通常需要一个可以接受任意输入的模型,例如上面的模型。 为了使模型可训练,我们需要能够修改图以获得具有相同输入的新输出。 Variables(变量)允许我们向图中添加可训练的参数。 它们使用类型和初始值构造:

W = tf.Variable([.3], tf.float32)
b = tf.Variable([-.3], tf.float32)
x = tf.placeholder(tf.float32)
linear_model = W * x + b

当调用tf.constant时,常量被初始化,它们的值永远不会改变。 相比之下,当调用tf.Variable时,变量不会被初始化。 要初始化TensorFlow程序中的所有变量,必须显式调用特殊操作,如下所示:

init = tf.global_variables_initializer()
sess.run(init)

重要的是理解init是TensorFlow子图的句柄,它初始化所有的全局变量。 直到我们调用sess.run,变量是未初始化的。

由于x是一个占位符,我们可以同时对多个值进行输入:

print(sess.run(linear_model, {x:[1,2,3,4]}))

结果为:

[ 0.          0.30000001  0.60000002  0.90000004]

我们已经创建了一个模型,但无法评价其性能。为了评估训练数据的模型,需要一个占位符y来提供所需的值,我们需要写一个损失函数。
损失函数测量当前模型与提供的数据之间的距离。 我们将使用用于线性回归的标准损失模型,其将当前模型和提供的数据之间的增量的平方求和。 用linear_model - y创建一个向量,其中每个元素是对应的示例的误差增量。 我们调用tf.square来平方误差。 然后,我们对所有平方误差求和,创建一个单一的标量,使用tf.reduce_sum抽象所有示例的错误:

y = tf.placeholder(tf.float32)
squared_deltas = tf.square(linear_model - y)
loss = tf.reduce_sum(squared_deltas)
print(sess.run(loss, {x:[1,2,3,4], y:[0,-1,-2,-3]}))

结果为:

23.66

我们可以通过将Wb的值重新赋值为-1和1的完美值来手动改进。变量初始化为提供给tf.Variable的值,但可以使用类似tf.assign的操作来更改。 例如,W = -1b = 1是我们模型的最佳参数。 我们可以相应地改变W和b:

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]}))

最终的输出为0:

0.0

我们人为猜测了Wb的“完美”值,但机器学习的整个要点是自动找到正确的模型参数。 我们将在下一节中说明如何完成这一任务。

tf.train API


机器学习的完整讨论超出了本教程的范围。 然而,TensorFlow提供了优化器,其缓慢地改变每个变量以便最小化损失函数。 最简单的优化器是梯度下降。 它根据相对于该变量的损失导数的大小来修改每个变量。 一般来说,人工计算符号导数是繁琐的并且容易出错。 因此,TensorFlow可以使用函数tf.gradients自动产生仅给出模型描述的导数。 为了简单起见,优化器通常会为您执行此操作。 例如,

optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)
sess.run(init) # reset values to incorrect defaults.
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)]

现在我们已经做了实际的机器学习! 虽然做这个简单的线性回归不需要太多的TensorFlow核心代码,但是更复杂的模型和方法来将数据输入到模型中需要更多的代码。 因此,TensorFlow为通用模式、结构和功能提供了更高级别的抽象。 我们将在下一节中学习如何使用这些抽象。

完整程序

import numpy as np
import tensorflow as tf

# Model parameters
W = tf.Variable([.3], tf.float32)
b = tf.Variable([-.3], tf.float32)
# Model input and output
x = tf.placeholder(tf.float32)
linear_model = W * x + b
y = tf.placeholder(tf.float32)
# loss
loss = tf.reduce_sum(tf.square(linear_model - y)) # sum of the squares
# optimizer
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)
# training data
x_train = [1,2,3,4]
y_train = [0,-1,-2,-3]
# training loop
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init) # reset values to wrong
for i in range(1000):
  sess.run(train, {x:x_train, y:y_train})

# evaluate training accuracy
curr_W, curr_b, curr_loss  = sess.run([W, b, loss], {x:x_train, y:y_train})
print("W: %s b: %s loss: %s"%(curr_W, curr_b, curr_loss))

运行后结果:

W: [-0.9999969] b: [ 0.99999082] loss: 5.69997e-11

其可视化图:
visual

tf.contrib.learn


tf.contrib.learn是一个高级TensorFlow库,它简化了机器学习的机制,包括以下内容:

  • 运行训练
  • 运行评价
  • 管理数据集
  • 管理输入

tf.contrib.learn定义了许多常见的模型。

基本用法

注意,线性回归程序用tf.contrib.learn变得更简单:

import tensorflow as tf
# NumPy is often used to load, manipulate and preprocess data.
import numpy as np

# Declare list of features. We only have one real-valued feature. There are many
# other types of columns that are more complicated and useful.
features = [tf.contrib.layers.real_valued_column("x", dimension=1)]

# An estimator is the front end to invoke training (fitting) and evaluation
# (inference). There are many predefined types like linear regression,
# logistic regression, linear classification, logistic classification, and
# many neural network classifiers and regressors. The following code
# provides an estimator that does linear regression.
estimator = tf.contrib.learn.LinearRegressor(feature_columns=features)

# TensorFlow provides many helper methods to read and set up data sets.
# Here we use `numpy_input_fn`. We have to tell the function how many batches
# of data (num_epochs) we want and how big each batch should be.
x = np.array([1., 2., 3., 4.])
y = np.array([0., -1., -2., -3.])
input_fn = tf.contrib.learn.io.numpy_input_fn({"x":x}, y, batch_size=4,
                                              num_epochs=1000)

# We can invoke 1000 training steps by invoking the `fit` method and passing the
# training data set.
estimator.fit(input_fn=input_fn, steps=1000)

# Here we evaluate how well our model did. In a real example, we would want
# to use a separate validation and testing data set to avoid overfitting.
estimator.evaluate(input_fn=input_fn)

运行后输出:

    {'global_step': 1000, 'loss': 1.9650059e-11}

自定义模型

tf.contrib.learn不会只能运行其预定义的模型。 假设我们想创建一个未内置到TensorFlow中的自定义模型。 我们仍然可以保留tf.contrib.learn的数据集,馈送,训练等的高级抽象。 为了说明,我们将演示如何使用我们的低级TensorFlow API的知识来实现我们自己的等效模型到LinearRegressor。
要定义与tf.contrib.learn一起使用的自定义模型,我们需要使用tf.contrib.learn.Estimatortf.contrib.learn.LinearRegressor实际上是tf.contrib.learn.Estimator的子类。 而不是子类别Estimator,我们只是提供Estimator一个函数model_fn,告诉tf.contrib.learn如何评估预测,训练步骤和损失。 代码如下:

import numpy as np
import tensorflow as tf
# Declare list of features, we only have one real-valued feature
def model(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))
  # ModelFnOps connects subgraphs we built to the
  # appropriate functionality.
  return tf.contrib.learn.ModelFnOps(
      mode=mode, predictions=y,
      loss= loss,
      train_op=train)

estimator = tf.contrib.learn.Estimator(model_fn=model)
# define our data set
x=np.array([1., 2., 3., 4.])
y=np.array([0., -1., -2., -3.])
input_fn = tf.contrib.learn.io.numpy_input_fn({"x": x}, y, 4, num_epochs=1000)

# train
estimator.fit(input_fn=input_fn, steps=1000)
# evaluate our model
print(estimator.evaluate(input_fn=input_fn, steps=10))

运行后输出:

{'loss': 5.9819476e-11, 'global_step': 1000}

注意自定义model()函数的内容与下层API的手动模型训练循环非常相似。


用惯了caffe,感觉TensorFlow有点麻烦呢

TensorFlow Develop

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值