Skip to content

Commit

Permalink
feat: add separate petal_params_s and improve dropout function
Browse files Browse the repository at this point in the history
  • Loading branch information
F33RNI committed Apr 16, 2024
1 parent a77d4ca commit 72af16a
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 63 deletions.
5 changes: 5 additions & 0 deletions include/bit_array.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,14 @@
* @param data pointer to array of BIT_ARRAY_TYPE numbers
* @param length length of array in BIT_ARRAY_TYPE
* @param error_code initialization or runtime error code
* @param _length_in_types internal length of *data array measured in BIT_ARRAY_TYPEs
*/
typedef struct {
BIT_ARRAY_TYPE *data;
uint32_t length;
uint8_t error_code;

uint32_t _length_in_types;
} bit_array_s;

bit_array_s *bit_array_init(uint32_t size_bits);
Expand All @@ -51,6 +54,8 @@ void bit_array_clear_bit(bit_array_s *bit_array, uint32_t index);

bool bit_array_get_bit(bit_array_s *bit_array, uint32_t index);

void bit_array_not(bit_array_s *bit_array);

void bit_array_clear(bit_array_s *bit_array);

void bit_array_destroy(bit_array_s *bit_array);
Expand Down
20 changes: 16 additions & 4 deletions include/petal.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@ typedef struct {
uint32_t length;
} petal_shape_s;

/**
* @struct petal_params_s
* Stores simple (non-pointers) optional parameters for dropout and normalization
*
* @param dropout ratio of dropped outputs (0 to 1)
* @param center center of normalization for PETAL_TYPE_NORMALIZE_...
* @param deviation deviation of normalization for PETAL_TYPE_NORMALIZE_...
*/
typedef struct {
float dropout, center, deviation;
} petal_params_s;

/**
* @struct petal_s
* Stores petal's data
Expand All @@ -69,7 +81,7 @@ typedef struct {
* @param weights - pointers to weights_s structs
* @param bias_weights - pointers to weights_s structs
* @param activation - pointer to activation_s struct
* @param dropout - ratio of dropped outputs (0 to 1)
* @param params - petal_params_s struct (for dropout / normalization)
* @param bit_array_s - pointer to bit_array_s struct that stores indices to drop
* @param output - petal outputs
* @param error_on_input - petal input state during backpropagation
Expand All @@ -81,16 +93,16 @@ typedef struct {
petal_shape_s *input_shape, *output_shape;
weights_s *weights, *bias_weights;
activation_s *activation;
float dropout, center, deviation;
petal_params_s params;

bit_array_s *bit_array;
float *output, *error_on_input;
uint8_t error_code;
} petal_s;

petal_s *petal_init(uint8_t petal_type, bool first, petal_shape_s *input_shape, petal_shape_s *output_shape,
weights_s *weights, weights_s *bias_weights, activation_s *activation, float dropout, float center,
float deviation);
weights_s *weights, weights_s *bias_weights, activation_s *activation,
petal_params_s *petal_params);

void petal_forward(petal_s *petal, float *input, bool training);

Expand Down
19 changes: 16 additions & 3 deletions src/bit_array.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ bit_array_s *bit_array_init(uint32_t size_bits) {
// Reset error
bit_array->error_code = ERROR_NONE;

// Calculate the number of BIT_ARRAY_TYPE needed to represent size_bits and initialize array with zeros
bit_array->data =
(BIT_ARRAY_TYPE *) calloc((size_bits + (BIT_ARRAY_BITS - 1U)) / BIT_ARRAY_BITS, sizeof(BIT_ARRAY_TYPE));
// Calculate the number of BIT_ARRAY_TYPE needed to represent size_bits
bit_array->_length_in_types = (size_bits + (BIT_ARRAY_BITS - 1U)) / BIT_ARRAY_BITS;

// Initialize array with zeros
bit_array->data = (BIT_ARRAY_TYPE *) calloc(bit_array->_length_in_types, sizeof(BIT_ARRAY_TYPE));
if (!bit_array->data) {
logger(LOG_E, "bit_array_init", "Error allocating memory for bit_array->data");
bit_array->error_code = ERROR_MALLOC;
Expand Down Expand Up @@ -121,6 +123,17 @@ bool bit_array_get_bit(bit_array_s *bit_array, uint32_t index) {
(BIT_ARRAY_TYPE) 1) != (BIT_ARRAY_TYPE) 0;
}

/**
* @brief Inverts bit array (inverts each bit in it)
*
* @param bit_array pointer to bit_array_s struct
*/
void bit_array_not(bit_array_s *bit_array) {
for (uint32_t i = 0; i < bit_array->_length_in_types; ++i) {
bit_array->data[i] = ~bit_array->data[i];
}
}

