본문 바로가기
AI SCHOOL/TIL

[DAY 74] Tensorflow를 활용한 자동차 연비 회귀 예측

2023. 4. 11.

Tensorflow를 활용하여 자동차 연비 회귀 예측을 했다.

Kaggle의 Mercedes-Benz Greener Manufacturing 데이터를 사용하며 딥러닝 동작 과정을 이해해 봤다.

데이터 준비

데이터 로드
pandas를 이용하여 train set, test set을 로드했다.

train = pd.read_csv('train.csv.zip', index_col="ID")
test = pd.read_csv('test.csv.zip', index_col="ID")
train.shape, test.shape

# 실행 결과
((4209, 377), (4209, 376))

Mercedes-Benz Greener Manufacturing 데이터는 학습용, 예측용 데이터 비율이 1:1이다.

train
train

타깃은 연비 값이므로 float, 8개 변수는 object, 나머지는 numeric 데이터로 이루어져 있다.

categorical 범주형 변수들을 category 타입으로 변경

categorical_feature = train.select_dtypes(exclude='number').columns
categorical_feature

# 실행 결과
Index(['X0', 'X1', 'X2', 'X3', 'X4', 'X5', 'X6', 'X8'], dtype='object')

위 8개 변수를 category 타입으로 변경해 준다.

train[categorical_feature] = train[categorical_feature].astype("category")
test[categorical_feature] = test[categorical_feature].astype("category")

train set, test set 각각 변경 완료

인코딩

from sklearn.preprocessing import OrdinalEncoder

OrdinalEncoder를 사용하여 인코딩한다.

oe = OrdinalEncoder(handle_unknown='use_encoded_value', unknown_value=-1)
train[categorical_feature] = oe.fit_transform(train[categorical_feature])
test[categorical_feature] = oe.transform(test[categorical_feature])

handle_unknown은 알 수 없는 카테고리의 인코딩 값 처리를 설정한다. 'use_encoded_value'로 설정하면 매개변수 unknown_value에 지정한 값으로 처리된다. 여기서는 -1이다.
train에 fit_transform, test에 transform을 통해 인코딩을 했다.

encoded

모두 숫자형 데이터로 변경된 것을 확인할 수 있다.

X, y 만들기

X = train.drop('y', axis=1)
y = train['y']

X.shape, y.shape

# 실행 결과
((4209, 376), (4209,))

y는 target, X는 target을 제외한 컬럼을 사용한다.

train_test_split
Hold-out validation을 위해 분할한다.

from sklearn.model_selection import train_test_split
X_train, X_valid, y_train, y_valid = train_test_split(X, y,
                                                      test_size=0.1, 
                                                      random_state=42)

X_train.shape, X_valid.shape, y_train.shape, y_valid.shape

# 실행 결과
((3788, 376), (421, 376), (3788,), (421,))

train 9 valid 1의 비율로 분할되었다. X_test는 test를 그대로 사용한다.

딥러닝 모델 사용

모델 생성

import tensorflow as tf
model = tf.keras.Sequential([
    tf.keras.layers.BatchNormalization(input_shape=X_train.iloc[0].shape),
    tf.keras.layers.Dense(units=128, activation='relu'),
    tf.keras.layers.Dense(units=64, activation='relu'),
    tf.keras.layers.Dense(units=1)
])

Tensorflow Keras API를 사용하여 모델을 생성했다. BatchNormalization 적용하는 입력층, 각각 unit 128개와 64개인 hidden layer 2개 층, 출력 층으로 구성했다. 활성화 함수는 ReLU를 지정했다.

모델 컴파일

optimizer = tf.keras.optimizers.RMSprop(0.001)
model.compile(loss='mse',
                optimizer=optimizer,
                metrics=['mae', 'mse'])

컴파일 단계에서 모델 훈련 전 몇 가지 설정이 추가된다. 옵티마이저, 측정 지표, 손실 함수를 지정했다.

model.summary()

# 실행 결과
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 batch_normalization (BatchN  (None, 376)              1504      
 ormalization)                                                   
                                                                 
 dense (Dense)               (None, 128)               48256     
                                                                 
 dense_1 (Dense)             (None, 64)                8256      
                                                                 
 dense_2 (Dense)             (None, 1)                 65        
                                                                 
=================================================================
Total params: 58,081
Trainable params: 57,329
Non-trainable params: 752
_________________________________________________________________

summary()를 통해 모델 구조를 확인할 수 있다.

모델 학습

early_stop = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=30)

history = model.fit(X_train, y_train, 
                    epochs=1000, validation_data=(X_valid, y_valid),
                    callbacks=[early_stop], verbose=0)

model에 학습 데이터를 fit 한다. 모델 학습 epoch는 총 1000회인데 그 과정에서 validation loss가 30회 이상 더 개선되지 않을 때 학습을 조기 종료한다.

df_hist = pd.DataFrame(history.history)
df_hist.tail()

학습 과정에서 저장된 metric들을 데이터프레임으로 만들어 확인해 본다.

tail

loss와 val_loss를 시각화하면 아래와 같다.

loss

빠른 조기 종료가 된 것 같다.

모델 평가

y_valid_pred = model.predict(X_valid).flatten()
sns.jointplot(x=y_valid, y=y_valid_pred, kind='reg')

X_valid에 대한 예측을 한 후, seaborn의 jointplot을 그려서 확인한다.

joint

언뜻 봐도 제대로 예측한 것 같지 않다.

score = r2_score(y_valid, y_valid_pred)
score

# 실행 결과
-0.33964473547467877

r2_score를 구해본 결과 약 -0.33964를 확인했다. 매우 잘못 예측하여 음수가 나왔다.
실제로 kaggle에 해당 모델을 통한 예측값을 제출한 결과 public score -0.32061, private score -0.81462를 받았다.
이후 정규화 생략, 층 개수 변경, 유닛 수 변경 등 모델을 다른 구성으로 다시 생성하고 사용해서 스코어를 약 0.4까지 올리는 데 성공했지만, 만족스럽진 못했다.
정형 데이터는 머신러닝 모델을 사용하는 것이 더 유리하며 딥러닝은 비정형 데이터에 주로 사용한다는 말이 생각났다.

Tensorflow활용 후 PyTorch에 대한 강의가 잠깐 이어졌다.
동작 과정은 같은 것 같은데 API가 달라지니 정말 어렵게 느껴졌다. 시간을 많이 들여야 할 것 같다.
미니프로젝트5 안내를 받았다. 이번 미니프로젝트를 통해 딥러닝에 대한 연습을 확실히 해야겠다.

반응형

댓글