许多情绪分析程序使用的功能之一是通过根据词典分配相关的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 Words和Java: Most efficient way to check if a String is in a wordlist
答案 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
}
}
}