交叉验证(
Cross-validation),也叫循环估计(
Rotation estimation)是评价学习算法好坏的一个验证手段。他的主要思路如下所示,以运用最广泛的
十折交叉验证 为例(当然, 2 折、5 折交叉验证也比较流行),
------------------
大概过程:首先,将总体样本随机打散;其次,将总体样本 Training set 平均分成 10 等份(即形成 10 折);然后,进入迭代,在每一次迭代中,都将其中的 1 份(第 i 个)作为测试集,其余 9 等分(9 折)作为训练集,这样一来,就可以建立起 10 个学习模型,也即图中的 E1,E2,E3,..., E10;最后,将这个 10 个模型的结果求均值,作为最后交叉验证的结果。
注意:
k-折交叉 运算的一些特例,比如说留一法(Leave-one-out)就是个数为m的样本集,令k=m,这样一来,每次就相当于取一个样本来做测试,其余样本做训练。
那么在WEKA中,我们第六讲,简单说明了一下 十折交叉验证的代码,利用随机森林 rf 来对样本集 trains 进行是折交叉运算。
RandomForest rf =
new
RandomForest();
rf.buildClassifier(trains);
Evaluation eval = new Evaluation(trains);
eval.crossValidateModel(rf, trains, 10, new Random(1)); // 第四个参数,指的是打散数据集的随机值
rf.buildClassifier(trains);
Evaluation eval = new Evaluation(trains);
eval.crossValidateModel(rf, trains, 10, new Random(1)); // 第四个参数,指的是打散数据集的随机值
一般来讲,这样就可以达到我们的要求,我们继续调用
eval.correst(),或
eval.precision() 等,就可以得到交叉运算的结果。但是今天更近一步,探究一下 WEKA 内部是如何按照交叉运算的大概过程来实现的呢,以下代码可能有助于我们理解其中过程,
trains.randomize(new Random(1));
// 首先,随机打散样本集trains
trains.stratify(10); // 其次,将其分成10等分
RandomForest rf = new RandomForest();
for( int i=0; i<10; i++){ // 然后,进入迭代模块
Instances dataTR = trains.trainCV(10, i); // 取出除第i份外的样本作为训练集
Instances dataTT = trains.testCV(10, i); // 取出第i分样本作为测试集
rf.buildClassifier(dataTR);
Evaluation eval = new Evaluation(dataTR);
eval.evaluateModel(rf, dataTT); // 预测测试集
}
trains.stratify(10); // 其次,将其分成10等分
RandomForest rf = new RandomForest();
for( int i=0; i<10; i++){ // 然后,进入迭代模块
Instances dataTR = trains.trainCV(10, i); // 取出除第i份外的样本作为训练集
Instances dataTT = trains.testCV(10, i); // 取出第i分样本作为测试集
rf.buildClassifier(dataTR);
Evaluation eval = new Evaluation(dataTR);
eval.evaluateModel(rf, dataTT); // 预测测试集
}
之后,我们再次统计出每一折的计算结果,求取平均值,即可得到最后的交叉运算综合结果。下图展示了我统计10折交叉运算的precision,recall,fMeasure,和accuracy的结果(正负2类)。
注意:WEKA中的 10 折交叉验证结果,并不是根据前 10 次求平均值而得到的。根据推算,WEKA 是根据总的混淆矩阵(即Confusion Matrix,CM)得到的,具体的过程,可以参考我在 StackOverflow 上的提问,
问题网址
[1] 百度百科.
交叉验证,2015.