在pytorch中動態調整優化器的學習率方式
阿新 • • 發佈:2020-06-27
在深度學習中,經常需要動態調整學習率,以達到更好地訓練效果,本文紀錄在pytorch中的實現方法,其優化器例項為SGD優化器,其他如Adam優化器同樣適用。
一般來說,在以SGD優化器作為基本優化器,然後根據epoch實現學習率指數下降,程式碼如下:
step = [10,20,30,40] base_lr = 1e-4 sgd_opt = torch.optim.SGD(model.parameters(),lr=base_lr,nesterov=True,momentum=0.9) def adjust_lr(epoch): lr = base_lr * (0.1 ** np.sum(epoch >= np.array(step))) for params_group in sgd_opt.param_groups: params_group['lr'] = lr return lr
只需要在每個train的epoch之前使用這個函式即可。
for epoch in range(60): model.train() adjust_lr(epoch) for ind,each in enumerate(train_loader): mat,label = each ...
補充知識:Pytorch框架下應用Bi-LSTM實現汽車評論文字關鍵詞抽取
需要呼叫的模組及整體Bi-lstm流程
import torch import pandas as pd import numpy as np from tensorflow import keras import torch.nn as nn import torch.nn.functional as F import torch.optim as optim from torch.utils.data import DataLoader from torch.utils.data import TensorDataset import gensim from sklearn.model_selection import train_test_split class word_extract(nn.Module): def __init__(self,d_model,embedding_matrix): super(word_extract,self).__init__() self.d_model=d_model self.embedding=nn.Embedding(num_embeddings=len(embedding_matrix),embedding_dim=200) self.embedding.weight.data.copy_(embedding_matrix) self.embedding.weight.requires_grad=False self.lstm1=nn.LSTM(input_size=200,hidden_size=50,bidirectional=True) self.lstm2=nn.LSTM(input_size=2*self.lstm1.hidden_size,bidirectional=True) self.linear=nn.Linear(2*self.lstm2.hidden_size,4) def forward(self,x): w_x=self.embedding(x) first_x,(first_h_x,first_c_x)=self.lstm1(w_x) second_x,(second_h_x,second_c_x)=self.lstm2(first_x) output_x=self.linear(second_x) return output_x
將文字轉換為數值形式
def trans_num(word2idx,text): text_list=[] for i in text: s=i.rstrip().replace('\r','').replace('\n','').split(' ') numtext=[word2idx[j] if j in word2idx.keys() else word2idx['_PAD'] for j in s ] text_list.append(numtext) return text_list
將Gensim裡的詞向量模型轉為矩陣形式,後續匯入到LSTM模型中
def establish_word2vec_matrix(model): #負責將數值索引轉為要輸入的資料 word2idx = {"_PAD": 0} # 初始化 `[word : token]` 字典,後期 tokenize 語料庫就是用該詞典。 num2idx = {0: "_PAD"} vocab_list = [(k,model.wv[k]) for k,v in model.wv.vocab.items()] # 儲存所有 word2vec 中所有向量的陣列,留意其中多一位,詞向量全為 0, 用於 padding embeddings_matrix = np.zeros((len(model.wv.vocab.items()) + 1,model.vector_size)) for i in range(len(vocab_list)): word = vocab_list[i][0] word2idx[word] = i + 1 num2idx[i + 1] = word embeddings_matrix[i + 1] = vocab_list[i][1] embeddings_matrix = torch.Tensor(embeddings_matrix) return embeddings_matrix,word2idx,num2idx
訓練過程
def train(model,epoch,learning_rate,batch_size,x,y,val_x,val_y): optimizor = optim.Adam(model.parameters(),lr=learning_rate) data = TensorDataset(x,y) data = DataLoader(data,batch_size=batch_size) for i in range(epoch): for j,(per_x,per_y) in enumerate(data): output_y = model(per_x) loss = F.cross_entropy(output_y.view(-1,output_y.size(2)),per_y.view(-1)) optimizor.zero_grad() loss.backward() optimizor.step() arg_y=output_y.argmax(dim=2) fit_correct=(arg_y==per_y).sum() fit_acc=fit_correct.item()/(per_y.size(0)*per_y.size(1)) print('##################################') print('第{}次迭代第{}批次的訓練誤差為{}'.format(i + 1,j + 1,loss),end=' ') print('第{}次迭代第{}批次的訓練準確度為{}'.format(i + 1,fit_acc)) val_output_y = model(val_x) val_loss = F.cross_entropy(val_output_y.view(-1,val_output_y.size(2)),val_y.view(-1)) arg_val_y=val_output_y.argmax(dim=2) val_correct=(arg_val_y==val_y).sum() val_acc=val_correct.item()/(val_y.size(0)*val_y.size(1)) print('第{}次迭代第{}批次的預測誤差為{}'.format(i + 1,val_loss),end=' ') print('第{}次迭代第{}批次的預測準確度為{}'.format(i + 1,val_acc)) torch.save(model,'./extract_model.pkl')#儲存模型
主函式部分
if __name__ =='__main__': #生成詞向量矩陣 word2vec = gensim.models.Word2Vec.load('./word2vec_model') embedding_matrix,num2idx=establish_word2vec_matrix(word2vec)#輸入的是詞向量模型 # train_data=pd.read_csv('./資料.csv') x=list(train_data['文字']) # 將文字從文字轉化為數值,這部分trans_num函式你需要自己改動去適應你自己的資料集 x=trans_num(word2idx,x) #x需要先進行填充,也就是每個句子都是一樣長度,不夠長度的以0來填充,填充詞單獨分為一類 # #也就是說輸入的x是固定長度的數值列表,例如[50,123,1850,21,199,0,0,...] #輸入的y是[2,1,3,.....] #填充程式碼你自行編寫,以下部分是針對我的資料集 x=keras.preprocessing.sequence.pad_sequences( x,maxlen=60,value=0,padding='post',) y=list(train_data['BIO數值']) y_text=[] for i in y: s=i.rstrip().split(' ') numtext=[int(j) for j in s] y_text.append(numtext) y=y_text y=keras.preprocessing.sequence.pad_sequences( y,value=3,) # 將資料進行劃分 fit_x,fit_y,val_y=train_test_split(x,train_size=0.8,test_size=0.2) fit_x=torch.LongTensor(fit_x) fit_y=torch.LongTensor(fit_y) val_x=torch.LongTensor(val_x) val_y=torch.LongTensor(val_y) #開始應用 w_extract=word_extract(d_model=200,embedding_matrix=embedding_matrix) train(model=w_extract,epoch=5,learning_rate=0.001,batch_size=50,x=fit_x,y=fit_y,val_x=val_x,val_y=val_y)#可以自行改動引數,設定學習率,批次,和迭代次數 w_extract=torch.load('./extract_model.pkl')#載入儲存好的模型 pred_val_y=w_extract(val_x).argmax(dim=2)
以上這篇在pytorch中動態調整優化器的學習率方式就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。