cs224n-Lecture 7 TensorFlow入门

文章目录
  1. 1. TensorFlow中的计算图
  2. 2. 定义损失函数
  3. 3. 计算梯度
  4. 4. 建立训练步骤
  5. 5. 训练模型
  6. 6. 使用TensorFlow构建线性分类的基本步骤
  7. 7. 使用TensorFlow的完整版线性分类

这个章节就是一个TensorFlow的入门课,直接上TF框架吧。

TensorFlow中的计算图

Tensorflow是一种图计算编程模型,它的中心思想是将数值运算以图的形式描述。
假如存在下列计算:

下图所示的计算图就是上述式子的计算步骤:

W 和 b 是变量,除此之外,还有一个占位符用来表示x,图中的节点表示每一步操作。
注:占位符是那些在执行时间才会接收值得节点。

变量将成为输出其当前值的有状态节点,在这个例子中 W 和 b 就是变量,它们是有状态的,他们保留多次执行过程中的当前值,将保存的值恢复到变量是很容易的,所以,变量有许多其他有用的特征,他们可以在训练过程以及训练后保存到硬盘中。

假如在你的图中有依赖外部,但是并不想在建立图时依赖任何实际的值,这些就是在计算当中添加到模型中充当占位符的值。
所以,对于占位符,我们不给定任何初始化的值,仅仅分配一个数据类型,分配一种大小的张量。但是计算图仍然知道需要计算什么,尽管当前模型中并没有存储的值。
计算图中的计算节点则是调用tensorflow来进行计算,而不是直接使用numpy。

上述计算通过Tensorflow编写如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env python
#coding:utf-8

import tensorflow as tf

if __name__=="__main__":
b=tf.Variable(tf.zeros(100,))
# [1,100]
W=tf.Variable(tf.random_uniform((184,100),-1,1))
# [184,100]

x=tf.placeholder(tf.float32,(100,184))
# 由于 wx+b 需要计算,所以这里x矩阵的大小就是w矩阵的转置

h=tf.nn.relu(tf.matmul(x,W)+b)
# 计算激活函数 relu

后面会用到两个变量 Fetches 和 feeds。
Fetches:返回节点输出的图形节点列表。
feeds:一个从图节点到我们想要在模型中运行的实际值的字典映射。
这些就是实际填写在前面提到的占位符的地方。

在原先的代码上再加上几行,变成如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/env python
#coding:utf-8

import numpy as np
import tensorflow as tf

if __name__=="__main__":
b=tf.Variable(tf.zeros(100,))
# [1,100]
W=tf.Variable(tf.random_uniform((184,100),-1,1))
# [184,100]

x=tf.placeholder(tf.float32,(100,184))
# 由于 wx+b 需要计算,所以这里x矩阵的大小就是w矩阵的转置

h=tf.nn.relu(tf.matmul(x,W)+b)
# 计算激活函数 relu

sess=tf.Session()
# 创建会话
sess.run(tf.initialize_all_variables())
# 初始化所有的变量
sess.run(h,{x:np.random.random(100,184)})

现在这个亚子肯定是没法进行训练的,其中没有加入任何训练数据。

定义损失函数

首先,使用占位符来表示标签,作为只在执行时喂给的数据。
label 是真实标记的占位符,模型根据这个值来进行计算。
最后创建交叉熵(cross_entropy),它是真实标签乘上TensorFlow中对prediction取对数的乘积,然后再按列求和。

1
2
3
4
5
6
7
prediction=tf.nn.softmax(...)
# 神经网络的预测输出
label=tf.placeholder(tf.float32,[100,10])
# 数据标签

cross_entropy=-tf.reduce_sum(label*tf.log(prediction),axis=1)
# 计算交叉熵

我们想要对每行数据进行求和,label 是一个one-hot变量。

计算梯度

在tensorflow中首先要创建一个优化器对象。
TF中有一个通用的抽象类叫做优化器,这个类中的每一个子类都是一个针对特定学习算法的优化器,目前使用的是梯度下降算法。

1
train_step=tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

通过这个式子,参数W和b就会根据一定的梯度进行下降。
在TF框架中它的工作方式是,每一个图节点都有一个附加的梯度操作,都有相对于输入预先构建的输出梯度。所以,当我们在计算交叉熵相对于所有参数的梯度时,通过图使用链式法则利用反向传播计算是非常简单的。

建立训练步骤

只需在上述步骤中加入交叉熵的部分并代入即可。

1
2
3
4
5
6
7
8
prediction=tf.nn.softmax(...)
# 神经网络的预测输出
label=tf.placeholder(tf.float32,[None,10])
# 数据标签
cross_entropy=tf.reduce_mean(-tf.reduce_sum(label*tf.log(prediction),axis=1))
# 计算交叉熵

train_step=tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

训练模型

假设迭代 1000 次,注意,在 train_step 上调用 sess.run 方法时,它已经对图中所有的变量应用了梯度。
此时需要建立一个字典,将值传给之前定义好的两个占位符,x 和 label 是图中的节点,字典中的关键字是图中的节点,对应的项是numpy数据。TF框架会自动把设定图中节点的数据转换为张量。
所以,可以把numpy数组插入到字典中,比如 batch_x 和 batch_label,执行 sess.run 之后会得到输出。

