【图像分类】【深度学习】【Pytorch版本】GoogLeNet(InceptionV1)模型算法详解

【图像分类】【深度学习】【Pytorch版本】GoogLeNet(InceptionV1)模型算法详解

文章目录

  • 【图像分类】【深度学习】【Pytorch版本】GoogLeNet(InceptionV1)模型算法详解
  • 前言
  • GoogLeNet(InceptionV1)讲解
    • Inception结构
    • InceptionV1结构
    • 1x1卷积的作用
    • 辅助分类器
  • GoogLeNet(InceptionV1)模型结构
  • GoogLeNet(InceptionV1) Pytorch代码
  • 完整代码
  • 总结


前言

GoogLeNet(InceptionV1)是由谷歌的Szegedy, Christian等人在《Going Deeper With Convolutions【CVPR-2015】》【论文地址】一文中提出的模型,主要特点是提高了网络内部计算资源的利用率,允许增加网络的深度和宽度,同时保持计算预算不变。


GoogLeNet(InceptionV1)讲解

此前传统的方式简单粗暴的增加隐藏层(网络深度)和各层神经元数目(网络宽度)以达到提高网络性能的目的, 但这类方法存在致命的问题:更大的参数空间需要更多的计算资源并且更容易导致过拟合;网络越深则梯度越容易消失导致优化更加困难。
卷积神经网络的性能提高都是依赖于提高网络的深度和宽度,如何在增加网络深度和宽度的同时减少参数?解决思路便是全连接变成稀疏连接,GoogLeNet从网络结构上入手,改变了网络结构,提出了inception的卷积网络结构:

  1. 空间(spatial)上的稀疏连接:卷积神经网络本身对输入图像的局部进行卷积,而不是对整个图像进行卷积,参数共享降低了总参数的数目并减少了计算量。
  2. 在特征维度(feature channel)上的稀疏:多个尺寸上进行卷积再聚合,把相关性强的特征聚集到一起(也是种稀疏连接),并使用1x1卷积进行降维,减少通道数,限制网络的大小,降低了计算复杂度。

Inception结构

原始的(基本)Inception模块,其通过多个尺寸上进行卷积再聚合,来提取更密集的特征。

对输入做了4个分支,分别用不同尺寸的filter进行卷积或池化,最后再在特征维度上拼接到一起,以便下一阶段能够同时从不同的尺度上提取特征。这种全新的结构设计能带来以下好处:

  1. 采用大小不同的卷积核,在多个尺度上同时进行卷积,意味着感受野的大小不同,得到的的特征尺度不同,特征更为丰富也意味着最后分类判断时更加准确。
  2. inception在特征维度上进行分解 (稀疏矩阵分解原理),在多个尺度上预先把相关性强的特征单独汇聚,(Hebbian原则) 强化具有相似类型特征的filter之间的关联(filter bank),如分别聚集1x1的的特征、3x3的特征和5x5的特征,用更少的filter来提取相关的特征,再将多个尺度的filter bank特征进行组合。

InceptionV1结构

原始的Inception 结构存在一个不可忽视的问题:卷积运算运算量过大,如果特征图的通道数过大(即当上一层的输出通道数较大时)会导致当前Inception模块的运算消费巨大,特别是当前Inception模块中的pooling层输出的通道数和输入保持一致,且由于多组卷积核并联运算,因此这是随着层数的堆叠而爆炸式增长的!
针对这一问题对原始结构做了改进,加上1x1卷积层作为reduction层做降维和特征映射、空间信息整合和引入非线性,以达到网络的压缩从而减少计算量。

1x1卷积的作用

1x1卷积在卷积神经网络中起着重要的作用:

  1. 降维和特征映射:1x1卷积可以用于降低通道数(即特征的维度),通过减少输入特征图的通道数来降低计算和存储成本,这对于减少模型的参数量、加快计算速度以及控制过拟合都非常有用。同时,1x1卷积也可以用于增加通道数,以增加特征的表达能力;
  2. 空间信息整合:尽管1x1卷积的感受野很小,但它可以在通道维度上对输入特征进行组合和整合,从而引入跨通道的交互和增加模型的非线性能力(1x1卷积中的非线性激活函数),这有助于模型学习不同通道之间的相关性和特征之间的互动,更好地拟合复杂的数据分布和提取更丰富的特征表示;
  3. 网络的压缩和加速:1x1卷积可以减少通道数,压缩卷积神经网络,减小模型的计算量和存储需求,从而实现更快的推理速度和更高的效率。

    使用128个3x3的卷积核对512通道特征图进行卷积
    参数量:512×3×3×128=589824
    计算量:512×3×3×128×W×H=589824×W×H
    使用24个1x1卷积核先对512通道特征图降维,再用128个3x3的卷积核进行卷积:
    参数量:512×1×1×24+24×3×3×128=12504
    计算量:512×1×1×24×W×H+24×3×3×128×W×H=12504×W×H

