2-15 Fermi-Dirac 확률분포를 사용하는 Sigmoid 확률분포 Rosenblatt Perceptron N = 1 조도센서 예제 적용 계산
#History
물리학에 비해 다소 늦게 시작된 머신 러닝은 통계 물리학에서 다루는 3종류 확률분포 중 2종류에 크게 영향을 받고 있다. 첫 번째가 Softmax로서 Boltzman의 통계 역학 공식을 포장도 전혀 바꾸지 않은 채로 그대로 가져다 쓰고 있으며 MNIST 수기 숫자 인식 문제에서 대단히 뛰어난 인식율을 보여 주고 있다. 그 다음이 Sigmoid 확률분포인데 Binary Classification 영역에서 사용이 가능하며 딥러닝에서도 많이 활용될 정도로 중요성이 있다.
머신 러닝에서 초기에 맞닥뜨리는 Sigmoid 확률분포는 사실 통계 물리학과 고체물리학에서 사용하는 Fermi-Dirac 확률분포를 역시 포장도 뜯지 않은 채 그대로 가져다 쓰는 실정이다. 그 내용을 읽어보니 Andrew NG 교수의 강의 보다 훨씬 어려운 듯하다. 이 확률분포는 이탈이아 출신의 저명한 물리학자 Fermi 가 연구를 주도하였고 공동 연구자로서 영국의 양자물리학자인 Paul Dirac과 함께 1926년에 논문으로 출판하였다. Fermi는 이차대전 중에 미국에서 오픈하이머 교수가 주도했던 원자탄 개발 프로젝트인 맨허튼 계획에 참여했으며 54세에 사망하였다.
Fermi-Dirac 확률분포(1926년)는 원자 내에서 파울리의 배타원리(1925년)에 지배를 받게 되는 전자들의 확률적인 분포를 다룬다. 하나의 orbital에 2개의 전자가 들어가는 경우 전자의 스핀이 서로 반대라야 즉 distinguishable 해야 한다는 파울리의 배타원리를 만족해야 한다. 이 사실을 다르게 표현하면 설사 에너지 레벨이 같다고 해도 최소 스핀 벡터가 다르므로 하나의 orbital에 degeneracy 가 2라면 즉 후술하겠지만 서브레벨이 2라면 각각의 서브레벨에 스핀이 반대되는 전자들이 위치하면 파울리의 배타원리가 만족되는 것이다.
#Fermi-Dirac 확률분포의 유도과정
다소 수학적인 유도과정을 이해 못해도 큰 상관은 없을 것이다. 이어지는 과정에서 SIgmoid 함수를 사용한 코드 사용법을 익힐 수 있으면 충분하리라 본다.
Fermi-Dirac 확률분포의전제조건들을 알아보자. 동일한(identical) ni개의 입자들이 에너지 레벨이 εi 로 가정하자. 에너지 레벨 εi 는 다시 구별이 가능한 서브레벨 gi(degeneracy)를 가지며 각 서브 레벨은 최대 1개의 입자를 포함하거나 비어 있을 수 있다. 에너지 레벨 εi는 크기만을 지정하는 스칼라 양이므로 설사 에너지 레벨이 같다고 해도 입자들의 운동량은 벡터이무로 운동 방향이나 회전 방향이 서로 다를 수 있으므로 이들이 속해 있는 서브레벨은 서로 구별이 가능하다.
에너지 레벨이 εi에 해당하는 gi개의 서브레벨에 ni개의 입자들이 각 서브레벨별로 최대 1개의 입자를 포함하거나 비어 있게 될 경우의 수를 계산해 보자.

