初学者的回归分析 - 第二部分_seaborn r2_score round(2)-程序员宅基地

技术标签: 后端  

初学者的回归分析 - 第二部分

使用基于树的算法(决策树、随机森林、XGboost)建立一个ML回归模型

alt
  • 简介
  • 第2.1部分 建立机器学习管道

∘ 第1步:收集数据

∘ 第二步:将数据可视化(问自己这些问题并回答)

∘ 第三步:清理数据

∘ 第四步:訓練模型

∘ 第五步:評估

∘ 第六步:使用hyperopt进行超参数调整

∘ 第七步:选择最佳模型和预测结果

  • 第2.2部分:分析ML算法

∘ 什么是决策树?

∘ 什么是随机森林?

∘ 什么是极限梯度提升法?(XGBoost)

∘ 决策树 vs 随机森林 vs XGBoost

∘ 线性模型与树状模型的对比。

  • 总结

引言

正如我在上一篇文章中所解释的,真正的数据科学家是从问题/应用的角度来思考的,并在编程语言或框架的帮助下找到解决问题的方法。在第一部分中,鱼的重量估计问题是用线性ML模型解决的,然而,今天我将介绍基于树的算法,如决策树,随机森林,XGBoost来解决同样的问题。在文章的前半部分2.1部分,我将建立一个模型,在后半部分2.2部分,我将从理论上解释每一种算法,将它们相互比较并找出其优点和缺点。

第2.1部分 构建机器学习管道

为了建立一个ML模型,我们需要遵循下面的管道步骤,几乎所有种类的模型都是如此。

alt

图片由作者提供 由于我们要解决的问题和以前一样,一些管道步骤也是一样的,比如1.收集数据,2.可视化数据。然而,其他步骤会有一些修改。

步骤1:收集数据 数据是可以从Kaggle上下载的公共数据集。


import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from itertools import combinations
import numpy as np
data = pd.read_csv("Fish.csv")

第2步:可视化数据(问自己这些问题并回答)

数据看起来是什么样子的?

data.head()
alt

数据是否有缺失值?

data.isna().sum()
alt

数字特征的分布是怎样的?

data_num = data.drop(columns=["Species"])

fig, axes = plt.subplots(len(data_num.columns)/3, 3, figsize=(15, 6))
i = 0
for triaxis in axes:
    for axis in triaxis:
        data_num.hist( column = data_num.columns[i], ax=axis)
        i = i+1
alt

目标变量(重量)相对于鱼种的分布是什么?

sns.deposot(
  data=data,
  x="重量"
  hue="Species",
  kind="hist",
  height=6,
  aspect=1.4,
  bins=15
)
plt.show()
alt

目标变量在物种方面的分布表明,有一些物种,如梭鱼,与其他物种相比具有巨大的权重。这种可视化给我们提供了更多关于 "物种 "特征如何被用于预测的信息。

sns.pairplot(data, kind='scatter', hue='Species')
alt
plt.figure(figsize=(7,6))
corr = data_num.corr()
sns.heatmap(corr, 
            xticklabels=corr.columns.values,
            yticklabels=corr.columns.values, annot=True)
plt.show()
alt

第3步:清理数据


from sklearn.model_selection import train_test_split
from sklearn.preprocessing import  LabelEncoder
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor
import xgboost as xgb
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
data_cleaned =   data.drop("Weight", axis=1)
y = data['Weight']
x_train, x_test, y_train, y_test = train_test_split(data_cleaned,y, test_size=0.2, random_state=42)
print(x_train.shape, x_test.shape, y_train.shape, y_test.shape)
# label encoder
label_encoder = LabelEncoder()
x_train['Species'] = label_encoder.fit_transform(x_train['Species'].values)
x_test['Species'] = label_encoder.transform(x_test['Species'].values)

标签编码器

label_encoder = LabelEncoder()
x_train['Species'] = label_encoder.fit_transform(x_train['Species'].value)
x_test['Species'] = label_encoder.transform(x_test['Species'].values)
alt

我们使用的是基于树的模型,因此我们不需要特征缩放。此外,为了将文本转换成数字,我只是用LabelEncoder给每个鱼种分配了唯一的数值。

第四步:训练模型


