コーンフレークなのかコーンフレーク違うかどっちなんだい！！！M-1グランプリ2019ミルクボーイのコーンフレーク判別モデルを作ってみる

# ミルクボーイのネタ

先日のM-1で優勝した「ミルクボーイ」さんの行ったり来たり漫才！！！

決勝一回戦のネタのである「コーンフレーク」の内容を用いて
・コーンフレークなのか
・コーンフレークと違うのか
を判別するモデルを作ってみました。

解説動画はこちら
https://youtu.be/PvFCy1mqzG8

# コーンフレークのネタをデータ化

まずはコーンフレークのネタを聞いて文字に起こします。

文字お越しをしたら、それを機械学習用のデータにしていきます。

データとしてはこんな感じに
corn_model_data.csv

|かどうか|説明文|
|----------------|-------------|
|コーンフレーク|甘くてカリカリしてて牛乳とかかけて食べるやつ|
|違う|死ぬ前の最後のご飯もそれでいい|
|コーンフレーク|まだ寿命に余裕があるから食べてられんねん|
|コーンフレーク|最期のごはんに任命されたら荷が重いよ|
|コーンフレーク|なんであんなに、栄養バランスの五角形が広いんかわからん|
|コーンフレーク|パッケージに書いてる五角形めちゃくちゃでかいんやから|
|コーンフレーク|自分の得意な項目だけで勝負してる|
|コーンフレーク|牛乳の栄養素を含んだうえでの五角形|
|違う|晩御飯ででてきても全然いい|
|コーンフレーク|晩飯で出てきたらちゃぶ台ひっくり返す|
|コーンフレーク|まだ朝の寝ぼけてるときやから食べてられる|
|コーンフレーク|食べてるうちにだんだん目が覚めてくるから、最後にちょっとだけ残してまう|
|コーンフレーク|子どもの頃、なぜかみんな憧れたらしい|
|コーンフレーク|ミロとフルーチェは憧れた|
|コーンフレーク|トランシーバーも憧れました|
|違う|お坊さんが修行も時に食べてる|
|違う|精進料理にカタカナのメニューなんかでえへん|
|コーンフレーク|朝から楽して腹を満たしたいという煩悩の塊|
|コーンフレーク|あれみんな煩悩に牛乳かけてる|
|コーンフレーク|パフェとかの傘増しに使われているらしい|
|コーンフレーク|あれは法律スレスレぐらいはいっとる|
|違う|ジャンルでいうなら中華|
|違う|中華だけではない|
|コーンフレーク|回るテーブルの上においたら回したとき全部飛び散る|
|コーンフレーク|食べてるときに誰に感謝したらええかわからん|
|コーンフレーク|コーンフレークは生産者さんの顔がうかばへん|
|コーンフレーク|浮かんでくるのは腕組んでるトラの顔だけ|
|コーンフレーク|赤いスカーフのトラの顔だけ|
|違う|おかんがではないと言えばちゃう|

データとしては2列分

コーンフレークの説明をしているものであれば「コーンフレーク」
そうでなければ「違う」を目的変数として設定します。

# モデルづくりへ

ここからは予測モデルを作っていきます。

## ライブラリのインポート

まず最初は必要なライブラリのインポートです。
形態素解析をするのでjanomeを使用していますが
mecabなどを持ち合わせている方はそれでも代用できます。

```
import codecs
import pandas as pd
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
from sklearn.metrics import confusion_matrix

import warnings
warnings.simplefilter('ignore')
from janome.tokenizer import Tokenizer
t = Tokenizer()
```

## データの読みこみ

文章をCSV化してインポートします。

```
df = pd.read_table('corn_model_data.csv')
df.head()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379626/4bf1df3e-50fe-b8d7-9776-2dedebaaa4d5.png)



## モデル用辞書データの作成

「説明文」列を形態素解析をして説明変数を作ります。
出てきた単語1語で1列とするために、まずは形態素解析を行って
出てきた単語を辞書型で取っておきます。

```
word_dict = {}
for i,v in df.iterrows():
    for token in t.tokenize(v[1]):
        h = token.part_of_speech.split(',')[0]
        if any([h=='名詞',h=='動詞',h=='形容詞']):
            key = token.surface
            word_dict[key]=0
