首先附上原文链接:如何利用TensorFlow.js部署简单的AI版「你画我猜」图像识别应用

本文创建了一个简单的工具来识别手绘图像,并且输出当前图像的名称。该应用无需安装任何额外的插件,可直接在浏览器上运行。作者使用谷歌 Colab 来训练模型,并使用 TensorFlow.js 将它部署到浏览器上。

代码和 demo

  • demo 地址:https://zaidalyafeai.github.io/sketcher/

  • 代码地址:https://github.com/zaidalyafeai/zaidalyafeai.github.io/tree/master/sketcher

  • 请通过以下链接在谷歌 Colab 上测试自己的 notebook:https://colab.research.google.com/github/zaidalyafeai/zaidalyafeai.github.io/blob/master/sketcher/Sketcher.ipynb

数据集

我们将使用卷积神经网络(CNN)来识别不同类型的手绘图像。这个卷积神经网络将在 Quick Draw 数据集(https://github.com/googlecreativelab/quickdraw-dataset)上接受训练。该数据集包含 345 个类别的大约 5 千万张手绘图像。

部分图像类别

流程

我们将使用 Keras 框架在谷歌 Colab 免费提供的 GPU 上训练模型,然后使用 TensorFlow.js 直接在浏览器上运行模型。我在 TensorFlow.js 上创建了一个教程(https://medium.com/tensorflow/a-gentle-introduction-to-tensorflow-js-dba2e5257702)。在继续下面的工作之前,请务必先阅读一下这个教程。下图为该项目的处理流程:

流程

在 Colab 上进行训练

谷歌 Colab 为我们提供了免费的 GPU 处理能力。你可以阅读下面的教程(https://medium.com/deep-learning-turkey/google-colab-free-gpu-tutorial-e113627b9f5d)了解如何创建 notebook 和开始进行 GPU 编程。

导入

我们将使用以 TensorFlow 作为后端、Keras 作为前端的编程框架

import os
import glob
import numpy as np
from tensorflow.keras import layers
from tensorflow import keras 
import tensorflow as tf

加载数据

由于内存容量有限,我们不会使用所有类别的图像进行训练。我们仅使用数据集中的 100 个类别(https://raw.githubusercontent.com/zaidalyafeai/zaidalyafeai.github.io/master/sketcher/mini_classes.txt)。每个类别的数据可以在谷歌 Colab(https://console.cloud.google.com/storage/browser/quickdrawdataset/full/numpybitmap?pli=1)上以 NumPy 数组的形式获得,数组的大小为 [N, 784],其中 N 为某类图像的数量。我们首先下载这个数据集:

import urllib.request
def download():

base = 'https://storage.googleapis.com/quickdraw_dataset/full/numpy_bitmap/'
  for c in classes:
    cls_url = c.replace('_', '%20')
    path = base+cls_url+'.npy'
    print(path)
    urllib.request.urlretrieve(path, 'data/'+c+'.npy')

由于内存限制,我们在这里将每类图像仅仅加载 5000 张。我们还将留出其中的 20% 作为测试数据。

def load_data(root, vfold_ratio=0.2, max_items_per_class= 5000 ):
    all_files = glob.glob(os.path.join(root, '*.npy'))

#initialize variables 
    x = np.empty([0, 784])
    y = np.empty([0])
    class_names = []

#load a subset of the data to memory 
    for idx, file in enumerate(all_files):
        data = np.load(file)
        data = data[0: max_items_per_class, :]
        labels = np.full(data.shape[0], idx)

x = np.concatenate((x, data), axis=0)
        y = np.append(y, labels)

class_name, ext = os.path.splitext(os.path.basename(file))
        class_names.append(class_name)

data = None
    labels = None

#separate into training and testing 
    permutation = np.random.permutation(y.shape[0])
    x = x[permutation, :]
    y = y[permutation]

vfold_size = int(x.shape[0]/100*(vfold_ratio*100))

x_test = x[0:vfold_size, :]
    y_test = y[0:vfold_size]

x_train = x[vfold_size:x.shape[0], :]
    y_train = y[vfold_size:y.shape[0]]
    return x_train, y_train, x_test, y_test, class_names

数据预处理

我们对数据进行预处理操作,为训练模型做准备。该模型将使用规模为 [N, 28, 28, 1] 的批处理,并且输出规模为 [N, 100] 的概率。

# Reshape and normalize
x_train = x_train.reshape(x_train.shape[0], image_size, image_size, 1).astype('float32')
x_test = x_test.reshape(x_test.shape[0], image_size, image_size, 1).astype('float32')

x_train /= 255.0
x_test /= 255.0

# Convert class vectors to class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

创建模型

我们将创建一个简单的卷积神经网络。请注意,模型越简单、参数越少越好。实际上,我们将把模型转换到浏览器上然后再运行,并希望模型能在预测任务中快速运行。下面的模型包含 3 个卷积层和 2 个全连接层:

# Define model
model = keras.Sequential()
model.add(layers.Convolution2D(16, (3, 3),
                        padding='same',
                        input_shape=x_train.shape[1:], activation='relu'))
model.add(layers.MaxPooling2D(pool_size=(2, 2)))
model.add(layers.Convolution2D(32, (3, 3), padding='same', activation= 'relu'))
model.add(layers.MaxPooling2D(pool_size=(2, 2)))
model.add(layers.Convolution2D(64, (3, 3), padding='same', activation= 'relu'))
model.add(layers.MaxPooling2D(pool_size =(2,2)))
model.add(layers.Flatten())
model.add(layers.Dense(128, activation='relu'))
model.add(layers.Dense(100, activation='softmax')) 
# Train model
adam = tf.train.AdamOptimizer()
model.compile(loss='categorical_crossentropy',
              optimizer=adam,
              metrics=['top_k_categorical_accuracy'])
print(model.summary())

拟合、验证及测试

在这之后我们对模型进行了 5 轮训练,将训练数据分成了 256 批输入模型,并且分离出 10% 作为验证集。

#fit the model 
model.fit(x = x_train, y = y_train, validation_split=0.1, batch_size = 256, verbose=2, epochs=5)

#evaluate on unseen data
score = model.evaluate(x_test, y_test, verbose=0)
print('Test accuarcy: {:0.2f}%'.format(score[1] * 100))

训练结果如下图所示:

测试准确率达到了 92.20% 的 top 5 准确率。

准备 WEB 格式的模型

在我们得到满意的模型准确率后,我们将模型保存下来,以便进行下一步的转换。

model.save('keras.h5')

为转换安装 tensorflow.js:

!pip install tensorflowjs

接着我们对模型进行转换:

!mkdir model
!tensorflowjs_converter --input_format keras keras.h5 model/

这个步骤将创建一些权重文件和包含模型架构的 json 文件。

通过 zip 将模型进行压缩,以便将其下载到本地机器上:

!zip -r model.zip model

最后下载模型:

from google.colab import files
files.download('model.zip')

在浏览器上进行推断

本节中,我们将展示如何加载模型并且进行推断。假设我们有一个尺寸为 300*300 的画布。在这里,我们不会详细介绍函数接口,而是将重点放在 TensorFlow.js 的部分。

加载模型

为了使用 TensorFlow.js,我们首先使用下面的脚本:

<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest"> script>

你的本地机器上需要有一台运行中的服务器来托管权重文件。你可以在 GitHub 上创建一个 apache 服务器或者托管网页,就像我在我的项目中所做的那样(https://github.com/zaidalyafeai/zaidalyafeai.github.io/tree/master/sketcher)。

接着,通过下面的代码将模型加载到浏览器:

model = await tf.loadModel('model/model.json')

关键字 await 的意思是等待模型被浏览器加载。

预处理

在进行预测前,我们需要对数据进行预处理。首先从画布中获取图像数据:

//the minimum boudning box around the current drawing
const mbb = getMinBox()
//cacluate the dpi of the current window 
const dpi = window.devicePixelRatio
//extract the image data 
const imgData = canvas.contextContainer.getImageData(mbb.min.x * dpi, mbb.min.y * dpi,
                               (mbb.max.x - mbb.min.x) * dpi, (mbb.max.y - mbb.min.y) * dpi);

文章稍后将介绍 getMinBox()。dpi 变量被用于根据屏幕像素的密度对裁剪出的画布进行拉伸。

我们将画布当前的图像数据转化为一个张量,调整大小并进行归一化处理:

function preprocess(imgData)
{
return tf.tidy(()=>{
    //convert the image data to a tensor 
    let tensor = tf.fromPixels(imgData, numChannels= 1)
    //resize to 28 x 28 
    const resized = tf.image.resizeBilinear(tensor, [28, 28]).toFloat()
    // Normalize the image 
    const offset = tf.scalar(255.0);
    const normalized = tf.scalar(1.0).sub(resized.div(offset));
    //We add a dimension to get a batch shape 
    const batched = normalized.expandDims(0)
    return batched
})
}

我们使用 model.predict 进行预测,这将返回一个规模为「N, 100」的概率。

const pred = model.predict(preprocess(imgData)).dataSync()

我们可以使用简单的函数找到 top 5 概率。

提升准确率

请记住,我们的模型接受的输入数据是规模为 [N, 28, 28, 1] 的张量。我们绘图画布的尺寸为 300*300,这可能是两个手绘图像的大小,或者用户可以在上面绘制一个小图像。最好只裁剪包含当前手绘图像的方框。为了做到这一点,我们通过找到左上方和右下方的点来提取围绕图像的最小边界框。

//record the current drawing coordinates       
function recordCoor(event)
{
  //get current mouse coordinate 
  var pointer = canvas.getPointer(event.e);
  var posX = pointer.x;
  var posY = pointer.y;

//record the point if withing the canvas and the mouse is pressed 
  if(posX >=0 && posY >= 0 && mousePressed)  
  {      
    coords.push(pointer) 
  } 
}

//get the best bounding box by finding the top left and bottom right cornders    
function getMinBox(){

var coorX = coords.map(function(p) {return p.x});
   var coorY = coords.map(function(p) {return p.y});
   //find top left corner 
   var min_coords = {
    x : Math.min.apply(null, coorX),
    y : Math.min.apply(null, coorY)
   }
   //find right bottom corner 
   var max_coords = {
    x : Math.max.apply(null, coorX),
    y : Math.max.apply(null, coorY)
   }
   return {
    min : min_coords,
    max : max_coords
   }
}

用手绘图像进行测试

下图显示了一些第一次绘制的图像以及准确率最高的类别。所有的手绘图像都是我用鼠标画的,用笔绘制的话应该会得到更高的准确率。

原文链接:https://medium.com/tensorflow/train-on-google-colab-and-run-on-the-browser-a-case-study-8a45f9b1474e

∞∞∞∞∞

IT派 - {技术青年圈} 持续关注互联网、区块链、人工智能领域

公众号回复“IT派”,

邀你加入IT派 { 技术交流群 }

使用Colab训练NN模型并利用Tensorflow.js部署网页应用相关推荐

  1. 如何利用TensorFlow.js部署简单AI版「你画我猜」

    选自Medium,作者:Zaid Alyafeai,机器之心编译,参与:Geek AI.路. 本文创建了一个简单的工具来识别手绘图像,并且输出当前图像的名称.该应用无需安装任何额外的插件,可直接在浏览 ...

  2. 如何利用TensorFlow.js部署简单的AI版「你画我猜」图像识别应用

    选自Medium,作者:Zaid Alyafeai,机器之心编译,参与:Geek AI.路. 本文创建了一个简单的工具来识别手绘图像,并且输出当前图像的名称.该应用无需安装任何额外的插件,可直接在浏览 ...

  3. 利用tensorflow.js在线实现图像要素识别提取

    什么是Tensorflow.js? TensorFlow.js是一个开源的基于硬件加速的JavaScript库,用于训练和部署机器学习模型.谷歌推出的第一个基于TensorFlow的前端深度学习框架T ...

  4. 图像迁移风格保存模型_用TensorFlow.js在浏览器中部署可进行任意图像风格迁移的模型...

    风格迁移一直是很多读者感兴趣的内容之一,近日,网友ReiichiroNakano公开了自己的一个实现:用TensorFlow.js在浏览器中部署可进行任意图像风格迁移的模型.让我们一起去看看吧! Gi ...

  5. ncnn填坑记录八:将自己训练的模型打包为APK并部署到安卓端运行

    上一篇:ncnn填坑记录七:examples/squeezenet.cpp代码阅读 做一个分类任务,模型选取的mobilenetv3,训练好模型,并按前文依次转换为onnx.ncnn后,参考官方htt ...

  6. 用浏览器训练Tensorflow.js模型的18个技巧(上)

    摘要: 送你18个训练Tensorflow.js模型的小技巧! 在移植现有模型(除tensorflow.js)进行物体检测.人脸检测.人脸识别后,我发现一些模型不能以最佳性能发挥.而tensorflo ...

  7. tensorflow sigmoid 如何计算训练数据的正确率_“来自蒙娜丽莎的凝视”— 结合 TensorFlow.js 和深度学习实现...

    客座博文 / Emily Xie,软件工程师 背景 坊间传闻,当您在房间里走动时,蒙娜丽莎的眼睛会一直盯着您. 这就是所谓的"蒙娜丽莎效应".兴趣使然,我最近就编写了一个可互动的数 ...

  8. tf.saved_model.save模型导出、TensorFlow Serving模型部署、TensorBoard中的HParams 超参数调优

    日萌社 人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新) 4.11 综合案例:模型导出与部署 学习目标 目标 掌握Ten ...

  9. 独家 | 在浏览器中使用TensorFlow.js和Python构建机器学习模型(附代码)

    作者:MOHD SANAD ZAKI RIZVI 翻译:吴金笛 校对:丁楠雅 本文约5500字,建议阅读15分钟. 本文首先介绍了TensorFlow.js的重要性及其组件,并介绍使用其在浏览器中构建 ...

最新文章

  1. Docker源码分析(一):Docker架构
  2. 学习使用 Manifest
  3. java中join的使用
  4. eveningplan
  5. 洛谷-DFS-1101-单词方阵-个人AC题解及公共题解的笔记
  6. 七个不容易被发现的生成对抗网络(GAN)用例
  7. OpenEIM以前在合作伙伴做的时候
  8. 运用Unity实现AOP拦截器[结合异常记录实例]
  9. 从“阿里月饼门”看安全
  10. 爬取b站最火up主及其粉丝信息
  11. 如何快速打开.pos
  12. 蓝牙定位技术原理--蓝牙人员定位--蓝牙定位--新导智能
  13. awk 的内置变量 NF、NR、FNR、FS、OFS、RS、ORS
  14. 拿了“普通女生”的人生剧本,可以不普通吗?
  15. 注解/Annotation
  16. 手机病毒肆虐:恶意软件每天获取超3000美元收益
  17. GetLastError的返回值意思
  18. SSDHDD混装换一块SSD(迁移系统与资料不重装)
  19. 课程设计报告linux小游戏,嵌入式课程设计报告---贪吃蛇游戏.doc
  20. 安踏官网首页html css,发布商品.html · peirenlei/layuiadmin-templete - Gitee.com

热门文章

  1. MBA-day6 逻辑学-假言推理练习题
  2. 迷失中的自己,找一个安静的地方
  3. Qt OpenGL(二十七)——Qt OpenGL 核心模式--EBO
  4. 财务模块常用BAPI
  5. 小米NFC公交卡门卡提示:固件需要升级,请删除实体门卡、小区门卡和空白门卡后重试
  6. python去噪音_如何使用opencvpython去除图像噪声?
  7. 模数(A/D)转换器工作原理
  8. 在endnote中制作符合硕士毕业论文的输出格式
  9. 常用知识点总结:萨克斯
  10. 中兴交换机vrrp及mstp多生成树详解