CountVectorizer로 텍스트 데이터 벡터화
워드 클라우드
- 단어의 빈도수 데이터를 가지고 있을 때 이용할 수 있는 시각화 방법
- 단순히 빈도수를 표현하기보다는 상관관계나 유사도 등으로 배치하는 게 더 의미 있기 때문에 큰 정보를 얻기는 어렵다.
from wordcloud import WordCloud, STOPWORDS
import matplotlib.pyplot as plt
# %matplotlib inline 설정을 해주어야지만 노트북 안에 그래프가 디스플레이 된다.
%matplotlib inline
def displayWordCloud(data = None, backgroundcolor = 'white', width=800, height=600 ):
wordcloud = WordCloud(stopwords = STOPWORDS,
background_color = backgroundcolor,
width = width, height = height).generate(data)
plt.figure(figsize = (15 , 10))
plt.imshow(wordcloud)
plt.axis("off")
plt.show()
# 학습 데이터의 모든 단어에 대한 워드 클라우드를 그려본다.
%time displayWordCloud(' '.join(clean_train_reviews))
CPU times: user 24.9 s, sys: 1.07 s, total: 26 s
Wall time: 27.7 s
# 테스트 데이터의 모든 단어에 대한 워드 클라우드를 그려본다.
%time displayWordCloud(' '.join(clean_test_reviews))
CPU times: user 23.4 s, sys: 906 ms, total: 24.3 s
Wall time: 25.1 s
# 단어 수
train['num_words'] = clean_train_reviews.apply(lambda x: len(str(x).split()))
# 중복을 제거한 단어 수
train['num_uniq_words'] = clean_train_reviews.apply(lambda x: len(set(str(x).split())))
# 첫 번째 리뷰에
x = clean_train_reviews[0]
x = str(x).split()
print(len(x))
x[:10]
219
['stuff',
'go',
'moment',
'mj',
'start',
'listen',
'music',
'watch',
'odd',
'documentari']
import seaborn as sns
fig, axes = plt.subplots(ncols=2)
fig.set_size_inches(18, 6)
print('리뷰 별 단어 평균값 :', train['num_words'].mean())
print('리뷰 별 단어 중간값', train['num_words'].median())
sns.distplot(train['num_words'], bins=100, ax=axes[0])
axes[0].axvline(train['num_words'].median(), linestyle='dashed')
axes[0].set_title('리뷰 별 단어 수 분포')
print('리뷰 별 고유 단어 평균값 :', train['num_uniq_words'].mean())
print('리뷰 별 고유 단어 중간값', train['num_uniq_words'].median())
sns.distplot(train['num_uniq_words'], bins=100, color='g', ax=axes[1])
axes[1].axvline(train['num_uniq_words'].median(), linestyle='dashed')
axes[1].set_title('리뷰 별 고유한 단어 수 분포')
리뷰 별 단어 평균값 : 119.52356
리뷰 별 단어 중간값 89.0
리뷰 별 고유 단어 평균값 : 94.05756
리뷰 별 고유 단어 중간값 74.0
Text(0.5,1,'리뷰 별 고유한 단어 수 분포')
Bag-of-words model - Wikipedia
다음의 두 문장이 있다고 하자,
(1) John likes to watch movies. Mary likes movies too.
(2) John also likes to watch football games.
위 두 문장을 토큰화하여 가방에 담아주면 다음과 같다.
[
"John",
"likes",
"to",
"watch",
"movies",
"Mary",
"too",
"also",
"football",
"games"
]
그리고 배열의 순서대로 가방에서 각 토큰이 몇 번 등장하는지 횟수를 세어준다.
(1) [1, 2, 1, 1, 2, 1, 1, 0, 0, 0]
(2) [1, 1, 1, 1, 0, 0, 0, 1, 1, 1]
=> 머신러닝 알고리즘이 이해할 수 있는 형태로 바꿔주는 작업이다.
단어 가방을 n-gram을 사용해 bigram으로 담아주면 다음과 같다.
[
"John likes",
"likes to",
"to watch",
"watch movies",
"Mary likes",
"likes movies",
"movies too",
]
=> 여기에서는 CountVectorizer를 통해 위 작업을 한다.
사이킷런의 CountVectorizer를 통해 피처 생성
- 정규표현식을 사용해 토큰을 추출한다.
- 모두 소문자로 변환시키기 때문에 good, Good, gOod이 모두 같은 특성이 된다.
- 의미 없는 특성을 많이 생성하기 때문에 적어도 두 개의 문서에 나타난 토큰만을 사용한다.
- min_df로 토큰이 나타날 최소 문서 개수를 지정할 수 있다.
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.pipeline import Pipeline
# 튜토리얼과 다르게 파라메터 값을 수정
# 파라메터 값만 수정해도 캐글 스코어 차이가 크게 남
vectorizer = CountVectorizer(analyzer = 'word',
tokenizer = None,
preprocessor = None,
stop_words = None,
min_df = 2, # 토큰이 나타날 최소 문서 개수
ngram_range=(1, 3),
max_features = 20000
)
vectorizer
CountVectorizer(analyzer='word', binary=False, decodeerror='strict',
dtype=
lowercase=True, max
ngramrange=(1, 3), preprocessor=None, stopwords=None,
stripaccents=None, tokenpattern='(?u)\b\w\w+\b',
tokenizer=None, vocabulary=None)
# 속도 개선을 위해 파이프라인을 사용하도록 개선
# 참고 : https://stackoverflow.com/questions/28160335/plot-a-document-tfidf-2d-graph
pipeline = Pipeline([
('vect', vectorizer),
])
%time train_data_features = pipeline.fit_transform(clean_train_reviews)
train_data_features
CPU times: user 31.9 s, sys: 829 ms, total: 32.8 s
Wall time: 32.8 s
<25000x20000 sparse matrix of type '
with 2762268 stored elements in Compressed Sparse Row format>
train_data_features.shape
(25000, 20000)
vocab = vectorizer.get_feature_names()
vocab[:10]
['aag',
'aaron',
'ab',
'abandon',
'abbey',
'abbi',
'abbot',
'abbott',
'abc',
'abduct']
# 벡터화된 피처를 확인해 봄
import numpy as np
dist = np.sum(train_data_features, axis=0)
for tag, count in zip(vocab, dist):
print(count, tag)
pd.DataFrame(dist, columns=vocab)
[[26 48 22 ..., 59 40 23]] aag
aag | aaron | ab | abandon | abbey | abbi | abbot | abbott | abc | abduct | ... | zombi bloodbath | zombi film | zombi flick | zombi movi | zone | zoo | zoom | zorro | zu | zucker | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 26 | 48 | 22 | 288 | 24 | 30 | 29 | 30 | 125 | 55 | ... | 23 | 52 | 37 | 89 | 161 | 31 | 71 | 59 | 40 | 23 |
1 rows × 20000 columns
pd.DataFrame(train_data_features[:100].toarray(), columns=vocab).head()
aag | aaron | ab | abandon | abbey | abbi | abbot | abbott | abc | abduct | ... | zombi bloodbath | zombi film | zombi flick | zombi movi | zone | zoo | zoom | zorro | zu | zucker | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
5 rows × 20000 columns
-
<CountVectorizer로 텍스트 데이터 벡터화> 영상이 비공개로 나타납니다
Hommy
2020.5.24 21:01
0