基于TensorFlow.js的JavaScript机器学习


Credits: aijs.rocks

虽然python或r编程语言有一个相对容易的学习曲线,但是Web开发人员更喜欢在他们舒适的javascript区域内做事情。目前来看,node.js已经开始向每个领域应用javascript,在这一大趋势下我们需要理解并使用JS进行机器学习。由于可用的软件包数量众多,python变得流行起来,但是JS社区也紧随其后。这篇文章会帮助初学者学习如何构建一个简单的分类器。

扩展:
2019年11个javascript机器学习库
很棒的机器学习库,可以在你的下一个应用程序中添加一些人工智能!
Big.bitsrc.io

创建

我们可以创建一个使用tensorflow.js在浏览器中训练模型的网页。考虑到房屋的“avgareanumberofrows”,模型可以学习去预测房屋的“价格”。

为此我们要做的是:

加载数据并为培训做好准备。

定义模型的体系结构。

训练模型并在训练时监控其性能。

通过做出一些预测来评估经过训练的模型。

第一步:让我们从基础开始

创建一个HTML页面并包含JavaScript。将以下代码复制到名为index.html的HTML文件中。

<!DOCTYPE html>
<html>
<head><title>TensorFlow.js Tutorial</title><!-- Import TensorFlow.js --><script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.0.0/dist/tf.min.js"></script><!-- Import tfjs-vis --><script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-vis@1.0.2/dist/tfjs-vis.umd.min.js"></script><!-- Import the main script file --><script src="script.js"></script>
</head>
<body>
</body>
</html>

为代码创建javascript文件

在与上面的HTML文件相同的文件夹中,创建一个名为script.js的文件,并将以下代码放入其中。

console.log('Hello TensorFlow');

测试

既然已经创建了HTML和JavaScript文件,那么就测试一下它们。在浏览器中打开index.html文件并打开devtools控制台。

如果一切正常,那么应该在devtools控制台中创建并可用两个全局变量:

  • tf是对tensorflow.js库的引用
  • tfvis是对tfjs vis库的引用

现在你应该可以看到一条消息,上面写着“Hello TensorFlow”。如果是这样,你就可以继续下一步了。

需要这样的输出

注意:可以使用Bit来共享可重用的JS代码

Bit(GitHub上的Bit)是跨项目和应用程序共享可重用JavaScript代码的最快和最可扩展的方式。可以试一试,它是免费的:

组件发现与协作·Bit

Bit是开发人员共享组件和协作,共同构建令人惊叹的软件的地方。发现共享的组件…
Bit.dev

例如:Ramda用作共享组件

Ramda by Ramda·Bit

一个用于JavaScript程序员的实用函数库。-256个javascript组件。例如:等号,乘…
Bit.dev

第2步:加载数据,格式化数据并可视化输入数据

我们将加载“house”数据集,可以在这里找到。它包含了特定房子的许多不同特征。对于本教程,我们只需要有关房间平均面积和每套房子价格的数据。

将以下代码添加到script.js文件中。

async function getData() {Const houseDataReq=await
fetch('https://raw.githubusercontent.com/meetnandu05/ml1/master/house.json');  const houseData = await houseDataReq.json();  const cleaned = houseData.map(house => ({price: house.Price,rooms: house.AvgAreaNumberofRooms,})).filter(house => (house.price != null && house.rooms != null));return cleaned;
}

这可以删除没有定义价格或房间数量的任何条目。我们可以将这些数据绘制成散点图,看看它是什么样子的。

将以下代码添加到script.js文件的底部。

async function run() {// Load and plot the original input data that we are going to train on.const data = await getData();const values = data.map(d => ({x: d.rooms,y: d.price,}));tfvis.render.scatterplot({name: 'No.of rooms v Price'},{values}, {xLabel: 'No. of rooms',yLabel: 'Price',height: 300});// More code will be added below
}
document.addEventListener('DOMContentLoaded', run);

刷新页面时,你可以在页面左侧看到一个面板,上面有数据的散点图,如下图。

散点图

