# 4-6-1-10. Network Architectures Solution

Hi and welcome back. Here’s my solution for this model that uses a LogSoftmax output.

It is a pretty similar to what I built before with an index sequential.

So, we just use a linear transformation,

ReLU, linear transformation, ReLU,

another linear transformation for output and then we can pass this

to our LogSoftmax module.

So, what I’m doing here is I’m making sure I set

the dimension to one for LogSoftmax and this

makes it so that it calculates the function across the columns instead of the rows.

So, if you remember, the rows correspond to our examples.

So, we have a batch of examples that we’re passing

to our network and each row is one of those examples.

So, we want to make sure that we’re covering

the softmax function across each of our examples and

not across each individual feature in our batches.

Here, I’m just defining our loss or criterion as

the negative log likelihood loss and

again get our images and labels from our train loader,

flatten them, pass it through our model to get the logits.

So, this is actually not the largest anymore,

this is like a log probability,

so we call it like logps,

and then you do that.

There you go. You see we get our nice loss.

Now, we know how to calculate a loss,

but how do we actually use it to perform backpropagation?

So, PyTorch towards actually has this really great module called

So, the way it works is that,

PyTorch will keep track of all the operations you do on

a tensor and then when you can tell it to do a backwards pass,

to go backwards through each of

those operations and calculate the gradients with respect to the input parameters.

In general, you need to tell PyTorch that you want to use autograd on a specific tensor.

So, in this case, you would create some tensor like x equals torch.zeros,

just to make it a scalar,

say one and then give it requires grad equals true.

So, this tells PyTorch to track the operations on this tensor x,

so that if you want to get the gradient then it will calculate it for you.

So, in general, if you’re creating a tensor and

you don’t want to calculate the gradient for it,

you want to make sure this is set to false.

You can also use this context torch.no grad to make sure

all the gradients are shut off for all of

the operations that you’re doing while you’re in this context.

Then, you can also turn on or off gradients globally with

torch.set grad enabled and give it true or false, depending on what you want to do.

So, the way this works in PyTorch is that you basically create your tensor and again,

you set requires grad equals true and then you just perform some operations on it.

Then, once you are done with those operations, you type in.backwards.

So, if you use x, this tensor x,

then calculate some other tensor z then if you do z.backward,

it’ll go backwards through your operations and calculate the total gradient for x.

So, for example, if I just create this random tensor,

random two-by-two tensor, and then I can square it like this.

What it does, you can actually see if you look at y,

so y is our secondary or squared tensor.

If you look at y.grad function,

then it actually shows us that this grad function is a power.

So, PyTorch just track this and it

knows that the last operation done was a power operation.

So, now, we can take the mean of y and get another tensor z.

So, now this is just a scalar tensor, we’ve reduced y,

y is a two-by-two matrix,

two by two array and then we take in the mean of it to get z.

Ingredients for tensor show up in this attribute grad,

so we can actually look at what’s the gradient of our tensor x right now,

and we’ve only done this forward pass,

we haven’t actually calculated the gradient yet and so it’s just none.

So, now if we do z.backward,

it’s going to go backwards through this tiny little set of operations that we’ve done.

So, we did a power and then a mean and let’s go

backwards through this and calculate the gradient for x.

So, if you actually work out the math,

you find out that the gradient of z with respect to x should

be x over two and if we look at the gradient,

then we can also look at x divided by two then they are the same.

So, our gradient is equal to what it should be mathematically,

and this is the general process for working with gradients,

Why this is useful,

is because we can use this to get our gradients when we calculate the loss.

So, if remember, our loss depends on our weight and bias parameters.

So, what we can do is we can set up our weights as

tensors that require gradients and then do a forward pass to calculate our loss.

With the loss, you do a backwards pass which calculates the gradients for your weights,

Now, I’ll show you how that looks in code.

So, here, I’m defining our model like I did before with LogSoftmax output,

then using the negative log-likelihood loss,

get our images and labels from our train loader, flatten it,

and then we can get our log probabilities from

our model and then pass that into our criterion,

