2017-12-27 5 views
1

Dank dieses großartige Artikel (http://machinethink.net/blog/coreml-custom-layers/), habe ich verstanden, wie man Konvertierung mit Coremltools und Lambda mit Keras benutzerdefinierte Schicht schreiben. Aber ich kann nicht auf die Situation verstehen, Funktion mit zwei Parametern.Benutzerdefinierte Schicht mit zwei Parametern Funktion auf Core ML

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

Keras-Schicht ist hier.

#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]) 

Auf dieser Situation, wie kann ich schreiben func evaluate(inputs: [MLMultiArray], outputs: [MLMultiArray]) in custom MLCustomLayer class auf Swift? Ich verstehe nur in einer Parameterfunktion Situation wie dieser,

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

Wie über zwei Parameter Funktion, wie x * scale?

Der vollständige Code ist hier.

Danke.

Antwort

1

Es sieht aus wie scale ist ein Hyperparameter, kein erlernbarer Parameter, ist das richtig? In diesem Fall müssen Sie scale dem Parameterverzeichnis für die benutzerdefinierte Ebene hinzufügen. Dann wird scale in Ihrer Swift-Klasse auch im Parameterwörterbuch enthalten sein, das an Ihre init(parameters)-Funktion übergeben wird. Speichern Sie es in einer Eigenschaft und dann in evaluate(inputs, outputs) lesen Sie wieder von dieser Eigenschaft.

Mein Blogpost zeigt tatsächlich, wie man das macht. ;-)

+0

Oh! Ich danke dir sehr. Ich bin so grad, dass du kommentiert hast. – osmszk

+0

Ja, Sie haben Recht. Die "Skala" ist ein Hyperparameter. Dank Ihres fruchtbaren Blogposts und Ihres Codes konnte ich dieses Problem lösen! – osmszk

+0

Vielen Dank soooo viel! – osmszk

1

Ich habe dieses Problem auf diesem Weg dank Hollance's Blog gelöst. Beim Konvertieren von func, in diesem Fall in convert_lambda, hätte ich einen scale Parameter für die benutzerdefinierte Ebene hinzugefügt.

Python-Code (Umwandlung von 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-Code (Custom Schicht)

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

Danke.

Verwandte Themen