Program Listing for File darknet.hpp

Return to documentation for file (/home/jenkins/docs/models/models/darknet/darknet.hpp)

 author = {Joseph Redmon, Ali Farhadi},
 title = {YOLO9000 : Better, Faster, Stronger},
 year = {2016},
 url = {https://pjreddie.com/media/files/papers/YOLO9000.pdf}
}
 author = {Joseph Redmon, Ali Farhadi},
 title = {YOLOv3 :  An Incremental Improvement},
 year = {2019},
 url = {https://pjreddie.com/media/files/papers/YOLOv3.pdf}
}

#ifndef MODELS_MODELS_DARKNET_DARKNET_HPP
#define MODELS_MODELS_DARKNET_DARKNET_HPP

#include <mlpack/core.hpp>
#include <mlpack/methods/ann/layer/layer.hpp>
#include <mlpack/methods/ann/ffn.hpp>
#include <mlpack/methods/ann/layer/layer_types.hpp>
#include <mlpack/methods/ann/init_rules/random_init.hpp>
#include <mlpack/methods/ann/loss_functions/binary_cross_entropy_loss.hpp>
#include <mlpack/methods/ann/init_rules/he_init.hpp>
#include <mlpack/methods/ann/init_rules/glorot_init.hpp>

namespace mlpack {
namespace models {

template<
  typename OutputLayerType = ann::CrossEntropyError<>,
  typename InitializationRuleType = ann::RandomInitialization,
  size_t DarkNetVersion = 19
>
class DarkNet
{
 public:
  DarkNet();

  DarkNet(const size_t inputChannel,
          const size_t inputWidth,
          const size_t inputHeight,
          const size_t numClasses = 1000,
          const std::string& weights = "none",
          const bool includeTop = true);

  DarkNet(const std::tuple<size_t, size_t, size_t> inputShape,
          const size_t numClasses = 1000,
          const std::string& weights = "none",
          const bool includeTop = true);

  ann::FFN<OutputLayerType, InitializationRuleType>& GetModel()
  {
    return darkNet;
  }

  void LoadModel(const std::string& filePath);

  void SaveModel(const std::string& filePath);

 private:
  template<typename SequentialType = ann::Sequential<>>
  void ConvolutionBlock(const size_t inSize,
                        const size_t outSize,
                        const size_t kernelWidth,
                        const size_t kernelHeight,
                        const size_t strideWidth = 1,
                        const size_t strideHeight = 1,
                        const size_t padW = 0,
                        const size_t padH = 0,
                        const bool batchNorm = true,
                        const double negativeSlope = 1e-1,
                        SequentialType* baseLayer = NULL)
  {
    ann::Sequential<>* bottleNeck = new ann::Sequential<>();
    bottleNeck->Add(new ann::Convolution<>(inSize, outSize, kernelWidth,
        kernelHeight, strideWidth, strideHeight, padW, padH, inputWidth,
        inputHeight));

    // Update inputWidth and input Height.
    mlpack::Log::Info << "Conv Layer.  ";
    mlpack::Log::Info << "(" << inputWidth << ", " << inputHeight <<
        ", " << inSize << ") ----> ";

    inputWidth = ConvOutSize(inputWidth, kernelWidth, strideWidth, padW);
    inputHeight = ConvOutSize(inputHeight, kernelHeight, strideHeight, padH);
    mlpack::Log::Info << "(" << inputWidth << ", " << inputHeight <<
        ", " << outSize << ")" << std::endl;

    if (batchNorm)
      bottleNeck->Add(new ann::BatchNorm<>(outSize, 1e-5, false));

    bottleNeck->Add(new ann::LeakyReLU<>(negativeSlope));

    if (baseLayer != NULL)
      baseLayer->Add(bottleNeck);
    else
      darkNet.Add(bottleNeck);
  }

  void PoolingBlock(const size_t factor = 2,
                    const std::string type = "max")
  {
    if (type == "max")
    {
      darkNet.Add(new ann::AdaptiveMaxPooling<>(
          std::ceil(inputWidth * 1.0 / factor),
          std::ceil(inputHeight * 1.0 / factor)));
    }
    else
    {
      darkNet.Add(new ann::AdaptiveMeanPooling<>(std::ceil(inputWidth * 1.0 /
          factor), std::ceil(inputHeight * 1.0 / factor)));
    }

    mlpack::Log::Info << "Pooling Layer.  ";
    mlpack::Log::Info << "(" << inputWidth << ", " << inputHeight <<
        ") ----> ";

    // Update inputWidth and inputHeight.
    inputWidth = std::ceil(inputWidth * 1.0 / factor);
    inputHeight = std::ceil(inputHeight * 1.0 / factor);
    mlpack::Log::Info << "(" << inputWidth << ", " << inputHeight <<
        ")" << std::endl;
  }

  void DarkNet19SequentialBlock(const size_t inputChannel,
                                const size_t kernelWidth,
                                const size_t kernelHeight,
                                const size_t padWidth,
                                const size_t padHeight)
  {
    ConvolutionBlock(inputChannel, inputChannel * 2,
        kernelWidth, kernelHeight, 1, 1, padWidth, padHeight, true);
    ConvolutionBlock(inputChannel * 2, inputChannel,
        1, 1, 1, 1, 0, 0, true);
    ConvolutionBlock(inputChannel, inputChannel * 2,
        kernelWidth, kernelHeight, 1, 1, padWidth, padHeight, true);
  }

  void DarkNet53ResidualBlock(const size_t inputChannel,
                              const size_t kernelWidth = 3,
                              const size_t kernelHeight = 3,
                              const size_t padWidth = 1,
                              const size_t padHeight = 1)
  {
    mlpack::Log::Info << "Residual Block Begin." << std::endl;
    ann::Residual<>* residualBlock = new ann::Residual<>();
    ConvolutionBlock(inputChannel, inputChannel / 2,
        1, 1, 1, 1, 0, 0, true, 1e-2, residualBlock);
    ConvolutionBlock(inputChannel / 2, inputChannel, kernelWidth,
        kernelHeight, 1, 1, padWidth, padHeight, true, 1e-2, residualBlock);
    darkNet.Add(residualBlock);
    mlpack::Log::Info << "Residual Block end." << std::endl;
  }

  size_t ConvOutSize(const size_t size,
                     const size_t k,
                     const size_t s,
                     const size_t padding)
  {
    return std::floor(size + 2 * padding - k) / s + 1;
  }

  ann::FFN<OutputLayerType, InitializationRuleType> darkNet;

  size_t inputWidth;

  size_t inputHeight;

  size_t inputChannel;

  size_t numClasses;

  std::string weights;
}; // DarkNet class.

// Convenience typedefs for different DarkNet models.
typedef DarkNet<ann::CrossEntropyError<>, ann::RandomInitialization, 19>
    DarkNet19;

typedef DarkNet<ann::CrossEntropyError<>, ann::RandomInitialization, 53>
    DarkNet53;

} // namespace models
} // namespace mlpack

# include "darknet_impl.hpp"

#endif