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



제가 이렇게 코드를 한번 구성해봤는데 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를 확장하시는 것이 좋을 것 같습니다. ^^