第3章 多层感知器
创始人
2024-06-03 00:35:12

这章节我们来解决的问题是:如何使用神经网络实现逻辑电路中的“异或门”模型?

如下图:

根据第2章我们知道,单层感知器是能够解决“与门”、“或门”、“非门”这些简单的线性问题,但是不能解决“异或门”这类非线性问题。

1.1 解决异或门问题的思路

如果在单层感知器上增加一层,能够很好的解决异或问题。

例如网络结构如下:

我们把每一个感知器节点代表了一个分类器,那么几个节点学习到的分割线如下:

以上3个节点的组合就可以解决异或门问题。

1.2 sigmoid激活函数 -- 线性转为非线性

多层感知器中,我们期望分割面是非线性的,故选择为sigmoid为激活函数。

sigmoid表达式和曲线:

sigmoid函数也叫 Logistic 函数,取值范围为(0,1),它可以将一个实数映射到(0,1)的区间。

求导如下:

这个公式在计算梯度的时候用到。

那么采样非线性激活函数,神经网络就有可能学习到平滑的曲线来分割平面,从线性到非线性。

1.3 新的问题

按照单层感知器的权重更新,节点3的权重更新可以轻松求得;但是节点1和节点2权重的更新如何求解呢?

按照公式如下:

要求得w111必须要知道节点1的期望值,但是节点1,2的期望值不存在,不能直接求其梯度。

解决方案:误差反向传播算法(Backpropagation,BP算法)

1.4 误差反向传播算法 -- BP算法

神经网络的训练关键在于如何调整权值和阈值,采用的算法:

(1)单层感知机的算法:梯度下降算法;

(2)多层感知器的算法:误差反向传播算法(error Back Propagation),简称BP算法。

反向传播过程如下:

在多层神经网络中,从最后一层开始,逐层的反向进行误差信息传递,并更新相应权重。使用BP算法的多层前馈(向前传播方式没有回路或者环路)网络又称之为BP神经网络;

BP神经网络学习过程:

以下图来源:http://galaxy.agh.edu.pl/~vlsi/AI/backp_t_en/backprop.html

(1)以一个3层全连接网络来为例子

下面通过一个3层全连接网络来讲解,包含2个输入、2个隐藏层(第1层3个节点、第2层2个节点)、一个输出(第3层1个节点),节点计算如右图:

(2)前向传播

输入层到隐藏层的计算,即计算第一层输出y1,y2,y3

隐藏层到隐藏层的计算,即计算第2层输出y4,y5。

隐藏层到输出层,即计算输出y

(3)反向传播

反向传播,根据网络的连接路径,从输出层反向把误差项前向传递,并更新权重和偏置参数的过程。

误差项计算:将网络输出信号y与训练数据集的输出值z(期望值)进行比较,得到的差异被称为输出层神经元的误差信号d(不是均方误差,是计算梯度的某一项)。

内部神经元的误差项的计算,有2种情况:

<1>误差权重:即前向传播的权重;

<2>如果传播的误差来自多个关联神经元,它们将被叠加。

(4)权重更新

权重更新,根据网络的连接路径,从输出层反向把误差反向传递并更新权重和偏置的过程。

权重更新公式:

(5)总结

来源:http://neuralnetworksanddeeplearning.com/chap2.html

1.5 多层感知器 -- 异或门例子

异或门数据集定义:

import numpy as npdef get_xy_data():""" XOR的训练集 -- 真值表 """x = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])y = np.array([0, 1, 1, 0])return x,y

多层感知器模型定义:

import numpy as np""" 定义感知器模型结构 """
class XORGateModel():def __init__(self):""" 初始化权重、偏置 """self.w = np.random.normal(size=6).reshape((3, 2))   # 权重self.b = np.random.normal(size=3)                   # 偏置self.lr = 0.1                                       # 学习率(超参数)def sigmoid(self, x):return 1/(1 + np.exp(-x))def dsigmoid(self, x):y = self.sigmoid(x)return y * (1 - y)def forward(self, x):""" 前向计算 """y1 = self.sigmoid((x[0]*self.w[0][0]) + (x[1]*self.w[0][1]) + self.b[0])y2 = self.sigmoid((x[0]*self.w[1][0]) + (x[1]*self.w[1][1]) + self.b[1])y3 = self.sigmoid((y1*self.w[2][0]) + (y2*self.w[2][1]) + self.b[2])return y3def update_weight(self, x, n, d):e = (x[0] * self.w[n][0]) + (x[1] * self.w[n][1]) + self.b[n]self.w[n][0] = self.w[n][0] + (self.lr * d * self.dsigmoid(e) * x[0])self.w[n][1] = self.w[n][1] + (self.lr * d * self.dsigmoid(e) * x[1])self.b[n]    = self.b[n]    + (self.lr * d * self.dsigmoid(e))def train(self, X, Y):"""X,Y -- 训练集"""for i in range(100000):   # 迭代j = 0C = 0for xi in X:yi = self.forward(xi)               # 前向计算Ci = np.power((Y[j] - yi), 2) / 2   # 计算误差C += Ci# 更新权重跟偏置if Ci > 0:d = Y[j] - yid1 = self.w[2][0] * dd2 = self.w[2][1] * dself.update_weight(xi, 0, d1)   # 节点1self.update_weight(xi, 1, d2)   # 节点2self.update_weight(xi, 2, d)    # 节点3j += 1print("epoch{} 误差:{}, 权重:{}".format(i, C, self.w))# 什么时候退出?if C <= 0.05:print("=== 与门的4数据都正确了, 退出迭代")break

训练并保存参数:

# 训练import data_managerX, Y = data_manager.get_xy_data()  # 读取数据集model = XORGateModel()            # 实例化类对象model.train(X, Y)               # 执行训练# 验证训练结果是否正确for xi in X:print("验证  输入:{}   模型的前向计算结果:{}".format(xi, model.forward(xi)))# 保存模型参数np.savez("./params", model.w, model.b)

读取参数并预测:

import numpy as npif __name__ == "__main__":# 加载参数r = np.load("./params.npz")print("权重", r["arr_0"])print("偏置", r["arr_1"])# 设置参数到网络结构import modeland_model = model.AndGateModel()and_model.w = r["arr_0"]and_model.b = r["arr_1"]# 预测X = [[0,0], [0, 1], [1, 0], [1, 1]]for xi in X:print("预测  输入:{}  结果:{}".format(xi, and_model.forward(xi)))

代码地址:https://download.csdn.net/download/qq_21386397/87567645

有帮助,一键三连哦~~~~~~~~~~~~~~~~~~~~~~~~

相关内容

热门资讯

猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...