Drop out

안녕하세요 Drop out 코드에 대해서 궁금증이 있는데
image
이 코드를 보시면 랜덤하게 layer 을 삭제하고 하는데 class 를 하나더 생성해서 랜덤하게 삭제하지않고 한줄을 아에 삭제할수 있게 코드를 생성할수있을까요 ?

안녕하세요, @111님.
제가 질문을 잘 이해했는지 확신이 없는데요,
np.random.rand()를 이용하지 않고 특정 위치의 weight(들)을 삭제하고 싶으신걸까요?

제가 이해한게 맞다면,
원하시는 위치(또는 dim)에 해당하게 True 또는 False 값을 갖는 mask를 생성하면 어떨까요?

1개의 좋아요

안녕하세요 답변 잘받았습니다. 혹시 제가 설명이조금 부족햇던거 같네요.
Drop out 을 하게되면 이코드에서는 layer 의 뉴런 들이 랜덤하게 삭제되어 학습이되는데 이렇게 랜덤하게 하다보면 한열이 다 삭제 될수있는 경우가 발생할수있는데 이 경우를 제가 직접 코드를 살짝 변형해서 바로 보기를 원하는것입니다.!

네, 위 코드에서 mask를 원하시는대로 생성하시면 될 것 같은 생각이 드는데요,
아래 코드를 참고하시면 도움이 되실까요?

>>> import numpy as np
>>> x = np.random.rand(3,2,5) # [3, 2, 5] 크기의 x 생성
>>> x
array([[[0.46918172, 0.11258791, 0.88114393, 0.34234521, 0.44530634],
        [0.57807807, 0.06605846, 0.55750651, 0.57141833, 0.16246153]],

       [[0.28683157, 0.50322143, 0.87470317, 0.27679885, 0.22180408],
        [0.95859261, 0.85769476, 0.02367689, 0.72162698, 0.15803484]],

       [[0.31796843, 0.39526271, 0.42042104, 0.22151302, 0.46494404],
        [0.24672249, 0.82213232, 0.96528883, 0.15269747, 0.08857033]]])
>>> mask = np.ones(x.shape) # x와 동일한 크기의 mask 생성
>>> mask
array([[[1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1.]],

       [[1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1.]],

       [[1., 1., 1., 1., 1.],
        [1., 1., 1., 1., 1.]]])
>>> mask[:, :, 2] = 0 # 원하는 위치의 값을 0으로 변경
>>> mask
array([[[1., 1., 0., 1., 1.],
        [1., 1., 0., 1., 1.]],

       [[1., 1., 0., 1., 1.],
        [1., 1., 0., 1., 1.]],

       [[1., 1., 0., 1., 1.],
        [1., 1., 0., 1., 1.]]])
>>> x * (mask == 1) # 위에서 변경한 위치들의 값들을 제외한 나머지 값들만 반영
array([[[0.46918172, 0.11258791, 0.        , 0.34234521, 0.44530634],
        [0.57807807, 0.06605846, 0.        , 0.57141833, 0.16246153]],

       [[0.28683157, 0.50322143, 0.        , 0.27679885, 0.22180408],
        [0.95859261, 0.85769476, 0.        , 0.72162698, 0.15803484]],

       [[0.31796843, 0.39526271, 0.        , 0.22151302, 0.46494404],
        [0.24672249, 0.82213232, 0.        , 0.15269747, 0.08857033]]])
>>>
1개의 좋아요

혹시 class 를 하나 더생성해서 할수 있을까요 ??

네, 위 코드의 마스크 생성 부분을
(처음 질문주셨던 Dropout 클래스를 새로 만든 뒤) forward() 부분에 바꿔 넣으면 될거 같습니다.

가중치가 적용되지 않길 원하시는 dim / col 정도를 추가 인자로 받아서 mask를 생성하게 하면 어떨까요?

1개의 좋아요

정말 죄송한데
이코드에서는 drop out 을 매 layer 마다 진행하는데 class 를 사용해서 매 layer 마다 진행하지 않고 모든 layer을 처음에 지정해줫던 dropout ratio 에 의해서 모든 layer 를 drop out 할수 있는 방법이 있을까요?
(이렇게하다보면 한줄을 다삭제 할수있다는 생각이 들어서 위와 같은 말을 했던거같습니다.)

1개의 좋아요

아, 그러시면 모델 전체의 매개변수들에 대해서 일괄적으로 (특정 Layer나 dim/col을 지우는 등의) Dropout을 진행하고 싶으신거로 이해해도 될까요?

