pix2pixではU-Netと呼ばれるネットワークを使用しています。
本記事では、下記サイトのchainer-pix2pixを参照しながら、chainerによるU-Netの実装方法を解説します。
https://github.com/pfnet-research/chainer-pix2pix

U-Netの概要については、下記論文の図1を参照してください。
U字ネットワークの左側の各層の出力を右側の各層の入力に連結するのが特徴です。
https://arxiv.org/abs/1505.04597

chainer-pix2pixからU-Netの実装を引用します。
class Encoder(chainer.Chain):
def __init__(self, in_ch):
layers = {}
w = chainer.initializers.Normal(0.02)
layers['c0'] = L.Convolution2D(in_ch, 64, 3, 1, 1, initialW=w)
layers['c1'] = CBR(64, 128, bn=True, sample='down', activation=F.leaky_relu, dropout=False)
layers['c2'] = CBR(128, 256, bn=True, sample='down', activation=F.leaky_relu, dropout=False)
layers['c3'] = CBR(256, 512, bn=True, sample='down', activation=F.leaky_relu, dropout=False)
layers['c4'] = CBR(512, 512, bn=True, sample='down', activation=F.leaky_relu, dropout=False)
layers['c5'] = CBR(512, 512, bn=True, sample='down', activation=F.leaky_relu, dropout=False)
layers['c6'] = CBR(512, 512, bn=True, sample='down', activation=F.leaky_relu, dropout=False)
layers['c7'] = CBR(512, 512, bn=True, sample='down', activation=F.leaky_relu, dropout=False)
super(Encoder, self).__init__(**layers)

def __call__(self, x):
hs = [F.leaky_relu(self.c0(x))]
for i in range(1,8):
hs.append(self['c%d'%i](hs[i-1]))
return hs

class Decoder(chainer.Chain):
def __init__(self, out_ch):
layers = {}
w = chainer.initializers.Normal(0.02)
layers['c0'] = CBR(512, 512, bn=True, sample='up', activation=F.relu, dropout=True)
layers['c1'] = CBR(1024, 512, bn=True, sample='up', activation=F.relu, dropout=True)
layers['c2'] = CBR(1024, 512, bn=True, sample='up', activation=F.relu, dropout=True)
layers['c3'] = CBR(1024, 512, bn=True, sample='up', activation=F.relu, dropout=False)
layers['c4'] = CBR(1024, 256, bn=True, sample='up', activation=F.relu, dropout=False)
layers['c5'] = CBR(512, 128, bn=True, sample='up', activation=F.relu, dropout=False)
layers['c6'] = CBR(256, 64, bn=True, sample='up', activation=F.relu, dropout=False)
layers['c7'] = L.Convolution2D(128, out_ch, 3, 1, 1, initialW=w)
super(Decoder, self).__init__(**layers)

def __call__(self, hs):
h = self.c0(hs[-1])
for i in range(1,8):
h = F.concat([h, hs[-i-1]])
if i<7:
h = self['c%d'%i](h)
else:
h = self.c7(h)
return h
EncoderとDecoderの2つ合わせてU-Netです。
Encoderの出力をDecoderに入力することでU字ネットワークを実現します。

特徴的なのは、Decoder.__call__()内で使用されているconcatという関数です。
これはVariable変数を結合する関数であり、これを用いてEncoder(U字左側)の各層の出力をDecoder(U字右側)の各層の入力に連結しています。

concat関数は連結する次元を引数axisで指定でき、デフォルト値は(0ではなく)1です。
Variable変数は(データ数, チャンネル数, 縦, 横)の4次元であるため、上記コードのようにaxisが指定されていない場合、axis=1つまり新しいチャンネルとしてEncoderの各層の出力を連結することになります。

以上がchainerでU-Netを実現する方法です。