which gives us the actual loss.

So, now, if we look at our models weights,

so model zero gives us the parameters for this first linear transformation.

So, we can look at the weight and then we can look at the gradient,

then we’ll do our backwards pass starting from

the loss and then we can look at the weight gradients again.

So, we see before the backward pass,

we don’t have any because we haven’t actually

calculated it yet but then after the backwards pass,

So, we can use these gradients in gradient descent to train our network. All right.

So, now you know how to calculate losses and you know

how to use those losses to calculate gradients.

So, there’s one piece left before we can start training.

So, you need to see how to use those gradients to actually update our weights,

and for that we use optimizers and these come from PyTorch’s Optim package.

So, for example, we can use stochastic gradient descent with optim.SGD.

The way this is defined is we import

this module optim from PyTorch and then we’d say optim.SGD,

we give it our model parameters.

So, these are the parameters that we want

this optimizer to actually update and then we give it a learning rate,

and this creates our optimizer for us.

So, the training pass consists of four different steps.

So, first, we’re going to make a forward pass through the network

then we’re going to use that network output to calculate the loss,

then we’ll perform a backwards pass through

the network with loss.backwards and this will calculate the gradients.

Then, we’ll make a step with our optimizer that updates the weights.

I’ll show you how this works with one training step and then you’re going

to write it up for real and a loop that is going to train a network.

So, first, we’re going to start by getting our images

and labels like we normally do from

our train loader and then we’re going to flatten them.

Then next, what we want to do is actually clear the gradients.

So, PyTorch by default accumulates gradients.

That means that if you actually do

multiple passes and multiple backwards like multiple forward passes,

it’s going to keep summing up those gradients.

So, if you don’t clear gradients,

then you’re going to be getting gradients from the previous training step in

your current training step and it’s going to end up where

your network is just not training properly.

So, for this in general,

you’re going to be calling zero grad before every training passes.

So, you just say optimizer.zero grad and this will just clean

and it’ll allow you to train appropriately.

So, this is one of the things in PyTorch that is easy to forget,

but it’s really important.

So, try your hardest to remember to do this part,

and then we do our forward pass,

backward pass, then update the weights.

So, we get our output,

so we do a forward pass through our model with our images,

then we calculate the loss using the output of the model and our labels,

then we do a backwards pass and then finally we take an optimizer step.

So, if we look at our initial weights,

so it looks like this and then we can calculate our gradient,

and so the gradient looks like and then if

we take an optimizer step and update our weights,

then our weights have changed.

So, in general, what has worked is you’re going to be looping

through your training set and then for each batch out of your training set,

you’ll do the same training pass.

in the labels, calculate your loss,

and then do a backwards pass on the loss and then update your weights.

So, now, it’s your turn to implement the training loop for this model.

So, the idea here is that we’re going to be looping through our data-set,

so grabbing images and labels from train loader and then on each of those batches,

you’ll be doing the training pass,

and so you’ll do this pass where you calculate the output of the network,

calculate the loss, do backwards pass on loss,

Each pass through the entire training set is called an

epoch and so here I just have it set for five epochs.

So, you can change this number if you want to go more or less.

Once you calculate the loss,

we can accumulate it to keep track,

so we’re going to be looking at a loss.

So, this is running loss and so we’ll be

printing out the training loss as it’s going along.

So, if it’s working,

you should see the loss start falling,

start dropping as you’re going through the data.

Try this out yourself and if you need some help,

be sure to check out my solution. Cheers.

안녕하세요. 다음은 LogSoftmax 출력을 사용하는 이 모델에 대한 솔루션입니다.

이전에 인덱스 순차로 구축한 것과 매우 유사합니다.

그래서 우리는 선형 변환을 사용합니다.

ReLU, 선형 변환, ReLU,

출력에 대한 또 다른 선형 변환을 수행한 다음 이를 전달할 수 있습니다.

LogSoftmax 모듈에.

그래서 제가 여기서 하는 일은

LogSoftmax에 대한 차원과 이