1x1卷积成为设计高效、灵活和强大的网络架构的重要工具。

辅助分类器

在GoogLeNet中,除了主要的分类器外,还在网络的中间层添加了两个辅助分类器,提供了额外的监督信号,帮助网络更好地学习特征表示。

辅助分类器的作用和优势:

  1. 渐进式训练和梯度传播:辅助分类器的添加有助于渐进式训练和梯度传播。由于辅助分类器位于网络的中间层,它们可以为网络的早期层和中间层提供额外的监督信号。这有助于缓解梯度消失问题,使得梯度能够更好地传播回网络的早期层,从而促进网络的训练和优化。
  2. 正则化和减轻过拟合:辅助分类器的添加有助于正则化网络,并减轻过拟合的风险。通过在网络的中间层引入额外的分类器,可以引入额外的参数约束和损失函数,从而限制网络的复杂性,降低过拟合的可能性。
  3. 梯度传播路径的多样性:辅助分类器的存在为网络提供了多条梯度传播路径。这有助于梯度在网络中传播更远,使得网络能够更好地学习和优化,多条梯度传播路径还有助于避免梯度消失或梯度爆炸的问题。
  4. 辅助训练信号:辅助分类器的预测结果可以提供额外的训练信号,用于监督网络的中间层。这可以促使中间层学习更具判别性的特征表示,从而提高网络的性能和泛化能力。
  5. 多尺度特征融合:辅助分类器在不同层级上进行分类,可以捕捉到不同尺度的特征。这有助于提高网络的感受野和特征表达能力。

需要注意的是,辅助分类器并不直接用于最终的预测结果。在训练过程中,辅助分类器的损失函数会被加权,并与主分类器的损失函数相结合。在推理阶段,辅助分类器被舍弃,仅使用主分类器进行预测。

辅助分类器的添加是GoogLeNet(InceptionV1)架构的一个重要设计特点,也为后续的深度卷积神经网络的发展奠定了基础。


GoogLeNet(InceptionV1)模型结构

下图是原论文给出的关于GoogLeNet(InceptionV1)模型结构的详细示意图:

GoogLeNet(InceptionV1)在图像分类中分为两部分:backbone部分: 主要由InceptionV1模块、卷积层和池化层(汇聚层)组成,分类器部分: 由主分类器和俩个辅助分类器组成。


GoogLeNet(InceptionV1) Pytorch代码

卷积层组: 卷积层+激活函数

# 卷积组:Conv2d+ReLU
class BasicConv2d(nn.Module):def __init__(self, in_channels, out_channels, kernel_size, stride=1, padding=0):super(BasicConv2d, self).__init__()self.conv = nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding)self.relu = nn.ReLU(inplace=True)def forward(self, x):x = self.conv(x)x = self.relu(x)return x

InceptionV1模块: 卷积层组+池化层

# InceptionV1:BasicConv2d+MaxPool2d
class InceptionV1(nn.Module):def __init__(self, in_channels, ch1x1, ch3x3red, ch3x3, ch5x5red, ch5x5, pool_proj):super(Inception, self).__init__()# 1×1卷积self.branch1 = BasicConv2d(in_channels, ch1x1, kernel_size=1)# 1×1卷积+3×3卷积self.branch2 = nn.Sequential(BasicConv2d(in_channels, ch3x3red, kernel_size=1),BasicConv2d(ch3x3red, ch3x3, kernel_size=3, padding=1)   # 保证输出大小等于输入大小)# 1×1卷积+5×5卷积self.branch3 = nn.Sequential(BasicConv2d(in_channels, ch5x5red, kernel_size=1),BasicConv2d(ch5x5red, ch5x5, kernel_size=5, padding=2)   # 保证输出大小等于输入大小)# 3×3池化+1×1卷积self.branch4 = nn.Sequential(nn.MaxPool2d(kernel_size=3, stride=1, padding=1),BasicConv2d(in_channels, pool_proj, kernel_size=1))def forward(self, x):branch1 = self.branch1(x)branch2 = self.branch2(x)branch3 = self.branch3(x)branch4 = self.branch4(x)# 拼接outputs = [branch1, branch2, branch3, branch4]return torch.cat(outputs, 1)

