【OCR学习笔记】7、明星经典模型汇总以及PyTroch实现(一)

本文涉及的产品
交互式建模 PAI-DSW,每月250计算时 3个月
模型训练 PAI-DLC,100CU*H 3个月
模型在线服务 PAI-EAS,A10/V100等 500元 1个月
简介: 【OCR学习笔记】7、明星经典模型汇总以及PyTroch实现(一)

1 卷积神经网络简介


卷积神经网络是一类包含卷积计算并且具有深度结构的前馈神经网络,是深度学习的重要算法之一。卷积神经网络通过有效提取图像的平移不变特征,CNN在计算机视觉等领域得到了广泛的应用。

此次推文主要讲解经典的卷积神经网络,包括,LeNet、AlexNet、VGGNet、GoogleNet、ResNet、DenseNet、SENet、SKNet以及ResNeStNet,后续会讲解轻量化模型和循环神经网络。

1.1、LeNet

1988年,Yann LeCun提出了用于手写字符识别的卷积网络模型LeNet5。其原理结构比较清晰,很多企业都采用了该模型用于识别现实场景中的数字,在邮政编码、手写数字识别方面都能够达到商用的程度,可见LeNet在AI领域的开创性地位。

LeNet虽然是一个很小的模型,但是麻雀虽小五脏俱全,以下是LeNet的PyTorch实现:

class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()
        # 输入的通道是1(黑白单通道),输出的通道是6, kernel大小为5
        # 卷积层1 输入尺寸 (32, 32),输出大小 (28, 28)
        self.conv1 = nn.Conv2d(1, 6, 5)
        #输入的通道是6,输出的通道是16,kernel的大小是5
        # 卷积层2 输入尺寸(14, 14),输出大小 (10, 10)
        self.conv2 = nn.Conv2d(6, 16, 5)
        # 输入的维度是16*5*5,输出的维度是120
        #全连接层1
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        # 全连接层2
        self.fc2 = nn.Linear(120, 84)
        # 全连接层3
        self.fc3 = nn.Linear(84, 10)
    def forward(self, x):
        # 推理过程
        # 输入大小为(28,28),输出大小为(14,14)
        x = F.max_pool2d(F.relu(self.conv1(x)), 2)
        # max pooling
        x = F.max_pool2d(F.relu(self.conv2(x)), 2)
        #拉直
        x = x.view(x.shape[0], -1)
        #全卷积之后输入激活函数
        x = F.relu(self.fc1(x))
        # 全卷积之后输入激活函数
        x = F.relu(self.fc2(x))
        # 压缩到类别数目
        x = self.fc3(x)
        return x

1.2 AlexNet

AlexNet是2012年提出的,AlexNet直接将ImageNet数据集的识别错误率从之前的非深度学习方法的28.2%降低到16.4%。AlexNet算是这波AI热潮的引爆点。AlexNet的结构与LeNet非常相似,但是做了很多改进,具体如下。

  • 更深的网络,增强了模型的表示能力。
  • 成功添加了ReLU激活函数作为CNN的激活层,缓解了sigmoid激活函数的梯度消失问题,收敛也更快。
  • 提出了局部响应归一化(Local Response Normalization,LRN),对局部神经元创建竞争机制,抑制反馈较少的神经元,增强模型的泛化能力。
  • 设计并使用了Dropout以随机忽略部分神经元,从而避免出现模型过拟合的问题。
  • 添加了裁剪旋转等方式增强数据。

6131f92edfd4d1bd83608be055c6d360.png

以下是基于PyTorch实现的AlexNet模型:

import torch.nn as nn  
class AlexNet(nn.Module):    
    def __init__(self, num_classes=1000):  
        super(AlexNet, self).__init__()  
        self.features = nn.Sequential(  
            nn.Conv2d(3, 64, kernel_size=11, stride=4, padding=2),  
            nn.ReLU(inplace=True),  
            nn.MaxPool2d(kernel_size=3, stride=2),  
            nn.Conv2d(64, 192, kernel_size=5, padding=2),  
            nn.ReLU(inplace=True),  
            nn.MaxPool2d(kernel_size=3, stride=2),  
            nn.Conv2d(192, 384, kernel_size=3, padding=1),  
            nn.ReLU(inplace=True),  
            nn.Conv2d(384, 256, kernel_size=3, padding=1),  
            nn.ReLU(inplace=True),  
            nn.Conv2d(256, 256, kernel_size=3, padding=1),  
            nn.ReLU(inplace=True),  
            nn.MaxPool2d(kernel_size=3, stride=2),  
        )  
        self.classifier = nn.Sequential(  
            nn.Dropout(),  
            nn.Linear(256 * 6 * 6, 4096),  
            nn.ReLU(inplace=True),  
            nn.Dropout(),  
            nn.Linear(4096, 4096),  
            nn.ReLU(inplace=True),  
            nn.Linear(4096, num_classes),  
        )  
    def forward(self, x):  
        x = self.features(x)  
        x = x.view(x.size(0), 256 * 6 * 6)  
        x = self.classifier(x)  
        return x

