Skip to content

Commit 272a0fc

Browse files
author
Yusuke Sugomori
committed
cpp dA
1 parent ddb2af3 commit 272a0fc

File tree

1 file changed

+244
-0
lines changed

1 file changed

+244
-0
lines changed

cpp/dA.cpp

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
#include <iostream>
2+
#include <math.h>
3+
using namespace std;
4+
5+
6+
double uniform(double min, double max) {
7+
return rand() / (RAND_MAX + 1.0) * (max - min) + min;
8+
}
9+
10+
int binomial(int n, double p) {
11+
if(p < 0 || p > 1) return 0;
12+
13+
int c = 0;
14+
double r;
15+
16+
for(int i=0; i<n; i++) {
17+
r = rand() / (RAND_MAX + 1.0);
18+
if (r < p) c++;
19+
}
20+
21+
return c;
22+
}
23+
24+
double sigmoid(double x) {
25+
return 1.0 / (1.0 + exp(-x));
26+
}
27+
28+
29+
30+
class dA {
31+
32+
public:
33+
int N;
34+
int n_visible;
35+
int n_hidden;
36+
double **W;
37+
double *hbias;
38+
double *vbias;
39+
dA(int, int, int , double**, double*, double*);
40+
~dA();
41+
void get_corrupted_input(int*, int*, double);
42+
void get_hidden_values(int*, double*);
43+
void get_reconstructed_input(double*, double*);
44+
void train(int*, double, double);
45+
void reconstruct(int*, double*);
46+
};
47+
48+
49+
dA::dA(int size, int n_v, int n_h, double **w, double *hb, double *vb) {
50+
N = size;
51+
n_visible = n_v;
52+
n_hidden = n_h;
53+
54+
if(w == NULL) {
55+
W = new double*[n_hidden];
56+
for(int i=0; i<n_hidden; i++) W[i] = new double[n_visible];
57+
double a = 1.0 / n_visible;
58+
59+
for(int i=0; i<n_hidden; i++) {
60+
for(int j=0; j<n_visible; j++) {
61+
W[i][j] = uniform(-a, a);
62+
}
63+
}
64+
} else {
65+
W = w;
66+
}
67+
68+
if(hb == NULL) {
69+
hbias = new double[n_hidden];
70+
for(int i=0; i<n_hidden; i++) hbias[i] = 0;
71+
} else {
72+
hbias = hb;
73+
}
74+
75+
if(vb == NULL) {
76+
vbias = new double[n_visible];
77+
for(int i=0; i<n_visible; i++) vbias[i] = 0;
78+
} else {
79+
vbias = vb;
80+
}
81+
}
82+
83+
dA::~dA() {
84+
for(int i=0; i<n_hidden; i++) delete[] W[i];
85+
delete[] W;
86+
delete[] hbias;
87+
delete[] vbias;
88+
}
89+
90+
void dA::get_corrupted_input(int *x, int *tilde_x, double p) {
91+
for(int i=0; i<n_visible; i++) {
92+
if(x[i] == 0) {
93+
tilde_x[i] = 0;
94+
} else {
95+
tilde_x[i] = binomial(1, p);
96+
}
97+
}
98+
}
99+
100+
// Encode
101+
void dA::get_hidden_values(int *x, double *y) {
102+
for(int i=0; i<n_hidden; i++) {
103+
y[i] = 0;
104+
for(int j=0; j<n_visible; j++) {
105+
y[i] += W[i][j] * x[j];
106+
}
107+
y[i] += hbias[i];
108+
y[i] = sigmoid(y[i]);
109+
}
110+
}
111+
112+
// Decode
113+
void dA::get_reconstructed_input(double *y, double *z) {
114+
for(int i=0; i<n_visible; i++) {
115+
z[i] = 0;
116+
for(int j=0; j<n_hidden; j++) {
117+
z[i] += W[j][i] * y[j];
118+
}
119+
z[i] += vbias[i];
120+
z[i] = sigmoid(z[i]);
121+
}
122+
}
123+
124+
void dA::train(int *x, double lr, double corruption_level) {
125+
int *tilde_x = new int[n_visible];
126+
double *y = new double[n_hidden];
127+
double *z = new double[n_visible];
128+
129+
double *L_vbias = new double[n_visible];
130+
double *L_hbias = new double[n_hidden];
131+
132+
double p = 1 - corruption_level;
133+
134+
get_corrupted_input(x, tilde_x, p);
135+
get_hidden_values(tilde_x, y);
136+
get_reconstructed_input(y, z);
137+
138+
// vbias
139+
for(int i=0; i<n_visible; i++) {
140+
L_vbias[i] = x[i] - z[i];
141+
vbias[i] += lr * L_vbias[i] / N;
142+
}
143+
144+
// hbias
145+
for(int i=0; i<n_hidden; i++) {
146+
L_hbias[i] = 0;
147+
for(int j=0; j<n_visible; j++) {
148+
L_hbias[i] += W[i][j] * L_vbias[j];
149+
}
150+
L_hbias[i] *= y[i] * (1 - y[i]);
151+
152+
hbias[i] += lr * L_hbias[i] / N;
153+
}
154+
155+
// W
156+
for(int i=0; i<n_hidden; i++) {
157+
for(int j=0; j<n_visible; j++) {
158+
W[i][j] += lr * (L_hbias[i] * tilde_x[j] + L_vbias[j] * y[i]) / N;
159+
}
160+
}
161+
162+
delete[] L_hbias;
163+
delete[] L_vbias;
164+
delete[] z;
165+
delete[] y;
166+
delete[] tilde_x;
167+
}
168+
169+
void dA::reconstruct(int *x, double *z) {
170+
double *y = new double[n_hidden];
171+
172+
// for(int i=0; i<n_visible; i++) z[i] = 0;
173+
for(int i=0; i<n_hidden; i++) y[i] = 0;
174+
175+
get_hidden_values(x, y);
176+
get_reconstructed_input(y, z);
177+
178+
delete[] y;
179+
}
180+
181+
182+
183+
void test_dA() {
184+
srand(0);
185+
186+
double learning_rate = 0.1;
187+
double corruption_level = 0.3;
188+
int training_epochs = 50;
189+
190+
int train_N = 10;
191+
int test_N = 2;
192+
int n_visible = 20;
193+
int n_hidden = 5;
194+
195+
// training data
196+
int train_X[10][20] = {
197+
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
198+
{1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
199+
{1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
200+
{1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
201+
{0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
202+
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
203+
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1},
204+
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1},
205+
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1},
206+
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0}
207+
};
208+
209+
// construct dA
210+
dA da(train_N, n_visible, n_hidden, NULL, NULL, NULL);
211+
212+
// train
213+
for(int epoch=0; epoch<training_epochs; epoch++) {
214+
for(int i=0; i<train_N; i++) {
215+
da.train(train_X[i], learning_rate, corruption_level);
216+
}
217+
}
218+
219+
// test data
220+
int test_X[2][20] = {
221+
{1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
222+
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0}
223+
};
224+
double reconstructed_X[2][20] = {0};
225+
226+
227+
// test
228+
for(int i=0; i<test_N; i++) {
229+
da.reconstruct(test_X[i], reconstructed_X[i]);
230+
for(int j=0; j<n_visible; j++) {
231+
printf("%.5f ", reconstructed_X[i][j]);
232+
}
233+
cout << endl;
234+
}
235+
236+
cout << endl;
237+
}
238+
239+
240+
241+
int main() {
242+
test_dA();
243+
return 0;
244+
}

0 commit comments

Comments
 (0)