내겐 '야구'라는 주제로 뭉친 친구들의 단체 카톡방이 있다. 여느 야구팬들이 보통 그렇듯이, 야구 경기를 보면서 희노애락의 이야기들을 나누곤 한다. 16년차 한화팬인 나는 올 시즌에도 기대에 못 미치는 경기력을 보며 한탄을 하던 도중 문득 궁금해졌다.
'이겨도 져도 욕하는 야구라지만 성적이 좀 괜찮다면 욕을 좀 덜하지 않았을까?'
하는 생각을 가지고 가볍게 재미를 가지고 카카오톡 메시지를 통해 긍/부정어 분석을 진행해보았다.
필요한 라이브러리
import pandas as pd
import torch
from transformers import BertTokenizer, BertForSequenceClassification
from transformers import TextClassificationPipeline
import re
import matplotlib.pyplot as plt
%matplotlib inline
사용한 라이브러리는 데이터를 dataframe으로 변환해 다룰 수 있는 Pandas, BERT 모델을 이용해 긍/부정 점수를 계산할 것이므로 Pytorch, 형태소 분석 및 토크나이저, 파이프라인을 위한 Transformers, txt파일을 다루기 위해 정규 표현식을 쓸 것이므로 re, 그리고 그래프를 그리기 위한 matplotlib이 있다.
txt 파일 dataframe으로 변환
카카오톡 내에서 내보내기를 통해 메시지를 txt파일로 받게 되면 아래와 같은 형태로 txt파일이 제공된다.
2022년 7월 11일 오전 8:49, XXX : 일단 화수는 안될 듯 동생 약속잇대
2022년 7월 11일 오전 8:50, XXX : 둘이 화요일에 봐라..
이 파일을 단순히 split() 메서드를 통해 나누게 된다면 dataframe의 칼럼으로 다루기가 모호해진다. 그래서 아래와 같이 정규표현식을 이용해 내가 의도한 칼럼 별로 데이터가 나눠지도록 했다.
# 텍스트 파일 불러오기
with open('/content/drive/MyDrive/baseball_talk/chat_data_single_line.txt', 'r', encoding='utf-8') as file:
lines = file.readlines()
# 정규 표현식 패턴
pattern = re.compile(r'(\d{4})년 (\d{1,2})월 (\d{1,2})일 (.*) (\d{1,2}:\d{2}), (.*) : (.*)')
# 결과를 저장할 리스트
parsed_data = []
for line in lines:
match = pattern.match(line.strip())
if match:
year, month, day, ampm, time, speaker, message = match.groups()
parsed_data.append([year, month, day, ampm, time, speaker, message])
그리고 이를 기준으로 dataframe을 만들어준다.
df = pd.DataFrame(parsed_data, columns = ['Year', 'Month', 'Day', 'AMPM', 'Time', 'Speaker', 'Message'])
긍/부정어 감정 분석
# BERT 모델과 토크나이저 불러오기
model_name = "beomi/kcbert-base"
tokenizer = BertTokenizer.from_pretrained(model_name)
model = BertForSequenceClassification.from_pretrained(model_name)
이제 긍/부정 감정 분석에 사용할 BERT 모델과 토크나이저를 불러온다. 한국어를 대상으로 하는 분석이기 때문에, kcBERT를 사용했다.
# 파이프라인 생성
pipeline = TextClassificationPipeline(model=model, tokenizer=tokenizer, return_all_scores=True)
그 뒤에 위 모델과 토크나이저를 기준으로 긍정/부정어를 나눌 파이프라인을 생성해준 뒤,
# 감정 분석 수행
def sentiment_analysis(message):
results = pipeline(message)
positive_score = results[0][1]['score']
negative_score = results[0][0]['score']
return positive_score, negative_score
# 대화 내용에 대해 감정 분석 수행
df['Positive'], df['Negative'] = zip(*df['Message'].map(sentiment_analysis))
sentiment_analysis 함수를 실행시켜 각 메시지에 대한 긍/부정 점수를 매기도록 한다. 이 부분에서 다소 시간이 걸린다. Colab Pro L4 GPU를 사용했을 때 기준으로 8~9분 정도 걸렸던 것 같다. 물론 메시지의 양에 따라 시간은 달라진다.
분석 결과 및 시각화
분석 결과에 앞서, 단체 카톡방의 멤버를 먼저 소개한다. 나를 포함해 총 4명이다.
- 16년차 LG팬
- 5년차 LG팬
- 5년차 KIA팬
- 16년차 한화팬(나)
그래프는 멤버 별 메시지의 긍정 점수 평균과 부정 점수 평균을 나타냈다.
그래프를 보면 알겠지만, 응원하는 팀의 성적과는 달리 점수는 생각보다 큰 차이가 없다. 실제 수치로 따져도 0.01~0.05점 차이 정도의 근소한 차이다. (오히려 성적 높은 애들이 더하다.) 2022년의 데이터부터 저장되어 있어서 연도 별로도 비교해봤으나 큰 차이는 없었다.
물론 kcBERT 모델이 야구의 특성을 고려한 대화흐름을 완벽히 파악하지는 못 했을 것이다. 하지만 모두가 큰 차이 없는 결과를 보니, 응원하는 팀과는 관계없이 '야구팬들은 다 똑같구나' 하는 생각도 든다.
그리고 또 하나 놀라운 점은 부정 점수에 비해 긍정점수가 생각보다 높다는 것이다. 어떤 사람은 '야구팬들은 이래도 욕하고 저래도 욕한다'라고 하지만, 야구로 얻는 기쁨과 짜릿함도 그에 못지않게 크다라는 것을 알 수 있었다.
이 글을 쓴 날은 야구팬들에게 '지지 않는 날'로 불리우는 월요일이다. 다른 날이었다면 저 단체 카톡방에 한탄을 하느라 이 분석도 못해봤겠지... 막상 데이터를 분석하면서 중간 중간 보이는 메시지들이 '이때 야구 참 재밌게 봤구나' 하는 생각도 떠오르게 해 재밌는 경험으로 남을 것 같다. 그리고 내일도 똑같이 이 시간에 야구를 보고 있을텐데... 한화는 제발 좀 이겨줬으면 좋겠다.
'Minding's Programming > Knowledge' 카테고리의 다른 글
[CS/Python] 자료구조 & 알고리즘 정리 - 선형 배열, 정렬, 탐색, 재귀, 순열 (1) | 2024.09.26 |
---|---|
[Linux/WSL] 간단한 리눅스 명령어 정리 (0) | 2024.07.18 |
[Windows10/WSL2/Zsh] Windows에 zsh 설치하기 (0) | 2024.06.18 |
[Windows10/WSL2] Windows 환경에서 Linux 사용을 위한 WSL2 설치 (0) | 2024.06.18 |
[Python] OpenCV를 이용해 자동 카톡 메시지 보내기 (0) | 2023.08.19 |