Python--TensorFlow

TensorFlow


张量(Tensor)

  • TensorFlow 内部的计算都是基于张量的,张量是在我们熟悉的标量、向量之上定义的,详细的定义比较复杂,我们可以先简单的将它理解为一个多维数组:

    3 # 这个 0 阶张量就是标量,shape=[]
    [1., 2., 3.] # 这个 1 阶张量就是向量,shape=[3]
    [[1., 2., 3.], [4., 5., 6.]] # 这个 2 阶张量就是二维数组,shape=[2, 3]
    [[[1., 2., 3.]], [[7., 8., 9.]]] # 这个 3 阶张量就是三维数组,shape=[2, 1, 3]

  • TensorFlow 内部使用tf.Tensor类的实例来表示张量,每个 tf.Tensor有两个属性:
    – dtype Tensor 存储的数据的类型,可以为tf.float32、tf.int32、tf.string…
    – shape Tensor 存储的多维数组中每个维度的数组中元素的个数,如上面中的shape

  • 我们现在可以敲几行代码看一下 Tensor 。

    # 引入 tensorflow 模块
    import tensorflow as tf
    # 创建一个整型常量,即 0 阶 Tensor
    t0 = tf.constant(3, dtype=tf.int32)
    # 创建一个浮点数的一维数组,即 1 阶 Tensor
    t1 = tf.constant([3., 4.1, 5.2], dtype=tf.float32)
    # 创建一个字符串的2x2数组,即 2 阶 Tensor
    t2 = tf.constant([['Apple', 'Orange'], ['Potato', 'Tomato']], dtype=tf.string)
    # 创建一个 2x3x1 数组,即 3 阶张量,数据类型默认为整型
    t3 = tf.constant([[[5], [6], [7]], [[4], [3], [2]]])
    # 打印上面创建的几个 Tensor
    print(t0)
    print(t1)
    print(t2)
    print(t3)
    
  • 上面代码的输出为,注意shape的类型:

    print(t0)
    Tensor(“Const:0”, shape=(), dtype=int32)

    print(t1)
    Tensor(“Const_1:0”, shape=(3,), dtype=float32)

    print(t2)
    Tensor(“Const_2:0”, shape=(2, 2), dtype=string)

    print(t3)
    Tensor(“Const_3:0”, shape=(2, 3, 1), dtype=int32)

  • print 一个 Tensor 只能打印出它的属性定义,并不能打印出它的值,要想查看一个 Tensor 中的值还需要经过Session 运行一下:

    sess = tf.Session()
    print(sess.run(t0))

数据流图(Dataflow Graph)

  • 数据流是一种常用的并行计算编程模型,数据流图是由节点(nodes)和线(edges)构成的有向图,节点(nodes) 表示计算单元,也可以是输入的起点或者输出的终点;线(edges) 表示节点之间的输入/输出关系。
  • TensorFlow 中的数据流图有以下几个优点:
    • 可并行 计算节点之间有明确的线进行连接,系统可以很容易的判断出哪些计算操作可以并行执行
    • 可分发 图中的各个节点可以分布在不同的计算单元(CPU、 GPU、 TPU等)或者不同的机器中,每个节点产生的数据可以通过明确的线发送的下一个节点中
    • 可优化 TensorFlow 中的 XLA 编译器可以根据数据流图进行代码优化,加快运行速度
    • 可移植 数据流图的信息可以不依赖代码进行保存,如使用Python创建的图,经过保存后可以在C++或Java中使用

Sesssion

  • 我们在Python中需要做一些计算操作时一般会使用NumPy,NumPy在做矩阵操作等复杂的计算的时候会使用其他语言(C/C++)来实现这些计算逻辑,来保证计算的高效性。但是频繁的在多个编程语言间切换也会有一定的耗时,如果只是单机操作这些耗时可能会忽略不计,但是如果在分布式并行计算中,计算操作可能分布在不同的CPU、GPU甚至不同的机器中,这些耗时可能会比较严重。
  • TensorFlow 底层是使用C++实现,这样可以保证计算效率,并使用 tf.Session类来连接客户端程序与C++运行时。上层的Python、Java等代码用来设计、定义模型,构建的Graph,最后通过tf.Session.run()方法传递给底层执行。

