Weka在我的Java代码中 - 使用StringToWordVector的文本分类似乎不起作用

时间:2016-03-31 17:38:46

标签: java text weka categorization

我是文本分类的新手,我正在尝试使用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条负面评论。

我希望我的问题很清楚,谢谢!

0 个答案:

没有答案