N-gram 分詞

概述

本課程作業(yè)主要借助python工具,實現(xiàn)了N-gram分詞中的Unigram和Bigram分詞器葬荷,并將前向最大切詞FMM和后向最大切詞的結(jié)果作為Baseline纽帖,對比分析N-gram分詞器在詞語切分正確率扒吁、詞義消歧和新詞識別等方面的優(yōu)勢室囊。 github地址

數(shù)據(jù)說明

本實驗使用的語料是人民日報1998年中文標(biāo)注的語料庫,19484條粗蔚。在處理過程中鹏控,按照訓(xùn)練集 : 測試集 = 9 : 1的比例進行隨機劃分肤寝。 數(shù)據(jù)預(yù)處理包括:去詞性当辐、去文本行標(biāo)識(19980101-01-001-001)、詞典統(tǒng)計醒陆、標(biāo)點統(tǒng)計等瀑构。

主要流程
  1. 文本預(yù)處理,分為:語料隨機切分刨摩、去詞性寺晌、統(tǒng)計詞典等
  2. 使用前向FMM和后向BMM最大切分,對測試語料進行切分澡刹,統(tǒng)計準(zhǔn)確率呻征、召回率和F1值
  3. 統(tǒng)計訓(xùn)練語料詞典概率,用Unigram模型對待切分文本采用遞歸的思想罢浇,進行最大概率切分攒岛,統(tǒng)計準(zhǔn)確率顺饮、召回率和F1值
  4. 統(tǒng)計Bigram詞典概率,用Bigram模型對文本進行切分方案概率計算,選取概率最大切分局蚀,統(tǒng)計準(zhǔn)確率千扶、召回率和F1值
  5. 對比分析不同切詞方案對文本歧義和未登錄詞的處理效果。

算法描述

1. 文本預(yù)處理
"""語料的隨機切分括饶,默認按照9 : 1的比例切分訓(xùn)練集合測試集"""
def splitCorpus(train=0.9, fileName='199801.txt'):
train_file = open('train.txt', 'wb')
test_file = open('test.txt', 'wb')
with open(fileName, 'rb') as f:
  for line in f:
      if random() <= train:
          train_file.write(line)
      else:
          test_file.write(line)
train_file.close()
test_file.close()
print('successfully to split corpus by train = %f test = %f' %
    (train, 1 - train))

"""統(tǒng)計語料詞典"""
def toWordSet(file_name='train.txt', is_save=False, save_file='wordSet.pkl'):
# 獲取詞典
word_dict = defaultdict(float)
with open(file_name, 'rb') as f:
    for line in f:
        content = line.decode('gbk').strip().split()
        # 去掉第一個詞“19980101-01-001-001/m”
        for word in content[1:]:
            word_dict[word.split(u'/')[0]] += 1
if is_save:
    # 保存wordSet以復(fù)用
    joblib.dump(word_dict, save_file)
print("successfully get word dictionary!")
print("the total number of words is:{0}".format(len(word_dict.keys())))
return word_dict
2. FMM和BMM
  • 前向最大切詞藤滥,是以可變滑動窗口對文本進行順序取詞时呀,若改詞在詞典中存在磺陡,則進行一次切分;否則彰阴,縮小窗口大小射众,繼續(xù)取詞與詞典庫進行搜索罗洗,知道窗口詞長為1仇让。后向切詞原理相似,只不過是從后面開始進行窗口滑動。
def forwardMaxCut(ustring, word_set, word_max_len=5):
"""
前向最大切詞
:param ustring: 待切詞文本
:param word_set: 詞典
:param word_max_len: 最大詞長
:return: 詞列表
"""
wordList = []
if not ustring:
return wordList
while ustring:
sentence_len = len(ustring)
if sentence_len < word_max_len:
    word_max_len = sentence_len
for i in range(word_max_len, 0, -1):
    if ustring[:i] in word_set or i == 1:
        wordList.append(ustring[:i])
        ustring = ustring[i:]
        break
    else:
        i -= 1
return wordList
  • 運行結(jié)果:

    前向分詞結(jié)果:
    successfully to split corpus by train = 0.900000 test = 0.100000
    the total number of punction is:47
    the total number of words is:53198
    召回率為:0.9466013860392212
    準(zhǔn)確率為:0.9154134377927275
    F值為:0.9307462195496794
    
    后向分詞結(jié)果:
    successfully to split corpus by train = 0.900000 test = 0.100000
    the total number of punction is:47
    the total number of words is:53767
    召回率為:0.950686195146746
    準(zhǔn)確率為:0.92130516483316
    F值為:0.9357651113664159
    
  • 由于每次運行,都會對語料進行隨機切分,因此運行結(jié)果中的詞典大小有出入荆永。

  1. Unigram分詞
  • Unigram切詞的計算公式如下:
  • 基本思路: 首先統(tǒng)計出訓(xùn)練集詞典中各個詞的頻率氓拼,用來表示公式中的wi;然后凭迹,對待切分文本的進行某種策略的切分,遞歸選擇切分概率最大的子切分序列羹铅,最后回溯得到最大概率切分哥蔚。
  • 舉個栗子:
