CS 20SI|Lecture 2 TensorFlow Ops

本文详细介绍了TensorFlow的基本操作,包括常数、数学运算、归约、数据类型和变量的创建与使用。此外,还讲解了如何利用TensorBoard进行可视化,并强调了在TensorFlow中正确管理变量和数据类型的重要性。
摘要由CSDN通过智能技术生成

Agenda

  • Basic operations
  • Tensor types
  • Project speed dating
  • Placeholders and feeding inputs
  • Lazy loading

Using TensorBoard

使用TensorBoard的5个步骤

#1. 定义需要记录的tensor
w2_hist = tf.summary.histogram("weights2",W2)
cost_sum = tf.summary.scalar("cost",cost)
#2. 合并所有记录
summary = tf.summary.merge_all()
#3. 创建writer并添加图
wirter = tf.summary.FileWriter('./logs')
writer.add_graph(sess.graph)
#4. 运行汇总op,添加结果
s,_ = sess.run([summary,optimizer],feed_dict=feed_dict)
writer.add_summary(s,global_step=global_step)

本地启动

tensorboard --logdir=./logs

远端启动

ssh -L local_port:127.0.0.1:remote_port username@server.com

local> $ ssh -L 7007:121.0.0.0:6006 test@server.com
server> $ tensorboard -logdir=./logs

在构建完计算图之后开始训练之前加入以下代码,
writer ​=​ tf​.​summary​.​FileWriter​(​logs_dir​,​ sess​.​graph)

import tensorflow as tf
a = tf.constant(2)
b = tf.constant(3)
x = tf.add(a, b)
with tf.Session() as sess:
    # add this line to use TensorBoard. 
    # Create the summary writer after graph definition and before running your session
    writer = tf.summary.FileWriter('./graphs', sess.graph) # Where you want to keep your event files
    print(sess.run(x))
writer.close() # close the writer when you’re done using it

在当前目录下打开终端控制台中输入

$ python [filename].py
$ tensorboard --logdir="./graphs" --port 6006

打开浏览器 http://localhost:6006/查看tensorboard
这里写图片描述
显式命名变量

import tensorflow as tf
a = tf.constant(2, name="a")
b = tf.constant(3, name="b")
x = tf.add(a, b, name="add")
writer = tf.summary.FileWriter("./graphs", sess.graph)
with tf.Session() as sess:
print sess.run(x) # >> 5

常数 More constants


tf.constant(value, dtype=None, shape=None, name='Const', verify_shape=False)

类似numpy.array创建多维数组一样

# constant of 1d tensor (vector) 
a ​=​ tf​.​constant​([​2​,​ ​2​],​ name​=​"vector") 
# constant of 2x2 tensor (matrix) 
b ​=​ tf​.​constant​([[​0​,​ ​1​],​ ​[​2​,​ ​3​]],​ name​=​"b") 

Tensors filled with a specific value

类似于numpy.zeros,numpy.zeros_like,numpy.ones,numpy.ones_like创建特定值的tensor

tf​.​zeros​(​shape​,​ dtype​=​tf​.​float32​,​ name​=​None) 
tf​.​zeros_like​(​input_tensor​,​ dtype​=​None​,​ name​=​None​,​ optimize​=​True)
tf​.​ones​(​shape​,​ dtype​=​tf​.​float32​,​ name​=​None) 
tf​.​ones_like​(​input_tensor​,​ dtype​=​None​,​ name​=​None​,​ optimize​=​True) 
tf​.​fill​(​dims​,​ value​,​ name​=​None​)

Constants as sequences

tf​.​linspace​(​start​,​ stop​,​ num​,​ name​=​None)
创建一个区间范围为[start,stop]间隔为(stop-start)/(num -1)的数字序列
tf​.​range​(​start​,​ limit​=​None​,​ delta​=​1​,​ dtype​=​None​,​ name​=​'range')
创建一个区间范围为[start,limit)间隔为delta的数字序列
与numpy序列不同的是,tensorflow的序列是不可迭代对象

for​ _ ​in​ np​.​linspace​(​0​,​ ​10​,​ ​4​):​ ​# OK 
for​ _ ​in​ tf​.​linspace​(​0​,​ ​10​,​ ​4​):​ ​# TypeError("'Tensor' object is not iterable.") 
for​ _ ​in​ range​(​4​):​ ​# OK 
for​ _ ​in​ tf​.​range​(​4​):​ ​# TypeError("'Tensor' object is not iterable.")  

Randomly Generated Constants

设置随机数种子tf.set_random_seed(seed)

tf.random_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None) 
tf.truncated_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None) tf.random_uniform(shape, minval=0, maxval=None, dtype=tf.float32, seed=None, name=None) 
tf.random_shuffle(value, seed=None, name=None) 
tf.random_crop(value, size, seed=None, name=None)
tf.multinomial(logits, num_samples, seed=None, name=None)
tf.random_gamma(shape, alpha, beta=None, dtype=tf.float32, seed=None, name=None) 

数学运算 Math Operations

