深層学習のアーキテクチャ図を見ると、ブロックをぐるっと飛び越えて先の地点に合流する矢印がほぼ必ず描かれています。ResNet でも、Transformer でも、U-Net でも、拡散モデルでも、この「飛び越える線」は共通して現れます。これが残差接続(residual connection)、別名スキップ接続(skip connection)です。
やっていることは驚くほど単純で、ある層の入力 $x$ を、その層の出力にそのまま足し算するだけです。式で書けば $H(x) = F(x) + x$。ただこれだけの一本の足し算が、2015年以前には誰も安定して学習できなかった100層超のネットワークを、あっさり学習可能にしてしまいました。

上の図が残差ブロックの全体像です。入力 $x$ は2つの経路に分かれます。ひとつは重み層 $F(x)$ を通る道、もうひとつは何もせずまっすぐ足し算ノードへ向かう青い道(スキップ接続)です。最後にこの2つを足して $H(x) = F(x) + x$ を出力します。この記事のゴールは、「なぜこの足し算がそんなに効くのか」を、ひとつの説明ではなく4つの異なる視点から立体的に理解することです。
なぜこれを学ぶ価値があるのでしょうか。第一に、残差接続は現代のほぼ全ての大規模モデルの土台だからです。あなたが使う画像認識モデルも大規模言語モデルも、内部では残差接続が勾配を運んでいます。第二に、「深くしたのに性能が上がらない」という現象は今も新しいアーキテクチャを作るたびに顔を出す普遍的な壁で、その処方箋の原型がここにあるからです。
本記事の内容
- 「深くすると逆に悪くなる」劣化問題という出発点
- 残差接続を理解する4つの視点(恒等写像・勾配・損失地形・アンサンブル)
- Python で「残差あり/なし」を実際に学習させ、数値で効果を確かめる
前提知識
この記事は残差接続そのものを直感から理解することに集中します。次の記事を先に読むと、背景がより深くわかります。
なお、CNN(ResNet)に特化した数理は ResNetとスキップ接続 — なぜ深いネットワークが学習できるのか で、Transformer での役割は 残差接続とTransformerの学習安定性 で扱っています。本記事はそれらを横断し、「なぜ効くのか」の直感を図で束ねる入門という位置づけです。
出発点:深くすると「逆に」悪くなる劣化問題
まず、残差接続が生まれる前に何が問題だったのかを押さえましょう。深層学習の素朴な期待は「層を増やせば表現力が上がり、性能も上がる」というものです。ところが2015年以前、20層を超えたあたりから奇妙なことが起きました。深いネットワークのほうが、浅いネットワークより訓練誤差すら高くなるのです。
これは過学習とは違います。過学習なら訓練誤差は下がりきってテスト誤差だけ悪化しますが、ここでは訓練データにすら当てはめられない。つまり最適化そのものが失敗している。この現象を劣化問題(degradation problem)と呼びます。

図は劣化問題の典型的な傾向です。残差接続なしの素朴なネットワーク(赤・以下「プレーン」と呼びます)は、ある深さを超えると訓練誤差がむしろ上昇に転じます。深くしたのに浅いモデルより悪い、という直感に反する挙動です。一方、残差接続あり(青)は深くするほど誤差が下がり続けます。
ここで論理的におかしな点に気づきます。もし深いネットワークの「追加した層」が全部恒等写像(入力をそのまま出力する、つまり何もしない層)になれるなら、深いネットワークは浅いネットワークと最低でも同じ性能を出せるはずです。追加層が何もしなければ、浅いモデルを完全に再現できるからです。それができないということは、「何もしない」という一見簡単な写像すら、素朴なネットワークには学習が難しいということ。この一点が残差接続のアイデアの核心になります。次の節から、なぜ足し算ひとつでこの壁が崩れるのかを見ていきます。
視点1:恒等写像を学ぶのが「ただ同然」になる
残差接続の最初の、そして最も本質的なご利益は、恒等写像を作るのが極端に簡単になることです。
素朴なネットワークで層に「何もするな($H(x)=x$)」と要求すると、その層は重み行列 $W$ を使って $Wx \approx x$ を再現しなければなりません。非線形の活性化関数を挟みながら恒等変換を精密に組み立てるのは、実は難しい注文です。重みの初期値はゼロ付近に置かれるので、初期状態は恒等どころか信号を潰す方向に働きがちです。
残差接続はこの要求を根本から書き換えます。$H(x) = F(x) + x$ と定義したので、$H(x) = x$ を実現したければ、単に $F(x) = 0$ にすればよい。そして重みをゼロに近づけて $F(x) \to 0$ にするのは、重みの正則化がもともと向かう方向であり、最適化にとってごく自然で簡単な操作です。

