# TODO 2-3) empty_t의 요소들에 1로 값을 채워주세요. | 변수명 ones_t
# TODO 2-3
ones_t=torch.ones_like(empty_t)
print('ones_t: {}'.format(ones_t))
# TODO 2-4) ones_t Tensor가 메모리 상에서 유지하는 위치의 고유한 식별자를 확인하여 출력해 주세요.
# TODO 2-4
print(f'id(ones_t): {id(ones_t)}')
print('\n')
# TODO 2-5) empty_t 의 요소들에 0으로 값을 채워주세요. 단, in-place 방식을 이용해 주세요. | 변수명 zeros_t
# TODO 2-5
zeros_t=empty_t.fill_(0)
print('zeros_t: {}'.format(zeros_t))
이 문제에서 나는 강의에서 torch.zeros_like()를 쓰면 메모리 주소가 변하지 않는다고 해서 이것을 썼었다. 근데 메모리 주소가 다른것이다!!
알고보니 torch.zeros_like는 참조하고자 하는 텐서의 shape, dtype, device, requires_grad 등 텐서가 선언되면 정해지는 arguments들을 그대로 이식하여 새로운 텐서를 만드는 것입니다.
강의 중 의도하신 바는 서로 다른 device 메모리에 할당이 되면 연산이 불가능하기 때문에 이를 강조하셨는데, 메모리 보다는 device 메모리라고 전달되는 것이 조금 더 명확한 것으로 보는 것이다.
그러니깐 결론은 like함수는 id가 바뀌지만 fill(in-place 방식)은 메모리 id를 바꾸지 않는 다는 것을 알고 있어야된다.
# TODO 7-3) noise_added_img의 모든 값이 0과 255 사이의 값을 가지도록 제한해 주세요. hint: clip
# TODO 7-3
noise_added_img=torch.clamp(noise_added_img,min=0,max=255)
이 문제에서는 강의에서 배우지 못한 함수가 있어서 기록해본다. torch.clamp을 하면 내가 최솟값,최대값을 정해 텐서의 값을 최솟값 이하로 떨어지지 않게 하고, 최댓값 이상으로 넘어가지 않게 합니다.
# TODO 7-1) img_t와 모양(shape)이 같은 표준정규분포 난수 Tensor를 생성해 주세요. | 변수명 random_noise
# TODO 7-1
random_noise=torch.randn_like(img_t.float())
여기서 짚고 넘어가야 할 것은 정수형 타입의 텐서를 표준정규분포로 바꿀때는 실수형 타입으로 바꾸어 주어야 들어갈 수 있다.
def show_blue_channel(img_tensor):
# TODO 6-13) img_t에서 blue 채널만 선택해 blue_only에 대입해 주세요. | 변수명: blue_only
# TODO 6-13
blue_only=img_t[:,:,2]
# TODO 6-14) blue_only의 마지막 차원을 확장하여 dim이 1이 되도록 만들어 주세요.
# 단, unsqueeze를 활용해 주세요.
# TODO 6-14
blue_only=blue_only.unsqueeze(-1)
# TODO 6-15) blue_only와 모양이 같으면서 0으로 채워진 Tensor를 만들어 주세요. | 변수명: zero_t
# TODO 6-15
zero_t=torch.zeros_like(blue_only)
# TODO 6-16) zero_t를 dim=0/dim=1축으로는 1번, dim=2축으로만 2번 *반복하여 Tensor의 크기를 확장해 주세요. | 변수명: zeros_t
# TODO 6-16
zeros_t=zero_t.repeat(1,1,2)
# TODO 6-17) zeros_t와 blue_only를 마지막 차원을 기준으로 연결해 주세요. | 변수명: blue_img_t
# 단, 순서에 유의해 주세요. blue channel이 마지막 채널에 배치되도록 연결해 주세요.
# TODO 6-17
blue_img_t=torch.cat((zeros_t,blue_only),dim=2)
# TODO 6-18) blue_img_t Tensor를 numpy array로 변환해 주세요. | 변수명: blue_img
# TODO 6-18
blue_img=blue_img_t.numpy()
위에 문제를 풀 때 내가 느낀건데 차원이 증가할때 마다 새롭게 증가한 것을 첫번째 차원으로 두면서 왜 인덲싱은 행열부터 하는건지 궁금했다.
PyTorch와 많은 다른 딥러닝 프레임워크에서 3차원 텐서를 다룰 때, 이미지의 차원 순서는 일반적으로 (C, H, W)로 표현됩니다. 여기서:
C는 채널 수 (깊이, 예: RGB 이미지의 경우 3)
H는 높이 (Height)
W는 너비 (Width)
하지만, 인덱싱할 때는 보통 img_t[h, w, c]와 같이 (H, W, C) 순서로 인덱싱을 하는 경우가 더 일반적입니다. 그 이유는 이미지 처리 라이브러리(예: OpenCV, PIL)에서 이미지를 다룰 때, 채널이 마지막 차원에 위치하는 (H, W, C) 형식이 자주 사용되기 때문입니다.
인덱싱 순서
a[h, w, c]와 같이 H와 W를 먼저 인덱싱하고 C를 마지막에 인덱싱하는 이유는, 이미지 데이터를 다루는 데 있어서 직관적인 방식으로, 행과 열을 먼저 지정한 후에 특정 채널을 선택하는 방식입니다.
따라서, 딥러닝 프레임워크에서 이미지를 다룰 때는 (C, H, W) 순서를 기억하고, 인덱싱할 때는 행과 열을 먼저 지정하는 것이 일반적입니다. 이와 같은 방식은 데이터의 처리와 변환을 최적화하기 위해 만들어진 규칙입니다.
nn.Model로 딥러닝이나 머신러닝 돌리기 위해 cuda까지 써서 할 때 꼭 그때 들어가는 tensor의 형태는 float32의 형태를 갖추어야 한다. 모델에 넣기 전에 그 형태를 갖고 있는지 살펴보자!!