Мне удалось создать модель CoreML 2.0 с гибкими размерами формы ввода / вывода:
Однако я не могу понять, как установить размер в моем проекте 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
Нужно ли создавать новый слой и затем связывать его со слоем, который выводится на него, и слоем, на который он выводится?