机器学习——逻辑回归
一、逻辑回归概念点
逻辑回归(Logistic Regression)是一种广泛使用的统计分析方法和机器学习算法,主要用于处理二分类问题(即因变量为二元类别,如0和1、是和否等)。尽管名字中有“回归”二字,但它实际上是一种分类算法,而不是回归分析方法
1.1 逻辑回归优缺点
1.优点
- 简单易懂:逻辑回归模型结构简单,易于理解和实现
- 可解释性强:模型参数(权重)具有明确的统计意义,可以解释各个特征对结果的影响
- 计算效率高:逻辑回归算法计算速度快,适合大规模数据集
- 适用于二分类问题:逻辑回归是处理二分类问题的标准方法之一
2.缺点
- 对非线性关系建模能力有限:逻辑回归假设特征与目标变量之间是线性关系,对非线性关系建模能力有限
- 对异常值敏感:逻辑回归对异常值较为敏感,可能会影响模型的准确性
- 需要特征缩放:逻辑回归对特征的尺度敏感,通常需要对特征进行标准化或归一化处理
- 不适合多分类问题:虽然可以通过一对多或一对一的方法扩展到多分类问题,但不如其他算法(如决策树、随机森林等)直接
1.2 逻辑回归原理
逻辑回归的核心是使用 Sigmoid 函数(也称为逻辑函数)将线性回归的输出映射到0和1之间,表示事件发生的概率
Sigmoid 函数的公式为:
其中,z是线性回归的输出,即
逻辑回归的目标是找到一组权重 w ,使得模型对训练数据的预测尽可能准确。这通常通过最大化似然函数来实现,等价于最小化损失函数(如交叉熵损失)
1.3 逻辑回归执行步骤
1.3.1 数据准备
- 收集数据:收集包含特征和目标变量的数据集
- 数据清洗:处理缺失值、异常值等
- 特征选择:选择对目标变量有影响的特征
- 数据分割:将数据集分为训练集和测试集
1.3.2 特征工程
- 特征缩放:对特征进行标准化或归一化处理,以提高模型的收敛速度和准确性
- 特征编码:对分类特征进行编码
1.3.3 模型训练
- 初始化参数:随机初始化模型参数(权重)
- 选择优化算法:如梯度下降法
- 迭代优化:通过迭代优化算法更新模型参数,直到收敛或达到最大迭代次数
1.3.4 模型评估
- 使用测试集评估模型性能,常用的评估指标包括准确率、精确率、召回率、F1分数等
- 交叉验证:使用交叉验证方法评估模型的泛化能力
1.3.5 模型优化
- 参数调优:通过网格搜索或随机搜索等方法调整模型参数。
- 特征选择:使用特征选择方法(如递归特征消除、L1正则化等)选择最佳特征
二、Python代码实现逻辑回归
2.1 数据分析
在给出的数据中,前两列是特征值分别作为X轴和Y轴,第三列是类别标签
-0.017612 14.053064 0
-1.395634 4.662541 1
-0.752157 6.538620 0
-1.322371 7.152853 0
0.423363 11.054677 0
0.406704 7.067335 1
0.667394 12.741452 0
-2.460150 6.866805 1
0.569411 9.548755 0
-0.026632 10.427743 0
0.850433 6.920334 1
1.347183 13.175500 0
1.176813 3.167020 1
-1.781871 9.097953 0
-0.566606 5.749003 1
0.931635 1.589505 1
-0.024205 6.151823 1
-0.036453 2.690988 1
-0.196949 0.444165 1
1.014459 5.754399 1
1.985298 3.230619 1
-1.693453 -0.557540 1
-0.576525 11.778922 0
-0.346811 -1.678730 1
-2.124484 2.672471 1
1.217916 9.597015 0
-0.733928 9.098687 0
-3.642001 -1.618087 1
0.315985 3.523953 1
1.416614 9.619232 0
-0.386323 3.989286 1
0.556921 8.294984 1
1.224863 11.587360 0
-1.347803 -2.406051 1
1.196604 4.951851 1
0.275221 9.543647 0
0.470575 9.332488 0
-1.889567 9.542662 0
-1.527893 12.150579 0
-1.185247 11.309318 0
-0.445678 3.297303 1
1.042222 6.105155 1
-0.618787 10.320986 0
1.152083 0.548467 1
0.828534 2.676045 1
-1.237728 10.549033 0
-0.683565 -2.166125 1
0.229456 5.921938 1
-0.959885 11.555336 0
0.492911 10.993324 0
0.184992 8.721488 0
-0.355715 10.325976 0
-0.397822 8.058397 0
0.824839 13.730343 0
1.507278 5.027866 1
0.099671 6.835839 1
-0.344008 10.717485 0
1.785928 7.718645 1
-0.918801 11.560217 0
-0.364009 4.747300 1
-0.841722 4.119083 1
0.490426 1.960539 1
-0.007194 9.075792 0
0.356107 12.447863 0
0.342578 12.281162 0
-0.810823 -1.466018 1
2.530777 6.476801 1
1.296683 11.607559 0
0.475487 12.040035 0
-0.783277 11.009725 0
0.074798 11.023650 0
-1.337472 0.468339 1
-0.102781 13.763651 0
-0.147324 2.874846 1
0.518389 9.887035 0
1.015399 7.571882 0
-1.658086 -0.027255 1
1.319944 2.171228 1
2.056216 5.019981 1
-0.851633 4.375691 1
-1.510047 6.061992 0
-1.076637 -3.181888 1
1.821096 10.283990 0
3.010150 8.401766 1
-1.099458 1.688274 1
-0.834872 -1.733869 1
-0.846637 3.849075 1
1.400102 12.628781 0
1.752842 5.468166 1
0.078557 0.059736 1
0.089392 -0.715300 1
1.825662 12.693808 0
0.197445 9.744638 0
0.126117 0.922311 1
-0.679797 1.220530 1
0.677983 2.556666 1
0.761349 10.693862 0
-2.168791 0.143632 1
1.388610 9.341997 0
0.317029 14.739025 0
2.2 代码展示
2.2.1 导入相关库
import numpy as np
import matplotlib.pyplot as plt
2.2.2 数据预处理
path = '文件名.txt'def loaddataset():testset = [[-3.141592, 2.343434], [7.12121, 3.232323], [-1.222222, 3.2323232], [2.794747, -4.67890]]datamat = []labelmat = []fr = open(path)for line in fr.readlines():linearr = line.strip().split()datamat.append([1.0, float(linearr[0]), float(linearr[1])])labelmat.append(int(linearr[2]))return datamat, labelmat, testset
代码解析:
1.定义了一个变量 path,对包含数据集的文本文件的路径和文件名进行存储
2.定义函数loaddataset(),将数据集从文件中加载出来
3.定义了一个 testset 的列表,其中包含了测试数据集。每个子列表代表一个测试样本,包含两个
特征值
4.初始化两个空列表,datamat 用于存储训练数据的特征,labelmat 用于存储训练数据的标签
5.打开文件,逐行读取文件中的内容并将数据存储到datamat列表和labelmat列表中
6.返回三个值:datamat(训练数据的特征),labelmat(训练数据的标签),以及 testset(测试数据集)
2.2.3 逻辑回归模型构建
def sigmoid(z):return 1 / (1 + np.exp(-z))# 测试函数并展示图像
def test_sigmoid():nums = np.arange(-10, 10, 0.1)sig_values = sigmoid(nums)fig, ax = plt.subplots(figsize=(12, 8))ax.plot(nums, sig_values, 'g')ax.set_xlabel('Input Value')ax.set_ylabel('Sigmoid Value')ax.set_title('Sigmoid Function')plt.grid(True)plt.show()
2.2.4 实现模型的梯度上升函数
# 实现模型的梯度上升函数
def gradascent(datamatin, classlabels, stoptype='bgd'):m, n = np.shape(datamatin) # m为矩阵的行数,n为矩阵的列数weights = np.ones((n, 1)) # 权重矩阵(n,1)的列向量alpha = 0.001 # 学习率(梯度上升的步长)if stoptype == 'bgd':datamatrix = np.asmatrix(datamatin) # 将datamatrix转化为矩阵labelmat = np.asmatrix(classlabels).transpose() # 将labelmat转化为矩阵同时转置maxcycles = 500 # 最大迭代次数for k in range(maxcycles): # 梯度上升循环h = sigmoid(datamatrix * weights) # 使用当前权重和输入数据计算每个数据点的预测概率error = (labelmat - h) # 计算预测概率和真实标签的误差weights = weights + alpha * datamatrix.transpose() * errorreturn weights # datamatrix.transpose()*error为梯度,再利用梯度*学习率来更新权值elif stoptype == 'sgd':weights = np.ones((n, 1)) # 初始化权重for i in range(m):h = sigmoid(np.dot(datamatin[i], weights)) # 使用当前权重和输入数据计算每个数据点的预测概率error = classlabels[i] - h # 计算预测概率和真实标签的误差weights = weights + alpha * error * np.array(datamatin[i]).reshape(n, 1)return weights
2.2.5 预测测试集,划分类别
# 预测测试集,划分类别
def classifyVector(testset, weights):count = 0testset = np.array(testset)for sample in testset:count += 1 # 用来记录当前的测试集z = weights[0] * 1 + weights[1] * sample[0] + weights[2] * sample[1]result = sigmoid(z)print(f"第{count}个测试集计算的概率结果为:{result}")if result > 0.5:print(f"第{count}个测试预测类别为1类")else:print(f"第{count}个预测类别为0类")
2.2.6 绘制决策边界
# 绘制决策边界
def plotBestFit(weights, dataMat, labelMat):dataArr = np.array(dataMat)n = np.shape(dataArr)[0] # 获取数据总数xcord1 = []; ycord1 = [] # 存放正样本xcord2 = []; ycord2 = [] # 存放负样本for i in range(n): # 依据数据集的标签来对数据进行分类if int(labelMat[i]) == 1: # 数据的标签为1,表示为正样本xcord1.append(dataArr[i, 1]); ycord1.append(dataArr[i, 2])else:xcord2.append(dataArr[i, 1]); ycord2.append(dataArr[i, 2])fig = plt.figure()ax = fig.add_subplot(111)ax.scatter(xcord1, ycord1, s=30, c='b', marker='o') # 绘制正样本ax.scatter(xcord2, ycord2, s=30, c='r', marker='x') # 绘制负样本x = np.arange(-3.0, 3.0, 0.1)y = (-weights[0, 0] - weights[1, 0] * x) / weights[2, 0]ax.plot(x, y)plt.xlabel('X1'); plt.ylabel('X2')plt.legend(["1", "0", "decision boundary"])plt.show()
2.2.7 主函数执行
# 主函数
if __name__ == "__main__":dataMat, labelMat, testset = loaddataset() # 加载数据集test_sigmoid()weights = gradascent(dataMat, labelMat) # 训练模型并获取最优权值print("最优权值:")print(weights)classifyVector(testset, weights) # 预测测试集plotBestFit(weights, dataMat, labelMat) # 绘制决策边界
2.3 效果截图
2.3.1 逻辑回归模型展示
2.3.2 最优权值
2.3.3 测试集预测
2.3.4 绘制决策边界
2.4 总结
2.4.1 实验目标
本次实验的目标是通过实现逻辑回归模型,对二分类数据集进行训练和预测,并通过绘制决策边界来直观展示模型的分类效果。实验主要涉及以下内容:
- 数据加载与预处理
- 实现逻辑回归模型的训练(梯度上升法)
- 对测试集进行预测
- 绘制决策边界并评估模型性能
2.4.2 实验方法
本次实验采用 Python 编程语言,使用 NumPy 和 Matplotlib 等库实现逻辑回归模型。实验步骤如下:
1. 数据加载与预处理
- 数据集包含两个特征和一个标签,标签为 0 或 1
- 数据加载时,每行数据被处理为一个特征向量(添加偏置项 1.0)和对应的标签
- 数据集被分为训练集和测试集
2. 模型训练
- 采用梯度上升法(Gradient Ascent)训练逻辑回归模型
- 实现了两种梯度上升方法:批量梯度上升,即使用所有数据点计算梯度,更新权重;随机梯度上升,即每次只使用一个数据点计算梯度,更新权重。
- 学习率设置为 0.001,迭代次数为 500 次(BGD)
3. 预测与评估
- 使用训练好的权重对测试集进行预测
- 预测结果基于 Sigmoid 函数的输出,阈值为 0.5
- 打印每个测试样本的预测概率和预测类别
4. 决策边界绘制
- 根据训练好的权重绘制决策边界
- 决策边界由公式
确定
- 数据点根据标签分为两类,分别用蓝色圆圈(正样本)和红色叉号(负样本)表示
2.4.3 实验分析
1. 模型性能
- 从决策边界图像可以看出,模型能够较好地分隔两类数据,说明训练效果较好
- 测试集的预测结果也表明,模型能够准确地对新样本进行分类
2. 梯度上升法
- 批量梯度上升法(BGD):计算稳定,但计算量较大,适合小数据集
- 随机梯度上升法(SGD):计算速度快,但收敛速度可能较慢,适合大数据集
通过实现逻辑回归模型,加深了对逻辑回归算法的理解,包括 Sigmoid 函数、梯度上升法等核心概念,在实验中, 使用 Python 和 NumPy 实现了数据处理、模型训练和可视化,提升了编程能力