diff options
author | Jake Hofman <jhofman@gmail> | 2013-06-27 04:37:18 +0400 |
---|---|---|
committer | Jake Hofman <jhofman@gmail> | 2013-06-27 04:37:18 +0400 |
commit | 8fec9447898c35262ca2d16f018b8ecdea2404ea (patch) | |
tree | 81d31de1a85be604b2fb9627b26bc28dfffb102b /vowpalwabbit/mf.cc | |
parent | d962dee760f5fbe709ac47b336ac18d14607a877 (diff) |
cleaned up mf.cc
Diffstat (limited to 'vowpalwabbit/mf.cc')
-rw-r--r-- | vowpalwabbit/mf.cc | 100 |
1 files changed, 46 insertions, 54 deletions
diff --git a/vowpalwabbit/mf.cc b/vowpalwabbit/mf.cc index 99535d57..670fe6b4 100644 --- a/vowpalwabbit/mf.cc +++ b/vowpalwabbit/mf.cc @@ -35,9 +35,11 @@ struct mf { vector<string> pairs; uint32_t rank; + uint32_t increment; // array to cache w*x, (l^k * x_l) and (r^k * x_r) + // [ w*(1,x_l,x_r) , l^1*x_l, r^1*x_r, l^2*x_l, r^2*x_2, ... ] v_array<float> sub_predictions; // array for temp storage of indices @@ -50,67 +52,67 @@ struct mf { }; void inline_predict(mf* data, vw* all, example* &ec) { + // store namespace indices copy_array(data->indices, ec->indices); float prediction = 0; - data->sub_predictions.erase(); - // modify label to indicate test example (predict only) + // set label to FLT_MAX to indicate test example (predict only) float label = ((label_data*) ec->ld)->label; ((label_data*) ec->ld)->label = FLT_MAX; - // prediction from linear terms + // predict from linear terms data->base.learn(ec); - // store constant + linear prediction + // store linear prediction data->sub_predictions.push_back(ec->partial_prediction); + prediction += ec->partial_prediction; - /* - // prediction from interaction terms + // add interaction terms to prediction for (vector<string>::iterator i = data->pairs.begin(); i != data->pairs.end(); i++) { if (ec->atomics[(int) (*i)[0]].size() > 0 && ec->atomics[(int) (*i)[1]].size() > 0) { for (size_t k = 1; k <= all->rank; k++) { - // set to left namespace only + // set example to left namespace only ec->indices.erase(); ec->indices.push_back((int) (*i)[0]); - // compute l_k * x_l + // compute l^k * x_l using base learner update_example_indicies(all->audit, ec, data->increment*k); data->base.learn(ec); float x_dot_l = ec->partial_prediction; data->sub_predictions.push_back(ec->partial_prediction); update_example_indicies(all->audit, ec, -data->increment*k); - // set to right namespace only + // set example to right namespace only ec->indices.erase(); ec->indices.push_back((int) (*i)[1]); - // compute r_k * x_r + // compute r^k * x_r using base learner update_example_indicies(all->audit, ec, data->increment*(k + data->rank)); data->base.learn(ec); float x_dot_r = ec->partial_prediction; data->sub_predictions.push_back(ec->partial_prediction); update_example_indicies(all->audit, ec, -data->increment*(k + data->rank)); + // accumulate prediction prediction += (x_dot_l * x_dot_r); } } } - */ - copy_array(ec->indices, data->indices); + // restore namespace indices and label + copy_array(ec->indices, data->indices); ((label_data*) ec->ld)->label = label; - ec->partial_prediction = data->sub_predictions[0] + prediction; + + // finalize prediction + ec->partial_prediction = prediction; ec->final_prediction = GD::finalize_prediction(*(data->all), ec->partial_prediction); } - float sgn(float x) { - return 2*(x >= 0) - 1; - } -void learn_with_output(void* d, example* ec, bool shouldOutput) { +void learn(void* d, example* ec) { mf* data = (mf*) d; vw* all = data->all; @@ -119,73 +121,67 @@ void learn_with_output(void* d, example* ec, bool shouldOutput) { return; } + // store namespace indices + copy_array(data->indices, ec->indices); + + // predict with current weights inline_predict(data, all, ec); - // update linear weights + // force base learner to use precomputed prediction ec->precomputed_prediction = true; - data->base.learn(ec); - copy_array(data->indices, ec->indices); + // update linear weights + data->base.learn(ec); - /* - // update left and right terms + // update interaction terms + // looping over all pairs of non-empty namespaces for (vector<string>::iterator i = data->pairs.begin(); i != data->pairs.end(); i++) { if (ec->atomics[(int) (*i)[0]].size() > 0 && ec->atomics[(int) (*i)[1]].size() > 0) { for (size_t k = 1; k <= all->rank; k++) { - // set to left namespace only + // set example to left namespace only ec->indices.erase(); ec->indices.push_back((int) (*i)[0]); + // store feature values for left namespace copy_array(data->temp_features, ec->atomics[(int) (*i)[0]]); - // modify features - // multiple features in left namespace by r^k * x_r + // multiply features in left namespace by r^k * x_r for (feature* f = ec->atomics[(int) (*i)[0]].begin; f != ec->atomics[(int) (*i)[0]].end; f++) f->x *= data->sub_predictions[2*k]; - // update l^k + // update l^k using base learner update_example_indicies(all->audit, ec, data->increment*k); data->base.learn(ec); update_example_indicies(all->audit, ec, -data->increment*k); - // restore features + // restore left namespace features copy_array(ec->atomics[(int) (*i)[0]], data->temp_features); - // for (feature* f = ec->atomics[(int) (*i)[0]].begin; f != ec->atomics[(int) (*i)[0]].end; f++) - // f->x /= data->sub_predictions[2*k]; - // set to right namespace only + // set example to right namespace only ec->indices.erase(); ec->indices.push_back((int) (*i)[1]); + // store feature values for right namespace copy_array(data->temp_features, ec->atomics[(int) (*i)[1]]); - // modify features - // multiple features in right namespace by l^k * x_l + // multiply features in right namespace by l^k * x_l for (feature* f = ec->atomics[(int) (*i)[1]].begin; f != ec->atomics[(int) (*i)[1]].end; f++) f->x *= data->sub_predictions[2*k-1]; - // update r^k + // update r^k using base learner update_example_indicies(all->audit, ec, data->increment*(k + data->rank)); data->base.learn(ec); update_example_indicies(all->audit, ec, -data->increment*(k + data->rank)); - // restore features + // restore right namespace features copy_array(ec->atomics[(int) (*i)[1]], data->temp_features); - // for (feature* f = ec->atomics[(int) (*i)[1]].begin; f != ec->atomics[(int) (*i)[1]].end; f++) - // f->x /= data->sub_predictions[2*k-1]; - } } } - */ - + + // restore namespace indices and unset precomputed prediction copy_array(ec->indices, data->indices); ec->precomputed_prediction = false; - -} - -void learn(void* d, example* ec) { - learn_with_output(d, ec, false); } void finish(void* data) { @@ -194,9 +190,7 @@ void finish(void* data) { o->all->pairs = o->pairs; o->base.finish(); - //cout << "constant " << o->all->reg.weight_vector[(constant * o->all->reg.stride)&o->all->reg.weight_mask] << endl; - - // clean up local arrays + // clean up local v_arrays o->indices.delete_v(); o->sub_predictions.delete_v(); delete o; @@ -204,7 +198,7 @@ void finish(void* data) { void drive(vw* all, void* d) { example* ec = NULL; - + while (true) { if ((ec = VW::get_example(all->p)) != NULL) //blocking operation. { @@ -218,19 +212,19 @@ void drive(vw* all, void* d) { } learner setup(vw& all, po::variables_map& vm) { - //mf* data = (mf*) calloc(1, sizeof(mf)); mf* data = new mf; + // copy global data locally data->base = all.l; data->all = &all; data->rank = all.rank; - // clear global pairs for eventual calls to base learner - // store pairs in local data structure + // store global pairs in local data structure and clear global pairs + // for eventual calls to base learner data->pairs = all.pairs; all.pairs.clear(); - // set increment + // set index increment between weights data->increment = all.reg.stride * all.weights_per_problem; all.weights_per_problem *= data->rank; @@ -241,8 +235,6 @@ learner setup(vw& all, po::variables_map& vm) { all.reg.weight_vector[j*all.reg.stride] = (float) (0.1 * frand48()); } - //cout << "constant " << data->all->reg.weight_vector[(constant * data->all->reg.stride)&data->all->reg.weight_mask] << endl; - learner ret(data, drive,learn, finish, all.l.sl); return ret; } |