# 多层神经网络(xor 问题)
# 代码展示
import * as tf from '@tensorflow/tfjs';
import * as tfvis from '@tensorflow/tfjs-vis';
import { getData } from './data';
window.onload = async () => {
/*构造数据*/
const data = getData(400);
console.log('data', data);
/*渲染数据*/
tfvis.render.scatterplot(
{ name: 'xor训练数据' },
{
values: [
data.filter((p) => p.label === 1),
data.filter((p) => p.label === 0),
],
}
);
/*初始化模型*/
const model = tf.sequential();
/*添加隐藏层*/
model.add(
tf.layers.dense({
units: 4, // 神经元个数
inputShape: [2], // // 神经元(输入)接受的形状
activation: 'relu', // 这个激活函数可以带来一些非线性的变化,如果这里不要激活函数相当于这个隐藏层没有用,因为无论设置多少个层没有激活函数输出都是线性的
})
);
/*添加输出层*/
model.add(
tf.layers.dense({
// sequential为连续输出模型所以这里不需要设置inputshape
units: 1, // 只需要输出一个概率
activation: 'sigmoid', // 输出一个0-1的概率只能选sigmoid
})
);
/*新增损失函数和优化器*/
model.compile({
loss: tf.losses.logLoss,
optimizer: tf.train.adam(0.1),
});
/*设置tensor数据*/
const inputs = tf.tensor(data.map((p) => [p.x, p.y]));
const labels = tf.tensor(data.map((p) => p.label));
/*开始训练*/
await model.fit(inputs, labels, {
epochs: 10,
callbacks: tfvis.show.fitCallbacks(
// 可视化模拟训练过程
{ name: '训练过程' },
['loss'] // 制定度量单位(制作损失曲线)
),
});
window.predict = async (form) => {
const pred = await model.predict(
tf.tensor([[form.x.value * 1, form.y.value * 1]])
);
alert(`预测结果:${pred.dataSync()[0]}`);
};
};
# 重点笔记
神经网络层数并不是越多越好,比如本示例中 2 层就比三层好,层数过少无法解决复杂问题,层数过多可能出现过拟合
神经元个数可调,但并不是越多越好,少了可能不能计算复杂情况,多了会导致计算缓慢
激活函数只需要带来非线性变化的就行,不必过于纠结使用哪个激活函数
输出层的神经元只需要设为 1,因为只需要输出一个概率
对于全连接层只有第一层需要设置 inputShape,因为后面层的输入是上一层的输出
如果不添加激活函数,那么变化则始终为线性,所有的线性加起来还是线性