辅助分类器: 池化层+卷积层组+全连接层+dropout

# 辅助分类器:AvgPool2d+BasicConv2d+Linear+dropout
class InceptionAux(nn.Module):def __init__(self, in_channels, num_classes):super(InceptionAux, self).__init__()# 池化层self.averagePool = nn.AvgPool2d(kernel_size=5, stride=3)# 1×1卷积self.conv = BasicConv2d(in_channels, 128, kernel_size=1)  # output[batch, 128, 4, 4]# 全连接层self.fc1 = nn.Linear(2048, 1024)self.fc2 = nn.Linear(1024, num_classes)def forward(self, x):# aux1: N x 512 x 14 x 14# aux2: N x 528 x 14 x 14x = self.averagePool(x)# aux1: N x 512 x 4 x 4# aux2: N x 528 x 4 x 4x = self.conv(x)# N x 128 x 4 x 4x = torch.flatten(x, 1)x = F.dropout(x, 0.5, training=self.training)# N x 2048x = F.relu(self.fc1(x), inplace=True)x = F.dropout(x, 0.5, training=self.training)# N x 1024x = self.fc2(x)# N x num_classesreturn x

完整代码

import torch.nn as nn
import torch
import torch.nn.functional as F
from torchsummary import summaryclass GoogLeNet(nn.Module):def __init__(self, num_classes=1000, aux_logits=True, init_weights=False):super(GoogLeNet, self).__init__()self.aux_logits = aux_logitsself.conv1 = BasicConv2d(3, 64, kernel_size=7, stride=2, padding=3)self.maxpool1 = nn.MaxPool2d(3, stride=2, ceil_mode=True)self.conv2 = BasicConv2d(64, 64, kernel_size=1)self.conv3 = BasicConv2d(64, 192, kernel_size=3, padding=1)self.maxpool2 = nn.MaxPool2d(3, stride=2, ceil_mode=True)self.inception3a = InceptionV1(192, 64, 96, 128, 16, 32, 32)self.inception3b = InceptionV1(256, 128, 128, 192, 32, 96, 64)self.maxpool3 = nn.MaxPool2d(3, stride=2, ceil_mode=True)self.inception4a = InceptionV1(480, 192, 96, 208, 16, 48, 64)self.inception4b = InceptionV1(512, 160, 112, 224, 24, 64, 64)self.inception4c = InceptionV1(512, 128, 128, 256, 24, 64, 64)self.inception4d = InceptionV1(512, 112, 144, 288, 32, 64, 64)self.inception4e = InceptionV1(528, 256, 160, 320, 32, 128, 128)self.maxpool4 = nn.MaxPool2d(3, stride=2, ceil_mode=True)self.inception5a = InceptionV1(832, 256, 160, 320, 32, 128, 128)self.inception5b = InceptionV1(832, 384, 192, 384, 48, 128, 128)if self.aux_logits:self.aux1 = InceptionAux(512, num_classes)self.aux2 = InceptionAux(528, num_classes)self.avgpool = nn.AdaptiveAvgPool2d((1, 1))self.dropout = nn.Dropout(0.4)self.fc = nn.Linear(1024, num_classes)if init_weights:self._initialize_weights()def forward(self, x):# N x 3 x 224 x 224x = self.conv1(x)# N x 64 x 112 x 112x = self.maxpool1(x)# N x 64 x 56 x 56x = self.conv2(x)# N x 64 x 56 x 56x = self.conv3(x)# N x 192 x 56 x 56x = self.maxpool2(x)# N x 192 x 28 x 28x = self.inception3a(x)# N x 256 x 28 x 28x = self.inception3b(x)# N x 480 x 28 x 28x = self.maxpool3(x)# N x 480 x 14 x 14x = self.inception4a(x)# N x 512 x 14 x 14if self.training and self.aux_logits:    # eval model lose this layeraux1 = self.aux1(x)x = self.inception4b(x)# N x 512 x 14 x 14x = self.inception4c(x)# N x 512 x 14 x 14x = self.inception4d(x)# N x 528 x 14 x 14if self.training and self.aux_logits:    # eval model lose this layeraux2 = self.aux2(x)x = self.inception4e(x)# N x 832 x 14 x 14x = self.maxpool4(x)# N x 832 x 7 x 7x = self.inception5a(x)# N x 832 x 7 x 7x = self.inception5b(x)# N x 1024 x 7 x 7x = self.avgpool(x)# N x 1024 x 1 x 1x = torch.flatten(x, 1)# N x 1024x = self.dropout(x)x = self.fc(x)# N x 1000(num_classes)if self.training and self.aux_logits:   # 训练阶段使用return x, aux2, aux1return x# 对模型的权重进行初始化操作def _initialize_weights(self):for m in self.modules():if isinstance(m, nn.Conv2d):nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')if m.bias is not None:nn.init.constant_(m.bias, 0)elif isinstance(m, nn.Linear):nn.init.normal_(m.weight, 0, 0.01)nn.init.constant_(m.bias, 0)# InceptionV1:BasicConv2d+MaxPool2d
class InceptionV1(nn.Module):def __init__(self, in_channels, ch1x1, ch3x3red, ch3x3, ch5x5red, ch5x5, pool_proj):super(InceptionV1, self).__init__()# 1×1卷积self.branch1 = BasicConv2d(in_channels, ch1x1, kernel_size=1)# 1×1卷积+3×3卷积self.branch2 = nn.Sequential(BasicConv2d(in_channels, ch3x3red, kernel_size=1),BasicConv2d(ch3x3red, ch3x3, kernel_size=3, padding=1)   # 保证输出大小等于输入大小)# 1×1卷积+5×5卷积self.branch3 = nn.Sequential(BasicConv2d(in_channels, ch5x5red, kernel_size=1),# 在官方的实现中,其实是3x3的kernel并不是5x5,这里我也懒得改了,具体可以参考下面的issue# Please see https://github.com/pytorch/vision/issues/906 for details.BasicConv2d(ch5x5red, ch5x5, kernel_size=5, padding=2)   # 保证输出大小等于输入大小)# 3×3池化+1×1卷积self.branch4 = nn.Sequential(nn.MaxPool2d(kernel_size=3, stride=1, padding=1),BasicConv2d(in_channels, pool_proj, kernel_size=1))def forward(self, x):branch1 = self.branch1(x)branch2 = self.branch2(x)branch3 = self.branch3(x)branch4 = self.branch4(x)# 拼接outputs = [branch1, branch2, branch3, branch4]return torch.cat(outputs, 1)# 辅助分类器:AvgPool2d+BasicConv2d+Linear+dropout
class InceptionAux(nn.Module):def __init__(self, in_channels, num_classes):super(InceptionAux, self).__init__()# 池化层self.averagePool = nn.AvgPool2d(kernel_size=5, stride=3)# 1×1卷积self.conv = BasicConv2d(in_channels, 128, kernel_size=1)  # output[batch, 128, 4, 4]# 全连接层self.fc1 = nn.Linear(2048, 1024)self.fc2 = nn.Linear(1024, num_classes)def forward(self, x):# aux1: N x 512 x 14 x 14# aux2: N x 528 x 14 x 14x = self.averagePool(x)# aux1: N x 512 x 4 x 4# aux2: N x 528 x 4 x 4x = self.conv(x)# N x 128 x 4 x 4x = torch.flatten(x, 1)x = F.dropout(x, 0.5, training=self.training)# N x 2048x = F.relu(self.fc1(x), inplace=True)x = F.dropout(x, 0.5, training=self.training)# N x 1024x = self.fc2(x)# N x num_classesreturn x# 卷积组: Conv2d+ReLU
class BasicConv2d(nn.Module):def __init__(self, in_channels, out_channels, kernel_size, stride=1, padding=0):super(BasicConv2d, self).__init__()self.conv = nn.Conv2d(in_channels, out_channels, kernel_size, stride, padding)self.relu = nn.ReLU(inplace=True)def forward(self, x):x = self.conv(x)x = self.relu(x)return xif __name__ == '__main__':device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")model = GoogLeNet().to(device)summary(model, input_size=(3, 224, 224))