def evauation_model(pred, y_val):
  score_MSE = round(mean_squared_error(pred, y_val),2)
  score_MAE = round(mean_absolute_error(pred, y_val),2)
  score_r2score = round(r2_score(pred, y_val),2)
  return score_MSE, score_MAE, score_r2score


def models_score(model_name, train_data, y_train, val_data,y_val):
    model_list = ["Decision_Tree","Random_Forest","XGboost_Regressor"]
    #model_1
    if model_name=="Decision_Tree":
        reg = DecisionTreeRegressor(random_state=42)
    #model_2
    elif model_name=="Random_Forest":
      reg = RandomForestRegressor(random_state=42)
        
    #model_3
    elif model_name=="XGboost_Regressor":
        reg = xgb.XGBRegressor(objective="reg:squarederror",random_state=42,)
    else:
        print("please enter correct regressor name")
        
    if model_name in model_list:
        reg.fit(train_data,y_train)
        pred = reg.predict(val_data)
     
        score_MSE, score_MAE, score_r2score = evauation_model(pred,y_val)
        return round(score_MSE,2), round(score_MAE,2), round(score_r2score,2)
model_list = ["Decision_Tree","Random_Forest","XGboost_Regressor"]
result_scores = []
for model in model_list:
    score = models_score(model, x_train, y_train, x_test, y_test)
    result_scores.append((model, score[0], score[1],score[2]))
    print(model,score)

我训练了决策树、随机森林XGboost并存储了所有的评估分数。

第5步:评估

df_result_scores = pd.DataFrame(result_scores,columns ["model""mse""mae""r2score"])
df_result_scores
alt

基于树的算法的评估结果 基于树的模型 这个结果真的很吸引人,你记得线性模型取得的结果要低得多(也如下图所示)。因此,在我们做任何类型的超参数调整之前,我们可以说所有基于树的模型在这种数据集中的表现都超过了线性模型。

alt

线性模型的评估结果

线性模型

第6步:使用hyperopt进行超参数调整 今天我们使用hyperopt来调整使用TPE算法的超参数。TPE算法不是从搜索空间中随机取值,而是考虑到一些超参数的分配(x)是已知的,在其他元素的特定值下是不相关的。在这种情况下,搜索比随机搜索有效,比贪婪搜索快。


from hyperopt import hp
from hyperopt import fmin, tpe, STATUS_OK, STATUS_FAIL, Trials
from sklearn.model_selection import cross_val_score
num_estimator = [100,150,200,250] 。

space= { 'max_depth': hp.quniform("max_depth", 3, 18, 1),
        'gamma': hp.uniform ('gamma', 1,9),
        'reg_alpha' : hp.quniform('reg_alpha', 30,180,1),
        'reg_lambda' : hp.uniform('reg_lambda', 0,1),
        'colsample_bytree' : hp.uniform('colsample_bytree', 0.5,1),
        'min_child_weight' : hp.quniform('min_child_weight', 0, 10, 1),
        'n_estimators' : hp.choice("n_estimators", num_estimator),
    }

def hyperparameter_tuning(space):
    model=xgb.XGBRegressor(n_estimators = space['n_estimators'], max_depth = int(space['max_depth']), gamma = space['gamma'],
                         reg_alpha = int(space['reg_alpha']) , min_child_weight=space['min_child_weight']。
                         colsample_bytree=space['colsample_bytree'], objective="reg:squarederror")
    
    score_cv = cross_val_score(model, x_train, y_train, cv=5, scoring="neg_mean_absolute_error") 。
    返回 { '损失':-score_cv, '状态': STATUS_OK, 'model': model}

alt

trials = Trials()
best = fmin(fn=hyperparameter_tuning,
            space=空间。
            algo=tpe.commend,
            max_evals=200。
            trials=trials)

print(best)

找到的超参数 hyperopt 最佳超参数的结果 这里是算法在200次试验后发现的最佳超参数的结果。但是,如果数据集太大,可以相应减少试验次数。

best['max_depth'] = int(best['max_depth']) 
# 转换为int

best["n_estimators"] = num_estimator[best["n_estimators"]]
#

根据索引计算出的数值

