0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

TensorFlow.js 的基本构建块及其操作,如何创建一些复杂的模型

Tensorflowers 来源:未知 作者:李倩 2018-08-01 11:37 次阅读

这创造了一个标量张量。我们还可以将数组转换为张量。

Tensorflow.js 是一个基于 deeplearn.js 构建的库,可直接在浏览器环境中创建深度学习模型。使用它可以在浏览器上创建 CNNs,RNNs 等,并使用客户端的 GPU 处理能力训练这些模型。因此,训练 NN 并不一定需要服务器级别的 GPU。本教程首先解释 TensorFlow.js 的基本构建块及其操作。然后,我们描述了如何创建一些复杂的模型。

我在 Observable 上创建了一个交互式编码会话,可用于代码演示。此外,我创建了许多迷你项目,包括简单分类,样式转换,姿势评估和 pix2pix 翻译。

入门

由于 TensorFlow.js 在浏览器上运行,您只需将以下脚本包含在 html 文件的 header 中即可:

1

以上会自动加载最新版本的 TensorFlow.js。

张量(Tensor)

如果您熟悉 TensorFlow 等深度学习平台,您应该能够认识到张量是 Operators 使用的 n 维数组。因此,它们代表了任何深度学习应用程序的构建块。让我们创建一个张量:

1const tensor = tf.scalar(2);

以上创建了一个张量。我们还可以将数组转换为张量:

1const input = tf.tensor([2,2]);

这会创建一个恒定的数组张量[2,2]。换句话说,我们通过应用张量函数将一维数组转换为张量。我们可以使用 input.shape 获取张量大小。

1const tensor_s = tf.tensor([2,2]).shape;

我们还可以创建具有特定大小的张量:

1const input = tf.zeros([2,2]);

操作(Operators)

为了使用张量,我们需要创建操作。如下所示,可以获取到张量的平方:

1const a = tf.tensor([1,2,3]);

2a.square().print();

TensorFlow.js 还允许链接操作。例如,要评估我们使用的张量的二次幂:

1const x = tf.tensor([1,2,3]);

2const x2 = x.square().square();

Tensor Disposal

通常我们会生成大量的中间张量。例如,在前面的例子中,我们不需要生成 const x。为了做到这一点,我们可以调用 dispose():

1const x = tf.tensor([1,2,3]);

2x.dispose();

请注意,我们在以后的操作中不再使用张量 x。现在,对于每个张量来说,这可能有点不方便。

TensorFlow.js 提供了一个特殊的操作 tidy() 来自动处理中间张量:

1function f(x)

2{

3return tf.tidy(()=>{

4const y = x.square();

5const z = x.mul(y);

6return z

7});

8}

请注意,张量 y 的值将被处理,因为我们在评估 z 的值之后不再需要它。

优化问题

在这里,我们将学习如何解决优化问题。给定函数 f(x),基于 x = a 评估最小化 f(x)。为此,我们需要一个优化器。优化器是一种通过渐变来最小化函数的算法。文献中有许多优化器,如 SGD,Adam 等......这些优化器的速度和准确性各不相同。Tensorflowjs 支持最重要的优化器。

我们将举一个简单的例子:f(x)=x⁶+2x⁴+3x²+ x + 1。函数图如下所示。我们看到函数的最小值在区间内 [-0.5,0] 。我们将使用优化器来查找确切的值。

首先,我们定义需要最小化的函数

1function f(x)

2{

3const f1 = x.pow(tf.scalar(6, 'int32')) //x^6

4const f2 = x.pow(tf.scalar(4, 'int32')).mul(tf.scalar(2)) //2x^4

5const f3 = x.pow(tf.scalar(2, 'int32')).mul(tf.scalar(3)) //3x^2

6const f4 = tf.scalar(1) //1

7return f1.add(f2).add(f3).add(x).add(f4)

8}

现在我们可以迭代该函数以找到最小值。我们将以 a = 2 的初始值开始。学习速率定义了我们达到最小值的速度。我们将使用 Adam 优化器

1function minimize(epochs , lr)

