본문 바로가기

dev_AI_framework

regularization 의 구현, 별도의 regularizer 의 layer 가 아닌, regularizer 클래스의 구현, Layer 클래스에서의 사용

2024.08.27 - [토이 프로젝트 진행] - activation 의 구현,

 

activation 의 구현,

dev/activations/__init__.pyfrom dev.activations.activations import sigmoidfrom dev.activations.activations import relufrom dev.activations.activations import relu6from dev.activations.activations import leaky_relufrom dev.activations.activations import sof

teach-meaning.tistory.com

activation 의 구현방법과 동일하게 regularization의 구현

다른 점으로 regularizor 는 별도의 해당 형태의 layer 로 존재할 수 없음,

 

해당 층의 가중치에 대해 연산을 수행하는 것이므로 가장 상위 부모 Layer 클래스 내에서 해당 메서드를 구현

 

dev/regulrizers/__init__.py

import inspect

from dev.regularizers.regularizers import L1
from dev.regularizers.regularizers import L2
from dev.regularizers.regularizers import L1L2
from dev.regularizers.regularizers import Orthogonal
from dev.regularizers.regularizers import Regularizer


ALL_REGULARIZERS = {
    L1,
    L2,
    L1L2,
    Orthogonal,
    Regularizer,
}

ALL_REGULARIZERS_DICT = {cls.__name__: cls for cls in ALL_REGULARIZERS}

def get(identifier):
    if identifier is isinstance(str):
        obj = ALL_REGULARIZERS_DICT.get(identifier, None)

    if callable(obj):
        if inspect.isclass(obj):
            obj = obj()
        return obj

    else:
        raise ValueError(
            f"Could not interpret regularizer identifier: {identifier}"
        )

get 메서드 호출 시 obj 반환

 

dev/regularizers/regularizers.py - 각 기능의 정의

import math
import numpy as np

# 계산 결과값을 weight 에 더해야 한다!!!!

class Regularizer:
    def __call__(self, x):
        # 자식 클래스에서 이 부분의 구현을 해야 함
        return 0

class L1(Regularizer):
    def __init__(self, l1=0.01):
        self.l1 = l1

    def __call__(self, weights):
        """
        L1 정규화 연산을 수행합니다.
        
        Args:
            weights (numpy.ndarray): 정규화할 가중치 행렬.
            l1_factor (float): L1 정규화 강도.

        Returns:
            float: L1 정규화 손실 값.
        """
        return self.l1 * np.sum(np.abs(weights))

class L2(Regularizer):
    def __init__(self, l2=0.01):
        self.l2 = l2

    def __call__(self, weights):
        """
        L2 정규화 연산을 수행합니다.
        
        Args:
            weights (numpy.ndarray): 정규화할 가중치 행렬.
            l2_factor (float): L2 정규화 강도.

        Returns:
            float: L2 정규화 손실 값.
        """
        return self.l2 * np.sum(np.square(weights))
    
class L1L2(Regularizer):
    def __init__(self, l1=0.01, l2=0.01):
        self.l1 = l1
        self.l2 = l2

    def l1_l2_regularization(self, weights):
        """
        L1과 L2 정규화 연산을 동시에 수행합니다.
        
        Args:
            weights (numpy.ndarray): 정규화할 가중치 행렬.
            l1_factor (float): L1 정규화 강도.
            l2_factor (float): L2 정규화 강도.

        Returns:
            float: L1 및 L2 정규화 손실 값의 합.
        """
        l1_loss = self.l1 * np.sum(np.abs(weights))
        l2_loss = self.l2 * np.sum(np.square(weights))
        return l1_loss + l2_loss
    
class Orthogonal(Regularizer):
    """
    직교 정규화 연산을 수행합니다.
    
    Args:
        weights (numpy.ndarray): 정규화할 가중치 행렬.
        factor (float): 정규화 강도.
        mode (str): "rows" 또는 "columns", 정규화를 적용할 축을 결정합니다.

    Returns:
        float: 직교 정규화 손실 값.
    """
    def __init__(self, factor=0.01, mode="rows"):
        self.factor = factor
        self.mode = mode

    def __call__(self, weights):
        if self.mode == "rows":
            normalized = weights / np.linalg.norm(weights, axis=1, keepdims=True)
            product = np.dot(normalized, normalized.T)
        elif self.mode == "columns":
            normalized = weights / np.linalg.norm(weights, axis=0, keepdims=True)
            product = np.dot(normalized.T, normalized)
        else:
            raise ValueError("Invalid mode. Use 'rows' or 'columns'.")

        size = product.shape[0]
        product_no_diagonal = product - np.eye(size)
        num_pairs = size * (size - 1) / 2.0
        return self.factor * 0.5 * np.sum(np.abs(product_no_diagonal)) / num_pairs

연산 내용 확인

 

Layer class 에서 쓰이는 방법,

    def __init__(self, name=None, regularizer=None,**kwargs):
        self.name = name
        self.input_shape = None
        self.output_shape = None
        self.regularizer = regularizers.get(regularizer)

인스턴스 정의에서의 사용,

'dev_AI_framework' 카테고리의 다른 글

optimizer, model.compile 구현을 위해..  (0) 2024.08.27
layer-flatten, 검증의 추가 필요  (1) 2024.08.27
activation 의 구현,  (0) 2024.08.27
layers - activation  (0) 2024.08.26
모델, layer 를 어떻게 입력받을 것인가  (0) 2024.08.23