TensorFlow实战Google深度学习框架第三章总结

Tensorflow的组成:

Tensorflow中的每一个计算都是计算图上的一个节点,而节点之间的边描述了计算之间的依赖关系。

1. Tensor:张量,即多维数组(处理类型)。零阶张量——>标量;1阶张量——>向量;n阶张量——>n维数组。张量中并没与保存具体的数字,而是保存的这些数字的计算过程,其中张量包括三种属性:a. 名字(唯一的标识符,同时给出张量如何计算得来的);b. 维度(get_shape函数可以获得维度信息);c. 类型(张量运算必须保持类型一致)。张量的使用主要分为两类:a. 对中间结果的引用;b. 计算图构造完成后,可以用来获得结果(通过会话)。在会话中可以使用Tensor.eval()函数获得张量的取值。

2.flow:计算模型(计算图)。

会话(session):

拥有并管理tensorflow此程序运行时的所有资源,计算完成后,需要关闭会话。

会话的模式一般分为两种:

1.需要明确调用会话生成函数和关闭会话函数。具体形式如下:

sess=tf.Session()

sess.run(…)

sess.close()

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

2.将所有的计算放在with的内部。具体的形式如下:

with tf.Session() as sess:

      sess.run(…)

这种模式的优点:当上下文管理器退出时,会自动将所有资源释放。这样既解决了因为异常退出时资源释放的问题,同时也解决了忘记调用Session.close函数而产生的资源泄露。


import tensorflow as tf

a=tf.constant([[1.0,2.0,3],[3.0,4.0,3]],name='a',dtype=tf.float32)
b=tf.constant([[3,4,3],[5,6,3]],name='b',dtype=tf.float32)

result=a+b

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


#print(result)

#sess=tf.Session()
#print(result.eval(session=sess))

#sess=tf.Session()
#c=sess.run(result)
#print(c)
#sess.close()


#with tf.Session() as sess:
#    c=sess.run(result)
#    print(c)


#sess=tf.Session()
#with sess.as_default():
#    print(result.eval())


#config=tf.ConfigProto(allow_soft_placement=True, log_device_placement=True)
#sess1=tf.InteractiveSession(config=config)
#sess2=tf.Session(config=config)
#c=sess2.run(result)
#print(c)

#sess=tf.InteractiveSession()
#print(result.eval())

在交互式环境下,通过设置默认会话获取张量更加方便。Tensorflow提供了一种在交互式环境下构建默认会话的函数tf.InteractiveSession(),这个函数会自动将生成的会话注册为默认会话。

神经网络解决分类问题的4个步骤:

1.提取问题中实体的特征向量作为神经网络的输入(构建输入);

2.定义神经网络的结构,并定义如何从神经网络的输入到输出。这个过程是神经网络前向传播的过程(定义神经网络的结构)。

3.通过训练数据来调整神经网络中参数的取值,这就是训练神经网络的过程(训练神经网络)。

4.使用训练好的神经网络来预测未知的数据(测试数据)。

前向传播算法:

神经元是构建神经网络的最小单元,每个神经元也可以称为节点。神经网络的前向传播算法可以通过tf.matmul函数实现。

神经网络的参数和Tensorflow变量:

Tensorflow中变量的作用就是保存和更新神经网络中的参数,变量通过tf.Variable函数实现,变量的初始化可以通过三种方式实现

1.可以通过随机数生成函数,来对变量初始化,例如tf.random_normal(正态分布)、tf.truncated_normal(正太分布,但如果随机出来的值偏离平均值超过两个标准差,那么这个数将会被重新随机)、tf.random_uniform(平均分布)、tf.random_gamma(Gamma分布)

2.也可以通过常数来初始化一个变量。例如tf.zeros(产生全零的数组)、tf.ones(产生全1的数组)、tf.fill(产生一个全部为给定数字的数组)、tf.constant(产生一个给定值的常量)。

3.也支持通过其他变量的初始值来初始化新的变量。例如:

w2=tf.Variable(weights.initialized_value())

w3=tf.Variable(weights.initialized_value()*2.0)

以上代码w2的初始值与weights相同,w3的初始值则是weights初始值的;两倍。

虽然在变量定义时给出了变量初始化的方法,但是这个方法并没有真正运行。在会话中需要将其运行。在会话中运行初始化主要有两种方式:

1.sess.run(w1.initializer)

sess.run(w2.initializer)

这种方式的缺点:当变量的数目增多时,或者变量之间存在依赖关系式,单个调用的方案就比较麻烦。

2.可以通过tf.global_variables_initializer函数实现所有变量的初始化(文中使用tf.initialize_all_variables()但是这个函数已经被弃用,由tf.global_variables_initializer()代替)。

init_op=tf.global_variables_initializer()

sess.run(init_op)

优点:不需要对变量一个一个初始化,同时这种方式会自动处理变量之间的依赖关系。

可以使用w1.assign(w2)函数,来对w1的值进行更新,需要注意的是要保证w1和w2张量中的数据类型是一致的。


import tensorflow as tf

#声明w1和w2两个变量,还通过seed参数设定了随机种子,这样可以保证每次运行结果是一样的
w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1))
w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=1))

#设定x(输入)为常数。注意这里x是一个1*2的矩阵
x=tf.constant([[0.7,0.9]])

a=tf.matmul(x,w1)#实现x和w1相乘
y=tf.matmul(a,w2)

sess=tf.Session()

#初始化方法1
#sess.run(w1.initializer)#初始化w1
#sess.run(w2.initializer)#初始化w2

#初始化方法2
init_op=tf.global_variables_initializer()
sess.run(init_op)

print(sess.run(y))

sess.close()


训练神经网络:

在神经网络优化算法中,最常用的方法是反向传播算法,在tensorflow中通过tf.train.AdamOptimizer()实现,例如train_step = tf.train.AdamOptimizer(learning_rate).minimize(cross_entropy)。

Tensorflow提供了placeholder机制用于提供输入数据。placeholder相当于定义了一个位置,这个位置中的数据在程序运行时在指定。在placeholder定义时,这个位置上上的数据类型是需要指定的,同时placeholder的类型也是不可以改变的。Placeholder中数据的维度可以根据数据推导出,所以不一定要给出。在会话中执行时,需要提供一个feed_dict来指定x的取值。Feed_dict是一个字典,字典中需要给出每个用到的placeholder的取值。

训练神经网络可以分为3个步骤:

1.定义神经网络的结构和前向传播算法的结果

2.定义损失函数以及选择反向传播算法优化的算法

3.生成会话并且在训练数据集上反复运行反向传播优化算法。

下面给出了一个完整的程序来训练神经网络解决二分类问题:


import tensorflow as tf
#通过Numpy工具包模拟数据集
from numpy.random import RandomState

batch_size=8#训练数据batch的大小

#定义神经网络的参数
w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1))
w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=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)

#定义损失熵和反向传播算法
cross_entropy=-tf.reduce_mean(y_*tf.log(tf.clip_by_value(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)

#定义规则来给出样本的标签。所有x1+x2<1的样例都认为是正样本而其他的为负样本。1表示正样本;0表示负样本
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(sess.run(w1))
    print(sess.run(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 %d training step(s), cross entropy on all data is %g"%(i,total_cross_entropy))
            
    print(sess.run(w1))
    print(sess.run(w2))


猜你喜欢

转载自blog.csdn.net/wyl1813240346/article/details/78346435