笔记-b站刘二大人《pytorch深度学习实践》-第十一讲

目录

GoogleNet

Residual Learning 


GoogleNet

 

定义inception块,然后整合起来成Net模块:

 贴个代码:

import torch
from torch.utils.data import DataLoader
from torchvision import transforms   #针对图像进行处理的工具包
from torchvision import datasets
import torch.nn.functional as F  #for using ReLU

batch_size = 64

transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.1307,),(0.3081,))])

train_dataset = datasets.MNIST(root='../dataset/mnist',train=True,transform=transform,download=True)  #mnist为28*28大小的灰度图像
test_dataset = datasets.MNIST(root='../dataset/mnist',train=False,transform=transform,download=True)

train_loader = DataLoader(dataset=train_dataset,batch_size=batch_size,shuffle=True)   #打乱->shuffle=true,训练要打乱
test_loader = DataLoader(dataset=test_dataset,batch_size=batch_size,shuffle=False)    #测试不用shuffle,可以观察结果

class InceptionA(torch.nn.Module):
    def __init__(self,in_channels):   #初始输入通道,构造函数时作为参数,将来实例化时,可以指明输出通道数是多少
        super(InceptionA,self).__init__()
        self.branch_pool = torch.nn.AvgPool2d(kernel_size=3,padding=1,stride=1)
        self.branch1x1_1 = torch.nn.Conv2d(in_channels,24,kernel_size=1)

        self.branch1x1_2 = torch.nn.Conv2d(in_channels,16,kernel_size=1)

        self.branch5x5_1 = torch.nn.Conv2d(in_channels,16,kernel_size=1)
        self.branch5x5_2 = torch.nn.Conv2d(16,24,kernel_size=5,padding=2)  #保证输出的W,H不变

        self.branch3x3_1 = torch.nn.Conv2d(in_channels,16,kernel_size=1)
        self.branch3x3_2 = torch.nn.Conv2d(16,24,kernel_size=3,padding=1)  #保证输出的W,H不变
        self.branch3x3_3 = torch.nn.Conv2d(24,24,kernel_size=3,padding=1)  #保证输出的W,H不变

    def forward(self,x):
        branch_pool = self.branch_pool(self.branch1x1_1(x))  #pool分支

        branch1x1 = self.branch1x1_2(x)   #1x1分支

        branch5x5 = self.branch5x5_1(x)
        branch5x5 = self.branch5x5_2(branch5x5)   #5x5分支

        branch3x3 = self.branch3x3_1(x)
        branch3x3 = self.branch3x3_2(branch3x3)
        branch3x3 = self.branch3x3_3(branch3x3)   #3x3分支

        outputs = [branch_pool,branch1x1,branch5x5,branch3x3]   #四个分支放一个列表里
        return torch.cat(outputs,dim=1)  #沿着dimension的维度拼起来 (B,C,W,H) C为第一个维度

class Net(torch.nn.Module):
    def __init__(self, in_channels):
        super(Net, self).__init__()
        self.conv1 = torch.nn.Conv2d(1,10,kernel_size=5)  #输入数据是(B,1,28,28)
        self.conv2 = torch.nn.Conv2d(88,20,kernel_size=5) #输入数据是(B,88,12,12)

        self.incep1 = InceptionA(in_channels=10)  #输入通道数为10
        self.incep2 = InceptionA(in_channels=20)

        self.mp = torch.nn.MaxPool2d(kernel_size=2)
        self.fc = torch.nn.Linear(1408,10)


    def forward(self,x):
        in_size = x.size(0)  #获得batch_size
                                            #(b,10,24,24)->(b,10,12,12)->(b,10,12,12)
        x = F.relu(self.mp(self.conv1(x)))   #卷积-> 最大池化-> 激活
        x = self.incep1(x)   #W,H大小不变,通道数变化->(b,88,12,12)    88=24*3+16

                                            #(b,20,8,8)->(b,20,4,4)->(b,20,4,4)
        x = F.relu(self.mp(self.conv2(x)))   #卷积-> 最大池化-> 激活
        x = self.incep2(x)   #W,H大小不变,通道数变化->(b,88,4,4) 所以最终像素为88*4*4=1408个

        x = x.view(in_size,-1)  #flatten,展平-> 行,列
        x = self.fc(x)
        return x

model = Net(10)
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
#使用GPU,可以选,不同的任务使用不同的显卡,第一块:cuda:0,第二块:cuda:1,这取决于显卡的数量
model.to(device) #整个模型的缓存、模块都放到cuda中,转成cuda Tensor

criterion = torch.nn.CrossEntropyLoss()  #相当于size_average=True
optimizer = torch.optim.SGD(model.parameters(), lr=0.01,momentum=0.5)  #momentum为动量参数

def train(epoch):
    running_loss = 0.0
    for batch_idx,data in enumerate(train_loader,0): #(x,y)放到data中,dataloader自动将它们转成tensor  batch_idx相当于i
        # prepare data
        inputs, target = data  #x存到inputs中,y存到target中
        inputs, target = inputs.to(device),target.to(device)  #放到同一块显卡中
        optimizer.zero_grad()

        # forward+backward+update
        outputs = model(inputs)
        loss = criterion(outputs,target)
        loss.backward()
        optimizer.step()

        running_loss += loss.item()  #用item,不然会构建计算图  计算一个batch的损失
        if batch_idx % 300 ==299:
            print('[%d %5d] loss:%.3f' % (epoch+1,batch_idx+1,running_loss/300))
            running_loss = 0.0

