배희수

201216 발표영상 및 소스코드 업로드

1 +# gesture_test
2 +
3 +## Project setup
4 +```
5 +npm install
6 +```
7 +
8 +### Compiles and hot-reloads for development
9 +```
10 +npm run serve
11 +```
12 +
13 +### Compiles and minifies for production
14 +```
15 +npm run build
16 +```
17 +
18 +### Lints and fixes files
19 +```
20 +npm run lint
21 +```
22 +
23 +### Customize configuration
24 +See [Configuration Reference](https://cli.vuejs.org/config/).
1 +module.exports = {
2 + presets: [
3 + '@vue/cli-plugin-babel/preset'
4 + ]
5 +}
This diff could not be displayed because it is too large.
1 +{
2 + "name": "gesture_test",
3 + "version": "0.1.0",
4 + "private": true,
5 + "scripts": {
6 + "serve": "vue-cli-service serve",
7 + "build": "vue-cli-service build",
8 + "lint": "vue-cli-service lint"
9 + },
10 + "dependencies": {
11 + "bootstrap": "^4.5.0",
12 + "bootstrap-vue": "^2.15.0",
13 + "brain.js": "^2.0.0-beta.2",
14 + "chart.js": "^2.9.4",
15 + "core-js": "^3.6.5",
16 + "vue": "^2.6.11",
17 + "vue-chart.js": "^0.2.0",
18 + "vue-chartjs-typescript": "^3.3.3",
19 + "vue-class-component": "^7.2.3",
20 + "vue-graph": "^0.8.7",
21 + "vue-property-decorator": "^8.4.2",
22 + "vue-router": "^3.2.0",
23 + "vuex": "^3.4.0"
24 + },
25 + "devDependencies": {
26 + "@typescript-eslint/eslint-plugin": "^2.33.0",
27 + "@typescript-eslint/parser": "^2.33.0",
28 + "@vue/cli-plugin-babel": "~4.4.0",
29 + "@vue/cli-plugin-eslint": "~4.4.0",
30 + "@vue/cli-plugin-router": "~4.4.0",
31 + "@vue/cli-plugin-typescript": "~4.4.0",
32 + "@vue/cli-plugin-vuex": "~4.4.0",
33 + "@vue/cli-service": "~4.4.0",
34 + "@vue/eslint-config-standard": "^5.1.2",
35 + "@vue/eslint-config-typescript": "^5.0.2",
36 + "eslint": "^6.7.2",
37 + "eslint-plugin-import": "^2.20.2",
38 + "eslint-plugin-node": "^11.1.0",
39 + "eslint-plugin-promise": "^4.2.1",
40 + "eslint-plugin-standard": "^4.0.0",
41 + "eslint-plugin-vue": "^6.2.2",
42 + "stylus": "^0.54.7",
43 + "stylus-loader": "^3.0.2",
44 + "typescript": "~3.9.3",
45 + "vue-template-compiler": "^2.6.11"
46 + },
47 + "eslintConfig": {
48 + "root": true,
49 + "env": {
50 + "node": true
51 + },
52 + "extends": [
53 + "plugin:vue/essential",
54 + "@vue/standard",
55 + "@vue/typescript/recommended"
56 + ],
57 + "parserOptions": {
58 + "ecmaVersion": 2020
59 + },
60 + "rules": {}
61 + },
62 + "browserslist": [
63 + "> 1%",
64 + "last 2 versions",
65 + "not dead"
66 + ]
67 +}
No preview for this file type
1 +<!DOCTYPE html>
2 +<html lang="en">
3 + <head>
4 + <meta charset="utf-8">
5 + <meta http-equiv="X-UA-Compatible" content="IE=edge">
6 + <meta name="viewport" content="width=device-width,initial-scale=1.0">
7 + <link rel="icon" href="<%= BASE_URL %>favicon.ico">
8 + <title><%= htmlWebpackPlugin.options.title %></title>
9 + </head>
10 + <body>
11 + <noscript>
12 + <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
13 + </noscript>
14 + <div id="app"></div>
15 + <!-- built files will be auto injected -->
16 + </body>
17 +</html>
1 +<template>
2 + <div>
3 + <Speech/>
4 + </div>
5 +</template>
6 +
7 +<style lang="stylus">
8 +#app
9 + font-family Avenir, Helvetica, Arial, sans-serif
10 + -webkit-font-smoothing antialiased
11 + -moz-osx-font-smoothing grayscale
12 + text-align center
13 + color #2c3e50
14 + margin-top 60px
15 +</style>
16 +
17 +<script>
18 +import Speech from './components/Speech'
19 +
20 +export default {
21 + name: 'app',
22 + components: {
23 + Speech
24 + }
25 +}
26 +</script>
1 +import { Bar, mixins } from 'vue-chartjs-typescript'
2 +const { reactiveProp } = mixins
3 +
4 +export default {
5 + extends: Bar,
6 + props: ['options'],
7 + mixins: [reactiveProp],
8 + mounted () {
9 + this.renderChart(this.chartData, this.options)
10 + }
11 +}
1 +<template >
2 + <div class="main-layout">
3 + <b-navbar variant="dark" type="dark" :sticky="sticky">
4 + <b-navbar-brand href="#">발화 추천 알고리즘의 비교</b-navbar-brand>
5 + </b-navbar>
6 + <b-tabs
7 + class="pl-1 content-wrapper"
8 + vertical
9 + pills
10 + card
11 + v-model="tabIndex"
12 + @input="initializeCommonData"
13 + >
14 + <b-tab title="HMM" active>
15 + <b-row>
16 + <b-col>
17 + <div class="p-3">
18 + <h5>추천 발화</h5>
19 + <b-form inline>
20 + <b-form-input v-model="userInputState" placeholder="추천 발화" class="m-2" :state="userInputState.length > 0 ? true : false"></b-form-input>
21 + <b-button class="m-2" @click="generateTrainingData" >학습 데이터 생성</b-button>
22 + </b-form>
23 + <b-alert
24 + :show="dismissCountDown"
25 + dismissible
26 + variant="warning"
27 + @dismissed="dismissCountDown=0"
28 + @dismiss-count-down="countDownChanged"
29 + >
30 + 최소 1개의 시나리오를 입력해주세요.
31 + </b-alert>
32 + </div>
33 + <div class="p-3">
34 + <h5>시나리오</h5>
35 + <b-form>
36 + <template v-for="(scenario, index) of scenarioList">
37 + <b-form-group
38 + :label="'시나리오-' + (index + 1)"
39 + :key="'scenario-' + index"
40 + >
41 + <div class="scenario-item">
42 + <b-form-input v-model="scenario.sequence" placeholder="블록 ID를 쉼표로 구분하여 입력해주세요." class="m-2" :state="scenario.sequence.length > 0 ? true : false"></b-form-input>
43 + <b-button class="m-2" @click="deleteScenario(scenario)">-</b-button>
44 + </div>
45 + </b-form-group>
46 + </template>
47 + <b-button class="m-2" @click="addNewItem">+</b-button>
48 + </b-form>
49 + </div>
50 + <div class="p-3">
51 + <b-form inline>
52 + <b-form-input v-model="userInputScenario.sequence" placeholder="블록 ID를 쉼표로 구분하여 입력해주세요." class="m-2" :state="userInputScenario.sequence.length > 0 ? true : false"></b-form-input>
53 + <b-button class="m-2" @click="detectSpeech" >발화 추천</b-button>
54 + </b-form>
55 + <span class="m-2">추천 발화: {{detectedSpeech}}</span>
56 + </div>
57 + <div class="p-3">
58 + <h5>학습 데이터</h5>
59 + <b-table striped hover :items="displayTrainingSet"></b-table>
60 + </div>
61 + </b-col>
62 + <b-col>
63 + <div>
64 + <b-card
65 + title="HMM 학습 및 예측 시나리오"
66 + img-src="https://cdn.pixabay.com/photo/2017/01/23/08/13/microphone-2001751_1280.png"
67 + img-alt="Speech Recommendation"
68 + img-top
69 + style="max-width: 30rem;"
70 + tag="article"
71 + class="mb-2"
72 + >
73 + <b-card-text>1. 추천 발화 입력</b-card-text>
74 + <b-card-text>2. 입력한 추천 발화가 나올 수 있는 시나리오 입력("+" 버튼 클릭)</b-card-text>
75 + <b-card-text>3. "학습 데이터 생성" 버튼 클릭</b-card-text>
76 + <b-card-text>4. 추천 대상 발화의 수 만큼 (1 ~ 3)번 과정 반복</b-card-text>
77 + <b-card-text>5. 발화를 추천 받고자 하는 시나리오 입력</b-card-text>
78 + <b-card-text>6. "발화 추천" 버튼 클릭</b-card-text>
79 + <b-card-text>7. 추천 발화 확인</b-card-text>
80 + </b-card>
81 + </div>
82 + </b-col>
83 + </b-row>
84 + </b-tab>
85 + <b-tab title="MC">
86 + <b-row>
87 + <b-col>
88 + <div class="p-3">
89 + <h5>블록</h5>
90 + <b-alert
91 + :show="dismissCountDown"
92 + dismissible
93 + variant="warning"
94 + @dismissed="dismissCountDown=0"
95 + @dismiss-count-down="countDownChanged"
96 + >
97 + 10개의 발화를 입력해주세요.
98 + </b-alert>
99 + <b-form>
100 + <template v-for="(block, index) of blockList">
101 + <b-form-group
102 + :label="'ID-' + index"
103 + :key="'block-' + index"
104 + >
105 + <div class="scenario-item">
106 + <b-form-input v-model="block.speech" placeholder="발화를 입력해주세요." class="m-2" :state="block.speech.length > 0 ? true : false"></b-form-input>
107 + <b-button class="m-2" @click="deleteBlock(block)">-</b-button>
108 + </div>
109 + </b-form-group>
110 + </template>
111 + <b-button class="m-2" @click="addNewItem">+</b-button>
112 + <b-button class="m-2" @click="generateTrainingData" >학습 데이터 생성</b-button>
113 + </b-form>
114 + </div>
115 + <div class="p-3">
116 + <b-form>
117 + <b-form-input v-model="userInputStateSequence" placeholder="추천하고자 하는 발화가 몇 번째 발화인지 입력해주세요" class="m-2" :state="userInputStateSequence.length > 0 ? true : false"></b-form-input>
118 + <b-button class="m-2" @click="detectSpeech" >발화 추천</b-button>
119 + <span class="m-2">추천 발화: {{detectedSpeech}}</span>
120 + </b-form>
121 + </div>
122 + <div class="p-3">
123 + <h5>학습 데이터</h5>
124 + <b-table striped hover :items="displayTrainingSet"></b-table>
125 + </div>
126 + </b-col>
127 + <b-col>
128 + <div>
129 + <b-card
130 + title="MC 학습 및 예측 시나리오"
131 + img-src="https://cdn.pixabay.com/photo/2017/01/23/08/13/microphone-2001751_1280.png"
132 + img-alt="Speech Recommendation"
133 + img-top
134 + style="max-width: 30rem;"
135 + tag="article"
136 + class="mb-2"
137 + >
138 + <b-card-text>1. 시나리오 상 포함되는 블록 정보(ID) 입력("+" 버튼 클릭)</b-card-text>
139 + <b-card-text>2. "학습 데이터 생성" 버튼 클릭</b-card-text>
140 + <b-card-text>3. 추천 발화가 필요한 시나리오 상 순서 입력</b-card-text>
141 + <b-card-text>4. "발화 추천" 버튼 클릭</b-card-text>
142 + <b-card-text>5. 추천 발화 확인</b-card-text>
143 + </b-card>
144 + </div>
145 + </b-col>
146 + </b-row>
147 + </b-tab>
148 + <b-tab title="RNN">
149 + <b-row>
150 + <b-col>
151 + <div class="p-3">
152 + <h5>추천 발화</h5>
153 + <b-form inline>
154 + <b-form-input v-model="userInputState" placeholder="추천 발화" class="m-2" :state="userInputState.length > 0 ? true : false"></b-form-input>
155 + <b-button class="m-2" @click="generateTrainingData" >학습 데이터 생성</b-button>
156 + </b-form>
157 + <b-alert
158 + :show="dismissCountDown"
159 + dismissible
160 + variant="warning"
161 + @dismissed="dismissCountDown=0"
162 + @dismiss-count-down="countDownChanged"
163 + >
164 + 최소 1개의 시나리오를 입력해주세요.
165 + </b-alert>
166 + </div>
167 + <div class="p-3">
168 + <h5>시나리오</h5>
169 + <b-form>
170 + <template v-for="(scenario, index) of scenarioList">
171 + <b-form-group
172 + :label="'시나리오-' + (index + 1)"
173 + :key="'scenario-' + index"
174 + >
175 + <div class="scenario-item">
176 + <b-form-input v-model="scenario.sequence" placeholder="블록 ID를 쉼표로 구분하여 입력해주세요." class="m-2" :state="scenario.sequence.length > 0 ? true : false"></b-form-input>
177 + <b-button class="m-2" @click="deleteScenario(scenario)">-</b-button>
178 + </div>
179 + </b-form-group>
180 + </template>
181 + <b-button class="m-2" @click="addNewItem">+</b-button>
182 + </b-form>
183 + </div>
184 + <div class="p-3">
185 + <b-form inline>
186 + <b-form-input v-model="userInputScenario.sequence" placeholder="블록 ID를 쉼표로 구분하여 입력해주세요." class="m-2" :state="userInputScenario.sequence.length > 0 ? true : false"></b-form-input>
187 + <b-button class="m-2" @click="detectSpeech" >발화 추천</b-button>
188 + </b-form>
189 + <span class="m-2">추천 발화: {{detectedSpeech}}</span>
190 + </div>
191 + <div class="p-3">
192 + <h5>학습 데이터</h5>
193 + <b-table striped hover :items="displayTrainingSet"></b-table>
194 + </div>
195 + </b-col>
196 + <b-col>
197 + <div>
198 + <b-card
199 + title="RNN 학습 및 예측 시나리오"
200 + img-src="https://cdn.pixabay.com/photo/2017/01/23/08/13/microphone-2001751_1280.png"
201 + img-alt="Speech Recommendation"
202 + img-top
203 + style="max-width: 30rem;"
204 + tag="article"
205 + class="mb-2"
206 + >
207 + <b-card-text>1. 추천 발화 입력</b-card-text>
208 + <b-card-text>2. 입력한 추천 발화가 나올 수 있는 시나리오 입력("+" 버튼 클릭)</b-card-text>
209 + <b-card-text>3. "학습 데이터 생성" 버튼 클릭</b-card-text>
210 + <b-card-text>4. 추천 대상 발화의 수 만큼 (1 ~ 3)번 과정 반복</b-card-text>
211 + <b-card-text>5. 발화를 추천 받고자 하는 시나리오 입력</b-card-text>
212 + <b-card-text>6. "발화 추천" 버튼 클릭</b-card-text>
213 + <b-card-text>7. 추천 발화 확인</b-card-text>
214 + </b-card>
215 + </div>
216 + </b-col>
217 + </b-row>
218 + </b-tab>
219 + <b-tab title="LSTM">
220 + <b-row>
221 + <b-col>
222 + <div class="p-3">
223 + <h5>추천 발화</h5>
224 + <b-form inline>
225 + <b-form-input v-model="userInputState" placeholder="추천 발화" class="m-2" :state="userInputState.length > 0 ? true : false"></b-form-input>
226 + <b-button class="m-2" @click="generateTrainingData" >학습 데이터 생성</b-button>
227 + </b-form>
228 + <b-alert
229 + :show="dismissCountDown"
230 + dismissible
231 + variant="warning"
232 + @dismissed="dismissCountDown=0"
233 + @dismiss-count-down="countDownChanged"
234 + >
235 + 최소 1개의 시나리오를 입력해주세요.
236 + </b-alert>
237 + </div>
238 + <div class="p-3">
239 + <h5>시나리오</h5>
240 + <b-form>
241 + <template v-for="(scenario, index) of scenarioList">
242 + <b-form-group
243 + :label="'시나리오-' + (index + 1)"
244 + :key="'scenario-' + index"
245 + >
246 + <div class="scenario-item">
247 + <b-form-input v-model="scenario.sequence" placeholder="블록 ID를 쉼표로 구분하여 입력해주세요." class="m-2" :state="scenario.sequence.length > 0 ? true : false"></b-form-input>
248 + <b-button class="m-2" @click="deleteScenario(scenario)">-</b-button>
249 + </div>
250 + </b-form-group>
251 + </template>
252 + <b-button class="m-2" @click="addNewItem">+</b-button>
253 + </b-form>
254 + </div>
255 + <div class="p-3">
256 + <b-form inline>
257 + <b-form-input v-model="userInputScenario.sequence" placeholder="블록 ID를 쉼표로 구분하여 입력해주세요." class="m-2" :state="userInputScenario.sequence.length > 0 ? true : false"></b-form-input>
258 + <b-button class="m-2" @click="detectSpeech" >발화 추천</b-button>
259 + </b-form>
260 + <span class="m-2">추천 발화: {{detectedSpeech}}</span>
261 + </div>
262 + <div class="p-3">
263 + <h5>학습 데이터</h5>
264 + <b-table striped hover :items="displayTrainingSet"></b-table>
265 + </div>
266 + </b-col>
267 + <b-col>
268 + <div>
269 + <b-card
270 + title="LSTM 학습 및 예측 시나리오"
271 + img-src="https://cdn.pixabay.com/photo/2017/01/23/08/13/microphone-2001751_1280.png"
272 + img-alt="Speech Recommendation"
273 + img-top
274 + style="max-width: 30rem;"
275 + tag="article"
276 + class="mb-2"
277 + >
278 + <b-card-text>1. 추천 발화 입력</b-card-text>
279 + <b-card-text>2. 입력한 추천 발화가 나올 수 있는 시나리오 입력("+" 버튼 클릭)</b-card-text>
280 + <b-card-text>3. "학습 데이터 생성" 버튼 클릭</b-card-text>
281 + <b-card-text>4. 추천 대상 발화의 수 만큼 (1 ~ 3)번 과정 반복</b-card-text>
282 + <b-card-text>5. 발화를 추천 받고자 하는 시나리오 입력</b-card-text>
283 + <b-card-text>6. "발화 추천" 버튼 클릭</b-card-text>
284 + <b-card-text>7. 추천 발화 확인</b-card-text>
285 + </b-card>
286 + </div>
287 + </b-col>
288 + </b-row>
289 + </b-tab>
290 + <b-tab title="통합">
291 + <b-row>
292 + <b-col>
293 + <div class="p-3">
294 + <h5>추천 발화</h5>
295 + <b-form inline>
296 + <b-form-input v-model="userInputState" placeholder="추천 발화" class="m-2" :state="userInputState.length > 0 ? true : false"></b-form-input>
297 + <b-button class="m-2" @click="generateTrainingData" >학습 데이터 생성</b-button>
298 + </b-form>
299 + <b-alert
300 + :show="dismissCountDown"
301 + dismissible
302 + variant="warning"
303 + @dismissed="dismissCountDown=0"
304 + @dismiss-count-down="countDownChanged"
305 + >
306 + 최소 1개의 시나리오를 입력해주세요.
307 + </b-alert>
308 + </div>
309 + <div class="p-3">
310 + <h5>시나리오</h5>
311 + <b-form>
312 + <template v-for="(scenario, index) of scenarioList">
313 + <b-form-group
314 + :label="'시나리오-' + (index + 1)"
315 + :key="'scenario-' + index"
316 + >
317 + <div class="scenario-item">
318 + <b-form-input v-model="scenario.sequence" placeholder="블록 ID를 쉼표로 구분하여 입력해주세요." class="m-2" :state="scenario.sequence.length > 0 ? true : false"></b-form-input>
319 + <b-button class="m-2" @click="deleteScenario(scenario)">-</b-button>
320 + </div>
321 + </b-form-group>
322 + </template>
323 + <b-button class="m-2" @click="addNewItem">+</b-button>
324 + </b-form>
325 + </div>
326 + <div class="p-3">
327 + <b-form inline>
328 + <b-form-input v-model="userInputScenario.sequence" placeholder="블록 ID를 쉼표로 구분하여 입력해주세요." class="m-2" :state="userInputScenario.sequence.length > 0 ? true : false"></b-form-input>
329 + <b-button class="m-2" @click="detectSpeech" >발화 추천</b-button>
330 + </b-form>
331 + <p class="m-2">추천 발화(HMM): {{detectedSpeechHMM}}</p>
332 + <p class="m-2">추천 발화(MC): {{detectedSpeechMC}}</p>
333 + <p class="m-2">추천 발화(RNN): {{detectedSpeechRNN}}</p>
334 + <p class="m-2">추천 발화(LSTM): {{detectedSpeechLSTM}}</p>
335 + </div>
336 + <div class="p-3">
337 + <h5>학습 데이터</h5>
338 + <b-button class="m-2" @click="onClickShowTrainingData">{{ showTrainingData ? '숨기기' : '보이기' }}</b-button>
339 + <b-table v-if="showTrainingData" striped hover :items="displayTrainingSet"></b-table>
340 + </div>
341 + </b-col>
342 + <b-col>
343 + <div>
344 + <b-card
345 + title="통합 학습 및 예측 시나리오"
346 + img-src="https://cdn.pixabay.com/photo/2017/01/23/08/13/microphone-2001751_1280.png"
347 + img-alt="Speech Recommendation"
348 + img-top
349 + style="max-width: 30rem;"
350 + tag="article"
351 + class="mb-2"
352 + >
353 + <b-card-text>1. 추천 발화 입력</b-card-text>
354 + <b-card-text>2. 입력한 추천 발화가 나올 수 있는 시나리오 입력("+" 버튼 클릭)</b-card-text>
355 + <b-card-text>3. "학습 데이터 생성" 버튼 클릭</b-card-text>
356 + <b-card-text>4. 추천 대상 발화의 수 만큼 (1 ~ 3)번 과정 반복</b-card-text>
357 + <b-card-text>5. 발화를 추천 받고자 하는 시나리오 입력</b-card-text>
358 + <b-card-text>6. "발화 추천" 버튼 클릭</b-card-text>
359 + <b-card-text>7. 추천 발화 확인</b-card-text>
360 + </b-card>
361 + </div>
362 + </b-col>
363 + </b-row>
364 + <b-row>
365 + <b-col>
366 + <div class="p-3">
367 + <h5>모델별 결과 확인</h5>
368 + <b-button class="m-2" @click="createGraph">그래프 생성</b-button>
369 + <div class="container">
370 + <bar-chart
371 + v-if="showGraph"
372 + :chart-data="chartData"
373 + :options="options"
374 + />
375 + </div>
376 + </div>
377 + </b-col>
378 + </b-row>
379 + </b-tab>
380 + </b-tabs>
381 + </div>
382 +</template>
383 +
384 +<script lang="ts">
385 +import 'bootstrap/dist/css/bootstrap.css'
386 +import 'bootstrap-vue/dist/bootstrap-vue.css'
387 +
388 +import Vue from 'vue'
389 +import { Component, Prop } from 'vue-property-decorator'
390 +
391 +import * as brain from 'brain.js/src'
392 +
393 +// @ts-ignore
394 +import BarChart from '../BarChart.js'
395 +
396 +class Scenario {
397 + sequence: string;
398 +
399 + constructor (sequence: string) {
400 + this.sequence = sequence
401 + }
402 +}
403 +
404 +class Block {
405 + speech: string;
406 +
407 + constructor (speech: string) {
408 + this.speech = speech
409 + }
410 +}
411 +
412 +@Component({
413 + components: {
414 + BarChart
415 + }
416 +})
417 +export default class Speech extends Vue {
418 + private sticky = true
419 + private dismissCountDown = 0
420 + private dismissSecs = 2
421 + private tabIndex = 1
422 + private showTrainingData = false
423 +
424 + // Graph
425 + private showGraph = false
426 + private chartData = {
427 + labels: ['HMM', 'RNN', 'LSTM'],
428 + datasets: [] as any[]
429 + }
430 +
431 + private options = {
432 + responsive: true,
433 + maintainAspectRatio: false
434 + }
435 +
436 + // 공통
437 + private displayTrainingSet: any[] = []
438 + private detectedSpeech = ''
439 + private singleTrainingData: any[] = []
440 + private userInputState = ''
441 + private scenarioList: Scenario[] = []
442 + private userInputScenario: Scenario = new Scenario('')
443 + private trainingSet: Map<string, any[]> = new Map()
444 +
445 + // HMM
446 + private observation2stateMatrix!: any[]
447 + private observation2observationMatrix!: any[]
448 +
449 + // MC
450 + private blockList: Block[] = []
451 + private initProbList: number[] = []
452 + private state2stateMatrix!: number[][]
453 + private userInputStateSequence = ''
454 +
455 + // RNN
456 + private netRnn = new brain.recurrent.RNN()
457 +
458 + // LSTM
459 + private netLstm = new brain.recurrent.LSTM()
460 +
461 + // ALL
462 + private detectedSpeechHMM = ''
463 + private detectedSpeechMC = ''
464 + private detectedSpeechRNN = ''
465 + private detectedSpeechLSTM = ''
466 +
467 + onClickShowTrainingData () {
468 + this.showTrainingData = !this.showTrainingData
469 + }
470 +
471 + createGraph () {
472 + const stateStrings = [...this.trainingSet.keys()]
473 + const chartDataEntry = {
474 + label: 'accuracy',
475 + data: [] as number[]
476 + }
477 + let totalNum = 0
478 + let hmmCount = 0
479 + let rnnCount = 0
480 + let lstmCount = 0
481 +
482 + for (let index = 0; index < stateStrings.length; index++) {
483 + const parsedSequenceList = this.trainingSet.get(stateStrings[index]) as any[]
484 +
485 + for (let secondIndex = 0; secondIndex < parsedSequenceList.length; secondIndex++) {
486 + const parsedSequence = parsedSequenceList[secondIndex] as number[]
487 + const parsedSequenceStr = parsedSequence.join()
488 +
489 + this.userInputScenario.sequence = parsedSequenceStr
490 +
491 + this.detectSpeechForHMM()
492 + if (this.detectedSpeechHMM === stateStrings[index]) {
493 + hmmCount++
494 + }
495 +
496 + this.detectSpeechForRNN()
497 + if (this.detectedSpeechRNN === stateStrings[index]) {
498 + rnnCount++
499 + }
500 + if (this.detectedSpeechLSTM === stateStrings[index]) {
501 + lstmCount++
502 + }
503 +
504 + totalNum++
505 + }
506 + }
507 +
508 + this.$set(chartDataEntry, 'data', [(hmmCount / totalNum) * 100, (rnnCount / totalNum) * 100, (lstmCount / totalNum) * 100])
509 + this.$set(this.chartData, 'datasets', [chartDataEntry])
510 +
511 + this.showGraph = true
512 + }
513 +
514 + initializeCommonData () {
515 + this.displayTrainingSet = []
516 + this.singleTrainingData = []
517 + this.userInputState = ''
518 + this.detectedSpeech = ''
519 + this.userInputStateSequence = ''
520 + this.trainingSet = new Map()
521 +
522 + if (this.tabIndex === 4) {
523 + this.observation2stateMatrix = []
524 + this.observation2observationMatrix = []
525 + this.state2stateMatrix = []
526 + this.initProbList = []
527 + this.blockList = []
528 +
529 + this.netRnn = new brain.recurrent.RNN()
530 + this.netLstm = new brain.recurrent.LSTM()
531 + }
532 + }
533 +
534 + countDownChanged (dismissCountDown: number) {
535 + this.dismissCountDown = dismissCountDown
536 + }
537 +
538 + showAlert () {
539 + this.dismissCountDown = this.dismissSecs
540 + }
541 +
542 + clearHMM () {
543 + this.singleTrainingData = []
544 + this.displayTrainingSet = []
545 + }
546 +
547 + clearMC () {
548 + this.singleTrainingData = []
549 + this.state2stateMatrix = []
550 + this.displayTrainingSet = []
551 + }
552 +
553 + clearRNN () {
554 + this.singleTrainingData = []
555 + this.displayTrainingSet = []
556 + }
557 +
558 + clearAll () {
559 + this.singleTrainingData = []
560 + this.displayTrainingSet = []
561 + }
562 +
563 + addNewItem () {
564 + if (this.tabIndex === 1) {
565 + const block: Block = new Block('')
566 +
567 + this.blockList.push(block)
568 + } else {
569 + const scenario: Scenario = new Scenario('')
570 +
571 + this.scenarioList.push(scenario)
572 + }
573 + }
574 +
575 + deleteScenario (input: Scenario) {
576 + const index = this.scenarioList.findIndex(scenario => scenario.sequence === input.sequence)
577 +
578 + if (index !== -1) {
579 + this.scenarioList.splice(index, 1)
580 + }
581 + }
582 +
583 + deleteBlock (input: Block) {
584 + const index = this.blockList.findIndex(block => block.speech === input.speech)
585 +
586 + if (index !== -1) {
587 + this.blockList.splice(index, 1)
588 + }
589 + }
590 +
591 + generateTrainingDataForHMM () {
592 + // 시나리오 입력 여부 체크
593 + if (this.scenarioList.length === 0) {
594 + this.showAlert()
595 +
596 + return
597 + }
598 +
599 + // 기존 학습 데이터 및 출력 데이터 클리어
600 + this.clearHMM()
601 +
602 + // 학습 데이터 생성
603 + this.generateRandomSequenceForHMM()
604 +
605 + // 생성된 학습 데이터를 출력 데이터로 할당
606 + this.displayTrainingSet = [...this.singleTrainingData]
607 +
608 + // 생성된 학습 데이터를 기반으로 학습 시작
609 + this.trainingForHMM()
610 + }
611 +
612 + generateTrainingDataForMC () {
613 + // 블록 입력 여부 체크
614 + if (this.blockList.length !== 10) {
615 + this.showAlert()
616 +
617 + return
618 + }
619 +
620 + // 기존 학습 데이터 및 출력 데이터 클리어
621 + this.clearMC()
622 +
623 + // 학습 데이터 생성 및 초기 확률 계산
624 + this.generateRandomSequenceForMC()
625 +
626 + // 생성된 학습 데이터를 출력 데이터로 할당
627 + this.displayTrainingSet = [...this.singleTrainingData]
628 +
629 + // 생성된 학습 데이터를 기반으로 학습 시작
630 + this.trainingForMC()
631 + }
632 +
633 + generateTrainingDataForRNN () {
634 + // 시나리오 입력 여부 체크
635 + if (this.scenarioList.length === 0) {
636 + this.showAlert()
637 +
638 + return
639 + }
640 +
641 + // 기존 학습 데이터 및 출력 데이터 클리어
642 + this.clearRNN()
643 +
644 + // 학습 데이터 생성
645 + this.setTrainingDataForRNN()
646 +
647 + // 생성된 학습 데이터를 출력 데이터로 할당
648 + this.displayTrainingSet = [...this.singleTrainingData]
649 +
650 + // 생성된 학습 데이터를 기반으로 학습 시작
651 + this.trainingForRNN()
652 + }
653 +
654 + generateTrainingDataForAll () {
655 + // 시나리오 입력 여부 체크
656 + if (this.scenarioList.length === 0) {
657 + this.showAlert()
658 +
659 + return
660 + }
661 +
662 + // 기존 학습 데이터 및 출력 데이터 클리어
663 + this.clearAll()
664 +
665 + // 학습 데이터 생성
666 + this.setTrainingDataForAll()
667 +
668 + // 생성된 학습 데이터를 출력 데이터로 할당
669 + this.displayTrainingSet = [...this.singleTrainingData]
670 +
671 + this.trainingForHMM()
672 + this.trainingForMC()
673 + this.trainingForRNN()
674 + }
675 +
676 + generateTrainingData () {
677 + if (this.tabIndex === 0) {
678 + this.generateTrainingDataForHMM()
679 + } else if (this.tabIndex === 1) {
680 + this.generateTrainingDataForMC()
681 + } else if (this.tabIndex === 2 || this.tabIndex === 3) {
682 + this.generateTrainingDataForRNN()
683 + } else {
684 + this.generateTrainingDataForAll()
685 + }
686 + }
687 +
688 + parseSequence (sequence: string) {
689 + const parsedSequence: string[] = sequence.split(',')
690 + const resultSequence: number[] = []
691 +
692 + for (let index = 0; index < parsedSequence.length; index++) {
693 + resultSequence.push(parseInt(parsedSequence[index]))
694 + }
695 +
696 + return resultSequence
697 + }
698 +
699 + // 100개의 랜덤 학습 데이터 생성
700 + generateRandomSequenceForHMM () {
701 + // 학습 셋에 STATE 추가
702 + this.trainingSet.set(this.userInputState, [])
703 +
704 + const parsedSequenceList: any[] = []
705 + for (let index = 0; index < this.scenarioList.length; index++) {
706 + const parsedSequence = this.parseSequence(this.scenarioList[index].sequence)
707 +
708 + parsedSequenceList.push(parsedSequence)
709 + }
710 +
711 + const iter = this.trainingSet.get(this.userInputState)
712 + if (iter === null || iter === undefined) {
713 + return
714 + }
715 +
716 + for (let index = 0; index < 100; index++) {
717 + const randomIndex = Math.floor(Math.random() * parsedSequenceList.length)
718 +
719 + this.singleTrainingData.push(parsedSequenceList[randomIndex])
720 + iter.push(parsedSequenceList[randomIndex])
721 + }
722 + }
723 +
724 + // 100개의 랜덤 학습 데이터 생성
725 + generateRandomSequenceForMC () {
726 + for (let index = 0; index < 10; index++) {
727 + this.initProbList[index] = 0
728 + }
729 +
730 + for (let index = 0; index < 100; index++) {
731 + const generatedSequence = []
732 + for (let secondIndex = 0; secondIndex < 5; secondIndex++) {
733 + const randomIndex = Math.floor(Math.random() * 10)
734 +
735 + this.initProbList[randomIndex]++
736 + generatedSequence.push(randomIndex)
737 + }
738 +
739 + this.singleTrainingData.push(generatedSequence)
740 + }
741 +
742 + for (let index = 0; index < 10; index++) {
743 + this.initProbList[index] /= 500
744 + }
745 + }
746 +
747 + setTrainingDataForAll () {
748 + // 학습 셋에 STATE 추가
749 + this.trainingSet.set(this.userInputState, [])
750 +
751 + // MC 초기 확률 리스트 초기화
752 + for (let index = 0; index < 10; index++) {
753 + this.initProbList[index] = 0
754 + }
755 +
756 + const parsedSequenceList: any[] = []
757 + for (let index = 0; index < this.scenarioList.length; index++) {
758 + const parsedSequence = this.parseSequence(this.scenarioList[index].sequence)
759 +
760 + parsedSequenceList.push(parsedSequence)
761 + }
762 +
763 + const iter = this.trainingSet.get(this.userInputState)
764 + if (iter === null || iter === undefined) {
765 + return
766 + }
767 +
768 + for (let index = 0; index < 100; index++) {
769 + const randomIndex = Math.floor(Math.random() * parsedSequenceList.length)
770 +
771 + this.singleTrainingData.push(parsedSequenceList[randomIndex])
772 + for (let secondIndex = 0; secondIndex < 5; secondIndex++) {
773 + this.initProbList[parsedSequenceList[randomIndex][secondIndex]]++
774 + }
775 +
776 + iter.push(parsedSequenceList[randomIndex])
777 + }
778 +
779 + for (let index = 0; index < 10; index++) {
780 + this.initProbList[index] /= 500
781 + }
782 + }
783 +
784 + setTrainingDataForRNN () {
785 + // 학습 셋에 STATE 추가
786 + this.trainingSet.set(this.userInputState, [])
787 +
788 + const parsedSequenceList: any[] = []
789 + for (let index = 0; index < this.scenarioList.length; index++) {
790 + const parsedSequence = this.parseSequence(this.scenarioList[index].sequence)
791 +
792 + parsedSequenceList.push(parsedSequence)
793 + }
794 +
795 + const iter = this.trainingSet.get(this.userInputState)
796 + if (iter === null || iter === undefined) {
797 + return
798 + }
799 +
800 + for (let index = 0; index < parsedSequenceList.length; index++) {
801 + const sequence = parsedSequenceList[index]
802 +
803 + this.singleTrainingData.push(sequence)
804 + iter.push(sequence)
805 + }
806 + }
807 +
808 + trainingForHMM () {
809 + const stateStrings = [...this.trainingSet.keys()]
810 + const nState = stateStrings.length
811 + const nObservation = 10 // 블록 ID (임시로 숫자로 가정... 0 ~ 9)
812 + const observation2stateMatrix = Array(nObservation).fill(null).map(() => Array(nState).fill(0))
813 + const observation2observationMatrix = Array(nObservation).fill(null).map(() => Array(nObservation).fill(0))
814 +
815 + let observationCount = 0
816 +
817 + for (let i = 0; i < nState; i++) {
818 + const key = stateStrings[i]
819 + const observations: any[] = this.trainingSet.get(key)!
820 + for (let j = 0; j < observations.length; j++) {
821 + const observation: number[] = observations[j]
822 + for (let k = 0; k < observation.length - 1; k++) {
823 + observation2observationMatrix[observation[k]][observation[k + 1]]++
824 + observation2stateMatrix[observation[k]][i]++
825 + observationCount++
826 + }
827 + observation2stateMatrix[observation[observation.length - 1]][i]++
828 + }
829 + }
830 +
831 + for (let i = 0; i < nState; i++) {
832 + const key: string = stateStrings[i]
833 + const obervationTrainNum: number = this.trainingSet.get(key)!.length
834 +
835 + for (let j = 0; j < 10; j++) {
836 + observation2stateMatrix[j][i] = observation2stateMatrix[j][i] / obervationTrainNum
837 + }
838 + }
839 +
840 + for (let i = 0; i < 10; i++) {
841 + for (let j = 0; j < 10; j++) {
842 + observation2observationMatrix[i][j] = observation2observationMatrix[i][j] / observationCount
843 + }
844 + }
845 +
846 + this.observation2stateMatrix = observation2stateMatrix
847 + this.observation2observationMatrix = observation2observationMatrix
848 +
849 + console.log(JSON.stringify(observation2stateMatrix).replace(/([[)(.*)(]])/g, '[\n [$2]\n]').replace(/],/g, '],\n '))
850 + console.log(JSON.stringify(observation2observationMatrix).replace(/([[)(.*)(]])/g, '[\n [$2]\n]').replace(/],/g, '],\n '))
851 + }
852 +
853 + trainingForMC () {
854 + const nState = 10
855 + const state2stateMatrix = Array(nState).fill(null).map(() => Array(nState).fill(0))
856 +
857 + let stateCount = 0
858 + for (let i = 0; i < this.singleTrainingData.length; i++) {
859 + const blockSequence: number[] = this.singleTrainingData[i]
860 + for (let j = 0; j < blockSequence.length - 1; j++) {
861 + state2stateMatrix[blockSequence[j]][blockSequence[j + 1]]++
862 + stateCount++
863 + }
864 + }
865 +
866 + for (let i = 0; i < 10; i++) {
867 + for (let j = 0; j < 10; j++) {
868 + state2stateMatrix[i][j] = state2stateMatrix[i][j] / stateCount
869 +
870 + if (state2stateMatrix[i][j] === 0) {
871 + state2stateMatrix[i][j] = 0.0001
872 + }
873 + }
874 + }
875 +
876 + this.state2stateMatrix = state2stateMatrix
877 +
878 + console.log(JSON.stringify(state2stateMatrix).replace(/([[)(.*)(]])/g, '[\n [$2]\n]').replace(/],/g, '],\n '))
879 + }
880 +
881 + trainingForRNN () {
882 + const stateString = [...this.trainingSet.keys()]
883 + const trainDataList: object[] = []
884 +
885 + for (let i = 0; i < stateString.length; i++) {
886 + const key = stateString[i]
887 + const iter = this.trainingSet.get(key) as any[]
888 +
889 + for (let j = 0; j < iter.length; j++) {
890 + const trainEntry = {
891 + input: [],
892 + output: ''
893 + }
894 +
895 + trainEntry.input = iter[j]
896 + trainEntry.output = key
897 +
898 + trainDataList.push(trainEntry)
899 + }
900 + }
901 +
902 + if (this.tabIndex === 2) {
903 + this.netRnn.train(trainDataList, {
904 + iterations: 30,
905 + log: (details) => console.log(details),
906 + errorThresh: 0.011
907 + })
908 + } else if (this.tabIndex === 3) {
909 + this.netLstm.train(trainDataList, {
910 + iterations: 30,
911 + log: (details) => console.log(details),
912 + errorThresh: 0.011
913 + })
914 + } else {
915 + this.netRnn = new brain.recurrent.RNN()
916 + this.netLstm = new brain.recurrent.LSTM()
917 +
918 + this.netRnn.train(trainDataList, {
919 + iterations: 30,
920 + log: (details) => console.log('RNN: ' + details),
921 + errorThresh: 0.0001
922 + })
923 +
924 + this.netLstm.train(trainDataList, {
925 + iterations: 30,
926 + log: (details) => console.log('LSTN: ' + details),
927 + errorThresh: 0.0001
928 + })
929 + }
930 + }
931 +
932 + detectSpeech () {
933 + if (this.tabIndex === 0) {
934 + this.detectSpeechForHMM()
935 + } else if (this.tabIndex === 1) {
936 + this.detectSpeechForMC()
937 + } else if (this.tabIndex === 2 || this.tabIndex === 3) {
938 + this.detectSpeechForRNN()
939 + } else {
940 + this.detectSpeechForHMM()
941 + this.detectSpeechForMC()
942 + this.detectSpeechForRNN()
943 + }
944 + }
945 +
946 + detectSpeechForHMM () {
947 + const parsedSequence = this.parseSequence(this.userInputScenario.sequence)
948 + this.detectedSpeech = parsedSequence.toString()
949 +
950 + const stateStrings = [...this.trainingSet.keys()]
951 + const nState = stateStrings.length
952 + const likelyhoodofAllClass = Array(nState).fill(1)
953 +
954 + for (let i = 0; i < parsedSequence.length - 1; i++) {
955 + const previousState = parsedSequence[i]
956 + const currentState = parsedSequence[i + 1]
957 +
958 + for (let i = 0; i < nState; i++) {
959 + likelyhoodofAllClass[i] = likelyhoodofAllClass[i] * this.observation2observationMatrix[previousState][currentState]
960 + likelyhoodofAllClass[i] = likelyhoodofAllClass[i] * this.observation2stateMatrix[currentState][i]
961 + }
962 + }
963 +
964 + const i = likelyhoodofAllClass.indexOf(Math.max(...likelyhoodofAllClass))
965 + if (this.tabIndex === 4) {
966 + this.detectedSpeechHMM = stateStrings[i]
967 + } else {
968 + this.detectedSpeechHMM = stateStrings[i] + ' ' + likelyhoodofAllClass[i].toString()
969 + }
970 + }
971 +
972 + detectSpeechForMC () {
973 + try {
974 + const stateStrings = [...this.trainingSet.keys()]
975 +
976 + let sequenceNum
977 + if (this.tabIndex === 4) {
978 + sequenceNum = this.parseSequence(this.userInputScenario.sequence).length
979 + } else {
980 + sequenceNum = parseInt(this.userInputStateSequence)
981 + }
982 +
983 + let resultMatrix: number[][] = this.state2stateMatrix
984 + for (let index = 1; index < sequenceNum; index++) {
985 + resultMatrix = this.multiplyMatrices(resultMatrix, this.state2stateMatrix)
986 + }
987 +
988 + const parsedSequence = this.parseSequence(this.userInputScenario.sequence)
989 + this.detectedSpeech = parsedSequence.toString()
990 +
991 + const nState = stateStrings.length
992 + const likelyhoodofAllClass = Array(nState).fill(0)
993 +
994 + for (let i = 0; i < nState; i++) {
995 + for (let j = 0; j < nState; j++) {
996 + likelyhoodofAllClass[i] += resultMatrix[j][i] * this.initProbList[j]
997 + }
998 + }
999 +
1000 + const i = likelyhoodofAllClass.indexOf(Math.max(...likelyhoodofAllClass))
1001 + if (this.tabIndex === 4) {
1002 + this.detectedSpeechMC = stateStrings[i]
1003 + } else {
1004 + this.detectedSpeech = this.blockList[i].speech + ' ' + likelyhoodofAllClass[i].toString()
1005 + }
1006 + } catch (e) {
1007 + console.log(e)
1008 + }
1009 + }
1010 +
1011 + detectSpeechForRNN () {
1012 + if (this.userInputScenario.sequence === '') {
1013 + return
1014 + }
1015 +
1016 + const parsedSequence = this.parseSequence(this.userInputScenario.sequence)
1017 + let result = ''
1018 + if (this.tabIndex === 2) {
1019 + result = this.netRnn.run(parsedSequence)
1020 + } else if (this.tabIndex === 3) {
1021 + result = this.netLstm.run(parsedSequence)
1022 + } else {
1023 + this.detectedSpeechRNN = this.netRnn.run(parsedSequence)
1024 + this.detectedSpeechLSTM = this.netLstm.run(parsedSequence)
1025 + }
1026 +
1027 + this.detectedSpeech = result
1028 + }
1029 +
1030 + multiplyMatrices (mat1: number[][], mat2: number[][]) {
1031 + if (this.matricesAreValid(mat1, mat2)) {
1032 + const rows = this.getMatrixRows(mat1)
1033 + const cols = this.getMatrixColumns(mat2)
1034 +
1035 + return this.generateEmptyMatrix(rows, cols).map((resultRow, i) =>
1036 + resultRow.map((element: number, j: number) => {
1037 + const column = mat2.map(row => row[j])
1038 + const row = mat1[i]
1039 +
1040 + return this.dotProduct(row, column)
1041 + })
1042 + )
1043 + } else {
1044 + return mat1
1045 + }
1046 + }
1047 +
1048 + getMatrixColumns (a: number[][]) {
1049 + return a[0].length
1050 + }
1051 +
1052 + getMatrixRows (a: number[][]) {
1053 + return a.length
1054 + }
1055 +
1056 + matricesAreValid (a: number[][], b: number[][]) {
1057 + return this.getMatrixColumns(a) === this.getMatrixRows(b)
1058 + }
1059 +
1060 + generateEmptyMatrix (rows: number, cols: number) {
1061 + return [...Array(rows)].fill(0).map(() => [...Array(cols)].fill(0))
1062 + }
1063 +
1064 + dotProduct (a: number[], b: number[]) {
1065 + return a.map((value, i) => value * b[i]).reduce((acc, val) => acc + val, 0)
1066 + }
1067 +}
1068 +</script>
1069 +
1070 +<style scoped>
1071 +.main-layout {
1072 + height: 100%;
1073 + width: 100%;
1074 +}
1075 +
1076 +.scenario-item {
1077 + display: flex;
1078 + flex-direction: row;
1079 +}
1080 +
1081 +.content-wrapper {
1082 + min-width: 1024px;
1083 + height: 100%;
1084 +}
1085 +</style>
1 +import Vue from 'vue'
2 +import App from './App.vue'
3 +import BootstrapVue from 'bootstrap-vue'
4 +import 'bootstrap/dist/css/bootstrap.min.css'
5 +import 'bootstrap-vue/dist/bootstrap-vue.css'
6 +
7 +Vue.config.productionTip = false
8 +Vue.use(BootstrapVue)
9 +
10 +new Vue({
11 + render: h => h(App)
12 +}).$mount('#app')
1 +import Vue, { VNode } from 'vue'
2 +
3 +declare global {
4 + namespace JSX {
5 + // tslint:disable no-empty-interface
6 + interface Element extends VNode {}
7 + // tslint:disable no-empty-interface
8 + interface ElementClass extends Vue {}
9 + interface IntrinsicElements {
10 + [elem: string]: any;
11 + }
12 + }
13 +}
1 +declare module '*.vue' {
2 + import Vue from 'vue'
3 + export default Vue
4 +}
1 +{
2 + "compilerOptions": {
3 + "target": "esnext",
4 + "module": "esnext",
5 + "strict": true,
6 + "jsx": "preserve",
7 + "importHelpers": true,
8 + "moduleResolution": "node",
9 + "experimentalDecorators": true,
10 + "esModuleInterop": true,
11 + "allowSyntheticDefaultImports": true,
12 + "sourceMap": true,
13 + "baseUrl": ".",
14 + "types": [
15 + "webpack-env"
16 + ],
17 + "paths": {
18 + "@/*": [
19 + "src/*"
20 + ]
21 + },
22 + "lib": [
23 + "esnext",
24 + "dom",
25 + "dom.iterable",
26 + "scripthost"
27 + ]
28 + },
29 + "include": [
30 + "src/**/*.ts",
31 + "src/**/*.tsx",
32 + "src/**/*.vue",
33 + "tests/**/*.ts",
34 + "tests/**/*.tsx"
35 + ],
36 + "exclude": [
37 + "node_modules"
38 + ],
39 +}
No preview for this file type
This file is too large to display.