NSMC(Naver Sentiment Movie Corpus) 데이터셋 이용 감성 분류(Sentiment Analysis) 문제 해결

실행 해 보기 (Corlab)

NSMC(Naver Sentiment Movie Corpus) 데이터셋은 20만 개의 영화 리뷰 데이터로 구성되어 있으며, 이를 바탕으로 긍정적인지, 부정적인지를 분류하는 감성 분류(Sentiment Analysis) 문제를 해결하는데 활용됩니다.

NSMC 데이터셋은 한글 데이터셋 중에서 가장 많이 사용되는 데이터셋 중 하나이며, 한국어 감성 분류 문제를 다루기 위한 대표적인 데이터셋으로 활용되고 있습니다. 이 데이터셋은 영화 리뷰에 대한 긍정/부정 정보를 레이블로 제공하고 있으며, 이를 학습 데이터로 활용하여 머신러닝 모델을 학습시킬 수 있습니다.

따라서 NSMC 데이터셋을 활용하면 한국어 감성 분류에 대한 다양한 연구나 분석을 수행할 수 있으며, 새로운 머신러닝 모델을 학습시키고 검증하는데에도 활용됩니다.

NSMC 데이터셋에서 train 데이터는 모델을 학습시킬 때 사용하는 원본 데이터이며, test 데이터는 학습된 모델의 성능을 평가하기 위해 사용하는 데이터로, 모델이 예측한 결과물과 실제 정답을 비교하여 모델의 성능을 측정합니다. 일반적으로 모델을 학습할 때 train 데이터와 test 데이터를 나누어서 사용하며, 모델의 성능이 일반화되고 테스트 데이터에 대해서도 잘 동작하는지 확인합니다.

https://raw.githubusercontent.com/e9t/nsmc/master/ratings_train.txt
NSMC 데이터셋의 경우, 각 영화 리뷰가 긍정(1)인지 부정(0)인지를 나타내는 레이블 데이터를 포함하고 있습니다. 이 레이블 데이터는 실제로 영화 리뷰를 작성한 사용자들이 부여한 점수를 기반으로 생성되었습니다. 예를 들어, 10점 만점에 8점 이상을 부여한 리뷰는 긍정(1)으로 분류되었고, 4점 이하를 부여한 리뷰는 부정(0)으로 분류되었습니다. 따라서 이 레이블 데이터는 사람이 임의로 만든 것이 아니라 실제 사용자들의 평가를 기반으로 생성된 것입니다.

https://raw.githubusercontent.com/e9t/nsmc/master/ratings_test.txt

ratings_test.txt 파일은 NSMC 데이터셋에서 제공하는 영화 리뷰 데이터 중에서 학습에 사용되지 않은 새로운 데이터로, 학습된 모델의 일반화 성능을 평가하기 위한 목적으로 제공됩니다. 따라서 해당 파일에 포함된 리뷰 데이터는 모두 실제로 존재하는 데이터이며, 해당 데이터에 대한 레이블(긍정/부정)을 예측하여 모델의 성능을 평가합니다.
예를 들어 데이터의 6270596 굳 ㅋ 1도 가상으로 만든 데이터가 아니며, 해당 리뷰는 실제로 존재하는 리뷰입니다. 이 리뷰에서는 “굳”이라는 축약어와 “ㅋ”이라는 이모티콘을 사용하여 긍정적인 평가를 전달하고 있으며, 해당 리뷰에 대한 레이블은 1(긍정)입니다.

NSMC 데이터셋을 이용하여 입력된 문장이 긍정인지 부정인지 판단하는 간단한 파이썬 코드는 다음과 같습니다. 이 코드는 train 데이터를 이용하여 CountVectorizer를 이용하여 단어장을 생성하고, 이를 이용하여 입력된 문장을 벡터화하여 Logistic Regression 모델을 이용하여 긍정/부정을 판단합니다.

 

import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.linear_model import LogisticRegression

# 데이터 불러오기
train_data = pd.read_csv('ratings_train.txt', sep='\t', na_values='NaN')
test_data = pd.read_csv('ratings_test.txt', sep='\t', na_values='NaN')

# null 값 제거
train_data.dropna(inplace=True)
test_data.dropna(inplace=True)

# CountVectorizer를 이용하여 단어장 생성
vectorizer = CountVectorizer(token_pattern=r'\b\w+\b')
vectorizer.fit(train_data['document'])

# train 데이터를 이용하여 Logistic Regression 모델 생성
lr = LogisticRegression(max_iter=5000)
train_X = vectorizer.transform(train_data['document'])
train_y = train_data['label']
lr.fit(train_X, train_y)

# test 데이터를 이용하여 예측 수행
test_X = vectorizer.transform(test_data['document'])
pred_y = lr.predict(test_X)

# 사용자로부터 입력 받은 문장 예측 수행
user_input = input("영화 리뷰를 입력하세요: ")
input_X = vectorizer.transform([user_input])
result = lr.predict(input_X)

# 예측 결과 출력
if result[0] == 1:
    print("긍정적인 리뷰입니다.")
else:
    print("부정적인 리뷰입니다.")

코드 설명을 좀더 상세히 하겠습니다.

#CountVectorizer를 이용하여 단어장 생성 부분

