動機
トレンドに上がっていたOctave Convolutionがなんだかよさそうだったのですが、Keras実装だったのでChainerしか知らない僕にはちょっと不便です。なので自分で実装してみることにしました。
「間違ってるよ」とか「ここはこう書くといいよ」的なアドバイスよろしくお願いします。
実装
from chainer import Chain
import chainer.functions as F
import chainer.links as L
import numpy as np
class OctConv(Chain):
def __init__(self, in_ch, out_ch, ksize, stride, pad, alpha0=0.25, alpha1=0.25):
super().__init__()
with self.init_scope():
self.h2h = L.Convolution2D(int(in_ch * (1 - alpha0)), int(out_ch * (1 - alpha1)), ksize, stride, pad)
self.h2l = L.Convolution2D(int(in_ch * (1 - alpha0)), int(out_ch * alpha1), ksize, stride, pad)
self.l2h = L.Convolution2D(int(in_ch * alpha0), int(out_ch * (1 - alpha1)), ksize, stride, pad)
self.l2l = L.Convolution2D(int(in_ch * alpha0), int(out_ch * alpha1), ksize, stride, pad)
def __call__(self, high, low):
_, _, H, W = high.shape
h2h = self.h2h(high)
h2l = self.h2l(F.average_pooling_2d(high, ksize=2))
l2h = F.unpooling_2d(self.l2h(low), ksize=2, outsize=(H, W))
l2l = self.l2l(low)
h = h2h + l2h
l = h2l + l2l
return h, l
まだこのコードで実験していないので、後で追記します。