用新詞發(fā)現(xiàn)做關(guān)鍵詞抽取

新詞發(fā)現(xiàn)是一個老生常談的任務(wù)了族淮,對怎么算“詞”屎鳍,有一個很好的比喻:怎樣判斷兩個人是情侶?首先蛋勺,我們得經(jīng)巢须纾看到他們在一起村斟,而不是今天看到A和B在一起,明天看到A和C抛猫,B和D蟆盹,那可能是海王;第二是他們周圍的圈子也很豐富闺金,不能說每次看到他們一起都是和其他同樣的面孔在同樣的環(huán)境逾滥,那可能是英語角練英語[/doge]。前者反映為凝固度败匹,后者反映為自由度寨昙。

1.互信息:MI(Mutual Information)

這個指標(biāo)衡量凝固度,對兩個字計算


計算公式.png

對多個字的掀亩,算平均互信息(AMI):


n個字的平均互信息.png

還有資料用以下方式計算:


舉例三個字凝固度計算.png

也就是考慮詞的兩兩組合的不同情況舔哪,取情況最壞(說明不能成為一個詞)的某種組合作為瓶頸值。這樣等于說我們期待這個詞是無論怎么切分都很凝聚的槽棍。

2.自信息(信息熵):Entropy

信息熵計算公式

這個公式用于新詞發(fā)現(xiàn)的計算時捉蚤,反映了周圍字的豐富度抬驴。我們分別計算一個詞的左右鄰字的信息熵。一個詞我們希望左右鄰字的信息熵都很高缆巧。這里需要一個公式計算左右鄰熵的綜合值怎爵。
hanlp中取左右信息熵中最小值。SmoothNLP和HelloNLP中公開的計算公式如下盅蝗。


smoothnlp和hellonlp.png

實際上源碼中計算公式為:
smoothnlp:

math.log((l_e * 2 ** r_e + r_e * 2 ** l_e + 0.00001) / (abs(l_e - r_e) + 1), 1.5)

hellonlp:

math.log((l_e * math.e ** r_e+0.00001)/(abs(l_e - r_e)+1), math.e) \
                                       + math.log((r_e * math.e ** l_e+0.00001)/(abs(l_e - r_e)+1), math.e)

這里的公式個人認(rèn)為不是很合理。因為我們的目標(biāo)是希望EL和ER都很大姆蘸,而|EL-ER|是隱含希望他們很相近墩莫,所以會出現(xiàn):

LS(2.99, 2.99) = 9.5222271192095
LS(3.0, 3.5) = 9.176423134994266
LH(2.99, 2.99) = 8.170547111175976
LH(3.0, 3.5) = 8.040445283853845

也就是說,EL和ER雙高的情況的值竟然比EL和ER相對雙低的情況的值還低逞敷,只因為后者接近狂秦,這顯然不合理。

以及

LS(2, 100) = 161.32768043007533
LS(40, 40) = 79.18785911538012
LH(2, 100) = 98.10807767981238
LH(40, 40) = 87.37775890822788

這里左右鄰熵失衡推捐、左鄰熵非常小的情況下裂问,分值比左右鄰熵雙高且均衡的情況還要大,說明公式也沒有很好地讓雙高且接近的值更大(因為差值的倒數(shù)有邊際效應(yīng)遞減)牛柒。
所以可以自己設(shè)計一個公式L_mine堪簿。e.g.

min(l_e, r_e) * math.sqrt(max(l_e, r_e))

L_mine(2.99, 2.99) = 5.170193323271384
L_mine(3.0, 3.5) = 5.612486080160912
L_mine(2, 100) = 20.0
L_mine(40, 40) = 252.98221281347037
L_mine(20, 50) = 141.4213562373095

這樣就同時考慮的兩邊的值同時削弱了大值的影響,很好地讓EL和ER雙高的情況值最大皮壁。

以上兩點是新詞發(fā)現(xiàn)常用的兩個指標(biāo)椭更,對于我們?nèi)蝿?wù)關(guān)鍵詞抽取來說,還是欠缺了一點蛾魄。因為我們希望抽取的詞能更專業(yè)名詞一點虑瀑,且長詞優(yōu)先。不希望充斥大量的“這句話”滴须、“忽大忽小”舌狗,雖然他們符合詞的定義,但是不是我們的target word扔水。所以后續(xù)還可以結(jié)合一些指標(biāo)來篩選和算分痛侍。

3.tf-idf

我們希望這個詞有一點特別,不是每篇文章都出現(xiàn)的口水詞铭污。很容易就能想到tf-idf可以做關(guān)鍵詞提取恋日。這里計算一個詞的idf并不是用的這個詞的idf,而是詞里的每個字的idf的平均值嘹狞。

idf計算公式.png

4.詞性結(jié)構(gòu)

