Skip to content

Commit ebc839f

Browse files
author
Yusuke Sugomori
committed
dA c
1 parent 4644aa4 commit ebc839f

File tree

4 files changed

+262
-8
lines changed

4 files changed

+262
-8
lines changed

c/RBM.c

+1-4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22
#include <stdlib.h>
33
#include <math.h>
44
#include "RBM.h"
5-
6-
double uniform(double, double);
7-
int binomial(int, double);
8-
double sigmoid(double);
5+
#include "utils.h"
96

107

118
void test_rbm(void);

c/dA.c

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

c/dA.h

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#ifndef DA_H
2+
#define DA_H
3+
4+
typedef struct {
5+
int N;
6+
int n_visible;
7+
int n_hidden;
8+
double **W;
9+
double *hbias;
10+
double *vbias;
11+
} dA;
12+
13+
void dA__construct(dA*, int, int, int, double**, double*, double*);
14+
void dA__destruct(dA*);
15+
void dA_get_corrupted_input(dA*, int*, int*, double);
16+
void dA_get_hidden_values(dA*, int*, double*);
17+
void dA_get_reconstructed_input(dA*, double*, double*);
18+
void dA_train(dA*, int*, double, double);
19+
void dA_reconstruct(dA*, int*, double*);
20+
21+
#endif

cpp/dA.cpp

+1-4
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,6 @@ void dA::train(int *x, double lr, double corruption_level) {
150150
void dA::reconstruct(int *x, double *z) {
151151
double *y = new double[n_hidden];
152152

153-
// for(int i=0; i<n_visible; i++) z[i] = 0;
154-
for(int i=0; i<n_hidden; i++) y[i] = 0;
155-
156153
get_hidden_values(x, y);
157154
get_reconstructed_input(y, z);
158155

@@ -202,7 +199,7 @@ void test_dA() {
202199
{1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
203200
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0}
204201
};
205-
double reconstructed_X[2][20] = {0};
202+
double reconstructed_X[2][20];
206203

207204

208205
// test

0 commit comments

Comments
 (0)