单层感知网络是最初的神经网络,具有模型清晰、结构简单、计算量小等优点,但是它无法处理非线性问题。BP神经网络具有任意复杂的模式分类能力和优良的多维函数映射能力,解决了简单感知器不能解决的异或问题和一些其他问题。
神经网络可以包含:
BP神经网络——最简单的
深度学习——可以看作复杂的BP神经网络解决范围更广
其他神经网络
人工神经网络的结构特点
☞非线性:自然界的普遍特性
☞非局限性:一个神经网络通常由多个神经元广泛连接而成。系统的整体行为取决于单元之间的相互作用、相互连接。
☞非常定性:人工神经网络具有自适应、自组织和自学习能力。系统本身一直在演化。
☞非凸性:非凸性是指这种函数有多个极值,因此系统具有多个较平稳的平衡态,这将导致系统演化的多样性。
✦神经网络模型主要有的4种类型:前向型、反馈型、随机型、竞争型
人工神经网络
一般来说,神经网络学习算法要能正常工作,激活函数F应当是可导和光滑的,比如:线性函数、逻辑斯蒂函数
单层神经网络
包括输入、权重、输出
单层神经网络的主要区别在于输出向量z,输出元的数量多于1时,即认为z是向量。
g(W*a)=z
双层神经网络
单层神经网络无法解决异或问题,增加一个计算层后,不仅可以解决异或问题,而且具有非常好的非线性分类效果。
在神经网络的每个层次中,除了输出层外,都会含有一个偏置单元
多层神经网络
“深度信念网络”,即“深度学习”包含的过程
“预训练”——让神经网络中的全职找到一个接近最优解的值。
“微调”——对整个网络进行优化训练。
多层神经网络中,输出也是按照一层一层的方式来计算的。
增加更多的层次有什么优势?
1、能够更深入地表示特征,更强的表现函数的模拟能力。
2、随着网络层数的增加,每一层对于前一层次的抽象表示更深入。
BP神经网络
BP神经网络是一种非线性多层前向反馈网络。BP神经网络般分为三层,分别是输入层、隐含层和输出层,这三层中的每一层的神经元状态只影响下一层的神经元状态,若预测结果得不到期望输出,网络则进行反向传播。主要思路是:输入数据,利用反向传播算法对网络的权值和阈值不断地进行调整训练,根据预测误差调整权值和阈值,输出与期望趋近的结果,直到预测结果可以达到期望。
BP神经网络对输入数据的处理步骤如下:
(1)初始化网络。初始化输入层和隐含层,以及输出层神经元之间的连接权值ωij,ωjk,初始化隐含层和输出阈值a,b,并设置学习率和激活函数
(2)计算隐含层输出。ωij,a分别为输入层和隐含层间的连接权值及隐含层阈值,隐含层输出H的计算为:
l为隐含层激活函数
(3)计算输出层。H为隐含层的输出,BP网络的预测输出Y为:
(4) 计算误差。误差e的计算为:
Ok是实际期望的值
(5)更新权值
η是学习率
(6)阈值更新。根据预测误差e更新网络的阈值a,b:
(7)判断迭代是否可以结束,若算法迭代没有结束,则返回第(2)步,直到算法结束。
!!!第(1)步到第(3)是信号的前馈过程,第(4)步到第(7)步是神经网络反向更新参数的过程。
通过TensorFlow实现BP神经网络
# -*- coding: utf-8 -*-
"""
Created on Mon Oct 31 11:50:53 2022
@author: Yangz
"""
#import tensorflow as tf
from numpy.random import RandomState
import tensorflow.compat.v1 as tf
#tensorflow版本原因2.0往上的用这种方式
tf.compat.v1.disable_eager_execution()
'''
定义神经网络的参数、输入、输出节点
Variable()函数,在TensorFlow的世界里,变量的定义和初始化是分开的,所有关于图变量的赋值和计算
都要通过tf.Session的run来进行。想要将所有图变量进行集体初始化时应该使用
tf.global_variables_initializer。
placeholder()函数是在神经网络构建graph的时候在模型中的占位,此时并没有把要输入的数据传入模型,
它只会分配必要的内存。等建立session,在会话中,运行模型的时候通过feed_dict()函数向占位符喂入数据。
'''
#定义训练数据的大小,是每次的训练数据
batch_size = 10
#声明w1变量,生成2*3的矩阵,均值为0,标准差为1
w1 = tf.Variable(tf.random.normal([2,3],mean=0,stddev=1,seed=1))
#声明w2变量,生成3*1的矩阵,均值为0,标准差为1
w2 = tf.Variable(tf.random.normal([3,1],mean=0,stddev=1,seed=1))
#定义输入x和输出y_
x = tf.placeholder(tf.float32,shape=(None,2),name="x-input")
y_ = tf.placeholder(tf.float32,shape=(None,1),name="y-output") #实际期望值,后面是Y
'''
定义前向传播过程
'''
#前向传播
a = tf.matmul(x, w1) #矩阵乘法
y = tf.matmul(a, w2) #网络预测值
'''
定义损失函数
'''
#tf.clip_by_value(a,b,c)a是一个矩阵,b是最小值,c是最大值;这个方法是控制a里面的值。
#如果里面的值小于b,输出b,大于c就输出c
cross_entropy = - tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y,1e-10,1.0))) #对数损失函数
'''
定义反向传播算法,修正权重w,偏置a,和学习率
'''
#AdamOptimizer是TensorFlow中实现Adam(自适应矩估计)算法的优化器。
#是一个寻找全局最优点的优化算法,引入了二次梯度校正。 0.001是权重的更新比率
#利用反向传播算法对权重和偏置项进行修正,同时也在运行中不断修正学习率
#.minimize(loss_function)的含义是根据其损失量学习自适应,损失量大则学习率大,
#进行修正的角度越大,损失量小,修正的幅度也小,学习率就小,但是不会超过自己所设定的学习率。
train_step = tf.train.AdamOptimizer(0.001).minimize(cross_entropy)
'''
生成模拟数据集,用于训练神经网络
'''
rdm = RandomState(1) #定义一个随机数种子
#数据量大小为128
dataset_size = 128
X = rdm.rand(dataset_size,2) #产生[0,1)之间的数组128*2
Y = [[int(x1 + x2 <1)] for (x1,x2) in X] #Y是与X所对应的存放布尔类型值的list,留为实际值
'''
创建一个会话来运行TensorFlow程序,其实这里只是查看了一下w1、w2,
不创建会话的情况下误差执行上面Tensorflow生成语句
'''
#可以理解为TensorFlow下定义的语句不会立即执行,只有等到开启会话session时,才会执行session.run()语句
with tf.Session() as sess:
#初始化变量,只有在定义了变量之后才可以初始化
#init_op = tf.initialize_all_variables() 已被弃用
init_op = tf.global_variables_initializer()
sess.run(init_op) #
#输出目前(未经训练)的参数取值
print(sess.run(w1))
print(sess.run(w2))
print("\n")
'''
最后训练模型,得到训练后的参数结果
'''
#设定训练轮数
STEPS = 5000
#训练的循环
for i in range(STEPS):
#每次只训练10个样本数据
start = (i * batch_size) % dataset_size
end = min(start + batch_size,dataset_size)
#利用feed_dict喂入数据
sess.run(train_step,feed_dict = {x:X[start:end],y_:Y[start:end]})
if i % 1000 == 0:
#每隔1000轮,计算在所有数据上的交叉熵并输出
total_cross_entropy = sess.run(cross_entropy,feed_dict={x:X,y_:Y})
print('After %d training step(s),cross_entropy on all data is %g' % (i,total_cross_entropy))
#输出训练后的参数取值
print(sess.run(w1))
print(sess.run(w2))
print("\n")