本篇文章主要讲网络搭建过程中的代码以及注意要点。

添加网络层

定义网络结构,然后将网络层添加到神经网络中。定义网络层的主要步骤有:

  • 确定网络的参数:输入,输入的size,输出的size,激励函数
  • 定义weight,biases
  • 计算output
1
2
3
4
5
6
7
8
9
def add_layer(input,in_size,out_size,activation_function = None):
Weights = tf.Variable(tf.random.normal([in_size,out_size]))
biases = tf.Variable(tf.zeros([1,out_size])+0.01)
Wx_plus_b = tf.matmul(input,Weights)+biases
if activation_function is None:
output = Wx_plus_b
else:
output = activation_function(Wx_bias_b)
return output

可以看出来,网络层神经元的个数即为输出的outsize的大小。

搭建神经网络

以下为搭建一个三层神经网络,其中输入层为1个神经元,输出层为1个神经元,隐藏层为10个神经元。搭建网络是需要完成的事情为:

  1. 定义数据,网络层中的参数维度
  2. 定义传入的参数placeholder,loss,optimizer等
  3. 值得注意的是,数据的维度变化需要十分注意
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
import tensorflow as tf
import numpy as np

# create data
x_data = np.linspace(-1,1,300)[:,np.newaxis]
noise = np.random.rand(x_data.shape[0],x_data.shape[1])
y_GT = np.square(x_data)+0.5+noise

# placeholder
xs = tf.placeholder(tf.float32,[None,1]) #表示样本数,和每个样本的维度为1
ys = tf.placeholder(tf.float32,[None,1])
# structure
l1 = add_layer(ms,1,10,tf.nn.relu)
output = add_layer(l2,10,1,None)
# loss
loss = tf.reduce_mean(tf.reduce_sum(tf.square(output-ys),1))
optimizer = tf.train.GrandientDescentOptimizer(0.1).minimize(loss)

#train
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
for step in range(1000):
sess.run(optimizer,feed_dict={xs:x_data,ys:y_GT})
if step%20 == 0:
print(loss,feed_dict={xs:x_data,ys:y_GT})

代码详解如下:

  1. x_data = np.linspace(-1,1,300)[:,np.newaxis]:其中np.linspace(-1,1)生成-1,到1之间的300个数。[:,np.newaxis]指将生成的数据维度提升。原来是1x300,现在是300x1,由1为变为300维,每个数据占一个维度。

  2. xs = tf.placeholder(tf.float32,[None,1]) #表示样本数,和每个样本的维度为1:其中[None,1]有一种含义为,当你不知道样本数的时候,抓住每个样本的维度即可。

  3. tf.reduce_sum(tf.square(output-ys),1): 其中tf.reduce_sum()这个函数为求和函数,第一个参数是一个数组,第二个参数默认则为所有数之和。第二个参数为0,则为列之和(0),第二个参数为1则为行之和(1)tf.reduce_mean()参数含义与求和函数一致。
  4. 在写网络结构的时候,用placeholder,暂时忘记掉真实的数据,先构建好框架后,然后传入参数。

结果可视化

可视化模块一般使用matplotlib.plot as plt 来绘图。

matplotlib的层次结构:
matplotlib的结构类似与一个树状结构。Figure : 为层次结构中的最外层,内部可包含多张plot图像。plot图层次结构可包含的对象例如刻度线,单独的线条,图例和文本框。几乎每个“元素”都是一个Python对象。具体代码实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-np.pi,np.pi,300)
xsin = np.sin(x)
xcos = np.cos(x)
plt.subplot(221) # 表明共有2列,2行的图片要画,现在拿到第一个来画
plt.plot(x,xsin) # 要画折线图,如果点很密集,就是曲线图
plt.xlabel('x轴') # 所有属于这个子图的小对象,如颜色,图例,都可以修改
plt.subplot(222) # 表明2列2行,现在要画第二个
plt.plot(x,xcos)
plt.subplot(223) # 表明2行2列,现在要画第三个
plt.scatter(x,xsin) # 要画散点图
plt.show()

如上,每次使用plt.subplot(xxx)交换控制的子图,非常好懂哈哈哈。

