open_clip仓库成分与模型文件model.py 介绍

起因:

 在DA-CLIP的开源库的DA-CLIP.md中自述该项目基于CLIP 和open_clip,在之前的退化类型检测中 我一度以为仓库只是使用了CLIP 的源码, 然而当发现缺少da-clip的模型名称时,我发现DA-CLIP使用的完全是open_clip的代码版本,专门配置了da-clip.json在open_clip的model_configs

This repository is based on the OpenAI's CLIP (Contrastive Language-Image Pre-training) and open_clip.

We extend the CLIP to a degradation-aware version (DA-CLIP) which predicts both degradation embedding and clean content embedding from corrupted images.

Then we can use the embeddings to improve image restoration performance and assist unified image restoration.

Moreover, we use the pretrained ViT CLIP model (ViT-B/32 on LAION-2B) and add an additional controller to control the image encoder.

该库基于OpenAI的CLIP(对比语言图像预训练)和open_clip。
我们将CLIP扩展到退化感知版本(DA-CLIP),该版本预测退化嵌入和从损坏图像中嵌入干净内容。

然后,我们可以利用该嵌入来提高图像恢复性能,帮助统一图像恢复。

此外,我们使用预训练的ViT CLIP模型(LAION-2B上的ViT- b /32),并添加一个额外的控制器来控制图像编码器。

 纵观DA-CLIP代码,关于CLIP模块,基本是从open_clip库上进行扩展。对于clip代码使用已有博主进行说明

CLIP模型原理与代码实现详解-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/weixin_38252409/article/details/133828294

 背景:

然而CSDN上对open_clip项目的介绍寥寥,以下项目虽有涉猎但都未对其仓库源码进行解析。

ImageNet零样本准确率首次超过80%!OpenCLIP:性能最强的开源CLIP模型-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/amusi1994/article/details/129036171?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171120819416800227464964%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=171120819416800227464964&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-1-129036171-null-null.142%5Ev99%5Epc_search_result_base6&utm_term=OpenCLIP&spm=1018.2226.3001.4449

项目解读:open_clip

结构

  • docs/ - 包含项目文档和使用说明。
  • src/ - 包含项目的主要源代码。
  • tests/ - 包含项目测试代码。
  • setup.py - 用于安装和项目的 Python 包设置文件。

src下的文件夹,包含open_clip和training,

由于DA-CLIP与open_clip数据集、模型结构等不同,其中DA-CLIP 主要使用了open_clip文件夹

该文件夹下:

  • model.py - 定义了 CLIP 模型的结构,包括图像编码器和文本编码器。这是模型训练和推理的核心部分。
  • config.py - 包含了模型配置的类和函数,用于设置模型的不同参数,如学习率、批次大小等。
  • tokenizer.py - 包含了文本处理的分词器,用于将文本转换为模型可以理解的格式。
  • trainer.py - 包含了模型训练的主要逻辑,如设置优化器、损失函数和训练循环。
  • evaluator.py - 包含了评估模型性能的代码,通常用于在验证集或测试集上计算指标。
  • utils.py - 包含了一些实用工具函数,如数据处理、日志记录等。
  • transform.py - 包含了数据预处理和增强的转换函数,用于准备输入数据。
  • model_configs:包含各类模型配置,如coca、convnext、EVA、Vit、RN50等json文件

open_clip 目录下,每个文件都有其独特的价值和作用,但如果要挑选一个文件进行深入解读,model.py 可能是最值得关注的。这是因为 model.py 定义了 CLIP 模型的核心结构,它直接关联到模型的性能和功能。以下是对 model.py 文件的详细解读:

model.py 的作用

model.py 文件定义了 CLIP 模型的架构,包括图像编码器和文本编码器的设计。CLIP 模型是一个双流(two-stream)模型,它分别处理图像和文本输入,并通过对比学习(contrastive learning)的方式,学习图像和文本之间的对应关系。

