Matlab 中的 J48 决策树使用 Weka for API

J48 decision tree in Matlab using Weka for API

我在 Matlab 中使用 Weka for API,我遇到了一个问题..

我想在我的 "Test" 文档的属性中添加一个值:

@relation test.txt-weka.filters.unsupervised.attribute.NumericToNominal-Rlast

@attribute att_2 numeric
@attribute att_2 numeric
@attribute att_3 {0,1}

@data

我想在 att_3 中添加“2”这个值,例如:@attribute att_3 {0,1,2}

我试着命令:

test.attribute(2).addStringValue(2) 要么 test.attribute(2).addStringValue('2')

这两个都出错了.. 谁能帮帮我:(


下面是我的代码 参考How to retrieve class values from WEKA using MATLAB

%# Set paths
WEKA_HOME = 'C:\Program Files\Weka-3-8';
javaaddpath([WEKA_HOME '\weka.jar']);
import weka.cores.meta.MatlabLoader.*;

%# load dataset 
load mydata
X = feas;
Y = grp2idx(species);

%# 10-fold crossvalidation
k=10;
cvFolds = crossvalind('Kfold', species, k);   %# get indices of 10-fold CV
cp = classperf(species);   

for i = 1:k  
testIdx = (cvFolds == i); 
trainIdx = ~testIdx;   
xtrain = feas(trainIdx,:);
ytrain = species(trainIdx);
xtest = feas(testIdx,:);
ytest = species(testIdx);

train = [xtrain ytrain];
test =  [xtest ytest];
save train.txt train -ascii
save test.txt test -ascii

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);

%# train J48 tree
classifier = weka.classifiers.trees.J48();
classifier.setOptions( weka.core.Utils.splitOptions('-O -B -J -A -S -M 1') );
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) );
end

for i=1:numInst
predProbs(i,:) = classifier.distributionForInstance( test.instance(i-1) );
end

eval = weka.classifiers.Evaluation(train);
eval.evaluateModel(classifier, test, javaArray('java.lang.Object',1));

disp( char(eval.toSummaryString()) )

end

我的数据集包含31个数据,每个数据有两个属性和一个class.

我的数据集的 class 包含三个值:“0”或“1”或“2”。 class '2' 中只有 4 个数据,其他 27 个数据在 class '0' 或 '1'.

当我使用 10 折交叉验证时,只有几折(大约 4 折)在我 运行 代码时不会出错。

但是剩下的(6折)都会显示错误信息: "Subscripted assignment dimension mismatch." 而 运行宁

for i=1:numInst
predProbs(i,:) = classifier.distributionForInstance( test.instance(i-1) );
end

首先我不知道为什么,然后我发现那 6 个折叠不包含 class '2' 在 "Test data" 中的数据。他们在 "Test data" 中只有 class '0' 或 '1' 中的数据,在 "Train data" 中有 class '0','1','2' 中的数据].

并且可以 运行 的折叠在 "Test Data".

中成功包含 class '2' 中的数据

那些在 "Test" 中不包含 class '2' 的显示

@relation test.txt-weka.filters.unsupervised.attribute.NumericToNominal-Rlast

@attribute att_1 numeric
@attribute att_2 numeric
@attribute att_3 {0,1}

@data
864.86315,40.15,0
1396.0296,36.263158,0
249.6065,71.5,1

所以,我想知道是否应该在@attribute att_3 {0,1}中添加'2'来解决问题..或者问题不是这个?

还需要几个步骤。请在下面找到我的示例:

%nAttributes is number of Attributes
YourAttributeName = 'MyFavoriteAttributeName';
YourAttributeValue = 123.456;

fvWekaAttribute=javaObject('weka.core.FastVector');
fvWekaAttribute.addElement(Attribute(YourAttributeName));
DataSet=javaObject('weka.core.Instances','Rel',fvWekaAttribute,10);
DataSet.setClassIndex(nAttributes-1);
iExample=javaObject('weka.core.DenseInstance',nAttributes);
iExample.setValue(fvWekaAttribute.elementAt(0),YourAttributeValue);
DataSet.add(iExample);

或者如果属性是标称属性

%nAttributes is number of Attributes
YourAttributeName = 'MyFavoriteAttributeName';
YourAttributeValue = 123.456;

nominalEgotypeFastVector=javaObject('weka.core.FastVector');
nominalEgotypeFastVector.addElement('YourType1');
nominalEgotypeFastVector.addElement('YourType2');
nominalEgotypeFastVector.addElement('SomeMoreType');
fvWekaAttribute.addElement(Attribute(YourAttributeName,nominalEgotypeFastVector));
DataSet=javaObject('weka.core.Instances','Rel',fvWekaAttribute,10);
DataSet.setClassIndex(nAttributes-1);
iExample=javaObject('weka.core.DenseInstance',nAttributes);
iExample.setValue(fvWekaAttribute.elementAt(0),YourAttributeValue);
DataSet.add(iExample); % continue with DataSet

我认为您需要将 weka.filters.unsupervised.attribute.AddValues 和选项 -C last -L 0,1,2 应用于您的测试数据,在将 class 属性转换为名义属性之后但在尝试使用测试数据进行预测之前。这将确保测试数据中的 class 属性与训练数据中的属性匹配,即使测试数据集不包含具有给定 class 值的任何实例。

我假设您有理由希望在 Weka 中构建模型之前在 MATLAB 中进行交叉验证分区,而不是让 Weka 构建交叉验证模型?