python scratch file_基于树的算法:Scratch的完整教程(R和Python)

介绍

在R中,我们经常使用多个包来执行各种机器学习任务。例如:我们使用一个程序包估算缺失值,然后使用另一个程序包构建模型,最后使用第三个程序包评估其性能。

问题是,每个程序包都有一组特定的参数。在使用许多软件包时,我们最终要花费大量时间来确定哪些参数很重要。你不觉得吗

为了解决这个问题,我研究并遇到了一个名为的R包MLR,这在执行机器学习任务方面绝对令人难以置信。 该软件包包括我们经常使用的所有ML算法。

在本教程中,我研究了一个分类问题,并尝试使用机器学习来提高其准确性。我没有从理论上解释ML算法,但将重点放在其实现上。到本文结束时,您将有望精通R中的几种ML算法。但是,只有与您一起练习时,才可以。

注意:本文仅适用于R中使用Machine Learning的初学者和初学者。需要基本的统计知识。

表中的内容获取数据

探索数据

缺失价值估算

特征工程通过封顶去除异常值

新功能

机器学习功能重要性

QDA

逻辑回归交叉验证

决策树交叉验证

使用网格搜索进行参数调整

随机森林

支持向量机

GBM(渐变增强)交叉验证

使用随机搜索进行参数调整(更快)

XGBoost(极端梯度增强)

功能选择

带MLR包的机器学习

到目前为止,R还没有类似于Python的

现在让我们了解此程序包如何工作的基本概念。如果您在这里做的正确,那么了解整个软件包将只是步履蹒跚。

该程序包的整个结构都取决于以下前提:

创建一个任务。做一个学习者。训练他们。

创建任务意味着将数据加载到包中。学习者意味着选择一种从任务(或数据)中学习的算法(学习者)。最后,训练他们。

MLR软件包包含多种算法。这些算法已分类为回归,分类,聚类,生存,多分类和成本敏感分类。让我们看一下分类问题的一些可用算法:

> listLearners("classif")[c("class","package")]

class package

1 classif.avNNet nnet

2 classif.bartMachine bartMachine

3 classif.binomial stats

4 classif.boosting adabag,rpart

5 classif.cforest party

6 classif.ctree party

7 classif.extraTrees extraTrees

8 classif.knn class

9 classif.lda MASS

10 classif.logreg stats

11 classif.lvq1 class

12 classif.multinom nnet

13 classif.neuralnet neuralnet

14 classif.nnet nnet

15 classif.plsdaCaret caret

16 classif.probit stats

17 classif.qda MASS

18 classif.randomForest randomForest

19 classif.randomForestSRC randomForestSRC

20 classif.randomForestSRCSyn randomForestSRC

21 classif.rpart rpart

22 classif.xgboost xgboost

而且,还有更多。让我们现在开始工作!

1.获取数据

在本教程中,我从DataHack处理了一个流行的ML问题(需要一次登录才能获取数据):

下载数据后,让我们快速完成诸如设置工作目录和加载数据之类的初始命令。

> path

> setwd(path)

#load libraries and data

> install.packages("mlr")

> library(mlr)

> train

> test

2.探索数据

加载数据后,您可以使用以下方式访问数据:

> summarizeColumns(train)

name type na mean disp median mad min max nlevs

LoanAmount integer 22 146.4121622 85.5873252 128.0 47.4432 9 700 0

Loan_Amount_Term integer 14 342.0000000 65.1204099 360.0 0.0000 12 480 0

Credit_History integer 50 0.8421986 0.3648783 1.0 0.0000 0 1 0

Property_Area factor 0 NA 0.6205212 NA NA 179 233 3

Loan_Status factor 0 NA 0.3127036 NA NA 192 422 2

与基本str()功能相比,此功能提供了数据集的全面视图。上面显示的是结果的最后5行。同样,您也可以对测试数据进行处理:

> summarizeColumns(test)

从这些输出,我们可以得出以下推断:在数据中,我们有12个变量,其中Loan_Status有因变量,其余是自变量。

火车数据具有614个观测值。测试数据有367个观察值。