构建计算图

  • 上面介绍的是 TensorFlow 和 Graph 的概念,下面介绍怎么用 Tensor 构建 Graph。
    Tensor 即可以表示输入、输出的端点,还可以表示计算单元,如下的代码创建了对两个 Tensor 执行 + 操作的 Tensor:

    import tensorflow as tf
    # 创建两个常量节点
    node1 = tf.constant(3.2)
    node2 = tf.constant(4.8)
    # 创建一个 adder 节点,对上面两个节点执行 + 操作
    adder = node1 + node2
    # 打印一下 adder 节点
    print(adder)
    # 打印 adder 运行后的结果
    sess = tf.Session()
    print(sess.run(adder))
    

    上面print的输出为:

    Tensor(“add:0”, shape=(), dtype=float32)
    8.0

  • 上面使用tf.constant()创建的 Tensor 都是常量,一旦创建后其中的值就不能改变了。有时我们还会需要从外部输入数据,这时可以用tf.placeholder 创建占位 Tensor,占位 Tensor 的值可以在运行的时候输入。如下就是创建占位 Tensor 的例子:

    import tensorflow as tf
    # 创建两个占位 Tensor 节点
    a = tf.placeholder(tf.float32)
    b = tf.placeholder(tf.float32)
    # 创建一个 adder 节点,对上面两个节点执行 + 操作
    adder_node = a + b
    # 打印三个节点
    print(a)
    print(b)
    print(adder)
    # 运行一下,后面的 dict 参数是为占位 Tensor 提供输入数据
    sess = tf.Session()
    print(sess.run(adder, {a: 3, b: 4.5}))
    print(sess.run(adder, {a: [1, 3], b: [2, 4]}))
    

    上面代码的输出为:

    Tensor(“Placeholder:0”, dtype=float32)
    Tensor(“Placeholder_1:0”, dtype=float32)
    Tensor(“add:0”, dtype=float32)
    7.5
    [ 3. 7.]

TensorFlow 应用实例

1.建立一个线性模型,并为这个线性模型设计了一个损失模型:

	import tensorflow as tf
	# 创建变量 W 和 b 节点,并设置初始值
	W = tf.Variable([.1], dtype=tf.float32)
	b = tf.Variable([-.1], dtype=tf.float32)
	# 创建 x 节点,用来输入实验中的输入数据
	x = tf.placeholder(tf.float32)
	# 创建线性模型
	linear_model = W*x + b
	
	# 创建 y 节点,用来输入实验中得到的输出数据,用于损失模型计算
	y = tf.placeholder(tf.float32)
	# 创建损失模型
	loss = tf.reduce_sum(tf.square(linear_model - y))
	
	# 创建 Session 用来计算模型
	sess = tf.Session()

2. 使用 TensorFlow 训练模型

  • 我们需要不断调整变量W和b的值,找到使损失值最小的W和b。这肯定是一个very boring的过程,因此 TensorFlow 提供了训练模型的方法,自动帮我们进行这些繁琐的训练工作。
  • TensorFlow 提供了很多优化算法来帮助我们训练模型。最简单的优化算法是梯度下降(Gradient Descent)算法,它通过不断的改变模型中变量的值,来找到最小损失值。
    如下的代码就是使用梯度下降优化算法帮助我们训练模型:
	# 创建一个梯度下降优化器,学习率为0.001
	optimizer = tf.train.GradientDescentOptimizer(0.001)
	train = optimizer.minimize(loss)
	
	# 用两个数组保存训练数据
	x_train = [1, 2, 3, 6, 8]
	y_train = [4.8, 8.5, 10.4, 21.0, 25.3]
	
	# 训练10000次
	for i in range(10000):
	    sess.run(train, {x: x_train, y: y_train})
	
	# 打印一下训练后的结果
	print('W: %s b: %s loss: %s' % (sess.run(W), sess.run(b), sess.run(loss, {x: x_train , y: y_train})))
  1. 整理一下前面的代码,完整的demo代码如下,将下面的代码保存在一个demo.py文件里,通过python3 demo.py执行一下就可以看到训练结果了:
	import tensorflow as tf
	
	# 创建变量 W 和 b 节点,并设置初始值
	W = tf.Variable([.1], dtype=tf.float32)
	b = tf.Variable([-.1], dtype=tf.float32)
	# 创建 x 节点,用来输入实验中的输入数据
	x = tf.placeholder(tf.float32)
	# 创建线性模型
	linear_model = W * x + b
	
	# 创建 y 节点,用来输入实验中得到的输出数据,用于损失模型计算
	y = tf.placeholder(tf.float32)
	# 创建损失模型
	loss = tf.reduce_sum(tf.square(linear_model - y))
	
	# 创建 Session 用来计算模型
	sess = tf.Session()
	
	# 初始化变量
	init = tf.global_variables_initializer()
	sess.run(init)
	
	# 创建一个梯度下降优化器,学习率为0.001
	optimizer = tf.train.GradientDescentOptimizer(0.001)
	train = optimizer.minimize(loss)
	
	# 用两个数组保存训练数据
	x_train = [1, 2, 3, 6, 8]
	y_train = [4.8, 8.5, 10.4, 21.0, 25.3]
	
	# 训练10000次
	for i in range(10000):
	    sess.run(train, {x: x_train, y: y_train})
	
	# 打印一下训练后的结果
	print('W: %s b: %s loss: %s' % (sess.run(W), sess.run(  b), sess.run(loss, {x: x_train, y: y_train})))

