Python 模式识别数据集分析与BP神经网络实现
Python 模式识别数据集分析与BP神经网络实现
本代码示例展示了使用Python进行模式识别数据集分析,包括数据预处理、特征提取、BP神经网络模型训练和评估。
导入库
import pandas as pd
from pandas import DataFrame
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
import numpy as np
import math
import random
from sklearn.model_selection import KFold
from sklearn.metrics import confusion_matrix, roc_curve, auc
import matplotlib.pyplot as plt
数据读取与处理
# 读取Excel表
data = pd.read_excel(r'C:\Users\86158\PycharmProjects\pythonProject1\2023模式识别数据集汇总.xlsx')
# 归一化函数
def maxminnorm(array):
maxcols = array.max(axis=0)
mincols = array.min(axis=0)
data_shape = array.shape
data_rows = data_shape[0]
data_cols = data_shape[1]
t = np.empty((data_rows, data_cols))
for i in range(data_cols):
t[:, i] = (array[:, i] - mincols[i]) / (maxcols[i] - mincols[i])
return t
# 数据集读取与处理
def loadDataset(filepath):
'''加载数据集,对数据进行预处理,并打乱数据集
filepath: 数据集文件存放路径
'''
pydata = pd.read_excel(r'C:\Users\86158\PycharmProjects\pythonProject1\2023模式识别数据集汇总.xlsx')
# 填充缺省值--用各列平均数补全
pydata['鞋码'] = pydata['鞋码'].fillna(pydata['鞋码'].mean())
pydata['50米成绩'] = pydata['50米成绩'].fillna(pydata['50米成绩'].mean())
pydata['肺活量'] = pydata['肺活量'].fillna(pydata['肺活量'].mean())
data = pydata.dropna()
data = data.iloc[:, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]].values
dataset = data[:, [1, 3, 4, 5, 6, 7]]
dataset = np.array(dataset)
dataset = maxminnorm(dataset)
return dataset
BP神经网络实现
def fun_z(weights, inputs):
'''计算神经元的输入:z = weight * inputs + b
:param weights: 网络参数(权重矩阵和偏置项)
:param inputs: 上一层神经元的输出
:return: 当前层神经元的输入
'''
bias_term = weights[-1]
z = 0
for i in range(len(weights) - 1):
z += weights[i] * inputs[i]
z += bias_term
return z
def sigmoid(z):
'''激活函数(Sigmoid):f(z) = Sigmoid(z)
:param z: 神经元的输入
:return: 神经元的输出
'''
return 1.0 / (1.0 + math.exp(-z))
def sigmoid_derivative(output):
'''Sigmoid激活函数求导
:param output: 激活函数的输出值
:return: 求导计算结果
'''
return output * (1.0 - output)
def forward_propagate(network, inputs):
'''前向传播计算
:param network: 神经网络
:param inputs: 一个样本数据
:return: 前向传播计算的结果
'''
for layer in network: # 循环计算每一层
new_inputs = []
for neuron in layer: # 循环计算每一层的每一个神经元
z = fun_z(neuron['weights'], inputs)
neuron['output'] = sigmoid(z)
new_inputs.append(neuron['output'])
inputs = new_inputs
return inputs
def backward_propagate_error(network, actual_label):
'''误差进行反向传播
:param network: 神经网络
:param actual_label: 真实的标签值
:return:
'''
for i in reversed(range(len(network))): # 从最后一层开始计算误差
layer = network[i]
errors = list()
if i != len(network) - 1: # 不是输出层
for j in range(len(layer)): # 计算每一个神经元的误差
error = 0.0
for neuron in network[i + 1]:
error += (neuron['weights'][j] * neuron['delta'])
errors.append(error)
else: # 输出层
for j in range(len(layer)): # 计算每一个神经元的误差
neuron = layer[j]
errors.append(actual_label[j] - neuron['output'])
# 计算误差项 delta
for j in range(len(layer)):
neuron = layer[j]
neuron['delta'] = errors[j] * sigmoid_derivative(neuron['output'])
def update_parameters(network, row, l_rate):
'''利用误差更新神经网络的参数(权重矩阵和偏置项)
:param network: 神经网络
:param row: 一个样本数据
:param l_rate: 学习率
:return:
'''
for i in range(len(network)):
inputs = row[:-1]
if i != 0: # 获取上一层网络的输出
inputs = [neuron['output'] for neuron in network[i - 1]]
for neuron in network[i]:
# 更新权重矩阵
for j in range(len(inputs)):
neuron['weights'][j] += l_rate * neuron['delta'] * inputs[j]
# 更新偏置项
neuron['weights'][-1] += l_rate * neuron['delta']
def initialize_network(n_inputs, n_hidden, n_outputs):
'''初始化BP网络(初始化隐藏层和输出层的参数:权重矩阵和偏置项)
:param n_inputs: 特征列数
:param n_hidden: 隐藏层神经元个数
:param n_outputs: 输出层神经元个数,即分类的总类别数
:return: 初始化后的神经网络
'''
network = list()
# 隐藏层
hidden_layer = [{'weights': [random.random() for i in range(n_inputs + 1)]} for i in range(n_hidden)]
network.append(hidden_layer)
# 输出层
output_layer = [{'weights': [random.random() for i in range(n_hidden + 1)]} for i in range(n_outputs)]
network.append(output_layer)
return network
def train(train_data, l_rate, epochs, n_hidden):
'''训练神经网络(迭代n_epoch个回合)
:param train_data: 训练集
:param l_rate: 学习率
:param epochs: 迭代的回合数
:param n_hidden: 隐藏层神经元个数
:param val_data: 验证集
:return: 训练好的网络
'''
# 获取特征列数
n_inputs = len(train_data[0]) - 1
# 获取分类的总类别数
n_outputs = len(set([row[0] for row in train_data]))
# 初始化网络
network = initialize_network(n_inputs, n_hidden, n_outputs)
for epoch in range(epochs): # 训练epochs个回合
for row in train_data:
# 前馈计算
_ = forward_propagate(network, row)
# 处理一下类标,用于计算误差
actual_label = [0 for i in range(n_outputs)]
row = row.tolist()
actual_label[int(row[0])] = 1
# 误差反向传播计算
backward_propagate_error(network, actual_label)
# 更新参数
update_parameters(network, row, l_rate)
return network
def validation(network, val_data):
'''测试模型在验证集上的效果
:param network: 神经网络
:param val_data: 验证集
:return: 模型在验证集上的准确率
'''
# 获取预测类标
predicted_label = []
for row in val_data:
prediction = predict(network, row)
predicted_label.append(prediction)
# 获取真实类标
actual_label = [row[0] for row in val_data]
# 计算SE,SP,ACC指标
SE, SP, ACC = accuracy_calculation(actual_label, predicted_label)
print('SE:', SE)
print('SP:', SP)
print('ACC:', ACC)
# 绘制ROC曲线
fpr, tpr, _ = roc_curve(actual_label, predicted_label)
roc_auc = auc(fpr, tpr)
plt.figure(figsize=(8, 8))
# 假正率为横坐标,真正率为纵坐标做曲线
lw = 3
plt.plot(fpr, tpr, color='darkorange', lw=lw, label='ROC curve (area = %0.2f)' % roc_auc)
plt.plot([0, 1], [0, 1], color='navy', linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('BP Algorithm')
plt.legend(loc='lower right')
plt.show()
def accuracy_calculation(actual_label, predicted_label):
'''计算准确率
:param actual_label: 真实类标
:param predicted_label: 模型预测的类标
:return: 准确率(百分制)
'''
correct_count = 0
for i in range(len(actual_label)):
if actual_label[i] == predicted_label[i]:
correct_count += 1
# 计算混淆矩阵
matrix = confusion_matrix(actual_label, predicted_label)
TP = matrix[0][0]
FP = matrix[0][1]
FN = matrix[1][0]
TN = matrix[1][1]
SE = TP / (TP + FN)
SP = TN / (TN + FP)
ACC = (TP + TN) / (TP + FP + TN + FN)
return SE, SP, ACC
def predict(network, row):
'''使用模型对当前输入的数据进行预测
:param network: 神经网络
:param row: 一个数据样本
:return: 预测结果
'''
outputs = forward_propagate(network, row)
return outputs.index(max(outputs))
# 主程序
if __name__ == '__main__':
file_path = r'C:\Users\86158\PycharmProjects\pythonProject1\2023模式识别数据集汇总.xlsx'
l_rate = 0.2 # 学习率
epochs = 150 # 迭代训练的次数
n_hidden = 5 # 隐藏层神经元个数
# 加载数据并划分训练集和验证集
dataset = loadDataset(r'C:\Users\86158\PycharmProjects\pythonProject1\2023模式识别数据集汇总.xlsx')
# 5折交叉划分数据集
kf = KFold(n_splits=5, shuffle=True, random_state=0)
# 训练模型
i = 1
for train_index, test_index in kf.split(dataset):
print('*********Train %d**********' % (i))
train_data = dataset[train_index]
val_data = dataset[test_index]
network = train(train_data, l_rate, epochs, n_hidden)
validation(network, val_data)
i += 1
代码说明
- 数据读取与预处理: 代码首先使用
pd.read_excel读取Excel数据集,然后使用fillna填充缺失值,并进行数据归一化处理。 - BP神经网络实现: 代码实现了BP神经网络的各个部分,包括神经元输入计算、激活函数、前向传播、误差反向传播和参数更新等。
- 训练和评估: 代码使用5折交叉验证进行模型训练和评估,并计算了模型的SE、SP、ACC指标,并绘制了ROC曲线。
运行说明
- 将数据集文件
2023模式识别数据集汇总.xlsx放置在代码所在目录下。 - 运行代码,代码会进行5折交叉验证,并输出训练过程中的结果。
注意事项
- 数据集的格式需要与代码中读取的格式一致。
- 可以根据实际情况调整学习率、迭代次数、隐藏层神经元个数等参数。
- 代码示例中使用的激活函数为Sigmoid函数,可以根据需要选择其他激活函数。
- 可以根据需求添加其他评估指标,例如F1 score、precision等。
总结
本代码示例展示了使用Python进行模式识别数据集分析和BP神经网络实现的基本步骤,您可以参考该代码进行其他数据集的分析和模型训练。
原文地址: https://www.cveoy.top/t/topic/tPN 著作权归作者所有。请勿转载和采集!