Используя экспортированную модель Custom vision с тензорным потоком JS и введите изображение
Я новичок в tenorflow.js и tenorflow
Контекст: мы обучили модель, используя нестандартное зрение, чтобы распознать по изображению длину волос: короткие, средние, длинные. Эта модель была экспортирована, и мы хотели бы использовать ее локально с tenorflow js. Экспортированные файлы из пользовательского видения - это файл *.pb и файл label.txt.
Я использовал скрипт python tenorflowjs_converter, вот команда, которую я использовал для преобразования замороженной модели *.pb в модель json:
tensorflowjs_converter --input_format=tf_frozen_model --output_node_names='model_outputs' --output_json OUTPUT_JSON C:\python\tf_models\hairlength\model.pb C:\python\tf_models\exports\
Затем я вставляю этот model.json и осколки в папку активов моего angular клиента. Затем я пытаюсь загрузить модель и даю ему изображение, чтобы получить прогноз, но все, что я получаю, это значения индексов, которые выходят за рамки, поскольку мне нужны только 0: длинная, 1: средняя, 2: короткая длина волос. Вот захват консоли
Это класс, который я использовал в моем клиенте (машинопись) для прогнозов:
import * as tf from '@tensorflow/tfjs';
// import {HAIRLENGTH_LABELS} from './hairlength';
import { FrozenModel } from '@tensorflow/tfjs';
const MODEL = 'assets/models/hairlength/model.json';
const INPUT_NODE_NAME = 'model_outputs';
const OUTPUT_NODE_NAME = 'model_outputs';
const PREPROCESS_DIVISOR = tf.scalar(255 / 2);
export class MobileNetHairLength {
private model: FrozenModel;
private labels = ['long', 'mid', 'short'];
constructor() {}
async load(){
this.model = await tf.loadGraphModel(MODEL);
}
dispose() {
if (this.model) {
this.model.dispose();
}
}
/**
* Infer through MobileNet. This does standard ImageNet pre-processing before
* inferring through the model. This method returns named activations as well
* as softmax logits.
*
* @param input un-preprocessed input Array.
* @return The softmax logits.
*/
predict(input) {
const preprocessedInput = tf.div(
tf.sub(input, PREPROCESS_DIVISOR),
PREPROCESS_DIVISOR);
const reshapedInput =
preprocessedInput.reshape([1, ...preprocessedInput.shape]);
// tslint:disable-next-line:no-unused-expression
return this.model.execute({[INPUT_NODE_NAME]: reshapedInput}, OUTPUT_NODE_NAME);
}
getTopKClasses(logits, topK: number) {
const predictions = tf.tidy(() => {
return tf.softmax(logits);
});
const values = predictions.dataSync();
predictions.dispose();
let predictionList = [];
for (let i = 0; i < values.length; i++) {
predictionList.push({value: values[i], index: i});
}
predictionList = predictionList
.sort((a, b) => {
return b.value - a.value;
})
.slice(0, topK);
console.log(predictionList);
return predictionList.map(x => {
return {label: this.labels[x.index], value: x.value};
});
}
}
И этот класс, который вызывает вышеупомянутый, я просто даю элемент canvas:
import 'babel-polyfill';
import * as tf from '@tensorflow/tfjs';
import { MobileNetHairLength } from './mobilenet-hairlength';
export class PredictionHairLength {
constructor() {}
async predict(canvas) {
const mobileNet = new MobileNetHairLength();
await mobileNet.load();
const pixels = tf.browser.fromPixels(canvas);
console.log('Prediction');
const result = mobileNet.predict(pixels);
const topK = mobileNet.getTopKClasses(result, 3);
topK.forEach(x => {
console.log( '${x.value.toFixed(3)}: ${x.label}\n' );
});
mobileNet.dispose();
}
}
Мои вопросы:
Правильна ли команда преобразования Python?
Я что-то упустил в своем клиенте, чтобы получить правильные индексы?
Спасибо за ваше время и ответы
Если вам нужна дополнительная информация, я с удовольствием предоставлю ее вам
Обновления 10/03/2019
Я обновил тензор потока до 1.0.0, используя npm
Я видел, что FrozenModel устарела
Экспорт моей пользовательской модели видения дает мне файлы model.pb и tags.txt, например:
Я пытался использовать эти файлы с Python все работает нормально...
Теперь я хотел бы преобразовать этот файл model.pb в файл model.json, чтобы использовать его с tennorflowjs, для этого мне нужно использовать tennsflowjs_converter, проблема в том, что структура файла для преобразования этой сохраненной модели недопустима, см. https://www.tensorflow.org/guide/saved_model#structure_of_a_savedmodel_directory
Единственное, что работает, если я использую формат frozen_model в конвертере и задаю в качестве имени выходного узла: потеря... вот так tensorflowjs_converter --input_format=tf_frozen_model --output_node_names='loss' --output_json OUTPUT_JSON C:\python\tf_models\hairlength\model.pb C:\python\tf_models\exports\
Это выходные данные, которые я получаю при запуске вышеуказанной команды:
затем я загружаю модель, вот мой код для загрузки и прогнозирования с использованием экспортированной модели json (я использую предикат() и удаляю узлы ввода и вывода, как вы мне посоветовали):
import * as tf from '@tensorflow/tfjs';
import { GraphModel } from '@tensorflow/tfjs';
const MODEL = 'assets/models/hairlength/model.json';
// const INPUT_NODE_NAME = 'Placeholder';
// const OUTPUT_NODE_NAME = 'loss';
const PREPROCESS_DIVISOR = tf.scalar(255 / 2);
export class MobileNetHairLength {
private model: GraphModel;
private labels = ['long', 'mid', 'short'];
constructor() {}
async load() {
this.model = await tf.loadGraphModel(MODEL);
}
dispose() {
if (this.model) {
this.model.dispose();
}
}
/**
* Infer through MobileNet. This does standard ImageNet pre-processing before
* inferring through the model. This method returns named activations as well
* as softmax logits.
*
* @param input un-preprocessed input Array.
* @return The softmax logits.
*/
predict(input: tf.Tensor<tf.Rank>) {
const preprocessedInput = tf.div(
tf.sub(input.asType('float32'), PREPROCESS_DIVISOR),
PREPROCESS_DIVISOR);
const reshapedInput =
preprocessedInput.reshape([...preprocessedInput.shape]);
return this.model.predict(reshapedInput);
}
getTopKClasses(logits, topK: number) {
const predictions = tf.tidy(() => {
return tf.softmax(logits);
});
const values = predictions.dataSync();
predictions.dispose();
let predictionList = [];
for (let i = 0; i < values.length; i++) {
predictionList.push({value: values[i], index: i});
}
predictionList = predictionList
.sort((a, b) => {
return b.value - a.value;
})
.slice(0, topK);
console.log(predictionList);
return predictionList.map(x => {
return {label: this.labels[x.index], value: x.value};
});
}
}
И вызывающий класс - это один:
import 'babel-polyfill';
import * as tf from '@tensorflow/tfjs';
import { MobileNetHairLength } from './mobilenet-hairlength';
export class PredictionHairLength {
constructor() {}
async predict(canvas) {
// Convert to tensor
const mobileNet = new MobileNetHairLength();
await mobileNet.load();
const imgTensor = tf.browser.fromPixels(canvas);
console.log(imgTensor);
// Init input with correct shape
const input = tf.zeros([1, 224, 224, 3]);
// Add img to input
input[0] = imgTensor;
console.log('Prediction');
const result = mobileNet.predict(input);
console.log(result);
const topK = mobileNet.getTopKClasses(result, 3);
topK.forEach(x => {
console.log( '${x.value.toFixed(3)}: ${x.label}\n' );
});
mobileNet.dispose();
}
}
Затем при отправке элемента холста, взятого из потока веб-камеры, появляется эта ошибка:
Как выполнить команду конвертера в формате "сохраненная модель", поскольку структура файла неверна?
Почему я получаю "Ошибка компиляции фрагмента шейдера, бесконечность: необъявленный идентификатор в tf-core.esm"?
Спасибо за ваше время и ответы
Ответы
Ответ 1
Я думаю, что это простая ошибка в вашем коде: const INPUT_NODE_NAME = 'model_outputs';
вероятно, должно быть 'model_inputs'
или как там на самом деле. Здесь вы устанавливаете выходное изображение как входное изображение, а затем читаете его обратно, ничего не прогнозируя.
Ответ 2
Также наткнулся на сбой неудачного шейдера. Запустите его на другом, более мощном компьютере, проблема исчезнет.
Мне кажется, что у Chrome недостаточно ресурсов для успеха