1
2
3
4
5
6
sess=tf.Session()
sess.run(tf.initialize_all_variables())

for i in range(1000):
batch_x,batch_label=data.next_batch()
sess.run(train_step,feed_dict={x:batch_x,label:batch_label})

字典示例:

但是像上述的命名会导致不知道变量类型等相关数据,所以TF框架的variable_scope 提供了一个简单得名称空间方案来避免冲突,而另一个相关的函数则是一个叫做 get_variable 的东西,get_variable 将会给你创建一个变量,如果具备特定名字的变量不存在的话,否则如果发现它存在,它将访问该变量。

使用TensorFlow构建线性分类的基本步骤

2019.9.10 更新
(拖延症一直拖了好久才写的这个部分,明明字不多的…(捂脸
首先,构建分类器的目的,就是为了给数据做分类,这里相当于一个数据的拟合。
这里根据习惯,可以先设置模型的基本参数,也可以后面需要训练的时候再进行设置。
1.设置模型参数:学习率(learning_rate),训练的轮数(trainiing_epoches),每多少step展示一次训练效果(display_step);
2.对应的训练数据集,包括X和Y两个部分;
3.找出对应的训练样例数,n_samples;
4.写出图输入对应的tf占位符(tf.placeholder);
5.为线性模型的权重(Weights)和偏置(bias)设置初始值,可以使用np.random.randn来生成,由于这里是在tf框架里,所以是tf.Variable的数据类型;
6.生成线性模型:Y=W*X+b;
7.误差计算(交叉熵或者是均方误差);
8.构建优化器来进行梯度下降:tf.train.GradientDescentOptimizer(学习率).minimize(交叉熵或是均方误差);
9.启动tf.Session()来run各轮训练的结果;
10.可以用matplotlib来画个图什么的。(这步可以直接忽略)

使用TensorFlow的完整版线性分类

直接上代码吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!/usr/bin/env python
#coding:utf-8

import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt

if __name__=="__main__":
learning_rate=0.01
training_epochs=1000
display_step=50

# Training Data
train_X=np.array([3.3, 4.4, 5.5, 6.71, 6.93, 4.168, 9.779, 6.182, 7.59, 2.167,
7.042, 10.791, 5.313, 7.997, 5.654, 9.27, 3.1])
train_Y=np.array([1.7, 2.76, 2.09, 3.19, 1.694, 1.573, 3.366, 2.596, 2.53, 1.221,
2.827, 3.465, 1.65, 2.904, 2.42, 2.94, 1.3])
n_samples=train_X.shape[0]
# 存在多行的情况,shape[0] 表示row,shape[1] 表示col
# 倘若数据只有一列,那么shape[0]表示的就是这行有多少个数值

# TF 图输入
X=tf.placeholder(tf.float32)
Y=tf.placeholder(tf.float32)

# 设置线性模型权重
W=tf.Variable(np.random.randn(),name='Weight')
b=tf.Variable(np.random.randn(),name='bias')

# 构建线性模型
prediction=tf.add(tf.multiply(X,W),b)

# 计算均方误差
cross_entropy=tf.reduce_mean(tf.square(prediction-Y))
# 梯度下降
optimizier=tf.train.GradientDescentOptimizer(learning_rate).minimize(cross_entropy)

# 初始化变量
init=tf.global_variables_initializer()

# 开始训练
with tf.Session() as sess:
# 运行初始化
sess.run(init)

# 加入全部的训练数据
for epoch in range(training_epochs):
for(x,y) in zip(train_X,train_Y):
sess.run(optimizier,feed_dict={X:x,Y:y})

# 显示每一轮训练的损失函数
if (epoch+1)%display_step==0:
c=sess.run(cross_entropy,feed_dict={X:train_X,Y:train_Y})
print("Epoch:","%04d"%(epoch+1),"cost=", "{:.9f}".format(c), \
"W=", sess.run(W), "b=", sess.run(b))

print("Optimization Finished!")
training_cost=sess.run(cross_entropy,feed_dict={X:train_X,Y:train_Y})
print("Training cost=",training_cost,"W=",sess.run(W),"b=",sess.run(b))

# 图展示
plt.plot(train_X,train_Y,'ro',label='Original Data')
plt.plot(train_X,sess.run(W)*train_X+sess.run(b),label='Fitted Line')
plt.legend()
plt.show()

# 测试样例
test_X = np.asarray([6.83, 4.668, 8.9, 7.91, 5.7, 8.7, 3.1, 2.1])
test_Y = np.asarray([1.84, 2.273, 3.2, 2.831, 2.92, 3.24, 1.35, 1.03])

print("Testing...(Mean square loss Comparison)")
testing_cost=sess.run(tf.reduce_sum(tf.pow(prediction - Y, 2)) / (2 * test_X.shape[0]),
feed_dict={X: test_X, Y: test_Y})
print("Testing cross-entropy=",testing_cost)
print("Absolute mean square loss difference:",abs(training_cost-testing_cost))

plt.plot(test_X, test_Y, 'bo', label='Testing data')
plt.plot(train_X, sess.run(W) * train_X + sess.run(b), label='Fitted line')
plt.legend()
plt.show()

代码参考自:https://blog.csdn.net/left_think/article/details/78061675