wordpress下載站源碼營銷推廣公司案例
一般來說,大家使用VGG16,用的是第四列的網(wǎng)絡(luò)架構(gòu),而使用VGG19,使用的就是第六列的網(wǎng)絡(luò)架構(gòu)。
使用vgg進(jìn)行提取特征,在這個(gè)項(xiàng)目中,使用的就是每一塊卷積層的第一層。
import torch.nn as nn
from torchvision import models
from torchvision.models.vgg import VGG19_Weightsclass VGGNet(nn.Module):def __init__(self):super(VGGNet, self).__init__()self.select = ['0', '5', '10', '19', '28']# self.vgg = models.vgg19(pretrained=True).features # .features用于提取卷積層self.vgg = models.vgg19(weights=VGG19_Weights.IMAGENET1K_V1).featuresdef forward(self, x):features = []for name, layer in self.vgg._modules.items():x = layer(x) # name為第幾層的序列號(hào),layer就是卷積層,,x為輸入的圖片。x = layer(x)的意思是,x經(jīng)過layer層卷積后再賦值給xif name in self.select:features.append(x)return featuresnet = VGGNet()
print(net)
我們打印了一下我們定義的net
VGGNet((vgg): Sequential((0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(1): ReLU(inplace=True)(2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(3): ReLU(inplace=True)(4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(6): ReLU(inplace=True)(7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(8): ReLU(inplace=True)(9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(11): ReLU(inplace=True)(12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(13): ReLU(inplace=True)(14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(15): ReLU(inplace=True)(16): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(17): ReLU(inplace=True)(18): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(19): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(20): ReLU(inplace=True)(21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(22): ReLU(inplace=True)(23): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(24): ReLU(inplace=True)(25): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(26): ReLU(inplace=True)(27): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(29): ReLU(inplace=True)(30): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(31): ReLU(inplace=True)(32): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(33): ReLU(inplace=True)(34): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(35): ReLU(inplace=True)(36): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False))
)
講解
特征提取列表
self.select = ['0', '5', '10', '19', '28']
第一次看代碼的時(shí)候,會(huì)被這個(gè)列表給迷惑住,VGG19不是只有19層嗎,19層指的是除去maxpool,softmax這些層以外,卷積層和全連接層這些包含參數(shù)的層,共有19層。
但是,實(shí)際過程中,ReLU激活函數(shù),也算在里面,因此,上文打印出來,會(huì)超過19層,因此,通過對(duì)應(yīng)的索引,可以找到每塊卷積的第一層。
forward函數(shù)
最簡(jiǎn)單的解釋,就是將x逐層喂入神經(jīng)網(wǎng)絡(luò),當(dāng)經(jīng)過的這個(gè)層剛好是每塊卷積層的第一層,就將經(jīng)過這層的結(jié)果保存到列表中,該結(jié)果中保存的就是圖片的特征。
我們調(diào)試一下看看
import torch.nn as nn
import torch
from torchvision import models
from torchvision.models.vgg import VGG19_Weightsclass VGGNet(nn.Module):def __init__(self):super(VGGNet, self).__init__()self.select = ['0', '5', '10', '19', '28']# self.vgg = models.vgg19(pretrained=True).features # .features用于提取卷積層self.vgg = models.vgg19(weights=VGG19_Weights.IMAGENET1K_V1).features# self.vgg = models.vgg19(weights=VGG19_Weights.IMAGENET1K_V1).featuresdef forward(self, x):features = []for name, layer in self.vgg._modules.items():x = layer(x) # name為第幾層的序列號(hào),layer就是卷積層,,x為輸入的圖片。x = layer(x)的意思是,x經(jīng)過layer層卷積后再賦值給xif name in self.select:features.append(x)return featuresnet = VGGNet()
print(net)
input_tensor = torch.randn(1, 3, 256, 256)
output = net(input_tensor)
print(output)
可以看到,里面存放的是tensor格式的數(shù)據(jù)。
所以,經(jīng)過這個(gè)網(wǎng)絡(luò),提取了圖片的特征。