例句S:我是北京大學(xué)的一名研究生
# S的切分可以拆成兩步
P(S) = P(我)*P(是北京大學(xué)的一名研究生)
#同時后面的子句,繼續(xù)可以拆成:
P(S) = P(我)*P(是北京大學(xué)的一名研究生) = P(我)*P(是)*p(北京大學(xué)的一名研究生)
#這里有個問題咕晋,我們是如何知道應(yīng)該拆成“我”和“是”兩個詞质蕉,而不是“我是”一個詞呢
#上面計算最大概率,是遞歸調(diào)用的灾常,假設(shè)我們開始有兩種切分
[我沈撞,是北京大學(xué)的一名研究生]
[我是,北京大學(xué)的一名研究生]
#計算組合概率
P1 = P(我)*P(是北京大學(xué)的一名研究生)
P2 = P(我是)*P(北京大學(xué)的一名研究生)
#我們會發(fā)現(xiàn)
P1 > P2
#對于后面的任何子句雕什,我們都采用無腦切分缠俺,即設(shè)置最大詞長显晶,這里假設(shè)為3,可得到以下切分:
[我壹士,是北京大學(xué)的一名研究生]
[我是磷雇,北京大學(xué)的一名研究生]
[我是北,京大學(xué)的一名研究生]
#然后分別遞歸計算
#為了滿足性能的要求躏救,避免重復(fù)計算唯笙,我們采用將間接計算的子序列的組合概率,都存儲起來
#每次計算新的子序列時盒使,先查看子序列的切分組合中崩掘,是否包含已經(jīng)計算過的子子序列,包含少办,則直接復(fù)用
  • 平滑苞慢,對于詞典中搜索不到的詞,需要做一定的平滑處理英妓,常用的平滑方法原理見這里枉疼,本課程實驗支持加1平滑、WItten-Bell平滑方法鞋拟,默認采用的是Wittten-Bell平滑方法骂维。以下為計算最大切分概率程序:
def maxP(self, sentence):
  '''
  計算最大切分方案
  :param sentence: 待切分句子
  :return:
  '''
  # 遍歷所有切分組合中,找出最大概率切分
  if len(sentence) <= 1:
      return self.DICT.getPValue(self, sentence)
  # 判斷切詞方向:backward 或 forward
  sentence_split_words = [self.backwardSplitSentence(
      sentence), self.forwardSplitSentence(sentence)][self.split_way != 'back']
  # 記錄最大概率值
  max_p_value = 0
  # 儲存最大概率下的切分組合
  word_pairs = []
  # 組合概率值
  word_p = 0
  for pair in sentence_split_words:
      p1, p2 = 0, 0
      if pair[0] in self.value_dict:
          p1 = self.value_dict[pair[0]]
      else:
          p1 = self.maxP(pair[0])
      if pair[1] in self.value_dict:
          p2 = self.value_dict[pair[1]]
      else:
          p2 = self.maxP(pair[1])
      word_p = p1 * p2
      if max_p_value < word_p:
          max_p_value = word_p
          word_pairs = pair
  # 在詞典中查詢當(dāng)前句對應(yīng)的頻率贺纲,不存在時航闺,返回 1/N
  sentence_p_value = self.DICT.getPValue(self, sentence)
  # 不切分概率最大時,更新各值
  if sentence_p_value > max_p_value and self.DICT.inDict(self, sentence):
      self.value_dict[sentence] = sentence_p_value
      self.seg_dict[sentence] = sentence
      return sentence_p_value
  # 某種切分組合概率最大時猴誊,更新sentence對應(yīng)概率潦刃,避免后續(xù)切分重復(fù)計算
  else:
      self.value_dict[sentence] = max_p_value
      self.seg_dict[sentence] = word_pairs
      return max_p_value
  • 運行結(jié)果:
