8

我使用WEKA gui訓練並創建了J48模型。我將模型文件保存到了我的電腦中,現在我想用它來對我的Java代碼中的單個實例進行分類。我想獲得屬性「集羣」的預測。我做的是以下幾點:對Weka的單實例進行分類

public void classify(double lat, double lon, double co) 
{    

// Create attributes to be used with classifiers 
        Attribute latitude = new Attribute("latitude"); 
        Attribute longitude = new Attribute("longitude"); 
        Attribute carbonmonoxide = new Attribute("co"); 

        // Create instances for each pollutant with attribute values latitude, longitude and pollutant itself 
        inst_co = new DenseInstance(4); 

        // Set instance's values for the attributes "latitude", "longitude", and "pollutant concentration" 
        inst_co.setValue(latitude, lat); 
        inst_co.setValue(longitude, lon); 
        inst_co.setValue(carbonmonoxide, co); 
        inst_co.setMissing(cluster); 


    Classifier cls_co = (Classifier) weka.core.SerializationHelper.read("/CO_J48Model.model");//load classifier from file 

        // Test the model 
     double result = cls_co.classifyInstance(inst_co); 
} 

但是,我得到一個IndexArrayOutofBoundsException就行inst_co.setValue(latitude, lat);。我找不到這個例外的原因。如果有人能指出我正確的方向,我將不勝感激。

回答

8

您需要將inst_co添加到您的數據集(一個Instances對象)。以下代碼應該工作。

import java.util.ArrayList; 

import weka.classifiers.Classifier; 
import weka.core.Attribute; 
import weka.core.DenseInstance; 
import weka.core.Instance; 
import weka.core.Instances; 

public class QuestionInstanceClassifiy { 

    public static void main(String[] args) { 
     QuestionInstanceClassifiy q = new QuestionInstanceClassifiy(); 
     double result = q.classify(1.0d, 1, 1); 
     System.out.println(result); 
    } 

    private Instance inst_co; 

    public double classify(double lat, double lon, double co) { 

     // Create attributes to be used with classifiers 
     // Test the model 
     double result = -1; 
     try { 

      ArrayList<Attribute> attributeList = new ArrayList<Attribute>(2); 

      Attribute latitude = new Attribute("latitude"); 
      Attribute longitude = new Attribute("longitude"); 
      Attribute carbonmonoxide = new Attribute("co"); 

      ArrayList<String> classVal = new ArrayList<String>(); 
      classVal.add("ClassA"); 
      classVal.add("ClassB"); 


      attributeList.add(latitude); 
      attributeList.add(longitude); 
      attributeList.add(carbonmonoxide); 
      attributeList.add(new Attribute("@@[email protected]@",classVal)); 

      Instances data = new Instances("TestInstances",attributeList,0); 


      // Create instances for each pollutant with attribute values latitude, 
      // longitude and pollutant itself 
      inst_co = new DenseInstance(data.numAttributes()); 
      data.add(inst_co); 

      // Set instance's values for the attributes "latitude", "longitude", and 
      // "pollutant concentration" 
      inst_co.setValue(latitude, lat); 
      inst_co.setValue(longitude, lon); 
      inst_co.setValue(carbonmonoxide, co); 
      // inst_co.setMissing(cluster); 

      // load classifier from file 
      Classifier cls_co = (Classifier) weka.core.SerializationHelper 
        .read("/CO_J48Model.model"); 

      result = cls_co.classifyInstance(inst_co); 
     } catch (Exception e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     return result; 
    } 
} 

您可以從實例創建數據對象。將您的實例添加到此數據。之後,您可以在實例中設置您的值。

Instances data = new Instances("TestInstances",attributeList,0); 
inst_co = new DenseInstance(data.numAttributes()); 
data.add(inst_co); 

我建議從外部文件獲取標頭信息和實例值或僅創建一次該信息。

+0

謝謝你的出色答案。爲了澄清,classA和classB是分類的可能結果,也就是我的分組名稱,對吧?我想他們需要與我在創建模型時使用的相同。 – Erol

+0

不工作,我得到weka.core.UnassignedDatasetException:DenseInstance無法訪問數據集!錯誤。猜猜我將不得不將它分配給一個數據集,也許是我用來訓練它的那個? – Erol

+0

@babatenor您需要將其分配給具有相同標題的數據集。他們的標題信息應該是相同的 –

3

其實我在我的情況下嘗試調用instance.setDataSet()方法,而不是addInstance方法。所以你的代碼應該是inst_co.setDataSet(data)。