Pytorch框架學習---(5)調整學習率、可視化操作


本節簡單總結Pytorch中用於學習率調整的函數,如何使用tensorboard可視化曲線、梯度、權重、特征圖、卷積核,以及如何使用torchvision.utils.make_grid()制作網格圖。【文中思維導圖采用MindMaster軟件

1.學習率的調整

  Pytorch中封裝了調整LR的函數,如下:

  它們都繼承父類class _LRScheduler,需要復寫函數def get_lr(self),該函數用於計算學習率並返回:

class _LRScheduler(object):
    def __init__(self, optimizer, last_epoch=-1):
    ······
    def get_lr(self):
        raise NotImplementedError

  參數:

  • optimizer:優化器類實例

  • last_epoch:記錄epoch數

  • base_lrs:記錄初始學習率,該參數用於后續的學習率計算

  方法:

  • step():更新下一個epoch的學習率

  • get_lr():虛函數,計算下一個epoch學習率

節省精力, 由於網上已經有人對這六個函數總結的很好,故在此引用,不再復寫。

2.tensorboard可視化工具

(1)流程

(2)如何記錄可視化的數據?

  調用SummaryWriter類,代碼如下:

'''SummaryWriter類'''
class SummaryWriter(object):
    def __init__(self, log_dir=None, comment='', purge_step=None, max_queue=10,
                 flush_secs=120, filename_suffix=''):

# 參數如下:
      # log_dir:eventfile輸出文件夾地址
      # comment:當不指定log_dir時,該參數為文件夾的后綴
      # filename_suffix:eventfile文件名的后綴

'''實際運用時'''
from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter(log_dir='./a',comment="handw_exp",filename_suffix="test1")

若不指定log_dir,則直接該項目下創建runs文件夾,可對照下圖進行理解:

各種記錄數據的方法如下:

①scalar繪制曲線(單條、多條)

'''一張圖中,只能單條曲線'''
def add_scalar(self, tag, scalar_value, global_step=None, walltime=None):

# 參數:
      # tag:圖像的標簽名
      # scalar_value:要記錄的標量,例如loss
      # global_step:x軸

'''一張圖中,可以多條曲線'''
def add_scalars(self, main_tag, tag_scalar_dict, global_step=None, walltime=None):

# 參數:
      # main_tag:總的標簽名,用於曲線索引放置
      # tag_scalar_dict:要記錄的標量,例如loss
      # global_step:x軸

實戰中,以 def add_scalars 為例

iter_count = 0
for epoch in range(Max_Epoch):
    ······
    for i, (inputs, labels) in enumerate(train_loader):
        iter_count += 1
        ······
        writer.add_scalars(main_tag="Loss", tag_scalar_dict={"Train": loss.item()}, global_step=iter_count)
        writer.add_scalars("Accuracy", {"Train": correct/total}, global_step=iter_count)

    if (epoch+1) % print_info_valid == 0:
        ······
        with torch.no_grad():
            for j,(inputs_valid,labels_valid) in enumerate(test_loader):
            ······
            writer.add_scalars("Loss", {"Valid": loss_info_valid/len(test_loader)}, iter_count)
            writer.add_scalars("Accuracy", {"Valid": correct_valid / total_valid}, iter_count)
            writer.flush()  # 及時刷新,否則無法同時觀看到訓練和驗證
writer.close()

 此時通過pycharm終端,輸入 tensorboard --logdir=./a(event的地址),就會得到tensorboard的可視化網址,打開可以得到如下圖:

②histogram直方圖,查看權重、梯度,判斷是否梯度消失或發散

def add_histogram(self, tag, values, global_step=None, bins='tensorflow', walltime=None, max_bins=None):

# 參數:
      # tag:圖像的標簽名
      # values:要統計的參數
      # global_step:y軸!!!!!!!!!!!!!(結合下圖理解)

實戰中,代碼參考如下:

    # 每一個epoch,記錄各層權重、梯度
    for name, param in net.named_parameters():  # 返回網絡的
        writer.add_histogram(name + '_grad', param.grad, epoch)
        writer.add_histogram(name + '_data', param, epoch)

貌似橫軸是大小,高度代表該數值下的個數???:

③記錄圖像(利用torchvision.utils中make_grid制作網格)

torchvision.utils.make_grid()函數定義:

def make_grid(tensor, nrow=8, padding=2,
              normalize=False, range=None, scale_each=False, pad_value=0):

# 參數:
      # tensor:必須是B*C*H*W形式
      # nrow:指定行數
      # padding:圖像與圖像之間的間隔多少個像素單位pad_value
      # normalize:是否將像素值標准化到(0~255)
      # range:指定標准化范圍,先將像素值規范到該range,然后再進行(0~255)轉換
      # scale_each:是否對單張圖像進行range
      # pad_value:指定padding的大小(黑色0、白色255等等)

實戰中,代碼參考如下:

'''調用torchvision中make_grid 網格可視化圖像'''
import torchvision.utils as vutils
img_batch,label_batch = next(iter(train_loader))  # 調用一個批次的圖片
img_grid = vutils.make_grid(img_batch, nrow=10,normalize=True)  # 變為 C*H*W 

writer.add_image("make_grid",img_grid, global_step=0)
writer.flush()

'''當然也可以直接調用add_image或add_images'''
    def add_image(self, tag, img_tensor, global_step=None, walltime=None, dataformats='CHW'):
# 參數:
      # 非常不方便,只能查看一個圖像!!!!
      # 當像素值為【0,1】,則乘以255,縮放回【0,255】;若像素值不在【0,1】之間,默認是0~255范圍內。
      # tag:圖像的標簽名
      # img_tensor:注意shape,可以是3HW、HW3、HW、1HW,但不能是四維的,即有batch!!!!!!!(可以通過add_images解決或torchvision.utils.make_grid())
      # global_step:x軸

    def add_images(self, tag, img_tensor, global_step=None, walltime=None, dataformats='NCHW'):  
# 參數:
      # 無法指定行數!!!!!
      # tag:圖像的標簽名
      # img_tensor:注意shape,可以是NCHW or NHWC,但是,這里Channel在后續處理的時候只能為1或者3!!!!!
      # global_step:x軸

④利用make_grid可視化特征圖

(每次都要調出對應層,一個個輸入,一個個輸出,有點麻煩,即便調用for循環,代碼也有點冗余性,下一節介紹的hook函數就可以在網絡運行過程中,直接保存特征圖)

vlaid_img,_ = next(iter(test_loader))
conv1 = net.cpu().feature[0]
fmap1 = conv1(vlaid_img)  # 100*16*72*72
fmap1_first = fmap1[0,:,:,:]
fmap1_first.unsqueeze_(0).transpose_(0,1)  # 16*1*72*72

fmap1_grid = vutils.make_grid(fmap1_first,4,normalize=True)
writer.add_image("fmap", fmap1,global_step=0)

從下面的特征圖可以看出: 經過卷積核操作后,得到的各種特征圖(提取邊緣后、銳化后等等)。

⑤graph可視化模型計算圖

    def add_graph(self, model, input_to_model=None, verbose=False):
# 參數:
      # model:模型,必須是繼承torch.nn.Module
      # input_to_model:模型的輸入
      # verbose:是否打印計算圖結構信息

'''可視化模型計算圖'''
input_v = torch.rand((1,3,75,75))
writer.add_graph(net, input_v)
writer.flush()


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM