Jawabannya oleh https://stackoverflow.com/users/1515832/generic-human sangat bagus. Tetapi implementasi terbaik dari ini yang pernah saya lihat ditulis sendiri oleh Peter Norvig dalam bukunya 'Beautiful Data'.
Sebelum saya menempelkan kodenya, izinkan saya menjelaskan mengapa metode Norvig lebih akurat (meskipun sedikit lebih lambat dan lebih lama dalam hal kode).
1) Datanya sedikit lebih baik - baik dalam hal ukuran dan presisi (ia menggunakan jumlah kata daripada peringkat sederhana) 2) Lebih penting lagi, logika di balik n-gram yang benar-benar membuat pendekatannya begitu akurat .
Contoh yang dia berikan dalam bukunya adalah masalah pemisahan string 'sitdown'. Sekarang metode pemisahan string non-bigram akan mempertimbangkan p ('sit') * p ('down'), dan jika ini kurang dari p ('sitdown') - yang akan sering terjadi - TIDAK akan terpecah itu, tapi kami menginginkannya (sebagian besar waktu).
Namun ketika Anda memiliki model bigram, Anda dapat menilai p ('sit down') sebagai bigram vs p ('sitdown') dan yang pertama menang. Pada dasarnya, jika Anda tidak menggunakan bigram, ini memperlakukan probabilitas kata-kata yang Anda pisahkan sebagai independen, yang tidak terjadi, beberapa kata lebih mungkin muncul satu demi satu. Sayangnya itu juga kata-kata yang sering menempel bersama dalam banyak kasus dan membingungkan splitter.
Berikut link ke datanya (data untuk 3 masalah terpisah dan segmentasi hanya satu. Silakan baca bab untuk detailnya): http://norvig.com/ngrams/
dan ini tautan ke kode: http://norvig.com/ngrams/ngrams.py
Tautan ini sudah aktif beberapa saat, tetapi saya akan menyalin dan menempelkan bagian segmentasi kode di sini
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