在训练和测试数据中,有6个变量缺少值(可以在na列中看到)。

ApplicantIncome并且Coapplicant Income是高度偏斜的变量。我们怎么知道呢?查看它们的最小值,最大值和中位数。我们必须将这些变量标准化。

LoanAmount,ApplicantIncome并且CoapplicantIncome具有离群值,应加以处理。

Credit_History是整数类型变量。但是,本质上是二进制的,我们应该将其转换为因数。

另外,您可以使用简单的直方图检查上述变量中​​是否存在偏斜。

> hist(train$ApplicantIncome, breaks = 300, main = "Applicant Income Chart",xlab = "ApplicantIncome")

> hist(train$CoapplicantIncome, breaks = 100,main = "Coapplicant Income Chart",xlab = "CoapplicantIncome")

正如您在上面的图表中看到的那样,偏斜只不过是大多数数据集中在图表的一侧。我们看到的是一个右偏图。为了可视化离群值,我们可以使用箱线图:

> boxplot(train$ApplicantIncome)

同样,您也可以为CoapplicantIncome和创建箱形图LoanAmount。

让我们更改Credit_History要分解的类。请记住,该类factor始终用于分类变量。

> train$Credit_History

> test$Credit_History

要检查更改,您可以执行以下操作:

> class(train$Credit_History)

[1] "factor"

您可以使用以下方法进一步检查数据:

> summary(train)

> summary(test)

我们发现该变量 Dependents的级别3+也应处理。在因子变量中修改名称级别非常简单。可以通过以下方式完成:

#rename level of Dependents

> levels(train$Dependents)[4]

> levels(test$Dependents)[4]

3.缺失价值估算

不仅是初学者,甚至优秀的R分析师都在为缺失的价值归因而苦苦挣扎。MLR软件包提供了一种很好的便捷方法,可以使用多种方法来估算缺失值。完成对数据的急需的修改后,让我们估算缺失的值。

在本例中,我们将使用基本均值和众数插补来插补数据。您还可以使用任何ML算法来推算这些值,但这是以计算为代价的。

#impute missing values by mean and mode

> imp

> imp1

该函数非常方便,因为您不必指定每个变量名称就可以进行插补。它根据变量的类别选择变量。它还为缺少的值创建新的虚拟变量。有时,这些(虚拟)特征包含可以使用此功能捕获的趋势。dummy.classes说我应该为哪些类创建一个虚拟变量。dummy.type说什么应该是新的虚拟变量的类。

$data imp函数的属性包含估算的数据。

> imp_train

> imp_test

现在,我们有了完整的数据。您可以使用以下命令检查新变量:

>summarizeColumns(imp_train)

>summarizeColumns(imp_test)

您是否注意到两个数据集之间存在差异?不是吗 再见。答案是Married.dummy变量仅存在于中imp_train,而不存在imp_test。因此,我们必须在建模阶段之前将其删除。

可选: 您可能会兴奋或好奇地尝试使用ML算法来估算缺失值。实际上,有些算法不需要您估算缺失值。您可以简单地为他们提供丢失的数据。他们自己照顾缺失的价值观。让我们看看它们是哪些算法:

> listLearners("classif", check.packages = TRUE, properties = "missings")[c("class","package")]

class package

1 classif.bartMachine bartMachine

2 classif.boosting adabag,rpart

3 classif.cforest party

4 classif.ctree party

5 classif.gbm gbm

6 classif.naiveBayes e1071

7 classif.randomForestSRC randomForestSRC

8 classif.rpart rpart

但是,建议始终单独处理缺失值。让我们看看如何使用rpart处理缺失值:

> rpart_imp

classes = list(numeric = imputeLearner(makeLearner("regr.rpart")),

factor = imputeLearner(makeLearner("classif.rpart"))),

dummy.classes = c("numeric","factor"),

dummy.type = "numeric")

4.特征工程

特征工程是预测建模中最有趣的部分。因此,特征工程具有两个方面:特征转换和特征创建。我们将在这里尝试这两个方面。

