鸢尾花BP算法实现 Python

楼下的蓝鸢尾花 和 它的果实

  

映射关系:

120\times 4 

train

120条数据,4个特征值

4\times 10 

W1

 

120\times 10

arrY1

隐藏层为10层

10\times 3 

W2

120\times 3 

arrY2

每一条数据,有3种输出结果

测试数据,输入层权重隐藏层权重输出层

输入层到隐藏层:y_1=x*w_1,arrY_1=sigmoid(y_1)

隐藏层到输出层:y2=arrY2*w_2,arrY_2=sigmoid(y2), sigmoid=\frac{1}{1+e^{-x}}

损失函数Loss(w_1,w_2)=\frac{1}{2}(trainL-arrY_2)^2

trainL为测试集的真实标签,arrY_2是预测的标签

对w1,w2进行更新,使用批量梯度下降,梯度即偏导数,需要根据损失函数对其分别求偏导\frac{\partial Loss(w_1,w_2)}{\partial w_1},\frac{\partial Loss(w_1,w_2)}{\partial w_2}

更新w_1-=studyRate*\frac{\partial Loss(w_1,w_2)}{\partial w_1}, w_2-=studyRate*\frac{\partial Loss(w_1,w_2)}{\partial w_2},学习率是0.9,学习率即步长。

没有设置偏置,如果设置了偏置,对偏置也需要进行更新,类似对权重的更新。

 

# -*- coding: UTF-8 -*-
import numpy as np
from numpy import *#解决引入array is not defined
import math
import random
import csv
import pandas as pd
import datetime
e=2.71828183
#定义隐藏层,输出结果,特征值
h1,re,f=10,3,4
#训练数据120条,测试数据30条
trainNum,testNum=120,30
#学习率0.9
studyRate=0.9
#开始测试
def testBP(testData,testLabel,w1T,w2T):
    y1=np.dot(testData,w1)
    derivativeY1=np.zeros((testNum,h1))
    arrY1,derivativeY1=derivative(y1,derivativeY1)
    y2=np.dot(arrY1,w2)
    derivativeY2=np.zeros((testNum,re))
    arrY2,derivativeY2=derivative(y2,derivativeY2)
    predictResult=[]

    count=0
    predictWrong={}
    for i in range(len(arrY2)):
        listY2=arrY2[i].tolist()
        predictValue=max(listY2)
        result=listY2.index(predictValue)
        predictResult.append (result)
        if(result==testLabel[i]):
            count+=1
        else:#将正确结果、预测错误的结果存入字典中
            predictWrong[i]={"the correct ":testLabel[i],"the predict":result}
    #输出错误预测的个数
    print("the wrong predict numbers are:",testNum-count)
    #返回预测结果,正确率,和预测错误的数据的字典
    return predictResult,(count+0.0)/testNum,predictWrong
#对列表中的每个元素求sigmoid(),和求出其导数,sigmoid()的导数为自身*(1-自身),返回sigmoid()和其导数
def derivative(arr,deri):
    for i in range(len(arr)):
        for j in range(len(arr[0])):
             arr[i][j]=sigmoid(arr[i][j])
             deri[i][j]=arr[i][j]*(1-arr[i][j])
    return arr,deri
#开始训练,w1和w2在每次训练后都有更新
def statrTrain(trainData,trainL,w1,w2):
    y1=np.dot(trainData,w1)
    derivativeY1=np.zeros((trainNum,h1))

    arrY1,derivativeY1=derivative(y1,derivativeY1)
    #arrY1作为隐藏层的输入
    y2=np.dot(arrY1,w2)
    derivativeY2=np.zeros((trainNum,re))
    #隐藏层输出,对每个元素求sigmoid()和其导数
    arrY2,derivativeY2=derivative(y2,derivativeY2)
    #以上得到预测的结果arrY2
    #反向传播
    #根据损失函数Loss对w2求导,使用批量梯度下降
    derivativeW2=np.multiply(-(trainL-arrY2)/trainData.shape[1],derivativeY2)

    #根据损失函数Loss对w1求导
    derivativeW1=np.multiply(np.dot(derivativeW2,w2.T),derivativeY1)
    '''不能把w2的更新放在上面的语句上面,我就栽这个地方,调了很久,因为对w1求导时,w2应该还未更新,如果把上面的语句放在求derivativeW1之上,会影响到derivativeW1的求值,因为用到了w2的值,w2的跟新应该放在w1求导之后'''
    #更新w1 w2
    w2-=studyRate*np.dot(arrY1.T,derivativeW2)
    w1-=studyRate*np.dot(trainData.T,derivativeW1)

    loss=1/2.0 *sum(np.multiply(trainL-arrY2,trainL-arrY2))
    #计算损失函数
    return w1,w2,loss
#归一化处理
def regulate(data):
    data=(data-data.min())/(data.max()-data.min())
    return data
def sigmoid(x):
    #return (1.0/(1.0+exp(-x)))#overflow encountered in exp x导致溢出
    return .5 * (1 + np.tanh(.5 * x))
