操屁眼的视频在线免费看,日本在线综合一区二区,久久在线观看免费视频,欧美日韩精品久久综

新聞資訊

    三:關鍵詞提取的方法

    01TF-IDF

    TF-IDF在nlp領域無人不知無人不曉,思想簡單卻有效,榮獲nlp界的諾貝爾獎:奧卡姆剃刀獎。

    TF(term ),即詞頻,用來衡量詞在一篇文檔中的重要性,詞頻越高,越重要。計算公式為:

    某文檔中某詞出現的次數該文檔的總詞數

    IDF((inverse ),叫做逆文檔頻率,衡量某個詞在所有文檔集合中的常見程度。

    當包含某個詞的文檔的數量越多時,這個詞也就爛大街了,重要性越低。計算公式為:

    全部文檔的數量包含某詞的文檔的數量

    于是TF-IDF = TF * IDF, 它表明字詞的重要性與它在某篇文檔中出現的次數成正比,與它在所有文檔中出現的次數成反比。

    使用TF-IDF的一個假設前提是:已經去掉了停用詞。

    TF-IDF的優(yōu)點是計算速度快,結果穩(wěn)健。

    需要輸入多篇文檔,可以輸出每篇文檔的關鍵詞。

    02.

    基于圖計算來提取關鍵詞,需要進行迭代,速度比TF-IDF慢,但不需要通過輸入多篇文檔來提取關鍵詞。

    是把一篇文檔構建成無向圖,圖中的節(jié)點就是詞語,圖上的邊就是共現詞之間的連接。

    共現詞通過滑動窗口來確定,共現詞之間用邊相連,而邊上的權重可以使用共現詞的相似度。

    jieba提供了用提取關鍵詞的函數,但是邊的權重是詞共現的頻率。

    這樣做其實比較粗糙,我們可以使用基于詞向量計算的相似度得分作為權重,來進行迭代。

    我這不知不覺又給自己安排了任務,文章名字都想好了:

    《提取關鍵詞:我也是改過jieba源碼的人!》

    也需要先去掉停用詞。

    03.文本聚類法

    TF-IDF只從淺層的詞頻角度挖掘關鍵詞,而通過Kmeans或Topic Model,可以從深層的隱含語義角度來提取關鍵詞。

    一種方法是通過Kmeans來提取,使用詞向量作為特征。

    比如對于一篇文檔,我們要提取10個關鍵詞。

    那么可以把文檔中的詞聚成5類,然后取每個類中,與類中心最近的2個點,作為關鍵詞。

    也可以直接聚成10類,取和類中心最近的詞。

    另一種方法是通過Topic Model來提取,比如LSA和LDA,使用詞頻矩陣作為特征。

    比如對于包含多篇文檔的單領域語料,我們要挖掘關鍵詞,整理詞庫。

    那么可以用LDA進行聚類,得到每個主題的單詞分布,再取出每個主題下排名靠前的topk個單詞,或者權重高于某個閾值的單詞,構成關鍵詞庫。

    主題的單詞分布為:
    (0,?'0.025*"基金"?+?0.020*"分紅"?+?0.007*"中"?+?0.006*"考試"?+?0.006*"私募"?+?0.005*"公司"?+?0.004*"采用"?+?0.004*"市場"?+?0.004*"游戲"?+?0.004*"元"')
    (1,?'0.007*"套裝"?+?0.007*"中"?+?0.006*"設計"?+?0.004*"元"?+?0.004*"拍攝"?+?0.003*"萬"?+?0.003*"市場"?+?0.003*"編輯"?+?0.003*"時尚"?+?0.003*"穿"')
    (2,?'0.007*"英寸"?+?0.005*"中"?+?0.004*"中國"?+?0.003*"拍攝"?+?0.003*"比賽"?+?0.002*"高清"?+?0.002*"小巧"?+?0.002*"產品"?+?0.002*"億股"?+?0.002*"機型"')
    (3,?'0.082*"基金"?+?0.015*"公司"?+?0.014*"市場"?+?0.014*"投資"?+?0.009*"股票"?+?0.007*"億元"?+?0.007*"中"?+?0.006*"收益"?+?0.006*"行業(yè)"?+?0.006*"一季度"')
    ...

    04.有監(jiān)督的關鍵詞提取

    有監(jiān)督的方法需要有標注的數據,我沒有嘗試過。

    看一些文章說可以轉化為統(tǒng)計機器翻譯(SMT)的問題,轉化為序列標注(NER)的問題,或者轉化為詞語排序(LTR)的問題。

    我只理解了轉化為序列標注問題的做法,這個和用深度學習做文本摘要類似。

    文檔中的詞語,如果為關鍵詞,則標注為1,否則標注為0,也就是對一個詞進行二分類。

    據說效果比上述無監(jiān)督的方法好。

    四:TF-IDF+n-gram提取關鍵詞

    提取單詞作為關鍵詞,比較容易實現,如果要提取短語呢?

    我嘗試了開源工具RAKE,它是根據停用詞來劃分句子,再提取短語的。

    使用之后,我發(fā)現RAKE存在兩個問題:

    一是提取的短語有些長達4-5個單詞,這顯然不合適;

    二是沒有根據詞性進行過濾。

    當然,我們可以用RAKE得到一個粗糙的結果,然后再做細致的處理,比如根據包含單詞的數量、根據詞性模板等進行過濾。

    不過RAKE的代碼寫得實在太亂了,我沒有耐心看下去,對其原理也不太了解,也就沒加工再利用。

    我給出的方案是TF-IDF結合n-gram來提取關鍵短語,并根據單詞長度、停用詞和詞性進行過濾。

    01.英文新聞測試語料

    我去某網站下載了4篇英語新聞,對于其中的一篇,經過增加一段和兩段、刪除一段和兩段的操作,得到4篇內容高度重合的新聞,最終得到8篇英語新聞。

    ├──?english_new_1.txt
    ├──?english_new_2.txt
    ├──?english_new_3.txt
    ├──?english_new_add_1.txt???????#?增加一段
    ├──?english_new_add_2.txt???????#?增加兩段
    ├──?english_new_base.txt????????#?原始新聞
    ├──?english_new_remove_1.txt????#?刪除一段
    └──?english_new_remove_2.txt????#?刪除兩段

    首先用SimHash去重,保留4篇英語新聞(為了測試SimHash)。

    02.需要的庫

    TF-IDF的計算,用sklearn的包。

    由于是英文文本的處理,所以需要用NLTK做英文單詞拆分、詞性標注和詞形還原。

    #coding:utf-8
    import?os,re
    from?sklearn.feature_extraction.text?import?TfidfVectorizer
    import?numpy?as?np
    from?itertools?import?chain
    from?nltk?import?pos_tag,?word_tokenize,sent_tokenize
    from?nltk.stem?import?WordNetLemmatizer
    """?一:初始化詞形還原的類?"""
    lemmatizer?=?WordNetLemmatizer()

    為什么需要做詞形還原呢?

    抽取算法文本短詞關鍵詞是什么_抽取字符的函數_短文本關鍵詞抽取算法

    詞形還原是指把英文的單詞,從復數形態(tài)、第三人稱形態(tài)等復雜形態(tài),轉換為最基礎的形態(tài),比如 還原為salary,makes還原為make。

    如果我們提取的關鍵詞是單個詞,那么在使用TF-IDF進行提取之前,先要對每個單詞做詞形還原,不然和salary會被認為是不同的兩個單詞。

    詞形還原是基于詞典的,準確率比較高,所以使用NLTK做詞形還原時,需要下載數據 WordNet。

    在公司很容易出現網絡不通的問題,反正我是下載不了。

    nltk.download('wordnet')
    [nltk_data]?Error?loading?wordnet:?
    False

    其實不止詞形還原需要下載數據,做詞性標注和實體識別,都需要下載,特別麻煩。

    于是我干脆把NLTK的所有數據文件都下載了,文件大小為1.08G,解壓后放到相應的路徑,就一勞永逸了。

    下載鏈接:

    提取碼:

    07qb

    下載好后解壓,在ubuntu環(huán)境下,給文件賦予相應的可執(zhí)行權限(Goup和Others也需要可執(zhí)行權限),然后把數據文件復制到以下路徑:

    ??Searched?in:
    ??
    ????-?'/opt/anaconda3/nltk_data'
    ????-?'/opt/anaconda3/share/nltk_data'
    ????-?'/opt/anaconda3/lib/nltk_data'
    ????-?'/usr/share/nltk_data'
    ????-?'/usr/local/share/nltk_data'
    ????-?'/usr/lib/nltk_data'
    ????-?'/usr/local/lib/nltk_data'

    03.對新聞做單詞拆分

    最好不要對整篇文檔做 ,而是先 (劃分句子),再。

    因為實體識別、詞性標注和句法分析,最好以句子為單位來做。

    """?一:對文檔進行分詞/拆字?"""
    def?tokenize_doc(docs):
    ????"""
    ????:params:?docs——多篇文檔
    ????"""
    ????docs_tokenized?=?[]
    ????for?doc?in?docs:
    ????????doc?=?re.sub('[\n\r\t]+','?',doc)
    ????????""" 1:分句?"""
    ????????sents?=?sent_tokenize(doc)
    ????????""" 2:單詞拆分?"""
    ????????sents_tokenized?=?[word_tokenize(sent.strip())?for?sent?in?sents]
    ????????docs_tokenized.append(sents_tokenized)
    ????return?docs_tokenized

    04.n-gram的生成

    sklearn的的類里邊,也提供了n-gram的功能,那為什么我還要自己生成呢?

    原因是sklearn內置的功能里,生成n-gram后,就直接計算TF-IDF了,沒根據停用詞和詞性,過濾n-gram。

    而根據停用詞和詞性過濾n-gram,必須在計算TF-IDF之前。

    那在的時候做過濾不就得了嗎?

    不行!

    過濾n-gram,是指如果n-gram中,有一個單詞是停用詞,或者有一個單詞的詞性是過濾的詞性,那么整個n-gram都需要去掉,而不能只去掉該單詞。

    在時過濾單詞,那么生成的n-gram短語塊可能是錯誤的。

    """?二:產生n-gram,用于提取短語塊?"""
    def?gene_ngram(sentence,n=3,m=2):
    ????"""
    ????----------
    ????sentence:?分詞后的句子
    ????n:?取3,則為3-gram
    ????m:?取1,則保留1-gram
    ????----------
    ????"""
    ????if?len(sentence)?

    05.n-gram的過濾

    生成的trigram如下:

    [['What',?'are',?'the'],?['are',?'the',?'legal'],?['the',?'legal',?'implications'],?['legal',?'implications',?'of'],

    我們要對n-gram進行過濾,根據停用詞、詞性、單詞的長度以及是否包含數字,來過濾。

    詞性可以去網上找英文詞性對照表。

    如果n-gram中,包含長度為1的單詞,那么過濾掉。

    """?n-gram中是否有單詞長度為1?"""
    def?clean_by_len(gram):
    ????for?word?in?gram:
    ????????if?len(word)?短文本關鍵詞抽取算法_抽取算法文本短詞關鍵詞是什么_抽取字符的函數

    """?三:按停用詞表和詞性,過濾單詞?""" def?clean_ngrams(ngrams): ????""" ????:params:?ngrams ????""" ????stopwords?=?open("./百度英文停用詞表.txt",encoding='utf-8').readlines() ????stopwords?=?[word.strip()?for?word?in?stopwords] ????pat?=?re.compile("[0-9]+") ????"""?如果n-gram中有停用詞,則去掉?""" ????ngrams?=?[gram?for?gram?in?ngrams?if?len(set(stopwords).intersection(set(gram)))==0] ????"""?如果n-gram中有數字,則去掉?""" ????ngrams?=?[gram?for?gram?in?ngrams?if?len(pat.findall(''.join(gram).strip()))==0]???? ????"""?n-gram中有單詞長度為1,則去掉?""" ????ngrams?=?[gram?for?gram?in?ngrams?if?clean_by_len(gram)] ????"""?只保留名詞、動詞和形容詞?""" ????allow_pos_one?=?["NN","NNS","NNP","NNPS"] ????allow_pos_two?=?["NN","NNS","NNP","NNPS","JJ","JJR","JJS"] ????allow_pos_three?=?["NN","NNS","NNP","NNPS","VB","VBD","VBG","VBN","VBP","VBZ","JJ","JJR","JJS"] ????ngrams_filter?=?[] ????for?gram?in?ngrams: ????????words,pos?=?zip(*pos_tag(gram)) ????????"""?如果提取單詞作為關鍵詞,則必須為名詞?""" ????????if?len(words)?==?1: ????????????if?not?pos[0]?in?allow_pos_one: ????????????????continue??? ????????????ngrams_filter.append(gram) ????????else: ????????????"""?如果提取短語,那么開頭必須為名詞、動詞、形容詞,結尾為名詞?""" ????????????if?not?(pos[0]?in?allow_pos_three?and?pos[-1]?in?allow_pos_one): ????????????????continue?? ????????????ngrams_filter.append(gram) ????return?ngrams_filter

    06.計算TF-IDF

    用上面的函數,完成生成n-gram、過濾n-gram的步驟,然后把n-gram之間的單詞用下劃線連接:"_",n-gram之間用空格連接。

    ????""" 1:處理為n-gram,n_=2或3 """
    ????docs_ngrams?=?[gene_ngram(doc,n=n_,m=n_)?for?doc?in?docs_tokenized]
    ????"""?2:?按停用詞表和詞性,過濾?"""
    ????docs_ngrams?=?[clean_ngrams(doc)?for?doc?in?docs_ngrams]
    ????docs_?=?[]
    ????for?doc?in?docs_ngrams:
    ????????docs_.append('?'.join(['_'.join(ngram)?for?ngram?in?doc]))

    得到的n-gram如下:

    ['face_tough_times?Hiring_activity_declines?reveals_Naukri_JobSpeak?health_system_preparedness?micro-delivery_startup_DailyNinja?...]

    為什么n-gram之間的單詞用下劃線來連接呢?

    我試了其他的符號:#、=,但是發(fā)現送入sklearn的包里計算時,n-gram會被重新拆分為單詞,vocab不是n-gram短語,而是單詞。

    我估計是因為python中,下劃線比較特殊,如正則表達式 \w,表示字母、數字和下劃線,其他的符號則容易被視為文本噪音而去掉。

    接著計算n-gram的TF-IDF,這里又有一個坑:如果不自己指定n-gram字典,那么sklearn自己構建的字典中,可能會有單詞或單詞加下劃線這種奇怪的東西。

    所以需要自己傳入vocab。

    """?四:獲取 tf-idf 特征?"""
    def?calcu_tf_idf(documents):
    ????"""
    ????:param:?data為列表格式的文檔集合,?計算?tf_idf?特征
    ????"""
    ????"""?指定vocab,否則n-gram的計算會出錯?"""
    ????vocab?=?set(chain.from_iterable([doc.split()?for?doc?in?documents]))
    ????vec?=?TfidfVectorizer(vocabulary=vocab)
    ????D?=?vec.fit_transform(documents)
    ????voc?=?dict((i,?w)?for?w,?i?in?vec.vocabulary_.items())
    ????features?=?{}
    ????for?i?in?range(D.shape[0]):
    ????????Di?=?D.getrow(i)
    ????????features[i]?=?list(zip([voc[j]?for?j?in?Di.indices],?Di.data))
    ????return?features

    07.完成關鍵詞提取

    接著,就可以完成關鍵詞的提取了。

    考慮到關鍵詞提取的全面性,分別提取unigram、bigram和trigram關鍵詞。

    短文本關鍵詞抽取算法_抽取算法文本短詞關鍵詞是什么_抽取字符的函數

    如果提取unigram關鍵詞,那么需要做詞形還原。

    def?get_ngram_keywords(docs_tokenized,topk=5,n_=2):
    ????"""?1:處理為n-gram?"""
    ????docs_ngrams?=?[gene_ngram(doc,n=n_,m=n_)?for?doc?in?docs_tokenized]
    ????"""?2:?按停用詞表和詞性,過濾?"""
    ????docs_ngrams?=?[clean_ngrams(doc)?for?doc?in?docs_ngrams]
    ????docs_?=?[]
    ????for?doc?in?docs_ngrams:
    ????????docs_.append('?'.join(['_'.join(ngram)?for?ngram?in?doc]))
    ????"""?3:?計算tf-idf,提取關鍵詞?"""
    ????features?=?calcu_tf_idf(docs_)
    ????docs_keys?=?[]
    ????for?i,pair?in?features.items():
    ????????topk_idx?=?np.argsort([v?for?w,v?in?pair])[::-1][:topk]
    ????????docs_keys.append([pair[idx][0]?for?idx?in?topk_idx])
    ????return?[['?'.join(words.split('_'))?for?words?in?doc?]for?doc?in?docs_keys]?
    """?五:抽取n-gram關鍵詞?"""
    def?get_keywords(docs_tokenized,topk):
    ????"""?1:?英文單詞拆分?"""??
    ????docs_tokenized?=?[list(chain.from_iterable(doc))?for?doc?in?docs_tokenized]
    ????"""?2:?提取關鍵詞,包括unigram,bigram和trigram?"""
    ????docs_keys?=?[]
    ????for?n?in?[1,2,3]:
    ????????if?n?==?1:
    ????????????"""?3:?如果是unigram,還需要做詞形還原?"""
    ????????????docs_tokenized?=?[[lemmatizer.lemmatize(word)?for?word?in?doc]?for?doc?in?docs_tokenized]
    ????????keys_ngram?=?get_ngram_keywords(docs_tokenized,?topk,n_=n)
    ????????docs_keys.append(keys_ngram)
    ????return?[uni+bi+tri?for?uni,bi,tri?in?zip(*docs_keys)]

    ok,來看關鍵詞提取的結果。

    選取其中一篇新聞,關于新冠肺炎禁閉防范期間,降薪和裁員的影響。

    """?標題:在冠狀病毒禁閉期間裁員或減薪有什么法律影響?"""
    What?are?the?legal?implications?of?layoffs?or?salary?cuts?during?coronavirus?lockdown

    以下是提取的unigram、bigram和trigram關鍵詞。

    從關鍵詞中,大致可以看出是關于降薪、削減成本、勞動者保護、公司決策。

    遺憾的是,冠狀病毒()這個詞沒有提取出來,但是通過實體識別抽取了出來。

    'keywords':?['employee',?????????????????#?雇員
    ?????????????'order',????????????????????#?訂貨
    ?????????????'employer',?????????????????#?雇主
    ?????????????'cut',??????????????????????#?削減
    ?????????????'lockdown',?????????????????#?一級防范禁閉(期)
    ?????????????'scenario',?????????????????#?方案
    ?????????????'time',?????????????????????#?時期
    ?????????????'salary',???????????????????#?薪酬
    ?????????????'organisation',?????????????#?組織
    ?????????????'startup',??????????????????#?創(chuàng)業(yè)公司
    ?????????????'cost?reduction',???????????#?成本削減
    ?????????????'legal?implications',???????#?法律影響
    ?????????????'salary?cuts',??????????????#?降薪
    ?????????????'employer?beware',??????????#?雇主品牌
    ?????????????'discretionary?spending',???#?可自由支配的個人開支
    ?????????????'activity?declines',????????#?活動減少
    ?????????????'recommended?philosophy',???#?被推薦的方式
    ?????????????'practice?group',???????????#?業(yè)務部門
    ?????????????'population?density',???????#?人口密度
    ?????????????'pay?scales',???????????????#?工資標準
    ?????????????'advising?startup?founders',??#?建議創(chuàng)業(yè)者
    ?????????????'broader?startup?ecosystem',??#?更廣泛的創(chuàng)業(yè)生態(tài)系統(tǒng)
    ?????????????'employers?make?payment',?????#?雇主支付
    ?????????????'ensure?legal?protection',????#?確保法律保護
    ?????????????'face?tough?times',???????????#?面臨艱難時期
    ?????????????'garner?sufficient?caution',??#?獲得足夠的關注
    ?????????????'health?system?preparedness',?#?衛(wèi)生系統(tǒng)的準備
    ?????????????'lower?pay?scales',???????????#?更低的工資標準
    ?????????????'seek?legal?advice',??????????#?尋求法律咨詢
    ?????????????'top?management?level']???????#?公司高層

    時間緊,關鍵詞提取做得還不夠深入,沒有嘗試更多方法。

    寫這篇文章,是為了整理思路,希望有小伙伴可以一起交流有效的提取短語的方法。

網站首頁   |    關于我們   |    公司新聞   |    產品方案   |    用戶案例   |    售后服務   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區(qū)    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權所有