def test():
    correct = 0
    total = 0
    with torch.no_grad():  #测试时不需要计算梯度
        for data in test_loader:
            images,target = data
            images, target = images.to(device), target.to(device)  # 放到同一块显卡中
            outputs = model(images)
            _,predicted = torch.max(outputs.data,dim=1)
            #torch.max()函数返回的是两个值,第一个值是具体的value,即输出的最大值(用下划线表示),第二个值是value所在的index(也就是predicted)
            #dim=1表示输出所在行的最大值,dim=0表示输出所在列的最大值
            total += target.size(0)   #求样本总数
            correct += (predicted==target).sum().item()  #.item()将tensor转化为普通的float或int型
    print('Accuracy on test set:%d %% [%d/%d]'%(100*correct/total,correct,total))  #%%表示文字%   后面的%表示传入数据

if __name__ =='__main__':
    for epoch in range(10):
        train(epoch)
        test()


输出结果:

 

Residual Learning 

 Residual Net 做了 F(x) + x 的操作,要求两个张量维度要一样,即通道、高度、宽度要一样。

下图中,红色的是residual block。

 

红色的里面是一个残差块,包含两个weight layer。第一个weight layer做conv1卷积,经过relu,送入第二个weight layer,在第二个weight layer做conv2卷积,输出与x相加,最后做relu。示意图及模块代码如下图。

 

定义了残差块,下面为整个残差网络的架构:

 完整代码:

import torch
from torch.utils.data import DataLoader
from torchvision import transforms   #针对图像进行处理的工具包
from torchvision import datasets
import torch.nn.functional as F  #for using ReLU

batch_size = 64
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.1307,),(0.3081,))])

train_dataset = datasets.MNIST(root='../dataset/mnist',train=True,transform=transform,download=True)  #mnist为28*28大小的灰度图像
test_dataset = datasets.MNIST(root='../dataset/mnist',train=False,transform=transform,download=True)

train_loader = DataLoader(dataset=train_dataset,batch_size=batch_size,shuffle=True)   #打乱->shuffle=true,训练要打乱
test_loader = DataLoader(dataset=test_dataset,batch_size=batch_size,shuffle=False)    #测试不用shuffle,可以观察结果

class ResidualBlock(torch.nn.Module):
    def __init__(self,channels):   #初始输入通道,构造函数时作为参数,将来实例化时,可以指明输出通道数是多少
        super(ResidualBlock,self).__init__()
        self.channels = channels
        self.conv1 = torch.nn.Conv2d(channels,channels,kernel_size=3,padding=1) #保证输入、输出通道一样,大小不变
        self.conv2 = torch.nn.Conv2d(channels, channels, kernel_size=3, padding=1)

    def forward(self,x):
        y = F.relu(self.conv1(x))  #卷积+激活
        y = self.conv2(y)          #卷积
        return F.relu(x+y)       #相加再激活

class Net(torch.nn.Module):  #如果网络结构复杂,可以用新的类去封装
    def __init__(self):    #定义需要调用的函数
        super(Net,self).__init__()
        self.conv1 = torch.nn.Conv2d(1,16,kernel_size=5)
        self.conv2 = torch.nn.Conv2d(16,32,kernel_size=5)
        self.mp = torch.nn.MaxPool2d(kernel_size=2)

        self.rblock1 = ResidualBlock(16)  #输入通道数为16
        self.rblock2 = ResidualBlock(32)

        self.fc = torch.nn.Linear(512,10)

    def forward(self,x):
        in_size = x.size(0)
        x = self.mp(F.relu(self.conv1(x)))
        x = self.rblock1(x)
        x = self.mp(F.relu(self.conv2(x)))
        x = self.rblock2(x)
        x = x.view(in_size,-1)
        x = self.fc(x)
        return x

model = Net()
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
#使用GPU,可以选,不同的任务使用不同的显卡,第一块:cuda:0,第二块:cuda:1,这取决于显卡的数量
model.to(device) #整个模型的缓存、模块都放到cuda中,转成cuda Tensor

criterion = torch.nn.CrossEntropyLoss()  #相当于size_average=True
optimizer = torch.optim.SGD(model.parameters(), lr=0.01,momentum=0.5)  #momentum为动量参数

def train(epoch):
    running_loss = 0.0
    for batch_idx,data in enumerate(train_loader,0): #(x,y)放到data中,dataloader自动将它们转成tensor  batch_idx相当于i
        # prepare data
        inputs, target = data  #x存到inputs中,y存到target中
        inputs, target = inputs.to(device),target.to(device)  #放到同一块显卡中
        optimizer.zero_grad()

        # forward+backward+update
        outputs = model(inputs)
        loss = criterion(outputs,target)
        loss.backward()
        optimizer.step()

        running_loss += loss.item()  #用item,不然会构建计算图  计算一个batch的损失
        if batch_idx % 300 ==299:
            print('[%d %5d] loss:%.3f' % (epoch+1,batch_idx+1,running_loss/300))
            running_loss = 0.0

def test():
    correct = 0
    total = 0
    with torch.no_grad():  #测试时不需要计算梯度
        for data in test_loader:
            images,target = data
            images, target = images.to(device), target.to(device)  # 放到同一块显卡中
            outputs = model(images)
            _,predicted = torch.max(outputs.data,dim=1)
            #torch.max()函数返回的是两个值,第一个值是具体的value,即输出的最大值(用下划线表示),第二个值是value所在的index(也就是predicted)
            #dim=1表示输出所在行的最大值,dim=0表示输出所在列的最大值
            total += target.size(0)   #求样本总数
            correct += (predicted==target).sum().item()  #.item()将tensor转化为普通的float或int型
    print('Accuracy on test set:%d %% [%d/%d]'%(100*correct/total,correct,total))  #%%表示文字%   后面的%表示传入数据

if __name__ =='__main__':
    for epoch in range(10):
        train(epoch)
        test()

输出结果:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值