vectorizer = CountVectorizer(token_pattern=r'\b\w+\b')
vectorizer.fit(train_data['document'])

CountVectorizer는 입력된 텍스트 데이터를 분석하여 단어장을 생성하는 역할을 합니다. 단어장이란, 분석된 텍스트 데이터에서 중복되지 않는 단어들의 집합을 의미합니다.  이때, 기본적으로는 공백을 기준으로 단어를 분리합니다.

ratings_train.txt 의 “3819312 흠…포스터보고 초딩영화줄….오버연기조차 가볍지 않구나 1 “를 이용해 설명해 보겠습니다.

위 코드에서는 train_data['document']의 텍스트 데이터를 이용하여 CountVectorizer를 통해 단어장을 생성하는 부분입니다.

이를 ratings_train.txt 파일의 텍스트 데이터인 ‘흠…포스터보고 초딩영화줄….오버연기조차 가볍지 않구나’로 대체해보면 다음과 같습니다.이를 실행하면 ‘흠’, ‘포스터보고’, ‘초딩영화줄’, ‘오버연기조차’, ‘가볍지’, ‘않구나’ 등의 단어가 단어장으로 생성됩니다. 이 단어장은 이후에 다른 텍스트 데이터에 대해서도 적용되어 해당 데이터를 벡터화하는 데 사용됩니다.

위에서 주어진 코드에서는 token_pattern=r'\b\w+\b' 옵션을 통해 정규식 패턴을 설정하여, 단어를 추출할 때는 알파벳 또는 숫자가 1개 이상인 문자열만 고려하도록 설정하였습니다. 따라서, “흠”, “포스터보고”, “초딩영화줄”, “오버연기조차”, “가볍지”, “않구나” 등의 단어가 추출됩니다.
이부분만 해 보겠습니다.
실행하기 (NSMC-1)

from sklearn.feature_extraction.text import CountVectorizer

# ratings_train.txt 파일에서 한 줄을 가져옴
text = '흠...포스터보고 초딩영화줄....오버연기조차 가볍지 않구나'

# CountVectorizer를 이용하여 단어장 생성
vectorizer = CountVectorizer(token_pattern=r'\b\w+\b')
vectorizer.fit([text])

# 단어장에 생성된 단어 출력
print(vectorizer.get_feature_names())

CountVectorizer는 텍스트 데이터를 입력 받아 각 단어가 몇 번 나타나는지를 세어서 단어장(vocabulary)을 생성하는 도구입니다. 예를 들어, “흠”, “포스터보고”, “초딩영화줄”, “오버연기조차”, “가볍지”, “않구나” 등의 단어가 추출되면, 이 단어들을 단어장에 등록하고 각 단어에 인덱스를 부여합니다. 이후, 각 문장을 벡터화할 때는 각 단어가 해당 문장에서 몇 번 나타나는지를 세어서 각 단어의 인덱스에 해당하는 원소에 그 횟수를 넣어줍니다. 이렇게 벡터화하면, 각 문장은 단어의 빈도수로 이루어진 벡터로 표현됩니다.

벡터 정보의 해당 단어의 횟수 정보와 단어 내용 자체는 CountVectorizer에서 생성된 단어장(vocabulary)에 저장됩니다. CountVectorizer는 입력된 텍스트 데이터에서 단어를 추출하고, 추출한 단어들을 기반으로 단어장을 생성합니다. 이때, 각 단어는 고유한 인덱스 번호를 부여받습니다.

예를 들어, “초딩영화줄”과 “오버연기조차”가 추출되었고, 이들이 단어장에서 각각 0번과 1번의 인덱스를 부여받았다면, “초딩영화줄”이 3번, “오버연기조차”가 5번 등장한다면, 벡터 정보에서는 0번 인덱스에 해당하는 값이 3이 되고, 1번 인덱스에 해당하는 값이 5가 됩니다. 이렇게 벡터 정보와 단어 내용이 인덱스를 활용하여 연결되는 것입니다.

# train 데이터를 이용하여 Logistic Regression 모델 생성

lr = LogisticRegression(max_iter=5000)
train_X = vectorizer.transform(train_data['document'])
train_y = train_data['label']
lr.fit(train_X, train_y)

Logistic Regression은 통계학에서 개발된 분류 모델 중 하나로, 데이터를 분석하여 해당 데이터가 어떤 범주(class)에 속하는지를 예측하는 모델입니다. 이 모델은 입력 변수의 가중치 합을 로지스틱 함수(sigmoid function)에 넣어서 결과를 0~1사이의 값으로 출력하고, 이를 이진 분류(binary classification)에서 확률값으로 해석하여 예측합니다.

위의 코드에서는 sklearn 라이브러리의 LogisticRegression 클래스를 이용하여 Logistic Regression 모델을 생성합니다. 이를 위해 max_iter 매개변수를 5000으로 설정하여 최적화를 위한 최대 반복 횟수를 설정합니다. 이후, CountVectorizer 클래스로부터 생성된 단어장에서 transform 메소드를 이용하여 train 데이터의 문서들을 벡터 형태로 변환한 후, 이를 train_X 변수에 저장합니다. train_y 변수에는 train 데이터의 레이블을 저장합니다. 마지막으로, LogisticRegression 모델의 fit 메소드를 이용하여 train_X와 train_y를 이용하여 모델을 학습시킵니다.