2{

3let y = tf.variable(tf.scalar(2)) //initial value

4const optim = tf.train.adam(lr); //gadient descent algorithm

5for(let i = 0 ; i < epochs ; i++) //start minimiziation     

6optim.minimize(() => f(y));

7return y

8}

当学习速率为 0.9 时,迭代 200 次之后找到最小值 -0.16092407703399658。

一个简单的神经网络

现在我们学习如何创建一个神经网络来学习 XOR,这是一个非线性操作。代码类似于 keras 实现。我们首先创建了两个输入和一个输出的训练集。

1xs = tf.tensor2d([[0,0],[0,1],[1,0],[1,1]])

2ys = tf.tensor2d([[0],[1],[1],[0]])

然后我们创建两个具有不同非线性激活函数的密集层。我们使用具有交叉熵损失的随机梯度下降。学习速率是 0.1

1function createModel()

2{

3var model = tf.sequential()

4model.add(tf.layers.dense({units:8, inputShape:2, activation: 'tanh'}))

5model.add(tf.layers.dense({units:1, activation: 'sigmoid'}))

6model.compile({optimizer: 'sgd', loss: 'binaryCrossentropy', lr:0.1})

7return model

8}

然后我们对模型进行 5000 次迭代

1await model.fit(xs, ys, {

2batchSize: 1,

3epochs: 5000

4})

最后我们预测训练集

1model.predict(xs).print()

输出预期应该是 [[0.0064339], [0.9836861], [0.9835356], [0.0208658]]。

CNN 模型

TensorFlow.js 使用计算图来自动区分。我们只需要创建图层,优化器并编译模型。让我们创建一个顺序模型:

1model = tf.sequential();

现在我们可以为模型添加不同的图层。让我们添加带输入的第一个卷积层 [28,28,1]

1const convlayer = tf.layers.conv2d({

2inputShape: [28,28,1],

3kernelSize: 5,

4filters: 8,

5strides: 1,

6activation: 'relu',

7kernelInitializer: 'VarianceScaling'

8});

在这里,我们创建了一个 convlayer 接受输入图层为 [28,28,1]。输入将是大小为 28 x 28 的灰色图像。然后我们对其进行初始化。之后,我们应用一个激活函数,它基本上取张量中的负值并用零替换它们。现在我们可以将此 convlayer 添加到模型中:

1model.add(convlayer);

使用 Tensorflow.js 我们不需要为下一层指定输入大小,因为在编译模型后它将自动评估。我们还可以添加最大池,密集层等。这是一个简单的模型:

1const model = tf.sequential();

2

3//create the first layer

4model.add(tf.layers.conv2d({

5inputShape: [28, 28, 1],

6kernelSize: 5,

7filters: 8,

8strides: 1,

9activation: 'relu',

10kernelInitializer: 'VarianceScaling'

11}));

12

13//create a max pooling layer

14model.add(tf.layers.maxPooling2d({

15poolSize: [2, 2],

16strides: [2, 2]

17}));

18

19//create the second conv layer

20model.add(tf.layers.conv2d({

21kernelSize: 5,

22filters: 16,

23strides: 1,

24activation: 'relu',

25kernelInitializer: 'VarianceScaling'

26}));

27

28//create a max pooling layer

29model.add(tf.layers.maxPooling2d({

30poolSize: [2, 2],

31strides: [2, 2]

32}));

33

34//flatten the layers to use it for the dense layers

35model.add(tf.layers.flatten());

36

37 //dense layer with output 10 units

38model.add(tf.layers.dense({

39units: 10,

40kernelInitializer: 'VarianceScaling',

41activation: 'softmax'

42}));

为了检查输出张量,我们可以为任何层应用张量。但是这里的输入需要的是一个形状为[BATCH_SIZE,28,28,1],其中BATCH_SIZE表示我们一次应用于模型的数据集元素的数量。以下是如何评估卷积层的示例:

1const convlayer = tf.layers.conv2d({

2inputShape: [28, 28, 1],

3kernelSize: 5,

4filters: 8,

5strides: 1,

6activation: 'relu',

7kernelInitializer: 'VarianceScaling'

8});

9