首先,让我们删除异常值从变量喜欢ApplicantIncome,CoapplicantIncome,LoanAmount。有许多技术可以消除异常值。在这里,我们将这些变量中的所有大值加盖,并将它们设置为阈值,如下所示:

#for train data set

> cd

> cd

> cd

#rename the train data as cd_train

> cd_train

#add a dummy Loan_Status column in test data

> imp_test$Loan_Status

> cde

> cde

> cde

#renaming test data

> cd_test

在分析变量分布之后,我可以自行选择阈值。要检查效果,您可以summary(cd_train$ApplicantIncome) 查看最大值最大值为33000。

在这两个数据集中,我们看到所有虚拟变量本质上都是数字。由于是二进制形式,因此应该是绝对的。让我们将其类转换为factor。这次,我们将使用简单 for和if循环。

#convert numeric to factor - train

> for (f in names(cd_train[, c(14:20)])) {

if( class(cd_train[, c(14:20)] [[f]]) == "numeric"){

levels

cd_train[, c(14:20)][[f]]

}

}

#convert numeric to factor - test

> for (f in names(cd_test[, c(13:18)])) {

if( class(cd_test[, c(13:18)] [[f]]) == "numeric"){

levels

cd_test[, c(13:18)][[f]]

}

}

这些循环说-'对于属于cd_train / cd_test数据帧的列号14到20的每个列名,如果这些变量的类别为数字,则从这些列中取出唯一值作为级别并将其转换为因数(分类)变量。

现在让我们创建一些新功能。

#Total_Income

> cd_train$Total_Income

> cd_test$Total_Income

#Income by loan

> cd_train$Income_by_loan

> cd_test$Income_by_loan

#change variable class

> cd_train$Loan_Amount_Term

> cd_test$Loan_Amount_Term

#Loan amount by term

> cd_train$Loan_amount_by_term

> cd_test$Loan_amount_by_term

在创建新特征(如果它们是数字的)时,我们必须检查它们与现有变量的相关性,因为经常有很高的机会。让我们看看我们的新变量是否也恰好是相关的:

#splitting the data based on class

> az

#creating a data frame of numeric variables

> xs

#check correlation

> cor(xs)

如我们所见,Total_Income与的相关性非常高ApplicantIncome。这意味着新变量不提供任何新信息。因此,此变量对建模数据没有帮助。

现在我们可以删除变量。

> cd_train$Total_Income

> cd_test$Total_Income

仍有足够的潜力创建新变量。在继续之前,我希望您对这个问题进行更深入的思考,并尝试创建更新的变量。在对数据进行了大量修改之后,让我们再次检查数据:

> summarizeColumns(cd_train)

> summarizeColumns(cd_test)

5.机器学习

到这里为止,我们已经执行了所有重要的转换步骤,除了标准化了偏斜的变量。这将在我们创建任务之后完成。

如开头所述,对于mlr,任务就是学习者在其上学习的数据集。由于这是一个分类问题,因此我们将创建一个分类任务。因此,任务类型仅取决于当前问题的类型。

#create a task

> trainTask

> testTask

我们来看看trainTask

> trainTask

Supervised task: cd_train

Type: classif

Target: Loan_Status

Observations: 614

Features:

numerics factors ordered

13 8 0

Missings: FALSE

Has weights: FALSE

Has blocking: FALSE

Classes: 2

N Y

192 422

Positive class: N

如您所见,它提供了cd_train数据描述。但是,一个明显的问题是它将正类视为N,而应将其视为Y。让我们对其进行修改:

> trainTask

要更深入地了解,可以使用查看任务数据str(getTaskData(trainTask))。

现在,我们将数据标准化。对于这一步,我们将使用normalizeFeaturesmlr包中的函数。默认情况下,此程序包将数据中的所有数字功能标准化。值得庆幸的是,我们仅需归一化的3个变量是数字变量,其余变量具有非数字变量类。

#normalize the variables

> trainTask

> testTask

在开始应用算法之前,我们应删除不需要的变量。

> trainTask

