본문 바로가기
AI

[ai-3team] 2020-11-05 study

by 나 왜 인공지능전공 2020. 11. 6.

Lab1

import tensorflow as tf   
tf.__version__            #tensorflow의 버전을 확인한다.

'1.12.0'

hello = tf.constant("Hello, TensorFlow!")

sess = tf.Session()

print(sess.run(hello))
print(sess.run(hello).decode(encoding='utf-8'))

b'Hello, TensorFlow!'

Hello, TensorFlow!

그냥 print를 하게 되면 b가 앞에 붙어서 출력이 되는데 sess.run(hello)의 자료형이 byte 이기 때문이다. 그래서 decode 함수로 문자열로 변환시켜 출력을 하면 정상적으로 나오게 된다.

여기서 우리는 한가지 의문점이 있었다. 왜 hello를 바로 사용하지 않고 sess를 거쳐서 사용하는 것일까?

print(hello)

Tensor("Const_1:0", shape=(), dtype=string)

이러한 이상한 문자열이 출력된 이유는 텐서플로우에서 데이터의 처리 단위는 텐서(Tensor)이기 때문이다.

(Const: 0는 차원수이고shape는 차원가지고 있는 요소의 수이다.dtype는 데이터 타입을 나타낸다.)

node1 = tf.constant(3.0)
node2 = tf.constant(4.0) 
node3 = tf.add(node1, node2)

print("node1:", node1, "node2:", node2)
print("node3: ", node3)

node1: Tensor("Const_6:0", shape=(), dtype=float32) node2: Tensor("Const_7:0", shape=(), dtype=float32)

node3: Tensor("Add_1:0", shape=(), dtype=float32)

우리가 tf.constant() 및 tf.add()를 이용해서 수행한 명령어는 위와 같은 그래프를 정의한 것이지 실제로 연산을 수행한 것은 아닙니다. 연산을 수행하기 위해서는a와 b에 데이터를 넣어서 흐름(Flow)이 이루어지도록 만들어야 합니다.이러한 동작을 바로세션(Session)이 수행합니다.

sess = tf.Session()
print("sess.run(node1, node2): ", sess.run([node1, node2]))
print("sess.run(node3): ", sess.run(node3))

sess.run(node1, node2): [3.0, 4.0]

sess.run(node3): 7.0

위와 같이 작성하니 결과값이 나오는 것을 알 수 있었다.

그리고 tf.constant 외에 다른 변수형으로 tf.placeholder 와 tf.Variable이 있다는 것도 알아보았다.

이중 tf.placeholder는 특이하게 입력으로 사용할 데이터의 타입만 지정해주고 실제 값은 나중에 세션에서 실행될 때 아래와 같이 "feed_dict={}"를 이용하여입력하는 방식이었다.

result = sess.run(y,feed_dict={x:input_data})

Lec2

회귀; Regression

"Regression toward the mean"

여기서 mean은 전체 평균을 의미한다.

크거나, 작거나, 어떤 값이 있더라도 전체적으로 보면 평균으로 회귀(되돌아가는)하는 특징, 속성이있다.

선형 회귀; Linear Regression

예를 들어 키, 몸무게를 나타내는 데이터들이 산포되어 있을 때, 그 데이터들을 가장 잘 표현하는 선을 찾는것을 선형 회귀 분석이라고 한다.

이 선을 가지고 다음 데이터를 예측하는 것이 목표이다.

데이터들을 가장 잘 대변하는 직선(일차함수)를 구하는 것이다.

y=ax+b

위의 식에서 기울기인 a값과 y절편인 b값을 구하는 것이 목적이다.

가설; Hypothesis

H(x)=Wx+b

가설 함수는 이처럼 표현한다. W는 weight, b는 bias를 나타낸다.

주어진 데이터에 가장 적합한 가설함수(일차방정식)를 찾는 것이 목표이다.

비용; Cost

그러면 가장 적합한 함수는 어떻게 구하나?

