Successfully reported this slideshow.
Your SlideShare is downloading. ×

プログラマのための文書推薦入門

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Loading in …3
×

Check these out next

1 of 77 Ad

プログラマのための文書推薦入門

Download to read offline

勤務先の社内勉強会での発表資料です。自然言語処理の基本として TF-IDF ベースの類似文書推薦について説明します。発展的な内容として LDA についても簡単に説明します。Wikipedia の要約データを対象として実際にコードを書いて文書推薦を試みます。

勤務先の社内勉強会での発表資料です。自然言語処理の基本として TF-IDF ベースの類似文書推薦について説明します。発展的な内容として LDA についても簡単に説明します。Wikipedia の要約データを対象として実際にコードを書いて文書推薦を試みます。

Advertisement
Advertisement

More Related Content

Slideshows for you (20)

Similar to プログラマのための文書推薦入門 (20)

Advertisement

More from y-uti (20)

Recently uploaded (20)

Advertisement

プログラマのための文書推薦入門

  1. 1. プログラマのための 文書推薦入門 2014/6/20 社内勉強会資料 1
  2. 2. はじめに スライドに出てくるスクリプトは GitHub に置いてあります ◦ https://github.com/y-uti/document-recommendation 2014/6/20 社内勉強会資料 2
  3. 3. 文書推薦とは ユーザが「読みたい」と思うような文書を提示する コンテンツベース ◦ 文書の内容そのものを利用する方法 ◦ メタデータを使う(同じ著者の書籍など) ◦ テキスト解析(内容が似ている文書を提示) 協調フィルタリング ◦ 文書とその他の情報との関係を利用する方法 ◦ 「この本を読んだ人はこんな本も読んでいます」というアレ ◦ テキスト解析の推薦を理解すればこれも簡単 2014/6/20 社内勉強会資料 3
  4. 4. 都道府県庁間の距離 問題:日本の都道府県を東京から近い順に並べなさい できますか? 2014/6/20 社内勉強会資料 4
  5. 5. 都道府県庁間の距離 問題:日本の都道府県を東京から近い順に並べなさい プログラマなら簡単ですよね! 1. 都道府県庁の緯度、経度を調べる 2. 東京都庁からの距離を計算する 3. 距離の近い順にソートする 参考:都道府県庁間の距離(国土地理院) ◦ http://www.gsi.go.jp/KOKUJYOHO/kenchokan.html 2014/6/20 社内勉強会資料 5
  6. 6. 文書間の距離 問題:Wikipedia のページを「東京」から近い順に並べなさい ◦ http://ja.wikipedia.org/wiki/東京 できますか? 2014/6/20 社内勉強会資料 6
  7. 7. 文書間の距離 問題:Wikipedia のページを「東京」から近い順に並べなさい ◦ http://ja.wikipedia.org/wiki/東京 プログラマなら簡単ですよね! 1. Wikipedia の各ページの座標を調べる 2. 「東京」ページからの距離を計算する 3. 距離の近い順にソートする えっ? 2014/6/20 社内勉強会資料 7
  8. 8. 文書間の距離 問題:Wikipedia のページを「東京」から近い順に並べなさい ◦ http://ja.wikipedia.org/wiki/東京 プログラマなら簡単ですよね! 1. Wikipedia の各ページの座標を調べる 2. 「東京」ページからの距離を計算する 3. 距離の近い順にソートする Wikipedia の各ページの座標??? 2014/6/20 社内勉強会資料 8
  9. 9. 問題の整理 文書の「座標」とは何か? それさえ決まれば、あとは距離を計算してソートするだけ というわけで・・・ 文書推薦の本質は以下の関数を実装する問題にほかならない 2014/6/20 社内勉強会資料 9 double[] documentToPosition (String document) { ... } ◦ 文書を受け取って ◦ 座標を返す
  10. 10. 特徴抽出 「座標」のことを「特徴量」と言う ◦ 特徴ベクトルと言ったりもするが同じだと思っておいて構わない 特徴量 ◦ オブジェクトの特徴を表現する double[] 型の値 ◦ 文書 = String オブジェクト ◦ 座標 = double[] 特徴抽出 ◦ オブジェクトから特徴量を取り出すこと 2014/6/20 社内勉強会資料 10
  11. 11. 文書の特徴量の決め方 問題による ◦ 何をもって「近い」ことにしたいのか もう一度問題を読み返してみましょう ◦ Wikipedia のページを「東京」から近い順に並べなさい そもそも「近い」の仕様が曖昧だ。だからといって・・・ ◦ 駄目PG: 最終更新日時の近い順でいいスか? ◦ お客さま: 馬鹿にしてんのか! ではどのように定義すればよいか? 2014/6/20 社内勉強会資料 11
  12. 12. TF-IDF による文書推薦 2014/6/20 社内勉強会資料 12
  13. 13. TF-IDF 文書の特徴量として使われる「定番」 どのような単語が使われているか = 文書の特徴を表す 似たような言葉が出てくる文書なら似てるだろうという発想 2014/6/20 社内勉強会資料 13
  14. 14. Term Frequency 文書中にどのような単語が何回現れるか ◦ TF が大きい = その文書が強く伝えたい単語 例文「李も桃も桃のうち」 2014/6/20 社内勉強会資料 14 単語 TF 李 1 も 2 桃 2 の 1 うち 1
  15. 15. Document Frequency 文書群の全体のなかで、単語がいくつの文書にあらわれるか ◦ DF が小さい = ごく一部の文書でしか使われない特徴的な単語 例文「李も桃も桃のうち」 2014/6/20 社内勉強会資料 15 単語 TF DF 李 1 7 も 2 1,045 桃 2 1 の 1 4,709 うち 1 113 ただし文書群として Wikipedia 要約から抽出した 5,000 記事を利用
  16. 16. TF-IDF TF ÷ DF で計算される値 ◦ IDF = Inverse Document Frequency 例文「李も桃も桃のうち」 2014/6/20 社内勉強会資料 16 単語 TF DF TF-IDF 李 1 7 0.1429 も 2 1,045 0.0019 桃 2 1 2.0000 の 1 4,709 0.0002 うち 1 113 0.0885
  17. 17. TF-IDF の座標としての解釈 日本語のすべての単語を考える ◦ たとえば・・・広辞苑第六版の収録項目数 24 万語 それらの単語に通し番号をつける 文書の TF-IDF を 24 万要素の double[] で表現できる ◦ 文書に現れない単語は TF = 0 だから TF-IDF = 0 文書を 24 万次元空間上の点として表すことができた 2014/6/20 社内勉強会資料 17
  18. 18. 高次元空間について 24 万次元空間って SF 的な話? ◦ 違います 日常的なイメージで考えはじめたら・・・ ◦ 1 次元 = 直線 ◦ 2 次元 = 平面 ◦ 3 次元 = 空間 ◦ 4 次元 = 時空? ◦ 5 次元 = ???? ◦ 240,000 次元 = ????????????? 負け 2014/6/20 社内勉強会資料 18
  19. 19. 空間と点の関係 プログラマならオブジェクト指向はわかりますよね! 2014/6/20 社内勉強会資料 19 class Point2D { double x; double y; Point2D(double x, double y) { this.x = x; this.y = y; } } Point2D p = new Point2D(1, 2); ◦ Point2D クラス = 二次元空間 ◦ そのインスタンス p = 二次元空間上の点
  20. 20. 三次元空間 簡単ですよね 2014/6/20 社内勉強会資料 20 class Point3D { double x; double y; double z; Point3D(double x, double y, double z) { this.x = x; this.y = y; this.z = z; } }
  21. 21. 二十四万次元空間 じゃあこれも簡単ですよね 2014/6/20 社内勉強会資料 21 class Point240000D { double x1; double x2; ... double x240000; Point240000D(double x1, double x2, ..., double x240000) { this.x1 = x1; this.x2 = x2; ... this.x240000 = x240000; } }
  22. 22. 二十四万次元空間 まあ普通は配列を使うでしょう 2014/6/20 社内勉強会資料 22 class Point240000D { double[] x; Point240000D(double[] x) { this.x = new double[240000]; for (int i = 0; i < 240000; i++) { this.x[i] = x[i]; } } }
  23. 23. 二十四万次元空間 よく考えてみたら配列そのもので十分でした 2014/6/20 社内勉強会資料 23 double[] p = new double[240000]; p[getId("李")] = 0.1429; p[getId("も")] = 0.0019; p[getId("桃")] = 2.0000; p[getId("の")] = 0.0002; p[getId("うち")] = 0.0885; ◦ というわけで 24 万要素の配列 = 24 万次元空間の点 N 次元空間と言われたら N 要素の配列を考えればよい ◦ N 次元配列ではないことに注意
  24. 24. 文書間の距離 問題:Wikipedia のページを「東京」から近い順に並べなさい ◦ http://ja.wikipedia.org/wiki/東京 プログラマなら簡単ですよね! 1. Wikipedia の各ページの座標を調べる 2. 「東京」ページからの距離を計算する 3. 距離の近い順にソートする 24 万次元空間で 2 点間の距離を計算する 2014/6/20 社内勉強会資料 24
  25. 25. 二点間の距離 距離の計算だけは数学から逃れられない ◦ 三平方の定理 2014/6/20 社内勉強会資料 25 P1(x1,y1) P2(x2,y2) y2-y1 x2-x1 sqrt( pow(x2-x1, 2) + pow(y2-y1, 2) )
  26. 26. 二点間の距離 三次元 三次元でも計算方法は変わらない 2014/6/20 社内勉強会資料 26 P1(x1,y1,z1) P2(x2,y2,z2) x2-x1 y2-y1 z2-z1 sqrt( pow(x2-x1, 2) + pow(y2-y1, 2) + pow(z2-z1, 2) )
  27. 27. 二点間の距離 24 万次元 24 万次元でも計算方法は変わらない 2014/6/20 社内勉強会資料 27 double calcDistance(double[] a, double[] b) { double distance = 0; for (int i = 0; i < 240000; ++i) { distance += pow(b[i] – a[i], 2); } return sqrt(distance); } ◦ 次元数に応じてループの回数が増えるだけ
  28. 28. 文書間の距離 問題:Wikipedia のページを「東京」から近い順に並べなさい ◦ http://ja.wikipedia.org/wiki/東京 プログラマなら簡単ですよね! 1. Wikipedia の各ページの座標を調べる 2. 「東京」ページからの距離を計算する 3. 距離の近い順にソートする プログラマなら楽勝だろうから省略 2014/6/20 社内勉強会資料 28
  29. 29. TF-IDF で文書推薦を試す 2014/6/20 社内勉強会資料 29
  30. 30. Wikipedia 要約の取得 日本語 Wikipedia のデータベースからダウンロード ◦ http://dumps.wikimedia.org/jawiki/ 2014/6/20 社内勉強会資料 30 $ wget http://dumps.wikimedia.org/jawiki/latest/jawiki- latest-abstract.xml ◦ データは巨大なので注意しましょう(2014-05-21 版で 1.4 GB) $ head –n 5 jawiki-latest-abstract.xml <feed> <doc> <title>Wikipedia: アンパサンド</title> <url>http://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%B3%E3%83% 91%E3%82%B5%E3%83%B3%E3%83%89</url> <abstract>right|thumb|100px|[[Trebuchet MS フォン ト]]</abstract>
  31. 31. テキストの抽出 ダウンロードした XML ファイルから必要な情報を切り出す ◦ 何が必要かは処理内容に応じて考える ◦ 今回の用途では「見出し」と「要約」を使う 2014/6/20 社内勉強会資料 31 $ grep -B2 '<abstract>' jawiki-latest-abstract.xml | grep '^<[ta]' >a.tmp $ grep '^<t' a.tmp | cut -f2- -d' ' | sed 's,<[^>]*>$,,' >title.txt $ grep '^<a' a.tmp | sed 's/<[^>]*>//g' >abstract.txt $ rm a.tmp ◦ scripts/extract_title_abstract.sh を参照
  32. 32. ちょっと小さく・・・ データが大きすぎて大変なので説明用に小さくする ◦ 要約が 100 字以上ある記事に絞り込む ◦ その中から 5,000 記事を選ぶ 2014/6/20 社内勉強会資料 32 $ awk '{ print length($0) >= 100 }' abstract.txt >a.tmp $ expr $(grep 1 a.tmp | wc -l) / 5000 24 $ awk '{ print $1 && ++i % 24 != 0 }' a.tmp >b.tmp $ paste b.tmp title.txt | grep ^1 | cut -f2- | head -n 5000 >title-5000.txt $ paste b.tmp abstract.txt | grep ^1 | cut -f2- | head -n 5000 >abstract-5000.txt $ rm a.tmp b.tmp ◦ scripts/shrink_data.sh を参照
  33. 33. ここまでの確認 Wikipedia から見出しと要約を 5,000 記事分だけ抽出した 2014/6/20 社内勉強会資料 33 $ wc -l *-5000.txt 5000 abstract-5000.txt 5000 title-5000.txt 10000 合計 $ paste title-5000.txt abstract-5000.txt | head -n 1000 | tail -n 1 | sed 's/¥t/¥n/' 講座派 講座派(こうざは)とは、日本資本主義論争において労農派と対抗した マルクス主義者の一派。岩波書店から1930年代前半に出版された、『日 本資本主義発達史講座』を執筆したグループが中心となったのでこう呼 ばれる。
  34. 34. 単語分割 TF-IDF は「単語」に注目した特徴量 ところが日本語の文は単語ごとに区切られていない 文を単語に分割する前処理が必要 ◦ 英語圏の人たちよりも一手間かかる 2014/6/20 社内勉強会資料 34
  35. 35. MeCab MeCab ◦ http://mecab.googlecode.com/svn/trunk/mecab/doc/index.html ◦ 定番の形態素解析器 形態素解析とは? 2014/6/20 社内勉強会資料 35 $ echo 'すもももももももものうち' | mecab すもも スモモ スモモ 李 名詞-普通名詞-一般 も モ モ も 助詞-係助詞 もも モモ モモ 桃 名詞-普通名詞-一般 も モ モ も 助詞-係助詞 もも モモ モモ 桃 名詞-普通名詞-一般 の ノ ノ の 助詞-格助詞 うち ウチ ウチ 内 名詞-普通名詞-副詞可能 EOS
  36. 36. Wikipedia 要約の単語分割 Wikipedia の要約データを MeCab で単語分割する 2014/6/20 社内勉強会資料 36 $ mecab -Owakati abstract-5000.txt >wakati.txt $ head -n 1000 wakati.txt | tail -n 1 講座 派 ( こう ざ は ) と は 、 日本 資本 主義 論争 に おい て 労農 派 と 対抗 し た マルクス 主義 者 の 一派 。 岩波 書店 から 1 9 3 0 年 代 前半 に 出版 さ れ た 、 『 日本 資本 主義 発達 史 講座 』 を 執筆 し た グループ が 中心 と なっ た の で こう 呼ば れる 。 ◦ -Owakati を指定すると区切った結果だけを出力してくれる
  37. 37. Wikipedia 要約の TF Wikipedia の要約 5,000 記事の TF を計算する 2014/6/20 社内勉強会資料 37 $ php ../scripts/calculate_tf.php <wakati.txt >tf.txt $ head -n 1000 tf.txt | tail -n 1 講座 2 派 2 ( 1 こう 2 ざ 1 は 2 ) 1 と 3 、 2 日本 2 資本 2 主義 3 論争 1 に 2 おい 1 て 1 労農 1 対抗 1 し 2 た 4 マル クス 1 者 1 の 2 一派 1 。 2 岩波 1 書店 1 から 1 1 1 9 1 3 1 0 1 年 1 代 1 前半 1 出版 1 さ 1 れ 1 『 1 発達 1 史 1 』 1 を 1 執筆 1 グループ 1 が 1 中心 1 なっ 1 で 1 呼ば 1 れる 1 ◦ 分かち書きされた各単語に出現回数を付加 ◦ 単語 回数 単語 回数・・・の繰り返し
  38. 38. Wikipedia 要約の DF Wikipedia の要約 5,000 記事に対する各単語の DF を計算する 2014/6/20 社内勉強会資料 38 ◦ tf.txt 中の単語の出現回数を数える(いくつの文書に出てきたか) ◦ 各行の内容は「単語 出現文書数」 ◦ 全部で 34,116 単語あった (34,116 次元の空間になる) $ php ../scripts/calculate_df <tf.txt >df.txt $ wc -l df.txt 34116 df.txt $ head -n 1000 df.txt | tail -n 20 | column -c 70 敵 4 人数 2 ほど 18 遊び 4 ぶつける 1 避 1 メジャー 11 ルール 10 スポーツ 42 球 3 学校 155 各地 17 チーム 52 飛球 1 協会 86 独特 5 分かれ 11 表記 139 JDBA 1 感覚 8
  39. 39. Wikipedia 要約の TF-IDF 5,000 記事それぞれの TF から DF を使って TF-IDF を計算する 2014/6/20 社内勉強会資料 39 $ php ../scripts/calculate_tfidf.php tf.txt df.txt >tfidf.txt $ head -n 1000 tfidf.txt | tail -n 1 講座 0.28571428571429 派 0.052631578947368 ( 0.00022988505747126 こう 0.014285714285714 ざ 0.083333333333333 は 0.00040551500405515 ) 0.00022983222247759 と 0.00096184674575184 、 0.00041262636682484 日本 0.002247191011236 資本 0.14285714285714 主義 0.04 論争 0.14285714285714 に 0.00051072522982635 おい 0.0031948881789137 て 0.00035161744022504 労農 1 対抗 0.071428571428571 し 0.00078400627205018 た 0.0013110455588332 マルクス 0.083333333333333 者 0.0017636684303351 の 0.00042471862391166 一派 0.33333333333333 。 0.00040609137055838 岩波 0.066666666666667 書店 0.037037037037037 から 0.00081366965012205 1 0.0003404834865509 9 0.00049407114624506 3 0.0006150061500615 0 0.00050556117290192 年 0.00038270187523919 代 0.0044642857142857 前半 0.058823529411765 出版 0.016129032258065 さ 0.00049554013875124 れ 0.00050327126321087 『 0.0012062726176116 発達 0.083333333333333 史 0.025641025641026 』 0.0012254901960784 を 0.00034904013961606 執筆 0.076923076923077 グルー プ 0.011904761904762 が 0.00043763676148797 中心 0.0075757575757576 なっ 0.0031948881789137 で 0.00026504108136761 呼ば 0.0036496350364964 れる 0.0010799136069114 ◦ 単語 TF-IDF 単語 TF-IDF・・・の繰り返し
  40. 40. ここまでの確認 Wikipedia から抽出した 5,000 記事の特徴量 (TF-IDF) を計算した 2014/6/20 社内勉強会資料 40 $ head -n 1000 tfidf.txt | tail -n 1 |¥ awk '{ for (i=1; i<=NF; i+=2) print $i, $(i+1); }' |¥ sort -nrsk2,2 |¥ head | column -c 80 労農 1 ざ 0.083333333333333 一派 0.33333333333333 マルクス 0.083333333333333 講座 0.28571428571429 発達 0.083333333333333 資本 0.14285714285714 執筆 0.076923076923077 論争 0.14285714285714 対抗 0.071428571428571
  41. 41. 文書間の距離 記事の間の距離を計算する 2014/6/20 社内勉強会資料 41 $ head -n 210 abstract-5000.txt | tail -n 1 普遍論争(ふへんろんそう)とは、スコラ哲学において「普遍は存在す るか」という問いをめぐって争われた哲学上・神学上の論争の一つであ る。これと内容的に同じ議論が、古代から続いており、近代哲学や現代 の哲学でも形を変えて問題となっている。「普遍概念」をめぐる論争と して、中世の論争を特にこの名で呼ぶ。 $ head -n 1000 abstract-5000.txt | tail -n 1 講座派(こうざは)とは、日本資本主義論争において労農派と対抗した マルクス主義者の一派。岩波書店から1930年代前半に出版された、『日 本資本主義発達史講座』を執筆したグループが中心となったのでこう呼 ばれる。
  42. 42. 文書間の距離 TF-IDF 同士の距離を数式どおりに計算 2014/6/20 社内勉強会資料 42 単語 TF-IDF 講座派 TF-IDF 普遍論争 TF-IDF の差 労農 1.000 1.000 スコラ 1.000 1.000 一派 0.333 0.333 普遍 0.750 0.750 講座 0.286 0.285 資本 0.143 0.143 論争 0.143 0.571 0.428 ・・・ ・・・ ・・・ ・・・ 合計
  43. 43. 文書間の距離 TF-IDF 同士の距離を数式どおりに計算 2014/6/20 社内勉強会資料 43 単語 TF-IDF の差 差の二乗 文書間距離 労農 1.000 1.000 スコラ 1.000 1.000 一派 0.333 0.111 普遍 0.750 0.563 講座 0.285 0.081 資本 0.143 0.020 論争 0.428 0.183 ・・・ ・・・ ・・・ 合計 5.250 2.291
  44. 44. 文書推薦 基準にする記事と各記事との距離を計算 距離の近い順に並べる 2014/6/20 社内勉強会資料 44 $ (head -n 1000 tfidf.txt | tail -n 1; cat tfidf.txt) |¥ php ../scripts/calculate_distance.php |¥ paste - title-5000.txt | sort -gsk1,1 | head 0 講座派 1.1319673488822 風の谷のナウシカ (映画) 1.134464051046 1977年のJSL 1.13839530087 ピアノソナタ第2番 1.13839530087 ピアノソナタ第15番 1.1417322424834 ニンテンドーDSi 1.1491742960789 第26回全日本中学校陸上競技選手権大会 ◦ あれ?何だか全然似ていないような・・・
  45. 45. 何がいけなかったのか 大事なことを二回言うと TF-IDF が変わる 2014/6/20 社内勉強会資料 45 李も桃も桃のうち 李も桃も桃のうち 李も桃も桃のうち ◦ 同じことを繰り返すだけで距離が離れてしまう ◦ 一般的には長い文書ほど TF-IDF が大きくなる
  46. 46. 特徴量の正規化 TF-IDF を同じ大きさに揃えてから計算する 2014/6/20 社内勉強会資料 46 李も桃も桃のうち = 李も桃も桃のうち 李も桃も桃のうち = 李も桃も桃のうち ◦ すべての点を円周上に移動する ◦ 原点から見て「どの方向にあるか」だけを考える
  47. 47. 改めて文書推薦 各記事の TF-IDF の大きさを 1 に揃えてから距離を計算する 2014/6/20 社内勉強会資料 47 $ php ../scripts/normalize_tfidf.php <tfidf.txt >norm.txt $ (head -n 1000 norm.txt | tail -n 1; cat norm.txt) |¥ php ../scripts/calculate_distance.php |¥ paste - title-5000.txt | sort –gsk1,1 | head 0 講座派 1.3471710592443 文化放送日曜深夜0時枠 1.3870131943576 アッセンブリーズ・オブ・ゴッド 1.3888849645415 普遍論争 1.3892983597792 コラショ 1.3922523642743 長福寺 (名古屋市緑区) 1.3947875194068 民法典論争 1.3983797117905 南京大虐殺論争 1.3992487750453 第12回全日本都市対抗バレーボール優勝大会
  48. 48. 距離計算の高速化 TF-IDF の大きさを 1 に揃えることで距離計算を高速化できる ◦ 点 A (a1, a2, a3, …, aN) と点 B (b1, b2, b3, …, bN) の距離は・・・ 2014/6/20 社内勉強会資料 48 sum = 0; for (i = 0; i < N; i++) { sum += pow(b[i] – a[i], 2); } sum = sqrt(sum); ◦ pow の部分を展開すると・・・ sum = 0; for (i = 0; i < N; i++) { sum += b[i]*b[i] – 2*a[i]*b[i] + a[i]*a[i]; } sum = sqrt(sum);
  49. 49. 距離計算の高速化 TF-IDF の大きさを 1 に揃えることで距離計算を高速化できる ◦ pow の部分を展開すると・・・ 2014/6/20 社内勉強会資料 49 sum = 0; for (i = 0; i < N; i++) { sum += b[i]*b[i] – 2*a[i]*b[i] + a[i]*a[i]; } sum = sqrt(sum); ◦ ばらばらに足してみると・・・ sum = 0; for (i = 0; i < N; i++) sum += b[i]*b[i]; for (i = 0; i < N; i++) sum –= 2*a[i]*b[i]; for (i = 0; i < N; i++) sum += a[i]*a[i]; sum = sqrt(sum);
  50. 50. 距離計算の高速化 TF-IDF の大きさを 1 に揃えることで距離計算を高速化できる ◦ ばらばらに足してみると・・・ 2014/6/20 社内勉強会資料 50 ◦ 大きさを 1 に揃えたのだから・・・ sum = 0; for (i = 0; i < N; i++) sum += b[i]*b[i]; for (i = 0; i < N; i++) sum –= 2*a[i]*b[i]; for (i = 0; i < N; i++) sum += a[i]*a[i]; sum = sqrt(sum); sum = 0; sum += 1; for (i = 0; i < N; i++) sum –= 2*a[i]*b[i]; sum += 1; sum = sqrt(sum);
  51. 51. 距離計算の高速化 TF-IDF の大きさを 1 に揃えることで距離計算を高速化できる ◦ 大きさを 1 に揃えたのだから・・・ 2014/6/20 社内勉強会資料 51 ◦ ここまでを整理すると・・・ sum = 0; sum += 1; for (i = 0; i < N; i++) sum –= 2*a[i]*b[i]; sum += 1; sum = sqrt(sum); sum = 2; for (i = 0; i < N; i++) sum –= 2*a[i]*b[i]; sum = sqrt(sum);
  52. 52. 距離計算の高速化 TF-IDF の大きさを 1 に揃えることで距離計算を高速化できる ◦ ここまでを整理すると・・・ 2014/6/20 社内勉強会資料 52 ◦ 距離そのものを計算しなくても大小関係が分かればよいので・・・ sum = 2; for (i = 0; i < N; i++) sum –= 2*a[i]*b[i]; sum = sqrt(sum); sum = 0; for (i = 0; i < N; i++) sum += a[i]*b[i]; ◦ これを大きな順に並べれば距離の近い順と同じになる ◦ a[i]*b[i] という形の計算しか残っていないのがポイント ◦ TF-IDF がどちらも 0 ではない単語だけ計算すればよい
  53. 53. コサイン類似度 (高校レベル) 最後の式で計算される値をベクトルの内積と言う 2014/6/20 社内勉強会資料 53 sum = 0; for (i = 0; i < N; i++) sum += a[i]*b[i]; a と b の原点からの距離が 1 のときは 「コサイン類似度」とも言う θ cos(θ) a b
  54. 54. コサイン類似度で文書推薦 距離ではなくコサイン類似度で計算する 2014/6/20 社内勉強会資料 54 $ (head -n 1000 norm.txt | tail -n 1; cat norm.txt) |¥ php ../scripts/calculate_cosine_similarity.php |¥ paste - title-5000.txt | sort –grsk1,1 | head 0.99999999999999 講座派 0.092565068567332 文化放送日曜深夜0時枠 0.038097199338955 アッセンブリーズ・オブ・ゴッド 0.035499277635225 普遍論争 0.03492503375735 コラショ 0.030816677086338 長福寺 (名古屋市緑区) 0.027283887853535 民法典論争 0.022267090826318 南京大虐殺論争 0.021051432767109 第12回全日本都市対抗バレーボール優勝大会 ◦ 距離で計算した結果と順位は変わらない(値は変わる)
  55. 55. 発展:次元削減 2014/6/20 社内勉強会資料 55
  56. 56. 動機 特徴量の空間の次元数を小さくしたい TF-IDF の例では簡単に数万次元になる 2014/6/20 社内勉強会資料 56
  57. 57. アドホックな手法 文書推薦では距離の近い順に文書をソートした ◦ 正確な距離を求める必要はない ◦ 順序だけ分かればよい 距離の計算に影響が少ない単語は捨ててしまっていいだろう 注意 ◦ 何を捨ててよいかは問題に依存する 2014/6/20 社内勉強会資料 57
  58. 58. ストップワード どんな文書にも出てくるような一般的な単語 ◦ 日本語なら「てにをは」など ◦ 専門用語で「ストップワード」という なぜ捨てるのか ◦ TF-IDF は DF で割り算するので DF の大きな単語はゴミ ◦ 大半の文書で TF-IDF > 0 になるので距離計算の高速化に効果絶大 2014/6/20 社内勉強会資料 58
  59. 59. 一文書にしか出ない単語 文書群全体のなかで一つの文書にしか出てこない単語 なぜ捨てるのか ◦ その文書にしか出ないので他の文書との距離の順序に影響しない ◦ そういう単語は大量にあるのでメモリ節約の効果絶大 2014/6/20 社内勉強会資料 59
  60. 60. 形態素解析の結果を利用 活用を無視して原形に戻すとか ◦ MeCab の解析結果を利用 注意 ◦ くどいようだが、そういうのが有益かどうかは問題に依存する 2014/6/20 社内勉強会資料 60
  61. 61. 数学的な手法 データの散らばり方を解析して複数の次元を一つにまとめる 2014/6/20 社内勉強会資料 61 ◦ こんなふうに散らばっていたら二次元で考える必要があるだろうか? ◦ 一次元で考えても十分なのではないだろうか というアイデア。実現方法はいろいろ提案されている ◦ PCA, SVD, NMF, LSI, LDA, …
  62. 62. Latent Dirichlet Allocation 潜在ディリクレ配分法 ◦ 流行りの手法 ◦ これを知っておけば専門家ぶれる ◦ この界隈でトピックモデルとかベイズとか言ってるのはみんなこれ ◦ そのくせ (上っ面を理解するのは) 難しくないのでコスパがよい 2014/6/20 社内勉強会資料 62
  63. 63. トピックモデル 文書とは以下のプロセスでこの世に産み落とされたものである 2014/6/20 社内勉強会資料 63 お前には 7 単語を与えてやろう 果物トピックから 3 語 場所トピックから 1 語 助詞トピックから 3 語持っていくがよい
  64. 64. トピックモデル 文書とは以下のプロセスでこの世に産み落とされたものである 2014/6/20 社内勉強会資料 64 3 語ほしいのね?それでは 李を 1 つ 桃を 2 つあげましょう
  65. 65. トピックモデル 下界の人間はこうして産まれてきた文書たちを見ている 2014/6/20 社内勉強会資料 65 李も桃も桃のうち うるさいだまれ 語順は気にしないことになっている
  66. 66. LDA は何をするのか 大量の文書を解析すると ◦ それぞれの文書が「どのトピックを何個もらったか」 ◦ それぞれのトピックが「どの単語をどういう確率で出すか」 を推定できる 各文書が「どのトピックを何個もらったか」を推定できるなら ◦ TF-IDF の代わりに使える ◦ 次元削減(単語の種類よりトピックの種類の方が普通は小さい) 2014/6/20 社内勉強会資料 66
  67. 67. どのように推定するのか 難しいので説明しない(できない) 理屈は分からんがとにかく実装する だけならそれほど難しくはない 2014/6/20 社内勉強会資料 67
  68. 68. LDA で文書推薦を試す 2014/6/20 社内勉強会資料 68
  69. 69. PLDA C++ による LDA の実装 ◦ https://code.google.com/p/plda/ インストール 2014/6/20 社内勉強会資料 69 $ tar zxf plda-3.1.tar.gz $ cd plda $ make lda infer ◦ 引数なしで make すると MPI 並列版もビルドしようとする ◦ MPI 並列版が不要なら上記のように make を実行
  70. 70. PLDA の実行(前半) 入力ファイル形式は tf.txt でよい 2014/6/20 社内勉強会資料 70 $ ../plda/lda ¥ --num_topics 20 ¥ # トピック数を指定する --alpha 0.1 ¥ --beta 0.01 ¥ --training_data_file tf.txt ¥ # 入力ファイル --model_file model.txt ¥ # 出力ファイル --burn_in_iterations 100 ¥ --total_iterations 150 ◦ model.txt は「各トピックからどの単語が何回出たか」
  71. 71. 各トピックの単語分布 各トピックからそれぞれの単語が何回出たか 2014/6/20 社内勉強会資料 71 $ head -n 5 model.txt Cascading 0 0 0.02 0 0.02 0.02 0 0 0 0.02 0 0 0 0.3 0 0 0.38 0.02 0.06 0.16 Style 0.1 0 0 0 0.02 0 0 0 0 0 0 0 0 1.52 0 0 0.04 0 0.18 0.14 Sheets 0 0 0 0.02 0 0.02 0 0 0 0.02 0 0.02 0.02 0.26 0 0 0.38 0.02 0.06 0.18 ( 0 430.26 526.04 219.48 344.34 668 817.72 436.16 473.44 278.02 439.62 509.3 386.58 319.32 193.78 432.32 358.84 280.72 388.52 343.54 C 79.52 0 0 0 0 0 0 0.02 0 0.02 0 0 0.2 0.02 0 0 481.12 0.04 0 0.06 ◦ 行 = 単語 ◦ 列 = トピック ◦ 値 = 平均出現回数(分母は集計対象の反復回数) ◦ 各行の合計 = 文書集合でのその単語の出現回数 ◦ すべての要素の合計 = 文書集合の延べ単語数
  72. 72. PLDA の実行(後半) model.txt を使って文書のトピックを推定する 2014/6/20 社内勉強会資料 72 $ ../plda/infer ¥ --alpha 0.1 ¥ --beta 0.01 ¥ --inference_data_file tf.txt ¥ # 入力ファイル --inference_result_file topics.txt ¥ # 出力ファイル --model_file model.txt ¥ # モデルファイル --burn_in_iterations 10 ¥ --total_iterations 15 ◦ topics.txt は「各文書がどのトピックを何個持っているか」 ◦ これを特徴量にできる
  73. 73. 各文書のトピック分布 各文書からどのトピックが何回出たか 2014/6/20 社内勉強会資料 73 $ head –n 5 topics.txt 0 0 0 0 0.8 0.8 0 0 0.2 0.2 0.8 0.4 0.2 31.8 2 0 20.6 0.6 24.4 0.2 0 0 0.8 1.8 1 0 0 1 0 0 18.8 0 0 17 0 26 0 0 0.8 2.8 0 0 0 0 0 0 0 0.2 0 0 0.2 0.6 0 27.4 0 0.6 10.2 0 15.2 7.6 3.4 7.8 0 0 0 0 0 0.2 0 5 3.6 0 0.6 2.4 0 0.8 0.4 0 40.8 26 0 0 0 0.4 0 0 0 0 0 0 0 0 0.2 51 0 0.6 0.2 0.2 4.8 4.6 ◦ 行 = 文書 ◦ 列 = トピック ◦ 値 =平均出現回数(分母は集計対象の反復回数) ◦ 各行の合計 = その文書の延べ単語数 ◦ すべての要素の合計 = 文書集合の延べ単語数
  74. 74. トピック空間上の距離 数学的に妥当なやり方は・・・ 1. 文書のトピック分布から確率分布を作る 2. 確率分布間の「距離」を計算する 2014/6/20 社内勉強会資料 74 $ ../scripts/calc_topic_probability.awk -valpha=0.1 <topics.txt >probs.txt ◦ 文書のトピック分布 = 各トピックの出現回数を合計で割る ◦ ただしパラメータ alpha を各トピックの出現回数に足す $ (head -n 1000 probs.txt | tail -n 1; cat probs.txt) | ../scripts/calc_js_divergence.awk | paste - title- 5000.txt | sort -gsk1,1 | head ◦ 確率分布間の「距離」には JS ダイバージェンスというのを使った ◦ ほかにも色々な「距離」が提案されている
  75. 75. トピック空間で文書推薦 前のスライドの実行結果 2014/6/20 社内勉強会資料 75 $ (head -n 1000 probs.txt | tail -n 1; cat probs.txt) | ../scripts/calc_js_divergence.awk | paste - title- 5000.txt | sort -gsk1,1 | head 0 講座派 0.0981113 リピエーノ 0.108711 東洋哲学 0.1173 デンマーク一周 0.117551 もつ 0.121794 スタニスワフ 0.124586 東進ブックス 0.12676 新版画 0.135116 ピアノソナタ第9番 (スクリャービン) 0.140275 ドワーフ
  76. 76. LDA の長所と短所 思いつくものを挙げてみると・・・ 長所 ◦ 字面上は同じ単語が出てこなくても「似ている」と判断できる ◦ データが小さくなる(?スパースネス) ◦ 距離の計算が速くなる(?同上) 短所 ◦ 似ていないもの同士がまとめられることもある(長所と表裏一体) ◦ 元になるデータが変わるとトピック分けが不正確になってくる ◦ 処理自体に時間がかかる 2014/6/20 社内勉強会資料 76
  77. 77. おわり 2014/6/20 社内勉強会資料 77

×