# 4-6-1-8. Implementing Softmax Solution

so it’s pretty straight forward with torch.exp.

So we’re going to use the exponential of x,

which is our input tensor.

In the denominator, we know we want to do something like,

again take exponentials so torch.exp,

and then take the sum across all those values.

So, one thing we need to remember is that we want the sum across one single row.

So, each of the columns in one single row for each example.

So, for one example, we want to sum up those values.

So, for here in torch.sum,

we’re going to use dimension equals one.

So, this is basically going to take the sum across the columns.

What this does, torch.sum here,

is going to actually going to give us a tensor,

that is just a vector of 64 elements.

So, the problem with this is that,

if this is 64 by 10,

and this is just a 64-long vector,

it’s going to try to divide every element in this tensor by all 64 of these values.

So, it’s going give us a 64 by 64 tensor, and that’s not what we want.

We want our output to be 64 by 10.

So, what you actually need to do is reshape this tensor here to have 64 rows,

but only one value for each of those rows.

So, what that’s going do,

it’s going look at for each row in this tensor,

is going to look at the equivalent row in this tensor.

So, since each row in this tensor only has one value,

it’s going to divide this exponential by the one value in this denominator tensor.

This can be really tricky,

but it’s also super important to understand how broadcasting works in PyTorch,

and how to actually fit all these tensors together with

the correct shape and the correct operations to get everything out right.

So, if we do this, it look what we have,

we pass our output through the softmax function,

and then we get our probabilities,

and we can look the shape and it is 64 by 10,

and if you take the sum across each of the rows,

then it adds up to one,

like it should with a proper probability distribution.

So, now, we’re going to look at how you use this nn module to build neural networks.

So, you’ll find that it’s actually in a lot of ways simpler and more powerful.

You’ll be able to build larger and larger neural networks using the same framework.

The way this works in general,

is that we’re going to create a new class,

and you can call it networking,

you can call it whatever you want,

you can call it classifier,

you can call it MNIST.

It doesn’t really matter so much what you call it,

but you need to subclass it from nn.module.

Then, in the init method, it’s __init method.

You need to call it super and run the init method of nn.module.

So, you need to do this because then,

PyTorch will know to register

all the different layers and

operations that you’re going to be putting into this network.

If you don’t do this part then,

it won’t be able to track the things that

So, here, we can create our hidden layers using nn.Linear.

So, what this does,

is it creates a operation for the linear transformation.

So, when we take our inputs x and then multiply it by weights and add your bias terms,

that’s a linear transformation.

So, what this does is calling NN.Linear,

it creates an object that itself has created

parameters for the weights and parameters for the bias and then,

when you pass a tensor through this hidden layer,

this object, it’s going to automatically calculate the linear transformation for you.

So, all you really need to do is tell it what’s the size of the inputs,

and then what are the size of the output.

So, 784 by 256,

we’re going to use 256 outputs for this.

So, it’s kind of rebuilding the network that we saw before.

Similarly, we want another linear transformation between our hidden units and our output.

So, again, we have 256 hidden units,

and we have 10 outputs, 10 output units,

so we’re going to create a output layer called self.output,

and create this linear transformation operation.

We also want to create a sigmoid operation for the activation and then,

softmax for the output,

so we get this probability distribution.

Now, we’re going to create a forward method and so,

forward is basically going to be,

as we pass a tensor in to the network.

It’s gonna go through all these operations,

and eventually give us our output.

So, here, x, the argument is going to be the input tensor and then,

we’re going to pass it through our hidden layer.

So, this is again, like this linear transformation that we defined up here,

and it’s going to go through a sigmoid activation,

and then through our output layer or output linear transformation, we have here,

and then through the sigmoid function,

and then finally return the output of our softmax.

so we can create this.

Then, if we kind of look at it, so it’ll print it out,

and it’ll tell us the operations, and not necessarily the order,

but at least it tells us the operations that we have defined for this network.

You can also use some functional definitions for things like sigmoid and softmax,

and it kind of makes the class the way you write the code a little bit cleaner.

We can get that from torch.nn.functional.

Most of the time, you’ll see is like import torch.nn.functional as capital F. So,

there’s kind of that convention in PyTorch code.

So, again, we define our linear transformations,

self.hidden, self.output but now in our forward method.

So, we can call self.hidden to get like our values for hidden layer, but then,

we pass it through the sigmoid function,

f.sigmoid, and the same thing with the output layers.

So, we have our output linear transformations of the output,

and we pass it through this softmax operation.

So, the reason we can do this because,

when we create these linear transformations,

it’s creating the weights and bias matrices on its own.

But for sigmoid and softmax,

it’s just an element wise operation,

so it doesn’t have to create any extra parameters

