赞
踩
目录
2、输入4*4*1,卷积核3*3*1,步长1*1,输出2*2*1
3、输入4*4*1,卷积核2*2*1,步长2*2,输出2*2*1
4、输入4*4*1,卷积核3*3*1,步长1*1,padding为1*1,输出2*2*1
5、输入4*4*2,卷积核3*3*2,步长1*1,padding为1*1,输出2*2*1
6、输入4*4*1,卷积核3*3*1,卷积核个数2,步长1*1,padding为1*1,输出2*2*1
7、输入4*4*2,卷积核3*3*2,步长1*1,padding为1*1,膨胀系数2,输出2*2*2
参考资料:
(图解)一步一步使用CPP实现深度学习中的卷积 - GiantPandaCV
其实在上述链接里已经写的非常详细了,为了便于后续理解和学习,所以写个理解的备忘录。
- F[] 为输入;
- width 为输入的宽;
- height 为输入的高;
- channel 为输入的通道;
-
- K[] 为 kernel;
- kSizeX 为 kernel 的宽;
- kSizeY 为 kernel 的高;
- filters 为 kernel 的个数;
- padX 为水平方向的填充;
- padY 为垂直方向的填充;
- strideX 为水平方向的步长;
- strideY 为垂直方向的步长;
-
-
- O[] 为输出;
- outW 为输出的宽;
- outH 为输出的高;
- outChannel 为输出的通道;
- int outH = (height+2*padY-(dilationY*(kSizeY-1)+1)) / strideY + 1;
- int outW = (width+2*padX-(dilationX*(kSizeX-1)+1)) / strideX + 1;
公式说明:
height + 2 * padY
: 首先,将输入图像的高度加上两倍的填充量,这是因为填充是对称地加在图像的顶部和底部。
dilationY * (kSizeY - 1)
: 这是计算卷积核中除了中心元素外,其他元素之间的总间隔。kSizeY - 1
表示卷积核的高度减去中心元素,乘以膨胀系数dilationY
,得到这些元素之间的间隔数。
dilationY * (kSizeY - 1) + 1
: 将上述间隔数加上1,是因为我们还要包括卷积核的中心元素。
(height + 2 * padY - (dilationY * (kSizeY - 1) + 1))
: 这个表达式计算了在考虑填充和膨胀后,输入图像实际上被卷积核覆盖的区域的高度。
/ strideY
: 将上述计算得到的高度除以步长,得到在垂直方向上卷积核可以覆盖的步数。
+ 1
: 最后,由于输出的高度至少要有一个元素,即使计算结果为0,我们也需要加1,以确保输出尺寸至少为1。
封装成demo0(),main()函数可直接调用
- void demo0()
- {
- float F[] = {1,2,3,4,5,6,7,8,9};
- float K[] = {1,2,3,4,5,6,7,8,9};
- float O = 0;
-
- int width = 3;
- int height = 3;
- int kSizeX = 3;
- int kSizeY = 3;
-
- for(int m=0;m<kSizeY;m++)
- {
- for(int n=0;n<kSizeX;n++)
- {
- O+=K[m*kSizeX+n]*F[m*width+n];
- }
- }
-
- std::cout<<O<<" ";
- }
- void demo1()
- {
- float F[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
- float K[] = {1,2,3,4,5,6,7,8,9};
- float O[] = {0,0,0,0};
-
- int padX = 0;
- int padY = 0;
-
- int dilationX = 1;
- int dilationY = 1;
-
- int strideX = 1;
- int strideY = 1;
-
- int width = 4;
- int height = 4;
-
- int kSizeX = 3;
- int kSizeY = 3;
-
- int outH = (height+2*padY-(dilationY*(kSizeY-1)+1)) / strideY + 1;
- int outW = (width+2*padX-(dilationX*(kSizeX-1)+1)) / strideX + 1;
-
- for(int i=0;i<outH;i++)
- {
- for(int j=0;j<outW;j++)
- {
- for(int m=0;m<kSizeY;m++)
- {
- for(int n=0;n<kSizeX;n++)
- {
- O[i*outW+j]+=K[m*kSizeX+n]*F[(m+i)*width+(n+j)];
- }
- }
- }
- }
-
- for (int i = 0; i < outH; ++i)
- {
- for (int j = 0; j < outW; ++j)
- {
- std::cout<<O[i*outW+j]<<" ";
- }
- std::cout<<std::endl;
- }
- }
在内层循环中,计算卷积核覆盖的输入特征图区域的加权和,并将结果累加到输出特征图的相应位置。
- void demo2()
- {
- // (height + 2 * paddingY - (dilationY * (kSizeY - 1) + 1)) / strideY + 1;
- // (width + 2 * paddingX - (dilationX * (kSizeX - 1) + 1)) / strideX + 1;
-
- float F[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
- float K[] = {1,2,3,4};
- //float K[] = {1,2,3,4,5,6,7,8,9};
- float O[] = {0,0,0,0};
-
- int padX = 0;
- int padY = 0;
-
- int dilationX = 1;
- int dilationY = 1;
-
- int strideX = 2;
- int strideY = 2;
-
- int width = 4;
- int height = 4;
-
- int kSizeX = 2;
- int kSizeY = 2;
-
- int outH = (height+2*padY-(dilationY*(kSizeY-1)+1)) / strideY + 1;
- int outW = (width+2*padX-(dilationX*(kSizeX-1)+1)) / strideX + 1;
-
- for(int i=0;i<outH;i++)
- {
- for(int j=0;j<outW;j++)
- {
- for(int m=0;m<kSizeY;m++)
- {
- for(int n=0;n<kSizeX;n++)
- {
- O[i*outW+j]+=K[m*kSizeX+n]*F[(m+i*strideY)*width+(n+j*strideX)];
- }
- }
- }
- }
-
- for (int i = 0; i < outH; ++i)
- {
- for (int j = 0; j < outW; ++j)
- {
- std::cout<<O[i*outW+j]<<" ";
- }
- std::cout<<std::endl;
- }
- }
这个和上一段代码解释相同,只不过步长和卷积核大小有改变。
- void demo3()
- {
- float F[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
- float K[] = {1,2,3,4,5,6,7,8,9};
- float O[] = {0,0,0,0};
-
- int padX = 1;
- int padY = 1;
-
- int dilationX = 1;
- int dilationY = 1;
-
- int strideX = 2;
- int strideY = 2;
-
- int width = 4;
- int height = 4;
-
- int kSizeX = 3;
- int kSizeY = 3;
-
- int outH = (height+2*padY-(dilationY*(kSizeY-1)+1)) / strideY + 1;
- int outW = (width+2*padX-(dilationX*(kSizeX-1)+1)) / strideX + 1;
-
- for(int i=0;i<outH;i++)
- {
- for(int j=0;j<outW;j++)
- {
- for(int m=0;m<kSizeY;m++)
- {
- for(int n=0;n<kSizeX;n++)
- {
- float fVal = 0;
- //考虑边界强情况
- if((n+j*strideX-padX)>-1&&(m+i*strideY-padY>-1)&&(n+j*strideX-padX)<=width&&(m+i*strideY-padY>-1)<=height)
- {
- fVal = F[(m+i*strideY-padX)*width+(n+j*strideX-padY)];
- }
- O[i*outW+j]+=K[m*kSizeX+n]*fVal;
- }
- }
- }
- }
-
- for (int i = 0; i < outH; ++i)
- {
- for (int j = 0; j < outW; ++j)
- {
- std::cout<<O[i*outW+j]<<" ";
- }
- std::cout<<std::endl;
- }
- }
按照正常计算输出规模公式计算的话,应该输出是4*4*1。但是考虑到边界墙问题。
if
语句块用来检查当前卷积核的 m
和 n
索引是否在输入特征图的边界内。这里考虑了填充(padding)的情况:
(n+j*strideX - padX)
计算了卷积核的左边界在输入特征图上的索引。(m+i*strideY - padY)
计算了卷积核的上边界在输入特征图上的索引。> -1
确保索引不会是负数。<= width
和 <= height
确保索引不会超出输入特征图的边界。其中依旧考虑了边界墙问题。
- void demo4()
- {
- float F[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
- float K[] = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9};
- float O[] = {0,0,0,0};
-
- int padX = 1;
- int padY = 1;
-
- int dilationX = 1;
- int dilationY = 1;
-
- int strideX = 2;
- int strideY = 2;
-
- int width = 4;
- int height = 4;
-
- int kSizeX = 3;
- int kSizeY = 3;
-
- int channel = 2;
-
- int outH = (height+2*padY-(dilationY*(kSizeY-1)+1)) / strideY + 1;
- int outW = (width+2*padX-(dilationX*(kSizeX-1)+1)) / strideX + 1;
-
- for (int c = 0; c < channel; ++c)
- {
- for(int i=0;i<outH;i++)
- {
- for(int j=0;j<outW;j++)
- {
- for(int m=0;m<kSizeY;m++)
- {
- for(int n=0;n<kSizeX;n++)
- {
- float fVal = 0;
- if((n+j*strideX-padX)>-1&&(m+i*strideY-padY>-1)&&(n+j*strideX-padX)<=width&&(m+i*strideY-padY>-1)<=height)
- {
- fVal = F[c*width*height + (m+i*strideY-padX)*width+(n+j*strideX-padY)];
- }
- O[i*outW+j]+=K[c*kSizeX*kSizeY+m*kSizeX+n]*fVal;
- }
- }
- }
- }
- }
-
- for (int i = 0; i < outH; ++i)
- {
- for (int j = 0; j < outW; ++j)
- {
- std::cout<<O[i*outW+j]<<" ";
- }
- std::cout<<std::endl;
- }
- }
- void demo5()
- {
- float F[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
- float K[] = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,
- 1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9
- };
- float O[] = {0,0,0,0,0,0,0,0};
-
- int padX = 1;
- int padY = 1;
-
- int dilationX = 1;
- int dilationY = 1;
-
- int strideX = 2;
- int strideY = 2;
-
- int width = 4;
- int height = 4;
-
- int kSizeX = 3;
- int kSizeY = 3;
-
- int channel = 2;
-
- int filters = 2;
-
- int outH = (height+2*padY-(dilationY*(kSizeY-1)+1)) / strideY + 1;
- int outW = (width+2*padX-(dilationX*(kSizeX-1)+1)) / strideX + 1;
-
- int outC = filters;
-
- for (int oc = 0; oc < outC; ++oc)
- {
- for (int c = 0; c < channel; ++c)
- {
- for(int i=0;i<outH;i++)
- {
- for(int j=0;j<outW;j++)
- {
- for(int m=0;m<kSizeY;m++)
- {
- for(int n=0;n<kSizeX;n++)
- {
- float fVal = 0;
- if((n+j*strideX-padX)>-1&&(m+i*strideY-padY>-1)&&(n+j*strideX-padX)<=width&&(m+i*strideY-padY>-1)<=height)
- {
- fVal = F[c*width*height + (m+i*strideY-padX)*width+(n+j*strideX-padY)];
- }
- O[oc*outH*outW+i*outW+j]+=K[oc*outC*kSizeX*kSizeY+c*kSizeX*kSizeY+m*kSizeX+n]*fVal;
- }
- }
- }
- }
- }
- }
-
- for (int oc = 0; oc < outC; ++oc)
- {
- for (int i = 0; i < outH; ++i)
- {
- for (int j = 0; j < outW; ++j)
- {
- std::cout<<O[oc*outH*outW+i*outW+j]<<" ";
- }
- std::cout<<std::endl;
- }
- std::cout<<std::endl<<std::endl;
- }
- }
六个嵌套循环实现了卷积操作:
在最内层循环中,首先检查当前卷积核的索引是否在输入特征图的边界内,如果是,则从输入特征图中取出相应的元素 fVal
。
然后,将 fVal
与对应卷积核的元素相乘,并将结果累加到输出特征图的对应位置。
- void demo6()
- {
- float F[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
- float K[] = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,
- 1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9
- };
- float O[] = {0,0,0,0,0,0,0,0};
-
- int padX = 1;
- int padY = 1;
-
- int dilationX = 2;
- int dilationY = 2;
-
- int strideX = 1;
- int strideY = 1;
-
- int width = 4;
- int height = 4;
-
- int kSizeX = 3;
- int kSizeY = 3;
-
- int channel = 2;
-
- int filters = 2;
-
- int outH = (height+2*padY-(dilationY*(kSizeY-1)+1)) / strideY + 1;
- int outW = (width+2*padX-(dilationX*(kSizeX-1)+1)) / strideX + 1;
-
- int outC = filters;
-
- for (int oc = 0; oc < outC; ++oc)
- {
- for (int c = 0; c < channel; ++c)
- {
- for(int i=0;i<outH;i++)
- {
- for(int j=0;j<outW;j++)
- {
- for(int m=0;m<kSizeY;m++)
- {
- for(int n=0;n<kSizeX;n++)
- {
- float fVal = 0;
- if( ((n+j*strideX)*dilationX-padX)>-1 && ((m+i*strideY)*dilationY-padY)>-1&&
- ((n+j*strideX)*dilationX-padX)<=width && ((m+i*strideY)*dilationY-padY>-1)<=height)
- {
- fVal = F[c*width*height + ((m+i*strideY)*dilationX-padX)*width+((n+j*strideX)*dilationY-padY)];
- }
- O[oc*outH*outW+i*outW+j]+=K[oc*outC*kSizeX*kSizeY+c*kSizeX*kSizeY+m*kSizeX+n]*fVal;
- }
- }
- }
- }
- }
- }
-
- for (int oc = 0; oc < outC; ++oc)
- {
- for (int i = 0; i < outH; ++i)
- {
- for (int j = 0; j < outW; ++j)
- {
- std::cout<<O[oc*outH*outW+i*outW+j]<<" ";
- }
- std::cout<<std::endl;
- }
- std::cout<<std::endl;
- }
- }
- #include <iostream>
-
- void demo0() //输入3*3*1,卷积核3*3*1,输出为1*1*1
- {
- float F[] = {1,2,3,4,5,6,7,8,9};
- float K[] = {1,2,3,4,5,6,7,8,9};
- float O = 0;
-
- int width = 3;
- int height = 3;
- int kSizeX = 3;
- int kSizeY = 3;
-
- for(int m=0;m<kSizeY;m++)
- {
- for(int n=0;n<kSizeX;n++)
- {
- O+=K[m*kSizeX+n]*F[m*width+n];
- }
- }
- std::cout<<O<<" ";
- }
-
- void demo1() //输入4*4*1,卷积核3*3*1,步长为1*1,no padding,输出为1*1*1
- {
- //计算公式
- // (height + 2 * paddingY - (dilationY * (kSizeY - 1) + 1)) / strideY + 1;
- // (width + 2 * paddingX - (dilationX * (kSizeX - 1) + 1)) / strideX + 1;
-
- float F[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
- float K[] = {1,2,3,4,5,6,7,8,9};
- float O[] = {0,0,0,0};
-
- int padX = 0;
- int padY = 0;
-
- int dilationX = 1;
- int dilationY = 1;
-
- int strideX = 1;
- int strideY = 1;
-
- int width = 4;
- int height = 4;
-
- int kSizeX = 3;
- int kSizeY = 3;
-
- int outH = (height+2*padY-(dilationY*(kSizeY-1)+1)) / strideY + 1;
- int outW = (width+2*padX-(dilationX*(kSizeX-1)+1)) / strideX + 1;
-
- for(int i=0;i<outH;i++)
- {
- for(int j=0;j<outW;j++)
- {
- for(int m=0;m<kSizeY;m++)
- {
- for(int n=0;n<kSizeX;n++)
- {
- O[i*outW+j]+=K[m*kSizeX+n]*F[(m+i)*width+(n+j)];
- /* int inputIndex = (i * strideY + m) * width + (j * strideX + n);
- O[i * outW + j] += K[m * kSizeX + n] * F[inputIndex]; */
- }
- }
- }
- }
-
- for (int i = 0; i < outH; ++i)
- {
- for (int j = 0; j < outW; ++j)
- {
- std::cout<<O[i*outW+j]<<" ";
- }
- std::cout<<std::endl;
- }
- }
-
- void demo2()
- {
-
- float F[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
- float K[] = {1,2,3,4};
- //float K[] = {1,2,3,4,5,6,7,8,9};
- float O[] = {0,0,0,0};
-
- int padX = 0;
- int padY = 0;
-
- int dilationX = 1;
- int dilationY = 1;
-
- int strideX = 2;
- int strideY = 2;
-
- int width = 4;
- int height = 4;
-
- int kSizeX = 2;
- int kSizeY = 2;
-
- int outH = (height+2*padY-(dilationY*(kSizeY-1)+1)) / strideY + 1;
- int outW = (width+2*padX-(dilationX*(kSizeX-1)+1)) / strideX + 1;
-
- for(int i=0;i<outH;i++)
- {
- for(int j=0;j<outW;j++)
- {
- for(int m=0;m<kSizeY;m++)
- {
- for(int n=0;n<kSizeX;n++)
- {
- O[i*outW+j]+=K[m*kSizeX+n]*F[(m+i*strideY)*width+(n+j*strideX)];
- }
- }
- }
- }
-
- for (int i = 0; i < outH; ++i)
- {
- for (int j = 0; j < outW; ++j)
- {
- std::cout<<O[i*outW+j]<<" ";
- }
- std::cout<<std::endl;
- }
- }
-
- void demo3()
- {
-
- float F[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
- //float K[] = {1,2,3,4};
- float K[] = {1,2,3,4,5,6,7,8,9};
- float O[] = {0,0,0,0};
-
- int padX = 1;
- int padY = 1;
-
- int dilationX = 1;
- int dilationY = 1;
-
- int strideX = 2;
- int strideY = 2;
-
- int width = 4;
- int height = 4;
-
- int kSizeX = 3;
- int kSizeY = 3;
-
- int outH = (height+2*padY-(dilationY*(kSizeY-1)+1)) / strideY + 1;
- int outW = (width+2*padX-(dilationX*(kSizeX-1)+1)) / strideX + 1;
-
- for(int i=0;i<outH;i++)
- {
- for(int j=0;j<outW;j++)
- {
- for(int m=0;m<kSizeY;m++)
- {
- for(int n=0;n<kSizeX;n++)
- {
- float fVal = 0;
- //考虑边界强情况
- if((n+j*strideX-padX)>-1&&(m+i*strideY-padY>-1)&&(n+j*strideX-padX)<=width&&(m+i*strideY-padY>-1)<=height)
- {
- fVal = F[(m+i*strideY-padX)*width+(n+j*strideX-padY)];
- }
- O[i*outW+j]+=K[m*kSizeX+n]*fVal;
- }
- }
- }
- }
-
- for (int i = 0; i < outH; ++i)
- {
- for (int j = 0; j < outW; ++j)
- {
- std::cout<<O[i*outW+j]<<" ";
- }
- std::cout<<std::endl;
- }
- }
-
- void demo4()
- {
- float F[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
- //float K[] = {1,2,3,4};
- float K[] = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9};
- float O[] = {0,0,0,0};
-
- int padX = 1;
- int padY = 1;
-
- int dilationX = 1;
- int dilationY = 1;
-
- int strideX = 2;
- int strideY = 2;
-
- int width = 4;
- int height = 4;
-
- int kSizeX = 3;
- int kSizeY = 3;
-
- int channel = 2;
-
- int outH = (height+2*padY-(dilationY*(kSizeY-1)+1)) / strideY + 1;
- int outW = (width+2*padX-(dilationX*(kSizeX-1)+1)) / strideX + 1;
-
- for (int c = 0; c < channel; ++c)
- {
- for(int i=0;i<outH;i++)
- {
- for(int j=0;j<outW;j++)
- {
- for(int m=0;m<kSizeY;m++)
- {
- for(int n=0;n<kSizeX;n++)
- {
- float fVal = 0;
- if((n+j*strideX-padX)>-1&&(m+i*strideY-padY>-1)&&(n+j*strideX-padX)<=width&&(m+i*strideY-padY>-1)<=height)
- {
- fVal = F[c*width*height + (m+i*strideY-padX)*width+(n+j*strideX-padY)];
- }
- O[i*outW+j]+=K[c*kSizeX*kSizeY+m*kSizeX+n]*fVal;
- }
- }
- }
- }
- }
-
- for (int i = 0; i < outH; ++i)
- {
- for (int j = 0; j < outW; ++j)
- {
- std::cout<<O[i*outW+j]<<" ";
- }
- std::cout<<std::endl;
- }
- }
-
- void demo5()
- {
-
- float F[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
- //float K[] = {1,2,3,4};
- float K[] = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,
- 1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9
- };
- float O[] = {0,0,0,0,0,0,0,0};
-
- int padX = 1;
- int padY = 1;
-
- int dilationX = 1;
- int dilationY = 1;
-
- int strideX = 2;
- int strideY = 2;
-
- int width = 4;
- int height = 4;
-
- int kSizeX = 3;
- int kSizeY = 3;
-
- int channel = 2;
-
- int filters = 2;
-
- int outH = (height+2*padY-(dilationY*(kSizeY-1)+1)) / strideY + 1;
- int outW = (width+2*padX-(dilationX*(kSizeX-1)+1)) / strideX + 1;
-
- int outC = filters;
-
- for (int oc = 0; oc < outC; ++oc)
- {
- for (int c = 0; c < channel; ++c)
- {
- for(int i=0;i<outH;i++)
- {
- for(int j=0;j<outW;j++)
- {
- for(int m=0;m<kSizeY;m++)
- {
- for(int n=0;n<kSizeX;n++)
- {
- float fVal = 0;
- if((n+j*strideX-padX)>-1&&(m+i*strideY-padY>-1)&&(n+j*strideX-padX)<=width&&(m+i*strideY-padY>-1)<=height)
- {
- fVal = F[c*width*height + (m+i*strideY-padX)*width+(n+j*strideX-padY)];
- }
- O[oc*outH*outW+i*outW+j]+=K[oc*channel*kSizeX*kSizeY+c*kSizeX*kSizeY+m*kSizeX+n]*fVal;
- }
- }
- }
- }
- }
- }
-
- for (int oc = 0; oc < outC; ++oc)
- {
- for (int i = 0; i < outH; ++i)
- {
- for (int j = 0; j < outW; ++j)
- {
- std::cout<<O[oc*outH*outW+i*outW+j]<<" ";
- }
- std::cout<<std::endl;
- }
- std::cout<<std::endl<<std::endl;
- }
- }
-
- void demo6()
- {
- // (height + 2 * paddingY - (dilationY * (kSizeY - 1) + 1)) / strideY + 1;
- // (width + 2 * paddingX - (dilationX * (kSizeX - 1) + 1)) / strideX + 1;
-
- float F[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
- //float K[] = {1,2,3,4};
- float K[] = {1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,
- 1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9
- };
- float O[] = {0,0,0,0,0,0,0,0};
-
- int padX = 1;
- int padY = 1;
-
- int dilationX = 2;
- int dilationY = 2;
-
- int strideX = 1;
- int strideY = 1;
-
- int width = 4;
- int height = 4;
-
- int kSizeX = 3;
- int kSizeY = 3;
-
- int channel = 2;
-
- int filters = 2;
-
- int outH = (height+2*padY-(dilationY*(kSizeY-1)+1)) / strideY + 1;
- int outW = (width+2*padX-(dilationX*(kSizeX-1)+1)) / strideX + 1;
-
- int outC = filters;
-
- for (int oc = 0; oc < outC; ++oc)
- {
- for (int c = 0; c < channel; ++c)
- {
- for(int i=0;i<outH;i++)
- {
- for(int j=0;j<outW;j++)
- {
- for(int m=0;m<kSizeY;m++)
- {
- for(int n=0;n<kSizeX;n++)
- {
- float fVal = 0;
- if( ((n+j*strideX)*dilationX-padX)>-1 && ((m+i*strideY)*dilationY-padY)>-1&&
- ((n+j*strideX)*dilationX-padX)<=width && ((m+i*strideY)*dilationY-padY>-1)<=height)
- {
- fVal = F[c*width*height + ((m+i*strideY)*dilationX-padX)*width+((n+j*strideX)*dilationY-padY)];
- }
- O[oc*outH*outW+i*outW+j]+=K[oc*channel*kSizeX*kSizeY+c*kSizeX*kSizeY+m*kSizeX+n]*fVal;
- }
- }
- }
- }
- }
- }
-
- for (int oc = 0; oc < outC; ++oc)
- {
- for (int i = 0; i < outH; ++i)
- {
- for (int j = 0; j < outW; ++j)
- {
- std::cout<<O[oc*outH*outW+i*outW+j]<<" ";
- }
- std::cout<<std::endl;
- }
- std::cout<<std::endl;
- }
- }
-
-
- int main(int argc, char *argv[])
- {
- //demo0();
- demo1();
- //demo2();
- //demo3();
- //demo4();
- //demo5();
- //demo6();
- }
(1)将上述文件为my_code.cc源文件。
如果要使用不同类型的demo,可以直接在main函数中调用。
(2)然后在终端运行:
g++ -o my_code my_code.cc
此时已编译出可执行的二进制my_code。
(3)执行my_code文件
./my_code
最后说明:其实我个人觉得这种方式使用起来除了简单易懂,但在实际操作中并不可取。主要是所有的变量值都需要在demo()函数中手工赋值,耦合性和实用性较差。但是目前也没有更好的实测,等过阵子我的程序写完后,再和大家分享。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。