6.构建神经网络

前言

我们已经知道,深度学习一词,最早是在2006~2007年,由Geoffrey Hinton 在《Science》上发表的文章开始被提出和逐步兴起的。深度学习是在机器学习的基础上发展的,神经网络的层级比机器学习的多而复杂。

《6.构建神经网络》 生物学领域神经网络中的单个神经元 ↑

神经网络结构,正是受到生物学领域中的神经网络的启发,才有了今天机器学习、深度学习中的神经网络的结构。

今天我们就利用谷歌的深度学习框架TensorFlow,来搭建一个自己的简单的神经网络。

《6.构建神经网络》

上面是一个3层的神经网络,其中:每一个⭕️代表一个神经元,也可以叫做神经节点、神经结点,每个神经元有一个偏置bias。每一条线,有一个权重weight。

神经网络学习的目标:就是通过减少损失loss或cost,来确定权重和偏置。理论上,如果有足够多的隐藏层和足够大的训练集,则可以模拟出任何方程。

搭建一个简单的神经网络

搭建一个简单的神经网络的基本思路:
1.准备数据
2.搭建模型
3.训练模型
4.使用模型

先来搭建一个只有两层(不包含输入层)的神经网络,也即:输入层–隐藏层–输出层。

为了方便层的添加,我们把添加层,抽到一个方法中add_layer(inputs, input_size, output_size, activation_func),参数解释如下:

inputs: 输入的数据
input_size: 输入的size
output_size: 输出的size
activation_func: 激励函数

完整的添加层,代码如下所示:

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


# 添加一层
def add_layer(inputs, input_size, output_size, activation_func):
    """
    :param inputs: 输入的数据
    :param input_size: 输入的size
    :param output_size: 输出的size
    :param activation_func: 激励函数
    :return:
    """
    weights = tf.Variable(tf.random_normal([input_size, output_size], seed=1024))
    bias = tf.Variable(tf.zeros([1, output_size]))

    w_x_plus_b = tf.matmul(inputs, weights) + bias

    if activation_func is None:
        outputs = w_x_plus_b
    else:
        outputs = activation_func(w_x_plus_b)
    return outputs

说明:
1.权重weights的初始化,通常是通过生产随机数作为权重的初始化值。

2.偏置bias的初始化,通常是将偏置初始化为0。

《6.构建神经网络》 神经元

3.我们已经知道,每一个⭕️代表着一个神经元,也可以叫做神经节点、神经结点,每个神经元有一个偏置bias。每一条线,有一个权重weight。如上图所示。神经网络学习的目标:就是通过减少损失loss或cost,来确定权重和偏置,所以权重和偏置都是用tensorflow中的tf.Variable()来创建的。tf.Variable()有一个很重要的特性,是可被训练。

4.w_x_plus_b = tf.matmul(inputs, weights) + bias整体表示:权重 * 自变量 + 偏置,也就是通常我们见到的线性函数y = a * x + b;权重即这里的a,偏置即这里的b。在tensorflow中,tf.matmul(inputs, weights)表示矩阵相乘。

5.通常,一层中的神经元经过加权求和,然后再经过非线性方程得到的结果转化为输出,或者作为下一层的输入。注意:非线性方程,即是通常所说的激励函数。

常见的激励函数:sigmoid函数、tanh函数、ReLu函数、SoftMax函数等等。这里我们设计的函数需要调用者传入一个激励函数,如果不传入,则按照线性处理。

补充:tensor flow中的随机数

tensor flow中的随机数,常用的有两种:正态分布的随机数和均匀分布随机数。
正态分布随机数:
tf.random_normal(shape, mean=平均值,stddev=标准差,seed=随机种子)

均匀分布随机数:
tf.random_uniform(shape,minval=下边界,maxval=上边界,dtype=数据类型,seed=随机种子)

每个参数的含义,都在上面写明了。其中,随机种子是产生伪随机数的一种,当设置了相同的随机种子后,每次运行得到的随机数都相同。

准备数据

通过准备x数据,y数据,其中为了数据的略显杂乱,加入了一些噪音数据,也即噪点。

# 上接

# 1.准备数据
x_data = np.linspace(-2.0, 2.0, 50)[:, np.newaxis]

# 添加一些噪点
noise = np.random.normal(0.0, 0.1, x_data.shape)
y_data = x_data ** 2 + noise
搭建模型

