fast text

fastText는 Facebook의 AI Research lab에서 만든 단어 임베딩 및 텍스트 분류 학습을위한 라이브러리입니다. 이 모델을 사용하면 단어에 대한 벡터 표현을 얻기 위해 비지도 학습 또는지도 학습 알고리즘을 만들 수 있습니다.

fastText에 대한 위키에 있는 간단한 정의입니다.

fastText is a library for learning of word embeddings and text classification created by Facebook‘s AI Research (FAIR) lab[3][4][5][6]. The model allows to create an unsupervised learning or supervised learning algorithm for obtaining vector representations for words. Facebook makes available pretrained models for 294 languages.[7] fastText uses a neural network for word embedding.

Algorithm of fasttext is based on these two papers:[8]

gensim 패키지를 활용하면 간단히 활용할 수 있습니다.
word2vec을 사용하는 것보다 더 좋은 성능을 얻을 수 있고 또 입력 시에 나온 오타도 어느 정도 해결할 수 있다고 합니다. 그 이유는 char-ngram 방식을 사용하기 때문입니다.

fastText attempts to solve this by treating each word as the aggregation of its subwords. For the sake of simplicity and language-independence, subwords are taken to be the character ngrams of the word. The vector for a word is simply taken to be the sum of all vectors of its component char-ngrams.

https://radimrehurek.com/gensim/auto_examples/tutorials/run_fasttext.html

다만 계산량이 word2vec을 사용할 때보다 많아서 시간이 더 걸립니다. 아래의 공식 문서를 참고하시기 바랍니다.

Training time for fastText is significantly higher than the Gensim version of Word2Vec (15min 42s vs 6min 42s on text8, 17 mil tokens, 5 epochs, and a vector size of 100).

https://radimrehurek.com/gensim/auto_examples/tutorials/run_fasttext.html

Test Code

테스트를 위해 인터넷에 공개 되어 있는 2018년도 데이터를 다운 받았습니다. 파일 포맷은 csv형태로 되어 있습니다.

def read_data(filename):    
    with open(filename, 'r',encoding='utf-8') as f:
        data = [line.split(',t') for line in f.read().splitlines()]        
        data = data[1:]   # header 제외 #    
    return data 
    
train_data = read_data('./data/2018_simpan_newgroup.csv') 

테스트를 위해 받은 텍스트 파일의 형태는 다음과 같습니다.

