### 使用Weka训练和Java训练的结果差异

我正在尝试使用Weka的Java API创建一个“自动训练”,但我觉得我做错了什么。每当我通过Weka的界面使用MultiLayerPerceptron进行10折交叉验证或66%的百分比分割测试我的ARFF文件时,我会得到一些满意的结果(约90%),但当我通过Weka的API测试同一文件时,每次测试都基本返回0%的匹配度(每一行都返回false)。

这是Weka GUI的输出:

=== 测试分割的评估 ====== 摘要 ===

正确分类的实例          78               91.7647 %错误分类的实例         7                8.2353 %Kappa统计量                          0.8081平均绝对误差                      0.0817均方根误差                  0.24  相对绝对误差                 17.742  %根相对平方误差             51.0603 %总实例数               85     

=== 按类别详细准确度 ===

                真正率   假正率   精确度   召回率  F-Measure   ROC面积  类别                 0.885     0.068      0.852     0.885     0.868      0.958    1                 0.932     0.115      0.948     0.932     0.94       0.958    0加权平均    0.918     0.101      0.919     0.918     0.918      0.958

=== 混淆矩阵 ===

  a  b   <-- 分类为 23  3 |  a = 1  4 55 |  b = 0

这是我在Java中使用的代码(实际上是在.NET中使用IKVM):

var classifier = new weka.classifiers.functions.MultilayerPerceptron();classifier.setOptions(weka.core.Utils.splitOptions("-L 0.7 -M 0.3 -N 75 -V 0 -S 0 -E 20 -H a")); //这些是测试在Weka GUI下运行时的相同选项(默认选项)string trainingFile = Properties.Settings.Default.WekaTrainingFile; //使用与Weka浏览器测试相同的文件路径weka.core.Instances data = null;data = new weka.core.Instances(new java.io.BufferedReader(new java.io.FileReader(trainingFile))); //加载文件data.setClassIndex(data.numAttributes() - 1); //将最后一列设置为类别属性cl.buildClassifier(data);var tmp = System.IO.Path.GetTempFileName(); //创建一个临时文件,用于创建一个包含我想要测试的实例的单行ARFF文件,该实例取自之前加载的ARFF文件using (var f = System.IO.File.CreateText(tmp)){    //长代码从数据库读取数据并重新生成行,模拟来自我真正想要测试的源的数据}var dataToTest = new weka.core.Instances(new java.io.BufferedReader(new java.io.FileReader(tmp)));dataToTest.setClassIndex(dataToTest.numAttributes() - 1);double prediction = 0;for (int i = 0; i < dataToTest.numInstances(); i++){    weka.core.Instance curr = dataToTest.instance(i);    weka.core.Instance inst = new weka.core.Instance(data.numAttributes());    inst.setDataset(data);    for (int n = 0; n < data.numAttributes(); n++)    {        weka.core.Attribute att = dataToTest.attribute(data.attribute(n).name());        if (att != null)        {            if (att.isNominal())            {                if ((data.attribute(n).numValues() > 0) && (att.numValues() > 0))                {                    String label = curr.stringValue(att);                    int index = data.attribute(n).indexOfValue(label);                    if (index != -1)                        inst.setValue(n, index);                }            }            else if (att.isNumeric())            {                inst.setValue(n, curr.value(att));            }            else            {                throw new InvalidOperationException("未处理的属性类型!");            }        }    }    prediction += cl.classifyInstance(inst);}//预测在这里总是0,我的ARFF文件有两个类别:0和1,92个零和159个一

有趣的是,如果我将分类器更改为NaiveBayes,结果与通过Weka GUI进行的测试相匹配


回答:

您使用的是读取ARFF文件的过时方法。请参阅此文档。尝试使用以下方法:

 import weka.core.converters.ConverterUtils.DataSource; ... DataSource source = new DataSource("/some/where/data.arff"); Instances data = source.getDataSet();

请注意,该文档还展示了如何直接连接到数据库,并绕过创建临时ARFF文件。您还可以从数据库读取数据,并手动创建实例来填充Instances对象。

最后,如果简单地将代码顶部的分类器类型更改为NaiveBayes就解决了问题,那么请检查Weka GUI中MultilayerPerceptron的选项,看看它们是否与默认值不同(不同的设置可能会导致同一种分类器类型产生不同的结果)。

更新:看起来您在代码中使用的数据与Weka GUI中使用的数据不同(来自数据库与原始训练文件的一个折叠);也可能是数据库中的特定数据实际上对MLP分类器看起来像是class 0。为了验证是否是这种情况,您可以使用Weka界面将训练ARFF文件分割成训练/测试集,然后在您的代码中重复原始实验。如果结果与GUI相同,那么数据有问题。如果结果不同,那么我们需要更仔细地查看代码。您将调用的函数是这个(来自文档)

public Instances trainCV(int numFolds, int numFold)

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注