Skip to content

Commit a6ef238

Browse files
committed
Adds SVM hyperparams and help.
Fixes #4
1 parent afd84cd commit a6ef238

File tree

3 files changed

+198
-14
lines changed

3 files changed

+198
-14
lines changed

app.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,15 +107,18 @@ def fit():
107107
if model is None or len(dataset) == 0:
108108
return "invalid fit request: please specify model and data", 400
109109

110-
try:
111-
params = {
112-
key: json.loads(val) for key, val in params.items()
113-
}
114-
except json.decoder.JSONDecodeError:
115-
return "invalid fit request: cannot parse json hyperparameters", 400
110+
# Parse the JSON hyperparameters or leave as string for type detection
111+
for key in params.keys():
112+
try:
113+
params[key] = json.loads(params[key])
114+
except json.decoder.JSONDecodeError:
115+
continue
116116

117117
# Set the hyperparameters on the model
118-
model.set_params(**params)
118+
try:
119+
model.set_params(**params)
120+
except ValueError as e:
121+
return str(e), 400
119122

120123
# Construct the dataset
121124
X, y = [], []

static/js/dataspace.js

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class Dataspace {
4848
.data(self.dataset)
4949
.enter()
5050
.append("circle")
51-
.attr('cx', function (d) { console.log(d); return self.xScale(d.x); })
51+
.attr('cx', function (d) { return self.xScale(d.x); })
5252
.attr('cy', function (d) { return self.yScale(d.y); })
5353
.attr('fill', function (d) { return self.color(d.c); })
5454
.attr('r', radius);
@@ -191,11 +191,11 @@ $(document).ready(function() {
191191
form.find('input[type="checkbox"]').each(function() {
192192
var cb = $(this);
193193
if (!cb.prop("disabled")) {
194-
data[cb.attr("name")] = cb.prop("checked").toString();
194+
data[cb.attr("name")] = JSON.stringify(cb.prop("checked"));
195195
}
196196
});
197197

198-
console.log(data);
198+
console.log("fitting model with params: ", data);
199199
app.fit(data);
200200
return false;
201201
});
@@ -236,4 +236,38 @@ $(document).ready(function() {
236236

237237
});
238238

239+
// Enable the correct hyperparameters based on the selected svm kernel
240+
$('#svm input[name="kernel"]').change(function (e) {
241+
var degree = $('#svm input[name="degree"]');
242+
var gamma = $('#svm input[name="gamma"]');
243+
var coef0 = $('#svm input[name="coef0"]');
244+
245+
// Enable/Disable based on the selected kernel
246+
switch ($(this).val()) {
247+
case "linear":
248+
$.each([degree, gamma, coef0], function (_, elem) {
249+
elem.prop("disabled", true);
250+
});
251+
break;
252+
case "poly":
253+
$.each([degree, gamma, coef0], function (_, elem) {
254+
elem.prop("disabled", false);
255+
});
256+
break;
257+
case "rbf":
258+
degree.prop("disabled", true);
259+
gamma.prop("disabled", false);
260+
coef0.prop("disabled", true);
261+
break;
262+
case "sigmoid":
263+
degree.prop("disabled", true);
264+
gamma.prop("disabled", false);
265+
coef0.prop("disabled", false);
266+
break;
267+
default:
268+
console.log("unknown SVM kernel selected, cannot enable form!");
269+
}
270+
271+
});
272+
239273
});

templates/index.html

