다중차원 선형모델 직접 구현
Python/인공지능

다중차원 선형모델 직접 구현

728x90

저번 글에서 간단한 선형 예측 모델을 직접 구현해 봤는데, 이번에는 다중차원일 경우에 어떻게 모델을 구현할지 알아보겠다.

 

해석해를 통한 방법과 경사하강법을 통한경우를 둘다 직접구현해 보았다.

 

수식적인 공식을 보고 직접 코드를 구현해 봐서 좋은코드는 아닐지 몰라도 원리는 들어가 있을꺼라 생각한다.

 

이전에 1차원인 경우에는 예측모델이 ax + b라는 말을 한적이 있는데,

 

그렇다면 2차원인 경우에는 어떨까 ax^2 + bx + c 일까? 그렇지는 않다.

 

우선 2차원이라는 표현도 맞긴 하지만 입력이 2개 이상으로 오는 경우라고 생각하면 좋을 것이다.

 

 

조금 쉽게 생각하여 키와 몸무게를 가지고 나이를 맞추는 모델을 구현해본다고 생각해보자. 키,몸무게 2개의 다른 요소가 입력으로 주어지고 이를 통해 나이를 맞추기 때문에

 

a * 키 + b * 몸무게 + c 라는 식이 맞을것이다.

 

자, 이제 이 a,b,c를 모은 집합을 W라고 하고 W1,W2,W3이라고 칭해보자.

 

그렇다면 입력이 3개인 경우에는

 

W1 * X1 + W2 * X2 + W3 * X3 + W4

 

와같이 표현될 수 있을 것이다. 이처럼 차원은 계속 확장해 나갈 수 있다. 그런데 이러한 곱셈 꼴을 어디서 많이 본 것 같지 않나???

 

 

행렬 곱으로 구한 예측값

이는 행렬곱으로 생각할 수 있고 또한 numpy배열을 사용하여 쉽게 구할 수 있다.

 

경사하강법을 통해서 구할때도 저번 글에서 구했던 것과 똑같지만, 각 입력값의 기울기들을 변화하게 하는것만 바꾸어주면 쉽게 구현할 수 있다.

 

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import os
current_path = os.path.dirname(os.path.abspath(__file__))
raw_data = pd.read_csv('multiple_linear_regression_data.csv',encoding='utf-8', engine = 'python')
X = raw_data[['height','weight']].to_numpy()    # x0 , x1 데이터 받기
X = np.c_[X,np.ones(80)]   # X데이터 있는 배열 뒤에 1 붙이기 ( 나중에 w구해서 계산하기 위함 )
Y = raw_data['label'].to_numpy()
Y = Y.reshape(80,1)   # 행렬계산을 위해 맞춰줌

#------------------------------------------------------------------
#                          실습1
#------------------------------------------------------------------
height = raw_data['height'].to_numpy()  # X0데이터
weight = raw_data['weight'].to_numpy()  # X1 데이터
age = raw_data['label'].to_numpy()    #Y 데이터
N = len(height)   # N = 80 ( 데이터 수 )

fig = plt.figure()
ax = fig.add_subplot(projection='3d')   # 3차원 그래프를 그리기 위함
ax.scatter(height,weight,age)
ax.set_xlabel('height')
ax.set_ylabel('weight')
ax.set_zlabel('age')
#plt.show()   # 마지막에 한번에 출력하기위해 주석
#------------------------------------------------------------------
#                           실습2
#------------------------------------------------------------------
analytic_W = np.linalg.pinv(X.T @ X) @ X.T @ Y    # 해석해 구하는 식을 행렬계산으로 풀이
height_data = np.linspace(55,190,1000)   # 55 ~ 190을 1000개로 나눈 배열
weight_data = np.linspace(10,100,1000)   # 10 ~ 100을 1000개로 나눈 배열
Height,Weight = np.meshgrid(height_data,weight_data)
analytic_y = analytic_W[0]*Height + analytic_W[1]*Weight + analytic_W[2]   # W0 * X0 + W1 * X1 + W2 식 구현
print(analytic_W)

