JSFiddle - React, Tailwind, and code Playground
HTML
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
<div>ρ:
<input id="rho" type="text" value="1.2" size="5">
<button id="step">step</button>
<button id="reset">reset</button>
</div>
<div style="background-color: #eee; font-family: monospace">
<span id="terminal">
Ready
</span>
</div>
CSS
body {
background-color: white;
}
.axis path, .axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 11px;
}
.draggable {
cursor: pointer;
}
JavaScript
'use strict';
// 学習パターンを識別関数に適用して誤識別した場合、パーセプトロンの学習規則に基づき重みを調整する
// ws : 拡張重みベクトル
// xs : 拡張特徴ベクトル
// c : クラス (0 or 1)
// rho: 学習係数ρ
function learn(ws, xs, c, rho) {
var g = dot(ws, xs); // 識別関数gを計算
if (c == 0 && g <= 0) { // クラスω1を誤識別
madd(ws, rho, xs); // w' = w + ρx
return true;
} else if (c != 0 && g >= 0) { // クラスω2を誤識別
madd(ws, -rho, xs); // w' = w - ρx
return true;
}
return false;
}
// 内積
function dot(a, b) {
var l = 0;
for (var i = 0; i < a.length; ++i)
l += a[i] * b[i];
return l;
}
// 係数付き加算
function madd(a, p, b) {
for (var i = 0; i < a.length; ++i)
a[i] += p * b[i];
}
// 学習パターン
var dataset = [
[0, 1.2],
[0, 0.2],
[0, -0.2],
[1, -0.5],
[1, -1.0],
[1, -1.5]
];
// 拡張重みベクトル
var ws = [-7, 2]; //[11, 5];
// D3.js関連
var width = 600,
height = 600,
padding = 30;
// 重みベクトルの軌跡
var plots = [];
// 原点からの距離
function dist(x, y) {
return Math.sqrt(x * x + y * y);
}
// 描画
function draw() {
d3.select('svg').remove();
var svg = d3.select('body').append('svg')
.attr('width', width)
.attr('height', height);
var xScale = d3.scale.linear()
.domain([-12, 12])
.range([padding, width - padding]);
var yScale = d3.scale.linear()
.domain([-12, 12])
.range([height - padding, padding]);
// パターンの座標を計算
function patternX(d1, r) {
return xScale(r / dist(d1, 1));
}
function patternY(d1, r) {
return yScale(-r / dist(d1, 1) * d1);
}
var lines, nodes;
// パターンをドラッグ時のイベント
var dragPattern = (function() {
var dragX, dragY;
return d3.behavior.drag()
.on('dragstart', function(d, i) {
d3.event.sourceEvent.stopPropagation();
dragX = xScale(13 / dist(d[1], 1));
dragY = yScale(-13 / dist(d[1], 1) * d[1]);
})
.on('drag', function(d, i) {
dragX += d3.event.dx;
dragY += d3.event.dy;
var x = xScale.invert(dragX);
var y = yScale.invert(dragY);
d[1] = -y / x;
...