summary可以打印网络结构和参数,方便查看搭建好的网络结构。


总结

尽可能简单、详细的介绍了深度可分卷积的原理和卷积过程,讲解了GoogLeNet(InceptionV1)模型的结构和pytorch代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/142455.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

算法通关村第十六关青铜挑战——原来滑动窗口如此简单!

大家好,我是怒码少年小码。 从本篇开始,我们就要开始算法的新篇章了——四大思想:滑动窗口、贪心、回溯、动态规划。现在,向我们迎面走来的是——滑动窗口思想!😝 滑动窗口思想 概念 在数组双指针里&am…

虚拟化服务器+华为防火墙+kiwi_syslog访问留痕

一、适用场景 1、大中型企业需要对接入用户的访问进行记录时,以前用3CDaemon时,只能用于小型网络当中,记录的数据量太大时,本例采用破解版的kiwi_syslog。 2、当网监、公安查到有非法访问时,可提供基于五元组的外网访…

SPI协议详解

SPI协议详解 文章目录 SPI协议详解前言一、SPI是什么?二、通信原理SPI 通信的 4 种工作模式 总结 前言 好久没写这种协议了,最近正好需要用到,便详细的复习一下。 一、SPI是什么? SPI是串行外设接口(Serial Periphe…

MES系统如何赋能制造企业实现4M防错追溯?

生产过程4M管理和MES系统的结合是现代制造业中关键的质量管理实践,它有助于提高生产效率、降低生产成本并保证产品质量。本文将深入探讨4M管理的概念,以及MES系统如何赋能制造企业实现4M防错追溯。 一、4M管理的概念 4M管理是指在制造过程中管理和控制四…

leetCode 92.反转链表 II + 图解

92. 反转链表 II - 力扣&#xff08;LeetCode&#xff09; 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 206. 反转链表 - 力扣&#xff08;LeetCode&am…

区块链链游合约系统开发项目模式技术方案

​随着区块链技术的发展&#xff0c;链游合约系统开发逐渐成为了一个备受关注的项目。本文将探讨区块链链游合约系统开发项目的技术方案&#xff0c;包括项目背景、开发目标、技术架构、系统流程、安全措施等方面的内容。 一、项目背景 链游是一种基于区块链技术的游戏&#xf…

加密磁盘密钥设置方案浅析 — LUKS1

虚拟化加密磁盘密钥设置方案浅析 前言元数据分析元数据格式整体格式头部格式加密算法密码校验key slot格式其它字段 流程验证 前言 我们在虚拟化加密磁盘密钥设置方案浅析 — TKS1中介绍了加密磁盘密钥设置方案&#xff0c;TKS1对密钥设置(Linux Unified Key Setup)的流程和方…

阿里云容器镜像服务的运维总结

一、背景 容器镜像服务&#xff0c;作为一个可选付费产品&#xff0c;主要作用是存储docker的镜像仓库&#xff0c;供k8s拉取到Pod节点里。 你可以自己搭建一个harbor镜像仓库&#xff0c;在公司的开发环境下&#xff0c;将image推送到仓库&#xff1b;然后在生产k8s从仓库拉取…

ECharts:显示暂无数据

ECharts 是一个使用 JavaScript 实现的开源可视化库&#xff0c;涵盖各行业图表&#xff0c;满足各种需求&#xff0c;实现各种炫酷的统计图表效果。 如上图所示&#xff0c;有数据的时候固然好看&#xff0c;但是当它没有数据的时候&#xff0c;就是光秃秃的一片&#xff0c;所…

排序算法之-快速

算法原理 丛待排序的数列中选择一个基准值&#xff0c;通过遍历数列&#xff0c;将数列分成两个子数列&#xff1a;小于基准值数列、大于基准值数列&#xff0c;准确来说还有个子数列&#xff1a;等于基准值即&#xff1a; 算法图解 选出基准元素pivot&#xff08;可以选择…

[文件读取]shopxo 文件读取(CNVD-2021-15822)

1.1漏洞描述 漏洞编号CNVD-2021-15822漏洞类型文件读取漏洞等级⭐⭐漏洞环境VULFOCUS攻击方式 描述: ShopXO是一套开源的企业级开源电子商务系统。 ShopXO存在任意文件读取漏洞&#xff0c;攻击者可利用该漏洞获取敏感信息。 1.2漏洞等级 高危 1.3影响版本 ShopXO 1.4漏洞复现…

【Git】第一篇:Git安装(centos)

git查看安装版本 以我自己的centos7.6为例&#xff0c;我们可以输入以下指令查看自己是否安装了git. git --version安装了的话就会显示自己安装的版本。 git 安装 安装很简单&#xff0c;一条命令即可 sudo yum install git -ygit 卸载 sudo yum remove git -y

《使用EasyExcel在Excel中增加序号列的方法》

《使用EasyExcel在Excel中增加序号列的方法》 1、简介2、正文3、核心代码4、使用方法5、效果 1、简介 在处理Excel文件时&#xff0c;有时候需要为表格增加序号列。本文介绍了如何使用Java代码实现在Excel中增加序号列的功能&#xff0c;并提供了一个示例代码。 2、正文 在处理…

Android 图层列表 、 LayerDrawable 、 layer-list \ 改变 seekbar thumb 滑块 的颜色

android 官网 &#xff1a; 图层列表 LayerDrawable / layer-list LayerDrawable 是管理其他可绘制对象数组的可绘制对象。列表中的每个可绘制对象均按照列表顺序绘制。列表中的最后一个可绘制对象绘于顶部。 每个可绘制对象均由单个 <layer-list> 元素内的 <item>…

【服务发现与配置】Consul特性及搭建

文章目录 一、前言二、概念2.1、什么是Consul&#xff1f;2.2、Consul具有哪些特点?2.3、Consul 架构图2.4、Consul的使用场景 三、安装3.1. 下载3.2. 解压3.3. 拷贝到usr目录下3.4. 查看 安装是否成功3.5. 启动 四、Consul 开机自启动4.1. 路径/usr/lib/systemd/system/&…

前端开发项目中使用字体库

开发中有些项目要求使用固定的字体&#xff0c;这就需要项目中使用字体库。 首先需要下载字体库 将下载的字体文件放进项目中 在项目代码样式文件中定义字体 font-face {font-family: "Tobias-SemiBold";src: url("./assets/font/Tobias-SemiBold.ttf"…

vscode因为大文件而无限崩溃的问题,窗口意外终止(原因:“oom“,代码:“-536870904“

复制了一大堆的代码&#xff08;好几兆&#xff09;到一个文件里&#xff0c;然后就导致 vscode 卡死&#xff0c; 之后就算把该文件删掉了&#xff0c;打开vscode还是会默认打开该文件而卡死 解决办法&#xff1a; win R 输入 %appdata%/code/ 删除该文件夹下的 backups/ 文件…

OpenCV 实现透视变换

一&#xff1a;OpenCV透视变换的概念 仿射变换(affine transform)与透视变换(perspective transform)在图像还原、图像局部变化处理方面有重要意义。通常&#xff0c;在2D平面中&#xff0c;仿射变换的应用较多&#xff0c;而在3D平面中&#xff0c;透视变换又有了自己的一席之…

ESP32 Arduino引脚分配参考:您应该使用哪些 GPIO 引脚?

ESP32 芯片有 48 个引脚&#xff0c;具有多种功能。并非所有 ESP32 开发板中的所有引脚都暴露出来&#xff0c;有些引脚无法使用。 关于如何使用 ESP32 GPIO 有很多问题。您应该使用什么引脚&#xff1f;您应该避免在项目中使用哪些引脚&#xff1f;这篇文章旨在成为 ESP32 GP…

【2023.11.6】OpenAI发布会——近期chatgpt被攻击,不能使用

OpenAI发布会 写在最前面发布会内容GPT-4 Turbo 具有 128K 上下文函数调用更新改进了指令遵循和 JSON 模式可重现的输出和对数概率更新了 GPT-3.5 Turbo 助手 API、检索和代码解释器API 中的新模式GPT-4 Turbo 带视觉DALLE 3文字转语音 &#xff08;TTS&#xff09;收听语音样本…