activations_1
Activation Function ์ด๋?
Activation Function(ํ์ฑํ ํจ์)์ ์ธ๊ณต์ ๊ฒฝ๋ง์์ ์ ๋ ฅ ์ ํธ๋ฅผ ์ฒ๋ฆฌํ ํ, ์ถ๋ ฅ ์ ํธ๋ฅผ ๋ง๋ค์ด๋ด๋ ํจ์์ ๋๋ค. ์ฆ, ์ ๋ ฅ๊ฐ์ ๋ํ ๊ฒฐ๊ณผ๊ฐ์ ๊ฒฐ์ ํ๋ ํจ์์ ๋๋ค.
ํ์ฑํ ํจ์๋ ๋น์ ํ ํจ์(non-linear function)์ด์ด์ผ ํฉ๋๋ค. ์ด๋ ์ธ๊ณต์ ๊ฒฝ๋ง์ด ๋ณต์กํ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๊ณ , ๋ค์ํ ํจํด์ ํ์ตํ ์ ์๋๋ก ํ๊ธฐ ์ํจ์ ๋๋ค. ๋ง์ฝ ํ์ฑํ ํจ์๊ฐ ์ ํ ํจ์(linear function)์ด๋ผ๋ฉด, ์ ๊ฒฝ๋ง์ด ๊น์ด์ง์๋ก ์ ๋ ฅ๊ฐ๊ณผ ์ถ๋ ฅ๊ฐ์ด ์ ํ์ ์ธ ๊ด๊ณ๋ฅผ ๊ฐ๊ฒ ๋์ด, ํจ๊ณผ์ ์ธ ํ์ต์ด ๋ถ๊ฐ๋ฅํด์ง๋๋ค.
๋ํ์ ์ธ ํ์ฑํ ํจ์๋ก๋ ์๊ทธ๋ชจ์ด๋ ํจ์, ReLU ํจ์, tanh ํจ์ ๋ฑ์ด ์์ต๋๋ค. ์ด๋ฌํ ํ์ฑํ ํจ์๋ ์ ๋ ฅ๊ฐ์ ๋ํด ๋ค์ํ ๋ณํ๋ฅผ ์ฃผ์ด, ์ ๊ฒฝ๋ง์ด ๋ณต์กํ ํจํด์ ํ์ตํ ์ ์๋๋ก ํฉ๋๋ค.
// darknet.h
typedef enum{
LOGISTIC, RELU, RELIE, LINEAR, RAMP, TANH, PLSE, LEAKY, ELU, LOGGY, STAIR, HARDTAN, LHTAN, SELU
} ACTIVATION;
ํ์ฑํ ํจ์์ ์ข ๋ฅ๋ฅผ ์ ์ํ๋ ์ด๊ฑฐํ(enum)์ ๋๋ค.
๊ฐ๊ฐ์ ํ์ฑํ ํจ์๋ ํด๋น ํจ์์ ํน์ฑ์ ๋ฐ๋ผ ์ ํ๋์ด ์ฌ์ฉ๋ฉ๋๋ค. ์ด๋ฌํ ํ์ฑํ ํจ์๋ค์ ๋ค์ํ ๋น์ ํ์ฑ(non-linearity)์ ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์, ์ธ๊ณต์ ๊ฒฝ๋ง ๋ชจ๋ธ์ด ๋ณต์กํ ํจํด์ ํ์ตํ ์ ์๋๋ก ๋์ต๋๋ค.
๊ฐ ํ์ฑํ ํจ์์ ํน์ง์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
LOGISTIC : ๋ก์ง์คํฑ ํจ์
RELU : ReLU ํจ์
RELIE : ReLU ํจ์์ ๋ณํ
LINEAR : ์ ํ ํจ์
RAMP : RAMP ํจ์
TANH : ํ์ดํผ๋ณผ๋ฆญ ํ์ ํธ ํจ์
PLSE : ํ๋ฆฝ-์ ํ ํจ์
LEAKY : Leaky ReLU ํจ์
ELU : Exponential Linear Units ํจ์
LOGGY : ๋ก์ง์คํฑ ํจ์์ ๋ณํ
STAIR : ๊ณ๋จ ํจ์
HARDTAN : ํ๋ ํ์ ํธ ํจ์
LHTAN : LeCun ํ์ดํผ๋ณผ๋ฆญ ํ์ ํธ ํจ์
SELU : Scaled Exponential Linear Units ํจ์
์ด๋ฌํ ํ์ฑํ ํจ์๋ค์ ๋ชจ๋ธ์ ์ ๋ ฅ๊ฐ์ ๋ํด ์ ํฉํ ๋น์ ํ ๋ณํ์ ์ํํ์ฌ, ๋ชจ๋ธ์ด ์ ๋ ฅ ๋ฐ์ดํฐ์ ํจํด์ ํ์ ํ๊ณ ์์ธก์ ์ํํ ์ ์๋๋ก ํฉ๋๋ค.
get_activation_string
char *get_activation_string(ACTIVATION a)
{
switch(a){
case LOGISTIC:
return "logistic";
case LOGGY:
return "loggy";
case RELU:
return "relu";
case ELU:
return "elu";
case SELU:
return "selu";
case RELIE:
return "relie";
case RAMP:
return "ramp";
case LINEAR:
return "linear";
case TANH:
return "tanh";
case PLSE:
return "plse";
case LEAKY:
return "leaky";
case STAIR:
return "stair";
case HARDTAN:
return "hardtan";
case LHTAN:
return "lhtan";
default:
break;
}
return "relu";
}
ํจ์ ์ด๋ฆ: get_activation_string
์ ๋ ฅ:
a: ํ์ฑํ ํจ์(enum ๊ฐ)
๋์:
์ ๋ ฅ๋ ํ์ฑํ ํจ์(enum ๊ฐ)์ ๋์๋๋ ๋ฌธ์์ด์ ๋ฐํํฉ๋๋ค.
์ค๋ช :
์ด ํจ์๋ ํ์ฑํ ํจ์๋ฅผ ์ ๋ ฅํ๋ฉด ํด๋น ํจ์์ ๋์๋๋ ๋ฌธ์์ด์ ๋ฐํํฉ๋๋ค.
๋ฌธ์์ด์ ํด๋น ํจ์์ ์ด๋ฆ๊ณผ ๋์ผํฉ๋๋ค.
๋ง์ฝ ์ ๋ ฅ๋ ํจ์์ ๋์ํ๋ ๋ฌธ์์ด์ด ์๋ ๊ฒฝ์ฐ, ๊ธฐ๋ณธ๊ฐ์ผ๋ก "relu"๋ฅผ ๋ฐํํฉ๋๋ค.
get_activation
ACTIVATION get_activation(char *s)
{
if (strcmp(s, "logistic")==0) return LOGISTIC;
if (strcmp(s, "loggy")==0) return LOGGY;
if (strcmp(s, "relu")==0) return RELU;
if (strcmp(s, "elu")==0) return ELU;
if (strcmp(s, "selu")==0) return SELU;
if (strcmp(s, "relie")==0) return RELIE;
if (strcmp(s, "plse")==0) return PLSE;
if (strcmp(s, "hardtan")==0) return HARDTAN;
if (strcmp(s, "lhtan")==0) return LHTAN;
if (strcmp(s, "linear")==0) return LINEAR;
if (strcmp(s, "ramp")==0) return RAMP;
if (strcmp(s, "leaky")==0) return LEAKY;
if (strcmp(s, "tanh")==0) return TANH;
if (strcmp(s, "stair")==0) return STAIR;
fprintf(stderr, "Couldn't find activation function %s, going with ReLU\n", s);
return RELU;
}
ํจ์ ์ด๋ฆ: get_activation
์ ๋ ฅ:
s: ํ์ฑํ ํจ์๋ฅผ ๋ํ๋ด๋ ๋ฌธ์์ด
๋์:
์ ๋ ฅ๋ ๋ฌธ์์ด์ ๋์ํ๋ ํ์ฑํ ํจ์(enum ๊ฐ)์ ๋ฐํํฉ๋๋ค.
์ค๋ช :
์ด ํจ์๋ ๋ฌธ์์ด๋ก ํํ๋ ํ์ฑํ ํจ์์ ์ด๋ฆ์ ์ ๋ ฅํ๋ฉด ํด๋น ํจ์์ ๋์ํ๋ enum ๊ฐ(์ ์)์ ๋ฐํํฉ๋๋ค.
ํจ์ ๋ด๋ถ์์๋ ์ ๋ ฅ๋ ๋ฌธ์์ด์ ํ์ฑํ ํจ์ ์ด๋ฆ๋ค๊ณผ ๋น๊ตํ์ฌ ๋์ํ๋ enum ๊ฐ์ ๋ฐํํ๋ฉฐ, ์ ๋ ฅ๋ ๋ฌธ์์ด์ด ์ด๋ ํ ํ์ฑํ ํจ์์๋ ๋์๋์ง ์๋ ๊ฒฝ์ฐ์๋ ๊ธฐ๋ณธ๊ฐ์ผ๋ก RELU๋ฅผ ๋ฐํํฉ๋๋ค.
์ด ๋, ํจ์๋ stderr์ ์ด์ฉํ์ฌ ์๋ฌ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
activate
float activate(float x, ACTIVATION a)
{
switch(a){
case LINEAR:
return linear_activate(x);
case LOGISTIC:
return logistic_activate(x);
case LOGGY:
return loggy_activate(x);
case RELU:
return relu_activate(x);
case ELU:
return elu_activate(x);
case SELU:
return selu_activate(x);
case RELIE:
return relie_activate(x);
case RAMP:
return ramp_activate(x);
case LEAKY:
return leaky_activate(x);
case TANH:
return tanh_activate(x);
case PLSE:
return plse_activate(x);
case STAIR:
return stair_activate(x);
case HARDTAN:
return hardtan_activate(x);
case LHTAN:
return lhtan_activate(x);
}
return 0;
}
ํจ์ ์ด๋ฆ: activate
์ ๋ ฅ:
x: ํ์ฑํ ํจ์์ ๋ํ ์ ๋ ฅ ๊ฐ
a: ์ ์ฉํ ํ์ฑํ ํจ์
๋์:
์ ๋ ฅ๋ ํ์ฑํ ํจ์(enum ๊ฐ)์ ๋ฐ๋ผ x ๊ฐ์ ํ์ฑํํฉ๋๋ค.
์ค๋ช :
์ด ํจ์๋ ์ ๋ ฅ๋ ์ค์๊ฐ x์ ํ์ฑํ ํจ์(enum ๊ฐ)์ ์ ๋ ฅ๋ฐ์, ํด๋น ํ์ฑํ ํจ์์ ๋ฐ๋ผ x ๊ฐ์ ํ์ฑํํฉ๋๋ค. ์ด ํจ์๋ float ํ ๊ฐ์ ๋ฐํํฉ๋๋ค.
ํ์ฑํ ํจ์๋ ์ ํ(linear), ๋ก์ง์คํฑ(logistic), ๋ก๊ทธ(loggy), ReLU(relu), ELU(elu), SELU(selu), RELIE(relie), RAMP(ramp), LeakyReLU(leaky), ํ์ดํผ๋ณผ๋ฆญ ํ์ ํธ(tanh), PLSE(plse), STAIR(stair), HardTanh(hardtan), LHTan(lhtan) ๋ฑ์ด ๊ฐ๋ฅํฉ๋๋ค.
ํด๋น ํจ์๋ ์ ๋ ฅ๋ ํ์ฑํ ํจ์(enum ๊ฐ)์ ๋ฐ๋ผ ์ ์ ํ ํ์ฑํ ํจ์๋ฅผ ํธ์ถํ์ฌ ์ค์๊ฐ x๋ฅผ ์ฒ๋ฆฌํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํฉ๋๋ค.
activate_array
void activate_array(float *x, const int n, const ACTIVATION a)
{
int i;
for(i = 0; i < n; ++i){
x[i] = activate(x[i], a);
}
}
ํจ์ ์ด๋ฆ: activate_array
์ ๋ ฅ:
x: ์ ๋ ฅ๊ฐ ๋ฐฐ์ด
n: ๋ฐฐ์ด ํฌ๊ธฐ
a: ํ์ฑํ ํจ์
๋์:
์ ๋ ฅ๊ฐ ๋ฐฐ์ด x์ ํ์ฑํ ํจ์ a๋ฅผ ์ ์ฉํ์ฌ ๊ฐ ์์๋ฅผ ํ์ฑํํฉ๋๋ค.
์ค๋ช :
์ด ํจ์๋ ์ ๋ ฅ๊ฐ ๋ฐฐ์ด x์ ๊ฐ ์์์ ํ์ฑํ ํจ์ a๋ฅผ ์ ์ฉํฉ๋๋ค.
์ ๋ ฅ๊ฐ ๋ฐฐ์ด x์ ๋ฐฐ์ด ํฌ๊ธฐ n, ๊ทธ๋ฆฌ๊ณ ํ์ฑํ ํจ์ a๋ฅผ ์ ๋ ฅ์ผ๋ก ๋ฐ์ต๋๋ค.
๋ฐฐ์ด x์ ๊ฐ ์์์ ๋ํด activate ํจ์๋ฅผ ํธ์ถํ์ฌ ํ์ฑํ๋ ๊ฐ์ ๋ค์ ๋ฐฐ์ด x์ ํด๋น ์์์ ์ ์ฅํฉ๋๋ค.
์ด ๊ณผ์ ์ ๋ฐฐ์ด x์ ๋ชจ๋ ์์์ ๋ํด ๋ฐ๋ณตํ๋ฉด, ์ ๋ ฅ๊ฐ ๋ฐฐ์ด x์ ํ์ฑํ ํจ์ a๋ฅผ ์ ์ฉํ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ต๋๋ค.
gradient
float gradient(float x, ACTIVATION a)
{
switch(a){
case LINEAR:
return linear_gradient(x);
case LOGISTIC:
return logistic_gradient(x);
case LOGGY:
return loggy_gradient(x);
case RELU:
return relu_gradient(x);
case ELU:
return elu_gradient(x);
case SELU:
return selu_gradient(x);
case RELIE:
return relie_gradient(x);
case RAMP:
return ramp_gradient(x);
case LEAKY:
return leaky_gradient(x);
case TANH:
return tanh_gradient(x);
case PLSE:
return plse_gradient(x);
case STAIR:
return stair_gradient(x);
case HARDTAN:
return hardtan_gradient(x);
case LHTAN:
return lhtan_gradient(x);
}
return 0;
}
ํจ์ ์ด๋ฆ: gradient
์ ๋ ฅ:
x: ํ์ฑํ ํจ์์ ๋ํ ์ ๋ ฅ ๊ฐ
a: ์ ์ฉํ ํ์ฑํ ํจ์
๋์:
์ ๋ ฅ ๊ฐ x์ ์ ์ฉํ ํ์ฑํ ํจ์ a์ ๋ฐ๋ผ ํด๋น ํ์ฑํ ํจ์์ ๋ํจ์๋ฅผ ๊ณ์ฐํ์ฌ ๋ฐํํ๋ ํจ์
์ค๋ช :
์ ๊ฒฝ๋ง์์ ์ญ์ ํ(backpropagation) ์๊ณ ๋ฆฌ์ฆ์ ์ ์ฉํ ๋, ์ค์ฐจ(error)๋ฅผ ์ต์ํํ๊ธฐ ์ํด ๊ฐ์ค์น(weight)๋ฅผ ์กฐ์ ํด์ผ ํ๋๋ฐ, ์ด๋ฅผ ์ํด ๊ฐ ๋ ธ๋์ ์ ๋ ฅ ๊ฐ์ด ํ์ฑํ ํจ์๋ฅผ ๊ฑฐ์ณ ์ถ๋ ฅ ๊ฐ์ผ๋ก ๋ณํ๋๋ ๊ณผ์ ์์ ํด๋น ํ์ฑํ ํจ์์ ๋ํจ์(gradient)๋ฅผ ๊ตฌํด์ผ ํ๋ค.
gradient ํจ์๋ ์ ๋ ฅ ๊ฐ x์ ์ ์ฉํ ํ์ฑํ ํจ์ a๋ฅผ ๋ฐ์ ํด๋น ํ์ฑํ ํจ์์ ๋ํจ์๋ฅผ ๊ณ์ฐํ์ฌ ๋ฐํํ๋ ํจ์๋ก, switch๋ฌธ์ ์ฌ์ฉํ์ฌ ์ ๋ ฅ์ผ๋ก ๋ฐ์ ํ์ฑํ ํจ์ a์ ๋ฐ๋ผ ํด๋น ๋ํจ์๋ฅผ ๊ณ์ฐํ์ฌ ๋ฐํํ๋ค.
gradient_array
void gradient_array(const float *x, const int n, const ACTIVATION a, float *delta)
{
int i;
for(i = 0; i < n; ++i){
delta[i] *= gradient(x[i], a);
}
}
ํจ์ ์ด๋ฆ: gradient_array
์ ๋ ฅ:
x: ์ ๋ ฅ ๋ฐฐ์ด ํฌ์ธํฐ
n: ์ ๋ ฅ ๋ฐฐ์ด์ ํฌ๊ธฐ
a: ํ์ฑํ ํจ์
delta: ์ถ๋ ฅ ๋ฐฐ์ด ํฌ์ธํฐ
๋์:
์ ๋ ฅ ๋ฐฐ์ด x์ ๊ฐ ์์์ ๋ํ ํ์ฑํ ํจ์์ ๋ฏธ๋ถ ๊ฐ์ delta์ ๊ณฑํ์ฌ ์ถ๋ ฅ ๋ฐฐ์ด์ ๊ณ์ฐํ๋ค.
์ด ํจ์๋ ์ญ์ ํ(backpropagation) ์๊ณ ๋ฆฌ์ฆ์์ ์ฌ์ฉ๋๋ฉฐ, ๋ฏธ๋ถ ๊ฐ(delta)์ ์ ๋ ฅ์ผ๋ก ๋ฐ์, ์ด์ ์ธต์์ ์ ๋ฌ๋ ๋ฏธ๋ถ ๊ฐ์ ๋ํ ํ์ฌ ์ธต์ ๋ฏธ๋ถ ๊ฐ์ ๊ณ์ฐํ์ฌ ์ด์ ์ธต์ผ๋ก ์ ๋ฌํ๋ ์ญํ ์ ํ๋ค.
์ค๋ช :
์ญ์ ํ ์๊ณ ๋ฆฌ์ฆ์ ๋ฅ๋ฌ๋ ํ์ต์์ ์ฌ์ฉ๋๋ ๊ธฐ๋ฒ์ผ๋ก, ์ถ๋ ฅ ๊ฐ๊ณผ ์ค์ ๊ฐ ์ฌ์ด์ ์ค์ฐจ๋ฅผ ์ต์ํํ๋ ๋ฐฉํฅ์ผ๋ก ๊ฐ์ค์น์ ํธํฅ์ ์ ๋ฐ์ดํธํ๋ค.
์ด ๊ณผ์ ์์ gradient_array ํจ์๋ ๊ฐ ์ธต์์ ๊ณ์ฐ๋ ๋ฏธ๋ถ ๊ฐ๊ณผ ํ์ฑํ ํจ์์ ๋ฏธ๋ถ ๊ฐ์ ๊ณฑํ์ฌ ์ด์ ์ธต์ผ๋ก ์ ๋ฌํ๋ฉฐ, ์ด์ ์ธต์์ ์ ๋ฌ๋ ๋ฏธ๋ถ ๊ฐ์ ํ์ฌ ์ธต์์ ๊ณฑํ์ฌ ์ถ๋ ฅ ๋ฐฐ์ด์ ๋ฏธ๋ถ ๊ฐ์ ๊ณ์ฐํ๋ค. ์ด๋ ๊ฒ ๊ณ์ฐ๋ ๋ฏธ๋ถ ๊ฐ์ ๊ฐ์ค์น์ ํธํฅ์ ์ ๋ฐ์ดํธํ ๋ ์ฌ์ฉ๋๋ค.
Last updated
Was this helpful?