記錄模型訓練時loss值的變化情況
記錄訓練過程中的每一步的loss變化
if verbose and step % verbose == 0: sys.stdout.write('\r{} / {} : loss = {}'.format( step,total_steps,np.mean(total_loss))) sys.stdout.flush() if verbose: sys.stdout.write('\r') sys.stdout.flush()
一般我們在訓練神經網路模型的時候,都是每隔多少步,輸出列印一下loss或者每一步列印一下loss,今天發現了另一種記錄loss變化的方法,就是用
sys.stdout.write('\r{} / {} : loss = {}')
如圖上的程式碼,可以記錄每一個在每個epoch中記錄用一行輸出就可以記錄每個step的loss值變化,
\r就是輸出不會換行,因此如果你想同一樣輸出多次,在需要輸出的字串物件裡面加上"\r",就可以回到行首了。
sys.stdout.flush() #一秒輸出了一個數字
具體的實現就是下面的圖:
這樣在每個epoch中也可以觀察loss變化,但是隻需要列印一行,而不是每一行都輸出。
補充知識:訓練模型中損失(loss)異常分析
前言
訓練模型過程中隨時都要注意目標函式值(loss)的大小變化。一個正常的模型loss應該隨訓練輪數(epoch)的增加而緩慢下降,然後趨於穩定。雖然在模型訓練的初始階段,loss有可能會出現大幅度震盪變化,但是隻要資料量充分,模型正確,訓練的輪數足夠長,模型最終會達到收斂狀態,接近最優值或者找到了某個區域性最優值。在模型實際訓練過程中,可能會得到一些異常loss值,如loss等於nan;loss值忽大忽小,不收斂等。
下面根據自己使用Pythorh訓練模型的經驗,分析出一些具體原因和給出對應的解決辦法。
一、輸入資料
1. 資料的預處理
輸入到模型的資料一般都是經過了預處理的,如用pandas先進行資料處理,尤其要注意空值,缺失值,異常值。
缺失值:數值型別(NaN),物件型別(None,NaN),時間型別(NaT)
空值:""
異常值:不再正常區間範圍的值
例如對缺失值可以進行判斷df.isnull()或者df.isna();丟棄df.dropna();填充df.fillna()等操作。
輸入到模型中的資料一般而言都是數值型別的值,一定要保證不能出現NaN,numpy中的nan是一種特殊的float,該值數值運算的結果是不正常的,所以可能會導致loss值等於nan。可以用numpy.any(numpy.isnan(x))檢查一下input和target。
2. 資料的讀寫
例如使用Pandas讀取.csv型別的資料得到的DataFrame會新增預設的index,再寫回到磁碟會多一列。如果用其他讀取方式再讀入,可能會導致資料有問題,讀取到NaN。
import pandas as pd Output = pd.read_csv('./data/diabetes/Output.csv') trainOutput,testOutput = Output[:6000],Output[6000:] trainOutput.to_csv('./data/diabetes/trainOutput.csv') testOutput.to_csv('./data/diabetes/testOutput.csv')
3. 資料的格式
Pythorch中的 torch.utils.data.Dataset 類是一個表示資料集的抽象類。自己資料集的類應該繼承自 Dataset 並且重寫__len__方法和__getitem__方法:
__len__ : len(dataset) 返回資料集的大小
__getitem__ :用以支援索引操作, dataset[idx]能夠返回第idx個樣本資料
然後使用torch.utils.data.DataLoader 這個迭代器(iterator)來遍歷所有的特徵。具體可以參見這裡
在構造自己Dataset類時,需要注意返回的資料格式和型別,一般不會出現NaN的情況但是可能會導致資料float,int,long這幾種型別的不相容,注意轉換。
二、學習率
基於梯度下降的優化方法,當學習率太高時會導致loss值不收斂,太低則下降緩慢。需要對學習率等超引數進行調參如使用網格搜尋,隨機搜尋等。
三、除零錯
對於迴歸問題,可能出現了除0 的計算,加一個很小的餘項可能可以解決。類似於計算概率時進行的平滑修正,下面的程式碼片段中loss使用交叉混合熵(CossEntropy),計算3分類問題的AUC值,為了避免概率計算出現NaN而採取了相應的平滑處理。
from sklearn.metrics import roc_auc_score model_ft,y_true,losslists = test_model(model_ft,criterion,optimizer) n_class = 3 y_one_hot = np.eye(n_class)[y_true.reshape(-1)] # solve divide zero errot eps = 0.0000001 y_scores = losslists / (losslists.sum(axis=1,keepdims=True)+eps) #print(y_scores) #print(np.isnan(y_scores)) """ metrics.roc_auc_score(y_one_hot,y_pred) """ print("auc: ") roc_auc_score(y_one_hot,y_scores)
四、loss函式
loss函式程式碼編寫不正確或者已經編寫好的loss函式API使用不清楚
五、某些易錯程式碼
Pytorch在進行自動微分的時候,預設梯度是會累加的,所以需要在每個epoch的每個batch中對梯度清零,否則可能會導致loss值不收斂。不要忘記新增如下程式碼
optimizer.zero_grad()
以上這篇記錄模型訓練時loss值的變化情況就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。