「似ているエロゲを探そう」というサービスを作ってみた


似ているエロゲを探そう(β)
http://similargames.pya.jp/

文章やキーワードを入力すると、
その文章とストーリーの似ているエロゲを探すことができます。

※ストーリーとの比較のため、タイトルで検索してもそのタイトルはほぼ出てきません

 ・ 好きなエロゲと似ているストーリーのエロゲを探したい
 ・ 話題のアニメと似ているストーリーのエロゲを探したい
 ・ 自作したシナリオに似ているものが既にあるかどうか探したい

など様々な用途にお使いください。




早速使ってみよう!


例として、アニメ『アイドルマスターシンデレラガールズ』のストーリーに似たエロゲを探してみます。

入力するのはこちら
歴史ある芸能プロダクション「346プロダクション」には数多くのアイドルが在籍している。そこで新たにスタートする「CINDERELLA PROJECT(シンデレラ プロジェクト)」!普通の毎日を送っていた女の子。アイドルの卵に選ばれた彼女達が、初めて見る世界で紡ぐシンデレラストーリー。みんなと一緒にお城へと続く階段を登っていく事が出来るのか。今、魔法がかかり始める――



フォームに入力して、


「似ているエロゲを探す」ボタンを押すと・・・


第1位から第10位までの作品名と類似度がこのように出力されます。

ちなみに1位の『studioアイドル』、2位の『D-EVE in you』、3位の『あいれぼ』は、
いずれも主人公がプロデューサーとなり、アイドルであるヒロインを攻略するといったゲーム内容です。



続いて、「夏 田舎」というキーワード形式で入力してみましょう。


第1位から第3位までの結果がこちら。
このように夏の田舎を舞台にしたエロゲを探してくれます。


どうやって探しているのか?


さて、このサービスどういった仕組みなのかというと、

入力された文章を単語に分割し、
事前に用意したエロゲのストーリーに、それらの単語がどれだけ含まれているかを判断することで、
入力された文章と各作品のストーリーとの類似度を計算しています。そしてその類似度の高い順に出力すると。


簡単に説明すると、このような感じです。
続いて、細かく説明していきたいと思います。


準備


まず比較対象として、エロゲのストーリーを大量に用意する必要があります。
各公式サイトから収集するのは非常に手間がかかる作業なので、
文字列になっていて、決まったところにストーリーの記述が存在するGetchu.comから収集しました。

本システムには、18禁のPCゲームのカテゴリで、ストーリーが重複していない6775作品が登録されています。
そのため、初回版と通常版がある作品でも、初回版だけが出力されるようになっています。

ちなみに6/26に収集したので、それ以降にストーリーが登録された作品については結果に出てきません。



収集した6775作品のストーリーに対して、事前処理を施します。
まずそれぞれのストーリーに対して形態素解析を行い、単語に分割します。

形態素解析というのは、自然言語処理の一種で、
文章を単語に分割し、その単語の品詞を特定する処理のことです。


例えば、

中世ヨーロッパの街並みをイメージした、大型ショッピングモール『ブリックモール』。グランドオープンを数ヵ月後に控え、人気飲食店の誘致を積極的に推し進めていた。喫茶店『ファミーユ』。

こちらの戯画の『パルフェ』のストーリーの一部を例にとって事前処理すると、以下のようになります。

中世|ヨーロッパ|街並み|イメージ|する|大型|ショッピング|モール|ブリックモール|グランド|オープン|数|ヵ月|後|控える|人気|飲食|店|誘致|積極|的|推し進める|いる|喫茶店|ファミーユ


事前処理の結果出力される単語は名詞、動詞、形容詞、副詞に絞っており、
動詞と形容詞については基本形に直しています。

形態素解析にはMecabを使用しています。


類似度の計算について


類似度の計算には、入力された文章のtf-idfベクトルと、
各作品のストーリーのtf-idfベクトルから算出されるコサイン類似度を使用しています。

といっても、自然言語処理を知らない人にとっては、
なんのこっちゃわからないと思うので、一つずつ説明していきます。



・ tf-idf

tf-idfとは、文章中でどの単語が重要なのか、それとも重要でないのかを決めるのに使用される値です。
詳しくはこちらに大変わかりやすい説明があるのでご覧ください。


tfは文章中における単語の出現頻度のことで、値が大きいほどその単語がよく出てきます。