[['0|이 건 심판청구는 처분청의 직권경정으로 인하여 심리일 현재 청구의 대상이 되는 처분이 존재하지 아니하므로 부적법한 청구로 판단됨|0'],
 ['1|처분청의 2016년 제2기 부가가치세 경정결정 후 청구인이 심판청구를 제기하여 2017.10.24. 이미 기각결정을 받았으므로 이 건 심판청구는 동일한 처분에 대하여 중복하여 제기된 점, 청구인은 당초 심판청구와 동일한 내용의 경정청구를 하였고, 그에 대한 처분청의 거부통지는 민원회신에 불과한 것이어서 심판청구의 대상이 되는 처분으로 볼 수 없는 점 등에 비추어 이 건 심판청구는 부적법한 청구로 판단됨|0'],
 ['2|처분청이 청구주장을 받아들여 이 건 과세처분을 직권으로 감액경정하였으므로 이 건 심판청구는 심리일 현재 불복 대상이 되는 처분이 존재하지 아니하여 부적법한 청구에 해당하는 것으로 판단됨|0'],
 ['3|쟁점건물은 종교인과 일반인을 상대로 종교서적 등을 판매하는 매장으로 사용되는 것으로 나타나고, 달리 종교용도로 직접 사용되었다고 인정할 만한 사실이 확인되지 아니하므로 처분청이 종교목적으로 직접 사용하지 아니한 것으로 보아 이 건 재산세 등을 부과한 처분은 잘못이 없다고 판단됨.|1']...

리스트 형태로 데이터가 들어오고 2372문장을 테스트로 사용합니다.

해당 문장에는 여러가지 특수기호가 있기 때문에 적절히 전처리를 해줍니다.

전처리 후에 konlpy.Okt()를 활용하여 각 문장을 형태소 단위로 나눠줍니다.

def tokenize(doc):
    s = doc[0].split('|')
    # 이부분에 특수문자 제거 등의 전처리를 해주시면 됩니다. 
    return ['/'.join(t) for t in pos_tagger.pos(s, norm=True, stem=True)]

tokens = [tokenize(row) for row in train_data]
[['이/Noun','건/Noun','심판/Noun','청구/Noun','는/Josa','처분/Noun','청/Noun','의/Josa','직권/Noun','경정/Noun','으로/Josa','인하다/Adjective','심리/Noun','일/Noun','현재/Noun','청구/Noun','의/Josa','대상/Noun','이/Josa','되다/Verb','처분/Noun','이/Josa','존재/Noun','하다/Verb','아니다/Adjective','부/Noun','적법하다/Adjective','청구/Noun','로/Josa','판단/Noun','되다/Verb']]

위와 같은 형태로 분리됩니다.

model = gensim.models.fasttext.FastText(size=100)
model.build_vocab(tokens)
model = gensim.models.fasttext.FastText(size=100)
model.build_vocab(tokens)

model.train(tokens, window=5, epochs=model.epochs, total_examples=model.corpus_count)
model.alpha -= 0.002
model.min_alpha = model.alpha

다음과 같이 수행합니다. 필요에 따라서 다양한 옵션을 사용하여 훈련을 진행하시면 됩니다. gensim 사이트에 가시면 이에 대한 내용이 설명되어 있습니다.

부동산을 입력했더니 아래와 같은 결과를 얻었습니다.

model.wv.similar_by_word('부동산/Noun')
[('취득/Noun', 0.9003169536590576),
 ('가액/Noun', 0.8994468450546265),
 ('정산/Noun', 0.8911253213882446),
 ('환산/Noun', 0.8888809084892273),
 ('연말정산/Noun', 0.8887563943862915),
 ('자산/Noun', 0.8879978656768799),
 ('재산/Noun', 0.8878995180130005),
 ('전액/Noun', 0.8871012330055237),
 ('분산/Noun', 0.8870201110839844),
 ('거액/Noun', 0.8869702816009521)]

해당 모델은 100차원으로 되어 있는데 그것은 위에 모델을 선언할 때에 size=100으로 설정했기 때문입니다.

model.wv['부동산/Noun']
array([ 0.23454253, -0.7865744 , -0.46801254, -0.11220518,  0.49738216,
        0.51051146,  0.28836748,  0.24520665, -0.2823485 ,  0.12481502,
        0.31313908,  0.09823137,  0.9331261 , -0.63185096,  0.79251087,
        0.07525934,  0.5575937 ,  0.6052933 , -0.36211282,  0.43174762,
        0.0608188 ,  0.18941545,  0.35179955, -0.43175125, -0.48578402,
        0.7635253 ,  0.19132383,  0.83176637, -0.4213232 ,  0.2916827 ,
        0.06576332,  0.03166943, -0.5215866 , -0.9714561 , -0.43011758,
        0.14605877,  0.77329254,  0.18222107,  0.5664433 ,  0.971345  ,
        0.65927994,  0.3893743 , -0.09935822,  0.2923206 ,  0.12915374,
       -0.14681472,  0.05491441, -0.27698728,  0.01709399,  0.26082256,
        0.07673132, -0.227397  , -0.15840591, -0.10292988, -0.6830837 ,
       -0.23510128,  0.6165825 ,  0.11153345, -0.4144705 ,  0.09626016,
       -0.11291514,  0.8256664 , -0.49922696,  0.26332954, -0.35839406,
        0.6881266 ,  0.6718516 ,  0.0867641 ,  0.24843903,  0.6920707 ,
        0.37919027, -0.27192804,  0.5573388 , -1.0683383 , -0.45235977,
       -0.5060888 , -0.693835  , -0.33676928,  0.5679421 , -0.4563976 ,
        0.4198934 , -0.06000128,  0.6072741 , -1.1808567 ,  0.09339973,
       -0.4496738 ,  0.02826241, -0.01418105,  0.01322413, -0.16594794,
       -0.8327613 , -0.02719802,  0.5258091 , -0.6739192 , -0.7354652 ,
       -0.6937513 , -0.28029326, -0.36118436, -0.41617483,  0.8403618 ],
      dtype=float32)

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다