当前位置: 首页 > news >正文

【sklearn】模型融合_投票法

投票法

    • 投票法类别
    • 参数含义 sklearn.ensemble.VotingClassifier
    • 1. 所需库, 数据
    • 2. 定义交叉验证函数
      • 2.1 对单个评估器
      • 2.2 对融合模型
    • 3. 基于交叉验证的benchmark
    • 4. 融合多组分类器
    • 5. 构建多样性
      • 5.1 多种多样性混合
      • 5.2 剔除不良算法
      • 5.3 尝试精简多样性
    • 6. 分类器加权

投票法类别

'''
相对多数投票 少数服从多数
绝对多数投票 至少50%以上分类器输出相同,否则拒绝预测. 可衡量投票置信程度.

(分类模型输出结果为具体类别)
硬投票 预测类别出现次数最多作为结果 
(分类模型输出结果为概率,可用阈值、softmax转换为类别)
软投票 不同类别的预测概率加和,取高概率类别作为结果. 可衡量投票置信程度. 可能过拟合.

加权投票
    应用于硬投票 改变不同分类器拥有的票数
    应用于软投票 改变不同分类器所占的比重,概率加和->概率加权求和
    表现好的分类器若给过多的权重,易过拟合.
'''

参数含义 sklearn.ensemble.VotingClassifier

'''
class sklearn.ensemble.VotingClassifier(estimators, *, voting='hard', 
            weights=None, n_jobs=None, flatten_transform=True, verbose=False)

estimators 
    多个评估器及其名称,用列表打包
voting 投票方式
    默认 相对多数投票
    'hard'硬投票
    'soft'软投票,只接受可以输出概率值的算法
weights 权重
    默认 None
    用列表打包多个权重
flatten_transform 输出的概率结构
    软投票voting='soft'时使用
    True 输出结构为(n_samples, n_estimators*n_classes)
    False 输出结构为(n_samples, n_estimators, n_classes)
n_job 线程数
verbose 模型监控
'''

1. 所需库, 数据

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# 数据
from sklearn.model_selection import KFold, cross_validate
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_digits # 分类手写数字数据集
from sklearn.datasets import load_boston

# 单一学习器
from sklearn.neighbors import KNeighborsClassifier as KNNC
from sklearn.neighbors import KNeighborsRegressor as KNNR
from sklearn.tree import DecisionTreeClassifier as DTC
from sklearn.tree import DecisionTreeRegressor as DTR
from sklearn.linear_model import LinearRegression as LR
from sklearn.linear_model import LogisticRegression as LogiR
from sklearn.ensemble import RandomForestClassifier as RFC
from sklearn.ensemble import RandomForestRegressor as RFR
from sklearn.ensemble import GradientBoostingClassifier as GBC
from sklearn.ensemble import GradientBoostingRegressor as GBR
from sklearn.naive_bayes import GaussianNB
import xgboost as xb # 只能用xgboost自带的sklearn api

# 融合模型
from sklearn.ensemble import VotingClassifier
from sklearn.ensemble import VotingRegressor
data = load_digits()
X = data.data
y = data.target
print('X.shape', X.shape)
print('y.shape', y.shape)
print('十分类', np.unique(y))

'''
    X.shape (1797, 64)
    y.shape (1797,)
    十分类 [0 1 2 3 4 5 6 7 8 9]
'''
Xtrain, Xtest, ytrain, ytest = train_test_split(X, y, test_size=0.2, random_state=42)

2. 定义交叉验证函数

2.1 对单个评估器

def individual_estimators(estimators):
    '''
    对模型融合的每个评估器做交叉验证,对单一评估器的表现进行评估
    '''
    for estimator in estimators:
        cv = KFold(n_splits=5, shuffle=True, random_state=42)
        result = cross_validate(estimator=estimator[1]
                               ,X=Xtrain
                               ,y=ytrain
                               ,scoring='accuracy'
                               ,n_jobs=-1
                               ,return_train_score=True
                               ,verbose=False
                               )
        test = estimator[1].fit(Xtrain, ytrain).score(Xtest, ytest)
        print(estimator[0]
             ,'\n train_score:{}'.format(result['train_score'].mean())
             ,'\n cv_mean:{}'.format(result['test_score'].mean())
             ,'\n test_score:{}'.format(test)
             ,'\n'
             )

2.2 对融合模型