행 대신 열에 걸쳐 함수를 계산하도록 합니다.

따라서 행은 우리의 예에 해당합니다.

그래서, 우리는 우리가 전달하는 예제의 배치가 있습니다

각 행은 이러한 예 중 하나입니다.

따라서

각 예제에서 softmax 함수와

배치의 각 개별 기능이 아닙니다.

여기서는 손실 또는 기준을 다음과 같이 정의합니다.

음의 로그 가능성 손실 및

다시 기차 로더에서 이미지와 레이블을 가져옵니다.

그것들을 평평하게 하고, 우리 모델을 통해 전달하여 로짓을 얻습니다.

그래서 이것은 실제로 더 이상 가장 크지 않습니다.

이것은 로그 확률과 같습니다.

그래서 우리는 그것을 logps라고 부릅니다.

그리고 나서 당신은 그렇게합니다.

거기 당신이 간다. 당신은 우리가 우리의 좋은 손실을 볼 수 있습니다.

이제 손실을 계산하는 방법을 알았습니다.

그러나 역전파를 수행하기 위해 실제로 어떻게 사용합니까?

따라서 PyTorch에는 실제로 이 정말 훌륭한 모듈이 있습니다.

작동 방식은 다음과 같습니다.

PyTorch는 사용자가 수행하는 모든 작업을 추적합니다.

텐서를 실행한 다음 역방향 패스를 수행하도록 지시할 수 있을 때

각각을 통해 뒤로 이동

이러한 작업을 수행하고 입력 매개변수에 대한 기울기를 계산합니다.

일반적으로 특정 텐서에서 autograd를 사용하고 싶다고 PyTorch에 알려야 합니다.

따라서 이 경우 x equals torch.zeros와 같은 일부 텐서를 생성합니다.

스칼라로 만들기 위해

하나를 말한 다음 grad equals true가 필요합니다.

따라서 이것은 PyTorch에게 이 텐서 x의 작업을 추적하도록 지시합니다.

그래디언트를 얻으려면 자동으로 계산합니다.

따라서 일반적으로 텐서를 만들고

그라디언트를 계산하고 싶지 않다면

이것이 false로 설정되어 있는지 확인하고 싶습니다.

이 컨텍스트 torch.no grad를 사용하여 확인할 수도 있습니다.

모든 그라디언트가 모두 차단됩니다.

이 컨텍스트에 있는 동안 수행 중인 작업입니다.

그런 다음 다음을 사용하여 전역적으로 그라디언트를 켜거나 끌 수도 있습니다.

torch.set grad를 활성화하고 수행하려는 작업에 따라 true 또는 false를 제공합니다.

따라서 PyTorch에서 이것이 작동하는 방식은 기본적으로 텐서를 만들고 다시,

당신이 설정한 grad는 true와 같아야 하고 그 다음에는 그것에 대해 몇 가지 작업을 수행하기만 하면 됩니다.

그런 다음 해당 작업이 끝나면 in.backwards를 입력합니다.

따라서 x를 사용하면 이 텐서 x는

그런 다음 다른 텐서 z를 계산한 다음 z.backward를 수행하면

작업을 거꾸로 진행하여 x에 대한 총 그래디언트를 계산합니다.

예를 들어 이 임의의 텐서를 생성하면

임의의 2×2 텐서를 다음과 같이 제곱할 수 있습니다.

그것이 하는 일은 실제로 y를 보면 알 수 있습니다.

따라서 y는 2차 또는 제곱 텐서입니다.

그러면 실제로 이 grad 함수가 거듭제곱임을 보여줍니다.

따라서 PyTorch는 이것을 추적하고

마지막으로 수행된 작업이 전원 작업이라는 것을 알고 있습니다.

이제 y의 평균을 취하고 또 다른 텐서 z를 얻을 수 있습니다.

이제 이것은 스칼라 텐서입니다. 우리는 y를 줄였습니다.

y는 2×2 행렬이고,

2 x 2 배열의 평균을 취하여 z를 얻습니다.

텐서의 성분은 이 속성 grad에 표시됩니다.

