728x90
반응형

 이전 포스트에서 변수가 1개인 Input이 들어가 Output이 1개인 모델을 만들어보았다. 이번 포스트에서는 Input이 2개고, Output이 1개인 모델을 만들어보도록 하겠다.

 

 

학습 목표

  • 이전 패턴보다 컴퓨터가 인지하기 어려운 패턴을 컴퓨터가 찾아내도록 해보자.
  • 패턴: $ f(x)=\frac{1}{2}x_1^2-3x_2+5 $

 

 

 

 

1. 이전 방식대로 모델을 만들고 평가해보자.

  • 이전 모델을 생성했던 방법대로 데이터셋을 생성하고 학습을 시켜서 패턴을 찾는지 확인해보자.
# Import Module
import pandas as pd
import numpy as np
from tensorflow import keras
from tensorflow.keras.layers import Dense
# Dataset 만들기
np.random.seed(1234)

def f2(x1, x2):
    
    return 0.5*x1**2 - 3*x2 + 5

X0_1 = np.random.randint(0, 100, (1000))
X0_2 = np.random.randint(0, 100, (1000))
X_train = np.c_[X0_1, X0_2]
y_train = f2(X0_1, X0_2)

X1_1 = np.random.randint(100, 200, (300))
X1_2 = np.random.randint(100, 200, (300))
X_test = np.c_[X1_1, X1_2]
y_test = f2(X1_1, X1_2)
# make model
model = keras.Sequential()
model.add(Dense(16, activation = 'relu'))
model.add(Dense(32, activation = 'relu'))
model.add(Dense(16, activation = 'relu'))
model.add(Dense(1, activation = 'linear'))


# Compile
opt = keras.optimizers.Adam(learning_rate=0.005)
model.compile(optimizer=opt, loss='mse')


# Standardization
mean_key = np.mean(X_train)
std_key = np.std(X_train)

X_train_std = (X_train - mean_key)/std_key
y_train_std = (y_train - mean_key)/std_key

X_test_std = (X_test - mean_key)/std_key
>>> model.fit(X_train_std, y_train_std, epochs = 100)

Epoch 1/100
32/32 [==============================] - 1s 972us/step - loss: 4486.5587
Epoch 2/100
32/32 [==============================] - 0s 1ms/step - loss: 2577.3394
Epoch 3/100
32/32 [==============================] - 0s 974us/step - loss: 135.0658
Epoch 4/100
32/32 [==============================] - 0s 1ms/step - loss: 39.6805
Epoch 5/100
32/32 [==============================] - 0s 1ms/step - loss: 26.0182
Epoch 6/100
32/32 [==============================] - 0s 1ms/step - loss: 23.2357

...

Epoch 96/100
32/32 [==============================] - ETA: 0s - loss: 0.870 - 0s 730us/step - loss: 0.9306
Epoch 97/100
32/32 [==============================] - 0s 835us/step - loss: 0.4291
Epoch 98/100
32/32 [==============================] - 0s 792us/step - loss: 0.5671
Epoch 99/100
32/32 [==============================] - 0s 856us/step - loss: 0.3809
Epoch 100/100
32/32 [==============================] - 0s 708us/step - loss: 0.4041
<tensorflow.python.keras.callbacks.History at 0x21cdb6c0b80>
>>> pred = (model.predict(X_test_std) * std_key) + mean_key
>>> pred = pred.reshape(pred.shape[0])
>>> print("Accuracy:", np.sqrt(np.sum((y_test - pred)**2))/len(y_test))
Accuracy: 209.2436541220142
  • 이전 포스트처럼 시험 데이터 셋과 학습 데이터 셋을 전혀 겹치지 않는 영역으로 만들어보았다.
  • 손실 값은 0에 가깝게 줄어들었으나, 정확도(Accuracy)가 209.243으로 매우 낮은 것을 알 수 있다.
  • 예측값과 라벨의 차이가 어느 정도인지 확인해보자.
result_DF = pd.DataFrame({"predict":pred, "label":y_test})
result_DF["gap"] = result_DF["label"] - result_DF["predict"]
result_DF

  • 위 데이터를 보면, 실제(label)와 예측값(predict)의 차이가 매우 크게 나는 것을 볼 수 있다.
  • 대체 왜 이런 현상이 발생한 것일까?

 

 

 

 

