用BP神经网络解决异或问题

初步的神经网络入门分为三篇

1:神经网络简析

2:Back Propagation算法

3:用BP神经网络解决异或问题

这一篇主要是讲解一下关于用BP神经网络解决异或问题

对于我们的输入

[0,0],[0,1],[1,0],[1,1]

对于我们的输出

0或1

这里我们需要借用上一篇文章的一张图片

扫描二维码关注公众号,回复: 9223658 查看本文章

构建双层神经网络

#导入numpy
import numpy as np

#先定义训练数据
train_X = np.array([[0,0],[0,1],[1,0],[1,1]])
train_Y = np.array([0,1,1,0])

#线性连接层
class LinearLayer:
    def __init__(self, input_D, output_D):
        self._W = np.random.normal(0, 0.1, (input_D, output_D))#权值
        self._b = np.random.normal(0, 0.1, (1,output_D))#偏置
        self._grad_W = np.zeros((input_D,output_D))#权值梯度
        self._grad_b = np.zeros((1,output_D))#偏置梯度

    def forward(self, X):
        return np.matmul(X, self._W) + self._b#前馈传播时,计算每个变量输出
    #逆向传播,计算梯度,更新权重和偏置
    def backward(self, X, grad):
        self._grad_W = np.matmul(X.T, grad)#权值梯度计算
        self._grad_b = np.matmul(grad.T, np.ones(X.shape[0]))#偏置梯度计算
        return np.matmul(grad, self._W.T)#这里是根据矩阵计算的,所以行和列必须匹配
    #更新权值和偏置,learn_rate是学习率
    def update(self, learn_rate):
        self._W = self._W - self._grad_W * learn_rate
        self._b = self._b - self._grad_b * learn_rate

#规则P其实可以是Sigmoid函数
class P:
    def __init__(self):
        pass
    def forward(self, X):
        return np.where(X < 0, 0, X)
    def backward(self, X, grad):
        return np.where(X>0, X, 0) * grad

#创建线性关系1,激活函数,线性关系2
linear1 = LinearLayer(2,3)
p = P()
linear2 = LinearLayer(3,1)
#神经网络模型
model = [linear1, p, linear2]
#预测函数
def predict(model, X):
    tmp = X
    for layer in model:
        tmp = layer.forward(tmp)
    return np.where(tmp > 0.5, 1, 0)

print("----------")
result = predict(model, train_X)

#最小均方误差
def MSEloss(train_Y, y):
    assert train_Y.shape == y.shape
    return np.linalg.norm(train_Y - y) ** 2

#训练网络
for i in range(50000):

    #先来前向传播,获取每个值
    o0 = train_X
    a1 = linear1.forward(o0)
    o1 = p.forward(a1)
    a2 = linear2.forward(o1)
    o2 = a2

    #根据前馈算法,来计算loss
    y = o2.reshape(o2.shape[0])
    loss = MSEloss(train_Y, y)

    #反向传播更新参数
    grad = (y-train_Y).reshape(result.shape[0], 1)
    grad = linear2.backward(o1,grad)
    grad = p.backward(a1, grad)
    grad = linear1.backward(o0, grad)

    learn_rate = 0.001

    #更新参数
    linear1.update(learn_rate)
    linear2.update(learn_rate)

    #判断学习是否完成
    if i% 200 == 0:
        print(loss)
    if loss < 0.001:
        print("训练完成")
        break

print("预测数据1")
print(train_X)
print("预测结果")
print(result)

我们这里可以看到的,除了numpy,其他的都没用,上面这个代码只是让我们更清楚BP算法过程。

甚至MSEloss都是自己写的。不过没有必要,其实pytorch都已经有现成的,我们可以直接用就是

下面就来看看pytorch版本

import torch.nn as nn
import torch.optim as optim
import torch
from torch.autograd import Variable
import numpy as np


#
#
#pytorch
#
#
#先定义训练数据
train_X = np.array([[0,0],[0,1],[1,0],[1,1]])
train_Y = np.array([[0],[1],[1],[0]])
#准备数据
x = torch.from_numpy(train_X).type(torch.FloatTensor)
y = torch.from_numpy(train_Y).type(torch.FloatTensor)
print(x)
print(y)
x = Variable(x)
y = Variable(y)

#模型
class BpNet(nn.Module):
    def __init__(self, n_input, n_hiden, n_output):
        super(BpNet, self).__init__()
        #两层线性模型2-》3-》1
        self.hidden = nn.Linear(n_input, n_hiden)
        self.out = nn.Linear(n_hiden, n_output)
    def forward(self, x):
        # x = nn.functional.sigmoid(x)
        # x = self.hidden(x)
        # x = self.out(nn.functional.sigmoid(x))
        #这里使用relu激活函数,没有使用sigmoid
        x = self.hidden(x)
        x = self.out(nn.functional.relu(x))
        return x
#创建模型,两层神经网络
net = BpNet(n_input=2, n_hiden=3, n_output=1)
print(net)
#损失函数
criterion = nn.MSELoss()
#优化器
optimizer = optim.SGD(net.parameters(), lr=0.08)

# plt.ion()
for t in range(10000):
    out = net(x)
    loss = criterion(out, y)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    print(loss)
    print(out.size())
    print(y.size())
    print(out)
    print(y)

训练结果,发现有两个接近于0,其他的为1

发布了66 篇原创文章 · 获赞 31 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_43272605/article/details/103334831