Используя экспортированную модель 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: короткая длина волос. Вот захват консоли prediction list

Это класс, который я использовал в моем клиенте (машинопись) для прогнозов:

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, например: custom vision exports

Я пытался использовать эти файлы с 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\

Это выходные данные, которые я получаю при запуске вышеуказанной команды: output files затем я загружаю модель, вот мой код для загрузки и прогнозирования с использованием экспортированной модели 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();
  }
}

Затем при отправке элемента холста, взятого из потока веб-камеры, появляется эта ошибка: js error

Как выполнить команду конвертера в формате "сохраненная модель", поскольку структура файла неверна?

Почему я получаю "Ошибка компиляции фрагмента шейдера, бесконечность: необъявленный идентификатор в tf-core.esm"?

Спасибо за ваше время и ответы

Ответ 1

Я думаю, что это простая ошибка в вашем коде: const INPUT_NODE_NAME = 'model_outputs'; вероятно, должно быть 'model_inputs' или как там на самом деле. Здесь вы устанавливаете выходное изображение как входное изображение, а затем читаете его обратно, ничего не прогнозируя.

Ответ 2

Также наткнулся на сбой неудачного шейдера. Запустите его на другом, более мощном компьютере, проблема исчезнет.

Мне кажется, что у Chrome недостаточно ресурсов для успеха