2016-11-16 7 views
0

개인 프로젝트로 그래프 기반 백 프로 퍼 게이트 신경망을 작성하고 있습니다. 앞으로 앞으로 나아가십시오. 컴파일됩니다. 성공적으로 반 시간을 실행하고 마지막 단계에서 절반 만 충돌합니다. 일부 쓰레기 수거 단계에서 죽어가는 것 같습니다. 저는 가상 함수와 static_cast를 처음 접했기 때문에 그 부분이 비난받을 지 궁금합니다. GDB에서 "프로그램 수신 신호 SIGABRT가 중단되었습니다. __gnu_cxx :: new_allocator :: deallocate (double *, unsigned long)()에서 0x00000000100404740이 중단되었습니다."코드의 첫 번째 절반 정도를 구성하는 함수는 아마 비난하지 않을 것입니다. , 그들은 신경 네트워크 (그래프없이)의 더 단순한 이전 버전에서 작동합니다. 구조체에 어딘가에있을거야.일시적인 "Aborted Core Dumped". 어쩌면 static_cast의 잘못입니까?

업데이트 : 시간 기반 임의 시드 대신 123으로 난수 생성을 시드하면 매번 실행됩니다. seed = 124는 매번 실패합니다. 일정한 가중치를 사용하여 임의성을 제거하면 매번 실행될 수 있습니다. 나는 당황했다!

#include <bits/stdc++.h> 
using namespace std; 

#define p(x) cout << #x << " = "<< x<< endl 
#define min(a,b) a<b ? a : b 
typedef vector<double> d1; 
typedef vector<d1> d2; 
typedef vector<d2> d3; 
typedef vector<int> i1; 

int argmax(d1 x){ 
    p(x.size()); 
    int maxIndex=0; 
    double maxValue=x[0]; 
    for (int i=1; i<x.size(); i++){ 
    if (x[i] > maxValue){ 
     maxValue = x[i]; 
     maxIndex = i; 
    } 
    } 
    return maxIndex; 
} 

d1 zeros(int n){ 
    return d1(n); 
} 

d2 zeros(int rows, int cols){ 
    return d2(rows, d1(cols, 0)); 
} 

d3 zeros(int x, int rows, int cols){ 
    return d3(x, d2(rows, d1(cols, 0))); 
} 

void print(d1 x){ 
    for (double d: x) 
    cout << d << endl; 
    cout << endl; 
} 

void print(d2 x){ 
    for (auto row: x){ 
    for (double d: row){ 
     cout << d << " "; 
    } 
    cout << endl; 
    } 
    cout << endl; 
} 

void print(d3 x){ 
    for (d2 X: x) 
    print(X); 
} 



void toRank2(d1&x, int rows, d2& y){ 
    for (int i=0; i<x.size()/rows; i++){ 
    y.emplace_back(); 
    for (int row=0; row<rows; row++){ 
     y[i].push_back(x[i*rows+row]); 
    } 
    } 
} 

void toRank3(d1& x, int rows, int cols, d3& y){ 
    for (int i=0; i<x.size()/rows/cols; i++){ 
    y.emplace_back(); 
    for (int row=0; row<rows; row++){ 
     y[i].emplace_back(); 
     for (int col=0; col<cols; col++){ 
     y[i][row].push_back(x[i*rows*cols+row*cols+col]); 
     } 
    } 
    } 
} 

d1 getRandomDoubles(int size, double mean=0, double standard_deviation=1){ 
    static normal_distribution<double> distribution(mean, standard_deviation); 
    int seed=time(NULL); 
    static default_random_engine generator(seed); 
    d1 data(size); 
    generate(data.begin(), data.end(), []() { return distribution(generator); }); 
    return data; 
} 

d2 getRandomDoubles(int rows, int cols, double mean=0, double standard_deviation=1){ 
    d1 d = getRandomDoubles(rows*cols, mean, standard_deviation); 
    d2 e; 
    toRank2(d, cols, e); 
    return e; 
} 

d3 getRandomDoubles(int depth, int rows, int cols, double mean=0, double standard_deviation=1){ 
    d1 d = getRandomDoubles(depth*rows*cols, mean, standard_deviation);; 
    d3 e; 
    toRank3(d, rows, cols, e); 
    return e; 
} 

