## Coverage Report

#### Created: 2026-05-04 15:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /home/liu/actions-runner/_work/ccv/ccv/test/unit/nnc/dropout.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("dropout 40% of a 20x50 matrix")
    14
    1
    {
    15
    1
      ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 20, 50), 0);
    16
    1
      ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 20, 50), 0);
    17
    1
      int i;
    18
    1.00k
      for (i = 0; i < 20 * 50; i++1.00k)
    19
    1.00k
        a->data.f32[i] = (i + 1) * 0.01;
    20
    1
      ccv_nnc_tensor_param_t output_info[2];
    21
    1
      ccv_nnc_hint_tensor_auto(CMD_DROPOUT_FORWARD(0.4), &a->info, 1, ccv_nnc_no_hint, output_info, 2);
    22
    1
      ccv_nnc_tensor_t* const c = ccv_nnc_tensor_new(0, output_info[1], 0);
    23
    1
      ccv_nnc_cmd_exec(CMD_DROPOUT_FORWARD(0.4), ccv_nnc_no_hint, 0, TENSOR_LIST(a), TENSOR_LIST(b, c), 0);
    24
    1
      int zero_count = 0;
    25
    1.00k
      for (i = 0; i < 20 * 50; i++1.00k)
    26
    1.00k
        if (b->data.f32[i] == 0)
    27
    395
          ++zero_count;
    28
    605
        else {
    29
    605
          REQUIRE_EQ_WITH_TOLERANCE(a->data.f32[i] / 0.6, b->data.f32[i], 1e-5, "should be scaled up by 1 / 0.6");
    30
    605
        }
    31
    1
      REQUIRE_EQ_WITH_TOLERANCE((float)zero_count / (20 * 50), 0.4, 5 * 1e-2, "should be within 2%% of error");
    32
    1
      ccv_nnc_tensor_free(a);
    33
    1
      ccv_nnc_tensor_free(b);
    34
    1
      ccv_nnc_tensor_free(c);
    35
    1
    }
    36
    37
    TEST_CASE("dropout gradient for 40% of a 20x30 matrix")
    38
    1
    {
    39
    1
      ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 20, 50), 0);
    40
    1
      ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 20, 50), 0);
    41
    1
      int i;
    42
    1.00k
      for (i = 0; i < 20 * 50; i++1.00k)
    43
    1.00k
        a->data.f32[i] = (i + 1) * 0.01;
    44
    1
      ccv_nnc_tensor_param_t output_info[2];
    45
    1
      ccv_nnc_hint_tensor_auto(CMD_DROPOUT_FORWARD(0.4), &a->info, 1, ccv_nnc_no_hint, output_info, 2);
    46
    1
      ccv_nnc_tensor_t* const c = ccv_nnc_tensor_new(0, output_info[1], 0);
    47
    1
      ccv_nnc_cmd_exec(CMD_DROPOUT_FORWARD(0.4), ccv_nnc_no_hint, 0, TENSOR_LIST(a), TENSOR_LIST(b, c), 0);
    48
    1
      ccv_nnc_tensor_t* const g = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 20, 50), 0);
    49
    1.00k
      for (i = 0; i < 20 * 50; i++1.00k)
    50
    1.00k
        g->data.f32[i] = i + 1;
    51
    1
      ccv_nnc_tensor_t* const h = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 20, 50), 0);
    52
    1
      ccv_nnc_cmd_exec(CMD_DROPOUT_BACKWARD(0.4), ccv_nnc_no_hint, 0, TENSOR_LIST(g, 0, 0, 0, c), TENSOR_LIST(h), 0);
    53
    1
      int zero_count = 0;
    54
    1.00k
      for (i = 0; i < 20 * 50; i++1.00k)
    55
    1.00k
        if (h->data.f32[i] == 0)
    56
    402
          ++zero_count;
    57
    1
      REQUIRE_EQ_WITH_TOLERANCE((float)zero_count / (20 * 50), 0.4, 5 * 1e-2, "should be within 2%% of error");
    58
    1
      ccv_nnc_tensor_t* const ht = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 20, 50), 0);
    59
    1
      ccv_nnc_tensor_zero(ht);
    60
    1.00k
      for (i = 0; i < 20 * 50; i++1.00k)
    61
    1.00k
        if (b->data.f32[i] != 0)
    62
    598
          ht->data.f32[i] = (i + 1) / 0.6;
    63
    1
      REQUIRE_TENSOR_EQ(h, ht, "propagated gradient should simply match the dropout");
    64
    1
      ccv_nnc_tensor_free(a);
    65
    1
      ccv_nnc_tensor_free(b);
    66
    1
      ccv_nnc_tensor_free(c);
    67
    1
      ccv_nnc_tensor_free(g);
    68
    1
      ccv_nnc_tensor_free(h);
    69
    1
      ccv_nnc_tensor_free(ht);
    70
    1
    }
    71
    72
    TEST_CASE("dropout entire matrix with 20% chance")
    73
    1
    {
    74
    1
      ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 20, 50), 0);
    75
    1
      ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 20, 50), 0);
    76
    1
      int i;
    77
    1.00k
      for (i = 0; i < 20 * 50; i++1.00k)
    78
    1.00k
        a->data.f32[i] = (i + 1) * 0.01;
    79
    1
      ccv_nnc_tensor_param_t output_info[2];
    80
    1
      ccv_nnc_hint_tensor_auto(CMD_DROPOUT_FORWARD(0.4), &a->info, 1, ccv_nnc_no_hint, output_info, 2);
    81
    1
      ccv_nnc_tensor_t* const c = ccv_nnc_tensor_new(0, output_info[1], 0);
    82
    1
      ccv_nnc_cmd_exec(CMD_DROPOUT_FORWARD(0.2, 1), ccv_nnc_no_hint, 0, TENSOR_LIST(a), TENSOR_LIST(b, c), 0);
    83
    1
      ccv_nnc_tensor_t* const d = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 20, 50), 0);
    84
    1
      if (b->data.f32[0] == 0)
    85
    0
        for (i = 0; i < 20 * 50; i++)
    86
    0
          d->data.f32[i] = 0;
    87
    1
      else
    88
    1.00k
        for (i = 0; 1i < 20 * 50; i++1.00k)
    89
    1.00k
          d->data.f32[i] = a->data.f32[i] / 0.8;
    90
    1
      REQUIRE_TENSOR_EQ(b, d, "dropout chance should be equal");
    91
    1
      ccv_nnc_tensor_free(a);
    92
    1
      ccv_nnc_tensor_free(b);
    93
    1
      ccv_nnc_tensor_free(c);
    94
    1
      ccv_nnc_tensor_free(d);
    95
    1
    }
    96
    97
    TEST_CASE("dropout gradient entire matrix with 20% chance")
    98
    1
    {
    99
    1
      ccv_nnc_tensor_t* const a = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 20, 50), 0);
    100
    1
      ccv_nnc_tensor_t* const b = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 20, 50), 0);
    101
    1
      int i;
    102
    1.00k
      for (i = 0; i < 20 * 50; i++1.00k)
    103
    1.00k
        a->data.f32[i] = (i + 1) * 0.01;
    104
    1
      ccv_nnc_tensor_param_t output_info[2];
    105
    1
      ccv_nnc_hint_tensor_auto(CMD_DROPOUT_FORWARD(0.4), &a->info, 1, ccv_nnc_no_hint, output_info, 2);
    106
    1
      ccv_nnc_tensor_t* const c = ccv_nnc_tensor_new(0, output_info[1], 0);
    107
    1
      ccv_nnc_cmd_exec(CMD_DROPOUT_FORWARD(0.2, 1), ccv_nnc_no_hint, 0, TENSOR_LIST(a), TENSOR_LIST(b, c), 0);
    108
    1
      ccv_nnc_tensor_t* const g = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 20, 50), 0);
    109
    1.00k
      for (i = 0; i < 20 * 50; i++1.00k)
    110
    1.00k
        g->data.f32[i] = i + 1;
    111
    1
      ccv_nnc_tensor_t* const h = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 20, 50), 0);
    112
    1
      ccv_nnc_cmd_exec(CMD_DROPOUT_BACKWARD(0.2, 1), ccv_nnc_no_hint, 0, TENSOR_LIST(g, 0, 0, 0, c), TENSOR_LIST(h), 0);
    113
    1
      ccv_nnc_tensor_t* const d = ccv_nnc_tensor_new(0, CPU_TENSOR_NHWC(32F, 20, 50), 0);
    114
    1
      if (b->data.f32[0] == 0)
    115
    0
        for (i = 0; i < 20 * 50; i++)
    116
    0
          d->data.f32[i] = 0;
    117
    1
      else
    118
    1.00k
        for (i = 0; 1i < 20 * 50; i++1.00k)
    119
    1.00k
          d->data.f32[i] = g->data.f32[i] / 0.8;
    120
    1
      REQUIRE_TENSOR_EQ(h, d, "dropout chance should be equal");
    121
    1
      ccv_nnc_tensor_free(a);
    122
    1
      ccv_nnc_tensor_free(b);
    123
    1
      ccv_nnc_tensor_free(c);
    124
    1
      ccv_nnc_tensor_free(g);
    125
    1
      ccv_nnc_tensor_free(h);
    126
    1
      ccv_nnc_tensor_free(d);
    127
    1
    }
    128
    129
    #include "case_main.h"