%matplotlib inline from matplotlib import pyplot as plt import numpy as np import collections import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim torch.set_default_tensor_type('torch.FloatTensor') torch.manual_seed(123) #定义类别的名称 class_namess=["airplane", "automobile", "bird", "cat", "deer","dog", "frog", "horse", "ship", "truck"] #加载CIFAR数据集,训练集 from torchvision import datasets, transforms data_path="data/8/cifae-10/" cifar10=datasets.CIFAR10(data_path, train=True, download=True,transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.4915, 0.4823, 0.4468), (0.2470, 0.2435, 0.2616))])) #加载验证集 cifar10_val=datasets.CIFAR10(data_path,train=False,download=True,transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.4915, 0.4823, 0.4468), (0.2470, 0.2435, 0.2616))])) #再把鸟和飞机摘出来,重新标注标签 label_map={0:0,2:1} class_names=["airplane","bird"] cifar2=[(img,label_map[label])for img,label in cifar10 if label in [0,2]] cifar2_val=[(img,label_map[label])for img,label in cifar10_val if label in [0,2]]
Files already downloaded and verified Files already downloaded and verified
In [38]:
conv=nn.Conv2d(3,16,kernel_size=3) conv
Out[38]:
Conv2d(3, 16, kernel_size=(3, 3), stride=(1, 1))
In [39]:
conv.weight.shape,conv.bias.shape
Out[39]:
(torch.Size([16, 3, 3, 3]), torch.Size([16]))
In [40]:
img,_=cifar2[0] output=conv(img.unsqueeze(0)) img.unsqueeze(0).shape,output.shape
Out[40]:
(torch.Size([1, 3, 32, 32]), torch.Size([1, 16, 30, 30]))
In [41]:
plt.figure(figsize=(10,4.8)) axl=plt.subplot(1,2,1) plt.title("output") plt.imshow(output[0,0].detach(),cmap="gray") plt.subplot(1,2,2,sharex=axl,sharey=axl) plt.imshow(img.mean(0),cmap="gray") plt.title("input") plt.show()

In [42]:
conv=nn.Conv2d(3,16,kernel_size=3,padding=1) img,_=cifar2[0] output=conv(img.unsqueeze(0)) img.unsqueeze(0).shape,output.shape
Out[42]:
(torch.Size([1, 3, 32, 32]), torch.Size([1, 16, 32, 32]))
In [43]:
with torch.no_grad(): conv.bias.zero_() with torch.no_grad(): conv.weight.fill_(1.0/9.0) output=conv(img.unsqueeze(0)) plt.figure(figsize=(10,4.8)) axl=plt.subplot(1,2,1) plt.title("output") plt.imshow(output[0,0].detach(),cmap="gray") plt.subplot(1,2,2,sharex=axl,sharey=axl) plt.imshow(img.mean(0),cmap="gray") plt.title("input") plt.show()

In [44]:
conv=nn.Conv2d(3,1,kernel_size=3,padding=1) with torch.no_grad(): conv.weight[:]=torch.tensor([[-1.0,0.0,1.0],[-1.0,0.0,1.0],[-1.0,0.0,1.0]]) conv.bias.zero_() output=conv(img.unsqueeze(0)) plt.figure(figsize=(10,4.8)) axl=plt.subplot(1,2,1) plt.title("output") plt.imshow(output[0,0].detach(),cmap="gray") plt.subplot(1,2,2,sharex=axl,sharey=axl) plt.imshow(img.mean(0),cmap="gray") plt.title("input") plt.show()

