机器学习(回归七)——逻辑回归-代码实现

上篇博客说的是逻辑回归的基本内容,包括公式推导,总体来说,和普通线性回归差不多。这篇博客使用逻辑回归基于病理数据进行乳腺癌预测。

数据

数据的来源: Breast Cancer Wisconsin (Original) Data Set
数据概要:
在这里插入图片描述
数据的属性

在这里插入图片描述

翻译过来,大致内容:

属性信息:

  1. 样本编号:id编号
  2. 簇厚:1 - 10
  3. 细胞大小均匀性:1 - 10
  4. 细胞形状均匀性:1 - 10
  5. 边缘附着力:1 - 10
  6. 单个上皮细胞大小:1 - 10
  7. 裸核:1 - 10
  8. 温和的染色质:1 - 10
  9. 正常核仁:1 - 10
  10. 有丝分裂:1 - 10
  11. 类别:(良性2人,恶性4人)

看几条具体数据
在这里插入图片描述

代码

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import pandas as pd
import warnings
import sklearn
from sklearn.linear_model import LogisticRegressionCV,LinearRegression	# 交叉验证逻辑回归
from sklearn.linear_model.coordinate_descent import ConvergenceWarning	# 普通逻辑回归
from sklearn.model_selection import train_test_split	# 数据划分
from sklearn.preprocessing import StandardScaler		# 标准化

## 设置字符集,防止中文乱码
mpl.rcParams['font.sans-serif']=[u'simHei']
mpl.rcParams['axes.unicode_minus']=False
## 拦截异常
warnings.filterwarnings(action = 'ignore', category=ConvergenceWarning)

## 数据读取并处理异常数据
path = "datas/breast-cancer-wisconsin.data"
names = ['id','Clump Thickness','Uniformity of Cell Size','Uniformity of Cell Shape',
         'Marginal Adhesion','Single Epithelial Cell Size','Bare Nuclei',
        'Bland Chromatin','Normal Nucleoli','Mitoses','Class']

df = pd.read_csv(path, header=None,names=names)

datas = df.replace('?', np.nan).dropna(how = 'any') # 只要有列为空,就进行删除操作
datas.head(5) ## 显示一下

在这里插入图片描述

# 1. 数据提取以及数据分隔
## 提取
X = datas[names[1:10]]
Y = datas[names[10]]
## 分隔
X_train,X_test,Y_train,Y_test = train_test_split(X,Y,test_size=0.1,random_state=0)

# 2. 数据格式化(归一化)
ss = StandardScaler()
X_train = ss.fit_transform(X_train) ## 训练模型及归一化数据

# 3. 模型构建及训练
## penalty: 过拟合解决参数,l1或者l2
## solver: 参数优化方式
### 当penalty为l1的时候,参数只能是:liblinear(坐标轴下降法);
### nlbfgs和cg都是关于目标函数的二阶泰勒展开
### 当penalty为l2的时候,参数可以是:lbfgs(拟牛顿法)、newton-cg(牛顿法变种),seg(minibatch)
# 维度<10000时,lbfgs法比较好,   维度>10000时, cg法比较好,显卡计算的时候,lbfgs和cg都比seg快
## multi_class: 分类方式参数;参数可选: ovr(默认)、multinomial;这两种方式在二元分类问题中,效果是一样的;在多元分类问题中,效果不一样
### ovr: one-vs-rest, 对于多元分类的问题,先将其看做二元分类,分类完成后,再迭代对其中一类继续进行二元分类
### multinomial: many-vs-many(MVM),即Softmax分类效果
## class_weight: 特征权重参数
### TODO: Logistic回归是一种分类算法,不能应用于回归中(也即是说对于传入模型的y值来讲,不能是float类型,必须是int类型)
lr = LogisticRegressionCV(multi_class='ovr',fit_intercept=True, Cs=np.logspace(-2, 2, 20), cv=2, penalty='l2', solver='lbfgs', tol=0.01)
re=lr.fit(X_train, Y_train)

# 4. 模型效果获取
r = re.score(X_train, Y_train)
print ("R值(准确率):", r)
print ("稀疏化特征比率:%.2f%%" % (np.mean(lr.coef_.ravel() == 0) * 100))
print ("参数:",re.coef_)
print ("截距:",re.intercept_)
print(re.predict_proba(X_test)) # 获取sigmoid函数返回的概率值

