本文作者:陈 鼎,中南财经政法大学统计与数学学院
文字编辑:任 哲
技术总编:张馨月
Logistic回归分析是一种广义的线性回归分析模型,常用于数据挖掘,疾病自动诊断,经济预测等领域。Logistic回归在二十世纪初用于生物科学, 随后被用于许多社会科学应用中。关于该模型的算法和原理介绍,大家可以在今天推送的第二篇推文《Logistic回归理论与模型简介》里了解。在本文中,我们将以良/恶性乳腺癌肿数据集为例,简要介绍Logistic回归的代码实现。
一、代码实现
(一) 读取数据集
本案例使用“良/恶性乳腺癌肿数据集”,该数据集收集了699条病人样本,共11列数据。第一列为检索的患者id,后9列包括了与癌症相关的9个特征指标,分别为肿块厚度(Clump Thickness),细胞大小的均匀性(Uniformity of Cell Size),细胞形状的均匀性(Uniformity of Cell Shape),边际附着力(Marginal Adhesion),单个上皮细胞大小(Single Epithelial Cell Size),裸核(Bare Nuclei),淡色染色质(Bland Chromatin),正常核(Normal Nucleoli),核分裂(mitoses)。类别(class)代表良性/恶性肿瘤,分别以2,4代替。数据中包含16个缺失值,以"?"标出。首先导入下文需要使用的库和数据集:
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
import pandas as pd
import numpy as np
#1.获取数据
column_list = ['Sample code number','Clump Thickness', 'Uniformity of Cell Size','Uniformity of Cell Shape','Marginal Adhesion','Single Epithelial Cell Size','Bare Nuclei','Bland Chromatin','Normal Nucleoli','Mitoses','Class']
dataset = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data"
,names = column_list)
pd.set_option('display.max_columns',None)
dataset.head()
(二) 特征工程
1.处理缺失值
将数据集中带"?"的数据替换成np.nan,再利用Pandas库的dropna函数便能快速地将缺失值删除。代码如下:
dataset = dataset.replace("?",np.nan)
dataset = dataset.dropna()
2.划分数据
分析上述数据集,第一列(Sample code number)是我们不需要的,应将其舍去;最后一列(Class)是我们的预测分类结果。利用sklearn.model_selection库中的train_test_split方法,实现训练集与测试集的划分。
y = dataset['Class']
x = dataset.iloc[:,2:10]
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.25)
x_train,x_test,y_train,y_test的含义在推文《朴素贝叶斯算法——以20Newsgroups数据集为例》中已经阐明,这里不再赘述。
3.数据标准化
为避免异常值对模型拟合产生影响,对每个特征进行标准化。导入sklearn.preprocessing中的StandardScaler,可以方便地对数据集按列进行标准化操作。标准化的公式与代码如下:
std = StandardScaler()
x_train = std.fit_transform(x_train)
x_test = std.transform(x_test)
(三) 进行Logistic回归
导入sklearn.linear_model中的Logistic Regression方法,实例化一个Logistic分类器,传入训练集供分类器学习。值得注意的是,在该案例中,我们需要关注的是查全率而非查准率(放过一个恶性癌症患者所带来的成本与风险要比误诊一个良性癌症患者所带来的成本高得多),因此我们利用sklearn.metrics中的classification_report方法,通过查看其查全率来观察该分类器的预测效果。在预测之前,我们按住ctrl+B定位到LogisticRegression的源码中,可以看到sklearn库中LogisticRegression默认设置的正则化项系数为l2(岭回归),且正则化力度为1.0。如下图所示:
以下是代码实现:
lg = LogisticRegression()
lg.fit(x_train,y_train)
y_predict = lg.predict(x_test)
print("预测模型的系数为:",lg.coef_)
print("测试集的预测结果为:",y_predict)
print("准确率为:",lg.score(x_test,y_test))
print("查准率与查重率:",classification_report(y_test, y_predict, labels=[2,4], target_names=["良性","恶性"],))
其输出结果如下图所示:
从上图输出结果可以看出,模型拟合的十分完美,其中恶性肿瘤的查全率(recall)已经到了99%。这也证明了前文的论断:Logistic回归分析往往在预测癌症,预测广告点击率,电商购物等领域表现良好。Logistic回归与朴素贝叶斯分类器都作为有监督学习,其算法都涉及到预测概率,具有一定的相同之处,但是有如下区别:1.Logistic回归属于判别模型,朴素贝叶斯分类器属于生成模型。2.Logistic回归只能解决二分类问题(多分类问题需依赖softmax与神经网络),朴素贝叶斯分类器可以解决多分类问题。3.Logistic回归具有超参数(如带有岭回归的线性模型中的正则化项系数),其模型可以通过交叉验证法不断优化,朴素贝叶斯分类器则不行。4.Logistic回归在预测患病,广告点击等方面应用广泛,朴素贝叶斯分类器常用于于文本分类中。
二、源码
将上述过程封装成函数,完整代码如下:
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
import pandas as pd
import numpy as np
def logistic():
#获取数据
column_list = ['Sample code number','Clump Thickness', 'Uniformity of Cell Size','Uniformity of Cell Shape','Marginal Adhesion','Single Epithelial Cell Size','Bare Nuclei','Bland Chromatin','Normal Nucleoli','Mitoses','Class']
dataset = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data"
,names = column_list)
pd.set_option('display.max_columns',None)
print(dataset.head())
#删除缺失值
dataset = dataset.replace("?",np.nan)
dataset = dataset.dropna()
#进行数据分割
y = dataset['Class']
x = dataset.iloc[:,2:10]
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.25)
#进行标准化
std = StandardScaler()
x_train = std.fit_transform(x_train)
x_test = std.transform(x_test)
#进行logistic预测
lg = LogisticRegression()
lg.fit(x_train,y_train)
y_predict = lg.predict(x_test)
print("预测模型的系数为:",lg.coef_)
print("测试集的预测结果为:",y_predict)
print("准确率为:",lg.score(x_test,y_test))
print("查准率与查重率:",classification_report(y_test, y_predict, labels=[2,4], target_names=["良性","恶性"],))
if __name__ == '__main__':
logistic()