Skip to content

Commit

Permalink
Merge pull request #844 from null-a/unused-option-warning2
Browse files Browse the repository at this point in the history
Show warning when Infer/Optimize receives unexpected option
  • Loading branch information
stuhlmueller committed May 5, 2017
2 parents 17d44ed + a88fc48 commit 1b5a0bf
Show file tree
Hide file tree
Showing 18 changed files with 144 additions and 135 deletions.
3 changes: 2 additions & 1 deletion src/header.wppl
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ var SampleGuide = function(wpplFn, options) {
};

var OptimizeThenSample = function(wpplFn, options) {
Optimize(wpplFn, _.omit(options, 'samples'));
Optimize(wpplFn, _.omit(options, 'samples', 'onlyMAP'));
var opts = _.pick(options, 'samples', 'onlyMAP', 'verbose');
return SampleGuide(wpplFn, opts);
};
Expand All @@ -481,6 +481,7 @@ var OptimizeThenSample = function(wpplFn, options) {
* next step in the heuristics flowchart
*/
var DefaultInfer = function(wpplFn, options) {
util.mergeDefaults(options, {}, 'Infer');
var maxEnumTreeSize = 200000;
var minSampleRate = 250; //from 1 to samples
var samples = 1000;
Expand Down
1 change: 0 additions & 1 deletion src/inference/asyncpf.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ module.exports = function(env) {
}

function AsyncPF(s, k, a, wpplFn, options) {
util.throwUnlessOpts(options, 'AsyncPF');
this.numParticles = 0; // K_0 -- initialized here, set in run
this.bufferSize = options.bufferSize == undefined ? options.particles : options.bufferSize; // \rho
this.initNumParticles = Math.floor(this.bufferSize * (1 / 2)); // \rho_0
Expand Down
13 changes: 7 additions & 6 deletions src/inference/dream/estimator.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,16 @@ module.exports = function(env) {
var dreamSample = require('./sample')(env).dreamSample;
var dreamGradients = require('./gradients')(env);

return function(wpplFn, s, a, options, state, step, cont) {
return function(options) {
var opts = util.mergeDefaults(options, {
samples: 1
});
}, 'dream');
return function(wpplFn, s, a, state, step, cont) {

var objVal = 0;
var grad = {};
var objVal = 0;
var grad = {};

return util.cpsLoop(
return util.cpsLoop(
opts.samples,
// Loop body.
function(i, next) {
Expand All @@ -71,6 +72,6 @@ module.exports = function(env) {
objVal /= opts.samples;
return cont(grad, objVal);
});
};
};

};
18 changes: 10 additions & 8 deletions src/inference/elbo.ad.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ var JoinNode = graph.JoinNode;

module.exports = function(env) {

function ELBO(wpplFn, s, a, options, state, step, cont) {
this.opts = util.mergeDefaults(options, {
function makeELBOEstimator(options) {
options = util.mergeDefaults(options, {
samples: 1,
avgBaselines: true,
avgBaselineDecay: 0.9,
Expand All @@ -30,8 +30,14 @@ module.exports = function(env) {
// is useful in combination with the dumpGraph option for
// understanding/debugging weight propagation.
debugWeights: false
});
}, 'ELBO');
return function(wpplFn, s, a, state, step, cont) {
return new ELBO(wpplFn, s, a, options, state, step, cont).run();
};
}

function ELBO(wpplFn, s, a, options, state, step, cont) {
this.opts = options;
this.step = step;
this.state = state;
this.cont = cont;
Expand Down Expand Up @@ -392,10 +398,6 @@ module.exports = function(env) {

};

return function() {
var coroutine = Object.create(ELBO.prototype);
ELBO.apply(coroutine, arguments);
return coroutine.run();
};
return makeELBOEstimator;

};
4 changes: 2 additions & 2 deletions src/inference/enumerate.ad.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ var ScoreAggregator = require('../aggregation/ScoreAggregator');
module.exports = function(env) {

function Enumerate(store, k, a, wpplFn, options) {
util.throwUnlessOpts(options, 'Enumerate');
options = util.mergeDefaults(options, {
maxExecutions: Infinity,
strategy: undefined,
throwOnError: true,
maxRuntimeInMS: Infinity,
maxEnumTreeSize: Infinity
});
}, 'Enumerate');

this.throwOnError = options.throwOnError;
this.maxRuntimeInMS = options.maxRuntimeInMS; // Time upper threshold for enumeration
Expand Down
33 changes: 17 additions & 16 deletions src/inference/eubo.ad.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,26 @@ var guide = require('../guide');

module.exports = function(env) {

function EUBO(wpplFn, s, a, options, state, step, cont) {
this.opts = util.mergeDefaults(options, {
batchSize: 1
});

if (!_.has(this.opts, 'traces')) {
function makeEUBOEstimator(options) {
options = util.mergeDefaults(options, {
batchSize: 1,
traces: undefined
}, 'EUBO');
if (!options.traces) {
throw 'Example traces required.';
}

this.traces = this.opts.traces;

if (this.opts.batchSize <= 0 ||
this.opts.batchSize > this.traces.length) {
if (options.batchSize <= 0 ||
options.batchSize > options.traces.length) {
throw 'Invalid batchSize.';
}
return function(wpplFn, s, a, state, step, cont) {
return new EUBO(wpplFn, s, a, options, state, step, cont).run();
};
}

function EUBO(wpplFn, s, a, options, state, step, cont) {
this.opts = options;
this.traces = this.opts.traces;

this.cont = cont;

Expand Down Expand Up @@ -158,10 +163,6 @@ module.exports = function(env) {
}
}

return function() {
var coroutine = Object.create(EUBO.prototype);
EUBO.apply(coroutine, arguments);
return coroutine.run();
};
return makeEUBOEstimator;

};
2 changes: 1 addition & 1 deletion src/inference/forwardSample.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ module.exports = function(env) {
guide: false, // true = sample guide, false = sample target
onlyMAP: false,
verbose: false
});
}, 'ForwardSample');

var hist = new CountAggregator(opts.onlyMAP);
var logWeights = []; // Save total factor weights
Expand Down
28 changes: 18 additions & 10 deletions src/inference/hmckernel.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,28 @@ var sum = generic.sum;

module.exports = function(env) {

function HMCKernel(cont, oldTrace, options) {
var options = util.mergeDefaults(options, {
function makeHMCKernel(options) {
options = util.mergeDefaults(options, {
steps: 5,
stepSize: 0.1,
exitFactor: 0
});
stepSize: 0.1
}, 'HMC kernel');
assert.ok(options.steps > 0);
var kernel = function(cont, oldTrace, runOpts) {
return new HMCKernel(cont, oldTrace, options, runOpts).run();
};
kernel.adRequired = true;
return kernel;
}

function HMCKernel(cont, oldTrace, options, runOpts) {
this.steps = options.steps;
this.stepSize = options.stepSize;
this.exitFactor = options.exitFactor;

assert.ok(this.steps > 0);
runOpts = util.mergeDefaults(runOpts, {
exitFactor: 0
});

this.exitFactor = runOpts.exitFactor;

this.cont = cont;
this.oldTrace = oldTrace;
Expand Down Expand Up @@ -253,8 +263,6 @@ module.exports = function(env) {

HMCKernel.prototype.incrementalize = env.defaultCoroutine.incrementalize;

return _.assign(function(cont, oldTrace, options) {
return new HMCKernel(cont, oldTrace, options).run();
}, { adRequired: true });
return makeHMCKernel;

};
52 changes: 26 additions & 26 deletions src/inference/incrementalmh.js
Original file line number Diff line number Diff line change
Expand Up @@ -775,48 +775,48 @@ module.exports = function(env) {
// ------------------------------------------------------------------

function IncrementalMH(s, k, a, wpplFn, opts) {
util.throwUnlessOpts(opts, 'IncrementalMH');
// Extract options
var numSamples = opts.samples === undefined ? 1 : opts.samples;
var dontAdapt = opts.dontAdapt === undefined ? false : opts.dontAdapt;
var debuglevel = opts.debuglevel === undefined ? 0 : opts.debuglevel;
var verbose = opts.verbose === undefined ? false : opts.verbose;
var doFullRerun = opts.doFullRerun === undefined ? false : opts.doFullRerun;
var onlyMAP = opts.onlyMAP === undefined ? false : opts.onlyMAP;
var minHitRate = opts.cacheMinHitRate === undefined ? 0.00000001 : opts.cacheMinHitRate;
var fuseLength = opts.cacheFuseLength === undefined ? 50 : opts.cacheFuseLength;
var lag = opts.lag === undefined ? 0 : opts.lag;
var iterFuseLength = opts.cacheIterFuseLength === undefined ? 10 : opts.cacheIterFuseLength;
var burn = opts.burn === undefined ? 0 : opts.burn;
var verboseLag = opts.verboseLag === undefined ? 1 : opts.verboseLag;
opts = util.mergeDefaults(opts, {
samples: 1,
dontAdapt: false,
debuglevel: 0,
verbose: false,
doFullRerun: false,
onlyMAP: false,
cacheMinHitRate: 0.00000001,
cacheFuseLength: 50,
lag: 0,
cacheIterFuseLength: 10,
burn: 0,
verboseLag: 1
}, 'IncrementalMH');

// Doing a full re-run doesn't really jive with the heuristic we use for adaptive
// caching, so disable adaptation in this case.
if (doFullRerun)
dontAdapt = true;
if (opts.doFullRerun)
opts.dontAdapt = true;

DEBUG = debuglevel;
this.verbose = verbose;
DEBUG = opts.debuglevel;
this.verbose = opts.verbose;

this.k = k;
this.oldStore = s;
this.iterations = numSamples * (lag + 1) + burn;
this.iterations = opts.samples * (opts.lag + 1) + opts.burn;
this.wpplFn = wpplFn;
this.s = s;
this.a = a;

this.aggregator = new CountAggregator(onlyMAP);
this.aggregator = new CountAggregator(opts.onlyMAP);

this.totalIterations = this.iterations;
this.acceptedProps = 0;
this.lag = lag;
this.burn = burn;
this.verboseLag = verboseLag;
this.lag = opts.lag;
this.burn = opts.burn;
this.verboseLag = opts.verboseLag;

this.doFullRerun = doFullRerun;
this.doFullRerun = opts.doFullRerun;

this.doAdapt = !dontAdapt;
this.cacheAdapter = new CacheAdapter(minHitRate, fuseLength, iterFuseLength);
this.doAdapt = !opts.dontAdapt;
this.cacheAdapter = new CacheAdapter(opts.cacheMinHitRate, opts.cacheFuseLength, opts.cacheIterFuseLength);

// Move old coroutine out of the way and install this as the current
// handler.
Expand Down
46 changes: 19 additions & 27 deletions src/inference/kernels.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,29 @@ var util = require('../util');

module.exports = function(env) {

var MHKernel = require('./mhkernel')(env);
var HMCKernel = require('./hmckernel')(env);

function HMCwithMHKernel(cont, oldTrace, options) {
// The options arg is passed to both kernels as SMC passes
// exitFactor via options.
return HMCKernel(function(trace) {
var opts = _.assign({ discreteOnly: true, adRequired: true }, options);
return MHKernel(cont, trace, opts);
}, oldTrace, options);
var makeMHKernel = require('./mhkernel')(env);
var makeHMCKernel = require('./hmckernel')(env);

function makeHMCwithMHKernel(options) {
var hmc = makeHMCKernel(options);
var mh = makeMHKernel({discreteOnly: true, adRequired: true});
var kernel = function(cont, oldTrace, runOpts) {
return hmc(function(trace) {
return mh(cont, trace, runOpts);
}, oldTrace, runOpts);
};
kernel.adRequired = true;
return kernel;
}

HMCwithMHKernel.adRequired = true;

var kernels = {
MH: MHKernel,
HMC: HMCwithMHKernel,
HMConly: HMCKernel
MH: makeMHKernel,
HMC: makeHMCwithMHKernel,
HMConly: makeHMCKernel
};

// Takes an options object (as passed to inference algorithms) and
// converts kernel options into functions with options partially
// applied. For example:

// 'MH' => function(..., opts) { return MHKernel(..., opts); }
// { MH: options } => function(..., extraOpts) { return MHKernel(..., merge(options, extraOpts)) }
// Takes a kernel options object (as passed to inference algorithms)
// and returns the specified kernel with any options applied.

function parseOptions(obj) {
// Expects either a kernel name or an object containing a single
Expand All @@ -49,12 +46,7 @@ module.exports = function(env) {

var name = _.isString(obj) ? obj : _.keys(obj)[0];
var options = _.isString(obj) ? {} : _.values(obj)[0];
var kernel = kernels[name];

return _.assign(function(cont, oldTrace, extraOptions) {
var allOptions = _.assign({}, options, extraOptions);
return kernel(cont, oldTrace, allOptions);
}, kernel);
return kernels[name](options);
}

// Combinators for kernel functions.
Expand Down
5 changes: 3 additions & 2 deletions src/inference/mcmc.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ module.exports = function(env) {
var kernels = require('./kernels')(env);

function MCMC(s, k, a, wpplFn, options) {
util.throwUnlessOpts(options, 'MCMC');
var options = util.mergeDefaults(options, {
samples: 100,
kernel: 'MH',
lag: 0,
burn: 0,
verbose: false,
onlyMAP: false,
callbacks: []
});
}, 'MCMC');

options.kernel = kernels.parseOptions(options.kernel);

Expand Down

0 comments on commit 1b5a0bf

Please sign in to comment.