1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
| #include <iostream>
#include <string>
#include "tiny_dnn/tiny_dnn.h"
using namespace tiny_dnn;
using namespace tiny_dnn::activation;
using namespace tiny_dnn::layers;
using namespace std;
#define EPOCHS 50
#define BATCH_SIZE 256
void sae() {
// define network, optimizer and engine
network<sequential> net;
adam optimizer;
core::backend_t backend_type = core::default_engine();
// construct network layers, include 3 encoder layers and 3 decoder layers
net << fully_connected_layer(784, 128, true, backend_type) << relu()
<< fully_connected_layer(128, 64, true, backend_type) << relu()
<< fully_connected_layer(64, 32, true, backend_type) << relu()
<< fully_connected_layer(32, 64, true, backend_type) << relu()
<< fully_connected_layer(64, 128, true, backend_type) << sigmoid()
<< fully_connected_layer(128, 784, true, backend_type);
// load MNIST dataset
vector<vec_t> train_images, test_images;
string data_dir_path = "tiny_dnn/data";
parse_mnist_images(data_dir_path + "/train-images.idx3-ubyte",
&train_images, -1.0, 1.0, 0, 0);
parse_mnist_images(data_dir_path + "/t10k-images.idx3-ubyte",
&test_images, -1.0, 1.0, 0, 0);
cout << "start training" << endl;
// define learning rate (0.05)
optimizer.alpha *= static_cast<tiny_dnn::float_t>(0.05);
// display training progress bar, and show training duration
progress_display disp(static_cast<unsigned long>(train_images.size()));
timer t;
// create callback
int epoch = 0;
auto on_enumerate_epoch = [&]() {
epoch++;
cout << "\n" << t.elapsed() << "s elapsed." << endl;
cout << "epoch=" << epoch << "/" << EPOCHS << endl;
disp.restart(static_cast<unsigned long>(train_images.size()));
t.restart();
};
auto on_enumerate_minibatch = [&]() {
disp += BATCH_SIZE;
};
// training
net.fit<mse>(optimizer, train_images, train_images, BATCH_SIZE, EPOCHS,
on_enumerate_minibatch, on_enumerate_epoch);
// save model
net.save("sae-net");
cout << "end training." << endl;
// if the model already exists, you can read it directly
//net.load("sae-net");
// save layers to image
//for (size_t i = 0; i < net.depth(); i++) {
// auto out_img = net[i]->output_to_image();
// auto filename = "layer_" + to_string(i) + ".bmp";
// out_img.save(filename);
//}
// test and show results
for (int i = 0; i < 10; i++) {
// get predicted result image
auto predict = net.predict(test_images[i]);
// save predicted result image to file
auto image = vec2image<float>(predict, 10, 28);
auto filename = "image_predicted_" + to_string(i) + ".bmp";
image.save(filename);
// save the origin test image to file
image = vec2image<float>(test_images[i], 10, 28);
filename = "image_test_" + to_string(i) + ".bmp";
image.save(filename);
}
}
int main() {
sae();
}
|