# 4-6-1-5. Multilayer Networks Solution

All right. So, here’s my solution for this exercise.

So, here, I had you calculate the output of

this multi-layer network using the weights and features that we’ve defined up here.

So, it was really similar to what we did before with

our single layer simple neural network.

So, it’s basically just taking the features and our weight matrix,

our first weight matrix,

and calculating a matrix multiplication.

So, here’s the torch.mm plus B1,

and then that gives us values for our hidden layer H. Now,

we can use the values H as the input for the next layer of our network.

So, we just do, again,

a matrix multiplication of these hidden values H,

with our second weight matrix W2,

and adding on our bias terms, and then we get the output.

So, my favorite features of PyTorches is being able to

convert between Numpy arrays and Torch tensors,

in a very nice and easy manner.

So, this is really useful because a lot of the times,

you’ll be preparing your data and to do some preprocessing using Numpy,

and then you want to move it into your network,

and so, you have to bridge these Numpy arrays,

what you’re using for your data,

and then the Torch tensors that you’re using for your network.

So, actually, to do this,

we can actually get a tensor from a Numpy array using torch.fromnumpy.

So, here I’ve just created a random array, a four-by-three array,

and then we can create a Torch tensor from

this array just by doing.from Numpy, and passing an array.

So, this creates a nice tensor for us.

So, this is a tensor in PyTorch,

we can use with all of our Torch methods and eventually,

use it in a neural network.

Then, we can go backwards,

so we can take a tensor such as B here.

This is our Torch tensor and we can go back to a Numpy array doing b.numpy.

So, this gives us back our Numpy array.

So, one thing to remember when you’re doing this,

is that the memory is actually shared between the Numpy array and this Torch tensor.

So, what this means, is that if you do any operations in

place on either the Numpy array or the tensor,

then you’re going to change the values for the other one.

So, for example, if we do this in-place operation of multiplying by two,

which means that we’re actually changing the values in memory,

and not creating a new tensor,

then we will actually change the values in the Numpy array.

So, you see here, we have our Numpy array.

So initially, it’s like this,

convert it to a Torch tensor, and here,

I’m doing this in-place multiplication,

and we’ve changed our values for this tensor.

Then, if you look back at the Numpy array,

the values have changed.

So, that’s just something to keep in mind as you’re doing this,

so you’re not caught off guard when you’re seeing your arrays,

your Numpy arrays, being changed because of operations you’re doing on the tensor.

See you in the next video, cheers.

괜찮아. 이 연습에 대한 제 솔루션은 다음과 같습니다.

그래서 여기, 나는 당신이 출력을 계산하도록 했습니다.

여기에서 정의한 가중치와 기능을 사용하는 이 다층 네트워크입니다.

그래서 우리가 전에 했던 것과 정말 비슷했습니다.

우리의 단일 레이어 단순 신경망.

따라서 기본적으로 기능과 가중치 행렬을 취하는 것입니다.

첫 번째 가중치 행렬,

및 행렬 곱셈을 계산하는 단계를 포함한다.

그래서, 여기에 토치가 있습니다.mm 플러스 B1,

그러면 은닉층 H에 대한 값이 제공됩니다. 이제,

네트워크의 다음 계층에 대한 입력으로 값 H를 사용할 수 있습니다.

그래서, 우리는 다시,

이러한 숨겨진 값 H의 행렬 곱셈,

두 번째 가중치 행렬 W2를 사용하여

편향 항을 더하면 결과가 나옵니다.

따라서 PyTorches의 가장 좋아하는 기능은 다음을 수행할 수 있다는 것입니다.

Numpy 배열과 Torch 텐서 간 변환,

아주 멋지고 쉬운 방법으로.

많은 경우에 이것은 매우 유용합니다.

데이터를 준비하고 Numpy를 사용하여 일부 사전 처리를 수행합니다.

네트워크로 이동하려는 경우

따라서 이 Numpy 배열을 연결해야 합니다.

데이터에 무엇을 사용하고 있는지,

그런 다음 네트워크에 사용 중인 Torch 텐서입니다.

그래서 실제로 이 작업을 수행하려면

우리는 실제로 torch.fromnumpy를 사용하여 Numpy 배열에서 텐서를 얻을 수 있습니다.

그래서 여기에서 4×3 배열인 임의의 배열을 만들었습니다.

다음에서 Torch 텐서를 생성할 수 있습니다.

이 배열은 Numpy에서 하고 배열을 전달하는 것입니다.

따라서 이것은 우리에게 좋은 텐서를 생성합니다.

이것은 PyTorch의 텐서입니다.

우리는 모든 Torch 방법과 함께 사용할 수 있으며 결국

신경망에서 사용합니다.

그러면 뒤로 갈 수 있습니다.

그래서 우리는 여기서 B와 같은 텐서를 취할 수 있습니다.

이것은 Torch 텐서이며 b.numpy를 수행하는 Numpy 배열로 돌아갈 수 있습니다.

따라서 이것은 Numpy 배열을 반환합니다.

따라서 이 작업을 수행할 때 한 가지 기억해야 할 점은,

메모리가 실제로 Numpy 배열과 이 Torch 텐서 간에 공유된다는 것입니다.

따라서 이것이 의미하는 바는 다음에서 작업을 수행하면

Numpy 배열이나 텐서에 배치하고,

그런 다음 다른 값의 값을 변경합니다.

예를 들어, 2를 곱하는 이 제자리 연산을 수행하면

이는 실제로 메모리의 값을 변경한다는 것을 의미합니다.

새로운 텐서를 생성하지 않고,

그런 다음 실제로 Numpy 배열의 값을 변경합니다.

여기 Numpy 배열이 있습니다.

그래서 처음에는 이렇습니다.

Torch 텐서로 변환하고 여기에서

이 제자리 곱셈을 하고 있습니다.

이 텐서에 대한 값을 변경했습니다.

그런 다음 Numpy 배열을 다시 보면,

값이 변경되었습니다.

따라서 이 작업을 수행할 때 염두에 두어야 할 사항은

배열을 볼 때 당황하지 않고

텐서에서 수행하는 작업으로 인해 Numpy 배열이 변경됩니다.

다음 영상에서 만나요, 건배.

# First, import PyTorch
import torch

def activation(x):
""" Sigmoid activation function

Arguments
---------
x: torch.Tensor
"""
return 1/(1+torch.exp(-x))

### Generate some data
torch.manual_seed(7) # Set the random seed so things are predictable

# Features are 5 random normal variables
features = torch.randn((1, 5))
# True weights for our data, random normal variables again
weights = torch.randn_like(features)
# and a true bias term
bias = torch.randn((1, 1))

### Solution

# Now, make our labels from our data and true weights

y = activation(torch.sum(features * weights) + bias)
y = activation((features * weights).sum() + bias)

## Solution

y = activation(torch.mm(features, weights.view(5,1)) + bias)

### Generate some data
torch.manual_seed(7) # Set the random seed so things are predictable

# Features are 3 random normal variables
features = torch.randn((1, 3))

# Define the size of each layer in our network
n_input = features.shape[1]     # Number of input units, must match number of input features
n_hidden = 2                    # Number of hidden units
n_output = 1                    # Number of output units

# Weights for inputs to hidden layer
W1 = torch.randn(n_input, n_hidden)
# Weights for hidden layer to output layer
W2 = torch.randn(n_hidden, n_output)

# and bias terms for hidden and output layers
B1 = torch.randn((1, n_hidden))
B2 = torch.randn((1, n_output))

### Solution

h = activation(torch.mm(features, W1) + B1)
output = activation(torch.mm(h, W2) + B2)
print(output)