/**
* @brief Clears bit array entirely (sets all bits to 0)
*
Expand Down
53 changes: 37 additions & 16 deletions src/dropout.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,28 +36,49 @@
* @param dropout_ratio 0 to 1
*/
void dropout_generate_indices(bit_array_s *bit_array, float dropout_ratio) {
// Calculate how many indices we need to drop
uint32_t indices_n_to_drop = (float) bit_array->length * dropout_ratio;
uint32_t indices_n_to_drop_or_keep = 0U;

// Calculate how many indices we need to drop for [0.0, 0.5] interval
if (dropout_ratio >= 0.f && dropout_ratio <= .5f)
indices_n_to_drop_or_keep = (float) bit_array->length * dropout_ratio;

// Calculate how many indices we need to keep for [0.5, 1.0] interval (because in this case it's easer to keep)
else if (dropout_ratio <= 1.f && dropout_ratio >= .5f)
indices_n_to_drop_or_keep = bit_array->length - (uint32_t) ((float) bit_array->length * dropout_ratio);

// Handle out-of-bounds access
if (indices_n_to_drop > bit_array->length) {
logger(LOG_E, "dropout_generate_indices", "Cannot drop %u indices. Out of bounds for bit array with size %u",
indices_n_to_drop, bit_array->length);
if (indices_n_to_drop_or_keep > bit_array->length) {
logger(LOG_E, "dropout_generate_indices",
"Cannot drop or keep %u indices. Out of bounds for bit array with size %u", indices_n_to_drop_or_keep,
bit_array->length);
bit_array->error_code = ERROR_BITMAP_ACCESS_OUT_OF_BOUNDS;
return;
}

// Drop random indexes
uint32_t drop_counter = 0U;
uint32_t index_to_drop;
while (drop_counter < indices_n_to_drop) {
// Generate random index
index_to_drop = rk_random_() % bit_array->length;

// Ignore if already dropped
if (!bit_array_get_bit(bit_array, index_to_drop)) {
bit_array_set_bit(bit_array, index_to_drop);
drop_counter++;
// Handle 100% keep / drop
if (indices_n_to_drop_or_keep == bit_array->length)
for (uint32_t i = 0; i < bit_array->length; ++i)
bit_array_set_bit(bit_array, i);

// Set random indexes
else {
uint32_t set_counter = 0U;
uint32_t index_to_set;
while (set_counter < indices_n_to_drop_or_keep) {
// Generate random index
index_to_set = rk_random_() % bit_array->length;

// Ignore if already set
if (bit_array_get_bit(bit_array, index_to_set))
continue;

// Set bit and increment counter
bit_array_set_bit(bit_array, index_to_set);
set_counter++;
}
}

// Invert if we use keep mode
if (dropout_ratio <= 1.f && dropout_ratio >= .5f)
bit_array_not(bit_array);
}
17 changes: 9 additions & 8 deletions src/forward.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@
void petal_forward(petal_s *petal, float *input, bool training) {
// Calculate dropout
bool dropout_enabled = false;
if (training && petal->dropout > 0.f && petal->bit_array) {
if (training && petal->params.dropout > 0.f && petal->bit_array) {
// Clear previous dropout
bit_array_clear(petal->bit_array);

// Generate new dropout
dropout_generate_indices(petal->bit_array, petal->dropout);
dropout_generate_indices(petal->bit_array, petal->params.dropout);
if (petal->bit_array->error_code != ERROR_NONE) {
logger(LOG_E, "petal_forward", "Error generating dropout indices: %s",
error_to_str[petal->bit_array->error_code]);
Expand Down Expand Up @@ -82,7 +82,8 @@ void petal_forward(petal_s *petal, float *input, bool training) {
petal->output[i] = 0.f;
else {
petal->output[i] = ((input[i] - min_value) / (max_value - min_value + EPSILON));
petal->output[i] = petal->output[i] * 2.f * petal->deviation + petal->center - petal->deviation;
petal->output[i] =
petal->output[i] * 2.f * petal->params.deviation + petal->params.center - petal->params.deviation;
}
}
}
Expand Down Expand Up @@ -113,8 +114,8 @@ void petal_forward(petal_s *petal, float *input, bool training) {
petal->output[index] = 0.f;
else {
petal->output[index] = ((input[index] - min_value) / (max_value - min_value + EPSILON));
petal->output[index] =
petal->output[index] * 2.f * petal->deviation + petal->center - petal->deviation;
petal->output[index] = petal->output[index] * 2.f * petal->params.deviation + petal->params.center -
petal->params.deviation;
}
}
}
Expand Down Expand Up @@ -143,8 +144,8 @@ void petal_forward(petal_s *petal, float *input, bool training) {
petal->output[index] = 0.f;
else {
petal->output[index] = ((input[index] - min_value) / (max_value - min_value + EPSILON));
petal->output[index] =
petal->output[index] * 2.f * petal->deviation + petal->center - petal->deviation;
petal->output[index] = petal->output[index] * 2.f * petal->params.deviation + petal->params.center -
petal->params.deviation;
}
}
}
Expand Down Expand Up @@ -195,7 +196,7 @@ void petal_forward(petal_s *petal, float *input, bool training) {

// Normalize sum after activation if dropout is enabled
if (dropout_enabled) {
float dropout_scaling = 1.f / (1.f - petal->dropout + EPSILON);
float dropout_scaling = 1.f / (1.f - petal->params.dropout + EPSILON);
for (uint32_t i = 0; i < petal->output_shape->length; ++i)
if (petal->output[i] != 0.f)
petal->output[i] *= dropout_scaling;
Expand Down
30 changes: 21 additions & 9 deletions src/petal.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,15 @@
* relu_leak - leak amount (for ACTIVATION_RELU only). Default = 0.01,
* elu_alpha - the value to which an ELU saturates for negative net inputs (for ACTIVATION_ELU only). Default = 0.01,
* swish_beta - beta for turning Swish into E-Swish (for ACTIVATION_SWISH only). Default = 1.0
* @param dropout ratio of dropped outputs (0 to 1)
* @param center center of normalization for PETAL_TYPE_NORMALIZE_... Default: 0.0
* @param deviation deviation of normalization for PETAL_TYPE_NORMALIZE_... Default: 1.0
* @param params - pointer to petal_params_s struct(for dropout / normalization)
* or NULL if it doesn't need / default values are ok:
* dropout - ratio of dropped outputs (0 to 1) (Default: 0.0)
* center - center of normalization for PETAL_TYPE_NORMALIZE_... (Default: 0.0)
* deviation - deviation of normalization for PETAL_TYPE_NORMALIZE_... (Default: 1.0)
* @return petal_s* petal's struct
*/
petal_s *petal_init(uint8_t petal_type, bool first, petal_shape_s *input_shape, petal_shape_s *output_shape,
weights_s *weights, weights_s *bias_weights, activation_s *activation, float dropout, float center,
float deviation) {
weights_s *weights, weights_s *bias_weights, activation_s *activation, petal_params_s *params) {
// Log
logger(LOG_I, "petal_init", "Initializing petal with type: %u", petal_type);

Expand All @@ -96,13 +97,24 @@ petal_s *petal_init(uint8_t petal_type, bool first, petal_shape_s *input_shape,
petal->weights = weights;
petal->bias_weights = bias_weights;
petal->activation = activation;
petal->dropout = dropout;
petal->center = center;
petal->deviation = deviation;
petal->bit_array = NULL;
if (petal->activation)
petal->activation->_derivatives_temp = NULL;

// Copy params
if (params) {
petal->params.dropout = params->dropout;
petal->params.center = params->center;
petal->params.deviation = params->deviation;
}

// Initialize params with default values
else {
petal->params.dropout = 0.f;
petal->params.center = 0.f;
petal->params.deviation = 1.f;
}

// Check petal type
if (petal_type > PETAL_TYPE_MAX) {
logger(LOG_E, "petal_init", "Wrong petal type: %u", petal_type);
Expand Down Expand Up @@ -152,7 +164,7 @@ petal_s *petal_init(uint8_t petal_type, bool first, petal_shape_s *input_shape,
}

// Initialize dropout
if (dropout > 0.f) {
if (petal->params.dropout > 0.f) {
petal->bit_array = bit_array_init(output_shape->length);
if (petal->bit_array->error_code != ERROR_NONE) {
logger(LOG_E, "petal_init", "Dropout bit array initialization error: %s",
Expand Down
Loading

0 comments on commit 72af16a

Please sign in to comment.