일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- SGD
- codingtest
- 코테
- pytorch
- 알고리즘
- wordcloud
- 프로그래머스
- 백준
- 데이터 엔지니어링
- 머신러닝
- 웹스크래핑
- 분산 시스템
- 웹크롤링
- 시각화
- 코딩테스트
- Python
- TF-IDF
- 데이터
- coursera
- Tensor
- selenium
- 딥러닝
- Overfitting
- 부스트캠프
- 추천시스템
- 추천 시스템
- 파이썬
- 협업 필터링
- Cosine-similarity
- recommendation system
- Today
- Total
개발자식
[Pytorch] Pytorch Module, Parameter, Backward 본문
딥러닝은 수많은 레이어(블록) 반복의 연속이다!
torch.nn.Module
- 딥러닝을 구성하는 Layer의 base 클래스
- input, output, forward, backward 그리고 학습의 대상이 되는 parameter(tensor)도 정의된다.
torch.nn.Parameter
- Tensor 객체의 상속 객체
- nn.Module 내에 attribute가 될 때는 required_grad = True로 지정되어 학습 대상이 되는 Tensor이다.
- low-level이 아니라면 우리가 직접 지정할 일은 잘 없다. (대부분 정해져 있음)
만약에 Module 내에 attribute를 Parameter 말고 Tensor로 선언한다면?
-. parameters()로 파라미터를 확인하면 나오지 않는다.
- 왜냐하면 파라미터로 출력되는 경우는 미분 대상이기 때문이다.
- Parameter로 선언하면 requires_grad=True로 .parameters()로 미분 대상인 값을 확인할 수 있고 이는 역전파의 대상이다.
Parameter로 선언하고 .parameters()로 출력한 결과 코드
class MyLiner(nn.Module):
def __init__(self, in_features, out_features, bias=True):
super().__init__()
self.in_features = in_features
self.out_features = out_features
self.weights = nn.Parameter(
torch.randn(in_features, out_features))
self.bias = nn.Parameter(torch.randn(out_features))
def forward(self, x : Tensor):
return x @ self.weights + self.bias
layer = MyLiner(7, 12)
for value in layer.parameters():
print(value)
Output:
Parameter containing:
tensor([[ 0.2482, 0.2727, 0.6945, 0.1879, 0.4732, 2.2693, -1.6261, -0.7074,
-0.8284, -0.4581, 0.5989, 0.6506],
[-0.3134, 0.5870, -0.1706, -0.7035, -0.0758, -0.7304, 0.3122, 0.5325,
0.1195, -2.4368, -0.1422, 0.0280],
[-0.0051, -0.6986, -0.4618, -0.8123, -2.0547, -2.7787, -0.9899, 0.4777,
0.6875, -0.3546, 1.2172, 0.9975],
[ 1.1294, -1.9423, 0.7216, 0.2683, 1.7940, -1.0777, -0.5499, 0.0216,
1.0361, 0.9964, 0.8483, 0.6719],
[-0.4104, -1.1598, -1.1437, -0.4701, 0.7079, -0.2966, -1.2883, -1.2595,
0.8861, 0.2785, -1.4302, -1.0315],
[-0.9925, 0.3052, 0.9983, -2.7115, 0.0303, 2.2076, -1.3721, 0.5701,
0.1194, -0.7236, -0.6762, -1.3057],
[-1.2586, 0.6245, -0.8562, 0.2581, 1.6552, -0.5766, -0.8893, -1.1381,
-0.5901, -0.0711, 0.1816, 0.6767]], requires_grad=True)
Parameter containing:
tensor([-0.1515, 0.5543, -0.0473, 0.4265, -2.3464, -0.4731, -0.5312, 0.7327,
0.2549, 0.3927, 1.1567, -0.7312], requires_grad=True)
- requires_grad = True 가 같이 출력되는 것을 알 수 있고,
- 위와 같은 코드에서 Parameters가 아닌 Tensor를 쓰면 print문이 출력되지 않는다.
Backward 코드
for epoch in range(epochs):
...
...
...
# 1) optimizer 초기화
optimizer.zero_grad()
# 2) 모델에 입력값을 넣어 출력물 저장
outputs = model(inputs)
# 3) 출력값과 실제 labels값을 사용해 손실함수 값 계산
loss = criterion(outputs, labels)
# 4) 손실함수를 사용해 backward(역전파) 진행
loss.backward()
# 5) optimizer를 이용해 가중치 업데이트
optimizer.step()
- 위 5단계 스텝은 자주 쓰이는 코드이니 기억하자
Backward from the scratch
- from the scratch : 처음부터, 바닥부터
- 실제 backward는 Module 단계에서 직접 지정이 가능하지만 할 필요가 없다. autograd가 해주기 때문에
- 직접 하는 방법은 Module에서 backward와 optimizer 오버라이딩한다.
- 이는 사용자가 직접 미분 수식을 써야 하는 부담이 있다.
- 쓸 일은 없으나 순서는 이해할 필요가 있다.
위 내용을 토대로 Linear Regression을 구현해보자
- y = w * x + b에서 딥러닝을 통해 w, b를 찾아보자
- 정답 : y = 2 * x + 1
학습 데이터 생성
import numpy as np
x_values = [i for i in range(11)]
x_train = np.array(x_values, dtype=np.float32)
x_train = x_train.reshape(-1, 1)
y_values = [2*i + 1 for i in x_values]
y_train = np.array(y_values, dtype=np.float32)
y_train = y_train.reshape(-1, 1)
LinearRegression 클래스 생성
import torch
from torch.autograd import Variable
class LinearRegression(torch.nn.Module):
def __init__(self, inputSize, outputSize):
super(LinearRegression, self).__init__()
self.linear = torch.nn.Linear(inputSize, outputSize) #LinearRegression와 같은 기능 구현 해줌
def forward(self, x):
out = self.linear(x)
return out
모델 생성
inputDim = 1
outputDim = 1
learningRate = 0.01
epochs = 100
model = LinearRegression(inputDim, outputDim)
#gpu 사용이 가능한지 확인
if torch.cuda.is_available():
model.cuda()
metric & optimizer 설정
criterion = torch.nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=learningRate)
학습
for epoch in range(epochs):
#inputs, labels을 Variable 형태로 바꾼다.
if torch.cuda.is_available():
inputs = Variable(torch.from_numpy(x_train).cuda())
labels = Variable(torch.from_numpy(y_train).cuda())
else:
inputs = Variable(torch.from_numpy(x_train))
labels = Variable(torch.from_numpy(y_train))
#optimizer 초기화
optimizer.zero_grad()
#model에 inputs값을 넣은 결과 값 저장
outputs = model(inputs)
#손실함수 계산
loss = criterion(outputs, labels)
#print(loss)
#손실함수를 이용해 역전파 계산
loss.backward()
#가중치(파라미터) 업데이트
optimizer.step()
#print('epoch {}, loss {}'.format(epoch, loss.item()))
위에서 구한 파라미터를 적용한 예측값
with torch.no_grad():
if torch.cuda.is_available():
predicted = model(Variable(torch.from_numpy(x_train).cuda())).cpu().data.numpy()
else:
predicted = model(Variable(torch.from_numpy(x_train))).data.numpy()
print(predicted)
- no_grad() 함수는 gradient 계산 context를 비활성화해준다.
- 추론과 validation 할 때 사용
for p in model.parameters():
if p.requires_grad: #requires_grad 미분이 되는 값
print(p.name, p.data)
Output:
None tensor([[2.0672]])
None tensor([0.5331])
파이토치에서 어떻게 layer를 만들고 파라미터를 업데이트 하는지 알았다.
코드를 직접 구현하는 것은 아직 어렵지만 어떤 역할을 수행하는지는 감이 오는 것 같다..ㅎ
'AI > Pytorch' 카테고리의 다른 글
[Pytorch] Pytorch 모델 불러오기(save, checkpoints, transfer learning) (0) | 2022.10.02 |
---|---|
[Pytorch] Pytorch Datasets, Dataloaders (0) | 2022.10.02 |
[Pytorch] Pytorch Template (0) | 2022.10.02 |
[Pytorch] PyTorch Basics (0) | 2022.10.02 |
[Pytorch] Introduction to PyTorch (0) | 2022.10.01 |