successfully to split corpus by train = 0.900000 test = 0.100000
the total number of words is:53705
the total number of punction is:47
召回率為:0.9614382160763091
準(zhǔn)確率為:0.9319770859102912
F值為:0.9464784466054017
3. Bigram分詞
  • Bigram切詞的計算公式如下:
  • 基本思路: 首先統(tǒng)計出訓(xùn)練集詞典中各個Bigram的頻率,如[我|是]懈叹、[我|來自]乖杠,用來表示公式中的[wi|wi-1];然后澄成,對待切分文本給出所有的切分方案胧洒,計算切分概率最大的切分序列。
  • 舉個栗子:
例句S: 這幾塊地面積還真不小墨状。
#對S進行切分卫漫,獲得所有切分方案
S1 = ['這', '幾', '塊', '地', '面', '積', '還', '真', '不', '小']
S2 = ['這', '幾', '塊', '地', '面', '積', '還', '真', '不小']
S3 = ['這', '幾', '塊', '地', '面積', '還', '真', '不', '小']
S4 = ['這', '幾', '塊', '地', '面積', '還', '真', '不小']
S5 = ['這', '幾', '塊', '地面', '積', '還', '真', '不小']
#利用Bigram公式,計算所有的方案的切分概率肾砂,為了避免出現(xiàn)float下溢出列赎,采用log求和
P(S1) = -64.745
P(S2) = -63.894
P(S3) = -55.041
P(S4) = -54.190
P(S5) = -58.190
P(S4) > P(S3)>P(S5)>P(S2)>P(S1)
#不難發(fā)現(xiàn),上述例句對于機器是一個歧義句镐确,S4和S5兩種切分都可以
#但是根據(jù)語境包吝,S4是正確的
  • 運行結(jié)果:
successfully to split corpus by train = 0.900000 test = 0.100000
the total number of words is:53260
The total number of bigram is : 403121.
successfully witten-Bell smoothing! smooth_value:1.3372788850370981e-05
the total number of punction is:47
召回率為:0.962036929819092
準(zhǔn)確率為:0.9401303935308096
F值為:0.950957517059212
4. 結(jié)果分析
  • 對比指標(biāo)
指標(biāo) FMM BMM Unigram Bigram
準(zhǔn)確率 91.54% 92.13% 93.20% 94.01%
召回率 94.66% 95.07% 96.14% 96.20%
F1值 93.07% 93.58% 94.64% 95.10%
  • 根據(jù)上表可知:分詞效果最好的是Bigram饼煞,最差的是FMM。 因為FMM只考慮了前向順序詞是否在字典中出現(xiàn)诗越,而Bigram除了考慮詞典中是否包含此詞砖瞧,同時也考慮了鄰接詞對分詞的選擇的影響。 在處理歧義上掺喻,Bigram具有較好的效果芭届,能基本實現(xiàn)消除歧義储矩,但是消除歧義的效果受文本訓(xùn)練大小的影響感耙。 在處理未登錄詞上,這里僅僅是對未登錄詞切分為單個字持隧,因此在未登錄詞的處理上還要進一步的研究討論即硼。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市屡拨,隨后出現(xiàn)的幾起案子只酥,更是在濱河造成了極大的恐慌,老刑警劉巖呀狼,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件裂允,死亡現(xiàn)場離奇詭異,居然都是意外死亡哥艇,警方通過查閱死者的電腦和手機绝编,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來貌踏,“玉大人十饥,你說我怎么就攤上這事∽嫒椋” “怎么了逗堵?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長眷昆。 經(jīng)常有香客問我蜒秤,道長,這世上最難降的妖魔是什么亚斋? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任垦藏,我火速辦了婚禮,結(jié)果婚禮上伞访,老公的妹妹穿的比我還像新娘掂骏。我一直安慰自己,他們只是感情好厚掷,可當(dāng)我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布弟灼。 她就那樣靜靜地躺著级解,像睡著了一般。 火紅的嫁衣襯著肌膚如雪田绑。 梳的紋絲不亂的頭發(fā)上勤哗,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機與錄音掩驱,去河邊找鬼芒划。 笑死,一個胖子當(dāng)著我的面吹牛欧穴,可吹牛的內(nèi)容都是我干的民逼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼涮帘,長吁一口氣:“原來是場噩夢啊……” “哼拼苍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起调缨,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤疮鲫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后弦叶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體俊犯,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年伤哺,在試婚紗的時候發(fā)現(xiàn)自己被綠了燕侠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡默责,死狀恐怖贬循,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情桃序,我是刑警寧澤杖虾,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站媒熊,受9級特大地震影響奇适,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜芦鳍,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一嚷往、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧柠衅,春花似錦皮仁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽趋急。三九已至,卻和暖如春势誊,著一層夾襖步出監(jiān)牢的瞬間呜达,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工粟耻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留查近,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓挤忙,卻偏偏與公主長得像霜威,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子饭玲,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容