struct Node{ 
    vector<Node*> parents, children; 
    bool ready=false; 
    // 
    // bool check_ready(){ 
    // for (Node* n: parents) 
    // if (!n->check_ready()) 
    // return false; 
    // return true; 
    // } 
    // 
    void add_child(Node& n){ 
    children.push_back(&n); 
    n.parents.push_back(this); 
    } 

    void forward_propagate(){ 
    cout << "starting r2 forward" <<endl; 
    // if (parents.size()==0 || updated_parents == parents.size()-1) 
    for (Node* n: children){ 
     cout << "loop" << endl; 
     n->update_state(); 
     // cout << "root child forward" << endl; 
    } 
    cout << "exiting r2 forward" << endl; 
    //updated_parents++; 
    } 

    virtual void update_state(){ 
    //if (parents.size()==0 || updated_parents == parents.size() - 1) 
    forward_propagate(); 
    } 
}; 

struct r1:Node{ 
    vector<double> state; 
    int r; 

    r1(){} 

    r1(int R){ 
    r=R; 
    state = vector<double>(r); 
    } 
}; 

struct r2:Node{ 
    vector<vector<double>> state; 
    int r,c; 

    r2(){} 
    r2(int R, int C){ 
    r=R; 
    c=C; 
    state = zeros(r, c); 
    } 
}; 

struct r3:Node{ 
    d3 state; 
    int r, c, d; 
    r3(){} 
    r3(int R, int C, int D){ 
    r=R; 
    c=C; 
    d=D; 
    state = zeros(R,C,D); 
    } 
}; 

struct MatrixProduct1_1: r1{ 
    MatrixProduct1_1(int n):r1(n){} 

    void update_state() override{ 
    cout << "mat11" << endl; 
    d2& W = static_cast<r2*>(parents[0])->state; 
    d1& x = static_cast<r1*>(parents[1])->state; 
    state = zeros(r); 
    for (int i=0; i<W.size(); i++) 
    for (int j=0; j<W[0].size(); j++) 
    state[i] += W[i][j]*x[j]; 
    forward_propagate(); 
    } 
}; 

struct MatrixProduct2_1: r1{ 
    MatrixProduct2_1(int n):r1(n){} 

    void update_state() override{ 
    cout << "matt21" << endl; 
    d3& W = static_cast<r3*>(parents[0])->state; 
    d2& x = static_cast<r2*>(parents[1])->state; 
    state = zeros(r); 
    for (int i=0; i<W.size(); i++) 
    for (int j=0; j<W[0].size(); j++) 
    for (int k=0; k<W[0][0].size(); k++) 
    state[k] += W[i][j][k]*x[i][j]; 
    forward_propagate(); 
    } 
}; 

struct Convolution: r2{ 
    Convolution(int r, int c): r2(r, c){} 
    void update_state() override{ 
    cout << "convolving" << endl; 
    state = zeros(r, c); 
    d2& W = static_cast<r2*>(parents[0])->state; 
    d2& x = static_cast<r2*>(parents[1])->state; 

    int wCenterX = W[0].size()/2; 
    int wCenterY = W.size()/2; 
    int rows = x.size(), cols = x[0].size(); 
    int wRows = W.size(), wCols = W[0].size(); 

    //#pragma omp parallel for 
    for(int i=0; i < rows; i++) 
    for(int j=0; j < cols; j++) 
    for(int m=0; m < W.size(); m++){ 
     int mm = W.size() - 1 - m; 
     for(int n=0; n < wCols; n++){ 
     int nn = wCols - 1 - n; 
     int ii = i + (m - wCenterY); 
     int jj = j + (n - wCenterX); 
     if (ii >= 0 && ii < rows && jj >= 0 && jj < cols) 
     state[i][j] += x[ii][jj] * W[mm][nn]; 
     } 
    } 
    forward_propagate(); 
    } 
}; 


struct RELU: r2{ 
    RELU(int r, int c):r2(r, c){} 
    void update_state() override{ 
    cout << "relu2" << endl; 
    state = zeros(r,c); 
    d2& x = static_cast<r2*>(parents[0])->state; 
    for (int i=0; i<state.size(); i++) 
    for (int j=0; j<state[0].size(); j++) 
    if (x[i][j] > 0) 
    state[i][j] = x[i][j]; 
    forward_propagate(); 
    } 
}; 

