当前位置: 首页 > article >正文

2.系统学习-逻辑回归

逻辑回归

  • 前言
  • 最大似然估计
    • 概率
    • 似然函数(likelihood function)
    • 最大似然估计
  • 逻辑回归
    • 逻辑回归的似然函数与梯度
  • 分类问题常用评价指标
  • 项目案例
  • 拓展内容
  • 作业

前言

逻辑回归与线性回归均属于广义线性模型,区别在于线性回归用于解决回归问题,例如身高、销量等连续变量预测,逻辑回归用于二分类问题,例如判断是否为垃圾邮件,客户是否会点击广告。本章我们将首先了解最大似然估计,一步步推导出逻辑回归模型,最大似然估计广泛用于各类机器学习、深度学习,需要认真理解。接着会以实际案例,讲解非结构化数据处理的基础方法,分类问题建模流程。
学习目标:

  • List item
  • 最大似然估计
  • 逻辑回归模型
  • 常用的分类问题评价指标
  • 基础数据处理&分类问题建模
  • 独自完成Kaggle Titanic竞赛首次提交,得分需要高于0.75链接: Titanic Machine Learning from Disaster

最大似然估计

概率

硬币有正反两面,如果硬币正反两面是均匀的,即每次抛掷后硬币为正的概率是0.5。使用这个硬币,很可能抛10次,有5次是正面。但是假如有人对硬币做了手脚,比如提前对硬币做了修改,硬币正面朝上概率大幅度提升了,你拿到硬币在尝试抛了10次,结果8次都是正面,如何估算下次硬币为正的概率呢?
P ( 8 正 2 反 ∣ θ ) = C 10 2 ( 1 − θ ) 2 ⋅ θ 8 P(8正2反|\theta) = C_{10}^2(1 - \theta)^2 \cdot \theta^8 P(82θ)=C102(1θ)2θ8

import numpy as np 
print(f"theta = 0.6,  概率为{10*9/2 * np.power(10.6, 2) * np.power(0.6, 8):.3}") 
print(f"theta = 0.7,  概率为{10*9/2 * np.power(10.7, 2) * np.power(0.7, 8):.3}") 
print(f"theta = 0.8,  概率为{10*9/2 * np.power(10.8, 2) * np.power(0.8, 8):.3}") 

theta = 0.6, 概率为0.121
theta = 0.7, 概率为0.233
theta = 0.8, 概率为0.302
可以看出,我们假设硬币朝正面参数为0.8的时候,出现8正2反情况的概率最大。我们有理由相信,0.8是候选的3个参数中的最接近真实概率的选项。

似然函数(likelihood function)

在上面的尝试中,0.8似乎是一个不错的猜测没,,但是否可能是0.81或者0.79呢,我们当然可以按照上面的方法再次计算概率,但是问题是我们无法遍历整个空间。因此我们需要定义一个函数来表示不同的参数 下,表示多个独立事件θ (x1, x2,…,xn)发生的整体概率,这个函数我们叫它似然函数( likelihood function, 通常用L表),其中组合数部分是常数,我们可以直接忽略。 L ( x 1 , x 2 , … , x n ∣ θ ) = ∏ i = 1 n p ( x i ∣ θ ) L(x_1, x_2, \dots, x_n|\theta) = \prod_{i=1}^{n} p(x_i|\theta) L(x1,x2,,xnθ)=i=1np(xiθ)
似然函数通常用L表示,观察到抛硬币“8正2反”的事实,硬币参数 取不同值时,似然函数表示为: L ( 8 正 2 反 ∣ θ ) = ( 1 − θ ) 2 ⋅ θ 8 L(8正2反|\theta) = (1 - \theta)^2 \cdot \theta^8 L(82θ)=(1θ)2θ8

通过似然函数,我们只要能找到使得似然函数最大(多个独立事件发生的整体概率最大化),就可以完成对硬币参数的估计了,这就是最大似然估计:
θ ^ = arg ⁡ max ⁡ θ ∏ i = 1 n p ( x i ∣ θ ) \hat{\theta} = \arg\max_{\theta} \prod_{i=1}^{n} p(x_i|\theta) θ^=argθmaxi=1np(xiθ)

