.mb是什么文件_神经网络长什么样不知道? 这有一份简单的 pytorch可视化技巧(1)
神經網絡長什么樣不知道?這有一份簡單的 pytorch可視化技巧(1)
深度學習這幾年伴隨著硬件性能的進一步提升,人們開始著手于設計更深更復雜的神經網絡,有時候我們在開源社區(qū)拿到網絡模型的時候,做客可能 不會直接開源模型代碼,而是給出一個模型的參數文件,當我們想要復現算法的時候,很可能就需要靠自己手動仿造源作者設計的神經網絡進行搭建,為了方便我們設計網絡,我結合了我最近的工作積累,給大家分享一些關于 pytorch 的網絡可視化方法
以下所有代碼我已經開源:https://github.com/OUCMachineLearning/OUCML/blob/master/One%20Day%20One%20GAN/day11/pytorch_show_1.ipynb>
pytorch-summary
https://github.com/sksq96/pytorch-summary 最簡單的 pytorch 網絡結構打印方法,也是最不依賴各種環(huán)境的一個輕量級可視化網絡結構pytorch 擴展包 類似于Keras style的model.summary() 以前用過Keras的朋友應該見過,Keras有一個簡潔的API來查看模型的可視化,這在調試網絡時非常有用。這是一個準備在PyTorch中模仿相同的準系統(tǒng)代碼。目的是提供補充信息,以及PyTorch中print(your_model)未提供的信息。
使用方法
pip 下載安裝 torchsummary
- pip install torchsummary or
- git clone https://github.com/sksq96/pytorch-summary
- 請注意,input_size是進行網絡正向傳遞所必需的。
一個簡單的例子:
CNN for MNSIT
import torch import torch.nn as nn import torch.nn.functional as F from torchsummary import summaryclass Net(nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 = nn.Conv2d(1, 10, kernel_size=5)self.conv2 = nn.Conv2d(10, 20, kernel_size=5)self.conv2_drop = nn.Dropout2d()self.fc1 = nn.Linear(320, 50)self.fc2 = nn.Linear(50, 10)def forward(self, x):x = F.relu(F.max_pool2d(self.conv1(x), 2))x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))x = x.view(-1, 320)x = F.relu(self.fc1(x))x = F.dropout(x, training=self.training)x = self.fc2(x)return F.log_softmax(x, dim=1)device = torch.device("cuda" if torch.cuda.is_available() else "cpu") # PyTorch v0.4.0 model = Net().to(device)summary(model, (1, 28, 28)) ----------------------------------------------------------------Layer (type) Output Shape Param # ================================================================Conv2d-1 [-1, 10, 24, 24] 260Conv2d-2 [-1, 20, 8, 8] 5,020Dropout2d-3 [-1, 20, 8, 8] 0Linear-4 [-1, 50] 16,050Linear-5 [-1, 10] 510 ================================================================ Total params: 21,840 Trainable params: 21,840 Non-trainable params: 0 ---------------------------------------------------------------- Input size (MB): 0.00 Forward/backward pass size (MB): 0.06 Params size (MB): 0.08 Estimated Total Size (MB): 0.15 ----------------------------------------------------------------可視化 torchvision 里邊的 vgg
import torch from torchvision import models from torchsummary import summarydevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu') vgg = models.vgg11_bn().to(device)summary(vgg, (3, 224, 224)) ----------------------------------------------------------------Layer (type) Output Shape Param # ================================================================Conv2d-1 [-1, 64, 224, 224] 1,792BatchNorm2d-2 [-1, 64, 224, 224] 128ReLU-3 [-1, 64, 224, 224] 0MaxPool2d-4 [-1, 64, 112, 112] 0Conv2d-5 [-1, 128, 112, 112] 73,856BatchNorm2d-6 [-1, 128, 112, 112] 256ReLU-7 [-1, 128, 112, 112] 0MaxPool2d-8 [-1, 128, 56, 56] 0Conv2d-9 [-1, 256, 56, 56] 295,168BatchNorm2d-10 [-1, 256, 56, 56] 512ReLU-11 [-1, 256, 56, 56] 0Conv2d-12 [-1, 256, 56, 56] 590,080BatchNorm2d-13 [-1, 256, 56, 56] 512ReLU-14 [-1, 256, 56, 56] 0MaxPool2d-15 [-1, 256, 28, 28] 0Conv2d-16 [-1, 512, 28, 28] 1,180,160BatchNorm2d-17 [-1, 512, 28, 28] 1,024ReLU-18 [-1, 512, 28, 28] 0Conv2d-19 [-1, 512, 28, 28] 2,359,808BatchNorm2d-20 [-1, 512, 28, 28] 1,024ReLU-21 [-1, 512, 28, 28] 0MaxPool2d-22 [-1, 512, 14, 14] 0Conv2d-23 [-1, 512, 14, 14] 2,359,808BatchNorm2d-24 [-1, 512, 14, 14] 1,024ReLU-25 [-1, 512, 14, 14] 0Conv2d-26 [-1, 512, 14, 14] 2,359,808BatchNorm2d-27 [-1, 512, 14, 14] 1,024ReLU-28 [-1, 512, 14, 14] 0MaxPool2d-29 [-1, 512, 7, 7] 0Linear-30 [-1, 4096] 102,764,544ReLU-31 [-1, 4096] 0Dropout-32 [-1, 4096] 0Linear-33 [-1, 4096] 16,781,312ReLU-34 [-1, 4096] 0Dropout-35 [-1, 4096] 0Linear-36 [-1, 1000] 4,097,000 ================================================================ Total params: 132,868,840 Trainable params: 132,868,840 Non-trainable params: 0 ---------------------------------------------------------------- Input size (MB): 0.57 Forward/backward pass size (MB): 181.84 Params size (MB): 506.85 Estimated Total Size (MB): 689.27 ----------------------------------------------------------------好處是我們可以很直觀的看到我們一個 batch_size的 Tensor 輸入神經網絡的時候需要多到多少的空間,缺點呢就是我們不能直觀的看到各層網絡間的連接結構
HiddenLayer
https://github.com/waleedka/hiddenlayer
HiddenLayer是一個可以用于PyTorch,Tensorflow和Keras的神經網絡圖和訓練指標的輕量級庫。 HiddenLayer簡單易用,適用于Jupyter Notebook。它不是要取代高級工具,例如TensorBoard,而是用于高級工具對于任務來說太大的情況。
安裝grazhviz
推薦使用 conda安裝,一鍵配置其所需要的環(huán)境
conda install graphviz python-graphvizOtherwise:
- Install GraphViz
- Then install the
Python wrapper for GraphViz
using pip:pip3 install graphviz
Install HiddenLayer
pip install hiddenlayer一個簡單的例子
VGG16
import torch import torchvision.models import hiddenlayer as hl# VGG16 with BatchNorm model = torchvision.models.vgg16()# Build HiddenLayer graph # Jupyter Notebook renders it automatically hl.build_graph(model, torch.zeros([1, 3, 224, 224]))在可視化網絡之前,我們先將 VGG 網絡實例化,然后個 hiddenlayer 輸入進去一個([1,3,224,224])的四階張量(意思相當于一張224*224的 RGB 圖片)
使用 transforms把殘差塊縮寫表示
# Resnet101 device = torch.device("cuda") print("device = ", device) model = torchvision.models.resnet152().cuda()# Rather than using the default transforms, build custom ones to group # nodes of residual and bottleneck blocks. transforms = [# Fold Conv, BN, RELU layers into onehl.transforms.Fold("Conv > BatchNorm > Relu", "ConvBnRelu"),# Fold Conv, BN layers togetherhl.transforms.Fold("Conv > BatchNorm", "ConvBn"),# Fold bottleneck blockshl.transforms.Fold("""((ConvBnRelu > ConvBnRelu > ConvBn) | ConvBn) > Add > Relu""", "BottleneckBlock", "Bottleneck Block"),# Fold residual blockshl.transforms.Fold("""ConvBnRelu > ConvBnRelu > ConvBn > Add > Relu""","ResBlock", "Residual Block"),# Fold repeated blockshl.transforms.FoldDuplicates(), ]# Display graph using the transforms above resnet152=hl.build_graph(model, torch.zeros([1, 3, 224, 224]).cuda(), transforms=transforms)保存圖片
resnet152.save("resnet152")有了網絡結構圖,我們便會像,如何把我們的模型他訓練的結果可視化出來呢?
比如我們經常在論文中看到這樣的圖:
import os import time import random import numpy as np import torch import torchvision.models import torch.nn as nn from torchvision import datasets, transforms import hiddenlayer as hl一個簡單的回歸的例子:
# New history and canvas objects history2 = hl.History() canvas2 = hl.Canvas()# Simulate a training loop with two metrics: loss and accuracy loss = 1 accuracy = 0 for step in range(800):# Fake loss and accuracyloss -= loss * np.random.uniform(-.09, 0.1)accuracy = max(0, accuracy + (1 - accuracy) * np.random.uniform(-.09, 0.1))# Log metrics and display them at certain intervalsif step % 10 == 0:history2.log(step, loss=loss, accuracy=accuracy)# Draw two plots# Encluse them in a "with" context to ensure they render togetherwith canvas2:canvas2.draw_plot([history1["loss"], history2["loss"]],labels=["Loss 1", "Loss 2"])canvas2.draw_plot([history1["accuracy"], history2["accuracy"]],labels=["Accuracy 1", "Accuracy 2"])time.sleep(0.1)序列化保存結果和加載:
# Save experiments 1 and 2 history1.save("experiment1.pkl") history2.save("experiment2.pkl") # Load them again. To verify it's working, load them into new objects. h1 = hl.History() h2 = hl.History() h1.load("experiment1.pkl") h2.load("experiment2.pkl")利用餅狀圖來顯示
class MyCanvas(hl.Canvas):"""Extending Canvas to add a pie chart method."""def draw_pie(self, metric):# Method name must start with 'draw_' for the Canvas to automatically manage it# Use the provided matplotlib Axes in self.axself.ax.axis('equal') # set square aspect ratio# Get latest value of the metricvalue = np.clip(metric.data[-1], 0, 1)# Draw pie chartself.ax.pie([value, 1-value], labels=["Accuracy", ""]) history3 = hl.History() canvas3 = MyCanvas() # My custom Canvas# Simulate a training loop loss = 1 accuracy = 0 for step in range(400):# Fake loss and accuracyloss -= loss * np.random.uniform(-.09, 0.1)accuracy = max(0, accuracy + (1 - accuracy) * np.random.uniform(-.09, 0.1))if step % 10 == 0:# Log loss and accuracyhistory3.log(step, loss=loss, accuracy=accuracy)# Log a fake image metric (e.g. image generated by a GAN)image = np.sin(np.sum(((np.indices([32, 32]) - 16) * 0.5 * accuracy) ** 2, 0))history3.log(step, image=image)# Displaywith canvas3:canvas3.draw_pie(history3["accuracy"])canvas3.draw_plot([history3["accuracy"], history3["loss"]])canvas3.draw_image(history3["image"])time.sleep(0.1)手動搭建一個簡易的分類網絡
import torch import torch.nn as nn import torch.optim as optim import torch.nn.functional as F import torch.backends.cudnn as cudnn import torchvision import torchvision.transforms as transforms import numpy as np import os import argparse # Simple Convolutional Network class CifarModel(nn.Module):def __init__(self):super(CifarModel, self).__init__()self.c2d=nn.Conv2d(3, 16, kernel_size=3, padding=1)self.features = nn.Sequential(nn.BatchNorm2d(16),nn.ReLU(),nn.Conv2d(16, 16, kernel_size=3, padding=1),nn.BatchNorm2d(16),nn.ReLU(),nn.MaxPool2d(2, 2),nn.Conv2d(16, 32, kernel_size=3, padding=1),nn.BatchNorm2d(32),nn.ReLU(),nn.Conv2d(32, 32, kernel_size=3, padding=1),nn.BatchNorm2d(32),nn.ReLU(),nn.MaxPool2d(2, 2),nn.Conv2d(32, 32, kernel_size=3, padding=1),nn.BatchNorm2d(32),nn.ReLU(),nn.Conv2d(32, 32, kernel_size=3, padding=1),nn.BatchNorm2d(32),nn.ReLU(),nn.AdaptiveMaxPool2d(1))self.classifier = nn.Sequential(nn.Linear(32, 32), # TODO: nn.BatchNorm2d(32),nn.ReLU(),nn.Linear(32, 10))def forward(self, x):x_0=self.c2d(x)x1 = self.features(x_0)self.feature_map=x_0x2 = x1.view(x1.size(0), -1)x3 = self.classifier(x2)return x3model = CifarModel().cuda() device = 'cuda' if torch.cuda.is_available() else 'cpu' criterion = torch.nn.CrossEntropyLoss() optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9)#show parameter summary(model, (3, 32, 32))hl.build_graph(model,torch.zeros([1,3,32,32]).cuda()) ----------------------------------------------------------------Layer (type) Output Shape Param # ================================================================Conv2d-1 [-1, 16, 32, 32] 448BatchNorm2d-2 [-1, 16, 32, 32] 32ReLU-3 [-1, 16, 32, 32] 0Conv2d-4 [-1, 16, 32, 32] 2,320BatchNorm2d-5 [-1, 16, 32, 32] 32ReLU-6 [-1, 16, 32, 32] 0MaxPool2d-7 [-1, 16, 16, 16] 0Conv2d-8 [-1, 32, 16, 16] 4,640BatchNorm2d-9 [-1, 32, 16, 16] 64ReLU-10 [-1, 32, 16, 16] 0Conv2d-11 [-1, 32, 16, 16] 9,248BatchNorm2d-12 [-1, 32, 16, 16] 64ReLU-13 [-1, 32, 16, 16] 0MaxPool2d-14 [-1, 32, 8, 8] 0Conv2d-15 [-1, 32, 8, 8] 9,248BatchNorm2d-16 [-1, 32, 8, 8] 64ReLU-17 [-1, 32, 8, 8] 0Conv2d-18 [-1, 32, 8, 8] 9,248BatchNorm2d-19 [-1, 32, 8, 8] 64ReLU-20 [-1, 32, 8, 8] 0 AdaptiveMaxPool2d-21 [-1, 32, 1, 1] 0Linear-22 [-1, 32] 1,056ReLU-23 [-1, 32] 0Linear-24 [-1, 10] 330 ================================================================ Total params: 36,858 Trainable params: 36,858 Non-trainable params: 0 ---------------------------------------------------------------- Input size (MB): 0.01 Forward/backward pass size (MB): 1.27 Params size (MB): 0.14 Estimated Total Size (MB): 1.42 ----------------------------------------------------------------加載數據
# Data print('==> Preparing data..') transform_train = transforms.Compose([transforms.RandomCrop(32, padding=4),transforms.RandomHorizontalFlip(),transforms.ToTensor(),transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)), ])transform_test = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)), ])trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform_train) trainloader = torch.utils.data.DataLoader(trainset, batch_size=128, shuffle=True, num_workers=2)testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform_test) testloader = torch.utils.data.DataLoader(testset, batch_size=100, shuffle=False, num_workers=2)classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck') ==> Preparing data.. Files already downloaded and verified Files already downloaded and verified train_dataset.data Tensor uint8 (50000, 32, 32, 3) min: 0.000 max: 255.000 train_dataset.labels list len: 50000 [6, 9, 9, 4, 1, 1, 2, 7, 8, 3] test_dataset.data Tensor uint8 (10000, 32, 32, 3) min: 0.000 max: 255.000 test_dataset.labels list len: 10000 [3, 8, 8, 0, 6, 6, 1, 6, 3, 1]訓練分類器
step = (0, 0) # tuple of (epoch, batch_ix) cifar_history = hl.History() cifar_canvas = hl.Canvas()# Training loop for epoch in range(10):train_iter = iter(trainloader)for batch_ix, (inputs, labels) in enumerate(train_iter):# Update global step counterstep = (epoch, batch_ix)optimizer.zero_grad()inputs = inputs.to(device)labels = labels.to(device)# forward + backward + optimizeoutputs = model(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()# Print statisticsif batch_ix and batch_ix % 100 == 0:# Compute accuracypred_labels = np.argmax(outputs.detach().cpu().numpy(), 1)accuracy = np.mean(pred_labels == labels.detach().cpu().numpy())# Log metrics to historycifar_history.log((epoch, batch_ix),loss=loss, accuracy=accuracy,conv1_weight=model.c2d.weight,feature_map=model.feature_map[0,1].detach().cpu().numpy())# Visualize metricswith cifar_canvas:cifar_canvas.draw_plot([cifar_history["loss"], cifar_history["accuracy"]])cifar_canvas.draw_image(cifar_history["feature_map"])cifar_canvas.draw_hist(cifar_history["conv1_weight"])通過hook 的方法,我們抓取了分類器里面第一層卷積層的輸出以及其 weight 參數,通過
step = (0, 0) # tuple of (epoch, batch_ix)cifar_history = hl.History()cifar_canvas = hl.Canvas()# Training loopfor epoch in range(10):train_iter = iter(trainloader)for batch_ix, (inputs, labels) in enumerate(train_iter):# Update global step counterstep = (epoch, batch_ix)optimizer.zero_grad()inputs = inputs.to(device)labels = labels.to(device)# forward + backward + optimizeoutputs = model(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()# Print statisticsif batch_ix and batch_ix % 100 == 0:# Compute accuracypred_labels = np.argmax(outputs.detach().cpu().numpy(), 1)accuracy = np.mean(pred_labels == labels.detach().cpu().numpy())# Log metrics to historycifar_history.log((epoch, batch_ix),loss=loss, accuracy=accuracy,conv1_weight=model.c2d.weight,feature_map=model.feature_map[0,1].detach().cpu().numpy())# Visualize metricswith cifar_canvas:cifar_canvas.draw_plot([cifar_history["loss"], cifar_history["accuracy"]])cifar_canvas.draw_image(cifar_history["feature_map"])cifar_canvas.draw_hist(cifar_history["conv1_weight"])通過hook 的方法,我們抓取了分類器里面第一層卷積層的輸出以及其 weight 參數,通過
step = (0, 0) # tuple of (epoch, batch_ix)cifar_history = hl.History()cifar_canvas = hl.Canvas()# Training loopfor epoch in range(10):train_iter = iter(trainloader)for batch_ix, (inputs, labels) in enumerate(train_iter):# Update global step counterstep = (epoch, batch_ix)optimizer.zero_grad()inputs = inputs.to(device)labels = labels.to(device)# forward + backward + optimizeoutputs = model(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()# Print statisticsif batch_ix and batch_ix % 100 == 0:# Compute accuracypred_labels = np.argmax(outputs.detach().cpu().numpy(), 1)accuracy = np.mean(pred_labels == labels.detach().cpu().numpy())# Log metrics to historycifar_history.log((epoch, batch_ix),loss=loss, accuracy=accuracy,conv1_weight=model.c2d.weight,feature_map=model.feature_map[0,1].detach().cpu().numpy())# Visualize metricswith cifar_canvas:cifar_canvas.draw_plot([cifar_history["loss"], cifar_history["accuracy"]])cifar_canvas.draw_image(cifar_history["feature_map"])cifar_canvas.draw_hist(cifar_history["conv1_weight"])通過hook 的方法,我們抓取了分類器里面第一層卷積層的輸出以及其 weight 參數,通過draw_image 和 draw_hist 的方法,把他們學習的過程動態(tài)的可視化出來(在我 github 上會放出其全部實現的代碼喲)
大家可以仿造我的寫法,拿到具體某一次特征圖的輸出.
總結
以上是生活随笔為你收集整理的.mb是什么文件_神经网络长什么样不知道? 这有一份简单的 pytorch可视化技巧(1)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何运行一段python代码_Pytho
- 下一篇: cent 8.0 安装tomcat 9.