【R语言实战】——多模型预测及评价

🍉CSDN小墨&晓末:https://blog.csdn.net/jd1813346972

   个人介绍: 研一|统计学|干货分享
         擅长Python、Matlab、R等主流编程软件
         累计十余项国家级比赛奖项,参与研究经费10w、40w级横向

该篇文章主要展示了利用R语言建立最小二乘线性回归、岭回归、LASSO、PCR、PLS五种模型对“College”数据集中的申请数量进行预测,并进行模型评估。

1 项目任务

  使用“College”数据集中的其他变量预测收到的申请数量。

   (a)将数据集分成训练集和测试集。

   (b)在训练集上使用最小二乘法拟合线性模型,并报告所获得的测试误差。

   ©在训练集上拟合岭回归模型,通过交叉验证选择 λ。报告获得的测试误差。

   (d)在训练集上拟合 LASSO 模型,通过交叉验证选择 λ。报告获得的测试误 差,以及非零系数估计值的数量。

   (e)在训练集上拟合 PCR 模型,通过交叉验证选择 M。报告获得的测试误差, 以及通过交叉验证选择的 M 值。

   (f)在训练集上拟合 PLS 模型,通过交叉验证选择 M。报告获得的测试误差, 以及通过交叉验证选择的 M 值。

   (g)对获得的结果进行评论。我们能多准确地预测收到的大学申请数量?这 五种方法产生的测试误差有很大差别吗?

2 数据集介绍

  这个数据集包含了大量关于不同学校的详细数据,主要变量包括: 1.Private:是否为私立学校。 2.Apps:申请人数。 3.Accept:被录取人数。 4.Enroll:注册人数。 5.Top10perc:排名前 10%的新生比例。 6.Top25perc:排名前 25%的新生比例。 7.F.Undergrad:全职本科生人数。 8.P.Undergrad:兼职本科生人数。 9.Outstate:州外学费。 10.Room.Board:房间和伙食费用。 11.Books:书籍费用。 12.Personal:个人费用。 13.PhD:拥有博士学位的教师比例。 14.Terminal:教师拥有终极学位的比例。 15.S.F.Ratio:学生与教师的比例。 16.perc.alumn:捐赠的校友比例。 17.Expend:学生教育支出。 18.Grad.Rate:毕业率。 此外,该数据集还公布了学校名称。

3 加载相关包并读取数据

  运行程序:

library("class")  
library("caret") 
library("gmodels") 
library('pls')
data<- read.csv("D:\\机器学习与R语言\\College.csv",header = T)
head(data)     #查看前六行

  运行结果:

4 探索和准备数据

  1)使用 str()发现,该数据集共有 777 个观测值,19 个属性,同时,其涉及 的数据类型有字符型(int)和整型(int),其中“Apps”为目标变量。

  运行程序:

str(data)                       #查看数据类型

  运行结果:

  2)使用 table()函数输出数据集中“Private”变量分布情况,同时利用 ifelse ()函数将其转化为 0-1 变量,其中“Yes”转化为 1,“No”转化为 0。该数据 集中,私立学校和公立学校数量分别为 565、212。

  运行程序:

table(data$Private)
data$Private_Yes=ifelse(data$Private=="Yes",1,0) #将分类变量Private转化为0-1变量,保存为Private_Yes
data=data[c(1,3:20)]                            ##剔除字符变量Private

  运行结果:

  3)利用 summary()查看各变量数据特征情况,见运行结果,包括每个特 征的最小值,1/4 分位数,中位数,均值,3/4 分位数,最大值。其中“Apps”数 量分布在 81-48094 之间。

  运行程序:

data<-data[c('Apps','Accept','Enroll',
             'Top10perc','Top25perc','F.Undergrad','P.Undergrad',
             'Outstate','Room.Board','Books','Personal',
             'PhD','Terminal','S.F.Ratio','perc.alumni','Expend','Grad.Rate',
             'Private_Yes')]

summary(data)

  运行结果:

5 划分训练集和测试集

  运行程序:

set.seed(123) #设置随机种子以保证结果可重复
trainIndex=createDataPartition(data$Apps,p=0.8,
                               list=FALSE,
                               times=1)


data_train<-data[trainIndex, ] #创建训练集
data_test<-data[-trainIndex, ] #创建测试集

