如何根据词序对文本进行分类,而不仅仅是使用词袋方法?

数据挖掘 分类
2021-09-22 05:05:35

我制作了一个朴素贝叶斯分类器,它使用词袋技术对留言板上的垃圾邮件帖子进行分类。它有效,但我认为如果我的模型考虑词序和短语,我可以获得更好的结果。(例如:'girls' 和 'live' 可能不会触发高垃圾邮件分数,即使 'live Girls' 很可能是垃圾邮件)。如何构建一个考虑词序的模型?

我考虑过存储 n-grams(check-out-these, out-these-live, these-live-girls),但这似乎从根本上增加了我记分的字典的大小,并导致短语不一致类似的措辞但不同的顺序将通过。

我不依赖贝叶斯分类,但我希望没有强大统计学背景的人可以理解和实施。

3个回答

有一个非常简单的技巧可以将词序合并到现有的词袋模型实现中。将一些短语,例如频繁出现的二元组(例如 New York)视为一个单元,即单个词,而不是将它们视为单独的实体。这将确保“New York”不同于“York New”。您还可以定义更高阶的单词 shingles,例如 n=3,4 等。

作为预处理步骤,您可以使用 Lucene ShingleFilter将文档文本分解为带状疱疹,然后将分类器应用于此分解后的文本。

import java.io.*;
import org.apache.lucene.analysis.core.*;
import org.apache.lucene.analysis.*;
import org.apache.lucene.analysis.shingle.ShingleFilter;
import org.apache.lucene.analysis.standard.*;
import org.apache.lucene.util.*;
import org.apache.lucene.analysis.util.*;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.charfilter.*;
import org.apache.lucene.analysis.core.WhitespaceTokenizer;

class TestAnalyzer extends Analyzer {

    TestAnalyzer() {
        super();
    }

    protected TokenStreamComponents createComponents( String fieldName, Reader reader ) {
        String token;
        TokenStream result = null;

        Tokenizer source = new WhitespaceTokenizer( Version.LUCENE_CURRENT, reader );
        result = new ShingleFilter(source, 2, 2);

        return new TokenStreamComponents( source, result );

    }
}

public class LuceneTest {

    public static void main(String[] args) throws Exception {

        TestAnalyzer analyzer = new TestAnalyzer();

        try {
            TokenStream stream = analyzer.tokenStream("field", new StringReader("This is a sample sentence."));
            CharTermAttribute termAtt = stream.addAttribute(CharTermAttribute.class);

            stream.reset();

            // print all tokens until stream is exhausted
            while (stream.incrementToken()) {
                System.out.println(termAtt.toString());
            }

            stream.end();
            stream.close();
         }
         catch (Exception ex) {
             ex.printStackTrace();
         }

    }
}

尝试一些生成模型,例如 HMM。只需检查以下链接: https ://stats.stackexchange.com/questions/91290/how-do-i-train-hmms-for-classification

有一堆技术。您已经提到了n-gram,然后是单词组合等。但主要问题(至少从您的角度来看)是,随着特征变得更加复杂(如 n-gram),特征数量急剧增加。这是可控的。基本上在分类之前,您必须对您的特征进行评分,然后以某个分数为阈值。这样,得分低于某个水平的特征(或在您的情况下为 n-gram)被忽略,特征计数变得易于管理。至于得分。有多种方法(选择取决于您的应用程序)对功能进行评分。您可以从“双法线分离”、“卡方”、“信息增益”等开始。我不知道这个答案是否对您有帮助,但如果您有兴趣,我可以详细说明...

我忘了,在单词组合中,您在文本上放置一个大小为 m 的窗口并提取 n 个单词的每个组合。当然