morijwana
수로그
morijwana
전체 방문자
오늘
어제
  • 분류 전체보기
    • 강의노트
    • Machine Learning
      • Pandas
      • NLP
    • Computer Science
      • Linux
      • TIL
    • Development
      • React
      • Swift
      • Javascript
    • 스터디 기록
      • Clean Code
      • 구글 BERT의 정석
      • 개발도서
      • 기타
    • Problem Solving
      • Baekjoon
      • ICPC Sinchon
    • 끄적
      • 끄적끄적
      • 요리왕

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • nlp
  • 민트하임스터디
  • 개발도서
  • 데이터사이언스
  • 프레임워크없는프론트엔드개발
  • Bert
  • 회고
  • gdsc
  • 프로그래밍언어론
  • word2vec
  • GDSC Sookmyung
  • 자연어처리
  • 백준
  • Python
  • 구부정스터디
  • cs224n
  • Pandas
  • Solution Challenge
  • ML
  • 구글BERT의정석

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
morijwana

수로그

Machine Learning/NLP

[파이토치로 배우는 자연어처리] 레스토랑 리뷰 감성 분류하기 - (1)데이터 전처리

2021. 10. 22. 22:26
이 글은 한빛미디어의 '파이토치로 배우는 자연어처리' 글을 읽고 정리한 것입니다.

 

퍼셉트론과 지도 학습 훈련 방법을 사용해 옐프(Yelp) 의 레스토랑 리뷰가 긍정적인지 부정적인지 분류하는 작업을 해보자. 데이터를 로드하고 전처리하는 전체 코드는 여기서 확인할 수 있다.

Dataset: 옐프 리뷰 데이터셋

이 실습에서는 2015년에 옐프가 주최한 레스토랑 등급 예측 대회에서 사용되었던 레스토랑 리뷰 데이터를 간소화한 뒤 훈련 샘플과 테스트 샘플로 분류해 둔 데이터셋 중 10%를 사용한다.

전체 데이터셋 중 일부만 사용하는 이유는 크게 2가지가 있다.

  1. 작은 데이터셋을 사용하면 훈련-테스트 반복이 빠르게 이루어져 실험 속도를 높일 수 있다.
  2. 전체 데이터를 사용할 때보다 모델의 정확도가 낮다. 낮은 정확도는 일반적으로 크게 문제가 되지 않으며, 작은 데이터셋에서 얻은 지식으로 전테 데이터셋에서 모델을 다시 훈련할 수 있기 때문에, 훈련 데이터 양이 아주 많을 때 딥러닝 모델을 훈련할 수 있는 유용한 방법이다.

 

Preprocessing: 데이터 가져오고 다듬기

데이터 가져오기

우선 데이터 전처리에 필요한 라이브러리를 임포트하자. 천리길도 임포트부터 🧗🏻‍♀️

import numpy as np
import pandas as pd
import regex as re
import collections

from argparse import Namespace

전처리 과정에서 사용할 변수들도 세팅하자.

args = Namespace(
    raw_train_dataset_csv="/content/drive/MyDrive/NLP-Pytorch/data/yelp/raw_train.csv",
    raw_test_dataset_csv="/content/drive/MyDrive/NLP-Pytorch/data/yelp/raw_test.csv",
    proportion_subset_of_train=0.1,
    train_proportion=0.7,
    val_proportion=0.15,
    test_proportion=0.15,
    output_munged_csv="/content/drive/MyDrive/NLP-Pytorch/data/yelp/reviews_with_splits_lite.csv",
    seed=1337
)

이제 본격적으로 데이터를 다뤄보자. 먼저, 원본 데이터를 가져온 다음 head()로 데이터의 생김새를 간단하게 파악하자.

train_reviews = pd.read_csv(args.raw_train_dataset_csv, header=None, names=['rating', 'review'])
train_reviews.head()
  rating review
0 1 Unfortunately, the frustration of being Dr.Go...
1 2 Been going to Dr. Goldberg for over 10 years. ...
2 1 I don't know what Dr. Goldberg was like before...
3 1 I'm writing this review to give you a heads up...
4 2 All the foods is great here. But the best thing...

 

데이터 분리하기

우리는 전체 데이터셋 중 10%에 해당하는 서브셋만 사용할 것이다. 하지만 이 서브셋에 특정 rating 값을 가진 데이터만 편중되게 포함된다면 학습이 제대로 진행되지 않을 것이다. 그래서 서브셋 내의 각 rating 클래스 비율이 동일하도록, 표본집단이 모집단의 성질을 반영하도록 서브셋을 구성해야 한다.

by_rating = collections.defaultdict(list)
for _, row in train_reviews.iterrows():
  by_rating[row.rating].append(row.to_dict())

review_subset = []

for _, item_list in sorted(by_rating.items()):
  n_total = len(item_list)  # 전체 데이터셋 중 해당 rating value를 갖는 데이터의 개수
  n_subset = int(args.proportion_subset_of_train * n_total)
  review_subset.extend(item_list[:n_subset])  # 전체 데이터셋 중 n_total * 0.1만큼만 슬라이싱하여 사용

