見出し画像

AIだって毎日チクショーしたい | 1 Word2Vecでチクショーとは何か

一瞬涼しくなったと思ったら、すぐにまた暑さ。
夏至を過ぎ、9月なりに傾いた癖に身体を焼いてくる太陽とは裏腹に
空はもう天高く薄雲が張っていていてちゃんと秋をアピールする。
そんなちぐはぐな空が9月の見どころだと思う。

ちぐはぐといえば、

自分がこれが大好きだ。支離滅裂、誰もが予想だにしないオチ。
自由律俳句か?????
上の句と下の句の繋がりはいくら考えても
微塵も繋がっているようには思えないまさにブラックボックス。
あんまりにも支離滅裂すぎて、機械学習とかの自動生成を疑うようになってきたので、本当にブラックボックスで作ってやろうと思った。

過去のまいチクから学ぶ

これを使えば、まいチクっぽい文章を生成できるはずだ。
Twitter@dayukoumeからできるだけまいにちチクショーを引っ張ってくる。


import tweepy
import csv
import pandas as pd

TwitterAPIにアクセスして、

consumer_key = "xxxxxxx"
consumer_secret = "xxxxxxx"
access_key = "xxxxxxx"
access_secret = "xxxxxxx"
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_key, access_secret)
api = tweepy.API(auth)

@dayukoumeのツイートを引っ張ってきて、テキストを保存する。

tweet_data = []

for tweet in tweepy.Cursor(api.user_timeline,screen_name="dayukoume").items():
   tweet_data.append([tweet.created_at,tweet.text.replace('\n',''),tweet.favorite_count,tweet.retweet_count])

with open('dayukoume.csv', 'a',newline='',encoding='utf-8') as f:
   writer = csv.writer(f, lineterminator='\n')
   writer.writerow(["created_at","text","fav","RT"])
   writer.writerows(tweet_data)
pass


こんな感じで取れます。

画像1

画像2

まだまいにちチクショーする必要がなかった時代もあったみたい。

まいにちチクショーを分かち書きする。

「。」や改行などで区切られた長い文章を一文ずつに分ける

def _divide(self, text):
       u"""
       @param text 分割前の文章
       @return 一文ずつの配列
       """
       # 改行文字以外の分割文字(正規表現表記)
       delimiter = u"。|.|\."
       # 全ての分割文字を改行文字に置換(splitしたときに「。」などの情報を無くさないため)
       text = re.sub(r"({0})".format(delimiter), r"\1\n", text)
       # 改行文字で分割
       sentences = text.splitlines()
       # 前後の空白文字を削除
       sentences = [sentence.strip() for sentence in sentences]
       return sentences

分けられた一文を形態素解析する

分けた一文を単語ごとに分割する。
本当はNelogd辞書をとかを使って特殊語や新語に対応できるようにすべきだろうけれど、
windowsに導入するのが恐ろしく手間......
というより二日かけてもうまく出来ず断念。Chasenで形態素解析する。

    self.tagger = MeCab.Tagger('-Ochasen')

   def _morphological_analysis(self, sentence):
       u"""
       @param sentence 一文
       @return 形態素で分割された配列
       """
       morphemes = []
       # sentence = sentence.encode("utf-8")
       node = self.tagger.parseToNode(sentence)
       while node:
           if node.posid != 0:
               # morpheme = node.surface.decode("utf-8")
               morpheme = node.surface
               morphemes.append(morpheme)
           node = node.next
       return morphemes

マルコフ連鎖を用いて適当な文章を自動生成する

前回同様お力を借りて文章を自動生成します。

出来上がったのがこれ。
いくつかをコウメ太夫のネタに合わせてどうぞ。

-------

チャンチャカ↑チャンチャン チャチャンチャ→チャン↑チャン↑
チャンチャカ↑チャンチャン チャチャンチャ→チャン↑チャン↑......

無償の愛かと思ったら~、チャーシューのひもで縛られてました~。
チクショー!

もう一回。

チャンチャカ↑チャンチャン チャチャンチャ→チャン↑チャン↑
チャンチャカ↑チャンチャン チャチャンチャ→チャン↑チャン↑......

