前端探索深度学习指北

背景

近年来Javascript生态链的繁荣发展,前端工程师早已不是当年的"切图仔"。Node.js的出现让前端工程师也能写服务端,随之而来诸如webpack等工具链结合MVVM框架更是让前端迈入工程化、组件化的时代。再后来ReactNative又让前端开发跨平台APP成为了可能。如今随着硬件性能的提升,以及WebGL的GPU计算能力,Tensorflow.js让前端有了做深度学习的能力。

作为前端的该关注的

如果你在百度或者知乎搜索这个问题,十有八九会被劝退,因为这些答案不是面向前端的。答案里大多包含数学公式、算法、以及大神的入门视频课程。诚然良好的基础确实决定了未来能走多远。但是我们需要明确的是:我们并不是要转行当算法工程师,更不是去发明一个新的模型算法,我们要学习的只是合理的调用大神封装好的算法来服务于业务。 俗称调包侠,真正做研究的屈指可数,就好比咱们前端都用react、vue但是也不需要自己开发它一样,你不懂原理也可以用它做需求。

在入门前你只需要具备:

  • 基本的矩阵运算知识(加减乘除)
  • python基础(虽然我们最后是用jsAPI,但是学习过程中很多case都是python实现,起码你得看懂)
  • 好像...没了

PS:后面所推荐的文章,都是基于此基础上保证能理解的,没有高深的数学公式。

什么是神经网络?什么是深度学习?

为了让计算机能识别出一张照片是小狗还是小猫,我们得准备10000张照片给它学,但是计算机只认识数字,所以我们需要把照片的每一个像素点色值转换成数字,最终100*100像素的照片被转换为一个二维矩阵,通过矩阵相乘使得输入向量空间多次变换,从而能找到非线性的关系。
神经网络的本质就是一个y=f(x)的函数,x就是照片,y就是小狗,训练就是通过算法不断的反复调用调整样本参数,最终找到一个损失值(loss)最小的拟合函数,深度学习就是一个多层的神经网络。

!! 必看 !! 《从神经元到深度学习》:非常简单易懂的描述了神经网络与深度学习的发展历史,一字不落地通读两遍会让你对神经网络有一个初步的认知。

《AiLearning》这是一个系列教程,从python基础到机器学习的分类,什么是监督学习非监督学习,什么是回归分类问题,里面还包含了卷积神经网络(CNN)、循环神经网络(RNN)、长短时序网络(LSTM)等高阶模型的原理解析,但是这部分设计到数学公示推导,看不懂可以不看,起码能知道这些神经网络是用来干嘛的,以及它们相较于普通的多层神经网络的优点在哪。后面我们使用tensorflow进行模型开发的时候这些已经都有相应的封装。

深度学习在工程上的运用

  • 方案1:目前最为广泛的实现方式。算法测用python的深度学习框架来构造模型,依赖于底层大数据样本来训练,最后透出模型调用接口给服务端,前端需要做预测、分类的时候把内容通过接口提交给服务端,服务端调用算法,得到结果返回给前端。前端要做的就是调接口等返回。

    优势:训练样本数据量大,模型拟合更准,适用于大部分常规场景。
    劣势:涉及的服务接口层面多。

  • 方案2:算法侧训练模型不变,但是最后需要把模型转换为前端所需要的格式导出(官方提供了模型转换工具pip install tensorflowjs),省去了服务端。前端通过tensorflow.js加载已经训练好的模型,在浏览器里执行作出预测(前端通过tf.loadLayersModel加载keras模型)。
    在此方案中,也可以直接使用tensorflow.js在Node.js环境里训练模型,直接导出给前端。不管是python还是JS都是胶水语言,提供的只是上层的API,数据计算过程都是由底层C++调用GPU算力执行。

    优势:能够在离线场景进行预测(比如用户发布一段视频,在上传的等待过程就可以根据视频帧信息作智能推荐)。
    劣势:如果是非常复杂的模型,资源会比较大,需要预加载,对网络开销与浏览器内存有占用。

  • 方案3:前端直接在浏览器内通过tensorflow.js进行训练(需要浏览器支持WebGL),模型训练完成后进行预测。

    优势:充分利用端侧资源,能够根据用户提供的样本实时训练可变的模型。
    劣势:局限于样本数量、端侧GPU计算能力,不适合行复杂的高阶模型训练。

