00001
00002
00003
00004 import chainer
00005 import chainer.functions as F
00006 import chainer.links as L
00007
00008
00009 class BottleNeckA(chainer.Chain):
00010
00011 def __init__(self, in_size, ch, out_size, stride=2):
00012 initialW = chainer.initializers.HeNormal()
00013 super(BottleNeckA, self).__init__(
00014 conv1=L.Convolution2D(
00015 in_size, ch, 1, stride, 0, nobias=True, initialW=initialW),
00016 bn1=L.BatchNormalization(ch),
00017 conv2=L.Convolution2D(
00018 ch, ch, 3, 1, 1, nobias=True, initialW=initialW),
00019 bn2=L.BatchNormalization(ch),
00020 conv3=L.Convolution2D(
00021 ch, out_size, 1, 1, 0, nobias=True, initialW=initialW),
00022 bn3=L.BatchNormalization(out_size),
00023
00024 conv4=L.Convolution2D(
00025 in_size, out_size, 1, stride, 0,
00026 nobias=True, initialW=initialW),
00027 bn4=L.BatchNormalization(out_size),
00028 )
00029
00030 def __call__(self, x):
00031 h1 = F.relu(self.bn1(self.conv1(x)))
00032 h1 = F.relu(self.bn2(self.conv2(h1)))
00033 h1 = self.bn3(self.conv3(h1))
00034 h2 = self.bn4(self.conv4(x))
00035
00036 return F.relu(h1 + h2)
00037
00038
00039 class BottleNeckB(chainer.Chain):
00040
00041 def __init__(self, in_size, ch):
00042 initialW = chainer.initializers.HeNormal()
00043 super(BottleNeckB, self).__init__(
00044 conv1=L.Convolution2D(
00045 in_size, ch, 1, 1, 0, nobias=True, initialW=initialW),
00046 bn1=L.BatchNormalization(ch),
00047 conv2=L.Convolution2D(
00048 ch, ch, 3, 1, 1, nobias=True, initialW=initialW),
00049 bn2=L.BatchNormalization(ch),
00050 conv3=L.Convolution2D(
00051 ch, in_size, 1, 1, 0, nobias=True, initialW=initialW),
00052 bn3=L.BatchNormalization(in_size),
00053 )
00054
00055 def __call__(self, x):
00056 h = F.relu(self.bn1(self.conv1(x)))
00057 h = F.relu(self.bn2(self.conv2(h)))
00058 h = self.bn3(self.conv3(h))
00059
00060 return F.relu(h + x)
00061
00062
00063 class Block(chainer.Chain):
00064
00065 def __init__(self, layer, in_size, ch, out_size, stride=2):
00066 super(Block, self).__init__()
00067 links = [('a', BottleNeckA(in_size, ch, out_size, stride))]
00068 for i in range(layer - 1):
00069 links += [('b{}'.format(i + 1), BottleNeckB(out_size, ch))]
00070
00071 for l in links:
00072 self.add_link(*l)
00073 self.forward = links
00074
00075 def __call__(self, x):
00076 for name, _ in self.forward:
00077 f = getattr(self, name)
00078 x = f(x)
00079
00080 return x
00081
00082
00083 class ResNet152(chainer.Chain):
00084
00085 insize = 224
00086
00087 def __init__(self):
00088 initialW = chainer.initializers.HeNormal()
00089 super(ResNet152, self).__init__(
00090 conv1=L.Convolution2D(
00091 3, 64, 7, 2, 3, nobias=True, initialW=initialW),
00092 bn1=L.BatchNormalization(64),
00093 res2=Block(3, 64, 64, 256, 1),
00094 res3=Block(8, 256, 128, 512),
00095 res4=Block(36, 512, 256, 1024),
00096 res5=Block(3, 1024, 512, 2048),
00097 fc=L.Linear(2048, 1000),
00098 )
00099
00100 def clear(self):
00101 self.loss = None
00102 self.accuracy = None
00103
00104 def __call__(self, x, t=None):
00105 self.clear()
00106 h = self.bn1(self.conv1(x))
00107 h = F.max_pooling_2d(F.relu(h), 3, stride=2)
00108 h = self.res2(h)
00109 h = self.res3(h)
00110 h = self.res4(h)
00111 h = self.res5(h)
00112 h = F.average_pooling_2d(h, 7, stride=1)
00113 h = self.fc(h)
00114
00115 if t is None:
00116 return h
00117
00118 self.loss = F.softmax_cross_entropy(h, t)
00119 self.accuracy = F.accuracy(h, t)
00120 return self.loss
00121
00122
00123 class ResNet152Feature(ResNet152):
00124
00125 def __call__(self, x):
00126 h = self.bn1(self.conv1(x))
00127 h = F.max_pooling_2d(F.relu(h), 3, stride=2)
00128 h = self.res2(h)
00129 h = self.res3(h)
00130 h = self.res4(h)
00131 h = self.res5(h)
00132 h = F.average_pooling_2d(h, 7, stride=1)
00133 return h