def fusion_estimator(clf):
    '''
    对融合模型做交叉验证,对融合模型的表现进行评估
    '''
    cv = KFold(n_splits=5, shuffle=True, random_state=42)
    result = cross_validate(clf
                           ,X=Xtrain,y=ytrain
                           ,cv=cv
                           ,scoring='accuracy'
                           ,n_jobs=-1
                           ,return_train_score=True
                           ,verbose=False
                           )
    test = clf.fit(Xtrain, ytrain).score(Xtest, ytest)
    print(' train_score:{}'.format(result['train_score'].mean())
          ,'\n cv_mean:{}'.format(result['test_score'].mean())
          ,'\n test_score:{}'.format(test)
          )

3. 基于交叉验证的benchmark

'''
分数最高的单一算法, 进一步精调,作为benchmark
'''
logi = LogiR(max_iter=3000, n_jobs=-1) # 初始较大max_iter, 方便迭代到收敛
fusion_estimator(logi) # 过拟合,需要调整
'''
     train_score:1.0  cv_mean:0.9603343979868371 
     test_score:0.9722222222222222
'''

4. 融合多组分类器

  • 第一组分类器: 放任自由,收敛为主,有过拟合风险
clf1 = LogiR(max_iter=3000, random_state=42, n_jobs=-1)
clf2 = RFC(n_estimators=100, random_state=42, n_jobs=-1)
# boosting 算法无法并行建树,无n_jobs
clf3 = GBC(n_estimators=100, random_state=42)

estimators = [('Logistic Regression', clf1)
             ,('RandomForest', clf2)
             ,('GBDT', clf3)
             ]
clf = VotingClassifier(estimators=estimators
                      ,voting='soft'
                      )
# 观察是否过拟合
individual_estimators(estimators)

'''
    Logistic Regression 
     train_score:1.0 
     cv_mean:0.956145954316686 
     test_score:0.9722222222222222 
    
    RandomForest 
     train_score:1.0 
     cv_mean:0.9735554587688734 
     test_score:0.9722222222222222 
    
    GBDT 
     train_score:1.0 
     cv_mean:0.951969608981804 
     test_score:0.9694444444444444
'''
# 融合后与benchmark效果对比
fusion_estimator(clf)
'''

     train_score:1.0 
     cv_mean:0.9784262485481998 
     test_score:0.9833333333333333
'''
  • 第二组分类器: 轻微调参(非精细化调参), 限制过拟合
clf2.fit(Xtrain, ytrain)
for i in clf2.estimators_[: 10]:
    print(i.tree_.max_depth)
'''
    12
    14
    14
    14
    14
    15
    16
    13
    15
    13
'''
'''
限制过拟合参数
clf1逻辑回归 调小C
clf2随机森林 调小max_depth
clf3GBDT 特征抽样max_features='sqrt',每次建树只使用根号下特征数目的特征
         (max_depth对boosting算法没用)
'''
clf1 = LogiR(max_iter=3000, C=0.1, random_state=42, n_jobs=-1)
clf2 = RFC(n_estimators=100, max_depth=12, random_state=42, n_jobs=-1)
clf3 = GBC(n_estimators=100, max_features='sqrt', random_state=42)

estimators = [('Logistic Regression', clf1)
             ,('RandomForest', clf2)
             ,('GBDT', clf3)
             ]
clf = VotingClassifier(estimators=estimators
                      ,voting='soft'
                      )
'''
判断各参数是否适合
'''
individual_estimators(estimators)
'''
    Logistic Regression 
     train_score:0.9998259355961705 
     cv_mean:0.9596205962059621 
     test_score:0.9722222222222222 
    
    RandomForest 
     train_score:1.0 
     cv_mean:0.9728585946573751 
     test_score:0.9722222222222222 
    
    GBDT 
     train_score:1.0 
     cv_mean:0.9686749903213319 
     test_score:0.9777777777777777
''' 
# 基本不过拟合了
fusion_estimator(clf)
'''
     train_score:1.0 
     cv_mean:0.9770325203252032 
     test_score:0.9777777777777777
'''

5. 构建多样性

'''
评估器之间差别越大,彼此间越独立
1. 训练数据多样性
    多组特征工程,不同特征矩阵训练不同模型.效果好.
2. 样本多样性
    相同特征矩阵,不同样本子集进行训练.数据量不宜过小,模型效果易下降.
3. 特征多样性
    相同特征矩阵,不同特征子集进行训练.特征量不宜过小,模型效果易下降.
    clf3GBDT 特征抽样max_features='sqrt'
4. 随机多样性/训练多样性
    相同算法,不同随机种子(不同特征、样本、起点)、不同损失函数、不同纯度下降量
    相当于bagging集成
5. 算法多样性
    增加模型类型, 集成、树、概率、线性混合,模型效果不能太差.
'''