池化
In [45]:
model=nn.Sequential( nn.Conv2d(3,16,kernel_size=3,padding=1), nn.Tanh(), nn.MaxPool2d(2), nn.Conv2d(16,16,kernel_size=3,padding=1), nn.Tanh(), nn.MaxPool2d(2), nn.Linear(8*8*8,32), nn.Tanh(), nn.Linear(32,2) ) numel_list=[p.numel() for p in model.parameters()] sum(numel_list),numel_list
Out[45]:
(19250, [432, 16, 2304, 16, 16384, 32, 64, 2])
In [46]:
class Net(nn.Module): def __init__(self): super(Net,self).__init__() self.conv1=nn.Conv2d(3,16,kernel_size=3,padding=1) self.conv2=nn.Tanh() self.pool1=nn.MaxPool2d(2) self.conv2=nn.Conv2d(16,16,kernel_size=3,padding=1) self.act2= nn.Tanh() self.pool2=nn.MaxPool2d(2) self.fc1=nn.Linear(8*8*8,32) self.act3= nn.Tanh() self.fc2=nn.Linear(32,2) def forward(self,x): out = self.pool1(self.act1(self.conv1(x))) out = self.pool2(self.act2(self.conv2(out))) out = out.view(-1,8*8*8) out = self.act3(self.fc1(out)) out = self.fc2(out) return out
In [47]:
import torch.nn.functional as F
In [48]:
class Net(nn.Module): def __init__(self): super().__init__() self.conv1=nn.Conv2d(3,16,kernel_size=3,padding=1) self.conv2=nn.Conv2d(16,8,kernel_size=3,padding=1) self.fc1=nn.Linear(8*8*8,32) self.fc2=nn.Linear(32,2) def forward(self,x): out=F.max_pool2d(torch.tanh(self.conv1(x)),2) out=F.max_pool2d(torch.tanh(self.conv2(out)),2) out = out.view(-1,8*8*8) out = torch.tanh(self.fc1(out)) out = self.fc2(out) return out
训练模型
In [49]:
import datetime
In [50]:
def train_loop(n_epochs,optimizer,model,loss_fn,train_loader): for epoch in range(1,n_epochs+1): loss_train=0.0 for imgs,labels in train_loader: outputs=model(imgs) loss = loss_fn(outputs,labels) optimizer.zero_grad() loss.backward() optimizer.step() loss_train+=loss.item() if epoch==1 or epoch % 10 == 0: print('{} epoch {}, Training Loss: {:.4f}'.format(datetime.datetime.now(),epoch,loss_train/ len(train_loader)))
In [51]:
train_loader=torch.utils.data.DataLoader(cifar2,batch_size=64,shuffle=True) model=Net() optimizer=optim.SGD(model.parameters(),lr=1e-2,) loss_fn=nn.CrossEntropyLoss() train_loop( n_epochs=100, optimizer=optimizer, model=model, loss_fn=loss_fn, train_loader=train_loader, )
2025-01-18 11:05:54.452644 epoch 1, Training Loss: 0.5669 2025-01-18 11:06:01.443614 epoch 10, Training Loss: 0.3434 2025-01-18 11:06:08.964075 epoch 20, Training Loss: 0.3072 2025-01-18 11:06:16.550718 epoch 30, Training Loss: 0.2764 2025-01-18 11:06:24.474405 epoch 40, Training Loss: 0.2524 2025-01-18 11:06:32.265278 epoch 50, Training Loss: 0.2309 2025-01-18 11:06:40.182867 epoch 60, Training Loss: 0.2109 2025-01-18 11:06:48.353061 epoch 70, Training Loss: 0.1975 2025-01-18 11:06:56.240187 epoch 80, Training Loss: 0.1830 2025-01-18 11:07:03.885278 epoch 90, Training Loss: 0.1692 2025-01-18 11:07:12.010916 epoch 100, Training Loss: 0.1593
In [52]:
train_loader=torch.utils.data.DataLoader(cifar2,batch_size=64,shuffle=True) val_loader=torch.utils.data.DataLoader(cifar2_val,batch_size=64,shuffle=True) def validate(model,train_loader,val_loader): for name,loader in [("train",train_loader),("val",val_loader)]: correct=0 total=0 with torch.no_grad(): for imgs,labels in loader: outputs=model(imgs) _,predicted=torch.max(outputs,dim=1) total += labels.size(0) correct +=int((predicted==labels).sum()) print("Accuracy {}: {:.2f}".format(name,correct/total)) validate(model,train_loader,val_loader)
Accuracy train: 0.94 Accuracy val: 0.90
In [53]:
#保存模型 torch.save(model.state_dict(),'birds_and_airplanes.pt')
In [54]:
#加载模型 loaded_model=Net() loaded_model.load_state_dict(torch.load('birds_and_airplanes.pt'))
C:\Users\tanhaowen\AppData\Local\Temp\ipykernel_5560\505120885.py:3: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature. loaded_model.load_state_dict(torch.load('birds_and_airplanes.pt'))
Out[54]:
<All keys matched successfully>
In [55]:
# 使用gpu训练模型 device=(torch.device('cuda' if torch.cuda.is_available() else 'cpu')) print(f"Training on device {device}")
Training on device cuda
In [56]:
import datetime def train_loop(n_epochs,optimizer,model,loss_fn,train_loader): for epoch in range(1,n_epochs+1): loss_train=0.0 for imgs,labels in train_loader: imgs=imgs.to(device=device) labels=labels.to(device=device) outputs=model(imgs) loss = loss_fn(outputs,labels) optimizer.zero_grad() loss.backward() optimizer.step() loss_train+=loss.item() if epoch==1 or epoch % 10 == 0: print("{} Epoch {},Trainging loss{}".format(datetime.datetime.now(),epoch,loss_train/ len(train_loader))) train_loader=torch.utils.data.DataLoader(cifar2,batch_size=64,shuffle=True) model=Net().to(device=device) optimizer=optim.SGD(model.parameters(),lr=1e-2,) loss_fn=nn.CrossEntropyLoss() train_loop( n_epochs=100, optimizer=optimizer, model=model, loss_fn=loss_fn, train_loader=train_loader )
2025-01-18 11:07:12.993692 Epoch 1,Trainging loss0.5774919248310624 2025-01-18 11:07:14.822029 Epoch 10,Trainging loss0.33247699137705905 2025-01-18 11:07:16.864327 Epoch 20,Trainging loss0.30183320971810895 2025-01-18 11:07:18.885874 Epoch 30,Trainging loss0.27957967806393935 2025-01-18 11:07:21.007782 Epoch 40,Trainging loss0.25747410525941544 2025-01-18 11:07:23.076285 Epoch 50,Trainging loss0.23804032361241662 2025-01-18 11:07:25.050501 Epoch 60,Trainging loss0.22230669409985754 2025-01-18 11:07:26.987403 Epoch 70,Trainging loss0.20533453340932822 2025-01-18 11:07:28.945509 Epoch 80,Trainging loss0.1917050355084383 2025-01-18 11:07:30.867017 Epoch 90,Trainging loss0.17810696173625387 2025-01-18 11:07:32.824421 Epoch 100,Trainging loss0.16675861360161168
In [57]:
# 优化方案:增加模型宽度 class Net(nn.Module): def __init__(self,n_classes=32): super().__init__() self.conv1=nn.Conv2d(3,32,kernel_size=3,padding=1) self.conv2=nn.Conv2d(32,16,kernel_size=3,padding=1) self.fc1=nn.Linear(16*8*8,32) self.fc2=nn.Linear(32,2) def forward(self,x): out = F.max_pool2d(torch.tanh(self.conv1(x)),2) out = F.max_pool2d(torch.tanh(self.conv2(out)),2) out = out.view(-1,16*8*8) out=torch.tanh(self.fc1(out)) out = self.fc2(out) return out
In [58]:
class NetWidth(nn.Module): def __init__(self,n_chans1=32): super().__init__() self.n_chans1=n_chans1 self.conv1=nn.Conv2d(3,n_chans1,kernel_size=3,padding=1) self.conv2=nn.Conv2d(n_chans1,n_chans1//2,kernel_size=3,padding=1) self.fc1=nn.Linear(16*8*n_chans1,32) self.fc2=nn.Linear(32,2) def forward(self,x): out = F.max_pool2d(torch.tanh(self.conv1(x)),2) out = F.max_pool2d(torch.tanh(self.conv2(out)),2) out = out.view(-1,16*8*8) out=torch.tanh(self.fc1(out)) out = self.fc2(out) return out
In [59]:
# 优化方案:正则化 def training_loop_12reg(n_epochs,optimizer,model,loss_fn,train_loader): for epoch in range(1,n_epochs+1): loss_train=0.0 for imgs,labels in train_loader: imgs=imgs.to(device=device) labels=labels.to(device=device) outputs=model(imgs) loss=loss_fn(outputs,labels) l2_lambda=0.001 l2_norn=sum(p.pow(2).sum() for p in model.parameters()) loss=loss+l2_lambda*l2_norn optimizer.zero_grad() loss.backwark() optimizer.step() loss_train+=loss.item() if epoch==1 or epoch % 10 == 0: print("{} Epoch {},Training loss{}".format(datetime.datetime.now(),epoch,loss_train/ len(train_loader)))
In [60]:
class NetDropout(nn.Module): def __init__(self,n_chans1=32): super().__init__() self.n_chans1=n_chans1 self.conv1=nn.Conv2d(3,n_chans1,kernel_size=3,padding=1) self.conv1_dropout=nn.Dropout2d(p=0.4) self.conv2=nn.Conv2d(n_chans1,n_chans1//2,kernel_size=3,padding=1) self.conv2_dropout=nn.Dropout2d(p=0.4) self.fc1=nn.Linear(16*8*n_chans1,32) self.fc2=nn.Linear(32,2) def forward(self,x): out = F.max_pool2d(torch.tanh(self.conv1(x)),2) out =self.conv1_dropout(out) out = F.max_pool2d(torch.tanh(self.conv2(x)),2) out = self.conv2_dropout(out) out = out.view(-1,8*8*self.n_chans1//2) out=torch.tanh(self.fc1(out)) out = self.fc2(out) return out
In [61]:
class NetBatchNorn(nn.Module): def __init__(self,n_chans1=32): super().__init__() self.n_chans1=n_chans1 self.conv1=nn.Conv2d(3,n_chans1,kernel_size=3,padding=1) self.conv1_batchnorm=nn.BatchNorm2d(num_features=n_chans1) self.conv2=nn.Conv2d(n_chans1,n_chans1//2,kernel_size=3,padding=1) self.conv2_batchnorm=nn.BatchNorm2d(num_features=n_chans1//2) self.fc1=nn.Linear(8*8*n_chans1//2,32) self.fc2=nn.Linear(32,2) def forward(self,x): out=self.conv1_batchnorm(self.conv1(x)) out=F.max_pool2d(torch.tanh(out),2) out=self.conv2_batchnorm(self.conv2(out)) out=F.max_pool2d(torch.tanh(out),2)
In [62]:
# 增加模型的深度
In [63]:
class ResNetTest(nn.Module): def __init__(self,n_chans1=32): super().__init__() self.n_chans1=n_chans1 self.conv1=nn.Conv2d(3,n_chans1,kernel_size=3,padding=1) self.conv2=nn.Conv2d(n_chans1,n_chans1//2,padding=1) self.conv3=nn.Conv2d(n_chans1//2,n_chans1//2,kernel_size=3,padding=1) self.fc1=nn.Linear(4*4*n_chans1//2,32) self.fc2=nn.Linear(32,2) def forward(self,x): out = F.max_pool2d(torch.tanh(self.conv1(x)),2) out = F.max_pool2d(torch.tanh(self.conv2(out)),2) out1=out out = F.max_pool2d(torch.tanh(self.conv3(out1))+out1,2) out=out.view(-1,4*4*self.n_chans1//2) out=torch.tanh(self.fc1(out)) out=self.fc2(out) return out
In [64]:
import datetime def train_loop(n_epochs,optimizer,model,loss_fn,train_loader): for epoch in range(1,n_epochs+1): loss_train=0.0 for imgs,labels in train_loader: imgs=imgs.to(device=device) labels=labels.to(device=device) outputs=model(imgs) loss=loss_fn(outputs,labels) optimizer.zero_grad() loss.backward() optimizer.step()
In [65]:
import datetime def train_loop(n_epochs,optimizer,model,loss_fn,train_loader): for epoch in range(1,n_epochs+1): loss_train=0.0 for imgs,labels in train_loader: imgs=imgs.to(device=device) labels=labels.to(device=device) outputs=model(imgs) loss = loss_fn(outputs,labels) optimizer.zero_grad() loss.backward() optimizer.step() loss_train+=loss.item() if epoch==1 or epoch % 10 == 0: print("{} Epoch {},Trainging loss{}".format(datetime.datetime.now(),epoch,loss_train/ len(train_loader))) train_loader=torch.utils.data.DataLoader(cifar2,batch_size=64,shuffle=True) model=Net().to(device=device) optimizer=optim.SGD(model.parameters(),lr=1e-2,) loss_fn=nn.CrossEntropyLoss() train_loop( n_epochs=100, optimizer=optimizer, model=model, loss_fn=loss_fn, train_loader=train_loader )
2025-01-18 11:07:33.129450 Epoch 1,Trainging loss0.5390971137839518 2025-01-18 11:07:35.072852 Epoch 10,Trainging loss0.3141013920117336 2025-01-18 11:07:37.278568 Epoch 20,Trainging loss0.2712045578155548 2025-01-18 11:07:39.430647 Epoch 30,Trainging loss0.24286607107159439 2025-01-18 11:07:41.834147 Epoch 40,Trainging loss0.21347075112306388 2025-01-18 11:07:44.318877 Epoch 50,Trainging loss0.18563196461671477 2025-01-18 11:07:46.807634 Epoch 60,Trainging loss0.16053212640486705 2025-01-18 11:07:49.275878 Epoch 70,Trainging loss0.13700199025167023 2025-01-18 11:07:51.757971 Epoch 80,Trainging loss0.12101342035516811 2025-01-18 11:07:54.277553 Epoch 90,Trainging loss0.09994453897664121 2025-01-18 11:07:56.746458 Epoch 100,Trainging loss0.0841510158008451
In [67]:
train_loader=torch.utils.data.DataLoader(cifar2,batch_size=64,shuffle=True) val_loader=torch.utils.data.DataLoader(cifar2_val,batch_size=64,shuffle=True) def validate(model,train_loader,val_loader): for name,loader in [("train",train_loader),("val",val_loader)]: correct=0 total=0 with torch.no_grad(): for imgs,labels in loader: imgs=imgs.to(device=device) labels=labels.to(device=device) outputs=model(imgs) _,predicted=torch.max(outputs,dim=1) total += labels.size(0) correct +=int((predicted==labels).sum()) print("Accuracy {}: {:.2f}".format(name,correct/total)) validate(model,train_loader,val_loader)
Accuracy train: 0.97 Accuracy val: 0.90
In [ ]:
发表回复