-
Notifications
You must be signed in to change notification settings - Fork 0
AI ChatBot Recommendation System
이 문서는 음성 인식을 사용한 챗봇 시스템에 대한 구현 내용을 기술합니다.
데이터셋, 문장 임베딩 모델, 명령 의도분류 모델, 엔티티 구별 모델, 모델 설정 및 데이터셋 처리 관련 로직, 학습시 모델 설정 내용에 대한 설명이 포함됩니다.
직접 구성한 레시피 조작 명령어 데이터셋을 통해 모델학습을 진행.
- 사용자의 명령어 문장에 대해 총 4가지 명령어 class 및 해당 명령어내 엔티티를 구별 가능하게 학습하였음.
데이터셋 세부 형태 :
-
명령어 의도분류 데이터셋 형태 :
question label 다음 보여줘 NEXT 다음 NEXT 2페이지 넘겨줘 NEXT 다음내용 알려줘 NEXT question label 다시 한번 들려줘 REPEAT 한번만 더 들려줘 REPEAT 한번 더 말해줘 REPEAT 다시 한번 말해줘 REPEAT -
명령어 엔티티(NER) 데이터셋 형태 :
question label 다음 보여줘 0 0 다음 0 2페이지 넘겨줘 S-Pcount 0 다음내용 알려줘 0 0 다음 넘겨줘 0 0 다음 2장 넘겨줘 0 S-Pcount 0 다음 3장 넘겨줘 0 S-Pcount 0 다음 4장 넘겨줘 0 S-Pcount 0 question label 현재 레시피 다시 말해줘 S-NOW 0 0 0 지금 레시피 다시 말해줘 S-NOW 0 0 0 전체 레시피 다시 말해줘 S-TOTAL 0 0 0 레시피 처음부터 다시 0 S-TOTAL 0 처음부터 다시 말해줘 S-TOTAL 0 0 처음부터 다시 들려줘 S-TOTAL 0 0 처음부터 다시 S-TOTAL 0 시작부터 다시 들려줘 S-TOTAL 0 0
FastText 임베딩 모델을 사용하여 처리하며,
전체 데이터셋 문장을 FastText 방식을 통해 임베딩하여 처리합니다.
- 인텐트 구별모델의 경우 SKTBrain/KoBERT 사용을 위해 별도의 문장 임베딩 모델을 사용함.

SKTBrain/KoBERT : https://github.com/SKTBrain/KoBERT#naver-sentiment-analysis

SKTBrain에서 제공하는 KoBERT 모델에 자체 제작한 명령어 의도분류 데이터셋을 학습하여 사용자 명령어 의도분류가 가능한 모델을 학습 및 사용하였습니다.
- 모델 결과 예시 :

KoChat/LSTM : https://github.com/hyunwoongko/kochat/blob/master/kochat/model/entity/lstm.py

KoChat 프로젝트의 LSTM 모델에 자체 제작한 명령어 엔티티(NER) 데이터셋을 학습하여 사용자의 명령어 문장별로 NER(개체명 인식) 태깅을 분류가능한 LSTM 모델을 학습 및 사용하였습니다.
임베딩, 인텐트 학습, 엔티티 학습 등에 사용한 학습 횟수 및 기타 설정은 kochat_config.py 파일 내에 기록되어 있습니다.

KoChat 프로젝트에서 사용하는 데이터셋 처리 방식 및 학습모델 세부 설정 방식을 차용하여 저희 프로젝트에 적용하였습니다.
이 문서는 협업 필터링 및 컨텐츠 베이스 필터링 방식으로 구현한 추천 시스템에 대한 내용을 기술합니다.
사용자들의 콘텐츠 평점 기록 (초기 데이터값은 자체적으로 제작)을 MatrixFactorization 방식을 통해 사용자 평점 예측 테이블을 제작 및 이를 기반으로 추천 리스트를 생성.
: 해당 MatrixFactorization 을 구현하는 과정에서 Gradient_descent 방식을 활용한 학습방식을 사용함.
관련 코드 :
` def fit(self): """ training Matrix Factorization : Update matrix latent weight and bias
참고: self._b에 대한 설명
- global bias: input R에서 평가가 매겨진 rating의 평균값을 global bias로 사용
- 정규화 기능. 최종 rating에 음수가 들어가는 것 대신 latent feature에 음수가 포함되도록 해줌.
:return: training_process
"""
# init latent features
self._User_Latent = np.random.normal(size=(self._num_users, self._k))
self._Item_Latent = np.random.normal(size=(self._num_items, self._k))
# init biases
self._b_User_Latent = np.zeros(self._num_users)
self._b_Item_Latent = np.zeros(self._num_items)
self._b = np.mean(self._R[np.where(self._R != 0)])
# train while epochs : 설정된 횟수만큼 반복 학습.
self._training_process = []
for epoch in range(self._epochs):
# rating이 존재하는 index를 기준으로 training
X_index, Y_index = self._R.nonzero()
for x, y in zip(X_index, Y_index):
self.gradient_descent(x, y, self._R[x, y])
cost = self.cost()
self._training_process.append((epoch, cost))
# print status
if self._verbose == True and ((epoch + 1) % 5 == 0):
print("Iteration: %d ; cost = %.4f" % (epoch + 1, cost))
def cost(self):
"""
compute root mean square error
:return: rmse cost
"""
# Nx_index, Ny_index: R[Nx_index, Ny_index]는 nonzero인 value를 의미한다.
# 참고: http://codepractice.tistory.com/90
Nx_index, Ny_index = self._R.nonzero()
# predicted = self.get_complete_matrix()
cost = 0
for Nx, Ny in zip(Nx_index,Ny_index):
cost += pow(self._R[Nx, Ny] - self.get_prediction(Nx, Ny), 2)
return np.sqrt(cost/len(Nx_index))
def gradient(self, error, x, y):
"""
gradient of latent feature for GD
:param error: rating - prediction error
:param i: user index
:param j: item index
:return: gradient of latent feature tuple
"""
dp = (error * self._Item_Latent[y, :]) - (self._reg_param * self._User_Latent[x, :])
dq = (error * self._User_Latent[x, :]) - (self._reg_param * self._Item_Latent[y, :])
return dp, dq
def gradient_descent(self, x, y, rating):
"""
graident descent function
:param x: user index of matrix
:param y: item index of matrix
:param rating: rating of (x,y)
"""
# get error
prediction = self.get_prediction(x, y)
error = rating - prediction
# update biases
self._b_User_Latent[x] += self._learning_rate * (error - self._reg_param * self._b_User_Latent[x])
self._b_Item_Latent[y] += self._learning_rate * (error - self._reg_param * self._b_Item_Latent[y])
# update latent feature
dp, dq = self.gradient(error, x, y)
self._User_Latent[x, :] += self._learning_rate * dp
self._Item_Latent[y, :] += self._learning_rate * dq
`
- 사용자의 명령어 문장에 대해 총 4가지 명령어 class 및 해당 명령어내 엔티티를 구별 가능하게 학습하였음.
직접 구성한 레시피 조작 명령어 데이터셋을 통해 모델학습을 진행.
- 사용자의 명령어 문장에 대해 총 4가지 명령어 class 및 해당 명령어내 엔티티를 구별 가능하게 학습하였음.