dl_tensorflow_guide_低阶API

1 低阶API

设置python环境

pip3 install tensorflow==1.12 -i https://pypi.tuna.tsinghua.edu.cn/simple

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import numpy as np
import tensorflow as tf

张量值

  • TensorFlow 使用 numpy 阵列来表示张量值。
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]
[[[1.0, 2.0, 3.0]], [[7.0, 8.0, 9.0]]]

计算图

  • 语句只会构建计算图。这些 tf.Tensor 对象仅代表将要运行的操作的结果。
  • 张量是根据生成它们的指令命名的,后面跟着输出索引,如上文的 “add:0” 所示
  • 静态图
    • 记录关系
  • 节点
    • 算子
      • 记录计算关系
  • 搭建水管
a = tf.constant(3.0, dtype=tf.float32)
b = tf.constant(4.0) # also tf.float32 implicitly
total = a + b
print(a)
print(b)
print(total)
Tensor("Const:0", shape=(), dtype=float32)
Tensor("Const_1:0", shape=(), dtype=float32)
Tensor("add:0", shape=(), dtype=float32)

TensorBoard

  • 计算图可视化
writer = tf.summary.FileWriter('.')
writer.add_graph(tf.get_default_graph())
#!tensorboard --logdir .

http://localhost:6006/#graphs&run=.

会话 (Session)

  • tf.Session 对象
  • 封装 TensorFlow 运行时的状态,并运行 TensorFlow 操作
  • run 方法来评估我们在上文中创建的 total 张量
    • 当您使用 Session.run 请求输出节点时,TensorFlow 会回溯整个图,
    • 并流经提供了所请求的输出节点对应的输入值的所有节点
  • 可以将多个张量传递给 tf.Session.run
  • 分配计算资源
  • 打开水龙图
  • 判断依赖关系
  • with语句,自动资源管理
sess = tf.Session()
print(sess.run(total))
7.0
print(sess.run({'ab':(a, b), 'total':total}))
{'total': 7.0, 'ab': (3.0, 4.0)}

每次调用 run 时,结果都会显示不同的随机值,但在单个 run 期间(out1 和 out2 接收到相同的随机输入值),结果显示的值是一致的:

vec = tf.random_uniform(shape=(3,))
out1 = vec + 1
out2 = vec + 2
print(sess.run(vec))
print(sess.run(vec))
print(sess.run((out1,out2)))
[0.8744987  0.3439585  0.05480385]
[0.6525699 0.7171612 0.9097812]
(array([1.7585876, 1.2583141, 1.6946543], dtype=float32), array([2.7585876, 2.2583141, 2.6946545], dtype=float32))

占位符 placeholder

目前来讲,这个图不是特别有趣,因为它总是生成一个常量结果。

  • 图可以参数化以便接受外部输入,也称为占位符。
  • 占位符表示承诺在稍后提供值,它就像函数参数。
x = tf.placeholder(tf.float32)
y = tf.placeholder(tf.float32)
z = x + y
  • 前面三行有点像函数。
  • 我们定义了这个函数的两个输入参数(x 和 y),然后对它们运行指令。
  • 我们可以使用 run 方法的 feed_dict 参数为占位符提供具体的值,从而评估这个具有多个输入的图:
print(sess.run(z, feed_dict={x: 3, y: 4.5}))
print(sess.run(z, feed_dict={x: [1, 3], y: [2, 4]}))
7.5
[3. 7.]

数据集

  • 占位符适用于简单的实验,而数据集是将数据流式传输到模型的首选方法。
  • 要从数据集中获取可运行的 tf.Tensor,您必须先将其转换成 tf.data.Iterator,然后调用迭代器的 get_next 方法。
  • 创建迭代器的最简单的方式是采用 make_one_shot_iterator 方法。例如,在下面的代码中,next_item 张量将在每次 run 调用时从 my_data 阵列返回一行:
my_data = [
    [0, 1,],
    [2, 3,],
    [4, 5,],
    [6, 7,],
]
slices = tf.data.Dataset.from_tensor_slices(my_data)
print(type(slices))
next_item = slices.make_one_shot_iterator().get_next()
<class 'tensorflow.python.data.ops.dataset_ops.TensorSliceDataset'>

到达数据流末端时,Dataset 会抛出 OutOfRangeError。例如,下面的代码会一直读取 next_item,直到没有数据可读:

while True:
  try:
    print(sess.run(next_item))
  except tf.errors.OutOfRangeError:
    break
[0 1]
[2 3]
[4 5]
[6 7]

如果 Dataset 依赖于有状态操作,则可能需要在使用迭代器之前先初始化它,如下所示:

r = tf.random_normal([10,3])
dataset = tf.data.Dataset.from_tensor_slices(r)
iterator = dataset.make_initializable_iterator()
next_row = iterator.get_next()

sess.run(iterator.initializer)
while True:
  try:
    print(sess.run(next_row))
  except tf.errors.OutOfRangeError:
    break
