Instruction: RuntimeError: Given groups=3, weight of size 12 64 3 768, expected input[32, 12, 30, 768] to have 192 channels, but got 12 channels instead

Input:
I started working with Pytorch recently so my understanding of it isn't quite strong. I previously had a 1 layer CNN but wanted to extend it to 2 layers, but the input and output channels have been throwing errors I can seem to decipher. Why does it expect 192 channels? Can someone give me a pointer to help me understand this better? I have seen several related problems on here, but I don't understand those solutions either.

import numpy as np
import pandas as pd
import torch
import torch.nn as nn
from transformers import BertConfig, BertModel, BertTokenizer
import math
from transformers import AdamW, get_linear_schedule_with_warmup

def pad_sents(sents, pad_token):  # Pad list of sentences according to the longest sentence in the batch.
    sents_padded = []
    max_len = max(len(s) for s in sents)
    for s in sents:
        padded = [pad_token] * max_len
        padded[:len(s)] = s
        sents_padded.append(padded)
    return sents_padded

def sents_to_tensor(tokenizer, sents, device):
    tokens_list = [tokenizer.tokenize(str(sent)) for sent in sents]
    sents_lengths = [len(tokens) for tokens in tokens_list]
    tokens_list_padded = pad_sents(tokens_list, '[PAD]')
    sents_lengths = torch.tensor(sents_lengths, device=device)
    masks = []
    for tokens in tokens_list_padded:
        mask = [0 if token == '[PAD]' else 1 for token in tokens]
        masks.append(mask)
    masks_tensor = torch.tensor(masks, dtype=torch.long, device=device)
    tokens_id_list = [tokenizer.convert_tokens_to_ids(tokens) for tokens in tokens_list_padded]
    sents_tensor = torch.tensor(tokens_id_list, dtype=torch.long, device=device)

    return sents_tensor, masks_tensor, sents_lengths

class ConvModel(nn.Module):

    def __init__(self, device, dropout_rate, n_class, out_channel=16):
        super(ConvModel, self).__init__()
        self.bert_config = BertConfig.from_pretrained('bert-base-uncased', output_hidden_states=True)
        self.dropout_rate = dropout_rate
        self.n_class = n_class
        self.out_channel = out_channel
        self.bert = BertModel.from_pretrained('bert-base-uncased', config=self.bert_config)
        self.out_channels = self.bert.config.num_hidden_layers * self.out_channel
        self.tokenizer = BertTokenizer.from_pretrained('bert-base-uncased', config=self.bert_config)
        self.conv = nn.Conv2d(in_channels=self.bert.config.num_hidden_layers,
                              out_channels=self.out_channels,
                              kernel_size=(3, self.bert.config.hidden_size),
                              groups=self.bert.config.num_hidden_layers)
        self.conv1 = nn.Conv2d(in_channels=self.out_channels,
                               out_channels=48,
                               kernel_size=(3, self.bert.config.hidden_size),
                               groups=self.bert.config.num_hidden_layers)
        self.hidden_to_softmax = nn.Linear(self.out_channels, self.n_class, bias=True)
        self.dropout = nn.Dropout(p=self.dropout_rate)
        self.device = device

    def forward(self, sents):
        sents_tensor, masks_tensor, sents_lengths = sents_to_tensor(self.tokenizer, sents, self.device)
        encoded_layers = self.bert(input_ids=sents_tensor, attention_mask=masks_tensor)
        hidden_encoded_layer = encoded_layers[2]
        hidden_encoded_layer = hidden_encoded_layer[0]
        hidden_encoded_layer = torch.unsqueeze(hidden_encoded_layer, dim=1)
        hidden_encoded_layer = hidden_encoded_layer.repeat(1, 12, 1, 1)
        conv_out = self.conv(hidden_encoded_layer)  # (batch_size, channel_out, some_length, 1)
        conv_out = self.conv1(conv_out)
        conv_out = torch.squeeze(conv_out, dim=3)  # (batch_size, channel_out, some_length)
        conv_out, _ = torch.max(conv_out, dim=2)  # (batch_size, channel_out)
        pre_softmax = self.hidden_to_softmax(conv_out)

        return pre_softmax

def batch_iter(data, batch_size, shuffle=False, bert=None):
    batch_num = math.ceil(data.shape[0] / batch_size)
    index_array = list(range(data.shape[0]))
    if shuffle:
        data = data.sample(frac=1)
    for i in range(batch_num):
        indices = index_array[i * batch_size: (i + 1) * batch_size]
        examples = data.iloc[indices]
        sents = list(examples.train_BERT_tweet)
        targets = list(examples.train_label.values)
        yield sents, targets  # list[list[str]] if not bert else list[str], list[int]

def train():
    label_name = ['Yes', 'Maybe', 'No']
    device = torch.device("cpu")

    df_train = pd.read_csv('trainn.csv')  # , index_col=0)
    train_label = dict(df_train.train_label.value_counts())
    label_max = float(max(train_label.values()))
    train_label_weight = torch.tensor([label_max / train_label[i] for i in range(len(train_label))], device=device)
    model = ConvModel(device=device, dropout_rate=0.2, n_class=len(label_name))
    optimizer = AdamW(model.parameters(), lr=1e-3, correct_bias=False)
    scheduler = get_linear_schedule_with_warmup(optimizer, num_warmup_steps=100, num_training_steps=1000)  # changed the last 2 arguments to old ones
    model = model.to(device)
    model.train()
    cn_loss = torch.nn.CrossEntropyLoss(weight=train_label_weight, reduction='mean')
    train_batch_size = 16

    for epoch in range(1):

        for sents, targets in batch_iter(df_train, batch_size=train_batch_size, shuffle=True):  # for each epoch
            optimizer.zero_grad()
            pre_softmax = model(sents)
            loss = cn_loss(pre_softmax, torch.tensor(targets, dtype=torch.long, device=device))
            loss.backward()
            optimizer.step()
            scheduler.step()
TrainingModel = train()

Here's a snippet of data https://github.com/Kosisochi/DataSnippet

Output:
It seems that the original version of the code you had in this question behaved differently. The final version of the code you have here gives me a different error from what you posted, more specifically - this:

RuntimeError: Calculated padded input size per channel: (20 x 1). Kernel size: (3 x 768). Kernel size can't be greater than actual input size

I apologize if I misunderstood the situation, but it seems to me that your understanding of what exactly nn.Conv2d layer does is not 100% clear and that is the main source of your struggle. I interpret the part "detailed explanation on 2 layer CNN in Pytorch" you requested as an ask to explain in detail on how that layer works and I hope that after this is done there will be no problem applying it 1 time, 2 times or more.

You can find all the documentation about the layer here, but let me give you a recap which hopefully will help to understand more the errors you're getting.
First of all nn.Conv2d inputs are 4-d tensors of the shape (BatchSize, ChannelsIn, Height, Width) and outputs are 4-d tensors of the shape (BatchSize, ChannelsOut, HeightOut, WidthOut). The simplest way to think about nn.Conv2d is of something applied to 2d images with pixel grid of size Height x Width and having ChannelsIn different colors or features per pixel. Even if your inputs have nothing to do with actual images the behavior of the layer is still the same. Simplest situation is when the nn.Conv2d is not using padding (as in your code). In that case the kernel_size=(kernel_height, kernel_width) argument specifies the rectangle which you can imagine sweeping through Height x Width rectangle of your inputs and producing one pixel for each valid position. Without padding the coordinate of the rectangle's point can be any pair of indicies (x, y) with x between 0 and Height - kernel_height and y between 0 and Width - kernel_width. Thus the output will look like a 2d image of size (Height - kernel_height + 1) x (Width - kernel_width + 1) and will have as many output channels as specified to nn.Conv2d constructor, so the output tensor will be of shape (BatchSize, ChannelsOut, Height - kernel_height + 1, Width - kernel_width + 1).

The parameter groups is not affecting how shapes are changed by the layer - it is only controlling which input channels are used as inputs for the output channels (groups=1 means that every input channel is used as input for every output channel, otherwise input and output channels are divided into corresponding number of groups and only input channels from group i are used as inputs for the output channels from group i).

Now in your current version of the code you have BatchSize = 16 and the output of pre-trained model is (BatchSize, DynamicSize, 768) with DynamicSize depending on the input, e.g. 22. You then introduce additional dimension as axis 1 with unsqueeze and repeat the values along that dimension transforming the tensor of shape (16, 22, 768) into (16, 12, 22, 768). Effectively you are using the output of the pre-trained model as 12-channel (with each channel having same values as others) 2-d images here of size (22, 768), where 22 is not fixed (depends on the batch). Then you apply a nn.Conv2d with kernel size (3, 768) - which means that there is no "wiggle room" for width and output 2-d images will be of size (20, 1) and since your layer has 192 channels final size of the output of first convolution layer has shape (16, 192, 20, 1). Then you try to apply second layer of convolution on top of that with kernel size (3, 768) again, but since your 2-d "image" is now just (20 x 1) there is no valid position to fit (3, 768) kernel rectangle inside a rectangle (20 x 1) which leads to the error message Kernel size can't be greater than actual input size.

Hope this explanation helps. Now to the choices you have to avoid the issue:

(a) is to add padding in such a way that the size of the output is not changing  comparing to input (I won't go into details here,
because I don't think this is what you need)
(b) Use smaller kernel on both first and/or second convolutions (e.g. if you don't change first convolution the only valid width for
the second kernel would be 1).
(c) Looking at what you're trying to do my guess is that you actually don't want to use 2d convolution, you want 1d convolution (on the sequence) with every position described by 768 values. When you're using one convolution layer with 768 width kernel (and same 768 width input) you're effectively doing exactly same thing as 1d convolution with 768 input channels, but then if you try to apply second one you have a problem. You can specify kernel width as 1 for the next layer(s) and that will work for you, but a more correct way would be to transpose pre-trained model's output tensor by switching the last dimensions - getting shape (16, 768, DynamicSize) from (16, DynamicSize, 768) and then apply nn.Conv1d layer with 768 input channels and arbitrary ChannelsOut as output channels and 1d kernel_size=3 (meaning you look at 3 consecutive elements of the sequence for convolution). If you do that than without padding input shape of (16, 768, DynamicSize) will become (16, ChannelsOut, DynamicSize-2), and after you apply second Conv1d with e.g. the same settings as first one you'll get a tensor of shape (16, ChannelsOut, DynamicSize-4), etc. (each time the 1d length will shrink by kernel_size-1). You can always change number of channels/kernel_size for each subsequent convolution layer too.


Instruction: Pytorch can't convert np.ndarray of type numpy.object

Input:
I am trying to create a PyTorch data-loader with variable image size. Here is a snippet of my code

def get_imgs(path_to_imgs):

    imgs = []
    for path in path_to_imgs:

        imgs.append(cv2.imread(path))

    imgs = np.asarray(imgs)

    return imgs

The function above takes a list of paths and loads the images from the path to the list 'imgs'. BTW the images are not equal-sized. The list looks like imgs = [NumPy array, NumPy array ....]. However, when I convert the list to np.asarray it turns the list into dtype = object.

This is my dataloader class

class Dataset(torch.utils.data.Dataset):

  def __init__(self, path_to_imgs, path_to_label):
        'Initialization'
        self.path_to_imgs = path_to_imgs
        self.path_to_label = path_to_label

        self.imgs = get_imgs(path_to_imgs)
        self.label = get_pts(path_to_label)

        self.imgs = torch.Tensor(self.imgs)             **Error here
        # self.imgs = torch.from_numpy(self.imgs)       ** I tried this as well. Same error

        self.label = torch.Tensor(self.label)

        self.len = len(self.imgs)

  def __len__(self):
        'Denotes the total number of samples'
        return self.len

  def __getitem__(self, index):

        return self.imgs, self.label

When I try to convert the list of images to tensor** it fails giving the following error

  can't convert np.ndarray of type numpy.object_. The only supported types are: float64, float32, float16, int64, int32, int16, int8, uint8, and bool.

I have looked similar questions here and here but they were not helpful.

Output:
def get_imgs(path_to_imgs):

    imgs = []
    for path in path_to_imgs:
        imgs.append(torch.Tensor(cv2.imread(path)))

    return imgs

class Dataset(torch.utils.data.Dataset):
    def __init__(self, path_to_imgs, path_to_label):
        'Initialization'
        self.path_to_imgs = path_to_imgs
        self.path_to_label = path_to_label

        self.imgs = get_imgs(path_to_imgs)
        self.label = get_pts(path_to_label)

        # padding ops here (https://pytorch.org/docs/stable/nn.html#padding-layers)
        # for img in self.imgs:
        #     ...

        self.label = torch.Tensor(self.label)

        self.len = len(self.imgs)

    def __len__(self):
        'Denotes the total number of samples'
        return self.len

    def __getitem__(self, index):

        return self.imgs, self.label


Instruction: how convert string to path in opemnmt-py

Input:
I use opennmt-py for MT and in the code any time I want to set a path I have to write all directory and it's not good looking when I have long directory. is there any way to set a string as the main directory and just add the file name to the end.
I use google colab to train the model
The code is like:

!onmt_preprocess  \\
-train_src //content//drive//My\ Drive//Colab\ Notebooks//NLP//spring99//CA6//Corpora//En2Fa-Translation//train.en \\
-train_tgt //content//drive//My\ Drive//Colab\ Notebooks//NLP//spring99//CA6//Corpora//En2Fa-Translation//train.fa \\
-valid_src //content//drive//My\ Drive//Colab\ Notebooks//NLP//spring99//CA6//Corpora//En2Fa-Translation//dev.en \\
-valid_tgt  //content//drive//My\ Drive//Colab\ Notebooks//NLP//spring99//CA6//Corpora//En2Fa-Translation//dev.fa \\
-save_data //content//drive//My\ Drive//Colab\ Notebooks//NLP//spring99//CA6//Corpora//En2Fa-Translation//demo//

and the code I want to be like:

path ='//content//dri`ve//My\ Drive//Colab\ Notebooks//NLP//spring99//CA6//Corpora//En2Fa-Translation//'

!onmt_preprocess  \\
-train_src path+'train.en' \\
-train_tgt path+'train.fa' \\
-valid_src path+'dev.en' \\
-valid_tgt  path++'dev.fa' \\
-save_data path+'demo//'

or maybe just can write all path in a variable and use it like:

path_train ='//content//dri`ve//My\ Drive//Colab\ Notebooks//NLP//spring99//CA6//Corpora//En2Fa-Translation//'

!onmt_preprocess  \\
-train_src path_train \\

Output:
You may use a mere concatenation:

path='//content//drive//My\ Drive//Colab\ Notebooks//NLP//spring99//CA6//Corpora//En2Fa-Translation//'
!onmt_preprocess  \\
  -train_src $path'train.en' \\
  -train_tgt $path'train.fa' \\
  -valid_src $path'dev.en' \\
  -valid_tgt $path'dev.fa' \\
  -save_data $path'demo//'

Notes:

The variable path must be followed with =, not a space. There must be no spaces around =. The path = 'text' is wrong, path ='text' is wrong, path= 'text' is also wrong.
When you use a variable, prepend it with $: !echo $path'train.en' will print //content//drive//My Drive//Colab Notebooks//NLP//spring99//CA6//Corpora//En2Fa-Translation//train.en
Concatenation means just glueing string literals to variables no need using +, &, etc.


Instruction: LSTM cell implementation in Pytorch design choices

Input:
I was looking for an implementation of an LSTM cell in Pytorch that I could extend, and I found an implementation of it in the accepted answer here. I will post it here because I'd like to refer to it. There are quite a few implementation details that I do not understand, and I was wondering if someone could clarify.

import math
import torch as th
import torch.nn as nn

class LSTM(nn.Module):

    def __init__(self, input_size, hidden_size, bias=True):
        super(LSTM, self).__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.bias = bias
        self.i2h = nn.Linear(input_size, 4 * hidden_size, bias=bias)
        self.h2h = nn.Linear(hidden_size, 4 * hidden_size, bias=bias)
        self.reset_parameters()

    def reset_parameters(self):
        std = 1.0 / math.sqrt(self.hidden_size)
        for w in self.parameters():
            w.data.uniform_(-std, std)

    def forward(self, x, hidden):
        h, c = hidden
        h = h.view(h.size(1), -1)
        c = c.view(c.size(1), -1)
        x = x.view(x.size(1), -1)

        # Linear mappings
        preact = self.i2h(x) + self.h2h(h)

        # activations
        gates = preact[:, :3 * self.hidden_size].sigmoid()
        g_t = preact[:, 3 * self.hidden_size:].tanh()
        i_t = gates[:, :self.hidden_size]
        f_t = gates[:, self.hidden_size:2 * self.hidden_size]
        o_t = gates[:, -self.hidden_size:]

        c_t = th.mul(c, f_t) + th.mul(i_t, g_t)

        h_t = th.mul(o_t, c_t.tanh())

        h_t = h_t.view(1, h_t.size(0), -1)
        c_t = c_t.view(1, c_t.size(0), -1)
        return h_t, (h_t, c_t)

1- Why multiply the hidden size by 4 for both self.i2h and self.h2h (in the init method)

2- I don't understand the reset method for the parameters. In particular, why do we reset parameters in this way?

3- Why do we use view for h, c, and x in the forward method?

4- I'm also confused about the column bounds in the activations part of the forward method. As an example, why do we upper bound with 3 * self.hidden_size for gates?

5- Where are all the parameters of the LSTM? I'm talking about the Us and Ws here:

Output:
  1- Why multiply the hidden size by 4 for both self.i2h and self.h2h (in the init method)

In the equations you have included, the input x and the hidden state h are used for four calculations, where each of them is a matrix multiplication with a weight. Whether you do four matrix multiplications or concatenate the weights and do one bigger matrix multiplication and separate the results afterwards, has the same result.

input_size = 5
hidden_size = 10

input = torch.randn((2, input_size))

# Two different weights
w_c = torch.randn((hidden_size, input_size))
w_i = torch.randn((hidden_size, input_size))

# Concatenated weights into one tensor
# with size:[2 * hidden_size, input_size]
w_combined = torch.cat((w_c, w_i), dim=0)

# Output calculated by using separate matrix multiplications
out_c = torch.matmul(w_c, input.transpose(0, 1))
out_i = torch.matmul(w_i, input.transpose(0, 1))

# One bigger matrix multiplication with the combined weights
out_combined = torch.matmul(w_combined, input.transpose(0, 1))
# The first hidden_size number of rows belong to w_c
out_combined_c = out_combined[:hidden_size]
# The second hidden_size number of rows belong to w_i
out_combined_i = out_combined[hidden_size:]

# Using torch.allclose because they are equal besides floating point errors.
torch.allclose(out_c, out_combined_c) # => True
torch.allclose(out_i, out_combined_i) # => True

By setting the output size of the linear layer to 4 * hidden_size there are four weights with size hidden_size, so only one layer is needed instead of four. There is not really an advantage of doing this, except maybe a minor performance improvement, mostly for smaller inputs that don't fully exhaust the parallelisations capabilities if done individually.

  4- I'm also confused about the column bounds in the activations part of the forward method. As an example, why do we upper bound with 3 * self.hidden_size for gates?

That's where the outputs are separated to correspond to the output of the four individual calculations. The output is the concatenation of  [i_t; f_t; o_t; g_t] (not including tanh and sigmoid respectively).

You can get the same separation by splitting the output into four chunks with torch.chunk:

i_t, f_t, o_t, g_t = torch.chunk(preact, 4, dim=1)

But after the separation you would have to apply torch.sigmoid to i_t, f_t and o_t, and torch.tanh to g_t.

  5- Where are all the parameters of the LSTM? I'm talking about the Us and Ws here:

The parameters W are the weights in the linear layer self.i2h and U in the linear layer self.h2h, but concatenated.

W_i, W_f, W_o, W_c = torch.chunk(self.i2h.weight, 4, dim=0)

U_i, U_f, U_o, U_c = torch.chunk(self.h2h.weight, 4, dim=0)

  3- Why do we use view for h, c, and x in the forward method?

Based on h_t = h_t.view(1, h_t.size(0), -1) towards the end, the hidden states have the size [1, batch_size, hidden_size]. With h = h.view(h.size(1), -1) that gets rid of the first singular dimension to get size [batch_size, hidden_size]. The same could be achieved with h.squeeze(0).

  2- I don't understand the reset method for the parameters. In particular, why do we reset parameters in this way?

Parameter initialisation can have a big impact on the model's learning capability. The general rule for the initialisation is to have values close to zero without being too small. A common initialisation is to draw from a normal distribution with mean 0 and variance of 1 / n, where n is the number of neurons, which in turn means a standard deviation of 1 / sqrt(n).

In this case it uses a uniform distribution instead of a normal distribution, but the general idea is similar. Determining the minimum/maximum value based on the number of neurons but avoiding to make them too small. If the minimum/maximum value would be 1 / n the values would get very small, so using 1 / sqrt(n) is more appropriate, e.g. 256 neurons: 1 / 256 = 0.0039 whereas 1 / sqrt(256) = 0.0625.

Initializing neural networks provides some explanations of different initialisations with interactive visualisations.


Instruction: RuntimeError: Error(s) in loading state_dict for Actor - torch.load()

Input:
I have created a custom environment in open ai gym  and i am facing error while loading the weights Could some one help me to resolve the issue . I am training a TD3 network in a custom environment and i have trained successfully but while inferencing i am facing this issue

class Actor(nn.Module):

  def __init__(self, state_dim, action_dim, max_action):
    super(Actor, self).__init__()
    self.layer_1 = nn.Linear(state_dim, 400)
    self.layer_2 = nn.Linear(400, 300)
    self.layer_3 = nn.Linear(300, action_dim)
    self.max_action = max_action

  def forward(self, x):
    x = F.relu(self.layer_1(x))
    x = F.relu(self.layer_2(x))
    x = self.max_action * torch.tanh(self.layer_3(x))
    return x

class Critic(nn.Module):

  def __init__(self, state_dim, action_dim):
    super(Critic, self).__init__()
    # Defining the first Critic neural network
    self.layer_1 = nn.Linear(state_dim + action_dim, 400)
    self.layer_2 = nn.Linear(400, 300)
    self.layer_3 = nn.Linear(300, 1)
    # Defining the second Critic neural network
    self.layer_4 = nn.Linear(state_dim + action_dim, 400)
    self.layer_5 = nn.Linear(400, 300)
    self.layer_6 = nn.Linear(300, 1)

  def forward(self, x, u):
    xu = torch.cat([x, u], 1)
    # Forward-Propagation on the first Critic Neural Network
    x1 = F.relu(self.layer_1(xu))
    x1 = F.relu(self.layer_2(x1))
    x1 = self.layer_3(x1)
    # Forward-Propagation on the second Critic Neural Network
    x2 = F.relu(self.layer_4(xu))
    x2 = F.relu(self.layer_5(x2))
    x2 = self.layer_6(x2)
    return x1, x2

  def Q1(self, x, u):
    xu = torch.cat([x, u], 1)
    x1 = F.relu(self.layer_1(xu))
    x1 = F.relu(self.layer_2(x1))
    x1 = self.layer_3(x1)
    return x1

# Selecting the device (CPU or GPU)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# Building the whole Training Process into a class

class TD3(object):

  def __init__(self, state_dim, action_dim, max_action):
    self.actor = Actor(state_dim, action_dim, max_action).to(device)
    self.actor_target = Actor(state_dim, action_dim, max_action).to(device)
    self.actor_target.load_state_dict(self.actor.state_dict())
    self.actor_optimizer = torch.optim.Adam(self.actor.parameters())
    self.critic = Critic(state_dim, action_dim).to(device)
    self.critic_target = Critic(state_dim, action_dim).to(device)
    self.critic_target.load_state_dict(self.critic.state_dict())
    self.critic_optimizer = torch.optim.Adam(self.critic.parameters())
    self.max_action = max_action

  def select_action(self, state):
    state = torch.Tensor(state.reshape(1, -1)).to(device)
    return self.actor(state).cpu().data.numpy().flatten()

  def train(self, replay_buffer, iterations, batch_size=100, discount=0.99, tau=0.005, policy_noise=0.2, noise_clip=0.5, policy_freq=2):

    for it in range(iterations):

      # Step 4: We sample a batch of transitions (s, s’, a, r) from the memory
      batch_states, batch_next_states, batch_actions, batch_rewards, batch_dones = replay_buffer.sample(batch_size)
      state = torch.Tensor(batch_states).to(device)
      next_state = torch.Tensor(batch_next_states).to(device)
      action = torch.Tensor(batch_actions).to(device)
      reward = torch.Tensor(batch_rewards).to(device)
      done = torch.Tensor(batch_dones).to(device)

      # Step 5: From the next state s’, the Actor target plays the next action a’
      next_action = self.actor_target(next_state)

      # Step 6: We add Gaussian noise to this next action a’ and we clamp it in a range of values supported by the environment
      noise = torch.Tensor(batch_actions).data.normal_(0, policy_noise).to(device)
      noise = noise.clamp(-noise_clip, noise_clip)
      next_action = (next_action + noise).clamp(-self.max_action, self.max_action)

      # Step 7: The two Critic targets take each the couple (s’, a’) as input and return two Q-values Qt1(s’,a’) and Qt2(s’,a’) as outputs
      target_Q1, target_Q2 = self.critic_target(next_state, next_action)

      # Step 8: We keep the minimum of these two Q-values: min(Qt1, Qt2)
      target_Q = torch.min(target_Q1, target_Q2)

      # Step 9: We get the final target of the two Critic models, which is: Qt = r + γ * min(Qt1, Qt2), where γ is the discount factor
      target_Q = reward + ((1 - done) * discount * target_Q).detach()

      # Step 10: The two Critic models take each the couple (s, a) as input and return two Q-values Q1(s,a) and Q2(s,a) as outputs
      current_Q1, current_Q2 = self.critic(state, action)

      # Step 11: We compute the loss coming from the two Critic models: Critic Loss = MSE_Loss(Q1(s,a), Qt) + MSE_Loss(Q2(s,a), Qt)
      critic_loss = F.mse_loss(current_Q1, target_Q) + F.mse_loss(current_Q2, target_Q)

      # Step 12: We backpropagate this Critic loss and update the parameters of the two Critic models with a SGD optimizer
      self.critic_optimizer.zero_grad()
      critic_loss.backward()
      self.critic_optimizer.step()

      # Step 13: Once every two iterations, we update our Actor model by performing gradient ascent on the output of the first Critic model
      if it % policy_freq == 0:
        actor_loss = -self.critic.Q1(state, self.actor(state)).mean()
        self.actor_optimizer.zero_grad()
        actor_loss.backward()
        self.actor_optimizer.step()

        # Step 14: Still once every two iterations, we update the weights of the Actor target by polyak averaging
        for param, target_param in zip(self.critic.parameters(), self.critic_target.parameters()):
          target_param.data.copy_(tau * param.data + (1 - tau) * target_param.data)

        # Step 15: Still once every two iterations, we update the weights of the Critic target by polyak averaging
        for param, target_param in zip(self.actor.parameters(), self.actor_target.parameters()):
          target_param.data.copy_(tau * param.data + (1 - tau) * target_param.data)

  # Making a save method to save a trained model
  def save(self, filename, directory):
    torch.save(self.actor.state_dict(), '%s/%s_actor.pth' % (directory, filename))
    torch.save(self.critic.state_dict(), '%s/%s_critic.pth' % (directory, filename))

  # Making a load method to load a pre-trained model
  def load(self, filename, directory):
    self.actor.load_state_dict(torch.load('%s/%s_actor.pth' % (directory, filename)))
    self.critic.load_state_dict(torch.load('%s/%s_critic.pth' % (directory, filename)))

def evaluate_policy(policy, eval_episodes=10):
  avg_reward = 0.
  for _ in range(eval_episodes):
    obs = env.reset()
    done = False
    while not done:
      action = policy.select_action(np.array(obs))
      obs, reward, done, _ = env.step(action)
      avg_reward += reward
  avg_reward /= eval_episodes
  print ("---------------------------------------")
  print ("Average Reward over the Evaluation Step: %f" % (avg_reward))
  print ("---------------------------------------")
  return avg_reward

env_name = "Pygame-v0"
seed = 0

file_name = "%s_%s_%s" % ("TD3", env_name, str(seed))
print ("---------------------------------------")
print ("Settings: %s" % (file_name))
print ("---------------------------------------")

eval_episodes = 10
save_env_vid = True
env = gym.make(env_name)
max_episode_steps = env._max_episode_steps
if save_env_vid:
  env = wrappers.Monitor(env, monitor_dir, force = True)
  env.reset()
env.seed(seed)
torch.manual_seed(seed)
np.random.seed(seed)
state_dim = env.observation_space.shape[0]
action_dim = env.action_space.shape[0]
max_action = float(env.action_space.high[0])
policy = TD3(state_dim, action_dim, max_action)
#policy.load(file_name, './pytorch_models/')
policy.load(file_name,"/content/gdrive/My Drive/reinforce/gym_game/pytorch_models")
_ = evaluate_policy(policy, eval_episodes=eval_episodes)

Traceback:
I am facing a runtime error while loading the state_dict for actor model .I searched google but couldnt find similar issues .

RuntimeError: Error(s) in loading state_dict for Actor:
    Missing key(s) in state_dict: "layer_1.weight", "layer_1.bias", "layer_2.weight", "layer_2.bias", "layer_3.weight", "layer_3.bias".
    Unexpected key(s) in state_dict: "encoder.0.weight", "encoder.0.bias", "encoder.2.weight", "encoder.2.bias", "encoder.2.running_mean", "encoder.2.running_var", "encoder.2.num_batches_tracked", "encoder.3.weight", "encoder.3.bias", "encoder.5.weight", "encoder.5.bias", "encoder.5.running_mean", "encoder.5.running_var", "encoder.5.num_batches_tracked", "encoder.6.weight", "encoder.6.bias", "encoder.8.weight", "encoder.8.bias", "encoder.8.running_mean", "encoder.8.running_var", "encoder.8.num_batches_tracked", "encoder.10.weight", "encoder.10.bias", "encoder.12.weight", "encoder.12.bias", "encoder.12.running_mean", "encoder.12.running_var", "encoder.12.num_batches_tracked", "encoder.13.weight", "encoder.13.bias", "encoder.15.weight", "encoder.15.bias", "encoder.15.running_mean", "encoder.15.running_var", "encoder.15.num_batches_tracked", "encoder.16.weight", "encoder.16.bias", "linear.0.weight", "linear.0.bias", "linear.2.weight", "linear.2.bias".

Output:
it was answered by @MicaelJungo
The weights you saved were not from the model you are using here. Make sure to load the correct checkpoint, which was created when training this particular model.


Instruction: Why does nn.CrossEntropyLoss throw "TypeError: iteration over a 0-d tensor" when I verify inputs to be non-0-dimensional?

Input:
I am using PyTorch version 1.5.0.
When I pass an input torch tensor of size [8,21,400,400] with a target of size [8,400,400], the program raises a TypeError: iteration over a 0-d tensor. However, the dimensions of the arguments are 4 and 3 respectively.

What could be causing this error?

The traceback points to torch\tensor.py's iter function.

Traceback (most recent call last):
  File "train.py", line 108, in <module>
    loss, accuracy = lossLayer(pred2, targetBatch)
  File "C:\Users\PC\anaconda3\lib\site-packages\torch\tensor.py", line 462, in __iter__
    raise TypeError('iteration over a 0-d tensor')
TypeError: iteration over a 0-d tensor

Output: You get the error because nn.CrossEntropyLoss just returns one torch.Tensor, not a pair (it doesn't return accuracy). And this tensor is 0-dimensional, i.e. one number (unless you don't override reduction argument to 'none' to get per-element loss). So when you try to assign its value to two variables loss, accuracy python tries to iterate over this tensor variable, hence the error message. Simply use loss = lossLayer(pred2, targetBatch).


Instruction: Keras vs Pytorch NN code small differences, need clarification

Input:
I have the Keras and Pytorch code for the same neural network. Some of the lines are switched around between the two.
I am wondering why for the Pytorch version max pooling comes before batch normalization and reel activation. In Keras it comes after those two lines. And for flattening, I'm also confused on how Pytorch used 64 * 7 * 7 (where do the 7s come from?).

Here's the Keras version of the Shallow net Alex net:

def shallownet(nb_classes):
    global img_size
    model = Sequential()
    model.add(Conv2D(64, (5, 5), input_shape=img_size, data_format='channels_first'))
    model.add(BatchNormalization(axis=1))
    model.add(Activation('relu'))
    model.add(MaxPooling2D(pool_size=(3,3), strides=(2,2), padding='same', data_format='channels_first'))

    model.add(Conv2D(64, (5, 5), padding='same', data_format='channels_first'))
    model.add(BatchNormalization(axis=1))
    model.add(Activation('relu'))
    model.add(MaxPooling2D(pool_size=(3,3), strides=(2,2), padding='same', data_format='channels_first'))

    model.add(Flatten())
    model.add(Dense(384))
    model.add(BatchNormalization())
    model.add(Activation('relu'))
    model.add(Dropout(0.5))
    model.add(Dense(192))
    model.add(BatchNormalization())
    model.add(Activation('relu'))
    model.add(Dropout(0.5))
    model.add(Dense(nb_classes, activation='softmax'))
    return model

and the Pytorch version:

class AlexNet(nn.Module):

    def __init__(self, num_classes=10):
        super(AlexNet, self).__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 64, kernel_size=5, padding=2,
                      bias=False),
            nn.MaxPool2d(kernel_size=3, stride=2),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace=True),
            nn.Conv2d(64, 64, kernel_size=5, padding=2, bias=False),
            nn.MaxPool2d(kernel_size=3, stride=2),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace=True),
        )
        self.classifier = nn.Sequential(
            nn.Linear(64 * 7 * 7, 384, bias=False),
            nn.BatchNorm1d(384),
            nn.ReLU(inplace=True),
            nn.Dropout(0.5),
            nn.Linear(384, 192, bias=False),
            nn.BatchNorm1d(192),
            nn.ReLU(inplace=True),
            nn.Dropout(0.5),
            nn.Linear(192, num_classes)
        )
        self.regime = {
            0: {'optimizer': 'SGD', 'lr': 1e-3,
                'weight_decay': 5e-4, 'momentum': 0.9},
            60: {'lr': 1e-2},
            120: {'lr': 1e-3},
            180: {'lr': 1e-4}
        }

    def forward(self, x):
        x = self.features(x)
        x = x.view(-1, 64 * 7 * 7)
        x = self.classifier(x)
        return F.log_softmax(x)