MLR包具有一个内置函数,该函数从数据返回重要变量。让我们看看哪些变量很重要。以后,我们可以使用这些知识来划分输入预测变量,以进行模型改进。运行此代码时,R可能会提示您安装“ FSelector”软件包,您应该这样做。

#Feature importance

> im_feat

> plotFilterValues(im_feat,n.show = 20)

#to launch its shiny application

> plotFilterValuesGGVIS(im_feat)

如果您仍然想知道information.gain,让我提供一个简单的解释。信息增益通常与决策树一起使用。决策树中拆分的每个节点都基于信息增益。通常,它会尝试找出包含最大信息的变量,从而使目标类别更容易预测。

现在开始建模。我不会详细解释这些算法,但是提供了有用资源的链接。首先,我们将讨论较简单的算法,并以复杂的算法结束本教程。

使用MLR,我们可以使用选择和设置算法makeLearner。该学习者将进行培训trainTask并尝试对进行预测testTask。

1.二次判别分析(QDA)。

通常,qda是一种参数算法。参数意味着它对数据做出某些假设。如果实际发现数据符合假设,则此类算法有时会优于几种非参数算法。

#load qda

> qda.learner

#train model

> qmodel

#predict on test data

> qpredict

#create submission file

> submit

> write.csv(submit, "submit1.csv",row.names = F)

这次,我们还要检查准确性。较高的CV精度确定我们的模型不会遭受高方差,并且可以很好地将看不见的数据概括化。

#logistic regression

> logistic.learner

#cross validation (cv) accuracy

> cv.logistic

同样,您可以为任何学习者进行简历。这不是很容易吗?因此,我使用了3倍CV的分层抽样。我总是建议您在分类问题中使用分层抽样,因为它可以将目标类别的比例保持为n倍。我们可以通过以下方式检查简历的准确性:

#cross validation accuracy

> cv.logistic$aggr

acc.test.mean

0.7947553

这是5折的平均准确度。要查看每个折叠的准确度,我们可以这样做:

> cv.logistic$measures.test

iter acc

1 1 0.8439024

2 2 0.7707317

3 3 0.7598039

现在,我们将训练模型并检查测试数据的预测准确性。

#train model

> fmodel

> getLearnerModel(fmodel)

#predict on test data

> fpmodel

#create submission file

> submit

> write.csv(submit, "submit2.csv",row.names = F)

哇!该算法极大地提高了准确性。此外,这是一个稳定的模型,因为我们的简历得分和排行榜得分非常接近。该提交的准确性为79.16%。好,我们现在正在改善。让我们继续下一个算法。

3. 决策树

据说决策树比逻辑回归模型更好地捕获了非线性关系。让我们看看是否可以进一步改善模型。这次,我们将对树参数进行超调以获得最佳结果。要获取任何算法的参数列表,只需编写(在本例中为rpart):

> getParamSet("classif.rpart")

这将返回一长串可调参数和非可调参数。让我们现在构建一个决策树。rpart package在创建树学习器之前,请确保已安装:

#make tree learner

> makeatree

#set 3 fold cross validation

> set_cv

我正在做3折简历,因为我们的数据较少。现在,让我们设置可调参数:

#Search for hyperparameters

> gs

makeIntegerParam("minsplit",lower = 10, upper = 50),

makeIntegerParam("minbucket", lower = 5, upper = 50),

makeNumericParam("cp", lower = 0.001, upper = 0.2)

)

如您所见,我已经设置了3个参数。minsplit表示节点中发生拆分的最小观察次数。minbucket说我应该在终端节点中保留的最少观察次数。cp是复杂度参数。它越小,树将在数据中学习更多特定关系,这可能会导致过度拟合。

#do a grid search

> gscontrol

#hypertune the parameters

> stune

您可以散步直到参数调整完成。可能是,去捉一些宠物小精灵!在我的机器上运行了15分钟。我有8GB intel i5处理器Windows机器。

#check best parameter

> stune$x

# $minsplit

# [1] 37

#

# $minbucket

# [1] 15

#

# $cp

# [1] 0.001

它返回最佳参数列表。您可以使用以下方法检查简历的准确性:

#cross validation result

> stune$y

