卷积神经网络简单实现

A simple implementation of Convolutional Neural Networks
namespace CNN{
    vector split(string& str,const char* c)
    {
        char *cstr, *p;
        vector res;
        cstr = new char[str.size()+1];
        strcpy(cstr,str.c_str());
        p = strtok(cstr,c);
        while(p!=NULL)
        {
            res.push_back((double)atof(p) );
            p = strtok(NULL,c);
        }

        return res;
    }

    double sigmoid(double z){
        return 1.0/(1.0 + pow(e,-z));
    }

}

vector* pool(vector<vector<vector > > *originOutput,const int sampleRateX,const int sampleRateY){
    vector *pooledData = new vector(originOutput->size());
    for (int i = 0; i < originOutput->size(); i++) {
        Patch *layerOutput = new Patch();
        for (int j = 0; j < (*originOutput)[i].size();j += sampleRateX ) {
            vector *oneRow = new vector();
            for (int k = 0; k < (*originOutput)[i][j].size(); k += sampleRateY ) {
                double max = 0.0;
                for (int m = 0; m < sampleRateX; m++) {
                    for (int n = 0; n < sampleRateY; n++) {

                        if (max < (*originOutput)[i][j + m][k + n]) {
                            max = (*originOutput)[i][j + m][k + n];
                        }
                    }
                }
                oneRow->push_back(max);
            }
            layerOutput->push_back((*oneRow));
        }
        (*pooledData)[i] = (*layerOutput);
    }
    originOutput->clear();
    originOutput = new vector(*pooledData);
    return originOutput;
}

void getParas(string filepPath){
    ifstream ifs;

    try {
        ifs.open((filepPath).c_str());

        string str;
        while (!ifs.eof()) {
            //get w1
            for (int i = 0; i < conv_hiddenNodes; i++ ) {
                getline(ifs, str);
                w1->push_back(CNN::split(str,","));
            }
            cout<size()<<endl;
            //get b1
            getline(ifs, str);
            *b1 = CNN::split(str,",");
            cout<size()<<endl;
            //get means
            getline(ifs, str);
            *means = CNN::split(str,",");
            cout<size()<<endl;

            //get stds
            getline(ifs, str);
            *stds = CNN::split(str, ",");
            cout<size()<<endl;
            break;
        }


        ifs.close();
    } catch (ifstream::failure e) {
        cout<<"Exception opening/reading/closing filen";
    }


}

vector* vetorized(Patch *patch){
    vector *res = new vector();
    for (int i = 0; i < patch->size(); i++) {
        for (int j = 0; j < (*patch)[i].size(); j++) {
            res->push_back((*patch)[i][j]);
        }
    }
    return res;
}



void preprocess(vector *vec_pat){
    for (int i = 0; i < vec_pat->size() ; i++) {
        (*vec_pat)[i] -= (*means)[i];
        (*vec_pat)[i] /= (*stds)[i];

    }
}

vector *forward2Middle(Patch *patch){
    vector *res = new vector();
    vector *patch_vec = vetorized(patch);
    preprocess(patch_vec);

    for (int i = 0; i < conv_hiddenNodes ; i ++) {
        double h = 0.0;
        for (int j = 0; j < inputNodes; j++) {
            h += (*patch_vec)[j] * (*w1)[i][j];
        }
        h += (*b1)[i];
        h = CNN::sigmoid(h);

        res->push_back(h);
    }

    return res;
}


vector* forward(vector<vector > *patches){
    int patchesSizeX = (int)patches->size();
    int patchesSizeY = (int)(*patches)[0].size();
    vector *middleLayerOutput  = new vector(conv_hiddenNodes,vector<vector >(patchesSizeX,vector(patchesSizeY)));
    for (int i = 0; i < patchesSizeX; i++) {
        for (int j = 0; j < patchesSizeY; j++) {
            vector *res =  forward2Middle(&(*patches)[i][j]);
            for (int k = 0; k < res->size(); k++) {
                (*middleLayerOutput)[k][i][j] = (*res)[k];
            }
        }
    }
    return middleLayerOutput;
}