def cifar10_shallow(**kwargs):
    num_classes = getattr(kwargs, 'num_classes', 10)
    return AlexNet(num_classes)

def cifar100_shallow(**kwargs):
    num_classes = getattr(kwargs, 'num_classes', 100)
    return AlexNet(num_classes)

Output:
Max pooling downsamples the data by picking the maximum of a certain pool of values. Comparisons between data will not be affected by batch normalization and ReLU activation because both are one-to-one monotonically increasing functions.

relu(x) = max(0, x)
bn(x) = (x - mu) / sigma

Therefore, it doesn't really matter if max pool comes after or before those two layers (it might be more efficient to have it before).

Regarding the flattening, I believe the 7s are the spatial dimensions of the layer before Flatten() i.e. H = W = 7. Thus, the total number of values is equal to the spatial dimensions times the channel size which is 64 * 7 * 7.


Instruction: Why does the BERT NSP head linear layer have two outputs?

Input:
Here's the code in question.

https://github.com/huggingface/transformers/blob/master/src/transformers/modeling_bert.py#L491

class BertOnlyNSPHead(nn.Module):
    def __init__(self, config):
        super().__init__()
        self.seq_relationship = nn.Linear(config.hidden_size, 2)

    def forward(self, pooled_output):
        seq_relationship_score = self.seq_relationship(pooled_output)
        return seq_relationship_score

