【深度學習】——pytorch搭建模型及相關模型

目錄

1、搭建模型的流程

1)步驟

?2)完整代碼——手寫minist數據集為例(這里使用的數據集是自帶的)

2、搭建模型的四種方法

1)方法一——利用nn.Sequential()

2)方法二——利用collections.orderDict()

3)方法三—— 先創建容器類,然后使用add_module函數向里面添加新模塊

4)方法四——利用nn.function中的函數

3、VGG16搭建

4、全卷積層實現方法

5、保存各個子模塊的輸出特征層



1、搭建模型的流程

1)步驟

1)先清楚需要搭建模型的構造,確定每層的通道數、步長、padding、卷積核大小等

2)創建模型類,將類繼承于nn.modules();

class VGG16(nn.Module):def __init__(self,num_classes = 1000):super(VGG16,self).__init__() # 繼承父類屬性和方法

3)根據模型前向傳播的順序,組建好每一個子模塊;一般是用容器nn.Sequential()來存放子模塊;一般是放在模型類的__init__()函數當中;

self.conv1 = nn.Sequential(nn.Conv2d(3,64,(3,3),(1,1),(1,1)),nn.ReLU(inplace=True), # inplace = True表示是否進行覆蓋計算)

4)添加forward方法()——上面__init__()方法中只是創建了每一個子模塊,每個模塊都是獨立的,因此在forward函數中主要是根據前向傳播的順序,將各個子模塊串起來。

	# 前向傳播函數def forward(self,x):# 十三個卷積層x = self.conv1(x)x = self.conv2(x)x = self.conv3(x)x = self.conv4(x)x = self.conv5(x)x = self.conv6(x)x = self.conv7(x)x = self.conv8(x)x = self.conv9(x)x = self.conv10(x)x = self.conv11(x)x = self.conv12(x)x = self.conv13(x)x = self.conv14(x)# 將圖像扁平化為一維向量,[1,512,7,7]-->1*512*7*7output = x.view(x.size(0),-1)return output

5)到第4)步模型已經搭建好了,接下來實例化模型后,需要確定損失函數、梯度下降優化算法、學習率更新策略等

# 指定優化器,即梯度下降使用的梯度下降算法,一般有sgd和adam用的多
optimizer = optim.Adam(net.parameters(), lr=0.01)
# 指定學習率優化器,即學習率的變化函數
'''
milestones:分段點
0-75:lr
75-150:gamma*lr
150-:gamma*gamma*lr
'''
scheduler = optim.lr_scheduler.MultiStepLR(optimizer, milestones=[75, 150], gamma=0.5)
# 指定損失函數,這里選擇的交叉熵損失函數來計算模型的loss
criterion = nn.CrossEntropyLoss()
# print(net)

6)如果數據樣本很大,則需要分批次進行訓練,即batch

7)訓練

8)測試

9)保存模型

?2)完整代碼——手寫minist數據集為例(這里使用的數據集是自帶的)

from collections import OrderedDict  # OrderedDict是字典的子類,可以記住元素的添加順序
from torch import optim
from torch import nn# 構建模型
class Net(nn.Module):def __init__(self):super(Net, self).__init__()'''一個卷積模塊一般有卷積層、激活層、池化層組成一個模型一般由多個卷積模塊和多個全連接層組成'''# input shape 28,28,3self.conv1 = nn.Sequential(OrderedDict([('conv1', nn.Conv2d(1, 16, (5, 5), (1, 1), (2, 2))),  # 28,28,16('ReLU1', nn.ReLU()),('pool1', nn.MaxPool2d(2)),  # 14,14,16]))self.conv2 = nn.Sequential(OrderedDict([('conv2', nn.Conv2d(16, 32, (5, 5), (1, 1), (2, 2))),  # 14,14,32('ReLU2', nn.ReLU()),('pool2', nn.MaxPool2d(2)) # 7,7,32]))self.linear = nn.Linear(32 * 7 * 7, 10)def forward(self, x):x = self.conv1(x)x = self.conv2(x)x = x.view(x.size(0), -1) # 將圖像扁平化為向量,即shape=【7,7,32】轉化為shape=【1,1,7*7*32】output = self.linear(x)return output# 模型實例化后,選擇優化器和學習
net = Net()
# 指定優化器,即梯度下降使用的梯度下降算法,一般有sgd和adam用的多
optimizer = optim.Adam(net.parameters(), lr=0.01)
# 指定學習率優化器,即學習率的變化函數
'''
milestones:分段點
0-75:lr
75-150:gamma*lr
150-:gamma*gamma*lr
'''
scheduler = optim.lr_scheduler.MultiStepLR(optimizer, milestones=[75, 150], gamma=0.5)
# 指定損失函數,這里選擇的交叉熵損失函數來計算模型的loss
criterion = nn.CrossEntropyLoss()
# print(net)# 將數據分成指定大小的批次,然后將數據分批輸入后進行訓練
def iterate_minibatches(inputs, targets, batch_size, shuffle=True):assert len(inputs) == len(targets)if shuffle:indices = np.arange(len(inputs))np.random.shuffle(indices)start_idx = None# 按照步長為batchsize來計算得到每一個batch的起始樣本索引號for start_idx in range(0, len(inputs) - batch_size + 1, batch_size):if shuffle:excerpt = indices[start_idx:start_idx + batch_size]else:excerpt = slice(start_idx, start_idx + batch_size) # 切片# 返回的是一個生成器對象,通過for循環可以取出,并且含有next函數yield inputs[excerpt], targets[excerpt] # 根據索引分割出了一個batch,返回對應的特征集和標簽集,一個生成器if start_idx is not None and start_idx + batch_size < len(inputs):excerpt = indices[start_idx + batch_size:] if shuffle else slice(start_idx + batch_size, len(inputs))yield inputs[excerpt], targets[excerpt]# 手寫訓練過程
# 導入數據
import numpy as np
import torch
from tensorflow.examples.tutorials.mnist import input_datamnist = input_data.read_data_sets("data/MNIST_data/", one_hot=False)
train_data_images = []
train_data_labels = []
test_data_images = []
test_data_labels = []X_train, y_train = mnist.train.images, mnist.train.labels  # 返回的 X_train 是 numpy 下的 多維數組,(55000, 784), (55000,)
X_test, y_test = mnist.test.images, mnist.test.labels  # (10000, 784), (10000,)
X_valid, y_valid = mnist.validation.images, mnist.validation.labels  # (5000, 784),(5000, )train_data_images = np.concatenate((X_train, X_valid), axis=0)  # (60000, 784)
train_data_labels = np.concatenate((y_train, y_valid), axis=0)  # (60000,)
test_data_images = X_test  # (10000, 784)
test_data_labels = y_test  # (10000,)# 變形
train_data_images = np.reshape(train_data_images, [-1, 1, 28, 28])  # (60000, 1, 28, 28)
test_data_images = np.reshape(test_data_images, [-1, 1, 28, 28])  # (10000, 1, 28, 28)# 訓練過程
train_loss = 0
train_correct = 0
total = 0
for epoch in range(epochs=100):# iterate_minibatches()對train_data_images, train_data_labels批量劃分,shuffle=True,表示亂序# iterate_minibatches()返回的是一個迭代器對象for data, target in iterate_minibatches(train_data_images, train_data_labels, batch_size=8, shuffle=True):optimizer.zero_grad()  # 清除梯度output = net(data)loss = criterion(output, target)  # 計算誤差loss.backward() # 后向傳播optimizer.step()train_loss += loss.item()  # 計算1個epoch的loss和# 將預測得分最大的類別作為最終的預測類別,元組pred = torch.max(output, 1)  # max函數會返回兩個tensor,第一個tensor是每行的最大值;第二個tensor是每行最大值的索引。train_correct += np.sum(pred[1] == target)  # 計算1個epoch的accuracy,這里是通過判斷最大預測得分的類別索引和真實標簽的索引是否一致,是則表示預測成功total += target.size(0)Train_Accuracy = train_correct / total
Train_Loss = train_loss# 測試過程
test_loss = 0
test_correct = 0
total = 0
for data, target in iterate_minibatches(test_data_images, test_data_labels, batch_size=8, shuffle=True):output = net(data)loss = criterion(output, target)test_loss += loss.item()pred = torch.max(output, 1)test_correct += np.sum(pred[1] == target)total += target.size(0)Test_Accuracy = test_correct / total
Test_Loss = test_loss# 保存模型
model_out_path = "model.pth"
torch.save(net, model_out_path)
print("Checkpoint saved to {}".format(model_out_path))

2、搭建模型的四種方法

1)方法一——利用nn.Sequential()

import torch.nn as nnclass Net(nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 = nn.Sequential(  # input shape (1, 28, 28)nn.Conv2d(1, 16, 5, 1, 2),  # output shape (16, 28, 28)nn.ReLU(),nn.MaxPool2d(2),  # output shape (16, 14, 14))self.conv2 = nn.Sequential(nn.Conv2d(16, 32, 5, 1, 2),  # output shape (32, 14, 14)nn.ReLU(),nn.MaxPool2d(2),  # output shape (32, 7, 7))self.linear = nn.Linear(32 * 7 * 7, 10)def forward(self, x):x = self.conv1(x)x = self.conv2(x)x = x.view(x.size(0), -1)output = self.linear(x)return output

2)方法二——利用collections.orderDict()

import torch.nn as nn
from collections import OrderedDict  # OrderedDict是字典的子類,可以記住元素的添加順序class Net(nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 = nn.Sequential(OrderedDict([('conv1', nn.Conv2d(1, 16, 5, 1, 2)),('ReLU1', nn.ReLU()),('pool1', nn.MaxPool2d(2)),]))self.conv2 = nn.Sequential(OrderedDict([('conv2', nn.Conv2d(16, 32, 5, 1, 2)),('ReLU2', nn.ReLU()),('pool2', nn.MaxPool2d(2)),]))self.linear = nn.Linear(32 * 7 * 7, 10)def forward(self, x):x = self.conv1(x)x = self.conv2(x)x = x.view(x.size(0), -1)output = self.linear(x)return output

3)方法三—— 先創建容器類,然后使用add_module函數向里面添加新模塊

import torch.nn as nnclass Net(nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 = nn.Sequential()self.conv1.add_module('conv1', nn.Conv2d(1, 16, 5, 1, 2))self.conv1.add_module('ReLU1', nn.ReLU())self.conv1.add_module('pool1', nn.MaxPool2d(2))self.conv2 = nn.Sequential()self.conv2.add_module('conv2', nn.Conv2d(16, 32, 5, 1, 2))self.conv2.add_module('ReLU2', nn.ReLU())self.conv2.add_module('pool2', nn.MaxPool2d(2))self.linear = nn.Linear(32 * 7 * 7, 10)def forward(self, x):x = self.conv1(x)x = self.conv2(x)x = x.view(x.size(0), -1)output = self.linear(x)return output

4)方法四——利用nn.function中的函數