0.8127132

使用setHyperPars函数,我们可以直接将最佳参数设置为算法中的建模参数。

#using hyperparameters for modeling

> t.tree

#train the model

> t.rpart

getLearnerModel(t.rpart)

#make predictions

> tpmodel

#create a submission file

> submit

> write.csv(submit, "submit3.csv",row.names = F)

决策树没有比逻辑回归更好的方法。与Logistic回归相比,该算法返回的准确度为79.14%。因此,仅凭一棵树是不够的。让我们现在建立一个森林。

4. 随机森林

随机森林是一种功能强大的算法,可产生惊人的结果。实际上,它的预测来自树木的合奏。它平均每棵树给出的预测并产生广义结果。从这里开始,大多数步骤与上面的步骤相似,但是这次我已经完成random search而不是grid search进行参数调整,因为它更快。

> getParamSet("classif.randomForest")

#create a learner

> rf

> rf$par.vals

importance = TRUE

)

#set tunable parameters

#grid search to find hyperparameters

> rf_param

makeIntegerParam("ntree",lower = 50, upper = 500),

makeIntegerParam("mtry", lower = 3, upper = 10),

makeIntegerParam("nodesize", lower = 10, upper = 50)

)

#let's do random search for 50 iterations

> rancontrol

虽然,随机搜索比网格搜索快,但有时却效率较低。在网格搜索中,该算法会调整提供的参数的每种可能组合。在随机搜索中,我们指定迭代次数,它随机地遍历参数组合。在此过程中,它可能会错过一些重要的参数组合,这些组合可能已返回最大精度,谁知道。

#set 3 fold cross validation

> set_cv

#hypertuning

> rf_tune

现在,我们有了最终参数。让我们检查参数列表和CV精度。

#cv accuracy

> rf_tune$y

acc.test.mean

0.8192571

#best parameters

> rf_tune$x

$ntree

[1] 168

$mtry

[1] 6

$nodesize

[1] 29

现在让我们构建随机森林模型并检查其准确性。

#using hyperparameters for modeling

> rf.tree

#train a model

> rforest

> getLearnerModel(t.rpart)

#make predictions

> rfmodel

#submission file

> submit

> write.csv(submit, "submit4.csv",row.names = F)

没有新的故事值得庆幸。该模型也返回了79.14%的准确性。因此,尝试使用网格搜索而不是随机搜索,并在评论中告诉我您的模型是否有所改进。

5. 支持向量机

支持向量机(SVM)也是一种用于回归和分类问题的监督学习算法。通常,它在n维空间中创建一个超平面,以根据目标类别对数据进行分类。让我们离开树算法一段时间,看看该算法是否可以带来一些改进。

由于大多数步骤与上述步骤相似,因此我认为为您理解这些代码不再是一个挑战。

#load svm

> getParamSet("classif.ksvm") #do install kernlab package

> ksvm

#Set parameters

> pssvm

makeDiscreteParam("C", values = 2^c(-8,-4,-2,0)), #cost parameters

makeDiscreteParam("sigma", values = 2^c(-8,-4,0,4)) #RBF Kernel Parameter

)

#specify search function

> ctrl

#tune model

> res

#CV accuracy

> res$y

acc.test.mean

0.8062092

#set the model with best params

> t.svm

#train

> par.svm

#test

> predict.svm

#submission file

> submit

> write.csv(submit, "submit5.csv",row.names = F)

该模型的准确性为77.08%。不错,但低于我们的最高分数。在这里不要感到绝望。这是机器学习的核心。除非获得一些好的变量,否则ML不会起作用。可能是,您应该在要素工程方面考虑得更多,并创建更多有用的变量。让我们现在进行增强。

6. GBM

现在,您正在进入增强算法的领域。GBM执行顺序建模,即在一轮预测之后,它将检查不正确的预测,为它们分配相对较大的权重,然后再次进行预测,直到正确预测它们为止。

#load GBM

> getParamSet("classif.gbm")

> g.gbm

#specify tuning method

> rancontrol

#3 fold cross validation

> set_cv

#parameters