最大似然估计

通常,由于似然函数为连乘,会造成小数位过高,无法有效表示,我们采用对数似然函数进行表示,把连乘转化为累加形式: l ( x 1 , x 2 , … , x n ∣ θ ) = ∑ i = 1 n log ⁡ p ( x i ∣ θ ) l(x_1, x_2, \dots, x_n|\theta) = \sum_{i=1}^{n} \log p(x_i|\theta) l(x1,x2,,xnθ)=i=1nlogp(xiθ)
θ ^ = arg ⁡ max ⁡ θ ∑ i = 1 n log ⁡ p ( x i ∣ θ ) \hat{\theta} = \arg\max_{\theta} \sum_{i=1}^{n} \log p(x_i|\theta) θ^=argθmaxi=1nlogp(xiθ)

逻辑回归

逻辑回归是线性分类模型,说线性是因为其决策边界是线性的(平面或超平面),模型输出值域为(0,1),通常我们将输出结果视为属于正样(y = 1)的概率。我们先来看一下逻辑回归模型的数学表示: P ( x ) = σ ( w T x ) = 1 1 + exp ⁡ − w T x P(x) = \sigma(w^T x) = \frac{1}{1 + \exp^{-w^T x}} P(x)=σ(wTx)=1+expwTx1
在这里插入图片描述

import numpy as np 
import matplotlib.pyplot as plt 
%matplotlib inline 
def sigmoid(x): 
    return 1 / (1 + np.exp(-x)) 
data = np.arange(-10, 10, 0.1) 
plt.plot(data, sigmoid(data)) 

在这里插入图片描述

逻辑回归的似然函数与梯度

tips: 本段包含了不少公式计算,但公式本身的推导细节并不是最重要的,最重要的是通过引入似然函数,我们构造了逻辑回归的损失函数,且该损失函数可以利用梯度下降进行优化。
在这里插入图片描述
p ( y = y i ∣ x i ) = p ( x i ) y i ( 1 − p ( x i ) ) 1 − y i p(y = y^i | x^i) = p(x^i)^{y^i}(1 - p(x^i))^{1-y^i} p(y=yixi)=p(xi)yi(1p(xi))1yi
在这里插入图片描述
Likelihood = ∏ i p ( y = y i ∣ x i ) = ∏ i p ( x i ) y i ( 1 − p ( x i ) ) 1 − y i \text{Likelihood} = \prod_i p(y = y^i | x^i) = \prod_i p(x^i)^{y^i} (1 - p(x^i))^{1-y^i} Likelihood=ip(y=yixi)=ip(xi)yi(1p(xi))1yi
两边同时取对数,对数似然函数为:
loglikelihood = ∑ i [ y i log ⁡ p ( x i ) + ( 1 − y i ) log ⁡ ( 1 − p ( x i ) ) ] \text{loglikelihood} = \sum_i \left[y^i \log p(x^i) + (1 - y^i) \log (1 - p(x^i))\right] loglikelihood=i[yilogp(xi)+(1yi)log(1p(xi))]
loglikelihood = ∑ i [ y i log ⁡ p ( x i ) 1 − p ( x i ) + log ⁡ ( 1 − p ( x i ) ) ] \text{loglikelihood} = \sum_i \left[y^i \log \frac{p(x^i)}{1 - p(x^i)} + \log (1 - p(x^i))\right] loglikelihood=i[yilog1p(xi)p(xi)+log(1p(xi))]
那么这个对数似然函数就是我们需要优化的目标的,其值越大越好,越大说明模型预测概率和真实发生概率一致性越高。由于梯度下降法是验证最小化损失函数目标进行的,因此我们对对数似然函数乘以‑1。
J ( w ) = − ∑ i [ y i log ⁡ p ( x i ) 1 − p ( x i ) + log ⁡ ( 1 − p ( x i ) ) ] J(w) = -\sum_i \left[y^i \log \frac{p(x^i)}{1 - p(x^i)} + \log (1 - p(x^i))\right] J(w)=i[yilog1p(xi)p(xi)+log(1p(xi))]
求关于参数的梯度,根据求导法则可得:
g = ∂ J ∂ w = ∑ i ( p ( x i ) − y i ) ⋅ x i g = \frac{\partial J}{\partial w} = \sum_i \left(p(x^i) - y^i\right) \cdot x^i g=wJ=i(p(xi)yi)xi

