Created
May 22, 2017 18:30
-
-
Save hsw0/3fdb654938220411f1a22160b06d4a3e to your computer and use it in GitHub Desktop.
다범주 분류
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Classfier</title> | |
</head> | |
<body> | |
<style> | |
#testbed td { margin: 0; padding: 0; width: 15px; height: 15px; } | |
</style> | |
<fieldset id="control"> | |
<legend>학습</legend> | |
<label for="epoch">목표 epoch</label> | |
<input type="number" id="epoch" value="1000"> | |
<button type="button">Train!</button> | |
</fieldset> | |
<fieldset id="testbed"> | |
<legend>시험</legend> | |
<table> | |
<tbody> | |
</tbody> | |
</table> | |
</fieldset> | |
<div id="result"></div> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/3.13.1/math.min.js" integrity="sha256-lhbCjXBlEjR6NpaM7mqLaqXSZTTA6Wc5f9/mPKe4BQ4=" crossorigin="anonymous"></script> | |
<script> | |
/***************************************************************************** | |
* UI | |
/*****************************************************************************/ | |
var W = 5; | |
var H = 5; | |
(function(){ | |
document.querySelector('#control button').onclick = train; | |
var area = document.querySelector('#testbed table tbody'); | |
for(var i = 0 ; i < W ; i++) | |
{ | |
var tr = document.createElement('tr'); | |
for(var j = 0 ; j < H ; j++) | |
{ | |
var td = document.createElement('td'); | |
var cb = document.createElement('input'); | |
cb.type = "checkbox"; | |
cb.id = "x_" + i + "," + j; | |
cb.onclick = testClassifier; | |
td.append(cb); | |
tr.append(td); | |
} | |
area.append(tr); | |
} | |
}()); | |
function train() | |
{ | |
var el = document.getElementById('epoch'); | |
var targetEpoch = parseInt(el.value); | |
const STEP = 100; | |
function _train(epoch) | |
{ | |
var to = Math.min(targetEpoch, epoch + STEP); | |
for(; epoch < to ; epoch++) { | |
classfier.train(); | |
} | |
if (epoch <= targetEpoch) { | |
//console.info("Epoch:", epoch); | |
el.value = epoch; | |
setTimeout(_train.bind(null, epoch), 0); | |
} | |
} | |
setTimeout(_train.bind(null, 0), 0); | |
} | |
function testClassifier() | |
{ | |
function getInput() | |
{ | |
var X = new Array(W); | |
for(var i = 0 ; i < W ; i++) | |
{ | |
X[i] = new Array(H); | |
for(var j = 0 ; j < H ; j++) | |
{ | |
var cbid = "x_" + i + "," + j; | |
X[i][j] = document.getElementById(cbid).checked ? 1 : 0; | |
} | |
} | |
return X; | |
} | |
var X = getInput(); | |
var result = classfier.interference(X).reshape([1,5]).toArray()[0]; | |
//console.info("Input=", math.matrix(X).toString()); | |
var greatestIdx = result.indexOf(Math.max.apply(Math, result)); | |
var msg = | |
`Candidate: ${greatestIdx+1} ` | |
+ `Probability: ${(result[greatestIdx] * 100).toFixed(4)}%\n` | |
+ "Raw data: " + result; | |
document.getElementById('result').innerText = msg; | |
console.info(msg); | |
} | |
/*****************************************************************************/ | |
var X = (function() { | |
var x_1 = [ | |
[0,1,1,0,0], | |
[0,0,1,0,0], | |
[0,0,1,0,0], | |
[0,0,1,0,0], | |
[0,1,1,1,0], | |
]; | |
var x_2 = [ | |
[1,1,1,1,0], | |
[0,0,0,0,1], | |
[0,1,1,1,0], | |
[1,0,0,0,0], | |
[1,1,1,1,1], | |
]; | |
var x_3 = [ | |
[1,1,1,1,0], | |
[0,0,0,0,1], | |
[0,1,1,1,0], | |
[0,0,0,0,1], | |
[1,1,1,1,0], | |
]; | |
var x_4 = [ | |
[0,0,0,1,0], | |
[0,0,1,1,0], | |
[0,1,0,1,0], | |
[1,1,1,1,1], | |
[0,0,0,1,0], | |
]; | |
var x_5 = [ | |
[1,1,1,1,1], | |
[1,0,0,0,0], | |
[1,1,1,1,0], | |
[0,0,0,0,1], | |
[1,1,1,1,0], | |
]; | |
return [ x_1, x_2, x_3, x_4, x_5 ]; | |
}()); | |
class Classfier | |
{ | |
constructor(X) | |
{ | |
this.DIGITS = X.length; | |
this.X = X.map(x => math.matrix(x)); | |
this.D = [ | |
[1,0,0,0,0], | |
[0,1,0,0,0], | |
[0,0,1,0,0], | |
[0,0,0,1,0], | |
[0,0,0,0,1], | |
]; | |
// W1=2*rand(50,25)-1 | |
this.W1 = math.subtract(math.multiply(2, math.matrix(math.random([50,25]))), 1); | |
// W2=2*rand(5,50)-1 | |
this.W2 = math.subtract(math.multiply(2, math.matrix(math.random([this.DIGITS,50]))), 1); | |
} | |
train() | |
{ | |
const alpha = 0.9; | |
var W1 = this.W1.clone(); | |
var W2 = this.W2.clone(); | |
for(var k = 0 ; k < this.DIGITS ; k++) | |
{ | |
var x = math.reshape(this.X[k].clone(), [25, 1]); | |
var d = math.reshape(this.D[k], [this.DIGITS,1]); // D(k, :)'; | |
var v1 = math.multiply(W1, x); | |
var y1 = Sigmoid(v1); | |
var v = math.multiply(W2, y1); | |
var y = Softmax(v); | |
var e = math.subtract(d, y); | |
var delta = e; | |
var e1 = math.multiply(math.transpose(W2), delta); | |
var delta1 = math.dotMultiply(math.dotMultiply(y1, math.subtract(1, y1)), e1); | |
var dW1 = math.multiply(alpha, delta1, math.transpose(x)); | |
W1 = math.add(W1, dW1); | |
var dW2 = math.multiply(alpha, delta, math.transpose(y1)); | |
W2 = math.add(W2, dW2); | |
} | |
[this.W1, this.W2] = [W1, W2]; | |
} | |
interference(x) | |
{ | |
var x = math.reshape(math.matrix(x), [25, 1]); | |
var v1 = math.multiply(this.W1, x); | |
var y1 = Sigmoid(v1); | |
var v = math.multiply(this.W2, y1); | |
var y = Softmax(v); | |
return y; | |
} | |
} | |
var classfier = new Classfier(X); | |
function Softmax(x) | |
{ | |
/* | |
ex = exp(x); | |
y = ex / sum(ex); | |
*/ | |
var ex = math.exp(x); | |
var y = math.divide(ex, math.sum(ex)); | |
return y; | |
} | |
function Sigmoid(x) | |
{ | |
// p91 | |
// y= 1 ./ (1 + exp(-x)); | |
var y = math.dotDivide(1, math.add(1, math.exp(math.multiply(-1, x)))); | |
return y; | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
참고: 김성필 저, "딥러닝 첫걸음", 한빛미디어, 2016. p126-131