Updated:

🧧 Attribute Function

이번 ν¬μŠ€νŒ…μ€ Python μ½”λ“œλ₯Ό μž‘μ„±ν•˜λ©΄μ„œ 객체와 λ‚΄λΆ€ λ©”μ„œλ“œμ— κ΄€λ ¨ν•œ μ²˜λ¦¬κ°€ ν•„μš”ν•  λ•Œ κ°€μž₯ 많이 μ‚¬μš©ν•˜κ²Œ λ˜λŠ” getattr, setattr , delattr , hasttr ν•¨μˆ˜λ“€μ˜ μ‚¬μš©λ²•μ— λŒ€ν•΄ 닀뀄보렀 ν•œλ‹€. 특히 getattr, setattr 의 경우 λ¨Έμ‹ λŸ¬λ‹ ν˜Ήμ€ λ”₯λŸ¬λ‹ κ΄€λ ¨ μ½”λ“œλ₯Ό 읽닀가 μ‹¬μ‹¬μΉ˜ μ•Šκ²Œ μ°Ύμ•„λ³Ό 수 μžˆλ‹€. λͺ¨λΈμ˜ hyper-parameterλ₯Ό νŠœλ‹ν•˜κ±°λ‚˜ 기타 μ‹€ν—˜μ„ ν•  λ•Œ μ •μ˜ν•œ 객체의 λ³€μˆ˜ ν˜Ήμ€ λ©”μ„œλ“œμ— 쉽고 κ°„κ²°ν•˜κ²Œ μ ‘κ·Όν•˜κΈ° μœ„ν•΄ μ‚¬μš©λ˜κ³  있기 λ•Œλ¬Έμ΄λ‹€.

πŸ“Œ getattr

""" getattr(object, attribute_name, default) """

class CFG:
    """--------[Common]--------"""
    wandb, train, competition, seed, cfg_name = True, True, 'UPPPM', 42, 'CFG'
    device, gpu_id = torch.device('cuda' if torch.cuda.is_available() else 'cpu'), 0
    num_workers = 0
    """ Mixed Precision, Gradient Check Point """
    amp_scaler = True
    gradient_checkpoint = True # save parameter
    output_dir = './output/'
    """ Clipping Grad Norm, Gradient Accumulation """
    clipping_grad = True # clip_grad_norm
    n_gradient_accumulation_steps = 1 # Gradient Accumulation
    max_grad_norm = n_gradient_accumulation_steps * 1000
    """ Model """
    model_name = 'microsoft/deberta-v3-large'
    tokenizer = AutoTokenizer.from_pretrained(model_name)
#    pooling = 'attention'
    max_len = 512
    """ CV, Epoch, Batch Size """
    n_folds = 4
    epochs = 180
    batch_size = 64

μœ„μ˜ κ°μ²΄λŠ” μ‹€μ œ μ œκ°€ 캐글 λŒ€νšŒλ₯Ό μ€€λΉ„ν•˜λ©΄μ„œ μ‚¬μš©ν–ˆλ˜ config.py λ₯Ό κ°€μ Έμ™”λ‹€.

getattr(object: object, attribute_name: str, default: Any) ν•¨μˆ˜λŠ” μ‚¬μš©μžκ°€ μ§€μ •ν•œ 객체에 λ§€κ°œλ³€μˆ˜λ‘œ μ „λ‹¬ν•œ attributeκ°€ μ‘΄μž¬ν•˜λŠ”μ§€ μ—¬λΆ€λ₯Ό νŒλ‹¨ν•˜κ³ , μ‘΄μž¬ν•œλ‹€λ©΄ ν•΄λ‹Ή attribute의 valueλ₯Ό λ°˜ν™˜ν•œλ‹€. ν•œνŽΈ μ‘΄μž¬ν•˜μ§€ μ•ŠμœΌλ©΄ default둜 μ„ΈνŒ…ν•œ 값을 λ°˜ν™˜ν•œλ‹€.

getattr(CFG, 'epochs', "This Attribute doesn't find")
getattr(CFG, 'MPL', "This Attribute doesn't find")
--------------- Result --------------- 
180
This Attribute doesn't find

if-else ꡬ문보닀 훨씬 κ°„κ²°ν•˜κ²Œ 객체의 λ©”μ„œλ“œμ— μ ‘κ·Όν•˜λŠ” 것이 κ°€λŠ₯ν•΄μ‘ŒμœΌλ©°, default 값을 λ§€κ°œλ³€μˆ˜λ‘œ 전달 λ°›κΈ° λ•Œλ¬Έμ— ν΄λΌμ΄μ–ΈνŠΈκ°€ μ§€μ •ν•œ attribute κ°€ 객체 내뢀에 없어도 AttributeError λ₯Ό λ°œμƒμ‹œν‚€μ§€ μ•Šμ•„ μ˜ˆμ™Έ 처리λ₯Ό λ³„λ„λ‘œ 지정할 ν•„μš”κ°€ 사라져 μ½”λ“œ 가독성 및 μœ μ§€λ³΄μˆ˜μ— μš©μ΄ν•˜λ‹€λŠ” μž₯점이 μžˆλ‹€.

class Exmple:
    def __init__(self):
        self.test1 = 0
        self.test2 = 0
    def A(self):
        print("A")  
    def B(self):
        print("B")  
    def C(self):
        print("C")

if __name__ == '__main__':
    exmple = Exmple()
    class_list = ['A','B','C']

    for c in class_list:
        getattr(exmple, c)()

ν•œνŽΈ getattr() 뒀에 κ΄„ν˜Έλ₯Ό ν•˜λ‚˜ 더 λΆ™μ—¬μ„œ μ‚¬μš©ν•˜κΈ°λ„(λ¨Έμ‹ λŸ¬λ‹, λ”₯λŸ¬λ‹ ν›ˆλ ¨ 루프 μ½”λ“œμ— μ’…μ’… λ³΄μž„) ν•˜λŠ”λ°, ν•΄λ‹Ή κ΄„ν˜ΈλŠ” 지정 attribute 의 ν˜ΈμΆœμ— ν•„μš”ν•œ λ§€κ°œλ³€μˆ˜λ₯Ό μ „λ‹¬ν•˜κΈ° μœ„ν•œ μš©λ„λ‘œ 쓰인닀. 이번 μ˜ˆμ‹œμ˜ 객체 λ‚΄λΆ€ λ©”μ„œλ“œλ“€μ€ ν˜ΈμΆœμ— ν•„μš”ν•œ λ§€κ°œλ³€μˆ˜κ°€ μ •μ˜λ˜μ–΄ μžˆμ§€ μ•ŠκΈ° λ•Œλ¬Έμ— κ΄„ν˜Έ μ•ˆμ„ λΉ„μ›Œλ’€λ‹€.

βœ‚οΈ setattr

""" setattr(object, attribute_name, value) """

class CFG:
    """--------[Common]--------"""
    wandb, train, competition, seed, cfg_name = True, True, 'UPPPM', 42, 'CFG'
    device, gpu_id = torch.device('cuda' if torch.cuda.is_available() else 'cpu'), 0
    num_workers = 0
    """ Mixed Precision, Gradient Check Point """
    amp_scaler = True
    gradient_checkpoint = True # save parameter
    output_dir = './output/'
    """ Clipping Grad Norm, Gradient Accumulation """
    clipping_grad = True # clip_grad_norm
    n_gradient_accumulation_steps = 1 # Gradient Accumulation
    max_grad_norm = n_gradient_accumulation_steps * 1000
    """ Model """
    model_name = 'microsoft/deberta-v3-large'
    tokenizer = AutoTokenizer.from_pretrained(model_name)
#    pooling = 'attention'
    max_len = 512
    """ CV, Epoch, Batch Size """
    n_folds = 4
    epochs = 180
    batch_size = 64

setattr(object: object, attribute_name: str, value: Any) λŠ” 지정 객체의 지정 λ©”μ„œλ“œ ν˜Ήμ€ λ³€μˆ˜μ— μ ‘κ·Όν•˜κ³  μ œμ–΄ν•˜λŠ” μš©λ„λ‘œ μ‚¬μš©ν•˜λŠ” ν•¨μˆ˜λ‹€. 지정 객체 λ‹¨μœ„λ‘œ μ ‘κ·Ό κ°€λŠ₯ν•˜κΈ° λ•Œλ¬Έμ— λͺ¨λΈμ„ νŠœλ‹ν•  λ•Œ 정말 많이 μ‚¬μš©ν•˜κ²Œ λœλ‹€. setattr() λ₯Ό ν™œμš©ν•΄ 상황에 λ§žλŠ” νŒŒλΌλ―Έν„°λ₯Ό λͺ¨λΈμ— μ£Όμž…ν•˜κ³  ν•΄λ‹Ή configλ₯Ό json ν˜Ήμ€ yaml ν˜•μ‹μœΌλ‘œ μ €μž₯해두면 λͺ¨λΈμ˜ 버전별 νŒŒλΌλ―Έν„° 값을 효율적으둜 관리할 수 μžˆμœΌλ‹ˆ κΈ°μ–΅ν•΄λ‘μž.

CFG.wandb
setattr(CFG, 'wandb', False)
CFG.wandb
setattr(CFG, 'wandb', True)
CFG.wandb

--------------- Result --------------- 
True
False
True

