Socket
Socket
Sign inDemoInstall

egreedy

Package Overview
Dependencies
4
Maintainers
1
Versions
23
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.3.0 to 0.4.0

2

package.json
{
"name": "egreedy",
"description": "An epsilon-greedy multi-armed bandit algorithm",
"version": "0.3.0",
"version": "0.4.0",
"license": "ISC",

@@ -6,0 +6,0 @@ "main": "index.js",

@@ -1,41 +0,50 @@

<a href="http://promisesaplus.com/">
<img src="http://promisesaplus.com/assets/logo-small.png" alt="Promises/A+ logo" title="Promises/A+ 1.0 compliant" align="right" />
</a>
egreedy
================
=======
[![Build Status](https://travis-ci.org/banditdb/egreedy.svg)](https://travis-ci.org/banditdb/egreedy)
[![Build Status](https://travis-ci.org/kurttheviking/egreedy.svg)](https://travis-ci.org/kurttheviking/egreedy)
A Promises/A+, [multi-armed bandit](http://en.wikipedia.org/wiki/Multi-armed_bandit) implemented with an epsilon-greedy algorithm.
**An epsilon-greedy multi-armed bandit algorithm**
This implemention 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"](https://d2w9gswcdc2jtf.cloudfront.net/research/Algorithms+for+the+multi-armed+bandit+problem.pdf).
## Specification
This module conforms to the [BanditLab/1.0 specification](https://github.com/banditlab/spec-js/blob/master/README.md).
## Quick start
1. Create a bandit with 3 arms and epsilon 0.25
First, install this module in your project:
```
```sh
npm install egreedy --save
```
Then, use the algorithm:
1. Create a bandit with 3 arms and epsilon 0.25:
```js
var Bandit = require('egreedy');
var bandit = new Bandit({
arms: 3,
epsilon: 0.25
arms: 3,
epsilon: 0.25
});
```
2. Select an arm (for exploration or exploitation, according to the algorithm)
2. Select an arm (for exploration or exploitation, according to the algorithm):
```
```js
bandit.select().then(function (arm) {
console.log('pulled arm=' + arm);
...
});
```
3. Report the reward earned from a chosen arm
3. Report the reward earned from a chosen arm:
```
bandit.reward(1, 1).then(function (rewards) {
console.log('arm rewards are currently=' + rewards);
```js
bandit.reward(armId, value).then(function (n) {
...
});

@@ -45,45 +54,41 @@ ```

## Configuration
## API
#### Load the bandit algorithm
#### `Bandit([config])`
Install from npm
Create a new optimization algorithm.
```
npm install egreedy --save
```
**Arguments**
Require in your project
- `config` (Object, Optional): algorithm instance parameters
```
var Bandit = require('egreedy');
```
The `config` object supports two parameters:
#### Instantiate a bandit
- `arms`: (Number:Integer, Optional), default=2, the number of arms over which the optimization will operate
- `epsilon`: (Number:Float, Optional), default=0.5, from 0 (never explore/always exploit) to 1 (always explore/never exploit)
This algorithm defaults to 2 arms and eplsilon 0.5
**Returns**
```
var bandit = new Bandit();
```
An instance of the egreedy optimization algorithm.
The constructor accepts an options object that supports two parameters:
**Example**
- `arms`: the number of arms over which the bandit can operate
- `epsilon`: the desired level of epsilon (from 0=never explore/always exploit to 1=always explore/never exploit)
```js
> var Bandit = require('egreedy');
> var bandit = new Bandit();
> assert.equal(bandit.arms, 3);
> assert.equal(bandit.epsilon, 0.5);
```
var bandit = new Bandit({
arms: 4,
epsilon: 0.75
});
```
Or, with a passed `config`:
## API
```js
> var Bandit = require('egreedy');
> var bandit = new Bandit({arms: 4, epsilon: 0.75});
> assert.equal(bandit.arms, 4);
> assert.equal(bandit.epsilon, 0.75);
```
All banditdb algorithms, including this implementation, provide the same Promises/A+ interface.
#### `Bandit#select()`
#### `bandit.select()`
Choose an arm to play, according to the specified bandit algorithm.

@@ -101,3 +106,3 @@

```
```js
> var Bandit = require('egreedy');

@@ -110,3 +115,3 @@ > var bandit = new Bandit();

#### `bandit.reward(arm, reward)`
#### `Bandit#reward(arm, reward)`

@@ -122,25 +127,17 @@ Inform the algorithm about the payoff from a given arm.

A promise that resolves to an Array of the current reward state of each arm; each position in the array corresponds to the associated arm index.
A promise that resolves to a Number representing the count of observed rounds.
**Example**
```
```js
> var Bandit = require('egreedy');
> var bandit = new Bandit();
> bandit.reward(0, 1).then(function (rewards) { console.log(rewards); });
> bandit.reward(0, 1).then(function (n) { console.log(n); });
[1, 0]
> bandit.reward(1, 1).then(function (rewards) { console.log(rewards); });
[1, 1]
> bandit.reward(1, 0).then(function (rewards) { console.log(rewards); });
[1, 0.5]
1
```
#### `bandit.serialize()`
#### `Bandit#serialize()`
Obtain a persistable JSON object representing the internal state of the algorithm.
Obtain a plain object representing the internal state of the algorithm.

@@ -157,3 +154,3 @@ **Arguments**

```
```js
> var Bandit = require('egreedy');

@@ -164,12 +161,12 @@ > var bandit = new Bandit();

{
arms: 2,
epsilon: 0.5,
counts: [ 0, 0 ],
values: [ 0, 0 ]
arms: 2,
epsilon: 0.5,
counts: [0, 0],
values: [0, 0]
}
```
#### `bandit.load(state)`
#### `Bandit#load(state)`
Restore an instance of a bandit to a perviously serialized algorithm state. This method overrides any options parameters passed at instantiation.
Restore an instance of a bandit to a previously serialized algorithm state. This method overrides any options parameters passed at instantiation.

@@ -182,39 +179,31 @@ **Arguments**

A promise that resolves to an Array of the current reward state of each arm; each position in the array corresponds to the associated arm index.
A promise that resolves to a Number representing the count of observed rounds.
**Example**
```
> var state = { arms: 2, epsilon: 0.5, counts: [ 1, 2 ], values: [ 1, 0.5 ] };
```js
> var state = {arms: 2, epsilon: 0.5, counts: [1, 2], values: [1, 0.5]};
> var Bandit = require('egreedy');
> var bandit = new Bandit();
> bandit.load(state).then(function (rewards) { console.log(rewards); });
> bandit.load(state).then(function (n) { console.log(n); });
[1, 0.5]
3
```
#### `bandit.n`
(Number) An instance property representing the total number of recorded reward samples, updated at each `bandit.reward()` call.
## Tests
**Example**
To run the unit test suite:
```
> var Bandit = require('egreedy');
> var bandit = new Bandit();
> bandit.reward(0, 1).then(function () { console.log(bandit.n); });
1
npm test
```
Or, to run the test suite and view test coverage:
## Tests
To run the full unit test suite
```sh
npm run coverage
```
npm test
```
Tests against stochastic methods (e.g. `bandit.select()`) are inherently tricky to test with deterministic assertions. The approach here is to iterate across a semi-random set of conditions to verify that each run produces valid output. So, strictly speaking, each call to `npm test` is executing a slightly different test suite. At some point, the test suite may be expanded to include a more robust test of the distribution's properties &ndash; though because of the number of runs required, would be triggered with an optional flag.
**Note:** tests against stochastic methods (e.g. `bandit.select()`) are inherently tricky to test with deterministic assertions. The approach here is to iterate across a semi-random set of conditions to verify that each run produces valid output. So, strictly speaking, each call to `npm test` is executing a slightly different test suite. At some point, the test suite may be expanded to include a more robust test of the distribution's properties &ndash; though because of the number of runs required, would be triggered with an optional flag.

@@ -224,3 +213,3 @@

PRs are welcome! For bugs, please include a failing test which passes when your PR is applied.
PRs are welcome! For bugs, please include a failing test which passes when your PR is applied. [Travis CI](https://travis-ci.org/kurttheviking/egreedy) provides on-demand testing for commits and pull requests.

@@ -230,4 +219,4 @@

Currently, this implementation relies on the [native Math.random()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random) which uses a seeded "random" number generator. In addition, the underlying calculations often encounter extended floating point numbers. Arm selection is therefore subject to JavaScript's floating point precision limitations. For general information about floating point issues see the [floating point guide](http://floating-point-gui.de/).
Currently, this implementation relies on the [native Math.random()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random) which uses a seeded "random" number generator. In addition, the underlying calculations often encounter extended floating point numbers. Arm selection is therefore subject to JavaScript's floating point precision limitations. For general information about floating point issues see the [floating point guide](http://floating-point-gui.de).
While these factors generally do not impede commercial application, I would consider the implementation suspect in any academic setting.
While these factors generally do not impede commercial application, I would consider the implementation suspect in an academic setting.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc