我是文本分类的新手,我正在尝试使用weka构建基于单个术语的决策树和具有相关tf-idf的n-gram,以对正或负类中的某些文本进行分类,考虑到意见包含在其中。这是文本分类的一项特殊任务,通常称为“情感分类”。 所以我找到了很多关于这个主题的有趣指南。 我正在尝试在标记的训练集上使用J48,使用StringToWordVector过滤器,使用tf-idf变换,并使用NGramWordTokenizer来标记训练集语料库的输入文档。
public class TextIndexer {
public static final int TFIDF=1;
public static final int TF=2;
public static final int BOW=3;
private static String sourceDirectory;
private static Instances inputInstances;
private static WordTokenizer singleWordTokenizer;
private static NGramTokenizer nGramTokenizer;
private static StringToWordVector wv;
private static boolean ngram;
private static int minOccSingleWords;
private static int minOccNGrams;
public TextIndexer (String fileDir) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(fileDir));
ArffReader arff = new ArffReader(reader);
inputInstances = arff.getData();
reader.close();
minOccSingleWords=minOccNGrams=2;
ngram=false;
tdl=new TextDirectoryLoader();
wv=new StringToWordVector();
singleWordTokenizer = new WordTokenizer();
defaultConfig();
}
private static final void defaultConfig() {
singleWordTokenizer.setDelimiters("\\W");
wv.setDoNotOperateOnPerClassBasis(true);
wv.setUseStoplist(false);
wv.setLowerCaseTokens(true);
wv.setWordsToKeep(1000000);
wv.setIDFTransform(true);
}
所以在TextIndexer中我设置了最小出现次数,用于特征的权重,最终启用ngrams等的方法。
我在我的主类中调用TextIndexer,它使用方法toWordVector构建基于过滤实例的J48:
public Instances toWordVector() throws NullPointerException {
try {
wv.setInputFormat(inputInstances);
System.out.println(inputInstances.numInstances());
wv.setTokenizer(singleWordTokenizer);
wv.setMinTermFreq(minOccSingleWords);
Instances i = Filter.useFilter(inputInstances, wv);
System.out.println(i);
//i.setClass(i.attribute("class"));
if(ngram) {
wv.setInputFormat(inputInstances);
wv.setTokenizer(nGramTokenizer);
wv.setMinTermFreq(minOccNGrams);
Instances i2 = Filter.useFilter(inputInstances, wv);
i2.deleteAttributeAt(0);
for(int ie=0;ie<i2.numAttributes();ie++)
System.out.println(i2.attribute(ie));
i= Instances.mergeInstances(i, i2);
}
i.setClassIndex(0);
return i;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new NullPointerException("Cannot find instances from selected source file");
}
}
这是我的主要类代码:
public static void main(String[] args) throws Exception
{
try {
TextIndexer ti = new TextIndexer("C:/.../TRAINING SET WEKA/TRAIN.arff");
ti.setTokensWeight(ti.TFIDF);
ti.enableNGrams(2,3);
J48 tree = new J48();
Instances in=ti.toWordVector();
tree.buildClassifier(in);
好吧,我的分类器已经建好了。 现在,我正在尝试使用它来对一些文本进行分类,因此我使用保留在训练集中的10个文本(5个正数,5个负数),创建一个具有两个属性的arff文件:document(类型字符串)和class(正文或否定),使用“?”类设置数据。
当我尝试使用classifyInstance(Instance i)时,结果始终为0.0(或正数)。这是我的主要课程中使用的分类代码:
Instances unlabeled = new Instances(new BufferedReader(
new FileReader("C:/Users/Honestus_/Desktop/TRAINING SET WEKA/TEST.arff")));
// set class attribute
unlabeled.setClassIndex(unlabeled.numAttributes() - 1);
// create copy
Instances labeled = new Instances(unlabeled);
// label instances
for (int i = 0; i < unlabeled.numInstances(); i++) {
double clsLabel = tree.classifyInstance(unlabeled.instance(i));
labeled.instance(i).setClassValue(clsLabel);
}
如您所见,这部分代码与Using Weka in your java code相同。怎么了?我也试过使用FilteredClassifier,但没有区别。 我已经阅读了一些类似的问题,答案中谈到了训练集中的一些错误。我正在使用multi-domain sentiment的训练集,使用来自“服装”类别的1000条正面和1000条负面评论。
我希望我的问题很清楚,谢谢!