2016-09-30 62 views
1

我有一些推文,我希望分成单词。其中大部分工作正常,除非人们将以下字词组合:trumpisamoronmakeamericagreatagain。但是,那么也有像password这样的东西,不应该分成password边界上的分词

我知道nltk包有一个punkt tokenizer模块,它以智能的方式将句子分开。有没有类似的话?即使它不在nltk包中?

注意:password -> pass + word的示例比拆分词问题要少得多。

+2

,如果你以'#hashtags'工作,他们应该区别对待(不过这只是我个人的意见 – alvas

+1

不认为这是有帮助的,但你可以得到一个。英文中的所有单词的文本文件,并将推文与单词进行比较,但这并非100%准确, – Corgs

+1

这将是绝对的蛮力解决方案(可能需要大量的计算能力),但您可以短语'trumpisamoron'并运行该字符串中所有可能的单词排列,并比较每个单词出现的可能性与'word:frequency'键值对的字典,这基本上意味着您将测试't','tr'中的哪一个,'tru','trum'或'trump'更可能是a字。我不会推荐这个解决方案,但根据数据的大小,它可能是可行的。 – blacksite

回答

1

Ref:My Answer on another Question - Need to split #tags to text

本答复中的更改我做了 - (1)不同的语料库获得WORDS和(2)增加def memo(f)加速过程。您可能需要根据您正在处理的域添加/使用语料库。

检查 - Word Segmentation TaskNorvig的工作。

from __future__ import division 
from collections import Counter 
import re, nltk 
from datetime import datetime 

WORDS = nltk.corpus.reuters.words() + nltk.corpus.words.words() 
COUNTS = Counter(WORDS) 

def memo(f): 
    "Memoize function f, whose args must all be hashable." 
    cache = {} 
    def fmemo(*args): 
     if args not in cache: 
      cache[args] = f(*args) 
     return cache[args] 
    fmemo.cache = cache 
    return fmemo 

def pdist(counter): 
    "Make a probability distribution, given evidence from a Counter." 
    N = sum(counter.values()) 
    return lambda x: counter[x]/N 

P = pdist(COUNTS) 

def Pwords(words): 
    "Probability of words, assuming each word is independent of others." 
    return product(P(w) for w in words) 

def product(nums): 
    "Multiply the numbers together. (Like `sum`, but with multiplication.)" 
    result = 1 
    for x in nums: 
     result *= x 
    return result 

def splits(text, start=0, L=20): 
    "Return a list of all (first, rest) pairs; start <= len(first) <= L." 
    return [(text[:i], text[i:]) 
      for i in range(start, min(len(text), L)+1)] 

@memo 
def segment(text): 
    "Return a list of words that is the most probable segmentation of text." 
    if not text: 
     return [] 
    else: 
     candidates = ([first] + segment(rest) 
         for (first, rest) in splits(text, 1)) 
     return max(candidates, key=Pwords) 

print segment('password')  # ['password'] 
print segment('makeamericagreatagain')  # ['make', 'america', 'great', 'again'] 
print segment('trumpisamoron')  # ['trump', 'is', 'a', 'moron'] 
print segment('narcisticidiots')  # ['narcistic', 'idiot', 's'] 

有时,在情况下,字被洒入较小的令牌,可能会有更高的几率词不存在于我们的WORDS字典。

在这里最后一段,它打破了narcisticidiots为3个标记,因为标记idiots不在我们的WORDS

# Check for sample word 'idiots' 
if 'idiots' in WORDS: 
    print("YES") 
else: 
    print("NO") 

您可以将新的用户定义单词添加到WORDS

. 
. 
user_words = [] 
user_words.append('idiots') 

WORDS+=user_words 
COUNTS = Counter(WORDS) 
. 
. 
. 
print segment('narcisticidiots')  # ['narcistic', 'idiots'] 

要获得比此更好的解决方案,您可以使用bigram/trigram。

在更多的例子:Word Segmentation Task