I think it was just ranking how likely one sentence would follow another? Wouldn't it be one score?

Output:
The two scores are meant to represent unnormalized probabilities (logits) from the model. If we softmax them, we get our predictions, where index 0 indicates next sentence, and index 1 indicates random.

This is just a stylistic choice on the HuggingFace author's behalf, probably to keep the loss function consistent.

Here's the forward method of BertForPretraining, where self.cls is BertOnlyNSPHead:

    prediction_scores, seq_relationship_score = self.cls(sequence_output, pooled_output)

    outputs = (prediction_scores, seq_relationship_score,) + outputs[
        2:
    ]  # add hidden states and attention if they are here

    if masked_lm_labels is not None and next_sentence_label is not None:
        loss_fct = CrossEntropyLoss()
        masked_lm_loss = loss_fct(prediction_scores.view(-1, self.config.vocab_size), masked_lm_labels.view(-1))
        next_sentence_loss = loss_fct(seq_relationship_score.view(-1, 2), next_sentence_label.view(-1))
        total_loss = masked_lm_loss + next_sentence_loss
        outputs = (total_loss,) + outputs

it's convenient to use the same CrossEntropyLoss for both MLM and NSP.

As you describe, it would be equivalent to have NSP produce a single output, then feed that number through a sigmoid to get probability of the next sentence. We can then train with BCEWithLogitsLoss. (where BCE is just the special binary case of cross entropy loss).


Instruction: What is the least total batch size for SyncBatchNorm

Input:
For the normal BatchNorm, the least batch size per GPU is 2.

I wonder if I use the SyncBatchNorm, can I use batch_size=1 for every GPU with more than a single GPU?

I.e, the total_batch_size is more than 1 but batch_size_per_gpu is 1.

I would appreciate answers for any deep learning framework, pytorch, tensorflow, mxnet, etc

Output: For PyTorch, using batch_size_per_gpu=1 and more than one GPU is fine.


Instruction: Trouble opening audio files stored on S3 in SageMaker

Input: I stored like 300 GB of audio data (mp3/wav mostly) on Amazon S3 and am trying to access it in a SageMaker notebook instance to do some data transformations. I'm trying to use either torchaudio or librosa to load a file as a waveform. torchaudio expects the file path as the input, librosa can either use a file path or file-like object. I tried using s3fs to get the url to the file but torchaudio doesn't recognize it as a file. And apparently SageMaker has problems installing librosa so I can't use that. What should I do?

Output: I ended up not using SageMaker for this, but for anybody else having similar problems, I solved this by opening the file using s3fs and writing it to a tempfile.NamedTemporaryFile. This gave me a file path that I could pass into either torchaudio.load or librosa.core.load. This was also important because I wanted the extra resampling functionality of librosa.core.load, but it doesn't accept file-like objects for loading mp3s.


Instruction: Load data into GPU directly using PyTorch

Input:
In training loop, I load a batch of data into CPU and then transfer it to GPU:

import torch.utils as utils

train_loader = utils.data.DataLoader(train_dataset, batch_size=128, shuffle=True, num_workers=4, pin_memory=True)

for inputs, labels in train_loader:
    inputs, labels = inputs.to(device), labels.to(device)

This way of loading data is very time-consuming. Any way to directly load data into GPU without transfer step ?

Output: You can load all the data to in tensor than move it yo GPU memory.(assuming that you have enough memory) When you need it use the one inside the tensor which is already at GPU memory. Hope it helps.


Instruction: Can't use with import in Pytorch

Input:
When I import torch, there's a problem like this:

C: lUsers / ruiha Desktopl flappy_DQL>python flappy.py
Traceback (most recent call last):
File "flappy.py", line 2, in <module>
import torch
File "C: IUsers I rui ha /AppDat a / Local Programs I Python/ Python37 libIsite-packagesI torchl__init__.py", line 81, in <mod
ctypes.CDLL(dll)
File "C: LUsersI ruiha lAppDat a l Local | Programs I Python/ Python37 liblctypesl__init_.py", line 364, in _init_
self._handle = _dlopen(self._name, mode)
OSError: [WinError 126] The specified module could not be found

Output:
Where are you doing your development? I ask because I see that you are on Windows, where it is much more difficult to manage dll files (compared to Linux). Thus, I would avoid setting up your own bare environment (it would require debugging your OS) and use Anaconda, a Python manager with a focus on scientific computing. Install Anaconda, setup an environment (this is a 'virtual' environment managed by Anaconda), and you will be ready. Simply install torch by

conda install PyTorch -c PyTorch

You can then continue writing your ML app on Jupyter, terminal, etc. by using the Conda runtime to execute your file.


Instruction: How to efficiently find correspondences between two point sets without nested for loop in Pytorch?

Input:
I now have two point sets (tensor) A and B that shape like

A.size() >>(50, 3) , example: [ [0, 0, 0], [0, 1, 2], ..., [1, 1, 1]]

B.size() >>(10, 3)

where the first dimension stands for number of points and the second dim stands for coordinates (x,y,z)

To some extent, the question could also be simplified into " Finding common elements between two tensors ". Is there a quick way to do this without nested loop ?

Output:
You can quickly compute all the 50x10 distances using:

d2 = ((A[:, None, :] - B[None, ...])**2).sum(dim=2)

Once you have all the pair-wise distances, you can select "similar" ones if the distance does not exceed a threshold thr:

(d2 < thr).nonzero()

returns pairs of a-idx, b-idx of "similar" points.

If you want to match the points exactly, you can do instead:

((a[:, None, :] == b[None, ...]).all(dim=2)).nonzero()


Instruction: When to use padding in Conv2d() and when to do ReflectionPad2d() Pytorch

Input:
I have two PyTorch models that are equivalent (I think), the only difference between them is the padding:

import torch
import torch.nn as nn

i = torch.arange(9, dtype=torch.float).reshape(1,1,3,3)
# First model:
model1 = nn.Conv2d(1, 1, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), padding_mode='reflection')
# tensor([[[[-0.6095, -0.0321,  2.2022],
#           [ 0.1018,  1.7650,  5.5392],
#           [ 1.7988,  3.9165,  5.6506]]]], grad_fn=<MkldnnConvolutionBackward>)

# Second model:
model2 = nn.Sequential(nn.ReflectionPad2d((1, 1, 1, 1)),
             nn.Conv2d(1, 1, kernel_size=3))
# tensor([[[[1.4751, 1.5513, 2.6566],
#           [4.0281, 4.1043, 5.2096],
#           [2.6149, 2.6911, 3.7964]]]], grad_fn=<MkldnnConvolutionBackward>)

I was wondering why and when you use both approaches, the output of both is different but as I see it they should be the same, because the padding is of type reflection.

Would appreciate some help in understanding it.

EDIT

After what @Ash said, I wanted to check wheter or not the weights had influence so I pinned all of them to the same value and still there is a difference between the 2 methods:

import torch
import torch.nn as nn

i = torch.arange(9, dtype=torch.float).reshape(1,1,3,3)
# First model:
model1 = nn.Conv2d(1, 1, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), padding_mode='reflection')
model1.weight.data = torch.full(model1.weight.data.shape, 0.4)
print(model1(i))
print(model1.weight)
# tensor([[[[ 3.4411,  6.2411,  5.0412],
#           [ 8.6411, 14.6411, 11.0412],
#           [ 8.2411, 13.4411,  9.8412]]]], grad_fn=<MkldnnConvolutionBackward>)
# Parameter containing:
# tensor([[[[0.4000, 0.4000, 0.4000],
#           [0.4000, 0.4000, 0.4000],
#           [0.4000, 0.4000, 0.4000]]]], requires_grad=True)

# Second model:
model2 = [nn.ReflectionPad2d((1, 1, 1, 1)),
             nn.Conv2d(1, 1, kernel_size=3)]
model2[1].weight.data = torch.full(model2[1].weight.data.shape, 0.4)
model2 = nn.Sequential(*model2)
print(model2(i))
print(model2[1].weight)
# tensor([[[[ 9.8926, 11.0926, 12.2926],
#           [13.4926, 14.6926, 15.8926],
#           [17.0926, 18.2926, 19.4926]]]], grad_fn=<MkldnnConvolutionBackward>)
# Parameter containing:
# tensor([[[[0.4000, 0.4000, 0.4000],
#           [0.4000, 0.4000, 0.4000],
#           [0.4000, 0.4000, 0.4000]]]], requires_grad=True)

Output:
  the output of both is different but as I see it they should be the same

I don't think that the different outputs that you get are only related to how the reflective padding is implemented. In the code snippet that you provide, the values of the weights and biases of the convolutions from model1 and model2 differ, since they are initialized randomly and you don't seem to fix their values in the code.

EDIT:

Following your new edit, it seems that for versions prior to 1.5, looking at  the implementation of the forward pass in <your_torch_install>/nn/modules/conv.pyshows that "reflection" is not supported. It wont complain about arbitrary strings instead of "reflection" either, but will default to zero-padding.


Instruction: Memory Leak in loop pytorch

Input:
The following loop is not discarding any of the tensors it makes after each iteration of the loop leading to a memory leak. It is due to the use of grad_loss.backward() in the below code. Is there anything I'm missing or is there an issue with pytorch.

    for (images, one_hot_labels) in tqdm(batched_train_data):
        # I collect batch size here because the last batch may have a smaller batch_size
        images = images.to(device)
        one_hot_labels = one_hot_labels.to(device)

        batch_size = images.shape[0]

        images.requires_grad = True
        optimizer.zero_grad()
        # as images is not a parameters optimizer.zero_grad() won't reset it's gradient
        if images.grad is not None:
            images.grad.data.zero_()

        probabilities = model.forward(images)

        # I want to use .backward() twice rather than autograd because I want to accumulate the gradients
        loss = loss_func(probabilities, one_hot_labels)
        loss.backward(create_graph=True)
        grad_loss = grad_loss_func(images.grad)
        grad_loss.backward()

        optimizer.step()

        labels = one_hot_labels.detach().argmax(dim=1)
        predictions = probabilities.detach().argmax(dim=1)
        num_correct = int(predictions.eq(labels).sum())

        train_data_length += batch_size
        train_correct += num_correct
        train_loss += float(loss.detach()) * batch_size

        writer.add_graph(model, images)
        writer.close()

        # To stop memory leaks
        del images
        del one_hot_labels
        del probabilities
        del loss
        del grad_loss
        del labels
        del predictions
        del num_correct

Output:
To fix it you need to replace

images.grad.data.zero_()

with

images.grad = None

I believe this is because doing images.grad.data.zero_() does not remove any computation graph associated with images therefore allowing the graph to grow as you loop through.

On a separate note, I've also been advised that you should avoid operating upon .data whenever possible as it's unsafe to do so.


Instruction: Extract features from pretrained resnet50 in pytorch

Input:
Hy guys, i want to extract the in_features of Fully connected layer of my pretrained resnet50.

I create before a method that give me the vector of features:

def get_vector(image):

#layer = model._modules.get('fc')

layer = model.fc
my_embedding = torch.zeros(2048) #2048 is the in_features of FC , output of avgpool

def copy_data(m, i, o):

    my_embedding.copy_(o.data)

h = layer.register_forward_hook(copy_data)
tmp = model(image)

h.remove()

# return the vector
return my_embedding

after I call this method here:

column = ["FlickrID", "Features"]

path = "./train_dataset/train_imgs/"

pathCSV = "./train_dataset/features/img_info_TRAIN.csv"

f_id=[]
features_extr=[]

df = pd.DataFrame(columns=column)

tr=transforms.Compose([transforms.Resize(256),
                       transforms.CenterCrop(224),
                       transforms.ToTensor(),
                       transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])

test = Dataset(path, pathCSV, transform=tr)

test_loader = DataLoader(test, batch_size=1, num_workers=2, shuffle = False)

#Leggiamo le immagini
for batch in test_loader:
    nome = batch['FlickrID']
    f_id.append(nome)
    image = batch['image']

    #print(image)
    with torch.no_grad():
        pred = get_vector(image)

    features_extr.append(pred)

