当前位置: 首页 > news >正文

训练CV模型常用的方法与技巧

最近参加一个CV比赛,看到有参赛者分享了自己训练图像识别模型时常用到的小技巧,故对其进行记录、整理,方便未来继续学习。整理了很多,它们不一定每次有用,但请记在心中,说不定未来某个任务它们就发挥了作用!

主要从以下9个方面进行介绍:

  1. 图像增强

  1. 更好的模型

  1. 学习率和scheduler

  1. 优化器

  1. 正则化手段

  1. 标签平滑

  1. 知识蒸馏

  1. 伪标签

  1. 错误分析

1.图像增强

以下列出了许多增强方式,有的甚至没见过,但是也不是每一种增强方式都是有利的,需要自己根据任务和实验进行选择合适的增强方式。

颜色增强

Color Skew:

这种增强通过将每个通道乘以随机选择的系数来随机调整图像的色调、饱和度和亮度。系数从 [0:6;1:4] 的范围内选择,以确保生成的图像不会过于失真。

def color_skew(image):h, s, v = cv2.split(image)h = h * np.random.uniform(low=0, high=6)s = s * np.random.uniform(low=1, high=4)v = v * np.random.uniform(low=0, high=6)return cv2.merge((h, s, v))

RGB Norm:

这种增强通过从每个通道的值中减去每个通道的平均值并除以通道的标准差来标准化图像的 RGB 通道。这有助于标准化图像中的值,并可以提高模型的性能。

def rgb_norm(image):r, g, b = cv2.split(image)r = (r - np.mean(r)) / np.std(r)g = (g - np.mean(g)) / np.std(g)b = (b - np.mean(b)) / np.std(b)return cv2.merge((r, g, b))

Black and White:

这种增强通过将图像转换为灰度色彩空间将图像转换为黑白。

defblack_and_white(image):return cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

Ben Graham: Greyscale + Gaussian Blur:

这种增强将图像转换为灰度并应用高斯模糊来平滑图像中的任何噪声或细节。

def ben_graham(image):image = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)image = cv2.GaussianBlur(image, (5, 5), 0)return image

Hue, Saturation, Brightness:

这种增强将图像转换为 HLS 色彩空间,HLS 色彩空间将图像分成色调、饱和度和亮度通道。

def hsb(image):return cv2.cvtColor(image, cv2.COLOR_RGB2HLS)

LUV Color Space:

这种增强将图像转换为 LUV 色彩空间,该空间旨在在感知上保持一致并实现更准确的色彩比较。

def luv(image):return cv2.cvtColor(image, cv2.COLOR_RGB2LUV)

Alpha Channel:

这种增强为图像添加了一个 alpha 通道,可用于增加透明效果。

def alpha_channel(image):return cv2.cvtColor(image, cv2.COLOR_RGB2RGBA)

YZ Color Space:

这种增强将图像转换为 XYZ 颜色空间,这是一种与设备无关的颜色空间,可以实现更准确的颜色表示。

def xyz(image):return cv2.cvtColor(image, cv2.COLOR_RGB2XYZ)

Luma Chroma:

这种增强将图像转换为 YCrCb 颜色空间,它将图像分成亮度(亮度)和色度(颜色)通道。

def luma_chroma(image):return cv2.cvtColor(image, cv2.COLOR_RGB2YCrCb)

CIE Lab:

这种增强将图像转换为 CIE Lab 颜色空间,该颜色空间设计为感知均匀,可实现更准确的颜色比较。

def cie_lab(image):return cv2.cvtColor(image, cv2.COLOR_RGB2Lab)

YUV Color Space:

这种增强将图像转换为 YUV 颜色空间,它将图像分成亮度(亮度)和色度(颜色)通道。

def yuv(image):return cv2.cvtColor(image, cv2.COLOR_RGB2YUV)

Center Crop:

这种增强随机裁剪长宽比为 [3/4,4/3] 的矩形区域,然后按 [8%,100%] 之间的因子随机缩放裁剪,最后将裁剪调整为 img_{size} * img_{size} img_{size} * img_{size} 正方形。这是在每个批次上随机完成的。

transforms.CenterCrop((100, 100))

Flippings:

