KerasJS初探

简介

Keras是一款非常流行的深度学习模型开发框架,基于python,语法简洁,封装程度高,只需十几行代码就可以构建一个深度神经网络。
Keras.js是一个可以在浏览器中运行深度神经网络的JS框架,支持CPU,GPU计算。区别于Keras,Keras.js只能运行已经调试好的模型,无法进行模型训练。


KerasJS

KerasJS流程

模型

借鉴这篇文章,开发一个识别圣诞老人的神经网络。本文不涉及Keras的开发细节,感兴趣的同学可以去原文查看。这里直接给出python代码

def build_model():
    model = models.Sequential()
    model.add(layers.Conv2D(20,(5,5),activation='relu',input_shape=(128,128,3)))
    model.add(layers.MaxPooling2D(pool_size=(2,2),strides=(2,2)))
    model.add(layers.Conv2D(50,(5,5),activation='relu',padding='same'))
    model.add(layers.MaxPooling2D(pool_size=(2,2),strides=(2,2)))
    model.add(layers.Flatten())
    model.add(layers.Dense(500,activation='relu'))
    model.add(layers.Dense(1, activation='sigmoid'))
    model.compile(optimizer=optimizers.RMSprop(lr=2e-5),
                  loss='binary_crossentropy',
                  metrics=['acc'])
    return model

数据

标注数据是AI模型的原料,数据搜集特别是图片搜集是前端可以介入的一个环节。基于React,开发了一款chrome图片批量下载插件GetThemAll,方便我们进行标记图片搜集。

GetThemAll

插件地址,安装好插件。然后去谷歌图片搜索“santa”, 使用插件标记不需要的图片,然后下载到本地的santa文件夹,通过谷歌图片可以搜集到400张圣诞老人的图片。
接着我们再下载一些非圣诞老人的图片,搜索“object”,同样的使用GetThemAll插件下载大约400张图片到本地的non_santa文件夹中。
除了训练数据集,我们还需要一个测试数据集用来衡量模型的泛化能力。在本地新建一个test文件夹,把刚刚准备好的训练集里面的最后100张圣诞老人图片移到test文件夹下的santa文件中,同样的,移动100张非圣诞老人图片到non_stanta文件中。
数据集结构

有了标记数据,我们就可以进行模型训练啦。具体的训练过程请见pyton代码,这里直接给出训练的结果,蓝点表示训练数据集准确率,蓝线表示测试数据集准备率,模型有着明显的High Variance问题,不过这个bug留给深度学习的专家们解决吧,这里就假设这个模型可用。


训练结果

迁移

上一步训练出的模型keras_santa.h5(h5是文件后缀,和HTML5没啥关系)不能直接给KerasJS使用,需要通过KerasJS提供的转换工具转换后,方可被KerasJS加载解析。

./encoder.py keras_santa.h5

转换后,得到了keras_santa.bin文件,20M左右,这个文件包含了神经网络结构和所有参数,可以被KerasJS加载。

KerasJS

通过上面的步骤,我们得到了一个训练完成的CNN神经网络以及全部参数,这个网络结构和参数全部保存在keras_santa.bin文件中。接下来,我们只需要在浏览器中复原上面的神经网络,然后就可以开始做预测啦。
使用webpack配合React,搭建一套简单的开发环境。做好了基础工作,就可以开始第一步开发,加载神经网络模型文件keras_santa.bin:

const model = new KerasJS.Model({
   filepath: 'http://localhost:3000/keras_santa.bin',
   gpu: false
})
//KerasJS提供模型加载进度接口,考虑到模型文件体积非常大,这个接口会经常用到
model.events.on('loadingProgress', (progress) => {
      this.setState({
        loadingtitle: '模型加载',
        progress: parseInt(progress)
      })
})

使用上面的模型做预测前,需要将数据转化成模型能够接受的数据格式。这个圣诞老人网络需要数据输入格式为(128,128,3),也即是图片需要为128x128分辨率,只能包含RGB三个分量。


输入数据

借助canvas,可以实现图片分辨率转换:

_updateImageSrc(imgid) {
    const ctx = this.refs.canvas.getContext('2d');
    const imgdom = document.createElement('img');
    imgdom.src = `http://localhost:3000/${imgid}.jpeg`
    this.setState({
      prediction:0
    })
    imgdom.onload = ()=>{
      ctx.drawImage(imgdom,0,0,128,128)
      const imagedata = ctx.getImageData(0,0,128,128)
      const processeddata = ImageDataUtils.preprocess(imagedata)
      setTimeout(()=>{
        this.doPrediction(processeddata)
      },100);
    }
  }

注意preprocess,通过canvas获取到的图片资源包含了rgba四个维度,prepross返回这4个维度中的前3个维度,也即rgb,同时将数据标准化:

export default class ImageDataUtils {
  static preprocess(imageData) {
    const {
      width,
      height,
      data
    } = imageData;
    const dataTensor = ndarray(new Float32Array(data),[width,height,4])
    const dataProcessedTensor = ndarray(new Float32Array(width*height*3),[width,height,3])
    //从[0,255]转化到[0,1]
    ops.divseq(dataTensor,255)
    //获取R数据
    ops.assign(dataProcessedTensor.pick(null,null,0),dataTensor.pick(null,null,0))
    //获取G数据
    ops.assign(dataProcessedTensor.pick(null,null,1),dataTensor.pick(null,null,1))
    //获取B数据
    ops.assign(dataProcessedTensor.pick(null,null,2),dataTensor.pick(null,null,2))
    const preprocessedData = dataProcessedTensor.data
    return preprocessedData
  }   
}

最后,使用上面返回的数据做预测

async doPrediction(imagedata) {
    if(!this.model) return;
    const inputname = this.model.inputLayerNames[0]
    const inputdata = {[inputname]: imagedata}
    const prediction = await this.model.predict(inputdata)
    this.setState({
      prediction: prediction.output[0]
    })
  }
预测

注意

可以看到,KerasJS在预测过程中,整个页面无法响应用户操作。这是因为神经网络计算过程中占用了大量CPU资源,从而致使页面卡顿。下一篇文章中,我们将介绍如何使用WebGL,将计算过程转移到GPU,达到实现前端高性能计算的目的。

相关资源

1.Image classification with Keras and deep learning, Adrain Rosebrock

  1. GetThemAll, eeandrew
  2. React Keras,eeandrew
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容