心脏病分类预测--逻辑回归
一、问题背景
利用逻辑回归算法实现心脏病预测。
二、数据集分析
- 数据集位置:https://www.kaggle.com/ronitf/heart-disease-uci
- 该数据集包含共303个实例,并拥有14个字段。这些字段的具体说明如下:
| 属性 | 含义 |
|---|---|
| age | 年龄 |
| sex | 性别 1=male,0=female |
| cp | 胸痛类型(4种) 值1:典型心绞痛,值2:非典型心绞痛,值3:非心绞痛,值4:无症状 |
| trestbps | 静息血压 |
| chol | 血清胆固醇 |
| fbs | 空腹血糖 >120mg/dl ,1=true; 0=false |
| restecg | 静息心电图(值0,1,2) |
| thalach | 达到的最大心率 |
| exang | 运动诱发的心绞痛(1=yes;0=no) |
| oldpeak | 相对于休息的运动引起的ST值(ST值与心电图上的位置有关) |
| slope | 运动高峰ST段的坡度 Value 1: upsloping向上倾斜, Value 2: flat持平, Value 3: downsloping向下倾斜 |
| ca | The number of major vessels(血管) (0-3) |
| thal | A blood disorder called thalassemia (3 = normal; 6 = fixed defect; 7 = reversable defect) 一种叫做地中海贫血的血液疾病(3 =正常;6 =固定缺陷;7 =可逆转缺陷) |
| target | 目标变量(数字0和1) |
注:slope特征:
通过坡度方向降低ST段心电图结果

ST段和T波异常与正常ST段比较

三、代码实现
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import f1_score
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix
from sklearn.metrics import precision_recall_curve
from sklearn.metrics import roc_curve
from sklearn.metrics import roc_auc_score
# 解决matplotlib中文问题
from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体
mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
# 导入数据
df = pd.read_csv(r'C:\Users\bo.chen\Desktop\heart.csv')
df.info()
df.describe()
df.target.value_counts()
plt.figure()
sns.countplot(x='target',data=df,palette="muted")
plt.xlabel("得病/未得病比例")
plt.Text(0.5,0,'得病/未得病比例')
df.sex.value_counts()
plt.figure()
sns.countplot(x='sex',data=df,palette="Set3")
plt.xlabel("Sex (0 = 女, 1= 男)")
plt.Text(0.5,0,'Sex (0 = 女, 1= 男)')
# 数据处理,对特征中非连续型数值进行处理
first = pd.get_dummies(df['cp'], prefix = "cp")
second = pd.get_dummies(df['slope'], prefix = "slope")
thrid = pd.get_dummies(df['thal'], prefix = "thal")
df = pd.concat([df,first,second,thrid], axis = 1)
df = df.drop(columns = ['cp', 'slope', 'thal'])
print(df.head(3))
# 将特征与目标分开
X = df.drop(['target'], axis = 1)
y = df.target.values
# 分割数据集
X_train,X_test,y_train,y_test = train_test_split(X,y,random_state=6) #随机种子6
# 标准化处理
standardScaler = StandardScaler()
standardScaler.fit(X_train)
X_train = standardScaler.transform(X_train)
X_test = standardScaler.transform(X_test)
# 逻辑回归模型
log_reg = LogisticRegression(solver='liblinear')
log_reg.fit(X_train,y_train)
print(log_reg.score(X_test,y_test))
y_predict = log_reg.predict(X_test)
# 调用accuracy_score计算分类准确度
print(accuracy_score(y_test,y_predict))
# 使用网格搜索找出更好的模型参数
param_grid = [
{
'C':[0.01,0.1,1,10,100],
'penalty':['l2','l1'],
'class_weight':['balanced',None]
}
]
grid_search = GridSearchCV(log_reg,param_grid,cv=10,n_jobs=-1)
grid_search.fit(X_train,y_train)
print(grid_search.best_estimator_)
print(grid_search.best_score_)
print(grid_search.best_params_)
log_reg = grid_search.best_estimator_
log_reg.score(X_test,y_test)
# 查看F1指标
print(f1_score(y_test,y_predict))
print(classification_report(y_test,y_predict))
# 绘制混淆矩阵
cnf_matrix = confusion_matrix(y_test,y_predict)
def plot_cnf_matirx(cnf_matrix,description):
class_names = [0,1]
fig,ax = plt.subplots()
tick_marks = np.arange(len(class_names))
plt.xticks(tick_marks,class_names)
plt.yticks(tick_marks,class_names)
#create a heat map
sns.heatmap(pd.DataFrame(cnf_matrix), annot = True, cmap = 'OrRd',
fmt = 'g')
ax.xaxis.set_label_position('top')
plt.tight_layout()
plt.title(description, y = 1.1,fontsize=16)
plt.ylabel('实际值0/1',fontsize=12)
plt.xlabel('预测值0/1',fontsize=12)
plt.show()
plot_cnf_matirx(cnf_matrix,'Confusion matrix -- Logistic Regression')
decision_scores = log_reg.decision_function(X_test)
precisions,recalls,thresholds = precision_recall_curve(y_test,decision_scores)
plt.plot(thresholds,precisions[:-1])
plt.plot(thresholds,recalls[:-1])
plt.grid()
plt.show()
# 绘制ROC曲线
fprs,tprs,thresholds = roc_curve(y_test,decision_scores)
def plot_roc_curve(fprs,tprs):
plt.figure(figsize=(8,6),dpi=80)
plt.plot(fprs,tprs)
plt.plot([0,1],linestyle='--')
plt.xticks(fontsize=13)
plt.yticks(fontsize=13)
plt.ylabel('TP rate',fontsize=15)
plt.xlabel('FP rate',fontsize=15)
plt.title('ROC曲线',fontsize=17)
plt.show()
plot_roc_curve(fprs,tprs)
# 求面积,相当于求得分
# auc:area under curve
print(roc_auc_score(y_test,decision_scores))
AI助手


