「褒められなくても好きだからやる」プログラミング漫画

王道ではないプログラミング漫画 - 木曜不足の続き。漫画の中身の話。

プログラミング漫画『ぺたスクリプト』には、プログラマーってこういう生き物だよな~という自分の経験や体感をあれこれ盛り込みました。

小学生のときにNHKの『マイコン入門』で覚えた BASIC を、電気屋に並び始めたコンピュータ(今で言うパソコンですが、当時は「マイコン」と呼んでいました)に入力するのが最初のプログラミング体験でした。当時は気の利いたデモ画面やスクリーンセイバーなどもなく、電源を入れただけの BASIC のプロンプトで放置(展示)されていたので、プログラムが入力し放題でした*1

とはいえ、プログラミング初心者が店頭でゼロから入力できるプログラムなどたかが知れていて*2、簡単な数当てゲームや、

10 PRINT "アホ ";
20 GOTO 10

みたいなプログラムを実行して、画面が「アホ」で埋まるのを友達と一緒に指さしてゲラゲラ笑い合う、みたいなしょうもないことをしていました。今のScratchでも、ネコに変な言葉喋らせてゲラゲラ笑うとか是非してほしいんですよね。

役に立つものとか、おもしろいゲームを作るとか、プログラミングでなにか意味のあることをさせようとするのではなく、おこずかいを増やしてもらうため、宿題をサボるため、給食の残りを賭けたじゃんけんに勝つため、宿題をサボるため(2回目)みたいな嬉しいのは自分だけなプログラミングでもいいんじゃないかと。

しかしプログラミング必修化の時代ともなると、そういう変なことをしたら怒られたり(まあ宿題サボったら普通に怒られるでしょうが)、「習ってないことをするな」と厳しく注意されたりしないかがちょっと心配です*3。学校の宿題でプログラミングをやらされたり、授業でやっていないことをすると怒られたりすると、それ以外のことはしなくなって、プログラミングはつまらないと感じてしまいそうです。

前回の記事でも扱った王道系のプログラミング漫画(に限らずノウハウ系漫画全般?)では、基本的には怒られたりすることはなく、ちょっとプログラミングが進んだら、すごいね、やったね、と褒めてくれます。

でも実はそこもちょっと気になっていて、現実にはそんなに都合よく褒めてくれる人はいないし、好きなら褒められなくても、怒られても、けなされても、やめないですよね。

かつてはコンピュータは金持ちの道楽扱いで、プログラミング(プログラマー)には市民権がなく、迫害に近い扱いをされていました。プログラミングが趣味だと言ったらネクラ&キモい、プログラミングを仕事にしたいと言ったら、それだけはやめてくれと親に懇願されたほどです(実体験)。

別に先見の明があったわけではなく、プログラミングがただただ好きだっただけなので誇ったり恨みに思ったりとかは全然なく、でもそうした経験から「褒められるからやる、褒められないからやらない」は危険だな、と思うのです。「褒めて伸ばす」とはある意味真逆の、怒られようがけなされようがプログラミングをやめない漫画だってあってもいいはず。

なので、漫画『ぺたスクリプト』の主人公のアキラはプログラミングで褒められることなんてほとんどなく、怒られたり、お小遣いを減らされたり、反省文を書かされたり、あれやこれやヒドイ目にあいます。まあ怒られそうなことばかりやっているので当然ですが(苦笑)。

それでも次の瞬間には「ぺたスクリプト、サイコー!」「それ、ぺたスクリプトでできるよ!」と、プログラミングで何ができるかばかり探している。そんな漫画があってもいいんじゃあないかなあ。

*1:その一方で、SHARPのMZシリーズのように電源を入れただけだと何もできないコンピュータもあって、ナイコン族(高価なコンピュータを持っていない人をそう呼んでいました)には忌避されていました。しかしあれはプログラムをテープからロードするのを待っている状態で、「BASICのプログラム」をロードしたらBASICが使えるようになると後に知り、「へー、BASICもプログラムなのか! いつかBASICそのもののプログラムを書いてみたいなあ」と思い、その10ウン年後にX68000で「ぺけBASIC」というBASICインタプリタを書いてその夢を叶えました。

*2:たまに怒られて追い払われたりもしました(苦笑)。

*3:うちの娘が低学年だったときには、自分の名前を漢字で書いたら、まだ習ってない漢字だとバツされたことがありました……。

王道ではないプログラミング漫画

2017年に『ぺたスクリプト』というプログラミング漫画を上梓しました。一言でいうと、「日常的なちょっとした困り事をプログラミングで解決する、実際に作れそうな『キテレツ大百科』」です。

創作は作品の中で語らないといけない気がして、積極的な宣伝や説明をしてなかったのですが、出版されて7年経つし、そろそろいいかな、という感じで創作意図や裏話をまとめておきます*1

もともとの経緯としては、学習指導要領の改定で2020年度から小学校でプログラミングが必修となることを受けて、技術評論社さんにて小学生向けのプログラミング漫画の企画が立ち上がったとき、高校時代は文芸部で、その後も趣味で小説や漫画を書いていた中谷に原作のお話をいただきました*2

プログラミング漫画と言って真っ先に思いつくのは、まずは「ゲームで遊びたい子が、パソコンでプログラミングすれば自分の好きなゲームが作れることを知り、褒められながら少しずつ完成させていく」という、すがやみつる先生の『こんにちはマイコン』から脈々と続く王道パターンです。もちろんその王道パターンを最初に検討しつつも、比較的早い段階で他のパターンを探すことにしました。

理由の1つ目は、プログラミング必修化の流れから他の出版社からも同種の漫画が出ることが予想されたことです。実際、同じ2017年に王道パターンのプログラミング漫画が複数出版されました*3。王道パターンは、なにしろ王道なだけあって決して悪くはありませんが、しかし、似た傾向の本がかぶることがあらかじめ予想されるなら、他に行くのは自然な発想ですよね。

王道パターンを採用しなかった理由はネタ被り以外にもあります。王道パターンの場合、その対象読者は「ゲームとプログラミングに興味がある子供」となります。そもそもプログラミングに興味のある子供しかプログラミング漫画を手に取ることはないでしょうし、ゲームはプログラミングのもっとも代表的な入口ですから、とても順当と言えます。なにしろ、自分自身もまさにゲームへの興味からプログラミングを始めた人間でしたし。

ただ、プログラミング必修化の時代になると、プログラミングに興味のない子供がプログラミングに触れることになります。ゲームを遊ぶことには興味があっても、それを自分で作ることには全く興味がない子供もいるでしょう*4。その子たちが王道パターンのプログラミング漫画を手に取ってくれると期待するのはちょっと無理がある気がします。ゲームに興味がない子供にも、というか、ゲームに興味がない子供にこそ読んでもらいたいのです。

さらに王道パターンを採用すると、「パソコンの前で座っているシーン」が多くなりがちという難点もあります*5。まあプログラミング漫画としては必然なのかもしれませんが、もし可能ならそれも根本的に解消したいと思いました。

つまり、

  • プログラミング漫画だけど、パソコンを使わない。
  • テーマはゲーム以外。広く興味を持ってもらえるように、日常に即したものが望ましい。

