手写bp神经网络分类鸾尾花数据集,以及bp的推导

59 篇文章 0 订阅
17 篇文章 0 订阅

bp的算法的推导:

神经网络代码如下:

import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split

iris = datasets.load_iris()
train_data, test_data, train_label, test_label = train_test_split(iris.data, iris.target, test_size=0.2,random_state=0)
train_label = train_label.reshape(120,1)
'''
搭建神经网络
    输入有四个特征
    第一层设置20个神经元
    第二层设置10个神经元
    输出有3个
'''
#初始化权值 -1 到 1
V = np.random.random((4,20))*2-1  #输入到第一层
W = np.random.random((20,10))*2-1
K = np.random.random((10,1))*2-1  #第二层到输出(train_label 数值为0 1 2,通过输出预测)

#定义一些参数
loop = 500 #最大迭代轮数
l = 0.001 #学习率

#激函数
def sigmoid(x):
    return 1/(1+np.exp(-x))

#更新
def update():
    global loop
    global train_data, train_label, V, W, K
    #前向传播过程
    y1 = sigmoid(np.dot(train_data,V))
    y2 = sigmoid(np.dot(y1,W))
    o = sigmoid(np.dot(y2,K))

    #误差反向传播过程
    '''
    下面这个是数组的乘法:
        矩阵的乘法和加法
    矩阵的乘法和加法和线性代数的矩阵加法和乘法一致,运算符号也一样用*,**表示平方,例如e**2 =e*e。
        数组的加法和乘法
    数组的乘法和加法为相应位置的数据乘法和加法。
    '''
    o_delta = (train_label - o) * o * (1-o)
    y2_delta = np.dot(o_delta, K.T) * y2 * (1-y2)
    y1_delta = y2_delta.dot(W.T) * y1 * (1-y1)

    K = K + l * np.dot(y2.T, o_delta)
    W = W + l * np.dot(y1.T, y2_delta)
    V = V + l * np.dot(train_data.T, y1_delta)

#迭代
for i in range(0,loop):
    update()
    if i%100 == 0:
        y1 = sigmoid(np.dot(train_data, V))
        y2 = sigmoid(np.dot(y1, W))
        o = sigmoid(np.dot(y2, K))
        print("error:")
        print(np.mean(train_label - o.T))


#训练好的模型在训练集上的表现
y1 = sigmoid(np.dot(train_data,V))
y2 = sigmoid(np.dot(y1,W))
o = sigmoid(np.dot(y2,K))
#对输出的o进行处理
for i in range(0,len(o)):
    if(o[i] < 0.5):
        o[i] = 0
    elif(o[i] > 1.5):
        o[i] = 2
    else:
        o[i] = 1
count = 0
sum = 0
for i in range(0,len(o)):
    if(o[i] == train_label[i]):
        count +=1
    sum+=1
print('Accuracy in train dataset %f' % (count/sum))

#训练好的模型在测试集上的表现
y1 = sigmoid(np.dot(test_data,V))
y2 = sigmoid(np.dot(y1,W))
o = sigmoid(np.dot(y2,K))
#对输出的o进行处理
for i in range(0,len(o)):
    if(o[i] < 0.5):
        o[i] = 0
    elif(o[i] > 1.5):
        o[i] = 2
    else:
        o[i] = 1
count = 0
sum = 0
for i in range(0,len(o)):
    if(o[i] == test_label[i]):
        count +=1
    sum += 1
print("Accuracy in test dataset %f" % (count/sum))

结果为:

 

可以看到,准确率很低,这时候需要调整参数,比如学习率,迭代次数,每层神经元或者层数等等。第一层增加到40个神经元,迭代轮数增加到1000

 

结果为:

 

比之前好很多,但还是很低,比昨天用sklearn的神经网络低太多了。 后来想了想,sigmod函数输出是0-1之间,而鸾尾花数据集的标签是0,1,2,也就是这个模型根本无法预测出2类型的花。所以进行改动,把标签标准化一下,除以二,然后对输出的处理改为<0.4认为是0类被,>0.7认为是1类别。结果很好:

修改后的代码为:

import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split

iris = datasets.load_iris()
train_data, test_data, train_label, test_label = train_test_split(iris.data, iris.target, test_size=0.2,random_state=0)
train_label = train_label.reshape(120,1)/2 #因为神经网络输出都是0-1,所以给它标准化
test_label = test_label/2
'''
搭建神经网络
    输入有四个特征
    第一层设置20个神经元
    第二层设置10个神经元
    输出有3个
'''
#初始化权值 -1 到 1
V = np.random.random((4,40))*2-1  #输入到第一层
W = np.random.random((40,10))*2-1
K = np.random.random((10,1))*2-1  #第二层到输出(train_label 数值为0 1 2,通过输出预测)

#定义一些参数
loop = 3000 #最大迭代轮数
l = 0.001 #学习率

#激函数
def sigmoid(x):
    return 1/(1+np.exp(-x))

#更新
def update():
    global loop
    global train_data, train_label, V, W, K
    #前向传播过程
    y1 = sigmoid(np.dot(train_data,V))
    y2 = sigmoid(np.dot(y1,W))
    o = sigmoid(np.dot(y2,K))

    #误差反向传播过程
    '''
    下面这个是数组的乘法:
        矩阵的乘法和加法
    矩阵的乘法和加法和线性代数的矩阵加法和乘法一致,运算符号也一样用*,**表示平方,例如e**2 =e*e。
        数组的加法和乘法
    数组的乘法和加法为相应位置的数据乘法和加法。
    '''
    o_delta = (train_label - o) * o * (1-o)
    y2_delta = np.dot(o_delta, K.T) * y2 * (1-y2)
    y1_delta = y2_delta.dot(W.T) * y1 * (1-y1)

    K = K + l * np.dot(y2.T, o_delta)
    W = W + l * np.dot(y1.T, y2_delta)
    V = V + l * np.dot(train_data.T, y1_delta)

#迭代
for i in range(0,loop):
    update()
    if i%100 == 0:
        y1 = sigmoid(np.dot(train_data, V))
        y2 = sigmoid(np.dot(y1, W))
        o = sigmoid(np.dot(y2, K))
        print("error:")
        print(np.mean(train_label - o.T))


#训练好的模型在训练集上的表现
y1 = sigmoid(np.dot(train_data,V))
y2 = sigmoid(np.dot(y1,W))
o = sigmoid(np.dot(y2,K))
#对输出的o进行处理
for i in range(0,len(o)):
    if(o[i] < 0.4):
        o[i] = 0
    elif(o[i] > 0.7):
        o[i] = 1
    else:
        o[i] = 0.5
count = 0
sum = 0
for i in range(0,len(o)):
    if(o[i] == train_label[i]):
        count +=1
    sum+=1
print('Accuracy in train dataset %f' % (count/sum))

#训练好的模型在测试集上的表现
y1 = sigmoid(np.dot(test_data,V))
y2 = sigmoid(np.dot(y1,W))
o = sigmoid(np.dot(y2,K))

#对输出的o进行处理
for i in range(0,len(o)):
    if(o[i] < 0.4):
        o[i] = 0
    elif(o[i] > 0.7):
        o[i] = 1
    else:
        o[i] = 0.5
count = 0
sum = 0
for i in range(0,len(o)):
    if(o[i] == test_label[i]):
        count +=1
    sum += 1
print("Accuracy in test dataset %f" % (count/sum))

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值