예제 #1
0
파일: rbm.cpp 프로젝트: daydreamt/pgm
	// this does two sampling steps for a rbm. TODO: Do one sampling step less please.
	rbm get_next(rbm* r) {
	  // first sample the hidden layer from the visible one

	  std::vector<int> hidden = sample_hidden(r, r->visible);

	  // make a new rbm
	  rbm r2 = *r;

	  std::vector<int> new_visible = sample_visible(r, r->hidden);

	  r2.visible = new_visible;

	  // you don't have to sample the hidden one
	  //std::vector<int> new_hidden = sample_hidden(&r2, r2.visible);
	  //r2.hidden = new_hidden;

	  return r2;
	}
예제 #2
0
파일: RBM_P.cpp 프로젝트: daiwk/DBN
void RBM_P::train_full(bool reset = true, int rbmlayers_id = 0)
{
    // Pop parameters
    int epochs = *(int*) getParameter("epochs");
    int batch_size = *(int*) getParameter("batch_size");
    int cd_steps = *(int*) getParameter("cd_steps");
    bool verbose = *(bool*) getParameter("verbose");
//    ostream* out = *(ostream**) getParameter("log");

//    // Pop LS
//    Dataset* LS = sets[dataset];
//    Dataset* QS = sets["QS"];
//    assert(LS != NULL);

//    if (conditional) {
//        assert(QS != NULL);
//        assert(LS->nb_rows == QS->nb_rows);
//    }

    // Start calculating the running time
    struct timeval start;
    struct timeval end;
    unsigned long usec;
    gettimeofday(&start, NULL);

    // Reset parameters
    if (reset) {
        // Reset everything
        this->reset();

//        // Set vb_ik to the logs of their respective base rates
//        // for (int n = 0; n < LS->nb_rows; n++) {
////            for (int m = LS->index[n]; m < LS->index[n] + LS->count[n]; m++) {
////                vb[_ik(LS->ids[m], LS->ratings[m] - 1)] += 1.;
//            }
//        }
//
//        for (int i = 0; i < M; i++) {
//            int ik_0 = _ik(i, 0);
//            double total = 0.;
//
//            for (int k = 0; k < K; k++) {
//                total += vb[ik_0 + k];
//            }
//
//            if (total > 0.) {
//                for (int k = 0; k < K; k++) {
//                    int ik = ik_0 + k;
//
//                    if (vb[ik] == 0.) {
//                        vb[ik] = -10E5;
//                    } else {
//                        vb[ik] = log(vb[ik] / total);
//                    }
//                }
//            }
//        }
    }

    // print running time
    gettimeofday(&end, NULL);
    usec = 1000000 * (end.tv_sec-start.tv_sec) + end.tv_usec - start.tv_usec;
//    cout << "File: " << __FILE__ << ", Function: " << __FUNCTION__  << ", Line: " << __LINE__ << endl;
    printf( "File: %s, Function: %s, Line: %d\n", __FILE__, __FUNCTION__, __LINE__);
//    cout << "Time of reset(): " << usec << " usec[" << usec / 1000000. <<" sec]." << endl;
    printf("Time of reset(): %ld usec[ %lf sec].", usec, usec / 1000000.);
    // Print some stats
//    if (verbose) {
//        *out << toString() << endl;
//        *out << "% ---" << endl;
//        *out << "% Epoch\tRMSE\tRMSE-TRAIN\tTIME\n";
//        out->flush();
//        //*out << 0 << "\t" << validate() << "\t" << usec / 1000000. << endl;
//        char res[1000];
//        sprintf(res, "0\t%lf\t%lf\t%lf\t\n", validate(), test("LS"), usec / 1000000.);
//        *out << res;
////        *out << 0 << "\t" << validate() << "\t" << usec / 1000000. << endl;
//	
//	
//        out->flush();
//    }

    // Start calculating the running time
    gettimeofday(&start, NULL);
    
    // Allocate local data structures
    double* vs = new double[M * K];
    double* vp = new double[M * K];
    double* hs = new double[F];
    double* hp = new double[F];

    double* w_acc = new double[M * K * F];
    int* w_count = new int[M * K * F];
    double* vb_acc = new double[M * K];
    int* vb_count = new int[M * K];
    double* hb_acc = new double[F];

//    bool* watched = NULL;
//    if (conditional) {
//        watched = new bool[M];
//    }
    
    char ss[1000];
    // 只有id=0(最开始那层)的时候才调用这个train函数,其他层调用的是train_full函数
    
    // 读取上一层的hs到这层的vs里面    
    sprintf(ss, "rbm-hs-%d", rbmlayers_id);
    string hs_filename_in = ss; 

    ifstream in_hs(hs_filename_in.c_str(), ios::in | ios::binary);
    if (in_hs.fail()) {
        throw runtime_error("I/O exception");
    }
    
    in_hs.read((char*) vs, M * K * sizeof (double));

    in_hs.close();

    for(int dd = 0; dd < M * K; dd++)
        printf("after reading from file: vs[%d]: %lf\n", dd, vs[dd]);

    // 读取上一层的hb到这层的vb里面    
    sprintf(ss, "rbm-hb-%d", rbmlayers_id);
    string hb_filename_in = ss; 

    ifstream in_hb(hb_filename_in.c_str(), ios::in | ios::binary);
    if (in_hb.fail()) {
        throw runtime_error("I/O exception");
    }
    
    in_hb.read((char*) vb, M * K * sizeof (double));

    in_hb.close();

    for(int dd = 0; dd < M * K; dd++)
        printf("after reading from file: vb[%d]: %lf\n", dd, vb[dd]);
    
    // Loop through epochs
    for (int epoch = 1; epoch <= epochs; epoch++) {
        
        // Start calculating the running time
        struct timeval start_train;
        struct timeval end_train;
        unsigned long usec_train;
        gettimeofday(&start_train, NULL);

        // Loop through mini-batches of users
        // for (int batch = 0; batch < LS->nb_rows; batch += batch_size)// 
        for (int batch = 0; batch < N; batch += batch_size) {
            // Reset the accumulators
            zero(w_acc, M * K * F);
            zero(w_count, M * K * F);
            zero(vb_acc, M * K);
            zero(vb_count, M * K);
            zero(hb_acc, F);

//            if (conditional) {
//                zero(watched, M);
//            }

            // Loop through users of current batch
            for (int n = batch; n < min(batch + batch_size, N); n++) {
            //for (int n = batch; n < min(batch + batch_size, LS->nb_rows); n++) // 
//                // Set user n data on the visible units
//                for (int m = LS->index[n]; m < LS->index[n] + LS->count[n]; m++) {
//                    int i = LS->ids[m];
//                    int ik_0 = _ik(i, 0);
//
//                    for (int k = 0; k < K; k++) {
//                        vs[ik_0 + k] = 0.;
//                    }
//
//                    vs[ik_0 + LS->ratings[m] - 1] = 1.;
//                }

                int* mask_hidden = new int[F];
                for(int ind = 0; ind < F; ind++) {
                    mask_hidden[ind] = ind;
                }
                
                int* mask_visible = new int[M];
                for(int ind = 0; ind < M; ind++) {
                    mask_visible[ind] = ind;
                }

                // Compute p(h | V, d) into hp
                if (!conditional) {
//                    update_hidden(vs, &LS->ids[LS->index[n]], LS->count[n], hp);
                    update_hidden_p(vs, &mask_visible[0], M, hp);
                    printf("finished first update hidden\n");
                } else {
//                    update_hidden(vs, &LS->ids[LS->index[n]], LS->count[n], &QS->ids[QS->index[n]], QS->count[n], hp);
                }

                // Accumulate "v_ik * h_j", "v_ik" and "h_j"s (0)
                for (int m = 0; m < M; m++) {
//                for (int m = LS->index[n]; m < LS->index[n] + LS->count[n]; m++) // 
//                    int i = LS->ids[m];
                    int i = m;
//                    int k = LS->ratings[m] - 1;
                    int k = 0;
                    int ikj_0 = _ikj(i, k, 0);

                    for (int j = 0; j < F; j++) {
                        w_acc[ikj_0 + j] += hp[j];
                    }

                    // 原来是对那些受影响的v+=1,现在是要更新所有v
                    vb_acc[_ik(i, k)] += 1.;
                    // 学习hb_acc,+= vp[]...不要乱搞。。。
                    printf("1.vb_acc[%d]: %lf\n", _ik(i, k), vb_acc[_ik(i, k)]);
                    printf("xx.vp[%d]: %lf\n", _ik(i, k), vp[_ik(i, k)]);
                    // vb_acc[_ik(i, k)] += vp[_ik(i, k)];
                    printf("2.vb_acc[%d]: %lf\n", _ik(i, k), vb_acc[_ik(i, k)]);
                }

                for (int j = 0; j < F; j++) {
                    hb_acc[j] += hp[j];
                    printf("hb_acc[%d]: %lf\n", j, hb_acc[j]);
                }

                // Count seen movies
//                if (conditional) {
//                    for (int m = LS->index[n]; m < LS->index[n] + LS->count[n]; m++) {
//                        watched[LS->ids[m]] = true;
//                    }
//
//                    for (int m = QS->index[n]; m < QS->index[n] + QS->count[n]; m++) {
//                        watched[QS->ids[m]] = true;
//                    }
//                }

                // Gibbs sampling
                for (int step = 0; step < cd_steps; step++) {
                    // Sample from p(h | V, d) into hs
                    sample_hidden(hp, hs);

                    // Compute p(V | h) into vp
                    update_visible_p(hs, vp, &mask_hidden[0], F);
//                    update_visible(hs, vp, &LS->ids[LS->index[n]], LS->count[n]);

                    // Sample from p(V | h) into hs
                    sample_visible_p(vp, vs, &mask_visible[0], M);
//                    sample_visible(vp, vs, &LS->ids[LS->index[n]], LS->count[n]);

                    // Compute p(h | V, d) into hp
                    if (!conditional) {
                        update_hidden_p(vs, &mask_visible[0], M, hp);
                        printf("finished second update hidden\n");
//                        update_hidden(vs, &LS->ids[LS->index[n]], LS->count[n], hp);
                    } else {
//                        update_hidden(vs, &LS->ids[LS->index[n]], LS->count[n], &QS->ids[QS->index[n]], QS->count[n], hp);
                    }
                }

                // Accumulate "-v_ik * h_j", "-v_ik" and "-h_j"s (T)
                // Count the number of terms in the accumulators
                for (int m = 0; m < M; m++) {
//                for (int m = LS->index[n]; m < LS->index[n] + LS->count[n]; m++) //
//                    int i = LS->ids[m];
                    int i = m;                    
                    int ik_0 = _ik(i, 0);

                    for (int k = 0; k < K; k++) {
                        int ik = ik_0 + k;
                        printf("after cd, vs[%d]: %lf\n", ik, vs[ik]);

                        for (int j = 0; j < F; j++) {
                            int ikj = _ikj(i, k, j);

                            w_acc[ikj] -= vs[ik] * hp[j];
                            // w_count[ikj]++;
                            w_count[ikj] = M * K * F;
                        }

                        vb_acc[ik] -= vs[ik];
                        vb_count[ik]++;
                        //vb_count[ik] = M * K;
                        printf("vb_count[%d]: %d\n", ik, vb_count[ik]);
                    }
                }

                for (int j = 0; j < F; j++) {
                    hb_acc[j] -= hp[j];
                }
            }

            // Update weights and biases
            // 参数3是用来算annealing rate用的
            update_w_p(w_acc, w_count, (epoch - 1) * N + batch);
            printf("last update_vb\n");
            update_vb_p(vb_acc, vb_count, (epoch - 1) * N + batch);
            update_hb_p(hb_acc, (epoch - 1) * N + batch);

//            if (conditional) {
//                update_d(hb_acc, watched, (epoch - 1) * LS->nb_rows + batch);
//            }
        }

//        // Log RMSE
//        if (verbose) {
//            
//            gettimeofday(&end_train, NULL);
//            usec_train = 1000000 * (end_train.tv_sec-start_train.tv_sec) + end_train.tv_usec - start_train.tv_usec;
//            char res[1000];
//            sprintf(res, "%d\t%lf\t%lf\t%lf\n", epoch, validate(), test("LS"), usec_train / 1000000.);
//            *out << res;
////            *out << epoch << "\t" << validate() << "\t" << usec_train / 1000000. << endl;
//            out->flush();
//        }
    }

    // Added by daiwenkai
    // 把hs的状态输出到文件,供下一层当做vs的输入

    sprintf(ss, "rbm-hs-%d", rbmlayers_id + 1);
    string hs_filename_out = ss; 
    ofstream out_hs(hs_filename_out.c_str(), ios::out | ios::binary);

    if (out_hs.fail()) {
        throw runtime_error("I/O exception! In openning rbm-hs-%d");
    }
    
    out_hs.write((char*) hs, F * sizeof (double));
    out_hs.close();
 
    // 把hb的状态输出到文件,供下一层当做vb的输入

    sprintf(ss, "rbm-hb-%d", rbmlayers_id + 1);
    string hb_filename_out = ss; 
    ofstream out_hb(hb_filename_out.c_str(), ios::out | ios::binary);

    if (out_hb.fail()) {
        throw runtime_error("I/O exception! In openning rbm-hs-%d");
    }
    
    out_hb.write((char*) hb, F * sizeof (double));
    out_hb.close();
   
    for(int dd = 0; dd < M; dd++)
        printf("after train_full: vb[%d]: %lf\n", dd, vb[dd]);

    for(int dd = 0; dd < F; dd++)
        printf("after train_full: hb[%d]: %lf\n", dd, hb[dd]);
    // Deallocate data structures
    if (vs != NULL) delete[] vs;
    if (vp != NULL) delete[] vp;
    if (hs != NULL) delete[] hs;
    if (hp != NULL) delete[] hp;

    if (w_acc != NULL) delete[] w_acc;
    if (w_count != NULL) delete[] w_count;
    if (vb_acc != NULL) delete[] vb_acc;
    if (vb_count != NULL) delete[] vb_count;
    if (hb_acc != NULL) delete[] hb_acc;
//    if (watched != NULL) delete[] watched;
    
    // print running time
    gettimeofday(&end, NULL);
    usec = 1000000 * (end.tv_sec-start.tv_sec) + end.tv_usec - start.tv_usec;
//    cout << "File: " << __FILE__ << ", Function: " << __FUNCTION__  << ", Line: " << __LINE__ << endl;
    printf( "File: %s, Function: %s, Line: %d\n", __FILE__, __FUNCTION__, __LINE__);
//    cout << "Time of train(): " << usec << " usec[" << usec / 1000000. <<" sec]." << endl;
    printf("Time of train_full(): %ld usec[ %lf sec].", usec, usec / 1000000.);
}
예제 #3
0
void train_crbm(dataset_blas *train_set, int nvisible, int nhidden, int nlabel,
               int epoch, double lr,
               int minibatch, double momentum, char *model_file){
    crbm m;
    int i, j, k;
    int nepoch;
    double *v1, *y1;
    uint8_t *l;
    int batch_size, niter;
    int wc;
    int err;
    double lik;
    double delta;
    int *idx;
    time_t start_t, end_t;

    init_crbm(&m, nvisible, nhidden, nlabel);

    //wc = (int)cblas_dasum(train_set->N * train_set->n_feature, train_set->input, 1);
    niter = (train_set->N-1)/minibatch + 1;
    delta = lr / (1.0*minibatch);
    /*
     * shuffle training data
    v1 = (double*)malloc(minibatch * m.nvisible * sizeof(double));
    y1 = (double*)malloc(minibatch * m.ncat * sizeof(double));
    l = (uint8_t*)malloc(minibatch * sizeof(uint8_t));
    idx = (int*)malloc(train_set->N * sizeof(int));
    for(i = 0; i < train_set->N; i++)
        idx[i] = i;*/
    bzero(w_u, sizeof(w_u));
    bzero(u_u, sizeof(u_u));
    bzero(bh_u, sizeof(bh_u));
    bzero(bv_u, sizeof(bv_u));
    bzero(by_u, sizeof(by_u));

    //shuffle(idx, train_set->N);
    
    for(nepoch = 0; nepoch < epoch; nepoch++){
        
        lik = 0;
        err = 0;
        start_t = time(NULL);

        for(k = 0; k < niter; k++){
#ifdef DEBUG
            if((k+1) % 200 == 0){
                printf("batch %d\n", k+1);
            }
#endif
            if(k == niter - 1){
                batch_size = train_set->N - minibatch * (niter-1);
            }else{
                batch_size = minibatch;
            }

            v1 = train_set->input + train_set->n_feature * minibatch * k;
            y1 = train_set->label + train_set->nlabel * minibatch * k;
            l = train_set->output + minibatch * k;
            /*
             * shuffle training data
            for(i = 0; i < batch_size; i++){
                cblas_dcopy(m.nvisible, train_set->input + m.nvisible * idx[k*minibatch+i],
                            1, v1 + m.nvisible * i, 1);
                cblas_dcopy(m.ncat, train_set->label + m.ncat * idx[k*minibatch+i],
                            1, y1 + m.ncat * i, 1);
                l[i] = train_set->output[idx[k*minibatch+i]];
            }*/
            get_hidden(&m, v1, y1, ph1, batch_size);            
            sample_hidden(&m, ph1, h1, batch_size);

            get_visible(&m, h1, pv, batch_size);
            sample_visible(&m, pv, v2, batch_size);

            get_class(&m, h1, py, batch_size);
            sample_class(&m, py, y2, batch_size);

            get_hidden(&m, v2, y2, ph2, batch_size);
            sample_hidden(&m, ph2, h2, batch_size);
            
            //lik += get_likelihood(&m, v1, pv, batch_size);
            err += get_error(&m, y2, l, batch_size);
            
            //update w_u
            cblas_dgemm(CblasRowMajor, CblasTrans, CblasNoTrans,
                        m.nhidden, m.nvisible, batch_size,
                        1.0, ph2, m.nhidden, v2, m.nvisible,
                        0, a, m.nvisible);
            cblas_dgemm(CblasRowMajor, CblasTrans, CblasNoTrans,
                        m.nhidden, m.nvisible, batch_size,
                        1.0, ph1, m.nhidden, v1, m.nvisible,
                        -1, a, m.nvisible);
            cblas_daxpy(m.nvisible * m.nhidden, momentum, w_u, 1,
                        a, 1);
            cblas_dcopy(m.nvisible * m.nhidden, a, 1, w_u, 1);

            //update u_u
            cblas_dgemm(CblasRowMajor, CblasTrans, CblasNoTrans,
                        m.nhidden, m.ncat, batch_size,
                        1.0, ph2, m.nhidden, y2, m.ncat,
                        0, a, m.ncat);
            cblas_dgemm(CblasRowMajor, CblasTrans, CblasNoTrans,
                        m.nhidden, m.ncat, batch_size,
                        1.0, ph1, m.nhidden, y1, m.ncat,
                        -1, a, m.ncat);
            cblas_daxpy(m.ncat * m.nhidden, momentum, u_u, 1,
                        a, 1);
            cblas_dcopy(m.ncat * m.nhidden, a, 1, u_u, 1);

            //update bv_u
            cblas_dgemm(CblasRowMajor, CblasTrans, CblasNoTrans,
                        m.nvisible, 1, batch_size,
                        1.0, v2, m.nvisible, I, 1,
                        0, a, 1);
            cblas_dgemm(CblasRowMajor, CblasTrans, CblasNoTrans,
                        m.nvisible, 1, batch_size,
                        1.0, v1, m.nvisible, I, 1,
                        -1, a, 1);
            cblas_daxpy(m.nvisible, momentum, bv_u, 1,
                        a, 1);
            cblas_dcopy(m.nvisible, a, 1, bv_u, 1);

            //update by_u
            cblas_dgemm(CblasRowMajor, CblasTrans, CblasNoTrans,
                        m.ncat, 1, batch_size,
                        1.0, y2, m.ncat, I, 1,
                        0, a, 1);
            cblas_dgemm(CblasRowMajor, CblasTrans, CblasNoTrans,
                        m.ncat, 1, batch_size,
                        1.0, y1, m.ncat, I, 1,
                        -1, a, 1);
            cblas_daxpy(m.ncat, momentum, by_u, 1,
                        a, 1);
            cblas_dcopy(m.ncat, a, 1, by_u, 1);

            //update bh_u
            cblas_dgemm(CblasRowMajor, CblasTrans, CblasNoTrans,
                        m.nhidden, 1, batch_size,
                        1.0, ph2, m.nhidden, I, 1,
                        0, a, 1);
            cblas_dgemm(CblasRowMajor, CblasTrans, CblasNoTrans,
                        m.nhidden, 1, batch_size,
                        1.0, ph1, m.nhidden, I, 1,
                        -1, a, 1);
            cblas_daxpy(m.nhidden, momentum, bh_u, 1,
                        a, 1);
            cblas_dcopy(m.nhidden, a, 1, bh_u, 1);

            //change parameter
            cblas_daxpy(m.nvisible * m.nhidden, delta, w_u, 1,
                        m.w, 1);
            cblas_daxpy(m.ncat * m.nhidden, delta, u_u, 1,
                        m.u, 1);
            cblas_daxpy(m.nvisible, delta, bv_u, 1,
                        m.bv, 1);
            cblas_daxpy(m.ncat, delta, by_u, 1,
                        m.by, 1);
            cblas_daxpy(m.nhidden, delta, bh_u, 1,
                        m.bh, 1);
        }
        end_t = time(NULL);

        printf("[epoch %d] error:%.5lf%%\ttime:%.2fmin\n", nepoch + 1, 
               err * 100.0 / train_set->N, (end_t - start_t) / 60.0);
    }
    dump_model(&m, model_file);
    //print_prob(&m, train_set, "../data/rsm/test.prob");

    /*
     * shuffle training data
    free(v1);
    free(y1);
    free(l);*/
    free_crbm(&m);
}