【Deep Learning 6】CNN卷积神经网络

本文涉及的产品
实时数仓Hologres,5000CU*H 100GB 3个月
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
简介: 🍊文本从小女孩图片检测开始引入CNN,将其与FNN进行对比,并对CNN的原理和流程进行了详细的介绍。最后使用CNN在计算机视觉和自然语言处理领域进行实验实战🍊实验一:模拟CNN,并观察其输入、卷积层、输出的维度情况🍊实验二:使用CNN对经典Mnist手写数字图像数据集进行图像分类检测。

image.gif编辑

🍊文本从如何识别出图片中的小女孩引入CNN,将其与FNN进行对比,并对CNN网络模型进行了详细的介绍。最后在自然语言处理和视觉领域进行实战。具体来说,使用CNN组合的四个经典模型对Mnist数据集进行图像分类,使用TextCNN对IMDB数据集进行文本分类

🍊实验一:模拟CNN,并观察其输入、卷积层、输出的维度情况

🍊实验二:图像分类--LeNet-5模型

🍊实验三:图像分类--AlexNet模型(改编版)

🍊实验四:图像分类--VGG16模型

🍊实验五:图像分类--GoogleNet模型

🍊实验六:文本分类--TextCNN模型

一、Introduction

假如有这样一张图片,我们是如何检测出图片中的小女孩呢?我们可以将图片分割成一个个小部分,对每个小部分来检测嘴巴、鼻子、眼睛,最后进行总体的判断。如此图像检测的流程就是CNN

image.gif编辑

在介绍CNN之前,我们先来看FNN有什么缺点。

缺点一:参数太多,因为FNN是全连接的,它的权重参数需要训练的数量是非常大的,比如有一个图像的尺寸是128*128*3,那么每一次层的神经元和权重参数就有128*128*3个,如此巨大的参数在实际训练过程中效率非常低下。

缺点二:局部不变性,FNN如果不进行数据增强的话是很那提取到对象的关键信息

而CNN的产生就是为了解决以上的两个问题,即权重比较少的FNN。

image.gif编辑

二、Convolutional Layer

如何判断一个网络层是CNN呢?如果一个网络层对输入使用了Receptive FieldParameters Sharing,那么这样的神经网络的架构就是CNN

image.gif编辑

我们拿一张图片的简化来举例子,首先神经网络的输入一定是一个向量,但是图片是一个三维(length、width、RGB)的Tensor矩阵,因此我们需要将此Tensor转化为100*100*3的向量。这么大的向量如果输入到模型中其权重w也非常大,因此我们需要对其进行简化

2.1 Receptive field

假如有一张图片,我们如何判断里面是否有小鸟,我们实际上不需要知道整张图片的细节,只需要知道关键的区分点,即特征

image.gif编辑

因此,我们可以将原始图片即一个大的三维Tensor分割成一个个小的三维Tensor,这里每个Tensor就是一个Receptive field(也被称作卷积核kernels)

随后将每个Receptive field放到一个单独的网络层中

image.gif编辑

因为一张图片中的任何位置都有可能有我们想要检测的目标,因此Receptive field需要覆盖整张图片,因此我们需要设置一个超参数stride步幅来控制覆盖图片的速度

在覆盖过程中,可能遇到一些边边角角难以适配(与stride超参数有关),那么我们可以覆盖上,超出的部分使用padding补齐,一般使用0或整张图片的平均值来补齐。此外,还有很多时候我们想用padding是因为想将图像变大

image.gif编辑

2.2 Parameters sharing

如果我们只想检测喙,我们需要使用receptive field覆盖整张图片来搜索检测,每个receptive field都有检测喙功能的neurons。

image.gif编辑

因为它们的主要功能就是检测喙,只是检测的图像区域不一样罢了,因此我们可以进行优化,即权重共享参数。如此可以共享权重的神经元就叫做filter

image.gif编辑

2.3 Pooling

还有一个简化的方法就是对图片进行压缩,比如说删除掉图片长度为奇数,RGB中的red,虽然图像的画质降低了,但是总体上我们还是能识别该图像。这就是Pooling技术。

但是如今不怎么使用了,虽然Pooling在一定程度上可以获取重要信息而舍去边缘信息,从而减少计算开销,但是Pooling同时是以牺牲精度为代价来提高训练速度,现在机器的算力如此强悍,这点训练时间不算什么