review_subset = pd.DataFrame(review_subset)
review_subset.head()
  rating review
0 1 Unfortunately, the frustration of being Dr.Go...
1 1 I don't know what Dr. Goldberg was like before...
2 1 I'm writing this review to give you a heads up...
3 1 Wing sauce is like water. Pretty much a lot of...
4 1 Owning a driving range inside the city limits ...

 

여기서 데이터셋의 각 rating 클래스의 개수를 세어보면 서로 동일한 개수의 데이터를 갖는다.

train_reviews.rating.value_counts()    # 2 280000 / 1 280000
set(review_subset.rating)    # {1, 2}

 

이렇게 처리된 데이터셋을 훈련, 검증, 테스트 세트로 분리해야 한다. 미리 정해둔 각 세트의 비율에 따라 데이터를 나눈다. 각 세트의 비율은 이 글의 2번째 코드블럭에서 선언한 args Namespace에 정의되어 있으며, args.train_proportion = 0.75, args.val_proportion = 0.15, args.test_proportion = 0.15다. 3개의 세트로 분리한 뒤에는 split 속성에 이 데이터가 어느 세트에 속한 데이터인지 표시한다.

# 별점 기준으로 나누어 훈련, 검증, 테스트 데이터셋을 만든다.
by_rating = collections.defaultdict(list)
for _, row in review_subset.iterrows():
  by_rating[row.rating].append(row.to_dict())

# 분할 데이터를 만든다.
final_list = []
np.random.seed(args.seed)

for _, item_list in sorted(by_rating.items()):
  np.random.shuffle(item_list)
  n_total = len(item_list)
  n_train = int(args.train_proportion * n_total)
  n_val = int(args.val_proportion * n_total)
  n_test = int(args.test_proportion * n_total)
    # 각 데이터에 레이블을 붙여준다.
  for item in item_list[:n_train]:
    item['split'] = 'train'

  for item in item_list[n_train:n_train+n_val]:
    item['split'] = 'val'

  for item in item_list[n_train+n_val:n_train+n_val+n_test]:
    item['split'] = 'test'

  final_list.extend(item_list)

final_reviews = pd.DataFrame(final_list)

 

데이터 정제하기

이후, 데이터를 정제하는 작업이 필요하다. 우리가 구현할 클래스는 리뷰 데이터를 공백을 기준으로 나누어 토큰을 획득하므로, 구두점 기호 앞뒤에 공백을 넣고, 구두점이 아닌 다른 기호들은 제거한다.

def preprocess_text(text):
  text = text.lower()
  text = re.sub(r"([.,!?])", r" \1 ", text)
  text = re.sub(r"[^a-zA-Z.,!?]+", r" ", text)

  return text

final_reviews.review = final_reviews.review.apply(preprocess_text)

 

다음으로, 숫자(1, 2)로 표시된 rating 열의 값들을 각각 'negative'와 'positive'로 바꿔준다.

final_reviews['rating'] = final_reviews.rating.apply({1: 'negative', 2: 'positive'}.get)

잘 바뀌었는지 final_reviews.head()로 확인해 보자.

  rating review split
0 negative terrible place to work for i just heard a stor... train
1 negative hours , minutes total time for an extremely s... train
2 negative my less then stellar review is for service . w... train
3 negative i m granting one star because there s no way t... train
4 negative the food here is mediocre at best . i went aft... train

잘 처리되었다! 이대로 csv로 저장하자 😚

final_reviews.to_csv(args.output_munged_csv, index=False)

 

다음 글에서는 전처리된 데이터셋을 가지고 본격적으로 분류 모델을 만들어볼 것이다.

저작자표시 (새창열림)

'Machine Learning > NLP' 카테고리의 다른 글

[NLP] Transformer 알아보기 - (1) Encoder  (0) 2022.01.11
Stanford cs224n (Winter 2019) | Lecture 2: Word Vectors and Word Senses  (0) 2021.12.09
Stanford CS224N (Winter 2019) | Lecture 1: Introduction and Word Vectors  (2) 2021.12.01
[파이토치로 배우는 자연어처리] 레스토랑 리뷰 감성 분류하기 - (3) 감성 분류 모델 만들기  (2) 2021.10.28
[파이토치로 배우는 자연어처리] 레스토랑 리뷰 감성 분류하기 - (2) 문장 토큰화와 Dataset  (0) 2021.10.25
    'Machine Learning/NLP' 카테고리의 다른 글
    • Stanford cs224n (Winter 2019) | Lecture 2: Word Vectors and Word Senses
    • Stanford CS224N (Winter 2019) | Lecture 1: Introduction and Word Vectors
    • [파이토치로 배우는 자연어처리] 레스토랑 리뷰 감성 분류하기 - (3) 감성 분류 모델 만들기
    • [파이토치로 배우는 자연어처리] 레스토랑 리뷰 감성 분류하기 - (2) 문장 토큰화와 Dataset
    morijwana
    morijwana
    행복한 휴학생의 devlog

    티스토리툴바