🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

워드 임베딩과 감성 분석 완벽 가이드 - 슬라이드 1/8
A

AI Generated

2025. 12. 4. · 14 Views

워드 임베딩과 감성 분석 완벽 가이드

자연어 처리의 핵심인 워드 임베딩과 감성 분석을 초급자도 이해할 수 있도록 설명합니다. Word2Vec의 원리부터 실제 레스토랑 리뷰 분석까지 실무 예제와 함께 배워봅니다.


목차

  1. 워드_임베딩_개념
  2. Word2Vec_원리
  3. CBOW와_Skip-gram
  4. 유사도_점수_해석
  5. Word2Vec_장단점
  6. 감성_분석_개요
  7. 사례_레스토랑_리뷰_분석

1. 워드 임베딩 개념

어느 날 김개발 씨는 회사에서 새로운 프로젝트를 맡았습니다. 고객 리뷰를 분석해서 불만 사항을 자동으로 분류하는 시스템을 만들어야 합니다.

그런데 컴퓨터가 어떻게 "맛있다"와 "훌륭하다"가 비슷한 의미라는 것을 알 수 있을까요?

워드 임베딩은 단어를 숫자 벡터로 변환하는 기술입니다. 마치 각 단어에 고유한 GPS 좌표를 부여하는 것과 같습니다.

비슷한 의미를 가진 단어들은 가까운 좌표에 위치하고, 다른 의미의 단어들은 멀리 떨어져 있습니다. 이렇게 하면 컴퓨터가 단어 간의 의미적 관계를 수학적으로 이해할 수 있게 됩니다.

다음 코드를 살펴봅시다.

import numpy as np

# 단어를 벡터로 표현하는 간단한 예시
word_vectors = {
    "왕": np.array([0.8, 0.2, 0.9]),
    "여왕": np.array([0.7, 0.8, 0.9]),
    "남자": np.array([0.9, 0.1, 0.3]),
    "여자": np.array([0.8, 0.9, 0.3])
}

# 왕 - 남자 + 여자 = 여왕에 가까운 벡터
result = word_vectors["왕"] - word_vectors["남자"] + word_vectors["여자"]
print(f"계산 결과: {result}")
print(f"여왕 벡터: {word_vectors['여왕']}")

김개발 씨는 입사 6개월 차 주니어 개발자입니다. 자연어 처리 프로젝트를 처음 맡게 된 그는 막막한 기분이 들었습니다.

컴퓨터는 0과 1만 이해하는데, 어떻게 사람의 언어를 분석할 수 있을까요? 선배 개발자 박시니어 씨가 다가와 설명을 시작합니다.

"컴퓨터에게 단어를 이해시키려면 먼저 숫자로 바꿔줘야 해요. 그게 바로 워드 임베딩이에요." 그렇다면 워드 임베딩이란 정확히 무엇일까요?

쉽게 비유하자면, 워드 임베딩은 마치 단어에게 집 주소를 부여하는 것과 같습니다. 서울에 사는 사람들은 서울 주소를 가지고, 부산에 사는 사람들은 부산 주소를 가지듯이, 비슷한 의미를 가진 단어들은 비슷한 좌표를 갖게 됩니다.

"강아지"와 "고양이"는 같은 동네에 살고, "자동차"와 "비행기"도 같은 동네에 삽니다. 워드 임베딩이 없던 시절에는 어땠을까요?

과거에는 원-핫 인코딩이라는 방식을 사용했습니다. 사전에 1만 개의 단어가 있다면, 각 단어를 1만 차원의 벡터로 표현했습니다.

"사과"는 [1,0,0,...,0], "바나나"는 [0,1,0,...,0] 이런 식이었죠. 문제는 이 방식으로는 "사과"와 "바나나"가 둘 다 과일이라는 사실을 전혀 알 수 없다는 것입니다.

바로 이런 문제를 해결하기 위해 워드 임베딩이 등장했습니다. 워드 임베딩을 사용하면 단어의 의미적 유사성을 파악할 수 있습니다.

또한 벡터 연산을 통해 단어 간의 관계를 추론할 수도 있습니다. 유명한 예시가 바로 "왕 - 남자 + 여자 = 여왕"입니다.

위의 코드를 살펴보겠습니다. 먼저 각 단어를 3차원 벡터로 표현했습니다.

