nlp(한국어) 분석 및 시각화, 자연어 처리
데이터셋 준비
KorNLI - 두 문장의 관계를 entailment/neutral/contradiction 으로 분류
https://github.com/kakaobrain/KorNLUDatasets/tree/master/KorNLI 에서 받아옵니다.
import pandas as pd
path = '/content/drive/MyDrive/KorNLUDatasets-master/KorNLI/'
train_snli = pd.read_csv(path + "snli_1.0_train.ko.tsv", sep='\t', quoting=3)
train_xnli = pd.read_csv(path + "multinli.train.ko.tsv", sep='\t', quoting=3)
# 결합 후 섞기
train_data = train_snli.append(train_xnli)
train = train_data.sample(frac=1).reset_index(drop=True)
def drop_na_and_duplciates(df):
df = df.dropna()
df = df.drop_duplicates()
df = df.reset_index(drop=True)
return df
# 전제, 가설에 존재하는 한글 단어가 아닌 다른 단어들은 전부 제거해줍니다.
# train['sentence1'] = train['sentence1'].str.replace('[^ㄱ-ㅎㅏ-ㅣ가-힣 0-9]', '')
# train['sentence2'] = train['sentence2'].str.replace('[^ㄱ-ㅎㅏ-ㅣ가-힣 0-9]', '')
# 결측값 및 중복 샘플 제거
train = drop_na_and_duplciates(train)
train.head()
sentence1 | sentence2 | gold_label | |
---|---|---|---|
0 | 군복 차림의 어린 소년이 흙길에서 빠르게 달린다. | 소년이 침실로 달려가고 있다. | contradiction |
1 | 이슬람교도들은 녹색 예언자 엘리야를 팬으로 대체하면서 예배의 전통을 이어갔다. 그리... | 두 건물의 폐허는 십자군 마을의 남은 전부다. | neutral |
2 | 검은 머리의 남자가 선글라스를 쓴 검은 머리의 여자 근처에 있는 구조물 위에 앉아 있다. | 두 아이가 구조물 아래에서 놀고 있다. | contradiction |
3 | 오 정말 오, 우리가 댈러스에 있기 때문에 나는 네가 여기 잘 있었다고 추측했어. ... | 오, 너 댈러스에 있잖아, 사실 우린 휴스턴에 있어. | contradiction |
4 | 과일 가게의 점원이 의상을 입는 사람들을 기다리고 있다. | 남자가 야외에 있다. | neutral |
데이터 시각화
import matplotlib.pyplot as plt
import numpy as np
label의 분포도 확인
label: neural, contradiction, entailment로 구성됨
features = train['gold_label'].value_counts()
plt.title('label')
plt.bar(features.keys(), features.values, width=0.5)
plt.show()
자연어 분석및 시각화
print('Train Label: ', train['gold_label'].value_counts(), sep='\n', end='\n\n')
Train Label: neutral 314148 contradiction 314130 entailment 313536 Name: gold_label, dtype: int64
premise_len_mean = np.mean(train['sentence1'].str.len()) # 자연어 길이의 평균값 계산
print('실제 Text 평균 길이 :',premise_len_mean)
hypo_len_mean = np.mean(train['sentence2'].str.len())
print('가설 Text 평균 길이 :',hypo_len_mean)
실제 Text 평균 길이 : 42.197995570250605 가설 Text 평균 길이 : 23.279179328402424
# 데이터 필터링을 위한 마스크 설정 (sentence1 부분만)
mask_true = (train.gold_label == 'entailment')
mask_false = (train.gold_label == 'contradiction')
mask_neutral = (train.gold_label == 'neutral')
df_train = train.sentence1.copy()
df_true = train.loc[mask_true,:].sentence1
df_false = train.loc[mask_false,:].sentence1
df_neu = train.loc[mask_neutral,:].sentence1
# 세 집합을 리스트로 묶어줍니다.
compare = [df_train, df_true, df_false, df_neu]
# 히스토그램 을 사용해서 데이터의 분포를 살펴봅니다.
plt.figure(figsize=(15,9))
plt.suptitle("Histogram: premise length", fontsize=40)
name = ['total dataset', 'entailment text', 'contradiction text', 'neutral text']
for i in range(len(compare)):
document = compare[i]
string_len = [len(x) for x in document]
plt.subplot(2, 2, i+1)
plt.title(name[i], fontsize=20)
plt.hist(string_len, alpha=0.5, color='orange')
plt.show()
각 label의 실제 문장들은 대부분 약 50자의 문장들로 구성되어 있음을 알 수 있다.
# 데이터 필터링을 위한 마스크 설정 (sentence2 부분만)
mask_true = (train.gold_label == 'entailment')
mask_false = (train.gold_label == 'contradiction')
mask_neutral = (train.gold_label == 'neutral')
df_train = train.sentence2.copy()
df_true = train.loc[mask_true,:].sentence2
df_false = train.loc[mask_false,:].sentence2
df_neu = train.loc[mask_neutral,:].sentence2
# 세 집합을 리스트로 묶어줍니다.
compare = [df_train, df_true, df_false, df_neu]
# 히스토그램 을 사용해서 데이터의 분포를 살펴봅니다.
plt.figure(figsize=(15,9))
plt.suptitle("Histogram: premise length", fontsize=40)
name = ['total dataset', 'entailment text', 'contradiction text', 'neutral text']
for i in range(len(compare)):
document = compare[i]
string_len = [len(x) for x in document]
plt.subplot(2, 2, i+1)
plt.title(name[i], fontsize=20)
plt.hist(string_len, alpha=0.5, color='orange')
plt.show()
각 label의 가설 문장은 대부분이 약 25자 정도에 많이 분포되어 있습니다.
Word cloud
wordcloud란 메타 데이터에서 얻어진 태그들을 분석하여 중요도나 인기도 등을 고려하여 시각적으로 늘어놓아 표시하는 것이다. 중요도(혹은 인기도)에 따라 글자의 색상이나 굵기 등 형태가 변한다.
-
KoNLPy와 nltk lib를 사용해서 문서에서 각각의 형태소(≒ 주로 명사인 단어)로 추출
-
Collection Counter() 모듈을 사용해서 명사가 언급된 횟수를 계산
-
WordCloud Lib를 사용하여 형태소(단어) 빈도에 따른 WordCloud 이미지 생성 및 저장
import wordcloud
#패키지 불러오기 및 각종 설치 & 폰트 설정 한방에
import matplotlib
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
!apt-get update -qq
!apt-get install fonts-nanum* -qq
font_path = '/usr/share/fonts/truetype/nanum/NanumBarunGothic.ttf'
font_name = fm.FontProperties(fname=font_path, size=10).get_name()
print(font_name)
plt.rc('font', family=font_name)
fm._rebuild()
matplotlib.rcParams['axes.unicode_minus'] = False
NanumBarunGothic
!pip install konlpy
Requirement already satisfied: konlpy in /usr/local/lib/python3.7/dist-packages (0.6.0) Requirement already satisfied: JPype1>=0.7.0 in /usr/local/lib/python3.7/dist-packages (from konlpy) (1.3.0) Requirement already satisfied: lxml>=4.1.0 in /usr/local/lib/python3.7/dist-packages (from konlpy) (4.2.6) Requirement already satisfied: numpy>=1.6 in /usr/local/lib/python3.7/dist-packages (from konlpy) (1.21.5) Requirement already satisfied: typing-extensions in /usr/local/lib/python3.7/dist-packages (from JPype1>=0.7.0->konlpy) (3.10.0.2)
from konlpy.tag import Okt
from collections import Counter
from wordcloud import WordCloud
def df2str(df):
#전체 문장들을 하나의 문자열로 만듦
s = [s for s in df]
document = ""
for i in range(len(s)):
document += s[i]
return document
def tokenizer_konlpy(text):
okt = Okt()
return [word for word in okt.nouns(text) if len(word) >1]
## train_data는 너무 오래 걸려 검증 데이터로 대신 사용
val = pd.read_csv(path + "xnli.dev.ko.tsv", sep='\t', quoting=3)
texts = df2str(val['sentence1'])
noun = tokenizer_konlpy(texts)
# count word
count = Counter(noun)
noun_list = count.most_common(100)
noun_list[:10] ## 가장 많이 쓰인 단어 출력
[('우리', 294), ('당신', 204), ('대한', 189), ('그것', 162), ('위해', 138), ('그녀', 126), ('사람', 126), ('미국', 120), ('가지', 114), ('다른', 112)]
# Generate a word cloud image
wc = WordCloud(font_path = font_path,
background_color = 'white',
width=512, height=512,
max_font_size=500,
max_words=1000)
wc.generate_from_frequencies(dict(noun_list))
plt.figure(figsize=(10,10)) #이미지 사이즈 지정
plt.title('text_rate', fontsize=20)
plt.imshow(wc, interpolation='lanczos') #이미지의 부드럽기 정도
plt.axis('off') #x y 축 숫자 제거
plt.show() # 워드클라우드 이미지 확인
texts = df2str(val['sentence2'])
noun = tokenizer_konlpy(texts)
# count word
count = Counter(noun)
noun_list = count.most_common(100)
noun_list[:10] ## 가장 많이 쓰인 단어 출력
[('사람', 176), ('우리', 172), ('당신', 87), ('그것', 86), ('그녀', 85), ('가지', 79), ('모든', 75), ('때문', 72), ('대해', 71), ('다른', 69)]
# Generate a word cloud image
wc = WordCloud(font_path = font_path,
background_color = 'white',
width=512, height=512,
max_font_size=500,
max_words=1000)
wc.generate_from_frequencies(dict(noun_list))
plt.figure(figsize=(10,10)) #이미지 사이즈 지정
plt.title('text_rate', fontsize=20)
plt.imshow(wc, interpolation='lanczos') #이미지의 부드럽기 정도
plt.axis('off') #x y 축 숫자 제거
plt.show() # 워드클라우드 이미지 확인
댓글남기기