Skip to Content

01. 텍스트 감성 분석 (Sentiment Analysis)

고급2시간

1. 개요 및 시나리오

상황: 수천 건의 리뷰가 매일 쏟아집니다. 별점은 5점인데 리뷰 내용은 “배송이 너무 늦어서 화가 나지만 제품은 좋아요”라면, 이걸 긍정으로 봐야 할까요? 텍스트 속에 숨겨진 **고객의 감정(Sentiment)**을 수치화하여 분석해봅시다.


2. 데이터 준비

raw_reviews_relabeled 테이블의 리뷰 텍스트(review_body)를 분석합니다.

from google.cloud import bigquery import pandas as pd client = bigquery.Client()

3. 키워드 기반 감성 분석

가장 단순한 방법은 “좋은 단어”와 “나쁜 단어”가 있는지 확인하는 것입니다.

❓ 문제 1: 긍정/부정 키워드 찾기

Q. 리뷰 텍스트에 bad, poor, terrible, late 등이 포함되면 ‘Negative’, good, great, excellent 등이 포함되면 ‘Positive’, 나머지는 ‘Neutral’로 분류하세요.

💡

Hint: REGEXP_CONTAINS를 사용하면 여러 패턴을 한 번에 찾을 수 있습니다.

정답 코드 보기

SELECT review_id, review_body, CASE WHEN REGEXP_CONTAINS(LOWER(review_body), r'bad|poor|terrible|late|slow|worst') THEN 'Negative' WHEN REGEXP_CONTAINS(LOWER(review_body), r'good|great|excellent|love|best') THEN 'Positive' ELSE 'Neutral' END as sentiment_category FROM `your-project-id.retail_analytics_us.raw_reviews_relabeled` LIMIT 10;

4. NLP 라이브러리 활용 (TextBlob)

단순 키워드 매칭은 “Not good”을 “Positive”로 잘못 분류할 수 있습니다. 전문 NLP 라이브러리를 사용하면 문맥을 어느 정도 파악하여 점수(1.0+1.0-1.0 \sim +1.0)를 줍니다.

❓ 문제 2: 감성 점수 계산 (Polarity Score)

Q. Python의 TextBlob (혹은 BigQuery Remote Function)을 사용하여 리뷰의 감성 점수를 계산하세요.

Pandas: TextBlob(text).sentiment.polarity를 사용합니다.

정답 코드 보기

from textblob import TextBlob # 감성 점수 계산 함수 def get_sentiment(text): return TextBlob(str(text)).sentiment.polarity reviews['sentiment_score'] = reviews['review_body'].apply(get_sentiment) # 결과 확인 print(reviews[['review_body', 'sentiment_score']].head()) # 평균 점수 print(f"평균 감성 점수: {reviews['sentiment_score'].mean():.4f}")

5. 카테고리별 감성 분석 및 시각화

어떤 제품군이 고객 불만이 가장 많은지 찾아봅시다.

❓ 문제 3: 최악의 카테고리 찾기

Q. 계산된 감성 점수를 바탕으로, 카테고리별 평균 감성 점수부정적 리뷰(점수 < 0) 비율을 집계 및 시각화하세요.

정답 코드 보기

import matplotlib.pyplot as plt # 집계 cat_summary = reviews.groupby('relabeled_category').agg({ 'sentiment_score': 'mean', 'review_id': 'count' }).reset_index() # 부정 리뷰 비율 계산 neg_reviews = reviews[reviews['sentiment_score'] < 0].groupby('relabeled_category').size() total_reviews = reviews.groupby('relabeled_category').size() cat_summary['neg_ratio'] = (neg_reviews / total_reviews * 100).fillna(0).values # 시각화 (Scatter Plot) plt.figure(figsize=(10, 6)) plt.scatter(cat_summary['neg_ratio'], cat_summary['sentiment_score'], s=cat_summary['review_id']/10, alpha=0.5) for i, txt in enumerate(cat_summary['relabeled_category']): plt.annotate(txt, (cat_summary['neg_ratio'][i], cat_summary['sentiment_score'][i])) plt.xlabel('Negative Review Ratio (%)') plt.ylabel('Average Sentiment Score') plt.title('Sentiment Analysis by Category') plt.axvline(x=30, color='r', linestyle='--') # 30% 이상이면 위험 plt.show()

💡 요약

  • 키워드 매칭: 빠르고 비용이 없지만 정확도가 떨어짐. “Not bad”를 구분 못함.
  • Rule-based NLP (TextBlob): 문법을 고려하여 조금 더 정확함.
  • LLM (다음 챕터): “비꼬는 말투”까지 이해하는 최고 수준의 성능.

다음 챕터에서는 Gemini를 사용하여 진짜 사람처럼 텍스트를 이해하고 분류해보겠습니다.

Last updated on

🤖AI 모의면접실전처럼 연습하기