DenseNet——CNN經典網絡模型詳解(pytorch實現)

2021-01-11 程序猿浩波

DenseNet——CNN經典網絡模型詳解(pytorch實現)

一個CV小白,寫文章目的為了讓和我意義的小白輕鬆如何,讓大佬鞏固基礎(手動狗頭),大家有任何問題可以一起在評論區留言討論~

一、概述

論文:Densely Connected Convolutional Networks 論文連結:https://arxiv.org/pdf/1608.06993.pdf

作為CVPR2017年的Best Paper, DenseNet脫離了加深網絡層數(ResNet)和加寬網絡結構(Inception)來提升網絡性能的定式思維,從特徵的角度考慮,通過特徵重用和旁路(Bypass)設置,既大幅度減少了網絡的參數量,又在一定程度上緩解了gradient vanishing問題的產生.結合信息流和特徵復用的假設,DenseNet當之無愧成為2017年計算機視覺頂會的年度最佳論文.

卷積神經網絡在沉睡了近20年後,如今成為了深度學習方向最主要的網絡結構之一.從一開始的只有五層結構的LeNet, 到後來擁有19層結構的VGG, 再到首次跨越100層網絡的Highway Networks與ResNet, 網絡層數的加深成為CNN發展的主要方向之一.

隨著CNN網絡層數的不斷增加,gradient vanishing和model degradation問題出現在了人們面前,BatchNormalization的廣泛使用在一定程度上緩解了gradient vanishing的問題,而ResNet和Highway Networks通過構造恆等映射設置旁路,進一步減少了gradient vanishing和model degradation的產生.Fractal Nets通過將不同深度的網絡並行化,在獲得了深度的同時保證了梯度的傳播,隨機深度網絡通過對網絡中一些層進行失活,既證明了ResNet深度的冗餘性,又緩解了上述問題的產生. 雖然這些不同的網絡框架通過不同的實現加深的網絡層數,但是他們都包含了相同的核心思想,既將feature map進行跨網絡層的連接.

DenseNet作為另一種擁有較深層數的卷積神經網絡,具有如下優點:

(1) 相比ResNet擁有更少的參數數量.(2) 旁路加強了特徵的重用.(3) 網絡更易於訓練,並具有一定的正則效果.(4) 緩解了gradient vanishing和model degradation的問題.何愷明先生在提出ResNet時做出了這樣的假設:若某一較深的網絡多出另一較淺網絡的若干層有能力學習到恆等映射,那麼這一較深網絡訓練得到的模型性能一定不會弱於該淺層網絡.

通俗的說就是如果對某一網絡中增添一些可以學到恆等映射的層組成新的網路,那麼最差的結果也是新網絡中的這些層在訓練後成為恆等映射而不會影響原網絡的性能.同樣DenseNet在提出時也做過假設:與其多次學習冗餘的特徵,特徵復用是一種更好的特徵提取方式.

二、DenseNet

在深度學習網絡中,隨著網絡深度的加深,梯度消失問題會愈加明顯,目前很多論文都針對這個問題提出了解決方案,比如ResNet,Highway Networks,Stochastic depth,FractalNets等,儘管這些算法的網絡結構有差別,但是核心都在於:create short paths from early layers to later layers。那麼作者是怎麼做呢?延續這個思路,那就是在保證網絡中層與層之間最大程度的信息傳輸的前提下,直接將所有層連接起來!

先放一個dense block的結構圖。在傳統的卷積神經網絡中,如果你有L層,那麼就會有L個連接,但是在DenseNet中,會有L(L+1)/2個連接。簡單講,就是每一層的輸入來自前面所有層的輸出。如下圖:x0是input,H1的輸入是x0(input),H2的輸入是x0和x1(x1是H1的輸出)……

DenseNet的一個優點是網絡更窄,參數更少,很大一部分原因得益於這種dense block的設計,後面有提到在dense block中每個卷積層的輸出feature map的數量都很小(小於100),而不是像其他網絡一樣動不動就幾百上千的寬度。同時這種連接方式使得特徵和梯度的傳遞更加有效,網絡也就更加容易訓練。

