基于FashionMnist数据集的自监督学习(对比式自监督学习SimCLR算法)

目录

一,对比式自监督学习

1.1 简介

1.2 常见算法

1.2.1 SimCLR (2020)

1.2.2 MoCo (2020)

1.2.3 BYOL (2021)

1.2.4 SimSiam (2021)

1.2.5 CLIP (2021)

1.2.6 DINO (2021)

1.2.7 SwAV (2020)

二,代码逻辑分析

2.1 整体目标与流程

2.2  数据增强:生成 “双胞胎” 图像

2.3 编码器:从图像到 “特征描述”

2.4 对比损失:让 “双胞胎” 特征靠近

2.5 训练过程:反复练习 “找不同”

2.6 线性评估:用学到的特征 “考试”

三,测试结果

3.1 对比学习结果

3.2 总结

四,完整代码


一,对比式自监督学习

1.1 简介

        对比式自监督学习是一种通过构造 “正样本对”(同一数据的不同增强视图)和 “负样本对”(不同数据的视图)来迫使模型学习数据本质特征的无监督学习方法。其核心流程包括数据增强生成正样本、编码器提取特征、对比损失函数拉近正样本 / 推远负样本,最终将预训练特征迁移到下游任务。该方法无需人工标注,能有效利用海量无标注数据,学习到对视角、光照等变化鲁棒的通用特征,广泛应用于图像、文本等领域,代表算法有 SimCLR、MoCo、CLIP 等,为解决数据标注成本高、特征泛化性不足等问题提供了高效方案。

1.2 常见算法

1.2.1 SimCLR (2020)

核心思想:通过多样化数据增强大规模对比学习学习图像特征。

(假设你在动物园观察动物,SimCLR 让你从不同角度(正面、侧面、背面)、不同光线(白天、黑夜)观察同一只动物,然后告诉你:“这些都是同一只动物,要记住它的本质特征!”同时,给你看其他动物的照片,告诉你:“这些和前面的不是同一种,要区分开来!”)

特点

        数据增强组合:随机裁剪、翻转、颜色抖动、高斯模糊等。(对同一张图片做各种 “变形”(裁剪、翻转、变色),生成很多版本。)

        非线性投影头:使用 MLP 将特征映射到对比空间。

        NT-Xent 损失:温度缩放的交叉熵损失,增大正负样本区分度。

        大批量训练:需 8192 样本 /batch 才能达到最佳效果。(每次训练看大量图片,强行记住 “哪些是同类,哪些不是”。)

应用场景:图像分类、目标检测、语义分割的预训练。


1.2.2 MoCo (2020)

核心思想:通过动量编码器动态负样本队列解决对比学习中的负样本数量限制。(你在动物园遇到一个 “记忆助手”,它会帮你记住之前看过的动物特征。当你看到新动物时,它会提醒你:“这只和之前看到的老虎很像吗?不像?那就是新物种!”)

特点

        动量更新:使用指数移动平均 (EMA) 缓慢更新编码器参数,保持负样本特征稳定性。

        队列机制:维护一个固定大小的负样本特征队列,突破 batch size 限制。(维护一个 “动物特征库”,不断更新和比对。不需要一次性看所有图片,用 “老照片” 当负样本。)

        端到端训练:无需多机并行即可处理大规模负样本。

应用场景:小批量训练、视频理解(利用时序信息构建队列)。算力有限,但想利用历史经验的情况。


1.2.3 BYOL (2021)

核心思想无需负样本,通过 “自举” 机制学习特征。(你照镜子,镜子里的 “你” 就是目标。你需要调整自己的姿势、表情,让镜子里的 “你” 和真实的你越来越像。只关注 “自己和自己的一致性”,不关心别人长什么样。)

特点

        孪生网络架构:在线网络 (online network) 和目标网络 (target network)。

        预测头:在线网络增加预测头,预测目标网络生成的特征。

        无负样本:仅通过正样本对 (同一图像的不同视图) 训练,避免模型坍塌。

应用场景:计算资源有限场景、半监督学习。快速训练、资源紧张的场景。


1.2.4 SimSiam (2021)

核心思想:证明对比学习无需负样本,甚至无需孪生网络权重共享。(你有两个 “克隆人”,一个负责观察动物(编码器),另一个负责猜测观察结果(预测头)。两个克隆人互相学习,但不共享记忆。)