```

# データの前処理

ここからは学習用データの作成に入ります。

## 目的変数の作成
```
df['y'] = df['かどうか'].replace({'コーンフレーク':1,'違う':0})
```

まずは目的変数は0,1でないといけないので「かどうか」列の値を用いて
コーンフレークなら1、違えば0に変換した列を作ります。


## データの数値化
```
columns = [k for k,v in sorted(word_dict.items())]
tf_df = pd.DataFrame(columns=columns)
for i,v in df.iterrows():
    tmp = word_dict.copy()
    for token in t.tokenize(v[1]):
        h = token.part_of_speech.split(',')[0]
        if any([h=='名詞',h=='動詞',h=='形容詞']):
            key = token.surface
            if key in tmp:
                tmp[key]=1
    tmp_list = [v for k,v in sorted(tmp.items())]
    tmp_df = pd.DataFrame(data=np.array(tmp_list).reshape(1,len(tmp_list)),columns=columns)
    tf_df = tf_df.append(tmp_df)

tf_df = tf_df.reset_index(drop=True)
data_df = pd.concat([df,tf_df],axis=1)
```

次に「説明文」列の文章を切り分けてone-hotベクトルを作成していきます。

色々なやり方が有るでしょうが最も原始的な方法で行います。
データフレームの1行ずつ形態素解析し、その単語があれば1、無ければ0という辞書を作り
データフレームに変換し足し上げます。





# 学習データの作成
```
x = data_df.iloc[0:,3:]
y = data_df['y']
```

上記まで行ったら、目的変数と説明変数が出来ているはずなので必要なものだけ残します。

「y」列を目的変数に
それ以降の列を説明変数にします。


# 学習
```
model = LogisticRegression(fit_intercept = False)
model.fit(x,y)
```

機械学習史上最も何も考えていないモデルづくりです。

トレーニング、テストに分けるなんていうことをせず
全データを用いて学習します。

二値の分類を行うので
ここではロジスティック回帰を用いてモデルを作ります。


# モデルの精度
```
predict = model.predict(x)
print('Accuracy : {0}%'.format(accuracy_score(y, predict)*100))
print(confusion_matrix(y, predict, labels=[0,1]))
```

Accuracy : 100.0%
[[ 7  0]
 [ 0 22]]

一応申し訳程度にモデルの評価をします。
仕事では通常有り得ない、正解率100%のモデルが出来上がります。



# Widgetsで予測モデルを使えるようにする
```
from __future__ import print_function
from ipywidgets import interact, interactive, fixed, interact_manual
import ipywidgets as widgets

def callback(word):

    if len(word)>0:
        data = word_dict.copy()
        for token in t.tokenize(word):
            h = token.part_of_speech.split(',')[0]
            if any([h=='名詞',h=='動詞',h=='形容詞']):
                key = token.surface
                if key in tmp:
                    data[key]=1

        input_list = [v for k,v in sorted(data.items())]
        input_df = pd.DataFrame(data=np.array(input_list).reshape(1,len(input_list)),columns=columns)
        input_predict = model.predict(input_df)
        
        if input_predict==1:
            print('それはコーンフレークや！！！')
        else:
            print('コーンフレークちゃうやないかい！！')
    else:
        print()

interact(callback,word='')
```

最後に出来上がったモデルを使えるようにしましょう。

jupyter上でwidgetを用いて
モデルを呼び出せるようにします。

上記を実行するとこんな画面が出るので
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379626/ffbe2c79-3cea-59ff-1234-315e80f97bb7.png)


ここにいろんな文章を入れてもらうと
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379626/333dd966-5092-5508-a2d6-54c288be3768.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379626/9ca2abff-93a4-8cae-0edb-36eedec64047.png)


結果が反映されます。

まあ、学習用のデータに用いたものしかコーンフレーク認定されない
雑な学習モデルですが
初学者の学習用にはなかなか面白いかもしれません。

ミルクボーイのネタはまだまだ沢山あるので
以下のようなものもイケますね！！

・モナカかモナカ違うか
・サイゼかサイゼちゃうか
・俳優か男優か
etc


M-1が始まる前までは個人的には「かまいたち」を
優勝予想していたものの、ミルクボーイのネタの完成度には
正直驚きましたねーーー

その他の細かい予想は当たったので
データからお笑いに関する予測するということも
面白い研究分野の一つになっています。


最後に
データからM-1で優勝する方法について
需要が有ればやりたいですねー
芸人の方々、ご連絡くださいませ！！