建設予定地

当面はやったことの備忘録

Open Hack U 2020 Vol.4に参加して

はじめに

開催からだいぶ間があいてしまいましたが、先日参加したヤフー主催のハッカソンOpen Hack U 2020 Vol.4の振り返りを行いたいと思います。
今回、惜しくも入賞は叶いませんでしたが、1つのプロダクト開発のために駆け抜けた2週間は楽しかった。

Open Hack Uについて

hacku.yahoo.co.jp

  • ヤフー社員の方のサポートのもと、学生が2週間でプロダクトを企画・開発・発表するイベントです。
  • 今回はチームメンバーの対面での開発禁止という完全オンラインの形式で開催されました。

本番のプレゼン動画
www.youtube.com

作ったもの

自分達のチーム「焼肉焼いたら家焼くな」では、「漫才」×「言語処理」をテーマに、あるキーワード(ボケ)に対して韻を踏んだ太めなキーワード(ツッコミ)を返してくれる漫才LINEBotを作りました。
元ネタはタイムマシーン〇号な某芸人さんです。

デモ動画はこちら
youtu.be

GitHubソースコードはこちら
github.com

開発期間

最初の1週間は事前学習にあてていて、実際の開発期間は1週間でした。

仕様技術

  • LINE Messaging API
  • Python
  • Heroku(本番運用)
  • ngrok(開発用サーバー)

アルゴリズム

大まかなロジックは
入力された文字列をローマ字に置き換える

母音が一致する食べ物関連の単語を辞書(csvファイル)から引っ張ってくる

ここから最も太らせスコアの高いものを出す

というものでした。

詳しい実装の流れとして、
ユーザーにより入力されたワードのローマ字変換をライブラリ(pykakasi)で行う。
同様に単語辞書のキーワードもローマ字への変換を行い、さらに母音に変換する前の単語をリストのインデックスから分かるように辞書を作成しておく(pandas)。
ユーザーワードと、食べ物関連の単語辞書からそれぞれ母音を抽出したものを引数としてランキングを生成する関数に渡す。
ここでスコアを生成する関数を呼び、渡されたワードの文字列がリストのものよりも長い/短い場合、短すぎる/長すぎる文字列にマイナス報酬を与える処理を行う。
上記の処理の結果より、母音変換前のリストのインデックスとスコアをセットで取得し、ランキングをfor文で回してトップスコアの単語を母音分解前のものに戻し、日本語に復元してメインクラスに返す。

このアルゴリズムには、母体となるデータ(単語辞書の語彙)が不足していることから、返しが特定のワードに偏ってしまう、思うように韻が踏めているとは言い難い(5文字の入力ワードに対して2文字の韻踏みワードがかえってきてしまうなど)という問題点がありました。

より精度を上げるため強化学習周りの調整として、

  • 辞書の語彙数を増強

  • ラップの韻踏みで重要視される末尾の得点変化率を強くする

などの調整を行いました。
精度の向上については、文字数ごとの単語辞書を作ったり、スコアリングのチューニングをユーザーにゆだねた双方向性的なシステムにする、というような調整も可能そうです。

当初はライブラリ(Word2Vec)で単語をベクトル化し、太らせスコアを出す予定でしたが、 Word2Vecの引数にローマ字をわたせず、スコア化にあたって上記のような自前のアルゴリズムを実装した、というような経緯がありました。

また、今回は実装が間に合いませんでしたが、マルコフ連鎖を用いて文章レベルでの応答を実現させるという展望もありました。

f:id:denham:20210326233915p:plain 秀逸な返しの例

開発方法

基本はDiscordで集まって夜通し作業や進捗共有をし、開発はソースコードをColaboratoryで共有しあいながら行いました。
LINEBotでのフロント処理を行う部分と、バックのpythonアルゴリズムをクラスで切り分けてしまえば、
機械学習ライブラリの試しや細かい調整などは共通プラットフォームであるColaboratoryで行うのが一番だったためです。

僕は今回、ライブラリ調査やスコア化アルゴリズムの実装、デプロイ環境周りの調整を行いました。
また、本番環境にAWS(Lambda)を導入したかったのですが、こちらは実装が間に合わず頓挫。
というのも、pykakasiのような外部モジュール扱いになるpythonライブラリを、Lambdaの実行環境(レイヤー)に導入することが出来なかったためです。 pythonのバージョンを下げて再構築など行ったもののうまくいかず...。

Lambda パッケージ用にDocker イメージを使用する などの方法を用いればうまくいきそうな気がしています。
要研究ですね。

ログ監視の所感

デプロイ回りは最終的にはHeroku、開発時と発表時はngrokで行っていました。
f:id:denham:20210326232841p:plain 発表時のサーバー稼働中はPCが激重案件。もっともchoromeのタブをゆうに50件は開いていたため、実にブラックな労働環境を強いていました。ごめんね。

とはいえログを眺めていると気が付くことはあって、POST過多による処理落ちかなぁと思っていた部分が、ランキングリストのデータが空のときのエラー落ちの可能性が高そうだ、と見ています。
ということは、ここは精度調整と絡めれば改善の見通しが立てられそう

最後に

めちゃくちゃ面白いアイディアの企画・立案、完璧なチームマネジメントとスライドの作成兼発表をやってくれたS君(段取り完璧すぎた。彼の声掛けがないと自分はハッカソン自体参加してなかったです)、
アイディア実装の核となる韻踏みアルゴリズムの発案と機械学習周りの実装、最後まで絶妙なスコアリング調整をやってくれたO君(最終日の朝6時半までともにAWSと格闘してくれて感謝!)
LINEBotのナイスな掛け合いの実装やリッチメニューなど画面デザイン、ピンポイントでGitHubソースコードを共有してくれたNさん(最終日激アツでした、ありがとう!)、

2週間お疲れさまでした。
次はジョ〇マンBotやりましょう!

(奇しくもインターン先でAWS機械学習を触らせてもらえることになったので、AWS力をなるたけたくわえておきます。)

LINEの友達登録はこちらから。
f:id:denham:20210326235530p:plain
ぜひ遊んでみてください!