我这里有一个自定义神经网络,主要由通常的构建块(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);
}