[플레이데이터 SK네트웍스 Family AI 캠프 10기] 10주차 회고

문승기·2025년 3월 14일
0

SK네트웍스 Family AI캠프 10기 10주차 회고록 (25.03.10 ~ 25.03.14)

기간: 25.03.10 ~ 25.03.14


학습 내용 요약

이번 주는 딥러닝 모델들에 대한 이해를 높이기 위해 CNN, RNN, LSTM 모델을 각각 분류 문제와 회귀 문제에 적용하는 예제를 실습했다.

1. CNN (Convolutional Neural Network)

1.1. 분류 문제 (MNIST 데이터셋)

CNN 모델은 이미지 분류에 매우 효과적이다. Conv2D 레이어를 통해 이미지에서 중요한 특징을 추출하고, MaxPooling2D 레이어를 사용하여 특징 맵의 크기를 축소한 뒤, Dense 레이어로 분류를 진행한다. 이를 통해 MNIST 데이터셋의 이미지 분류 문제를 해결하는 예제이다.

모델 정의 예제 (MNIST 데이터셋)
import tensorflow as tf
from tensorflow.keras import layers, models

# Conv2D 레이어 클래스 정의
class Conv2DLayer(layers.Layer):
    def __init__(self, filters, kernel_size, activation='relu'):
        super(Conv2DLayer, self).__init__()
        self.conv = layers.Conv2D(filters, kernel_size, activation=activation)
        self.pool = layers.MaxPooling2D((2, 2))

    def call(self, inputs):
        x = self.conv(inputs)
        return self.pool(x)

# Fully Connected 레이어 클래스 정의
class FullyConnectedLayer(layers.Layer):
    def __init__(self, units, activation='relu'):
        super(FullyConnectedLayer, self).__init__()
        self.dense = layers.Dense(units, activation=activation)

    def call(self, inputs):
        return self.dense(inputs)

# CNN 모델 클래스 정의
class CNNModel(models.Model):
    def __init__(self):
        super(CNNModel, self).__init__()
        self.conv1 = Conv2DLayer(32, (3, 3))
        self.conv2 = Conv2DLayer(64, (3, 3))
        self.flatten = layers.Flatten()
        self.fc1 = FullyConnectedLayer(64)
        self.fc2 = FullyConnectedLayer(10, activation='softmax')  # 10개의 클래스 분류

    def call(self, inputs):
        x = self.conv1(inputs)
        x = self.conv2(x)
        x = self.flatten(x)
        x = self.fc1(x)
        return self.fc2(x)

# 모델 생성
model = CNNModel()
model.build((None, 28, 28, 1))  # MNIST 이미지 크기

# 모델 컴파일
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])

1.2. 회귀 문제 (Boston Housing 데이터셋)

회귀 문제에서는 출력층에서 선형 활성화 함수를 사용하여 연속적인 값을 예측하도록 설정했다. CNN 모델을 회귀 문제에 맞게 조정하여 Boston Housing 데이터셋에서 주택 가격 예측 문제를 해결하는 예제이다.

모델 정의 예제 (Boston Housing 데이터셋)
class CNNRegressor(models.Model):
    def __init__(self):
        super(CNNRegressor, self).__init__()
        self.conv1 = Conv2DLayer(32, (3, 3))
        self.conv2 = Conv2DLayer(64, (3, 3))
        self.flatten = layers.Flatten()
        self.fc1 = FullyConnectedLayer(64)
        self.fc2 = FullyConnectedLayer(1)  # 회귀 문제: 선형 활성화 함수

    def call(self, inputs):
        x = self.conv1(inputs)
        x = self.conv2(x)
        x = self.flatten(x)
        x = self.fc1(x)
        return self.fc2(x)

# 모델 생성
model = CNNRegressor()
model.build((None, 28, 28, 1))

# 모델 컴파일
model.compile(optimizer='adam', loss='mean_squared_error')

2. RNN (Recurrent Neural Network)

2.1. 분류 문제 (IMDB 영화 리뷰 데이터셋)

