一、基础

 1. 经典的BP神经网络通常由三层组成:输入层、隐含层与输出层。通常输入层神经元的个数与特征数相关,输出层的个数与类别数相同, 隐含层的层数与神经元数均可以自定义。

在这里插入图片描述

 2. 每个神经元代表对数据的一次处理:

在这里插入图片描述

二、代码

2.1 说明

在这里插入图片描述

在这里插入图片描述

2.2 源代码

import numpy as np

np.random.seed(1)  # 随机种子,使得每次随机产生的weight都是一样的

# 输入层到隐藏层的权重 范围是[-1,1] 表示3个输入,4个神经元
w1 = 2 * np.random.random((3, 4)) - 1
# 隐藏层到输出层的权重 范围是[-1,1] 表示4个神经元,1个输出
w2 = 2 * np.random.random((4, 1)) - 1

# sigmoid激活函数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))
# sigmoid激活函数的导数
def derivative(x):
    return sigmoid(x) * (1 - sigmoid(x))

# 前向传播,根据输入值以及当前权重得每一层的输出
def fp(x):
    z1 = np.dot(x, w1)  # 汇聚第一层的输入
    l1 = sigmoid(z1)  # 经过第一层激活函数
    z2 = np.dot(l1, w2)  # 汇聚第二层的输入
    l2 = sigmoid(z2)  # 经过第二层激活函数
    return l1, l2

# 反向传播,根据输入以及预测的值,计算增量,以便于更新权重
# l1,l2指第一层和第二层神经网络输出
def bp(y, x, l1, l2):
    l2_error = l2 - y  # 实际上是MSE对第二层神经元输出的导数
    l2_slope = l2 * (1 - l2)  # 实际上是sigmoid函数的输出对输入的导数
    l2_delta = np.dot(l1.T, l2_error * l2_slope)

    l1_error = np.dot(l2_error * l2_slope, w2.T)  # 实际上是MSE对第一层神经元输出的导数
    l1_slope = l1 * (1 - l1)
    l1_delta = np.dot(x.T, l1_error * l1_slope)

    return l1_delta, l2_delta


def main():
    global w1
    global w2
    x = np.array([[0, 0, 1],
                  [0, 1, 1],
                  [1, 0, 1],
                  [1, 1, 1],
                  [0, 0, 0],
                  [0, 1, 0],
                  [1, 0, 0],
                  [1, 1, 0]])
    # y转置成列向量
    y = np.array([[0, 1, 1, 0, 0, 1, 1, 0]]).T

    learning_rate = 20
    # 训练网络
    for it in range(1000):
        l1, l2 = fp(x)  # 前向传播,得到第一层和第二层的输出
        l1_delta, l2_delta = bp(y, x, l1, l2)  # 反向传播,得到增量,用于更新权重
        w2 -= learning_rate * l2_delta
        w1 -= learning_rate * l1_delta

    print(fp([[1, 0, 0]])[1])
    print(fp([[0, 0, 0]])[1])

if __name__ == '__main__':
    main()
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