struct Softmax: r1{ 
    Softmax(int r):r1(r){} 
    void update_state() override{ 
    cout << "softmax" << endl; 
    state = zeros(r); 
    p(parents.size()); 
    d1& x = static_cast<r1*>(parents[0])->state; 
    cout << "got state" << endl; 
    //p(x.size()); 
    //print(x); 

    p(x.size()); 
    cout << "argmax " << argmax(x) << endl; 
    double largest = x[argmax(x)]; 
    double lndenom = largest; 
    double expsum = 0; 
    cout << "starting expsum" << endl; 
    for (int i=0; i<x.size(); i++) 
    //expsum += exp(x[i]-largest); 
    expsum += x[i] - largest; 
    cout << "next loop " << endl; 
    for (int i=0; i<x.size(); i++) 
    // state[i] = exp(x[i]-largest)/expsum; 
    state[i] = x[i]-largest; 
    cout << "forward proping" << endl; 
    cout << "weird" << endl; 
    // forward_propagate(); 
    cout << "done with softmax" <<endl; 
    } 
}; 

struct Add1: r1{ 
    Add1(int r):r1(r){} 
    void update_state() override{ 
    cout << "add1ing" << endl; 
    d1& x = static_cast<r1*>(parents[0])->state; 
    d1& y = static_cast<r1*>(parents[1])->state; 
    for (int i=0; i<r; i++) 
    state[i] = x[i]+y[i]; 
    forward_propagate(); 
    } 
}; 

struct Add2: r2{ 
    Add2(int r, int c): r2(r, c){} 
    void update_state() override{ 
    d2& x = static_cast<r2*>(parents[0])->state; 
    d2& y = static_cast<r2*>(parents[1])->state; 
    for (int i=0; i<x.size(); i++) 
    for (int j=0; j<x[0].size(); j++) 
    state[i][j] = x[i][j] + y[i][j]; 
    forward_propagate(); 
    } 
}; 

struct MaxPool: r2{ 
    MaxPool(int r, int c): r2(r, c){} 
    void update_state() override{ 
    d2& x = static_cast<r2*>(parents[0])->state; 
    for (int i=0; i<x.size(); i+=2) 
    for (int j=0; j<x[0].size(); j+=2) 
    state[i/2][j/2] = max(max(x[i][j], x[i+1][j]), max(x[i+1][j], x[i+1][j+1])); 
    forward_propagate(); 
    } 
}; 

int main(){ 
    Node root; 
    r2 x; 
    x.state = getRandomDoubles(28,28); 
    r2 wConv; 
    wConv.state = getRandomDoubles(10, 10); 
    root.add_child(x); 
    root.add_child(wConv); 
    Convolution c(28,28); 
    wConv.add_child(c); 
    x.add_child(c); 
    Add2 a(28,28); 
    r2 bConv(28,28); 
    bConv.state = getRandomDoubles(28,28); 
    c.add_child(a); 
    bConv.add_child(a); 
    RELU r(28,28); 
    a.add_child(r); 
    MaxPool max(14, 14); 
    r.add_child(max); 
    r3 wFull(10,28,28); 
    wFull.state = getRandomDoubles(10,28,28); 
    // print(wFull.state); 
    // return 0; 
    MatrixProduct2_1 full(10); 
    wFull.add_child(full); 
    max.add_child(full); 
    r1 bFull(10); 
    bFull.state = getRandomDoubles(10); 
    Add1 aFull(10); 
    aFull.state[0] = 123; 
    full.add_child(aFull); 
    bFull.add_child(aFull); 
    Softmax s(10); 
    aFull.add_child(s); 
    // d1& x =   static_cast<r1*>(parents[0])->state; 
    // d1& asdf = static_cast<r1*>(s.parents[0])->state; 
    // print(asdf); 
    //root.forward_propagate(); 
    x.forward_propagate(); 
    //print(s.state); 
    cout << "returning main"; 
} 
+1

'min' 매크로는 실패로 악명이 높습니다. 이것은 잘못된 버전입니다. 우리가 완벽하게 훌륭한'std :: min'을 가지고 있기 때문에 또한 무의미합니다. 여러분이 재발 명하고있는 유일한 바퀴가 아닙니다.'argmax'는 단지'std :: max_element'입니다. – MSalters

답변

1

static_cast은 거의 필요하지 않습니다. 이것도 예외는 아닙니다. 당신의 노드는 이웃들이 어떤 유형인지 정말로 알아야합니다.

저는 구체적인 문제를 즉시 발견 할 수 없지만 신경 네트워크에 익숙합니다. struct MatrixProduct1_1: r1과 같은 코드는 거의 빨간색 경고입니다. 왜 구조체입니까? r1에서 상속되는 이유는 무엇입니까? 뉴럴 네트워크 이론에서 매트릭스 제품은 노드의 두 레이어 사이의 완전한 연결을 표현하는 방법입니다. 그런 다음 노드는 일반적으로 스칼라 활성화를가집니다.

