首页 文章

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

提问于
浏览
1

感谢这篇精彩的文章(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上的 custom MLCustomLayer class 中编写 func evaluate(inputs: [MLMultiArray], outputs: [MLMultiArray]) ?我理解只是在一个参数函数情况下,像这样,

#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

完整代码在这里 .

谢谢 .

2 回答

  • 3

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

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

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

  • 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 })
    

    快速代码(自定义图层)

    //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))
            */
        }
    }
    

    谢谢 .

相关问题