Указание размеров ввода / вывода для модели CoreML 2 с гибкими формами - PullRequest
0 голосов
/ 01 ноября 2018

Мне удалось создать модель CoreML 2.0 с гибкими размерами формы ввода / вывода:

enter image description here

Однако я не могу понять, как установить размер в моем проекте XCode. Если я установлю размер буфера входного пикселя 2048x2048, буфер выходного пикселя будет по-прежнему 1536x1536. Если я установлю его на 768x768, результирующий пиксельный буфер будет все еще 1536x1536 - но будет пустым за пределами области 768x768.

Я изучил автоматически сгенерированный класс модели Swift и не вижу там никаких подсказок.

Я не могу найти ни одного примера, показывающего, как использовать размеры "Гибкость".

В сессии 708 WWDC 2018 «Что нового в Core ML», часть 1, говорится:

Это означает, что теперь вам нужно отправить одну модель. Вам не нужно иметь избыточный код. И если вам нужно переключаться между стандартным и высоким разрешением, вы можете сделать это намного быстрее, потому что нам не нужно перезагружать модель с нуля; нам просто нужно изменить его размер. У вас есть два варианта, чтобы указать гибкость модели. Вы можете определить диапазон для его размера, чтобы вы могли определить минимальную ширину и высоту, а также максимальную ширину и высоту. А затем при выводе выбрать любое значение между. Но есть и другой способ. Вы можете перечислить все формы, которые вы собираетесь использовать. Например, все разные соотношения сторон, все разные разрешения, и это лучше для производительности. Core ML знает больше о вашем сценарии использования ранее, так что он может - у него есть возможность проводить больше оптимизаций.

Они говорят: «Нам просто нужно изменить его размер». Это так расстраивает, потому что они не говорят вам, как просто изменить его размер! Они также говорят: «А затем на умозаключении выбирают любое значение между», но не дают ни малейшего понятия, как выбрать промежуточное значение!

Вот как я добавил гибкие размеры форм:

import coremltools
from coremltools.models.neural_network import flexible_shape_utils
spec = coremltools.utils.load_spec('mymodel_fxedShape.mlmodel')
img_size_ranges = flexible_shape_utils.NeuralNetworkImageSizeRange()
img_size_ranges.add_height_range(640, 2048)
img_size_ranges.add_width_range(640, 2048)
flexible_shape_utils.update_image_size_range(spec, feature_name='inputImage', size_range=img_size_ranges)
flexible_shape_utils.update_image_size_range(spec, feature_name='outputImage', size_range=img_size_ranges)
coremltools.utils.save_spec(spec, 'myModel.mlmodel')

Вот описание модели:

description {
  input {
    name: "inputImage"
    shortDescription: "Image to stylize"
    type {
      imageType {
        width: 1536
        height: 1536
        colorSpace: BGR
        imageSizeRange {
          widthRange {
            lowerBound: 640
            upperBound: 2048
          }
          heightRange {
            lowerBound: 640
            upperBound: 2048
          }
        }
      }
    }
  }
  output {
    name: "outputImage"
    shortDescription: "Stylized image"
    type {
      imageType {
        width: 1536
        height: 1536
        colorSpace: BGR
        imageSizeRange {
          widthRange {
            lowerBound: 640
            upperBound: 2048
          }
          heightRange {
            lowerBound: 640
            upperBound: 2048
          }
        }
      }
    }
  }
}

Существует два слоя, использующих «outputShape»:

layers {
    name: "SpatialFullConvolution_63"
    input: "Sequential_53"
    output: "SpatialFullConvolution_63_output"
    convolution {
      outputChannels: 16
      kernelChannels: 32
      nGroups: 1
      kernelSize: 3
      kernelSize: 3
      stride: 2
      stride: 2
      dilationFactor: 1
      dilationFactor: 1
      valid {
        paddingAmounts {
          borderAmounts {
          }
          borderAmounts {
          }
        }
      }
      isDeconvolution: true
      hasBias: true
      weights {
      }
      bias {
      }
      outputShape: 770
      outputShape: 770
    }
  }
  ...relu layer...
  layers {
    name: "SpatialFullConvolution_67"
    input: "ReLU_66"
    output: "SpatialFullConvolution_67_output"
    convolution {
      outputChannels: 8
      kernelChannels: 16
      nGroups: 1
      kernelSize: 3
      kernelSize: 3
      stride: 2
      stride: 2
      dilationFactor: 1
      dilationFactor: 1
      valid {
        paddingAmounts {
          borderAmounts {
          }
          borderAmounts {
          }
        }
      }
      isDeconvolution: true
      hasBias: true
      weights {
      }
      bias {
      }
      outputShape: 1538
      outputShape: 1538
    }
  }

Я сейчас пытаюсь выяснить, как удалить outputShape из этих двух слоев.

>>> layer = spec.neuralNetwork.layers[49]
>>> layer.convolution.outputShape
[1538L, 1538L]

Я попытался установить его на []:

layer.convolution.outputShape = []

в форму:

layer.convolution.outputShape = flexible_shape_utils.Shape(())

Что бы я ни пытался, я получаю ошибку:

TypeError: Can't set composite field

Нужно ли создавать новый слой и затем связывать его со слоем, который выводится на него, и слоем, на который он выводится?

...