pytorch 入门:模型集成,VGG16,循环神经网络基本结构,BPTT,Counter模块

模型集成提升性能

为了改善一项机器学习或深度学习的任务,首先想到的是从模型,数据,优化器等方面进行优化,但效果有时不大理想,这时可以尝试一下其他方法:比如模型集成,迁移学习,数据增强等优化方法。这里介绍利用模型集成来提升任务的性能。

集成学习是提升分类器或预测系统效果的重要方法。原理就是集合多个模型的效果,得到一个强于单个模型效果的模型。具体使用中还要考虑各个模型的差异性,如果各个模型性能差不多,可以取预测结果的平均值,如果性能差距较大,模型集成后的性能可能不如当个模型,相差较大时可以采用加权平均的方法,其中权重可以采用 SLSQP, Nelder-Mead, Powell, CG , BFGS 等优化算法获取。

敲代码

import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
import torch.backends.cudnn as cudnn
import numpy as np
import torchvision
import torchvision.transforms as transforms
from torch.utils.data import DataLoader
from collections import Counter

# 一些超参数
BATCHSIZE=100
DOWNLOAD_MNIST=False
EPOCHES=20
LR=0.001

# 这里使用三个网络
class CNNNet(nn.Module):
    def __init__(self):
        super(CNNNet,self).__init__()
        self.conv1 = nn.Conv2d(in_channels=3,out_channels=16,kernel_size=5,stride=1)
        self.pool1 = nn.MaxPool2d(kernel_size=2,stride=2)
        self.conv2 = nn.Conv2d(in_channels=16,out_channels=36,kernel_size=3,stride=1)
        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)
        self.fc1 = nn.Linear(1296,128)
        self.fc2 = nn.Linear(128,10)      

    def forward(self,x):
        x=self.pool1(F.relu(self.conv1(x)))
        x=self.pool2(F.relu(self.conv2(x)))
        #print(x.shape)
        x=x.view(-1,36*6*6)
        x=F.relu(self.fc2(F.relu(self.fc1(x))))
        return x

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, 5)
        self.pool1 = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(16, 36, 5)
        self.pool2 = nn.MaxPool2d(2, 2)
        self.aap=nn.AdaptiveAvgPool2d(1)   # 全局平均池化
        self.fc3 = nn.Linear(36, 10)

    def forward(self, x):
        x = self.pool1(F.relu(self.conv1(x)))
        x = self.pool2(F.relu(self.conv2(x)))
        x = self.aap(x)
        x = x.view(x.shape[0], -1)
        x = self.fc3(x)
        return x
    
class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1   = nn.Linear(16*5*5, 120)
        self.fc2   = nn.Linear(120, 84)
        self.fc3   = nn.Linear(84, 10)

    def forward(self, x):
        out = F.relu(self.conv1(x))
        out = F.max_pool2d(out, 2)
        out = F.relu(self.conv2(out))
        out = F.max_pool2d(out, 2)
        out = out.view(out.size(0), -1)
        out = F.relu(self.fc1(out))
        out = F.relu(self.fc2(out))
        out = self.fc3(out)
        return out

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

print('==> Preparing data..')
transform_train = transforms.Compose([
    transforms.RandomCrop(32, padding=4),
    transforms.RandomHorizontalFlip(),
    transforms.ToTensor(),
    transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
])

transform_test = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
])

trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=False, transform=transform_train)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=128, shuffle=True, num_workers=2)

testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=False, transform=transform_test)
testloader = torch.utils.data.DataLoader(testset, batch_size=100, shuffle=False, num_workers=2)

classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

print('==> Building model..')
net1 = CNNNet()
net2 = Net()
net3 = LeNet()

mlps=[net1.to(device),net2.to(device),net3.to(device)]
optimizer = optim.Adam([{'params':mlp.parameters()} for mlp in mlps],lr=LR)
loss_function=nn.CrossEntropyLoss()