Lines changed: 151 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,102 @@
198198
</form>
199199
</div>
200200
<div class="tab-pane fade" id="svm" role="tabpanel">
201-
<p>Support Vector Machine</p>
202201
<form class="form">
203202
<input type="hidden" name="model" value="svm" />
203+
<div class="row">
204+
<div class="col-md-2">
205+
<div class="form-check">
206+
<input class="form-check-input" type="radio" name="kernel" id="svmkernel1" value="linear" checked>
207+
<label class="form-check-label" for="svmkernel1">
208+
Linear
209+
</label>
210+
</div>
211+
<div class="form-check">
212+
<input class="form-check-input" type="radio" name="kernel" id="svmkernel2" value="poly">
213+
<label class="form-check-label" for="svmkernel2">
214+
Polynomial
215+
</label>
216+
</div>
217+
<div class="form-check">
218+
<input class="form-check-input" type="radio" name="kernel" id="svmkernel3" value="rbf">
219+
<label class="form-check-label" for="svmkernel3">
220+
RBF
221+
</label>
222+
</div>
223+
<div class="form-check">
224+
<input class="form-check-input" type="radio" name="kernel" id="svmkernel4" value="sigmoid">
225+
<label class="form-check-label" for="svmkernel4">
226+
Sigmoid
227+
</label>
228+
</div>
229+
</div>
230+
<div class="col-md-3">
231+
<div class="form-group form-row mb-1">
232+
<label for="C" class="col-form-label col-md-4">C</label>
233+
<div class="col-md-8">
234+
<input class="form-control" type="text" name="C" id="C" value="1.0" />
235+
</div>
236+
</div>
237+
<div class="form-group form-row mb-1">
238+
<label for="degree" class="col-form-label col-md-4">Degree</label>
239+
<div class="col-md-8">
240+
<input class="form-control" type="number" name="degree" id="degree" value="3" min="1" max="42" step="1" disabled />
241+
</div>
242+
</div>
243+
<div class="form-group form-row mb-1">
244+
<label for="gamma" class="col-form-label col-md-4">Gamma</label>
245+
<div class="col-md-8">
246+
<input class="form-control" type="text" name="gamma" id="gamma" value="scale" disabled />
247+
</div>
248+
</div>
249+
</div>
250+
<div class="col-md-3">
251+
<div class="form-group form-row mb-1">
252+
<label for="coef0" class="col-form-label col-md-4">Coef0</label>
253+
<div class="col-md-8">
254+
<input class="form-control" type="text" name="coef0" id="coef0" value="0.0" disabled />
255+
</div>
256+
</div>
257+
<div class="form-group form-row mb-1">
258+
<label for="tol" class="col-form-label col-md-4">Tol</label>
259+
<div class="col-md-8">
260+
<input class="form-control" type="text" name="tol" id="tol" value="0.001" />
261+
</div>
262+
</div>
263+
<div class="form-group form-row mb-1">
264+
<label for="max_iter" class="col-form-label col-md-4">Max Iter</label>
265+
<div class="col-md-8">
266+
<input class="form-control" type="text" name="max_iter" id="max_iter" value="-1" />
267+
</div>
268+
</div>
269+
</div>
270+
<div class="col-md-4">
271+
<div class="form-group form-row mb-1">
272+
<div class="col-md-4"></div>
273+
<div class="col-md-8">
274+
<div class="form-check">
275+
<input class="form-check-input" type="checkbox" name="shrinking" id="shrinking" checked>
276+
<label class="form-check-label" for="shrinking">Shrinking</label>
277+
</div>
278+
</div>
279+
</div>
280+
<div class="form-group form-row mb-1">
281+
<label for="class_weight" class="col-form-label col-md-4">Class Weight</label>
282+
<div class="col-md-8">
283+
<input class="form-control" type="text" name="class_weight" id="class_weight" value="null" />
284+
</div>
285+
</div>
286+
<div class="form-group form-row mb-1">
287+
<label for="decision_function_shape" class="col-form-label col-md-4">Decision Shape</label>
288+
<div class="col-md-8">
289+
<select class="custom-select my-1 mr-sm-2" name="decision_function_shape" id="decision_function_shape">
290+
<option value="ovr" selected>One v. Rest</option>
291+
<option value="ovo">One v. One</option>
292+
</select>
293+
</div>
294+
</div>
295+
</div>
296+
</div>
204297
</form>
205298
</div>
206299
<div class="tab-pane fade" id="logit" role="tabpanel">
@@ -326,7 +419,7 @@ <h6>Hyperparameters</h6>
326419

