From 314448a32833a1e1226b40ab81b07dbf44b8c55c Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Fri, 12 Jun 2020 08:55:34 +0530 Subject: [PATCH 01/35] Add darknet model architecture with basic tests --- models/CMakeLists.txt | 15 ++ models/darknet/CMakeLists.txt | 16 ++ models/darknet/darknet.hpp | 298 ++++++++++++++++++++++++++++++++ models/darknet/darknet_impl.hpp | 188 ++++++++++++++++++++ tests/ffn_model_tests.cpp | 82 +++++++++ 5 files changed, 599 insertions(+) create mode 100644 models/CMakeLists.txt create mode 100644 models/darknet/CMakeLists.txt create mode 100644 models/darknet/darknet.hpp create mode 100644 models/darknet/darknet_impl.hpp create mode 100644 tests/ffn_model_tests.cpp diff --git a/models/CMakeLists.txt b/models/CMakeLists.txt new file mode 100644 index 00000000..418ada80 --- /dev/null +++ b/models/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) +project(models) + +add_subdirectory(darknet) + +# Add directory name to sources. +set(DIR_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/) + +foreach(file ${SOURCES}) + set(DIR_SRCS ${DIR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/${file}) +endforeach() + +# Append sources (with directory name) to list of all models sources (used at +# the parent scope). +set(DIRS ${DIRS} ${DIR_SRCS} PARENT_SCOPE) diff --git a/models/darknet/CMakeLists.txt b/models/darknet/CMakeLists.txt new file mode 100644 index 00000000..92bbdf82 --- /dev/null +++ b/models/darknet/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) +project(darknet) + +set(DIR_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/) +include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../../") + +set(SOURCES + darknet.hpp + darknet_impl.hpp +) + +foreach(file ${SOURCES}) + set(DIR_SRCS ${DIR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/${file}) +endforeach() + +set(DIRS ${DIRS} ${DIR_SRCS} PARENT_SCOPE) diff --git a/models/darknet/darknet.hpp b/models/darknet/darknet.hpp new file mode 100644 index 00000000..71d66840 --- /dev/null +++ b/models/darknet/darknet.hpp @@ -0,0 +1,298 @@ +/** + * @file darknet.hpp + * @author Kartik Dutt + * + * Definition of Darknet models. + * + * For more information, kindly refer to the following paper. + * + * Paper for DarkNet-19. + * + * @code + * @article{Redmon2016, + * author = {Joseph Redmon, Ali Farhadi}, + * title = {YOLO9000 : Better, Faster, Stronger}, + * year = {2016}, + * url = {https://pjreddie.com/media/files/papers/YOLO9000.pdf} + * } + * @endcode + * + * Paper for DarkNet-53. + * + * @code + * @article{Redmon2016, + * author = {Joseph Redmon, Ali Farhadi}, + * title = {YOLOv3 : An Incremental Improvement}, + * year = {2019}, + * url = {https://pjreddie.com/media/files/papers/YOLOv3.pdf} + * } + * @endcode + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ + +#ifndef MODELS_DARKNET_HPP +#define MODELS_DARKNET_HPP + +#include +#include +#include +#include +#include + +namespace mlpack { +namespace ann /** Artificial Neural Network. */{ + +/** + * Definition of a Darknet CNN. + * + * @tparam OutputLayerType The output layer type used to evaluate the network. + * @tparam InitializationRuleType Rule used to initialize the weight matrix. + * @tparam DaknetVer Version of DarkNet. + */ +template< + typename OutputLayerType = NegativeLogLikelihood<>, + typename InitializationRuleType = RandomInitialization, + size_t DarkNetVer = 19 +> +class DarkNet +{ + public: + //! Create the DarkNet model. + DarkNet(); + + /** + * DarkNet constructor intializes input shape and number of classes. + * + * @param inputChannels Number of input channels of the input image. + * @param inputWidth Width of the input image. + * @param inputHeight Height of the input image. + * @param numClasses Optional number of classes to classify images into, + * only to be specified if includeTop is true. + * @param weights One of 'none', 'cifar10'(pre-training on CIFAR10) or path to weights. + * @param includeTop Must be set to true if weights are set. + */ + 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 constructor intializes input shape and number of classes. + * + * @param inputShape A three-valued tuple indicating input shape. + * First value is number of Channels (Channels-First). + * Second value is input height. + * Third value is input width.. + * @param numClasses Optional number of classes to classify images into, + * only to be specified if includeTop is true. + * @param weights One of 'none', 'cifar10'(pre-training on CIFAR10) or path to weights. + */ + DarkNet(const std::tuple inputShape, + const size_t numClasses = 1000, + const std::string& weights = "none", + const bool includeTop = true); + + //! Get Layers of the model. + FFN& GetModel() { return darkNet; } + + //! Load weights into the model. + void LoadModel(const std::string& filePath); + + //! Save weights for the model. + void SaveModel(const std::string& filePath); + + private: + /** + * Adds Convolution Block. + * + * @param inSize Number of input maps. + * @param outSize Number of output maps. + * @param kernelWidth Width of the filter/kernel. + * @param kernelHeight Height of the filter/kernel. + * @param strideWidth Stride of filter application in the x direction. + * @param strideHeight Stride of filter application in the y direction. + * @param padW Padding width of the input. + * @param padH Padding height of the input. + */ + Sequential<>* 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 size_t batchNorm = false) + { + Sequential<>* bottleNeck = new Sequential<>(); + bottleNeck->Add(new Convolution<>(inSize, outSize, kernelWidth, + kernelHeight, strideWidth, strideHeight, padW, padH, inputWidth, + inputHeight)); + if (batchNorm) + { + bottleNeck->Add(new BatchNorm<>(outSize)); + } + + bottleNeck->Add(new LeakyReLU<>()); + + // Update inputWidth and input Height. + std::cout << "(" << inputWidth << ", " << inputHeight << + ", " << inSize << ") ----> "; + + inputWidth = ConvOutSize(inputWidth, kernelWidth, strideWidth, padW); + inputHeight = ConvOutSize(inputHeight, kernelHeight, strideHeight, padH); + std::cout << "(" << inputWidth << ", " << inputHeight << + ", " << outSize << ")" << std::endl; + return bottleNeck; + } + + /** + * Adds Pooling Block. + * + * @param kernelWidth Width of the filter/kernel. + * @param kernelHeight Height of the filter/kernel. + * @param strideWidth Stride of filter application in the x direction. + * @param strideHeight Stride of filter application in the y direction. + */ + Sequential<>* PoolingBlock(const size_t kernelWidth, + const size_t kernelHeight, + const size_t strideWidth = 1, + const size_t strideHeight = 1, + const std::string type = "max") + { + Sequential<>* bottleNeck = new Sequential<>(); + if (type == "max") + { + bottleNeck->Add(new MaxPooling<>(kernelWidth, kernelHeight, + strideWidth, strideHeight, true)); + } + else + { + bottleNeck->Add(new MeanPooling<>(kernelWidth, kernelHeight, + strideWidth, strideHeight, true)); + } + + // Update inputWidth and inputHeight. + inputWidth = PoolOutSize(inputWidth, kernelWidth, strideWidth); + inputHeight = PoolOutSize(inputHeight, kernelHeight, strideHeight); + return bottleNeck; + } + + /** + * Adds bottleneck block for DarkNet 19. + * + * It's represented as: + * ConvolutionLayer(inputChannel, inputChannel * 2, stride) + * | + * ConvolutionLayer(inputChannel * 2, inputChannel, 1) + * | + * ConvolutionLayer(inputChannel, inputChannel * 2, stride) + * + * @param inputChannel Input channel in the convolution block. + * @param kernelWidth Width of the filter/kernel. + * @param kernelHeight Height of the filter/kernel. + * @param padWidth Padding in convolutional layer. + * @param padHeight Padding in convolutional layer. + */ + Sequential<>* DarkNet19SequentialBlock(const size_t inputChannel, + const size_t kernelWidth, + const size_t kernelHeight, + const size_t padWidth, + const size_t padHeight) + { + Sequential<>* block = new Sequential<>(); + block->Add(ConvolutionBlock(inputChannel, inputChannel * 2, + kernelWidth, kernelHeight, 1, 1, padWidth, padHeight)); + block->Add(ConvolutionBlock(inputChannel * 2, inputChannel, + 1, 1)); + block->Add(ConvolutionBlock(inputChannel, inputChannel * 2, + kernelWidth, kernelHeight, 1, 1, padWidth, padHeight)); + return block; + } + + /** + * Adds residual bottleneck block for DarkNet 53. + * + * @param inputChannel Input channel in the bottle-neck. + * @param kernelWidth Width of the filter/kernel. + * @param kernelHeight Height of the filter/kernel. + * @param padWidth Padding in convolutional layer. + * @param padHeight Padding in convolutional layer. + */ + Residual<>* 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) + { + Residual<>* residualBlock = new Residual<>(); + residualBlock->Add(ConvolutionBlock(inputChannel, inputChannel / 2, + 1, 1, 1, 1, 0, 0, true)); + residualBlock->Add(ConvolutionBlock(inputChannel / 2, inputChannel, + kernelWidth, kernelHeight, 1, 1, padWidth, padWidth, true)); + return residualBlock; + } + + /** + * Return the convolution output size. + * + * @param size The size of the input (row or column). + * @param k The size of the filter (width or height). + * @param s The stride size (x or y direction). + * @param padding The size of the padding (width or height) on one side. + * @return The convolution output size. + */ + 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; + } + + /** + * Return the convolution output size. + * + * @param size The size of the input (row or column). + * @param k The size of the filter (width or height). + * @param s The stride size (x or y direction). + * @return The convolution output size. + */ + size_t PoolOutSize(const size_t size, + const size_t k, + const size_t s) + { + return std::floor(size - 1) / s + 1; + } + + //! Locally stored LeNet Model. + FFN darkNet; + + //! Locally stored width of the image. + size_t inputWidth; + + //! Locally stored height of the image. + size_t inputHeight; + + //! Locally stored number of channels in the image. + size_t inputChannel; + + //! Locally stored number of output classes. + size_t numClasses; + + //! Locally stored type of pre-trained weights. + std::string weights; +}; // DarkNet class. + +} // namespace ann +} // namespace mlpack + +# include "darknet_impl.hpp" + +#endif diff --git a/models/darknet/darknet_impl.hpp b/models/darknet/darknet_impl.hpp new file mode 100644 index 00000000..b1fa0ca0 --- /dev/null +++ b/models/darknet/darknet_impl.hpp @@ -0,0 +1,188 @@ +/** + * @file darknet_impl.hpp + * @author Kartik Dutt + * + * Implementation of LeNet using mlpack. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ +#ifndef MODELS_DARKNET_IMPL_HPP +#define MODELS_DARKNET_IMPL_HPP + +#include "darknet.hpp" + +namespace mlpack { +namespace ann { + +template< + typename OutputLayerType, + typename InitializationRuleType, + size_t DarkNetVer +> +DarkNet::DarkNet() : + inputChannel(0), + inputWidth(0), + inputHeight(0), + numClasses(0), + weights("none") +{ + // Nothing to do here. +} + +template< + typename OutputLayerType, + typename InitializationRuleType, + size_t DarkNetVer +> +DarkNet::DarkNet( + const size_t inputChannel, + const size_t inputWidth, + const size_t inputHeight, + const size_t numClasses, + const std::string& weights, + const bool includeTop) : + DarkNet( + std::tuple( + inputChannel, + inputWidth, + inputHeight), + numClasses, + weights, + includeTop) +{ + // Nothing to do here. +} + +template< + typename OutputLayerType, + typename InitializationRuleType, + size_t DarkNetVer +> +DarkNet::DarkNet( + const std::tuple inputShape, + const size_t numClasses, + const std::string& weights, + const bool includeTop) : + inputChannel(std::get<0>(inputShape)), + inputWidth(std::get<1>(inputShape)), + inputHeight(std::get<2>(inputShape)), + numClasses(numClasses), + weights(weights) +{ + mlpack::Log::Assert(DarkNetVer == 19 || DarkNetVer == 53, + "Incorrect DarkNet version. Possible values are 19 and 53. Trying \ + to find version : " + std::to_string(DarkNetVer) + "."); + + if (weights == "cifar10") + { + // Download weights here. + LoadModel("./../weights/darknet/darknet" + std::to_string(DarkNetVer) + + "_cifar10.bin"); + return; + } + else if (weights != "none") + { + LoadModel(weights); + return; + } + + if (DarkNetVer == 19) + { + darkNet.Add(new IdentityLayer<>()); + + // Convolution and activation function in a block. + darkNet.Add(ConvolutionBlock(inputChannel, 32, 3, + 3, 1, 1, 1, 1)); + darkNet.Add(PoolingBlock(2, 2, 2, 2)); + darkNet.Add(ConvolutionBlock(32, 64, 3, + 3, 1, 1, 1, 1)); + darkNet.Add(PoolingBlock(2, 2, 2, 2)); + darkNet.Add(DarkNet19SequentialBlock(64, 3, 3, 1, 1)); + darkNet.Add(PoolingBlock(2, 2, 2, 2)); + darkNet.Add(DarkNet19SequentialBlock(128, 3, 3, 1, 1)); + darkNet.Add(PoolingBlock(2, 2, 2, 2)); + darkNet.Add(DarkNet19SequentialBlock(256, 3, 3, 1, 1)); + darkNet.Add(ConvolutionBlock(512, 256, 1, 1, 1, 1)); + darkNet.Add(ConvolutionBlock(256, 512, 3, 3, 1, + 1, 1, 1)); + darkNet.Add(PoolingBlock(2, 2, 2, 2)); + darkNet.Add(DarkNet19SequentialBlock(1024, 3, 3, 1, 1)); + darkNet.Add(ConvolutionBlock(1024, 512, 1, 1, 1, 1)); + darkNet.Add(ConvolutionBlock(512, 1024, 3, 3, 1, 1, + 1, 1)); + darkNet.Add(ConvolutionBlock(1024, 1000, 1, 1, 1, 1)); + darkNet.Add(PoolingBlock(inputWidth, inputHeight, + inputWidth, inputHeight, "mean")); + + if (includeTop) + { + darkNet.Add(new Linear<>(1000, numClasses)); + darkNet.Add(new LogSoftMax<>()); + } + } + else if (DarkNetVer == 53) + { + darkNet.Add(new IdentityLayer<>()); + darkNet.Add(ConvolutionBlock(inputChannel, 32, 3, 3, 1, 1, + 0, 0, true)); + darkNet.Add(ConvolutionBlock(inputChannel, 64, 3, 3, 2, 2, + 1, 1, true)); + // Let's automate this a bit. + size_t curChannels = 64; + + // Residual block configuration for DarkNet 53. + std::vector residualBlockConfig = {1, 2, 8, 8, 4}; + for (size_t blockCount : residualBlockConfig) + { + for (size_t i = 0; i < blockCount; i++) + { + darkNet.Add(DarkNet53ResidualBlock(curChannels)); + } + + darkNet.Add(ConvolutionBlock(curChannels, curChannels * 2, 3, 3, + 2, 2, 1, 1, true)); + curChannels = curChannels * 2; + } + + if (includeTop) + { + darkNet.Add(new Linear<>(1000, numClasses)); + darkNet.Add(new LogSoftMax<>()); + } + } +} + +template< + typename OutputLayerType, + typename InitializationRuleType, + size_t DarkNetVer +> +void DarkNet< + OutputLayerType, InitializationRuleType, DarkNetVer +>::LoadModel(const std::string& filePath) +{ + data::Load(filePath, "DarkNet" + std::to_string(DarkNetVer), darkNet); + Log::Info << "Loaded model" << std::endl; +} + +template< + typename OutputLayerType, + typename InitializationRuleType, + size_t DarkNetVer +> +void DarkNet< + OutputLayerType, InitializationRuleType, DarkNetVer +>::SaveModel(const std::string& filePath) +{ + Log::Info<< "Saving model." << std::endl; + data::Save(filePath, "DarkNet" + std::to_string(DarkNetVer), darkNet); + Log::Info << "Model saved in " << filePath << "." << std::endl; +} + +} // namespace ann +} // namespace mlpack + +#endif diff --git a/tests/ffn_model_tests.cpp b/tests/ffn_model_tests.cpp new file mode 100644 index 00000000..a047e65d --- /dev/null +++ b/tests/ffn_model_tests.cpp @@ -0,0 +1,82 @@ +/** + * @file model_tests.cpp + * @author Kartik Dutt + * + * Tests for various functionalities and performance of models. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ +#define BOOST_TEST_DYN_LINK +#include +#include +#include +#include +#include + +// Use namespaces for convenience. +using namespace boost::unit_test; + +BOOST_AUTO_TEST_SUITE(FFNModelsTests); + +template< + typename OptimizerType, + typename OutputLayerType = mlpack::ann::NegativeLogLikelihood<>, + typename InitializationRuleType = mlpack::ann::RandomInitialization, + class MetricType = mlpack::metric::SquaredEuclideanDistance, + typename InputType = arma::mat, + typename OutputType = arma::mat +> +void CheckFFNClassificationWeights(mlpack::ann::FFN& model, const std::string& datasetName, + const double threshold, const bool takeMean, + OptimizerType& optimizer) +{ + DataLoader dataloader(datasetName, true); + + // Train the model. Note: Callbacks such as progress bar and loss aren't + // used in testing. Training the model for few epochs ensures that a + // user can use the pretrained model on any other dataset. + model.Train(dataloader.TrainFeatures(), dataloader.TrainLabels(), optimizer); + + // Verify viability of model on validation datset. + OutputType predictions; + model.Predict(dataloader.ValidFeatures(), predictions); + + // Since this checks weights for classification problem, we need to convert + // predictions into labels. + arma::Row predLabels(predictions.n_cols); + for (arma::uword i = 0; i < predictions.n_cols; ++i) + { + predLabels(i) = predictions.col(i).index_max() + 1; + } + + double error = MetricType::Evaluate(predLabels, dataloader.ValidLabels()); + + if (takeMean) + { + error = error / predictions.n_elem; + } + + BOOST_REQUIRE_LE(error, threshold); +} + +/** + * Simple test for Darknet model. + */ +BOOST_AUTO_TEST_CASE(DarknetModelTest) +{ + mlpack::ann::DarkNet<> darknetModel(3, 56, 56, 10); + + // Create an optimizer object for tests. + ens::SGD optimizer(1e-4, 16, 50, + 1e-8, true, ens::AdamUpdate(1e-8, 0.9, 0.999)); + + // Check whether FFN model performs well. + // CheckFFNClassificationWeights>( + // darknetModel1.GetModel(), "mnist", 1e-1, true, optimizer); +} + +BOOST_AUTO_TEST_SUITE_END(); From c5adb851bc2704b7c38c1937555c08389db97335 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Fri, 12 Jun 2020 10:40:31 +0530 Subject: [PATCH 02/35] Add training script --- CMakeLists.txt | 2 + computer_vision/CMakeLists.txt | 13 +++++ .../object_classification.cpp | 55 +++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 computer_vision/CMakeLists.txt create mode 100644 computer_vision/object_classification/object_classification.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d5a32184..a5a57555 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -216,7 +216,9 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/) set(DIRS utils/ dataloader/ + models/ tests/ + computer_vision/ ) foreach(dir ${DIRS}) diff --git a/computer_vision/CMakeLists.txt b/computer_vision/CMakeLists.txt new file mode 100644 index 00000000..d9268fba --- /dev/null +++ b/computer_vision/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) +project(computer_vision) + +add_subdirectory(object_classification/) + +# Add directory name to sources. +set(DIR_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/) + +foreach(file ${SOURCES}) + set(DIR_SRCS ${DIR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/${file}) +endforeach() + +set(DIRS ${DIRS} ${DIR_SRCS} PARENT_SCOPE) diff --git a/computer_vision/object_classification/object_classification.cpp b/computer_vision/object_classification/object_classification.cpp new file mode 100644 index 00000000..81604367 --- /dev/null +++ b/computer_vision/object_classification/object_classification.cpp @@ -0,0 +1,55 @@ +/** + * @file object_classification.hpp + * @author Kartik Dutt + * + * Contains implementation of object classification suite. It can be used + * to select object classification model, it's parameter dataset and + * other training parameters. + * + * NOTE: This code needs to be adapted as this implementation doesn't support + * Command Line Arguments. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ + #include + #include + #include + #include + + using namespace mlpack; + using namespace mlpack::ann; + using namespace arma; + using namespace std; + using namespace ens; + + int main() + { + DataLoader<> dataloader; + std::cout << "Loading Dataset!" << std::endl; + dataloader.LoadImageDatasetFromDirectory("./../data/cifar10", 32, + 32, 3, true, 0.2, true, {"resize : 56"}); + + std::cout << "Dataset Loaded!" << std::endl; + + DarkNet<> darknetModel(3, 56, 56, 10); + std::cout << "Model Compiled" << std::endl; + + constexpr double RATIO = 0.1; + constexpr size_t EPOCHS = 3; + constexpr double STEP_SIZE = 1.2e-3; + constexpr int BATCH_SIZE = 50; + + ens::Adam optimizer(STEP_SIZE, BATCH_SIZE, 0.9, 0.998, 1e-8, + dataloader.TrainFeatures().n_cols * EPOCHS); + std::cout << "Optimizer Created, Starting Training!" << std::endl; + + darknetModel.GetModel().Train(dataloader.TrainFeatures(), + dataloader.TrainLabels(), optimizer, ens::PrintLoss(), + ens::ProgressBar(), ens::EarlyStopAtMinLoss()); + mlpack::data::Save("darknet19.bin", "darknet", + darknetModel.GetModel(), false); + return 0; +} From 4e196d89aaf9842e5e5ee548cb05be1d77598d02 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Fri, 12 Jun 2020 21:45:15 +0530 Subject: [PATCH 03/35] Force add cmake --- models/darknet/darknet.hpp | 9 ++++++++- models/darknet/darknet_impl.hpp | 4 ++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/models/darknet/darknet.hpp b/models/darknet/darknet.hpp index 71d66840..57f3dd07 100644 --- a/models/darknet/darknet.hpp +++ b/models/darknet/darknet.hpp @@ -142,6 +142,7 @@ class DarkNet bottleNeck->Add(new LeakyReLU<>()); // Update inputWidth and input Height. + std::cout << "Conv Layer. "; std::cout << "(" << inputWidth << ", " << inputHeight << ", " << inSize << ") ----> "; @@ -177,10 +178,14 @@ class DarkNet bottleNeck->Add(new MeanPooling<>(kernelWidth, kernelHeight, strideWidth, strideHeight, true)); } - + std::cout << "Pooling Layer. "; + std::cout << "(" << inputWidth << ", " << inputHeight << + ") ----> "; // Update inputWidth and inputHeight. inputWidth = PoolOutSize(inputWidth, kernelWidth, strideWidth); inputHeight = PoolOutSize(inputHeight, kernelHeight, strideHeight); + std::cout << "(" << inputWidth << ", " << inputHeight << + ")" << std::endl;; return bottleNeck; } @@ -231,11 +236,13 @@ class DarkNet const size_t padWidth = 1, const size_t padHeight = 1) { + std::cout << "Residual Block Begin." << std::endl; Residual<>* residualBlock = new Residual<>(); residualBlock->Add(ConvolutionBlock(inputChannel, inputChannel / 2, 1, 1, 1, 1, 0, 0, true)); residualBlock->Add(ConvolutionBlock(inputChannel / 2, inputChannel, kernelWidth, kernelHeight, 1, 1, padWidth, padWidth, true)); + std::cout << "Residual Block end." << std::endl; return residualBlock; } diff --git a/models/darknet/darknet_impl.hpp b/models/darknet/darknet_impl.hpp index b1fa0ca0..96612c69 100644 --- a/models/darknet/darknet_impl.hpp +++ b/models/darknet/darknet_impl.hpp @@ -122,6 +122,8 @@ DarkNet::DarkNet( darkNet.Add(new Linear<>(1000, numClasses)); darkNet.Add(new LogSoftMax<>()); } + + darkNet.ResetParameters(); } else if (DarkNetVer == 53) { @@ -152,6 +154,8 @@ DarkNet::DarkNet( darkNet.Add(new Linear<>(1000, numClasses)); darkNet.Add(new LogSoftMax<>()); } + + darkNet.ResetParameters(); } } From c50966bc326e7140686a4565b168f016bcd05a74 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Fri, 12 Jun 2020 21:56:25 +0530 Subject: [PATCH 04/35] Force add cmake --- .../object_classification/CMakeLists.txt | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 computer_vision/object_classification/CMakeLists.txt diff --git a/computer_vision/object_classification/CMakeLists.txt b/computer_vision/object_classification/CMakeLists.txt new file mode 100644 index 00000000..345c9620 --- /dev/null +++ b/computer_vision/object_classification/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) + project(object_classification) + +set(MODEL_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/) +include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../../") + +set(SOURCES + object_classification.cpp +) + +foreach(file ${SOURCES}) + string( REPLACE ".cpp" "" name ${file}) + add_executable(${name} ${MODEL_SOURCE_DIR}/${file}) + target_link_libraries(${name} + ${COMPILER_SUPPORT_LIBRARIES} + ${ARMADILLO_LIBRARIES} + ${Boost_FILESYSTEM_LIBRARY} + ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} + ${Boost_SYSTEM_LIBRARY} + ${Boost_SERIALIZATION_LIBRARY} + ${Boost_REGEX_LIBRARY} + ${MLPACK_LIBRARIES} +) +endforeach() From 7b444b52a2d675d088c9b16eac4464b3946fd2af Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Fri, 12 Jun 2020 22:01:04 +0530 Subject: [PATCH 05/35] Force add cmake --- .../object_classification.cpp | 59 ++++++++++--------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/computer_vision/object_classification/object_classification.cpp b/computer_vision/object_classification/object_classification.cpp index 81604367..8c1939bc 100644 --- a/computer_vision/object_classification/object_classification.cpp +++ b/computer_vision/object_classification/object_classification.cpp @@ -1,40 +1,41 @@ /** - * @file object_classification.hpp - * @author Kartik Dutt - * - * Contains implementation of object classification suite. It can be used - * to select object classification model, it's parameter dataset and - * other training parameters. - * - * NOTE: This code needs to be adapted as this implementation doesn't support - * Command Line Arguments. - * - * mlpack is free software; you may redistribute it and/or modify it under the - * terms of the 3-clause BSD license. You should have received a copy of the - * 3-clause BSD license along with mlpack. If not, see - * http://www.opensource.org/licenses/BSD-3-Clause for more information. - */ - #include - #include - #include - #include + * @file object_classification.hpp + * @author Kartik Dutt + * + * Contains implementation of object classification suite. It can be used + * to select object classification model, it's parameter dataset and + * other training parameters. + * + * NOTE: This code needs to be adapted as this implementation doesn't support + * Command Line Arguments. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ +#include +#include +#include +#include - using namespace mlpack; - using namespace mlpack::ann; - using namespace arma; - using namespace std; - using namespace ens; +using namespace mlpack; +using namespace mlpack::ann; +using namespace arma; +using namespace std; +using namespace ens; - int main() - { +int main() +{ DataLoader<> dataloader; std::cout << "Loading Dataset!" << std::endl; - dataloader.LoadImageDatasetFromDirectory("./../data/cifar10", 32, - 32, 3, true, 0.2, true, {"resize : 56"}); + dataloader.LoadImageDatasetFromDirectory("./../data/cifar-test", + 32, 32, 3, true, 0.2, true, + {"resize : 128"}); std::cout << "Dataset Loaded!" << std::endl; - DarkNet<> darknetModel(3, 56, 56, 10); + DarkNet<> darknetModel(3, 128, 128, 10); std::cout << "Model Compiled" << std::endl; constexpr double RATIO = 0.1; From 77ee0bf6e444ac4dc2728fc3d03c54165bfa940b Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Sun, 14 Jun 2020 13:14:16 +0530 Subject: [PATCH 06/35] Fix segfault --- .../object_classification.cpp | 2 +- models/darknet/darknet.hpp | 120 ++++++++++++------ models/darknet/darknet_impl.hpp | 65 +++++----- 3 files changed, 111 insertions(+), 76 deletions(-) diff --git a/computer_vision/object_classification/object_classification.cpp b/computer_vision/object_classification/object_classification.cpp index 8c1939bc..adc437e1 100644 --- a/computer_vision/object_classification/object_classification.cpp +++ b/computer_vision/object_classification/object_classification.cpp @@ -34,7 +34,7 @@ int main() {"resize : 128"}); std::cout << "Dataset Loaded!" << std::endl; - + dataloader.TrainLabels() = dataloader.TrainLabels() + 1; DarkNet<> darknetModel(3, 128, 128, 10); std::cout << "Model Compiled" << std::endl; diff --git a/models/darknet/darknet.hpp b/models/darknet/darknet.hpp index 57f3dd07..f7727884 100644 --- a/models/darknet/darknet.hpp +++ b/models/darknet/darknet.hpp @@ -110,7 +110,10 @@ class DarkNet private: /** * Adds Convolution Block. - * + * + * @tparam SequentialType Layer type in which convolution block will + * be added. + * * @param inSize Number of input maps. * @param outSize Number of output maps. * @param kernelWidth Width of the filter/kernel. @@ -119,16 +122,22 @@ class DarkNet * @param strideHeight Stride of filter application in the y direction. * @param padW Padding width of the input. * @param padH Padding height of the input. + * @param batchNorm Boolean to determine whether a batch normalization + * layer is added. + * @param baseLayer Layer in which Convolution block will be added, if + * NULL added to darkNet FFN. */ - Sequential<>* 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 size_t batchNorm = false) + template> + 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 = false, + SequentialType* baseLayer = NULL) { Sequential<>* bottleNeck = new Sequential<>(); bottleNeck->Add(new Convolution<>(inSize, outSize, kernelWidth, @@ -150,7 +159,17 @@ class DarkNet inputHeight = ConvOutSize(inputHeight, kernelHeight, strideHeight, padH); std::cout << "(" << inputWidth << ", " << inputHeight << ", " << outSize << ")" << std::endl; - return bottleNeck; + + if (baseLayer) + { + baseLayer->Add(bottleNeck); + } + else + { + darkNet.Add(bottleNeck); + } + + return; } /** @@ -160,12 +179,18 @@ class DarkNet * @param kernelHeight Height of the filter/kernel. * @param strideWidth Stride of filter application in the x direction. * @param strideHeight Stride of filter application in the y direction. + * @param type One of "max" or "mean". Determines whether add mean pooling + * layer or max pooling layer. + * @param baseLayer Layer in which Convolution block will be added, if + * NULL added to darkNet FFN. */ - Sequential<>* PoolingBlock(const size_t kernelWidth, - const size_t kernelHeight, - const size_t strideWidth = 1, - const size_t strideHeight = 1, - const std::string type = "max") + template> + void PoolingBlock(const size_t kernelWidth, + const size_t kernelHeight, + const size_t strideWidth = 1, + const size_t strideHeight = 1, + const std::string type = "max", + SequentialType* baseLayer = NULL) { Sequential<>* bottleNeck = new Sequential<>(); if (type == "max") @@ -185,8 +210,18 @@ class DarkNet inputWidth = PoolOutSize(inputWidth, kernelWidth, strideWidth); inputHeight = PoolOutSize(inputHeight, kernelHeight, strideHeight); std::cout << "(" << inputWidth << ", " << inputHeight << - ")" << std::endl;; - return bottleNeck; + ")" << std::endl; + + if (baseLayer) + { + baseLayer->Add(bottleNeck); + } + else + { + darkNet.Add(bottleNeck); + } + + return; } /** @@ -205,20 +240,24 @@ class DarkNet * @param padWidth Padding in convolutional layer. * @param padHeight Padding in convolutional layer. */ - Sequential<>* DarkNet19SequentialBlock(const size_t inputChannel, - const size_t kernelWidth, - const size_t kernelHeight, - const size_t padWidth, - const size_t padHeight) + void DarkNet19SequentialBlock(const size_t inputChannel, + const size_t kernelWidth, + const size_t kernelHeight, + const size_t padWidth, + const size_t padHeight) { Sequential<>* block = new Sequential<>(); - block->Add(ConvolutionBlock(inputChannel, inputChannel * 2, - kernelWidth, kernelHeight, 1, 1, padWidth, padHeight)); - block->Add(ConvolutionBlock(inputChannel * 2, inputChannel, - 1, 1)); - block->Add(ConvolutionBlock(inputChannel, inputChannel * 2, - kernelWidth, kernelHeight, 1, 1, padWidth, padHeight)); - return block; + ConvolutionBlock(inputChannel, inputChannel * 2, + kernelWidth, kernelHeight, 1, 1, padWidth, padHeight, false, + block); + ConvolutionBlock(inputChannel * 2, inputChannel, + 1, 1, 1, 1, 0, 0, false, block); + ConvolutionBlock(inputChannel, inputChannel * 2, + kernelWidth, kernelHeight, 1, 1, padWidth, padHeight, false, + block); + + darkNet.Add(block); + return; } /** @@ -230,20 +269,21 @@ class DarkNet * @param padWidth Padding in convolutional layer. * @param padHeight Padding in convolutional layer. */ - Residual<>* 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) + 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) { std::cout << "Residual Block Begin." << std::endl; Residual<>* residualBlock = new Residual<>(); - residualBlock->Add(ConvolutionBlock(inputChannel, inputChannel / 2, - 1, 1, 1, 1, 0, 0, true)); - residualBlock->Add(ConvolutionBlock(inputChannel / 2, inputChannel, - kernelWidth, kernelHeight, 1, 1, padWidth, padWidth, true)); + ConvolutionBlock(inputChannel, inputChannel / 2, + 1, 1, 1, 1, 0, 0, true, residualBlock); + ConvolutionBlock(inputChannel / 2, inputChannel, kernelWidth, + kernelHeight, 1, 1, padWidth, padWidth, true, residualBlock); + darkNet.Add(residualBlock); std::cout << "Residual Block end." << std::endl; - return residualBlock; + return; } /** diff --git a/models/darknet/darknet_impl.hpp b/models/darknet/darknet_impl.hpp index 96612c69..dc1265a8 100644 --- a/models/darknet/darknet_impl.hpp +++ b/models/darknet/darknet_impl.hpp @@ -91,47 +91,41 @@ DarkNet::DarkNet( if (DarkNetVer == 19) { - darkNet.Add(new IdentityLayer<>()); + darkNet.Add>(); // Convolution and activation function in a block. - darkNet.Add(ConvolutionBlock(inputChannel, 32, 3, - 3, 1, 1, 1, 1)); - darkNet.Add(PoolingBlock(2, 2, 2, 2)); - darkNet.Add(ConvolutionBlock(32, 64, 3, - 3, 1, 1, 1, 1)); - darkNet.Add(PoolingBlock(2, 2, 2, 2)); - darkNet.Add(DarkNet19SequentialBlock(64, 3, 3, 1, 1)); - darkNet.Add(PoolingBlock(2, 2, 2, 2)); - darkNet.Add(DarkNet19SequentialBlock(128, 3, 3, 1, 1)); - darkNet.Add(PoolingBlock(2, 2, 2, 2)); - darkNet.Add(DarkNet19SequentialBlock(256, 3, 3, 1, 1)); - darkNet.Add(ConvolutionBlock(512, 256, 1, 1, 1, 1)); - darkNet.Add(ConvolutionBlock(256, 512, 3, 3, 1, - 1, 1, 1)); - darkNet.Add(PoolingBlock(2, 2, 2, 2)); - darkNet.Add(DarkNet19SequentialBlock(1024, 3, 3, 1, 1)); - darkNet.Add(ConvolutionBlock(1024, 512, 1, 1, 1, 1)); - darkNet.Add(ConvolutionBlock(512, 1024, 3, 3, 1, 1, - 1, 1)); - darkNet.Add(ConvolutionBlock(1024, 1000, 1, 1, 1, 1)); - darkNet.Add(PoolingBlock(inputWidth, inputHeight, - inputWidth, inputHeight, "mean")); + ConvolutionBlock(inputChannel, 32, 3, 3, 1, 1, 1, 1); + PoolingBlock(2, 2, 2, 2); + ConvolutionBlock(32, 64, 3, 3, 1, 1, 1, 1); + PoolingBlock(2, 2, 2, 2); + DarkNet19SequentialBlock(64, 3, 3, 1, 1); + PoolingBlock(2, 2, 2, 2); + DarkNet19SequentialBlock(128, 3, 3, 1, 1); + PoolingBlock(2, 2, 2, 2); + DarkNet19SequentialBlock(256, 3, 3, 1, 1); + ConvolutionBlock(512, 256, 1, 1, 1, 1); + ConvolutionBlock(256, 512, 3, 3, 1, 1, 1, 1); + PoolingBlock(2, 2, 2, 2); + DarkNet19SequentialBlock(512, 3, 3, 1, 1); + ConvolutionBlock(1024, 512, 1, 1, 1, 1); + ConvolutionBlock(512, 1024, 3, 3, 1, 1, 1, 1); + ConvolutionBlock(1024, 1000, 1, 1, 1, 1); + PoolingBlock(inputWidth, inputHeight, inputWidth, + inputHeight, "mean"); if (includeTop) { - darkNet.Add(new Linear<>(1000, numClasses)); - darkNet.Add(new LogSoftMax<>()); + darkNet.Add>(1000, numClasses); + darkNet.Add>(); } darkNet.ResetParameters(); } else if (DarkNetVer == 53) { - darkNet.Add(new IdentityLayer<>()); - darkNet.Add(ConvolutionBlock(inputChannel, 32, 3, 3, 1, 1, - 0, 0, true)); - darkNet.Add(ConvolutionBlock(inputChannel, 64, 3, 3, 2, 2, - 1, 1, true)); + darkNet.Add>(); + ConvolutionBlock(inputChannel, 32, 3, 3, 1, 1, 1, 1, true); + ConvolutionBlock(inputChannel, 64, 3, 3, 2, 2, 1, 1, true); // Let's automate this a bit. size_t curChannels = 64; @@ -141,18 +135,19 @@ DarkNet::DarkNet( { for (size_t i = 0; i < blockCount; i++) { - darkNet.Add(DarkNet53ResidualBlock(curChannels)); + DarkNet53ResidualBlock(curChannels); } - darkNet.Add(ConvolutionBlock(curChannels, curChannels * 2, 3, 3, - 2, 2, 1, 1, true)); + ConvolutionBlock(curChannels, curChannels * 2, 3, 3, + 2, 2, 1, 1, true); curChannels = curChannels * 2; } + darkNet.Add>(inputWidth * inputHeight * curChannels, numClasses); if (includeTop) { - darkNet.Add(new Linear<>(1000, numClasses)); - darkNet.Add(new LogSoftMax<>()); + //darkNet.Add>(1000, numClasses); + darkNet.Add>(); } darkNet.ResetParameters(); From 038a2fb63e781977d77d8aabbe4fd1681ec3427d Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Sun, 14 Jun 2020 13:16:39 +0530 Subject: [PATCH 07/35] Style fixes --- models/darknet/darknet_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/darknet/darknet_impl.hpp b/models/darknet/darknet_impl.hpp index dc1265a8..48c433eb 100644 --- a/models/darknet/darknet_impl.hpp +++ b/models/darknet/darknet_impl.hpp @@ -146,7 +146,7 @@ DarkNet::DarkNet( darkNet.Add>(inputWidth * inputHeight * curChannels, numClasses); if (includeTop) { - //darkNet.Add>(1000, numClasses); + // darkNet.Add>(1000, numClasses); darkNet.Add>(); } From 5ff86eeaaeae5d1c9b826dbfddc8e77def4abb3a Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Mon, 15 Jun 2020 15:48:27 +0530 Subject: [PATCH 08/35] Build Fixed / Model --- .../object_classification.cpp | 10 ++- models/darknet/darknet.hpp | 61 +++++-------------- models/darknet/darknet_impl.hpp | 29 ++++----- 3 files changed, 36 insertions(+), 64 deletions(-) diff --git a/computer_vision/object_classification/object_classification.cpp b/computer_vision/object_classification/object_classification.cpp index adc437e1..8bdf644a 100644 --- a/computer_vision/object_classification/object_classification.cpp +++ b/computer_vision/object_classification/object_classification.cpp @@ -31,17 +31,21 @@ int main() std::cout << "Loading Dataset!" << std::endl; dataloader.LoadImageDatasetFromDirectory("./../data/cifar-test", 32, 32, 3, true, 0.2, true, - {"resize : 128"}); + {"resize : 32"}); std::cout << "Dataset Loaded!" << std::endl; dataloader.TrainLabels() = dataloader.TrainLabels() + 1; - DarkNet<> darknetModel(3, 128, 128, 10); + DarkNet<> darknetModel(3, 32, 32, 10); std::cout << "Model Compiled" << std::endl; constexpr double RATIO = 0.1; constexpr size_t EPOCHS = 3; constexpr double STEP_SIZE = 1.2e-3; - constexpr int BATCH_SIZE = 50; + constexpr int BATCH_SIZE = 1; + + mlpack::data::MinMaxScaler scaler; + scaler.Fit(dataloader.TrainFeatures()); + scaler.Transform(dataloader.TrainFeatures(), dataloader.TrainFeatures()); ens::Adam optimizer(STEP_SIZE, BATCH_SIZE, 0.9, 0.998, 1e-8, dataloader.TrainFeatures().n_cols * EPOCHS); diff --git a/models/darknet/darknet.hpp b/models/darknet/darknet.hpp index f7727884..0725e315 100644 --- a/models/darknet/darknet.hpp +++ b/models/darknet/darknet.hpp @@ -42,6 +42,7 @@ #include #include #include +#include namespace mlpack { namespace ann /** Artificial Neural Network. */{ @@ -55,7 +56,7 @@ namespace ann /** Artificial Neural Network. */{ */ template< typename OutputLayerType = NegativeLogLikelihood<>, - typename InitializationRuleType = RandomInitialization, + typename InitializationRuleType = HeInitialization, size_t DarkNetVer = 19 > class DarkNet @@ -160,7 +161,7 @@ class DarkNet std::cout << "(" << inputWidth << ", " << inputHeight << ", " << outSize << ")" << std::endl; - if (baseLayer) + if (baseLayer != NULL) { baseLayer->Add(bottleNeck); } @@ -175,52 +176,33 @@ class DarkNet /** * Adds Pooling Block. * - * @param kernelWidth Width of the filter/kernel. - * @param kernelHeight Height of the filter/kernel. - * @param strideWidth Stride of filter application in the x direction. - * @param strideHeight Stride of filter application in the y direction. + * @param factor The factor by which input dimensions will be divided. * @param type One of "max" or "mean". Determines whether add mean pooling * layer or max pooling layer. - * @param baseLayer Layer in which Convolution block will be added, if - * NULL added to darkNet FFN. */ - template> - void PoolingBlock(const size_t kernelWidth, - const size_t kernelHeight, - const size_t strideWidth = 1, - const size_t strideHeight = 1, - const std::string type = "max", - SequentialType* baseLayer = NULL) + void PoolingBlock(const size_t factor = 2, + const std::string type = "max") { - Sequential<>* bottleNeck = new Sequential<>(); + if (type == "max") { - bottleNeck->Add(new MaxPooling<>(kernelWidth, kernelHeight, - strideWidth, strideHeight, true)); + darkNet.Add(new AdaptiveMaxPooling<>(std::ceil(inputWidth * 1.0 / factor), + std::ceil(inputHeight * 1.0 / factor))); } else { - bottleNeck->Add(new MeanPooling<>(kernelWidth, kernelHeight, - strideWidth, strideHeight, true)); + darkNet.Add(new AdaptiveMeanPooling<>(std::ceil(inputWidth * 1.0 / factor), + std::ceil(inputHeight * 1.0 / factor))); } + std::cout << "Pooling Layer. "; std::cout << "(" << inputWidth << ", " << inputHeight << ") ----> "; // Update inputWidth and inputHeight. - inputWidth = PoolOutSize(inputWidth, kernelWidth, strideWidth); - inputHeight = PoolOutSize(inputHeight, kernelHeight, strideHeight); + inputWidth = std::ceil(inputWidth * 1.0 / factor); + inputHeight = std::ceil(inputHeight * 1.0 / factor); std::cout << "(" << inputWidth << ", " << inputHeight << ")" << std::endl; - - if (baseLayer) - { - baseLayer->Add(bottleNeck); - } - else - { - darkNet.Add(bottleNeck); - } - return; } @@ -303,21 +285,6 @@ class DarkNet return std::floor(size + 2 * padding - k) / s + 1; } - /** - * Return the convolution output size. - * - * @param size The size of the input (row or column). - * @param k The size of the filter (width or height). - * @param s The stride size (x or y direction). - * @return The convolution output size. - */ - size_t PoolOutSize(const size_t size, - const size_t k, - const size_t s) - { - return std::floor(size - 1) / s + 1; - } - //! Locally stored LeNet Model. FFN darkNet; diff --git a/models/darknet/darknet_impl.hpp b/models/darknet/darknet_impl.hpp index 48c433eb..3b441bef 100644 --- a/models/darknet/darknet_impl.hpp +++ b/models/darknet/darknet_impl.hpp @@ -91,39 +91,39 @@ DarkNet::DarkNet( if (DarkNetVer == 19) { - darkNet.Add>(); + darkNet.Add(new IdentityLayer<>()); // Convolution and activation function in a block. ConvolutionBlock(inputChannel, 32, 3, 3, 1, 1, 1, 1); - PoolingBlock(2, 2, 2, 2); + PoolingBlock(); ConvolutionBlock(32, 64, 3, 3, 1, 1, 1, 1); - PoolingBlock(2, 2, 2, 2); + PoolingBlock(); DarkNet19SequentialBlock(64, 3, 3, 1, 1); - PoolingBlock(2, 2, 2, 2); + PoolingBlock(); DarkNet19SequentialBlock(128, 3, 3, 1, 1); - PoolingBlock(2, 2, 2, 2); + PoolingBlock(); DarkNet19SequentialBlock(256, 3, 3, 1, 1); ConvolutionBlock(512, 256, 1, 1, 1, 1); ConvolutionBlock(256, 512, 3, 3, 1, 1, 1, 1); - PoolingBlock(2, 2, 2, 2); + PoolingBlock(); DarkNet19SequentialBlock(512, 3, 3, 1, 1); ConvolutionBlock(1024, 512, 1, 1, 1, 1); ConvolutionBlock(512, 1024, 3, 3, 1, 1, 1, 1); ConvolutionBlock(1024, 1000, 1, 1, 1, 1); - PoolingBlock(inputWidth, inputHeight, inputWidth, - inputHeight, "mean"); + + darkNet.Add(new AdaptiveMeanPooling<>(1, 1)); if (includeTop) { - darkNet.Add>(1000, numClasses); - darkNet.Add>(); + darkNet.Add(new Linear<>(1000, numClasses)); + darkNet.Add(new LogSoftMax<>()); } darkNet.ResetParameters(); } else if (DarkNetVer == 53) { - darkNet.Add>(); + darkNet.Add(new IdentityLayer<>()); ConvolutionBlock(inputChannel, 32, 3, 3, 1, 1, 1, 1, true); ConvolutionBlock(inputChannel, 64, 3, 3, 2, 2, 1, 1, true); // Let's automate this a bit. @@ -143,11 +143,12 @@ DarkNet::DarkNet( curChannels = curChannels * 2; } - darkNet.Add>(inputWidth * inputHeight * curChannels, numClasses); + darkNet.Add(new Linear<>(inputWidth * inputHeight * curChannels, + numClasses)); if (includeTop) { - // darkNet.Add>(1000, numClasses); - darkNet.Add>(); + darkNet.Add(new Linear<>(1000, numClasses)); + darkNet.Add(new LogSoftMax<>()); } darkNet.ResetParameters(); From bca33e48e77a9e4850f67f565b3ecf92d569ad68 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Mon, 15 Jun 2020 15:51:23 +0530 Subject: [PATCH 09/35] Style Fix --- models/darknet/darknet.hpp | 5 ++--- models/darknet/darknet_impl.hpp | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/models/darknet/darknet.hpp b/models/darknet/darknet.hpp index 0725e315..f81f5d08 100644 --- a/models/darknet/darknet.hpp +++ b/models/darknet/darknet.hpp @@ -183,7 +183,6 @@ class DarkNet void PoolingBlock(const size_t factor = 2, const std::string type = "max") { - if (type == "max") { darkNet.Add(new AdaptiveMaxPooling<>(std::ceil(inputWidth * 1.0 / factor), @@ -191,8 +190,8 @@ class DarkNet } else { - darkNet.Add(new AdaptiveMeanPooling<>(std::ceil(inputWidth * 1.0 / factor), - std::ceil(inputHeight * 1.0 / factor))); + darkNet.Add(new AdaptiveMeanPooling<>(std::ceil(inputWidth * 1.0 / + factor), std::ceil(inputHeight * 1.0 / factor))); } std::cout << "Pooling Layer. "; diff --git a/models/darknet/darknet_impl.hpp b/models/darknet/darknet_impl.hpp index 3b441bef..3396ccc4 100644 --- a/models/darknet/darknet_impl.hpp +++ b/models/darknet/darknet_impl.hpp @@ -110,7 +110,7 @@ DarkNet::DarkNet( ConvolutionBlock(1024, 512, 1, 1, 1, 1); ConvolutionBlock(512, 1024, 3, 3, 1, 1, 1, 1); ConvolutionBlock(1024, 1000, 1, 1, 1, 1); - + darkNet.Add(new AdaptiveMeanPooling<>(1, 1)); if (includeTop) From a61cf5ebb092076cd1fa86e95a1c70fe0926735a Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Tue, 16 Jun 2020 13:05:15 +0530 Subject: [PATCH 10/35] Add ensmallen utility --- .../object_classification.cpp | 17 +++- models/darknet/darknet.hpp | 2 +- utils/CMakeLists.txt | 4 +- utils/ensmallen_utils.hpp | 89 +++++++++++++++++++ 4 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 utils/ensmallen_utils.hpp diff --git a/computer_vision/object_classification/object_classification.cpp b/computer_vision/object_classification/object_classification.cpp index 8bdf644a..8c9a1b24 100644 --- a/computer_vision/object_classification/object_classification.cpp +++ b/computer_vision/object_classification/object_classification.cpp @@ -14,9 +14,11 @@ * 3-clause BSD license along with mlpack. If not, see * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ +#include #include #include #include +#include #include using namespace mlpack; @@ -25,6 +27,16 @@ using namespace arma; using namespace std; using namespace ens; +class Accuracy +{ + public: + template + static double Evaluate(InputType& input, OutputType& output) + { + return 3.14; + } +}; + int main() { DataLoader<> dataloader; @@ -53,7 +65,10 @@ int main() darknetModel.GetModel().Train(dataloader.TrainFeatures(), dataloader.TrainLabels(), optimizer, ens::PrintLoss(), - ens::ProgressBar(), ens::EarlyStopAtMinLoss()); + ens::ProgressBar(), ens::EarlyStopAtMinLoss(), + ens::PrintMetric, HeInitialization>, + Accuracy>(darknetModel.GetModel(), dataloader.TrainFeatures(), + "accuracy", true)); mlpack::data::Save("darknet19.bin", "darknet", darknetModel.GetModel(), false); return 0; diff --git a/models/darknet/darknet.hpp b/models/darknet/darknet.hpp index f81f5d08..7aa8a4a0 100644 --- a/models/darknet/darknet.hpp +++ b/models/darknet/darknet.hpp @@ -85,7 +85,7 @@ class DarkNet /** * DarkNet constructor intializes input shape and number of classes. - * + * * @param inputShape A three-valued tuple indicating input shape. * First value is number of Channels (Channels-First). * Second value is input height. diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index e7a48950..0eab52d3 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -3,7 +3,9 @@ project(utils) set(DIR_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/) -set(SOURCES utils.hpp) +set(SOURCES + utils.hpp + ensmallen_utils.hpp) foreach(file ${SOURCES}) set(DIR_SRCS ${DIR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/${file}) diff --git a/utils/ensmallen_utils.hpp b/utils/ensmallen_utils.hpp new file mode 100644 index 00000000..a6103ecd --- /dev/null +++ b/utils/ensmallen_utils.hpp @@ -0,0 +1,89 @@ +/** + * @file utils.hpp + * @author Kartik Dutt + * + * Definition of Ensmallen Utility functions. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ + +#ifndef ENSMALLEN_CALLBACKS_PRINT_METRIC_HPP +#define ENSMALLEN_CALLBACKS_PRINT_METRIC_HPP + +#include +#include + +namespace ens { + +/** + * Prints metric on validation set. + */ +template +class PrintMetric +{ + public: + /** + * Constructor for PrintMetric class. + */ + PrintMetric(AnnType& network, + const InputType features, + const std::string metricName = "metric", + const bool trainData = false, + std::ostream& output = arma::get_cout_stream()) : + network(network), + features(features), + metricName(metricName), + trainData(trainData), + output(output) + { + // Nothing to do here. + } + + template + bool EndEpoch(OptimizerType& /* optimizer */, + FunctionType& /* function */, + const MatType& /* coordinates */, + const size_t /* epoch */, + const double /* objective */) + { + OutputType predictions; + network.Predict(features, predictions); + const double localObjective = MetricType::Evaluate(features, predictions); + if (!std::isnan(localObjective)) + { + std::string outputString = (trainData == true) ? "train " : "validation "; + outputString = outputString + metricName + " : " + + std::to_string(localObjective); + output << outputString << std::endl; + } + return true; + } + + private: + // Reference to the model which will be used for evaluated using the metric. + AnnType& network; + + // Dataset which will be used for evaluating the metric. + InputType features; + + // Locally held string that depicts the name of the metric. + std::string metricName; + + // Locally held boolean to determin whether evaluation is done on train data or + // validation data. + bool trainData; + + // The output stream that all data is to be sent to; example: std::cout. + std::ostream& output; +}; + +} + +#endif \ No newline at end of file From 21f5c472108a26736881657ec19eabb41885b6c2 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Tue, 16 Jun 2020 13:08:53 +0530 Subject: [PATCH 11/35] Style Fix --- utils/ensmallen_utils.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/utils/ensmallen_utils.hpp b/utils/ensmallen_utils.hpp index a6103ecd..75772e98 100644 --- a/utils/ensmallen_utils.hpp +++ b/utils/ensmallen_utils.hpp @@ -76,14 +76,14 @@ class PrintMetric // Locally held string that depicts the name of the metric. std::string metricName; - // Locally held boolean to determin whether evaluation is done on train data or - // validation data. + // Locally held boolean to determin whether evaluation is done on train data + // or validation data. bool trainData; // The output stream that all data is to be sent to; example: std::cout. std::ostream& output; }; -} +} // namespace ens -#endif \ No newline at end of file +#endif From 8ff1f1738ceff121beff3e83aea28f78beff017d Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Tue, 16 Jun 2020 17:02:44 +0530 Subject: [PATCH 12/35] Add accuracy metric Add Periodic Save Add param description, rename darknetver to darknetversion, style changes, openmp cmake fix style fixes, commits also need clean up style fixes, commits also need clean up style fixes, commits also need clean up --- CMakeLists.txt | 1 + .../object_classification/CMakeLists.txt | 6 + .../object_classification.cpp | 50 +++++++-- ensmallen_utils/CMakeLists.txt | 16 +++ ensmallen_utils/periodic_save.hpp | 104 ++++++++++++++++++ .../print_metric.hpp | 36 ++++-- models/darknet/darknet.hpp | 7 +- models/darknet/darknet_impl.hpp | 36 +++--- 8 files changed, 214 insertions(+), 42 deletions(-) create mode 100644 ensmallen_utils/CMakeLists.txt create mode 100644 ensmallen_utils/periodic_save.hpp rename utils/ensmallen_utils.hpp => ensmallen_utils/print_metric.hpp (60%) diff --git a/CMakeLists.txt b/CMakeLists.txt index a5a57555..55083993 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -215,6 +215,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/) # Recurse into each model. set(DIRS utils/ + ensmallen_utils/ dataloader/ models/ tests/ diff --git a/computer_vision/object_classification/CMakeLists.txt b/computer_vision/object_classification/CMakeLists.txt index 345c9620..fbcf2779 100644 --- a/computer_vision/object_classification/CMakeLists.txt +++ b/computer_vision/object_classification/CMakeLists.txt @@ -11,6 +11,12 @@ set(SOURCES foreach(file ${SOURCES}) string( REPLACE ".cpp" "" name ${file}) add_executable(${name} ${MODEL_SOURCE_DIR}/${file}) + if (USE_OPENMP AND OPENMP_FOUND AND CMAKE_CXX_COMPILER_ID MATCHES "AppleClang") + if (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL "7.0" OR + CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "7.0") + target_link_libraries(${name} ${OpenMP_libomp_LIBRARY}) + endif() + endif() target_link_libraries(${name} ${COMPILER_SUPPORT_LIBRARIES} ${ARMADILLO_LIBRARIES} diff --git a/computer_vision/object_classification/object_classification.cpp b/computer_vision/object_classification/object_classification.cpp index 8c9a1b24..1d9838a1 100644 --- a/computer_vision/object_classification/object_classification.cpp +++ b/computer_vision/object_classification/object_classification.cpp @@ -18,7 +18,8 @@ #include #include #include -#include +#include +#include #include using namespace mlpack; @@ -33,15 +34,25 @@ class Accuracy template static double Evaluate(InputType& input, OutputType& output) { - return 3.14; + arma::Row predLabels(input.n_cols); + for (arma::uword i = 0; i < input.n_cols; ++i) + { + predLabels(i) = input.col(i).index_max() + 1; + } + return arma::accu(predLabels == output) / (double)output.n_elem * 100; } }; int main() { + #if defined(_OPENMP) + std::cout << "Compiled with OpenMP!" << std::endl; + #endif + DataLoader<> dataloader; + std::cout << "Loading Dataset!" << std::endl; - dataloader.LoadImageDatasetFromDirectory("./../data/cifar-test", + dataloader.LoadImageDatasetFromDirectory("./../data/cifar10-small/", 32, 32, 3, true, 0.2, true, {"resize : 32"}); @@ -51,24 +62,45 @@ int main() std::cout << "Model Compiled" << std::endl; constexpr double RATIO = 0.1; - constexpr size_t EPOCHS = 3; + constexpr size_t EPOCHS = 10; constexpr double STEP_SIZE = 1.2e-3; - constexpr int BATCH_SIZE = 1; + constexpr int BATCH_SIZE = 32; mlpack::data::MinMaxScaler scaler; scaler.Fit(dataloader.TrainFeatures()); scaler.Transform(dataloader.TrainFeatures(), dataloader.TrainFeatures()); + scaler.Transform(dataloader.ValidFeatures(), dataloader.ValidFeatures()); ens::Adam optimizer(STEP_SIZE, BATCH_SIZE, 0.9, 0.998, 1e-8, dataloader.TrainFeatures().n_cols * EPOCHS); + std::cout << "Optimizer Created, Starting Training!" << std::endl; darknetModel.GetModel().Train(dataloader.TrainFeatures(), - dataloader.TrainLabels(), optimizer, ens::PrintLoss(), - ens::ProgressBar(), ens::EarlyStopAtMinLoss(), + dataloader.TrainLabels(), + optimizer, + ens::PrintLoss(), + ens::ProgressBar(), + ens::EarlyStopAtMinLoss(), ens::PrintMetric, HeInitialization>, - Accuracy>(darknetModel.GetModel(), dataloader.TrainFeatures(), - "accuracy", true)); + Accuracy>( + darknetModel.GetModel(), + dataloader.TrainFeatures(), + dataloader.TrainLabels(), + "accuracy", + true), + ens::PrintMetric, HeInitialization>, + Accuracy>( + darknetModel.GetModel(), + dataloader.ValidFeatures(), + dataloader.ValidLabels(), + "accuracy", + false), + ens::PeriodicSave, HeInitialization>>( + darknetModel.GetModel(), + "./../weights/", + "darknet19", 1)); + mlpack::data::Save("darknet19.bin", "darknet", darknetModel.GetModel(), false); return 0; diff --git a/ensmallen_utils/CMakeLists.txt b/ensmallen_utils/CMakeLists.txt new file mode 100644 index 00000000..ded5df9b --- /dev/null +++ b/ensmallen_utils/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) +project(ensmallen_utils) + +set(DIR_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/) + +set(SOURCES + print_metric.hpp + periodic_save.hpp) + +foreach(file ${SOURCES}) + set(DIR_SRCS ${DIR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/${file}) +endforeach() + +# Append sources (with directory name) to list of all models sources (used at +# the parent scope). +set(DIRS ${DIRS} ${DIR_SRCS} PARENT_SCOPE) \ No newline at end of file diff --git a/ensmallen_utils/periodic_save.hpp b/ensmallen_utils/periodic_save.hpp new file mode 100644 index 00000000..067db076 --- /dev/null +++ b/ensmallen_utils/periodic_save.hpp @@ -0,0 +1,104 @@ +/** + * @file utils.hpp + * @author Kartik Dutt + * + * Definition of Periodic Save utility functions. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ + +#ifndef ENSMALLEN_CALLBACKS_PERIODIC_SAVE_HPP +#define ENSMALLEN_CALLBACKS_PERIODIC_SAVE_HPP + +#include +#include + +namespace ens { + +/** + * Saves model being trained periodically. + * + * @tparam ANNType Type of model which will be used for evaluating metric. + */ +template +class PeriodicSave +{ + public: + /** + * Constructor for PeriodicSave class. + * + * @param network Network type which will be saved periodically. + * @param filePath Base path / folder where weights will be saved. + * @param modelPrefix Weights will be stored as + * modelPrefix_epoch_loss.bin. + * @param period Period after which the model will be saved. + * @param silent Boolean to determine whether or not to print saving + * of model. + * @param output Outputstream where output will be directed. + */ + PeriodicSave(AnnType& network, + const std::string filePath = "./", + const std::string modelPrefix = "model", + const size_t period = 1, + const bool silent = false, + std::ostream& output = arma::get_cout_stream()) : + network(network), + filePath(filePath), + modelPrefix(modelPrefix), + period(period), + silent(silent), + output(output) + { + // Nothing to do here. + } + + template + bool EndEpoch(OptimizerType& /* optimizer */, + FunctionType& /* function */, + const MatType& /* coordinates */, + const size_t epoch, + const double objective) + { + if (epoch % period == 0) + { + std::string objectiveString = std::to_string(objective); + std::replace(objectiveString.begin(), objectiveString.end(), '.', '_'); + std::string modelName = modelPrefix + "_" + std::to_string(epoch) + "_" + + objectiveString; + mlpack::data::Save(filePath + modelName + ".bin", modelPrefix, network); + if (!silent) + { + output << "Model saved as " << modelName << std::endl; + } + } + + return false; + } + + private: + // Reference to the model which will be used for evaluated using the metric. + AnnType& network; + + // Locally held string that depicts path for saving the model. + std::string filePath; + + // Locally held string that depicts the prefix name of model being trained. + std::string modelPrefix; + + // Period to save the model. + size_t period; + + // Locally held boolean to determine whether to print success / failure output + // when model is saved. + bool silent; + + // The output stream that all data is to be sent to; example: std::cout. + std::ostream& output; +}; + +} // namespace ens + +#endif diff --git a/utils/ensmallen_utils.hpp b/ensmallen_utils/print_metric.hpp similarity index 60% rename from utils/ensmallen_utils.hpp rename to ensmallen_utils/print_metric.hpp index 75772e98..5c0c98e6 100644 --- a/utils/ensmallen_utils.hpp +++ b/ensmallen_utils/print_metric.hpp @@ -2,7 +2,7 @@ * @file utils.hpp * @author Kartik Dutt * - * Definition of Ensmallen Utility functions. + * Definition of PrintMetric class. * * mlpack is free software; you may redistribute it and/or modify it under the * terms of the 3-clause BSD license. You should have received a copy of the @@ -19,7 +19,13 @@ namespace ens { /** - * Prints metric on validation set. + * Prints metric on training / validation set. + * + * @tparam ANNType Type of model which will be used for evaluating metric. + * @tparam MetricType Metric class which must have static `Evaluate` function + * that will be called at the end of the epoch. + * @tparam InputType Arma type of dataset features. + * @tparam OutputType Arma type of dataset labels. */ template @@ -55,15 +70,15 @@ class PrintMetric { OutputType predictions; network.Predict(features, predictions); - const double localObjective = MetricType::Evaluate(features, predictions); + const double localObjective = MetricType::Evaluate(predictions, responses); if (!std::isnan(localObjective)) { - std::string outputString = (trainData == true) ? "train " : "validation "; + std::string outputString = (trainData == true) ? "Train " : "Validation "; outputString = outputString + metricName + " : " + std::to_string(localObjective); output << outputString << std::endl; } - return true; + return false; } private: @@ -73,6 +88,9 @@ class PrintMetric // Dataset which will be used for evaluating the metric. InputType features; + // Dataset labels / predictions that will be used for evaluating the dataset. + OutputType responses; + // Locally held string that depicts the name of the metric. std::string metricName; diff --git a/models/darknet/darknet.hpp b/models/darknet/darknet.hpp index 7aa8a4a0..df91ec4d 100644 --- a/models/darknet/darknet.hpp +++ b/models/darknet/darknet.hpp @@ -57,7 +57,7 @@ namespace ann /** Artificial Neural Network. */{ template< typename OutputLayerType = NegativeLogLikelihood<>, typename InitializationRuleType = HeInitialization, - size_t DarkNetVer = 19 + size_t DarkNetVersion = 19 > class DarkNet { @@ -169,8 +169,6 @@ class DarkNet { darkNet.Add(bottleNeck); } - - return; } /** @@ -202,7 +200,6 @@ class DarkNet inputHeight = std::ceil(inputHeight * 1.0 / factor); std::cout << "(" << inputWidth << ", " << inputHeight << ")" << std::endl; - return; } /** @@ -238,7 +235,6 @@ class DarkNet block); darkNet.Add(block); - return; } /** @@ -264,7 +260,6 @@ class DarkNet kernelHeight, 1, 1, padWidth, padWidth, true, residualBlock); darkNet.Add(residualBlock); std::cout << "Residual Block end." << std::endl; - return; } /** diff --git a/models/darknet/darknet_impl.hpp b/models/darknet/darknet_impl.hpp index 3396ccc4..4f29f818 100644 --- a/models/darknet/darknet_impl.hpp +++ b/models/darknet/darknet_impl.hpp @@ -20,9 +20,9 @@ namespace ann { template< typename OutputLayerType, typename InitializationRuleType, - size_t DarkNetVer + size_t DarkNetVersion > -DarkNet::DarkNet() : +DarkNet::DarkNet() : inputChannel(0), inputWidth(0), inputHeight(0), @@ -35,16 +35,16 @@ DarkNet::DarkNet() : template< typename OutputLayerType, typename InitializationRuleType, - size_t DarkNetVer + size_t DarkNetVersion > -DarkNet::DarkNet( +DarkNet::DarkNet( const size_t inputChannel, const size_t inputWidth, const size_t inputHeight, const size_t numClasses, const std::string& weights, const bool includeTop) : - DarkNet( + DarkNet( std::tuple( inputChannel, inputWidth, @@ -59,9 +59,9 @@ DarkNet::DarkNet( template< typename OutputLayerType, typename InitializationRuleType, - size_t DarkNetVer + size_t DarkNetVersion > -DarkNet::DarkNet( +DarkNet::DarkNet( const std::tuple inputShape, const size_t numClasses, const std::string& weights, @@ -72,14 +72,14 @@ DarkNet::DarkNet( numClasses(numClasses), weights(weights) { - mlpack::Log::Assert(DarkNetVer == 19 || DarkNetVer == 53, + mlpack::Log::Assert(DarkNetVersion == 19 || DarkNetVersion == 53, "Incorrect DarkNet version. Possible values are 19 and 53. Trying \ - to find version : " + std::to_string(DarkNetVer) + "."); + to find version : " + std::to_string(DarkNetVersion) + "."); if (weights == "cifar10") { // Download weights here. - LoadModel("./../weights/darknet/darknet" + std::to_string(DarkNetVer) + + LoadModel("./../weights/darknet/darknet" + std::to_string(DarkNetVersion) + "_cifar10.bin"); return; } @@ -89,7 +89,7 @@ DarkNet::DarkNet( return; } - if (DarkNetVer == 19) + if (DarkNetVersion == 19) { darkNet.Add(new IdentityLayer<>()); @@ -121,7 +121,7 @@ DarkNet::DarkNet( darkNet.ResetParameters(); } - else if (DarkNetVer == 53) + else if (DarkNetVersion == 53) { darkNet.Add(new IdentityLayer<>()); ConvolutionBlock(inputChannel, 32, 3, 3, 1, 1, 1, 1, true); @@ -158,27 +158,27 @@ DarkNet::DarkNet( template< typename OutputLayerType, typename InitializationRuleType, - size_t DarkNetVer + size_t DarkNetVersion > void DarkNet< - OutputLayerType, InitializationRuleType, DarkNetVer + OutputLayerType, InitializationRuleType, DarkNetVersion >::LoadModel(const std::string& filePath) { - data::Load(filePath, "DarkNet" + std::to_string(DarkNetVer), darkNet); + data::Load(filePath, "DarkNet" + std::to_string(DarkNetVersion), darkNet); Log::Info << "Loaded model" << std::endl; } template< typename OutputLayerType, typename InitializationRuleType, - size_t DarkNetVer + size_t DarkNetVersion > void DarkNet< - OutputLayerType, InitializationRuleType, DarkNetVer + OutputLayerType, InitializationRuleType, DarkNetVersion >::SaveModel(const std::string& filePath) { Log::Info<< "Saving model." << std::endl; - data::Save(filePath, "DarkNet" + std::to_string(DarkNetVer), darkNet); + data::Save(filePath, "DarkNet" + std::to_string(DarkNetVersion), darkNet); Log::Info << "Model saved in " << filePath << "." << std::endl; } From 6ccb359caae1dbc03e238be259c6cd3032e8c950 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Sun, 21 Jun 2020 13:16:10 +0530 Subject: [PATCH 13/35] Some changes --- .gitignore | 1 + .../object_classification.cpp | 17 +++++++++------- models/darknet/darknet.hpp | 20 ++++++++++--------- models/darknet/darknet_impl.hpp | 9 +++++---- 4 files changed, 27 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index 6fc3b1f2..4708e5bb 100644 --- a/.gitignore +++ b/.gitignore @@ -13,5 +13,6 @@ data/* *.jpg *.png *.txt +*.bin .travis/configs.hpp Testing/* diff --git a/computer_vision/object_classification/object_classification.cpp b/computer_vision/object_classification/object_classification.cpp index 1d9838a1..08295e93 100644 --- a/computer_vision/object_classification/object_classification.cpp +++ b/computer_vision/object_classification/object_classification.cpp @@ -51,6 +51,9 @@ int main() DataLoader<> dataloader; + // Utils::DownloadFile("/datasets/cifar10.tar.gz", + // "./../data/cifar10.tar.gz", "", false, true, + // "www.mlpack.org", true); std::cout << "Loading Dataset!" << std::endl; dataloader.LoadImageDatasetFromDirectory("./../data/cifar10-small/", 32, 32, 3, true, 0.2, true, @@ -62,16 +65,16 @@ int main() std::cout << "Model Compiled" << std::endl; constexpr double RATIO = 0.1; - constexpr size_t EPOCHS = 10; - constexpr double STEP_SIZE = 1.2e-3; - constexpr int BATCH_SIZE = 32; + constexpr size_t EPOCHS = 5; + constexpr double STEP_SIZE = 0.001; + constexpr int BATCH_SIZE = 8; mlpack::data::MinMaxScaler scaler; scaler.Fit(dataloader.TrainFeatures()); scaler.Transform(dataloader.TrainFeatures(), dataloader.TrainFeatures()); scaler.Transform(dataloader.ValidFeatures(), dataloader.ValidFeatures()); - ens::Adam optimizer(STEP_SIZE, BATCH_SIZE, 0.9, 0.998, 1e-8, + ens::Adam optimizer(STEP_SIZE, BATCH_SIZE, 0.9, 0.995, 1e-8, dataloader.TrainFeatures().n_cols * EPOCHS); std::cout << "Optimizer Created, Starting Training!" << std::endl; @@ -82,21 +85,21 @@ int main() ens::PrintLoss(), ens::ProgressBar(), ens::EarlyStopAtMinLoss(), - ens::PrintMetric, HeInitialization>, + ens::PrintMetric, RandomInitialization>, Accuracy>( darknetModel.GetModel(), dataloader.TrainFeatures(), dataloader.TrainLabels(), "accuracy", true), - ens::PrintMetric, HeInitialization>, + ens::PrintMetric, RandomInitialization>, Accuracy>( darknetModel.GetModel(), dataloader.ValidFeatures(), dataloader.ValidLabels(), "accuracy", false), - ens::PeriodicSave, HeInitialization>>( + ens::PeriodicSave, RandomInitialization>>( darknetModel.GetModel(), "./../weights/", "darknet19", 1)); diff --git a/models/darknet/darknet.hpp b/models/darknet/darknet.hpp index df91ec4d..60af2359 100644 --- a/models/darknet/darknet.hpp +++ b/models/darknet/darknet.hpp @@ -43,6 +43,7 @@ #include #include #include +#include namespace mlpack { namespace ann /** Artificial Neural Network. */{ @@ -56,7 +57,7 @@ namespace ann /** Artificial Neural Network. */{ */ template< typename OutputLayerType = NegativeLogLikelihood<>, - typename InitializationRuleType = HeInitialization, + typename InitializationRuleType = RandomInitialization, size_t DarkNetVersion = 19 > class DarkNet @@ -144,12 +145,6 @@ class DarkNet bottleNeck->Add(new Convolution<>(inSize, outSize, kernelWidth, kernelHeight, strideWidth, strideHeight, padW, padH, inputWidth, inputHeight)); - if (batchNorm) - { - bottleNeck->Add(new BatchNorm<>(outSize)); - } - - bottleNeck->Add(new LeakyReLU<>()); // Update inputWidth and input Height. std::cout << "Conv Layer. "; @@ -161,6 +156,13 @@ class DarkNet std::cout << "(" << inputWidth << ", " << inputHeight << ", " << outSize << ")" << std::endl; + if (batchNorm) + { + bottleNeck->Add(new BatchNorm<>(outSize * inputWidth * inputHeight)); + } + + bottleNeck->Add(new LeakyReLU<>()); + if (baseLayer != NULL) { baseLayer->Add(bottleNeck); @@ -226,12 +228,12 @@ class DarkNet { Sequential<>* block = new Sequential<>(); ConvolutionBlock(inputChannel, inputChannel * 2, - kernelWidth, kernelHeight, 1, 1, padWidth, padHeight, false, + kernelWidth, kernelHeight, 1, 1, padWidth, padHeight, true, block); ConvolutionBlock(inputChannel * 2, inputChannel, 1, 1, 1, 1, 0, 0, false, block); ConvolutionBlock(inputChannel, inputChannel * 2, - kernelWidth, kernelHeight, 1, 1, padWidth, padHeight, false, + kernelWidth, kernelHeight, 1, 1, padWidth, padHeight, true, block); darkNet.Add(block); diff --git a/models/darknet/darknet_impl.hpp b/models/darknet/darknet_impl.hpp index 4f29f818..8847ab03 100644 --- a/models/darknet/darknet_impl.hpp +++ b/models/darknet/darknet_impl.hpp @@ -96,7 +96,7 @@ DarkNet::DarkNet( // Convolution and activation function in a block. ConvolutionBlock(inputChannel, 32, 3, 3, 1, 1, 1, 1); PoolingBlock(); - ConvolutionBlock(32, 64, 3, 3, 1, 1, 1, 1); + ConvolutionBlock(32, 64, 3, 3, 1, 1, 1, 1, true); PoolingBlock(); DarkNet19SequentialBlock(64, 3, 3, 1, 1); PoolingBlock(); @@ -104,17 +104,18 @@ DarkNet::DarkNet( PoolingBlock(); DarkNet19SequentialBlock(256, 3, 3, 1, 1); ConvolutionBlock(512, 256, 1, 1, 1, 1); - ConvolutionBlock(256, 512, 3, 3, 1, 1, 1, 1); + ConvolutionBlock(256, 512, 3, 3, 1, 1, 1, 1, true); PoolingBlock(); DarkNet19SequentialBlock(512, 3, 3, 1, 1); ConvolutionBlock(1024, 512, 1, 1, 1, 1); - ConvolutionBlock(512, 1024, 3, 3, 1, 1, 1, 1); + ConvolutionBlock(512, 1024, 3, 3, 1, 1, 1, 1, true); ConvolutionBlock(1024, 1000, 1, 1, 1, 1); darkNet.Add(new AdaptiveMeanPooling<>(1, 1)); if (includeTop) { + darkNet.Add(new BatchNorm<>(1000)); darkNet.Add(new Linear<>(1000, numClasses)); darkNet.Add(new LogSoftMax<>()); } @@ -185,4 +186,4 @@ void DarkNet< } // namespace ann } // namespace mlpack -#endif +#endif \ No newline at end of file From bf2abd92c327b51b082672649afbba6a399b7ed9 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Mon, 22 Jun 2020 15:49:23 +0530 Subject: [PATCH 14/35] Attempt to load weights --- .../object_classification/CMakeLists.txt | 1 + .../object_classification.cpp | 5 +- .../weight_converter.cpp | 65 +++++++++++++++++++ 3 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 computer_vision/object_classification/weight_converter.cpp diff --git a/computer_vision/object_classification/CMakeLists.txt b/computer_vision/object_classification/CMakeLists.txt index fbcf2779..486ff2a7 100644 --- a/computer_vision/object_classification/CMakeLists.txt +++ b/computer_vision/object_classification/CMakeLists.txt @@ -6,6 +6,7 @@ include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../../") set(SOURCES object_classification.cpp + weight_converter.cpp ) foreach(file ${SOURCES}) diff --git a/computer_vision/object_classification/object_classification.cpp b/computer_vision/object_classification/object_classification.cpp index 08295e93..39934316 100644 --- a/computer_vision/object_classification/object_classification.cpp +++ b/computer_vision/object_classification/object_classification.cpp @@ -56,8 +56,7 @@ int main() // "www.mlpack.org", true); std::cout << "Loading Dataset!" << std::endl; dataloader.LoadImageDatasetFromDirectory("./../data/cifar10-small/", - 32, 32, 3, true, 0.2, true, - {"resize : 32"}); + 32, 32, 3, true, 0.2, true); std::cout << "Dataset Loaded!" << std::endl; dataloader.TrainLabels() = dataloader.TrainLabels() + 1; @@ -67,7 +66,7 @@ int main() constexpr double RATIO = 0.1; constexpr size_t EPOCHS = 5; constexpr double STEP_SIZE = 0.001; - constexpr int BATCH_SIZE = 8; + constexpr int BATCH_SIZE = 1; mlpack::data::MinMaxScaler scaler; scaler.Fit(dataloader.TrainFeatures()); diff --git a/computer_vision/object_classification/weight_converter.cpp b/computer_vision/object_classification/weight_converter.cpp new file mode 100644 index 00000000..594180b6 --- /dev/null +++ b/computer_vision/object_classification/weight_converter.cpp @@ -0,0 +1,65 @@ +/** + * @file object_classification.hpp + * @author Kartik Dutt + * + * Contains implementation of object classification suite. It can be used + * to select object classification model, it's parameter dataset and + * other training parameters. + * + * NOTE: This code needs to be adapted as this implementation doesn't support + * Command Line Arguments. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ +#include +#include +#include +#include +#include +#include +#include + +using namespace mlpack; +using namespace mlpack::ann; +using namespace arma; +using namespace std; +using namespace ens; + +class Accuracy +{ + public: + template + static double Evaluate(InputType& input, OutputType& output) + { + arma::Row predLabels(input.n_cols); + for (arma::uword i = 0; i < input.n_cols; ++i) + { + predLabels(i) = input.col(i).index_max() + 1; + } + return arma::accu(predLabels == output) / (double)output.n_elem * 100; + } +}; + +struct output : public boost::static_visitor<> +{ + template + void operator()(T t) const { std::cout<< t->Parameters().n_cols << '\n'; } +}; + +int main() +{ + #if defined(_OPENMP) + std::cout << "Compiled with OpenMP!" << std::endl; + #endif + + DarkNet<> darknetModel(3, 32, 32, 10); + std::cout << "Model Compiled" << std::endl; + + boost::apply_visitor(output{}, darknetModel.GetModel().Model()[0]); + //std::cout << boost::get *>(darknetModel.GetModel().Model()[0])->Parameters().n_rows << std::endl; + + return 0; +} From 6010bbe58595cb014af340f97e45d5e7d5929fe0 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Mon, 22 Jun 2020 17:22:26 +0530 Subject: [PATCH 15/35] Ahh, make shift model summary can be from this --- .../weight_converter.cpp | 33 ++++++++----------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/computer_vision/object_classification/weight_converter.cpp b/computer_vision/object_classification/weight_converter.cpp index 594180b6..b8f2ca47 100644 --- a/computer_vision/object_classification/weight_converter.cpp +++ b/computer_vision/object_classification/weight_converter.cpp @@ -21,6 +21,7 @@ #include #include #include +#include using namespace mlpack; using namespace mlpack::ann; @@ -28,25 +29,16 @@ using namespace arma; using namespace std; using namespace ens; -class Accuracy -{ - public: - template - static double Evaluate(InputType& input, OutputType& output) - { - arma::Row predLabels(input.n_cols); - for (arma::uword i = 0; i < input.n_cols; ++i) - { - predLabels(i) = input.col(i).index_max() + 1; - } - return arma::accu(predLabels == output) / (double)output.n_elem * 100; - } -}; - struct output : public boost::static_visitor<> { template - void operator()(T t) const { std::cout<< t->Parameters().n_cols << '\n'; } + void operator()(T t) const + { + // We could use this as a summary. + LayerNameVisitor a1; + std::cout << a1.LayerString(&t) << std::endl; + return; + } }; int main() @@ -55,11 +47,14 @@ int main() std::cout << "Compiled with OpenMP!" << std::endl; #endif - DarkNet<> darknetModel(3, 32, 32, 10); + DarkNet<> darknetModel(3, 32, 32, 10, "none", true); std::cout << "Model Compiled" << std::endl; + for (int i = 0; i < darknetModel.GetModel().Model().size(); i++) + { + cout << i << " : "; + boost::apply_visitor(output{}, darknetModel.GetModel().Model()[i]); + } - boost::apply_visitor(output{}, darknetModel.GetModel().Model()[0]); //std::cout << boost::get *>(darknetModel.GetModel().Model()[0])->Parameters().n_rows << std::endl; - return 0; } From fa58f33ebac8257032736653b766c72a7e10dc14 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Tue, 23 Jun 2020 13:01:25 +0530 Subject: [PATCH 16/35] Weight Transfer PoC --- .../weight_converter.cpp | 55 +++++++++++++++++-- models/darknet/darknet_impl.hpp | 7 +-- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/computer_vision/object_classification/weight_converter.cpp b/computer_vision/object_classification/weight_converter.cpp index b8f2ca47..40220a0f 100644 --- a/computer_vision/object_classification/weight_converter.cpp +++ b/computer_vision/object_classification/weight_converter.cpp @@ -36,25 +36,68 @@ struct output : public boost::static_visitor<> { // We could use this as a summary. LayerNameVisitor a1; + t.Parameters(); std::cout << a1.LayerString(&t) << std::endl; return; } }; +/** + * std::cout << boost::get *>( + * darknetModel.GetModel().Model()[3])->Parameters().n_elem << std::endl; + */ int main() { #if defined(_OPENMP) std::cout << "Compiled with OpenMP!" << std::endl; #endif - - DarkNet<> darknetModel(3, 32, 32, 10, "none", true); + DarkNet<> darknetModel(3, 224, 224, 1000, "none", true); std::cout << "Model Compiled" << std::endl; - for (int i = 0; i < darknetModel.GetModel().Model().size(); i++) + + // std::cout << darknetModel.GetModel().Parameters().n_rows << " " << + // darknetModel.GetModel().Parameters().n_cols << std::endl; + + size_t outSize = 32; + Convolution<> *layer = new Convolution<>(3, 32, 3, 3, 1, 1, 1, 1, 224, 224); + // std::cout << layer->Parameters().n_elem << std::endl; + size_t layerElement = layer->Parameters().n_elem - outSize; + + // This will be equal to output size for conv layers. + // In darknet model bias term is removed. + size_t offset = 0; + size_t biasOffset = outSize; + + arma::mat ConvWeights; + mlpack::data::Load("../../PyTorch-mlpack-DarkNet-Weight-Converter/conv_1_1.csv", + ConvWeights); + // Transpose weights to match FFN Class. + ConvWeights = ConvWeights.t(); + std::cout << ConvWeights.n_rows << " " << ConvWeights.n_cols << std::endl; + + darknetModel.GetModel().Parameters()(arma::span(offset, offset + layerElement - 1), + arma::span()) = ConvWeights; + + + bool weightsEqual = true; + for (size_t i = offset; i < offset + layerElement; i++) + { + if (darknetModel.GetModel().Parameters()(i) != ConvWeights(i - offset)) + { + weightsEqual = false; + break; + } + } + + if (weightsEqual) + { + std::cout << "Yay!, Transferred weights" << std::endl; + } + else { - cout << i << " : "; - boost::apply_visitor(output{}, darknetModel.GetModel().Model()[i]); + std::cout << "Hmm, Looks like you missed something!" << std::endl; } - //std::cout << boost::get *>(darknetModel.GetModel().Model()[0])->Parameters().n_rows << std::endl; + offset = offset + layerElement + biasOffset; + biasOffset = 0; return 0; } diff --git a/models/darknet/darknet_impl.hpp b/models/darknet/darknet_impl.hpp index 8847ab03..bb09b581 100644 --- a/models/darknet/darknet_impl.hpp +++ b/models/darknet/darknet_impl.hpp @@ -109,14 +109,12 @@ DarkNet::DarkNet( DarkNet19SequentialBlock(512, 3, 3, 1, 1); ConvolutionBlock(1024, 512, 1, 1, 1, 1); ConvolutionBlock(512, 1024, 3, 3, 1, 1, 1, 1, true); - ConvolutionBlock(1024, 1000, 1, 1, 1, 1); - + darkNet.Add(new Convolution<>(1024, numClasses, 1, 1, + 1, 1, 0, 0, inputWidth, inputHeight)); darkNet.Add(new AdaptiveMeanPooling<>(1, 1)); if (includeTop) { - darkNet.Add(new BatchNorm<>(1000)); - darkNet.Add(new Linear<>(1000, numClasses)); darkNet.Add(new LogSoftMax<>()); } @@ -148,7 +146,6 @@ DarkNet::DarkNet( numClasses)); if (includeTop) { - darkNet.Add(new Linear<>(1000, numClasses)); darkNet.Add(new LogSoftMax<>()); } From 1b99b330ee3472dded7d7645c73d6375e4935917 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Wed, 24 Jun 2020 11:27:52 +0530 Subject: [PATCH 17/35] Layer Access --- .../object_classification/object_classification.cpp | 10 ++++------ .../object_classification/weight_converter.cpp | 3 +++ models/darknet/darknet.hpp | 2 +- models/darknet/darknet_impl.hpp | 8 ++++---- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/computer_vision/object_classification/object_classification.cpp b/computer_vision/object_classification/object_classification.cpp index 39934316..47ad8bde 100644 --- a/computer_vision/object_classification/object_classification.cpp +++ b/computer_vision/object_classification/object_classification.cpp @@ -55,12 +55,12 @@ int main() // "./../data/cifar10.tar.gz", "", false, true, // "www.mlpack.org", true); std::cout << "Loading Dataset!" << std::endl; - dataloader.LoadImageDatasetFromDirectory("./../data/cifar10-small/", - 32, 32, 3, true, 0.2, true); + dataloader.LoadImageDatasetFromDirectory("./../data/cifar-test/", + 32, 32, 3, true, 0.2, true, {"resize : 224"}); std::cout << "Dataset Loaded!" << std::endl; dataloader.TrainLabels() = dataloader.TrainLabels() + 1; - DarkNet<> darknetModel(3, 32, 32, 10); + DarkNet<> darknetModel(3, 224, 224, 10); std::cout << "Model Compiled" << std::endl; constexpr double RATIO = 0.1; @@ -69,9 +69,7 @@ int main() constexpr int BATCH_SIZE = 1; mlpack::data::MinMaxScaler scaler; - scaler.Fit(dataloader.TrainFeatures()); - scaler.Transform(dataloader.TrainFeatures(), dataloader.TrainFeatures()); - scaler.Transform(dataloader.ValidFeatures(), dataloader.ValidFeatures()); + ens::Adam optimizer(STEP_SIZE, BATCH_SIZE, 0.9, 0.995, 1e-8, dataloader.TrainFeatures().n_cols * EPOCHS); diff --git a/computer_vision/object_classification/weight_converter.cpp b/computer_vision/object_classification/weight_converter.cpp index 40220a0f..ad6d317f 100644 --- a/computer_vision/object_classification/weight_converter.cpp +++ b/computer_vision/object_classification/weight_converter.cpp @@ -99,5 +99,8 @@ int main() offset = offset + layerElement + biasOffset; biasOffset = 0; + + BatchNorm<>* layer2 = new BatchNorm<>(32); + std::cout << layer2->Parameters().n_elem << std::endl; return 0; } diff --git a/models/darknet/darknet.hpp b/models/darknet/darknet.hpp index 60af2359..fb081c7a 100644 --- a/models/darknet/darknet.hpp +++ b/models/darknet/darknet.hpp @@ -158,7 +158,7 @@ class DarkNet if (batchNorm) { - bottleNeck->Add(new BatchNorm<>(outSize * inputWidth * inputHeight)); + bottleNeck->Add(new BatchNorm<>(inputWidth)); } bottleNeck->Add(new LeakyReLU<>()); diff --git a/models/darknet/darknet_impl.hpp b/models/darknet/darknet_impl.hpp index bb09b581..e2a94ce2 100644 --- a/models/darknet/darknet_impl.hpp +++ b/models/darknet/darknet_impl.hpp @@ -94,7 +94,7 @@ DarkNet::DarkNet( darkNet.Add(new IdentityLayer<>()); // Convolution and activation function in a block. - ConvolutionBlock(inputChannel, 32, 3, 3, 1, 1, 1, 1); + ConvolutionBlock(inputChannel, 32, 3, 3, 1, 1, 1, 1, true); PoolingBlock(); ConvolutionBlock(32, 64, 3, 3, 1, 1, 1, 1, true); PoolingBlock(); @@ -109,12 +109,12 @@ DarkNet::DarkNet( DarkNet19SequentialBlock(512, 3, 3, 1, 1); ConvolutionBlock(1024, 512, 1, 1, 1, 1); ConvolutionBlock(512, 1024, 3, 3, 1, 1, 1, 1, true); - darkNet.Add(new Convolution<>(1024, numClasses, 1, 1, - 1, 1, 0, 0, inputWidth, inputHeight)); - darkNet.Add(new AdaptiveMeanPooling<>(1, 1)); if (includeTop) { + darkNet.Add(new Convolution<>(1024, numClasses, 1, 1, + 1, 1, 0, 0, inputWidth, inputHeight)); + darkNet.Add(new AdaptiveMeanPooling<>(1, 1)); darkNet.Add(new LogSoftMax<>()); } From 761edd9216d9158de2a03ba788d02e7f42f0b0dd Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Thu, 9 Jul 2020 08:55:57 +0530 Subject: [PATCH 18/35] Style Fixes --- computer_vision/object_classification/CMakeLists.txt | 2 +- models/darknet/darknet.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/computer_vision/object_classification/CMakeLists.txt b/computer_vision/object_classification/CMakeLists.txt index 486ff2a7..256771d7 100644 --- a/computer_vision/object_classification/CMakeLists.txt +++ b/computer_vision/object_classification/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) - project(object_classification) +project(object_classification) set(MODEL_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/) include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../../") diff --git a/models/darknet/darknet.hpp b/models/darknet/darknet.hpp index fb081c7a..8d79f4d8 100644 --- a/models/darknet/darknet.hpp +++ b/models/darknet/darknet.hpp @@ -158,7 +158,7 @@ class DarkNet if (batchNorm) { - bottleNeck->Add(new BatchNorm<>(inputWidth)); + bottleNeck->Add(new BatchNorm<>(outSize, 1e-8, false)); } bottleNeck->Add(new LeakyReLU<>()); From ac81ca1e5847afa8b85951a7fbba6d98040ce201 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Sat, 11 Jul 2020 11:59:53 +0530 Subject: [PATCH 19/35] Some changes --- .../object_classification/object_classification.cpp | 10 +++++----- models/darknet/darknet.hpp | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/computer_vision/object_classification/object_classification.cpp b/computer_vision/object_classification/object_classification.cpp index 47ad8bde..ba6502fa 100644 --- a/computer_vision/object_classification/object_classification.cpp +++ b/computer_vision/object_classification/object_classification.cpp @@ -55,18 +55,18 @@ int main() // "./../data/cifar10.tar.gz", "", false, true, // "www.mlpack.org", true); std::cout << "Loading Dataset!" << std::endl; - dataloader.LoadImageDatasetFromDirectory("./../data/cifar-test/", - 32, 32, 3, true, 0.2, true, {"resize : 224"}); + dataloader.LoadImageDatasetFromDirectory("./../data/cifar10-small/", + 32, 32, 3, true, 0.2, true, {"resize : 32"}); std::cout << "Dataset Loaded!" << std::endl; dataloader.TrainLabels() = dataloader.TrainLabels() + 1; - DarkNet<> darknetModel(3, 224, 224, 10); + DarkNet<> darknetModel(3, 32, 32, 10); std::cout << "Model Compiled" << std::endl; constexpr double RATIO = 0.1; constexpr size_t EPOCHS = 5; - constexpr double STEP_SIZE = 0.001; - constexpr int BATCH_SIZE = 1; + constexpr double STEP_SIZE = 0.1; + constexpr int BATCH_SIZE = 256; mlpack::data::MinMaxScaler scaler; diff --git a/models/darknet/darknet.hpp b/models/darknet/darknet.hpp index 8d79f4d8..0ab76886 100644 --- a/models/darknet/darknet.hpp +++ b/models/darknet/darknet.hpp @@ -138,7 +138,7 @@ class DarkNet const size_t strideHeight = 1, const size_t padW = 0, const size_t padH = 0, - const bool batchNorm = false, + const bool batchNorm = true, SequentialType* baseLayer = NULL) { Sequential<>* bottleNeck = new Sequential<>(); From 949d512056478c88c8436c4c3a56010a37790e8e Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Sat, 18 Jul 2020 13:07:21 +0530 Subject: [PATCH 20/35] Add models.hpp so that single file imported in weight converter --- .../object_classification.cpp | 22 +++--- .../weight_converter.cpp | 75 +------------------ models/CMakeLists.txt | 1 + models/darknet/darknet_impl.hpp | 2 +- models/models.hpp | 8 ++ 5 files changed, 26 insertions(+), 82 deletions(-) create mode 100644 models/models.hpp diff --git a/computer_vision/object_classification/object_classification.cpp b/computer_vision/object_classification/object_classification.cpp index ba6502fa..3b7686dd 100644 --- a/computer_vision/object_classification/object_classification.cpp +++ b/computer_vision/object_classification/object_classification.cpp @@ -56,23 +56,27 @@ int main() // "www.mlpack.org", true); std::cout << "Loading Dataset!" << std::endl; dataloader.LoadImageDatasetFromDirectory("./../data/cifar10-small/", - 32, 32, 3, true, 0.2, true, {"resize : 32"}); + 32, 32, 3, true, 0.2, true, {"resize : 56"}); std::cout << "Dataset Loaded!" << std::endl; dataloader.TrainLabels() = dataloader.TrainLabels() + 1; - DarkNet<> darknetModel(3, 32, 32, 10); + DarkNet, + mlpack::ann::XavierInitialization, 19> darknetModel(3, 56, 56, 10); std::cout << "Model Compiled" << std::endl; constexpr double RATIO = 0.1; constexpr size_t EPOCHS = 5; - constexpr double STEP_SIZE = 0.1; - constexpr int BATCH_SIZE = 256; + constexpr double STEP_SIZE = 0.001; + constexpr int BATCH_SIZE = 8; mlpack::data::MinMaxScaler scaler; - ens::Adam optimizer(STEP_SIZE, BATCH_SIZE, 0.9, 0.995, 1e-8, - dataloader.TrainFeatures().n_cols * EPOCHS); + SGD optimizer(STEP_SIZE, BATCH_SIZE, + dataloader.TrainLabels().n_cols * EPOCHS, + 1e-8, + true, + AdamUpdate(1e-8, 0.9, 0.999)); std::cout << "Optimizer Created, Starting Training!" << std::endl; @@ -82,21 +86,21 @@ int main() ens::PrintLoss(), ens::ProgressBar(), ens::EarlyStopAtMinLoss(), - ens::PrintMetric, RandomInitialization>, + ens::PrintMetric, XavierInitialization>, Accuracy>( darknetModel.GetModel(), dataloader.TrainFeatures(), dataloader.TrainLabels(), "accuracy", true), - ens::PrintMetric, RandomInitialization>, + ens::PrintMetric, XavierInitialization>, Accuracy>( darknetModel.GetModel(), dataloader.ValidFeatures(), dataloader.ValidLabels(), "accuracy", false), - ens::PeriodicSave, RandomInitialization>>( + ens::PeriodicSave, XavierInitialization>>( darknetModel.GetModel(), "./../weights/", "darknet19", 1)); diff --git a/computer_vision/object_classification/weight_converter.cpp b/computer_vision/object_classification/weight_converter.cpp index ad6d317f..3be1729a 100644 --- a/computer_vision/object_classification/weight_converter.cpp +++ b/computer_vision/object_classification/weight_converter.cpp @@ -16,7 +16,7 @@ */ #include #include -#include +#include #include #include #include @@ -29,78 +29,9 @@ using namespace arma; using namespace std; using namespace ens; -struct output : public boost::static_visitor<> -{ - template - void operator()(T t) const - { - // We could use this as a summary. - LayerNameVisitor a1; - t.Parameters(); - std::cout << a1.LayerString(&t) << std::endl; - return; - } -}; - -/** - * std::cout << boost::get *>( - * darknetModel.GetModel().Model()[3])->Parameters().n_elem << std::endl; - */ int main() { - #if defined(_OPENMP) - std::cout << "Compiled with OpenMP!" << std::endl; - #endif - DarkNet<> darknetModel(3, 224, 224, 1000, "none", true); - std::cout << "Model Compiled" << std::endl; - - // std::cout << darknetModel.GetModel().Parameters().n_rows << " " << - // darknetModel.GetModel().Parameters().n_cols << std::endl; - - size_t outSize = 32; - Convolution<> *layer = new Convolution<>(3, 32, 3, 3, 1, 1, 1, 1, 224, 224); - // std::cout << layer->Parameters().n_elem << std::endl; - size_t layerElement = layer->Parameters().n_elem - outSize; - - // This will be equal to output size for conv layers. - // In darknet model bias term is removed. - size_t offset = 0; - size_t biasOffset = outSize; - - arma::mat ConvWeights; - mlpack::data::Load("../../PyTorch-mlpack-DarkNet-Weight-Converter/conv_1_1.csv", - ConvWeights); - // Transpose weights to match FFN Class. - ConvWeights = ConvWeights.t(); - std::cout << ConvWeights.n_rows << " " << ConvWeights.n_cols << std::endl; - - darknetModel.GetModel().Parameters()(arma::span(offset, offset + layerElement - 1), - arma::span()) = ConvWeights; - - - bool weightsEqual = true; - for (size_t i = offset; i < offset + layerElement; i++) - { - if (darknetModel.GetModel().Parameters()(i) != ConvWeights(i - offset)) - { - weightsEqual = false; - break; - } - } - - if (weightsEqual) - { - std::cout << "Yay!, Transferred weights" << std::endl; - } - else - { - std::cout << "Hmm, Looks like you missed something!" << std::endl; - } - - offset = offset + layerElement + biasOffset; - biasOffset = 0; - - BatchNorm<>* layer2 = new BatchNorm<>(32); - std::cout << layer2->Parameters().n_elem << std::endl; + DarkNet<> darknet(3, 224, 224, 1000); + std::cout << darknet.GetModel().Parameters().n_elem << std::endl; return 0; } diff --git a/models/CMakeLists.txt b/models/CMakeLists.txt index 418ada80..c4bd5a8c 100644 --- a/models/CMakeLists.txt +++ b/models/CMakeLists.txt @@ -10,6 +10,7 @@ foreach(file ${SOURCES}) set(DIR_SRCS ${DIR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/${file}) endforeach() +set(DIR_SRCS ${DIR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/layer.hpp) # Append sources (with directory name) to list of all models sources (used at # the parent scope). set(DIRS ${DIRS} ${DIR_SRCS} PARENT_SCOPE) diff --git a/models/darknet/darknet_impl.hpp b/models/darknet/darknet_impl.hpp index e2a94ce2..1386ec3a 100644 --- a/models/darknet/darknet_impl.hpp +++ b/models/darknet/darknet_impl.hpp @@ -124,7 +124,7 @@ DarkNet::DarkNet( { darkNet.Add(new IdentityLayer<>()); ConvolutionBlock(inputChannel, 32, 3, 3, 1, 1, 1, 1, true); - ConvolutionBlock(inputChannel, 64, 3, 3, 2, 2, 1, 1, true); + ConvolutionBlock(32, 64, 3, 3, 2, 2, 1, 1, true); // Let's automate this a bit. size_t curChannels = 64; diff --git a/models/models.hpp b/models/models.hpp new file mode 100644 index 00000000..d2d66f64 --- /dev/null +++ b/models/models.hpp @@ -0,0 +1,8 @@ +/** + * @file models.hpp + * @author Kartik Dutt + * + * This includes various models. + */ + +#include "darknet/darknet.hpp" \ No newline at end of file From b0fb83fda6474d6de916ca436d4892977a764324 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Sun, 19 Jul 2020 11:08:04 +0530 Subject: [PATCH 21/35] Update for weight converter --- models/darknet/darknet.hpp | 2 +- models/darknet/darknet_impl.hpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/models/darknet/darknet.hpp b/models/darknet/darknet.hpp index 0ab76886..76ae409d 100644 --- a/models/darknet/darknet.hpp +++ b/models/darknet/darknet.hpp @@ -231,7 +231,7 @@ class DarkNet kernelWidth, kernelHeight, 1, 1, padWidth, padHeight, true, block); ConvolutionBlock(inputChannel * 2, inputChannel, - 1, 1, 1, 1, 0, 0, false, block); + 1, 1, 1, 1, 0, 0, true, block); ConvolutionBlock(inputChannel, inputChannel * 2, kernelWidth, kernelHeight, 1, 1, padWidth, padHeight, true, block); diff --git a/models/darknet/darknet_impl.hpp b/models/darknet/darknet_impl.hpp index 1386ec3a..866d980c 100644 --- a/models/darknet/darknet_impl.hpp +++ b/models/darknet/darknet_impl.hpp @@ -103,11 +103,11 @@ DarkNet::DarkNet( DarkNet19SequentialBlock(128, 3, 3, 1, 1); PoolingBlock(); DarkNet19SequentialBlock(256, 3, 3, 1, 1); - ConvolutionBlock(512, 256, 1, 1, 1, 1); + ConvolutionBlock(512, 256, 1, 1, 1, 1, 1, 1, true); ConvolutionBlock(256, 512, 3, 3, 1, 1, 1, 1, true); PoolingBlock(); DarkNet19SequentialBlock(512, 3, 3, 1, 1); - ConvolutionBlock(1024, 512, 1, 1, 1, 1); + ConvolutionBlock(1024, 512, 1, 1, 1, 1, 1, 1, true); ConvolutionBlock(512, 1024, 3, 3, 1, 1, 1, 1, true); if (includeTop) From 27670c0b8d3cf288748c925e883eead02e950fed Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Mon, 20 Jul 2020 21:07:51 +0530 Subject: [PATCH 22/35] Add weight conv for review --- .../object_classification.cpp | 4 +- .../weight_converter.cpp | 102 +++++++++++++++++- models/darknet/darknet_impl.hpp | 29 ++++- 3 files changed, 130 insertions(+), 5 deletions(-) diff --git a/computer_vision/object_classification/object_classification.cpp b/computer_vision/object_classification/object_classification.cpp index 3b7686dd..d7d2bd62 100644 --- a/computer_vision/object_classification/object_classification.cpp +++ b/computer_vision/object_classification/object_classification.cpp @@ -56,12 +56,12 @@ int main() // "www.mlpack.org", true); std::cout << "Loading Dataset!" << std::endl; dataloader.LoadImageDatasetFromDirectory("./../data/cifar10-small/", - 32, 32, 3, true, 0.2, true, {"resize : 56"}); + 32, 32, 3, true, 0.2, true, {"resize : 32"}); std::cout << "Dataset Loaded!" << std::endl; dataloader.TrainLabels() = dataloader.TrainLabels() + 1; DarkNet, - mlpack::ann::XavierInitialization, 19> darknetModel(3, 56, 56, 10); + mlpack::ann::XavierInitialization, 1> darknetModel(3, 32, 32, 10); std::cout << "Model Compiled" << std::endl; constexpr double RATIO = 0.1; diff --git a/computer_vision/object_classification/weight_converter.cpp b/computer_vision/object_classification/weight_converter.cpp index 3be1729a..3801fa82 100644 --- a/computer_vision/object_classification/weight_converter.cpp +++ b/computer_vision/object_classification/weight_converter.cpp @@ -21,7 +21,11 @@ #include #include #include +#include #include +#include +#include +#include using namespace mlpack; using namespace mlpack::ann; @@ -29,9 +33,105 @@ using namespace arma; using namespace std; using namespace ens; +std::queue batchNormRunningMean; +std::queue batchNormRunningVar; +template < + typename OutputLayer = mlpack::ann::NegativeLogLikelihood<>, + typename InitializationRule = mlpack::ann::RandomInitialization> +void LoadWeights(mlpack::ann::FFN &model, + std::string modelConfigPath) +{ + std::cout << "Loading Weights\n"; + size_t currentOffset = 0; + boost::property_tree::ptree xmlFile; + boost::property_tree::read_xml(modelConfigPath, xmlFile); + boost::property_tree::ptree modelConfig = xmlFile.get_child("model"); + BOOST_FOREACH (boost::property_tree::ptree::value_type const &layer, modelConfig) + { + std::string progressBar(81, '-'); + size_t filled = std::ceil(currentOffset * 80.0 / model.Parameters().n_elem); + progressBar[0] = '['; + std::fill(progressBar.begin() + 1, progressBar.begin() + filled + 1, '='); + std::cout << progressBar << "] " << filled * 100.0 / 80.0 << "%\r"; + std::cout.flush(); + // Load Weights. + if (layer.second.get_child("has_weights").data() != "0") + { + arma::mat weights; + mlpack::data::Load("./../../../" + layer.second.get_child("weight_csv").data(), weights); + model.Parameters()(arma::span(currentOffset, currentOffset + weights.n_elem - 1), + arma::span()) = weights.t(); + currentOffset += weights.n_elem; + } + else + { + currentOffset += std::stoi(layer.second.get_child("weight_offset").data()); + } + + // Load Biases. + if (layer.second.get_child("has_bias").data() != "0") + { + arma::mat bias; + mlpack::data::Load("./../../../" + layer.second.get_child("bias_csv").data(), bias); + model.Parameters()(arma::span(currentOffset, currentOffset + bias.n_elem - 1), + arma::span()) = bias.t(); + currentOffset += bias.n_elem; + } + else + { + currentOffset += std::stoi(layer.second.get_child("bias_offset").data()); + } + + if (layer.second.get_child("has_running_mean").data() != "0") + { + batchNormRunningMean.push("./../../../" + layer.second.get_child("running_mean_csv").data()); + } + + if (layer.second.get_child("has_running_var").data() != "0") + { + batchNormRunningMean.push("./../../../" + layer.second.get_child("running_var_csv").data()); + } + } + std::cout << std::endl; +} + +template> +LayerType LoadRunningMeanAndVariance(LayerType&& baseLayer, size_t i = 0) +{ + while (i < baseLayer.Model().size() && !batchNormRunningMean.empty()) + { + if (baseLayer.Model()[i].type() == typeid(new mlpack::ann::Sequential<>())) + { + std::cout << "Sequential Layer. " << i << std::endl; + LoadRunningMeanAndVariance>(&(baseLayer.Model()[i])); + } + + if (!batchNormRunningMean.empty() && + baseLayer.Model()[i].type() == typeid(new mlpack::ann::BatchNorm<>())) + { + std::cout << "BATCHNORM Layer " << i << std::endl; + arma::mat runningMean; + mlpack::data::Load(batchNormRunningMean.front(), runningMean); + batchNormRunningMean.pop(); + // baseLayer.Model()[i].TrainingMean() = runningMean; + // baseLayer.Model()[i].TrainingMean().print(); + } + + i++; + } + return baseLayer; +} + + int main() { DarkNet<> darknet(3, 224, 224, 1000); - std::cout << darknet.GetModel().Parameters().n_elem << std::endl; + batchNormRunningMean.push("as"); + // LoadWeights<>(darknet.GetModel(), "./../../../cfg/darknet19.xml"); + LoadRunningMeanAndVariance<>(darknet.GetModel()); + boost::get*>(darknet.GetModel().Model()[1])->Model().size(); + std::cout << boost::get*>(darknet.GetModel().Model()[1])->Model().size() << std::endl; + std::cout << (boost::get *>(darknet.GetModel().Model()[1])->Model()[1].type() == typeid(new mlpack::ann::BatchNorm<>())) << std::endl; + return 0; } diff --git a/models/darknet/darknet_impl.hpp b/models/darknet/darknet_impl.hpp index 866d980c..0becbe9f 100644 --- a/models/darknet/darknet_impl.hpp +++ b/models/darknet/darknet_impl.hpp @@ -72,8 +72,9 @@ DarkNet::DarkNet( numClasses(numClasses), weights(weights) { - mlpack::Log::Assert(DarkNetVersion == 19 || DarkNetVersion == 53, - "Incorrect DarkNet version. Possible values are 19 and 53. Trying \ + mlpack::Log::Assert(DarkNetVersion == 19 || DarkNetVersion == 53 || + DarkNetVersion == 1, "Incorrect DarkNet version. \ + Possible values are 19 and 53. Trying \ to find version : " + std::to_string(DarkNetVersion) + "."); if (weights == "cifar10") @@ -149,6 +150,30 @@ DarkNet::DarkNet( darkNet.Add(new LogSoftMax<>()); } + darkNet.ResetParameters(); + } + else if (DarkNetVersion == 1) + { + darkNet.Add(new IdentityLayer<>()); + ConvolutionBlock(inputChannel, 16, 3, 3, 1, 1, 1, 1, true); + PoolingBlock(); + + size_t numBlocks = 6; + size_t outChannels = 16; + for (size_t blockId = 0; blockId < numBlocks; blockId++) + { + ConvolutionBlock(outChannels, outChannels * 2, 3, 3, 1, 1, 1, 1, true); + PoolingBlock(2); + outChannels *= 2; + } + + if (includeTop) + { + darkNet.Add(new Linear<>(inputWidth * inputHeight * outChannels, + numClasses)); + darkNet.Add(new LogSoftMax<>()); + } + darkNet.ResetParameters(); } } From ef422f1afff1a8d8776ec0fed3754621a16a76ef Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Mon, 20 Jul 2020 21:14:14 +0530 Subject: [PATCH 23/35] Add print statements --- computer_vision/object_classification/weight_converter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/computer_vision/object_classification/weight_converter.cpp b/computer_vision/object_classification/weight_converter.cpp index 3801fa82..e357d861 100644 --- a/computer_vision/object_classification/weight_converter.cpp +++ b/computer_vision/object_classification/weight_converter.cpp @@ -98,6 +98,7 @@ void LoadWeights(mlpack::ann::FFN &model, template> LayerType LoadRunningMeanAndVariance(LayerType&& baseLayer, size_t i = 0) { + std::cout << "Recursive Call" << baseLayer.Model().size() << std::endl; while (i < baseLayer.Model().size() && !batchNormRunningMean.empty()) { if (baseLayer.Model()[i].type() == typeid(new mlpack::ann::Sequential<>())) From 0eb2435231a457d946a89d11c10ca10d92623945 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Wed, 5 Aug 2020 23:57:02 +0530 Subject: [PATCH 24/35] Clean Up --- CMakeLists.txt | 1 - computer_vision/CMakeLists.txt | 13 -- .../object_classification/CMakeLists.txt | 31 ---- .../object_classification.cpp | 111 -------------- .../weight_converter.cpp | 138 ------------------ dataloader/dataloader_impl.hpp | 18 ++- models/darknet/darknet_impl.hpp | 35 +---- 7 files changed, 15 insertions(+), 332 deletions(-) delete mode 100644 computer_vision/CMakeLists.txt delete mode 100644 computer_vision/object_classification/CMakeLists.txt delete mode 100644 computer_vision/object_classification/object_classification.cpp delete mode 100644 computer_vision/object_classification/weight_converter.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 55083993..0a464a49 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -219,7 +219,6 @@ set(DIRS dataloader/ models/ tests/ - computer_vision/ ) foreach(dir ${DIRS}) diff --git a/computer_vision/CMakeLists.txt b/computer_vision/CMakeLists.txt deleted file mode 100644 index d9268fba..00000000 --- a/computer_vision/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) -project(computer_vision) - -add_subdirectory(object_classification/) - -# Add directory name to sources. -set(DIR_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/) - -foreach(file ${SOURCES}) - set(DIR_SRCS ${DIR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/${file}) -endforeach() - -set(DIRS ${DIRS} ${DIR_SRCS} PARENT_SCOPE) diff --git a/computer_vision/object_classification/CMakeLists.txt b/computer_vision/object_classification/CMakeLists.txt deleted file mode 100644 index 256771d7..00000000 --- a/computer_vision/object_classification/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR) -project(object_classification) - -set(MODEL_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/) -include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../../") - -set(SOURCES - object_classification.cpp - weight_converter.cpp -) - -foreach(file ${SOURCES}) - string( REPLACE ".cpp" "" name ${file}) - add_executable(${name} ${MODEL_SOURCE_DIR}/${file}) - if (USE_OPENMP AND OPENMP_FOUND AND CMAKE_CXX_COMPILER_ID MATCHES "AppleClang") - if (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL "7.0" OR - CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "7.0") - target_link_libraries(${name} ${OpenMP_libomp_LIBRARY}) - endif() - endif() - target_link_libraries(${name} - ${COMPILER_SUPPORT_LIBRARIES} - ${ARMADILLO_LIBRARIES} - ${Boost_FILESYSTEM_LIBRARY} - ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} - ${Boost_SYSTEM_LIBRARY} - ${Boost_SERIALIZATION_LIBRARY} - ${Boost_REGEX_LIBRARY} - ${MLPACK_LIBRARIES} -) -endforeach() diff --git a/computer_vision/object_classification/object_classification.cpp b/computer_vision/object_classification/object_classification.cpp deleted file mode 100644 index d7d2bd62..00000000 --- a/computer_vision/object_classification/object_classification.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/** - * @file object_classification.hpp - * @author Kartik Dutt - * - * Contains implementation of object classification suite. It can be used - * to select object classification model, it's parameter dataset and - * other training parameters. - * - * NOTE: This code needs to be adapted as this implementation doesn't support - * Command Line Arguments. - * - * mlpack is free software; you may redistribute it and/or modify it under the - * terms of the 3-clause BSD license. You should have received a copy of the - * 3-clause BSD license along with mlpack. If not, see - * http://www.opensource.org/licenses/BSD-3-Clause for more information. - */ -#include -#include -#include -#include -#include -#include -#include - -using namespace mlpack; -using namespace mlpack::ann; -using namespace arma; -using namespace std; -using namespace ens; - -class Accuracy -{ - public: - template - static double Evaluate(InputType& input, OutputType& output) - { - arma::Row predLabels(input.n_cols); - for (arma::uword i = 0; i < input.n_cols; ++i) - { - predLabels(i) = input.col(i).index_max() + 1; - } - return arma::accu(predLabels == output) / (double)output.n_elem * 100; - } -}; - -int main() -{ - #if defined(_OPENMP) - std::cout << "Compiled with OpenMP!" << std::endl; - #endif - - DataLoader<> dataloader; - - // Utils::DownloadFile("/datasets/cifar10.tar.gz", - // "./../data/cifar10.tar.gz", "", false, true, - // "www.mlpack.org", true); - std::cout << "Loading Dataset!" << std::endl; - dataloader.LoadImageDatasetFromDirectory("./../data/cifar10-small/", - 32, 32, 3, true, 0.2, true, {"resize : 32"}); - - std::cout << "Dataset Loaded!" << std::endl; - dataloader.TrainLabels() = dataloader.TrainLabels() + 1; - DarkNet, - mlpack::ann::XavierInitialization, 1> darknetModel(3, 32, 32, 10); - std::cout << "Model Compiled" << std::endl; - - constexpr double RATIO = 0.1; - constexpr size_t EPOCHS = 5; - constexpr double STEP_SIZE = 0.001; - constexpr int BATCH_SIZE = 8; - - mlpack::data::MinMaxScaler scaler; - - - SGD optimizer(STEP_SIZE, BATCH_SIZE, - dataloader.TrainLabels().n_cols * EPOCHS, - 1e-8, - true, - AdamUpdate(1e-8, 0.9, 0.999)); - - std::cout << "Optimizer Created, Starting Training!" << std::endl; - - darknetModel.GetModel().Train(dataloader.TrainFeatures(), - dataloader.TrainLabels(), - optimizer, - ens::PrintLoss(), - ens::ProgressBar(), - ens::EarlyStopAtMinLoss(), - ens::PrintMetric, XavierInitialization>, - Accuracy>( - darknetModel.GetModel(), - dataloader.TrainFeatures(), - dataloader.TrainLabels(), - "accuracy", - true), - ens::PrintMetric, XavierInitialization>, - Accuracy>( - darknetModel.GetModel(), - dataloader.ValidFeatures(), - dataloader.ValidLabels(), - "accuracy", - false), - ens::PeriodicSave, XavierInitialization>>( - darknetModel.GetModel(), - "./../weights/", - "darknet19", 1)); - - mlpack::data::Save("darknet19.bin", "darknet", - darknetModel.GetModel(), false); - return 0; -} diff --git a/computer_vision/object_classification/weight_converter.cpp b/computer_vision/object_classification/weight_converter.cpp deleted file mode 100644 index e357d861..00000000 --- a/computer_vision/object_classification/weight_converter.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/** - * @file object_classification.hpp - * @author Kartik Dutt - * - * Contains implementation of object classification suite. It can be used - * to select object classification model, it's parameter dataset and - * other training parameters. - * - * NOTE: This code needs to be adapted as this implementation doesn't support - * Command Line Arguments. - * - * mlpack is free software; you may redistribute it and/or modify it under the - * terms of the 3-clause BSD license. You should have received a copy of the - * 3-clause BSD license along with mlpack. If not, see - * http://www.opensource.org/licenses/BSD-3-Clause for more information. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace mlpack; -using namespace mlpack::ann; -using namespace arma; -using namespace std; -using namespace ens; - -std::queue batchNormRunningMean; -std::queue batchNormRunningVar; -template < - typename OutputLayer = mlpack::ann::NegativeLogLikelihood<>, - typename InitializationRule = mlpack::ann::RandomInitialization> -void LoadWeights(mlpack::ann::FFN &model, - std::string modelConfigPath) -{ - std::cout << "Loading Weights\n"; - size_t currentOffset = 0; - boost::property_tree::ptree xmlFile; - boost::property_tree::read_xml(modelConfigPath, xmlFile); - boost::property_tree::ptree modelConfig = xmlFile.get_child("model"); - BOOST_FOREACH (boost::property_tree::ptree::value_type const &layer, modelConfig) - { - std::string progressBar(81, '-'); - size_t filled = std::ceil(currentOffset * 80.0 / model.Parameters().n_elem); - progressBar[0] = '['; - std::fill(progressBar.begin() + 1, progressBar.begin() + filled + 1, '='); - std::cout << progressBar << "] " << filled * 100.0 / 80.0 << "%\r"; - std::cout.flush(); - // Load Weights. - if (layer.second.get_child("has_weights").data() != "0") - { - arma::mat weights; - mlpack::data::Load("./../../../" + layer.second.get_child("weight_csv").data(), weights); - model.Parameters()(arma::span(currentOffset, currentOffset + weights.n_elem - 1), - arma::span()) = weights.t(); - currentOffset += weights.n_elem; - } - else - { - currentOffset += std::stoi(layer.second.get_child("weight_offset").data()); - } - - // Load Biases. - if (layer.second.get_child("has_bias").data() != "0") - { - arma::mat bias; - mlpack::data::Load("./../../../" + layer.second.get_child("bias_csv").data(), bias); - model.Parameters()(arma::span(currentOffset, currentOffset + bias.n_elem - 1), - arma::span()) = bias.t(); - currentOffset += bias.n_elem; - } - else - { - currentOffset += std::stoi(layer.second.get_child("bias_offset").data()); - } - - if (layer.second.get_child("has_running_mean").data() != "0") - { - batchNormRunningMean.push("./../../../" + layer.second.get_child("running_mean_csv").data()); - } - - if (layer.second.get_child("has_running_var").data() != "0") - { - batchNormRunningMean.push("./../../../" + layer.second.get_child("running_var_csv").data()); - } - } - std::cout << std::endl; -} - -template> -LayerType LoadRunningMeanAndVariance(LayerType&& baseLayer, size_t i = 0) -{ - std::cout << "Recursive Call" << baseLayer.Model().size() << std::endl; - while (i < baseLayer.Model().size() && !batchNormRunningMean.empty()) - { - if (baseLayer.Model()[i].type() == typeid(new mlpack::ann::Sequential<>())) - { - std::cout << "Sequential Layer. " << i << std::endl; - LoadRunningMeanAndVariance>(&(baseLayer.Model()[i])); - } - - if (!batchNormRunningMean.empty() && - baseLayer.Model()[i].type() == typeid(new mlpack::ann::BatchNorm<>())) - { - std::cout << "BATCHNORM Layer " << i << std::endl; - arma::mat runningMean; - mlpack::data::Load(batchNormRunningMean.front(), runningMean); - batchNormRunningMean.pop(); - // baseLayer.Model()[i].TrainingMean() = runningMean; - // baseLayer.Model()[i].TrainingMean().print(); - } - - i++; - } - return baseLayer; -} - - -int main() -{ - DarkNet<> darknet(3, 224, 224, 1000); - batchNormRunningMean.push("as"); - // LoadWeights<>(darknet.GetModel(), "./../../../cfg/darknet19.xml"); - LoadRunningMeanAndVariance<>(darknet.GetModel()); - boost::get*>(darknet.GetModel().Model()[1])->Model().size(); - std::cout << boost::get*>(darknet.GetModel().Model()[1])->Model().size() << std::endl; - std::cout << (boost::get *>(darknet.GetModel().Model()[1])->Model()[1].type() == typeid(new mlpack::ann::BatchNorm<>())) << std::endl; - - return 0; -} diff --git a/dataloader/dataloader_impl.hpp b/dataloader/dataloader_impl.hpp index e0069f4c..5538cd1d 100644 --- a/dataloader/dataloader_impl.hpp +++ b/dataloader/dataloader_impl.hpp @@ -383,7 +383,7 @@ template< // We use to endls here as one of them will be replaced by print // command below. - Log::Info << "Found " << imagesDirectory.size() << " belonging to " << + mlpack::Log::Info << "Found " << imagesDirectory.size() << " belonging to " << label << " class." << std::endl << std::endl; size_t loadedImages = 0; @@ -395,7 +395,6 @@ template< { continue; } - mlpack::data::ImageInfo imageInfo(imageWidth, imageHeight, imageDepth); // Load the image. @@ -406,12 +405,14 @@ template< mlpack::data::Load(imageName.string(), image, imageInfo); // Add object to training set. - dataset.insert_cols(0, image); - labels.insert_cols(0, arma::vec(1).fill(label)); - - loadedImages++; - mlpack::Log::Info << "Loaded " << loadedImages << " out of " << - imagesDirectory.size() << "\r" << std::endl; + if (image.n_rows == dataset.n_rows || dataset.n_elem == 0) + { + labels.insert_cols(0, arma::vec(1).fill(label)); + dataset.insert_cols(0, image); + loadedImages++; + mlpack::Log::Info << "Loaded " << loadedImages << " out of " << + imagesDirectory.size() << "\r" << std::endl; + } } } @@ -485,6 +486,7 @@ template< validationData.n_rows - 1); augmentations.Transform(trainFeatures, imageWidth, imageHeight, imageDepth); + augmentations.Transform(validFeatures, imageWidth, imageHeight, imageDepth); mlpack::Log::Info << "Found " << totalClasses << " classes." << std::endl; diff --git a/models/darknet/darknet_impl.hpp b/models/darknet/darknet_impl.hpp index 0becbe9f..77ba172a 100644 --- a/models/darknet/darknet_impl.hpp +++ b/models/darknet/darknet_impl.hpp @@ -72,16 +72,15 @@ DarkNet::DarkNet( numClasses(numClasses), weights(weights) { - mlpack::Log::Assert(DarkNetVersion == 19 || DarkNetVersion == 53 || - DarkNetVersion == 1, "Incorrect DarkNet version. \ - Possible values are 19 and 53. Trying \ - to find version : " + std::to_string(DarkNetVersion) + "."); + mlpack::Log::Assert(DarkNetVersion == 19 || DarkNetVersion == 53, + "Incorrect DarkNet version. Possible values are 19 and 53. \ + Trying to find version : " + std::to_string(DarkNetVersion) + "."); - if (weights == "cifar10") + if (weights == "imagenet") { // Download weights here. LoadModel("./../weights/darknet/darknet" + std::to_string(DarkNetVersion) + - "_cifar10.bin"); + "_imagenet.bin"); return; } else if (weights != "none") @@ -150,30 +149,6 @@ DarkNet::DarkNet( darkNet.Add(new LogSoftMax<>()); } - darkNet.ResetParameters(); - } - else if (DarkNetVersion == 1) - { - darkNet.Add(new IdentityLayer<>()); - ConvolutionBlock(inputChannel, 16, 3, 3, 1, 1, 1, 1, true); - PoolingBlock(); - - size_t numBlocks = 6; - size_t outChannels = 16; - for (size_t blockId = 0; blockId < numBlocks; blockId++) - { - ConvolutionBlock(outChannels, outChannels * 2, 3, 3, 1, 1, 1, 1, true); - PoolingBlock(2); - outChannels *= 2; - } - - if (includeTop) - { - darkNet.Add(new Linear<>(inputWidth * inputHeight * outChannels, - numClasses)); - darkNet.Add(new LogSoftMax<>()); - } - darkNet.ResetParameters(); } } From 8aba774c1afd40f2e5a5fe22a5fbd61dbdd08923 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Wed, 5 Aug 2020 23:59:31 +0530 Subject: [PATCH 25/35] Remove print statements --- models/darknet/darknet.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/models/darknet/darknet.hpp b/models/darknet/darknet.hpp index 76ae409d..2ccbb71c 100644 --- a/models/darknet/darknet.hpp +++ b/models/darknet/darknet.hpp @@ -147,13 +147,13 @@ class DarkNet inputHeight)); // Update inputWidth and input Height. - std::cout << "Conv Layer. "; - std::cout << "(" << inputWidth << ", " << inputHeight << + mlpack::Log::Info << "Conv Layer. "; + mlpack::Log::Info << "(" << inputWidth << ", " << inputHeight << ", " << inSize << ") ----> "; inputWidth = ConvOutSize(inputWidth, kernelWidth, strideWidth, padW); inputHeight = ConvOutSize(inputHeight, kernelHeight, strideHeight, padH); - std::cout << "(" << inputWidth << ", " << inputHeight << + mlpack::Log::Info << "(" << inputWidth << ", " << inputHeight << ", " << outSize << ")" << std::endl; if (batchNorm) @@ -194,13 +194,13 @@ class DarkNet factor), std::ceil(inputHeight * 1.0 / factor))); } - std::cout << "Pooling Layer. "; - std::cout << "(" << inputWidth << ", " << inputHeight << + 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); - std::cout << "(" << inputWidth << ", " << inputHeight << + mlpack::Log::Info << "(" << inputWidth << ", " << inputHeight << ")" << std::endl; } @@ -254,14 +254,14 @@ class DarkNet const size_t padWidth = 1, const size_t padHeight = 1) { - std::cout << "Residual Block Begin." << std::endl; + mlpack::Log::Info << "Residual Block Begin." << std::endl; Residual<>* residualBlock = new Residual<>(); ConvolutionBlock(inputChannel, inputChannel / 2, 1, 1, 1, 1, 0, 0, true, residualBlock); ConvolutionBlock(inputChannel / 2, inputChannel, kernelWidth, kernelHeight, 1, 1, padWidth, padWidth, true, residualBlock); darkNet.Add(residualBlock); - std::cout << "Residual Block end." << std::endl; + mlpack::Log::Info << "Residual Block end." << std::endl; } /** From 14abd611e667ab489d1050976df4d34680c98001 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Thu, 6 Aug 2020 00:01:21 +0530 Subject: [PATCH 26/35] Style fixes and remove model.hpp --- ensmallen_utils/CMakeLists.txt | 2 +- models/darknet/darknet_impl.hpp | 2 +- models/models.hpp | 8 -------- 3 files changed, 2 insertions(+), 10 deletions(-) delete mode 100644 models/models.hpp diff --git a/ensmallen_utils/CMakeLists.txt b/ensmallen_utils/CMakeLists.txt index ded5df9b..57b77395 100644 --- a/ensmallen_utils/CMakeLists.txt +++ b/ensmallen_utils/CMakeLists.txt @@ -13,4 +13,4 @@ endforeach() # Append sources (with directory name) to list of all models sources (used at # the parent scope). -set(DIRS ${DIRS} ${DIR_SRCS} PARENT_SCOPE) \ No newline at end of file +set(DIRS ${DIRS} ${DIR_SRCS} PARENT_SCOPE) diff --git a/models/darknet/darknet_impl.hpp b/models/darknet/darknet_impl.hpp index 77ba172a..173c577f 100644 --- a/models/darknet/darknet_impl.hpp +++ b/models/darknet/darknet_impl.hpp @@ -183,4 +183,4 @@ void DarkNet< } // namespace ann } // namespace mlpack -#endif \ No newline at end of file +#endif diff --git a/models/models.hpp b/models/models.hpp deleted file mode 100644 index d2d66f64..00000000 --- a/models/models.hpp +++ /dev/null @@ -1,8 +0,0 @@ -/** - * @file models.hpp - * @author Kartik Dutt - * - * This includes various models. - */ - -#include "darknet/darknet.hpp" \ No newline at end of file From cca5573c816e5fc60e2a41b51af416a0fc674454 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Thu, 6 Aug 2020 00:46:56 +0530 Subject: [PATCH 27/35] Fix windows build --- dataloader/dataloader.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/dataloader/dataloader.hpp b/dataloader/dataloader.hpp index d389e58f..28c1cb44 100644 --- a/dataloader/dataloader.hpp +++ b/dataloader/dataloader.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #ifndef MODELS_DATALOADER_HPP From 8eaf6890447740370704850ddcfffc39187481a8 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Thu, 6 Aug 2020 13:32:24 +0530 Subject: [PATCH 28/35] Matched darknet53 to PyTorch weights --- models/darknet/darknet_impl.hpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/models/darknet/darknet_impl.hpp b/models/darknet/darknet_impl.hpp index 173c577f..f1b5acbe 100644 --- a/models/darknet/darknet_impl.hpp +++ b/models/darknet/darknet_impl.hpp @@ -137,16 +137,20 @@ DarkNet::DarkNet( DarkNet53ResidualBlock(curChannels); } - ConvolutionBlock(curChannels, curChannels * 2, 3, 3, - 2, 2, 1, 1, true); - curChannels = curChannels * 2; + if (blockCount != 4) + { + ConvolutionBlock(curChannels, curChannels * 2, 3, 3, + 2, 2, 1, 1, true); + curChannels = curChannels * 2; + } } - darkNet.Add(new Linear<>(inputWidth * inputHeight * curChannels, - numClasses)); if (includeTop) { - darkNet.Add(new LogSoftMax<>()); + darkNet.Add(new MeanPooling<>(inputWidth, inputHeight, + 1, 1)); + darkNet.Add(new Linear<>(curChannels, numClasses)); + darkNet.Add(new Softmax<>()); } darkNet.ResetParameters(); From e1aae1697ab61a11b7f0493e1e8351573583ac99 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Thu, 6 Aug 2020 20:04:39 +0530 Subject: [PATCH 29/35] Use 1e-2 threshold for darknet53 --- models/darknet/darknet.hpp | 44 +++++++++++++++++++++------------ models/darknet/darknet_impl.hpp | 10 ++++---- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/models/darknet/darknet.hpp b/models/darknet/darknet.hpp index 2ccbb71c..7e523d93 100644 --- a/models/darknet/darknet.hpp +++ b/models/darknet/darknet.hpp @@ -128,6 +128,7 @@ class DarkNet * layer is added. * @param baseLayer Layer in which Convolution block will be added, if * NULL added to darkNet FFN. + * @param negativeSlope Negative slope hyper-parameter for LeakyReLU. */ template> void ConvolutionBlock(const size_t inSize, @@ -139,7 +140,8 @@ class DarkNet const size_t padW = 0, const size_t padH = 0, const bool batchNorm = true, - SequentialType* baseLayer = NULL) + SequentialType* baseLayer = NULL, + const double negativeSlope = 1e-1) { Sequential<>* bottleNeck = new Sequential<>(); bottleNeck->Add(new Convolution<>(inSize, outSize, kernelWidth, @@ -158,10 +160,10 @@ class DarkNet if (batchNorm) { - bottleNeck->Add(new BatchNorm<>(outSize, 1e-8, false)); + bottleNeck->Add(new BatchNorm<>(outSize, 1e-5, false)); } - bottleNeck->Add(new LeakyReLU<>()); + bottleNeck->Add(new LeakyReLU<>(negativeSlope)); if (baseLayer != NULL) { @@ -197,6 +199,7 @@ class DarkNet 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); @@ -226,17 +229,26 @@ class DarkNet const size_t padWidth, const size_t padHeight) { - Sequential<>* block = new Sequential<>(); - ConvolutionBlock(inputChannel, inputChannel * 2, - kernelWidth, kernelHeight, 1, 1, padWidth, padHeight, true, - block); - ConvolutionBlock(inputChannel * 2, inputChannel, - 1, 1, 1, 1, 0, 0, true, block); - ConvolutionBlock(inputChannel, inputChannel * 2, - kernelWidth, kernelHeight, 1, 1, padWidth, padHeight, true, - block); - - darkNet.Add(block); + if (type == "max") + { + darkNet.Add(new MaxPooling<>(std::ceil(factor), + std::ceil(factor), factor, factor)); + } + else + { + darkNet.Add(new MeanPooling<>(std::ceil( + factor), std::ceil(factor), factor, 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; } /** @@ -257,9 +269,9 @@ class DarkNet mlpack::Log::Info << "Residual Block Begin." << std::endl; Residual<>* residualBlock = new Residual<>(); ConvolutionBlock(inputChannel, inputChannel / 2, - 1, 1, 1, 1, 0, 0, true, residualBlock); + 1, 1, 1, 1, 0, 0, true, residualBlock, 1e-2); ConvolutionBlock(inputChannel / 2, inputChannel, kernelWidth, - kernelHeight, 1, 1, padWidth, padWidth, true, residualBlock); + kernelHeight, 1, 1, padWidth, padWidth, true, residualBlock, 1e-2); darkNet.Add(residualBlock); mlpack::Log::Info << "Residual Block end." << std::endl; } diff --git a/models/darknet/darknet_impl.hpp b/models/darknet/darknet_impl.hpp index f1b5acbe..60b23eb5 100644 --- a/models/darknet/darknet_impl.hpp +++ b/models/darknet/darknet_impl.hpp @@ -123,8 +123,9 @@ DarkNet::DarkNet( else if (DarkNetVersion == 53) { darkNet.Add(new IdentityLayer<>()); - ConvolutionBlock(inputChannel, 32, 3, 3, 1, 1, 1, 1, true); - ConvolutionBlock(32, 64, 3, 3, 2, 2, 1, 1, true); + ConvolutionBlock(inputChannel, 32, 3, 3, 1, 1, 1, 1, true, NULL, 1e-2); + ConvolutionBlock(32, 64, 3, 3, 2, 2, 1, 1, true, NULL, 1e-2); + // Let's automate this a bit. size_t curChannels = 64; @@ -140,15 +141,14 @@ DarkNet::DarkNet( if (blockCount != 4) { ConvolutionBlock(curChannels, curChannels * 2, 3, 3, - 2, 2, 1, 1, true); + 2, 2, 1, 1, true, NULL, 1e-2); curChannels = curChannels * 2; } } if (includeTop) { - darkNet.Add(new MeanPooling<>(inputWidth, inputHeight, - 1, 1)); + darkNet.Add(new AdaptiveMeanPooling<>(1, 1)); darkNet.Add(new Linear<>(curChannels, numClasses)); darkNet.Add(new Softmax<>()); } From 83c885520b1da64d7d29d123703b1474e8f07dc3 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Sat, 8 Aug 2020 11:24:18 +0530 Subject: [PATCH 30/35] Remove softmax in 53 --- models/darknet/darknet_impl.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/models/darknet/darknet_impl.hpp b/models/darknet/darknet_impl.hpp index 60b23eb5..62b6d498 100644 --- a/models/darknet/darknet_impl.hpp +++ b/models/darknet/darknet_impl.hpp @@ -150,7 +150,6 @@ DarkNet::DarkNet( { darkNet.Add(new AdaptiveMeanPooling<>(1, 1)); darkNet.Add(new Linear<>(curChannels, numClasses)); - darkNet.Add(new Softmax<>()); } darkNet.ResetParameters(); From 0220e38f039a9bc9e325601721bbc029adf02600 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Sat, 8 Aug 2020 12:23:43 +0530 Subject: [PATCH 31/35] Remove extra space after logs --- models/darknet/darknet.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/darknet/darknet.hpp b/models/darknet/darknet.hpp index 7e523d93..dfd20324 100644 --- a/models/darknet/darknet.hpp +++ b/models/darknet/darknet.hpp @@ -248,7 +248,7 @@ class DarkNet inputWidth = std::ceil(inputWidth * 1.0 / factor); inputHeight = std::ceil(inputHeight * 1.0 / factor); mlpack::Log::Info << "(" << inputWidth << ", " << inputHeight << - ")" << std::endl; + ")" << std::endl; } /** From 07d6040ab340804542ccfe078d76bcb695ad5103 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Mon, 10 Aug 2020 13:13:14 +0530 Subject: [PATCH 32/35] Add converted weights --- models/darknet/darknet.hpp | 3 ++- tests/ffn_model_tests.cpp | 34 +++++++++++++++------------------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/models/darknet/darknet.hpp b/models/darknet/darknet.hpp index dfd20324..1f97b599 100644 --- a/models/darknet/darknet.hpp +++ b/models/darknet/darknet.hpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -56,7 +57,7 @@ namespace ann /** Artificial Neural Network. */{ * @tparam DaknetVer Version of DarkNet. */ template< - typename OutputLayerType = NegativeLogLikelihood<>, + typename OutputLayerType = CrossEntropyError<>, typename InitializationRuleType = RandomInitialization, size_t DarkNetVersion = 19 > diff --git a/tests/ffn_model_tests.cpp b/tests/ffn_model_tests.cpp index a047e65d..29c016c6 100644 --- a/tests/ffn_model_tests.cpp +++ b/tests/ffn_model_tests.cpp @@ -23,24 +23,22 @@ BOOST_AUTO_TEST_SUITE(FFNModelsTests); template< typename OptimizerType, - typename OutputLayerType = mlpack::ann::NegativeLogLikelihood<>, + typename OutputLayerType = mlpack::ann::CrossEntropyError<>, typename InitializationRuleType = mlpack::ann::RandomInitialization, class MetricType = mlpack::metric::SquaredEuclideanDistance, typename InputType = arma::mat, typename OutputType = arma::mat > void CheckFFNClassificationWeights(mlpack::ann::FFN& model, const std::string& datasetName, - const double threshold, const bool takeMean, + InitializationRuleType>& model, + InputType& inputFeatures, + OutputType& inputLabels, + const double threshold, + const bool takeMean, OptimizerType& optimizer) { DataLoader dataloader(datasetName, true); - // Train the model. Note: Callbacks such as progress bar and loss aren't - // used in testing. Training the model for few epochs ensures that a - // user can use the pretrained model on any other dataset. - model.Train(dataloader.TrainFeatures(), dataloader.TrainLabels(), optimizer); - // Verify viability of model on validation datset. OutputType predictions; model.Predict(dataloader.ValidFeatures(), predictions); @@ -50,17 +48,23 @@ void CheckFFNClassificationWeights(mlpack::ann::FFN predLabels(predictions.n_cols); for (arma::uword i = 0; i < predictions.n_cols; ++i) { - predLabels(i) = predictions.col(i).index_max() + 1; + predLabels(i) = predictions.col(i).index_max(); } double error = MetricType::Evaluate(predLabels, dataloader.ValidLabels()); if (takeMean) { - error = error / predictions.n_elem; + error = error / predictions.n_elem; } BOOST_REQUIRE_LE(error, threshold); + + + // Train the model. Note: Callbacks such as progress bar and loss aren't + // used in testing. Training the model for few epochs ensures that a + // user can use the pretrained model on any other dataset as well. + model.Train(inputFeatures, inputLabels, optimizer); } /** @@ -68,15 +72,7 @@ void CheckFFNClassificationWeights(mlpack::ann::FFN darknetModel(3, 56, 56, 10); - - // Create an optimizer object for tests. - ens::SGD optimizer(1e-4, 16, 50, - 1e-8, true, ens::AdamUpdate(1e-8, 0.9, 0.999)); - - // Check whether FFN model performs well. - // CheckFFNClassificationWeights>( - // darknetModel1.GetModel(), "mnist", 1e-1, true, optimizer); + mlpack::ann::DarkNet<> darknetModel(3, 224, 224, 1000, "imagenet"); } BOOST_AUTO_TEST_SUITE_END(); From 025db538d9aa985060137b8e1085a842ec04a6d2 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Mon, 10 Aug 2020 16:44:14 +0530 Subject: [PATCH 33/35] Name the saved model same as class --- models/darknet/darknet_impl.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/models/darknet/darknet_impl.hpp b/models/darknet/darknet_impl.hpp index 62b6d498..971d15c6 100644 --- a/models/darknet/darknet_impl.hpp +++ b/models/darknet/darknet_impl.hpp @@ -165,7 +165,7 @@ void DarkNet< OutputLayerType, InitializationRuleType, DarkNetVersion >::LoadModel(const std::string& filePath) { - data::Load(filePath, "DarkNet" + std::to_string(DarkNetVersion), darkNet); + data::Load(filePath, "DarkNet", darkNet); Log::Info << "Loaded model" << std::endl; } @@ -179,7 +179,7 @@ void DarkNet< >::SaveModel(const std::string& filePath) { Log::Info<< "Saving model." << std::endl; - data::Save(filePath, "DarkNet" + std::to_string(DarkNetVersion), darkNet); + data::Save(filePath, "DarkNet", darkNet); Log::Info << "Model saved in " << filePath << "." << std::endl; } From 68780d0fea8dac1d6010cbb1b2be0e6c46f8eeb8 Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Tue, 11 Aug 2020 13:28:22 +0530 Subject: [PATCH 34/35] run tests --- dataloader/preprocessor.hpp | 40 +++++++++++++++++++++ models/darknet/darknet.hpp | 38 +++++++------------- models/darknet/darknet_impl.hpp | 6 ++-- tests/CMakeLists.txt | 1 + tests/ffn_model_tests.cpp | 61 ++++++++------------------------- 5 files changed, 70 insertions(+), 76 deletions(-) diff --git a/dataloader/preprocessor.hpp b/dataloader/preprocessor.hpp index d41d7b23..9d748820 100644 --- a/dataloader/preprocessor.hpp +++ b/dataloader/preprocessor.hpp @@ -55,6 +55,46 @@ class PreProcessor { // Nothing to do here. Added to match the rest of the codebase. } + + /** + * Converts image to channel first format used in PyTorch. Performs the same function + * as torch.transforms.ToTensor(). + * + * @param trainFeatures Input features that will be converted into channel first format. + * @param imageWidth Width of the image in dataset. + * @param imageHeight Height of the image in dataset. + * @param imageDepth Depth / Number of channels of the image in dataset. + */ + static void ChannelFirstImages(DatasetX& trainFeatures, + const size_t imageWidth, + const size_t imageHeight, + const size_t imageDepth, + bool normalize = true) + { + for (size_t idx = 0; idx < trainFeatures.n_cols; idx++) + { + // Create a copy of the current image so that the image isn't affected. + arma::cube inputTemp(trainFeatures.col(idx).memptr(), 3, 224, 224); + + size_t currentOffset = 0; + for (size_t i = 0; i < inputTemp.n_slices; i++) + { + trainFeatures.col(idx)(arma::span(currentOffset, currentOffset + + inputTemp.slice(i).n_elem - 1), arma::span()) = + arma::vectorise(inputTemp.slice(i).t()); + currentOffset += inputTemp.slice(i).n_elem; + } + } + + if (normalize) + { + // Convert each element to uint8 first and then divide by 255. + for (size_t i = 0; i < trainFeatures.n_elem; i++) + { + trainFeatures(i) = ((uint8_t)(trainFeatures(i)) / 255.0); + } + } + } }; #endif diff --git a/models/darknet/darknet.hpp b/models/darknet/darknet.hpp index 1f97b599..d49737e5 100644 --- a/models/darknet/darknet.hpp +++ b/models/darknet/darknet.hpp @@ -127,9 +127,9 @@ class DarkNet * @param padH Padding height of the input. * @param batchNorm Boolean to determine whether a batch normalization * layer is added. + * @param negativeSlope Negative slope hyper-parameter for LeakyReLU. * @param baseLayer Layer in which Convolution block will be added, if * NULL added to darkNet FFN. - * @param negativeSlope Negative slope hyper-parameter for LeakyReLU. */ template> void ConvolutionBlock(const size_t inSize, @@ -141,8 +141,8 @@ class DarkNet const size_t padW = 0, const size_t padH = 0, const bool batchNorm = true, - SequentialType* baseLayer = NULL, - const double negativeSlope = 1e-1) + const double negativeSlope = 1e-1, + SequentialType* baseLayer = NULL) { Sequential<>* bottleNeck = new Sequential<>(); bottleNeck->Add(new Convolution<>(inSize, outSize, kernelWidth, @@ -230,26 +230,12 @@ class DarkNet const size_t padWidth, const size_t padHeight) { - if (type == "max") - { - darkNet.Add(new MaxPooling<>(std::ceil(factor), - std::ceil(factor), factor, factor)); - } - else - { - darkNet.Add(new MeanPooling<>(std::ceil( - factor), std::ceil(factor), factor, 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; + 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); } /** @@ -270,9 +256,9 @@ class DarkNet mlpack::Log::Info << "Residual Block Begin." << std::endl; Residual<>* residualBlock = new Residual<>(); ConvolutionBlock(inputChannel, inputChannel / 2, - 1, 1, 1, 1, 0, 0, true, residualBlock, 1e-2); + 1, 1, 1, 1, 0, 0, true, 1e-2, residualBlock); ConvolutionBlock(inputChannel / 2, inputChannel, kernelWidth, - kernelHeight, 1, 1, padWidth, padWidth, true, residualBlock, 1e-2); + kernelHeight, 1, 1, padWidth, padWidth, true, 1e-2, residualBlock); darkNet.Add(residualBlock); mlpack::Log::Info << "Residual Block end." << std::endl; } @@ -294,7 +280,7 @@ class DarkNet return std::floor(size + 2 * padding - k) / s + 1; } - //! Locally stored LeNet Model. + //! Locally stored DarkNet Model. FFN darkNet; //! Locally stored width of the image. diff --git a/models/darknet/darknet_impl.hpp b/models/darknet/darknet_impl.hpp index 971d15c6..6825b6a7 100644 --- a/models/darknet/darknet_impl.hpp +++ b/models/darknet/darknet_impl.hpp @@ -123,8 +123,8 @@ DarkNet::DarkNet( else if (DarkNetVersion == 53) { darkNet.Add(new IdentityLayer<>()); - ConvolutionBlock(inputChannel, 32, 3, 3, 1, 1, 1, 1, true, NULL, 1e-2); - ConvolutionBlock(32, 64, 3, 3, 2, 2, 1, 1, true, NULL, 1e-2); + ConvolutionBlock(inputChannel, 32, 3, 3, 1, 1, 1, 1, true, 1e-2); + ConvolutionBlock(32, 64, 3, 3, 2, 2, 1, 1, true, 1e-2); // Let's automate this a bit. size_t curChannels = 64; @@ -141,7 +141,7 @@ DarkNet::DarkNet( if (blockCount != 4) { ConvolutionBlock(curChannels, curChannels * 2, 3, 3, - 2, 2, 1, 1, true, NULL, 1e-2); + 2, 2, 1, 1, true, 1e-2); curChannels = curChannels * 2; } } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ded2245a..dacc08f8 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -8,6 +8,7 @@ include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../") add_executable(models_test augmentation_tests.cpp + ffn_model_tests.cpp dataloader_tests.cpp utils_tests.cpp ) diff --git a/tests/ffn_model_tests.cpp b/tests/ffn_model_tests.cpp index 29c016c6..84e42eb7 100644 --- a/tests/ffn_model_tests.cpp +++ b/tests/ffn_model_tests.cpp @@ -21,58 +21,25 @@ using namespace boost::unit_test; BOOST_AUTO_TEST_SUITE(FFNModelsTests); -template< - typename OptimizerType, - typename OutputLayerType = mlpack::ann::CrossEntropyError<>, - typename InitializationRuleType = mlpack::ann::RandomInitialization, - class MetricType = mlpack::metric::SquaredEuclideanDistance, - typename InputType = arma::mat, - typename OutputType = arma::mat -> -void CheckFFNClassificationWeights(mlpack::ann::FFN& model, - InputType& inputFeatures, - OutputType& inputLabels, - const double threshold, - const bool takeMean, - OptimizerType& optimizer) -{ - DataLoader dataloader(datasetName, true); - - // Verify viability of model on validation datset. - OutputType predictions; - model.Predict(dataloader.ValidFeatures(), predictions); - - // Since this checks weights for classification problem, we need to convert - // predictions into labels. - arma::Row predLabels(predictions.n_cols); - for (arma::uword i = 0; i < predictions.n_cols; ++i) - { - predLabels(i) = predictions.col(i).index_max(); - } - - double error = MetricType::Evaluate(predLabels, dataloader.ValidLabels()); - - if (takeMean) - { - error = error / predictions.n_elem; - } - - BOOST_REQUIRE_LE(error, threshold); - - - // Train the model. Note: Callbacks such as progress bar and loss aren't - // used in testing. Training the model for few epochs ensures that a - // user can use the pretrained model on any other dataset as well. - model.Train(inputFeatures, inputLabels, optimizer); -} - /** * Simple test for Darknet model. */ BOOST_AUTO_TEST_CASE(DarknetModelTest) { - mlpack::ann::DarkNet<> darknetModel(3, 224, 224, 1000, "imagenet"); + mlpack::ann::DarkNet<> darknetModel(3, 224, 224, 1000); + arma::mat input(224 * 224 * 3, 1), output; + input.ones(); + + // Check output shape. + darknetModel.GetModel().Predict(input, output); + BOOST_REQUIRE_EQUAL(output.n_cols, 1); + BOOST_REQUIRE_EQUAL(output.n_rows, 1000); + + // Repeat for DarkNet-53. + mlpack::ann::DarkNet<> darknet53(3, 224, 224, 1000); + darknet53.GetModel().Predict(input, output); + BOOST_REQUIRE_EQUAL(output.n_cols, 1); + BOOST_REQUIRE_EQUAL(output.n_rows, 1000); } BOOST_AUTO_TEST_SUITE_END(); From acc4eb044e0459f436f25aaa872219750b73447c Mon Sep 17 00:00:00 2001 From: kartikdutt18 Date: Wed, 12 Aug 2020 16:38:16 +0530 Subject: [PATCH 35/35] Style fixes --- dataloader/preprocessor.hpp | 2 -- ensmallen_utils/periodic_save.hpp | 6 ++---- ensmallen_utils/print_metric.hpp | 4 ++-- models/darknet/darknet.hpp | 29 +++++++++++------------------ models/darknet/darknet_impl.hpp | 6 ++---- 5 files changed, 17 insertions(+), 30 deletions(-) diff --git a/dataloader/preprocessor.hpp b/dataloader/preprocessor.hpp index 9d748820..85887a0b 100644 --- a/dataloader/preprocessor.hpp +++ b/dataloader/preprocessor.hpp @@ -90,9 +90,7 @@ class PreProcessor { // Convert each element to uint8 first and then divide by 255. for (size_t i = 0; i < trainFeatures.n_elem; i++) - { trainFeatures(i) = ((uint8_t)(trainFeatures(i)) / 255.0); - } } } }; diff --git a/ensmallen_utils/periodic_save.hpp b/ensmallen_utils/periodic_save.hpp index 067db076..ad10a832 100644 --- a/ensmallen_utils/periodic_save.hpp +++ b/ensmallen_utils/periodic_save.hpp @@ -33,10 +33,10 @@ class PeriodicSave * @param network Network type which will be saved periodically. * @param filePath Base path / folder where weights will be saved. * @param modelPrefix Weights will be stored as - * modelPrefix_epoch_loss.bin. + * modelPrefix_epoch_loss.bin. * @param period Period after which the model will be saved. * @param silent Boolean to determine whether or not to print saving - * of model. + * of model. * @param output Outputstream where output will be directed. */ PeriodicSave(AnnType& network, @@ -70,9 +70,7 @@ class PeriodicSave objectiveString; mlpack::data::Save(filePath + modelName + ".bin", modelPrefix, network); if (!silent) - { output << "Model saved as " << modelName << std::endl; - } } return false; diff --git a/ensmallen_utils/print_metric.hpp b/ensmallen_utils/print_metric.hpp index 5c0c98e6..b5099c55 100644 --- a/ensmallen_utils/print_metric.hpp +++ b/ensmallen_utils/print_metric.hpp @@ -23,7 +23,7 @@ namespace ens { * * @tparam ANNType Type of model which will be used for evaluating metric. * @tparam MetricType Metric class which must have static `Evaluate` function - * that will be called at the end of the epoch. + * that will be called at the end of the epoch. * @tparam InputType Arma type of dataset features. * @tparam OutputType Arma type of dataset labels. */ @@ -42,7 +42,7 @@ class PrintMetric * @param responses Ground truth label for the mdoel. * @param metricName Metric name which will be printed after each epoch. * @param trainData Boolean to determine whether dataset corresponds to - * training data or validation data. + * training data or validation data. * @param output Outputstream where output will be directed. */ PrintMetric(AnnType &network, diff --git a/models/darknet/darknet.hpp b/models/darknet/darknet.hpp index d49737e5..7b24401c 100644 --- a/models/darknet/darknet.hpp +++ b/models/darknet/darknet.hpp @@ -2,7 +2,7 @@ * @file darknet.hpp * @author Kartik Dutt * - * Definition of Darknet models. + * Definition of DarkNet models. * * For more information, kindly refer to the following paper. * @@ -50,7 +50,7 @@ namespace mlpack { namespace ann /** Artificial Neural Network. */{ /** - * Definition of a Darknet CNN. + * Definition of a DarkNet CNN. * * @tparam OutputLayerType The output layer type used to evaluate the network. * @tparam InitializationRuleType Rule used to initialize the weight matrix. @@ -74,8 +74,8 @@ class DarkNet * @param inputWidth Width of the input image. * @param inputHeight Height of the input image. * @param numClasses Optional number of classes to classify images into, - * only to be specified if includeTop is true. - * @param weights One of 'none', 'cifar10'(pre-training on CIFAR10) or path to weights. + * only to be specified if includeTop is true. + * @param weights One of 'none', 'imagenet'(pre-training on ImageNet) or path to weights. * @param includeTop Must be set to true if weights are set. */ DarkNet(const size_t inputChannel, @@ -89,12 +89,11 @@ class DarkNet * DarkNet constructor intializes input shape and number of classes. * * @param inputShape A three-valued tuple indicating input shape. - * First value is number of Channels (Channels-First). - * Second value is input height. - * Third value is input width.. + * First value is number of channels (channels-first). + * Second value is input height. Third value is input width. * @param numClasses Optional number of classes to classify images into, - * only to be specified if includeTop is true. - * @param weights One of 'none', 'cifar10'(pre-training on CIFAR10) or path to weights. + * only to be specified if includeTop is true. + * @param weights One of 'none', 'imagenet'(pre-training on ImageNet) or path to weights. */ DarkNet(const std::tuple inputShape, const size_t numClasses = 1000, @@ -115,7 +114,7 @@ class DarkNet * Adds Convolution Block. * * @tparam SequentialType Layer type in which convolution block will - * be added. + * be added. * * @param inSize Number of input maps. * @param outSize Number of output maps. @@ -126,7 +125,7 @@ class DarkNet * @param padW Padding width of the input. * @param padH Padding height of the input. * @param batchNorm Boolean to determine whether a batch normalization - * layer is added. + * layer is added. * @param negativeSlope Negative slope hyper-parameter for LeakyReLU. * @param baseLayer Layer in which Convolution block will be added, if * NULL added to darkNet FFN. @@ -160,20 +159,14 @@ class DarkNet ", " << outSize << ")" << std::endl; if (batchNorm) - { bottleNeck->Add(new BatchNorm<>(outSize, 1e-5, false)); - } bottleNeck->Add(new LeakyReLU<>(negativeSlope)); if (baseLayer != NULL) - { baseLayer->Add(bottleNeck); - } else - { darkNet.Add(bottleNeck); - } } /** @@ -181,7 +174,7 @@ class DarkNet * * @param factor The factor by which input dimensions will be divided. * @param type One of "max" or "mean". Determines whether add mean pooling - * layer or max pooling layer. + * layer or max pooling layer. */ void PoolingBlock(const size_t factor = 2, const std::string type = "max") diff --git a/models/darknet/darknet_impl.hpp b/models/darknet/darknet_impl.hpp index 6825b6a7..ec2567b7 100644 --- a/models/darknet/darknet_impl.hpp +++ b/models/darknet/darknet_impl.hpp @@ -2,7 +2,7 @@ * @file darknet_impl.hpp * @author Kartik Dutt * - * Implementation of LeNet using mlpack. + * Implementation of DarkNet using mlpack. * * mlpack is free software; you may redistribute it and/or modify it under the * terms of the 3-clause BSD license. You should have received a copy of the @@ -113,7 +113,7 @@ DarkNet::DarkNet( if (includeTop) { darkNet.Add(new Convolution<>(1024, numClasses, 1, 1, - 1, 1, 0, 0, inputWidth, inputHeight)); + 1, 1, 0, 0, inputWidth, inputHeight)); darkNet.Add(new AdaptiveMeanPooling<>(1, 1)); darkNet.Add(new LogSoftMax<>()); } @@ -134,9 +134,7 @@ DarkNet::DarkNet( for (size_t blockCount : residualBlockConfig) { for (size_t i = 0; i < blockCount; i++) - { DarkNet53ResidualBlock(curChannels); - } if (blockCount != 4) {