新手python之BP神经网络——手写公式推导+可运行代码+编程中遇到的问题

python,现在临近毕业也逐渐意识到这门语言的重要性,后悔不能当初把它学好(悔不当初)!!!
本文原来是matlab的,编写过常用的机器学习代码,现在转型python,希望大家看了我写的新手代码,不要嘲笑!!
学了一段时间python,自己尝试编写的第一个算法——BP神经网络,并将应用到鸢尾花数据集上,数据集连接如下:
鸢尾花数据集iris0.txt

数据集集已经进行了处理,属于纯纯的0-1问题分类(二分类问题),

先说一说在编写过程中遇到的问题,程序已经附在最后了

1、程序的模块化

在写程序的程序的时候,应当尽可能的将程序进行模块分割,一方面看起来简洁,另一方面,也会提高程序的可阅读。通常情况下,将固定功能的程序和高频重复调用次数,进行封装成单个函数。个人感觉程序模块分割可能需要考虑如下几点:
1、模块的功能是否固定,
2、封装的函数的通用性,不可能每个程序都需要重新修改封装好的函数
3、调用的次数,个人感觉对于大型程序的话,这一点比较重要

2、函数包的导入,如numpy random

对于初次接触python的来说,函数包真的是很头疼的问题,很多包都不知道什么意思,也不知道自己需要的在那个包中,
我常用的方式:
1、将光标放在报错的位置
在这里插入图片描述
2、同时按下快捷键:alt+enter,系统会进行提示,点击第一个选项,系统会自动导入工具包
在这里插入图片描述
导入前:
在这里插入图片描述
操作后:
在这里插入图片描述

3、文件的打开方式和读取方式

1、打开方式
file=open(‘filename.txt’,‘type’)

filename:代表文件的名字,注意需要加上文件的类型,如.txt,.dat 等等
type:代表的是对文件进行的操作,如 r:只读,w:只写,r+:可读可写等等,目前,我还用不到o(╥﹏╥)o

2、读取方式
file.read():默认读取文件中的每一行元素,并单独输出,这有点像readlines
在这里插入图片描述
file.readline():表示,支队数据的第一行读取,并将第一行中的每个元素单独进行保存,空格也不放过。
在这里插入图片描述
file.readlines():表示对数据进行按行读取,并将每一行进行保存成列表
在这里插入图片描述

4 错误:TypeError: slice indices must be integers or None or have an index method

这边表示列表在切片时的索引必须是整数才行,如,在训练集和测试集的分配过程,矩阵的数据获取,进行经常性忽略列表中数据的类型。

#按比例划分训练集和测试集
    trainset = dataset_temp[: int(len(dataset_temp)*ratio)]
    testset = dataset_temp[int(len(dataset_temp)*ratio) + 1:]
5 随机数的参数方式

随机数在网络参数初始化过程中,会经常使用,需要注意的是,需要导入random和numpy包

import random
import numpy as np

如下:
np.random.uniform(lower, upper, (size)):产生随机数,类型为浮点型,可指定上下界,指定产生随机数的大小

    input_hidden_weight = np.random.uniform(lower, upper, [num_input, num_hidden])
    hidden_bais = np.random.uniform(lower, upper, [1, num_hidden])
    hidden_output_weight = np.random.uniform(lower, upper, [num_output, num_hidden])
    output_bais = np.random.uniform(lower, upper, [1, num_output])

np.random.randint(lower, upper, (size)):产生指定范围的整数

5 np.mat 函数

该函数的功能主要是将列表,转化成矩阵,方便后面的计算

6 列表之间的乘运算

np.dot(sample1, sample2):将两个列表或者矩阵相乘,并将计算后的结果求和。该方法遵循矩阵之间运算法则

hidden_input = np.dot(input_data, input_hidden_weight).astype(np.float)

np.multiply(sample1, sample2):两个向量或者矩阵之间,进行点对点的相乘,返回相同大小的矩阵或者列表。

temp3 = np.multiply(error, device_sigmoid).astype(np.float)
7 错误:TypeError: Cannot cast array data from dtype(‘float64’) to dtype(’<U32’) according to the rule ‘safe’

主要是说的计算类型或者赋值类型错误,此时需要进行数据类型转化
也就是再出现错误的位置后面添加:.astype(np.float),根据自己的需要,改变数据类型

为方便阅读和验证,手写推导图敬上:

在这里插入图片描述

python之BP神经网络代码

'''
BP 神经网络分为如下几个部分:
1 数据读取预处理部分
2 网络参数预处理部分
3 激活函数部分
4 参数训练部分
5 模型性能测试部分
6 主函数部分

'''

import random
import numpy as np