실제로는 100~300차원을 사용하지만, 원리를 이해하기 위해 단순화한 것입니다. "왕"에서 "남자"의 성분을 빼고 "여자"의 성분을 더하면, 놀랍게도 "여왕"과 비슷한 벡터가 나옵니다.

이것이 워드 임베딩의 마법입니다. 실제 현업에서는 어떻게 활용할까요?

검색 엔진을 만든다고 가정해봅시다. 사용자가 "저렴한 맛집"을 검색했을 때, "가성비 좋은 식당"도 함께 보여줄 수 있습니다.

워드 임베딩 덕분에 "저렴한"과 "가성비 좋은", "맛집"과 "식당"이 비슷한 의미라는 것을 컴퓨터가 알 수 있기 때문입니다. 하지만 주의할 점도 있습니다.

워드 임베딩은 학습 데이터에 따라 품질이 크게 달라집니다. 편향된 데이터로 학습하면 편향된 임베딩이 만들어집니다.

따라서 다양하고 균형 잡힌 데이터로 학습하는 것이 중요합니다. 박시니어 씨의 설명을 들은 김개발 씨는 고개를 끄덕였습니다.

"아, 그래서 자연어 처리에서 워드 임베딩이 그렇게 중요하다고 하는 거군요!"

실전 팁

💡 - 워드 임베딩의 차원 수는 보통 100~300 사이가 적당합니다

  • 사전 학습된 임베딩(Word2Vec, GloVe)을 활용하면 시간을 크게 절약할 수 있습니다

2. Word2Vec 원리

김개발 씨는 워드 임베딩의 개념을 이해했습니다. 그런데 한 가지 의문이 생겼습니다.

도대체 어떻게 단어의 의미를 벡터로 학습할 수 있는 걸까요? 박시니어 씨가 웃으며 말했습니다.

"그게 바로 Word2Vec의 마법이에요."

Word2Vec은 구글에서 2013년에 발표한 워드 임베딩 알고리즘입니다. 핵심 아이디어는 "함께 자주 등장하는 단어는 비슷한 의미를 가진다"는 것입니다.

마치 친한 친구들은 항상 같이 다니는 것처럼, "커피"와 "카페", "바다"와 "파도"는 문장에서 자주 함께 등장합니다.

다음 코드를 살펴봅시다.

from gensim.models import Word2Vec

# 학습용 문장 데이터
sentences = [
    ["오늘", "날씨", "정말", "좋다"],
    ["날씨", "좋은", "날", "산책", "하자"],
    ["비", "오는", "날", "집", "에서", "쉬자"],
    ["맑은", "날씨", "에", "소풍", "가자"]
]

# Word2Vec 모델 학습
model = Word2Vec(sentences, vector_size=100, window=3, min_count=1, epochs=100)

# "날씨"와 비슷한 단어 찾기
similar_words = model.wv.most_similar("날씨", topn=3)
print(f"날씨와 비슷한 단어: {similar_words}")

김개발 씨가 물었습니다. "선배, 컴퓨터가 어떻게 '커피'와 '카페'가 관련 있다는 걸 알 수 있나요?" 박시니어 씨가 답했습니다.

"문장을 많이 읽다 보면 알게 돼요. '커피'라는 단어 주변에는 '카페', '향', '원두' 같은 단어가 자주 나오잖아요." 이것이 바로 분포 가설입니다.

단어의 의미는 그 단어가 사용되는 맥락에 의해 결정된다는 것입니다. Word2Vec은 이 가설을 바탕으로 만들어졌습니다.

비유를 들어 설명해보겠습니다. 학교에서 새 학기가 시작되면, 누가 누구와 친한지 금방 알 수 있습니다.

항상 같이 다니는 친구들이 있기 때문입니다. Word2Vec도 마찬가지입니다.

문장이라는 "교실"에서 어떤 단어들이 자주 "함께 다니는지" 관찰합니다. Word2Vec의 학습 과정은 이렇습니다.

먼저 대량의 텍스트 데이터를 준비합니다. 그리고 각 단어에 대해 주변에 어떤 단어들이 등장하는지 살펴봅니다.

이 정보를 바탕으로 신경망이 단어 벡터를 조금씩 조정해 나갑니다. 수백만 번의 학습을 거치면, 비슷한 맥락에서 사용되는 단어들은 비슷한 벡터를 갖게 됩니다.

