政安晨:【深度学习处理实践】(二)—— 最大汇聚运算

最大汇聚运算(Max Pooling Operation)深度学习领域卷积神经网络常用的一种汇聚运算方式在卷积神经网络中,经过一系列卷积层和激活函数层后,数据在空间尺寸上逐渐减小,特征图的深度也逐渐增加。为了降低数据尺寸并提取最重要的特征,我们需要对特征图进行汇聚运算。

最大汇聚运算的原理是在一个固定大小的滑动窗口内找到最大的数值作为输出。具体操作步骤如下:

  1. 将特征图划分成不重叠的区域,这些区域称为汇聚窗口(pooling window)。
  2. 在每个汇聚窗口内,找到最大的数值作为该窗口的输出。
  3. 将所有汇聚窗口的输出组成汇聚特征图(pooled feature map)。

最大汇聚运算具有以下特点:

  1. 参数少:最大汇聚运算没有需要学习的参数,因此可以有效地减少模型的参数量。
  2. 位置不变性:最大汇聚运算不考虑特征在特征图上的位置,因此对输入的小变化具有一定的鲁棒性,使得模型对平移、旋转等变换具有一定的不变性。
  3. 特征不变性:最大汇聚运算只保留最重要的特征,对于噪音、冗余的特征具有一定的抑制作用,提取出更加鲁棒的特征。

最大汇聚运算在深度学习领域卷积神经网络中广泛应用,能够有效地降低特征图的尺寸并提取重要的特征,从而在模型训练和特征提取中发挥关键作用。

政安晨的个人主页政安晨

欢迎 👍点赞✍评论⭐收藏

收录专栏政安晨的机器学习笔记

希望政安晨的博客能够对您有所裨益,如有不足之处,欢迎在评论区提出指正!


开始

在咱们上一篇的文章中:

政安晨:【深度学习处理实践】(一)—— 卷积神经网络入门icon-default.png?t=N7T8https://blog.csdn.net/snowdenkeke/article/details/136495239你可能已经注意到,在卷积神经网络示例的每个MaxPooling2D层之后,特征图的尺寸都会减半。例如,在第一个MaxPooling2D层之前,特征图的尺寸是26×26,最大汇聚运算将其减半为13×13。这就是最大汇聚的作用主动对特征图进行下采样,与步进卷积类似。

最大汇聚是指从输入特征图中提取窗口,并输出每个通道的最大值。

它的概念与卷积类似,但是最大汇聚使用硬编码的max张量运算对局部图块进行变换,而不是使用学到的线性变换(卷积核)来进行变换。

最大汇聚与卷积的一大区别在于,最大汇聚通常使用2×2的窗口和步幅2,其目的是对特征图进行2倍下采样;与此相对,卷积通常使用3×3的窗口和步幅1。

为什么要用这种方法对特征图进行下采样?为什么不删除最大汇聚层,一直保留较大的特征图呢?我们来这样试一下,模型代码如下所示:

一个没有最大汇聚层、结构错误的卷积神经网络

from tensorflow import keras
from tensorflow.keras import layersinputs = keras.Input(shape=(28, 28, 1))
x = layers.Conv2D(filters=32, kernel_size=3, activation="relu")(inputs)
x = layers.Conv2D(filters=64, kernel_size=3, activation="relu")(x)
x = layers.Conv2D(filters=128, kernel_size=3, activation="relu")(x)
x = layers.Flatten()(x)
outputs = layers.Dense(10, activation="softmax")(x)
model_no_max_pool = keras.Model(inputs=inputs, outputs=outputs)

该模型的概述信息如下:

这种架构有以下两个问题:

这种架构不利于学习特征的空间层级结构。

第三层的3×3窗口只包含初始输入中7×7窗口所包含的信息。卷积神经网络学到的高级模式相对于初始输入来说仍然很小,这可能不足以学会对数字进行分类(你可以试试仅通过7像素×7像素的窗口来观察图像并识别其中的数字)。我们需要让最后一个卷积层的特征包含输入的全部信息。

最后一个特征图对每个样本都有61 952个元素(22×22×128=61 952)。

