我正在使用迁移学习的概念对我的图像进行分类,我已经重用了https://towardsdatascience.com/transfer-learning-from-pre-trained-models-f2393f124751中提到的代码
该模型适用于我的 jupyter 笔记本中的数据(https://www.dropbox.com/s/esirpr6q1lsdsms/ricetransfer1.zip?dl=0),但在测试模型之前,我正在重塑图像。
但是当我想使用 TensorFlow 在浏览器中运行相同的模型时,我使用了 tfjs.converters.save_keras_model 来保存我的模型。
from keras.applications import VGG16
import tensorflowjs as tfjs
import tensorflow as tf
tf.compat.v1.disable_eager_execution()
img_width, img_height = 224, 224 # Default input size for VGG16
conv_base = VGG16(weights='imagenet',
include_top=False,
#input_shape=(224, 224, 3))
input_shape=(img_width, img_height, 3))
# Extract features
import os, shutil
from keras.preprocessing.image import ImageDataGenerator
import numpy as np
train_size, validation_size, test_size = 148, 27, 31
datagen = ImageDataGenerator(rescale=1./255)
batch_size = 16
train_dir = "ricetransfer1/train"
validation_dir = "ricetransfer1/validation"
test_dir="ricetransfer1/test"
#indices = np.random.choice(range(len(X_train)))
def extract_features(directory, sample_count):
#sample_count= X_train.ravel()
features = np.zeros(shape=(sample_count, 7, 7, 512)) # Must be
equal to the output of the convolutional base
labels = np.zeros(shape=(sample_count))
# Preprocess data
generator = datagen.flow_from_directory(directory,
target_size=(img_width,img_height),
batch_size = batch_size,
class_mode='binary')
# Pass data through convolutional base
i = 0
for inputs_batch, labels_batch in generator:
features_batch = conv_base.predict(inputs_batch)
features[i * batch_size: (i + 1) * batch_size] = features_batch
labels[i * batch_size: (i + 1) * batch_size] = labels_batch
i += 1
if i * batch_size >= sample_count:
break
return features, labels
train_features, train_labels = extract_features(train_dir, train_size)
validation_features, validation_labels = extract_features(validation_dir, validation_size)
test_features, test_labels = extract_features(test_dir, test_size)
from keras import models
from keras import layers
from keras import optimizers
epochs = 1
ricemodel = models.Sequential()
ricemodel.add(layers.Flatten(input_shape=(7,7,512)),)
ricemodel.add(layers.Dense(256, activation='relu', input_dim=(7*7*512)))
ricemodel.add(layers.Dropout(0.5))
ricemodel.add(layers.Dense(1, activation='sigmoid'))
ricemodel.summary()
ricemodel.compile(optimizer=optimizers.Adam(),
loss='binary_crossentropy',
metrics=['acc'])
import os
history=ricemodel.fit(train_features, train_labels,
epochs=epochs,
batch_size=batch_size,
validation_data=(validation_features, validation_labels))
path='\vgg'
tfjs.converters.save_keras_model(ricemodel, path)
TensorFlowjs 代码是
$(document).ready()
{
$('.progress-bar').hide();
}
$("#image-selector").change(function(){
let reader = new FileReader();
reader.onload = function(){
let dataURL = reader.result;
$("#selected-image").attr("src",dataURL);
$("#prediction-list").empty();
}
let file = $("#image-selector").prop('files')[0];
reader.readAsDataURL(file);
});
$("#model-selector").change(function(){
loadModel($("#model-selector").val());
$('.progress-bar').show();
})
let model;
async function loadModel(name){
model=await tf.loadModel(`http://localhost:8081/${name}/model.json`);
$('.progress-bar').hide();
}
$("#predict-button").click(async function(){
let image= $('#selected-image').get(0);
let tensor = preprocessImage(image,$("#model-selector").val());
let prediction = await model.predict(tensor).data();
let top5=Array.from(prediction)
.map(function(p,i){
return {
probability: p,
className: IMAGENET_CLASSES[i]
};
}).sort(function(a,b){
return b.probability-a.probability;
}).slice(0,5);
$("#prediction-list").empty();
top5.forEach(function(p){
$("#prediction-
list").append(`<li>${p.className}:${p.probability.toFixed(6)}</li>`);
});
});
function preprocessImage(image,modelName)
{
let tensor=tf.fromPixels(image)
.resizeNearestNeighbor([224,224])
.toFloat();//.sub(meanImageNetRGB)
if(modelName==undefined)
{
return tensor.expandDims();
}
else if(modelName=="vgg")
{
let meanImageNetRGB= tf.tensor1d([123.68,116.779,103.939]);
return tensor.sub(meanImageNetRGB)
.reverse(2)
.expandDims();
}
else if(modelName=="mobilenet")
{
let offset=tf.scalar(127.5);
return tensor.sub(offset)
.div(offset)
.expandDims();
}
else
{
throw new Error("UnKnown Model error");
}
}
在 tensorflowjs 中加载模型后浏览器出现错误消息,我收到以下错误(我可以在 Web 开发控制台中看到错误消息)
未捕获(承诺中)错误:检查时出错:预期 flatten_1_input 的形状为 [null,7,7,512] 但得到的数组的形状为 [1,224,224,3]
有什么办法可以解决这个问题,我可以在加载到浏览器之前重塑图像吗?
我尝试了所有可能的选择,但我现在卡住了。
我已经在 stackoverflow 上检查了可能的解决方案。如何在浏览器上运行分类模型?