그래서 우리는 실제로 지금 텐서 x의 기울기가 무엇인지 볼 수 있습니다.

우리는 이 정방향 패스만 수행했습니다.

우리는 아직 그라디언트를 실제로 계산하지 않았으므로 아무 것도 아닙니다.

이제 z.backward를 수행하면

우리가 수행한 이 작은 작업 집합을 통해 거꾸로 갈 것입니다.

그래서 우리는 힘을 가한 다음 비열한 짓을 하고 가자

이를 통해 거꾸로 x에 대한 기울기를 계산합니다.

그래서 실제로 수학을 해보면,

x에 대한 z의 기울기가

x는 2보다 크며 기울기를 보면

그런 다음 x를 2로 나눈 것을 볼 수도 있습니다. 그러면 그들은 동일합니다.

그래서, 우리의 기울기는 수학적으로 해야 하는 것과 같습니다.

이것은 그라디언트 작업을 위한 일반적인 프로세스입니다.

이것이 유용한 이유,

손실을 계산할 때 이것을 사용하여 기울기를 얻을 수 있기 때문입니다.

따라서 손실은 가중치와 편향 매개변수에 따라 달라집니다.

경사하강법을 수행하려면 가중치의 경사도가 필요합니다.

그래서 우리가 할 수 있는 것은 우리의 가중치를 다음과 같이 설정할 수 있다는 것입니다.

그래디언트가 필요한 텐서는 손실을 계산하기 위해 순방향 패스를 수행합니다.

손실과 함께 가중치에 대한 기울기를 계산하는 역방향 패스를 수행합니다.

그런 다음 그 그라디언트를 사용하여 그라디언트 하강 단계를 수행할 수 있습니다.

이제 코드에서 어떻게 보이는지 보여 드리겠습니다.

여기에서는 이전에 LogSoftmax 출력으로 했던 것처럼 모델을 정의하고 있습니다.

그런 다음 음의 로그 가능성 손실을 사용하여

기차 로더에서 이미지와 레이블을 가져와 평평하게 만들고,

그리고 나서 우리는 우리의 로그 확률을 얻을 수 있습니다

모델을 만든 다음 이를 기준에 전달합니다.

이는 우리에게 실제 손실을 줍니다.

이제 모델 가중치를 보면

따라서 모델 0은 이 첫 번째 선형 변환에 대한 매개변수를 제공합니다.

그래서 우리는 무게를 볼 수 있고 기울기를 볼 수 있습니다.

그런 다음 다음부터 역방향 패스를 수행합니다.

손실을 확인한 다음 가중치 기울기를 다시 볼 수 있습니다.

그래서, 우리는 역방향 패스 전에,

우리는 실제로 가지고 있지 않기 때문에

아직 계산했지만 역방향 통과 후

우리는 기울기를 계산했습니다.

그래서, 우리는 우리의 네트워크를 훈련시키기 위해 경사하강법에서 이러한 경사를 사용할 수 있습니다. 괜찮아.

이제 손실을 계산하는 방법과

이러한 손실을 사용하여 기울기를 계산하는 방법.

자, 훈련을 시작하기 전에 한 조각이 남았습니다.

따라서 이러한 그라디언트를 사용하여 실제로 가중치를 업데이트하는 방법을 알아야 합니다.

이를 위해 옵티마이저를 사용하며 이는 PyTorch의 Optim 패키지에서 제공됩니다.

예를 들어 optim.SGD와 함께 확률적 경사하강법을 사용할 수 있습니다.

이것이 정의된 방식은 우리가 import하는 것입니다

이 모듈은 PyTorch에서 최적화한 다음 optim.SGD라고 합니다.

모델 매개변수를 제공합니다.

그래서 이것들은 우리가 원하는 매개변수입니다.

이 옵티마이저는 실제로 업데이트하고 학습률을 제공합니다.

이것은 우리를 위한 최적화 프로그램을 만듭니다.

따라서 교육 패스는 4단계로 구성됩니다.