TensorFlow 数学运算类似于Numpy的操作。官方API链接文档 https://www.tensorflow.org/api_guides/python/math_ops#Arithmetic_Operators

图片来自于Fundamental of Deep Learning
这里写图片描述

归约 Reduction

规约可对k维的张量的指定维度进行操作从而达到降维的目的。
https://www.tensorflow.org/api_guides/python/math_ops#Reduction
以最常用的tf.reduce_sum为例,其API如下

reduce_sum(
    input_tensor,
    axis=None,
    keep_dims=False,
    name=None,
    reduction_indices=None
)

官网给了如下例子

# 'x' is [[1, 1, 1]
#         [1, 1, 1]]
tf.reduce_sum(x) ==> 6
tf.reduce_sum(x, 0) ==> [2, 2, 2]
tf.reduce_sum(x, 1) ==> [3, 3]
tf.reduce_sum(x, 1, keep_dims=True) ==> [[3], [3]]
tf.reduce_sum(x, [0, 1]) ==> 6

简单来说,当axis=None时,操作会沿着所有维度进行。
axis=0时,操作沿着0轴进行,对于2维的张量,竖直方向为0轴,水平方向为1轴。
keep_dims=True,返回的维度和原来保持一致(通常归约操作是导致维度减少的)。
axis=[0,1]时,表明规约操作沿着多个轴进行。
对于k维的张量,我们只要记住最里面那一层的元素所在维度为k-1,相应地,往外的维度继续减1.
现在考虑一个三维3*2*2的张量,对应k=3,现在对他进行一些规约操作

a = [[[ 1,  2],
        [ 3,  4]],

       [[ 5,  6],
        [ 7,  8]],

       [[ 9, 10],
        [11, 12]]]
tf.reduce_sum(x,2,keep_dims=True)#这里axis=k-1,那么是对最里面一层的元素进行规约操作,最里面一层的维度对应的长度应该变为1,也就是说结果应该是一个3*2*1的张量ans_1,如果不保持维度的话,就会变成3*2的张量ans_2
ans_1 =[[ [3],  [7]],
       [[11], [15]],
       [[19], [23]]]
ans_2 = [[ 3,  7],
       [11, 15],
       [19, 23]]
tf.reduce_sum(x, 2) #axis=k-2,那么是对倒数第二层的元素进行规约求和,分别对应于1+3,2+4,6+7...结果如下
ans = [[ 4,  6],
       [12, 14],
       [20, 22]]
tf.reduce_sum(x, 0) #axis = k-3,这是对倒数第三层元素进行求和,分别对应于1+5+9,2+6+10,。。。结果如下
ans = [[15, 18],
       [21, 24]]

最后,对于k维的形状为(k1,k2,ki,…,kn)的张量,若规约操作沿着ki进行,那么得到结果形状为(k1,k2,1,…,kn),将长度为1的维度删去就达到了规约降低张量维度的目的。

数据类型 Data Types

下图是TensorFlow的数据类型
这里写图片描述

重要说明

  1. TF的数据类型和Numpy之间是可以相互转换的,如tf.int32 == np.int32该表达式的值为True
  2. 当执行tf.Session.run(fetchs)时,如果请求的fetches是tensor,那么该函数的返回值将是一个Numpy的ndarray
  3. 尽量不要使用Python原生类型的数据,如Python的整数类型只有int而TF分为tf.int8,tf.int16,tf.int32等,对于原生类型的Python数据结构,TF需要进行类型推断,影响效率
  4. 虽然Numpy数组和TF的tensor之间可以相互转换,但是Numpy并不提供创建tensor的函数,也不支持自动求导和GPU计算。所以尽量使用TensorFlow的数据类型
  5. TensorFlow的constants数存储在图定义中的,这意味着当constants很大的时,每次加载计算图都会很慢,也会消耗大量的内存。
    Print out the graph def
import tensorflow as tf
my_const = tf.constant([1.0, 2.0], name="my_const")
with tf.Session() as sess:
print sess.graph.as_graph_def()
# you will see value of my_const stored in the graph’s definition

只有对于基本类型使用constants,对于需要大量内存的数据尽量使用Variablereaders

变量 Variables

使用tf.Variable(initial_value=None, validate_shape=True, name=None, dtype=None, )创建变量
注意不是tf.variable因为tf.Varible是一个类,而之前的tf.constant是一个op。
tf.Variable包含了若干ops:

x = tf.Variable(...)  
x.initializer # init  x.value() # read op  x.assign(...) # write op  x.assign_add(...)  
# and more 

变量初始化

声明好变量后,在使用之前需要对变量进行初始化操作
1.全局变量初始化 tf.global_variables_initializer()

init ​=​ tf​.​global_variables_initializer​() 
with​ tf​.​Session​()​ ​as​ sess: 
    tf​.​run​(​init)

2.初始化指定变量 tf.variables_initializer()

init_ab ​=​ tf​.​variables_initializer​([​a​,​ b​],​ name​=​"init_ab") 
with​ tf​.​Session​()​ ​as​ sess: 
    tf​.​run​(​init_ab)

3.变量单独初始化tf.Variable.initializer