6 拟合最小二乘线性回归模型

  1)模型总结。训练集中,根据运行结果显示,线性回归方程 F 值为 537.3, p 值远小于 0.05,说明拟合的回归方程在 0.05 的显著性水平上显著成立。拟合优 度 R 2 为 0.9378,说明申请数量有 93.78%的信息可以用模型中的自变量来解释, 模型效果较好。其中,变量“Accept”、“Enroll”、“Top10perc”、“Top25perc”、 “F.Undergrad”、“Outstate”、“Expend”、“Grad.Rate”、“Private_Yes”在 0.05 的显著性水平下,对因变量“Apps”存在显著影响。

  运行程序:

lm_model=lm(Apps~.,data=data_train) #拟合线性回归模型
summary(lm_model)

  运行结果:

  2)测试误差。根据运行结果显示,最小二乘线性回归模型,在测试集表现 中,RMSE 为 1106.46,MAE 为 609.14。

  运行程序:

lm_pred=predict(lm_model,newdata=data_test) #对测试集进行预测
lm_error_RMSE=sqrt(mean((lm_pred-data_test$Apps)^2)) #计算均方根误差
lm_error_MAE=mean(abs(lm_pred-data_test$Apps)) #计算绝对平均误差

print(paste("线性模型测试误差RMSE:",lm_error_RMSE))
print(paste("线性模型测试误差MAE:",lm_error_MAE))

  运行结果:

7 拟合岭回归模型

  1)模型总结。训练集中,在拟合岭回归模型过程中,利用交叉验证的方式 选择最优正则化λ,根据结果运行显示,对应最小 MSE 的λ值为 388.9,MSE 为1785806,在该 λ 值下,模型中非零系数的数量为 17(不包含截距项),且在最小 MSE 的一个标准误差内的最大 λ 值为 1430.4,MSE 为 2405994,该 λ 值 下,模型中非零系数的数量为 17(不包含截距项)。

  运行程序:

ridge_model=cv.glmnet(as.matrix(data_train[,-c(1)]),data_train$Apps,alpha=0) #交叉验证拟合岭回归模型
print(ridge_model) #输出模型

  运行结果:

  2)测试误差。根据运行结果显示,交叉验证的岭回归模型,在测试集表现 中,RMSE 为 1108.10,MAE 为 605.30。

  运行程序:

ridge_model <- glmnet(as.matrix(data_train[,-c(1)]),data_train$Apps, alpha = 0, lambda = best_lambda)

ridge_pred <- predict(ridge_model, newx = as.matrix(data_test[,-c(1)]), s = best_lambda)  

ridge_error_RMSE=sqrt(mean((ridge_pred-data_test$Apps)^2)) #计算均方根误差
ridge_error_MAE=mean(abs(ridge_pred-data_test$Apps)) #计算绝对平均误差

print(paste("交叉验证岭回归测试误差RMSE:",ridge_error_RMSE))
print(paste("交叉验证岭回归测试误差MAE:",ridge_error_MAE))

  运行结果:

8 拟合LASSO模型

  1)模型总结。训练集中,在拟合 LASSO 回归模型过程中,利用交叉验证 的方式选择最优正则化λ,根据结果运行显示,对应最小 MSE 的λ值为 2.1,MSE 为 1346355,在该 λ 值下,模型中非零系数的数量为 17(不包含截距 项),且在最小 MSE 的一个标准误差内的最大 λ 值为 346.2,MSE 为 1587747,该 λ 值下,模型中非零系数的数量为 2(不包含截距项)。

  运行程序:

lasso_model=cv.glmnet(as.matrix(data_train[,-c(1)]),data_train$Apps,alpha=1) #交叉验证拟合lasso回归模型
print(lasso_model) #输出模型

  运行结果:

  2)测试误差。根据运行结果显示,交叉验证的 LASSO 回归模型,在测试 集表现中,RMSE 为 1099.85,MAE 为 604.00。

  运行程序:

best_lambda <- lasso_model$lambda.min 
print(paste("最优lambda:",best_lambda))

# 使用最佳λ在训练集上重新拟合模型  
lasso_model <- glmnet(as.matrix(data_train[,-c(1)]),data_train$Apps, alpha = 1, lambda = best_lambda)
lasso_pred=predict(lasso_model,newx = as.matrix(data_test[,-c(1)]), s = best_lambda) #对测试集进行预测
lasso_error_RMSE=sqrt(mean((lasso_pred-data_test$Apps)^2)) #计算均方根误差
lasso_error_MAE=mean(abs(lasso_pred-data_test$Apps)) #计算绝对平均误差

