最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

解決pytorch 模型復制的一些問題

 更新時間:2021年03月03日 11:09:43   作者:冰菓(笑)  
這篇文章主要介紹了解決pytorch 模型復制的一些問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

直接使用

model2=model1

會出現(xiàn)當更新model2時,model1的權(quán)重也會更新,這和自己的初始目的不同。

經(jīng)評論指出可以使用:

model2=copy.deepcopy(model1)

來實現(xiàn)深拷貝,手上沒有pytorch環(huán)境,具體還沒測試過,誰測試過可以和我說下有沒有用。

原方法:

所有要使用模型復制可以使用如下方法。

torch.save(model, "net_params.pkl")
model5=Cnn(3,10)
model5=torch.load('net_params.pkl')

這樣編寫不會影響原始模型的權(quán)重

補充:pytorch模型訓練流程中遇到的一些坑(持續(xù)更新)

要訓練一個模型,主要分成幾個部分,如下。

數(shù)據(jù)預處理

入門的話肯定是拿 MNIST 手寫數(shù)據(jù)集先練習。

pytorch 中有幫助我們制作數(shù)據(jù)生成器的模塊,其中有 Dataset、TensorDataset、DataLoader 等類可以來創(chuàng)建數(shù)據(jù)入口。

之前在 tensorflow 中可以用 dataset.from_generator() 的形式,pytorch 中也類似,目前我了解到的有兩種方法可以實現(xiàn)。

第一種就繼承 pytorch 定義的 dataset,改寫其中的方法即可。如下,就獲得了一個 DataLoader 生成器。

class MyDataset(Dataset):
 def __init__(self, data, labels):
 self.data = data
 self.labels = labels
 def __getitem__(self, index):
 return self.data[index], self.labels[index]
 def __len__(self):
 return len(self.labels)
 
train_dataset = MyDataset(train_data, train_label)
train_loader = DataLoader(dataset = train_dataset,
 batch_size = 1,
 shuffle = True)

第二種就是轉(zhuǎn)換,先把我們準備好的數(shù)據(jù)轉(zhuǎn)化成 pytorch 的變量(或者是 Tensor),然后傳入 TensorDataset,再構(gòu)造 DataLoader。

X = torch.from_numpy(train_data).float()
Y = torch.from_numpy(train_label).float()
train_dataset = TensorDataset(X, Y)
 
train_loader = DataLoader(dataset = train_dataset,
 batch_size = 1,
 shuffle = True)
 #num_workers = 2)

模型定義

class Net(nn.Module):
 
 def __init__(self):
 super(Net, self).__init__()
 self.conv1 = nn.Conv2d(1, 6, 3)
 self.conv2 = nn.Conv2d(6 ,16, 3)
 
 self.fc1 = nn.Linear(400, 120)
 self.fc2 = nn.Linear(120, 84)
 self.fc3 = nn.Linear(84, 10)
 
 def forward(self, x):
 relu = F.relu(self.conv1(x))
 x = F.max_pool2d(relu, (2, 2))
 x = F.max_pool2d(F.relu(self.conv2(x)), 2)
 x = x.view(-1, self.num_flat_features(x))
 x = F.relu(self.fc1(x))
 x = F.relu(self.fc2(x))
 x = self.fc3(x)
 
 return x 
 def num_flat_features(self, x):
 size = x.size()[1:] #除了batch_size之外的維度
 num_features = 1
 for s in size:
 num_features *= s
 return num_features

訓練模型那么肯定要先定義一個網(wǎng)絡結(jié)構(gòu),如上定義一個前向傳播網(wǎng)絡。里面包含了卷積層、全連接層、最大池化層和 relu 非線性激活層(名字我自己取的)以及一個 view 展開,把一個多維的特征圖平展成一維的。

其中nn.Conv2d(in_channels, out_channels, kernel_size),第一個參數(shù)是輸入的深度,第二是輸出的深度,第三是卷積核的尺寸。

F.max_pool2d(input, (pool_size, pool_size)),第二個參數(shù)是池話

nn.Linear(in_features, out_features)

x.view是平展的操作,不過實際上相當于 numpy 的 reshape,需要計算轉(zhuǎn)換后的尺寸。

損失函數(shù)定義

import torch.optim as optim
 
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

模型定義完之后,意味著給出輸入,就可以得到輸出的結(jié)果。那么就來比較 outputs 和 targets 之間的區(qū)別,那么就需要用到損失函數(shù)來描述。

訓練網(wǎng)絡

