pytorch - 可视化

可视化网络结构

  1. 使用print函数打印模型基础信息
    只能得出基础构件的信息,既不能显示出每一层的shape,也不能显示对应参数量的大小
    1
    2
    import torchvision.models as models
    model = models.resnet18()
  2. 使用torchinfo可视化网络结构
    输出结构化的更详细的信息,包括模块信息(每一层的类型、输出shape和参数量)、模型整体的参数量、模型大小、一次前向或者反向传播需要的内存大小等
    1
    2
    3
    4
    import torchvision.models as models
    from torchinfo import summary
    resnet18 = models.resnet18() # 实例化模型
    summary(resnet18, (1, 3, 224, 224)) # 1:batch_size 3:图片的通道数 224: 图片的高宽

CNN可视化

  1. CNN卷积核可视化
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    import torch
    from torchvision.models import vgg11

    model = vgg11(pretrained=True)
    print(dict(model.features.named_children()))
    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')
  2. CNN特征图可视化方法
    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
    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, inputs):
    hh = Hook()
    model.features[idx].register_forward_hook(hh)

    # forward_model(model,False)
    model.eval()
    _ = model(inputs)
    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())
  3. CNN class activation map可视化方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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 = './dog.png'
    # 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
    14
    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

    target_layers = [model.features[-1]]
    # 选取合适的类激活图,但是ScoreCAM和AblationCAM需要batch_size
    cam = GradCAM(model=model,target_layers=target_layers)
    targets = [ClassifierOutputTarget(preds)]
    # 上方preds需要设定,比如ImageNet有1000类,这里可以设为200
    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)
  4. 使用FlashTorch快速实现CNN可视化
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    # 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
    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")

使用TensorBoard可视化训练过程

  1. TensorBoard安装
  2. TensorBoard可视化的基本逻辑
  3. TensorBoard的配置与启动
  4. TensorBoard模型结构可视化
    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
    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)

    writer.add_graph(model, input_to_model = torch.rand(1, 3, 224, 224))
    writer.close()
  5. TensorBoard图像可视化
    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
    import torchvision
    from torchvision import datasets, transforms
    from torch.utils.data import DataLoader

    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()
  6. TensorBoard连续变量可视化
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    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()

    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()
  7. TensorBoard参数分布可视化
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import torch
    import numpy as np

    # 创建正态分布的张量模拟参数矩阵
    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()
  8. 服务器端使用TensorBoard
  9. 总结
    TensorBoard的基本逻辑就是文件的读写逻辑,写入想要可视化的数据,然后TensorBoard自己会读出来。

    参考资料

    深入浅出PyTorch
作者

Yang

发布于

2022-10-22

更新于

2022-10-22

许可协议

评论