프로젝트

웹툰 승격 확률 예측 시스템 프로젝트 - kosac사전을 이용한 감정분석 [광주인공지능학원]

취준생코린이 2021. 7. 11. 22:05
728x90

웹툰 승격 확률 예측 프로젝트에서 댓글을 가지고 긍정 부정 감정분석을 진행했어요.

먼저 kosac 한국어 감정사전을 이용하여 분석해봤고 긍정 부정 분류가 예상처럼 잘되지 않아서 다음으로는 수기로 긍정부정 라벨링을 달아주고 머신러닝을 돌려봤는데 훈련데이터의 수가 너무 적어서 정확도가 낮게 나오더라구요.

그래서 마지막으로 직접 긍정 부정 단어사전을 만들어서 머신러닝을 진행 했습니다.

 

티스토리에는 1. kosac 사전 사용 2. 수기 라벨링 3. 직접만든 단어사전 시행 착오를 전부 작성할 예정이고 

이 글에서는 1. kosac 사전 사용을 적을 거에요.

 

import numpy as np
import pandas as pd

 

댓글 데이터가 10mb가 넘어서 업로드 할수가 없네요 ㅠㅠ

먼저 데이터를 불러옵니다

저는 크롤링하고 csv파일로 저장하면서 필요없는 컬럼이 추가되어 drop으로 제거해 줬어요

# 데이터 수집
comment = pd.read_csv("전처리후데이터/댓글데이터fin.csv", encoding="cp949")
comment.drop('Unnamed: 0', axis=1, inplace = True)

 

kosac사전의 형태소가 kkma형태소를 사용해야 맞아서 시간이 너무 오래걸리더라구요.

댓글 데이터가 38만개라 예상소요시간이 며칠이나 걸린다더라구요...

따라서 웹툰 회차별로 댓글 10개만 샘플로 뽑아서 38만개중 총 2만 4천개만 분석해보기로 했습니다.

 

아래코드는 웹툰 회차별 댓글 10개만 샘플로 뽑는 코드에요.

sample이라는 함수를 써서 데이터에서 샘플을 뽑았어요.

여기서 n=10은 10개만 뽑는다는 의미에요.

replace=False는 복원추출을 허용하지 않겠다는 의미에요.

그리고 어떤 웹툰은 한화에 댓글이 10개 미만일 수 도 있어서 예외처리로 샘플 10개를 뽑을수없어서 오류가 나면 모든 댓글을 다 가져오게 작성했어요.

sampleList = pd.Series(dtype= object)
# listCom = comment['웹툰제목'].unique()[11:]
# 각웹툰 1화마다 10개 댓글만 뽑기
name = [] # 웹툰 제목
view = [] # 회차
for i in comment['웹툰제목'].unique():
    for j in range(1, 6):
        boolean1 = comment["웹툰제목"] == i
        boolean2 = comment["회차"] == j
        com1 = comment.loc[boolean1&boolean2, "댓글"]
        try: # 웹툰 한화당 10개 댓글만 샘플링하여 가져오기
            sam = com1.sample(n=10, replace=False)
            sampleList =  pd.concat([sampleList, sam], axis = 0)
            for random in range(0, 10):
                name.append(i)
                view.append(j)
        except: # 웹툰 한화가 10개 미만일경우 전부 가져오기
            if len(com1) != 0:
                sampleList =  pd.concat([sampleList, com1], axis = 0)
                for random in range(0, len(com1)):
                    name.append(i)
                    view.append(j)

위에서 샘플로 뽑은 댓글이에요

 

댓글만 보면 어떤 웹툰의 몇화 댓글인지 알수가 없어서 웹툰 제목과 회차를 묶어 데이터프레임으로 만들어 주었어요.

dd = {"웹툰제목" : name, "회차" : view, "추출된댓글" : sampleList}
Sample = pd.DataFrame(dd)
Sample

 

저는 이제 2만 4천개의 단어도 kkma형태소 분석기를 이용하면 분석시간이 너무 오래걸려서 팀원들이랑 나눠서 돌렸어요. 따라서 팀원들에게 나눠서 돌리게 하려구 csv파일로 만들어 줬습니다.

Sample.to_csv("Sample최종.csv", encoding="")

 

반응형

그리고 긍정부정 라벨링을 달아주기 위해 kosac사전을 가져옵니다.

# 감정사전
kosac = pd.read_csv("data/polarity.csv")
kosac

 

아까 만들어준 샘플 데이터인데요. 샘플데이터에 감정점수라는 컬럼을 만들어주고 모두 값을 0으로 줬어요.

그리고 댓글데이터만 total이라는 변수에 담아줬습니다.

