理解を深めるためにRNNを用いて名前の分類を行いたいと思い実装しているのですが
line 196, in <module>
avg_train_acc,avg_train_loss= train(batch_size,train_size,device)
line 126, in train
loss.backward()
line 363, in backward
torch.autograd.backward(self, gradient, retain_graph, create_graph, inputs=inputs)
line 173, in backward
Variable._execution_engine.run_backward( # Calls into the C++ engine to run the backward pass
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!
というエラーが発生しうまくいっておりません。バックプロパゲーションがうまくいっていないことは何となくわかり、train関数の部分を修正すればよいのだと思うのですが、どのように修正すればよいのかが全く分かりませんもしよろしければ教えていただければ幸いです。
修正ではなくてもこのエラーの時はこのような間違いが多いなどといった情報でもとても嬉しいです。
自分が参考にしたサイトはこちらです。サイトはバッチ処理していませんが自分はバッチ処理を実装しようとしています。
https://pytorch.org/tutorials/intermediate/char_rnn_classification_tutorial.html
python
1import torch 2import torch.nn as nn 3import matplotlib.pyplot as plt 4import numpy as np 5import random 6import io 7import os 8import unicodedata 9import string 10import glob 11import time 12import matplotlib.ticker as ticker 13from data_download import ALL_LETTERS, N_LETTERS 14from data_download import load_data, letter_to_tensor, line_to_tensor, random_training_example 15from sklearn.model_selection import train_test_split 16import torch.nn.functional as F #様々な関数を持つクラス 17 18class RNN(nn.Module): 19 def __init__(self, input_size, hidden_size,output_size):#57,256,18 20 super(RNN, self).__init__() 21 22 self.hidden_size = hidden_size 23 self.h = nn.Linear(input_size + hidden_size, hidden_size)#データと隠れ層からの入力、出力は隠れ層 24 self.o = nn.Linear(input_size + hidden_size,output_size)#データと隠れ層からの入力、出力は国の数 25 self.softmax = nn.LogSoftmax(dim=1) 26 27 def forward(self, input_tensor, hidden_tensor): 28 combined = torch.cat((input_tensor, hidden_tensor),1) 29 30 hidden = self.h(combined) 31 hidden = F.relu(hidden) 32 output = self.o(combined) 33 output=F.relu(output) 34 output = self.softmax(output) 35 return output, hidden 36 37 def init_hidden(self): 38 return torch.zeros(1, self.hidden_size) 39 40 41#ユニコード文字をascii文字に直す 42def unicode_to_ascii(s): 43 return ''.join( 44 c for c in unicodedata.normalize('NFD', s) 45 if unicodedata.category(c) != 'Mn' 46 and c in ALL_LETTERS 47 ) 48 49def load_data(): 50 # category_linesにそれぞれの国の性と名前、all_categoriesに国の名前を代入 51 category_lines = {} 52 all_categories = [] 53 test_lines={} 54 lines_list=[] 55 def find_files(path): 56 return glob.glob(path) 57 58 # ファイルを読み込み 59 def read_lines(filename): 60 lines = io.open(filename, encoding='utf-8').read().strip().split('\n')#性と名前を取得 61 return [unicode_to_ascii(line) for line in lines]#名前ごとに値を返す 62 63 for filename in find_files('data/names/*.txt'): 64 category = os.path.splitext(os.path.basename(filename))[0]#国の名前を取得 65 all_categories.append(category) 66 67 lines = read_lines(filename) 68 category_lines[category] = lines 69 lengs=len(category_lines[category]) 70 for i in range(int(lengs*0.2)): 71 k=random.randint(-1,lengs-2-i) 72 lines_list.append(category_lines[category].pop(k)) 73 test_lines[category]=lines_list 74 lines_list=[] 75 return category_lines, all_categories,test_lines 76 77category_lines, all_categories,test_lines = load_data() 78 79n_categories = len(all_categories) 80n_hidden = 256 81n_hidden2=128 82rnn = RNN(N_LETTERS, n_hidden,n_categories)#57,256,18 83 84#outputを国の名前に変換 85def category_from_output(output): 86 category_idx = torch.argmax(output).item() 87 return all_categories[category_idx] 88 89def train(batch_size,train_size,device): 90 train_loss = 0 91 train_acc = 0 92 rnn.train() 93 hidden = rnn.init_hidden() 94 hidden=hidden.to(device) 95 #hidden2 = rnn.init_hidden2() 96 for i in range(int(train_size/batch_size)): 97 category, line, category_tensor, line_tensor,lines_num = random_training_example(category_lines, all_categories) 98 category_tensor=category_tensor.to(device) 99 line_tensor=line_tensor.to(device) 100 for j in range(len(lines_num)): 101 for k in range(lines_num[j]):#line_tensor.size()[0]=文字数 102 output, hidden = rnn(line_tensor[k], hidden) 103 104 f=torch.tensor([category_tensor[j]]) 105 f=f.to(torch.int64) 106 print(f,f.dtype,f.size()) 107 loss = criterion(output,f) 108 loss.backward() 109 optimizer.step() 110 optimizer.zero_grad() 111 train_loss = train_loss+loss.item()*batch_size 112 # 正解数の合計を更新 113 guess = category_from_output(output) 114 if(guess==category): 115 train_acc=train_acc+1 116 117 # epochごとのlossと正解率を表示 118 avg_val_loss = train_loss / train_size 119 avg_val_acc = train_acc.double() / train_size 120 return avg_val_acc,avg_val_loss 121 122def test(batch_size,val_size,device): 123 with torch.no_grad(): 124 rnn.eval() 125 hidden = rnn.init_hidden()#初期化 126 hidden=hidden.to(device) 127 for i in range(int(val_size/batch_size)): 128 category, line, category_tensor, line_tensor,lines_num = random_training_example(category_lines, all_categories) 129 category_tensor=category_tensor.to(device) 130 line_tensor=line_tensor.to(device) 131 for j in range(len(lines_num)): 132 for k in range(lines_num[j]):#line_tensor.size()[0]=文字数 133 output, hidden = rnn(line_tensor[k], hidden) 134 135 f=torch.LongTensor(category_tensor[j]) 136 loss = criterion(output,f) 137 138 val_loss =val_loss+ loss.item()*batch_size 139 # 正解数の合計を更新 140 guess = category_from_output(output) 141 if(guess==category): 142 val_acc=val_acc+1 143 144 # epochごとのlossと正解率を表示 145 avg_val_loss = val_loss / val_size 146 avg_val_acc = val_acc.double() / val_size 147 return avg_val_acc,avg_val_loss 148 149train_loss_list = [] 150train_acc_list = [] 151val_loss_list = [] 152val_acc_list = [] 153epoch_num_list=[] 154epoch=10 155batch_size=100 156train_size=18067 157val_size=2007 158 159""""" 160n_iters =18067*50 161n_lines=20074#八割は16059 162train_lines_num=181 163test_lines_num=20 164""" 165criterion = nn.NLLLoss() 166optimizer =torch.optim.SGD(rnn.parameters(), lr=0.005) 167 168use_cuda =torch.cuda.is_available()#cudaを使えと指定されcudaが使える場合にcudaを使用 169device = torch.device("cuda" if use_cuda else "cpu")#GPUを指定なければCPU 170device="cpu" 171# 開始 172start_time = time.perf_counter() 173 174# ダミー処理 175time.sleep(1) 176 177for i in range(epoch): 178 avg_train_acc,avg_train_loss= train(batch_size,train_size,device) 179 train_acc_list.append(avg_train_acc) 180 train_loss_list.append(avg_train_loss) 181 182 avg_val_acc,avg_val_loss = test(batch_size,val_size,device) 183 val_acc_list.append(avg_val_acc) 184 val_loss_list.append(avg_val_loss) 185 epoch_num_list.append(i+1) 186 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)) 187 188# 修了 189end_time = time.perf_counter() 190 191# 経過時間を出力(秒) 192elapsed_time = end_time - start_time 193print('elapsed time {}'.format(elapsed_time)) 194プログラムはここまで 195 196この下は別のスクリプトファイルに書いています 197def random_training_example(category_lines, all_categories): 198 #ランダムで名前や国のインデックスを返す 199 datas=[] 200 datas_label=[] 201 line_num=[] 202 category_np=np.array([]) 203 def random_choice(a): 204 random_idx = random.randint(0, len(a) - 1) 205 return a[random_idx] 206 for i in range(batch_size): 207 category = random_choice(all_categories)#0~17の数字を返す 208 line = random_choice(category_lines[category])#選ばれた国の名前の列を代入する 209 category_np=np.append(category_np,all_categories.index(category)) 210 #category_tensor = torch.tensor([all_categories.index(category)])#国のインデックスを代入 211 line_tensor = line_to_tensor(line)#名前を文字列にtensorに変換する 212 line_num.append(line_tensor.size()[0])#文字数を代入 213 datas.append(line_tensor)#名前を追加 214 #datas_label.append(category_tensor) 215 line_tensor =torch.cat(datas,axis=0)#今までのデータを連結 216 category_tensor=torch.tensor(category_np) 217 218 return category, line, category_tensor, line_tensor,line_num
あなたの回答
tips
プレビュー