2-7 갓 머신 러닝 툴 TensorFlow Softmax 에 의한 Rosenblatt Perceptron N =1 예제 체크

in #kr6 years ago (edited)

Rosenblatt 의 퍼셉트론 장치를 반드시 알고리듬이나 수학을 쓰지 않으면서도 좀 더 쉽게 이해할 수 있는 수단을 강구해 보자. 그것은 바로 우리가 잘 알고 있는 아두이노 조도센서 장치이다. 이 조도 센서 배선 및 코딩은 초중고 아두이노 컴퓨터 코딩 과정에서 누구나 다루어 보는 잘 알려진 과제라고 보면 된다.

조도 센서는 빛의 밝기에 의해 저항 값이 조절 되는 일종의 반도체성 가변 저항으로 실제로 도시의 수많은 가로등 ON OFF에 사용되는 센서이며 영문 명칭을 Photocell 이라고 한다. 일년여 전에 조도센서 배선 및 코딩을 다룰 때만 해도 그 정식 영문 명칭을 모르고 있었는데 근자에 Rosenblatt 퍼셉트론에 관한 Wikipedia 설명에서 보게 된 용어가 Photocell 이었다. 팔자가 아는 반도체 소자로서 정류용 다이오드(Diode)와 발광용 다이오드(LED)가 있고 한편 빛을 받아들이는 Photodiode가 있는 것으로 알고 있었다. Photodiode는 솔라셀로 이해하면 된다. 빛을 쪼여주면 빛 에너지를 10∼20% 의 효율로 전류를 발생시켜 전기 에너지로 바꾸어 주는 반도체 소자이다.

반면에 Cds 라는 명칭으로 잘 알려진 조도센서 Photocell은 빛을 쬬여 주면 반도체 조직의 저항 값이 민감하게 변동되는 특성을 가지고 있다. 따라서 저녁 무렵에 어두워질 때와 아침녁에 밝아질 때의 저항값 변화 특성을 잘 알고 있으면 도시에 깕려 있는 수많은 가로등 시스템에 전기를 공급하거나 차단할 수 있는 것이다.
이 조도센서와 1KΩ 저항을 직렬 연결하고 LOLIN 보드의 3.3V 와 GND에 아래 그림과 같이 연결 배선하자.

noname01.png

WeMos LOLIN 보드에서 아날로그 전압을 읽어 들일 때에는 0.0∼3.3V를 0∼4095 사이의 정수 값으로 읽는다. 반면에 아두이노 우노를 사용하면 전압은 5V 와 3.3V 중에서 선택할 수 있으며 아날로그 핀에서 읽어들이는 정수 값의 범위가 0∼1023이 됨에 유의하자. 여기서는 LOLIN 보드를 사용한다.

조도센서 회로에서 아날로그 핀 위치에서 측정할 수 있는 전압을 옴(Ohm)의 법칙에 의해서 계산해 보자.

noname11.png

어두울 경우 조도센서의 저항 값이 커져 직렬 연결된 합성 저항 값은 41KΩ이 된다. 따라서 이 회로에 흐르는 전류는 다음과 같이 계산된다.

noname12.png

전류가 흐르는 배선이 한 가닥이므로 1KΩ저항과 40KΩ 조도센서 저항에 흐르는 전류값은 동일하며 각각의 저항에 가해지는 전압은 전류X저항 공식으로 계산이 가능하다. 측정하고자 하는 전압이 GND의 0V 대비 1KΩ저항의 반대편으로 조도센서와 연결되는 부분이다.

noname13.png

0.08V는 0V에 근접한 값으로서 0∼4095 사이의 정수 값으로 환산하면 약 99 내지는 100 정도가 된다.

반면에 밝을 경우 조도센서 회로에서 아날로그 핀에서 측정할 수 있는 전압을 옴(Ohm)의 법칙에 의해서 계산해 보자.
직렬 연결된 합성 저항 값은 1.1KΩ이다. 따라서 이 회로에 흐르는 전류는 다음과 같이 계산된다.

noname14.png

전류가 흐흐는 배선이 한 가닥이므로 1KΩ저항과 100Ω 조도센서 저항에 흐르는 전류값은 동일하며 각각의 저항에 가해지는 전압은 전류X저항 공식으로 계산이 가능하다. 측정하고자 하는 전압이 GND 의 0V 대비 1KΩ저항의 반대편으로 조도센서와 연결되는 부분이다.

3.0V는 3.3V에 근접한 값으로서 0∼4095 사이의 정수 값으로 환산하면 약 3723 정도가 된다.

다음은 조도센서에 의해 아날로그 핀의 값을 읽어 출력하는 WeMos LOLIN 코드이다.
//WeMos_lolin_ML_Cds_01
float Volt = 3.3; //아두이노 전압 실측치
float r = 987.0; //1K옴 실측치
int ledPin = 27;
void setup() {
Serial.begin(9600);
pinMode(ledPin,OUTPUT);
}

