2021年1月29日星期五

Python re-write jupyter notebook to python script problem

I have a very simple RNN model which I can execute on Jupyter notebook without any problem, now I want to embed this model in my Django project, so I downloaded the .ipynb file then saved it as .py file, then I just put it in my Django project.

However, the first problem is VSCode says I have unresolved import 'MLutils, the MLutils is my utility file in the same folder.

The second problem is if I just run this file, I'll get this error RuntimeError: cannot perform reduction function argmax on a tensor with no elements because the operation does not have an identity but if I use the Run Cell Above button of the VSCode, I'll get the correct result. The code I want to run is this, called MLTrain.py

  import torch  import torch.nn as nn  import matplotlib.pyplot as plt     from MLutils import ALL_LETTERS, N_LETTERS  from MLutils import load_data, letter_to_tensor, line_to_tensor, random_training_example      class RNN(nn.Module):      # implement RNN from scratch rather than using nn.RNN      # # number of possible letters, hidden size, categories number      def __init__(self, input_size, hidden_size, output_size):          super(RNN, self).__init__()                    self.hidden_size = hidden_size          #Define 2 different liner layers          self.i2h = nn.Linear(input_size + hidden_size, hidden_size)          self.i2o = nn.Linear(input_size + hidden_size, output_size)          self.softmax = nn.LogSoftmax(dim=1)                def forward(self, input_tensor, hidden_tensor):          # combine input and hidden tensor          combined = torch.cat((input_tensor, hidden_tensor), 1)          # apply the Linear layers and the softmax          hidden = self.i2h(combined)          output = self.i2o(combined)          output = self.softmax(output)          # return 2 different tensors          return output, hidden            # need some initial hidden states in the begining.      def init_hidden(self):          return torch.zeros(1, self.hidden_size)  # dictionary with the country as the key and names as values  category_lines, all_categories = load_data()  # number of categories  n_categories = len(all_categories)    # a Hyperparameter   n_hidden = 128  # number of possible letters, hidden size, output size  rnn = RNN(N_LETTERS, n_hidden, n_categories)    # one step  input_tensor = letter_to_tensor('A')  hidden_tensor = rnn.init_hidden()    output, next_hidden = rnn(input_tensor, hidden_tensor)  #print(output.size())  #>>> size: [1,18]  #print(next_hidden.size())  #>>> size: [1,128]  # whole sequence/name  input_tensor = line_to_tensor('if')  hidden_tensor = rnn.init_hidden()    output, next_hidden = rnn(input_tensor[0], hidden_tensor)  print(output.size())  print(next_hidden.size())      # In[17]:        # In[2]:      # apply softmax in the end.  # this is the likelyhood of each character of each category  def category_from_output(output):      # return index of the greatest value      category_idx = torch.argmax(output).item()      return all_categories[category_idx]  print(category_from_output(output))      # In[3]:      criterion = nn.NLLLoss()  # hyperparameter  learning_rate = 0.005  optimizer = torch.optim.SGD(rnn.parameters(), lr=learning_rate)  # whole name as tensor,  def train(line_tensor, category_tensor):      hidden = rnn.init_hidden()      #line_tensor.size()[0]: the length of the name      for i in range(line_tensor.size()[0]):          # apply the current character and the previous hidden state.          output, hidden = rnn(line_tensor[i], hidden)                loss = criterion(output, category_tensor)            optimizer.zero_grad()      loss.backward()      optimizer.step()            return output, loss.item()    current_loss = 0  all_losses = []  plot_steps, print_steps = 100, 500  n_iters = 2000  for i in range(n_iters):      category, line, category_tensor, line_tensor = random_training_example(category_lines, all_categories)            output, loss = train(line_tensor, category_tensor)      current_loss += loss             if (i+1) % plot_steps == 0:          all_losses.append(current_loss / plot_steps)          current_loss = 0                if (i+1) % print_steps == 0:          guess = category_from_output(output)          correct = "CORRECT" if guess == category else f"WRONG ({category})"          print(f"{i+1} {(i+1)/n_iters*100} {loss:.4f} {line} / {guess} {correct}")                  plt.figure()  plt.plot(all_losses)  plt.show()  # model can be saved    def predict(input_line):      print(f"\n> {input_line}")      with torch.no_grad():          line_tensor = line_to_tensor(input_line)                    hidden = rnn.init_hidden()                for i in range(line_tensor.size()[0]):              output, hidden = rnn(line_tensor[i], hidden)                    guess = category_from_output(output)          print(guess)      while True:      sentence = input("Input:")      if sentence == "quit":          break            predict(sentence)      if __name__ == "__main__":      predict("abcde 1 ifelse"  

The MLutils.py is this

import io  import os  import unicodedata  import string  import glob    import torch  import random    # alphabet small + capital letters + " .,;'"  ALL_LETTERS = string.ascii_letters + " .,;'"  N_LETTERS = len(ALL_LETTERS)    # Turn a Unicode string to plain ASCII, thanks to https://stackoverflow.com/a/518232/2809427  def unicode_to_ascii(s):      return ''.join(          c for c in unicodedata.normalize('NFD', s)          if unicodedata.category(c) != 'Mn'          and c in ALL_LETTERS      )    def load_data():      # Build the category_lines dictionary, a list of names per language      category_lines = {}      all_categories = []            def find_files(path):          return glob.glob(path)            # Read a file and split into lines      def read_lines(filename):          lines = io.open(filename, encoding='utf-8').read().strip().split('\n')          return [unicode_to_ascii(line) for line in lines]            for filename in find_files('data/categories/*.txt'):          category = os.path.splitext(os.path.basename(filename))[0]          all_categories.append(category)                    lines = read_lines(filename)          category_lines[category] = lines                return category_lines, all_categories        # Find letter index from all_letters, e.g. "a" = 0  def letter_to_index(letter):      return ALL_LETTERS.find(letter)    # Just for demonstration, turn a letter into a <1 x n_letters> Tensor  def letter_to_tensor(letter):      tensor = torch.zeros(1, N_LETTERS)      tensor[0][letter_to_index(letter)] = 1      return tensor    # Turn a line into a <line_length x 1 x n_letters>,  # or an array of one-hot letter vectors  def line_to_tensor(line):      tensor = torch.zeros(len(line), 1, N_LETTERS)      for i, letter in enumerate(line):          tensor[i][0][letter_to_index(letter)] = 1      return tensor      def random_training_example(category_lines, all_categories):            def random_choice(a):          random_idx = random.randint(0, len(a) - 1)          return a[random_idx]            category = random_choice(all_categories)      line = random_choice(category_lines[category])      category_tensor = torch.tensor([all_categories.index(category)], dtype=torch.long)      line_tensor = line_to_tensor(line)      return category, line, category_tensor, line_tensor        if __name__ == '__main__':      print(ALL_LETTERS)      print(unicode_to_ascii('Ślusàrski'))            # category_lines, all_categories = load_data()      # print(category_lines['Flow'][:5])            # print(letter_to_tensor('J')) # [1, 57]      # print(line_to_tensor('Jones').size()) # [5, 1, 57]    

That's really wired or I am really stupid on somewhere. Someone please help me! Many thanks.

https://stackoverflow.com/questions/65963949/python-re-write-jupyter-notebook-to-python-script-problem January 30, 2021 at 10:05AM

没有评论:

发表评论