四、逻辑回归
①定义:Logistic回归模型被归类为一种经典的分类算法。尽管其名称中包含'回归'一词,在本质上它被视为解决分类问题的标准方法,并通过借鉴回归分析的方法来实现对离散类别变量的预测任务。
Logistic Regression回归模型属于sklearn.linear_model.Logistic分支类模型,在该模型中其核心参数包括哪些?
回归模型参数设置如下:C参数设为1.0(即正则化强度设为1.0),无类别加权配置(class_weight=None)。对偶模式关闭(dual=False)。在线性回归中包含截距项(fit_intercept=True),并且截距缩放因子设定为1(intercept_scaling=1)。最大迭代次数设定为100(max_iter=100)。多分类任务采用二元分类器策略(multi_class='ovr')。使用单个处理器完成计算任务(n_jobs=1)。正则化项选择L2范数形式(penalty='l2')。随机种子设置为默认值(random_state=None)。选择liblinear算法求解问题(solver='liblinear')。模型收敛阈值设定为很小的值(tol=0.0001),并抑制训练过程信息输出(verbose=0)。同时不使用前一次模型的系数作为初始值(warm_start=False)
penalty:用于选择正则化的参数项,默认采用的是L_2范数的惩罚项;该参数支持两种取值选项:l_1与l_2两种形式;其中l_1对应基于L_1范数的惩罚项实现;而l_2则是基于L_2范数的标准惩罚项方法。
该模型的正则化参数调节主要目的是解决过拟合问题。通常情况下,我们会选择L2正则化作为惩罚项(regularization term),因为它能够有效防止模型过于依赖训练数据而提升泛化能力。然而,在某些情况下若采用L2正则化反而导致模型预测效果不佳(预测效果差),此时我们可以考虑转而使用L1正则化(另一种惩罚项形式)。值得注意的是,在面对特征数量极大的复杂模型时,采用L1正则化不仅可以减少不必要的特征权重(系数),还能实现模型系数的稀疏性(sparsity)。此外,在优化算法的选择上需要注意:当采用的是L2惩罚项时('\lambda 2范数),可以选择四种优化算法{‘newton-cg’, ‘lbfgs’, ‘liblinear’, ‘sag’}中的一种;但如果选用的是L1惩罚项,则只能使用‘liblinear’算法(这是因为带有绝对值的L1范数会使损失函数不可导)。
solver :优化算法选择参数,有4种算法可以选择,分别为:
该算法基于开源的liblinear库实现,在算法内部采用了坐标轴下降法逐步优化损失函数。
LBFGS是一种用于迭代优化损失函数的拟牛顿优化算法,其基于损失函数的海森矩阵来进行计算.
Newton-CG 也属于牛顿法家族的一种成员,在优化过程中基于损失函数的二阶导数矩阵——即海森矩阵——来进行迭代优化。
④SAG 即称为随机平均梯度下降法,在优化过程中属于一种改进型的梯度下降方法。其主要区别在于每次迭代时仅使用部分样本数据来计算当前的梯度方向。特别适用于样本数据量较大的情况,在这种场景下 SAG 算法表现出良好的收敛特性,并且其收敛速度显著快于普通的随机 Gradient Descent(SGD)算法。
