ermig1979 / Simd

C++ image processing and machine learning library with using of SIMD: SSE, AVX, AVX-512, AMX for x86/x64, VMX(Altivec) and VSX(Power7) for PowerPC, NEON for ARM.
http://ermig1979.github.io/Simd
MIT License
2.03k stars 406 forks source link

Ошибка в коде к статье на Хабре #201

Closed GlebSBrykin closed 1 year ago

GlebSBrykin commented 2 years ago

Сегодня обнаружилась ещё одна ошибка в коде к статье на Хабре (https://habr.com/ru/post/448436/): в наивном коде свёртки для BCHW индекс в массиве смещений берётся некорректный. Параметр dc идёт по обновлённому значению dstC, т.е. делённому на group, таким образом, если group > 1, мы рассматриваем лишь часть массива bias, что неправильно.

float relu(float value)
{
  return value > 0 ? value : 0;
}

void convolution(const float * src, int batch, int srcC, int srcH, int srcW,
    int kernelY, int kernelX, int dilationY, int dilationX, 
    int strideY, int strideX, int padY, int padX, int padH, int padW, int group,
    const float * weight, const float * bias, float * dst, int dstC)
{
  int dstH = (srcH + padY + padH - (dilationY * (kernelY - 1) + 1)) / strideY + 1;
  int dstW = (srcW + padX + padW - (dilationX * (kernelX - 1) + 1)) / strideX + 1;
  dstC = dstC / group;
  srcC = srcC / group;
  for (int b = 0; b < batch; ++b)
  {
    for (int g = 0; g < group; ++g)
    {
      for (int dc = 0; dc < dstC; ++dc)
      {
        for (int dy = 0; dy < dstH; ++dy)
        {
          for (int dx = 0; dx < dstW; ++dx)
          {
            float sum = 0;
            for (int sc = 0; sc < srcC; ++sc)
            {
              for (int ky = 0; ky < kernelY; ky++)
              {
                for (int kx = 0; kx < kernelX; kx++)
                {
                  int sy = dy * strideY + ky * dilationY - padY;
                  int sx = dx * strideX + kx * dilationX - padX;
                  if (sy >= 0 && sy < srcH && sx >= 0 && sx < srcW)
                    sum += 
                    src[(((b*group + g)*srcC + sc)*srcH + sy)*srcW + sx] *
                    weight[(((g*dstC + dc)*srcC + sc)*kernelY + ky)*kernelX + kx];
                }
              }
            }
            dst[(((b*group + g)*dstC + dc)*dstH + dy)*dstW + dx] = sum + bias[dc];
          }
        }
      }
    }
  }
}

У себя я исправил это так:

sum + bias[g * dstC + dc];
ermig1979 commented 2 years ago

Здравствуйте! Размер bias равен dstC. Группы имеют отношение только к свертке, а не к операции добавления bias. Так что код примера верен. P.S. Поторопился с ответом - вы правы (я же его сам изменяю в коде). P.P.S. Пока отредактировать статью на Хабре не представляется возможным - почему-то там сейчас не разрешается редактировать статьи старше 30 дней. Обратился в службу поддержки. Жду ответа.