비용 개념을 알아야한다. 각각의 데이터에서 가설 함수가 얼만큼 떨어져 있는지를 알면된다. 그 오차값을 점점 줄여나가는 것이다.

선형 회귀 모델(머신러닝 모델)의 목표은 결국 이 오차를 줄이는 것이다.

방법으로는 평균 제곱 오차, MSE, 절대값을 사용하는 평균 절대 오차 MAE, 이 둘을 절충하여 사용하는 후버 손실, 그리고 MSE를 직관적으로 나타내주는 결정계수가 쓰인다.

평균 제곱 오차; MSE

H(x)-y 값은 음수가 될 수 있기 때문에, 이 차이값을 나타내는 척도는 제곱을 이용하여 정의한다.

으로 나타낸다.

이 식은 분산과 똑같다. 각 데이터와 평균의 차이를 제곱하여 평균낸 것이다. 따라서 데이터가 예측(평균)으로부터 얼마나 퍼져있는지를

나타낸다고 할 수 있다.

MSE 비용 함수

이렇게 나타낸다.

이다.

평균 절대 오차; MAE

제곱 대신 절대값을 사용하는 것이다. 일반적으로는 MSE가 계산하기 편하기 때문에 MSE가 더 많이 사용된다.

하지만 MSE는 제곱값이기 때문에 오차가 커질 수록 손실이 제곱으로 커진다. 패턴에서 많이 벗어나는 데이터르 이상점(outlier)라고 하는데 MAE는 이 이상점에 영향을 적게 받는다.

MAE는 강건(robust)하다고 한다.

후버 손실; Huber loss

MSE와 MAE를 절충한 것이다. 일정한 범위(δ)를 정해서 그 범위 안에 있으면 오차를 제곱하고 그 밖에 있으면 절대값을 사용한다.

결정 계수 R^2

MSE는 수치만 보고는 오차의 크고 작음을 직관적으로 알기 어렵다. 따라서 결정 계수 수치로 보는 경우가 많다. R^2라고 표기한다.

앞에서 봤듯이 MSE는 VAR(분산)과 같은 형태이다.

만약 모든 MSE를 같은 평균과 비교하여 계산한다면 MSE=VAR이 되고 R^2=0이 된다.

또는 오차가 존재하지 않는다면 MSE=0이 되고 R^2=1이 된다.

0~1사이의 값이 나오기 때문에 직관적으로 이해하기 쉽다.

MSE가 커지면 R^2는 작아지고 MSE가 작아지면 R^2는 커진다.

R^2=0.7이면 "이 모형은 분산의 70%를 설명한다" 라고 해석한다.

목표

결국 선형회귀를 사용하는 머신러닝의 목표는 cost(W,b)를 최소화하는 W와 b를 찾는 것이다.

추가 설명; 그러면 컴퓨터는 어떻게 학습을 하는가?

만약 $y=2x$에 라는 함수를 구한다고 해보자. a=2, b=1이 되어야하는 것이다.

위의 함수는 모른채로 x=1,2,3,4,5,... y=2,4,6,8,10,... 이렇게 주어진다면,

처음에는 임의의 숫자를 세팅한다. 만약 a=0, b=0로 세팅된다면 무슨 값을 넣든 0이 나올 것이다.

이 때 나오는 결과값과, 데이터값을 비교하여, a와 b를 조절해나간다.

비용 함수를 최소화하는 방향으로 a,b를 조절한다.

경사 하강법; Gradient Descent

그렇다면 비용을 최소화하는 지점을 구하려면 어떻게 해야하나?

만약 비용 함수의 그래프가 아래와 같은 형태라면 목표지점, 즉 비용이 가장 낮아지는 지점의 a와 b값을 구하면 되는 것이다.

이 때 미분을 사용하여(a와 b로 미분한다.) 기울기 값의 증감에 따라 a,b값을 조절해가면서 목표지점에 가까워지게 하는 것이다.