# create variable W as 784 x 10 tensor, filled with zeros W ​=​ tf​.​Variable​(​tf​.​zeros​([​784​,​10​])) with​ tf​.​Session​()​ ​as​ sess: tf​.​run​(​W​.​initializer) 

4.restore from a save file

变量求值

变量初始化后,直接进行print会得到如下的结果

W ​=​ tf.Variable(tf.ones([2,2],)) 
with​ tf​.​Session​()​ ​as​ sess: 
    sess​.​run​(​W​.​initializer) 
    print​(W) 
>>​ ​Tensor​(​"Variable/read:0"​,​ shape=(2, 2), dtype=float32) 

要想获得变量的值,对变量调用eval()函数

W ​=​ tf.Variable(tf.ones([2,2],))  
with​ tf​.​Session​()​ ​as​ sess: 
    sess​.​run​(​W​.​initializer) 
    print​(W​.​eval​())
>> [[ 1.  1.]
 [ 1.  1.]] 

变量赋值

使用tf.Variable.assign()函数为变量赋值。

W ​=​ tf​.​Variable​(​10​) 
W​.​assign​(​100​) 
with​ tf​.​Session​()​ ​as​ sess: 
    sess​.​run​(​W​.​initializer) 
    print​ (W​.​eval​())
>> 10 

上面这段代码并不会输入我们赋值的变量10,这是为什么呢?
注意到,在Lecture1中提到过,所有的op都要在Session中被执行,而上面我们虽然声明了一个assignop,但是该op并没有被真正的执行,所以变量的值仍然是10。做如下的修改:

W ​=​ tf​.​Variable​(​10​) 
assign_op = W​.​assign​(​100​) 
with​ tf​.​Session​()​ ​as​ sess: 
    sess​.​run​(​assign_op) 
    print​ (W​.​eval​()) 
>> 100 

注意到,上述代码中并没有执行初始化的op,这是因为assignop进行了初始化的操作,事实上,initializer op执行的操作就是将初始值assign给变量。

assign_add和assign_sub

使用tf.Variable.assign_add()tf.Variable.assign_sub()可以对变量进行增加或减少指定数值,但是需要进行初始化。

W = tf.Variable(10) 
with tf.Session() as sess:     
    sess.run(W.initializer) 
    print (sess.run(W.assign_add(10))) # >> 20 
    print (sess.run(W.assign_sub(2))) # >> 18 

不同的Session会维护同一个变量的不同副本

W = tf.Variable(10) 
sess1 = tf.Session() 
sess2 = tf.Session() 
sess1.run(W.initializer) 
sess2.run(W.initializer) 

print (sess1.run(W.assign_add(10))) # >> 20 
print (sess2.run(W.assign_sub(2))) # >> 8 

print (sess1.run(W.assign_add(100))) # >> 120 print (sess2.run(W.assign_sub(50))) # >> -42 

sess1.close() 
sess2.close()

交互式会话 InteractiveSession

使用InteractiveSession代替SessionInteractiveSession将自身设置为默认的Session,这样就可以直接调用run()eval()等方法而不需要显式地指定一个Session。这在交互式编程环境中用起来会很方便,但是如果你有多个Session需要运行的话,就不太方便了。

sess ​=​ tf​.​InteractiveSession​() 
a ​=​ tf​.​constant​(​5.0) 
b ​=​ tf​.​constant​(​6.0) 
c ​=​ a ​*​ b # We can just use 'c.eval()' without passing 'sess' 
print​(​c​.​eval​()) 
sess​.​close​() 

tf.InteractiveSession.close()会关闭一个 InteractiveSession.

tf.get_default_session() 返回当前线程的默认session。返回的session将称为SessionSession.as_default()上下文进入的session

控制依赖性 Control Dependencies

当我们有若干个互相独立的op a,b,c,d时,若想要让ab先执行,de后执行,可以使用tf.Graph.control_dependencies(control_inputs)方法

 # your graph g have 5 ops: a, b, c, d, 
with​ g​.​control_dependencies​([​a​,​ b​,​​]):   ​# `c` and `d` will only run after `a`, `b` have executed.   
c ​=​ ​...   
d ​=​ … 

占位符 Placeholders and feed_dict

事实上,我们可以先定义出计算图的结构,而不具体提供需要的数据,等到需要真正执行计算的时候,再将数据传入。可以先定义一个承载数据的占位符
tf​.​placeholder​(​dtype​,​ shape​=​None​,​ name​=​None)
我们需要指定数据类型dtype,对于shape来说,尽量清晰的指定出来,这在之后的debug中会比较方便。
在需要真实数据进行计算时,将数据作feed_dict的参数传递到sess.run()方法中。
我们还可以喂给非placeholdertensor数据,只要tensorfeedable的。通过tf.Graph.is_feedable(tensor)检查tensor的该性质。
在测试模型时,feed_dict会很方便,我们可以直接向某个中间步喂给数据,而不需要进行所有的的计算。

The trap of lazy loading

大概的意思是尽量在session外就定义好各种需要的op,不要在run中再写op,否则有可能造成计算图消耗不必要的资源。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值