Search
Duplicate

음성기반 감정인식 서비스

소속팀
크리에이티브랩 팀
팀명
Mad Scientist

Motivation

원래는 말하면 재즈로 변환시켜주는 서비스를 만들려고 했다. 근데 선행연구 검토와 여러 자료조사를 해본 결과 현재 우리 수준에서는 너무 어려운 주제이고 5주안에 끝낼 수 있는 주제가 아닌 것 같아서 다른 주제를 찾아보기로 했다.
이전에 우리가 했던 프로젝트는 텍스트에서 감정추출 하여 이모지를 추천하는 서비스였다.
트위터에서 트윗을 크롤링 해와서 FastText에 학습을 시켜서 텍스트를 입력하면 이모지를 추천해주는 서비스였다.
우리가 저번에는 텍스트에서 감정을 추출하는 것을 했으니까 이번에는 음성에서 감정을 추출해보는 것을 하는 것이 어떨까 라는 생각을 했다.
최근에 유행했던 드라마 “이상한 변호사 우영우”를 보다가 자폐 스펙트럼 장애를 알게 되었다.
자폐스펙트럼 장애란?
(1) 사회적 상호작용에서의 질적인 장해가 다음 항목들 가운데 적어도 2개 항목으로 표현된다.
(a) 사회적 상호작용을 조절하기 위한 눈 마주치기, 얼굴 표정, 몸 자세, 몸짓과 같은 다양한 비언어적 행동을 사용함에 있어서 현저한 장해
(b) 발달 수준에 적합한 친구 관계 발달의 실패
(c) 자발적으로 다른 사람들과 기쁨, 관심, 성공을 나누지 못한다(예: 관심의 대상을 보여주거나, 가져오거나, 지적하지 못함)
(d) 사회적으로나 감정적으로 서로 반응을 주고받는 상호 교류의 결여
[네이버 지식백과] 자폐 스펙트럼 장애 [autism spectrum disorder] (심리학용어사전, 2014. 4.)
드라마 “이상한 변호사 우영우”를 보면서 우리는 자폐스펙트럼 장애를 가진 사람들이 타인의 감정을 인식하는 데 어려움을 느낀 다는 것을 알게 되었다. 그래서 우리가 이분들을 인공지능을 활용해서 타인의 감정을 예측(판단)해주는 서비스를 만들면 좋을 것 같다는생각을 해서 이번 주제를 “Speech Emotion Recogniton”으로 하였다.

Method

인공지능에서는 다른 분야에서 사용되던 모델이나 방법론을 가져오는 경우가 많다. 음성 인공지능 분야에서도 마찬가지로 컴퓨터 비전에서 발전된 CNN, 자연어처리에서 발전된 BERT를 변형한 HuBERT 등을 사용한다. 우리는 Shallow CNN와 HuBERT 이렇게 두 모델을 사용하였다. 검색으로는 두 모델을 비교한 논문이나 깃허브 코드가 없으므로 우리가 직접 이 둘을 비교하려고 한다.
Shallow CNN
CNN은 컴퓨터 비전에서 2d 이미지를 처리하기 위해 만들어진 모델 구조이다. 아래의 그림처럼 0~9의 숫자를 손글씨로 쓴 MNIST 데이터셋을 분류하는 것이 CNN을 사용하는 가장 대표적인 활용사례중 하나이다.
또한 CNN은 보통 이미지를 입력값으로 받기 때문에 음성 데이터를 시각화하는 과정이 필요한데, 그 방법이 mel spectogram이다. 오케스트라를 상상해보면 첼로처럼 낮은 음(=낮은 주파수)과 플루트처럼 높은 음(=높은 주파수)의 여러가지 소리를 듣게 된다. mel spectogram은 주파수 영역대에 따라 어느 영역대의 소리가 큰지 나타내주는 그래프이다. 그래서 x축이 시간, y축이 주파수로 나타나고 각 점들에서 히트맵 색깔로 소리의 세기가 나타난다.
정리하면 음성 데이터를 CNN 모델을 통해 처리할 때에는 음성 데이터를 mel spectogram으로 시각화하는 과정이 들어가고, 그 이후는 일반적인 CNN 모델과 같은 방식으로 작동한다.
Shallow CNN의 모델 구조
HuBERT
HuBERT는 hidden unit BERT의 줄임말인데, 페이스북에서 개발한 모델이고 BERT처럼 사전 학습된 모델로 비지도학습을 하는 모델이다.
HuBERT에서는 음성 데이터를 아래 그림과 같이 mfcc라는 형태로 변환해 학습한다.
자연어처리에서는 단어의 word embedding vector를 학습을 하는 반면, HuBERT는 음성에 대한 speech embedding vector를 학습한다.
HuBERT 모델 구조