原文的一句話非常喜歡:Each layer has direct access to the gradients from the loss function and the original input signal, leading to an implicit deep supervision.直接解釋了為什麼這個網絡的效果會很好。前面提到過梯度消失問題在網絡深度越深的時候越容易出現,原因就是輸入信息和梯度信息在很多層之間傳遞導致的,而現在這種dense connection相當於每一層都直接連接input和loss,因此就可以減輕梯度消失現象,這樣更深網絡不是問題。另外作者還觀察到這種dense connection有正則化的效果,因此對於過擬合有一定的抑制作用,博主認為是因為參數減少了(後面會介紹為什麼參數會減少),所以過擬合現象減輕。

這篇文章的一個優點就是基本上沒有公式,不像灌水文章一樣堆複雜公式把人看得一愣一愣的。文章中只有兩個公式,是用來闡述DenseNet和ResNet的關係,對於從原理上理解這兩個網絡還是非常重要的。

第一個公式是ResNet的。這裡的l表示層,xl表示l層的輸出,Hl表示一個非線性變換。所以對於ResNet而言,l層的輸出是l-1層的輸出加上對l-1層輸出的非線性變換。第二個公式是DenseNet的。[x0,x1,…,xl-1]表示將0到l-1層的輸出feature map做concatenation。concatenation是做通道的合併,就像Inception那樣。而前面resnet是做值的相加,通道數是不變的。Hl包括BN,ReLU和3*3的卷積。 所以從這兩個公式就能看出DenseNet和ResNet在本質上的區別,太精闢了。接著說下論文中一直提到的Identity function: 很簡單 就是輸出等於輸入

傳統的前饋網絡結構可以看成處理網絡狀態(特徵圖?)的算法,狀態從層之間傳遞,每個層從之前層讀入狀態,然後寫入之後層,可能會改變狀態,也會保持傳遞不變的信息。ResNet是通過Identity transformations來明確傳遞這種不變信息。

再看下面,前面的Figure 1表示的是dense block,而下面的Figure 2表示的則是一個DenseNet的結構圖,在這個結構圖中包含了3個dense block。作者將DenseNet分成多個dense block,原因是希望各個dense block內的feature map的size統一,這樣在做concatenation就不會有size的問題。

這個Table1(下圖)就是整個網絡的結構圖。

這個表中的k=32,k=48中的k是growth rate,表示每個dense block中每層輸出的feature map個數。為了避免網絡變得很寬,作者都是採用較小的k,比如32這樣,

作者的實驗也表明小的k可以有更好的效果。根據dense block的設計,後面幾層可以得到前面所有層的輸入,因此concat後的輸入channel還是比較大的。另外這裡每個dense block的33卷積前面都包含了一個11的卷積操作,就是所謂的bottleneck layer,目的是減少輸入的feature map數量,既能降維減少計算量,又能融合各個通道的特徵,何樂而不為。

另外作者為了進一步壓縮參數,在每兩個dense block之間又增加了11的卷積操作。因此在後面的實驗對比中,如果你看到DenseNet-C這個網絡,表示增加了這個Translation layer,該層的11卷積的輸出channel默認是輸入channel到一半。如果你看到DenseNet-BC這個網絡,表示既有bottleneck layer,又有Translation layer。

再詳細說下bottleneck和transition layer操作

在每個Dense Block中都包含很多個子結構,以DenseNet-169的Dense Block(3)為例,包含32個11和33的卷積操作,也就是第32個子結構的輸入是前面31層的輸出結果,每層輸出的channel是32(growth rate),那麼如果不做bottleneck操作,第32層的33卷積操作的輸入就是3132+(上一個Dense Block的輸出channel),近1000了。而加上11的卷積,代碼中的11卷積的channel是growth rate4,也就是128,然後再作為33卷積的輸入。這就大大減少了計算量,這就是bottleneck。

至於transition layer,放在兩個Dense Block中間,是因為每個Dense Block結束後的輸出channel個數很多,需要用11的卷積核來降維。還是以DenseNet-169的Dense Block(3)為例,雖然第32層的33卷積輸出channel只有32個(growth rate),但是緊接著還會像前面幾層一樣有通道的concat操作,即將第32層的輸出和第32層的輸入做concat,前面說過第32層的輸入是1000左右的channel,所以最後每個Dense Block的輸出也是1000多的channel。因此這個transition layer有個參數reduction(範圍是0到1),表示將這些輸出縮小到原來的多少倍,默認是0.5,這樣傳給下一個Dense Block的時候channel數量就會減少一半,這就是transition layer的作用。文中還用到dropout操作來隨機減少分支,避免過擬合,畢竟這篇文章的連接確實多。

