Tensorflow

Tensorflow

Tensorflow简介

TensorFlow™ 是一个开放源代码软件库,用于进行高性能数值计算。借助其灵活的架构,用户可以轻松地将计算工作部署到多种平台(CPU、GPU、TPU)和设备(桌面设备、服务器集群、移动设备、边缘设备等)。TensorFlow™ 最初是由 Google Brain 团队(隶属于 Google 的 AI 部门)中的研究人员和工程师开发的,可为机器学习和深度学习提供强力支持,并且其灵活的数值计算核心广泛应用于许多其他科学领域。

Tensorflow安装

Tensorflow分为CPU与GPU两个版本,可以使用如下命令安装Tensorflow。
pip install tensorflow(CPU版本)
pip install tensorflow-gpu(GPU版本)
安装之后,在程序中就可以通过import导入使用,按照管理,我们重命名为tf。
import tensorflow as tf 可以通过如下的方式查看tenforflow的版本:
tf.__version__

计算方式

Tensorflow是通过数据流图完成计算的。Tensorflow的名称就是Tensor + flow。
Tensor就是张量,张量是深度学习中表示数据的标准方式。简单的说,张量就是多维数组。
flow就是数据的流动,是张量从一端流动到另外一端的过程。
图是由节点与边连接构成,在Tensorflow中,节点表示操作,边表示张量对象(张量的流动)。

官方案例演示

http://playground.tensorflow.org

第一个程序

使用tensorflow的常量编写第一个tensorflow程序Hello world,并观察与以前Python程序有何不同之处。

# Python版本
# s = "Hello"
# s2 = " World"
# s3 = s + s2
# print(s3)

# tensorflow

# 创建tensorflow中的常量。
s = tf.constant("Hello", name="s")
s2 = tf.constant(" World", name="s2")
# s3 = s + s2
s3 = tf.add(s, s2, name="my_add")
print(s)
print(s2)
print(s3)
# tensorflow与Python的计算规则不同,我们输出相关的变量(张量),并不能够得到计算的结果。
# tensorflow是基于计算图的,我们创建的张量会加入到计算图当中。我们对张量执行的操作(加,减,乘,除等)
# 并没有产生真正的计算,而是仅仅描述计算规则而已。

在Tensorflow中,当我们期望计算时,实际上,并没有执行真正的计算,而是把这些计算操作添加到图当中。而计算图在稍后才会执行(图只是用来描述了计算的规则,而并没有产生真正的计算)。
简单说,使用Tensorflow包含两个步骤:

  • 构建图
  • 执行图

思考:为什么要使用图的概念,而不是直接进行像Python那样执行计算?

图的创建

当我们引入tensorflow时,一个空的默认图就已经创建完成了。我们后续创建的节点都会关联到该默认图上。当然,我们也可以自己创建图,然后关联相关的节点。

说明:

  • 可以通过操作对象的graph属性来获取操作所属的图。
  • 可以使用with与as_default来切换默认图。
  • 不同图中定义的操作,不能进行运算。
  • Tensorflow对类型的要求非常严格,不同类型之间无法进行运算
# 当我们引入tensorflow时,就会创建一个默认图。
# import tensorflow as tf
# 获取默认图。
g = tf.get_default_graph()
# 当我们创建张量,执行操作时,就会自动加入到默认图当中。
a = tf.constant(100)
# 通过张量的graph属性,可以获取张量所属的图。
# print(a.graph is g)
# 我们也可以去创建自己的图,而不是使用默认图。
my_graph = tf.Graph()
# 我们可以通过上下文管理器来设置默认图。
# as_default()返回上下文管理器对象,我们可以与with结合使用。
# 在__enter__方法中,会将当前的图(调用as_default方法的图)设置为默认图。
# 在__exit__方法中,会将默认图恢复成修改之前的图。
with my_graph.as_default():
    # with上下文中,my_graph就是默认图。
#     print(my_graph is tf.get_default_graph())
    # 我们在with上下文中,创建的张量,加入到了my_graph图中。
    b = tf.constant(200)
print(b.graph is my_graph)    
# print(my_graph is g)
# print(my_graph is tf.get_default_graph())

# 不在同一个图的节点不能进行计算。
# 错误!
# a + b

# 在Python中,不同的类型也可能进行计算。例如:int与float, int与bool。
# 但是,Tensorflow的计算对类型要求非常严格,只要不是同一个类型,就不能进行计算。
c = tf.constant(1, dtype=tf.int32)
d = tf.constant(2, dtype=tf.int64)
# 错误。只要不是同一个类型,就不能进行计算。(int32与int64也不可以。)
# c + d

图的运行

我们可以通过创建Session对象,来运行图(获取数据)。Session对象在使用之后需要进行关闭,我们可以使用with来简化关闭的操作。
我们也可以创建交互式会话(InteractiveSession)。二者之间的差别在于:交互式会话相当于设置了默认的Session。在进行求值时,无需显式指定。

