[Keras] fix convert_pooling with same pad (#322)

This commit is contained in:
Yuwei Hu 2018-01-18 02:13:50 +08:00 коммит произвёл Tianqi Chen
Родитель 53361fae2a
Коммит 4bd92a4a21
1 изменённых файлов: 27 добавлений и 38 удалений

Просмотреть файл

@ -16,6 +16,14 @@ def _check_data_format(keras_layer):
raise ValueError("Keras frontend currently supports data_format = channels_last only.")
def _get_pad_pair(input1d, kernel1d, stride1d):
out1d = (input1d + stride1d - 1) // stride1d
pad = np.maximum((out1d - 1) * stride1d + kernel1d - input1d, 0)
pad_before = pad // 2
pad_after = pad - pad_before
return [pad_before, pad_after]
def _convert_activation(insym, keras_layer, _):
if isinstance(keras_layer, str):
act_type = keras_layer
@ -120,6 +128,8 @@ def _convert_convolution(insym, keras_layer, symtab):
dilation = [keras_layer.dilation_rate[0], keras_layer.dilation_rate[1]]
else:
dilation = [keras_layer.dilation_rate, keras_layer.dilation_rate]
kernel_h = (kernel_h - 1) * dilation[0] + 1
kernel_w = (kernel_w - 1) * dilation[1] + 1
stride_h, stride_w = keras_layer.strides
params = {'weight': symtab.new_const(weight),
'kernel_size': [kernel_h, kernel_w],
@ -141,14 +151,8 @@ def _convert_convolution(insym, keras_layer, symtab):
elif keras_layer.padding == 'same':
in_h = keras_layer.input.shape[1].value
in_w = keras_layer.input.shape[2].value
out_h = (in_h + stride_h - 1) // stride_h
out_w = (in_w + stride_w - 1) // stride_w
pad_h = np.maximum((out_h - 1) * stride_h + kernel_h - in_h, 0)
pad_w = np.maximum((out_w - 1) * stride_w + kernel_w - in_w, 0)
pad_t = pad_h // 2
pad_l = pad_w // 2
pad_b = pad_h - pad_t
pad_r = pad_w - pad_l
pad_t, pad_b = _get_pad_pair(in_h, kernel_h, stride_h)
pad_l, pad_r = _get_pad_pair(in_w, kernel_w, stride_w)
insym = _sym.pad(data=insym, pad_width=((0, 0), (0, 0), (pad_t, pad_b), (pad_l, pad_r)))
else:
raise TypeError("Unsupported padding type : {}".format(keras_layer.padding))
@ -187,14 +191,8 @@ def _convert_separable_convolution(insym, keras_layer, symtab):
elif keras_layer.padding == 'same':
in_h = keras_layer.input.shape[1].value
in_w = keras_layer.input.shape[2].value
out_h = (in_h + stride_h - 1) // stride_h
out_w = (in_w + stride_w - 1) // stride_w
pad_h = np.maximum((out_h - 1) * stride_h + kernel_h - in_h, 0)
pad_w = np.maximum((out_w - 1) * stride_w + kernel_w - in_w, 0)
pad_t = pad_h // 2
pad_l = pad_w // 2
pad_b = pad_h - pad_t
pad_r = pad_w - pad_l
pad_t, pad_b = _get_pad_pair(in_h, kernel_h, stride_h)
pad_l, pad_r = _get_pad_pair(in_w, kernel_w, stride_w)
insym = _sym.pad(data=insym, pad_width=(
(0, 0), (0, 0), (pad_t, pad_b), (pad_l, pad_r)))
else:
@ -242,23 +240,18 @@ def _convert_pooling(insym, keras_layer, symtab):
pool_h, pool_w = keras_layer.pool_size
stride_h, stride_w = keras_layer.strides
params = {'pool_size': [pool_h, pool_w],
'strides': [stride_h, stride_w]}
'strides': [stride_h, stride_w],
'padding': [0, 0]}
if keras_layer.padding == 'valid':
params['padding'] = [0, 0]
pass
# we insert a separate pad operator
elif keras_layer.padding == 'same':
in_h = keras_layer.input.shape[1].value
in_w = keras_layer.input.shape[2].value
out_h = (in_h + stride_h - 1) // stride_h
out_w = (in_w + stride_w - 1) // stride_w
pad_h = np.maximum((out_h - 1) * stride_h + pool_h - in_h, 0)
pad_w = np.maximum((out_w - 1) * stride_w + pool_w - in_w, 0)
pad_t = pad_h // 2
pad_l = pad_w // 2
pad_b = pad_h - pad_t
pad_r = pad_w - pad_l
params['padding'] = [pad_t, pad_l]
if pad_b > pad_t and pad_r > pad_l:
params['ceil_mode'] = True
pad_t, pad_b = _get_pad_pair(in_h, pool_h, stride_h)
pad_l, pad_r = _get_pad_pair(in_w, pool_w, stride_w)
insym = _sym.pad(data=insym, pad_width=(
(0, 0), (0, 0), (pad_t, pad_b), (pad_l, pad_r)))
else:
raise TypeError("Unsupported padding type : {}".format(keras_layer.padding))
if pool_type == 'MaxPooling2D':
@ -349,13 +342,11 @@ def _convert_concat(insym, keras_layer, _):
def _convert_reshape(insym, keras_layer, _):
shape = keras_layer.shape if hasattr(keras_layer, 'shape') else \
keras_layer.target_shape if hasattr(keras_layer, 'target_shape') else\
None
shape = keras_layer.shape if hasattr(keras_layer, 'shape') \
else keras_layer.target_shape if hasattr(keras_layer, 'target_shape') \
else None
if shape is None:
raise TypeError("No shape attribute in reshape layer: {}".format(keras_layer))
return _sym.reshape(insym, shape=shape)
@ -485,13 +476,11 @@ def from_keras(model):
else:
predecessors = []
inbound_nodes = keras_layer.inbound_nodes if hasattr(keras_layer, 'inbound_nodes') \
else keras_layer._inbound_nodes if hasattr(keras_layer, '_inbound_nodes') \
else None
else keras_layer._inbound_nodes if hasattr(keras_layer, '_inbound_nodes') \
else None
if inbound_nodes is None:
raise TypeError("Unknown layer type or unsupported Keras version : {}"
.format(keras_layer))
for node in inbound_nodes:
for pred in node.inbound_layers:
predecessors.append(pred.name)