DEVELOPER’s BLOG

技術ブログ

【M-1 記念】ミルクボーイを機械学習で再現してみた

2019.12.27 都築 勇祐
コラム 機械学習
【M-1 記念】ミルクボーイを機械学習で再現してみた

【ネタバレあり】


皆さん今年のM-1グランプリご覧になりましたか? 今年はミルクボーイさんが見事歴代最高得点で優勝しました。本当におめでとうございます!


ミルクボーイさんといえば

「それコーンフレークやないかい!」

「いやほなコーンフレークちゃうやないかい!」

と一方の文章に対してもう一方がコーンフレークかどうかをつっこむ、というネタですよね。


そこでテレビを見ながら思ったわけです。

「これって、機械学習でできるんじゃね?」

与えられた文章に対して、それがコーンフレークについての文章かどうかを判別する、というのはいかにも機械学習ができそうなことです。

ということで作ってみました!

スクリーンショット 2019-12-27 16.40.46.png @1_milkboy
このツイッターアカウントは入力した文章に対して「それコーンフレークやないかい!」/「いやほなコーンフレークちゃうやないかい!」と突っ込んでくれます。


BERTを使ってみた

まずは、元データを用意します。
これはミルクボーイさんの漫才の中の言葉の他に、ウィキペディアの記事などから集めてきました。
コーンフレークなら1、そうでないなら0という風に値を指定していきます。
時間もなかったので、全部で70件ほどしか集まりませんでした...
image1.png
次に、学習機です。
文章の学習、ということで用いたのはBERTです。(BERTについてはこちらを参照
Googleさんが104ヶ国語に対応しているmultilingual BERTを公開しているので、改めて日本語を学習していく必要はありません。
日本語を学習済みのBERTを使って、元データを読み込ませてどういう分がコーンフレークなのか学習していきます。

train = pd.read_csv(text, header=0)
BERT_MODEL_HUB = "https://tfhub.dev/google/bert_multi_cased_L-12_H-768_A-12/1"

[途中略]

print(f'Beginning Training!')
start_time = datetime.now()
model.train(input_fn=train_input_fn, max_steps=num_train_steps)
print("Training took time ", datetime.now() - start_time)


学習が終わったところで、実際の文で試していきましょう!

今回は
「朝ごはんに食べると目が覚めるやつ」

「ごはんと食べるとおいしいやつ」
の2文で試していきます。

前者が「ほなそれコーンフレークやないか」、後者が「ほなそれコーンフレークちゃうやないか」の予定なのですが、元データが少ないので、「朝ごはん」と「ごはん」の違いに引っかからないかがポイントですね。


labels = ["ほなそれコーンフレークやないか", "ほなそれコーンフレークちゃうやないか"]

[途中略]

predict_text = ["朝ごはんに食べると目が覚めるやつ", "ごはんと食べるとおいしいやつ"]
predictions = getPrediction(model, predict_text)
predictions


結果がこちら!
image2.png
残念ながらどちらも「ほなそれコーンフレークやないか!」とつっこまれています...
やはり元データを増やさないと精度はまだまだ出ませんね。


Word2Vecを使ってみた

ということで今度はWord2Vecを使ってみました!(切り替えが早い...)
BERTはWord2Vecより性能が高いのですが、元データが小さい場合、Word2Vecでキーワードだけ拾ったほうがよいのではと思い試してみることにしました。
まずは日本語のWord2Vecを(http://www.cl.ecei.tohoku.ac.jp/~m-suzuki/jawiki_vector/)から引っ張ってきました。
BERTもそうでしたが、日本語に対して学習済みの機械が出ているのは非常に助かりますね!

次に、入力を処理していきます。与えられた文章の中から名詞と動詞のみを抽出し、単語のlistにします。

def counter(texts):
            t = Tokenizer()
            word_count = defaultdict(int)
            words = []
            for text in texts:
                tokens = t.tokenize(text)
                for token in tokens:
                    pos = token.part_of_speech.split(',')[0]
                    if pos in ['名詞', '動詞']:
                        # 必要ない単語を省く(実際の結果を見て調整)
                        if token.base_form not in ["こと", "よう", "そう", "これ", "それ", "もの", "ため", "ある", "いる", "する"]:
                            word_count[token.base_form] += 1
                            words.append(token.base_form)
            return word_count, words


続いて、この単語のlistとキーワード(今回はコーンフレーク)との相関度を計算します。
Gensimのライブラリは充実しているので一行ですみます。

score = self.model.n_similarity([keyword], words)


最後にこの数字が0.5以上なら「ほなそれコーンフレークやないか」、0.5以下なら「ほなそれコーンフレークちゃうやないか」を出力する、という形にしました。

if (score > 0.5):
          return("ほなそれコーンフレークやないか")
        else:
          return("ほなそれコーンフレークちゃうやないか")


これをキーワードは「コーンフレーク」、文章は「アフリカの名産品って言ってた」で試してみましょう。
文章の中から「アフリカ」「名産品」「言って」を抜き出し、それぞれと「コーンフレーク」との相関の平均を取ります。
するとなんということでしょう、「ほなそれコーンフレークちゃうやないか」と出力されるではありませんか!

さきほど失敗した「ごはんとめっちゃ合うって言ってた」でも試してみると、
今度は大成功です!


まとめ

今回Word2VecとBERTの両方を試してみて、ぱっと見たところWord2Vecのほうが結果が良いことがわかりました。
しかしこれは本当は苦肉の策です。単語だけを抜き出すより、文脈全体を考慮したほうがよいですし、0.5という敷居値も独断っと偏見でしかありません。それぞれの単語とキーワードの相関も足し合わせただけではホントは良くないかもしれません。そういった点で、最初にBERTを使ってみたのですが、いかんせん元データの数が少なすぎました。いずれ十分なデータ量がたまれば、BERTが活躍できる日が来るかもしれません。
最終的にはミルクボーイさんとコラボなんてしてみたいですね。
それではまた!皆様よい新年をお迎えください!


Twitter・Facebookで定期的に情報発信しています!

関連記事

MacBook Proにログインできない?復旧キーの探し方とロックの解除手順

はじめに 復旧キーとは? 「復旧キーがない場合」を試す まとめ はじめに 先日、私用のMacBook Proにログインできなくなる問題が発生しました。 経緯としては、2台あるMacBook Pro AとMacBook Pro Bを取り違えてしまい、MacBook Pro AにMacBook Pro Bのパスワードを入力し続け、パスワード入力の試行可能回数を超過してMacBook Pro Aにロックがかかりました。 Macのログインパスワー

記事詳細
MacBook Proにログインできない?復旧キーの探し方とロックの解除手順
コラム
AWSマルチアカウント環境でのOS・パッチ・証明書の統合管理

はじめに SSM統合コンソールによる一元管理 OSなど構成情報の可視化 Patch Managerによるパッチ運用の標準化 証明書有効期限の集中監視と自動通知 導入効果と業務改善イメージ 導入時の設計上の留意点 継続的改善を支える「運用の仕組み化」 1.はじめに クラウド活用が拡大し、AWS環境が複数アカウントで利用されたり、複数システムにまたがって利用されることは、システム運用における構成の一貫性を維持することの難易度を

記事詳細
AWSマルチアカウント環境でのOS・パッチ・証明書の統合管理
AWS SRE コラム
AWSの可用性設計を考える:AZ・リージョン・事業継続計画(BCP)のバランス

はじめに 可用性設計の基礎:リージョンとAZの仕組みを理解する 止まらない設計を妨げる単一点障害:単一AZ構成の限界 マルチAZ構成:同一リージョン内での止まらない仕組み マルチリージョン構成:事業継続(BCP)のための冗長化 まとめ:設計段階で「どこまで止めないか」を決めよう 1. はじめに AWSは、数クリックで仮想サーバー(EC2)を立ち上げられるなど、手軽にサービスを構築できるクラウドです。システム企画や開発の初期段階では

記事詳細
AWSの可用性設計を考える:AZ・リージョン・事業継続計画(BCP)のバランス
AWS コラム
[AWS ECS + Rails] スティッキーセッションとCSRFトークンエラー対策

はじめに スティッキーセッション(Sticky Session)とは Railsのセッション管理とCSRFトークン スティッキーセッションを無効化し、redisにセッションを保持させる場合 負荷分散とスティッキーセッションの設定 × セッションの保存場所 1. はじめに AWS ECS上でRails on Railsで開発したWebアプリケーション(以下Railsアプリ)を運用する際、ユーザーごとのセッション管理は重要なポイントです。 負荷分散を行いた

記事詳細
[AWS ECS + Rails] スティッキーセッションとCSRFトークンエラー対策
AWS コラム

お問い合わせはこちらから