在一系列MPSCNNConvolution之后实现自定义层

时间:2016-12-29 04:24:56

标签: ios neural-network convolution conv-neural-network metal

我这里有一个自定义神经网络,主要由通常的构建块(conv,relu,max pool等)组成。

但是最后一层在某些特征通道上需要一个sigmoid,而在其他特征通道上需要softmax(试图预测类和一个置信度指数)。

无论如何,我正在尝试在我的卷积结束时在MPSImage.texture上构建一个Metal操作。

这是毛茸茸的地方。我认为每个conv_img.texture数组条目包含4层神经网络(每个rgba通道一个

如果我有自定义金属线程代码,我将获得一个对应于每个网格条目4个图层的值。

这是我的sigmoid示例,它应该在所需的图层中获取网格值,并将输出值存储在其他图层中。

我不认为它会因上述原因而起作用。

我喜欢一些帮助,或者在Apple提供MPSConvolution之后实现自定义图层的一些示例。

kernel void sigmoid(texture2d_array<float, access::read> inTexture [[texture(0)]],
                    texture2d_array<float, access::write> outTexture [[texture(1)]],
                    uint3 gid [[thread_position_in_grid]]) {

    if (gid.x >= outTexture.get_width()
        || gid.y >= outTexture.get_height()
        || gid.z >= outTexture.get_array_size()) {
        return;
    }

    const uint classes = 80;
    const uint coords = 4;
    const uint size_pred = (classes + coords + 1);

    uint layer = size_pred * gid.z + 4;
    float4 x = inTexture.read(uint2(gid.x, gid.y), layer);
    float4 y = float4(1.0 / (1.0 + exp(-x)));
    outTexture.write(y, uint2(gid.x, gid.y), gid.z);
}
编辑:这就是我一直在尝试调试它的方式 在具有所有值的最终缓冲区中,我应该看到一些东西 最初看起来像我的线程网格 但它似乎没有用。

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

    const uint classes = 80;
    const uint coords = 4;
    const uint texture_channels = 4;
    const uint size_pred = (classes + coords + 1) / texture_channels;

    const uint layer = size_pred * gid.z + 4;
    const uint offset = layer % texture_channels;
    const float4 channels = inTexture.read(uint2(gid.x, gid.y), layer);
    // const float r = x[0]
    // const float g = x[1]
    // const float b = x[2]
    // const float a = x[3]
    const float channel_of_interest = channels[offset];

    // in the output buffer should see a bunch of numbers that look 
    // like the thread grid
    const float y = gid.x * 10000 + gid.y * 10 + gid.z;
    // float y = float(1.0 / (1.0 + exp(-channel_of_interest)));
    const uint new_offset = gid.z % texture_channels;
    float4 new_channels = 0;
    new_channels[new_offset] = y;
    outTexture.write(y, uint2(gid.x, gid.y), gid.z);
}

0 个答案:

没有答案