1. 程式人生 > >PageRank做簡單的文字摘要

PageRank做簡單的文字摘要

PageRank做簡單的文字摘要


公式

PageRank演算法把所有評論的句子集合視作一個圖結構 G = ( V , E ) ,把評論中的單個句子視為節點。對於任意節點

i 和節點 j e
( i j )
表示這兩個節點之間邊的權重,我們使用兩句子之間的餘弦相似度來計算:

e (
i j ) = v i v j | v i | | v j |
其中, v i , v j 分別表示任意兩個句子的向量表示,這裡 e ( i j ) 0
我們可以對所有句子建立一個矩陣 M R | V | × | V | 存放任意兩個句子之間邊的權重,然後對該矩陣的每行除以其L1範數,得到任意兩句子之間的轉移概率,我們將節點自身的轉移概率設定為0,即 e ( i i ) = 0 ,並且對全為0的行中的元素統一設定為 1 / | V | 進行平滑處理:
p ( i j ) = { e ( i j ) k = 1 | V | e ( i k ) , i f e 0 1 / | V | , o t h e r w i s e
我們使用下面的公式進行迭代若干次: λ = μ M T λ + ( 1 μ ) e | V | 其中, λ R | V | × 1 為顯著性得分,初始化全為1, μ 為阻尼因子,一般設定為0.85, e 為單位向量。如果任意兩次迭代的顯著性得分都小於某個給定的閾值 ϵ ,我們認為該演算法收斂。我們取 λ 最終的值對句子進行重排序。

程式碼

import numpy as np
from sklearn import preprocessing
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer, TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity

def transition_probability(vec_arr):
    n = vec_arr.shape[0]
    m = np.zeros((n, n))
    for i in range(n):
        for j in range(i + 1, n):
            m[i, j] = cosine_similarity(vec_arr[i].reshape(1, -1),
                                        vec_arr[j].reshape(1, -1))[0][0]
            m[j, i] = m[i, j]
    for i in range(n):
        if not np.count_nonzero(m[i]):
            m[i] = np.full((1, n), 1 / n)
    return preprocessing.normalize(m, norm='l1')


def score(m, mu=0.85, epsilon=0.0001, n=50):
    score = np.full((m.shape[0], 1), 1)
    for _ in range(n):
        temp = score.copy()
        score = mu * np.mat(m).T * score + (1 - mu) / m.shape[0]
        if max(abs(temp - score)) < epsilon:
            break
    return score

def summary(sentences, n=5):
    # take the top n sentences in scores
    vectorizer = CountVectorizer(binary=True)
    # vectorizer = TfidfVectorizer()
    x = vectorizer.fit_transform(sentences)
    m = mrw_transition_probability(x.toarray())
    scores = mrw_score(m).A
    sents = []
    for i in np.argsort(-scores, axis=0).flatten()[:n]:
        sents.append(sentences[i])
    return sents