🥺

君には今から3時間で機械学習Webアプリを作ってもらうよ

2022/05/28に公開
1

新人: 「本日データサイエンス部に配属になりました森本です!」
先輩: 「お、君が新人の森本さんか。僕が上司の馬庄だ。よろしく!」

新人: 「よろしくお願いします!」
先輩: 「さっそくだけど、練習として簡単なアプリを作ってみようか」
先輩: 「森本くんは Python なら書けるかな?」

新人: 「はい!大学の研究で Python 書いてました!PyTorch でモデル作成もできます!」
先輩: 「ほう、流石だね」
新人: 😊

先輩: 「じゃ、君には今から 3 時間で機械学習 Web アプリを作ってもらうよ
先輩: 「題材はそうだなぁ、写真に写ってる顔を絵文字で隠すアプリにしよう」
先輩: 「あ、デプロイは不要。ローカルで動けばいいからね。顔認識と画像処理でいけるよね?」

新人: 😐
新人: (えぇぇぇぇぇぇぇ。3 時間?厳しすぎる...)
新人: (まずモデルどうしよう。てかもらってるノート PC だと GPU ないから学習回せないよな)
新人: (Web アプリ Flask くらいしか触ったことないし、JS とか良く分からんぞ...)

手を付ける順番を整理しよう

先輩: 「あ、Python の開発環境は用意してあるからね」
先輩: 「時間もないし、まず手を付ける順番を整理しようか。最初はどうする?」
新人: 「えーっと。深層学習モデルを使って、写真から顔の範囲を特定します」

先輩: 「いいね!次は?」
新人: 「顔の範囲に絵文字の画像を重ねて、顔を隠します」

先輩: 「おっけー。重ねる顔文字画像はこっちでを用意するね。次は?」
新人: 「画像のアップロードと、加工画像を表示する機能をもつ Web ページを作ります」

先輩: 「素晴らしい。何も教えることないね」
新人: 「ありがとうございます!あの質問してもいいですか...?」
先輩: 「いいよー。」

ベースラインを決める

新人: 「今もらってるノート PC だと GPU が付いてないので、学習回せないんですが...」
先輩: 「え?3 時間しかないのにモデルの学習からやろうとしてたの?」
新人: 「え?違うんですか?」

先輩: 「まず第一に僕たちは学者でも研究職でもないよ。」
先輩: 「一から素晴らしいモデルを作って SOTA を叩き出す必要はないし」
先輩: 「機械学習コンペのように細かい精度を競う必要もない」
先輩: 「最初は簡単に試せる AutoML とかを使ってベースラインを決めるんだよ」

新人: 「なるほど」

先輩: 「ベースラインとなるモデルで要件を満たせれば OK」
先輩: 「満たさなければ他のライブラリや学習済みモデルを試してみる」
先輩: 「それでもダメなら初めて、一から自分で作ることを考えるんだ」
先輩: 「自分でモデルを作るのは、最初から選ぶ選択肢ではないかな」

新人: 「わかりました。調べてみます」

〜〜 新人、ググる 〜〜

新人: 「face_recognitionというのがありました!PyPI で公開されてるみたいです」
先輩: 「おっけ!それで試してみよう」

新人: 「こんな感じですかね?」

im = Image.open("test-image.png")
image = np.asarray(im)
face_bboxes = face_recognition.face_locations(image)

先輩: 「いい感じだね!次は画像の重ね合わせかな」
新人: 「これは pillow で簡単に出来そうです」
先輩: 「素晴らしい!」

Python でもフロントエンドが書けるよ

先輩: 「次は Web ページを作っていこうか」
新人: 「実は僕 HTML/JS/CSS とかは全然分からないんです」

先輩: 「データサイエンティストでフロントも書ける人は多くないかもね」
先輩: 「でも最低限の知識は必要だから、勉強はしといてね。」
新人: 「分かりました」

先輩: 「とは言いつつも、実は Python でもフロントエンドが書けるよ
新人: 「え?Jinja とかでテンプレートを作るとかですか?」

先輩: 「それでもいいけど、今回はStreamlitを使おう」
先輩: 「Streamlit なら HTML/JS/CSS は一切使わずにイケてる UI のアプリを作れるんだ」
新人: 「それはいいですね」

先輩: 「簡単に学べる本を教えるから、こっちも読んでおいて」
先輩: 「今日は時間ないから、必要最低限の機能だけ使っていこう」

新人: 「分かりました!よろしくお願いします!」

〜〜新人、Streamlit で実装〜〜

新人: 「出来ました!こんな感じです」

実行イメージ(男)

先輩: 「いいね!なんとか 3 時間以内に出来たね」
新人: 「先輩のおかげです!ありがとうございます!」

保守しやすいコードを書くことを忘れないでね

先輩: 「アプリは問題なく動いてるかな?」
新人: 「そうですね。ただ、うまくいかない画像もあります」

実行イメージ(三銃士)

先輩: 「これは横を向いてる顔を認識できてないね」
先輩: 「こういう時はどうすればいいと思う?」

新人: 「今回は face_recognition をベースラインとして採用しましたが」
新人: 「精度を改善するために他の学習済みモデルを試す選択肢があります」
新人: 「それでもダメなら自分でモデルを作ったり Fine-Tuning を試します」

