1. 程式人生 > 程式設計 >記錄模型訓練時loss值的變化情況

記錄模型訓練時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() #一秒輸出了一個數字

具體的實現就是下面的圖:

記錄模型訓練時loss值的變化情況

這樣在每個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')

記錄模型訓練時loss值的變化情況

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值的變化情況就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。