almost 2 years ago

前一篇介紹TextRank算法中,除了可提取一段短句的關鍵字之外,相同的原理也可應用於一篇文章,作關鍵句子的抽取,成為一篇文章的簡單摘要。作法如下,

一篇報導颱風的新聞

莫蘭蒂颱風步步逼近,中央氣象局今天表示,這是1995年以來有發布陸警的最強颱風,明天到中秋節上半天是影響最劇烈的時候。...

可以按照標點符號斷句為,

莫蘭蒂颱風步步逼近
中央氣象局今天表示
這是1995年以來有發布陸警的最強颱風
明天到中秋節上半天是影響最劇烈的時候
...

針對每個句子先進行分詞與過濾停用詞(更精確一點的作法,可以再判斷詞性,把詞性無關的詞去掉。)再利用TextRank計算每個句子中詞彙的權重程度(上一篇作法),抽取前三個關鍵字。

句子標號 句子內容 關鍵詞
A 莫蘭蒂颱風步步逼近 莫蘭蒂/颱風/逼近
B 中央氣象局今天表示 中央/氣象局/表示
C 這是1995年以來有發布陸警的最強颱風 陸警/發布/颱風
D 明天到中秋節上半天是影響最劇烈的時候 影響/劇烈/中秋節

按照關鍵詞出現的狀況,建立句子之間的關鍵字共現次數圖。

A B C D ...
A 0 0 1 0 ...
B 0 0 0 0 ...
C 1 0 0 0 ...
D 0 0 0 0 ...

將上表轉換為句子之間的權重關係圖,

類似的也可依照句子之間的共現關係,迭代並將結果歸一化。最後找出的結果如下,

過去曾有過比莫蘭蒂颱風強度更強的颱風出現 1.0
這是1995年以來有發布陸警的最強颱風 0.999996131374
莫蘭蒂颱風步步逼近 0.999992038026
有發布陸警的最強颱風 0.999987708567
根據中央氣象局觀測 0.999983131725

程式碼實作

1) 建立句子之間的共現關係(Coocurance)
透過判斷標點符號,切分句子。然後建立dict of dict結構。類似sentence_kw = {'A':[1,2,3],'B':[2,3,4],'C':[1,3,5]}

def sentence_coocurance(text,kw_num=3):
    ## sentence_kw :

    ## {'sen1':[word1,word2,word3],'sen2':[word2,word3,word4],

    ##  'sen3':[word1,word3,word5]}

    # sentence_kw = {'A':[1,2,3],'B':[2,3,4],'C':[1,3,5]} # test used!!

    docs = re.split(u',|。',text)
    sentence_kw = defaultdict(list)
    for sen in docs:
        if sen == u'':
            continue
        keywords = textRank(coocurance(text,windows=5),kw_num=kw_num)
        sentence_kw[sen] = keywords

    cooc_dict = defaultdict(dict) # coocurance sentence with respect to keywords


    for sentence,kw in sentence_kw.items():
        # cooc_dict[sentence] = {sentence:0}

        temp = {}
        for sent_check, kw_check in sentence_kw.items():
            if sentence == sent_check:
                # print 'nope'

                temp[sentence] =0
                continue
            else:
                count = 0
                for word in kw:
                    if word in kw_check:
                        count+=1
                # print 'yes:\t',count

                temp[sent_check] = count
        cooc_dict[sentence] = temp
    return cooc_dict

2) 利用1)計算句子之間的TextRank

def abstractTextRank(graph,d=0.85,sent_num=3,with_weight=False):
    sent_TR = defaultdict(float,[(sent,np.random.rand()) for sent,_ in graph.items()])

    err = 1e-5
    error = 1
    iter_no = 100
    index = 1
    while (iter_no >index and  error > err):
        error = 0
        sent_TR_prev = sent_TR.copy()
        for sent,cooc in graph.items():
            temp = 0
            for link_sent,weight in cooc.items():
                temp += d*sent_TR[link_sent]*weight/sum(graph[link_sent].values())
                # print 'add temp:',temp

            # print '----'

            sent_TR[sent] = 1 -d + temp
        error += (sent_TR[sent] - sent_TR_prev[sent])**2

        print 'key sentence finding...iter_no:{},\terror:{}'.format(index,error)
        index += 1
    if with_weight:
        ks = sorted(sent_TR.iteritems(),key=lambda (k,v):(v,k),reverse=True)
        ks = [(k,v/max(zip(*ks)[1])) for k,v in ks ][:sent_num]
    else:
        ks = [sent for sent,weight in sorted(sent_TR.iteritems(),key=lambda (k,v):(v,k),reverse=True)[:sent_num]]
    return ks
← 關鍵字提取-TextRank算法 神經網路-簡易分類器(NN Classifier) →
 
comments powered by Disqus