特点

        停止梯度:预测头的梯度不回传到编码器,防止模型坍塌。(两个克隆人独立学习,避免 “作弊”(模型坍塌)。)

        极简架构:仅需一个编码器和预测头,训练速度快。(结构简单,训练高效,效果还不错。)

        无需负样本队列:依赖 “预测 - 编码” 结构学习不变特征。

应用场景:轻量级预训练、快速迭代实验,快速实验、不想折腾复杂模型的情况。


1.2.5 CLIP (2021)

核心思想跨模态对比学习,对齐图像与文本的语义空间。(你同时学习 “文字描述” 和 “图片”,比如看到 “一只猫在沙发上” 的文字,就去找对应的图片。时间久了,你能直接根据文字找到图片,或者根据图片写出描述。)

特点

        多模态输入:同时处理图像和文本,学习图文关联。(同时学习图像和文字,建立两者的联系。)

        零样本学习:通过文本描述直接分类图像,无需训练数据。(没见过的东西也能分类,比如看到 “独角兽” 的描述,能从图片中找出独角兽(即使没见过)。)

        大规模预训练:在 4 亿图文对上训练,泛化能力强。

应用场景:图像检索、多模态生成、零样本任务迁移,多语言任务(文字描述可以是任何语言)


1.2.6 DINO (2021)

核心思想:通过自蒸馏学习视觉特征,无需标签或对比对。(你是一个美术生,老师给你一张 “半成品” 的动物画(教师网络),让你照着画完(学生网络)。通过不断模仿老师的风格,你学会了如何画动物的细节(如眼睛、毛发)。)

特点

        教师 - 学生架构:教师网络生成伪标签,指导学生网络学习。(用 “教师模型” 指导 “学生模型”,不需要标签。)

        无监督注意力:自动发现图像中的语义区域(如物体轮廓)。(自动关注图像中的重要部分(如动物轮廓)。)

        ViT 友好:特别适合 Vision Transformer 架构。

应用场景:目标检测、实例分割的预训练。基于 Transformer 的模型(如 ViT),擅长捕捉图像的局部细节。


1.2.7 SwAV (2020)

核心思想:将对比学习与聚类相结合,无需负样本队列。(你在整理照片,把相似的动物照片放在同一个相册(聚类)。然后,你用一个相册的照片去猜测另一个相册的分类,不断调整分类规则。)

特点

        对比聚类:动态分配样本到聚类中心,强制特征对齐。(先聚类,再对比,不需要显式的负样本。)

        交换预测:用一个视图的特征预测另一个视图的聚类分配。(不需要维护大规模队列,适合处理高维数据。)

        内存高效:无需维护大规模负样本队列。

应用场景:高维特征学习、大规模图像检索、高维特征分析(如图像的像素级特征)。


1.2.8 算法对比表

算法负样本需求关键创新点计算效率应用领域
SimCLR显式需要多样化增强 + NT-Xent 损失图像基础任务
MoCo队列机制动量编码器 + 动态队列小批量训练、视频
BYOL无需自举机制 + 孪生网络资源受限场景
SimSiam无需停止梯度 + 极简架构快速实验
CLIP跨模态图文对齐 + 零样本学习极高多模态任务
DINO无对比对自蒸馏 + 注意力机制基于 ViT 的检测 / 分割
SwAV隐式对比对比聚类 + 交换预测高维特征学习

计算资源充足:优先使用 SimCLR 或 MoCo,利用大规模负样本提升性能。

轻量级场景:选择 BYOL 或 SimSiam,无需负样本,训练更高效。

多模态任务:使用 CLIP,支持图文联合推理。

基于 ViT 的模型:考虑 DINO,专为 Transformer 设计。

高维特征需求:尝试 SwAV,结合聚类优化特征结构。


二,代码逻辑分析

2.1 整体目标与流程

通俗解释
我们要让模型在没有标签的情况下学习图像的特征,就像小孩通过观察不同角度的玩具来理解 “这是同一个东西”。然后用学到的特征完成分类任务(如识别 FashionMNIST 中的衣服类型)。

def main():# 1. 加载数据(无需标签)train_loader = DataLoader(FashionMNIST(...))# 2. 预训练:通过对比学习提取特征encoder = train_contrastive(encoder, projection_head, train_loader, ...)# 3. 测试:用线性分类器验证特征质量linear_evaluation(encoder, train_loader, test_loader)

