キャッチフレーズを自動生成するプログラムを考える

「弱みを握る寿司屋」みたいなやついっぱい教えて
こちらのスレッドを眺めていて、ここに登場するいくつかのフレーズに関しては、プログラム的に自動生成できるのではないかと思い、作り始めてみた。
例えば、下記の3つ。

  1. 手に汗握る寿司屋
  2. ヘソを曲げるユリゲラー
  3. 屁理屈をこねるうどん屋

この3つは、「慣用句」+「名詞」という構成になっており、慣用句部分は「名詞」から連想されるものが使われている。

  1. 「寿司屋」→「握る(寿司を)」→「手に汗握る」
  2. 「ユリゲラー」→「曲げる(スプーン)」→「ヘソを曲げる」
  3. 「うどん屋」→「こねる(小麦粉を)」→「屁理屈をこねる」

これをプログラムで再現してみようと考えた。「寿司屋」「ユリゲラー」「うどん屋」という単語を与えると、上記のキャッチフレーズを生成してくれるところまでが最初の目標だ。
まずは、与えられた単語から別の単語を連想させてみる。はじめはWord2Vecを使った類義語判定を試してみたのだが、「類義語」ではなかなか期待した単語が出てこなかったので、シンプルにWikipediaの当該項目のページに記載されている本文から関連する単語を抽出する方法を試みた。

# coding: utf-8
import collections
import mecab_local
import wikipedia
def find_verbs(keyword, ignore_verbs):
    wikipedia.set_lang("ja")
    page = wikipedia.page(keyword)
    content = page.content
    verbs = filter(lambda x: x.endswith(":自立:動詞"), mecab_local.parse(content))
    verbs = map(lambda x: x.split(":")[0], verbs)
    filtered_verbs = filter(lambda x: x not in ignore_verbs, verbs)
    count_dict = collections.Counter(filtered_verbs)
    return count_dict
import MeCab
def parse(sentence):
    mecab = MeCab.Tagger("mecabrc -F%f[6]:%f[1]:%f[0],")
    parsed = mecab.parse(sentence)
    entities = parsed.split(",")[:-1]
    return entities

Wikipediaの内容をMeCabで形態素解析し、登場頻度の高い自立語の動詞を抽出する。名詞や形容詞なども扱いたいところだが、最初のプロトタイプとしてシンプルにするために、省略した。また「する」や「行う」などの汎用性が高すぎる単語は、除外するようにした。

供する 4, 任せる 3, 用いる 3, 握る 2, 限る 2, 仕入れる 2, 劣る 2, 伴う 2, 兼ねる 2, 置く 2

「寿司屋」を与えると、このような結果が返って来た。「握る」が含まれている。
次に、この単語を含む慣用句を検索する。慣用句のリストは、いくつかのウェブサイトで紹介されているものから手動で作成した。誰でも知っているような馴染みのある慣用句で、かつ語尾が動詞になっているようなものだけをリスト化した。

愛想を尽かす|尽かす:自立:動詞
呆気にとられる|とる:自立:動詞
汗水たらす|たらす:自立:動詞
足をひっぱる|ひっぱる:自立:動詞
足の踏み場もない|踏む:自立:動詞
足が棒になる|なる:自立:動詞
足を洗う|洗う:自立:動詞
...
手に汗を握る|握る:自立:動詞
...

各慣用句も形態素解析を行い、含まれる動詞をリストの末尾につけておく。
最後に、連想された動詞「握る」を含む慣用句を検索し、くっつける。なお、表記ブレ(「握らない」と「握る」)による検索漏れを防ぐため、動詞は「連想された単語」も「慣用句に含まれる単語」共に原形に変換した上で検索している。

import wikipedia_verb
def make_phrases(keyword, idioms, ignore_verbs):
    generated_idioms = []
    verbs = wikipedia_verb.find_verbs(keyword, ignore_verbs).most_common(10)
    print(verbs)
    for word, cnt in verbs:
        idioms_containing = list(filter(lambda x: word in x, idioms))
        if len(idioms_containing) > 0:
            for idiom in idioms_containing:
                generated_idioms.append("{}{}".format(idiom.strip().split("|")[0], keyword))
    return {"phrases": generated_idioms, "verbs": verbs }

「寿司屋」を入れてみたところ、めでたく「手に汗握る寿司屋」が生成された。

足に任せる寿司屋
運を天に任せる寿司屋
手を握る寿司屋
手に汗握る寿司屋
一目置く寿司屋
下にも置かない寿司屋
筆を置く寿司屋

また、「ユリゲラー」では「ヘソを曲げるユリゲラー」が生成された。「屁理屈をこねるうどん屋」は生成できなかった。これは「うどん屋」から連想される同士の中に「こねる」が出てこなかったためだった。
他にも、スレッドに登場する単語などで試してみたところ、下記のようなフレーズが生成された。

  • 釘をさす大工
  • さばを読む読書家
  • 足の踏み場もない踏み絵

現状では、上の寿司屋の例にもある通り、面白くないフレーズが大半なので、いつか「生成されたフレーズが面白いかどうか」を学習させる方法を考えてみようと思う。
続きはこちら

キャッチフレーズを自動生成するプログラムを考える(生成されたフレーズの分析)

Pocket

「キャッチフレーズを自動生成するプログラムを考える」への2件のフィードバック

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です