这篇指南可以让你使用tensorflow编程, 在使用指南前, 你应该安装tensorflow, 为了你能从这篇教程得到更多的东西, 你应该有以下的基础:
1. 会使用Python编程
2. 有点矩阵的知识
3. 理想情况下, 你应该具备一些机器学习的知识。然而, 如果你知道的很少或者几乎没有机器学习的这 方面的知识, 那么你仍然可以阅读这篇指南。
tesnsorflow 提供了众多的api接口, 最低级的api —tensorflow core— 能提供给你完成程序控制, 我们推荐机器学习研究人员和要求更好操作模型的人使用TensorFlow core Api; 高级api是建立在TensorFlow Core之上的, 这些高级的api一般是比Core api更容易学习和使用的。 另外, 对于不同的使用者来说, 更高的等级的api再使用时是更容易的, 也更能体现出一致性(这个可能是说在代码可读性上)
这个指南开始是一个TensorFlow的教程, 以后, 我们演示怎么使用tf.estimator方法实现相同的模型,懂得TensorFlow Core 规则讲给你在心里建立一个强大的模型, 当你使用更高级的api时, 能了解其内部的工作原理。
Tensor
TensorFlow的核心数据单位是tensor(翻译成中文,就是张量的意思),一个tensor是用一组形如任意数量的数据组组成,这个tensor的阶数就是其数组的维度。比如(二维就是rank=2)
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]
TensorFlow Core 教程
首先,我们先得创建一个文件tensorflow.py文件, 在第一行写入下面的一行代码
import tensorflow as tf
这条语句是表示导入tensorflow包并将其重新命名为tf, 这样我们就可以使用tensorflow的方法、类等,同时减少一些代码量, 写起来比较方便
你或者可以把TensorFlow Core程序看成由两个离散的部分组成的
计算图是排列成节点图的一系列TensorFlow操作, 让我们构建一个计算图, 每个节点由0或者多个tensor作为输入, 和生成一个tensor作为输出, 一节点的类型是一个常数。像所有的TensorFlow常数一样, 这个计算图将没有输入, 和她输出一个值在内部储存。我们可以创建两个浮点类型的tensor, node1和node2,如下
node1 = tf.constant(3.0, dtype=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.0和4.0, 取而代之, 他们是节点; 那是应为当他们被触发时才能输出3.0和4.0。 实际上要触发节点 , 我们必须运行计算图在一个session(会话)中, 这个会话封装了tensorflow运行时的控制和状态。
下面的代码创建了一个session对象, 并调用它run方法运行计算图, 以此来触发node1和node2, 如下:
sess = tf.Session()
print(sess.run([node1, node2]))
结果如下:
[3.0, 4.0]
我们可以组合tensor节点的操作来构建更复杂的计算(Operations are also nodes),例如,我们可以加和我们两个常数节点和生成一个新的图, 如下:
node3 = tf.add(node1, node2)
print("node3:", node3)
print("sess.run(node3):", sess.run(node3))
最后两个print语句生成:
node3: Tensor("Add:0", shape=(), dtype=float32
sess.run(node3): 7.0
tensorflow提供了一个实用的工具叫做tensorBoard, 它能把计算图展示成一张图片,这里有张截图,是tensorBoard可视化后的。
对于这张图来说,我们认证了一个事情, 就是add操作也是作为一个节点的。
就是这样, 这个图表不是一个特别地有趣,以为他总是产生一个恒定的结果, 一个图是可以被参数化来接受外部的参数输入,被称为placeholder(中文:占位符)。placeholder将是在最后提供数值
a = tf.placeholder(tf.float32)
b = tf.placeholder(tf.float32)
adder_node = a + b # + provides a shortcut for tf.add(a, b)
上面的三行能表明有两个输入(a和b),还有一个加和操作;我们可以通过使用run方法的feed_dict参数对多个输入进行评估,以将具体值提供给占位符:
print(sess.run(adder_node, feed_dict={a: 3, b: 4.5}))
print(sess.run(adder_node, feed_dict={a: [1, 3], b: [2, 4]}))
这里feed_dict是可以被省略的
结果如下:
7.5
[ 3. 7.]
tensorBoard上大致会生成如下的图:
同样,我们可以实现相对复杂的操作,比如乘法,如下:
add_and_triple = adder_node * 3.
print(sess.run(add_and_triple, {a: 3, b: 4.5}))
产生的结果:
22.5
这个在tensorBoard上的图大致像这样:
在机器学习中,我们通常想要一个随意输入的模型, 如上所述, 为了使模型可训练, 我们需要能够修改图形以获得在相同输入情况下获得新输出。Variables 允许我们在图中加入可训练的变量, 他们的构建的同时,需要设置一个类型和初始值。
W = tf.Variable([.3], dtype=tf.float32)
b = tf.Variable([-.3], dtype=tf.float32)
x = tf.placeholder(tf.float32)
linear_model = W * x + b
Constants在tf.constants被调用时初始化, 它们的值也绝不会变得。相比之下, variables在tf.Variables被调用时不被初始化, 想要使所有的variables全部初始化必须明确的调用一下操作:
init = tf.global_variables_initializer()
sess.run(init)
重要的是实现init是TensorFlow子图的handle(我理解为处理),它初始化所有的全局变量。在我们调用sess.run之前,这些变量是未初始化的。
由于x是一个placeholder, 我们可以用几个值同时触发linear_model:
print(sess.run(linear_model, {x: [1, 2, 3, 4]}))
输出值:
[ 0. 0.30000001 0.60000002 0.90000004]
我们创建了一个模型, 但是我们不知道他是不是我们预期的,为了评估训练模型, 我们需要一个名为y的placeholder(占位符),这个占位符提供我们预期的值,并且我们需要写一个loss(损失)函数。
损失函数是测量当前模型和提供数据的差距, 我们将使用一个标准的loss模型–linear regression(线性回归),它将加和当前模型与所提供数据误差的平方, 其中
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
我们可以重新分配W和b为-1, 1完善手动匹配, tf.Variable变量在初始化之后是可以使用tf.assign等操作进行更改, 例如, W=-1 和 b=1是可最佳变量, 我们能相应地改变他们:
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
我们可以猜测完美的W和b的值, 但是整个机器学习的就是为了自动找到模型正确的参数,在下一章我们将演示如何自动找到模型的正确参数。
全面的机器学习讨论已经超出了教程的范围, 然而, tensorflow提供了优化器(optimizers), 能缓慢更改变量最小化损失功能(减小误差), 最简单的优化器是梯度降低优化器(gradient descen), 它能相对于变量损失的导数大小修改该值。一般来说, 手动计算导数是枯燥和容易出错。 所以, 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 tensorflow as tf
# Model parameters
W = tf.Variable([.3], dtype=tf.float32)
b = tf.Variable([-.3], dtype=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
值得注意的是loss的值是非常小的(几乎趋近于0), 如果你运行这个程序, 如果你运行这个程序,你得loss值可能是不相同的,因为这个model是以一个为随机值被初始化的。
这个复杂的程序是可以用TensorBoard可视化
tf.estimator(估算器) 是一个高级的tensorflow库, 简化了机器学习的机制, 包括以下功能:
tf.estimator 定义在很多公共模型中。
基础用法
tf.estimator 使用线性回归变得简单
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 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.
# tensorflow提供了很多阅读和建立数据集的方法
# 这里我们使用两个数据集: 一个训练、一个测评
# 我们必须告诉程序,我们想要多少批次的数据和每个批次多大
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.
# 我们调用方法和传入数据集进行1000次的训练
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: {'average_loss': 1.6875985e-07, 'loss': 6.7503942e-07, 'global_step': 1000}
eval metrics: {'average_loss': 0.0025609413, 'loss': 0.010243765, 'global_step': 1000}
注意到我们的eval数据中loss有个更高的误差,但是它是趋近于0的,这证明我们学习到了。
定制模型
tf.estimator 不锁定你得预定义的模型, 假如我们想要创建一个不内置到tensorflow中的模型, 我们仍可以保留 tf.estimator数据集、填充、训练等的高级抽象。为了说明这点,我们使用低级api实现LinearRegressor模型的等效模型
今天工作就没有翻译多少