實驗結果:

作者在不同數據集上採用的DenseNet網絡會有一點不一樣,比如在Imagenet數據集上,DenseNet-BC有4個dense block,但是在別的數據集上只用3個dense block。其他更多細節可以看論文3部分的Implementation Details。訓練的細節和超參數的設置可以看論文4.2部分,在ImageNet數據集上測試的時候有做224*224的center crop。

Table2是在三個數據集(C10,C100,SVHN)上和其他算法的對比結果。ResNet[11]就是kaiming He的論文,對比結果一目了然。DenseNet-BC的網絡參數和相同深度的DenseNet相比確實減少了很多!參數減少除了可以節省內存,還能減少過擬合這裡對於SVHN數據集,DenseNet-BC的結果並沒有DenseNet(k=24)的效果好,作者認為原因主要是SVHN這個數據集相對簡單,更深的模型容易過擬合。在表格的倒數第二個區域的三個不同深度L和k的DenseNet的對比可以看出隨著L和k的增加,模型的效果是更好的。

Figure3是DenseNet-BC和ResNet在Imagenet數據集上的對比,左邊那個圖是參數複雜度和錯誤率的對比,你可以在相同錯誤率下看參數複雜度,也可以在相同參數複雜度下看錯誤率,提升還是很明顯的!右邊是flops(可以理解為計算複雜度)和錯誤率的對比,同樣有效果。

Figure4也很重要。左邊的圖表示不同類型DenseNet的參數和error對比。中間的圖表示DenseNet-BC和ResNet在參數和error的對比,相同error下,DenseNet-BC的參數複雜度要小很多。右邊的圖也是表達DenseNet-BC-100隻需要很少的參數就能達到和ResNet-1001相同的結果。

在設計初,DenseNet便被設計成讓一層網絡可以使用所有之前層網絡feature map的網絡結構,為了探索feature的復用情況,作者進行了相關實驗.作者訓練的L=40,K=12的DenseNet,對於任意Denseblock中的所有卷積層,計算之前某層feature map在該層權重的絕對值平均數.這一平均數表明了這一層對於之前某一層feature的利用率,下圖為由該平均數繪製出的熱力圖:

從圖中我們可以得出以下結論:

a一些較早層提取出的特徵仍可能被較深層直接使用b 即使是Transition layer也會使用到之前Denseblock中所有層的特徵c 第2-3個Denseblock中的層對之前Transition layer利用率很低,說明transition layer輸出大量冗餘特徵.這也為DenseNet-BC提供了證據支持,既Compression的必要性.d 最後的分類層雖然使用了之前Denseblock中的多層信息,但更偏向於使用最後幾個feature map的特徵,說明在網絡的最後幾層,某些high-level的特徵可能被產生.另外提一下DenseNet和stochastic depth的關係,在stochastic depth中,residual中的layers在訓練過程中會被隨機drop掉,其實這就會使得相鄰層之間直接連接,這和DenseNet是很像的。

總結:

該文章提出的DenseNet核心思想在於建立了不同層之間的連接關係,充分利用了feature,進一步減輕了梯度消失問題,加深網絡不是問題,而且訓練效果非常好。另外,利用bottleneck layer,Translation layer以及較小的growth rate使得網絡變窄,參數減少,有效抑制了過擬合,同時計算量也減少了。DenseNet優點很多,而且在和ResNet的對比中優勢還是非常明顯的。

pytorch實現(參考自官網densenet121)

model.py

整體為

1.輸入:圖片2.經過feature block(圖中的第一個convolution層,後面可以加一個pooling層,這裡沒有畫出來)3.經過第一個dense block, 該Block中有n個dense layer,灰色圓圈表示,每個dense layer都是dense connection,即每一層的輸入都是前面所有層的輸出的拼接4.經過第一個transition block,由convolution和poolling組成5.經過第二個dense block6.經過第二個transition block7.經過第三個dense block8.經過classification block,由pooling,linear層組成,輸出softmax的score9.經過prediction層,softmax分類10.輸出:分類概率

Dense Layer