> gbm_par

makeDiscreteParam("distribution", values = "bernoulli"),

makeIntegerParam("n.trees", lower = 100, upper = 1000), #number of trees

makeIntegerParam("interaction.depth", lower = 2, upper = 10), #depth of tree

makeIntegerParam("n.minobsinnode", lower = 10, upper = 80),

makeNumericParam("shrinkage",lower = 0.01, upper = 1)

)

n.minobsinnode指的是树节点中最少的观测值。shrinkage是调节参数,它指示算法应移动的快慢程度。

#tune parameters

> tune_gbm

#check CV accuracy

> tune_gbm$y

#set parameters

> final_gbm

#train

> to.gbm

#test

> pr.gbm

#submission file

> submit

> write.csv(submit, "submit6.csv",row.names = F)

该模型的准确性为78.47%。GBM的性能优于SVM,但不能超过随机森林的准确性。最后,让我们也测试XGboost。

7. Xgboost

Xgboost的内在属性包括一阶和二阶渐变,并行处理和修剪树的能力,因此被认为比GBM更好。xgboost的常规实现要求您将数据转换为矩阵。使用mlr,这不是必需的。

正如我在一开始所说的,使用此(MLR)包的好处是您可以遵循相同的命令集来实现不同的算法。

#load xgboost

> set.seed(1001)

> getParamSet("classif.xgboost")

#make learner with inital parameters

> xg_set

> xg_set$par.vals

objective = "binary:logistic",

eval_metric = "error",

nrounds = 250

)

#define parameters for tuning

> xg_ps

makeIntegerParam("nrounds",lower=200,upper=600),

makeIntegerParam("max_depth",lower=3,upper=20),

makeNumericParam("lambda",lower=0.55,upper=0.60),

makeNumericParam("eta", lower = 0.001, upper = 0.5),

makeNumericParam("subsample", lower = 0.10, upper = 0.80),

makeNumericParam("min_child_weight",lower=1,upper=5),

makeNumericParam("colsample_bytree",lower = 0.2,upper = 0.8)

)

#define search function

> rancontrol

#3 fold cross validation

> set_cv

#tune parameters

> xg_tune

#set parameters

> xg_new

#train model

> xgmodel

#test model

> predict.xg

#submission file

> submit

> write.csv(submit, "submit7.csv",row.names = F)

糟糕的XGBoost。该模型的准确性为68.5%,甚至低于qda。会发生什么?过度拟合。因此,该模型返回的CV准确度约为80%,但排行榜得分却急剧下降,因为该模型无法根据看不见的数据正确预测。

接下来您该怎么办?功能选择?

为了改进,让我们这样做。到目前为止,我们已经使用trainTask进行模型构建。让我们使用重要变量的知识。选取前6个重要变量,并在其上训练模型。您可以期待一些改进。要创建选择重要变量的任务,请执行以下操作:

#selecting top 6 important features

> top_task

因此,我已要求此函数使用随机森林重要性功能为我提供前6个重要功能。现在,在上述模型中替换top_task为trainTask,如果有任何改进,请在评论中告诉我。

另外,尝试创建更多功能。当前的排行榜冠军的准确率约为81%。如果您一直关注我到这里,现在就不要放弃。

尾注

本文的目的是让您开始使用机器学习技术。这些技术在当今的行业中普遍使用。因此,请确保您了解它们。不要将这些算法用作黑盒方法,请充分理解它们。我提供了资源链接。

上面发生的事情在现实生活中经常发生。您会尝试许多算法,但无法获得更高的准确性。但是,你不应该放弃。作为初学者,您应该尝试探索其他方法来提高准确性。请记住,无论您进行了多少错误尝试,您都必须一次正确。

您可能需要在加载这些模型时安装软件包,但这仅是一次。如果您完全按照本文进行操作,就可以构建模型了。您要做的就是学习背后的理论。

您觉得这篇文章对您有帮助吗?您是否尝试了上面列出的改进方法?哪种算法为您提供了最高 准确性?在下面的评论中分享您的看法/经验。

你可能感兴趣的:(python,scratch,file)