코드를 살펴보겠습니다. vector_size=100은 각 단어를 100차원 벡터로 표현하겠다는 의미입니다.

window=3은 주변 3개 단어까지 고려하겠다는 뜻입니다. min_count=1은 최소 1번 이상 등장한 단어만 학습에 포함합니다.

실제로는 훨씬 큰 데이터셋으로 학습해야 좋은 결과를 얻을 수 있습니다. 실무에서 Word2Vec은 어떻게 활용될까요?

추천 시스템에서 많이 사용됩니다. "이 상품을 본 고객이 함께 본 상품" 기능을 생각해보세요.

상품 ID를 단어처럼 취급하고, 사용자의 구매 이력을 문장처럼 취급하면 Word2Vec으로 비슷한 상품을 찾을 수 있습니다. 주의할 점이 있습니다.

Word2Vec은 동음이의어를 구분하지 못합니다. "배"가 먹는 과일인지, 타는 배인지, 사람의 신체 부위인지 구분할 수 없습니다.

모든 "배"가 하나의 벡터로 표현되기 때문입니다. 김개발 씨가 말했습니다.

"신기하네요. 컴퓨터가 문맥을 보고 단어의 의미를 학습하다니요."

실전 팁

💡 - 학습 데이터가 많을수록 임베딩 품질이 좋아집니다

  • 도메인에 특화된 임베딩이 필요하면 해당 분야 텍스트로 직접 학습하세요

3. CBOW와 Skip-gram

박시니어 씨가 화이트보드에 그림을 그리기 시작했습니다. "Word2Vec에는 두 가지 방식이 있어요.

CBOW와 Skip-gram이라고 해요. 둘 다 같은 목표를 향하지만, 방향이 정반대예요."

CBOW(Continuous Bag of Words)는 주변 단어들을 보고 중심 단어를 예측하는 방식입니다. 반대로 Skip-gram은 중심 단어를 보고 주변 단어들을 예측합니다.

CBOW는 빈도가 높은 단어 학습에 유리하고, Skip-gram은 빈도가 낮은 단어도 잘 학습합니다.

다음 코드를 살펴봅시다.

from gensim.models import Word2Vec

sentences = [
    ["나는", "맛있는", "커피를", "마신다"],
    ["그녀는", "따뜻한", "커피를", "좋아한다"],
    ["아침에", "커피", "한잔", "마시면", "좋다"]
]

# CBOW 방식 (sg=0)
cbow_model = Word2Vec(sentences, vector_size=50, window=2, sg=0, min_count=1)

# Skip-gram 방식 (sg=1)
skipgram_model = Word2Vec(sentences, vector_size=50, window=2, sg=1, min_count=1)

# 두 모델 비교
print("CBOW 커피 벡터 일부:", cbow_model.wv["커피를"][:5])
print("Skip-gram 커피 벡터 일부:", skipgram_model.wv["커피를"][:5])

김개발 씨가 고개를 갸웃거렸습니다. "두 방식이 뭐가 다른 건가요?" 박시니어 씨가 예시를 들었습니다.

"빈칸 채우기 문제를 생각해봐요. '나는 맛있는 ___를 마신다'에서 빈칸에 들어갈 단어는 뭘까요?" "커피요?" 김개발 씨가 답했습니다.

"맞아요. 이게 바로 CBOW 방식이에요.

주변 단어들(나는, 맛있는, 마신다)을 보고 중심 단어(커피)를 맞추는 거예요." 박시니어 씨가 이어서 설명했습니다. "반대로 Skip-gram은 '커피'라는 단어만 보고 주변에 어떤 단어들이 있을지 예측해요.

커피 주변에는 '맛있는', '마신다', '향' 같은 단어가 있겠죠?" 비유로 설명하면 이렇습니다. CBOW는 마치 단서를 모아 범인을 찾는 탐정과 같습니다.

여러 증거(주변 단어)를 종합해서 답(중심 단어)을 찾습니다. Skip-gram은 반대로 범인(중심 단어) 한 명을 보고 그와 관련된 모든 증거(주변 단어)를 유추하는 것과 같습니다.

실무에서는 어떤 것을 선택해야 할까요? CBOW는 학습 속도가 빠릅니다.

