*필자는 자연어 처리 전문가가 아니라 말하는 감자입니다. 틀린 내용이 있다면 너그러히 이해하고 알려주세요.
저번글에서 꼬맨틀이 작동하는 기본적인 원리에 대해서 이야기를 했었습니다. 이번 게시글에서는 저번에 다루었던 word embedding의 개념과 vector similarity의 계산을 기반으로 하여 꼬맨틀 게임을 치팅 프로그램을 만들기 위한 전처리 과정을 다루겠습니다. 대부분의 내용이 python code를 분석하는 내용이라 '치팅만 할래...~' 하시는 분들은 다음글로 가시면 됩니다. 전처리 된 데이터만 날먹하시고 싶은 분들도 다음 글로...
우선 공개되어 있는 오픈소스를 제작자 분의 repo에서 가지고 와야 합니다만 이후 다룰 내용들도 있으니 그냥 제 github repo를 걸어두겠습니다. 다운을 받던가 'git clone <link>' 명령어를 terminal에 입력하여서 repo를 긁어오시면 됩니다. 기본적인 코드들은 해당 repo에 이미 작성되어 있으니, 다음은 data를 준비해야 합니다. repo에서는 명령어를 기반으로 데이터를 가지고 오는 방식을 소개하고 있습니다. 아래의 명령어들을 긁어온 repo directory에서 실행하면 데이터가 받아집니다.
cd data
wget https://dl.fbaipublicfiles.com/fasttext/vectors-crawl/cc.ko.300.vec.gz
gzip -d cc.ko.300.vec.gz
wget https://github.com/spellcheck-ko/hunspell-dict-ko/releases/download/0.7.92/ko-aff-dic-0.7.92.zip
unzip ko-aff-dic-0.7.92.zip
해당 방법은 mac이나 linux 환경에 최적화 된(?) 명령이어서 window 환경에서는 잘 안되었던 기억이 있는데, 문제가 있으신 분들은 아래 링크들을 직접 chrome 등에 입력하시면 바로 데이터가 다운이 됩니다.
https://dl.fbaipublicfiles.com/fasttext/vectors-crawl/cc.ko.300.vec.gz
https://github.com/spellcheck-ko/hunspell-dict-ko/releases/download/0.7.92/ko-aff-dic-0.7.92.zip
첫번째 링크는 단어들과 그 단어를 FastText를 기반으로 300차원의 vector로 embedding한 결과가 들어있습니다. 두번째 링크에는 올바른 한국어인지 확인하기 위한 데이터들이 들어있는 사전이라고 생각하시면됩니다. 다운받은 데이터들은 clone 해온 repo의 directory 내부 data 폴더에 집어 넣어주고, 두 파일 모두 unzip 해줍니다.
이제 데이터를 모두 받아왔으니, 데이터를 전처리(pre-processing)하는 과정을 거칩니다. 저번 글에서 이야기한 비속어를 필터링 하는 작업을 포함하여 한국어가 아니거나 사전에 등록되어 있지 않은 단어들은 이 과정에서 제거 됩니다. 실행하는 파일은 filter_words.py 입니다. 코드를 실행하는 과정에서 package가 설치가 안되어 있어서 오류가 생긴다면 해당 package를 따로 설치해주거나 제작자 분이 제공하시는 docker 환경을 사용하시면 좋을 듯 합니다. 대충 코드를 훑어 봅시다. main 함수 내부에서 'kor_unsmile'이라는 model을 불러옵니다.
if __name__ == '__main__':
model_name = 'smilegate-ai/kor_unsmile'
model = BertForSequenceClassification.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)
해당 모델은 입력된 단어가 비속어인지 아닌지를 판별해주는 model으로 보입니다. 해당 모델에서 비속어에 속하는 단어들은 이후 반복문 안에서 제거가 되고 unknown으로 분류된 알 수 없는 단어들도 이 과정에서 제거가 됩니다. 필터링이 완료된 단어들은 'data/filtered_frequent_words.txt'와 './data/ko-aff-dic-0.7.92/ko_filtered.txt'에 저장이 됩니다. 정확한 시간은 기억이 나지 않지만 제 데스크톱 환경에서 3분정도 걸렸던 것으로 기억합니다. 'data/filtered_frequent_words.txt' 파일은 정답으로 나올 수 있는(?) 자주 쓰이는 단어들을 따로 저장해둔 것으로 보입니다. 갑자기 '선형회귀'와 같이 사람들이 잘 알지 못하는 단어가 정답으로 선정되지 않도록, 일반적인 사람들은 모두 알 법한 단어들만 선정 해둔 것으로 보입니다.
앞선 과정들은 모두 '단어'들을 정리하는 과정이었습니다. 다음 과정들은 이제 정리된 '단어'들에 대한 '임베딩'을 얻을 차례입니다. 일반적으로 embedding을 계산하는 방식은 원하는 입력을 FastText 등의 학습된 model에 집어넣는 것이 일반적 입니다. 하지만 이러한 embedding model들을 매번 정답을 입력했을 때마다 호출하여서 embedding vector를 새로 계산하는 것은 비효율적입니다. 개발자의 입장에서 서버에 연산 부하를 줄일 수 있는 방법은 미리 계산하여서 embedding vector들을 가지고 있는 것이지요. 그런데 우리는 앞서 해당 vector들을 얻어뒀습니다. process_vecs.py 파일에서는 정리해둔 단어들을 대상으로 vector들을 정리해봅시다. 다른 것들은 저도 사실 별 관심이 없고 핵심적인 역할을 하는 부분은 다음 부분인 것 같습니다.
with open('data/cc.ko.300.vec', 'r', encoding='utf-8', errors='ignore') as w2v_file:
_ = w2v_file.readline()
t = tqdm(total=total_lines, desc='Processing vectors', mininterval=1)
for n, line in enumerate(w2v_file):
# careful! some data sets (e.g. dewiki100.txt) have non-breaking spaces, which get split
# others have trailing spaces (e.g. COW.token.wang2vec), meaning an empty string is included with split(' ')
words = line.rstrip().split(' ')
word = words[0]
word = unicodedata.normalize('NFC', word)
if not is_hangul(word) or word in checked_words:
eliminated += 1
else:
vec = array([float(w1) for w1 in words[1:]])
if word in normal_words:
valid_nearest.append(word)
if valid_nearest_mat is None:
valid_nearest_mat = [vec]
else:
valid_nearest_mat.append(vec)
'cc.ko.300.vec' 파일을 읽어와서 해당 단어가 한글이며 동시에 앞에서 정리해둔 단어에 들어있는 valid한 단어들만 valid_nearest_mat이라는 변수에 저장해둡니다.
valid_nearest_mat = np.array(valid_nearest_mat)
print("valid nearest shape:", valid_nearest_mat.shape)
with open('data/valid_nearest.dat', 'wb') as f:
pickle.dump((valid_nearest, valid_nearest_mat), f)
이후 해당 정보들을 ([words], [vecs]) 형태로 정리하여 'data/valid_nearest.dat'에 모두 저장합니다. 저는 해당 부분에서 오류가 있어서 data/valid_nearest.pkl' 확장자로 저장하였고 이후 코드들은 .pkl 확장자 데이터를 가지고 작성하였습니다. 해당 코드는 제 데스크톱 환경에서 1시간 가량 시간이 소요되었던 것으로 기억합니다.
'호에에엥? > Side Project' 카테고리의 다른 글
| 꼬맨틀로 NLP(자연어 처리) 찍먹하기 (3) - 꼬맨틀 치팅 프로그램 만들기! (完) (4) | 2022.12.21 |
|---|---|
| 꼬맨틀로 NLP(자연어 처리) 찍먹하기 (1) - 꼬맨틀의 단어 유사도 측정의 원리와 유사도가 이상한 이유! (2) | 2022.12.09 |