or extra matrices to do these operations,

and so we can have these be purely functional

without having to create any sort of object or classes.

However, they are equivalent.

So this way to build the network is equivalent to this way up here,

but it’s a little bit more succinct when you’re

doing it with these kind of functional pattern.

So far, we’ve only been using the sigmoid function as an activation function,

but there are, of course,

a lot of different ones you want to use.

Really the only requirement is that,

these activation functions should typically be non-linear.

So, if you want your network to be able to learn non-linear correlations and patterns,

and we want the output to be non-linear,

then you need to use non-linear activation functions in your hidden layers.

So, a sigmoid is one example.

The hyperbolic tangent is another.

One that is pretty much used all the time,

like almost exclusively as activation function and hidden layers,

is the ReLU, so the rectified linear unit.

This is basically the simplest non-linear function that you can use,

and it turns out that networks tend to train a lot faster

when using ReLU as compared to sigmoid and hyperbolic tangent,

so ReLU was what we typically use.

Okay. So, here, you’re going to build your own neural network, that’s larger.

So, this time, it’s going to have two hidden layers,

and you’ll be using the ReLU activation function for this on your hidden layers.

So using this object-oriented class method within a.module,

go ahead and build a network that looks like this,

with 784 input units,

a 128 units in the first hidden layer,

64 units and the second hidden layer,

and then 10 output units. All right. Cheers.

다시 오신 것을 환영합니다. 다음은 softmax 기능에 대한 내 솔루션입니다.

여기에서 분자,

우리는 지수를 취하기를 원한다는 것을 알고 있습니다.

따라서 torch.exp를 사용하면 매우 간단합니다.

그래서 우리는 x의 지수를 사용할 것입니다.

이것은 우리의 입력 텐서입니다.

분모에서 우리는 우리가 다음과 같은 것을 하기를 원한다는 것을 압니다.

다시 지수를 취하여 토치.exp,

그런 다음 모든 값의 합계를 구합니다.

따라서 기억해야 할 한 가지는 단일 행에 대한 합계를 원한다는 것입니다.

따라서 각 예에 대해 하나의 단일 행에 있는 각 열.

예를 들어 이러한 값을 합산하고자 합니다.

그래서, 여기 torch.sum에서,

차원이 1인 것을 사용할 것입니다.

따라서 이것은 기본적으로 열에 걸쳐 합계를 취합니다.

이것이 하는 일, 여기에 토치.sum,

실제로 우리에게 텐서를 줄 것입니다.

64개 요소로 구성된 벡터일 뿐입니다.

그래서, 이것의 문제는,

이것이 64 x 10이면

이것은 64개의 길이의 벡터입니다.

이 텐서의 모든 요소를 ​​64개의 값으로 나누려고 합니다.

따라서 64 x 64 텐서를 제공할 것이며 이는 우리가 원하는 것이 아닙니다.

우리는 출력이 64 x 10이 되기를 원합니다.

따라서 실제로 해야 할 일은 여기 이 텐서를 64행으로 재구성하는 것입니다.

그러나 각 행에 대해 하나의 값만 있습니다.

그래서, 그것이 무엇을 할 것인지,

이 텐서의 각 행을 살펴보고

이 텐서에서 동등한 행을 볼 것입니다.

따라서 이 텐서의 각 행에는 하나의 값만 있기 때문에

이 지수를 이 분모 텐서의 한 값으로 나눌 것입니다.

이것은 정말 까다로울 수 있습니다,

하지만 PyTorch에서 브로드캐스팅이 어떻게 작동하는지 이해하는 것도 매우 중요합니다.

실제로 이 모든 텐서를 함께 맞추는 방법

올바른 모양과 올바른 작업을 통해 모든 것이 올바르게 표시됩니다.

그래서, 우리가 이것을 하면, 우리가 가지고 있는 것처럼 보입니다.

softmax 함수를 통해 출력을 전달합니다.

그런 다음 우리는 확률을 얻습니다.

모양을 보면 64 x 10입니다.

각 행의 합계를 구하면

그러면 하나가 됩니다.

적절한 확률 분포가 있어야 하는 것처럼.

이제 이 nn 모듈을 사용하여 신경망을 구축하는 방법을 살펴보겠습니다.

따라서 실제로 여러 면에서 더 간단하고 강력하다는 것을 알게 될 것입니다.

동일한 프레임워크를 사용하여 더 크고 더 큰 신경망을 구축할 수 있습니다.

이것이 일반적으로 작동하는 방식,

새 클래스를 생성한다는 것입니다.

네트워킹이라고 할 수 있습니다.

원하는 대로 부를 수 있습니다.

분류기라고 부를 수 있습니다.