10const input = tf.zeros([1,28,28,1]);

11const output = convlayer.apply(input);

在检查 output 张量的形状后,我们看到它的形状为 [1,24,24,8]。使用公式评估:

1const outputSize = Math.floor((inputSize-kernelSize)/stride +1);

回到我们的模型,我们意识到我们使用的 flatten() 基本上将输入从形状 [BATCH_SIZE,a,b,c] 转换为形状 [BATCH_SIZE,axbxc]。这很重要,因为在密集层中我们不能应用 2d 数组。最后,我们使用了带有输出单元的密集层,10 代表了我们识别系统中所需的类别。实际上,该模型用于识别所谓的 MNIST 数据集中的手写数字。

优化和编译

创建模型后,我们需要一种优化参数的方法。像 SGD 和 Adam 优化器都有不同的方法。如下所示创建优化器:

1const LEARNING_RATE = 0.0001;

2const optimizer = tf.train.adam(LEARNING_RATE);

这将使用指定的学习速率创建 Adam 优化器。现在,我们已准备好编译模型

1model.compile({

2optimizer: optimizer,

3loss: 'categoricalCrossentropy',

4metrics: ['accuracy'],

5});

在这里,我们创建了使用 Adam 来优化损失函数的模型,该函数评估预测输出和真实标签的交叉熵。

训练

在编译模型之后,我们准备在数据集上训练模型。我们需要使用 fit() 函数:

1const batch = tf.zeros([BATCH_SIZE,28,28,1]);

2const labels = tf.zeros([BATCH_SIZE, NUM_CLASSES]);

3

4const h = await model.fit(batch, labels,

5{

6batchSize: BATCH_SIZE,

7validationData: validationData,

8epochs: BATCH_EPOCHs

9});

10

请注意,我们正在为一组训练集提供 fit 函数。fit 函数的第二个变量表示模型的真实标签。最后,我们有配置参数,如 batchSize 和 epochs。请注意,它 epochs 表示我们迭代当前批次而不是整个数据集的次数。因此,我们可以将该代码包装在 for 循环中,该循环遍历训练集的所有批次。

注意我们使用了特殊的关键字 await,它阻塞并等待函数执行完成。这就像运行另一个线程,主线程正在等待拟合函数完成执行。

热编码

通常给定的标签是代表该类的数字。例如,假设我们有两个类,一个橙色类和一个苹果类。然后我们将给出橙色类标签 0 和苹果类标签 1。但是,我们的网络接受一个大小为 [BATCH_SIZE,NUM_CLASSES] 的张量。因此,我们需要使用热编码:

1const output = tf.oneHot(tf.tensor1d([0,1,0]), 2);

2

3//the output will be [[1, 0],[0, 1],[1, 0]]

4

5

因此,我们将 1d 张量标签转换为张量形状[BATCH_SIZE,NUM_CLASSES]。

损失和准确性

为了检查我们模型的性能,我们需要知道损失和准确性。为此,我们需要使用历史模型获取结果。

1//h is the output of the fitting module

2const loss = h.history.loss[0];

3const accuracy = h.history.acc[0];

请注意,我们正在评估 validationData 的损失性和准确性。

预测

假设我们完成了对模型的训练,并且给出了良好的损失和准确性。是时候预测看不见的数据元素的结果了。假设我们的浏览器中有一个图像,或者我们直接从我们的网络摄像头拍摄,那么我们就可以使用我们训练有素的模型来预测它的类。首先,我们需要将图像转换为张量

1//retrieve the canvas

2const canvas = document.getElementById("myCanvas");

3const ctx = canvas.getContext("2d");

4

5//get image data

6imageData = ctx.getImageData(0, 0, 28, 28);

7

8//convert to tensor

9const tensor = tf.fromPixels(imageData);

在这里我们创建了一个 canvas 并从中获取imageData,然后我们转换为张量。现在张量大小为 [28,28,3] 但模型采用 4 维向量。因此,利用 expandDims 我们可以为张量添加额外的维度。

1const eTensor = tensor.expandDims(0);