最開始輸出(56 * 56 * 64)或者是上一層dense layer的輸出 1.Batch Normalization, 輸出(56 * 56 * 64) 2.ReLU ,輸出(56 * 56 * 64) 3. -1x1 Convolution, kernel_size=1, channel = bn_size *growth_rate, 則輸出為(56 * 56 * 128) -Batch Normalization(56 * 56 * 128) -ReLU(56 * 56 * 128) 4.Convolution, kernel_size=3, channel = growth_rate (56 * 56 * 32) 5.Dropout,可選的,用於防止過擬合(56 * 56 * 32)

class_DenseLayer(nn.Sequential):def__init__(self, num_input_features, growth_rate, bn_size, drop_rate, memory_efficient=False):#num_input_features特徵層數super(_DenseLayer, self).__init__()#growth_rate=32增長率 bn_size=4#(56 * 56 * 64)self.add_module('norm1', nn.BatchNorm2d(num_input_features)), self.add_module('relu1', nn.ReLU(inplace=True)), self.add_module('conv1', nn.Conv2d(num_input_features, bn_size * growth_rate, kernel_size=1, stride=1, bias=False)), self.add_module('norm2', nn.BatchNorm2d(bn_size * growth_rate)), self.add_module('relu2', nn.ReLU(inplace=True)), self.add_module('conv2', nn.Conv2d(bn_size * growth_rate, growth_rate, kernel_size=3, stride=1, padding=1, bias=False)), #(56 * 56 * 32)self.drop_rate = drop_rate self.memory_efficient = memory_efficient defforward(self, *prev_features): bn_function = _bn_function_factory(self.norm1, self.relu1, self.conv1)#(56 * 56 * 64*3)ifself.memory_efficient and any(prev_feature.requires_grad for prev_feature in prev_features): bottleneck_output = cp.checkpoint(bn_function, *prev_features) else: bottleneck_output = bn_function(*prev_features) # bn1 + relu1 + conv1 new_features = self.conv2(self.relu2(self.norm2(bottleneck_output))) ifself.drop_rate > 0: new_features = F.dropout(new_features, p=self.drop_rate, training=self.training) return new_featuresdef_bn_function_factory(norm, relu, conv): defbn_function(*inputs): # type(List[Tensor]) -> Tensor concated_features = torch.cat(inputs, 1)#按通道合併# bn1 + relu1 + conv1 bottleneck_output = conv(relu(norm(concated_features))) return bottleneck_output return bn_function

Dense Block

DenseBlock有L層denselayer組成layer0:輸入(56*56*64)->輸出(56*56*32)layer1:輸入(56*56(32*1))->輸出(56*56*32)layer2:輸入(56*56(32*2))->輸出(56*56*32)…layerL:輸入(56*56*(32*L))->輸出(56*56*32)注意,L層denselayer的輸出都是不變的,而每層的輸入channel數是增加的,因為如上所述,每層的輸入是前面所有層的拼接。

class_DenseBlock(nn.Module):def__init__(self, num_layers, num_input_features, bn_size, growth_rate, drop_rate, memory_efficient=False): super(_DenseBlock, self).__init__()#num_layers層重複次數for i in range(num_layers): layer = _DenseLayer( num_input_features + i * growth_rate, #for一次層數增加32 growth_rate=growth_rate, bn_size=bn_size, drop_rate=drop_rate, memory_efficient=memory_efficient, ) self.add_module('denselayer%d' % (i + 1), layer) # 追加denselayer層到字典裡面defforward(self, init_features): features = [init_features] #原來的特徵,64for name, layer inself.named_children(): # 依次遍歷添加的6個layer層, new_features = layer(*features) #計算特徵 features.append(new_features) # 追加特徵return torch.cat(features, 1) # 按通道數合併特徵 64 + 6*32=256

Transition Block

Transition Block是在兩個Dense Block之間的,由一個卷積+一個pooling組成(下面的數據維度以第一個transition block為例):

輸入:DenseBlock的輸出(56*56*32)1.BatchNormalization輸出(56*56*32)2.ReLU輸出(56*56*32)3.1x1Convolution,kernel_size=1,此處可以根據預先設定的壓縮係數(0-1之間)來壓縮原來的channel數,以減小參數,輸出(56*56*(32*compression))4.2x2AveragePooling輸出(28*28*(32*compression))