電車が遅れてセンタ~試験を受けてみたら~、社長がチンパンジーでした~。(中は五目チャ~ハンでした~。チクショー!!

チャンチャカ↑チャンチャン チャチャンチャ→チャン↑チャン↑
チャンチャカ↑チャンチャン チャチャンチャ→チャン↑チャン↑......

子供かと思ったら~、抱きついてシロ塗りヌリヌリシャワ~でした~。
チクショー!!ゴリ押しチクショー!!


出来た.....支離滅裂感は再現できたが、明らかに本物のほうが面白い。
いくらゴリ押しが芸だからといって、「シロ塗りヌリヌリシャワ~」は
ないわ.......

何が違うのか、悲哀か季節感か勢いかそれとも文脈か......
とにかくコウメ太夫っぽさが足りないのだ。
これではTwitterで#まいチクチャレンジとかいう大喜利タグがあったら
集まってくるだろう有象無象と変わらないだろう。坊主のクソつまらん選手権とおんなじである。

屈辱なのでどうにかしてコウメ太夫っぽさを追求する。

コウメは何に対してチクショーなのか

コウメ太夫なりのチクショーポイントがあるのではないか。
彼なりのチクショー感性を理解すれば少しは近づけるのではないだろうか。
もっと言えば今まで千件くらいのまいチクの中からしか生成できてないが
まいチク流チクショーが分かればコウメの模倣の域を超えられるんじゃないかとも思わされる。

「チクショー」の意味をword2vecでベクトル計算する

word2vecは、大量のテキストデータを解析し、各単語の意味をベクトル表現化する手法。単語をベクトル化することで、
・単語同士の意味の近さを計算
・単語同士の意味を足したり引いたり ということが可能になる。

word2vecを使えばチクショーの意味ベクトルに近い言葉を計算できるのではないか。

import MeCab
import csv
import sys
import pandas as pd
import os.path
import urllib.request
import urllib.parse
import unicodedata

まずはまいチクの下の句、
いわばチクショーな部分を前処理・形態素に分ける。
今回も辞書はとりあえずChasen。

tagger = MeCab.Tagger("-Ochasen")

df = pd.read_csv('maichiku.txt', sep='\t', names=['text'], encoding='utf-8',engine='python')
text_lists = df['text'].unique().tolist()

with open('maichiku_splited.txt', 'w', encoding='utf-8') as f:
   for text in text_lists:
       tmp_lists = []
       text = unicodedata.normalize('NFKC',str(text))
       if 'ちくしょー' in text:
           text = text.replace('ちくしょー','チクショー')
       if 'チクショー' in text:
           text_splited = text.split('チクショー')
           for i, text in enumerate(text_splited):
               node = tagger.parseToNode(text)
               while node:
                   if node.feature.startswith('名詞') or node.feature.startswith('形容詞'):
                       tmp_lists.append(node.surface)
                   node = node.next
               if i != len(text_splited)-1:
                   tmp_lists.append('チクショー')
       else:
           node = tagger.parseToNode(text)
           while node:
               if node.feature.startswith('名詞') or node.feature.startswith('形容詞'):
                   tmp_lists.append(node.surface)
               node = node.next
       f.write(' '.join(tmp_lists) + '\n')


テキストの中から、「チクショー」に近い言葉を見つける。
今回はSkip-Gram Modelを使います。
意味ベクトルが近い10件を計算させるとこんな感じ。

from gensim.models import word2vec

sentences = word2vec.LineSentence('maichiku_splited.txt')
model = word2vec.Word2Vec(sentences,
                         sg=1,         #0: CBOW, 3: skip-gram
                         size=300,     # ベクトルの次元数
                         window=100,    # 入力単語からの最大距離
                         min_count=1,  # 単語の出現回数でフィルタリング
                         )

model.most_similar(positive='チクショー', topn=10)
[('ネタ', 0.9998814463615417),
('仕事', 0.999877393245697),
('コウメ', 0.9998762011528015),
('収録', 0.9998486042022705),
('お願い', 0.9998421669006348),
('チクショウ', 0.9998351335525513),
('tikuporadio', 0.9998349547386169),
('チンパンジー', 0.9998189806938171),
('番組', 0.9998156428337097),
('再生', 0.999796450138092)]

実際にでてきた単語でコーパス(本文)を検索すると確かにこの10語は結構な回数登場していることがわかる。
特に「チンパンジー」はネタのオチによく使われている模様。
「チンパンジー」が初登場した回を探すと

どうやらチクポーレディオっていうラジオ番組で
「チンパンジーのコーナー」があったらしい。
チンパンジーネタに関して、チンパンジー近辺の単語に何かしら重み付けかなんかをしたらいいだろうか。

コウメ太夫の出演番組の内容というドメイン情報を入れないとコウメっぽいまいチクは難しいようだ。

少しげんなりしたのでまた次回。

この記事が気に入ったらサポートをしてみませんか?