for ep in range(EPOCHES):
    for img ,label in trainloader:
        img,label = img.to(device),label.to(device)
        optimizer.zero_grad()
        for mlp in mlps:
            mlp.train()
            out = mlp(img)
            loss = loss_function(out,label)
            loss.backward()
        optimizer.step()
    pre=[]
    vote_correct = 0
    mlps_correct=[0 for i in range(len(mlps))]
    for img ,label in testloader:
        img,label = img.to(device),label.to(device)
        for i,mlp in enumerate(mlps):
            mlp.eval()
            out = mlp(img)
            _, prediction = torch.max(out,1)
            pre_num = prediction.cpu().numpy()
            mlps_correct[i]+=(pre_num==label.cpu().numpy()).sum()
            pre.append(pre_num)
            
        arr = np.array(pre)
        pre.clear()
        result=[Counter(arr[:,i]).most_common(1)[0][0] for i in range(BATCHSIZE)]
        vote_correct+=(result == label.cpu().numpy()).sum()
    print("epoch:" + str(ep)+"集成模型的正确率"+str(vote_correct/len(testloader)))
 
    for idx, coreect in enumerate( mlps_correct):
        print("模型"+str(idx)+"的正确率为:"+str(coreect/len(testloader)))
'''
epoch:19集成模型的正确率69.57     循环次数高了以后精度可以达到 74%
模型0的正确率为:61.84
模型1的正确率为:60.24
模型2的正确率为:65.6
'''

使用现代经典网络模型提升性能

精度够不够很大程度与网络模型有关,这里使用经典的 VGG16 作为模型对数据进行分类,这个精度可以达到 90%,,就是训练的好慢啊。。


cfg = {   # 各层的输出通道。
    'VGG16': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'],
    'VGG19': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'],
}

class VGG(nn.Module):
    def __init__(self, vgg_name):
        super(VGG, self).__init__()
        self.features = self._make_layers(cfg[vgg_name])
        self.classifier = nn.Linear(512, 10)

    def forward(self, x):
        out = self.features(x)
        out = out.view(out.size(0), -1)
        out = self.classifier(out)
        return out

    def _make_layers(self, cfg):
        layers = []
        in_channels = 3
        for x in cfg:
            if x == 'M':
                layers += [nn.MaxPool2d(kernel_size=2, stride=2)]
            else:
                layers += [nn.Conv2d(in_channels, x, kernel_size=3, padding=1),
                           nn.BatchNorm2d(x),
                           nn.ReLU(inplace=True)]
                in_channels = x
        layers += [nn.AvgPool2d(kernel_size=1, stride=1)]
        return nn.Sequential(*layers)
        
net4 = VGG('VGG16')

mlps=[net4.to(device)]    # 使用 VGG16

optimizer=torch.optim.Adam([{"params":mlp.parameters()} for mlp in mlps],lr=LR)
  
loss_function=nn.CrossEntropyLoss()
 
for ep in range(EPOCHES):
    for img,label in trainloader:
        img,label=img.to(device),label.to(device)
        optimizer.zero_grad()#10个网络清除梯度
        for mlp in mlps:
            mlp.train()
            out=mlp(img)
            loss=loss_function(out,label)
            loss.backward()#网络们获得梯度
        optimizer.step()
 
    pre=[]
    vote_correct=0
    mlps_correct=[0 for i in range(len(mlps))]
    for img,label in testloader:
        img,label=img.to(device),label.to(device)
        for i, mlp in  enumerate( mlps):
            mlp.eval()
            out=mlp(img)
 
            _,prediction=torch.max(out,1) #按行取最大值
            pre_num=prediction.cpu().numpy()
            mlps_correct[i]+=(pre_num==label.cpu().numpy()).sum()
 
            pre.append(pre_num)
        arr=np.array(pre)
        pre.clear()
        result=[Counter(arr[:,i]).most_common(1)[0][0] for i in range(BATCHSIZE)]
        vote_correct+=(result == label.cpu().numpy()).sum()
    #print("epoch:" + str(ep)+"集成模型的正确率"+str(vote_correct/len(testloader)))
 
    for idx, coreect in enumerate( mlps_correct):
        print("VGG16模型迭代"+str(ep)+"次的正确率为:"+str(coreect/len(testloader)))

自然语言处理基础

之间视觉处理中的卷积神经网络利用卷积核的方式来共享参数,使得参数量大大降低的同时还可以利用位置信息,但是其输入大小时固定的。但是对于语言处理,语音识别等方面,每句话的长度是不一样的,且一句话的前后是有关系的,里斯这样的数据还有语音数据,翻译的语句等,这样有先后顺序的数据称为序列数据。

对于序列数据可用使用循环神经网络(RNN),就很适合处理序列数据,RNN 已经成功用于自然语言处理,语音识别,图片标注,机器翻译等时序问题了。

循环神经网络基本结构

在这里插入图片描述

