Tensorflow之底层操作

1、张量值

TF的核心数据单位是张量,张量由一组形成阵列的原始数据组成,张量的阶是它的维数,而它的维数是一哥整数元组,指定了阵列的每个维度的长度:

2、TF的低级API可以由两部分独立组成

    (1) 构建计算图(tf.Graph)

    (2) 运算计算图(tf.Session)

    (1) Graph

        计算图是排列成一个图的一系列TF指令,图由两种类型的对象组成

    •      指令:图的节点。指令说明的是消耗和生成张量的计算。
    •      张量:图的边。它们代表将流经图的值。大多数会返回tf.Tensor

最基本的指令是一个常量。构建指令的Python函数将一个张量值作为输入值。生成的指令不需要输入值。它在运行时输出的是被传递给构造函数的值。我们创建两个浮点数常量a和b:

a = tf.constant(3.0,dtype = tf.float32)
b = tf.constant(4.0)
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)

图中每个张量都拥有唯一的名称。这个名称不同于使用的Python分配给对应的对象的名称。张量是根据生成它们的指令命名的,后面跟着输出索引。

Tensorboard

Tensorboard能够使计算图可视化。其过程如下:

(1)将计算图保存为Tnesorboard摘要文件,具体操作如下:

writer = tf.summary.FileWriter('.')
writer.add_graph(tf.get_default_graph())

这将在当前目录中生成一个event文件,其名称格式如下

events.out.tfevents.{timestamp}.{hostname}

在终端使用shell命令,启动TensorBoard

tensorboard --logdir

接下来在浏览器打开TnesorBoard的图页面,你应该看到计算图如下所示:


会话

要评估张量,需要实例化一个tf.Session对象(会话)。会话会封装TensorFlow运行时的状态,并运行TF指令。如果tf.Graph像一个.py文件,那么tf.Session就像一个可执行的python

以下创建一个tf.Session对象,然后调用其run方法来评估我们在上文中创建的total张量:

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

当使用Session.run请求输出节点时,TF会回溯整个图,并流经提供了所请求的输出节点对应的输入值的所有节点,因此指令会打印出预期值。

也可以将多个张量传递给tf.Session.run。run方法以透明方式处理元组或字典的任何组合,如下例

print (sess.run('ab':(a,b),'total':total))

它返回的结果有相同的布局:

{‘total’:7.0,'ab':(3.0,4.0)}

供给

上面的图只能产生一个常量的结果,图可以参数化以便接收外部输入,也称为占位符。占位符表示承诺在稍后提供值,它就行函数参数:

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

注意,feed_dict参数可以用于覆盖图中的任何张量。占位符和其他tf.Tensors的唯一不同之处在于如果没有提供值给他们,那么占位符会显示错误。

数据集

占位符适用于简单实验,但数据集是将数据流形式传递到模型的首选方法。

要从数据集中获取可运行的tf.Tensor,必须现将其转换成tf.data.Iterater,然后调用迭代器的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)
next_item = slices.make_one_shot_iterator().get_next()

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

while True:
  try:
    print(sess.run(next_item))
  except tf.errors.OutOfRangeError:
   break

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

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

创建层

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

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

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

在定义完图后,还有一个细节需要处理(初始化)

初始化层

层包含的变量必须先初始化,然后才能使用。如下所示:

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

此global_variables_initializer仅会初始化创建初始化程序是图中就存在的变量。因此应该在构建图标的最后一步添加初始化程序。

执行层

我们现在已经完成了层的初始化,可以像处理任何其他张量一样评估linear_model的输出张量了。例如:

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

会生成一个两元素向量,如下所示:

[[-3.413478999]
 [-9.149999908]]

层函数的快捷方式

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

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


print (sess.run(y,{x:[[1,2,3],[4,5,6]]}))
尽管这种方法很方便,但无法访问  tf.layers.Layer  对象。这会让自省和调试变得更加困难,并且无法重复使用相应的层。

特征列

使用特征列进行试验的最简单方式是使用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)

运行inputs张量会将features解析为一批向量

特征列和层一样具有内部状态,因此通常需要将他们初始化。分类列会在内部使用对照表,而这些表需要单独的初始化指令tf.tables_initializer

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

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

print (sess.run(inputs))

这显示了特征列如何打包输入矢量,在这个过程中,独热“部门”被用作第一和第二索引,“销售”用作第三个。

[[  1.   0.   5.]
 [  1.   0.  10.]
 [  0.   1.   8.]
 [  0.   1.   9.]]

训练

1、定义数据

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

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

2、定义模型

接下来,定义一个简单的线性模型,其输出值只1个

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

可以如下评估预测值:

sess=  tf.Session()
init = tf.global_variables_initializers()
sess.run()
print (sess.run(y_pred))

模型尚未接受训练,预测值并不理想

3、损失

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

tf.losses提供了一系列常用损失函数,可以使用它来计算均方误差

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

print (sess.run(loss))

将会生成一个损失

4、训练

TF也提供了优化器啦执行标准的优化算法,这些优化器被用作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)

由于train是一个指令而不是张量,因此在她运行时不会返回一个值。为了查看训练期间损失的进展,我们会同时运行损失张量,生如下损失值:

1.35659
1.00412
0.759167
0.588829
0.470264
0.387626
0.329918
0.289511
0.261112
0.241046

完整程序

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)

print(sess.run(y_pred))
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值