1.3 VGGNet

VGGNet在2014年的ImageNet比赛中,证明了增加网络的深度能够在一定程度上提升网络的最终性能。VGG有两种结构,分别是VGG16和VGG19,二者之间没有本质的区别,只是网络深度不同。

相较于AlexNet,VGGNet的主要改进是采用连续的3×3卷积核代替AlexNet中比较大的卷积核:11×11、7×7、5×5。对于给定的感受野,采用堆积的小卷积核优于采用大的卷积核,主要原因是能在不降低性能的前提下,极大地降低参数量。

展开来看,VGG使用三个3×3卷积核来替代一个7×7卷积核,使用两个3×3卷积核来替代一个5×5卷积核,这样可以在保证相同感受野的前提下,降低参数量,使得增加网络的深度成为可能(显存有限的条件下),从而极大地提升了网络的性能。原理如图所示:

80b26af2da408fc05de14e46b845156a.png

ff718f42dcb8933212cf2112755eaf19.png

以下是基于PyTorch实现的AlexNet模型:

class Vgg16(torch.nn.Module):
    def __init__(self):
        super(Vgg16, self).__init__()
        self.conv1_1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1)
        self.conv1_2 = nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1)
        self.conv2_1 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
        self.conv2_2 = nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1)
        self.conv3_1 = nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1)
        self.conv3_2 = nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1)
        self.conv3_3 = nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1)
        self.conv4_1 = nn.Conv2d(256, 512, kernel_size=3, stride=1, padding=1)
        self.conv4_2 = nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1)
        self.conv4_3 = nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1)
        self.conv5_1 = nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1)
        self.conv5_2 = nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1)
        self.conv5_3 = nn.Conv2d(512, 512, kernel_size=3, stride=1, padding=1)
    def forward(self, X):
        h = F.relu(self.conv1_1(X))
        h = F.relu(self.conv1_2(h))
        relu1_2 = h
        h = F.max_pool2d(h, kernel_size=2, stride=2)
        h = F.relu(self.conv2_1(h))
        h = F.relu(self.conv2_2(h))
        relu2_2 = h
        h = F.max_pool2d(h, kernel_size=2, stride=2)
        h = F.relu(self.conv3_1(h))
        h = F.relu(self.conv3_2(h))
        h = F.relu(self.conv3_3(h))
        relu3_3 = h
        h = F.max_pool2d(h, kernel_size=2, stride=2)
        h = F.relu(self.conv4_1(h))
        h = F.relu(self.conv4_2(h))
        h = F.relu(self.conv4_3(h))
        relu4_3 = h
        return [relu1_2, relu2_2, relu3_3, relu4_3]

1.4 GoogLeNet

VGG、AlexNet的绝大部分参数集中在最后几个全连接(FC)层,然而FC组件不仅参数多,而且容易过拟合,之后便有了NIN。NIN使用1×1卷积核创造性地解决了这个问题,极大地降低了参数量,同时还提升了效果

受到NIN的启发,Google的研究小组提出了Inception模块一种高效表达特征的稀疏性结构,主要是增加对尺度的适应性,达到提升特征表达能力的效果。Inception的结构如图所示:

为5×5的卷积核可能会导致参数量过大,所以需要通过降维控制参数量。GoogLeNet的另外一个贡献是将最后的卷积层都替换为全局均值池化层,因为Pooling的操作没有参数,因此能够进一步减少网络的参数量(这里笔者认为池化并不是一个很好的发明,如果能够避免尽可能少地使用该操作),便于应用于更大更深的网络,同时使准确率提升至93.3%(ImageNet上的top-5),速度还比VGG快很多。以下是基于PyTorch实现的GoogLeNet模型:

class Inception(nn.Module):
    def __init__(self, in_planes, n1x1, n3x3red, n3x3, n5x5red, n5x5, pool_planes):
        super(Inception, self).__init__()
        # 1x1 卷积
        self.conv1 = nn.Sequential(nn.Conv2d(in_planes, n1x1, kernel_size=1),
                                   nn.BatchNorm2d(n1x1),nn.ReLU(True))
        # 1x1卷积 + 3x3卷积
        self.conv2 = nn.Sequential(nn.Conv2d(in_planes, n3x3red, kernel_size=1),
                                   nn.BatchNorm2d(n3x3red),nn.ReLU(True),
                                   nn.Conv2d(n3x3red, n3x3, kernel_size=3, padding=1),
                                   nn.BatchNorm2d(n3x3),nn.ReLU(True))
        # 1x1卷积 + 5x5卷积
        self.conv3 = nn.Sequential(nn.Conv2d(in_planes, n5x5red, kernel_size=1),
                                   nn.BatchNorm2d(n5x5red),nn.ReLU(True),
                                   nn.Conv2d(n5x5red, n5x5, kernel_size=3, padding=1),
                                   nn.BatchNorm2d(n5x5),nn.ReLU(True),
                                   nn.Conv2d(n5x5, n5x5, kernel_size=3, padding=1),
                                   nn.BatchNorm2d(n5x5),nn.ReLU(True))
        # 3x3卷积 + 1x1卷积
        self.conv4 = nn.Sequential(nn.MaxPool2d(3, stride=1, padding=1),
                                   nn.Conv2d(in_planes, pool_planes, kernel_size=1),
                                   nn.BatchNorm2d(pool_planes),nn.ReLU(True))
    def forward(self, x):
        out1 = self.conv1(x)
        out2 = self.conv2(x)
        out3 = self.conv3(x)
        out4 = self.conv4(x)
        return torch.cat([out1, out2, out3, out4], 1)
# GoogleNet
class GoogleNet(nn.Module):
    def __init__(self, out_dim):
        super(GoogleNet, self).__init__()
        self.pre_layer = nn.Sequential(nn.Conv2d(3, 192, kernel_size=3, padding=1),
                                       nn.BatchNorm2d(192),
                                       nn.ReLU(True)
                                       )
        self.a3 = Inception(192, 64, 96, 128, 16, 32, 32)
        self.b3 = Inception(256, 128, 128, 192, 32, 96, 64)
        self.maxpool = nn.MaxPool2d(3, stride=2, padding=1)
        self.a4 = Inception(480, 192, 96, 208, 16, 48, 64)
        self.b4 = Inception(512, 160, 112, 224, 24, 64, 64)
        self.c4 = Inception(512, 128, 128, 256, 24, 64, 64)
        self.d4 = Inception(512, 112, 144, 288, 32, 64, 64)
        self.e4 = Inception(528, 256, 160, 320, 32, 128, 128)
        self.a5 = Inception(832, 256, 160, 320, 32, 128, 128)
        self.b5 = Inception(832, 384, 192, 384, 48, 128, 128)
        self.avgpool = nn.AvgPool2d(8, stride=1)
        self.linear = nn.Linear(1024, out_dim)
    def forward(self, x):
        x = self.pre_layer(x)
        x = self.a3(x)
        x = self.b3(x)
        x = self.maxpool(x)
        x = self.a4(x)
        x = self.b4(x)
        x = self.c4(x)
        x = self.d4(x)
        x = self.e4(x)
        x = self.maxpool(x)
        x = self.a5(x)
        x = self.b5(x)
        x = self.avgpool(x)
        x = x.view(x.size(0), -1)
        x = self.linear(x)
        return x


