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

【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 是一个开源的机器学习库&#xff0c;由 Facebook 的人工智能研究实验室开发。它提供了两种主要的功能&#xff1a;张量计算&#xff08;类似于 NumPy&#xff0c;但具有 GPU 加速&#xff09;和基于动态计算图的深度学习工具。PyTorch 因其灵活性、…...

Lucas-Kanade光流法详解

简介&#xff1a;个人学习分享&#xff0c;如有错误&#xff0c;欢迎批评指正。 光流&#xff08;Optical Flow&#xff09;描述的是图像序列中各像素点随时间的运动情况&#xff0c;是计算机视觉中的基本问题之一。光流问题涉及尝试找出一幅图像中的许多点在第二幅图像中移动的…...

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--请求参数的绑定

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

Redis查询缓存

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

双馈风电DFIG并网系统次转子侧变流器RSC抑制策略研究基于LADRC和重复控制的方法

风电装机容量的持续增长以及电力电子装置的大规模接入&#xff0c;导致电网强度降低&#xff0c;系 统运行特性发生深刻变化&#xff0c;严重威胁风电并网系统的安全稳定运行。因此本文以双馈风 电场经串补线路并网系统为研究对象&#xff0c;在深入分析双馈风电并网系统振荡…...

国产编辑器EverEdit - 使用技巧:变量重命名的一种简单替代方法

1 使用技巧&#xff1a;变量重命名的一种简单替代方法 1.1 应用场景 写过代码的都知道&#xff0c;经常添加功能的时候&#xff0c;是把别的地方的代码拷贝过来&#xff0c;改吧改吧&#xff0c;就能用了&#xff0c;改的过程中&#xff0c;就涉及到一个变量名的问题&#xff…...

使用SSH建立内网穿透,能够访问内网的web服务器

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

JWT认证实战

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

计算机网络 (23)IP层转发分组的过程

一、IP层的基本功能 IP层&#xff08;Internet Protocol Layer&#xff09;是网络通信模型中的关键层&#xff0c;属于OSI模型的第三层&#xff0c;即网络层。它负责在不同网络之间传输数据包&#xff0c;实现网络间的互联。IP层的主要功能包括寻址、路由、分段和重组、错误检测…...

权限管理的方法

模块化分类 功能模块划分 把人资管理系统按业务逻辑拆分成清晰的功能区&#xff0c;例如招聘管理、培训管理、绩效管理、员工档案管理等。招聘管理模块下还能细分职位发布、简历筛选、面试安排等子功能&#xff1b;员工档案管理涵盖基本信息、教育经历、工作履历录入与查询等。…...

【郑大主办、ACM出版、EI稳定检索】第四届密码学、网络安全与通信技术国际会议 (CNSCT 2025)

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

48小时,搭建一个设备巡检报修系统

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

基于Redisson实现重入锁

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

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和第二列&#xff1c;6的行。按名字删除 无论行列&#xff0c;可以找出对应索引或构造相同长…...

动态规划六——两个数组的dp问题

目录 题目一——1143. 最长公共子序列 - 力扣&#xff08;LeetCode&#xff09; 题目二——1035. 不相交的线 - 力扣&#xff08;LeetCode&#xff09; 题目三——115. 不同的子序列 - 力扣&#xff08;LeetCode&#xff09; 题目四—— 44. 通配符匹配 - 力扣&#xff08;…...

项目优化之策略模式

目录 策略模式基本概念 策略模式的应用场景 实际项目中具体应用 项目背景&#xff1a; 策略模式解决方案&#xff1a; 计费模块策略模式简要代码 策略模式基本概念 策略模式(Strategy Pattern) 是一种行为型设计模式&#xff0c;把算法的使用放到环境类中&#xff0c;而算…...

[读书日志]从零开始学习Chisel 第四篇:Scala面向对象编程——操作符即方法(敏捷硬件开发语言Chisel与数字系统设计)

3.2操作符即方法 3.2.1操作符在Scala中的解释 在其它语言中&#xff0c;定义了一些基本的类型&#xff0c;但这些类型并不是我们在面向对象中所说的类。比如说1&#xff0c;这是一个int类型常量&#xff0c;但不能说它是int类型的对象。针对这些数据类型&#xff0c;存在一些…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

安卓基础(aar)

重新设置java21的环境&#xff0c;临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的&#xff1a; MyApp/ ├── app/ …...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...

人机融合智能 | “人智交互”跨学科新领域

本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...

jmeter聚合报告中参数详解

sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample&#xff08;样本数&#xff09; 表示测试中发送的请求数量&#xff0c;即测试执行了多少次请求。 单位&#xff0c;以个或者次数表示。 示例&#xff1a;…...