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')