背景
逻辑回归(Logistic Regression)是一种用于分类问题的统计模型,尽管名字里有"回归",但它主要用于解决二元分类(binary classification)或多类分类问题。与线性回归不同,逻辑回归输出的是一个概率,通过设置阈值将概率转换为类别。
一、适用数据集
1. 数据集选择
逻辑回归适用于二分类问题,即输出为两个类别(如【是/否】或【正/负】)。若要练习逻辑回归分析,在选择数据集时可以参考以下 3 个方面。反过来,如果在为项目选择合适的算法模型时,数据集符合以下条件,则可以选用逻辑回归进行数据分析。
1.1 领域
逻辑回归广泛应用于各种领域,包括但不限于:
- 医疗健康:预测某人是否患病(如患病/不患病,阳性/阴性)。
- 金融:预测贷款申请是否会被批准,或是否会违约(如信用风险评估)。
- 市场营销:根据用户行为预测是否会购买产品或订阅服务。
- 社交媒体:通过用户行为预测某个帖子是否会获得点赞或分享。
- 人力资源:预测员工是否会离职。
- 教育:预测学生是否会通过考试或被录取。
1.2 数据集维度
- 特征数(维度):逻辑回归适用于中低维度的数据集。一般情况下,输入特征数从 2 到 20 维是常见的范围。过多的特征可能会导致过拟合,尤其是当样本数量不足时。
- 类别标签:逻辑回归特别适用于二分类任务,因此类别标签只有两个(如 0 和 1,或者 "A 类" 和 "B 类")。
1.3 记录行(样本数量)
样本量大小 :逻辑回归的一个优势是即使在较小的数据集上也能有效工作,通常数百到几千条记录的样本集即可获得良好的训练效果。典型样本数量可以在 100 到 10,000 行之间:
- 小型数据集(100-1000 行):适合初学者理解逻辑回归的基本概念和快速训练模型。
- 中型数据集(1000-10,000 行):适合做一些更复杂的练习,如交叉验证、正则化等。
2. 本文数据集介绍
Titanic 数据集 基于 1912 年泰坦尼克号沉船事故的真实乘客数据,泰坦尼克号是当时最大的远洋客轮之一,但在其首次航行中不幸撞上冰山沉没,超过1500人遇难。该数据集包含了泰坦尼克号部分乘客的个人信息以及他们是否在船难中幸存,分析目的是:预测哪些乘客能够在这场灾难中幸存下来。
数据集中包含 12 列的维度信息,详细如下:
- PassengerId: 乘客的唯一标识符。
- Survived: 是否幸存,目标变量(0 = 未幸存,1 = 幸存)。
- Pclass: 乘客舱位等级(1 = 一等舱,2 = 二等舱,3 = 三等舱)。
- Name: 乘客姓名。
- Sex: 性别(male = 男性,female = 女性)。
- Age: 年龄(有部分缺失值)。
- SibSp: 同行的兄弟姐妹或配偶人数。
- Parch: 同行的父母或子女人数。
- Ticket: 票号。
- Fare: 票价。
- Cabin: 船舱号(有部分缺失值)。
- Embarked: 登船地点(C = Cherbourg, Q = Queenstown, S = Southampton)。
数据记录行共有 1309 行,属于中型数据集。
3. 数据集下载
数据集下载地址:https://www.kaggle.com/datasets/heptapod/titanic
也可以在文首 绑定资源中下载获取,原版下载出来有多列是无意义的【zero】列,作者这里直接在表里删了,上传资源为处理后的。自行在 Kaggle 下载的朋友记得处理【zero】列。
注意
Kaggle 上 Titanic 数据集有俩都点赞比较高,不要选择看起来更完整的 Titanic dataset!
博主先使用了 Titanic dataset,因为预测结果全都是 100%,于是开始 debug。。。
直到发现这个数据集的获救与否是由性别决定的(dead。。)
重复:千万要使用对的 Titanic 数据集啊!
二、逻辑回归的基本原理
1. 目的
逻辑回归的目的是预测输入数据属于某一类别的概率。它最常用于二元分类问题,例如:预测某个乘客在 Titanic 数据集中是否生还。
2. Sigmoid 函数
Sigmoid 函数的公式:
逻辑回归模型的核心是 Sigmoid 函数,它将线性回归的输出值(任何实数)压缩到 [0, 1] 的范围内,这样我们可以将输出解释为概率。
其中, ,即将特征向量 X 经过线性组合(权重 w 和偏置 b)后输入到 Sigmoid 函数中。
通过这种方式,我们将线性回归输出的值(通常是实数)转换为一个概率值:
3. 类别划分
逻辑回归通常使用 0.5 作为默认的阈值,将输出的概率值转换为二元分类的类别:
这个阈值可以根据具体的需求调整。
4. 召回率
召回率 (Recall)是分类模型评估指标之一,尤其在 二元分类 问题中常用。召回率表示在所有实际为正例(Positive)的样本中,模型正确识别出的正例样本的比例。
公式:
三、代码
完整版代码和初步处理的数据集见文章绑定资源。
1. 导入所需包&数据集
python
#数据分析与可视化包
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
from sklearn.model_selection import learning_curve, train_test_split
from sklearn.preprocessing import StandardScaler, PolynomialFeatures
from sklearn.linear_model import LogisticRegression #逻辑回归
from sklearn.metrics import roc_curve, auc, precision_recall_curve
from sklearn.metrics import log_loss
from sklearn.pipeline import make_pipeline
from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score
#accuracy_score,准确率
#f1_score,精确率和召回率的调和平均数
#precision_score,精确率
#recall_score,召回率
from sklearn.metrics import confusion_matrix, classification_report
#confusion_matrix混淆矩阵
#classification_report任务性能分析
Titanic_data=pd.read_csv("D:/project/Jupyter/csdn/AI_ML/datasets/Lesson3_Titanic.csv")
Titanic_data
Titanic_data.info()
2. 数据预处理&数据编码
2.1 数据预处理
python
# 将 float 类型转换为 int 类型
Titanic_data['Age'] = Titanic_data['Age'].astype('int64')
Titanic_data['Fare'] = Titanic_data['Fare'].astype('int64')
# 用众数填充 Embarked(登船地点)列缺失值
Titanic_data['Embarked'].fillna(Titanic_data['Embarked'].mode()[0], inplace=True)
# 将 float 类型转换为 int 类型
Titanic_data['Embarked'] = Titanic_data['Embarked'].astype('int64')
2.2 数据预处理&编码(Titanic dataset版,可跳过)
本部分是 Titanic dataset 的预处理,相对完整。参考一下就行,在 Titanic 数据集用不到。
python
# 填补缺失值
# Age(年龄)列用中位数填充,Embarked(登船地点)列用众数填充
# 按乘客的票舱等级(Pclass)进行分组,分别计算每个等级的均值填补 Fare(票价)列
Titanic_data['Age'].fillna(Titanic_data['Age'].median(), inplace=True)
Titanic_data['Embarked'].fillna(Titanic_data['Embarked'].mode()[0], inplace=True)
Titanic_data['Fare'] = Titanic_data.groupby('Pclass')['Fare'].apply(lambda x: x.fillna(x.median()))
# 将 非int或float 类型列进行编码变为 int 类型
# 将性别和登船港口编码为数值
Titanic_data['Sex'] = Titanic_data['Sex'].map({'male': 0, 'female': 1})
Titanic_data['Embarked'] = Titanic_data['Embarked'].map({'C': 0, 'Q': 1, 'S': 2})
# 丢弃无用的列
Titanic_data.drop(['Name', 'Ticket', 'Cabin'], axis=1, inplace=True)
# 对 Age 和 Fare 列进行四舍五入,并转换为 int64 型
Titanic_data['Age'] = Titanic_data['Age'].round().astype('int64')
Titanic_data['Fare'] = Titanic_data['Fare'].round().astype('int64')
# 查看处理后的数据
Titanic_data.head()
Titanic_data.info()
由于 'Name'、 'Ticket' 列,即 "姓名"、"票号" 列都是唯一的,在判断乘客是否会遇难时无法起到帮助分析作用,即可删去。
由于 'Cabin' 列,即 "船舱号" 并无性质表现,且缺失过多,分析是可删去,以免大量的填补数据干扰模型预测结果。
3. 绘制热力图
显示各个特征之间的相关性,并显示不同特征之间的相关关系。观察数据各维度之间的相关性,同时具有验证数据集可用性的功效(如作者通过热力图发现 Titanic dataset 用不了)。
python
plt.figure(figsize=(10, 8))
sns.heatmap(Titanic_data.corr(), annot=True, cmap='coolwarm')
plt.title('Correlation Heatmap')
plt.show()
4. 数据拆分&标准化
python
# 特征选择
X = Titanic_data.drop('Survived', axis=1)
y = Titanic_data['Survived']
# 拆分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 标准化特征(可选,但推荐逻辑回归中进行特征缩放)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
5. 逻辑回归分类算法
python
# 使用 scikit-learn 的逻辑回归模型
model = LogisticRegression(
max_iter=10000,
penalty='l2',
#C=0.1,
#solver='liblinear',
class_weight="balanced"
)
model.fit(X_train, y_train)
# 预测
y_pred_test = model.predict(X_test)
print(classification_report(y_test,y_pred_test))
y_pred_train = model.predict(X_train)
print(classification_report(y_train,y_pred_train))
confusion_matrix(y_train,y_pred_train)#生成混淆矩阵
#画热力图
sns.heatmap(confusion_matrix(y_test,y_pred_test),annot=True,fmt="d")
accuracy_score(y_pred_test,y_test)#准确率
f1_score(y_pred_test,y_test)#精确率和召回率的调和平均数
# 从负类,计算模型精确率和召回率
precision_score(y_pred_test,y_test,pos_label=0)#精确率
recall_score(y_pred_test,y_test,pos_label=0)#召回率
print(model.coef_)
print(model.intercept_)
# 显示模型系数
coefficients = pd.DataFrame(model.coef_.flatten(), index=X.columns, columns=['Coefficient'])
print(coefficients)
pd.DataFrame(model.coef_,columns=X.columns).T.plot(kind="barh")#显示系数大小
model.predict_proba(X_test)
model.predict(X_test)
# 从正类,计算精确率和召回率
precision = precision_score(y_test, y_pred_test,pos_label=1)
recall = recall_score(y_test, y_pred_test,pos_label=1)
print(f"Precision: {precision}")
print(f"Recall: {recall}")
6. 绘制 PR / ROC 曲线
6.1 PR 曲线
显示模型在不同阈值下的精确率和召回率的权衡关系。
python
probs=model.predict_proba(X_test)[:,0]
precision,recall,thresholds=precision_recall_curve(y_test,probs,pos_label=0)
plt.plot(recall,precision)
plt.title("Precision-Recall Curve")
plt.xlabel("recall")
plt.ylabel("precision")
pd.DataFrame([precision,recall,thresholds])
6.2 ROC 曲线
python
probs=model.predict_proba(X_test)[:,1]
fpr,tpr,thresholds=roc_curve(y_test,probs,pos_label=1)
roc_auc = auc(fpr, tpr)
plt.plot(fpr,tpr, label=f'ROC curve (area = {roc_auc:.2f})')
plt.plot([0, 1], [0, 1], linestyle='--')
plt.title("roc_curve")
plt.xlabel("fpr")
plt.ylabel("tpr")
plt.legend(loc='lower right')
plt.show()
AUC 在 0.8 到 0.9 之间,表明模型具有良好的性能,可以有效地区分正例和负例。