[-1.0132575  1.3031845 -0.6429276]
[-0.7033596  -0.3365624  -0.04388215]
[ 0.00403259 -0.2319483   0.2555564 ]
[ 1.0925672   1.1205714  -0.42639807]
[-0.38956103 -1.202344   -1.2956861 ]
[-1.4274018  -0.1561978   0.12417508]
[-0.52844036 -1.9942417  -0.9224725 ]
[1.6623509  0.32826144 1.008489  ]
[-0.1316477  -0.03261911 -0.6876448 ]
[ 1.2795713 -0.944837  -1.3226062]

可训练的模型必须修改图中的值,以便在输入相同值的情况下获得新的输出值。将可训练参数添加到图中的首选方法是层。

层将变量和作用于它们的操作打包在一起。例如,密集连接层会对每个输出对应的所有输入执行加权和,并应用激活函数(可选)。连接权重和偏差由层对象管理

创建层

下面的代码会创建一个 Dense 层,
- 该层会接受一批输入矢量,并为每个矢量生成一个输出值。
- 要将层应用于输入值,请将该层当做函数来调用。例如:

层会检查其输入数据,以确定其内部变量的大小。因此,我们必须在这里设置 x 占位符的形状,以便层构建正确大小的权重矩阵

我们现在已经定义了输出值 y 的计算

x = tf.placeholder(tf.float32, shape=[None, 3])
linear_model = tf.layers.Dense(units=1)
y = linear_model(x)

初始化层

  • 层包含的变量必须先初始化,然后才能使用。
  • 尽管可以单独初始化各个变量,
  • 但也可以轻松地初始化一个 TensorFlow 图中的所有变量(如下所示)
init = tf.global_variables_initializer()
sess.run(init)
  • 重要提示:调用 tf.global_variables_initializer 仅会创建并返回 TensorFlow 操作的句柄。当我们使用 tf.Session.run 运行该操作时,该操作将初始化所有全局变量。
  • 另请注意,此 global_variables_initializer 仅会初始化创建初始化程序时图中就存在的变量。因此您应该在构建图表的最后一步添加初始化程序。

执行层

  • 我们现在已经完成了层的初始化,可以像处理任何其他张量一样评估 linear_model 的输出张量了。例如,下面的代码:
print(sess.run(y, {x: [[1, 2, 3],[4, 5, 6]]}))
[[-0.3522125]
 [-1.6149296]]

层函数的快捷方式

对于每个层类(如 tf.layers.Dense),TensorFlow 还提供了一个快捷函数(如 tf.layers.dense)。两者唯一的区别是快捷函数版本是在单次调用中创建和运行层。例如,以下代码等同于较早的版本:

尽管这种方法很方便,但无法访问 tf.layers.Layer 对象。这会让自省和调试变得更加困难,并且无法重复使用相应的层。

x = tf.placeholder(tf.float32, shape=[None, 3])
y = tf.layers.dense(x, units=1)

init = tf.global_variables_initializer()
sess.run(init)

print(sess.run(y, {x: [[1, 2, 3], [4, 5, 6]]}))
[[3.3312573]
 [7.103777 ]]

特征列

  • 使用特征列进行实验的最简单方法是使用 tf.feature_column.input_layer 函数。
  • 此函数只接受密集列作为输入,
  • 因此要查看类别列的结果,您必须将其封装在 tf.feature_column.indicator_column 中
features = {
    'sales' : [[5], [10], [8], [9]],
    'department': ['sports', 'sports', 'gardening', 'gardening']}

department_column = tf.feature_column.categorical_column_with_vocabulary_list(
        'department', ['sports', 'gardening'])
department_column = tf.feature_column.indicator_column(department_column)

columns = [
    tf.feature_column.numeric_column('sales'),
    department_column
]

inputs = tf.feature_column.input_layer(features, columns)
WARNING:tensorflow:From c:\users\clark_xu\.conda\envs\py35\lib\site-packages\tensorflow\python\ops\sparse_ops.py:1165: sparse_to_dense (from tensorflow.python.ops.sparse_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Create a `tf.sparse.SparseTensor` and use `tf.sparse.to_dense` instead.
  • 运行 inputs 张量会将 features 解析为一批向量。

  • 特征列和层一样具有内部状态,因此通常需要将它们初始化。

  • 类别列会在内部使用对照表,而这些表需要单独的初始化操作 tf.tables_initializer。

var_init = tf.global_variables_initializer()
table_init = tf.tables_initializer()
sess = tf.Session()
sess.run((var_init, table_init))
(None, None)

初始化内部状态后,您可以运行 inputs(像运行任何其他 tf.Tensor 一样):

print(sess.run(inputs))
[[ 1.  0.  5.]
 [ 1.  0. 10.]
 [ 0.  1.  8.]
 [ 0.  1.  9.]]

训练

定义数据

我们首先来定义一些输入值 x,以及每个输入值的预期输出值 y_true:

x = tf.constant([[1], [2], [3], [4]], dtype=tf.float32)
y_true = tf.constant([[0], [-1], [-2], [-3]], dtype=tf.float32)

定义模型

接下来,建立一个简单的线性模型,其输出值只有 1 个:

linear_model = tf.layers.Dense(units=1)
y_pred = linear_model(x)

您可以如下评估预测值:
该模型尚未接受训练,因此四个“预测”值并不理想。以下是我们得到的结果,您自己的输出应该有所不同:

sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init)

