Error back propagation method does not work

zxyv_fujiww: <p>I want to use RNN to classify names in order to deepen my understanding of RNN.<br>
But I got an error.Below is the error<br>
line 196, in <br>
avg_train_acc,avg_train_loss= train(batch_size,train_size,device)<br>
line 126, in train<br>
loss.backward()<br>
line 363, in backward<br>
torch.autograd.backward(self, gradient, retain_graph, create_graph, inputs=inputs)<br>
line 173, in backward<br>
Variable._execution_engine.run_backward( # Calls into the C++ engine to run the backward pass<br>
RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.FloatTensor [313, 256]], which is output 0 of AsStridedBackward0, is at version 2; expected version 1 instead. Hint: the backtrace further above shows the operation that failed to compute its gradient. The variable in question was changed in there or anywhere later. Good luck!</p>
<p>I somehow find out that backpropagation isn’t working, and I think I should fix the train function part, but I have no idea how to fix it. I would appreciate it if you could let me know.<br>
Also, I can only speak a little English, so if it’s strange, point it out.<br>
Thank you.</p>
<pre><code class="lang-auto">import torch
import torch.nn as nn 
import matplotlib.pyplot as plt 
import numpy as np
import random
import io
import os
import unicodedata
import string
import glob
import time
import matplotlib.ticker as ticker
from data_download import ALL_LETTERS, N_LETTERS
from data_download import load_data, letter_to_tensor, line_to_tensor, random_training_example
from sklearn.model_selection import train_test_split
import torch.nn.functional as F #様々な関数を持つクラス

class RNN(nn.Module):
    def __init__(self, input_size, hidden_size,output_size):#57,256,18
        super(RNN, self).__init__()
        
        self.hidden_size = hidden_size
        self.h = nn.Linear(input_size + hidden_size, hidden_size)#データと隠れ層からの入力、出力は隠れ層
        self.o = nn.Linear(input_size + hidden_size,output_size)#データと隠れ層からの入力、出力は国の数
        self.softmax = nn.LogSoftmax(dim=1)
        
    def forward(self, input_tensor, hidden_tensor):
        combined = torch.cat((input_tensor, hidden_tensor),1)

        hidden = self.h(combined)
        hidden = F.relu(hidden)
        output = self.o(combined)
        output=F.relu(output)
        output = self.softmax(output)
        return output, hidden
    
    def init_hidden(self):
        return torch.zeros(1, self.hidden_size)
    

