MA2018参戦記 - 人工苔と対話する技術

#はじめに
今年の9/6〜11/5の期間で開催された[MashupAwards2018ヒーローズ・リーグ（MA）](https://ma2018.we-are-ma.jp/)という開発コンテストに参加してきました．この記事は，コンテスト参戦記として＆作品の技術的なメモとして記載します．

MAに参加するのは，今回で5回目になります．過去には[こんな](https://protopedia.net/prototyper/makotokoike)作品を作ってきました．
そして，今年の作品が[「鳥籠の人工苔は電気琴鳥の夢をみるか」](https://protopedia.net/prototype/a588a6199feff5ba48402883d9b72700)です．
![koke.jpg](https://qiita-image-store.s3.amazonaws.com/0/29374/70190bdf-1f68-a561-f71b-0a0f872dfdf5.jpeg)

#コンテスト結果
まずは，結果から．

- オレトク部門決勝ノミネート　→　敗退
- インタラクティブ・デザイン部門決勝ノミネート　→　敗退
- みんなで選ぶHEROES 2ndSTAGE　→　敗退

3部門で決勝ノミネートするも，残念ながら受賞には至らずという結果でした．しかし，最後の2ndSTAGEで『技術の無駄遣い枠』で選ばれ，翌日の[FESTA 2018](https://mashupawards.connpass.com/event/105737/)でLTする権利もらって，言いたいこと全部話してきました（会場ポカーンです）<ワーイ！

正直今回の作品は***「地球外生命体と対話する」***なんていう，客観的に見れば**ふざけたシロモノ**（本人は割とマジ）だった訳ですが…なんと言うか，改めてMAの懐の深さを感じる回になりました．いやホントに，マジメにすごい作品からアレな作品まで，とにかく何かしら振り切ってるヤバイ作品（人間？）が集まりますねMAは．

※あっ！今回はパートナーAPIを一切使用しなかったwのでテーマ賞は初めから考えてなかったです

##個人賞
個人賞は９人から頂きました．表彰状の代わりに“かるかん饅頭”くれた方も！
今年から始まった個人賞ですが，〇〇賞で端的に良かった点を伝えつつ「いいね！」ボタンのような手軽さで渡せるという，なんともちょうどいいデザインですね．それに，もらうとなんか作った作品達が報われる感じがして良いです．
<img src="https://qiita-image-store.s3.amazonaws.com/0/29374/880838d2-dec8-6696-c509-1fd97975ffb1.jpeg" width=70%>


#鳥籠の人工苔は電気琴鳥の夢を見るか
ここからは，作品の裏話（というか4分のプレゼンでは話せなかったこと）です．
###言いたかったこと（ほぼ妄想）
作品テーマは「地球外生命体とのコミュニケーション方法を習得するためのデバイス」だった訳ですが，ここでの*"地球外生命体"*とは昨今目覚ましい発展を続けている**人工知能，人工生命**のメタファーです．今後，人工知能（人工生命）が高度に発達した世界で，我々の言語コミュニケーションはどうなっていくだろう…という問が開発の始まりでした．
テッド・チャンのSF短編小説[『あなたの人生の物語』](https://ja.wikipedia.org/wiki/%E3%81%82%E3%81%AA%E3%81%9F%E3%81%AE%E4%BA%BA%E7%94%9F%E3%81%AE%E7%89%A9%E8%AA%9E)からもかなり影響を受けています．

####溶ける言語
例えば，現在の機械翻訳を考えてみましょう．Google翻訳を見ても分かるように，ひと昔前と思うと格段に精度が向上していますね．ここでポイントとなるのは，機械翻訳は日本語から英語，日本語からドイツ語…といったように，各言語間の対応をとっているわけではなく，日本語と**中間言語**の相互変換だけを行うという点です（もちろん，英語と中間言語の相互変換も必要です）．
※実際に中間言語を用いた翻訳が実現しているかは不明ですがGoogleのZero-Shot Translationなどを読むと将来的にはそうなるかもという妄想です

ここで言う**中間言語**とは人間が声に出して発することが出来るようなものではなく，ただの**ベクトル空間**です．あらゆる言語，文法，文化的な言の葉を全て包括して圧縮したベクトル空間です．あらゆる言語が中間言語を介して相互変換可能であれば，もはや人間はどんな言葉を喋るかなんてどうでもよくなりますよね．**自分の発する音声（音波）と中間言語（ベクトル空間）との対応さえ取れれば良い**のです．

さらに，あらゆる言語を内包するベクトル空間には，人間以外のイルカや犬，猫といった動物を含むことが可能になるかもしれません．人，イルカ，犬などの違いは，ベクトルのサブセットとして表現可能であり共通部分は相互変換可能なのです．そうなると，**もやは言語なんて必要なくて，意思を言葉（鳴き声）として出すだけでコミュニケーション可能**になるのかもしれません．どんな言葉（鳴き声）を習得するかは個人の自由になるでしょうし，新しい言葉を作ることも自由です．将来ターミネーターやエクス・マキナ的な人工知性体が出来るとして，彼らはどんな言葉を話すのでしょうか．

もう一つ別の視点から考えると，人工知能が発達した世界では言語コミュニケーションはより高解像度，高コンテキスト，プライベートなものになっていくのではないかということです．まず，
　A「明日のFESTA．10時集合ね」
　B「了解」
なんて会話はする必要がなくなります．何時にどこで（手段）なんて全て人工知能が上手く調整・レコメンデーションしてくれるでしょう．こういったことは，“会いたい”，“集まりたい”という目的をシステムに伝えるだけで，**全て調整された状態で存在する世界**になるでしょう．そんな世界でも残るのは１対１の非常に高密度のコミュニケーションじゃないでしょうか．ツーといえばカーみたいなコミュニケーションで，もはや言語の形を取る必要もなく，**鳥のさえずりのようなものだけで良い**のかもしれません．
※もしくは音声を使わない表情だけのコミュニケーションとか

###対話（未来に必要なコミュニケーション能力とは）
というようなことを考えつつ，中間言語との対応を取るにしても，１対１のコミュニケーションにしても，結局対話とは**言葉の体系を（大なり小なり）自身の中に作り出していく**ということかなと．これが，**未来のコミュニケーション強者になるために必要な能力**なんじゃないかと．じゃあ，どうやって作るのってところは，まずは**他者の意思はブラックボックスである**ということを前提として，言葉の壁打ちから始めてみようと考えた訳です．
<img src="https://qiita-image-store.s3.amazonaws.com/0/29374/6d6002b3-49a9-19d8-03c4-53693d856184.jpeg" width=60%>
（この文脈で『中国語の部屋』を引用するのは，適切かわかりませんが）イメージとしてはこんな感じです．

この“言語体系を自ら作る“という体験を行うデバイスが，今回作った鳥籠の人工苔〜です．

###開発環境
Pythonを使って，Raspberry Pi 3上に実装しました．使用した主なライブラリ（用途）は下記の通りです．

- PyAudio（録音）
- Librosa（MFCC,STFT，ISTFTなど）
- TensorFlow（オートエンコーダ）

###仕組み
仕組みは，下の図の通りです．
中にはオートエンコーダが入っていて，入力音声を復元するよう学習しています．これにより，始めはランダムなノイズしか応答しないのですが，話しかけ続けることにより何かしらの応答パターンを形成していくという仕組みです．
オートエンコーダへの入力はメル周波数ケプストラム係数（MFCC）を使用し，出力はパワースペクトルとしています．最後に，Griffin-Lim法で位相復元を行った後，逆フーリエ変換することで音声データに復元しています．


<img src="https://qiita-image-store.s3.amazonaws.com/0/29374/550d2481-7b97-49fa-a44d-d91d337db74b.jpeg" width=60%>

```python:model.py
#オートエンコーダ部の抜粋
    def _build_encoder(self):
        model_input = Input(shape=[16, 16, 1])
        x = Conv2D(16, kernel_size=5, padding='same')(model_input)
        x = BatchNormalization(momentum=0.8)(x)
        x = Activation('relu')(x)
        x = MaxPooling2D()(x) #16x16x16->8x8x16
        x = Conv2D(1, kernel_size=5, padding='same')(x)
        x = BatchNormalization(momentum=0.8)(x)
        x = Activation('relu')(x)
        model_output = MaxPooling2D()(x) #8x8x1->4x4x1

        model = Model(model_input, model_output)
        return model

    def _build_decoder(self):
        model_input = Input(shape=[4,4,1])
        x = UpSampling2D((8,2))(model_input) #4x4x1->32x8x1
        x = Conv2D(16, kernel_size=5, padding='same', kernel_initializer=RandomNormal(stddev=0.02))(x)
        x = BatchNormalization(momentum=0.8)(x)
        x = Activation('relu')(x)
        x = UpSampling2D((4,2))(x) #32x8x16->128x16x16
        x = Conv2D(8, kernel_size=5, padding='same', kernel_initializer=RandomNormal(stddev=0.02))(x)
        x = BatchNormalization(momentum=0.8)(x)
        x = Activation('relu')(x)
        x = Conv2D(1, kernel_size=5, padding='same', kernel_initializer=RandomNormal(stddev=0.02))(x)
        model_output = Activation('sigmoid')(x)

        model = Model(model_input, model_output)
        return model
```

##人工苔と対話できたのか
３週間ほど話しかけてみました．
「ただいま」「おはよう」「調子どう？」の３ワードを話しかけることが比較的多かったですが，その他にも適当に色々と話しかけています．
…で，相手の応答はというと，始めの3日ぐらいはホワイトノイズしか返ず，４日目には全くなにも応答しなくなってしまいました．

これは失敗かな？と思ったのですが5日目から何か「…ジィーッ　…ジィーッ　…ジィー」と言うようになり，１周間ぐらい経つと応答のパターンが若干わかるようになってきました．

そして，2週間目ぐらいからは私の「ただいま」に対し，毎回**「キュル…ググ…キュキュ…グググ」**みたいな音声が帰ってくるようになりました！**こっ，これは…きっと「おかえり」と言っているに違いない！！**

とう言う感じで，「ただいま」の応答についてはなんとなく判断ができるようになりました…が，それ以外は難しい．
でも，この声にはちょっと愛着を感じるようになった3週間でした．


##今後の展開
タッチ＆トライ中に，
・2台作ってお互いで会話させてみては？
・テレビを見せ続けて（音楽を聞かせ続けて）みては？
というアドバイスを頂きました．どちらも面白そうなので試してみようと思います．

あと，今後も話しかけ続けてどうなるか見てみたいとう声もありましたが…どうしよう．流石にしんどい．
来年のMAでまた同じ作品だったら，「あっ，こいつ人間やめたな」と思って下さい．
では，また来年！