classDenseNet(nn.Module):r"""Densenet-BC model class, based on `"Densely Connected Convolutional Networks" <https://arxiv.org/pdf/1608.06993.pdf>`_ Args: growth_rate (int) - how many filters to add each layer (`k` in paper) block_config (list of 4 ints) - how many layers in each pooling block num_init_features (int) - the number of filters to learn in the first convolution layer bn_size (int) - multiplicative factor for number of bottle neck layers (i.e. bn_size * k features in the bottleneck layer) drop_rate (float) - dropout rate after each dense layer num_classes (int) - number of classification classes memory_efficient (bool) - If True, uses checkpointing. Much more memory efficient, but slower. Default: *False*. See `"paper" <https://arxiv.org/pdf/1707.06990.pdf>`_ """def__init__(self, growth_rate=32, block_config=(6, 12, 24, 16), num_init_features=64, bn_size=4, drop_rate=0, num_classes=1000, memory_efficient=False): super(DenseNet, self).__init__() # First convolution self.features = nn.Sequential(OrderedDict([ ('conv0', nn.Conv2d(3, num_init_features, kernel_size=7, stride=2, padding=3, bias=False)), ('norm0', nn.BatchNorm2d(num_init_features)), ('relu0', nn.ReLU(inplace=True)), ('pool0', nn.MaxPool2d(kernel_size=3, stride=2, padding=1)), ])) # Each denseblock num_features = num_init_features for i, num_layers in enumerate(block_config): block = _DenseBlock( num_layers=num_layers, # 層數重複次數 num_input_features=num_features, # 特徵層數64 bn_size=bn_size, growth_rate=growth_rate, drop_rate=drop_rate, # dropout值 0 memory_efficient=memory_efficient ) self.features.add_module('denseblock%d' % (i + 1), block) # 追加denseblock num_features = num_features + num_layers * growth_rate # 更新num_features=64+6*32 = 256if i != len(block_config) - 1:#每兩個dense block之間增加一個過渡層,i != (4-1),即 i != 3 非最後一個denseblock,後面跟_Transition層 trans = _Transition(num_input_features=num_features, num_output_features=num_features // 2) # 輸出通道數減半 self.features.add_module('transition%d' % (i + 1), trans) num_features = num_features // 2# 更新num_features= num_features//2 取整數部分# Final batch norm self.features.add_module('norm5', nn.BatchNorm2d(num_features)) # Linear layer self.classifier = nn.Linear(num_features, num_classes) # Official init from torch repo.for m in self.modules(): if isinstance(m, nn.Conv2d): nn.init.kaiming_normal_(m.weight) elif isinstance(m, nn.BatchNorm2d): nn.init.constant_(m.weight, 1) nn.init.constant_(m.bias, 0) elif isinstance(m, nn.Linear): nn.init.constant_(m.bias, 0) defforward(self, x): features = self.features(x) # 特徵提取層 out = F.relu(features, inplace=True) out = F.adaptive_avg_pool2d(out, (1, 1)) # 自適應均值池化,輸出大小為(1,1) out = torch.flatten(out, 1) out = self.classifier(out) # 分類器return outdef_densenet(arch, growth_rate, block_config, num_init_features, pretrained, progress, **kwargs): model = DenseNet(growth_rate, block_config, num_init_features, **kwargs) if pretrained: _load_state_dict(model, model_urls[arch], progress) return modeldefdensenet121(pretrained=False, progress=True, **kwargs):r"""Densenet-121 model from `"Densely Connected Convolutional Networks" <https://arxiv.org/pdf/1608.06993.pdf>`_ Args: pretrained (bool): If True, returns a model pre-trained on ImageNet progress (bool): If True, displays a progress bar of the download to stderr memory_efficient (bool) - If True, uses checkpointing. Much more memory efficient, but slower. Default: *False*. See `"paper" <https://arxiv.org/pdf/1707.06990.pdf>`_ """return _densenet('densenet121', 32, (6, 12, 24, 16), 64, pretrained, progress, **kwargs)

註:本次訓練集下載在AlexNet博客有詳細解說:https://blog.csdn.net/weixin_44023658/article/details/105798326

#train.pyimport torchimport torch.nn as nnfrom torchvision import transforms, datasetsimport jsonimport matplotlib.pyplot as pltfrom model import densenet121import osimport torch.optim as optimimport torchvision.models.densenetimport torchvision.models as modelsdevice = torch.device("cuda:0"if torch.cuda.is_available() else"cpu")print(device)data_transform = { "train": transforms.Compose([transforms.RandomResizedCrop(224), transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])]),#來自官網參數"val": transforms.Compose([transforms.Resize(256),#將最小邊長縮放到256 transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])}data_root = os.path.abspath(os.path.join(os.getcwd(), "../../..")) # get data root pathimage_path = data_root + "/data_set/flower_data/"# flower data set pathtrain_dataset = datasets.ImageFolder(root=image_path + "train", transform=data_transform["train"])train_num = len(train_dataset)# {'daisy':0, 'dandelion':1, 'roses':2, 'sunflower':3, 'tulips':4}flower_list = train_dataset.class_to_idxcla_dict = dict((val, key) for key, val in flower_list.items())# write dict into json filejson_str = json.dumps(cla_dict, indent=4)with open('class_indices.json', 'w') as json_file: json_file.write(json_str)batch_size = 16train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=0)validate_dataset = datasets.ImageFolder(root=image_path + "/val", transform=data_transform["val"])val_num = len(validate_dataset)validate_loader = torch.utils.data.DataLoader(validate_dataset, batch_size=batch_size, shuffle=False, num_workers=0)#遷移學習net = models.densenet121(pretrained=False)model_weight_path="./densenet121-a.pth"missing_keys, unexpected_keys = net.load_state_dict(torch.load(model_weight_path), strict= False)inchannel = net.classifier.in_featuresnet.classifier = nn.Linear(inchannel, 5)net.to(device)loss_function = nn.CrossEntropyLoss()optimizer = optim.Adam(net.parameters(), lr=0.0001)#普通# net = densenet121(pretrained=False)# net.to(device)# inchannel = net.classifier.in_features# net.classifier = nn.Linear(inchannel, 5)## loss_function = nn.CrossEntropyLoss()# optimizer = optim.Adam(net.parameters(), lr=0.0001)best_acc = 0.0save_path = './densenet121.pth'for epoch in range(10): # train net.train() running_loss = 0.0for step, data in enumerate(train_loader, start=0): images, labels = data optimizer.zero_grad() logits = net(images.to(device)) loss = loss_function(logits, labels.to(device)) loss.backward() optimizer.step() # print statistics running_loss += loss.item() # print train process rate = (step+1)/len(train_loader) a = "*" * int(rate * 50) b = "." * int((1 - rate) * 50) print("\rtrain loss: {:^3.0f}%[{}->{}]{:.4f}".format(int(rate*100), a, b, loss), end="") print() # validate net.eval() acc = 0.0# accumulate accurate number / epochwith torch.no_grad(): for val_data in validate_loader: val_images, val_labels = val_data outputs = net(val_images.to(device)) # eval model only have last output layer# loss = loss_function(outputs, test_labels) predict_y = torch.max(outputs, dim=1)[1] acc += (predict_y == val_labels.to(device)).sum().item() val_accurate = acc / val_num if val_accurate > best_acc: best_acc = val_accurate torch.save(net.state_dict(), save_path) print('[epoch %d] train_loss: %.3f test_accuracy: %.3f' % (epoch + 1, running_loss / step, val_accurate))print('Finished Training')

#predict.pyimport torchfrom model import densenet121from PIL import Imagefrom torchvision import transformsimport matplotlib.pyplot as pltimport jsondata_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])])# load imageimg = Image.open("./roses.jpg")plt.imshow(img)# [N, C, H, W]img = data_transform(img)# expand batch dimensionimg = torch.unsqueeze(img, dim=0)# read class_indicttry: json_file = open('./class_indices.json', 'r') class_indict = json.load(json_file)except Exception as e: print(e) exit(-1)# create modelmodel = densenet121(num_classes=5)# load model weightsmodel_weight_path = "./densenet121.pth"model.load_state_dict(torch.load(model_weight_path))model.eval()with torch.no_grad(): # predict class output = torch.squeeze(model(img)) predict = torch.softmax(output, dim=0) predict_cla = torch.argmax(predict).numpy()print(class_indict[str(predict_cla)], predict[predict_cla].numpy())plt.show()

