Implement reference nGraph implementation for "Interpolate-4" with 5D tensor support in the "linear_onnx" mode (#3948)
* Commit. * Written the structure InfoForLinearONNXMode5D that contains info to perform interpolation in 'linear_onnx' mode for 5D tensors. * Started to write the method get_info_for_linear_onnx_mode5D() that returns info for calculations of 'linear_onnx' mode in 5D case. * Written the method InterpolateEvalHelper::get_info_for_linear_onnx_mode5D(). * Code style fix. * Started to write calculation of 5D case of 'linear_onnx' mode. * Written the method void InterpolateEval<T>::linear_onnx5D_func(const T* input_data, T* out). * Added dispatching of 4D/5D cases of the mode 'linear_onnx'. * Fixed code style. * Some fixes. * Code style fixes. * Now linear_onnx_func throws an exception for incorrect input rank. * Code style fix. * Started to write tests for evaluation of 'linear_onnx' mode in the 5D case. * Added first test for linear_onnx 5D. * Small fixes. * Written tests for evaluation of Interpolate-4 in linear_onnx 5D case. * Some code style fixes. * Small fix. * Corrected documentation. * Started to write generic implementation of 'linear_onnx' mode, for any ranks. * Written the draft of a generic (for all ranks) implementation of 'linear_onnx' mode. * Small fixes. * Small fix. * Small fix. * Small fix. * Code style fix. * Small fix. * Code style fix. * Some fixes. * Some fix. * Small fix. * Small fix. * Code style fix. * Added check for axes correctness into a generic implementation of the 'linear_onnx' mode. * Now 5D case of the 'linear_onnx' mode is calculated using generic function. * Code style fix. * Deleted unused variable. * Added debug prints. * Small fix. * Some fixes. * Code style fix. * Now all ranks are processed by a generic implementation in the 'linear_onnx' mode. * Deleted name of missed test. * Deleted 4D case implementation of the 'linear_onnx' mode. * Reverted change in tests. * Added needed 'const' modifiers and added a comment about the variable 'axis_idx_offset'. * Small fixes.
This commit is contained in:
1 parent
deca4fc443
commit
2c4c3a777a
4 files changed
+429
-136
No files matched your search
@@ -15,7 +15,7 @@
|
||||
* **Type**: string
|
||||
* **Default value**: none
|
||||
* **Required**: *yes*
|
||||
* **Note**: Only 2D and 4D tensors with `axes = {0, 1}` and `axes = {2, 3}` respectively are supported for `"mode" == "linear_onnx"`.
|
||||
**Note**: Only 2D, 3D, 4D, 5D tensors with `axes = {0, 1}`, `axes = {0, 1, 2}`, `axes = {2, 3}`, `axes = {2, 3, 4}` respectively are supported for `"mode" == "linear_onnx"`.
|
||||
|
||||
* *shape_calculation_mode*
|
||||
|
||||
@@ -366,7 +366,119 @@ class InterpolateCalculation:
|
||||
|
||||
return result
|
||||
|
||||
def onnx_linear_interpolation(self, input_data):
|
||||
def onnx_linear_interpolation5D(self, input_data):
|
||||
rank = len(self.input_shape)
|
||||
assert rank in [3, 5], "mode 'linear_onnx' supports only 3D or 5D tensors"
|
||||
assert set(self.axes) == {2, 3, 4} or set(self.axes) == {0, 1, 2}, \
|
||||
"mode 'linear_onnx' supports only case when axes = {2, 3, 4} or axes = {0, 1, 2}"
|
||||
|
||||
result = np.zeros(self.output_shape)
|
||||
|
||||
if rank == 3:
|
||||
reshaped_data = np.reshape(input_data, (1, 1, self.input_shape[0], self.input_shape[1], self.input_shape[2]))
|
||||
result = np.reshape(result, (1, 1, self.output_shape[0], self.output_shape[1], self.output_shape[2]))
|
||||
else:
|
||||
reshaped_data = input_data
|
||||
|
||||
input_shape = np.array(reshaped_data.shape).astype(np.int64)
|
||||
output_shape = np.array(result.shape).astype(np.int64)
|
||||
|
||||
batch_size = input_shape[0];
|
||||
num_channels = input_shape[1];
|
||||
input_depth = input_shape[2];
|
||||
input_height = input_shape[3];
|
||||
input_width = input_shape[4];
|
||||
output_depth = output_shape[2];
|
||||
output_height = output_shape[3];
|
||||
output_width = output_shape[4];
|
||||
|
||||
depth_scale = self.scales[0];
|
||||
height_scale = self.scales[1];
|
||||
width_scale = self.scales[2];
|
||||
|
||||
z_original = np.zeros(output_depth).astype(np.float)
|
||||
y_original = np.zeros(output_height).astype(np.float)
|
||||
x_original = np.zeros(output_width).astype(np.float)
|
||||
|
||||
in_z1 = np.zeros(output_depth).astype(np.int64)
|
||||
in_z2 = np.zeros(output_depth).astype(np.int64)
|
||||
in_y1 = np.zeros(output_height).astype(np.int64)
|
||||
in_y2 = np.zeros(output_height).astype(np.int64)
|
||||
in_x1 = np.zeros(output_width).astype(np.int64)
|
||||
in_x2 = np.zeros(output_width).astype(np.int64)
|
||||
|
||||
dz1 = np.zeros(output_depth).astype(np.float)
|
||||
dz2 = np.zeros(output_depth).astype(np.float)
|
||||
|
||||
dy1 = np.zeros(output_height).astype(np.float)
|
||||
dy2 = np.zeros(output_height).astype(np.float)
|
||||
|
||||
dx1 = np.zeros(output_width).astype(np.float)
|
||||
dx2 = np.zeros(output_width).astype(np.float)
|
||||
|
||||
for z in range(0, output_depth):
|
||||
in_z = self.get_original_coordinate(z, depth_scale, output_depth, input_depth)
|
||||
z_original[z] = in_z
|
||||
in_z = max(0, min(in_z, input_depth - 1))
|
||||
in_z1[z] = max(0, min(int(in_z), input_depth - 1))
|
||||
in_z2[z] = min(in_z1[z] + 1, input_depth - 1)
|
||||
dz1[z] = abs(in_z - in_z1[z])
|
||||
dz2[z] = abs(in_z - in_z2[z])
|
||||
|
||||
if in_z1[z] == in_z2[z]:
|
||||
dz1[z] = 0.5
|
||||
dz2[z] = 0.5
|
||||
|
||||
for y in range(0, output_height):
|
||||
in_y = self.get_original_coordinate(y, height_scale, output_height, input_height)
|
||||
y_original[y] = in_y
|
||||
in_y = max(0, min(in_y, input_height - 1))
|
||||
in_y1[y] = max(0, min(int(in_y), input_height - 1))
|
||||
in_y2[y] = min(in_y1[y] + 1, input_height - 1)
|
||||
dy1[y] = abs(in_y - in_y1[y])
|
||||
dy2[y] = abs(in_y - in_y2[y])
|
||||
|
||||
if in_y1[y] == in_y2[y]:
|
||||
dy1[y] = 0.5
|
||||
dy2[y] = 0.5
|
||||
|
||||
for x in range(0, output_width):
|
||||
in_x = self.get_original_coordinate(x, width_scale, output_width, input_width);
|
||||
x_original[x] = in_x
|
||||
in_x = max(0.0, min(in_x, input_width - 1));
|
||||
|
||||
in_x1[x] = min(in_x, input_width - 1);
|
||||
in_x2[x] = min(in_x1[x] + 1, input_width - 1);
|
||||
|
||||
dx1[x] = abs(in_x - in_x1[x]);
|
||||
dx2[x] = abs(in_x - in_x2[x]);
|
||||
if in_x1[x] == in_x2[x]:
|
||||
dx1[x] = 0.5
|
||||
dx2[x] = 0.5
|
||||
for n in range(0, batch_size):
|
||||
for c in range(0, num_channels):
|
||||
for z in range(0, output_depth):
|
||||
for y in range(0, output_height):
|
||||
for x in range(0, output_width):
|
||||
x111 = reshaped_data[n, c, in_z1[z], in_y1[y], in_x1[x]]
|
||||
x211 = reshaped_data[n, c, in_z1[z], in_y1[y], in_x2[x]]
|
||||
x121 = reshaped_data[n, c, in_z1[z], in_y2[y], in_x1[x]]
|
||||
x221 = reshaped_data[n, c, in_z1[z], in_y2[y], in_x2[x]]
|
||||
x112 = reshaped_data[n, c, in_z2[z], in_y1[y], in_x1[x]]
|
||||
x212 = reshaped_data[n, c, in_z2[z], in_y1[y], in_x2[x]]
|
||||
x122 = reshaped_data[n, c, in_z2[z], in_y2[y], in_x1[x]]
|
||||
x222 = reshaped_data[n, c, in_z2[z], in_y2[y], in_x2[x]]
|
||||
|
||||
temp = dx2[x] * dy2[y] * dz2[z] * x111 + dx1[x] * dy2[y] * dz2[z] * x211
|
||||
temp += dx2[x] * dy1[y] * dz2[z] * x121 + dx1[x] * dy1[y] * dz2[z] * x221
|
||||
temp += dx2[x] * dy2[y] * dz1[z] * x112 + dx1[x] * dy2[y] * dz1[z] * x212
|
||||
temp += dx2[x] * dy1[y] * dz1[z] * x122 + dx1[x] * dy1[y] * dz1[z] * x222
|
||||
|
||||
result[n, c, z, y, x] = temp
|
||||
|
||||
return np.reshape(result, self.output_shape)
|
||||
|
||||
def onnx_linear_interpolation4D(self, input_data):
|
||||
rank = len(self.input_shape)
|
||||
assert rank in [2, 4], "mode 'linear_onnx' supports only 2D or 4D tensors"
|
||||
assert set(self.axes) == {2, 3} or set(self.axes) == {0, 1}, \
|
||||
@@ -446,6 +558,15 @@ class InterpolateCalculation:
|
||||
|
||||
return np.reshape(result, self.output_shape)
|
||||
|
||||
def onnx_linear_interpolation(self, input_data):
|
||||
rank = len(self.input_shape)
|
||||
assert rank in [2, 3, 4, 5], "mode 'linear_onnx' supports only 2D, 3D, 4D, or 5D tensors"
|
||||
|
||||
if rank in [2, 4]:
|
||||
self.onnx_linear_interpolation4D(input_data)
|
||||
else:
|
||||
self.onnx_linear_interpolation5D(input_data)
|
||||
|
||||
def nearest_interpolation(self, input_data):
|
||||
result = np.zeros(self.output_shape)
|
||||
|
||||
|
||||
Reference in new issue
Block a user