一、计算模型——计算图
Tensor(张量)可以被简单理解为多维数组。
TensorFlow中的每一个计算都是计算图上的一个节点,节点之间的边描述了计算之间的依赖关系。
在TensorFlow中,系统会自动维护一个默认的计算图,通过tf.get_default_graph函数可以获取当前的计算图:
print(a.graph is tf.get_default_graph()) //默认为true
可以通过tf.Graph函数来生成新的计算图。不同计算图上的张量和运算都不会共享:
计算图可以通过tf.Graph.device函数来指定运行计算的设备:
g=tf.Graph()
with g.device('/gpu:0'):
result=a+b
在一个计算图中,可以通过集合(collection)来管理不同类别的资源,这里的资源可以是张量、变量或者运行TensorFlow程度所需要的队列资源。
tf.add_to_collection函数可以将资源加入一个或多个集合中
tf.get_collection获取一个集合里面的所有资源
二、数据模型——张量
张量可以简单被理解为多维数组,但张量并不是直接采用数组的形式,它只是对TensorFlow中运算结果的引用。张量中并没有保存数字,它保存的是如何得到这些数字的计算过程。
一个张量中主要保存了三个属性:名字(name)、维度(shape)、类型(type)
张量的命名可以通过“node:scr_output”的形式给出来,node为节点的名字,scr_output表示当前张量来自节点的第几个输出。比如:add:0说明了result这个张量是计算节点add输出的第一个结果(编号为0)
类型不匹配会报错。
TensorFlow支持14重不同的类型,主要包括实数(tf.float32、tf.float64)、整数(tf.int8、tf.int16、tf.int32、tf.int64、tf.unit8)、布尔型(tf.bool)、复数(tf.complex64/128)
张量本身没有存储具体的数字,但是可以使用tf.Session().run(result)语句来得到计算结果
三、运行模式——会话
使用会话的模式一般有两种:
第一种需要明确调用会话生成和会话关闭函数,否则会造成资源泄露:
sess=tf.Session()
sess.run(...)
sess.close()
第二种使用python的上下文管理器来使用会话,上下文管理器退出时候回自动释放所有资源:
with tf.Session() as sess:
sess.run(...)
通过tf.Tensor.eval函数来计算一个张量的取值:
sess=tf.Session()
with sess.as_default();
print(result.eval())
tf.InteractivaSession会自动将生成的会话注册为默认会话:
sess=tf.InteractiveSession()
print(result.eval())
see.close()
四、神经网络的实现
tf.matmul实现了矩阵乘法的功能:
a=tf.matmul(x,W1)
y=tf.matmul(a,W2)
TensorFlow中,变量(tf.Variable)的作用就是保存和更新神经网络中的参数。
声明一个2×3的矩阵变量的方法:
weights=tf.Variable(tf.random_normal([2,3],stddev=2))
tf.random_normal([2,3],stddev=2)会产生一个2×3的矩阵,矩阵中的元素是均值为0,标准差为2的正态分布随机数。
tf.random_normal | 正态分布 |
tf.truncated_normal | 正态分布,但如果随机出来的值偏离平均值超过2个标准差,那么这个数将会被重新随机 |
tf.random_uniform | 平均分布 |
tf.random_gamma | Gamma分布 |
tf.zeros | 产生全0的数组 |
tf.ones | 产生全1的数组 |
tf.fill | 产生一个全部为给定数字的数组 |
tf.constant | 产生一个给定值的常量 |
在TensorFlow中,一个变量的值在被使用之前,这个变量的初始化过程需要被明确的调用:
import tensorflow as tf
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.constant([[0.7, 0.9]])
a = tf.matmul(x, w1)
y = tf.matmul(a, w2)
sess = tf.Session()
sess.run(w1.initializer) #初始化
sess.run(w2.initializer)
print(sess.run(y))
sess.close()
当变量比较多时,可以通过tf.global_variables_initializer()函数实现初始化所有变量:
init_op=tf.global_variables_initializer()
sess.run(init_op)
变量声明函数tf.Variable是一个运算。这个运算的输出结果就是一个张量,这个张量也就是变量。所以变量是一个特殊的张量。
所有的变量都会被自动地加入到GraphKeys . VARIABLES 这个集合中。通过tf.global_variables ()函数可以拿到当前计算图
上所有的变量。
如果声明变量时参数trainable 为True ,那么这个变量将会被加入到GraphKeys. TRAINABLE_ V ARJABLES 集合。在TensorFlow 中可以通过tf.trainable _variables函数得到所有需要优化的参数。TensorF!ow 中提供的神经网络优化算法会将
GraphKeys .TRAINABLE_ VARIABLES 集合中的变量作为默认的优化对象
变量的类型时不可改变的。一个变量在构建之后,它的类型就不能再改变了。
维度在程序运行中是有可能改变的,但是需要通过设置参数validate_shape=False。虽然TensorFlow支持更改变量的维度,但是这种用法在实践中比较罕见。
反向传播算法
TensorFlow 提供了placeholder 机制用于提供输入数据。placeholder 相当于定义了一个位置,这个位置中的数据在程序运行时再指定。这样在程序中就不需要生成大量常量来提供输入数据,而只需要将数据通过placeholder 传入Tensor Flow 计算图。在placeholder 定义时,这个位置上的数据类型是需要指定的。和其他张量一样, placeholder 的类型也是不可以改变的。placeholder 中数据的维度信息可以根据提供的数据推导得出,所以不一定要给出。
x = tf.placeholder(tf.float32, shape=(1, 2), name="input")
a = tf.matmul(x, w1)
y = tf.matmul(a, w2)
sess = tf.Session()
init_op = tf.global_variables_initializer()
sess.run(init_op)
print(sess.run(y, feed_dict={x: [[0.7,0.9]]}))
在新的程序中计算前向传播结果时,需要提供一个feed_dict 来指定x 的取值。feed_dict 是一个字典( map ),在字典中需要给出每个用到的placeholder 的取值。如果某个需要的placeholder 没有被指定取值,那么程序在运行时将会报错。
增加多个输出
x = tf.placeholder(tf.float32, shape=(3, 2), name="input")
a = tf.matmul(x, w1)
y = tf.matmul(a, w2)
sess = tf.Session()
#使用tf.global_variables_initializer()来初始化所有的变量
init_op = tf.global_variables_initializer()
sess.run(init_op)
print(sess.run(y, feed_dict={x: [[0.7,0.9],[0.1,0.4],[0.5,0.8]]}))
#输出
[[ 3.95757794]
[ 1.15376544]
[ 3.16749239]]
完整神经网络样例程序
import tensorflow as tf
from numpy.random import RandomState
#定义神经网络的参数,输入和输出节点。
batch_size = 8
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)
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)
X = rdm.rand(128,2)
Y = [[int(x1+x2 < 1)] for (x1, x2) in X]
#创建一个会话来运行TensorFlow程序。
with tf.Session() as sess:
init_op = tf.global_variables_initializer()
sess.run(init_op)
# 输出目前(未经训练)的参数取值。
print(sess.run(w1))
print(sess.run(w2))
print("\n")
# 训练模型。
STEPS = 5000
for i in range(STEPS):
start = (i*batch_size) % 128
end = (i*batch_size) % 128 + batch_size
sess.run([train_step, y, y_], 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("\n")
print(sess.run(w1))
print(sess.run(w2))