异或问题(exclusive OR, XOR、 EOR、 EX-OR)。 1969 年, Marvin Minsky 出版《感知器》一书,指出了神经网络的两个关键缺陷: 一是感知器无法处理 “异或” 回路问题; 二是当时的计算机无法支持处理大型神经网络所需要的计算能力。这些论断使得人们对以感知器为代表的神经网络产生质疑, 并导致神经网络的研究进入了十多年的 “冰河期”。可以认为感知器是一层前馈神经网络(不含输入层)。试利用两层前馈神经网络(不含输入层)解决异或问题, 要求在测试集上准确率 100%。具体地,神经网络的训练集和测试集相同, 均为 S = {(1, 0, 1), (1, 1, 0), (0, 0, 0), (0, 1, 1)}, 其中每个数据的第三维是 label。
题目中指出,感知机(一层前馈神经网络)无法实现异或问题,这主要是因为一层前馈神经网络只能表示线性空间,而异或问题属于非线性空间内的问题。
由数字电路知识可知,异或门可通过与门、与非门、或门进行配置,如图所示。
而根据感知机(一层前馈神经网络)的知识可知,与门、与非门、或门均可以通过一层神经网络实现。因此可以推知,异或门可以通过两层前馈神经网络实现。
首先列出与门、与非门、或门、异或门的真值表,如图所示。
由于真值表逻辑简单,因此不需要训练神经网络,直接设置权重与偏置来构建两层神经网络。
根据真值表构建的两层前馈神经网络如图所示。
此神经网络的激活函数选用的是阶跃函数,神经网络各层的权重和偏置可见下面的公式。
据此可以先利用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)))
代码运行后的输出结果如图所示。
如图所示,构建的两层前馈神经网络解决了异或问题,并且,在测试集上的准确率为100%。
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)))