c = tf.constant(1, dtype=tf.int32)
d = tf.constant(2, dtype=tf.int32)
e = c + d
# 运行图需要Session(会话)对象的支持。
# sess = tf.Session()
# 运行图, 参数指定要获取的值。
# sess.run(e)
# Session对象使用完成后,需要关闭会话。
# esss.close()

# 我们通常将Session对象放入with环境下。
with tf.Session() as sess:
    print(sess.run(e))
    

# 与Session对应的,还提供了一个交互式会话对象InteractiveSession。
# Session与InteractiveSession的区别仅在于:
# InteractiveSession在创建后,会自动注册为默认的Session对象(这在IPython等交互式环境下,
# 会带来一定的方便性,在eval的时候,不需要再显式指定Session对象)。
# 而Session在创建后,则不会。
sess = tf.InteractiveSession()
# sess = tf.Session()
# 对张量进行求值,我们可以使用sess.run,或者使用张量对象.eval。但是,后者
# 需要显式指定运行的会话对象(Session对象)
# print(sess.run(e))
# print(e.eval(session=sess))
# 如果没有显式指定Session,并且,当前也没有默认的Session对象,将会产生错误。
# print(e.eval())
print(e.eval())

# with tf.Session() as sess:
# 有两个作用:
# 1 不需要显式调用close方法去关闭session。
# 2 在with环境下,当前创建的Session对象会注册为默认的Session对象,
# 因此,我们在调用eval,run等方法时,我们就可以不用显式去指定Session对象。
# 离开with环境后,默认的Session对象会恢复成之前的形式。
with tf.Session() as sess:
#     sess.run(e)
    # 可以不用去指定session对象。
    print(e.eval())
    # 如果需要获取多个值,可以传递一个数组。
    print(sess.run([c, d, e]))

变量与占位符

变量与占位符也是张量Tensor类型。

  • 占位符表示其值由用户进行传递,通常用来存储样本数据与标签。
  • 变量在计算过程中,可以改变其值,通常用来存储模型的参数。

说明:

  • 变量必须要初始化后才能使用。
  • 占位符的数据,需要使用实际值进行填充。
# 变量,在程序运行过程中可以发生改变的量。
# 变量通常用来保存模型的参数(权重)。

# 创建变量
a = tf.Variable([[1, 2], [3, 4]])
b = tf.Variable([[0, 1], [2, 3]])
# 实现矩阵点积运算。
c = tf.matmul(a, b)

# 变量与常量不同,如果我们需要对变量求值,则必须首先对变量进行初始化操作。否则会产生错误。
with tf.Session() as sess:
    # 获取全局变量初始化器。(操作类型)
    init = tf.global_variables_initializer()
    # 执行变量的初始化。
    sess.run(init)
#     print(type(init))
    print(sess.run(c))

# 占位符类似Python格式化输出中的占位符,在运行时,使用传递的真实值进行替换。
# 占位符通常用来标识模型的输入数据(样本的特征与标签)。
a = tf.constant([[1, 2], [3, 4]])
# 创建占位符。
b = tf.placeholder(dtype=tf.int32, shape=(2, 2))
c = tf.matmul(a, b)
with tf.Session() as sess:
    # 如果运行中需要依赖占位符,则必须要进行填充值。
    # 使用feed_dict来进行传值,该参数需要传递字典类型,key用来指定占位符对象(引用变量),
    # value用来指定该占位符的填充值。
    print(sess.run(c, feed_dict={b:[[0, 1],[2, 3]]}))

变量的作用域

在我们使用tf.Variable定义变量时,每次执行,就会创建一个新的变量。有时,我们可能并不总是想创建新的变量,而是可以复用已经创建的变量。这样,就可以实现变量共享。
通过tf.variable_scope方法可以创建变量作用域,通过该作用域获取变量时,会进行检查。因此,我们就能够控制创建变量或者复用已经存在(创建好)的变量。

说明:

  • 通过变量作用域,就可以避免意外创建或者共享变量。
  • 使用reuse参数来控制获取变量的行为。该参数的意义如下:
    • 默认为获取新变量,当变量已经存在时,出错。
    • tf.AUTO_REUSE 当变量不存在时,创建变量,存在时,复用已经创建的变量。
    • true 复用变量,当变量不存在时出错。
  • 底层会使用作用域名/变量名:0的方式来标记变量。
# 创建变量作用域。
# 作用:
# 1 可以避免意外的创建新的变量。
# 2 可以实现变量的复用,而无需再创建新的变量。

# variable_scope应该与get_variable结合使用。tf.Variable总是无条件创建新的变量。
# reuse 默认为False。创建新的变量。如果变量不存在,则创建,如果存在,则产生错误。
# with tf.variable_scope("my_scope"):
#     v = tf.get_variable("my_var", shape=(3,), initializer=tf.random_normal_initializer(mean=0, stddev=1))
#     print(v.name)
# reuse = True,重用变量,当变量已经存在时,复用已经存在的变量,否则,会产生错误。
# 这样可以避免去意外创建新的变量。
# with tf.variable_scope("my_scope", reuse=True):
#     v = tf.get_variable("my_var1", shape=(3,), initializer=tf.random_normal_initializer(mean=0, stddev=1))
#     print(v.name)