πŸ“Œ hasattr

hasattr(object, attribute_name) λŠ” 지정 객체에 λ§€κ°œλ³€μˆ˜λ‘œ μ „λ‹¬ν•œ attribute κ°€ μ‘΄μž¬ν•˜λ©΄ True, μ—†λ‹€λ©΄ False λ₯Ό λ°˜ν™˜ν•œλ‹€. μ‚¬μš©λ²•μ€ getattr() 와 맀우 μœ μ‚¬ν•˜κΈ° λ•Œλ¬Έμ— μƒλž΅ν•œλ‹€.

✏️ delattr

delattr(object, attribute_name) λŠ” 지정 객체에 λ§€κ°œλ³€μˆ˜λ‘œ μ „λ‹¬ν•œ attributeλ₯Ό 객체 λ‚΄λΆ€μ—μ„œ μ‚­μ œν•˜λŠ” 역할을 ν•œλ‹€. μ‚¬μš© μ˜ˆμ‹œλŠ” μ•„λž˜μ™€ κ°™λ‹€.

delattr(CFG, 'epochs')
hasattr(CFG, 'epochs')

--------------- Result --------------- 
False

ν•œνŽΈ, λͺ¨λ“ˆ(ex: config,py, model.py, model_utils.py λ“±)도 객체둜 κ°„μ£Όλ˜κΈ° λ•Œλ¬Έμ— μœ„μ—μ„œ μ‚΄νŽ΄λ³Έ 4가지 function은 λͺ¨λ“ˆ λ ˆλ²¨μ—μ„œλ„ λ™μΌν•˜κ²Œ μ‚¬μš©ν•  수 μžˆλ‹€.

⚠️ Assertion

assert 쑰건, 메세지 

쑰건이 True이면 μ•„λ¬΄λŸ° 일이 μΌμ–΄λ‚˜μ§€ μ•ŠλŠ”λ‹€. ν•˜μ§€λ§Œ 쑰건이 False이면 AssertionErrorκ°€ λ°œμƒν•˜κ³  μ§€μ •ν•œ 메세지가 좜λ ₯λœλ‹€. 메세지λ₯Ό μ§€μ •ν•˜μ§€ μ•Šμ•˜λ‹€λ©΄ AssertionErrorκ°€ λ™μΌν•˜κ²Œ λ°œμƒν•˜μ§€λ§Œ ꡬ체적인 μ—λŸ¬ λͺ…μ‹œλž€μ€ λΉ„μ›Œμ§„ μ±„λ‘œ λ‘œκ·Έκ°€ 좜λ ₯λœλ‹€.

assertλŠ” μ½”λ“œμ˜ 였λ₯˜λ₯Ό μ°ΎλŠ” 데 μœ μš©ν•˜λ‹€. λ˜ν•œ μ½”λ“œμ˜ μ˜λ„λ₯Ό λͺ…ν™•ν•˜κ²Œ ν‘œν˜„ν•˜λŠ” 데에도 μœ μš©ν•˜λ‹€. 예λ₯Ό λ“€μ–΄, λ³€μˆ˜μ˜ 값이 νŠΉμ • 쑰건을 λ§Œμ‘±ν•΄μ•Ό ν•œλ‹€λŠ” 것을 assertλ₯Ό μ‚¬μš©ν•΄ ν‘œν˜„ν•  수 μžˆλ‹€.

assertλŠ” μ—λŸ¬ 둜그λ₯Ό λ°˜ν™˜ν•˜λ©΄μ„œ κ°œλ°œμžκ°€ ν”„λ‘œκ·Έλž¨μ„ λ§Œλ“œλŠ” 과정에 κ΄€μ—¬ν•œλ‹€. μ›ν•˜λŠ” 쑰건의 λ³€μˆ˜ 값을 보증받을 λ•ŒκΉŒμ§€ assert둜 ν…ŒμŠ€νŠΈ ν•  수 μžˆλ‹€. μ΄λŠ” 데이터 μœ νš¨μ„± κ²€μ‚¬μ²˜λŸΌ λ‹¨μˆœνžˆ μ—λŸ¬λ₯Ό μ°ΎλŠ”κ²ƒμ΄ μ•„λ‹ˆλΌ 값을 λ³΄μ¦ν•˜κΈ° μœ„ν•΄ μ‚¬μš©λœλ‹€. 예λ₯Ό λ“€μ–΄ ν•¨μˆ˜μ˜ μž…λ ₯ 값이 μ–΄λ–€ 쑰건의 μ°Έμž„μ„ λ³΄μ¦ν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν•  수 있고 ν•¨μˆ˜μ˜ λ°˜ν™˜ 값이 μ–΄λ–€ 쑰건에 λ§Œμ‘±ν•˜λ„λ‘ λ§Œλ“€ 수 μžˆλ‹€. ν˜Ήμ€ λ³€μˆ˜ 값이 λ³€ν•˜λŠ” κ³Όμ •μ—μ„œ νŠΉμ • 뢀뢄은 λ°˜λ“œμ‹œ μ–΄λ–€ μ˜μ—­μ— μ†ν•˜λŠ” 것을 λ³΄μ¦ν•˜κΈ° μœ„ν•΄ κ°€μ • 섀정문을 톡해 확인 ν•  μˆ˜λ„ μžˆλ‹€. assertλŠ” μ‹€μˆ˜λ₯Ό κ°€μ •ν•΄ 값을 λ³΄μ¦ν•˜λŠ” λ°©μ‹μœΌλ‘œ μ½”λ”© ν•˜κΈ° λ•Œλ¬Έμ— '방어적 ν”„λ‘œκ·Έλž˜λ°'에 μ†ν•œλ‹€. 방어적 ν”„λ‘œκ·Έλž˜λ°μ— λŒ€ν•œ μžμ„Έν•œ λ‚΄μš©μ€ λ‹€μŒ ν¬μŠ€νŠΈμ—μ„œ μ‚΄νŽ΄λ³΄λ„λ‘ ν•˜μž.