자주 등장하는 단어들의 임베딩을 잘 학습합니다. 데이터가 충분히 많고, 일반적인 단어들의 관계가 중요할 때 적합합니다.

Skip-gram은 학습 속도는 느리지만, 드물게 등장하는 단어도 잘 학습합니다. 전문 용어가 많은 도메인이나, 희귀 단어의 의미가 중요한 경우에 적합합니다.

코드에서 sg 파라미터가 핵심입니다. sg=0이면 CBOW, sg=1이면 Skip-gram입니다.

같은 데이터로 학습해도 두 모델이 만들어내는 벡터는 다릅니다. 어떤 것이 더 좋은지는 데이터와 목적에 따라 달라집니다.

김개발 씨가 정리했습니다. "그러니까 일반적인 상황에서는 CBOW가 효율적이고, 희귀 단어가 중요한 경우에는 Skip-gram을 쓰면 되겠네요." 박시니어 씨가 엄지를 치켜올렸습니다.

"정확해요!"

실전 팁

💡 - 대용량 데이터에서는 CBOW가 학습 속도 면에서 유리합니다

  • 의료, 법률 등 전문 분야에서는 Skip-gram이 더 좋은 결과를 보입니다

4. 유사도 점수 해석

김개발 씨가 Word2Vec 모델을 학습시키고 유사 단어를 검색했습니다. 결과에 "유사도: 0.85"라는 숫자가 나왔습니다.

"선배, 이 0.85가 무슨 의미예요? 85점이라는 건가요?"

코사인 유사도는 두 벡터 사이의 각도를 측정하는 방법입니다. 값이 1에 가까울수록 두 단어가 비슷하고, 0에 가까울수록 관련이 없으며, -1에 가까우면 반대 의미입니다.

Word2Vec에서는 이 코사인 유사도를 사용해 단어 간 유사성을 계산합니다.

다음 코드를 살펴봅시다.

import numpy as np
from numpy.linalg import norm

def cosine_similarity(vec1, vec2):
    # 코사인 유사도 계산
    dot_product = np.dot(vec1, vec2)
    norm_product = norm(vec1) * norm(vec2)
    return dot_product / norm_product

# 예시 벡터들
coffee = np.array([0.8, 0.6, 0.9, 0.2])
tea = np.array([0.7, 0.5, 0.85, 0.3])
car = np.array([0.1, 0.9, 0.2, 0.8])

# 유사도 계산
print(f"커피-차 유사도: {cosine_similarity(coffee, tea):.3f}")
print(f"커피-자동차 유사도: {cosine_similarity(coffee, car):.3f}")

박시니어 씨가 종이에 그림을 그렸습니다. "두 개의 화살표를 상상해봐요.

같은 방향을 가리키면 비슷한 거고, 다른 방향을 가리키면 다른 거예요." 코사인 유사도는 두 벡터가 이루는 각도를 측정합니다. 완전히 같은 방향이면 각도가 0도이고, 코사인 값은 1입니다.

수직(90도)이면 코사인 값은 0입니다. 완전히 반대 방향(180도)이면 코사인 값은 -1입니다.

왜 단순한 거리가 아니라 각도를 사용할까요? 문서의 길이가 다르면 벡터의 크기도 달라집니다.

긴 문서는 큰 벡터, 짧은 문서는 작은 벡터를 가질 수 있습니다. 이때 유클리드 거리를 사용하면 길이 차이 때문에 잘못된 결과가 나올 수 있습니다.

코사인 유사도는 방향만 비교하기 때문에 이런 문제가 없습니다. 코드를 살펴보겠습니다.

먼저 두 벡터의 내적(dot product)을 계산합니다. 그리고 각 벡터의 크기(norm)를 곱합니다.

내적을 크기의 곱으로 나누면 코사인 유사도가 됩니다. "커피"와 "차"는 0.9 이상의 높은 유사도를 보이고, "커피"와 "자동차"는 낮은 유사도를 보입니다.

유사도 점수는 어떻게 해석해야 할까요? 일반적으로 0.7 이상이면 상당히 유사하다고 봅니다.

0.4~0.7은 어느 정도 관련이 있습니다. 0.4 미만은 거의 관련이 없습니다.

하지만 이 기준은 데이터셋과 도메인에 따라 달라질 수 있습니다. 실무에서 주의할 점이 있습니다.