如何上手Tensorflow

理论知识基本了解后尽快进行实战是学习一门新技术的最好办法,在实战的中我们再来反向回补不足的理论知识。

Tensorflow是谷歌封装的一套机器学习所用的框架,它有多个编程语言版本。

keras是对tensorflow的又一层高级封装,简单来说使用keras API对编程能力要求基本没有了。目前keras已经集成到官方tensorflow API了,而且我们后面使用tensorflow.js的时候,直接就完全支持keras API,也意味着在python训练的模型代码,可以很便捷的改写为JS版本。

这是一个对输入图片进行识别的简单多层神经网络模型训练:

# cv.py
import tensorflow as tf
import numpy as np
from tensorflow import keras
# 获取训练数据集
fashion_mnist = keras.datasets.fashion_mnist
# 将数据集结构为训练样本数据,以及测试样本数据
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
# 数据归一化:每个图片原始二维矩阵的值为色值,我们先转换为0到1的小数,最后预测的时候再转回来
train_images = train_images / 255.0
test_images = test_images / 255.0
# 开始构建模型层
model = keras.Sequential([
    # 第一层将图片矩阵(28*28像素)展平为一位数组
    keras.layers.Flatten(input_shape=(28, 28)),
    # 第二层为隐藏层,设置128个神经元,并使用激活函数 relu 进行矩阵变换
    keras.layers.Dense(128, activation='relu'),
    # 最后一层为全连接输出层,目标为0-10每个数值的概率,因为我们原数据集中有10个类型的图片数据
    keras.layers.Dense(10)
])
# 打印层级详情信息
model.summary()
# 编译模型
model.compile(
    # 选择优化器
    optimizer='adam',
    # 选择损失函数
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    # 准确率函数
    metrics=['accuracy']
)
# 循环训练次数为10次,开始训练
model.fit(train_images, train_labels, epochs=10)
# 测试评估训练好的模型
test_loss, test_acc = model.evaluate(test_images,  test_labels, verbose=1)
# 具体到测试数据中第一条返回的预测结果
predictions = model.predict(test_images)
result = predictions[0]
# 打印预测结果
print(result)
print(np.argmax(result))

执行上面的python文件控制台会打印出模型构造、训练、测试结果的每一步:

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
flatten (Flatten)            (None, 784)               0         
_________________________________________________________________
dense (Dense)                (None, 128)               100480    
_________________________________________________________________
dense_1 (Dense)              (None, 10)                1290      
=================================================================
Total params: 101,770
Trainable params: 101,770
Non-trainable params: 0
_________________________________________________________________
Epoch 1/10
1875/1875 [==============================] - 1s 784us/step - loss: 0.4979 - accuracy: 0.8251
Epoch 2/10
1875/1875 [==============================] - 1s 738us/step - loss: 0.3759 - accuracy: 0.8623
Epoch 3/10
1875/1875 [==============================] - 2s 820us/step - loss: 0.3392 - accuracy: 0.8766
Epoch 4/10
1875/1875 [==============================] - 1s 728us/step - loss: 0.3122 - accuracy: 0.8865
Epoch 5/10
1875/1875 [==============================] - 2s 839us/step - loss: 0.2950 - accuracy: 0.8916
Epoch 6/10
1875/1875 [==============================] - 1s 700us/step - loss: 0.2800 - accuracy: 0.8965
Epoch 7/10
1875/1875 [==============================] - 1s 636us/step - loss: 0.2696 - accuracy: 0.9011
Epoch 8/10
1875/1875 [==============================] - 1s 640us/step - loss: 0.2577 - accuracy: 0.9049
Epoch 9/10
1875/1875 [==============================] - 1s 717us/step - loss: 0.2490 - accuracy: 0.9081
Epoch 10/10
1875/1875 [==============================] - 2s 805us/step - loss: 0.2380 - accuracy: 0.9114
313/313 [==============================] - 0s 488us/step - loss: 0.3228 - accuracy: 0.8846
[-11.414778   -10.971654   -10.141903   -12.772112    -9.676536
  -1.9003754   -6.694176    -0.34978372  -7.149466     3.345558  ]
9