kkma = Kkma()
sampledata = pd.read_csv("Sample최종.csv", encoding="cp949")
sampledata['감정점수'] = 0
total = sampledata["추출된댓글"]
total

 

아래 코드는 댓글데이터에서 kosac사전에 있는 단어를 발견하면 max.value컬럼을 확인하여 POS면 긍정에 +1

NEG면 부정에 +1을 하여 긍정단어 갯수 부정 단어갯수를 구하고 위에서 만들어준 감정점수라는 컬럼에 0을 긍정단어개수 - 부정 단어 개수로 바꿔 주었어요.

aa = ""
for k in range(0, len(total)):
    characters = "ㅋㄱ"
    try:
        aa = ''.join( x for x in total[k] if x not in characters)
        data = kkma.pos(aa, join=True)
    except:
        data = kkma.pos(total[k], join=True)
    print(data)
    count_POS = 0
    count_NEG = 0
    i = 0
    while i < len(data):
        for j in range(0, len(kosac)):
            if data[i] == kosac.iloc[j, 0]:
                try:
                    if data[i+1] == kosac.iloc[j+1, 0].split(";")[1]:
                        if data[i+2] == kosac.iloc[j+2, 0].split(";")[2]:
                            print(f"단어: {kosac.iloc[j+2, 0]}, 긍부정:{kosac.loc[j+2, 'max.value']}")
                            i += 3
                            if kosac.loc[j+2, 'max.value'] == 'POS': count_POS += 1
                            elif kosac.loc[j+2, 'max.value'] == 'NEG': count_NEG += 1
                            break
                        else:
                            print(f"단어: {kosac.iloc[j+1, 0]}, 긍부정:{kosac.loc[j+1, 'max.value']}")
                            i += 2
                            if kosac.loc[j+1, 'max.value'] == 'POS': count_POS += 1
                            elif kosac.loc[j+1, 'max.value'] == 'NEG': count_NEG += 1
                            break
                    else:
                        print(f"단어: {kosac.iloc[j, 0]}, 긍부정:{kosac.loc[j, 'max.value']}")
                        i += 1
                        if kosac.loc[j, 'max.value'] == 'POS': count_POS += 1
                        elif kosac.loc[j, 'max.value'] == 'NEG': count_NEG += 1
                        break
                except:
                    print("")
            elif data[i] != kosac.iloc[j, 0] and j == len(kosac)-1:
                i += 1
    print(f"긍정개수: {count_POS}, 부정개수: {count_NEG}")
    sampledata.iloc[k, 4] = count_POS - count_NEG

kosac 사전 일부

그리고 kosac사전을 보면 위에처럼 가/ 가되/ 가되ㄴ/ 가되ㄹ/ 가되어...이렇게 같은 가여도 뒤에 뭐가 오는지에 따라 나눠져 있어요. 그래서 위의 반복문에서 저걸 비교하게 조전문을 짰어요.

예를들어 ) 댓글을 형태소 분석한후 만약 가/JKC가 있으면 되/VV가 있는지 보고 되/VV가 있으면 ㄹ/ETM이 있는지 확인합니다.

 

그리고 중간중간에 있는 print문은 반복문이 잘돌아가는지 확인하기 위해 넣어줬습니다.

pirnt 출력 결과중 일부

 

그러면 아래와 같이 감정점수가 나와요.

 

안타깝게도 댓글과 감정점수를 비교해 봤는데 감정점수랑 댓글이 너무 맞지 않았어요. 그래서 이건 그냥 버렸답니다.

kosac사전을 쓰고 느낀점은 이사전은 단순히 긍정 부정 갯수를 카운트 하면 안되고 특정 조사와 명사가 같이오면 긍정에서 부정이 되거나 부정에서 긍정으로 변한다거나 어미에 따라 앞까지는 긍정이었지만 부정어미가 붙어서 부정이 된다던가 그런걸 일일히 설정해주면 좋은 결과가 나올거 같아요.

 

아쉽게도 저는 국문학과를 나오지 않았고 한국어 형태소의 감정을 세세하게 짤만큼 한글을 공부하지 않아서 KOSAC사전을 쓰는건 포기하고 다음으로는 직접 하나하나 라벨링을 다는 방법과 긍정단어 부정 단어 단어사전을 직접 만드는 방법 이렇게 2가지를 같이 진행했어요. 다음 내용은 다음글에서 작성하겠습니다.

 

 

 

이글은 광주인공지능학원(스마트인재개발원)에서 진행된 프로젝트 내용입니다.

https://www.smhrd.or.kr/

 

스마트인재개발원

4차산업혁명시대를 선도하는 빅데이터, 인공지능, 사물인터넷 전문 '0원' 취업연계교육기관

www.smhrd.or.kr

 

728x90