【PyTorch】迁移学习、数据增强
PyTorch官网
介绍
PyTorch 是一个开源的机器学习库,由 Facebook 的人工智能研究实验室开发。它提供了两种主要的功能:张量计算(类似于 NumPy,但具有 GPU 加速)和基于动态计算图的深度学习工具。PyTorch 因其灵活性、易用性和强大的社区支持而广受欢迎,特别适合研究和原型设计。
PyTorch 的核心特性
- 张量(Tensor):PyTorch 中的基本数据结构是 torch.Tensor,它可以表示多维数组,并且可以在 CPU 或 GPU 上运行。张量支持自动求导功能,这使得实现复杂的神经网络变得简单。
- 自动求导(Autograd):PyTorch 的 torch.autograd 模块可以自动计算梯度,这对于训练神经网络至关重要。每个张量都可以跟踪其计算历史,并根据需要反向传播以计算梯度。
- 神经网络模块(nn.Module):torch.nn 提供了构建神经网络所需的各种层和损失函数。你可以通过- 继承 nn.Module 类来定义自己的模型,并使用内置或自定义的层和激活函数。
- 优化器(Optimizers):torch.optim 包含了多种常用的优化算法,如 SGD、Adam 等,可以帮助你轻松地设置训练过程中的参数更新规则。
- 数据处理(Data Loading):torch.utils.data 提供了方便的数据加载和预处理工具,包括 Dataset 和 DataLoader 类,它们能够高效地管理批量数据并支持多线程读取。
- 分布式训练(Distributed Training):PyTorch 支持单机多 GPU 和多机多 GPU 的分布式训练,可以通过 torch.distributed 和 torch.nn.parallel.DistributedDataParallel 实现高效的模型并行化。
- 迁移学习(Transfer Learning):PyTorch 提供了许多预训练模型,可以直接用于新的任务或者作为基础模型进行微调。
- 可视化(Visualization):结合 TensorBoard 或其他可视化工具,PyTorch 可以帮助开发者更好地理解模型的行为和性能。
PyTorch 生态系统
除了核心库外,PyTorch 还拥有丰富的生态系统,涵盖了从计算机视觉到自然语言处理等多个领域。例如:
- torchvision:提供了一系列与图像相关的数据集、模型架构和常用变换。
- torchaudio:专注于音频处理,包含数据集和预训练模型。
- torchtext:为文本数据处理提供工具和支持。
- transformers:Hugging Face 提供的库,包含了大量预训练的语言模型及其应用。
迁移学习
迁移学习(Transfer Learning)是一种机器学习方法,其中在一个任务上预训练的模型被重新用于另一个相关任务。这种方法特别有用,当新任务的数据量较少时,可以利用预训练模型中已经学到的特征表示,从而提高性能和减少过拟合的风险。
在 PyTorch 中进行迁移学习通常涉及以下几个步骤:
- 选择预训练模型:PyTorch 提供了许多流行的深度学习架构(如 ResNet、VGG、DenseNet 等),这些模型已经在大规模数据集(如 ImageNet)上进行了预训练。你可以从 torchvision.models 模块中加载这些预训练模型。
- 冻结或微调部分层:根据具体的应用场景,可以选择冻结预训练模型中的某些层(通常是前面的卷积层),只对后面的全连接层进行训练。这样做可以保留预训练模型中捕捉到的低级特征,同时调整高层特征以适应新的任务。如果目标任务与原始任务非常相似,则可以考虑微调整个网络。
- 修改分类器:对于分类任务,通常需要替换预训练模型的最后一层(即分类器)。因为预训练模型的最后一层是针对原始任务设计的,而新任务可能有不同的类别数量。你需要根据新任务的需求构建一个新的分类器,并将其附加到预训练模型的顶部。
- 训练模型:使用目标数据集来训练模型。由于你可能会冻结一些层,因此需要确保优化器只更新未冻结的参数。
- 评估模型:在验证集上评估模型性能,必要时调整超参数或继续微调模型。
案例
导包
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import numpy as np
import matplotlib.pyplot as pltimport torchvision
from torchvision import transforms
数据目录
base_dir = './dataset'
train_dir = os.path.join(base_dir, 'train')
test_dir = os.path.join(base_dir, 'test')
<IPython.core.display.Javascript object><IPython.core.display.Javascript object>
图像数据转换
transform = transforms.Compose([# 统一缩放到96 * 96transforms.Resize((96, 96)),transforms.ToTensor(),# 正则化transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
])
train_ds = torchvision.datasets.ImageFolder(train_dir, transform=transform)
test_ds = torchvision.datasets.ImageFolder(test_dir, transform=transform)batch_size = 32
train_dl = torch.utils.data.DataLoader(train_ds, batch_size=batch_size, shuffle=True, drop_last=True)
test_dl = torch.utils.data.DataLoader(test_ds, batch_size=batch_size)
加载预训练好的模型(VGG16)
# 加载预训练好的模型
model = torchvision.models.vgg16(pretrained=True)
model
VGG((features): Sequential((0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(1): ReLU(inplace=True)(2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(3): ReLU(inplace=True)(4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(6): ReLU(inplace=True)(7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(8): ReLU(inplace=True)(9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(11): ReLU(inplace=True)(12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(13): ReLU(inplace=True)(14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(15): ReLU(inplace=True)(16): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(17): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(18): ReLU(inplace=True)(19): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(20): ReLU(inplace=True)(21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(22): ReLU(inplace=True)(23): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(24): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(25): ReLU(inplace=True)(26): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(27): ReLU(inplace=True)(28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(29): ReLU(inplace=True)(30): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False))(avgpool): AdaptiveAvgPool2d(output_size=(7, 7))(classifier): Sequential((0): Linear(in_features=25088, out_features=4096, bias=True)(1): ReLU(inplace=True)(2): Dropout(p=0.5, inplace=False)(3): Linear(in_features=4096, out_features=4096, bias=True)(4): ReLU(inplace=True)(5): Dropout(p=0.5, inplace=False)(6): Linear(in_features=4096, out_features=1000, bias=True))
)
model.features.parameters()
<generator object Module.parameters at 0x000001F0515FBAF0>
for param in model.features.parameters():param.requires_grad = False
修改原网络中的输出层的结构
# 修改原网络中的输出层的结构.
model.classifier[-1].out_features = 4
另一种修改输出层的写法
# 另一种修改输出层的写法.
model.classifier[-1] = torch.nn.Linear(model.classifier[-1], 4)
Linear(in_features=4096, out_features=4, bias=True)
拷到gpu上
# 拷到gpu上
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
model.to(device)
VGG((features): Sequential((0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(1): ReLU(inplace=True)(2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(3): ReLU(inplace=True)(4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(6): ReLU(inplace=True)(7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(8): ReLU(inplace=True)(9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(11): ReLU(inplace=True)(12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(13): ReLU(inplace=True)(14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(15): ReLU(inplace=True)(16): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(17): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(18): ReLU(inplace=True)(19): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(20): ReLU(inplace=True)(21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(22): ReLU(inplace=True)(23): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)(24): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(25): ReLU(inplace=True)(26): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(27): ReLU(inplace=True)(28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(29): ReLU(inplace=True)(30): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False))(avgpool): AdaptiveAvgPool2d(output_size=(7, 7))(classifier): Sequential((0): Linear(in_features=25088, out_features=4096, bias=True)(1): ReLU(inplace=True)(2): Dropout(p=0.5, inplace=False)(3): Linear(in_features=4096, out_features=4096, bias=True)(4): ReLU(inplace=True)(5): Dropout(p=0.5, inplace=False)(6): Linear(in_features=4096, out_features=4, bias=True))
)
优化器和损失函数
optimizer = optim.Adam(model.parameters(), lr=0.001)
loss_fn = nn.CrossEntropyLoss()
定义训练函数
def fit(epoch, model, train_loader, test_loader):correct = 0total = 0running_loss = 0model.train()for x, y in train_loader:# 把数据放到GPU上去. x, y = x.to(device), y.to(device)y_pred = model(x)loss = loss_fn(y_pred, y)optimizer.zero_grad()loss.backward()optimizer.step()with torch.no_grad():y_pred = torch.argmax(y_pred, dim=1)correct += (y_pred == y).sum().item()total += y.size(0)running_loss += loss.item()epoch_loss = running_loss / len(train_loader.dataset)epoch_acc = correct / total# 测试过程test_correct = 0test_total = 0test_running_loss = 0model.eval()with torch.no_grad():for x, y in test_loader:x, y = x.to(device), y.to(device)y_pred = model(x)loss = loss_fn(y_pred, y)y_pred = torch.argmax(y_pred, dim=1)test_correct += (y_pred == y).sum().item()test_total += y.size(0)test_running_loss += loss.item()test_epoch_loss = test_running_loss / len(test_loader.dataset)test_epoch_acc = test_correct / test_totalprint('epoch: ', epoch,'loss: ', round(epoch_loss, 3),'accuracy: ', round(epoch_acc, 3),'test_loss: ', round(test_epoch_loss, 3),'test_accuracy: ', round(test_epoch_acc, 3))return epoch_loss, epoch_acc, test_epoch_loss, test_epoch_acc
训练
epochs = 10
train_loss = []
train_acc = []
test_loss = []
test_acc = []
for epoch in range(epochs):epoch_loss, epoch_acc, test_epoch_loss, test_epoch_acc = fit(epoch, model, train_dl, test_dl)train_loss.append(epoch_loss)train_acc.append(epoch_acc)test_loss.append(test_epoch_loss)test_acc.append(test_epoch_acc)
epoch: 0 loss: 0.079 accuracy: 0.709 test_loss: 0.012 test_accuracy: 0.933
epoch: 1 loss: 0.007 accuracy: 0.951 test_loss: 0.014 test_accuracy: 0.938
epoch: 2 loss: 0.012 accuracy: 0.942 test_loss: 0.014 test_accuracy: 0.942
epoch: 3 loss: 0.01 accuracy: 0.95 test_loss: 0.03 test_accuracy: 0.898
epoch: 4 loss: 0.009 accuracy: 0.96 test_loss: 0.014 test_accuracy: 0.956
epoch: 5 loss: 0.002 accuracy: 0.982 test_loss: 0.017 test_accuracy: 0.964
epoch: 6 loss: 0.003 accuracy: 0.991 test_loss: 0.026 test_accuracy: 0.933
epoch: 7 loss: 0.008 accuracy: 0.974 test_loss: 0.036 test_accuracy: 0.933
epoch: 8 loss: 0.019 accuracy: 0.96 test_loss: 0.04 test_accuracy: 0.951
epoch: 9 loss: 0.019 accuracy: 0.968 test_loss: 0.082 test_accuracy: 0.942
model.parameters()
<generator object Module.parameters at 0x000001F04BA67DB0>
plt.plot(range(1, epochs+1), train_loss, label='train_loss')
plt.plot(range(1, epochs+1), test_loss, label='test_loss')
plt.legend()
<matplotlib.legend.Legend at 0x1f09c7aad68>
plt.plot(range(1, epochs+1), train_acc, label='train_acc')
plt.plot(range(1, epochs+1), test_acc, label='test_acc')
plt.legend()
<matplotlib.legend.Legend at 0x1f062c532e8>
模型保存。state_dict, 是一个字典, 保存了训练模型
model.state_dict()
OrderedDict([('features.0.weight',tensor([[[[-5.5373e-01, 1.4270e-01, 5.2896e-01],[-5.8312e-01, 3.5655e-01, 7.6566e-01],[-6.9022e-01, -4.8019e-02, 4.8409e-01]],[[ 1.7548e-01, 9.8630e-03, -8.1413e-02],[ 4.4089e-02, -7.0323e-02, -2.6035e-01],[ 1.3239e-01, -1.7279e-01, -1.3226e-01]],....1.1987e-02, -2.5213e-02, 1.0111e-02, 3.8605e-02, 5.9450e-02,-2.3559e-02, -1.9590e-02, -1.3793e-03, 1.9122e-02, -2.9245e-02,-1.8233e-02, 1.8062e-02, -4.7170e-02, 2.3613e-03, 5.9311e-02,-2.2850e-02, -4.1937e-02, -9.4028e-02, -3.3440e-02, -8.7492e-03,2.1338e-02, -2.2048e-03, -2.3466e-02, -3.6288e-02, -3.4857e-02,-1.5877e-02, -1.4878e-02, -4.4460e-02, 4.1556e-04, -5.2920e-02,-3.3104e-02, -4.3998e-02, -8.0722e-02, 1.8624e-03, -8.0641e-02,-1.0499e-01, -3.8824e-02, -4.2339e-02, -2.5216e-02, -3.0640e-02,5.8134e-04, -1.6703e-02, -5.3450e-02, -2.9327e-02, -4.9636e-02,-1.7681e-02, -1.7017e-03, -2.4267e-02, -5.5113e-02, -5.1077e-02,5.5027e-02, -1.9267e-02, 1.8775e-02, -9.4351e-02, 8.4938e-03,-1.4278e-02, 4.2343e-02, -4.4048e-03, -5.8631e-02, 1.5991e-02,-9.0777e-03, 3.0489e-02, 2.1308e-02, -2.0702e-02, 4.4335e-03,9.7881e-03, 8.7422e-03, 5.1457e-02, -7.3706e-03, -5.8167e-02,-3.7386e-02, -4.3151e-02, -7.5032e-02, -9.4130e-03, -3.6172e-02,-5.3026e-02, -5.7748e-02, -5.2776e-02, -6.5282e-02, -3.8436e-02,-2.2584e-02, -5.9209e-02, 1.3151e-02, -4.4181e-02, -1.6432e-02],device='cuda:0'))])
保存参数
# 保存参数
path = './vgg16.pth'
torch.save(model.state_dict(), path)
数据增强
数据增强(Data Augmentation)是指通过对训练数据应用一系列随机变换,生成额外的训练样本,以此增加模型的泛化能力和鲁棒性。这有助于防止过拟合,尤其是在数据集较小的情况下。
在 PyTorch 中,数据增强主要通过 torchvision.transforms 模块实现。这个模块提供了多种图像转换操作,包括但不限于:
- 几何变换:如水平翻转、垂直翻转、旋转、缩放和平移。
- 颜色变换:如亮度调整、对比度调整、饱和度调整和色调调整。
- 裁剪:如中心裁剪、随机裁剪和弹性变形。
- 噪声添加:如高斯噪声和其他类型的噪声。
- 标准化:将像素值归一化到特定范围,例如 [0, 1] 或 [-1, 1]。
- 其他变换:如仿射变换、透视变换等。
这些变换可以单独使用,也可以组合起来形成一个复杂的增强管道。transforms.Compose 函数允许你按顺序定义多个转换,并一次性应用于输入数据。此外,还可以结合自定义函数来实现更高级别的增强逻辑。
数据增强不仅限于图像数据,也可以应用于其他类型的数据,比如文本(如词序扰动)、音频(如音调变化)等。对于不同的任务和数据类型,选择合适的数据增强策略非常重要,因为它可以直接影响模型的表现。
案例
- 随机位置的裁剪 , CenterCrop 中间位置裁剪
- 随机旋转
- 水平翻转
- 垂直翻转
- 亮度
- 对比度
- 饱和度
- 随机灰度化
transforms.RandomCrop # 随机位置的裁剪 , CenterCrop 中间位置裁剪
transforms.RandomRotation # 随机旋转
transforms.RandomHorizontalFlip() # 水平翻转
transforms.RandomVerticalFlip() # 垂直翻转
transforms.ColorJitter(brightness) # 亮度
transforms.ColorJitter(contrast) # 对比度
transforms.ColorJitter(saturation) # 饱和度
transforms.ColorJitter(hue)
transforms.RandomGrayscale() # 随机灰度化.
数据增强只会加在训练数据上
# 数据增强只会加在训练数据上.
train_transform = transforms.Compose([transforms.Resize((224, 224)),transforms.RandomCrop(192), transforms.RandomHorizontalFlip(),transforms.RandomVerticalFlip(),transforms.RandomRotation(0.4),
# transforms.ColorJitter(brightness=0.5),
# transforms.ColorJitter(contrast=0.5),transforms.ToTensor(),# 正则化transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
])
test_transform = transforms.Compose([transforms.Resize((224, 224)),transforms.ToTensor(),# 正则化transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
])
其他代码都一样,再看一下训练过程:
train_loss、test_loss
train_acc、test_acc
对比数据增强的前后结果,数据增强后,训练和测试损失变化明显比增强前要更收敛,效果更好。
相关文章:

【PyTorch】迁移学习、数据增强
PyTorch官网 介绍 PyTorch 是一个开源的机器学习库,由 Facebook 的人工智能研究实验室开发。它提供了两种主要的功能:张量计算(类似于 NumPy,但具有 GPU 加速)和基于动态计算图的深度学习工具。PyTorch 因其灵活性、…...

Lucas-Kanade光流法详解
简介:个人学习分享,如有错误,欢迎批评指正。 光流(Optical Flow)描述的是图像序列中各像素点随时间的运动情况,是计算机视觉中的基本问题之一。光流问题涉及尝试找出一幅图像中的许多点在第二幅图像中移动的…...
python多张图片生成/合成gif
你可以通过调整帧率来提高GIF的流畅度。默认情况下,代码中的帧率为每秒1帧(fps=1)。我们可以增加这个值来加快动画速度。 下面是修改后的代码,将帧率从每秒1帧提高到每秒5帧(你可以根据需要进一步调整): 在这个版本中,我添加了一个可选参数fps,默认值为5帧每秒。你可…...
iptable限制多个端口出站
iptable限制多个端口出站 安装包 rootiptable:/home/bb# apt-get update rootiptable:/home/bb# apt-get -y install iptables iptables-restoreweb准备 rootweb:/home/bb/test-iptables# docker run -itd --name web -p 80:80 -v ./web1/index.html:/usr/share/nginx/html…...

springmvc--请求参数的绑定
目录 一、创建项目,pom文件 二、web.xml 三、spring-mvc.xml 四、index.jsp 五、实体类 Address类 User类 六、UserController类 七、请求参数解决中文乱码 八、配置tomcat,然后启动tomcat 1. 2. 3. 4. 九、接收Map类型 1.直接接收Map类型 &#x…...

Redis查询缓存
什么是缓存? 缓存是一种提高数据访问效率的技术,通过在内存中存储数据的副本来减少对数据库或其他慢速存储设备的频繁访问。缓存通常用于存储热点数据或计算代价高的结果,以加快响应速度。 添加Redis缓存有什么好处? Redis 基…...

双馈风电DFIG并网系统次转子侧变流器RSC抑制策略研究基于LADRC和重复控制的方法
风电装机容量的持续增长以及电力电子装置的大规模接入,导致电网强度降低,系 统运行特性发生深刻变化,严重威胁风电并网系统的安全稳定运行。因此本文以双馈风 电场经串补线路并网系统为研究对象,在深入分析双馈风电并网系统振荡…...

国产编辑器EverEdit - 使用技巧:变量重命名的一种简单替代方法
1 使用技巧:变量重命名的一种简单替代方法 1.1 应用场景 写过代码的都知道,经常添加功能的时候,是把别的地方的代码拷贝过来,改吧改吧,就能用了,改的过程中,就涉及到一个变量名的问题ÿ…...

使用SSH建立内网穿透,能够访问内网的web服务器
搞了一个晚上,终于建立了一个内网穿透。和AI配合,还是得自己思考,AI配合才能搞定,不思考只依赖AI也不行。内网服务器只是简单地使用了python -m http.server 8899,但是对于Gradio建立的服务器好像不行,会出…...

JWT认证实战
JWT(JSON Web Token)是一种轻量级的、基于 JSON 的开放标准(RFC 7519),用于在各方之间安全地传递信息。JWT 的特点是结构简单、轻量化和跨平台支持,适用于用户身份验证、信息加密以及无状态的 API 访问控制…...

计算机网络 (23)IP层转发分组的过程
一、IP层的基本功能 IP层(Internet Protocol Layer)是网络通信模型中的关键层,属于OSI模型的第三层,即网络层。它负责在不同网络之间传输数据包,实现网络间的互联。IP层的主要功能包括寻址、路由、分段和重组、错误检测…...
权限管理的方法
模块化分类 功能模块划分 把人资管理系统按业务逻辑拆分成清晰的功能区,例如招聘管理、培训管理、绩效管理、员工档案管理等。招聘管理模块下还能细分职位发布、简历筛选、面试安排等子功能;员工档案管理涵盖基本信息、教育经历、工作履历录入与查询等。…...

【郑大主办、ACM出版、EI稳定检索】第四届密码学、网络安全与通信技术国际会议 (CNSCT 2025)
第四届密码学、网络安全与通信技术国际会议(CNSCT 2025)将于2025年1月17-19日在中国郑州盛大启幕(线上召开)。本次会议旨在汇聚全球密码学、网络安全与通信技术领域的顶尖学者、研究人员与行业领袖,共同探索计算机科学的最新进展与未来趋势。…...

48小时,搭建一个设备巡检报修系统
背景 时不时的,工地的设备又出了状况。巡检人员一顿懵逼、维修人员手忙脚乱,操作工人抱怨影响进度。老板看着待完成的订单,就差骂娘了:“这么搞下去,还能有效率吗?”。 于是,抱着试一试的心态…...

基于Redisson实现重入锁
一. 分布式锁基础 在分布式系统中,当多个客户端(应用实例)需要访问同一资源时,可以使用分布式锁来确保同一时刻只有一个客户端能访问该资源。Redis作为高性能的内存数据库,提供了基于键值对的分布式锁实现,…...

Java文件操作的简单示例
使用原生库 创建空白文件 package com.company; import java.io.File; import java.io.IOException;public class Main {public static void main(String[] args) {File f new File("newfile.txt");try {boolean flag f.createNewFile();System.out.println(&quo…...
删除与增加特定行
1.删除特定行 new_df <- df[-c(4), ] #删除第4行 new_df <- df[-c(2:4), ] #去除第2-4行 new_df <- subset(df, col1 < 10 & col2 < 6) #删除特定第一列<10和第二列<6的行。按名字删除 无论行列,可以找出对应索引或构造相同长…...

动态规划六——两个数组的dp问题
目录 题目一——1143. 最长公共子序列 - 力扣(LeetCode) 题目二——1035. 不相交的线 - 力扣(LeetCode) 题目三——115. 不同的子序列 - 力扣(LeetCode) 题目四—— 44. 通配符匹配 - 力扣(…...
项目优化之策略模式
目录 策略模式基本概念 策略模式的应用场景 实际项目中具体应用 项目背景: 策略模式解决方案: 计费模块策略模式简要代码 策略模式基本概念 策略模式(Strategy Pattern) 是一种行为型设计模式,把算法的使用放到环境类中,而算…...

[读书日志]从零开始学习Chisel 第四篇:Scala面向对象编程——操作符即方法(敏捷硬件开发语言Chisel与数字系统设计)
3.2操作符即方法 3.2.1操作符在Scala中的解释 在其它语言中,定义了一些基本的类型,但这些类型并不是我们在面向对象中所说的类。比如说1,这是一个int类型常量,但不能说它是int类型的对象。针对这些数据类型,存在一些…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...

Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...