先輩: 「いいね!じゃソースコードを見せてくれるかな?」

〜〜先輩、コードレビュー〜〜

先輩: 「うーん、ちょっとリファクタリングが必要かな」
先輩: 「動くことは正義だけど、保守しやすいコードを書くことを忘れないでね

新人: 「分かりました!どういったところを直せばいいでしょうか」

先輩: 「TypeHint と変数の命名の 2 つ意識してみようか。」
先輩: 「TypeHint は知ってるかな?」

新人: 「いえ、初めて聞きました」

TypeHint を書いてコードの質を上げていこう

先輩: 「TypeHint は変数につける型のヒントのことだよ」
先輩: 「例えば次のようなコードがあったとする」

def add(a, b):
    return a + b

先輩: 「これだと数値の和をとるのか、文字列結合するのか分からない」
先輩: 「これに TypeHint をつけると次のようになる」

def add(a: int, b: int) -> int:
    return a + b

先輩: 「これでaddint型の足し算をする関数だと分かるよね」
新人: 「Java みたいに型を明示するってことですか?」

先輩: 「そうだね、でも Java などの静的型付け言語と違うよ」
先輩: 「TypeHint はあくまでも型のヒントなんだ」
先輩: 「だから add に文字列を渡してもエラーにはならない」

新人: 「え?じゃあ何のために書くんですか?」
先輩: 「まず開発者の意図がコードで示すことが出来るね」
先輩: 「チームメンバや未来の自分がコードを理解するのに役立つよ」

新人: 「なるほど」

先輩: 「また、flake8mypyといった静的解析ツールと組み合わせることで」
先輩: 「実行前にエラーに気づくことが出来るんだ。TypeHint を書くことをオススメするよ」
先輩: 「TypeHint を書いてコードの質を上げていこう
先輩: 「この辺を学べる本も教えとくから、これも読んでおいてね」

新人: 「分かりました」
新人: (また課題図書が増えたよ...)

変数名は分かりやすく

先輩: 「次に変数の命名だけど、ここのr, lは何?」
新人: 「あ、right, leftです」

先輩: 「じゃそのままright, leftって書こうか」
先輩: 「変数名の予測は IDE で出来るし、変数名が長いのはそれほどデメリットじゃない」
先輩: 「それよりも 1 文字でよく分からない変数名の方が困るかな」
先輩: 「変数名は分かりやすく、が基本だからね」
先輩: 「あと、左の x 座標って意味だと思うからleft_xとかでもいいかもね」

新人: 「なるほど、1 文字の変数名は全部直します!」

先輩: 「あー 1 文字の変数名が絶対悪って訳じゃないよ」
先輩: 「lambda x:とか変数の有効範囲が小さければ 1 文字で OK」
先輩: 「この辺はリーダブルコードとか読んで勉強してみてね」

新人: 「はい...」
新人: (また課題図書が増えた...きついなぁ)

先輩: 「新人の頃は色々読む本が多くて大変だろうけど、頑張ってね」

新人: 「頑張ります!」
新人: (この人エスパーかよ)
新人: 「あの、先輩ピーナッツ好きですか?」

先輩: 「いや、カシューナッツの方が好きかな」
先輩: 「そんなことはおいといて、リファクタリングと機能拡張お願いね」
先輩: 「これは 3 時間とは言わず、明日 1 日使ってくれていいからね」
先輩: 「出来たら GitHub に push しといて」

新人: 「分かりました」
新人: (大変そうな部署に配属になったなぁ...)

〜〜翌日〜〜〜

新人: 「先輩!GitHub に push したので確認お願いします」

先輩: 「お〜確認しとくわ。どんな感じになったかデモ見せてくれる?」
新人: 「こんな感じですね」

実行イメージ

先輩: 「いい感じだね!じゃ後でコードレビューしとくわ」
先輩: 「明日からはちゃんとした業務だけど、この調子で頑張ってね」

新人: 「はい!頑張ります!」
先輩: 「よし、じゃ今日は飲みに行くか」

〜〜 To Be Continued... 〜〜

最後に

(今更ながら...)こんにちわ alivelimb です。
今回はこれまでと趣向を変えてコミカルな会話調で執筆してみました。書いてて楽しかったので、また会話調の記事も書いてみたいと思います。

振り返り

さてスパルタな先輩さんでしたが、言ってることは一理あります。今は簡単に機械学習モデルを試せるサービス・ライブラリがあるので、まずはベースラインを決めるのは大事なことです。

今回利用したface_recognitionの他にもパッケージであればmediapipe, facenet-pytorchやサービスであれば SageMaker(AWS), VertexAI(GCP)などが挙げられます。

また、簡単なデモアプリを作るのにStreamlitは強力です。データサイエンティストには Python や R, C++を書ける方が多いと思いますが、React や Vue といった JavaScript(TypeScript)のフレームワークを書ける方は多くないと思います。Streamlit を使うとやや自由度は減るものの、簡単に WebUI を作ることができます。

Streamlit はデータサイエンス系のデモアプリを想定していますが、普通の Web アプリケーションのデモアプリにも使えます。先輩さんも紹介していましたが、こちらに関しては書籍を書いているので適宜参考にしてください。

(2022.06.01 追記)
思った以上にいいねを頂けたので、後日談と称した補足記事を書きました。

Discussion