print(sess.run(y_pred))
[[-0.84013945]
 [-1.6802789 ]
 [-2.5204184 ]
 [-3.3605578 ]]

损失

要优化模型,您首先需要定义损失。我们将使用均方误差,这是回归问题的标准损失。

虽然您可以使用较低级别的数学运算手动定义,但 tf.losses 模块提供了一系列常用的损失函数。您可以使用它来计算均方误差,具体操作如下所示:

这会生成如下所示的一个损失值:

loss = tf.losses.mean_squared_error(labels=y_true, predictions=y_pred)

print(sess.run(loss))
0.3923627

训练

TensorFlow 提供了执行标准优化算法的优化器。这些优化器被实现为 tf.train.Optimizer 的子类。它们会逐渐改变每个变量,以便将损失最小化。最简单的优化算法是梯度下降法,由 tf.train.GradientDescentOptimizer 实现。它会根据损失相对于变量的导数大小来修改各个变量。例如:

optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)

该代码构建了优化所需的所有图组件,并返回一个训练指令。该训练指令在运行时会更新图中的变量。您可以按以下方式运行该指令:

for i in range(100):
  _, loss_value = sess.run((train, loss))
  print(loss_value,end='\t')
0.04468648	0.0444193	0.044153724	0.043889742	0.043627325	0.043366484	0.043107204	0.04284948	0.042593285	0.04233863	0.04208549	0.04183387	0.04158375	0.041335132	0.041087985	0.040842313	0.040598135	0.0403554	0.040114112	0.039874278	0.039635878	0.039398905	0.03916335	0.03892919	0.038696434	0.03846509	0.038235113	0.038006507	0.03777927	0.037553407	0.03732889	0.037105694	0.03688383	0.036663312	0.03644412	0.03622622	0.036009625	0.03579434	0.035580322	0.03536761	0.03515614	0.03494596	0.034737006	0.03452932	0.034322884	0.03411767	0.033913698	0.033710927	0.03350938	0.03330902	0.03310989	0.032911927	0.032715127	0.03251954	0.03232511	0.03213185	0.03193974	0.03174877	0.03155895	0.03137027	0.031182703	0.030996269	0.030810954	0.030626725	0.030443627	0.030261602	0.030080667	0.029900838	0.02972206	0.029544342	0.029367713	0.029192118	0.029017597	0.028844098	0.028671645	0.028500209	0.028329818	0.028160451	0.027992088	0.027824726	0.027658356	0.027492985	0.027328618	0.027165223	0.027002795	0.02684136	0.026680876	0.026521355	0.02636279	0.02620517	0.026048483	0.025892742	0.025737938	0.02558405	0.025431097	0.025279043	0.02512792	0.024977684	0.024828348	0.0246799	

完成程序

x = tf.constant([[1], [2], [3], [4]], dtype=tf.float32)
y_true = tf.constant([[0], [-1], [-2], [-3]], dtype=tf.float32)

linear_model = tf.layers.Dense(units=1)

y_pred = linear_model(x)
loss = tf.losses.mean_squared_error(labels=y_true, predictions=y_pred)

optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)

init = tf.global_variables_initializer()

sess = tf.Session()
sess.run(init)
for i in range(100):
  _, loss_value = sess.run((train, loss))
  print(loss_value,end='\t')

print(sess.run(y_pred),end='\t')
0.5981666	0.47255915	0.385059	0.32400262	0.28129727	0.25132734	0.23019612	0.21519992	0.20446277	0.19668277	0.19095673	0.18665773	0.18335101	0.18073465	0.17859936	0.17679964	0.17523474	0.17383467	0.17255087	0.17134953	0.17020734	0.169108	0.16804026	0.1669962	0.16597047	0.16495922	0.16395985	0.16297045	0.16198973	0.16101682	0.16005109	0.15909204	0.15813944	0.15719289	0.15625237	0.15531768	0.15438873	0.15346542	0.15254769	0.15163554	0.15072885	0.14982761	0.14893177	0.1480413	0.1471562	0.14627635	0.14540175	0.14453241	0.14366826	0.14280929	0.14195548	0.14110675	0.14026311	0.13942447	0.13859089	0.13776228	0.13693857	0.13611987	0.135306	0.13449708	0.13369294	0.13289359	0.13209906	0.13130924	0.13052416	0.12974378	0.12896806	0.12819698	0.12743048	0.12666862	0.1259113	0.1251585	0.12441017	0.123666346	0.12292698	0.12219201	0.121461436	0.12073524	0.1200134	0.11929583	0.11858258	0.11787361	0.11716886	0.11646833	0.115771964	0.115079775	0.114391744	0.113707796	0.11302799	0.11235219	0.11168049	0.111012734	0.110349014	0.10968924	0.109033436	0.10838154	0.10773354	0.107089445	0.10644916	0.105812706	[[-0.5236681]
 [-1.253753 ]
 [-1.9838377]
 [-2.7139227]]	

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值