深度学习框架:TensorFlow(人生若只如初见)

来源:互联网 发布:蜂窝移动数据已关闭 编辑:程序博客网 时间:2024/06/05 03:36

内容翻译自:https://www.tensorflow.org/get_started/

人生若只如初见,初见是美好的,有多少人会忘记自己和女朋友的第一次相遇,相见或相约呢?不会有,如果有说明爱不够。

我们第一次接触某个新的领域也是充满了新鲜和好奇,往往会幻想着众多美好。想想我当时转到计算机专业读研时,在经过C语言和Java的摧残后,初见Python,心里满满的都是Python的各种优势和好处。至今不能忘怀,然而现在却在为Python的进阶各种苦恼。虽然苦恼,却可以用初见的美好来化解。(见笑了,我也不知道自己再说些什么。。。请记得初见的美好)

如果您是刚刚接触TensorFlow,请结合原版英文来看,不要被不专业的我给误导了。说了好多废话,开始我们的学习笔记吧。

目录

入门前言

TensorFlow核心教程

       导入TensorFlow

       计算图

tf.train API

       完整的程序

tf.estimator

       基本用法

       自定义模型


入门前言

请您在Python环境下自行安装TensorFlow以后再进行本教程的阅读,为了能够更好的理解本教程的内容,您需要以下一些基础支持:

