神经网络多层感知器异或问题求解-学习篇

多层感知器可以解决单层感知器无法解决的异或问题

首先给了四个输入样本,输入样本和位置信息如下所示,现在要学习一个模型,在二维空间中把两个样本分开,输入数据是个矩阵,矩阵中有四个样本,样本的维度是三维,三个维度分别表示偏置,x坐标,y坐标。对应的标签Y是 区分矩阵中的样本,例如:1,0,0对应0,1,0,1对应1,以此类推。使用单层感知器无法解决此异或问题,怎么样使用多层感知器求解这个问题?

python 复制代码
#输入数据 各维度表示偏置,x坐标,y坐标
X = np.array([[1,0,0],
              [1,0,1],
              [1,1,0],
              [1,1,1]])
#标签
Y = np.array([[0,1,1,0]])
#第一个网络层参数矩阵,初始化输入层权值,取值范围-1 到 1
V = (np.random.random((3,4)) - 0.5) * 2
#第二个网络层参数矩阵,初始化输入层权值,取值范围-1 到 1
W = (np.random.random((4,1)) - 0.5) * 2
使用误差反向传播算法原理

算法原理:

误差反向传播算法的基本思想是通过两个过程来实现神经网络的训练:信号的正向传播与误差的反向传播。

正向传播: 输入一个训练样本,通过神经网络的前向传播计算出输出结果。具体来说,从输入层开始,计算每一层节点的输出值,直到得到网络最终的输出结果。每一层节点的输出都是基于前一层的输出和当前层的权重、偏置计算得到的。
误差反向传播: 将输出结果与实际结果进行比较,计算出误差。然后,将误差从输出层向输入层反向传播,计算每个节点对误差的贡献,并根据贡献值调整每个节点的权重和偏置。这个过程是通过链式法则实现的,即利用误差的梯度信息来逐层调整权重和偏置。

算法步骤:
初始化: 随机初始化神经网络的权重和偏置。
输入训练样本对: 将训练样本输入到神经网络的输入层。
前向传播: 根据当前的权重和偏置,计算每一层节点的输出值,直到得到网络最终的输出结果。
计算网络输出误差: 将输出结果与实际结果进行比较,计算出误差。误差的计算通常使用损失函数,如均方误差、交叉熵损失等。
反向传播: 根据误差计算每个节点对误差的贡献,并将此贡献值反向传播回去。具体来说,对于每个输出节点,计算其误差,然后将此误差沿着连接线进行反向传播,直到到达输入层的节点。
调整权重和偏置: 根据误差贡献值,对每个权重和偏置进行调整。调整的方法通常是使用梯度下降算法,即根据误差的梯度信息来更新权重和偏置。
检查网络总误差: 检查网络的总误差是否达到精度要求。如果满足,则训练结束;如果不满足,则返回步骤2,继续训练过程。

接下来我们进行一下公式迭代:




根据上面的计算,我们就可以求得Wji的参数

下面使用Python解决多层感知器异或问题

python 复制代码
import numpy as np
import matplotlib.pyplot as plt

#输入数据
X = np.array([[1,0,0],
              [1,0,1],
              [1,1,0],
              [1,1,1]])
#标签
Y = np.array([[0,1,1,0]])
#第一个网络层参数矩阵,初始化输入层权值,取值范围-1 到 1
V = (np.random.random((3,4)) - 0.5) * 2
#第二个网络层参数矩阵,初始化输入层权值,取值范围-1 到 1
W = (np.random.random((4,1)) - 0.5) * 2

def get_show():
    #正样本
    all_positive_x = [0,1]
    all_positive_y = [0,1]
    #负样本
    all_negative_x = [0,1]
    all_negative_y = [1,0]

    plt.figure()
    plt.plot(all_positive_x, all_positive_y,'bo')
    plt.plot(all_negative_x, all_negative_y,'yo')
    plt.xlabel('x')
    plt.ylabel('y')
    plt.show()

#get_show()

lr = 0.11  #学习率
#激活函数(从0-1)
def sigmoid(x):
    return 1/(1+np.exp(-x))
#激活函数的导数
def dsigmoid(x):
    x = x*(1-x)
    return x
#更新权值(2个权值矩阵,V和W)
def update():
    global X,Y,V,W,lr
    L1 = sigmoid(np.dot(X,V))  #隐藏层输出(4*3)x(3*4)=(4,4)
    L2 = sigmoid(np.dot(L1,W))  #输出层输出(4,4)x(4*1)=(4,1)
    L2_delta = (Y.T - L2) * dsigmoid(L2) #输出层的误差=下一层的误差*激活函数导数*与下一层的连接权重矩阵(全为1)
    L1_delta = L2_delta.dot(W.T)*dsigmoid(L1) #隐藏层的误差=下一层的误差*激活函数导数*与下一层的连接权重矩阵
    W_C = lr*L1.T.dot(L2_delta)
    V_C = lr*X.T.dot(L1_delta)
    W = W + W_C #对W矩阵的参数更新 模型的学习
    V = V + V_C #对V矩阵的参数更新

errors = []  #记录误差
for i in range(100000):
    update() #更新权值
    if i % 1000 == 0: #输出误差
        L1 = sigmoid(np.dot(X,V))
        L2 = sigmoid(np.dot(L1,W))
        errors.append(np.mean(np.abs(Y.T-L2)))
        print("Error:",np.mean(np.abs(Y.T-L2)))
plt.plot(errors)
plt.ylabel('Errors')
plt.show()

L1 = sigmoid(np.dot(X, V))  # 隐藏层输出(4*3)x(3*4)=(4,4)
L2 = sigmoid(np.dot(L1, W))  # 输出层输出(4,4)x(4*1)=(4,1)
print(L2) #第二层的结果 概率矩阵 》0.5是一类,小于05是一类

def classify(x):
    if x > 0.5:
        return 1
    else:
        return 0

for i in map(classify, L2): #L2一共4个数
    print(i)

运行结果为:

python 复制代码
#是与 标签Y = np.array([[0,1,1,0]]) 趋向一致的
[[0.01011728]
 [0.98925078]
 [0.99013233]
 [0.01323669]]
0
1
1
0
相关推荐
Hello数据集17 分钟前
医疗AI实战:如何利用免疫与内分泌系统疾病数据集训练高精度预测模型?
人工智能·机器学习·数据挖掘·医疗ai
雪碧聊技术19 分钟前
什么是AI辅助编程?一文详解
人工智能·ai辅助编程
qq_5710993520 分钟前
学习周报四十九
学习
一锅炖出任易仙21 分钟前
创梦汤锅学习日记day34
学习·游戏引擎
m0_图灵灵23 分钟前
吴恩达《深度学习》之看懂 ResNet
人工智能·深度学习·学习笔记
AI客栈26 分钟前
AI 大模型网关架构:动态限频与负载均衡设计实战
人工智能
暗黑小白30 分钟前
第二篇:不碰模型,意图识别快 9 倍 —— P0→P1→P2 流水线设计
人工智能·架构·ai agent
半导体守望者31 分钟前
AE AZX射频调谐器射频负载匹配(调谐)原理PPT
学习·机器人·自动化·制造·模块测试
happyprince34 分钟前
07_verl-Trainer模块详解
人工智能·架构·wpf·强化学习
花骨朵轻创37 分钟前
基于WeChatBot框架 API 封装的 Python SDK,提供简洁易用的接口调用方式
人工智能