K折交叉验证

在训练模型时为了得到可靠稳定的模型,通常会通过将数据分为训练数据和测试数据,在使用训练数据训练出模型后,使用测试数据对模型进行评估,如此训练多次后,选择在测试数据上性能评估最好的模型。有时我们没有单独的测试数据来对模型进行评估。这时通常采用交叉验证的方法,常见的有K折交叉验证法、留一法(K折交叉验证法的特例)、自助法等。这里只说K折交叉验证法。所谓K折交叉验证法就是将训练数据大致均分成K份,每次选择其中一份做为测试数据,而其余的K-1份做为训练数据进行模型训练,训练出模型后再用留出的测试数据进行评估。如此重复训练K次后,选择正在测试数据上性能最好的模型做为最终的模型。

RankLib中通过-kcv等训练参数可以在训练时进行K折交叉验证。简单示例如下:

java -jar bin/RankLib-2.11.jar -train data/train.txt -ranker 6 -kcv 10 -kcvmd models/ -kcvmn mdl -metric2t NDCG@60 -metric2T ERR@10

 RankLib将data下的train.txt分为10份,采用10折交叉验证法进行训练。在训练过程中,会将每次训练出的模型保存到models目录下,分别命名为:f1.mdl、f2.mdl、...、f10.mdl。在每次训练出模型后都会用测试数据对其性能进行评估。在10次训练结束后,会打印每个模型的训练和测试的整体性能,以及所有模型性能的均值。上例中训练模型时使用的评估指标为NDCG@60,测试模型时使用的评估指标为ERR@10。注意:由于RankLib没有对参数-metric2t和-metric2T做区分,所以如果训练和测试时想要使用不同的评估指标需要对源码做修改。

数据混排

上面的K折交叉验证法在训练时是将训练数据按顺序切分成K份的。如果训练数据中的query以某种方式排序,那么按顺序切分训练数据可能引入一些偏差。可以通过训练数据的重排序来减少这种可能的偏差。

RankLib中的FeatureManager提供了数据重排序的功能。通过-shuffle选项可以简单的将数据进行重排序。

java -cp bin/RankLib.jar ciir.umass.edu.features.FeatureManager -input data/train.txt -output data/ -shuffle

 -input指定要重排序的文件路径,-output指定保存排序后的文件的目录,-shuffle表示对数据进行重排序。重排序后的文件名会为源文件名后面加上后缀“.shuffled”,如上例中生成的文件保存在data目录下,名为train.txt.shuffled。重排后就可以使用train.txt.shuffled通过K折交叉验证法训练模型。

有时为了方便可能需要将每折的数据分别进行存储。同样可以通过FeatureManager实现。

java -cp bin/RankLib.jar ciir.umass.edu.features.FeatureManager -input data/train.txt.shuffled -output data/ -k 10

如上将混排后的train.txt.shuffled文件按10折进行分区后保存到data目录下。

分区后的文件格式为: "f"+折数+“.train.”/“.test.”/“.validation.”+文件名。如:

f1.train.train.txt.shuffled
f1.test.train.txt.shuffled

f2.train.train.txt.shuffled
f2.test.train.txt.shuffled

通常每折只包含train(训练数据)和test(测试数据)两种文件。如果想要获得验证数据,则可再上例中再添加-tvs选项来从每折的训练数据中再分出一部分数据作为验证数据。

如果既要重排数据,又想保存每折的数据,可以将两个功能的参数合并:

java -cp bin/RankLib.jar ciir.umass.edu.features.FeatureManager -input data/train.txt -output data/ -k 10 -shuffle

FeatureManager会先将数据混排然后再分区。最终得到的文件与两步分开执行的结果相同。

使用FeatureManager进行分区与RankLib训练时进行分区的效果完全相同,都是按顺序分区。