主要组件

  1. 图像编码器(Image Encoder): 通常使用预训练的卷积神经网络(如 ResNet 或 Vision Transformer)作为基础,用于提取图像特征。

  2. 文本编码器(Text Encoder): 通常基于 Transformer 架构,用于处理文本输入并提取文本特征。文本编码器可能使用 BERT 或类似的 Transformer 变体。

  3. 投影头(Projection Heads): 用于将图像和文本编码器的输出映射到共同的特征空间,以便进行相似性比较。

  4. 损失函数(Loss Function): CLIP 模型使用对比损失函数来训练,这要求模型能够区分匹配的图像-文本对和不匹配的对。

关键概念

  • 对比学习(Contrastive Learning): 一种自监督学习方法,模型通过比较正样本对和负样本对来学习特征表示。

  • 多模态学习(Multimodal Learning): 涉及处理和理解多种类型数据(如图像和文本)的机器学习方法。

  • 零样本学习(Zero-Shot Learning): 模型能够在没有见过特定类别的样本的情况下进行分类或识别。

代码结构

model.py 文件包含以下部分:

  • 类定义(Class Definitions): 定义了图像编码器、文本编码器和整个 CLIP 模型的结构。

  • 前向传播(Forward Pass): 描述了数据如何通过模型,以及如何计算图像和文本的特征表示。

  • 初始化方法(Initialization Methods): 描述了模型权重的初始化过程,这对于训练的稳定性和收敛速度至关重要。

  • 损失计算(Loss Computation): 实现了对比损失函数,用于训练过程中的优化。

通过对 model.py 文件的深入理解,可以更好地把握 CLIP 模型的工作原理,以及如何修改和扩展模型以适应不同的应用场景。这个文件是进行模型训练和评估的基础,对于任何想要深入了解或贡献于 OpenCLIP 项目的人来说都是必读的。

该文件的CLIP类如下

class CLIP(nn.Module):output_dict: torch.jit.Final[bool]def __init__(self,embed_dim: int,vision_cfg: CLIPVisionCfg,text_cfg: CLIPTextCfg,quick_gelu: bool = False,init_logit_scale: float = np.log(1 / 0.07),init_logit_bias: Optional[float] = None,cast_dtype: Optional[torch.dtype] = None,output_dict: bool = False,):super().__init__()self.output_dict = output_dictself.visual = _build_vision_tower(embed_dim, vision_cfg, quick_gelu, cast_dtype)text = _build_text_tower(embed_dim, text_cfg, quick_gelu, cast_dtype)self.transformer = text.transformerself.context_length = text.context_lengthself.vocab_size = text.vocab_sizeself.token_embedding = text.token_embeddingself.positional_embedding = text.positional_embeddingself.ln_final = text.ln_finalself.text_projection = text.text_projectionself.text_pool_type = text.pool_typeself.register_buffer('attn_mask', text.attn_mask, persistent=False)self.logit_scale = nn.Parameter(torch.ones([]) * init_logit_scale)if init_logit_bias is not None:self.logit_bias = nn.Parameter(torch.ones([]) * init_logit_bias)else:self.logit_bias = Nonedef lock_image_tower(self, unlocked_groups=0, freeze_bn_stats=False):# lock image tower as per LiT - https://arxiv.org/abs/2111.07991self.visual.lock(unlocked_groups=unlocked_groups, freeze_bn_stats=freeze_bn_stats)@torch.jit.ignoredef set_grad_checkpointing(self, enable=True):self.visual.set_grad_checkpointing(enable)self.transformer.grad_checkpointing = enabledef encode_image(self, image, normalize: bool = False):features = self.visual(image)return F.normalize(features, dim=-1) if normalize else featuresdef encode_text(self, text, normalize: bool = False):cast_dtype = self.transformer.get_cast_dtype()x = self.token_embedding(text).to(cast_dtype)  # [batch_size, n_ctx, d_model]x = x + self.positional_embedding.to(cast_dtype)x = x.permute(1, 0, 2)  # NLD -> LNDx = self.transformer(x, attn_mask=self.attn_mask)x = x.permute(1, 0, 2)  # LND -> NLDx = self.ln_final(x)  # [batch_size, n_ctx, transformer.width]x, _ = text_global_pool(x, text, self.text_pool_type)if self.text_projection is not None:if isinstance(self.text_projection, nn.Linear):x = self.text_projection(x)else:x = x @ self.text_projectionreturn F.normalize(x, dim=-1) if normalize else xdef get_logits(self, image, text):image_features = self.encode_image(image, normalize=True)text_features = self.encode_text(text, normalize=True)image_logits = self.logit_scale.exp() * image_features @ text_features.Tif self.logit_bias is not None:image_logits += self.logit_biastext_logits = image_logits.Treturn image_logits, text_logitsdef forward(self,image: Optional[torch.Tensor] = None,text: Optional[torch.Tensor] = None,):image_features = self.encode_image(image, normalize=True) if image is not None else Nonetext_features = self.encode_text(text, normalize=True) if text is not None else Noneif self.output_dict:out_dict = {"image_features": image_features,"text_features": text_features,"logit_scale": self.logit_scale.exp()}if self.logit_bias is not None:out_dict['logit_bias'] = self.logit_biasreturn out_dictif self.logit_bias is not None:return image_features, text_features, self.logit_scale.exp(), self.logit_biasreturn image_features, text_features, self.logit_scale.exp()

