FAQ 챗봇 만들기 [3] - 많은 데이터로 실험해보기

     

들어가기 전에

지난 시간에 한국전력공사의 FAQ데이터를 가지고 모델을 만들어 보았습니다. 그런데 생각보다 성능이 구렸(?)어요 ㅠㅠ 모델의 문제인지 데이터의 문제인지.. 일단 데이터가 너무 적다고 생각해서 이번엔 많은~! 영어문장을 이용해 FAQ모델을 만들어 볼 예정입니다. 데이터는 지난 시간에 소개해드렸던 영어 농답 Q&A데이터 입니다. (feat. kaggle)

이전글 -
2019/10/22 - [Study/AI] - FAQ 챗봇 만들기 [1] - 모델만들기
2019/10/24 - [Study/AI] - FAQ 챗봇 만들기 [2] - 모델다듬기

github - https://github.com/tkdlek11112/faq_chatbot_learning

유튜브 - 

 

데이터 살펴보기

일단 캐글에서 FAQ데이터를 가져와볼게요 url은 요기~ https://www.kaggle.com/jiriroz/qa-jokes

 

Question-Answer Jokes

Jokes of the question-answer form from Reddit's r/jokes

www.kaggle.com

url 들어가서 다운로드 누르면 됩니다~ (가입해야 합니다.. 언젠가 캐글 하실 테니 미리미리 가입하세요. 구글로 가입도 쌉 가능 :) )

조~기 위에서 다운로드를 눌르면 된다.

페이지에서 조금만 내리시면 데이터를 조금 맛볼(?)수 있습니다. 잠깐 봐볼까요

데이터 성격을 볼 수 있슴

일단 데이터는 38.3k. 질문이 38269개인데 대답이 35870개인 거 보면, 중복되는 대답이 조금 있나봅니다. 음.. 뭔가 읽어봐도 알 수 없습니다.. 이것이 미쿸의 개그인가... 질문 : 문밖에 있는 팔다리 없는 사람을 뭐라고 부를래? 답 : 매트 ..? ..? ....? 나만 못 이해함? ㅋㅋㅋㅋㅋㅋㅋ 암튼 이런 종류의 질문과 답이 있습니다. 한번 모델에 돌려볼께요~!

 

데이터 불러오기, 전처리

일단 구글 드라이브에 data에 올리고 시작하겠습니다. 이전 시간에 했던 것처럼 구글 드라이브를 연동하고 파일을 읽어와서 한번 뿌려봅니다.

구글드라이브 연동 있지 마시고~

한글과 다르게 영어는 띄어쓰기로 단어가 잘 구분되기 때문에 형태소 분석은 생략합니다. 형태소 분석을 하지 않아도 띄어쓰기로 split 하면 단어 단위로 잘 짤리기 때문이죠~ 하지만 영어 단어를 원형으로 만들어주는 lemmatization과 the나 a같은 관사를 제거하는 stopword 제거는 해줍니다. 먼저 토큰화부터 해볼까요?

토큰화 하고나서 출력해보기

소스는 github에 있으니 캡처본으로 설명하겠습니다. 일단 한국어 전처리를 할 때는 konlpy를 사용했는데 영어는 nltk라는 패키지를 사용했습니다. nltk 안에 word_tokenize를 사용해 영어를 쉽게 토큰화할 수 있습니다. 그냥 word_tokenize를 쓰면 에러가 나는데 nltk.download('punkt')를 해서 추가적인 패키지 에드온을 다운받으면 에러가나지 않습니다. 토큰화한다음 출력해보면 띄어쓰기로 출력된 것을 알 수 있습니다. 그런데~? 출력물을 보니 하나 깜빡한 게 있네요. 바로 대문자를 소문자로 바꿔주는 작업입니다. 영어는 대문자와 소문자로 나뉘어있지만, 실질적인 의미는 차이가 없습니다. 하지만 문자 자체로는 다른 문자로 인식하기 때문에 하나로 통일해주는 것이 좋습니다. 방법은 간단합니다. 하나만 추가하면 돼요~!

# 토근화
tokened_questions = [word_tokenize(question.lower()) for question in faqs['Question']]
tokened_questions

요렇게 lower()를 붙여주면 끝~! 이제 lemmatization 해봅시다.

lemmatization

 토큰화와 똑같이 wordnet이라는것을 다운받아야 사용할 수 있습니다. lemmatization을 거치면 단어들이 원형으로 바뀝니다. 이제 마지막으로 불용어를 제거해봅시다.

불용어제거

불용어제거도 역시 stopwords라는 추가 에드온을 다운받고 사용할 수 있습니다. 출력해보면 do나 the가 생략된 토큰들을 확인할 수 있습니다. 이제 모든 준비가 끝났군요! doc2vec에 넣어봅시다~! 