有了梯度,根据上节课我们学习的梯度下降,就可以根据学习率α逐步迭代更新模型参数 w = w − α ⋅ g w = w - \alpha \cdot g w=wαg

分类问题常用评价指标

在二分类场景,模型所有的预测结果可以分为四类:

  1. TP(True positive),意思是模型预测为正样本(Positive),预测是正确的(True)
  2. FP(False positive),意思是模型预测为正样本(Positive),预测是错误的(False)
  3. TN(True negtive),意思是模型预测为负样本(negtive),预测是正确的(True)
  4. FN(False negtive),意思是模型预测为负样本(negtive),预测是错误的(False)
    基于以上四类预测结果,我们可以定义指标:
指标公式含义
准确率 Accuracy = # T P + # T N # A L L \text{Accuracy} = \frac{\#TP + \#TN}{\#ALL} Accuracy=#ALL#TP+#TN所有预测结果中,预测正确的比例,值越大说明模型表现越好。
精准率 Precision = # T P # T P + # F P \text{Precision} = \frac{\#TP}{\#TP + \#FP} Precision=#TP+#FP#TP所有预测的正样本中,正确的比例,值越大说明模型表现越好。
召回率 Recall = # T P # T P + # F N \text{Recall} = \frac{\#TP}{\#TP + \#FN} Recall=#TP+#FN#TP所有正样本被正确预测的比例,值越大说明模型表现越好。
from sklearn.metrics import accuracy_score, precision_score, recall_score 
y_true = [1, 1, 0, 1, 0] 
y_pred = [0, 1, 0, 1, 0]
accuracy_score(y_true, y_pred)#0.8
precision_score(y_true, y_pred)#1.0
recall_score(y_true, y_pred)#0.6666666666666666

在一些极端场景下,准确率会失效,比如正负样本及其不均匀的情况:

y_true = [1, 1, 1, 1, 1, 0] 
y_pred = [1, 1, 1, 1, 1, 1] 
accuracy_score(y_true, y_pred) #0.8333333333333334

不过什么输入,模型都预测为正样本,导致模型本质上没有预测能力,但是依然能够取得很高的Accuracy。为了避免评估指标失效,我们可以同时查看precision 和 recall指标

precision_score(y_true, y_pred) #0.8333333333333334
recall_score(y_true, y_pred) # 1.0

也可以应用一个由recall,precision 一起组成的复合指标 f1‑score,该值越大,说明模型表现越好:
f 1 = 2 ⋅ recall ⋅ precision recall + precision f1 = \frac{2 \cdot \text{recall} \cdot \text{precision}}{\text{recall} + \text{precision}} f1=recall+precision2recallprecision

 from sklearn.metrics import f1_score
 f1_score(y_true, y_pred) # 0.9090909090909091
 
p = precision_score(y_true, y_pred) 
r = recall_score(y_true, y_pred) 
 
2 * p * r / (p + r) #0.9090909090909091

项目案例

链接: Titanic Machine Learning from Disaster

# 导入所需的库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import re 
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler, PolynomialFeatures, OneHotEncoder
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
%matplotlib inline 

# 读取 Titanic 数据集
train = pd.read_csv("./titanic/train.csv")  # 训练数据
test = pd.read_csv("./titanic/test.csv")    # 测试数据
submission = pd.read_csv("./titanic/gender_submission.csv")  # 示例提交文件

# 数据概览
print(train.head())  # 查看训练数据的前几行
print(test.head())   # 查看测试数据的前几行
print(train.isnull().sum())  # 检查训练数据的缺失值

# 填充缺失值
# 用中位数填充缺失的年龄数据
train['Age'] = train['Age'].fillna(train['Age'].median())
test['Age'] = test['Age'].fillna(test['Age'].median())

# 用众数填充缺失的登船港口数据
train['Embarked'] = train['Embarked'].fillna('S')
test['Embarked'] = test['Embarked'].fillna('S')

