Skip to content

Instantly share code, notes, and snippets.

@otknoy
Created March 26, 2020 14:53
Show Gist options
  • Save otknoy/40a2e9e7870bd71a5f8ca2129830eedb to your computer and use it in GitHub Desktop.
Save otknoy/40a2e9e7870bd71a5f8ca2129830eedb to your computer and use it in GitHub Desktop.
title tags author slide
マルコフ連鎖で AV のタイトルを自動生成してみた
Python マルコフ連鎖 mecab
otknoy
false

背景

これ見て、DMM API を使って取得したAVのタイトル3万件をローカルに保存してあるのを思い出したけどなんかやるか。DMM API・MeCab・マルコフ連鎖でAV作品の紹介文を自動生成 on @Qiita https://t.co/IFqGSHy2bM

— Naoya Otsuka (@otknoy) 2016年3月19日
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

単語頻度を求めた形跡があるけど、見せられないよ!

— Naoya Otsuka (@otknoy) 2016年3月19日
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

放置しすぎやったな・・・。https://t.co/G0Esfh5ene

— Naoya Otsuka (@otknoy) 2016年3月19日
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

ということで、マルコフ連鎖で AV のタイトルを自動生成してみる。

データの準備

だいぶ前にDMM の API を叩いて AV のタイトルを収集するプログラムを書いた。けど、プログラムがどこに行ったのか思いだせない・・・。

その時に作った python で DMM API を叩くモジュールを pypi で公開してあります。 https://pypi.python.org/pypi/dmm-search/0.2.1 今も動くかどうかわからないので、気が向いたときにでもそのあたりをまとめて書く。

今回は、以前に収集したデータをそのまま使います。 1行に1AVタイトルが書かれたテキストファイルです。

プログラム

github に置いといた。 https://github.com/otknoy/markov_chain

MeCab で形態素解析

def tokenize(text):
    m = MeCab.Tagger('-d /Users/otknoy/local/lib/mecab/dic/mecab-ipadic-neologd/')
    m.parse('')

    node = m.parseToNode(text)

    terms = []
    while node:
        terms.append(node.surface)

        node = node.next

	return terms[1:-1]

こんなかんじ。 トークナイズするだけでやこしい処理はしていません。 mecab-ipadic-neologd 使ってます。

マルコフ連鎖

誰かが作ったやつを使ってもよかったけど、最近はあまり家でプログラミングしていなかったので自作してみた。超シンプル。

def ngram(tokens, n=2):
    tokens = tokens[:]
    tokens.insert(0, '(BOS)')
    tokens.append('(EOS)')

    ret = []
    for i in range(0, len(tokens)-n+1):
        ret.append(tokens[i:i+n])
    return ret

class MarkovChain:
    def __init__(self):
        self.chains = {}

    def train(self, tokens):
        bigram = ngram(tokens)

        for s1, s2 in bigram:
            self.chains.setdefault(s1, [])
            self.chains[s1].append(s2)

    def generate(self, bos='(BOS)'):
        tokens = []

        node = random.choice(self.chains[bos])
        while node != '(EOS)':
            tokens.append(node)

            node = random.choice(self.chains[node])

        return ' '.join(tokens)

結果

ここでは見せられないよ! 紳士の皆様はこちらへどうぞ。

オト コノ 娘。 あ ぁっ !

なんだこれは・・・。

考察とか

  • それっぽいタイトルは自動生成できるけど、それっぽいだけだった
    • たまにすごくそれっぽいタイトルが自動生成されるけど、人間が必死に解釈しようとした結果に過ぎないのだろう
    • RNN とか使えばもっとマシになんのかな?
  • AV タイトルの単語頻度を調べてみると、僕の興味がないジャンルの単語が結構上位に多い
    • 興味がない単語は落としてしまってもいいかも
    • しかし「こんなジャンルの需要があるんだ・・・」という新たな知見を得ることができた
  • 結果の共有が困難 (躊躇してしまう)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment