机器学习(二)——xgboost(实战篇)Pima印第安人数据集上的机器学习-分类算法(根据诊断措施预测糖尿病的发病)

数据集简介
该数据集最初来自国家糖尿病/消化/肾脏疾病研究所。数据集的目标是基于数据集中包含的某些诊断测量来诊断性的预测 患者是否患有糖尿病。
从较大的数据库中选择这些实例有几个约束条件。尤其是,这里的所有患者都是Pima印第安至少21岁的女性。
数据集由多个医学预测变量和一个目标变量组成Outcome。预测变量包括患者的怀孕次数、BMI、胰岛素水平、年龄等。


1 、加载库

 

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

import pandas as pd # 数据科学计算工具
import numpy as np # 数值计算工具
import matplotlib.pyplot as plt # 可视化
import seaborn as sns # matplotlib的高级API
%matplotlib inline # 在Notebook里面作图/嵌图
%config InlineBackend.figure_format = 'retina'
import warnings
warnings.filterwarnings('ignore')


2 、加载数据并作图查看属性分布特征


【1】Pregnancies:怀孕次数 
【2】Glucose:葡萄糖 
【3】BloodPressure:血压 (mm Hg) 
【4】SkinThickness:皮层厚度 (mm) 
【5】Insulin:胰岛素 2小时血清胰岛素(mu U / ml 
【6】BMI:体重指数 (体重/身高)^2 
【7】DiabetesPedigreeFunction:糖尿病谱系功能 
【8】Age:年龄 (岁) 
【9】Outcome:类标变量 (0或1)

pima = pd.read_csv("pima_indians-diabetes.csv") 

pima.head() 


# panda.head()/panda.tail() 查看Series或者DataFrame对象的小样本;显示的默认元素数量的前五个,当然我们可以传递一个自定义数字

pima.shape 
# panda的shape形状属性,给出对象的尺寸(行数目,列数目)

pima.describe() 
# panda的describe描述属性,展示了每一个字段的
#【count条目统计,mean平均值,std标准值,min最小值,25%,50%中位数,75%,max最大值】


Data Visualization - 数据可视化

1.柱状图
pima.hist(figsize=(16,14))  #查看每个字段的数据分布;figsize的参数显示的是每个子图的长和宽


2.散点图

sns.pairplot(pima, hue = "Outcome")

# seaborn常用命令

【1】set_style()是用来设置主题的,Seaborn有5个预设好的主题:darkgrid、whitegrid、dark、white、ticks,默认为darkgrid
【2】set()通过设置参数可以用来设置背景,调色板等,更加常用
【3】displot()为hist加强版
【4】kdeplot()为密度曲线图
【5】boxplot()为箱图
【6】joinplot()联合分布图
【7】heatmap()热点图
【8】pairplot()多变量图,可以支持各种类型的变量分析,是特征分析很好用的工具

3.箱图

pima.plot(kind='box', subplots=True, layout=(3,3), sharex=False,sharey=False, figsize=(16,14))

#pandas.plot作图:数据分为Series 和 DataFrame两种类型;现释义数据为DataFrame的参数

【0】data:DataFrame
【1】x:label or position,default None 指数据框列的标签或位置参数
【2】y:label or position,default None 指数据框列的标签或位置参数
【3】kind:str(line折线图、bar条形图、barh横向条形图、hist柱状图、
               box箱线图、kde Kernel的密度估计图,主要对柱状图添加Kernel概率密度线、
               density same as “kde”、area区域图、pie饼图、scatter散点图、hexbin)
【4】subplots:boolean,default False,为每一列单独画一个子图
【5】sharex:boolean,default True if ax is None else False
【6】sharey:boolean,default False
【7】loglog:boolean,default False,x轴/y轴同时使用log刻度



4.热度图

column_x = pima.columns[0:len(pima.columns) - 1] # 选择特征列,去掉目标列

column_x # 显示所有特征列信息

corr = pima[pima.columns].corr() # 计算变量的相关系数,得到一个N * N的矩阵

plt.subplots(figsize=(14,12)) # 可以先试用plt设置画布的大小,然后在作图,修改
sns.heatmap(corr, annot = True) # 使用热度图可视化这个相关系数矩阵


3、 数据预处理——特征工程

    3.1、特征选择


# 导入和特征选择相关的包

from sklearn.feature_selection import SelectKBest 
from sklearn.feature_selection import chi2

X = pima.iloc[:, 0:8] # 特征列 0-7列,不含第8列
Y = pima.iloc[:, 8] # 目标列为第8列

select_top_4 = SelectKBest(score_func=chi2, k =4) # 通过卡方检验选择4个得分最高的特征
fits = select_top_4.fit(X, Y) #将特征输入到评分函数,获取特征信息和目标值信息
features = fits.transform(X) #展现特征转换后的结果
features[0:5] #新特征列
'''
评分函数
1.SelectKBest()      #只保留K个最高分的特征,能够返回特征评价的得分   SelectKBest(score_func=<function f_classif>, k=10)

2.SelectPercentile() #只保留用户指定百分比的最高得分的特征,能够返回特征评价的得分 SelectPercentile(score_func=<function f_classif>, percentile=10) 
使用常见的单变量统计检验:假正率SelectFpr,错误发现率SelectFdr,或者总体错误率SelectFwe
3.GenericUnivariateSelect() #通过结构化策略进行特征选择,通过超参数搜索估计器进行特征选择
'''

将特征输入到评分函数,返回一个单变量的f_score(F检验的值)或p-values(P值,假设检验中的一个标准,P-value用来和显著性水平作比较),
注意SelectKBest 和 SelectPercentile只有得分,没有p-value。
 其中的参数score_func有以下选项:

【1】回归:f_regression:相关系数,计算每个变量与目标变量的相关系数,然后计算出F值和P值
          mutual_info_regression:互信息,互信息度量X和Y共享的信息:
         它度量知道这两个变量其中一个,对另一个不确定度减少的程度。
【2】分类:chi2:卡方检验
          f_classif:方差分析,计算方差分析(ANOVA)的F值(组间均方/组内均方);
          mutual_info_classif:互信息,互信息方法可以捕捉任何一种统计依赖,但是作为非参数法,            需要更多的样本进行准确的估计。

结果:


pima.head()

# 因此,表现最佳的特征是:Glucose-葡萄糖、Insulin-胰岛素、BMI指数、Age-年龄

构造新特征DataFrame

X_features = pd.DataFrame(data = features, columns=["Glucose","Insulin","BMI","Age"]) # 构造新特征DataFrame

X_features.head()

Y_features = pd.DataFrame(data = y, columns=["Outcome"]) 
# 构造新特征DataFrame
Y_features.head()



  3.2、 Standardization - 标准化


它将属性值更改为 均值为0,标准差为1 的 高斯分布. 当算法期望输入特征处于高斯分布时,它非常有用

from sklearn.preprocessing import StandardScaler

rescaledX = StandardScaler().fit_transform(X_features)
#通过sklearn的preprocessing数据预处理中StandardScaler特征缩放 标准化特征信息

X = pd.DataFrame(data = rescaledX, columns = X_features.columns)
 # 构建新特征DataFrame

X.head()

    3.3、将数据集切分——训练集和测试集

from sklearn.model_selection import train_test_split

seed = 7 #重现随机生成的训练
test_size = 0.33 #33%测试,67%训练
X_train, X_test, Y_train, Y_test = train_test_split(X, Y_features, test_size=test_size, random_state=seed)

4、 构建二分类算法模型

from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.naive_bayes import GaussianNB
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from xgboost import XGBClassifier
models = []
models.append(("LR", LogisticRegression())) #逻辑回归
models.append(("NB", GaussianNB())) # 高斯朴素贝叶斯
models.append(("KNN", KNeighborsClassifier())) #K近邻分类
models.append(("DT", DecisionTreeClassifier())) #决策树分类
models.append(("SVM", SVC())) # 支持向量机分类
models.append(("xgboost", XGBClassifier())) #支持向量机分类

cross_val_score()函数

sklearn.cross_validation.cross_val_score(estimator, X, y=None, scoring=None, cv=None, n_jobs=1, verbose=0, fit_params=None, pre_dispatch=‘2*n_jobs’)

参数

estimator:数据对象 
X:数据 
y:预测数据 
soring:调用的方法
cv:交叉验证生成器或可迭代的次数 
n_jobs:同时工作的cpu个数(-1代表全部)
verbose:详细程度
fit_params:传递给估计器的拟合方法的参数
pre_dispatch:控制并行执行期间调度的作业数量。

KFold——K折交叉验证:

这是将数据集分成K份的官方给定方案,所谓K折就是将数据集通过K次分割,使得所有数据既在训练集出现过,又在测试集出现过,当然,每次分割中不会有重叠。相当于无放回抽样。

StratifiedKFold用法类似Kfold,但是他是分层采样,确保训练集,测试集中各类别样本的比例与原始数据集中相同。

sklearn.model_selection.KFold(n_splits=3, shuffle=False, random_state=None)

思路:将训练/测试数据集划分n_splits个互斥子集,每次用其中一个子集当作验证集,剩下的n_splits-1个作为训练集,进行n_splits次训练和测试,得到n_splits个结果

注意点:对于不能均等份的数据集,其前n_samples % n_splits子集拥有n_samples // n_splits + 1个样本,其余子集都只有n_samples // n_splits样本

参数说明:

n_splits:表示划分几等份

shuffle:在每次划分时,是否进行洗牌

①若为Falses时,其效果等同于random_state等于整数,每次划分的结果相同

②若为True时,每次划分的结果都不一样,表示经过洗牌,随机取样的

random_state:随机种子数

属性:

①get_n_splits(X=None, y=None, groups=None):获取参数n_splits的值

②split(X, y=None, groups=None):将数据集划分成训练集和测试集,返回索引生成器

results = []
names = []
for name, model in models:
    kflod = KFold(n_splits=10, random_state=22)
    cv_result = cross_val_score(model, X_train,Y_train, cv = kflod,scoring="accuracy")
    names.append(name)
    results.append(cv_result)

for i in range(len(names)):
    print(names[i], results[i].mean)


结果:

 

5、模型评估(参数选择)

   1.SVM

from sklearn.svm import SVC
from sklearn.metrics import classification_report, confusion_matrix

classifier = SVC(kernel = 'rbf')
classifier.fit(X_train_pca, Y_train)

sklearn.svm.SVC(C=1.0, kernel='rbf', degree=3, gamma='auto', coef0=0.0, shrinking=True, probability=False,tol=0.001, cache_size=200, class_weight=None, verbose=False, max_iter=-1, decision_function_shape=None,random_state=None)

参数:

l  C:C-SVC的惩罚参数C?默认值是1.0

C越大,相当于惩罚松弛变量,希望松弛变量接近0,即对误分类的惩罚增大,趋向于对训练集全分对的情况,这样对训练集测试时准确率很高,但泛化能力弱。C值小,对误分类的惩罚减小,允许容错,将他们当成噪声点,泛化能力较强。

kernel :核函数,默认是rbf,可以是‘linear’, ‘poly’, ‘rbf’, ‘sigmoid’, ‘precomputed’ 

    0 – 线性:u'v

    1 – 多项式:(gamma*u'*v + coef0)^degree

    2 – RBF函数:exp(-gamma|u-v|^2)

    3 –sigmoid:tanh(gamma*u'*v + coef0)

degree :多项式poly函数的维度,默认是3,选择其他核函数时会被忽略。

gamma : ‘rbf’,‘poly’ 和‘sigmoid’的核函数参数。默认是’auto’,则会选择1/n_features

coef0 :核函数的常数项。对于‘poly’和 ‘sigmoid’有用。

probability :是否采用概率估计?.默认为False

shrinking :是否采用shrinking heuristic方法,默认为true

tol :停止训练的误差值大小,默认为1e-3

cache_size :核函数cache缓存大小,默认为200

class_weight :类别的权重,字典形式传递。设置第几类的参数C为weight*C(C-SVC中的C)

verbose :允许冗余输出?

max_iter :最大迭代次数。-1为无限制。

decision_function_shape :‘ovo’, ‘ovr’ or None, default=None3

random_state :数据洗牌时的种子值,int值

主要调节的参数有:C、kernel、degree、gamma、coef0。
 

    2.xgboost   

xgb1 = XGBClassifier(
    learning_rate = 0.1,
    n_estimators = 1000,
    max_depth = 5,
    min_child_weight = 1,
    gamma = 0,
    subsample = 0.8,
    colsample_bytree = 0.8,
    objective = 'binary:logistic',
    nthread = 4,
    scale_pos_weight = 1,
    seed = 27
    )
model = XGBClassifier()               
learning_rate = [0.0001,0.001,0.01,0.1,0.2,0.3] #学习率
gamma = [1, 0.1, 0.01, 0.001]

param_grid = dict(learning_rate = learning_rate,gamma = gamma)#转化为字典格式,网络搜索要求

kflod = StratifiedKFold(n_splits=10, shuffle = True,random_state=7)#将训练/测试数据集划分10个互斥子集,

grid_search = GridSearchCV(model,param_grid,scoring = 'neg_log_loss',n_jobs = -1,cv = kflod)
#scoring指定损失函数类型,n_jobs指定全部cpu跑,cv指定交叉验证
grid_result = grid_search.fit(X_train, Y_train) #运行网格搜索
print("Best: %f using %s" % (grid_result.best_score_,grid_search.best_params_))
#best_params_:描述了已取得最佳结果的参数的组合
#best_score_:成员提供优化过程期间观察到的最好的评分
#具有键作为列标题和值作为列的dict,可以导入到DataFrame中。
#注意,“params”键用于存储所有参数候选项的参数设置列表。
means = grid_result.cv_results_['mean_test_score']
params = grid_result.cv_results_['params']
for mean,param in zip(means,params):
    print("%f  with:   %r" % (mean,param))

参数选择结果

5.1.详细评估

       classification_report

y_pred = classifier.predict(X_test)
cm = confusion_matrix(Y_test, y_pred)#混淆矩阵

print(classification_report(Y_test, y_pred))#显示准确率

SVM结果:cm

结果说明:把0预测成0的有139个,把0预测成1的有23个,把1预测成0的有37个,把1预测成1的有55个。

confusion_matrix函数的使用

官方文档中给出的用法是 
sklearn.metrics.confusion_matrix(y_true, y_pred, labels=None, sample_weight=None)

y_true: 是样本真实分类结果,y_pred: 是样本预测分类结果 
labels:是所给出的类别,通过这个可对类别进行选择 
sample_weight : 样本权重

实现例子:

from sklearn.metrics import confusion_matrix

y_true=[2,1,0,1,2,0]
y_pred=[2,0,0,1,2,1]

C=confusion_matrix(y_true, y_pred)


运行结果:

这儿没有标注类别:下图是标注类别以后,更加好理解

sklearn.classification_report预测准确率

 

classification_report(Y_test, y_pred)结果如下:

       其中列表左边的一列为分类的标签名,右边support列为每个标签的出现次数.avg / total行为各列的均值(support列为总和)

下面将一一给出‘precision’,‘recall’,‘f1’的具体含义:

准确率

所有识别为”1”的数据中,正确的比率是多少。 

如识别出来100个结果是“1”, 而只有90个结果正确,有10个实现是非“1”的数据。 所以准确率就为90%

召回率

所有样本为1的数据中,最后真正识别出1的比率。 

如100个样本”1”, 只识别出了93个是“1”, 其它7个是识别成了其它数据。 所以召回率是93%

F1-score:

是准确率与召回率的综合。 可以认为是平均效果。

 F1值是精确度和召回率的调和平均值:2F1=1P+1R 2F1=1P+1R           F1=2P×RP+R F1=2P×RP+R
精确度和召回率都高时, F1 F1值也会高. F1 F1值在1时达到最佳值(完美的精确度和召回率),最差为0.在二元分类中, F1 F1值是测试准确度的量度。

例子:当一个搜索引擎返回30个页面时,只有20页是相关的,而没有返回40个额外的相关页面,其精度为20/30 = 2/3,而其召回率为20/60 = 1/3。在这种情况下,精确度是“搜索结果有多大用处”,而召回是“结果如何完整”。

详细定义如下:

对于数据测试结果有下面4种情况:

TP: 预测为正, 实现为正

FP: 预测为正, 实现为负

FN: 预测为负,实现为正

TN: 预测为负, 实现为负

准确率: TP/ (TP+FP) 

召回率: TP(TP + FN)

F1-score: 2*TP/(2*TP + FP + FN) 

  一般(粗)评估——accuracy_score

sklearn.metrics.accuracy_score(y_true, y_pred, normalize=True, sample_weight=None)

normalize:默认值为True,返回正确分类的比例;如果为False,返回正确分类的样本数

from sklearn.metrics import accuracy_score
accuracy = accuracy_score(Y_test, predictions)#显示准确率——分类0和1的total
print("Accuracy: %.2f%%" % (accuracy * 100.0))

结果:

from sklearn.metrics import accuracy_score
accuracy = accuracy_score(Y_test, y_pred,normalize = False)#正确分类的样本数——分类0和1的total

结果

判断比较不同特征的重要程度:

#判断特征的重要程度
from xgboost import plot_importance
from matplotlib import pyplot
plot_importance(model)
pyplot.show()

结果:

  

 5.2.使用 网格搜索 来提高模型——模型优化

from sklearn.model_selection import GridSearchCV

param_grid = {'C':[0.1, 1, 10, 100], 'gamma':[1, 0.1, 0.01, 0.001]}

grid = GridSearchCV(SVC(),param_grid,refit=True,verbose = 2)
grid.fit(X_train, Y_train)

# 预测
grid_predictions = grid.predict(X_test)

# 分类报告
print(classification_report(Y_test,grid_predictions))

优化结果:

 GridSearchCV   相关参数

初始化了一个GridSearchCV对象,用于对支持向量机流水线的训练与调优。将GridSearchCV的param_grid参数以字典的方式定义为待调优参数。

(1)estimator

选择使用的分类器,并且传入除需要确定最佳的参数之外的其他参数。每一个分类器都需要一个scoring参数,或者score方法:estimator=RandomForestClassifier(min_samples_split=100,min_samples_leaf=20,max_depth=8,max_features='sqrt',random_state=10),

(2 param_grid

需要最优化的参数的取值,值为字典或者列表,例如:param_grid =param_test1,param_test1 = {'n_estimators':range(10,71,10)}。

(3)scoring=None

模型评价标准,默认None,这时需要使用score函数;或者如scoring='roc_auc',根据所选模型不同,评价准则不同。字符串(函数名),或是可调用对象,需要其函数签名形如:scorer(estimator, X, y);如果是None,则使用estimator的误差估计函数。具体值的选取看本篇第三节内容

(4)fit_params=None

(5) n_jobs=1

n_jobs: 并行数,int:个数,-1:跟CPU核数一致, 1:默认值

进行预测的常用方法和属性

grid.fit():运行网格搜索

grid_scores_:给出不同参数情况下的评价结果

best_params_:描述了已取得最佳结果的参数的组合

best_score_:提供优化过程期间观察到的最好的评分

cv_results_ : dict of numpy (masked) ndarrays

具有键作为列标题和值作为列的dict,可以导入到DataFrame中。注意,“params”键用于存储所有参数候选项的参数设置列表。

   

不同模型下的可视化结果

      1.盒图:

ax = sns.boxplot(data = results)
ax.set_xticklabels(names)

 

图片解释:

    2.热力图

ax = sns.heatmap(data = results)
ax.set_xticklabels(names)

    3.散点图

ax = sns.stripplot(data = results)
ax.set_xticklabels(names)

   4.小提琴图:

   中间的白点是中位数,黑色粗线对应分位数

ax = sns.violinplot(data = results)
ax.set_xticklabels(names)

 

6、选择适宜的模型,使用测试数据预测

from sklearn.svm import SVC
from sklearn.metrics import classification_report, confusion_matrix

classifier = SVC(kernel = 'rbf') #kernel:核函数,默认是rbf,将低维映射成高维
model = classifier.fit(X_train, Y_train)
y_pred = model.predict(X_test)#预测的值

结果如下:

Accuracy: 74.80%


 

猜你喜欢

转载自blog.csdn.net/weixin_41988628/article/details/83051712