利用前馈神经网络(参数自拟)解决异或问题(python实现)

0. 问题

异或问题(exclusive OR, XOR、 EOR、 EX-OR)。 1969 年, Marvin Minsky 出版《感知器》一书,指出了神经网络的两个关键缺陷: 一是感知器无法处理 “异或” 回路问题; 二是当时的计算机无法支持处理大型神经网络所需要的计算能力。这些论断使得人们对以感知器为代表的神经网络产生质疑, 并导致神经网络的研究进入了十多年的 “冰河期”。可以认为感知器是一层前馈神经网络(不含输入层)。试利用两层前馈神经网络(不含输入层)解决异或问题, 要求在测试集上准确率 100%。具体地,神经网络的训练集和测试集相同, 均为 S = {(1, 0, 1), (1, 1, 0), (0, 0, 0), (0, 1, 1)}, 其中每个数据的第三维是 label。

1. 问题分析

题目中指出,感知机(一层前馈神经网络)无法实现异或问题,这主要是因为一层前馈神经网络只能表示线性空间,而异或问题属于非线性空间内的问题。
由数字电路知识可知,异或门可通过与门、与非门、或门进行配置,如图所示。
在这里插入图片描述
而根据感知机(一层前馈神经网络)的知识可知,与门、与非门、或门均可以通过一层神经网络实现。因此可以推知,异或门可以通过两层前馈神经网络实现。

2. 实现步骤

首先列出与门、与非门、或门、异或门的真值表,如图所示。
在这里插入图片描述
由于真值表逻辑简单,因此不需要训练神经网络,直接设置权重与偏置来构建两层神经网络。
根据真值表构建的两层前馈神经网络如图所示。

在这里插入图片描述
此神经网络的激活函数选用的是阶跃函数,神经网络各层的权重和偏置可见下面的公式。
在这里插入图片描述
据此可以先利用python构造出阶跃函数,初始化神经网络,构造前馈函数。

import numpy as np

def step_function(x):
    y = x > 0
    return y.astype(np.int)

def init_network():
    network = {
    
    }
    network['W1'] = np.array([[-0.5, 0.5], [-0.5, 0.5]])
    network['b1'] = np.array([0.7, -0.2])
    network['W2'] = np.array([0.5, 0.5])
    network['b2'] = np.array([-0.7])
    
    return network

def forward(network, x):
    W1, W2 = network['W1'], network['W2']
    b1, b2 = network['b1'], network['b2']
    
    NAND_OR = step_function(np.dot(x, W1) + b1)
    XOR = step_function(np.dot(NAND_OR, W2) + b2)    
    
    return XOR

最后便可将测试集S = {(1, 0, 1), (1, 1, 0), (0, 0, 0), (0, 1, 1)}输入至构建好的两层前馈神经网络中,并将输出结果与测试集中的label进行比较,最终得到准确率。

network = init_network()
s_test = np.array([[1, 0, 1], [1, 1, 0], [0, 0, 0], [0, 1, 1]])

y = []
accuracy_cnt = 0
for i in range(0, 4):
    y.append(forward(network, s_test[i, 0:2]))
    if y[i] == s_test[i, 2]:
        accuracy_cnt += 1
print('accuracy:', str(accuracy_cnt / len(s_test)))

3. 实验结果和分析

代码运行后的输出结果如图所示。
在这里插入图片描述
如图所示,构建的两层前馈神经网络解决了异或问题,并且,在测试集上的准确率为100%。

4. 源代码

XOR.py

# -*- coding: utf-8 -*-
"""
Created on Wed Dec 23 20:30:24 2020

@author: jiawei
"""

import numpy as np

def step_function(x):
    y = x > 0
    return y.astype(np.int)

def init_network():
    network = {
    
    }
    network['W1'] = np.array([[-0.5, 0.5], [-0.5, 0.5]])
    network['b1'] = np.array([0.7, -0.2])
    network['W2'] = np.array([0.5, 0.5])
    network['b2'] = np.array([-0.7])
    
    return network

def forward(network, x):
    W1, W2 = network['W1'], network['W2']
    b1, b2 = network['b1'], network['b2']
    
    NAND_OR = step_function(np.dot(x, W1) + b1)
    XOR = step_function(np.dot(NAND_OR, W2) + b2)    
    
    return XOR

network = init_network()
s_test = np.array([[1, 0, 1], [1, 1, 0], [0, 0, 0], [0, 1, 1]])

y = []
accuracy_cnt = 0
for i in range(0, 4):
    y.append(forward(network, s_test[i, 0:2]))
    if y[i] == s_test[i, 2]:
        accuracy_cnt += 1
print('accuracy:', str(accuracy_cnt / len(s_test)))

猜你喜欢

转载自blog.csdn.net/mahoon411/article/details/112299993