目录
设置TensorFlow.js
创建训练数据
检查点
定义神经网络模型
训练AI
测试结果
终点线
内存使用注意事项
下一步是什么?狗和披萨?
TensorFlow + JavaScript。现在,最流行、最先进的AI框架支持地球上使用最广泛的编程语言,因此,让我们在我们的web浏览器中通过深度学习实现奇迹,通过TensorFlow.js的WebGL GPU加速!
这是我们六个系列的第一篇文章:
- 使用TensorFlow.js在浏览器中进行深度学习入门
- 狗和披萨:使用TensorFlow.js在浏览器中实现计算机视觉
- 绒毛动物探测器:通过TensorFlow.js中的迁移学习识别浏览器中的自定义对象
- 使用TensorFlow.js进行人脸触摸检测第1部分:将实时网络摄像头数据与深度学习配合使用
- 使用TensorFlow.js进行人脸触摸检测第2部分:使用BodyPix
- 使用TensorFlow.js进行AI在网络摄像头中翻译手势和手语
在本文中,我将向您展示如何快速轻松地设置和使用TensorFlow.js训练神经网络,以便根据数据点进行预测。通过单击下载上面链接的.zip文件,您可以找到该项目的代码以及其他示例。
设置TensorFlow.js
第一步是创建一个HTML网页文件,例如index.html,并将TensorFlow.js脚本包含在<head>标记中,这将使我们可以使用tf对象使用TensorFlow 。
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.0.0/dist/tf.min.js"></script>
这是我们可以用于项目的入门模板页面,其中一部分保留给我们的代码:
<html>
<head>
<title>Deep Learning in Your Browser with TensorFlow.js</title>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.0.0/dist/tf.min.js"></script>
</head>
<body>
<script>
(async () => {
// Your Code Goes Here
})();
</script>
</body>
</html>
本文讨论的所有代码都将放置在网页的async包装器部分内。
要运行代码,请在任何现代浏览器中打开上述网页,然后启动控制台调试器日志(在大多数浏览器中按F12即可完成操作)。
async包装器将让我们使用await关键字来处理TensorFlow的异步函数,而不是一堆.then()代码链。它应该相当简单;但是,如果您想更熟悉这种模式,建议您阅读本指南。
创建训练数据
我们将复制一个XOR布尔逻辑门,该逻辑门有两个选择并检查是否选择了一个,但不能同时选择两个。
作为一个表,它看起来像这样:
A | B | 输出 |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
在代码中,我们可以将其设置为两个数字数组,一个用于我们的两个输入选择,一个用于我们的预期输出:
// XOR datac
onst data = [ [ 0, 0 ], [ 0, 1 ], [ 1, 0 ], [ 1, 1 ] ];
const output = [ [ 0 ], [ 1 ], [ 1 ], [ 0 ] ];
接下来,我们需要将值转换为数据“张量”,以将其准备用于TensorFlow。我们可以通过为每个元素创建一维张量并将它们分批成“堆栈”来实现,如下所示:
const xs = tf.stack( data.map( a => tf.tensor1d( a ) ) );
const ys = tf.stack( output.map( a => tf.tensor1d( a ) ) );
替代方法:如果您不熟悉此map()函数,这里有for循环版本。
const dataTensors = [];
const outputTensors = [];
for( let i = 0; i < data.length; i++ ) {
dataTensors.push( tf.tensor1d( data[ i ] ) );
outputTensors.push( tf.tensor1d( output[ i ] ) );
}
const xs = tf.stack( dataTensors );
const ys = tf.stack( outputTensors );
检查点
您的代码现在应类似于以下内容:
<html>
<head>
<title>Deep Learning in Your Browser with TensorFlow.js</title>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.0.0/dist/tf.min.js"></script>
</head>
<body>
<script>
(async () => {
// XOR data
const data = [ [ 0, 0 ], [ 0, 1 ], [ 1, 0 ], [ 1, 1 ] ];
const output = [ [ 0 ], [ 1 ], [ 1 ], [ 0 ] ];
const xs = tf.stack( data.map( a => tf.tensor1d( a ) ) );
const ys = tf.stack( output.map( a => tf.tensor1d( a ) ) );
})();
</script>
</body>
</html>
定义神经网络模型
现在,让我们建立网络以进行深度学习。“深度”是指我们网络的复杂性,通常定义为网络中的三个或更多“隐藏层”。让我们来建立一个。
// Define our model with several hidden layers
const model = tf.sequential();
model.add(tf.layers.dense( { units: 100, inputShape: [ 2 ] } ) );
model.add(tf.layers.dense( { units: 100, activation: 'relu' } ) );
model.add(tf.layers.dense( { units: 10, activation: 'relu' } ) );
model.add(tf.layers.dense( { units: 1 } ) );
model.summary();
我们将按顺序定义模型。为了匹配我们的数据,我们的神经网络需要采用2的输入形状和1数字的输出。
前两个隐藏层具有100个节点或单元,而第三个隐藏层具有10个节点或单元。由于relu(Rectified Linear Unit)激活函数在大多数情况下学习速度很快且表现良好,因此,这里是一个很好的默认选择。
训练AI
仅剩一步,那就是在数据上训练我们的神经网络。在TensorFlow中,这意味着我们只需编译模型并使用指定数量的迭代或``epochs''来拟合数据。
model.compile( { loss: 'meanSquaredError', optimizer: "adam", metrics: [ "acc" ] } );
// Train the model using the data.
let result = await model.fit( xs, ys, {
epochs: 100,
shuffle: true,
callbacks: {
onEpochEnd: ( epoch, logs ) => {
console.log( "Epoch #", epoch, logs );
}
}
} );
就像我们在模型中为激活功能选择relu的方式一样,我们将使用适合大多数情况的内置meanSquaredError和adam(损失和优化程序)函数。
由于我们的XOR训练数据不是顺序相关的(例如,不像时间序列数据,例如天气或一段时间内的温度),因此我们希望启用shuffle选项,并且将训练100个纪元。
测试结果
终于是时候使用我们训练有素的神经网络了。我们需要做的就是使用我们的输入和数据运行模型的predict()函数,然后将其打印出来。
for( let i = 0; i < data.length; i++ ) {
let x = data[ i ];
let result = model.predict( tf.stack( [ tf.tensor1d( x ) ] ) );
let prediction = await result.data();
console.log( x[ 0 ] + " -> Expected: " + output[ i ][ 0 ] + " Predicted: " + prediction[ 0 ] );
}
培训完成后,浏览器调试器控制台将显示如下输出:
终点线
这是完整的脚本代码:
<html>
<head>
<title>Deep Learning in Your Browser with TensorFlow.js</title>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.0.0/dist/tf.min.js"></script>
</head>
<body>
<script>
(async () => {
// XOR data
const data = [ [ 0, 0 ], [ 0, 1 ], [ 1, 0 ], [ 1, 1 ] ];
const output = [ [ 0 ], [ 1 ], [ 1 ], [ 0 ] ];
const xs = tf.stack( data.map( a => tf.tensor1d( a ) ) );
const ys = tf.stack( output.map( a => tf.tensor1d( a ) ) );
// Define our model with several hidden layers
const model = tf.sequential();
model.add(tf.layers.dense( { units: 100, inputShape: [ 2 ] } ) );
model.add(tf.layers.dense( { units: 100, activation: 'relu' } ) );
model.add(tf.layers.dense( { units: 10, activation: 'relu' } ) );
model.add(tf.layers.dense( { units: 1 } ) );
model.summary();
model.compile( { loss: 'meanSquaredError', optimizer: "adam", metrics: [ "acc" ] } );
// Train the model using the data.
let result = await model.fit( xs, ys, {
epochs: 100,
shuffle: true,
callbacks: {
onEpochEnd: ( epoch, logs ) => {
console.log( "Epoch #", epoch, logs );
}
}
} );
for( let i = 0; i < data.length; i++ ) {
let x = data[ i ];
let result = model.predict( tf.stack( [ tf.tensor1d( x ) ] ) );
let prediction = await result.data();
console.log( x[ 0 ] + " -> Expected: " + output[ i ][ 0 ] + " Predicted: " + prediction[ 0 ] );
}
})();
</script>
</body>
</html>
内存使用注意事项
为简单起见,本教程不必担心张量的内存使用情况以及事后的处理方式。但是,这对于更大、更复杂的项目很重要。TensorFlow.js在GPU上分配张量,如果我们想防止内存泄漏,就必须自己处理它们。我们可以使用每个张量对象上的dispose()函数来做到这一点。另外,我们可以通过将代码包装在如下tf.tidy()函数中,让TensorFlow.js自动管理张量处理:
for( let i = 0; i < data.length; i++ ) {
let x = data[ i ];
let result = tf.tidy( () => {
return model.predict( tf.stack( [ tf.tensor1d( x ) ] ) );
});
let prediction = await result.data();
result.dispose();
console.log( x[ 0 ] + " -> Expected: " + output[ i ][ 0 ] + " Predicted: " + prediction[ 0 ] );
}
下一步是什么?狗和披萨?
因此,您已经看到在浏览器中设置和使用TensorFlow是多么容易。不要在这里停下来,还有更多!我们如何以迄今为止取得的进展为基础,并尝试一些更有趣的事情,例如检测图像中的动物和物体?
紧随本系列的下一篇文章“狗和披萨:TensorFlow.js在浏览器中的计算机视觉”。