Python 基于多层感知器的异或分类

Python 基于多层感知器的异或分类,python,machine-learning,neural-network,xor,perceptron,Python,Machine Learning,Neural Network,Xor,Perceptron,我想实现一个多层感知器。 我在GitHub上发现了一些对MNIST分类很好的代码(96%)。但是,由于某些原因,它不能处理XOR任务。 我想知道原因。 代码如下: 感知器 随机导入 将numpy作为np导入 类感知器: 定义初始值(自、*、层大小、激活函数、成本函数): self.layer\u size=层大小 如果透镜(自身层大小)-1!=len(激活功能): 提升值错误(“…”) 自激活功能=激活功能 self.cost\u function\u deriv=cost\u function

我想实现一个多层感知器。
我在GitHub上发现了一些对MNIST分类很好的代码(96%)。但是,由于某些原因,它不能处理XOR任务。
我想知道原因。
代码如下:

感知器

随机导入
将numpy作为np导入
类感知器:
定义初始值(自、*、层大小、激活函数、成本函数):
self.layer\u size=层大小
如果透镜(自身层大小)-1!=len(激活功能):
提升值错误(“…”)
自激活功能=激活功能
self.cost\u function\u deriv=cost\u function\u deriv
self.biases=[np.random.randn(y,1)表示层大小[1:]
self.weights=[np.random.randn(y,x)表示拉链中的x,y(层大小[:-1],层大小[1:])]
def序列(自我、训练数据、测试数据、时代、小批量、lr):
测试数据长度=长度(测试数据)
对于范围内的历元(历元):
随机洗牌(训练数据)
小批量=[训练数据[x:x+小批量大小]
对于范围内的x(0,len(训练数据),最小批量大小)]
对于mini_批次中的mini_批次:
mb_len=len(小批量)
梯度_权重=[自权重中w的np.zero(w.shape)]
梯度_偏差=[自偏差中b的np.零(b.形状)]
对于小批量中的x、y:
增量梯度偏差,增量梯度权重=自反向传播(np.数组(x),y)
渐变权重=[渐变+渐变增量,拉链中的增量(渐变权重,渐变权重)]
梯度偏差=[梯度+增量表示梯度,增量表示压缩(梯度偏差,增量梯度偏差)]
自重=[w-(lr/mb长度)*w的梯度,拉链的梯度(自重,梯度重量)]
自偏差=[b-(lr/mb_len)*b的梯度,zip中的梯度(自偏差,梯度_偏差)]
正确答案=自我。有多少正确答案(测试数据)
打印(f“历元编号{Epoch}:{正确答案}/{测试数据}正确答案”)
def反向传播(自、x、y):
梯度_b=[自偏压中b的np.零(b.形状)]
梯度w=[np.零(w.形状)表示自权重中的w]
激活=[x]
上一次激活=x
对于枚举中的i,(b,w)(zip(自偏压,自权重)):
当前激活=自激活功能[i](np.dot(w,前激活)+b)
activations.append(当前\u激活)
上一次激活=当前激活
delta=self.cost\u function\u deriv(激活[-1],y)*self.activation\u functions[-1].deriv(激活[-1])
梯度_b[-1]=δ
梯度w[-1]=np.dot(增量,激活[-2].T)
对于范围内的i(2,len(自层大小)):
z=激活[-i]
act_der=self.activation_函数[-i+1].deriv(z)
delta=np.dot(自身权重[-i+1].T,delta)*动作顺序
梯度_b[-i]=δ
梯度w[-i]=np.dot(增量,激活[-i-1].T)
#正常索引变量:
#对于范围内的i(透镜(自层)-1,0,-1):
#z=激活[i]
#act_der=self.activation_函数[i].deriv(z)
#delta=np.dot(自身权重[i].T,delta)*作用顺序
#梯度_b[i-1]=δ
#梯度w[i-1]=np.dot(增量,激活[i-1].T)
返回梯度b,梯度w
def前馈(自,a):
对于枚举中的i,(b,w)(zip(自偏压,自权重)):
a=自激活函数[i](np.dot(w,a)+b)
归还
定义正确答案的数量(自我、测试数据):
k=0
对于测试数据中的x,y:
y_predict=np.argmax(自前馈(x))
打印(y_,y)
k+=int(y_=y)
返回k
main.py

从复制导入deepcopy
将numpy作为np导入
从感知器导入感知器
乙状结肠类:
out\u min\u max=[0,1]
定义调用(self,x):
返回1./(1.+np.exp(-x))
def deriv(自我,y):
#t=self(x)
#返回t*(1.-t)
返回y*(1.-y)
def成本函数导数(y预测,y真实标签):
label_vector=np.zero(y_.shape)
label\u vector[y\u true\u label]=1.0
返回y_预测-标签_向量
def main():
训练数据=np.asarray([[0],[0]],0],,
[[[0], [1]], 1],
[[[1], [0]], 1],
[[[1], [1]], 0]])
图层大小=[2,8,2]
模型=感知器(层大小=层大小,
激活函数=[Sigmoid(),Sigmoid()],
成本函数导数=成本函数导数)
模型列车(deepcopy(列车数据),
deepcopy(培训数据),
纪元=10000,
最小批量大小=4,
lr=0.01)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
main()
格式为“y_predict y_true”的最终输出(在每个历元之后):
0 0
01
01
0 0

如果删除random.shuffle(训练数据),则:
10
01
11
0 0

但不是0 1 1 0

我明白了。它需要以下几点

mini\u批量大小=1
#随机.洗牌(训练数据)--注释
epochs=10000
最好这样做:

lr=0.1
在大多数情况下,结果是在大约1000个时代之后获得的:
0 0
11
11
0 0