활성화 함수는 상속을 사용하여 구현할 수 있지만 Node에서 상속받습니다. 그건 당신도 그 r1 .. r3 유형을 가질 수 없다는 의미지만, 어쨌든 그걸 이해하지 못했습니다.

TLDR : 형식이 엉망이되어 static_cast으로 숨기고 있지만 컴파일 만하면 올바르지 않습니다.

-1

해결! MatrixProd2_1에서 잘못된 색인을 사용하여 버그가 발생했습니다. 나는 신경망의 끝에서 시작하여 노드가 버그의 근원임을 확인하고 vector :: operator [] 인수에 대한 주장을 넣음으로써 그것을 잡았습니다. 경계 밖으로 액세스하여 정의되지 않은 동작이 발생했습니다. 왜 어떤 씨앗이 (어쩌면 다소 잘못된 결과와 함께) 도망 갔는지 분명하지 않습니다.

또한 main에서 wFull을 만들 때 모양을 변경하고 MatrixProd2_1에서 사용되는 getRandomDoubles의 인수를 변경했습니다. 완전히 새로운 버전 :

#include <bits/stdc++.h> 
using namespace std; 

#define p(x) cout << #x << " = "<< x<< endl 
//#define min(a,b) a<b ? a : b 
typedef vector<double> d1; 
typedef vector<d1> d2; 
typedef vector<d2> d3; 
typedef vector<int> i1; 
int seed; 
bool time_seed = true; 

int argmax(d1 x){ 
    p(x.size()); 
    int maxIndex=0; 
    double maxValue=x[0]; 
    for (int i=1; i<x.size(); i++){ 
    if (x[i] > maxValue){ 
     maxValue = x[i]; 
     maxIndex = i; 
    } 
    } 
    return maxIndex; 
} 

d1 zeros(int n){ 
    return d1(n); 
} 

d2 zeros(int rows, int cols){ 
    return d2(rows, d1(cols, 0)); 
} 

d3 zeros(int x, int rows, int cols){ 
    return d3(x, d2(rows, d1(cols, 0))); 
} 

void print(d1 x){ 
    for (double d: x) 
    cout << d << endl; 
    cout << endl; 
} 

void print(d2 x){ 
    for (auto row: x){ 
    for (double d: row){ 
     cout << d << " "; 
    } 
    cout << endl; 
    } 
    cout << endl; 
} 

void print(d3 x){ 
    for (d2 X: x) 
    print(X); 
} 



void toRank2(d1&x, int rows, d2& y){ 
    for (int i=0; i<x.size()/rows; i++){ 
    y.emplace_back(); 
    for (int row=0; row<rows; row++){ 
     y[i].push_back(x[i*rows+row]); 
    } 
    } 
} 

void toRank3(d1& x, int rows, int cols, d3& y){ 
    for (int i=0; i<x.size()/rows/cols; i++){ 
    y.emplace_back(); 
    for (int row=0; row<rows; row++){ 
     y[i].emplace_back(); 
     for (int col=0; col<cols; col++){ 
     y[i][row].push_back(x[i*rows*cols+row*cols+col]); 
     } 
    } 
    } 
} 

d1 getRandomDoubles(int size, double mean=1, double standard_deviation=1){ 
    static normal_distribution<double> distribution(mean, standard_deviation); 
    if (time_seed) 
    seed=time(NULL); 
    //int seed=123; //123 works, 124 fails 
    static default_random_engine generator(seed); 
    d1 data(size); 
    generate(data.begin(), data.end(), []() { return distribution(generator); }); 
    // generate(data.begin(), data.end(), [](){return -.1;}); 
    return data; 
} 

d2 getRandomDoubles(int rows, int cols, double mean=0, double standard_deviation=1){ 
    d1 d = getRandomDoubles(rows*cols, mean, standard_deviation); 
    d2 e; 
    toRank2(d, cols, e); 
    return e; 
} 

d3 getRandomDoubles(int depth, int rows, int cols, double mean=0, double standard_deviation=1){ 
    d1 d = getRandomDoubles(depth*rows*cols, mean, standard_deviation);; 
    d3 e; 
    toRank3(d, rows, cols, e); 
    return e; 
} 

