Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/node_modules
/.project
126 changes: 126 additions & 0 deletions associative.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/**
* Utilities for associative arrays (= hashes = Javascript objects).
* @author Erel Segal-Halevi
*/

var api = {};

/**
* add one associative array to another.
* @param target [input and output]
* @param source [input]: will be added to target.
*/
api.add = function(target, source) {
for (var feature in source) {
if (!(feature in target))
target[feature]=0;
target[feature] += source[feature];
}
}

/**
* multiply one associative array by another.
* @param target [input and output]
* @param source [input]: target will be multiplied by it.
*/
api.multiply = function(target, source) {
for (var feature in source) {
if (!(feature in target))
target[feature]=1;
target[feature] *= source[feature];
}
}

/**
* multiply an associative array by a scalar.
* @param target [input and output]
* @param source [input]: target will be multiplied by it.
*/
api.multiply_scalar = function(target, source) {
for (var feature in target) {
target[feature] *= source;
}
}

/**
* calculate the scalar product of the given two arrays.
* @param features [input]
* @param weights [input]
* @note Usually, there are much less features than weights.
*/
api.inner_product = function(features, weights) {
var result = 0;
for (var feature in features) {
if (feature in weights) {
result += features[feature] * weights[feature]
} else {
/* the sample contains a feature that was never seen in training - ignore it for now */
}
}
return result;
}

api.sum_of_values = function(weights) {
var result = 0;
for (var feature in weights)
result += weights[feature];
return result;
}

api.sum_of_absolute_values = function(weights) {
var result = 0;
for (var feature in weights)
result += Math.abs(weights[feature]);
return result;
}

api.sum_of_square_values = function(weights) {
var result = 0;
for (var feature in weights)
result += Math.pow(weights[feature],2);
return result;
}

/**
* Normalize the given associative array, such that the sum of values is 1.
* Unless, of course, the current sum is 0, in which case, nothing is done.
*/
api.normalize_sum_of_values_to_1 = function(features) {
var sum = api.sum_of_absolute_values(features);
if (sum!=0)
api.multiply_scalar(features, 1/sum);
}

/**
* Normalize the given associative array, such that the sum of squares of the values is 1.
* Unless, of course, the current sum is 0, in which case, nothing is done.
*/
api.normalize_sum_of_squares_to_1 = function(features) {
var sum = api.sum_of_square_values(features);
if (sum!=0)
api.multiply_scalar(features, 1/Math.sqrt(sum));
}


/**
* @param array [input]
* @return a string of the given associative array, sorted by keys.
*/
api.stringify_sorted = function(weights, separator) {
var result = "{" + separator;
var keys = Object.keys(weights);
keys.sort();
var last = keys.length-1;
for (i = 0; i <= last; i++) {
var key = keys[i];
var weight = weights[key];
result += '"'+key+'": '+weight;
if (i<last) result+=",";
result += separator;
}
result += "}";
return result;
}

module.exports = api;

1 change: 1 addition & 0 deletions demos/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/rte3model
36 changes: 36 additions & 0 deletions demos/and.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* A perceptron that calculates the boolean "and" function
*/

var perceptron = require('../perceptron')

var and = perceptron()

and.train([1, 1], 1)
and.train([0, 1], 0)
and.train([1, 0], 0)
and.train([0, 0], 0)

// practice makes perfect (we hope...)
while(!and.retrain()) {}

console.log("2 FEATURES: ");
console.log(and.perceive([1, 1])) // 1
console.log(and.perceive([0, 1])) // 0
console.log(and.perceive([1, 0])) // 0
console.log(and.perceive([0, 0])) // 0
console.log(and.perceive([2, 0])) // ?
console.log(and.perceive([0, 2])) // ?

console.log("3 FEATURES: ");
console.log(and.perceive([0, 0, 0])) // 0
console.log(and.perceive([0, 0, 1])) // 0
console.log(and.perceive([0, 1, 0])) // 0
console.log(and.perceive([1, 0, 0])) // 0
console.log(and.perceive([1, 1, 0])) // 0
console.log(and.perceive([1, 0, 1])) // 0
console.log(and.perceive([0, 1, 1])) // 0
console.log(and.perceive([1, 1, 1])) // 0

console.dir(and);

802 changes: 802 additions & 0 deletions demos/rte3devproofs.json

Large diffs are not rendered by default.

802 changes: 802 additions & 0 deletions demos/rte3testproofs.json

Large diffs are not rendered by default.

62 changes: 62 additions & 0 deletions demos/rtedemo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**
* A perceptron for recognizing textual entailment, based on BIUTEE's proofs.
*/

var perceptron = require('../perceptron_associative')
, associative = require('../associative')
, fs = require('fs');

var opts = {
feature_extractor: function(pair, features) {
if (pair.task)
features[pair.task]=1;
if (pair.hypothesis_length)
features.InverseHypothesisLength = 1 / pair.hypothesis_length;
for (var iStep=0; iStep<pair.proof.length; ++iStep) {
var step = pair.proof[iStep];
associative.add(features, step);
}
},
learningrate: 1,
do_averaging: false,
do_normalization: true,
debug: 0
};
var rte = perceptron(opts);

var devpairs = JSON.parse(fs.readFileSync('rte3devproofs.json', 'utf8'));
var testpairs = JSON.parse(fs.readFileSync('rte3testproofs.json', 'utf8'));

for (var iPair=0; iPair<devpairs.length; ++iPair)
rte.train(devpairs[iPair], devpairs[iPair].decision);

// test save and load:
rte.save("rte3model");
var rte2 = perceptron(opts);
rte2.load("rte3model");
//rte = rte2;

console.log("\n\nafter first train: ");
console.log("test on train data: ");
console.dir(rte.test_on_train());

console.log("test on test data: ");
rte.test_start();
for (var iPair=0; iPair<testpairs.length; ++iPair)
rte.test(testpairs[iPair], testpairs[iPair].decision);
console.dir(rte.test_results());
for (var i=1; i<=10; ++i) {
rte.retrain();
if (i==1 || i==10 || i==20) {
console.log("\n\nafter retrain "+i+":");
console.log("test on train data: ");
console.dir(rte.test_on_train());
console.log("test on test data: ");
rte.test_start();
for (var iPair=0; iPair<testpairs.length; ++iPair)
rte.test(testpairs[iPair], testpairs[iPair].decision);
console.dir(rte.test_results());
}
}


7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@
"directories": {
"test": "tests"
},
"dependencies": {},
"dependencies": {
"mkpath": "~0.1.0",
"should": "~1.2.2"
},
"devDependencies": {
"specify": "~1.1.2"
"specify": "*"
},
"keywords": [
"machine learning",
Expand Down
Loading