TensorFlow入门 学习总结

junliang 20190301

说明:以下所有代码使用版本TensorFlow1.4.0或1.12.0版本

import tensorflow as tf
print(tf.__version__)
1.12.0

3.TensorFlow入门

3.1TensorFlow计算模型–计算图

TensorFlow是一个通过计算图的形式来表述计算的编程系统,每一个计算都是计算图上的一个节点,而节点之间的边描述了计算之间的依赖关系。

Tensor代表张量,可以简单理解为多维数组,Tensor表明了它的数据结构。
Flow则体现了它的计算模型,表达了张量之间通过计算相互转化的过程。

TensorFlow程序一般可以分为两个阶段,第一个阶段需要定义计算图中所有的计算,第二个阶段为执行计算。

a = tf.constant([1.0, 2.0], name='a')
b = tf.constant([2.0, 3.0], name='b')
result = a + b

系统维护一个默认的计算图,通过tf.get_default_graph函数可以获取当前默认的计算图。

# 通过a.graph可以查看张量所属的计算图。因为没有特意指定,所以这个计算图应该等于当前默认的计算图。
print(a.graph is tf.get_default_graph())
True

通过tf.Graph()可以生成新的计算图,不同计算图上的张量和运算都不会共享。

1.4.0版本代码

g1 = tf.Graph()
with g1.as_default():
    v = tf.get_variable("v", initializer=tf.zeros_initializer(shape=[1]))
    
g2 = tf.Graph()
with g2.as_default():
    v = tf.get_variable("v", initializer=tf.ones_initializer(shape=[1]))
    
# 在计算图g1中读取变量v的取值
with tf.Session(graph=g1) as sess:
    tf.global_variable_initilizer().run()
    with tf.variable_scope("", reuse=True):
        # 在计算图g1中,变量v的取值应该为0,所以下面这行会输出[0.]
        print('g1 v='.format(sess.run(tf.get_variable("v"))))
    
# 在计算图g1中读取变量v的取值
with tf.Session(graph=g2) as sess:
    tf.global_variable_initilizer().run()
    with tf.variable_scope("", reuse=True):
        # 在计算图g2中,变量v的取值应该为0,所以下面这行会输出[0.]
        print('g2 v='.format(sess.run(tf.get_variable("v"))))
        

1.12.0版本代码

g1 = tf.Graph()
with g1.as_default():
    v = tf.get_variable("v", initializer=tf.zeros_initializer(), shape=[1])
    
g2 = tf.Graph()
with g2.as_default():
    v = tf.get_variable("v", initializer=tf.ones_initializer(), shape=[1])
    
# 在计算图g1中读取变量v的取值
with tf.Session(graph=g1) as sess:
    tf.global_variables_initializer().run()
    with tf.variable_scope("", reuse=True):
        # 在计算图g1中,变量v的取值应该为0,所以下面这行会输出[0.]
        print(sess.run(tf.get_variable("v", [1])))
    
# 在计算图g1中读取变量v的取值
with tf.Session(graph=g2) as sess:
    tf.global_variables_initializer().run()
    with tf.variable_scope("", reuse=True):
        # 在计算图g2中,变量v的取值应该为0,所以下面这行会输出[0.]
        print(sess.run(tf.get_variable("v")))
        
[0.]
[1.]

TensorFlow中的计算图不仅仅可以用来隔离张量和计算,它还提供了管理张量和计算的机制。
通过tf.Graph.device()来指定运行计算的设备,可以指定使用GPU运行。

g = tf.Graph()
with g.device('/gpu:0'):
    result = a + b
    print(result)
    
Tensor("add_2:0", shape=(2,), dtype=float32)

在一个计算图中,可以通过集合(collection)来管理不同类别的资源。
通过tf.add_to_collect()可以将资源加入一个或多个集合中,然后通过tf.get_collect()获取一个集合里面的所有资源(张量、变量、运行程序所需要的队列资源等)。

集合名词集合内容使用场景
tf.GraphKeys.VARIABLES所有变量持久化TensorFlow模型
tf.GraphKeys.TRAINABLE_VARIABLES可学习的变量(一般指神经网络中的参数)模型训练、生成模型可视化内容
tf.GraphKeys.SUMMARIES日志生成相关的张量TensorFlow计算可视化
tf.GraphKeys.QUEUE_RUNNERS处理输入的QueueRunner处理输入
tf.GraphKeys.MOVING_AVERAGE_VARIABLES所有计算了滑动平均值的变量计算变量的滑动平均值

3.2 TensorFlow数据模型–张量

张量是TensorFlow管理数据的形式

TensorFlow中,所有的数据都通过张量的形式来表示。

  • 张量可以被简单理解为多维数组。零阶张量表示标量,也就是一个数;一阶张量为向量,也就是一个一维数组;n阶张量可以理解为n维数组。
  • 张量中并没有真正保存数字,它保存的是如何得到这些数字的计算过程。
  • 张量主要保存了三个属性:
    • 名字(name):张量的唯一标识符,也给出了张量是如何计算出来的。张量命名通过”node:src_output“形式给出,node为结点名称,src_output表示当前张量来自节点的第几个输出。
    • 维度(shape):维度信息
    • 类型(type):每个张量会有一个唯一的类型,如果参与运算的所有张量类型不匹配时会报错。共14种不同的类型:
      • 实数:tf.float32, tf.float64
      • 整数:tf.int8, tf.int16, tf.int32, tf.int64, tf.unit8
      • 布尔型:tf.bool
      • 复数:tf.complex64, tf.complex128
print(result)
Tensor("add_2:0", shape=(2,), dtype=float32)

张量的使用主要有两类:

* 对中间计算结果引用。
# 使用张量a和b记录中间结果来进行计算,增加代码可读性
result = a + b
* 当计算图构造完成之后,张量可以用来获得计算结果,也就是得到真实的数字。

3.3 TensorFlow运算模型–会话

会话拥有并管理TensorFlow程序运行时的所有资源,所有计算完成之后需要关闭会话来帮助系统回收资源,否则可能出现资源泄露的问题。

使用会话的第一种模型:需要明确调用会话生成函数和关闭函数。

当程序因为异常退出时,关闭会话的函数可能就不会被执行从而导致资源泄露。

sess = tf.Session()

a33 = tf.constant([1.0, 2.0], name='a')
b33 = tf.constant([2.0, 3.0], name='b')
result33 = a33 + b33
print(sess.run(result33))

sess.close()

[3. 5.]
第二种模型:为了解决异常退出时资源释放的问题,可以通过python的上下文管理器来使用会话。
with tf.Session() as sess:

    a33 = tf.constant([1.0, 2.0], name='a')
    b33 = tf.constant([2.0, 3.0], name='b')
    result33 = a33 + b33
    print(sess.run(result33))


[3. 5.]
TensorFlow不会自动生成默认会话,而是需要手动指定。当默认的会话被指定后可以通过tf.Tensor.eval()来计算一个张量的取值。

通过设定默认会话计算张量的取值:

sess = tf.Session()
with sess.as_default():
    print(result.eval())
    
[3. 5.]
sess = tf.Session()
print(sess.run(result))
print(result.eval(session=sess))

[3. 5.]
[3. 5.]
在交互式环境(python脚本或jupyter)下直接构建默认会话使用tf.InteractiveSession
sses = tf.InteractiveSession()
print(result.eval())
sess.close()
[3. 5.]
通过ConfigProto可以配置类似并行的线程数、GPU分配策略、运算时间等参数。

allow_soft_placement=True时,以下任意一个条件成立时,GPU上的运算可以放到CPU上进行:

  • 运算无法在GPU上运算
  • 没有GPU资源,或者指定的第n个GPU不存在
  • 运算输入包含对CPU计算结果的引用

log_device_placement=True时,日志中将会记录每个节点被安排在哪个设备上以方便调试。为False时将减少日志量。

config = tf.ConfigProto(allow_soft_placement=True, log_device_placement=True)
sess1 = tf.InteractiveSession(config=config)
sess2 = tf.Session(config=config)
print(sess1 is sess2)
False


