分类树与多层分析:R语言中的数据挖掘与建模
1. 安装必要的R包
在开始分类树分析之前,我们需要安装一些包含必要函数的R包。以下是具体的安装步骤:
1. 安装C4.5相关包 :J48是Weka中C4.5的实现,R用户可以通过RWeka包使用它。
install.packages("RWeka"); library(RWeka)
如果出现“JAVA_HOME cannot be determined from the Registry”错误,请安装正确的Java版本,参考:http://www.r-statistics.com/2012/08/how-to-load-the-rjava-package-after-the-error-java_home-cannot-be-determined-from-the-registry/ 。
2. 安装C5.0相关包 :C5.0包含在C50包中。
install.packages("C50"); library(C50)
- 安装CART相关包 :rpart包的rpart()函数可用于在R中运行CART,同时安装rpart.plot包用于绘制树。
install.packages("rpart"); library(rpart)
install.packages("rpart.plot"); library(rpart.plot)
- 安装随机森林相关包 :
install.packages("randomForest"); library(randomForest)
- 安装条件推理树相关包 :安装partykit包(包含ctree()函数)和Formula包。
install.packages(c("Formula","partykit"))
library(Formula); library(partykit)
2. 加载和准备数据
我们使用arules包中的AdultUCI数据集进行分析。以下是数据的加载和预处理步骤:
install.packages("arules")
library(arules)
data(AdultUCI)
summary(AdultUCI)
该数据集的类别是“income”,表示个人的年收入是否超过50,000美元。数据集中有很多缺失值,我们将移除包含缺失值的观测,并移除“fnlwgt”和“education-num”这两个属性。
ADULT = na.omit(AdultUCI)[,-c(3,5)]
接下来,我们使用caret包的createDataPartition()函数生成训练集和测试集,并对训练集进行过采样以平衡数据集。
install.packages("caret", dependencies = (c("Suggests","Depends")));
library(caret)
set.seed(123)
TrainCases = createDataPartition(ADULT$income, p = .5, list=F)
TrainTemp = ADULT[TrainCases,]
AdultTrainSmallIncome = TrainTemp[TrainTemp$income == "small",]
AdultTrainLargeIncome = TrainTemp[TrainTemp$income == "large",]
Oversample = sample(nrow(AdultTrainLargeIncome), nrow(AdultTrainSmallIncome), replace = TRUE)
AdultTrain = rbind(AdultTrainSmallIncome, AdultTrainLargeIncome[Oversample,])
AdultTest = ADULT[-TrainCases,]
3. 在R中进行分析
3.1 C4.5分类
3.1.1 未剪枝树
我们首先使用C4.5预测参与者的收入,先检查未剪枝树。
C45tree = J48(income ~ . , data= AdultTrain, control= Weka_control(U=TRUE))
C45tree
summary(C45tree)
Predictions = data.frame(matrix(nrow = nrow(AdultTest), ncol=0))
Predictions$C45 = predict(C45tree, AdultTest)
未剪枝树的大小为5,715,有4,683个叶子节点。训练集上约89%的案例被正确分类,kappa统计量为0.78。
3.1.2 剪枝树
C45pruned = J48(income ~ . , data= AdultTrain, control= Weka_control(U=FALSE))
summary(C45pruned)
Predictions$C45pr = predict(C45pruned, AdultTest)
剪枝树的大小为2,278,有1,767个叶子节点。剪枝后训练集的分类性能略有下降,kappa值为0.76。
3.2 C50分类
C50进行提升(boosting),我们运行一个进行10次提升的C5.0模型。
C50tree = C5.0(y = AdultTrain$income, x = AdultTrain[,-13], Trials = 10)
summary(C50tree)
TabC5.0= as.table(matrix(c(10061,1980,714,10613), byrow=T, nrow = 2))
library(psych)
cohen.kappa(TabC5.0)
Predictions$C5.0 = predict(C50tree, AdultTest)
C5.0树的大小为714,误分类率为8.4%,kappa值为0.77。
3.3 CART分类
CARTtree = rpart(income ~. , data= AdultTrain)
summary(CARTtree)
rpart.plot(CARTtree, extra = 1)
ProbsCART = predict(CARTtree, AdultTrain)
PredictCART = rep(0, nrow(ProbsCART))
PredictCART[ProbsCART[,1] <=.5] = "small"
PredictCART[ProbsCART[,1] >.5] = "large"
TabCART = table(AdultTrain$income, PredictCART)
TabCART
cohen.kappa(TabCART)
CART树比C4.5和C5.0的树更简单。该分类的准确率为81%,但kappa值较低,为0.62。
3.3.1 CART剪枝
CARTtreePruned = prune(CARTtree, cp=0.03)
rpart.plot(CARTtreePruned, extra = 1)
ProbsCARTtest = predict(CARTtreePruned, AdultTest)
Predictions$CART[ProbsCARTtest[,1] <=.5] = "small"
Predictions$CART[ProbsCARTtest[,1] >.5] = "large"
剪枝后的树更小,训练集准确率为78%,测试集准确率为81%,kappa值为0.56。
3.4 随机森林分类
RF = randomForest(y = AdultTrain$income, x = AdultTrain[,-13])
RF
Predictions$RF = predict(RF, AdultTest)
随机森林的分类效果令人失望,袋外(OOB)估计的错误率为35.79%。
3.5 测试集预测结果评估
values = data.frame(matrix(ncol = ncol(Predictions), nrow = 6))
rownames(values) = c("True +", "True -", "False +", "False -", "Accuracy", "Kappa")
names(values) = names(Predictions)
for (i in 1:ncol(Predictions)) {
tab = table(AdultTest$income,Predictions[,i])
values[1,i] = tab[1,1]
values[2,i] = tab[2,2]
values[3,i] = tab[1,2]
values[4,i] = tab[2,1]
values[5,i] = sum(diag(tab))/sum(tab)
values[6,i] = cohen.kappa(tab)[1]
}
round(values,2)
各算法在测试集上的分类准确率都超过70%,但kappa值均未超过0.56。随机森林的表现最差。
3.6 条件推理树分类
set.seed(999)
TitanicRandom = Titanic.df[sample(nrow(Titanic.df)),]
TitanicTrain = TitanicRandom[1:1100,]
TitanicTest = TitanicRandom[1101:2201,]
CItree <- ctree(Survived ~ Class + Sex + Age, data=TitanicTrain)
plot(CItree)
CIpredictTrain = predict(CItree, TitanicTrain)
CIpredictTest = predict(CItree, TitanicTest)
TabCI_Train = table(TitanicTrain$Survived,CIpredictTrain)
TabCI_Test = table(TitanicTest$Survived,CIpredictTest)
TabCI_Train
TabCI_Test
训练集和测试集上,只有约三分之一的幸存者被正确分类,kappa值分别为0.42和0.4。
3.7 Caret - 统一的分类框架
Caret包为支持的所有算法使用相似的符号,包含执行采样操作的工具,如分层采样、提升或装袋(bagging)以及交叉验证等。
4. 多层分析
4.1 嵌套数据
嵌套数据指的是观测共享一个共同的上下文,例如:
- 消费者嵌套在商店中
- 员工嵌套在经理之下
- 教师和/或学生嵌套在学校中
- 护士、患者和/或医生嵌套在医院中
- 居民嵌套在社区中
如果数据具有层次结构,传统回归分析可能会产生不可靠的结果,因为观测并非独立的,但分析假设它们是独立的。这可能导致标准误差被低估,从而产生虚假的显著结果。
4.2 相关问题
- Robinson效应 :数据聚合时属性之间的统计关系会增强。
- 原子论谬误 :从高层数据得出低层结论。
- 生态谬误 :从低层数据得出高层结论。
- Simpson悖论 :不区分组进行分析会导致不准确的结果。
4.3 示例
以下是一个生态谬误的示例:
graph LR
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
A(Attribute x) -->|Group 1| B(Attribute y)
A -->|Group 2| C(Attribute y)
A -->|Group 3| D(Attribute y)
A -->|Aggregated| E(Attribute y)
style A fill:#ffffff,stroke:#000000,stroke-width:2px;
style B fill:#ffffff,stroke:#000000,stroke-width:2px;
style C fill:#ffffff,stroke:#000000,stroke-width:2px;
style D fill:#ffffff,stroke:#000000,stroke-width:2px;
style E fill:#ffffff,stroke:#000000,stroke-width:2px;
在这个示例中,分组内Attribute x与Attribute y呈负相关,但聚合后呈正相关。
4.4 各算法测试集评估结果
| 算法 | True + | True - | False + | False - | Accuracy | Kappa |
|---|---|---|---|---|---|---|
| C45 | 9400 | 2737 | 1927 | 1017 | 0.8 | 0.52 |
| C45pr | 9352 | 2920 | 1975 | 834 | 0.81 | 0.55 |
| C5.0 | 9438 | 2949 | 1889 | 805 | 0.82 | 0.56 |
| CART | 7543 | 3338 | 3784 | 416 | 0.72 | 0.43 |
| RF | 11300 | 793 | 27 | 2961 | 0.80 | 0.28 |
5. 多层回归
5.1 多层回归概述
多层回归是处理嵌套数据的有效方法,它包括随机截距和随机斜率。随机截距允许不同组的截距不同,而随机斜率则允许不同组的斜率不同。通过多层回归,我们可以更准确地分析嵌套数据中的关系。
5.2 模型比较
在多层回归中,比较不同的模型是很重要的。我们可以通过比较模型的拟合优度、AIC(赤池信息准则)、BIC(贝叶斯信息准则)等指标来选择最优模型。例如,AIC和BIC值越小,说明模型的拟合效果越好。
5.3 预测
使用多层建模进行预测时,我们可以利用训练好的模型对新的数据进行预测。预测的准确性取决于模型的质量和数据的特征。
6. 多层模型的应用示例
假设我们有一个关于学生成绩的嵌套数据集,学生嵌套在学校中。我们可以使用多层回归来分析学校因素和学生个人因素对成绩的影响。
6.1 数据准备
首先,我们需要准备好数据,确保数据具有嵌套结构。假设我们的数据框名为 student_data ,包含学生的成绩 score 、学校编号 school_id 和其他相关变量。
6.2 构建多层模型
以下是一个简单的多层模型示例,包含随机截距:
library(lme4)
model <- lmer(score ~ student_variable + (1 | school_id), data = student_data)
summary(model)
在这个模型中, student_variable 是学生的个人变量, (1 | school_id) 表示随机截距,即不同学校的截距可以不同。
6.3 模型评估
我们可以使用 anova() 函数比较不同模型的拟合效果:
model_null <- lmer(score ~ 1 + (1 | school_id), data = student_data)
anova(model_null, model)
通过比较零模型(只包含随机截距)和完整模型,我们可以判断学生个人变量是否对成绩有显著影响。
6.4 预测
使用训练好的模型进行预测:
new_data <- student_data[1:10, ] # 选择部分数据进行预测
predictions <- predict(model, new_data)
7. 总结与建议
7.1 分类树总结
在分类树分析中,我们尝试了多种算法,包括C4.5、C50、CART、随机森林和条件推理树。各算法在测试集上的分类准确率都超过70%,但kappa值均未超过0.56,说明分类效果还有提升空间。随机森林在本次分析中的表现最差,因此在实际应用中,我们应该尝试多种算法,并选择最适合数据的算法。
7.2 多层分析总结
多层分析适用于处理嵌套数据,能够避免传统回归分析在处理层次结构数据时的问题。通过多层回归,我们可以更准确地分析不同层次因素对结果的影响。在实际应用中,我们需要注意数据的嵌套结构,选择合适的模型,并进行模型比较和评估。
7.3 建议
- 在进行分类树分析时,对数据进行预处理,如处理缺失值、平衡数据集等,可以提高模型的性能。
- 在多层分析中,仔细考虑数据的嵌套结构和模型的复杂度,避免过度拟合。
- 不断尝试不同的算法和模型,通过比较和评估选择最优方案。
7.4 各算法性能对比表格
| 算法 | 准确率 | Kappa值 | 特点 |
|---|---|---|---|
| C4.5 | 0.8 - 0.81 | 0.52 - 0.55 | 未剪枝树较大,剪枝后性能略有下降 |
| C50 | 0.82 | 0.56 | 进行提升,树较小,误分类率较低 |
| CART | 0.72 - 0.81 | 0.43 - 0.56 | 树较简单,剪枝后树更小 |
| 随机森林 | 0.80 | 0.28 | 分类效果较差,OOB错误率高 |
| 条件推理树 | - | 0.4 - 0.42 | 对幸存者分类效果不佳 |
7.5 多层分析流程mermaid图
graph LR
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
A(数据准备):::process --> B(构建多层模型):::process
B --> C(模型评估):::process
C --> D{选择最优模型}:::process
D -->|是| E(模型预测):::process
D -->|否| B
通过以上的分析和总结,我们可以更好地理解分类树和多层分析在R语言中的应用,以及如何处理不同类型的数据和选择合适的模型。在实际应用中,我们应该根据数据的特点和分析的目的,灵活运用这些方法,以获得更准确的结果。
超级会员免费看
1517

被折叠的 条评论
为什么被折叠?