図の左(プレーン)では、恒等写像を作るために重み層が「$Wx \approx x$」という非自明な解を探し当てる必要があります。右(残差)では、スキップ接続が $x$ を運んでくれるので、重み層は $F(x)=0$、つまり「何も足さない」だけで恒等写像が完成します。
視点を変えると、残差接続は学習の基準点をゼロから恒等写像へずらす操作だと言えます。プレーンネットは「白紙」から目標の写像を組み立てますが、残差ネットは「まず入力をそのまま通す」という賢い初期地点から出発し、そこに必要な差分 $F(x)$ だけを付け足します。多くの層で本当に必要な変換は入力からの小さなズレなので、この差分(=残差)を学ぶほうがずっと楽なのです。「$F$ は残った差を担当する」——これが残差(residual)という名前の由来です。
恒等写像が簡単に作れるだけでも劣化問題は説明できます。しかし残差接続の威力はこれにとどまりません。次は、学習の心臓部である「勾配の流れ」から見てみましょう。
視点2:勾配のハイウェイ — 逆伝播で「1」が素通りする
深いネットワークが学習できないもうひとつの理由が勾配消失です。誤差逆伝播では、出力側の勾配を各層のヤコビアン(微分)で次々と掛け算しながら入力側へ伝えます。各層の微分が1より小さいと、掛け算を繰り返すうちに勾配は指数的に小さくなり、入力側の層にはほとんど何も届かなくなります。届かなければ重みは更新されず、その層は学習できません。
残差接続はここに掛け算ではなく足し算を持ち込みます。$x_{\ell+1} = F(x_\ell) + x_\ell$ という関係を、入力 $x_\ell$ で微分してみましょう。
$$ \frac{\partial x_{\ell+1}}{\partial x_\ell} = \frac{\partial F(x_\ell)}{\partial x_\ell} + 1 $$
右辺に注目してください。第2項の $+1$ は、スキップ接続 $x$ をそのまま足したことから生まれた項です。この $1$ があるおかげで、勾配を出力層 $L$ から層 $\ell$ まで逆伝播させると、連鎖律は次の形になります。
$$ \frac{\partial \mathcal{L}}{\partial x_\ell} = \frac{\partial \mathcal{L}}{\partial x_L} \prod_{k=\ell}^{L-1}\left(1 + \frac{\partial F(x_k)}{\partial x_k}\right) $$
この積を展開すると、すべての括弧から $1$ だけを選んだ項、すなわち $\dfrac{\partial \mathcal{L}}{\partial x_L}\cdot 1$ が必ず含まれます。これは出力層の勾配が一切減衰せずに層 $\ell$ へ直接届く経路です。重み層 $F$ の微分がどれだけ小さくても、この「1の道」は生き残ります。

図のように、残差接続は各ブロックの下に「勾配のハイウェイ」を敷きます。上の重み経路は減衰しやすくても、下のスキップ経路は $\times 1$ で勾配をそのまま次へ渡す。おかげで最も入力に近い層まで、しっかりした大きさの勾配が届きます。
これは机上の話ではありません。実際に測ってみましょう。20層のネットワークを初期化した直後、各層の重みが受け取る勾配のノルムを、プレーンと残差ありで比較します。

縦軸は対数目盛です。プレーン(赤)は出力側(右)では勾配がそれなりにありますが、入力側(左)へ向かうにつれ急降下し、最も入力に近い層では約 $1.5\times10^{-6}$ まで消えています。出力側の約 $3.9\times10^{-3}$ と比べても3桁以上小さく、この層はほとんど学習できません。一方、残差あり(青)は全20層でノルムが $1.6$〜$2.4$ の範囲に収まり、入力側でも出力側でもほぼ同じ大きさを保っています。$+1$ の項が勾配消失を封じている様子が、そのまま数値に出ています。
勾配が全層に届くなら、当然ながら学習も速く深く進むはずです。それを次に確かめます。
学習させて確かめる — 残差あり/なしの実測
ここで一度、コードを動かして残差接続の効果を体感しましょう。1次元の非線形関数 $y=\sin(2x)\,e^{-0.2x^2}+0.1\cos(5x)$ を、20層の深い全結合ネットワークで近似します。同じ構造・同じ初期化で、残差接続の有無だけを切り替えます。
import torch
import torch.nn as nn
import numpy as np
class Block(nn.Module):
def __init__(self, d, residual):
super().__init__()
self.fc = nn.Linear(d, d)
self.act = nn.Tanh()
self.residual = residual
def forward(self, x):
out = self.act(self.fc(x))
return out + x if self.residual else out # ← ここが残差接続
class DeepNet(nn.Module):
def __init__(self, d, depth, residual):
super().__init__()
self.inp = nn.Linear(1, d)
self.blocks = nn.ModuleList([Block(d, residual) for _ in range(depth)])
self.out = nn.Linear(d, 1)
def forward(self, x):
h = self.inp(x)
for b in self.blocks:
h = b(h)
return self.out(h)
def make_data(n=512):
g = torch.Generator().manual_seed(0)
x = torch.rand(n, 1, generator=g) * 2*np.pi - np.pi
y = torch.sin(2*x) * torch.exp(-0.2*x**2) + 0.1*torch.cos(5*x)
return x, y
残差接続の実装は return out + x のたった一行です。この一行があるかないかだけを比較します。次に学習ループを回して、訓練損失の推移を記録します。
def train_net(residual, depth=20, d=32, epochs=400, lr=1e-3, seed=0):
torch.manual_seed(seed)
net = DeepNet(d, depth, residual)
x, y = make_data()
opt = torch.optim.Adam(net.parameters(), lr=lr)
lossf = nn.MSELoss()
hist = []
for _ in range(epochs):
opt.zero_grad()
loss = lossf(net(x), y)
loss.backward()
opt.step()
hist.append(loss.item())
return np.array(hist)
hist_plain = train_net(False)
hist_resid = train_net(True)
print(f"プレーン 最終損失: {hist_plain[-1]:.5f}")
print(f"残差あり 最終損失: {hist_resid[-1]:.5f}")
実行すると、プレーンの最終損失は約 0.00538、残差ありは約 0.00015 になります。同じ深さ・同じ初期化・同じ学習率で、残差接続を入れただけで最終損失が約37倍改善しました。学習曲線を描くと差はさらに鮮明です。

