当wikiでは画像生成分野での学習における「loss」の意味で用いる

>
#contents

*概要 [#vb15dc3a]
-Wikipedia
https://ja.wikipedia.org/wiki/損失関数

-lossとは、簡単に言うと、学習中に発生する、教師画像と学習中の計算結果の差異のこと。
-機械学習を行うということは、weightと呼ばれる変数を解く行為に相当する。
--Stable Diffusionではものすごく雑にまとめると回帰分析のようなものだが、最小二乗法のように連立方程式1発で解くことはできないので反復処理してweightを調整する。

 説明上の都合、すごく簡単に表現した学習モデル
 f(入力画像) = g(weight, 入力画像) → (教師画像の予測値)
 g()は、例えば weight×入力画像 など
 
ここでf(), g()はモデル(事前学習モデルや既知のU-Net層などの関数)を含めた関数。
義務教育で習う二次関数でいうと、ax^2 + bx + cのa, b, cのところがweightやbiasといったパラメータ。
二次関数の式のxに相当するのは推論時の入力値で、画像生成モデルでは入力ノイズ画像、プロンプトやステップ数など。

#br

lossが小さいほど、教師画像とモデル予測値とのズレが少ないということなので、学習用プログラムはloss削減するようにウェイト算出をします。

*lossの種類 [#a4bc6648]
lossは設計次第で自由に作成できるが、実用面を考えると画像生成AIで使用されるものは限定される。
**重み付けによる分類 [#he10dbeb]
-lossの値をどう重み付けするかという視点で分類ができる
lossの名称や評価対象というよりも、lossの算出方法に着目した分類である
-学習において基本的にはPyTorchに登録されている下記が使用されることが多い。
下記がよく使われるloss計算式。
--[[L1>https://docs.pytorch.org/docs/2.12/generated/torch.nn.L1Loss.html]]
--[[MSE(L2)>https://docs.pytorch.org/docs/2.12/generated/torch.nn.MSELoss.html]]
--[[SmoothL1>https://docs.pytorch.org/docs/2.12/generated/torch.nn.SmoothL1Loss.html]]
--[[Huber>https://docs.pytorch.org/docs/2.12/generated/torch.nn.HuberLoss.html]]

-数式と定義はリンク先に書いてありますので、このページでの定義の説明は省略します。

-sd-scripts, musubi-tunerでも上記のlossが使用されているが、loss計算式そのものをPyTorchを使用せずにスクリプトに内蔵することで、PyTorchのバージョンとの依存性を断つ工夫をしている。

**L1, L2, SmoothL1, Huberの特徴 [#h1db5812]
pred(予測値), target(目標値、教師データ)とするとき((実際に学習コード内部でもpred,targetと表現されている))、便宜上、predとtargetの差を予実差と呼ぶものとします。何を比較するかはツールによって異なりますが、ピクセル毎の比較をする手法が多いです。
下記の特徴はケースバイケースなので、ここでは初心者向けの''直接的な影響と有名な問題の説明''に留めます。
数式や定義は先述のリンクを参照して下さい。

#shadowheader(3,L1 loss)
予実差がそのままlossの値になる。
-メリット
--lossの意味が直感的にわかりやすい
--求められる[[勾配]]はどんな予実差でも一定であり、[[勾配]]が過大になりすぎない。
---教師画像に外れががあっても無理に拾わない
---常に安定した大きい[[勾配]]が得られるため、局所解にはまりにくい
--ボケにくい
---ノイズが多く教師画像の候補が複数考えられるケースなどでは、モデル予測値が「正当群の中央値」に向かって収束するように訓練される為、L2 lossより平均化によるボケが抑制される
---メディアンフィルタがボケにくいのと同じような理屈だが、フィルタリングされるのは画像内の近傍画素群じゃなくて教師画像群のほう
-デメリット
--loss=0付近において、急激に[[勾配]]は正負反転する。
---''収束することが難しくなる''。
---ベースモデルの学習済み情報が消されやすい
--どんな教師データに対しても、学習の進行ペースが比較的一定なので、メジャーな情報ばかり学習しがちで、数の少ない正則化画像が寄与しにくい
---データセットの画像枚数バランスの調整が煩わしくなる
---学習の順序(画像のstepの順番)、timestep samplingの影響を受ける
--サンプラーが前提としている数学的条件から外れる為、相性問題が出る可能性がある
---[[CFG>CFG Scale]]等も理論的に厳密な裏付けがあったというよりは実証実験で効果が出たことにより導入されているので、予測値がある程度妥当であればカバーされる
---拡散モデルは本来、ノイズが多く教師画像の候補が複数考えられるケースなどではモデルは「正答群の加重平均」を返すよう訓練されることを前提としている
しかしL1 lossだと予実差の大小を問わず勾配は正負が異なるだけの定数になるため、理想的には「正答群の中央値」に収束する。これは必ずしも平均に近づくとは限らない
---具体的には、どっちつかずのときにL2 lossで学習したときよりも急峻に予測が揺れることが予想される
極端な例を出すと信じて送り出した瓶底眼鏡っ娘がちょっと黄色が入っただけで急にギャル化するようなことがL2よりも起こりやすい
高次補正サンプラーが前提としている「モデルの予測値がある程度滑らかで安定している」という条件が崩れる可能性が高まる

総じてデリケートな運用が要求される。

#shadowheader(3,MSE(L2) loss)
-予実差の2乗がlossになる。
予実差が大きいと[[勾配]]が急速に大きくなり、
予実差が小さいと[[勾配]]はとても小さくなる。
-画像生成AIの基礎論文(DDPM、Flow Matching)で使われている一番基本的なloss。
-メリット
--loss=0付近において、[[勾配]]が小さくなるため、限りなくloss=0周辺で収束しやすい。
--収束しそうなウェイトと、そうでないウェイトに学習の速度差が発生し、特定のウェイトが遅れるということが少ない
-デメリット
--外れ値(画像のJPEGノイズや、余計な背景など)を拾いやすい
---ただし、正則化画像を準備することで打ち消すことは可能な程度である
--教師画像の候補が複数考えられるケースなどで考えうる教師画像の加重平均を返すように訓練される
---「近傍画素群」の加重平均ではなく、「想定しうる教師画像群」の加重平均となる((ただし、「画像が平均化されてボケる」現象と「複数の教師画像が滑らかにブレンドされて新しい絵が創作される」現象は表裏一体であり、メリットにもなりうる))
//↑「ただし、」以降の内容は(())内に移動。直接的な理由としてはちょっと弱く運用面での話になるが、「想定しうる教師画像群」の加重平均となると強く紐づいた情報であるという理由から他項へ移動せずに(())内で保持します
--L1 lossよりボケやすい。
--L1 lossよりノイズが多い。

適当な設定でもそこそこ再現性の高い結果が得られるが、
好ましい情報(学習/生成安定性やマイナータグ)、好ましくない情報(外れ値)の両方を取り入れやすくなるため、それをユーザーがどう判断するかで、評価が変わる。

#shadowheader(3,SmoothL1 loss、Huber loss)
-どちらのlossも、L1, L2の良い所をブレンドしたloss。
予実差が少ないときはL2を、予実差が大きいときはL1を使用する。
--特にMES(L2)の弱点を補うことができる。
--モデルの予測値はt値に応じてスケールされる為、ノイズが少ないステップでは生成時の見た目より巨大な値になることに注意。
-L1とL2を切り替えるしきい値を設定して使用する。
--sd-scriptsの場合は、huber_cというパラメータを指定する。
-両者の違いは、huber_c値の設定によってL1領域(グラフの直線部分)の傾きが変わるか、同じかである。
ただ、sd-scriptsの場合はsmooth_L1しか使えないので、特に意識する必要はない。
#ref(./Smooth_L1_vs_Huber_loss.png,60%)
CENTER:*図はとしあき自作(Gemini生成画像)

-メリット
--L1,L2のメリットすべて
--外れ値を除外しやすいため、ベースモデルの特徴を維持しやすい
-デメリット
--外れ値を除外し過ぎて教師画像が活かされにくくなる。
予実差小のときはL2効果によりブレーキがかかり、予実差大のときはL1効果によりブレーキがかかる、というダブルブレーキ構造が問題。
---結果として、ベースモデルからの脱出が難しくなる。
--''c値の設定が面倒''
c値を調整するとloss曲線の全体が変化するため、''直感的な調整が困難''である。
#fold(詳細){{
-具体的にはc=0.05, 0.1, 0.2, 1.0といった粗い設定をしない限り変化を実感しにくいにも関わらず、
c値の選択の有無で局所解から脱出可否が大きく左右されるために、c値の設定にもそれなりに厳密さが求められるという困難さがある。
-その難しさを理解するなら、ここで説明するよりも実際に挑戦する方が早い
}}

-c値調整
ひとまずcを低めに設定して、もし収束せず不安定ならば、c値を上げてL2特性を強めるようにすると良いかも知れない。

-補足
sd-scriptsのsmooth_L1は、PyTorchのsmooth_L1と数式の0.5倍になっていて、厳密には同じものではない

-huber_lossに関する情報
--arXiv論文
https://arxiv.org/abs/2403.16728
--sd-scriptsで導入時のやりとり
https://github.com/huggingface/diffusers/issues/7488

**どのlossを使えばいいの? [#x6b71b65]
前項の特徴を読んで悩んだ人向けに簡単に。
//↑正解はないのでwikiで示すことは好ましくないが...前項の特徴を読んで悩んだ人向けに簡単に。という意図。
//なので、基本的に最小限の情報とし防衛的内容にしたほうが、他サイトからの攻撃を防げる(Claude等からの無作為情報取得による偽情報の流布や、正義マンからの修正要求によるページ本質の喪失を回避するため)
-オプティマイザやLearning rate、loss_weighting((=min_SNR_gammaなどの,loss補正式全般のこと)), 正則化画像との強い相性があるので、ここでの説明は難しい。
それらのどの手段を用いて、収束と学習進行を両立させたいかのトレードオフ。
-とはいえ、L2特性があるのは便利なので、
L2, smooth L1のどちらかを選ぶのが一般的とされている。

**【参考】L1, L2, SmoothL1, Huberの適用事例 [#l558a97f]
//元々、1個前の項目に書かれていた内容を移植しました。「特徴」という項目名からは外れる「実態」に近い内容なので項目を新設するに至りました。時節の影響を受けやすい情報であるため将来的に非正確な情報となる可能性を想定し、【参考】という題名にしています。

#shadowheader(3,L1 loss)
-ボケにくさというメリットのためか、モデル本体以外では[[VAE]]で使われている
-Consistency Models等の蒸留モデルは予測ターゲット自体が通常のモデルと異なる為L1 lossがデフォルトのものもある


**評価対象による分類 [#ab8b8ef1]
ピクセル単位での比較ではなく、画像そのものの質を評価する方式
LPIPSなどがあるが、
当wikiでは使用することがないため、省略します。

*lossは小さいほど良い? (よくある質問)[#fde51bb0]

半分正解ですが、どちらかと言えば No.
あくまで「1つの指標」と捉えるのがベター、という意見が多いです。
#br

#shadowheader(3,「Yes」である理由)
-学習過程の進行度合い
--lossを徐々に下げることで、モデルが教師画像の特徴を捉えているか確認できる。
--タグや画質がバラバラな教師画像で、あるステップだけlossが大きくなる(例:20%超)と、その画像の特徴をまだ学習できていないことを示す。
-最終的なモデル精度への寄与
--教師画像の特徴をきちんと反映させたい場合、ある程度lossを小さく抑えることは有効。
--LoRAやHyperNetworkなど、非few‑shot系手法で学習した経験がある人には馴染みがある現象です。

#shadowheader(3,「No」である理由)
-lossはモデル性能の一部しか表せていない
--sd-scriptsなどの一般的なトレーニングツールでは、lossとして教師画像と予測値とのズレが数値的に大きいか小さいかしか計測していないことが多い。
--そのズレが人間の知覚特性にとって目立つか目立たないか、プロンプトの効きはどうかといった点は使ってみないとわからない。

-loss=0でも生成結果は完全一致しない
--loss=0は「たまたまそのバッチでドンピシャで予測できた」というだけで、すべての教師画像を網羅できているとは限らない。
--「lossがほぼ0」は「誤差の絶対値の総和がゼロに近い」だけで、ピクセル単位で一致したわけではない。
またモデルの予測値は「教師画像そのもの」ではなく「教師画像を復元するために削るべきノイズ」であり、さらに生成時にはステップごとに予測誤差が蓄積するので、lossの見た目よりも復元画像は大きくズレることが多い。
--またモデルの予測誤差がわずか1点だけだったとしても、[[VAE]]がデコードした際に周囲に伝播する。
--数ステップでloss≈0.01(1%)に到達しても、その時点の生成物は事前学習モデルの影響が大きく、教師画像の再現には至らないことが多い。

-過学習の危険
--step数を増やしすぎると、特定層のウェイトが過大・過小になり、汎用性を失ったモデルになる。
--weightはテンソルなので、たとえloss=0でも解は一意に定まらない。
-ランダム要素への脆弱性
--学習中に理想のweightを得られても、生成時にSeedやノイズが少し変わるだけで想定外の結果(奇形や別画風)になることがある。
--比喩的に回帰分析を挙げると、回帰分析ではデータ数より多い次数にすれば無理やり誤差ゼロにできてしまうがオーバーフィッティングで予測能力はない。
ニューラルネットワークは伝統的な回帰分析よりは過学習が起きにくいように設計されているが、それでもデータ数が少なすぎると同様に過学習される。ベースモデルに莫大な量の教師画像が使われているのはこの為。

-モデル種別が異なるとlossの相場も異なる
--SDXLやSD1.5とFlow Matchingモデルとだと予測ターゲットが異なるので、同じloss評価を使っていても数値の相場も異なる。
一般にFlow Matchingモデルのほうが予測が難しくlossが下がりにくい。
SDXLでもepredとvpredとで差が出る。

-個々の教師画像x0との比較は勾配を出すための方便であって、モデルの真の学習ターゲットは想定しうるすべてのx0を考慮したうえでの期待値(加重平均)
#fold(生成時のモデルの挙動){{
※ステップ数はあくまでイメージ
#ref(./behavior-of-diffusion.jpg)
}}
--Flow Matchingモデルの場合は教師画像x0だけでなく起点画像(生成開始時のノイズに相当)x1についてもあらゆる可能性を考慮したうえでの期待値が学習ターゲットになるので、lossを0にするのは不可能に近い。
--理想的なモデルであっても、推定される教師画像の候補が2つあってどちらの可能性も半々というときはそのステップでは中間ぐらいの予測値を返せばよく、lossは0にならなくても良い。
---この場合、理想的な学習が行われていればどちらかに寄りすぎるともう片方の教師画像でlossが大きくなるのでどちらにも偏らないように学習される。
--モデルに本当に学習させたいのは生成結果x0が誰にも不明な状況でどう編集すればいいか(ノイズe ∝ -∇xt log pt(xt) ただしpt(xt)は混合分布)だが計算不可能。
---pt(xt)は「データセット全体についてのtステップノイズ化させた段階でのノイズ化画像の分布」になるが、個々の教師画像を中心にノイズでぼかしたものの重ね合わせになる為、ノイズの量が下がるにつれて教師画像周辺に縮退する。画像生成はこの密度の高い方向へ寄せる操作。
--教師画像x0が(訓練ツールにとっては)既知の状態で、条件付き期待値(ノイズeの期待値 ∝ -E[∇xt log pt(xt|x0) | xt] ただしpt(xt|x0)は正規分布)の推定方法をモデルに学習させることができれば代用できることが数学的に分かっている。

#shadowheader(3,結論)

-lossは小さいほど良いが、小さいだけでは不十分。
-常にloss=0を追い求めると、生成条件をわずかに変えただけで全く応用が効かないモデルになる可能性があります。
-本来の目標は「lossを下げること」ではなく、その先にある「安定して高品質な汎用モデル」を作ることです。


*loss=0にするには(参考) [#l2bf67a7]
極端な例として、loss=0にする方法は下記の通り。
これを読めば、いかにloss=0にすることが無意味なことがおわかりいただけると思います。

loss=0になる条件
-悪要素とも完全一致
各ステップで、すべての画像に対してキャプションがピクセル単位で完全一致(JPEGノイズ含む)していること。

-バッチ設定
batch_size=1、gradient_accumulation_steps=1 に固定。これ以外だと全画像のlossをゼロにする必要が出る。

-過去ステップとの統一性度外視
過去のステップや学習済みウェイトの保持を考慮せず、各画像の瞬間的なlossゼロのみを追求。

-ランダム要素の無視
timestep・Seed値・ノイズなどの揺らぎを無視し、常にloss=0を目指す。

-生成後の崩壊許容
学習後の生成プロセスで一瞬だけ完璧なら、その後の崩壊を無視。

-loss増幅機能使用不可
学習効率化のためのmin_SNR_gammaなどのloss増幅は使わず、lossを小さく抑える方向のみを重視(実質不可能)

-勾配更新の困難
勾配予測に十分な入力がなく、ウェイト更新が難航。