# Resizegrad — MindSpore Signal+ 使用手册 alpha 文档

# Resizegrad

计算 Resize 操作的梯度。该算子包含两种实现：最近邻插值梯度（ResizeNearestNeighborGrad）和双线性插值梯度（ResizeBiLinearGrad）。用于将上游梯度从输出尺寸反向传播到输入尺寸。

最近邻插值梯度（ResizeNearestNeighborGrad）

对于最近邻插值，输入梯度通过最近邻映射反向传播到输出梯度。

\[\begin{split}out_y = \begin{cases} \mathrm{round}(in_y \cdot height\_scale), & \text{if } align\_corners \\ \lfloor in_y \cdot height\_scale \rfloor, & \text{otherwise} \end{cases}\end{split}\]
\[\begin{split}out_x = \begin{cases} \mathrm{round}(in_x \cdot width\_scale), & \text{if } align\_corners \\ \lfloor in_x \cdot width\_scale \rfloor, & \text{otherwise} \end{cases}\end{split}\]
\[out\_addr[out\_offset] \mathrel{+}= in\_addr[in\_offset]\]

其中 in_addr 是上游梯度（输出尺寸），out_addr 是输入梯度（输入尺寸）。注意使用累加操作（+=），因为多个输入位置可能映射到同一个输出位置。

双线性插值梯度（ResizeBiLinearGrad）

对于双线性插值，输入梯度通过双线性插值的反向传播分配到4个相邻的输出位置。

\[in_y = h \cdot height\_scale\]
\[top_y = \max(\lfloor in_y \rfloor, 0)\]
\[bottom_y = \min(\lceil in_y \rceil, out\_height - 1)\]
\[y_{\mathrm{lerp}} = in_y - \lfloor in_y \rfloor\]
\[inverse\_y\_lerp = 1.0 - y_{\mathrm{lerp}}\]

对于 x 维度有类似的公式：

\[in_x = w \cdot width\_scale\]
\[left_x = \max(\lfloor in_x \rfloor, 0)\]
\[right_x = \min(\lceil in_x \rceil, out\_width - 1)\]
\[x_{\mathrm{lerp}} = in_x - \lfloor in_x \rfloor\]
\[inverse\_x\_lerp = 1.0 - x_{\mathrm{lerp}}\]

输入梯度按权重分配到4个相邻位置：

\[out\_addr[top_y, left_x] \mathrel{+}= in\_addr[h, w] \cdot (inverse\_y\_lerp \cdot inverse\_x\_lerp)\]
\[out\_addr[top_y, right_x] \mathrel{+}= in\_addr[h, w] \cdot (inverse\_y\_lerp \cdot x_{\mathrm{lerp}})\]
\[out\_addr[bottom_y, left_x] \mathrel{+}= in\_addr[h, w] \cdot (y_{\mathrm{lerp}} \cdot inverse\_x\_lerp)\]
\[out\_addr[bottom_y, right_x] \mathrel{+}= in\_addr[h, w] \cdot (y_{\mathrm{lerp}} \cdot x_{\mathrm{lerp}})\]

输入：

  - in_addr - 指向上游梯度数据的指针（输出尺寸的梯度）。

  - out_addr - 指向输出梯度数据的指针（输入尺寸的梯度），需要初始化为0。

  - batch_size - 批次大小。

  - channel - 通道数。

  - format - 数据格式，0 表示 NHWC，1 表示 NCHW。

  - align_corners - 是否对齐角点标志，0 表示不对齐，1 表示对齐。

  - in_height - 输入高度。

  - in_width - 输入宽度。

  - out_height - 输出高度。

  - out_width - 输出宽度。

  - height_scale - 高度缩放因子，通常为 (out_height - 1) / (in_height - 1) 或 out_height / in_height。

  - width_scale - 宽度缩放因子，通常为 (out_width - 1) / (in_width - 1) 或 out_width / in_width。

输出：

  - out_addr - 计算后的输入梯度（输入尺寸的梯度）。