対数目盛の学習曲線から2つのことが読み取れます。第一に、残差あり(青)は最初の数十エポックで一気に損失を下げ、立ち上がりが圧倒的に速い。第二に、プレーン(赤)は早い段階で下げ止まり、その後ほとんど改善しません。勾配が入力側に届かないので、ネットワークの前半が働かず、実効的に浅いモデルとして頭打ちになっているのです。
では深さを変えるとどうなるでしょうか。劣化問題の核心である「深いほど悪くなるか」を直接調べます。
depths = [4, 8, 12, 20, 30, 40]
for dep in depths:
lp = train_net(False, depth=dep, epochs=300)[-1]
lr = train_net(True, depth=dep, epochs=300)[-1]
print(f"深さ{dep:2d} プレーン={lp:.4f} 残差あり={lr:.4f}")

結果は劣化問題の教科書的な再現になりました。プレーン(赤)は深さ20あたりまでは何とか学習できますが、深さ30・40では損失が約 0.22 に跳ね上がり、浅いモデルよりはるかに悪化します。まさに「深くすると逆に悪くなる」現象です。対して残差あり(青)は、深くするほど損失が下がり続け、深さ40では損失がほぼ 0 に達します。足し算一本の有無が、深さのスケーラビリティを決定的に分けています。
数値で効果を確認できたところで、残りの2つの視点に進みましょう。ここからは「なぜ最適化が楽になるのか」をより深く掘り下げます。
視点3:損失地形をなめらかにする
勾配が届くだけでは、良い解にたどり着けるとは限りません。最適化の難しさは損失地形(loss landscape)の形にも左右されます。損失地形とは、パラメータを座標、損失を高さとした「山と谷の風景」のことです。地形が急峻でギザギザだと、勾配降下は谷から谷へ跳ね回って迷子になります。逆に滑らかで広い谷なら、素直に底へ滑り落ちられます。
残差接続には、この損失地形を平滑化する効果があることが知られています(Li ら 2018, “Visualizing the Loss Landscape of Neural Nets”)。直感的には、恒等写像という「安全な基準解」の周りに広い平坦な盆地ができるためです。実際に、学習後のネットワークのパラメータをランダムな方向へ少しずつ動かし、損失がどう変化するかの断面を描いてみます。

横軸は最小点からランダム方向にどれだけ動いたか、縦軸はそのときの損失です。プレーン(赤)は最小点から少し動いただけで損失が急激に立ち上がる、切り立った谷になっています。残差あり(青)は、同じだけ動いても損失の上昇がゆるやかで、底が広くなだらかです。谷が広いということは、多少ずれた場所からでも勾配降下が安定して底へ向かえるということ。これが残差ネットの学習が安定し、良い解に到達しやすい理由のひとつです。
損失地形の視点は「最適化のしやすさ」を説明しました。最後に、まったく毛色の違う、しかし残差ネットの汎化性能を説明する視点を紹介します。
視点4:暗黙のアンサンブル — 指数的に多い経路の集合
残差ネットには、驚くほど美しい別の見方があります。Veit ら(2016, “Residual Networks Behave Like Ensembles of Relatively Shallow Networks”)が示したのは、残差ネットは実質的に膨大な数の浅いネットワークの寄せ集め(アンサンブル)として振る舞うという事実です。
なぜそう言えるのか。各残差ブロックは $x_{\ell+1} = x_\ell + F(x_\ell)$、つまり「スキップ経路($x_\ell$)」と「重み経路($F$)」の和です。この和を全ブロックにわたって展開すると、各ブロックで「$F$ を通るか/スキップするか」の2択が生まれます。$n$ 個のブロックがあれば、その組み合わせは $2^n$ 通り。残差ネットの出力は、この $2^n$ 通りの経路すべての和として書けるのです。

