Jah524’s blog

気が向いた時に技術的なことを書いたりします

架空対義語生成bot作ってみた

相当久しぶりの更新...!

もともと数年前に、就活を意識しだして書いてたブログだったので、進学決めてからすっかり存在を忘れていました。
久々に何か書いてもいいよな〜、と思いたったので、作ったものについて記事にしてまとめてみます。

作ったもの twitter.com

使い方は簡単、@taigigo_kaku の後に続けて種となる表現と「⇔」を繫げるだけです。

使用例1) @taigigo_kaku マカロニグラタン ⇔
使用例2) @taigigo_kaku 架空対義語 ⇔

挙動例としては次になります。

架空対義語って?

定義があるなら私も教えて欲しいです。
一言で言ってしまえば、でたらめな対義語です。

架空対義語の楽しみ方としては、次のように説明できるでしょう。
本来、対義語として定義されていない単語を、何らかの属性の対称性から対義語であると無理やり認識することで、原文との間に生じる不適合を楽しむもの。
ユーモアの一種ですね。

なぜ作った?

きっかけは、poroLogueさんと飲んでいる時でした。
架空対義語を集めてボットにしている(架空対義語くん)、という話を聞き、

「自動生成もある程度出来るんじゃないですかね〜? 空いてる時間にやってみます」

と、言ってしまったんですね。
研究の一部で、昨年から話題になっているword2vec使っていましたし、自然言語処理の応用に使える資源も持ち合わせていましたし、実際どこまでできそうなのか試してみた次第です。

結果から言うと、まだまだ期待通りでない箇所はありますが、入力する文章の属性を意識すれば、面白い表現も作れそう、といったところです。

どうやったの?

まず用意したものとして、

  1. word2vec(今回はgensimを使いました)
  2. それの学習に使う新聞記事/twitterのデータ合わせて10GBほど
  3. 日本語語彙大系

以上の3種ですね。

さて、どうやって対義語を同定するのかですが、ここが一番悩まされました。
任意の単語に対して、word2vecで構築した空間上から最も遠い単語って、人間の感覚からする逆の特性ではなく、無関係になるような単語になりやすい気がします。

例 )
コサイン類似度("単語", "言葉") = 0.54
コサイン類似度("単語", "手紙") = 0.26
コサイン類似度("単語", "ブログ") = 0.03

つまり、単純に単語ベクトル空間上から最も遠い単語を抽出するだけでは、対義語っぽい単語は得られません。
そこで、まず対義語を表すようなベクトルが抽出できないか、試しました。
具体的には、"良"→"悪", "悪"→"良"といったベクトルを使用しました。
単に"軽い"の逆は"重い"で、"闇"の逆は"光"だろうという安易な発想です。

まず、入力された単語を{"良", "悪"}と類似度を算出し、2値分類しました (一般的には、教師あり機械学習で対応する箇所ですね) 。
次に、入力単語が"良"と類似度が高い場合は"良"→"悪"のベクトル加算を、"悪"と類似度が高い場合は"悪"→"良"のベクトル加算をしました。 このベクトル加算先での最近傍の単語が、求める対義語になる、といった仮定です。

しかし、満足には期待したような結果はでませんでした。
場合によっては、ベクトル加算語の近傍の単語を確認すると、元の入力単語に似すぎている単語が得られてしまいました。

例)
"過去" + "悪"→"良" = "歴史"         <= 対義語っていうより類義語?
"冷蔵庫" + "良"→"悪" = "洗濯機"      <= ある程度対義語っぽい?ような?
"パソコン" + "良"→"悪" = "インターネット"  <= 類義語っぽい?

そもそも、"良"と"悪"のコサイン類似度が0.56もあります。
つまり、入力単語に"良"→"悪といったベクトルを加算しても、入力単語に近い場所を指し示すだけなんですよね。
影響は大きくないかもですが、多少は求める単語に近づくだろうと判断しました。
しかし、対義語っぽい単語を得るためには、追加で別の対策を考える必要があります。
似すぎていてもダメ、似ていなさすぎてもダメ、なかなか難しいですね。

そこで、今回のところは、3. 日本語語彙体系を用いました。
この語彙体系を参照し、入力の単語に対する類義語を得ます。
得られた同義語全てに対して、入力の単語にベクトル加算した最近傍の単語との類似度を算出し、最も類似していないものを選択します。
これで、似ていないけど、連想できないほど似ていない単語ではない単語が得られます。
これが実際のリプライにもある架空対義語として使用される箇所です。

ちなみに、計算量が地味にヤバイので、ある程度対象を間引いて計算してます。
従って、再現性は完全にあるわけではないので、面白い表現に会えるかどうかは、偶然も絡んできます。

技術的には、以上のようになっております。

出来は?

是非使ってみて判断してみてください。

...というのはさておき、入力する単語にある程度依存しやすいです。
まず、日本語体系に掲載されているある程度メジャーな単語にしか対応出来ていないですし(例えば、"マイクラ"などの単語には対応できてない)、現在ではまだ名詞のみでしか対応をしていないので、形容詞などはそのままです。

グレードアップに乞うご期待。

最後に

気楽に使って頂ければ嬉しいです。
そして、時間があるときにでも追加で機能を出していければ、と思います。
とりあえず次は定期つぶやきとかでしょうか。

何かあれば私の方まで連絡を頂ければ幸いです。

twitter.com