Statictics & Math & Data Science/파이썬 데이터 분석

[케라스(keras)] MLP regression 다층퍼셉트론으로 회귀모델 만들기

Taewon Heo 2019. 1. 17. 19:14

[케라스(keras)] MLP regression 다층퍼셉트론으로 회귀모델 만들기



케라스를 이용해서 다층퍼셉트론으로 Neural Network 회귀 모델을 만들어보겠습니다.


모델링에 쓰인 데이터는 비행기가 이륙할 때의 속도와 무게에 따른 이륙 전 이동 거리입니다.



데이터를 보시면 선형적인 관계가 있다는 것을 알 수 있습니다.

import numpy as np
import matplotlib.pyplot as plt
from keras import models, layers
import tensorflow as tf

우선 Sequential 형태로 레이어를 쌓겠습니다.

def build_model():
model = models.Sequential()
model.add(layers.Dense(2, activation='sigmoid', input_shape=(2,)))
model.add(layers.Dense(1))
optimizer = tf.train.RMSPropOptimizer(0.001)
model.compile(optimizer=optimizer, loss='mse', metrics=['mae', 'mae'])
return model

input_shape이 2인 것은 데이터(x1, x2)가 input node에 순차적으로 들어가기 때문입니다.

activation 함수는 sigmoid를 사용했고, optimizer의 learning rate를 0.001로 맞췄습니다.


그리고 main함수를 작성합니다.


def main():
traincsvdata = np.loadtxt('trainset.csv', unpack=True, delimiter=',', skiprows=1)
num_points = len(traincsvdata[0])
print("points : ", num_points)
train_num_colum = len(traincsvdata)
train_mean = []
train_std = []
for i in range(train_num_colum):
train_mean.append(traincsvdata[i].mean())
train_std.append(traincsvdata[i].std())
traincsvdata[i] -= traincsvdata[i].mean()
traincsvdata[i] /= traincsvdata[i].std()

csv파일을 읽어들이면 300개의 행과 3개의 컬럼을 가진 데이터를 얻을 수 있습니다. 그리고 x1, x2와 y데이터를 표준화 해줍니다.

numpy의 .mean(), std() 함수를 이용해서 순서대로 연산을 합니다. 

# x_data생성
x_data = np.array([traincsvdata[0], traincsvdata[1]])
x_data = np.array(x_data).transpose()
# y_data reshape
y_data = traincsvdata[2]
y_data = np.array(y_data).transpose()

그리고 모델의 input_shape에 맞도록 행렬을 transpose 해줍니다.

model = build_model()
model.fit(x_data, y_data, epochs=2000, batch_size=50, verbose=1, shuffle=True)
w = model.get_weights()

모델을 return받아서 학습을 시작합니다. epochs는 300행짜리 데이터를 2000번 학습시키는 것이고 batch_size는 50행씩 학습시키겠다는 것입니다. verbose는 console에 학습 진행을 보여줍니다. shuffle은 True/False 차이가 없습니다.(시간 의존적 데이터가 아니므로)

그리고 layer별 weight와 bias는 다음과 같습니다.

[array([[-0.94589883,  0.15035586],  [-0.5647819 , 0.96030337]], dtype=float32), array([0.46524414, 0.03646885], dtype=float32), array([[-2.0237916], [ 3.0606623]], dtype=float32), array([-0.3549767], dtype=float32)]


학습을 끝냈으니 test 데이터와 비교해보겠습니다.


test_csv_data = np.loadtxt('testset.csv', unpack=True, delimiter=',', skiprows=1)
test_csv_data2 = np.loadtxt('testset.csv', unpack=True, delimiter=',', skiprows=1)
test_num_colum = len(test_csv_data)

#테스트셋 정규화 진행
for i in range(test_num_colum):
test_csv_data[i] -= train_mean[i]
test_csv_data[i] /= train_std[i]

test_x_data = np.array([test_csv_data[0], test_csv_data[1]])
test_x_data = np.array(test_x_data).transpose()

prediction = model.predict(test_x_data)
prediction *= train_std[2]
prediction += train_mean[2]
plt.plot(range(len(prediction)), prediction, 'k*')
plt.plot(range(len(prediction)), test_csv_data2[2], 'mo')
plt.show()

plot에 띄워 test target 데이터와 비교하려면 표준화 한 값을 원래 스케일로 돌려야합니다. 테스트 셋을 정규화 할 때 trainset의 평균, 표준편차로 정규화 했으므로 원래 스케일로 돌릴때도 같은 숫자를 이용합니다.

순서는 표준편차를 먼저 곱하고 평균을 곱해줘야합니다.


별표는 예측값이고 파란색 점은 실제값입니다. 관계가 단순해서 그런지 나름 잘 맞는 것 같습니다.

사실 모델을 단층으로 만들어도 결과는 잘 나왔습니다.
model.add(layers.Dense(1, input_shape=(2,)))

testset.csv

trainset.csv


데이터를 이용해서 선형으로도 해보시고 optimizer나 activation function도 바꿔보세요 :)



배우는 과정이라 설명이 틀렸을 수 있습니다. 이상이 있으면 댓글 남겨주세요!


도움이 되셨으면 공감 부탁드립니다!