先看一下简单训练的预测效果

加载MNIST数据集

其中–cors表示允许跨域访问

卷积神经网络

为什么要用卷积神经网络

卷积神经网络的结构

卷积层
池化层
dense全链接层

构建卷积神经网络代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

const model = tf.sequential();
//添加一个二位卷积层
model.add(tf.layers.conv2d({
inputShape: [28, 28, 1],
kernelSize: 5, //卷积核的大小是5X5的矩阵
filters: 8, //应用8种图像卷积核
strides: 1, //移动步长,每一个像素单元都进行卷积操作
activation: 'relu', //激活函数,移除掉无用的特征(特征<0就废弃
kernelInitializer: 'varianceScaling' //可以不设置,设置了可以加快收敛速度
}));

//最大池化层
model.add(tf.layers.maxPool2d({
poolSize: [2, 2], //尺寸是2X2
strides: [2, 2] //移动步长,每隔两个像素单元进行一次卷积操作
}));

// 重复上述两个层
model.add(tf.layers.conv2d({
kernelSize: 5,
filters: 16, //需要提取更多特征
strides: 1,
activation: 'relu',
kernelInitializer: 'varianceScaling'
}));
model.add(tf.layers.maxPool2d({
poolSize: [2, 2],
strides: [2, 2]
}));

//flatten层用于将多维的特征数据,转换为一维的分类数据,传入dense层
model.add(tf.layers.flatten());


model.add(tf.layers.dense({
units: 10, //最终输出0-9十个分类
activation: 'softmax',
kernelInitializer: 'varianceScaling'
}));

训练模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//训练参数
model.compile({
loss: 'categoricalCrossentropy', //交叉熵损失函数
optimizer: tf.train.adam(), //优化器
metrics: ['accuracy'] //准确度度量
});

//训练集数据
const [trainXs, trainYs] = tf.tidy(() => {
const d = data.nextTrainBatch(1000);
return [
d.xs.reshape([1000, 28, 28, 1]),
d.labels
];
});

//验证集数据
const [testXs, testYs] = tf.tidy(() => {
const d = data.nextTestBatch(200);
return [
d.xs.reshape([200, 28, 28, 1]),
d.labels
];
});

//训练
await model.fit(trainXs, trainYs, {
validationData: [testXs, testYs],
batchSize: 500,
epochs: 50,
callbacks: tfvis.show.fitCallbacks(
{ name: '训练效果' },
['loss', 'val_loss', 'acc', 'val_acc'],
{ callbacks: ['onEpochEnd'] }
)
});

使用模型预测识别canvas绘制数字

预测效果


总结:这一节有两个难点,一是卷积神经网络的构建,重在理解图像卷积核;二是图像与tensor格式的转换,需要多加练习与斟酌;

本地训练结果正确率大概70%,可以通过增加训练集数据和训练次数来提升效果


代码仓库