RNN 모델은 시퀀스 데이터에서 시간적인 의존성을 학습하는 데 강점이 있다. SimpleRNN 레이어를 사용하여 텍스트 데이터를 시퀀스별로 처리하고, Dense 레이어를 사용하여 이진 분류 문제를 해결하는 예제이다.

모델 정의 예제 (IMDB 영화 리뷰 데이터셋)
class RNNLayer(layers.Layer):
    def __init__(self, units, activation='relu'):
        super(RNNLayer, self).__init__()
        self.rnn = layers.SimpleRNN(units, activation=activation)

    def call(self, inputs):
        return self.rnn(inputs)

class FullyConnectedLayer(layers.Layer):
    def __init__(self, units, activation='relu'):
        super(FullyConnectedLayer, self).__init__()
        self.dense = layers.Dense(units, activation=activation)

    def call(self, inputs):
        return self.dense(inputs)

class RNNModel(models.Model):
    def __init__(self):
        super(RNNModel, self).__init__()
        self.embedding = layers.Embedding(10000, 128, input_length=500)
        self.rnn1 = RNNLayer(128)
        self.fc1 = FullyConnectedLayer(64)
        self.fc2 = FullyConnectedLayer(1, activation='sigmoid')  # 이진 분류

    def call(self, inputs):
        x = self.embedding(inputs)
        x = self.rnn1(x)
        x = self.fc1(x)
        return self.fc2(x)

# 모델 생성
model = RNNModel()

# 모델 컴파일
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

2.2. 회귀 문제 (시계열 예측)

회귀 문제에서는 RNN을 시계열 데이터에 적용하여 연속적인 값을 예측하는 모델을 구현하는 예제이다. 출력층에서 선형 활성화 함수를 사용하여 시계열 예측 문제를 해결한다.

모델 정의 예제 (시계열 예측)
class RNNRegressor(models.Model):
    def __init__(self):
        super(RNNRegressor, self).__init__()
        self.embedding = layers.Embedding(10000, 128, input_length=500)
        self.rnn1 = RNNLayer(128)
        self.fc1 = FullyConnectedLayer(64)
        self.fc2 = FullyConnectedLayer(1)  # 회귀 문제: 선형 활성화 함수

    def call(self, inputs):
        x = self.embedding(inputs)
        x = self.rnn1(x)
        x = self.fc1(x)
        return self.fc2(x)

# 모델 생성
model = RNNRegressor()

# 모델 컴파일
model.compile(optimizer='adam', loss='mean_squared_error')

3. LSTM (Long Short-Term Memory)

3.1. 분류 문제 (IMDB 영화 리뷰 데이터셋)

LSTM은 RNN의 개선된 버전으로, 장기 의존성 문제를 해결할 수 있는 모델이다. LSTM 레이어를 사용하여 텍스트 데이터의 시퀀스를 처리하고, Dense 레이어를 통해 이진 분류 문제를 해결하는 예제이다.

모델 정의 예제 (IMDB 영화 리뷰 데이터셋)
class LSTMLayer(layers.Layer):
    def __init__(self, units, activation='relu'):
        super(LSTMLayer, self).__init__()
        self.lstm = layers.LSTM(units, activation=activation)

    def call(self, inputs):
        return self.lstm(inputs)

class FullyConnectedLayer(layers.Layer):
    def __init__(self, units, activation='relu'):
        super(FullyConnectedLayer, self).__init__()
        self.dense = layers.Dense(units, activation=activation)

    def call(self, inputs):
        return self.dense(inputs)

class LSTMModel(models.Model):
    def __init__(self):
        super(LSTMModel, self).__init__()
        self.embedding = layers.Embedding(10000, 128, input_length=500)
        self.lstm1 = LSTMLayer(128)
        self.fc1 = FullyConnectedLayer(64)
        self.fc2 = FullyConnectedLayer(1, activation='sigmoid')  # 이진 분류

    def call(self, inputs):
        x = self.embedding(inputs)
        x = self.lstm1(x)
        x = self.fc1(x)
        return self.fc2(x)

# 모델 생성
model = LSTMModel()

# 모델 컴파일
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

3.2. 회귀 문제 (시계열 예측)

