20240620텐서플로우2 기초 키와 신발사이즈즈 예측하기 (Linear Regression)

선형회귀모델을 만들고 학습시키는 방법에 대해 알아보자

선형회귀모델 (Linear Regression)

  • 머신러닝에서 사용되는 방법으로 독립변수(x)와 종속변수(y)사이의 관계를 직선(Linear)로 모델링 하는 기법이다.
    # 기본 식
    y= ax + b
    # y : 종속변수(예측하려는 값)
    # x : 독립변수(입력 값)
    # a : 기울기(독립변수의 변화에 따른 종속변수의 변화 비율)
    # b : y절편 (독립변수가 0일 때 종속변수 값)
    

키와 신발사이즈 예측

  • 텐서플로우를 이용해서 키와 신발사이즈를 예측해보는법을 알아보았다.
  • 키와 신발사이즈의 관계는 어느정도 관계가 있을 것 같아 이를 선형회귀모델의 a,b값을 구해보자.
  • 변수 설정
# 파이썬버전 : 2.17.0-dev20240604
import tensorflow as tf

 = 170
신발 = 260
a = tf.Variable(0.1)
b = tf.Variable(0.2)

경사하강법에서 사용할 손실함수 정의

def 손실함수():
  예측값 =  * a + b
  return tf.square(신발 - 예측값) #평균제곱오차

경사하강법을 이용해서 미지수 a,b값을 구해보자 (딥러닝)

opt = tf.keras.optimizers.Adam(learning_rate=0.1) # 경사하강법을 이용해서 a,b변수를 업데이트해주는 함수

# tf.keras.optimizers.알고리즘
# Adam : 전반적으로 성능이 좋은 알고리즘
# learning_rate=0.1 : 한번에 변수들이 얼마나 업데이트 할지 정의

  • optimizer를 통해 경사하강법을 계속 반복해서 적용하며 최적의 a,b를 찾아주자.
    for i in range(300)
    with tf.GradientTape() as tape: #GradientTape 컨텍스트 사용
      손실 = 손실함수()
      gradients = tape.gradient(손실,[a,b]) # 손실함수에 대한 경사도 계산 (해당 텐서플로우 버전에서는 minimize 대신 gradient를 사용한다.)
      opt.apply_graidents(zip(gradients,[a,b])) #경사도를 적용하여 파라미터 업데이트
      print(a.numpy(),b.numpy()) #업데이트 된 파라미터 출력
    

뭔가 이상한데? 오차 발생생

  • 우리가 만든 모델을 통해 a는 1.5 , b는 1.6의 값을 얻음
    신발 =  * 1.5 + 1.6
    
  • 이 식에서 키 170인사람의 신발사이즈를 예측하면 256.6으로 오차가 발생한다.

모델이 제대로 학습되지 않은 이유

    1. 단일 데이터를 통한 학습이기 때문에 선형회귀모델을 적절히 학습시킬 수 없다.
      • 그렇다면 데이터를 더 넣어가지고 알아보자
    1. learning_Rate와 반복횟수
      • 해당 값이 너무 크면 경사하강법에서 왔다갔다 할 수도 있고, 반복횟수가 더 높으면 좀더 자세한 값을 얻을 수 있다고 한다.
      • 그렇다면 학습률을 0.1 -> 0.01로 / 반복횟수는 300-> 1000으로 늘려보자

데이터가 1개가 아니라 많은 경우

  • 데이터가 많은 경우도 한번 다뤄보겠습니다.
train_x = [1,2,3,4,5,6,7]
train_y = [3,5,7,9,11,13,15]

a = tf.Variable(0.1)
b = tf.Variable(0.1)

opt = tf.keras.optimizers.Adam(learning_rate=0.01)

def 손실함수(a,b):
    예측_y = train_x * a + b
    return tf.keras.losses.mse(train_y,예측_y) # 리스트값을 매개변수로 넣으면 통째로 계산해준다.(반복문 등을 쓸 필요 없음)

for i in range(1000) :
    with tf.GradientTape() as tape:
        손실 = 손실함수(a,b)
        gradients = tape.gradient(손실,[a,b])
        opt.apply_gradients(zip(gradients,[a,b]))
        print(a.numpy(),b.numpy())
  • 우리가 예측 모델을 다음과 같이 만들었습니다.
예측_y = train_x * a + b
  • 우리는 여기서, y값을 만드는 변수 a,b는 각각 2와,1로 쉽게 예측할 수 있는데, 저 for문을 돌려보면, 애매한 숫자들이 나온다.
.
.
.
1.8993518 1.4825469
1.8994493 1.4820793
1.8995469 1.4816117
  • 여기서 for문의 반복 횟수를 1000번에서 3000번으로 늘려보면, 우리가 예측한 수와 점점 더 가까워짐을 알 수 있다.
  • 더 많은 양의 학습과 데이터가 있으면 정답에 더 가까워 진다는 뜻인것 같다.
    .
    .
    .
    1.9980218 1.0094842
    1.9980284 1.0094529
    1.998035 1.0094218
    1.9980414 1.0093907
    1.9980478 1.0093597