天天看點

關鍵字提取算法

關鍵字提取算法

文章目錄

  • ​​關鍵字提取算法​​
  • ​​去除停用詞​​
  • ​​停用詞簡介​​
  • ​​停用詞的類别​​
  • ​​停用詞的功能​​
  • ​​測試說明​​
  • ​​編寫TF/IDF 算法程式​​
  • ​​關鍵詞提取技術概述​​
  • ​​TF/IDF 算法​​
  • ​​如何訓練關鍵詞提取算法​​
  • ​​測試​​

去除停用詞

停用詞簡介

停用詞是指在資訊檢索中,為節省存儲空間和提高搜尋效率,在處理自然語言資料(或文本)之前或之後會自動過濾掉某些字或詞,這些字或詞即被稱為 Stop Words(停用詞)。這些停用詞都是人工輸入、非自動化生成的,生成後的停用詞會形成一個停用詞表。

但是,并沒有一個明确的停用詞表能夠适用于所有的工具。甚至有一些工具是明确地避免使用停用詞來支援短語搜尋的。

停用詞的類别

對于一個給定的目的,任何一類的詞語都可以被選作停用詞。通常意義上,停用詞大緻分為兩類:

1、人類語言中包含的功能詞:這些功能詞極其普遍,與其他詞相比,功能詞沒有什麼實際含義,比如 the、is、at、which、on 等。但是對于搜尋引擎來說,當所要搜尋的短語包含功能詞,特别是像 The Who、Take That 等複合名詞時,停用詞的使用就會導緻問題。

2、詞彙詞:比如 want 等,這些詞應用十分廣泛,但是對這樣的詞搜尋引擎無法保證能夠給出真正相關的搜尋結果,難以幫助縮小搜尋範圍,同時還會降低搜尋的效率,是以通常會把這些詞從問題中移去,進而提高搜尋性能。

停用詞的功能

文檔中如果大量使用 Stop words 容易對頁面中的有效資訊造成噪音幹擾,是以搜尋引擎在運算之前都要對所索引的資訊進行消除噪音的處理。了解了 Stop Words ,在網頁内容中适當地減少停用詞出現的頻率,可以有效地幫助我們提高關鍵詞密度,在網頁标題标簽中避免出現停用詞能夠讓所優化的關鍵詞更集中、更突出。

是以,我們在進行自然語言處理的過程中,經常會使用停用詞表去除文本中的停用詞,以提高文本處理效率。常見步驟有:

  1. 找到一個合适的停用詞表;
  2. 對文本内容進行周遊,去除文本中的停用詞并儲存。

測試說明

測試輸入:

輸入測試語句

正确輸出:

輸出

測試代碼如下:

# 停用詞表加載方法
def get_stopword_list():
    # 停用詞表存儲路徑,每一行為一個詞,按行讀取進行加載
    # 進行編碼轉換確定比對準确率
    stop_word_path = './stopword.txt'
    stopword_list = [sw.replace('\n', '') for sw in open(stop_word_path, encoding='utf-8').readlines()]
    return stopword_list


if __name__ == '__main__':
    text = input()
    result = ""
    # 任務:使用停用詞表去掉text文本中的停用詞,并将結果儲存至result變量


    stopword_list = get_stopword_list()
    for s in text:
        if s not in stopword_list:
            result += s



    print(result, end="")      

你需求調用停用詞表 stopword.txt

———
》),
)÷(1-
”,
)、
=(
:
→
℃
&
*
一一
~~~~
’
.
『
.一
./
--
』
=″
【
[*]
}>
[⑤]]
[①D]
c]
ng昉
*
//
[
]
[②e]
[②g]
={
}
,也
‘
A
[①⑥]
[②B]
[①a]
[④a]
[①③]
[③h]
③]
1.
--
[②b]
’‘
×××
[①⑧]
0:2
=[
[⑤b]
[②c]
[④b]
[②③]
[③a]
[④c]
[①⑤]
[①⑦]
[①g]
∈[
[①⑨]
[①④]
[①c]
[②f]
[②⑧]
[②①]
[①C]
[③c]
[③g]
[②⑤]
[②②]
一.
[①h]
.數
[]
[①B]
數/
[①i]
[③e]
[①①]
[④d]
[④e]
[③b]
[⑤a]
[①A]
[②⑧]
[②⑦]
[①d]
[②j]
〕〔
][
://
′∈
[②④
[⑤e]
12%
b]
...
...................
…………………………………………………③
ZXFITL
[③F]
」
[①o]
]∧′=[
∪φ∈
′|
{-
②c
}
[③①]
R.L.
[①E]
Ψ
-[*]-
↑
.日
[②d]
[②
[②⑦]
[②②]
[③e]
[①i]
[①B]
[①h]
[①d]
[①g]
[①②]
[②a]
f]
[⑩]
a]
[①e]
[②h]
[②⑥]
[③d]
[②⑩]
e]
〉
】
元/噸
[②⑩]
2.3%
5:0
[①]
::
[②]
[③]
[④]
[⑤]
[⑥]
[⑦]
[⑧]
[⑨]
……
——
?
、
。
“
”
《
》
!
,
:
;
?
.
,
.
'
?
·
———
──
?
—
<
>
(
)
〔
〕
[
]
(
)
-
+
~
×
/
/
①
②
③
④
⑤
⑥
⑦
⑧
⑨
⑩
Ⅲ
В
"
;
#
@
γ
μ
φ
φ.
×
Δ
■
▲
sub
exp
sup
sub
Lex
#
%
&
'
+
+ξ
++
-
-β
<
<±
<Δ
<λ
<φ
<<
=
=
=☆
=-
>
>λ
_
~±
~+
[⑤f]
[⑤d]
[②i]
≈
[②G]
[①f]
LI
㈧
[-
......
〉
[③⑩]
第二
一番
一直
一個
一些
許多
種
有的是
也就是說
末##末
啊
阿
哎
哎呀
哎喲
唉
俺
俺們
按
按照
吧
吧哒
把
罷了
被
本
本着
比
比方
比如
鄙人
彼
彼此
邊
别
别的
别說
并
并且
不比
不成
不單
不但
不獨
不管
不光
不過
不僅
不拘
不論
不怕
不然
不如
不特
不惟
不問
不隻
朝
朝着
趁
趁着
乘
沖
除
除此之外
除非
除了
此
此間
此外
從
進而
打
待
但
但是
當
當着
到
得
的
的話
等
等等
地
第
叮咚
對
對于
多
多少
而
而況
而且
而是
而外
而言
而已
爾後
反過來
反過來說
反之
非但
非徒
否則
嘎
嘎登
該
趕
個
各
各個
各位
各種
各自
給
根據
跟
故
故此
固然
關于
管
歸
果然
果真
過
哈
哈哈
呵
和
何
何處
何況
何時
嘿
哼
哼唷
呼哧
乎
嘩
還是
還有
換句話說
換言之
或
或是
或者
極了
及
及其
及至
即
即便
即或
即令
即若
即使
幾
幾時
己
既
既然
既是
繼而
加之
假如
假若
假使
鑒于
将
較
較之
叫
接着
結果
借
緊接着
進而
盡
盡管
經
經過
就
就是
就是說
據
具體地說
具體說來
開始
開外
靠
咳
可
可見
可是
可以
況且
啦
來
來着
離
例如
哩
連
連同
兩者
了
臨
另
另外
另一方面
論
嘛
嗎
慢說
漫說
冒
麼
每
每當
們
莫若
某
某個
某些
拿
哪
哪邊
哪兒
哪個
哪裡
哪年
哪怕
哪天
哪些
哪樣
那
那邊
那兒
那個
那會兒
那裡
那麼
那麼些
那麼樣
那時
那些
那樣
乃
乃至
呢
能
你
你們
您
甯
甯可
甯肯
甯願
哦
嘔
啪達
旁人
呸
憑
憑借
其
其次
其二
其他
其它
其一
其餘
其中
起
起見
起見
豈但
恰恰相反
前後
前者
且
然而
然後
然則
讓
人家
任
任何
任憑
如
如此
如果
如何
如其
如若
如上所述
若
若非
若是
啥
上下
尚且
設若
設使
甚而
甚麼
甚至
省得
時候
什麼
什麼樣
使得
是
是的
首先
誰
誰知
順
順着
似的
雖
雖然
雖說
雖則
随
随着
所
是以
他
他們
他人
它
它們
她
她們
倘
倘或
倘然
倘若
倘使
騰
替
通過
同
同時
哇
萬一
往
望
為
為何
為了
為什麼
為着
喂
嗡嗡
我
我們
嗚
嗚呼
烏乎
無論
無甯
毋甯
嘻
吓
相對而言
像
向
向着
噓
呀
焉
沿
沿着
要
要不
要不然
要不是
要麼
要是
也
也罷
也好
一
一般
一旦
一方面
一來
一切
一樣
一則
依
依照
矣
以
以便
以及
以免
以至
以至于
以緻
抑或
因
是以
因而
因為
喲
用
由
由此可見
由于
有
有的
有關
有些
又
于
于是
于是乎
與
與此同時
與否
與其
越是
雲雲
哉
再說
再者
在
在下
咱
咱們
則
怎
怎麼
怎麼辦
怎麼樣
怎樣
咋
照
照着
者
這
這邊
這兒
這個
這會兒
這就是說
這裡
這麼
這麼點兒
這麼些
這麼樣
這時
這些
這樣
正如
吱
之
之類
之是以
之一
隻是
隻限
隻要
隻有
至
至于
諸位
着
着呢
自
自從
自個兒
自各兒
自己
自家
自身
綜上所述
總的來看
總的來說
總的說來
總而言之
總之
縱
縱令
縱然
縱使
遵照
作為
兮
呃
呗
咚
咦
喏
啐
喔唷
嗬
嗯
嗳      

編寫TF/IDF 算法程式

關鍵詞提取技術概述

在資訊爆炸的時代,很多資訊我們無法全面接收,我們需要從中篩選出一些我們感興趣的或者說對我們有用的資訊進行接收。怎麼選擇呢,關鍵詞提取就是其中一個很好的方法。如果我們可以準确地将所有文檔都用幾個簡單的關鍵詞描述出來,單看幾個關鍵詞就可以了解一篇文章,這樣會大大提高我們的資訊擷取效率。

類似于其他的機器學習方法,關鍵詞提取算法一般也可以分為有監督和無監督兩類:

  1. 有監督

主要通過分類的方式進行,通過建構一個豐富和完善的詞表,然後通過判斷每個文檔與詞表中每個詞的比對程度,以類似打标簽的方式,進而達到關鍵詞提取的效果。能夠獲得較高精度,但是需要大批量的标注資料,人工成本較高;

  1. 無監督

這種方式無需人工生成、維護的詞表,同時也不需要人工标注語料輔助進行訓練,這類方法目前主要有 TF-IDF 算法、 TextRank 算法和主題模型算法( LSA 、 LSI 、 LDA 等);

TF/IDF 算法

TF/IDF 算法(Term Frequency-Inverse Document Frequency ,詞頻-逆文檔頻次算法)是一種基于統計的計算方法,常用于評估在一個文檔集中一個詞對某份文檔的重要程度。這種作用顯然很符合關鍵詞抽取的需求,一個詞對文檔越重要,那就越可能是文檔的關鍵詞,是以,人們常将 TF/IDF 算法應用于關鍵詞提取中。

關鍵字提取算法

圖1

TF-IDF 的主要思想是:如果某個單詞在一篇文章中出現的頻率(TF)高,并且在其他文章中很少出現,則認為此詞或者短語具有很好的類别區分能力,适合用來分類。

1、TF 是詞頻( Term Frequency )

詞頻( TF )表示詞條(關鍵字)在文本中出現的頻率。這個數字通常會被歸一化(一般是詞頻除以文章總詞數), 以防止它偏向長的檔案。計算公式為:

TFw=該類中所有詞條數目在某一類中詞條w出現的次數

2、IDF 是逆向檔案頻率( Inverse Document Frequency )

某一特定詞語的 IDF ,可以由總檔案數目除以包含該詞語的檔案的數目,再将得到的商取對數得到。計算公式為:

idf**i=log∣j:t**i∈d**j∣∣D∣

3、TF-IDF 實際上是:TF * IDF

某一特定檔案内的高詞語頻率,以及該詞語在整個檔案集合中的低檔案頻率,可以産生出高權重的 TF-IDF 。是以,TF-IDF 傾向于過濾掉常見的詞語,保留重要的詞語。計算公式為:

TF-IDF=T**F∗IDF

如何訓練關鍵詞提取算法

我們訓練一個關鍵詞提取算法需要以下幾個步驟:

  • 加載已有的文檔資料集;
  • 加載停用詞表;
  • 對資料集中的文檔進行分詞;
  • 根據停用詞表,過濾幹擾詞;
  • 根據資料集訓練算法。

在根據訓練好的關鍵詞提取算法對新文檔進行關鍵詞提取要經過對新文檔進行分詞;根據停用詞表,過濾幹擾詞;提取關鍵詞這個幾個環節。

測試

測試輸入:

輸入測試詞

正确結果輸出:

Building prefix dict from the default dictionary …

Dumping model to file cache /tmp/jieba.cache

Loading model cost 0.738 seconds.

Prefix dict has been built successfully. # 接口調用的附加資訊

輸出對應

# 本程式的作用是通過TF/IDF算法完成對文本的關鍵詞提取,輸出前十個關鍵詞。
import math
import jieba
import jieba.posseg as psg
from gensim import corpora, models
from jieba import analyse
import functools


class TfIdf(object):
    # 四個參數分别是:訓練好的idf字典,預設idf值,處理後的待提取文本,關鍵詞數量
    def __init__(self, idf_dic, default_idf, word_list, keyword_num):
        self.word_list = word_list
        self.idf_dic, self.default_idf = idf_dic, default_idf
        self.tf_dic = self.get_tf_dic()
        self.keyword_num = keyword_num

    def get_tf_dic(self):
        tf_dic = {}
        # 任務:完成word_list的tf值的統計函數,将結果存儲到tf_dic變量中
        # ** Begin *****#
        for word in self.word_list:
            tf_dic[word] = tf_dic.get(word, 0.0) + 1.0
        tt_count = len(self.word_list)
        for k, v in tf_dic.items():
            tf_dic[k] = float(v) / tt_count
        # ** End **#
        return tf_dic

    # 按公式計算tf-idf
    def get_tfidf(self):
        tfidf_dic = {}
        for word in self.word_list:
            idf = self.idf_dic.get(word, self.default_idf)
            tf = self.tf_dic.get(word, 0)

            tfidf = tf * idf
            tfidf_dic[word] = tfidf

        tfidf_dic.items()
        # 根據tf-idf排序,去排名前keyword_num的詞作為關鍵詞
        for k, v in sorted(tfidf_dic.items(), key=functools.cmp_to_key(cmp), reverse=True)[:self.keyword_num]:
            print(k + "/ ", end='')
        print()


# 排序函數,用于topK關鍵詞的按值排序
def cmp(e1, e2):
    import numpy as np
    res = np.sign(e1[1] - e2[1])
    if res != 0:
        return res
    else:
        a = e1[0] + e2[0]
        b = e2[0] + e1[0]
        if a > b:
            return 1
        elif a == b:
            return 0
        else:
            return -1      
import math
import jieba
import jieba.posseg as psg
from gensim import corpora, models
from jieba import analyse
import functools
from test import TfIdf


# 停用詞表加載方法
def get_stopword_list():
    # 停用詞表存儲路徑,每一行為一個詞,按行讀取進行加載
    # 進行編碼轉換確定比對準确率
    stop_word_path = './stopword.txt'
    stopword_list = [sw.replace('\n', '') for sw in open(stop_word_path, encoding='utf-8').readlines()]
    return stopword_list


# 分詞方法,調用結巴接口
def seg_to_list(sentence, pos=False):
    if not pos:
        # 不進行詞性标注的分詞方法
        seg_list = jieba.cut(sentence)
    else:
        # 進行詞性标注的分詞方法
        seg_list = psg.cut(sentence)
    return seg_list


def tfidf_extract(word_list, pos=False, keyword_num=10):
    doc_list = load_data(pos)
    idf_dic, default_idf = train_idf(doc_list)
    tfidf_model = TfIdf(idf_dic, default_idf, word_list, keyword_num)
    tfidf_model.get_tfidf()


# 資料加載,pos為是否詞性标注的參數,corpus_path為資料集路徑
def load_data(pos=False, corpus_path='./corpus.txt'):
    # 調用上面方式對資料集進行處理,處理後的每條資料僅保留非幹擾詞
    doc_list = []
    for line in open(corpus_path, 'r', encoding='utf-8'):
        content = line.strip()
        seg_list = seg_to_list(content, pos)
        filter_list = word_filter(seg_list, pos)
        doc_list.append(filter_list)

    return doc_list


def train_idf(doc_list):
    idf_dic = {}
    # 總文檔數
    tt_count = len(doc_list)

    # 每個詞出現的文檔數
    for doc in doc_list:
        for word in set(doc):
            idf_dic[word] = idf_dic.get(word, 0.0) + 1.0

    # 按公式轉換為idf值,分母加1進行平滑處理
    for k, v in idf_dic.items():
        idf_dic[k] = math.log(tt_count / (1.0 + v))

    # 對于沒有在字典中的詞,預設其僅在一個文檔出現,得到預設idf值
    default_idf = math.log(tt_count / (1.0))
    return idf_dic, default_idf


# 去除幹擾詞
def word_filter(seg_list, pos=False):
    stopword_list = get_stopword_list()
    filter_list = []
    # 根據POS參數選擇是否詞性過濾
    ## 不進行詞性過濾,則将詞性都标記為n,表示全部保留
    for seg in seg_list:
        if not pos:
            word = seg
            flag = 'n'
        else:
            word = seg.word
            flag = seg.flag
        if not flag.startswith('n'):
            continue
        # 過濾停用詞表中的詞,以及長度為<2的詞
        if not word in stopword_list and len(word) > 1:
            filter_list.append(word)

    return filter_list


if __name__ == '__main__':
    text = input()
    pos = True
    seg_list = seg_to_list(text, pos)
    filter_list = word_filter(seg_list, pos)
    tfidf_extract(filter_list)