这个类定义了 CLIP 模型的结构和行为。

初始化

  def __init__(self,embed_dim: int,vision_cfg: CLIPVisionCfg,text_cfg: CLIPTextCfg,quick_gelu: bool = False,cast_dtype: Optional[torch.dtype] = None,output_dict: bool = False,):super().__init__()self.output_dict = output_dictself.visual = _build_vision_tower(embed_dim, vision_cfg, quick_gelu, cast_dtype)text = _build_text_tower(embed_dim, text_cfg, quick_gelu, cast_dtype)self.transformer = text.transformerself.context_length = text.context_lengthself.vocab_size = text.vocab_sizeself.token_embedding = text.token_embeddingself.positional_embedding = text.positional_embeddingself.ln_final = text.ln_finalself.text_projection = text.text_projectionself.register_buffer('attn_mask', text.attn_mask, persistent=False)self.logit_scale = nn.Parameter(torch.ones([]) * np.log(1 / 0.07))
参数解释
  • self: 指向类的实例。
  • embed_dim: 嵌入维度,这是模型中嵌入层的维度。
  • vision_cfg: 图像配置对象,它包含了构建图像处理部分(视觉塔)所需的配置信息。
  • text_cfg: 文本配置对象,它包含了构建文本处理部分(文本塔)所需的配置信息。
  • quick_gelu: 布尔值,指示是否使用快速的GELU(Gaussian Error Linear Unit)激活函数。
  • cast_dtype: 可选参数,指定数据类型,用于将模型参数转换为指定的数据类型。
  • output_dict: 布尔值,指示模型输出是否应该是一个字典。
方法体解释
  • super().__init__(): 调用父类的构造函数。
  • self.output_dict: 存储传入的output_dict参数,这可能影响模型输出的格式。
  • self.visual: 通过调用一个内部函数_build_vision_tower来构建视觉塔,并存储结果。
  • text: 通过调用一个内部函数_build_text_tower来构建文本塔,并存储结果。
  • self.transformer: 从文本塔中提取变换器(transformer)模块。
  • self.context_length: 存储文本塔的上下文长度。
  • self.vocab_size: 存储文本塔的词汇表大小。
  • self.token_embedding: 存储文本塔的词嵌入层。
  • self.positional_embedding: 存储文本塔的位置嵌入层。
  • self.ln_final: 存储文本塔的最终层归一化(Layer Normalization)。
  • self.text_projection: 存储文本塔的文本投影层。
  • self.register_buffer('attn_mask', text.attn_mask, persistent=False): 注册一个缓冲区,用于存储文本塔的注意力掩码(attention mask),这个掩码在自注意力机制中用于指示哪些位置应该被模型关注。
  • self.logit_scale: 创建一个可学习的参数,用于缩放模型的输出(logits),初始化为一个全1的向量,乘以一个基于经验的对数缩放因子。