5.1 多种多样性混合

# 逻辑回归没有增加多样性的选项,只能随机多样性
clf1 = LogiR(max_iter=3000, C=0.1, random_state=1412, n_jobs=-1)
# 随机森林增加特征多样性和样本多样性
# max_features特征抽样, max_samples样本抽样
clf2 = RFC(n_estimators=100, max_features='sqrt', max_samples=0.9, random_state=1412, n_jobs=-1)
# 梯度提升树增加特征多样性,微调特征数量
#  max_features特征抽样, subsample样本抽样
clf3 = GBC(n_estimators=100, max_features=16, random_state=1412)

# 增加算法多样性, 增加决策树、knn、贝叶斯. 拖后腿的不能用
clf4 = DTC(max_depth=8, random_state=1412)
clf5 = KNNC(n_neighbors=10, n_jobs=8)
clf6 = GaussianNB()

# 增加随即多样性, 相同算法更换随机数种子
clf7 = RFC(n_estimators=100, max_features='sqrt', max_samples=0.9, random_state=1234, n_jobs=-1)
clf8 = GBC(n_estimators=100, max_features=16, random_state=1234)

estimators = [('Logistic Regression', clf1)
             ,('RandomForest', clf2)
             ,('GBDT', clf3)
             ,('Decision Tree', clf4)
             ,('KNN', clf5)
             ,('Bayes', clf6)
             ,('RandomForest2', clf7)
             ,('GBDT2', clf8)
             ]
clf = VotingClassifier(estimators=estimators
                      ,voting='soft'
                      )
individual_estimators(estimators)
'''
决策树过拟合, max_depth再小影响交叉验证分数, 无法提升效果
KNN效果很好
Bayes过拟合不严重, 但效果很差, 在训练集上显示学习能力不强
'''
'''
    Logistic Regression 
     train_score:0.9998259355961705 
     cv_mean:0.9596205962059621 
     test_score:0.9722222222222222 
    
    RandomForest 
     train_score:1.0 
     cv_mean:0.9763332365466513 
     test_score:0.9777777777777777 
    
    GBDT 
     train_score:1.0 
     cv_mean:0.968672570654278 
     test_score:0.975 
    
    Decision Tree 
     train_score:0.9363260301963902 
     cv_mean:0.8301901858304298 
     test_score:0.85 
    
    KNN 
     train_score:0.9824278200325425 
     cv_mean:0.9742523228803716 
     test_score:0.9833333333333333 
    
    Bayes 
     train_score:0.8590824535512922 
     cv_mean:0.8295489740611692 
     test_score:0.8472222222222222 
    
    RandomForest2 
     train_score:1.0 
     cv_mean:0.9700783972125435 
     test_score:0.9694444444444444 
    
    GBDT2 
     train_score:1.0 
     cv_mean:0.9672812620983352 
     test_score:0.9722222222222222 
'''
fusion_estimator(clf)
'''
和第一组分类器效果相似,需要删掉不好的模型
'''
'''
     train_score:1.0 
     cv_mean:0.974934668989547 
     test_score:0.9805555555555555
'''

5.2 剔除不良算法

estimators = [('Logistic Regression', clf1)
             ,('RandomForest', clf2)
             ,('GBDT', clf3)
             ,('Decision Tree', clf4)
             ,('KNN', clf5)
             #,('Bayes', clf6)
             ,('RandomForest2', clf7)
             ,('GBDT2', clf8)
             ]
clf = VotingClassifier(estimators=estimators
                      ,voting='soft'
                      )
fusion_estimator(clf)
'''
效果提升
'''
'''
     train_score:1.0 
     cv_mean:0.9812040263259775 
     test_score:0.9833333333333333
'''

5.3 尝试精简多样性

# 随机森林和梯度提升树耗时长
estimators = [('Logistic Regression', clf1)
             ,('RandomForest', clf2)
             ,('GBDT', clf3)
             ,('Decision Tree', clf4)
             ,('KNN', clf5)
             #,('Bayes', clf6)
             #,('RandomForest2', clf7)
             #,('GBDT2', clf8)
             ]
clf = VotingClassifier(estimators=estimators
                      ,voting='soft'
                      )
