私は仕事で AI 機能の開発に取り組み始めました。使いにくい古い専門ツールを回避できるチャンスを見つけたからです。もちろん、すべてのスタートアップはAIスタートアップである必要があります。この機能のプロトタイプを作成しているときに、奇妙に馴染みのある問題にいくつか遭遇しました。そこで日記を調べ、パンデミック前に友人と作った赤ちゃん翻訳機の Maggie を見つけました。あれからほぼ 7 年が経ち、最先端の技術は大幅に進歩しているものの、AI のテストと本番環境の展開を悩ませていたのと同じ問題が依然として解消されていません。ここでは、私のメモ、考え、Maggie のコードについて振り返り、AI を本番環境化するまでの一般的な問題を示します。お役に立てれば幸いです。
マギーは、同名の番組に登場するシンプソンズの末っ子の名前です。マギーはまだ話せない赤ちゃんです。マギーの叔父のハーブは、ビジネス上の判断を誤ったことでどん底に落ち、シンプソンズに引っ越します。彼は姪と、姪が話せないことに対する家族の不満からヒントを得て、奇跡的に機能する赤ちゃん用翻訳機を作りました。同じように、赤ちゃん用翻訳機を作るというアイデアは、私の友人クリスの妹との関係から生まれました。妹は言葉をなかなか覚えられなかったのです。そこで、私たちはアプリをマギーと名付けました。
クリスは当時、赤ちゃんの研究室で働いており、特定の年齢の子供が発することのできる音のスペクトルには生理的な限界があることに気付きました。この洞察から、彼はトレーニング データを収集し、赤ちゃんの泣き声の分類モデルを構築しました。物理学を専攻し、コンピューター サイエンスの経験がなかったクリスにとって、これは素晴らしい偉業でした。
私たちはエンジニア・サービス・ラーニングという授業を一緒に受けていました。その授業では、クラス全員がキャンパス内の建物の 1 つに LEED 認証を取得する取り組みをしていました。彼はロングボードに乗って教室に入ってくる楽天的な人だったのを覚えています。私たちが初めて会ったのは教室の外、食料品店の暗い駐車場で、そこで彼がダートバイクに乗る準備をしているのを見ました。彼は私の車の隣に車を停めていたので、私たちは話をしました。それから私は彼の隣にくしゃくしゃになった紙切れがあるのに気づき、それを拾い上げ、それがお金だと気づき、彼がお金を落としたと伝えました。彼は自分のものではないと言いましたが、私は彼に取っておくように言いました。駐車場が暗すぎて、それがいくらだったかはわかりませんでした。1 ドル、10 ドル、あるいは 100 ドル。私は 100 ドルだったらいいのにと言いました。実際は 10 ドルでした。しかし、その最初の交流で私たちの間には十分な信頼が築かれ、数週間後、私たちが 2 人ともベンチャー ラボ (カリフォルニア大学マーセド校のスタートアップ インキュベーター) で働いていたとき、彼は私に彼の赤ちゃん用翻訳機を展開するアプリを作るように頼んできました。ベンチャー ラボがなければ、私たちは決して協力しようとは思わなかったでしょう。私は Android アプリを開発していると、クラスメートに言いふらしたりはしませんでしたし、彼も自分の未熟な翻訳モデルを自慢したりはしませんでした。対面式の第三の空間には、人を惹きつける魅力があり、それを過小評価すべきではありません。
実用的なモデルを構築したにもかかわらず、Chris はそれをどのようにデプロイすればよいのかわかりませんでした。これは 2017 年の初めのことで、これをデモンストレーションするコースやガイドはあまりありませんでした。TensorFlow の彼の指導者は Android へのデプロイを勧めましたが、モバイル開発を学ぶのは難しすぎました。私は Android を知っていて、Play ストアに複数のアプリをデプロイしたことがありましたが、それでも私にとっては無理でした。そこで、簡単な方を選びました。
モデルをサーバー上に置き、API 呼び出しを行いました。Flask サーバーでモデルを実行するのは驚くほど簡単でした。TensorFlow をインポートし、ローカル ディスクからモデルをロードし (後になってバージョン管理しやすい方法でモデルを展開することなど考えもしませんでした)、リクエストをそのモデルに向けるだけです。ただし、いくつか注意点がありました。
これらの問題にもかかわらず、それはうまくいきました。モデル入力パーサーとトランスフォーマー コードを共有することで、最初の問題は解決しました。モデルをブラック ボックスとして扱い、モック化することで、モデルを中心とする統合テストの構築が容易になりました。これらのテストにより、モックが正確である限り、サーバーとモデルの間に予期しない不整合がないことが保証されます。現在では、開発中にモックの正確性を確保できるモデル インターフェイスがあります。モデルの展開とバージョン管理は、今日のほとんどのユース ケースで新しいソリューションを必要とする問題ではありません。
一方、レイテンシと可用性の問題により、最終的にはエッジのアプリにモデルを展開することになりました。これにより、ネットワーク レイテンシがなくなり、携帯電話のはるかに高速な CPU が使用され、アプリがバックグラウンドで実行され続けるという利点があり、起動レイテンシの問題が解決され、ホスティング コストが削減されました。しかし、もちろん、新たな問題もありました。
モデルをどこに置くか、かなりの時間をかけて議論しました。携帯電話のスピードと確実性を求めていましたが、サーバーのセキュリティと展開のしやすさも求めていました。当初、モデルをサーバーに置くことは魅力的でした。
最終的に、最初の 2 つの理由から、モデルをアプリに組み込むことにしました。つまり、翻訳を待たなければならなかったり、ときどきダウンしたりしたら、アプリは魅力的ではありません。泣いている新生児を腕に抱いていると、数秒の遅延は永遠のように感じられます。しかし、次のセクションで説明するように、モデルを電話に組み込むことには問題がありました。
このことから私が得た教訓は、ソリューションが拡張可能でなかったり、将来の成長をもたらさなかったり、IP を危険にさらしたりしても、最高のユーザー エクスペリエンスを実現するために最適化する必要があるということです。企業の存亡はユーザー エクスペリエンスにかかっています。特に、信頼を獲得してブランドを構築する必要がある新興企業の場合はそうです。
モデルをスマートフォンに搭載するには、山ほどの技術的困難が伴いました。現在では存在しないものもありますが、ほとんどは存在します。私たちは最先端にいました。TensorFlow for Android がようやく登場したばかりで、一般公開されたのは 2017 年 2 月で、私がアプリを構築していたのは 3 月でした。しかし、粘り強く取り組み、TensorFlow のPete Wardenから多大な支援を得て、モデルをアプリで動作させることができました。
最初の問題は、モデルを APK パッケージに組み込むことでした。当時、Android には 50 MB の APK 制限があり、インストール後にコンポーネントをダウンロードすることでアプリのサイズを大きくできる拡張機能がありました。しかし、拡張機能はモデルをサーバーに公開することを意味するため、安全ではないと判断しました。そこで、アプリを量子化することにしました。これは、すべてのレイヤーのすべての入力と出力の精度を下げる手法です。
私たちの場合、すべての浮動小数点数を整数に変換しました。これにより、モデルのサイズが大幅に縮小され、高速化されましたが、精度も低下しました。Chris は、さまざまな量子化スキームを使用してモデルを数回繰り返し、精度の低下にもかかわらず、最終的に整数量子化に落ち着きました。モデルが新しい親よりも優れたパフォーマンスを発揮する限り、これは有用でした。ボーナス: 更新の問題も解決しました。モデルの更新ごとに数百 MB のデータをダウンロードするのは、従量制のインターネット接続では負担が大きすぎましたが、数 MB なら管理可能でした (今では、人々は携帯電話で GB 単位のビデオ コンテンツを定期的にダウンロードしているので、これは馬鹿げているように思えます)。
その後、小さな問題が次々と発生しました。最も大きな問題は、Android に同梱されている Java のさまざまなバージョンでサポートされている FFT ライブラリが、モデルのトレーニングに使用されたスペクトログラムと同じものを生成しなかったことです。私たちは C++ FFT ライブラリを使用してモデルをトレーニングしましたが、異なる色と次元のスペクトログラムが生成されました。秘密のツールであるため、C++ と Java の両方のバージョンは不透明に記述されており、変更が困難でした。もう 1 つの迅速な決定は、Java FFT スペクトログラムを使用してモデルを再トレーニングすることにしました。これは、すべてのオーディオ ファイルをスペクトログラムに変換してからトレーニング プロセスを実行することを意味し、友人の古い Macbook で数日かかりました。しかし、問題は解決し、その間に他のことに集中することができました。
しかし、アプリはフリーズとクラッシュを繰り返しました。録音をメモリにロードしてからメモリ内にスペクトログラムを作成するのは悪い考えだったことが判明しました。アプリは携帯電話のリソースを大量に消費していました。解決策は、ディスクに保存してストリーミングすることでした。ディスクへの保存は簡単でしたが、ストリーミング部分は困難でした。オーディオがメモリから出ると、ディスク上で何が起きてもおかしくなかったからです。別のプログラムが読み取って変更したり、削除したり、保存に失敗したりできます。これらのエッジケースは、通常、Web 上には存在しません。ユーザーとの隔離されたチャネルはありますが、デバイス上にはありません。そもそもこれを行うのに十分なスペースがあることを確認し、アプリの後にクリーンアップすることは、予想外の課題でした。後でわかったことですが、携帯電話にアプリをインストールするのに十分なメモリがあれば、アプリを実行するのに十分なメモリがあると考えるのは誤った前提でした。
最後に、デバイス自体が敵でした。Android スマートフォンには、さまざまな CPU、メモリ量、そして最も重要なマイクが搭載されています。CPU とメモリの問題は、必要な Android バージョンを最新に設定して最善を期待することで解決できます。最悪のシナリオはアプリの速度低下です。Android でリソース要件を直接設定する方法はありません。実際の問題は、マイクのさまざまな品質を考慮することでした。Android では、アプリがインストールされているデバイスにマイクを要求できますが、マイクの種類は要求できません。
私はこの問題を解決しようとはしませんでした。当時、私はテスト用の携帯電話をたくさん持っていて、安価な携帯電話での予測がいかに悪いかに気付いていました。今、解決策を見つける時間はないと判断しました。私たちはできるだけ早く発売しようとしていたのです。時には、問題に対する最善の解決策は、それをメモして先に進むことです。今となっては、この問題が私たちを最終製品、スマート スピーカー Homer へと導いたことに気づいています。
技術的な困難を克服 (または回避) した後、予測品質というより困難な問題に取り組みました。モデルはアプリ上で動作していたため、そのパフォーマンスはわかりませんでした。パフォーマンスが悪かった場合、アプリ ページのコメントやアンインストールを通じてしかわかりませんでしたが、その時点では手遅れでした。そのため、モデルに関するログ、監視、データ収集、フィードバックのラッパーを構築することが重要でした。
モデルはスペクトログラムと他のいくつかの情報を使用して、赤ちゃんの発する音を分類しました。空腹、不快、痛み、眠気、ガスが溜まっている、これらが翻訳でした。モデルは、すべての可能性のあるカテゴリのリストを返し、各カテゴリには、その特定の翻訳に対するモデルの信頼度を表すパーセンテージがあります。すべてのパーセンテージを合計すると 100 になります。最も正確な翻訳が 90% の空腹である場合、他の 5 つのカテゴリの精度は合計すると 10% になります。
当初私たちが直面した問題は、すべての翻訳を表示するか (最も正確なものから最も正確でないものの順に)、それとも 1 つだけを表示するかということでした。翻訳を多くして人々を混乱させたくなかったことと、この方が構築が簡単だったこと (怠惰はアジャイルの基礎です) から、1 つだけを表示することにしました。しかし、最初のユーザー セットで問題が発生しました。
モデルが確実だった場合 (80% 以上)、提案は機能し、保護者からの苦情はありませんでした。しかし、常にそれほど自信があったわけではありません。翻訳の精度が 80% を下回った場合、親の推測と同程度でした。これではアプリの目的が達成されません。アプリは、慌てて子供をなだめようとする新米の親の試みよりも正確な翻訳を提供する必要があります。そして実際にそうなりました。当然のことながら、2 回目または 3 回目の翻訳は正確でした。私たちは対面インタビューを通じてこれを発見しました。対面インタビューはスケーラブルではなく時間がかかりますが、情報量が非常に多いです。毎日 1 回実施できる場合はそうしてください。赤ちゃんが泣くと、アプリは信頼性の低い間違った翻訳を表示しますが、私たちは他の翻訳 (ログで確認) を試し、それが機能しました。
これは私にとって直感に反するものでした。なぜなら、私はこのアプリを翻訳機だと考えていたからです。何かを翻訳する方法は 1 つしかないはずですよね? 違います。このアプリは、新米の親や保護者が最初に試すべきことを判断するための探索ツールでした。赤ちゃんにげっぷをさせてみようか? お腹が空いているか? 最後にお昼寝をしたのはいつ? 赤ちゃんが泣き始めたら、すべての親がこのチェックリストを確認します。私たちのアプリはこの探索をスピードアップしました。親たちはこのようにアプリを使用し、複数の翻訳を展開したときに得たフィードバックもそれでした。これはキラー機能ではありませんでしたが、アプリを単なる小道具から日常的に使用するツール、配偶者がいないときや祖父母が寝ているときの信頼できる相棒へと確実に変えました。
このデータを基に、私たちはすぐにもっと多くの翻訳を表示することを決めました。問題は、いくつ表示するかでした。すべての翻訳 (5 つのカテゴリすべて) を表示すると、アプリが毎回同じ翻訳を繰り返しているように見えてしまいます。Google が食べ物を検索するたびに同じ 4 つのレストランを表示したらどう思いますか? 私たちは、アートとデータの両方を兼ね備えた上位 3 つの翻訳を選択しました。
人々はなぜか 3 という数字に傾倒します。データによると、3 回目の翻訳以降、モデルの他の翻訳に対する信頼度は大幅に低下しました。最初の翻訳の信頼度が 70% だった場合、2 回目は 20%、3 回目は 9%、残りは 1% 未満になります。そのため、これらの翻訳は削除しました。削除された翻訳が正確である可能性はわずかでしたが、それらを含めるとアプリが繰り返しのように見えてしまうリスクがありました。100 人のユーザーのうち 1 人がすべて間違った翻訳を受け取るか、すべてのユーザーが役に立たない翻訳を見てアプリが推測していると思うかのどちらかでした。これは簡単な選択でした。
もちろん、今にして思えば、マルチアームバンディットを使ってこれをテストすべきでした。つまり、選択肢ごとに 1 つずつ、たとえば 1 つの翻訳を表示する、2 つを表示する、3 つを表示するなど、アプリの 5 つの異なるバージョンをリリースし、最良の結果が得られたバージョンのアプリにユーザーを徐々に移行させるのです。主な成功の指標は、緑のチェックマーク (翻訳に満足している) をクリックした人の数です。しかし、このような早い段階で、私たちは正しい決断をしたと思います。そして、さらに重要なことに、正しい方法で決断したのです。私たちはオープンマインドで、どんな決断も具体的なものとは考えず (エゴはなし)、常にユーザーと連絡を取り合い、たとえそれが正しいとは思えなくても、ユーザーの意見に耳を傾けました。
すべてのやり取りは、改善し、感動を与える機会です。この事業を始めた当初から、このモデルは単に運が良かっただけなのではないか、赤ちゃんが泣いているのはガスが溜まっているからで、げっぷをさせすぎて赤ちゃんが死んでしまうと言われたお父さんやお母さんが一人でも出てくるのではないか、と心配していました。そんなことはまずありませんが、私たちは各ユーザーの赤ちゃんの健康に責任を感じました。そこで、アプリにフィードバック機能を追加してリリースを遅らせました。
翻訳が終わるたびに、どれだけ役に立ったかを尋ねられました。これはスキップできないページです。その後、アプリはユーザーからのフィードバック、モデルの出力、デバイスの種類、スペクトログラムをアップロードしました。最初はオーディオ ファイルをアップロードしましたが、マイクがバックグラウンド ノイズを多く拾っていることにすぐに気付きました。ユーザーのプライバシー保護のため、スペクトログラムのみをアップロードすることにしました。当時は、スペクトログラムを逆順にしてオーディオを再構築できることを知りませんでしたが、品質は低下し、多少の困難を伴います。これが私たちのフライホイールでした。
ただし、この最終版に至るまでの議論や複数の草稿については省略します。収集するデータ、成功の測定方法、成功の定義方法を決めるのは難しいですが、小さなステップで実行して改善できる反復的なプロセスです。私が得た最良のアドバイスは、成功とはどのようなものか、またはそれが難しすぎる場合は失敗とはどのようなものかを定義することです (私にとっては、失敗の定義は成功の定義よりもはるかに簡単です。自分が何を望んでいるかはわかりませんが、避けたいことは確かです)。そして、具体的に定義します。その答えから、取り組みを評価するために使用できる指標を導き出します。失敗とは、赤ちゃんがアプリを使用できない年齢になる前にユーザーを失うことであれば、ユーザーの携帯電話でのアプリの平均寿命を測定します。ただし、これらの定義と指標は静的ではなく、変化することを忘れないでください。決定して、機能しなくなるまでそれに従う必要があります。それらから学ぶことをやめるか、少なくともそれらから学ぶことが難しくなると、それらは機能しなくなります。それが目標です。学習して改善することであり、残りは細かいことです。
AI/ML 時代において、企業にとって最も価値のあるデジタル資産はモデルではなく、託されたデータです。このデータを増やすこと (できれば透明性と倫理性を備えた方法で) は、継続的な成功に不可欠です。したがって、コンバージョン率に関係なく、すべてのユーザー インタラクションを価値創出の瞬間として扱う必要があります。つまり、すべてのインタラクションがユーザーに感銘を与え、また利用したいと思わせるものでなければなりません。私たちは、ユーザーを驚かせ、刺激を与えるものを構築しました。素晴らしいデザイナーであるTeresa Ibarraが、私の粗削りな草稿を、心地よく楽しく使えるアプリに磨き上げてくれました。そして、翻訳するたびに、次のアプリがより良くなりました。
最後に作ったのは Homer です。アプリのユーザーと何十回も面談し、さらに多くの人に電話をかけた結果、泣いている子供を抱きながら、携帯電話を探して画面のロックを解除し、アプリを見つけて開き、翻訳をクリックするのは大変で不便だということが分かりました。なぜこのことに気づくのにこんなに時間がかかったのでしょう。私たちは 20 代の独身で子供のいない男性 2 人でした。赤ちゃんを最後に抱いたのはいつだったか思い出せませんし、泣き声をなだめたことも思い出せません。そこで、スマート スピーカーを使ってベビー モニターを作ることにしました。Raspberry Pi のキットを注文し、上部に大きな青いボタンが付いたカスタムの Google Home スピーカーを作りました。
クリスは、このモデルをベビーモニターの会社に販売するという素晴らしいビジョンを持っていましたが、これらの会社から支持を得ることができなかったので、スマートスピーカーを使って独自のベビーモニターを作ろうと思いました。Google Home を作った後、起動時に翻訳を実行する bash スクリプトを作成しました。この翻訳は、Google Home の SDK を使用して、「OK、Google、翻訳して」というトリガーフレーズで翻訳します。この翻訳は、マイクから音声を読み取り、スペクトログラムに変換してから、サーバーに送信して翻訳する Python スクリプトでした。私はアジャイルなやり方で進め、うまくいきました。ついにキラー アプリが完成しましたが、会社を救うことはできませんでした。
資金が尽きました。コンテストで獲得した賞金です。生活は急速に厳しくなっていきました。私たちは大学を卒業し、2人とも故郷に戻りました。私はベイエリアで仕事に就き、クリスは病気の母親の世話をするためにテキサスに向かいました。スタートアップは失敗しました。
スタートアップは大変で、心が痛みます。パートタイムではできません。利害関係のある全員がフルタイムで働くか、他の人のために場所を空けるために辞める必要があります。あるいは、野望を縮小するか、完全に諦める必要があります。パートタイムで利益を上げて解決できる問題もありますが、それは価値があるのでしょうか。ワクワクしますか。
Android に ML モデルを展開するのは大変だという以外に、私が学んだことがあるとすれば、解決しようとしている問題に本当に関心を持つ必要があるということです。金銭的なリスクや莫大な機会費用をものともせず、フルタイムで取り組む勇気が必要です。この仕事のために技術職を辞めるつもりはまったくありませんでした。新米の親や絶望的な父親を助けるのは大好きでしたし、技術を学んで構築するのは爽快でしたが、卒業後に狭いセクション 8 のアパートに戻る理由を父にどう説明すればいいのでしょうか。長い間生活保護で暮らしてきた私が、6 桁の給料を断れるでしょうか。
ベンチャーキャピタルはどうですか? なぜ資金調達を試みなかったのですか? 現実には、VC は、あなたやあなたが通った学校、またはあなたが勤めていた会社を知っている場合にのみ電話に出ます。彼らはあなたが何を構築したかは気にしません。利益が出ない限り、あなたのイノベーションは些細なことです。VC はまず創業者とチームに投資し、最後に製品に投資します。しかし、ほとんどの VC は良い創業者やチームの選び方を知らないので、エリート校や FAANG の入学担当者に任せています。