-
데이터 분석_파이토치 : Pytorch1DATA_STUDY 2024. 1. 19. 20:15
해당 자료는 이수안 컴퓨터 연구소의 유튜브에 올라와있는 자료입니다. !
유튜브에 이수안 컴퓨터 연구소 검색하고 보세요!. 자료 좋아요!!
문제가 있을 시에 알려주시면, 빛 삭제 혹은 수정하겠습니다.
https://www.youtube.com/watch?v=k60oT_8lyFw&list=PL7ZVZgsnLwEEIC4-KQIchiPda_EjxX61r&index=
1.파이토치(PyTorch)
- 페이스북이 초기 루아(Lua) 언어로 개발된 토치(Torch)를 파이썬 버전으로 개발하여 2017년도에 공개
- 초기에 (프레임워크) 토치(Torch)는 넘파이(NumPy) 라이브러리처럼 과학 연산을 위한 라이브러리로 공개
- 이후 (텐서병렬처리를위한) GPU를 이용한 텐서 조작 및 동적 신경망 구축이 가능하도록 딥러닝 프레임워크로 발전시킴
- 파이썬답게 만들어졌고, 유연하면서도 가속화된 계산 속도를 제공
1.파이토치의 구성요소
- torch: 메인 네임스페이스, 텐서 등의 다양한 수학 함수가 포함
- torch.autograd: 자동 미분 기능을 제공하는 라이브러리
- torch.nn: 신경망 구축을 위한 데이터 구조나 레이어 등의 라이브러리
- torch.multiprocessing: 병럴처리 기능을 제공하는 라이브러리
- torch.optim: SGD(Stochastic Gradient Descent)를 중심으로 한 파라미터 최적화 알고리즘 제공
- torch.utils: 데이터 조작 등 유틸리티 기능 제공
- torch.onnx: ONNX(Open Neural Network Exchange), 서로 다른 프레임워크 간의 모델을 공유할 때 사용
2.텐서(Tensors)
- 다차원에 대한 데이터 표현 방법
- 데이터 표현을 위한 기본 구조로 텐서(tensor)를 사용
- 텐서는 데이터를 담기위한 컨테이너(container)로서 일반적으로 수치형 데이터를 저장
- 넘파이(NumPy)의 ndarray와 유사
- GPU를 사용한 연산 가속 가능
# Tensor는 다차원 데이터 구조를 가지고 있다 import torch #쿠다 버전 확인 torch.__version__ # 버전 2.1.0 쿠다 121
3.텐서 초기화와 데이터 타입
## 초기화 되지 않은 텐서 x = torch.empty(4,2) #4행 2열짜리 torch를 만들어 #tensor([[2.1707e-18, 7.0952e+22], # [1.7748e+28, 1.8176e+31], # [7.2708e+31, 5.0778e+31], # [3.2608e-12, 1.7728e+28]]) ## 무작위로 초기화된 텐서 x = torch.rand(4,2) #초기화가 랜덤을 기준으로 print(x) #tensor([[0.5978, 0.0850], # [0.9591, 0.3563], # [0.2373, 0.3342], # [0.0166, 0.6169]]) ## 데이터 타입(dtype)이 long이고, 0으로 채워진 텐서 x = torch.zeros(4,2, dtype=torch.long) #long = 정수 ## 사용자가 입력한 값으로 텐서 초기화 x = torch.tensor([3, 2.3]) #기본적으로 실수형 타입으로 들어감 ## 2 x 4 크기, double 타입, 1로 채워진 텐서 x = x.new_ones(2,4, dtype=torch.double) # 데이터 타입의 최소단위인 텐서를 자유자제로 다룰수 있어야합니다. ## x와 같은 크기, float 타입, 무작위로 채워진 텐서 x = torch.randn_like(x, dtype=torch.float ) # _like 뜻 기존의 tensor와 같은 것으로 만들어줘 ## 텐서의 크기 계산 print(x.size())
4. 데이터 타입(Data Type)
# float.tensor ft = torch.FloatTensor([1,2,3]) print(ft) print(ft.dtype) #기본이 32bit float 다 #타입 캐스팅 => 데이터타입을 바꿔주는 역할 print(ft.short()) # 기존 tensor를 short으로 타입 캐스팅을 합니다 print (ft.int()) # short 은 int16짜리/ int는 32bit, long 64bit의 정수임 print(ft.long()) it = torch.IntTensor([1,2,3]) print(it) print(it.dtype) print(it.float()) # 실수 기본형 32bit print(it.double()) # 실수 64 bit print(it.half()) # 실수 16 bit
5. CUDA Tensors
- .to 메소드를 사용하여 텐서를 어떠한 장치(cpu, gpu)로도 옮길 수 있음
- 쿠다 : 엔비디아의 대표 GPU 라이브러리
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu' ) #조건을 걸어서 gpu가 안되면 자동으로 cpu로 넘어가게 # torch.device('cuda') 또는 ('cpu')로 동작함 print(device) y = torch.ones_like(x, device=device) print(y) x = x.to(device) print(x) z = x + y print(z) print(z.to('cpu', torch.double)) # 계산된 결과를 cpu로 double타입으로 옮겼음
6.다차원 텐서 표현
0D Tensor(Scalar)
- 하나의 숫자를 담고 있는 텐서(tensor)
- 축과 형상이 없음
t0 = torch.tensor(0) print( t0.ndim ) #차원 없음 print(t0.shape) #형태 없음 print(t0) # 값은 그냥 0
1D Tensor(Vector)
- 값들을 저장한 리스트와 유사한 텐서
- 하나의 축이 존재
t1 = torch.tensor([1,2,3]) print( t1.ndim ) # 1차원 print(t1.shape) # 형태 한줄 print(t1) # 값은 1 2 3
2D Tensor(Matrix)
- 행렬과 같은 모양으로 두개의 축이 존재
- 일반적인 수치, 통계 데이터셋이 해당
- 주로 샘플(samples)과 특성(features)을 가진 구조로 사용
t2 = torch.tensor([[1,2,3], [4,5,6], [7,8,9]]) print( t2.ndim ) # 2차원 print(t2.shape) # 형태 행렬/수치모양 print(t2) # 값은 1 2 3 , 4 5 6 , 78 9 3*3행
3D Tensor
- 큐브(cube)와 같은 모양으로 세개의 축이 존재
- 데이터가 연속된 시퀀스 데이터나 시간 축이 포함된 시계열 데이터에 해당
- 주식 가격 데이터셋, 시간에 따른 질병 발병 데이터 등이 존재
- 주로 샘플(samples), 타임스텝(timesteps), 특성(features)을 가진 구조로 사용
t3 = torch.tensor([ [[1,2,3], # t2가 여러개인 형태로 들어감 [4,5,6], [7,8,9]], [[1,2,3], [4,5,6], [7,8,9]], [[1,2,3], [4,5,6], [7,8,9]] ] ) print( t3.ndim ) # 3차원 큐브모양 print(t3.shape) # 형태 행렬/수치모양 print(t3)
4D Tensor
- 4개의 축
- 컬러 이미지 데이터가 대표적인 사례
- 흑백 이미지 데이터는 3D Tensor로 가능
- 흑백은 채널 정보가 빠짐
- 주로 샘플(samples), 높이(height), 너비(width), 컬러 채널(channel)을 가진 구조로 사용
5D Tensor
- 5개의 축
- 비디오 데이터가 대표적인 사례
- 주로 샘플(samples), 프레임(frames), 높이(height), 너비(width), 컬러 채널(channel)을 가진 구조로 사용
- 이미지가 연달아 시퀀스로 있는 것이 비디오
- 초당 몇개의 이미지가 있냐 ; 프레임
7. 텐서의 연산(Operations)
- 텐서에 대한 수학 연산, 삼각함수, 비트 연산, 비교 연산, 집계 등 제공
import math a = torch.rand(1,2) * 2 - 1 print(a) print(torch.abs(a)) print(torch.ceil(a)) print(torch.floor(a)) print(torch.clamp(a, -0.5, 0.5)) #범위 지정해서 값을 찝음? 최솟값이 -0.5 최대값이 0.5까지
print(a) print(torch.min(a)) # 최소 print(torch.max(a)) #최대 print(torch.mean(a)) # 평균 print(torch.std(a)) #표준편차 print(torch.prod(a)) #곱 print(torch.unique(torch.tensor([1,2,3, 1,2,2]))) # 중복제외 유닉크
max와 min은 dim 인자를 줄 경우 argmax와 argmin도 함께 리턴
- argmax: 최대값을 가진 인덱스
- argmin: 최소값을 가진 인덱스
x = torch.rand(2,2) print(x) print(x.max(dim=0)) # 위아래로 묶어서 누가 더 큰값인지 비교했음 values=tensor([0.8898, 0.8613]), print(x.max(dim=1)) # 좌우로 묶어서 비교했음 # 인덱스로 하면 [0 , 1], [0, 1] values=tensor([0.8613, 0.8898]), print(x.min(dim=0)) print(x.min(dim=1))
torch.add: 덧셈
print(x + y) print( torch.add(x,y))
결과 텐서를 인자로 제공
result = torch.empty(2, 4 ) torch.add(x,y, out=result) print(result)
in-place 방식
- in-place방식으로 텐서의 값을 변경하는 연산 뒤에는 _''가 붙음
- x.copy_(y), x.t_()
print(x ) print(y) y.add_(x) # x에 더한 값을 y에 저장해줘 라는 뜻 print(y)
torch.sub: 뺄셈
print(x) print(y) print( x- y) print(torch.sub(x,y)) print(x.sub(y))
torch.mul: 곱셉
print(x) print(y) print( x * y) print(torch.mul(x,y)) print(x.mul(y))
torch.div: 나눗셈
print(x) print(y) print( x / y) print(torch.div(x,y)) print(x.div(y))
torch.mm: 내적(dot product)
print(x) print(y) print(torch.matmul(x,y)) #메트릭스 멀티뮬리? z = torch.mm(x,y) #줄여서 mm 이라고 #행렬곱 print(z) print(torch.svd(z))# singular value decomposition #분해
8. 텐서의 조작(Manipulations)
인덱싱(Indexing): NumPy처럼 인덱싱 형태로 사용가능
x = torch.Tensor([[1,2], [3,4]]) print(x) #인덱스 print(x[0,0]) print(x[0,1]) print(x[1,0]) print(x[1,1]) #슬라이싱 print(x[:, 0]) # 행은 다 선택하면서 0번째 컬럼을 선택 print(x[:, 1]) print(x[0, :]) # 행은 0번째 선택, 컬럼은 다 선택 print(x[1, :])
view: 텐서의 크기(size)나 모양(shape)을 변경
- 기본적으로 변경 전과 후에 텐서 안의 원소 개수가 유지되어야 함
- -1로 설정되면 계산을 통해 해당 크기값을 유추
x = torch.randn(4,5) print(x) y = x.view(20) # 4by5 구조가 없어지고 flat한 형태로 바뀜 print(y) z = x.view(5, -1) # -1은 알아서 하라는 뜻 print(z) # 결과는 5,4
item: 텐서에 값이 단 하나라도 존재하면 숫자값을 얻을 수 있음
- tensor 안의 값을 가져오는 것
x = torch.randn(1) print(x) print(x.item()) print(x.dtype)
주의!! 스칼라값 하나만 존재해야 item() 사용 가능
squeeze: 차원을 축소(제거)
tensor = torch.rand(1,3,3) print(tensor) print(tensor.shape) t = tensor.squeeze() print(t.shape)
unsqueeze: 차원을 증가(생성)
t = torch.rand(3,3) print(t) print(t.shape) tensor = t.unsqueeze(dim=0) #0은 첫번째 차원을 기준으로 늘려줘 print(tensor) print(tensor.shape) tensor = t.unsqueeze(dim=2) #2은 세번째 차원을 기준으로 늘려줘 print(tensor) print(tensor.shape)
stack: 텐서간 결합
- stack = 쌓는다
x = torch.FloatTensor([1,4]) print(x) y = torch.FloatTensor([2,5]) print(y) z = torch.FloatTensor([3,6]) print(z) print(torch.stack([x,y,z]) )
cat: 텐서를 결합하는 메소드(concatenate)
- 넘파이의 stack과 유사하지만, 쌓을 dim이 존재해야함
- 해당 차원을 늘려준 후 결합
a = torch.randn( 1,3, 3) print(a) b = torch.randn(1,3,3) print(b) c = torch.cat((a,b), dim=0) print(c) print(c.size()) c = torch.cat((a,b), dim=1) print(c) print(c.size()) c = torch.cat((a,b), dim=2) print(c) print(c.size())
chunk: 텐서를 여러 개로 나눌 때 사용
- (몇 개로 나눌 것인가?)
tensor = torch.rand(3,6) print(tensor) t1, t2, t3 = torch.chunk(tensor, 3, dim=1)
split: chunk와 동일한 기능이지만 조금 다름
- (텐서의 크기는 몇인가?)라고 물어보는 것
tensor = torch.rand(3,6) t1, t2 = torch.split( tensor, 3, dim=1) # tensor 3크기/ 기준차원은 print(tensor ) print(t1) print(t2)
torch ↔ numpy
- Torch Tensor(텐서)를 NumPy array(배열)로 변환 가능
- numpy()
- from_numpy()
- Tensor가 CPU상에 있다면 NumPy 배열은 메모리 공간을 공유하므로 하나가 변하면, 다른 하나도 변함
a = torch.ones(7) print(a) a.add_(1) # 언더바는 inplace 반영값을 넣기 print(a) print(b) # NumPy 배열은 메모리 공간을 공유하므로 하나가 변하면, 다른 하나도 변함 import numpy as np a = np.ones(7) b = torch.from_numpy(a) # torch형태로 바뀐 numpy np.add(a, 1, out=a) #out 출력은 a로 해줘 ( add_ 와 같은 기능 ) print(a) print(b) # torch 와 numpy 가 메모리를 공유한다!!
9.Autograd(자동미분)
- torch.autograd 패키지는 Tensor의 모든 연산에 대해 자동 미분 제공
- 이는 코드를 어떻게 작성하여 실행하느냐에 따라 역전파가 정의된다는 뜻
- backprop를 위해 미분값을 자동으로 계산
-
- 역전파 : BackPropagation이 되어야지 우리가 미분값을 backprop(미세조정)을 위해 신경망에서 ?? 에?
- requires_grad 속성을 True로 설정하면, 해당 텐서에서 이루어지는 모든 연산들을 추적하기 시작
- 기록을 추적하는 것을 중단하게 하려면, .detach()를 호출하여 연산기록으로부터 분리
a = torch.rand(3,3) a = a * 3 print(a) print(a.requires_grad)
requires_grad_(...)는 기존 텐서의 requires_grad 값을 바꿔치기(in-place)하여 변경
grad_fn: 미분값을 계산한 함수에 대한 정보 저장 (어떤 함수에 대해서 backprop 했는지)
a.requires_grad_(True) #언더바 inplace 바꾼값을 바로 적용해서 연산 print(a.requires_grad ) b = (a * a).sum() # 연산을 한것을 기록으로 남김 : =<SumBackward0>) print(b) print(b.grad_fn)# gradient function
10.기울기(Gradient)
import torch import math x = torch.ones(3,3, requires_grad=True) print(x) y = x + 5 print(y) z = y * y # grad_fn=<MulBackward0> out = z.mean() # grad_fn=<MeanBackward0> print(z, out)
계산이 완료된 후, .backward()를 호출하면 자동으로 역전파 계산이 가능하고, .grad 속성에 누적됨
print(out) out.backward() #tensor(36., grad_fn=<MeanBackward0>)
grad: data가 거쳐온 layer에 대한 미분값 저장
print(x) print(x.grad) # 실제 미분값을 알려줘 x = torch.randn(3, requires_grad=True) y = x * 2 while y.data.norm() < 1000: # normalistion y = y * 2 print(y) # tensor([ 839.1677, -426.3043, 1344.2209], grad_fn=<MulBackward0>) v = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float) y.backward(v) print(x.grad) #tensor([2.0480e+02, 2.0480e+03, 2.0480e-01])
with torch.no_grad()를 사용하여 기울기의 업데이트를 하지 않음
- 기록을 추적하는 것을 방지하기 위해 코드 블럭을 with torch.no_grad()로 감싸면 기울기 계산은 필요없지만,
- requires_grad=True로 설정되어 학습 가능한 매개변수를 갖는 모델을 평가(evaluate)할 때 유용
- 모델을 평가시에는 모델을 새로 고치거나/업데이트 하지 않기 때문에 기울기 계산이 딱히 필요없음
print(x.requires_grad) print(( x ** 2).requires_grad ) with torch.no_grad() : print((x ** 2).requires_grad)
detach(): 내용물(content)은 같지만 require_grad가 다른 새로운 Tensor를 가져올 때
print(x.requires_grad) # 기울기 True y = x.detach() # 기울기빼기? print(y.requires_grad) # 기울기 False print(x.eq(y).all()) # x와 y가 equal 인지 확인
자동 미분 흐름 예제
- 계산 흐름 a→b→c→out
∂out / ∂a = ?
- -> (미분값을 의미)
- backward()를 통해 a←b←c←out을 계산하면 ∂out∂a값이 a.grad에 채워짐
a = torch.ones(2,2) a = torch.ones(2,2, requires_grad=True) # tensor([[1., 1.], # [1., 1.]], requires_grad=True) print(a.data) print(a.grad) print(a.grad_fn) # 현재 tensor 대한 연산이 들어간 것이 없음 => gradient 값이 없음 = None
b = a + 2
b = a + 2 print(b)
c = b^2
c = b ** 2 out = c.sum() print(out) #tensor(36., grad_fn=<SumBackward0>) out.backward() #역전파를 해보자?? #tensor(36., grad_fn=<SumBackward0>)
a의 grad_fn이 None인 이유는 직접적으로 계산한 부분이 없었기 때문
print(a.data) print(a.grad) print(a.grad_fn) #None #a의 값을 활용했을뿐 직접적인 계산은 없었음 print(b.data) #실제값 #tensor([[3., 3.], [3., 3.]]) print(b.grad) #None print(b.grad_fn) #<AddBackward0 object at 0x7f9212ec0f10> print(c.data) #실제값 #tensor([[9., 9.], [9., 9.]]) print(c.grad) #None print(c.grad_fn) #<PowBackward0 object at 0x7f9212ec0b50> print(out.data) #최종결과 #tensor(36.) print(out.grad) #None print(out.grad_fn) #<SumBackward0 object at 0x7f9212ec0910>
파이토치 활용 딥러닝
데이터 준비 -mnist
파이토치에서는 데이터 준비를 위해 torch.utils.data의 Dataset과 DataLoader 사용 가능
- Dataset에는 다양한 데이터셋이 존재 (MNIST, FashionMNIST, CIFAR10, ...)
- Vision Dataset: https://pytorch.org/vision/stable/datasets.html
- Text Dataset: https://pytorch.org/text/stable/datasets.html
- Audio Dataset: https://pytorch.org/audio/stable/datasets.html
- DataLoader와 Dataset을 통해 batch_size, train 여부, transform 등을 인자로 넣어 데이터를 어떻게 load할 것인지 정해줄 수 있음
라이브러리 import
import torch, math, numpy as np, pandas as pd from torch.utils.data import Dataset, DataLoader
토치비전(torchvision)은 파이토치에서 제공하는 데이터셋들이 모여있는 패키지
- transforms: 전처리할 때 사용하는 메소드 (https://pytorch.org/docs/stable/torchvision/transforms.html)
- transforms에서 제공하는 클래스 이외는 일반적으로 클래스를 따로 만들어 전처리 단계를 진행
import torchvision.transforms as transforms from torchvision import datasets
- DataLoader의 인자로 들어갈 transform을 미리 정의할 수 있고, Compose를 통해 리스트 안에 순서대로 전처리 진행
- ToTensor()를 하는 이유는 torchvision이 PIL Image 형태로만 입력을 받기 때문에 데이터 처리를 위해서 Tensor형으로 변환 필요
# Tensor 형태로 미리 전환 mnist_transform = transforms.Compose([transforms.ToTensor(), #Tensor 형태로 바꿔줌 transforms.Normalize(mean=(0.5, ), std=(1.0, ))])
#모델의 train set, test set trainset = datasets.MNIST(root='/content/', train=True, download=True, transform=mnist_transform ) testset = datasets.MNIST(root='/content/', train=False, download=True, transform=mnist_transform )
- DataLoader는 데이터 전체를 보관했다가 실제 모델 학습을 할 때 batch_size 크기만큼 데이터를 가져옴
train_loader = DataLoader(trainset, batch_size=8, shuffle=True, num_workers=2) test_loader = DataLoader(testset, batch_size=8, shuffle=True, num_workers=2)
# python 3.6 version # dataiter = iter(train_loader) # images, labels = dataiter.next() # images.shape, labels.shape # python 3.7 version부터는 dataiter = iter(train_loader) images, labels = next(dataiter) images.shape, labels.shape # (torch.Size([8, 1, 28, 28]), torch.Size([8])) # 28*28짜리 이미지, 1이면 흑백, 8개 => 8개의 흑백 사진이라는 # 왜 8개인가 batch_size가 8이라서
torch_image = torch.squeeze(images[0]) # 차원 축소, 첫번째 이미지 기준으로 torch_image.shape
## 이미지 시각화 하기
import matplotlib.pyplot as plt figure = plt.figure(figsize=(12,6)) cols, rows = 4,2 for i in range(1, cols * rows +1): # 1-9까지 반복 sample_idx = torch.randint(len(trainset), size=(1, ) ).item() #len기준으로 size를 가오는데, 랜덤값의 item =실제값을 인덱스로 가져오기 img, label = trainset[sample_idx] figure.add_subplot(rows, cols, i) plt.title(label) #실제 숫자가 label 몇인지 뜸 plt.axis('off') plt.imshow(img.squeeze(), cmap='gray' ) plt.show()
신경망 구성
- 레이어(layer): 신경망의 핵심 데이터 구조로 하나 이상의 텐서를 입력받아 하나 이상의 텐서를 출력
- 모듈(module): 한 개 이상의 계층이 모여서 구성
- 모델(model): 한 개 이상의 모듈이 모여서 구성
torch.nn 패키지 = neural network
주로 가중치(weights), 편향(bias)값들이 내부에서 자동으로 생성되는 레이어들을 사용할 때 사용 (weight값들을 직접 선언 안함) https://pytorch.org/docs/stable/nn.html
import torch.nn as nn
nn.Linear 계층 예제
input = torch.randn(128, 20) print(input) m = nn.Linear(20, 30) print(m) output = m(input) print(output) print(output.size())
nn.Conv2d 계층 예시
input = torch.randn(20,16,50,100) print(input.size()) m = nn.Conv2d(16, 33, 3, stride=2 ) m = nn.Conv2d(16, 33, (3,5), stride=(2,1), padding=(4,2) ) m = nn.Conv2d(16, 33, kernel_size=(3,5), stride=(2,1), padding=(4,2), dilation=(3,1) ) print(m) #Conv2d(16, 33, kernel_size=(3, 5), stride=(2, 1), padding=(4, 2), dilation=(3, 1)) output = m(input) print(output.size())
컨볼루션 레이어(Convolution Layers)
nn.Conv2d 예제
- in_channels: channel의 갯수
- out_channels: 출력 채널의 갯수
- kernel_size: 커널(필터) 사이즈
nn.Conv2d(in_channels=1, out_channels=20, kernel_size=5, stride=1 ) layer = nn.Conv2d(1,20,5,1).to(torch.device('cpu')) # in, out, 커널, 보폭 layer #Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1))
weight 확인
weight = layer.weight weight.shape
weight는 detach()를 통해 꺼내줘야 numpy()변환이 가능
weight = weight.detach() weight = weight.numpy() weight.shape
시각화하기
import matplotlib.pyplot as plt plt.imshow(weight[0,0, :, :, ],'jet') #'gray' plt.colorbar() plt.show()
print(images.shape) #torch.Size([8, 1, 28, 28]) print(images[0].size()) #torch.Size([1, 28, 28]) input_image = torch.squeeze(images[0]) print(input_image.size())#torch.Size([28, 28])
input_data = torch.unsqueeze(images[0], dim=0) print(input_data.size()) #torch.Size([1, 1, 28, 28]) 흑백사진 1장 output_data = layer(input_data) #레이어를 통과시키고 output = output_data.data # 통과한 것의 데이터만 뽑아서 output_arr = output.numpy() #array, 즉 numpy로 바꾼후에 output_arr.shape #즉 레이어 통과후의 모양은 => (1, 20, 24, 24)
## 레이어 통과 후의 시각화
# 레이어 통과후의 시각화 plt.figure(figsize=(30,15)) plt.subplot(131) plt.title('input') plt.imshow(input_image, 'gray') plt.subplot(132) plt.title('Weight') plt.imshow(weight[0,0, :,:], 'jet') plt.subplot(133) plt.title('Output') plt.imshow(output_arr[0, 0, :, :], 'gray') plt.show()
풀링 레이어(Pooling layers)
- F.max_pool2d
- stride
- kernel_size
- torch.nn.MaxPool2d 도 많이 사용
import torch.nn.functional as F pool = F.max_pool2d(output, 2, 2) pool.shape
- MaxPool Layer는 weight가 없기 때문에 바로 numpy()변환 가능
pool_arr = pool.numpy() pool_arr.shape
# 풀링 이후 시각화 : 풀링 레이어를 통과하면 , 해상도가 떨어진다
# 풀링 이후 시각화 : 풀링 레이어를 통과하면 , 해상도가 절반?으로 떨어진다 # 2 by 2 짜리중에 최대값을 가지는 것으로 결과가 나옴 plt.figure(figsize=(10,15)) plt.subplot(121) plt.title('Input') plt.imshow(input_image, 'gray') plt.subplot(122) plt.title('Output') plt.imshow(pool_arr[0,0, :,:], 'gray') plt.show()
선형 레이어(Linear layers)
1d만 가능하므로 .view()를 통해 1d로 펼쳐줘야함
- 쭉 펼치는 flatten과정이 필요
flatten = input_image.view(1,28*28) flatten.shape lin = nn.Linear(784, 10)(flatten)#in_features=784, out_features=10 # 784 -> 10짜리로 줄이는 것 lin.shape #tensor 확인 lin
시각
plt.imshow(lin.detach().numpy(), cmap='jet') plt.colorbar() plt.show()
비선형 활성화 (Non-linear Activations)
F.softmax와 같은 활성화 함수 등
with torch.no_grad(): flatten = input_image.view(1, 28 * 28) lin = nn.Linear(784,10)(flatten) # input이 리니어를 거쳐서 softmax까지 softmax = F.softmax(lin, dim=1) softmax np.sum(softmax.numpy()) # 결과는 모든 10개의 합이 100% / 다중 분류
F.relu
- ReLU 활성화함수를 적용하는 레이어
- nn.ReLU로도 사용 가능
inputs = torch.randn(4,3 , 28, 28).to(device) inputs.shape layer = nn.Conv2d(3, 20, 5,1).to(device) output = F.relu(layer(inputs)) output.shape
'DATA_STUDY' 카테고리의 다른 글
파이썬_워드클라우드 2 (0) 2024.01.22 파이썬_파일읽고쓰기_워드클라우드 (1) 2024.01.22 데이터 분석_파이토치 : Pytorch3 (0) 2024.01.22 데이터 분석_파이토치 : Pytorch2 (0) 2024.01.22 데이터 분석_라이브러리_함수_모음_ (1) 2023.11.01