Skip to content

Commit b354d5a

Browse files
Merge branch 'mlpack:master' into gan-mnist
2 parents e4f0597 + a640ca9 commit b354d5a

File tree

16 files changed

+3424
-25
lines changed

16 files changed

+3424
-25
lines changed

avocado_price_prediction_with_linear_regression/avocado_price_prediction_with_lr_cpp.ipynb

Lines changed: 705 additions & 0 deletions
Large diffs are not rendered by default.

avocado_price_prediction_with_linear_regression/avocado_price_prediction_with_lr_py.ipynb

Lines changed: 979 additions & 0 deletions
Large diffs are not rendered by default.

mnist_vae_cnn/generate_images.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
"""
2+
@file generate_images.py
3+
@author Atharva Khandait
4+
5+
Generates jpg files from csv.
6+
7+
mlpack is free software; you may redistribute it and/or modify it under the
8+
terms of the 3-clause BSD license. You should have received a copy of the
9+
3-clause BSD license along with mlpack. If not, see
10+
http://www.opensource.org/licenses/BSD-3-Clause for more information.
11+
"""
12+
13+
from PIL import Image
14+
import numpy as np
15+
16+
def ImagesFromCSV(filename,
17+
imgShape = (28, 28),
18+
destination = 'samples',
19+
saveIndividual = False):
20+
21+
# Import the data into a numpy matrix.
22+
samples = np.genfromtxt(filename, delimiter = ',', dtype = np.uint8)
23+
24+
# Reshape and save it as an image in the destination.
25+
tempImage = Image.fromarray(np.reshape(samples[:, 0], imgShape), 'L')
26+
if saveIndividual:
27+
tempImage.save(destination + '/sample0.jpg')
28+
29+
# All the images will be concatenated to this for a combined image.
30+
allSamples = tempImage
31+
32+
for i in range(1, samples.shape[1]):
33+
tempImage = np.reshape(samples[:, i], imgShape)
34+
35+
allSamples = np.concatenate((allSamples, tempImage), axis = 1)
36+
37+
tempImage = Image.fromarray(tempImage, 'L')
38+
if saveIndividual:
39+
tempImage.save(destination + '/sample' + str(i) + '.jpg')
40+
41+
tempImage = allSamples
42+
allSamples = Image.fromarray(allSamples, 'L')
43+
allSamples.save(destination + '/allSamples' + '.jpg')
44+
45+
print ('Samples saved in ' + destination + '/.')
46+
47+
return tempImage
48+
49+
# Save posterior samples.
50+
ImagesFromCSV('./samples_csv_files/samples_posterior.csv', destination =
51+
'samples_posterior')
52+
53+
# Save prior samples with individual latent varying.
54+
latentSize = 10
55+
allLatent = ImagesFromCSV('./samples_csv_files/samples_prior_latent0.csv',
56+
destination = 'samples_prior')
57+
58+
for i in range(1, latentSize):
59+
allLatent = np.concatenate((allLatent,
60+
(ImagesFromCSV('./samples_csv_files/samples_prior_latent' + str(i) + '.csv',
61+
destination = 'samples_prior'))), axis = 0)
62+
63+
saved = Image.fromarray(allLatent, 'L')
64+
saved.save('./samples_prior/allLatent.jpg')
65+
66+
# Save prior samples with 2d latent varying.
67+
nofSamples = 20
68+
allLatent = ImagesFromCSV('./samples_csv_files/samples_prior_latent_2d0.csv',
69+
destination = 'latent')
70+
71+
for i in range(1, nofSamples):
72+
allLatent = np.concatenate((allLatent,
73+
(ImagesFromCSV('./samples_csv_files/samples_prior_latent_2d' + str(i) +
74+
'.csv', destination = 'samples_prior'))), axis = 0)
75+
76+
saved = Image.fromarray(allLatent, 'L')
77+
saved.save('./samples_prior/2dLatent.jpg')
2.93 KB
Loading

mnist_vae_cnn/mnist_vae_cnn.cpp

