textsearch jaで吉川三国志を読み解く
Upcoming SlideShare
Loading in...5
×
 

textsearch jaで吉川三国志を読み解く

on

  • 854 views

textsearch_jaを使って青空文庫の吉川三国志を分析してみたという、誰得な資料。

textsearch_jaを使って青空文庫の吉川三国志を分析してみたという、誰得な資料。

Statistics

Views

Total Views
854
Views on SlideShare
853
Embed Views
1

Actions

Likes
0
Downloads
2
Comments
0

1 Embed 1

http://www.slideee.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

textsearch jaで吉川三国志を読み解く textsearch jaで吉川三国志を読み解く Presentation Transcript

  • textsearch_ja で 三国志を読み解く ぬこ@横浜 (@nuko_yokohama)
  • まず・・・ 今回の話の前提
  • 三国志が嫌いな 男子なんていません!!!!! 最近は腐女子にも 人気があるようだが
  • 三国志の本は山ほどある 陳寿「三国志」 羅漢中「三国志演義」 元祖 吉川英治「三国志」 基本 時代劇 柴田錬三郎「柴錬三国志」 北方謙三「三国志」 呂布贔屓 八百長 陳舜臣「秘本三国志」「曹操 魏の曹一族」 宮城谷昌光「三国志」 未読 呉ファン向け 伴野朗「呉・三国志」 酒見賢一「泣き虫弱虫諸葛孔明」 読書中 パロディ 横山光輝「三国志」 ジャーンジャーン 王欣太「蒼天航路」 曹操主役 うちには多分 武論尊 / 池上遼一「覇 – Load 」 100 冊以上は トンデモ 転がっている・・・ etc ... 正史
  • さて
  • 昨年の秋くらいに 吉川英治「三国志」が 青空文庫化されました。 実に素晴らしい!
  • 吉川英治「三国志」 吉川英治が 1939 年から 1943 年まで 連載していた小説 三国志が日本に定着した要因には、この本の影響が大きい
  • 青空文庫とは ⇒Wikipedia 見て 要するに著作権が切れた文学作品を テキスト化してオープンにしたもの
  • 実は青空文庫は 長大な日本語テキストの サンプルとしても使える ⇒textsearch_ja の検証とか 青空文庫は昭和の頃の格調高い日本語のサンプルとしても重要。 また、形態素解析方式は、「壊れていない」日本語向き。 ネットスラングとか、ギャル語とかはかなり苦手・・・
  • 今日は、 PostgreSQL の 日本語形態素解析全文検索 textsearch_ja を使って 「吉川三国志」を分析した 結果を話します。
  • textsearch_ja PostgreSQL の形態素解析全文検索 形態素解析には Mecab を利用
  • 青空文庫版「三国志」を textsearch_ja で 使うための準備 (なお、今回は「序」は対象外)
  • 青空文庫のサイトから DL 10 個のテキストファイル SJIS なので UTF8 化する 先頭・末尾部分の削除 COPY 文形式への置換 章単位で行分割 ファイルのマージ
  • 実行環境 CentOS 6.3 PostgreSQL 9.3.2 textsearch_ja(patched) Mecab 0.994 9.3 上で動かすためには、 少しだけソースの 修正が必要 ( 補足参照 )
  • テーブル構成 sangokushi=# d List of relations Schema | Name | Type | Owner --------+-------------------+----------+-------public | sangokushi | table | harada public | sangokushi_id_seq | sequence | harada (2 rows) sangokushi=# d sangokushi Table "public.sangokushi" Column | Type | Modifiers ---------+---------+--------------------------------------------------------id | integer | not null default nextval('sangokushi_id_seq'::regclass) vol | text | chapter | text | body | text | Indexes: "idx" gin (to_tsvector('japanese'::regconfig, body)
  • テーブル構成(補足) vol : 巻名 chapter : 章名 body : 本文 本文を to_tsvector 型に変換する 関数 GIN インデックスを設定
  • 巻数: 10 総文字数:約 20 万字 章数: 314 1 章の平均字数:約 6200 文字 ⇒ だいたい TOAST 対象
  • 動作確認 sangokushi=# EXPLAIN ANALYZE SELECT id FROM sangokushi WHERE to_tsvector('japanese', body) @@ to_tsquery('japanese', ' 孔明 '); QUERY PLAN ----------------------------------------------------------------------------------------------------------------Bitmap Heap Scan on sangokushi (cost=16.01..137.36 rows=2 width=4) (actual time=0.048..0.072 rows=134 loops=1) Recheck Cond: (to_tsvector('japanese'::regconfig, body) @@ ''' 孔明 '''::tsquery) -> Bitmap Index Scan on idx (cost=0.00..16.01 rows=2 width=0) (actual time=0.039..0.039 rows=134 loops=1) Index Cond: (to_tsvector('japanese'::regconfig, body) @@ ''' 孔明 '''::tsquery) Total runtime: 0.103 ms (5 rows) sangokushi=# EXPLAIN ANALYZE SELECT count(id) FROM sangokushi WHERE body LIKE '% 孔明 %'; QUERY PLAN ---------------------------------------------------------------------------------------------------------------Aggregate (cost=773.93..773.94 rows=1 width=4) (actual time=34.806..34.806 rows=1 loops=1) -> Seq Scan on sangokushi (cost=0.00..773.92 rows=1 width=4) (actual time=13.361..34.763 rows=134 loops=1) Filter: (body ~~ '% 孔明 %'::text) Rows Removed by Filter: 180 Total runtime: 34.834 ms (5 rows) textsearch_ja を使った検索ではきちんと インデックスが使用されている。 このくらいのデータ量でも、 LIKE との性能差は明らか。
  • 今回の検証
  • textsearch_ja の 検索ランク取得関数 ts_rank_cd() を使って 主要登場人物の出現頻度を カウントしてグラフ化します
  • 検証を阻害する 意外な (?) 障壁
  • 障壁 1
  • 中国の人名が意外と厄介 Mecab 辞書に登録されてない 登場人物名が多い
  • 諸葛亮 「孔明」は登録 されてるのだが 例 わし、一応 主役なのに… 劉備 「劉備」は Mecab 辞書に 登録されていないのか、 「劉」と「備」で解析されてしまう。 しかも中国に「劉」姓は多い! 「劉備」「劉禅」「劉表」「劉虞」・・・
  • ということで、三国志検索用に Mecab 辞書を登録して かつ、検索されるような チューニングが必要になる
  • さすがに三国志に登場する 全キャラクターを登録すると 1000 人を超えちゃうので ホントに主要なキャラのみ 登録することに
  • こんな感じで Mecab ユーザ辞書を追加する 劉備 ,,,6000, 名詞 , 固有名詞 , 人名 , 名 ,*,*, りゅうび , リュウビ , リュービ 玄徳 ,,,6000, 名詞 , 固有名詞 , 人名 , 名 ,*,*, げんとく , ゲントク , ゲントク 諸葛亮 ,,,6000, 名詞 , 固有名詞 , 人名 , 名 ,*,*, しょかつりょう , ショカツリョウ , ショカツリョー 関羽 ,,,6000, 名詞 , 固有名詞 , 人名 , 名 ,*,*, かんう , カンウ , カンウ 雲長 ,,,6000, 名詞 , 固有名詞 , 人名 , 名 ,*,*, うんちょう , ウンチョウ , ウンチョー 張飛 ,,,6000, 名詞 , 固有名詞 , 人名 , 名 ,*,*, ちょうひ , チョウヒ , チョーヒ 翼徳 ,,,6000, 名詞 , 固有名詞 , 人名 , 名 ,*,*, よくとく , ヨクトク , ヨクトク (省略) 呂布 ,,,6000, 名詞 , 固有名詞 , 人名 , 名 ,*,*, りょふ , リョフ , リョフ 奉先 ,,,6000, 名詞 , 固有名詞 , 人名 , 名 ,*,*, ほうせん , ホウセン , ホーセン 張遼 ,,,6000, 名詞 , 固有名詞 , 人名 , 名 ,*,*, ちょうりょう , チョウリョウ , チョーリョー 文遠 ,,,6000, 名詞 , 固有名詞 , 人名 , 名 ,*,*, ぶんえん , ブンエン , ブンエン 袁紹 ,,,6000, 名詞 , 固有名詞 , 人名 , 名 ,*,*, えんしょう , エンショウ , エンショー 本初 ,,,6000, 名詞 , 固有名詞 , 人名 , 名 ,*,*, ほんしょ , ホンショ , ホンショ 貂蝉 ,,,6000, 名詞 , 固有名詞 , 人名 , 名 ,*,*, ちょうせん , チョウセン , チョーセン 赤兎馬 ,,,6000, 名詞 , 固有名詞 , 人名 , 名 ,*,*, せきとば , セキトバ , セキトバ これを Mecab 機能で コンパイル& 登録する 今回は数十人の主要人物名の「姓名」「姓字名」を登録した。 (ついでに赤兎馬も)
  • 障壁 2
  • 呼称のぶれ 「姓・名」 「姓・字名」 「姓・官職」 「諱」 の表記が混在している
  • 例 「劉備」「劉玄徳」「劉皇叔」 とりあえず「姓名」「姓字名」 のみ対応することにした ⇒ to_tsquery で OR 指定
  • こんな感じのクエリになる しばちゅうさん(司馬懿)の例 sangokushi=# SELECT id, left(substr(chapter,8),10) AS chapter, left(ts_headline('japanese',body, to_tsquery('japanese', ' 司馬懿 | 仲達 ')),30) AS body FROM sangokushi WHERE to_tsvector('japanese', body) @@ to_tsquery('japanese', ' 司馬懿 | 仲達 ') LIMIT 10; id | chapter | body -----+----------------------+------------------------------------------------------138 | 臨戦《りんせん》第一 | <b> 司馬懿 </b> 《しばい》、字を <b> 仲達 </b> 《ちゅ 208 | 剣《けん》と戟《ほこ | <b> 司馬懿 </b> 《しばい》 <b> 仲達 </b> 《ちゅうたつ 215 | 正月十五夜[#「正月 | <b> 司馬懿 </b><b> 仲達 </b> が、側で眉をひそめた。 225 | 漢中王《かんちゅうお | <b> 司馬懿 </b> 《しばい》、字《あざな》は <b> 仲達 </ 231 | 建業会議《けんぎょう | <b> 司馬懿 </b> 《しばい》 <b> 仲達 </b> 《ちゅうたつ 239 | 国葬[#「国葬」は大 | <b> 司馬懿 </b> 《しばい》、字《あざな》は <b> 仲達 </ 242 | 曹操《そうそう》死《 | <b> 司馬懿 </b> 《しばい》 <b> 仲達 </b> がそっと、枕 246 | 改元[#「改元」は大 | <b> 司馬懿 </b> 《しばい》 <b> 仲達 </b> があわてて、 259 | 魚紋[#「魚紋」は大 | <b> 司馬懿 </b> 《しばい》、字は <b> 仲達 </b> 《ちゅ 261 | 建艦総力[#「建艦総 | <b> 仲達 </b> は、「呉の守りは、長江を生命としています。
  • 障壁 3
  • ついつい本文を 読み耽ってしまうw 気づくと数巻分、 数時間くらい 経過することも屡々 検証中、結局全巻読み直したよ・・・
  • 検証結果 全巻スコア総計 章ごとの登場比率
  • 全巻スコア総計 名前 スコア総計 ランク総計 劉備 269.7 諸葛亮 209.4 董卓 関羽 142.5 呂布 曹操 285.1 陸遜 呂蒙 司馬懿 48.7 魯粛 張遼 23.6 周瑜 (孫家三代) 98.7 (孫家三代) 周瑜 48.5 司馬懿 魯粛 25.8 曹操 呂蒙 25.5 関羽 陸遜 25.5 諸葛亮 呂布 88.0 董卓 33.9 張遼 劉備 0.0 50.0 100.0 150.0 200.0 250.0 300.0
  • 全巻スコア総計 劉備・諸葛亮をおさえて、なんと曹操がトップに ● 曹操を単なる悪者にしていないのもポイント。 ●とはいえ、劉備・諸葛亮もさすがは主役級のスコア ● 武将の中でも関羽は別格だね・・・ ● 呂布は前半で消えちゃったから・・・ ● 中盤の好敵手・周瑜、終盤の好敵手・司馬懿も高めのスコア ●でも全般に呉はあまり書かれていない・・・ ● 劉備・曹操、諸葛亮の物語だからなのかな。 ●呉家三代の総計でも関羽に及ばない。 ●呉にも良い武将・軍師も多いけどリリーフ的だから・・・ ●
  • 章ごとの登場比率 吉川三国志 主要人物 / 章別 ランク比率 100% 90% 80% 70% 董卓 呂布 周瑜 孫家 司馬懿 曹操 孔明 関羽 劉備 60% 50% 40% 30% 20% 10% 0% 6 16 26 36 46 56 66 76 86 96 106 116 126 136 146 156 166 176 186 196 206 216 226 236 246 256 266 276 286 296 306 1 11 21 31 41 51 61 71 81 91 101 111 121 131 141 151 161 171 181 191 201 211 221 231 241 251 261 271 281 291 301 311
  • ストーリーと比較するとこんな感じに 虎牢関 小覇王 呂布の最期 赤壁 周瑜の最期 夷陵 出師の表 吉川三国志 主要人物 / 章別 ランク比率 100% 90% 80% 70% 董卓 呂布 周瑜 孫家 司馬懿 曹操 孔明 関羽 劉備 60% 50% 40% 30% 20% 10% 0% 6 16 26 36 46 56 66 76 86 96 106 116 126 136 146 156 166 176 186 196 206 216 226 236 246 256 266 276 286 296 306 1 11 21 31 41 51 61 71 81 91 101 111 121 131 141 151 161 171 181 191 201 211 221 231 241 251 261 271 281 291 301 311 桃園の誓い 連環の計 関羽千里行 関羽の最期 曹操の最期 南蛮行 五丈原
  • 章ごとの登場比率 冒頭の主役は劉備と関羽 ( と張飛 ) ● 曹操も出てくるけど、そこまで目立たない ● 序盤での呂布の暴れっぷり ●中盤の主役は実は曹操なのだな ●終盤の主役は勿論、諸葛亮と司馬懿 ●呉(笑) ● 小覇王の時代や赤壁など見せ場はあるけどさ ●
  • ということで、 textsearch_ja を使って 誰得な分析をしてみました。
  • そして 三国志は やっぱり面白い
  • おしまい
  • 補足 textsearch_ja は 9.0 以降、正式な対応が止まっている。 ●現状は EXTENSION に対応していない。 ●9.2 以降だと、 DL したファイルそのままだと、インストール 時に失敗するので、 LANGUAGE='C' を LANGUAGE=c など に変更する必要がある。 ●9.3 上で動かす場合、 textsearch_ja.c に #include "access/htup_details.h" の行を追加しないとビルド時に警告がでる。 ●また、上記の対処をしないと、 ja_analyze() で異常終了する ことがある。 ●