print(paste("交叉验证LASSO回归测试误差RMSE:",lasso_error_RMSE))
print(paste("交叉验证LASSO回归测试误差MAE:",lasso_error_MAE))

  运行结果:

9 拟合 PCR 模型

  1)模型总结。训练集中,在拟合 PCR 模型过程中,利用交叉验证的方式 选择最优主成分数量 M 为 10,当使用 10 个主成分时,可以解释原始数据中 85.87%的方差,解释能力较强。

  运行程序:

##拟合PCR模型
pcr_model=train(Apps~.,data=data_train,method="pcr",
                preProcess=c("center","scale"),tuneLength=10) #交叉验证拟合主成分回归模型

##选定的主成分数M
print(paste("选定的主成分数 (M):",pcr_model$bestTune))
print(summary(pcr_model))

  运行结果:

  2)测试误差。根据运行结果显示,交叉验证的 PCR 模型,在测试集表现 中,RMSE 为 1021.33,MAE 为 707.41。

  运行程序:

pcr_pred=predict(pcr_model,newdata=data_test)

pcr_error_RMSE=sqrt(mean((pcr_pred-data_test$Apps)^2)) #计算均方根误差
pcr_error_MAE=mean(abs(pcr_pred-data_test$Apps)) #计算绝对平均误差

print(paste("交叉验证PCR模型测试误差RMSE:",pcr_error_RMSE))
print(paste("交叉验证PCR模型测试误差MAE:",pcr_error_MAE))

  运行结果:

10 拟合PLS模型

  1)模型总结。训练集中,在拟合 PLS 回归模型过程中,利用交叉验证的 方式选择最优主成分数量 M 为 10,当使用 10 个主成分时,可以解释原始数据 中 93.73%的方差,解释能力较强。

  运行程序:

pls_model=train(Apps~.,data=data_train,method="pls",
                preProcess=c("center","scale"),tuneLength=10) #交叉验证拟合偏最小二乘回归

##选定的主成分数M
print(paste("选定的主成分数 (M):",pls_model$bestTune))
print(summary(pls_model))

  运行结果:

  2)测试误差。根据运行结果显示,交叉验证的 PCR 模型,在测试集表现 中,RMSE 为 1095.97,MAE 为 607.09。

  运行程序:

pls_pred=predict(pls_model,newdata=data_test)

pls_error_RMSE=sqrt(mean((pls_pred-data_test$Apps)^2)) #计算均方根误差
pls_error_MAE=mean(abs(pls_pred-data_test$Apps)) #计算绝对平均误差

print(paste("交叉验证PLS模型测试误差RMSE:",pls_error_RMSE))
print(paste("交叉验证PLS模型测试误差MAE:",pls_error_MAE))

  运行结果:

11 模型评估

  本实验在训练集过程中,利用训练集分别拟合了最小二乘线性回归模型、交 叉验证的岭回归模型、交叉验证的 LASSO 模型、PCR 模型、PLS 回归模型五 个模型,并在测试集进行测试,以 RMSE、MAE 指标评估模型。结果见表 1 所 示。

  根据表 1 可以看出,五种模型在测试集表现中,RMSE 集中在 1100 附近, 其中 PCR 模型的 RMSE 指标最低,MAE 大多集中在 600 附近,PCR 为 707,五 种模型总体上性能相似。

12 完整代码

##加载相关包并读取数据
library("class")  
library("caret") 
library("gmodels") 
library('pls')
data<- read.csv("D:\\机器学习与R语言\\College.csv",header = T)
head(data)     #查看前六行

str(data)                       #查看数据类型


table(data$Private)
data$Private_Yes=ifelse(data$Private=="Yes",1,0) #将分类变量Private转化为0-1变量,保存为Private_Yes
data=data[c(1,3:20)]                            ##剔除字符变量Private



data<-data[c('Apps','Accept','Enroll',
             'Top10perc','Top25perc','F.Undergrad','P.Undergrad',
             'Outstate','Room.Board','Books','Personal',
             'PhD','Terminal','S.F.Ratio','perc.alumni','Expend','Grad.Rate',
             'Private_Yes')]

summary(data)


set.seed(123) #设置随机种子以保证结果可重复
trainIndex=createDataPartition(data$Apps,p=0.8,
                               list=FALSE,
                               times=1)


