diff --git a/src/mlpack/methods/ann/layer/atrous_convolution_impl.hpp b/src/mlpack/methods/ann/layer/atrous_convolution_impl.hpp index 519a409760..bac305fa33 100644 --- a/src/mlpack/methods/ann/layer/atrous_convolution_impl.hpp +++ b/src/mlpack/methods/ann/layer/atrous_convolution_impl.hpp @@ -215,10 +215,9 @@ void AtrousConvolution< if (padW != 0 || padH != 0) { - gTemp.slice(inMap + batchCount * inSize) += output.submat( - rotatedFilter.n_rows / 2, rotatedFilter.n_cols / 2, - rotatedFilter.n_rows / 2 + gTemp.n_rows - 1, - rotatedFilter.n_cols / 2 + gTemp.n_cols - 1); + gTemp.slice(inMap + batchCount * inSize) += output.submat(padW, padH, + padW + gTemp.n_rows - 1, + padH + gTemp.n_cols - 1); } else { @@ -308,10 +307,9 @@ void AtrousConvolution< (gradientTemp.n_rows < output.n_rows && gradientTemp.n_cols < output.n_cols)) { - gradientTemp.slice(outMapIdx) += output.submat(output.n_rows / 2, - output.n_cols / 2, - output.n_rows / 2 + gradientTemp.n_rows - 1, - output.n_cols / 2 + gradientTemp.n_cols - 1); + gradientTemp.slice(outMapIdx) += output.submat(padW, padH, + padW + gradientTemp.n_rows - 1, + padH + gradientTemp.n_cols - 1); } else { diff --git a/src/mlpack/methods/ann/layer/convolution_impl.hpp b/src/mlpack/methods/ann/layer/convolution_impl.hpp index 1eba6478a7..e06905b845 100644 --- a/src/mlpack/methods/ann/layer/convolution_impl.hpp +++ b/src/mlpack/methods/ann/layer/convolution_impl.hpp @@ -208,10 +208,9 @@ void Convolution< if (padW != 0 || padH != 0) { - gTemp.slice(inMap + batchCount * inSize) += output.submat( - rotatedFilter.n_rows / 2, rotatedFilter.n_cols / 2, - rotatedFilter.n_rows / 2 + gTemp.n_rows - 1, - rotatedFilter.n_cols / 2 + gTemp.n_cols - 1); + gTemp.slice(inMap + batchCount * inSize) += output.submat(padW, padH, + padW + gTemp.n_rows - 1, + padH + gTemp.n_cols - 1); } else { @@ -288,10 +287,9 @@ void Convolution< (gradientTemp.n_rows < output.n_rows && gradientTemp.n_cols < output.n_cols)) { - gradientTemp.slice(outMapIdx) += output.submat(output.n_rows / 2, - output.n_cols / 2, - output.n_rows / 2 + gradientTemp.n_rows - 1, - output.n_cols / 2 + gradientTemp.n_cols - 1); + gradientTemp.slice(outMapIdx) += output.submat(padW, padH, + padW + gradientTemp.n_rows - 1, + padH + gradientTemp.n_cols - 1); } else { diff --git a/src/mlpack/methods/ann/layer/leaky_relu.hpp b/src/mlpack/methods/ann/layer/leaky_relu.hpp index dfa7af8e92..a5ef7ed6d8 100644 --- a/src/mlpack/methods/ann/layer/leaky_relu.hpp +++ b/src/mlpack/methods/ann/layer/leaky_relu.hpp @@ -46,7 +46,7 @@ class LeakyReLU public: /** * Create the LeakyReLU object using the specified parameters. - * The non zero gradient can be adjusted by specifying tha parameter + * The non zero gradient can be adjusted by specifying the parameter * alpha in the range 0 to 1. Default (alpha = 0.03) * * @param alpha Non zero gradient diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt index bf6dfa75b1..a32e5407d5 100644 --- a/src/mlpack/tests/CMakeLists.txt +++ b/src/mlpack/tests/CMakeLists.txt @@ -26,6 +26,7 @@ add_executable(mlpack_test cosine_tree_test.cpp cv_test.cpp dbscan_test.cpp + dcgan_test.cpp decision_stump_test.cpp decision_tree_test.cpp det_test.cpp diff --git a/src/mlpack/tests/dcgan_test.cpp b/src/mlpack/tests/dcgan_test.cpp new file mode 100644 index 0000000000..1fb94714f3 --- /dev/null +++ b/src/mlpack/tests/dcgan_test.cpp @@ -0,0 +1,280 @@ +/** + * @file dcgan_network_test.cpp + * @author Shikhar Jaiswal + * + * Tests the DCGAN network. + * + * 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 "test_tools.hpp" + +using namespace mlpack; +using namespace mlpack::ann; +using namespace mlpack::math; +using namespace mlpack::optimization; +using namespace mlpack::regression; +using namespace std::placeholders; + +BOOST_AUTO_TEST_SUITE(DCGANNetworkTest); + +/* + * Tests the DCGAN implementation on the MNIST dataset. + * It's not viable to train on bigger parameters due to time constraints. + * Please refer mlpack/models repository for the tutorial. + */ +BOOST_AUTO_TEST_CASE(DCGANMNISTTest) +{ + size_t dNumKernels = 32; + size_t discriminatorPreTrain = 5; + size_t batchSize = 5; + size_t noiseDim = 100; + size_t generatorUpdateStep = 1; + size_t numSamples = 10; + double stepSize = 0.0003; + double eps = 1e-8; + size_t numEpoches = 1; + double tolerance = 1e-5; + int datasetMaxCols = 10; + bool shuffle = true; + double multiplier = 10; + + Log::Info << std::boolalpha + << " batchSize = " << batchSize << std::endl + << " generatorUpdateStep = " << generatorUpdateStep << std::endl + << " noiseDim = " << noiseDim << std::endl + << " numSamples = " << numSamples << std::endl + << " stepSize = " << stepSize << std::endl + << " numEpoches = " << numEpoches << std::endl + << " tolerance = " << tolerance << std::endl + << " shuffle = " << shuffle << std::endl; + + arma::mat trainData; + trainData.load("mnist_first250_training_4s_and_9s.arm"); + Log::Info << arma::size(trainData) << std::endl; + + if (datasetMaxCols > 0) + trainData = trainData.cols(0, datasetMaxCols - 1); + + size_t numIterations = trainData.n_cols * numEpoches; + numIterations /= batchSize; + + Log::Info << "Dataset loaded (" << trainData.n_rows << ", " + << trainData.n_cols << ")" << std::endl; + Log::Info << trainData.n_rows << "--------" << trainData.n_cols << std::endl; + + // Create the Discriminator network + FFN > discriminator; + discriminator.Add >(1, dNumKernels, 4, 4, 2, 2, 1, 1, 28, 28); + discriminator.Add >(0.2); + discriminator.Add >(dNumKernels, 2 * dNumKernels, 4, 4, 2, 2, + 1, 1, 14, 14); + discriminator.Add >(0.2); + discriminator.Add >(2 * dNumKernels, 4 * dNumKernels, 4, 4, + 2, 2, 1, 1, 7, 7); + discriminator.Add >(0.2); + discriminator.Add >(4 * dNumKernels, 8 * dNumKernels, 4, 4, + 2, 2, 2, 2, 3, 3); + discriminator.Add >(0.2); + discriminator.Add >(8 * dNumKernels, 1, 4, 4, 1, 1, + 1, 1, 2, 2); + discriminator.Add >(); + + // Create the Generator network + FFN > generator; + generator.Add >(noiseDim, 8 * dNumKernels, 2, 2, + 1, 1, 1, 1, 1, 1); + generator.Add >(); + generator.Add >(8 * dNumKernels, 4 * dNumKernels, + 2, 2, 1, 1, 0, 0, 2, 2); + generator.Add >(); + generator.Add >(4 * dNumKernels, 2 * dNumKernels, + 5, 5, 2, 2, 1, 1, 3, 3); + generator.Add >(); + generator.Add >(2 * dNumKernels, dNumKernels, 8, 8, + 1, 1, 1, 1, 7, 7); + generator.Add >(); + generator.Add >(dNumKernels, 1, 15, 15, 1, 1, 1, 1, + 14, 14); + generator.Add >(); + + // Create GAN + GaussianInitialization gaussian(0, 1); + Adam optimizer(stepSize, batchSize, 0.9, 0.999, eps, numIterations, + tolerance, shuffle); + std::function noiseFunction = [] () { + return math::RandNormal(0, 1);}; + GAN >, GaussianInitialization, + std::function > gan(trainData, generator, discriminator, + gaussian, noiseFunction, noiseDim, batchSize, generatorUpdateStep, + discriminatorPreTrain, multiplier); + + Log::Info << "Training..." << std::endl; + gan.Train(optimizer); + + // Generate samples + Log::Info << "Sampling..." << std::endl; + arma::mat noise(noiseDim, 1); + size_t dim = std::sqrt(trainData.n_rows); + arma::mat generatedData(2 * dim, dim * numSamples); + + for (size_t i = 0; i < numSamples; i++) + { + arma::mat samples; + noise.imbue( [&]() { return noiseFunction(); } ); + + generator.Forward(noise, samples); + samples.reshape(dim, dim); + samples = samples.t(); + + generatedData.submat(0, i * dim, dim - 1, i * dim + dim - 1) = samples; + + samples = trainData.col(math::RandInt(0, trainData.n_cols)); + samples.reshape(dim, dim); + samples = samples.t(); + + generatedData.submat(dim, + i * dim, 2 * dim - 1, i * dim + dim - 1) = samples; + } + + Log::Info << "Output generated!" << std::endl; +} + +/* + * Tests the DCGAN implementation on the CelebA dataset. + * It's currently not possible to run this every time due to time constraints. + * Please refer mlpack/models repository for the tutorial. + +BOOST_AUTO_TEST_CASE(DCGANCelebATest) +{ + size_t dNumKernels = 64; + size_t discriminatorPreTrain = 300; + size_t batchSize = 1; + size_t noiseDim = 100; + size_t generatorUpdateStep = 1; + size_t numSamples = 10; + double stepSize = 0.0003; + double eps = 1e-8; + size_t numEpoches = 20; + double tolerance = 1e-5; + int datasetMaxCols = -1; + bool shuffle = true; + double multiplier = 10; + + Log::Info << std::boolalpha + << " batchSize = " << batchSize << std::endl + << " generatorUpdateStep = " << generatorUpdateStep << std::endl + << " noiseDim = " << noiseDim << std::endl + << " numSamples = " << numSamples << std::endl + << " stepSize = " << stepSize << std::endl + << " numEpoches = " << numEpoches << std::endl + << " tolerance = " << tolerance << std::endl + << " shuffle = " << shuffle << std::endl; + + arma::mat trainData; + trainData.load("celeba.csv"); + Log::Info << arma::size(trainData) << std::endl; + + if (datasetMaxCols > 0) + trainData = trainData.cols(0, datasetMaxCols - 1); + + size_t numIterations = trainData.n_cols * numEpoches; + numIterations /= batchSize; + + Log::Info << "Dataset loaded (" << trainData.n_rows << ", " + << trainData.n_cols << ")" << std::endl; + Log::Info << trainData.n_rows << "--------" << trainData.n_cols << std::endl; + + // Create the Discriminator network + FFN > discriminator; + discriminator.Add >(3, dNumKernels, 4, 4, 2, 2, 1, 1, 64, 64); + discriminator.Add >(0.2); + discriminator.Add >(dNumKernels, 2 * dNumKernels, 4, 4, 2, 2, + 1, 1, 32, 32); + discriminator.Add >(0.2); + discriminator.Add >(2 * dNumKernels, 4 * dNumKernels, 4, 4, + 2, 2, 1, 1, 16, 16); + discriminator.Add >(0.2); + discriminator.Add >(4 * dNumKernels, 8 * dNumKernels, 4, 4, + 2, 2, 1, 1, 8, 8); + discriminator.Add >(0.2); + discriminator.Add >(8 * dNumKernels, 1, 4, 4, 1, 1, + 0, 0, 4, 4); + discriminator.Add >(); + + // Create the Generator network + FFN > generator; + generator.Add >(noiseDim, 8 * dNumKernels, 4, 4, + 1, 1, 2, 2, 1, 1); + generator.Add >(); + generator.Add >(8 * dNumKernels, 4 * dNumKernels, + 5, 5, 1, 1, 1, 1, 4, 4); + generator.Add >(); + generator.Add >(4 * dNumKernels, 2 * dNumKernels, + 9, 9, 1, 1, 1, 1, 8, 8); + generator.Add >(); + generator.Add >(2 * dNumKernels, dNumKernels, 17, 17, + 1, 1, 1, 1, 16, 16); + generator.Add >(); + generator.Add >(dNumKernels, 3, 33, 33, 1, 1, 1, 1, + 32, 32); + generator.Add >(); + + // Create GAN + GaussianInitialization gaussian(0, 1); + Adam optimizer(stepSize, batchSize, 0.9, 0.999, eps, numIterations, + tolerance, shuffle); + std::function noiseFunction = [] () { + return math::RandNormal(0, 1);}; + GAN >, GaussianInitialization, + std::function > gan(trainData, generator, discriminator, + gaussian, noiseFunction, noiseDim, batchSize, generatorUpdateStep, + discriminatorPreTrain, multiplier); + + Log::Info << "Training..." << std::endl; + gan.Train(optimizer); + + // Generate samples + Log::Info << "Sampling..." << std::endl; + arma::mat noise(noiseDim, 1); + size_t dim = std::sqrt(trainData.n_rows); + arma::mat generatedData(2 * dim, dim * numSamples); + + for (size_t i = 0; i < numSamples; i++) + { + arma::mat samples; + noise.imbue( [&]() { return noiseFunction(); } ); + + generator.Forward(noise, samples); + samples.reshape(dim, dim); + samples = samples.t(); + + generatedData.submat(0, i * dim, dim - 1, i * dim + dim - 1) = samples; + + samples = trainData.col(math::RandInt(0, trainData.n_cols)); + samples.reshape(dim, dim); + samples = samples.t(); + + generatedData.submat(dim, + i * dim, 2 * dim - 1, i * dim + dim - 1) = samples; + } + + Log::Info << "Output generated!" << std::endl; +} +*/ + +BOOST_AUTO_TEST_SUITE_END(); diff --git a/src/mlpack/tests/gan_test.cpp b/src/mlpack/tests/gan_test.cpp index 40fc4c12f2..a6d47c6f9e 100644 --- a/src/mlpack/tests/gan_test.cpp +++ b/src/mlpack/tests/gan_test.cpp @@ -132,28 +132,26 @@ BOOST_AUTO_TEST_CASE(GANTest) } /* - * Tests the GAN implementation on the O'Reilly Test on the MNIST dataset. - * It's currently not possible to run this every time due to time constraints. + * Tests the GAN implementation of the O'Reilly Test on the MNIST dataset. + * It's not viable to train on bigger parameters due to time constraints. * Please refer mlpack/models repository for the tutorial. - + */ BOOST_AUTO_TEST_CASE(GANMNISTTest) { size_t dNumKernels = 32; - size_t discriminatorPreTrain = 300; - size_t batchSize = 50; + size_t discriminatorPreTrain = 5; + size_t batchSize = 5; size_t noiseDim = 100; size_t generatorUpdateStep = 1; size_t numSamples = 10; double stepSize = 0.0003; double eps = 1e-8; - size_t numEpoches = 20; + size_t numEpoches = 1; double tolerance = 1e-5; - int datasetMaxCols = -1; + int datasetMaxCols = 10; bool shuffle = true; double multiplier = 10; - std::string output_dataset = "output_mnist.csv"; - Log::Info << "output_dataset = '" << output_dataset << "'" << std::endl; Log::Info << std::boolalpha << " batchSize = " << batchSize << std::endl << " generatorUpdateStep = " << generatorUpdateStep << std::endl @@ -244,10 +242,7 @@ BOOST_AUTO_TEST_CASE(GANMNISTTest) i * dim, 2 * dim - 1, i * dim + dim - 1) = samples; } - Log::Info << "Saving output to " << output_dataset << "..." << std::endl; - generatedData.save(output_dataset, arma::csv_ascii); - Log::Info << "Output saved!" << std::endl; + Log::Info << "Output generated!" << std::endl; } -*/ BOOST_AUTO_TEST_SUITE_END();