title: Pytorch : Neural network is not learning at all
body: <p>I'm new to deep learning so I might just miss something stupid.</p>
  <p>I'm training several neural networks on trees. I'm trying to generate trees with my neural networks, and I have a reward function to select the best trees after each generation. I try to learn on the 100 best trees, but when I try to learn, my loss is computed correctly but it's constant even after several <code>optimizer.step()</code>. I honestly have no idea why it's not working. I'm using <code>torch.nn.CrossEntorpyLoss</code> and <code>torch.optim.SGD</code>. Here's my entire code but I think the problem is in the <code>learn</code> function.
  I can give further explanation if necessary.</p>
  <pre><code>import torch
  import random as rd
  import networkx as nx
  import numpy as np
  import heapq
  from time import time
  import matplotlib.pyplot as plt
  
  n = 19 # Taille de l'arbre
  n_edg = 171 # Taille des vecteurs
  iters = 10000 # Nombre d'itérations
  bests = 100 # Nombre de graphes sur lesquels on apprend
  const = 1 + (n - 1) ** 0.5 # Constante du problème
  
  def create_net(in_size, out_size):
      l1 = torch.nn.Linear(in_size, 64)
      r1 = torch.nn.ReLU()
      l2 = torch.nn.Linear(64, 8)
      r2 = torch.nn.ReLU()
      l3 = torch.nn.Linear(8, out_size)
      s = torch.nn.Softmax(0)
      return torch.nn.Sequential(l1, r1, l2, r2, l3, s)
  
  net_list = [create_net(i * (i - 1) // 2, i) for i in range(2, n)]
  
  def from_edge_vec(g):
      G = nx.Graph()
      G.add_nodes_from(range(n))
      G.add_edge(0, 1)
      index = 0
      for i in range(n - 1):
          for j in range(i + 1):
              if g[index]: G.add_edge(i + 1, j)
              index += 1
      return G
  
  def reward(g, G):
      return g, np.max(nx.adjacency_spectrum(G)) + len(nx.max_weight_matching(G)) - const
  
  def sortSecond(elt):
      return elt[1]
  
  def meanSecond(list):
      acc = 0
      for _, r in list:
          acc += r
      return acc / len(list)
  
  def step():
      v = torch.zeros(iters, n_edg)
      v[:, 0] = 1
      max_index = 1
      for i in range(n - 2):
          out = net_list[i](v[:, :max_index])
          val = torch.multinomial(out, 1)
          for j in range(iters):
              v[j, max_index + val[j]] = 1
          max_index += i + 2
      l = map(from_edge_vec, v)
      acc = map(reward, v, l)
      learn_graphs = heapq.nsmallest(bests, acc, key = sortSecond)
      return learn_graphs
  
  def learn(graph_list):
      criterion = torch.nn.CrossEntropyLoss()
      prog_v = torch.zeros(bests, n_edg)
      prog_v[:, 0] = 1
      max_index = 1
      for i in range(n - 2):
          net = net_list[i]
          optimizer = torch.optim.SGD(net.parameters(), lr=1e-2)
          label = torch.empty(bests, dtype = torch.long)
          for j in range(bests):
              label[j] = torch.argmax(graph_list[j][0][max_index:max_index + i + 2])
          loss = 1
          # while loss &gt; 0.1:
          for _ in range(5):
              out = net(prog_v[:, :max_index])
              # print(label)
              # print(prog_v)
              loss = criterion(out, label)
              print(loss)
              optimizer.zero_grad()
              loss.backward()
              optimizer.step()
          for j in range(bests):
              prog_v[j, max_index + label[j]] = 1
          max_index += i + 2
              
  
  mean_result = []
  best = [None, 100]
  
  t = time()
  for epoch in range(3):
      res = step()
      if res[0][1] &lt; best[1]: best = res[0]
      mean_result.append(meanSecond(res))
      learn(res)
      print(epoch)
  print(time() - t)
  
  print(mean_result)
  print(best)
  nx.draw(from_edge_vec(best[0]))
  plt.show()
  </code></pre>