data_train<-data[trainIndex, ] #创建训练集
data_test<-data[-trainIndex, ] #创建测试集


##最小二乘线性回归
lm_model=lm(Apps~.,data=data_train) #拟合线性回归模型
summary(lm_model)


lm_pred=predict(lm_model,newdata=data_test) #对测试集进行预测
lm_error_RMSE=sqrt(mean((lm_pred-data_test$Apps)^2)) #计算均方根误差
lm_error_MAE=mean(abs(lm_pred-data_test$Apps)) #计算绝对平均误差

print(paste("线性模型测试误差RMSE:",lm_error_RMSE))
print(paste("线性模型测试误差MAE:",lm_error_MAE))



##拟合岭回归模型
ridge_model=cv.glmnet(as.matrix(data_train[,-c(1)]),data_train$Apps,alpha=0) #交叉验证拟合岭回归模型
print(ridge_model) #输出模型


# 使用最佳λ在训练集上重新拟合模型  
ridge_model <- glmnet(as.matrix(data_train[,-c(1)]),data_train$Apps, alpha = 0, lambda = best_lambda)

ridge_pred <- predict(ridge_model, newx = as.matrix(data_test[,-c(1)]), s = best_lambda)  

ridge_error_RMSE=sqrt(mean((ridge_pred-data_test$Apps)^2)) #计算均方根误差
ridge_error_MAE=mean(abs(ridge_pred-data_test$Apps)) #计算绝对平均误差

print(paste("交叉验证岭回归测试误差RMSE:",ridge_error_RMSE))
print(paste("交叉验证岭回归测试误差MAE:",ridge_error_MAE))

##LASSO回归
lasso_model=cv.glmnet(as.matrix(data_train[,-c(1)]),data_train$Apps,alpha=1) #交叉验证拟合lasso回归模型
print(lasso_model) #输出模型


# 选择最佳λ(最小交叉验证误差的λ)  
best_lambda <- lasso_model$lambda.min 
print(paste("最优lambda:",best_lambda))

# 使用最佳λ在训练集上重新拟合模型  
lasso_model <- glmnet(as.matrix(data_train[,-c(1)]),data_train$Apps, alpha = 1, lambda = best_lambda)
lasso_pred=predict(lasso_model,newx = as.matrix(data_test[,-c(1)]), s = best_lambda) #对测试集进行预测
lasso_error_RMSE=sqrt(mean((lasso_pred-data_test$Apps)^2)) #计算均方根误差
lasso_error_MAE=mean(abs(lasso_pred-data_test$Apps)) #计算绝对平均误差

print(paste("交叉验证LASSO回归测试误差RMSE:",lasso_error_RMSE))
print(paste("交叉验证LASSO回归测试误差MAE:",lasso_error_MAE))


##拟合PCR模型
pcr_model=train(Apps~.,data=data_train,method="pcr",
                preProcess=c("center","scale"),tuneLength=10) #交叉验证拟合主成分回归模型

##选定的主成分数M
print(paste("选定的主成分数 (M):",pcr_model$bestTune))
print(summary(pcr_model))


pcr_pred=predict(pcr_model,newdata=data_test)

pcr_error_RMSE=sqrt(mean((pcr_pred-data_test$Apps)^2)) #计算均方根误差
pcr_error_MAE=mean(abs(pcr_pred-data_test$Apps)) #计算绝对平均误差

print(paste("交叉验证PCR模型测试误差RMSE:",pcr_error_RMSE))
print(paste("交叉验证PCR模型测试误差MAE:",pcr_error_MAE))


##拟合PLS回归模型
pls_model=train(Apps~.,data=data_train,method="pls",
                preProcess=c("center","scale"),tuneLength=10) #交叉验证拟合偏最小二乘回归

##选定的主成分数M
print(paste("选定的主成分数 (M):",pls_model$bestTune))
print(summary(pls_model))

pls_pred=predict(pls_model,newdata=data_test)

pls_error_RMSE=sqrt(mean((pls_pred-data_test$Apps)^2)) #计算均方根误差
pls_error_MAE=mean(abs(pls_pred-data_test$Apps)) #计算绝对平均误差

print(paste("交叉验证PLS模型测试误差RMSE:",pls_error_RMSE))
print(paste("交叉验证PLS模型测试误差MAE:",pls_error_MAE))
  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小墨&晓末

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值