【Pytorch基礎教程23】可視化網絡和訓練過程(pytorch訓練可視化)

      網友投稿 1641 2022-05-30

      學習總結

      TensorBoard,主要的實現(xiàn)方案是構建一個SummaryWriter,然后通過add_XXX()函數(shù)來實現(xiàn)。

      TensorBoard的基本邏輯:文件的讀寫邏輯。寫入想要可視化的數(shù)據(jù),然后TensorBoard自己會讀出來。

      torchinfo可視化網絡結構:模塊信息(每一層的類型、輸出shape和參數(shù)量)、模型整體的參數(shù)量、模型大小、一次前向或者反向傳播需要的內存大小。

      CNN可視化有多種方法:CAM和flashTorch(可視化梯度和可視化卷積核)。

      文章目錄

      學習總結

      一、可視化網絡結構

      1.1 使用print函數(shù)打印模型基礎信息

      1.2 使用torchinfo可視化網絡結構

      二、CNN可視化

      2.1 CNN卷積核可視化

      2.2 CNN特征圖可視化方法

      2.3 CNN class activation map(CAM)可視化方法

      2.4 用FlashTorch實現(xiàn)CNN特征可視化

      (1)可視化梯度

      (2)可視化卷積核

      三、使用TensorBoard可視化訓練過程(下載模型時更改本地路徑)

      3.1 TensorBoard可視化的基本邏輯

      【PyTorch基礎教程23】可視化網絡和訓練過程(pytorch訓練可視化)

      3.2 TensorBoard的配置與啟動

      3.3 TensorBoard模型結構可視化的完整栗子

      3.4 TensorBoard圖像可視化

      3.5 TensorBoard連續(xù)變量可視化

      3.6 TensorBoard參數(shù)分布可視化

      Reference

      一、可視化網絡結構

      為了更好確定復雜網絡模型中,每一層的輸入結構,輸出結構以及參數(shù)等信息,在Keras中可以調用一個叫做model.summary()的API能夠顯示我們的模型參數(shù),輸入大小,輸出大小,模型的整體參數(shù)等。

      在PyTorch中有torchinfo工具包 ( torchinfo是由torchsummary和torchsummaryX重構出的庫, torchsummary和torchsummaryX已經許久沒更新了) 。

      1.1 使用print函數(shù)打印模型基礎信息

      將使用ResNet18的結構進行展示。

      import torchvision.models as models model = models.resnet18()

      1

      2

      通過上面的兩步,我們就得到resnet18的模型結構。在學習torchinfo之前,讓我們先看下直接print(model)的結果。

      ResNet( (conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False) (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace=True) (maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False) (layer1): Sequential( (0): Bottleneck( (conv1): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False) (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False) (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False) (bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (relu): ReLU(inplace=True) (downsample): Sequential( (0): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False) (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) ) ) ... ... ) (avgpool): AdaptiveAvgPool2d(output_size=(1, 1)) (fc): Linear(in_features=2048, out_features=1000, bias=True) )

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      我們可以發(fā)現(xiàn)單純的print(model),只能得出基礎構件的信息,既不能顯示出每一層的shape,也不能顯示對應參數(shù)量的大小.

      1.2 使用torchinfo可視化網絡結構

      torchinfo的安裝

      # 安裝方法一 pip install torchinfo # 安裝方法二 conda install -c conda-forge torchinfo

      1

      2

      3

      4

      torchinfo的使用

      trochinfo的使用也是十分簡單,我們只需要使用torchinfo.summary()就行了,必需的參數(shù)分別是model,input_size[batch_size,channel,h,w],更多參數(shù)可以參考documentation.

      import torchvision.models as models from torchinfo import summary resnet18 = models.resnet18() # 實例化模型 summary(model, (1, 3, 224, 224)) # 1:batch_size 3:圖片的通道數(shù) 224: 圖片的高寬

      1

      2

      3

      4

      torchinfo的結構化輸出

      ========================================================================================= Layer (type:depth-idx) Output Shape Param # ========================================================================================= ResNet -- -- ├─Conv2d: 1-1 [1, 64, 112, 112] 9,408 ├─BatchNorm2d: 1-2 [1, 64, 112, 112] 128 ├─ReLU: 1-3 [1, 64, 112, 112] -- ├─MaxPool2d: 1-4 [1, 64, 56, 56] -- ├─Sequential: 1-5 [1, 64, 56, 56] -- │ └─BasicBlock: 2-1 [1, 64, 56, 56] -- │ │ └─Conv2d: 3-1 [1, 64, 56, 56] 36,864 │ │ └─BatchNorm2d: 3-2 [1, 64, 56, 56] 128 │ │ └─ReLU: 3-3 [1, 64, 56, 56] -- │ │ └─Conv2d: 3-4 [1, 64, 56, 56] 36,864 │ │ └─BatchNorm2d: 3-5 [1, 64, 56, 56] 128 │ │ └─ReLU: 3-6 [1, 64, 56, 56] -- │ └─BasicBlock: 2-2 [1, 64, 56, 56] -- │ │ └─Conv2d: 3-7 [1, 64, 56, 56] 36,864 │ │ └─BatchNorm2d: 3-8 [1, 64, 56, 56] 128 │ │ └─ReLU: 3-9 [1, 64, 56, 56] -- │ │ └─Conv2d: 3-10 [1, 64, 56, 56] 36,864 │ │ └─BatchNorm2d: 3-11 [1, 64, 56, 56] 128 │ │ └─ReLU: 3-12 [1, 64, 56, 56] -- ├─Sequential: 1-6 [1, 128, 28, 28] -- │ └─BasicBlock: 2-3 [1, 128, 28, 28] -- │ │ └─Conv2d: 3-13 [1, 128, 28, 28] 73,728 │ │ └─BatchNorm2d: 3-14 [1, 128, 28, 28] 256 │ │ └─ReLU: 3-15 [1, 128, 28, 28] -- │ │ └─Conv2d: 3-16 [1, 128, 28, 28] 147,456 │ │ └─BatchNorm2d: 3-17 [1, 128, 28, 28] 256 │ │ └─Sequential: 3-18 [1, 128, 28, 28] 8,448 │ │ └─ReLU: 3-19 [1, 128, 28, 28] -- │ └─BasicBlock: 2-4 [1, 128, 28, 28] -- │ │ └─Conv2d: 3-20 [1, 128, 28, 28] 147,456 │ │ └─BatchNorm2d: 3-21 [1, 128, 28, 28] 256 │ │ └─ReLU: 3-22 [1, 128, 28, 28] -- │ │ └─Conv2d: 3-23 [1, 128, 28, 28] 147,456 │ │ └─BatchNorm2d: 3-24 [1, 128, 28, 28] 256 │ │ └─ReLU: 3-25 [1, 128, 28, 28] -- ├─Sequential: 1-7 [1, 256, 14, 14] -- │ └─BasicBlock: 2-5 [1, 256, 14, 14] -- │ │ └─Conv2d: 3-26 [1, 256, 14, 14] 294,912 │ │ └─BatchNorm2d: 3-27 [1, 256, 14, 14] 512 │ │ └─ReLU: 3-28 [1, 256, 14, 14] -- │ │ └─Conv2d: 3-29 [1, 256, 14, 14] 589,824 │ │ └─BatchNorm2d: 3-30 [1, 256, 14, 14] 512 │ │ └─Sequential: 3-31 [1, 256, 14, 14] 33,280 │ │ └─ReLU: 3-32 [1, 256, 14, 14] -- │ └─BasicBlock: 2-6 [1, 256, 14, 14] -- │ │ └─Conv2d: 3-33 [1, 256, 14, 14] 589,824 │ │ └─BatchNorm2d: 3-34 [1, 256, 14, 14] 512 │ │ └─ReLU: 3-35 [1, 256, 14, 14] -- │ │ └─Conv2d: 3-36 [1, 256, 14, 14] 589,824 │ │ └─BatchNorm2d: 3-37 [1, 256, 14, 14] 512 │ │ └─ReLU: 3-38 [1, 256, 14, 14] -- ├─Sequential: 1-8 [1, 512, 7, 7] -- │ └─BasicBlock: 2-7 [1, 512, 7, 7] -- │ │ └─Conv2d: 3-39 [1, 512, 7, 7] 1,179,648 │ │ └─BatchNorm2d: 3-40 [1, 512, 7, 7] 1,024 │ │ └─ReLU: 3-41 [1, 512, 7, 7] -- │ │ └─Conv2d: 3-42 [1, 512, 7, 7] 2,359,296 │ │ └─BatchNorm2d: 3-43 [1, 512, 7, 7] 1,024 │ │ └─Sequential: 3-44 [1, 512, 7, 7] 132,096 │ │ └─ReLU: 3-45 [1, 512, 7, 7] -- │ └─BasicBlock: 2-8 [1, 512, 7, 7] -- │ │ └─Conv2d: 3-46 [1, 512, 7, 7] 2,359,296 │ │ └─BatchNorm2d: 3-47 [1, 512, 7, 7] 1,024 │ │ └─ReLU: 3-48 [1, 512, 7, 7] -- │ │ └─Conv2d: 3-49 [1, 512, 7, 7] 2,359,296 │ │ └─BatchNorm2d: 3-50 [1, 512, 7, 7] 1,024 │ │ └─ReLU: 3-51 [1, 512, 7, 7] -- ├─AdaptiveAvgPool2d: 1-9 [1, 512, 1, 1] -- ├─Linear: 1-10 [1, 1000] 513,000 ========================================================================================= Total params: 11,689,512 Trainable params: 11,689,512 Non-trainable params: 0 Total mult-adds (G): 1.81 ========================================================================================= Input size (MB): 0.60 Forward/backward pass size (MB): 39.75 Params size (MB): 46.76 Estimated Total Size (MB): 87.11 =========================================================================================

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      64

      65

      66

      67

      68

      69

      70

      71

      72

      73

      74

      75

      76

      77

      78

      79

      80

      81

      82

      83

      84

      我們可以看到torchinfo提供了更加詳細的信息,包括模塊信息(每一層的類型、輸出shape和參數(shù)量)、模型整體的參數(shù)量、模型大小、一次前向或者反向傳播需要的內存大小等

      注意:當你使用的是colab或者jupyter notebook時,想要實現(xiàn)該方法,summary()一定是該單元(即notebook中的cell)的返回值,否則我們就需要使用print(summary(...))來可視化。

      二、CNN可視化

      卷積神經網絡(CNN)是深度學習中非常重要的模型結構,它廣泛地用于圖像處理,極大地提升了模型表現(xiàn),推動了計算機視覺的發(fā)展和進步。但CNN是一個“黑盒模型”,人們并不知道CNN是如何獲得較好表現(xiàn)的,由此帶來了深度學習的可解釋性問題。

      如果能理解CNN工作的方式,人們不僅能夠解釋所獲得的結果,提升模型的魯棒性,而且還能有針對性地改進CNN的結構以獲得進一步的效果提升。

      理解CNN的重要一步是可視化,包括

      可視化特征是如何提取的、提取到的特征的形式以及模型在輸入數(shù)據(jù)上的關注點等

      。本節(jié)我們就從上述三個方面出發(fā),介紹如何在PyTorch的框架下完成CNN模型的可視化。

      2.1 CNN卷積核可視化

      卷積核在CNN中負責提取特征,可視化卷積核能夠幫助人們理解CNN各個層在提取什么樣的特征,進而理解模型的工作原理。例如在Zeiler和Fergus 2013年的paper中就研究了CNN各個層的卷積核的不同,他們發(fā)現(xiàn)靠近輸入的層提取的特征是相對簡單的結構,而靠近輸出的層提取的特征就和圖中的實體形狀相近了,如下圖所示:

      在PyTorch中可視化卷積核也非常方便,

      核心在于特定層的卷積核即特定層的模型權重,可視化卷積核就等價于可視化對應的權重矩陣

      。下面給出在PyTorch中可視化卷積核的實現(xiàn)方案,以torchvision自帶的VGG11模型為例。

      首先加載模型,并確定模型的層信息:

      import torch from torchvision.models import vgg11 model = vgg11(pretrained=True) print(dict(model.features.named_children()))

      1

      2

      3

      4

      5

      {'0': Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)), '1': ReLU(inplace=True), '2': MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False), '3': Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)), '4': ReLU(inplace=True), '5': MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False), '6': Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)), '7': ReLU(inplace=True), '8': Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)), '9': ReLU(inplace=True), '10': MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False), '11': Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)), '12': ReLU(inplace=True), '13': Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)), '14': ReLU(inplace=True), '15': MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False), '16': Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)), '17': ReLU(inplace=True), '18': Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)), '19': ReLU(inplace=True), '20': MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)}

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      卷積核對應的應為卷積層(Conv2d),這里以第“3”層為例,可視化對應的參數(shù):

      import matplotlib.pyplot as plt conv1 = dict(model.features.named_children())['3'] kernel_set = conv1.weight.detach() num = len(conv1.weight.detach()) print(kernel_set.shape) for i in range(0,num): i_kernel = kernel_set[i] plt.figure(figsize=(20, 17)) if (len(i_kernel)) > 1: for idx, filer in enumerate(i_kernel): plt.subplot(9, 9, idx+1) plt.axis('off') plt.imshow(filer[ :, :].detach(),cmap='bwr')

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      torch.Size([128, 64, 3, 3])

      1

      由于第“3”層的特征圖由64維變?yōu)?28維,因此共有128*64個卷積核,其中部分卷積核可視化效果如下圖所示:

      2.2 CNN特征圖可視化方法

      與卷積核相對應,輸入的原始圖像經過每次卷積層得到的數(shù)據(jù)稱為特征圖(feature map),可視化卷積核是為了看模型提取哪些特征,可視化特征圖則是為了看模型提取到的特征是什么樣子的。

      獲取特征圖的方法有很多種,可以從輸入開始,逐層做前向傳播,直到想要的特征圖處將其返回。盡管這種方法可行,但是有些麻煩了。

      在PyTorch中,提供了一個專用的接口使得網絡在前向傳播過程中能夠獲取到特征圖,這個接口的名稱非常形象,叫做hook。

      可以想象這樣的場景,數(shù)據(jù)通過網絡向前傳播,網絡某一層我們預先設置了一個鉤子,數(shù)據(jù)傳播過后鉤子上會留下數(shù)據(jù)在這一層的樣子,讀取鉤子的信息就是這一層的特征圖。具體實現(xiàn)如下:

      class Hook(object): def __init__(self): self.module_name = [] self.features_in_hook = [] self.features_out_hook = [] def __call__(self,module, fea_in, fea_out): print("hooker working", self) self.module_name.append(module.__class__) self.features_in_hook.append(fea_in) self.features_out_hook.append(fea_out) return None def plot_feature(model, idx): hh = Hook() model.features[idx].register_forward_hook(hh) forward_model(model,False) print(hh.module_name) print((hh.features_in_hook[0][0].shape)) print((hh.features_out_hook[0].shape)) out1 = hh.features_out_hook[0] total_ft = out1.shape[1] first_item = out1[0].cpu().clone() plt.figure(figsize=(20, 17)) for ftidx in range(total_ft): if ftidx > 99: break ft = first_item[ftidx] plt.subplot(10, 10, ftidx+1) plt.axis('off') #plt.imshow(ft[ :, :].detach(),cmap='gray') plt.imshow(ft[ :, :].detach())

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      這里我們首先實現(xiàn)了一個hook類,之后在plot_feature函數(shù)中,將該hook類的對象注冊到要進行可視化的網絡的某層中。model在進行前向傳播的時候會調用hook的__call__函數(shù),我們也就是在那里存儲了當前層的輸入和輸出。這里的features_out_hook 是一個list,每次前向傳播一次,都是調用一次,也就是features_out_hook 長度會增加1。

      2.3 CNN class activation map(CAM)可視化方法

      class activation map (CAM)的作用是判斷哪些變量對模型來說是重要的,在CNN可視化的場景下,即判斷圖像中哪些像素點對預測結果是重要的。除了確定重要的像素點,人們也會對重要區(qū)域的梯度感興趣,因此在CAM的基礎上也進一步改進得到了Grad-CAM(以及諸多變種)。CAM和Grad-CAM的示例如下圖所示:

      相比可視化卷積核與可視化特征圖,CAM系列可視化更為直觀,能夠一目了然地確定重要區(qū)域,進而進行可解釋性分析或模型優(yōu)化改進。CAM系列操作的實現(xiàn)可以通過開源工具包pytorch-grad-cam來實現(xiàn)。

      安裝

      pip install grad-cam

      1

      一個簡單的例子

      import torch from torchvision.models import vgg11,resnet18,resnet101,resnext101_32x8d import matplotlib.pyplot as plt from PIL import Image import numpy as np model = vgg11(pretrained=True) img_path = './wu.jpg' # resize操作是為了和傳入神經網絡訓練圖片大小一致 img = Image.open(img_path).resize((224,224)) # 需要將原始圖片轉為np.float32格式并且在0-1之間 rgb_img = np.float32(img)/255 plt.imshow(img)

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      from pytorch_grad_cam import GradCAM,ScoreCAM,GradCAMPlusPlus,AblationCAM,XGradCAM,EigenCAM,FullGrad from pytorch_grad_cam.utils.model_targets import ClassifierOutputTarget from pytorch_grad_cam.utils.image import show_cam_on_image, preprocess_image target_layers = [model.features[-1]] # 選取合適的類激活圖,但是ScoreCAM和AblationCAM需要batch_size cam = GradCAM(model=model,target_layers=target_layers) preds = 200 targets = [ClassifierOutputTarget(preds)] # preprocess_image作用:歸一化圖像,并轉成tensor img_tensor = preprocess_image(rgb_img, mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) grayscale_cam = cam(input_tensor=img_tensor, targets=targets) grayscale_cam = grayscale_cam[0, :] cam_img = show_cam_on_image(rgb_img, grayscale_cam, use_rgb=True) print(type(cam_img)) Image.fromarray(cam_img)

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      結果有點神奇哈哈,都注意在吳恩達大佬的衣服像素點上了:

      2.4 用FlashTorch實現(xiàn)CNN特征可視化

      pytorch的FlashTorch工具也能實現(xiàn)CNN的可視化。Backprop類的核心就是創(chuàng)建顯著圖。安裝:pip install flashtorch。

      在實例化時,它接收模型Backprop(model)并將自定義鉤子注冊到網絡中感興趣的層,以便我們可以從計算圖中獲取中間梯度以進行可視化。由于PyTorch的設計方式,這些中間梯度并不是立即可用的。FlashTorch會幫你整理。

      具體參考FlashTorch的github文檔。

      (1)可視化梯度

      # Download example images # !mkdir -p images # !wget -nv \ # https://github.com/MisaOgura/flashtorch/raw/master/examples/images/great_grey_owl.jpg \ # https://github.com/MisaOgura/flashtorch/raw/master/examples/images/peacock.jpg \ # https://github.com/MisaOgura/flashtorch/raw/master/examples/images/toucan.jpg \ # -P /content/images import matplotlib.pyplot as plt import torchvision.models as models from flashtorch.utils import apply_transforms, load_image from flashtorch.saliency import Backprop model = models.alexnet(pretrained=True) backprop = Backprop(model) image = load_image('/content/images/great_grey_owl.jpg') owl = apply_transforms(image) target_class = 24 backprop.visualize(owl, target_class, guided=True, use_gpu=True)

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      (2)可視化卷積核

      import torchvision.models as models from flashtorch.activmax import GradientAscent model = models.vgg16(pretrained=True) g_ascent = GradientAscent(model.features) # specify layer and filter info conv5_1 = model.features[24] conv5_1_filters = [45, 271, 363, 489] g_ascent.visualize(conv5_1, conv5_1_filters, title="VGG16: conv5_1")

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      三、使用TensorBoard可視化訓練過程(下載模型時更改本地路徑)

      訓練過程的可視化在深度學習模型訓練中扮演著重要的角色。學習的過程是一個優(yōu)化的過程,我們需要找到最優(yōu)的點作為訓練過程的輸出產物。

      一般會

      結合訓練集的損失函數(shù)和驗證集的損失函數(shù),繪制兩條損失函數(shù)的曲線來確定訓練的終點,找到對應的模型用于測試

      。那么除了記錄訓練中每個epoch的loss值,能否實時觀察損失函數(shù)曲線的變化,及時捕捉模型的變化呢?

      為了可視化其他內容,如輸入數(shù)據(jù)(尤其是圖片)、模型結構、參數(shù)分布等,這些對于我們在debug中查找問題來源非常重要(比如輸入數(shù)據(jù)和我們想象的是否一致)。這就要用到TensorBoard了。

      【TensorBoard安裝】

      在已安裝PyTorch的環(huán)境下使用pip安裝即可:

      pip install tensorboard

      1

      也可以使用PyTorch自帶的tensorboard工具,此時不需要額外安裝tensorboard。

      3.1 TensorBoard可視化的基本邏輯

      原本是tensorflow的可視化工具,pytorch從1.2.0開始支持tensorboard。之前的版本也可以使用tensorboardX代替。

      調用tensorboard中的SummaryWriter作為上述“記錄員”,它可以記錄我們指定的數(shù)據(jù),包括模型每一層的feature map,權重,以及訓練loss等等。將記錄下來的內容保存在一個用戶指定的文件夾里。

      TensorBoard程序不斷運行中TensorBoard會不斷記錄。記錄下的內容可以通過網頁的形式加以可視化。這一步通過命令行運行tensorboard完成。

      3.2 TensorBoard的配置與啟動

      (1)TensorBoard的配置

      在使用TensorBoard前,我們需要先指定一個文件夾供TensorBoard保存記錄下來的數(shù)據(jù)。

      然后調用tensorboard中的SummaryWriter作為上述“記錄員”。下面的操作實例化SummaryWritter為變量writer,并指定writer的輸出目錄為當前目錄下的"runs"目錄。也就是說,之后tensorboard記錄下來的內容都會保存在runs。

      from tensorboardX import SummaryWriter writer = SummaryWriter('./runs') # 如果使用PyTorch自帶的tensorboard,則采用如下方式import: from torch.utils.tensorboard import SummaryWriter

      1

      2

      3

      4

      5

      6

      可以手動往runs文件夾里添加數(shù)據(jù)用于可視化,或者把runs文件夾里的數(shù)據(jù)放到其他機器上可視化。

      (2)模型訓練(可以參考3.4的栗子),保存tensorboard記錄結果到對應文件。

      (3)TensorBoard的啟動,在命令行中輸入:

      tensorboard --logdir=/path/to/logs/ --port=xxxx

      1

      其中“path/to/logs/“是指定的保存tensorboard記錄結果的文件路徑(等價于上面的“./runs”,port是外部訪問TensorBoard的端口號,可以通過訪問ip:port訪問tensorboard,這一操作和jupyter notebook的使用類似。如果不是在服務器遠程使用的話則不需要配置port。

      為了tensorboard能夠不斷地在后臺運行,也可以使用nohup命令或者tmux工具來運行tensorboard。

      3.3 TensorBoard模型結構可視化的完整栗子

      writer對象可以拿出傳入它參數(shù)路徑里的數(shù)據(jù),這個writer對象也包含多個方法。首先來了解幾個API:

      可視化模型結構:writer.add_graph

      可視化指標變化:writer.add_scalar,比如針對數(shù)值,可以調用

      writer.add_scalar(tag, scalar_value, global_step=None, walltime=None)

      1

      可視化參數(shù)分布:writer.add_histogram

      可視化原始圖像:writer.add_image 或 writer.add_images

      可視化人工繪圖:writer.add_figure

      首先定義模型:

      import torch.nn as nn class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(in_channels=3,out_channels=32,kernel_size = 3) self.pool = nn.MaxPool2d(kernel_size = 2,stride = 2) self.conv2 = nn.Conv2d(in_channels=32,out_channels=64,kernel_size = 5) self.adaptive_pool = nn.AdaptiveMaxPool2d((1,1)) self.flatten = nn.Flatten() self.linear1 = nn.Linear(64,32) self.relu = nn.ReLU() self.linear2 = nn.Linear(32,1) self.sigmoid = nn.Sigmoid() def forward(self,x): x = self.conv1(x) x = self.pool(x) x = self.conv2(x) x = self.pool(x) x = self.adaptive_pool(x) x = self.flatten(x) x = self.linear1(x) x = self.relu(x) x = self.linear2(x) y = self.sigmoid(x) return y model = Net() print(model)

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      輸出如下:

      Net( (conv1): Conv2d(3, 32, kernel_size=(3, 3), stride=(1, 1)) (pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (conv2): Conv2d(32, 64, kernel_size=(5, 5), stride=(1, 1)) (adaptive_pool): AdaptiveMaxPool2d(output_size=(1, 1)) (flatten): Flatten(start_dim=1, end_dim=-1) (linear1): Linear(in_features=64, out_features=32, bias=True) (relu): ReLU() (linear2): Linear(in_features=32, out_features=1, bias=True) (sigmoid): Sigmoid() )

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      可視化模型的思路和1.1中介紹的方法一樣,都是

      給定一個輸入數(shù)據(jù),前向傳播后得到模型的結構

      ,再通過TensorBoard進行可視化,其實是使用add_graph:

      writer.add_graph(model, input_to_model = torch.rand(1, 3, 224, 224)) writer.close()

      1

      2

      展示結果如下(其中框內部分初始會顯示為“Net",需要雙擊后才會展開):

      在左側欄也可以download當前的流程圖片:

      3.4 TensorBoard圖像可視化

      當我們做圖像相關的任務時,可以方便地將所處理的圖片在tensorboard中進行可視化展示。

      對于單張圖片的顯示使用add_image

      對于多張圖片的顯示使用add_images

      有時需要使用torchvision.utils.make_grid將多張圖片拼成一張圖片后,用writer.add_image顯示

      這里我們使用torchvision的CIFAR10數(shù)據(jù)集為例:

      import torchvision from torchvision import datasets, transforms from torch.utils.data import DataLoader from tensorboardX import SummaryWriter transform_train = transforms.Compose( [transforms.ToTensor()]) transform_test = transforms.Compose( [transforms.ToTensor()]) train_data = datasets.CIFAR10(".", train=True, download=True, transform=transform_train) test_data = datasets.CIFAR10(".", train=False, download=True, transform=transform_test) train_loader = DataLoader(train_data, batch_size=64, shuffle=True) test_loader = DataLoader(test_data, batch_size=64) images, labels = next(iter(train_loader)) # 僅查看一張圖片 writer = SummaryWriter('./pytorch_tb') writer.add_image('images[0]', images[0]) writer.close() # 將多張圖片拼接成一張圖片,中間用黑色網格分割 # create grid of images writer = SummaryWriter('./pytorch_tb') img_grid = torchvision.utils.make_grid(images) writer.add_image('image_grid', img_grid) writer.close() # 將多張圖片直接寫入 writer = SummaryWriter('./pytorch_tb') writer.add_images("images",images,global_step = 0) writer.close()

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      依次運行上面三組可視化(注意

      不要同時在notebook的一個單元格內運行

      ),得到的可視化結果如下(最后運行的結果在最上面):

      注意上方menu部分,剛剛只有“GRAPHS"欄對應模型的可視化,現(xiàn)在則多出了”IMAGES“欄對應圖像的可視化。左側的滑動按鈕可以調整圖像的亮度和對比度。

      除了可視化原始圖像,TensorBoard提供的可視化方案自然也適用于我們在Python中用matplotlib等工具繪制的其他圖像,用于展示分析結果等內容。

      3.5 TensorBoard連續(xù)變量可視化

      TensorBoard可以用來可視化連續(xù)變量(或時序變量)的變化過程,通過add_scalar實現(xiàn):

      writer = SummaryWriter('./pytorch_tb') for i in range(500): x = i y = x**2 writer.add_scalar("x", x, i) #日志中記錄x在第step i 的值 writer.add_scalar("y", y, i) #日志中記錄y在第step i 的值 writer.close()

      1

      2

      3

      4

      5

      6

      7

      可視化結果如下:

      如果想在同一張圖中顯示多個曲線,則需要分別建立存放子路徑(使用SummaryWriter指定路徑即可自動創(chuàng)建,但需要在tensorboard運行目錄下),同時在add_scalar中修改曲線的標簽使其一致即可:

      writer1 = SummaryWriter('./pytorch_tb/x') writer2 = SummaryWriter('./pytorch_tb/y') for i in range(500): x = i y = x*2 writer1.add_scalar("same", x, i) #日志中記錄x在第step i 的值 writer2.add_scalar("same", y, i) #日志中記錄y在第step i 的值 writer1.close() writer2.close()

      1

      2

      3

      4

      5

      6

      7

      8

      9

      這里也可以用一個writer,但for循環(huán)中不斷創(chuàng)建SummaryWriter不是一個好選項。此時左下角的Runs部分出現(xiàn)了勾選項,我們可以選擇我們想要可視化的曲線。曲線名稱對應存放子路徑的名稱(這里是x和y)。

      損失函數(shù)的可視化,可以幫助我們更加直觀地了解模型的訓練情況,從而確定最佳的checkpoint。左側的Smoothing滑動按鈕可以調整曲線的平滑度,當損失函數(shù)震蕩較大時,將Smoothing調大有助于觀察loss的整體變化趨勢。

      3.6 TensorBoard參數(shù)分布可視化

      當我們需要對參數(shù)(或向量)的變化,或者對其分布進行研究時,可以方便地用TensorBoard來進行可視化,通過add_histogram實現(xiàn)。

      import torch import numpy as np # 創(chuàng)建正態(tài)分布的張量模擬參數(shù)矩陣 def norm(mean, std): t = std * torch.randn((100, 20)) + mean return t writer = SummaryWriter('./pytorch_tb/') for step, mean in enumerate(range(-10, 10, 1)): w = norm(mean, 1) writer.add_histogram("w", w, step) writer.flush() writer.close()

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      結果如下:

      Reference

      https://andrewhuman.github.io/cnn-hidden-layout_search

      https://github.com/jacobgil/pytorch-grad-cam

      https://github.com/MisaOgura/flashtorch

      https://blog.csdn.net/Python_Ai_Road/article/details/107704530

      datawhale notebook

      如何利用CAM(類激活圖)動態(tài)可視化模型的學習過程

      Tensorflow Tensorboard 報錯 “No dashboards are active for the current data set.“ 解決方案 原因分析

      解決問題:AssertionError: Torch not compiled with CUDA enabled

      一個庫可視化類激活熱力圖Grad-CAM pytorch版本

      torchkeras,像Keras一樣訓練Pytorch模型

      TensorBoard可視化

      扁扁筆記

      PyTorch 下使用 Tensorboard

      pytorch 機器學習 神經網絡

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:Python基礎語法回顧(python基本語法總結)
      下一篇:excel制作組織結構圖的教程(怎樣制作組織結構圖excel)
      相關文章
      亚洲韩国精品无码一区二区三区| 亚洲成综合人影院在院播放| 亚洲AV人无码综合在线观看| 亚洲欧洲日产国码高潮αv| 亚洲人成电影在线观看网| 亚洲色偷拍另类无码专区| 亚洲精品天堂成人片?V在线播放| 亚洲综合av一区二区三区 | 久久亚洲精品11p| 亚洲国产精品无码中文lv| 亚洲综合精品第一页| 亚洲影院天堂中文av色| 中文字幕无码亚洲欧洲日韩| 亚洲色欲色欲www| 伊人久久五月丁香综合中文亚洲| 亚洲妇女熟BBW| 亚洲第一综合天堂另类专| 亚洲人成电影网站色| 亚洲色大成网站www永久男同| 亚洲人成无码网站在线观看| 亚洲精品美女久久7777777| 亚洲日韩精品无码专区| 亚洲AV香蕉一区区二区三区| 亚洲av乱码中文一区二区三区| 亚洲av成人无码网站…| 五月天婷亚洲天综合网精品偷| 亚洲成a人片在线观看久| 亚洲日韩在线观看免费视频| 美腿丝袜亚洲综合| 久久亚洲综合色一区二区三区| 亚洲Aⅴ无码专区在线观看q| 久久久婷婷五月亚洲97号色| 91嫩草亚洲精品| 亚洲性无码一区二区三区| 亚洲AV无码一区二区三区久久精品 | 亚洲AV一二三区成人影片| 香蕉大伊亚洲人在线观看| 亚洲国产成人无码AV在线| 亚洲不卡AV影片在线播放| 国产亚洲人成A在线V网站 | 亚洲av无码一区二区三区网站 |