for epoch in range(2): # loop over the dataset multiple times
 
 running_loss = 0.0
 for i, data in enumerate(trainloader, 0):
 # get the inputs; data is a list of [inputs, labels]
 inputs, labels = data
 
 # zero the parameter gradients
 optimizer.zero_grad()
 
 # forward + backward + optimize
 outputs = net(inputs)
 loss = criterion(outputs, labels)
 loss.backward()
 optimizer.step()
 
 # print statistics
 running_loss += loss.item()
 if i % 2000 == 1999: # print every 2000 mini-batches
  print('[%d, %5d] loss: %.3f' %
   (epoch + 1, i + 1, running_loss / 2000))
  running_loss = 0.0
 
print('Finished Training')

以上的代碼是官方教程中給出來的,我們要做的就是學習他的思路。

1.首先是 epoch 的數(shù)量為 2,每個 epoch 都會歷遍一次整個訓練集。在每個 epoch 內(nèi)累積統(tǒng)計 running_loss,每 2000 個 batch 數(shù)據(jù)計算一次損失的平均值,然后 print 再重新將 running_loss 置為 0。

2.然后分 mini-batch 進行訓練,在每個計算每個 mini-batch 的損失之前,都會將優(yōu)化器 optimizer 中的梯度清空,防止不同 mini-batch 的梯度被累加到一起。更新分成兩步:第一步計算損失函數(shù),然后把總的損失分配到各個層中,即 loss.backward(),然后就使用優(yōu)化器更新權(quán)重,即 optimizer.step()。

保存模型

PATH = '...'
torch.save(net.state_dict(), PATH)

爬坑總結(jié)

總的來說流程就是上面那幾步,但自己做的時候就遇到了挺多問題,最主要是對于其中張量傳播過程中的要求不清楚,導致出了不少錯誤。

首先是輸入的數(shù)據(jù),pytorch 默認圖片的 batch 數(shù)據(jù)的結(jié)構(gòu)是(BATCH_SIZE, CHANNELS, IMG_H, IMG_W),所以要在生成數(shù)據(jù)時做一些調(diào)整,滿足這種 BCHW 的規(guī)則。

會經(jīng)常出現(xiàn)一些某個矩陣或者張量要求的數(shù)據(jù),例如 “RuntimeError: Expected object of scalar type Double but got scalar type Float for argument #2 ‘mat2'” 等錯誤信息。

可以使用 x.double(),y.float(),z.long() 等方式轉(zhuǎn)換成他要求的格式。

RuntimeError: multi-target not supported。這個錯誤出現(xiàn)在損失函數(shù)那個地方,對于分類問題肯定是優(yōu)先考慮交叉熵。

criterion = nn.CrossEntropyLoss()
loss = criterion(outputs, labels.long())#報錯的地方

當我batch-size=1時這個地方不會報錯,但是當batch-size>1時就會報錯。

查了別人的代碼,大家基本都是和官方教程里面寫的一樣,使用官方的 mnist 數(shù)據(jù)接口,代碼如下。一開始我是不愿意的,因為那樣子意味著可能數(shù)據(jù)格式被封裝起來看不見,但是自己折騰成本比較高,所以還是試了,真香!

train_dataset = datasets.MNIST(root='./data/',
    train=True,
    transform=transforms.ToTensor(),
    download=True)
train_loader = DataLoader(dataset = train_dataset,
  batch_size = 4,
  shuffle = True)

打印了一下從生成器中獲得數(shù)據(jù),看一下 size,發(fā)現(xiàn)果然和我自己寫的不同。當 batch_size=4 時,數(shù)據(jù) data.size() 都是4*1*28*28,這個是相同的;但是 labels.size() 是不同的,我寫的是 one_hot 向量所以是 4*10,但它的是 4。

直接打印 labels 看看,果然,是單個指,例如 tensor([3, 2, 6, 2]) 這樣。

不過模型的 outputs 依然是 4*10,看來是 nn.CrossEntropyLoss() 這個函數(shù)自己會做計算,所以他才會報錯說 multi-target not supported,因為 lables.size() 不對,原本只有一個數(shù)字,但現(xiàn)在是10個數(shù)字,相當于被分配了10個屬性,自然就報錯啦。

所以稍微修改了自己寫的生成器之后,就沒問題了。

不過,如果想要更自由的調(diào)用數(shù)據(jù),還是需要對對象進行一些方法的重載,使用 pytoch 定義的 DataLoader,用 enumerate,就會把所有的數(shù)據(jù)歷遍一次,如果使用 iter() 得到一個可迭代對象之后 next(),并不可以像 tensorflow 那樣子生成訓練數(shù)據(jù)。

