Comparing version
38
index.js
@@ -1,37 +0,1 @@ | ||
var _ = require('lodash'); | ||
var BPromise = require('bluebird'); | ||
var debug = require('debug')('softmax'); | ||
var async = BPromise.method; | ||
function Algorithm(options) { | ||
var opts = options || {}; | ||
if (!(this instanceof Algorithm)) { | ||
return new Algorithm(opts); | ||
} | ||
debug('init', opts); | ||
this.arms = _.isUndefined(opts.arms) ? 2 : parseInt(opts.arms, 10); | ||
this.gamma = _.isUndefined(opts.gamma) ? 1e-7 : parseFloat(opts.gamma); | ||
this.tau = _.isUndefined(opts.tau) ? null : parseFloat(opts.tau); | ||
if (this.arms < 1) { | ||
throw new TypeError('invalid arms: cannot be less than 1'); | ||
} else if (this.gamma < 0) { | ||
throw new TypeError('invalid gamma: cannot be less than 0'); | ||
} else if (!_.isNull(this.tau) && this.tau < 0) { | ||
throw new TypeError('invalid tau: cannot be less than 0'); | ||
} | ||
this.counts = Array.apply(null, Array(this.arms)).map(Number.prototype.valueOf, 0); | ||
this.values = Array.apply(null, Array(this.arms)).map(Number.prototype.valueOf, 0); | ||
} | ||
Algorithm.prototype.load = async(require('./lib/load')); | ||
Algorithm.prototype.reward = async(require('./lib/reward')); | ||
Algorithm.prototype.select = async(require('./lib/select')); | ||
Algorithm.prototype.serialize = async(require('./lib/serialize')); | ||
module.exports = Algorithm; | ||
module.exports = require('./lib/Algorithm'); |
{ | ||
"name": "softmax", | ||
"description": "A softmax multi-armed bandit algorithm", | ||
"version": "0.5.0", | ||
"version": "2.0.0", | ||
"license": "ISC", | ||
@@ -11,3 +11,3 @@ "main": "index.js", | ||
"promises-aplus", | ||
"banditlab" | ||
"banditlab/2.0" | ||
], | ||
@@ -28,21 +28,23 @@ "author": { | ||
"type": "git", | ||
"url": "git://github.com/kurttheviking/softmax.git" | ||
"url": "git://github.com/kurttheviking/softmax-js.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/kurttheviking/softmax/issues" | ||
"url": "https://github.com/kurttheviking/softmax-js/issues" | ||
}, | ||
"homepage": "https://github.com/kurttheviking/softmax#readme", | ||
"homepage": "https://github.com/kurttheviking/softmax-js#readme", | ||
"dependencies": { | ||
"bluebird": "3.3.0", | ||
"bluebird": "3.3.5", | ||
"debug": "2.2.0", | ||
"lodash": "4.3.0" | ||
"lodash": "4.12.0" | ||
}, | ||
"devDependencies": { | ||
"chai": "3.5.0", | ||
"eslint": "1.10.3", | ||
"eslint-config-airbnb": "5.0.0", | ||
"mocha-eslint": "1.0.0", | ||
"istanbul": "0.4.2", | ||
"eslint": "2.9.0", | ||
"eslint-config-airbnb": "9.0.1", | ||
"eslint-plugin-import": "1.8.0", | ||
"mocha-eslint": "2.0.2", | ||
"istanbul": "0.4.3", | ||
"mocha": "2.4.5", | ||
"sinon": "1.17.3" | ||
"mockery": "1.7.0", | ||
"sinon": "1.17.4" | ||
}, | ||
@@ -52,3 +54,4 @@ "scripts": { | ||
"test": "node node_modules/mocha/bin/mocha ./test --recursive" | ||
} | ||
}, | ||
"tonicExampleFilename": "./opt/tonic.js" | ||
} |
109
README.md
softmax | ||
======= | ||
[](https://travis-ci.org/kurttheviking/softmax) | ||
[](https://travis-ci.org/kurttheviking/softmax-js) | ||
**A softmax algorithm for multi-armed bandit problems** | ||
**A softmax multi-armed bandit algorithm** | ||
This implementation is based on [<em>Bandit Algorithms for Website Optimization</em>](http://shop.oreilly.com/product/0636920027393.do) and related empirical research in ["Algorithms for the multi-armed bandit problem"](https://d2w9gswcdc2jtf.cloudfront.net/research/Algorithms+for+the+multi-armed+bandit+problem.pdf). | ||
This implementation is based on [<em>Bandit Algorithms for Website Optimization</em>](http://shop.oreilly.com/product/0636920027393.do) and related empirical research in ["Algorithms for the multi-armed bandit problem"](http://www.cs.mcgill.ca/~vkules/bandits.pdf). | ||
@@ -13,3 +13,3 @@ | ||
This module conforms to the [BanditLab/1.0 specification](https://github.com/banditlab/spec-js/blob/master/README.md). | ||
This module conforms to the [BanditLab/2.0 specification](https://github.com/banditlab/spec-js/releases). | ||
@@ -27,3 +27,3 @@ | ||
1. Create an optimizer with 3 arms and default [annealing](https://en.wikipedia.org/wiki/Simulated_annealing): | ||
1. Create an optimizer with `3` arms and default [annealing](https://en.wikipedia.org/wiki/Simulated_annealing): | ||
@@ -42,3 +42,3 @@ ```js | ||
algorithm.select().then(function (arm) { | ||
... | ||
// do something based on the chosen arm | ||
}); | ||
@@ -50,5 +50,3 @@ ``` | ||
```js | ||
algorithm.reward(armId, value).then(function (n) { | ||
... | ||
}); | ||
algorithm.reward(arm, value); | ||
``` | ||
@@ -59,3 +57,3 @@ | ||
#### `Algorithm([config])` | ||
#### `Algorithm(config)` | ||
@@ -66,12 +64,14 @@ Create a new optimization algorithm. | ||
- `config` (Object, Optional): algorithm instance parameters | ||
- `config` (Object): algorithm instance parameters | ||
The `config` object supports three parameters: | ||
- `arms`: (Number:Integer, Optional), default=2, the number of arms over which the optimization will operate | ||
- `gamma`: the annealing (cooling) factor – defaults to 1e-7 (0.0000001) | ||
- `tau`: the temperature (scaling) factor – 0 to Infinity, higher leads to more exploration | ||
- `arms`: (Number:Integer, Optional), defaults to `2`, the number of arms over which the optimization will operate | ||
- `gamma`: annealing factor, defaults to `1e-7` (`0.0000001`) | ||
- `tau`: fixed temperature, `0` to `Infinity`, higher leads to more exploration | ||
By default, `gamma` of 1e-7 will cause the algorithm to explore less as more information is received. In this case, the underlying "temperature" is changing. If this behavior is not desired, set `tau` to instead employ an algorithm with a fixed temperature. If `tau` is provided then `gamma` is ignored. | ||
By default, `gamma` is set to `1e-7` which causes the algorithm to reduce exploration as more information is received. That is, the "temperature cools" slightly with each iteration. In contrast, `tau` represents a "constant temperature" wherein the influence of random search is fixed across all iterations. If `tau` is provided then `gamma` is ignored. | ||
Alternatively, the `state` object returned from [`Algorithm#serialize`](https://github.com/kurttheviking/softmax-js-js#algorithmserialize) can be passed as `config`. | ||
**Returns** | ||
@@ -84,6 +84,7 @@ | ||
```js | ||
> var Algorithm = require('softmax'); | ||
> var algorithm = new Algorithm(); | ||
> assert.equal(algorithm.arms, 3); | ||
> assert.equal(algorithm.gamma, 0.0000001); | ||
var Algorithm = require('softmax'); | ||
var algorithm = new Algorithm(); | ||
assert.equal(algorithm.arms, 3); | ||
assert.equal(algorithm.gamma, 0.0000001); | ||
``` | ||
@@ -94,6 +95,7 @@ | ||
```js | ||
> var Algorithm = require('softmax'); | ||
> var algorithm = new Algorithm({arms: 4, tau: 0.000005}); | ||
> assert.equal(algorithm.arms, 4); | ||
> assert.equal(algorithm.tau, 0.000005); | ||
var Algorithm = require('softmax'); | ||
var algorithm = new Algorithm({arms: 4, tau: 0.000005}); | ||
assert.equal(algorithm.arms, 4); | ||
assert.equal(algorithm.tau, 0.000005); | ||
``` | ||
@@ -116,6 +118,9 @@ | ||
```js | ||
> var Algorithm = require('softmax'); | ||
> var algorithm = new Algorithm(); | ||
> algorithm.select().then(function (arm) { console.log(arm); }); | ||
var Algorithm = require('softmax'); | ||
var algorithm = new Algorithm(); | ||
algorithm.select().then(function (arm) { console.log(arm); }); | ||
``` | ||
```js | ||
0 | ||
@@ -135,3 +140,3 @@ ``` | ||
A promise that resolves to a Number representing the count of observed rounds. | ||
A promise that resolves to an updated instance of the algorithm. | ||
@@ -141,9 +146,17 @@ **Example** | ||
```js | ||
> var Algorithm = require('softmax'); | ||
> var algorithm = new Algorithm(); | ||
> algorithm.reward(0, 1).then(function (n) { console.log(n); }); | ||
var Algorithm = require('softmax'); | ||
var algorithm = new Algorithm(); | ||
1 | ||
algorithm.reward(0, 1).then(function (algorithmUpdated) { console.log(algorithmUpdated) }); | ||
``` | ||
```js | ||
<Algorithm>{ | ||
arms: 2, | ||
gamma: 0.0000001, | ||
counts: [1, 0], | ||
values: [1, 0] | ||
} | ||
``` | ||
#### `Algorithm#serialize()` | ||
@@ -164,6 +177,9 @@ | ||
```js | ||
> var Algorithm = require('softmax'); | ||
> var algorithm = new Algorithm(); | ||
> algorithm.serialize().then(function (state) { console.log(state); }); | ||
var Algorithm = require('softmax'); | ||
var algorithm = new Algorithm(); | ||
algorithm.serialize().then(function (state) { console.log(state); }); | ||
``` | ||
```js | ||
{ | ||
@@ -177,26 +193,3 @@ arms: 2, | ||
#### `Algorithm#load(state)` | ||
Restore an instance of an algorithm to a previously serialized state. This method overrides any options parameters passed at instantiation. | ||
**Arguments** | ||
- `state` (Object): a serialized algorithm state (provided from `algorithm.serialize()`) | ||
**Returns** | ||
A promise that resolves to a Number representing the count of observed rounds. | ||
**Example** | ||
```js | ||
> var state = {arms: 2, gamma: 0.0000001, counts: [1, 2], values: [1, 0.5]}; | ||
> var Algorithm = require('softmax'); | ||
> var algorithm = new Algorithm(); | ||
> algorithm.load(state).then(function (n) { console.log(n); }); | ||
3 | ||
``` | ||
## Tests | ||
@@ -221,3 +214,3 @@ | ||
PRs are welcome! For bugs, please include a failing test which passes when your PR is applied. [Travis CI](https://travis-ci.org/kurttheviking/softmax) provides on-demand testing for commits and pull requests. | ||
PRs are welcome! For bugs, please include a failing test which passes when your PR is applied. [Travis CI](https://travis-ci.org/kurttheviking/softmax-js) provides on-demand testing for commits and pull requests. | ||
@@ -224,0 +217,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
0
-100%11801
-49.18%9
28.57%10
-44.44%114
-74.32%209
-3.24%1
Infinity%+ Added
+ Added
- Removed
- Removed
Updated
Updated