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