R值(准确率): 0.9706840390879479
稀疏化特征比率:0.00%
参数: [[1.3926311 0.17397478 0.65749877 0.8929026 0.36507062 1.36092964
0.91444624 0.63198866 0.75459326]]
截距: [-1.02717163]
[[6.61838068e-06 9.99993382e-01]
[3.78575185e-05 9.99962142e-01]
[2.44249065e-15 1.00000000e+00]
[0.00000000e+00 1.00000000e+00]
[1.52850624e-03 9.98471494e-01]
[6.67061684e-05 9.99933294e-01]
[6.75536843e-07 9.99999324e-01]
[0.00000000e+00 1.00000000e+00]
[2.43117004e-05 9.99975688e-01]
[6.13092842e-04 9.99386907e-01]
[0.00000000e+00 1.00000000e+00]
[2.00330728e-06 9.99997997e-01]
[0.00000000e+00 1.00000000e+00]
[3.78575185e-05 9.99962142e-01]
[4.65824155e-08 9.99999953e-01]
[5.47788703e-10 9.99999999e-01]
[0.00000000e+00 1.00000000e+00]
[0.00000000e+00 1.00000000e+00]
[0.00000000e+00 1.00000000e+00]
[6.27260778e-07 9.99999373e-01]
[3.78575185e-05 9.99962142e-01]
[3.85098865e-06 9.99996149e-01]
[1.80189197e-12 1.00000000e+00]
[9.44640398e-05 9.99905536e-01]
[0.00000000e+00 1.00000000e+00]
[0.00000000e+00 1.00000000e+00]
[4.11688915e-06 9.99995883e-01]
[1.85886872e-05 9.99981411e-01]
[5.83016713e-06 9.99994170e-01]
[0.00000000e+00 1.00000000e+00]
[1.52850624e-03 9.98471494e-01]
[0.00000000e+00 1.00000000e+00]
[0.00000000e+00 1.00000000e+00]
[1.51713085e-05 9.99984829e-01]
[2.34685008e-05 9.99976531e-01]
[1.51713085e-05 9.99984829e-01]
[0.00000000e+00 1.00000000e+00]
[0.00000000e+00 1.00000000e+00]
[2.34685008e-05 9.99976531e-01]
[0.00000000e+00 1.00000000e+00]
[9.97563915e-07 9.99999002e-01]
[1.70686321e-07 9.99999829e-01]
[1.38382134e-04 9.99861618e-01]
[1.36080718e-04 9.99863919e-01]
[1.52850624e-03 9.98471494e-01]
[1.68154251e-05 9.99983185e-01]
[6.66097483e-04 9.99333903e-01]
[0.00000000e+00 1.00000000e+00]
[9.77502258e-07 9.99999022e-01]
[5.83016713e-06 9.99994170e-01]
[0.00000000e+00 1.00000000e+00]
[4.09496721e-06 9.99995905e-01]
[0.00000000e+00 1.00000000e+00]
[1.37819117e-06 9.99998622e-01]
[6.27260778e-07 9.99999373e-01]
[4.52734741e-07 9.99999547e-01]
[0.00000000e+00 1.00000000e+00]
[8.88178420e-16 1.00000000e+00]
[1.06976766e-08 9.99999989e-01]
[0.00000000e+00 1.00000000e+00]
[2.45780192e-04 9.99754220e-01]
[3.92389040e-04 9.99607611e-01]
[6.10681985e-05 9.99938932e-01]
[9.44640398e-05 9.99905536e-01]
[1.51713085e-05 9.99984829e-01]
[2.45780192e-04 9.99754220e-01]
[2.45780192e-04 9.99754220e-01]
[1.51713085e-05 9.99984829e-01]
[0.00000000e+00 1.00000000e+00]]

这里还需要详细的说明一下:
逻辑回归用于二分类,如果是二分类,和普通的逻辑回归是一样的,对于多分类有两种(通过multi_class参数设置)
ovr(默认):比如现在有ABCD四类,分别训练四个模型

  • 模型1:A(对应为1类),BCD(对应为0类)
  • 模型2:B(对应为1类),ACD(对应为0类)
  • 模型3:C(对应为1类),ABD(对应为0类)
  • 模型4:D(对应为1类),ACD(对应为0类)

对于样本x,如果通过模型1返回1,则该样本属于A类。所以最终转化成了四个二分类的问题。

multinomial:many-vs-many(MVM),即SoftMax分类效果。(后面博客会有详细介绍)

还有一点:对于逻辑回归,API中没有阈值参数,默认是以0.5为分割点,大于的为1类,小于的为0类。我们可以自行调整。

# # 5. 模型相关信息保存
# ## 引入包
# from sklearn.externals import joblib
# ## 要求文件夹必须存在
# joblib.dump(ss, "datas/logistic/ss.model") ## 将标准化模型保存
# # joblib.dump(lr, "datas/models/logistic/lr.model") ## 将模型保存

# # 模型加载
# ## 引入包
# from sklearn.externals import joblib
# oss = joblib.load("models/logistic/ss.model")
# olr = joblib.load("models/logistic/lr.model")
# 数据预测
## a. 预测数据格式化(归一化)
X_test = ss.transform(X_test) # 使用模型进行归一化操作

## b. 结果数据预测
Y_predict = re.predict(X_test)

## c. 图表展示
x_len = range(len(X_test))
plt.figure(figsize=(14,7), facecolor='w')
plt.ylim(0,6)
plt.plot(x_len, Y_test, 'ro',markersize = 8, zorder=3, label=u'真实值')
plt.plot(x_len, Y_predict, 'go', markersize = 14, zorder=2, label=u'预测值,$R^2$=%.3f' % re.score(X_test, Y_test))
plt.legend(loc = 'upper left')
plt.xlabel(u'数据编号', fontsize=18)
plt.ylabel(u'乳腺癌类型', fontsize=18)
plt.title(u'Logistic回归算法对数据进行分类', fontsize=20)
plt.show()

看一下效果:
在这里插入图片描述
红色的点 \color {#F00} { \bullet} 表示的真实值,绿色的点 \color {#0F0} { \bullet} 是我们预测的值,最终结果还是比较不错的。

发布了119 篇原创文章 · 获赞 350 · 访问量 48万+

猜你喜欢

转载自blog.csdn.net/zhanglianhai555/article/details/104119140