我对Weka的使用还比较新手,尤其是对命令行下的Weka使用更是如此。我发现文档资料很少,我在尝试弄清楚一些操作时遇到了困难。例如,我想使用两个.arff文件,一个用于训练,一个用于测试,并获取测试数据中缺失标签的预测输出。
我该怎么做呢?
我有以下代码作为起点
java -classpath weka.jar weka.classifiers.meta.FilteredClassifier-t "training_file_with_missing_values.arff"-T "test_file_with_missing_values.arff"-F weka.filters.unsupervised.attribute.ReplaceMissingValues -- -c last-W weka.classifiers.functions.MultilayerPerceptron -- -L 0.3 -M 0.2 -H a
运行这段代码时,我得到了“非法选项 -c last”的错误提示,我不确定这是为什么。我也不打算使用MLP,因为当我有几千个来自文本数据的特征时,神经网络往往会太慢。不过我知道如何将其更改为其他分类器(如NB或libSVM,这很好)。
但我不确定如何在一个调用中添加多个过滤器,因为我还需要添加StringToWordVector过滤器(可能还需要添加Reorder过滤器,将类别调整到最后,而不是第一个属性)。
然后,我该如何实际输出每个类的预测标签?然后如何将这些标签存储在一个包含初始数据的arff文件中?
回答:
Weka的文档并不是特别出色,但你仍然可以在他们的网站上找到有价值的信息。你应该从入门指南开始。我理解你想对文本文件进行分类,所以你也应该看看使用Weka进行文本分类。还有一个新的Weka文档网站。
[编辑:Wikispaces已经关闭,Weka还没有在其他地方重新建立这些网站,所以我已经修改了链接,指向Google缓存。如果有人看到这个,并且新的Weka Wiki已经上线,请随意编辑链接并删除此说明。]
你在问题中发布的命令行包含了一个错误。我知道,你是从我对另一个问题的回答中复制过来的,但我刚刚也注意到了。你必须省略-- -c last
,因为ReplaceMissingValue
过滤器不喜欢它。
在入门指南中提到:
weka.filters.supervised
类层次结构中weka.filters.supervised下的类用于监督过滤,即利用类信息。必须通过-c指定一个类,对于Weka的默认行为使用
-c last
。
但ReplaceMissingValue
是一个无监督过滤器,StringToWordVector
也是如此。
多个过滤器
添加多个过滤器也没有问题,这就是MultiFilter
的用途所在。不过,命令行可能会变得有点混乱:(我在这里选择了RandomForest
,因为它比神经网络快得多)。
java -classpath weka.jar weka.classifiers.meta.FilteredClassifier \ -t ~/weka-3-7-9/data/ReutersCorn-train.arff \ -T ~/weka-3-7-9/data/ReutersCorn-test.arff \ -F "weka.filters.MultiFilter \ -F weka.filters.unsupervised.attribute.StringToWordVector \ -F weka.filters.unsupervised.attribute.Standardize" \ -W weka.classifiers.trees.RandomForest -- -I 100 \
进行预测
关于获取预测,入门指南中是这样说的:
然而,如果需要关于分类器预测的更详细信息,-p # 会输出每个测试实例的预测,以及一系列基于1的属性ID(0表示无)。
将这些通用选项如-p 0
直接放在你调用的类之后是一个好习惯,所以命令行应该是
java -classpath weka.jar weka.classifiers.meta.FilteredClassifier \ -t ~/weka-3-7-9/data/ReutersCorn-train.arff \ -T ~/weka-3-7-9/data/ReutersCorn-test.arff \ -p 0 \ -F "weka.filters.MultiFilter \ -F weka.filters.unsupervised.attribute.StringToWordVector \ -F weka.filters.unsupervised.attribute.Standardize" \ -W weka.classifiers.trees.RandomForest -- -I 100 \
Weka分类器/过滤器的结构
但正如你所见,从命令行调用Weka时可能会变得非常复杂。这是由于Weka分类器和过滤器的树状结构。虽然你每次只能运行一个分类器/过滤器,但可以根据需要构建复杂的结构。对于上面的命令,其结构如下所示:
FilteredClassifier将在训练数据集上初始化一个过滤器,过滤训练和测试数据,然后在训练数据上训练模型并对给定的测试数据进行分类。
FilteredClassifier | + Filter | + Classifier
如果我们想要多个过滤器,我们使用MultiFilter,它只是一个过滤器,但它会按给定的顺序调用多个其他过滤器。
FilteredClassifier | + MultiFilter | | | + StringToWordVector | | | + Standardize | + RandomForest
从命令行运行这样的操作的难点在于将所需的选项分配给正确的类,因为选项名称通常是相同的。例如,-F
选项用于FilteredClassifier
和MultiFilter
,所以我必须使用引号来明确哪个-F属于哪个过滤器。
在最后一行,你会看到属于RandomForest
的选项-I 100
不能直接附加,因为这样它会被分配给FilteredClassifier
,你会得到非法选项:-I 100
的错误。因此,你必须在它之前添加--
。
将预测添加到数据文件中
添加预测的类别标签也是可能的,但更加复杂。据我所知,这不能一步完成,你必须先训练并保存一个模型,然后使用这个模型进行预测并分配新的类别标签。
训练并保存模型:
java -classpath weka.jar weka.classifiers.meta.FilteredClassifier \ -t ~/weka-3-7-9/data/ReutersCorn-train.arff \ -d rf.model \ -F "weka.filters.MultiFilter \ -F weka.filters.unsupervised.attribute.StringToWordVector \ -F weka.filters.unsupervised.attribute.Standardize" \ -W weka.classifiers.trees.RandomForest -- -I 100 \
这将把训练好的FilteredClassifier
模型序列化到文件rf.model
中。这里重要的是,初始化的过滤器也会被序列化,否则过滤后的测试集将不兼容。
加载模型,进行预测并保存:
java -classpath weka.jar weka.filters.supervised.attribute.AddClassification \ -serialized rf.model \ -classification \ -remove-old-class \ -i ~/weka-3-7-9/data/ReutersCorn-test.arff \ -o pred.arff \ -c last