텍스트 전처리부터 Transformer까지 — NLP 핵심 개념 완전 정리
머신러닝 모델은 숫자만 이해한다. 그런데 우리가 다루는 텍스트 데이터는 지저분한 자연어다. “안녕하세요!!!”, “HELLO world “, “I’m running” — 이런 것들을 그대로 모델에 던져주면 모델 입장에서는 완전히 다른 데이터로 인식한다. 그래서 전처리(Preprocessing)는 단순한 정리가 아니라, 모델이 언어의 패턴을 제대로 학습할 수 있도록 데이터를 표준화하는 핵심 작업이다.
일반적으로 NLP 전처리는 아래 단계들을 거친다.
① 소문자 변환 (Lowercasing)
“Apple”과 “apple”은 같은 단어지만 모델은 다르게 인식한다. 대소문자를 통일해서 동일 단어로 취급되도록 한다. 단, 고유명사나 감성분석에서는 대문자가 의미를 가질 수 있어서 태스크에 따라 선택적으로 적용한다.
② 노이즈 제거 (Noise Removal)
HTML 태그, 특수문자, URL, 이메일 주소, 숫자 등 분석에 불필요한 요소를 제거한다. 정규표현식(re 모듈)을 주로 사용한다.
③ 토큰화 (Tokenization)
문장을 단어 또는 서브워드 단위로 나누는 과정이다. 한국어는 형태소 분석기(KoNLPy, Mecab)를 쓰고, 영어는 nltk나 spaCy를 많이 쓴다. 이게 전처리의 핵심 단계라고 해도 과언이 아니다.
④ 불용어 제거 (Stopword Removal)
“the”, “is”, “을”, “이” 같이 자주 나오지만 의미가 없는 단어들을 제거한다. 하지만 감성 분석 태스크에서는 “not”같은 불용어가 의미를 완전히 바꾸기 때문에 무조건 제거가 능사는 아니다.
⑤ 어간 추출 / 표제어 추출 (Stemming / Lemmatization)
“running”, “ran”, “runs”를 모두 “run”으로 통일하는 과정이다. Stemming은 규칙 기반으로 빠르지만 거칠고, Lemmatization은 문법적으로 정확하지만 느리다. 보통 Lemmatization을 더 선호한다.
⑥ 벡터화 (Vectorization)
전처리된 텍스트를 최종적으로 숫자(벡터)로 변환한다. Bag of Words, TF-IDF, 또는 임베딩(Word2Vec, FastText, BERT) 방식 중 태스크에 맞게 선택한다.
핵심 포인트
전처리 방법은 태스크마다 달라진다. 감성분석, 기계번역, 정보검색 각각 최적의 전처리가 다르다. “무조건 다 하면 좋다”는 함정에 빠지지 말 것. 특히 최근 BERT, GPT 같은 Pretrained 모델을 쓸 때는 자체 토크나이저가 있어서 기존 전처리를 일부 생략하기도 한다.
Word2Vec을 배우고 나면 자연스럽게 FastText로 넘어가게 된다. “그냥 더 좋은 버전 아닌가?” 하고 넘어가기 쉬운데, 둘의 차이는 단순한 성능 차이가 아니라 단어를 바라보는 근본적인 철학의 차이다.
Word2Vec의 한계 — 단어를 원자처럼 취급한다
Word2Vec은 단어 자체를 하나의 단위로 본다. “apple” → 하나의 벡터. 그래서 학습 데이터에 없는 단어(OOV, Out-of-Vocabulary)를 만나면 완전히 무력해진다. “unhappiness”를 학습했어도 “unhappily”가 없으면 모른다.
Word2Vec
단어 전체를 하나의 토큰으로 임베딩. 학습 어휘에 없는 단어는 처리 불가. 형태론적 유사성을 학습하지 못함.
FastText
단어를 n-gram 문자 단위로 분해해서 임베딩. OOV 단어도 서브워드 조합으로 처리 가능. 형태론적 유사성까지 포착.
FastText의 핵심 — 서브워드(Subword) 임베딩
FastText(Facebook AI 개발)는 단어를 n-gram 문자 단위로 쪼갠다. 예를 들어 “where”는 “<wh”, “whe”, “her”, “ere”, “re>” 같은 character n-gram으로 분해된다. 단어의 벡터는 이 n-gram 벡터들의 합이다.
덕분에 “unhappiness”를 본 적 없어도, “un-“, “happi-“, “-ness” 각각의 의미를 알고 있으면 추론이 가능하다. 특히 한국어나 독일어처럼 형태 변화가 많은 언어에서 FastText의 강점이 극명하게 드러난다. “먹다”, “먹었다”, “먹고” 같은 활용형을 서브워드 수준에서 연결지을 수 있기 때문이다.
핵심 포인트
FastText는 속도도 빠르고 OOV에 강하며 형태론적 정보까지 학습한다. 다만 서브워드 분해 때문에 어휘 크기가 커지고, 의미보다 형태에 집중하다 보니 문맥 이해는 여전히 제한적이다. 진짜 문맥 이해는 이후에 나오는 Attention과 Transformer가 해결한다.
Seq2Seq 모델을 처음 배울 때 굉장히 우아해 보인다. 인코더가 문장을 읽어서 하나의 벡터로 압축하고, 디코더가 그걸 펼쳐서 번역을 뱉는다. 근데 실제로 써보면 긴 문장에서 성능이 급격히 떨어진다. 왜일까?
문제: Fixed-size Context Vector의 저주
기존 Seq2Seq는 입력 문장 전체를 딱 하나의 고정 크기 벡터(Context Vector)에 우겨넣는다. 5단어짜리 문장이든 100단어짜리 문장이든 같은 크기의 벡터다. 긴 문장의 경우 앞부분 정보가 뒤로 전달되면서 희석되거나 완전히 사라진다. 이걸 Long-term Dependency 문제라고 한다.
해결: Attention이 “어디를 봐야 하는지” 알려준다
2015년 Bahdanau et al.이 제안한 Attention 메커니즘은 발상 자체가 직관적이다. 디코더가 출력 단어를 하나씩 생성할 때, 인코더의 모든 히든 스테이트를 다시 참조하면 어떨까? 그리고 현재 생성 중인 단어와 가장 관련 있는 입력 단어에 더 높은 가중치(Attention Score)를 부여하면?
예를 들어 “I love dogs”를 “나는 개를 좋아해”로 번역할 때, 디코더가 “개를”을 생성하는 순간에는 인코더의 “dogs” 부분에 높은 Attention을 두고, “나는”을 생성할 때는 “I”에 집중한다. 문장 전체를 단 하나의 벡터에 욱여넣는 대신, 매 출력 스텝마다 입력 전체를 동적으로 참조하는 방식이다.
이렇게 하면 두 가지 문제가 동시에 해결된다. 첫째, 긴 문장에서도 초반부 정보가 손실되지 않는다. 둘째, 모델이 어느 입력에 집중하는지 Attention Weight를 시각화해서 해석 가능성(Interpretability)까지 얻게 된다.
핵심 포인트
Attention은 Seq2Seq의 정보 병목을 해결한 핵심 아이디어다. 그리고 이 아이디어가 너무 강력해서 결국 “RNN이 굳이 필요한가?”라는 의문으로 이어지고, 그게 Transformer의 탄생으로 이어진다.
2017년 “Attention is All You Need” 논문 제목이 이미 모든 걸 설명한다. RNN 없이, CNN 없이, Attention만으로 Seq2Seq 태스크를 처리하겠다는 선언이다. 이건 단순한 성능 개선이 아니라 NLP 아키텍처의 패러다임 전환이었다.
Seq2Seq(RNN 기반)의 구조적 한계
RNN 계열(LSTM, GRU 포함)은 본질적으로 순차적(sequential)이다. 3번째 단어를 처리하려면 반드시 1번, 2번을 먼저 처리해야 한다. 이 구조 때문에 두 가지 문제가 생긴다: 첫째는 GPU 병렬 처리가 어렵다는 것, 둘째는 긴 문장에서 기울기 소실(Vanishing Gradient)이 발생한다는 것이다.Word2Vec의 한계 — 단어를 원자처럼 취급한다
Seq2Seq (RNN 기반)
순차적 처리 → 병렬화 불가. 긴 거리 의존성에 취약. 학습 속도 느림. Attention을 추가해도 RNN 한계는 여전히 존재.
Transformer
Self-Attention으로 전체 병렬 처리. 모든 단어 쌍의 관계를 동시에 계산. 학습 속도 대폭 향상. BERT, GPT의 기반 구조.
Transformer의 핵심 — Self-Attention
Transformer는 RNN을 완전히 제거하고 Self-Attention만으로 문장을 처리한다. Self-Attention이란 한 문장 내에서 각 단어가 다른 모든 단어들과 얼마나 관련 있는지를 동시에 계산하는 메커니즘이다. “The animal didn’t cross the street because it was tired”에서 “it”이 “animal”을 가리킨다는 것을 Self-Attention이 학습한다.
RNN이 왼쪽에서 오른쪽으로 순서대로 읽는다면, Transformer는 문장 전체를 한 번에 보고 단어 간의 관계를 계산한다. 이 덕분에 GPU 병렬 처리가 가능해지고 학습 속도가 비약적으로 빨라진다.
Positional Encoding — 순서 정보를 따로 주입
RNN은 순서대로 읽으니까 자연히 위치 정보를 갖는다. 반면 Transformer는 병렬로 처리하니까 “이 단어가 몇 번째다”라는 정보가 없다. 그래서 각 단어 임베딩에 위치 정보를 담은 Positional Encoding 벡터를 더해준다. 이로써 순서 정보도 학습에 반영된다.
핵심 포인트
Transformer의 혁신은 “순차 처리”를 포기하고 “병렬 처리”를 선택했다는 데 있다. 이 구조가 이후 BERT(인코더만 사용), GPT(디코더만 사용), T5(인코더-디코더 모두 사용) 등 현대 LLM 전체의 기반이 된다. 지금 우리가 쓰는 ChatGPT, Claude도 결국 Transformer 위에 서 있다.
Leave a comment