위와 같이 제가 이해한게 맞다면, 한 Layer의 가중치를 모두 변경하여 원하시는 형태로 만들 수도 있지 않을까 싶습니다.
(다만 이 경우 각 Layer마다 가중치들의 차원/모양이 다른 부분이 있어 특정 dim/col만 변경하시는 것은 좀 고민이 필요할 것 같습니다.)

예를 들어서 아래처럼 model.parameters()를 사용하여 각 Layer의 가중치들에 접근하는 방식도 가능할 것 같습니다.

>>> import torch
>>> model = torch.hub.load('pytorch/vision:v0.9.0', 'resnet18', pretrained=True)
Using cache found in /Users/blah/.cache/torch/hub/pytorch_vision_v0.9.0
>>> for p in model.parameters():
...   print(p.shape) # print 대신 다른 함수를 사용하여 각 Layer의 가중치에 직접 접근
...
torch.Size([64, 3, 7, 7])
torch.Size([64])
torch.Size([64])
torch.Size([64, 64, 3, 3])
torch.Size([64])
torch.Size([64])
torch.Size([64, 64, 3, 3])
torch.Size([64])
torch.Size([64])
torch.Size([64, 64, 3, 3])
torch.Size([64])
torch.Size([64])
torch.Size([64, 64, 3, 3])
torch.Size([64])
torch.Size([64])
torch.Size([128, 64, 3, 3])
torch.Size([128])
torch.Size([128])
torch.Size([128, 128, 3, 3])
torch.Size([128])
torch.Size([128])
torch.Size([128, 64, 1, 1])
torch.Size([128])
torch.Size([128])
torch.Size([128, 128, 3, 3])
torch.Size([128])
torch.Size([128])
torch.Size([128, 128, 3, 3])
torch.Size([128])
torch.Size([128])
torch.Size([256, 128, 3, 3])
torch.Size([256])
torch.Size([256])
torch.Size([256, 256, 3, 3])
torch.Size([256])
torch.Size([256])
torch.Size([256, 128, 1, 1])
torch.Size([256])
torch.Size([256])
torch.Size([256, 256, 3, 3])
torch.Size([256])
torch.Size([256])
torch.Size([256, 256, 3, 3])
torch.Size([256])
torch.Size([256])
torch.Size([512, 256, 3, 3])
torch.Size([512])
torch.Size([512])
torch.Size([512, 512, 3, 3])
torch.Size([512])
torch.Size([512])
torch.Size([512, 256, 1, 1])
torch.Size([512])
torch.Size([512])
torch.Size([512, 512, 3, 3])
torch.Size([512])
torch.Size([512])
torch.Size([512, 512, 3, 3])
torch.Size([512])
torch.Size([512])
torch.Size([1000, 512])
torch.Size([1000])

아래 공식 홈페이지의 discuss에도 참고하실만한 코드가 있어 링크를 남겨둡니다. :slight_smile:

1개의 좋아요

같이 고민해주셔서 감사합니다.
답변 해주신내용 차근차근 참고해가면서 저도 고민을 조금더 해보겠습니다.!

1개의 좋아요

:slight_smile:
더 궁금하신거 있으시면 알려주세요~

1개의 좋아요

33


22
제가 이렇게 코드를 한번 구성해봤는데 self.bean(x) 에 들어가고싶은데 들어가지지 않고 바로 나오게 되네요ㅠ.ㅠself.bean 에서 Dropout 의 self 라서 안되는건 알겠는데 어디가가 self.bean을 사용해야 들어갈수있을까요?! 그리고 마지막에 return self.x 를 카운트해서 처음에는 x 에 Drop_out1 을 두번째카운트 일때는 Drop_out2를 x 에 저장후 계산하고싶은데 카운트 를 구성하는 코드 좀 도움 부탁드려도 될까요? 파이썬으로요!!

안녕하세요, 알람 확인이 늦어서 남겨주신 덧글 확인이 늦었습니다.

물어보신 내용들은 PyTorch보다는 Python에 대한 질문인 것 같은데요,

(두 번째 이미지에서) 별도로 만드신 bean class를 Dropout class에서 사용하고 싶으시다면 Dropout class를 초기화하는 __init__() 내에서 bean class의 instance를 먼저 만드신 뒤(예. self.bean = bean(...))에 bean instance의 멤버 함수들을 불러서 사용할 수는 있을 것 같습니다.

제가 코드를 대신 짜드리는 것은 무리일 것 같구요,
Python class에 대한 설명이 있는 공식 문서([1], [2]) 또는 공개된 도서([1], [2]) 등을 먼저 참고하셔서 Python class의 선언과 사용에 대해서 먼저 익히시고 Dropout class를 확장하시는 것이 좋을 것 같습니다. ^^