前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一把 sklearn 走天下 | 统计师的Python日记 第12天

一把 sklearn 走天下 | 统计师的Python日记 第12天

作者头像
数说君
发布2019-03-07 09:36:34
1.6K0
发布2019-03-07 09:36:34
举报
文章被收录于专栏:数说工作室数说工作室

本文是【统计师的Python日记】第12天的日记

回顾一下:

  • 第1天学习了Python的基本页面、操作,以及几种主要的容器类型。
  • 第2天学习了python的函数、循环和条件、类。
  • 第3天了解了Numpy这个工具库。
  • 第4、5两天掌握了Pandas这个库的基本用法。
  • 第6天学习了数据的合并堆叠。
  • 第7天开始学习数据清洗,着手学会了重复值删除、异常值处理、替换、创建哑变量等技能。
  • 第8天接着学习数据清洗,一些常见的数据处理技巧,如分列、去除空白等被我一一攻破
  • 第9天学习了正则表达式处理文本数据
  • 第10天学习了数据的聚合操作、数据透视表pivot_table()方法、交叉表crosstab
  • 第11天学习了class类的概念以及如何写一个类

今天将带来第12天的学习日记,开始学习Python的机器学习库:Scikit-learn(这个系列会不断连载,建议关注哦~)。本文会先认识一下 sklearn 这个库,再根据建模流程,学习一下 sklearn 的各个模块的使用。


目录如下:

前言

一、初识 sklearn

二、sklearn 的建模流程

1. 数据导入

2. 数据处理

(1)划分训练集和测试集

(2)数据清洗

3. 特征工程

4. 模型调参/选择

5. 模型测试和评价

6. 模型保存和调用

三、sklearn 建模流程总结 和 一个文本建模的例子


统计师的Python日记【第12天:一把 sklearn 走天下】

前言

前面学习了很多 Python 的数据基本操作,应付一个 project 前期的数据清洗、描述分析已然足够。今天开始要学习数据工程中的重头戏——数据建模。

用 Python 完成一个模型的构建,比较快的可以有三种方法:

① 第一种是完全按照计算逻辑写代码,比如 logistic 回归模型,你可以这么写:

