Skip to content

Commit

Permalink
Add JS template to support exported model data
Browse files Browse the repository at this point in the history
  • Loading branch information
Darius Morawiec committed Nov 25, 2017
1 parent 1b81d3f commit f915b70
Show file tree
Hide file tree
Showing 2 changed files with 194 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
if (typeof XMLHttpRequest === 'undefined') {{
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
}}

var {class_name} = function(jsonFile) {{
this.data = undefined;

var Neighbor = function(y, dist) {{
this.y = y;
this.dist = dist;
}};

var promise = new Promise(function(resolve, reject) {{
var httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = function() {{
if (httpRequest.readyState === 4) {{
if (httpRequest.status === 200) {{
resolve(JSON.parse(httpRequest.responseText));
}} else {{
reject(new Error(httpRequest.statusText));
}}
}}
}};
httpRequest.open('GET', jsonFile, true);
httpRequest.send();
}});

var compute = function(temp, cand, q) {{
var dist = 0.,
diff;
for (var i = 0, l = temp.length; i < l; i++) {{
diff = Math.abs(temp[i] - cand[i]);
if (q==1) {{
dist += diff;
}} else if (q==2) {{
dist += diff*diff;
}} else if (q==Number.POSITIVE_INFINITY) {{
if (diff > dist) {{
dist = diff;
}}
}} else {{
dist += Math.pow(diff, q);
}}
}}
if (q==1 || q==Number.POSITIVE_INFINITY) {{
return dist;
}} else if (q==2) {{
return Math.sqrt(dist);
}} else {{
return Math.pow(dist, 1. / q);
}}
}};

this.{method_name} = function(features) {{
return new Promise(function(resolve, reject) {{
promise.then(function(data) {{
if (typeof this.data === 'undefined') {{
this.data = data;
this.nTemplates = this.data.X.length;
}}
var classIdx = 0, i, dist;
if (this.data.nNeighbors == 1) {{
var minDist = Number.POSITIVE_INFINITY;
for (i = 0; i < this.data.nTemplates; i++) {{
dist = compute(this.data.X[i], features, this.data.power);
if (dist <= minDist) {{
minDist = dist;
classIdx = this.data.y[i];
}}
}}
}} else {{
var classes = new Array(this.data.nClasses).fill(0);
var dists = [];
for (i = 0; i < this.nTemplates; i++) {{
dist = compute(this.data.X[i], features, this.data.power);
dists.push(new Neighbor(this.data.y[i], dist));
}}
dists.sort(function compare(n1, n2) {{
return (n1.dist < n2.dist) ? -1 : 1;
}});
for (i = 0; i < this.data.kNeighbors; i++) {{
classes[dists[i].y]++;
}}
for (i = 0; i < this.data.nClasses; i++) {{
classIdx = classes[i] > classes[classIdx] ? i : classIdx;
}}
}}
resolve(classIdx);
}}, function(error) {{
reject(error);
}});
}});
}};

}};

if (typeof process !== 'undefined' && typeof process.argv !== 'undefined') {{
if (process.argv[2].trim().endsWith('.json')) {{

// Parameters:
var json = process.argv[2];

// Estimator:
var clf = new {class_name}(json);

// Features:
var features = process.argv.slice(3);

// Prediction:
clf.{method_name}(features).then(function(prediction) {{
console.log(prediction);
}});

}}
}}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from unittest import TestCase

import numpy as np
from sklearn.neighbors import KNeighborsClassifier

from tests.estimator.classifier.Classifier import Classifier
Expand All @@ -16,3 +17,81 @@ def setUp(self):

def tearDown(self):
super(KNeighborsClassifierJSTest, self).tearDown()

def test_random_features_w_binary_data_export(self):
self.load_binary_data()
self._port_estimator(export_data=True)
amin = np.amin(self.X, axis=0)
amax = np.amax(self.X, axis=0)
preds, ground_truth = [], []
for _ in range(self.N_RANDOM_FEATURE_SETS):
x = np.random.uniform(amin, amax, self.n_features)
preds.append(self.pred_in_custom(x, export_data=True))
ground_truth.append(self.pred_in_py(x))
self._clear_estimator()
# noinspection PyUnresolvedReferences
self.assertListEqual(preds, ground_truth)

def test_random_features_w_iris_data_export(self):
self.load_iris_data()
self._port_estimator(export_data=True)
amin = np.amin(self.X, axis=0)
amax = np.amax(self.X, axis=0)
preds, ground_truth = [], []
for _ in range(self.N_RANDOM_FEATURE_SETS):
x = np.random.uniform(amin, amax, self.n_features)
preds.append(self.pred_in_custom(x, export_data=True))
ground_truth.append(self.pred_in_py(x))
self._clear_estimator()
# noinspection PyUnresolvedReferences
self.assertListEqual(preds, ground_truth)

def test_random_features_w_digits_data_export(self):
self.load_digits_data()
self._port_estimator(export_data=True)
amin = np.amin(self.X, axis=0)
amax = np.amax(self.X, axis=0)
preds, ground_truth = [], []
for _ in range(self.N_RANDOM_FEATURE_SETS):
x = np.random.uniform(amin, amax, self.n_features)
preds.append(self.pred_in_custom(x, export_data=True))
ground_truth.append(self.pred_in_py(x))
self._clear_estimator()
# noinspection PyUnresolvedReferences
self.assertListEqual(preds, ground_truth)

def test_existing_features_w_binary_data_export(self):
self.load_binary_data()
self._port_estimator(export_data=True)
preds, ground_truth = [], []
n = min(self.N_EXISTING_FEATURE_SETS, len(self.X))
for x in self.X[:n]:
preds.append(self.pred_in_custom(x, export_data=True))
ground_truth.append(self.pred_in_py(x))
self._clear_estimator()
# noinspection PyUnresolvedReferences
self.assertListEqual(preds, ground_truth)

def test_existing_features_w_iris_data_export(self):
self.load_iris_data()
self._port_estimator(export_data=True)
preds, ground_truth = [], []
n = min(self.N_EXISTING_FEATURE_SETS, len(self.X))
for x in self.X[:n]:
preds.append(self.pred_in_custom(x, export_data=True))
ground_truth.append(self.pred_in_py(x))
self._clear_estimator()
# noinspection PyUnresolvedReferences
self.assertListEqual(preds, ground_truth)

def test_existing_features_w_digits_data_export(self):
self.load_digits_data()
self._port_estimator(export_data=True)
preds, ground_truth = [], []
n = min(self.N_EXISTING_FEATURE_SETS, len(self.X))
for x in self.X[:n]:
preds.append(self.pred_in_custom(x, export_data=True))
ground_truth.append(self.pred_in_py(x))
self._clear_estimator()
# noinspection PyUnresolvedReferences
self.assertListEqual(preds, ground_truth)

0 comments on commit f915b70

Please sign in to comment.