reg = xgb.XGBRegressor(**best)
reg.fit(x_train,y_train)
pred = reg.predict(x_test)
score_MSE, score_MAE, score_r2score = evauation_model(pred,y_test) 
to_append = ["XGboost_hyper_tuned",score_MSE, score_MAE, score_r2score]
df_result_scores.loc[len(df_result_scores)] = to_append
df_result_scores

结果非常好! 与其他算法相比,这个超调模型真的很好。例如,XGboost将MAE的结果从41.65提高到36.33。

这是一个很好的例子,说明了超参数调整是多么强大。

第7步:选择最佳模型和预测

赢家

reg = xgb.XGBRegressor(**best)
reg.fit(x_train,y_train)
pred = reg.predict(x_test)
plt.figure(figsize=(18,7))
plt.subplot(1, 2, 1) # 第1行,第2列索引1
plt.scatter(range(0,len(x_test)), pred,color="green", label="predicted")
plt.scatter(range(0,len(x_test)), y_test,color="red",label="True value")
plt.legend()
plt.subplot(1, 2, 2) # 索引2
plt.plot(range(0,len(x_test)), pred,color="green",label=" predicted")
plt.plot(range(0,len(x_test)), y_test,color="red",label="true value")
plt.legend()
plt.show()
alt

预测与真实 这个可视化图清楚地说明了预测值和真值有多接近,以及调整后的XGBoost的表现有多好。

第2.2部分 分析ML算法 什么是决策树? 决策树是一种有监督的ML算法,善于捕捉特征和目标变量之间的非线性关系。算法背后的直觉类似于人类的逻辑。在每个节点中,该算法找到特征和阈值,在此基础上将数据分成两部分。下面是决策树的图示。

alt

鱼类重量预测决策树

首先,让我们看看图中每个变量代表什么。让我们以第一个节点为例。


width≤5.154:
特征和数值的阈值,算法根据这个阈值决定分割数据样本。

samples = 127: 
分割前有127个数据点。

value = 386.794
#预测特征(鱼的重量)的平均值。

Squared_error = 122928.22: 与MSE(true, pred)相同 - 其中pred与value(样本的平均鱼重)相同。

因此,基于宽度≤5.154的阈值的算法将数据分成两部分。但问题是该算法是如何找到这个阈值的?有几种分割标准,对于回归任务来说,CART算法试图通过贪婪的搜索方式找到一个阈值,使两个子组的加权平均MSE最小。

alt

例如,在我们的案例中,在第一次拆分后,与其他拆分相比,两个子组的加权平均MSE是最小的。


J(k,t_k) = 88/127 *20583.394 + 39/127 *75630.727 = 37487.69

决策树的问题。

树对训练数据的微小变化非常敏感。数据的微小变化会导致决策树的结构发生重大变化。解决这一限制的方法是随机森林。

什么是随机森林?

随机森林是一个决策树的集合体。随机森林背后的直觉是建立多个决策树,在每个决策树中,它不是寻找分割数据的最佳特征,而是在一个特征子集中寻找最佳特征,因此这提高了树的多样性。然而,它的可解释性比简单的决策树要差。另外,它需要大量的树来构建,这使得该算法对于实时应用来说很慢。一般来说,算法的训练速度快,但创建预测的速度慢。决策树的一个改进版本也是XGBoost。

什么是极限梯度提升法?(XGBoost)

XGBoost也是一种基于树的集合监督学习算法,它使用梯度提升框架。这种算法背后的直觉是,它试图将新的预测器与前一个预测器的残余误差相适应。它的速度极快,可扩展,可移植。

决策树 vs 随机森林 vs XGBoost

因此,在我们的实验中,XGboost在性能上优于其他。从理论上讲,我们可以得出结论,决策树是最简单的基于树的算法,它有不稳定的局限性--数据的变化会导致树结构的巨大变化,然而,它有完美的可解释性。随机森林和XGboost则更为复杂。其中一个区别是,随机森林在过程结束时结合了结果(多数规则),而XGboost则在过程中结合了结果。一般来说,XGboost比随机森林有更好的性能,然而,当我们的数据中有大量的噪音时,XGBoost不能成为一个好的选择,它会导致过拟合,而且比随机森林更难调整。

线性模型与基于树的模型。

线性模型捕捉自变量和因变量之间的线性关系,这在现实世界场景的大多数情况下并不是这样的。然而,基于树的模型捕获了更复杂的关系。

