| 56 | } |
| 57 | |
| 58 | void train(const array &in, double lr, int num_epochs, int batch_size, |
| 59 | bool verbose) { |
| 60 | const int num_samples = in.dims(0); |
| 61 | const int num_batches = num_samples / batch_size; |
| 62 | |
| 63 | for (int i = 0; i < num_epochs; i++) { |
| 64 | double err = 0; |
| 65 | |
| 66 | for (int j = 0; j < num_batches - 1; j++) { |
| 67 | int st = j * batch_size; |
| 68 | int en = std::min(num_samples - 1, st + batch_size - 1); |
| 69 | int num = en - st + 1; |
| 70 | |
| 71 | array v_pos = in(seq(st, en), span); |
| 72 | |
| 73 | array h_pos = sigmoid_binary(tile(h_bias, num) + |
| 74 | matmulNT(v_pos, weights)); |
| 75 | |
| 76 | array v_neg = |
| 77 | sigmoid_binary(tile(v_bias, num) + matmul(h_pos, weights)); |
| 78 | |
| 79 | array h_neg = sigmoid_binary(tile(h_bias, num) + |
| 80 | matmulNT(v_neg, weights)); |
| 81 | |
| 82 | array c_pos = matmulTN(h_pos, v_pos); |
| 83 | array c_neg = matmulTN(h_neg, v_neg); |
| 84 | |
| 85 | array delta_w = lr * (c_pos - c_neg) / num; |
| 86 | array delta_vb = lr * sum(v_pos - v_neg) / num; |
| 87 | array delta_hb = lr * sum(h_pos - h_neg) / num; |
| 88 | |
| 89 | weights += delta_w; |
| 90 | v_bias += delta_vb; |
| 91 | h_bias += delta_hb; |
| 92 | |
| 93 | if (verbose) { err += error(v_pos, v_neg); } |
| 94 | } |
| 95 | |
| 96 | if (verbose) { |
| 97 | printf("Epoch %d: Reconstruction error: %0.4f\n", i + 1, |
| 98 | err / num_batches); |
| 99 | } |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | array prop_up(const array &in) { |
| 104 | return sigmoid(tile(h_bias, in.dims(0)) + matmulNT(in, weights)); |