数据建模中的交叉验证、自助法与模型导出
1. 自助法(Bootstrapping)
自助法的目标是更精确地评估模型在数据上的可靠性。与将数据划分为训练集和测试集不同,自助法是从原始数据集中有放回地随机抽取 n 个样本,重复 N 次(N 为迭代次数,n 为样本数量)。每次抽取的样本都独立进行分析,从而得到估计值的均值和标准差。
在 R 语言中使用 caret 包进行自助法的操作如下:
CtrlBoot = trainControl(method="boot", number=1000)
# 以下是不同算法的示例
# Naive Bayes
modelNBboot = train(Species ~ ., data = iris,
trControl = CtrlBoot, method = "nb")
# C4.5
modelC45boot = train(Species ~ ., data = iris,
trControl = CtrlBoot, method = "J48")
# C5.0
modelC50boot = train(Species ~ ., data = iris,
trControl = CtrlBoot, method = "C5.0")
# CART
modelCARTboot = train(Species ~ ., data = iris,
trControl = CtrlBoot, method = "rpart")
# 随机森林
modelRFboot = train(Species ~ ., data = iris,
trControl = CtrlBoot, method = "rf")
2. 预测新数据
构建预测模型的目的是对未知数据进行预测。可以通过以下步骤实现:
1. 使用分层抽样将数据划分为两个集合,75% 用于交叉验证的训练和测试,25% 作为未知数据。
forCV = createDataPartition(iris$Species, p=0.75, list=FALSE)
CVset = iris[forCV,]
NEWset = iris[-forCV,]
- 创建交叉验证模型(以朴素贝叶斯为例)。
model = train(Species ~ ., data = CVset, trControl = CtrlCV,
method = "nb")
- 使用该模型预测未知数据。
Predictions = predict(model, NEWset)
3. 使用 PMML 导出模型
3.1 什么是 PMML
PMML(Predictive Model Markup Language)是一种跨软件共享预测模型的标准。自 1997 年以来,数据挖掘组一直在开发和改进该标准。使用 PMML,用户可以在一个软件包中构建模型,并在另一个软件包中进行预测。目前,许多软件都支持使用 PMML 进行模型的导出和导入,包括 R、Rapidminer、SAS Enterprise Miner、SPSS Modeler 和 Weka 等。
支持 PMML 的算法如下表所示:
| 算法 | 函数 | 包 |
| — | — | — |
| K - 均值聚类 | kmeans | (stats) |
| 层次聚类 | hclust | (stats) |
| 关联规则挖掘 | apriori | arules |
| 线性回归 | lm | (stats) |
| 朴素贝叶斯分类与回归 | naiveBayes | e1071 |
| 分类与回归树 | rpart | rpart |
| 随机森林分类与回归 | randomForest | randomForest |
| 逻辑回归 | glm | (stats) |
| 支持向量机分类 | svm | e1071 |
3.2 PMML 对象结构简介
PMML 对象使用 XML 生成。以下是一个简单线性回归模型的 PMML 转换示例:
install.packages("pmml"); library(pmml)
model = lm (Sepal.Length ~ Sepal.Width, data = iris)
model
# 生成 PMML 代码
pmml(model)
生成的 PMML 代码结构如下:
<PMML version="4.2" xmlns="http://www.dmg.org/PMML-4_2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.dmg.org/PMML-4_2
http://www.dmg.org/v4-2/pmml-4-2.xsd">
<Header copyright="Copyright (c) 2015 mayore" description="Linear
Regression Model">
<Extension name="user" value="mayore" extender="Rattle/PMML"/>
<Application name="Rattle/PMML" version="1.4"/>
<Timestamp>2015-02-18 13:36:46</Timestamp>
</Header>
<DataDictionary numberOfFields="2">
<DataField name="Sepal.Length" optype="continuous" dataType="double"/>
<DataField name="Sepal.Width" optype="continuous" dataType="double"/>
</DataDictionary>
<RegressionModel modelName="Linear_Regression_Model"
functionName="regression" algorithmName="least squares">
<MiningSchema>
<MiningField name="Sepal.Length" usageType="predicted"/><MiningField
name="Sepal.Width" usageType="active"/>
</MiningSchema>
<Output>
<OutputField name="Predicted_Sepal.Length" feature="predictedValue"/>
</Output>
<RegressionTable intercept="6.52622255089448">
<NumericPredictor name="Sepal.Width" exponent="1"
coefficient="-0.2233610611299"/>
</RegressionTable>
</RegressionModel>
</PMML>
3.3 预测模型导出示例
- 导出 K - 均值对象
iris.kmeans = kmeans(iris[1:4],3)
pmml_kmeans = pmml(iris.kmeans)
saveXML(pmml_kmeans, data=iris, "iris_kmeans.PMML")
- 层次聚类
DF = cbind(c(rep(1,4),rep(2,4),rep(3,4),rep(4,4)), rep(c(1,2,3,4),4),
rep(c(rep(1,2),rep(2,2),rep(3,2),rep(4,2)),2))
DF.hclust = hclust(dist(DF))
plot(DF.hclust)
Cut = cutree(DF.hclust, k = 2)
centroids = aggregate(DF, list(Cut), mean)
pmml_hclust = pmml(DF.hclust, centers = centroids)
saveXML(pmml_hclust, data=DF, "DF_hclust.PMML")
- 导出关联规则(apriori 对象)
library(arules)
data(Adult,AdultUCI)
Adult.Apriori = apriori(Adult)
saveXML(pmml(Adult.Apriori), "Adult_Apriori.PMML")
- 导出朴素贝叶斯对象
library(e1071)
iris.NaiveBayes = naiveBayes(Species ~ Sepal.Length + Sepal.Width +
Petal.Length + Petal.Width, data = iris)
saveXML(pmml(iris.NaiveBayes,dataset = iris, predictedField =
"Species"), "iris_NaiveBayes.pmml")
- 导出决策树(rpart 对象)
iris.rpart = rpart(Species ~ Sepal.Length + Sepal.Width +
Petal.Length + Petal.Width, data = iris)
saveXML(pmml(iris.rpart), data = iris, "iris_rpart.pmml")
- 导出随机森林对象
library(randomForest)
iris.RandomForest = randomForest(Species ~ Sepal.Length + Sepal.Width
+ Petal.Length + Petal.Width, data = iris)
saveXML(pmml(iris.RandomForest), data = iris,
"iris_randomForest.pmml")
- 导出逻辑回归对象
set.seed(1234)
y = c(rep(0,50),rep(1,50))
x = rnorm(100)
x[51:100] = x[51:100] + 0.2
glm.model = glm(y ~ x, family = "binomial")
saveXML(pmml(glm.model), "glm_model.PMML")
- 导出支持向量机对象
iris.svm = svm(Species ~ Sepal.Length + Sepal.Width + Petal.Length +
Petal.Width, data = iris)
saveXML(pmml(iris.svm), "iris_svm.PMML")
4. 练习题
以下是一些练习题,帮助巩固所学知识:
1.
数据可视化与操作
:想象一个玩家连续 1000 次押注红色,使用数据框 Data 的 isRed 属性,玩家初始资金为 1000 美元,每次押注 1 美元。绘制游戏过程中资金的变化图,判断玩家最终是赢还是输。
2.
数据可视化(Lattice)
:绘制 iris 数据集中 Petal.Length 和 Petal.Width 的关系图,并包含回归直线。
3.
聚类分析
:使用不同的距离度量(欧几里得距离、最大距离、曼哈顿距离),确定 iris 数据集(不包括 Species 属性)的最佳聚类数。
4.
层次聚类
:使用 hclust() 对 iris 数据集(不包括 Species 属性)进行聚类,使用不同的距离计算方法和链接选项。
5.
主成分分析
:对 bfi 数据集中的 25 个项目进行分析,包括检查缺失值、进行诊断、运行 PCA、确定保留的成分数、重新运行分析并保存得分、计算累积方差比例、命名成分以及分析成分与年龄的相关性。
6.
关联规则挖掘
:使用 ICU 数据集(不包括 race 属性),获取支持度为 0.1、置信度为 0.8、最小长度为 2 且前件为 pco=<=45 的关联规则,将规则对象转换为数据框,添加 Fisher 精确检验的显著性值,并可视化提升度与显著性的关系。
7.
概率分布、协方差和相关性
:计算欧洲轮盘赌中出现 40 - 49 次和 51 - 60 次红色数字的概率,计算 iris 数据集中花瓣长度和宽度的相关性。
8.
线性回归
:使用 nurses 数据集,分析工作 - 家庭冲突(WFC)对工作满意度(WorkSat)的影响,包括创建不同的模型、检查关系变化、进行 Sobel 检验。
9.
K - 近邻和朴素贝叶斯分类
:使用 knn() 对 Ozone 数据集进行分类,确定最佳邻居数,并评估分类的可靠性。
10.
分类树
:使用 C4.5 和 CART 对 iris 数据集进行分类,比较测试集上的准确率,并创建评估准确率的函数。
11.
多层次分析
:使用 NursesML 数据集,可视化不同医院中疲惫感、去个性化与工作满意度的关系,确定预测值增加 1 时工作满意度的差异以及模型的截距。
12.
文本分析
:找出 tm 包中 50 篇新闻文章语料库在预处理前后出现次数超过 100 次的术语,并绘制预处理后词频大于 10 的排序词频图。
5. 练习题解决方案
- 数据可视化与操作
money = rep(0,1001)
money[1] = 1000
wins = Data$isRed
for (i in 1:nrow(Data)) {
if (wins[i] == 1) money[i+1] = money[i] + 1
else money[i+1] = money[i] - 1
}
par (mfrow = c(1,1), pin=c(5,2))
plot(money, type = "l", xlab = "Trial number")
- 数据可视化(Lattice)
library(lattice)
xyplot(Petal.Length ~ Petal.Width | Species, data = iris,
panel = function(x, y, ...) {
panel.xyplot(x,y)
panel.abline(lm(y~x))
}
)
- 聚类分析
library(NbClust)
NbClust(iris[1:4],distance="euclidean", method= "kmeans")
NbClust(iris[1:4],distance="manhattan", method= "kmeans")
NbClust(iris[1:4],distance="maximum", method= "kmeans")
- 层次聚类
dist.types = c("euclidean", "maximum", "manhattan", "canberra",
"binary", "minkowski")
d = list(dist(iris[1:4], method = dist.types[1]))
for (i in 2:length(dist.types)) d = c(d,list(dist(iris[1:4],
method = dist.types[i])))
agglo.types = c("ward.D", "ward.D2", "single", "complete",
"average", "mcquitty", "median", "centroid")
M = array(list(), 8)
for (i in 1:length(agglo.types)) {
OneDList = list(hclust(d[[1]], method = agglo.types[i]))
for (j in 2:length(dist.types)) OneDList =
c(OneDList, list(hclust(d[[j]], method = agglo.types[i])))
M[[i]] = OneDList
}
plot(M[[4]][[1]])
- 主成分分析
library(psych)
summary(bfi[,1:25])
Dat = na.omit(bfi[,1:25])
dim(bfi)[1] - dim(Dat)[1]
cortest.normal(Dat)
KMO(Dat)
pcas = princomp(Dat)
plot(pcas$sd^2)
pcas2 = principal(Dat,nfactors=5, rotate="varimax", scores=T)
Dat = cbind(Dat, pcas2$scores)
pcas2
- 关联规则挖掘
library(vcdExtra)
ICU_norace = ICU[-4]
library(arules)
ICU_norace$age = cut(ICU_norace$age, breaks = 4)
ICU_norace$systolic = cut(ICU_norace$systolic, breaks = 4)
ICU_norace$hrtrate = cut(ICU_norace$hrtrate, breaks = 4)
ICU_norace_tr = as(ICU_norace, "transactions")
rulesLowpco = apriori(ICU_norace_tr, parameter =
list(confidence = 0.8, support=.1, minlen = 2),
appearance = list(lhs = c("pco=<=45"), default="rhs"))
rulesLowpco.df = as(rulesLowpco,"data.frame")
IM = interestMeasure(rulesLowpco, "fishersExactTest",
ICU_norace_tr)
rulesLowpco.df$IM= round(IM, digits = 2)
plot (rulesLowpco.df$lift, rulesLowpco.df$IM, xlab = "lift",
ylab = "Significance")
- 概率分布、协方差和相关性
p = 18/37
N = 100
n = 1
v40_49 = rep(1,10)
v51_60 = v40_49
i=1
for (n in 40:49) {
v40_49[i] = choose(N, n) * (p^n) * (1 - p)^(N-n)
i = i + 1
}
i=1
for (n in 51:60) {
v51_60[i] = choose(N, n) * (p^n) * (1 - p)^(N-n)
i = i + 1
}
sum(v40_49)
sum(v51_60)
cor.test(iris$Petal.Width,iris$Petal.Length)
- 线性回归
model01 = lm(WorkSat ~ WFC, data = nurses)
model02 = lm(WorkSat ~ WFC + Exhaus, data = nurses)
summary(model01)
summary(model02)
model03 = lm(Exhaus ~ WFC, data = nurses)
summary(model03)
library(bda)
mediation.test(nurses$Exhaus, nurses$WFC, nurses$WorkSat)
- K - 近邻和朴素贝叶斯分类
library(psych); library(class)
kappas = rep(0,9)
for (i in 1:9) {
set.seed(2222)
pred.train = knn(train = TRAIN[,2:13], test = TRAIN[,2:13],
cl = TRAIN$season, k = i+1)
tab = table(pred.train,TRAIN[,14])
kappas[i] = cohen.kappa(tab)[1]
}
which.max(kappas)
pred.test = knn(train = TRAIN[,2:13], test = TEST[,2:13],
cl = TRAIN$season, k = 2)
cohen.kappa(table(pred.test,TEST[,14]))[1]
- 分类树
library(RWeka)
IRIS.C45 = J48(Species~ . , data= IRIStrain,
control= Weka_control(U=FALSE))
C45.preds = predict(IRIS.C45, IRIStest)
library(rpart)
IRIS.CART = rpart(Species ~. , data= IRIStrain)
CART.probs = as.data.frame(predict(IRIS.CART, IRIStest))
CART.preds = apply(CART.probs, 1, which.max)
for (i in 1:length(CART.preds)) {
col= as.numeric(CART.preds[i])
CART.preds[i] = names(CART.probs[col])
}
CONF.C45 = table(IRIStest$Species, C45.preds)
CONF.CART = table(IRIStest$Species, CART.preds)
acc = function(table) {
sum(diag(dim(table)[1])*table) / sum(CONF.C45)
}
acc(CONF.C45)
acc(CONF.CART)
- 多层次分析
library(lattice)
attach(NursesML)
xyplot(WorkSat~Exhaust | as.factor(hosp), panel = function(x,y) {
panel.xyplot(x,y)
panel.lmline(x,y)
})
xyplot(WorkSat~Depers | as.factor(hosp), panel = function(x,y) {
panel.xyplot(x,y)
panel.lmline(x,y)
})
coeffs(modelPred)
- 文本分析
DTM = as.matrix(DocumentTermMatrix(acq))
FR = colSums(DTM)
FR[FR>100]
acq2 = preprocess(acq)
DTM2 = as.matrix(DocumentTermMatrix(acq2))
FR2 = colSums(DTM2)
FR2[FR2>100]
barplot(sort(FR2[FR2>30]), names.arg = rownames(sort(FR2[FR2>30])))
通过以上内容,我们学习了自助法、交叉验证、使用 PMML 导出模型的方法,并通过练习题和解决方案巩固了相关知识。这些技术和方法在数据建模和分析中具有重要的应用价值。
数据建模中的交叉验证、自助法与模型导出
6. 方法总结与对比
在前面的内容中,我们介绍了自助法、交叉验证以及使用 PMML 导出模型等多种方法。下面对这些方法进行总结和对比,以便更好地理解它们的特点和适用场景。
| 方法 | 目的 | 操作步骤 | 适用场景 |
|---|---|---|---|
| 自助法 | 更精确地评估模型在数据上的可靠性 | 从原始数据集中有放回地随机抽取 n 个样本,重复 N 次,每次抽取的样本独立进行分析 | 当需要对模型的可靠性进行更精确的估计时使用 |
| 交叉验证 | 评估模型的泛化能力 | 将数据划分为训练集和测试集,多次重复划分和训练测试过程,取平均结果 | 用于评估模型在不同数据集上的表现,选择最优模型 |
| PMML 导出模型 | 跨软件共享预测模型 | 将模型作为参数传递给 pmml() 函数生成 PMML 代码,保存为 XML 文件 | 需要在不同软件之间共享模型时使用 |
7. 流程梳理
为了更清晰地展示这些方法的使用流程,下面使用 mermaid 格式的流程图进行梳理。
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px;
A([开始]):::startend --> B{选择方法}:::decision
B -->|自助法| C(设置参数,进行抽样和分析):::process
B -->|交叉验证| D(划分数据集,训练和测试模型):::process
B -->|PMML 导出模型| E(生成 PMML 代码,保存为 XML 文件):::process
C --> F(评估模型可靠性):::process
D --> G(评估模型泛化能力):::process
E --> H(在其他软件中使用模型):::process
F --> I([结束]):::startend
G --> I
H --> I
8. 深入理解与拓展
8.1 自助法的原理和优势
自助法的核心思想是通过有放回的抽样来模拟从总体中多次抽样的过程。这种方法可以在不增加数据量的情况下,通过多次抽样得到多个样本,从而更全面地评估模型的可靠性。自助法的优势在于它可以处理各种类型的数据,并且不需要对数据的分布做出假设。
8.2 交叉验证的不同方式
交叉验证有多种方式,如 k - 折交叉验证、留一交叉验证等。k - 折交叉验证将数据划分为 k 个子集,每次选择一个子集作为测试集,其余子集作为训练集,重复 k 次。留一交叉验证则是每次只留下一个样本作为测试集,其余样本作为训练集,重复 n 次(n 为样本数量)。不同的交叉验证方式适用于不同的数据集和问题,需要根据具体情况进行选择。
8.3 PMML 的应用场景和发展趋势
PMML 作为一种跨软件共享预测模型的标准,具有广泛的应用场景。它可以方便地在不同的软件之间共享模型,提高模型的复用性和可移植性。随着数据挖掘和机器学习的发展,PMML 的应用也越来越广泛,未来可能会在更多的领域得到应用。
9. 注意事项和常见问题
在使用这些方法时,需要注意以下几点:
1.
数据预处理
:在进行自助法、交叉验证或模型导出之前,需要对数据进行预处理,包括缺失值处理、异常值处理、特征选择等。
2.
参数选择
:不同的方法有不同的参数需要选择,如自助法的抽样次数、交叉验证的折数等。参数的选择会影响方法的效果,需要根据具体情况进行调整。
3.
模型评估指标
:在评估模型时,需要选择合适的评估指标,如准确率、召回率、F1 值等。不同的评估指标适用于不同的问题,需要根据具体情况进行选择。
常见问题及解决方法如下:
| 问题 | 解决方法 |
| — | — |
| 自助法抽样结果不稳定 | 增加抽样次数,或者使用更稳定的抽样方法 |
| 交叉验证结果差异较大 | 检查数据的分布情况,调整折数或使用其他交叉验证方式 |
| PMML 导出的模型在其他软件中无法使用 | 检查 PMML 代码的格式是否正确,确保其他软件支持 PMML 标准 |
10. 总结与展望
通过本文的介绍,我们学习了自助法、交叉验证和使用 PMML 导出模型的方法,了解了它们的原理、操作步骤、适用场景以及注意事项。这些方法在数据建模和分析中具有重要的应用价值,可以帮助我们更准确地评估模型的性能,提高模型的泛化能力,实现模型的跨软件共享。
未来,随着数据挖掘和机器学习技术的不断发展,这些方法也将不断完善和创新。例如,自助法可能会与深度学习相结合,提高模型的训练效率和可靠性;交叉验证可能会采用更智能的方式进行数据集的划分,提高评估的准确性;PMML 可能会支持更多的算法和模型类型,进一步拓展其应用范围。
希望本文能够帮助读者更好地理解和应用这些方法,在实际的数据建模和分析中取得更好的效果。
超级会员免费看
908

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



