TensorFlow.js浏览器训练后合并保存Mobilenet与KNN分类器的实现方法
报错原因
你调用model.add时报错的核心原因是:你传入的backbone(即Mobilenet加载实例)和outputlayer(KNN分类器实例)都不是TF.js的标准tf.layers.Layer类型,无法直接加入序列模型。
另外KNN分类器本身是基于实例的非参数算法,仅存储样本特征,没有可训练的层权重,不属于TF.js的计算图组件,所以无法直接和Mobilenet合并为标准的结构化模型文件。
最优实现方案
方案1:分开导出两部分(最简便,完全兼容你现有逻辑)
你不需要强行合并模型,分别导出骨干网络和KNN样本数据集即可,后续加载后可以直接沿用现有推理逻辑。
- 导出Mobilenet骨干模型
// 提取Mobilenet的conv_preds层作为输出,构建标准TF.js模型 const backboneModel = tf.model({ inputs: net.model.inputs, outputs: net.model.getLayer('conv_preds').output }); // 导出骨干模型,会自动下载my-backbone.json和对应的权重文件 await backboneModel.save('downloads://my-backbone');
- 导出KNN分类器的样本数据集
// 获取KNN内部存储的所有类别特征数据集 const knnDataset = classifier.getClassifierDataset(); // 将张量转为普通数组,方便序列化为JSON const serializedDataset = {}; Object.keys(knnDataset).forEach(classId => { serializedDataset[classId] = knnDataset[classId].arraySync(); }); // 生成JSON文件下载到本地 const dataBlob = new Blob([JSON.stringify(serializedDataset)], {type: 'application/json'}); const downloadLink = document.createElement('a'); downloadLink.href = URL.createObjectURL(dataBlob); downloadLink.download = 'knn-dataset.json'; downloadLink.click();
后续加载使用时,先加载my-backbone.json得到骨干模型,再加载knn-dataset.json将数组转回张量,调用classifier.setClassifierDataset()方法即可恢复分类器,推理逻辑和你现有代码完全一致。
方案2:替换KNN为全连接层,合并为单个模型
如果你需要导出单个结构化模型,可将KNN分类器替换为标准全连接层,重新训练后合并导出:
- 用现有样本通过Mobilenet提取
conv_preds激活值作为训练数据,对应标签做one-hot编码 - 构建小型全连接分类层,用提取好的训练数据完成训练
- 将Mobilenet骨干和训练好的全连接层拼接为完整模型,直接调用
save方法导出即可,导出的模型也可以通过工具转换为.h5格式在Python端使用。
内容的提问来源于stack exchange,提问作者mrk
相关产品推荐
相关产品推荐

