WEBVTT 00:01.160 --> 00:06.590 さて、 皆さんは私が「真実の瞬間が来た」と言うのにうんざりしていると思うが、 本当に来たのだ。 00:06.590 --> 00:07.970 真実の瞬間がやってきた。 00:07.970 --> 00:12.440 おそらくお分かりになると思うが、 私は非常に興奮している。 00:12.500 --> 00:17.270 これは我々にとって大きな出来事であり、 大きな、 大きな瞬間だ。 00:17.270 --> 00:24.680 まず最初に、 我々は7週目3日目のColabにいるのだが、 正直に告白すると、 00:24.710 --> 00:37.370 私はColabの箱の中で最も高価なA100 GPUの箱を選んだという、 ちょっとエッチなことをしている。 00:37.370 --> 00:46.790 11を食い尽くす。 77ユニットで1時間あたりの計算単位を算出し、 現在のレートは、 私の記憶が間違っていなければ、 00:46.790 --> 00:52.160 だいたい100ユニットで10ドルくらいだと思います。 00:52.160 --> 00:56.000 つまり、 これは1時間に約1ドルを費やしていることになる。 00:56.210 --> 01:00.050 ええと、 今現在、 その値段は時々変わるんだ。 01:00.050 --> 01:05.820 うーん、 そうだね、 これはいつものように安くはないよ。 01:05.820 --> 01:07.260 そして、 こんなことをする必要はない。 01:07.260 --> 01:13.050 間違いなく使えるよ。 01:13.080 --> 01:14.820 ええと、 ランタイムのタイプを変更してください。 01:14.820 --> 01:16.560 t4GPUを使用している可能性があります。 01:16.590 --> 01:21.030 そのためにどのパラメーターを変更すればいいかを教えよう。 01:21.090 --> 01:25.560 うーん、 でも、 もしあなたが数ドルの出費を気にせず、 爆走したい、 ハイパーパラメーターを変更し、 01:25.560 --> 01:36.540 速くトレーニングしたいのであれば、 しばらくA100ボックスを持って、 40GBのGPU Ramを搭載したボックスの生のパワーを体験するのは美しいよ。 01:36.540 --> 01:46.080 なぜなら、 このようなジューシーでパワフルなボックスがあるのはとても喜ばしいことだからだ。 01:46.080 --> 01:49.260 とにかく、 まずはpipのインストールから始めよう。 01:49.260 --> 01:56.850 これには、 HuggingfaceのTRL Transformers Reinforcement Learningというライブラリがあり、 01:56.850 --> 02:03.730 SFTトレーナー監修のFine Tuning Trainerが含まれています。 02:04.090 --> 02:10.990 前回のビデオでは、 トレーニングについて少しお話しましたが、 その際、 02:11.170 --> 02:23.440 ハイパーパラメータについてお話し、 フォワードパスとバックワードパスのトレーニングプロセスについて少しお話しました。 02:23.440 --> 02:26.830 そしてまた、 ある人たちにとっては、 このことはもう古いことで、 よく知っていることだろう。 02:26.830 --> 02:36.490 トレーニングの全過程をもっと時間をかけて説明できないのか? 02:36.490 --> 02:43.600 そして、 ひとつ言いたいのは、 ハグフェイスのおかげで、 このことがとても身近に、 とても簡単になったということだ。 02:43.660 --> 02:49.150 モデルをトレーニングするための参入障壁を低くしているので、 最適化や正しい方向へのステップを踏む上で、 02:49.180 --> 02:57.220 何が起こっているのか直感的に理解することは非常に役に立つ。 02:57.220 --> 03:00.880 理論の詳細を知ることは必須ではない。 03:00.940 --> 03:04.390 ハイパーパラメーターを微調整できるくらいの知識があればいいんだ。 03:04.390 --> 03:04.390 パラメーター 03:04.390 --> 03:07.960 顔をハグすることで、 トレーニングは驚くほど簡単になる。 03:07.960 --> 03:13.690 だから、 もし頭から抜けてしまったと感じたとしても、 それは本当に重要なことではないので安心してほしい。 03:13.690 --> 03:15.760 規約を見れば一目瞭然だ。 03:15.760 --> 03:20.710 そして、 もしあなたがすでにこのようなことを隅から隅まで知っていて、 最適化に精通しているのであれば、 それは素晴らしいことだ。 03:21.130 --> 03:22.750 そうすればもっと良くなる。 03:22.750 --> 03:24.220 そうすればもっと簡単になる 03:24.430 --> 03:27.760 よし、 では輸入をいくつかやってみよう。 03:28.120 --> 03:31.180 そして今、 私たちは話すべきたくさんのパラメーターを持っている。 03:31.180 --> 03:36.160 ベースモデルはもちろんラマ3だ。 180億ドル 03:36.160 --> 03:38.680 私たちはそのプロジェクト名をよく知っている。 03:38.680 --> 03:42.820 つまり、 これがウェイトとバイアスで使われるプロジェクト名だ。 03:42.820 --> 03:47.980 そうなったら、 その結果を比較するんだ。 03:47.980 --> 03:51.010 そして、 ハギング・フェイスのハブにアップロードする際にも使う。 03:51.010 --> 03:55.990 そして、 このプロジェクトにはプライサーという名前を使っている。 03:55.990 --> 04:00.820 GPTをトレーニングしていたとき、 私はそれをプライサーGPTと呼んでいたのを覚えているかもしれない。 04:01.360 --> 04:07.520 プロジェクトは別々にしているのは、 結果があまりにも異なるからだ。 異なる量を計測するというだけで、 04:07.520 --> 04:10.640 同じプロジェクトにすると混乱するだろう。 04:10.910 --> 04:14.600 ええと、 だから、 僕はこれをただのプライサーと呼んでいるんだ。 04:15.170 --> 04:19.580 ええと、 ハギング・フェイスのユーザー、 ここにハギング・フェイスの名前を入れるべきだよ。 04:19.670 --> 04:29.180 ええと、 あなたが微調整したモデルを大事にし、 将来的に使用するために、 モデル用のハブにプッシュ投稿したくなるでしょうから。 04:29.180 --> 04:30.860 また、 非公開にすることもできる。 04:30.860 --> 04:33.440 ええと、 自分で食べるだけだよ。 04:34.430 --> 04:38.000 データに関しては、 データセットをロードする必要がある。 04:38.000 --> 04:41.810 そしてここで、 あなたには選択肢がある。 04:41.840 --> 04:47.990 数週間前にデータ・キュレーションを行った際に、 ハギング・フェイスのハブにデータセットをアップロードしたのであれば、 04:47.990 --> 04:53.960 この行をそのままにしておけば、 ハギング・フェイスのユーザー名とプライサー・データが表示され、 04:53.960 --> 04:59.210 それを読み込むことができます。 04:59.330 --> 05:08.460 あるいは、 もしあなたが、 その1本だけを見て、 僕がデータセットをやっているのを見ようと決めたとしても、 それをHuggingfaceにアップロードしなかったとしたら。 05:08.460 --> 05:09.030 残念だ。 05:09.030 --> 05:11.460 それでも、 かなり多くのことがあったことは理解している。 05:11.490 --> 05:15.660 ハードコードしたこの行をコメントアウトすればいい。 05:15.660 --> 05:17.010 そこにFは必要ない。 05:17.220 --> 05:24.150 ええと、 僕のハブにはデータの価格をハードコーディングしてあるんだ。 05:24.150 --> 05:26.460 そこでダウンロードすればいい。 05:26.460 --> 05:26.730 素晴らしい。 05:26.760 --> 05:27.360 素晴らしい。 05:27.360 --> 05:29.730 自分でアップロードする必要はない。 05:30.090 --> 05:36.180 それから、 最大配列長ですが、 データは常に179トークン以下になるように作られていることを思い出してください。 05:36.180 --> 05:46.620 文頭の数トークンと、 末尾のガムテープのようなものを加えて、 最大配列長182ということになります。 05:46.620 --> 05:50.610 これは非常に重要なことで、 すべてのトレーニング・データ・ポイントがこれに適合することになるからだ。 05:50.610 --> 05:55.080 そのため、 GPUのメモリに収まるような小さな数値にする必要がある。 05:55.260 --> 05:59.640 そのため、 この金額内に収まるように説明を削っている。 06:00.450 --> 06:11.350 それで、 いくつか、 ええと、 管理的なことなんだけど、 それぞれのランにランネームというものを考えたんだ。 06:11.350 --> 06:12.010 月だ。 06:12.010 --> 06:13.720 曜日と時間 06:13.720 --> 06:13.990 分。 06:13.990 --> 06:14.650 セカンドだ。 06:14.800 --> 06:18.550 その理由はすぐにわかるだろう。 06:18.580 --> 06:23.830 プロジェクト・ラン名と呼ばれるもので、 Pricer、 06:23.830 --> 06:32.200 ハイフン、 日付、 そしてモデルを保存するハブモデル名がユーザー名になります。 06:32.200 --> 06:34.480 そしてこれだ。 06:34.810 --> 06:35.290 ええと。 06:35.290 --> 06:36.670 そして、 なぜ私はこんなことをしているのか。 06:36.670 --> 06:40.000 だから時々、 1つのモデルだけを持ちたがる人がいる。 06:40.000 --> 06:46.720 そしてこれを実行しながら、 同じモデル・リポジトリに対して保存する異なるバージョンをアップロードするだけだ。 06:46.720 --> 06:49.810 Huggingfaceのすべてが単なるgitレポであることを覚えておいてほしい。 06:49.810 --> 06:56.560 だから、 基本的には、 新しいバージョンのコードをチェックインしたり、 新しいバージョンのコードをプッシュしたりするだけで、 06:56.560 --> 07:03.700 新しいバージョンのモデルをプッシュし続けることができる。 07:03.700 --> 07:07.600 同じモデル名でもバージョンが違うだけかもしれない。 07:07.600 --> 07:17.230 しかし、 私は自分の異なるランを分けて、 それぞれを異なるモデルとして持ちたいんだ。 07:17.230 --> 07:22.450 ハイパーパラメーターを変えてトレーニングすることもあるし、 そのメモを残しておきたいからだ。 07:22.900 --> 07:25.300 だから、 それが僕の好きなやり方なんだ。 07:25.390 --> 07:28.420 厳密には必要ではないが、 役に立つと思う。 07:28.510 --> 07:34.150 その感覚を味わってもらうために、 ランネームをいくつか挙げてみよう。 07:34.480 --> 07:37.450 今、 ランの名前をお見せしましょうか? 07:37.960 --> 07:46.150 ランネームは、 22日という現在の日付と、 現在の時刻です。 07:46.330 --> 07:50.080 その時間は協定世界時(UTC)である。 07:50.080 --> 07:52.690 実はまだ午前0時4分じゃないんだ。 07:53.020 --> 07:55.060 ええと、 それがランの名前なんだ。 07:55.060 --> 07:57.220 それからもうひとつは? 07:57.220 --> 08:00.730 プロジェクト・ラン名とハブ・モデル名がある。 08:00.730 --> 08:07.480 だから、 プロジェクト・ランの名前はPricerと続くだけだ。 08:07.480 --> 08:12.860 そして、 アップロードされるハブのモデル名。 08:14.720 --> 08:16.190 そうなのか? 08:16.190 --> 08:20.360 これは、 実行後にその名前のモデルを作成することになる。 08:20.360 --> 08:29.150 モデル・ディレクトリを見ると、 このようなものがたくさんある。 08:29.240 --> 08:31.100 でも、 とても楽しかった。 08:31.160 --> 08:34.070 あ、 この手の値段の高いモデルはたくさん持っているよ。 08:34.070 --> 08:36.770 みんな走っていたよ。 08:37.070 --> 08:45.260 ええと、 それで最後に、 ええと、 あそこで接続が切れたり切れたりしてるのが見えるんだけど。 08:45.500 --> 08:55.430 トレーニングに使うハイパーパラメータは、 行列の次元です。 08:55.490 --> 08:57.110 ええと、 32から始めます。 08:57.140 --> 08:59.540 だから、 それを8つまで減らすことができる。 08:59.540 --> 09:01.520 特に下位のボックスで走っている場合はね。 09:01.520 --> 09:02.900 大丈夫だよ。 09:03.050 --> 09:06.140 ええと、 ローラ、 アルファはダブルRのはずだよ。 09:06.170 --> 09:09.440 ええと、 これを8つに減らすと16になる。 09:10.040 --> 09:13.050 もちろん、 ターゲット・モジュールだ。 09:13.050 --> 09:14.520 あなたはそれを知りすぎている。 09:14.520 --> 09:15.840 それが何であるかは言うまでもない。 09:17.190 --> 09:19.770 そして、 これがラマ3世のスタンダードなものだ。 09:19.800 --> 09:21.960 これらは、 あなたがターゲットとするモジュールである。 09:22.080 --> 09:26.250 ローラの脱落は、 前回かなり長い説明をしたことだ。 09:26.250 --> 09:33.450 正則化、 つまりモデルが新しいデータポイントに対してうまく汎化できるようにするためのトリックで、 09:33.480 --> 09:47.160 ニューロンの10%(この場合は10%)を取り出し、 それらを消去してアクティブ度をゼロにする。 09:47.160 --> 09:51.780 その結果、 モデルは特定のニューロンに過度に依存することはない。 09:51.810 --> 09:59.160 モデル全体がトレーニングポイントを受け取り、 正しい次のトークンを与えることができるようになるよう、 09:59.160 --> 10:03.390 一般的に学習しているのだ。 10:03.540 --> 10:07.020 10%は10である。 1は非常に典型的な出発点だ。 10:07.020 --> 10:13.300 5%と20%を試してみて、 そのパフォーマンスとビットの量を見てみるべきだ。 10:13.300 --> 10:13.690 その通りだ。 10:13.720 --> 10:16.150 これは4ビットに量子化することである。 10:16.690 --> 10:17.530 オーケー。 10:17.560 --> 10:20.740 トレーニング用のハイパーパラメータ。 10:20.980 --> 10:23.230 私はこれを3エポック実行するように設定した。 10:23.230 --> 10:25.060 一人だけならできるだろう。 10:25.270 --> 10:30.580 ぜひとも、 1回のバッチサイズで申し分のない結果が得られるだろう。 10:30.580 --> 10:32.980 私はここで16番を任された。 10:33.130 --> 10:36.580 ええと、 一緒に必要ですか? 10:36.580 --> 10:39.760 ジューシーなA100の箱で? 10:39.760 --> 10:42.790 私は16バッチで包装できる。 10:42.790 --> 10:51.760 これが最大シーケンス長であることを考えると、 すべてのシーケンスを詰め込んでも、 40GBのメモリにギリギリ収まる。 10:51.820 --> 11:00.820 うーん、 でも、 もしT4のようなローエンドボックスを使うつもりなら、 これを試してみるのもいいかもしれないね。 11:00.850 --> 11:01.480 もっと高くしてみて。 11:01.480 --> 11:04.300 もしGPUメモリが増えたとしても、 それはまだ無料だ。 11:04.480 --> 11:09.340 バッチサイズには2のべき乗を使うという慣例があるんだ。 11:09.340 --> 11:12.640 つまり、 1か2か4か8か16か。 11:12.820 --> 11:20.290 理論的には、 2のべき乗にするとGPUが並列化しやすくなり、 パフォーマンスがわずかに向上するという、 11:20.290 --> 11:27.160 さまざまなゆるい証拠があります。 11:27.250 --> 11:33.370 でも、 そのデータはいつも、 ちょっと曖昧なんだ。 11:33.370 --> 11:41.800 だから一般的に言って、 GPUにもうちょっと多くのバッチを詰め込めるなら、 そうすべきだと思う。 11:41.800 --> 11:44.860 だから、 私は3人分のバッチを作ることをためらわない。 11:44.890 --> 11:48.940 それをGPUに搭載できれば、 2つのバッチサイズよりも高速に実行できるだろう。 11:49.000 --> 11:54.820 ええと、 もしかしたら、 4つあれば、 もう少し、 もう少し効率的になるかもしれない。 11:54.820 --> 12:02.080 ただ、 一般的なアドバイスとしては、 GPUに搭載できるものなら何でもいい。 12:02.080 --> 12:08.320 私のように大枚をはたくのでなければ、 16段のグラデーション蓄積を目指そう。 12:08.320 --> 12:09.430 それは前回説明した。 12:09.430 --> 12:13.570 実際、 これはプロセスの記憶を向上させるのに役立っていると思う。 12:13.600 --> 12:16.760 ああ、 やってみてもいいけど、 でも僕は1人でいるよ。 12:16.760 --> 12:19.040 2、 4番でも試すことができる。 12:19.340 --> 12:29.210 学習率......超重要なのは、 正しい方向への一歩を踏み出そうと最適化するときに、 どれだけの一歩を踏み出すかということだと理解していると思う。 12:29.210 --> 12:34.250 そして学習率は、 実験が必要な超重要なハイパーパラメーターだ。 12:34.370 --> 12:40.130 うーん、 これは正解がないことのひとつなんだ。 12:40.160 --> 12:42.830 学習率は高すぎるかもしれないし、 低すぎるかもしれない。 12:42.860 --> 12:46.220 あなたが達成しようとしていることは、 少し手探りなものになるだろう。 12:46.250 --> 12:55.910 繰り返しになりますが、 あなたが達成しようとしているのは、 あなたのモデルの本当の損失が、 このように大きなくぼみを持つものだと想像することです。 12:55.910 --> 12:59.540 そして、 あなたはこの谷を見つけようとしている。 12:59.540 --> 13:07.460 そして、 谷の方向に沿ってステップを踏み、 谷の底にたどり着くように下がっていく。 13:07.460 --> 13:14.870 学習率が高すぎると、 谷を飛び越えてはまた戻り、 実際に谷に降りることはないかもしれない。 13:14.870 --> 13:16.770 学習率が低すぎる場合 13:16.800 --> 13:22.170 小さな小さなステップを踏みながら、 その谷に向かって2歩ずつゆっくり進んでいるかもしれない。 13:22.200 --> 13:24.810 小さなステップを2つ踏むことには、 もう一つ問題がある。 13:24.810 --> 13:31.560 仮に大きな谷が1つだけでなく、 小さな谷と大きな谷があるとする。 13:31.590 --> 13:38.010 学習率が低すぎると、 小さな一歩を踏み出しても、 小さな谷に沈んでしまうかもしれない。 13:38.010 --> 13:45.120 そして実際、 あなたが踏み出す小さな一歩一歩は、 小さな谷の二つの壁を登っていくだけで、 その小さな谷から出ることはない。 13:45.180 --> 13:50.340 だから、 すぐ隣にもっと大きな価値の谷があったことに気づかない。 13:50.730 --> 13:55.860 それが重要な問題だ。 13:55.860 --> 13:59.040 学習率が小さすぎるのはよくある問題だ。 13:59.070 --> 14:02.400 人はそれをローカルミニマムから抜け出せないと呼ぶ。 14:02.400 --> 14:05.370 これはミニマムと呼ばれるもので、 あなたがいる場所のローカルなものだ。 14:05.370 --> 14:12.780 ローカル・ミニマムから抜け出せないので、 グローバル・ミニマムはまだ見つかっていない。 14:12.780 --> 14:16.290 そしてそれが、 学習率が低すぎることの問題なのだ。 14:16.680 --> 14:19.210 こんな素敵なトリックがある。 14:19.270 --> 14:25.390 学習率は0を選んだ。 10の00011乗マイナス4。 14:25.660 --> 14:30.820 学習率スケジューラーというものを使うと、 学習率を変化させ、 3回のエポックの間にどんどん小さくしていき、 14:30.820 --> 14:36.220 3回のエポックが終わるころには学習率がほとんどゼロになるようにする、 14:36.250 --> 14:40.870 いいトリックがある。 14:41.200 --> 14:42.340 ええと、 そして、 あなたはそれを与えることができる。 14:42.370 --> 14:45.700 これらのいずれかを使用する場合は、 異なる形状を与えることができる。 14:45.700 --> 14:55.390 そしてコサインはとてもいいもので、 学習率が徐々に低下していくところから始まり、 その後かなり低下していく。 14:55.390 --> 14:57.250 そして最後には尻すぼみになる。 14:57.400 --> 14:59.650 すぐに視覚的にわかるよ。 14:59.650 --> 15:01.960 そして、 それは本当に良い、 良いテクニックだ。 15:02.110 --> 15:07.510 最終的な学習率のパラメーターはウォームアップ率と呼ばれるもので、 学習プロセスの最初の段階では、 15:07.510 --> 15:15.190 モデルは最初の数データポイントから多くのことを学ばなければならないため、 かなり不安定になると言っています。 15:15.190 --> 15:20.020 それに、 最初に学習率を大きくするのはかなり危険だ。 15:20.020 --> 15:28.330 つまり、 ウォームアップの比率は、 低い学習率から始めて、 ピークとなる学習率までウォームアップさせるということだ。 15:28.330 --> 15:31.960 そしてコサインのトレイルを始めるんだ。 15:32.230 --> 15:33.550 そして、 それを視覚的に見ることができる。 15:33.550 --> 15:34.420 だから、 もっと意味がある。 15:34.420 --> 15:36.880 しかし、 これらは非常に賢明な設定だ。 15:36.880 --> 15:42.700 しかし、 学習開始率を高くしたり低くしたり、 スケジューラーの種類を変えてみたりすることは間違いなくできる。 15:43.090 --> 15:45.760 そして最後にオプティマイザーだ。 15:45.910 --> 15:54.430 だから、 ここではページングされたアダムwを選んでいる。 wとは、 ページングされたアダムw 32ビットのウェイト減衰を意味する。 15:54.460 --> 15:57.940 これは収束性の良いオプティマイザーだ。 15:57.940 --> 16:04.480 最適な場所を見つけるのは良い仕事だが、 その代償としてメモリを消費する。 16:04.660 --> 16:11.260 ええと、 あなたが選ぶことのできるさまざまなオプティマイザーについてのハグフェイス・ライトアップへのリンクをここに貼っておきます。 16:11.320 --> 16:15.910 ええと、 トランスフォーマーで最も一般的なのはアダムかアダムであることは明らかです。 16:15.910 --> 16:25.310 アダムは、 過去の勾配のローリング平均を保存し、 最新の勾配だけでなく、 16:25.550 --> 16:28.820 それを使うからだ。 16:28.820 --> 16:32.420 しかしもちろん、 それを保存することで、 余計なメモリ・フットプリントが必要になる。 16:32.420 --> 16:34.640 だから、 ちょっとメモリに貪欲なんだ。 16:34.640 --> 16:41.990 だから、 もしメモリが足りなくなったら、 より安価で、 より貪欲でないオプティマイザを選んでメモリを節約するという選択肢もある。 16:41.990 --> 16:48.590 しかし、 その結果は、 ページングされたアダムを使うよりも若干悪いかもしれない。 16:48.620 --> 16:51.680 そして最後に、 いくつかの管理設定を行う。 16:51.710 --> 16:56.600 ええと、 このステップ数は、 その前に何回バッチステップを踏むかということです。 16:56.630 --> 17:01.310 ウエイトとバイアスに進捗状況を保存し、 物事の進捗状況を示してくれる。 17:01.460 --> 17:10.460 モデルを実際にハブにアップロードし、 適切なバージョンを保存するまでに、 このようなステップがあります。 17:10.460 --> 17:17.090 これは、 ウェイトとバイアスにログを取るかどうかということで、 パラメーターのツアーになる。 17:17.090 --> 17:21.770 そして次回は、 本当にトレーナー自身に迫っていく。