keras - 是否可以用原生 CoreML 替换 keras Lambda 层来转换模型?
问题描述
我第一次需要将 mu keras 模型转换为 coreml。这可以通过coremltools
包来完成,
import coremltools
import keras
model = Model(...) # keras
coreml_model = coremltools.converters.keras.convert(model,
input_names="input_image_NHWC",
output_names="output_image_NHWC",
image_scale=1.0,
model_precision='float32',
use_float_arraytype=True,
custom_conversion_functions={ "Lambda": convert_lambda },
input_name_shape_dict={'input_image_NHWC': [None, 384, 384, 3]}
)
但是,我有两个 lambda 层,其中第一个是深度到空间(pixelshuffle),另一个是缩放器:
def tf_upsampler(x):
return tf.nn.depth_to_space(x, 4)
def mulfunc(x, beta=0.2):
return beta*x
...
x = Lambda(tf_upsampler)(x)
...
x = Lambda(mulfunc)(x)
据我所知,我发现的唯一建议是使用自定义层,稍后需要在 Swift 代码中实现我的层。像这样的东西,MyPixelShuffle
并MyScaleLayer
以某种方式实现为 XCode 项目中的类(?):
def convert_lambda(layer):
# Only convert this Lambda layer if it is for our swish function.
if layer.function == tf_upsampler:
params = NeuralNetwork_pb2.CustomLayerParams()
# The name of the Swift or Obj-C class that implements this layer.
params.className = "MyPixelShuffle"
# The desciption is shown in Xcode's mlmodel viewer.
params.description = "pixelshuffle"
params.parameters["blockSize"].intValue = 4
return params
elif layer.function == mulfunc:
# https://stackoverflow.com/questions/47987777/custom-layer-with-two-parameters-function-on-core-ml
params = NeuralNetwork_pb2.CustomLayerParams()
# The name of the Swift or Obj-C class that implements this layer.
params.className = "MyScaleLayer"
params.description = "scaling input"
# HERE!! This is important.
params.parameters["scale"].doubleValue = 0.2
# The desciption is shown in Xcode's mlmodel viewer.
params.description = "multiplication by constant"
return params
ScaleLayer
但是,我发现 CoreML 实际上有我需要的层,它们可以找到ReorganizeDataLayer
如何使用这些原生层来替换 keras 模型中的 lambda?是否可以为网络编辑 coreML protobuf?或者如果它们有 Swift/OBj-C 类,它们是如何被调用的?
可以通过删除/添加图层来完成coremltools.models.neural_network.NeuralNetworkBuilder
吗?
更新:
我发现keras 转换器实际上调用了神经网络构建器来添加不同的层。Builder 有builder.add_reorganize_data
我需要的层。现在是如何替换模型中的自定义层的问题。我可以将它加载到 builder 和 ispect 层中:
coreml_model_path = 'mymodel.mlmodel'
spec = coremltools.models.utils.load_spec(coreml_model_path)
builder = coremltools.models.neural_network.NeuralNetworkBuilder(spec=spec)
builder.inspect_layers(last=10)
[Id: 417], Name: lambda_10 (Type: custom)
Updatable: False
Input blobs: ['up1_output']
Output blobs: ['lambda_10_output']
解决方案
做这样的事情要简单得多:
def convert_lambda(layer):
if layer.function == tf_upsampler:
params = NeuralNetwork_pb2.ReorganizeDataLayerParams()
params.fillInTheOtherPropertiesHere = someValue
return params
...etc..
换句话说,如果某些现有图层类型已经满足您的需求,您不必返回自定义图层。
推荐阅读
- gitlab - Gitlab API 按主题过滤项目(项目标签)
- azure - 如何仅将 nginx 入口控制器部署到用户节点池
- google-sheets - 当单元格相等时执行数学运算
- python - 如何让我的图像(矩形)与我随机生成的圆圈碰撞以结束游戏?
- javascript - 如何在 json 中使用 mustache 和单个实体呈现 html 块
- python - 查找一系列行并搜索匹配的列参数
- spring-kafka - @Header 和 Spring Stream 函数式编程模型
- c++ - 初始化结构数组 - C++
- javascript - 使用 javascript 在正文中查找乱码
- javascript - Angular FxFlex Layout MediaOberver - 根据给定的 div 计算活动宽度?