TensorflowJs是一个加速API,用于在nodeJs和浏览器中部署深度神经网络和机器学习模型。在本教程中,我们将解释如何在tensorflowJs中编写感知器模型。
Perceptron(感知器)是一种监督学习算法。它由以下内容组成:给定一个输入,它乘以一个权重张量w。人们可以加上一个偏差的张量b。在该线性步骤之后,使用激活函数来保持优于特定阈值的结果。激活函数很棒,因为它们在机器学习模型中引入了非线性。请记住,第一步只是一个线性操作:wx + b。如果我们希望模型能够学习非线性函数,我们需要添加激活函数。
让我们实现一个感知器模型来学习非线性函数(cosinus)。
首先,我们需要创建一个模型。
const model = tf.sequential();
tf.sequential允许创建一个模型,其中各层叠加在另一层之上。单个感知器模型由一个层组成。
model.add(tf.layers.dense({units: 10, activation: 'relu', inputShape: [1]}));
tensorflowJs将创建一个形状的权重矩阵[1,10],将在每个epoch中更新。epoch是一个训练的周期。relu是模型中非线性的激活函数。通过上面的两行代码,我们创建了一个单层感知器。我们可以添加更多的层,改变每个学习周期中要学习的权重。我们需要记住,更多的参数可以让机器学习模型在学习过程中消耗更多的时间,并且会过度拟合。相反,使用较少的参数,机器学习模型将花费较少的时间进行训练,但在预测期间会出现错误。
我们添加另一层:
model.add(tf.layers.dense({ units: 5 })); model.add(tf.layers.dense({ units: 1 }));
我们现在有一个多层感知器。我们计算y数据和估计数据?之间的均方误差,使用adam优化。
model.compile({ loss: 'meanSquaredError', optimizer: 'adam' });
创建机器学习模型后,我们现在必须训练它。为此,我们需要创建自己的数据集。使用tf.randomNormal,我们创建一个具有随机值的一维张量x。对于x中的每个条目,我们计算cos(x); 我们在其中添加一个随机值来模拟真实情况下的噪声。该数据在一维张量y中。
const NUM_POINTS = 1000; const x = tf.randomNormal([NUM_POINTS], undefined, undefined, undefined, NUM_POINTS); const y = tf.cos(x).add(tf.scalar(0.1).mul(tf.randomNormal([NUM_POINTS], undefined, undefined, undefined, seed = NUM_POINTS))) const f = (x) => tf.cos(x).add(0.1 * tf.random);
部分数据用于训练,另一部分用于测试。需要多少数据用于训练/测试呢?我们使用规则70/30进行训练。
const features_training = x.gather(tf.tensor1d(training_indices, 'int32')); const labels_training = y.gather(tf.tensor1d(training_indices, 'int32')); const features_test = x.gather(tf.tensor1d(test_indices, 'int32')); const labels_test = y.gather(tf.tensor1d(test_indices, 'int32'));
最后,我们的机器学习模型需要从训练数据中学习。我们使用训练数据的特征和标签来拟合我们的模型。特征通常是给予数据x的名称,数据y称为标签。我们使用测试数据的特征进行预测。这是关键时刻:我们将看到模型的准确程度。
model.fit(features_training.reshape([TRAINING_POINTS , 1]), labels_training.reshape([TRAINING_POINTS , 1]), { epochs: 100, batchSize: 100, callbacks: { onEpochEnd: (epoch, log) => { console.log(epoch, log.loss); } } }).then(() => { const p = tf.stack(features_test.unstack().map(t => model.predict(t.reshape([1, 1])))); })
HTML示例代码:
<head> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script> </head> <body> <h1>Multiple Layer Perceptron Model</h1> <div>You can open your console to see the error decreasing while training (ctrl + shift + j)</div> <canvas id="myChart"></canvas> </body>
javascript代码:
(function train() { const NUM_POINTS = 1000; const TRAINING_POINTS = 700; const x = tf.randomNormal([NUM_POINTS], undefined, undefined, undefined, NUM_POINTS); const y = tf.cos(x).add(tf.scalar(0.1).mul(tf.randomNormal([NUM_POINTS], undefined, undefined, undefined, seed = NUM_POINTS))) const f = (x) => tf.cos(x).add(0.1 * tf.random); const learningRate = 0.00001; const optimizer = tf.train.adam(); const model = tf.sequential(); model.add(tf.layers.dense({ units: 10, activation: 'relu', inputShape: [1] })); model.add(tf.layers.dense({ units: 5 })); model.add(tf.layers.dense({ units: 1 })); model.compile({ loss: 'meanSquaredError', optimizer: 'adam' }); const intermediate = [] const training_indices = Array.from({ length: TRAINING_POINTS }, (_, i, a) => { const generate = () => Math.floor(Math.random() * NUM_POINTS); let n = generate(); while (intermediate.includes(n)) { n = generate() } intermediate.push(n); return n; }); const test_indices = Array.from({ length: NUM_POINTS }, (_, i) => i).filter(e => !training_indices.includes(e)); const features_training = x.gather(tf.tensor1d(training_indices, 'int32')); const labels_training = y.gather(tf.tensor1d(training_indices, 'int32')); const features_test = x.gather(tf.tensor1d(test_indices, 'int32')); const labels_test = y.gather(tf.tensor1d(test_indices, 'int32')); model.fit(features_training.reshape([TRAINING_POINTS , 1]), labels_training.reshape([TRAINING_POINTS , 1]), { epochs: 100, batchSize: 100, callbacks: { onEpochEnd: (epoch, log) => { console.log(epoch, log.loss); } } }).then(() => { const p = tf.stack(features_test.unstack().map(t => model.predict(t.reshape([1, 1])))); const x_dataset = features_test.dataSync(); const y_dataset = labels_test.dataSync(); const p_dataset = p.dataSync(); const data1 = []; const data2 = []; for (let i = 0; i < NUM_POINTS; i++) { data1.push({ x: x_dataset[i], y: y_dataset[i] }); data2.push({ x: x_dataset[i], y: p_dataset[i] }); } new Chart(document.getElementById("myChart"), { type: 'scatter', data: { datasets: [{ label: "test-label", data: data1, pointBackgroundColor: "red", borderColor: "red" }, { label: "estimation", data: data2, pointBackgroundColor: "green", borderColor: "green" }] }, options: { responsive: true, showLines: false, legend: { labels: { usePointStyle: true } } } }); }) })()
下图显示了测试数据以及模型的预测