update ResNet50 demo

This commit is contained in:
Leon Chen
2016-10-09 00:54:19 -04:00
parent b97e2a1b89
commit 39ce7c85eb
6 changed files with 51 additions and 34 deletions
+5
View File
@@ -0,0 +1,5 @@
export const IMAGE_URLS = [
{ name: 'cat', value: 'http://i.imgur.com/CzXTtJV.jpg' },
{ name: 'dog', value: 'http://i.imgur.com/OB0y6MR.jpg' },
{ name: 'bridge', value: 'http://i.imgur.com/Bvke53p.jpg' }
]
-2
View File
@@ -10,13 +10,11 @@ const MODEL_FILEPATHS_DEV = {
weights: '/demos/data/mnist_cnn/mnist_cnn_weights.buf',
metadata: '/demos/data/mnist_cnn/mnist_cnn_metadata.json'
}
const MODEL_FILEPATHS_PROD = {
model: 'demos/data/mnist_cnn/mnist_cnn.json',
weights: 'https://transcranial.github.io/keras-js-demos-data/mnist_cnn/mnist_cnn_weights.buf',
metadata: 'demos/data/mnist_cnn/mnist_cnn_metadata.json'
}
const MODEL_CONFIG = {
filepaths: (process.env.NODE_ENV === 'production') ? MODEL_FILEPATHS_PROD : MODEL_FILEPATHS_DEV
}
-2
View File
@@ -8,13 +8,11 @@ const MODEL_FILEPATHS_DEV = {
weights: '/demos/data/mnist_vae/mnist_vae_weights.buf',
metadata: '/demos/data/mnist_vae/mnist_vae_metadata.json'
}
const MODEL_FILEPATHS_PROD = {
model: 'demos/data/mnist_vae/mnist_vae.json',
weights: 'https://transcranial.github.io/keras-js-demos-data/mnist_vae/mnist_vae_weights.buf',
metadata: 'demos/data/mnist_vae/mnist_vae_metadata.json'
}
const MODEL_CONFIG = {
filepaths: (process.env.NODE_ENV === 'production') ? MODEL_FILEPATHS_PROD : MODEL_FILEPATHS_DEV
}
+12 -11
View File
@@ -79,7 +79,7 @@
height: 160px;
display: flex;
flex-direction: column;
align-items: flex-end;
align-items: flex-start;
justify-content: center;
user-select: none;
cursor: default;
@@ -92,8 +92,13 @@
padding: 6px 0;
.output-label {
text-align: right;
width: 200px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-family: $font-2;
font-size: 20px;
font-size: 18px;
color: $color-2;
padding: 0 6px;
border-right: 2px solid $color-1-lighter;
@@ -101,18 +106,14 @@
.output-bar {
height: 8px;
transition: height 0.2s ease-out;
}
.output-bar-rest {
height: 8px;
background: none;
transition: width 0.2s ease-out;
}
.output-value {
width: 50px;
text-align: left;
margin-left: 5px;
font-family: $font-2;
font-size: 16px;
font-size: 14px;
color: $color-2;
}
}
@@ -120,7 +121,7 @@
.output-class.predicted {
.output-label {
color: $color-1;
border-right-color: $color-1;
border-left-color: $color-1;
}
.output-value {
+29 -11
View File
@@ -5,6 +5,7 @@ import ndarray from 'ndarray'
import ops from 'ndarray-ops'
import find from 'lodash/find'
import * as utils from './utils'
import { IMAGE_URLS } from './image-urls'
import { ARCHITECTURE_DIAGRAM, ARCHITECTURE_CONNECTIONS } from './resnet50-arch'
const MODEL_FILEPATHS_DEV = {
@@ -12,23 +13,15 @@ const MODEL_FILEPATHS_DEV = {
weights: '/demos/data/resnet50/resnet50_weights.buf',
metadata: '/demos/data/resnet50/resnet50_metadata.json'
}
const MODEL_FILEPATHS_PROD = {
model: 'demos/data/resnet50/resnet50.json',
weights: 'https://transcranial.github.io/keras-js-demos-data/resnet50/resnet50_weights.buf',
metadata: 'demos/data/resnet50/resnet50_metadata.json'
}
const MODEL_CONFIG = {
filepaths: (process.env.NODE_ENV === 'production') ? MODEL_FILEPATHS_PROD : MODEL_FILEPATHS_DEV
}
const IMAGE_URL_LIST = [
{ name: 'cat', value: 'http://i.imgur.com/CzXTtJV.jpg' },
{ name: 'dog', value: 'http://i.imgur.com/OB0y6MR.jpg' },
{ name: 'bridge', value: 'http://i.imgur.com/Bvke53p.jpg' }
]
/**
*
* VUE COMPONENT
@@ -46,7 +39,7 @@ export const ResNet50 = Vue.extend({
modelRunning: false,
imageURLInput: null,
imageURLSelect: null,
imageURLSelectList: IMAGE_URL_LIST,
imageURLSelectList: IMAGE_URLS,
imageLoading: false,
imageLoadingError: false,
output: null,
@@ -77,7 +70,13 @@ export const ResNet50 = Vue.extend({
return this.model.layersWithResults
},
outputClasses: function () {
if (!this.output) return []
if (!this.output) {
let empty = []
for (let i = 0; i < 5; i++) {
empty.push({ name: '.', probability: 0 })
}
return empty
}
return utils.imagenetClassesTopK(this.output, 5)
}
},
@@ -134,6 +133,11 @@ export const ResNet50 = Vue.extend({
},
loadImageToCanvas: function (url) {
if (!url) {
this.clearAll()
return
}
this.imageLoading = true
loadImage(
url,
@@ -174,7 +178,7 @@ export const ResNet50 = Vue.extend({
// data processing
// see https://github.com/fchollet/keras/blob/master/keras/applications/imagenet_utils.py
let dataTensor = ndarray(data, [width, height, 4])
let dataTensor = ndarray(new Float32Array(data), [width, height, 4])
let dataProcessedTensor = ndarray(new Float32Array(width * height * 3), [width, height, 3])
ops.subseq(dataTensor.pick(null, null, 0), 103.939)
ops.subseq(dataTensor.pick(null, null, 1), 116.779)
@@ -190,6 +194,20 @@ export const ResNet50 = Vue.extend({
this.output = outputData['fc1000']
this.modelRunning = false
})
},
clearAll: function () {
this.modelRunning = false
this.imageURLInput = null
this.imageURLSelect = null
this.imageLoading = false
this.imageLoadingError = false
this.output = null
this.model.layersWithResults = []
const ctx = document.getElementById('input-canvas').getContext('2d')
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)
}
}
})
+5 -8
View File
@@ -46,17 +46,14 @@
<div class="column output-column">
<div class="output">
<div class="output-class"
:class="{ 'predicted': $index === 0 }"
v-for="entry in outputClasses"
:class="{ 'predicted': i === 0 && outputClasses[i].probability.toFixed(2) > 0 }"
v-for="i in [0, 1, 2, 3, 4]"
>
<div class="output-label">{{ entry.name }}</div>
<div class="output-label">{{ outputClasses[i].name }}</div>
<div class="output-bar"
style="width: {{ Math.round(100 * entry.probability) }}px; background: rgba(27, 188, 155, {{ entry.probability.toFixed(2) }});"
style="width: {{ Math.round(100 * outputClasses[i].probability) }}px; background: rgba(27, 188, 155, {{ outputClasses[i].probability.toFixed(2) }});"
></div>
<div class="output-bar-rest"
style="width: {{ 100 - Math.round(100 * entry.probability) }}px;"
></div>
<div class="output-value">{{ Math.round(100 * entry.probability) }}%</div>
<div class="output-value">{{ Math.round(100 * outputClasses[i].probability) }}%</div>
</div>
</div>
</div>