df["FlickrID"] = f_id
df["Features"] = features_extr

df.to_hdf("Places.h5", key='df', mode='w')

I have an error like this:
output with shape [2048] doesn't match the broadcast shape [1, 2048, 1, 2048]

How can I take the in_feature of Fully Connected of this resnet50?
The Dataset is a customized Dataset class.

Sorry for my bad english

Output:
The model takes batched inputs, that means the input to the fully connected layer has size [batch_size, 2048]. Because you are using a batch size of 1, that becomes [1, 2048]. Therefore that doesn't fit into a the tensor torch.zeros(2048), so it should be torch.zeros(1, 2048) instead.

You are also trying to use the output (o) of the layer model.fc instead of the input (i).

Besides that, using hooks is overly complicated for this and a much easier way to get features is to modify the model by replacing model.fc with nn.Identity, which just returns the input as the output, and since the features are its input, the output of the entire model will be the features.

model.fc = nn.Identity()

features = model(image)


Instruction: Testing an implementation of an LSTM in Pytorch

Input:
I'm trying to use the Pytorch implementation of an LSTM here. I'm including it here for reference. It consists of two classes, LSTMCell and LSTM, where LSTMCell is just a single unit and LSTM puts stacks multiple units together to create a full LSTM model

import math
import torch as th
import torch.nn as nn

class LSTMCell(nn.Module):

    def __init__(self, input_size, hidden_size, bias=True):
        super(LSTM, self).__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.bias = bias
        self.i2h = nn.Linear(input_size, 4 * hidden_size, bias=bias)
        self.h2h = nn.Linear(hidden_size, 4 * hidden_size, bias=bias)
        self.reset_parameters()

    def reset_parameters(self):
        std = 1.0 / math.sqrt(self.hidden_size)
        for w in self.parameters():
            w.data.uniform_(-std, std)

    def forward(self, x, hidden):
        if hidden is None:
            hidden = self._init_hidden(x)

        h, c = hidden
        h = h.view(h.size(1), -1)
        c = c.view(c.size(1), -1)
        x = x.view(x.size(1), -1)

        # Linear mappings
        preact = self.i2h(x) + self.h2h(h)

        # activations
        gates = preact[:, :3 * self.hidden_size].sigmoid()
        g_t = preact[:, 3 * self.hidden_size:].tanh()
        i_t = gates[:, :self.hidden_size]
        f_t = gates[:, self.hidden_size:2 * self.hidden_size]
        o_t = gates[:, -self.hidden_size:]

        c_t = th.mul(c, f_t) + th.mul(i_t, g_t)

        h_t = th.mul(o_t, c_t.tanh())

        h_t = h_t.view(1, h_t.size(0), -1)
        c_t = c_t.view(1, c_t.size(0), -1)
        return h_t, (h_t, c_t)

    @staticmethod
    def _init_hidden(input_):
        h = th.zeros_like(input_.view(1, input_.size(1), -1))
        c = th.zeros_like(input_.view(1, input_.size(1), -1))
        return h, c

class LSTM(nn.Module):

    def __init__(self, input_size, hidden_size, bias=True):
        super().__init__()
        self.lstm_cell = LSTMCell(input_size, hidden_size, bias)

    def forward(self, input_, hidden=None):
        # input_ is of dimensionalty (1, time, input_size, ...)

        outputs = []
        for x in torch.unbind(input_, dim=1):
            hidden = self.lstm_cell(x, hidden)
            outputs.append(hidden[0].clone())

        return torch.stack(outputs, dim=1)

I'm doing the following simple test:

x = torch.randn(1, 3, 2, 4)
model = LSTM(4, 5, False)
model(x)

and I get the following error. What exactly is the problem here?

TypeError                                 Traceback (most recent call last)
<ipython-input-33-09e5544a61fc> in <module>
----> 1 model = LSTM(4, 5, False)

<ipython-input-30-9ad06cd4b768> in __init__(self, input_size, hidden_size, bias)
      3     def __init__(self, input_size, hidden_size, bias=True):
      4         super().__init__()
----> 5         self.lstm_cell = LSTMCell(input_size, hidden_size, bias)
      6
      7     def forward(self, input_, hidden=None):

<ipython-input-29-c91ddfb9dfae> in __init__(self, input_size, hidden_size, bias)
      6
      7     def __init__(self, input_size, hidden_size, bias=True):
----> 8         super(LSTM, self).__init__()
      9         self.input_size = input_size
     10         self.hidden_size = hidden_size

TypeError: super(type, obj): obj must be an instance or subtype of type

Output:
The first argument to super() should be class itself, not a different class.

class LSTMCell(nn.Module):

    def __init__(self, input_size, hidden_size, bias=True):
        super(LSTM, self).__init__()
#             ^^^^ self is not an instance of LSTM but LSTMCell

It should be:

super(LSTMCell, self).__init__()

Since Python 3 you can omit the arguments to super to get the same result (as you have done in the LSTM class):

super().__init__()


Instruction: Implementation Issue: Deep ConvNet for Pattern Recognition

Input:
I'm trying to implement a pattern recognition model using a fully convolutional network (fig 1 in https://www.sciencedirect.com/science/article/pii/S0031320318304370, I was able to get the full text without signing in or anything but if it's a problem I can attach a picture too!) but I'm getting a size error when moving from the final Conv2D layer to the first fc_layer.

Here is my error message:

RuntimeError: size mismatch, m1: [4 x 1024], m2: [4 x 1024] at /pytorch/aten/src/THC/generic/THCTensorMathBlas.cu:283

Originally, as in the figure, my first linear layer was:

nn.Linear(4*4*512, 1024)

but after getting the size mismatch, I changed it to:

nn.Linear(4,1024)

Now, I have a strange error message as written above.

For reference (if it helps), here is my code:

import torch.nn as nn
import torch.utils.model_zoo as model_zoo