这太多了!如果你将特征图展平并在后面添加一个大小为10的Dense层,那么该层将有超过50万个参数。对于这样的小模型来说,这实在是太多了,会导致严重的过拟合。简而言之,使用下采样的原因,一是减少需要处理的特征图的元素个数,二是通过让连续卷积层的观察窗口越来越大(窗口覆盖原始输入的比例越来越大),从而引入空间滤波器的层级结构。

请注意,最大汇聚不是实现这种下采样的唯一方法。

你已经知道,还可以在前一个卷积层中使用步幅来实现。

此外,你还可以使用平均汇聚来代替最大汇聚,方法是对每个局部输入图块取各通道的均值,而不是最大值。

但最大汇聚的效果往往比这些替代方法更好,原因在于:特征中往往编码了某种模式或概念在特征图的不同位置是否存在(因此得名特征图),观察不同特征的最大值而不是均值能够给出更多的信息。最合理的子采样策略是,首先生成密集的特征图(利用无步进卷积),然后观察特征在每个小图块上的最大激活值,而不是通过稀疏的窗口观察输入(利用步进卷积)或对输入图块取均值,因为后两种方法可能导致错过或淡化特征是否存在的信息。

现在你应该已经理解了卷积神经网络的基本概念特征图、卷积和最大汇聚,并且也知道如何构建一个小型卷积神经网络来解决MNIST数字分类等简单问题。

下面我们将介绍更有用的实际应用:

在小型数据集上从头开始训练一个卷积神经网络

利用少量数据来训练图像分类模型,这是一种很常见的情况。

如果你从事与计算机视觉相关的职业,那么很可能会在实践中遇到这种情况。“少量”样本既可能是几百张图片,也可能是上万张图片。我们来看一个实例——猫狗图片分类,数据集包含5000张猫和狗的图片(2500张猫的图片,2500张狗的图片)。我们将2000张图片用于训练,1000张用于验证,2000张用于测试。

咱们这篇文章,将介绍解决这个问题的基本方法:使用已有的少量数据从头开始训练一个新模型。首先,我们在2000个训练样本上训练一个简单的小型卷积神经网络,不做任何正则化,为模型改进设定一个基准。我们得到的分类精度约为70%。这时的主要问题是过拟合。

然后,我们会使用数据增强(data augmentation),它是计算机视觉领域中非常强大的降低过拟合的方法。使用数据增强之后,模型的分类精度将提高到80%~85%。

咱们今后会介绍将深度学习应用于小型数据集的另外两个重要方法:使用预训练模型做特征提取(得到的精度为97.5%)微调预训练模型(最终精度为98.5%)

总而言之,这三种方法——从头开始训练一个小模型、使用预训练模型做特征提取、微调预训练模型——构成了你的工具箱,可用于解决小型数据集的图像分类问题。

深度学习对数据量很小的问题的适用性

要训练模型,“样本足够”是相对的,也就是说,“样本足够”是相对于待训练模型的大小和深度而言的。

只用几十个样本训练卷积神经网络来解决复杂问题是不可能的,但如果模型很小,并且做了很好的正则化,同时任务非常简单,那么几百个样本可能就足够了。由于卷积神经网络学到的是局部、平移不变的特征,因此它在感知问题上可以高效地利用数据。虽然数据量相对较少,但在非常小的图像数据集上从头开始训练一个卷积神经网络,仍然可以得到不错的结果,而且无须任何自定义的特征工程。咱们这篇文章中您能看到这种方法的效果。

此外,深度学习模型本质上具有很强的可复用性。

比如,已有一个在大规模数据集上训练好的图像分类模型或语音转文本模型,只需稍作修改就能将其复用于完全不同的问题。特别是在计算机视觉领域,许多预训练模型(通常都是在ImageNet数据集上训练得到的)现在都可以公开下载,并可用于在数据量很少的情况下构建强大的视觉模型。特征复用是深度学习的一大优势,咱们以后将介绍这一点。

下载数据

咱们这篇文章中用到的猫狗分类数据集不包含在Keras中。它由Kaggle提供,在2013年底作为一项计算机视觉竞赛的一部分,当时卷积神经网络还不是主流算法。你可以从Kaggle网站下载原始数据集Dogs vs. Cats(如果没有Kaggle账户,你需要注册一个。别担心,注册过程很简单)。此外,你也可以在Colab中使用Kaggle API来下载数据集(详见下方文本框“在Google Colaboratory中下载Kaggle数据集”)。