因此,输出张量大小为 [1,28,28,3] 因为我们在索引 0 处添加了维度。现在我们使用 predict() 进行预测。

1model.predict(eTensor);

函数 predict 将返回我们最后一层的值。

转移学习

在前面的部分中,我们必须从头开始训练我们的模型。然而,这是一项昂贵的操作,因为它需要更多的训练迭代。因此,我们使用称为 mobilenet 的预训练模型。它是一款轻巧的 CNN,经过优化可在移动应用中运行。Mobilenet 受过 ImageNet 训练。

要加载模型,如下所示:

1const mobilenet = await tf.loadModel(

2 'https://storage.googleapis.com/tfjs-models/tfjs/mobilenet_v1_0.25_224/model.json');

我们可以使用输入,输出来检查模型的结构:

1//The input size is [null, 224, 224, 3]

2const input_s = mobilenet.inputs[0].shape;

3

4//The output size is [null, 1000]

5const output_s = mobilenet.outputs[0].shape;

6

因此,我们需要大小为 [1,224,224,3] 的图像,输出将是一个大小为 [1,1000] 的张量,它保存 ImageNet 数据集中每个类的概率。

为了简便起见,我们将采取零值数组,并试图预测出 1,000 种类别。

1var pred = mobilenet.predict(tf.zeros([1, 224, 224, 3]));

2pred.argMax().print();

运行代码后,我得到 class = 21:

现在我们需要检查模型的内容。为此,我们可以获得模型图层和名称:

1//The number of layers in the model '88'

2const len = mobilenet.layers.length;

3

4//this outputs the name of the 3rd layer 'conv1_relu'

5const name3 = mobilenet.layers[3].name;

当基于另一个数据集再次训练具有 88 个图层的模型时,是非常昂贵的。因此,基本的技巧是使用这个模型来评估激活(我们不会重新训练)。

假设我们需要一个模型来区分胡萝卜和黄瓜。我们将使用 mobilene tmodel 来计算我们选择的某个层的激活。然后我们使用具有输出大小为 2 的密集层来预测正确的类。因此,我们只需要训练密集层。

首先,我们需要摆脱模型的密集层。

1const layer = mobilenet.getLayer('conv_pw_13_relu');

现在让我们更新我们的模型,让这个图层成为一个输出

1mobilenet = tf.model({inputs: mobilenet.inputs, outputs: layer.output});

最后,我们创建了可训练模型,但我们需要知道最后一层输出形状:

1//this outputs a layer of size [null, 7, 7, 256]

2const layerOutput = layer.output.shape;

我们看到形状为 [null,7,7,256],现在我们可以将它输入到我们的密集层:

1trainableModel = tf.sequential({

2layers: [

3tf.layers.flatten({inputShape: [7, 7, 256]}),

4tf.layers.dense({

5units: 100,

6activation: 'relu',

7kernelInitializer: 'varianceScaling',

8useBias: true

9}),

10tf.layers.dense({

11units: 2,

12kernelInitializer: 'varianceScaling',

13useBias: false,

14activation: 'softmax'

15})

16]

17});

如您所见,我们创建了一个带有 100 个神经元的密集层和带有大小为 2 的输出层。

1const activation = mobilenet.predict(input);

2const predictions = trainableModel.predict(activation);

我们可以使用前面的部分来使用某个优化器训练模型。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 神经网络
    +关注

    关注

    42

    文章

    4771

    浏览量

    100752
  • 深度学习
    +关注

    关注

    73

    文章

    5503

    浏览量

    121151
  • tensorflow
    +关注

    关注

    13

    文章

    329

    浏览量

    60532

原文标题:TensorFlow.js 入门指南