という、まあまあの無理難題です。でも、この方向で数日考え続けて閃いたのが、「Scratch の部品そっくりのシールを貼ったら、そのモノがプログラム通りに動く」という、ちょこっとファンタジーなアイデアでした。



これでプログラミング漫画だけどパソコンを登場させる必要がなくなりましたし、場面もパソコンの前だけではなくどこでも好きな場所が選べるようになりました*6

テーマについては、以前見てすごく感心したツイートがあって、こういうのがやりたいなあというのは企画が動き始めたかなり早くからありました。シールのアイデアのお陰で、こういうネタもものすごくやりやすくなりました。

またこのアイデアで思わぬ嬉しいことが1つありました。プログラミングなんかしたこと無い人から、「ぺたスクリプトがあったら楽できるのに~と思うことがちょいちょいある」って感想をもらえたんです。

ぺたスクリプトがあったら……と思った瞬間にはもうプログラミングしているということですよね。完成はしてないかもしれませんが(笑)。プログラミング漫画をパソコンから開放したいという発想から生まれたアイデアでしたが、現実のプログラミングもパソコンから開放できてたのか、と ものすごく嬉しかったです。

次回は、漫画の中身についてのお話。

*1:間もなく次の自著が出るので、一種の棚卸しとも言えます。

*2:漫画も描いていいと言われましたが、さすがに商業レベルの腕ではありません……。

*3:「まんがでプログラミング 進め!けやき坂クリエイターズ」はScratch 3.0 対応の新装版で、2017年時点では「はじめてのプログラミング」という名前でした。

*4:今のゲームは高度すぎて、作れそうな感じが全くないのも関係するかも。

*5:こんにちはマイコン」や前掲の2冊は、主人公がゲームの世界に入ってプログラミングの説明をする空想シーンなどを入れることで、「パソコンの前で座っているシーン」を減らす工夫が見られます。そこまで含めて王道パターンと言ってもいいかもしれません。

*6:と言いながら、漫画の舞台のほとんどが家と学校だった……。もっと色んな場面を出したかったです。

「論理処理が必要と思ったことが確率処理でできるとわかった」のは AI だけだろうか

2004年ごろに Google の猫で深層学習が一躍脚光を浴びたとき、画像認識は特徴抽出が難しいので深層学習で良い結果が出るが、自然言語処理は特徴量*1がリッチなので、深層学習を適用するのは難しいだろうと思っていた。
特徴量がリッチとは、例えば「ホームラン」のたった1語でその文はスポーツ、特に野球の話題である可能性が高くなる、みたいな話である。一方、ピクセルの1つが緑であることから何の画像か当てるのは不可能だ。
その後、自然言語処理でも深層学習が当たり前になったのは誰もがご存知のとおりであり、自身の不明を恥じるばかりだ。ただ言い訳をさせてもらえるなら、自然言語処理のえらい先生方も同じように言っていたのだ。

2014年ごろ、LSTM などの深層学習モデルが発展し、自然言語処理でも目覚ましい結果が出始めた。機械翻訳など多くのタスクで、人間の平均といい勝負になったのもこの頃だったと思う。すると、人工知能はもうすぐ人間に追いつき追い越すのでは、という話になってくる。いわゆるシンギュラリティというやつである。
しかしこの頃の論調としては、仮にシンギュラリティが来るとしても、どんなに早くても10年でなんとかなる話ではなく、いいとこ30年くらい先の話じゃあないか、という人が多かったんじゃあないかと思う(一部の気の早い人を除く)。他ならぬ自分もそうだったし。

大脳に含まれるニューロン神経細胞)のネットワークを数理モデル化したものがニューラルネットワークであり、規模こそとても大きくなったものの、今ある深層学習も基本的に全てニューラルネットワークである。
ニューラルネットワークで記述できるのは確率モデルであり、人間がするような論理的な思考を記述することはできないだろう。そうである以上、まだ見ぬブレイクスルーを1つ以上経なければ、真の汎用人工知能を実現することはできないだろう。そう思っていた。
実際、神経細胞網はあくまで脳の一部でしかなく、脳の他の部分をエミュレートした何かが人工知能を実現するのに重要な要素になる、と考えてしまうのはむしろ自然だったわけだ。

そして 2022年末、ChatGPT が登場した。
自然言語処理の数あるタスクの中でも最高難度である対話を、多くの人を感心させるレベルでこなすだけでもすごいのに、同じモデルで文書分類、質問応答、翻訳、言い換え、文生成、要約なども全部まるごと、1つのモデルで実現していることに言葉を失う。

どれほど難しいと言われていたタスクでも、一度でも解けることを誰かに示されれば、次からは他の人も同じレベル以上でそのタスクを解き始めるものである(場合によっては他の方法を使って)。つい最近も、テキストからの画像生成でそれを見たばかりだ。
つまり ChatGPT レベルの AI が今後続々と登場することが予想できる。今は汎用の ChatGPT(とその眷属)しかないが、いろんな特徴を持った AI や、専門分野に特化した AI が登場するわけだ。今は遅かったり不安定だったりする AI のレスポンスも、きっと日常使いに耐えるレベルに向上するだろう。

これはもうシンギュラリティ来ちゃったって言ってもいいんじゃない? いや待て落ち着こう。現時点でシンギュラリティ来てる来てない議論をしても、どちらも決定的な決め手はなく不毛な展開しか見えないので、ひとまず置いておく。

nowokay.hatenablog.com

ChatGPTのヤバいところは、論理処理が必要だと思っていたことが、じつは多数のデータを学習させた確率処理で解決可能だと示したことだと思います。

これは本当にそのとおり。「脳の他の部分をエミュレートした何か」なんかいらんかったんや……というところから、もう一歩考えを進めてみる。

  • そもそも人間の「知能」と呼ばれているナニカは、脳で実現されていることはわかっているものの、どうやって実現しているかはわかっていない。
  • 脳の一部を模したニューラルネットワークという確率的なモデルで、かなり高い精度の「知能」のエミュレーションが可能であることが示された。

ここから素直に考えれば、今まで人間の脳が行ってきたとされる論理処理も、実は「論理的に行われているように見えていただけの確率処理」だったりしないだろうか。実際、「人間の論理処理」は穴があったり飛躍があったりとしばしば間違っており、確率処理だったとしてもなんの不思議もない。むしろ納得感さえある。

Large Language Model は世界の知識を獲得できることが示され共通認識となりつつあるが、同様に「知能のエミュレーション」も獲得できることが ChatGPT によって示された。そしてサールの中国語の部屋は、知能と「知能のエミュレーション」を区別できないことを表している(サールの言いたかったことは逆だが*2 )。

ja.wikipedia.org

このように、「知能は高度な確率モデルである」という仮説は俄然信憑性を増しつつあると思うのだが、哲学はこの問いにどう答えるんだろう。
今までに哲学を浅く狭く読んだ範囲だと、「知能は高度な確率モデル」仮説は今までの哲学を土台から揺らしてくるように思えるのだが、今のところ目立った反応は見えない。スルーなのか、気づいてないのか、単に自分の観測範囲が狭いのか……。
というわけで哲学が ChatGPT 的 AI にちゃんと向き合った言説があればぜひ読みたいので教えて欲しい。緩募。

*1:その頃の自然言語処理界隈では特徴量のことを「素性(そせい)」と言っていた。最近は深層学習でマルチモーダルが当たり前になったからか聞かなくなったなあ。

