/home/liu/actions-runner/_work/ccv/ccv/test/unit/nnc/autograd.tests.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "case.h" |
2 | | #include "ccv_case.h" |
3 | | #include "ccv_nnc_case.h" |
4 | | #include <ccv.h> |
5 | | #include <nnc/ccv_nnc.h> |
6 | | #include <nnc/ccv_nnc_easy.h> |
7 | | |
8 | | TEST_SETUP() |
9 | | { |
10 | | ccv_nnc_init(); |
11 | | } |
12 | | |
13 | | TEST_CASE("simple autograd with D[x * x + Log[1 / x], x] when x = 0.84") |
14 | 1 | { |
15 | 1 | ccv_nnc_symbolic_graph_t* symbolic_graph = ccv_nnc_symbolic_graph_new(); |
16 | 1 | ccv_nnc_tensor_symbol_t one = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "1"); |
17 | 1 | ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "x"); |
18 | | // w = x * x |
19 | 1 | ccv_nnc_tensor_symbol_t w = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "w"); |
20 | | // u = 1 / x |
21 | 1 | ccv_nnc_tensor_symbol_t u = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "u"); |
22 | | // v = Log[u] |
23 | 1 | ccv_nnc_tensor_symbol_t v = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "v"); |
24 | | // z = w + v |
25 | 1 | ccv_nnc_tensor_symbol_t z = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "z"); |
26 | 1 | ccv_nnc_graph_exec_symbol_t prod = ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWPROD_FORWARD(), TENSOR_SYMBOL_LIST(x, x), TENSOR_SYMBOL_LIST(w), "prod"); |
27 | 1 | ccv_nnc_graph_exec_symbol_t inv = ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWDIV_FORWARD(), TENSOR_SYMBOL_LIST(one, x), TENSOR_SYMBOL_LIST(u), "inv"); |
28 | 1 | ccv_nnc_graph_exec_symbol_t log = ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWLOG_FORWARD(), TENSOR_SYMBOL_LIST(u), TENSOR_SYMBOL_LIST(v), "log"); |
29 | 1 | ccv_nnc_graph_exec_symbol_t sum = ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWSUM_FORWARD(), TENSOR_SYMBOL_LIST(w, v), TENSOR_SYMBOL_LIST(z), "sum"); |
30 | 1 | ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, GRAPH_EXEC_SYMBOL_LIST(prod, inv, log, sum), 0); |
31 | 1 | ccv_nnc_symbolic_graph_backward(symbolic_graph, TENSOR_SYMBOL_LIST(z), TENSOR_SYMBOL_LIST(x), GRAPH_EXEC_SYMBOL_LIST(prod, inv), GRAPH_EXEC_SYMBOL_LIST(sum)); |
32 | 1 | ccv_nnc_graph_t* graph = 0; |
33 | 1 | ccv_nnc_tensor_arena_t* tensor_arena = 0; |
34 | 1 | ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0; |
35 | 1 | ccv_nnc_tensor_symbol_t dx = ccv_nnc_tensor_symbol_for_backward(symbolic_graph, x); |
36 | 1 | ccv_nnc_graph_exec_symbol_t dxc = ccv_nnc_graph_exec_symbol_for_backward(symbolic_graph, dx); |
37 | 1 | ccv_nnc_symbolic_graph_compile(symbolic_graph, ccv_nnc_default_compile_params, 0, 0, TENSOR_SYMBOL_LIST(z, dx), GRAPH_EXEC_SYMBOL_LIST(prod, inv), GRAPH_EXEC_SYMBOL_LIST(dxc, sum), &graph, &tensor_arena, &graph_exec_arena); |
38 | 1 | SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH); |
39 | 1 | GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH); |
40 | 1 | ccv_nnc_tensor_t* tone = ccv_nnc_tensor_from_symbol(tensor_arena, one); |
41 | 1 | tone->data.f32[0] = 1; |
42 | 1 | ccv_nnc_tensor_t* tx = ccv_nnc_tensor_from_symbol(tensor_arena, x); |
43 | 1 | tx->data.f32[0] = 0.84; |
44 | 1 | ccv_nnc_tensor_symbol_t dz = ccv_nnc_tensor_symbol_for_backward(symbolic_graph, z); |
45 | 1 | ccv_nnc_tensor_t* tdz = ccv_nnc_tensor_from_symbol(tensor_arena, dz); |
46 | | // Seed the initialization vector. |
47 | 1 | tdz->data.f32[0] = 1; |
48 | 1 | ccv_nnc_graph_run(graph, 0, GRAPH_EXEC_LIST(ccv_nnc_graph_exec_from_symbol(graph_exec_arena, prod), ccv_nnc_graph_exec_from_symbol(graph_exec_arena, inv)), GRAPH_EXEC_LIST(ccv_nnc_graph_exec_from_symbol(graph_exec_arena, dxc), ccv_nnc_graph_exec_from_symbol(graph_exec_arena, sum)), 0, 0); |
49 | 1 | ccv_nnc_tensor_t* tz = ccv_nnc_tensor_from_symbol(tensor_arena, z); |
50 | 1 | ccv_nnc_tensor_t* tdx = ccv_nnc_tensor_from_symbol(tensor_arena, dx); |
51 | 1 | REQUIRE_EQ_WITH_TOLERANCE(tz->data.f32[0], 0.84 * 0.84 + logf(1.0 / 0.84), 1e-6, "computed result of x * x + Log[1 / x] should be the same"); |
52 | 1 | REQUIRE_EQ_WITH_TOLERANCE(tdx->data.f32[0], 2 * 0.84 - (1.0 / 0.84), 1e-6, "computed result of D[x * x + Log[1 / x], x] should be the same"); |
53 | 1 | ccv_nnc_symbolic_graph_free(symbolic_graph); |
54 | 1 | ccv_nnc_graph_free(graph); |
55 | 1 | ccv_nnc_tensor_arena_free(tensor_arena); |
56 | 1 | ccv_nnc_graph_exec_arena_free(graph_exec_arena); |
57 | 1 | } |
58 | | |
59 | | TEST_CASE("autograd with D[y, x] when x = 10 and y = 1 (no x presence in the formula)") |
60 | 1 | { |
61 | 1 | ccv_nnc_symbolic_graph_t* symbolic_graph = ccv_nnc_symbolic_graph_new(); |
62 | 1 | ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "x"); |
63 | 1 | ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "y"); |
64 | 1 | ccv_nnc_graph_exec_symbol_t set = ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_SET_FORWARD(1), TENSOR_SYMBOL_LIST(), TENSOR_SYMBOL_LIST(y), "set"); |
65 | 1 | ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS); |
66 | 1 | ccv_nnc_symbolic_graph_backward(symbolic_graph, TENSOR_SYMBOL_LIST(y), TENSOR_SYMBOL_LIST(x), GRAPH_EXEC_SYMBOL_LIST(set), GRAPH_EXEC_SYMBOL_LIST(set)); |
67 | 1 | SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH); |
68 | 1 | ccv_nnc_graph_t* graph = 0; |
69 | 1 | ccv_nnc_tensor_arena_t* tensor_arena = 0; |
70 | 1 | ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0; |
71 | 1 | ccv_nnc_tensor_symbol_t dx = ccv_nnc_tensor_symbol_for_backward(symbolic_graph, x); |
72 | 1 | ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS); |
73 | 1 | ccv_nnc_symbolic_graph_compile(symbolic_graph, ccv_nnc_default_compile_params, 0, 0, TENSOR_SYMBOL_LIST(dx), ccv_nnc_symbolic_graph_sources(symbolic_graph), ccv_nnc_symbolic_graph_source_size(symbolic_graph), ccv_nnc_symbolic_graph_destinations(symbolic_graph), ccv_nnc_symbolic_graph_destination_size(symbolic_graph), &graph, &tensor_arena, &graph_exec_arena); |
74 | 1 | GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH); |
75 | 1 | ccv_nnc_tensor_t* tx = ccv_nnc_tensor_from_symbol(tensor_arena, x); |
76 | 1 | if (tx) |
77 | 0 | tx->data.f32[0] = 10; |
78 | 1 | ccv_nnc_tensor_t* ty = ccv_nnc_tensor_from_symbol(tensor_arena, y); |
79 | 1 | if (ty) |
80 | 1 | ty->data.f32[0] = 1; |
81 | 1 | ccv_nnc_tensor_symbol_t dy = ccv_nnc_tensor_symbol_for_backward(symbolic_graph, y); |
82 | 1 | ccv_nnc_tensor_t* tdy = ccv_nnc_tensor_from_symbol(tensor_arena, dy); |
83 | | // Seed the initialization vector if needed. |
84 | 1 | if (tdy) |
85 | 0 | tdy->data.f32[0] = 1; |
86 | 1 | ccv_nnc_graph_exec_t source = ccv_nnc_graph_exec_source(graph_exec_arena); |
87 | 1 | ccv_nnc_graph_exec_t destination = ccv_nnc_graph_exec_destination(graph_exec_arena); |
88 | 1 | ccv_nnc_graph_run(graph, 0, &source, 1, &destination, 1, 0, 0); |
89 | 1 | ccv_nnc_tensor_t* tdx = ccv_nnc_tensor_from_symbol(tensor_arena, dx); |
90 | 1 | REQUIRE_EQ_WITH_TOLERANCE(tdx->data.f32[0], 0, 1e-6, "computed result of D[y, x] should be 0"); |
91 | 1 | ccv_nnc_symbolic_graph_free(symbolic_graph); |
92 | 1 | ccv_nnc_graph_free(graph); |
93 | 1 | ccv_nnc_tensor_arena_free(tensor_arena); |
94 | 1 | ccv_nnc_graph_exec_arena_free(graph_exec_arena); |
95 | 1 | } |
96 | | |
97 | | TEST_CASE("autograd with D[(x - y) * (x + 1), [x, y]] when x = 43.24 and y = 0.38") |
98 | 1 | { |
99 | 1 | ccv_nnc_symbolic_graph_t* symbolic_graph = ccv_nnc_symbolic_graph_new(); |
100 | 1 | ccv_nnc_tensor_symbol_t one = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "1"); |
101 | 1 | ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "x"); |
102 | 1 | ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "y"); |
103 | | // w = x - y |
104 | 1 | ccv_nnc_tensor_symbol_t w = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "w"); |
105 | | // u = y + 1 |
106 | 1 | ccv_nnc_tensor_symbol_t u = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "u"); |
107 | | // v = w * u |
108 | 1 | ccv_nnc_tensor_symbol_t v = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "v"); |
109 | 1 | ccv_nnc_graph_exec_symbol_t minus = ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_ADD_FORWARD(1, -1), TENSOR_SYMBOL_LIST(x, y), TENSOR_SYMBOL_LIST(w), "minus"); |
110 | 1 | ccv_nnc_graph_exec_symbol_t plus = ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_ADD_FORWARD(1, 1), TENSOR_SYMBOL_LIST(y, one), TENSOR_SYMBOL_LIST(u), "plus"); |
111 | 1 | ccv_nnc_graph_exec_symbol_t prod = ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWPROD_FORWARD(), TENSOR_SYMBOL_LIST(w, u), TENSOR_SYMBOL_LIST(v), "prod"); |
112 | 1 | ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, GRAPH_EXEC_SYMBOL_LIST(minus, plus, prod), 0); |
113 | 1 | ccv_nnc_symbolic_graph_backward(symbolic_graph, TENSOR_SYMBOL_LIST(v), TENSOR_SYMBOL_LIST(x, y), GRAPH_EXEC_SYMBOL_LIST(minus, plus), GRAPH_EXEC_SYMBOL_LIST(prod)); |
114 | 1 | ccv_nnc_graph_t* graph = 0; |
115 | 1 | ccv_nnc_tensor_arena_t* tensor_arena = 0; |
116 | 1 | ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0; |
117 | 1 | ccv_nnc_tensor_symbol_t dx = ccv_nnc_tensor_symbol_for_backward(symbolic_graph, x); |
118 | 1 | ccv_nnc_graph_exec_symbol_t dxc = ccv_nnc_graph_exec_symbol_for_backward(symbolic_graph, dx); |
119 | 1 | ccv_nnc_tensor_symbol_t dy = ccv_nnc_tensor_symbol_for_backward(symbolic_graph, y); |
120 | 1 | ccv_nnc_graph_exec_symbol_t dyc = ccv_nnc_graph_exec_symbol_for_backward(symbolic_graph, dy); |
121 | 1 | ccv_nnc_symbolic_graph_compile(symbolic_graph, ccv_nnc_default_compile_params, 0, 0, TENSOR_SYMBOL_LIST(v, dx, dy), GRAPH_EXEC_SYMBOL_LIST(minus, plus), GRAPH_EXEC_SYMBOL_LIST(dxc, dyc, prod), &graph, &tensor_arena, &graph_exec_arena); |
122 | 1 | SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH); |
123 | 1 | GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH); |
124 | 1 | ccv_nnc_tensor_t* tone = ccv_nnc_tensor_from_symbol(tensor_arena, one); |
125 | 1 | tone->data.f32[0] = 1; |
126 | 1 | ccv_nnc_tensor_t* tx = ccv_nnc_tensor_from_symbol(tensor_arena, x); |
127 | 1 | tx->data.f32[0] = 43.24; |
128 | 1 | ccv_nnc_tensor_t* ty = ccv_nnc_tensor_from_symbol(tensor_arena, y); |
129 | 1 | ty->data.f32[0] = 0.38; |
130 | 1 | ccv_nnc_tensor_symbol_t dv = ccv_nnc_tensor_symbol_for_backward(symbolic_graph, v); |
131 | 1 | ccv_nnc_tensor_t* tdv = ccv_nnc_tensor_from_symbol(tensor_arena, dv); |
132 | | // Seed the initialization vector. |
133 | 1 | tdv->data.f32[0] = 1; |
134 | 1 | ccv_nnc_graph_run(graph, 0, GRAPH_EXEC_LIST(ccv_nnc_graph_exec_from_symbol(graph_exec_arena, minus), ccv_nnc_graph_exec_from_symbol(graph_exec_arena, plus)), GRAPH_EXEC_LIST(ccv_nnc_graph_exec_from_symbol(graph_exec_arena, dxc), ccv_nnc_graph_exec_from_symbol(graph_exec_arena, dyc), ccv_nnc_graph_exec_from_symbol(graph_exec_arena, prod)), 0, 0); |
135 | 1 | ccv_nnc_tensor_t* tv = ccv_nnc_tensor_from_symbol(tensor_arena, v); |
136 | 1 | ccv_nnc_tensor_t* tdx = ccv_nnc_tensor_from_symbol(tensor_arena, dx); |
137 | 1 | ccv_nnc_tensor_t* tdy = ccv_nnc_tensor_from_symbol(tensor_arena, dy); |
138 | 1 | REQUIRE_EQ_WITH_TOLERANCE(tv->data.f32[0], (43.24 - 0.38) * (0.38 + 1), 1e-6, "computed result of (x + y) * (y + 1) should be the same"); |
139 | 1 | REQUIRE_EQ_WITH_TOLERANCE(tdx->data.f32[0], 0.38 + 1, 1e-6, "computed result of D[(x + y) * (y + 1), x] should be the same"); |
140 | 1 | REQUIRE_EQ_WITH_TOLERANCE(tdy->data.f32[0], -2 * 0.38 + 43.24 - 1, 1e-6, "computed result of D[(x + y) * (y + 1), y] should be the same"); |
141 | 1 | ccv_nnc_symbolic_graph_free(symbolic_graph); |
142 | 1 | ccv_nnc_graph_free(graph); |
143 | 1 | ccv_nnc_tensor_arena_free(tensor_arena); |
144 | 1 | ccv_nnc_graph_exec_arena_free(graph_exec_arena); |
145 | 1 | } |
146 | | |
147 | | TEST_CASE("partial autograd with D[y * x + Log[1 / x], y] when x = 0.84 and y = 1.23") |
148 | 1 | { |
149 | 1 | ccv_nnc_symbolic_graph_t* symbolic_graph = ccv_nnc_symbolic_graph_new(); |
150 | 1 | ccv_nnc_tensor_symbol_t one = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "1"); |
151 | 1 | ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "x"); |
152 | 1 | ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "y"); |
153 | | // w = y * x |
154 | 1 | ccv_nnc_tensor_symbol_t w = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "w"); |
155 | | // u = 1 / x |
156 | 1 | ccv_nnc_tensor_symbol_t u = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "u"); |
157 | | // v = Log[u] |
158 | 1 | ccv_nnc_tensor_symbol_t v = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "v"); |
159 | | // z = w + v |
160 | 1 | ccv_nnc_tensor_symbol_t z = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "z"); |
161 | 1 | ccv_nnc_graph_exec_symbol_t prod = ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWPROD_FORWARD(), TENSOR_SYMBOL_LIST(y, x), TENSOR_SYMBOL_LIST(w), "prod"); |
162 | 1 | ccv_nnc_graph_exec_symbol_t inv = ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWDIV_FORWARD(), TENSOR_SYMBOL_LIST(one, x), TENSOR_SYMBOL_LIST(u), "inv"); |
163 | 1 | ccv_nnc_graph_exec_symbol_t log = ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWLOG_FORWARD(), TENSOR_SYMBOL_LIST(u), TENSOR_SYMBOL_LIST(v), "log"); |
164 | 1 | ccv_nnc_graph_exec_symbol_t sum = ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWSUM_FORWARD(), TENSOR_SYMBOL_LIST(w, v), TENSOR_SYMBOL_LIST(z), "sum"); |
165 | 1 | ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, GRAPH_EXEC_SYMBOL_LIST(prod, inv, log, sum), 0); |
166 | 1 | ccv_nnc_symbolic_graph_backward(symbolic_graph, TENSOR_SYMBOL_LIST(z), TENSOR_SYMBOL_LIST(y), GRAPH_EXEC_SYMBOL_LIST(prod, inv), GRAPH_EXEC_SYMBOL_LIST(sum)); |
167 | 1 | ccv_nnc_graph_t* graph = 0; |
168 | 1 | ccv_nnc_tensor_arena_t* tensor_arena = 0; |
169 | 1 | ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0; |
170 | 1 | ccv_nnc_tensor_symbol_t dy = ccv_nnc_tensor_symbol_for_backward(symbolic_graph, y); |
171 | 1 | ccv_nnc_graph_exec_symbol_t dyc = ccv_nnc_graph_exec_symbol_for_backward(symbolic_graph, dy); |
172 | 1 | ccv_nnc_symbolic_graph_compile(symbolic_graph, ccv_nnc_default_compile_params, 0, 0, TENSOR_SYMBOL_LIST(z, dy), GRAPH_EXEC_SYMBOL_LIST(prod, inv), GRAPH_EXEC_SYMBOL_LIST(dyc, sum), &graph, &tensor_arena, &graph_exec_arena); |
173 | 1 | SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH); |
174 | 1 | ccv_nnc_graph_set_default_static_schedule(graph, CCV_STREAM_CONTEXT_CPU, 0); |
175 | 1 | GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH); |
176 | 1 | ccv_nnc_tensor_t* tone = ccv_nnc_tensor_from_symbol(tensor_arena, one); |
177 | 1 | tone->data.f32[0] = 1; |
178 | 1 | ccv_nnc_tensor_t* tx = ccv_nnc_tensor_from_symbol(tensor_arena, x); |
179 | 1 | tx->data.f32[0] = 0.84; |
180 | 1 | ccv_nnc_tensor_t* ty = ccv_nnc_tensor_from_symbol(tensor_arena, y); |
181 | 1 | ty->data.f32[0] = 1.23; |
182 | 1 | ccv_nnc_tensor_symbol_t dz = ccv_nnc_tensor_symbol_for_backward(symbolic_graph, z); |
183 | 1 | ccv_nnc_tensor_t* tdz = ccv_nnc_tensor_from_symbol(tensor_arena, dz); |
184 | | // Seed the initialization vector. |
185 | 1 | tdz->data.f32[0] = 1; |
186 | 1 | ccv_nnc_graph_run(graph, 0, GRAPH_EXEC_LIST(ccv_nnc_graph_exec_from_symbol(graph_exec_arena, prod), ccv_nnc_graph_exec_from_symbol(graph_exec_arena, inv)), GRAPH_EXEC_LIST(ccv_nnc_graph_exec_from_symbol(graph_exec_arena, dyc), ccv_nnc_graph_exec_from_symbol(graph_exec_arena, sum)), 0, 0); |
187 | 1 | ccv_nnc_tensor_t* tz = ccv_nnc_tensor_from_symbol(tensor_arena, z); |
188 | 1 | ccv_nnc_tensor_t* tdy = ccv_nnc_tensor_from_symbol(tensor_arena, dy); |
189 | 1 | REQUIRE_EQ_WITH_TOLERANCE(tz->data.f32[0], 1.23 * 0.84 + logf(1.0 / 0.84), 1e-6, "computed result of y * x + Log[1 / x] should be the same"); |
190 | 1 | REQUIRE_EQ_WITH_TOLERANCE(tdy->data.f32[0], 0.84, 1e-6, "computed result of D[y * x + Log[1 / x], y] should be the same"); |
191 | 1 | ccv_nnc_symbolic_graph_free(symbolic_graph); |
192 | 1 | ccv_nnc_graph_free(graph); |
193 | 1 | ccv_nnc_tensor_arena_free(tensor_arena); |
194 | 1 | ccv_nnc_graph_exec_arena_free(graph_exec_arena); |
195 | 1 | } |
196 | | |
197 | | TEST_CASE("autograd with D[x * x + Log[1 / x], x] D[y * y + Log[1 / y], y] when x = 0.84 and y = 0.24") |
198 | 1 | { |
199 | 1 | ccv_nnc_symbolic_graph_t* symbolic_graph = ccv_nnc_symbolic_graph_new(); |
200 | 1 | ccv_nnc_tensor_symbol_t one = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "1"); |
201 | 1 | ccv_nnc_tensor_symbol_t x0 = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "x"); |
202 | | // w = x * x |
203 | 1 | ccv_nnc_tensor_symbol_t w0 = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "w"); |
204 | | // u = 1 / x |
205 | 1 | ccv_nnc_tensor_symbol_t u0 = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "u"); |
206 | | // v = Log[u] |
207 | 1 | ccv_nnc_tensor_symbol_t v0 = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "v"); |
208 | | // z = w + v |
209 | 1 | ccv_nnc_tensor_symbol_t z0 = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "z"); |
210 | 1 | ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWPROD_FORWARD(), TENSOR_SYMBOL_LIST(x0, x0), TENSOR_SYMBOL_LIST(w0), "prod0"); |
211 | 1 | ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWDIV_FORWARD(), TENSOR_SYMBOL_LIST(one, x0), TENSOR_SYMBOL_LIST(u0), "inv0"); |
212 | 1 | ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWLOG_FORWARD(), TENSOR_SYMBOL_LIST(u0), TENSOR_SYMBOL_LIST(v0), "log0"); |
213 | 1 | ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWSUM_FORWARD(), TENSOR_SYMBOL_LIST(w0, v0), TENSOR_SYMBOL_LIST(z0), "sum0"); |
214 | 1 | ccv_nnc_tensor_symbol_t x1 = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "x"); |
215 | | // w = x * x |
216 | 1 | ccv_nnc_tensor_symbol_t w1 = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "w"); |
217 | | // u = 1 / x |
218 | 1 | ccv_nnc_tensor_symbol_t u1 = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "u"); |
219 | | // v = Log[u] |
220 | 1 | ccv_nnc_tensor_symbol_t v1 = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "v"); |
221 | | // z = w + v |
222 | 1 | ccv_nnc_tensor_symbol_t z1 = ccv_nnc_tensor_symbol_new(symbolic_graph, CPU_TENSOR_NHWC(32F, 1), "z"); |
223 | 1 | ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWPROD_FORWARD(), TENSOR_SYMBOL_LIST(x1, x1), TENSOR_SYMBOL_LIST(w1), "prod1"); |
224 | 1 | ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWDIV_FORWARD(), TENSOR_SYMBOL_LIST(one, x1), TENSOR_SYMBOL_LIST(u1), "inv1"); |
225 | 1 | ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWLOG_FORWARD(), TENSOR_SYMBOL_LIST(u1), TENSOR_SYMBOL_LIST(v1), "log1"); |
226 | 1 | ccv_nnc_graph_exec_symbol_new(symbolic_graph, CMD_EWSUM_FORWARD(), TENSOR_SYMBOL_LIST(w1, v1), TENSOR_SYMBOL_LIST(z1), "sum1"); |
227 | 1 | ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS); |
228 | 1 | ccv_nnc_symbolic_graph_backward(symbolic_graph, TENSOR_SYMBOL_LIST(z0, z1), TENSOR_SYMBOL_LIST(x0, x1), SYMBOLIC_GRAPH_SOURCES(symbolic_graph), SYMBOLIC_GRAPH_DESTINATIONS(symbolic_graph)); |
229 | 1 | ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, 0, 0, CCV_NNC_AUTOGEN_ALL_EXECS | CCV_NNC_AUTOGEN_SOURCES_AND_DESTINATIONS); |
230 | 1 | SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH); |
231 | 1 | ccv_nnc_graph_t* graph = 0; |
232 | 1 | ccv_nnc_tensor_arena_t* tensor_arena = 0; |
233 | 1 | ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0; |
234 | 1 | ccv_nnc_tensor_symbol_t dx0 = ccv_nnc_tensor_symbol_for_backward(symbolic_graph, x0); |
235 | 1 | ccv_nnc_tensor_symbol_t dx1 = ccv_nnc_tensor_symbol_for_backward(symbolic_graph, x1); |
236 | 1 | ccv_nnc_symbolic_graph_compile(symbolic_graph, ccv_nnc_default_compile_params, |
237 | 1 | 0, 0, |
238 | 1 | TENSOR_SYMBOL_LIST(z0, z1), |
239 | 1 | SYMBOLIC_GRAPH_SOURCES(symbolic_graph), SYMBOLIC_GRAPH_DESTINATIONS(symbolic_graph), |
240 | 1 | &graph, &tensor_arena, &graph_exec_arena); |
241 | 1 | GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH); |
242 | 1 | ccv_nnc_tensor_t* tone = ccv_nnc_tensor_from_symbol(tensor_arena, one); |
243 | 1 | tone->data.f32[0] = 1; |
244 | 1 | ccv_nnc_tensor_t* tx0 = ccv_nnc_tensor_from_symbol(tensor_arena, x0); |
245 | 1 | tx0->data.f32[0] = 0.84; |
246 | 1 | ccv_nnc_tensor_t* tx1 = ccv_nnc_tensor_from_symbol(tensor_arena, x1); |
247 | 1 | tx1->data.f32[0] = 0.24; |
248 | 1 | ccv_nnc_tensor_symbol_t dz0 = ccv_nnc_tensor_symbol_for_backward(symbolic_graph, z0); |
249 | 1 | ccv_nnc_tensor_t* tdz0 = ccv_nnc_tensor_from_symbol(tensor_arena, dz0); |
250 | 1 | ccv_nnc_tensor_symbol_t dz1 = ccv_nnc_tensor_symbol_for_backward(symbolic_graph, z1); |
251 | 1 | ccv_nnc_tensor_t* tdz1 = ccv_nnc_tensor_from_symbol(tensor_arena, dz1); |
252 | | // Seed the initialization vector. |
253 | 1 | tdz0->data.f32[0] = 1; |
254 | 1 | tdz1->data.f32[0] = 1; |
255 | 1 | ccv_nnc_graph_run(graph, 0, TRAVERSE_FULL, 0, 0); |
256 | 1 | ccv_nnc_tensor_t* tz0 = ccv_nnc_tensor_from_symbol(tensor_arena, z0); |
257 | 1 | ccv_nnc_tensor_t* tdx0 = ccv_nnc_tensor_from_symbol(tensor_arena, dx0); |
258 | 1 | ccv_nnc_tensor_t* tz1 = ccv_nnc_tensor_from_symbol(tensor_arena, z1); |
259 | 1 | ccv_nnc_tensor_t* tdx1 = ccv_nnc_tensor_from_symbol(tensor_arena, dx1); |
260 | 1 | REQUIRE_EQ_WITH_TOLERANCE(tz0->data.f32[0], 0.84 * 0.84 + logf(1.0 / 0.84), 1e-6, "computed result of x * x + Log[1 / x] should be the same"); |
261 | 1 | REQUIRE_EQ_WITH_TOLERANCE(tdx0->data.f32[0], 2 * 0.84 - (1.0 / 0.84), 1e-6, "computed result of D[x * x + Log[1 / x], x] should be the same"); |
262 | 1 | REQUIRE_EQ_WITH_TOLERANCE(tz1->data.f32[0], 0.24 * 0.24 + logf(1.0 / 0.24), 1e-6, "computed result of y * y + Log[1 / y] should be the same"); |
263 | 1 | REQUIRE_EQ_WITH_TOLERANCE(tdx1->data.f32[0], 2 * 0.24 - (1.0 / 0.24), 1e-6, "computed result of D[y * y + Log[1 / y], y] should be the same"); |
264 | 1 | ccv_nnc_symbolic_graph_free(symbolic_graph); |
265 | 1 | ccv_nnc_graph_free(graph); |
266 | 1 | ccv_nnc_tensor_arena_free(tensor_arena); |
267 | 1 | ccv_nnc_graph_exec_arena_free(graph_exec_arena); |
268 | 1 | } |
269 | | |
270 | | #include "case_main.h" |