에를 들어 3개의 서브레벨에 2개의 입자를 배치해 보면 110, 101, 011(3!/{2!1!})이 될 것이다. 수많은 에너지 레벨 εi 전체의 경우의 수를 계산해 보자.
Boltzman 확률분포 유도과정을 따라 W가 최대값을 가지게 되는 즉 가장 probale 한 물리적 상태를 찾아보자. 입자분포 ni는 2개의 구속조건 즉 전체 입자수가 N이며 전체 에너지 값이 E 라는 조건을 만족하면서 W 가 최대값을 가질 수 있도록 다음과 같이 볼츠만의 엔트로피에 비례하는 logW에 대해 라그랑즈 승수 기법을 적용함과 아울러 ni에 관해서 편미분을 하여 0 으로 두고 풀도록 하자.
이 과정에서 큰 수의 Factorial 값들의 ∑항에 대해서 Stirling 의 근사공식 적용이 반드시 이루어지며 다음과 같은 형태의 입자 분포 식이 얻어진다.
각 서브레벨별 평균 입자수는 다음과 같이 표현된다.
k는 Boltzman 상수이며 T는 절대온도 K 이다. μ는 화학적 포텐셜(Chemical Potential) 또는 Fermi level 이라고도 한다.
이와 같은 확률분포 공식의 유도 과정은 Boltzman, Fermi-Dirac, Bose-Einstein 확률분포 별로 경우의 수 W가 얻어지면 동일한 과정을 따르며 각각 조금씩 다른 확률분포형태가 얻어진다.
Fermi-Dirac 확률분포를 사용하면 절연체, 반도체 및 도체로 구분되는 많은 물질들의 전기 전도 특성 설명이 가능하다. Fermi-Dirac 확률분포는 원자들의 안정된 화학적 공유 결합을 가능케하는 Valence Band 와 Fermi level 보다 높은 에너지 레벨에 속하는 전자들의 전기적 흐름이 가능해지는 Conduction Band의 역할에 대한 물리적 배경을 제공한다.
반면에 Andrew NG 교수의 Logistic regression에 관한 명강의를 들어 보면 Sigmoid 함수의 사용법에 대한 명쾌한 설명이 있는 것은 사실이나 Andrew NG 교수가 예제로 드는 Tumer 사이즈 문제가 반드시 Sigmoid 함수를 사용해서 머신 러닝 문제를 풀어야 하는지에 관해서는 그다지 확신이 가지 않는다.
그렇다면 차라리 Rosenblatt 의 퍼셉트론으로 돌아가서 아두이노 조도센서 측정 문제를 이해할 정도면 만들 수 있는 예제를 고려해 보자. 아두이노에서 측정이 가능한 조도센서 1개를 사용하는 N=1 퍼셉트론 문제를 이미 Softmax를 사용하여 풀어 보았으미 다음 사이트를 참조하기 바란다.
2-7 갓 머신러닝 툴 TensorFlow Softmax에 의한 Rosenblatt Perceptron N =1 예제 체크
https://steemit.com/kr/@codingart/tensorflow-softmax-rosenblatt-perceptron-n-1
즉 조도센서 1개짜리 퍼셉트론 문제에서 Rosenblatt의 웨이트 업데이트 알고리듬 대신 Softmax 확률분포와 cost함수에 해당하는 Cross entropy를 적용하며 문제를 풀었다. 물론 Softmax는 N=1 뿐만 아니라 MNIST 문제처럼 라벨 값이 많은 경우에도 얼마든지 적용이 가능한 기법이다. 반면에 Sigmoid 함수는 2개의 라벨 값만을 사용하는 Binary Classification에는 Softmax처럼 적용이 가능할 것이다. 하지만 라벨 값이 늘어나면 적용이 곤란하다.
#N=1 조도센서 장치의 원리
Cds 라는 명칭으로 잘 알려진 조도센서 Photocell은 빛을 쬬여 주면 반도체 조직의 저항 값이 민감하게 변동되는 특성을 가지고 있다. 따라서 저녁 무렵에 어두워질 때와 아침 녁에 밝아질 때의 저항값 변화 특성을 잘 알고 있으면 가로등 시스템에 공급하는 전기를 아두이노 보드의 코드를 사용하여 자동으로 ON 또는 OFF가 가능하다.
이 조도센서와 1KΩ 저항을 직렬 연결하고 LOLIN 보드의 3.3V 와 GND에 아래 그림과 같이 연결 배선하자. LOLIN 보드가 없으면 아두이노 우노 보드를 사용해도 무방하다. LOLIN 보드에서는 analogRead() 명령을 사용하여 0.0∼3.3V를 0∼4095 사이의 정수 값으로 읽어 들인다. 반면에 아두이노 우노를 사용하면 전압은 5V 와 3.3V 중에서 선택할 수 있으며 아날로그 핀에서 읽어들이는 정수 값의 범위가 0∼1023이 됨에 유의하자. 여기서는 LOLIN 보드를 기준으로 설명하도록 하자.
아두이노 LOLIN 보드 조도센서 장치를 사용하여 2가지 경우를 실측한다. 첫 번째는 조도센서를 손가락으로 막은 상태에서 측정하고 두 번째는 햇빛이 쨍하게 내리쬐는 오후 2시경이 좋을 듯하다.
실측 후 밝기 데이터를 4095로 나누어 normalization 하면 손가락으로 가렸을 때 100은 약 0.02, 3723은 0.909 가 된다. 그 사이 밝기가 애매한 정도로서 구름이 낀 상태에서 선글라스로 가리면 약 2000 가까운 값이 출력되므로 0.5 까지는 밝은 쪽으로 볼 수 있을 듯하다.
Rosenblatt의 퍼셉트론 장치에서 가능한 N=1인 문제를 체크해 본다는 입장에서 TensorFlow Softmax 코드에 의해 2개의 학습용 데이터를 가지고 머신 러닝 지도 학습(Supervised Learning)을 시킨 후 어디까지가 밝음의 영역이고 어디까지가 어둠의 영역인지 확인해 보기위해서 이원분류문제( Binary Clasification) 문제를 코딩하여 풀어보았다.
Sigmoid 확률분포 함수와 cost 함수를 사용하여 코드를 작성하자. 아래와 같이 hypothesis 와 cost 함수를 Sigmoid 함수에 적합하게 수정하도록 하고 나머지 코드는 그대로 사용하기로 한다.
코드의 앞부분에 x_data 가 아두이노 조도센서에서의 실측 값 0.02와 0.909로 되어 있는데 이론적이긴 하지만 어두울 때의 극한 값 0.0 과 밝을 때의 극한 값 1.0 으로 대체하여 학습을 시킨 후 Session 단계에서 밝기 데이터를 0.1 간격으로 9개의 테스트 데이터를 준비하여 그 라벨 값을 판정해 보고 계산된 확률 값을 그래프로 작성해 보기로 한다.
아울러 learning rate 와 학습을 위한 steps 의 수에 따른 확률계산의 영향을 파악할 필요가 있다. 여기서는 learning rate 값을 0.1로 고정시키고 steps 수를 2000, 4000, 8000,20000, 100000 의 5 경우를 계산하여 확률 분포를 계산하였다. 특히 10만번 계산 시에는 윈도우즈10에 깔린 아나콘다 스파이더에서 계산 시에도 제법 시간이 걸리므로 만약에라도 라즈베리파이와 같이 작은 컴퓨터 보드를 사용하는 경우에는 2만번까지만 해보도록 권장한다.
그래프를 관찰해보면 steps의 수가 늘어날수록 뚜렸한 S자형을 보여주고 있다. 물론 2000번 계산 시에도 라벨 판정 결과는 100,000번 계산 때와 동일한 결과를 주고 있으므로 불필요할 정도로 steps 수를 늘릴 필요는 없어 보이지만 Sigmoid 형 확률분포의 극한적인 모양을 관찰해 보기 위해서 10만번 경우를 포함하였다.
또 하나의 관찰점은모든 그래프들이 한점에서 교차하는 0.5에서의 확률 값이다. 이론 적으로 Fermi-Dirac 확률 분포의 Fermi level 또는 일종의 threshold에 해당하는 지점이라 정확하게 0.5라는 숫자를 계산하기 극히 어려우며 차라리 양쪽 극한을 고려하여 하나는 라벨 값“0”이 되는 0.49 라든지 또 다른 하나는 라벨 값“1”이 되는 0.51을 택하여 2개의 확률 값을 계산해야 할 것이다.
아래의 코드를 복사해서 실행할 경우 혹 indentation 이 잘못되어 에러가 검출되면 2018년 8월 10일의 AS 내용을 참조하기 바란다. indentation 위치 AS 꼭 보시고 수정작업하기 바란다.
※1-25 Irises flower(붓꽃) data set을 사용한 Softmax Classification 머신 러닝 첨부 코드 AS
https://steemit.com/kr/@codingart/1-25-irises-flower-data-set-softmax-classification-as-as
#Logistic_Classifier_2Data_Sigmoid_01.py
import tensorflow as tf
tf.set_random_seed(777) # for reproducibility
x_data = [[0.0], [1.0]]
y_data = [[1, 0],[0, 1]]
X = tf.placeholder("float", [None, 1])
Y = tf.placeholder("float", [None, 2])
nb_classes = 2
W = tf.Variable(tf.random_normal([1, nb_classes]), name='weight')
b = tf.Variable(tf.random_normal([nb_classes]), name='bias')
#tf.nn.softmax computes softmax activations
#softmax = exp(logits) / reduce_sum(exp(logits), dim)
hypothesis = tf.nn.softmax(tf.matmul(X, W) + b)
#Cross entropy cost/loss
cost = tf.reduce_mean(-tf.reduce_sum(Y * tf.log(hypothesis), axis=1))
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(cost)
#Launch graph
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for step in range(2001):
sess.run(optimizer, feed_dict={X: x_data, Y: y_data})
if step % 200 == 0:
print(step, sess.run(cost, feed_dict={X: x_data, Y: y_data}))
print('--------------')
# Testing & One-hot encoding
all = sess.run(hypothesis, feed_dict={
X: [[0.1],[0.2],[0.3],[0.4],[0.5],[0.6],[0.7],[0.8],[0.9]]})
print(all, sess.run(tf.argmax(all, 1)))
#Sigmoid_classifier_plot_01.py
import matplotlib.pyplot as plt
x = [ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
y1 = [0.10306392, 0.17237695, 0.2740614, 0.4062831, 0.5536449,
0.69214565, 0.8029651, 0.88076466, 0.93050367]
y2 = [0.06243501, 0.12136347, 0.22269966, 0.372753, 0.55209875,
0.7188435, 0.8413505, 0.9166662, 0.9580117]
y3 = [0.03633959,0.082648, 0.17712186, 0.33960837, 0.5512915,
0.74589187, 0.87520117, 0.943677, 0.9756271 ]
y4 = [0.01735957, 0.048518, 0.12830019, 0.29816347,
0.55081266,0.7797085, 0.9108438, 0.9672006, 0.98838764]
y5 = [0.00480084,0.01889341,0.07138641,0.23481815,0.55057174,
0.8302308, 0.9512721, 0.98733073,0.99679595]
plt.plot(x,y1,linestyle='dashed', marker="o", color="black", label="steps:2000")
plt.plot(x,y2,linestyle='dashed', marker="o", color="blue", label="steps:4000")
plt.plot(x,y3,linestyle='dashed', marker="o", color="yellow", label="steps:8000")
plt.plot(x,y4,linestyle='dashed', marker="o", color="green", label="steps:20000")
plt.plot(x,y5,linestyle='dashed', marker="o", color="red", label="steps:100000")
plt.xlim(-0.1,1.1)
plt.ylim(-0.1,1.1)
plt.legend()
plt.grid()
plt.show()
pairplay 가 kr-dev 컨텐츠를 응원합니다! :)
이오스 계정이 없다면 마나마인에서 만든 계정생성툴을 사용해보는건 어떨까요?
https://steemit.com/kr/@virus707/2uepul
아직 Payout 되지 않은 관련 글
모든 기간 관련 글
인터레스팀(@interesteem)은 AI기반 관심있는 연관글을 자동으로 추천해 주는 서비스입니다.
#interesteem 태그를 달고 글을 써주세요!