본문 바로가기

Natural_Language

[NLP] 03.자연어 처리 개요 - 데이터 이해하기

반응형

아래 내용은 텐서플로우와 머신러닝으로 시작하는 자연어처리

책을 바탕으로 작성 된 내용입니다.

 

 

데이터 이해하기

                 " 데이터 전처리 >> 정제된 전처리 >> 탐색적 자료 분석 >> 모델 >> 사용 "

 

- 문제 해결을 위해서는 데이터 이해가 선행되어야 하는데, 이러한 과정을 EDA라고 한다.

- 이러한 과정을 통해 생각하지 못한 데이터의 여러 패턴이나 잠재적인 문제점을 발견할 수 있다.

- 탐색적 데이터 분석의 흐름  

 

데이터 가져오기

import os
import re

import pandas as pd
import tensorflow as tf
from tensorflow.keras import utils

data_set = tf.keras.utils.get_file(
            fname = "imdb.tar.gz",
            origin = "http://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz",
            extract = True)

 

- 텐서플로 케라스 모듈의 get_file 함수를 통해 IMDB 데이터를 가져온다.

- origin 인자에 데이터의 URL을 넣으면 해당 데이터를 다운로드하게 된다.

- 다운로드 받으면 디렉토리 안의 txt 파일 형태로 되어있다.

 

 

데이터를 읽기 위한 함수 생성

def directory_data(directory):
    data ={}
    data['review'] = []
    for file_path in os.listdir(directory):
        with open(os.path.join(directory, file_path), "r") as file:
            data['review'].append(file.read())
            
    return pd.DataFrame.from_dict(data)

 

- 데이터를 가져올 디렉토리를 인자로 받는다.

- 그리고 안에있는 파일을 하나씩 가져와 배열에 넣는다.

- 딕셔너리를 판다스 데이터프레임 형태로 만든다.

 

 

def data(directory):
    pos_df = directory_data(os.path.join(directory, "pos"))
    neg_df = directory_data(os.path.join(directory, "neg"))
    pos_df['sentiment'] = 1
    neg_df['sentiment'] = 0
    
    return pd.concat([pos_df, neg_df])

 

- 위에서 만든 함수를 사용해서 긍정과 부정중 어떤 폴도로 접근할지를 정한다.

- 그리고 각각 데이터 프레임으로 받아 합친다.

 

 

train_df = data(os.path.join(os.path.dirname(dataset),"aclImdb","train"))
test_df = data(os.path.join(os.path.dirname(dataset),"aclImdb","text"))

 

- 위에서 만든 두개의 함수를 사용해서 최종 train, text 데이터 프레임을 생성한다.

 

 

데이터 확인하기

train_df.head()

 

- 데이터가 잘 들어왔는지 상위 5개만 확인한다.

 

데이터프레임 확인하기

 

reviews = list(train_df['review'])

 

- 데이터 프레임의 review칼럼안에 리뷰들이 들어있다. 

- 리뷰들을 가져와서 list 형태로 변환시켜 새로운 변수에 넣는다.

 

 

tokenized_reviews = [r.split() for r in reviews]

 

- 리스트에 들어있는 리뷰들을 공백을 기준으로 잘라서 새롭게 리스트 안에 넣는다.

- 배열안에 배열 형태로 들어간다.

 

 

review_len_by_token = [len(t) for t in tokenized_reviews]

 

- 공백을 기준으로 잘라진 단어들의 갯수를 확인해서 그 길이를 저장한다.

- 각 리뷰별 단어의 갯수

 

 

review_len_by_eumjeol = [len(s.replace(' ', '')) for s in reviews]

 

- 토크나이징된 것을 붙여서 음절의 길이를 저장한다.

- 각 리뷰별 알파벳의 개수

 

 

데이터 시각적으로 확인하기

import matplotlib.pyplot as plt

 

- 필요한 라이브러리 불러오기

 

 

plt.figure(figsize = (12,5))

plt.hist(review_len_by_token, bins = 50, alpha=0.5, color="r", label="word")
plt.hist(review_len_by_eumjeol, bins = 50, alpha=0.5, color="b", label="aplt.yscallphabet")

plt.yscale('log', nonposy = 'clip')
plt.title('Review Length Histogram')
plt.xlabel('review length')
plt.ylabel('number of reviews')

 

- bins : 히스토그램 값에 대한 버킷 범위 / alpha : 투명도 / color : 색상 / label : 라벨

 

