所属大学にて9月に1日で機械学習なんもわからん状態から生成モデルを組めるようになろうというワークショップをした。普通に考えて参加者側の視点に立ったら無理なんだが, まあとにかくそういうイベントをやった。やってみたところ, 「何話してるのかわからん」という感想が多く大絶賛だった(反省しています)。
ただワークショップ中にきた質問が結構自分も最初のころは躓いたところだな〜〜というものも多く, ワークショップ中にきた質問点をまとめていけば案外生成AIをフルスクラッチで作れる技術者になるためのTips集が作れるのではないかと思い, この記事を書くことにした。ただ正直, 自分が学びたての頃こういうTips集を読んで理解したかと言うとそうではない気がするので, 読者の皆様に関しては「へ〜こんなのあるんだ」という感じで読んでいただき, 実際にこのTipsでの問題が起こった時に思い出していただきたい。
重要度別に☆何個みたいな感じで発表していこうとも思ったが, なんだかんだ無意識に使う知識が多いのでつけないで発表を行う。
Tips 1: まずDeep Learningとは何か
これはまあまず知能がどういうものかどうこうという話に持っていくこともできるんですが, 技術者研究者, アイシアソリッド信者としてはDeep Learningは関数近似論という考えを進めていきたい
Deep Learningを学んでいくと音声, 言語, 画像を数字の羅列としてモデル化して, それを入力として出力を計算し, 人間にとってわかりやすい形に戻すということをしていることがわかってくると思う。というわけで少なくとも自分は数値化した入力に対して欲しい出力を計算する関数を作るのがDeep Learningだと思っています。関連した話として, MLPのUniversal approximation theoremがあります。
Tips 2: それぞれのデータの表現の仕方
これもつまずくところかなと思います。テーブルデータの場合はデータ数と特徴量の2次元配列でわかりやすいです。画像もデータ数, RGBなどのチャンネル数, 高さ, 幅と考えれば4次元配列なのはわかるかと思います。
じゃあ言語とかはどうなっているのかというと, 実はDeep Learningでは系列データとして扱うことが多いです。
これはどういうことかというと, 例えば「I have a pen.」みたいな文章を考えた時, 単語ごとに区切ると[I, have, a, pen, .]みたいな5つに分けられます。これをI->have->a->pen->.の時系列順に単語が出現したと考えて次元の系列データにします。そしてとある変換を経てそれぞれの単語の数字で表された割とぼんやりとした意味みたいなのをE次元のベクトルで表現します。
なので,
$$
\text{I have a pen.} \rightarrow \text{[I, have, a, pen, .]} \rightarrow \text{(5, E)の2次元配列}
$$
みたいな感じで変換しています。長さLの文章なら(L, E)の2次元配列になります。このような文章がB個あると考えて, 文章データは(B, L, E)の3次元配列になります。文章で表現するなら, データ数, 系列長, トークンを表すベクトルみたいな感じです。トークンという言葉がでてきました。今回は[I, have, a, pen, .]という文章を単語で区切りましたが, 単語以外で区切ることも考えられます。例えばextra, extraordinary, extraordinarilyなどの単語は単語で区切るよりもextraordinaryは「extra, ordinary」, extraordinarilyは「extra, ordinarily」のように共通部分のextraを出してしまうといった方法もあります。この分割された1単位をトークンといいます。
とりあえずデータをこういう表現にしていると言うのは覚えておきましょう。ただ説明されてもわかりにくいものはわかりにくいので, この辺りはコーディングするのが一番だと思います。
あとコーディング上の注意としては, 深層学習の理論本や解説記事は1データに関する数式をかいており, 実際の処理とは違う数式を書いています。例えばMLPは理論本だと
$$
y = Ax + b
$$
のように書かれがちですが, Pytorchのnn.Linearのドキュメントでは
$$
y = xA^T + b
$$
のように書かれます。この違いはなんでしょうか? 詳しくは昔僕が書いた記事でも参照してください
Tips 3: Python
Pythonはクラス継承と基本的な構文はかけること, あとNumpyの挙動はしっかり学んでください特に, ブロードキャスト機能には慣れておきましょう。
あとは大規模なコードベースを読んでどこでエラーが起こっているかを理解できるようになっておいた方がよいかなと思います。Transformersライブラリは元リポジトリまで見に行かないとダメなエラーが多いです。
あとかなり個人的に大事なこととしてポリモーフィズムとインターフェースの概念はMLエンジニアも知っておいて欲しいと思います。特に生成AIはTransformersライブラリのクラスとメソッドを継承することが多いんですが, それを意識しないコードを書くと簡単に変な動作を引きます。
結局なんだかんだ普通のソフトウェアエンジニアリングのメンタルモデルがあると作業しやすいです。
Tips 4: 確率統計
深層学習に確率統計が必要だという話を聞いたことのある人は多いかと思います。個人的に一番それが活きるのは損失関数の選定の時だと思います。例えば, 分類問題を解く時に何故CrossEntropyLossを使うのか説明できますか?もし説明できなければ今すぐ確率統計を尤度推定まで学んで, 以下の記事を読んでください。
あとは誤差逆伝播法も一回は数式を追った方が良い経験になるとは思います。あと日本は恵まれていて, ゼロつく3巻がPytorchを0から作るような内容になっています。こちらも余裕があれば体験しておきましょう。
ここまでが一般的なDeep Learningにも大体通じる話ではないでしょうか, ここからは言語モデルとか生成AIとかに踏み込んでいきます。
Tips 5: Deep Learningで自然言語処理を扱う時の用語を理解する
主に以下が何をしているのか, どういう処理なのか, どう言う種類があるかを説明できるようになってください。
- Tokenize
- Encode(TokenにIDを振り分ける作業)
- Embedding
参考になるならどんな本でも記事でも良いです。W&Bの資料とかがよくまとまっていると思います。ただ言葉で説明できるようになるだけよりもコーディングはした方が良いと思います。理解度が全然違います。
Tips 6: OSと並列処理を理解する
ここまでくるとコンピューターサイエンスの知識から逃げることはできません。普通にパソコンを扱ってる時は起きないようなメモリオーバーな作業が多く含まれるようになってくるからです。まずOSはスレッド, プロセスの違いを理解し, 仮想記憶システム, mmapなどのシステムコールの挙動を理解しましょう。岩波のOSレベルまで読む必要はないですが, 大学の講義資料などがおすすめではないかと思います。とにかく, どの作業で物理メモリが割り当てられそうかということは知っておかないと下手にメモリを食う処理をすることになります。
スレッド, プロセスもOpenMP, MPIなどでプログラミングしておきましょう。MPIはこちらのリポジトリがおすすめです。
余裕があればGPUを使ってCUDAプログラミングもしてみてください。
Tips 7: Attention is all you need. を読む。
Tips 7の前に本などを参考にしてMLP, Conv2d, LSTMなどでモデルを組んでみてください。そのあとまずはAttention is all you need.を読みましょう。これは読んだ方がいいです。AttentionがLSTMなどの実時間計算の遅さの改善と性能を両立させたものであることなどを実感しましょう。あと余裕があればTransformerを組んでいる邦訳の本を読んだりして原論文の実装を再現しましょう。
Tips 8: 分散処理を理解する
大きなモデルを効率よく訓練するためには複数台の計算機にまたがって計算を行います。以下の記事に目を通し, Data parallelism, Pipeline parallelism, Tensor parallelismの概念はよく理解しておきましょう。この記事を理解するためにTips 6でMPIプログラミングをする必要があったんですね。
あとDeepspeedというライブラリも目を通すことをお勧めします。特にZeRO, ZeRO Offloadは理解しておきましょう。余裕があったらMegatron-LMとかもみてみましょう。
Tips 9: nanoGPTを写経する
nanoGPTは強化学習なしのGPTを実装するリポジトリです。Tips 7のScaled dot attentionの実装練習や, Tips 8のData Parallelismの実装などの良い演習になります。ここまで来ればなんとあなたは今の大規模モデルの基礎を作ることができるようになっています。
Tips 10: Huggingface Tutorial
Tips 9で満足してもいいんですが, やはり最新のAIに追いつきたいですよね。ここから先はPytorchやJAXを離れてHuggingfaceのTransformersライブラリを使ってモデルをファインチューニングすることが増えてくるかと思います。そのためにまずはHuggingfaceを学びましょう。NLP Courseなどがおすすめです。Huggingfaceはエラーを吐いたらソースコードまでなんども見直すことをおすすめします。そのためにもTips 3でPythonを学ぶ必要がありました。
Huggingface AccelerateやHuggingfaceでDeepspeedを呼び出す方法も学んでおきましょう。使いこなせば大規模モデルを自分で訓練するための強力なツールとなります。
Tips 11: Huggingfaceで自分好みのデータを使って事後学習をする
事後学習用ライブラリとしてHuggingface TRLなどがあります。TRLもただ使うだけではなく是非中身の処理を見てみることをお勧めします。ここまでくれば生成AIエンジニアを名乗ってもバチは当たらないんじゃないかと考えています。
終わり
学んだこととワークショップ中に質問がきたことをまとめてみましたが, この1年でこんなに学んだんだなという気持ちで一杯です。質問・指摘などがあればお願いします。