这种增强增加了图像随机水平翻转的概率。例如,概率为 0.5,图像有 50% 的机会被水平翻转。

def flippings(image):if np.random.uniform() < 0.5:image = cv2.flip(image, 1)return image

Random Crop:

这种增强从图像中随机裁剪出一个矩形区域。

transforms.RandomCrop((100, 100))

Random Resized Crop:

这种增强从图像中随机调整大小和裁剪矩形区域。

transforms.RandomResizedCrop((100, 100))

Color Jitter:

这种增强随机调整图像的亮度、对比度、饱和度和色调。

transforms.ColorJitter(brightness=0.5, contrast=0.5, saturation=0.5, hue=0.5)

Random Affine:

这种增强对图像随机应用仿射变换,包括旋转、缩放和剪切。

transforms.RandomAffine(degrees=45,translate=(0.1,0.1),scale=(0.5,2.0),shear=45)

Random Horizontal Flip:

以 0.5 的概率随机水平翻转图像。

transforms.RandomHorizontalFlip()

Random Vertical Flip:

这种增强以 0.5 的概率随机垂直翻转图像。

transforms.RandomVerticalFlip()

Random Perspective:

这种增强随机对图像应用透视变换。

transforms.RandomPerspective()

Random Rotation:

这种增强将图像随机旋转给定的度数范围。

transforms.RandomRotation(degrees=45)

Random Invert:

这种增强会随机反转图像的颜色。

transforms.RandomInvert()

Random Posterize:

这种增强随机减少了用于表示每个像素值的位数,从而产生了分色效果。

transforms.RandomPosterize(bits=4)

Random Solarize:

这种增强对图像随机应用曝光效果,其中高于某个强度阈值的像素被反转。

transforms.RandomSolarize(threshold=128)

Random Autocontrast:

这种增强通过将强度值拉伸到整个可用范围来随机调整图像的对比度。

transforms.RandomAutocontrast()

Random Equalize:

这种增强随机地均衡了图像的直方图,从而增加了对比度。

transforms.RandomEqualize()

更高级的增强方式

除了以上的基础增强方式,还有一些更高级的增强方式。

Auto Augment:

Auto Augment 是一种增强方法,它使用强化学习来搜索给定数据集的最佳增强策略。它已被证明可以提高图像分类模型的性能。

from autoaugment import AutoAugmentauto_augment = AutoAugment()
image = auto_augment(image)

Fast Autoaugment:

Fast Autoaugment 是 Auto Augment 方法的更快实现。它使用神经网络来预测给定数据集的最佳扩充策略。

from fast_autoaugment import FastAutoAugmentfast_auto_augment = FastAutoAugment()
image = fast_auto_augment(image)

Augmix:

Augmix 是一种增强方法,它将多个增强图像组合起来创建一个单一的、更加多样化和逼真的图像。它已被证明可以提高图像分类模型的鲁棒性和泛化能力。

from augmix import AugMixaug_mix = AugMix()
image = aug_mix(image)

Mixup/Cutout:

Mixup 是一种增强方法,通过线性插值像素值来组合两个图像。Cutout 是一种从图像中随机删除矩形区域的增强方法。这些方法已被证明可以提高图像分类模型的鲁棒性和泛化能力。

"You take a picture of a cat and add some "transparent dog" on top of it. The amount of transparency is a hyperparam."x=lambda*x1+(1-lambda)x2,y=lambda*x1+(1-lambda)y2

Test Time Augmentations(TTA)

图像增强不仅在训练期间很有用,而且在测试期间也很有用。用在测试阶段,人们称它为TTA,只需将测试集的图像进行多次增强,应用于预测并对结果进行平均即可。这种方法能增强预测的鲁棒性,但是相应的,会增加时间。对测试集做增强,不适应太高级的增强方式,常见的如改变图像尺度,crop不同的地方,进行翻转等。

个人感觉这种做法应该只适用于比赛中吧~

2.更好的模型

虽然下面的模型距离现在相隔几年,但是它们出众的性能,使得它们仍在比赛中占据前排,这几年虽然出了更好的模型,但很多模型未开源或是太大了,并未得到更广泛的应用。

tf_efficientnetv1,v2系列
seresnext