锁定参数

下面两个方法的目的是为了在训练过程中冻结图像塔和文本塔的参数,这与 LiT 方法的核心思想相符,即在对比学习(contrastive learning)过程中,只更新文本模型的参数,而保持图像模型的参数不变。这样做可以利用预训练图像模型的强大特征提取能力,同时通过文本模型来适应新任务,实现零样本(zero-shot)迁移学习。 

    def lock_image_tower(self, unlocked_groups=0, freeze_bn_stats=False):# lock image tower as per LiT - https://arxiv.org/abs/2111.07991self.visual.lock(unlocked_groups=unlocked_groups, freeze_bn_stats=freeze_bn_stats)def lock_text_tower(self, unlocked_layers: int = 0, freeze_layer_norm: bool = True):for param in self.transformer.parameters():param.requires_grad = Falseself.token_embedding.requires_grad = Falseself.positional_embedding.requires_grad = Falseself.text_projection.requires_grad = False

这段代码定义了两个方法,lock_image_towerlock_text_tower,它们似乎是用于控制神经网络模型中的图像塔(image tower)和文本塔(text tower)的参数更新机制。CLIP类实现了类似于 LiT(Locked-image Tuning)的机制,这是一种在图像和文本模型对齐时锁定预训练图像模型参数的技术,如在论文 "LiT: Zero-Shot Transfer with Locked-image text Tuning" 中所描述的。

lock_image_tower 方法
  • unlocked_groups 参数:指定哪些层组应该保持未锁定(即可训练的)。默认值为 0,意味着所有层组都被锁定。
  • freeze_bn_stats 参数:决定是否冻结批量归一化(Batch Normalization, BN)层的统计数据。如果设置为 True,则BN层的运行时统计数据(均值和方差)不会在训练过程中更新。

在这个方法中,调用了 self.visual.lock(),这是一个自定义的方法,用于锁定图像塔中的参数。这个方法可能会根据 unlocked_groups 参数来决定哪些层或层组应该保持可训练状态。

lock_text_tower 方法
  • unlocked_layers 参数:指定文本塔中应该保持未锁定的层的数量。默认值为 0,意味着所有层都被锁定。
  • freeze_layer_norm 参数:决定是否冻结层归一化(Layer Normalization, LN)的参数。如果设置为 True,则LN层的参数不会在训练过程中更新。

在这个方法中,遍历了 self.transformer 中的所有参数,并将它们的 requires_grad 属性设置为 False,这意味着在训练过程中这些参数不会更新。此外,还冻结了文本塔中的词嵌入(token_embedding)、位置嵌入(positional_embedding)和文本投影(text_projection)的参数。

set_grad_checkpointing 方法设置梯度检查点

   def set_grad_checkpointing(self, enable=True):self.visual.set_grad_checkpointing(enable)self.transformer.grad_checkpointing = enable
  • enable: 布尔值,指示是否启用梯度检查点。当启用时,可以减少模型训练过程中的内存消耗,但可能会增加计算成本。

这个方法在模型的两个主要组件,visual(视觉塔)和transformer(文本塔)上设置梯度检查点。梯度检查点是一种内存优化技术,它允许模型在前向传播过程中保存中间激活的梯度,从而在反向传播时减少内存使用。

encode_image 方法

    def encode_image(self, image, normalize: bool = False):features = self.visual(image)return F.normalize(features, dim=-1) if normalize else features
  • image: 输入的图像数据。
  • normalize: 布尔值,指示是否对编码后的特征进行归一化。

