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?