**1 **問題
在學(xué)習(xí)深度學(xué)習(xí)中卷積網(wǎng)絡(luò)過程中,有卷積層,池化層,全連接層等等,其中卷積層與池化層均可以對(duì)特征圖降維,本次實(shí)驗(yàn)針對(duì)控制其他層次一致的情況下,使用卷積降維與池化降維進(jìn)行對(duì)比分析,主要是看兩種降維方式對(duì)精度的影響以,以及損失值的大小。與此同時(shí)還可以探究不同維度下對(duì)精度是否有影響。
**2 **方法
這里是所有的代碼,每次只需要更改網(wǎng)絡(luò)的模型,即使用卷積層,使其降維的維度最后是1x1、7x7、14x14,需要更改三次,其次是使用池化層降維,最后也需要達(dá)到1x1、7x7、14x14,這三種維度。
| import torchvision
from torchvision.transforms import ToTensor, transforms
from torch.utils.data import DataLoader
from torch import nn
import torch
from time import *
import xlwt
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
創(chuàng)建一個(gè)新的類繼承nn.Module
class MyNet(nn.Module):
(5.2) 定義網(wǎng)絡(luò)有哪些層,這些層都作為成員變量
def init (self):
super(). init ()
卷積
in_channels輸入 out_channels輸出 kernel_size 卷積核 stride 步長
self.conv1 = nn.Conv2d(in_channels=1, out_channels=16, kernel_size=3, stride=1, padding=1, )
[-,16,28,28] [B, C, H, W] batch channel height weight
self.max_pool1 = nn.MaxPool2d(2)
self.conv2 = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=3, stride=2, padding=1, )
self.max_pool2 = nn.MaxPool2d(2)
self.conv3 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=4, stride=2, padding=1, )
self.max_pool3 = nn.MaxPool2d(2)
[-,32,28,28]
全連接
self.fc = nn.Linear(in_features=32 * 14 * 14, out_features=10)
(5.3) 定義數(shù)據(jù)在網(wǎng)絡(luò)中的流動(dòng)
x - 1x28x28 CxHxW C表示通道數(shù),H表示圖像高度,W表示圖像寬度
def forward(self, x):
x = torch.relu(self.conv1(x))
x = self.max_pool1(x)
x = torch.relu(self.conv2(x))
x = self.max_pool2(x)
x = torch.relu(self.conv3(x))
x = self.max_pool3(x)
x = torch.flatten(x, 1) #! 默認(rèn)從0維開始拉伸 如果不設(shè)置1的話 會(huì)吧batch也拉伸進(jìn)去
[B, C, H, W]
拉伸 C H W
out = torch.relu(self.fc(x))
return out
訓(xùn)練網(wǎng)絡(luò)
loss_list: 統(tǒng)計(jì)每個(gè)周期的平均loss
def train(dataloader, net, loss_fn, optimizer):
size = len(dataloader.dataset)
epoch_loss = 0.0
batch_num = len(dataloader)
net.train()
精度=原預(yù)測正確數(shù)量/總數(shù)
correct = 0
一個(gè)batch一個(gè)batch的訓(xùn)練網(wǎng)絡(luò)
for batch_idx, (x, y) in enumerate(dataloader):
--->
x, y = x.to(device), y.to(device) # 在GPU上運(yùn)行x,y
pred = net(x)
loss = loss_fn(pred, y)
基于loss信息利用優(yōu)化器從后向前更新網(wǎng)絡(luò)全部參數(shù)
optimizer.zero_grad()
loss.backward()
optimizer.step()
epoch_loss += loss.item()
correct += (pred.argmax(1) == y).type(torch.float).sum().item()
if batch_idx % 100 == 0:
print(f'batch index:, loss:') # item()方法將單個(gè)tensor轉(zhuǎn)化成數(shù)字
print(f'[ {batch_idx + 1 :>5d} / {batch_num :>5d} ] loss: {loss.item()}')
統(tǒng)計(jì)一個(gè)周期的平均loss
avg_loss = epoch_loss / batch_num
avg_accuracy = correct / size
return avg_accuracy, avg_loss
驗(yàn)證and評(píng)估
def test_and_val(dataloader, net, loss_fn):
size = len(dataloader.dataset)
batch_num = len(dataloader)
correct = 0
losses = 0
net.eval()
with torch.no_grad():
for x, y in dataloader:
x, y = x.to(device), y.to(device)
pred = net(x)
loss = loss_fn(pred, y)
losses += loss.item()
correct += (pred.argmax(1) == y).type(torch.int).sum().item()
accuracy = correct / size
avg_loss = losses / batch_num
print(f'The Accuracy =%')
return accuracy, avg_loss
if name == 'main':
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(0.1307, 0.3081)])
(0) 測試機(jī)器是否支持GPU
data_train_acc = []
data_train_loss = []
data_val_acc = []
data_val_loss = []
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
batch_size = [32,64,128,256]
batch_size = [64]
train_all_ds = torchvision.datasets.MNIST(root="data", download=True, train=True, transform=transform, )
將訓(xùn)練集劃分為訓(xùn)練集+驗(yàn)證集
train_ds, val_ds = torch.utils.data.random_split(train_all_ds, [50000,10000])
test_ds = torchvision.datasets.MNIST(root="data", download=True, train=False, transform=transform, )
for each in range(len(batch_size)):
train_loader = DataLoader(dataset=train_ds,batch_size=batch_size[each], shuffle=True,)
val_loader = DataLoader(dataset=val_ds,batch_size=batch_size[each],)
test_loader = DataLoader(dataset=test_ds,batch_size=batch_size[each],)
(5) 網(wǎng)絡(luò)的輸入、輸出以及測試網(wǎng)絡(luò)的性能(不經(jīng)過任何訓(xùn)練的網(wǎng)絡(luò))
net = MyNet().to(device)
optimizer = torch.optim.SGD(net.parameters(), lr=0.01)
loss_fn = torch.nn.CrossEntropyLoss()
(6)訓(xùn)練周期
begin_time = time()
train_accuracy_list = []
train_loss_list = []
val_accuracy_list = []
val_loss_list = []
epoch = 10
for t in range(epoch):
print(f"Epoch {t + 1}")
train_accuracy, train_loss = train(train_loader, net, loss_fn, optimizer)
train_accuracy_list.append(train_accuracy)
train_loss_list.append(train_loss)
print(f'Epoch {t + 1 :<2d} Train Acc = {train_accuracy * 100 :.2f}% || Epoch {t + 1} Train Loss = {train_loss}')
val_accuracy, val_loss = test_and_val(val_loader, net, loss_fn)
val_accuracy_list.append(val_accuracy)
val_loss_list.append(val_loss)
print(f'Epoch {t + 1 :<2d} Val Acc = {val_accuracy * 100 :.2f}% || Epoch {t + 1} Val Loss = {val_loss}')
print(f'Best_Train_Acc =% || Best_Val_Acc =%')
data_train_acc.append(train_accuracy_list)
data_train_loss.append(train_loss_list)
data_val_acc.append(val_accuracy_list)
data_val_loss.append(val_loss_list)
data_set = [data_train_acc,data_train_loss,data_val_acc,data_val_loss]
file = xlwt.Workbook('encoding = utf-8') # 設(shè)置工作簿編碼
sheet1 = file.add_sheet('數(shù)據(jù)', cell_overwrite_ok=True) # 創(chuàng)建sheet工作表
要寫入的列表的值
name = ['train_acc_batch','train_loss_batch','val_acc_batch','val_loss_batch']
for one in range(len(data_set)):
data = data_set[one]
id = name[one]
for i in range(len(data)):
for j in range(len(data[i])):
sheet1.write(j, i, data[i][j]) # 寫入數(shù)據(jù)參數(shù)對(duì)應(yīng) 行, 列, 值
file.save(f'CNN1_CH_.xls') # 保存.xls到當(dāng)前工作目錄
print(f'Best_Train_Acc = {max(train_accuracy_list) * 100 :.2f}%, Best_Val_Acc = {max(val_accuracy_list) * 100 :.2f}%')
test_accuracy,_ = test_and_val(test_loader, net, loss_fn)
print(f'Test Acc = {test_accuracy * 100}%')
end_time = time()
print('Time Consumed:',end_time-begin_time) |
卷積降維與池化降維對(duì)精度的影響
圖2.1訓(xùn)練集精度對(duì)比
圖2.2驗(yàn)證集精度對(duì)比
如圖2.1和圖2.2所示在使用卷積降維的情況下無論特征圖尺寸在14x14、7x7、1x1在訓(xùn)練集下,精度最開始都是從80%多在10個(gè)周期以后均能達(dá)到99%左右,最終預(yù)測精度能達(dá)到99.99%,并且在10個(gè)周期以后就達(dá)到99%,再訓(xùn)練90個(gè)周期就是緩慢的從99%到99.99%幾乎接近1的精度了。訓(xùn)練集也是如此,10個(gè)周期左右達(dá)到98%,最后穩(wěn)定在98.40%左右。
池化降維,無論訓(xùn)練集還是驗(yàn)證集在14x14、7x7,1x1在首次只有60%多的準(zhǔn)確率,在14x14的尺寸下,池化降維可以接近90%的準(zhǔn)確率,大致在88%-89%,7x7、1x1均只能達(dá)到78%-79%左右,并且都是在10個(gè)周期左右趨于穩(wěn)定,只有小幅波動(dòng)。
圖2.3訓(xùn)練集損失值對(duì)比
卷積降維與池化降維對(duì)損失值****的影響
圖2.4驗(yàn)證集損失值對(duì)比
如圖2.3和2.4所示,卷積降維訓(xùn)練集與驗(yàn)證集的損失值在首次就能達(dá)到池化降維的最小值,并且卷積降維隨著訓(xùn)練次數(shù)的增加還在持續(xù)減小,幾乎能夠達(dá)到0.00幾的損失值,最后穩(wěn)定在這附近波動(dòng),代表預(yù)測值與真實(shí)值之間的差距非常小,幾乎接近。
然后池化降維首次就是0.8-0.9左右,隨著訓(xùn)練次數(shù)增加最低值也就只有0.5-0.6左右。但是池化降維在14x14尺寸下其損失值可以相對(duì)于在池化降維下7x7、1x1的尺寸下較小一些,可以達(dá)到0.3左右的損失值。
**3 **結(jié)語
針對(duì)卷積降維和池化降維,這里是對(duì)特征圖14x14、7x7、1x1進(jìn)行了精度對(duì)比和損失值對(duì)比的分析,最終得出在對(duì)于降維的方法使用下,卷積降維效果更佳,但需要人為去計(jì)算出該卷積出來的特征圖大小,但是池化可以直接很簡單的得出特征圖大小,這是其中一個(gè)區(qū)別,也是池化特征的一個(gè)優(yōu)點(diǎn)。但是對(duì)于實(shí)驗(yàn)結(jié)果的效果,卷積降維要更好與池化降維的。能夠使訓(xùn)練集精度達(dá)到99.99%,驗(yàn)證集精度達(dá)到98.40%左右。這是卷積降維的優(yōu)點(diǎn)所在。
在本次實(shí)驗(yàn)中,得出的最后的結(jié)論是,卷積降維對(duì)于結(jié)果精度要優(yōu)于池化降維,但是卷積降維需要人為來計(jì)算卷積后的特征圖大小,從而去更改卷積層的參數(shù),有時(shí)候較為麻煩。池化降維則可以輕易的得出想要的特征圖大小。
對(duì)于本次實(shí)驗(yàn)只是比較了特征圖14x14、7x7、1x1,這三個(gè)尺寸對(duì)于精度的影響不同。還可以試著比較訓(xùn)練花費(fèi)時(shí)間。以及不同尺寸是否對(duì)結(jié)果有什么影響。這次實(shí)驗(yàn)數(shù)據(jù)也有不同尺寸的結(jié)果,我也同時(shí)對(duì)比了一下在卷積層最后不同的尺寸對(duì)于精度的影響,最后發(fā)現(xiàn)只有前10個(gè)周期有一點(diǎn)區(qū)別,最終均能達(dá)到最優(yōu)的效果,但是為了計(jì)算量的減少,在同等結(jié)果的情況下,尺寸小那么更節(jié)省時(shí)間吧。
-
卷積
+關(guān)注
關(guān)注
0文章
94瀏覽量
18466 -
深度學(xué)習(xí)
+關(guān)注
關(guān)注
73文章
5422瀏覽量
120593 -
卷積網(wǎng)絡(luò)
+關(guān)注
關(guān)注
0文章
42瀏覽量
2143
發(fā)布評(píng)論請先 登錄
相關(guān)推薦
評(píng)論