TensorFlow 高级训练模型

  • 前面的demo中我们构建了一个线性模型,通过使用一组实验数据训练我们的线性模型,我们得到了一个自认为损失最小的最优模型, 但是这个我们自认为的最优模型是否会一直是最优的?我们需要通过一些新的实验数据来评估(evaluation)模型的泛化性能(generalization performance),如果新的实验数据应用到到这个模型中损失值越小,那么这个模型的泛化性能就越好,反之就越差。下面的demo中我们也会看到怎么评估模型。
    1. 使用LinearRegressor
    前面我们构建了一个线性模型,通过训练得到一个线性回归方程。tf.estimator中也提供了线性回归的训练模型tf.estimator.LinearRegressor,下面的代码就是使用LinearRegressor训练并评估模型的方法:
	# 我们会用到NumPy来处理各种训练数据
	import numpy as np
	import tensorflow as tf
	
	# 创建一个特征向量列表,该特征列表里只有一个特征向量,
	# 该特征向量为实数向量,只有一个元素的数组,且该元素名称为 x,
	# 我们还可以创建其他更加复杂的特征列表
	feature_columns = [tf.feature_column.numeric_column("x", shape=[1])]
	
	# 创建一个LinearRegressor训练器,并传入特征向量列表
	estimator = tf.estimator.LinearRegressor(feature_columns=feature_columns)
	
	# 保存训练用的数据
	x_train = np.array([1., 2., 3., 6., 8.])
	y_train = np.array([4.8, 8.5, 10.4, 21.0, 25.3])
	
	# 保存评估用的数据
	x_eavl = np.array([2., 5., 7., 9.])
	y_eavl = np.array([7.6, 17.2, 23.6, 28.8])
	
	# 用训练数据创建一个输入模型,用来进行后面的模型训练
	# 第一个参数用来作为线性回归模型的输入数据
	# 第二个参数用来作为线性回归模型损失模型的输入
	# 第三个参数batch_size表示每批训练数据的个数
	# 第四个参数num_epochs为epoch的次数,将训练集的所有数据都训练一遍为1次epoch
	# 低五个参数shuffle为取训练数据是顺序取还是随机取
	train_input_fn = tf.estimator.inputs.numpy_input_fn(
	    {"x": x_train}, y_train, batch_size=2, num_epochs=None, shuffle=True)
	
	# 再用训练数据创建一个输入模型,用来进行后面的模型评估
	train_input_fn_2 = tf.estimator.inputs.numpy_input_fn(
	    {"x": x_train}, y_train, batch_size=2, num_epochs=1000, shuffle=False)
	
	# 用评估数据创建一个输入模型,用来进行后面的模型评估
	eval_input_fn = tf.estimator.inputs.numpy_input_fn(
	    {"x": x_eavl}, y_eavl, batch_size=2, num_epochs=1000, shuffle=False)
	
	# 使用训练数据训练1000次
	estimator.train(input_fn=train_input_fn, steps=1000)
	
	# 使用原来训练数据评估一下模型,目的是查看训练的结果
	train_metrics = estimator.evaluate(input_fn=train_input_fn_2)
	print("train metrics: %r" % train_metrics)
	
	# 使用评估数据评估一下模型,目的是验证模型的泛化性能
	eval_metrics = estimator.evaluate(input_fn=eval_input_fn)
	print("eval metrics: %s" % eval_metrics)

运行上面的代码输出为:

train metrics: {‘loss’: 1.0493528, ‘average_loss’: 0.52467638, ‘global_step’: 1000}
eval metrics: {‘loss’: 0.72186172, ‘average_loss’: 0.36093086, ‘global_step’: 1000}

