배희수

README 업데이트

# Speech Recommendation
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
This diff could not be displayed because it is too large.
{
"name": "gesture_test",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"bootstrap": "^4.5.0",
"bootstrap-vue": "^2.15.0",
"brain.js": "^2.0.0-beta.2",
"chart.js": "^2.9.4",
"core-js": "^3.6.5",
"vue": "^2.6.11",
"vue-chart.js": "^0.2.0",
"vue-chartjs-typescript": "^3.3.3",
"vue-class-component": "^7.2.3",
"vue-graph": "^0.8.7",
"vue-property-decorator": "^8.4.2",
"vue-router": "^3.2.0",
"vuex": "^3.4.0"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^2.33.0",
"@typescript-eslint/parser": "^2.33.0",
"@vue/cli-plugin-babel": "~4.4.0",
"@vue/cli-plugin-eslint": "~4.4.0",
"@vue/cli-plugin-router": "~4.4.0",
"@vue/cli-plugin-typescript": "~4.4.0",
"@vue/cli-plugin-vuex": "~4.4.0",
"@vue/cli-service": "~4.4.0",
"@vue/eslint-config-standard": "^5.1.2",
"@vue/eslint-config-typescript": "^5.0.2",
"eslint": "^6.7.2",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^6.2.2",
"stylus": "^0.54.7",
"stylus-loader": "^3.0.2",
"typescript": "~3.9.3",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"@vue/standard",
"@vue/typescript/recommended"
],
"parserOptions": {
"ecmaVersion": 2020
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
No preview for this file type
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
<template>
<div>
<Speech/>
</div>
</template>
<style lang="stylus">
#app
font-family Avenir, Helvetica, Arial, sans-serif
-webkit-font-smoothing antialiased
-moz-osx-font-smoothing grayscale
text-align center
color #2c3e50
margin-top 60px
</style>
<script>
import Speech from './components/Speech'
export default {
name: 'app',
components: {
Speech
}
}
</script>
import { Bar, mixins } from 'vue-chartjs-typescript'
const { reactiveProp } = mixins
export default {
extends: Bar,
props: ['options'],
mixins: [reactiveProp],
mounted () {
this.renderChart(this.chartData, this.options)
}
}
<template >
<div class="main-layout">
<b-navbar variant="dark" type="dark" :sticky="sticky">
<b-navbar-brand href="#">발화 추천 알고리즘의 비교</b-navbar-brand>
</b-navbar>
<b-tabs
class="pl-1 content-wrapper"
vertical
pills
card
v-model="tabIndex"
@input="initializeCommonData"
>
<b-tab title="HMM" active>
<b-row>
<b-col>
<div class="p-3">
<h5>추천 발화</h5>
<b-form inline>
<b-form-input v-model="userInputState" placeholder="추천 발화" class="m-2" :state="userInputState.length > 0 ? true : false"></b-form-input>
<b-button class="m-2" @click="generateTrainingData" >학습 데이터 생성</b-button>
</b-form>
<b-alert
:show="dismissCountDown"
dismissible
variant="warning"
@dismissed="dismissCountDown=0"
@dismiss-count-down="countDownChanged"
>
최소 1개의 시나리오를 입력해주세요.
</b-alert>
</div>
<div class="p-3">
<h5>시나리오</h5>
<b-form>
<template v-for="(scenario, index) of scenarioList">
<b-form-group
:label="'시나리오-' + (index + 1)"
:key="'scenario-' + index"
>
<div class="scenario-item">
<b-form-input v-model="scenario.sequence" placeholder="블록 ID를 쉼표로 구분하여 입력해주세요." class="m-2" :state="scenario.sequence.length > 0 ? true : false"></b-form-input>
<b-button class="m-2" @click="deleteScenario(scenario)">-</b-button>
</div>
</b-form-group>
</template>
<b-button class="m-2" @click="addNewItem">+</b-button>
</b-form>
</div>
<div class="p-3">
<b-form inline>
<b-form-input v-model="userInputScenario.sequence" placeholder="블록 ID를 쉼표로 구분하여 입력해주세요." class="m-2" :state="userInputScenario.sequence.length > 0 ? true : false"></b-form-input>
<b-button class="m-2" @click="detectSpeech" >발화 추천</b-button>
</b-form>
<span class="m-2">추천 발화: {{detectedSpeech}}</span>
</div>
<div class="p-3">
<h5>학습 데이터</h5>
<b-table striped hover :items="displayTrainingSet"></b-table>
</div>
</b-col>
<b-col>
<div>
<b-card
title="HMM 학습 및 예측 시나리오"
img-src="https://cdn.pixabay.com/photo/2017/01/23/08/13/microphone-2001751_1280.png"
img-alt="Speech Recommendation"
img-top
style="max-width: 30rem;"
tag="article"
class="mb-2"
>
<b-card-text>1. 추천 발화 입력</b-card-text>
<b-card-text>2. 입력한 추천 발화가 나올 수 있는 시나리오 입력("+" 버튼 클릭)</b-card-text>
<b-card-text>3. "학습 데이터 생성" 버튼 클릭</b-card-text>
<b-card-text>4. 추천 대상 발화의 수 만큼 (1 ~ 3)번 과정 반복</b-card-text>
<b-card-text>5. 발화를 추천 받고자 하는 시나리오 입력</b-card-text>
<b-card-text>6. "발화 추천" 버튼 클릭</b-card-text>
<b-card-text>7. 추천 발화 확인</b-card-text>
</b-card>
</div>
</b-col>
</b-row>
</b-tab>
<b-tab title="MC">
<b-row>
<b-col>
<div class="p-3">
<h5>블록</h5>
<b-alert
:show="dismissCountDown"
dismissible
variant="warning"
@dismissed="dismissCountDown=0"
@dismiss-count-down="countDownChanged"
>
10개의 발화를 입력해주세요.
</b-alert>
<b-form>
<template v-for="(block, index) of blockList">
<b-form-group
:label="'ID-' + index"
:key="'block-' + index"
>
<div class="scenario-item">
<b-form-input v-model="block.speech" placeholder="발화를 입력해주세요." class="m-2" :state="block.speech.length > 0 ? true : false"></b-form-input>
<b-button class="m-2" @click="deleteBlock(block)">-</b-button>
</div>
</b-form-group>
</template>
<b-button class="m-2" @click="addNewItem">+</b-button>
<b-button class="m-2" @click="generateTrainingData" >학습 데이터 생성</b-button>
</b-form>
</div>
<div class="p-3">
<b-form>
<b-form-input v-model="userInputStateSequence" placeholder="추천하고자 하는 발화가 몇 번째 발화인지 입력해주세요" class="m-2" :state="userInputStateSequence.length > 0 ? true : false"></b-form-input>
<b-button class="m-2" @click="detectSpeech" >발화 추천</b-button>
<span class="m-2">추천 발화: {{detectedSpeech}}</span>
</b-form>
</div>
<div class="p-3">
<h5>학습 데이터</h5>
<b-table striped hover :items="displayTrainingSet"></b-table>
</div>
</b-col>
<b-col>
<div>
<b-card
title="MC 학습 및 예측 시나리오"
img-src="https://cdn.pixabay.com/photo/2017/01/23/08/13/microphone-2001751_1280.png"
img-alt="Speech Recommendation"
img-top
style="max-width: 30rem;"
tag="article"
class="mb-2"
>
<b-card-text>1. 시나리오 상 포함되는 블록 정보(ID) 입력("+" 버튼 클릭)</b-card-text>
<b-card-text>2. "학습 데이터 생성" 버튼 클릭</b-card-text>
<b-card-text>3. 추천 발화가 필요한 시나리오 상 순서 입력</b-card-text>
<b-card-text>4. "발화 추천" 버튼 클릭</b-card-text>
<b-card-text>5. 추천 발화 확인</b-card-text>
</b-card>
</div>
</b-col>
</b-row>
</b-tab>
<b-tab title="RNN">
<b-row>
<b-col>
<div class="p-3">
<h5>추천 발화</h5>
<b-form inline>
<b-form-input v-model="userInputState" placeholder="추천 발화" class="m-2" :state="userInputState.length > 0 ? true : false"></b-form-input>
<b-button class="m-2" @click="generateTrainingData" >학습 데이터 생성</b-button>
</b-form>
<b-alert
:show="dismissCountDown"
dismissible
variant="warning"
@dismissed="dismissCountDown=0"
@dismiss-count-down="countDownChanged"
>
최소 1개의 시나리오를 입력해주세요.
</b-alert>
</div>
<div class="p-3">
<h5>시나리오</h5>
<b-form>
<template v-for="(scenario, index) of scenarioList">
<b-form-group
:label="'시나리오-' + (index + 1)"
:key="'scenario-' + index"
>
<div class="scenario-item">
<b-form-input v-model="scenario.sequence" placeholder="블록 ID를 쉼표로 구분하여 입력해주세요." class="m-2" :state="scenario.sequence.length > 0 ? true : false"></b-form-input>
<b-button class="m-2" @click="deleteScenario(scenario)">-</b-button>
</div>
</b-form-group>
</template>
<b-button class="m-2" @click="addNewItem">+</b-button>
</b-form>
</div>
<div class="p-3">
<b-form inline>
<b-form-input v-model="userInputScenario.sequence" placeholder="블록 ID를 쉼표로 구분하여 입력해주세요." class="m-2" :state="userInputScenario.sequence.length > 0 ? true : false"></b-form-input>
<b-button class="m-2" @click="detectSpeech" >발화 추천</b-button>
</b-form>
<span class="m-2">추천 발화: {{detectedSpeech}}</span>
</div>
<div class="p-3">
<h5>학습 데이터</h5>
<b-table striped hover :items="displayTrainingSet"></b-table>
</div>
</b-col>
<b-col>
<div>
<b-card
title="RNN 학습 및 예측 시나리오"
img-src="https://cdn.pixabay.com/photo/2017/01/23/08/13/microphone-2001751_1280.png"
img-alt="Speech Recommendation"
img-top
style="max-width: 30rem;"
tag="article"
class="mb-2"
>
<b-card-text>1. 추천 발화 입력</b-card-text>
<b-card-text>2. 입력한 추천 발화가 나올 수 있는 시나리오 입력("+" 버튼 클릭)</b-card-text>
<b-card-text>3. "학습 데이터 생성" 버튼 클릭</b-card-text>
<b-card-text>4. 추천 대상 발화의 수 만큼 (1 ~ 3)번 과정 반복</b-card-text>
<b-card-text>5. 발화를 추천 받고자 하는 시나리오 입력</b-card-text>
<b-card-text>6. "발화 추천" 버튼 클릭</b-card-text>
<b-card-text>7. 추천 발화 확인</b-card-text>
</b-card>
</div>
</b-col>
</b-row>
</b-tab>
<b-tab title="LSTM">
<b-row>
<b-col>
<div class="p-3">
<h5>추천 발화</h5>
<b-form inline>
<b-form-input v-model="userInputState" placeholder="추천 발화" class="m-2" :state="userInputState.length > 0 ? true : false"></b-form-input>
<b-button class="m-2" @click="generateTrainingData" >학습 데이터 생성</b-button>
</b-form>
<b-alert
:show="dismissCountDown"
dismissible
variant="warning"
@dismissed="dismissCountDown=0"
@dismiss-count-down="countDownChanged"
>
최소 1개의 시나리오를 입력해주세요.
</b-alert>
</div>
<div class="p-3">
<h5>시나리오</h5>
<b-form>
<template v-for="(scenario, index) of scenarioList">
<b-form-group
:label="'시나리오-' + (index + 1)"
:key="'scenario-' + index"
>
<div class="scenario-item">
<b-form-input v-model="scenario.sequence" placeholder="블록 ID를 쉼표로 구분하여 입력해주세요." class="m-2" :state="scenario.sequence.length > 0 ? true : false"></b-form-input>
<b-button class="m-2" @click="deleteScenario(scenario)">-</b-button>
</div>
</b-form-group>
</template>
<b-button class="m-2" @click="addNewItem">+</b-button>
</b-form>
</div>
<div class="p-3">
<b-form inline>
<b-form-input v-model="userInputScenario.sequence" placeholder="블록 ID를 쉼표로 구분하여 입력해주세요." class="m-2" :state="userInputScenario.sequence.length > 0 ? true : false"></b-form-input>
<b-button class="m-2" @click="detectSpeech" >발화 추천</b-button>
</b-form>
<span class="m-2">추천 발화: {{detectedSpeech}}</span>
</div>
<div class="p-3">
<h5>학습 데이터</h5>
<b-table striped hover :items="displayTrainingSet"></b-table>
</div>
</b-col>
<b-col>
<div>
<b-card
title="LSTM 학습 및 예측 시나리오"
img-src="https://cdn.pixabay.com/photo/2017/01/23/08/13/microphone-2001751_1280.png"
img-alt="Speech Recommendation"
img-top
style="max-width: 30rem;"
tag="article"
class="mb-2"
>
<b-card-text>1. 추천 발화 입력</b-card-text>
<b-card-text>2. 입력한 추천 발화가 나올 수 있는 시나리오 입력("+" 버튼 클릭)</b-card-text>
<b-card-text>3. "학습 데이터 생성" 버튼 클릭</b-card-text>
<b-card-text>4. 추천 대상 발화의 수 만큼 (1 ~ 3)번 과정 반복</b-card-text>
<b-card-text>5. 발화를 추천 받고자 하는 시나리오 입력</b-card-text>
<b-card-text>6. "발화 추천" 버튼 클릭</b-card-text>
<b-card-text>7. 추천 발화 확인</b-card-text>
</b-card>
</div>
</b-col>
</b-row>
</b-tab>
<b-tab title="통합">
<b-row>
<b-col>
<div class="p-3">
<h5>추천 발화</h5>
<b-form inline>
<b-form-input v-model="userInputState" placeholder="추천 발화" class="m-2" :state="userInputState.length > 0 ? true : false"></b-form-input>
<b-button class="m-2" @click="generateTrainingData" >학습 데이터 생성</b-button>
</b-form>
<b-alert
:show="dismissCountDown"
dismissible
variant="warning"
@dismissed="dismissCountDown=0"
@dismiss-count-down="countDownChanged"
>
최소 1개의 시나리오를 입력해주세요.
</b-alert>
</div>
<div class="p-3">
<h5>시나리오</h5>
<b-form>
<template v-for="(scenario, index) of scenarioList">
<b-form-group
:label="'시나리오-' + (index + 1)"
:key="'scenario-' + index"
>
<div class="scenario-item">
<b-form-input v-model="scenario.sequence" placeholder="블록 ID를 쉼표로 구분하여 입력해주세요." class="m-2" :state="scenario.sequence.length > 0 ? true : false"></b-form-input>
<b-button class="m-2" @click="deleteScenario(scenario)">-</b-button>
</div>
</b-form-group>
</template>
<b-button class="m-2" @click="addNewItem">+</b-button>
</b-form>
</div>
<div class="p-3">
<b-form inline>
<b-form-input v-model="userInputScenario.sequence" placeholder="블록 ID를 쉼표로 구분하여 입력해주세요." class="m-2" :state="userInputScenario.sequence.length > 0 ? true : false"></b-form-input>
<b-button class="m-2" @click="detectSpeech" >발화 추천</b-button>
</b-form>
<p class="m-2">추천 발화(HMM): {{detectedSpeechHMM}}</p>
<p class="m-2">추천 발화(MC): {{detectedSpeechMC}}</p>
<p class="m-2">추천 발화(RNN): {{detectedSpeechRNN}}</p>
<p class="m-2">추천 발화(LSTM): {{detectedSpeechLSTM}}</p>
</div>
<div class="p-3">
<h5>학습 데이터</h5>
<b-button class="m-2" @click="onClickShowTrainingData">{{ showTrainingData ? '숨기기' : '보이기' }}</b-button>
<b-table v-if="showTrainingData" striped hover :items="displayTrainingSet"></b-table>
</div>
</b-col>
<b-col>
<div>
<b-card
title="통합 학습 및 예측 시나리오"
img-src="https://cdn.pixabay.com/photo/2017/01/23/08/13/microphone-2001751_1280.png"
img-alt="Speech Recommendation"
img-top
style="max-width: 30rem;"
tag="article"
class="mb-2"
>
<b-card-text>1. 추천 발화 입력</b-card-text>
<b-card-text>2. 입력한 추천 발화가 나올 수 있는 시나리오 입력("+" 버튼 클릭)</b-card-text>
<b-card-text>3. "학습 데이터 생성" 버튼 클릭</b-card-text>
<b-card-text>4. 추천 대상 발화의 수 만큼 (1 ~ 3)번 과정 반복</b-card-text>
<b-card-text>5. 발화를 추천 받고자 하는 시나리오 입력</b-card-text>
<b-card-text>6. "발화 추천" 버튼 클릭</b-card-text>
<b-card-text>7. 추천 발화 확인</b-card-text>
</b-card>
</div>
</b-col>
</b-row>
<b-row>
<b-col>
<div class="p-3">
<h5>모델별 결과 확인</h5>
<b-button class="m-2" @click="createGraph">그래프 생성</b-button>
<div class="container">
<bar-chart
v-if="showGraph"
:chart-data="chartData"
:options="options"
/>
</div>
</div>
</b-col>
</b-row>
</b-tab>
</b-tabs>
</div>
</template>
<script lang="ts">
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
import Vue from 'vue'
import { Component, Prop } from 'vue-property-decorator'
import * as brain from 'brain.js/src'
// @ts-ignore
import BarChart from '../BarChart.js'
class Scenario {
sequence: string;
constructor (sequence: string) {
this.sequence = sequence
}
}
class Block {
speech: string;
constructor (speech: string) {
this.speech = speech
}
}
@Component({
components: {
BarChart
}
})
export default class Speech extends Vue {
private sticky = true
private dismissCountDown = 0
private dismissSecs = 2
private tabIndex = 1
private showTrainingData = false
// Graph
private showGraph = false
private chartData = {
labels: ['HMM', 'RNN', 'LSTM'],
datasets: [] as any[]
}
private options = {
responsive: true,
maintainAspectRatio: false
}
// 공통
private displayTrainingSet: any[] = []
private detectedSpeech = ''
private singleTrainingData: any[] = []
private userInputState = ''
private scenarioList: Scenario[] = []
private userInputScenario: Scenario = new Scenario('')
private trainingSet: Map<string, any[]> = new Map()
// HMM
private observation2stateMatrix!: any[]
private observation2observationMatrix!: any[]
// MC
private blockList: Block[] = []
private initProbList: number[] = []
private state2stateMatrix!: number[][]
private userInputStateSequence = ''
// RNN
private netRnn = new brain.recurrent.RNN()
// LSTM
private netLstm = new brain.recurrent.LSTM()
// ALL
private detectedSpeechHMM = ''
private detectedSpeechMC = ''
private detectedSpeechRNN = ''
private detectedSpeechLSTM = ''
onClickShowTrainingData () {
this.showTrainingData = !this.showTrainingData
}
createGraph () {
const stateStrings = [...this.trainingSet.keys()]
const chartDataEntry = {
label: 'accuracy',
data: [] as number[]
}
let totalNum = 0
let hmmCount = 0
let rnnCount = 0
let lstmCount = 0
for (let index = 0; index < stateStrings.length; index++) {
const parsedSequenceList = this.trainingSet.get(stateStrings[index]) as any[]
for (let secondIndex = 0; secondIndex < parsedSequenceList.length; secondIndex++) {
const parsedSequence = parsedSequenceList[secondIndex] as number[]
const parsedSequenceStr = parsedSequence.join()
this.userInputScenario.sequence = parsedSequenceStr
this.detectSpeechForHMM()
if (this.detectedSpeechHMM === stateStrings[index]) {
hmmCount++
}
this.detectSpeechForRNN()
if (this.detectedSpeechRNN === stateStrings[index]) {
rnnCount++
}
if (this.detectedSpeechLSTM === stateStrings[index]) {
lstmCount++
}
totalNum++
}
}
this.$set(chartDataEntry, 'data', [(hmmCount / totalNum) * 100, (rnnCount / totalNum) * 100, (lstmCount / totalNum) * 100])
this.$set(this.chartData, 'datasets', [chartDataEntry])
this.showGraph = true
}
initializeCommonData () {
this.displayTrainingSet = []
this.singleTrainingData = []
this.userInputState = ''
this.detectedSpeech = ''
this.userInputStateSequence = ''
this.trainingSet = new Map()
if (this.tabIndex === 4) {
this.observation2stateMatrix = []
this.observation2observationMatrix = []
this.state2stateMatrix = []
this.initProbList = []
this.blockList = []
this.netRnn = new brain.recurrent.RNN()
this.netLstm = new brain.recurrent.LSTM()
}
}
countDownChanged (dismissCountDown: number) {
this.dismissCountDown = dismissCountDown
}
showAlert () {
this.dismissCountDown = this.dismissSecs
}
clearHMM () {
this.singleTrainingData = []
this.displayTrainingSet = []
}
clearMC () {
this.singleTrainingData = []
this.state2stateMatrix = []
this.displayTrainingSet = []
}
clearRNN () {
this.singleTrainingData = []
this.displayTrainingSet = []
}
clearAll () {
this.singleTrainingData = []
this.displayTrainingSet = []
}
addNewItem () {
if (this.tabIndex === 1) {
const block: Block = new Block('')
this.blockList.push(block)
} else {
const scenario: Scenario = new Scenario('')
this.scenarioList.push(scenario)
}
}
deleteScenario (input: Scenario) {
const index = this.scenarioList.findIndex(scenario => scenario.sequence === input.sequence)
if (index !== -1) {
this.scenarioList.splice(index, 1)
}
}
deleteBlock (input: Block) {
const index = this.blockList.findIndex(block => block.speech === input.speech)
if (index !== -1) {
this.blockList.splice(index, 1)
}
}
generateTrainingDataForHMM () {
// 시나리오 입력 여부 체크
if (this.scenarioList.length === 0) {
this.showAlert()
return
}
// 기존 학습 데이터 및 출력 데이터 클리어
this.clearHMM()
// 학습 데이터 생성
this.generateRandomSequenceForHMM()
// 생성된 학습 데이터를 출력 데이터로 할당
this.displayTrainingSet = [...this.singleTrainingData]
// 생성된 학습 데이터를 기반으로 학습 시작
this.trainingForHMM()
}
generateTrainingDataForMC () {
// 블록 입력 여부 체크
if (this.blockList.length !== 10) {
this.showAlert()
return
}
// 기존 학습 데이터 및 출력 데이터 클리어
this.clearMC()
// 학습 데이터 생성 및 초기 확률 계산
this.generateRandomSequenceForMC()
// 생성된 학습 데이터를 출력 데이터로 할당
this.displayTrainingSet = [...this.singleTrainingData]
// 생성된 학습 데이터를 기반으로 학습 시작
this.trainingForMC()
}
generateTrainingDataForRNN () {
// 시나리오 입력 여부 체크
if (this.scenarioList.length === 0) {
this.showAlert()
return
}
// 기존 학습 데이터 및 출력 데이터 클리어
this.clearRNN()
// 학습 데이터 생성
this.setTrainingDataForRNN()
// 생성된 학습 데이터를 출력 데이터로 할당
this.displayTrainingSet = [...this.singleTrainingData]
// 생성된 학습 데이터를 기반으로 학습 시작
this.trainingForRNN()
}
generateTrainingDataForAll () {
// 시나리오 입력 여부 체크
if (this.scenarioList.length === 0) {
this.showAlert()
return
}
// 기존 학습 데이터 및 출력 데이터 클리어
this.clearAll()
// 학습 데이터 생성
this.setTrainingDataForAll()
// 생성된 학습 데이터를 출력 데이터로 할당
this.displayTrainingSet = [...this.singleTrainingData]
this.trainingForHMM()
this.trainingForMC()
this.trainingForRNN()
}
generateTrainingData () {
if (this.tabIndex === 0) {
this.generateTrainingDataForHMM()
} else if (this.tabIndex === 1) {
this.generateTrainingDataForMC()
} else if (this.tabIndex === 2 || this.tabIndex === 3) {
this.generateTrainingDataForRNN()
} else {
this.generateTrainingDataForAll()
}
}
parseSequence (sequence: string) {
const parsedSequence: string[] = sequence.split(',')
const resultSequence: number[] = []
for (let index = 0; index < parsedSequence.length; index++) {
resultSequence.push(parseInt(parsedSequence[index]))
}
return resultSequence
}
// 100개의 랜덤 학습 데이터 생성
generateRandomSequenceForHMM () {
// 학습 셋에 STATE 추가
this.trainingSet.set(this.userInputState, [])
const parsedSequenceList: any[] = []
for (let index = 0; index < this.scenarioList.length; index++) {
const parsedSequence = this.parseSequence(this.scenarioList[index].sequence)
parsedSequenceList.push(parsedSequence)
}
const iter = this.trainingSet.get(this.userInputState)
if (iter === null || iter === undefined) {
return
}
for (let index = 0; index < 100; index++) {
const randomIndex = Math.floor(Math.random() * parsedSequenceList.length)
this.singleTrainingData.push(parsedSequenceList[randomIndex])
iter.push(parsedSequenceList[randomIndex])
}
}
// 100개의 랜덤 학습 데이터 생성
generateRandomSequenceForMC () {
for (let index = 0; index < 10; index++) {
this.initProbList[index] = 0
}
for (let index = 0; index < 100; index++) {
const generatedSequence = []
for (let secondIndex = 0; secondIndex < 5; secondIndex++) {
const randomIndex = Math.floor(Math.random() * 10)
this.initProbList[randomIndex]++
generatedSequence.push(randomIndex)
}
this.singleTrainingData.push(generatedSequence)
}
for (let index = 0; index < 10; index++) {
this.initProbList[index] /= 500
}
}
setTrainingDataForAll () {
// 학습 셋에 STATE 추가
this.trainingSet.set(this.userInputState, [])
// MC 초기 확률 리스트 초기화
for (let index = 0; index < 10; index++) {
this.initProbList[index] = 0
}
const parsedSequenceList: any[] = []
for (let index = 0; index < this.scenarioList.length; index++) {
const parsedSequence = this.parseSequence(this.scenarioList[index].sequence)
parsedSequenceList.push(parsedSequence)
}
const iter = this.trainingSet.get(this.userInputState)
if (iter === null || iter === undefined) {
return
}
for (let index = 0; index < 100; index++) {
const randomIndex = Math.floor(Math.random() * parsedSequenceList.length)
this.singleTrainingData.push(parsedSequenceList[randomIndex])
for (let secondIndex = 0; secondIndex < 5; secondIndex++) {
this.initProbList[parsedSequenceList[randomIndex][secondIndex]]++
}
iter.push(parsedSequenceList[randomIndex])
}
for (let index = 0; index < 10; index++) {
this.initProbList[index] /= 500
}
}
setTrainingDataForRNN () {
// 학습 셋에 STATE 추가
this.trainingSet.set(this.userInputState, [])
const parsedSequenceList: any[] = []
for (let index = 0; index < this.scenarioList.length; index++) {
const parsedSequence = this.parseSequence(this.scenarioList[index].sequence)
parsedSequenceList.push(parsedSequence)
}
const iter = this.trainingSet.get(this.userInputState)
if (iter === null || iter === undefined) {
return
}
for (let index = 0; index < parsedSequenceList.length; index++) {
const sequence = parsedSequenceList[index]
this.singleTrainingData.push(sequence)
iter.push(sequence)
}
}
trainingForHMM () {
const stateStrings = [...this.trainingSet.keys()]
const nState = stateStrings.length
const nObservation = 10 // 블록 ID (임시로 숫자로 가정... 0 ~ 9)
const observation2stateMatrix = Array(nObservation).fill(null).map(() => Array(nState).fill(0))
const observation2observationMatrix = Array(nObservation).fill(null).map(() => Array(nObservation).fill(0))
let observationCount = 0
for (let i = 0; i < nState; i++) {
const key = stateStrings[i]
const observations: any[] = this.trainingSet.get(key)!
for (let j = 0; j < observations.length; j++) {
const observation: number[] = observations[j]
for (let k = 0; k < observation.length - 1; k++) {
observation2observationMatrix[observation[k]][observation[k + 1]]++
observation2stateMatrix[observation[k]][i]++
observationCount++
}
observation2stateMatrix[observation[observation.length - 1]][i]++
}
}
for (let i = 0; i < nState; i++) {
const key: string = stateStrings[i]
const obervationTrainNum: number = this.trainingSet.get(key)!.length
for (let j = 0; j < 10; j++) {
observation2stateMatrix[j][i] = observation2stateMatrix[j][i] / obervationTrainNum
}
}
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
observation2observationMatrix[i][j] = observation2observationMatrix[i][j] / observationCount
}
}
this.observation2stateMatrix = observation2stateMatrix
this.observation2observationMatrix = observation2observationMatrix
console.log(JSON.stringify(observation2stateMatrix).replace(/([[)(.*)(]])/g, '[\n [$2]\n]').replace(/],/g, '],\n '))
console.log(JSON.stringify(observation2observationMatrix).replace(/([[)(.*)(]])/g, '[\n [$2]\n]').replace(/],/g, '],\n '))
}
trainingForMC () {
const nState = 10
const state2stateMatrix = Array(nState).fill(null).map(() => Array(nState).fill(0))
let stateCount = 0
for (let i = 0; i < this.singleTrainingData.length; i++) {
const blockSequence: number[] = this.singleTrainingData[i]
for (let j = 0; j < blockSequence.length - 1; j++) {
state2stateMatrix[blockSequence[j]][blockSequence[j + 1]]++
stateCount++
}
}
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
state2stateMatrix[i][j] = state2stateMatrix[i][j] / stateCount
if (state2stateMatrix[i][j] === 0) {
state2stateMatrix[i][j] = 0.0001
}
}
}
this.state2stateMatrix = state2stateMatrix
console.log(JSON.stringify(state2stateMatrix).replace(/([[)(.*)(]])/g, '[\n [$2]\n]').replace(/],/g, '],\n '))
}
trainingForRNN () {
const stateString = [...this.trainingSet.keys()]
const trainDataList: object[] = []
for (let i = 0; i < stateString.length; i++) {
const key = stateString[i]
const iter = this.trainingSet.get(key) as any[]
for (let j = 0; j < iter.length; j++) {
const trainEntry = {
input: [],
output: ''
}
trainEntry.input = iter[j]
trainEntry.output = key
trainDataList.push(trainEntry)
}
}
if (this.tabIndex === 2) {
this.netRnn.train(trainDataList, {
iterations: 30,
log: (details) => console.log(details),
errorThresh: 0.011
})
} else if (this.tabIndex === 3) {
this.netLstm.train(trainDataList, {
iterations: 30,
log: (details) => console.log(details),
errorThresh: 0.011
})
} else {
this.netRnn = new brain.recurrent.RNN()
this.netLstm = new brain.recurrent.LSTM()
this.netRnn.train(trainDataList, {
iterations: 30,
log: (details) => console.log('RNN: ' + details),
errorThresh: 0.0001
})
this.netLstm.train(trainDataList, {
iterations: 30,
log: (details) => console.log('LSTN: ' + details),
errorThresh: 0.0001
})
}
}
detectSpeech () {
if (this.tabIndex === 0) {
this.detectSpeechForHMM()
} else if (this.tabIndex === 1) {
this.detectSpeechForMC()
} else if (this.tabIndex === 2 || this.tabIndex === 3) {
this.detectSpeechForRNN()
} else {
this.detectSpeechForHMM()
this.detectSpeechForMC()
this.detectSpeechForRNN()
}
}
detectSpeechForHMM () {
const parsedSequence = this.parseSequence(this.userInputScenario.sequence)
this.detectedSpeech = parsedSequence.toString()
const stateStrings = [...this.trainingSet.keys()]
const nState = stateStrings.length
const likelyhoodofAllClass = Array(nState).fill(1)
for (let i = 0; i < parsedSequence.length - 1; i++) {
const previousState = parsedSequence[i]
const currentState = parsedSequence[i + 1]
for (let i = 0; i < nState; i++) {
likelyhoodofAllClass[i] = likelyhoodofAllClass[i] * this.observation2observationMatrix[previousState][currentState]
likelyhoodofAllClass[i] = likelyhoodofAllClass[i] * this.observation2stateMatrix[currentState][i]
}
}
const i = likelyhoodofAllClass.indexOf(Math.max(...likelyhoodofAllClass))
if (this.tabIndex === 4) {
this.detectedSpeechHMM = stateStrings[i]
} else {
this.detectedSpeechHMM = stateStrings[i] + ' ' + likelyhoodofAllClass[i].toString()
}
}
detectSpeechForMC () {
try {
const stateStrings = [...this.trainingSet.keys()]
let sequenceNum
if (this.tabIndex === 4) {
sequenceNum = this.parseSequence(this.userInputScenario.sequence).length
} else {
sequenceNum = parseInt(this.userInputStateSequence)
}
let resultMatrix: number[][] = this.state2stateMatrix
for (let index = 1; index < sequenceNum; index++) {
resultMatrix = this.multiplyMatrices(resultMatrix, this.state2stateMatrix)
}
const parsedSequence = this.parseSequence(this.userInputScenario.sequence)
this.detectedSpeech = parsedSequence.toString()
const nState = stateStrings.length
const likelyhoodofAllClass = Array(nState).fill(0)
for (let i = 0; i < nState; i++) {
for (let j = 0; j < nState; j++) {
likelyhoodofAllClass[i] += resultMatrix[j][i] * this.initProbList[j]
}
}
const i = likelyhoodofAllClass.indexOf(Math.max(...likelyhoodofAllClass))
if (this.tabIndex === 4) {
this.detectedSpeechMC = stateStrings[i]
} else {
this.detectedSpeech = this.blockList[i].speech + ' ' + likelyhoodofAllClass[i].toString()
}
} catch (e) {
console.log(e)
}
}
detectSpeechForRNN () {
if (this.userInputScenario.sequence === '') {
return
}
const parsedSequence = this.parseSequence(this.userInputScenario.sequence)
let result = ''
if (this.tabIndex === 2) {
result = this.netRnn.run(parsedSequence)
} else if (this.tabIndex === 3) {
result = this.netLstm.run(parsedSequence)
} else {
this.detectedSpeechRNN = this.netRnn.run(parsedSequence)
this.detectedSpeechLSTM = this.netLstm.run(parsedSequence)
}
this.detectedSpeech = result
}
multiplyMatrices (mat1: number[][], mat2: number[][]) {
if (this.matricesAreValid(mat1, mat2)) {
const rows = this.getMatrixRows(mat1)
const cols = this.getMatrixColumns(mat2)
return this.generateEmptyMatrix(rows, cols).map((resultRow, i) =>
resultRow.map((element: number, j: number) => {
const column = mat2.map(row => row[j])
const row = mat1[i]
return this.dotProduct(row, column)
})
)
} else {
return mat1
}
}
getMatrixColumns (a: number[][]) {
return a[0].length
}
getMatrixRows (a: number[][]) {
return a.length
}
matricesAreValid (a: number[][], b: number[][]) {
return this.getMatrixColumns(a) === this.getMatrixRows(b)
}
generateEmptyMatrix (rows: number, cols: number) {
return [...Array(rows)].fill(0).map(() => [...Array(cols)].fill(0))
}
dotProduct (a: number[], b: number[]) {
return a.map((value, i) => value * b[i]).reduce((acc, val) => acc + val, 0)
}
}
</script>
<style scoped>
.main-layout {
height: 100%;
width: 100%;
}
.scenario-item {
display: flex;
flex-direction: row;
}
.content-wrapper {
min-width: 1024px;
height: 100%;
}
</style>
import Vue from 'vue'
import App from './App.vue'
import BootstrapVue from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.min.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
Vue.config.productionTip = false
Vue.use(BootstrapVue)
new Vue({
render: h => h(App)
}).$mount('#app')
import Vue, { VNode } from 'vue'
declare global {
namespace JSX {
// tslint:disable no-empty-interface
interface Element extends VNode {}
// tslint:disable no-empty-interface
interface ElementClass extends Vue {}
interface IntrinsicElements {
[elem: string]: any;
}
}
}
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"baseUrl": ".",
"types": [
"webpack-env"
],
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
],
}