# 1 数据读取预处理部分
def dataset_open(address, ratio):
    #读取样本数据
    dataset = open(address)
    # dataset = random.shuffle
    #建立空的列表用于存放,训练集特征和标签,测试集特征和标签
    train_feature = []
    train_label = []
    test_feature = []
    test_label = []

    dataset_temp = []
    #将数据集进行随机打乱
    for i in dataset.readlines():
        temp1 = i.strip().split()
        dataset_temp.append([temp1[j] for j in range(len(temp1))])
        random.shuffle(dataset_temp)
    #按比例划分训练集和测试集
    trainset = dataset_temp[: int(len(dataset_temp)*ratio)]
    testset = dataset_temp[int(len(dataset_temp)*ratio) + 1:]
    #将训练集和测试集存放到相应的列表中
    for i in trainset:
        train_feature.append([i[j] for j in range(len(i) - 1)])
        train_label.append(i[-1])
    for i in testset:
        test_feature.append([i[j] for j in range(len(i) - 1)])
        test_label.append(i[-1])
        # data_feature.append([temp[j] for j in range(len(temp)-1)]) #同上

    return train_feature, train_label, test_feature, test_label


# 2 网络参数预处理部分
def parameter_proprocess(num_input, num_hidden, num_output, lower, upper):
    #初始化产生相应大小的权重和偏置
    input_hidden_weight = np.random.uniform(lower, upper, [num_input, num_hidden])
    hidden_bais = np.random.uniform(lower, upper, [1, num_hidden])
    hidden_output_weight = np.random.uniform(lower, upper, [num_output, num_hidden])
    output_bais = np.random.uniform(lower, upper, [1, num_output])

    return input_hidden_weight, hidden_bais, hidden_output_weight, output_bais


# 3 激活函数部分
def sigmoid(input):
    result = 1 / (1 + np.exp(input))
    return result


# 4 参数训练部分
def training(train_set, train_label, input_hidden_weight, hidden_bais, hidden_output_weight, output_bais, num_iter, step_size):

    for k in range(num_iter):
        for i in range(len(train_set)):
            #将输入的数据从训练集中单独提取出来
            input_data = np.mat(train_set[i]).astype(np.float)
            #计算相应的隐层输入,隐层输出,输出层输入,输出层输出
            hidden_input = np.dot(input_data, input_hidden_weight).astype(np.float)
            hidden_output = sigmoid(hidden_input + hidden_bais).astype(np.float)
            output_input = np.dot(hidden_output, np.transpose(hidden_output_weight)).astype(np.float)
            output = sigmoid(output_input + output_bais).astype(np.float)

            #参数更新
            device_sigmoid = np.dot(output, 1-output).astype(np.float)
            error = float(output) - float(train_label[i])
            temp3 = np.multiply(error, device_sigmoid).astype(np.float)

            #输出层权重
            delta_beta = np.multiply(temp3, hidden_output).astype(np.float)
            #输出层阈值
            delta_b2 = temp3
            #隐层阈值
            temp4 = np.multiply(hidden_output, np.array(1-hidden_output)).astype(np.float)
            temp5 = np.multiply(temp4, hidden_output_weight).astype(np.float)
            delta_b1 = np.multiply(temp5, temp3).astype(np.float)
            # 隐层权重
            delta_w = np.multiply(np.transpose(input_data), delta_b1).astype(np.float)

            #加入步长,更新策略
            input_hidden_weight += delta_w * float(step_size)
            hidden_bais += delta_b1 * float(step_size)
            hidden_output_weight += delta_beta * float(step_size)
            output_bais += delta_b2 * float(step_size)

        return input_hidden_weight, hidden_bais, hidden_output_weight, output_bais

#测试集编程
def testing(test_set, test_label, input_hidden_weight, hidden_bais, hidden_output_weight, output_bais):
    count = 0
    for i in range(len(test_set)):
        #测试集数据输入
        input_data = np.mat(test_set[i]).astype(np.float)
        #模型在测试集上的计算结果
        hidden_input = np.dot(input_data, input_hidden_weight).astype(np.float)
        hidden_output = sigmoid(hidden_input + hidden_bais).astype(np.float)
        output_input = np.dot(hidden_output, np.transpose(hidden_output_weight)).astype(np.float)
        output = sigmoid(output_input + output_bais).astype(np.float)
        # 二分类问题,取0.5作为类别分界线,考虑到不平衡问题的同学,可自行设计
        if output > 0.5:
            output = 1
        else:
            output = 0
        #统计预测正确的数量
        if output == int(test_label[i]):
            count += 1
    #计算预测正确的比例
    accuracy = count / len(test_set)

    return accuracy

#模型超参数设置
num_input=4
num_hidden=100
num_output=1
lower=-1
upper=1
num_iter=100
step_size = 0.01
ratio = 0.8
#函数的调用
train_feature, train_label, test_feature, test_label = dataset_open('iris0.txt', ratio)
input_hidden_weight, hidden_bais, hidden_output_weight, output_bais = parameter_proprocess(num_input, num_hidden, num_output, lower, upper)

training(train_feature, train_label, input_hidden_weight, hidden_bais, hidden_output_weight, output_bais, num_iter, step_size)
accuracy = testing(test_feature, test_label, input_hidden_weight, hidden_bais, hidden_output_weight, output_bais)

print(accuracy)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值