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 构建交叉验证模型?
我在 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 构建交叉验证模型?