在Google Colaboratory中下载Kaggle数据集

Kaggle提供了一个易于使用的API,可以编写代码下载Kaggle托管的数据集。你可以用它将猫狗数据集下载到Colab笔记本中。这个API包含在kaggle包中,kaggle包已经预先安装在Colab上。下载这个数据集非常简单,只需在Colab单元格中运行下面这条命令。

!kaggle competitions download -c dogs-vs-cats

为了顺利进行演绎,咱们现在转移到Colab上继续执行:

(这个API的访问仅限于Kaggle用户,所以要想运行上述命令,首先需要进行身份验证。kaggle包会在一个JSON文件(位于~/.kaggle/kaggle.json)中查找你的登录凭证。我们来创建这个文件。)

首先,你需要创建一个Kaggle API密钥,并将其下载到本地计算机。只需在浏览器中访问Kaggle网站,登录,然后进入My Account页面。在账户设置中,找到API,单击Create New API Token按钮将生成一个kaggle.json密钥文件,然后将其下载到计算机中。

然后,打开Colab笔记本,在笔记本单元格中运行下列代码,将API密钥的JSON文件上传到Colab会话中。

运行这个单元格时,会出现Choose Files按钮。单击按钮并选择刚刚下载的kaggle.json文件。这样就把文件上传到Colab本地运行时。

上传好文件后:

创建~/.kaggle文件夹(mkdir ~/.kaggle),并将密钥文件复制过去(cp kaggle.json ~/.kaggle/)。作为最佳安全实践,你还应该确保该文件只能由当前用户(也就是你自己)读取(chmod 600)

!mkdir ~/.kaggle
!cp kaggle.json ~/.kaggle/
!chmod 600 ~/.kaggle/kaggle.json

现在再执行上面的指令下载数据:

!kaggle competitions download -c dogs-vs-cats

第一次尝试下载数据时,你可能会遇到403 Forbidden错误。这是因为在下载数据集之前,你需要接受与数据集相关的条款。你需要登录Kaggle账户并访问该数据集对应的Rules页面,然后单击I Understand and Accept按钮。该操作只需完成一次即可。

上面那个错误在这个地址接受:

Dogs vs. Cats | KaggleCreate an algorithm to distinguish dogs from catsicon-default.png?t=N7T8https://www.kaggle.com/c/dogs-vs-cats/rules现在可以下载数据了。

最后,训练数据是一个名为dogs-vs-cats.zip的压缩文件。请使用静默方式(-qq)解压缩(unzip)。

!unzip -qq dogs-vs-cats.zip

这个数据集中的图片都是中等分辨率的彩色JPEG图片。下图给出了一些样本示例。

不出所料,2013年猫狗分类Kaggle竞赛的优胜者使用的就是卷积神经网络。最佳结果达到了95%的精度。

本例中,虽然训练模型的数据量不到参赛选手所用数据量的10%,但结果与这个精度相当接近。

这个数据集包含25 000张猫和狗的图像(每个类别各有12 500张),压缩后的大小为543 MB。

下载数据并解压后,我们将创建一个新数据集,其中包含3个子集:

训练集,每个类别各1000个样本;

验证集,每个类别各500个样本;

测试集,每个类别各1000个样本。

之所以要这样做,是因为在你的职业生涯中,你遇到的许多图像数据集只包含几千个样本,而不是几万个。拥有更多的数据,可以让问题更容易解决,所以使用小型数据集进行学习是很好的做法。

我们要使用的子数据集的目录结构如下所示:

cats_vs_dogs_small/
...train/
......cat/  ←----包含1000张猫的图像
......dog/  ←----包含1000张狗的图像
...validation/
......cat/  ←----包含500张猫的图像
......dog/  ←----包含500张狗的图像
...test/
......cat/  ←----包含1000张猫的图像
......dog/  ←----包含1000张狗的图像

我们通过调用几次shutil来创建这个子数据集,如代码如下所示:

将图像复制到训练目录、验证目录和测试目录