Experiment

영어로된 데이터셋(RAVDESS) 모델 평가

Shallow CNN + RAVDESS
먼저 모델이 제대로 돌아가는지 확인을 하기 위해서 해당 모델의 깃허브에서 제공되는 코드와 데이터셋으로 돌려보았다. 여기서 사용된 데이터는 RAVDESS 데이터셋이다. RAVDESS은 8가지의 감정으로 분류되어 있는 데이터셋이다. (01 = neutral, 02 = calm, 03 = happy, 04 = sad, 05 = angry, 06 = fearful, 07 = disgust, 08 = surprised) 이 데이터셋은 남/여 비율 1:1로 구성된 24명의 성우들이 “Kids are talking by the door”, “Dogs are sitting by the door” 두 문장에 8가지의 감정을 담아 녹음한 데이터셋이다.
파일이름은 다음과 같은 기준으로 저장이 되었다.
Modality (01 = full-AV, 02 = video-only, 03 = audio-only).
Vocal channel (01 = speech, 02 = song).
Emotion (01 = neutral, 02 = calm, 03 = happy, 04 = sad, 05 = angry, 06 = fearful, 07 = disgust, 08 = surprised).
Emotional intensity (01 = normal, 02 = strong). NOTE: There is no strong intensity for the ‘neutral’ emotion.
Statement (01 = “Kids are talking by the door”, 02 = “Dogs are sitting by the door”).
Repetition (01 = 1st repetition, 02 = 2nd repetition).
Actor (01 to 24. Odd numbered actors are male, even numbered actors are female).
예를 들어, 02-01-06-01-02-01-12.mp4 파일은 다음과 같은 데이터이다.
Video-only (02)
Speech (01)
Fearful (06)
Normal intensity (01)
Statement “dogs” (02)
1st Repetition (01)
12th Actor (12)
Shallow CNN에 RAVDESS을 학습시킨 결과
한국어 말뭉치 데이터셋으로 평가하기
영어로 된 RAVDESS 데이터셋으로 학습시킨 모델을 한국어로 된 한국어 말뭉치 데이터셋으로 평가를 해봤는데 두 데이터셋의 감정 분류가 다르기 때문에 이상한 결과가 나왔다.
HuBERT + RAVDESS
RAVDESS 데이터셋의 7가지 감정중에서 4가지 감정(sad, neutral, happy, angry)만을 사용해 학습에 적용했해서 성능 평가를 하였고 다음과 같은 결과 가나왔다. 정확도는 75%로 나왔다.

한국어 데이터셋으로 모델 학습 후 평가