以及一些可以尝试的想法和模型。

Swin Transformer
BeIT Transformer
ViT Transformers

在backbone后面添加更多隐藏层

添加更多层可能是有益的,因为你可以使用它们来学习更多高级特征,但它也可以缓和大型预训练模型的微调,甚至损害模型性能。

逐层解冻

一个可以让你获得微小改进的简单技巧是随着训练的进行解冻预训练骨干的层。先添加更多层并冻结backbone,然后再慢慢解冻backbone的参数让其参与训练。

## Weight freezing
for param in model.parameters():param.requires_grad = False ## Weight unfreezing
for param in model.parameters():param.requires_grad = True

TensorFlow 中的权重冻结和解冻

## Weight freezing
layer.trainable = False
## Weight unfreezing
layer.trainable = True

3.学习率和scheduler

学习率和学习率调度器会影响模型的训练性能。改变学习率会对性能和训练收敛产生很大影响。

学习率schedulers

最近,One Cycle Cosine schedule 已经显示出在其在多个任务上提供更好的结果,你可以这样使用它:

One Cycle Cosine scheduling in PyTorch

from torch.optim.lr_scheduler import CosineAnnealingLR
optimizer = torch.optim.Adam(optimizer_grouped_parameters, lr=args.learning_rate, eps=args.adam_epsilon)
#这里使用
scheduler = CosineAnnealingLR(optimizer, T_max=num_train_optimization_steps)
num_training_steps = num_train_optimization_steps / args.gradient_accumulation_steps
# Update the scheduler
scheduler.step()
# step the learning rate scheduler here, 
# you will want to step the learning rate scheduler only once per optimizer step nothing more nothing less. 
# So in this case, it should be called before you expect the gradients to be applied.

tensorflow

## One Cycle Cosine scheduling in TensorFlow
optimizer = tf.keras.optimizers.Adam(learning_rate)
scheduler = tf.keras.optimizers.schedules.CosineDecay(learning_rate, decay_steps=num_training_steps)

使用学习率调度器的小技巧

  • 使用“Triangular”或“One Cyclic”方法进行学习率调整可以提供微妙但显着的改进——这些学习率调度的智能方法可以克服一些batch大小问题。

  • 花时间研究适合你的任务和你使用的模型的最佳学习率调度方法,这是你的模型如何收敛的一个非常重要的部分。

  • 学习率调度策略可用于训练具有较低batchsize或多个学习率的模型。

  • 众所周知,学习率很重要,所以首先优先尝试低学习率,再看看提高学习率是有助于还是损害模型的表现。

  • 在训练的后期增加学习率或多个学习率或batchsize或梯度累积或学习率调度策略有时会帮助模型更好地收敛,这是一种高级技术,因为有时它会损害性能但前提是你给予它太大的值 - 记得测试它。

  • 当使用梯度累积或多个学习率或高批量大小时,Loss scaling有助于减少损失方差并改善梯度流,但如果你试图通过增加批量大小来解决该问题,请尝试增加学习率,因为它有时会产生更好的性能。

4.优化器

现在很多人都在使用 Adam 或 AdamW。如果你希望从 Adam 优化器中获得最佳性能,则需要了解几件事:

找到最佳的权重衰减值可能很麻烦,依靠大量的实验(和运气)。

  • 另一个重要的超参数是 Adam 优化器中使用的 beta1 和 beta2,选择最佳值取决于你的任务和数据。许多新任务可以从较低的 beta1 和较高的 beta2 中获益,而在已建立的任务中它们会执行相反的操作。再强调一遍:实验将是你最好的朋友。

  • 在 Adam 优化器的世界中,首要规则是不要低估优化器 epsilon 值的重要性。寻找最佳权重衰减超参数的相同原则也适用于此。

  • 不要过度使用梯度裁剪范数——当你的梯度爆炸时它有时可能会有所帮助,反之亦然——它会阻止某些任务的收敛。

  • 梯度累积仍然可以提供一些微妙的好处,我通常累积大约 2 步的梯度,但如果你的 GPU 没有耗尽内存,你最多可以推送 8 步梯度累积。使用混合精度时,梯度累积也很有用。

另外,如果你以足够的时间去调整 SGD的动量,你可能会得到更好的结果,但这同样需要大量调整。