따라서 먼저 네트워크를 통해 정방향 패스를 만들 것입니다.

그런 다음 해당 네트워크 출력을 사용하여 손실을 계산합니다.

그런 다음 역방향 통과를 수행합니다.

loss.backwards가 있는 네트워크를 사용하면 그래디언트가 계산됩니다.

그런 다음 가중치를 업데이트하는 옵티마이저로 단계를 수행합니다.

하나의 훈련 단계로 이것이 어떻게 작동하는지 보여 드리겠습니다.

실제와 네트워크를 훈련시킬 루프를 작성합니다.

따라서 먼저 이미지를 가져오는 것으로 시작하겠습니다.

그리고 우리가 일반적으로 하는 것과 같은 라벨

우리의 기차 로더 그리고 우리는 그들을 평평하게 할 것입니다.

다음으로 우리가 하고자 하는 것은 실제로 그라디언트를 지우는 것입니다.

따라서 PyTorch는 기본적으로 그라디언트를 누적합니다.

즉, 실제로 하면

다중 전진 패스와 같은 다중 패스 및 다중 역방향,

여러 개의 역방향 패스를 사용하고 계속해서 기울기를 계산합니다.

계속해서 그 그라디언트를 요약할 것입니다.

따라서 그라디언트를 지우지 않으면

그러면 이전 학습 단계에서 그라디언트를 얻게 됩니다.

귀하의 현재 훈련 단계는

네트워크가 제대로 훈련되지 않고 있습니다.

따라서 일반적으로

모든 훈련이 통과하기 전에 제로 그레이드를 호출할 것입니다.

그래서, 당신은 optimizer.zero grad라고 말하고 이것은 그냥 깨끗할 것입니다

옵티마이저의 모든 그래디언트와 모든 매개변수를

적절하게 훈련할 수 있습니다.

따라서 이것은 PyTorch에서 잊기 쉬운 것 중 하나입니다.

하지만 정말 중요합니다.

따라서 이 부분을 기억하기 위해 최선을 다하십시오.

그리고 나서 우리는 우리의 전진 패스를 하고,

역방향 패스를 수행한 다음 가중치를 업데이트합니다.

따라서 우리는 출력을 얻습니다.

그래서 우리는 우리의 이미지를 가지고 모델을 통해 순방향 패스를 하고,

그런 다음 모델과 레이블의 출력을 사용하여 손실을 계산합니다.

그런 다음 역방향 패스를 수행하고 마지막으로 최적화 단계를 수행합니다.

따라서 초기 가중치를 보면

이렇게 하면 기울기를 계산할 수 있습니다.

그래디언트가 다음과 같이 보입니다.

최적화 단계를 수행하고 가중치를 업데이트합니다.

그럼 우리의 무게가 변경되었습니다.

따라서 일반적으로 효과가 있었던 것은 루프를 돌게 된다는 것입니다.

훈련 세트를 통과한 다음 훈련 세트의 각 배치에 대해

당신은 같은 훈련 패스를 할 것입니다.

그래서, 당신은 당신의 데이터를 얻을 것이다,

그런 다음 그라디언트를 지우고

그 이미지나 입력을 네트워크를 통해 전달하여 출력을 얻습니다.

레이블에서 손실을 계산하고,

그런 다음 손실에 대해 역방향 패스를 수행한 다음 가중치를 업데이트합니다.

이제 이 모델에 대한 훈련 루프를 구현할 차례입니다.

여기에서 아이디어는 우리가 데이터 세트를 반복할 것이라는 것입니다.

그래서 기차 로더에서 이미지와 레이블을 가져온 다음 각 배치에서

당신은 훈련 패스를 할 것입니다,

따라서 네트워크의 출력을 계산하는 이 단계를 수행합니다.

손실을 계산하고 손실을 역전승하고,

그런 다음 가중치를 업데이트하십시오.

전체 훈련 세트를 통과하는 각 패스를

epoch, 그래서 여기서는 5개의 epoch로 설정했습니다.

