卷积核里面的参数怎么来的_使用pytorch查看中间层特征矩阵以及卷积核参数

推荐一个可视化工具:TensorBoard

注: 本次所使用的为AlexNet与ResNet34俩个网络,关于这俩个网络的详细信息可以在我另外俩篇blog查看

  • ResNet——CNN经典网络模型详解(pytorch实现)
  • AlexNet--CNN经典网络模型详解(pytorch实现)

查看中间层特征矩阵

AlexNet

alexnet_model.py

import torch.nn as nnimport torchclass AlexNet(nn.Module):    def __init__(self, num_classes=1000, init_weights=False):        super(AlexNet, self).__init__()        self.features = nn.Sequential(            nn.Conv2d(3, 48, kernel_size=11, stride=4, padding=2),  # input[3, 224, 224]  output[48, 55, 55]            nn.ReLU(inplace=True),            nn.MaxPool2d(kernel_size=3, stride=2),                  # output[48, 27, 27]            nn.Conv2d(48, 128, kernel_size=5, padding=2),           # output[128, 27, 27]            nn.ReLU(inplace=True),            nn.MaxPool2d(kernel_size=3, stride=2),                  # output[128, 13, 13]            nn.Conv2d(128, 192, kernel_size=3, padding=1),          # output[192, 13, 13]            nn.ReLU(inplace=True),            nn.Conv2d(192, 192, kernel_size=3, padding=1),          # output[192, 13, 13]            nn.ReLU(inplace=True),            nn.Conv2d(192, 128, kernel_size=3, padding=1),          # output[128, 13, 13]            nn.ReLU(inplace=True),            nn.MaxPool2d(kernel_size=3, stride=2),                  # output[128, 6, 6]        )        self.classifier = nn.Sequential(            nn.Dropout(p=0.5),            nn.Linear(128 * 6 * 6, 2048),            nn.ReLU(inplace=True),            nn.Dropout(p=0.5),            nn.Linear(2048, 2048),            nn.ReLU(inplace=True),            nn.Linear(2048, num_classes),        )        if init_weights:            self._initialize_weights()    def forward(self, x):        outputs = []        for name, module in self.features.named_children():            x = module(x)            if name in ["0", "3", "6"]:                outputs.append(x)        return outputs    def _initialize_weights(self):        for m in self.modules():            if isinstance(m, nn.Conv2d):                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')                if m.bias is not None:                    nn.init.constant_(m.bias, 0)            elif isinstance(m, nn.Linear):                nn.init.normal_(m.weight, 0, 0.01)                nn.init.constant_(m.bias, 0)

在 for name, module in self.features.named_children():设置一个断点来确认name是否为conv

afd0ff35c54ebb75341c92319eba1616.png

analyze_feature_map.py

import torchfrom alexnet_model import AlexNetfrom resnet_model import resnet34import matplotlib.pyplot as pltimport numpy as npfrom PIL import Imagefrom torchvision import transforms#图像预处理,要与生成alexnet.pth文件的train预处理一致data_transform = transforms.Compose(    [transforms.Resize((224, 224)),     transforms.ToTensor(),     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])# data_transform = transforms.Compose(#     [transforms.Resize(256),#      transforms.CenterCrop(224),#      transforms.ToTensor(),#      transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])# create modelmodel = AlexNet(num_classes=5)# model = resnet34(num_classes=5)# load model weightsmodel_weight_path = "./AlexNet.pth"  # "./resNet34.pth"model.load_state_dict(torch.load(model_weight_path))print(model)# load imageimg = Image.open("roses.jpg")# [N, C, H, W]img = data_transform(img)# expand batch dimensionimg = torch.unsqueeze(img, dim=0)# forwardout_put = model(img)for feature_map in out_put:    # [N, C, H, W] -> [C, H, W]    im = np.squeeze(feature_map.detach().numpy())    # [C, H, W] -> [H, W, C]print(model)    im = np.transpose(im, [1, 2, 0])    # show top 12 feature maps    plt.figure()    for i in range(12):        ax = plt.subplot(3, 4, i+1)#行,列,索引        # [H, W, C]        plt.imshow(im[:, :, i], cmap='gray')#cmap默认为蓝绿图    plt.show()

图中的俩个.pth文件为训练模型所生成,所以文件目录应该为

589586b7290a0a2072c83552864767f9.png

在out_put = model(img)设置一个断点,来查看print(model)的信息

47c5296a1754e9d718d570f6f1369e0a.png

在for feature_map in out_put:设置断点out_put = model(img)

6c06094b61d3c5f22499b31cc06fcaf6.png

原图

aaa68f9f4cef2b199a3cba6fd4817a9e.png

其输出为: conv1:

3f970ee83a9e8d656ae192fcf52801aa.png

conv2:

390f6190770e70ddcb12418eb27c924e.png

conv3

9e3c35663e702e5a6d6902e91ee374ea.png

若将plt.imshow(im[:, :, i], cmap='gray')中 cmap='gray'去掉

1d83b86d04bf722da8d9a3572436d881.png

ResnetNet34

resnet_model.py

import torch.nn as nnimport torchclass BasicBlock(nn.Module):    expansion = 1    def __init__(self, in_channel, out_channel, stride=1, downsample=None):        super(BasicBlock, self).__init__()        self.conv1 = nn.Conv2d(in_channels=in_channel, out_channels=out_channel,                               kernel_size=3, stride=stride, padding=1, bias=False)        self.bn1 = nn.BatchNorm2d(out_channel)        self.relu = nn.ReLU()        self.conv2 = nn.Conv2d(in_channels=out_channel, out_channels=out_channel,                               kernel_size=3, stride=1, padding=1, bias=False)        self.bn2 = nn.BatchNorm2d(out_channel)        self.downsample = downsample    def forward(self, x):        identity = x        if self.downsample is not None:            identity = self.downsample(x)        out = self.conv1(x)        out = self.bn1(out)        out = self.relu(out)        out = self.conv2(out)        out = self.bn2(out)        out += identity        out = self.relu(out)        return outclass Bottleneck(nn.Module):    expansion = 4    def __init__(self, in_channel, out_channel, stride=1, downsample=None):        super(Bottleneck, self).__init__()        self.conv1 = nn.Conv2d(in_channels=in_channel, out_channels=out_channel,                               kernel_size=1, stride=1, bias=False)  # squeeze channels        self.bn1 = nn.BatchNorm2d(out_channel)        # -----------------------------------------        self.conv2 = nn.Conv2d(in_channels=out_channel, out_channels=out_channel,                               kernel_size=3, stride=stride, bias=False, padding=1)        self.bn2 = nn.BatchNorm2d(out_channel)        # -----------------------------------------        self.conv3 = nn.Conv2d(in_channels=out_channel, out_channels=out_channel*self.expansion,                               kernel_size=1, stride=1, bias=False)  # unsqueeze channels        self.bn3 = nn.BatchNorm2d(out_channel*self.expansion)        self.relu = nn.ReLU(inplace=True)        self.downsample = downsample    def forward(self, x):        identity = x        if self.downsample is not None:            identity = self.downsample(x)        out = self.conv1(x)        out = self.bn1(out)        out = self.relu(out)        out = self.conv2(out)        out = self.bn2(out)        out = self.relu(out)        out = self.conv3(out)        out = self.bn3(out)        out += identity        out = self.relu(out)        return outclass ResNet(nn.Module):    def __init__(self, block, blocks_num, num_classes=1000, include_top=True):        super(ResNet, self).__init__()        self.include_top = include_top        self.in_channel = 64        self.conv1 = nn.Conv2d(3, self.in_channel, kernel_size=7, stride=2,                               padding=3, bias=False)        self.bn1 = nn.BatchNorm2d(self.in_channel)        self.relu = nn.ReLU(inplace=True)        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)        self.layer1 = self._make_layer(block, 64, blocks_num[0])        self.layer2 = self._make_layer(block, 128, blocks_num[1], stride=2)        self.layer3 = self._make_layer(block, 256, blocks_num[2], stride=2)        self.layer4 = self._make_layer(block, 512, blocks_num[3], stride=2)        if self.include_top:            self.avgpool = nn.AdaptiveAvgPool2d((1, 1))  # output size = (1, 1)            self.fc = nn.Linear(512 * block.expansion, num_classes)        for m in self.modules():            if isinstance(m, nn.Conv2d):                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')    def _make_layer(self, block, channel, block_num, stride=1):        downsample = None        if stride != 1 or self.in_channel != channel * block.expansion:            downsample = nn.Sequential(                nn.Conv2d(self.in_channel, channel * block.expansion, kernel_size=1, stride=stride, bias=False),                nn.BatchNorm2d(channel * block.expansion))        layers = []        layers.append(block(self.in_channel, channel, downsample=downsample, stride=stride))        self.in_channel = channel * block.expansion        for _ in range(1, block_num):            layers.append(block(self.in_channel, channel))        return nn.Sequential(*layers)    def forward(self, x):        outputs = []        x = self.conv1(x)        outputs.append(x)        x = self.bn1(x)        x = self.relu(x)        x = self.maxpool(x)        x = self.layer1(x)#仅查看layer1        outputs.append(x)        # x = self.layer2(x)        # x = self.layer3(x)        # x = self.layer4(x)        #        # if self.include_top:        #     x = self.avgpool(x)        #     x = torch.flatten(x, 1)        #     x = self.fc(x)        return outputsdef resnet34(num_classes=1000, include_top=True):    return ResNet(BasicBlock, [3, 4, 6, 3], num_classes=num_classes, include_top=include_top)def resnet101(num_classes=1000, include_top=True):    return ResNet(Bottleneck, [3, 4, 23, 3], num_classes=num_classes, include_top=include_top)

analyze_feature_map.py

import torchfrom alexnet_model import AlexNetfrom resnet_model import resnet34import matplotlib.pyplot as pltimport numpy as npfrom PIL import Imagefrom torchvision import transforms#图像预处理,要与生成alexnet.pth文件的train预处理一致# data_transform = transforms.Compose(#     [transforms.Resize((224, 224)),#      transforms.ToTensor(),#      transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])data_transform = transforms.Compose(    [transforms.Resize(256),     transforms.CenterCrop(224),     transforms.ToTensor(),     transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])# create model# model = AlexNet(num_classes=5)model = resnet34(num_classes=5)# load model weightsmodel_weight_path = "./resNet34.pth"  # "./resNet34.pth"model.load_state_dict(torch.load(model_weight_path))print(model)# load imageimg = Image.open("roses.jpg")# [N, C, H, W]img = data_transform(img)# expand batch dimensionimg = torch.unsqueeze(img, dim=0)# forwardout_put = model(img)for feature_map in out_put:    # [N, C, H, W] -> [C, H, W]    im = np.squeeze(feature_map.detach().numpy())    # [C, H, W] -> [H, W, C]print(model)    im = np.transpose(im, [1, 2, 0])    # show top 12 feature maps    plt.figure()    for i in range(12):        ax = plt.subplot(3, 4, i+1)#行,列,索引        # [H, W, C]        plt.imshow(im[:, :, i])#cmap默认为蓝绿图    plt.show()

在img = Image.open("roses.jpg")设置断点打印model层结构为

e89f53645a2d9cc60ca0cb3921c9e68a.png

最终的输出为

323a3a8515791778e8368442b47cade9.png
d0669650a377c5f3b59c729262b2f84d.png

对比可以发现resnet比alexnet更加好

查看卷积核参数

AlnexNet

analyze_kernel_weight.py

import torchfrom alexnet_model import AlexNetfrom resnet_model import resnet34import matplotlib.pyplot as pltimport numpy as np# create modelmodel = AlexNet(num_classes=5)# model = resnet34(num_classes=5)# load model weightsmodel_weight_path = "./AlexNet.pth"  # "resNet34.pth"model.load_state_dict(torch.load(model_weight_path))print(model)weights_keys = model.state_dict().keys()for key in weights_keys:    # remove num_batches_tracked para(in bn)    if "num_batches_tracked" in key:        continue    # [kernel_number, kernel_channel, kernel_height, kernel_width]    weight_t = model.state_dict()[key].numpy()    # read a kernel information    # k = weight_t[0, :, :, :]    # calculate mean, std, min, max    weight_mean = weight_t.mean()    weight_std = weight_t.std(ddof=1)    weight_min = weight_t.min()    weight_max = weight_t.max()    print("mean is {}, std is {}, min is {}, max is {}".format(weight_mean,                                                               weight_std,                                                               weight_max,                                                               weight_min))    # plot hist image    plt.close()    weight_vec = np.reshape(weight_t, [-1])    plt.hist(weight_vec, bins=50)    plt.title(key)    plt.show()

在weights_keys = model.state_dict().keys()设置断点来单步运行查看weights_keys

9d1759f2ca2c32eff76c2ad034d722d4.png

卷积核1kernel值分布

b7b218e65f5d22493c64e1ffab882ece.png

卷积核1偏置分布

f9b07d12b7a608eb4b9da1e2e00e62bc.png

下面也都一样

a5789f89b240c3d18c04c11ed267ff78.png
ab4cd1978612adede7f3adf95a2da879.png

ResNet34

analyze_kernel_weight.py

import torchfrom alexnet_model import AlexNetfrom resnet_model import resnet34import matplotlib.pyplot as pltimport numpy as np# create model# model = AlexNet(num_classes=5)model = resnet34(num_classes=5)# load model weightsmodel_weight_path = "./resNet34.pth"  # "resNet34.pth"model.load_state_dict(torch.load(model_weight_path))print(model)weights_keys = model.state_dict().keys()for key in weights_keys:    # remove num_batches_tracked para(in bn)    if "num_batches_tracked" in key:        continue    # [kernel_number, kernel_channel, kernel_height, kernel_width]    weight_t = model.state_dict()[key].numpy()    # read a kernel information    # k = weight_t[0, :, :, :]    # calculate mean, std, min, max    weight_mean = weight_t.mean()    weight_std = weight_t.std(ddof=1)    weight_min = weight_t.min()    weight_max = weight_t.max()    print("mean is {}, std is {}, min is {}, max is {}".format(weight_mean,                                                               weight_std,                                                               weight_max,                                                               weight_min))    # plot hist image    plt.close()    weight_vec = np.reshape(weight_t, [-1])    plt.hist(weight_vec, bins=50)    plt.title(key)    plt.show()

卷积层

7b24c31dae7ad169a1ad491c753e0adf.png

BN层 对BN忘记同学可以查看Batch Normalization(BN)超详细解析

ae73057653ec21dbbe513d08e71134cd.png

weight为参数

7e97e277617b546a444d9c93640367ce.png

bias为参数

226bcac37231df98f66744dda68bbbae.png

mean就是参数

1dfa578c6bf808afce050191c4c5ae87.png

var就是

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值