您使用了错误的算法来执行 SVM 回归。 LibSVM 用于分类。你想要的是SMOreg,它是一个特定的回归支持向量机。
下面是一个完整的示例,展示了如何通过 Weka Explorer GUI 和 Java API 使用 SMOreg。对于数据,我将使用 Weka 发行版附带的 cpu.arff 数据文件。请注意,我会将此文件用于训练和测试,但理想情况下,您应该拥有单独的数据集。
使用 Weka Explorer GUI
- 打开 WEKA Explorer GUI,单击
Preprocess 选项卡,单击 Open File,然后打开应该在 Weka 发行版中的 cpu.arff 文件。在我的系统上,该文件位于weka-3-8-1/data/cpu.arff 下。资源管理器窗口应如下所示:
- 单击
Classify 选项卡。它真的应该被称为“预测”,因为你可以在这里进行分类和回归。在Classifier下,点击Choose,然后选择weka --> classifiers --> functions --> SMOreg,如下图。
- 现在构建回归模型并对其进行评估。在
Test Options 下选择Use training set 以便我们的训练集也用于测试(正如我上面提到的,这不是理想的方法)。现在按Start,结果应该如下所示:
记下 RMSE 值 (74.5996)。我们将在 Java 代码实现中重新讨论这一点。
使用 Java API
下面是一个完整的 Java 程序,它使用 Weka API 来复制前面在 Weka Explorer GUI 中显示的结果。
import weka.classifiers.functions.SMOreg;
import weka.classifiers.Evaluation;
import weka.core.Instance;
import weka.core.Instances;
import weka.core.converters.ConverterUtils.DataSource;
public class Tester {
/**
* Builds a regression model using SMOreg, the SVM for regression, and
* evaluates it with the Evalution framework.
*/
public void buildAndEvaluate(String trainingArff, String testArff) throws Exception {
System.out.printf("buildAndEvaluate() called.\n");
// Load the training and test instances.
Instances trainingInstances = DataSource.read(trainingArff);
Instances testInstances = DataSource.read(testArff);
// Set the true value to be the last field in each instance.
trainingInstances.setClassIndex(trainingInstances.numAttributes()-1);
testInstances.setClassIndex(testInstances.numAttributes()-1);
// Build the SMOregression model.
SMOreg smo = new SMOreg();
smo.buildClassifier(trainingInstances);
// Use Weka's evaluation framework.
Evaluation eval = new Evaluation(trainingInstances);
eval.evaluateModel(smo, testInstances);
// Print the options that were used in the ML algorithm.
String[] options = smo.getOptions();
System.out.printf("Options used:\n");
for (String option : options) {
System.out.printf("%s ", option);
}
System.out.printf("\n\n");
// Print the algorithm details.
System.out.printf("Algorithm:\n %s\n", smo.toString());
// Print the evaluation results.
System.out.printf("%s\n", eval.toSummaryString("\nResults\n=====\n", false));
}
/**
* Builds a regression model using SMOreg, the SVM for regression, and
* tests each data instance individually to compute RMSE.
*/
public void buildAndTestEachInstance(String trainingArff, String testArff) throws Exception {
System.out.printf("buildAndTestEachInstance() called.\n");
// Load the training and test instances.
Instances trainingInstances = DataSource.read(trainingArff);
Instances testInstances = DataSource.read(testArff);
// Set the true value to be the last field in each instance.
trainingInstances.setClassIndex(trainingInstances.numAttributes()-1);
testInstances.setClassIndex(testInstances.numAttributes()-1);
// Build the SMOregression model.
SMOreg smo = new SMOreg();
smo.buildClassifier(trainingInstances);
int numTestInstances = testInstances.numInstances();
// This variable accumulates the squared error from each test instance.
double sumOfSquaredError = 0.0;
// Loop over each test instance.
for (int i = 0; i < numTestInstances; i++) {
Instance instance = testInstances.instance(i);
double trueValue = instance.value(testInstances.classIndex());
double predictedValue = smo.classifyInstance(instance);
// Uncomment the next line to see every prediction on the test instances.
//System.out.printf("true=%10.5f, predicted=%10.5f\n", trueValue, predictedValue);
double error = trueValue - predictedValue;
sumOfSquaredError += (error * error);
}
// Print the RMSE results.
double rmse = Math.sqrt(sumOfSquaredError / numTestInstances);
System.out.printf("RMSE = %10.5f\n", rmse);
}
public static void main(String argv[]) throws Exception {
Tester classify = new Tester();
classify.buildAndEvaluate("../weka-3-8-1/data/cpu.arff", "../weka-3-8-1/data/cpu.arff");
classify.buildAndTestEachInstance("../weka-3-8-1/data/cpu.arff", "../weka-3-8-1/data/cpu.arff");
}
}
我编写了两个函数来训练 SMOreg 模型并通过对训练数据运行预测来评估模型。
buildAndEvaluate() 使用 Weka 评估模型
Evaluation 框架运行一套测试以获得完全相同
结果作为资源管理器 GUI。值得注意的是,它会产生一个 RMSE 值。
buildAndTestEachInstance() 通过显式评估模型
循环遍历每个测试实例,进行预测,计算
误差,并计算整体 RMSE。请注意,此 RMSE 匹配
来自buildAndEvaluate() 的那个,反过来匹配那个
从资源管理器 GUI。
下面是编译运行程序的结果。
prompt> javac -cp weka.jar Tester.java
prompt> java -cp .:weka.jar Tester
buildAndEvaluate() called.
Options used:
-C 1.0 -N 0 -I weka.classifiers.functions.supportVector.RegSMOImproved -T 0.001 -V -P 1.0E-12 -L 0.001 -W 1 -K weka.classifiers.functions.supportVector.PolyKernel -E 1.0 -C 250007
Algorithm:
SMOreg
weights (not support vectors):
+ 0.01 * (normalized) MYCT
+ 0.4321 * (normalized) MMIN
+ 0.1847 * (normalized) MMAX
+ 0.1175 * (normalized) CACH
+ 0.0973 * (normalized) CHMIN
+ 0.0235 * (normalized) CHMAX
- 0.0168
Number of kernel evaluations: 21945 (93.081% cached)
Results
=====
Correlation coefficient 0.9044
Mean absolute error 31.7392
Root mean squared error 74.5996
Relative absolute error 33.0908 %
Root relative squared error 46.4953 %
Total Number of Instances 209
buildAndTestEachInstance() called.
RMSE = 74.59964