线性模型大多数时候都需要进行特征缩放,但是基于树的模型不需要。 基于树的模型的性能多数时候比线性模型好。我们的实验很好地说明了这一点,最好的超调线性模型取得了66.20的MAE,而最好的树状模型取得了36.33,这是一个很大的进步。

基于树的算法比线性模型更容易解释。

结论 如前所述,对于哪种类型的算法效果最好,没有现成的收据,一切都取决于数据和任务。这就是为什么应该对几种算法进行测试和评估。然而,了解每一种算法背后的直觉,它们的优点和缺点是什么,以及如何应对其局限性是有好处的。

这里是我GitHub中的完整代码。

数据科学家并不是懂得python、Sklearn、TensorFlow等的人。但是,谁是谁,谁知道如何玩弄这些东西。 媒介.com

参考文献 [1] Stephanie Glen Decision Tree vs Random Forest vs Gradient Boosting Machines: 简单解释一下(2018)

[2] Vishal Morde XGBoost算法。愿她长久统治! (2019)

[3] GAURAV SHARMA,你应该知道的5种回归算法--介绍性指南!

[4] Aarshay Jain,《XGBoost中的参数调整完整指南》,用Python编写的代码

[5] scikit-learn.org,决策树,了解决策树结构¶。

[6] Hyperopt: 分布式异步超参数优化

[7] XGboost, XGBoost参数

[8] TINU ROHITH D, HyperParameter Tuning - Hyperopt Bayesian Optimization for (Xgboost and Neural network) (2019)

[9] Jobs Admin,你需要知道的另一种超参数优化技术--Hyperopt (2020)

[10] Aurelien Geron,用Scikit-learn和Tensorflow进行机器学习的实践(2019)

本文由 mdnice 多平台发布

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_40523298/article/details/127106158

智能推荐

项目开发_vue_app_pubilc_path作用-程序员宅基地

文章浏览阅读340次。项目开发.env(在所有的环境中被载入)# 环境NODE_ENV = "development".env.staging(只在测试环境中被载入)# staging 预演环境,即线上的dev环境NODE_ENV = "production"# publicPathVUE_APP_PUBLIC_PATH = '/'.env.production(只在生产环境中被载入)# 环境NODE_ENV = "production"# publicPath# VUE_APP_PUBLIC_P_vue_app_pubilc_path作用

Spring Boot配置RabbitMQ(消息队列)_springboot rabbitconfig-程序员宅基地

文章浏览阅读1.7k次。11 RabbitMQRabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。RabbitMQ服务器是用Erlang语言编写的,而集群和故障转移是构建在开放电信平台框架上的。所有主要的编程语言均有与代理接口通讯的客户端库。_springboot rabbitconfig

eclipse使用宏设置_eclipse添加宏定义-程序员宅基地

文章浏览阅读4.9k次,点赞4次,收藏3次。安装宏插件Eclipse没有自带的宏设置,需要添加插件Practical Macro插件,将插件下载到本地。eclipse中点击菜单Help->Install New software打开对话框,点击右上边Add按钮,点击Archive按钮选择上一步下载的插件,填写名称点击OK。重启eclipse,在工具栏上会出现宏设置相关的三个按钮。如下图: 宏使用,以格式化并保存为..._eclipse添加宏定义

修改线程栈大小_rt-thread修改空闲线程栈大小-程序员宅基地

文章浏览阅读1.3k次。首先,我们需要明白,我们在创建线程的时候,线程是有属性的,那么都包括哪些属性呢?今天我们要讲的栈大小就是创建的线程的属性之一,在pthread_attr_t 结构体中,都保存着一些缺省值,如果我们没有对其进行修改,则以缺省值进行存储 如图:属性值结果scopePTHREAD_SCOPE_PROCESS新线程与进程中的其他线程发生竞争。detachstatePTHREAD_CREATE_JOINA..._rt-thread修改空闲线程栈大小

java发送邮件354_基于SMTP的JAVA邮件发送程序-程序员宅基地

文章浏览阅读479次。这个程序没有使用JavaMail API,而是根据SMTP协议的要求直接处理协议的细节发送邮件,虽然比较麻烦了一些,但是对了解邮件协议的细节很有帮助的。本文分两部分,第一部分是SMTP命令介绍(这个从别的地方抄的,嘿嘿);第二部分通过一个实例真正理解一下发送邮件的过程。一:SMTP 命令简介什么是 SMTPSMTP (Simple Mail Transfer Protocol) : 电子邮件从客户..._java 邮件客户端 354

oracle ocm查寻,如何查询Oracle 12c OCP , 11g OCP , OCM考试成绩和证书-程序员宅基地

文章浏览阅读1.1k次。从2013年10月30日开始,Oradle的考试成绩不在VUE考试系统当场出来,需要考试在考试结束后到CertView.上查询。其中的关键是需要考生先到Oracle网站注册个SSO(单点登录)账号,同时在Certview.oradle.com绑定一个VUEtestID。同时保证你在VUE系统的E-MAIL正确设置,考试结束后在CertView.oradle.com就可以查看你的成绩和电..._ocp 认证查询

随便推点

python怎么将png转为tif_python处理遥感必知或必会(1)-程序员宅基地

文章浏览阅读1.8k次。笔者目前的主要对遥感的研究方法如下,其中对大图及其结果处理和分析主要使用Arcgis、Envi等遥感专用软件,可以方便的进行可视化,尤其是当研究分析的图像为多光谱的大范围的大图时,直接进行波段组合观察预测的准确性,并可以分析标签的诸多属性。遥感图像常见的保存格式为tif,其包含了地理投影坐标等信息。python的GDAL提供了读写分析。一般而言,笔者用到了GDAL的读图功能,尤其是当操作..._png 转tiff 坐标

关于VUE + element-UI 项目中icon 图片显示不出来,报警告:OTS parsing error: invalid version tag_elemetn failed to decode downloaded font icon图标不显示-程序员宅基地

文章浏览阅读4.7k次。今天在写一写自己的小东西的时候,vue-cli+element-ui 项目跑起来的时候,icon 图片显示不出来,莫名其妙的报警告:Failed to decode downloaded font: OTS parsing error: invalid version tag先上图片一:..._elemetn failed to decode downloaded font icon图标不显示

SAP CRM Fiori 应用 My Opportunity 的分页读取逻辑,在 GM4 - AG3 无法正常工作_fiori分页显示-程序员宅基地

文章浏览阅读237次。从OData V2注释转换而来的完整OData V4注释被包含在指定目标的注释文件中的注释所取代。此外,来自“http://www.sap.com/Protocols/SAPData”名称空间的注释从扩展数组中提取出来,并从对象转换为名称前缀为。注意,这是另外发生的,因此下面的示例显示了这两种表示。这样,这样的注释就可以通过简单的相对路径来处理,而不是搜索数组。作为基础,并将现有的sap.ui.model.odata.ODataAnnotations的 V4 直接合并到相应的模型元素。但 task 可以。._fiori分页显示

it论坛 计算机科学概论,(毕业论文) 计算机科学与技术专业 IT技术论坛.doc-程序员宅基地

文章浏览阅读102次。您所在位置:网站首页 > 海量文档&nbsp>&nbsp学术论文&nbsp>&nbsp毕业论文(毕业论文) 计算机科学与技术专业 IT技术论坛.doc39页本文档一共被下载:次,您可全文免费在线阅读后下载本文档。 下载提示1.本站不保证该用户上传的文档完整性,不预览、不比对内容而直接下载产生的反悔问题本站不予受理。2...

java 骆驼,从Java中的骆驼路线获取可视化文档?-程序员宅基地

文章浏览阅读93次。I'm new to apache camel and made some routes working properly via Java DSL.Now I'm wondering if there is a chance to get automatic a visual representation of these routes with JBoss Fuse?I mean not by..._java 骆驼监控

java has already_spring mvc处理http请求报错:java.lang.IllegalStateException: getInputStream() has already ...-程序员宅基地

文章浏览阅读1.1k次。发送post请求到controller处理失败,报错日志如下:java.lang.IllegalStateException: getInputStream() has already been called for this requestat org.apache.catalina.connector.Request.getReader(Request.java:1212)at org.apa..._java.lang.illegalstateexception: getinputstream() has already been called fo

推荐文章

热门文章

相关标签