LSTM을 사용하여 시계열 데이터를 처리하고, Dense 레이어에서 선형 활성화 함수를 사용하여 연속적인 값을 예측하는 모델을 구현하는 예제이다.

모델 정의 예제 (시계열 예측)
class LSTMRegressor(models.Model):
    def __init__(self):
        super(LSTMRegressor, self).__init__()
        self.embedding = layers.Embedding(10000, 128, input_length=500)
        self.lstm1 = LSTMLayer(128)
        self.fc1 = FullyConnectedLayer(64)
        self.fc2 = FullyConnectedLayer(1)  # 회귀 문제: 선형 활성화 함수

    def call(self, inputs):
        x = self.embedding(inputs)
        x = self.lstm1(x)
        x = self.fc1(x)
        return self.fc2(x)

# 모델 생성
model = LSTMRegressor()

# 모델 컴파일
model.compile(optimizer='adam', loss='mean_squared_error')

트러블 슈팅

- 왜 어휘집(Vocabulary)은 Train Dataset으로 만들어야 할까?

자연어 처리(NLP)에서 어휘집(Vocabulary)이란 **텍스트 데이터를 토큰화한

후, 등장한 단어(또는 서브워드, 문자 등)에 대해 인덱스를 부여한 목록을 의미한다. 이 어휘집을 생성할 때 Train Dataset을 기반으로 하는 것이 중요한 이유**는 다음과 같다.


1. 모델이 학습하는 데이터와 일관성을 유지하기 위해
  • 모델이 학습하는 과정에서 어휘집은 입력 데이터를 수치화하는 기준이 된다.
  • 학습 시 사용되지 않은 단어가 예측(테스트) 시 포함되면, 해당 단어는 어휘집에 없는 단어(OOV, Out-Of-Vocabulary)가 되어 처리할 수 없거나 성능이 떨어질 가능성이 높다.
  • 따라서, Train Dataset에 있는 단어들만을 기준으로 어휘집을 만들어야 모델이 안정적으로 학습할 수 있다.

2. 테스트 데이터에서 발생하는 데이터 누수(Data Leakage) 방지
  • 테스트 데이터(Test Dataset)를 어휘집 생성 과정에 포함하면, 모델이 테스트 데이터를 "미리 본 것"과 같은 효과를 낼 수 있다.
  • 즉, 학습 단계에서 본 적 없는 단어가 평가 단계에서 나오는 것이 자연스러워야 하지만, 만약 어휘집을 테스트 데이터를 포함해서 만든다면, 테스트 데이터에서 나온 단어도 학습 데이터처럼 취급되어 모델 성능이 왜곡될 위험이 있다.
  • 이런 상황을 데이터 누수(Data Leakage)라고 하며, 모델의 실제 성능을 과대평가할 가능성이 높다.

3. 일반적인 NLP 파이프라인에서는 Train Dataset을 기준으로 단어 임베딩을 생성
  • 어휘집은 단순한 단어 목록이 아니라, 각 단어를 고유한 인덱스로 변환하는 역할을 한다.
  • 대부분의 NLP 모델(예: Word2Vec, FastText, BERT 등)에서도 어휘집을 훈련 데이터(Train Dataset)에서만 만들고, 이후 등장하지 않은 단어는 <unk>(unknown token)으로 처리한다.
  • 이는 모델이 훈련된 데이터에서 학습한 의미를 유지하면서, 새로운 데이터에서도 유사한 패턴을 찾을 수 있도록 일반화하는 데 도움을 준다.

정리 (결론)
  • 어휘집은 Train Dataset을 기반으로 만들어야 한다.
  • 이유 1️⃣: 모델이 학습하는 데이터와 일관성을 유지하기 위해
  • 이유 2️⃣: 데이터 누수(Data Leakage)를 방지하여 모델 평가를 정확하게 하기 위해
  • 이유 3️⃣: 일반적인 NLP 파이프라인에서 단어 임베딩을 학습 데이터 기준으로 생성하기 때문

따라서, NLP 프로젝트에서 어휘집을 만들 때는 반드시 Train Dataset을 기준으로 생성해야 하며, Test Dataset을 포함해서는 안 된다.