import os, shutil, pathlib#   ←----原始数据集的解压目录
original_dir = pathlib.Path("train")#   ←----保存较小数据集的目录
new_base_dir = pathlib.Path("cats_vs_dogs_small")#   ←----一个实用函数,将索引从start_index到end_index的猫/狗图像复制到子目录new_base_dir/{subset_name}/cat(或/dog)下。subset_name可以是"train"、"validation"或"test"
def make_subset(subset_name, start_index, end_index):for category in ("cat", "dog"):dir = new_base_dir / subset_name / categoryos.makedirs(dir)fnames = [f"{category}.{i}.jpg"for i in range(start_index, end_index)]for fname in fnames:shutil.copyfile(src=original_dir / fname,dst=dir / fname)#   ←----用每个类别的前1000张图像创建训练子集
make_subset("train", start_index=0, end_index=1000)#   ←----用每个类别接下来的500张图像创建验证子集
make_subset("validation", start_index=1000, end_index=1500)#   ←----用每个类别接下来的1000张图像创建测试子集
make_subset("test", start_index=1500, end_index=2500)

现在我们有2000张训练图像、1000张验证图像和2000张测试图像。在这3个集合中,两个类别的样本数相同,所以这是一个均衡的二分类问题,分类精度可作为衡量成功的指标。

构建模型

模型的大致结构与前面第一个示例相同,卷积神经网络由Conv2D层(使用relu激活函数)和MaxPooling2D层交替堆叠而成,如代码如下所示。

但因为这里要处理更大的图像和更复杂的问题,所以需要相应地增大模型,增加两个Conv2D+MaxPooling2D的组合。这样做既可以增大模型容量,又可以进一步缩小特征图尺寸,使其在进入Flatten层时尺寸不会太大。本例初始输入的尺寸为180像素×180像素(这是一个随意的选择),最后在Flatten层之前的特征图尺寸为7×7。

注意 在模型中,特征图的深度逐渐增大(从32增大到128),而特征图的尺寸则逐渐缩小(从180×180缩小到7×7)。几乎所有卷积神经网络都是这种模式。

因为这是一个二分类问题,所以模型的最后一层是使用sigmoid激活函数的单个单元(大小为1的Dense层)。这个单元表示的是模型认为样本属于某个类别的概率。

最后还有一个小区别:模型最开始是一个Rescaling层,它将图像输入(初始取值范围是[0, 255]区间)的取值范围缩放到[0, 1]区间。

为猫狗分类问题实例化一个小型卷积神经网络

from tensorflow import keras
from tensorflow.keras import layers#   ←----模型输入应该是尺寸为180×180的RGB图像
inputs = keras.Input(shape=(180, 180, 3))#   ←----将输入除以255,使其缩放至[0, 1]区间
x = layers.Rescaling(1./255)(inputs)x = layers.Conv2D(filters=32, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=64, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=128, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=256, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=256, kernel_size=3, activation="relu")(x)
x = layers.Flatten()(x)outputs = layers.Dense(1, activation="sigmoid")(x)
model = keras.Model(inputs=inputs, outputs=outputs)

与前面一样,模型编译将使用rmsprop优化器。模型最后一层是单一的sigmoid单元,所以我们将使用二元交叉熵作为损失函数。

配置模型,以进行训练

model.compile(loss="binary_crossentropy",optimizer="rmsprop",metrics=["accuracy"])

数据预处理

现在你已经知道,将数据输入模型之前,应该将数据格式化为经过预处理的浮点数张量。当前数据以JPEG文件的形式存储在硬盘上,所以数据预处理步骤大致如下:

(1)读取JPEG文件。

(2)将JPEG文件解码为RGB像素网格。

(3)将这些像素网格转换为浮点数张量。

(4)将这些张量调节为相同大小(本例为180×180)。

(5)将数据打包成批量(一个批量包含32张图像)。

这些步骤可能看起来有些复杂,但幸运的是,Keras拥有自动完成这些步骤的工具。具体地说,Keras包含实用函数image_dataset_from_directory(),它可以快速建立数据管道,自动将磁盘上的图像文件转换为预处理好的张量批量。下面我们将使用这个函数,代码如下所示。

from tensorflow.keras.utils import image_dataset_from_directorytrain_dataset = image_dataset_from_directory(new_base_dir / "train",image_size=(180, 180),batch_size=32)
validation_dataset = image_dataset_from_directory(new_base_dir / "validation",image_size=(180, 180),batch_size=32)
test_dataset = image_dataset_from_directory(new_base_dir / "test",image_size=(180, 180),batch_size=32)

