1+ #include < iostream>
2+ #include < cassert>
3+ #include " ./matrix/matrix_def.h"
4+ #include " ./matrix/matrix_pro.h"
5+ #include " ./root/include/edgelayer.h"
6+
7+ // 辅助函数:检查两个浮点数是否近似相等
8+ bool is_close (float a, float b, float rtol = 1e-5 , float atol = 1e-8 ) {
9+ return fabs (a - b) <= (atol + rtol * fabs (b));
10+ }
11+
12+ int main () {
13+ // 创建测试输入 (batch=1, channels=3, height=4, width=4)
14+ Matrix4d input = CreateMatrix4d (1 , 3 , 4 , 4 );
15+
16+ // 用固定的测试值填充输入
17+ float test_input[3 ][4 ][4 ] = {
18+ {{1 ,2 ,3 ,4 }, {2 ,3 ,4 ,5 }, {3 ,4 ,5 ,6 }, {4 ,5 ,6 ,7 }}, // channel 1
19+ {{2 ,4 ,6 ,8 }, {4 ,6 ,8 ,10 }, {6 ,8 ,10 ,12 }, {8 ,10 ,12 ,14 }}, // channel 2
20+ {{3 ,6 ,9 ,12 }, {6 ,9 ,12 ,15 }, {9 ,12 ,15 ,18 }, {12 ,15 ,18 ,21 }} // channel 3
21+ };
22+
23+ for (int c = 0 ; c < 3 ; c++) {
24+ for (int i = 0 ; i < 4 ; i++) {
25+ for (int j = 0 ; j < 4 ; j++) {
26+ input.matrix4d [0 ].matrix3d [c].matrix [i][j] = test_input[c][i][j];
27+ }
28+ }
29+ }
30+
31+ // 创建卷积层并设置固定的卷积核
32+ edge_layer* conv = new conv2d (input, 3 , 2 , 1 , 3 , 0 , 1 );
33+ conv2d* conv_ptr = dynamic_cast <conv2d*>(conv);
34+
35+ // 设置固定的卷积核值
36+ float test_kernel[3 ][2 ][3 ][3 ] = {
37+ {{{1 ,0 ,1 }, {0 ,1 ,0 }, {1 ,0 ,1 }}, // in_channel 0, out_channel 0
38+ {{0 ,1 ,0 }, {1 ,0 ,1 }, {0 ,1 ,0 }}}, // in_channel 0, out_channel 1
39+ {{{1 ,1 ,0 }, {1 ,0 ,1 }, {0 ,1 ,1 }}, // in_channel 1, out_channel 0
40+ {{0 ,1 ,1 }, {1 ,0 ,1 }, {1 ,1 ,0 }}}, // in_channel 1, out_channel 1
41+ {{{0 ,0 ,1 }, {0 ,1 ,0 }, {1 ,0 ,0 }}, // in_channel 2, out_channel 0
42+ {{1 ,0 ,0 }, {0 ,1 ,0 }, {0 ,0 ,1 }}} // in_channel 2, out_channel 1
43+ };
44+
45+ for (int in_c = 0 ; in_c < 3 ; in_c++) {
46+ for (int out_c = 0 ; out_c < 2 ; out_c++) {
47+ conv_ptr->set_kernel (&test_kernel[in_c][out_c][0 ][0 ], in_c, out_c);
48+ }
49+ }
50+
51+ // 前向传播
52+ Matrix4d output = conv->forward (input);
53+ std::cout << " Forward output shape:" << std::endl;
54+ print_shape (output);
55+ std::cout << " Forward output values:" << std::endl;
56+ cout_mat4d (output);
57+
58+ // 验证前向传播的输出尺寸
59+ assert (output.batch == 1 );
60+ assert (output.dep == 2 );
61+ // 计算期望的输出尺寸
62+ int expected_size = ((4 + 2 *1 - 3 ) / 1 ) + 1 ; // ((4 + 2 - 3) / 1) + 1 = 4
63+ assert (output.wid == expected_size);
64+ assert (output.high == expected_size);
65+
66+ // 创建固定的梯度输出
67+ int output_size = ((4 + 2 *1 - 3 ) / 1 ) + 1 ; // 计算正确的输出尺寸
68+ Matrix4d grad_output = CreateMatrix4d (1 , 2 , output_size, output_size);
69+ float test_grad[2 ][4 ][4 ] = {
70+ {{1 ,1 ,1 ,1 }, {1 ,1 ,1 ,1 }, {1 ,1 ,1 ,1 }, {1 ,1 ,1 ,1 }}, // out_channel 0
71+ {{0.5 ,0.5 ,0.5 ,0.5 }, {0.5 ,0.5 ,0.5 ,0.5 }, {0.5 ,0.5 ,0.5 ,0.5 }, {0.5 ,0.5 ,0.5 ,0.5 }} // out_channel 1
72+ };
73+
74+ for (int c = 0 ; c < 2 ; c++) {
75+ for (int i = 0 ; i < 4 ; i++) {
76+ for (int j = 0 ; j < 4 ; j++) {
77+ grad_output.matrix4d [0 ].matrix3d [c].matrix [i][j] = test_grad[c][i][j];
78+ }
79+ }
80+ }
81+
82+ // 反向传播
83+ Matrix4d grad_input = conv->backward (grad_output);
84+ std::cout << " Backward gradients shape:" << std::endl;
85+ print_shape (grad_input);
86+ std::cout << " Backward gradients values:" << std::endl;
87+ cout_mat4d (grad_input);
88+
89+ // 验证反向传播的梯度尺寸
90+ assert (grad_input.batch == 1 );
91+ assert (grad_input.dep == 3 );
92+ assert (grad_input.wid == 4 );
93+ assert (grad_input.high == 4 );
94+
95+ // 验证一些特定位置的梯度值
96+ // 手动计算的预期梯度值
97+ float expected_grads[3 ][4 ][4 ] = {
98+ // channel 0
99+ {
100+ {2 .0f , 1 .5f , 1 .5f , 1 .0f },
101+ {1 .5f , 2 .0f , 2 .0f , 1 .5f },
102+ {1 .5f , 2 .0f , 2 .0f , 1 .5f },
103+ {1 .0f , 1 .5f , 1 .5f , 1 .0f }
104+ },
105+ // channel 1
106+ {
107+ {2 .5f , 2 .0f , 2 .0f , 1 .5f },
108+ {2 .0f , 3 .0f , 3 .0f , 2 .0f },
109+ {2 .0f , 3 .0f , 3 .0f , 2 .0f },
110+ {1 .5f , 2 .0f , 2 .0f , 1 .5f }
111+ },
112+ // channel 2
113+ {
114+ {1 .5f , 1 .0f , 1 .0f , 0 .5f },
115+ {1 .0f , 1 .5f , 1 .5f , 1 .0f },
116+ {1 .0f , 1 .5f , 1 .5f , 1 .0f },
117+ {0 .5f , 1 .0f , 1 .0f , 0 .5f }
118+ }
119+ };
120+
121+ for (int c = 0 ; c < 3 ; c++) {
122+ for (int i = 0 ; i < 4 ; i++) {
123+ for (int j = 0 ; j < 4 ; j++) {
124+ float actual = grad_input.matrix4d [0 ].matrix3d [c].matrix [i][j];
125+ float expected = expected_grads[c][i][j];
126+ if (!is_close (actual, expected)) {
127+ std::cout << " Gradient mismatch at position [" << c << " ][" << i << " ][" << j << " ]" << std::endl;
128+ std::cout << " Expected: " << expected << " , Got: " << actual << std::endl;
129+ }
130+ }
131+ }
132+ }
133+
134+ std::cout << " All tests passed!" << std::endl;
135+
136+ delete conv;
137+ return 0 ;
138+ }
0 commit comments