TensorFlow入门-下 | 陈浩然的博客

TensorFlow入门-下

前置准备

在阅读本文之前,请确定你已经了解了神经网络的基本结构以及前向传播、后向传播的基本原理,如果尚未了解,可以查看下文。

神经网络初探

本文的上篇在TensorFlow入门-上,从中可以了解到TensorFlow的基本概念——计算图,张量,会话,变量,变量集合等。

几种重要算法

前向传播

前向传播是神经网络最重要的算法之一,他的目的是通过输入层的输入进行推断,得到输出层的结果,下面假定一个简单的神经网络如下图,包含:一个输入层,一个隐藏层,一个输出层。

则该算法的tensorFlow表达为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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)
init_op = tf.initialize_all_variables()
sess.run(init_op)

# 运行
print(sess.run(y))
sess.close()

反向传播

反向传播(英语:Backpropagation,缩写为BP)是“误差反向传播”的简称,是一种与最优化方法(如梯度下降法)结合使用的,用来训练人工神经网络的常见方法。该方法对网络中所有权重计算损失函数的梯度。这个梯度会反馈给最优化方法,用来更新权值以最小化损失函数。

反向传播在TensorFlow中的实现很简单,不需要我们一步一步定义,只需要我们定义好损失函数,然后开始计算时,程序会自动进行反向传播减小误差。

注入数据

进行训练需要用到大量数据,注入数据是通过placeHolder进行的,示意如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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))

# 定义placeholder
x = tf.placeholder(tf.float32,shape=(3,2),name="input")
a = tf.matmul(x,w1)
y = tf.matmul(a,w2)

# 真正开始初始化权重
sess = tf.Session()
init_op = tf.initialize_all_variables()
sess.run(init_op)

# 像x中注入数据
print(sess.run(y,feed_dict={x:[[0.7,0.9],[0.1,0.4],[0.5,0.8]]}))

TensorFlow模型步骤

由于TensorFlow是使用连接主义进行架构的,也就是说,先定义网络结构,在进行运算,所以建立模型有以下几个步骤:

  1. 建立各个变量之间的定义以及他们之间的关系
  2. 建立数据训练过程
  3. 通过sess.run()开始训练
  4. 在训练过程中进行评估,以适时结束训练

第一个神经网络

下面通过建立第一个神经网络,更好的进行理解,该网络结构如上图所示,数据集随机模拟而来:

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
import tensorflow as tf
# 使用numpy包来模拟数据集
from numpy.random import RandomState

# 训练数据batch的大小
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)

# 定义损失函数和反向传播算法
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)

# 通过随机数生成一个模拟数据集,x1+x2<1则标签为正样本,否则为负样本
rdm = RandomState(1)
dateset_size = 128
X = rdm.rand(dateset_size,2)
Y = [[int (x1 + x2 <1)] for (x1,x2) in X]

# 创建会话
with tf.Session() as sess:
# 初始化参数
init_op = tf.initialize_all_variables()
sess.run(init_op)
print(sess.run(w1),sess.run(w2))
# 设定训练的各种参数
steps = 7000
for i in range(steps):
# 每轮选择batch_size个样本来训练
start = (i*batch_size) % dateset_size
end = min(start + batch_size,dateset_size)
# 开始训练
sess.run(train_step,feed_dict={x: X[start:end], y_: Y[start:end]})
# 每过100轮进行一次计算交叉熵(损失函数)
if i % 1000 ==0:
total_crosss_entropy = sess.run(cross_entropy,feed_dict={x:X,y_:Y})
print("After %d training steps, cross entropy is %g" %(i,total_crosss_entropy))
# 输出训练后的权重
print(sess.run(w1),sess.run(w2))

结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[[-0.8113182   1.4845988   0.06532937]
[-2.4427042 0.0992484 0.5912243 ]]
[[-0.8113182 ]
[ 1.4845988 ]
[ 0.06532937]]
After 0 training steps, cross entropy is 0.0674925
After 1000 training steps, cross entropy is 0.0163385
After 2000 training steps, cross entropy is 0.00907547
After 3000 training steps, cross entropy is 0.00714436
After 4000 training steps, cross entropy is 0.00578471
After 5000 training steps, cross entropy is 0.00430222
After 6000 training steps, cross entropy is 0.00280812
[[-2.3681936 2.968816 2.1473026]
[-3.882967 1.4639109 2.5922096]]
[[-2.2131984]
[ 3.1050255]
[ 1.8669094]

自定义损失函数

在现实生活中,损失可能并不想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
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

import tensorflow as tf
from numpy.random import RandomState

batch_size = 8


# 定义输入和标签输出
x = tf.placeholder(tf.float32,shape=(None,2),name='x-input')
y_ = tf.placeholder(tf.float32,shape=(None,1),name='y-input')

# 前向传播的结构
w1 = tf.Variable(tf.random_normal([2,1],stddev=1,seed=1))
y = tf.matmul(x,w1)

# 自定义损失函数
loss_less = 10
loss_more = 1
# 注意select名称改成了where,这里自定义了损失函数
loss = tf.reduce_sum(tf.where(tf.greater(y,y_),
(y-y_)*loss_more,
(y_-y)*loss_less))
train_step = tf.train.AdamOptimizer(0.001).minimize(loss)

# 随机生成模拟集
rdm = RandomState(1)
dateset_size = 128
X = rdm.rand(dateset_size,2)
# 加入了随机噪声
Y = [[x1 + x2 + rdm.rand()/10.0-0.05] for (x1,x2) in X]

with tf.Session() as sess:
init_op = tf.global_variables_initializer()
sess.run(init_op)
STEPS = 5000
for i in range(STEPS):
# 每轮选择batch_size个样本来训练
start = (i * batch_size) % dateset_size
end = min(start + batch_size, dateset_size)
# 开始训练
sess.run(train_step, feed_dict={x: X[start:end], y_: Y[start:end]})
# 每过100轮进行一次计算交叉熵(损失函数)

print(sess.run(w1))

结果如下:

1
2
[[1.019347 ]
[1.0428089]]

查看更多

所有的文章都会在我的博客和我的知乎专栏同步进行更新,欢迎阅读


本文结束啦感谢您的阅读
生活不易,求打赏
0%