5.使用机器学习来做模型的预测

最后,我们放弃之前被转换并使用用过的变量和标识变量。我们要完成这个步骤,需要用到dplyr包里面的select函数

> combi <- select(combi,-c(Item_Identifier,Outlet_Identifier,Item_Fat_Content,Outlet_Establishment_Year,Item_Type))
> str(combi)

在这个部分,我会讲到回归、决策树和随即森林。对这些算法的详细解释已经超过了这篇文章的范围。这些算法在我们之前的文章里面已经有比较满意的解释。我已经对向这些有用的资源提供了连接.
你可以看到,我们已经对所有的分类变量进行了编码。现在,这个数据集可以进行进一步的建模。让我们从训练集和测试集开始,先把数据集分类.

> new_train <- combi[1:nrow(train),]
> new_test <- combi[-(1:nrow(train)),]

线性回归(多元)

当解释变量本质上是连续的和被解释变量有许多个的情况下我们会使用多元线性回归。如果被解释变量是分类变量,我们将使用Logistic回归。在你进一步学习之前,这里再加强一下回归的基础知识.
线性回归遵循下面的假设:
1.解释变量和被解释变量直接存在线性关.
2.解释变量之间不相关,如果相关会出现共线性,也就是我们所知的多重共线性
3.误差项是不相关的,否则会出现自相关性
4.误差项的方差是常数,不是常数的方差会导致异方差性
5.现在,让我们开始用这个数据集建立我们的第一个线性回归模型。R使用lm()函数来做线性回归

> linear_model <- lm(Item_Outlet_Sales ~ ., data = new_train)
> summary(linear_model)

调整后的R平方表示回归模型的拟合程度。更高的R平方,模型的拟合程度越好。我们的R平方=0.2085,这意味着我们出线了极其严重的错误,让我们把错误找出来.
在我们的例子中,我能发现我们新的变量并没有多大的作用。比如,Item count、Outlet Count,Item_Type_New.这些变量都是不显著的,显著的变量用“*“表示
我们知道,解释变量之间相关会降低模型的准确性。让我们来找出大量的出线在解释变量之间的相关性。这个只要简单的使用下列方法:

> cor(new_train)

另外,你也可以用corrplot包来做一个有趣的相关性的作图。通过游览很长的一列相关系数表,我能发现一个致命的相关系数.

cor(new_train$Outlet_Count, new_train$`Outlet_Type_Grocery Store`)
[1] -0.9991203

Outlet_Count和Outlet Type Grocery Store之间高度(负)相关。下面是我在这个模型中发现的一些问题:
我们有一些解释变量之间是相关的。
我们做了一个热键编码和标签编码。那是没有必要的,因为线性回归会自动创建虚拟变量来处理分类变量。
在特征工程中创建的新的变量(item count,outlet count,item type new)不显著。
让我们建立更多的稳健的回归模型。这个时候,我们用没有编码和新特征的变量来建立简单的模型。下面是整个代码:

#load directory加载目录
> path <- "C:/Users/manish/desktop/Data/February 2016"

> setwd(path)

#load data加载数据
> train <- read.csv("train_Big.csv")
> test <- read.csv("test_Big.csv")

#create a new variable in test file 在测试文件中创建一个新的变???
> test$Item_Outlet_Sales <- 1

#combine train and test data 把训练集和测试集合并
> combi <- rbind(train, test)

#impute missing value in Item_Weight 补充在Item_Weight中的缺失???
> combi$Item_Weight[is.na(combi$Item_Weight)] <- median(combi$Item_Weight, na.rm = TRUE)

#impute 0 in item_visibility ???0增加到item_visibility???
> combi$Item_Visibility <- ifelse(combi$Item_Visibility == 0, median(combi$Item_Visibility),                         combi$Item_Visibility)

#rename level in Outlet_Size 更改Outlet_Size???*水平*的名???
> levels(combi$Outlet_Size)[1] <- "Other"

#rename levels of Item_Fat_Content 更改Item_Fat_Content???*水平*的名???
> library(plyr)
> combi$Item_Fat_Content <- revalue(combi$Item_Fat_Content,c("LF" = "Low Fat", "reg" =                                   "Regular"))
> combi$Item_Fat_Content <- revalue(combi$Item_Fat_Content, c("low fat" = "Low Fat"))

