Daniel Konegen / MNIST_example

Dependencies:   mbed-os

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pooling.h Source File

pooling.h

00001 /* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
00002 
00003 Licensed under the Apache License, Version 2.0 (the "License");
00004 you may not use this file except in compliance with the License.
00005 You may obtain a copy of the License at
00006 
00007     http://www.apache.org/licenses/LICENSE-2.0
00008 
00009 Unless required by applicable law or agreed to in writing, software
00010 distributed under the License is distributed on an "AS IS" BASIS,
00011 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 See the License for the specific language governing permissions and
00013 limitations under the License.
00014 ==============================================================================*/
00015 #ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_POOLING_H_
00016 #define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_POOLING_H_
00017 
00018 #include <limits>
00019 #include "tensorflow/lite/kernels/internal/common.h"
00020 
00021 namespace tflite {
00022 namespace reference_integer_ops {
00023 
00024 inline void AveragePool(const PoolParams& params,
00025                         const RuntimeShape& input_shape, const int8* input_data,
00026                         const RuntimeShape& output_shape, int8* output_data) {
00027   TFLITE_DCHECK_LE(params.quantized_activation_min,
00028                    params.quantized_activation_max);
00029   TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4);
00030   TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4);
00031   const int batches = MatchingDim(input_shape, 0, output_shape, 0);
00032   const int depth = MatchingDim(input_shape, 3, output_shape, 3);
00033   const int input_height = input_shape.Dims(1);
00034   const int input_width = input_shape.Dims(2);
00035   const int output_height = output_shape.Dims(1);
00036   const int output_width = output_shape.Dims(2);
00037   const int stride_height = params.stride_height;
00038   const int stride_width = params.stride_width;
00039   for (int batch = 0; batch < batches; ++batch) {
00040     for (int out_y = 0; out_y < output_height; ++out_y) {
00041       for (int out_x = 0; out_x < output_width; ++out_x) {
00042         for (int channel = 0; channel < depth; ++channel) {
00043           const int in_x_origin =
00044               (out_x * stride_width) - params.padding_values.width;
00045           const int in_y_origin =
00046               (out_y * stride_height) - params.padding_values.height;
00047           // Compute the boundaries of the filter region clamped so as to
00048           // ensure that the filter window fits in the input array.
00049           const int filter_x_start = std::max(0, -in_x_origin);
00050           const int filter_x_end =
00051               std::min(params.filter_width, input_width - in_x_origin);
00052           const int filter_y_start = std::max(0, -in_y_origin);
00053           const int filter_y_end =
00054               std::min(params.filter_height, input_height - in_y_origin);
00055           int32 acc = 0;
00056           int filter_count = 0;
00057           for (int filter_y = filter_y_start; filter_y < filter_y_end;
00058                ++filter_y) {
00059             for (int filter_x = filter_x_start; filter_x < filter_x_end;
00060                  ++filter_x) {
00061               const int in_x = in_x_origin + filter_x;
00062               const int in_y = in_y_origin + filter_y;
00063               acc +=
00064                   input_data[Offset(input_shape, batch, in_y, in_x, channel)];
00065               filter_count++;
00066             }
00067           }
00068           // Round to the closest integer value.
00069           acc = acc > 0 ? (acc + filter_count / 2) / filter_count
00070                         : (acc - filter_count / 2) / filter_count;
00071           acc = std::max(acc, params.quantized_activation_min);
00072           acc = std::min(acc, params.quantized_activation_max);
00073           output_data[Offset(output_shape, batch, out_y, out_x, channel)] =
00074               static_cast<int8>(acc);
00075         }
00076       }
00077     }
00078   }
00079 }
00080 
00081 inline void MaxPool(const PoolParams& params, const RuntimeShape& input_shape,
00082                     const int8* input_data, const RuntimeShape& output_shape,
00083                     int8* output_data) {
00084   TFLITE_DCHECK_LE(params.quantized_activation_min,
00085                    params.quantized_activation_max);
00086   TFLITE_DCHECK_GE(params.quantized_activation_min,
00087                    std::numeric_limits<int8_t>::min());
00088   TFLITE_DCHECK_LE(params.quantized_activation_max,
00089                    std::numeric_limits<int8_t>::max());
00090   TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4);
00091   TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4);
00092   const int batches = MatchingDim(input_shape, 0, output_shape, 0);
00093   const int depth = MatchingDim(input_shape, 3, output_shape, 3);
00094   const int input_height = input_shape.Dims(1);
00095   const int input_width = input_shape.Dims(2);
00096   const int output_height = output_shape.Dims(1);
00097   const int output_width = output_shape.Dims(2);
00098   const int stride_height = params.stride_height;
00099   const int stride_width = params.stride_width;
00100   for (int batch = 0; batch < batches; ++batch) {
00101     for (int out_y = 0; out_y < output_height; ++out_y) {
00102       for (int out_x = 0; out_x < output_width; ++out_x) {
00103         for (int channel = 0; channel < depth; ++channel) {
00104           const int in_x_origin =
00105               (out_x * stride_width) - params.padding_values.width;
00106           const int in_y_origin =
00107               (out_y * stride_height) - params.padding_values.height;
00108           // Compute the boundaries of the filter region clamped so as to
00109           // ensure that the filter window fits in the input array.
00110           const int filter_x_start = std::max(0, -in_x_origin);
00111           const int filter_x_end =
00112               std::min(params.filter_width, input_width - in_x_origin);
00113           const int filter_y_start = std::max(0, -in_y_origin);
00114           const int filter_y_end =
00115               std::min(params.filter_height, input_height - in_y_origin);
00116           int8_t max = std::numeric_limits<int8_t>::lowest();
00117           for (int filter_y = filter_y_start; filter_y < filter_y_end;
00118                ++filter_y) {
00119             for (int filter_x = filter_x_start; filter_x < filter_x_end;
00120                  ++filter_x) {
00121               const int in_x = in_x_origin + filter_x;
00122               const int in_y = in_y_origin + filter_y;
00123               max = std::max(
00124                   max,
00125                   input_data[Offset(input_shape, batch, in_y, in_x, channel)]);
00126             }
00127           }
00128           max = std::max<int8_t>(max, params.quantized_activation_min);
00129           max = std::min<int8_t>(max, params.quantized_activation_max);
00130           output_data[Offset(output_shape, batch, out_y, out_x, channel)] =
00131               static_cast<int8_t>(max);
00132         }
00133       }
00134     }
00135   }
00136 }
00137 
00138 }  // namespace reference_integer_ops
00139 }  // namespace tflite
00140 
00141 #endif  // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_INTEGER_OPS_POOLING_H_