PyTorch深度学习实战第八章代码交互式编程转普通py脚本(带注释) Jupyter Notebook代码转普通py代码
·
8.2卷积实战:
from torchvision import datasets,transforms
import numpy as np
import matplotlib.pyplot as plt
import torch.nn as nn
import torch
data_path = '../data-unversioned/p1ch7/'
cifar10 = datasets.CIFAR10(data_path, train=True, download=True,transform=transforms.ToTensor())
cifar10_val = datasets.CIFAR10(data_path, train=False, download=True,transform=transforms.ToTensor())
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] ]
#8.2卷积实战
conv = nn.Conv2d(3,16,kernel_size=3)
print(conv)
print(conv.weight.shape,conv.bias.shape)
img, _ = cifar2[0]
output = conv(img.unsqueeze(0))
print(img.unsqueeze(0).shape,output.shape)
plt.imshow(output[0,0].detach(),cmap='gray')
plt.show()
#8.2.1填充边界
conv = nn.Conv2d(3,1,kernel_size=3,padding=1)
output = conv(img.unsqueeze(0))
print(img.unsqueeze(0).shape,output.shape)
#8.2.2用卷积检测特征
with torch.no_grad():
conv.bias.zero_()
with torch.no_grad():
conv.weight.fill_(1.0/9.0)
output = conv(img.unsqueeze(0))
plt.imshow(output[0,0].detach(),cmap='gray')
plt.show()
#8.2.3 深度和池化技术
pool = nn.MaxPool2d(2)
output = pool(img.unsqueeze(0))
print(img.unsqueeze(0).shape,output.shape)
#8.2.4 整合一切(书上原本代码就是跑不通的,因此会报错,此处仅供展示,运行时请注释掉)
model = nn.Sequential(
nn.Conv2d(3,16,kernel_size=5,padding=2),
nn.ReLU(),
nn.MaxPool2d(2),
nn.Conv2d(16,8,kernel_size=5,padding=2),
nn.ReLU(),
nn.MaxPool2d(2),
nn.Linear(8*8*8,32),
nn.Tanh(),
nn.Linear(32,2)
)
numel_list = [p.numel() for p in model.parameters()]
print(sum(numel_list),numel_list)
model(img.unsqueeze(0))#此处必定报错,报错为:RuntimeError: mat1 and mat2 shapes cannot be multiplied (64x8 and 512x32)
此代码运行时在最后一步会报错,与书上报错内容一致,具体报错原因为输入张量(64*8)与需求张量(512*32)结构不符
8.3子类化nn.Module
from torchvision import datasets,transforms
import numpy as np
import matplotlib.pyplot as plt
import torch.nn as nn
import torch
#8.3.1将网络作为一个nn.module 注此处应和8.3.3代码互斥,即运行时请注释掉8.3.3代码,否则会报重复定义Net类的错
# class Net(nn.Module):
# def __init__(self):
# super().__init__()
# self.conv1 = nn.Conv2d(3,16,kernel_size=3,padding=1)
# self.act1 = nn.Tanh()
# self.pool1 = nn.MaxPool2d(2)
# self.conv2 = nn.Conv2d(16,8,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
#8.3.2查看网络参数 运行时解除8.3.1代码注释
# model = Net()
# numel_list = [p.numel() for p in model.parameters()]
# print("输出网络总参数:",sum(numel_list),"网络各部分参数:",numel_list)
#8.3.3函数式API 注此处应和8.3.1代码互斥,即运行时请注释掉8.3.1代码,否则会报重复定义Net类的错
import torch.nn.functional as F
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
data_path = '../data-unversioned/p1ch7/'
cifar10 = datasets.CIFAR10(data_path, train=True, download=True,transform=transforms.ToTensor())
cifar10_val = datasets.CIFAR10(data_path, train=False, download=True,transform=transforms.ToTensor())
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] ]
img, _ = cifar2[0]
model = Net()
print(model(img.unsqueeze(0)))
注意注释中提及的代码互斥问题
8.4训练convnet(CPU)
from torchvision import datasets,transforms
import torch.nn as nn
import torch
import torch.nn.functional as F
import datetime
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
def training_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 {}'.format(datetime.datetime.now(),epoch,loss_train/len(train_loader)))
#8.4.1测量精度
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.shape[0]
correct += int((predicted == labels).sum())
print('Accuracy{}:{:.2f}'.format(name,correct/total))
data_path = '../data-unversioned/p1ch7/'
cifar10 = datasets.CIFAR10(data_path, train=True, download=True,transform=transforms.ToTensor())
cifar10_val = datasets.CIFAR10(data_path, train=False, download=True,transform=transforms.ToTensor())
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] ]
train_loader = torch.utils.data.DataLoader(cifar2,batch_size=64,shuffle=True)#此处shuffle设置为True时打乱数据
model = Net()
optimizer = torch.optim.SGD(model.parameters(),lr=1e-2)
loss_fn = nn.CrossEntropyLoss()
training_loop(n_epochs=100,optimizer=optimizer,model=model,loss_fn=loss_fn,train_loader=train_loader)
train_loader = torch.utils.data.DataLoader(cifar2,batch_size=64,shuffle=False)
val_loader = torch.utils.data.DataLoader(cifar2_val,batch_size=64,shuffle=False)
validate(model,train_loader,val_loader)
#8.4.2保存加载模型
torch.save(model.state_dict(),data_path + 'bird_vs_airplane.pt')#保存模型
load_model = Net()#实例化模型
load_return = load_model.load_state_dict(torch.load(data_path+'bird_vs_airplane.pt'))#加载模型参数
print(load_return)
8.4.3GPU:
from torchvision import datasets,transforms
import torch.nn as nn
import torch
import torch.nn.functional as F
import datetime
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
def training_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)#将数据移动到GPU或CPU上
labels = labels.to(device=device)#将数据移动到GPU或CPU上
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 {}'.format(datetime.datetime.now(),epoch,loss_train/len(train_loader)))
#8.4.1测量精度
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)#将数据移动到GPU或CPU上
labels = labels.to(device=device)#将数据移动到GPU或CPU上
outputs = model(imgs)
_,predicted = torch.max(outputs,dim=1)
total += labels.shape[0]
correct += int((predicted == labels).sum())
print('Accuracy{}:{:.2f}'.format(name,correct/total))
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print('Using device:',device)
data_path = '../data-unversioned/p1ch7/'
cifar10 = datasets.CIFAR10(data_path, train=True, download=True,transform=transforms.ToTensor())
cifar10_val = datasets.CIFAR10(data_path, train=False, download=True,transform=transforms.ToTensor())
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] ]
train_loader = torch.utils.data.DataLoader(cifar2,batch_size=64,shuffle=True)#此处shuffle设置为True时打乱数据
model = Net().to(device=device)
optimizer = torch.optim.SGD(model.parameters(),lr=1e-2)
loss_fn = nn.CrossEntropyLoss()
training_loop(n_epochs=100,optimizer=optimizer,model=model,loss_fn=loss_fn,train_loader=train_loader)
train_loader = torch.utils.data.DataLoader(cifar2,batch_size=64,shuffle=False)
val_loader = torch.utils.data.DataLoader(cifar2_val,batch_size=64,shuffle=False)
validate(model,train_loader,val_loader)
#8.4.2保存加载模型
torch.save(model.state_dict(),data_path + 'bird_vs_airplane.pt')#保存模型
load_model = Net().to(device=device)#实例化模型
load_return = load_model.load_state_dict(torch.load(data_path+'bird_vs_airplane.pt'))#加载模型参数
print(load_return)
8.5模型设计:
8.5.1增加内存容量:宽度
from torchvision import datasets,transforms
import torch.nn as nn
import torch
import torch.nn.functional as F
class NetWideth(nn.Module):#硬编码数字
def __init__(self):
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
model = NetWideth()
numel_list = [p.numel() for p in model.parameters()]
print("输出网络总参数:",sum(numel_list),"网络各部分参数:",numel_list)
class NetWideth2(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(8*8*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)
out = out.view(-1,8*8*self.n_chans1//2)
out = torch.tanh(self.fc1(out))
out = self.fc2(out)
return out
model2 = NetWideth2()
numel_list2 = [p2.numel() for p2 in model2.parameters()]
print("输出网络总参数:",sum(numel_list2),"网络各部分参数:",numel_list2)
8.5.2模型收敛和泛化:
1.检查参数:权重惩罚:
def training_loop_l2reg(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)#将数据移动到GPU或CPU上
labels = labels.to(device=device)#将数据移动到GPU或CPU上
outputs = model(imgs)
loss = loss_fn(outputs,labels)
l2_lambda = 0.001
l2_norm = sum(p.pow(2.0).sum() for p in model.parameters())
loss = loss + l2_lambda*l2_norm
optimizer.zero_grad()
loss.backward()
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)))
2.不依赖单一输入:Dropout:
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(8*8*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 = self.conv1_dropout(out)
out = F.max_pool2d(torch.tanh(self.conv2(out)),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
3.批量归一化:
class NetBatchNorm(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(self.conv1(x)),2)
out = self.conv2_batchnorm(self.conv2(out))
out = F.max_pool2d(torch.tanh(self.conv2(out)),2)
out = out.view(-1,8*8*self.n_chans1//2)
out = torch.tanh(self.fc1(out))
out = self.fc2(out)
return out
8.5.3深度:
1.跳跃连接:
class NetRes(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.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.relu(self.conv1(x)),2)
out = F.max_pool2d(torch.relu(self.conv2(out)),2)
out1 = out
out = F.max_pool2d(torch.relu(self.conv3(out))+out1,2)
out = out.view(-1,4*4*self.n_chans1//2)
out = torch.tanh(self.fc1(out))
out = self.fc2(out)
return out
2.使用pytorch建立非常深的模型:
class ResBlock(nn.Module):
def __init__(self,n_chans):
super(ResBlock,self).__init__()
self.conv = nn.Conv2d(n_chans,n_chans,kernel_size=3,padding=1,bias=False)
self.batch_norm = nn.BatchNorm2d(num_features=n_chans)
torch.nn.init.kaiming_normal_(self.conv.weight,nonlinearity='relu')
torch.nn.init.constant_(self.batch_norm.weight,0.5)
torch.nn.init.zeros_(self.batch_norm.bias)
def forward(self,x):
out = self.conv(x)
out = self.batch_norm(out)
out = torch.relu(out)
return out+x
class NetResDeep(nn.Module):
def __init__(self,n_chans1 = 32,n_blocks = 10):
super().__init__()
self.n_chans1 = n_chans1
self.conv1 = nn.Conv2d(3,n_chans1,kernel_size=3,padding=1)
self.resblocks = nn.Sequential(*(n_blocks*[ResBlock(n_chans=n_chans1)]))
self.fc1 = nn.Linear(8*8*n_chans1,32)
self.fc2 = nn.Linear(32,2)
def forward(self,x):
out = F.max_pool2d(torch.relu(self.conv1(x)),2)
out = self.resblocks(out)
out =F.max_pool2d(out,2)
out = out.view(-1,8*8*self.n_chans1)
out = torch.relu(self.fc1(out))
out = self.fc2(out)
return out
更多推荐
所有评论(0)