Lines changed: 50 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,10 @@ int main()
4646
constexpr int batchSize = 64;
4747
// The step size of the optimizer.
4848
constexpr double stepSize = 0.001;
49-
// The maximum number of possible iteration
50-
constexpr int maxIteration = 0;
49+
// Number of epochs/ cycle
50+
constexpr int epochs = 1;
51+
// Number of cycles
52+
constexpr int cycles = 10;
5153
// Whether to load a model to train.
5254
constexpr bool loadModel = false;
5355
// Whether to save the trained model.
@@ -60,9 +62,18 @@ int main()
6062
// Entire dataset(without labels) is loaded from a CSV file.
6163
// Each column represents a data point.
6264
arma::mat fullData;
63-
data::Load("../data/mnist_train.csv", fullData, true, false);
65+
data::Load("../data/mnist_train.csv", fullData, true, true);
66+
67+
// Originally on Kaggle dataset CSV file has header, so it's necessary to
68+
// get rid of this row, in Armadillo representation it's the first column.
69+
fullData =
70+
fullData.submat(0, 1, fullData.n_rows -1, fullData.n_cols -1);
6471
fullData /= 255.0;
6572

73+
// Get rid of the labels
74+
fullData =
75+
fullData.submat(1, 0, fullData.n_rows - 1, fullData.n_cols -1);
76+
6677
if (isBinary)
6778
{
6879
fullData = arma::conv_to<arma::mat>::from(
@@ -75,10 +86,13 @@ int main()
7586

7687
arma::mat train, validation;
7788
data::Split(fullData, validation, train, trainRatio);
78-
89+
7990
// Loss is calculated on train_test data after each cycle.
80-
arma::mat train_test, dump;
81-
data::Split(train, dump, train_test, 0.045);
91+
arma::mat trainTest, dump;
92+
data::Split(train, dump, trainTest, 0.045);
93+
94+
// No of iterations of the optimizer.
95+
int iterPerCycle = (epochs * train.n_cols);
8296

8397
/**
8498
* Model architecture:
@@ -102,7 +116,7 @@ int main()
102116
* size 5x5, stride = 1, padding = 0) ---> 14x14x16
103117
* 14x14x16 ------------- Leaky ReLU ------------> 14x14x16
104118
* 14x14x16 ---- transposed conv (1 filter of
105-
* size 15x15, stride = 1, padding = 1) -> 28x28x1
119+
* size 15x15, stride = 0, padding = 1) -> 28x28x1
106120
*/
107121

108122
// Creating the VAE model.
@@ -171,10 +185,13 @@ int main()
171185
0, // Padding width.
172186
0, // Padding height.
173187
10, // Input width.
174-
10); // Input height.
188+
10, // Input height.
189+
14, // Output width.
190+
14); // Output height.
175191

176192
decoder->Add<LeakyReLU<>>();
177-
decoder->Add<TransposedConvolution<>>(16, 1, 15, 15, 1, 1, 1, 1, 14, 14);
193+
decoder->Add<TransposedConvolution<>>
194+
(16, 1, 15, 15, 1, 1, 0, 0, 14, 14, 28, 28);
178195

179196
vaeModel.Add(decoder);
180197
}
@@ -189,27 +206,37 @@ int main()
189206
0.9, // Exponential decay rate for the first moment estimates.
190207
0.999, // Exponential decay rate for the weighted infinity norm estimates.
191208
1e-8, // Value used to initialise the mean squared gradient parameter.
192-
maxIteration, // Max number of iterations.
209+
iterPerCycle, // Max number of iterations.
193210
1e-8, // Tolerance.
194211
true);
212+
213+
const clock_t beginTime = clock();
214+
// Cycles for monitoring the progress.
215+
for (int i = 0; i < cycles; i++)
216+
{
217+
// Train neural network. If this is the first iteration, weights are
218+
// random, using current values as starting point otherwise.
219+
vaeModel.Train(train,
220+
train,
221+
optimizer,
222+
ens::PrintLoss(),
223+
ens::ProgressBar(),
224+
ens::Report());
225+
226+
// Don't reset optimizer's parameters between cycles.
227+
optimizer.ResetPolicy() = false;
228+
229+
std::cout << "Loss after cycle " << i << " -> " <<
230+
MeanTestLoss<MeanSModel>(vaeModel, trainTest, batchSize) << std::endl;
231+
}
195232

