Dropout技术之随机神经元与随机深度

1. 写在前面

在学习复现EfficientNet网络的时候,里面有一个MBConv模块长下面这个样子:

在这里插入图片描述
当然,这个结构本身并不是很新奇,从resNet开始,几乎后面很多网络,比如DenseNet, MobileNet系列,ShuffleNet系列以及EfficientNet系列都会发现这样的残差结构。 但这次探索里面发现了Dropout这个点, 之前在实现残差结构的时候, 如果碰到Dropout, 我一直以为是之前学习到的随机失活神经元的Dropout,但直到在这里看到源码才发现,不是我想象的那么简单!

这种残差结构里面使用的Dropout,是一种叫做随机深度的Dropout技术。这个是2016年ECCV上发表的一篇paper,论文叫做《Deep Network with Stochastic depth》, 说的是训练过程中,不是随机失活每一层的神经元了,而是随机去掉很多层,这样能减少冗余,还能加速训练。

出于好奇,我读了下这篇paper, 又学习到了一种训练带有残差网络的骚操作,所以,这篇文章想统一把这两种Dropout放一块整理下。

2. Dropout之随机神经元

这个技术就是普通的Dropout技术了,Dropout随机失活神经元,就是我们给出一个概率,让神经网络层的某个神经元权重为0(失活)

就是每一层,让某些神经元不起作用,这样就就相当于把网络进行简化了(左边和右边可以对比),我们有时候之所以会出现过拟合现象,就是因为我们的网络太复杂了,参数太多了,并且我们后面层的网络也可能太过于依赖前层的某个神经元

加入Dropout之后, 首先网络会变得简单,减少一些参数,并且由于不知道浅层的哪些神经元会失活,导致后面的网络不敢放太多的权重在前层的某个神经元,这样就减轻了一个过渡依赖的现象, 对特征少了依赖, 从而有利于缓解过拟合

这个类似于我们期末考试的时候有没有,老师总是会给我们画出一个重点,但是由于我们不知道这些重点哪些会真的出现在试卷上,所以就得把精力分的均匀一些,都得看看, 这样保险一些,也能泛化一点,至少只要是这些类型的题都会做。 而如果我们不把精力分的均匀一些,只关注某种题型, 那么准糊一波