이전 시간에 doc2vec에 데이터를 넣기전에 항상 TaggedDocument로 변형했던거 기억나시죠? 여기서도 만찬가지로 Tag값을 먹여서 모델에 넣어줍니다.

TaggedDocument로 합시다

 

doc2vec 모델화

doc2vec을 훈련하기전에 구글링으로 몇가지 알아낸점이 있는데, 굳이 for문으로 따로 epoch를 하지 않아도 된다고 하더라구요. 괜히 시간만 더 걸리고 특정한 이유가 아니면 돌릴필요가 없다고 하네요. 특정한 이유는 매 epoch마다 값을 처리해줄게 있거나, print를 하고 싶은경우?라서. 그리고 epoch 중간에 learning rate를 수정하는것도 별로 안좋다고 합니다. 그래서 이전시간과 doc2vec 파라메터가 살짝 다릅니다.

# make model
import multiprocessing
cores = multiprocessing.cpu_count()
d2v_faqs = doc2vec.Doc2Vec(
                                vector_size=200,
#                                 alpha=0.025,
#                                 min_alpha=0.025,
                                hs=1,
                                negative=0,
                                dm=0,
                                dbow_words = 1,
                                min_count = 5,
                                workers = cores,
                                seed=0,
                                epochs=20
                                )
d2v_faqs.build_vocab(tagged_questions)
d2v_faqs.train(tagged_faqs,
               total_examples = d2v_faqs.corpus_count,
               epochs = d2v_faqs.epochs
                                )
    # # train document vectors
    # for epoch in range(50):
    #     d2v_faqs.train(tagged_faqs,
    #                                total_examples = d2v_faqs.corpus_count,
    #                                epochs = d2v_faqs.epochs
    #                                )
    #     d2v_faqs.alpha -= 0.0025 # decrease the learning rate
    #     d2v_faqs.min_alpha = d2v_faqs.alpha # fix the learning rate, no decay

for문을 빼버리고 alpha값과 min_alpha값도 디폴트로 주려고 없애버렸습니다. min_count는 한국어를 할 때는 1을 했는데 영어는 데이터가 많아서 5로 주었어요. 보통은 5~10 사이 값을 씁니다. train은 for문에서 반복하는 게 아니라 딱 한 번만 돌게됩니다. 따라서 속도가 매우 빨라요~ 

doc2vec 모델을 만들었으면 얼마나 잘 맞추는지 테스트코드를 만들어봅시다.

테스트 코드

옼ㅋㅋㅋㅋㅋㅋㅋ 한국어 데이터 350개로 했을 때는 씨알도 안먹히던 모델이... 아주아주 정확하게 같은 문장을 찾아주었네요. 전체 문장으로 정확도를 체크해볼까요? 참고로 한글로 했을때는 정확도가 55%(194/351)였습니다.

74%!!

오.. 무려 74%의 정확도가 나왔네요. 그래도 살짝 아쉽긴 한데 top 5로 해볼까요?

탑 5로 하니 86%

물론 100%가 나오면 좋겠지만.. 그런 이상적인 모델은 이상에 존재하겠죠? ㅎㅎ... FAQ 챗봇이니 비슷한 질문을 찾아주는데 86%면 나름 높은 성능을 보여줄 것 같습니다.

 

마무리하며

 

영어 3만문장 데이터로 doc2vec 모델을 만드니 한글 350문장보다 약 20~30% 성능 향상을 보였습니다. 사실 한글, 영어는 그렇게 중요하지 않고 아마 데이터의 문제겠지요. 적어도 수만문장을 학습해야 어느정도 제 역할을 하는 것이 doc2vec이기 때문이지요. 

여기서 더 정확도를 높이려면 파라미터 값을 조금 바꿔보던가, 아니면 데이터를 수정하는 방법이 있습니다. 지금은 질문과 답이 1:1로 매핑되어있는데 질문을 좀 더 다양하게 늘리는 방법입니다. 단어의 순서나 동의어를 사용해서 여러 개의 질문을 만들어 N:1로 만드는 거죠. 그러면 찾아야 하는 유사한 질문이 하나가 아니라 여러 개이기 때문에 정확도를 더 높일 수 있습니다. 

모델 만드는 건 이 정도로 하고 다음엔 서비스를 만들어 보겠습니다. 일단 생각 중인 건 웹에서 간단하게 채팅을 만드는 거였는데, 시간 나면 카카오 오픈 빌더를 이용해 카카오톡에 연결해보겠습니다. 음... 데이터는.. 한글도 해보고 영어도 해보죠 뭐 ㅎ

 

 

반응형

댓글

Designed by JB FACTORY