본문 바로가기
데이터 분석/Python

[텍스트 마이닝-분석] 한글 N-gram 분석

by 초코레모네이드 2023. 9. 18.

 
 
N-gram은 언어 모델을 만들 때 쓰이는 확률론적 언어 모형입니다.
몇 개의 단어를 묶느냐에 따라서 Unigram(1), Bigram(2), Ngram(3개 이상) 등으로 불립니다.
https://datascienceschool.net/03%20machine%20learning/03.01.05%20%ED%99%95%EB%A5%A0%EB%A1%A0%EC%A0%81%20%EC%96%B8%EC%96%B4%20%EB%AA%A8%ED%98%95.html

확률론적 언어 모형 — 데이터 사이언스 스쿨

.ipynb .pdf to have style consistency -->

datascienceschool.net

 
영어의 경우 NLTK 내에 Ngram 생성 명령이 있지만
한글은! .. ... 없습니다. (😂)
하지만, 위대한 파이썬에는 내장함수 zip이 있습니다.
zip 함수를 통해 아주 간편하게 Bigram을 만들 수 있습니다.
저는 언어 모델을 만들지 않고, 단순히 함께 쓰인 두 개의 단어들의 빈도를 계산하고자 했기 때문에 zip을 이용하여 Bigram만 계산했습니다.
 
 


 
 
먼저 분석에 필요한 모듈과 패키지를 임포트해줍니다.

import pandas as pd
import numpy as np
import re
from tqdm.notebook import tqdm
from collections import Counter # 동일한 bigram의 합계를 구할 때 사용

 
 
분석에 사용할 파일과 불용어 파일을 불러옵니다.
데이터가 클 경우 bigram의 개수도 매우 많아지기 때문에 조금이라고 줄이고자 불용어를 적용합니다.
주의할 점은, 이때 분석 대상이 되는 파일은 문장 기준입니다.
데이터 전처리 과정에서 한글과 숫자만 남기고 문장부호, 특수문자 등을 전부 제거하였기 때문에 문장이 나뉘는 지점을 알 수 없고, 줄바꿈 역시 삭제되었기 때문에 전처리 과정을 거친 본문 데이터는 함께 쓰이지 않은 단어가 bigram으로 분석되는 문제가 발생합니다.
문장분리 과정에서 따로 저장해둔 문장 파일을 형태소로 변환한 데이터를 분석에 사용합니다.

# 불용어 파일
stopdf = pd.read_csv("파일저장경로", encoding='UTF-8')
print(stopdf.columns)
stopwords = stopdf['불용어'].to_list()
print(len(stopwords))

# 분석 대상 파일
df = pd.read_csv("파일저장경로", encoding='UTF-8')
corpus = df['형태소'].to_list()
df

 
str 타입인 문장을 list of str으로 바꾸고 불용어를 제거합니다.

for i in tqdm(range(len(corpus))):
    corpus[i] = corpus[i].split(' ')
    corpus[i] = [word for word in corpus[i] if word not in stopwords]

 
불용어가 제거된 문장 데이터에 zip을 사용하여 bigram을 생성합니다.

bigram = []

for i in tqdm(range(len(corpus))):
    a = zip(corpus[i], corpus[i][1:])
    for j in a:
        bigram.append(j)

# 잘 만들어졌나 확인해봅니다.
bigram

 
이제 파이썬의 collections 모듈에서 Counter 클래스를 사용하여 동일한 bigram의 빈도 합계를 구합니다.
Counter()는 자동으로 빈도 합에 따라 내림차순 정렬을 해줍니다.

bigram_cnt = Counter(bigram).most_common(len(Counter(bigram)))
# 제일 많은 bigram을 출력해봅니다.
print(bigram_cnt[0])
# 잘 만들어졌나 확인해봅니다.
bigram_cnt

 
Counter()로 만든 bigram 합계는 dictionary 형태이므로 리스트에 담아 데이터프레임으로 저장해줍니다.

bigram_list = []

for i in tqdm(range(len(bigram_cnt))):
    if (bigram_cnt[i][0][0] not in stopwords) & (bigram_cnt[i][0][1] not in stopwords):
        bigram_list.append([bigram_cnt[i][0][0], bigram_cnt[i][0][1], bigram_cnt[i][1]])

bigram_df = pd.DataFrame(bigram_list, columns=['단어1', '단어2', '빈도'])
# 잘 만들어졌나 확인해봅니다.
bigram_df

 
단어 빈도 합계 순서대로 데이터 프레임이 잘 만들어졌다면 원하는 파일 형태로 저장하면 끝! 입니다.

# csv 파일
bigram_df.to_csv("파일저장경로", index=False, encoding='UTF-8')
# 엑셀 파일
bigram_df.to_excel("파일저장경로")

 
 
다른 기술 블로그들이 그렇듯,
코드를 블로그에 공유하는 것은 기록과 '공유'를 위해서입니다.
만약 제 글의 도움을 받아 본인의 글을 작성하신다면 출처를 남겨주시길 바랍니다.
 
문의는 댓글로 남겨주시면 확인 후 답변드리겠습니다.
 
 
 
 

728x90

댓글