实验目的
理解和掌握逻辑回归模型基本原理和方法,学会使用逻辑回归模型对分类问题进行建模和预测,掌握分类问题上模型评估方法。
实验内容
编程实现逻辑回归模型,在给定数据集上,绘制损失函数曲线图。使用混淆矩阵、错误率、精度、查全率、查准率、F1指标评估逻辑回归模型性能表现。
实验环境
python
numpy
matplotlib
实验代码
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use('TkAgg')
# 导入训练数据
train_dataset = np.genfromtxt("experiment_03_training_set.csv", delimiter=',', skip_header=1)
# 得到数据列数
column = train_dataset.shape[1]
# 得到数据条数
numberOfTrainDataset = train_dataset.shape[0]
# 将训练数据除了最后一列与全一列合并得到x
xOfTrainDataset = np.hstack((train_dataset[:, 0:column-1], np.ones((numberOfTrainDataset, 1))))
# 训练数据最后一列是y
yOfTrainDataset = train_dataset[:, column-1:column]
# 初始化权重 全为0
w = np.zeros((column, 1))
# 设置超参数
# 学习率
learn_rate = 0.1
# 迭代次数
epoch = 100
# 存储每次迭代的损失函数值
loss = np.zeros((100, 2))
# 开始训练
for i in range(epoch):
temp = xOfTrainDataset @ w
temp2 = np.exp(temp)
# 存储迭代次数
loss[i, 0] = i+1
# 迭代次数对应的损失函数值
loss[i, 1] = np.sum(-yOfTrainDataset * temp + np.log(1+temp2))
# 计算梯度
diff = -np.sum(xOfTrainDataset * (yOfTrainDataset - (temp2 / (1 + temp2))), axis=0) / numberOfTrainDataset
diff = diff.reshape(column, 1)
# 更新权重
w -= learn_rate * diff
# 输出中间结果
print(f"epoch {i+1}: loss->{loss[i, 1]: .4f}")
# 导入测试数据
test_dataset = np.genfromtxt("experiment_03_testing_set.csv", delimiter=',', skip_header=1)
# 得到数据列数
column = test_dataset.shape[1]
# 得到数据条数
numberOfTestDataset = test_dataset.shape[0]
# 将测试数据除了最后一列与全一列合并得到x
xOfTestDataset = np.hstack((test_dataset[:, 0:column-1], np.ones((numberOfTestDataset, 1))))
# 训练数据最后一列是y
yOfTestDataset = test_dataset[:, column-1:column]
# 初始化统计变量
TP = 0
FN = 0
FP = 0
TN = 0
# 计算得到预测值
yHatOfTestDataset = 1 / (1 + np.exp(-xOfTestDataset @ w))
# 进行统计
for i in range(numberOfTestDataset):
y = yOfTestDataset[i, 0]
yHat = yHatOfTestDataset[i, 0]
if yHat >= 0.5 and np.isclose(y, 1.0):
TP += 1
elif yHat >= 0.5 and np.isclose(y, 0.0):
FP += 1
elif yHat < 0.5 and np.isclose(y, 1.0):
FN += 1
else:
TN += 1
# 输出混淆矩阵
print("--------混淆矩阵--------")
print(f"TP: {TP} FN: {FN}")
print(f"FP: {FP} TN: {TN}")
# 计算评价指标
E = (FN + FP) / (TP + FN + FP + TN)
A = (TP + TN) / (TP + FN + FP + TN)
P = TP / (TP + FP)
R = TP / (TP + FN)
F1 = (2 * P * R) / (P + R)
# 输出评价指标
print(f"错误率: {E: .4f} | 精度: {A: .4f} | 查准率: {P: .4f} | 查全率: {R: .4f} | F1: {F1: .4f}")
# 准备画图数据
x_line = loss[:, 0:1]
y_line = loss[:, 1:2]
# 调整参数生成图像
plt.plot(x_line, y_line, color='b', linewidth=1.5, label='Loss function')
plt.title("Loss function", fontsize=14)
plt.xlabel("Epoch", fontsize=12)
plt.ylabel("Loss function value", fontsize=12)
plt.legend(loc='upper right', frameon=True)
plt.grid(alpha=0.3, linestyle=':')
plt.tight_layout()
plt.show()
结果分析
初始权值设为w=[0,0,…,0] ,学习率设为0.1,迭代次数为100。
损失曲线迭代图:
混淆矩阵:
真实情况 |
预测结果 |
|
正例 |
反例 |
|
正例 |
111 |
2 |
反例 |
14 |
42 |
评价指标:
指标 |
数值 |
错误率(error rate) |
0.0947 |
精度(accuracy) |
0.9053 |
查准率(precision) |
0.8880 |
查全率(recall) |
0.9823 |
F1 |
0.9328 |