결과 창

 

- 위의 데이터를 통해 문장에 대한 길이 분포를 확인 할 수 있다.

- 빨간색 히스토그램은 단어 개수에 대한 히스토그램

- 파란색의 알파벳 개수의 히스토그램

 

 

데이터를 통계치로 수치화

# 단어 갯수 기반

print('문장 최대 길이 : {}'.format(np.max(review_len_by_token)))
print('문장 최소 길이 : {}'.format(np.min(review_len_by_token)))
print('문장 평균 길이 : {:.2f}'.format(np.mean(review_len_by_token)))
print('문장 길이 표준편타 : {:.2f}'.format(np.std(review_len_by_token)))
print('문장 중간 길이 : {}'.format(np.median(review_len_by_token)))
print('제 1사분위 길이 : {}'.format(np.percentile(review_len_by_token, 25)))
print('제 3사분위 길이 : {}'.format(np.percentile(review_len_by_token, 75)))

 

- 단어 갯수 기반으로 데이터 분포를 통계치로 수치화

 

 

# 알파벳 갯수 기반

print('문장 최대 길이 : {}'.format(np.max(review_len_by_eumjeol)))
print('문장 최소 길이 : {}'.format(np.min(review_len_by_eumjeol)))
print('문장 평균 길이 : {:.2f}'.format(np.mean(review_len_by_eumjeol)))
print('문장 길이 표준편타 : {:.2f}'.format(np.std(review_len_by_eumjeol)))
print('문장 중간 길이 : {}'.format(np.median(review_len_by_eumjeol)))
print('제 1사분위 길이 : {}'.format(np.percentile(review_len_by_eumjeol, 25)))
print('제 3사분위 길이 : {}'.format(np.percentile(review_len_by_eumjeol, 75)))

 

- 알파벳 갯수 기반으로 데이터 분포를 통계치로 수치화

 

 

 

박스플롯으로 시각화

- 박스플롯을 사용하면 전체적인 데이터의 분포를 확인할 수 있다.

- 박스플롯을 통해 이상치가 심한 데이터를 확인 할 수 있다.

- 이상치가 심하면 데이터의 범위가 너무 넓어 학습이 효율적으로 이루어지지 않는다.

 

# 단어 갯수 기반

plt.figure(figsize=(12,5))
plt.boxplot([review_len_by_token],
            labels = ['Word'],
            showmeans=True)

 

- 첫 번째 인자 : 데이터리스트 / 두 번째 인자 : 라벨 / 세번째 인자 : 평균값을 마크할지 안할지 여부

- 단어 기반의 박스플롯 아웃풋

 

 

# 알파벳 갯수 기반

plt.figure(figsize=(12,5))
plt.boxplot([review_len_by_eumjeol],
            labels = ['Alphabet'],
            showmeans=True)

 

- 첫 번째 인자 : 데이터리스트 / 두 번째 인자 : 라벨 / 세번째 인자 : 평균값을 마크할지 안할지 여부

- 알파벳 기반의 박스플롯 아웃풋

 

 

 

워드 클라우드

from wordcloud import WordCloud, STOPWORDS
import matplotlib.pyplot as plt
%matplotlib inline

 

- 필요한 라이브러리 로딩

- wordcloud는 설치해야한다.

 

wordcloud = WordCloud(stopwords=STOPWORDS, background_color='black', width=800, height=600)
wordcloud = wordcloud.generate(' '.join(train_df['review']))

plt.figure(figsize=(15,10))
plt.imshow(wordcloud)
plt.axis('off')
plt.show()

 

- stopwords는 빈도수를 계산할 때 제외되는 단어 (영어는 STOPWORDS에 저장되어있다)

 

WORDCLOUD

 

 

긍부정 분포 확인하기

import seaborn as sns
import matplotlib.pyplot as plt

 

- 필요한 라이브러리 로딩하기

- seaborn은 추가적으로 설치해주어야한다.

 

 

sentiment = train_df['sentiment'].value_counts()
fig, axe = plt.subplots(ncols = 1)
fig.set_size_inches(6,3)
sns.countplot(train_df['sentiment'])

 

- 데이터 프레임의 sentiment를 읽어서 값을 카운트한다.

- 동일한 값끼리 count가 된다.

 

- 확인해보면 긍정과 부정의 갯수가 12,000 로 같다.

- 데이터의 균형이 좋다.

반응형