【问题标题】:How to retrieve class values from WEKA using MATLAB如何使用 MATLAB 从 WEKA 检索类值
【发布时间】:2011-11-24 01:00:22
【问题描述】:

我正在尝试使用 MATLAB 和 WEKA API 从 WEKA 检索类。一切看起来都很好,但类总是 0。有什么想法吗??

我的数据集有 241 个属性,将 WEKA 应用到这个数据集我得到了正确的结果。

创建第一个训练和测试对象,然后构建分类器并执行分类实例。但这给出了错误的结果

    train = [xtrain ytrain];
    test =  [xtest];

    save ('train.txt','train','-ASCII');    
    save ('test.txt','test','-ASCII');

%## paths
WEKA_HOME = 'C:\Program Files\Weka-3-7';
javaaddpath([WEKA_HOME '\weka.jar']);

fName = 'train.txt';

%## read file

loader = weka.core.converters.MatlabLoader();

loader.setFile( java.io.File(fName) );
train = loader.getDataSet();
train.setClassIndex( train.numAttributes()-1 );

% setting class as nominal

v(1) = java.lang.String('-R');
v(2) = java.lang.String('242');
options = cat(1,v(1:end));

filter = weka.filters.unsupervised.attribute.NumericToNominal();
filter.setOptions(options); 
filter.setInputFormat(train);   
train = filter.useFilter(train, filter);

fName = 'test.txt';

%## read file

loader = weka.core.converters.MatlabLoader();

loader.setFile( java.io.File(fName) );
test = loader.getDataSet();

%## dataset
relationName = char(test.relationName);
numAttr = test.numAttributes;
numInst = test.numInstances;

%## classification
classifier = weka.classifiers.trees.J48();
classifier.buildClassifier( train );
fprintf('Classifier: %s %s\n%s', ...
    char(classifier.getClass().getName()), ...
    char(weka.core.Utils.joinOptions(classifier.getOptions())), ...
    char(classifier.toString()) )

classes =[];

for i=1:numInst

     classes(i) = classifier.classifyInstance(test.instance(i-1));


end

这是一个新代码,但仍然无法正常工作 - classes = 0。来自 Weka 的相同算法和数据集的输出正常

=== 按类别划分的详细准确度 ===

TP Rate FP Rate Precision Recall F-Measure ROC Area Class 0.99 0.015 0.985 0.99 0.988 0.991 0 0.985 0.01 0.99 0.985 0.988 0.991 1 加权平均0.988 0.012 0.988 0.988 0.988 0.991

=== 混淆矩阵 ===

a b

 

    ytest1 = ones(size(xtest,1),1); 

    train = [xtrain ytrain];
    test =  [xtest ytest1];

    save ('train.txt','train','-ASCII');    
    save ('test.txt','test','-ASCII');

%## paths
WEKA_HOME = 'C:\Program Files\Weka-3-7';
javaaddpath([WEKA_HOME '\weka.jar']);

fName = 'train.txt';

%## read file

loader = weka.core.converters.MatlabLoader();

loader.setFile( java.io.File(fName) );
train = loader.getDataSet();
train.setClassIndex( train.numAttributes()-1 );

v(1) = java.lang.String('-R');
v(2) = java.lang.String('242');
options = cat(1,v(1:end));

filter = weka.filters.unsupervised.attribute.NumericToNominal();
filter.setOptions(options); 
filter.setInputFormat(train);   
train = filter.useFilter(train, filter);

fName = 'test.txt';

%## read file

loader = weka.core.converters.MatlabLoader();

loader.setFile( java.io.File(fName) );
test = loader.getDataSet();

filter = weka.filters.unsupervised.attribute.NumericToNominal();
filter.setOptions( weka.core.Utils.splitOptions('-R last') );
filter.setInputFormat(test);   
test = filter.useFilter(test, filter);


%## dataset
relationName = char(test.relationName);
numAttr = test.numAttributes;
numInst = test.numInstances;

%## classification
classifier = weka.classifiers.trees.J48();

classifier.buildClassifier( train );
fprintf('Classifier: %s %s\n%s', ...
    char(classifier.getClass().getName()), ...
    char(weka.core.Utils.joinOptions(classifier.getOptions())), ...
    char(classifier.toString()) )

classes = zeros(numInst,1);
for i=1:numInst   
     classes(i) = classifier.classifyInstance(test.instance(i-1));     
end

这是Java中类分布的代码sn-p