以下还有几个值得注意的优化器:

  • AdamW:这是 Adam 算法的扩展,可防止外层模型权重的指数权重衰减,并鼓励低于默认权重的惩罚超体积。

  • Adafactor:它被设计成具有低内存使用率和可扩展性。该优化器可以使用多个 GPU 提供显着的优化器性能。

  • Novograd:基本上是另一个类似 Adam 的优化器,但具有更好的特性。它是用于训练 bert-large 模型的优化器之一。

  • Ranger:Ranger 优化器是一个非常有趣的优化器,它在性能优化方面的解决方案中取得了不错的成绩,但它不是很出名或不受支持。

  • Lamb:由 GLUE 和 QQP 竞赛获胜者开发的 GPU 优化可重用 Adam 优化器。

  • Lookahead:一种流行的优化器,你可以在其他优化器之上使用它,它将为你提供一些性能提升。

5.正则化手段

使用dropout!在层之间添加dropout通常会产生更高的训练稳定性和更可靠的结果,请在隐藏层中使用。Dropout 也可用于小幅提高性能,在训练前尝试设置层 dropouts。任务和模型。

正则化:当你的神经网络过度拟合或欠拟合时,正则化可以极大地提升性能,对于正常的机器学习模型,L1 或 L2 正则化是可以的。

始终使用实验来检验想法:使用实验。实验。实验并尝试模型。

Multi Validations:你可以通过使用Multi Validations来提高模型对过度拟合的稳健性。然而,这是以计算时间为代价的。

6.标签平滑

论文链接:

When Does Label Smoothing Help?:

https://arxiv.org/pdf/1906.02629.pdf

核心公式一行概括之:

通常效果很好,可以在很多比赛中看到它的身影。以二分类任务为例,以下给出标签平滑的示例代码,可以直接用。

Tensorflow:

loss = BinaryCrossentropy(label_smoothing = label_smoothing)

Pytorch:

from torch.nn.modules.loss import _WeightedLossclass SmoothBCEwLogits(_WeightedLoss):def __init__(self, weight = None, reduction = 'mean', smoothing = 0.0, pos_weight = None):super().__init__(weight=weight, reduction=reduction)self.smoothing = smoothingself.weight = weightself.reduction = reductionself.pos_weight = pos_weight@staticmethoddef _smooth(targets, n_labels, smoothing = 0.0):assert 0 <= smoothing < 1with torch.no_grad(): targets = targets * (1.0 - smoothing) + 0.5 * smoothingreturn targetsdef forward(self, inputs, targets):targets = SmoothBCEwLogits._smooth(targets, inputs.size(-1), self.smoothing)loss = F.binary_cross_entropy_with_logits(inputs, targets,self.weight, pos_weight = self.pos_weight)if  self.reduction == 'sum': loss = loss.sum()elif  self.reduction == 'mean': loss = loss.mean()return loss

7.知识蒸馏

用一个大的teacher network来指导一个small network的学习。

步骤:

  • 训练大型模型:在数据上训练大型模型。

  • 计算软标签:使用训练好的大模型计算软标签。即大模型“软化”后softmax的输出

  • Student模型训练:在大模型的基础上,训练一个基于教师输出的学生模型作为额外的软标签损失函数,通过插值调整两个损失函数的比例。

8.伪标签

使用模型标记未标记的数据(例如测试数据),然后使用新的标记数据来重新训练模型。

步骤:

  • 训练教师模型:根据你拥有的数据训练模型。

  • 计算伪标签:使用训练好的大模型为未标注数据计算软标签。

  • 仅使用模型“确定”的目标:仅使用最高置信度的预测作为伪标签,以尽可能避免错误。(如果你不这样做,它可能不起作用)

  • Studnet 模型训练:根据你拥有的新标记数据训练学生模型。

9.错误分析

很多人在训练的时候,都只是一昧的调参,却不懂得分析,在公司里面也常常听到分析bad case这一词。它同样很重要,甚至有时候可以为我们提供额外的思路。可以为你节省大量时间的一个重要做法是使用你的模型来查找更难或损坏的数据样本。图像对于你的模型来说“更难”的原因可能有很多,例如,小目标对象、不同颜色、切断目标、无效注释等等。尝试从中找出原因,这可能能帮助你。