327420
<div class="modal fade" id="svmInfoModal" tabindex="-1" role="dialog" aria-labelledby="svmInfoModalLabel"
328421
aria-hidden="true">
329-
<div class="modal-dialog modal-dialog-centered" role="document">
422+
<div class="modal-dialog modal-dialog-centered modal-lg" role="document">
330423
<div class="modal-content">
331424
<div class="modal-header">
332425
<h5 class="modal-title" id="svmInfoModalLabel">Support Vector Machines</h5>
@@ -335,7 +428,55 @@ <h5 class="modal-title" id="svmInfoModalLabel">Support Vector Machines</h5>
335428
</button>
336429
</div>
337430
<div class="modal-body">
338-
<p>TODO</p>
431+
<p>
432+
<a href="https://scikit-learn.org/stable/modules/svm.html" target="_blank">
433+
Support vector machines</a> are supervised, discriminitive classifiers that learn
434+
an optimal hyperplane that can separate and categorize data. This hyperplane
435+
(e.g. an defined space one dimension less than the ambient space) maximizes
436+
the distance between groups of classes by selecting support vectors from each
437+
group (potentially with some slack) then finding the parallel hyperplane between
438+
those vectors that is halfway between the orthogonal. To optimize support vector
439+
discovery, the kernel functions are used to find mappings that increase the space
440+
between points, increasing separability between classes.
441+
</p>
442+
<h6>Hyperparameters</h6>
443+
<dl>
444+
<dt>C <code>float</code></dt>
445+
<dd>Penalty parameter C of the error term.</dd>
446+
<dt>kernel <code>string</code></dt>
447+
<dd>
448+
Specifies the kernel type to be used in the algorithm. It must be one of ‘linear’, ‘poly’,
449+
‘rbf’, ‘sigmoid’, ‘precomputed’ or a callable. If none is given, ‘rbf’ will be used. If a
450+
callable is given it is used to pre-compute the kernel matrix from data matrices; that
451+
matrix should be an array of shape <code>(n_samples, n_samples)</code>.
452+
</dd>
453+
<dt>degree <code>int</code></dt>
454+
<dd>Degree of the polynomial kernel function (‘poly’). Ignored by all other kernels.</dd>
455+
<dt>gamma <code>float</code></dt>
456+
<dd>Kernel coefficient for ‘rbf’, ‘poly’ and ‘sigmoid’.</dd>
457+
<dt>coef0 <code>float</code></dt>
458+
<dd>Independent term in kernel function. It is only significant in ‘poly’ and ‘sigmoid’.</dd>
459+
<dt>shrinking <code>boolean</code></dt>
460+
<dd>Whether to use the shrinking heuristic.</dd>
461+
<dt>tol <code>float</code></dt>
462+
<dd>Tolerance for stopping criterion.</dd>
463+
<dt>class_weight <code>{dict, 'balanced'}</code></dt>
464+
<dd>
465+
Set the parameter C of class i to class_weight[i]*C for SVC. If not given, all classes are
466+
supposed to have weight one. The “balanced” mode uses the values of y to automatically adjust
467+
weights inversely proportional to class frequencies in the input data as
468+
<code>n_samples / (n_classes * np.bincount(y))</code>
469+
</dd>
470+
<dt>max_iter <code>int</code></dt>
471+
<dd>Hard limit on iterations within solver, or -1 for no limit.</dd>
472+
<dt>decision_function_shape <code>{‘ovo’, ‘ovr’}</code></dt>
473+
<dd>
474+
Whether to return a one-vs-rest (‘ovr’) decision function of shape <code>(n_samples, n_classes)</code>
475+
as all other classifiers, or the original one-vs-one (‘ovo’) decision function of libsvm which has shape
476+
<code>(n_samples, n_classes * (n_classes - 1) / 2)</code>. However, one-vs-one (‘ovo’) is always used
477+
as multi-class strategy.
478+
</dd>
479+
</dl>
339480
</div>
340481
<div class="modal-footer">
341482
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
@@ -346,7 +487,7 @@ <h5 class="modal-title" id="svmInfoModalLabel">Support Vector Machines</h5>
346487

347488
<div class="modal fade" id="logitInfoModal" tabindex="-1" role="dialog" aria-labelledby="logitInfoModalLabel"
348489
aria-hidden="true">
349-
<div class="modal-dialog modal-dialog-centered" role="document">
490+
<div class="modal-dialog modal-dialog-centered modal-lg" role="document">
350491
<div class="modal-content">
351492
<div class="modal-header">
352493
<h5 class="modal-title" id="logitInfoModalLabel">Logistic Regression</h5>
@@ -356,6 +497,12 @@ <h5 class="modal-title" id="logitInfoModalLabel">Logistic Regression</h5>
356497
</div>
357498
<div class="modal-body">
358499
<p>TODO</p>
500+
501+
<h6>Hyperparameters</h6>
502+
<dl>
503+
<dt>param <code>type</code></dt>
504+
<dd>description</dd>
505+
</dl>
359506
</div>
360507
<div class="modal-footer">
361508
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>

0 commit comments

Comments
 (0)