void loop() {
int analogV = analogRead(36);//0-4095
Serial.println(analogV);
delay(3000);
}//프로그램 끝

이 문제의 제기는 비록 Rosenblatt이지만 우리가 체크해 본다는 입장에서 갓(God) 머신 러닝 툴로 봐도 무방한 TensorFlow Softmax 코드에 의해 2개의 데이터를 대상으로 머신 러닝 지도 학습(Supervised Learning)을 시킨 후 어디까지가 밝음의 영역이고 어디까지가 어둠의 영역인지 확인해 나가는 어려운 분류문제( clasification)를 부과하도록 한다.

밝기 데이터를 4095로 나누어 normalization 하면 100은 약 0.02, 3723은 0.909 이다. 그 사이 밝기가 애매한 정도로서 구름이 낀 상태에서 선글라스로 가리면 약 2000 가까운 값이 출력되므로 0.5 까지는 밝은 쪽으로 볼 수 있을 듯하다. 해봐야 알지?

TensorFlow에 의한 softmax 코드를 준비하자. 어둠 데이터 0.02, 밝음 데이터 0.909, 라벨 값은 on hot code를 사용한다. 즉 어둠은 10, 밝음은 01 이며 나중에 출력해야 할 라벨 값으로는 어둠은 “0”, 밝음은 “1” 이다.

noname02.png

학습(trainning)이 완료된 후 classification 문제를 풀어보도록 한다. 예제는 밝기 데이터 [0.01], [0.95] 를 먼저 테스트 하고 그 다음에는 알으켜 주지 않은 0.445와 0.5를 테스트하기로 한다. 앞의 두문제의 해답 라벨은 [0]과 [1]이다. 뒤의 두 문제도 라벨은 [0]과 [1]이지만 중요한 사실은 앞과 뒤의 확률 값 또는 확신 정도가 크게 다르다는 점이다.

TensorFlow 해석 결과를 보도록 하자. 다음은 cost 함수가 학습횟수에 따라 최소화가 이루어지는 속도를 보여준다.

noname03.png

테스트 데이터는 [0.01], [0.95], [0.447], [0.5]를 대상으로 하였다. 0.01 이나 0.95는 학습 범위 내에 들어오므로 당연한 결과를 준다. 하지만 0.5는 62.37% 확률로 가까스로 밝은 범주로 판정되었고 0.447은 50.17%로 가까스로 어둠으로 판정되었지만 확률이 거의 50 대 50인 셈이 된다. 즉 Rosenblatt의 퍼셉트론 알고리듬 분석해서 출현했던 N=1 인 경우의 문제를 TensorFlow Softmax 에 의해 체크해 보았을 때 마음에 드는 합리적인 결과를 보여준다.

noname04.png

한편 Rosenblatt의 알고리듬 체크과정에서의 딱딱한 수학적인 형태들에 대해 어렵고 난해해서 마음에 들어하지 않는 수알못 분들도 계셨다. 이 예제가 Rosenblatt 퍼셉트론 N=1 경우를 이해하기 위한 보다 적절한 설명이 되었으면 한다.
아래의 코드를 복사해서 실행할 경우 혹 indentation 이 잘못되어 에러가 검출되면 2018년 8월 10일의 AS 내용을 참조하기 바란다. 실제 편집과정에서 paste 하는 순간에 indentation 이 사라지는군요. 오호통재라 누굴 원망하랴! indentation 위치 AS 꼭 보시고 수정작업하세요.

#Softmax Classifier
import tensorflow as tf
tf.set_random_seed(777) # for reproducibility

x_data = [[0.02], [0.909]]
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
a = sess.run(hypothesis, feed_dict={X: [[0.01]]})
print(a, sess.run(tf.argmax(a, 1)))

print('--------------')

b = sess.run(hypothesis, feed_dict={X: [[0.95]]})
print(b, sess.run(tf.argmax(b, 1)))

print('--------------')

c = sess.run(hypothesis, feed_dict={X: [[0.447]]})
print(c, sess.run(tf.argmax(c, 1)))

print('--------------')

d = sess.run(hypothesis, feed_dict={X: [[0.5]]})
print(d, sess.run(tf.argmax(d, 1)))

print('--------------')

all = sess.run(hypothesis, feed_dict={
               X: [[0.01],[0.95],[0.445],[0.5]]})
print(all, sess.run(tf.argmax(all, 1)))
Sort:  

즐거운 스팀잇 생활하시나요?
무더위야 가라!!!!

Coin Marketplace

STEEM 0.36
TRX 0.12
JST 0.039
BTC 69735.97
ETH 3533.64
USDT 1.00
SBD 4.72