错误有时候是好消息!

这些它们正是将排行榜顶部大佬与其他参与者区分开来的样本。如果你很难解释你的模型发生了什么,那么看看你的模型遇到的验证样本。

Finding Your Model's Errors!

查找错误的最简单方法是根据模型的置信度分数对验证样本进行排序,并查看哪些样本的预测置信度最低。

mistakes_idx = [img_idx for img_idx in range(len(train)) if int(pred[img_idx] > 0.5) != target[img_idx]]
mistakes_preds = pred[mistakes_idx]
sorted_idx = np.argsort(mistakes_preds)[:20]
# Show the images of the sorted idx here..

总结

以上,整理了很多,它们不一定每次有用,但请记在心中,说不定未来某个任务它们就发挥了作用!

相关文章:

训练CV模型常用的方法与技巧

最近参加一个CV比赛&#xff0c;看到有参赛者分享了自己训练图像识别模型时常用到的小技巧&#xff0c;故对其进行记录、整理&#xff0c;方便未来继续学习。整理了很多&#xff0c;它们不一定每次有用&#xff0c;但请记在心中&#xff0c;说不定未来某个任务它们就发挥了作用…...

[Java·算法·中等]LeetCode22. 括号生成

每天一题&#xff0c;防止痴呆题目示例分析思路1题解1分析思路2题解2分析思路3题解3&#x1f449;️ 力扣原文 题目 数字 n 代表生成括号的对数&#xff0c;请你设计一个函数&#xff0c;用于能够生成所有可能的并且 有效的 括号组合。 示例 输入&#xff1a;n 3 输出&…...

Git项目合并实践

Git项目合并实践 一、前言 环境 操作系统&#xff1a;Windows 10 专业版 代码托管平台&#xff1a;Gitee 场景 同一个项目&#xff0c;在某一个时间点&#xff0c;被另外一个团队拷贝和修改&#xff0c;并且代码不在同一个仓库&#xff0c;最后需要合并项目 不是同一个项…...

C++实战md5、base64算法实现(附源码)

C++常用功能源码系列 文章目录 C++常用功能源码系列前言一、常用加密算法1. md5是什么二、源码1. md52. base64、decode总结前言 本文是C/C++常用功能代码封装专栏的导航贴。部分来源于实战项目中的部分功能提炼,希望能够达到你在自己的项目中拿来就用的效果,这样更好的服务…...

P6专题:P6 EPPM和PPM基本概念

目录 引言 Oracles Primavera P6 Enterprise Project Portfolio Management&#xff08;P6 EPPM&#xff09; Oracles Primavera P6 Professional Project Management 引言 Oracle Primavera系列软件专注于项目密集型企业&#xff0c;其整个项目生命周期内所有项目的组合管…...

【为什么事务@Transactional会失效】

在Spring框架中&#xff0c;Transactional注解用于声明一个方法需要被包含在事务中&#xff0c;以确保数据库操作的一致性和完整性。Transactional注解通常用于Service层或DAO层的方法上。 Transactional注解失效可能是由以下原因引起的&#xff1a; 注解未被正确声明或配置&a…...

NLP中的对话机器人——模型的评估

引言 本文是七月在线《NLP中的对话机器人》的视频笔记&#xff0c;主要介绍FAQ问答型聊天机器人的实现。 模型的评估 我们如何评估模型的好坏&#xff1f;由于我们的数据集没有提供测试数据&#xff0c;所以我们很难评估模型的好 坏。如果我们要做非常严谨的评估&#xff0c…...

数据挖掘知识规整与心得体会

一.大数据的特点&#xff1a; 数据多&#xff0c;类型多&#xff0c;更新快&#xff0c;更新内容多。 二.分类&#xff08;classification&#xff09;与混淆矩阵&#xff08;confusion matrix&#xff09; 这里的分类说的是二分类问题&#xff0c;比如说把人分为好人和坏人&a…...

修正一些formdesigner的一些bug与操作

