重みの表を8bitに落とすと、大きさは25.0%になり、誤差は0.77%で済みました。
ところが外れ値が0.1%混ざるだけで、誤差は10.00%に跳ね上がります。その外れ値だけ元の精度で残すと0.76%に戻りました。
重みの表に対して精度を落とし、誤差を計算しました。外れ値の扱いが結果を大きく左右します。
量子化で何がどれだけ変わるのかを、実際に計算して測りました。使ったのは512×768の重みの表、393,216個の数値です。
誤差は相対で見ています。元の値の散らばりに対して何パーセントずれたか、という見方です。
def quant_int(x, bits, per_row=False):
qmax = 2 ** (bits - 1) - 1
if per_row:
s = np.max(np.abs(x), axis=1, keepdims=True) / qmax
else:
s = np.max(np.abs(x)) / qmax
q = np.clip(np.round(x / s), -qmax - 1, qmax)
return q * s, q, s
精度 1個あたり 全体の大きさ 32bitとの比 平均の誤差 相対誤差 32bit(元) 32 bit 1.50 MB 100.0% 0.000000 0.00% 16bit 16 bit 0.75 MB 50.0% 0.000007 0.02% 8bit 8 bit 0.38 MB 25.0% 0.000329 0.77% 4bit 4 bit 0.19 MB 12.5% 0.005973 13.89% 2bit 2 bit 0.09 MB 6.2% 0.035783 85.69%
上の表を見てください。8bitなら大きさは25.0%になり、誤差は0.77%で済みます。
16bitから8bitへは、誤差が0.02%から0.77%です。ところが8bitから4bitへは0.77%から13.89%と、18倍になります。
2bitでは85.69%です。元の値とほぼ関係のない数字になっています。半分にするたびに同じだけ悪くなるわけではありません。
外れ値の割合 外れ値の大きさ 8bitの相対誤差 4bitの相対誤差
なし - 0.77% 13.89%
0.1% 10倍 1.81% 31.94%
0.1% 50倍 9.47% 66.47%
1.0% 10倍 4.14% 68.86%
1.0% 50倍 20.47% 99.70%
外れ値が0.1%混ざって50倍の大きさだと、8bitの誤差は0.77%から9.47%になりました。
ここで測っているのは外れ値そのものではなく、普通の値の誤差です。外れ値に合わせて目盛りが引き伸ばされ、普通の値の刻みが粗くなります。
扱い方 8bitの相対誤差 4bitの相対誤差 余分に持つ量 そのまま落とす 10.00% 67.41% 0 KB 外れ値だけ残す 0.76% 13.71% 3.1 KB 外れ値として残したのは 394個(全体の 0.10%)。
394個を元の精度で残すだけで、8bitの誤差が10.00%から0.76%になりました。外れ値がない場合の0.77%とほぼ同じです。
余分に持つ量は3.1KBです。本体が384KBなので、1%にも届きません。
0.1%を別扱いにするだけで、誤差がほぼ元に戻る。
cut the memory needed for inference by half while retaining full precision performance原文Dettmers et al.「LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale」 この内容の有効期限2027-02-18
数値を表すbit数を減らして、小さく速くします。減らしたぶんだけ元の値からずれます。
量子化は、数値を表すbit数を減らして小さくする手法です。日本語では量子化、または低精度化と呼ばれます。
3番目で情報が落ちます。刻みの間にあった値は、どちらかに寄せられます。これが前の節で測った誤差です。
いちばん分かりやすいのは大きさです。前の節でも1.50MBが0.38MBになりました。
実際の効果は論文でも報告されています。8bitでの計算を導入することで推論に必要なメモリを半分に削りながら、完全な精度での性能を保つとされています。
適用する場所は選ばれます。同じ論文は、対象として変換器の順伝播層と注意の投影層に対する8bitの行列積の手続きを示しています。
つまり全部を一律に落とすわけではありません。どの部分を落とすかは、誤差の出方を見て決めることになります。
使ったのは正規分布から作った人工の表で、実際のモデルの重みではありません。実際の重みは分布が偏っており、外れ値の出方も違います。ここで見せているのは、bit数と誤差の関係と、外れ値が普通の値を巻き込む仕組みです。埋め込みに対する同種の手法はバイナリ量子化の記事で扱っています。
We develop a procedure for Int8 matrix multiplication for feed-forward and attention projection layers in transformers原文Dettmers et al.「LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale」 この内容の有効期限2027-02-18
一律に落とすと外れ値に引きずられます。目盛りを細かく持つか、外れ値を別扱いにするかで結果が変わります。
量子化でいちばん多い失敗は、表全体に1つの目盛りを当てることです。外れ値が1つあると全体が引きずられます。
精度 目盛りの取り方 相対誤差 最大の誤差 8bit 表全体で1つ 1.09% 0.000944 8bit 行ごとに1つ 0.77% 0.000943 4bit 表全体で1つ 19.81% 0.017118 4bit 行ごとに1つ 13.89% 0.017107 精度 目盛りの持ち方 本体 目盛り 合計 32bitとの比 4bit 表全体で1つ 192.0KB 0.00KB 192.0KB 12.5% 4bit 行ごとに1つ 192.0KB 2.00KB 194.0KB 12.6%
4bitでは、行ごとに目盛りを持つと誤差が19.81%から13.89%に下がりました。
余分に持つ量は2.00KBだけです。全体に対する比は12.5%から12.6%にしか変わりません。
目盛りを細かくしても足りない場合、外れ値だけ元の精度で持つという方式があります。前の節では誤差が10.00%から0.76%になりました。
この考え方は論文でも取られています。外れ値の次元を16bitに切り分ける、精度を混ぜた分解の方式を新たに含めるとされています。
結果として1750億の規模まで、性能の劣化なしに推論を行えると報告されています。外れ値の扱いが、規模の上限を決めていた形です。
3番目が抜けやすい部分です。全体の平均を取ると、外れ値が誤差の分母も押し上げます。悪化しているのに数字が下がることがあります。
一律に落とさない。外れ値を先に見つける。
we also include a new mixed-precision decomposition scheme, which isolates the outlier feature dimensions into a 16-bit原文Dettmers et al.「LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale」 この内容の有効期限2027-02-18
同じ課題を持つ会社にとって、動いている設定は「作る時間」を買えるということです。ServiceDockは自作のワークフローやテンプレートを出品できるマーケットプレイスです。手数料や出品の流れは出品者向けページにまとまっています。
出品の仕組みを見る