coremltools: как правильно использовать NeuralNetworkMultiArrayShapeRange? - PullRequest
0 голосов
/ 09 января 2020

У меня есть сеть PyTorch, и я хочу развернуть ее на iOS устройствах. Короче говоря, я не могу добавить гибкость к форме входного тензора в CoreML.

Сеть представляет собой con vnet, который принимает изображение RGB (сохраненное как тензор) в качестве входных данных и возвращает изображение RGB с такой же размер. Используя PyTorch, я могу вводить изображения любого размера, который мне нужен, например тензор размера (1, 3, 300, 300) для изображения 300x300.

Чтобы преобразовать модель PyTorch в модель CoreML, я сначала конвертируйте его в модель ONNX, используя torch.onnx.export. Эта функция требует передачи фиктивного ввода, чтобы он мог выполнить график. Поэтому я использовал:

input = torch.rand(1, 3, 300, 300)

Я предполагаю, что модель ONNX принимает только изображения / тензоры размера (1, 3, 300, 300). Теперь я могу использовать функцию onnx_coreml.convert для преобразования модели ONNX в модель CoreML. Распечатав описание модели CoreML spe c с использованием Python, я получаю что-то вроде:

input {
  name: "my_image"
  type {
    multiArrayType {
      shape: 1
      shape: 3
      shape: 300
      shape: 300
      dataType: FLOAT32
    }
  }
}
output {
  name: "my_output"
  type {
    multiArrayType {
      shape: 1
      shape: 3
      shape: 300
      shape: 300
      dataType: FLOAT32
    }
  }
}
metadata {
  userDefined {
    key: "coremltoolsVersion"
    value: "3.1"
  }
}

Ввод модели должен иметь размер multiArrayType (1, 3, 300, 300). Копируя эту модель в XCode, я вижу при проверке модели, что my_name указано в разделе «Входы» и ожидается, что оно будет MultiArray (Float32 1 x 3 x 300 x 300). Пока что все согласованно.

Моя задача - придать гибкость форме ввода. Я попытался использовать coremltools без удачи. Это моя проблема. Вот мой код:

import coremltools
from coremltools.models.neural_network import flexible_shape_utils

spec = coremltools.utils.load_spec('my_model.mlmodel')

shape_range = flexible_shape_utils.NeuralNetworkMultiArrayShapeRange()
shape_range.add_channel_range((3,3))
shape_range.add_height_range((64, 5000))
shape_range.add_width_range((64, 5000))
flexible_shape_utils.update_multiarray_shape_range(spec, feature_name='my_image', shape_range=shape_range)
coremltools.models.utils.save_spec(spec, 'my_flexible_model.mlmodel')

Я получаю следующее описание spe c, используя Python:

input {
  name: "my_image"
  type {
    multiArrayType {
      shape: 1
      shape: 3
      shape: 300
      shape: 300
      dataType: FLOAT32
      shapeRange {
        sizeRanges {
          lowerBound: 3
          upperBound: 3
        }
        sizeRanges {
          lowerBound: 64
          upperBound: 5000
        }
        sizeRanges {
          lowerBound: 64
          upperBound: 5000
        }
      }
    }
  }
}

Только 3 диапазона, как указано, что имеет смысл, так как я только определил диапазон для канала, высоты и ширины, но не для размера партии. В XCode я получаю следующую ошибку при проверке гибкой модели CoreML:

There was a problem decoding this CoreML document
validator error: Description of multiarray feature 'my_image' has a default 4-d shape but a 3-d shape range

Я почти уверен, что она работала над другим проектом, когда я работал в MacOS X Mojave, но на данный момент я ничего не знаю.

Я использую:

  • macOS X Catalina
  • conda 4.7.12
  • python 3.7.5
  • pytorch 1.3.1
  • onnx 1.6.0
  • onnx-coreml 1.1
  • coremltools 3.1

Спасибо за помощь

1 Ответ

1 голос
/ 09 января 2020

Самое простое, что нужно сделать, это удалить shape:1. Примерно так:

del spec.description.input[0].shape[0]

Теперь фигура по умолчанию также должна иметь 3 измерения.

Однако я бы предложил изменить тип ввода с нескольких массивов на фактическое изображение. Так как вы собираетесь использовать его с изображениями в любом случае. Это позволит вам передать изображение как CVPixelBuffer или CGImage объект вместо MLMultiArray.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...