# 用票价的中位数填充缺失的票价数据
test['Fare'] = test['Fare'].fillna(test['Fare'].median())

# 数据预处理
# 将性别和登船港口转换为数值类型
train = pd.get_dummies(train, columns=['Sex', 'Embarked'], drop_first=True)
test = pd.get_dummies(test, columns=['Sex', 'Embarked'], drop_first=True)

# 删除不需要的列
train.drop(['Name', 'Ticket', 'Cabin'], axis=1, inplace=True)
test.drop(['Name', 'Ticket', 'Cabin'], axis=1, inplace=True)

# 提取目标变量和特征
train_target = train['Survived']  # 目标变量
train_features = train.drop(['Survived', 'PassengerId'], axis=1)  # 特征
test_features = test.drop(['PassengerId'], axis=1)  # 测试集特征

# 标准化特征
scaler = StandardScaler()
train_features = scaler.fit_transform(train_features)
test_features = scaler.transform(test_features)

# 逻辑回归模型
model = LogisticRegression()  # 创建逻辑回归模型
model.fit(train_features, train_target)  # 训练模型

# 模型评估
predictions = model.predict(train_features)  # 在训练集上预测
print("Accuracy:", accuracy_score(train_target, predictions))  # 准确率
print("Precision:", precision_score(train_target, predictions))  # 精准率
print("Recall:", recall_score(train_target, predictions))  # 召回率
print("F1 Score:", f1_score(train_target, predictions))  # F1 分数

# 在测试集上进行预测
test_predictions = model.predict(test_features)

# 生成提交文件
submission['Survived'] = test_predictions
submission.to_csv("./submission.csv", index=False)  # 保存结果到 CSV 文件

print("结果已保存至 submission.csv")

拓展内容

需要注意的是,逻辑回归虽然存在sigmoid函数将输出结果映射到0~1区间,但本质依然是一个线性模型,因为模型的分类决策边界是一个平面,而不是曲面或其他,以下图为例,中间的蓝色直线就是我们的分类(超)平面,位于平面上方的点为正样本,下方的点为负样本,这个分类(超)平面可以用一个线性方程表示出来。
在这里插入图片描述

作业

  1. 分类问题中,在正负样本不均衡的情况下,我们如何评价模型?
  2. 在Titanic Machine Learning from Disaster比赛提交逻辑回归建模预测结果,需要得分高于0.75

http://www.kler.cn/a/452105.html

相关文章:

  • 【Linux】查询磁盘空间被谁占用了
  • Golang的容器化技术实践总结
  • 修炼内功之函数栈帧的创建与销毁
  • 【蓝桥杯——物联网设计与开发】基础模块8 - RTC
  • 【每日学点鸿蒙知识】AVCodec、SmartPerf工具、web组件加载、监听键盘的显示隐藏、Asset Store Kit
  • 【RAG实战】Prompting vs. RAG vs. Finetuning: 如何选择LLM应用选择最佳方案
  • 怎么在ubuntu系统上安装qt项目的打包工具linuxdeployqt
  • 目标检测与R-CNN——paddle部分
  • 前端面经每日一题Day21
  • MDS-NPV/NPIV
  • 如何完全剔除对Eureka的依赖,报错Cannot execute request on any known server
  • pytorch nn.Unflatten 和 nn.Flatten模块介绍
  • Chrome 浏览器插件获取网页 iframe 中的 window 对象
  • 【ORB-SLAM3:相机针孔模型和相机K8模型】
  • Chapter 03 复合数据类型-1
  • RBF分类-径向基函数神经网络(Radial Basis Function Neural Network)
  • 数据库安全-redisCouchdb
  • 硬件设计-传输线匹配
  • 3D视觉坐标变换(像素坐标转换得到基于相机坐标系的坐标)
  • 以太网通信--读取物理层PHY芯片的状态
  • C++ 特殊类的设计
  • 开发微信小程序的过程与心得
  • RuoYi-ue前端分离版部署流程
  • mac中idea菜单工具栏没有git图标了
  • 【HarmonyOS NEXT】hdc环境变量配置
  • 认识计算机网络