检查文本中是否存在对的最有效方法

时间:2014-01-20 18:14:54

标签: java regex dictionary pattern-matching sentiment-analysis

简介:

许多情绪分析程序使用的功能之一是通过根据词典分配相关的unigrams,bigrams或配对特定分数来计算。更详细:

示例词典可以是:

//unigrams
good 1
bad -1
great 2
//bigrams
good idea 1
bad idea -1
//pairs (--- stands for whatever):
hold---up   -0.62
how---i still -0.62

给定示例文本 T ,对于 T 中的每个unigram,bigram或pair,我想检查词典中是否存在对应关系。

unigram \ bigram部分很简单:我在地图中加载词典,然后迭代我的文本,检查字典中是否存在每个单词。我的问题在于检测对。

我的问题:

检查我的文本中是否存在特定对的一种方法是迭代整个词对,并在文本上使用正则表达式。检查词典中的每个单词,如果" start_of_pair。* end_of_pair"在文中。这似乎非常浪费,因为我必须为每个要分析的文本迭代WHOLE词典。关于如何以更聪明的方式做到这一点的任何想法?

相关问题:Most Efficient Way to Check File for List of WordsJava: Most efficient way to check if a String is in a wordlist

2 个答案:

答案 0 :(得分:0)

可以实现双字母的频率图:

Map<String, Map<String, Integer> bigramFrequencyMap = new TreeMap<>();

使用初始频率为0的所需双字母填充地图。 第一个lexeme,第二个lexeme,频率计数。

static final int MAX_DISTANCE = 5;

然后词法扫描将保留最后的#MAX_DISTANCE词条。

List<Map<String, Integer>> lastLexemesSecondFrequencies = new ArrayList<>();

void processLexeme() {
     String lexeme = readLexeme();

     // Check whether there is a bigram:
     for (Map<String, Integer> prior : lastLexemesSecondFrequencies) {
          Integer freq = prior.get(lexeme);
          if (freq != null) {
              prior.put(lexeme, 1 + freq);
          }
     }

     Map<String, Integer> lexemeSecondFrequencies =
             bigramFrequencyMap.get(lexeme);
     if (lexemeSecondFrequencies != null) {
         // Could remove lexemeSecondFrequencies if present in lastLexemes.
         lastLexems.add(0, lexemeSecondFrequencies); // addFirst
         if (lastLexemes.size() > MAX_DISTANCE) {
             lastLexemes.remove(lastLexemes.size() - 1); // removeLast
         }
     }
}

优化是将bigrams保持在后半部分,并且只处理注册的双字母。

答案 1 :(得分:0)

最后我最终解决了这个问题: 我将对词汇加载为Map<String, Map<String, Float>> - 其中第一个键是对的前半部分,内部地图保存该键的开始和相应的情绪值的所有可能结尾。

基本上我有一个可能的结局列表( enabledTokens ),我每次读取新令牌时都会增加 - 然后我搜索此列表以查看当前令牌是否是某些先前的结尾对

通过一些修改来阻止前一个令牌立即用于结尾,这是我的代码:

private Map<String, Map<String, Float>> firstPartMap;
private List<LexiconPair> enabledTokensForUnigrams, enabledTokensForBigrams;
private Queue<List<LexiconPair>> pairsForBigrams; //is initialized with two empty lists
private Token oldToken;

public void parseToken(Token token) {
    String unigram = token.getText();
    String bigram = null;
    if (oldToken != null) {
        bigram = oldToken.getText() + " " + token.getText();
    }

    checkIfPairMatchesAndUpdateFeatures(unigram, enabledTokensForUnigrams);
    checkIfPairMatchesAndUpdateFeatures(bigram, enabledTokensForBigrams);

    List<LexiconPair> pairEndings = toPairs(firstPartMap.get(unigram));
    if(bigram!=null)pairEndings.addAll(toPairs(firstPartMap.get(bigram)));
    pairsForBigrams.add(pairEndings);

    enabledTokensForUnigrams.addAll(pairEndings);
    enabledTokensForBigrams.addAll(pairsForBigrams.poll());

    oldToken = token;
}
private void checkIfPairMatchesAndUpdateFeatures(String text, List<LexiconPair> listToCheck) {
    Iterator<LexiconPair> iter = listToCheck.iterator();
    while (iter.hasNext()) {
        LexiconPair next = iter.next();
        if (next.getText().equals(text)) {
            float val = next.getValue();
            POLARITY polarity = getPolarity(val);
            for (LexiconFeatureSubset lfs : lexiconsFeatures) {
                lfs.handleNewValue(Math.abs(val), polarity);
            }
            //iter.remove();
            //return; //remove only 1 occurrence
        }
    }
}