196-
std::cout << "Initial loss -> "
197-
<< MeanTestLoss<MeanSModel>(vaeModel, train_test, 50) << std::endl;
198-
199-
// Train neural network. If this is the first iteration, weights are
200-
// random, using current values as starting point otherwise.
201-
vaeModel.Train(train,
202-
train,
203-
optimizer,
204-
ens::PrintLoss(),
205-
ens::ProgressBar(),
206-
// Stop the training using Early Stop at min loss.
207-
ens::EarlyStopAtMinLoss());
233+
std::cout << "Time taken to train -> " << float(clock() - beginTime) /
234+
CLOCKS_PER_SEC << " seconds" << std::endl;
208235

209236
// Save the model if specified.
210237
if (saveModel)
211238
{
212-
data::Save("vae/saved_models/vaeCNN.bin", "vaeCNN", vaeModel);
239+
data::Save("./saved_models/vaeCNN.bin", "vaeCNN", vaeModel);
213240
std::cout << "Model saved in vae/saved_models." << std::endl;
214241
}
215242
}
3.44 KB
Loading
48.6 KB
Loading
30.3 KB
Loading
3 KB
Loading

mnist_vae_cnn/vae_generate.cpp

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
/**
2+
* @file vae_generate.cpp
3+
* @author Atharva Khandait
4+
*
5+
* Generate MNIST using trained VAE model.
6+
*
7+
* mlpack is free software; you may redistribute it and/or modify it under the
8+
* terms of the 3-clause BSD license. You should have received a copy of the
9+
* 3-clause BSD license along with mlpack. If not, see
10+
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
11+
*/
12+
#include <mlpack/core.hpp>
13+
#include <mlpack/core/data/split_data.hpp>
14+
#include <mlpack/core/data/save.hpp>
15+
16+
#include <mlpack/methods/ann/ffn.hpp>
17+
#include <mlpack/methods/ann/layer/layer.hpp>
18+
#include <mlpack/methods/ann/init_rules/he_init.hpp>
19+
#include <mlpack/methods/ann/loss_functions/reconstruction_loss.hpp>
20+
#include <mlpack/methods/ann/loss_functions/mean_squared_error.hpp>
21+
#include <mlpack/methods/ann/dists/bernoulli_distribution.hpp>
22+
23+
#include "vae_utils.hpp"
24+
25+
using namespace mlpack;
26+
using namespace mlpack::ann;
27+
28+
// Convenience typedef
29+
typedef FFN<ReconstructionLoss<arma::mat,
30+
arma::mat,
31+
BernoulliDistribution<arma::mat> >,
32+
HeInitialization> ReconModel;
33+
34+
int main()
35+
{
36+
// Whether to load training data.
37+
constexpr bool loadData = true;
38+
// The number of samples to generate.
39+
constexpr size_t nofSamples = 20;
40+
// Whether modelled on binary data.
41+
constexpr bool isBinary = false;
42+
// the latent size of the VAE model.
43+
constexpr size_t latentSize = 20;
44+
45+
arma::mat fullData, train, validation;
46+
47+
if (loadData)
48+
{
49+
data::Load("../data/mnist_train.csv", fullData, true, false);
50+
// Get rid of the header.
51+
fullData =
52+
fullData.submat(0, 1, fullData.n_rows - 1, fullData.n_cols -1);
53+
fullData /= 255.0;
54+
// Get rid of the labels.
55+
fullData =
56+
fullData.submat(1, 0, fullData.n_rows - 1, fullData.n_cols - 1);
57+
58+
if (isBinary)
59+
{
60+
fullData = arma::conv_to<arma::mat>::from(arma::randu<arma::mat>
61+
(fullData.n_rows, fullData.n_cols) <= fullData);
62+
}
63+
else
64+
fullData = (fullData - 0.5) * 2;
65+
66+
data::Split(fullData, validation, train, 0.8);
67+
}
68+
69+
arma::arma_rng::set_seed_random();
70+
71+
// It doesn't matter what type of network we initialize, as we only need to
72+
// forward pass throught it and not initialize weights or take loss.
73+
FFN<> vaeModel;
74+
75+
// Load the trained model.
76+
if (isBinary)
77+
{
78+
data::Load("./saved_models/vaeBinaryMS.xml", "vaeBinaryMS", vaeModel);
79+
vaeModel.Add<SigmoidLayer<> >();
80+
}
81+
else
82+
{
83+
data::Load("./saved_models/vaeCNN.bin", "vaeMS", vaeModel);
84+
}
85+
86+
arma::mat gaussianSamples, outputDists, samples;
87+
88+
/*
89+
* Sampling from the prior.
90+
*/
91+
gaussianSamples = arma::randn<arma::mat>(latentSize, nofSamples);
92+
93+
// Forward pass only through the decoder(and Sigmod layer in case of binary).
94+
vaeModel.Forward(gaussianSamples,
95+
outputDists,
96+
3 /* Index of the decoder */,
97+
3 + (size_t)isBinary /* Index of the last layer */);
98+
99+
GetSample(outputDists, samples, isBinary);
100+
// Save the prior samples as csv.
101+
data::Save("./samples_csv_files/samples_prior.csv", samples, false, false);
102+
103+
/*
104+
* Sampling from the prior by varying all latent variables.
105+
*/
106+
arma::mat gaussianVaried;
107+
108+
for (size_t i = 0; i < latentSize; i++)
109+
{
110+
gaussianSamples = arma::randn<arma::mat>(latentSize, 1);
111+
gaussianVaried = arma::zeros(latentSize, nofSamples);
112+
gaussianVaried.each_col() = gaussianSamples;
113+
114+
for (size_t j = 0; j < nofSamples; j++)
115+
{
116+
gaussianVaried.col(j)(i) = -1.5 + j * (3.0 / nofSamples);
117+
}
118+
119+
// Forward pass only through the decoder
120+
// (and Sigmod layer in case of binary).
121+
vaeModel.Forward(gaussianVaried,
122+
outputDists,
123+
3 /* Index of the decoder */,
124+
3 + (size_t)isBinary /* Index of the last layer */);
125+
126+
GetSample(outputDists, samples, isBinary);
127+
// Save the prior samples as csv.
128+
data::Save(
129+
"./samples_csv_files/samples_prior_latent" + std::to_string(i) + ".csv",
130+
samples,
131+
false,
132+
false);
133+
}
134+
135+
/*
136+
* Sampling from the prior by varying two latent variables in 2d.
137+
*/
138+
size_t latent1 = 3; // Latent variable to be varied vertically.
139+
size_t latent2 = 4; // Latent variable to be varied horizontally.
140+
141+
for (size_t i = 0; i < nofSamples; i++)
142+
{
143+
gaussianVaried = arma::zeros(latentSize, nofSamples);
144+
145+
for (size_t j = 0; j < nofSamples; j++)
146+
{
147+
// Set the vertical variable to a constant value for the outer loop.
148+
gaussianVaried.col(j)(latent1) = 1.5 - i * (3.0 / nofSamples);
149+
// Vary the horizontal variable from -1.5 to 1.5.
150+
gaussianVaried.col(j)(latent2) = -1.5 + j * (3.0 / nofSamples);
151+
}
152+
153+
// Forward pass only through the decoder
154+
// (and Sigmod layer in case of binary).
155+
vaeModel.Forward(gaussianVaried,
156+
outputDists,
157+
3 /* Index of the decoder */,
158+
3 + (size_t)isBinary /* Index of the last layer */);
159+
160+
GetSample(outputDists, samples, isBinary);
161+
// Save the prior samples as csv.
162+
data::Save("./samples_csv_files/samples_prior_latent_2d" + std::to_string(i)
163+
+ ".csv", samples, false, false);
164+
}
165+
166+
/*
167+
* Sampling from the posterior.
168+
*/
169+
if (loadData)
170+
{
171+
// Forward pass through the entire network given an input datapoint.
172+
vaeModel.Forward(validation.cols(0, 19),
173+
outputDists,
174+
1 /* Index of the encoder */,
175+
3 + (size_t)isBinary /* Index of the last layer */);
176+
177+
GetSample(outputDists, samples, isBinary);
178+
// Save the posterior samples as csv.
179+
data::Save(
180+
"./samples_csv_files/samples_posterior.csv",
181+
samples,
182+
false,
183+
false);
184+
}
185+
}

0 commit comments

Comments
 (0)