这个方法使用模型的视觉塔来编码输入的图像数据。如果normalize参数为True,则使用F.normalize函数对特征进行归一化处理,否则直接返回特征。

encode_text 方法

    def encode_text(self, text, normalize: bool = False):cast_dtype = self.transformer.get_cast_dtype()x = self.token_embedding(text).to(cast_dtype)  # [batch_size, n_ctx, d_model]x = x + self.positional_embedding.to(cast_dtype)x = x.permute(1, 0, 2)  # NLD -> LNDx = self.transformer(x, attn_mask=self.attn_mask)x = x.permute(1, 0, 2)  # LND -> NLDx = self.ln_final(x)  # [batch_size, n_ctx, transformer.width]# take features from the eot embedding (eot_token is the highest number in each sequence)x = x[torch.arange(x.shape[0]), text.argmax(dim=-1)] @ self.text_projectionreturn F.normalize(x, dim=-1) if normalize else x
  • text: 输入的文本数据。
  • normalize: 布尔值,指示是否对编码后的文本特征进行归一化。

这个方法首先将文本数据通过词嵌入层和位置嵌入层来获取嵌入表示,然后将这些嵌入表示转换为适合transformer的格式。接下来,使用transformer处理这些嵌入,并通过层归一化(self.ln_final)进行归一化。最后,通过文本投影层(self.text_projection)将嵌入映射到最终的特征空间,并进行归一化处理(如果normalizeTrue)。

前向传播函数 

 def forward(self,image: Optional[torch.Tensor] = None,text: Optional[torch.Tensor] = None,):image_features = self.encode_image(image, normalize=True) if image is not None else Nonetext_features = self.encode_text(text, normalize=True) if text is not None else Noneif self.output_dict:return {"image_features": image_features,"text_features": text_features,"logit_scale": self.logit_scale.exp()}return image_features, text_features, self.logit_scale.exp()

段代码定义了一个名为 forward 的方法,它是神经网络模型中的前向传播函数。该方法接收图像和文本作为输入,并输出它们的特征表示以及用于缩放 logits 的比例因子。这个方法是模型核心功能的一部分,负责将输入数据转换为模型可以处理的嵌入向量。

参数解释
  • self: 指向类的实例。
  • image: 输入的图像数据,类型为 torch.Tensor。如果为 None,则表示没有图像输入。
  • text: 输入的文本数据,类型为 torch.Tensor。如果为 None,则表示没有文本输入。
方法体解释
  • image_features: 如果提供了图像输入,使用 self.encode_image 方法对图像进行编码,并在返回前进行归一化处理。如果没有图像输入,则设置为 None
  • text_features: 如果提供了文本输入,使用 self.encode_text 方法对文本进行编码,并在返回前进行归一化处理。如果没有文本输入,则设置为 None
  • if self.output_dict: 判断是否以字典格式输出。如果 output_dict 属性为 True,则将图像特征、文本特征和 logits 缩放因子封装成一个字典返回。否则,将这三个值作为独立的返回值。
返回值
  • 如果 self.output_dict 为 True,则返回一个包含图像特征、文本特征和 logits 缩放因子的字典。
  • 如果 self.output_dict 为 False,则返回一个包含图像特征、文本特征和 logits 缩放因子的元组。
总结

forward 方法是模型的入口点,它根据输入的图像和文本数据,通过模型的编码器生成对应的特征表示。这些特征表示可以用于后续的多模态任务,例如图像-文本匹配、联合嵌入学习或零样本分类等。此外,该方法还提供了 logits 缩放因子,这在某些情况下(如对比学习或分类任务)可能是必需的。通过灵活的输出格式,该方法可以适应不同的使用场景和后处理需求。

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

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

相关文章

16.JRE和JDK