fusion_estimator(clf)
'''
效果差不多
希望在测试集上效果更好则用test_score值高的融合模型
'''
'''

     train_score:1.0 
     cv_mean:0.9819008904374759 
     test_score:0.9805555555555555
'''

6. 分类器加权

'''
依赖余=于多次尝试
'''
  • 第一种选项: 使用各模型交叉验证结果作为权重, 有过拟合风险
estimators = [('Logistic Regression', clf1)
             ,('RandomForest', clf2)
             ,('GBDT', clf3)
             ,('Decision Tree', clf4)
             ,('KNN', clf5)]
# 精准权重
clf_weighted = VotingClassifier(estimators=estimators
                               ,voting='soft'
                               ,weights=[0.9722, 0.9777, 0.9750, 0.85, 0.9833]
                               )
fusion_estimator(clf_weighted)
'''
没有出现严重过拟合
'''
'''
     train_score:1.0 
     cv_mean:0.9825953348819201 
     test_score:0.9805555555555555
'''
  • 第二种选项: 稍微降低权重精度,或许一定程度上抵消过拟合
# 模糊权重
# 多给效果好的KNN权重
clf_weighted = VotingClassifier(estimators=estimators
                               ,voting='soft'
                               ,weights=[0.96, 0.96, 0.96, 0.85, 0.99]
                               )
fusion_estimator(clf_weighted)
'''
权重精确和粗略对效果影响不大
'''
'''
     train_score:1.0 
     cv_mean:0.9825953348819201 
     test_score:0.9805555555555555
'''
  • 第三种选项: 加大效果好的算法的权重,减小效果差的算法的权重
clf_weighted = VotingClassifier(estimators=estimators
                               ,voting='soft'
                               ,weights=[0.96, 0.96, 0.96, 0.85, 1.3]
                               )
fusion_estimator(clf_weighted)
'''
若过拟合,不能加大效果好的算法的权重,可降低效果差的算法的权重
降低0.85
'''
'''
     train_score:0.9998259355961705 
     cv_mean:0.9825929152148664 
     test_score:0.9805555555555555
'''
clf_weighted = VotingClassifier(estimators=estimators
                               ,voting='soft'
                               ,weights=[0.96, 0.96, 0.96, 0.3, 1.3]
                               )
fusion_estimator(clf_weighted)
'''
这个情况看来努力降低不好的提升好的效果更好
'''
'''
     train_score:1.0 
     cv_mean:0.9832897793263647 
     test_score:0.9833333333333333
'''

相关文章:

  • 回归预测 | MATLAB实现BO-BP贝叶斯优化BP神经网络多输入单输出回归预测
  • 【RAG 论文】Adaptive-RAG:自适应地根据 query 难度来选择合适的 RAG 模型
  • C# GetField 方法应用实例
  • CUDA的应用场景
  • 深度优先搜索与广度优先搜索,你知道它们的区别吗?
  • python学习笔记(集合)
  • InnoDB高级特性篇(5)-使用InnoDB的全文索引
  • Android Kotlin协程实战
  • C语言printf()大全
  • kafka学习问题
  • WSL里的Ubuntu 登录密码忘了怎么更改
  • LVS-DR实验.
  • ASP.NET MVC会计教学管理端项目系列--Log4Net日志组件
  • AD域帐户密码过期,终端802.1x认证自动重连导致AD账号被锁,员工无法上网、办公怎么办?
  • iOS小技能:跳转到地图APP(navForIOSMap)
  • Unreal Engine源代码下载方法
  • JavaScript简识
  • 【正点原子STM32连载】第五十一章 视频播放器实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1
  • 下一个(全)排列
  • 读懂MEV链上套利操作
  • Mac 电脑下载 AppStore 中的 ipa 软件包详细流程
  • Pycharm Runtime Error R6034解决方法
  • LQ0100 人物相关性分析【文本处理】
  • 虚拟形象制作该如何进行?带你深入了解虚拟形象制作
  • 一文读懂TDengine3.0中的事务机制
  • Java入门刷题篇 基础语法->>基本数据类型->>Java1类型转换
  • 入门学python(三)
  • 湖北住建厅七大员报考条件和取证流程
  • 字节码指令 || JVM类加载与字节码技术
  • 哪个开源工作流引擎更好?Flowable or Camunda ?
  • 牛客网专项练习30天Pytnon篇第17天
  • 【Vue】Vue全家桶(九)Vue3