很荣幸从我的导师那里获得了一次给我们院老师讲解人工智能代码的机会,有一种"受命以来,夙夜忧叹,恐托付不效"的感觉,所以找了本高分评价书籍《TensorFlow 实战Google深度学习框架》系统的回顾一下,写下这个系列的博客,主要提炼了书中重要知识点,同时对复杂的部分提供个人理解。使用框架前,需要对深度学习有一定的理论基础。
一、计算图
TensorFlow 程序一般可以分为两个阶段:
- 定义计算图中所有的计算
- 执行计算
# 这里定义了一个计算图
a = tf.constant([1.0,2.0], name = "a")
b = tf.constant([2.0,3.0], name = "b")
result = a + b
# 查询张量所属的计算图,下列因为没有特意指定,所以是当前默认的计算图
print(a.graph is tf.get_default_graph())
使用tf.Graph生成新的计算图,不同计算图的张量运算不会共享
# 定义g1图并生成变量v
g1 = tf.Graph()
with g1.as_default():
v = tf.get_variable(
"v", shape = [1], initializer = tf.zeros_initializer())
# 定义g2图并生成变量v
g2 = tf.Graph()
with g2.as_default():
v = tf.get_variable(
"v", shape = [1], initializer = tf.ones_initializer())
# 在计算图g1中读取变量v的取值
with tf.Session(graph = g1) as sess:
sess.run(tf.global_variables_initializer())
tf.global_variables_initializer()
with tf.variable_scope("", reuse = True):
print(sess.run(tf.get_variable("v")))
# 在计算图g2中读取变量v的取值
with tf.Session(graph = g2) as sess:
sess.run(tf.global_variables_initializer())
tf.global_variables_initializer()
with tf.variable_scope("", reuse = True):
print(sess.run(tf.get_variable("v")))
此段代码会报错,a默认类型为float32,b默认类型int32
a = tf.constant([1.0, 2.0], name = "a")
b = tf.constant([2, 3], name = "b")
result = tf.add(a, b, name = "add")
print(result)
二、张量
# tf.constant 生成常量
a = tf.constant([1.0, 2.0], name = "a")
b = tf.constant([2.0, 3.0], name = "b")
result = a + b
# 使用张量获取张量维度
result.get_shape
三、会话
之前所说的都是定义一个计算图,后续我们需要执行定义好的计算,这就需要使用会话
a = tf.constant([1.0, 2.0], name = "a")
b = tf.constant([2, 3], name = "b")
result = tf.add(a, b, name = "add")
print (result)
此时打印出的结果是:
Tensor("add_1:0", shape=(2,), dtype=int32)
分别表示了这个result张量名字,维度和类型,但实际未出现结果,下述代码通过定义会话成功的打印出了结果
a = tf.constant([1, 2], name = "a")
b = tf.constant([2, 3], name = "b")
result = tf.add(a, b, name = "add")
# 定义一个会话,通过python上下文管理器管理会话
with tf.Session() as sess:
print(sess.run(result))
# 当然也可以使用.eval()函数打印result的值
with tf.Session() as sess:
print(result.eval())
未特殊指定情况下,会话使用了之前默认定义的图.
# 把定义的sess1会话设定为默认会话
sess1 = tf.Session()
with sess1.as_default():
print(result.eval())
交互式会话
tf.InteractiveSession()函数会将自动生成的会话注册成为默认会话
sess = tf.InteractiveSession()
print(result.eval())
sess.close()
通过使用tf.ConfigProto配置要生成会话
config = tf.ConfigProto(allow_soft_placement = True,
log_device_placement = True)
sess1 = tf.InteractiveSession(config = config)
sess2 = tf.Session(config = config)
allow_soft_placement = True时候,在某些无法使用GPU计算的时候,会转到CPU上进行,默认值为False
log_device_placement = True受,日志会记录每个节点被安排在哪个设备上以方便调试
四、变量
创建变量:
weights = tf.Variable(tf.random_normal([2, 3], stddev = 2))
biases = tf.Variable(tf.zeros([3]))
# 使用其他变量初始值来初始化新的变量
w2 = tf.Variable(weights.initialized_value() * 2.0)
Tensorflow随机数生成函数
Tensorflow常数生成函数
需要注意的是变量是特殊的张量,所有的变量都会假如到GraphKeys.VARIABLES集合中,通过tf.global_variables函数可以拿到当前计算图上所有的变量。当构建机器学习模型的时候,可以通过变量声明函数中的trainable参数区分需要优化的参数和其他参数。
注意变量的类型不匹配
# 该段程序会出现报错现象
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)
Tensorflow还支持改变变量的维度
w1 = tf.Variable(tf.random_normal([2,3], stddev = 1), name = "w1")
w2 = tf.Variable(tf.random_normal([2,2], stddev = 1), name = "w2")
# 报错
w1.assign(w2)
# 设置参数validate_shape = False可以修改
tf.assign(w1, w2, validate_shape = False)
五、搭建简单的神经网络
Tensorflow下搭建神经网络的步骤主要是:
- 定义神经网络的结构和前向传播的输出结果
- 定义损失函数以及选择反向传播算法
- 生成会话并且在训练数据上反复运行反向传播优化算法
# 定义神经网络的参数
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))
# shape的一个维度上使用None,可以使用不同batch大小填充输入数据
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_hat = tf.sigmoid(tf.matmul(a, w2))
# 定义损失函数
# tf.clip_by_value在这里表示如果y_hat小于1e-10,则就等于1e-10,如果y_hat大于1,则就等于1
loss = -tf.reduce_mean(y * tf.log(tf.clip_by_value(y_hat, 1e-10, 1.0))
+ (1-y) * tf.log(tf.clip_by_value(1-y, 1e-10, 1.0)))
# 定义反向传播算法
# 使用Adam算法优化
train_step = tf.train.AdamOptimizer(0.001).minimize(loss)
# 使用随机数生成模拟数据集
np.random.seed(1)
dataset_size = 128
X = np.random.rand(dataset_size, 2)
Y = [[int (x1 + x2 < 1)] for (x1, x2) in X]
# 初始化变量
init = tf.global_variables_initializer()
# 创建会话执行程序
with tf.Session() as sess:
# 执行初始化变量
sess.run(init)
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_loss = sess.run(loss, feed_dict = {x: X, y: Y})
print("After %d training step, loss:%g" %(i, total_loss))