string stringlized(const vector<vector<vector > > *pooledOutput){
    stringstream ss;

    for (int i = 0; i < pooledOutput->size(); i++) {
        for (int j = 0; j < (*pooledOutput)[i].size(); j++) {
            for (int k = 0; k < (*pooledOutput)[i][j].size(); k++) {
                ss<<","<< (*pooledOutput)[i][j][k];
            }
        }
    }
    return ss.str();
}
string int2str(const int value){
    string str;

    return str;

void savetoDisk(const vector<vector<vector > > *pooledOutput,string filePath,bool isTrain,int sampleId = 0,int ylabel = -1){
    ofstream fs;
    try {

        if (isTrain) {
            if (!trainFirstFlag) {
                fs.open(filePath.c_str(),ios::app|ios::out);
            }else{
                fs.open(filePath.c_str(),ios::ate|ios::out);
                trainFirstFlag = false;
                fs<<"Id,label,value"<<endl;

            }
            stringstream ss;

            ss << sampleId<<","<<ylabel;
            string str = ss.str();

            str += stringlized(pooledOutput);
            fs<<str<<endl;

        }else{
            if (!testFirstFlag) {
                fs.open(filePath.c_str(),ios::app|ios::out);
            }else{
                fs.open(filePath.c_str(),ios::ate|ios::out);
                fs<<"Id,value"<<endl;
                testFirstFlag = false;
            }
            stringstream ss;
            ss << sampleId;
            string str = ss.str();
            str += stringlized(pooledOutput);
            fs<<str<<endl;

        }
        fs.close();

    } catch (fstream::failure err) {
        cout<<"Cannot open output file!"<<endl;
    }
}




vector<vector >* transfer2Twodimention(const vector *rowVec ,const int first_dimension){
    vector<vector > *res = new vector<vector >(first_dimension);
    int cols = (int)rowVec->size() / first_dimension;

    for (int i = 0 ; i < first_dimension; i++) {
        for (int j = 0; j < cols; j++) {
            (*res)[i].push_back( (*rowVec)[i * cols + j]);
        }
    }

    return res;

}


vector<vector >* getPatches(Image *image,int patchX,int patchY){
    int patchesX = ((int)image->size() - patchX +1)  ;
    int patchesY = ((int)(*image)[0].size() - patchY  + 1);

    vector< vector > *patches = new vector<vector >(patchesX,vector(patchesY));

    for (int i = 0; i< patchesX; i++) {
        Patch apatch = Patch(patchX);
        for (int j = 0; j < patchesY; j++) {
            for (int k = 0; k < patchX; k++) {
                for (int m = 0; m < patchY; m++) {
                    apatch[k].push_back( (*image)[i + k][ j + m]);
                }
            }
            (*patches)[i][j] = apatch;
        }
    }
    return patches;

}


void convol( FileReader* fileReader,const int patchSizeX,const int patchSizeY,const int middleNodes){
    conv_hiddenNodes = middleNodes;
    inputNodes = patchSizeX * patchSizeY;
    string filePath = "sparsePara.csv";
    string trainPath = "train.csv";
    string testPath = "test.csv";

    getParas(filePath);

    const vector<vector > *trainX = (fileReader->getTrainX());
    const vector<vector > *trainY = fileReader -> getTrainY();
    const vector<vector > *testID = fileReader->getTestID();

    for (int i = 0; i < trainX->size(); i++) {
        Image *image = transfer2Twodimention(&(*trainX)[i], sizeX);

        vector<vector > *patches;
        patches = getPatches(image, patchSizeX, patchSizeY);

        vector *middleOutput = forward(patches);

        middleOutput = pool(middleOutput, samRateX, samRateY);     // now middleOutput saves the pooled output
        int y = int((*trainY)[i][0]);
        savetoDisk(middleOutput, trainPath, true,0,y);
        delete patches;
        delete middleOutput;
        cout<<i<<endl;
     }
}
Read More