按照预先设计的神经网络:输入层 — 隐藏层(1层)— 输出层,所以搭建模型这一步骤中,我们加入了:
一个隐藏层hidden_layer1 = add_layer(xs, 1, 20, activation_func=tf.nn.sigmoid),这一层有20个神经元,且这一层使用的激励函数为tf.nn.sigmoid。当然,你也可以使用其他激励函数tf.nn.tanh或者tf.nn.reLu,来对比下他们的拟合效果。

一个输出层prediction = add_layer(hidden_layer1, 20, 1, activation_func=None),这一层只有一个神经元,即:预测值。另外,这一层没有使用激励函数。

神经网络学习的目标:就是通过减少损失loss或cost: loss = tf.reduce_mean(tf.reduce_sum(tf.square(prediction - ys), reduction_indices=[1]))使用均方误差来计算的损失函数。

提示:均方误差是指参数估计值与参数真值之差平方的期望值; 可以评价数据的变化程度,其值越小,说明预测模型描述实验数据具有更好的精确度。

本步骤的完整代码如下:

# 上接

# 2.搭建模型
xs = tf.placeholder(dtype=tf.float32, shape=[None, 1])
ys = tf.placeholder(dtype=tf.float32, shape=[None, 1])

# 隐藏层:这一层有20个神经元
hidden_layer1 = add_layer(xs, 1, 20, activation_func=tf.nn.sigmoid)

# 输出层:这一层只有一个神经元,即:预测值
prediction = add_layer(hidden_layer1, 20, 1, activation_func=None)

# 损失函数
loss = tf.reduce_mean(tf.reduce_sum(tf.square(prediction - ys), reduction_indices=[1]))

# 假设学习率为: 0.1
learning_rate = 0.1

# 梯度下降优化器,让损失最小化
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)

# 初始化tensor flow中的变量
init = tf.global_variables_initializer()

# 画图
figure = plt.figure()
ax = figure.add_subplot(1, 1, 1)
ax.scatter(x_data, y_data)
plt.grid(True)
# 连续画图像
plt.ion()
plt.show()

注意:

  1. 本示例,采用的是梯度下降优化器,让损失最小化: tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)。传入的学习率,通常是个小数,通常不同的学习率对最终的学习效果是有影响的,且不同的模型影响不同。开发过程中,可以修改学习率的大小,来看看具体的影响。

2.tensorflow中必须对变量进行显示初始化:tf.global_variables_initializer(),否则在会话中运行会报错。

3.由于x、y的值需要根据后面的值来确定,所以用了tensorflow中的占位。

训练模型

训练模型,必须在tensorflow中的Session会话的上下文中进行。因为涉及多次训练,我们设计了一个循环。每学习200次后打印一下损失值,并且更新拟合的图像。

# 3.训练模型
with tf.Session() as sess:
    sess.run(init)
  
    for i in range(2000):
        sess.run(train_step, feed_dict={xs: x_data, ys: y_data})
        if i % 200 == 0:

            # 打印一下损失值
            print(sess.run(loss, feed_dict={xs: x_data, ys: y_data}))

            # 拿到预测值,方便后面画图像
            prediction_value = sess.run(prediction, feed_dict={xs: x_data})

            # 异常处理
            try:
                ax.lines.remove(lines[0])
            except Exception as result:
                print(result)
                pass

            # 用实线画出拟合结果
            lines = ax.plot(x_data, prediction_value, color="red", linewidth=2)
            plt.pause(0.2)

运行结果如下:

name 'lines' is not defined

0.4657365
0.10333648
0.061281133
0.04103751
0.03180971
0.026741847
0.023417206
0.021100197
0.019451708

《6.构建神经网络》 学习效果图

说明:
1.name 'lines' is not defined是捕捉到的异常。因为第一次删除实线的图像时,我们还没有绘制,所以有异常抛出,被我们捕捉到了。

2.打印剩余的信息,就是每学习200次后打印一下损失值。可见,损失是由最初的0.4657365逐渐降到了0.019451708。

3.通过学习效果图,可以看到,最初偏离数据很多,随着学习次数增多,拟合的效果也越来越好。

小结

本文通过谷歌的深度学习框架TensorFlow,来搭建一个自己的简单的神经网络。

更多了解,可关注微信公众号:人人懂编程

《6.构建神经网络》 微信公众号:人人懂编程

    原文作者:TensorFlow开发者
    原文地址: https://www.jianshu.com/p/cf039c77b9c5
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