Cevabı https://stackoverflow.com/users/1515832/generic-human harika. Ancak bunun şimdiye kadar gördüğüm en iyi uygulaması Peter Norvig'in "Beautiful Data" adlı kitabında yazılmıştır.
Kodunu yapıştırmadan önce, Norvig yönteminin neden daha doğru olduğunu açıklayayım (kod açısından biraz daha yavaş ve daha uzun olmasına rağmen).
1) Veriler biraz daha iyidir - hem boyut hem de hassasiyet açısından (basit bir sıralama yerine bir kelime sayısı kullanır) 2) Daha da önemlisi, yaklaşımı gerçekten bu kadar doğru yapan n-gramların arkasındaki mantıktır. .
Kitabında sunduğu örnek, bir dizeyi 'oturuş' olarak bölme sorunudur. Şimdi, bigram olmayan bir dize bölme yöntemi p ('otur') * p ('aşağı') olarak değerlendirilir ve bu p ('sitdown') değerinden daha az ise - ki bu oldukça sık görülür - bölünmez , ama biz onu isterdik (çoğu zaman).
Ancak, bigram modeline sahip olduğunuzda, p'yi ('oturun') bir bigram'a karşı p ('sitdown') olarak değerlendirebilirsiniz ve eski kazanır. Temel olarak, bigram kullanmazsanız, böldüğünüz kelimelerin olasılığını bağımsız olarak ele alır, bu durum böyle değildir, bazı kelimelerin birbiri ardına görünme olasılığı daha yüksektir. Ne yazık ki bunlar aynı zamanda çoğu durumda sık sık birbirine yapışan ve ayırıcıyı karıştıran kelimelerdir.
Verilere bağlantı burada (3 ayrı probleme ait veriler ve segmentasyon yalnızca bir tanesidir. Ayrıntılar için lütfen bölümü okuyun): http://norvig.com/ngrams/
ve işte kodun bağlantısı: http://norvig.com/ngrams/ngrams.py
Bu bağlantılar bir süredir arttı, ancak yine de kodun bölümleme kısmını kopyalayıp buraya yapıştıracağım
import re, string, random, glob, operator, heapq
from collections import defaultdict
from math import log10
def memo(f):
"Memoize function f."
table = {}
def fmemo(*args):
if args not in table:
table[args] = f(*args)
return table[args]
fmemo.memo = table
return fmemo
def test(verbose=None):
"""Run some tests, taken from the chapter.
Since the hillclimbing algorithm is randomized, some tests may fail."""
import doctest
print 'Running tests...'
doctest.testfile('ngrams-test.txt', verbose=verbose)
################ Word Segmentation (p. 223)
@memo
def segment(text):
"Return a list of words that is the best segmentation of text."
if not text: return []
candidates = ([first]+segment(rem) for first,rem in splits(text))
return max(candidates, key=Pwords)
def splits(text, L=20):
"Return a list of all possible (first, rem) pairs, len(first)<=L."
return [(text[:i+1], text[i+1:])
for i in range(min(len(text), L))]
def Pwords(words):
"The Naive Bayes probability of a sequence of words."
return product(Pw(w) for w in words)
#### Support functions (p. 224)
def product(nums):
"Return the product of a sequence of numbers."
return reduce(operator.mul, nums, 1)
class Pdist(dict):
"A probability distribution estimated from counts in datafile."
def __init__(self, data=[], N=None, missingfn=None):
for key,count in data:
self[key] = self.get(key, 0) + int(count)
self.N = float(N or sum(self.itervalues()))
self.missingfn = missingfn or (lambda k, N: 1./N)
def __call__(self, key):
if key in self: return self[key]/self.N
else: return self.missingfn(key, self.N)
def datafile(name, sep='\t'):
"Read key,value pairs from file."
for line in file(name):
yield line.split(sep)
def avoid_long_words(key, N):
"Estimate the probability of an unknown word."
return 10./(N * 10**len(key))
N = 1024908267229 ## Number of tokens
Pw = Pdist(datafile('count_1w.txt'), N, avoid_long_words)
#### segment2: second version, with bigram counts, (p. 226-227)
def cPw(word, prev):
"Conditional probability of word, given previous word."
try:
return P2w[prev + ' ' + word]/float(Pw[prev])
except KeyError:
return Pw(word)
P2w = Pdist(datafile('count_2w.txt'), N)
@memo
def segment2(text, prev='<S>'):
"Return (log P(words), words), where words is the best segmentation."
if not text: return 0.0, []
candidates = [combine(log10(cPw(first, prev)), first, segment2(rem, first))
for first,rem in splits(text)]
return max(candidates)
def combine(Pfirst, first, (Prem, rem)):
"Combine first and rem results into one (probability, words) pair."
return Pfirst+Prem, [first]+rem