2022-07-05 08:13:25 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <float.h>
|
2022-10-24 12:54:51 +02:00
|
|
|
|
2023-02-28 13:14:51 +01:00
|
|
|
#include "../include/colors.h"
|
|
|
|
|
2022-09-16 14:53:35 +02:00
|
|
|
#include "include/function.h"
|
2023-03-09 14:27:23 +01:00
|
|
|
#define BOUND_RELU 15
|
2023-03-03 21:56:42 +01:00
|
|
|
|
2022-11-12 14:20:13 +01:00
|
|
|
float identity(float x) {
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
float identity_derivative(float x) {
|
|
|
|
(void)x;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2023-03-03 21:56:42 +01:00
|
|
|
|
2022-07-05 08:13:25 +02:00
|
|
|
float sigmoid(float x) {
|
|
|
|
return 1/(1 + exp(-x));
|
|
|
|
}
|
|
|
|
|
|
|
|
float sigmoid_derivative(float x) {
|
|
|
|
float tmp = exp(-x);
|
|
|
|
return tmp/((1+tmp)*(1+tmp));
|
|
|
|
}
|
|
|
|
|
2023-03-03 21:56:42 +01:00
|
|
|
|
2022-07-05 08:13:25 +02:00
|
|
|
float relu(float x) {
|
2023-03-09 14:27:23 +01:00
|
|
|
return fmaxf(0, fminf(x, BOUND_RELU));
|
2022-07-05 08:13:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
float relu_derivative(float x) {
|
|
|
|
if (x > 0)
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-03-03 21:56:42 +01:00
|
|
|
|
2023-02-19 12:13:03 +01:00
|
|
|
float leaky_relu(float x) {
|
|
|
|
if (x>0)
|
2023-03-09 14:27:23 +01:00
|
|
|
return fminf(x, BOUND_RELU);
|
2023-02-19 12:13:03 +01:00
|
|
|
return x*LEAKER;
|
|
|
|
}
|
|
|
|
|
|
|
|
float leaky_relu_derivative(float x) {
|
|
|
|
if (x > 0)
|
|
|
|
return 1;
|
|
|
|
return LEAKER;
|
|
|
|
}
|
|
|
|
|
2023-03-03 21:56:42 +01:00
|
|
|
|
2022-07-05 08:13:25 +02:00
|
|
|
float tanh_(float x) {
|
|
|
|
return tanh(x);
|
|
|
|
}
|
|
|
|
|
|
|
|
float tanh_derivative(float x) {
|
|
|
|
float a = tanh(x);
|
|
|
|
return 1 - a*a;
|
|
|
|
}
|
|
|
|
|
2023-03-03 21:56:42 +01:00
|
|
|
|
2022-07-05 08:13:25 +02:00
|
|
|
void apply_softmax_input(float ***input, int depth, int rows, int columns) {
|
|
|
|
float m = FLT_MIN;
|
|
|
|
float sum=0;
|
2022-09-09 17:39:07 +02:00
|
|
|
for (int i=0; i < depth; i++) {
|
|
|
|
for (int j=0; j < rows; j++) {
|
|
|
|
for (int k=0; k < columns; k++) {
|
2023-03-09 14:27:23 +01:00
|
|
|
m = fmaxf(m, input[i][j][k]);
|
2022-07-05 08:13:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-09-09 17:39:07 +02:00
|
|
|
for (int i=0; i < depth; i++) {
|
|
|
|
for (int j=0; j < rows; j++) {
|
|
|
|
for (int k=0; k < columns; k++) {
|
2022-07-05 08:13:25 +02:00
|
|
|
input[i][j][k] = exp(m-input[i][j][k]);
|
|
|
|
sum += input[i][j][k];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-09-09 17:39:07 +02:00
|
|
|
for (int i=0; i < depth; i++) {
|
|
|
|
for (int j=0; j < rows; j++) {
|
|
|
|
for (int k=0; k < columns; k++) {
|
2022-07-05 08:13:25 +02:00
|
|
|
input[i][j][k] = input[i][j][k]/sum;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-03 21:56:42 +01:00
|
|
|
|
2022-07-05 08:13:25 +02:00
|
|
|
void apply_function_input(float (*f)(float), float*** input, int depth, int rows, int columns) {
|
2022-09-09 17:39:07 +02:00
|
|
|
for (int i=0; i < depth; i++) {
|
|
|
|
for (int j=0; j < rows; j++) {
|
|
|
|
for (int k=0; k < columns; k++) {
|
2022-07-05 08:13:25 +02:00
|
|
|
input[i][j][k] = (*f)(input[i][j][k]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-03 21:56:42 +01:00
|
|
|
void apply_function_to_matrix(int activation, float*** input, int depth, int dim) {
|
|
|
|
if (activation == SOFTMAX) {
|
|
|
|
return apply_softmax_input(input, depth, dim, dim);
|
|
|
|
}
|
|
|
|
if (activation > 1) { // Exclude negative values (derivative) and 1 (identity)
|
|
|
|
ptr f = get_activation_function(activation);
|
|
|
|
return apply_function_input(f, input, depth, dim, dim);
|
|
|
|
}
|
|
|
|
printf_error("fonction d'activation inconnue (apply_function_to_matrix): ");
|
|
|
|
printf("%d\n", activation);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void apply_function_to_vector(int activation, float*** input, int dim) {
|
|
|
|
if (activation == SOFTMAX) {
|
|
|
|
return apply_softmax_input(input, 1, 1, dim);
|
|
|
|
}
|
|
|
|
if (activation > 1) { // Exclude negative values (derivative) and 1 (identity)
|
|
|
|
ptr f = get_activation_function(activation);
|
|
|
|
return apply_function_input(f, input, 1, 1, dim);
|
|
|
|
}
|
|
|
|
printf_error("fonction d'activation inconnue (apply_function_to_vector): ");
|
|
|
|
printf("%d\n", activation);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ptr get_activation_function(int activation) {
|
2022-11-01 11:20:17 +01:00
|
|
|
if (activation == RELU) {
|
|
|
|
return &relu;
|
2022-11-12 14:20:13 +01:00
|
|
|
}
|
|
|
|
if (activation == -RELU) {
|
2022-11-01 11:20:17 +01:00
|
|
|
return &relu_derivative;
|
2022-11-12 14:20:13 +01:00
|
|
|
}
|
2023-03-03 21:56:42 +01:00
|
|
|
|
2022-11-12 14:20:13 +01:00
|
|
|
if (activation == IDENTITY) {
|
|
|
|
return &identity;
|
|
|
|
}
|
2023-03-03 21:56:42 +01:00
|
|
|
if (activation == -IDENTITY) {
|
|
|
|
return &identity_derivative;
|
|
|
|
}
|
|
|
|
|
2022-11-12 14:20:13 +01:00
|
|
|
if (activation == SIGMOID) {
|
2022-11-01 11:20:17 +01:00
|
|
|
return &sigmoid;
|
2022-11-12 14:20:13 +01:00
|
|
|
}
|
|
|
|
if (activation == -SIGMOID) {
|
2022-11-01 11:20:17 +01:00
|
|
|
return &sigmoid_derivative;
|
2022-11-12 14:20:13 +01:00
|
|
|
}
|
2023-03-03 21:56:42 +01:00
|
|
|
|
2022-11-12 14:20:13 +01:00
|
|
|
if (activation == SOFTMAX) {
|
2023-02-28 13:14:51 +01:00
|
|
|
printf_error("impossible de renvoyer la fonction softmax\n");
|
2022-11-01 11:20:17 +01:00
|
|
|
return NULL;
|
2022-11-12 14:20:13 +01:00
|
|
|
}
|
|
|
|
if (activation == -SOFTMAX) {
|
2023-02-28 13:14:51 +01:00
|
|
|
printf_error("impossible de renvoyer la dérivée de la fonction softmax\n");
|
2022-11-01 11:20:17 +01:00
|
|
|
return NULL;
|
2022-11-12 14:20:13 +01:00
|
|
|
}
|
2023-03-03 21:56:42 +01:00
|
|
|
|
2022-11-12 14:20:13 +01:00
|
|
|
if (activation == TANH) {
|
2022-11-01 11:20:17 +01:00
|
|
|
return &tanh_;
|
2022-11-12 14:20:13 +01:00
|
|
|
}
|
|
|
|
if (activation == -TANH) {
|
2022-11-01 11:20:17 +01:00
|
|
|
return &tanh_derivative;
|
|
|
|
}
|
2023-03-03 21:56:42 +01:00
|
|
|
|
2023-02-19 12:13:03 +01:00
|
|
|
if (activation == LEAKY_RELU) {
|
|
|
|
return &leaky_relu;
|
|
|
|
}
|
|
|
|
if (activation == -LEAKY_RELU) {
|
|
|
|
return &leaky_relu_derivative;
|
|
|
|
}
|
2023-02-28 13:14:51 +01:00
|
|
|
printf_error("fonction d'activation inconnue (get_activation_function): ");
|
|
|
|
printf("%d\n", activation);
|
2022-11-12 14:20:13 +01:00
|
|
|
return NULL;
|
2022-11-01 11:20:17 +01:00
|
|
|
}
|