前端智能漫谈

2019 年 12 月 19 日 TensorFlow

文 /  腾讯IEG 王高垒 (Allan)

本文作者: Allan, 来自腾讯互娱 tgideas 团队,10 年 + 前端开发经验,负责游戏相关的 web 业务。喜欢鼓捣提高生产力的前端工具和研究创意相关的技术实现。

众所周知,前端相关的业务相当于整个业务的用户体验前哨站。


除了在性能优化、动画等传统的体验上做努力,我们又如何在:目标(手势、肢体)识别、语音识别分析、无障碍、语音分析、增强现实、情绪识别、画像细分等等,基于人工智能的交互体验上,尽自己的一份力呢?


本文分为:第三方接口 、重头训练一个模型、使用成熟模型、再次训练 4个部分来展开前端应用人工智能的方法。


希望可以抛砖引玉,给大家带来一些思考。如果能对实际工作带来帮助,那就更好不过了。


下面开始正文:



使用第三方应用接口

使用第三方接口(比如腾讯云,谷歌云)就跟普通的业务没太大区别,都是 【用户输入数据 -> 请求接口 -> 解析接口内容】,难点主要在于把解析后的数据玩出花样。


比如之前刷爆朋友圈的你画我猜,就是先让用户在 canvas 上画出图形后,把图形上传到自己的服务器,然后做出相应的预测,你画我猜类似版本体验

  • 版本体验
    https://quickdraw.withgoogle.com/


如果你调查市面上的 API 接口没有发现你需要的,那么就跟我一起来看下第二种解决方案:重头训练一个新的模型。



重头训练一个新的模型

重头训练一个模型需要大量的专业知识,但是这并不影响我开始这部分的介绍 :p,我会以一个简单的例子开始,你可以测试一下你是否有兴趣深入下去。


大家请看这个例子:

x = [-1,0,1,2,3,4]
y = [-3,-1.0,1,3,5,7],

请用一点时间推导一下 X 和 Y 的关系公式:


3…


2…


1…


相信大家经过试错和思考已经找到答案了:


【y=2x-1】


这个就是神经网络的原理 (我所理解的大白话):设计好神经网络之后,输入的数据根据正确答案,经过某些次数的训练 (试错) 之后,拟合到一个最终的值 (参数)。把值 (参数) 保存下来,以方便其他类似场景使用。


那么落地到 TensorFlow 代码中又是怎样的呢?我们又如何设计这个神经网络呢?


请看代码(代码基于 TensorFlow 1.15.x):

#加载模块依赖
import tensorflow as tf
import numpy as np
from tensorflow import keras
#添加一层神经网络,输入的参数是一维向量
model = keras.Sequential([keras.layers.Dense(units=1,input_shape=[1])])
#为模型添加sgd优化器 损失函数为均方误差
model.compile(optimizer='sgd',loss='mse')
#输入的数据及正确的数据
xs = np.array([-1.0,0.0,1.0,2.0,3.0,4.0],dtype=float)
ys = np.array([-3.0,-1.0,1.0,3.0,5.0,7.0],dtype=float)
#训练模型50轮
model.fit(xs,ys,epochs=500)
#输出模型详细信息
model.summary()
#保存模型
model.save('model1.h5')
#预测某个数字的结果
print(model.predict([654615]))
#[[1307159.4]]

接下来,在模型调试成功之后,把 keras 模型转为 tfjs 可以使用的模型就可以在网页中预测了 (在第 4 部分有讲到具体操作方法)。


如果你是一个没有接触过 TensorFlow 的同学,看完这段代码应该大概率懵逼了,没错,我也是懵逼的。


而这只是一个非常简单的只有一个全连接层的入门例子 (人都可以短时间推导出来),但是人工智能往往需要做特别复杂的预测,比如票房预测、无人机飞行控制,人类手动计算各项输入几乎没办法完成。那网络的设计将比这个复杂的多(手动狗头)。


除了完美的网络设计以外,如果你还希望预测的准确率高一些,很完善的数据集也是必不可少的。比如之前提到的快速涂鸦的例子,仅 "飞机" 一个分类的数据集就有高达 13 万张图片数据。

  • 数据集
    https://quickdraw.withgoogle.com/data/airplane


所以重头训练一个新的模型,是一个学习周期很长、成本相当高的方案。如果希望短时间内用 AI 赋能你的业务,最好先看下其他三种方案有没有适合你的需求,或者问下 AI 部门的同事,他们有没有兴趣和你一起干。


如果你对此很有兴趣想要深入学习下去,推荐你看吴恩达的最新课程 (开始的例子也是出自这个课程,旁听免费)。

  • 吴恩达最新课程
    https://www.coursera.org/specializations/tensorflow-in-practice



使用成熟模型

除了很多限制的使用第三方接口和门槛很高的重头训练以外,我们还可以选择使用成熟的模型,TensorFlow 已经有 js 版本了,并且已经有成熟的开源模型和类库(前端开源的相关应用几乎全是基于 tfjs 的)。


但是几乎每个例子的 demo 为了展示能力,都预置了参数调整和复杂的交互逻辑,可读性方面尚待提高。


我把社区中开源的前端 AI 能力,又重新用直白的语言写了一遍,每个 DEMO 下有原项目地址链接,有兴趣应用的可以研究更精确的参数。


为了照顾没有摄像头的用户,我为每个例子都写了上传图像的版本。


也为了保持demo的单独性和便于理解,没有抽离公用模块,基本开箱即用:

  • 风格迁移
    抽取图像上的特征应用到其他图片
    https://allan5.com/FE-AI/style-transfer.html

  • 看图识花
    可识别的分类:雏菊、蒲公英、玫瑰、向日葵、郁金香
    https://allan5.com/FE-AI/flower.html

  • 人脸检测 支持摄像头
    识别人脸、情绪、年龄
    https://allan5.com/FE-AI/flower.html

  • 手部追踪
    识别人体手部
    https://allan5.com/FE-AI/handtrack.html

  • 图像分类 支持摄像头
    可识别的分类:https://github.com/tensorflow/tfjs-models/blob/master/mobilenet/src/imagenet_classes.ts

    https://allan5.com/FE-AI/mobilenet.html

  • 目标识别 支持摄像头
    可识别的目标:https://github.com/tensorflow/tfjs-models/blob/master/coco-ssd/src/classes.ts

    https://allan5.com/FE-AI/object_detection.html

  • 人物分割 1.0 支持摄像头
    可识别人体轮廓

    https://allan5.com/FE-AI/bodypix.html

  • 人物分割 2.0 支持摄像头
    可同时识别多个人体轮廓

    https://allan5.com/FE-AI/bodypix2.html

  • 姿态检测 支持摄像头
    识别人体关键点

    https://allan5.com/FE-AI/posenet.html


除了在浏览器中支持以外,TensorFlow.js 官方也推出了支持小程序的插件

  • 插件
    https://mp.weixin.qq.com/wxopen/pluginbasicprofile?action=intro&appid=wx6afed118d9e81df9&token=612578398&lang=zh_CN


有兴趣的同学可以学习我同事 @xiaoxiwang 出品在腾讯课堂上发布的 TensorFlow.js 小程序视频教程

  • 视频教程
    https://ke.qq.com/course/428263?taid=3607622205212903&dialog=1


成熟模型带来了免费、视频实时预测等等优点,同时也带来了无法定制识别自己的分类等缺点。


接下来是最后一种方法:再次训练



再次训练

有的时候你的需求,需要的 AI 能力仅仅只需要识别一个标志物体或者目标的坐标,比如某个 LOGO、某幅画。那么可以在前人的训练好的模型基础上再次训练。