#one hot 编码
def oneHot(lable,num):
    matrixL=[[0.01,0.01,0.01] for i in range(num)]
    #若以上代码为matrixL=[0.01,0.01,0.01]*num,为浅拷贝,每一列的地址相同,那么在后面 matrixL[i][j-1]=0.99中,每一列的值都相同了
    #matrixL=np.zeros(10,4)
    i=0
    for j in lable:

        j=int(j)
        matrixL[i][j]=0.99
        i+=1
    return matrixL

if __name__=='__main__':
    #pandas读取csv文件
    #trainTable=pd.read_table(trainCsv,sep=',')
    trainCsv="F:\ANN\iris_training.csv"
    testCsv="F:\ANN\iris_test.csv"
    trainD=pd.read_csv(trainCsv)
    trainD=array(trainD)
    trainData=trainD[:,0:4]#读取列表的前四列,前四列为鸢尾花的特征值
    trainL=trainD[:,-1]#读取列表的最后一列,最后一列为标签内容

    testD=pd.read_csv(testCsv)
    testD=array(testD)
    testData=testD[:,0:4]
    testL=testD[:,-1]
#随机生成权重
    w1=2*np.random.random((f,h1))-1#生成(-1,1)之间的大小为(f,h1)的随机数列表,使之在y轴左右分布
    w2=2*np.random.random((h1,re))-1
#one hot编码对训练集的标签
    trainLOneHot=oneHot(trainL,len(trainL))

#训练集和测试集数据归一化处理
    train=regulate(trainData)
    test=regulate(testData)
#训练1000次,每次的权重都有更新
    for i in range(1000):
        w1,w2,loss=statrTrain(train,trainLOneHot,w1,w2)
    print("the loss is:",loss)
    predictResult,correctRate,predictWrong=testBP(test,testL,w1,w2)
    print("the correct rate is",correctRate)
    print("the wrong predict:\n",predictWrong)

没有设置偏置,对预测结果影响很小。最后显示第23条数据是预测错误的,正确的结果为1,预测是2。

数据集链接:https://pan.baidu.com/s/13sM2Ui1XKsuOYj5CY8e9UA,提取码:xopc

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
鸢尾花是一个常用的机器学习分类问题,而BP神经网络是一种常用的分类算法。下面是一个用Python编写的BP算法解决鸢尾花分类问题的示例: 首先,我们需要导入必要的模块,如numpy和pandas: ```python import numpy as np import pandas as pd ``` 然后,我们读取鸢尾花的数据集,可以使用pandas的read_csv函数: ```python data = pd.read_csv('iris.csv') ``` 接下来,我们将数据集分为特征和标签,特征为花萼长度、花萼宽度、花瓣长度和花瓣宽度,而标签为鸢尾花的类别: ```python features = data.iloc[:, 0:4].values labels = data.iloc[:, 4].values ``` 然后,我们将标签进行独热编码,将其转化为向量的形式: ```python from sklearn.preprocessing import LabelEncoder encoder = LabelEncoder() labels = encoder.fit_transform(labels) ``` 接下来,我们需要将数据集划分为训练集和测试集,可以使用train_test_split函数: ```python from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(features, labels, test_size=0.2) ``` 然后,我们需要定义神经网络的结构和参数: ```python input_size = 4 hidden_size = 6 output_size = 3 learning_rate = 0.1 epochs = 1000 ``` 接下来,我们可以开始构建神经网络模型: ```python class NeuralNetwork: def __init__(self, input_size, hidden_size, output_size): self.input_size = input_size self.hidden_size = hidden_size self.output_size = output_size self.W1 = np.random.randn(self.input_size, self.hidden_size) self.W2 = np.random.randn(self.hidden_size, self.output_size) def forward(self, X): self.z = np.dot(X, self.W1) self.z2 = self.sigmoid(self.z) self.z3 = np.dot(self.z2, self.W2) self.output = self.sigmoid(self.z3) def sigmoid(self, s): return 1 / (1 + np.exp(-s)) def sigmoid_derivative(self, s): return s * (1 - s) def backward(self, X, y): self.error = y - self.output self.delta = self.error * self.sigmoid_derivative(self.output) self.W2 += np.dot(self.z2.T, self.delta) self.delta2 = np.dot(self.delta, self.W2.T) * self.sigmoid_derivative(self.z2) self.W1 += np.dot(X.T, self.delta2) def train(self, X, y): self.forward(X) self.backward(X, y) def predict(self, X): self.forward(X) return np.argmax(self.output, axis=1) ``` 最后,我们可以训练并测试神经网络模型: ```python np.random.seed(0) model = NeuralNetwork(input_size, hidden_size, output_size) for epoch in range(epochs): model.train(X_train, y_train) y_pred = model.predict(X_test) from sklearn.metrics import accuracy_score accuracy = accuracy_score(y_test, y_pred) print("准确率:", accuracy) ``` 通过以上步骤,我们就完成了用Python编写BP算法解决鸢尾花分类问题的过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值