class convnet(nn.Module):

    def __init__(self, num_classes=1000):
        super(convnet, self).__init__()
        self.features = nn.Sequential(
            nn.Conv2d(1, 64, kernel_size=3, stride=2, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(64, 64, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(64, 64, kernel_size=3, padding=1),
            nn.MaxPool2d(kernel_size=1),
            nn.Conv2d(64, 128, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(128, 128, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2),# stride=2),
            nn.Conv2d(128, 256, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(256, 256, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2), #stride=2),
            nn.Conv2d(256, 512, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(512, 512, kernel_size=3, padding=1),
            nn.ReLU(inplace=True), #nn.Dropout(p=0.5)
        )

        self.classifier = nn.Sequential(
            nn.Linear(4, 1024),
            nn.Dropout(p=0.5),
            nn.ReLU(inplace=True),
            #nn.Dropout(p=0.5),
            nn.Linear(1024, 1024),
            nn.ReLU(inplace=True),
            nn.Linear(1024, num_classes),
        )

    def forward(self, x):
        x = self.features(x)
        x = torch.flatten(x,1)
        x = self.classifier(x)
        return x

I suspect it's an issue with the padding and stride.
Thanks!

Output:
The error is from a matrix multiplication, where m1 should be an m x n matrix and m2 an n x p matrix and the result would be an m x p matrix. In your case it's 4 x 1024 and 4 x 1024, but that doesn't work since 1024 != 4.

That means your input to the first linear layer has size [4, 1024] (4 being the batch size), therefore the input features of the first linear layer should be 1024.

self.classifier = nn.Sequential(
    nn.Linear(1024, 1024),
    nn.Dropout(p=0.5),
    nn.ReLU(inplace=True),
    #nn.Dropout(p=0.5),
    nn.Linear(1024, 1024),
    nn.ReLU(inplace=True),
    nn.Linear(1024, num_classes),
)

If you are uncertain how many features your input has, you can print out its size just before the layer:

x = self.features(x)
x = torch.flatten(x,1)
print(x.size()) # => torch.Size([4, 1024])
x = self.classifier(x)


Instruction: Test Time Augmentation throwing a value error

Input:
I am trying to use the Test Time Augmentation on my Classifier:

log_preds,y = learn.TTA(scale=1.1, ds_type=DatasetType.Valid, with_loss=True)

And this is the error that it threw:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-14-f33d9737819a> in <module>()
----> 1 log_preds,y = learn.TTA(scale=1.1, ds_type=DatasetType.Valid, with_loss=True)
      2 probs = np.mean(np.exp(log_preds),0)
      3
      4 accuracy(probs, y)

ValueError: too many values to unpack (expected 2)

Initially, I tried to find a way to use my custom test set in TTA but couldn’t figure out how to do it and DatasetType.Test was throwing an error so I decided to go with DatasetType.Valid and after running 8 epochs, I got the above error.

Output:
The error message indicate that learn.TTA returns more than 2 values,but you only got log_predsand y for them.
You want to find out what exactly does learn.TTA return


Instruction: RuntimeError: Expected object of device type cuda but got device type cpu for argument #3 'index' in call to _th_index_select site:stackoverflow.com

Input:
I am using the bert on the SMILE dataset. I have written following code can you guide me where I am getting wrong.
I have written training code which is evaluating correctly but the when I try to run evaluate code for validation it is giving error. I tried to pass the parameters directly to cuda. still I am facing the issue

'''

def evaluate(dataloader_val):

  print("in evaluate")
  model.eval()

  loss_val_total = 0
  predictions, true_value = [],[]

  for batch in dataloader_val:

    print("in for loop of dataloader")
    barch = tuple(b.to(device) for b in batch)

    inputs = {
               'input_ids':  batch[0],
                'attention_mask': batch[1],
                 'labels' : batch[2],
    }

    with torch.no_grad():
      outputs = model(**inputs)

    loss = outputs[0]
    logits = outputs[1]
    loss_val_total += loss.item()

    print("before logit")

    logits = logits.to(device)
    print("in the for batch evaluate: ",logits)
    label_ids = inputs['labels'].to(device)
    true_vals.append(label_ids)

  loss_val_avg = loss_val_total/len(dataloader_val)

  predictions = np.concatenate(predictions, axis = 0)
  true_vals = np.concatenate(true_vals,axis = 0)

  return loss_val_avg, predictions, true_vals
'''

and another function is

'''
for epoch in tqdm(range(1, epochs+1)):
  model.train()

  loss_train_total = 0

  progress_bar = tqdm(dataloader_train,
                      desc = 'Epoch {:1d}'.format(epoch),
                      leave = False,
                      disable = False)
  for batch in progress_bar:

    model.zero_grad()

    batch = tuple(b.to(device) for b in batch)

    inputs = {

            'input_ids'      : batch[0],
            'attention_mask' : batch[1],
            'labels'         : batch[2]
    }

    outputs = model(**inputs)

    loss = outputs[0]
    loss_train_total += loss.item()
    loss.backward()

    torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)

    optimizer.step()
    scheduler.step()

    progress_bar.set_postfix({'training_loss' : '{:.3f}'.format(loss.item()/len(batch))})

  torch.save(model.state_dict(), f'/content/drive/My Drive/Bert/Coursera/SMILE/Bert_ft_epoch{epoch}.model')

  tqdm.write(f'\n Epoch {epoch}')

  loss_train_avg = loss_train_total / len(dataloader_train)

  tqdm.write(f'Training Loss: {loss_train_avg}')

  val_loss, predictions, true_vals = evaluate(dataloader_val)
  val_f1 = f1_score_func(predictions, true_vals)
  tqdm.write(f'Validation loss : {val_loss}')
  tqdm.write(f'F1 score(weighted): {val_f1}')
'''

Output:
You have a typo in your evaluation function:

barch = tuple(b.to(device) for b in batch)

You assign the gpu data to barch instead of batch.


Instruction: What is the difference between mm and spmm in Pytorch

Input: What is the difference between mm and spmm in Pytorch? I know that spmm does sparse matrix multiplication, but what exactly does that mean? Why would you ever choose mm as opposed to spmm if spmm has the potential to save space?

Output:
In order to use spmm you need your tensor arguments to actually be of sparse type.

Although torch.sparse representation does have the potential of saving space, sparse support does not yet covers all tensor operations and functions.


Instruction: RuntimeError: the derivative for 'indices' is not implemented

Input:
I am following this online tutorial for coding a DQN,https://github.com/philtabor/Youtube-Code-Repository/blob/master/ReinforcementLearning/DeepQLearning/torch_deep_q_model.py
, however I am running into this Runtime Error that I am unsure of how to debug or modify to prevent this error. Thanks!

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-196-00975d66fd2d> in <module>
     28         agent.storeTransition(preprocess(obs),action,reward,preprocess(obs_))
     29         obs= obs_
---> 30         agent.learn(batch_size)
     31         lastAction = action
     32     scores.append(score)

<ipython-input-191-f6b163cc3a8a> in learn(self, batch_size)
     72         Qtarget = Qpred.clone()
     73         print(Qnext[1])
---> 74         Qtarget[:,maxA] = rewards + self.GAMMA*torch.max(Qnext[1])
     75         # epsilon decay action
     76         if self.steps > 2000:

RuntimeError: the derivative for 'indices' is not implemented

These are my code blocks in my jupyter notebook

class DeepQNetwork(nn.Module):
    def __init__(self,Alpha):
        super(DeepQNetwork,self).__init__()
        self.conv1 = nn.Conv2d(1,32,8,stride=4, padding=1)
        self.conv2 = nn.Conv2d(32,64,4,stride=2)
        self.conv3 = nn.Conv2d(64,128,3)
        self.fc1 = nn.Linear(128* 21* 12,512)
        self.fc2 = nn.Linear(512,6)

        self.optimizer = optim.RMSprop(self.parameters(), lr = Alpha)
        self.loss = nn.MSELoss()
        self.device =  torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
        self.to(self.device)

    def forward(self,obs):
        '''Passing in a sequence of arrays'''
        obs = torch.Tensor(obs).to(self.device) # send to the GPU
        ''' Feed forward the Network Parameters'''
        obs = obs.view(-1, 1,200,125)
        #print(obs.shape)
        obs = F.relu(self.conv1(obs))
        #print(obs.shape)
        obs = F.relu(self.conv2(obs))
        #print(obs.shape)
        obs = F.relu(self.conv3(obs))
        #print(obs.shape)
        obs = obs.view(-1,128* 21* 12)
        obs = F.relu(self.fc1(obs))
        # 4 Rows and 6 columns
        actions = self.fc2(obs)
        return actions

This is the Agent Code, and it contains the error causing line of code

class DQNAgent(object):
    def __init__(self, gamma, epsilon, alpha, maxMemory,
                 epsEnd = 0.05, replace =10000, actionSpace = [0,1,2,3,4,5]):
        '''
        Gamma -> discount factor of valuing current reward over future reward
        Epsilon -> for trade off between exploration-exploitation
        alpha -> learn rate
        maxMemory -> max size of Memory buffer
        epsEnd -> smallest value of Exploration
        repace -> how often to replace target network
        '''
        self.GAMMA = gamma
        self.EPSILON = epsilon
        self.EPS_END = epsEnd
        self.actionSpace = actionSpace
        self.maxMemory = maxMemory
        self.steps = 0
        self.learn_step_counter = 0
        self.memory = []
        self.memCount = 0
        self.replace_tgt_count = replace
        self.Q_eval = DeepQNetwork(alpha)
        self.Q_next = DeepQNetwork(alpha)

    def storeTransition(self, state, action, reward, state_):
        '''Stores Transition states'''
        if self.memCount < self.maxMemory:
            self.memory.append([state,action,reward,state_])
        else:
            self.memory[self.memCount%self.maxMemory] = [state,action,reward,state_]
        self.memCount +=1

    def chooseAction(self,obs):
        '''
        Exploration if np.random > epsilon
        else take epsilon greedy action
        '''
        rand = np.random.random()
        # Get the value for all actions for the current set of states
        # Forward pass the stack of frames to get value of each action given subset of staes in obs
        actions = self.Q_eval.forward(obs)
        if rand<1-self.EPSILON:
            action = torch.argmax(actions[1]).item()
        else:
            action = np.random.choice(self.actionSpace)
        self.steps += 1
        return action

    def learn(self, batch_size):
        self.Q_eval.optimizer.zero_grad()
        #0 gradient to do batch optimisation
        if self.replace_tgt_count is not None and self.learn_step_counter % self.replace_tgt_count==0:
            self.Q_next.load_state_dict(self.Q_eval.state_dict())

        # memory subsampling
        if self.memCount + batch_size < self.maxMemory:
            memStart = int(np.random.choice(range(self.memCount)))
        else:
            memStart = int(np.random.choice(range(self.maxMemory-batch_size-1)))

        miniBatch = self.memory[memStart:memStart+batch_size]
        memory = np.array(miniBatch)

        #feed forward current state and successor state conv to list as memory is array of numpy objects
        Qpred = self.Q_eval.forward(list(memory[:,0][:])).to(self.Q_eval.device)
        Qnext = self.Q_next.forward(list(memory[:,3][:])).to(self.Q_eval.device)

        maxA = torch.argmax(Qnext,dim = 1).to(self.Q_eval.device)
        #calculate rewards
        rewards = torch.Tensor(list(memory[:,2])).to(self.Q_eval.device)
        # loss for every action except max action to be 0
        Qtarget = Qpred.clone()
        print(Qnext.shape)
        Qtarget[:,maxA] = rewards + self.GAMMA*torch.max(Qnext[1])# PROBLEMATIC LINE
        # epsilon decay action
        if self.steps > 2000:
            if self.EPSILON-1e-4 >self.EPS_END:
                self.EPSILON-= 1e-4
            else:
                self.EPSILON = self.EPS_END
        loss = self.Q_eval.loss(Qtarget,Qpred).to(self.Q_eval.device)
        loss.backward()
        self.Q_eval.optimizer.step()
        self.learn_step_counter +=1

env = gym.make("Invader-v0")
agent = DQNAgent(gamma=0.95,epsilon = 1.0,alpha = 0.003, maxMemory = 5000,replace = None)
while agent.memCount < agent.maxMemory:
        obs = env.reset()
        done = False
        lives = 3
        while not done:
            action = env.action_space.sample()
            obs_ , reward, done, info = env.step(action)
            if done and info['lives']<lives:
                lives = info['lives']
                reward -= 200
            agent.storeTransition(preprocess(obs),action,reward,preprocess(obs_))
            obs= obs_
initialised = True

scores = []
epsHistory = []
numGames = 50
batch_size = 16

for i in range(numGames):

    print(f'starting game {i+1}, epsilon = {agent.EPSILON}')
    epsHistory.append(agent.EPSILON)
    done = False
    obs = env.reset()

    frames = [np.sum(obs)]
    score = 0
    lastAction = 0
    lives = 3
    while not done:
        if len(frames) == 4:
            action = agent.chooseAction(frames)
            frames = []
        else:
            action = lastAction
        obs_, reward, done, info = env.step(action)
        score += score-reward
        frames.append(preprocess(obs_))
        if done and info['lives'] < lives:
            reward -=200
        agent.storeTransition(preprocess(obs),action,reward,preprocess(obs_))
        obs= obs_
        agent.learn(batch_size)
        lastAction = action
    scores.append(score)
    print('score: ', score)
    x = [i+1 for i in range(numGames)]

Output:
You have to do use .detach() for :

Qnext = self.Q_next.forward(list(memory[:,3][:])).detach().to(self.Q_eval.device)


Instruction: High Loss Validation

Input:
I use the following model to predict the competition: "intel-mobileodt-cervical-cancer-screening".
The labels are divided into 3 categories(1 ,2 ,3).

When I want to do a prediction workout I get the next output

Model:

resnet50 = pretrainedmodels.__dict__["resnet50"](num_classes=1000, pretrained='imagenet')
resnet50.last_linear=torch.nn.Linear(in_features=2048,out_features=3, bias=True)
#optim
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model=model.to(device)
loss_cross=torch.nn.CrossEntropyLoss().cuda()

optim Adam

DataLoader:

class Kaggle_Cancer(Dataset):
  def __init__(self, root_path, transform=None,preprocessing=None,resize=216):
    self.path = root_path
    self.transform=transform
    self.preprocessing=preprocessing
    self.resize=resize

  def __len__(self):
      return len(self.path)

  def __getitem__(self, idx):
    p=self.path[idx]
    image1=cv2.imread(p)
    label=p.split("/")[-2].split("_")[-1]
    image1=cv2.cvtColor(image1,cv2.COLOR_BGR2RGB)
    if self.transform:
      image1=self.transform(image=image1)['image']
    image1=transforms.ToPILImage()(image1)
    image1=transforms.ToTensor()(image1)
    normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225])
    image1=normalize(image1)
    return image1,int(label)

Train :

def train(epoch_number,model,optim,loss):
  model.train()
  all_loss=0
  correct=0
  tqdm_loader=tqdm(training_set)
  for  index,(img,target) in enumerate(tqdm_loader):
    img=img.float().cuda()
    target=target.long().cuda()

    optim.zero_grad()
    out=model(img)
    print(out," target ",target)
    loss1=loss(out,target)
    print(loss1)
    loss1.backward()
    optim.step()
    all_loss+=loss1.item()
    avg_loss=all_loss/(index+1)
    pred=out.argmax(dim=1,keepdim=True)
    correct+=pred.eq(target.view_as(pred)).sum().item()/len(target)

    avg_acc=correct/(index+1)
    tqdm_loader.set_description("Epoch {} train loss={:4}  acc={:4} ".format(epoch_number,round(avg_loss,4),round(avg_acc,4)))

  return avg_loss,avg_acc

output:

print(out," target ",target)

,
        [ 6.1667e-02, -3.9864e-01, -4.1212e-01],
        [-2.3100e-01, -3.7821e-01, -2.8159e-01],
        [-2.9442e-01, -5.0409e-01, -3.1046e-01],
        [ 1.4866e-01, -2.8496e-01, -1.7643e-01],
        [-2.4554e-01, -2.5063e-01, -6.7061e-01],
        [-7.1597e-02, -3.5376e-01, -5.7830e-01],
        [-2.1527e-01, -4.0284e-01, -4.5993e-01],
        [ 1.2050e-02, -5.5684e-01, -1.6044e-01],
        [-3.7750e-02, -5.3680e-01, -4.3820e-01],
        [-1.1966e-01, -2.5146e-01, -4.9405e-01],
        [-2.3308e-01, -6.3452e-01, -3.9821e-01],
        [-3.6530e-01, -1.5242e-01, -2.6457e-01],
        [-1.8864e-01, -6.0979e-01, -5.5342e-01],
        [-2.4755e-01, -4.7011e-01, -2.6204e-01],
        [-3.1907e-01, -4.2680e-01, -3.4576e-01],
        [-2.1872e-01, -5.3857e-01, -2.9729e-01],
        [-7.1475e-02, -4.0458e-01, -3.2042e-01],
        [-2.8925e-01, -4.3376e-02, -4.9899e-01],
        [-4.8227e-02, -1.8701e-01, -2.2106e-01],
        [ 1.7829e-02, -6.5816e-01, -4.0141e-01],
        [-2.7450e-01, -3.9498e-01, -2.3189e-01],
        [-1.8847e-01, -6.8187e-01, -2.0631e-01],
        [-3.5251e-01, -5.3258e-01, -6.3298e-01],
        [-6.5548e-02, -2.5093e-01, -5.4346e-01],
        [ 2.3848e-01, -3.6152e-01, -1.6380e-01],
        [-2.1488e-01, -6.4888e-01, -7.7022e-01],.....

target  tensor([2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 3, 2, 3, 2, 2, 2, 2, 3, 2, 1, 3, 3, 2, 2,
        3, 2, 3, 2, 3, 1, 3, 3, 1, 2, 3, 2, 1, 1, 3, 1, 1, 2, 3, 2, 2, 2, 2, 2,.....

print(loss1)

 1, 2, 3, 3, 1, 3, 1, 3, 3, 2, 3, 3, 2, 3, 2, 3], device='cuda:0'
tensor(1.0870, device='cuda:0', grad_fn=<NllLossBackward>

number epoch =10/20/30:

same result:

val loss=1.2  acc=0.4 train loss=0.6  acc=0.65

What i do wrong?

Output:
When the validation loss is larger than the training loss, It is usually a sign of overfitting. There area few things you can do:

Add Dropout of Batch Normalisation:

This makes the model more robust.

Make the model deeper:

Add more layers to the model for a better comprehension of the patterns.

Use better optimizers:

Adaptive optimizers such as Adam, Adagrad and RMSprop are usually effective.


Instruction: Duplicate element of tensor while perserving gradient values

Input:
So I have a vector that I computed somehow with size k

x = torch.FloatTensor([0.5, 0.3, 0.1, 0.7])
x = x + 2

I want to take its first element x[0] and create a vector of size k-1 filled with the value x[0] so that the gradients that come along with this element are present in the new vector.

I tried using torch.full and filling it up with x[0] but that does not preserve gradients.

Using pytorch 1.4

Output:
You could also use .repeat like this (IMO cleaner and more verbose):

# type deduction is automatic
x = torch.tensor([0.5, 0.3, 0.1, 0.7])
x = x + 2
y = x[0].repeat(50)

Gradient will be preserved (gradient history will be copied).


Instruction: Clip or threshold a tensor using condition and zero pad the result in PyTorch

Input:
let's say I have a tensor like this

w = [[0.1, 0.7, 0.7, 0.8, 0.3],
    [0.3, 0.2, 0.9, 0.1, 0.5],
    [0.1, 0.4, 0.8, 0.3, 0.4]]

Now I want to eliminate certain values base on some condition (for example greater than 0.5 or not)

w = [[0.1, 0.3],
     [0.3, 0.2, 0.1],
     [0.1, 0.4, 0.3, 0.4]]

Then pad it to equal length:

w = [[0.1, 0.3, 0, 0],
     [0.3, 0.2, 0.1, 0],
     [0.1, 0.4, 0.3, 0.4]]

and this is how I implemented it in pytorch:

w = torch.rand(3, 5)
condition = w <= 0.5
w = [w[i][condition[i]] for i in range(3)]
w = torch.nn.utils.rnn.pad_sequence(w)

But apparently this is going to be extremely slow, mainly because of the list comprehension.
is there any better way to do it?

Output:
Here's one straightforward way using boolean masking, tensor splitting, and then eventually padding the splitted tensors using torch.nn.utils.rnn.pad_sequence(...).

# input tensor to work with
In [213]: w
Out[213]:
tensor([[0.1000, 0.7000, 0.7000, 0.8000, 0.3000],
        [0.3000, 0.2000, 0.9000, 0.1000, 0.5000],
        [0.1000, 0.4000, 0.8000, 0.3000, 0.4000]])

# values above this should be clipped from the input tensor
In [214]: clip_value = 0.5

# generate a boolean mask that satisfies the condition
In [215]: boolean_mask = (w <= clip_value)

# we need to sum the mask along axis 1 (needed for splitting)
In [216]: summed_mask = boolean_mask.sum(dim=1)

# a sequence of splitted tensors
In [217]: splitted_tensors = torch.split(w[boolean_mask], summed_mask.tolist())

# finally pad them along dimension 1 (or axis 1)
In [219]: torch.nn.utils.rnn.pad_sequence(splitted_tensors, 1)
Out[219]:
tensor([[0.1000, 0.3000, 0.0000, 0.0000],
        [0.3000, 0.2000, 0.1000, 0.5000],
        [0.1000, 0.4000, 0.3000, 0.4000]])

A short note on efficiency: Using torch.split() is super efficient since it returns the splitted tensors as a view of the original tensor (i.e. no copy is made).


Instruction: How does PyTorch's loss.backward() work when "retain_graph=True" is specified?

Input:
I'm a newbie with PyTorch and adversarial networks. I've tried to look for an answer on the PyTorch documentation and from previous discussions both in the PyTorch and StackOverflow forums, but I couldn't find anything useful.

I'm trying to train a GAN with a Generator and a Discriminator, but I cannot understand if the whole process is working or not. As far as I'm concerned, I should train the Generator first and, then, updating the Discriminator's weights (similarly as this). My code for updating the weights of both models is:

# computing loss_g and loss_d...
optim_g.zero_grad()
loss_g.backward()
optim_g.step()

optim_d.zero_grad()
loss_d.backward()
optim_d.step()

where loss_g is the generator loss, loss_d is the discriminator loss, optim_g is the optimizer referring to the generator's parameters and optim_d is the discriminator optimizer.
If I run the code like this, I get an error:

RuntimeError: Trying to backward through the graph a second time, but the buffers have already been freed. Specify retain_graph=True when calling backward the first time.

So I specify loss_g.backward(retain_graph=True), and here comes my doubt: why should I specify retain_graph=True if there are two networks with two different graphs? Am I getting something wrong?

Output:
Having two different networks doesn't necessarily mean that the computational graph is different. The computational graph only tracks the operations that were performed from the input to the output and it doesn't matter where the operation takes place. In other words, if you use the output of the first model in the second model (e.g. model2(model1(input))), you have the same sequential operations as if they were part of the same model. In fact, that is no different from having different parts of the model, such as multiple convolutions, that you apply one after the other.

The error you get, indicates that you are trying to backpropagate from the discriminator through the generator, which would mean that the discriminator's output directly adapts the generator's parameters for the discriminator to be successful. In an adversarial setting that is precisely what you want to avoid, they should be independent from each other. By setting retrain_graph=True you incorrectly hide this bug. In nearly all cases retain_graph=True is not the solution and should be avoided.

To resolve that issue, the two models need to be made independent from each other. The crossover between the two models happens when you use the generators output for the discriminator, since it should decide whether that was real or fake. Something along these lines:

fake = generator(noise)

real_prediction = discriminator(real)
# Using the output of the generator, continues the graph.
fake_prediction = discriminator(fake)

Even though fake comes from the generator, as far as the discriminator is concerned, it's merely another input, just like real. Therefore fake should be treated the same as real, where it is not attached to any computational graph. That can easily be done with torch.Tensor.detach, which decouples the tensor from the graph.

fake = generator(noise)

real_prediction = discriminator(real)
# Detach to make it independent of the generator
fake_prediction = discriminator(fake.detach())

That is also done in the code you referenced, from erikqu/EnhanceNet-PyTorch - train.py:

hr_imgs = torch.cat([discriminator(hr), discriminator(generated_hr.detach())], dim=0)


Instruction: Convert custom Convolution from PyTorch to Tensorflow (2.2.0)

Input:
I am currently attempting to convert a custom convolution from PyTorch to Tensorflow (V. 2.2.0).

The convolution is defined in PyTorch as:

    self.quantizer = q = nn.Conv1d(1, 2*nq, kernel_size=1, bias=True)
    a = (nq-1) / gap
    #1st half = lines passing to (min+x,1) and (min+x+1/a,0) with x = {nq-1..0}*gap/(nq-1)
    q.weight.data[:nq] = -a
    q.bias.data[:nq] = torch.from_numpy(a*min + np.arange(nq, 0, -1)) # b = 1 + a*(min+x)
    #2nd half = lines passing to (min+x,1) and (min+x-1/a,0) with x = {nq-1..0}*gap/(nq-1)
    q.weight.data[nq:] = a
    q.bias.data[nq:] = torch.from_numpy(np.arange(2-nq, 2, 1) - a*min) # b = 1 - a*(min+x)
    # first and last one are special: just horizontal straight line
    q.weight.data[0] = q.weight.data[-1] = 0
    q.bias.data[0] = q.bias.data[-1] = 1

where nq = 20, min = 0 and max = 1.

My reimplementation looks like this:

my_weight = my_init_weight((1,1,nq*2))
q = tf.nn.convolution(input_q, my_weight)
q = tf.nn.bias_add(q, my_init_bias((40,1), tf.float32))

with these these functions as weight and bias initialization:

def my_init_weight(shape, dtype=None):

    weights = np.zeros(shape, dtype=np.float32)
    weights[:, :, :nq] = -a
    weights[:, :, nq:] = a
    weights[:, :, 0] = weights[:, :, -1] = 0
    return tf.convert_to_tensor(weights, dtype=tf.float32)
def my_init_bias(shape, dtype=None):
    weights = np.zeros(shape[0], dtype=np.float32)
    weights[:nq] = a*min + np.arange(nq, 0, -1)
    weights[nq:] = np.arange(2-nq, 2, 1) - a*min
    weights[0] = weights[-1] = 1
    return weights

The input is a matrix with shape 1681, 1, 1600 for PyTorch (as it uses channels first) and 1681, 1600, 1 for Tensorflow (as it uses channels last) and the out put is 1681, 40, 1600 or 1681, 1600, 40. So it should be correct, however, the output of both convolutions is different.

Input, Output: Tensorflow on a random 100, 100 image:

my_weight = my_init_weight((1,1,nq*2))
my_weight = tf.nn.bias_add(my_weight, my_init_bias((40,1), tf.float32))
q = tf.nn.convolution(test_conv, my_weight)

q_left, q_right = tf.split(q, 2, axis=2)
q = tf.math.minimum(q_left, q_right)
nbs = tf.reduce_sum(q, axis=0)

Input, Output: PyTorch on a random 100, 100 image:

output = q(input_t_t)
output = torch.min(output[:,:nq], output[:,nq:]).clamp(min=0)
nbs = output.sum(dim=-1)

Output:
Okay, I found the solution:

I forgot to add the .clamp(min=0).

Adding q = tf.clip_by_value(q, 0, tf.keras.backend.max(q)) to

my_weight = my_init_weight((1,1,nq*2))
my_weight = tf.nn.bias_add(my_weight, my_init_bias((40,1), tf.float32))
q = tf.nn.convolution(test_conv, my_weight)

q_left, q_right = tf.split(q, 2, axis=2)
q = tf.math.minimum(q_left, q_right)
q = tf.clip_by_value(q, 0, tf.keras.backend.max(q)) <-----------
nbs = tf.reduce_sum(q, axis=0)

fixed the problem.


Instruction: How to compile torch 1.5.0 without GPU support?

Input:
I want to install pytorch 1.5.0 on AWS lambda. Since the torch library is very large, I need to make it as small as possible to fit within the size limits. My script looks like this so far:

    mkdir python
    docker run \
        --rm \
        -v $(pwd):/build \
        python:3.8 \
        sh -c "
            cd /build;
            pip3 install torch==1.5.0 -t python/torch --no-cache-dir;
            find . -type d -name '__pycache__' | xargs rm -rf;
            find . -type d -name 'tests' | xargs rm -rf;
            find . -type f -name '*.py[co]' | xargs rm -rf;
        ";

    zip -r9 torch.zip python;

But the resulting zip file is very large (500+ MB). However, one of the largest files in the installation package is libtorch_cuda.so. Removing that file makes the zip file less than half the size. I know that cuda is a library for GPUs, and since AWS lambda doesn't have a GPU, i don't need this support. But when I remove that file torch will not import correctly.

torch 1.4.0, by comparison, is much smaller because it did not by default include the cuda libraries.

I want torch 1.5.0 without the GPU support.

Is there a way to pip install torch==1.5.0 without gpu support?

Output:
PyTorch also distributes CPU only versions, that you can install with pip. Although they aren't published to PyPI, so you need to get them from their own registry.

You can get the CPU version on PyTorch - Getting Started Locally by selecting CUDA: None.

pip install torch==1.5.0+cpu -f https://download.pytorch.org/whl/torch_stable.html


Instruction: Pytorch / device problem(cpu, gpu) when load state dict for optimizer

Input:
Hi i`m student who studies pytorch since last summer.

state = torch.load('drive/My Drive/MODEL/4 CBAM classifier55')

model = MyResNet()
model.load_state_dict(state['state_dict'])

criterion = nn.CrossEntropyLoss()

optimizer = optim.Adam(model.parameters(), lr=0.0003,betas=(0.5,0.999))
optimizer.load_state_dict(state['optimizer'])

model.to(device)

i wrote code like above.

RuntimeError                              Traceback (most recent call last)
<ipython-input-26-507493db387a> in <module>()
     56     new_loss.backward()
     57
---> 58     optimizer.step()
     59
     60     running_loss += loss.item()

/usr/local/lib/python3.6/dist-packages/torch/autograd/grad_mode.py in decorate_context(*args, **kwargs)
     13         def decorate_context(*args, **kwargs):
     14             with self:
---> 15                 return func(*args, **kwargs)
     16         return decorate_context
     17

/usr/local/lib/python3.6/dist-packages/torch/optim/adam.py in step(self, closure)
     97
     98                 # Decay the first and second moment running average coefficient
---> 99                 exp_avg.mul_(beta1).add_(grad, alpha=1 - beta1)
    100                 exp_avg_sq.mul_(beta2).addcmul_(grad, grad, value=1 - beta2)
    101                 if amsgrad:

RuntimeError: expected device cpu but got device cuda:0

And when i implement training code, then i got this kind of error. When i comment out 'optimizer.load_state_dict', it works well. How can i solve this problem? Thank you for your answer. :)

Output:
Seems like the state was on cuda when you saved and now trying to use it on cpu or vice-versa. To avoid this error, a simple way is to pass the map_location argument to load.

Just pass map_location=<device you want to use> in torch.load and it should work fine. Also, see https://pytorch.org/tutorials/beginner/saving_loading_models.html#saving-loading-model-across-devices


Instruction: Pytorch NN Training issue: Loss of NN does not decrase

Input:
I want to classify random Instagram images as "image has a dog" or "image has not a dog".
To train my NN to classify dogs I want to use the Stanford Dogs Dataset, so I have about 20.000 training images of different dogs with different breeds.

But while training my NN the loss does not decrease, I checked that with different learning rates and with or without dropout layers.

Can anyone give tips or does anyone see bugs in the following code?:

import torch
import torchvision
from torchvision import transforms
from PIL import Image
from os import listdir
import os
import random
import torch.optim as optim
from torch.autograd import Variable
import torch.nn.functional as F
import torch.nn as nn

TRAINDATAPATH = 'C:/Users/.../Desktop/train/'
TESTDATAPATH = 'C:/Users/.../Desktop/#apfel/'

"""normalize = transforms.Normalize(
   mean=[0.485, 0.456, 0.406],
   std=[0.229, 0.224, 0.225]
)"""
normalize = transforms.Normalize(
   mean=[0.5, 0.5, 0.5],
   std=[0.5, 0.5, 0.5]
)
transforms = transforms.Compose([transforms.Resize(256),
                                 transforms.CenterCrop(256),
                                 transforms.ToTensor(),
                                 normalize])

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
train_data_list = []
target_list = []
train_data = []

batch_size = 1

files = listdir(TRAINDATAPATH)

for i in range(len(listdir(TRAINDATAPATH))):
    try:
        f = random.choice(files)
        files.remove(f)
        img = Image.open(TRAINDATAPATH + f)
        img_tensor = transforms(img) # (3,256,256)
        train_data_list.append(img_tensor)
        isObj = 1 if 'obj' in f else 0
        isNotObj = 0 if 'obj' in f else 1
        target = [isObj, isNotObj]

        target_list.append(target)
        if len(train_data_list) >= 1:
            train_data.append((torch.stack(train_data_list), target_list))
            train_data_list = []
            target_list = []
            print('Loaded batch ', int(len(train_data)/batch_size), 'of ', int(len(listdir(TRAINDATAPATH))/batch_size))
            print('Percentage Done: ', 100*int(len(train_data)/batch_size)/int(len(listdir(TRAINDATAPATH))/batch_size), '%')
    except Exception:
        print("Error occured but ignored")
        print(str(Exception))
        continue

class Netz(nn.Module):
    def __init__(self):
        super(Netz, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, kernel_size=5)
        self.conv2 = nn.Conv2d(6, 12, kernel_size=5)
        self.conv3 = nn.Conv2d(12, 18, kernel_size=5)
        self.conv4 = nn.Conv2d(18, 24, kernel_size=5)
        self.fc1 = nn.Linear(3456, 1000)
        self.fc2 = nn.Linear(1000, 2)

    def forward(self, x):
        x = self.conv1(x)
        x = F.max_pool2d(x,2)
        x = F.relu(x)
        x = self.conv2(x)
        x = F.max_pool2d(x,2)
        x = F.relu(x)
        x = self.conv3(x)
        x = F.max_pool2d(x,2)
        x = F.relu(x)
        x = self.conv4(x)
        x = F.max_pool2d(x,2)
        x = F.relu(x)
        x = x.view(-1,3456)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)

        return torch.sigmoid(x)

model = Netz()
model.to(torch.device("cuda" if torch.cuda.is_available() else "cpu"))

optimizer = optim.Adadelta(model.parameters(), lr=10)
def train(epoch):
    global model

    model.train()
    batch_idx = 0
    for data, target in train_data:
        batch_idx += 1
        data = data.to(torch.device("cuda" if torch.cuda.is_available() else "cpu"))
        target = torch.Tensor(target).to(torch.device("cuda" if torch.cuda.is_available() else "cpu"))
        data = Variable(data)
        target = Variable(target)
        optimizer.zero_grad()

        output = model(data)

        criterion = F.binary_cross_entropy
        loss = criterion(output, target)
        loss.backward()

        optimizer.step()
        print('Train Epoch: '+ str(epoch) + '\tLoss: ' + str(loss.data.item()) )

def test():
    global model

    model.eval()
    files = listdir(TESTDATAPATH)
    f = random.choice(files)
    img = Image.open(TESTDATAPATH + f)
    img_eval_tensor = transforms(img)
    img_eval_tensor.unsqueeze_(0)
    data = Variable(img_eval_tensor.to(torch.device("cuda" if torch.cuda.is_available() else "cpu")) )
    out = model(data)
    string_prediction = str(out.data.max(0, keepdim=True)[1])
    print(string_prediction[9:10])

for epoch in range(1,4):
    train(epoch)
i = 100
while i > 0:
    test()
    i -= 1

In the TRAINDATAPATH are thousands of Dog images with the filename "obj_XXX.jpg" and some other images WITHOUT dogs with other filenames don't including "obj".

In the TESTDATAPATH are just random images, some with dogs, some without.
The NN classifies them all as "not including dogs" or "0" which is incorrect.

Thanks for every help!

Output:
You are doing a binary classification but you are using two classes:

isObj = 1 if 'obj' in f else 0
isNotObj = 0 if 'obj' in f else 1
target = [isObj, isNotObj]

In the binary case, it should be a single class, where 1 means it is a dog, and 0 means it is not. You are already doing it, but twice. You can remove the isNotObj entirely and only keep the isObj.

You need to adapt the model accordingly, such that it only predicts the isObj, therefore fc2 should only have 1 class as output:

self.fc2 = nn.Linear(1000, 1)

In the testing phase you need to make a prediction based on a single class, which can be seen as the probability of being a dog. Then you set a threshold for which you consider the model to be confident enough that it's actually a dog. To make it balanced, the threshold is 0.5, so everything above that is a dog and everything below it is not. This can easily be achieved with torch.round:

# Size: [batch_size, 1]
out = model(data)
predictions = torch.round(out)
# Get rid of the singular dimension
# To get size: [batch_size]
predictions = predictions.squeeze(1)

Besides that, the learning rate of 10 is astronomically high, and a learning rate greater than 1 makes it impossible to converge. A more appropriate learning rate is around 0.01 or 0.001.

And on side note, since you are new to PyTorch: Please don't use Variable, it was deprecated with PyTorch 0.4.0, which was released over 2 years ago, and all of its functionality has been merged into the tensors.


Instruction: Is there a function that finds the OR of every row in a boolean matrix in pytorch?

Input:
I have a matrix A of size n x m and all the entries are bools.  I want all my calculation to be on the GPU and I have matrix A stored as a tensor with each entry being the pytorch's bool datatype.  I want an output of a single vector, b, to be a 1 x m tensor that stores the OR of all rows in A.

What I want:
A matrix =
[a1,1, a1,2, , a1,3, ... , a1,m]
[a2,1, a2,2, , a2,3, ... , a2,m]
...
[an,1, an,2, , an,3, ... , an,m]

b = [b1, b2, , b3, , ..., bm]

s.t. bi = a1,i | a2,i | a3,i | ... | an,iwhere | is the OR operator in Pytorch

essentially I want a function that applies row or column wise boolean operation. I know the | .__OR__ can be used and Pytorch's OR function takes two boolean tensor as inputs and I would need to loop over all rows to get my desired b vector.
Since OR is commutative (a|(b|c) = (a|b)|c), I would think pytorch would have some nice function that speeds it up by doing the | operations in parallel or in some divide and conquer method, instead of doing this with a loop. Any ideas or references to speed up the process of applying communicative row/column wise boolean operation with pytorch is welcomed.  Best if all operations are done on the GPU.

Output:
See torch.any and torch.all.

Both take a dim argument and hence you can compute or/and of rows.


Instruction: How to use pretrained weights of a model for initializing the weights in next iteration?

Input:
I have a model architecture. I have saved the entire model using torch.save() for some n number of iterations. I want to run another iteration of my code by using the pre-trained weights of the model I saved previously.

Edit: I want the weight initialization for the new iteration be done from the weights of the pretrained model

Edit 2: Just to add, I don't plan to resume training. I intend to save the model and use it for a separate training with same parameters. Think of it like using a saved model with weights etc. for a larger run and more samples (i.e. a complete new training job)

Right now, I do something like:

# default_lr = 5
# default_weight_decay = 0.001
# model_io = the pretrained model
model = torch.load(model_io)
optim = torch.optim.Adam(model.parameters(),lr=default_lr, weight_decay=default_weight_decay)
loss_new = BCELoss()
epochs = default_epoch
.
.
training_loop():
....
outputs = model(input)
....
.
#similarly for test loop

Am I missing something? I have to run for a very long epoch for a huge number of sample so can not afford to wait to see the results then figure out things.

Thank you!

Output:
From the code that you have posted, I see that you are only loading the previous model parameters in order to restart your training from where you left it off. This is not sufficient to restart your training correctly. Along with your model parameters (weights), you also need to save and load your optimizer state, especially when your choice of optimizer is Adam which has velocity parameters for all your weights that help in decaying the learning rate.

In order to smoothly restart training, I would do the following:

# For saving your model

state = {
    'model': model.state_dict(),
    'optimizer': optimizer.state_dict()
}
model_save_path = "Enter/your/model/path/here/model_name.pth"
torch.save(state, model_save_path)

# ------------------------------------------

# For loading your model
state = torch.load(model_save_path)

model = MyNetwork()
model.load_state_dict(state['model'])

optim = torch.optim.Adam(model.parameters(),lr=default_lr, weight_decay=default_weight_decay)
optim.load_state_dict(state['optimizer'])

Besides these, you may also want to save your learning rate if you are using a learning rate decay strategy, your best validation accuracy so far which you may want for checkpointing purposes, and any other changeable parameter which might affect your training. But in most of the cases, saving and loading just the model weights and optimizer state should be sufficient.

EDIT: You may also want to look at this following answer which explains in detail how you should save your model in different scenarios.


Instruction: How to convert a tensor of booleans to ints in PyTorch?

Input:
Suppose, we have a tensor

t = torch.tensor([True, False, True, False])

How do we convert it to an integer tensor with values [1, 0, 1, 0]?

Output:
The solution is just a single line of code.
To convert a tensor t with values [True, False, True, False] to an integer tensor, just do the following.
t = torch.tensor([True, False, True, False])
t_integer = t.long()
print(t_integer)
[1, 0, 1, 0]


Instruction: pytorch to Onnx(OCR model)

Input:
I am trying to convert pytorch model in the given repo https://github.com/clovaai/deep-text-recognition-benchmark
to onnx.

I am facing the issue while doing so.

Failed to export an ONNX attribute 'onnx::Gather', since it's not constant, please try to make things (e.g., kernel size) static if possible

Link to the git issue https://github.com/clovaai/deep-text-recognition-benchmark/issues/76

Any suggestion?

Thanks.

Output: adaptive_avg_pool2d  is not supported in my case and this  nn.AdaptiveAvgPool2d((None,1)) also have have issue.