더 자세히 알아보자.

처음에 설정한 직선을 H(x)=Wx라 두고, 이 것의 비용 함수를 최소로하는 W를 찾는 것이 목적이다.

W는 처음에 초기화한 상수이다.

α는 learning_rate로 학습속도를 조절하는 상수이다. 이 역시도 초기화한다.

α은 적절하게 조절해주어야한다. 너무 작으면 목표값을 찾는것이 오래걸리게 되고, 너무 크면 목표값을 지나쳐버릴 수 있기 때문이다. W값 업데이트 가중치라고 생각하자.

그리고 남은 부분은 비용 함수를 W로 편미분 한것이다.

(편미분은 다변수 함수의 특정 변수를 제외한 나머지 변수를 상수로 생각하여 미분하는 것이다.)

결국 비용 함수를 편미분한 것을 통해 W를 변화시켜 최적의 W를 구하는 것이다.

위에서 본 것과 같이 W에 변화에 따라 비용 함수가 그려지기 때문에, 최소가 되는 지점, 즉 접선의 기울기가 0과 가까운 지점에서의 W가 목표값이 된다고 할 수 있다.

만약 가설 함수에 y절편이 있는 H(x) = Wx + b 형태라면, b를 W2라고보고 문제를 푼다.

즉 H(x) = Wx + W2x를 풀어야한다.

이 때는 비용함수가 3차원이 된다. 이후의 과정은 머신러닝이 해결해준다.

Lab2

Lec2에서 배운 개념을 Tensorflow를 통해서 학습해보자.

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
tf.enable_eager_execution()



x_data = [1, 2, 3, 4, 5]
y_data = [1, 2, 3, 4, 5]
plt.plot(x_data, y_data, 'o') #'o'는 그래프에 점찍는거 s나 *로 바꿀수 있다
plt.ylim(0, 8) #y축을 8까지 제한
plt.show()

먼저 임의로 데이터를 정한다. 데이터를 정한후에 plt 메소드를 통해서 그래프에 표현을 해보았다.

W = tf.Variable(2.9)
b = tf.Variable(0.5)

hypothesis = W * x_data + b   #가설함수

plt.plot(x_data, hypothesis.numpy(), '-r') #빨간선 그려주는거
plt.plot(x_data, y_data, 'o')
plt.ylim(0, 8)
plt.show()

W와 b값을 임의로 정하여 hypothesis(가설함수)를 그래프에 표현해 보았다. 현재는 가설함수가 많이 벗어나 있는 것을 볼 수가 있다.

learning_rate = 0.01

for i in range(100): # W, b update

    with tf.GradientTape() as tape:       #Gradient descent(경사하강법) 함수 : 코스트를 최소화 시키는 함수다
        hypothesis = W * x_data + b
        cost = tf.reduce_mean(tf.square(hypothesis - y_data)) 
    W_grad, b_grad = tape.gradient(cost, [W, b]) 

    W.assign_sub(learning_rate * W_grad)
    b.assign_sub(learning_rate * b_grad)    

    if i % 10 == 0:
        print("{:5}|{:10.4f}|{:10.4}|{:10.6f}".format(i, W.numpy(), b.numpy(), cost))

Gradientdescent(경사하강법)을 사용하여Cost최소화 한다. 진행 상황을 알기위해서 10번 반복할 때 마다 W,b,cost 값을 화면에 나타낸다.

plt.plot(x_data, y_data, 'o')
plt.plot(x_data, hypothesis.numpy(), 'r-')
plt.ylim(0, 8)

경사하강법을 사용하여 최적의 W와 b값을 찾아 가설함수를 그래프에 그려보았더니 거의 일치하는 것을 알 수 있었다.

Next Study

  • Lac3, Leb3 까지 해오기
  • 모두의 딥러닝 시즌2 에서 사용하는 텐서플로우의 버전이 낮아서 혼란이 올 수도 있으니 해결방안 생각하기