例如說,如果使用如上的形式,DataLoader 得到的是一個生成器,python 中的生成器對象主要有 __next__ 和 __iter__ 等魔術(shù)方法決定。

__iter__ 方法使得實例可以如下調(diào)用,可以得到一個可迭代對象,iterable,但是如果不加也沒關(guān)系,因為更重要的是 __next__ 類方法。

如下自己寫了 __next__ 方法之后就可以看到,原本會出現(xiàn)越界的現(xiàn)象不見了,可以循環(huán)的歷遍數(shù)據(jù),當然也可以想被注釋的那部分一樣,拋出 StopIteration 來終止。

a = A()
a_iter = iter(a)
class A():
 def __init__(self):
 self.list = [1,2,3]
 self.index = 0
 #def __getitem__(self, index):
 # return self.list[i]
 #def __iter__(self):
 # return self
 def __next__(self):
 #for i in range():
 if self.index >= len(self.list):
 #raise StopIteration 
 self.index = self.index%len(self.list)
 result = self.list[self.index]
 self.index += 1
 return result 
b = A() 
for i in range(20):
 print(next(b))
 

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。

相關(guān)文章

  • Python 實現(xiàn)數(shù)組相減示例

    Python 實現(xiàn)數(shù)組相減示例

    今天小編就為大家分享一篇Python 實現(xiàn)數(shù)組相減示例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12
  • Python 調(diào)用 Windows API COM 新法

    Python 調(diào)用 Windows API COM 新法

    Python中調(diào)用Win32API 通常都是使用 PyWin32或者ctypes。本文給大家介紹Python 調(diào)用 Windows API COM 新法,感興趣的朋友跟隨小編一起看看吧
    2019-08-08
  • Python實現(xiàn)簡單的圖書管理系統(tǒng)

    Python實現(xiàn)簡單的圖書管理系統(tǒng)

    這篇文章主要為大家詳細介紹了Python實現(xiàn)簡單的圖書管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Python+Selenium鍵盤鼠標模擬事件操作詳解

    Python+Selenium鍵盤鼠標模擬事件操作詳解

    這篇文章主要帶大家一起學習一下Selenium的元素的基本操作與鼠標鍵盤模擬事件的操作,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下
    2022-06-06
  • python學習之hook鉤子的原理和使用

    python學習之hook鉤子的原理和使用

    這篇文章主要為大家詳細介紹了python學習之hook鉤子的原理和使用,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-10-10
  • 聊聊python中的循環(huán)遍歷

    聊聊python中的循環(huán)遍歷

    這篇文章主要介紹了python中的循環(huán)遍歷的相關(guān)資料,幫助大家更好的理解和學習python,感興趣的朋友可以了解下
    2020-09-09
  • Python函數(shù)常見幾種return返回值類型

    Python函數(shù)常見幾種return返回值類型

    本文主要介紹了Python函數(shù)常見幾種return返回值類型,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-01-01
  • Python語法def語句及復雜用法實例探究

    Python語法def語句及復雜用法實例探究

    在 Python 中,def?是用于定義函數(shù)的關(guān)鍵字,本文將深入介紹def的用法和特點,詳細說明如何定義函數(shù)、傳遞參數(shù)、返回值以及更復雜的用法
    2024-01-01
  • 20個解決日常編程問題的Python代碼分享

    20個解決日常編程問題的Python代碼分享

    在這篇文章中,主要和大家分享了20個Python代碼片段,以幫助你應對日常編程挑戰(zhàn)。文中的示例代碼講解詳細,感興趣的小伙伴可以跟上小編一起了解一下
    2023-01-01
  • Python爬蟲實現(xiàn)抓取京東店鋪信息及下載圖片功能示例

    Python爬蟲實現(xiàn)抓取京東店鋪信息及下載圖片功能示例

    這篇文章主要介紹了Python爬蟲實現(xiàn)抓取京東店鋪信息及下載圖片功能,涉及Python頁面請求、響應、解析等相關(guān)操作技巧,需要的朋友可以參考下
    2018-08-08

最新評論

阿荣旗| 平罗县| 阿克苏市| 盘山县| 宁化县| 永顺县| 广安市| 龙里县| 江安县| 威远县| 乳山市| 都匀市| 红安县| 巴彦县| 介休市| 宕昌县| 廊坊市| 镇巴县| 泸溪县| 凌源市| 安顺市| 福清市| 洪洞县| 民丰县| 银川市| 辉县市| 五家渠市| 曲麻莱县| 郧西县| 永济市| 团风县| 乌鲁木齐县| 浦江县| 汉中市| 航空| 英吉沙县| 晋江市| 乐山市| 竹北市| 阿拉善盟| 都匀市|