따라서 더 많이 또는 더 적게 가고 싶다면 이 숫자를 변경할 수 있습니다.

손실을 계산하면,

추적하기 위해 축적할 수 있습니다.

그래서 우리는 손실을 볼 것입니다.

자, 이것은 적자입니다. 그래서 우리는

진행하면서 학습 손실을 인쇄합니다.

작동하는 경우

손실이 감소하기 시작하는 것을 볼 수 있습니다.

데이터를 살펴보는 동안 떨어지기 시작합니다.

직접 시도해보고 도움이 필요하면

내 솔루션을 확인하십시오. 건배.

# The MNIST datasets are hosted on yann.lecun.com that has moved under CloudFlare protection
# Reference: https://github.com/pytorch/vision/issues/1938

from six.moves import urllib
opener = urllib.request.build_opener()
urllib.request.install_opener(opener)

import torch
from torch import nn
import torch.nn.functional as F
from torchvision import datasets, transforms

# Define a transform to normalize the data
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,)),
])

# Note If you haven't seen nn.Sequential yet, please finish the end of the Part 2 notebook.

# Build a feed-forward network
model = nn.Sequential(nn.Linear(784, 128),
nn.ReLU(),
nn.Linear(128, 64),
nn.ReLU(),
nn.Linear(64, 10))

# Define the loss
criterion = nn.CrossEntropyLoss()

# Get our data

images, labels = next(dataiter)

# Flatten images
images = images.view(images.shape[0], -1)

# Forward pass, get our logits
logits = model(images)
# Calculate the loss with the logits and the labels
loss = criterion(logits, labels)

print(loss)

## Solution ##################################
# TODO: Build a feed-forward network
# Build a feed-forward network
model = nn.Sequential(nn.Linear(784, 128),
nn.ReLU(),
nn.Linear(128, 64),
nn.ReLU(),
nn.Linear(64, 10),
nn.LogSoftmax(dim=1))

# TODO: Define the loss
# Define the loss
criterion = nn.NLLLoss()

# Get our data
# Flatten images
images = images.view(images.shape[0], -1)

# Forward pass, get our log-probabilities
logps = model(images)
# Calculate the loss with the logps and the labels
loss = criterion(logps, labels)

print(loss)
################################################

### Run this to check your work
# Get our data

images, labels = next(dataiter)

# Flatten images
images = images.view(images.shape[0], -1)

# Forward pass, get our logits
logits = model(images)
# Calculate the loss with the logits and the labels
loss = criterion(logits, labels)

print(loss)

# Build a feed-forward network
model = nn.Sequential(nn.Linear(784, 128),
nn.ReLU(),
nn.Linear(128, 64),
nn.ReLU(),
nn.Linear(64, 10),
nn.LogSoftmax(dim=1))

criterion = nn.NLLLoss()
images, labels = next(dataiter)
images = images.view(images.shape[0], -1)

logits = model(images)
loss = criterion(logits, labels)

loss.backward()

from torch import optim

# Optimizers require the parameters to optimize and a learning rate
optimizer = optim.SGD(model.parameters(), lr=0.01)

print('Initial weights - ', model[0].weight)

images, labels = next(dataiter)
images.resize_(64, 784)

# Forward pass, then backward pass, then update weights
output = model(images)
loss = criterion(output, labels)
loss.backward()

# Take an update step and view the new weights
optimizer.step()
print('Updated weights - ', model[0].weight)

model = nn.Sequential(nn.Linear(784, 128),
nn.ReLU(),
nn.Linear(128, 64),
nn.ReLU(),
nn.Linear(64, 10),
nn.LogSoftmax(dim=1))

criterion = nn.NLLLoss()
optimizer = optim.SGD(model.parameters(), lr=0.003)

epochs = 5
for e in range(epochs):
running_loss = 0
# Flatten MNIST images into a 784 long vector
images = images.view(images.shape[0], -1)

# TODO: Training pass

#####################

running_loss += loss.item()
else:

# With the network trained, we can check out it's predictions.

import helper

helper.view_classify(img.view(1, 28, 28), ps)