/Users/jliang/anaconda3/envs/py36/lib/python3.6/site-packages/tensorflow/python/client/session.py:1702: UserWarning: An interactive session is already active. This can cause out-of-memory errors in some cases. You must explicitly call `InteractiveSession.close()` to release resources held by the other session(s).
  warnings.warn('An interactive session is already active. This can '

3.4 TensorFlow实现神经网络

计算神经网络的前向传播结果需要三部分信息:

  • 神经网络的输入:从实体中提取的特征向量
  • 神经网络的连接结构:神经网络的结构给出不同神经元之间输入输出的连接关系,TensorFlow的节点指代神经元。
  • 每个神经元中的参数:权重值

神经网络参数与TensorFlow变量

变量tf.Variable的作用就是保持和更新神经网络中的参数,需要指定初始值。

weights = tf.Variable(tf.random_normal([2, 3], stddev=2))
print(weights)
<tf.Variable 'Variable:0' shape=(2, 3) dtype=float32_ref>
TensorFlow随机数生成函数
函数名称随机数分布主要参数
tf.random_normal正态分布平均值、标准差、取值类型
tf.truncated_normal正态分布,如果随机出来的值偏离平均值超过2个标准差,那么这个数将会被重新随机平均值、标准差、取值类型
tf.random_uniform均匀分布最小值、最大值、取值类型
tf.random_gammaGamma分布形状参数alpha、尺度参数beta、取值类型
TensorFlow常数生成函数
函数名称功能样例
tf.zeros产生全0的数组tf.zeros([2,3], int32)
tf.ones产生全1的数组tf.ones([2,3], int32)
tf.fill产生一个全部为给定数字的数组tf.fill([2,3],9)
tf.constant产生一个给定值的常量tf.constant([1,2,3])
print(tf.zeros([2,3], tf.int32))
print(tf.ones([2,3], tf.int32))
print(tf.fill([2,3],9))
print(tf.constant([1,2,3]))
Tensor("zeros_1:0", shape=(2, 3), dtype=int32)
Tensor("ones:0", shape=(2, 3), dtype=int32)
Tensor("Fill:0", shape=(2, 3), dtype=int32)
Tensor("Const:0", shape=(3,), dtype=int32)
biases = tf.Variable(tf.zeros([3]))
print(biases) 
<tf.Variable 'Variable_1:0' shape=(3,) dtype=float32_ref>
w2 = tf.Variable(weights.initialized_value())
w3 = tf.Variable(weights.initialized_value()*2.0)
print(w2)
print(w3)
<tf.Variable 'Variable_4:0' shape=(2, 3) dtype=float32_ref>
<tf.Variable 'Variable_5:0' shape=(2, 3) dtype=float32_ref>
Tensorflow程序

第一步是定义TensorFlow计算图中所有的计算,但这些被定义的计算在这一步并不真正地运行。
第二步会声明一个会话,并通过会话计算结果。在计算真实结果前需要将所有用到的变量初始化,即可以逐一调用每个变量的initializer初始化,也可以通过tf.global_variables_initializer()实现所有变量的初始化。

with tf.Session() as sess:
    sess.run(weights.initializer)
    sess.run(w2.initializer)
    sess.run(w3.initializer)
    #...
    # 或者
    sess.run(tf.global_variables_initializer())
    

变量与张量的关系:变量的声明函数tf.Variable是一个运算,输出结果就是一个张量,所以变量只是一种特殊的张量。

TensorFlow中集合collection的概念
  • 所有的变量都会被自动地加入到GraphKeys.VARIABLES这个集合中。
  • 通过tf.global_variables()可以获取到当前计算图上所有的变量(有助于持久化整个计算图的运行状态)。
  • 通过变量声明函数中的trainable参数来区分需要优化的参数(神经网络中的参数)和其他参数
    • trainable=True时,这个变量将会被加入到GraphKeys.TRAINABLE_VARIABLES集合
    • 可以通过tf.trainable_variables函数得到所有需要优化的参数
print(tf.global_variables())
print(tf.trainable_variables())
[<tf.Variable 'Variable:0' shape=(2, 3) dtype=float32_ref>, <tf.Variable 'Variable_1:0' shape=(3,) dtype=float32_ref>, <tf.Variable 'Variable_2:0' shape=(2, 3) dtype=float32_ref>, <tf.Variable 'Variable_3:0' shape=(2, 3) dtype=float32_ref>, <tf.Variable 'Variable_4:0' shape=(2, 3) dtype=float32_ref>, <tf.Variable 'Variable_5:0' shape=(2, 3) dtype=float32_ref>]
[<tf.Variable 'Variable:0' shape=(2, 3) dtype=float32_ref>, <tf.Variable 'Variable_1:0' shape=(3,) dtype=float32_ref>, <tf.Variable 'Variable_2:0' shape=(2, 3) dtype=float32_ref>, <tf.Variable 'Variable_3:0' shape=(2, 3) dtype=float32_ref>, <tf.Variable 'Variable_4:0' shape=(2, 3) dtype=float32_ref>, <tf.Variable 'Variable_5:0' shape=(2, 3) dtype=float32_ref>]
变量在构建后,它的类型就不能再改变了
w1 = tf.Variable(tf.random_normal([2,3], stddev=1), name='w1')
w2 = tf.Variable(tf.random_normal([2,3], dtype=tf.float64, stddev=1), name='w2')

w1.assign(w2)
# 此处会运行错误
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

~/anaconda3/envs/py36/lib/python3.6/site-packages/tensorflow/python/framework/op_def_library.py in _apply_op_helper(self, op_type_name, name, **keywords)
    509                 as_ref=input_arg.is_ref,
--> 510                 preferred_dtype=default_dtype)
    511           except TypeError as err:


