传统算法(四)
集成算法
一、什么是集成算法?
集成学习(ensemble learning)是大概17年非常火的机器学习方法。因为它本身不是一个单独的机器学习算法,而是通过构建并结合多个机器学习器来完成学习任务。也就是我们常说的“博采众长”。
集成学习可以用于分类问题集成,回归问题集成,特征选取集成,异常点检测集成等等,可以说所有的机器学习领域都可以看到集成学习的身影。
- 集成算法目的:让机器学习效果更好
- 集成算特点:
(1)将多个分类方法聚集在一起,以提高分类的准确率(这些算法可以是不同的算法,也可以是相同的算法);
(2)集成学习法由训练数据构建一组基分类器,然后通过对每个基分类器的预测进行投票来进行分类;
(3)严格来说,集成学习并不算是一种分类器,而是一种分类器结合的方法;
(4)通常一个集成分类器的分类性能会好于单个分类器;
(5)如果把单个分类器比作一个决策者的话,集成学习的方法就相当于多个决策者共同进行一项决策。
本文会对集成算法中的三种算法:bagging、boosting和stacking来做一个简单的介绍。
二、bagging算法
bagging算法的全称是:bootstrap aggregation
特点是各个弱学习器之间没有依赖关系,训练多个分类器取平均,公式表达如下:
f(x)=1M∑i=1mfm(x)f(x) = \dfrac{1}{M}\sum^m_{i=1}f_m(x)f(x)=M1i=1∑mfm(x)
bagging算法中最典型的就是:随机森林(Random Forest Simplified)
随机:每次抽样的数据均采样随机,特征选择随机
总结来说:
(1)Bagging通过降低基分类器的方差,改善了泛化误差;
(2)其性能依赖于基分类器的稳定性;如果基分类器不稳定,bagging有助于降低训练数据的随机波动导致的误差;如果稳定,则集成分类器的误差主要由基分类器的偏倚引起;
(3)由于每个样本被选中的概率相同,因此bagging并不侧重于训练数据集中的任何特定实例。
三、boosting算法
从弱学习器开始加强,通过加权来进行训练,权值越高的样本在下一次训练中所占的比重越大,也就是说越难区分的样本在训练过程中会变得越来越重要。公式表达为:
fm(x)=fm−1(x)+argmin∑i=1mL(yi,fm−1(x)+h(xi))f_m(x)=f_{m-1}(x)+argmin\sum^m_{i=1}L(y_i,f_{m-1}(x)+h(x_i))fm(x)=fm−1(x)+argmini=1∑mL(yi,fm−1(x)+h(xi))
根据前一次的分类效果调整权重,如果某一个数据在这次分错了,那么在下一次我就会给它更大的权重,每个分类器根据自身的准确性来确定各自的权重,再合体。
典型的算法有:Adaboost、Xgboost
总结来说:
(1)AdaBoost分类算法是一种自适应提升的方法,由于训练的过程是重复使用相同的训练集,因而不要求数据集很大,其自身就可以组合任意数量的基分类器。
(2)在AdaBoost算法中,基分类器使用的训练集稍有差异,是前一个基分类器的误差函数。
(3)基分类器应当是弱的但又不至于太弱(即分类准确率略大于50%),而提升的过程对噪声和离群点的干扰尤为明显。
四、stacking算法
聚合多个分类器或回归模型(可以分阶段来做);直接将各种分类器堆在一起;使用的相对于bagging和boosting较少,它不像bagging和boosting,而是组合不同的模型;
分阶段执行:第一阶段得出各自结果,第二阶段再用前一阶段结果训练;
如下图,对比各种算法(KNN\RF\Naive Bayes),以及stacking算法的结果,可以发现stacking堆叠在一起确实能使得准确率提升,但是因为要分阶段直接,在训练的时间速度上,是个明显短板;
五、python实例代码
以下实例为预测泰坦尼克号获救的概率
使用sklearn
模块中的随机森林以及集成算法的代码:
#coding=utf-8
# write by sz
'''导入库'''
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression,LogisticRegression
from sklearn.model_selection import KFold,cross_val_score,GridSearchCV
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestClassifier,GradientBoostingClassifier
from sklearn.feature_selection import SelectKBest,f_classif
'''读取数据'''
titanic = pd.read_csv('titanic_train.csv')
'''清洗数据'''
titanic = titanic.drop(columns =['Name','Ticket','Cabin'])
titanic['Age'] = titanic['Age'].fillna(titanic['Age'].median())
titanic.loc[titanic['Sex'] == 'female','Sex'] = 1
titanic.loc[titanic['Sex'] == 'male','Sex'] = 0
titanic['Embarked'] = titanic['Embarked'].fillna('S')
titanic.loc[titanic['Embarked'] == 'S','Embarked'] =1
titanic.loc[titanic['Embarked'] == 'C','Embarked'] =2
titanic.loc[titanic['Embarked'] == 'Q','Embarked'] =3
x = titanic.loc[:,titanic.columns != 'Survived']
y = titanic['Survived']
'''线性回归'''
line = LinearRegression()
kf = KFold(n_splits=3,random_state=1)
x_split = kf.split(titanic['Survived'])
predicts = []
for x_train,x_test in x_split:
# print(x_train)
line.fit(titanic.iloc[x_train,titanic.columns != 'Survived'],
titanic.iloc[x_train,titanic.columns == 'Survived'])
y_predict =line.predict(titanic.loc[x_test,titanic.columns != 'Survived'])
predicts.append(y_predict)
# print(predicts)
predicts = np.concatenate(predicts,axis=0)
predicts[ predicts >0.5] = 1
predicts[ predicts <= 0.5] =0
Prd_lin = sum( predicts.ravel() == titanic['Survived'])/len(titanic)
print('LinearRegression: %f%%' %(Prd_lin*100))
'''逻辑回归'''
GR = GridSearchCV(LogisticRegression(),{'C':[0.01,0.1,1,10,100]},scoring='precision',cv=4)
GR.fit(x,y)
# print(GR.best_score_)
lr = LogisticRegression(C=GR.best_params_['C'],penalty='l2')
kf = KFold(n_splits=3,random_state=1)
x_split = kf.split(x)
predicts_lr = []
for x_train,x_test in x_split:
lr.fit(x.loc[x_train,:],y.loc[x_train])
# y_predict = lr.predict(x.loc[x_test,:])
y_predict = lr.predict_proba(x.loc[x_test,:])
predicts_lr.append(y_predict[:,1])
predicts_lr = np.concatenate(predicts_lr,axis=0)
predicts_lr[predicts_lr > 0.5 ] = 1
predicts_lr[predicts_lr <= 0.5 ] = 0
Prd_lr = sum(predicts_lr.ravel() == y)/len(predicts_lr)
print('LogisticRegression: %f%%' %(Prd_lr*100))
titanic_test = pd.read_csv('test.csv')
titanic_test = titanic_test.drop(columns=['Name','Cabin','Ticket'])
titanic_test['Age'] = titanic_test['Age'].fillna(titanic_test['Age'].median())
titanic_test['Fare'] = titanic_test['Fare'].fillna(titanic_test['Fare'].median())
titanic_test.loc[titanic_test['Sex'] == 'female','Sex'] = 1
titanic_test.loc[titanic_test['Sex'] == 'male','Sex'] = 0
titanic_test['Embarked'] = titanic_test['Embarked'].fillna('S')
titanic_test.loc[titanic_test['Embarked'] == 'S','Embarked'] =1
titanic_test.loc[titanic_test['Embarked'] == 'C','Embarked'] =2
titanic_test.loc[titanic_test['Embarked'] == 'Q','Embarked'] =3
Y_predict = lr.predict(titanic_test)
titanic_test['Survived_test']=Y_predict
# print(Y_predict)
'''随机森林'''
rf = RandomForestClassifier(n_estimators=100,min_samples_split=3)
kf = KFold(n_splits=6)
x_split = kf.split(x)
score = cross_val_score(rf,x,y,cv= 6)
print('RandomForestClassifier_O: %f%%' %(score.mean()*100))
'''选择三个最重要的特征值,并可视化'''
best_f = SelectKBest(k=3)
best_f.fit(x,y)
ff = -np.log10(best_f.pvalues_)
plt.bar(np.arange(x.shape[1]),ff)
plt.xticks(np.arange(x.shape[1]),x.columns,rotation=90)
plt.xlabel('feature')
plt.ylabel('f_scores')
plt.show()
best_fe = x.columns[best_f.get_support()]
score = cross_val_score(rf,x[best_fe],y,cv= 6)
print('RandomForestClassifier_F: %f%%' %(score.mean()*100))
'''集成模型'''
algs = [[GradientBoostingClassifier(learning_rate=0.01,random_state=1),best_fe],
[RandomForestClassifier(n_estimators=100, random_state=1),best_fe]]
pr = []
for x_train,x_test in x_split :
predicts_al = []
for alg, columns in algs:
alg.fit(x.loc[x_train,columns],y.loc[x_train])
predicts = alg.predict(x.loc[x_test,columns])
PRD_T = sum(predicts == y.loc[x_test]) / len(predicts)
predicts_al.append(PRD_T)
prd = np.mean(predicts_al)
pr.append(prd)
Prd_mo = np.mean(pr)
print('alg(GBooting,RF): %f%%' %(Prd_mo*100))
以上,就是本次学习的集成模型及算法的思想,以及python代码实现的案例,对Adaboost以及Xgboost目前使用的比较广泛的算法,后续会单独详细说明;