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

NLP : SentencePiece 패키지로 tokenizer 만들기!

by E0 2021. 11. 5.

특수 산업군의 데이터일수록 사용되는 용어/어투 등이 일반 어휘와 동떨어져 있다보니, konlpy 형태소 분석기를 사용해 분석할 경우 OOV 문제로 인해 뜻하지 않는 결과를 얻는 경우가 많은 것 같다.

특수한 단어들을 모두 모아 리스트로 만들어서 예외처리를 하는 방법도 있지만... 상품/작업 풀네임과 업계 사람들이 해당 상품/작업을 지칭할 때 사용하는 줄임말(이것도 제각각이다), 일상언어에 잘 쓰이지 않는 복합명사 등을 모두 찾아내 등록하는 작업이 효율이 너무 낮다는 생각이 들었다. 초딩때 놀이터에서 자주 하던 '모래에서 조개랑 예쁜 돌 찾기 놀이' 같다고 해야할까.

 

그래서 OOV 문제를 해결하고자!  구글의 SentencePiece 패키지를 활용해 형태소 분석기를 생성하여 적용하기로 결정하였다. 

 

* 코드 구현에 참고한 내용은 여기! 정말 알기 쉽게 잘 설명해주셨다 <3

https://wikidocs.net/22592

 

01) 바이트 페어 인코딩(Byte Pair Encoding, BPE)

기계에게 아무리 많은 단어를 학습시켜도, 세상의 모든 단어를 알려줄 수는 없는 노릇입니다. 만약, 기계가 모르는 단어가 등장하면 그 단어를 단어 집합에 없는 단어란 의미에서 ...

wikidocs.net

 

https://wikidocs.net/86657

 

02) 센텐스피스(SentencePiece)

앞서 서브워드 토큰화를 위한 BPE(Byte Pair Encoding) 알고리즘과 그 외 BPE의 변형 알고리즘에 대해서 간단히 언급했습니다. 물론, 알고리즘을 아는 것도 ...

wikidocs.net

 

with open('content.txt','w',encoding='UTF-8') as f:
    f.write('\n'.join(data['content']))
    
from sentencepiece import SentencePieceTrainer
SentencePieceTrainer.Train('--input=content.txt --model_prefix=content --vocab_size=50000')

from sentencepiece import SentencePieceProcessor
sp=SentencePieceProcessor()
sp.load('content.model')

최대한 많은 신조어와 업계 용어를 반영하고 싶어서 vocab_size는 50000을 넣었다. 

이렇게 모델을 만들어 load하고 테스트를 진행해보았다.

 

text="무한로딩 뭐냐 재설치 10번해도 무한로딩 이네. 개빡친다 이딴 쓰레기앱을 누가씀? ㅋㅋ"
sp.encode_as_pieces(text)
['▁무한로딩', '▁뭐냐', '▁', '재설치', '▁', '10', '번', '해도', '▁무한로딩', '▁', '이네', '.', '▁',
 '개빡친다', '▁', '이딴', '▁쓰레기앱', '을', '▁', '누가', '씀', '?', '▁', 'ᄏᄏ']

 

무한로딩, 개빡친다, 쓰레기앱, 재설치가 하나의 단어로 잡혔다. 만족!

 

다른 문장으로 한 번 더 테스트 해봤다.

 

text="어떻게만들면 거지같이만들수있지 만든사람 진짜 노답이네"
sp.encode_as_pieces(text)
['▁어떻게', '만들면', '▁거지같이', '만들수있', '지', '▁만든사람', '▁진짜', '▁', '노답이네']

vocab_size를 크게 했더니 '노답'과 '이네'가 붙어버렸다. 좀 조정이 필요해 보인다.

 

 

konlpy의 Okt와 Komoran의 형태소 분석 결과와 비교해보면 다음과 같다.

 

Okt

# "무한로딩 뭐냐 재설치 10번해도 무한로딩 이네. 이딴 쓰레기앱을 누가씀? ㅋㅋ"

[('무한', 'Noun'),
 ('로딩', 'Noun'),
 ('뭐', 'Noun'),
 ('냐', 'Josa'),
 ('재', 'Noun'),
 ('설치', 'Noun'),
 ('10', 'Number'),
 ('번해도', 'Adjective'),
 ('무한', 'Noun'),
 ('로딩', 'Noun'),
 ('이네', 'Josa'),
 ('.', 'Punctuation'),
 ('개', 'Noun'),
 ('빡친다', 'Adjective'),
 ('이딴', 'Modifier'),
 ('쓰레기', 'Noun'),
 ('앱', 'Noun'),
 ('을', 'Josa'),
 ('누가', 'Noun'),
 ('씀', 'Verb'),
 ('?', 'Punctuation'),
 ('ㅋㅋ', 'KoreanParticle')]

무한로딩이 분리됐다.

 

Komoran

# "무한로딩 뭐냐 재설치 10번해도 무한로딩 이네. 이딴 쓰레기앱을 누가씀? ㅋㅋ"

[('무한', 'NNP'),
 ('로딩', 'NNP'),
 ('뭐', 'NP'),
 ('냐', 'EC'),
 ('재', 'XPN'),
 ('설치', 'NNP'),
 ('10', 'SN'),
 ('번', 'NNB'),
 ('해도', 'NNP'),
 ('무한', 'NNP'),
 ('로딩', 'NNP'),
 ('이', 'VCP'),
 ('네', 'EF'),
 ('.', 'SF'),
 ('개빡친다', 'NA'),
 ('이', 'MM'),
 ('딴', 'NNB'),
 ('쓰레기앱을', 'NA'),
 ('누가', 'NNP'),
 ('씀', 'NNG'),
 ('?', 'SF'),
 ('ㅋㅋ', 'NA')]

Komoran은 개빡친다는 원하는 형태로 나왔는데, 마찬가지로 무한로딩이 분리됐다.

 

실제 업무에서 사용되는 표현을 최대한 많이 줍는 것이 이번 프로젝트의 목표이기 때문에 

일단 1차적인 목표는 달성한 것 같다..?!

 

 

 

 

 

 

 

 

 

 

 

 

'공부 > 데이터분석' 카테고리의 다른 글

모델 정리  (0) 2022.11.09
PageRank / TextRank  (0) 2022.01.05
자카드 유사도 이용하여 의미상 중복 제거하기  (0) 2021.11.18
TFIDF (Term Frequency Inverse Document Frequency)  (0) 2021.08.27