所以这种Dropout技术可以帮助网络缓解过拟合。不太难理解, 但使用的时候有几个注意问题:

  1. 数据尺度变化
    我们用Dropout的时候是这样用的: 只在训练的时候开启Dropout,而测试的时候是不用Dropout的,也就是说模型训练的时候会随机失活一部分神经元, 而测试的时候我们用所有的神经元,那么这时候就会出现这个数据尺度的问题, 所以测试的时候,所有权重都乘以1-drop_prob, 以保证训练和测试时尺度变化一致。 怎么理解? 依然拿上面的图来说:

    假设我们的输入是100个特征, 那么第一层的第一个神经元的表达式应该是这样, 这里先假设不失活:
    Z 1 1 = ∑ i = 1 100 w i x i Z_{1}^{1}=\sum_{i=1}^{100} w_{i} x_{i} Z11=i=1100wixi
    假设我们这里的 w i x i = 1 w_ix_i=1 wixi=1, 那么第一层第1个神经元 Z 1 1 = 100 Z_1^1=100 Z11=100, 注意这是不失活的情况,那么如果失活呢? 假设失活率drop_prob=0.3, 也就是我们的输入大约有30%是不起作用的,也就是会有30个不起作用, 当然这里是大约哈,因为失活率%30指的是每个神经元的失活率。换在整体上差不多可以理解成30个不起作用,那么我们的 Z 1 1 Z_1^1 Z11相当于
    Z 1 1 t r a i n = ∑ i = 1 70 w i x i = 70 {Z_1^1}_{train} = \sum_{i=1}^{70} w_ix_i = 70 Z11train=i=170wixi=70
    我们发现,如果使用Dropout之后,我们的 Z 1 1 Z_1^1 Z11成了70, 比起不失活来少了30, 这就是一个尺度的变化, 所以我们就发现如果训练的时候用Dropout, 我们每个神经元取值的一个尺度是会缩小的,比如这里的70, 而测试的时候我们用的是全部的神经元,尺度会变成100,这就导致了模型在数值上有了一个差异。因此,我们在测试的时候,需要所有的权重乘以1-drop_prob这一项, 这时候我们在测试的时候就相当于:
    Z 1 1 t e s t = ∑ i = 1 100 ( 0.7 × w i ) x i = 0.7 × 100 = 70 {Z_1^1}_{test} = \sum_{i=1}^{100}(0.7\times w_i)x_i = 0.7 \times100 = 70 Z11test=i=1100(0.7×wi)xi=0.7×100=70

    这样采用Dropout的训练集和不采用Dropout的测试集的尺度就变成一致了。 Pytorch在实现Dropout的时候, 是权重乘以 1 1 − p \frac{1}{1-p} 1p1的,也就是除以1-p, 这样就不用再测试的时候权重乘以1-p了, 也没有改变原来数据的尺度。 也就是上面公式中的
    Z 1 1 t r a i n = ∑ i = 1 70 ( 70 0.7 w i ) x i = 100 Z 1 1 t e s t = ∑ i = 1 100 w i x i = 100 {Z_1^1}_{train} = \sum_{i=1}^{70} (\frac{70}{0.7}w_i)x_i = 100 \\ {Z_1^1}_{test} = \sum_{i=1}^{100} w_ix_i = 100 Z11train=i=170(0.770wi)xi=100Z11test=i=1100wixi=100
    这个细节要注意下。

  2. Dropout层放置的位置
    比如,我们写下面这段代码

    class MLP(nn.Module):def __init__(self, neural_num, d_prob=0.5):super(MLP, self).__init__()self.linears = nn.Sequential(nn.Linear(1, neural_num),nn.ReLU(inplace=True),nn.Dropout(d_prob),             # 注意这里用上了Dropout, 我们看到这个Dropout是接在第二个Linear之前,Dropout通常放在需要Dropout网络的前一层nn.Linear(neural_num, neural_num),nn.ReLU(inplace=True),nn.Dropout(d_prob),nn.Linear(neural_num, neural_num),nn.ReLU(inplace=True),nn.Dropout(d_prob),  # 通常输出层的Dropout是不加的,这里由于数据太简单了才加上nn.Linear(neural_num, 1),)def forward(self, x):return self.linears(x)net_prob_05 = MLP(neural_num=n_hidden, d_prob=0.5)# ============================ step 3/5 优化器 ============================
    optim_reglar = torch.optim.SGD(net_prob_05.parameters(), lr=lr_init, momentum=0.9)# ============================ step 4/5 损失函数 ============================
    loss_func = torch.nn.MSELoss()# ============================ step 5/5 迭代训练 ============================for epoch in range(max_iter):pred_wdecay = net_prob_05(train_x)loss_wdecay = loss_func(pred_wdecay, train_y)optim_reglar.zero_grad()loss_wdecay.backward()optim_reglar.step()if (epoch+1) % disp_interval == 0:# 这里要注意一下,Dropout在训练和测试阶段不一样,这时候需要对网络设置一个状态net_prob_05.eval() # 这个.eval()函数表示我们的网络即将使用测试状态, 设置了这个测试状态之后,才能用测试数据去测试网络, 否则网络怎么知道啥时候测试啥时候训练?test_pred_prob_05 = net_prob_05(test_x)
    

    这里注意看MLP网络里面Dropout层的位置,一般是放在需要Dropout的层的前面。输入层不需要dropout,最后一个输出层一般也不需要。就是由于Dropout操作,模型训练和测试是不一样的,上面我们说了,训练的时候采用Dropout而测试的时候不用Dropout, 那么我们在迭代的时候,就得告诉网络目前是什么状态,如果要测试,就得先用.eval()函数告诉网络一下子,训练的时候就用.train()函数告诉网络一下子。

这就是我们之前熟知的Dropout随机神经元技术了, 之前我的学习认知也停留在这里为止,直到又见识到了随机深度技术, 所以下面重点整理下这个是怎么玩的。

3. Dropout之随机深度

随机深度是黄高博士在2016年提出来的一种针对网络高效训练的技术, 谈到黄高博士,可能大家更熟悉他提出的DenseNet网络, 这个网络要比随机深度晚一些,但也受到随机深度的一些启发。

3.1 背景

深的网络在现在表现出了十分强大的能力,但是也存在许多问题。即使在现代计算机上,梯度会消散、前向传播中信息的不断衰减、训练时间也会非常缓慢等问题。

ResNet的强大性能在很多应用中已经得到了证实,尽管如此,ResNet还是有一个不可忽视的缺陷——更深层的网络通常需要进行数周的训练——因此,把它应用在实际场景下的成本非常高。为了解决这个问题,作者们引入了一个“反直觉”的方法,即在我们可以在训练过程中任意地丢弃一些层,并在测试过程中使用完整的网络

在EfficientNet中也逐渐发现了这个现象, 之前的一些研究, 主要是关注网络的准确率和参数数量,比如设计更加复杂的网络结构,更深,更宽,分辨率更大等,去提高网络的准确率,但后来逐渐发现,这些网络在实际场景中可能不太好落地。 所以后续的一些研究,又开始关注与网络的训练速度,推理速度等,所以一些轻量级的网络慢慢诞生。 比如MobileNet系列,ShuffleNet系列以及EfficientNet系列。 当然也有可能是精度慢慢的到了瓶颈了。

这篇paper也是想提高网络的训练速度或者效率,所以思路就是提出随机深度,在训练时使用较浅的深度(随机在resnet的基础上pass掉一些层),在测试时使用较深的深度,较少训练时间,提高训练性能,最终在四个数据集上都超过了resnet原有的性能(cifar-10, cifar-100, SVHN, imageNet)。其训练过程中采用随机dropout一些中间层的方法改进ResNet,发现可以显著提高ResNet的泛化能力。

那么怎么做到呢?

3.2 网络基本思想

作者用了残差块作为他们网络的构件,因此,在训练中,如果一个特定的残差块被启用了,那么它的输入就会同时流经恒等表换shortcut(identity shortcut)和权重层;否则输入就只会流经恒等变换shortcut。

在训练的过程中,每一个层都有一个“生存概率”,并且都会被任意丢弃。在测试过程中,所有的block都将保持被激活状态,而且block都将根据其在训练中的生存概率进行调整。

在这里插入图片描述
假设 H l H_l Hl是第 l l l个残差块的输出结果, f l f_l fl是由第 l l l个残差块的主分支输出。 b l b_l bl是一个随机变量(只有1或者0,反映一个block是否是被激活的,或者是否启用当前主分支)。那么加了随机深度的Dropout之后的残差块输出公式计算如下:
H ℓ = ReLU ⁡ ( b ℓ f ℓ ( H ℓ − 1 ) + id ⁡ ( H ℓ − 1 ) ) H_{\ell}=\operatorname{ReLU}\left(b_{\ell} f_{\ell}\left(H_{\ell-1}\right)+\operatorname{id}\left(H_{\ell-1}\right)\right) H=ReLU(bf(H1)+id(H1))
这个其实也非常好理解, 原先的残差结构,就是跳远连接+主分支然后非线性激活,只不过这里多了一个 b l b_l bl来控制主分支是否有效。 如果 b l = 0 b_l=0 bl=0, 那么
H l = ReLU ⁡ ( i d ( H l − 1 ) ) H_{l}=\operatorname{ReLU}\left(i d\left(H_{l-1}\right)\right) Hl=ReLU(id(Hl1))
直走跳远连接,而这个是恒等映射,相当于当前的残差块不起作用,否则当前的残差块就被启用。

那么这个 b l b_l bl是怎么得到的呢? 这个和普通Dropout差不多,我们对于每个残差块,都指定一个是主分支激活的概率 p p p,即每个残差块都有 1 − p 1-p 1p可能性被dropout掉,即 b l = 0 b_l=0 bl=0

当然,在实际操作的时候,作者是将“线性衰减规律”应用到了每一层的生存概率,因为他们觉得较早的层会提取低级特征,而这些基础特征对后面的层很重要,所以这些层不应该频繁的丢弃主分支。 而随着后面层提取的特征越来越抽象,冗余度可能更高,所以越到后面,这个丢弃主分支的概率就增加,具体计算公式如下:
p ℓ = 1 − ℓ L ( 1 − p L ) p_{\ell}=1-\frac{\ell}{L}\left(1-p_{L}\right) p=1L(1pL)
这里的 p l p_l pl表示 l l l层训练中主分支的保留概率, L L L是block块的总数量, p L p_L pL是我们给出的dropout_rate。 l l l是表示 l l l层的残差块。

实验表明,同样是训练一个110层的ResNet,以任意深度进行训练的性能,比以固定深度进行训练的性能要好。这就意味着ResNet中的一些层(路径)可能是冗余的。

所以这种训练方式的优点:

  1. 成果解决深度网络训练时间难题
  2. 大大减少训练时间,并显著改善网络的精度
  3. 可以使得网络更深

当然,这里的原理不是很难, 下面主要是从代码层面看看具体是怎么实现的。

这里拿EfficientNet网络里面的代码进行说明,其他的也都类似:

# kernel_size, in_channel, out_channel, exp_ratio, strides, use_SE, drop_connect_rate, repeats
default_cnf = [[3, 32, 16, 1, 1, True, drop_connect_rate, 1],[3, 16, 24, 6, 2, True, drop_connect_rate, 2],[5, 24, 40, 6, 2, True, drop_connect_rate, 2],[3, 40, 80, 6, 2, True, drop_connect_rate, 3],[5, 80, 112, 6, 1, True, drop_connect_rate, 3],[5, 112, 192, 6, 2, True, drop_connect_rate, 4],[3, 192, 320, 6, 1, True, drop_connect_rate, 1]]

这里给出每个stage的配置, 这个具体不用管,这个看EfficientNet的网络结构就知道。
在这里插入图片描述
这里是修改配置的代码,也就是会遍历上面的每个stage,然后根据重复次数建立残差块,这里的残差块是倒残差模块,开头的那个图里面的结构。 主要是框出来的这句话,就是“线性衰减规律”的那个公式, 这里的cnf[-1]表示的当前残差块的dropout_rate, 而args[-2]是我们指定的dropout_rate, b b b表示当前 l l l层, num_blocks就是总的blocks数, 和上面公式一一对应。

这里就会发现,搭建网络的时候,每个残差块都会指定一个dropout_rate, 那么在每个残差块里面,我们搭建的dropout层如下, 这里直接拿EfficientNetV1来看,重点关注self.dropout即可,上面的那些是主分支上的扩张卷积,dw卷积以及降维卷积,不是这篇文章的重点:

class InvertedResidualEfficientNetV1(nn.Module):def __init__(self,cnf: InvertedResidualConfigEfficientNet,norm_layer: Callable[..., nn.Module]):super(InvertedResidualEfficientNetV1, self).__init__()self.use_res_connect = (cnf.stride == 1 and cnf.input_c == cnf.out_c)layers = OrderedDict()activation_layer = nn.SiLU  # alias Swish# expandif cnf.expanded_c != cnf.input_c:layers.update({"expand_conv": ConvBNActivation(cnf.input_c,cnf.expanded_c,kernel_size=1,norm_layer=norm_layer,activation_layer=activation_layer)})# depthwiselayers.update({"dwconv": ConvBNActivation(cnf.expanded_c,cnf.expanded_c,kernel_size=cnf.kernel,stride=cnf.stride,groups=cnf.expanded_c,norm_layer=norm_layer,activation_layer=activation_layer)})if cnf.use_se:layers.update({"se": SqueezeExcitationV2(cnf.input_c,cnf.expanded_c)})# projectlayers.update({"project_conv": ConvBNActivation(cnf.expanded_c,cnf.out_c,kernel_size=1,norm_layer=norm_layer,activation_layer=nn.Identity)})self.block = nn.Sequential(layers)self.out_channels = cnf.out_cself.is_strided = cnf.stride > 1# 只有在使用shortcut连接时才使用dropout层if self.use_res_connect and cnf.drop_rate > 0:self.dropout = DropPath(cnf.drop_rate)else:self.dropout = nn.Identity()def forward(self, x: Tensor) -> Tensor:result = self.block(x)result = self.dropout(result)if self.use_res_connect:result += x

这里的代码细节不用多说, 其实就是开头的那个残差网络结构, 我们主要看看啥时候使用Dropout, 只有使用跳远连接,以及当前的dropout_rate大于0的时候, 我们的Dropout层会走一个DropPath, 否则不是残差结构,或者没有dropout_rate, 那么我们就恒等过去,所以DropoutPath只用于残差结构。

那么DropPath是怎么实现呢?

class DropPath(nn.Module):def __init__(self, drop_prob=None):super(DropPath, self).__init__()self.drop_prob = drop_probdef forward(self, x):return drop_path(x, self.drop_prob, self.training)

这里是建了一个DropPath层, 这里的核心实现是drop_path函数,在这里面,实现的就是根据给定的dropout_rate概率随机失活主分支。所以重点看看这个的实现逻辑:

def drop_path(x, drop_prob: float = 0, training: bool = False):if drop_prob == 0. or not training:return xkeep_prob = 1 - drop_prob# ndim是维度个数  x.shape[0] 是样本个数, shape: (x.shape[0], 1, 1, 1)  维度可以用+拼接shape = (x.shape[0], ) + (1, ) * (x.ndim - 1)# 为每个样本生成一个随机数 torch.rand[0, 1), keep_prob (0, 1], 两者之和是[0, 2)  形状是(x.shape[0], 1, 1, 1)random_tensor = keep_prob + torch.rand(shape, dtype=x.dtype, device=x.device)  # torch.rand 均匀分布抽取的随机数([0,1))# 下取整,即random_tensor非0即1  形状(x.shape[0], 1, 1, 1)random_tensor.floor_()    # 下取整# 这里随机失活主分支, 除以keep_prob是为了保持训练和测试的尺度一致,普通dropout思路output = x.div(keep_prob) * random_tensorreturn output

这里为了弄明白,我每一行代码就加了注释。 其实逻辑很简单, 对于我们一个batch里面的样本,比如 n n n个, 那么输入x的形状就是 ( n , c h a n n e l s i z e , h , w ) (n, channel_{size}, h, w) (n,channelsize,h,w), 我们首先会每个样本,都会生成一个[0,2)之间的随机数, 然后下取整,就得到了非0即1的random_tensor, 这个其实就是我们的 b l b_l bl, 每个样本对应一个,所以每个样本训练的时候,都会看看是否激活主分支。 然后具体是否激活,就是最后一行代码做的事情, 这里除以keep_prob是为了保证训练集和测试集的尺度范围一致,和普通的dropout一样。

这样,就实现了dropout技术随机丢弃某些残差层。

之所以整理, 我觉得这个技术在网络的训练中还是非常实用的,并且是一种通用技术,可以用到带有残差网络的很多模型,比如resnet, densenet, efficientnet等等,既能加快训练速度,也能增加网络精度,非常powerful的东西。

参考:

  • 深度学习模型之——Stochastic depth(随机深度)

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

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

相关文章

如何做高质量研究、写高水平论文?| 黄高、王兴刚等共话科研与论文写作

如何产生好的研究思路?如何撰写一篇高质量论文?如何从浩如烟海的论文中寻找好的科研灵感?如何通过Rebuttal为自己的文章扳回一城?导师跟学生之间怎样才能形成更好的合作关系? 在ECCV 2022中国预会议的Panel环节&#x…

智源青年科学家黄高:面向高效推理的深度网络结构设计

随着深度学习在工业界的广泛应用,人们对模型的关注不仅仅在于其预测精度,同时也对计算和存储效率提出了更高的要求。在提升模型效率的诸多手段中,神经网络结构创新始终是最为有效的方式之一。 2019年12月24日上午,智源青年科学家、…

RANet:MSDNet加强版!清华黄高团队提出分辨率自适应的高效推理网络RANet!

关注公众号,发现CV技术之美 本文分享论文『Resolution Adaptive Networks for Efficient Inference』,由清华黄高团队提出分辨率自适应的高效推理网络RANet!MSDNet加强版! 详细信息如下: 论文链接:https://…

ICLR2021 | 清华大学黄高团队:显存不够?不妨抛弃端到端训练

智源导读:本文主要介绍清华大学黄高团队被ICLR2021接收的一篇文章:Revisiting Locally Supervised Learning: an Alternative to End-to-End Training。 论文链接:https://openreview.net/forum?idfAbkE6ant2 代码链接:https://g…

清华大学黄高——图像数据的语义层扩增方法

⬆⬆⬆ 点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入! 2020 年 9 月 25 日,在由中国科协主办,清华大学计算机科学与技术系、AI TIME 论道承办的《2020 中国科技峰会系列活动青年科学家沙龙——人工智能学术生态与产业创新》上&#xf…

DenseNet发明者黄高:动态模型好在哪里?

智源导读:自2012年至今,计算机视觉领域蓬勃发展,各种模型不断涌现,短短 8 年时间,计算机视觉领域便发生了天翻地覆的变化。那么如何看待过往变化,当下研究又如何? 12月10日晚,在【青…

对话 DenseNet 一作黄高:做有韧劲、能抗压、不断探索未知的科研

点击上方“计算机视觉工坊”,选择“星标” 干货第一时间送达 作者丨刘冰一 来源丨极市平台 清华大学助理教授、密集连接卷积网络 (DenseNet)提出者 、计算机视觉领域一作顶会论文被引次数最高的国内学者、百万青橙奖奖金获得者..... 这些标签…

测试工程师的好日子来啦?Testin发布AI测试产品,提升易用性和自动化效率

2019年10月26日,以"AI未来"为主题的第二届NCTS中国云测试行业峰会在北京国际会议中心正式开幕。在本次大会上,Testin 总裁徐琨正式发布测试业务Testin云测的全新AI产品iTestin。作为 Testin 人工智能战略中的重要一环,iTestin 融合…

【CodingNoBorder - 07】无际软工队 - 求职岛:ALPHA 阶段测试报告

无际软工队 - 求职岛:ALPHA 阶段测试报告 项目内容这个作业属于哪个课程2022年北航敏捷软件工程这个作业的要求在哪里团队项目-Alpha阶段测试报告我们在这个课程的目标是熟悉敏捷开发的方法论,并通过实际开发产品进行实践。这个作业在哪个具体方面帮助我…

pytest测试报告Allure - 动态生成标题生成功能、添加用例失败截图

一、动态生成标题 默认 allure 报告上的测试用例标题不设置就是用例名称,其可读性不高;当结合 pytest.mark.parametrize 参数化完成数据驱动时,如标题写死,其可读性也不高。 那如果希望标题可以动态的生成,采取的方案…

❀YOLOv5学习❀图像标注工具LabelImg的下载,配置和使用。

LabelImg是图形图像注释工具。它是用Python编写的,并将Qt用于其图形界面。批注以PASCAL VOC格式(ImageNet使用的格式)另存为XML文件。此外,它还支持YOLO格式。下载这个,主要是为了YOLOv5中,做自己的数据集&…

brat事件标注平台使用教程

事件图谱首先涉及到的是事件标注,我采用的是brat事件标注平台,该平台使用的是Linux系统,因为我的电脑是windows系统, 将brat安装在了linux虚拟机(Ubuntu)上。 一.下载与安装 1.下载brat 进入brat官网brat…

OpenAI 成近期顶流团队?如何使用 OpenAI 和 Node.js 构建 AI 图像生成器?

摘要: 12月7号,知名人工智能研究机构 Open AI 在Youtub上发布视频介绍使用OpenAI 和 DALL-E 模型创建一个网络应用程序,该应用程序将根据输入的文本从头开始生成图像。https://www.youtube.com/watch?vfU4o_BKaUZE 前言💖 大家好&#xff0…

AI 自动写代码插件 Copilot(副驾驶员)

AI 自动写代码插件 Copilot 提示:Copilot单词直译过来就是副驾驶员的意思。 介绍:本质上就是基于GitHub开源的亿级别的代码,训练AI模型,自动生成代码。 就是数据量(GitHub的数据量就很大!)能够决定你AI模型精度的上…

软件测试中的AI——运用AI编写测试用例

文章目录 一、现状二、测试技术可结合AI的几个方向三、尝试使用AI编写测试用例(实验过程)1、AI联系上下文的能力弱2、回答的内容类似于能在网上搜索到的内容3、需要有一个明确的指令4、输出内容有限5、无法想象到需求描述之外的内容 四、总结&#xff1a…

AI热度降温?揭秘加德纳技术成熟度曲线与AI发展阶段

一文解决你所有对 AI 的焦虑 近期,我们发现ChatGPT的热度似乎不如前几个月。许多人尝试了这个技术,觉得它非常强大,但似乎与自己的日常生活和工作关系不大,因此逐渐失去了兴趣。 然而,这实际上是技术发展的正常周期&…

王炸赚钱组合!!ChatGPT + AI大模型

“ 你近期有体验过哪些大模型产品呢? 你有使用大模型API做过一些实际开发吗? 在你日常开发中,可以与大模型相关应用结合来完成工作吗? ” 从去年底开始,大模型的发展趋势就非常迅猛,这也代表着人工智能进入…

ChatGPT + AI大模型 = 王炸!!!

“ 你近期有体验过哪些大模型产品呢? 你有使用大模型API做过一些实际开发吗? 在你日常开发中,可以与大模型相关应用结合来完成工作吗? ” 从去年底开始,大模型的发展趋势就非常迅猛,这也代表着人工智能进入…

ChatGPT+低代码,好用到飞起?

ChatGPT 凭借短短 2 个月,月活用户突破 1 亿,成为史上用户增长速度最快的消费级应用程序。ChatGPT 的爆火,在全球范围内掀起了一场关于 AI 技术革命的狂潮,AIGC 也迅速成为科技圈最火赛道。 更有国际咨询机构预测,203…

信用卡兴趣人群洞察报告.pdf

男性用户对信用卡的关注度显著高于女性 信用卡兴趣人群年龄集中在24-40岁,与主流消费人群相吻合。41岁以上人群信用卡关注度明显滑落 深广信用卡关注度最高,占据前四名知州、西安等中西部城市占据前十名中半数名额 信用卡兴趣人群高度集中于iPhone手机,其次分别为三星、魅族…