[진짜 재난 뉴스 판별기] - 1
지도 학습의 기법인 분류(Classification)는 실제 비즈니스에서 매우 자주 사용되는 머신러닝 알고리즘의 하나이다. 주어진 데이터를 기반으로 새로운 범주형 클래스를 예측하는 기법이다.
예를 들면 고객의 이탈 유무 판별, 신용 카드 연체 유무 판별, 스팸 이메일 감지, 암 진단 유무 등 다양한 곳에서 활용이 가능하다. 분류의 종류에는 이진 분류(Binary Classification), 다중 분류(Multiclass Classification)가 존재한다. 다중 분류의 가장 대표적인 예는 IRIS 데이터의 종 분류이다.
이번 글에서는 캐글 대회인 트위터 진짜 재난 뉴스 판별기 만들기를 진행해 볼 것이다.
비정형 데이터인 만큼 텍스트 마이닝이 필요하다.
데이터 불러오기
먼저 데이터는 아래의 링크에 있다.
https://www.kaggle.com/c/nlp-getting-started
import pandas as pd
train = pd.read_csv('PART_II_Basic/nlp_train.csv')
test = pd.read_csv('PART_II_Basic/nlp_test.csv')
train.head()
train 데이터는 'id', 'keyword', 'location', 'text', 'target' 등 총 5개의 변수로 이루어져 있다.
- id : 각 트위터 데이터의 식별자
- keyword : 해당 트윗의 특정 키워드
- location : 트위터가 작성된 장소
- text : 실제 트윗의 메시지
- target : 실제로 재난이라면 1, 가짜라면 0을 표시
하지만 test 데이터셋에는 target 변수명이 없는 것을 확인할 수 있다.
탐색적 자료 분석(EDA)
수치를 예측하는 회귀 문제와 달리 범주를 예측하는 분류 문제에서 가장 중요한 것은 종속 변수를 시각화해 분포를 확인하는 것이다. 종속 변수를 시각화해 진짜 재난 뉴스와 가짜 뉴스의 분포를 확인해보자.
# EDA
import matplotlib.pyplot as plt
import seaborn as sns
news_class = train['target'].value_counts()
labels = ['Non-Disaster', 'Disaster']
fig, ax = plt.subplots(figsize = (10, 6))
ax.bar(labels, news_class, color = ['green', 'orange'])
fig.show()
Non Disaster의 개수는 4,342개이고, Real Disaster의 개수는 3,271개로 Non Disaster의 개수가 더 많은 것을 확인할 수 있다. 위의 그림처럼 분류 문제의 종속 변수는 데이터의 개수가 불균형할 때가 많다. 분류 문제의 핵심은 비대칭 데이터를 어떻게 샘플링해 학습시킬 것인지가 가장 핵심이므로 시각화를 통해 가장 먼저 확인해야 한다.
이번에는 독립 변수로 활용할 트윗 데이터를 시각화를 할 것이다. Disaster일 때의 트윗의 길이와 Non Disaster일 때의 트윗의 길이의 분포를 시각화해보자.
disaster_tweet_len = train[train['target'] == 1]['text'].str.len()
non_disaster_tweet_len = train[train['target'] == 0]['text'].str.len()
fig, ax = plt.subplots(1, 2, figsize = (12, 6))
ax[0].hist(disaster_tweet_len, color = 'green')
ax[0].set_title('Disaster Tweet Length')
ax[1].hist(non_disaster_tweet_len, color = 'orange')
ax[1].set_title('Non Disaster Tweet Length')
fig.suptitle('All word in Tweets')
plt.show()
두 그래프 모두 비슷한 분포를 보인다. 하지만 Non Disaster의 길이가 140 이후에는 급격히 떨어지는 특성이 보인다.
박스 플롯을 통해 양 그래프의 글자 수를 확인해보자. 파라미터 showmeans을 통해 평균값을 그래프에 표시하도록 지정할 수 있다.
fig, ax = plt.subplots(1, 2, figsize = (12, 6))
ax[0].boxplot(disaster_tweet_len, labels = ['counts'], showmeans = True)
ax[0].set_title('Disaster Tweet Length')
ax[1].boxplot(non_disaster_tweet_len, labels = ['counts'], showmeans = True)
ax[1].set_title('Non Disaster Tweet Length')
fig.suptitle('All words in Tweets')
plt.show()
두 데이터 모두 중간값보다는 작은 값을 나타내는 것을 확인할 수 있다. 전반적으로 Disaster 트윗 문장의 길이가 Non Disaster 트윗의 글자 수보다는 많은 것을 확인할 수 있다.
import numpy as np
disaster_tweet_len = train[train['target'] == 1]['text'].str.len()
non_disaster_tweet_len = train[train['target'] == 0]['text'].str.len()
print('Max Length of Disaster Tweet : {}'.format(np.max(disaster_tweet_len)))
print('Min Length of Disaster Tweet : {}'.format(np.min(disaster_tweet_len)))
print('Mean Length of Disaster Tweet : {:.2f}'.format(np.mean(disaster_tweet_len)))
print('Median Length of Disaster Tweet : {}'.format(np.median(disaster_tweet_len)))
print('Max Length of Non Disaster Tweet : {}'.format(np.max(non_disaster_tweet_len)))
print('Min Length of Non Disaster Tweet : {}'.format(np.min(non_disaster_tweet_len)))
print('Mean Length of Non Disaster Tweet : {:.2f}'.format(np.mean(non_disaster_tweet_len)))
print('Median Length of Non Disaster Tweet : {}'.format(np.median(non_disaster_tweet_len)))
Numpy 모듈을 활용해 여러 가지 통계 값도 볼 수 있다.
다음으로는 워드 클라우드를 통해 주로 사용된 데이터의 빈도수를 확인해보자. 워드 클라우드는 빈도수를 기반으로 설정되는데 매우 직관적인 것이 특성이다. STOPWORDS라는 일명 '불용어' 모듈을 통해 자주 사용되는 영어의 불용어를 처리하도록 도와주는 것을 사용할 것이다.
# 워드클라우드
from wordcloud import WordCloud, STOPWORDS
disaster_tweet_keywords = dict(train[train['target'] == 1]['keyword'].value_counts())
non_disaster_tweet_keywords = dict(train[train['target'] == 0]['keyword'].value_counts())
stopwords = set(STOPWORDS)
disaster_wordcloud = WordCloud(stopwords = stopwords, width = 800, height = 400, background_color = 'white').generate_from_frequencies(disaster_tweet_keywords)
non_disaster_wordcloud = WordCloud(stopwords = stopwords, width = 800, height = 400, background_color = 'white').generate_from_frequencies(non_disaster_tweet_keywords)
fig, ax = plt.subplots(1, 2, figsize = (16, 10))
ax[0].imshow(disaster_wordcloud, interpolation = 'bilinear')
ax[0].axis('off')
ax[0].set_title('Disaster Tweet')
ax[1].imshow(non_disaster_wordcloud, interpolation = 'bilinear')
ax[1].axis('off')
ax[1].set_title('Non Disaster Tweet')
fig.show()
먼저 Disaster 트윗은 Typhoon(태풍), Outbreak(어떤 사건의 발생), Wreckage(난파), Derailment(탈선) 등처럼 명사 하나로도 충분하게 설명되는 것이 진짜 재난 뉴스라면, Non Disaster 트윗은 명사보다는 형용사나 동사가 주로 사용되는 것을 확인할 수 있다. 여러 문장에 나온 단어의 빈도수를 확인해 직관적으로 시각화하도록 도와주는 워드 클라우드를 통해 두 뉴스의 차이점을 확인할 수 있다.
시각화를 진행하고 이제 본격적으로 피처 엔지니어링, 모델 학습을 진행해 볼 것이다. 일반적인 정형 데이터와 달리 텍스트를 대상으로 한 피처 엔지니어링은 조금 다르다. 텍스트만을 대상으로 해서 사전에 손질해야 할 전처리 작업이 많다.
피처엔지니어링부터는 다음 시간에 다뤄 볼 예정이다.
'Kaggle' 카테고리의 다른 글
[샌프란시스코 범죄 분류] - 1 (0) | 2021.10.05 |
---|---|
[진짜 재난 뉴스 판별기] - 2 (0) | 2021.10.04 |
[자전거 수요 예측] - 1 (0) | 2021.09.10 |
[타이타닉 생존자 분류] - 2 (0) | 2021.09.09 |
[타이타닉 생존자 분류] - 1 (0) | 2021.09.08 |