struct Node{ 
    vector<Node*> parents, children; 
    bool ready=false; 
    // 
    // bool check_ready(){ 
    // for (Node* n: parents) 
    // if (!n->check_ready()) 
    // return false; 
    // return true; 
    // } 
    // 
    void add_child(Node& n){ 
    children.push_back(&n); 
    n.parents.push_back(this); 
    } 

    void forward_propagate(){ 
    cout << "starting r2 forward" <<endl; 
    // if (parents.size()==0 || updated_parents == parents.size()-1) 
    for (Node* n: children){ 
     cout << "loop" << endl; 
     n->update_state(); 
     // cout << "root child forward" << endl; 
    } 
    cout << "exiting r2 forward" << endl; 
    //updated_parents++; 
    } 

    virtual void update_state(){ 
    //if (parents.size()==0 || updated_parents == parents.size() - 1) 
    forward_propagate(); 
    } 
}; 

struct r1:Node{ 
    vector<double> state; 
    int r; 

    r1(){} 

    r1(int R){ 
    r=R; 
    state = vector<double>(r); 
    } 
}; 

struct r2:Node{ 
    vector<vector<double>> state; 
    int r,c; 

    r2(){} 
    r2(int R, int C){ 
    r=R; 
    c=C; 
    state = zeros(r, c); 
    } 
}; 

struct r3:Node{ 
    d3 state; 
    int r, c, d; 
    r3(){} 
    r3(int R, int C, int D){ 
    r=R; 
    c=C; 
    d=D; 
    state = zeros(R,C,D); 
    } 
}; 

struct MatrixProduct1_1: r1{ 
    MatrixProduct1_1(int n):r1(n){} 

    void update_state() override{ 
    cout << "mat11" << endl; 
    d2& W = static_cast<r2*>(parents[0])->state; 
    d1& x = static_cast<r1*>(parents[1])->state; 
    state = zeros(r); 
    for (int i=0; i<W.size(); i++) 
    for (int j=0; j<W[0].size(); j++) 
    state[i] += W[i][j]*x[j]; 
    forward_propagate(); 
    } 
}; 

struct MatrixProduct2_1: r1{ 
    MatrixProduct2_1(int n):r1(n){} 

    void update_state() override{ 
    cout << "matt21" << endl; 
    d3& W = static_cast<r3*>(parents[0])->state; 
    d2& x = static_cast<r2*>(parents[1])->state; 
    p(x.size()); 
    p(W.size()); 
    p(x[0].size()); 
    p(W[0].size()); 
    p(W[0][0].size()); 
    p(state.size()); 
    // assert (x.size()==W.size()); 
    // assert (x[0].size()==W[0].size()); 
    // assert (state.size()==W[0][0].size()); 
    assert (state.size() == W.size()); 

    state = zeros(r); 
    for (int i=0; i<W.size(); i++) 
    for (int j=0; j<W[0].size(); j++) 
    for (int k=0; k<W[0][0].size(); k++) 
    state[i] += W[i][j][k]*x[j][k]; 
    forward_propagate(); 
    } 
}; 

struct Convolution: r2{ 
    Convolution(int r, int c): r2(r, c){} 
    void update_state() override{ 
    cout << "convolving" << endl; 
    state = zeros(r, c); 
    d2& W = static_cast<r2*>(parents[0])->state; 
    d2& x = static_cast<r2*>(parents[1])->state; 

    int wCenterX = W[0].size()/2; 
    int wCenterY = W.size()/2; 
    int rows = x.size(), cols = x[0].size(); 
    int wRows = W.size(), wCols = W[0].size(); 

    //#pragma omp parallel for 
    for(int i=0; i < rows; i++) 
    for(int j=0; j < cols; j++) 
    for(int m=0; m < W.size(); m++){ 
     int mm = W.size() - 1 - m; 
     for(int n=0; n < wCols; n++){ 
     int nn = wCols - 1 - n; 
     int ii = i + (m - wCenterY); 
     int jj = j + (n - wCenterX); 
     if (ii >= 0 && ii < rows && jj >= 0 && jj < cols) 
     state[i][j] += x[ii][jj] * W[mm][nn]; 
     } 
    } 
    forward_propagate(); 
    } 
}; 


