【问题标题】:Serialise and Deserialise an object in Java/Android [WEKA]在 Java/Android [WEKA] 中序列化和反序列化对象
【发布时间】:2016-09-28 20:22:30
【问题描述】:

我正在我的计算机上序列化一个已经训练过的分类器,我正在尝试在 Android 上反序列化它。但是,当我尝试在我的 Android 设备上对其进行反序列化时,我会在控制台中看到以下日志:

W/System.err: java.io.InvalidClassException: weka.classifiers.meta.LogitBoost;
Incompatible class (SUID): weka.classifiers.meta.LogitBoost: static final long serialVersionUID =-1105660358715833753L;
but expected weka.classifiers.meta.LogitBoost: static final long 
serialVersionUID =-3905660358715833753L;
W/System.err:     at java.io.ObjectInputStream.verifyAndInit(ObjectInputStream.java:2336)

不知道该怎么办。我不得不提一下,我使用的是 WEKA 的精简版,可用here

这是我的分类器类,用于在我的计算机上训练和序列化分类器:

public class ClassifierSerializer {
//variables//
public ClassifierSerializer(String classifierName,
                            String classifierParameters,
                            String dataSourceFile,
                            String outputFileName) {

    this.classifierName = classifierName;
    this.classifierParameters = classifierParameters;
    this.dataSourceFile = dataSourceFile;
    this.outputFileName = outputFileName;
}

/**
 * Output the trained classifier to the specified file
 */
public void serialize() {
    readFile();
    train();
    writeToFile();
}
private void train() {
        classifier = AbstractClassifier.forName(classifierName, Utils.splitOptions(classifierParameters));
        classifier.buildClassifier(dataset);
 }
private void writeToFile() {
    // Serialize classifier
    FileOutputStream fileStream;

    fileStream = new FileOutputStream(outputFileName);
    ObjectOutputStream objectStream = new ObjectOutputStream(fileStream);
    objectStream.writeObject(classifier);
    objectStream.close();
    fileStream.close(); 
}
}

这就是我在我的主要方法中使用它的方式:

public static void main(String[] args) throws Exception {
    String datasource = "C:\\Users\\Georgi\\Desktop\\HAR_training.arff";
    ClassifierSerializer classifierSerializer = new ClassifierSerializer(
            "weka.classifiers.meta.LogitBoost",
            "-P 100  -L -1.7976931348623157E308 -H 1.0 -S 1 -I 10 -W weka.classifiers.trees.DecisionStump",
            datasource,
            "logit.data");
    classifierSerializer.serialize();
 }

这就是我在 Android 上反序列化它的方式(我的资产文件夹中有罚款):

private Classifier getClassifier() {
    // Add logic to make a network call to download the trained offline model/classifier
    String filename = "logit.data";
    ObjectInputStream objectStream = new ObjectInputStream(getAssets().open(filename));
    Object obj =objectStream.readObject();

    if (obj instanceof Classifier) {
        return (Classifier) obj;
    } else {
        return null;
    }

}

【问题讨论】:

  • 您是否在 ClassifierSerializer 中设置了 serialVersionUID?它应该与您在读取文件时得到的相同(这就是您遇到的问题)
  • @ale.m 我在我的 classSerializer 中又添加了一个方法。我没有设置它。我不确定我该怎么做。

标签: java android serialization deserialization weka


【解决方案1】:

我发现发生了什么事(有点)。我决定将我 PC 上 InteliJ 项目中的完整 weka.jar 库替换为我在 Android 项目中使用的相同剥离版本的 weka 库。出于某种原因,解决了这个问题。我认为,版本有点不同,一些变化差异导致了问题。

【讨论】:

  • Weka项目中的某个白痴在版本之间更改了serialVersionUID
  • @EJP 是的,我想这一定是发生了什么事! :)