输入层,隐藏层,输出层还有 循环层。将神经元之间相互关联。U,V,权重矩阵,W 是状态到隐含层的权重矩阵,s 为状态, 这就是一个经典的Elman循环神经网络,其中w , u ,v 共享参数保存不变,再细化隐藏层:
在这里插入图片描述
加速输入 x 为 n 维向量,隐含层神经元有 m 个,输出层神经元有 r 个,则U 的大小维 n * m 维,W 是上一次的 a^t-1 为 这一次输入的权重矩阵,大小为 M * M ,V 是输出层矩阵,大小 M *r维。

  • xt 是时刻 t 的输入
  • at 是时刻 t 的隐层状态,是网络的记忆,基于前一次时刻的隐层状态和当前时刻的输入进行计算。即at=f(Uxt+Wa^t-1),计划函数一般是非线性,一般 a 初始化为 0 .
  • ot 是时刻 t 的输出,例如想预测句子的下一个词,将会是一个词汇表中的概率向量 ot=softmax(V at)
  • at 是网络的记忆状态,可用捕获之前所有时刻发生的信息,输出的 ot 仅仅依赖于时刻 t 的记忆。

网络的每一步不一定要有输出,比如预测一个句子的情感时,可能仅关注最后的输出,而不是每个词的情感。而且不一定每一步都需要输入。循环神经网络最大的特点就是隐层状态,可以捕获一个序列的一些信息。

循环神经网络可以像卷积神经网络一样,除了可以横向扩展(增加时间长度或序列长度)也可以纵向扩展成多层循环神经网络。

在这里插入图片描述

前向传播与随时间反向传播

RNN 参数更新的基本思路一样
在这里插入图片描述
在这里插入图片描述
矩阵表示:
在这里插入图片描述

import numpy as np

X = [1,2]
state = [0.0, 0.0]     # 初始状态
w_cell_state = np.asarray([[0.1, 0.2], [0.3, 0.4],[0.5, 0.6]])
b_cell = np.asarray([0.1, -0.1])
w_output = np.asarray([[1.0], [2.0]])   # 权重矩阵
b_output = 0.1

for i in range(len(X)):
    state=np.append(state,X[i])    # 转成矩阵操作
    before_activation = np.dot(state, w_cell_state) + b_cell
    state = np.tanh(before_activation)
    final_output = np.dot(state, w_output) + b_output
    print("状态值_%i: "%i, state)
    print("输出值_%i: "%i, final_output)

>>>
状态值_0:  [0.53704957 0.46211716]
输出值_0:  [1.56128388]
状态值_1:  [0.85973818 0.88366641]
输出值_1:  [2.72707101]

循环神经网络的反向传播训练算法称为随时间反向传播(BPTT)算法,基本原理和反向传播算法一样,只是BP 时按照层进行反向, BPTT 是按照时间 t 进行反向。

在这里插入图片描述
其中 L 为输入对应的代价函数,L() 为总的代价函数
在这里插入图片描述

Counter 模块

文档,一个计数器工具提供快速方便的计数

是字典的子类,元素是字典的键,值是计数的值。没有记录就是0 .

>>> c=Counter('qiangqiang')
>>> c
Counter({'q': 2, 'i': 2, 'a': 2, 'n': 2, 'g': 2})
>>> c=Counter({'q':2,'b':4})
>>> c
Counter({'b': 4, 'q': 2})
>>> c['c']
0
>>> c
Counter({'b': 4, 'q': 2})
>>> sorted(c.elements())    # 返回一个迭代器
['b', 'b', 'b', 'b', 'q', 'q']

>>> c = Counter(a=4, b=2, c=0, d=-2)
>>> d = Counter(a=1, b=2, c=3, d=4)
>>> c.subtract(d)           # 减法
>>> c
Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})

>>> Counter('abracadabra').most_common(3)  # 排序后选出最高的 n 个
[('a', 5), ('b', 2), ('r', 2)]

# 常用案例
sum(c.values())                 # total of all counts
c.clear()                       # reset all counts
list(c)                         # list unique elements
set(c)                          # convert to a set
dict(c)                         # convert to a regular dictionary
c.items()                       # convert to a list of (elem, cnt) pairs
Counter(dict(list_of_pairs))    # convert from a list of (elem, cnt) pairs
c.most_common()[:-n-1:-1]       # n least common elements
+c                              # remove zero and negative counts
  • 0
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值