我們可以將詞當(dāng)作字進(jìn)行如上的計算岂膳,先分詞再結(jié)合。這時候分詞就可以得到每個詞的詞性磅网。整理出詞性組合谈截,就可以通過詞性組合來篩選出目標(biāo)詞了。但是由于詞性這一步也會有錯誤和例外,所以這一步我只做了簡單的判斷:當(dāng)出現(xiàn)名詞時簸喂,加分毙死;當(dāng)出現(xiàn)助詞、符號等明顯錯誤的喻鳄,減分扼倘。

代碼來說,先統(tǒng)計文檔里ngram的基本信息除呵,以及統(tǒng)計idf再菊。

def calculate_idf(idf_list):
    idf_di = dict()
    for sentence_word_set in idf_list:
        for word in sentence_word_set:
            if word not in idf_di:
                idf_di[word] = 0
            idf_di[word] += 1
    l = len(idf_list)
    for word in idf_di:
        idf_di[word] = math.log(l/(idf_di[word] + 1))
    return idf_di


def calculate_frequency(sentences, k=4, mode="word"):
    word_num = 0
    freq_di = dict()
    idf_list = []
    for sentence in sentences:
        sentence_set = set()
        if mode == "word":
            res = jieba.lcut(sentence)
            words = [elem.word for elem in res]
            flags = [elem.flag for elem in res]
        elif mode == "char":
            words = list(sentence)
            flags = ["n" for i in words]
        l = len(words)
        word_num = word_num + l
        for i in range(l):
            sentence_set.add(words[i])
            for j in range(1, k + 1 if i + k + 1 <= l else l - i):
                word = tuple(words[i: i + j])
                if word not in freq_di:
                    freq_di[word] = {"freq": 0, "left": [], "right": [], "pos":[]}
                freq_di[word]["freq"] += 1
                freq_di[word]["left"].append(words[i - 1] if i - 1 >= 0 else "")
                freq_di[word]["right"].append(words[i + j] if i + j <= l else "")
                freq_di[word]["pos"] = flags[i: i + j]
        idf_list.append(sentence_set)
    idf_di = calculate_idf(idf_list)
    return freq_di, word_num, idf_di

計算entropy,這里有個問題颜曾,就是有的詞是句首詞或句尾詞時意味著它沒有左鄰/右鄰纠拔,這時候想到幾種處理方式:1.沒有鄰時即不將這種情況算進(jìn)去。這種方式容易漏掉諸如名字等容易出現(xiàn)在句首的詞泛豪。2.此時將鄰看作""這個字符和其他字符一樣處理稠诲。 3.將鄰看作""這個字符,但是“”彼此之間看作不同字符诡曙,也就是說句首句尾詞認(rèn)為它有一個互不相同的鄰字臀叙。這時候我的處理方式是2和3方法的折中處理。將所有""看作不同字符岗仑,然而對這個情況的數(shù)目通過開方來降權(quán)匹耕。

def entropy(word_list):
   di = dict(Counter(word_list))
   num = sum(di.values())
   res = 0
   for word, freq in di.items():
       if word == "":
            res -= (1/num * math.log2(1/num)) * math.sqrt(freq)
       else:
           res -= freq/num * math.log2(freq/num)
   return res




def L_entropy(freq_di, threshold=0, percent=10):
    di = dict()
    for word in freq_di:
        if len(word) > 1:
            l_e = entropy(freq_di[word]["left"])
            r_e = entropy(freq_di[word]["right"])
            final_entropy = min(l_e, r_e) * math.sqrt(max(l_e, r_e))
            if final_entropy > threshold:
                #di[word] = final_entropy
                di[word] = [final_entropy, l_e, r_e]
    #di = sorted(di.items(), key=lambda x: x[1], reverse=True)
    di = sorted(di.items(), key=lambda x: x[1][0], reverse=True)
    di = di[:int(len(freq_di) * percent / 100)]
    print(di[0][1], di[-1][1])
    di = {key: value for key, value in di}
    return di

計算ami:

def ami(freq_di, word_num, threshold=0, percent=10):
    di = dict()
    for word in freq_di:
        if len(word) > 1:
            val = freq_di[word]["freq"]/word_num
            for single_word in word:
                val = val / (freq_di[tuple([single_word])]["freq"]/word_num)
            val = math.log2(val)
            val /= len(word)
            if val > threshold:
                di[word] = val
    di = sorted(di.items(), key=lambda x: x[1], reverse=True)
    di = di[:int(len(freq_di) * percent / 100)]
    print(di[0][1], di[-1][1])
    di = {key: value for key, value in di}
    return di

最后對三體.txt進(jìn)行測試,結(jié)合entropy, ami, idf, 詞性結(jié)構(gòu)分荠雕,詞頻幾個因素綜合篩選稳其、算分得char模式top100詞:

['雷迪亞茲', '章北海', '希恩斯', 'PDC', '狄奧倫娜', '申玉菲', '穿梭機(jī)', '瓦季姆', '金字塔', '銀河系', '吳岳', '饕餮魚', '楊衛(wèi)寧', '曲率驅(qū)動', '曹彬', '黑暗森林', '思想鋼印', '山杉惠子', 'PIA', '赫爾辛根默斯肯', '常偉思', 'ETO', '降臨派', '塵埃云', '斐茲羅', '東方延緒', '高Way', '階梯計劃', '逃亡主義', '黑暗森林威懾', '聯(lián)邦政府', '黑暗森林打擊', '行星防御理事會', '馮?諾伊曼', '威懾紀(jì)元', '伽爾寧', '伊甸園', '白Ice', 'DX3906', '弗雷斯', '疲憊', '法扎蘭', '張援朝', '失敗主義', '‘自然選擇’號', '執(zhí)政官', '柯伊伯帶', '公元世紀(jì)', '亞洲艦隊', 'IDC', '哈勃二號', '雷迪亞茲的', '鋼印族', '韋斯特', '引力波發(fā)射', '喬納森', '國際社會', '殘骸', '君士坦丁', '蒙娜麗莎', '曲率引擎', '翹曲點', '露珠公主', '盧浮宮', '白沐霖', '星環(huán)集團(tuán)', '拯救派', '楊晉文', '小心翼翼地', '信息窗口', '基礎(chǔ)研究', '褐蟻', 'KILLER', '君士坦丁堡', '宇宙廣播', '晶瑩', '陶醉', '紅岸基地', '末日戰(zhàn)役', '‘星環(huán)’號', '祈禱', '葉哲泰', '科學(xué)執(zhí)政官', '四維碎塊', 'NH558J2', '拐杖', '針眼畫師', '階梯計劃的', '沙瑞山', '聚變發(fā)動機(jī)', '指揮系統(tǒng)', '艦隊聯(lián)席會議', '電磁輻射', '莫沃維奇', '幼稚', '螞蟻', '紅岸系統(tǒng)', '肥皂', '追擊艦隊', '‘審判日’號']

這里的一些錯誤詞主要是"的,"地"模式炸卑,smoothnnlp對這種情況(最后一個字為頻繁字)專門做了過濾處理既鞠,我這里還沒做。

如果用word模式:

['行星防御理事會', '狄奧倫娜', '治安軍', '山杉惠子', '各常任理事國', '馮?諾伊曼', '執(zhí)劍人', '雷達(dá)峰', '莫沃維奇', '莫沃維奇和關(guān)一帆', '奧爾特星云', '宏原子', '無故事王國', '恒星型氫彈', '恒星級戰(zhàn)艦', '強互作用力', '機(jī)械臂', '程心想', '常任理事國', '聯(lián)合國行星防御理事會', '化學(xué)火箭', '史耐德', 'V裝具', '赫爾辛根默斯', '可控核聚變', '猜疑鏈', '黑暗森林理論', '禇巖', '低熵體', '斐茲羅', '面壁者雷迪亞茲', '”馮?諾伊曼', '托馬斯?維德', '兩位副艦長', '187J3X1恒星', '解析攝像機(jī)', '半人馬座', '強互作用力宇宙探測器', '解讀者', '第三宇宙速度']

效果還是不錯的盖文,肉眼看出遠(yuǎn)好于下面smoothnlp和hellonlp的結(jié)果嘱蛋。

['短短', '長長', '空間', '技術(shù)', '宇宙', '引力', '00', '太陽', '11', '太空', '狄奧倫娜', '赫爾辛根默', '辛根默斯肯', '爾辛根默斯', '史瓦西半徑', '爾辛根默', '福爾摩斯', '瓦西半徑', '赫爾辛根', '申玉菲', 'V裝具', '狄奧倫', '奧倫娜', '根默斯肯', '辛根默斯', '福爾摩', '雷迪亞茲', '史瓦西半', '辛根默', '張援朝', '赫爾辛', '逃亡主義', '默斯肯', '爾辛根', '瓦西半', '希恩斯', '降臨派', '爾摩斯', '饕餮魚', '控制單元', '西半徑', '嘿嘿嘿', '根默斯', '青銅時代號', '楊衛(wèi)寧', '運載艙', '青銅時代', '自然選擇', '史瓦西', '雷迪亞', '迪亞茲', '執(zhí)政官', '自然選擇號', '拯救派', '機(jī)械臂', '逃亡主', '澳大利亞', '技術(shù)突變', '望遠(yuǎn)鏡', '螳螂號', '1187', '章北海', '思想鋼印', '然選擇號', '然選擇', '隊司令', '艦隊司令', '控制單', '蒸汽機(jī)', '科學(xué)和理性', '層隱喻', '187', '環(huán)集團(tuán)', '亡主義', '技術(shù)公有化', '亂紀(jì)元', '制單元', '銀河系', '塵埃云', '要回答', '秘書長', '哈哈哈', '金字塔', '星環(huán)集團(tuán)', '穿梭機(jī)', '青銅時', '銅時代號', '000萬年', '短短短短', '護(hù)士', 'KB', '裝具', '吳岳', '狄奧', '殘骸', '倫娜', '申玉', '援朝', '械臂', '奧倫']