#create a new column 2013 - Year 创建2013-Year这一???
> combi$Year <- 2013 - combi$Outlet_Establishment_Year

#drop variables not required in modeling 删除模型中不需要的变量
> library(dplyr)
> combi <- select(combi, -c(Item_Identifier, Outlet_Identifier, Outlet_Establishment_Year))

#divide data set 把数据集分成两部???
> new_train <- combi[1:nrow(train),]
> new_test <- combi[-(1:nrow(train)),]

#linear regression 线性回???
> linear_model <- lm(Item_Outlet_Sales ~ ., data = new_train)
> summary(linear_model)

现在我们得到R平方=0.5623。这个告诉我们,只要通过简单的方法就能得到更高的准确性。比先前的模型有很大的提高,以后建模,请记住要从简单的模型开始。
让我们检查回归图来找出提高模型的方法。

> par(mfrow=c(2,2))
> plot(linear_model)

tupian
你可以在R Studio中同过按zoom按钮来放大这个图片。每一幅图片都有一个不同故事,但是最重要的故事是被残差和拟合图所描绘出来。
真实的残差值和预测的残差值直接有所不同。拟合值是预测值。如果你仔细看,你会发现它是一个漏斗形(从右往左看)。这个图片的形状显示出我们的模型有异方差性(误差项的方差不是常数)。如果误差项的方差是常数,图形就不会是这个样子。
一个通常的处理异方差性的做法是对被解释变量做对数处理。让我们这样做看看我们能不能进一步的提高模型:

> linear_model <- lm(log(Item_Outlet_Sales) ~ ., data = new_train)
> summary(linear_model)

tupian2
同时,这是对我们模型的输出的截图。恭喜!我们把模型的R平方=0.72提高了。现在,我们在正确的道路上。你可以在再一次检验模型的残差(你可以放大它)。你会发现在residual vs fitted value图中不在有趋势。
tupian3
这个模型可以通过探测到异常指和更高的杠杆点来提高模型。目前为止,我把这一部分的任务留给你!我会写另一个分离的部分关于回归的秘密。现在,让我们检查RMSE,以至于让我们可以和下面提出的其他算法的效果进行比较。
为了计算RMSE,我们要加载Metrics包。

> install.packages("Metrics")
> library(Metrics)
> rmse(new_train$Item_Outlet_Sales,exp(linear_model$fitted.values))
[1] 1140.004

让我们继续进行决策树算法并且尝试进一步提高RMSE分数。

决策树

在你开始之前,我会推荐你看一下决策树算法的基础。从而明白是什么让它比线性回归更好,查看这个教程的第一部分第二部分
在R里面,决策树算法能够通过运行rpart包来运行。另外,我们可以使用caret包来做交叉验证。交叉验证是一个建立文件模型的工具,不会导致过度拟合。阅读更多关于交叉验证
在R里面,决策树使用一个复杂参数(cp)。它在训练集里面测度了模型的复杂性和精度的衡量指标。一个小的cp将会导致更大的树,将会导致过度拟合模型。相反的,一个大的cp值会导致拟合不足。当模型不能捕获拟合趋势的时候会发生拟合不足的情况。让我们为我们的模型5次交叉验证找出最优的cp值

#loading required libraries
> library(rpart)
> library(e1071)
> library(rpart.plot)
> library(caret)

#setting the tree control parameters
> fitControl <- trainControl(method = "cv", number = 5)
> cartGrid <- expand.grid(.cp=(1:50)*0.01)

#decision tree
> tree_model <- train(Item_Outlet_Sales ~ ., data = new_train, method = "rpart", trControl = fitControl, tuneGrid = cartGrid)
> print(tree_model)

最后得出cp=0.01.你也可以检查在控制台中的表来发现更多的信息。cp=0.01的模型有最小的RMSE。让我们现在用cp=0.01作为复杂参数建立一个决策树

> main_tree <- rpart(Item_Outlet_Sales ~ ., data = new_train, control = rpart.control(cp=0.01))
> prp(main_tree)

