我有一些推文,我希望分成单词。其中大部分工作正常,除非人们将以下字词组合:trumpisamoron
或makeamericagreatagain
。但是,那么也有像password
这样的东西,不应该分成pass
和word
。边界上的分词
我知道nltk包有一个punkt tokenizer
模块,它以智能的方式将句子分开。有没有类似的话?即使它不在nltk包中?
注意:password -> pass + word
的示例比拆分词问题要少得多。
我有一些推文,我希望分成单词。其中大部分工作正常,除非人们将以下字词组合:trumpisamoron
或makeamericagreatagain
。但是,那么也有像password
这样的东西,不应该分成pass
和word
。边界上的分词
我知道nltk包有一个punkt tokenizer
模块,它以智能的方式将句子分开。有没有类似的话?即使它不在nltk包中?
注意:password -> pass + word
的示例比拆分词问题要少得多。
Ref:My Answer on another Question - Need to split #tags to text。
本答复中的更改我做了 - (1)不同的语料库获得WORDS
和(2)增加def memo(f)
加速过程。您可能需要根据您正在处理的域添加/使用语料库。
检查 - Word Segmentation Task从Norvig的工作。
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
,如果你以'#hashtags'工作,他们应该区别对待(不过这只是我个人的意见 – alvas
不认为这是有帮助的,但你可以得到一个。英文中的所有单词的文本文件,并将推文与单词进行比较,但这并非100%准确, – Corgs
这将是绝对的蛮力解决方案(可能需要大量的计算能力),但您可以短语'trumpisamoron'并运行该字符串中所有可能的单词排列,并比较每个单词出现的可能性与'word:frequency'键值对的字典,这基本上意味着您将测试't','tr'中的哪一个,'tru','trum'或'trump'更可能是a字。我不会推荐这个解决方案,但根据数据的大小,它可能是可行的。 – blacksite