将一个Tensor分割成很多小Tensor,每个小Tensor取一个值来合并成一个大Tensor,取值主要有三种方法

Mean-Pooling 取平均值
Max-Pooling 取最大值
Stochastic-pooling 轮盘法取值

MaxPooling技术

image.gif编辑

2.4 Convolution Algorithm

在CNN中有一个独特的计算方式叫做卷积计算,其符号的表示和乘法一样都是*,其计算过程如下图中,橙色图为待计算初始图,我们选中一个Receptive field,绿色图为一个filter。

2*1+3*0+2*(-1)+1*1+0*0+3*(-1)+1*1+2*0+3*(-1)=-4

image.gif编辑

随后对其他图也进行卷积计算,最终一个channel计算的结果如下,将所有channels相加起来就是最终的输出

image.gif编辑

如果你的数学敏感性比较高,可以发现

1 若没有进行padding操作,卷积后的Tensor的尺寸=原图尺寸-Filter尺寸+1

2 卷积核的有多少个,输出Tensor的channels就有多少层

最后,再放上一张卷积计算的总过程

image.gif编辑

image.gif编辑

2.5 Calculation skill

在学CNN的时候大家最烦的莫过于图像尺寸的变化,Padding、Kernal、Stride到底怎么计算?其实这样是有一个计算公式的如下

image.gif编辑

N:输出大小

W:输入图片大小

F:kernel大小

S:步长

P:补缺数量

2.6 Total flow

       1 根据对象特征设计好一个个Filter

       2 在图片中取出一个个Receptive Field数据,将与Filter进行卷积运算,得到一个具体的数值,将这些数值组合起来形成一个二维Tensor

       3 将2得到的2维Tensor结合起来得到一个高维的Tensor,称之为Feature Map

       4 使用Pooling技术将Tensor压缩(经典做法为其进入几个卷积层之后做一次Pooling)

       5 到这里卷积结束了,但是它是无法直接连接Dense全连接层的,需要将Convolution层的数据压平Flatten为一维数据

       6 最后放到一个FNN中进行分类预测

image.gif编辑

2.7 GoogleNet

我们先看看整个整个网络模型的架构

image.gif编辑

咋一看是不是感觉头皮发麻,怎么这个网络模型这么复杂,但是仔细看看会发现可以将其分成许多小模块,这些小模块很多都是重复的,如下图中所示

这个可复用的小模块称之为Inceptioin

image.gif编辑

那为什么要设计这样Inception呢?

我们在设计CNN网络模型的时候,卷积核的参数、卷积层的个数等超参数都难以确定,Inception就是为了解决这个问题。具体的做法的思想是我们不知道哪种CNN比较好,就设计四个如下图的CNN模型,都放进Inception中,哪个效果最好哪个权重就比较高。

作者感觉这与集成学习中的软投票做法一致

image.gif编辑

使用四个模型计算出了四个Tensor后,还需要使用Concatenate方法将其拼接在一起,实践操作就是使用cat函数

Inception中有一个非常有意思的东西就是1*1 Conv,它计算的过程如下

image.gif编辑

是不是感觉像一个美颜滤镜,对每个图层进行美化,最后合并成一个图层?是的,它的作用是直接压缩Tensor的Channels

2.8 TextCNN

CNN一般都是用于CV领域中,而深度学习中主流研究对象还有NLP,那CNN可以用在NLP中吗?当然可以,直观的讲,CNN就是一个滑窗,图像是一个矩形,所以滑窗也是个矩形,而文本是一个向量,因此滑窗就是个向量。

早在2014年就有人提出了TextCNN,其模型如下

image.gif编辑

欸,看起来可能有点抽象,看另一篇解释该模型的图可能好理解多了

