首页 > 学院 > 开发设计 > 正文

TensorFlow 新手入门

2019-11-06 06:03:45
字体:
来源:转载
供稿:网友

刚装上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核心程序想成两个独立的模块:

搭建计算图运行计算图

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

node1 = tf.constant(3.0, tf.float32)node2 = tf.constant(4.0) # also tf.float32 implicitlyPRint(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 npimport tensorflow as tf# Model parametersW = tf.Variable([.3], tf.float32)b = tf.Variable([-.3], tf.float32)# Model input and outputx = tf.placeholder(tf.float32)linear_model = W * x + by = tf.placeholder(tf.float32)# lossloss = tf.reduce_sum(tf.square(linear_model - y)) # sum of the squares# optimizeroptimizer = tf.train.GradientDescentOptimizer(0.01)train = optimizer.minimize(loss)# training datax_train = [1,2,3,4]y_train = [0,-1,-2,-3]# training loopinit = tf.global_variables_initializer()sess = tf.Session()sess.run(init) # reset values to wrongfor i in range(1000): sess.run(train, {x:x_train, y:y_train})# evaluate training accuracycurr_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 npimport tensorflow as tf# Declare list of features, we only have one real-valued featuredef 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 setx=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)# trainestimator.fit(input_fn=input_fn, steps=1000)# evaluate our modelprint(estimator.evaluate(input_fn=input_fn, steps=10))

运行后输出:

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

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


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

TensorFlow Develop


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表