높은 유사도가 항상 좋은 것은 아닙니다. 예를 들어 추천 시스템에서 너무 비슷한 것만 추천하면 다양성이 떨어집니다.

적절한 임계값(threshold)을 설정하는 것이 중요합니다. 김개발 씨가 말했습니다.

"그러니까 0.85는 두 단어가 같은 방향을 향하고 있다는 뜻이군요. 의미가 비슷하다는 거죠!"

실전 팁

💡 - 유사도 임계값은 프로젝트마다 실험을 통해 결정하세요

  • 음수 유사도가 나오면 반의어 관계일 수 있습니다

5. Word2Vec 장단점

김개발 씨가 Word2Vec으로 여러 실험을 해보았습니다. 놀라운 결과도 있었지만, 때로는 이상한 결과도 나왔습니다.

"선배, Word2Vec이 만능인 줄 알았는데, 한계도 있네요."

Word2Vec의 장점은 빠른 학습 속도와 단어 간 의미적 관계를 잘 포착한다는 것입니다. 하지만 동음이의어를 구분하지 못하고, 문맥에 따른 의미 변화를 반영하지 못하며, 학습 데이터에 없는 단어(OOV)는 처리할 수 없다는 단점이 있습니다.

다음 코드를 살펴봅시다.

from gensim.models import Word2Vec
import numpy as np

# Word2Vec의 한계 예시
sentences = [
    ["나는", "배가", "고프다"],  # 배 = 신체
    ["배를", "타고", "바다로", "갔다"],  # 배 = 탈것
    ["배", "한개를", "먹었다"]  # 배 = 과일
]

model = Word2Vec(sentences, vector_size=50, window=2, min_count=1)

# 모든 "배"가 하나의 벡터로 표현됨 - 의미 구분 불가
print("'배' 벡터:", model.wv["배"][:5])
print("모든 의미가 섞인 하나의 벡터입니다")

# OOV(Out of Vocabulary) 문제
try:
    print(model.wv["포도"])  # 학습 데이터에 없는 단어
except KeyError:
    print("'포도'는 학습되지 않은 단어입니다 - OOV 문제 발생")

박시니어 씨가 고개를 끄덕였습니다. "맞아요.

Word2Vec은 훌륭한 도구지만, 모든 상황에서 완벽하지는 않아요." Word2Vec의 장점부터 살펴보겠습니다. 첫째, 학습이 빠릅니다.

수백만 개의 문서도 상대적으로 짧은 시간에 학습할 수 있습니다. 둘째, 단어 간 의미적 관계를 잘 포착합니다.

"왕 - 남자 + 여자 = 여왕" 같은 연산이 가능한 것이 좋은 예입니다. 셋째, 적은 메모리로 많은 단어를 표현할 수 있습니다.

하지만 단점도 분명히 있습니다. 가장 큰 문제는 동음이의어입니다.

코드에서 보듯이 "배"라는 단어는 문맥에 따라 신체 부위, 탈것, 과일 등 여러 의미를 가집니다. 하지만 Word2Vec은 모든 "배"를 하나의 벡터로 표현합니다.

세 가지 의미가 섞인 이상한 벡터가 만들어지는 것입니다. 두 번째 문제는 OOV(Out of Vocabulary)입니다.

학습할 때 보지 못한 단어는 처리할 수 없습니다. 새로운 신조어나 오타가 있는 단어를 만나면 에러가 발생합니다.

실제 서비스에서는 이런 경우가 빈번하게 발생합니다. 세 번째 문제는 문맥 무시입니다.

"오늘 날씨가 좋다"와 "좋다, 어서 해보자"에서 "좋다"의 뉘앙스는 다릅니다. 하지만 Word2Vec은 이런 차이를 반영하지 못합니다.

이런 한계를 극복하기 위해 BERT, ELMo 같은 모델이 등장했습니다. 이들은 문맥에 따라 다른 임베딩을 생성합니다.

"배가 고프다"의 "배"와 "배를 타다"의 "배"가 다른 벡터를 갖게 됩니다. 하지만 그만큼 계산 비용이 높습니다.

김개발 씨가 정리했습니다. "그러니까 빠르고 간단한 분석에는 Word2Vec이 좋고, 더 정교한 분석이 필요하면 BERT 같은 모델을 써야겠네요."

