手写bpnn算法实现iris多分类

这是一个关于机器学习的实验作业,详细介绍了如何从零开始编写BP神经网络(BPNN)算法来实现鸢尾花数据集的多分类任务。代码包括sigmoid激活函数、层的构建、前向传播、反向传播等关键步骤,并通过matplotlib绘制损失曲线。最终,通过调整网络结构和训练轮数,实现了训练集上的预设精度,并给出了测试集上的分类准确率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

手写bpnn算法实现iris多分类

东北大学工业智能专业机器学习实验的一个作业,手写bpnn,我实在是写不出来,在网上参考了github大神的代码,再自己修改一下得到了要的代码。
原代码地址:https://github.com/RiptideBo/simpy/blob/master/deep_learning/models/bpnn.py

import numpy as np
import matplotlib.pyplot as plt


def sigmoid(x):
    return 1 / (1 + np.exp(-1 * x))
    

class layerbuild:   #建造层

    def __init__(
        self, units, activation=None, learning_rate=None, is_input_layer=False
    ):
        """
        :param units: 每层的神经元数量,第一层必须和x的特征数相同,最后一层要和进行onehot编码后的y的特征数相同
        """
        self.units = units
        self.weight = None
        self.bias = None
        self.activation = activation
        if learning_rate is None:
            learning_rate = 0.3
        self.learn_rate = learning_rate
        self.is_input_layer = is_input_layer

    def initializer(self, back_units):
        self.weight = np.asmatrix(np.random.normal(0, 0.5, (self.units, back_units)))
        self.bias = np.asmatrix(np.random.normal(0, 0.5, self.units)).T
        #随机化权重和偏置
        if self.activation is None:
            self.activation = sigmoid

    def cal_gradient(self):
        if self.activation == sigmoid:
            gradient_mat = np.dot(self.output, (1 - self.output).T)
            gradient_activation = np.diag(np.diag(gradient_mat))
        else:
            gradient_activation = 1
        return gradient_activation

    def forward_propagation(self, xdata):
        self.xdata = xdata
        if self.is_input_layer:
            self.wx_plus_b = xdata
            self.output = xdata
            return xdata
        else:
            self.wx_plus_b = np.dot(self.weight, self.xdata) - self.bias
            self.output = self.activation(self.wx_plus_b)
            return self.output

    def backpropagation(self, gradient):
        gradient_activation = self.cal_gradient()  # i * i 维
        gradient = np.asmatrix(np.dot(gradient.T, gradient_activation))

        self._gradient_weight = np.asmatrix(self.xdata)
        self._gradient_bias = -1
        self._gradient_x = self.weight

        self.gradient_weight = np.dot(gradient.T, self._gradient_weight.T)
        self.gradient_bias = gradient * self._gradient_bias
        self.gradient = np.dot(gradient, self._gradient_x).T
        self.weight = self.weight - self.learn_rate * self.gradient_weight
        self.bias = self.bias - self.learn_rate * self.gradient_bias.T
        # 更新权重和偏置
        return self.gradient

class BPNN:

    def __init__(self):
        self.layers = []
        self.train_mse = []
    def add_layer(self, layer):
        self.layers.append(layer)

    def build(self):
        for i, layer in enumerate(self.layers[:]):
            if i < 1:
                layer.is_input_layer = True
            else:
                layer.initializer(self.layers[i - 1].units)

    def train(self, xdata, ydata, max_train_round, accuracy):
        self.max_train_round = max_train_round
        self.accuracy = accuracy
        x_shape = np.shape(xdata)
        k=0
        #k用来记录训练轮数
        for round_i in range(max_train_round):
            all_loss = 0
            k+=1
            for row in range(x_shape[0]):
                _xdata = np.asmatrix(xdata[row, :]).T
                _ydata = np.asmatrix(ydata[row, :]).T
                for layer in self.layers:
                    _xdata = layer.forward_propagation(_xdata)

                loss, gradient = self.cal_loss(_ydata, _xdata)
                all_loss = all_loss + loss
                for layer in self.layers[:0:-1]:
                    gradient = layer.backpropagation(gradient)

            mse = all_loss / x_shape[0]
            self.train_mse.append(mse)

            if mse < self.accuracy:
                print("训练集上达到预设精度,所用训练轮数为:{}轮".format(k))
                #print(self.train_mse)
                xx=np.arange(1,k+1)
                xx=xx.reshape(-1,1)
                yy=self.train_mse
                yy=np.array(self.train_mse)
                yy=yy.reshape(-1,1)
                plt.plot(xx,yy)
                plt.xlabel("train_round")
                plt.ylabel("error")
                return print("分类准确率为",1-mse)
            if k==self.max_train_round:
                print("训练集上未达到预设精度,所用训练轮数为:{}轮".format(k))
                xx=np.arange(1,k+1)
                xx=xx.reshape(-1,1)
                yy=np.array(self.train_mse)
                yy=yy.reshape(-1,1)
                plt.plot(xx,yy)
                plt.xlabel("train_round")
                plt.ylabel("error")
                plt.title("loss visualization")
                return print("分类准确率为",1-mse)
    
    def cal_loss(self, ydata, ydata_):
        self.loss = -((1-ydata.T)*np.log(1-ydata_) + ydata.T * np.log(ydata_))
        self.loss_gradient = 2 * (ydata_ - ydata)
        return self.loss, self.loss_gradient
    
    def predict(self,xdata):
        y_pred=[]
        x_shape = np.shape(xdata)
        for row in range(x_shape[0]):
            _xdata = np.asmatrix(xdata[row, :]).T
            for layer in self.layers:
                _xdata = layer.forward_propagation(_xdata)
            #print(_xdata)
            _xdata=list(_xdata)
            y_pred.append(_xdata.index(max(_xdata)))
        y_pred=np.array(y_pred)
        return y_pred

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
iris_1 = load_iris()
#加载鸢尾花数据集
x = iris_1['data']
y = iris_1['target']
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=2)
import pandas as pd
y_train=y_train.reshape(-1,1)

y_train=pd.DataFrame(y_train)
y_train.columns=['type']
y_train1 = pd.get_dummies(y_train.type, prefix='type')
y_train=np.array(y_train1)

#这四行代码是将y转化为onehot编码
#使用方法:先实例化,然后构建层
model = BPNN()
for i in (4, 10, 20, 3):
    model.add_layer(layerbuild(i))
#这里是构建层,注意,第一层的数字必须和x的特征数一样,最后一层是输出,和y的特征数一样。
#x有四个特征,所以第一个是4,y有三类,所以最后的数字是3
#中间两个是隐层,数字任选,你可以调参观察中间的数字变化对于训练轮数有何影响。
model.build()
model.train(xdata=x_train, ydata=y_train, max_train_round=500, accuracy=0.05)
print("测试集上的准确度为:",accuracy_score(model.predict(x_test),y_test))

在这里插入图片描述

这个可以实现多分类预测,如果你要预测别的数据集的话就把加载数据的部分改一下,然后记得把y转化为二维向量,就是必须要用reshape,再把y用onehot编码转换一下,这个看代码照葫芦画瓢应该能会吧。
最后,如果你也是工业智能的学生恰好刷到了这篇文章,要参考这里的代码的话,记得改一下变量名hhh

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值