【PyTorch】5-进阶训练技巧(损失函数、学习率、模型微调、半精度训练、数据增强、超参数设置)

PyTorch:5-进阶训练技巧

注:所有资料来源且归属于thorough-pytorch(https://datawhalechina.github.io/thorough-pytorch/),下文仅为学习记录

5.1:自定义损失函数

PyTorch在torch.nn模块提供了许多常用的损失函数,比如:MSELoss,L1Loss,BCELoss

非官方提供的Loss,比如:DiceLoss,HuberLoss,SobolevLoss

5.1.1:以函数方式定义

损失函数仅是一个函数

def my_loss(output, target):loss = torch.mean((output - target)**2)return loss

5.1.2:以类方式定义

如果看每一个损失函数的继承关系,可以发现Loss函数部分继承自_loss,部分继承自_WeightedLoss,而_WeightedLoss继承自_loss _loss继承自 nn.Module

损失函数类需要继承自nn.Module类。

【案例:DiceLoss】

应用:分割
D i c e L o s s = 2 ∣ X ∩ Y ∣ ∣ X ∣ + ∣ Y ∣ DiceLoss=\frac{2|X∩Y|}{|X|+|Y|} DiceLoss=X+Y2∣XY
实现代码:

class DiceLoss(nn.Module):def __init__(self,weight=None,size_average=True):super(DiceLoss,self).__init__()def forward(self,inputs,targets,smooth=1):inputs = F.sigmoid(inputs)       inputs = inputs.view(-1)targets = targets.view(-1)intersection = (inputs * targets).sum()                   dice = (2.*intersection + smooth)/(inputs.sum() + targets.sum() + smooth)  return 1 - dice# 使用方法    
criterion = DiceLoss()
loss = criterion(input,targets)

在自定义损失函数时,可能涉及到数学运算,最好全程使用PyTorch提供的张量计算接口,这样就不需要实现自动求导功能,并且可以直接调用cuda

【案例:IoULoss】

实现代码:

class IoULoss(nn.Module):def __init__(self, weight=None, size_average=True):super(IoULoss, self).__init__()def forward(self, inputs, targets, smooth=1):inputs = F.sigmoid(inputs)       inputs = inputs.view(-1)targets = targets.view(-1)intersection = (inputs * targets).sum()total = (inputs + targets).sum()union = total - intersection IoU = (intersection + smooth)/(union + smooth)return 1 - IoU

5.2:动态调整学习率

学习率过小:极大降低收敛速度,增加训练时间

学习率过大:导致参数在最优解两侧来回振荡

scheduler——通过一个适当的学习率衰减策略来改善这种现象

5.2.1:官方scheduler

PyTorch已经在torch.optim.lr_scheduler封装好了一些动态调整学习率的方法

  • lr_scheduler.LambdaLR
  • lr_scheduler.MultiplicativeLR
  • lr_scheduler.StepLR
  • lr_scheduler.MultiStepLR
  • lr_scheduler.ExponentialLR
  • lr_scheduler.CosineAnnealingLR
  • lr_scheduler.ReduceLROnPlateau
  • lr_scheduler.CyclicLR
  • lr_scheduler.OneCycleLR
  • lr_scheduler.CosineAnnealingWarmRestarts
  • lr_scheduler.ConstantLR
  • lr_scheduler.LinearLR
  • lr_scheduler.PolynomialLR
  • lr_scheduler.ChainedScheduler
  • lr_scheduler.SequentialLR

这些scheduler都是继承自_LRScheduler类。

使用API:

# 选择一种优化器
optimizer = torch.optim.Adam(...) 
# 选择上面提到的一种或多种动态调整学习率的方法
scheduler1 = torch.optim.lr_scheduler.... 
scheduler2 = torch.optim.lr_scheduler....
...
schedulern = torch.optim.lr_scheduler....
# 进行训练
for epoch in range(100):train(...)validate(...)optimizer.step()# 需要在优化器参数更新之后再动态调整学习率
# scheduler的优化是在每一轮后面进行的
scheduler1.step() 
...
schedulern.step()

在使用官方给出的torch.optim.lr_scheduler时,需要将scheduler.step()放在optimizer.step()后面进行使用。

5.2.2:自定义scheduler

方法:自定义函数adjust_learning_rate来改变param_grouplr的值

假设需要学习率每30轮下降为原来的1/10,实现代码如下:

def adjust_learning_rate(optimizer, epoch):lr = args.lr * (0.1 ** (epoch // 30))for param_group in optimizer.param_groups:param_group['lr'] = lr

在训练的过程调用学习率修正函数来实现学习率的动态变化

optimizer = torch.optim.SGD(model.parameters(),lr = args.lr,momentum = 0.9)
for epoch in range(10):train(...)validate(...)adjust_learning_rate(optimizer,epoch)

5.3:模型微调——torchvision

迁移学习(transfer learning):将从源数据集学到的知识迁移到目标数据集上。

模型微调(finetune):先找到一个同类的别人训练好的模型,把别人现成的训练好了的模型拿过来,换成自己的数据,通过训练调整一下参数。

5.3.1:模型微调流程

  1. 在源数据集上预训练一个神经网络模型,即源模型。
  2. 创建一个新的神经网络模型,即目标模型。它复制了源模型上除了输出层外的所有模型设计及其参数。
  3. 为目标模型添加一个输出大小为目标数据集类别个数的输出层,并随机初始化该层的模型参数。
  4. 在目标数据集上训练目标模型。从头训练输出层,而其余层的参数基于源模型的参数微调。

5.3.2:使用已有模型结构

实例化模型

import torchvision.models as models
resnet18 = models.resnet18()

传递参数

通过True或者False来决定是否使用预训练好的权重,在默认状态下pretrained = False

import torchvision.models as models
resnet18 = models.resnet18(pretrained=True)

可以将自己的权重下载下来放到同文件夹下,然后再将参数加载网络。

self.model = models.resnet50(pretrained=False)
self.model.load_state_dict(torch.load('./model/resnet50-19c8e357.pth'))

如果中途强行停止下载的话,一定要去对应路径下将权重文件删除干净,要不然可能会报错。

5.3.3:训练特定层

在默认情况下,参数的属性.requires_grad = True

如果正在提取特征并且只想为新初始化的层计算梯度,其他参数不进行改变,就需要通过设置requires_grad = False冻结部分层

PyTorch官方提供的例程:

def set_parameter_requires_grad(model, feature_extracting):if feature_extracting:for param in model.parameters():param.requires_grad = False

修改示例:resnet输出从1000转为4,仅改变最后一层的模型参数,不改变特征提取的模型参数。

先冻结模型参数的梯度,再对模型输出部分的全连接层进行修改,修改后的全连接层的参数就是可计算梯度的。

实现过程:

import torchvision.models as models
# 冻结参数的梯度
feature_extract = True
model = models.resnet18(pretrained=True)
set_parameter_requires_grad(model, feature_extract)
# 修改模型
num_ftrs = model.fc.in_features
model.fc = nn.Linear(in_features=num_ftrs, out_features=4, bias=True)

5.4:模型微调——timm

5.4.1:依赖安装

通过pip

pip install timm

通过源码编译

git clone https://github.com/rwightman/pytorch-image-models
cd pytorch-image-models && pip install -e .

5.4.2:查看预训练模型种类

通过timm.list_models()方法查看timm提供的预训练模型

import timm
avail_pretrained_models = timm.list_models(pretrained=True)
len(avail_pretrained_models)

查看特定模型的所有种类

timm.list_models()传入想查询的模型名称(模糊查询)

案例:查询densenet系列的所有模型

all_densnet_models = timm.list_models("*densenet*")
all_densnet_models"""
['densenet121','densenet121d','densenet161','densenet169','densenet201','densenet264','densenet264d_iabn','densenetblur121d','tv_densenet121']
"""

查看模型的具体参数

访问模型的default_cfg属性

model = timm.create_model('resnet34',num_classes=10,pretrained=True)
model.default_cfg"""
{'url': 'https://github.com/rwightman/pytorch-image-models/releases/download/v0.1-weights/resnet34-43635321.pth','num_classes': 1000,'input_size': (3, 224, 224),'pool_size': (7, 7),'crop_pct': 0.875,'interpolation': 'bilinear','mean': (0.485, 0.456, 0.406),'std': (0.229, 0.224, 0.225),'first_conv': 'conv1','classifier': 'fc','architecture': 'resnet34'}
"""

5.4.3:使用和修改预训练模型

得到预训练模型后,通过timm.create_model()的方法创建新模型。

通过传入参数pretrained=True,使用预训练模型。

import timm
import torchmodel = timm.create_model('resnet34',pretrained=True)
x = torch.randn(1,3,224,224)
output = model(x)
output.shape"""
torch.Size([1, 1000])
"""

查看某一层模型参数

model = timm.create_model('resnet34',pretrained=True)
list(dict(model.named_children())['conv1'].parameters())"""
[Parameter containing:tensor([[[[-2.9398e-02, -3.6421e-02, -2.8832e-02,  ..., -1.8349e-02,-6.9210e-03,  1.2127e-02],[-3.6199e-02, -6.0810e-02, -5.3891e-02,  ..., -4.2744e-02,-7.3169e-03, -1.1834e-02],...[ 8.4563e-03, -1.7099e-02, -1.2176e-03,  ...,  7.0081e-02,2.9756e-02, -4.1400e-03]]]], requires_grad=True)]
"""

修改模型

model = timm.create_model('resnet34',num_classes=10,pretrained=True)
x = torch.randn(1,3,224,224)
output = model(x)
output.shape"""
torch.Size([1, 10])
"""

改变输入通道数

model = timm.create_model('resnet34',num_classes=10,pretrained=True,in_chans=1)
# 通过添加in_chans=1来改变
x = torch.randn(1,1,224,224)
output = model(x)

5.4.4:模型保存

timm库所创建的模型是torch.model的子类

可以直接使用torch库中内置的模型参数保存和加载的方法

torch.save(model.state_dict(),'./checkpoint/timm_model.pth')
model.load_state_dict(torch.load('./checkpoint/timm_model.pth'))

5.5:半精度训练

GPU的性能主要分为两部分:算力和显存。

前者决定了显卡计算的速度,后者则决定了显卡可以同时放入多少数据用于计算。

PyTorch默认的浮点数存储方式用的是torch.float32

绝大多数场景其实并不需要这么精确,只保留一半的信息也不会影响结果,即使用torch.float16格式。

数位减了一半,因此被称为**“半精度”**。半精度能够减少显存占用,使显卡可以同时加载更多数据进行计算。

5.5.1:半精度训练的设置

使用autocast配置半精度训练,需要在下面三处加以设置:

【1】import package

from torch.cuda.amp import autocast

【2】模型

使用python的装饰器方法,用autocast装饰模型中的forward函数

@autocast()   
def forward(self, x):...return x

【3】训练过程

在将数据输入模型及其之后的部分放入“with autocast():“即可

 for x in train_loader:x = x.cuda()with autocast():output = model(x)...

半精度训练适用于数据本身的size比较大(3D图像、视频等)。

5.6:数据增强——imgaug

最简单的避免过拟合的方法是增加数据

imgaug封装了很多数据增强算法

5.6.1:imgaug简介

imgaug是计算机视觉任务中常用的一个数据增强的包,相比于torchvision.transforms,它提供了更多的数据增强方法。

pip安装:

pip install imgaug

conda安装:

conda config --add channels conda-forge
conda install imgaug

5.6.2:imgaug使用

imgaug仅提供了图像增强的一些方法,但是并未提供图像的IO操作,因此需要使用一些库来对图像进行导入。

建议使用imageio进行读入,如果使用的是opencv进行文件读取的时候,需要进行手动改变通道,将读取的BGR图像转换为RGB图像

PIL.Image进行读取时,因为读取的图片没有shape的属性,所以需要将读取到的img转换为np.array()的形式再进行处理。

【1】单张图片处理

读取图像:

import imageio
import imgaug as ia
%matplotlib inline# 图片的读取
img = imageio.imread("./Lenna.jpg")# 使用Image进行读取
# img = Image.open("./Lenna.jpg")
# image = np.array(img)
# ia.imshow(image)# 可视化图片
ia.imshow(img)

imgaug包含了许多从Augmenter继承的数据增强的操作

数据增强:以Affine为例

from imgaug import augmenters as iaa# 设置随机数种子
ia.seed(4)# 实例化方法
rotate = iaa.Affine(rotate=(-4,45))# 旋转图片
img_aug = rotate(image=img)
ia.imshow(img_aug)

做多种数据增强处理时,需要利用imgaug.augmenters.Sequential()来构造数据增强的pipeline,该方法与torchvison.transforms.Compose()相类似。

标准格式:

iaa.Sequential(children=None, # Augmenter集合random_order=False, # 是否对每个batch使用不同顺序的Augmenter listname=None,deterministic=False,random_state=None)

多种增强:

# 构建处理序列
aug_seq = iaa.Sequential([iaa.Affine(rotate=(-25,25)),iaa.AdditiveGaussianNoise(scale=(10,60)),iaa.Crop(percent=(0,0.2))
])
# 对图片进行处理,image不可以省略,也不能写成images
image_aug = aug_seq(image=img)
ia.imshow(image_aug)

【2】批次图片处理

可以将图形数据按照NHWC的形式,或者由列表组成的HWC的形式对批量的图像进行处理。

主要分为以下两部分,对批次的图片以同一种方式处理和对批次的图片进行分部分处理。

对批次的图片以同一种方式处理

案例1:

images = [img,img,img,img,]
images_aug = rotate(images=images)
ia.imshow(np.hstack(images_aug))

案例2:

aug_seq = iaa.Sequential([iaa.Affine(rotate=(-25, 25)),iaa.AdditiveGaussianNoise(scale=(10, 60)),iaa.Crop(percent=(0, 0.2))
])# 传入时需要指明是images参数
images_aug = aug_seq.augment_images(images = images)
ia.imshow(np.hstack(images_aug))

对批次的图片进行分部分处理

可以通过imgaug.augmenters.Sometimes()对batch中的一部分图片应用一部分Augmenters,剩下的图片应用另外的Augmenters。

标准格式:

iaa.Sometimes(p=0.5,  # 代表划分比例then_list=None,  # Augmenter集合。p概率的图片进行变换的Augmenters。else_list=None,  #1-p概率的图片会被进行变换的Augmenters。注意变换的图片应用的Augmenter只能是then_list或者else_list中的一个。name=None,deterministic=False,random_state=None)

【3】不同大小图片处理

# 构建pipline
seq = iaa.Sequential([iaa.CropAndPad(percent=(-0.2, 0.2), pad_mode="edge"),  # crop and pad imagesiaa.AddToHueAndSaturation((-60, 60)),  # change their coloriaa.ElasticTransformation(alpha=90, sigma=9),  # water-like effectiaa.Cutout()  # replace one squared area within the image by a constant intensity value
], random_order=True)# 加载不同大小的图片
images_different_sizes = [imageio.imread("https://upload.wikimedia.org/wikipedia/commons/e/ed/BRACHYLAGUS_IDAHOENSIS.jpg"),imageio.imread("https://upload.wikimedia.org/wikipedia/commons/c/c9/Southern_swamp_rabbit_baby.jpg"),imageio.imread("https://upload.wikimedia.org/wikipedia/commons/9/9f/Lower_Keys_marsh_rabbit.jpg")
]# 对图片进行增强
images_aug = seq(images=images_different_sizes)# 可视化结果
print("Image 0 (input shape: %s, output shape: %s)" % (images_different_sizes[0].shape, images_aug[0].shape))
ia.imshow(np.hstack([images_different_sizes[0], images_aug[0]]))print("Image 1 (input shape: %s, output shape: %s)" % (images_different_sizes[1].shape, images_aug[1].shape))
ia.imshow(np.hstack([images_different_sizes[1], images_aug[1]]))print("Image 2 (input shape: %s, output shape: %s)" % (images_different_sizes[2].shape, images_aug[2].shape))
ia.imshow(np.hstack([images_different_sizes[2], images_aug[2]]))

5.6.3:imgaug应用

import numpy as np
from imgaug import augmenters as iaa
from torch.utils.data import DataLoader, Dataset
from torchvision import transforms# 构建pipline
tfs = transforms.Compose([iaa.Sequential([iaa.flip.Fliplr(p=0.5),iaa.flip.Flipud(p=0.5),iaa.GaussianBlur(sigma=(0.0, 0.1)),iaa.MultiplyBrightness(mul=(0.65, 1.35)),]).augment_image,# 不要忘记了使用ToTensor()transforms.ToTensor()
])# 自定义数据集
class CustomDataset(Dataset):def __init__(self, n_images, n_classes, transform=None):# 图片的读取,建议使用imageioself.images = np.random.randint(0, 255,(n_images, 224, 224, 3),dtype=np.uint8)self.targets = np.random.randn(n_images, n_classes)self.transform = transformdef __getitem__(self, item):image = self.images[item]target = self.targets[item]if self.transform:image = self.transform(image)return image, targetdef __len__(self):return len(self.images)def worker_init_fn(worker_id):imgaug.seed(np.random.get_state()[1][0] + worker_id)custom_ds = CustomDataset(n_images=50, n_classes=10, transform=tfs)
custom_dl = DataLoader(custom_ds, batch_size=64,num_workers=4, pin_memory=True, worker_init_fn=worker_init_fn)

使用Linux远程服务器时,可使用不同的num_workers的数量。worker_init_fn()函数的作用:保证了使用的数据增强在num_workers>0时是对数据的增强是随机的。

其他数据增强库:Albumentations,Augmentor。

5.7:使用argparse调参

作用:解析输入的命令行参数再传入模型的超参数中。

5.7.1:简介

argsparse是python的命令行解析的标准模块,内置于python,不需要安装。

argparse的作用是将命令行传入的其他参数进行解析、保存和使用。

5.7.2:使用

三个步骤:

  • 创建ArgumentParser()对象
  • 调用add_argument()方法添加参数
  • 使用parse_args()解析参数
import argparse# 创建ArgumentParser()对象
parser = argparse.ArgumentParser()# 添加参数
parser.add_argument('-o', '--output', action='store_true', help="shows output")
# action = `store_true` 会将output参数记录为Trueparser.add_argument('--lr', type=float, default=3e-5, help='select the learning rate, default=1e-3') 
# type 规定了参数的格式
# default 规定了默认值parser.add_argument('--batch_size', type=int, required=True, help='input batch size')  
# required=True,表示batch-size是必选# 使用parse_args()解析函数
args = parser.parse_args()if args.output:print("This is some output")print(f"learning rate:{args.lr} ")

在命令行使用python demo.py --lr 3e-4 --batch_size 32,可以看到以下的输出

This is some output
learning rate: 3e-4

argparse的参数主要可以分为可选参数和必选参数。

可选参数在未输入的情况下会设置为默认值。

必选参数在当给参数设置required =True后,就必须传入该参数,否则就会报错。

【输入参数的时候不使用–】会严格按照参数位置进行解析

import argparse# 位置参数
parser = argparse.ArgumentParser()parser.add_argument('name')
parser.add_argument('age')args = parser.parse_args()print(f'{args.name} is {args.age} years old')

终端输入和输出的结果

$ positional_arg.py Peter 23
Peter is 23 years old

5.7.3:高效修改超参数

将有关超参数的操作写在config.py,然后在train.py或者其他文件导入。

【config.py】

import argparse  def get_options(parser=argparse.ArgumentParser()):  parser.add_argument('--workers', type=int, default=0,  help='number of data loading workers, you had better put it '  '4 times of your gpu')  parser.add_argument('--batch_size', type=int, default=4, help='input batch size, default=64')  parser.add_argument('--niter', type=int, default=10, help='number of epochs to train for, default=10')  parser.add_argument('--lr', type=float, default=3e-5, help='select the learning rate, default=1e-3')  parser.add_argument('--seed', type=int, default=118, help="random seed")  parser.add_argument('--cuda', action='store_true', default=True, help='enables cuda')  parser.add_argument('--checkpoint_path',type=str,default='',  help='Path to load a previous trained model if not empty (default empty)')  parser.add_argument('--output',action='store_true',default=True,help="shows output")  opt = parser.parse_args()  if opt.output:  print(f'num_workers: {opt.workers}')  print(f'batch_size: {opt.batch_size}')  print(f'epochs (niters) : {opt.niter}')  print(f'learning rate : {opt.lr}')  print(f'manual_seed: {opt.seed}')  print(f'cuda enable: {opt.cuda}')  print(f'checkpoint_path: {opt.checkpoint_path}')  return opt  if __name__ == '__main__':  opt = get_options()

终端:

$ python config.pynum_workers: 0
batch_size: 4
epochs (niters) : 10
learning rate : 3e-05
manual_seed: 118
cuda enable: True
checkpoint_path:

【train.py】

import configopt = config.get_options()manual_seed = opt.seed
num_workers = opt.workers
batch_size = opt.batch_size
lr = opt.lr
niters = opt.niters
checkpoint_path = opt.checkpoint_path# 随机数的设置,保证复现结果
def set_seed(seed):torch.manual_seed(seed)torch.cuda.manual_seed_all(seed)random.seed(seed)np.random.seed(seed)torch.backends.cudnn.benchmark = Falsetorch.backends.cudnn.deterministic = True...if __name__ == '__main__':set_seed(manual_seed)for epoch in range(niters):train(model,lr,batch_size,num_workers,checkpoint_path)val(model,lr,batch_size,num_workers,checkpoint_path)

argparse提供了一种新的更加便捷的方式,而在一些大型的深度学习库中人们也会使用json、dict、yaml等文件格式去保存超参数进行训练。

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

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

相关文章

Windows远程桌面实现之十四:实现AirPlay接收端,让苹果设备(iOS,iPad等)屏幕镜像到PC端

by fanxiushu 2024-05-04 转载或引用请注明原始作者。 这个课题已经持续了好几年,已经可以说是很长时间了。 实现的程序是 xdisp_virt, 可以去github下载使用:GitHub - fanxiushu/xdisp_virt: xfsredir file system 一开始是基于测试镜像驱动的目的随便开…

Vue前端环境准备

vue-cli Vue-cli是Vue官方提供的脚手架,用于快速生成一个Vue项目模板 提供功能: 统一的目录结构 本地调试 热部署 单元测试 集成打包上线 依赖环境:NodeJs 安装NodeJs与Vue-Cli 1、安装nodejs(已经安装就不用了) node-…

linux文本三剑客之grep

目录 1、三剑客特点和应用场景 2、三件客之grep 1) -v 参数使用示例: 1、三剑客特点和应用场景 命令特点场景grep过滤grep命令过滤速度最快sed替换,修改文件内容,取行 如果要进替换/修改文件内容 取出某个范围的内容(从中午12.到…

【stomp 实战】spring websocket用户消息发送源码分析

这一节,我们学习用户消息是如何发送的。 消息的分类 spring websocket将消息分为两种,一种是给指定的用户发送(用户消息),一种是广播消息,即给所有用户发送消息。那怎么区分这两种消息呢?那就是用前缀了…

我们说的数据分析,到底要分析些什么?

作者 Gam 本文为CDA志愿者投稿作品 “我们说数据分析,到底要分析些什么?” 数据分析这个话题自从进入人们的视线以来,这个话题就成为人们茶余饭后的谈资,但是一千个人眼中就有一千个哈姆雷特,就意味着每个人对数据分…

使用Photoshop压缩图片大小的4种方法

使用Photoshop压缩图片大小,一般可采用下面4种方法: 1.调整图片分辨率: 打开需要压缩的图片文件。 依次点击菜单栏中的“图像”>“图像大小”。 在弹出的对话框中,通过调整分辨率参数来减小文件大小。 2.降低图片品质&#…

什么是水经微图注册码?

水经微图(以下简称“微图”)注册码,是微图的一种授权方式。 什么是微图注册码? 注册码仅可授权一台电脑,绑定CPU和网卡,激活后不可更换电脑使用。 如果CPU或网卡被更换,以及电脑损坏无法开机…

数据库中索引的底层原理和SQL优化

文章目录 关于索引B 树的特点MySQL 为什么使用 B 树? 索引分类聚簇索引 和 非聚簇索引覆盖索引索引的最左匹配原则索引与NULL索引的代价大表结构修改 SQL优化EXPLAIN命令选择索引列其它细节 关于索引 索引是一种用来加快查找效率的数据结构,可以简单粗暴…

卸载、安装、配置快捷mysql

卸载mysql 1、筛选过滤出mysql相关组件 rpm -qa | grep mysql2、关闭MySQL服务 systemctl stop mysql.service 3、卸载对应组件命令如下: rpm -ev --nodeps [显示的组件名称] 4、查找MySQL对应的所有文件夹 find / -name mysql rm -rf [显示的文件夹路径] 检查…

基于若依框架搭建网站的开发日志(一):若依框架搭建、启动、部署

RuoYi(基于SpringBoot开发的轻量级Java快速开发框架) 链接:开源地址 若依是一款开源的基于VueSpringCloud的微服务后台管理系统(也有SpringBoot版本),集成了用户管理、权限管理、定时任务、前端表单生成等…

linux的基础入门(2)

环境变量 在Shell中,正确的赋值语法是没有空格的,即变量名数值。所以,正确的方式是: tmpshy 这样就将变量tmp赋值为"shy"了。 注意:并不是任何形式的变量名都是可用的,变量名只能是英文字母、…

【neteq】tgcall的调用、neteq的创建及接收侧ReceiveStatisticsImpl统计

G:\CDN\P2P-DEV\Libraries\tg_owt\src\call\call.cc基本是按照原生webrtc的来的:G:\CDN\P2P-DEV\tdesktop-offical\Telegram\ThirdParty\tgcalls\tgcalls\group\GroupInstanceCustomImpl.cpptg对neteq的使用 worker 线程创建call Call的config需要neteqfactory Call::CreateAu…

Java中使用RediSearch进行高效数据检索

RediSearch是一款构建在Redis上的搜索引擎,它为Redis数据库提供了全文搜索、排序、过滤和聚合等高级查询功能。通过RediSearch,开发者能够在Redis中实现复杂的数据搜索需求,而无需依赖外部搜索引擎。本文将介绍如何在Java应用中集成并使用Red…

300V直流充电桩测试有哪些实验项目

300V直流充电桩测试的实验项目主要包括以下几个方面: 1. 电气性能测试: - 输入电压范围测试:检查充电桩在不同输入电压下的正常工作情况。 - 输出电压范围测试:检查充电桩在不同输出电压下的正常工作情况。 - 输出电流范围测试…

MySQL#MySql数据库的操作

目录 一、创建数据库 二、字符集和校验规则 1.查看系统默认字符集以及校验规则 2.查看数据库支持的字符集 3.查看数据库支持的字符集校验规则 4.校验规则对数据库的影响 1.以UTF-8格式创建数据库 2.不区分大小写 3.区分大小写 4 大小写对数据库的影响 三、操纵数据…

流程:采集1688店铺内有成交的商品列表||1688商品订单列表+订单详情API接口

此API目前支持以下基本接口: item_get 获得1688商品详情item_search 按关键字搜索商品item_search_img 按图搜索1688商品(拍立淘)item_search_suggest 获得搜索词推荐item_fee 获得商品快递费用seller_info 获得店铺详情item_search_shop 获得…

沃伦·巴菲特将AI比做原子弹:“瓶中精灵”使诈骗成为最快增长产业|TodayAI

在伯克希尔哈撒韦公司的年度股东大会上,投资大师沃伦巴菲特对人工智能的未来提出了严重警告。巴菲特对这项可以模拟现实并产生误导性内容的技术表示担忧,他认为这将成为史上增长最快的行业之一。 巴菲特在会上说:“当你思考诈骗人们的潜力时…

NCBI GEO王炸:GEO2R直接分析RNA-seq数据,几家欢喜几家愁?

GEO2R是NCBI GEO团队针对上传到GEO的芯片数据开发的一款在线差异分析、可视化作图工具,是广大数据分析人员的福音。然而,一直以来GEO2R仅针对芯片数据,对于越来越多的测序数据,只能下载所上传的matrix矩阵,进行分析&am…

ENZO:Insulin(胰岛素)ELISA kit

胰岛素是一种由胰岛β细胞合成分泌的肽类激素。它促进葡萄糖从血液中吸收到组织中,并以糖原和脂肪的形式储存起来;此外胰岛素还抑制肝脏产生葡萄糖。通过控制葡萄糖水平,胰岛素成为脂肪和碳水化合物代谢的调节器。当由于缺乏胰岛素分泌而失去…