通常,在处理数据时,最好找到方法来查看数据,并在必要时对其进行清理。可视化数据可以让我们了解模型是否可以学习数据的任何结构。

从上面的图中可以看出,房间数量与价格之间存在正相关关系,即随着房间数量的增加,房屋价格普遍上涨。

第三步:建立待培训的模型

这一步我们将编写代码来构建机器学习模型。模型主要基于此代码进行架构,所以这是一个比较重要的步骤。机器学习模型接受输入,然后产生输出。对于tensorflow.js,我们必须构建神经网络。

将以下函数添加到script.js文件中以定义模型。

function createModel() {// Create a sequential modelconst model = tf.sequential(); // Add a single hidden layermodel.add(tf.layers.dense({inputShape: [1], units: 1, useBias: true}));// Add an output layermodel.add(tf.layers.dense({units: 1, useBias: true}));return model;
}

这是我们可以在tensorflow.js中定义的最简单的模型之一,我们来试下简单分解每一行。

实例化模型

const model = tf.sequential();

这将实例化一个tf.model对象。这个模型是连续的,因为它的输入直接流向它的输出。其他类型的模型可以有分支,甚至可以有多个输入和输出,但在许多情况下,你的模型是连续的。

添加层

model.add(tf.layers.dense({inputShape: [1], units: 1, useBias: true}));

这为我们的网络添加了一个隐藏层。因为这是网络的第一层,所以我们需要定义我们的输入形状。输入形状是[1],因为我们有1这个数字作为输入(给定房间的房间数)。

单位(链接)设置权重矩阵在层中的大小。在这里将其设置为1,我们可以说每个数据输入特性都有一个权重。

model.add(tf.layers.dense({units: 1}));

上面的代码创建了我们的输出层。我们将单位设置为1,因为我们要输出1这个数字。

创建实例

将以下代码添加到前面定义的运行函数中。

// Create the model
const model = createModel();  
tfvis.show.modelSummary({name: 'Model Summary'}, model);

这样可以创建实例模型,并且在网页上有显示层的摘要。

步骤4:为创建准备数据

为了获得TensorFlow.js的性能优势,使培训机器学习模型实用化,我们需要将数据转换为Tensors。

将以下代码添加到script.js文件中。