1.
AI-Hub
우리가 처음 적용할 데이터셋은 AI-Hub에서 제공해주는 감성 대화 말뭉치 데이터셋이다.
약 10,000개의 음성데이터로 이루어져있고, [기쁨, 당황, 분노, 슬픔, 불안, 상처]로 6개의 감정으로 레이블이 되어있는 데이터셋이다.
다운로드 링크: AI-Hub (aihub.or.kr)
Shallow CNN + AI-Hub
HuBERT + AI-Hub
코드
HuBERT는 happy, sad, angry, neutral 이렇게 네가지 감정으로 학습된 pre-trained 모델을 사용하는데 AI허브는 슬픔, 분노, 불안, 기쁨, 당황, 상처 이렇게 6가지 감정데이터가 있어서 차원이 맞지 않는 에러가 생긴다.
그래서 임시방편으로 당황-neutral 이렇게 매칭을 시키고 나머지는 happy - 기쁨, sad - 슬픔, angry - 분노 이렇게 매칭했다.
그리고 한가지 더 문제점이 있는데 데이터가 많아지면 코랩에서 돌릴때 런타임이 초기화 된다. 전체데이터(1만개)의 20퍼센트만 랜덤 추출해서 돌려도 런타임이 초기화되는 오류가 생긴다. 그래서 전체 데이터의 15퍼센트만 랜덤 추출해서 돌렸다.
neutral과 당황을 매칭했는데도 불구하고 epoch을 7회로 설정했는데 정확도가 약70퍼센트가 나온다.
2.
ETRI
neutral과 당황을 매치하는 비약이 있었기 때문에 AI-Hub 데이터로 만든 모델을 사용하기에는 문제가 있으므로 다른 데이터 셋을 찾기로 했다. 그러다가 발견한 데이터셋이 ETRI에서 제공해주는 KESDy18 데이터셋이다.
총 30명의 한국인 성우(남/여 각 15명)를 대상으로 4가지 카테고리 감정(중립, 행복, 슬픔, 분노)을 표현하며 각 감정 카테고리당 20문장의 한국어 문장을 발화하였다.
다운로드 링크: ETRI 나눔 (nanum.etri.re.kr)
Shallow CNN + ETRI
epoch에 따른 model accuracy와 loss이다. 이전의 7가지 감정분류가 아닌 4가지 감정분류를 사용했음에도 불구하고 높은 정확도를 얻을 수 없었다. 모델의 한계라고 결론내렸다.
감정 예측 히트맵
HuBERT + Etri
코드
데이터 양이 많아서 다 넣어서 학습을 시키면 코랩에서 런타임 초기화 에러가 뜨므로 전체 데이터에서 57% 랜덤 추출하여 학습을 시켰다.
결과적으로 87.5%의 정확도를 가진 모델이 완성 되었다!!
Shallow CNN VS HuBERT
학습속도: Shallow CNN > HuBERT
정확도 : Shallow CNN < HuBERT

GSLM (데이터 증식 목적)

코랩에서 데이터 양이 많다고 런타임 초기화 에러가 나올지 모르고 진행해본 데이터 증식 시도이다. GSLM으로 하나의 음성파일 여러 감정으로 전환하여 데이터 만들고 학습시키려고 하였다.
GSLM은 페이스북에서 작년에 개발한 모델로 올해 4월에 하나의 음성파일을 넣으면 여러 감정으로 전환시켜주는 기능을 추가했다.
페이스북 공식 GSLM 깃허브 코드: https://github.com/facebookresearch/textlesslib
코드
결과는 실패이다…
GSLM은 영어 기반으로 만들어진 데이터라서 그런지 결과물이 너무 이상하게 나왔다.
GSLM 처리 전
GSLM 처리 후
어차피 런타임 에러때문에 사용할 수 없었지만 그래도 좋은 시도였던 것 같다.

웹 및 어플로 서비스화

좋은 모델을 만들었는데 우리 코랩이나 우리 팀원들의 컴퓨터에서만 이 모델을 테스트해볼 수 있다는게 너무 안타까워서 웹 및 어플로 만들어서 누구나 접근해서 사용해볼 수 있게 하려고했다.

Web app  프론트엔드 Goorm react