2. 학습에 맞는 데이터셋 만들기

  • 이전 학습에서 숨겨져 있던 패턴은 다음과 같다.
  • $h(x) = x + 10 $
  • 위 패턴은 아주 단순한 선형 함수이므로, 학습 데이터 셋과 거리가 있는 데이터라 할지라도, 쉽게 예측할 수 있다.
  • 그러나, 이번에 숨겨진 패턴인 $f(x)=\frac{1}{2}x_1^2-3x_2+5$은 $x^2$의 존재로 인해 선형 함수가 아니며, 해가 2개이므로, 이전에 비해 꽤 복잡해졌다.
  • 이번엔 train Dataset에서 test Dataset을 분리해서 학습해보자.
  • 단, train Dataset과 test Dataset은 절대 중복되선 안 된다.
# Dataset 만들기
np.random.seed(1234)

def f2(x1, x2):
    
    return 0.5*x1**2 - 3*x2 + 5

X1 = np.random.randint(0, 100, (1000))
X2 = np.random.randint(0, 100, (1000))
X = np.c_[X1, X2]
y = f2(X1, X2)

# 데이터셋을 중복되지 않게 만든다.
Xy = np.c_[X, y]
Xy = np.unique(Xy, axis = 0)
np.random.shuffle(Xy)
test_len = int(np.ceil(len(Xy)*0.3))
X = Xy[:, [0,1]]
y = Xy[:, 2]

# test Dataset과 train Dataset으로 나누기
X_test = X[:test_len]
y_test = y[:test_len]

X_train = X[test_len:]
y_train = y[test_len:]
  • np.c_[array1, array2]: 두 array를 열 기준으로 붙인다.
  • np.unique(array, axis = 0): array에서 unique 한 값만 추출한다(axis를 어떻게 잡느냐에 따라 다른 결과를 가지고 올 수 있다).
  • np.random.shuffle(array): array를 랜덤 하게 섞는다
  • np.ceil(float): float을 올림 한다.
  • 데이터셋을 중복되지 않게 만들어, test set과 train set이 중복되어 Accuracy가 낮게 나오는 현상을 피한다.
# make model
model = keras.Sequential()
model.add(Dense(16, activation = 'relu'))
model.add(Dense(32, activation = 'relu'))
model.add(Dense(16, activation = 'relu'))
model.add(Dense(1, activation = 'linear'))


# Compile
opt = keras.optimizers.Adam(learning_rate=0.005)
model.compile(optimizer=opt, loss='mse')


# Standardization
mean_key = np.mean(X_train)
std_key = np.std(X_train)

X_train_std = (X_train - mean_key)/std_key
y_train_std = (y_train - mean_key)/std_key

X_test_std = (X_test - mean_key)/std_key
# Model Learning
>>> model.fit(X_train_std, y_train_std, epochs = 100)

Epoch 1/100
139/139 [==============================] - 1s 912us/step - loss: 2999.6784
Epoch 2/100
139/139 [==============================] - 0s 943us/step - loss: 26.4051
Epoch 3/100
139/139 [==============================] - 0s 1ms/step - loss: 14.5395
Epoch 4/100
139/139 [==============================] - 0s 1ms/step - loss: 9.9778
Epoch 5/100
139/139 [==============================] - 0s 814us/step - loss: 7.2809
Epoch 6/100
139/139 [==============================] - 0s 777us/step - loss: 5.1137
Epoch 7/100

...

Epoch 96/100
139/139 [==============================] - 0s 1ms/step - loss: 0.0378
Epoch 97/100
139/139 [==============================] - 0s 931us/step - loss: 0.0468
Epoch 98/100
139/139 [==============================] - 0s 821us/step - loss: 0.0808
Epoch 99/100
139/139 [==============================] - 0s 745us/step - loss: 0.1535
Epoch 100/100
139/139 [==============================] - 0s 793us/step - loss: 0.0493
<tensorflow.python.keras.callbacks.History at 0x260b7b33c70>
>>> pred = (model.predict(X_test_std) * std_key) + mean_key
>>> pred = pred.reshape(pred.shape[0])
>>> print("Accuracy:", np.sqrt(np.sum((y_test - pred)**2))/len(y_test))
Accuracy: 0.9916198414587479
  • 데이터 셋만 바꿨는데, 이전 데이터 셋의 정확도(Accuracy)가 209.243에서 0.9916으로 큰 폭으로 떨어진 것을 볼 수 있다.
  • 실제 예측 결과가 어떻게 생겼는지 확인해보자.
result_DF = pd.DataFrame({"predict":pred, "label":y_test})
result_DF["gap"] = result_DF["label"] - result_DF["predict"]
result_DF

  • 차이가 있긴 하지만, 실제 데이터와 상당히 가까워졌다.
  • 이번엔 데이터의 양을 늘려서 학습시켜보자.

 

 

 

 

3. 데이터의 양을 늘려보자.