// output predictions
    System.out.println("# - actual - predicted - error - distribution");
    for (int i = 0; i < test.numInstances(); i++) {
      double pred = cls.classifyInstance(test.instance(i));
      double[] dist = cls.distributionForInstance(test.instance(i));
      System.out.print((i+1));
      System.out.print(" - ");
      System.out.print(test.instance(i).toString(test.classIndex()));
      System.out.print(" - ");
      System.out.print(test.classAttribute().value((int) pred));
      System.out.print(" - ");
      if (pred != test.instance(i).classValue())
    System.out.print("yes");
      else
    System.out.print("no");
      System.out.print(" - ");
      System.out.print(Utils.arrayToString(dist));
      System.out.println();

我把它转换成这样的 MATLAB 代码

classes = zeros(numInst,1);
for i=1:numInst
     pred = classifier.classifyInstance(test.instance(i-1));  
     classes(i) = str2num(char(test.classAttribute().value(( pred))));
end

但是类的输出不正确。

在您的回答中,您没有表明 pred 包含类和 predProb 概率。打印出来!!!

【问题讨论】:

    标签: matlab machine-learning classification weka decision-tree


    【解决方案1】:

    训练和测试数据必须具有相同数量的属性。因此,在您的情况下,即使您不知道测试数据的实际类别,也只需使用虚拟值:

    ytest = ones(size(xtest,1),1);    %# dummy class values for test data
    
    train = [xtrain ytrain];
    test =  [xtest ytest];
    
    save ('train.txt','train','-ASCII');    
    save ('test.txt','test','-ASCII');
    

    在加载测试数据集时不要忘记将其转换为名义属性(就像您对训练数据集所做的那样):

    filter = weka.filters.unsupervised.attribute.NumericToNominal();
    filter.setOptions( weka.core.Utils.splitOptions('-R last') );
    filter.setInputFormat(test);   
    test = filter.useFilter(test, filter);
    

    最后,您可以调用经过训练的 J48 分类器来预测测试实例的类值:

    classes = zeros(numInst,1);
    for i=1:numInst
         classes(i) = classifier.classifyInstance(test.instance(i-1));
    end
    

    编辑

    如果不知道您正在使用的数据,就很难判断..

    所以让我用一个完整的例子来说明。我将使用 Fisher Iris 数据(4 个属性、150 个实例、3 个类)在 MATLAB 中创建数据集。

    %# load dataset (data + labels)
    load fisheriris
    X = meas;
    Y = grp2idx(species);
    
    %# partition the data into training/testing
    c = cvpartition(Y, 'holdout',1/3);
    xtrain = X(c.training,:);
    ytrain = Y(c.training);
    xtest = X(c.test,:);
    ytest = Y(c.test);          %# or dummy values
    
    %# save as space-delimited text file
    train = [xtrain ytrain];
    test =  [xtest ytest];
    save train.txt train -ascii
    save test.txt test -ascii
    

    我应该在这里提到,在使用NumericToNominal 过滤器之前,确保类值在两个数据集中的每一个中都得到完全表示是很重要的。否则,训练集和测试集可能不兼容。我的意思是你必须至少有一个来自每个类值的实例。因此,如果您使用虚拟值,也许我们可以这样做:

    ytest = ones(size(xtest,1),1);
    v = unique(Y);
    ytest(1:numel(v)) = v;
    

    接下来,让我们使用 Weka API 读取新创建的文件。我们将最后一个属性从数字转换为名义(以启用分类):

    %# read train/test files using Weka
    fName = 'train.txt';
    loader = weka.core.converters.MatlabLoader();
    loader.setFile( java.io.File(fName) );
    train = loader.getDataSet();
    train.setClassIndex( train.numAttributes()-1 );
    
    fName = 'test.txt';
    loader = weka.core.converters.MatlabLoader();
    loader.setFile( java.io.File(fName) );
    test = loader.getDataSet();
    test.setClassIndex( test.numAttributes()-1 );
    
    %# convert last attribute (class) from numeric to nominal
    filter = weka.filters.unsupervised.attribute.NumericToNominal();
    filter.setOptions( weka.core.Utils.splitOptions('-R last') );
    filter.setInputFormat(train);   
    train = filter.useFilter(train, filter);
    
    filter = weka.filters.unsupervised.attribute.NumericToNominal();
    filter.setOptions( weka.core.Utils.splitOptions('-R last') );
    filter.setInputFormat(test);   
    test = filter.useFilter(test, filter);
    

    现在我们训练一个 J48 分类器并用它来预测测试实例的类别:

    %# train a J48 tree
    classifier = weka.classifiers.trees.J48();
    classifier.setOptions( weka.core.Utils.splitOptions('-c last -C 0.25 -M 2') );
    classifier.buildClassifier( train );
    
    %# classify test instances
    numInst = test.numInstances();
    pred = zeros(numInst,1);
    predProbs = zeros(numInst, train.numClasses());
    for i=1:numInst
         pred(i) = classifier.classifyInstance( test.instance(i-1) );
         predProbs(i,:) = classifier.distributionForInstance( test.instance(i-1) );
    end
    

    最后,我们根据测试数据评估训练模型的性能(这应该与您在 Weka Explorer 中看到的相似)。显然,这只有在测试实例具有真正的类值(不是虚拟值)时才有意义:

    eval = weka.classifiers.Evaluation(train);
    
    eval.evaluateModel(classifier, test, javaArray('java.lang.Object',1));
    
    fprintf('=== Run information ===\n\n')
    fprintf('Scheme: %s %s\n', ...
        char(classifier.getClass().getName()), ...
        char(weka.core.Utils.joinOptions(classifier.getOptions())) )
    fprintf('Relation: %s\n', char(train.relationName))
    fprintf('Instances: %d\n', train.numInstances)
    fprintf('Attributes: %d\n\n', train.numAttributes)
    
    fprintf('=== Classifier model ===\n\n')
    disp( char(classifier.toString()) )
    
    fprintf('=== Summary ===\n')
    disp( char(eval.toSummaryString()) )
    disp( char(eval.toClassDetailsString()) )
    disp( char(eval.toMatrixString()) )
    

    上述示例在 MATLAB 中的输出:

    === Run information ===
    
    Scheme: weka.classifiers.trees.J48 -C 0.25 -M 2
    Relation: train.txt-weka.filters.unsupervised.attribute.NumericToNominal-Rlast
    Instances: 100
    Attributes: 5
    
    === Classifier model ===
    
    J48 pruned tree
    ------------------
    
    att_4 <= 0.6: 1 (33.0)
    att_4 > 0.6
    |   att_3 <= 4.8
    |   |   att_4 <= 1.6: 2 (32.0)
    |   |   att_4 > 1.6: 3 (3.0/1.0)
    |   att_3 > 4.8: 3 (32.0)
    
    Number of Leaves  :     4
    
    Size of the tree :  7
    
    === Summary ===
    
    Correctly Classified Instances          46               92      %
    Incorrectly Classified Instances         4                8      %
    Kappa statistic                          0.8802
    Mean absolute error                      0.0578
    Root mean squared error                  0.2341
    Relative absolute error                 12.9975 %
    Root relative squared error             49.6536 %
    Coverage of cases (0.95 level)          92      %
    Mean rel. region size (0.95 level)      34      %
    Total Number of Instances               50     
    
    === Detailed Accuracy By Class ===
    
                 TP Rate  FP Rate  Precision   Recall  F-Measure   ROC Area  Class
                  1        0         1         1         1          1        1
                  0.765    0         1         0.765     0.867      0.879    2
                  1        0.118     0.8       1         0.889      0.938    3
    Weighted Avg. 0.92     0.038     0.936     0.92      0.919      0.939
    
    === Confusion Matrix ===
    
      a  b  c   <-- classified as
     17  0  0 |  a = 1
      0 13  4 |  b = 2
      0  0 16 |  c = 3
    

    【讨论】:

    • 是的,我同意,但如果您打印 pred 和 predProbs,您会看到 pred 不包含正确的类和 predProbs 概率。我还用更多 cmets 编辑我的问题
    • @KrzysztoFajst:它们对我来说确实有正确的值:prob 包含预测的类值(实际上是从零开始的索引),predProbs 是预测的类概率分布每个测试实例。
    • 发现问题!!!它不起作用,因为 ytest 只有一个类,我添加了 ytest1(1)=0 所以 ytest1 有 2 个类并且它可以工作。谢谢!!!
    • @KrzysztoFajst:正如我上面提到的,如果不是所有的类值都被表示,NumericToNominal 将创建一个标称值少于您预期的属性(这在我的示例中不是问题,因为我使用分层拆分来构建训练/测试数据集)
    • 答案当然被接受 - 我发送了一个积极的反馈(我希望你接受答案是这个意思)
    猜你喜欢
    • 2011-11-30
    • 2015-03-21
    • 2019-04-25
    • 2019-11-05
    • 1970-01-01
    • 1970-01-01
    • 2017-01-29
    • 1970-01-01
    • 2014-06-08
    相关资源
    最近更新 更多