前面几行显示了模型的层数以及每层输出格式,然后就是训练10次的过程,倒数第三行显示了模型训练完成后用测试数据进行测试得到的损失值以及正确率。倒数第二行打印除了具体的一条数据每种类型的概率,最后得出索引为9概率最高,那么我们就看原始数据标签中9对应的是什么图片类型,这个就是计算机给出的识别结果。

基本上所有的模型训练,在使用keras API的情况下都是如此的清晰明了。只是层数和参数的设置不一样。那么问题来了,上面这么参数都该怎么传入呢?你最终会发现做深度学习编程能力并不是关键,你想用的算法模型都有现成的。你真正需要学习的是如何选择正确的模型,并且将各种参数设置为最合适的值,而这也是困难所在,它需要一定的经验积累以及对模型原理认知。因为同样的模型下,不同的神经网络层数、神经元个数、训练回归次数,都会导致结果出现欠拟合或者过拟合。这里只能说:无他,但手熟尔。

当我们仔细思考后会发现,如果图片的尺寸变大,模型的矩阵运算会指数级递增,计算将变得不可实现。这时候你就会探索到卷积神经网络(CNN)更适合用于作图像模型的建设,它的详细原理在之前的分享连接里有,在使用之前务必先了解原理,一个卷积神经网络的层数会更多(包含了卷积层和池化层),数据格式也有一维变成了三维,就像这样:

model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10))

所以说我们才需要在尝试中发现问题,再寻找解决方案。看完整本理论书籍再开始实践是非常糟糕的选择,一来你不知道途中会遇到哪些问题,二来越来越深入的知识点会让你提前放弃。

更多像这种高阶神经网络模型可以在入门后再去慢慢了解,在此过程中可以参考 Tensorflow中文文档

使用Javascript训练、调用模型

本质上和python的tensorflow.kearas没有区别,只是python语法换成了js而已,比如构建一个包含两个隐藏层的多层神经网络:

model.js
import * as tf from '@tensorflow/tfjs';

function tf_model() {
  const model = tf.sequential();
  model.add(
    tf.layers.dense({
      units: 32, inputShape: [784]
    })
  );
  model.add(
    tf.layers.dense({
      units: 256
    })
  );
  model.add(
    tf.layers.dense({
      units: 10, 
      kernelInitializer: 'varianceScaling', 
      activation: 'softmax'
    })
  );
  return model;
}

除此之外,我们还能加载训练好的远程的模型文件,或者将训练的模型保存在本地indexDB里,以及在node.js中使用CUDA计算能力。更多的API可参照Tensorflow.js中文文档,关于API调用这对于前端来讲不是问题。

知乎有个大佬写的专栏《Tensorflow.js》系列是我目前发现的比较棒的实践案例,从最基本的机器学习模型到复杂的LSTM时序预测都有代码讲解。

总结

本文重点在于给想入门人工智能的前端工程师一些学习路线,与相关的资源推荐,并没有详细的教授深度学习的细节或者代码实现等。一来社区本身有很多已有的优秀教学文章;二来我水平有限教授不了。
其次关于深度学习在前端领域的应用场景也是值得思考的一个点,但是换个角度来想,一个没有被广泛使用的技术就意味着机会与创造力。

在此之前我们要努力成为合格的调包侠。

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

推荐阅读更多精彩内容

  • TensorFlow.js 的发布可以说是 JS 社区开发者的福音!但是在浏览器中训练一些模型还是会存在一些问题与...
    强哥科技兴阅读 585评论 0 1
  • 过春节前一周,不知从哪里看到优达学城(Udacity)的深度学习(Deep learning)课程在搞优惠活动,抱...
    bmy阅读 9,346评论 5 33
  • 姓名:苗春雨 学号:16019110036 转载自:http://blog.csdn.net/anymake_...
    MASTER__TONY阅读 844评论 0 8
  • 久违的晴天,家长会。 家长大会开好到教室时,离放学已经没多少时间了。班主任说已经安排了三个家长分享经验。 放学铃声...
    飘雪儿5阅读 7,458评论 16 22
  • 创业是很多人的梦想,多少人为了理想和不甘选择了创业来实现自我价值,我就是其中一个。 创业后,我由女人变成了超人,什...
    亦宝宝阅读 1,796评论 4 1