2. 自定义Estimator模型

  • tf.estimator库中提供了很多预定义的训练模型,但是有可能这些训练模型不能满足我们的需求,我们需要使用自己构建的模型。
  • 我们可以通过实现tf.estimator.Estimator的子类来构建我们自己的训练模型,LinearRegressor就是Estimator的一个子类。另外我们也可以只给Estimator基类提供一个model_fn的实现,定义我们自己的模型训练、评估方法以及计算损失的方法。
  • 下面的代码就是使用我们最开始构建的线性模型实现自定义Estimator的实例。
	import numpy as np
	import tensorflow as tf
	
	# 定义模型训练函数,同时也定义了特征向量
	def model_fn(features, labels, mode):
	    # 构建线性模型
	    W = tf.get_variable("W", [1], dtype=tf.float64)
	    b = tf.get_variable("b", [1], dtype=tf.float64)
	    y = W * features['x'] + b
	    # 构建损失模型
	    loss = tf.reduce_sum(tf.square(y - labels))
	    # 训练模型子图
	    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指定我们的训练子图积极损失模型
	    return tf.estimator.EstimatorSpec(
	        mode=mode,
	        predictions=y,
	        loss=loss,
	        train_op=train)
	
	# 创建自定义的训练模型
	estimator = tf.estimator.Estimator(model_fn=model_fn)
	
	# 后面的训练逻辑与使用LinearRegressor一样
	x_train = np.array([1., 2., 3., 6., 8.])
	y_train = np.array([4.8, 8.5, 10.4, 21.0, 25.3])
	
	x_eavl = np.array([2., 5., 7., 9.])
	y_eavl = np.array([7.6, 17.2, 23.6, 28.8])
	
	train_input_fn = tf.estimator.inputs.numpy_input_fn(
	    {"x": x_train}, y_train, batch_size=2, num_epochs=None, shuffle=True)
	
	train_input_fn_2 = tf.estimator.inputs.numpy_input_fn(
	    {"x": x_train}, y_train, batch_size=2, num_epochs=1000, shuffle=False)
	
	eval_input_fn = tf.estimator.inputs.numpy_input_fn(
	    {"x": x_eavl}, y_eavl, batch_size=2, num_epochs=1000, shuffle=False)
	
	estimator.train(input_fn=train_input_fn, steps=1000)
	
	train_metrics = estimator.evaluate(input_fn=train_input_fn_2)
	print("train metrics: %r" % train_metrics)
	
	eval_metrics = estimator.evaluate(input_fn=eval_input_fn)
	print("eval metrics: %s" % eval_metrics)

上面代码的输出为

train metrics: {‘loss’: 0.8984344, ‘global_step’: 1000}
eval metrics: {‘loss’: 0.48776609, ‘global_step’: 1000}

TensorBoard

  • 为了更方便 TensorFlow 的建模和调优,Google 还为 TensorFlow 开发了一款可视化的工具:TensorBoard,将我们第一个Demo的代码稍微改造一下,就可以使用 TensorBoard更加直观的理解 TensorFlow 的训练过程。
	import tensorflow as tf
	
	# 创建节点时设置name,方便在图中识别
	W = tf.Variable([0], dtype=tf.float32, name='W')
	b = tf.Variable([0], dtype=tf.float32, name='b')
	
	# 创建节点时设置name,方便在图中识别
	x = tf.placeholder(tf.float32, name='x')
	y = tf.placeholder(tf.float32, name='y')
	
	# 线性模型
	linear_model = W * x + b
	
	# 损失模型隐藏到loss-model模块
	with tf.name_scope("loss-model"):
	    loss = tf.reduce_sum(tf.square(linear_model - y))
	    # 给损失模型的输出添加scalar,用来观察loss的收敛曲线
	    tf.summary.scalar("loss", loss)
	
	optmizer = tf.train.GradientDescentOptimizer(0.001)
	
	train = optmizer.minimize(loss)
	
	x_train = [1, 2, 3, 6, 8]
	y_train = [4.8, 8.5, 10.4, 21.0, 25.3]
	
	
	sess = tf.Session()
	init = tf.global_variables_initializer()
	sess.run(init)
	
	# 调用 merge_all() 收集所有的操作数据
	merged = tf.summary.merge_all()
	
	# 模型运行产生的所有数据保存到 /tmp/tensorflow 文件夹供 TensorBoard 使用
	writer = tf.summary.FileWriter('/tmp/tensorflow', sess.graph)
	
	# 训练10000次
	for i in range(10000):
	    # 训练时传入merge
	    summary, _ = sess.run([merged, train], {x: x_train, y: y_train})
	    # 收集每次训练产生的数据
	    writer.add_summary(summary, i)
	
	curr_W, curr_b, curr_loss = sess.run(
	    [W, b, loss], {x: x_train, y: y_train})
	
	print("After train W: %s b %s loss: %s" % (curr_W, curr_b, curr_loss))
  • 运行完上面的代码后,训练过程产生的数据就保存在 /tmp/tensorflow 文件夹了,我们可以在命令行终端运行下面的命令启动 TensorBoard:

    通过 --logdir 参数设置我们存放训练数据的目录
    $ tensorboard --logdir /tmp/tensorflow

然后在浏览器中打开 http://localhost:6006 页面就可以看到我们的模型数据了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值