ディープラーニングを活用した作詞ツールを作った

[個人開発 Advent Calendar 2018](https://qiita.com/advent-calendar/2018/private-development) の11日目の記事です。

楽曲制作における作詞を支援する Web アプリ [Shikaki](http://shikaki.diatonic.codes/) （シカキ; 詞書き・詩書き）を作りました。歌詞の生成にディープニューラルネットワーク (DNN) を使っています。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">歌詞作成ツール Shikaki (シカキ) のデモです。<a href="https://t.co/foWGLFmBzb">https://t.co/foWGLFmBzb</a> <a href="https://t.co/uMrQclcraA">pic.twitter.com/uMrQclcraA</a></p>&mdash; tanikawa (@diatonic_codes) <a href="https://twitter.com/diatonic_codes/status/1072462476082667520?ref_src=twsrc%5Etfw">2018年12月11日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<img width="751" alt="shikaki_0.png" src="https://qiita-image-store.s3.amazonaws.com/0/19511/794f555e-10e9-4dd1-8edd-2d7e781d6e4b.png">

2018年4月に初版を公開し、現在も細々と開発を続けています。


## アプリ概要

Shikaki は、いわゆる「歌モノ」を制作する上で、作詞が苦手な人（私です）や、作詞のアイデアに困っている人を手助けしてくれるツールがあればいいなと思い、開発しました。

主な特徴・機能は次の通りです。

* 歌詞を自動生成できます
* セクション（A メロ、B メロ、サビなど）単位でメロディの音数をコントロールできます（※ただし正確性は保証していません）
* 歌詞生成後に特定の単語をピンポイントで生成しなおすことができます
* 歌詞が気に入らなければ手動で修正できます

作詞をすべて AI に任せるのではなく、あくまでも作詞の主体は人間にあって AI はそれを支援するものである、というコンセプトで開発を行っています。


## 歌詞生成の仕組み

現在のバージョンでは、ごく基本的な LSTM 言語モデルを使っています（なので、生成される文の質もたかが知れています…）。
ただし、メロディの音数をコントロールするために、音数の情報を LSTM の初期状態としてセットするようにしています。その後の音数の消費は LSTM のセルに管理させます。うまくいけば、LSTM がすべての音数を消費したと判断した時点で、文末記号 `<EOS>` [^1] が出力されるはずです。

![shikaki_1.png](https://qiita-image-store.s3.amazonaws.com/0/19511/d685dec0-3d97-5df0-e493-1a5bbb317e89.png)


## 運用環境・使用技術など

運用環境は次のような構成です。かなりシンプルですが、現状のアクセス数だとこれで十分です。

![shikaki_2.png](https://qiita-image-store.s3.amazonaws.com/0/19511/66920f34-6361-fd5e-1c33-5627695e0877.png)

使用しているインフラ、言語、ライブラリ等は次の通りです。

* サーバ
    * AWS EC2 (t2.small)
* Web フロントエンド
    * [Vue.js](https://jp.vuejs.org/index.html)
        * 複数人で規模の大きい開発の場合 React を使いますが、個人でなんとなく開発する場合はだいたい Vue を使っています。
* Web サーバ
    * Node.js
    * [Koa](https://koajs.com/)
    * [node-canvas](https://github.com/Automattic/node-canvas)
        * 作成した歌詞のテキストを画像化して Twitter に投稿するための機能で使用しています。
* 歌詞生成エンジン
    * Python
    * [Chainer](https://chainer.org/)
        * DNN モデルの実装に使用しています。
    * [MeCab](http://taku910.github.io/mecab/)
        * 単語の分割および単語の読みの取得に使用しています。単語の読みは音数の計算に反映されます。

歌詞生成エンジンを Web API 化してフロントエンドと直接やり取りをする方がシンプルで良い気もしますが、今後の機能拡張（eg. ユーザ管理、…）を想定して、個人的に書き慣れている Node.js で Web サーバを間に置く構成にしました。

### DNN モデルを動かすために

ディープラーニングといえば、GPU が搭載された高スペックなマシンが要求されるというイメージがあるかもしれませんが、小規模なモデルの場合、推論（学習済みモデルの利用）自体は CPU のみの環境で問題ないことも多いです。
このアプリで使用しているモデルも規模は大きくないので、モデルを動かすために最低限必要なリソースやレスポンスタイムなどを考慮した上で、できる限り費用を抑えた結果、t2.small で動かすことに落ち着きました。 [^2]

もしも GPU インスタンス p2.xlarge で運用した場合、1ヶ月で12万円以上の費用が飛びます。おそらく私の収入では破産するでしょう。CPU で動いてくれて良かったです。


なお、Web ブラウザ側で推論処理を行う方法もありますが、JavaScript のディープラーニング系のライブラリは、Python に比べて機能が限定されるため、実現が困難な場合もあります。このアプリでも、組んでいるモデルを JavaScript で動かすのが難しかったことから、サーバ側で推論処理を行うことにしました。 [^3]


## 課題

いろいろと開発タスクは残されているので、今後もアップデートを続けていきます。

やりたいことは [ロードマップ](https://trello.com/b/n6kGTZkC/shikaki-product-roadmap) として記録することにしました。


## おわりに

クオリティはまだまだなツールではありますが、まずは基本コンセプトを示すこと大切だと思い、現在公開をしています。
ぜひ使ってフィードバックをいただけると幸いです。

[歌詞作成ツール Shikaki（シカキ）](http://shikaki.diatonic.codes/)


[^1]: この場合、End-Of-Sentence ではなく、End-Of-Section かも。
[^2]: ちなみに、モデルの学習には P2 インスタンスおよび、自前の GPU マシンを使用しました。
[^3]: 今であれば [ONNX.js](https://onnx.ai/) の使用が候補として挙がりますが、ONNX.js は LSTM に対応していないので、モデルの構造を変えないと難しいです。自作の DNN モデルをブラウザで動かしたい方は、実装前にまず、使いたい関数や操作をライブラリがサポートしているか確認することが重要だと思います。