首先找爱,談一下這個(gè)概念是怎么走進(jìn)我的腦袋的惯驼。要解決的問題是清蚀,土木專業(yè)有一些專業(yè)學(xué)術(shù)的文檔需要根據(jù)一些特殊的實(shí)體進(jìn)行標(biāo)注匕荸,以前都是一些老師傅或者前輩人工進(jìn)行工作,這樣費(fèi)人費(fèi)力枷邪,并且人非圣賢孰能無過榛搔。所以,我們作為計(jì)算機(jī)一員东揣,伸出了橄欖枝践惑,希望通過計(jì)算機(jī)最大程度地正確快速進(jìn)行實(shí)體標(biāo)注。一開始嘶卧,需求提出尔觉,我們就開始尋找匹配算法,網(wǎng)絡(luò)資源雖然很多芥吟,但是并不知道怎么去查找侦铜。過程不細(xì)說专甩,之后我莫名地就進(jìn)入了CRF算法的了解與學(xué)習(xí)中。
CRF的使用場(chǎng)景:
假設(shè)你有許多小明同學(xué)一天內(nèi)不同時(shí)段的照片钉稍,從小明提褲子起床到脫褲子睡覺各個(gè)時(shí)間段都有(小明是照片控5佣恪)。現(xiàn)在的任務(wù)是對(duì)這些照片進(jìn)行分類嫁盲。比如有的照片是吃飯篓叶,那就給它打上吃飯的標(biāo)簽;有的照片是跑步時(shí)拍的羞秤,那就打上跑步的標(biāo)簽缸托;有的照片是開會(huì)時(shí)拍的,那就打上開會(huì)的標(biāo)簽瘾蛋。問題來了俐镐,你準(zhǔn)備怎么干?一個(gè)簡(jiǎn)單直觀的辦法就是哺哼,不管這些照片之間的時(shí)間順序佩抹,想辦法訓(xùn)練出一個(gè)多元分類器。就是用一些打好標(biāo)簽的照片作為訓(xùn)練數(shù)據(jù)取董,訓(xùn)練出一個(gè)模型棍苹,直接根據(jù)照片的特征來分類。例如茵汰,如果照片是早上6:00拍的枢里,且畫面是黑暗的,那就給它打上睡覺的標(biāo)簽;如果照片上有車蹂午,那就給它打上開車的標(biāo)簽栏豺。這樣可行嗎?乍一看可以豆胸!但實(shí)際上奥洼,由于我們忽略了這些照片之間的時(shí)間順序這一重要信息,或者說晚胡,照片之間的一些聯(lián)系灵奖。我們的分類器會(huì)有缺陷的。舉個(gè)例子搬泥,假如有一張小明閉著嘴的照片桑寨,怎么分類?顯然難以直接判斷忿檩,需要參考閉嘴之前的照片尉尾,如果之前的照片顯示小明在吃飯,那這個(gè)閉嘴的照片很可能是小明在咀嚼食物準(zhǔn)備下咽燥透,可以給它打上吃飯的標(biāo)簽沙咏;如果之前的照片顯示小明在唱歌辨图,那這個(gè)閉嘴的照片很可能是小明唱歌瞬間的抓拍,可以給它打上唱歌的標(biāo)簽肢藐。所以故河,為了讓我們的分類器能夠有更好的表現(xiàn),在為一張照片分類時(shí)吆豹,我們必須將與它相鄰的照片的標(biāo)簽信息考慮進(jìn)來鱼的。這——就是條件隨機(jī)場(chǎng)(CRF)大顯身手的地方!
(注:示例摘自:https://www.zhihu.com/question/35866596/answer/139485548)
分析:先補(bǔ)充一下痘煤,我們整個(gè)設(shè)計(jì)過程中擁有的輸入凑阶,一份需要標(biāo)注的doc文檔;一份xlsx格式的實(shí)體庫衷快。那么宙橱,結(jié)合示例和我們擁有的輸入分析,CRF算法是需要一個(gè)訓(xùn)練模型的蘸拔,也就是說要使用CRF算法實(shí)現(xiàn)分詞师郑,必須有一個(gè)訓(xùn)練模型作為輸入,這個(gè)訓(xùn)練模型說的通俗點(diǎn)调窍,就是經(jīng)過可以確定的一些相互關(guān)系實(shí)現(xiàn)了分詞的文檔宝冕。但是我們的輸入,與訓(xùn)練模型概念相匹配的就是那個(gè)xlsx格式的實(shí)體庫邓萨,但是這個(gè)實(shí)體庫只是一些沒有相互關(guān)系的詞組猬仁,是一個(gè)個(gè)邏輯上沒有聯(lián)系的個(gè)體,所以我們無法將它作為訓(xùn)練模型先誉。
小結(jié)一下:講了這么多,是因?yàn)橄胝f明的烁,從實(shí)現(xiàn)分詞的角度上褐耳,CRF這個(gè)基于統(tǒng)計(jì)以及機(jī)器學(xué)習(xí)的分詞方法,或許在準(zhǔn)確度或者更多的方面要優(yōu)于其他算法渴庆。但是我們要追求铃芦,對(duì)癥下藥。
下面描述一下網(wǎng)上我最接收的中文分詞算法的分類
中文分詞算法大概分為三大類襟雷,第一類是基于字符串匹配刃滓,即掃描字符串,如果發(fā)現(xiàn)字符串的子串和詞典中的詞相同耸弄,就算匹配咧虎,比如機(jī)械分詞方法。這類分詞通常會(huì)加入一些啟發(fā)式規(guī)則计呈,比如“正向/反向最大匹配”砰诵,“長(zhǎng)詞優(yōu)先”等征唬。第二類是基于統(tǒng)計(jì)以及機(jī)器學(xué)習(xí)的分詞方法,它們基于人工標(biāo)注的詞性和統(tǒng)計(jì)特征茁彭,對(duì)中文進(jìn)行建模总寒,即根據(jù)觀測(cè)到的數(shù)據(jù)(標(biāo)注好的語料)對(duì)模型參數(shù)進(jìn)行訓(xùn)練,在分詞階段再通過模型計(jì)算各種分詞出現(xiàn)的概率理肺,將概率最大的分詞結(jié)果作為最終結(jié)果摄闸。常見的序列標(biāo)注模型有HMM和CRF。這類分詞算法能很好處理歧義和未登錄詞問題妹萨,效果比前一類效果好年枕,但是需要大量的人工標(biāo)注數(shù)據(jù),以及較慢的分詞速度眠副。第三類是通過讓計(jì)算機(jī)模擬人對(duì)句子的理解画切,達(dá)到識(shí)別詞的效果,由于漢語語義的復(fù)雜性囱怕,難以將各種語言信息組織成機(jī)器能夠識(shí)別的形式霍弹,目前這種分詞系統(tǒng)還處于試驗(yàn)階段。
由此可以看來娃弓,問題的解決辦法趨向于使用機(jī)械分詞的算法典格,即這中間最簡(jiǎn)單的正逆向匹配算法。這個(gè)網(wǎng)上也有各種語言的實(shí)現(xiàn)過程台丛,異曲同工耍缴。
正向最大匹配算法(MM):按照人得而自然閱讀順序從左往右對(duì)一段話甚至文章進(jìn)行詞庫匹配切分。
設(shè)MaxLen為最大詞長(zhǎng),D為分詞詞典
(1)從待切分語料中按正向取長(zhǎng)度為MaxLen的字符串str挽霉,令Len =MaxLen防嗡;
(2)將str與D中的詞語互相匹配;
(3)if匹配成功侠坎,將指針向前移Len個(gè)漢字蚁趁,并返回到(1);
(4)if 不成功:
if( Len>1):
Len = Len-1实胸;
從待切分語料中取長(zhǎng)度為L(zhǎng)en的字符串str他嫡,并返回(2);
else:
得到單個(gè)漢字庐完,指針向前移一個(gè)漢字钢属,并返回(1)
逆向最大匹配算法(RMM):主要原理與正向最大匹配算法一致,只是切分方向相反门躯,從文章的尾部開始匹配淆党。
(注:這不是我總結(jié)的_,來源也是一篇博客,看的多了宁否,源地址一時(shí)找不到了...)
下面放出我的實(shí)現(xiàn)代碼
match_result.py(正向匹配)
# -*- coding: utf-8 -*-
import xlrd # 處理xlsx文件
import codecs
from win32com import client # 處理word文檔
import sys
# 打開xlsx文件
def open_excel(file_name):
try:
data = xlrd.open_workbook(file_name)
print("[data]:", data)
return data
except (Exception, e):
print(e)
return False
# 解析xlsx文件中的內(nèi)容
def excel_table_byindex(file_name, colnameindex=0, by_index=0):
try:
data = open_excel(file_name)
except:
return False
if not data:
return False
table = data.sheets()[by_index]
#print("[table]:", table)
nrows = table.nrows # 行數(shù)
print("[nrows]:", nrows)
colnames = table.row_values(colnameindex) # 第一行數(shù)據(jù)(表頭)
#print("[colnames]:", colnames)
ret_list = []
for rownum in range(1, nrows): # 對(duì)于表中的一行進(jìn)行操作
row = table.row_values(rownum) # 一行的數(shù)據(jù)
max_len = 0
for item in row:
item_no_blank = item.strip()
if len(item_no_blank) > max_len:
max_len = len(item_no_blank)
ret_list.append(item_no_blank)
return ret_list,max_len
# 進(jìn)行匹配
# 這里有個(gè)坑解決了好長(zhǎng)時(shí)間,temp.txt是本目錄下的窒升,但是win32這個(gè)模塊在使用的時(shí)候必須
# 要寫全路徑,不然報(bào)錯(cuò):File "<COMObject <unknown>>", line 8, in Open
def match_result(input_file, output_file, word_dict, max_len):
word = client.Dispatch('Word.Application')
input_data = word.Documents.Open(input_file)
input_data.SaveAs(r"C:\Users\Maria\Desktop\研究生資料\正向匹配\temp.txt", 4)
temp_file = open("temp.txt", "r")
txt_content = temp_file.read()
data_len = len(txt_content)
temp_file.close()
input_data.Close()
word.Quit()
word_list = ""
cur = 0
while cur < data_len:
data = None
for data in range(max_len, 0, -1):
if txt_content[cur: cur+data] in word_dict:
word_list += txt_content[cur: cur+data] + "/"
break
cur += data
output_data = open(output_file, "w")
output_data.write(word_list)
output_data.close()
if __name__ == '__main__':
if len(sys.argv) != 3:
print("Usage:Need two arguments!")
sys.exit()
input_file = sys.argv[1]
output_file = sys.argv[2]
data,max_len = excel_table_byindex("實(shí)體庫.xlsx")
#print(data)
match_result(input_file, output_file, data, max_len)
逆向匹配
reverse_match_result.py
def reverse_match_result(input_file, output_file, word_dict, max_len):
word = client.Dispatch('Word.Application')
input_data = word.Documents.Open(input_file)
input_data.SaveAs(r"C:\Users\Maria\Desktop\研究生資料\正向匹配\temp.txt", 4)
temp_file = open("temp.txt", "r")
txt_content = temp_file.read()
data_len = len(txt_content)
temp_file.close()
input_data.Close()
word.Quit()
word_list = []
cur = data_len
while cur > 0:
data = None
if max_len > cur:
max_len = cur
for data in range(max_len, 0, -1):
if txt_content[cur-data: cur] in word_dict:
word_list.insert(0, str(txt_content[cur-data: cur]) + "/")
break
cur -= data
output_data = open(output_file, "w")
output_data.write("".join(word_list))
output_data.close()
注:兩點(diǎn),1.正逆向匹配算法簡(jiǎn)單說起來就是字符串匹配,一種很機(jī)械化地分詞方式歇僧,所以只是在于編寫代碼的語言相應(yīng)代碼的多少和使用的數(shù)據(jù)結(jié)構(gòu)上有的選胆筒,或者一些程度上的優(yōu)化。2.代碼實(shí)現(xiàn)過程中可能有些繁瑣,希望提出意見。
最后,雖然CRF算法直接使用有點(diǎn)不太合適酪呻,但是,優(yōu)先在待分析字符串中識(shí)別和切分出一些帶有明顯特征的詞,以這些詞作為斷點(diǎn),可將原字符串分為較小的串再來進(jìn)機(jī)械分詞盐须,從而減少匹配的錯(cuò)誤率玩荠,這也是一個(gè)不錯(cuò)的選擇,只不過這樣的話贼邓,我們就需要有一個(gè)這個(gè)行業(yè)的訓(xùn)練模型了阶冈。
這是CRF算法中可以下載的一些訓(xùn)練模型(我自己的騰訊云服務(wù)器沒有實(shí)現(xiàn)訓(xùn)練,可能是內(nèi)存的關(guān)系吧塑径,對(duì)于CRF的使用女坑,網(wǎng)上有很多教程,搜索即可统舀。)
下載中文分詞語料庫地址:http://sighan.cs.uchicago.edu/bakeoff2005/匆骗,語料來自:
臺(tái)灣中央研究院(Academia Sinica)、香港城市大學(xué)(City University of Hong Kong)誉简、北京大學(xué)(Peking University)及微軟亞洲研究院(Microsoft Research)