환경구축 / 실행방법
프론트 엔드 개발에는 구름 ide를 사용했고, react를 기반으로 페이지를 만들었다. 구름 ide의 장점은 서버를 무료로 호스팅해주는 서비스를 제공한다는 점이다.
1.
먼저 구름 ide에 회원가입을 하고, 새 컨테이너를 만들고 실행한다. 이때 ‘항상 켜두기’ 옵션으로 실행한다. ([구름IDE/REACT] 구름IDE 환경으로 리액트 시작하기#1 (tistory.com)를 참고!)
2.
“npm install -g create-react-app” 명령어를 통해 create-react-app 모듈을 설치한다.
3.
“npm install -g n”, “n stable” 명령어를 통해 node.js를 업데이트 한다. (How to Update Node and NPM to the Latest Version (freecodecamp.org)를 참고)
4.
“create-react-app react_front” 를 입력해 ./react_front 폴더에 react 앱을 생성한다.
5.
react_front/src에서 App.js를 아래와 같이 고친다.
코드
6.
react_front/src에 RecordView.js를 생성해, 아래와 같이 작성한다.
코드
7.
아래 사진을 다운로드받아 .svg 형식으로 변환한 이후, react_front/Mad.svg로 업로드 한다. (구글에 png to svg 검색)
8.
“npm install react-media-recorder”를 통해 음성녹음 패키지를 설치한다.
“npm install axios”를 통해 axios 패키지를 설치한다.
9.
“npm install -g pm2”를 통해 백그라운드 실행 모듈인 pm2를 설치한다.
10.
“cd react_front”, “pm2 --name react start npm -- start”를 통해 서버를 실행한다. [작업명]에 아무 글자를 써도 되지만, 우리는 ‘react’로 썼다.
11.
구름 ide의 실행화면에서 “프로젝트” > “실행 URL과 포트”의 url을 통해 외부에서도 웹 페이지에 접속할 수 있다.
** github 저장소에서 clone 하게 되면 코드들을 직접 고칠 필요 없이 개발 환경 세팅에 관련된 명령어들만 입력해주면 된다.
프론트 작동방식
음성녹음을 프론트 서버에 저장하는 것 까지를 구현했다. 이후 계획은 백엔드 서버와 연결해 감정분석 결과를 페이지에 보여주는 것이다. 계획은 다음과 같다.
“send to flask” 버튼을 누르면 flask로 구현한 백엔드 서버에 음성파일을 .wav 형식으로 전송한다. 백엔드 서버에서는 저장된 모델을 통해 감정분석을 하고, 그 결과를 프론트 서버로 다시 전송한다. 프론트 서버는 감정 데이터를 받아서 웹 페이지에 보여준다.
백 엔드와 프론트 엔드는 http의 ‘post’ 메서드를 통해 통신하도록 할 계획이다.

백엔드 Flask pythonanywhere

백엔드 개발에는 pythonanywhere의 개발환경을 사용했고, flask를 통해 구현했다. flask는 파이썬 패키지로, 아주 간단하게 웹 페이지를 만들 수 있다는 장점이 있고, 무엇보다 파이썬이라는 것에 큰 장점이 있다.

디자인 개선 (기존 디자인 -> 현재 디자인)

부트스트랩
부트스트랩 (Bootstrap) 이란?
프론트엔드 개발을 쉽고 빠르게 할 수 있는 프레임워크
프론트에 필요한 각종 레이아웃, 버튼, 입력창 등의 디자인을 CSS와 Javascript로 만들어 놓은 것이다. 웹 디자이너나 개발자 사이에서는 웹 디자인의 혁명이라고 불릴 정도로 폭발적은 반응을 얻는 프레임워크이다.
쉽게 말해 ppt자료를 제작할 때 쓰는 템플릿이라고 보면 된다.
React 용 부트스트랩을 이용해서 빠르게 웹 디자인을 했다. ( React-Bootstrap )
1.
React-Bootstrap 설치 goorm 내 터미널에 아래 코드 입력
npm install react-bootstrap bootstrap
Python
복사
2.
index.html 에 아래 코드 추가
<script src="https://unpkg.com/react/umd/react.production.min.js" crossorigin></script> <script src="https://unpkg.com/react-dom/umd/react-dom.production.min.js" crossorigin></script> <script src="https://unpkg.com/react-bootstrap@next/dist/react-bootstrap.min.js" crossorigin></script> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous" />
Python
복사
3.
index.js 에 아래 코드 추가
import 'bootstrap/dist/css/bootstrap.min.css';
Python
복사
4.
Navigation bar 등 웹페이지에 필요한 요소를 가져와 App.js 에 추가한다.
goorm 컨테이너, 서버, 부트스트랩 연결오류 해결
협업을 하기 위해 여러 방법을 시도해보았다.
한 사람의 깃헙에 프로젝트를 올려서 다른 사람이 그것을 클론해보기도 하고, goorm 에서 자체적으로 제공하는 ‘프로젝트 공유’ 서비스를 이용해보기도 했지만 같은 프로젝트여도 사용자가 누구냐에 따라 허가 문제(Error : permission denied) 등의 여러 오류가 발생해 협업에 어려움이 있었다.
goorm IDE 의 CPU 가 1GB 정도밖에 되지 않고 전체적인 컨트롤이 잘 되지 않는다는 느낌이 들었다. 잘 되던 것도 갑자기 오류가 발생하기도 했다.
1.
환경 설정에 필요한 커맨드들을 cd react_front 한 후에도 터미널에 입력해줌 (커맨드는 지난 노션 페이지 참고)
2.
메인 프로젝트 내에 있는 node_modules 폴더 제거 (react_front 안에 있는 node_modules 아님)
둘 중에 하나로 인해 오류가 해결되었다.
오류를 해결하면서 깨달은 점
vulnerabilities 는 많이 나오지만 크게 신경쓰지 않아도 된다.
그러니 npm audit fix --force 와 같은 컨테이너 환경 자체에 영향을 주는 명령어는 자제하는 것이 좋다.
React-Bootstrap 사용법
터미널에 아래 코드를 입력해 router를 깔아준다.
npm i react-router-dom
Python
복사
react-bootstrap을 깔아준다.
npm install react-bootstrap bootstrap
Python
복사
지난 프로젝트(텍스트 감정추출 이용 이모지 추천 시스템) 를 위해서 혼자 만들고 공개하지 않은 프론트가 있는데 그것을 최대한 활용하고 싶었다. 하지만 이 프론트는 vs code 에서 html과 css만을 이용해서 만든 것이었고 이번에는 react 를 썼기 때문에 jsx를 사용해야했어서 언어가 달라 문제가 있었다. 그러나 이 문제는 html 을 jsx로 바꿔주는 변환기를 이용해 생각보다 쉽게 해결됐다.
html 을 jsx로 바꿔주는 변환기: https://transform.tools/html-to-jsx
변환기를 이용하고 보니 html 과 jsx에 그렇게 큰 차이는 없다는 것을 깨달았다. 문법이 조금 다른데 한 번 변환기를 쓴 이후에는 변환기를 쓰지 않고 직접 쓸 수 있는 정도였다.
요소 추가하기
‘Disqus’ 이용해 웹사이트에 댓글, 반응 기능 추가하기
Disqus (https://disqus.com/) 는 사용자가 원하는 페이지에 댓글과 반응기능을 넣을 수 있게끔해주는 서비스이다. 다행히 goorm , react 와 충돌이 없어서 이번 프론트에도 적용할 수 있었다.
가입하고 내가 원하는 사이트를 입력하면 기능이 담긴 아래와 같은 스크립트를 주는데 이것을 바로 index.html 에 붙여넣어주기만 하면 기능이 생성된다.
코드
디자인의 html, css, js 를 공유하는 오픈소스 사이트 이용
웹디자인을 공유하는 사이트는 여러개 있지만 그중에서 Codepen (https://codepen.io/trending) 을 이용했다. 이를 버튼 디자인에 활용했다.
위와 같이 제공되는 html 을 jsx식으로 변경해 App.js 파일에 넣어주고 css 를 App.css 에 넣어주면 된다. 색상, 크기 등을 바꾸고 싶으면 css를 조금 바꿔주면 된다.
결과물

PWA로 웹을 어플로 만들기

PWA란? Progressive Web Application 의 약자로 PWA는 HTML, CSS, 자바스크립트(JavaScript)와 같은 웹 기술로 만드는 앱이다. 하지만 그 느낌과 기능은 실제 네이티브 앱과 견줄 수 있을 정도로 좋다. 몇 가지의 스마트한 기능들을 추가하면, 세상의 그 어떤 웹사이트라도 PWA로 바꿀 수 있다. 즉, 네이티브 앱을 개발하는 것은 상당히 어렵지만, PWA는 훨씬 더 빠르게 개발할 수 있고, 푸시 알림이나 오프라인 지원과 같은 네이티브 앱의 특징들도 전부 제공해준다. 실제로 트위터(twitter.com), 스타벅스(Starbucks.com), 핀터레스트(Pinterest.com), 워싱턴포스트(Washingtonpost.com) 등 우리가 온라인에서 볼 수 있는 많은 사이트들도 PWA이다.
PWA builder 사이트(https://www.pwabuilder.com/)
앱을 만들기 전, 우리 웹사이트 주소를 입력하면 앱으로 잘 변환될 수 있는지 점수를 매겨준다.
아래 4가지 모두를 충족시키면 위와 같이 180점을 얻을 수 있다.
PWA 필수 Requirement 4가지
1. deploy 된 website or webApp
2. Https - 보안
3. Application Manifest
Json format 으로 된 text 파일로 webApp에 대한 여러가지 정보들이 담겨있는 파일이다. 이 manifest 를 이용해서 다양한 기기들의 webApp을 설치할 수 있다.
web app manifest 에 필수로 들어가야 되는 사항들
short_name or name
icons : must include a 192px and a 512px icon
start_url
display : must be one of fullscreenstandalone, or minimal-ui
prefer_related_applications must not be present, or be false
4. Service Worker
JS 파일로, Webapp 과 서버와 데이터를 주고 받을때 중간에서 그 모든 요청들을 통제하고 관리한다. 그래서 어떤 특정한 네트위크 요청과 반응에 한해서 어떠한 부분을 따로 저장을 해놓았다가 offline 상태일때 저장해둔 데이터를 보여주는 역할, 또는 최신의 사항들은 미리 fetch 해와서 사용자가 webapp 을 키자마자 데이터를 바로 보여줄수 있도록 하는 것, 성능이 좋은 webapp 을 만들기 위해서 service worker 를 사용할 수 있다.
PWA builder는 이러한 요구사항들이 충족되었는지 확인하고 수정할 수 있도록 해준다. 수정해서 만든 요구사항들을 마지막에 패키지로 만들어서 다운받을 수 있게 한다.
어플의 기본적인 정보를 설정하고 앱 아이콘을 만들어준다.
안드로이드로 어플을 배포한다.
PWA builder 를 이용해 우리 웹사이트를 PWA로 만든다.

최종 결과물!!

컴퓨터 인터넷 창
모바일 앱

Contribution

발전 가능성
음성, 텍스트, 영상 데이터를 모두 입력받아서 여러 모델을 사용해서 감정 분석을 하는 multimodal으로 발전시킬 수 있다.
이 모든 것을 실시간으로도 구현할 수 있다. 그렇게 되면 자폐 스펙트럼장애를 가진 분들에게 훨씬 유용한 서비스가 될 것이다.
한계
사람의 감정에 대한 판단은 주관적이다. 그래서 감정을 완벽하게 구분하여 학습시키기가 어렵다.