式で表すと、 tf = ある単語の出現回数 / 文章全体の単語の出現回数の合計 となります。


例えば、「好き好き大好き」という文章は、
「好き」という単語が2個、「大好き」という単語が1個使用されているので、
「好き」のtfは2/3となり、「大好き」のtfは1/3となります。


idfはその単語が多くの文章の中でどれだけ共通して使われているかのことで、
値が大きいほどその単語が少ない文章でしか使われていないことを表します。

式で表すと、 idf = log ( 文書数の合計 / ある単語が出現する文書数 ) + 1 となります。


例えば、「する」という動詞は非常に多くの文章で使われているのでidfは小さく、
具体的には6775作品中、6416作品で使われており、idfは1.02となっています。

一方、「徹する」という動詞はほとんど使われていないのでidfは大きく、
具体的には6775作品中、1作品しか使われておらず、idfは4.83となっています。


そして、このtfとidfを掛け合わせたものがtf-idfです。



・ tf-idfベクトル

文章をベクトル化することで、文章の方向が一意に定まり、
類似度を計算することが出来るようになります。

各単語のtf-idfをベクトルの次元とすることで、文章をベクトルにします。
ちなみに全作品のストーリーを分割した結果、合計約4万単語となったので、
4万次元のベクトルとなります。(実際はほとんどの次元が大きさ0ですが)



・ コサイン類似度

コサイン類似度というのは、2つのベクトル間の角度の近さのことです。
コサイン類似度が0に近いほど、ベクトル間の角度が大きく、似ていません。
コサイン類似度が1に近いほど、ベクトル間の角度が小さく、似ています。

コサイン類似度は、2つのベクトルの内積を、2つのベクトルの絶対値の積で割ると求めることが出来ます。

この2つのベクトルに入力された文章のtf-idfベクトルと、各作品のストーリーのtf-idfベクトルを使用しています。
結果で表示されるパーセンテージは、このコサイン類似度をパーセントに直したもので、
数値の高い順に出力しています。


実装について


PHPで実装しています。せいぜい150行ぐらいですけどね。
入力された文章に対して形態素解析を行うのにはMECAPIという、MecabのWeb API版を使用しています。

ちなみに6775作品全てに対して類似度を計算しているため、
入力された文章が長いと、かなり処理時間がかかってしまいますが、
最初にコーディングした時に比べるとこれでも割とマシになった方です・・・。

一番最初は5分ぐらい時間がかかっていて、使い物にならないレベルでした。


最後に


もしPHPのエラーメッセージが表示されたり、挙動がおかしかったりした場合は、報告をお願いします。

入力された文章を表示するようにはしていないので、ある程度安全だとは思いますが、
普段PHPをほとんど書かないので、バグとか脆弱性とか残ってそうでちょっと怖かったりします。

タイトルについてはとりあえずβ版としていますが、おそらく永遠にβ版のままな気がします。
それから、ご意見ご感想などありましたら、どしどしお寄せください。


関連記事
2015年07月08日 | 未分類 | コメント(4)
完全に門外漢の人間ですが、なるほど単語ごとにベクトルを用意して、その内積で類似度を計測するというのが大変興味深いです。
ところで形態素解析において、名詞副詞形容詞を鑑別するメカニズムが想像つきません。言語の「活用」のパターンから鑑別しているのかなぁとは思いますが、実際のところいかがでしょうか?
[ 2015年07月11日 22:42 ]
ちょい訂正
単語ごとにベクトルを用意して→単語ごとに次元を用意して
[ 2015年07月11日 23:01 ]
日本語の形態素解析における品詞推定では一般的に単語辞書が使用されます。
単語辞書には色々な単語とその単語の品詞などが一覧になっており、
それに照らし合わせながら形態素解析を行っています。

システム内で使用しているMecabにおける推定に関しては、
こちらを見ていただくとわかりやすいかと思います。
https://mecab.googlecode.com/svn/trunk/mecab/doc/learn.html

ちなみに英語の形態素解析における品詞推定の場合は、
「名詞の後は動詞が来やすい」のような語順の傾向を学習することによって、
品詞推定を行うのが一般的なようです。
[ 2015年07月12日 02:24 ]
丁寧な回答、ありがとうございました。
[ 2015年07月12日 18:49 ]
コメントの投稿