Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Ann.cpp : Defines the entry point for the console application.
- //
- #include "stdafx.h"
- # include <cmath>
- #include <math.h>
- #include <vector>
- #include <iostream>
- #include <iomanip>
- #include <fstream>
- #include <string>
- using namespace std;
- //Generating random number: either 0 or 1, uniform distribution, for XOR operation. Can remove later if using data from files.
- int randint();
- struct Sample
- {
- double input[2];
- double output[2];
- string ToString() {
- string str;
- str = "input: " + to_string(input[0]) + " " + to_string(input[1]) + " output: " + to_string(output[0]) + " " + to_string(output[1])+"\n";
- return str;
- }
- };
- class Data
- {
- public:
- int getNumberOfInputs() { return inputs; }
- int getNumberOfOutputs() { return outputs; }
- double *getInput(int index)
- {
- double *input = data[index].input;
- return input;
- }
- double *getOutput(int index)
- {
- double *output = data[index].output;
- return output;
- }
- int getNumberOfSamples() { return samples; }
- void addSample(Sample sample)
- {
- data.push_back(sample);
- samples++;
- //cout << sample.ToString();
- }
- void setSizes(int input_size, int output_size)
- {
- inputs = input_size;
- outputs = output_size;
- }
- protected:
- std::vector<Sample> data;
- int inputs;
- int outputs;
- int samples = 0;
- };
- class XOR : public Data
- {
- public:
- void generate(int n)
- {
- for (int i = 0; i < n; i++)
- {
- double input1 = randint();
- double input2 = randint();
- double output1 = input1 == input2;
- double output2 = input1 != input2;
- addSample({ { input1, input2 },{ output1, output2 } });
- }
- }
- XOR()
- {
- inputs = 2;
- outputs = 2;
- samples = 0;
- }
- void printInputs(int index)
- {
- cout << index << " index inputs: " << endl;
- for (int i = 0; i < inputs; i++)
- {
- cout << getInput(index)[i] << " ";
- }
- cout << endl;
- }
- void printOutputs(int index)
- {
- cout << index << " index outputs: " << endl;
- for (int i = 0; i < outputs; i++)
- {
- cout << fixed << setprecision(2) << data[index].output[i] << " ";
- }
- cout << endl;
- }
- };
- struct Topology
- {
- int L;//sluoksniu sk
- std::vector<int> l;//kiekiai sluoksnyje
- } topolygy;
- int kiek = 0;//for statistics - ignore
- double f(double x);
- double f_deriv(double x);
- double gL(double a, double z, double t);
- double gl(int layer_id, int w_i, int w_j, double *a_arr, double *z_arr, double *t_arr, double *w_arr, int *s,int *sw, int L, int *l);
- double w_gradient(int layer_id, int w_i, int w_j, double *a_arr, double *z_arr, double *t_arr, double *w_arr,int *s, int *sw, int L, int *l);
- double delta_w(double grad, double dw);
- const double ETA = 0.1;
- const double ALPHA = 0.5;
- class AnnBase {
- public:
- virtual void prepare(Topology top) = 0;
- virtual void init(Topology top, double w_arr_1[]) = 0;
- virtual void train(double *a, double *b) = 0;
- virtual void feedForward(double *a, double *b) = 0;//a and b temp vars for now.
- virtual void destroy() = 0;
- };
- class AnnSerialDBL : public AnnBase {
- public:
- void prepare(Topology top);
- void init(Topology top, double w_arr_1[]);
- void train(double *a, double *b);
- void feedForward(double *a,double *b);
- void destroy();
- public:
- int sum1;//temp var to keep the length of z, so z could be reset for calcs. Can adapt code later, so this could be removed
- int L;
- int * l;
- int * s;
- double * a_arr;
- double * z_arr;
- int * W;
- int * sw;
- double * w_arr;
- double * dw_arr;
- double * t_arr;
- };
- int main()
- {
- topolygy.L = 5;
- topolygy.l.push_back(2);
- topolygy.l.push_back(10);
- topolygy.l.push_back(10);
- topolygy.l.push_back(12);
- topolygy.l.push_back(2);
- AnnSerialDBL labas;
- labas.prepare(topolygy);
- labas.init(topolygy, NULL);
- for (int i = 0; i < topolygy.L; i++) {
- // cout << ": " << labas.W[i];
- }
- XOR xo;
- xo.generate(10);
- for (int i = 0; i < xo.getNumberOfSamples(); i++) {
- labas.train(xo.getInput(i), xo.getOutput(i));
- }
- int sum = 0;
- for (int i = 0; i < labas.L; i++) {
- sum += topolygy.l.at(i) + 1;
- }
- for (int i = 0; i < sum; i++) {
- // cout << labas.a_arr[i] << endl;
- }
- //Checking results
- for (int i = 0; i < 5;i++){
- double input[] = { randint()*1.0, randint()*1.0 };
- double output[] = { 0,0 };
- //cout << endl;
- labas.feedForward(input, output);
- cout << endl << "1: " << input[0] << " 2: " << input[1] << endl;
- cout << endl << "1: " << output[0] << " 2: " << output[1] << endl<<endl;
- }
- labas.destroy();
- int a;
- cout << kiek;
- cin >> a;
- return 0;
- }
- //returns random int, either 0 or 1
- int randint() {
- double r = ((double)rand() / (RAND_MAX));
- int a = 0;
- if (r > 0.5) {
- a = 1;
- }
- else
- {
- a = 0;
- }
- return a;
- }
- void AnnSerialDBL::prepare(Topology top)
- {
- l = new int[top.L];
- s = new int[top.L];
- int sum = 0;
- int mult = 0;
- for (int i = 0; i < top.L; i++) {
- sum += top.l.at(i) + 1;
- }
- sum1 = sum;
- for (int i = 0; i < top.L - 1; i++) {
- mult += (top.l.at(i) + 1)*top.l.at(i+1);
- }
- a_arr = new double[sum];
- z_arr = new double[sum];
- W = new int[top.L];
- sw = new int[top.L];
- w_arr = new double[mult];
- dw_arr = new double[mult];
- t_arr = new double[top.l.at(top.L - 1)];
- }
- void AnnSerialDBL::init(Topology top, double w_arr_1[] = NULL)
- {
- L = top.L;
- //Neuronu kiekiai sluoksnyje
- for (int i = 0; i < top.L; i++) {
- l[i] = top.l.at(i) + 1;
- }
- //Sluoksniu pradzios indeksai
- for (int i = 0; i < top.L; i++) {
- s[i] = 0;
- for (int j = i; j > 0; j--) {
- s[i] += l[j - 1];
- }
- }
- //Bias neuronai
- for (int i = 0; i < top.L - 1; i++) {
- a_arr[s[i + 1] - 1] = 1;
- }
- //Svoriu kiekiai l-ame sluoksnyje
- for (int i = 0; i < top.L - 1; i++) {
- W[i] = l[i] * (l[i + 1] - 1);
- //cout << "Svoriu sk: " << W[i] << " Pradzios index: ";
- sw[i] = 0;
- if (i != 0) {
- for (int j = 0; j < i; j++) {
- sw[i] += W[j];
- }
- }
- if (w_arr_1 == NULL) {
- for (int j = 0; j < W[i]; j++) {
- w_arr[sw[i] + j] = (double)rand() / double(RAND_MAX);
- //cout << w_arr[sw[i] + j]<< endl;
- dw_arr[sw[i] + j] = 0;
- }
- }
- else {
- w_arr = w_arr_1; //ar reikia pokycius issisaugoti irgi?
- }
- //cout << sw[i] << " " << endl;
- }
- }
- void AnnSerialDBL::train(double *a,double *b)
- {
- a_arr[0] = a[0];
- a_arr[1] = a[1];
- for (int j = 0; j < sum1; j++) {
- z_arr[j] = 0;
- }
- //FFEEED FORWARD
- for (int i = 0; i < L - 1; i++) {//per sluoksnius einu+
- for (int j = 0; j < l[i]; j++) { //kiek neuronu sluoksnyje+
- for (int k = 0; k < l[i + 1] - 1; k++) {//per sekancio sluoksnio z+
- z_arr[s[i + 1] + k] += w_arr[sw[i] + k + j*l[i + 1]] * a_arr[s[i] + j];
- // cout << "w: "<< w_arr[sw[i] + k + j*l[i + 1]] << endl;
- // cout << "a: " << a_arr[s[i] + j] << endl;
- // cout << "z reiksmes: " << z_arr[s[i+1] + k] << endl;
- //cout << endl;
- kiek++;
- }
- }
- for (int k = 0; k < l[i + 1] - 1; k++) {//per sekancio sluoksnio z
- a_arr[s[i + 1] + k] = f(z_arr[s[i + 1] + k]);
- //cout << s[i + 1] + k << " a reiksmes: " << a_arr[s[i + 1] + k] << endl;
- }
- }
- t_arr[0] = b[0];
- t_arr[1] = b[1];
- //back propogation:
- for (int i = L-2; i >=0; i--) {//per sluoksnius
- for (int j = 0; j < l[i]; j++) {//per neuronus
- for (int k = 0; k < l[i + 1] - 1; k++) {//per kito sluoksnio neuronus
- dw_arr[sw[i] + k] = delta_w(w_gradient(i, j, k, a_arr, z_arr, t_arr, w_arr, s,sw, L, l), dw_arr[sw[i] + k]);
- w_arr[sw[i] + k] += dw_arr[sw[i] + k];
- //w_arr[sw[i] + k] = delta_w(w_gradient(i, j, k, a_arr, z_arr, t_arr, w_arr, s, sw, L, l), w_arr[sw[i] + k]);
- //dw_arr[sw[i] + k] += dw_arr[sw[i] + k];
- // cout << w_arr[sw[i] + k] << " " << endl;
- }
- }
- }
- }
- void AnnSerialDBL::feedForward(double *a, double *b)
- {
- a_arr[0] = a[0];
- a_arr[1] = a[1];
- for (int j = 0; j < sum1; j++) {
- z_arr[j] = 0;
- }
- //FFEEED FORWARD
- for (int i = 0; i < L - 1; i++) {//per sluoksnius einu+
- for (int j = 0; j < l[i]; j++) { //kiek neuronu sluoksnyje+
- for (int k = 0; k < l[i + 1] - 1; k++) {//per sekancio sluoksnio z+
- z_arr[s[i + 1] + k] += w_arr[sw[i] + k + j*l[i + 1]] * a_arr[s[i] + j];
- /* cout << "w: "<< w_arr[sw[i] + k + j*l[i + 1]] << endl;
- cout << "a: " << a_arr[s[i] + j] << endl;
- cout << "z reiksmes: " << z_arr[s[i+1] + k] << endl;
- cout << endl;*/
- }
- }
- for (int k = 0; k < l[i + 1] - 1; k++) {//per sekancio sluoksnio z
- a_arr[s[i + 1] + k] = f(z_arr[s[i + 1] + k]);
- cout << s[i + 1] + k << " a reiksmes: " << a_arr[s[i + 1] + k] << endl;
- }
- }
- //cout << a_arr[s[L - 1]];
- //cout << a_arr[s[L - 1]+1];
- if (a_arr[s[L - 1]] < a_arr[s[L - 1] + 1]) {
- b[0] = 1;
- b[1] = 0;
- }
- else {
- b[0] = 0;
- b[1] = 1;
- }
- //data.output[0] = a_arr[s[L - 1]];
- //data.output[1] = a_arr[s[L - 1] + 1];
- }
- void AnnSerialDBL::destroy()
- {
- delete l;
- l = NULL;
- delete s;
- s = NULL;
- delete a_arr;
- a_arr = NULL;
- delete z_arr;
- z_arr = NULL;
- delete W;
- W = NULL;
- delete sw;
- sw = NULL;
- delete w_arr;
- w_arr = NULL;
- delete dw_arr;
- dw_arr = NULL;
- delete t_arr;
- t_arr = NULL;
- }
- double f(double x) {
- double y = 1+exp(-x);
- if (y == 0) {
- cout << "Error 1";
- }
- if ((y-1) == 0) {
- //cout << "Error 2";
- }
- return 1 / y;
- }
- double f_deriv(double x) {
- double y = pow((1 + exp(-x)), 2);
- double z = exp(-x);
- if (y == 0) {
- cout << "Error 3";
- }
- if (z == 0) {
- //cout << "Error 4";
- }
- return exp(-x) / pow((1 + exp(-x)), 2);
- }
- double gL(double a, double z, double t) {
- double w = f_deriv(z) * (a - t);
- //cout << "z: " << z << " a: " << a << " t: " << t << endl;
- return w;
- }
- double gl(int layer_id, int w_i, int w_j, double *a_arr, double *z_arr, double *t_arr, double *w_arr, int *s,int *sw, int L, int *l) {
- double w = f_deriv(z_arr[s[layer_id] + w_j]);
- double sum = 0;
- for (int i = 0; i < l[layer_id + 1] - 1; i++) {
- if (layer_id + 2 == L) {
- sum += w_arr[sw[layer_id] + i] * gL(a_arr[s[layer_id + 1] + i], z_arr[s[layer_id + 1]+ i], t_arr[i]);
- }
- else {
- sum += w_arr[sw[layer_id] + w_j] * gl(layer_id + 1, w_i, i, a_arr, z_arr, t_arr,w_arr, s, sw, L, l);
- }
- }
- return w*sum;
- }
- double w_gradient(int layer_id, int w_i, int w_j, double *a_arr, double *z_arr, double *t_arr, double *w_arr,int *s, int *sw, int L, int *l) {
- double w = a_arr[s[layer_id] + w_i];
- if (layer_id + 2 == L) {
- w *= gL(a_arr[s[layer_id + 1] + w_j], z_arr[s[layer_id + 1] + w_j], t_arr[w_j]);
- }
- else {
- w *= gl(layer_id + 1, w_i, w_j, a_arr, z_arr, t_arr, w_arr, s, sw, L, l);
- }
- //cout << L << endl;
- //cout << w << " layer id:"<< layer_id <<endl;
- return w;
- }
- double delta_w(double grad, double dw) {
- return (-ETA)*grad + ALPHA*dw;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement