550 lines
20 KiB
Python
550 lines
20 KiB
Python
#!/usr/bin/env python3
|
|
|
|
# Copyright (c) 2021 CINN Authors. All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import math
|
|
import sys
|
|
|
|
import numpy as np
|
|
|
|
|
|
def pool2d(np_data, attrs, dtype="float32"):
|
|
pool_type = "max"
|
|
ceil_mode = False
|
|
exclusive = True
|
|
data_format = "NCHW"
|
|
for key in attrs.attr_store:
|
|
if key == "kernel_size":
|
|
kernel_size = attrs.get_attr("kernel_size")
|
|
elif key == "stride_size":
|
|
stride_size = attrs.get_attr("stride_size")
|
|
elif key == "padding_size":
|
|
padding_size = attrs.get_attr("padding_size")
|
|
elif key == "pool_type":
|
|
pool_type = attrs.get_attr("pool_type")
|
|
elif key == "ceil_mode":
|
|
ceil_mode = attrs.get_attr("ceil_mode")
|
|
elif key == "exclusive":
|
|
exclusive = attrs.get_attr("exclusive")
|
|
elif key == "data_format":
|
|
data_format = attrs.get_attr("data_format")
|
|
else:
|
|
raise ValueError(f"attr_store {key} is not supported")
|
|
|
|
if data_format == "NCHW":
|
|
in_n, in_c, in_h, in_w = in_shape = np_data.shape
|
|
height_axis = 2
|
|
width_axis = 3
|
|
elif data_format == "NHWC":
|
|
in_n, in_h, in_w, in_c = in_shape = np_data.shape
|
|
height_axis = 1
|
|
width_axis = 2
|
|
else:
|
|
raise ValueError(f"data_format {data_format} is not supported")
|
|
|
|
if isinstance(kernel_size, int):
|
|
k_h = k_w = kernel_size
|
|
else:
|
|
k_h, k_w = kernel_size
|
|
if isinstance(stride_size, int):
|
|
s_h = s_w = stride_size
|
|
else:
|
|
s_h, s_w = stride_size
|
|
if isinstance(padding_size, int):
|
|
pt = pl = pb = pr = padding_size
|
|
else:
|
|
pt, pl, pb, pr = padding_size
|
|
|
|
out_shape = list(in_shape)
|
|
if ceil_mode:
|
|
out_shape[height_axis] = int(
|
|
math.ceil(float(in_shape[height_axis] - k_h + pt + pb) / s_h) + 1
|
|
)
|
|
out_shape[width_axis] = int(
|
|
math.ceil(float(in_shape[width_axis] - k_w + pl + pr) / s_w) + 1
|
|
)
|
|
else:
|
|
out_shape[height_axis] = int(
|
|
math.floor(float(in_shape[height_axis] - k_h + pt + pb) / s_h) + 1
|
|
)
|
|
out_shape[width_axis] = int(
|
|
math.floor(float(in_shape[width_axis] - k_w + pl + pr) / s_w) + 1
|
|
)
|
|
|
|
fill_value = 0
|
|
if exclusive and pool_type == 'max':
|
|
fill_value = sys.float_info.min
|
|
|
|
if data_format == "NCHW":
|
|
pad_np = np.full(
|
|
shape=(in_n, in_c, in_h + pt + pb, in_w + pl + pr),
|
|
fill_value=fill_value,
|
|
dtype=dtype,
|
|
)
|
|
no_zero = (
|
|
range(in_n),
|
|
range(in_c),
|
|
range(pt, in_h + pt),
|
|
range(pl, in_w + pl),
|
|
)
|
|
else:
|
|
pad_np = np.full(
|
|
shape=(in_n, in_h + pt + pb, in_w + pl + pr, in_c),
|
|
fill_value=fill_value,
|
|
dtype=dtype,
|
|
)
|
|
no_zero = (
|
|
range(in_n),
|
|
range(pt, in_h + pt),
|
|
range(pl, in_w + pl),
|
|
range(in_c),
|
|
)
|
|
|
|
pad_np[np.ix_(*no_zero)] = np_data
|
|
ret_np = np.zeros(shape=out_shape).astype(dtype)
|
|
if pool_type == 'avg':
|
|
for i in range(out_shape[height_axis]):
|
|
for j in range(out_shape[width_axis]):
|
|
if exclusive:
|
|
pad_exclusive = pad_np.copy()
|
|
pad_exclusive[np.ix_(*no_zero)] = 1
|
|
if data_format == "NCHW":
|
|
pad_count = np.sum(
|
|
pad_exclusive[
|
|
:,
|
|
:,
|
|
i * s_h : i * s_h + k_h,
|
|
j * s_w : j * s_w + k_w,
|
|
]
|
|
== 1,
|
|
axis=(height_axis, width_axis),
|
|
)
|
|
ret_np[:, :, i, j] = np.sum(
|
|
pad_np[
|
|
:,
|
|
:,
|
|
i * s_h : i * s_h + k_h,
|
|
j * s_w : j * s_w + k_w,
|
|
],
|
|
axis=(height_axis, width_axis),
|
|
) / np.maximum(pad_count, 1)
|
|
else:
|
|
pad_count = np.sum(
|
|
pad_exclusive[
|
|
:,
|
|
i * s_h : i * s_h + k_h,
|
|
j * s_w : j * s_w + k_w,
|
|
:,
|
|
]
|
|
== 1,
|
|
axis=(height_axis, width_axis),
|
|
)
|
|
ret_np[:, i, j, :] = np.sum(
|
|
pad_np[
|
|
:,
|
|
i * s_h : i * s_h + k_h,
|
|
j * s_w : j * s_w + k_w,
|
|
:,
|
|
],
|
|
axis=(height_axis, width_axis),
|
|
) / np.maximum(pad_count, 1)
|
|
else:
|
|
if data_format == "NCHW":
|
|
window = (
|
|
pad_np[
|
|
:,
|
|
:,
|
|
i * s_h : i * s_h + k_h,
|
|
j * s_w : j * s_w + k_w,
|
|
],
|
|
)
|
|
ret_np[:, :, i, j] = np.sum(
|
|
window, axis=(height_axis, width_axis)
|
|
) / (k_h * k_w)
|
|
else:
|
|
window = (
|
|
pad_np[
|
|
:,
|
|
i * s_h : i * s_h + k_h,
|
|
j * s_w : j * s_w + k_w,
|
|
:,
|
|
],
|
|
)
|
|
ret_np[:, i, j, :] = np.sum(
|
|
window, axis=(height_axis, width_axis)
|
|
) / (k_h * k_w)
|
|
elif pool_type == 'max':
|
|
for i in range(out_shape[height_axis]):
|
|
for j in range(out_shape[width_axis]):
|
|
if data_format == "NCHW":
|
|
ret_np[:, :, i, j] = np.max(
|
|
pad_np[
|
|
:,
|
|
:,
|
|
i * s_h : i * s_h + k_h,
|
|
j * s_w : j * s_w + k_w,
|
|
],
|
|
axis=(height_axis, width_axis),
|
|
)
|
|
else:
|
|
ret_np[:, i, j, :] = np.max(
|
|
pad_np[
|
|
:,
|
|
i * s_h : i * s_h + k_h,
|
|
j * s_w : j * s_w + k_w,
|
|
:,
|
|
],
|
|
axis=(height_axis, width_axis),
|
|
)
|
|
else:
|
|
raise ValueError(f"pool type {pool_type} is not supported")
|
|
|
|
ret_np = np.maximum(ret_np, fill_value)
|
|
return ret_np, [out_shape]
|
|
|
|
|
|
def pool3d(np_data, attrs, dtype="float32"):
|
|
pool_type = "max"
|
|
ceil_mode = False
|
|
exclusive = True
|
|
data_format = "NCDHW"
|
|
for key in attrs.attr_store:
|
|
if key == "kernel_size":
|
|
kernel_size = attrs.get_attr("kernel_size")
|
|
elif key == "stride_size":
|
|
stride_size = attrs.get_attr("stride_size")
|
|
elif key == "padding_size":
|
|
padding_size = attrs.get_attr("padding_size")
|
|
elif key == "pool_type":
|
|
pool_type = attrs.get_attr("pool_type")
|
|
elif key == "ceil_mode":
|
|
ceil_mode = attrs.get_attr("ceil_mode")
|
|
elif key == "exclusive":
|
|
exclusive = attrs.get_attr("exclusive")
|
|
elif key == "data_format":
|
|
data_format = attrs.get_attr("data_format")
|
|
else:
|
|
raise ValueError(f"attr_store {key} is not supported")
|
|
|
|
if data_format == "NCDHW":
|
|
in_n, in_c, in_d, in_h, in_w = in_shape = np_data.shape
|
|
depth_axis = 2
|
|
height_axis = 3
|
|
width_axis = 4
|
|
elif data_format == "NDHWC":
|
|
in_n, in_d, in_h, in_w, in_c = in_shape = np_data.shape
|
|
depth_axis = 1
|
|
height_axis = 2
|
|
width_axis = 3
|
|
else:
|
|
raise ValueError(f"data_format {data_format} is not supported")
|
|
|
|
if isinstance(kernel_size, int):
|
|
k_d = k_h = k_w = kernel_size
|
|
else:
|
|
k_d, k_h, k_w = kernel_size
|
|
if isinstance(stride_size, int):
|
|
s_d = s_h = s_w = stride_size
|
|
else:
|
|
s_d, s_h, s_w = stride_size
|
|
if isinstance(padding_size, int):
|
|
pf = pt = pl = pk = pb = pr = padding_size
|
|
else:
|
|
pf, pt, pl, pk, pb, pr = padding_size
|
|
|
|
out_shape = list(in_shape)
|
|
if ceil_mode:
|
|
out_shape[depth_axis] = int(
|
|
math.ceil(float(in_shape[depth_axis] - k_d + pf + pk) / s_d) + 1
|
|
)
|
|
out_shape[height_axis] = int(
|
|
math.ceil(float(in_shape[height_axis] - k_h + pt + pb) / s_h) + 1
|
|
)
|
|
out_shape[width_axis] = int(
|
|
math.ceil(float(in_shape[width_axis] - k_w + pl + pr) / s_w) + 1
|
|
)
|
|
else:
|
|
out_shape[depth_axis] = int(
|
|
math.floor(float(in_shape[depth_axis] - k_d + pf + pk) / s_d) + 1
|
|
)
|
|
out_shape[height_axis] = int(
|
|
math.floor(float(in_shape[height_axis] - k_h + pt + pb) / s_h) + 1
|
|
)
|
|
out_shape[width_axis] = int(
|
|
math.floor(float(in_shape[width_axis] - k_w + pl + pr) / s_w) + 1
|
|
)
|
|
|
|
fill_value = 0
|
|
if exclusive and pool_type == 'max':
|
|
fill_value = sys.float_info.min
|
|
|
|
if data_format == "NCDHW":
|
|
pad_np = np.full(
|
|
shape=(in_n, in_c, in_d + pf + pk, in_h + pt + pb, in_w + pl + pr),
|
|
fill_value=fill_value,
|
|
dtype=dtype,
|
|
)
|
|
no_zero = (
|
|
range(in_n),
|
|
range(in_c),
|
|
range(pf, in_d + pf),
|
|
range(pt, in_h + pt),
|
|
range(pl, in_w + pl),
|
|
)
|
|
else:
|
|
pad_np = np.full(
|
|
shape=(in_n, in_d + pf + pk, in_h + pt + pb, in_w + pl + pr, in_c),
|
|
fill_value=fill_value,
|
|
dtype=dtype,
|
|
)
|
|
no_zero = (
|
|
range(in_n),
|
|
range(pf, in_d + pf),
|
|
range(pt, in_h + pt),
|
|
range(pl, in_w + pl),
|
|
range(in_c),
|
|
)
|
|
|
|
pad_np[np.ix_(*no_zero)] = np_data
|
|
ret_np = np.zeros(shape=out_shape).astype(dtype)
|
|
if pool_type == 'avg':
|
|
for i in range(out_shape[depth_axis]):
|
|
for j in range(out_shape[height_axis]):
|
|
for k in range(out_shape[width_axis]):
|
|
if exclusive:
|
|
pad_exclusive = pad_np.copy()
|
|
pad_exclusive[np.ix_(*no_zero)] = 1
|
|
if data_format == "NCDHW":
|
|
pad_count = np.sum(
|
|
pad_exclusive[
|
|
:,
|
|
:,
|
|
i * s_d : i * s_d + k_d,
|
|
j * s_h : j * s_h + k_h,
|
|
k * s_w : k * s_w + k_w,
|
|
]
|
|
== 1,
|
|
axis=(depth_axis, height_axis, width_axis),
|
|
)
|
|
ret_np[:, :, i, j, k] = np.sum(
|
|
pad_np[
|
|
:,
|
|
:,
|
|
i * s_d : i * s_d + k_d,
|
|
j * s_h : j * s_h + k_h,
|
|
k * s_w : k * s_w + k_w,
|
|
],
|
|
axis=(depth_axis, height_axis, width_axis),
|
|
) / np.maximum(pad_count, 1)
|
|
else:
|
|
pad_count = np.sum(
|
|
pad_exclusive[
|
|
:,
|
|
i * s_d : i * s_d + k_d,
|
|
j * s_h : j * s_h + k_h,
|
|
k * s_w : k * s_w + k_w,
|
|
:,
|
|
]
|
|
== 1,
|
|
axis=(depth_axis, height_axis, width_axis),
|
|
)
|
|
ret_np[:, i, j, k, :] = np.sum(
|
|
pad_np[
|
|
:,
|
|
i * s_d : i * s_d + k_d,
|
|
j * s_h : j * s_h + k_h,
|
|
k * s_w : k * s_w + k_w,
|
|
:,
|
|
],
|
|
axis=(depth_axis, height_axis, width_axis),
|
|
) / np.maximum(pad_count, 1)
|
|
else:
|
|
if data_format == "NCDHW":
|
|
ret_np[:, :, i, j, k] = np.mean(
|
|
pad_np[
|
|
:,
|
|
:,
|
|
i * s_d : i * s_d + k_d,
|
|
j * s_h : j * s_h + k_h,
|
|
k * s_w : k * s_w + k_w,
|
|
],
|
|
axis=(depth_axis, height_axis, width_axis),
|
|
)
|
|
else:
|
|
ret_np[:, i, j, k, :] = np.mean(
|
|
pad_np[
|
|
:,
|
|
i * s_d : i * s_d + k_d,
|
|
j * s_h : j * s_h + k_h,
|
|
k * s_w : k * s_w + k_w,
|
|
:,
|
|
],
|
|
axis=(depth_axis, height_axis, width_axis),
|
|
)
|
|
elif pool_type == 'max':
|
|
for i in range(out_shape[depth_axis]):
|
|
for j in range(out_shape[height_axis]):
|
|
for k in range(out_shape[width_axis]):
|
|
if data_format == "NCDHW":
|
|
ret_np[:, :, i, j, k] = np.max(
|
|
pad_np[
|
|
:,
|
|
:,
|
|
i * s_d : i * s_d + k_d,
|
|
j * s_h : j * s_h + k_h,
|
|
k * s_w : k * s_w + k_w,
|
|
],
|
|
axis=(depth_axis, height_axis, width_axis),
|
|
)
|
|
else:
|
|
ret_np[:, i, j, k, :] = np.max(
|
|
pad_np[
|
|
:,
|
|
i * s_d : i * s_d + k_d,
|
|
j * s_h : j * s_h + k_h,
|
|
k * s_w : k * s_w + k_w,
|
|
:,
|
|
],
|
|
axis=(depth_axis, height_axis, width_axis),
|
|
)
|
|
else:
|
|
raise ValueError(f"pool type {pool_type} is not supported")
|
|
|
|
ret_np = np.maximum(ret_np, fill_value)
|
|
return ret_np, [out_shape]
|
|
|
|
|
|
def pool1d(np_data, attrs, dtype="float32"):
|
|
pool_type = "max"
|
|
ceil_mode = False
|
|
exclusive = True
|
|
data_format = "NCW"
|
|
for key in attrs.attr_store:
|
|
if key == "kernel_size":
|
|
kernel_size = attrs.get_attr("kernel_size")
|
|
elif key == "stride_size":
|
|
stride_size = attrs.get_attr("stride_size")
|
|
elif key == "padding_size":
|
|
padding_size = attrs.get_attr("padding_size")
|
|
elif key == "pool_type":
|
|
pool_type = attrs.get_attr("pool_type")
|
|
elif key == "ceil_mode":
|
|
ceil_mode = attrs.get_attr("ceil_mode")
|
|
elif key == "exclusive":
|
|
exclusive = attrs.get_attr("exclusive")
|
|
elif key == "data_format":
|
|
data_format = attrs.get_attr("data_format")
|
|
else:
|
|
raise ValueError(f"attr_store {key} is not supported")
|
|
|
|
if data_format == "NCW":
|
|
in_n, in_c, in_w = in_shape = np_data.shape
|
|
width_axis = 2
|
|
elif data_format == "NWC":
|
|
in_n, in_w, in_c = in_shape = np_data.shape
|
|
width_axis = 1
|
|
else:
|
|
raise ValueError(f"data_format {data_format} is not supported")
|
|
|
|
if isinstance(kernel_size, int):
|
|
k_w = kernel_size
|
|
else:
|
|
(k_w,) = kernel_size
|
|
if isinstance(stride_size, int):
|
|
s_w = stride_size
|
|
else:
|
|
(s_w,) = stride_size
|
|
if isinstance(padding_size, int):
|
|
pl = pr = padding_size
|
|
else:
|
|
pl, pr = padding_size
|
|
|
|
out_shape = list(in_shape)
|
|
if ceil_mode:
|
|
out_shape[width_axis] = int(
|
|
math.ceil(float(in_shape[width_axis] - k_w + pl + pr) / s_w) + 1
|
|
)
|
|
else:
|
|
out_shape[width_axis] = int(
|
|
math.floor(float(in_shape[width_axis] - k_w + pl + pr) / s_w) + 1
|
|
)
|
|
|
|
fill_value = 0
|
|
if exclusive and pool_type == 'max':
|
|
fill_value = sys.float_info.min
|
|
|
|
if data_format == "NCW":
|
|
pad_np = np.full(
|
|
shape=(in_n, in_c, in_w + pl + pr),
|
|
fill_value=fill_value,
|
|
dtype=dtype,
|
|
)
|
|
no_zero = (range(in_n), range(in_c), range(pl, in_w + pl))
|
|
else:
|
|
pad_np = np.full(
|
|
shape=(in_n, in_w + pl + pr, in_c),
|
|
fill_value=fill_value,
|
|
dtype=dtype,
|
|
)
|
|
no_zero = (range(in_n), range(pl, in_w + pl), range(in_c))
|
|
|
|
pad_np[np.ix_(*no_zero)] = np_data
|
|
ret_np = np.zeros(shape=out_shape).astype(dtype)
|
|
if pool_type == 'avg':
|
|
for i in range(out_shape[width_axis]):
|
|
if exclusive:
|
|
pad_exclusive = pad_np.copy()
|
|
pad_exclusive[np.ix_(*no_zero)] = 1
|
|
if data_format == "NCW":
|
|
pad_count = np.sum(
|
|
pad_exclusive[:, :, i * s_w : i * s_w + k_w] == 1,
|
|
axis=width_axis,
|
|
)
|
|
ret_np[:, :, i] = np.sum(
|
|
pad_np[:, :, i * s_w : i * s_w + k_w], axis=width_axis
|
|
) / np.maximum(pad_count, 1)
|
|
else:
|
|
pad_count = np.sum(
|
|
pad_exclusive[:, i * s_w : i * s_w + k_w, :] == 1,
|
|
axis=width_axis,
|
|
)
|
|
ret_np[:, i, :] = np.sum(
|
|
pad_np[:, i * s_w : i * s_w + k_w, :], axis=width_axis
|
|
) / np.maximum(pad_count, 1)
|
|
else:
|
|
if data_format == "NCW":
|
|
ret_np[:, :, i] = np.mean(
|
|
pad_np[:, :, i * s_w : i * s_w + k_w], axis=width_axis
|
|
)
|
|
else:
|
|
ret_np[:, i, :] = np.mean(
|
|
pad_np[:, i * s_w : i * s_w + k_w, :], axis=width_axis
|
|
)
|
|
elif pool_type == 'max':
|
|
for k in range(out_shape[width_axis]):
|
|
if data_format == "NCW":
|
|
ret_np[:, :, k] = np.max(
|
|
pad_np[:, :, k * s_w : k * s_w + k_w], axis=width_axis
|
|
)
|
|
else:
|
|
ret_np[:, k, :] = np.max(
|
|
pad_np[:, k * s_w : k * s_w + k_w, :], axis=width_axis
|
|
)
|
|
else:
|
|
raise ValueError(f"pool type {pool_type} is not supported")
|
|
|
|
ret_np = np.maximum(ret_np, fill_value)
|
|
return ret_np, [out_shape]
|