2.2  数据增强:生成 “双胞胎” 图像

通俗解释
对同一张图像做不同的 “变形”(裁剪、翻转、变色等),生成一对 “双胞胎”。模型需要学会:虽然外观不同,但它们本质是同一个东西

def get_transform():return transforms.Compose([transforms.RandomResizedCrop(28),  # 随机裁剪transforms.RandomHorizontalFlip(),  # 随机翻转transforms.ColorJitter(0.4, 0.4, 0.4),  # 颜色抖动transforms.GaussianBlur(3),  # 模糊transforms.Normalize(...)  # 归一化])# 训练时对每个图像生成两个视图
view1 = get_transform()(image)
view2 = get_transform()(image)

2.3 编码器:从图像到 “特征描述”

通俗解释
编码器就像一个 “翻译器”,把图像(像素矩阵)转化为计算机能理解的 “特征描述”(数字向量)。例如,把 “猫的图片” 转化为 “耳朵尖、眼睛圆、有胡须” 这样的描述。

class ResNet18Encoder(nn.Module):def __init__(self, pretrained=False):super().__init__()# 加载预训练的ResNet18并修改输入通道resnet = models.resnet18(pretrained=pretrained)# 修改第一层卷积以适应单通道输入(原输入通道为3)resnet.conv1 = nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3, bias=False)# 移除最后的全连接层,保留特征提取部分self.features = nn.Sequential(*list(resnet.children())[:-1])self.projection_dim = 512  # ResNet18的输出维度def forward(self, x):x = self.features(x)x = torch.flatten(x, 1)return x

2.4 对比损失:让 “双胞胎” 特征靠近

通俗解释
对比损失就像一个 “裁判”,它告诉模型:同一图像的两个视图(双胞胎)特征要相似,不同图像的特征要远离

def contrastive_loss(z1, z2, temperature=0.1):# 计算所有样本对的相似度sim_matrix = torch.matmul(z1, z2.T) / temperature# 标签:正样本对是对角线上的元素labels = torch.arange(batch_size).to(device)# 目标:最大化正样本对的相似度,最小化负样本对的相似度loss = F.cross_entropy(sim_matrix, labels)return loss

2.5 训练过程:反复练习 “找不同”

通俗解释
模型反复看大量图像对,不断调整自己的 “特征提取方式”,直到能准确区分 “双胞胎” 和 “陌生人”。

def train_contrastive(encoder, projection_head, dataloader, optimizer, epochs=30):for epoch in range(epochs):for images, _ in dataloader:  # 无需标签!# 生成两个视图view1 = torch.stack([get_transform()(img) for img in images])view2 = torch.stack([get_transform()(img) for img in images])# 提取特征并计算损失z1 = projection_head(encoder(view1))z2 = projection_head(encoder(view2))loss = contrastive_loss(z1, z2)# 优化模型:调整参数,让损失变小optimizer.zero_grad()loss.backward()optimizer.step()

2.6 线性评估:用学到的特征 “考试”

通俗解释
冻结训练好的编码器(固定 “特征提取方式”),只训练一个简单的线性分类器(类似 “填空题”)。如果分类准确率高,说明编码器学到的特征确实有用。

def linear_evaluation(encoder, train_loader, test_loader, epochs=15):encoder.eval()  # 冻结编码器,不再更新classifier = nn.Linear(256, 10).to(device)  # 简单线性分类器for epoch in range(epochs):for images, labels in train_loader:# 用编码器提取特征(固定不变)with torch.no_grad():features = encoder(images)# 仅训练分类器:将特征映射到类别logits = classifier(features)loss = F.cross_entropy(logits, labels)optimizer.zero_grad()loss.backward()optimizer.step()

三,测试结果

3.1 对比学习结果

3.2 总结

        相比使用更为简单的判别式自监督学习,更复杂的对比式自监督学习的准确度反而下降了,SimCLR 的对比训练就像是一场 “找相同与找不同” 的游戏。在这个游戏里,它先对同一张图片施展 “变形魔法”,通过裁剪、旋转、改变颜色等数据增强手段,变出多个 “长得不一样但本质相同” 的视图,把这些视图配成对,就是正样本对;而其他图片的视图,不管来自哪张图,都被当作负样本对。接着,对比损失函数就像一个 “裁判”,时刻盯着模型,要是模型把正样本对的特征分得太开,或者把负样本对的特征靠得太近,就要 “扣分”(增加损失值)。在不断 “扣分” 和调整的过程中,模型慢慢学会把正样本对的特征在 “特征空间” 里拉近,把负样本对的特征推远,最终掌握了提取通用特征的能力。

        这种对比训练在样本超级多的数据集里特别 “如鱼得水”。想象一下,如果数据集里只有寥寥几张图片,模型很容易被图片里一些偶然出现的相似点误导,比如两张不同类别的图片刚好都有一块红色区域,模型可能就错误地把它们归为相似的。但当数据集里有成千上万、甚至几十万上百万张图片时,同类图片的数量足够多,模型就能从大量同类样本里总结出真正的共性特征,比如从海量猫的图片里学到猫有尖耳朵、长胡须这些关键特点,而不是被某张图片里猫身上的装饰误导。同时,丰富的负样本也能让模型见识到各种各样不相似的情况,更好地区分不同类别,就像见过了所有动物,才能更准确地分辨出猫和狗。最终,模型构建出的特征空间,能让相似的样本自然地聚集在一起,不相似的样本远远分开,为后续的图像分类、检索等任务,打下了坚实又可靠的基础 。

        对于fashionmnist数据集来说,其数据规模还远小于需要使用simCLR算法的程度,在实际使用中,这种不太合适的算法选择往往会事倍功半。

基于FashionMnist数据集的自监督学习(判别式自监督学习)-CSDN博客


四,完整代码

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
import torch.nn.functional as F
from torch.optim.lr_scheduler import CosineAnnealingLR# 设置设备:优先使用GPU,否则使用CPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")# ----------------------
# 1. 数据增强(增强多样性)
# ----------------------
def get_transform():"""创建一系列随机变换,用于生成同一张图片的不同视图"""return transforms.Compose([transforms.RandomResizedCrop(28, scale=(0.7, 1.0)),  # 随机裁剪并调整大小,模拟不同视角transforms.RandomHorizontalFlip(),  # 随机水平翻转transforms.RandomApply([transforms.ColorJitter(0.4, 0.4, 0.4, 0.1)], p=0.8),  # 随机改变颜色transforms.RandomGrayscale(p=0.2),  # 20%概率转为灰度图transforms.GaussianBlur(kernel_size=3, sigma=(0.1, 2.0)),  # 随机高斯模糊,模拟模糊场景transforms.Normalize((0.1307,), (0.3081,))  # 标准化,确保数据分布一致])# ----------------------
# 2. 简单编码器(卷积网络)
# ----------------------
class Encoder(nn.Module):"""将图片转换为特征向量的神经网络"""def __init__(self):super().__init__()# 三层卷积提取特征,逐步增加通道数self.conv1 = nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1)  # 输入通道1(灰度图),输出32self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)  # 通道从32增加到64self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)  # 通道从64增加到128self.pool = nn.MaxPool2d(2, 2)  # 最大池化层,降低空间尺寸self.fc = nn.Linear(128 * 3 * 3, 256)  # 全连接层,将特征展平为256维向量def forward(self, x):# 卷积+激活+池化的三层处理x = self.pool(F.relu(self.conv1(x)))  # 尺寸从28x28变为14x14x = self.pool(F.relu(self.conv2(x)))  # 尺寸从14x14变为7x7x = self.pool(F.relu(self.conv3(x)))  # 尺寸从7x7变为3x3x = x.view(-1, 128 * 3 * 3)  # 将特征图展平为一维向量x = self.fc(x)  # 最后通过全连接层生成256维特征向量return x# ----------------------
# 3. 投影头(增加归一化)
# ----------------------
class ProjectionHead(nn.Module):"""将编码器输出的特征映射到对比学习的目标空间"""def __init__(self):super().__init__()self.fc1 = nn.Linear(256, 512)  # 第一个全连接层,扩展到512维self.ln1 = nn.LayerNorm(512)  # 层归一化,加速训练并提高稳定性self.relu = nn.ReLU()  # 激活函数,引入非线性self.fc2 = nn.Linear(512, 128)  # 第二个全连接层,压缩到128维self.ln2 = nn.LayerNorm(128)  # 层归一化def forward(self, x):x = self.relu(self.ln1(self.fc1(x)))  # 第一层处理x = self.ln2(self.fc2(x))  # 第二层处理,输出128维向量return x# ----------------------
# 4. 对比损失函数(InfoNCE)
# ----------------------
def contrastive_loss(z1, z2, temperature=0.07):"""计算两个特征向量之间的对比损失,使正样本对更接近,负样本对更远离"""batch_size = z1.shape[0]z1 = F.normalize(z1, dim=1)  # 归一化特征向量,便于计算相似度z2 = F.normalize(z2, dim=1)  # 归一化特征向量# 构建正样本对标签:每个z1的正样本是对应的z2,反之亦然positive = torch.cat([torch.arange(batch_size), torch.arange(batch_size)], dim=0).to(device)# 计算所有样本对之间的相似度(点积),并除以温度参数logits = torch.cat([torch.matmul(z1, z2.T), torch.matmul(z2, z1.T)], dim=0) / temperature# 使用交叉熵损失:目标是让正样本对的相似度得分最高loss = F.cross_entropy(logits, positive)return loss# ----------------------
# 5. 训练函数(对比学习)
# ----------------------
def train_contrastive(encoder, projection_head, dataloader, optimizer, scheduler, epochs=30):"""对比学习的训练主循环"""encoder.train()projection_head.train()for epoch in range(epochs):total_loss = 0for images, _ in dataloader:  # 注意:这里只使用图片,不使用标签(自监督)images = images.to(device)# 对同一批图片应用两次不同的数据增强,生成两个视图view1 = torch.stack([get_transform()(img) for img in images])view2 = torch.stack([get_transform()(img) for img in images])view1, view2 = view1.to(device), view2.to(device)# 通过编码器和投影头处理两个视图h1 = encoder(view1)  # 提取特征h2 = encoder(view2)  # 提取特征z1 = projection_head(h1)  # 投影到对比学习空间z2 = projection_head(h2)  # 投影到对比学习空间# 计算对比损失loss = contrastive_loss(z1, z2)# 反向传播和优化optimizer.zero_grad()loss.backward()optimizer.step()scheduler.step()  # 更新学习率(余弦退火策略)total_loss += loss.item()# 打印每个epoch的平均损失和当前学习率avg_loss = total_loss / len(dataloader)print(f"Epoch {epoch + 1}/{epochs}, Loss: {avg_loss:.4f}, LR: {scheduler.get_last_lr()[0]:.6f}")return encoder# ----------------------
# 6. 线性评估函数
# ----------------------
def linear_evaluation(encoder, train_loader, test_loader, epochs=30):"""评估对比学习得到的编码器性能:固定编码器,训练一个线性分类器"""encoder.eval()  # 冻结编码器,只训练线性分类器classifier = nn.Linear(256, 10).to(device)  # 创建一个线性分类器(256维特征到10个类别)optimizer = optim.Adam(classifier.parameters(), lr=1e-3, weight_decay=1e-4)criterion = nn.CrossEntropyLoss()for epoch in range(epochs):# 训练阶段classifier.train()train_loss = 0correct = 0total = 0for images, labels in train_loader:images, labels = images.to(device), labels.to(device)with torch.no_grad():features = encoder(images)  # 使用编码器提取特征(固定不变)outputs = classifier(features)  # 通过线性分类器预测类别loss = criterion(outputs, labels)optimizer.zero_grad()loss.backward()optimizer.step()train_loss += loss.item()correct += (outputs.argmax(1) == labels).sum().item()total += labels.size(0)# 测试阶段classifier.eval()test_correct = 0test_total = 0with torch.no_grad():for images, labels in test_loader:images, labels = images.to(device), labels.to(device)features = encoder(images)test_correct += (classifier(features).argmax(1) == labels).sum().item()test_total += labels.size(0)# 打印训练和测试准确率train_acc = 100 * correct / totaltest_acc = 100 * test_correct / test_totalprint(f"Epoch {epoch + 1}/{epochs}, Train Acc: {train_acc:.2f}%, Test Acc: {test_acc:.2f}%")return test_acc# ----------------------
# 7. 主函数
# ----------------------
def main():"""程序入口:加载数据,训练模型,评估性能"""# 加载FashionMNIST数据集train_dataset = datasets.FashionMNIST(root='./data',train=True,download=True,transform=transforms.ToTensor()  # 仅转换为张量,不使用其他增强(训练时单独处理))test_dataset = datasets.FashionMNIST(root='./data',train=False,download=True,transform=transforms.ToTensor())train_loader = DataLoader(train_dataset, batch_size=256, shuffle=True, num_workers=4)  # 大批次加速训练test_loader = DataLoader(test_dataset, batch_size=256, shuffle=False, num_workers=4)# 初始化模型encoder = Encoder().to(device)projection_head = ProjectionHead().to(device)# 优化器与学习率调度器optimizer = optim.Adam(list(encoder.parameters()) + list(projection_head.parameters()),lr=1e-3,  # 学习率weight_decay=1e-5  # 权重衰减,防止过拟合)# 余弦退火学习率调度:先增大后减小,帮助跳出局部最优scheduler = CosineAnnealingLR(optimizer, T_max=30, eta_min=1e-5)# 对比学习训练print("开始对比学习训练...")encoder = train_contrastive(encoder, projection_head, train_loader, optimizer, scheduler, epochs=30)# 线性评估:测试编码器学到的特征质量print("\n开始线性评估...")linear_evaluation(encoder, train_loader, test_loader, epochs=30)if __name__ == "__main__":main()

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

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

相关文章

Linux:基础指令与内涵理解(下)与权限

1.mv 作用:将文件移动、文件重命名 语法: mv (选项) 源文件/目录 目标文件/目录 (1)将文件/目录移动到当前目录的新文件/目录(也就是重命名操作) 这里我们mv了test.txt文件到当前目录下当前并不存在的ln.tx…

卷积神经网络(CNN)入门学习笔记

什么是 CNN? CNN,全称 卷积神经网络(Convolutional Neural Network),是一种专门用来处理图片、语音、文本等结构化数据的神经网络。 它模仿人眼识别图像的方式: 从局部到整体,一步步提取特征&a…

c#基础07(调试与异常捕捉)

文章目录 调试与异常捕捉调试异常处理C#中的异常类异常处理抛出对象 调试与异常捕捉 很多时间,写代码不能一撸到底,中间都是经历过无数次的调试,才能正常正确的运行起来。.Net调试有很多方法和技巧。 调试 在C#中程序调试主要指在Visual S…

一种比较精简的协议

链接地址为:ctLink: 一个比较精简的支持C/C的嵌入式通信的中间协议。 本文采用的协议格式如下 *帧头 uint8_t 起始字节:0XAF\ *协议版本 uint8_t 使用的协议版本号:当前为0X01\ *负载长度 uint8_t 数据段内容长…

【windwos】文本编辑器Notepad++ 替代品Notepad--

一、N和N--对比介绍 曾经备受推崇的「Notepad」曾是Windows上的经典代码编辑器。然而,作者的一些政治言论已经让它被广大中国用户抛弃。 一个名为「Notepad--」的新编辑器,也是开源免费,功能和实用性也在尽可能接近。与此同时,「N…

贪心算法套路模板+详细适用场景+经典题目清单

1. 排序 贪心选择 适用场景: 任务调度问题:需要安排多个任务,尽量完成更多任务或最小冲突。 区间调度问题:选出最多互不重叠的区间。 区间覆盖问题:用最少区间覆盖某个范围。 合并区间问题:合并重叠区…

Qt QPaintEvent绘图事件painter使用指南

绘制需在paintEvent函数中实现 用图片形象理解 如果加了刷子再用笔就相当于用笔画过的区域用刷子走 防雷达&#xff1a; 源文件 #include "widget.h" #include "ui_widget.h" #include <QDebug> #include <QPainter> Widget::Widget(QWidget…

SIGGRAPH 2025 | 快手可灵团队提出3D感知的电影级文本到视频生成框架CineMaster

Sora、可灵等视频生成模型令人惊艳的性能表现使得创作者仅依靠文本输入就能够创作出高质量的视频内容。然而&#xff0c;我们常见的电影片段通常是由导演在一个场景中精心布置多个目标的运动、摄像机拍摄角度后再剪辑而成的。例如&#xff0c;在拍摄赛车追逐的场景时&#xff0…

在springboot,禁止查询数据库种的某字段

使用Mp注解&#xff08;只对Mp提供的基础方法有效&#xff09; 在注解TableField后面加一个select false,这样就无法查询到该表下密码这个字段了 但需要注意的是如果是自己写的sql就无法通过这一种方法实现了

Spring Boot + MyBatis-Plus实现操作日志记录

创建数据库表 CREATE TABLE sys_operation_log (log_id bigint NOT NULL AUTO_INCREMENT COMMENT 日志ID,operation_type varchar(20) NOT NULL COMMENT 操作类型,operation_module varchar(50) NOT NULL COMMENT 操作模块,operation_desc varchar(200) DEFAULT NULL COMMENT …

开源多模态新标杆——BAGEL本地部署教程:7B参数撬动万亿数据

一、简介 BAGEL &#xff0c;这是一个开源的多模态基础模型&#xff0c;具有 70 亿个激活参数&#xff08;总共 140 亿个&#xff09;&#xff0c;并在大规模交错多模态数据上进行训练。 BAGEL 在标准多模态理解排行榜上超越了当前顶级的开源 VLMs 如 Qwen2.5-VL 和 InternVL…

SD卡+FATFS+Tinyjpeg图片解码显示 (STM32F103VET6通过CubeMX快速建立工程)

先展示最终实现的功能效果如下: 1.目的与意义 为什么选用SD卡? 使用Nor-flash(W25Q系列)进行图片的存取,需要先把图片通过对应软件批量处理为二进制bin文件,再通过SPI等通讯方式将 bin文件烧写进Nor-flash才能进行使用,使用时还要记住每张图片的首地址和对应字节数,MC…

数据结构-散列表查找(哈希表)

一&#xff0c;散列表查找定义 散列技术是在记录的存储位置和它的关键字之间建立一个确定的对应关系f&#xff0c;使得每个关键字key对应一个存储位置f(key)。查找时&#xff0c;根据这个确定的对应关系找到给定值key的映射f(key)&#xff0c;若查找集中存在这个记录&#xff0…

Stable Diffusion 简单了解一下

1. 帮我简单介绍一下:StableDiffusion 🌈 Stable Diffusion 是什么? Stable Diffusion 是一个 文本生成图像(Text-to-Image) 的人工智能模型。你只需要输入一句话,它就能根据这句话生成一张高质量的图片。 比如: "一只穿着太空服的猫,在月球上弹吉他"St…

R语言科研编程-标准偏差柱状图

生成随机数据 在R中&#xff0c;可以使用rnorm()生成正态分布的随机数据&#xff0c;并模拟分组数据。以下代码生成3组&#xff08;A、B、C&#xff09;随机数据&#xff0c;每组包含10个样本&#xff1a; set.seed(123) # 确保可重复性 group_A <- rnorm(10, mean50, sd…

普罗米修斯监控CPU\内存汇聚图

要找出内存使用率大于80%的主机&#xff0c;你可以使用以下PromQL查询。这个查询会计算每个节点的内存使用率&#xff0c;然后筛选出使用率超过80%的节点&#xff1a; (avg by(nodename) ((node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes)* on(instance) group…

飞牛fnNAS手机相册备份及AI搜图

目录 一、相册安装应用 二、手机开启自动备份 三、开始备份 四、照片检索 五、AI搜图设置 六、AI搜图测试 七、照片传递 现代的手机,已经成为我们最亲密的“伙伴”。自从手机拍照性能提升后,手机已经完全取代了简单的卡片相机,而且与入门级“单反”相机发起了挑战。在…

华为高斯数据库(GaussDB)深度解析:国产分布式数据库的旗舰之作

高斯数据库介绍 一、高斯数据库概述 GaussDB是华为自主研发的新一代分布式关系型数据库&#xff0c;专为企业核心系统设计。它支持HTAP&#xff08;混合事务与分析处理&#xff09;&#xff0c;兼具强大的事务处理与数据分析能力&#xff0c;是国产数据库替代的重要选择。 产…

网页 CSS美化2(详解)

这是接着上一篇css基础的第二篇&#xff1a;主要开始对页面的布局进行学习 显示模式&#xff1a; 块级模式&#xff08;Block&#xff09; 特点 &#xff1a; 元素会独占一行&#xff0c;在其前后会自动换行&#xff0c;与其他块级元素在垂直方向上排列。 宽度默认为所在容器…

JSON解析性能优化全攻略:协程调度器选择与线程池饥饿解决方案

简介 JSON解析是现代应用开发中的基础操作,但在使用协程处理时,若调度器选择不当,会导致性能严重下降。特别是当使用Dispatchers.IO处理JSON解析时,可能触发线程池饥饿,进而引发ANR或系统卡顿。本文将深入剖析这一问题的技术原理,提供全面的性能检测方法,并给出多种优化…