36
Web本文抽出 using CRF 2010/7/4 中谷 秀洋@サイボウズ・ラボ

Web本文抽出 using crf

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Web本文抽出 using crf

Web本文抽出 using CRF

2010/7/4

中谷 秀洋@サイボウズ・ラボ

Page 2: Web本文抽出 using crf

本文抽出 for Project Gutenberg

• Project Gutenberg (http://gutenberg.org/)

– 著作権フリーテキストのデータベース

• 英語が主だが、最近は他の言語もぼちぼち

– コーパスの宝庫

• DVDのisoイメージがtorrentで配布されている

• テキストの前後にヘッダ・フッタが

– 分量多め&規則性無し。カオス!

– サボると頻出語の上位に“Gutenberg”

Page 3: Web本文抽出 using crf

パターン1

ここから本文

それっぽいセパレータ

Page 4: Web本文抽出 using crf

パターン2

ここから本文

それっぽいセパレータ

Page 5: Web本文抽出 using crf

パターン3

それっぽいセパレータ

本当はここから本文

ここから本文かと思いきや

Page 6: Web本文抽出 using crf

正規表現による切り出し

http://d.hatena.ne.jp/n_shuyo/20081118/gutenberg

Page 7: Web本文抽出 using crf

本文抽出 for Web

• ExtractContent for Ruby – Webページの本文抽出を行うRubyモジュール

• http://rubyforge.org/projects/extractcontent/

• http://labs.cybozu.co.jp/blog/nakatani/2007/09/web_1.html

– HTML::ExtractContent • Perl への移植&改良 by はてな

• Webページカテゴライズのために開発 – Pathtraq (http://pathtraq.com/)

• みんなのアクセスログで作るランキングサービス

– カテゴライズはナイーブベイズで

– 分類アルゴリズムより 本文抽出の方が精度への影響が大きい

Page 8: Web本文抽出 using crf

本文抽出の方が 精度への影響が大きい

Page 9: Web本文抽出 using crf

ノイズの少ない コーパス重要

Page 10: Web本文抽出 using crf

ExtractContentのアルゴリズム概略

• html をブロックに分割

• ブロックごとにスコアを計算 – 句読点が多い – 非リンクテキストが長い – 本文っぽくないフレーズが含まれている

• 連続するブロックを「大ブロック」にまとめる – スコアの高いものをつなげていく – スコアが低いとつながる確率は減衰していく

• スコアが最大となる「大ブロック」が本文

• 「ヒューリスティック」と言えば聞こえがいいが – 思いつきのアイデア+感覚による調整

Page 11: Web本文抽出 using crf

ExtractContentのコード(抜粋) module ExtractContent # Default option parameters. @default = { :threshold => 100, :min_length => 80, :decay_factor => 0.73, :continuous_factor => 1.62, :punctuation_weight => 10, :

# スコア算出 c = (notlinked.length + notlinked.scan(punctu.. factor *= decay_factor not_body_rate = block.scan(waste_expressions).. c *= (0.72 ** not_body_rate) if not_body_rate>0 c1 = c * continuous :

Page 12: Web本文抽出 using crf

ExtractContentの課題

• 本文おまけ問題 – 本文とその他の要素(関連記事リンク、コメント)が

<br> 区切りで続く場合に、それらを分離できない • 現行の方式で <br> でも区切ると、1つのブロック長が短く&

本文ブロック数が増えすぎてスコアの評価がうまくいかない

• 本文がない問題 – 「本文がない/極端に短い」ページで、出来るだけ長

いテキスト(≠本文)を抽出してしまう

– サイドバーに長文のレビューや自己紹介が書かれていて、そっちを抜いてしまうケースも。

• アプリごとに違うよ問題 – 「本文」として求める範囲がアプリによって違う

• 分類ではコメント不要。全文検索では必要。

Page 13: Web本文抽出 using crf

本文がない/短い

Page 14: Web本文抽出 using crf

ExtractContentのアルゴリズム概略(再)

• html をブロックに分割

• ブロックごとにスコアを計算 – 句読点が多い

– 非リンクテキストが長い ←素性

– 本文っぽくないフレーズが含まれている

• 連続するブロックを「大ブロック」にまとめる – スコアの高いものをつなげていく

– スコアが低いとつながる確率は減衰 ←転移確率

• スコアが最大となる「大ブロック」が【本文】 ←ラベル

どうみても「系列ラベリング」の問題

Page 15: Web本文抽出 using crf

系列ラベリング

• 系列に対してラベルを付与する

– 観測変数と隠れ変数が1対1に対応

• 様々な問題を解くための定式化の一つ

– 形態素解析

• 品詞推定

• 分かち書き

– 係り受け

– 音声認識

– DNA解析

I am a pen

代名詞 動詞 不定冠詞 名詞

観測変数

隠れ変数

Page 16: Web本文抽出 using crf

隠れマルコフモデル

– HMM(Hidden Markov Model) – Pettern Recognition and Machine Learning 13章

• 代表的な系列タギング手法の一つ

• 隠れ変数は(1次の)マルコフ連鎖をなす – 観測変数は対応する隠れ変数にのみ依存 – 観測変数間の条件付独立を仮定しない

• 高速な計算方法がある – Baum-Welch/Viterbi

• 教師無し

• 生成モデル

𝑥1 𝑥2 𝑥3 𝑥𝑛

𝑦1 𝑦2 𝑦3 𝑦𝑛

𝑝 𝑦𝑖+1 𝑦𝑖 と𝑝 𝑥𝑖 𝑦𝑖 から 𝑝(𝒙, 𝒚)と𝑝(𝒚|𝒙)を求める

Page 17: Web本文抽出 using crf

HMM の問題点

• 未知の観測値を扱うことが出来ない – p(X|Y) が値を持たないと計算できない

• 非独立/同時に起きうる素性を扱うことが出来ない – 「テキストが長い」と「句読点が多い」は同時に起きやすい

– 「<table>タグを含む」と「<ul>タグを含む」は非独立

• 大域的な最適性を得られない可能性がある – 分岐の少ない経路が選ばれやすい

• Label bias と Length bias

– 同じラベルを持つ系列の続く確率が指数的に減衰するため、「長い本文」が選ばれにくい • 局所的な条件付き確率の積によって尤度を求めるため

[Kudo+ 2004] より

Page 18: Web本文抽出 using crf

CRF(条件付き乱数場) » CRF (Conditional Random Fields)[Lafferty+ 2001]

• 系列ラベリングのための識別モデル – 無向グラフ/マルコフ確率場 [PRML 8章] – クリークに対しバイナリ素性 𝑓𝑘(𝑦𝑖−1, 𝑦𝑖 , 𝒙)を定義

• 例:「𝑥𝑖が大文字で始まる」かつ「𝑦𝑖が名詞」なら1

– 𝑝 𝒚 𝒙 ∝ exp 𝜆𝑘𝑓𝑘 𝑦𝑖−1, 𝑦𝑖 , 𝒙𝑘 より𝒚の推定を行う • 高速に計算するアルゴリズムがある(Forward/Backward)

• HMMより最適な系列を得やすい

• Mecabで利用

素性からエネルギー関数を定義、𝑝(𝒚|𝒙)を直接計算する

𝒙

𝑦1 𝑦2 𝑦3 𝑦𝑛 𝑦0 𝑦𝑛+1

Linear-chain CRF

Page 19: Web本文抽出 using crf

HMM と CRF の相違点

• Vapnikの原理:ある問題を解くとき,その問題よりも難しい問題を途中段階で解いてはならない

• "When solving a problem of interest, do not solve a more general problem as an intermediate step. Try to get the answer that you really need but not a more general one."

• http://en.wikipedia.org/wiki/Transduction_(machine_learning)

Hidden Markov Model Conditional Random Fields

状態空間モデル (有向グラフィカルモデル)

マルコフ確率場 (無向グラフィカルモデル)

生成モデル 識別モデル

教師無し 教師有り

𝑝(𝑥𝑖|𝑦𝑖)で記述できる素性 バイナリ素性を自由に設計

𝑝(𝒙, 𝒚)から𝑝(𝒚|𝒙)を計算 𝑝(𝒚|𝒙)を直接計算

計算量はどちらも O(素性数×状態数^2×系列長) だが、 CRFは素性数が爆発する傾向あり(bigramの素性=状態数^2)

Page 20: Web本文抽出 using crf

CRFのPython実装 » http://github.com/shuyo/iir/blob/master/sequence/crf.py

• Linear-chain CRF の学習&ラベリング実装 – 1つの素性に1つの観測値

• 簡略化というより 実装開始時の誤解から……

• [Lafferty+ 2001]のグラフが右図だった……

– scipy の BFGS を使ってパラメータを推論 • [Lafferty+ 2001] Forward/Backward • [Sutton+ 2006] gradient • L2正則化

– numpy/scipyにできる限り処理させる • ラベル数=11、素性数=700、学習データの系列長=2500でパ

ラメータ推論に4分 • 系列長=300のラベリングに4秒 • スクリプト言語のわりには?

• 実用より、「読める実装」としての値打ち?? – CRF処理部は 200行弱

Page 21: Web本文抽出 using crf

アプリケーション

Page 22: Web本文抽出 using crf

まずは Project Gutenbergで

試してみよう

Page 23: Web本文抽出 using crf

Project Gutenberg本文抽出 using CRF • 系列ラベリングの問題に定式化

– テキストの空行でパラグラフに分割 – パラグラフの系列に対し、 3種類のラベル H(ヘッダ)、

B(本文)、F(フッタ)を付与する

• 素性設計(素性数: 188) – 特徴的なキーワードが含まれているか

• Project, Gutenberg, David Reed, など

– 使われている文字種 • 大文字、数値、記号

– 先頭、末尾 • “*” が続いている、インデントされている

– 行数 • 3行以上ある、2行以上の空行で区切られている

• 学習データ=7(系列長=3300) • http://github.com/shuyo/iir/blob/master/sequence/pg.py

Page 24: Web本文抽出 using crf

実行例(パターン3)

• 正しく抽出(先頭が付与されたラベル)

H Project Gutenberg's Etext of Shakespeare's First Folio/35 Plays H Copyright laws are changing all over the world, be sure to check H Please take a look at the important information in this header. : ( 66 paragraphs) H If you find any scanning errors, out and out typos, punctuation H David Reed H Project Gutenberg's Etext of Shakespeare's First Folio/35 Plays B To the Reader. B This Figure, that thou here feest put, It was for gentle Shakesp B B.I. : ( 27143 paragraphs) B Cym. Laud we the Gods, And let our crooked Smoakes climbe to B Exeunt. B FINIS. THE TRAGEDIE OF CYMBELINE. F End of Project Gutenberg's Etext of Shakespeare's First Folio/35

長い系列でも 正しくラベリング

不規則な本文開始位置を 正しく判定

Page 25: Web本文抽出 using crf

CRFで Webページ本文抽出

Page 26: Web本文抽出 using crf

Web本文抽出 using CRF

• 系列ラベリングの問題に定式化 – htmlを閉じタグおよび<br>で分割、ブロックの系列を得る – ブロックの系列に9種類のラベル付けを行う

• head, header, menu, title, body, comment, linklist, cm, footer

• 素性設計(647個) – タグ(a/p/div/...) – キーワード(Copyright/会社概要/利用規約/など) – 句読点、日付、アフィリエイトリンク – テキスト長、リンクされているテキスト長

• 学習データ=15(系列長=2500)

• 素性設計以外にヒューリスティックな工夫はしない – script/style タグの除去のみ例外として行っている – Google AdSense Section Targetは無視

• 本文抽出における魔法のアイテム

• http://github.com/shuyo/iir/blob/master/extractcontent/webextract.py

Page 27: Web本文抽出 using crf

実行例(本文おまけ~Yahoo! Sports)

[head] <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" " [header] <body class="yj950-2"> <div id="wrapper"> <!--- header ---> [header] <div class="yjmth"> <div class="yjmthproplogoarea"><a href=htt [header] <div class="yjmthloginarea"><strong><a href="https://login.yaho : ( 29 blocks) [header] <li title="ニュース" class="active_click"><a href="/news"> [header] <li title="コラム" class="end"><a href="/column/">コラム</ [header] <!---/globalnavi---> <div id="contents-header"> <div id="cat-pa [title] <!--- body ---> <div id="contents-body"> <span class="yj-guid" [title] <em>サンケイスポーツ - 2009/7/9 7:52</em> </div> [body] <!----- article -----> <div class="Article clearfix"> <table [body] <p> (セ・リーグ、巨人3x-2横浜、11 [body] 一塁ベースを回っても、坂本は下を向いたま : ( 5 blocks) [body] 「チームにとっても彼にとっても大きな本塁 [body] 現役時代に何度もスランプを味わった原監督 [body] 【関連記事】<br /> [linklist] ・<a href="http://www.sanspo.com/baseball/news/090709/bsa09070 [linklist] ・<a href="http://www.sanspo.com/baseball/news/090709/bsa09070 [linklist] ・<a href="http://www.sanspo.com/baseball/news/090709/bsa09070 : ( 3 blocks) [linklist] <!-- anemos --> <!-- /anemos --> <div class="Kejiban"> <im

関連記事へのリンクを linklist として正しく分類

Page 28: Web本文抽出 using crf

実行例(はてなダイアリー)

[head] <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> [header] <body> <div id="simple-header"> <a href="http://www.hatena. : ( 9 paragraphs) [header] <p class="sectionheader"><span class="sectioncategory"><a hre [body] <p><a class="keyword" href="http://d.hatena.ne.jp/keyword/Py [body] <p>でも以下のように書くと、<a class="keyword" hr [body] <pre class="syntax-highlight"> <span class="synComment"># A, B, : ( 2 paragraphs) [body] <pre class="syntax-highlight"> labels = [&quot;<span class="syn [body] <p>そのせいで以下のようなハマりパターンも [body] <pre class="syntax-highlight"> <span class="synStatement">def</ [comment] <p class="sectionfooter"><a href="/n_shuyo/20100629/python"> [comment] <!-- google_ad_section_end --> </div> [comment] <form id="comment-form" method="post" action="/n_shuyo/comment : ( 14 paragraphs) [comment] <div class="refererlist"> <div class="caption"> [comment] <div class="refererlist"> <div class="caption"><a [linklist] <ul> <li><a href="http://d.ha [linklist] <div class="refererlist"> <div class="caption : ( 121 paragraphs)

コメントを分離 アプリごとに必要なラベルを

Page 29: Web本文抽出 using crf

実行例(Yahoo! Japan トップ)

[head] <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" " [menu] <body> <div id="wrapper"> <div id="header"> <div id="masthead" [menu] <ul id="mhicon"> <li id="mhi1st"><a title="Yahoo! BB" href="r/m [menu] <li id="mhi2nd"><a title="オークション" href="r/mauc">オ : ( 30 paragraphs) [menu] <li id="clr5"><a href="r/header/color/5/*-http://www.yahoo.co. [menu] <li id="clr6"><a href="r/header/color/6/*-http://www.yahoo.co. [menu] <p class="help"><a href="r/mht">ヘルプ</a></p></div> </div> < [linklist] <hr class="separate"> <div id="contents"> <div id="toptxt"> <u [linklist] <li id="toptxt2"><a href=s/69879>全国約1000件の花火大莨 [linklist] <li id="toptxt3"><a href=s/69950>新機能は?「ポケモン : ( 150 paragraphs) [linklist] <li><a title="Yahoo!ノートパッド" class="second" href="r/p [linklist] <li><a title="Yahoo!ブリーフケース" class="third" href="r [linklist] <div id="pbindexbg"><div id="pbindex"> <div id="pbcalendar"><di [footer] </tr> <tr> <td><a href="f/pbox/clndr/06/27/*-http://calendar.ya [footer] <td><a href="f/pbox/clndr/06/28/*-http://calendar.yahoo.co.jp/? [footer] <td><a href="f/pbox/clndr/06/29/*-http://calendar.yahoo.co.jp/? : ( 101 paragraphs) [footer] <li><a href="r/fdi">免責事項</a></li></ul> [footer] <address>Copyright (C) 2010 Yahoo Japan Corporation. All Rights [footer] </body> <!--http://ard.yahoo.co.jp/SIG=15blcke9p/M=300330001.

記事見出しや抜粋を linklist として正しく分類

Page 30: Web本文抽出 using crf

実行例(しょこたんブログ)

[head] <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " [menu] <body id="mainIndex"> <!--bodyTop--> <ul id="amebaBar"> <li id [menu] <li><a href="http://pigg.ameba.jp/" title="ピグ">ピグ</a></ [menu] <li class="last"><a href="http://blog.ameba.jp/ucs/entry/srvent : ( 167 paragraphs) [menu] <p><a href="http://blog.ameba.jp/reader.do?bnm=nakagawa-shoko"> [menu] <!--//.readerMainLink--> <div class="page articlePaging"> <a ti [menu] <!--TopPagingBottom--> <div class="entry new"> <div class="ent [cm] <!--//.entry_head--> <h3 class="title"><!-- google_ad_s [cm] <span class="theme">テーマ:<!-- google_ad_section_s [cm] <DIV>ぽこ(&lt;●&gt;&lt;●&gt;)メポぽん</DIV><DIV>&nbsp; : ( 33 paragraphs) [cm] <!--//#footer_ad--></div> [cm] <!--//#sub_main--> </div><!--//#main--> </div> [cm] <!--//#subFirstContentsArea--> </div> [linklist] <!--//#firstContentsArea--> <div id="sub_b"> <!--subBTop--> <!-- [linklist] “中川翔子物語~空色デイズ~”連載中<br [linklist] 原明日美 (著)<br> : ( 53 paragraphs) [linklist] <li><a href="http://ameblo.jp/nakagawa-shoko/theme-10014191488.

手強すなよ……

Page 31: Web本文抽出 using crf

参考

Page 32: Web本文抽出 using crf

CRFについて雑感

• CRFはおもしろい! – 非独立な素性を好きに設計できる

• 効果を見込めそうな素性を適当に放り込める

– 不必要な素性を選んでしまっても性能悪化しにくい • 職人技がなくても、それなりのものが作れる

– 期待していたより精度が高い • おもしろいものがいろいろ作れそう!!!

• CRFはまだちょっと難しい – こなれた解説がまだない

• エンジニアにはハードルが高い

– ライブラリはあるが研究用? • アプリからはまだ使いにくい

今回試した範囲での「感想」ですので、あしからず。

Page 33: Web本文抽出 using crf

CLEANEVAL: 本文抽出コンテスト

» http://cleaneval.sigwac.org.uk/

• 2007年に行われたWebページcleaning (本文抽出)のコンテスト – 英語と中国語の開発用データセット(約60件ずつ)

は現在もサイトで配布されている • テスト用データセットは約650件ずつあるらしいが、

配布されていない?

• あまり変な(=普通な)データはなさそう。 – 開発データセット120件中、「本文なし」は1件だけ

– ファイルサイズの最大は150KB

– 結果: • 中国語は参加1組。精度は18%……

• 英語は9組。精度の最高値は84%

Page 34: Web本文抽出 using crf

先行研究

• [Marek+ 2007] Web Page Cleaning with Conditional Random Fields – CLEANEVALで精度が一番高かったチーム – 今回紹介したのとだいたい同じ内容?

• 4日前に存在に気づいた。あえてまだ読んでない

– 評価はCLEANEVALのデータセット(英語)に対してのみ • 他の言語でもうまくいくの? • 現実には1MB超えるhtmlとかざらにあるんだけど

• 研究者にそこらへんのモチベーションはない – できることはわかってるけどやってない

• 「2chまとめ系ブログの本文抽出」で論文書けないし

– エンジニアが がんばる!

Page 35: Web本文抽出 using crf

機械学習をはじめたいエンジニアへ

• 「機械学習 はじめよう」 – gihyo.jpにて大絶賛(?)連載中!

• http://gihyo.jp/dev/serial/01/machine-learning

– 機械学習を知らない人、勉強してみたい人向け • チュートリアルではなく結構硬派に

• 数式ばんばん

– 実際に勉強し始めたらつまずきそうなところ • 独立とか、近似とか

• 事前分布とか、事後分布とか

– 次回第2回は 7/10 ごろ掲載予定

• 機械学習を初めてまだ1年のにわかですが、応援・ご教授いただけると嬉しいです

Page 36: Web本文抽出 using crf

References

• [Lafferty+ 2001] Conditional Random Fields: Probabilistic Models for Segmenting and Labeling Sequence Data

• [Sutton+ 2006] An Introduction to Conditional Random Fields for Relational Learning

• [Kudo+ 2004] Conditional Random Fieldsを用いた日本語形態素解析

• [Marek+ 2007] Web Page Cleaning with Conditional Random Fields

• 岡野原さんの「機械学習による自然言語処理チュートリアル~PerceptronからCRFまで~」 – http://hillbig.cocolog-nifty.com/do/2008/08/post_040f.html