~/anaconda3/envs/py36/lib/python3.6/site-packages/tensorflow/python/framework/ops.py in internal_convert_to_tensor(value, dtype, name, as_ref, preferred_dtype, ctx)
   1145     if ret is None:
-> 1146       ret = conversion_func(value, dtype=dtype, name=name, as_ref=as_ref)
   1147 


~/anaconda3/envs/py36/lib/python3.6/site-packages/tensorflow/python/ops/variables.py in _TensorConversionFunction(v, dtype, name, as_ref)
    827           "Incompatible type conversion requested to type '%s' for variable "
--> 828           "of type '%s'" % (dtype.name, v.dtype.name))
    829     if as_ref:


ValueError: Incompatible type conversion requested to type 'float32' for variable of type 'float64_ref'


During handling of the above exception, another exception occurred:


TypeError                                 Traceback (most recent call last)

<ipython-input-82-9641fac053bd> in <module>()
      2 w2 = tf.Variable(tf.random_normal([2,3], dtype=tf.float64, stddev=1), name='w2')
      3 
----> 4 w1.assign(w2)
      5 # 此处会运行错误


~/anaconda3/envs/py36/lib/python3.6/site-packages/tensorflow/python/ops/variables.py in assign(self, value, use_locking, name, read_value)
   1716     """
   1717     assign = state_ops.assign(self._variable, value, use_locking=use_locking,
-> 1718                               name=name)
   1719     if read_value:
   1720       return assign


~/anaconda3/envs/py36/lib/python3.6/site-packages/tensorflow/python/ops/state_ops.py in assign(ref, value, validate_shape, use_locking, name)
    219     return gen_state_ops.assign(
    220         ref, value, use_locking=use_locking, name=name,
--> 221         validate_shape=validate_shape)
    222   return ref.assign(value, name=name)
    223 


~/anaconda3/envs/py36/lib/python3.6/site-packages/tensorflow/python/ops/gen_state_ops.py in assign(ref, value, validate_shape, use_locking, name)
     59     _, _, _op = _op_def_lib._apply_op_helper(
     60         "Assign", ref=ref, value=value, validate_shape=validate_shape,
---> 61         use_locking=use_locking, name=name)
     62     _result = _op.outputs[:]
     63     _inputs_flat = _op.inputs


~/anaconda3/envs/py36/lib/python3.6/site-packages/tensorflow/python/framework/op_def_library.py in _apply_op_helper(self, op_type_name, name, **keywords)
    544                   "%s type %s of argument '%s'." %
    545                   (prefix, dtypes.as_dtype(attrs[input_arg.type_attr]).name,
--> 546                    inferred_from[input_arg.type_attr]))
    547 
    548           types = [values.dtype]


TypeError: Input 'value' of 'Assign' Op has type float64 that does not match type float32 of argument 'ref'.
维度在程序运行中可以改变,但是需要设置参数validate_shape=False
w1 = tf.Variable(tf.random_normal([2,3], stddev=1), name='w1')
w2 = tf.Variable(tf.random_normal([2,2], stddev=1), name='w2')

tf.assign(w1, w2, validate_shape=False)

<tf.Tensor 'Assign_1:0' shape=(2, 2) dtype=float32_ref>
TensorFlow提供了placeholder机制用于提供输入数据,它相当于定义了一个位置,这个位置中的数据在程序运行时再指定。
  • 定义时数据类型需要指定,并且不可改变
  • 维度信息可以根据提供的数据推导得出,所以不一定要给出
  • 计算结果时,需要提供一个feed_dict来指定x的值
w1 = tf.Variable(tf.random_normal([2,3], stddev=1))
w2 = tf.Variable(tf.random_normal([3,1], stddev=1))

x = tf.placeholder(tf.float32, shape=(1,2), name="input")
a = tf.matmul(x, w1)
y = tf.matmul(a, w2)

with tf.Session() as sess:
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
    
    print(sess.run(y, feed_dict={x: [[0.7, 0.9]]}))
    
[[-1.4116144]]
定义损失函数来刻画预测值与真实值的差距

TensorFlow支持10种不同的优化器,常用的三种:

  • tf.train.GradientDescentOptimizer
  • tf.train.AdamOptimizer
  • tf.train.MomentumOptimizer
通过运行sess.run(train_step)可以对所有在GraphKeys.TRAINABLE_VARIABLES集合中的变量进行优化,使得当前batch下损失函数最小。
y = tf.sigmoid(y)

cross_entropy = -tf.reduce_mean(
    y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0)) + (1-y_)*tf.log(tf.clip_by_value((1-y), 1e-10, 1.0))
)
learning_rate = 0.001
train_step = tf.train.AdamOptimizer(learning_rate).minimize(cross_encropy)

训练神经网络的过程

1. 定义神经网络的结构和前向传播的输出结果
2. 定义损失函数以及选择反向传播优化的算法
3. 生成会话并在训练数据上反复运行反向传播优化算法

完整神经网络样例程序

import tensorflow as tf

# 用于生成随机模拟数据集
from numpy.random import RandomState

# 定义训练集大小
batch_size = 8

# 定义神经网络的参数
w1 = tf.Variable(tf.random_normal([2,3], stddev=1))
w2 = tf.Variable(tf.random_normal([3,1], stddev=1))

x = tf.placeholder(tf.float32, shape=(None, 2), name="x-input")
y_ = tf.placeholder(tf.float32, shape=(None, 1), name='y-input')

# 定义神经网络前向传播过程
a = tf.matmul(x, w1)
y = tf.matmul(a, w2)

#定义损失函数及反向传播算法
y = tf.sigmoid(y)
cross_entropy = -tf.reduce_mean(
    y_ * tf.log(tf.clip_by_value(y, 1e-10, 1.0))
    + (1-y_) * tf.log(tf.clip_by_value((1-y), 1e-10, 1.0))
)
train_step = tf.train.AdamOptimizer(0.001).minimize(cross_entropy)

# 生成随机模拟数据集
rdm = RandomState(1)
dataset_size = 128
X = rdm.rand(dataset_size, 2)
Y = [[int(x1+x2 < 1)] for (x1,x2) in X]

with tf.Session() as sess:
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
    
    print(w1)
    print(w2)
    
    # 训练轮数
    STEPS = 5000
    for i in range(STEPS):
        # 每次选取batch_size个样本进行训练
        start = (i*batch_size)%dataset_size
        end = min(start+batch_size, dataset_size)

        sess.run(train_step, feed_dict={x: X[start:end], y_:Y[start:end]})
        
        if i % 1000 == 0:
            total_cross_entropy = sess.run(cross_entropy, feed_dict={x: X, y_:Y})
            print('After {} training steps, cross entropy on all data is {}'.format(i, total_cross_entropy))
            
    print(w1)
    print(w2)
    
<tf.Variable 'Variable_16:0' shape=(2, 3) dtype=float32_ref>
<tf.Variable 'Variable_17:0' shape=(3, 1) dtype=float32_ref>
After 0 training steps, cross entropy on all data is 0.7092494964599609
After 1000 training steps, cross entropy on all data is 0.6105073690414429
After 2000 training steps, cross entropy on all data is 0.6082877516746521
After 3000 training steps, cross entropy on all data is 0.6080943942070007
After 4000 training steps, cross entropy on all data is 0.6080805063247681
<tf.Variable 'Variable_16:0' shape=(2, 3) dtype=float32_ref>
<tf.Variable 'Variable_17:0' shape=(3, 1) dtype=float32_ref>

总结

计算图是TensorFlow的计算模型,所有TensorFlow的程序都会通过计算图的形式表示。

  • 计算图的每个节点都是一个运算,而计算图上的边则表示运算之间的数据传递关系。
  • 计算图上保存了运行每个运算的设备信息以及运算之间的依赖关系
  • 计算图提供了管理不同集合的功能

张量是TensorFlow的数据模型,所有运算的输入、输出都是张量。

  • 张量不存储任何数据,它只是对运算结果的引用。

会话是TensorFlow的运算模型,它管理了一个TensorFlow程序拥有的系统资源,所有的运算都要通过会话执行。




  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值