*2:サールの主張を認めるには「意識」の存在を仮定しないといけないが、それは全然トリビアルじゃないよね? という解釈。

CLIP を使った画像検索(VRC-LT #15)

VRC-LT という VRChat 上で LT 大会を行うイベントに、のこのこ参加させてもらって、CLIP で画像検索の簡単なサービスを書いてみた話をしてきました。
主催の @haru2036 さん、発表者&参加者の皆さん、ありがとうございました&お疲れ様でした~。

vrc-lt.org

このブログ、VR や AR の記事がちらほらありますが、VRChat はなんか怖そうと手を出してませんでした。*1
@haru2036 さんは実はすごーく昔にサイボウズ・ラボユースでメンターさせてもらったことがあって、その縁で VRC-LT に誘ってもらい、ようやく VRChat を始める踏ん切りが付きました(笑)。

発表資料はこちら。

www.slideshare.net

ただ、しゃべり有り前提の資料なので、VRC-LT の録画を見るほうがいいかもしれません(↓のリンク先の1時間23分ごろから)。


さて、CLIP を一言で説明すると、画像とテキストを同じ潜在空間(512次元)に埋め込むモデルです。
画像とテキストが似ていたら、CLIP によって似ているベクトルにエンコードされることが期待できます。
ググラビリティの低さから OpenAI CLIP と呼ばれることも多いですね。

CLIP の応用範囲は広く、最近話題の Stable Diffusion をはじめとしたテキストから画像を生成するモデルの多くにも CLIP が組み込まれていますし、画像にキャプションを付けるモデルにも CLIP が使われているものがあります。
中でも最もシンプルな CLIP の応用が、「似ている画像とテキストが似ているベクトルにエンコードされる」という特徴をそのまま使った画像検索になります。
あらかじめ画像を全部長さ1のベクトルにしておくことで、入力されたクエリーテキストをベクトルにエンコードし長さ1に正規化、画像ベクトルと内積をとると、長さ1同士なのでコサイン類似度になります。
あとは topk をとるだけで画像検索の完成です。

CLIP の学習は、大量の GPU と大量の画像・テキストペアが必要なので自分でやるのは正直しんどいですが、いろんな会社や研究所が学習済みモデルを公開しています。
特に AI bot 「りんな」で有名な rinna さんが日本語 CLIP モデルを商用利用可能なライセンスで公開してくれているので、ありがたく使わせてもらうことにしましょう。*2

rinna.co.jp
huggingface.co

CLIP による画像検索の実力を見てみましょう。実装についてはあとで紹介します。
「バス」で検索すると、バスが大きく写った画像がヒットします。

「バス」の検索結果

これくらいなら Google Photos の画像検索でもできそうですが、実際やってみると「確かにバスも写ってはいるけど……」みたいな写真がヒットすることも多いです。

物体検出ベースの検索の困るところ(VRC-LT の発表資料より)

Google Photos のような物体検出による画像検索は、基本的にその物体が画像に入っているかいないかだけを情報として取得して、それをもとにしたインデックスを検索しているので、こうした問題が生じます。つまり「バスの写真」ではなく「バスが写っている写真」を検索しているわけですね。
他にも、物体検出があらかじめ想定しているキーワード以外や、「青いバス」「寝ている猫」では検索できません。

さて、CLIP を使った潜在ベクトル検索はどうでしょう。

「青いバス」の検索結果
「おもちゃのバス」の検索結果
「渋滞に巻き込まれたバス」の検索結果

期待以上にいい結果が得られてホクホクしてしまいます。
他の検索結果例については、冒頭の資料 or 録画をごらんください。

この手の深層学習の「いい感じの結果」は厳選前提だったりすることがよくあります。この CLIP 検索は、まあもちろんダメな結果もあるはあるんですが、どちらかというと「おもしろい結果が簡単にたくさん得られてしまって、どれをスライドに採用するか悩む」というくらい、安定して良い検索結果が得られました。

VRC-LT の歓談中に「検索結果のスコアが 0.3 くらいと低い」という良い指摘がありました。これは 512次元のような高次元空間では低次元の常識が成り立たず、ランダムなベクトル同士のコサイン類似度は 0 の周辺に集中する分布を持つ(つまり、ほぼ直交する)という事情があります。つまりコサイン類似度 = 0.3 というのはその分布においては実はかなり高い値で、ベクトル同士もかなりよく似てくるんですね。

shuyo.hatenablog.com


さて最後に実装を載せて終わりましょう。普通なら github とかに載せるところでしょうが、コードの短さを見てもらうために記事にそのまま貼り付けることにします。
VRC-LT のプレゼンでは、スライド一枚にプログラムコードを収めて短さを強調していましたが、実際、web サーバ部分込みで 70行程度に収まっています。

画像は COCO と ImageNette というデータセットから適当に借りてきた約5万枚を使っています。
好きな画像を用意して、「# 画像を置いてあるパス」のところを適宜書き換えてください。
バリエーションの幅広い、十分な枚数の画像を用意しないと結果がおもしろくならないので、画像の用意が今回の話で一番難しいところでしょう(笑)。

import os, io, base64, glob, tqdm
from PIL import Image

import tornado.ioloop, tornado.web
import torch
import japanese_clip as ja_clip

device = "cuda" if torch.cuda.is_available() else "cpu"
model, preprocess = ja_clip.load("rinna/japanese-clip-vit-b-16", cache_dir="/tmp/japanese_clip", device=device)
tokenizer = ja_clip.load_tokenizer()

DATASETS = [ # 画像を置いてあるパス
    "/media/hdd/dataset/imagenette2-320/train/**/*.JPEG",
    "/media/hdd/dataset/imagenette2-320/test/**/*.JPEG",
    "/media/hdd/dataset/coco/val2017/*.jpg",
    "/media/hdd/dataset/coco/test2017/*.jpg",
]
imglist = []
for path in DATASETS:
    imglist.extend(glob.glob(path))

if os.path.exists("image_features.pt"):
    norm = torch.load("image_features.pt")
else:
    features = []
    for path in tqdm.tqdm(imglist):
        img = Image.open(path)
        image = preprocess(img).unsqueeze(0).to(device)
        with torch.no_grad():
            features.append(model.get_image_features(image))
    features = torch.cat(features)
    norm = features / torch.sqrt((features**2).sum(axis=1)).unsqueeze(1)
    torch.save(norm, "image_features.pt")

def read(path):
    with open(path, "rb") as f: return base64.b64encode(f.read()).decode("utf-8")

def search(query):
    encodings = ja_clip.tokenize(query, tokenizer=tokenizer)
    with torch.no_grad():
        text_features = model.get_text_features(**encodings)
    textnorm = text_features / torch.sqrt((text_features**2).sum())
    sim = norm.matmul(textnorm.squeeze(0))
    topk = torch.topk(sim, 5)
    return [{"image_base64":read(imglist[topk.indices[i]]), "score":topk.values[i].item()} for i in range(5)]

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        query = self.get_argument("query", "").strip()
        if query!="":
            topk = search(query)
        else:
            topk = []
        self.render("main.html", query=query, topk=topk)

if __name__ == "__main__":
    dir = os.path.dirname(__file__)
    app = tornado.web.Application([
        ("/", MainHandler),
        ],
        template_path=os.path.join(dir, "template"),
        static_path=os.path.join(dir, "static"),
        compiled_template_cache=False,
    )
    app.listen(8000)
    print("Listening...")
    tornado.ioloop.IOLoop.current().start()

あと2つのファイルを置くだけで動きます。
まず以下のような tornado の HTML テンプレートを template/main.html に置きます。
渡された画像リストを展開するだけの簡単なものです。

次に スタイルシートを static/bootstrap.css に置きます。bootstrap に対応させてますので、好きなスタイルを選んでください。
LT で見せた実装では bootswatch の slate を使いました。

<!DOCTYPE html>
<html lang="ja" style="height:100%">
<head>
<meta charset="utf-8">
<title>CLIP Search</title>
<link href="{{ static_url("bootstrap.css") }}" rel="stylesheet"/>
<style>
.card {
 --bs-card-spacer-y: .3rem; --bs-card-spacer-x: .3rem;
 float: left; width: 240px; height: 240px;
}
.card-text { max-width: 99%; max-height: 99%; }
</style>
</head>
<body style="height:100%">
<div id="main" style="height:100%; box-sizing:border-box; padding: 30px 0 70px">
<h1 style="position:absolute; top:0">CLIP で画像をテキスト検索!</h1>

<div id="chat-log" style="height:100%; overflow-y:auto">
{% for x in topk %}
  <div id="card-template">
    <div class="card text-white bg-primary mb-3">
      <div class="card-header">score: {{ f"{x['score']:.04f}" }}</div>
      <div class="card-body">
        <img class="card-text" src="data:image/jpeg;base64,{{ x['image_base64'] }}" />
      </div>
    </div>
  </div>
{% end %}
</div>

<div id="chat-input" class="form-group" style="position:absolute; bottom:0; width:100%; padding-bottom: 15px">
  <form id="prompt_form" class="d-flex" method="get">
    <input id="query" name="query" class="form-control me-sm-2" type="text" placeholder="Query" value="{{ query }}">
    <button id="send_btn" class="btn btn-secondary my-2 my-sm-0" type="submit">Send</button>
  </form>
</div>
</div>
</body>
</html>

*1:友達がいないから……という真の理由はヒミツです。

*2:CLIP の改良版に当たる CLOOB の学習済みモデルも同時に公開されていますが、今回は CLIP の実力を見たかったのでそちらを採用しました。

実験用 GPU 環境をどう準備したらいい?(非情報系が機械学習を使う研究をしたいとき)

深層学習が著しく発展し、今まで人間にしかできないと思われていたことができるようになってきました。そのおかげで、今まで機械学習と縁が薄かった分野でも、機械学習を使った研究がしたいという声が上がるようになっています。
前々回は、それを裏付けるように非情報系の学生さんが機械学習を使った研究をしたいという応募がサイボウズ・ラボユースに増えているという話、前回はいままで機械学習や深層学習に縁のなかった人が何から勉強したらいいかという話を書きました。
今回はその続き、研究に必要な実験用 PC 環境をどのように準備したらいいかというお話です。

深層学習の実験をするには、十分な性能の GPU を積んだ PC が必要です。
今どきの機械学習関連の研究室では、院生有志がメンテナンスしている GPUクラスタがあって、それを使わせてもらえることが期待できます。自分用の PC を手配する場合も、研究テーマに適したマシンの選択について教授や先輩が相談に乗ってくれるでしょうし、環境構築&運用のノウハウもバッチリです。
しかし非情報系だと、そんな環境も相談相手もおそらくないでしょう。予算だけ出すから自分でマシンを選定するように、ってところでしょうか。環境構築も自分でググって手探りでやってみるしか。
ということで、前回の記事と同じくあくまで私見ですが、あまり後悔しなくて済むだろう深層学習用の PC 選びと環境構築の第一歩を書いてみます。

まず結論を言うと(TL;DR ってやつ)、

  • GPUNVIDIA(CUDA) 一択。予算の範囲で一番 GPU のメモリが多いものを選ぶ
  • OS は Linux がベスト。好きなディストリビューションでいいが、困ったときのググりやすさなら Ubuntu がおすすめ
  • CUDA の環境構築は nvidia-docker2(NVIDIA Container Toolkit) の導入を強くおすすめ

GPU

深層学習では GPU が必須です。CPU オンリーでも動きはしますが、大きいモデルの学習が現実的な時間で終わりません。

今購入が可能な GPUNVIDIA(GeForce, Quadro 等) と AMD (Radeon) です。他には、まもなく Intelディスクリート GPU (CPU と分離している、GPU 専用チップ)である Arc が出ますし、Apple の M1/M2 も AI 演算性能を喧伝しています。
ただ、深層学習の研究で使うなら、現状は NVIDIA 一択です。
他の選択肢を選んでもいいのは、機械学習とコンピュータ全般にとてもとても詳しくて、困難に出くわしたときに嬉々として自力で解決したがる人か、人柱になってもいいから特定のメーカーを応援したい人だけです。

NVIDIA は、GPU 上での基本的な演算をサポートした CUDA Toolkit と、 cuDNN という深層学習に頻出する計算を最適化したライブラリを提供しており、tensorflow や pytorch などの深層学習ライブラリは CUDA/cuDNN をサポートしています。
特に cuDNN は深層学習の推論速度に大きな影響があります。cuDNN がなくても tensorflow などは一応動きますが、推論速度に大きな差が出ます。
一方の AMD は、CUDA に相当する機能は OpenCL などで代替できますし、Intel も oneDNN という自社製ライブラリで頑張ってますが、いずれも cuDNN に相当する部分が強くないです。そのため、スペック上では同等の AMDGPU を持ってきても、深層学習の推論性能では NVIDIA に負けてしまいます。
Apple M1/M2 はメモリを CPU と GPU で共用できるなど、将来のポテンシャルには期待できます*1。何年かしたら「深層学習を始めるなら、コスト対性能で Mac に決まり!」なんて時代がもしかしたら来ちゃったりするかもしれません。が、それは今ではありません。

さて、NVIDIA 一択と言っても、「NVIDIAGPU」はいっぱいあります。GPU のスペック比較で注目されがちな CUDA コア数が多い製品をつい選んでしまうかもしれませんが、こと機械学習で使うとなると、最優先するべきスペックは GPU のメモリ量です。
CUDA コア数は GPU の並列計算能力を表し、それが多いほど計算が速いというのは間違っていません。しかし速い遅い以前に、実は深層学習のモデルは GPU のメモリに乗らなかったら計算ができません。「遅いけど計算できる」と「速いけど計算できない」なら、どちらを選ぶべきかは言うまでもないですよね。

深層学習の訓練では、その推論(予測)の何倍ものメモリが必要になります。その倍率に直結するのがミニバッチサイズ(1回のモデルパラメータ更新に用いる訓練データ数)です。GPU のメモリが足りないと、推奨されているミニバッチサイズで訓練ができなくて、しかたなくミニバッチサイズを減らすという貧乏ハック(涙)がよくあります。*2
ミニバッチサイズは学習したモデルの性能に結構影響があり、最適なバッチサイズを試行錯誤するのが深層学習チューニングの第一歩なところがありますが、メモリが少ないとその手も使えません。*3

よって、(低予算での) GPU 選びはメモリが最重要! これが鉄則です。*4
2022年現在、一部の低ランク NVIDIA GPU は、上位製品より搭載メモリが多いという逆転現象が起きていて、12GB のメモリを積んだ GeForce RTX 3060 が狙い目です。RTX 2060 にも 12GB 版がありますが、価格差は小さいので、より高性能な 3060 がいいでしょう。
12GB の次にメモリが多いのは RTX 3090(24GB) ですが、暗号通貨ブームによる高騰が収まった今でも20万円以上しますので、予算に収めるのは難しいでしょう(苦笑)。*5

【追記】
GeForce RTX 4060 Ti 16GB が 2023年7月に ¥ 88,800(NVIDIA 公式ページより。税別?) で出るそうです。
実売 5万円前後の RTX3060 12GB と悩ましい価格差ですが、この 4GB の差で動かせる LLM が結構増えそうなので、予算が許すなら 4060Ti を狙いたいところですね。
【/追記】

CPU とメモリ

CPU は、IntelAMD で動かせるプログラムに差が出ることはありませんので、どちらでも大丈夫です*6。予算が許す範囲で高速なものを選びましょう。
深層学習では CPU より GPU の速度のほうが重要なので、グレードは高くなくても大丈夫。とはいえ Intel で言えば、Core i5 以上を選んでおきたいところです。
ARM 系(Apple M1/M2 含む)はもう何年かしたら主流に上がってくる可能性は秘めてますが、今はまだ苦労の元なのでやめましょう。

メインメモリは 16GB が最低ラインです。32GB あると嬉しい。予算が厳しいなら、CPU のグレードを下げてでもメインメモリを積んでください。
深層学習を主に使った研究でも、従来の機械学習の手法や線形代数の演算(SVD など)が前処理などに組み合わせて使われることも多く、それらは大量のメモリを消費することがあります。また深層学習においても、訓練データをオンメモリで保持できたら訓練時間を短縮できる可能性があります。
また後述の docker においても、メモリが多ければ多いほどコンテナをたくさん立てることができて嬉しいです。

OS

OS は Linux を割と強めにおすすめします。
tensorflow や pytorch といった深層学習のライブラリ自体は WindowsMac にも対応していますが、配布されているモデルを動かすには、それ以外のプログラムをビルド(プログラムのソースファイルから実行ファイルを作成する作業)する必要があって、それが Linux にしか対応していない(あるいは Windows/Mac で動かすのが面倒)ということが少なくありません。
また深層学習を使った研究における第一級の必需品と断言したい nvidia-docker2(後で説明) を動かすのは Linux が一番楽です。
Linuxディストリビューションは、CUDA が対応しているものならどれでもいいです。困ったときにググると情報が多く見つかるのは UbuntuCentOS*7 でしょう。

どうしても Windows がいいという場合、nvidia-docker2 を Windows で動かすのは大変なので、docker を使わずに深層学習するほうが楽でしょう。逆に言えば、docker を使わないなら Windows でもなんとかなります。nvidia-docker2 を使わないのはまあまあ大きなハンデになりますが。
どうしても Mac がいいという場合、以前なら Intel Mac + NVIDIA GPU という選択肢もありました。でも NVIDIAMac OS での CUDA サポートを 2021年に終了してしまいました……。「Mac でする苦労は大歓迎」という人以外は、M1 や M2 で安心して深層学習ができると定評が得られるまで待ったほうがいいでしょう。

docker

例えば tensorflow を使って深層学習の研究をするなら、調達したマシンに以下のパッケージをインストールする必要があります。

  • CUDA Toolkit と cuDNN の適したバージョン
  • python の適したバージョン
  • tensorflow の適したバージョン

この「適したバージョン」というのが厄介です。うまく動くバージョンの組み合わせが限られていて、適していない組み合わせだと簡単に動かなくなります。
深層学習の速すぎる発展に合わせてなのか、tensorflow や pytorch といった深層学習ライブラリでは、通常のソフトウェアのようなバージョン間の互換性が期待できません。今まで動いていたモデルの実装が、tensorflow をバージョンアップしたら動かなくなった、ということが普通に頻繁によくあります。特に tensorflow v1(バージョン1系) と v2(バージョン2系) は、名前変えた方がいいくらい別物です。

さて話は変わりますが、これから深層学習を使った研究を始めますという人が、最近の複雑なモデルを自力でいきなり実装することはやっぱり難しいです。幸い、機械学習の研究では github などで実装を共有するのが一般的であり*8、公開されているモデル実装を自身の研究に応用するというアプローチを多くの人が取るでしょう。

ここで先ほどのバージョン問題が立ちはだかります。モデルの実装は tensorflow (あるいは pytorch)の特定のバージョンでしか動きません。それに対応する python や CUDA/cuDNN のバージョンも限られます。
うまくいくモデルを探すためには、また論文にモデル性能比較を書くためには、深層学習の研究では複数のモデルを実験する必要もあります。それらが要求する複数バージョンの CUDA/tensorflow/pytorch を自分の実験環境に混在させようとすると、環境は簡単に壊れて、今まで動いていたモデルも動かなくなります……。

そこで是非使ってほしいのが docker と nvidia-docker2(NVIDIA Container Toolkit) です。
docker はコンテナと呼ばれる仮想環境を親マシン(ホストと言います)の中に簡単に作って、動かして、消すことができます。コンテナはホストから独立しており、コンテナ内での変更がホストや他のコンテナに影響を及ぼすには特別に許可する必要があります。nvidia-docker2 は、docker コンテナが GPU を使えるようにするためのランタイム(コンテナの実行機能)です。docker と nvidia-docker2 があれば、CUDA や tensorflow などのバージョンごとにコンテナを立ててしまえば、安全に環境混在できます。
以前はバージョン不整合を起こした CUDA 環境の復旧を年に数回とかしなくちゃいけなくて、とてもとても面倒でしたが、nvidia-docker2 を導入してからは一切なくなりました。天国です。

とはいえ、docker を導入するということは docker を勉強するコストがかかってしまいます。Linux に慣れていなかったら、さらに困難でしょう。docker 勉強のコストくらい上記のメリットだけで簡単にペイしてお釣りが来ると思いますが、未経験でそれを実感しろって言うのも無理な話……。
最初は普通に CUDA 環境構築しておいて、複数の環境が必要になる頃には Linux や深層学習にちょっとは慣れてくるでしょうから、そのときに docker のことを思い出してあげてください。

(番外編) GPU クラウド

GPU サーバをスポットで借りて使う GPU クラウドサービスという選択肢もあります。Google Colab が最もポピュラーで手軽ですね。他に、AmazonAWSマイクロソフトの Azure、GoogleGCP なども GPU を使えるクラウドサービスです。これらの GPU クラウドは、費用対効果を考えればとても安価に GPU を使った深層学習を行うことができます。
上述した通り、深層学習で一番ネックになる GPU のメモリ量についても、Google Colab の無料版でも 11GB 以上、月1000円の Google Colab Pro だと 16GB もあり(2022年現在)、頑張って導入した自分用の GPU サーバと匹敵するか、それ以上の容量があります。
では、自分用の GPU マシンなんか用意せずに、最初から GPU クラウドを使えばいいのでは? という発想もあるかもしれません。しかし深層学習を使った研究に挑戦するなら、最悪 GPU のメモリが少なくてもいいので、手元に1台マシンがあったほうが良いと思います。

実は深層学習は、うまく学習させることが結構難しいのです。機械学習用に整備されたデータセットではなく、自前のデータを比較的新しめの(つまり複雑な)深層学習のモデルに食わせて学習させたら、十中八九失敗します。なんなら賭けてもいいくらいです。
学習失敗には、学習の目安となるloss(損失)が全然下がらない、loss が下がらないどころか inf(無限大) や nan(非数値エラー) に飛ぶ、性能がランダム分類より悪いなど、いろいろパターンがあり、これを解決するには手探りで試行錯誤を繰り返すことになります。最も有効な解決策は、この非情報系向けシリーズの初回の記事に書いたように、機械学習に詳しい人にアドバイスをもらうことですが、まあそれはおいときましょう(苦笑)。

そうした試行錯誤を GPU クラウドでできるかというと、正直厳しいでしょう。Google Colab の無料版はセッションがいつ切れても文句言えませんし、内部で割り当てられたリソース使用量の上限*9を超えたらしばらく使えなくなります。AWS などの GPU クラウドは従量制で、失敗を繰り返す可能性の高い学習に使うのは強い抵抗を感じてしまうのではないでしょうか。
深層学習の試行錯誤は何度も繰り返す必要があるので、まずはデータを減らしたりモデルを小さくしたりして、1回の学習サイクルは短くするのが効果的です。そのため、メモリがちょっと少なくてもちゃんと役に立ってくれます。
ある程度うまく動くことを確信できるようになって、もう少しメモリがあったら……というとき、GPU クラウドの利用を検討してみてください。

参考リンク

nvidia-docker2(NVIDIA Container Toolkit) について最も参考になった NVIDIA 公式ブログの記事です。
短い記事ではないですが、nvidia-docker2 とは何か? インストールと使い方は? が端的に書かれています。足りない分は後からリファレンスで補うので事足ります。
medium.com

CUDA や tensorflow などのバージョン非互換性の話題に触れています。
ほかのソフトウェアではあまり問題にならないような機械学習特有の諸問題についても簡単にまとまっていますので、一読して警戒レベルを上げておくのもいいかも(苦笑)。
euske.github.io

 

 

蛇足の追記

この記事の本来のターゲットである「深層学習を使った研究を始めたいけど、周りも含めて機械学習の経験が少ない人」はここから先を読む必要は特にありません。

実験用 GPU 環境をどう準備したらいい?(非情報系が機械学習を使う研究をしたいとき) - 木曜不足

個人的には非情報系ならなおさらColab等の環境が良い気が。より安定するPro+(月$50)にしても自前でPC持つコスト(PC代、電気代、メンテ時間)考えるとペイするかな。NotebookをGitHubにpushして共有すればアドバイスももらいやすい

2022/07/26 13:26

9割同意ですが、そう書かなかった理由がいくつかあります。

GPU クラウドは高い」と言われる

Google Colab Pro は破格の安さ、めっちゃお得、むしろしない理由がない、くらい猛プッシュしてるんです。
ただ、それでも「月 1000円は高いですよね」と言われてしまう。
クラウドの安さを実感・納得してもらうには、理屈と正論は無力で、知識と経験が必要なんですよね。

また、従量制のクラウド料金は天井知らずなので、予算を立てづらいという問題もあります(研究室だけじゃなく企業でも)。
それを説得するにはやっぱり実績が物を言うわけで、ここにもニワトリタマゴ問題が。

PC 購入の予算なら研究室から出してもらえる

見えている範囲からの勝手な推測なので間違っているかもしれませんが、非情報系の研究室の方々も深層学習は大きな鍵になる予感を持っていて、でもノウハウが無いから自発的に声を上げた学生さんに期待を寄せているという雰囲気を感じます。
その期待の表れでしょうか、深層学習研究用の PC を購入する予算が、論文執筆用のノート PC レベルではなく、それなりの GPU を積んだゲーミング PC レベルでちゃんと支給されている、という認識。
つまり、PC を買うか買わないかという問題はすでにクリアして、何を買うかという問題に移っているわけです。

ただそこで RTX 3070(8GB) を買いました~、みたいになることも多くて、もちろん全然ダメじゃないけど、事前に相談してくれたら RTX 3060(12GB) を勧められたのになあ、というのがまさにこの記事を書いた動機です。

Google Colab 用の運用ノウハウが必要

Linux や docker は身につけたことが他でも役立つ、いわゆる「つぶしがきく」ので、そこでの苦労は報われるチャンスが多いです。
一方 Google Colab をホームグラウンドとして真面目に深層学習研究しようと思ったら、セッション切れ対策など Google Colab 固有のノウハウが必要になり、これは他の場所では基本的に役立ちません。
Google Colab は共有には手軽で便利ですが、初手の選択肢としては難点も多いかなあ、というのが個人的な感想。


冒頭に書いたように「あくまで私見」なので、他の意見にも耳を傾けることは全然いいことだと思います。

*1:CPU と GPU のメモリが共有で十分な容量があると、後述の GPU メモリ量の問題が大きく軽減されますし、推論コストの無視できない割合を占める CPU から GPU へのデータ転送もなくなるので、環境さえ整えば一番手に躍り出る可能性は十分あります。それにはまず cuDNN 相当品を Apple が作ってくれないと……。

*2:モデルやデータによって適したミニバッチサイズは違いますが、だいたい 16~100 くらいの数になると考えてください。それを、メモリエラーが出なくなるまで減らしたら、ミニバッチサイズが 2 になった、なんて悲しい出来事も本当によくあるんです……。

*3:ミニバッチサイズが大きいほどいい/小さいほどいい、という単純な話ではなく、収束の速さと性能のバランスを見た適切な値を選ぶ必要があります。

*4:予算が潤沢なら、マルチ GPU のための NVLink を備えているか等、メモリ以外にも必須要件が出てきます。

*5:RTX 3070 に 16GB 版が出る計画があったらしいのですが、キャンセルになったそうな。残念。

*6:厳密には違いはありますが、深層学習の研究をする上でその違いが問題になることはまずありません。

*7:CentOS はサポート終了しているので、今だと RHEL 互換の RockyLinux とかでしょうか。使ったことがないからわからない……。

*8:近年の機械学習の学会では、実装を共有して検証可能にすることが論文をアクセプトする条件になっていることも珍しくありません。

*9:Google Colab のリソース上限の正確な値はわかりません。

何から勉強始めたらいい?(非情報系が機械学習を使う研究をしたいとき)

以前、「非情報系が機械学習を使う研究をしたいとき」という記事を書きましたが、内容の半分はサイボウズ・ラボユースの宣伝だったんで、今回はタイトル詐欺じゃあないことも書きます。

いままで機械学習や深層学習に縁のなかった人が、それを使った研究を始めたいとなったとき、共通して直面する大きな課題は「何を優先的に勉強したらいいか」と「実験用の環境(PC)をどのように整えたらいいか」でしょう。
今回は何から勉強する? という話。
機械学習そのもの(特に自分が使おうとしているモデル)を学ぶのは必須に決まっているので、機械学習を使う上で必要となる前提知識を学ぶ優先順位について考えてみます。

機械学習(深層学習を含む)を使う上でキーになる前提知識は、数学(特に解析・線形代数・統計)とプログラミングを含む情報科学であることは意見の一致するところだと思います。
情報系の人なら、情報科学はさすがにやってます。プログラミングもやってるでしょう(始めたばかりかもしれませんが)。解析と線形代数はカリキュラムに入っていたはず。最近はデータサイエンス流行りで、統計も必修だったりするかも。
「テストが終わったら忘れた。まさか数学使う日が来るとは夢にも思わなかった」という人には厳しい日々が待ってます……。

非情報系の人だと、それらを修めている可能性はやっぱり高くはないですよね。「いわゆる文系」だと、解析・線形代数すら怪しい。それらを学び終わるまで待っていたら研究が始まりませんから、走りながら学ぶしかありません。
しかし自身の専門分野の勉強もある中で、数学と情報科学を学ぶ時間を作るのは大変ですし、モチベーションの維持も難しい。となると優先順位をつけるしかありません。
あくまで個人的な見解ですが、それらに学ぶ優先順位をつけるとすれば、「プログラミング > 情報科学 > 統計 > 線形代数・解析」だろうと考えています(先に書いたものほど優先順位が高い)。
これは、機械学習を使った研究をする上で、それを学ばなかった場合に生じるかもしれない支障の大きさの順で並べました。

プログラミング

今は深層学習系のライブラリがとても充実していて、数学の知識が足りなくても、モデルとその学習を実装するくらいならそこそこなんとかなります。
もちろん、数学を勉強する必要が全くなくなった、というわけではありません。モデルを理解し、データに合わせて改良するときなどは、数学の知識は間違いなく役立ちますし、自分が最終的に選んだ手法を(後付でも)理屈をつけて説明したいときに数学ほど頼りになるものはありません。

ただ、深層学習を使った研究をするときにネックになりやすいのは、設定(ハイパーパラメータやモデルの構造)を変えながら試行錯誤を繰り返す部分です。深層学習では同じモデルですら、ハイパーパラメータだけではなく初期値や学習順序の乱数で性能が大きく変わるので、様々な設定で実験を繰り返し、計測した性能を比較する必要があります。
これを手作業でやっていては実験できる回数が限られてしまい、最終的に到達できる性能が(本来届いたかもしれない性能よりも)低くなってしまいます。したがって、放っておいても自動的に実験を繰り返してくれるようにシステムを作り上げることがとても有効です。
もちろんそれを助けてくれるライブラリもありますが、それを使いこなして、自動的にモデルを組み替えて性能を計測してくれる仕組みを作るにはやっぱりある程度以上のプログラミング能力がないとうまくいきません。つまり、プログラミング能力が結果(論文に書く性能値)に直結するわけです。

また、非情報系の人がわざわざ機械学習に手を出すということは、機械学習用に整備されたデータセットを使うのではなく、おそらく独自のデータを使って研究するのでしょう。そういうデータを機械学習のモデルで扱えるように変換したり、ラベルをつけたりするだけで結構な手間がかかります。経験のない人がなんとなく想像するのより、10倍以上大変だと思っておいてください。
さらに、機械学習では性能を出すためにオーグメンテーション(データにランダムなノイズを乗せたり変換したりして訓練データを増やすこと)などの工夫を行うことが望ましいです。独自データで量が少なかったら、そのあたりの工夫がとりわけ重要になります。
これらを解決するのにも、とにかくプログラミング能力が要求されます。ほら、プログラミングが最優先な気分になってきたでしょう?

情報科学

情報科学のうち、プログラミングに関わりが深い範囲は同じくらいの必要度があると考えてます。例えば、基本的なアルゴリズムと計算量の考え方、疑似乱数、そしてできれば浮動小数点の精度と演算誤差についても押さえておきたいです。
アルゴリズムはデータの前処理の部分で必要になりがちですし、計算量は処理時間の見積もり(データやパラメータを増やしたときの変化)や、先行研究との速度比較において重要です。
機械学習の実験では、初期値や学習データの順番などさまざまなランダム性が用いられますが、ランダムな値を使っていると毎回結果が異なってしまい、実験結果を再現できないという問題があります。コンピュータが使っている通常の乱数は、実際は疑似乱数と呼ばれるもので、乱数の初期化に用いられる値(シードといいます)を固定することで、毎回同じ乱数列を生成してくれるようになります。

コンピュータで実数を表現するのは浮動小数点数というデータ形式です。これは任意の実数を扱えるわけではありません。「浮動小数点数で扱えない実数」が出てきたときは、誤差が生じたり、オーバーフロー(扱える範囲を超えた)というエラーになったりします。
というと、滅多にない事のように聞こえるかもしれませんが、実は残念なことに、浮動小数点数で表現できる実数は、実数全体からしたらほんのわずかでしかなく、誤差は常に付きまとう問題なのです*1
例えば 0.1 という、人間にはごく普通に見える値ですら、コンピュータ上では「0.1 に一番近い浮動小数点数」として表現されているに過ぎません。

In [1]: format(0.1, ".18g") # 0.1 を小数点以下18桁まで表示
Out[1]: '0.100000000000000006'

数学では 1-(1-x)=x は常に成り立ちますが、浮動小数点数の計算誤差のためコンピュータ上では必ずしも成り立ちません*2

In [2]: 1-(1-0.0001) # 0.0001 が出力されることを期待
Out[2]: 9.999999999998899e-05

こうした誤差を考慮して、機械学習でもよく使われるライブラリの numpy や torch には、isclose という「同じ値とみなせるほど十分近い」を判定する関数があり、イコールの代わりにそちらを使わなければならないケースも多いです。
また、機械学習では指数関数 exp が大活躍しますが、この関数はとてもオーバーフローしやすいです。GPU で主に使われる float32(32ビットの浮動小数点数) では exp(89) がオーバーフローして inf(無限大) になります。無限大よりはるかにはるかに小さいんですけどね(笑)。

浮動小数点数の計算誤差は普段はあまり気にしなくていいですが、たまにそれに起因する問題が生じます(長く機械学習の研究をしている人なら、少なからず経験してるはず)。そのとき、それを知ってるか知らないかで対処できるかどうかが変わってくるでしょう。

数学

数学はプログラミングたちより低い優先順位にしちゃいましたが、機械学習にとって数学は引き続き重要です。ただ、学習コストと即効性がね……。
上にも書いた通り、深層学習の流行と環境の整備のおかげで、「数学を避けたら研究できない」という状況でもなくなったという事情もあります。

ただそれでもやっぱり数学をやるしか! となったとき、機械学習に直接関係してくる数学トリオ(解析・線形代数・統計)の中で優先するものを1つ選ぶなら、統計です。
特に、母集団、標本、分布、各種統計量などの基本と、検定の初歩(統計で何がわかって、何がわからないか)あたりが重要です。ついでに大数の法則中心極限定理も是非押さえておきたい*3
統計の本で結構なページ数で紹介されていることの多い「いろんな種類の検定(z検定とかカイ二乗検定とかとか)」はひとまず不要です(仮に必要になったらその時学べばいい)。

というのも、(統計的)機械学習がやっていることは「与えられた標本から母集団の分布を推定する」ことにほかならないからです。
深層学習の時代になっても、いやむしろ、現実のデータをそのまま食わせる深層学習だからこそ、その統計の基本を理解していることは大きなアドバンテージになります。
即効性のある話に限っても、標準化やオーグメンテーションなどのデータ前処理では統計の知識が役立ちます。統計がわかっていれば、トンチンカンな標準化をしてしまう可能性を小さくできるでしょう。


最初にも書いた通り、この優先順位はあくまで個人的な意見です。機械学習(深層学習)をどのように使いたいかという個々の事情によって優先度が変わってくる可能性もあるでしょうから、もし身近に聞ける人がいるなら自分が何を優先したらいいか聞いてみるといいでしょう。
そういう人がいるなら、こんなブログ記事を読む必要もないんですけどね(笑)。

*1:浮動小数点数の問題ではなく、そもそもコンピュータは有限通りの値しか扱えないので、任意の実数など当然扱えません

*2:float32 で 1-(1-0.0001) を計算すると、もっと無視できない大きさの誤差になります。

*3:チェビシェフ不等式とイェンセン不等式も重要でしょ……みたいなツッコミも出るでしょうが、キリがないので、大数の法則中心極限定理で勘弁してあげてください。

非情報系が機械学習を使う研究をしたいとき

機械学習(深層学習・人工知能を含む)が使われる領域は、自然言語処理や画像処理といった機械学習の近隣とみなされる分野が従来のメインストリートでしたが、最近はそれ以外の分野の人からも機械学習を使った研究をしたいという声がよく聞かれるようになってきたと感じています。
サイボウズ・ラボでは、学生の開発・研究をサポートする「サイボウズ・ラボユース」という制度を10年続けています。メンターごとに募集テーマは異なり、「機械学習/自然言語処理に関するソフトウェア開発」では、その名前通り機械学習に関する応募を受け付けています。

labs.cybozu.co.jp

初期の応募者の動機は「自然言語処理やりたい」「画像処理やりたい」ばかりでしたが、そのうち応募の傾向が「機械学習を使った○○○○をやりたいが、ネットワーク(など機械学習と隣接していない情報系)の研究室なので機械学習に詳しい人が周りにいない」といったものに変わっていき、さらには非情報系の自然科学についても「機械学習を使いたい!」という応募をもらえるようになってきました。
昨年度のサイボウズ・ラボユースでも、「赤外線/電波望遠鏡の画像データから天体を検出」という天文学の研究に機械学習を応用するテーマをメンタリングしました(継続中)。

blog.cybozu.io

機械学習研究が広がっている背景には、深層学習以降の機械学習(AI)ブームがあるだろう、とは無難でありきたりな考察ですが、実際、機械学習でできることが劇的に広がり、(良くも悪くも)機械学習への期待が大きくなっているのを感じます。幸い、機械学習を始めるハードルは年々下がっています。入門本が数多く出版され*1、各種ライブラリもどんどん使いやすくなっています。
一方で、学習に使うデータは巨大化して扱いづらくなり、またモデルの推論に GPU などの高価な計算リソースが必要になってきているという面もありますが、AWSGoogle Colab などのクラウド環境を使えばリソースを持っていない人でも機械学習できます。また学習済みモデルのリポジトリの整備も驚くほどの勢いで進んでおり、巨大なデータで学習された性能の高いモデルを誰でも簡単に利用できるようになっています。

機械学習がそうやって広く研究されるのはとても嬉しいですが、その人の属する分野が機械学習から遠ければ遠いほど大変だろうなあと、ここ数年のラボユースの学生さんを見ていて実感します。
モデルを引っ張ってきてとりあえずあり物のデータで動かして見るだけなら結構誰でもできますが、機械学習用に整備されたデータセットではなく自分の手元のデータを食わせてみようと考えただけでいきなり壁が立ちはだかることも珍しくありません。データに適切な(と期待できる)前処理を施すだけでも大変ですし、だいたい必ずモデルの実装にも手を入れる必要も出てきます。
それを機械学習の知識も、モデルの知識も、フレームワークの知識も全部乏しい状態で試みるのはそりゃあ茨の道に決まってますよね。これが非情報系になると、さらに情報科学の知識やプログラミング経験も乏しくなりがち。
それだけの困難が見えているのに*2果敢に機械学習研究にチャレンジする学生さんがいたら、応援したくなりますよね。

解決策はとても簡単。機械学習に多少なりとも詳しい人を引っ張ってくることです!!

……と書くと完全に身もふたもないですが、まあ考えてみてください。
例えば、自分のデータを機械学習のモデルに食わせた実験結果を見て、「training loss が中途半端に下げ止まっているから、実装が間違っているか、モデルの表現力が足りないか、途中の層で特徴が潰れているか、訓練データにゴミが入っているか」と機械学習の立場から分析した上で、それらの切り分け方法を一緒に考えてくれる人がいるときと、いないときを想像して、いなかったときにそれを補う方法が果たしてあるだろうか、と。

「いっしょに研究してくれたら嬉しいけど、機械学習の人が全然関係ない分野の研究に協力してくれるんだろうか……」と心配になるでしょう。
それに対して、機械学習の代表どころか中の人と言うのもおこがましい立場の人間が何を言っても保証にならないかもしれませんが、実は機械学習は、本質的に他の分野とくっつかなければ研究ができません。というのも、機械学習の研究にはデータが絶対に必要ですが、そのデータを機械学習自身が生むことは基本的にないからです。
機械学習の代表例的な自然言語処理や画像処理も、そのデータの発生に機械学習は関係ありません。単に、機械学習人工知能から分かれて生まれたときからくっついているから、一体化しているようにみえるだけです。
だから機械学習界隈の人は、他の分野の話を聞くことをあまり嫌がりません。むしろ、データがどんな集められ方をして、どれくらいの規模があって、どういう特性があるのか、ついつい聞きたがります。共同研究に発展できるかどうかはさすがに時の運ですが……。
機械学習はその存在自体が学際的なんですね。

ただ、たとえそうだとしても、機械学習に詳しい外部の人と話す機会を作るのは難しいでしょう。研究室の先生にツテがあれば一番簡単ですが、もしそうならこんな記事読んで悩む必要が最初からないですね(苦笑)。IBIS(情報論的学習理論と機械学習研究会のワークショップ)のポスターセッションに出かけていって声かけまくる、なんてできたら尊敬しますが、それはさすがに強心臓すぎる……。
あとは機械学習人工知能をテーマにしたインターンに応募するという手もありますが、おそらく情報系の学生が優先されますし、自分の研究ができる可能性は低めです。(その他に良い手をコメントでもらえれば追記します)
そんな中、ハードル低めでチャレンジし甲斐があるのがラボユース応募ですね!(手前味噌!!)

labs.cybozu.co.jp

今回ラボユースで、天文学の学生さんの研究をメンタリングして、domain specific なデータそのもののおもしろさ、そのデータを機械学習のモデルと突き合わせて、お互いを調整するおもしろさにとても刺激的でした。
天文学に限らず、機械学習から遠い分野の研究からの応募をお待ちしています。もちろん普通の自然言語処理や画像処理もね!

*1:拙著もその1つです(笑)。

*2:困難さに気づいて無くて、無謀に当たって砕けてるのかも?(苦笑)