# tf.AUTO_REUSE  自动重用变量,如果变量不存在,则创建变量,如果变量已经存在,则复用现有的变量。
# with tf.variable_scope("my_scope", reuse=tf.AUTO_REUSE):
#     v = tf.get_variable("my_var1", shape=(3,), initializer=tf.random_normal_initializer(mean=0, stddev=1))
#     print(v.name)

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    with tf.variable_scope("my_scope", reuse=tf.AUTO_REUSE):
        v = tf.get_variable("my_var", shape=(3,), initializer=tf.random_normal_initializer(mean=0, stddev=1))
        print(sess.run(v), id(v))

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    with tf.variable_scope("my_scope", reuse=tf.AUTO_REUSE):
        v = tf.get_variable("my_var", shape=(3,), initializer=tf.random_normal_initializer(mean=0, stddev=1))
        print(sess.run(v), id(v))

程序示例

  1. 使用Tensorflow实现一元线性回归。
    ?=0.5∗?+0.4 y=0.5∗x+0.4
  2. 使用Tensorflow实现二元线性回归。
    ?=0.5∗?1+0.3∗?2+0.4 y=0.5∗x1+0.3∗x2+0.4
import matplotlib.pyplot as plt
import numpy as np

# 创造样本x。
x_sample = np.linspace(-5, 5, 100).reshape(-1, 1)
# 根据方程式,创造样本y。
y_sample = 0.5 * x_sample + 0.4
# 在y的上面,增加一个噪声。
y_sample += np.random.normal(scale=0.1, size=y_sample.shape)
# 对于模型的输入,我们定义为placeholder,占位符。
# shape中的None表示不固定,按实际需要就可以。(对实际传递的形状没有要求)
x = tf.placeholder(tf.float32, shape=(None, 1))
y = tf.placeholder(tf.float32, shape=(None, 1))
# 模型的参数(权重),应该定义成变量。
w = tf.Variable(0.0)
b = tf.Variable(0.0)
# 构建模型方程。
y_hat = x * w + b
# 使用均方误差损失函数。
loss = tf.reduce_mean(tf.square(y - y_hat))
# 使用梯度下降优化器,对损失值进行优化。优化的过程中,就会调整模型中的参数(w与b)
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(loss)
with tf.Session() as sess:
    # 变量进行初始化。
    sess.run(tf.global_variables_initializer())
    # 执行(调整)1000次。
    for i in range(1, 1001):
        result = sess.run([train_step, w, b], feed_dict={x: x_sample, y: y_sample})
        if i % 100 == 0:
            print(result[1:])
    plt.scatter(x_sample, y_sample)
    plt.plot(x_sample, sess.run(y_hat, feed_dict={x: x_sample, y: y_sample}), color="r")
    plt.show()
from mpl_toolkits.mplot3d import Axes3D
# tk 在虚拟环境中有些问题。
%matplotlib qt

x1 = np.linspace(-5, 5, 30)
x2 = np.linspace(-5, 5, 30)
X1, X2 = np.meshgrid(x1, x2)
# 构建样本x,每个样本还有两个元素。
X_sample = np.array([X1.ravel(), X2.ravel()]).T
# 构建标签y。
y_sample = np.dot(X_sample, np.array([[0.5], [0.3]])) + 0.4
# 加入噪声。
y_sample += np.random.normal(size=y_sample.shape, scale=0.1)
# 模型的输入。
X = tf.placeholder(shape=[None, 2], dtype=tf.float32)
y = tf.placeholder(shape=[None, 1], dtype=tf.float32)
# 模型的参数(权重)
w = tf.Variable(tf.random_normal(shape=[2, 1], stddev=0.1))
b = tf.Variable(tf.zeros(1))
y_hat = tf.matmul(X, w) + b
# 定义损失函数。
loss = tf.reduce_mean(tf.square(y - y_hat))
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(loss)
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for i in range(1, 1001):
        result = sess.run([train_step, w, b], feed_dict={X:X_sample, y:y_sample})
        if i % 100 == 0:
            print(result[1:])
    fig = plt.figure()
    ax = Axes3D(fig)
    ax.scatter(X_sample[:, 0], X_sample[:, 1], y_sample, color="b")
    # 这里,y_hat的形状需要与X1(X2)的形状相同。
    surf = ax.plot_surface(X1, X2, y_hat.eval(feed_dict={X:X_sample, y:y_sample}).reshape(X1.shape),
            rstride=5, cstride=5, cmap="rainbow")
    # 显示颜色条。
    fig.colorbar(surf)
    plt.show()

你可能感兴趣的:(Tensorflow)