224 lines
7.3 KiB
Python
224 lines
7.3 KiB
Python
from keras.layers import *
|
|
from keras.models import *
|
|
from keras.regularizers import *
|
|
|
|
import numpy as np
|
|
import keras
|
|
from models_bd.utils import Act, get_bn_opt, get_conv_opt, get_convdw_opt
|
|
|
|
conv_option = get_conv_opt()
|
|
conv_dw_option = get_convdw_opt()
|
|
bn_option = get_bn_opt()
|
|
act_type = 'relu'
|
|
|
|
def residual_block(data, num_filter,stride=1, dialation=1, residual=None):
|
|
|
|
# conv-bn-relu-conv-bnjavascript:void(0)
|
|
conv1 = data
|
|
conv1 = ZeroPadding2D(1)(conv1)
|
|
conv1 = Conv2D(filters=num_filter, kernel_size=3, strides=stride, **conv_option)(conv1)
|
|
bn2 = BatchNormalization(**bn_option)(conv1)
|
|
act1 = Act(act_type=act_type)(bn2)
|
|
|
|
act1 = ZeroPadding2D(1)(act1)
|
|
conv2 = Conv2D(filters=num_filter, kernel_size=3, strides=1, dilation_rate=dialation, **conv_option)(act1)
|
|
bn3 = BatchNormalization(**bn_option)(conv2)
|
|
if residual is not None:
|
|
out = Add()([bn3, residual])
|
|
else:
|
|
assert stride==1
|
|
out = Add()([bn3, data])
|
|
out = Act(act_type)(out)
|
|
return out
|
|
|
|
|
|
def root(children, filters, kernel, residual):
|
|
x = children
|
|
x = Concatenate(axis=-1)(x)
|
|
x = ZeroPadding2D((kernel-1)//2)(x)
|
|
x = Conv2D(filters, kernel, **conv_option)(x)
|
|
x = BatchNormalization(**bn_option)(x)
|
|
if residual:
|
|
x = Add()([x, children[0]])
|
|
x = Act(act_type)(x)
|
|
return x
|
|
|
|
|
|
def Tree(data, levels, block, num_filter, stride=1, root_kernel_size=1, dilation=1,
|
|
level_root=False, root_residual=False, children=None):
|
|
|
|
children = [] if children is None else children
|
|
in_channel = data._keras_shape[-1]
|
|
if stride > 1:
|
|
|
|
bottom = MaxPool2D(stride, padding='same')(data)
|
|
else:
|
|
bottom = data
|
|
|
|
if in_channel != num_filter:
|
|
residual = Conv2D(num_filter, kernel_size=1)(bottom)
|
|
residual = BatchNormalization(**bn_option)(residual)
|
|
else:
|
|
residual = bottom
|
|
|
|
if level_root:
|
|
children.append(bottom)
|
|
|
|
if levels == 1:
|
|
x1 = block(data, num_filter, stride, dilation, residual)
|
|
x2 = block(x1, num_filter, 1, dilation)
|
|
x = root([x2, x1]+children, num_filter, root_kernel_size, root_residual)
|
|
else:
|
|
x1 = Tree(data, levels-1, block, num_filter, stride=stride, root_kernel_size=root_kernel_size, dilation=dilation,
|
|
level_root=False, root_residual=root_residual, children=None)
|
|
children.append(x1)
|
|
x = Tree(x1, levels-1, block, num_filter, stride=1, root_kernel_size=root_kernel_size, dilation=dilation,
|
|
level_root=False, root_residual=root_residual, children=children)
|
|
|
|
return x
|
|
|
|
def DLA(shape, n_layer=34, block=residual_block, root_residual=False, include_top=True, n_class=1000, **kwargs):
|
|
|
|
if n_layer == 34:
|
|
levels = [1, 1, 1, 2, 2, 1]
|
|
channels = [16, 32, 64, 128, 256, 512]
|
|
if isinstance(shape,tuple) or isinstance(shape,list):
|
|
inp = Input(shape)
|
|
else:
|
|
assert keras.backend.is_keras_tensor(shape)
|
|
inp = shape
|
|
conv1 = Conv2D(channels[0], kernel_size=7, strides=1, padding="same", **conv_option)(inp)
|
|
bn1 = BatchNormalization(**bn_option)(conv1)
|
|
act1 = Act(act_type)(bn1)
|
|
|
|
conv2 = Conv2D(channels[0], kernel_size=3, strides=1, padding="same", **conv_option)(act1)
|
|
bn2 = BatchNormalization(**bn_option)(conv2)
|
|
act2 = Act(act_type)(bn2)
|
|
level0 = act2
|
|
|
|
conv3 = Conv2D(channels[1], kernel_size=3, strides=2, padding="same", **conv_option)(act2)
|
|
bn3 = BatchNormalization(**bn_option)(conv3)
|
|
act3 = Act(act_type)(bn3)
|
|
level1 = act3
|
|
|
|
level2 = Tree(level1, levels[2], block, channels[2], stride=2, root_kernel_size=1, dilation=1,
|
|
level_root=False, root_residual=root_residual, children=None)
|
|
level3 = Tree(level2, levels[3], block, channels[3], stride=2, root_kernel_size=1, dilation=1,
|
|
level_root=True, root_residual=root_residual, children=None)
|
|
level4 = Tree(level3, levels[4], block, channels[4], stride=2, root_kernel_size=1, dilation=1,
|
|
level_root=True, root_residual=root_residual, children=None)
|
|
level5 = Tree(level4, levels[5], block, channels[5], stride=2, root_kernel_size=1, dilation=1,
|
|
level_root=True, root_residual=root_residual, children=None)
|
|
if not include_top:
|
|
x = [level0, level1, level2, level3, level4, level5]
|
|
else:
|
|
x = GlobalAveragePooling2D()(level5)
|
|
x = Dense(n_class)(x)
|
|
|
|
m = Model(inp, x)
|
|
return m
|
|
|
|
def IDAUp(layers, node_kernel, num_filter, up_factors):
|
|
"""
|
|
aggregate all layers and make nodes
|
|
first layer should have smaller stride
|
|
:param layers:
|
|
:param node_kernel:
|
|
:param num_filter:
|
|
:param up_factors:
|
|
:return:
|
|
"""
|
|
# every layer do a upsample and projection except first layer
|
|
|
|
for i, l in enumerate(layers):
|
|
in_channel = l._keras_shape[-1]
|
|
x = l
|
|
|
|
if in_channel != num_filter:
|
|
x = Conv2D(num_filter, kernel_size=1, **conv_option)(x)
|
|
x = BatchNormalization(**bn_option)(x)
|
|
x = Act(act_type)(x)
|
|
|
|
if up_factors[i] != 1:
|
|
x = UpSampling2D()(x)
|
|
x = ZeroPadding2D((up_factors[i]*2+1)//2)(x)
|
|
x = DepthwiseConv2D(kernel_size=up_factors[i]*2+1)(x)
|
|
|
|
# replace old layer with new one
|
|
layers[i] = x
|
|
# all layer should have same size(h,w,c)
|
|
|
|
x = layers[0]
|
|
y = []
|
|
# then aggregate all layer and make nodes
|
|
for i in range(1,len(layers)):
|
|
# every step aggregate two layer and make a node x
|
|
x = Concatenate(axis=-1)([x, layers[i]])
|
|
x = ZeroPadding2D(node_kernel//2)(x)
|
|
x = Conv2D(num_filter, kernel_size=node_kernel,**conv_option)(x)
|
|
x = BatchNormalization(**bn_option)(x)
|
|
x = Act(act_type)(x)
|
|
y.append(x)
|
|
return x, y
|
|
|
|
|
|
def DLA_up(layers, channels, scales=(1,2,4,8,16)):
|
|
"""
|
|
deep aggregation
|
|
scales update
|
|
step1:
|
|
8, 16 -> 8, 8
|
|
step2:
|
|
4, 8, 8 -> 4, 4, 4
|
|
step3:
|
|
2, 4, 4, 4 -> 2 2 2 2
|
|
step4:
|
|
1 2 2 2 2 -> 1 1 1 1 1
|
|
:param layers: output from backbone model
|
|
:param channels: output channel for each step
|
|
:param scales: stride of each layers
|
|
:return:
|
|
"""
|
|
layers = list(layers)
|
|
assert (len(layers)==len(scales) and len(layers)==len(channels))
|
|
scales = np.asarray(scales, 'int')
|
|
assert (len(layers) > 1)
|
|
x = layers[-1]
|
|
for i in range(len(layers) - 1):
|
|
# get last several layer to aggregation from 2 to all
|
|
j = -i-2
|
|
x, y = IDAUp(layers[j:], node_kernel=3, num_filter=channels[j], up_factors=scales[j:]//scales[j])
|
|
# update layers with new node update scale with new scale
|
|
layers[j+1:] = y
|
|
scales[j+1:] = scales[j]
|
|
return x
|
|
|
|
|
|
def DLA_seg(layers, down_ratio=4,mode=0):
|
|
|
|
assert (down_ratio in [2,4,8,16])
|
|
first_level = int(np.log2(down_ratio))
|
|
|
|
# print layers
|
|
channels = [item._keras_shape[-1] for item in layers]
|
|
scales = [2**i for i in range(len(channels[first_level:]))]
|
|
|
|
x = DLA_up(layers[first_level:], channels[first_level:], scales)
|
|
|
|
return x
|
|
|
|
|
|
if __name__ == '__main__':
|
|
m = DLA((512,512,3))
|
|
m.summary()
|
|
|
|
x = np.random.random((1, 512, 512, 3))
|
|
m.predict(x)
|
|
|
|
import datetime
|
|
t1_1 = datetime.datetime.now()
|
|
for _ in range(100):
|
|
m.predict(x)
|
|
t2_1 = datetime.datetime.now()
|
|
print("Single GPU computation time: " + str(t2_1 - t1_1))
|
|
# model.save('dla34.hdf5') |