function convertToTensor(data) {return tf.tidy(() => {// Step 1. Shuffle the data    tf.util.shuffle(data);// Step 2. Convert data to Tensorconst inputs = data.map(d => d.rooms)const labels = data.map(d => d.price);const inputTensor = tf.tensor2d(inputs, [inputs.length, 1]);const labelTensor = tf.tensor2d(labels, [labels.length, 1]);//Step 3. Normalize the data to the range 0 - 1 using min-max scalingconst inputMax = inputTensor.max();const inputMin = inputTensor.min();  const labelMax = labelTensor.max();const labelMin = labelTensor.min();const normalizedInputs = inputTensor.sub(inputMin).div(inputMax.sub(inputMin));const normalizedLabels = labelTensor.sub(labelMin).div(labelMax.sub(labelMin));return {inputs: normalizedInputs,labels: normalizedLabels,// Return the min/max bounds so we can use them later.inputMax,inputMin,labelMax,labelMin,}});  
}

接下来,我们可以分析一下将会出现什么情况。

随机播放数据

// Step 1. Shuffle the data    
tf.util.shuffle(data);

在训练模型的过程中,数据集被分成更小的集合,每个集合称为一个批。然后将这些批次送入模型运行。整理数据很重要,因为模型不应该一次又一次地得到相同的数据。如果模型一次又一次地得到相同的数据,那么模型将无法归纳数据,并为运行期间收到的输入提供指定的输出。洗牌将有助于在每个批次中拥有各种数据。

转换为Tensor

// Step 2. Convert data to Tensor
const inputs = data.map(d => d.rooms)
const labels = data.map(d => d.price);
const inputTensor = tf.tensor2d(inputs, [inputs.length, 1]);
const labelTensor = tf.tensor2d(labels, [labels.length, 1]);

这里我们制作了两个数组,一个用于输入示例(房间条目数),另一个用于实际输出值(在机器学习中称为标签,在我们的例子中是每个房子的价格)。然后我们将每个数组数据转换为一个二维张量。

规范化数据

//Step 3. Normalize the data to the range 0 - 1 using min-max scaling
const inputMax = inputTensor.max();
const inputMin = inputTensor.min();  
const labelMax = labelTensor.max();
const labelMin = labelTensor.min();
const normalizedInputs = inputTensor.sub(inputMin).div(inputMax.sub(inputMin));
const normalizedLabels = labelTensor.sub(labelMin).div(labelMax.sub(labelMin));

接下来,我们规范化数据。在这里,我们使用最小-最大比例将数据规范化为数值范围0-1。规范化很重要,因为您将使用tensorflow.js构建的许多机器学习模型的内部设计都是为了使用不太大的数字。规范化数据以包括0到1或-1到1的公共范围。

返回数据和规范化界限

return {inputs: normalizedInputs,labels: normalizedLabels,// Return the min/max bounds so we can use them later.inputMax,inputMin,labelMax,labelMin,
}

我们可以在运行期间保留用于标准化的值,这样我们就可以取消标准化输出,使其恢复到原始规模,我们就可以用同样的方式规范化未来的输入数据。

步骤5:运行模型

通过创建模型实例、将数据表示为张量,我们可以准备开始运行模型。

将以下函数复制到script.js文件中。

async function trainModel(model, inputs, labels) {// Prepare the model for training.  model.compile({optimizer: tf.train.adam(),loss: tf.losses.meanSquaredError,metrics: ['mse'],});const batchSize = 28;const epochs = 50;return await model.fit(inputs, labels, {batchSize,epochs,shuffle: true,callbacks: tfvis.show.fitCallbacks({ name: 'Training Performance' },['loss', 'mse'], { height: 200, callbacks: ['onEpochEnd'] })});
}

我们把它分解一下。

准备运行

// Prepare the model for training.  
model.compile({optimizer: tf.train.adam(),loss: tf.losses.meanSquaredError,metrics: ['mse'],
});

我们必须在训练前“编译”模型。要做到这一点,我们必须明确一些非常重要的事情:

优化器:这是一个算法,它可以控制模型的更新,就像上面看到的例子一样。TensorFlow.js中有许多可用的优化器。这里我们选择了Adam优化器,因为它在实践中非常有效,不需要进行额外配置。

损失函数:这是一个函数,它用于检测模型所显示的每个批(数据子集)方面完成的情况如何。在这里,我们可以使用meansquaredrror将模型所做的预测与真实值进行比较。

度量:这是我们要在每个区块结束时用来计算的度量数组。我们可以用它计算整个训练集的准确度,这样我们就可以检查自己的运行结果了。这里我们使用mse,它是meansquaredrror的简写。这是我们用于损失函数的相同函数,也是回归任务中常用的函数。

const batchSize = 28;
const epochs = 50;

接下来,我们选择一个批量大小和一些时间段:

batchSize指的是模型在每次运行迭代时将看到的数据子集的大小。常见的批量大小通常在32-512之间。对于所有问题来说,并没有一个真正理想的批量大小,描述各种批量大小的精确方式这一知识点本教程没有相关讲解,对这些有兴趣可以通过别的渠道进行了解学习。

epochs指的是模型将查看你提供的整个数据集的次数。在这里,我们通过数据集进行50次迭代。

启动列车环路

return model.fit(inputs, labels, {batchSize,epochs,callbacks: tfvis.show.fitCallbacks({ name: 'Training Performance' },['loss', 'mse'], { height: 200, callbacks: ['onEpochEnd']})
});

model.fit是我们调用的启动循环的函数。它是一个异步函数,因此我们返回它给我们的特定值,以便调用者可以确定运行结束时间。

为了监控运行进度,我们将一些回调传递给model.fit。我们使用tfvis.show.fitcallbacks生成函数,这些函数可以为前面指定的“损失”和“毫秒”度量绘制图表。

把它们放在一起

现在我们必须调用从运行函数定义的函数。

将以下代码添加到运行函数的底部。

// Convert the data to a form we can use for training.
const tensorData = convertToTensor(data);
const {inputs, labels} = tensorData;// Train the model  
await trainModel(model, inputs, labels);
console.log('Done Training');

刷新页面时,几秒钟后,你应该会看到图形正在更新。

这些是由我们之前创建的回调创建的。它们在每个时代结束时显示丢失(在最近的批处理上)和毫秒(在整个数据集上)。

当训练一个模型时,我们希望看到损失减少。在这种情况下,因为我们的度量是一个误差度量,所以我们希望看到它也下降。

第6步:做出预测

既然我们的模型经过了训练,我们想做一些预测。让我们通过观察它预测的低到高数量房间的统一范围来评估模型。

将以下函数添加到script.js文件中

function testModel(model, inputData, normalizationData) {const {inputMax, inputMin, labelMin, labelMax} = normalizationData;  // Generate predictions for a uniform range of numbers between 0 and 1;// We un-normalize the data by doing the inverse of the min-max scaling // that we did earlier.const [xs, preds] = tf.tidy(() => {const xs = tf.linspace(0, 1, 100);      const preds = model.predict(xs.reshape([100, 1]));      const unNormXs = xs.mul(inputMax.sub(inputMin)).add(inputMin);const unNormPreds = preds.mul(labelMax.sub(labelMin)).add(labelMin);// Un-normalize the datareturn [unNormXs.dataSync(), unNormPreds.dataSync()];});const predictedPoints = Array.from(xs).map((val, i) => {return {x: val, y: preds[i]}});const originalPoints = inputData.map(d => ({x: d.rooms, y: d.price,}));tfvis.render.scatterplot({name: 'Model Predictions vs Original Data'}, {values: [originalPoints, predictedPoints], series: ['original', 'predicted']}, {xLabel: 'No. of rooms',yLabel: 'Price',height: 300});
}

在上面的函数中需要注意的一些事情。

const xs = tf.linspace(0, 1, 100);      
const preds = model.predict(xs.reshape([100, 1]));

我们生成100个新的“示例”以提供给模型。model.predict是我们如何将这些示例输入到模型中的。注意,他们需要有一个类似的形状([num_的例子,num_的特点每个_的例子])当我们做培训时。

// Un-normalize the data
const unNormXs = xs.mul(inputMax.sub(inputMin)).add(inputMin);const unNormPreds = preds.mul(labelMax.sub(labelMin)).add(labelMin);

为了将数据恢复到原始范围(而不是0–1),我们使用规范化时计算的值,但只需反转操作。

return [unNormXs.dataSync(), unNormPreds.dataSync()];

.datasync()是一种方法,我们可以使用它来获取存储在张量中的值的typedarray。这允许我们在常规的javascript中处理这些值。这是通常首选的.data()方法的同步版本。

最后,我们使用tfjs-vis来绘制原始数据和模型中的预测。

将以下代码添加到运行函数中。

testModel(model, data, tensorData);

刷新页面,现在已经完成啦!

现在你已经学会使用tensorflow.js创建一个简单的机器学习模型了。这里是Github存储库供参考。

结论

我开始接触这些是因为机器学习的概念非常吸引我,还有就是我想看看有没有方法可以让它在前端开发中实现,我很高兴发现tensorflow.js库可以帮助我实现我的目标。这只是前端开发中机器学习的开始,TensorFlow.js还可以完成很多工作。谢谢你的阅读!


原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/519104.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

阿里巴巴、支付宝员工都在用的知识管理工具,究竟有何特别?

公司内各部门工作文档难以共享&#xff1f;缺乏高效便捷的团队协作工具&#xff1f;文档放到在线云平台担心安全&#xff1f;…… 2019年4月22日&#xff0c;蚂蚁金服旗下知识创作与分享工具语雀发布“空间功能”。语雀在支持在线文档编写、多人协作、灵活的团队管理和金融级安…

探索处理数据的新方法,8 个重点带你搞懂云数据库——DBaaS(数据库即服务)到底是什么!...

作者| Rohan Wadiwala、Mangesh More翻译 | 天道酬勤&#xff0c;编辑 | Carol出品| CSDN云计算&#xff08;ID&#xff1a;CSDNcloud&#xff09;在分析的世界中&#xff0c;网站的每次点击都是数据分析的候选对象&#xff0c;显然&#xff0c;这会涉及大量的数据生成。对于海…

阿里开发者招聘节 | 面试题05: 关于epoll和select的区别,哪些说法是正确的?

为帮助开发者们提升面试技能、有机会入职阿里&#xff0c;云栖社区特别制作了这个专辑——阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的面试真题这一次将陆续放出&#xff08;面试题官方参考答案将在专辑结束后统一汇总分享&#xff0c;点此进入答题并围观他…

c语言printf里的自增,笔试题记录:C语言——函数printf()的执行机制;先自增与后自增的区别;取值运算与自增运算的优先级...

考点&#xff1a;函数printf()的执行机制&#xff1a;参数按照从右至左的顺序入栈&#xff0c;在调用时出栈&#xff1b;考察运算符“”在变量之前、变量之后的运算机制&#xff0c;即是先赋值/还是先自增*(p)、*(p)、*(p1)之间的区别后面两项主要是考察&#xff1a;取值运算与…

分布式系统:CAP 理论的前世今生

CAP 理论是分布式系统设计中的一个重要理论&#xff0c;虽然它为系统设计提供了非常有用的依据&#xff0c;但是也带来了很多误解。本文将从 CAP 诞生的背景说起&#xff0c;然后对理论进行解释&#xff0c;最后对 CAP 在当前背景下的一些新理解进行分析&#xff0c;澄清一些对…

你的企业混合云了吗?来看看评估混合云解决方案时要注意的6个原则!

作者| Matt Kimball翻译 | 天道酬勤&#xff0c;编辑 | Carol出品| CSDN云计算&#xff08;ID&#xff1a;CSDNcloud&#xff09;混合云如今很流行。几乎每个IT公司都声称已部署了解决方案&#xff0c;但实际上实现的却很少。相反&#xff0c;它们拥有与多个云实例进行某种程度…

c语言int超出范围字符串,Go返回int64类型字段超出javascript Number范围的解决方法...

Go返回int64类型字段超出javascript Number范围的解决方法最近在项目中&#xff0c;一个go服务给前端提供了一个接口&#xff0c;返回json格式数据&#xff0c;其中Int64字段会超出javascript Number可表示的最大的Int值会丢精度&#xff0c;可以通过返回string类型值来屏蔽这个…

构建可靠系统的原则与实践

随着阿里技术的发展&#xff0c;我们的技术系统越来越成为社会的基础设施&#xff0c;对于这些系统的可靠性要求也就越来越高。但是实际上很多的基础的产品和系统确仍然会出现一些稳定性问题&#xff0c;那么如何才能构建可靠的系统呢&#xff1f;是不是制定非常严格而细致的规…

看完就能独自把集群搭起来!Hadoop HDFS完全分布式环境搭建以及技术详解

作者 | 慢慢变成大佬责编 | Carol出品 | CSDN云计算&#xff08;ID&#xff1a;CSDNcloud&#xff09;在文章开始之前&#xff0c;作者想要告诉大家&#xff1a;读懂本篇文章&#xff0c;能让小白快速入门&#xff0c;并且能够搭建完全分布式的集群&#xff0c;以及能对Hadoop …

使用idea创建JavaWeb项目

【第一步】 File—New—Project 【第二步】 选择Java Enterprise版本&#xff0c;然后配置tomcat 注意&#xff1a;这里关联的tomcat home指的是tomcat的解压目录&#xff08;bin目录的上一级目录&#xff09;&#xff1b; 【第三步】 选择使用模板创建项目 【第四步】 填写…

阿里云栖开发者沙龙PHP技术专场-聊聊服务稳定性保障这些事

本文主要带大家了解服务稳定性的重要性和相关策略。策略大概分两部分&#xff0c;第一方面从架构层面介绍保障服务稳定性的常见策略&#xff08;限流&#xff0c;降级&#xff0c;隔离&#xff0c;超时&#xff0c;重试和集群&#xff09;。第二个方面是从流程方面&#xff08;…

ccs读取dat文件c语言程序,TMS320DM642学习----第六篇(CCS中.dat文件类型详解)

1、如下为.dat文件中文件头的基本格式&#xff1a;MagicNumber Format StartingAddress PageNum Length [NewFormat]下面是分别的解释&#xff1a;MagicNumber&#xff1a;1651.Format&#xff1a;a number from 1 to 4, indicating the format of the samples in the file. Th…

阿里开发者招聘节 | 面试题06-07: MySQL的数据如何恢复到任意时间点

为帮助开发者们提升面试技能、有机会入职阿里&#xff0c;云栖社区特别制作了这个专辑——阿里巴巴资深技术专家们结合多年的工作、面试经验总结提炼而成的面试真题这一次将陆续放出&#xff08;面试题官方参考答案将在专辑结束后统一汇总分享&#xff0c;点此进入答题并围观他…

通过接口操作MyBatis及数据库配置文件

优点&#xff1a; 不用每次实例化SqlSession配置优于硬编码减少sql书写错误的概率规范代码&#xff0c;面向接口服务 文章目录一、回顾二、如何通过接口操作MyBatis2.1. 文件结构2.2. 依赖jar包2.3. 表结构2.4. mybatis配置文件2.5. db配置文件2.6. 获取SqlSession工具类2.7. 基…

厉害!中国AI企业50强榜单!看完员工待遇,网友:我酸了!

有自媒体说&#xff0c;现在各大国对AI的部署&#xff0c;就像对“核武器”的部署一样&#xff0c;这份脑力和智力的比拼&#xff0c;超级大国都绝对不能输。在最近&#xff0c;赛迪研究院就发布了「2019人工智能企业综合实力100强名单」&#xff0c;BAT毫无疑问霸榜&#xff0…

蚂蚁金服SOFA开源负责人鲁直:不只是中间件,未来会开源更多

近日&#xff0c;技术媒体Linux中国的创始人王兴宇对蚂蚁金服SOFA开源负责人鲁直&#xff0c;就SOFA 5、ServiceMesh、Serverless、Seata等技术内容进行了探讨&#xff0c;以下为专访文章。 虽然我和鲁直在微信上已经联系很久了&#xff0c;但这还是第一次见面。交谈中&#x…

Redis radix tree源码解析

Redis实现了不定长压缩前缀的radix tree&#xff0c;用在集群模式下存储slot对应的的所有key信息。本文将详述在Redis中如何实现radix tree。 核心数据结构 raxNode是radix tree的核心数据结构&#xff0c;其结构体如下代码所示&#xff1a; typedef struct raxNode {uint32…

针对提高48V 配电性能的诸多思考!

作者&#xff1a;Phil Davies 众所周知配电网络 (PDN) 是所有电源系统的主干部分&#xff0c;但随着系统电源需求的不断上升&#xff0c;传统 PDN 承受着提供足够性能的巨大压力。 对于功耗和热管理而言&#xff0c;主要有两种方法可以改善 PDN 对电源系统性能的影响&#x…

android线性布局快捷键,【整理】Android图形界面知识学习与总结之:Linear Layout线性布局...

【背景】之前已经学习了&#xff1a;现在接着去学习&#xff1a;整理如下&#xff1a;Linear Layout1.LinearLayout是一个视图组合2.LinearLayout中的子视图只能已单个方向排列&#xff0c;要么是水平&#xff0c;要么是垂直&#xff1b;4.所有如果是垂直的列表&#xff0c;则每…

收藏!企业数据安全防护5条建议

引言&#xff1a;数据安全对企业生存发展有着举足轻重的影响&#xff0c;数据资产的外泄、破坏都会导致企业无可挽回的经济损失和核心竞争力缺失&#xff0c;而往往绝大多数中小企业侧重的是业务的快速发展&#xff0c;忽略了数据安全重要性。近年来&#xff0c;企业由于自身的…