三层BP神经网络Python代码实现

数据集使用iris数据集

# 开发时间:2021/11/5 15:07
import numpy as np
import math
import random
import string
import matplotlib as mpl
import matplotlib.pyplot as plt
import pandas
from pandas import read_csv
from sklearn.preprocessing import LabelEncoder             # 编码
from sklearn.model_selection import train_test_split


# 导入数据
iris = pandas.read_csv('http://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data', header=None)
iris.columns=['SepalLengthCm', 'SepalWidthCm', 'PetalLengthCm', 'PetalWidthCm', 'Species']

size_mapping = {'Iris-virginica': 2,            # 001
                'Iris-versicolor': 1,           # 010
                'Iris-setosa': 0}               # 100
iris['Species'] = iris['Species'].map(size_mapping)
arrary = iris.values

a = arrary[:100, :]
b = arrary[100:, :]
c = arrary[:100, 4]


# 独热编码
def onehot(targets, num_out):
    onehot = np.zeros((num_out, targets.shape[0]))
    for idx, val in enumerate(targets.astype(int)):
        onehot[val, idx] = 1.
    return onehot.T

# 生成一个矩阵,大小为m*n,并且设置默认零矩阵
def makematrix(m, n, fill=0.0):
    a = []
    for i in range(m):
        a.append([fill] * n)
    return a


# 函数sigmoid(),采用tanh,
def sigmoid(x):
    return math.tanh(x)


# 函数sigmoid的派生函数
def derived_sigmoid(x):
    return 1.0 - x ** 2

class BPNN:
    def __init__(self, num_in, num_hidden, num_out):
        self.num_in = num_in+1
        self.num_hidden = num_hidden+1
        self.num_out = num_out

        self.active_in = [1.0] * self.num_in
        self.active_hidden = [1.0] * self.num_hidden
        self.active_out = [1.0] * self.num_out

        self.wight_in = makematrix(self.num_in, self.num_hidden)
        self.wight_out = makematrix(self.num_hidden, self.num_out)

        # 对权值矩阵赋初值
        for i in range(self.num_in):
            for j in range(self.num_hidden):
                self.wight_in[i][j] = np.random.normal(0.0, pow(self.num_hidden,-0.5))  # 5x4 输出num_in行,num_hidden列权重矩阵,随机生成满足正态分布的权重
        for i in range(self.num_hidden):
            for j in range(self.num_out):
                self.wight_out[i][j] = np.random.normal(0.0, pow(self.num_out, -0.5))

                # 最后建立动量因子(矩阵)
        self.ci = makematrix(self.num_in, self.num_hidden)
        self.co = makematrix(self.num_hidden, self.num_out)

    def update(self, inputs):
        if len(inputs) != self.num_in - 1:
            raise ValueError('与输入层节点数不符')

        # 数据输入输入层
        for i in range(self.num_in - 1):
            # self.active_in[i] = sigmoid(inputs[i])  #或者先在输入层进行数据处理
            self.active_in[i] = inputs[i]  # active_in[]是输入数据的矩阵

        # 数据在隐藏层的处理
        for i in range(self.num_hidden-1):
            sum = 0.0
            for j in range(self.num_in):
                sum = sum + self.active_in[j] * self.wight_in[j][i]
            self.active_hidden[i] = sigmoid(sum)  # active_hidden[]是处理完输入数据之后存储,作为输出层的输入数据

        # 数据在输出层的处理
        for i in range(self.num_out):
            sum = 0.0
            for j in range(self.num_hidden):
                sum = sum + self.active_hidden[j] * self.wight_out[j][i]
            self.active_out[i] = sigmoid(sum)
        return self.active_out[:]

    def errorbackpropagate(self, targets, lr, m):  # lr是学习率, m是动量因子
        if len(targets) != self.num_out:
            raise ValueError('与输出层节点数不符!')

        # 首先计算输出层的误差
        out_deltas = [0.0] * self.num_out
        for i in range(self.num_out):
            error = targets[i] - self.active_out[i]
            out_deltas[i] = derived_sigmoid(self.active_out[i]) * error

        # 然后计算隐藏层误差
        hidden_deltas = [0.0] * self.num_hidden
        for i in range(self.num_hidden):
            error = 0.0
            for j in range(self.num_out):
                error = error + out_deltas[j] * self.wight_out[i][j]
            hidden_deltas[i] = derived_sigmoid(self.active_hidden[i]) * error

        # 首先更新输出层权值
        for i in range(self.num_hidden):
            for j in range(self.num_out):
                change = out_deltas[j] * self.active_hidden[i]
                self.wight_out[i][j] = self.wight_out[i][j] + lr * change + m * self.co[i][j]
                self.co[i][j] = change

        # 然后更新输入层权值
        for i in range(self.num_in):
            for j in range(self.num_hidden):
                change = hidden_deltas[j] * self.active_in[i]
                self.wight_in[i][j] = self.wight_in[i][j] + lr * change + m * self.ci[i][j]
                self.ci[i][j] = change

        # 计算总误差
        error = 0.0
        for i in range(self.num_out):
            error = error + 0.5 * (targets[i] - self.active_out[i]) ** 2
        return error

    def train(self, a, itera=1000, lr=0.1, m=0.1):
        for i in range(itera):
            error = 0.0
            for j in range(100):
                inputs = a[j, 0:4]
                d = onehot(c, self.num_out)
                targets = d[j, :]
                self.update(inputs)
                error = error + self.errorbackpropagate(targets, lr, m)
            if i % 100 == 0:
                print('误差 %-.5f' % error)

    def test(self, b):
        for i in range(b.shape[0]):
            print(b[i, 0:4], '->', self.update(b[i, 0:4]))

    # 权重
    def weights(self):
        print("输入层权重")
        for i in range(self.num_in):
            print(self.wight_in[i])
        print("输出层权重")
        for i in range(self.num_hidden):
            print(self.wight_out[i])


def Mytrain():
    a = iris.values
    # 创建神经网络,4个输入节点,X个隐藏层节点,1个输出层节点
    n = BPNN(4, 8, 3)
    # 训练神经网络
    n.train(a)
    n.weights()
    n.test(b)

if __name__ == '__main__':
    Mytrain()

  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

odd~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值