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 2019 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_POOLING_H_
00016 #define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_POOLING_H_
00017 
00018 #include "tensorflow/lite/kernels/internal/common.h"
00019 #include "tensorflow/lite/kernels/internal/quantization_util.h"
00020 #include "tensorflow/lite/kernels/internal/round.h"
00021 #include "tensorflow/lite/kernels/internal/types.h"
00022 
00023 namespace tflite {
00024 namespace reference_ops {
00025 
00026 inline void AveragePool(const PoolParams& params,
00027                         const RuntimeShape& input_shape,
00028                         const float* input_data,
00029                         const RuntimeShape& output_shape, float* output_data) {
00030   TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4);
00031   TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4);
00032   const int batches = MatchingDim(input_shape, 0, output_shape, 0);
00033   const int depth = MatchingDim(input_shape, 3, output_shape, 3);
00034   const int input_height = input_shape.Dims(1);
00035   const int input_width = input_shape.Dims(2);
00036   const int output_height = output_shape.Dims(1);
00037   const int output_width = output_shape.Dims(2);
00038   const int stride_height = params.stride_height;
00039   const int stride_width = params.stride_width;
00040   for (int batch = 0; batch < batches; ++batch) {
00041     for (int out_y = 0; out_y < output_height; ++out_y) {
00042       for (int out_x = 0; out_x < output_width; ++out_x) {
00043         for (int channel = 0; channel < depth; ++channel) {
00044           const int in_x_origin =
00045               (out_x * stride_width) - params.padding_values.width;
00046           const int in_y_origin =
00047               (out_y * stride_height) - params.padding_values.height;
00048           // Compute the boundaries of the filter region clamped so as to
00049           // ensure that the filter window fits in the input array.
00050           const int filter_x_start = std::max(0, -in_x_origin);
00051           const int filter_x_end =
00052               std::min(params.filter_width, input_width - in_x_origin);
00053           const int filter_y_start = std::max(0, -in_y_origin);
00054           const int filter_y_end =
00055               std::min(params.filter_height, input_height - in_y_origin);
00056           float total = 0.f;
00057           float filter_count = 0;
00058           for (int filter_y = filter_y_start; filter_y < filter_y_end;
00059                ++filter_y) {
00060             for (int filter_x = filter_x_start; filter_x < filter_x_end;
00061                  ++filter_x) {
00062               const int in_x = in_x_origin + filter_x;
00063               const int in_y = in_y_origin + filter_y;
00064               total +=
00065                   input_data[Offset(input_shape, batch, in_y, in_x, channel)];
00066               filter_count++;
00067             }
00068           }
00069           const float average = total / filter_count;
00070           output_data[Offset(output_shape, batch, out_y, out_x, channel)] =
00071               ActivationFunctionWithMinMax(average, params.float_activation_min,
00072                                            params.float_activation_max);
00073         }
00074       }
00075     }
00076   }
00077 }
00078 
00079 inline void AveragePool(const PoolParams& params,
00080                         const RuntimeShape& input_shape,
00081                         const uint8* input_data,
00082                         const RuntimeShape& output_shape, uint8* output_data) {
00083   TFLITE_DCHECK_LE(params.quantized_activation_min,
00084                    params.quantized_activation_max);
00085   TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4);
00086   TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4);
00087   const int batches = MatchingDim(input_shape, 0, output_shape, 0);
00088   const int depth = MatchingDim(input_shape, 3, output_shape, 3);
00089   const int input_height = input_shape.Dims(1);
00090   const int input_width = input_shape.Dims(2);
00091   const int output_height = output_shape.Dims(1);
00092   const int output_width = output_shape.Dims(2);
00093   const int stride_height = params.stride_height;
00094   const int stride_width = params.stride_width;
00095   for (int batch = 0; batch < batches; ++batch) {
00096     for (int out_y = 0; out_y < output_height; ++out_y) {
00097       for (int out_x = 0; out_x < output_width; ++out_x) {
00098         for (int channel = 0; channel < depth; ++channel) {
00099           const int in_x_origin =
00100               (out_x * stride_width) - params.padding_values.width;
00101           const int in_y_origin =
00102               (out_y * stride_height) - params.padding_values.height;
00103           // Compute the boundaries of the filter region clamped so as to
00104           // ensure that the filter window fits in the input array.
00105           const int filter_x_start = std::max(0, -in_x_origin);
00106           const int filter_x_end =
00107               std::min(params.filter_width, input_width - in_x_origin);
00108           const int filter_y_start = std::max(0, -in_y_origin);
00109           const int filter_y_end =
00110               std::min(params.filter_height, input_height - in_y_origin);
00111           int32 acc = 0;
00112           int filter_count = 0;
00113           for (int filter_y = filter_y_start; filter_y < filter_y_end;
00114                ++filter_y) {
00115             for (int filter_x = filter_x_start; filter_x < filter_x_end;
00116                  ++filter_x) {
00117               const int in_x = in_x_origin + filter_x;
00118               const int in_y = in_y_origin + filter_y;
00119               acc +=
00120                   input_data[Offset(input_shape, batch, in_y, in_x, channel)];
00121               filter_count++;
00122             }
00123           }
00124           acc = (acc + filter_count / 2) / filter_count;
00125           acc = std::max(acc, params.quantized_activation_min);
00126           acc = std::min(acc, params.quantized_activation_max);
00127           output_data[Offset(output_shape, batch, out_y, out_x, channel)] =
00128               static_cast<uint8>(acc);
00129         }
00130       }
00131     }
00132   }
00133 }
00134 
00135 inline void L2Pool(const PoolParams& params, const RuntimeShape& input_shape,
00136                    const float* input_data, const RuntimeShape& output_shape,
00137                    float* output_data) {
00138   TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4);
00139   TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4);
00140   const int batches = MatchingDim(input_shape, 0, output_shape, 0);
00141   const int depth = MatchingDim(input_shape, 3, output_shape, 3);
00142   const int input_height = input_shape.Dims(1);
00143   const int input_width = input_shape.Dims(2);
00144   const int output_height = output_shape.Dims(1);
00145   const int output_width = output_shape.Dims(2);
00146   const int stride_height = params.stride_height;
00147   const int stride_width = params.stride_width;
00148   for (int batch = 0; batch < batches; ++batch) {
00149     for (int out_y = 0; out_y < output_height; ++out_y) {
00150       for (int out_x = 0; out_x < output_width; ++out_x) {
00151         for (int channel = 0; channel < depth; ++channel) {
00152           const int in_x_origin =
00153               (out_x * stride_width) - params.padding_values.width;
00154           const int in_y_origin =
00155               (out_y * stride_height) - params.padding_values.height;
00156           // Compute the boundaries of the filter region clamped so as to
00157           // ensure that the filter window fits in the input array.
00158           const int filter_x_start = std::max(0, -in_x_origin);
00159           const int filter_x_end =
00160               std::min(params.filter_width, input_width - in_x_origin);
00161           const int filter_y_start = std::max(0, -in_y_origin);
00162           const int filter_y_end =
00163               std::min(params.filter_height, input_height - in_y_origin);
00164           float sum_squares = 0.f;
00165           int filter_count = 0;
00166           for (int filter_y = filter_y_start; filter_y < filter_y_end;
00167                ++filter_y) {
00168             for (int filter_x = filter_x_start; filter_x < filter_x_end;
00169                  ++filter_x) {
00170               const int in_x = in_x_origin + filter_x;
00171               const int in_y = in_y_origin + filter_y;
00172               const float val =
00173                   input_data[Offset(input_shape, batch, in_y, in_x, channel)];
00174               sum_squares += val * val;
00175               filter_count++;
00176             }
00177           }
00178           const float l2pool_result = std::sqrt(sum_squares / filter_count);
00179           output_data[Offset(output_shape, batch, out_y, out_x, channel)] =
00180               ActivationFunctionWithMinMax(l2pool_result,
00181                                            params.float_activation_min,
00182                                            params.float_activation_max);
00183         }
00184       }
00185     }
00186   }
00187 }
00188 
00189 inline void MaxPool(const PoolParams& params, const RuntimeShape& input_shape,
00190                     const float* input_data, const RuntimeShape& output_shape,
00191                     float* output_data) {
00192   TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4);
00193   TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4);
00194   const int batches = MatchingDim(input_shape, 0, output_shape, 0);
00195   const int depth = MatchingDim(input_shape, 3, output_shape, 3);
00196   const int input_height = input_shape.Dims(1);
00197   const int input_width = input_shape.Dims(2);
00198   const int output_height = output_shape.Dims(1);
00199   const int output_width = output_shape.Dims(2);
00200   const int stride_height = params.stride_height;
00201   const int stride_width = params.stride_width;
00202   for (int batch = 0; batch < batches; ++batch) {
00203     for (int out_y = 0; out_y < output_height; ++out_y) {
00204       for (int out_x = 0; out_x < output_width; ++out_x) {
00205         for (int channel = 0; channel < depth; ++channel) {
00206           const int in_x_origin =
00207               (out_x * stride_width) - params.padding_values.width;
00208           const int in_y_origin =
00209               (out_y * stride_height) - params.padding_values.height;
00210           // Compute the boundaries of the filter region clamped so as to
00211           // ensure that the filter window fits in the input array.
00212           const int filter_x_start = std::max(0, -in_x_origin);
00213           const int filter_x_end =
00214               std::min(params.filter_width, input_width - in_x_origin);
00215           const int filter_y_start = std::max(0, -in_y_origin);
00216           const int filter_y_end =
00217               std::min(params.filter_height, input_height - in_y_origin);
00218           float max = std::numeric_limits<float>::lowest();
00219           for (int filter_y = filter_y_start; filter_y < filter_y_end;
00220                ++filter_y) {
00221             for (int filter_x = filter_x_start; filter_x < filter_x_end;
00222                  ++filter_x) {
00223               const int in_x = in_x_origin + filter_x;
00224               const int in_y = in_y_origin + filter_y;
00225               max = std::max(
00226                   max,
00227                   input_data[Offset(input_shape, batch, in_y, in_x, channel)]);
00228             }
00229           }
00230           output_data[Offset(output_shape, batch, out_y, out_x, channel)] =
00231               ActivationFunctionWithMinMax(max, params.float_activation_min,
00232                                            params.float_activation_max);
00233         }
00234       }
00235     }
00236   }
00237 }
00238 
00239 inline void MaxPool(const PoolParams& params, const RuntimeShape& input_shape,
00240                     const uint8* input_data, const RuntimeShape& output_shape,
00241                     uint8* output_data) {
00242   TFLITE_DCHECK_LE(params.quantized_activation_min,
00243                    params.quantized_activation_max);
00244   TFLITE_DCHECK_GE(params.quantized_activation_min, 0);
00245   TFLITE_DCHECK_LE(params.quantized_activation_max, 255);
00246   TFLITE_DCHECK_EQ(input_shape.DimensionsCount(), 4);
00247   TFLITE_DCHECK_EQ(output_shape.DimensionsCount(), 4);
00248   const int batches = MatchingDim(input_shape, 0, output_shape, 0);
00249   const int depth = MatchingDim(input_shape, 3, output_shape, 3);
00250   const int input_height = input_shape.Dims(1);
00251   const int input_width = input_shape.Dims(2);
00252   const int output_height = output_shape.Dims(1);
00253   const int output_width = output_shape.Dims(2);
00254   const int stride_height = params.stride_height;
00255   const int stride_width = params.stride_width;
00256   for (int batch = 0; batch < batches; ++batch) {
00257     for (int out_y = 0; out_y < output_height; ++out_y) {
00258       for (int out_x = 0; out_x < output_width; ++out_x) {
00259         for (int channel = 0; channel < depth; ++channel) {
00260           const int in_x_origin =
00261               (out_x * stride_width) - params.padding_values.width;
00262           const int in_y_origin =
00263               (out_y * stride_height) - params.padding_values.height;
00264           // Compute the boundaries of the filter region clamped so as to
00265           // ensure that the filter window fits in the input array.
00266           const int filter_x_start = std::max(0, -in_x_origin);
00267           const int filter_x_end =
00268               std::min(params.filter_width, input_width - in_x_origin);
00269           const int filter_y_start = std::max(0, -in_y_origin);
00270           const int filter_y_end =
00271               std::min(params.filter_height, input_height - in_y_origin);
00272           uint8 max = 0;
00273           for (int filter_y = filter_y_start; filter_y < filter_y_end;
00274                ++filter_y) {
00275             for (int filter_x = filter_x_start; filter_x < filter_x_end;
00276                  ++filter_x) {
00277               const int in_x = in_x_origin + filter_x;
00278               const int in_y = in_y_origin + filter_y;
00279               max = std::max(
00280                   max,
00281                   input_data[Offset(input_shape, batch, in_y, in_x, channel)]);
00282             }
00283           }
00284           max = std::max<uint8>(max, params.quantized_activation_min);
00285           max = std::min<uint8>(max, params.quantized_activation_max);
00286           output_data[Offset(output_shape, batch, out_y, out_x, channel)] =
00287               static_cast<uint8>(max);
00288         }
00289       }
00290     }
00291   }
00292 }
00293 }  // namespace reference_ops
00294 }  // namespace tflite
00295 
00296 #endif  // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_POOLING_H_