# Import Module
import pandas as pd
import numpy as np
from tensorflow import keras
from tensorflow.keras.layers import Dense




# Dataset 만들기
np.random.seed(1234)

def f2(x1, x2):
    
    return 0.5*x1**2 - 3*x2 + 5

X1 = np.random.randint(0, 100, (30000))
X2 = np.random.randint(0, 100, (30000))
X = np.c_[X1, X2]
y = f2(X1, X2)

# 데이터셋을 중복되지 않게 만든다.
Xy = np.c_[X, y]
Xy = np.unique(Xy, axis = 0)
np.random.shuffle(Xy)
test_len = int(np.ceil(len(Xy)*0.2))
X = Xy[:, [0,1]]
y = Xy[:, 2]

# test Dataset과 train Dataset으로 나누기
X_test = X[:test_len]
y_test = y[:test_len]

X_train = X[test_len:]
y_train = y[test_len:]




# make model
model = keras.Sequential()
model.add(Dense(32, activation = 'elu'))
model.add(Dense(32, activation = 'elu'))
model.add(Dense(1, activation = 'linear'))


# Compile
opt = keras.optimizers.Adam(learning_rate=0.005)
model.compile(optimizer=opt, loss='mse')


# min-max scaling
min_key = np.min(X_train)
max_key = np.max(X_train)

X_train_std = (X_train - min_key)/(max_key - min_key)
y_train_std = (y_train - min_key)/(max_key - min_key)

X_test_std = (X_test - min_key)/(max_key - min_key)
>>> model.fit(X_train_std, y_train_std, epochs = 100)

Epoch 1/100
238/238 [==============================] - 1s 970us/step - loss: 168.8257
Epoch 2/100
238/238 [==============================] - 0s 1ms/step - loss: 4.6773A: 0s - loss: 5.8
Epoch 3/100
238/238 [==============================] - 0s 821us/step - loss: 1.2054
Epoch 4/100
238/238 [==============================] - 0s 842us/step - loss: 0.4222
Epoch 5/100
238/238 [==============================] - 0s 781us/step - loss: 0.1056
Epoch 6/100
238/238 [==============================] - 0s 851us/step - loss: 0.0459

...

Epoch 96/100
238/238 [==============================] - 0s 736us/step - loss: 4.2894e-04
Epoch 97/100
238/238 [==============================] - 0s 741us/step - loss: 5.0023e-04
Epoch 98/100
238/238 [==============================] - 0s 720us/step - loss: 0.0046
Epoch 99/100
238/238 [==============================] - 0s 749us/step - loss: 0.0036
Epoch 100/100
238/238 [==============================] - 0s 812us/step - loss: 0.0189
<tensorflow.python.keras.callbacks.History at 0x24611ae5910>
>>> pred = (model.predict(X_test_std) * (max_key - min_key)) + min_key
>>> pred = pred.reshape(pred.shape[0])
>>> print("Accuracy:", np.sqrt(np.sum((y_test - pred)**2))/len(y_test))
Accuracy: 0.03539701825569002
result_DF = pd.DataFrame({"predict":pred, "label":y_test})
result_DF["gap"] = result_DF["label"] - result_DF["predict"]
result_DF

  • 중복을 제거하여 데이터의 양을 953개에서 9,493개로 늘렸다.
  • 그로 인해 Accuracy가 0.9916에서 0.0353으로 감소하여, 정확도가 보다 올라갔다.
  • 이상치가 존재하지 않는 데이터이므로, 최소-최대 스케일 변환(min-max scaling)을 이용해 표준화를 시켰다. 그로 인해, Accuracy가 크게 변하지는 않았으나, 이전에 비해 손실 값이 빠르게 0에 수렴하는 것을 볼 수 있다.
  • 활성화 함수를 relu가 아닌 elu를 사용하였다. 성능 차이가 그리 크지는 않으나, 손실 값과 Accuracy에 긍정적인 영향을 미쳤다.
  • 네트워크의 노드 수와 Layer의 수를 바꿨다.

 

 

 

 지금까지 변수가 2개인 데이터 셋을 학습시키는 과정을 해보았다. 숨어있는 패턴이 복잡하고 변수의 수가 늘어났더니, 처음 보는 영역에 있는 데이터를 제대로 분류하지 못하는 현상이 발생하였다.

 이 때는 학습 데이터셋에 시험 데이터셋과 유사한 데이터 셋을 포함시키는 것이 가장 좋은 해결 방법이다. 위처럼 시험 데이터 셋과 학습 데이터 셋이 중복되지 않는다 할지라도, 유사한 영역에 있는 경우 제대로 예측하는 것을 볼 수 있다.

728x90
반응형

+ Recent posts