안녕하세요, '소프트웨어 공장'에 오신 것을 환영합니다!
지난 포스팅에서는 눈으로 보는 이미지 데이터를 다루는 CNN 모델을 함께 만들어 보았습니다. 이번에는 우리가 매일 쓰는 '말'과 '글', 즉 텍스트 데이터를 컴퓨터가 처리하도록 만드는 '자연어 처리(NLP)'의 세계로 떠나보려 합니다. 챗봇, 자동 번역기, 스팸 메일 필터링 등 이미 우리 삶 깊숙이 자리 잡은 핵심 기술이기도 하죠.
자연어 처리는 컴퓨터가 이해하기 힘든 텍스트를 숫자로 바꾸고, 문맥의 앞뒤 흐름을 파악해야 해서 이미지 처리와는 또 다른 접근법이 필요합니다. 이번 글에서는 텍스트 데이터를 처리하는 기본적인 원리를 이해하고, 글로벌 벤치마크 데이터셋인 IMDB 영화 리뷰 데이터를 활용해 리뷰가 긍정적인지 부정적인지 기가 막히게 맞추는 감정 분석 딥러닝 모델을 직접 구현해 보겠습니다. 파이썬과 텐서플로우만 있다면 어렵지 않으니 바로 시작해 볼까요?

📌 핵심 요약 3줄
- 개념 파악: 인간의 언어(자연어)를 컴퓨터가 연산할 수 있는 수학적 공간으로 매핑하고 이해하는 NLP의 기본 원리를 배웁니다.
- 텍스트 전처리: 문장의 길이를 통일하는 패딩(Padding) 작업과 단어를 고차원 벡터로 바꾸는 임베딩(Embedding) 레이어를 이해합니다.
- 시퀀스 모델링: 순서가 중요한 데이터 학습에 탁월한 LSTM(순환 신경망) 구조를 설계하여 영화 리뷰 감정 분석 파이프라인을 완성합니다.
🔤 자연어 처리 파이프라인 핵심 요소 정리
컴퓨터는 '재미있다', '지루하다' 같은 단어를 그대로 계산할 수 없습니다. 텍스트를 정밀한 수학적 벡터로 바꾸고 문맥을 파악하기 위해 사용하는 핵심 기법과 레이어 정보를 아래 표로 정리했습니다.
| 파이프라인 단계 / 기술 | 주요 역할 | 상세 설명 및 특징 |
| 토큰화 (Tokenization) | 문장 쪼개기 | 문장을 단어, 형태소, 혹은 글자 단위로 나누어 모델이 처리할 수 있는 최소 단위로 분리 |
| 패딩 (Padding) | 데이터 크기 일치 | 서로 길이가 다른 리뷰 문장들의 길이를 맞춰주기 위해 빈 공간을 0으로 채우는 작업 |
| 임베딩 (Embedding) 레이어 | 단어의 벡터화 | 고정된 정수 인덱스를 서로의 의미적 유사도가 반영된 고차원 밀집 벡터(Dense Vector)로 변환 |
| LSTM 레이어 | 문맥 및 시퀀스 학습 | RNN의 장기 의존성(Long-Term Dependency) 문제를 해결하여 긴 문장 속 흐름을 왜곡 없이 기억 |
| Dense (Sigmoid) 레이어 | 이진 분류 판단 | 모델의 마지막 출력층으로, 값이 0.5 이상이면 긍정(1), 이하면 부정(0)의 확률 도출 |
🎬 딥러닝 예제: 영화 리뷰 감정 분석 모델 만들기
이제 TensorFlow와 Keras를 조합해 실제 영화 리뷰 텍스트가 담긴 IMDB 데이터셋을 분류하는 감정 분석(Sentiment Analysis) 모델을 만들어보겠습니다.
① 환경 설정 및 모듈 로드
파이썬 환경에 텐서플로우 패키지가 설치되어 있지 않다면 먼저 터미널에 pip install tensorflow를 실행해 줍니다. 설치가 끝났다면 전처리와 모델 빌드에 필요한 모듈들을 불러옵니다.
import tensorflow as tf
from tensorflow.keras import datasets, layers, models, preprocessing
② 데이터셋 로드 및 패딩 전처리
IMDB 데이터셋은 각 단어가 이미 빈도수 순위에 맞는 정수 인덱스로 인코딩되어 있어서 관리가 편합니다. 문장 길이를 일정하게 맞추는 패딩 작업을 꼭 거쳐야 합니다.
# 1. 빈도수 상위 10,000개의 단어만 남기고 IMDB 영화 리뷰 데이터셋 로드
(train_data, train_labels), (test_data, test_labels) = (
datasets.imdb.load_data(num_words=10000)
)
# 2. 모든 문장의 길이를 256 단어로 통일 (짧으면 0으로 채우고, 길면 자릅니다)
train_data = preprocessing.sequence.pad_sequences(train_data, maxlen=256)
test_data = preprocessing.sequence.pad_sequences(test_data, maxlen=256)
③ LSTM 딥러닝 모델 아키텍처 설계
시퀀스 데이터 학습에 강력한 LSTM(Long Short-Term Memory) 신경망을 구조화합니다.
# Sequential 모델 객체 정의
model = models.Sequential()
# 10,000개의 단어 사량을 32차원의 밀집 벡터 공간으로 매핑하는 임베딩 층 추가
model.add(layers.Embedding(10000, 32))
# 문장의 흐름과 맥락을 기억하는 32개 셀 규모의 LSTM 레이어 배치
model.add(layers.LSTM(32))
# 긍정/부정 이진 분류를 처리하기 위해 최종 출력층 뉴런 1개와 시그모이드 함수 지정
model.add(layers.Dense(1, activation="sigmoid"))
④ 모델 컴파일 및 학습
이진 분류 문제에 맞는 손실 함수와 옵티마이저를 세팅하고 학습을 돌려보겠습니다.
# 컴파일 세팅: 이진 분류이므로 binary_crossentropy를 채택합니다.
model.compile(
optimizer="adam", loss="binary_crossentropy", metrics=["accuracy"]
)
# 5바퀴(Epochs) 동안 학습을 수행하며 테스트 데이터셋으로 검증을 병행합니다.
model.fit(
train_data,
train_labels,
epochs=5,
batch_size=64,
validation_data=(test_data, test_labels),
)
⑤ 모델 평가 및 임의의 리뷰 예측 테스트
학습 완료 후 테스트 데이터셋을 통해 최종 정확도를 뽑아내고, 샘플 하나를 가져와 모델이 판단한 결과를 한글 문장으로 보기 좋게 출력해 보겠습니다.
# 테스트 데이터셋을 기반으로 오차와 정확도 검증
test_loss, test_acc = model.evaluate(test_data, test_labels, verbose=2)
print(f"\n🎯 최종 테스트 정확도: {test_acc:.4f}")
# 첫 번째 테스트 리뷰 데이터를 가져와 2차원 배열 형태로 가공 후 예측 진행
sample_review = test_data[0].reshape(1, -1)
prediction = model.predict(sample_review)
print(f"\n📊 모델의 예측 확률 값: {prediction[0][0]:.4f}")
# 시그모이드 출력값이 0.5 이상이면 긍정, 미만이면 부정으로 최종 해석합니다.
if prediction >= 0.5:
print("✨ 결과 분석: 긍정적인 영화 리뷰입니다.")
else:
print("💧 결과 분석: 부정적인 영화 리뷰입니다.")
🛠️ 개발을 위한 팁 (Tips for Developers)
- 사전 학습된 임베딩(Word2Vec/FastText) 활용 고려: 데이터셋의 규모가 작을 때는 내 프로젝트 내부에서 임베딩 레이어를 처음부터 새로 학습시키는 것보다, Google이나 Meta 등이 대용량 위키피디아 문서 데이터로 미리 학습시켜 둔 사전 학습 가중치(Pre-trained Word Embedding)를 로드해 사용하는 것이 성능 면에서 압도적으로 훌륭할 수 있습니다.
- pad_sequences의 위치 설정 옵션 튜닝: 패딩 함수는 기본적으로 문장 '앞(pre)'에 0을 채웁니다. 만약 문장 '뒤(post)'에 0을 채우고 싶다면 padding='post' 속성을 주어야 합니다. LSTM 같은 RNN 계열은 문장 후반부 데이터에 더 민감하게 반응하는 경향이 있으므로, 패딩 위치 옵션 하나만 바꿔도 모델의 학습 양상이 눈에 띄게 달라집니다.
- 텍스트 전처리 함수 전용 모듈화: 실제 프로덕션 환경에서는 유저가 날것으로 입력한 텍스트 문장이 들어옵니다. 이를 인덱스 숫자로 변환하는 과정에서 사전에 정의한 Tokenizer 객체를 로컬 디스크에 잘 직렬화(Pickle 등)해서 저장해 두어야 나중에 추론(Inference) 서버를 띄울 때 데이터 꼬임 없이 원활하게 서비스할 수 있습니다.
⚠️ 흔히 하는 실수 (Common Mistakes)
- 테스트 데이터를 전처리할 때 새로운 토크나이저 생성: 학습 데이터에 적용했던 단어 사전 인덱스와 테스트 데이터에 적용하는 단어 사전 인덱스는 완벽하게 같아야 합니다. 테스트 데이터 세트를 인코딩할 때 Tokenizer 객체를 새로 만들어서 피팅(fit_on_texts)을 다시 해버리면 단어 번호가 꼬여 정확도가 0%에 가깝게 폭락하게 되니 주의하세요.
- 이진 분류 출력층의 뉴런 개수와 손실 함수 불일치: 마지막 출력층에 Dense(1, activation='sigmoid')를 썼다면 손실 함수는 무조건 binary_crossentropy가 짝꿍입니다. 만약 뉴런을 2개로 잡고 상호 확률을 비교하고 싶다면 Dense(2, activation='softmax')를 선언하고 손실 함수를 categorical_crossentropy 계열로 명시해야 충돌 에러가 나지 않습니다.
- LSTM 입력 데이터의 3차원 텐서 구조 오해: Keras의 Embedding 레이어를 거치면 자동으로 (Batch_size, Sequence_length, Embedding_dim) 형태의 3차원 텐서가 완성되어 LSTM으로 부드럽게 흘러 들어갑니다. 하지만 임베딩 레이어를 거치지 않고 직접 수치 데이터를 만들어 LSTM에 던져줄 때는 이 3차원 형상을 개발자가 reshape로 직접 명시해 주지 않으면 구조 불일치 컴파일 에러를 마주하게 됩니다.
🏁 마치며
오늘 포스팅에서는 이미지 픽셀과는 전혀 다른 결을 가진 자연어 텍스트 데이터를 컴퓨터에게 학습시키는 NLP의 기본 개념 노선부터 시작해서 문장 길이를 자르고 늘려주는 패딩 처리, 단어의 숨은 뜻을 좌표로 정렬하는 Embedding 기법, 그리고 긴 문맥 흐름을 유연하게 학습하는 LSTM 신경망까지 깊이 있게 관통해 보았습니다.
인간의 복잡 미묘한 감정이 담긴 문자열을 단 몇 줄의 파이썬 코드로 분석해 내는 과정이 참 흥미롭지 않으셨나요?
오늘 예제를 실행해 보시다가 텍스트 셰이프가 안 맞거나, 패키지 버전 스펙 탓에 경고 메시지가 터진다면 언제든지 아래 댓글창에 로그를 남겨주세요. 같이 시원하게 뚫어드리겠습니다. 오늘도 열공하시느라 고생 많으셨습니다!
'Python for AI, Embedded > Python: Core & Automation' 카테고리의 다른 글
| 파이썬 배포 가이드: PyInstaller로 EXE 실행 파일 만들기 (onefile, noconsole 옵션 총정리) (0) | 2025.07.17 |
|---|---|
| Python 딥러닝 기초: TensorFlow와 Keras로 MNIST 이미지 분류 모델 만들기 (0) | 2025.07.15 |
| FastAPI 앱 보안 강화와 스케일링 가이드: JWT 인증부터 Kubernetes 및 Nginx 로드 밸런싱까지 (0) | 2025.07.14 |
| 파이썬 앱 성능 최적화와 모니터링: Prometheus, Grafana부터 Redis 캐싱 기법까지 (0) | 2025.07.13 |
| Python 데이터 분석 앱 확장과 배포: FastAPI 백그라운드 태스크부터 Docker, GitHub Actions CI/CD까지 (0) | 2025.07.12 |