1

我對PyTorch非常陌生,對於神經網絡來說相​​當新穎。
我試圖建立一個可以猜測性別名稱的神經網絡,並且我基於判斷國籍的PyTorch RNN教程。
我得到的代碼運行沒有錯誤,但損失幾乎沒有變化,使我認爲權重沒有更新...
這是我的輸入/輸出/目標張量設置的問題?或者我的訓練功能可能有問題?我很失落,任何幫助將不勝感激:cold_sweat:
這裏是我的代碼:RNN參數不更新?

from __future__ import unicode_literals, print_function, division 
from io import open 
import glob 
import unicodedata 
import string 
import torch 
import torchvision 
import torch.nn as nn 
import torch.optim as optim 
import random 
from torch.autograd import Variable 

"""------GLOBAL VARIABLES------""" 

all_letters = string.ascii_letters + " .,;'" 
num_letters = len(all_letters) 
all_names = {} 
genders = ["Female", "Male"] 

"""-------DATA EXTRACTION------""" 

def findFiles(path): 
    return glob.glob(path) 

def unicodeToAscii(s): 
    return ''.join(
     c for c in unicodedata.normalize('NFD', s) 
     if unicodedata.category(c) != 'Mn' 
     and c in all_letters 
    ) 

# Read a file and split into lines 
def readLines(filename): 
    lines = open(filename, encoding='utf-8').read().strip().split('\n') 
    return [unicodeToAscii(line) for line in lines] 

for file in findFiles("/home/andrew/PyCharm/PycharmProjects/CantStop/data/names/*.txt"): 
    gender = file.split("/")[-1].split(".")[0] 
    names = readLines(file) 
    all_names[gender] = names 

"""-----DATA INTERPRETATION-----""" 

def nameToTensor(name): 
    tensor = torch.zeros(len(name), 1, num_letters) 
    for index, letter in enumerate(name): 
     tensor[index][0][all_letters.find(letter)] = 1 
    return tensor 

def outputToGender(output): 
    gender, gender_index = output.data.topk(1) 
    if gender_index[0][0] == 0: 
     return "Female" 
    return "Male" 

"""------NETWORK SETUP------""" 

class Net(nn.Module): 
    def __init__(self, input_size, hidden_size, output_size): 
     super(Net, self).__init__() 
     self.hidden_size = hidden_size 
     #Layer 1 
     self.Lin1 = nn.Linear(input_size+hidden_size, int((input_size+hidden_size)/2)) 
     self.ReLu1 = nn.ReLU() 
     self.Batch1 = nn.BatchNorm1d(int((input_size+hidden_size)/2)) 
     #Layer 2 
     self.Lin2 = nn.Linear(int((input_size+hidden_size)/2), output_size) 
     self.ReLu2 = nn.ReLU() 
     self.Batch2 = nn.BatchNorm1d(output_size) 
     self.softMax = nn.LogSoftmax() 
     #Hidden layer 
     self.HidLin = nn.Linear(input_size+hidden_size, hidden_size) 
     self.HidReLu = nn.ReLU() 
     self.HidBatch = nn.BatchNorm1d(hidden_size) 

    def forward(self, input, hidden): 
     comb = torch.cat((input, hidden), 1) 
     hidden = self.HidBatch(self.HidReLu(self.HidLin(comb))) 
     output1 = self.Batch1(self.ReLu1(self.Lin1(comb))) 
     output2 = self.softMax(self.Batch2(self.ReLu2(self.Lin2(output1)))) 
     return output2, hidden 

    def initHidden(self): 
     return Variable(torch.zeros(1, self.hidden_size)) 

NN = Net(num_letters, 128, 2) 

"""------TRAINING------""" 

def getRandomTrainingEx(): 
    gender = genders[random.randint(0, 1)] 
    name = all_names[gender][random.randint(0, len(all_names[gender])-1)] 
    gender_tensor = Variable(torch.LongTensor([genders.index(gender)])) 
    name_tensor = Variable(nameToTensor(name)) 
    return gender_tensor, name_tensor, gender 

def train(input, target): 
    hidden = NN.initHidden() 

    loss_func = nn.NLLLoss() 

    alpha = 0.01 

    NN.zero_grad() 

    for i in range(input.size()[0]): 
     output, hidden = NN(input[i], hidden) 

    loss = loss_func(output, target) 
    loss.backward() 
    for w in NN.parameters(): 
     w.data.add_(-alpha, w.grad.data) 

    return output, loss 

for i in range(5000): 
    gender_tensor, name_tensor, gender = getRandomTrainingEx() 
    output, loss = train(name_tensor, gender_tensor) 

    if i%500 == 0: 
     print("Guess: %s, Correct: %s, Loss: %s" % (outputToGender(output), gender, loss.data[0])) 

而這裏的輸出:

Guess: Male, Correct: Male, Loss: 0.6931471824645996 
Guess: Male, Correct: Female, Loss: 0.7400936484336853 
Guess: Male, Correct: Male, Loss: 0.6755779385566711 
Guess: Female, Correct: Female, Loss: 0.6648257374763489 
Guess: Male, Correct: Male, Loss: 0.6765623688697815 
Guess: Female, Correct: Male, Loss: 0.7330614924430847 
Guess: Female, Correct: Female, Loss: 0.6565149426460266 
Guess: Male, Correct: Female, Loss: 0.6946508884429932 
Guess: Female, Correct: Female, Loss: 0.6621525287628174 
Guess: Male, Correct: Male, Loss: 0.6662092804908752 

Process finished with exit code 0 
+0

你在訓練時會得到什麼損失和準確性? – DarkCygnus

+0

另外,您好,歡迎來到Stack Overflow,請花點時間瀏覽[歡迎導覽](https://stackoverflow.com/tour),在此處瞭解您的方式(並獲取您的第一張徽章),閱讀如何創建[Minimal,Complete和Verifiable示例](https://stackoverflow.com/help/mcve)並檢查[如何提出好問題](https://stackoverflow.com/help/how-to - 問),所以你增加了獲得反饋和有用答案的機會。 – DarkCygnus

回答

0

我想建議你改變add_sub_ 。 add_可能會使你遠離最佳點。

w.data.sub_(f.grad.data * alpha) 

因爲在權重更新公式中有一個減法。

updating

通過的方式,嘗試增加/減少的α0.1 0.05 0.01。如果alpha太大,可能會錯過最佳點。如果α爲小,則需要太長時間。

+0

改變學習率的好的呼叫。我擔心的是,損失不會持續變化......它會從0.6跳躍到0.5到0.7,這類事情...... –

+0

也許你應該在代碼中包含你的數據集,或者在這裏發佈你的數據集(你可以使用https://gist.github.com作爲文本文件)。所以我們可以調試你的代碼。 –