作為乙個python初學者+自然語言處理初學者,我用python寫了乙個簡單的中文分詞器,整個程式 加上注釋100行左右,算是乙個小練習。
演算法是最簡單的正向最大匹配(fmm):
注:這是最初的演算法,這樣做**可以控制在60行內,後來看測試結果發現沒有很好地處理數字問題, 才又增加了對數字的處理。
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# author: minix
# date: 2013-03-20
# email: [email protected]
import codecs
import sys
# 由規則處理的一些特殊符號
nummath = [u'0', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9']
nummath_suffix = [u'.', u'%', u'億', u'萬', u'千', u'百', u'十', u'個']
numcn = [u'一', u'二', u'三', u'四', u'五', u'六', u'七', u'八', u'九', u'〇', u'零']
numcn_suffix_date = [u'年', u'月', u'日']
numcn_suffix_unit = [u'億', u'萬', u'千', u'百', u'十', u'個']
special_char = [u'(', u')']
defproc_num_math(line, start):
""" 處理句子**現的數學符號 """
oldstart = start
while line[start] in nummath or line[start] in nummath_suffix:
start = start + 1
if line[start] in numcn_suffix_date:
start = start + 1
return start - oldstart
defproc_num_cn(line, start):
""" 處理句子**現的中文數字 """
oldstart = start
while line[start] in numcn or line[start] in numcn_suffix_unit:
start = start + 1
if line[start] in numcn_suffix_date:
start = start + 1
return start - oldstart
defrules(line, start):
""" 處理特殊規則 """
if line[start] in nummath:
return proc_num_math(line, start)
elif line[start] in numcn:
return proc_num_cn(line, start)
defgendict(path):
""" 獲取詞典 """
f = codecs.open(path,'r','utf-8')
contents = f.read()
contents = contents.replace(u'\r', u'')
contents = contents.replace(u'\n', u'')
# 將檔案內容按空格分開
mydict = contents.split(u' ')
# 去除詞典list中的重複
newdict = list
(set
(mydict))
newdict.remove(u'')
# 建立詞典
# key為詞首字,value為以此字開始的詞構成的list
truedict = {}
for item in newdict:
iflen(item)>0 and item[0] in truedict:
value = truedict[item[0]]
truedict[item[0]] = value
else:
truedict[item[0]] = [item]
return truedict
defprint_unicode_list(uni_list):
for item in uni_list:
print item,
defdividewords(mydict, sentence):
"""
根據詞典對句子進行分詞,
使用正向匹配的演算法,從左到右掃瞄,遇到最長的詞,
就將它切下來,直到句子被分割完閉
""" rulechar =
rulechar.extend(numcn)
rulechar.extend(nummath)
result =
start = 0
senlen = len
(sentence)
while start < senlen:
curword = sentence[start]
maxlen = 1
# 首先檢視是否可以匹配特殊規則
if curword in numcn or curword in nummath:
maxlen = rules(sentence, start)
# 尋找以當前字開頭的最長詞
if curword in mydict:
words = mydict[curword]
for item in words:
itemlen = len
(item)
if sentence[start:start+itemlen] == item and itemlen > maxlen:
maxlen = itemlen
start = start + maxlen
return result
defmain():
args = sys.ar**[1:]
iflen(args) < 3:
print
'usage: python dw.py dict_path test_path result_path'
exit
(-1)
dict_path = args[0]
test_path = args[1]
result_path = args[2]
dicts = gendict(dict_path)
fr = codecs.open(test_path,'r','utf-8')
test = fr.read()
result = dividewords(dicts,test)
fr.close()
fw = codecs.open(result_path,'w','utf-8')
for item in result:
fw.write(item + ' ')
fw.close()
if__name__
== "__main__":
main()
注:整個測試過程都在ubuntu下完成
$ python dw.py pku_training.utf8 pku_test.utf8 pku_result.utf8
$ perl score pku_training.utf8 pku_test_gold.utf8 pku_result.utf8 > score.utf8
$ tail -14 score.utf8
=== summary:
=== total insertions: 4623
=== total deletions: 1740
=== total substitutions: 6650
=== total nchange: 13013
=== total true word count: 104372
=== total test word count: 107255
=== total true words recall: 0.920
=== total test words precision: 0.895
=== f measure: 0.907
=== oov rate: 0.940
=== oov recall rate: 0.917
=== iv recall rate: 0.966
基於詞典的fmm演算法是非常基礎的分詞演算法,效果沒那麼好,不過足夠簡單,也易於入手,隨著學習的深入,我可能還會用python實現其它的分詞演算法。另外乙個感受是,看書的時候盡量多去實現,這樣會讓你有足夠的熱情去關注理論的每乙個細節,不會感到那麼枯燥無力。
用python寫乙個簡單的視窗
import sys if name main 建立乙個視窗 w qwidget 設定視窗的尺寸 w.resize 400,200 移動視窗 w.move 300,300 設定視窗的標題 w.setwindowtitle 第乙個基於pyqt5的桌面應用 顯示視窗 w.show 進入程式的主迴圈 並通...
ROS 用Python寫乙個簡單服務
一.編寫服務資料 在功能包的頂級目錄中,建立srv資料夾,並在裡面建立.srv檔案 先成為a.srv 在srv檔案中,填入服務資料,如 int64 a int64 b int64 sum其中,上方是請求資料,下方是答應資料 二.修改cmakelist和package.xml cmakelist ca...
用python寫乙個簡單的彈球遊戲
用python寫乙個簡單的彈球遊戲,可以使用球拍接住球讓球在邊框內不停的彈動,如果球拍沒有接住則遊戲結束 我們需要匯入tkinter模組來建立畫布 匯入時間模組來控制球的速度,就是控制球移動的間隔時間 匯入隨機模組使球彈的方向是隨機的。fromtkinterimport importtime imp...