실전 팁

💡 - 간단한 키워드 분석이나 추천 시스템에는 Word2Vec이 충분합니다

  • OOV 문제가 심각하면 FastText를 고려해보세요 (부분 단어 학습 가능)

6. 감성 분석 개요

김개발 씨에게 새로운 과제가 주어졌습니다. "고객 리뷰를 분석해서 긍정인지 부정인지 자동으로 분류해주세요." 워드 임베딩을 배웠으니, 이제 본격적으로 감성 분석에 도전해볼 시간입니다.

감성 분석(Sentiment Analysis)은 텍스트에 담긴 감정이나 의견을 파악하는 기술입니다. 긍정, 부정, 중립으로 분류하거나 감성 점수를 수치로 계산합니다.

고객 리뷰 분석, 소셜 미디어 모니터링, 브랜드 평판 관리 등에 널리 활용됩니다.

다음 코드를 살펴봅시다.

from transformers import pipeline

# 감성 분석 파이프라인 생성
sentiment_analyzer = pipeline("sentiment-analysis",
                              model="nlptown/bert-base-multilingual-uncased-sentiment")

# 리뷰 분석
reviews = [
    "이 제품 정말 최고예요! 강력 추천합니다.",
    "배송이 너무 느리고 포장도 엉망이었어요.",
    "그냥 그래요. 가격 대비 보통입니다."
]

for review in reviews:
    result = sentiment_analyzer(review)[0]
    stars = int(result['label'].split()[0])
    print(f"리뷰: {review[:20]}...")
    print(f"평점: {'⭐' * stars} ({result['score']:.2f})")
    print()

박시니어 씨가 설명을 시작했습니다. "감성 분석은 결국 '이 글을 쓴 사람의 기분이 어떤가'를 파악하는 거예요." 사람은 글을 읽으면 직관적으로 감정을 파악합니다.

"맛있어요!"를 보면 긍정, "별로예요"를 보면 부정이라는 걸 바로 알 수 있습니다. 하지만 하루에 수만 개의 리뷰가 쏟아진다면 어떨까요?

사람이 일일이 읽고 분류하는 것은 불가능합니다. 바로 이런 상황에서 감성 분석이 필요합니다.

감성 분석의 접근 방식은 크게 두 가지입니다. 첫 번째는 규칙 기반입니다.

"좋아요", "훌륭해요" 같은 긍정 단어 목록과 "나빠요", "실망이에요" 같은 부정 단어 목록을 만들어 놓습니다. 글에 긍정 단어가 많으면 긍정, 부정 단어가 많으면 부정으로 분류합니다.

간단하지만 "안 좋아요"처럼 부정어가 섞인 표현을 처리하기 어렵습니다. 두 번째는 머신러닝 기반입니다.

대량의 라벨링된 데이터로 모델을 학습시킵니다. 학습된 모델은 새로운 텍스트의 감성을 예측합니다.

최근에는 BERT 같은 트랜스포머 모델이 뛰어난 성능을 보여줍니다. 코드를 살펴보겠습니다.

Hugging Face의 transformers 라이브러리를 사용했습니다. pipeline은 복잡한 과정을 한 줄로 처리해주는 편리한 기능입니다.

사전 학습된 다국어 감성 분석 모델을 불러와서 바로 사용합니다. 결과는 1~5점 척도로 나오며, 점수가 높을수록 긍정입니다.

감성 분석은 어디에 활용될까요? 이커머스에서는 상품 리뷰를 분석해 품질 문제를 조기에 발견합니다.

금융에서는 뉴스 기사의 감성을 분석해 주가 예측에 활용합니다. 콜센터에서는 고객 상담 내용을 분석해 불만 고객을 우선 처리합니다.

김개발 씨가 눈을 빛냈습니다. "고객의 목소리를 자동으로 분석할 수 있다니, 정말 유용하겠네요!"

실전 팁

💡 - 도메인에 특화된 감성 사전을 구축하면 정확도가 올라갑니다

  • "안 좋다", "별로 맛없다" 같은 부정어 처리에 주의하세요

7. 사례 레스토랑 리뷰 분석

이론은 충분히 배웠습니다. 이제 실전입니다.

