我在Java代码中使用了Weka的LibSVM进行回归。以下是我的代码,
public static void predict() { try { DataSource sourcePref1 = new DataSource("train_pref2new.arff"); Instances trainData = sourcePref1.getDataSet(); DataSource sourcePref2 = new DataSource("testDatanew.arff"); Instances testData = sourcePref2.getDataSet(); if (trainData.classIndex() == -1) { trainData.setClassIndex(trainData.numAttributes() - 2); } if (testData.classIndex() == -1) { testData.setClassIndex(testData.numAttributes() - 2); } LibSVM svm1 = new LibSVM(); String options = ("-S 3 -K 2 -D 3 -G 1000.0 -R 0.0 -N 0.5 -M 40.0 -C 1.0 -E 0.001 -P 0.1"); String[] optionsArray = options.split(" "); svm1.setOptions(optionsArray); svm1.buildClassifier(trainData); for (int i = 0; i < testData.numInstances(); i++) { double pref1 = svm1.classifyInstance(testData.instance(i)); System.out.println("predicted value : " + pref1); } } catch (Exception ex) { Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex); }}
但是我从这个代码中得到的预测值与使用Weka GUI得到的预测值不同。
示例: 以下是我为Java代码和Weka GUI提供的单个测试数据。
Java代码预测的值为 1.9064516129032265,而Weka GUI的预测值为 10.043。我对Java代码和Weka GUI使用了相同的训练数据集和相同的参数。
希望您能理解我的问题。能否有人告诉我我的代码哪里出了问题?
回答:
您使用了错误的算法来进行SVM回归。LibSVM用于分类。您需要使用的是SMOreg,这是一个专门用于回归的SVM算法。
以下是一个完整的示例,展示了如何使用SMOreg,通过Weka Explorer GUI以及Java API。对于数据,我将使用Weka分发附带的cpu.arff
数据文件。请注意,我将使用此文件进行训练和测试,但理想情况下,您应该有单独的数据集。
使用Weka Explorer GUI
- 打开Weka Explorer GUI,点击
Preprocess
选项卡,点击Open File
,然后打开Weka分发中应该有的cpu.arff
文件。在我的系统中,文件位于weka-3-8-1/data/cpu.arff
。Explorer窗口应该看起来如下所示:
- 点击
Classify
选项卡。实际上它应该被称为“预测”,因为您可以在这里进行分类和回归。在Classifier
下,点击Choose
,然后选择weka
–>classifiers
–>functions
–>SMOreg
,如下所示。
- 现在构建回归模型并评估它。在
Test Options
下选择Use training set
,这样训练集也用于测试(如上所述,这不是理想的方法)。现在按Start
,结果应该如下所示:
请注意RMSE值(74.5996)。我们将在Java代码实现中重新审视这个值。