tupian4
这里是我们模型的决策树结构。如果你已经有基础,你现在会明白这个算法把Item_MRP作为最重要的变量(作为根节点)。让我们检查模型的RMSE并且看看是否比回归模型要好.

> pre_score <- predict(main_tree, type = "vector")
> rmse(new_train$Item_Outlet_Sales, pre_score)
[1] 1102.774

你可以看到,我们的RMSE从1140-1102.77有了一个很大提高,为了进一步的提高这个分数,你可以进一步调节参数来得到更大的精度.
## 随机森林
随机森林是一种很强大的算法,这种算法在整体上考虑了数据集中缺失值,离群值和其他非线性的因素。它简单的集合了一些分类树,因子命名为“森林”。我会建议你复习下随机森林的基础知识通过这个课程指导
在R里面,随机森林算法能够通过randomForest包来实现。同时,我们将会train包来做交叉验证和发现模型的最优值。
对于这个问题,我将会随机森林的两个参数。mtry和ntree,ntree是在森林中树的数量。mtry是在每一个节点种树需要采用的变量的个数。同时,我们会做一个5次的交叉验证。
让我们开始吧!

#load randomForest library
> library(randomForest)

#set tuning parameters
> control <- trainControl(method = "cv", number = 5)

#random forest model
> rf_model <- train(Item_Outlet_Sales ~ ., data = new_train, method = "parRF", trControl =                 control, prox = TRUE, allowParallel = TRUE)

#check optimal parameters
> print(rf_model)

tupian6
如果你注意看,我会发现我使用了方法=“parRF”。这是一个平行随机森林。这是一个平行的运行随机森林的方法。这个包让你本地计算机用更少的时间计算。另外,你可以使用“rf”的方法作为一个标准的随机森林函数。
现在我们得到了最优的mtry=15,让我们使用1000棵树来做运算。

#random forest model
> forest_model <- randomForest(Item_Outlet_Sales ~ ., data = new_train, mtry = 15, ntree = 1000)
> print(forest_model)
> varImpPlot(forest_model)

这个模型得到的RMSE=1132.04,并没有比决策树提高。随机森林具有一个可以展示出重要变量的特征。我们可以看到最重要的变量是Item_MRP(决策树算法得到的也是这个结果)
tuanpian7
这个模型能够进一步通过调整参数来提高。同时,让我们来看下由决策树得到的第一个最好的RMSE。

> main_predict <- predict(main_tree, newdata = new_test, type = "vector")
> sub_file <- data.frame(Item_Identifier = test$Item_Identifier, Outlet_Identifier = test$Outlet_Identifier,       Item_Outlet_Sales = main_predict)
> write.csv(sub_file, 'Decision_tree_sales.csv')

当预测一个样本外的数据时候,我们的RMSE得到的是1174.33.下面是你能够用来改进模型的方法:
1.因为我们没有使用编码,我鼓励你对随机森林使用一个热键编码和标签编码。
2.参数调整也许有用
3.使用梯度推进
4.建立一组合模型,关于组合模型的资料
做上面建议的想法的实现同时分享你的进步在下面的评论区。目前,在排行榜排名第一的算法在RMSE已经取得了1120.94分,去打败它吧!
## 结束语
这个学习指导结束了,对这个不是很好的结尾表示很抱歉。但是,我已经给了你足够的提示去做练习。在模型中不使用编码的决定,在碰到决策树之前证明是有作用的。
这个学习指导的动机是让你在R里从预测模型开始,我们学习了一些神奇的东西比如“建模”。不要跳到建立复杂的模型。简单的模型给你一个基准分同时也给了你一个门槛。
在这个学习指导中,我已经演示了每一步在R里的模型的预测。已经包括了数据探索,数据可视化,数据处理和使用回归建模,决策树和随机森林算法。
你发现这个学习指导有用吗?你在这个学习指导中面临什么问题?你可以在评论中随便的提问,如果你得到一个更好的分数请分享出来吧。
编辑:关于访客的要求,PDF版本的学习指导可以下载使用。你需要注册并登录来下载PDF。同时,你可以收藏这个网页为了进一步的学习,点击这个下载