支持平台：

  `FT78NE` `MT7004`

备注

- FT78NE 支持 fp32

- MT7004 支持 fp16, fp32

共享存储版本:

void fp_resizenearestneighborgrad_s(float *in_addr, float *out_addr, int batch_size, int channel, int format, int align_corners, int in_height, int in_width, int out_height, int out_width, float height_scale, float width_scale, int core_mask)

void hp_resizenearestneighborgrad_s(half *in_addr, half *out_addr, int batch_size, int channel, int format, int align_corners, int in_height, int in_width, int out_height, int out_width, float height_scale, float width_scale, int core_mask)

void fp_resizebilineargrad_s(float *in_addr, float *out_addr, int batch_size, int channel, int format, int align_corners, int in_height, int in_width, int out_height, int out_width, float height_scale, float width_scale, int core_mask)

void hp_resizebilineargrad_s(half *in_addr, half *out_addr, int batch_size, int channel, int format, int align_corners, int in_height, int in_width, int out_height, int out_width, float height_scale, float width_scale, int core_mask)

C调用示例（最近邻插值梯度）:

     1#include <stdio.h>
     2#include <resizegrad.h>
     3
     4int main(int argc, char* argv[]) {
     5    float *in_addr = (float *)0x10010000;
     6    float *out_addr = (float *)0x10020000;
     7
     8    int batch_size = 4;
     9    int channel = 3;
    10    int format = 1;
    11    int align_corners = 1;
    12    int in_height = 4, in_width = 4;
    13    int out_height = 6, out_width = 6;
    14    int core_mask = 0xff;
    15
    16    float height_scale = (float)(out_height - 1) / (in_height - 1);
    17    float width_scale = (float)(out_width - 1) / (in_width - 1);
    18
    19    int output_size = in_height * in_width * channel * batch_size;
    20    memset(out_addr, 0, output_size * sizeof(float));
    21
    22    fp_resizenearestneighborgrad_s(in_addr, out_addr, batch_size, channel,
    23                                    format, align_corners, in_height, in_width,
    24                                    out_height, out_width, height_scale, width_scale, core_mask);
    25    return 0;
    26}

私有存储版本:

void fp_resizenearestneighborgrad_p(float *in_addr, float *out_addr, int batch_size, int channel, int format, int align_corners, int in_height, int in_width, int out_height, int out_width, float height_scale, float width_scale)

void hp_resizenearestneighborgrad_p(half *in_addr, half *out_addr, int batch_size, int channel, int format, int align_corners, int in_height, int in_width, int out_height, int out_width, float height_scale, float width_scale)

void fp_resizebilineargrad_p(float *in_addr, float *out_addr, int batch_size, int channel, int format, int align_corners, int in_height, int in_width, int out_height, int out_width, float height_scale, float width_scale)

void hp_resizebilineargrad_p(half *in_addr, half *out_addr, int batch_size, int channel, int format, int align_corners, int in_height, int in_width, int out_height, int out_width, float height_scale, float width_scale)

C调用示例（双线性插值梯度）:

     1#include <stdio.h>
     2#include <resizegrad.h>
     3
     4int main(int argc, char* argv[]) {
     5    float *in_addr = (float *)0x10010000;
     6    float *out_addr = (float *)0x10020000;
     7
     8    int batch_size = 4;
     9    int channel = 3;
    10    int format = 0;
    11    int align_corners = 0;
    12    int in_height = 4, in_width = 4;
    13    int out_height = 6, out_width = 6;
    14
    15    float height_scale = (float)out_height / in_height;
    16    float width_scale = (float)out_width / in_width;
    17
    18    int output_size = in_height * in_width * channel * batch_size;
    19    memset(out_addr, 0, output_size * sizeof(float));
    20
    21    fp_resizebilineargrad_p(in_addr, out_addr, batch_size, channel,
    22                             format, align_corners, in_height, in_width,
    23                             out_height, out_width, height_scale, width_scale);
    24    return 0;
    25}