文章出处:【微信号:tensorflowers,微信公众号:Tensorflowers】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    如何使用TensorFlow构建机器学习模型

    在这篇文章中,我将逐步讲解如何使用 TensorFlow 创建个简单的机器学习模型
    的头像 发表于 01-08 09:25 984次阅读
    如何使用<b class='flag-5'>TensorFlow</b><b class='flag-5'>构建</b>机器学习<b class='flag-5'>模型</b>

    使用 TensorFlow, 你必须明白 TensorFlow

    , 通常在构建阶段创建个图来表示和训练神经网络, 然后在执行阶段反复执行图中的训练 op.TensorFlow 支持 C, C++, Python 编程语言. 目前,
    发表于 03-30 20:03

    高阶API构建模型和数据集使用

    TensorFlow2.0Beta版本,同pytorch样支持动态执行(TensorFlow2.0默认eager模式,无需启动会话执行计算图),同时删除了杂乱低阶API,使用高阶API简单地
    发表于 11-04 07:49

    CAM 350一些基本操作

    CAM 350一些基本操作 G
    发表于 01-25 11:26 2233次阅读

    TensorFlow发表推文正式发布TensorFlow v1.9

    其中有两个案例受到了大家的广泛关注,这个项目是通过 Colab 在 tf.keras 中训练模型,并通过TensorFlow.js 在浏览器中运行;最近在 JS 社区中,对这些相关项目的高度需求
    的头像 发表于 07-16 10:23 3114次阅读

    利用TensorFlow.js,D3.js 和 Web 的力量使训练模型的过程可视化

    TensorFlow.js 将机器学习引入 JavaScript 和 Web。 我们将利用这个很棒的框架来构建个深度神经网络模型。这个模型
    的头像 发表于 08-08 14:24 6989次阅读

    如何使用TensorFlow.js构建系统

    TensorFlow.js团队直在进行有趣的基于浏览器的实验,以使人们熟悉机器学习的概念,并鼓励他们将其用作您自己项目的构建。对于那些不熟悉的人来说,
    的头像 发表于 08-19 08:55 3557次阅读

    基于tensorflow.js设计、训练面向web的神经网络模型的经验

    NVIDIA显卡。tensorflow.js在底层使用了WebGL加速,所以在浏览器中训练模型个好处是可以利用AMD显卡。另外,在浏览器中训练模型,可以更好地保护用户隐私,更容易让
    的头像 发表于 10-18 09:43 4105次阅读

    Shadow Art: 颂扬中国皮影戏艺术的 AI 实验

    在本文中,我们将探讨我们如何利用 TensorFlow.js 构建 Shadow Art。
    的头像 发表于 03-15 16:21 5510次阅读

    Google LLC开源TensorFlow Quantum

    这就是TensorFlow Quantum出现的地方。它提供了组运算符,低级编程构造,用于创建可与qubit,量子逻辑门和量子电路配合使用的AI
    的头像 发表于 03-22 15:13 3268次阅读

    TensorFlow.js制作了个仅用 200 余行代码的项目

    我们先来看下运行的效果。下图中,上半部分是原始视频,下半部分是使用 TensorFlow.js 对人像进行消除后的视频。可以看到,除了偶尔会在边缘处留有残影之外,整体效果还是很不错的。
    的头像 发表于 05-11 18:08 5593次阅读

    Danfo.js提供高性能、直观易用的数据结构,支持结构化数据的操作和处理

    我们的愿景致,本质上也符合 TensorFlow.js 团队向 Web 引入 ML 的目标。Numpy 和 Pandas 等开源库全面革新了 Python 中数据操作的便利性。因此很多工具都围绕它们构
    的头像 发表于 09-23 18:21 5291次阅读

    如何基于 ES6 的 JavaScript 进行 TensorFlow.js 的开发

    从头开发、训练和部署模型,也可以用来运行已有的 Python 版 TensorFlow 模型,或者基于现有的模型进行继续训练。 TensorFlo
    的头像 发表于 10-31 11:16 3121次阅读

    TensorFlow主题演讲中涉及的一些更新总结

    Google 开发者 Youku 频道上找到所有主题演讲的视频。以下是按产品领域列出的一些更新摘要(视频中还有更多产品更新要点,请务必查看)。 移动版和网站版 TensorFlow
    的头像 发表于 05-28 14:19 1868次阅读

    keras模型tensorflow session

    在这篇文章中,我们将讨论如何将Keras模型转换为TensorFlow session。 Keras和TensorFlow简介 Keras是个高级神经网络API,它提供了
    的头像 发表于 07-05 09:36 533次阅读