특수 산업군의 데이터일수록 사용되는 용어/어투 등이 일반 어휘와 동떨어져 있다보니, konlpy 형태소 분석기를 사용해 분석할 경우 OOV 문제로 인해 뜻하지 않는 결과를 얻는 경우가 많은 것 같다.
특수한 단어들을 모두 모아 리스트로 만들어서 예외처리를 하는 방법도 있지만... 상품/작업 풀네임과 업계 사람들이 해당 상품/작업을 지칭할 때 사용하는 줄임말(이것도 제각각이다), 일상언어에 잘 쓰이지 않는 복합명사 등을 모두 찾아내 등록하는 작업이 효율이 너무 낮다는 생각이 들었다. 초딩때 놀이터에서 자주 하던 '모래에서 조개랑 예쁜 돌 찾기 놀이' 같다고 해야할까.
그래서 OOV 문제를 해결하고자! 구글의 SentencePiece 패키지를 활용해 형태소 분석기를 생성하여 적용하기로 결정하였다.
* 코드 구현에 참고한 내용은 여기! 정말 알기 쉽게 잘 설명해주셨다 <3
01) 바이트 페어 인코딩(Byte Pair Encoding, BPE)
기계에게 아무리 많은 단어를 학습시켜도, 세상의 모든 단어를 알려줄 수는 없는 노릇입니다. 만약, 기계가 모르는 단어가 등장하면 그 단어를 단어 집합에 없는 단어란 의미에서 ...
wikidocs.net
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 |