TensorFlow.js 入门
如果您像我一样,一直想知道什么是机器学习(又名 ML),并且摆脱了所有那些数学术语,那么这是一个激动人心的时刻,因为它TensorFlow.js
可以为您提供帮助。
您可以在此处找到此帖子的代码。
简介
我从事前端开发多年,也对机器学习和人工智能充满好奇。然而,由于我一直很忙,而且大多数机器学习框架都是用我从未接触过的语言编写的,所以一直没有机会深入研究。
如今,情况已经发生了变化,人们现在在移动设备或浏览器中使用机器学习。TensorFlow.js
它是一个允许我们在浏览器或 中创建、训练和部署 ML 模型的库Node.js
。说实话,我对此感到非常兴奋,因为它让我可以玩转模型和神经网络,而无需深入底层或学习一门新语言🤯。
别误会,我并不害怕学习一门新语言,事实上,学习语言也是我的爱好之一。但由于我最近忙于各种事务,根本没时间深入研究这个领域。
这个库的好处在于,您不需要具备 ML 方面的先验知识,您只需处理一些为您简化了很多概念的高级 API,这样您就可以专注于部署模型和解决问题,而不是重新发明轮子🔥。
但还有更多选择,为我们带来了更多机会。基本上你可以:
- 导入预先训练的模型并使用它(预测或部署它)
- 导入预先训练的模型(Keras 或 Python)并使用数据集进行训练
- 创建、训练、预测和部署隐私友好模型(数据永远不会离开应用程序)
- 可能还有更多我不知道的事情🤷。
核心概念
在进一步了解如何使用它之前,我们需要熟悉一些基本概念,以便达成共识。
张量
数据的核心单位TensorFlow.js
是张量:一组数值,被塑造成一个或多个维度的数组。Tensor
实例具有一个shape属性,该属性定义数组shape
(即数组每个维度上有多少个值)。
变量
变量用一个张量值来初始化。然而,与张量不同的是,变量的值是可变的。
运营(Ops)
张量允许您存储数据,而操作 (ops) 允许您操作这些数据。TensorFlow.js
提供了各种适用于线性代数和机器学习的可在张量上执行的操作。由于张量是不可变的,这些操作不会改变其值;相反,操作会返回新的张量。
模型和层
从概念上讲,模型是一个函数,给定一些输入,它将产生一些期望的输出。TensorFlow.js
创建模型有两种方法。你可以直接使用操作符 (ops) 来表示模型所做的工作。
或者您可以使用高级 APItf.model
来构建层模型,这是深度学习中流行的抽象。
警告:由于TensorFlow.js
使用 GPU 加速数学运算,因此在处理张量和变量时需要管理 GPU 内存。它提供了两个函数来帮助实现这一点:dispose
和tf.tidy
。我们稍后会深入探讨这两个函数。
如何使用预先训练的模型
您可以使用广受欢迎的Keras Python 库中的预训练模型进行预测。这意味着您无需成为数据科学家即可使用这些模型,甚至可以构建强大的机器学习应用。
幸运的是,有许多可用且随时可用的模型,它们通过 公开TensorFlow.js
。为此,您需要使用TensorFlow.js converter
一个开源库,将预先训练的模型加载到 可以理解的格式中TenserFlow.js
。
注意:为此,您需要了解一点Python知识并将其安装在本地。
您需要执行两个操作才能获得一个可立即使用的模型。首先,将模型保存在本地,然后运行转换器进行转换。但我找到了一种更简单的方法,不需要运行转换。转换逻辑已经在tensorflowjs
Python 包中实现了😁,所以我就直接用它吧。
保存模型
让我们来看一个例子,假设我们要导入MobileNet网络(用于检测图像中的物体)并将其保存在本地。首先,按照此处的说明安装先决条件。
然后我们可以编写下面的代码将模型保存在本地:
from keras.applications import mobilenet
import tensorflowjs as tfjs
mobilenet = mobilenet.MobileNet()
save_path = "output\\mobilenet"
tfjs.converters.save_keras_model(mobilenet, save_path)
mobilenet
运行此程序后,文件夹中应该有一个output
包含以下文件的文件夹:
猜猜看,您已经准备好使用它并编写您的第一个TensorFlow.js
应用程序了。
如果您热衷于使用 CLI 命令转换模型,请查看本教程。
在您的应用程序中使用模型
我在示例中使用了Angular ,但您可以随意使用您喜欢的任何框架,甚至是原始 JS 🙃。
创建应用程序
我已经安装了 Angular CLI,因此我只需打开命令提示符并创建一个新的应用程序:
ng new mobilenet
cd mobilenet
安装 TensorFlow.js
这需要一些时间(创建应用并安装所有 npm 包)。完成后,TensorFlow.js
也添加以下包:
npm install @tensorflow/tfjs --save
完成后,将保存的模型的内容复制到资产文件夹中,然后使用您选择的编辑器(VS Code😁)打开该文件夹。
您还需要图像类别用于预测。因此,请在项目中的某个位置创建一个文件,并将该文件的内容添加到其中。我已将其放在我的 assets 文件夹中。
导入模型并使用它
打开app.component.ts
文件并添加导入语句:
import * as tf from '@tensorflow/tfjs';
import { IMAGENET_CLASSES } from '../assets/imagenet-classes';
我们需要一些变量来保存我们的数据和一些我们必须使用的 HTML 元素的引用:
model: tf.Model;
classes: any[];
imageData: ImageData;
@ViewChild('chosenImage') img: ElementRef;
@ViewChild('fileUpload') fileUpload: ElementRef;
该模型将具有我们的模型,类用于我们的预测结果,并imageData
用于将我们的文件上传文件转换为它并在页面上的图像中显示它。
还有两个全局变量,图像大小是模型训练的大小,以及我们想要从预测结果中选择的预测数量(因为它是一个数组):
const IMAGE_SIZE = 224;
const TOPK_PREDICTIONS = 5;
是时候添加一个方法来加载模型并在其中调用它了ngOnInit
:
ngOnInit() {
this.loadModel();
}
async loadModel() {
this.model = await tf.loadModel('/assets/model.json');
}
我们需要在 HTML 中上传文件和添加图像,所以让我们添加它们:
<div class="container">
<h2>
Using MobileNet neural network in Angular
</h2>
<div class="upload" [hidden]="!model">
Upload an image:
<input
#fileUpload
type="file"
id="files"
name="files[]"
(change)="fileChangeEvent($event)"
/>
</div>
<div>
<img
#chosenImage
width="224"
height="224"
class="sample-image"
/>
<div class="predictions">
<div
*ngFor="let class of classes"
class="row"
>
<div class="col-sm-6">
{{class.className}}
</div>
<div class="col-sm-6">
{{class.probability.toFixed(3)}}
</div>
</div>
</div>
</div>
</div>
再用一点 CSS 让它更漂亮:
.container {
padding: 200px;
.sample-image {
margin: 20px;
}
.predictions {
margin-top: 20px;
width: 100%;
}
}
HTML 中的预测部分将包含预测结果,我们假设它存储在名为的变量中classes
。
现在让我们回到TypeScript
文件并添加预测代码。首先,为文件输入创建一个处理程序,它将触发我们的预测逻辑:
fileChangeEvent(event: any) {
const file = event.target.files[0];
if (!file || !file.type.match('image.*')) {
return;
}
this.classes = [];
const reader = new FileReader();
reader.onload = e => {
this.img.nativeElement.src = e.target['result'];
this.predict(this.img.nativeElement);
};
reader.readAsDataURL(file);
}
在这个方法中,我们所做的就是读取选定的文件,将其作为图像源放在页面上,以便页面能够看到所选的图像,然后调用预测方法。onload
由于必须先读取文件,因此我们在事件处理程序中异步调用了该方法。
现在让我们编写预测代码:
async predict(imageData: ImageData): Promise<any> {
this.fileUpload.nativeElement.value = '';
const startTime = performance.now();
const logits = tf.tidy(() => {
// tf.fromPixels() returns a Tensor from an image element.
const img = tf.fromPixels(imageData).toFloat();
const offset = tf.scalar(127.5);
// Normalize the image from [0, 255] to [-1, 1].
const normalized = img.sub(offset).div(offset);
// Reshape to a single-element batch so we can pass it to predict.
const batched = normalized.reshape([1, IMAGE_SIZE, IMAGE_SIZE, 3]);
// Make a prediction through mobilenet.
return this.model.predict(batched);
});
// Convert logits to probabilities and class names.
this.classes = await this.getTopKClasses(logits, TOPK_PREDICTIONS);
const totalTime = performance.now() - startTime;
console.log(`Done in ${Math.floor(totalTime)}ms`);
}
如果你乍一看不懂这里的代码,没关系。既然我们已经导入了模型,那么就需要了解一下它的内部原理。
首先,我使用tidy
前面提到的函数来确保我们没有任何内存泄漏。
然后我将图像转换为该模型所需的浮点数据类型。
完成后,我们需要将数据从 [0, 255] 范围归一化到 [-1, 1]。该scalar
操作会创建一个具有指定值的张量。
最后,我们需要将输入重塑为 [1, IMAGE_SIZE, IMAGE_SIZE, 3] 张量并调用预测。
一旦我们得到结果,我们就必须x
从结果中提取顶级类,所以让我们实现它:
async getTopKClasses(logits, topK): Promise<any[]> {
const values = await logits.data();
const valuesAndIndices = [];
for (let i = 0; i < values.length; i++) {
valuesAndIndices.push({ value: values[i], index: i });
}
valuesAndIndices.sort((a, b) => {
return b.value - a.value;
});
const topkValues = new Float32Array(topK);
const topkIndices = new Int32Array(topK);
for (let i = 0; i < topK; i++) {
topkValues[i] = valuesAndIndices[i].value;
topkIndices[i] = valuesAndIndices[i].index;
}
const topClassesAndProbs = [];
for (let i = 0; i < topkIndices.length; i++) {
topClassesAndProbs.push({
className: IMAGENET_CLASSES[topkIndices[i]],
probability: topkValues[i]
});
}
return topClassesAndProbs;
}
好的,记得我们调用了这个方法,并将 predict 的结果设置为 a 的形状logit
。Logits 通常是 a Tensor
、一个数组或一个类型数组。
基本上,我们通过等待方法获取结果data
。然后,我们使用该输出的值和索引创建一个新数组。
在此基础上,我们根据形成的数组计算出最终的类。同样,你不需要理解代码的作用,从高层次上讲,它只是将结果映射到我们之前从 GitHub 仓库获取的某个类上。
运行应用程序
您现在可以运行该应用程序并上传localhost:4200
图像,看看您得到了什么预测😎。
入门就是这么简单。希望你喜欢这篇指南,并能激励你去看看。
再次,您可以在此处找到此帖子的代码。
文章来源:https://dev.to/yashints/getting-started-on-tensorflow-js-4n5