程序员在编写代码的时候其实是需要一些环境,例如我们之前写的HelloWorld。我们需要的东西有JVM、核心类库、开发工具。 1、JVM(Java Virtual Machine):Java虚拟机,真正运行Java程序的地方。没有虚拟机,代码…

C语言例4-9:格式字符s的使用例子

代码如下&#xff1a; //格式字符s的使用例子 #include<stdio.h> int main(void) {printf("%s,%5s,%-5s\n","Internet","Internet","Internet");//以三种不同格式&#xff0c;输出字符串printf("%10.5s,%-10.5s,%4.5s\n&q…

rtthread studio 基于bsp生成代码stm32l475正点原子潘多拉,以及硬件配置

1、基于bsp生成代码 rtthread studio 很强大的一个功能就是可以根据芯片或者bsp 生成驱动代码&#xff0c;而且rtthread内核 已经集成到了代码中&#xff01;&#xff01;只需要关注于如何使用硬件和设备完成我们想要的功能就可以&#xff1b; 它的官网文档也特别详细&#x…

实用有趣的宝藏网站推荐!【第二期】

上次给大家推荐了10个宝藏网站&#xff08;http://t.csdnimg.cn/qcRWY&#xff09;&#xff0c;这次我又来啦&#xff01; 话不多说&#xff0c;直接开始&#xff01; 先收藏&#xff0c;防止以后找不到了&#xff01; 整理不易&#xff0c;顺便把赞留下吧&#xff01; 1. 爱…

江苏开放大学2024年春《市政管理学050011》第一次形考作业参考答案

答案&#xff1a;更多答案&#xff0c;请关注【电大搜题】微信公众号 答案&#xff1a;更多答案&#xff0c;请关注【电大搜题】微信公众号 答案&#xff1a;更多答案&#xff0c;请关注【电大搜题】微信公众号 电大搜题 多的用不完的题库&#xff0c;支持文字、图片搜题…

代码随想录算法训练营Day55 ||leetCode 583. 两个字符串的删除操作 || 72. 编辑距离

