파이토치 헬로 월드
에서 우리는 하나의 입력 뉴런, 하나의 숨겨진 뉴런 및 하나의 출력 뉴런으로 구성된 작은 네트워크에 대한 순방향 및 역방향 전파를 수동으로 계산하는 방법을 보았습니다.
우리는 네트워크를 통해 0.8의 입력을 실행한 다음 0.1의 학습률로 목표 값으로 1을 사용하여 역전파했습니다. 활성화 함수로 시그모이드를 사용하고 네트워크의 실제 출력과 원하는 출력을 비교하기 위해 2차 비용 함수를 사용했습니다.
아래 코드는 PyTorch를 사용하여 동일한 작업을 수행합니다.
import torch
import torch.nn as nn
import torch.optim as optim
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.hidden_layer = nn.Linear(1, 1)
self.hidden_layer.weight = torch.nn.Parameter(torch.tensor([[1.58]]))
self.hidden_layer.bias = torch.nn.Parameter(torch.tensor([-0.14]))
self.output_layer = nn.Linear(1, 1)
self.output_layer.weight = torch.nn.Parameter(torch.tensor([[2.45]]))
self.output_layer.bias = torch.nn.Parameter(torch.tensor([-0.11]))
def forward(self, x):
x = torch.sigmoid(self.hidden_layer(x))
x = torch.sigmoid(self.output_layer(x))
return x
net = Net()
print(f"network topology: {net}")
print(f"w_l1 = {round(net.hidden_layer.weight.item(), 4)}")
print(f"b_l1 = {round(net.hidden_layer.bias.item(), 4)}")
print(f"w_l2 = {round(net.output_layer.weight.item(), 4)}")
print(f"b_l2 = {round(net.output_layer.bias.item(), 4)}")
# run input data forward through network
input_data = torch.tensor([0.8])
output = net(input_data)
print(f"a_l2 = {round(output.item(), 4)}")
# backpropagate gradient
target = torch.tensor([1.])
criterion = nn.MSELoss()
loss = criterion(output, target)
net.zero_grad()
loss.backward()
# update weights and biases
optimizer = optim.SGD(net.parameters(), lr=0.1)
optimizer.step()
print(f"updated_w_l1 = {round(net.hidden_layer.weight.item(), 4)}")
print(f"updated_b_l1 = {round(net.hidden_layer.bias.item(), 4)}")
print(f"updated_w_l2 = {round(net.output_layer.weight.item(), 4)}")
print(f"updated_b_l2 = {round(net.output_layer.bias.item(), 4)}")
output = net(input_data)
print(f"updated_a_l2 = {round(output.item(), 4)}")
이 코드에 대한 몇 가지 참고 사항:
nn.Linear
는 완전히 연결되거나 조밀한 계층에 사용됩니다. 이 간단한 경우에는 각 레이어에 대해 단일 입력과 단일 출력이 있습니다. forward
메서드는 입력을 output = net(input_data)
로 네트워크에 전달할 때 호출됩니다. tensor
는 numpy의 array
와 유사합니다. criterion = nn.MSELoss()
는 2차 비용 함수를 설정합니다. PyTorch에서는 평균 제곱 오류 손실 함수라고 합니다. loss = criterion(output, target)
는 손실이라고도 하는 비용을 계산합니다. net.zero_grad()
를 사용하여 그래디언트를 0으로 재설정합니다(그렇지 않으면 역전파가 누적됨). 여기서 반드시 필요한 것은 아니지만 루프에서 역전파를 실행할 때 이를 염두에 두는 것이 좋습니다. loss.backward()
는 기울기, 즉 모든 가중치 및 편향에 대한 비용의 미분을 계산합니다. SGD
(확률적 경사하강법) 옵티마이저를 사용하여 네트워크의 가중치와 편향을 업데이트하기 위해 이 기울기를 사용합니다. 결과는 다음과 같습니다.
C:\Dev\python\pytorch>python backprop_pytorch.py
network topology: Net(
(hidden_layer): Linear(in_features=1, out_features=1, bias=True)
(output_layer): Linear(in_features=1, out_features=1, bias=True)
)
w_l1 = 1.58
b_l1 = -0.14
w_l2 = 2.45
b_l2 = -0.11
a_l2 = 0.8506
updated_w_l1 = 1.5814
updated_b_l1 = -0.1383
updated_w_l2 = 2.4529
updated_b_l2 = -0.1062
updated_a_l2 = 0.8515
역전파 단계 전후에 네트워크 토폴로지와 가중치, 편향, 출력을 출력합니다.
아래에서 이 계산을 일반 Python으로 복제해 보겠습니다. 이 계산은 신경망 입문서에서 본 것과 거의 동일합니다. 유일한 차이점은 PyTorch의
MSELoss
함수에는 2로 추가 나누기가 없기 때문에 아래 코드에서 PyTorch가 수행하는 것과 일치하도록 조정했습니다dc_da_l2 = 2 * (a_l2-1)
.import numpy as np
def sigmoid(z_value):
return 1.0/(1.0+np.exp(-z_value))
def z(w, a, b):
return w * a + b
def sigmoid_prime(z_value):
return sigmoid(z_value)*(1-sigmoid(z_value))
def dc_db(z_value, dc_da):
return sigmoid_prime(z_value) * dc_da
def dc_dw(a_prev, dc_db_value):
return a_prev * dc_db_value
def dc_da_prev(w, dc_db_value):
return w * dc_db_value
a_l0 = 0.8
w_l1 = 1.58
b_l1 = -0.14
print(f"w_l1 = {round(w_l1, 4)}")
print(f"b_l1 = {round(b_l1, 4)}")
z_l1 = z(w_l1, a_l0, b_l1)
a_l1 = sigmoid(z_l1)
w_l2 = 2.45
b_l2 = -0.11
print(f"w_l2 = {round(w_l2, 4)}")
print(f"b_l2 = {round(b_l2, 4)}")
z_l2 = z(w_l2, a_l1, b_l2)
a_l2 = sigmoid(z_l2)
print(f"a_l2 = {round(a_l2, 4)}")
dc_da_l2 = 2 * (a_l2-1)
dc_db_l2 = dc_db(z_l2, dc_da_l2)
dc_dw_l2 = dc_dw(a_l1, dc_db_l2)
dc_da_l1 = dc_da_prev(w_l2, dc_db_l2)
step_size = 0.1
updated_b_l2 = b_l2 - dc_db_l2 * step_size
updated_w_l2 = w_l2 - dc_dw_l2 * step_size
dc_db_l1 = dc_db(z_l1, dc_da_l1)
dc_dw_l1 = dc_dw(a_l0, dc_db_l1)
updated_b_l1 = b_l1 - dc_db_l1 * step_size
updated_w_l1 = w_l1 - dc_dw_l1 * step_size
print(f"updated_w_l1 = {round(updated_w_l1, 4)}")
print(f"updated_b_l1 = {round(updated_b_l1, 4)}")
print(f"updated_w_l2 = {round(updated_w_l2, 4)}")
print(f"updated_b_l2 = {round(updated_b_l2, 4)}")
updated_z_l1 = z(updated_w_l1, a_l0, updated_b_l1)
updated_a_l1 = sigmoid(updated_z_l1)
updated_z_l2 = z(updated_w_l2, updated_a_l1, updated_b_l2)
updated_a_l2 = sigmoid(updated_z_l2)
print(f"updated_a_l2 = {round(updated_a_l2, 4)}")
결과는 다음과 같습니다.
C:\Dev\python\pytorch>python backprop_manual_calculation.py
w_l1 = 1.58
b_l1 = -0.14
w_l2 = 2.45
b_l2 = -0.11
a_l2 = 0.8506
updated_w_l1 = 1.5814
updated_b_l1 = -0.1383
updated_w_l2 = 2.4529
updated_b_l2 = -0.1062
updated_a_l2 = 0.8515
결과가 PyTorch 네트워크의 결과와 일치하는 것을 볼 수 있습니다! 다음 기사에서는 PyTorch를 사용하여 MNIST 데이터베이스에서 숫자를 인식합니다.
코드는 github에서 사용할 수 있습니다.
중첩 소프트웨어 / 파이토치
기본 PyTorch 사용법 데모. 조밀한 네트워크와 컨벌루션 네트워크를 사용하는 MNIST 인식을 포함합니다.
이 프로젝트에는 기본 PyTorch 사용법을 보여주는 스크립트가 포함되어 있습니다. 이 코드에는 Python 3, numpy 및 pytorch가 필요합니다.
수동 대 PyTorch 역전파 계산
수동 역전파 계산을 동등한 PyTorch 버전과 비교하려면 다음을 실행하십시오.
python backprop_manual_calculation.py
w_l1 = 1.58
b_l1 = -0.14
w_l2 = 2.45
b_l2 = -0.11
a_l2 = 0.8506
updated_w_l1 = 1.5814
updated_b_l1 = -0.1383
updated_w_l2 = 2.4529
updated_b_l2 = -0.1062
updated_a_l2 = 0.8515
그리고python backprop_pytorch.py
network topology: Net(
(hidden_layer): Linear(in_features=1, out_features=1, bias=True)
(output_layer): Linear(in_features=1, out_features=1, bias=True)
)
w_l1 = 1.58
b_l1 = -0.14
w_l2 = 2.45
b_l2 = -0.11
a_l2 = 0.8506
updated_w_l1 = 1.5814
updated_b_l1 = -0.1383
updated_w_l2 = 2.4529
updated_b_l2 = -0.1062
updated_a_l2 = 0.8515
블로그 게시물:MNIST 인식
다음 예제는 처음에는 조밀한 네트워크를 사용한 다음 몇 가지 컨볼루션 네트워크 디자인을 사용하여 MNIST 숫자를 인식합니다(예제는 Michael Nielsen의 책 Neural Networks and Deep Learning에서 채택됨).
나는 추가했다…
View on GitHub
관련된
Reference
이 문제에 관하여(파이토치 헬로 월드), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/nestedsoftware/pytorch-hello-world-37mo텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)