TensorFlow入门(一)安装与基本框架

安装

TensorFlow分为CPU和GPU两个版本,如果系统没有NVIDIA® GPU,就安装CPU版本,GPU版本的TensorFlow计算速度更快,如果满足以下要求,可以安装GPU版本

  • CUDA® Toolkit 8.0. CUDA是一种由NVIDIA推出的通用并行计算架构,该架构使GPU能够解决复杂的计算问题。它包含了CUDA指令集架构(ISA)以及GPU内部的并行计算引擎。CUDA® Toolkit是一种针对支持CUDA功能的GPU(图形处理器)的C语言开发环境。
  • CUDA® Toolkit 8.0的NVIDIA驱动
  • cuDNN v5.1.是用于深度神经网络的GPU加速库
  • 显卡的CUDA计算能力在3.0以上

安装方式

  • pip
    原生pip直接安装TensorFlow而不需要通过虚拟环境,因此pip安装的TensorFlow存放于其他python库的路径,并且,可以在计算机的任何路径下运行TensorFlow
    python3.5版本里,安装CPU版本在命令提示符中键入pip install –upgrade tensorflow,安装GPU版本键入pip install –upgrade tensorflow-gpu
    截止17年5月TensorFlow还不支持在python3.6中pip安装
  • Anaconda
    可以用conda指令创建虚拟环境,但是推荐使用在anaconda下pip install.创建TensorFlow环境安装,TensorFlow库存在于创建的虚拟环境中,运行时有所限制。

TensorFlow起步

起步前的准备工作:python的编程基础、矩阵的简单数学知识、机器学习

TensorFlow提供多种API。底层API(TensorFlow Core)提供完整的程序控制。高级API建立在core之上,高级API更加容易学习应用。像tf.contrib.learn帮助你管理数据集,学习器,训练和推断。注意名字中包含contrib的高级API还在开发当中,在以后的版本可能会改变或者废弃。

指南先介绍底层API,之后会用tf.contrib.learn来得到相同的模型。了解core可以更加了解在高级API使用中的内部运行机制。

Tensors

TensorFlow的数据核心单元是tensor(张量)。可以把张量想象成一个n维的数组或列表。张量的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]

TensorFlow Core

导入TensorFlow的所有类、方法和属性:import tensorflow as tf

the computational graph(计算图)

你可以认为TensorFlow核心代码有两部分组成:

  1. 构建计算图
  2. 执行计算图
    计算图是由TensorFlow operation(节点)组成。让我们构建一个简单的计算图。每个节点有0或更多张量作为输入然后产生一个张量作为输出。有一类节点是常量。所有的TensorFlow常量没有输入,它输出一个值在内部存储。我们创建两个浮点型常量node1和node2如下:
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)

注意:打印node并没有输出3.0和4.0,而是node的本身属性,在被计算的时候才会产生3.0和4.0,为了正确计算节点,我们必须在对话(session)中执行计算图。session压缩了控制和TensorFlow的状态。

接下来的代码构造了session对象并用它的方法run执行足够的计算图来计算node1和node2:

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_2:0", shape=(), dtype=float32)
sess.run(node3):  7.0

TensorFlow提供TensorBoard使计算图可视化。

《TensorFlow入门(一)安装与基本框架》 TensorBoard可视化的效果

这个图形并不完美因为它总是产生常量结果。计算图应该接受外部输入变得参数化。placeholders(占位符)可以在之后提供值。

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

上面三行代码有点像我们定义两个输入参数和关于这两个参数的节点的函数或匿名函数。我们可以用feed_dict参数来指定提供具体值的张量给这些placeholders来计算多输入的计算图。

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

《TensorFlow入门(一)安装与基本框架》 在TensorBoard中的图形显示

我们可以通过增加另一个节点使计算图更加复杂

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

产生输出22.5

《TensorFlow入门(一)安装与基本框架》 在TensorBoard中的图形显示

在机器学习中,我们通常需要任意输入,为了使模型可训练,我们需要修改模型使在相同输入下得到新的输出。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之前,变量是为初始化的。

区别:

tf.Variable:训练模型时用于更新存储参数,声明时必须提供初始值

tf.placeholder:用于得到传递进来的真实的训练样本,不必指定初始值,可在运行时,通过Session.run的函数的feed_dict参数指定

既然x是placeholder,我们可以训练linear_model来同时计算x的几个值

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

得到输出
[ 0. 0.30000001 0.60000002 0.90000004]
我们构造了一个模型但并不知道他的性能。为了在训练集上评估模型,我们需要一个y placeholder来提供期望值,和一个loss funciton(代价函数)

代价函数表征了当前模型与提供数据的距离。我们将在线性回归上用一个标准的代价函数,即当前模型与提供数据的delta的平方和。linear_model-y构造了一个向量,它的每个元素即使样本的误差delta。然后调用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

我们只是猜想得到理想的w和b的值,但机器学习的目的就是要自动找出理想的模型参数。我们将在下一节介绍

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

这样复杂的代码仍可以在tensorboard中可视化

《TensorFlow入门(一)安装与基本框架》 在TensorBoard中的图形显示

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.
print(estimator.evaluate(input_fn=input_fn))

自定义模型

tf.contrib.learn没有限制你使用它的预定义模型,假设我们想创建自定义的模型,我们仍能够在tf.contrib.learn保持对数据集、攻击、训练等的高级抽象。我们将展示用底层API实现等价模型线性回归。

为了定制tf.contrib.learn上的自定义模型,我们需要使用tf.contrib.learn.Estimator。tf.contrib.learn.LinearRegressor也是tf.contrib.learn.Estimator的一个子类。

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

定制的model函数与底层API的训练循环模型非常相似!

    原文作者:迅速傅里叶变换
    原文地址: https://www.jianshu.com/p/6e6a8bf1f88b
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