调用image_dataset_from_directory(directory),首先会列出directory的子目录,并假定每个子目录都包含某一个类别的图像。然后,它会为每个子目录下的图像文件建立索引。最后,它会创建并返回一个tf.data.Dataset对象,用于读取这些文件、打乱其顺序、将其调节为相同大小并打包成批量。

理解TensorFlow Dataset对象

TensorFlow提供了tf.data API,用于为机器学习模型创建高效的入管道,其中最重要的类是tf.data.Dataset。

Dataset对象是一个迭代器,你可以在for循环中使用它。它通常会返回由入数据和标签组成的批量。你可以将Dataset对象直接传入Keras模型的fit()方法中。

幸好Dataset类实现了许多重要功能,否则自己实现起来会很麻烦,特别是异步数据预取(在模型处理前一批数据时,预处理下一批数据,从而保持执行流畅而不中断)。

Dataset类还拥有一个用于修改数据集的函数式API


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

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

相关文章

微信小程序(五十三)修改用户头像与昵称

注释很详细,直接上代码 上一篇 新增内容: 1.外界面个人资料基本模块 2.资料修改界面同步问题实现(细节挺多,考虑了后期转服务器端的方便之处) 源码: app.json {"window": {},"usingCompone…

算法打卡day11|栈与队列篇03|Leetcode 239. 滑动窗口最大值、347.前 K 个高频元素

小顶堆和大顶堆 小顶堆(Min Heap)和大顶堆(Max Heap)是两种特殊的完全二叉树,它们遵循特定的堆属性,即父节点的值总是小于或等于(小顶堆)或者大于或等于(大顶堆&#xf…

Latex公式太长换行标号

Latex中公式太长换行,且编号,可以采用align,不编号行公式用\nonumber,示例如下: \begin{align}\nonumber %第1行公式不编号&abababababababa\\&cdm %第2行公式编号 \end{align}效果如下 原文件链接 公式不…

WordPress建站入门教程:如何上传安装WordPress主题?

我们成功搭建WordPress网站后,默认使用的是自带的最新主题,但是这个是国外主题,可能会引用一些国外的资源文件,所以为了让我们的WordPress网站访问速度更快,强烈建议大家使用国产优秀的WordPress主题。 今天boke112百…

【MySQL 系列】MySQL 架构篇

在我们开始了解 MySQL 核心功能之前,首先我们需要站在一个全局的视角,来看 SQL 是如何运作执行的。通过这种方式,我们可以在头脑中构建出一幅 MySQL 各组件之间的协同工作方式,有助于我们加深对 MySQL 服务器的理解。 文章目录 1、…

深入浅出运维可观测工具(四):如何使用eBPF绘制网络拓扑图

哈喽~又到了我们技术分享环节了。eBPF这个系列自分享以来收到了很多朋友的喜欢,真是让博主又惊又喜,感谢大家的支持。话不多说,今天我们将对如何使用eBPF绘制网络拓扑图做一篇分享,文章较长,干货较多,大家可…

R语言lavaan结构方程模型在复杂网络分析中的科研技术新趋势

此外,我们还将深入探讨R语言的基础知识、结构方程模型的基本原理、lavaan程序包的使用方法等内容。无论是潜变量分析、复合变量分析,还是非线性/非正态/缺失数据处理、分类变量分析、分组数据处理等复杂问题,我们都将一一为您解析。 希望通过…

微服务获取登录用户Id与单体服务下获取用户Id对比(黑马头条Day03)

前置声明 当前前后端分离开发项目中,后端某个请求向具体某个数据库中的多个表插入数据时,经常需要使用到当前登录用户的Id(唯一标识)。在当前用户线程下以实现变量共享,同时为了避免不同用户线程之间操作变量的影响&am…

【机器学习300问】28、什么是决策树?

〇、两个预测任务 (1)任务一:银行预测偿还能力 当前,某银行正致力于发掘潜在的放贷用户。他们掌握了每位用户的三个关键特征:房产状况、婚姻状况以及年收入。此外,银行还拥有过往这些用户的债务偿还能力的…

蓝桥杯简单题,公司名称

题目链接&#xff08;需要登录&#xff09; #include <iostream> #include <cstring> #include <algorithm> using namespace std; bool lanqiao(string str,int len){ sort(str.begin(),str.end());//对str按照ascii排序if(str.find("Laainoq")s…

React 从0到1构建企业级框架基于Antd Designer

一、 create-react-app 创建 cms-front 二、 删除不必须要的文件形成如下结构 1. React版本为17版本 public 文件夹下保留 favicon.ico 偏爱图标index.html资源文件 2.src 保留 index.js 入口文件和app.js(基于spa原则)单文件即可 三、配置eslint 1. 安装 eslint. npm inst…

DataX及使用

DataX及使用 【一】DataX概述【二】DataX架构原理【1】设计理念【2】框架设计【3】运行流程【4】调度决策思路【5】DataX和Sqoop对比 【三】DataX部署【四】DataX上手【1】使用概述【2】配置文件格式【3】同步Mysql数据到HDFS 【五】DataX整合Springboot 【一】DataX概述 Data…

27.基于springboot + vue实现的前后端分离-网上租赁交易系统(项目 + 论文)

项目介绍 本课题是根据用户的需要以及网络的优势建立的一个基于Spring Boot的网上租贸系统&#xff0c;来满足用户网络商品租赁的需求。本网上租贸系统应用Java技术&#xff0c;MYSQL数据库存储数据&#xff0c;基于Spring Boot框架开发。在网站的整个开发过程中&#xff0c;首…

24 Linux PWM 驱动

一、PWM 驱动简介 其实在 stm32 中我们就学过了 PWM&#xff0c;这里就是再复习一下。PWM&#xff08;Pulse Width Modulation&#xff09;&#xff0c;称为脉宽调制&#xff0c;PWM 信号图如下&#xff1a; PWM 最关键的两个参数&#xff1a;频率和占空比。 频率是指单位时间内…

如何使用c++的PCL库 对Las点云进行重建

在 C 中对点云进行重建通常需要使用一些专门的库和算法。下面是一种常见的方法&#xff0c;使用 PCL&#xff08;点云库&#xff09;进行点云重建&#xff1a; 安装 PCL 库&#xff1a;首先&#xff0c;需要安装 PCL 库。可以在 PCL 的官方网站上找到安装指南和文档。 读取点云…

排序算法:插入排序和希尔排序

一、插入排序 1.基本原理 插入排序&#xff08;英语&#xff1a;Insertion Sort&#xff09;是一种简单直观的排序算法。它的工作原理是通过构建有序序列&#xff0c;对于未排序数据&#xff0c;在已排序序列中从后向前扫描&#xff0c;找到相应位置并插入。插入排序在实现上…

排序算法:冒泡排序和简单选择排序

一、冒泡排序 1.冒泡排序的基本原理 对存放原始数组的数据&#xff0c;按照从前往后的方向进行多次扫描&#xff0c;每次扫描都称为一趟。当发现相邻两个数据的大小次序不符合时&#xff0c;即将这两个数据进行互换&#xff0c;如果从小大小排序&#xff0c;这时较小的数据就…

python将conda环境打入docker环境中

1.假设你本地已经安装好了conda相关的 ubuntu安装python以及conda-CSDN博客 并且已经创建启动过相关的环境&#xff0c;并且install了相关的包。 我本地的conda环境叫做,gptsovits_conda3 2.下载conda打包工具 conda install conda-pack pip install conda-pack 3.打包 con…

蓝桥杯day6队列-3.3

目录 1.约瑟夫环 1.注意&#xff01;q.push(q.front()); 2.机器翻译 3.小桥的神秘礼盒 4.餐厅排队 1.约瑟夫环 今天学习了队列的STL写法&#xff0c;来试试这个题。 #include<bits/stdc.h> using namespace std;int main() {int n,m;cin>>n>>m;queue&l…

基于uniapp cli项目开发的老项目,运行报错path.replace is not a function

项目&#xff1a;基于uniapp cli的微信小程序老项目 问题&#xff1a;git拉取代码&#xff0c;npm安装包时就报错&#xff1b; cnpm能安装成功包&#xff0c;运行报错 三种方法尝试解决&#xff1a; 更改代码&#xff0c;typeof pathstring的话&#xff0c;才走path.replace…