struct RELU: r2{ 
    RELU(int r, int c):r2(r, c){} 
    void update_state() override{ 
    cout << "relu2" << endl; 
    state = zeros(r,c); 
    d2& x = static_cast<r2*>(parents[0])->state; 
    for (int i=0; i<state.size(); i++) 
    for (int j=0; j<state[0].size(); j++) 
    if (x[i][j] > 0) 
    state[i][j] = x[i][j]; 
    forward_propagate(); 
    } 
}; 

struct Softmax: r1{ 
    Softmax(int r):r1(r){} 
    void update_state() override{ 
    cout << "softmax" << endl; 
    state = zeros(r); 
    p(parents.size()); 
    d1& x = static_cast<r1*>(parents[0])->state; 
    cout << "got state" << endl; 
    //p(x.size()); 
    //print(x); 

    p(x.size()); 
    cout << "argmax " << argmax(x) << endl; 
    double largest = x[argmax(x)]; 
    double lndenom = largest; 
    double expsum = 0; 
    cout << "starting expsum" << endl; 
    for (int i=0; i<x.size(); i++) 
    expsum += exp(x[i]-largest); 
    //expsum += x[i] - largest; 
    cout << "next loop " << endl; 
    for (int i=0; i<x.size(); i++) 
    state[i] = exp(x[i]-largest)/expsum; 
    //state[i] = x[i]-largest; 
    // state[i] = 3; 
    cout << "forward proping" << endl; 
    cout << "weird" << endl; 
    forward_propagate(); 
    cout << "done with softmax" <<endl; 
    } 
}; 

struct Add1: r1{ 
    Add1(int r):r1(r){} 
    void update_state() override{ 
    cout << "add1ing" << endl; 
    d1& x = static_cast<r1*>(parents[0])->state; 
    d1& y = static_cast<r1*>(parents[1])->state; 
    for (int i=0; i<r; i++) 
    state[i] = x[i]+y[i]; 
    forward_propagate(); 
    } 
}; 

struct Add2: r2{ 
    Add2(int r, int c): r2(r, c){} 
    void update_state() override{ 
    d2& x = static_cast<r2*>(parents[0])->state; 
    d2& y = static_cast<r2*>(parents[1])->state; 
    for (int i=0; i<x.size(); i++) 
    for (int j=0; j<x[0].size(); j++) 
    state[i][j] = x[i][j] + y[i][j]; 
    forward_propagate(); 
    } 
}; 

struct MaxPool: r2{ 
    MaxPool(int r, int c): r2(r, c){} 
    void update_state() override{ 
    d2& x = static_cast<r2*>(parents[0])->state; 
    for (int i=0; i<x.size(); i+=2) 
    for (int j=0; j<x[0].size(); j+=2) 
    state[i/2][j/2] = max(max(x[i][j], x[i+1][j]), max(x[i+1][j], x[i+1][j+1])); 
    forward_propagate(); 
    } 
}; 

int main(int argc, char *argv[]){ 
    if (argc>1){ 
    seed = atoi(argv[1]); 
    time_seed = false; 
    } 
    Node root; 
    r2 x; 
    x.state = getRandomDoubles(28,28); 
    //x.state[0][0]-=1000; 
    r2 wConv; 
    wConv.state = getRandomDoubles(10, 10); 
    root.add_child(x); 
    root.add_child(wConv); 
    Convolution c(28,28); 
    wConv.add_child(c); 
    x.add_child(c); 
    Add2 a(28,28); 
    r2 bConv(28,28); 
    bConv.state = getRandomDoubles(28,28); 
    c.add_child(a); 
    bConv.add_child(a); 
    RELU r(28,28); 
    a.add_child(r); 
    MaxPool max(14, 14); 
    r.add_child(max); 
// print(max.state); 
    r3 wFull(10,14,14); 
    wFull.state = getRandomDoubles(10,14,14); 
    //print(wFull.state); 
    // return 0; 
    MatrixProduct2_1 full(10); 
    wFull.add_child(full); 
    max.add_child(full); 
    //print(full.state); //suspiciously zero 
    r1 bFull(10); 
    bFull.state = getRandomDoubles(10); 
    Add1 aFull(10); 
    aFull.state[0] = 123; 
    full.add_child(aFull); 
    bFull.add_child(aFull); 
    Softmax s(10); 
    aFull.add_child(s); 
    // d1& x =   static_cast<r1*>(parents[0])->state; 
    // d1& asdf = static_cast<r1*>(s.parents[0])->state; 
    // print(asdf); 
    //root.forward_propagate(); 
    x.forward_propagate(); 
    //print(aFull.state); 
    print(s.state); 
    cout << "returning main"; 
}