import torch.nn as nn
import torch.nn.functional as Fclass Net(nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 = nn.Conv2d(1, 16, 5, 1, 2)self.conv2 = nn.Conv2d(16, 32, 5, 1, 2)self.linear = nn.Linear(32 * 7 * 7, 10)def forward(self, x):x = F.max_pool2d(F.relu(self.conv1(x)), 2)x = F.max_pool2d(F.relu(self.conv2(x)), 2)output = self.linear(x)return output

3、VGG16搭建

from torch import nnclass VGG16(nn.Module):def __init__(self,num_classes = 1000):super(VGG16,self).__init__() # 繼承父類屬性和方法# 根據前向傳播的順序,搭建各個子網絡模塊## 十三個卷積層,每個卷積模塊都有卷積層、激活層和池化層,用nn.Sequential()這個容器將各個模塊存放起來# [1,3,224,224]self.conv1 = nn.Sequential(nn.Conv2d(3,64,(3,3),(1,1),(1,1)),nn.ReLU(inplace=True), # inplace = True表示是否進行覆蓋計算)# [1,64,224,224]self.conv2 = nn.Sequential(nn.Conv2d(64,64,(3,3),(1,1),(1,1)),nn.ReLU(inplace=True), # inplace = True表示是否進行覆蓋計算nn.MaxPool2d((2,2),(2,2)))# [1,64,112,112]self.conv3 = nn.Sequential(nn.Conv2d(64,128,(3,3),(1,1),(1,1)),nn.ReLU(inplace=True), # inplace = True表示是否進行覆蓋計算)# [1,128,112,112]self.conv4 = nn.Sequential(nn.Conv2d(128,128,(3,3),(1,1),(1,1)),nn.ReLU(inplace=True), # inplace = True表示是否進行覆蓋計算nn.MaxPool2d((2,2),(2,2)))# [1,128,56,56]self.conv5 = nn.Sequential(nn.Conv2d(128,256,(3,3),(1,1),(1,1)),nn.ReLU(inplace=True), # inplace = True表示是否進行覆蓋計算)# [1,256,56,56]self.conv6 = nn.Sequential(nn.Conv2d(256,256,(3,3),(1,1),(1,1)),nn.ReLU(inplace=True), # inplace = True表示是否進行覆蓋計算)# [1,256,56,56]self.conv7 = nn.Sequential(nn.Conv2d(256,256,(3,3),(1,1),(1,1)),nn.ReLU(inplace=True), # inplace = True表示是否進行覆蓋計算nn.MaxPool2d((2,2),(2,2)))# [1,256,28,28]self.conv8 = nn.Sequential(nn.Conv2d(256,512,(3,3),(1,1),(1,1)),nn.ReLU(inplace=True))# [1,512,28,28]self.conv9 = nn.Sequential(nn.Conv2d(512,512,(3,3),(1,1),(1,1)),nn.ReLU(inplace=True))# [1,512,28,28]self.conv10 = nn.Sequential(nn.Conv2d(512,512,(3,3),(1,1),(1,1)),nn.ReLU(inplace=True),nn.MaxPool2d((2,2),(2,2)))# [1,512,14,14]self.conv11 = nn.Sequential(nn.Conv2d(512, 512, (3, 3), (1, 1), (1, 1)),nn.ReLU(inplace=True),)# [1,512,14,14]self.conv12 = nn.Sequential(nn.Conv2d(512, 512, (3, 3), (1, 1), (1, 1)),nn.ReLU(inplace=True),)# [1,512,14,14]-->[1,512,7,7]self.conv13 = nn.Sequential(nn.Conv2d(512, 512, (3, 3), (1, 1), (1, 1)),nn.ReLU(inplace=True),nn.MaxPool2d((2, 2), (2, 2)))# 三個全連接層,每個全連接層之間存在激活層和dropout層self.classfier = nn.Sequential(# [1*512*7*7]nn.Linear(1*512*7*7,4096),nn.ReLU(True),nn.Dropout(),# 4096nn.Linear(4096,4096),nn.ReLU(True),nn.Dropout(),# 4096-->1000nn.Linear(4096,num_classes))# 前向傳播函數def forward(self,x):# 十三個卷積層x = self.conv1(x)x = self.conv2(x)x = self.conv3(x)x = self.conv4(x)x = self.conv5(x)x = self.conv6(x)x = self.conv7(x)x = self.conv8(x)x = self.conv9(x)x = self.conv10(x)x = self.conv11(x)x = self.conv12(x)x = self.conv13(x)# 將圖像扁平化為一維向量,[1,512,7,7]-->1*512*7*7x = x.view(x.size(0),-1)# 三個全連接層output = self.classfier(x)return output## 測試
import torch
vgg16 = VGG16(21)
print(vgg16)input_ = torch.randn(1,3,224,224)
output = vgg16(input_)
print(output.shape)
print(output)

4、全卷積層實現方法

核心思想:其實就是將全連接層用卷積層去替換了,一般需要經過精心的設計,使得最后輸出的是【1,1,channels】的shape。這里以vgg16為例,vgg16最后的特征圖大小為【1,512,7,7】,若要變為1,1大小的特征圖,則可以使用7,7的卷積核進行卷積,然后利用num_classes個卷積核去進行卷積,最后就得到了特征圖【1,num_classes,1,1】,在輸出前使用激活函數得到分類得分。

		# 全卷積層self.conv14 = nn.Sequential(nn.Conv2d(512,num_classes,(7,7),(1,1)),nn.ReLU(inplace=True))
from torch import nnclass VGG16(nn.Module):def __init__(self,num_classes = 1000):super(VGG16,self).__init__() # 繼承父類屬性和方法# 根據前向傳播的順序,搭建各個子網絡模塊## 十三個卷積層,每個卷積模塊都有卷積層、激活層和池化層,用nn.Sequential()這個容器將各個模塊存放起來# [1,3,224,224]self.conv1 = nn.Sequential(nn.Conv2d(3,64,(3,3),(1,1),(1,1)),nn.ReLU(inplace=True), # inplace = True表示是否進行覆蓋計算)# [1,64,224,224]self.conv2 = nn.Sequential(nn.Conv2d(64,64,(3,3),(1,1),(1,1)),nn.ReLU(inplace=True), # inplace = True表示是否進行覆蓋計算nn.MaxPool2d((2,2),(2,2)))# [1,64,112,112]self.conv3 = nn.Sequential(nn.Conv2d(64,128,(3,3),(1,1),(1,1)),nn.ReLU(inplace=True), # inplace = True表示是否進行覆蓋計算)# [1,128,112,112]self.conv4 = nn.Sequential(nn.Conv2d(128,128,(3,3),(1,1),(1,1)),nn.ReLU(inplace=True), # inplace = True表示是否進行覆蓋計算nn.MaxPool2d((2,2),(2,2)))# [1,128,56,56]self.conv5 = nn.Sequential(nn.Conv2d(128,256,(3,3),(1,1),(1,1)),nn.ReLU(inplace=True), # inplace = True表示是否進行覆蓋計算)# [1,256,56,56]self.conv6 = nn.Sequential(nn.Conv2d(256,256,(3,3),(1,1),(1,1)),nn.ReLU(inplace=True), # inplace = True表示是否進行覆蓋計算)# [1,256,56,56]self.conv7 = nn.Sequential(nn.Conv2d(256,256,(3,3),(1,1),(1,1)),nn.ReLU(inplace=True), # inplace = True表示是否進行覆蓋計算nn.MaxPool2d((2,2),(2,2)))# [1,256,28,28]self.conv8 = nn.Sequential(nn.Conv2d(256,512,(3,3),(1,1),(1,1)),nn.ReLU(inplace=True))# [1,512,28,28]self.conv9 = nn.Sequential(nn.Conv2d(512,512,(3,3),(1,1),(1,1)),nn.ReLU(inplace=True))# [1,512,28,28]self.conv10 = nn.Sequential(nn.Conv2d(512,512,(3,3),(1,1),(1,1)),nn.ReLU(inplace=True),nn.MaxPool2d((2,2),(2,2)))# [1,512,14,14]self.conv11 = nn.Sequential(nn.Conv2d(512, 512, (3, 3), (1, 1), (1, 1)),nn.ReLU(inplace=True),)# [1,512,14,14]self.conv12 = nn.Sequential(nn.Conv2d(512, 512, (3, 3), (1, 1), (1, 1)),nn.ReLU(inplace=True),)# [1,512,14,14]-->[1,512,7,7]self.conv13 = nn.Sequential(nn.Conv2d(512, 512, (3, 3), (1, 1), (1, 1)),nn.ReLU(inplace=True),nn.MaxPool2d((2, 2), (2, 2)))# 全卷積層self.conv14 = nn.Sequential(nn.Conv2d(512,num_classes,(7,7),(1,1)),nn.ReLU(inplace=True))# 前向傳播函數def forward(self,x):# 十三個卷積層x = self.conv1(x)x = self.conv2(x)x = self.conv3(x)x = self.conv4(x)x = self.conv5(x)x = self.conv6(x)x = self.conv7(x)x = self.conv8(x)x = self.conv9(x)x = self.conv10(x)x = self.conv11(x)x = self.conv12(x)x = self.conv13(x)x = self.conv14(x)# 將圖像扁平化為一維向量,[1,512,7,7]-->1*512*7*7output = x.view(x.size(0),-1)return output## 測試
import torch
vgg16 = VGG16(21)
print(vgg16)input_ = torch.randn(1,3,224,224)
output = vgg16(input_)
print(output.shape)
print(output)

5、保存各個子模塊的輸出特征層

?在forward函數中,將需要保存的特征層的輸出保存在列表中即可,這里以ssd中的為例,其中feathers就是將需要的幾個特征圖保存了起來,便于后續進行特征圖訓練,實現多尺度的訓練。

    def forward(self, x):features = []for i in range(23):x = self.vgg[i](x)s = self.l2_norm(x)  # Conv4_3 L2 normalizationfeatures.append(s)# apply vgg up to fc7for i in range(23, len(self.vgg)):x = self.vgg[i](x)features.append(x)for k, v in enumerate(self.extras):x = F.relu(v(x), inplace=True)if k % 2 == 1:features.append(x)return tuple(features)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/255777.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/255777.shtml
英文地址,請注明出處:http://en.pswp.cn/news/255777.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ABB robot 與 Fronius 設備 IO

ABB robot 與 Fronius 設備 IO

初次使用cocoapods注意事項

在僅僅用cocoapods時可能會遇到各種各樣的錯誤和問題 這里中總結下: 1.首先使用cocoapods有非常多優點,在github上非常多優秀的開源項目都用到了它;假設你不會使用它,那么非常多優秀的開源項目你下載下來了也發現跑不起來,假設發現有Profile,Profile.lock,Pods等cocoapods相關…

MongoDB復制集技術

為什么使用MongogDB復制集技術? mysql中:一主一從&#xff0c;一主多從結構存在的問題 1、 fileover&#xff08;故障轉移&#xff09;a) 選主投票b) 切換 2、 是否對就用透明化 3、 數據補償的問題a) 兩階段數據補償 4、 解決方法 mysql中使用MHAVIP b…

Linux文件系統的實現 (圖文并茂,比較好)

作者&#xff1a;Vamei 出處&#xff1a;http://www.cnblogs.com/vamei 歡迎轉載&#xff0c;也請保留這段聲明。謝謝&#xff01; Linux文件管理從用戶的層面介紹了Linux管理文件的方式。Linux有一個樹狀結構來組織文件。樹的頂端為根目錄(/)&#xff0c;節點為目錄&#xff0…

【深度學習】——如何處理輸入圖像大小不一樣的情況

這里一般有常見的幾種方法&#xff1a; 1&#xff09;將圖像縮放成大小一致后再輸入&#xff0c;如RCNN算法 2&#xff09;roi pooling&#xff1a;這里允許輸入圖像的大小不一樣&#xff0c;后續根據指定的固定大小來求解池化的核大小&#xff0c;以此來得到相同大小的特征圖&…

ROS探索總結(一)——ROS簡介

隨著機器人領域的快速發展和復雜化&#xff0c;代碼的復用性和模塊化的需求原來越強烈&#xff0c;而已有的開源機器人系統又不能很好的適應需求。2010年Willow Garage公司發布了開源機器人操作系統ROS&#xff08;robot operating system&#xff09;&#xff0c;很快在機器人…

微信瀏覽器取消緩存的方法

摘要:做微信公家號以及調試手機頁面的時辰&#xff0c;防止不了頁面要跳轉到微信閱讀器打開&#xff0c;調試階段&#xff0c;android版微信閱讀器一直都默許緩存html靜態資本&#xff0c;每一次靜態資本變革乃至新內容發布的時辰在微信閱讀器上都極有可能不克不及更新&#xf…

【機器視覺】——裂紋檢測筆記

目錄 傳統算法處理裂縫的基本思路&#xff1a; 第一種思路 第二種思路&#xff1a; 第三種思路 CPP代碼 halcon代碼 python代碼 Matlab代碼 深度學習缺陷檢測 裂縫檢測文獻 傳統算法處理裂縫的基本思路&#xff1a; 第一種思路 1.先轉換彩色圖為灰度圖 2.進行自適應…

利用union判斷系統的大小端

int checkCPUendian()//返回1&#xff0c;為小端&#xff1b;反之&#xff0c;為大端&#xff1b; { union{ unsigned int a; unsigned char b; }c; c.a 1; return 1 c.b; }大端模式(Big-endian)&#xff0c;是指數據的高字節保存在內存的低地址中&#xff0c;而數據…

Filter(過濾器)?和?interceptor(攔截器)的區別

Filter&#xff08;過濾器&#xff09; 和 interceptor&#xff08;攔截器&#xff09;的區別 1.攔截器是基于java反射機制的&#xff0c;而過濾器是基于函數回調的。 2.過濾器依賴于Servlet容器&#xff0c;而攔截器不依賴于Servlet容器。 3.攔截器只對Action請求起作用&#…

ROS探索總結(二)——ROS總體框架

一、 總體結構 根據ROS系統代碼的維護者和分布來標示&#xff0c;主要有兩大部分&#xff1a;&#xff08;1&#xff09;main&#xff1a;核心部分&#xff0c;主要由Willow Garage公司和一些開發者設計、提供以及維護。它提供了一些分布式計算的基本工具&#xff0c;以及整個…

python 阿貍的進階之路(4)

裝飾器 #1、開放封閉原則&#xff1a;對擴展開放&#xff0c;對修改是封閉#2、裝飾器&#xff1a;裝飾它人的&#xff0c;器指的是任意可調用對象&#xff0c;現在的場景裝飾器-》函數&#xff0c;被裝飾的對象也是-》函數#原則&#xff1a;1、不修改被裝飾對象的源代碼 2、不修…

【深度學習】——利用pytorch搭建一個完整的深度學習項目(構建模型、加載數據集、參數配置、訓練、模型保存、預測)

目錄 一、深度學習項目的基本構成 二、實戰&#xff08;貓狗分類&#xff09; 1、數據集下載 2、dataset.py文件 3、model.py 4、config.py 5、predict.py 一、深度學習項目的基本構成 一個深度學習模型一般包含以下幾個文件&#xff1a; datasets文件夾&#xff1a;存放…

二叉樹的序遍歷

時間限制: 1 s空間限制: 32000 KB題目等級 : 白銀 Silver題目描述 Description求一棵二叉樹的前序遍歷&#xff0c;中序遍歷和后序遍歷 輸入描述 Input Description第一行一個整數n&#xff0c;表示這棵樹的節點個數。 接下來n行每行2個整數L和R。第i行的兩個整數Li和Ri代表編號…

GUI登錄界面

在這次的作業中&#xff0c;我先使用單選按鈕&#xff0c;輸入框&#xff0c;復選框設計了一個簡單地登錄界面。接著我使用了MouseListener將登陸按鈕與下一個“查詢界面”連接起來。最后我使用了我們本周所學的JFrame框架與事件處理機制設計了一個簡單地界面。我所設計的登錄界…

淺談ROS操作系統及其應用趨勢

ROS操作系統是最先由斯坦福開發的開源機器人操作系統&#xff0c;目前由willowgarage公司開發和維護&#xff0c;相關的開發社區也很成熟&#xff08; http://www.ros.org &#xff0c; http://answers.ros.org, http://www.willowgarage.com), 經過幾年的發展API也逐漸穩定&a…

Raft學習傳送門

Raft官網 官方可視化動畫1 官方可視化動畫2 論文中文翻譯 論文英文地址 Paxos Made Simple論文翻譯 Raft理解 技術分享 《分布式一致性raft算法實現原理》 狀態機 MIT&#xff1a; raft實現 分布式系統學習2-Raft算法分析與實現 分布式系統MIT 6.824學習資源 知乎大神的&#…

【Python生成器與迭代器的區別】

目錄 一、迭代 二、迭代器 1&#xff09;創建迭代器——兩種方法 iter&#xff08;&#xff09;方法 利用()和range結合使用 2&#xff09;具體案例 3、生成器 4、二者的異同 1&#xff09;、共同點 2&#xff09;、不同點 a、語法上 b、用法上 一、迭代 首先理解一…

BZOJ4426 : [Nwerc2015]Better Productivity最大生產率

如果一個區間包含另一個區間&#xff0c;那么這兩個區間是否在一起的生產率是一樣的。 將所有這種包含了其他區間的區間放入數組$b$&#xff0c;其余的放入數組$c$&#xff0c;有多個相同的時候則從$b$移一個到$c$。 那么$c$里所有區間左端點遞增&#xff0c;右端點也遞增&…

[codevs1105][COJ0183][NOIP2005]過河

[codevs1105][COJ0183][NOIP2005]過河 試題描述 在河上有一座獨木橋&#xff0c;一只青蛙想沿著獨木橋從河的一側跳到另一側。在橋上有一些石子&#xff0c;青蛙很討厭踩在這些石子上。由于橋的長度和青蛙一次跳過的距離都是正整數&#xff0c;我們可以把獨木橋上青蛙可能到達的…