#ユニコード文字をascii文字に直す
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():
    # category_linesにそれぞれの国の性と名前、all_categoriesに国の名前を代入
    category_lines = {}
    all_categories = []
    test_lines={}
    lines_list=[]
    def find_files(path):
        return glob.glob(path)
    
    # ファイルを読み込み
    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/names/*.txt'):
        category = os.path.splitext(os.path.basename(filename))[0]#国の名前を取得
        all_categories.append(category)
        
        lines = read_lines(filename)
        category_lines[category] = lines
        lengs=len(category_lines[category])
        for i in range(int(lengs*0.2)):
            k=random.randint(-1,lengs-2-i)
            lines_list.append(category_lines[category].pop(k))
        test_lines[category]=lines_list
        lines_list=[]
    return category_lines, all_categories,test_lines

category_lines, all_categories,test_lines = load_data()

n_categories = len(all_categories)
n_hidden = 256
n_hidden2=128
rnn = RNN(N_LETTERS, n_hidden,n_categories)#57,256,18

#outputを国の名前に変換
def category_from_output(output):
    category_idx = torch.argmax(output).item()
    return all_categories[category_idx]

def train(batch_size,train_size,device):
    train_loss = 0
    train_acc = 0
    rnn.train()
    hidden = rnn.init_hidden()
    hidden=hidden.to(device)
    #hidden2 = rnn.init_hidden2()
    for i in range(int(train_size/batch_size)):
        category, line, category_tensor, line_tensor,lines_num = random_training_example(category_lines, all_categories)
        category_tensor=category_tensor.to(device)
        line_tensor=line_tensor.to(device)
        for j in range(len(lines_num)):
            for k in range(lines_num[j]):#line_tensor.size()[0]=文字数
                output, hidden = rnn(line_tensor[k], hidden)
            
            f=torch.tensor([category_tensor[j]])
            f=f.to(torch.int64)
            print(f,f.dtype,f.size())
            loss = criterion(output,f)
            loss.backward()
            optimizer.step()
            optimizer.zero_grad()
            train_loss = train_loss+loss.item()*batch_size
            # 正解数の合計を更新
            guess = category_from_output(output)
            if(guess==category):
                train_acc=train_acc+1
    
    # epochごとのlossと正解率を表示
    avg_val_loss = train_loss / train_size
    avg_val_acc = train_acc.double() / train_size
    return avg_val_acc,avg_val_loss

def test(batch_size,val_size,device):
    with torch.no_grad():
        rnn.eval()
        hidden = rnn.init_hidden()#初期化
        hidden=hidden.to(device)
    for i in range(int(val_size/batch_size)):
        category, line, category_tensor, line_tensor,lines_num = random_training_example(category_lines, all_categories)
        category_tensor=category_tensor.to(device)
        line_tensor=line_tensor.to(device)
        for j in range(len(lines_num)):
            for k in range(lines_num[j]):#line_tensor.size()[0]=文字数
                output, hidden = rnn(line_tensor[k], hidden)
            
            f=torch.LongTensor(category_tensor[j])
            loss = criterion(output,f)
        
            val_loss =val_loss+ loss.item()*batch_size
            # 正解数の合計を更新
            guess = category_from_output(output)
            if(guess==category):
                val_acc=val_acc+1
    
    # epochごとのlossと正解率を表示
    avg_val_loss = val_loss / val_size
    avg_val_acc = val_acc.double() / val_size
    return avg_val_acc,avg_val_loss

train_loss_list = []
train_acc_list = []
val_loss_list = []
val_acc_list = []
epoch_num_list=[]
epoch=10
batch_size=100
train_size=18067
val_size=2007

"""""
n_iters =18067*50
n_lines=20074#八割は16059
train_lines_num=181
test_lines_num=20
"""
criterion = nn.NLLLoss()
optimizer =torch.optim.SGD(rnn.parameters(), lr=0.005)

use_cuda =torch.cuda.is_available()#cudaを使えと指定されcudaが使える場合にcudaを使用
device = torch.device("cuda" if use_cuda else "cpu")#GPUを指定なければCPU
device="cpu"
# 開始
start_time = time.perf_counter()
 
# ダミー処理
time.sleep(1)

for i in range(epoch):
    avg_train_acc,avg_train_loss= train(batch_size,train_size,device)
    train_acc_list.append(avg_train_acc)
    train_loss_list.append(avg_train_loss)

    avg_val_acc,avg_val_loss = test(batch_size,val_size,device)
    val_acc_list.append(avg_val_acc)
    val_loss_list.append(avg_val_loss)
    epoch_num_list.append(i+1)
    print('Epoch: {} train_Loss: {:.6f} train_Acc: {:.6f} test_Loss: {:.6f} test_Acc: {:.6f}'.format(i+1,avg_train_loss,avg_train_acc,avg_val_loss,avg_val_acc))

# 修了
end_time = time.perf_counter()
 
# 経過時間を出力(秒)
elapsed_time = end_time - start_time
print('elapsed time {}'.format(elapsed_time))
Program end

Below this is written in another script file

def random_training_example(category_lines, all_categories):
    #ランダムで名前や国のインデックスを返す
    datas=[]
    datas_label=[]
    line_num=[]
    category_np=np.array([])
    def random_choice(a):
        random_idx = random.randint(0, len(a) - 1)
        return a[random_idx]
    for i in range(batch_size):
        category = random_choice(all_categories)#0~17の数字を返す
        line = random_choice(category_lines[category])#選ばれた国の名前の列を代入する
        category_np=np.append(category_np,all_categories.index(category))
        #category_tensor = torch.tensor([all_categories.index(category)])#国のインデックスを代入
        line_tensor = line_to_tensor(line)#名前を文字列にtensorに変換する
        line_num.append(line_tensor.size()[0])#文字数を代入
        datas.append(line_tensor)#名前を追加
        #datas_label.append(category_tensor)
    line_tensor =torch.cat(datas,axis=0)#今までのデータを連結
    category_tensor=torch.tensor(category_np)

    return category, line, category_tensor, line_tensor,line_num
</code></pre>