Jupyter notebook 끄기 ! -> 위의 코드 진행 -> 다시 키기 ! :::: 마법처럼 되었다! 끝!
예시:
import matplotlib as mpl
import matplotlib as mpl
import matplotlib.font_manager as fm
set(sorted([f.name for f in fm.fontManager.ttflist]))
#---> 사용 가능한 폰트들이 뜬다!!\
#이 중 NanumBarunGothic을 사용하려면,
mpl.rcParams['font.family'] = 'NanumBarunGothic'
#폰트를 바꾸고 그래프를 그리면 -부호가 안 나오는 경우가 있는데 아래와 같이 하면 나온당.
matplotlib.rcParams['axes.unicode_minus'] = False
from soynlp.noun import LRNounExtractor_v2
from nltk import sent_tokenize
noun_extractor = LRNounExtractor_v2(verbose=True)
nouns = noun_extractor.train_extract(sent_tokenize(corpus))
LRNounExtractor_v2 를 호출하고 corpus를 리스트로 넣어준다. 이를 통해 얻은 nouns는 단어를 key로 count와 score를 담은 dictionary 객체이다. count와 score의 threshold를 정해 어느 정도 이상 빈번하게 등장하며 모델이 판단하기에 명사일 가능성이 높은 것들만 따로 저장해 볼 수 있다.
tgt_noun = []
for noun in nouns:
if (nouns[noun][0] >= lower_count) and (nouns[noun][1]) >= lower_score:
tgt_noun.append(noun)
이렇게 추출된 명사들에 대해 클리닝 작업을 해볼 수 있다.
non_noun_eomi_list = ('.', '?', ',', '야', '고', '는', '까', '한', '인', '들', '이', '면', '로', '은')
tgt_noun = set([item.strip(""""',.‘“△[]()”’ """) for item in tgt_noun if (item[-1] not in non_noun_eomi_list) \
& (sum([1 if char.isdigit() else 0 for char in item]) <= 2) \
& (len(re.sub('[^가-힣]', '', item)) >= 4) \
& (not re.search('[^가-힣0-9]', item))])
마지막으로 이렇게 얻은 (복합) 명사 리스트를 기존에 사용하는 형태소 분석기 (여기서는 Mecab과 Khaiii)의 사용자 사전에 등록할 수 있다.
#Save to Mecab
f1 = open(os.path.join('/home', 'yoonchan', 'Downloads', 'mecab-ko-dic-2.1.1-20180720',\
'user-dic', 'lab_strike_nouns.csv'), 'w')
for noun in nouns:
#f1.write(noun + '\t\t\t\tNNP\t*\tT\t' + noun + '\t*\t*\t*\t*\t*\n')
f1.write(noun + ',,,,NNP,*,T,' + noun + ',*,*,*,*\n')
f1.close()
#Build Khaiii again
#https://hanshuginn.blogspot.com/2019/02/khaiii.html
f1 = open(os.path.join('/home', 'yoonchan', 'khaiii', 'rsc', 'src', 'preanal.my'), 'w')
for noun in nouns:
f1.write(noun + '\t' + noun + '/NNG\n')
f1.close()
Soyspacing – https://github.com/lovit/soyspacing : 휴리스틱 알고리즘 기반 띄어쓰기 모델. 주어진 알고리즘으로 input으로 들어간 문장들에서 띄어쓰기 규칙을 파악하고 이를 새로운 문장에 적용. 모든 한글 문서에 광범위하게 적용할 수 있는 모델을 내기에는 한계가 있겠지만, 동질적인 주제와 형식을 가진 문서들에 대해 분석을 하는 경우 특히 유용하게 쓸 수 있을 것 같다. (특정 도메인을 위한 모델)
PyKoSpacing – https://github.com/haven-jeon/PyKoSpacing : CNN에 RNN을 쌓아 올린 모델을 뉴스 데이터로 훈련. 세종 코퍼스 등 테스트 셋에서 잘 작동한다고 한다. 하지만 accuracy measure가 성능을 over represent 할 수 있을 것 같다. 대체로 띄어쓰기가 정말 난장판으로 되어있는 경우 볼만한 문서로 바꾸는데 사용할 수 있을 것 같다.
비슷한 주제/형태 (특정 도메인)의 문서를 다루고 있기에, Soyspacing으로 띄어쓰기 규칙을 발견하고 전체 문서에 적용해 보고자 하였다.
가지고 있는 한글 문서를 텍스트 파일로 저장
with open(os.path.join(dir_to_save_on, 'spacing_train_full.txt'), 'w') as f1:
for parag in text:
f1.write(parag + '\n')
f1.close()
위 텍스트 파일로 띄어쓰기 규칙 발견
from soyspacing.countbase import CountSpace
#Train a simple huristic model -- takes about 45mins with 4000000 sentences.
corpus_fname = os.path.join(dir_, 'train_sample', 'spacing_train_full.txt')
model = CountSpace()
model.train(corpus_fname)
#Save the model
model_fname = os.path.join(dir_, 'train_sample', 'spacing_model_full_0706')
model.save_model(model_fname, json_format=False)
#Load the model
model_fname = os.path.join(dir_, 'train_sample', 'spacing_model_full_0706')
model = CountSpace()
model.load_model(model_fname, json_format=False)
적용 사례
#good case
print(model.correct('이번공산베트남에'))
--> returned ('이번 공산 베트남에', [0, 1, 0, 1, 0, 0, 0, 1])
#bad case
print(model.correct('현대자동차기아자동차'))
--> returned ('현대자동차기아자동차', [0, 0, 0, 0, None, 0, 0, 0, 0, 1])
문서 뭉치에서 회사 이름의 경우 띄어쓰기가 잘 지켜지지 않는 문제가 종종 있었고, 방어적으로 띄어쓰기를 하는 이 모델의 특성으로 인해 bad case가 발생. 회사 이름 사이를 띄어 쓰게 만들기 위해서 아래의 코드로 일종의 사용자 규칙을 부여할 수 있다.
#Making a rule based dict
firms = ['현대자동차', '기아자동차', .....]
with open(os.path.join(dir_, 'train_sample', 'spacing_firm_names.txt'), 'w') as f1:
for firm in firms:
f1.write(firm + '\t' + '1' + '0'*(len(firm)-1) +'1' + '\n')
f1.close()
이렇게 만든 사용자 규칙을 RuleDict 함수로 넣어주면 모델에 반영된다.
from soyspacing.countbase import RuleDict
rule_dict = RuleDict(os.path.join(dir_, 'train_sample', 'spacing_firm_names.txt'))
model.correct('현대자동차기아자동차', rules=rule_dict)[0]
--> returned '현대자동차 기아자동차'