CoreML自定义层:使用金属着色器进行像素化规范化

时间:2018-09-21 00:24:34

标签: c++ tensorflow keras metal coreml

我正在将Nvidia的GAN生成器的渐进式增长转换为coreML。我已经设法将所有内容转移到coreML上,除了Pixelwise Normalization(Lambda)层之外,我计划将其实现为Swift / Metal中的自定义coreML层。

在TensorFlow.Keras中,我将像素规范实现为

def pixelwise_norm(a):
    return a / tf.sqrt(tf.reduce_mean(a * a, axis=3, keep_dims=True) + 1e-8)

现在,我几乎从未使用过着色器/金属,但是按照此处的说明进行操作:http://machinethink.net/blog/coreml-custom-layers/,我设置了一个自定义层,以使用Metal进行前馈操作。我使用的MTLComputePipelineState(调用?编码?)以下着色器用于图层的操作:

#include <metal_stdlib>
using namespace metal;


kernel void pixelwise_norm(
              texture2d_array<half, access::read> inTexture [[texture(0)]],
              texture2d_array<half, access::write> outTexture [[texture(1)]],
              ushort3 gid [[thread_position_in_grid]])
{
    if (gid.x >= outTexture.get_width() ||
        gid.y >= outTexture.get_height()) {
        return;
    }

    const float4 x = float4(inTexture.read(gid.xy, gid.z));
    const float4 y = 0.0000001f + (x / sqrt(pow(x,2)));
    outTexture.write(half4(y), gid.xy, gid.z);
}

我在弄清楚“ reduce_mean”的等效金属时遇到了麻烦,现在此着色器实现了〜tensorflow〜操作,如

return a / tf.sqrt((a * a) + 1e-8) 

有人有指针吗? 谢谢

1 个答案:

答案 0 :(得分:0)

如果我没看错的话,那么对于特征图中的每个像素,都可以将该像素除以该像素通道上的L2范数?

在这种情况下,您需要使用for循环来读取该像素的通道,将这些数字求和,然后除以通道数。 (仅当通道数大于4时才需要执行此循环。)

还请注意,您的1e-8必须位于sqrt()内或至少在分母中。