図は3ブロックの場合の展開(unraveled view)です。入力から出力まで $2^3 = 8$ 通りの経路があり、それぞれが「どのブロックで $F$ を通ったか」の違いを表します。すべて $F$ をスキップする経路(・・・)は最短、すべて通る経路(FFF)は最長です。残差ネットは、これら長短さまざまな経路の出力を暗黙のうちに足し合わせている——つまり、深さの異なる無数のサブネットワークのアンサンブルだ、という見方です。
この経路の「長さ(通った重み層の数)」がどう分布するかを見ると、さらに面白いことがわかります。$n$ ブロックのうち $k$ 個で $F$ を通る経路の数は $\binom{n}{k}$ 通りなので、経路長は二項分布に従います。

20ブロックの残差ネットでは、経路長の分布は平均10のあたりに鋭く集中します。つまり、名目上は20層でも、勾配に実際に寄与するのは主として中程度の長さ(実効的に浅め)の経路なのです。Veit らは、長い経路は勾配がやはり小さく、学習に効いているのは相対的に浅い経路群だと示しました。これは「残差ネットが深くても勾配消失に悩まされにくい」ことの、経路数という別角度からの説明になっています。アンサンブルであることは汎化性能の高さにもつながり、実際に一部のブロックを取り除いても性能が急に崩れない頑健さ(各経路が独立に寄与するため)としても現れます。
4つの視点を見てきました。最後に、これらを踏まえた実務上の注意点を補足しておきます。
補足:順伝播の信号と、正規化をどこに置くか
勾配だけでなく順伝播の信号も、残差接続は保ちます。プレーンネットでは活性化関数を通るたびに信号が縮み、深い層では分散が潰れてしまいます。一方、残差ネットは各層で $x$ を足し戻すので、信号の大きさが層をまたいで維持されます。

実測すると、プレーン(赤)は層を経るごとに活性の分散が単調に減り、20層目では約 0.011 まで縮みます。残差あり(青)は層ごとに寄与が積み上がり、最終層で分散が約 7.7 と、むしろ増える傾向すら見せます。信号が生き残るからこそ、深い層が意味のある変換を担えるのです。
もうひとつ実務で重要なのが、残差接続と正規化層(Batch Norm / Layer Norm)の配置です。加算の後に正規化を置く Post-Norm と、重み層の前に置く Pre-Norm では、学習の安定性が変わります。

Post-Norm(左、初代 Transformer や元祖 ResNet の一部)は加算の後に正規化が入るため、スキップ経路が正規化に「洗われて」しまい、非常に深くすると勾配の素通りが弱まります。Pre-Norm(右、現代の大規模モデルの主流)は正規化を重み層の前に移し、スキップ経路には何も挟みません。すると視点2で見た「1の道」が最上流まで完全に保たれ、100層超でも安定して学習できます。GPT 系をはじめ現代の巨大モデルが Pre-Norm を採用するのは、この理由によります。配置の詳しい比較は 残差接続とTransformerの学習安定性 を参照してください。
まとめ
残差接続 $H(x) = F(x) + x$ という一本の足し算が、なぜ深いネットワークを学習可能にするのか。本記事では4つの視点から見てきました。
- 視点1・恒等写像:$F(x)=0$ にするだけで「何もしない層」が作れる。学習の基準点が白紙から恒等写像に移り、必要な差分(残差)だけを学べばよくなる
- 視点2・勾配のハイウェイ:逆伝播に $+1$ の項が現れ、勾配が減衰せず全層に届く。実測でも入力側の勾配が $1.5\times10^{-6}$(プレーン)→ $2.4$(残差)と桁違いに改善した
- 視点3・損失地形:恒等写像の周りに広くなめらかな谷ができ、最適化が安定する
- 視点4・暗黙のアンサンブル:$n$ ブロックで $2^n$ 通りの経路が生まれ、深さの異なる浅いネットワークの集合として振る舞う。これが頑健さと汎化を生む
そして実測では、残差接続を入れただけで20層ネットの最終損失が約37倍改善し、深さ40でもプレーンのように劣化しませんでした。たった一本の足し算が、これだけの効果を持つのです。
残差接続は特定のアーキテクチャの小技ではなく、深いモデルを成立させる普遍的な設計原理です。次のステップとして、以下の記事も参考にしてください。