김개발 씨는 레스토랑 리뷰 데이터를 받았습니다. 수천 개의 리뷰에서 고객들이 무엇에 만족하고, 무엇에 불만인지 자동으로 분석해야 합니다.

실제 레스토랑 리뷰 분석 프로젝트에서는 감성 분류뿐만 아니라 토픽 추출, 키워드 분석도 함께 수행합니다. 이를 통해 "맛은 좋은데 서비스가 별로"처럼 복합적인 피드백도 세분화하여 분석할 수 있습니다.

다음 코드를 살펴봅시다.

from collections import Counter
import re

# 샘플 리뷰 데이터
reviews = [
    {"text": "음식이 정말 맛있었어요. 직원분들도 친절했습니다.", "rating": 5},
    {"text": "가격이 너무 비싸요. 양도 적고 맛도 그저 그래요.", "rating": 2},
    {"text": "분위기는 좋은데 웨이팅이 너무 길어요.", "rating": 3},
    {"text": "최고의 파스타! 재방문 의사 100%입니다.", "rating": 5},
    {"text": "주차가 불편하고 음식이 늦게 나와요.", "rating": 2}
]

# 감성별 키워드 추출
positive_words = []
negative_words = []

for review in reviews:
    words = re.findall(r'[가-힣]+', review['text'])
    if review['rating'] >= 4:
        positive_words.extend(words)
    elif review['rating'] <= 2:
        negative_words.extend(words)

print("긍정 리뷰 주요 키워드:", Counter(positive_words).most_common(5))
print("부정 리뷰 주요 키워드:", Counter(negative_words).most_common(5))

김개발 씨가 데이터를 살펴보았습니다. "5점 리뷰도 있고 2점 리뷰도 있네요.

어떻게 분석을 시작해야 할까요?" 박시니어 씨가 조언했습니다. "먼저 전체적인 패턴을 파악해봐요.

고객들이 어떤 주제에 대해 이야기하는지, 긍정적인 리뷰와 부정적인 리뷰에서 공통으로 등장하는 키워드가 무엇인지 살펴보는 거예요." 첫 번째 단계는 데이터 전처리입니다. 리뷰 텍스트에서 의미 없는 문자를 제거하고, 단어 단위로 분리합니다.

한국어는 조사가 붙기 때문에 형태소 분석을 하면 더 정확합니다. 여기서는 간단히 정규표현식으로 한글만 추출했습니다.

두 번째 단계는 감성별 분류입니다. 평점 4점 이상은 긍정, 2점 이하는 부정으로 분류했습니다.

이제 각 그룹에서 어떤 단어가 자주 등장하는지 살펴봅니다. 코드의 결과를 해석해보겠습니다.

긍정 리뷰에서는 "맛있었어요", "친절", "최고" 같은 단어가 자주 등장합니다. 부정 리뷰에서는 "비싸요", "불편", "늦게" 같은 단어가 눈에 띕니다.

이를 통해 레스토랑의 강점과 약점을 파악할 수 있습니다. 실제 프로젝트에서는 여기서 더 나아갑니다.

토픽 모델링을 적용하면 리뷰를 "음식 품질", "서비스", "가격", "분위기" 등 카테고리로 자동 분류할 수 있습니다. 시계열 분석을 추가하면 시간에 따른 고객 만족도 변화를 추적할 수 있습니다.

김개발 씨가 분석 결과를 정리했습니다. "이 레스토랑은 음식 맛과 직원 서비스는 좋은데, 가격과 대기 시간에 대한 불만이 있네요.

이 정보를 경영진에게 전달하면 구체적인 개선 방향을 잡을 수 있겠어요." 박시니어 씨가 흐뭇하게 웃었습니다. "바로 그거예요.

데이터에서 인사이트를 뽑아내는 게 진짜 실력이에요." 김개발 씨는 뿌듯한 마음으로 프로젝트를 마무리했습니다. 워드 임베딩부터 감성 분석까지, 자연어 처리의 기초를 제대로 배운 것 같았습니다.

실전 팁

💡 - 한국어 분석에는 KoNLPy 라이브러리의 형태소 분석기를 활용하세요

  • 실제 서비스에서는 비속어 필터링과 스팸 리뷰 탐지도 필요합니다

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#Python#WordEmbedding#Word2Vec#SentimentAnalysis#NLP#Python,NLP,Embedding

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.