['短短', '長長', '太陽', '技術(shù)', '世界', '宇宙', '飛船', '三體', '太空', '187j3x1', '赫爾辛根默', '辛根默斯肯', '爾辛根默斯', '爾辛根默', '赫爾辛根', '根默斯肯', '辛根默斯', '187j3', 'j3x1', '福爾摩斯', '辛根默', '愛因斯坦', '雷迪亞茲', '爾辛根', '嘿嘿嘿嘿', '戰(zhàn)略研究室', '饕餮魚', '福爾摩', '略研究室', '食品垛', '黑暗森林', '赫爾辛', '默斯肯', '根默斯', '暗森林', '爾摩斯', '術(shù)戰(zhàn)略研究', '青銅時代號', '執(zhí)政官', '降臨派', '因斯坦', '青銅時代', '逃亡主義', '拯救派', '技術(shù)戰(zhàn)略研', '嘿嘿嘿', '控制單元', '雷迪亞', '迪亞茲', '技術(shù)突變', '洛文斯基', '自然選擇', '自然選擇號', '紅衛(wèi)兵', '思想鋼印', '研究室', '機(jī)械臂', '澳大利亞', '望遠(yuǎn)鏡', '戰(zhàn)略研究', '章北海', '愛因斯', '金字塔', '環(huán)集團(tuán)', '層隱喻', '復(fù)制世界', '黑暗森', '蒸汽機(jī)', '術(shù)戰(zhàn)略研', '然選擇號', '監(jiān)護(hù)官', '然選擇', '監(jiān)聽部', '信念簿', '星環(huán)集團(tuán)', '技術(shù)戰(zhàn)略', '同義詞', '逃亡主', '銀河系人類', '略研究', '哈哈哈', '銀河系', '術(shù)突變', '治安軍', '短短短短', '怎樣想', '萬千米', '要回答', '青銅時', '穿梭機(jī)', '控制單', '銅時代號', '饕餮', '187j', '幽閉', '規(guī)律', '退卻', '獨裁', '仇恨', '莊顏']

參考資料:
http://www.reibang.com/p/9b8bf8bb197c
https://github.com/smoothnlp/SmoothNLP/tree/master/tutorials/新詞發(fā)現(xiàn)
https://zhuanlan.zhihu.com/p/210584733
https://blog.csdn.net/cdd2xd/article/details/94354751
https://blog.csdn.net/wendingzhulu/article/details/44464895
https://blog.csdn.net/zhaomengszu/article/details/81452907

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市五续,隨后出現(xiàn)的幾起案子洒敏,更是在濱河造成了極大的恐慌,老刑警劉巖疙驾,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件凶伙,死亡現(xiàn)場離奇詭異,居然都是意外死亡它碎,警方通過查閱死者的電腦和手機(jī)函荣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門显押,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人傻挂,你說我怎么就攤上這事乘碑。” “怎么了金拒?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵兽肤,是天一觀的道長。 經(jīng)常有香客問我绪抛,道長轿衔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任睦疫,我火速辦了婚禮,結(jié)果婚禮上鞭呕,老公的妹妹穿的比我還像新娘蛤育。我一直安慰自己,他們只是感情好葫松,可當(dāng)我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布瓦糕。 她就那樣靜靜地躺著,像睡著了一般腋么。 火紅的嫁衣襯著肌膚如雪咕娄。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天珊擂,我揣著相機(jī)與錄音圣勒,去河邊找鬼。 笑死摧扇,一個胖子當(dāng)著我的面吹牛圣贸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播扛稽,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼在张!你這毒婦竟也來了用含?” 一聲冷哼從身側(cè)響起帮匾,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辟狈,沒想到半個月后肠缔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡明未,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了趟妥。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡披摄,死狀恐怖亲雪,靈堂內(nèi)的尸體忽然破棺而出疚膊,到底是詐尸還是另有隱情义辕,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布寓盗,位于F島的核電站灌砖,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏傀蚌。R本人自食惡果不足惜基显,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望善炫。 院中可真熱鬧撩幽,春花似錦、人聲如沸箩艺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽艺谆。三九已至酱虎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間擂涛,已是汗流浹背读串。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留撒妈,地道東北人恢暖。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像狰右,于是被迫代替她去往敵國和親杰捂。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,722評論 2 345