MNIST라고 부를 수 있습니다.

당신이 그것을 무엇이라고 부르는지는 그다지 중요하지 않습니다.

하지만 nn.module에서 서브클래스화해야 합니다.

그런 다음 init 메소드에서 __init 메소드입니다.

그것을 super라고 부르고 nn.module의 init 메소드를 실행해야 합니다.

따라서 이렇게 해야 합니다.

PyTorch는 등록을 알게 됩니다.

모든 다른 레이어와

이 네트워크에 넣을 작업입니다.

이 부분을 하지 않으면

추적할 수 없습니다.

네트워크에 추가하고 있는데 작동하지 않습니다.

여기에서 nn.Linear를 사용하여 은닉층을 생성할 수 있습니다.

그래서 이것이 무엇을 하는지,

선형 변환을 위한 연산을 생성합니다.

따라서 입력 x를 취한 다음 가중치를 곱하고 편향 항을 추가하면

그것은 선형 변환입니다.

따라서 이것이 하는 일은 NN.Linear를 호출하는 것입니다.

자신이 만든 객체를 생성합니다.

가중치에 대한 매개변수와 편향에 대한 매개변수,

이 은닉층을 통해 텐서를 전달할 때,

이 개체는 자동으로 선형 변환을 계산합니다.

따라서 실제로 해야 할 일은 입력의 크기를 알려주는 것뿐입니다.

그런 다음 출력의 크기는 얼마입니까?

따라서 784 x 256,

이를 위해 256개의 출력을 사용할 것입니다.

그래서, 그것은 우리가 전에 본 네트워크를 재구축하는 것입니다.

유사하게, 우리는 은닉 유닛과 출력 사이의 또 다른 선형 변환을 원합니다.

다시, 256개의 은닉 유닛이 있습니다.

우리는 10개의 출력, 10개의 출력 유닛,

따라서 self.output이라는 출력 레이어를 만들 것입니다.

이 선형 변환 작업을 만듭니다.

우리는 또한 활성화를 위한 시그모이드 연산을 만들고 싶습니다.

출력을 위한 softmax,

그래서 우리는 이 확률 분포를 얻습니다.

이제 우리는 forward 메서드를 만들 것입니다.

앞으로는 기본적으로

텐서를 네트워크에 전달할 때.

이 모든 작업을 거치게 됩니다.

그리고 결국 우리에게 우리의 출력을 제공합니다.

그래서, 여기 x, 인수는 입력 텐서가 될 것이고, 그리고 나서,

은닉층을 통과할 것입니다.

그래서 이것은 다시, 우리가 여기에서 정의한 선형 변환과 같습니다.

시그모이드 활성화를 거치게 됩니다.

그런 다음 출력 레이어 또는 출력 선형 변환을 통해 여기에 있습니다.

그런 다음 시그모이드 함수를 통해

그런 다음 마지막으로 softmax의 출력을 반환합니다.

그래서 우리는 이것을 만들 수 있습니다.

그런 다음, 우리가 그것을 보면, 그래서 그것을 인쇄할 것입니다.

필요하지 않은 작업을 알려줍니다.

Exercise: Implement a function softmax that performs the softmax calculation and returns probability distributions for each example in the batch. Note that you’ll need to pay attention to the shapes when doing this. If you have a tensor a with shape (64, 10) and a tensor b with shape (64,), doing a/b will give you an error because PyTorch will try to do the division across the columns (called broadcasting) but you’ll get a size mismatch. The way to think about this is for each of the 64 examples, you only want to divide by one value, the sum in the denominator. So you need b to have a shape of (64, 1). This way PyTorch will divide the 10 values in each row of a by the one value in each row of b. Pay attention to how you take the sum as well. You’ll need to define the dim keyword in torch.sum. Setting dim=0 takes the sum across the rows while dim=1 takes the sum across the columns.

# Import necessary packages

import numpy as np
import torch

import helper

import matplotlib.pyplot as plt

# 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)

### Run this cell

from torchvision import datasets, transforms

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

images, labels = dataiter.next()
print(type(images))
print(images.shape)
print(labels.shape)

plt.imshow(images[1].numpy().squeeze(), cmap='Greys_r');

def activation(x):
return 1/(1+torch.exp(-x))

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

# Create parameters
w1 = torch.randn(784, 256)
b1 = torch.randn(256)

w2 = torch.randn(256, 10)
b2 = torch.randn(10)

h = activation(torch.mm(inputs, w1) + b1)

out = activation(torch.mm(h, w2) + b2)

## Solution
def softmax(x):

probabilities = softmax(out)

# Does it have the right shape? Should be (64, 10)
print(probabilities.shape)
# Does it sum to 1?
print(probabilities.sum(dim=1))