相關焦點

  • ResNet——CNN經典網絡模型詳解(pytorch實現)
    ResNet的結構可以極快的加速神經網絡的訓練,模型的準確率也有比較大的提升。同時ResNet的推廣性非常好,甚至可以直接用到InceptionNet網絡中。下圖是ResNet34層模型的結構簡圖。2、ResNet詳解在ResNet網絡中有如下幾個亮點:提出residual結構(殘差結構),並搭建超深的網絡結構(突破1000層)使用Batch Normalization加速訓練(丟棄dropout)在ResNet網絡提出之前,傳統的卷積神經網絡都是通過將一系列卷積層與下採樣層進行堆疊得到的。但是當堆疊到一定網絡深度時,就會出現兩個問題。
  • LeNet-5——CNN經典網絡模型詳解(pytorch實現)
    一、LeNet-5這個是n多年前就有的一個CNN的經典結構,主要是用於手寫字體的識別,也是剛入門需要學習熟悉的一個網絡。原論文地址輸入:32*32的手寫字體圖片,這些手寫字體包含0~9數字,也就是相當於10個類別的圖片輸出:分類結果,0~9之間的一個數因此我們可以知道,這是一個多分類問題,總共有十個類,因此神經網絡的最後輸出層必然是SoftMax問題,然後神經元的個數是10個。
  • PyTorch實現TPU版本CNN模型
    隨著深度學習模型在各種應用中的成功實施,現在是時候獲得不僅準確而且速度更快的結果。為了得到更準確的結果,數據的大小是非常重要的,但是當這個大小影響到機器學習模型的訓練時間時,這一直是一個值得關注的問題。為了克服訓練時間的問題,我們使用TPU運行時環境來加速訓練。為此,PyTorch一直在通過提供最先進的硬體加速器來支持機器學習的實現。
  • 一行代碼即可調用18款主流模型!PyTorch Hub輕鬆解決論文可復現性
    代碼示例:>>> torch.hub.list('pytorch/vision')>>>['alexnet','deeplabv3_resnet101','densenet121',...'
  • 從R-CNN到YOLO,一文帶你了解目標檢測模型(附論文下載)
    要想進一步了解,可以查看以下PPT和筆記:http://www.image-net.org/challenges/LSVRC/2013/slides/r-cnn-ilsvrc2013-workshop.pdfhttp://www.cs.berkeley.edu/~rbg/slides/rcnn-cvpr14-slides.pdf
  • 雲計算學習:用PyTorch實現一個簡單的分類器
    回想了一下自己關於 pytorch 的學習路線,一開始找的各種資料,寫下來都能跑,但是卻沒有給自己體會到學習的過程。有的教程一上來就是寫一個 cnn,雖然其實內容很簡單,但是直接上手容易讓人找不到重點,學的雲裡霧裡。有的教程又淺嘗輒止,師傅領到了門檻跟前,總感覺自己還沒有進門,教程就結束了。
  • 13個算法工程師必須掌握的PyTorch Tricks
    指定GPU的命令需要放在和神經網絡相關的一系列操作的前面。2、查看模型每層輸出詳情Keras有一個簡潔的API來查看模型的每一層輸出尺寸,這在調試網絡時非常有用。現在在PyTorch中也可以實現這個功能。
  • Deep CARs:使用Pytorch學習框架實現遷移學習
    本文將介紹一個能識別196種類型汽車的模型。本模型將通過神經網絡來實現目標。更準確地說,是使用一個深度神經網絡,因此得名Deep CARs(深度計算機自動額定值系統)。想要實現這一目標,需要完成兩部分的學習,第1部分:構建汽車分類器;第2部分:部署分類器。本文將著重論述第1部分內容。我們將使用一種叫做遷移學習的方法來訓練分類器。
  • PyTorch可視化理解卷積神經網絡
    如今,機器已經能夠在理解、識別圖像中的特徵和對象等領域實現99%級別的準確率。生活中,我們每天都會運用到這一點,比如,智慧型手機拍照的時候能夠識別臉部、在類似於谷歌搜圖中搜索特定照片、從條形碼掃描文本或掃描書籍等。造就機器能夠獲得在這些視覺方面取得優異性能可能是源於一種特定類型的神經網絡——卷積神經網絡(CNN)。
  • 使用PyTorch實現鳥類音頻檢測卷積網絡模型
    跳入其中,鳥的音頻檢測出現了這樣一個利基(有利可圖的形式),在本文中,我將向您展示如何在BirdVox-70k數據集上使用一個簡單的卷積神經網絡(CNN)來實現這一點。為什麼鳥類的聲音檢測很重要呢?多年來,鳥類音頻檢測應用中深度學習模型的使用一直在不斷發展進步,這也是一些人對此非常感興趣的原因。首先,鳥類移動速度快,體型小,已經很難追蹤。
  • 輕鬆學Pytorch-使用ResNet50實現圖像分類
    Hello大家好,這篇文章給大家詳細介紹一下pytorch中最重要的組件torchvision,它包含了常見的數據集、模型架構與預訓練模型權重文件、常見圖像變換、計算機視覺任務訓練。可以是說是pytorch中非常有用的模型遷移學習神器。本文將會介紹如何使用torchvison的預訓練模型ResNet50實現圖像分類。
  • 學界| Facebook提出DensePose數據集和網絡架構:可實現實時的人體...
    在圖形處理、增強現實或人機互動等不只需要平面關鍵特徵位置標記的問題中,這一任務的解決將能實現很多應用,並且還能助力實現通用型的基於 3D 的物體理解。建立從圖像到基於表面的模型的密集對應的任務已經在可使用深度傳感器的設置中基本得到了解決,比如在 [41] 的 Vitruvian 流形中、指標回歸森林 [33] 或最近 [44] 提出的密集點雲對應。
  • PyTorch模型訓練特徵圖可視化(TensorboardX)
    tensor-yu/PyTorch_Tutorialhttps://github.com/tensor-yu/PyTorch_Tutorial1、Loss可視化最常見的可視化就是loss曲線作圖,這個實現相對比較簡單,不多做介紹了
  • 9大主題卷積神經網絡(CNN)的PyTorch實現
    上文聚焦於源碼和論文,對於各種卷積神經網絡模型的實現,本文將介紹它們的 PyTorch 實現,非常有用!這份資源已經開源在了 GitHub 上,連結如下:https://github.com/shanglianlm0525/PyTorch-Networks先來個總結介紹,該系列的卷積神經網絡實現包含了 9 大主題,目錄如下:1. 典型網絡2. 輕量級網絡3. 目標檢測網絡4.
  • 60分鐘入門深度學習工具PyTorch
    要防止跟蹤歷史記錄(和使用內存),您還可以使用torch.no_grad包裝代碼塊:在評估模型時,這可能特別有用,因為模型可能具有requires_grad = True的可訓練參數,但我們不需要梯度。還有一個類對於autograd實現非常重要 - Function。
  • 60 題 PyTorch 簡易入門指南,做技術的弄潮兒
    /zh/latest/改編自:https://pytorch.org/tutorials/beginner/deep_learning_60min_blitz.html#deep-learning-with-pytorch-a-60-minute-blitz1 初識PyTorch
  • 如何在PyTorch和TensorFlow中訓練圖像分類模型
    在本文中,我們將了解如何在PyTorch和TensorFlow中建立基本的圖像分類模型。我們將從PyTorch和TensorFlow的簡要概述開始。然後,我們將使用MNIST手寫數字分類數據集,並在PyTorch和TensorFlow中使用CNN(卷積神經網絡)建立圖像分類模型。這將是你的起點,然後你可以選擇自己喜歡的任何框架,也可以開始構建其他計算機視覺模型。
  • 有哪些好看的CNN模型畫法?
    說起CNN的模型圖,要從經典CNN的相關paper開始:LeNet,1998年;AlexNet,2012年 ;ZF-net,2013年;NIN,2013年;GoogLeNet (InceptionV1),2014年;VGG,2014年;Batch Norm (InceptionV2),2015年;InceptionV3 ,2015年;ResNet,2015年;InceptionV4,2016
  • 初學AI神經網絡應該選擇Keras或是Pytorch框架?
    keras是神經網絡的一個模型計算框架,嚴格來說不是神經網絡框架。本身沒有重量級計算,它使用其他AI框架作為計算後臺,傻瓜式的使用。它的計算後臺還支持 Theano、CNTK(微軟的一個AI計算後臺)等,也就是說keras是多個計算後臺的門面。官方設計哲學為Simple. Flexible.
  • Facebook 發布 Detectron2:基於 PyTorch 的新一代目標檢測工具
    而 Detectron2 則是剛推出的新版 PyTorch 1.3 (詳情查看:https://www.leiphone.com/news/201910/9J4PTd833WMwdVoQ.html)中一重大新工具,它源於 maskrcnn 基準測試,但它卻是對先前版本 detectron 的一次徹底重寫。