image.gif编辑

    • 首先原句与卷积核分别为[2,768]、[3,768]、[4,768]且channels为2的filtet进行卷积运算得到6个一维向量
    • 随后将每个一维向量中取出最大值,将这6个最大值拼接成[6,2]的Tensor
    • 最后进行常规的分类预测

    三、Experiment

    3.1 实验一:模拟CNN观察各网络层尺寸

    题目:自定义输入图片尺寸,卷积核数量,观察CNN输入、卷积层、输出的各个尺寸分别为多少?

    import torch
    in_channel, out_channel = 5, 10  # 输入输出的channel
    width, height = 100, 100  # 一张照片的长宽
    kernel_size = 3  # 卷积核的数量
    batch_size = 1  # 当前训练的batch序号
    input = torch.randn(batch_size, in_channel, width, height)  # 假设有一张照片输入进来
    conv_layer = torch.nn.Conv2d(in_channel, out_channel, kernel_size=kernel_size)  # 定义卷积层
    output = conv_layer(input)
    print(input.shape)
    print(output.shape)
    print(conv_layer.weight.shape)

    image.gif

    Result

    image.gif编辑

    1 输入的channel为5,输出的channel为10,而卷积层的卷积核的channel为5,一共有10个

    2 该CNN没有Padding操作,输出尺寸98=输入尺寸100-filter尺寸3+1

    3.2 Mnist数据集

    数据集我们是使用torchvision,torchvision是专门服务于Pytorch的图形库

    torchvision.datasets:加载图形数据集

    tramsforms.Compose:各类图片变换,如裁剪,旋转,标准化。按照左到右顺序进行转换

    transforms.ToTensor:转换一张图片或Numpy数组为Tensor张量类型

    transforms.Normalize:使用平均值和标准误差来标准化图片,其中0.1307和0.3081超参数是官方提供的

    MNIST数据集是手写数字的图片, 通过以下代码测试,我们可以发现该数据集的训练集一共有60k条,测试集有10k条,每条数据由28*28的图片构成

    print('test_loader.dataset',test_loader.dataset)
        print('train_loader.dataset',train_loader.dataset)
        imgs,_=next(iter(test_loader))
        print(imgs.shape)

    image.gif

    image.gif编辑

    3.3 实验二:LeNet-5 模型

    实验二:构建LeNet-5模型对经典手写数字Mnist数据集进行分类识别

    神经网络架构图

    image.gif编辑

    Code

    import torch
    from torch import nn
    from torchvision import transforms
    from torchvision import datasets
    from torch.utils.data import DataLoader
    import torch.nn.functional as F
    import torch.optim as optim
    import matplotlib.pyplot as plt
    # Prepare for the datasets
    batch_size = 64
    EPOCH = 100
    transform = transforms.Compose(
        [transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])  # Transform picture to tensor
    train_dataset = datasets.MNIST(root='../dataset/mnist/', train=True, download=True, transform=transform)
    train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
    test_dataset = datasets.MNIST(root='../dataset/mnist/', train=False, download=True, transform=transform)
    test_loader = DataLoader(test_dataset, shuffle=False, batch_size=batch_size)
    class LeNet(torch.nn.Module):
        def __init__(self):
            super(LeNet,self).__init__()
            self.conv=nn.Sequential(
                nn.Conv2d(1,6,5),
                nn.Sigmoid(),
                nn.MaxPool2d(2,2),
                nn.Conv2d(6,16,5),
                nn.Sigmoid(),
                nn.MaxPool2d(2,2)
            )
            self.fc=nn.Sequential(
                nn.Linear(16*4*4,120),
                nn.Sigmoid(),
                nn.Linear(120,84),
                nn.Sigmoid(),
                nn.Linear(84,10)
            )
        def forward(self,x):
            batch_size=x.size(0)# Get the batch_size
            x=self.conv(x)
            x=x.view(batch_size, -1)
            x=self.fc(x)
            return x
    model = LeNet()
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    model.to(device)
    # Define criterion and optimizer
    criterion = torch.nn.CrossEntropyLoss()
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)  # momentum是动量,主要解决初始化数值特殊陷入局部最优问题
    def train(epoch):
        running_loss = 0.0
        for batch_index, data in enumerate(train_loader, 0):
            inputs, labels = data
            inputs, labels = inputs.to(device), labels.to(device)
            outputs = model(inputs)
            loss = criterion(outputs, labels)
            running_loss += loss.item()
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            if batch_index % 200 == 199:
                print('Epoch:[%d/%d] batch_index: %d loss: %.6f' % (epoch + 1, EPOCH, batch_index + 1, running_loss / 300))
                running_loss = 0.0
    def test():
        correct = 0
        total = 0
        with torch.no_grad():
            for data in test_loader:
                images, labels = data
                images, labels = images.to(device), labels.to(device)
                outputs = model(images)  # outputs.shape=[64,10]
                _, predicted = torch.max(outputs.data, dim=1)  # predicted.shape=[64]
                total += labels.size(0)  # Add every batch.size
                correct += (predicted == labels).sum().item()
        print('accuracy on test set: %.6f %% ' % (100 * correct / total))
        return correct / total
    if __name__ == '__main__':
        epoch_list = []
        acc_list = []
        for epoch in range(EPOCH):
            train(epoch)
            acc = test()
            epoch_list.append(epoch)
            acc_list.append(acc)
        plt.plot(epoch_list, acc_list)
        plt.ylabel('accuracy')
        plt.xlabel('epoch')
        plt.show()

    image.gif

    Result

    image.gif编辑

    image.gif编辑

    最终准确率在98%左右

    3.4 实验三:AlexNet 模型(改编版)

    实验三:构建AlexN模型改编版对经典手写数字Mnist数据集进行分类识别

    神经网络架构图

    我们使用了3个CNN,将其串行连接,随后将其Flatten成一维向量,放入到两个FNN中进行下游分类任务

    这里的两个FNN都没有加激活函数,大家可能会对此感到疑惑,其实这主要是因为该数据集和网络模型过于简单,更符合于线性规则

    image.gif编辑

    代码

    import torch
    from torchvision import transforms
    from torchvision import datasets
    from torch.utils.data import DataLoader
    import torch.nn.functional as F
    import torch.optim as optim
    import matplotlib.pyplot as plt
    # Prepare for the datasets
    batch_size = 64
    EPOCH = 10
    transform = transforms.Compose(
        [transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])  # Transform picture to tensor
    train_dataset = datasets.MNIST(root='../dataset/mnist/', train=True, download=True, transform=transform)
    train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
    test_dataset = datasets.MNIST(root='../dataset/mnist/', train=False, download=True, transform=transform)
    test_loader = DataLoader(test_dataset, shuffle=False, batch_size=batch_size)
    # Define the CNN_model
    class CNN_Net(torch.nn.Module):
        def __init__(self):
            super(CNN_Net, self).__init__()
            self.conv1 = torch.nn.Conv2d(1, 10, kernel_size=5)
            self.conv2 = torch.nn.Conv2d(10, 20, kernel_size=3)
            self.conv3 = torch.nn.Conv2d(20, 40, kernel_size=2)
            self.pooling = torch.nn.MaxPool2d(2)
            self.fc1 = torch.nn.Linear(640, 160)
            self.fc2 = torch.nn.Linear(160, 10)
        def forward(self, x):
            batch_size = x.size(0)
            x = F.relu(self.pooling(self.conv1(x)))  # conv1+pooling
            x = F.relu(self.pooling(self.conv2(x)))  # conv2+pooling
            x = F.relu(self.conv3(x))
            x = x.view(batch_size, -1)  # flatten
            x = self.fc1(x)  # FNN
            x = self.fc2(x)
            return x
    model = CNN_Net()
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    model.to(device)
    # Define criterion and optimizer
    criterion = torch.nn.CrossEntropyLoss()
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)  # momentum是动量,主要解决初始化数值特殊陷入局部最优问题
    def train(epoch):
        running_loss = 0.0
        for batch_index, data in enumerate(train_loader, 0):
            inputs, labels = data
            inputs, labels = inputs.to(device), labels.to(device)
            outputs = model(inputs)
            loss = criterion(outputs, labels)
            running_loss += loss.item()
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            if batch_index % 200 == 199:
                print('Epoch:[%d/%d] batch_index: %d loss: %.6f' % (epoch + 1,EPOCH, batch_index + 1, running_loss / 300))
                running_loss = 0.0
    def test():
        correct = 0
        total = 0
        with torch.no_grad():
            for data in test_loader:
                images, labels = data
                images, labels = images.to(device), labels.to(device)
                outputs = model(images)  # outputs.shape=[64,10]
                _, predicted = torch.max(outputs.data, dim=1)  # predicted.shape=[64]
                total += labels.size(0)  # Add every batch.size
                correct += (predicted == labels).sum().item()
        print('accuracy on test set: %.6f %% ' % (100 * correct / total))
        return correct / total
    if __name__ == '__main__':
        epoch_list = []
        acc_list = []
        for epoch in range(EPOCH):
            train(epoch)
            acc = test()
            epoch_list.append(epoch)
            acc_list.append(acc)
        plt.plot(epoch_list, acc_list)
        plt.ylabel('accuracy')
        plt.xlabel('epoch')
        plt.show()

    image.gif

    Result

    image.gif编辑

    image.gif编辑

    可以看到随着训练的进行,该网络模型准确率上升,最终达到了99.12%

    3.5 实验四:VGG16模型

    题目:构建GoogleNet模型来对Mnist模型进行分类预测

    首先看看VGG16的原始模型长啥样

    image.gif编辑

    其实也非常简单,只用(2,2)或(3,3)卷积核的卷积层和Pool(2,2)的池化层进行拼接

    但是由于我们的图像是28*28的,因此我对原始模型进行了部分的小改

    首先将28*28的图像扩展为64*64的,28*28实在玩不动这么多卷积的网络模型!

    网络架构图

    import torch
    from torchvision import transforms
    from torchvision import datasets
    from torch.utils.data import DataLoader
    import torch.nn.functional as F
    import torch.optim as optim
    import matplotlib.pyplot as plt
    # Prepare for the datasets
    batch_size = 64
    EPOCH = 10
    transform_VGG16 = transforms.Compose([transforms.Resize([64, 64]),
                                            transforms.ToTensor()])
    train_dataset = datasets.MNIST(root='../dataset/mnist/', train=True, download=True, transform=transform_VGG16)
    train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
    test_dataset = datasets.MNIST(root='../dataset/mnist/', train=False, download=True, transform=transform_VGG16)
    test_loader = DataLoader(test_dataset, shuffle=False, batch_size=batch_size)
    # Define the CNN_model
    class VGG16(torch.nn.Module):
        def __init__(self):
            super(VGG16, self).__init__()
            self.block1 = nn.Sequential(
                nn.Conv2d(1, 64, 3, 1, 1),
                nn.ReLU(),
                nn.Conv2d(64, 64, 3, 1, 1),
                nn.ReLU(),
                nn.MaxPool2d(2, 2)
            )
            self.block2 = nn.Sequential(
                nn.Conv2d(64, 128, 3, 1, 1),
                nn.ReLU(),
                nn.Conv2d(128, 128, 3, 1, 1),
                nn.ReLU(),
                nn.MaxPool2d(2, 2)
            )
            self.block3 = nn.Sequential(
                nn.Conv2d(128, 256, 3, 1, 1),
                nn.ReLU(),
                nn.Conv2d(256, 256, 3, 1, 1),
                nn.ReLU(),
                nn.Conv2d(256, 256, 3, 1, 1),
                nn.ReLU(),
                nn.MaxPool2d(2, 2)
            )
            self.block4 = nn.Sequential(
                nn.Conv2d(256, 512, 3, 1, 1),
                nn.ReLU(),
                nn.Conv2d(512, 512, 3, 1, 1),
                nn.ReLU(),
                nn.Conv2d(512, 512, 3, 1, 1),
                nn.ReLU(),
                nn.MaxPool2d(2, 2)
            )
            self.block5 = nn.Sequential(
                nn.Conv2d(512, 512, 3, 1, 1),
                nn.ReLU(),
                nn.Conv2d(512, 512, 3, 1, 1),
                nn.ReLU(),
                nn.Conv2d(512, 512, 3, 1, 1),
                nn.ReLU(),
                nn.MaxPool2d(2, 2)
            )
            self.fnn = nn.Sequential(
                nn.Linear(2 * 2 * 512, 512),
                nn.ReLU(),
                nn.Linear(512, 512),
                nn.ReLU(),
                nn.Linear(512, 256),
                nn.ReLU(),
                nn.Linear(256, 10)
            )
        def forward(self, x):
            batch_size = x.size(0)
            x = self.block1(x)
            x = self.block2(x)
            x = self.block3(x)
            x = self.block4(x)
            x = self.block5(x)
            x = x.view(batch_size, -1)
            x = self.fnn(x)
            return x
    model = VGG16()
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    model.to(device)
    # Define criterion and optimizer
    criterion = torch.nn.CrossEntropyLoss()
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)  # momentum是动量,主要解决初始化数值特殊陷入局部最优问题
    def train(epoch):
        running_loss = 0.0
        for batch_index, data in enumerate(train_loader, 0):
            inputs, labels = data
            inputs, labels = inputs.to(device), labels.to(device)
            outputs = model(inputs)
            loss = criterion(outputs, labels)
            running_loss += loss.item()
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            if batch_index % 200 == 199:
                print('Epoch:[%d/%d] batch_index: %d loss: %.6f' % (epoch + 1,EPOCH, batch_index + 1, running_loss / 300))
                running_loss = 0.0
    def test():
        correct = 0
        total = 0
        with torch.no_grad():
            for data in test_loader:
                images, labels = data
                images, labels = images.to(device), labels.to(device)
                outputs = model(images)  # outputs.shape=[64,10]
                _, predicted = torch.max(outputs.data, dim=1)  # predicted.shape=[64]
                total += labels.size(0)  # Add every batch.size
                correct += (predicted == labels).sum().item()
        print('accuracy on test set: %.6f %% ' % (100 * correct / total))
        return correct / total
    if __name__ == '__main__':
        epoch_list = []
        acc_list = []
        for epoch in range(EPOCH):
            train(epoch)
            acc = test()
            epoch_list.append(epoch)
            acc_list.append(acc)
        plt.plot(epoch_list, acc_list)
        plt.ylabel('accuracy')
        plt.xlabel('epoch')
        plt.show()

    image.gif

    image.gif编辑

    image.gif编辑

    最终的准确率也是在99%左右

    3.6 实验五:GoogleNet模型

    题目:构建GoogleNet模型来对Mnist模型进行分类预测

    import torch
    from torch import nn
    from torchvision import transforms
    from torchvision import datasets
    from torch.utils.data import DataLoader
    import torch.nn.functional as F
    import torch.optim as optim
    import matplotlib.pyplot as plt
    # Prepare for the datasets
    batch_size = 64
    EPOCH = 30
    transform = transforms.Compose(
        [transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])  # Transform picture to tensor
    train_dataset = datasets.MNIST(root='../dataset/mnist/', train=True, download=True, transform=transform)
    train_loader = DataLoader(train_dataset, shuffle=True, batch_size=batch_size)
    test_dataset = datasets.MNIST(root='../dataset/mnist/', train=False, download=True, transform=transform)
    test_loader = DataLoader(test_dataset, shuffle=False, batch_size=batch_size)
    # GoogleNet_Inception
    class InceptionA(nn.Module):
        def __init__(self, in_channels):
            super(InceptionA, self).__init__()
            self.branch1x1 = nn.Conv2d(in_channels, 16, kernel_size=1)
            self.branch5x5_1 = nn.Conv2d(in_channels, 16, kernel_size=1)
            self.branch5x5_2 = nn.Conv2d(16, 24, kernel_size=5, padding=2)
            self.branch3x3_1 = nn.Conv2d(in_channels, 16, kernel_size=1)
            self.branch3x3_2 = nn.Conv2d(16, 24, kernel_size=3, padding=1)
            self.branch3x3_3 = nn.Conv2d(24, 24, kernel_size=3, padding=1)
            self.branch_pool = nn.Conv2d(in_channels, 24, kernel_size=1)
        def forward(self, x):
            branch1x1 = self.branch1x1(x)
            branch5x5 = self.branch5x5_1(x)
            branch5x5 = self.branch5x5_2(branch5x5)
            branch3x3 = self.branch3x3_1(x)
            branch3x3 = self.branch3x3_2(branch3x3)
            branch3x3 = self.branch3x3_3(branch3x3)
            branch_pool = F.avg_pool2d(x, kernel_size=3, stride=1, padding=1)
            branch_pool = self.branch_pool(branch_pool)
            outputs = [branch1x1, branch5x5, branch3x3, branch_pool]
            return torch.cat(outputs, dim=1)  # b,c,w,h  c对应的是dim=1
    class GoogleNet(nn.Module):
        def __init__(self):
            super(GoogleNet, self).__init__()
            self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
            self.conv2 = nn.Conv2d(88, 20, kernel_size=5)  # 88 = 24x3 + 16
            self.incep1 = InceptionA(in_channels=10)  # 与conv1 中的10对应
            self.incep2 = InceptionA(in_channels=20)  # 与conv2 中的20对应
            self.mp = nn.MaxPool2d(2)
            self.fc = nn.Linear(1408, 10)
        def forward(self, x):
            in_size = x.size(0)
            x = F.relu(self.mp(self.conv1(x)))
            x = self.incep1(x)
            x = F.relu(self.mp(self.conv2(x)))
            x = self.incep2(x)
            x = x.view(in_size, -1)
            x = self.fc(x)
            return x
    model = GoogleNet()
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    model.to(device)
    # Define criterion and optimizer
    criterion = torch.nn.CrossEntropyLoss()
    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)  # momentum是动量,主要解决初始化数值特殊陷入局部最优问题
    def train(epoch):
        running_loss = 0.0
        for batch_index, data in enumerate(train_loader, 0):
            inputs, labels = data
            inputs, labels = inputs.to(device), labels.to(device)
            outputs = model(inputs)
            loss = criterion(outputs, labels)
            running_loss += loss.item()
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            if batch_index % 200 == 199:
                print('Epoch:[%d/%d] batch_index: %d loss: %.6f' % (epoch + 1, EPOCH, batch_index + 1, running_loss / 300))
                running_loss = 0.0
    def test():
        correct = 0
        total = 0
        with torch.no_grad():
            for data in test_loader:
                images, labels = data
                images, labels = images.to(device), labels.to(device)
                outputs = model(images)  # outputs.shape=[64,10]
                _, predicted = torch.max(outputs.data, dim=1)  # predicted.shape=[64]
                total += labels.size(0)  # Add every batch.size
                correct += (predicted == labels).sum().item()
        print('accuracy on test set: %.6f %% ' % (100 * correct / total))
        return correct / total
    if __name__ == '__main__':
        epoch_list = []
        acc_list = []
        for epoch in range(EPOCH):
            train(epoch)
            acc = test()
            epoch_list.append(epoch)
            acc_list.append(acc)
        plt.plot(epoch_list, acc_list)
        plt.ylabel('accuracy')
        plt.xlabel('epoch')
        plt.show()

    image.gif

    Result

    image.gif编辑

    image.gif编辑

    最终的准确率也在99%左右

    3.7 实验六:TextCnn

    题目:使用Bert+TextCNN对IMDB进行文本情感分析

    该题的完整工程代码可参考这篇文章,在本节中只描述TextCNN代码模块

    class TextCNN_Model(nn.Module):
        def __init__(self, base_model, num_classes):
            super().__init__()
            self.base_model = base_model
            self.num_classes = num_classes
            for param in base_model.parameters():
                param.requires_grad = (True)
            # Define the hyperparameters
            self.filter_sizes = [2, 3, 4]
            self.num_filters = 2
            self.encode_layer = 12
            # TextCNN
            self.convs = nn.ModuleList(
                [nn.Conv2d(in_channels=1, out_channels=self.num_filters,
                           kernel_size=(K, self.base_model.config.hidden_size)) for K in self.filter_sizes]
            )
            self.block = nn.Sequential(
                nn.Dropout(0.5),
                nn.Linear(self.num_filters * len(self.filter_sizes), self.num_classes),
                nn.Softmax(dim=1)
            )
        def conv_pool(self, tokens, conv):
            tokens = conv(tokens)
            tokens = F.relu(tokens)
            tokens = tokens.squeeze(3)
            tokens = F.max_pool1d(tokens, tokens.size(2))
            out = tokens.squeeze(2)
            return out
        def forward(self, inputs):
            raw_outputs = self.base_model(**inputs)
            tokens = raw_outputs.last_hidden_state.unsqueeze(1)
            out = torch.cat([self.conv_pool(tokens, conv) for conv in self.convs],
                            1)
            predicts = self.block(out)
            return predicts

    image.gif

    其准确率也是可以达到92.30%

    参考资料

    《机器学习》周志华

    《深度学习与机器学习》吴恩达

    《神经网络与与深度学习》邱锡鹏

    《Pytorch深度学习实战》刘二大人

    相关实践学习
    【文生图】一键部署Stable Diffusion基于函数计算
    本实验教你如何在函数计算FC上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。函数计算提供一定的免费额度供用户使用。本实验答疑钉钉群:29290019867
    建立 Serverless 思维
    本课程包括: Serverless 应用引擎的概念, 为开发者带来的实际价值, 以及让您了解常见的 Serverless 架构模式
    目录
    相关文章
    |
    8天前
    |
    机器学习/深度学习 人工智能 算法
    猫狗宠物识别系统Python+TensorFlow+人工智能+深度学习+卷积网络算法
    宠物识别系统使用Python和TensorFlow搭建卷积神经网络,基于37种常见猫狗数据集训练高精度模型,并保存为h5格式。通过Django框架搭建Web平台,用户上传宠物图片即可识别其名称,提供便捷的宠物识别服务。
    127 55
    |
    18天前
    |
    机器学习/深度学习 人工智能 算法
    【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
    宠物识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了37种常见的猫狗宠物种类数据集【'阿比西尼亚猫(Abyssinian)', '孟加拉猫(Bengal)', '暹罗猫(Birman)', '孟买猫(Bombay)', '英国短毛猫(British Shorthair)', '埃及猫(Egyptian Mau)', '缅因猫(Maine Coon)', '波斯猫(Persian)', '布偶猫(Ragdoll)', '俄罗斯蓝猫(Russian Blue)', '暹罗猫(Siamese)', '斯芬克斯猫(Sphynx)', '美国斗牛犬
    104 29
    【宠物识别系统】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+图像识别
    |
    21天前
    |
    机器学习/深度学习 资源调度 算法
    图卷积网络入门:数学基础与架构设计
    本文系统地阐述了图卷积网络的架构原理。通过简化数学表述并聚焦于矩阵运算的核心概念,详细解析了GCN的工作机制。
    54 3
    图卷积网络入门:数学基础与架构设计
    |
    17天前
    |
    机器学习/深度学习 人工智能 自然语言处理
    深入理解深度学习中的卷积神经网络(CNN)##
    在当今的人工智能领域,深度学习已成为推动技术革新的核心力量之一。其中,卷积神经网络(CNN)作为深度学习的一个重要分支,因其在图像和视频处理方面的卓越性能而备受关注。本文旨在深入探讨CNN的基本原理、结构及其在实际应用中的表现,为读者提供一个全面了解CNN的窗口。 ##
    |
    21天前
    |
    机器学习/深度学习 算法 数据安全/隐私保护
    基于贝叶斯优化CNN-GRU网络的数据分类识别算法matlab仿真
    本项目展示了使用MATLAB2022a实现的贝叶斯优化、CNN和GRU算法优化效果。优化前后对比显著,完整代码附带中文注释及操作视频。贝叶斯优化适用于黑盒函数,CNN用于时间序列特征提取,GRU改进了RNN的长序列处理能力。
    |
    24天前
    |
    机器学习/深度学习 人工智能 自然语言处理
    深入理解深度学习中的卷积神经网络(CNN)
    深入理解深度学习中的卷积神经网络(CNN)
    |
    7天前
    |
    SQL 安全 网络安全
    网络安全与信息安全:知识分享####
    【10月更文挑战第21天】 随着数字化时代的快速发展,网络安全和信息安全已成为个人和企业不可忽视的关键问题。本文将探讨网络安全漏洞、加密技术以及安全意识的重要性,并提供一些实用的建议,帮助读者提高自身的网络安全防护能力。 ####
    45 17
    |
    17天前
    |
    存储 SQL 安全
    网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
    随着互联网的普及,网络安全问题日益突出。本文将介绍网络安全的重要性,分析常见的网络安全漏洞及其危害,探讨加密技术在保障网络安全中的作用,并强调提高安全意识的必要性。通过本文的学习,读者将了解网络安全的基本概念和应对策略,提升个人和组织的网络安全防护能力。
    |
    18天前
    |
    SQL 安全 网络安全
    网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
    随着互联网的普及,网络安全问题日益突出。本文将从网络安全漏洞、加密技术和安全意识三个方面进行探讨,旨在提高读者对网络安全的认识和防范能力。通过分析常见的网络安全漏洞,介绍加密技术的基本原理和应用,以及强调安全意识的重要性,帮助读者更好地保护自己的网络信息安全。
    40 10
    |
    20天前
    |
    SQL 安全 网络安全
    网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
    在数字化时代,网络安全和信息安全已成为我们生活中不可或缺的一部分。本文将介绍网络安全漏洞、加密技术和安全意识等方面的内容,并提供一些实用的代码示例。通过阅读本文,您将了解到如何保护自己的网络安全,以及如何提高自己的信息安全意识。
    46 10

    热门文章

    最新文章