在没有强大数据集和 AI 团队支持的情况下,使用前人训练好的参数和模型设计基础上,再次训练不失为一种不错的选择(这种方法也称为迁移学习)。


下面以高度封装的 tensorflow-for-poets-2 为例,介绍训练图片分类的详细步骤(只需 7 步):


1. clone 预训练源代码

git clone https://github.com/googlecodelabs/tensorflow-for-poets-2
cd tensorflow-for-poets-2


2. 下载测试数据集 (解压到 tensorflow-for-poets-2/tf_files)

  • 测试数据集
    http://download.tensorflow.org/example_images/flower_photos.tgz


3. 开始训练 (基于 tensorflow 1.15.0 环境)

python -m scripts.retrain ^
--bottleneck_dir=tf_files/bottlenecks ^
--how_many_training_steps=2000 ^
--model_dir=tf_files/models/ ^
--summaries_dir=tf_files/training_summaries/mobilenet_0.50_224 ^
--output_graph=tf_files/retrained_graph.pb ^
--output_labels=tf_files/retrained_labels.txt ^
--architecture=mobilenet_0.50_224 ^
--image_dir=tf_files/flower_photos

(mac下命令连接符是 \,win下是 ^)


4. 测试输出 

python -m scripts.label_image --graph=tf_files/retrained_graph.pb --image=xxx

#正常情况下会有类似输出:
daisy (score = 0.xxxx)
sunflowers (score = 0.xxxx)


5. 优化 PB 文件

python  scripts/quantize_graph.py ^
--input=tf_files/retrained_graph.pb ^
--output=tf_files/quantized_graph.pb ^
--output_node_names=final_result ^
--mode=weights_rounded


6.安装 tensorflowjs

pip install tensorflowjs==1.3.2


7. 转换 PB 文件为 web 可用的 PB 文件

tensorflowjs_converter ^
--input_format=tf_frozen_model ^
--output_node_names=final_result ^
--output_format=tfjs_graph_model ^
tf_files/quantized_graph.pb ^
tf_files/web