# Python assert 데이터 μœ νš¨μ„± 검사 μ˜ˆμ‹œ
class DeBERTa(nn.Module):
    def __init__(self,):
    ...μ€‘λž΅...

    def forward(self, inputs: Tensor, mask: Tensor):
        assert inputs.ndim == 3, f'Expected (batch, sequence, vocab_size) got {inputs.shape}'
    ...μ€‘λž΅...

μœ„μ˜ μ½”λ“œλŠ” ν•„μžκ°€ 논문을 보고 따라 κ΅¬ν˜„ν•œ DeBERTa λͺ¨λΈ μ΅œμƒμœ„ 객체의 μ½”λ“œ 일뢀뢄이닀. μ΅œμƒμœ„ κ°μ²΄λŠ” λͺ¨λΈμ˜ μž…λ ₯ μž„λ² λ”© μΈ΅κ³Ό μœ„μΉ˜ μž„λ² λ”© 측을 μ •μ˜ν•΄μ€˜μ•Ό ν•˜κΈ° λ•Œλ¬Έμ— λ°˜λ“œμ‹œ μž…λ ₯값을 미리 정해진 차원 ν˜•μ‹μ— 맞게 객체의 맀개 λ³€μˆ˜λ‘œ λ„˜κ²¨μ€˜μ•Ό ν•œλ‹€. 지정 ν˜•μ‹μ—μ„œ λ²—μ–΄λ‚œ ν…μ„œλŠ” μž…λ ₯으둜 μ‚¬μš©λ  수 μ—†κ²Œ λ§Œλ“€κΈ° μœ„ν•΄ 객체의 forward λ©”μ„œλ“œ μ‹œμž‘λΆ€λΆ„μ— assert ν•¨μˆ˜λ₯Ό 두어 데이터 μœ νš¨μ„± 검사λ₯Ό ν•˜λ„λ‘ κ΅¬ν˜„ν–ˆλ‹€. μ§€μ •λœ 차원 ν˜•νƒœμ— λ§žμ§€ μ•ŠλŠ” 데이터λ₯Ό μž…λ ₯ν•˜κ²Œ 되면 AssertionError와 ν•¨κ»˜ ν•„μžκ°€ μ§€μ •ν•œ μ—λŸ¬ 메세지λ₯Ό λ°˜ν™˜ λ°›κ²Œ 될 것이닀.

ν•œνŽΈ AssertionErrorλŠ” ν”„λ‘œκ·Έλž˜λ¨Έκ°€ μ˜λ„μ— λ§žμ§€ μ•ŠλŠ” λ©”μ„œλ“œ ν˜Ήμ€ 객체 μ‚¬μš©μ„ 막기 μœ„ν•΄ μ„ μ œμ μœΌλ‘œ λŒ€μ‘ν•œ 것이라고 λ³Ό 수 μžˆλ‹€. μ΄λŠ” ν”„λ‘œκ·Έλž˜λ¨Έκ°€ λ§Œλ“  κ·œμΉ™μ— ν•΄λ‹Ήν•  뿐, μ‹€μ œ νŒŒμ΄μ¬μ΄λ‚˜ 컴퓨터 λ‚΄λΆ€ λ™μž‘ 문법에 ν‹€λ Έλ‹€λŠ” 것을 μ˜λ―Έν•˜λŠ” 것은 μ•„λ‹ˆλ‹€.

Leave a comment