之前集成了formdesigner表单设计器&#xff0c;但还是有些问题&#xff0c;所以进行一些bug修复与功能修正 一、之前组件布局的图标不见了 在main.js里增加下面一行 import /components/formdesigner/assets/iconfont/iconfont.js 效果如下&#xff1a; 二、选择列表没有数…...

前端网络安全

什么是同源策略同源指的是&#xff1a;协议、端口号、域名必须一致。他是浏览器的一个用于隔离潜在恶意文件的重要安全机制。限制了从同一个源加载的文档或脚本&#xff0c;与另一个源的资源进行交互。同源策略主要限制了三个方面&#xff1a;当前域下的js脚本不能够访问其他域…...

docker内存统计

在docker里top和在docker外top看内存都是没有变化的&#xff0c;但是用docker stats看mem uasge就一直在涨top命令和docker stats命令采集内存使用的方式不同所致。top命令采集的是当前进程的内存使用情况&#xff0c;而docker stats命令采集的是整个Docker容器的内存使用情况。…...

【IDEA】IDEA使用有道翻译引擎—详细配置步骤

目录 前言 步骤一&#xff1a;下载翻译工具Translate 步骤二&#xff1a;注册登录有道云平台 步骤三&#xff1a;配置有道翻译 前言 2022年10月 谷歌翻译已经不在中国了&#xff0c;所以IDEA配置谷歌翻译会出错。 步骤一&#xff1a;下载翻译工具Translate 打开idea设置set…...

js求解《初级算法》56.最长公共前缀

一、题目描述 编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀&#xff0c;返回空字符串 ""。 输入&#xff1a;strs ["flower","flow","flight"] 输出&#xff1a;"fl" 输入&#xff1a;strs ["…...

嵌入式Linux(二十四)系统烧写

将uboot&#xff0c;linux kernel&#xff0c;.dtb&#xff0c;rootfs烧写到板子上的EMMC上&#xff0c;避免断网导致不能运行。 1. MfgTool工具介绍 一路解压之后&#xff0c;得到以下两项&#xff1a; ①Profiles文件夹&#xff1a;后续烧写文件放到这个文件夹。  其中关注…...

【ECNU】3496. 贪吃的 xjj 和贪心的 oxx(C++)

目录 题目 输入格式 输出格式 样例 提示 思路 代码 题目 单点时限: 2.0 sec 内存限制: 256 MB oxx 与 xjj 终于到了 Xiamen&#xff0c;他们第一件事就是去吃当地著名的特产椰子饼。 他们共买了 n 盒礼盒&#xff0c;第 i 盒含 ai 块椰子饼。oxx 与 xjj 约定让 oxx …...

【iOS】设置背景渐变色

drawRect函数 主要负责iOS的绘图操作&#xff0c;程序会自动调用此方法进行绘图。我在这个函数中绘制渐变背景色。 方法定义&#xff1a; -(void)drawRect:(CGRect)rect; 重写此方法&#xff0c;执行重绘任务-(void)setNeedsDisplay; 标记为需要重绘&#xff0c;异步调用dra…...

Scrapy框架(高效爬虫)

文章目录一、环境配置二、创建项目三、scrapy数据解析四、基于终端指令的持久化存储1、基于终端指令2、基于管道3、数据同时保存至本地及数据库4、基于spider爬取某网站各页面数据5、爬取本页和详情页信息&#xff08;请求传参&#xff09;6、图片数据爬取ImagesPipeline五、中…...

程序设计语言-软件设计(二十一)

数据结构与算法&#xff08;二十&#xff09;快速排序、堆排序(四)https://blog.csdn.net/ke1ying/article/details/129269655 这篇主要讲的是 编译与解释、文法、正规式、有限自动机、表达式、传值与传址、多种程序语言特点。 编译的过程 解释型 和 编译型 编译型过程&#…...

【小破站下载工具】Python tkinter 实现网站下载工具,所有数据一键获取

目录前言开发环境本次项目案例步骤先展示下完成品的效果界面导入模块先创建个窗口功能按键主要功能代码编写功能一功能二功能三前言 最近很多同学想问我&#xff0c;怎么把几个代码的功能集合到一起&#xff1f; 很简单&#xff0c;写一个界面就行了&#xff0c;想要哪个代码…...

C51---IO口状态翻转

