티스토리 뷰
학습목표
- Bag of Words의 개념과 원리를 이해한다.
- CountVectorizer를 활용해 텍스트 데이터를 벡터화하는 방법을 익힌다.
- 벡터화된 데이터를 분석하고 단어 사전과 행렬을 해석할 수 있다.
- 실습과 시각화를 통해 텍스트 데이터의 유용한 정보를 추출하고 활용한다.
1. Bag of Words ?
스파이의 암호 해독 이야기
어느 날, 스파이들이 사용하는 암호 메시지를 해독해야 하는 상황에 놓였다고 상상해보자. 메시지는 온갖 단어로 이루어져 있지만 그 안에 숨겨진 패턴을 찾아야 한다. 이때 우리가 사용하는 도구가 바로 "Bag of Words"이다. "Bag of Words"는 단어를 '그냥 모아놓은 주머니'처럼 생각하는 기법으로, 단어가 몇 번 사용되었는지만 세는 아주 단순하면서도 강력한 방법이다.
즉, 텍스트 데이터를 숫자 벡터로 변환하는 가장 기본적이고 널리 사용되는 기법 중 하나이며, BoW는 텍스트에서 단어의 순서와 문맥을 무시하고, "각 단어가 몇 번 등장했는가"에만 초점을 맞춘다.
이제 이 기술을 실제로 사용하는 법을 파이썬 코드를 통해 살펴보겠다.
Bag of Words의 작동 원리
- 텍스트 데이터 준비
분석하고자 하는 문장이나 문서(텍스트)를 모은다. - 토큰화(Tokenization)
문장을 구성하는 단어(토큰)로 나눈다. 예:- 문장: "고양이가 집에서 뛰어다닌다."
- 토큰: ["고양이", "집", "뛰어다닌다"]
- 단어 사전(Vocabulary) 생성
전체 텍스트에서 등장한 고유한 단어를 모아 단어 사전을 만든다.
예: ["고양이", "집", "뛰어다닌다", "강아지", "공원"] - 단어 등장 횟수 계산
각 문장에서 단어가 몇 번 등장했는지를 세어 숫자로 표현한다.- 문장 1: "고양이가 집에서 뛰어다닌다" → [1, 1, 1, 0, 0]
- 문장 2: "강아지가 공원에서 뛴다" → [0, 0, 0, 1, 1]
Bag of Words의 특징
- 장점:
- 구현이 간단하고 빠르게 계산할 수 있다.
- 기본적인 자연어 처리에 적합하다.
- 단점:
- 단어의 순서를 무시하므로 문맥을 이해하지 못한다.
- 희소 행렬(Sparse Matrix) 문제가 발생한다. (데이터 대부분이 0으로 채워짐)
Bag of Words가 많이 사용되는 분야
- 텍스트 분류
- 스팸 이메일 분류: 이메일의 텍스트를 분석하여 스팸 여부를 판단.
- 뉴스 카테고리 분류: 뉴스 기사를 주제별로 분류.
- 감정 분석(Sentiment Analysis)
- 영화 리뷰, 소셜 미디어 글 등에서 긍정/부정 감정을 예측.
- 정보 검색 및 추천 시스템
- 문서 검색: 입력된 키워드와 관련성이 높은 문서를 추천.
- 영화/상품 추천: 텍스트 설명을 기반으로 유사성을 분석.
- 자연어 처리 및 언어 모델링
- 챗봇, 번역기, 요약 시스템 등 다양한 언어 기반 응용.
- 소셜 네트워크 분석
- 트위터, 페이스북 같은 플랫폼에서 특정 키워드의 빈도를 분석하여 트렌드를 파악.
Bag of Words의 대표 응용 예시
- 스팸 필터링:
이메일 본문에서 단어 등장 횟수를 분석해 스팸 메일을 걸러냄. - 감정 분석:
영화 리뷰에서 "좋다", "최고", "재밌다" 같은 긍정적인 단어와 "별로", "지루하다" 같은 부정적인 단어 빈도를 분석. - 키워드 추출:
문서에서 빈도 기반으로 중요한 키워드를 자동으로 추출.
2. Bag of Words 기초 코드
1) 필요한 라이브러리 소개
- scikit-learn(사이킷런): 텍스트를 벡터화하는 데 유용하다.
- pandas: 데이터를 다루는 데 편리하다.
- numpy: 수학 연산에 유용하다.
pip install scikit-learn pandas numpy
1. scikit-learn이란?
scikit-learn(사이킷런)은 파이썬에서 사용할 수 있는 머신러닝 라이브러리로, 데이터 처리부터 머신러닝 모델 생성, 평가까지 지원하는 강력한 도구이다.
- 사용하기 쉽고 직관적인 API 제공
- 다양한 데이터 전처리 및 모델링 기능
- 텍스트 데이터 처리부터 이미지, 수치 데이터까지 지원
- 단순한 텍스트 벡터화부터 고급 TF-IDF 계산까지 지원
- 다른 머신러닝 모델과 쉽게 결합 가능.
* scikit-learn을 사용할 때는 주로 from sklearn,을 통해 필요한 모듈이나 클래스를 불러옵니다.
sklearn은 scikit-learn의 약어로, Python에서 표준적으로 사용하는 방법입니다.
2. 텍스트 벡터화에서의 역할
텍스트 데이터는 머신러닝 모델이 직접 처리하기 어렵기 때문에, 이를 숫자(벡터)로 변환해야 한다.
scikit-learn은 이를 위한 다양한 도구를 제공하며, 대표적으로 CountVectorizer와 TfidfVectorizer가 있다.
3. CountVectorizer: Bag of Words 생성
CountVectorizer는 텍스트 데이터를 벡터로 변환하는 데 사용하는 가장 기본적인 도구이다.
- 텍스트 데이터를 단어(토큰) 단위로 나누어 빈도를 계산
- 단어 사전(vocabulary)을 자동으로 생성
- 벡터화된 데이터를 희소 행렬(sparse matrix) 형태로 반환
희소 행렬(sparse matrix)
보통 행렬(matrix)에서 대부분의 값이 0 으로 이루어진 경우를 의미하며, 주로 머신러닝과 데이터 과학에서 큰 데이터를 효율적으로 표현하기 위해 사용된다.
from sklearn.feature_extraction.text import CountVectorizer
# 샘플 텍스트 데이터
documents = ["나는 데이터 분석을 좋아한다", "데이터는 미래의 자산이다", "분석은 데이터를 이해하는 도구이다"]
# CountVectorizer로 벡터화
vectorizer = CountVectorizer()
bow_matrix = vectorizer.fit_transform(documents)
# 결과 출력
print("단어 사전:", vectorizer.vocabulary_)
print("Bag of Words 행렬:\n", bow_matrix.toarray())
- 필요한 라이브러리(scikit-learn, pandas, numpy)를 임포트합니다.
- 분석할 텍스트 데이터를 리스트 형태로 정의합니다.
- CountVectorizer 초기화: CountVectorizer는 텍스트 데이터를 숫자로 변환하기 위해 사용됩니다.
- Bag of Words 생성: fit_transform을 통해 단어의 빈도를 계산하여 벡터 형태의 데이터로 변환합니다.
- 결과 출력:
- vocabulary_는 단어 사전을 출력합니다.
- bow_matrix.toarray()는 문장별로 단어의 빈도를 행렬로 나타냅니다.
4. TfidfVectorizer: 단어 가중치 계산
TfidfVectorizer는 단어의 빈도와 함께 가중치(TF-IDF)를 계산해 더 정교한 벡터화를 지원한다.
TF-IDF란?
- TF (Term Frequency): 특정 단어가 문서에서 얼마나 자주 등장하는지.
- IDF (Inverse Document Frequency): 단어가 전체 문서에서 얼마나 드문지.
- TF-IDF: 특정 단어가 문서에서 얼마나 중요한지를 수치로 표현한 값.
(점수는 보통 0에서 1 사이 값을 가지며, 1에 가까울수록 해당 단어가 중요함을 의미합니다.)
#1.TfidfVectorizer를 사용하기 위해 라이브러리 불러오기
from sklearn.feature_extraction.text import TfidfVectorizer
#2.샘플 텍스트 데이터
documents = [
"나는 데이터 분석을 좋아한다", # 문장 1
"데이터는 미래의 자산이다", # 문장 2
"분석은 데이터를 이해하는 도구이다" # 문장 3
]
#3.TfidfVectorizer 객체 생성 (TF-IDF 방식으로 텍스트를 벡터화)
vectorizer = TfidfVectorizer()
#4. 텍스트 데이터를 TF-IDF 방식으로 변환
tfidf_matrix = vectorizer.fit_transform(documents)
# 5. 출력 (단어와 해당 인덱스를 보여줌)
print("단어 사전:", vectorizer.vocabulary_)
# TF-IDF 행렬 출력 (각 문장에서 단어의 TF-IDF 점수를 배열로 나타냄)
print("TF-IDF 행렬:\n", tfidf_matrix.toarray())
대표적인 모듈과 주요 클래스/함수
모듈 | 설명 | 주요 클래스 / 함수 |
sklearn.preprocessing | 데이터 전처리를 위한 도구 제공 | StandardScaler, MinMaxScaler, LabelEncoder, OneHotEncoder |
sklearn.model_selection | 데이터 분리 및 모델 평가 | train_test_split, GridSearchCV, RandomizedSearchCV |
sklearn.metrics | 모델 평가를 위한 지표 제공 | accuracy_score, confusion_matrix, mean_squared_error, roc_auc_score |
sklearn.linear_model | 선형 모델 관련 알고리즘 | LinearRegression, LogisticRegression, Ridge, Lasso |
sklearn.ensemble | 앙상블(Ensemble) 학습 관련 알고리즘 | RandomForestClassifier, GradientBoostingClassifier, AdaBoostClassifier |
sklearn.svm | 서포트 벡터 머신(SVM) 모델 | SVC (Support Vector Classifier), SVR (Support Vector Regressor) |
sklearn.neighbors | K-최근접 이웃(KNN) 알고리즘 | KNeighborsClassifier, KNeighborsRegressor |
sklearn.cluster | 군집화(Clustering) 알고리즘 | KMeans, DBSCAN, AgglomerativeClustering |
sklearn.decomposition | 차원 축소(Dimensionality Reduction) 도구 | PCA (Principal Component Analysis), TruncatedSVD, NMF |
sklearn.tree | 의사결정 트리(Decision Tree) 모델 | DecisionTreeClassifier, DecisionTreeRegressor |
sklearn.feature_extraction | 텍스트 및 이미지 데이터 벡터화 도구 | CountVectorizer, TfidfVectorizer, DictVectorizer |
sklearn.datasets | 샘플 데이터셋 제공 | load_iris, load_boston, load_digits, make_classification |
sklearn.pipeline | 데이터 전처리와 모델 학습을 연결하는 파이프라인 제공 | Pipeline, make_pipeline |
2) Bag of Words 기본 예제
from sklearn.feature_extraction.text import CountVectorizer
import pandas as pd
# 샘플 텍스트 데이터
documents = [
"스파이는 암호를 해독해야 한다",
"암호는 단어의 반복과 패턴을 포함한다",
"스파이는 메시지의 단서를 찾는다"
]
# CountVectorizer를 사용하여 Bag of Words 생성
vectorizer = CountVectorizer()
bow_matrix = vectorizer.fit_transform(documents)
# 단어별 인덱스 확인
print("단어 사전 (Vocabulary):")
print(vectorizer.vocabulary_)
# Bag of Words 행렬을 데이터프레임으로 변환
bow_df = pd.DataFrame(bow_matrix.toarray(), columns=vectorizer.get_feature_names_out())
print("\nBag of Words 행렬:")
print(bow_df)
- 데이터 준비: 텍스트 데이터가 들어 있는 리스트 documents를 준비한다.
- CountVectorizer 사용:
- CountVectorizer는 텍스트 데이터를 벡터로 변환한다.
- 각 단어가 문서에서 몇 번 등장했는지를 세어 행렬로 나타낸다.
- 결과 확인:
- vocabulary_를 통해 단어와 인덱스를 확인한다.
- 결과 행렬은 데이터프레임으로 만들어 더 보기 쉽게 출력한다.
실행 결과 예시
단어 사전 (Vocabulary):
{'스파이는': 5, '암호를': 6, '해독해야': 8, '한다': 7, '암호는': 4, '단어의': 1, '반복과': 2, '패턴을': 3, '포함한다': 9, '메시지의': 0, '단서를': 10, '찾는다': 11}
Bag of Words 행렬:
단어의 단서를 메시지의 반복과 스파이는 암호는 암호를 찾는다 패턴을 포함한다 해독해야 한다
0 0 0 0 0 1 0 1 0 0 0 1 1
1 1 0 0 1 0 1 0 0 1 1 0 0
2 0 1 1 0 1 0 0 1 0 0 0 0
3. 연습문제
- 1. 다음 텍스트 데이터로 Bag of Words를 만들어보자:
documents = ["너를 처음 봤을 때 마음이 떨려",
"사랑은 마치 불꽃처럼 뜨겁게 타올라",
"나의 마음속에 빛이 되어줘",
"우리는 하나가 되어 춤을 춘다",
"별처럼 빛나는 너의 눈동자"]
1)라이브러리 불러오기
from sklearn.feature_extraction.text import CountVectorizer
import pandas as pd
2) 문서 데이터 셋팅
documents = ["너를 처음 봤을 때 마음이 떨려",
"사랑은 마치 불꽃처럼 뜨겁게 타올라",
"나의 마음속에 빛이 되어줘",
"우리는 하나가 되어 춤을 춘다",
"별처럼 빛나는 너의 눈동자"]
3) 벡터화 및 BoW 생성
vectorizer = CountVectorizer()
bow_matrix = vectorizer.fit_transform(documents)
4) BoW 단어사전 출력
print('단어사전:', vectorizer.vocabulary_)
5) BoW 행렬을 데이터프레임으로 변환 후 출력
bow_df = pd.DataFrame(bow_matrix.toarray(), columns=vectorizer.get_feature_names_out())
print('Bag of Words 행렬:')
print(bow_df)
- 2. 단어 사전과 Bag of Words 행렬을 출력하고, 가장 많이 등장한 단어를 찾아라.
from sklearn.feature_extraction.text import CountVectorizer
import pandas as pd
# 노래 가사 데이터
documents = [
"너를 처음 봤을 때 마음이 떨려",
"사랑은 마치 불꽃처럼 뜨겁게 타올라",
"나의 마음속에 빛이 되어줘",
"우리는 하나가 되어 춤을 춘다",
"별처럼 빛나는 너의 눈동자"
]
# CountVectorizer를 사용하여 Bag of Words 생성
vectorizer = CountVectorizer()
bow_matrix = vectorizer.fit_transform(documents)
# 단어 사전
vocab = vectorizer.vocabulary_
# Bag of Words 행렬을 데이터프레임으로 변환
bow_df = pd.DataFrame(bow_matrix.toarray(), columns=vectorizer.get_feature_names_out())
# 각 단어의 총 빈도 계산
word_frequencies = bow_df.sum(axis=0).sort_values(ascending=False)
# 결과 출력
print("단어 사전 (Vocabulary):", vocab)
print("\nBag of Words 행렬:\n", bow_df)
print("\n가장 많이 등장한 단어:")
print(word_frequencies.head(1)) # 가장 많이 등장한 단어 출력
과제
1. 추가 데이터로 실습: 뉴스 기사 제목 5개를 직접 검색하여 documents 리스트에 추가하고 Bag of Words를 만들어보자.
"한국 경제, 올해 성장률 2.5% 예상"
"AI 기술, 산업 전반에 혁신을 가져오다"
"기후 변화 대응, 각국 협력 중요성 부각"
"스포츠 이벤트, 지역 경제 활성화에 기여"
"우주 탐사, 새로운 행성 발견 가능성 열리다"
from sklearn.feature_extraction.text import CountVectorizer
import pandas as pd
# 뉴스 기사 제목 샘플
documents = [
"한국 경제, 올해 성장률 2.5% 예상",
"AI 기술, 산업 전반에 혁신을 가져오다",
"기후 변화 대응, 각국 협력 중요성 부각",
"스포츠 이벤트, 지역 경제 활성화에 기여",
"우주 탐사, 새로운 행성 발견 가능성 열리다"
]
# CountVectorizer를 사용하여 Bag of Words 생성
vectorizer = CountVectorizer()
bow_matrix = vectorizer.fit_transform(documents)
# 단어 사전 확인
print("단어 사전 (Vocabulary):")
print(vectorizer.vocabulary_)
# Bag of Words 행렬을 데이터프레임으로 변환
bow_df = pd.DataFrame(bow_matrix.toarray(), columns=vectorizer.get_feature_names_out())
print("\nBag of Words 행렬:")
print(bow_df)
- 단어 사전: vocabulary_는 모든 단어와 그 단어의 인덱스를 보여준다.
예: {'한국': 12, '경제': 3, '올해': 10, '성장률': 8, '예상': 11, ...} - Bag of Words 행렬: 각 문장(문서)을 행으로, 단어를 열로 하여 단어의 빈도를 숫자로 나타낸다.
ai 경제 기여 기후 ... 우주 예상 열리다
0 0 1 0 0 ... 0 1 0
1 1 0 0 0 ... 0 0 0
...
2. 단어 빈도 시각화: Bag of Words 행렬에서 단어 빈도를 추출해 Matplotlib를 사용해 막대 그래프로 시각화하라.
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer
# 뉴스 기사 제목 샘플
documents = [
"한국 경제, 올해 성장률 2.5% 예상",
"AI 기술, 산업 전반에 혁신을 가져오다",
"기후 변화 대응, 각국 협력 중요성 부각",
"스포츠 이벤트, 지역 경제 활성화에 기여",
"우주 탐사, 새로운 행성 발견 가능성 열리다"
]
# CountVectorizer를 사용하여 Bag of Words 생성
vectorizer = CountVectorizer()
bow_matrix = vectorizer.fit_transform(documents)
# 단어 사전 및 빈도 추출
vocab = vectorizer.get_feature_names_out()
word_counts = bow_matrix.toarray().sum(axis=0)
# 데이터프레임 생성
bow_df = pd.DataFrame({'단어': vocab, '빈도': word_counts})
bow_df = bow_df.sort_values(by='빈도', ascending=False)
# 시각화
plt.figure(figsize=(12, 6))
plt.bar(bow_df['단어'], bow_df['빈도'])
plt.title('단어 빈도 시각화 (Bag of Words)', fontsize=16)
plt.xlabel('단어', fontsize=12)
plt.ylabel('빈도', fontsize=12)
plt.xticks(rotation=45, ha='right')
plt.tight_layout()
plt.show()
핵심 키워드
- Bag of Words (BoW)
- CountVectorizer
- 텍스트 벡터화
- 단어 사전 (Vocabulary)
- 희소 행렬 (Sparse Matrix)
- Total
- Today
- Yesterday