文末重磅福利|Python实现回归预测及模型优化

2020-06-19 15:34:02 浏览数 (1)

前言

大家好,之前写多了自动化办公的内容,现在换个机器学习的专题跟大家交流学习,作为一个眼科研究生后面也希望后面多通过一些眼科案例顺带普及下眼科知识!在眼科中AI的一项应用就是利用卷积神经网络实现图像识别。今天先从一个虚构的冠心病数据集说说python如何实现简单的有监督学习

数据说明

因文章以分享技术为目的,疾病数据集不含有现实意义,且出于保护目的将四个特征指标以S1-S4替代

400 多位病人的数据,包含年龄、性别(1为男性,2为女性),S1-S4为4个冠心病检测指标,Results是冠心病高相关性的定量指标,也是我们本次设计模型需要预测的指标

有监督学习是指有目标变量或预测目标的机器学习方法,包括分类和回归

本例中需要预测的是连续的定量指标,属于回归问题。作为入门介绍就简单利用scikit-learn库中的LinearRegression()实现

初步代码实现

首先导入需要的库并设置好文件路径

代码语言:javascript复制
import pandas as pd
# 分隔训练集和测试集,本例用7:3
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
import os

# 利用函数定位到桌面文件夹,个人习惯。可指定绝对路径
def GetDesktopPath():
    return os.path.join(os.path.expanduser("~"), 'Desktop')

dat_path = f'{GetDesktopPath()}\data\冠心病.csv'

指定特征列(需要纳入预测模型的指标)

代码语言:javascript复制
features = ['Age', 'Sex', 'S1', 'S2', 'S3', 'S4']

读取数据集并分隔

代码语言:javascript复制
CAD_data = pd.read_csv(dat_path)
X = CAD_data[features].values
y = CAD_data['Results'].values

# 分割数据集,本例训练集和测试集分割比例为7:3
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=3/10, random_state=10)

random_state参数设置的好处:

  • 读入数据集如果是有序整理好的,如果不随机则模型构建效果大打折
  • 类似于R语言的set.seed()函数,设定生成随机数的种子,让结果能够重现

现在建立线性回归模型,并进行训练及验证

代码语言:javascript复制
linear_model = LinearRegression()
linear_model.fit(X_train, y_train)
R2 = linear_model.score(X_test, y_test)
print('基础线性模型的R2值为:{:.4f}'.format(R2))

# 基础线性模型的R2值为:0.4100

模型优化

上述基础线性回归模型存在几个问题:

  • 不同的数值变量所处的范围不同,可以考虑归一化,消除量纲或者其他因素可能引入的偏差,影响模型精度。有一种常用方法是将数值线性缩放到 [-1, 1] 或 [0, 1]
  • 性别是分类变量,男女彼此没有高低之分。抽象来说就是离散特征的取值之间没有大小的意义,但用 1 和 0 代替分类变量进入模型中会引入数值大小的区别。数据预处理针对这类变量可以考虑使用独热编码 (One-Hot Encode),又称一位有效编码,其方法是使用N位状态寄存器来对N个状态进行编码。独热编码在各类算法中运用广泛,这里只是非常简单的运用。简单理解就是男性 -> [0, 1],女性 -> [1, 0]

综上,对特征进行分类后分别进行相应的处理,有时会使模型性能提升。这属于特征工程的范畴,仅类别特征可再细分为:

有兴趣的读者可以自行了解。下面是优化模型的代码。

首先引入所需库

代码语言:javascript复制
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
import os
# 引入numpy库做多维数据合并
import numpy as np 
# 数据预处理用到的独热编码和最大最小归一化
from sklearn.preprocessing import OneHotEncoder, MinMaxScaler

def GetDesktopPath():
    return os.path.join(os.path.expanduser("~"), 'Desktop')

dat_path = f'{GetDesktopPath()}\data\冠心病.csv'

特征分类

代码语言:javascript复制
numeric_features = ['Age', 'S1', 'S2', 'S3', 'S4']
category_features = ['Sex']numeric_features = ['Age', 'S1', 'S2', 'S3', 'S4']
category_features = ['Sex']

读取数据

代码语言:javascript复制
CAD_data = pd.read_csv(dat_path)

X = CAD_data[numeric_features   category_features]
y = CAD_data['Results']

数据预处理,注意训练集和测试集的特征都需要预处理,因此可以考虑封装成函数方便调用

代码语言:javascript复制
def preprocessing(train, test):
    # 独热编码处理分类变量
    encoder = OneHotEncoder(sparse=False)
    encoded_train = encoder.fit_transform(train[category_features])
    encoded_test = encoder.transform(test[category_features])
    # 归一化处理数值变量
    scaler = MinMaxScaler()
    scaled_train = scaler.fit_transform(train[numeric_features])
    scaled_test = scaler.transform(test[numeric_features])
    # 横向合并
    train_new = np.hstack((encoded_train, scaled_train))
    test_new = np.hstack((encoded_test, scaled_test))
    # 返回数据
    return train_new, test_new

分隔数据集并对特征预处理

代码语言:javascript复制
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=3/10, random_state=10)
X_train_new, X_test_new = preprocessing(X_train, X_test)

最后构建新模型,训练并验证

代码语言:javascript复制
linear_model_new = LinearRegression()
linear_model_new.fit(X_train_new, y_train)
R2_new = linear_model_new.score(X_test_new, y_test)
print('优化线性模型的R2值为:{:.4f}'.format(R2_new))

我们看一下结果,并跟旧模型进行比对

结束语

其实这个结果并不出乎意料,样本量小也是特征预处理不能发挥出显著优化作用的一个原因。另外,针对模型优化可以再指出的一点是,如果特征较多时往往也不会全部纳入模型中拟合,也要考虑相关性做适当舍弃剪裁。例如本例中实际上去掉年龄Age特征后模型的R值上升会比直接预处理更明显!

当然,本实例的目的不是为了将模型优化的多好,而是希望通过这个简单的案例能够吸引更多的人学习Python,学习人工智能,并用于现实世界,产生新的思想并创造价值!

端午节就要来了,腾讯云 社区联合早起Python给大家送10份腾讯云 社区定制五芳斋粽子礼盒

现在公布赠送规则,一定要按照要求参与才有机会获得!

活动1:长按扫描下方二维码登陆并关注我的云 社区主页,截图发送到公众号后台并回复粽子即可参与抽奖,一共抽出5份

活动2:点亮文末在看并登陆腾讯云 社区,评论我的任意一篇云 社区文章,将从中抽取优质评论赠送粽子4份

活动3:点亮文末在看并点击下方文字给我留言(不限主题),点赞第一赠粽子1份

点击给我留言

最后再次感谢腾讯云 社区对本活动的支持,祝各位好运!

注1:为保证粽子能及时送达幸运读者的手中,本次活动截止时间为6.18日22点!

注2:以上三个活动可以同时参加,但同一用户只能获得一份礼盒!

注3:本次活动将不再单独发文公布获赠名单,所以请所有参与用户添加早小起微信(sshs321)关注最新消息。同时一定要仔细阅读规则参与,谢谢!

0 人点赞