수치 미분 Numerical Differentitaion link
f(x) = ax^n f`(x) = anx^(n-1) = df/dx (x) // 구조적으로 미분하는 해석적 방법
하지만 컴터엔 무한소가 없기때문에 수치 미분을 함
df/dx (x) = ( f(x + dx) - f(x) ) / dx // forward differentiation
var x = 1;
var dx = 1e-5;
var f = x=> x * x;
var df = f(x + dx) - f(x);
var dfdx = df / dx;
함수가 어떻게 생겼는지 몰라도 이런식으로 수치 미분을 함. 하지만 함수가 복잡하거나 dx 가 충분히 작지 않으면 오차가 크다. 이렇게 구한 미분을 어디에 쓰지? -> 어떤 지점에서의 함수 값과 미분값을 알 때 x 가 조금 더 나아갔을 때의 값을 추측할 수 있음 -> interpolation / extrapolation
f(x + dxt) =~ f(x) + df/dx (x) * dxt
var dxt = 0.2;
var fdtx = f(x) + dfdx * dxt;
// =~ 1.4, f(x + dxt) = 1.44 얼추 비슷하다!
dxt를 찾기 위해서
f(x+dxt) = f target
dxt = ( f target - f(x) ) / dfdx (x)
var ft = 1.44;
var dxtp = (ft - f(x)) / dfdx;
// dxtp = 0.219
// 아까 0.2 가 목표값인데 얼추 비슷하다!
이미 도함수를 알 수 있을 땐 수치미분 대신 도함수를 그냥 사용하면 보다 정확하게 값을 추측할 수 있다.
보통 딥러닝에선 activation 함수로는 미분된 함수를 알 수 있기 때문에 효율적임
또한 이 개념이 gradient descent method
에 사용됨
경사하강법 Gradient Descent Method link
input x -> [ function ] -> output y
y target 을 얻기 위한 input x 값은?
함수가 얼마나 틀렸는지 정해야 함
E = 1/2 * ( yt - y )^2
E == 0 이면 원하는 결과를 달성했다 를 판별할 수 있음 (아마도 최소) // 모든곳에서 0 이 되어버리면 오버피팅이라고 함
y = ax + b
E = 1/2 ( yt - ax - b)^2
a 또는 b 가 변해야 함
E 가 2차함수니까 최소점이 되는 a, b 를 구해야함
이렇게 에러함수가 2차함수이고 우리가 원하는 지점이 최소점 -> 시작한 지점에서 에러를 줄여주는쪽으로 가야함 -> 미분을 하면 경사가 0 이되는 지점을 찾는다 -> 경사가 하강된당
a updated = a - ar * dE/da // ar: learning rate
minimize E
a updated = a - ar * dE/da
b updated = b - ar * de/db
E가 충분히 작을 때까지 반복
E = 1/2 ( yt - ax - b)^2
dE/da = (yt - ax - b) * -x // a 에 대해서 미분
= (yt - y) * -x
dE/db = (yt - ax - b) * -1 // b 에 대해서 미분
= (yt - y) * -1
var a=0,b=0;
var f = (a,x,b) => a*x + b;
var yt = 1;
var x = 0;
var alpha = 0.01;
for (var i=1000;i-->0;) {
error = yt - f(a,x,b);
console.log(`square error: ${0.5*error*error}`);
var ea = error * -x;
var eb = error * -1;
a -= alpha * ea;
b -= alpha * eb;
}
console.log(`a: ${a}, b: ${b}, error: ${yt-f(a,x,b)}`);
constraint 가 여러개 일경우
var numConst = 3;
var yt = [1, 1.5, 2];
var x = [0, 0.5, 1];
var alpha = 0.01;
var a = 0, b = 0;
var f = (a,x,b) => a*x + b;
for (var i=1000; i-->0;) {
var sqrErrorSum = 0;
var eaSum = 0, ebSum = 0;
for (var c=0; c<numConst; c++) {
var error = yt[c] - f(a, x[c], b);
var ea = error * -x[c];
var eb = error * -1;
sqrErrorSum += error * error;
eaSum += ea;
ebSum += eb;
}
a -= alpha * eaSum / numConst;
b -= alpha * ebSum / numConst;
console.log(`Square error: ${0.5 * sqrErrorSum} when a:${a}, b:${b}`);
}
for (var i=0; i<numConst; i++)
console.log(`a: ${a}, b: ${b}, error: ${yt[i]-f(a,x[i],b)}`);
결과 a: 0.9123957710439071, b: 1.0503135492522502, error: -0.006511434774203684 얼추 x + 1 이랑 같아짐
굳이 모든 constraint 에 대해서 할 필요 없이 랜덤하게 정하도록 하면 최적화 할 수 있다
Stochastic GDM
var numConst = 3;
var yt = [1, 1.5, 2];
var x = [0, 0.5, 1];
var alpha = 0.01;
var a = 0, b = 0;
var f = (a,x,b) => a*x + b;
for (var i=1000; i-->0;) {
var c = ~~(numConst * Math.random()); // 랜덤을 썼지만 데이터에 따라서 적절하게 주면 좋다
var error = yt[c] - f(a, x[c], b);
var ea = error * -x[c];
var eb = error * -1;
a -= alpha * ea;
b -= alpha * eb;
console.log(`Square error: ${0.5 * error*error} when a:${a}, b:${b}`);
}
for (var i=0; i<numConst; i++)
console.log(`a: ${a}, b: ${b}, error: ${yt[i]-f(a,x[i],b)}`);
결과 a: 0.9167923973982887, b: 1.0454330682483828, error: -0.0038292669475270547
연쇄 미분 Chain rule link
back-propagation 이해에 도움
Chained Functions
함수의 조합일 경우
input x -> [ [ g(x) ] -> [ f(g) ] ] -> output y = f(g(x))
f(x) = ax + b
걍 미분: df/dx(x) = a
x 가 유일한 변수일 경우
편미분 :
df/dx(x,a,b) = a
df/da(x,a,b) = x
df/db(x,a,b) = 1
변수가(x, a, b) 여러개일 경우
f(x) = f(g(x))
df/dx = df(g)/dg * dg(x)/dx
y = f(g(x))
f(x) = af * x + bf
g(x) = ag * x + bg
eaf1 = af0 - ar * dE/daf
ebf1 = bf0 - ar * dE/dbf
eag1 = ag0 - ar * dE/dag
ebg1 = bg0 - ar * dE/dbg
dy/dx = df(g)/dg * dg/dx = af * ag
dy/daf = df/daf = g(x)
dy/dbf = df/dbf = 1
dy/dag = df(g)/dg * dg(x)/dag = af * x
dy/dbg = df(g)/dg * dg(x)/dbf = af * 1
dE/daf = -(yt - y) * dy/daf = -(yt - y) * df(g)/daf = -(yt - y) * g(x)
... (각각 `-(yt - y)`를 곱해주는 형태)
var MAX = 1;
var rand = () => Math.random() * MAX;
var f = (a,x,b)=> a * x + b;
var g = (a,x,b)=> a * x + b;
var yt = 1;
var x = 0;
var af=rand(), bf=rand(), ag=rand(), bg=rand();
var alpha = 0.01;
for (var i=0;i<500;i++) {
var error = yt - f(af, g(ag, x, bg), bf);
var sqError = 0.5 * error * error;
var eaf = -error * g(ag, x, bg);
var ebf = -error * 1;
var eag = -error * af * x;
var ebg = -error * af * 1;
af -= alpha * eaf;
bf -= alpha * ebf;
ag -= alpha * eag;
bg -= alpha * ebg;
console.log(`error: ${sqError}`);
}
console.log(`${af} ${bf} ${ag} ${bg} ------ ${f(af, g(ag, x, bg), bf)}`);
결과 error: 1.115465481992649e-12 1.0865808935532866 0.34940286962120654 0.9937056196788403 0.5987549371928094 ------ 0.9999985442956114
class Neuron {
constructor(w=2, b=1) {
this.w = w; // weight 인풋이 한개일 경우. 여러개면 배열로
this.b = b; // bias
this.input = 0; // for back-propagation
this.output = 0; // for back-propagation
}
getAct(x) {
return x;
// ReLU: return Math.max(x,0);
}
getActGrad(x) {
return 1;
}
feedForward(input) {
this.input = input;
const sigma = this.w * input + this.b;
this.output = this.getAct(sigma);
return this.output;
}
propBackward(target) {
var alpha = 0.1 // learning rate
var grad = (this.output - target) * this.getActGrad(this.output);
this.w -= alpha * grad * this.input;
this.b -= alpha * grad * 1;
}
}
var neuron = new Neuron();
for (var i=0;i<100;i++) {
neuron.feedForward(1);
console.log(`i:${neuron.input} o:${neuron.output} w:${neuron.w} b:${neuron.b}`);
neuron.propBackward(4);
}
sigma = w0 * x0 + w1 * x1 + ... + wn * b
= [w0 w1 w2 ... wn] * [x0
x1
x2
...
b]
b 도 가중치를 곱하는 이유는 매트릭스로 하면 식이 간단해져서 b도 가중치를 곱한다. 대신 wn 이나 b 를 1로 두기도 함.
[ sigma0 [ w00 w01 w02 w03 [ x0
sigma1 = w10 w11 w12 w13 * x1
sigma2 ] w20 w21 w22 w23 ] x2
x3 ]
sigma = W * x
y = f1(sig1) = f1(w1 * f0(sig0) + w1b * b)
input x0 sigma00 | f00 sigma10 | f10
input x1 sigma01 | f01 sigma10 | f11
input x2 sigma02 | f02 sigma10 | f12
input hidden output
layer layer layer
[ sigma00 [ w000 w001 w002 w003 [ x0 sigma01 = w010 w011 w012 w013 * x1 sigma02 ] w020 w021 w022 w023 ] x2 b ]
Array.prototype.sum = function() { return this.reduce((r,a)=> r+a, 0)}
var scalaProd = (W,X)=> W.map((w,i)=> w*X[i]).sum();
- supervised learning
Z = F(X)
point mapping
back propagation
perceptron: input * w -> z
ReLU;
Good at And/Or problem but XOR -> Add hidden layer
x1 -(w11)- y1
(w12,w21) z
x2 -(w22)- y2
```
cost function 을 w로 미분
2. unsupervised learning
```
P(X,Z)
```
energy landscape
볼츠만 분포
볼츠만 머신
S^n, n={1....M}
Data distribution = P(S) = 1/M sum d(S - S^n)
Model distribution = Q(S) = e^(-E(S)) / Z
E(S) = - sum(Wij*Sj*Sj)
Z = sum(e^-E(S))
Kullback-Leibler divergence
D(P||Q) = sum(P(S)*log(P(S)/Q(S)))
3. Information flow
```
H[P(X), P(Z|X)]
```
shannon entropy
두 사람이 있을 때 누가 고수인가? -> 질문 1개 필요
H(Y) = -sum(P(Y) log P(X))
# Restricted Boltzmann Machine
S = Kb ln W
Hopfield NN (HNN)
# CNN
feature extraction layer + classification layer
[ CNN ] [ FC ]
ReLU
Pooling layer; Max Pooling; dimension reduction + rotation/skew... invariant -> data augmentation
# GAN
Two type of Deep learning
Discriminative : 데이터를 서로 다른 클래스로 분류
Generative : 데이터 분포 학습, 이를 기반으로 데이터 재생성
GAN :
Discriminator: 입력을 가짜와 진짜로 분류
Generator: 가짜 데이터 생성
# Reinforcement Learning
supervised, unsupervised, pattern recognition
Sequential decision making and control problem
AlphaGo - DeepMind
- Markov Decision process
- Dynamic programing
- Monte-Carlo
- Temporal Difference
## Markov Decision Process
> 미래 상태가 현재의 상태만 주어지면 과거의 역사와는 무관하게 결정되는 성질을 가지게 되는 확률 과정
Markov Process <- Action
```
a0 a1
s0 -> s1 -> s2
```
`(S, A, P, r, R)`
S: 모든 상태 집합
A: 모든 액션 집합
P: s에서 a행동을 할때 s’으로 갈 확률
r: discount factor; [0 <= r <= 1] 보상이 시간에 따라 r배 만큼 줄어든다
R: 리워드; 얻을 수 있는 모든 보상의 평균
Gt = sum(t)(rRt)
## Policy
s 상태에서 a행동을 할 확률
Our goal in Reinforcement learning is to choose policy so as to maximize the expected value of the total payoff
## Value Function : 상태와 행동의 가치를 매겨주는 함수
State-value function: 상태의 가치 `V(s) = R[Gt|St = s]`
Action-value function: 액션의 가치 `q(s,a) = E[Gt|St = s, At = a]`: 여기의 `q` 가 나중에 나오는 Deep-Q Learning 의 `Q`임
## Bellman Equation: 현재 상태와 다음상태의 value function 사이의 관계식
Monte-Carlo; 직접 움직여서????
Monte-Carlo Control: 현 상태에서 최고의 value만 가지고 판단할경우 local optimum에 빠질 수 있어서 다른 상태로 갈 확률을 정함