- CNN 1D Model 구조 설명

CNN 1D(1차원 합성곱 신경망)는 자연어 처리(NLP)에서 문장을 벡터로 변환하고, 의미 있는 특징을 추출하여 분류하는 데 사용되는 모델이다. 이 모델의 주요 구조는 3가지 주요 레이어로 구성된다.


1. Embedding Layer (임베딩 레이어)

📖 역할

  • 자연어 데이터(텍스트)를 벡터로 변환하는 과정
  • 텍스트 데이터는 숫자로 이루어지지 않았기 때문에, 모델이 학습할 수 있도록 각 단어(토큰)를 의미 있는 숫자로 변환하는 과정이 필요하다.
  • 단어 간의 유사한 의미를 반영할 수 있도록 고차원 공간에서 벡터로 표현한다.

🛠 작동 방식

  • 입력: 토큰화된 데이터 (단어가 숫자 인덱스로 변환됨)
  • 출력: 각 단어를 n 차원의 벡터로 변환 (예: 128차원)

2. CNN 1D Layer (합성곱 신경망, 특징 추출)

📖 역할

  • 문장의 중요한 특징을 학습하여 패턴을 찾는 과정
  • 단어 벡터에서 중요한 부분(예: 감정을 나타내는 단어, 주요 의미어)을 자동으로 추출한다.
  • 1D CNN을 사용하면, 연속된 단어들의 관계를 고려하면서 의미를 학습할 수 있다.

3. Fully Connected Layer (FC Layer, 분류)

📖 역할

  • CNN 1D Layer에서 추출된 특징을 최종적으로 학습하여 감정(긍정/부정)을 예측
  • 문장을 하나의 숫자로 변환하여 예측할 수 있도록 한다.

apply() vs map() 차이점

기능apply()map()
DataFrame 전체 적용✅ 가능❌ 불가능 (Series만 가능)
여러 열(column) 활용 가능✅ 가능❌ 불가능
행(row) 단위 연산 (axis=1)✅ 가능❌ 불가능
단일 열 변환가능가능

👉 결론: reviewTitlereviewDescription합치는 작업은 여러 열을 활용하므로 apply()를 사용해야 한다.


KPT 회고 (10주차)

Keep (계속 유지할 점)

  • 꾸준히 운동을 다니며 건강을 유지하고, 학습을 이어가는 일정을 잘 관리하는 점.
  • 딥러닝 모델에 대한 이해도가 점차 향상되고 있어, 계속해서 이 방향으로 공부를 이어가는 점.

Problem (개선이 필요한 점)

  • 토익 공부를 제대로 못하고 있어서 불안하다. 시간을 더 효율적으로 활용해야 한다.
  • 딥러닝 개념에서 여전히 이해가 부족한 부분이 있어, 더 많은 예제를 통해 이론을 보강할 필요가 있다.

Try (앞으로 시도할 것)

  • 토익 공부를 위해 매일 일정 시간을 투자하고, 목표를 설정해 학습 계획을 다시 세우기로 했다.
  • 딥러닝부터 어려운 개념을 다시 복습하고, 실험을 통해 더 깊이 이해하려 노력할 것이다.

마무리

  • 이번 주는 딥러닝 모델을 여러 가지 실습을 통해 더 잘 이해하게 되었으며, 특히 모델 설계에 있어 클래스 기반으로 레이어를 정의하는 방법을 익혔다. 너무나 어려웠고, 개념이 제대로 이해되지 않으니 코드로 작성하는 것 또한 불가능했다.
  • 다만, 토익 공부와 딥러닝 개념 복습을 병행해야 하므로, 효율적으로 시간을 관리하는 것이 중요하다고 생각되었다. 또한, 효율적으로 잘 공부하기 위해 데이콘 사이트를 구독하여 자체 학습자료를 통해 필요한 공부만 하며 복습을 진행하고자 한다.
profile
AI 모델을 개발하여 이를 활용한 서비스를 개발하고 운영하는 개발자가 되기 위해 꾸준히 노력하겠습니다!

0개의 댓글