Core ML 上具有两个参数功能的自定义层

Posted

技术标签:

【中文标题】Core ML 上具有两个参数功能的自定义层【英文标题】:Custom layer with two parameters function on Core ML 【发布时间】:2018-06-07 20:07:51 【问题描述】:

感谢这篇精彩的文章 (http://machinethink.net/blog/coreml-custom-layers/),我了解了如何使用 coremltools 和 Lambda 和 Keras 自定义层编写转换。 但是,我无法理解这种情况,有两个参数的函数。

#python
def scaling(x, scale):
    return x * scale

Keras 层在这里。

#python
up = conv2d_bn(mixed,
                   K.int_shape(x)[channel_axis],
                   1,
                   activation=None,
                   use_bias=True,
                   name=name_fmt('Conv2d_1x1'))
x = Lambda(scaling, # HERE !!
           output_shape=K.int_shape(up)[1:],
           arguments='scale': scale)(up)
x = add([x, up])

在这种情况下,我如何在 Swift 上将 func evaluate(inputs: [MLMultiArray], outputs: [MLMultiArray]) 写入 custom MLCustomLayer class?我只了解一种参数函数情况,像这样,

#swift 
func evaluate(inputs: [MLMultiArray], outputs: [MLMultiArray]) throws 
  for i in 0..<inputs.count 
    let input = inputs[i]
    let output = outputs[i]

    for j in 0..<input.count 
      let x = input[j].floatValue
      let y = x / (1 + exp(-x))
      output[j] = NSNumber(value: y)
    
    

两个参数函数怎么样,比如x * scale

完整代码在这里。

使用自定义层转换为 Core ML 模型 https://github.com/osmszk/dla_team14/blob/master/facenet/coreml/CoremlTest.ipynb Keras 的网络模型 https://github.com/osmszk/dla_team14/blob/master/facenet/code/facenet_keras_v2.py

谢谢。

【问题讨论】:

【参考方案1】:

看起来scale 是一个超参数,而不是一个可学习的参数,对吗?

在这种情况下,您需要将scale 添加到自定义层的参数字典中。然后在您的 Swift 类中,scale 也将在传递给您的 init(parameters) 函数的参数字典中。将其存储在一个属性中,然后在evaluate(inputs, outputs) 中再次从该属性中读取。

我的博客文章实际上展示了如何做到这一点。 ;-)

【讨论】:

哦!太感谢了。我毕业了,你评论了。 是的,你是对的。 scale 是一个超参数。感谢您富有成果的博文和代码,我可以解决这个问题!【参考方案2】:

感谢 hollance 的博客,我以这种方式解决了这个问题。在转换 func 时,在这种情况下,在 convert_lambda 中,我应该为自定义层添加一个 scale 参数。

python代码(转换Core ML)

def convert_lambda(layer):
    if layer.function == scaling:
        params = NeuralNetwork_pb2.CustomLayerParams()

        params.className = "scaling"
        params.description = "scaling input"

        # HERE!! This is important.
        params.parameters["scale"].doubleValue = layer.arguments['scale']

        return params
    else:
        return None

coreml_model = coremltools.converters.keras.convert(
    model,
    input_names="image",
    image_input_names="image",
    output_names="output",
    add_custom_layers=True,
    custom_conversion_functions= "Lambda": convert_lambda )

swift代码(自定义层)

//custom MLCustomLayer `scaling` class
let scale: Float

required init(parameters: [String : Any]) throws 
    if let scale = parameters["scale"] as? Float 
        self.scale = scale
     else 
        self.scale = 1.0
    
    print(#function, parameters, self.scale)
    super.init()


func evaluate(inputs: [MLMultiArray], outputs: [MLMultiArray]) throws 

    for i in 0..<inputs.count 
        let input = inputs[i]
        let output = outputs[i]

        for j in 0..<input.count 
            let x = input[j].floatValue
            let y = x * self.scale
            output[j] = NSNumber(value: y)
        
        //faster
        /*
        let count = input.count
        let inputPointer = UnsafeMutablePointer<Float>(OpaquePointer(input.dataPointer))
        let outputPointer = UnsafeMutablePointer<Float>(OpaquePointer(output.dataPointer))
        var scale = self.scale
        vDSP_vsmul(inputPointer, 1, &scale, outputPointer, 1, vDSP_Length(count))
        */
    

谢谢。

【讨论】:

以上是关于Core ML 上具有两个参数功能的自定义层的主要内容,如果未能解决你的问题,请参考以下文章

android :framework层自定义theme无法取得

具有居中 UISlider 和两个图像的自定义 UITableViewCell

具有滚动功能的自定义 UITabBarController

.NET Core 中的自定义授权属性 [重复]

如何创建不依赖于 ASP.NET Core 声明的自定义 Authorize 属性?

QVector 与具有参数的自定义对象?