下面是搭建网络,绘制拟合图的完整代码:

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
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import os
os.environ['KMP_DUPLICATE_LIB_OK']='True'
"""
添加层需要考虑的因素有几个,首先输入的数据,输入的数据尺度,输出的尺度(神经元个数),激活函数
"""

def add_layer(input,in_size,out_size,activation_function = None):
#定义权重
Weights = tf.Variable(tf.random.normal([in_size,out_size]))
bias = tf.Variable(tf.zeros([1,out_size])+ 0.01)
Wx_plus_b = tf.matmul(input,Weights) + bias
if activation_function is None:
outputs = Wx_plus_b
else:
outputs = activation_function(Wx_plus_b)
return outputs

"""
构建神经网络:
1. 搭建一个输入层仅有一个神经元,隐藏层10个神经元,输出层1个神经元的网络
2. 需要定义数据,网络层,输入输出,placeholder,loss ,optimizer
"""
# np.linspace(-1,1,10)[:,np.newaxis],引入新维度

# create data

x_data = np.linspace(-1,1,300)[:,np.newaxis]

noise = np.random.rand(300,1)
y_GT = np.square(x_data) + 0.5+noise

# create network

xs = tf.placeholder(tf.float32,x_data.shape)
ys = tf.placeholder(tf.float32,y_GT.shape)

l1 = add_layer(xs,1,10,activation_function=tf.nn.relu)
output = add_layer(l1,10,1,activation_function=None)

# loss
loss = tf.reduce_mean(tf.reduce_sum(tf.square(output-ys),1))
optimizer = tf.train.GradientDescentOptimizer(0.1).minimize(loss)

#illustration
ax = plt.subplot(111)
plt.scatter(x_data,y_GT)

plt.ion() # 动态画图,不停止
plt.show()

# train

init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
for step in range(500):
sess.run(optimizer,feed_dict={xs:x_data,ys:y_GT})
if step%20 == 0:
print(sess.run(loss,feed_dict={xs:x_data,ys:y_GT}))
predict = sess.run(output,feed_dict={xs:x_data})
# plt.plot(x_data,predict)
try:
ax.lines.remove(lines[0])
except Exception:
pass

# plot the prediction
lines = plt.plot(x_data, predict, 'r-', lw=5)
plt.pause(0.5)

TensorBoard 可视化

Tensorboard 作为tensorflow网络结果可视化的一个比较好的工具,他使用tf.name_scope("name"):的方式对部分元件进行整体的命名。并且支持多层的嵌套。如下例子:

1
2
3
with tf.name_scope("layer"):
with tf.name_scope("Weight"):
Weights = tf.Variable(tf.random.normal([300,1]),name = 'W')

tensorboard工作的思路是将文件写入磁盘,然后由浏览器进行访问,写入磁盘的语句如下:

1
2
sess = tf.Session()
writer = tf.summary.FileWriter('./log',sess.graph)

最后在命令行中,进入文件目录输入指令:

1
tensorboard --logdir = 'log/'

随后在浏览器中输入:0.0.0.0:6006即可预览。

tensorboard还可以监控单个变量的变化情况,使用histogram直方图来显示。tf.summary.histogram代码如下:

1
2
3
with tf.name_scope("Weight"):
Weights = tf.Variable(tf.random.normal([300,1]),name = 'W')
tf.summary.histogram(name,Weight)

tensorboard看一个一维的变量,如loss,使用tf.summary.scalar

1
2
3
with tf.name_scope('loss'):
loss = tf.reduce.mean(tf.reduce.sum(tf.square(y-p_pred),1),1)
tf.summary.scalar('loss',loss)

最后需要对所有的summary进行融合:

1
merged = tf.summary.merge_all()

接下来在训练的时候更新参数,然后使用writer.add_summary(result,step)来将summary写入文件中。

1
2
3
4
5
6
7
8
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
for step in range(1000):
sess.run(optimizer,feed_dict={xs:x_data,ys:y_GT})
if step%20 == 0:
result = sess.run(merged,feed_dict={xs:x_data,ys:y_GT})
writer.add_summary(result,step)

接着使用命令行运行即可.x