fig = plt.figure()   # 그래프 그리기
ax = fig.add_subplot(projection='3d')
ax.scatter(height,weight,age)
ax.plot_surface(Height,Weight,analytic_y,cmap='plasma')
ax.set_xlabel('height')
ax.set_ylabel('weight')
ax.set_zlabel('age')
ax.set_title('Analytic Solution')   #해석해로 구한 평면
#plt.show()  # 마지막에 한번에 출력하기위해 주석

#------------------------------------------------------------------
#                           실습3
#------------------------------------------------------------------
MSE_Analytic_Solution = np.mean( (X @ analytic_W - Y) ** 2 )  # 해석해로 구한 식의 MSE값을 행렬로 계산
print('----------------')
print('실습3')
print('MSE_Analytic_Solution :',MSE_Analytic_Solution)
print('----------------')

#------------------------------------------------------------------
#                           실습4
#------------------------------------------------------------------
print('실습4')
def Gradient_Descent(lr,Gradient_W,epoch):    #경사하강법 함수 learning rate , epoch 와 W들을 인자로 받음
    MSE_Gradient_Descent = np.mean((X @ Gradient_W - age) ** 2)      #경사하강법으로 구한 해석해의 MSE
    print('before MSE_Gradient_Descent :', MSE_Gradient_Descent)     #학습 시키기 전의 MSE
    print('')

    for i in range(epoch):   # epoch만큼 반복
        y_pred = X @ Gradient_W   # 바뀐 W들로 구한 예측값
        error = y_pred - age      # 예측값과의 차이

        W0_diff = np.mean((height * error))    # 각 W들의 기울기 구하기
        W1_diff = np.mean((weight * error).mean())
        W2_diff = np.mean(error)

        Gradient_W[0] = Gradient_W[0] - lr * W0_diff    # W들 값 갱신
        Gradient_W[1] = Gradient_W[1] - lr * W1_diff
        Gradient_W[2] = Gradient_W[2] - lr * W2_diff

        if i%500 ==0:   # 500번 학습할때마다 W0,W1,W2값과 MSE값 출력
            MSE_Gradient_Descent = np.mean((X @ Gradient_W - age) ** 2)  # 학습을 시켰으므로 MSE값 갱신
            print( "epoch",i, '====> W0 =',Gradient_W[0],'W1 =',Gradient_W[1],'W2 =',Gradient_W[2],'MSE =',MSE_Gradient_Descent)

    print('')
    print('END MSE_Gradient_Descent :', MSE_Gradient_Descent)   #학습 종료시 MSE출력
    return Gradient_W

Gradient_W = Gradient_Descent(lr=0.00001,Gradient_W=[1,2,-5],epoch=10000)   #넣어준 값들로 학습시킨 후 Gradient_W에 저장

print('----------------')
print('W0 =',Gradient_W[0],'W1 =',Gradient_W[1],'W2 =',Gradient_W[2])  #학습 완료 후 W값들 출력
print('----------------')

gradient_y = Gradient_W[0]*Height + Gradient_W[1]*Weight + Gradient_W[2]  #경사하강법으로 구한 W를 사용하여 구한 모델
fig = plt.figure()   #모델 출력
ax = fig.add_subplot(projection='3d')
ax.scatter(height,weight,age)
ax.plot_surface(Height,Weight,gradient_y,cmap='plasma')
ax.set_xlabel('height')
ax.set_ylabel('weight')
ax.set_zlabel('age')
ax.set_title('Gradient Desent')
plt.show()

 

728x90

'Python > 인공지능' 카테고리의 다른 글

파이참에서 GPU사용!  (0) 2022.04.24
가우스 함수를 이용한 선형회귀 모델 직접구현  (0) 2022.04.17
경사하강법 직접구현  (0) 2022.04.10
10_Text Detection(문자감지)  (0) 2022.03.26
09_순환신경망 RNN  (0) 2022.03.19