1. 한국어 자연어처리
한국어에서 단어는 문법 단위의 기본이기는 하지만 규칙이나 구조를 일정하게 정의하기가 어렵습니다. 왜냐하면 한국어의 단어는 교착어 형태의 언어이므로 하나의 단어가 의미적 기능을 하는 부분과 문법적인 기능을 하는 부분의 조합으로 구성이 되기 때문입니다.
2. KoNLPy
형태소 분석이란 텍스트를 원형 형태로 분리하는 작업을 의미합니다. KoNLPy는 형태소 사전을 이용해 형태소 분석을 도와주는 라이브러리입니다.
KoNLPy를 통한 한국어 전처리
KoNLPy는 한국어 형태소 사전을 기반으로 한국어 단어를 추출해 주는 파이썬 라이브러리입니다.
이번 실습에서는 KoNLPy를 사용하여 한국어 문장 간 유사도 측정용 데이터셋인 KorSTS 데이터셋을 전처리하도록 하겠습니다.
지시사항
- 변수 sent에는 sts-train.tsv파일에 저장되어 있는 KorSTS 데이터셋이 들어있습니다. 첫 5개 문장을 확인하세요.
- 꼬꼬마 형태소 사전(Kkma)을 사용해서 변수 sent 내 모든 문장의 명사를 nouns 리스트에 저장하세요.
- Open Korean Text 형태소 사전(Okt)을 사용하여 변수 sent 내 각 문장의 형태소 분석의 결과를 pos_results 리스트에 저장하세요.
- 형태소 분석이 수행된 sent의 두 번째 문장의 분석 결과를 확인해보세요. 변수 sent에 stemming 기반 형태소 분석을 적용하여 sent의 두 번째 문장을 stem_pos_results 변수에 저장하세요.
# 경고문을 무시합니다.
import warnings
warnings.filterwarnings(action='ignore')
import pandas as pd
from konlpy.tag import Kkma, Okt
# sts-train.tsv 파일에 저장되어 있는 KorSTS 데이터셋을 불러옵니다.
sent = pd.read_table("sts-train.tsv", delimiter='\t', header=0)['sentence1']
# sent 변수에 저장된 첫 5개 문장을 확인해봅니다.
print(sent[:5])
# 꼬꼬마 형태소 사전을 이용해서 sent 내 문장의 명사를 nouns 리스트에 저장하세요.
nouns = []
kkma = Kkma() #클래스만들고
for s in sent:
nouns += kkma.nouns(s)
# 명사의 종류를 확인해봅니다.
print(set(nouns))
# Open Korean Text 형태소 사전을 이용해서 sent 내 형태소 분석 결과를 pos_results 리스트에 저장하세요.
pos_results = []
okt = Okt()
for s in sent:
pos_results.append(okt.pos(s))
# 분석 결과를 확인해봅니다.
print(pos_results)
# stemming 기반 형태소 분석이 적용된 sent의 두 번째 문장을 stem_pos_results 리스트에 저장하세요.
stem_pos_results = []
stem_pos_results = okt.pos(sent[1], stem =True)
print(stem_pos_results)
3. soynlp
soynlp는 사전을 사용하지 않고 학습 데이터 내 자주 발생하는 패턴을 기반으로 단어의 경계선을 구분합니다.
soynlp를 통한 한국어 전처리
soynlp는 한국어 단어 추출 중 발생할 수 있는 미등록 단어 문제를 해결할 수 있는 전처리 라이브러리입니다. soynlp는 학습 데이터에서 자주 발생하는 패턴을 기반으로 단어의 경계선을 구분하여 단어를 추출합니다.
이번 실습에서는 신문 기사를 학습 데이터로 사용하여 명사 목록을 학습한 뒤, 주어진 문장에서 명사를 추출할 예정입니다.
지시사항
- 학습에 사용할 신문 기사는 articles.txt에 저장되어 있습니다. 실습을 위해 내용은 이미 train_data에 저장되어 있습니다. 실행 버튼을 눌러 학습 문서의 개수를 확인하세요.
- 명사 추출을 위해 LRNounExtractor_v2 객체를 생성하세요.
- 생성한 LRNounExtractor_v2 객체를 train_data로 학습을 진행한 뒤 생성된 명사 목록을 nouns 변수에 저장하세요.
- 생성된 명사 목록을 사용해서 문장이 들어있는 sent에서 명사를 추출해 sent_nouns 리스트에 저장하세요.
from soynlp.utils import DoublespaceLineCorpus
from soynlp.noun import LRNounExtractor_v2
sent = '트와이스 아이오아이 좋아여 tt가 저번에 1위 했었죠?'
# 학습에 사용할 데이터가 train_data에 저장되어 있습니다.
corpus_path = 'articles.txt'
train_data = DoublespaceLineCorpus(corpus_path)
print("학습 문서의 개수: %d" %(len(train_data)))
# LRNounExtractor_v2 객체를 이용해 train_data에서 명사로 추정되는 단어를 nouns 변수에 저장하세요.
noun_extr = LRNounExtractor_v2() #클래스객체 만들고
nouns = noun_extr.train_extract(train_data)
# 생성된 명사의 개수를 확인해봅니다.
print(len(nouns))
# 생성된 명사 목록을 사용해서 sent에 주어진 문장에서 명사를 sent_nouns 리스트에 저장하세요.
sent_nouns = [] #명사 추출하기
for word in sent.split():
if word in nouns:
sent_nouns.append(word)nt_nouns.
print(sent_nouns)
4. 문장유사도
자카드 지수를 통한 문장 유사도 측정
자카드 지수는 두 문장 간 공통된 단어의 비율로 문장 간 유사도를 측정합니다. 이번 실습에서는 직접 자카드 지수를 계산하는 cal_jaccard_sim함수를 구현하고, nltk에서 이미 구현된 자카드 거리 함수와 비교해 볼 예정입니다.
import nltk
sent_1 = "오늘 중부지방을 중심으로 소나기가 예상됩니다"
sent_2 = "오늘 전국이 맑은 날씨가 예상됩니다"
def cal_jaccard_sim(sent1, sent2):
# 각 문장을 토큰화 후 set 타입으로 변환하세요.
words_sent1 = set(sent1.split())
words_sent2 = set(sent2.split())
# 공통된 단어의 개수를 intersection 변수에 저장하세요.
intersection = words_sent1.intersection(words_sent2)
# 두 문장 내 발생하는 모든 단어의 개수를 union 변수에 저장하세요.
union = words_sent1.union(words_sent2)
# intersection과 union을 사용하여 자카드 지수를 계산하고 float 타입으로 반환하세요.
return float(len(intersection)/len(union))
# cal_jaccard_sim() 함수 실행 결과를 확인합니다.
print(cal_jaccard_sim(sent_1, sent_2))
# nltk의 jaccard_distance() 함수를 이용해 자카드 유사도를 계산하세요.
sent1_set = set(sent_1.split())
sent2_set = set(sent_2.split())
nltk_jaccard_sim = 1 - nltk.jaccard_distance(sent1_set, sent2_set)
# 직접 정의한 함수와 결과가 같은지 비교합니다.
print(nltk_jaccard_sim)
마무리
마무리