到这里,全部步骤已经完成了。我也使用刚才的 tfjs-converter 转换之后的 model.json 写了一个示例  (https://allan5.com/FE-AI/flower.html)


和使用成熟模型最大的不同是,需要自己处理传递给模型的图像参数:

//初始输入信息
const image = tf.browser.fromPixels(pic);
//把初始化为224x224的大小
const resized_image =tf.image.resizeBilinear(image, [224,224]).toFloat();
//把向量转换为0~1的数值
const offset = tf.scalar(255.0);
const normalized = tf.scalar(1.0).sub(resized_image.div(offset));
//把输入的数据转换为[0,224,224,3]的标准格式
const batchedImage = normalized.expandDims(0);
const result = await model.predict(batchedImage).data();
//根据评分排序结果
let text = label.map((label, index) => ({ label, score: result[index] })).sort((a,b)=>b.score - a.score)


因为篇幅的关系,就不仔细拆解目标识别 (带物体具体的坐标信息的预测) 的训练步骤了,如果有兴趣,可以试试这个项目

  • 项目
    https://github.com/EdjeElectronics/TensorFlow-Object-Detection-API-Tutorial-Train-Multiple-Objects-Windows-10


文中第二部分和第四部分选用了 python 语言作为演示语言,作为前端的你现在 tfjs 同样支持在 nodejs 和浏览器中训练模型。


笔者认为现阶段如果要深入机器学习,python 有自己得天独厚的优势,比如社区丰富、有大规模训练的解决方案、图像处理和数学计算等 nodejs 或 js 不能替代的模块。所以本文中的一些示例用了 python 语言。


现在 tf.js 现在也在飞速发展,除了开源社区,TensorFlow 官方也投入了数个全职人力开发。相信不久的将来,tf.js 除了适合前端应用以外,对训练、部署这些周边支撑也会有高效的解决方案!



结语

  • 四种应用方案各有利弊,具体选用哪种,就要 case by case 来评估了。
  • 随着前端算力的逐渐进化,会有更多成熟的模型和算法移植到前端的领域。
  • 模型的加载是一个问题,像目标识别模型分类多一些的有超过 20M 大小。现阶段如果应用比较复杂的预测,还是比较适合在资源预载的场景(线下、打包到移动 APP、桌面端软件)使用。但是未来 5G 的发展,可能会逐渐弱化这个劣势。


但是这些都是客观原因,如何用现在的技术和自己本身的领域结合,做出更多花样,才是前端同胞们需要一直思考的地方。


最后,特别感谢 tfjs 官方团队 Ping Yu 和 Wei Wei,对此文的指导和校对。



登录查看更多
0

相关内容

Google发布的第二代深度学习系统TensorFlow
专知会员服务
54+阅读 · 2020年7月4日
【ICML2020-华为港科大】RNN和LSTM有长期记忆吗?
专知会员服务
74+阅读 · 2020年6月25日
【WWW2020】DGL深度图神经网络实战教程,PPT+代码
专知会员服务
175+阅读 · 2020年4月12日
【干货书】流畅Python,766页pdf,中英文版
专知会员服务
224+阅读 · 2020年3月22日
TensorFlow Lite指南实战《TensorFlow Lite A primer》,附48页PPT
专知会员服务
69+阅读 · 2020年1月17日
盘一盘 Python 系列 10 - Keras (上)
平均机器
5+阅读 · 2019年8月26日
TF Boys必看!一文搞懂TensorFlow 2.0新架构!
引力空间站
18+阅读 · 2019年1月16日
进阶深度学习?这里有9个给程序员的建议
量子位
4+阅读 · 2018年10月14日
语音识别中的CTC算法的基本原理解释
数盟
4+阅读 · 2018年6月24日
用Python调用百度OCR接口实例
数据挖掘入门与实战
16+阅读 · 2018年1月29日
一个小例子带你轻松Keras图像分类入门
云栖社区
4+阅读 · 2018年1月24日
教程帖:用TensorFlow自制Taylor Swift识别器
论智
13+阅读 · 2018年1月17日
Neural Module Networks for Reasoning over Text
Arxiv
9+阅读 · 2019年12月10日
Feature Selection Library (MATLAB Toolbox)
Arxiv
7+阅读 · 2018年8月6日
Arxiv
5+阅读 · 2018年5月1日
Arxiv
4+阅读 · 2018年2月13日
Arxiv
8+阅读 · 2018年1月25日
Arxiv
27+阅读 · 2017年12月6日
VIP会员
相关资讯
盘一盘 Python 系列 10 - Keras (上)
平均机器
5+阅读 · 2019年8月26日
TF Boys必看!一文搞懂TensorFlow 2.0新架构!
引力空间站
18+阅读 · 2019年1月16日
进阶深度学习?这里有9个给程序员的建议
量子位
4+阅读 · 2018年10月14日
语音识别中的CTC算法的基本原理解释
数盟
4+阅读 · 2018年6月24日
用Python调用百度OCR接口实例
数据挖掘入门与实战
16+阅读 · 2018年1月29日
一个小例子带你轻松Keras图像分类入门
云栖社区
4+阅读 · 2018年1月24日
教程帖:用TensorFlow自制Taylor Swift识别器
论智
13+阅读 · 2018年1月17日
相关论文
Neural Module Networks for Reasoning over Text
Arxiv
9+阅读 · 2019年12月10日
Feature Selection Library (MATLAB Toolbox)
Arxiv
7+阅读 · 2018年8月6日
Arxiv
5+阅读 · 2018年5月1日
Arxiv
4+阅读 · 2018年2月13日
Arxiv
8+阅读 · 2018年1月25日
Arxiv
27+阅读 · 2017年12月6日
Top
微信扫码咨询专知VIP会员