소개
이 실습에서는 숫자가 아닌 입력 데이터 (예: 사전이나 텍스트 문서) 를 실수 벡터로 표현하는 텍스트 벡터화 과정을 살펴봅니다. 사용자 정의 파이썬 함수를 사용하여 사전처리 (토큰화) 된 텍스트 문서를 벡터화하는 두 가지 방법인 FeatureHasher와 DictVectorizer를 비교해 보겠습니다.
VM 팁
VM 시작이 완료되면 왼쪽 상단 모서리를 클릭하여 Notebook 탭으로 전환하여 연습용 Jupyter Notebook에 접근합니다.
때때로 Jupyter Notebook 이 완전히 로드되기까지 몇 초 정도 기다려야 할 수 있습니다. Jupyter Notebook 의 제한으로 인해 작업의 유효성 검사는 자동화될 수 없습니다.
학습 중 문제가 발생하면 Labby 에 문의하십시오. 세션 후 피드백을 제공하면 문제를 신속하게 해결해 드리겠습니다.
데이터 로드
20newsgroups_dataset에서 데이터를 로드합니다. 이 데이터는 20 개 주제에 대한 약 18,000 개의 뉴스그룹 게시물로 구성되며, 두 개의 하위 집합 (하나는 학습용, 하나는 테스트용) 으로 나뉩니다. 간결성과 계산 비용 절감을 위해 7 개 주제의 하위 집합을 선택하고 학습용 집합만 사용합니다.
from sklearn.datasets import fetch_20newsgroups
categories = [
"alt.atheism",
"comp.graphics",
"comp.sys.ibm.pc.hardware",
"misc.forsale",
"rec.autos",
"sci.space",
"talk.religion.misc",
]
print("20 뉴스그룹 학습 데이터 로드 중")
raw_data, _ = fetch_20newsgroups(subset="train", categories=categories, return_X_y=True)
data_size_mb = sum(len(s.encode("utf-8")) for s in raw_data) / 1e6
print(f"{len(raw_data)} 문서 - {data_size_mb:.3f}MB")
전처리 함수 정의
토큰은 단어, 단어 일부 또는 문자열에서 공백이나 기호 사이에 포함된 모든 것을 의미할 수 있습니다. 여기서는 유니코드 단어 문자를 일치시키는 간단한 정규 표현식 (regex) 을 사용하여 토큰을 추출하는 함수를 정의합니다. 이에는 모든 언어에서 단어의 일부가 될 수 있는 대부분의 문자와 숫자, 밑줄이 포함됩니다.
import re
def tokenize(doc):
"""doc 에서 토큰을 추출합니다.
문자열을 토큰으로 분할하기 위해 단어 문자를 일치시키는 간단한 정규 표현식을 사용합니다.
더 체계적인 접근 방식은 CountVectorizer 또는 TfidfVectorizer 를 참조하십시오.
"""
return (tok.lower() for tok in re.findall(r"\w+", doc))
주어진 문서에서 각 토큰의 발생 빈도를 계산하는 추가 함수를 정의합니다. 벡터화기에 사용할 빈도 사전을 반환합니다.
from collections import defaultdict
def token_freqs(doc):
"""doc 에서 토큰과 그 발생 횟수를 매핑하는 사전을 추출합니다."""
freq = defaultdict(int)
for tok in tokenize(doc):
freq[tok] += 1
return freq
DictVectorizer
DictVectorizer를 평가합니다. 이 메서드는 입력으로 사전을 받습니다.
from sklearn.feature_extraction import DictVectorizer
from time import time
t0 = time()
vectorizer = DictVectorizer()
vectorizer.fit_transform(token_freqs(d) for d in raw_data)
duration = time() - t0
print(f"done in {duration:.3f} s")
print(f"Found {len(vectorizer.get_feature_names_out())} unique terms")
FeatureHasher
FeatureHasher를 평가합니다. 이 메서드는 특징 (예: 토큰) 에 해시 함수를 적용하여 미리 정의된 길이의 벡터를 생성한 다음, 해시 값을 직접 특징 인덱스로 사용하고 결과 벡터를 해당 인덱스에서 업데이트하는 방법입니다.
from sklearn.feature_extraction import FeatureHasher
import numpy as np
t0 = time()
hasher = FeatureHasher(n_features=2**18)
X = hasher.transform(token_freqs(d) for d in raw_data)
duration = time() - t0
print(f"done in {duration:.3f} s")
print(f"Found {len(np.unique(X.nonzero()[1]))} unique tokens")
특수 목적 텍스트 벡터화기와의 비교
이전 방법들을 CountVectorizer와 HashingVectorizer와 비교해 보겠습니다.
from sklearn.feature_extraction.text import CountVectorizer, HashingVectorizer, TfidfVectorizer
t0 = time()
vectorizer = CountVectorizer()
vectorizer.fit_transform(raw_data)
duration = time() - t0
print(f"done in {duration:.3f} s")
print(f"Found {len(vectorizer.get_feature_names_out())} unique terms")
t0 = time()
vectorizer = HashingVectorizer(n_features=2**18)
vectorizer.fit_transform(raw_data)
duration = time() - t0
print(f"done in {duration:.3f} s")
t0 = time()
vectorizer = TfidfVectorizer()
vectorizer.fit_transform(raw_data)
duration = time() - t0
print(f"done in {duration:.3f} s")
print(f"Found {len(vectorizer.get_feature_names_out())} unique terms")
결과 플롯
위 벡터화 방법들의 속도를 플롯합니다.
import matplotlib.pyplot as plt
dict_count_vectorizers = {
"vectorizer": [
"DictVectorizer\non freq dicts",
"FeatureHasher\non freq dicts",
"FeatureHasher\non raw tokens",
"CountVectorizer",
"HashingVectorizer",
"TfidfVectorizer"
],
"speed": [
2.4, 4.4, 7.2, 5.1, 11.7, 2.9
]
}
fig, ax = plt.subplots(figsize=(12, 6))
y_pos = np.arange(len(dict_count_vectorizers["vectorizer"]))
ax.barh(y_pos, dict_count_vectorizers["speed"], align="center")
ax.set_yticks(y_pos)
ax.set_yticklabels(dict_count_vectorizers["vectorizer"])
ax.invert_yaxis()
_ = ax.set_xlabel("속도 (MB/s)")
요약
이 실험에서는 두 가지 방법인 FeatureHasher와 DictVectorizer 그리고 네 가지 특수 목적 텍스트 벡터화기인 CountVectorizer, HashingVectorizer, TfidfVectorizer를 비교하여 텍스트 벡터화를 탐색했습니다. 벡터화 방법들을 벤치마킹하고 결과를 플롯했습니다. 결론적으로 HashingVectorizer는 해시 충돌로 인한 변환의 역변환 불가능성에도 불구하고 CountVectorizer보다 성능이 더 좋았습니다. 또한, DictVectorizer와 FeatureHasher는 내부 토큰화 단계가 문서 전체에 대해 정규 표현식을 한 번 컴파일하고 재사용하기 때문에 수동으로 토큰화된 문서에서 동등한 텍스트 벡터화기보다 성능이 더 좋았습니다.