相关文章
|
21天前
|
机器学习/深度学习 人工智能 文字识别
Kimi 上线视觉思考模型,K1 系列强化学习模型正式开放,无需借助外部 OCR 处理图像与文本进行思考并回答
k1视觉思考模型是kimi推出的k1系列强化学习AI模型,具备端到端图像理解和思维链技术,能够在数学、物理、化学等领域表现优异。本文详细介绍了k1视觉思考模型的功能、技术原理、使用方法及其在多个应用场景中的表现。
168 68
Kimi 上线视觉思考模型,K1 系列强化学习模型正式开放,无需借助外部 OCR 处理图像与文本进行思考并回答
|
4月前
|
编解码 人工智能 文字识别
阶跃星辰开源GOT-OCR2.0:统一端到端模型,魔搭一站式推理微调最佳实践来啦!
GOT来促进OCR-2.0的到来。该模型具有580百万参数,是一个统一、优雅和端到端的模型,由高压缩编码器和长上下文解码器组成。
阶跃星辰开源GOT-OCR2.0:统一端到端模型,魔搭一站式推理微调最佳实践来啦!
|
5月前
|
文字识别 并行计算 PyTorch
MiniCPM-V 系列模型在多模态文档 RAG 中的应用(无需OCR的多模态文档检索+生成)
现在我们以 OpenBMB 基于 MiniCPM-V-2.0 训练的端到端多模态检索模型 MiniCPM-Visual-Embedding-v0 为例,实现无需OCR的多模态文档检索与问答。
MiniCPM-V 系列模型在多模态文档 RAG 中的应用(无需OCR的多模态文档检索+生成)
|
5月前
|
数据采集 机器学习/深度学习 文字识别
OCR -- 文本检测 - 训练DB文字检测模型
OCR -- 文本检测 - 训练DB文字检测模型
116 0
|
6月前
|
文字识别 开发工具
印刷文字识别使用问题之模型已经生成,如何追加样本量
印刷文字识别产品,通常称为OCR(Optical Character Recognition)技术,是一种将图像中的印刷或手写文字转换为机器编码文本的过程。这项技术广泛应用于多个行业和场景中,显著提升文档处理、信息提取和数据录入的效率。以下是印刷文字识别产品的一些典型使用合集。
|
6月前
|
文字识别
印刷文字识别使用问题之如何实让其他人标注,自己创建模型
印刷文字识别产品,通常称为OCR(Optical Character Recognition)技术,是一种将图像中的印刷或手写文字转换为机器编码文本的过程。这项技术广泛应用于多个行业和场景中,显著提升文档处理、信息提取和数据录入的效率。以下是印刷文字识别产品的一些典型使用合集。
|
7月前
|
人工智能 文字识别 自然语言处理
OCR小模型仍有机会!华科等提出VIMTS:零样本视频端到端识别新SOTA
【6月更文挑战第7天】华中科技大学团队推出VIMTS模型,刷新零样本视频文本识别SOTA。该模型通过Prompt Queries Generation Module和Tasks-aware Adapter增强跨任务协同,提升泛化能力。在多个跨域基准测试中,VIMTS平均性能提升2.6%,视频识别上超越现有方法。此创新降低OCR对标注数据依赖,为资源受限场景提供新方案。论文链接:https://arxiv.org/pdf/2404.19652
87 3
|
8月前
|
编解码 文字识别 测试技术
论文介绍:TextMonkey——面向文本理解的无OCR大型多模态模型
【5月更文挑战第2天】TextMonkey是一款无OCR的大型多模态模型,设计用于高效提取文本信息。它采用Shifted Window Attention和零初始化技术处理高分辨率文档,减少训练成本。通过假设图像中的冗余标记,模型能精简标记并提升性能。TextMonkey还能定位文本答案在图像中的位置,增强可解释性,在场景文本任务和关键信息提取中表现优越,特别是在OCRBench基准测试中刷新记录。然而,它在处理小图像和需要深层推理的任务时仍面临挑战。[链接](https://arxiv.org/abs/2403.04473)
210 5
|
人工智能 文字识别 自然语言处理
Nougat:一种用于科学文档OCR的Transformer 模型
随着人工智能领域的不断进步,其子领域,包括自然语言处理,自然语言生成,计算机视觉等,由于其广泛的用例而迅速获得了大量的普及。光学字符识别(OCR)是计算机视觉中一个成熟且被广泛研究的领域。它有许多用途,如文档数字化、手写识别和场景文本识别。数学表达式的识别是OCR在学术研究中受到广泛关注的一个领域。
325 0
|
8月前
|
人工智能 文字识别 自然语言处理
【2023 CSIG垂直领域大模型】大模型时代,如何完成IDP智能文档处理领域的OCR大一统?
2023年12月28-31日,由中国图象图形学学会主办的第十九届CSIG青年科学家会议在中国广州隆重召开,会议吸引了学术界和企业界专家与青年学者,会议面向国际学术前沿与国家战略需求,聚焦最新前沿技术和热点领域,共同探讨图象图形学领域的前沿问题,分享最新的研究成果和创新观点,在垂直领域大模型专场,合合信息智能技术平台事业部副总经理、高级工程师丁凯博士为我们带来了《文档图像大模型的思考与探索》主题报告。

热门文章

最新文章

相关产品

  • 文字识别