1、Python语言编程基础(如想快速了解Python编程语言可参考:菜鸟教程(http://www.runoob.com/python3/python3-tutorial.html))

2、了解一些数据结构

3、最理想的情况是您有机器学习的基础,没有的话该教程正是需要您详细阅读的。

TensorFlow提供了多个API。最低级别的API是TensorFlow核心--为您提供完整的编程控制。我们向机器学习的研究人员以及其他需要对模型进行精细控制的研究人员推荐使用TensorFlow核心。更高级别的API是建立在TensorFlow核心API之上的,而且高级别的API往往更容易学习和使用。高级别的API使得不同用户之间的重复性任务实现的更容易,像tf.estimator这样的高级API可以帮助您管理数据集,评估函数,训练集以及推论。

我们从TensorFlow的核心教程开始学习,了解TensorFlow核心原则将使您在使用更高级别的API时,能够更好的理解程序的内部是如何工作的。


Tensor

TensorFlow中的数据单位是Tensor(张量),一个Tensor是一组原始值组成的任意维数的数组。Tensorrank(等级)是它的维数,下面是一些Tensor的例子:
3
# a rank 0 tensor; a scalar with shape []
[
1.,2.,3.]# a rank 1 tensor; 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]

可能第三个Tensor不太容易理解:

[[[1., 2., 3.]], [[7., 8., 9.]]]的维数是从外往内依次来看:最外层包含两个列表:[[1., 2., 3.]],[[7., 8., 9.]],次外层为一个列表:[1., 2., 3.],最里层为三个元素:1., 2., 3.。


TensorFlow核心教程


导入TensorFlow

TensorFlow程序的规范化导入语句为:
import
tensorflowas tf

你将可以使用Python访问所有TensorFlow的类,方法和符号。


计算图

TensorFlow核心程序由另个独立的部分组成:

1、构建计算图

2、运行计算图

计算图是一系列排列成图节点的TensorFlow操作,图中的每个节点将零个或多个Tensor作为输入,并产生Tensor作为输出。下面我们通过一个简单的例子来说明:计算图节点的输入类型为常量,它不需要输入,即可输出一个内部存储的值,首先创建两个浮点型Tensor
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内运行计算图,Session封装了TensorFlow运行时的控制和状态。

下面创建一个Session对象,然后调用它的run方法运行计算图来评估node1和node2。
sess
= tf.Session()
print(sess.run([node1,node2]))

输出结果:
[
3.0,4.0]

我们可以通过组合Tensor节点和操作来构建更复杂的计算。(操作也是节点)
from
__future__import print_function
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

TensorFlow提供了一个名为TensorBoard的实用程序,可以将计算图可视化。

placeholder可以实现参数化的外部输入,placeholder是占位符:预先给定一个参数,会在调用运行之前对其赋值。

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

这三行代码有点像是一个函数或lambda,我们定义了两个输入参数,然后对它们进行操作。我们可以在调用run方法时,使用run方法中的feed_dict参数将多个具体的输入值提供给placeholder来评估计算图。
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操作来使计算图更复杂:

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

输出结果:
22.5

在机器学习中,我们通常需要一个可以进行任意输入的模型,为了使模型可训练并且满足上面的要求,我们需要能够修改计算图在相同的输入情况下得到不同的输出结果。Variable允许我们将可训练参数添加到计算图中,这样输入就被构造成一个类型和初始值。

W = tf.Variable([.3],dtype=tf.float32)
b
= tf.Variable([-.3],dtype=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是占位符,我们可以同时评估liner_model几个值:
print
(sess.run(linear_model,{x:[1,2,3,4]}))

输出结果:
[
0.  0.30000001   0.60000002  0.90000004]

我们已经创建了一个模型但我们不知道它有多好,为了评估训练数据的模型,我们需要一个y占位符来提供所需的值,y就是我们编写的一个损失函数。

损失函数用来衡量当前模型训练得到的值与所提供的数据有多大的误差。这里使用线性回归的标准损失模型的损失函数:模型训练数据和提供的数据差的平方和。Liner_model-y是模型训练数据与所提供数据之间的误差向量。我们调用tf.square来实现squared_deltas(平方差)。然后求所有平方差的和:
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变量的值,来提高精确度。我们可以通过tf.assign来修改初始化过的tf.Variable的值。例如:我们可以修改为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

很多比较复杂的情况是不可能靠人工实现最佳参数的寻找,我们需要机器学习能够自动寻找到模型的最优参数。下面将通过tf.train API来实现。


tf.train API


TensorFlow为我们提供了optimizers(优化器),可以逐渐改变每个变量,以最大限度地减少损失函数。最简单的优化器是gradient descent它根据相对于该变量的损失函数的大小来修改每个变量。TensorFlow可以通过tf.gradients函数对模型优化过程进行描述,为了简单起见,优化程序通常会为您执行此操作。
optimizer
= tf.train.GradientDescentOptimizer(0.01)
train
= optimizer.minimize(loss)
sess.run(init) # reset values to incorrectdefaults.
for iin 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核心代码,但是我们能够从小见大看出机器学习的整个实现流程。

比如:机器学习模型的构建,模型的评估函数构造,自动优化模型参数实现评估函数的最优化。这些都是机器学习最重要的思想,然后我们也不能忽略了这些步骤的方法本身以及数据前期的处理。


完整的程序


可训练线性回归模型代码如下:
import
tensorflowas 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 iin 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

可以看出损失值是非常小的数字(接近0),即完成了机器学习的目的。

tf.estimator


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

1、运行训练循环

2、运行评估循环

3、管理数据集

tf.estimator定义了许多常见的机器学习模型。


基本用法

使用tf.estimator之后简化的线性回归代码:
# NumPy is often used to load, manipulate and preprocess data.

import numpyas np
import tensorflowas tf

# Declare list of features. We onlyhave one numeric feature. There are many
# other types of columns that are morecomplicated and useful.
feature_columns
=[tf.feature_column.numeric_column("x",shape=[1])]

# An estimator is the front end toinvoke training (fitting) and evaluation
# (inference). There are manypredefined types like linear regression,
# linear classification, and manyneural network classifiers and regressors.
# The following code provides anestimator that does linear regression.
estimator
= tf.estimator.LinearRegressor(feature_columns=feature_columns)

# TensorFlow provides many helpermethods to read and set up data sets.
# Here we use two data sets: one fortraining and one for evaluation
# We have to tell the function howmany batches
# of data (num_epochs) we want and howbig 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 byinvoking the  method and passing the
# training data set.
estimator
.train(input_fn=input_fn, steps=1000)

# Here we evaluate how well our modeldid.
train_metrics
=estimator.evaluate(input_fn=train_input_fn)
eval_metrics =estimator.evaluate(input_fn=eval_input_fn)
print("trainmetrics: %r"% train_metrics)
print("evalmetrics: %r"% eval_metrics)

输出结果:

train metrics: {'average_loss':1.4833182e-08,'global_step':1000,'loss':5.9332727e-08}eval metrics:{'average_loss':0.0025353201,'global_step':1000,'loss':0.01014128}
虽然我们的损失值有所提高,但是仍然很接近0。(思考为什么调用封装好的模型损失值会有所偏高?)


自定义模型

tf.estimator不会将您锁定在预定义的模型中,假如我们想创建一个TensorFlow中没有预定义的自定义模型。我们仍然可以保留tf.estimator对数据集、训练集等的高级别抽象。为了说明,我们将展示如何实现等价于LinearRegressor模型的自定义模型,仅仅使用低级别TensorFlow API的知识。

要定义一个适用tf.estimator的工作原理的自定义模型,我们需要使用tf.estimator.Estimatortf.estimator.LinearRegressor实际上是tf.estimator.Estimator的一个子类。我们能够提供给Estimator一个函数model_fn来告诉tf.estimator怎样实现评估预测,训练步骤,损失函数。代码如下:
import
numpyas np
import tensorflowas tf

#Declare list of features, we only have one real-valued feature
def model_fn(features, labels, mode):
 
# Build a linear model andpredict 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 connectssubgraphs 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 wellour 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}

值得注意的是自定义model_fn()函数的内容和低级别API的手动模型训练循环非常相似。

原创粉丝点击