토이프로젝트 주제
다이어리 기반 질문 생성
딥러닝 모델을 통해 사용자가 작성한 일기를 기반으로 정보를 추출해 일기에 대한 적절한 질문 제시하기
주제 선정 계기
딥다이브 위키팀으로 자연어처리 분야를 공부하며 다양한 모델들을 배우면서, 딥러닝 모델들을 활용해 실제로 사용될 수 있는 서비스를 만들어보고 싶었습니다. 딥러닝을 활용한 다양한 서비스 아이디어 중에서 저희는 “매일 생각할 거리가 담긴 질문을 던져주는 다이어리 서비스”를 NLP 모델을 통해 개선해보고자 하였습니다.
기존에 시장에 나와있는 다이어리 서비스 중에는 일기와 더불어 매일 생각할 거리를 함께 던져주며 깊은 생각을 하도록 도와주는 다이어리가 있습니다. 이러한 다이어리의 질문이 이미 정해진 질문을 던지는 것이 아니라, 내가 오늘 작성한 일기를 바탕으로 질문을 만들어준다면 조금 더 의미있는 생각들을 할 수 있지 않을까? 라는 아이디어에서 시작해 저희는 토이프로젝트를 구상하게 되었습니다.
아래 코랩을 통해 직접 본 모델을 사용해볼 수 있습니다!
코랩 사용을 위해 학습된 본 모델과 질문 JSON 파일의 업로드가 필요합니다! →
프로젝트 진행
일기에 대한 질문을 제시하는 과정은 크게 다음 3가지로 이루어집니다.
1.
사용자가 입력한 일기에서 감정을 분류
2.
일기에서 감정과 관련된 핵심 키워드를 추출
3.
감정과 키워드를 바탕으로 질문을 생성
1. 감정 분류
감정 분류 모델 학습에 사용한 코드를 아래 코랩에서 확인할 수 있습니다!
한국어 문장에 대한 감정 분류를 위해 KoBERT 모델을 활용하였습니다. KoBERT 모델을 이용해 BERTClassifier를 만들고, 데이터를 학습시켜 문장에 대한 감정 분류를 수행합니다. 모델은 입력된 문장을 7가지 감정 —기쁨, 공포, 혐오, 놀람, 슬픔, 분노, 중립— 으로 분류하도록 설계하였습니다.
KoBERT
koBERT의 원형은 구글이 공개한 버트(BERT)이며, 영어 읽기에 특출난 AI 모델입니다. SK텔레콤은 버트에 한국어를 학습시켜 KoBERT를 오픈소스로 공개하였습니다. KoBERT의 학습에는 위키 문서의 문장 500만개(5400만 단어)와 뉴스 문장 2000만개(2억 7000만 단어)가 사용되었습니다.
데이터셋
저희가 입력으로 받을 문장은 일기 데이터이지만, 인터넷에서 충분한 크기의 양질의 일기 데이터셋을 구할 수 없었습니다. 그러나 일기를 “내가 내면과 일기를 통해 대화"하면서 글을 적는다는 관점에서 감정에 대한 챗봇 데이터를 활용한다면 일기에서 감정을 잘 분류해낼 수 있을 것이라 생각했습니다. 이에 모델 학습을 위해 2가지 데이터셋을 시도해보았습니다.
데이터셋 #1
처음으로 시도한 데이터는 AIHub에서 제공하는 한국어 감정 정보가 포함된 연속된 대화 데이터셋입니다. 약 27만 문장의 대화와 레이블링된 감정을 가지고 있는 데이터셋은 아래와 같은 형식으로 구성됩니다.
감정 : 기쁨
발화1: 나 이번에 남자친구 생겼어.
응답1: 남자친구가 생기셨군요. 자세히 말해 주시겠어요?
발화2: 그 친구가 고백해서 사귀기로 했어. 이제 나도 커플이라 기뻐.
응답2: 커플이 되어서 기쁘시군요.
발화3: 응. 앞으로 남자친구한테 잘해 줘야지.
응답3: 남자친구한테 잘해 줄 생각이시군요.
Plain Text
복사
데이터셋에서 발화는 사람이 하지만, 응답은 시스템의 응답을 사용하고 있습니다. 따라서 응답을 데이터로 활용하기에는 부자연스러운 문장이 많다고 생각되어 감정과 발화만을 묶어서 데이터로 활용하고자 하였습니다. 모델 학습에 조금 더 적합한 형태로 만들어주기 위해 데이터를 가공하였고, (감정, 발화1), (감정, 발화2), (감정, 발화3)으로 데이터를 분리해 약 50만개의 문장, 감정 쌍 데이터를 구성하여 모델에게 감정 분류를 학습시켰습니다.
그러나 위 데이터 셋을 활용했을 때에는 기대했던 바와 다르게 2시간 넘게 학습을 돌려도 정답률이 20%도 나오지 않는 처참한 결과를 보여주었습니다… 나름대로 데이터와 모델에 대해 분석해보았는데, 데이터를 가공하는 과정에서 아래 예시와 같은 문제가 발생했다고 판단하였습니다.
감정 : 기쁨
발화1: 연락이 끊겼던 친구랑 만나기로 했어. 정말 기뻐.
발화2: 맞아. 고등학교 때 정말 친했던 친구였는데 핸드폰을 잃어버리는 바람에 연락이 끊겼어.
발화3: 정말 보고 싶었지.
⬇️
1. 기쁨 / 연락이 끊겼던 친구랑 만나기로 했어. 정말 기뻐.
2. 기쁨 / 맞아. 고등학교 때 정말 친했던 친구였는데 핸드폰을 잃어버리는 바람에 연락이 끊겼어.
3. 기쁨 / 정말 보고 싶었지.
Plain Text
복사
아무래도 대화 데이터셋을 활용하다보니, 문장 자체보다는 대화의 맥락에 감정이 연결되어있는 경우가 많았는데, 이를 각 문장으로 분리해 데이터셋을 만들어버렸다보니, 2번 문장처럼 ‘핸드폰을 잃어버렸다', ‘연락이 끊겼다' 라는 슬픈 감정의 문장이 기쁨으로 분류되고, 3번 문장처럼 중립적인 감정의 문장이 기쁨으로 분류되어버리는 경우가 발생했습니다.
이 과정에서 하나로 묶여진 데이터를 함부로 분리하여 여러 데이터로 나누다보면 데이터의 특성에 의해 저품질의 데이터가 되어버릴 수 있다는 것을 느꼈습니다.
데이터셋 #2
다시 한 번 서치를 해서 문장 하나와 감정이 연결된 데이터셋을 찾아보았습니다. 그리고 두 번째로 시도한 데이터셋은 동일하게 AIHub에서 제공하는 한국어 감정 정보가 포함된 단발성 대화 데이터셋입니다. 연속 대화 데이터가 아닌 단발성 대화 데이터이다 보니, 아래 사진처럼 구어체적인 문장 하나하나에 감정 레이블링이 되어있어 그대로 학습 데이터로 활용이 가능했습니다.
한국어 감정 정보가 포함된 단발성 대화 데이터셋 의 문장과 감정들
(생각보다 날 것의 데이터가 많아서 놀랐고, 감정 분류가 적절히 되어 있어서 데이터조차 재미있게 봤어요 ㅋㅋㅋ)
이 데이터셋을 활용해 모델을 학습시킨 결과, 모델의 정답률은 약 96%로 거의 대부분의 문장에 대한 감정을 잘 분류해낼 정도로 좋은 성능을 보이고 있습니다. 이에, 본 데이터셋을 기반으로 학습시킨 감정분류 모델을 사용하기로 결정하였습니다.
감정 분류 적용
서비스에서는 사용자로부터 일기를 입력받아 감정분류를 수행하는 만큼, 예시 일기데이터를 input으로 넣어 감정분류를 해보았습니다. 감정 분류 모델 학습 과정에서 하나의 문장에 대해 감정을 분류하기 때문에, 일기 데이터 역시 문장 단위로 분리해 모델에 입력으로 전달해주었습니다. 그 결과, 아래처럼 일기 문장에 대한 감정을 잘 분류해내는 것을 확인할 수 있습니다. 빨간색으로 강조표시해둔 문장들은 생각보다 정확하게 잘 분류해서 재미있다고 느꼈던 문장들이예요!
일기 문장
내가 딸기 제철을 모르고 있나 해서 네이버까지 검색해 봤다.
딸기 제철은 1~5월이 맞다. 2월은 딸기 제철이다.
그런데 왜 가격은 금딸기야ㅠㅠㅠ
12월에 딸기케이크 가격이 상한선을 치고 … 생각했단 말이지ㅠㅠ
금딸기가 하루이틀이었냐? 라고 물으신다면.
낚시당해서 분노폭발한 것도 있다.
출근길 마트가 하나 있는데 출근때마다 마트를 흘깃거린다.
뭐 가격 할인 같은 거 없나 하고 항상 주시하고 있었다.
그리고 출근길에 발견한 은혜로운 딸기 가격 전단지.
실화입니까?
진짜에요?ㅠㅠ
요새 팀을 이동하고 인수인계 하는 와중에 바쁘기는 하였으나.
그 날은 야근하고 돌아오는 길에도 마트에 들르는 것은 까먹지 않았다.
1kg.마음껏 먹겠다는.큰 꿈을 꾸었는데ㅠㅠ
올해 딸기 가격이 비싸서 진짜 너무 슬프다.
2월 중순 이후부터는 딸기 가격 좀 하락한다는데 … 내려가긴 한거같다.
저런 낚시매물도 팔고 말이지.
하지만 아직도.ㅠㅠ
한때는 1kg 사놓고 맘껏 먹었는데.ㅠㅠ
작년만 해도 저 파격가가 일반적인 딸기 가격이었다.
감정
놀람
중립
슬픔
슬픔
놀람
혐오
중립
중립
행복
놀람
놀람
공포
행복
슬픔
슬픔
중립
분노
슬픔
슬픔
놀람
가중치
1.00
1.08
1.16
…
…
1.92
2.00
각 문장의 감정이 아닌 일기의 감정을 분류하기 위해서는 일기에서 가장 높은 비율을 차지하는 감정을 선택하고자 하였습니다. 일반적으로 사람들이 일기의 앞부분에는 있었던 일을, 뒷부분에서는 느꼈던 감정을 주로 작성하는 만큼, 문장의 뒷부분에 조금 더 높은 가중치를 부여해 감정을 뽑아내는 방법을 생각해 적용해보고자 하였습니다. 이를 위해 가장 첫 문장에는 가중치로 1을 부여하고, 일정한 비율로 증가하다가 마지막 문장에는 가중치로 2를 부여하였습니다. 각 감정 분류에 속한 모든 문장의 가중치 합을 구하고, 가장 높은 가중치합을 갖는 감정을 일기의 메인 감정으로 선택합니다.
슬픔의 가중치 합 : 49.999999999
→ 슬픔이 일기에서 32.86%로 가장 높은 비중을 차지해요
또한, 일기에 나타난 감정의 깊고 얕은 정도에 따라 필요로하는 질문이 달라질 수 있다고 생각해, 메인 감정이 다른 감정에 비해 얼마나 많이 나타나고 있는지, 그 비율을 이용해 감정의 단계를 선택하고자 하였습니다. 이 감정에 대해서는 임의로 해당 감정이 차지하는 비율에 따라 30%까지는 0단계, 33%까지는 1단계, 37%까지는 2단계, 37% 이상은 3단계로 분류하도록 설정하였습니다. 가장 많이 포함된 감정의 비율이 20%보다 낮다면, 유의미한 감정이라고 판단하지 않아 일기에서 중립이 느껴진다고 분류하도록 설정하였습니다.
감정분류 모델을 실행하여 일기를 입력으로 넣는다면, 아래와 같은 정보를 얻을 수 있습니다.
슬픔의 가중치 합 : 49.999999999
→ 슬픔이 일기에서 32.86%로 가장 높은 비중을 차지해요
→ 일기의 해당 감정 단계는 1입니다.
Plain Text
복사
실험
문장 하나하나가 아닌 일기 전체를 한 번에 감정 추출 모델에 입력으로 전달하면 일기의 감정을 분류해낼 수 있지 않을까? 라는 생각에 일기 전체를 모델에 입력으로 넣어봤습니다. 유의미한 결과를 얻을 것이라는 기대와 달리, 모델의 감정 분류 결과는 중립을 뱉어냈습니다! 아무래도 입력이 약 10~15문장으로, 학습에 사용했던 데이터 길이였던 1문장보다 15배 이상 길다보니, 학습 방식에서 활용했던 추론 방식이 잘 드러맞지 않는 것으로 생각됩니다. 또, 동일한 추론 과정이 적용되었다고 하더라도, 다양한 감정의 단어들이 희석되어 두드러지는 감정이 크게 보이지 않아 중립으로 분류되었다고 생각됩니다.
2. 핵심 키워드 추출
키워드 추출에 활용한 패키지와 코드는 아래에서 코랩에서 확인할 수 있습니다!
일기에 대한 질문을 생성해내기 위해, 사용자의 일기에서 핵심적인 키워드를 추출해야합니다. 이를 위해 KoNLPy(코엔엘파이)를 이용해 문서의 명사들을 추출하고, 해당 명사들 중에서 가장 문서와 유사도가 높은 명사를 문장의 핵심 키워드로 제시합니다.
이 과정에서 앞서 추출한 일기의 메인 감정과 관련된 키워드를 추출하는 것이 질문 생성에 더 유리하다고 판단하여, 모든 문장에 대한 키워드를 추출하기보다는 메인 감정의 문장들만 이어붙인 문단을 하나 생성해 키워드 추출 모델에 전달하였습니다. 이를 위해서는 MMR 함수를 통해 문서 요약을 적용하고 키워드를 추출하였습니다.
앞서 감정 분류에서 사용한 일기데이터에 대한 키워드를 추출하면 다음의 결과를 얻을 수 있습니다.
주요 키워드는 "['딸기', '케이크', '상한선', '메뉴', '품절']"입니다.
Plain Text
복사
MMR(Maximal Marginal Relevance)
MMR은 고려중인 항목과 이미 선택된 항목 사이의 불일치를 정량화하기 위한 척도입니다. 텍스트 요약 작업에서 정보의 중복성을 최소화하고 결과의 다양성을 극대화하기 위해 사용됩니다. 문서와 가장 유사한 키워드를 선택하는 것으로 시작하며, 그 후에는 문서와 비슷하면서도 이미 선택한 키워드와 비슷하지 않은 새 후보를 반복적으로 선택하게 됩니다. 이때 다양성 임계값을 선택할 수 있는데, 이 값이 작아질수록 정보의 중복성에 관계없는 결과가 출력됩니다.
3. 질문 생성
코랩 사용을 위해 학습된 본 모델과 질문 JSON 파일의 업로드가 필요합니다! →
앞서 1번, 2번 과정에서 일기의 메인 감정, 감정의 깊이(0~3단계), 키워드를 추출하였고, 이를 바탕으로 질문은 미리 작성된 템플릿에 키워드를 넣어 문장을 출력하는 방식으로 생성합니다. 질문 템플릿은 감정과 깊이에 따라 분류되어있는 JSON 파일에서 가져옵니다. 질문 템플릿은 아래와 같은 형식으로 구성되어 있습니다.
행복
0단계 : {키워드}가 당신에게 즐거움을 주는 이유는 무엇인가요?
1단계 : {키워드}와 공통점을 가지는 당신에게 행복을 주는 또 다른 것은 어떤 것이 있을까요?
...
분노
0단계 : 당신이 {키워드}에 화를 느끼는 이유는 무엇일까요?
1단계 : 화가 난 스스로를 달래주는 좋은 방법을 알고있나요?
2단계 : 앞으로 {키워드}때문에 화가 나려 한다면, 어떻게 대처할 수 있을까요?
...
공포, 놀람, 슬픔, 혐오 역시 동일하게 0~3단계의 질문으로 구성됨
중립 (무작위 출력)
내가 용감했던 적은 언제인가요?
살면서 돈은 왜 필요할까요?
내가 좋아하는 것과 잘하는 것은 무엇이 있나요?
10년 뒤의 나는 어떤 모습일까요?
...
Plain Text
복사
감정이 중립인 경우에는 일기에 대한 질문을 던지지 않고, 기존의 다이어리 질문 서비스처럼 “10년 뒤의 나는 어떤 모습일까요?”와 같이 나에 대해 생각할 수 있는 질문들을 제시합니다.
질문 생성 예시
감정 : 슬픔 1단계 / 키워드 : 딸기
슬픔 1단계 : {키워드} 때문에 속상해진 나를 달래는 방법은 무엇일까요?
일기를 바탕으로 생성된 질문
딸기 때문에 속상해진 나를 달래는 방법은 무엇일까요?
Plain Text
복사
결과
네이버 블로그나 일기 예시 등의 키워드로 인터넷을 통해 수집한 일기 데이터를 우리가 구성한 서비스에 입력으로 넣을 경우, 일기에 대한 코멘트 및 질문을 받을 수 있습니다.
예시1
입력한 일기
내가 딸기 제철을 모르고 있나 해서 네이버까지 검색해 봤다. 딸기 제철은 1~5월이 맞다. 2월은 딸기 제철이다. 그런데 왜 가격은 금딸기야ㅠㅠㅠ 12월에 딸기케이크 가격이 상한선을 치고 와플대학 생딸기 들어간 메뉴들이 품절크리 겪는 와중에도 내년이 되면 괜찮지 않을까 하고 생각했단 말이지ㅠㅠ 금딸기가 하루이틀이었냐? 라고 물으신다면. 낚시당해서 분노폭발한 것도 있다. 출근길 마트가 하나 있는데 출근때마다 마트를 흘깃거린다. 뭐 가격 할인 같은 거 없나 하고 항상 주시하고 있었다. 그리고 출근길에 발견한 은혜로운 딸기 가격 전단지. 실화입니까? 진짜에요?ㅠㅠ 요새 팀을 이동하고 인수인계 받고 인수인계 하는 와중에 바쁘기는 하였으나. 그 날은 야근하고 돌아오는 길에도 마트에 들르는 것은 까먹지 않았다. 1kg.마음껏 먹겠다는.큰 꿈을 꾸었는데ㅠㅠ 올해 딸기 가격이 비싸서 진짜 너무 슬프다. 2월 중순 이후부터는 딸기 가격 좀 하락한다는데 확실히 1월보단 좀 내려가긴 한거같다. 저런 낚시매물도 팔고 말이지. 하지만 아직도.ㅠㅠ한때는 1kg 사놓고 맘껏 먹었는데.ㅠㅠ 작년만 해도 저 파격가가 일반적인 딸기 가격이었다.
글에서 느껴지는 감정
슬픔 1단계
생성한 추천 질문
→ 딸기 때문에 속상해진 나를 달래는 방법은 무엇일까요?
[출처] 딸기 가격 제철임에도 금딸기라 슬픈 일기
예시2
입력한 일기
오늘 며칠 대충 공부했던 한식조리기능사 시험을 보러 수원장안구시험센터에 갔다. 여긴 주차가 헬이었다. 주차장에 도착해보니 차 한 대 주차할곳없이 빽빽했고 그나마 불법주차할만한 자리는 큰 차 두대 사이에 평행주차해야했는데. 자리가 좁아 끙끙대다가 한 차가 조금 뒤로 빠지면 주차할 수 있을거 같아 (안될거 같았지만) 주차하다 내려서 그 차를 밀어보려고 하는데. 그 차안에 운전자가 있었던거다. 지금 뭐하는거냐고. 화내는데 소심해서 차마 차 좀 뒤로빼달라는 얘기를 못했다ㅠ 결국 이중주차를 하였고 시험장도 겨우 들어갔다. 주차때문에 조마조마해서 시험도 집중이 안되었다. 오전내내 뻘짓한거 같았다. 시험점수도 55점으로 불합격. 공부가 부족했던거겠지. 점심때 산본으로와서 밥먹고 쉬었다. 수연이한테 하소연하고 기분 안좋은거 얘기하다 저녁에는 다시 수원으로 넘어와서 닭발을 먹었다. 투자 망한거도 떠오르고 서운해서 닭발먹다가 울었다 ㅠㅠ 오늘의 일기 끝!
글에서 느껴지는 감정
슬픔 3단계
생성한 추천 질문
→ 나를 슬프게 만든 불합격의 원인은 외부에 있나요? 아니면 내부에 있나요? 앞으로 어떻게 해야할까요?
예시3
입력한 일기
나는 아침에 눈이 일찍 떠질 때는 언제인지 생각해보았다. 당연히 학교 가는 날은 무조건 늦게 일어나고 싶지만 일찍 일어나야 한다. 그것 말고 또 다른 날이 있는지 생각해보았다.
나는 토요일에 일찍 눈이 떠질때라고 생각한다. 토요일은 늦잠도 실컷 할 수 있다고 생각할 수 있지만 나는 토요일 아침에 일어나 게임을 한다. 그냥 내가 알람을 맞춰 일어나는 것이 아니라 그냥 본능적으로 일어난다. 게임을 하고 싶은 마음이 잘 때도 느껴지나 보다.
일찍 일어나 자주적인 생활을 하고 싶다면 밤에 컴퓨터나 스마트폰등을 보지 말아야한다. 일찍 밤에 자기에 방해가 된다. 나도 밤에 늦게 자지 말고 일찍 자서 일찍 일어나야겠다.
글에서 느껴지는 감정
공포 3단계
생성한 추천 질문
→ 당신에게 학교는 무서운 것인가요? 어떤 점이 당신이 그렇게 느끼게 만들었나요?
프로젝트의 한계와 추후 발전 방향
이번 토이프로젝트를 진행하면서 지식과 능력, 시간의 한계로 조금 더 좋은 형태의 서비스를 만들지 못해 아쉬움이 남았습니다 ㅜㅜ 저희가 만들어낸 “다이어리 기반 질문 생성” 토이프로젝트의 결과물이 가진 몇가지 한계점과 추후 개선 방향을 제시해보겠습니다.
한계
1.
키워드 추출의 결과를 100% 신뢰할 수 없다.
명사를 기준으로 키워드를 추출하기는 하지만, 키워드를 추출하는 기준이 “다른 문서에서 잘 등장하지 않고, 본 문서와 연관이 많이 되어있는 단어"이기에, 정확한 일기의 키워드를 추출해냈다고는 할 수 없습니다. 몇 가지 일기 데이터에서는 아예 엉뚱한 “이때, 빗속"와 같은 단어를 핵심 키워드로 추출하는 결과를 보이기도 합니다.
2.
생성한 질문이 예리하지 못하다.
이미 작성된 템플릿을 기반으로 키워드를 집어넣어 질문을 생성하는 방식을 선택하였기 때문에, 키워드는 핵심적인 단어를 뽑아올 수 있을지 몰라도 질문 자체를 예리하게 던지는 것은 아직 부족함이 있다고 생각됩니다.
개선 방향
1.
개체명 인식 적용하기.
추출한 키워드가 사람/사물/장소/음식 등의 카테고리로 분류될 수 있음을 인식하고, 이에 따라 다른 유형의 질문 템플릿을 가져와 질문을 생성한다면 좀 더 예리한 질문을 던질 수 있을 것이라고 생각됩니다.
2.
감성 세분화하기.
지금은 단순히 7가지 감정을 기반으로 분류를 수행하고 있는데, 만약 ‘섭섭함, 실망스러움, 아련함' 같은 조금 더 디테일한 감정이나 ‘연애+즐거움, 음식+즐거움, 이별+슬픔' 같이 내용과 감정이 결합된 형태로 분류하여 질문 템플릿을 활용할 수 있다면 더욱 적절한 질문을 생성할 수 있을 것입니다.
3.
단어의 감정 정도 반영하기.
지금은 일기의 감정을 추출하는 과정에서 단순히 문장의 개수와 문장의 위치만을 이용해 감정을 찾아내지만, ‘삐짐'과 ‘통탄함'에서 느껴지는 슬픔의 차이처럼, 단어가 가지고 있는 감정의 깊이를 문장 가중치에 반영한다면 더욱 감정의 깊이를 잘 분류해내어 감정을 더욱 잘 반영한 질문을 만들어낼 수 있을 것입니다.