2026年10月14日(UTC)付のarXiv新着告知に、4bit通信と誤差補償を扱う論文Echoが載った。通信する値を小さくすれば軽くなる。ただ、0.02という更新を10回渡しても、受け手の合計が0のままになる条件がある。
自分は今日、この丸めだけをPythonで切り出してて、残差を戻す前後の配列を見比べた。10個とも0だった配列に、1が2個現れる。地味だけど、低精度化の確認では単発の誤差より先に見たい挙動なんだよね。
ここで確かめるのは、一定の刻み幅で丸める小さな実験。Echoの通信アルゴリズムの再現や、GPUでの速度・学習精度の検証は含まない。
Pythonで0.02を10回丸める
刻み幅を0.1に固定し、整数の符号を含めた4bitの範囲から、対称な15段階の-7〜7を使う。復元できる値は-0.7〜0.7だ。残る1通りは使わない。整数コードを返すだけで、実際に4bitずつバイト列へ詰める処理も省いた。
0.02を0.1単位に直すと0.2。これを四捨五入して整数にすると0になる。10回分を先に足せば0.2が残るのに、各回で丸めてから足すと全部消える。
Python 3.14.8で実行した。標準ライブラリだけで動く。Fractionを使うのは、2進浮動小数点の表現誤差を混ぜずに丸めの影響を見るためだ。roundのちょうど中間の値は偶数側へ丸められる。
from fractions import Fraction as F
STEP = F(1, 10)
def run(updates, feedback):
codes = []
residual = F(0)
for x in updates:
u = x + residual if feedback else x
q = max(-7, min(7, round(u / STEP)))
codes.append(q)
residual = u - q * STEP if feedback else F(0)
return codes, sum(codes) * STEP, residual
updates = [F(1, 50)] * 10
for enabled in (False, True):
codes, total, residual = run(updates, enabled)
print(enabled, codes, total, residual)
codes, total, residual = run(updates, True)
assert total + residual == sum(updates)
assert (total, residual) == (F(1, 5), F(0))
# 表現範囲を超える入力も確認する
_, total, residual = run([F(4, 5)] * 3, True)
print("clipped:", total, residual)
assert (total, residual) == (F(21, 10), F(3, 10))
出力は次のとおり。末尾の2列は、復元した値の合計と、最後に手元へ残った誤差だ。
False [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 0 0
True [0, 0, 1, 0, 0, 0, 0, 1, 0, 0] 1/5 0
clipped: 21/10 3/10
残差を次の入力へ戻すと、何が残るか
feedback=Trueでは、その回に復元できなかった分をresidualに保存する。次回は新しい入力へ足してから丸める。
3回目には、入力0.02と持ち越した0.04が合わさって0.06になる。コード1、つまり0.1を渡し、残差には-0.04を残す。多めに渡した分も、次回の丸めへ反映される。
残差には負の値も入る。
初期残差が0なら、各回のresidual = u - q * STEPを足し合わせると、中間の残差が打ち消し合う。結果として「入力の累計 = 復元値の累計 + 最後の残差」が保たれる。コードの最初のassertで見ているのは、この関係だ。今回は10回目の残差が0になったので、復元値の累計も元の0.2と一致した。
Fractionの出力が1/5なのも、ログを読むときにはちょっと面倒だ。今回は小数表示に直す処理を入れず、計算をそのまま追える形にした。
ただし、残差を持てば何でも解決するわけではない。
最後の入力は0.8を3回。上限の0.7へ毎回切り詰めるため、入力合計2.4に対して渡せたのは2.1、残差は0.3だった。入力が上限を超え続けると、持ち越す量が増える。同じ関係式が成り立っていても、受け手へ届いていない値は残る。
低精度化で自分が確認したい値
量子化の試験には、小さい同符号の入力を繰り返す列と、上限を超える列を入れておきたい。前者で更新が消える条件、後者で残差がたまる条件を分けて確認できる。この実験から学習精度の維持までは言えず、更新が届くタイミングも変わる。実装を速くする段階でも、送った値の累計と残差を一緒に追える検査は手元に残すつもりだ。
