概要
- 従来の要約は冗長性を最小化するようなメイントピックを含む文を抽出することによって実現。
- 本手法はオリジナルのドキュメント全体を再現できるような文集合を抽出して再構成。そのために抽出した文集合を評価するために再構成関数 reconstruction function の提案。
- 線形的再構成 linear reconstruction。文の線形的な組み合わせによってドキュメントの近似。貪欲法 greedy strategy で最適化。
- 非負線形的再構成 nonnegative linear construction 。文の線形的な組み合わせを足し算で再構成。乗算型重み更新 multiplicative updating で最適化。
- 提案するフレームワークをDSDR (Document Summarization based on Data Reconstruction)と呼ぶ。
- DUC 2006とDUC 2007で実験。ランダム、Lead、LSA、ClusterHITS、SNMFと比較。
DSDR
要約文がなるべくドキュメント全体の内容を含むようにする。再構成誤差(reconstruction error)を小さくするようにする。
- ドキュメントの各文について重み付き語頻度ベクトル weighted term-frequency vector で表現。ステミングをしておいたり、ストップワードを取り除いたりしておく。候補文集合 the candidate set 。
- 再構成関数により候補文集合から選ばれた文集合の評価。
- 再構成誤差を最小にするような最適な組み合わせを探索。
コンセプト
まずオリジナルドキュメントと要約の再構成誤差を
L({\mathbf v}_i - f(X; {\mathbf a}_i))
と考える。ただし、候補文集合V、要約文集合X、全単語数dとして、V=[{\mathbf v}_1,...,{\mathbf v}_n]^T where {\mathbf v}_i \in R^d, X=[{\mathbf x}_1,...,{\mathbf x}_m]^T, n > mとする。{\mathbf v}_iは語頻度ベクトル、またf(\cdot)を再構成関数とする。このとき再構成誤差を最小とするようにX, Aを定めれば目的関数は
\min_{X,A} \sum_{i=1}^n ||{\mathbf v}_i - f(X; {\mathbf a}_i)||^2
となる。これに対して2つの手法で解く。
本論文では再構成関数は
f_i(X;{\mathbf a}_i)=\sum_{i=1}^m{\mathbf x}_j a_{ij}
と表し、候補文集合が
{\mathbf v}_i\approx\sum_{i=1}^m{\mathbf x}_j a_{ij}
と選ばれた文集合の線形結合で近似されるとする。
詳細は論文参照。
線形的再構成 linear reconstruction
\begin{aligned}\min_{X, A} & \sum_{i=1}^n||{\mathbf v}_i-X^TA||^2+\lambda||{\mathbf a}_i||^2\\s.t. & X \subset V, |X|=m \\& A = [{\mathbf a}_1, \cdots, {\mathbf a}_n]^T \in R^{n\times m}\end{aligned}
非負線形的 nonnegative linear reconstruction
\begin{aligned}\min_{{\mathbf a}_i, \beta} & \sum_{i=1}^n\{ ||{\mathbf v}_i -V^T {\mathbf a}_i||^2+\sum_{j=1}^n\frac{a_{ij}^2}{\beta_j} \} + \gamma||\beta||_1 \\s.t. & \beta_j \ge0, a_{ij} \ge 0, {\mathbf a}_i \in R^n\end{aligned}
実装
論文に疑似コードが載っているのでPythonで実装。要NumPy。
V = [[1,0,0,0], [0,1,0,0], [1,1,0,0], [0,0,1,0], [0,0,1,1]]というドキュメント(行が文、列が語)に対して、
- 線形的再構成では3番目と5番目の[1,1,0,0], [0,0,1,1]という文が選ばれた。
- 非負線形的再構成ではそれぞれに[ 0.49301097 0.49301097 0.6996585 0.49301097 0.70211699]という重みがつき、同様に3番目と5番目の文が選ばれやすいことを示している。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
import numpy as np | |
class DSDR: | |
"""Z He, et al. Document Summarization based onData Reconstruction (2012) | |
http://www.aaai.org/ocs/index.php/AAAI/AAAI12/paper/viewPaper/4991 | |
""" | |
@staticmethod | |
def lin(V, m, lamb): | |
'''DSDR with linear reconstruction | |
Parameters | |
========== | |
- V : 2d array_like, the candidate data set | |
- m : int, the number of sentences to be selected | |
- lamb : float, the trade off parameter | |
Returns | |
======= | |
- L : list, the set of m summary sentences indices | |
''' | |
L = [] | |
V = np.array(V) | |
B = np.dot(V, V.T) / lamb | |
n = len(V) | |
for t in range(m): | |
scores = [] | |
for i in range(n): | |
score = np.sum(B[:,i] ** 2) / (1. + B[i,i]) | |
scores += [(score, i)] | |
max_score, max_i = max(scores) | |
L += [max_i] | |
B = B - np.outer(B[:,max_i], B[:,max_i]) / (1. + B[max_i,max_i]) | |
return L | |
@staticmethod | |
def non(V, gamma, eps=1.e-8): | |
'''DSDR with nonnegative linear reconstruction | |
Parameters | |
========== | |
- V : 2d array_like, the candidate sentence set | |
- gamma : float, > 0, the trade off parameter | |
- eps : float, for converge | |
Returns | |
======= | |
- beta : 1d array, the auxiliary variable to control candidate sentences | |
selection | |
''' | |
V = np.array(V) | |
n = len(V) | |
A = np.ones((n,n)) | |
beta = np.zeros(n) | |
VVT = np.dot(V, V.T) # V * V.T | |
np.seterr(all='ignore') | |
while True: | |
_beta = np.copy(beta) | |
beta = (np.sum(A ** 2, axis=0) / gamma) ** .5 | |
while True: | |
_A = np.copy(A) | |
A *= VVT / np.dot(A, VVT + np.diag(beta)) | |
A = np.nan_to_num(A) # nan (zero divide by zero) to zero | |
if np.sum(A - _A) < eps: break | |
if np.sum(beta - _beta) < eps: break | |
return beta | |
if __name__ == '__main__': | |
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
import unittest | |
from dsdr import DSDR | |
class TestDSDR(unittest.TestCase): | |
def test_lin(self): | |
''' | |
>>> DSDR.lin(V, m=2, lamb=0.1) | |
[2, 4] | |
''' | |
V = [[1,0,0,0], | |
[0,1,0,0], | |
[1,1,0,0], | |
[0,0,1,0], | |
[0,0,1,1]] | |
L = DSDR.lin(V, m=2, lamb=0.1) | |
print L | |
# show summary | |
for i in L: | |
print V[i] | |
def test_non(self): | |
''' | |
>>> DSDR.non(V, gamma=0.1) | |
[ 0.49301097 0.49301097 0.6996585 0.49301097 0.70211699] | |
''' | |
V = [[1,0,0,0], | |
[0,1,0,0], | |
[1,1,0,0], | |
[0,0,1,0], | |
[0,0,1,1]] | |
beta = DSDR.non(V, gamma=0.1) | |
print beta | |
# show summary | |
for score, v in sorted(zip(beta, V), reverse=True): | |
print score, v | |
if __name__ == '__main__': | |
unittest.main() |
実験
あとで。
メモ
- 報知的要約。(cf. 指示的要約)
- LSAと似てる気がする。制約ついてるのがちょっと違うのかな。
- おもしろい。でも実装してみただけ。あとでちゃんと読む。
- テストの書き方がわからない。
- 訳し方がわからない。
No comments:
Post a Comment