583. 两个字符串的删除操作 这道题的状态方程比上一题简单一些 初始化如下 class Solution { public:int minDistance(string word1, string word2) {vector<vector<int>> dp(word1.size() 1, vector<int>(word2.size() 1));for (int i 0; i < word1…

Linux 基础IO [缓冲区文件系统]

&#x1f493;博主CSDN主页:麻辣韭菜&#x1f493;   ⏩专栏分类&#xff1a;Linux知识分享⏪   &#x1f69a;代码仓库:Linux代码练习&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多Linux知识   &#x1f51d; 目录 前言 一.Linux下一切皆文件 二.缓冲…

在线接口文档预言方案

在线接口文档预言方案 要求&#xff1a; ​ 支持自动生成接口文档 ​ 能够支持在线测试(http&#xff0c;websocket) ​ 对代码没有侵入性 一、目前涉及的相关技术收集 sudo apt update #更新数据 sudo apt upgrade #更新软件 sudo apt install openssh-server #下载安装…

14.黑盒测试

黑盒测试、白盒测试考题固定&#xff0c;重视&#xff01;&#xff01;&#xff01; 等价类、边界值、场景法&#xff1b;考察频率高&#xff01;&#xff01;&#xff01; 因果图&#xff0c;偶尔考&#xff1b;要能看懂因果图&#xff0c;结合题干填写缺失的部分内容&#x…

Redis中的客户端(三)

客户端 身份验证 客户端状态的authenticated属性用于记录客户端是否通过了身份验证: typedef struct redisClient {// ...int authenticated;// ... } redisClient;如果authnticated的值为0&#xff0c;那么表示客户端未通过身份验证&#xff1b;如果authenticated的值为1&a…

智慧酒店(二):AI智能分析网关V4视频分析技术在酒店管理中的应用

一、人工智能技术如何应用在酒店管理中&#xff1f; 随着科技的飞速发展&#xff0c;人工智能技术已经逐渐渗透到我们生活的方方面面&#xff0c;其中&#xff0c;酒店管理行业便是其应用的重要领域之一。人工智能技术以其高效、精准的特点&#xff0c;为酒店管理带来了革命性…

修改nuxtjs项目中的浏览器图标步骤

处理步骤&#xff1a; 打开配置页面 使用el-upload 上传图片到后台 后台把图片转为ico&#xff0c;返回图标路径 配置页面修改本页面预览图&#xff0c;点击保存&#xff0c;修改的数据库。 通知nuxt布局页面&#xff0c;修改head节点中的图标属性&#xff0c;…

《VulnHub》Lampião:1

title: 《VulnHub》Lampio&#xff1a;1 date: 2024-03-28 21:37:49 updated: 2024-03-28 21:37:50 categories: WriteUp&#xff1a;Cyber-Range excerpt: 关键技术&#xff1a;主机发现&#xff0c;端口扫描、服务探测、操作系统探测&#xff0c;对开放的端口探测漏洞&#x…

寒冬继续!飞书发全员信 “适当精简团队规模”

多精彩内容在公众号。 3月26日飞书CEO谢欣发布全员信&#xff0c;宣布进行组织调整&#xff0c;同时为受到影响的“同学”提供补偿方案和转岗机会。 在致员工的一封信中&#xff0c;谢欣坦诚地指出&#xff0c;尽管飞书的团队人数众多&#xff0c;但组织结构的不够紧凑导致了工…

fastadmin学习05-开启debug以及配置

FastAdmin 框架提供了对 .env 环境变量配置的支持&#xff0c;并附带一个默认示例文件 .env.sample。在安装后&#xff0c;框架并不会自动启用 env 环境变量&#xff0c;需要手动将 .env.sample 复制为 .env 并进行配置。 如果不开启.env会读取database.php中的配置 下面测试…

redis缓存穿透、缓存击穿、缓存雪崩及其解决方法

缓存穿透、缓存击穿、缓存雪崩是redis的三大问题。 在介绍这三大问题之前&#xff0c;我们需要先了解Redis作为一个缓存中间件&#xff0c;在项目中是如何工作的。首先看一下在没有缓存中间件的时候的系统数据访问的架构图&#xff1a; 客户端发起一个查询请求的时候&#xff…

Maya 2024 for Mac/Win:重塑三维创意世界的利器

在数字化浪潮汹涌的当下&#xff0c;三维图形软件早已成为创意产业不可或缺的重要工具。而在这其中&#xff0c;Maya 2024以其卓越的性能和丰富的功能&#xff0c;赢得了无数设计师的青睐。无论是Mac还是Win平台&#xff0c;Maya 2024都能为您的三维创作提供强大的支持。 Maya…

算法系列--动态规划--背包问题(2)--01背包拓展题目

&#x1f495;"2024.3.28小米汽车发布"&#x1f495; 作者&#xff1a;Lvzi 文章主要内容&#xff1a;算法系列–动态规划–背包问题(2)–01背包拓展题目 大家好,今天为大家带来的是算法系列--动态规划--背包问题(2)--01背包拓展题目 1.分割等和⼦集 链接: https:/…

史上最全-Java面试题(涵盖基础、高级、框架、微服务、中间件、大厂真题等28个大类超3000+面试题,全部附带详细答案)

3月4月又到了一年一度的跳槽黄金期,无论几年经验,也无论技术能力如何,跳槽前都离不开面试准备,其中刷面试题是重中之重。 刷面试题的时候一大痛点就是太分散了,需要自己根据知识点一项一项的去搜,容易遗漏知识点而且面试题质量无法保证,非常痛苦,基于此我花了两个月的…

AOP切入点表达式基本格式

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 官方地址 https://docs.spring.io/spring-framework/reference/core/aop/ataspectj/pointcuts.html AOP切入点表达式基本格式如下&#xff1a; execution(modifiers-patte…