(具体可以看这里:造出一艘logistic模型 | 【logistic从生产到使用】(下)

② 第二种是用最近很火的 tensorflow 开源框架,同样的 logistic 回归,简洁一点的话可以这么写:

③ 第三种是用机器学习库 sklearn,logistic 回归我们只用这么写:

其他还有很多库就不说了,这三种中,第二种或者第三种显然是合理的选择。

  • tensorflow 是一种深度学习框架,用于完成深度学习任务,有很高的自由度,需要自己实现算法。适合数据量较大、一般需要GPU加速的运算。
  • 而sklearn 是通用机器学习库,里面已经包含了很多现成的机器学习模型,以及数据预处理和特征工程。封装的高度抽象化,简单易用,适合中小型的机器学习项目,那种数据量不大、CPU上就可以完成的运算。

所以,对于初学者来说,sklearn是首选,因为它不仅封装了大量的机器学习库,还自带数据集!连学习要用的数据都准备好了,今天,就先学习一下 sklearn。

一、初识sklearn

sklearn 全称是 scikit-learn,它建立在 Numpy 和 matplotlib 的基础上,所以需要注意的是,以下我们介绍的方法,都是适用于 Numpy 数组的哦。现在我们导入这个库:

代码语言:javascript
复制
import sklearn

这个库里面包含了很多数据集、模块和函数,使用某几种函数,可以不用全部导入,用:

代码语言:javascript
复制
from sklearn.模块 import XX

比如:

代码语言:javascript
复制
from sklearn import datasets
from sklearn.feature_selection import SelectKBest
from sklearn.neighbors import KNeighborsClassifier

sklearn 有专门的 feature_selection (特征工程)和 neighbors(近邻算法)模块,下面有对应的方法。如上代码展示:

  • feature_selection 模块下面不仅有 SelectKBest(选出K个得分最高的特征),还有chi2(计算每个特征的卡方值)等等;
  • neighbors模块下不仅有KNeighborsClassifier(K近邻),还有LocalOutlierFactor(LOF异常检测算法)等算法可供调用。

那么 sklearn 主要有哪些模块,每个模块下面有哪些方法呢?

我数了一下 sklearn 的官方介绍,大概37个模块,包含了差不多500种算法实现(http://scikit-learn.org/stable/modules/classes.html)。

这里列出了我们建模常用的一些模块和算法:

其实,只要学习一种方法的典型流程,其他的方法查查资料就可以很快上手。现在我们就以内部数据集为例,用 sklearn 学习一遍整个建模的流程。

二、sklearn 的建模流程

1. 数据导入

(1)导入自带数据

我们要导入最经典的sklearn自带「鸢尾花」数据。先了解一下数据结构,首先,导入数据集 load_iris。

代码语言:javascript
复制
#从sklearn的自带datasets中导入load_iris数据集
from sklearn.datasets import load_iris 
iris = load_iris()

看下数据的结构,用keys来看:

代码语言:javascript
复制
print (iris.keys())

结果如下:

代码语言:javascript
复制
dict_keys(['target_names', 'target', 'data', 'feature_names', 'DESCR'])

target 是标签数据,target_names 标签每个类别的意义,data 是特征数据, feature_names 是特征列名,DESCR 是关于此数据的一个全面描述。

比如查看 target.name,数据的lable分类:

代码语言:javascript
复制
print(iris.target_names)

可知lable一共有三类。同理 iris.target 就是具体 lable 的数据,iris.data 就是特征的数据了。

代码语言:javascript
复制
print(iris.target)

我们也可以直接来看 DESCR,有更全面的介绍:

代码语言:javascript
复制
print(iris.DESCR)

从描述可以看出,这个数据

  • 一共150行;
  • label 是鸢尾花的类型,有三类:Setosa/Versicolour/Virginica;
  • 共四个特征:萼片sepal的长度和宽度,花瓣petal的长度和宽度,我们就要用这四个特征,来预测鸢尾花的类型。

如果是外部数据,我们可以用 pandas 的read_csv工具来导入,详见 第5天:Pandas,露两手

2. 数据处理

(1)划分数据集

首先是训练集和测试集的划分,在Python中建模,我们至少需要四个子数据集:

  • 训练数据-特征列
  • 训练数据-label列
  • 测试数据-特征列
  • 测试数据-label列

记得在 SAS 中,特征和lable是不需要分开的,在一个数据集中,建模的时候只需要在proc过程中指定出哪一列是 lable 就好。在Python中是需要分开的。

训练数据和测试数据的划分,可以用 train_test_split() 处理,以 iris 数据为例,划分方式如下:

代码语言:javascript
复制
from sklearn.model_selection import train_test_split
X=iris.data
y=iris.target
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.3,random_state=0)

test_size 指定测试样本的比例,random_state 是随机数种子,如果random_state的设置是相同的,那么别人运行你的代码就会和你得到完全一样的数据。

(2)数据清洗

现在数据已经导入,用 preprocessing 来做一些预处理:

  • 填充缺失值:
代码语言:javascript
复制
from sklearn.preprocessing import Imputer
impt= Imputer(missing_values='NaN', strategy='mean', axis=0)
#还可以用"median"、"most_frequent"等来填充          
impt.fit(X)         
impt.transform(X) 
  • 数据标准化(有时候特征的量纲不一致,或者存在很多异常值,需要进行标准化处理)
代码语言:javascript
复制
from sklearn import preprocessing
X_scale = preprocessing.scale(X)  

在前面我们也学习了Pandas Dataframe数据的一些预处理方法(详见 第5天:Pandas,露两手第7天:数据清洗(1)),比如:

  • 丢弃缺失值:df.dropna()
  • 填充缺失值:data.fillna()

等等,可以在Dataframe中处理好,再转换成 Numpy array 数组。

3. 特征工程

我们现在对这四个特征进行筛选,使用 feature_selection 模块的 SelectFpr 来进行选择,选出P值在0.01以下的特征。格式是:

selectFpr(<func>, alpha)

<func>是筛选的统计方法,默认是方差检验的F检验对应p值,此外还可以选chi2(卡方检验)

  • f_regression(回归的F检验P值)
  • mutal_info_regression(利用特征和标签之间的互信息)
  • 等等,具体可查阅官网
代码语言:javascript
复制
from sklearn.feature_selection import SelectFpr
selectFea=SelectFpr(alpha=0.01)
X_train_new = selectFea.fit_transform(X_train, y_train)
X_test_new = selectFea.transform(X_test)

这里 fit_transform() 在数据处理环节我们会经常看到,

A.fit_transform()

以及

A.transform()

A.fit_transform()

是对前面的方法A先进行数据拟合fit,如果A是一个标准化处理的方法,那么fit就可以拟合出数据的均值、方差等参数。这里A是要选择P值,fit就会拟合出每个特征的P值等......再利用这些参数对数据进行transform(),得到最终我们要的数据。

A.transform()

按照上面说的,这个就是直接对已经fit过的进行transform了。通常train的数据既要fit又要transform,测试数据只要也必须要transform。“只要”是因为已经fit过了,就用测试集fit的结果,“必须要”是测试集的特征选择必须要和训练集的选择结果一致。

特征选择的时候,我们通常不会那么粗暴,还会综合考虑特征的IV值、WOE分等,网上很多代码,推荐学习:https://www.sohu.com/a/227312722_479788

4. 模型调参/选择

选择完特征,我们需要选择一个合适的模型。思路是:

先指定若干分类模型,每个模型在测试数据集上进行参数的【网格搜索+交叉验证】,选出表现最好的模型和其参数。

首先,导入一些待验证的分类模型:

代码语言:javascript
复制
#MultinomialNB 离散型朴素贝叶斯
from sklearn.naive_bayes import MultinomialNB
#LogisticRegression 逻辑回归
from sklearn.linear_model import LogisticRegression
#DecisionTreeClassifier 决策树
from sklearn.tree import DecisionTreeClassifier
#SVC 支持向量分类
from sklearn.svm import SVC

关于交叉验证,之前有学习过:

K折交叉验证可以充分利用少样本的信息。 K折交叉验证是将样本分成K个子样本集,拿出其中的K-1个子样本集来训练模型,用剩下的1个子样本集来对模型进行验证;再拿出K-1个训练模型,留下另外1个(与上一步的不同)子样本集进行验证......,如此交叉验证K次,每个子样本集验证1次,平均K次的结果作为一个模型的预测效果。

具体可见这里:留一交叉验证及SAS代码

交叉验证可充分利用样本的信息,在我们调参的时候,如果有多个模型供选择,或者一个模型需要选择一个最好的参数时,我们可以对每个模型进行一轮交叉验证,看那个模型或参数的效果最好。

但是有一个问题,那么多模型,每个模型都要试不同的参数甚至参数组合,这样成本是不是太高了?用For循环去试,又不够灵活,层次太分明。网格搜索解决这个问题的一个利器。Sklearn 的 GridSearchCV 就有一个现成的子模块可以用。它其实就是代替了人工暴力穷举,并且把很多功能包在了一起,让我们在调参时很方便。子模块的调用如下:

代码语言:javascript
复制
from sklearn.model_selection import GridSearchCV

GridSearchCV 的参数,常用的如下:

GridSearchCV(estimator, param_grid, scoring, cv)

  • estimator 是分类器,如 DecisionTreeClassifier();
  • parameter 是一个字典,它用来限定参数范围,一般取值是 {’参数名‘: 参数范围},比如决策树的参数一般是max_depth,其范围我们可以限定为 param_grid= {'max_depth': xrange(1, 10)},SVC 的参数有核函数(kernel),C 和 gamma,我们可以限定为: param_grid= {'kernel':('linear', 'rbf'), 'C':[1, 2, 4], 'gamma':[0.125, 0.25, 0.5 ,1, 2, 4]};
  • cv:交叉验证参数,指定K折验证,默认是3;
  • scoring 是模型的评价准则,如 roc_auc/recall/precision 等,可以缺失,默认使用 estimator 的误差估计函数,可选如下(来源官网):

关于 GribSearchCV 更详细的说明也可以看官网:

https://scikit-learn.org/0.17/modules/generated/sklearn.grid_search.GridSearchCV.html

需要注意的是,GribSearchCV 适合数据量比较小的场景,一旦数据量较大,就特别耗费计算资源和时间,此时还是得结合建模经验进行半手动调参,比如,可以先对一个影响最大得参数进行调参,得到最优后再调下一个参数,直到所有参数调节完,但这样得到得是一个局部最优而不是全局最优。

以 DecisionTreeClassifier 为例,我们可以这样使用网格搜索:

代码语言:javascript
复制
from sklearn.model_selection import GridSearchCV

clf_DT=DecisionTreeClassifier()
param_grid_DT= {'max_depth': [1,2,3,4,5,6]}
grid=GridSearchCV(clf_DT, param_grid_DT, scoring='roc_auc', cv=5)
grid.fit(X_train, y_train)

然而,得到的结果是:

注意,有人会认为是 DecisionTreeClassifier 只能解决二分类的问题,并不是。当数据是多分类时,就算是 sklearn 的二分类器,也将多分类的转换处理考虑了进来,处理方法通常是 'ovr',即one-vs-rest,顾名思义,就是某一类相对于其他类的可能,将多分类做多次2分类,来实现多分类的问题。

比如 LogisticRegression(),有一个默认的参数 multiclass=’ovr' 参数,SVC() 也有一个默认的参数 decision_function_shape='ovr',当数据是多分类时,都会自动用ovr算法进行处理。

这里报错是因为scoring='roc_auc',这个评价方法只适用于二分类,我们索性换成 accuracy:

代码语言:javascript
复制
from sklearn.model_selection import GridSearchCV

clf_DT=DecisionTreeClassifier()
param_grid_DT= {'max_depth': [1,2,3,4,5,6]}
grid=GridSearchCV(clf_DT, param_grid_DT, scoring='accuracy', cv=5)
grid.fit(X_train, y_train)

print (grid.best_score_)
print (grid.best_params_)

用 best_score_ 查看最高的得分,用 best_params_ 查看最优的参数,print 结果是:

代码语言:javascript
复制
0.9523809523809523
{'max_depth': 5}

现在对这4个模型,我们都搜索一遍参数:

代码语言:javascript
复制
from sklearn.model_selection import GridSearchCV

clf_DT=DecisionTreeClassifier()
param_grid_DT= {'max_depth': [1,2,3,4,5,6]}

clf_MNB=MultinomialNB()
param_grid_MNB= {'alpha': [0.01,0.05,0.1,0.25,0.5,0.7,1]}

clf_Logit=LogisticRegression()
param_grid_logit= {'solver': ['liblinear','lbfgs','newton-cg','sag']}

clf_svc=SVC()
param_grid_svc={'kernel':('linear', 'rbf'), 
                'C':[1, 2, 4], 
                'gamma':[0.125, 0.25, 0.5 ,1, 2, 4]}

clf=[clf_DT,clf_MNB,clf_Logit,clf_svc]
param_grid=[param_grid_DT,param_grid_MNB,param_grid_logit,param_grid_svc]


for i in range(0,4):
    grid=GridSearchCV(clf[i], param_grid[i], scoring='accuracy', cv=5)
    grid.fit(X_train, y_train)
    print (grid.best_params_,': ',grid.best_score_)

输出结果是:

代码语言:javascript
复制
{'max_depth': 4} :  0.9523809523809523
{'alpha': 0.01} :  0.7047619047619048
代码语言:javascript
复制
{'solver': 'sag'} :  0.9619047619047619
{'C': 2, 'kernel': 'linear', 'gamma': 0.125} :  0.9809523809523809

所以 accuracy 最高的是 SVC,0.98,参数是

{'C': 2, 'kernel': 'linear', 'gamma': 0.125},

我们最终选择的模型:SVC(C=2, kernel='linear', gamma=0.125)

5. 模型测试和评价

我们在训练和调参时,用的是交叉验证,即只用了部分训练数据来训练,确定了最佳模型和参数之后,我们要用所有的训练样本再训练一遍作为预测模型,因为样本不能浪费。

代码语言:javascript
复制
clf=SVC(C=2, kernel='linear', gamma=0.125)
clf.fit(X_train, y_train)
clf.predict(X_test)

clf.predict(X_test),是fit后的模型在 X_test 上进行预测。预测完之后,可以用个 sklearn 的 metric 模块进行模型的评价,比如计算准确率、精准率和召回率:

代码语言:javascript
复制
from sklearn import metrics

y_pred = clf.predict(X_test)

#accuracy
accuracy=metrics.accuracy_score(y_true=y_test, y_pred=y_pred)
print ('accuracy:',accuracy)

#precision
precision=metrics.precision_score(y_true=y_test, y_pred=y_pred,average="micro")
print ('precision:',precision)

#recall
recall=metrics.recall_score(y_true=y_test, y_pred=y_pred,average="micro")
print ('recall:',recall)

#实际值和预测值
print (y_test)
print (y_pred)

注意这里是多分类数据,因此计算精准和找回的时候需要加参数 average="micro"。结果如下:

代码语言:javascript
复制
accuracy: 0.9777777777777777
precision: 0.9777777777777777
recall: 0.9777777777777777
代码语言:javascript
复制
y_test:
[2 1 0 2 0 2 0 1 1 1 2 1 1 1 1 0 1 1 0 0 2 1 0 0 2 0 0 1 1 0 2 1 0 2 2 1 0
 1 1 1 2 0 2 0 0]
y_pred:
[2 1 0 2 0 2 0 1 1 1 2 1 1 1 1 0 1 1 0 0 2 1 0 0 2 0 0 1 1 0 2 1 0 2 2 1 0
 2 1 1 2 0 2 0 0]

我们再用之前其他三个模型的最优参数预测一下,看表现有什么不同,三个模型分别是:

代码语言:javascript
复制
clf_MNB=MultinomialNB(alpha=0.01)
clf_DT=DecisionTreeClassifier(max_depth=4)
clf_logit=LogisticRegression(solver='sag')

具体 code 略去,直接看结果:

代码语言:javascript
复制
clf_MNB:
accuracy: 0.6
precision: 0.6
recall: 0.6
代码语言:javascript
复制
clf_DT:
accuracy: 0.9777777777777777
precision: 0.9777777777777777
recall: 0.9777777777777777
代码语言:javascript
复制
clf_logit:
accuracy: 0.9333333333333333
precision: 0.9333333333333333
recall: 0.9333333333333333

可以看出 SVC 确实是几个模型中表现最好的。

6. 模型保存和调用

模型的保存和调用,使用 sklearn 的 joblib 子模块:

代码语言:javascript
复制
from sklearn.externals import joblib
#模型保存到本地
joblib.dump(clf,'SVC_model.m')
#模型的恢复
clf_tmp=joblib.load('SVC_model.m')

三、sklearn 建模流程总结 和 一个文本分类的例子

现在来总结一下 sklearn 建模的大致流程以及相关知识点:

1. 数据导入

  • sklearn 自带数据集:sklearn.datasets
  • 外部数据导入:pd.read_csv()

2. 数据处理

(1)划分训练集和测试集

  • model_selection.train_test_split()

(2)数据清洗

  • 缺失值填充:preprocessing.Imputer()
  • 数据标准化:preprocessing.scale()

3. 特征工程

  • 根据P值选:feature_selection.SelectFpr()
  • 选出K个最高分特征:feature_selection.SelectKBest()

4. 模型调参/选择

  • 交叉验证+网格搜索:model_selection.GridSearchCV()

5. 模型测试和评价

  • 模型预测:model.predict()
  • Accuracy:metrics.accuracy_score()
  • Presicion:metrics.precision_score()
  • Recall:metrics.recall_score()

6. 模型保存和调用

  • 模型保存:joblib.dump()
  • 模型调用:joblib.load()

以上就是 sklearn 建模的一个大体流程,无论是特征工程还是数据处理、建模,无论是有监督模型还是无监督学习,Sklearn 都封装了成熟的模块供我们调用。

但是,如果数据换成其他一种形式,比如文本数据,我们应该怎么怎么处理?其实仅仅是多了一个文本向量化的过程,回复 sktext 看一个文本建模的例子。

下期预告:tensorflow

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-02-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数说工作室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档