1.example #include "reg52.h" #include "intrins.h" //main.c(11): error C264: intrinsic _nop_: declaration/activation error,?????????? sbit led1 P3^7;//????,??????? sbit key1 P2^1; sbit key2 P2^0; void Delay50ms()…...

2023年春【移动计算技术】文献精读(一)-1 ||| 附:【Markdow语法】向上取整 向下取整。

沉默着走了有 // 多遥远 // 抬起头 // 蓦然间 // 才发现 // 一直倒退 // 倒退到原点 // 倔强坚持 // 对抗时间 “在光芒万丈之前,我们都要欣然接受眼下的难堪和不易,接受一个人的孤独和偶然无助,认真做好眼前的每件事,你想要的都会有。”——毕淑敏 🎯作者主页:追光者♂…...

Java 包装类的二进制操作

Integer 位翻转 位翻转就是将二进制左边的位与右边的位进行互换&#xff0c;reverse 是按位进行互换&#xff0c; reverseBytes 是按 byte 进行互换。 public static int reverse(int i)public static int reverseBytes(int i)来看个例子&#xff1a; int a 0x12345678; S…...

CSS居中之 { left:50%; top:50%; transform:translate(-50%,-50%); }

CSS居中之 { left:50%; top:50%; transform:translate(-50%,-50%); } left:50%; top:50%; transform:translate(-50%,-50%); left:50%; top:50%; transform:translate(-50%,-50%);也可以写成: left:50%; top:50%; translate: -50% -50%; left:50%; top:50%; translate: -50%…...

AcWing 4868. 数字替换(DFS + 剪枝优化)

AcWing 4868. 数字替换&#xff08;DFS 剪枝优化&#xff09;一、问题二、思路三、代码一、问题 二、思路 题目中要求变换次数最小&#xff0c;其实第一印象应该是贪心&#xff0c;即我们每一次都去成各位中最大的那个数字。但是这个想法很容易推翻。因为你这次乘了一个最大的…...

【教学典型案例】01.redis只管存不管删除让失效时间删除的问题

目录一&#xff1a;背景介绍二&#xff1a;redis1&#xff09;redis数据类型①String&#xff08;字符串&#xff09;②Hash&#xff08;哈希&#xff09;③List&#xff08;列表&#xff09;④Set&#xff08;集合&#xff09;2)缓存同步①设置有效期②同步双写③异步通知3&am…...

电话号码管理

电话号码管理 文章目录 电话号码管理综述链表结构initcreatedeleteallfreeANSI颜色转义颜色列表如下:字背景颜色范围:40--49 字颜色: 30--39输出特效格式控制:光标位置等的格式控制:Makefile顶层Makefilescripts Makefilesearch main init include display delete create all…...

Shell 教程

Shell 是一个用 C 语言编写的程序&#xff0c;它是用户使用 Linux 的桥梁。Shell 既是一种命令语言&#xff0c;又是一种程序设计语言。 Shell 是指一种应用程序&#xff0c;这个应用程序提供了一个界面&#xff0c;用户通过这个界面访问操作系统内核的服务。 Ken Thompson 的…...

Shader 阴影

阴影生成原理 以平行光为例&#xff0c;把相机移动到光源位置&#xff0c;计算阴影映射纹理&#xff08;shadowmap&#xff09;&#xff0c;这张shadowmap本质上是一张深度图&#xff0c;它记录了从该光源的位置出发、能看到的场景中距离它最近的表面位置&#xff08;深度信息&…...

【冲刺蓝桥杯的最后30天】day2

大家好&#x1f603;&#xff0c;我是想要慢慢变得优秀的向阳&#x1f31e;同学&#x1f468;‍&#x1f4bb;&#xff0c;断更了整整一年&#xff0c;又开始恢复CSDN更新&#xff0c;从今天开始更新备战蓝桥30天系列&#xff0c;一共30天&#xff0c;如果对你有帮助或者正在备…...

docker系列1:docker安装

传送门 docker官网地址&#xff1a; Docker: Accelerated, Containerized Application Development 安装地址&#xff1a;Install Docker Engine docker hub地址 docker hub&#xff1a;Docker 安装步骤 前置条件 由于安装docker&#xff0c;需要根据操作系统版本选择…...