Coverage Report

Created: 2017-11-12 13:27

/home/liu/buildslave/linux-x64-runtests/build/test/unit/nnc/autograd.tests.c
Line
Count
Source
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, ONE_CPU_TENSOR(1), "1");
17
1
  ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, ONE_CPU_TENSOR(1), "x");
18
1
  // w = x * x
19
1
  ccv_nnc_tensor_symbol_t w = ccv_nnc_tensor_symbol_new(symbolic_graph, ONE_CPU_TENSOR(1), "w");
20
1
  // u = 1 / x
21
1
  ccv_nnc_tensor_symbol_t u = ccv_nnc_tensor_symbol_new(symbolic_graph, ONE_CPU_TENSOR(1), "u");
22
1
  // v = Log[u]
23
1
  ccv_nnc_tensor_symbol_t v = ccv_nnc_tensor_symbol_new(symbolic_graph, ONE_CPU_TENSOR(1), "v");
24
1
  // z = w + v
25
1
  ccv_nnc_tensor_symbol_t z = ccv_nnc_tensor_symbol_new(symbolic_graph, ONE_CPU_TENSOR(1), "z");
26
1
  ccv_nnc_graph_exec_symbol_t prod = ccv_nnc_graph_exec_symbol_new(symbolic_graph, ccv_nnc_cmd(CCV_NNC_EWPROD_FORWARD, 0, 
CMD_GENERIC1
(), 0),
TENSOR_SYMBOL_LIST1
(x, x),
TENSOR_SYMBOL_LIST1
(w), "prod");
27
1
  ccv_nnc_graph_exec_symbol_t inv = ccv_nnc_graph_exec_symbol_new(symbolic_graph, ccv_nnc_cmd(CCV_NNC_EWDIV_FORWARD, 0, 
CMD_GENERIC1
(), 0),
TENSOR_SYMBOL_LIST1
(one, x),
TENSOR_SYMBOL_LIST1
(u), "inv");
28
1
  ccv_nnc_graph_exec_symbol_t log = ccv_nnc_graph_exec_symbol_new(symbolic_graph, ccv_nnc_cmd(CCV_NNC_EWLOG_FORWARD, 0, 
CMD_GENERIC1
(), 0),
TENSOR_SYMBOL_LIST1
(u),
TENSOR_SYMBOL_LIST1
(v), "log");
29
1
  ccv_nnc_graph_exec_symbol_t sum = ccv_nnc_graph_exec_symbol_new(symbolic_graph, ccv_nnc_cmd(CCV_NNC_EWSUM_FORWARD, 0, 
CMD_GENERIC1
(), 0),
TENSOR_SYMBOL_LIST1
(w, v),
TENSOR_SYMBOL_LIST1
(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, 
GRAPH_EXEC_SYMBOL_LIST1
(prod, inv),
GRAPH_EXEC_SYMBOL_LIST1
(sum),
TENSOR_SYMBOL_LIST1
(z),
TENSOR_SYMBOL_LIST1
(x));
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, 0, 0, 
GRAPH_EXEC_SYMBOL_LIST1
(prod, inv),
GRAPH_EXEC_SYMBOL_LIST1
(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
1
  // Seed the initialization vector.
47
1
  tdz->data.f32[0] = 1;
48
1
  ccv_nnc_graph_run(graph, 0, 
GRAPH_EXEC_LIST1
(ccv_nnc_graph_exec_from_symbol(graph_exec_arena, prod), ccv_nnc_graph_exec_from_symbol(graph_exec_arena, inv)),
GRAPH_EXEC_LIST1
(ccv_nnc_graph_exec_from_symbol(graph_exec_arena, dxc), ccv_nnc_graph_exec_from_symbol(graph_exec_arena, sum)));
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_TOLERANCE1
(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")
;1
52
1
  
REQUIRE_EQ_WITH_TOLERANCE1
(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")
;1
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[(x - y) * (x + 1), [x, y]] when x = 43.24 and y = 0.38")
60
1
{
61
1
  ccv_nnc_symbolic_graph_t* symbolic_graph = ccv_nnc_symbolic_graph_new();
62
1
  ccv_nnc_tensor_symbol_t one = ccv_nnc_tensor_symbol_new(symbolic_graph, ONE_CPU_TENSOR(1), "1");
63
1
  ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, ONE_CPU_TENSOR(1), "x");
64
1
  ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(symbolic_graph, ONE_CPU_TENSOR(1), "y");
65
1
  // w = x - y
66
1
  ccv_nnc_tensor_symbol_t w = ccv_nnc_tensor_symbol_new(symbolic_graph, ONE_CPU_TENSOR(1), "w");
67
1
  // u = y + 1
68
1
  ccv_nnc_tensor_symbol_t u = ccv_nnc_tensor_symbol_new(symbolic_graph, ONE_CPU_TENSOR(1), "u");
69
1
  // v = w * u
70
1
  ccv_nnc_tensor_symbol_t v = ccv_nnc_tensor_symbol_new(symbolic_graph, ONE_CPU_TENSOR(1), "v");
71
1
  ccv_nnc_graph_exec_symbol_t minus = ccv_nnc_graph_exec_symbol_new(symbolic_graph, ccv_nnc_cmd(CCV_NNC_AXPY_FORWARD, 0, 
CMD_BLAS1
(1, -1), 0),
TENSOR_SYMBOL_LIST1
(x, y),
TENSOR_SYMBOL_LIST1
(w), "minus");
72
1
  ccv_nnc_graph_exec_symbol_t plus = ccv_nnc_graph_exec_symbol_new(symbolic_graph, ccv_nnc_cmd(CCV_NNC_AXPY_FORWARD, 0, 
CMD_BLAS1
(1, 1), 0),
TENSOR_SYMBOL_LIST1
(y, one),
TENSOR_SYMBOL_LIST1
(u), "plus");
73
1
  ccv_nnc_graph_exec_symbol_t prod = ccv_nnc_graph_exec_symbol_new(symbolic_graph, ccv_nnc_cmd(CCV_NNC_EWPROD_FORWARD, 0, 
CMD_GENERIC1
(), 0),
TENSOR_SYMBOL_LIST1
(w, u),
TENSOR_SYMBOL_LIST1
(v), "prod");
74
1
  ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, GRAPH_EXEC_SYMBOL_LIST(minus, plus, prod), 0);
75
1
  ccv_nnc_symbolic_graph_backward(symbolic_graph, 
GRAPH_EXEC_SYMBOL_LIST1
(minus, plus),
GRAPH_EXEC_SYMBOL_LIST1
(prod),
TENSOR_SYMBOL_LIST1
(v),
TENSOR_SYMBOL_LIST1
(x, y));
76
1
  ccv_nnc_graph_t* graph = 0;
77
1
  ccv_nnc_tensor_arena_t* tensor_arena = 0;
78
1
  ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
79
1
  ccv_nnc_tensor_symbol_t dx = ccv_nnc_tensor_symbol_for_backward(symbolic_graph, x);
80
1
  ccv_nnc_graph_exec_symbol_t dxc = ccv_nnc_graph_exec_symbol_for_backward(symbolic_graph, dx);
81
1
  ccv_nnc_tensor_symbol_t dy = ccv_nnc_tensor_symbol_for_backward(symbolic_graph, y);
82
1
  ccv_nnc_graph_exec_symbol_t dyc = ccv_nnc_graph_exec_symbol_for_backward(symbolic_graph, dy);
83
1
  ccv_nnc_symbolic_graph_compile(symbolic_graph, 0, 0, 
GRAPH_EXEC_SYMBOL_LIST1
(minus, plus),
GRAPH_EXEC_SYMBOL_LIST1
(dxc, dyc, prod), &graph, &tensor_arena, &graph_exec_arena);
84
1
  SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
85
1
  GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
86
1
  ccv_nnc_tensor_t* tone = ccv_nnc_tensor_from_symbol(tensor_arena, one);
87
1
  tone->data.f32[0] = 1;
88
1
  ccv_nnc_tensor_t* tx = ccv_nnc_tensor_from_symbol(tensor_arena, x);
89
1
  tx->data.f32[0] = 43.24;
90
1
  ccv_nnc_tensor_t* ty = ccv_nnc_tensor_from_symbol(tensor_arena, y);
91
1
  ty->data.f32[0] = 0.38;
92
1
  ccv_nnc_tensor_symbol_t dv = ccv_nnc_tensor_symbol_for_backward(symbolic_graph, v);
93
1
  ccv_nnc_tensor_t* tdv = ccv_nnc_tensor_from_symbol(tensor_arena, dv);
94
1
  // Seed the initialization vector.
95
1
  tdv->data.f32[0] = 1;
96
1
  ccv_nnc_graph_run(graph, 0, 
GRAPH_EXEC_LIST1
(ccv_nnc_graph_exec_from_symbol(graph_exec_arena, minus), ccv_nnc_graph_exec_from_symbol(graph_exec_arena, plus)),
GRAPH_EXEC_LIST1
(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)));
97
1
  ccv_nnc_tensor_t* tv = ccv_nnc_tensor_from_symbol(tensor_arena, v);
98
1
  ccv_nnc_tensor_t* tdx = ccv_nnc_tensor_from_symbol(tensor_arena, dx);
99
1
  ccv_nnc_tensor_t* tdy = ccv_nnc_tensor_from_symbol(tensor_arena, dy);
100
1
  
REQUIRE_EQ_WITH_TOLERANCE1
(tv->data.f32[0], (43.24 - 0.38) * (0.38 + 1), 1e-6, "computed result of (x + y) * (y + 1) should be the same")
;1
101
1
  
REQUIRE_EQ_WITH_TOLERANCE1
(tdx->data.f32[0], 0.38 + 1, 1e-6, "computed result of D[(x + y) * (y + 1), x] should be the same")
;1
102
1
  
REQUIRE_EQ_WITH_TOLERANCE1
(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")
;1
103
1
  ccv_nnc_symbolic_graph_free(symbolic_graph);
104
1
  ccv_nnc_graph_free(graph);
105
1
  ccv_nnc_tensor_arena_free(tensor_arena);
106
1
  ccv_nnc_graph_exec_arena_free(graph_exec_arena);
107
1
}
108
109
TEST_CASE("partial autograd with D[y * x + Log[1 / x], y] when x = 0.84 and y = 1.23")
110
1
{
111
1
  ccv_nnc_symbolic_graph_t* symbolic_graph = ccv_nnc_symbolic_graph_new();
112
1
  ccv_nnc_tensor_symbol_t one = ccv_nnc_tensor_symbol_new(symbolic_graph, ONE_CPU_TENSOR(1), "1");
113
1
  ccv_nnc_tensor_symbol_t x = ccv_nnc_tensor_symbol_new(symbolic_graph, ONE_CPU_TENSOR(1), "x");
114
1
  ccv_nnc_tensor_symbol_t y = ccv_nnc_tensor_symbol_new(symbolic_graph, ONE_CPU_TENSOR(1), "y");
115
1
  // w = y * x
116
1
  ccv_nnc_tensor_symbol_t w = ccv_nnc_tensor_symbol_new(symbolic_graph, ONE_CPU_TENSOR(1), "w");
117
1
  // u = 1 / x
118
1
  ccv_nnc_tensor_symbol_t u = ccv_nnc_tensor_symbol_new(symbolic_graph, ONE_CPU_TENSOR(1), "u");
119
1
  // v = Log[u]
120
1
  ccv_nnc_tensor_symbol_t v = ccv_nnc_tensor_symbol_new(symbolic_graph, ONE_CPU_TENSOR(1), "v");
121
1
  // z = w + v
122
1
  ccv_nnc_tensor_symbol_t z = ccv_nnc_tensor_symbol_new(symbolic_graph, ONE_CPU_TENSOR(1), "z");
123
1
  ccv_nnc_graph_exec_symbol_t prod = ccv_nnc_graph_exec_symbol_new(symbolic_graph, ccv_nnc_cmd(CCV_NNC_EWPROD_FORWARD, 0, 
CMD_GENERIC1
(), 0),
TENSOR_SYMBOL_LIST1
(y, x),
TENSOR_SYMBOL_LIST1
(w), "prod");
124
1
  ccv_nnc_graph_exec_symbol_t inv = ccv_nnc_graph_exec_symbol_new(symbolic_graph, ccv_nnc_cmd(CCV_NNC_EWDIV_FORWARD, 0, 
CMD_GENERIC1
(), 0),
TENSOR_SYMBOL_LIST1
(one, x),
TENSOR_SYMBOL_LIST1
(u), "inv");
125
1
  ccv_nnc_graph_exec_symbol_t log = ccv_nnc_graph_exec_symbol_new(symbolic_graph, ccv_nnc_cmd(CCV_NNC_EWLOG_FORWARD, 0, 
CMD_GENERIC1
(), 0),
TENSOR_SYMBOL_LIST1
(u),
TENSOR_SYMBOL_LIST1
(v), "log");
126
1
  ccv_nnc_graph_exec_symbol_t sum = ccv_nnc_graph_exec_symbol_new(symbolic_graph, ccv_nnc_cmd(CCV_NNC_EWSUM_FORWARD, 0, 
CMD_GENERIC1
(), 0),
TENSOR_SYMBOL_LIST1
(w, v),
TENSOR_SYMBOL_LIST1
(z), "sum");
127
1
  ccv_nnc_graph_exec_symbol_autogen(symbolic_graph, GRAPH_EXEC_SYMBOL_LIST(prod, inv, log, sum), 0);
128
1
  ccv_nnc_symbolic_graph_backward(symbolic_graph, 
GRAPH_EXEC_SYMBOL_LIST1
(prod, inv),
GRAPH_EXEC_SYMBOL_LIST1
(sum),
TENSOR_SYMBOL_LIST1
(z),
TENSOR_SYMBOL_LIST1
(y));
129
1
  ccv_nnc_graph_t* graph = 0;
130
1
  ccv_nnc_tensor_arena_t* tensor_arena = 0;
131
1
  ccv_nnc_graph_exec_arena_t* graph_exec_arena = 0;
132
1
  ccv_nnc_tensor_symbol_t dy = ccv_nnc_tensor_symbol_for_backward(symbolic_graph, y);
133
1
  ccv_nnc_graph_exec_symbol_t dyc = ccv_nnc_graph_exec_symbol_for_backward(symbolic_graph, dy);
134
1
  ccv_nnc_symbolic_graph_compile(symbolic_graph, 0, 0, 
GRAPH_EXEC_SYMBOL_LIST1
(prod, inv),
GRAPH_EXEC_SYMBOL_LIST1
(dyc, sum), &graph, &tensor_arena, &graph_exec_arena);
135
1
  SYMBOLIC_GRAPH_GEN(symbolic_graph, CCV_NNC_LONG_DOT_GRAPH);
136
1
  GRAPH_GEN(graph, CCV_NNC_LONG_DOT_GRAPH);
137
1
  ccv_nnc_tensor_t* tone = ccv_nnc_tensor_from_symbol(tensor_arena, one);
138
1
  tone->data.f32[0] = 1;
139
1
  ccv_nnc_tensor_t* tx = ccv_nnc_tensor_from_symbol(tensor_arena, x);
140
1
  tx->data.f32[0] = 0.84;
141
1
  ccv_nnc_tensor_t* ty = ccv_nnc_tensor_from_symbol(tensor_arena, y);
142
1
  ty->data.f32[0] = 1.23;
143
1
  ccv_nnc_tensor_symbol_t dz = ccv_nnc_tensor_symbol_for_backward(symbolic_graph, z);
144
1
  ccv_nnc_tensor_t* tdz = ccv_nnc_tensor_from_symbol(tensor_arena, dz);
145
1
  // Seed the initialization vector.
146
1
  tdz->data.f32[0] = 1;
147
1
  ccv_nnc_graph_run(graph, 0, 
GRAPH_EXEC_LIST1
(ccv_nnc_graph_exec_from_symbol(graph_exec_arena, prod), ccv_nnc_graph_exec_from_symbol(graph_exec_arena, inv)),
GRAPH_EXEC_LIST1
(ccv_nnc_graph_exec_from_symbol(graph_exec_arena, dyc), ccv_nnc_graph_exec_from_symbol(graph_exec_arena, sum)));
148
1
  ccv_nnc_tensor_t* tz = ccv_nnc_tensor_from_symbol(tensor_arena, z);
149
1
  ccv_nnc_tensor_t* tdy = ccv_nnc_tensor_from_symbol(tensor_arena, dy);
150
1
  
REQUIRE_EQ_WITH_TOLERANCE1
(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")
;1
151
1
  
REQUIRE_EQ_WITH_TOLERANCE1
(tdy->data.f32[0], 0.84, 1e-6, "computed result of D[y * x + Log[1 / x], y] should be the same")
;1
152
1
  ccv_nnc_symbolic_graph_free(symbolic_graph);
153
1
  ccv_nnc_graph_free(graph);
154
1
  ccv_nnc_tensor_arena_free(tensor_arena);
155
1
  ccv_nnc_graph_exec_arena_free(graph_exec_arena);
156
1
}
157
158
#include "case_main.h"