YOLOv5 + SE注意力机制:提升目标检测性能的实践
一、引言
目标检测是计算机视觉领域的一个重要任务,广泛应用于自动驾驶、安防监控、工业检测等领域。YOLOv5作为YOLO系列的最新版本,以其高效性和准确性在实际应用中表现出色。然而,随着应用场景的复杂化,传统的卷积神经网络在处理复杂背景和多尺度目标时可能会遇到性能瓶颈。为此,引入注意力机制成为了一种有效的改进方法。本文将详细介绍如何在YOLOv5中引入SE(Squeeze-and-Excitation)注意力机制,通过修改模型配置文件和代码实现,提升模型性能,并对比训练效果。
YOLOv5是YOLO系列的最新版本,相较于之前的版本,YOLOv5在模型结构、训练策略和数据增强等方面进行了多项改进,显著提升了模型的性能和效率。其主要特点包括:
- 模型结构优化:YOLOv5采用新的骨干网络(Backbone)和路径聚合网络(Neck),提高了特征提取和融合的能力。
- 数据增强策略:引入了多种数据增强方法,如Mosaic、MixUp等,提升了模型的泛化能力。
- 训练策略改进:采用动态标签分配策略(SimOTA),提高了训练效率和检测精度。
然而,随着任务复杂度的增加,传统的卷积神经网络在处理多尺度目标时的表现不够理想,SE注意力机制的引入为提升目标检测精度提供了新的思路。
二、YOLOv5与SE注意力机制
2.1 YOLOv5简介
YOLOv5以其高效性和准确性在目标检测中得到了广泛应用。其主要结构特点是:
- Backbone:负责从输入图像中提取特征。
- Neck:通过特征融合提高模型的多尺度感知能力。
- Head:根据提取的特征进行预测。
2.2 SE注意力机制简介
SE(Squeeze-and-Excitation)注意力机制是一种轻量级的注意力模块,旨在通过显式地建模通道间的依赖关系,提升模型的表示能力。SE模块由两个关键部分组成:
- Squeeze(压缩):通过全局平均池化操作,将特征图的空间维度压缩为1,生成通道描述符。
- Excitation(激励):通过两个全连接层和一个Sigmoid激活函数生成通道权重,用于重新校准特征图的通道响应。
通过引入SE模块,YOLOv5能够更加关注重要的特征通道,抑制不重要的特征通道,从而提升模型性能。
三、YOLOv5 + SE注意力机制的实现
3.1 模型配置文件修改
首先,想要将SE注意力机制引入到Yolov5中去,需要修改以下几个文件:commom.py、yolo.py和yolov5s.yaml文件。需要修改YOLOv5的模型配置文件(yolov5_se.yaml
),在Backbone和Neck中引入SE模块。注意将SE模块引入之后,需要更改层数的号码,SE注意力机制也可以加入到其他层中,比如head层的P3输出之前等等。以下是修改后的配置文件内容:
# YOLOv5 馃殌 by Ultralytics, GPL-3.0 license# Parameters
nc: 80 # number of classes
depth_multiple: 0.33 # model depth multiple
width_multiple: 0.50 # layer channel multiple
anchors:- [10,13, 16,30, 33,23] # P3/8- [30,61, 62,45, 59,119] # P4/16- [116,90, 156,198, 373,326] # P5/32# YOLOv5 v6.0 backbone
backbone:# [from, number, module, args][[-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2[-1, 1, Conv, [128, 3, 2]], # 1-P2/4[-1, 3, C3, [128]],[-1, 1, Conv, [256, 3, 2]], # 3-P3/8[-1, 6, C3, [256]],[-1, 1, Conv, [512, 3, 2]], # 5-P4/16[-1, 9, C3, [512]],[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32[-1, 3, C3, [1024]],[-1, 1, SENet,[1024]], #SEAttention #9[-1, 1, SPPF, [1024, 5]], # 10]# YOLOv5 v6.0 head
head:[[-1, 1, Conv, [512, 1, 1]],[-1, 1, nn.Upsample, [None, 2, 'nearest']],[[-1, 6], 1, Concat, [1]], # cat backbone P4[-1, 3, C3, [512, False]], # 13[-1, 1, Conv, [256, 1, 1]],[-1, 1, nn.Upsample, [None, 2, 'nearest']],[[-1, 4], 1, Concat, [1]], # cat backbone P3#[-1, 1, SENet,[1024]], #SEAttention #9[-1, 3, C3, [256, False]], # 18 (P3/8-small)[-1, 1, Conv, [256, 3, 2]],[[-1, 14], 1, Concat, [1]], # cat head P4#[-1, 1, SENet,[1024]], #SEAttention #9[-1, 3, C3, [512, False]], # 21 (P4/16-medium)[-1, 1, Conv, [512, 3, 2]],[[-1, 10], 1, Concat, [1]], # cat head P5#[-1, 1, SENet,[1024]], #SEAttention #9[-1, 3, C3, [1024, False]], # 24 (P5/32-large)[[18, 21, 24], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)]
3.2 SE注意力模块的代码实现
在YOLOv5的代码中,需要实现SE模块。以下是一个SEBlock的实现:
import torch
import torch.nn as nnclass SENet(nn.Module):#c1, c2, n=1, shortcut=True, g=1, e=0.5def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5 ):super(SENet, self).__init__()#c*1*1self.avgpool = nn.AdaptiveAvgPool2d(1)self.l1 = nn.Linear(c1, c1 // 16, bias=False)self.relu = nn.ReLU(inplace=True)self.l2 = nn.Linear(c1 // 16, c1, bias=False)self.sig = nn.Sigmoid()def forward(self, x):b, c, _, _ = x.size()y = self.avgpool(x).view(b, c)y = self.l1(y)y = self.relu(y)y = self.l2(y)y = self.sig(y)y = y.view(b, c, 1, 1)return x * y.expand_as(x)
3.3 使用SE注意力模块
为了在YOLOv5的Backbone和Neck中引入SE模块,可以对Yolo.py文件原有的parse_model
进行修改,以下是修改后的Bottleneck模块:
def parse_model(d, ch): # model_dict, input_channels(3)# Parse a YOLOv5 model.yaml dictionaryLOGGER.info(f"\n{'':>3}{'from':>18}{'n':>3}{'params':>10} {'module':<40}{'arguments':<30}")anchors, nc, gd, gw, act = d['anchors'], d['nc'], d['depth_multiple'], d['width_multiple'], d.get('activation')if act:Conv.default_act = eval(act) # redefine default activation, i.e. Conv.default_act = nn.SiLU()LOGGER.info(f"{colorstr('activation:')} {act}") # printna = (len(anchors[0]) // 2) if isinstance(anchors, list) else anchors # number of anchorsno = na * (nc + 5) # number of outputs = anchors * (classes + 5)layers, save, c2 = [], [], ch[-1] # layers, savelist, ch outfor i, (f, n, m, args) in enumerate(d['backbone'] + d['head']): # from, number, module, argsm = eval(m) if isinstance(m, str) else m # eval stringsfor j, a in enumerate(args):with contextlib.suppress(NameError):args[j] = eval(a) if isinstance(a, str) else a # eval stringsn = n_ = max(round(n * gd), 1) if n > 1 else n # depth gainif m in {Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, MixConv2d, Focus, CrossConv,BottleneckCSP, C3, C3TR, C3SPP, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x,SENet,}:c1, c2 = ch[f], args[0]if c2 != no: # if not outputc2 = make_divisible(c2 * gw, 8)args = [c1, c2, *args[1:]]if m in {BottleneckCSP, C3, C3TR, C3Ghost, C3x, CBAMBottleneck, CABottleneck, CBAMC3, SENet, CANet, CAC3, CBAM, ECANet, GAMNet}:args.insert(2, n) # number of repeatsn = 1elif m is nn.BatchNorm2d:args = [ch[f]]elif m is Concat:c2 = sum(ch[x] for x in f)# TODO: channel, gw, gdelif m in {Detect, Segment}:args.append([ch[x] for x in f])if isinstance(args[1], int): # number of anchorsargs[1] = [list(range(args[1] * 2))] * len(f)if m is Segment:args[3] = make_divisible(args[3] * gw, 8)elif m is Contract:c2 = ch[f] * args[0] ** 2elif m is Expand:c2 = ch[f] // args[0] ** 2else:c2 = ch[f]m_ = nn.Sequential(*(m(*args) for _ in range(n))) if n > 1 else m(*args) # modulet = str(m)[8:-2].replace('__main__.', '') # module typenp = sum(x.numel() for x in m_.parameters()) # number paramsm_.i, m_.f, m_.type, m_.np = i, f, t, np # attach index, 'from' index, type, number paramsLOGGER.info(f'{i:>3}{str(f):>18}{n_:>3}{np:10.0f} {t:<40}{str(args):<30}') # printsave.extend(x % i for x in ([f] if isinstance(f, int) else f) if x != -1) # append to savelistlayers.append(m_)if i == 0:ch = []ch.append(c2)return nn.Sequential(*layers), sorted(save)
3.4 模型训练与效果对比
完成模型配置文件和代码的修改后,可以开始训练模型。推荐使用
COCO数据集或自定义数据集进行训练和验证。或者其他的自定义数据集也可以,在这里我使用自定义数据集camel_elephant_training进行100个epoch训练,该数据集仅仅有骆驼和大象两个种类。
训练完成后,可以通过AP(平均精度)指标来评估引入SE注意力机制前后的模型性能。一般情况下,引入SE模块后,YOLOv5在复杂背景和多尺度目标的检测中表现更为出色。
训练之后的结果如下:
由于时间有限我仅仅训练了100个epoch,正常情况下应设置150~200epoch,从train/obj_loss来看,仍然有下降的空间。
3.5 训练步骤
- 配置训练环境,确保已安装YOLOv5和相关依赖。
- 下载COCO数据集或使用自定义数据集进行训练。
- 修改训练脚本,加载修改后的模型配置文件
yolov5_se.yaml
。 - 开始训练并监控训练过程中的损失和精度。
- 完成训练后,使用验证集评估效果。
3.6 模型部署
将训练好的数据权重通过export.py文件转换成.onnx格式,可以部署到任意平台上。
import argparse
import contextlib
import json
import os
import platform
import re
import subprocess
import sys
import time
import warnings
from pathlib import Pathimport pandas as pd
import torch
from torch.utils.mobile_optimizer import optimize_for_mobileFILE = Path(__file__).resolve()
ROOT = FILE.parents[0] # YOLOv5 root directory
if str(ROOT) not in sys.path:sys.path.append(str(ROOT)) # add ROOT to PATH
if platform.system() != 'Windows':ROOT = Path(os.path.relpath(ROOT, Path.cwd())) # relativefrom models.experimental import attempt_load
from models.yolo import ClassificationModel, Detect, DetectionModel, SegmentationModel
from utils.dataloaders import LoadImages
from utils.general import (LOGGER, Profile, check_dataset, check_img_size, check_requirements, check_version,check_yaml, colorstr, file_size, get_default_args, print_args, url2file, yaml_save)
from utils.torch_utils import select_device, smart_inference_modeMACOS = platform.system() == 'Darwin' # macOS environmentdef export_formats():# YOLOv5 export formatsx = [['PyTorch', '-', '.pt', True, True],['TorchScript', 'torchscript', '.torchscript', True, True],['ONNX', 'onnx', '.onnx', True, True],['OpenVINO', 'openvino', '_openvino_model', True, False],['TensorRT', 'engine', '.engine', False, True],['CoreML', 'coreml', '.mlmodel', True, False],['TensorFlow SavedModel', 'saved_model', '_saved_model', True, True],['TensorFlow GraphDef', 'pb', '.pb', True, True],['TensorFlow Lite', 'tflite', '.tflite', True, False],['TensorFlow Edge TPU', 'edgetpu', '_edgetpu.tflite', False, False],['TensorFlow.js', 'tfjs', '_web_model', False, False],['PaddlePaddle', 'paddle', '_paddle_model', True, True],]return pd.DataFrame(x, columns=['Format', 'Argument', 'Suffix', 'CPU', 'GPU'])def try_export(inner_func):# YOLOv5 export decorator, i..e @try_exportinner_args = get_default_args(inner_func)def outer_func(*args, **kwargs):prefix = inner_args['prefix']try:with Profile() as dt:f, model = inner_func(*args, **kwargs)LOGGER.info(f'{prefix} export success 鉁?{dt.t:.1f}s, saved as {f} ({file_size(f):.1f} MB)')return f, modelexcept Exception as e:LOGGER.info(f'{prefix} export failure 鉂?{dt.t:.1f}s: {e}')return None, Nonereturn outer_func@try_export
def export_torchscript(model, im, file, optimize, prefix=colorstr('TorchScript:')):# YOLOv5 TorchScript model exportLOGGER.info(f'\n{prefix} starting export with torch {torch.__version__}...')f = file.with_suffix('.torchscript')ts = torch.jit.trace(model, im, strict=False)d = {"shape": im.shape, "stride": int(max(model.stride)), "names": model.names}extra_files = {'config.txt': json.dumps(d)} # torch._C.ExtraFilesMap()if optimize: # https://pytorch.org/tutorials/recipes/mobile_interpreter.htmloptimize_for_mobile(ts)._save_for_lite_interpreter(str(f), _extra_files=extra_files)else:ts.save(str(f), _extra_files=extra_files)return f, None@try_export
def export_onnx(model, im, file, opset, dynamic, simplify, prefix=colorstr('ONNX:')):# YOLOv5 ONNX exportcheck_requirements('onnx')import onnxLOGGER.info(f'\n{prefix} starting export with onnx {onnx.__version__}...')f = file.with_suffix('.onnx')output_names = ['output0', 'output1'] if isinstance(model, SegmentationModel) else ['output0']if dynamic:dynamic = {'images': {0: 'batch', 2: 'height', 3: 'width'}} # shape(1,3,640,640)if isinstance(model, SegmentationModel):dynamic['output0'] = {0: 'batch', 1: 'anchors'} # shape(1,25200,85)dynamic['output1'] = {0: 'batch', 2: 'mask_height', 3: 'mask_width'} # shape(1,32,160,160)elif isinstance(model, DetectionModel):dynamic['output0'] = {0: 'batch', 1: 'anchors'} # shape(1,25200,85)torch.onnx.export(model.cpu() if dynamic else model, # --dynamic only compatible with cpuim.cpu() if dynamic else im,f,verbose=False,opset_version=opset,do_constant_folding=True,input_names=['images'],output_names=output_names,dynamic_axes=dynamic or None)# Checksmodel_onnx = onnx.load(f) # load onnx modelonnx.checker.check_model(model_onnx) # check onnx model# Metadatad = {'stride': int(max(model.stride)), 'names': model.names}for k, v in d.items():meta = model_onnx.metadata_props.add()meta.key, meta.value = k, str(v)onnx.save(model_onnx, f)# Simplifyif simplify:try:cuda = torch.cuda.is_available()check_requirements(('onnxruntime-gpu' if cuda else 'onnxruntime', 'onnx-simplifier>=0.4.1'))import onnxsimLOGGER.info(f'{prefix} simplifying with onnx-simplifier {onnxsim.__version__}...')model_onnx, check = onnxsim.simplify(model_onnx)assert check, 'assert check failed'onnx.save(model_onnx, f)except Exception as e:LOGGER.info(f'{prefix} simplifier failure: {e}')return f, model_onnx@try_export
def export_openvino(file, metadata, half, prefix=colorstr('OpenVINO:')):# YOLOv5 OpenVINO exportcheck_requirements('openvino-dev') # requires openvino-dev: https://pypi.org/project/openvino-dev/import openvino.inference_engine as ieLOGGER.info(f'\n{prefix} starting export with openvino {ie.__version__}...')f = str(file).replace('.pt', f'_openvino_model{os.sep}')cmd = f"mo --input_model {file.with_suffix('.onnx')} --output_dir {f} --data_type {'FP16' if half else 'FP32'}"subprocess.run(cmd.split(), check=True, env=os.environ) # exportyaml_save(Path(f) / file.with_suffix('.yaml').name, metadata) # add metadata.yamlreturn f, None@try_export
def export_paddle(model, im, file, metadata, prefix=colorstr('PaddlePaddle:')):# YOLOv5 Paddle exportcheck_requirements(('paddlepaddle', 'x2paddle'))import x2paddlefrom x2paddle.convert import pytorch2paddleLOGGER.info(f'\n{prefix} starting export with X2Paddle {x2paddle.__version__}...')f = str(file).replace('.pt', f'_paddle_model{os.sep}')pytorch2paddle(module=model, save_dir=f, jit_type='trace', input_examples=[im]) # exportyaml_save(Path(f) / file.with_suffix('.yaml').name, metadata) # add metadata.yamlreturn f, None@try_export
def export_coreml(model, im, file, int8, half, prefix=colorstr('CoreML:')):# YOLOv5 CoreML exportcheck_requirements('coremltools')import coremltools as ctLOGGER.info(f'\n{prefix} starting export with coremltools {ct.__version__}...')f = file.with_suffix('.mlmodel')ts = torch.jit.trace(model, im, strict=False) # TorchScript modelct_model = ct.convert(ts, inputs=[ct.ImageType('image', shape=im.shape, scale=1 / 255, bias=[0, 0, 0])])bits, mode = (8, 'kmeans_lut') if int8 else (16, 'linear') if half else (32, None)if bits < 32:if MACOS: # quantization only supported on macOSwith warnings.catch_warnings():warnings.filterwarnings("ignore", category=DeprecationWarning) # suppress numpy==1.20 float warningct_model = ct.models.neural_network.quantization_utils.quantize_weights(ct_model, bits, mode)else:print(f'{prefix} quantization only supported on macOS, skipping...')ct_model.save(f)return f, ct_model@try_export
def export_engine(model, im, file, half, dynamic, simplify, workspace=4, verbose=False, prefix=colorstr('TensorRT:')):# YOLOv5 TensorRT export https://developer.nvidia.com/tensorrtassert im.device.type != 'cpu', 'export running on CPU but must be on GPU, i.e. `python export.py --device 0`'try:import tensorrt as trtexcept Exception:if platform.system() == 'Linux':check_requirements('nvidia-tensorrt', cmds='-U --index-url https://pypi.ngc.nvidia.com')import tensorrt as trtif trt.__version__[0] == '7': # TensorRT 7 handling https://github.com/ultralytics/yolov5/issues/6012grid = model.model[-1].anchor_gridmodel.model[-1].anchor_grid = [a[..., :1, :1, :] for a in grid]export_onnx(model, im, file, 12, dynamic, simplify) # opset 12model.model[-1].anchor_grid = gridelse: # TensorRT >= 8check_version(trt.__version__, '8.0.0', hard=True) # require tensorrt>=8.0.0export_onnx(model, im, file, 12, dynamic, simplify) # opset 12onnx = file.with_suffix('.onnx')LOGGER.info(f'\n{prefix} starting export with TensorRT {trt.__version__}...')assert onnx.exists(), f'failed to export ONNX file: {onnx}'f = file.with_suffix('.engine') # TensorRT engine filelogger = trt.Logger(trt.Logger.INFO)if verbose:logger.min_severity = trt.Logger.Severity.VERBOSEbuilder = trt.Builder(logger)config = builder.create_builder_config()config.max_workspace_size = workspace * 1 << 30# config.set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE, workspace << 30) # fix TRT 8.4 deprecation noticeflag = (1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH))network = builder.create_network(flag)parser = trt.OnnxParser(network, logger)if not parser.parse_from_file(str(onnx)):raise RuntimeError(f'failed to load ONNX file: {onnx}')inputs = [network.get_input(i) for i in range(network.num_inputs)]outputs = [network.get_output(i) for i in range(network.num_outputs)]for inp in inputs:LOGGER.info(f'{prefix} input "{inp.name}" with shape{inp.shape} {inp.dtype}')for out in outputs:LOGGER.info(f'{prefix} output "{out.name}" with shape{out.shape} {out.dtype}')if dynamic:if im.shape[0] <= 1:LOGGER.warning(f"{prefix} WARNING 鈿狅笍 --dynamic model requires maximum --batch-size argument")profile = builder.create_optimization_profile()for inp in inputs:profile.set_shape(inp.name, (1, *im.shape[1:]), (max(1, im.shape[0] // 2), *im.shape[1:]), im.shape)config.add_optimization_profile(profile)LOGGER.info(f'{prefix} building FP{16 if builder.platform_has_fast_fp16 and half else 32} engine as {f}')if builder.platform_has_fast_fp16 and half:config.set_flag(trt.BuilderFlag.FP16)with builder.build_engine(network, config) as engine, open(f, 'wb') as t:t.write(engine.serialize())return f, None@try_export
def export_saved_model(model,im,file,dynamic,tf_nms=False,agnostic_nms=False,topk_per_class=100,topk_all=100,iou_thres=0.45,conf_thres=0.25,keras=False,prefix=colorstr('TensorFlow SavedModel:')):# YOLOv5 TensorFlow SavedModel exporttry:import tensorflow as tfexcept Exception:check_requirements(f"tensorflow{'' if torch.cuda.is_available() else '-macos' if MACOS else '-cpu'}")import tensorflow as tffrom tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2from models.tf import TFModelLOGGER.info(f'\n{prefix} starting export with tensorflow {tf.__version__}...')f = str(file).replace('.pt', '_saved_model')batch_size, ch, *imgsz = list(im.shape) # BCHWtf_model = TFModel(cfg=model.yaml, model=model, nc=model.nc, imgsz=imgsz)im = tf.zeros((batch_size, *imgsz, ch)) # BHWC order for TensorFlow_ = tf_model.predict(im, tf_nms, agnostic_nms, topk_per_class, topk_all, iou_thres, conf_thres)inputs = tf.keras.Input(shape=(*imgsz, ch), batch_size=None if dynamic else batch_size)outputs = tf_model.predict(inputs, tf_nms, agnostic_nms, topk_per_class, topk_all, iou_thres, conf_thres)keras_model = tf.keras.Model(inputs=inputs, outputs=outputs)keras_model.trainable = Falsekeras_model.summary()if keras:keras_model.save(f, save_format='tf')else:spec = tf.TensorSpec(keras_model.inputs[0].shape, keras_model.inputs[0].dtype)m = tf.function(lambda x: keras_model(x)) # full modelm = m.get_concrete_function(spec)frozen_func = convert_variables_to_constants_v2(m)tfm = tf.Module()tfm.__call__ = tf.function(lambda x: frozen_func(x)[:4] if tf_nms else frozen_func(x), [spec])tfm.__call__(im)tf.saved_model.save(tfm,f,options=tf.saved_model.SaveOptions(experimental_custom_gradients=False) if check_version(tf.__version__, '2.6') else tf.saved_model.SaveOptions())return f, keras_model@try_export
def export_pb(keras_model, file, prefix=colorstr('TensorFlow GraphDef:')):# YOLOv5 TensorFlow GraphDef *.pb export https://github.com/leimao/Frozen_Graph_TensorFlowimport tensorflow as tffrom tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2LOGGER.info(f'\n{prefix} starting export with tensorflow {tf.__version__}...')f = file.with_suffix('.pb')m = tf.function(lambda x: keras_model(x)) # full modelm = m.get_concrete_function(tf.TensorSpec(keras_model.inputs[0].shape, keras_model.inputs[0].dtype))frozen_func = convert_variables_to_constants_v2(m)frozen_func.graph.as_graph_def()tf.io.write_graph(graph_or_graph_def=frozen_func.graph, logdir=str(f.parent), name=f.name, as_text=False)return f, None@try_export
def export_tflite(keras_model, im, file, int8, data, nms, agnostic_nms, prefix=colorstr('TensorFlow Lite:')):# YOLOv5 TensorFlow Lite exportimport tensorflow as tfLOGGER.info(f'\n{prefix} starting export with tensorflow {tf.__version__}...')batch_size, ch, *imgsz = list(im.shape) # BCHWf = str(file).replace('.pt', '-fp16.tflite')converter = tf.lite.TFLiteConverter.from_keras_model(keras_model)converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS]converter.target_spec.supported_types = [tf.float16]converter.optimizations = [tf.lite.Optimize.DEFAULT]if int8:from models.tf import representative_dataset_gendataset = LoadImages(check_dataset(check_yaml(data))['train'], img_size=imgsz, auto=False)converter.representative_dataset = lambda: representative_dataset_gen(dataset, ncalib=100)converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]converter.target_spec.supported_types = []converter.inference_input_type = tf.uint8 # or tf.int8converter.inference_output_type = tf.uint8 # or tf.int8converter.experimental_new_quantizer = Truef = str(file).replace('.pt', '-int8.tflite')if nms or agnostic_nms:converter.target_spec.supported_ops.append(tf.lite.OpsSet.SELECT_TF_OPS)tflite_model = converter.convert()open(f, "wb").write(tflite_model)return f, None@try_export
def export_edgetpu(file, prefix=colorstr('Edge TPU:')):# YOLOv5 Edge TPU export https://coral.ai/docs/edgetpu/models-intro/cmd = 'edgetpu_compiler --version'help_url = 'https://coral.ai/docs/edgetpu/compiler/'assert platform.system() == 'Linux', f'export only supported on Linux. See {help_url}'if subprocess.run(f'{cmd} >/dev/null', shell=True).returncode != 0:LOGGER.info(f'\n{prefix} export requires Edge TPU compiler. Attempting install from {help_url}')sudo = subprocess.run('sudo --version >/dev/null', shell=True).returncode == 0 # sudo installed on systemfor c in ('curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -','echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | sudo tee /etc/apt/sources.list.d/coral-edgetpu.list','sudo apt-get update', 'sudo apt-get install edgetpu-compiler'):subprocess.run(c if sudo else c.replace('sudo ', ''), shell=True, check=True)ver = subprocess.run(cmd, shell=True, capture_output=True, check=True).stdout.decode().split()[-1]LOGGER.info(f'\n{prefix} starting export with Edge TPU compiler {ver}...')f = str(file).replace('.pt', '-int8_edgetpu.tflite') # Edge TPU modelf_tfl = str(file).replace('.pt', '-int8.tflite') # TFLite modelcmd = f"edgetpu_compiler -s -d -k 10 --out_dir {file.parent} {f_tfl}"subprocess.run(cmd.split(), check=True)return f, None@try_export
def export_tfjs(file, prefix=colorstr('TensorFlow.js:')):# YOLOv5 TensorFlow.js exportcheck_requirements('tensorflowjs')import tensorflowjs as tfjsLOGGER.info(f'\n{prefix} starting export with tensorflowjs {tfjs.__version__}...')f = str(file).replace('.pt', '_web_model') # js dirf_pb = file.with_suffix('.pb') # *.pb pathf_json = f'{f}/model.json' # *.json pathcmd = f'tensorflowjs_converter --input_format=tf_frozen_model ' \f'--output_node_names=Identity,Identity_1,Identity_2,Identity_3 {f_pb} {f}'subprocess.run(cmd.split())json = Path(f_json).read_text()with open(f_json, 'w') as j: # sort JSON Identity_* in ascending ordersubst = re.sub(r'{"outputs": {"Identity.?.?": {"name": "Identity.?.?"}, 'r'"Identity.?.?": {"name": "Identity.?.?"}, 'r'"Identity.?.?": {"name": "Identity.?.?"}, 'r'"Identity.?.?": {"name": "Identity.?.?"}}}', r'{"outputs": {"Identity": {"name": "Identity"}, 'r'"Identity_1": {"name": "Identity_1"}, 'r'"Identity_2": {"name": "Identity_2"}, 'r'"Identity_3": {"name": "Identity_3"}}}', json)j.write(subst)return f, Nonedef add_tflite_metadata(file, metadata, num_outputs):# Add metadata to *.tflite models per https://www.tensorflow.org/lite/models/convert/metadatawith contextlib.suppress(ImportError):# check_requirements('tflite_support')from tflite_support import flatbuffersfrom tflite_support import metadata as _metadatafrom tflite_support import metadata_schema_py_generated as _metadata_fbtmp_file = Path('/tmp/meta.txt')with open(tmp_file, 'w') as meta_f:meta_f.write(str(metadata))model_meta = _metadata_fb.ModelMetadataT()label_file = _metadata_fb.AssociatedFileT()label_file.name = tmp_file.namemodel_meta.associatedFiles = [label_file]subgraph = _metadata_fb.SubGraphMetadataT()subgraph.inputTensorMetadata = [_metadata_fb.TensorMetadataT()]subgraph.outputTensorMetadata = [_metadata_fb.TensorMetadataT()] * num_outputsmodel_meta.subgraphMetadata = [subgraph]b = flatbuffers.Builder(0)b.Finish(model_meta.Pack(b), _metadata.MetadataPopulator.METADATA_FILE_IDENTIFIER)metadata_buf = b.Output()populator = _metadata.MetadataPopulator.with_model_file(file)populator.load_metadata_buffer(metadata_buf)populator.load_associated_files([str(tmp_file)])populator.populate()tmp_file.unlink()@smart_inference_mode()
def run(data=ROOT / 'data/coco128.yaml', # 'dataset.yaml path'weights=ROOT / 'yolov5s.pt', # weights pathimgsz=(640, 640), # image (height, width)batch_size=1, # batch sizedevice='cpu', # cuda device, i.e. 0 or 0,1,2,3 or cpuinclude=('torchscript', 'onnx'), # include formatshalf=False, # FP16 half-precision exportinplace=False, # set YOLOv5 Detect() inplace=Truekeras=False, # use Kerasoptimize=False, # TorchScript: optimize for mobileint8=False, # CoreML/TF INT8 quantizationdynamic=False, # ONNX/TF/TensorRT: dynamic axessimplify=False, # ONNX: simplify modelopset=12, # ONNX: opset versionverbose=False, # TensorRT: verbose logworkspace=4, # TensorRT: workspace size (GB)nms=False, # TF: add NMS to modelagnostic_nms=False, # TF: add agnostic NMS to modeltopk_per_class=100, # TF.js NMS: topk per class to keeptopk_all=100, # TF.js NMS: topk for all classes to keepiou_thres=0.45, # TF.js NMS: IoU thresholdconf_thres=0.25, # TF.js NMS: confidence threshold
):t = time.time()include = [x.lower() for x in include] # to lowercasefmts = tuple(export_formats()['Argument'][1:]) # --include argumentsflags = [x in include for x in fmts]assert sum(flags) == len(include), f'ERROR: Invalid --include {include}, valid --include arguments are {fmts}'jit, onnx, xml, engine, coreml, saved_model, pb, tflite, edgetpu, tfjs, paddle = flags # export booleansfile = Path(url2file(weights) if str(weights).startswith(('http:/', 'https:/')) else weights) # PyTorch weights# Load PyTorch modeldevice = select_device(device)if half:assert device.type != 'cpu' or coreml, '--half only compatible with GPU export, i.e. use --device 0'assert not dynamic, '--half not compatible with --dynamic, i.e. use either --half or --dynamic but not both'model = attempt_load(weights, device=device, inplace=True, fuse=True) # load FP32 model# Checksimgsz *= 2 if len(imgsz) == 1 else 1 # expandif optimize:assert device.type == 'cpu', '--optimize not compatible with cuda devices, i.e. use --device cpu'# Inputgs = int(max(model.stride)) # grid size (max stride)imgsz = [check_img_size(x, gs) for x in imgsz] # verify img_size are gs-multiplesim = torch.zeros(batch_size, 3, *imgsz).to(device) # image size(1,3,320,192) BCHW iDetection# Update modelmodel.eval()for k, m in model.named_modules():if isinstance(m, Detect):m.inplace = inplacem.dynamic = dynamicm.export = Truefor _ in range(2):y = model(im) # dry runsif half and not coreml:im, model = im.half(), model.half() # to FP16shape = tuple((y[0] if isinstance(y, tuple) else y).shape) # model output shapemetadata = {'stride': int(max(model.stride)), 'names': model.names} # model metadataLOGGER.info(f"\n{colorstr('PyTorch:')} starting from {file} with output shape {shape} ({file_size(file):.1f} MB)")# Exportsf = [''] * len(fmts) # exported filenameswarnings.filterwarnings(action='ignore', category=torch.jit.TracerWarning) # suppress TracerWarningif jit: # TorchScriptf[0], _ = export_torchscript(model, im, file, optimize)if engine: # TensorRT required before ONNXf[1], _ = export_engine(model, im, file, half, dynamic, simplify, workspace, verbose)if onnx or xml: # OpenVINO requires ONNXf[2], _ = export_onnx(model, im, file, opset, dynamic, simplify)if xml: # OpenVINOf[3], _ = export_openvino(file, metadata, half)if coreml: # CoreMLf[4], _ = export_coreml(model, im, file, int8, half)if any((saved_model, pb, tflite, edgetpu, tfjs)): # TensorFlow formatsassert not tflite or not tfjs, 'TFLite and TF.js models must be exported separately, please pass only one type.'assert not isinstance(model, ClassificationModel), 'ClassificationModel export to TF formats not yet supported.'f[5], s_model = export_saved_model(model.cpu(),im,file,dynamic,tf_nms=nms or agnostic_nms or tfjs,agnostic_nms=agnostic_nms or tfjs,topk_per_class=topk_per_class,topk_all=topk_all,iou_thres=iou_thres,conf_thres=conf_thres,keras=keras)if pb or tfjs: # pb prerequisite to tfjsf[6], _ = export_pb(s_model, file)if tflite or edgetpu:f[7], _ = export_tflite(s_model, im, file, int8 or edgetpu, data=data, nms=nms, agnostic_nms=agnostic_nms)if edgetpu:f[8], _ = export_edgetpu(file)add_tflite_metadata(f[8] or f[7], metadata, num_outputs=len(s_model.outputs))if tfjs:f[9], _ = export_tfjs(file)if paddle: # PaddlePaddlef[10], _ = export_paddle(model, im, file, metadata)# Finishf = [str(x) for x in f if x] # filter out '' and Noneif any(f):cls, det, seg = (isinstance(model, x) for x in (ClassificationModel, DetectionModel, SegmentationModel)) # typedir = Path('segment' if seg else 'classify' if cls else '')h = '--half' if half else '' # --half FP16 inference args = "# WARNING 鈿狅笍 ClassificationModel not yet supported for PyTorch Hub AutoShape inference" if cls else \"# WARNING 鈿狅笍 SegmentationModel not yet supported for PyTorch Hub AutoShape inference" if seg else ''LOGGER.info(f'\nExport complete ({time.time() - t:.1f}s)'f"\nResults saved to {colorstr('bold', file.parent.resolve())}"f"\nDetect: python {dir / ('detect.py' if det else 'predict.py')} --weights {f[-1]} {h}"f"\nValidate: python {dir / 'val.py'} --weights {f[-1]} {h}"f"\nPyTorch Hub: model = torch.hub.load('ultralytics/yolov5', 'custom', '{f[-1]}') {s}"f"\nVisualize: https://netron.app")return f # return list of exported files/dirsdef parse_opt():parser = argparse.ArgumentParser()parser.add_argument('--data', type=str, default=ROOT / 'data/coco128.yaml', help='dataset.yaml path')parser.add_argument('--weights', nargs='+', type=str, default=ROOT / 'yolov5s.pt', help='model.pt path(s)')parser.add_argument('--imgsz', '--img', '--img-size', nargs='+', type=int, default=[640, 640], help='image (h, w)')parser.add_argument('--batch-size', type=int, default=1, help='batch size')parser.add_argument('--device', default='cpu', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')parser.add_argument('--half', action='store_true', help='FP16 half-precision export')parser.add_argument('--inplace', action='store_true', help='set YOLOv5 Detect() inplace=True')parser.add_argument('--keras', action='store_true', help='TF: use Keras')parser.add_argument('--optimize', action='store_true', help='TorchScript: optimize for mobile')parser.add_argument('--int8', action='store_true', help='CoreML/TF INT8 quantization')parser.add_argument('--dynamic', action='store_true', help='ONNX/TF/TensorRT: dynamic axes')parser.add_argument('--simplify', action='store_true', help='ONNX: simplify model')parser.add_argument('--opset', type=int, default=12, help='ONNX: opset version')parser.add_argument('--verbose', action='store_true', help='TensorRT: verbose log')parser.add_argument('--workspace', type=int, default=4, help='TensorRT: workspace size (GB)')parser.add_argument('--nms', action='store_true', help='TF: add NMS to model')parser.add_argument('--agnostic-nms', action='store_true', help='TF: add agnostic NMS to model')parser.add_argument('--topk-per-class', type=int, default=100, help='TF.js NMS: topk per class to keep')parser.add_argument('--topk-all', type=int, default=100, help='TF.js NMS: topk for all classes to keep')parser.add_argument('--iou-thres', type=float, default=0.45, help='TF.js NMS: IoU threshold')parser.add_argument('--conf-thres', type=float, default=0.25, help='TF.js NMS: confidence threshold')parser.add_argument('--include',nargs='+',default=['torchscript'],help='torchscript, onnx, openvino, engine, coreml, saved_model, pb, tflite, edgetpu, tfjs, paddle')opt = parser.parse_args()print_args(vars(opt))return optdef main(opt):for opt.weights in (opt.weights if isinstance(opt.weights, list) else [opt.weights]):run(**vars(opt))if __name__ == "__main__":opt = parse_opt()main(opt)
四、总结
本文介绍了如何在YOLOv5中引入SE注意力机制,包括模型配置文件的修改、代码实现、训练步骤以及效果对比。通过引入SE模块,YOLOv5在多尺度目标和复杂背景下的检测精度有所提升。未来,可以继续探索其他注意力机制(如CBAM、ECA等)的应用,以进一步提升YOLOv5的性能。感谢大家的支持。
相关文章:
YOLOv5 + SE注意力机制:提升目标检测性能的实践
一、引言 目标检测是计算机视觉领域的一个重要任务,广泛应用于自动驾驶、安防监控、工业检测等领域。YOLOv5作为YOLO系列的最新版本,以其高效性和准确性在实际应用中表现出色。然而,随着应用场景的复杂化,传统的卷积神经网络在处…...
第十四届蓝桥杯大赛软件赛国赛C/C++大学C组
A 【跑步计划——日期问题】-CSDN博客 B 【残缺的数字】-CSDN博客 C 题目 代码 #include <bits/stdc.h> using namespace std;void change(int &x) {int sum 0, t x;while(t){sum t % 10;t / 10;}x - sum; } int main() {int n;cin >> n;int ans 0;…...
【备份】php项目处理跨域请求踩坑
这都是老生常谈的东西了。我还在踩坑,记录一下。 我在项目入口明明写了如下代码: // 处理预检请求 (OPTIONS) if ($_SERVER[REQUEST_METHOD] OPTIONS) {header("Access-Control-Allow-Origin: https://xxx.vip");header("Access-Cont…...
编程题 - 汽水瓶【JavaScript/Node.js解法】
“学如逆水行舟,不进则退。” ——《增广贤文》 目录 汽水瓶 题目:解答分析:js代码解答 -ACM模式:代码通过:题解分析:简洁思路代码: 汽水瓶 题目: 某商店规定:三个空…...
【考研】复试相关上机题目
文章目录 22机试回忆版1、判断燃气费描述输入格式输出格式输入样例输出样例 C o d e Code Code 2、统计闰年数量描述输入格式输出格式输入样例输出样例 C o d e Code Code 3、打印图形描述输入格式输出格式 C o d e Code Code 4、密文数据描述输入格式输出格式输入样例输出样例…...
HONOR荣耀MagicBook 15 2021款 独显(BOD-WXX9,BDR-WFH9HN)原厂Win10系统
适用型号:【BOD-WXX9】 MagicBook 15 2021款 i7 独显 MX450 16GB512GB (BDR-WFE9HN) MagicBook 15 2021款 i5 独显 MX450 16GB512GB (BDR-WFH9HN) MagicBook 15 2021款 i5 集显 16GB512GB (BDR-WFH9HN) 链接:https://pan.baidu.com/s/1S6L57ADS18fnJZ1…...
微信小程序:完善购物车功能,购物车主页面展示,详细页面展示效果
一、效果图 1、主页面 根据物品信息进行菜单分类,点击单项购物车图标添加至购物车,记录总购物车数量 2、购物车详情页 根据主页面选择的项,根据后台查询展示到页面,可进行多选,数量加减等 二、代码 1、主页面 页…...
Spring Boot集成MyBatis访问MySQL:从项目搭建到基础数据库查询(基础入门)
Spring Boot集成MyBatis访问MySQL 一、引言 在当今企业级应用开发中,Spring Boot、MyBatis与MySQL的组合凭借其高效性和灵活性,成为构建数据驱动型应用的首选方案。本文将带你从零开始搭建项目,掌握Spring Boot集成MyBatis的基础入门内容。…...
基于STM32的智能家居能源管理系统
1. 引言 传统家庭能源管理存在能耗监控粗放、设备联动不足等问题,难以适应绿色低碳发展需求。本文设计了一款基于STM32的智能家居能源管理系统,通过多源能耗监测、负荷预测与优化调度技术,实现家庭能源的精细化管理与智能优化,提…...
OpenAI发布GPT-4.5:功能非常特殊,推理很贵
今天凌晨4点,OpenAI进行了在线技术直播,发布了最新模型GPT-4.5。 GPT-4.5与之前的模型相比,本次最大的亮点是加上了“情商”,这也是目前所有大模型最缺、最难的功能。 此外,GPT-4.5 在SimpleQA上的测试数据显示&…...
DeepSeek开源周 Day04:从DualPipe聊聊大模型分布式训练的并行策略
DualPipe简介 今天是DeepSeek开源周的第四天,官方开源了一种新型并行计算优化策略——DualPipe。 其实大家阅读过Deepseek-V3技术报告的同学,对这个技术并不陌生。 开源地址:https://github.com/deepseek-ai/DualPipe 核心亮点 DualPipe&…...
RabbitMQ系列(七)基本概念之Channel
RabbitMQ 中的 Channel(信道) 是客户端与 RabbitMQ 服务器通信的虚拟会话通道,其核心作用在于优化资源利用并提升消息处理效率。以下是其核心机制与功能的详细解析: 一、Channel 的核心定义 虚拟通信链路 Channel 是建立在 TCP 连…...
LeetCode 热题 100_有效的括号(69_20_简单_C++)(栈;栈+哈希表(建立左右括号的对应关系))
LeetCode 热题 100_有效的括号(69_20) 题目描述:输入输出样例:题解:解题思路:思路一(栈):思路二(栈哈希表(建立左右括号的对应关系)&a…...
c#-LINQ与lambda表达式学习笔记
https://blog.csdn.net/m0_56259289/article/details/144134122 static void Main(string[] args) //程序入口{int[] arr1 new int[] { 1, 2, 3, 4, 5, 6, 7 };int[] arr2 new int[] { 1, 2, 3, 4, 5, 6, 7 };var query1 from n in arr1 select n;var query2 from a in arr…...
数据库基础二(数据库安装配置)
打开MySQL官网进行安装包的下载 https://www.mysql.com/ 接着找到适用于windows的版本 下载版本 直接点击下载即可 接下来对应的内容分别是: 1:安装所有 MySQL 数据库需要的产品; 2:仅使用 MySQL 数据库的服务器; 3&a…...
Word 插入图片会到文字底下解决方案
一、现象描述 正常情况下,我们插入图片都是这样的。 但有时突然会这样,插入的图片陷于文字底部。 二、网上解决方案 网上有教程说,修改图片布局选项,从嵌入型改成上下型环绕。改完之后确实有用,但是需要手动拖动图片…...
有没有什么免费的AI工具可以帮忙做简单的ppt?
互联网各领域资料分享专区(不定期更新): Sheet 正文 1. 博思AIPPT 特点:专为中文用户设计,支持文本/文件导入生成PPT,内置海量模板和智能排版功能,涵盖商务、教育等多种场景。可一键优化布局、配色,并集成AI绘图功能(文生图/图生图)。适用场景:职场汇报、教育培训、商…...
实战-使用 Playbook 批量部署多台 LAMP 环境
实战-使用 Playbook 批量部署多台 LAMP 环境 playbooks 使用步骤 playbook 是一个不同于使用 ansible 命令行执行方式的模式,功能更强大更灵活。 1、在 playbooks 中定义任务: - name: task description #任务描述信息 module_name: modul…...
CSS—引入方式、选择器、复合选择器、文字控制属性、CSS特性
目录 CSS 1.引入方式 2.选择器 3.复合选择器 4.文字控制属性 5.CSS特性 CSS 层叠样式表,是一种样式表语言,用来描述HTML文档的呈现 书写时一般按照顺序:盒子模型属性—>文字样式—>圆角、阴影等修饰属性 1.引入方式 引入方式方…...
Spring 源码硬核解析系列专题(十):Spring Data JPA 的 ORM 源码解析
在前几期中,我们从 Spring 核心到 Spring Boot、Spring Cloud、Spring Security 和 Spring Batch,逐步揭示了 Spring 生态的多样性。在企业级开发中,数据访问是不可或缺的部分,而 Spring Data JPA 通过简化 JPA(Java Persistence API)操作,成为主流的 ORM 框架。本篇将深…...
爬虫和逆向教程-专栏介绍和目录
文章目录 一、爬虫基础和进阶二、App数据采集三、爬虫项目四、爬虫面试 本专栏为爬虫初学者和进阶开发者量身定制的爬虫和逆向学习园地。为你提供全面而深入的爬虫和逆向技术指导,从入门到精通,从基础理论到高级实战,助你在数据的海洋中畅游&…...
Lua | 每日一练 (4)
💢欢迎来到张胤尘的技术站 💥技术如江河,汇聚众志成。代码似星辰,照亮行征程。开源精神长,传承永不忘。携手共前行,未来更辉煌💥 文章目录 Lua | 每日一练 (4)题目参考答案线程和协程调度方式上…...
【折线图 Line】——1
🌟 解锁数据可视化的魔法钥匙 —— pyecharts实战指南 🌟 在这个数据为王的时代,每一次点击、每一次交易、每一份报告背后都隐藏着无尽的故事与洞察。但你是否曾苦恼于如何将这些冰冷的数据转化为直观、吸引人的视觉盛宴? 🔥 欢迎来到《pyecharts图形绘制大师班》 �…...
大白话前端性能优化,常见方法有哪些?
大白话前端性能优化,常见方法有哪些? 咱来唠唠前端性能优化,其实就是想办法让网页打开得更快、用起来更流畅,就跟给汽车做保养让它跑得更顺溜一样。下面详细说说常见的优化方法: 压缩代码 CSS 压缩:CSS …...
IP属地是通过卫星定位的吗?如何保护用户隐私
在数字时代,网络空间成为了人们日常生活不可或缺的一部分。随着社交媒体、在线服务等平台的兴起,用户IP属地信息的重要性日益凸显。然而,关于IP属地是如何确定的,尤其是是否通过卫星定位这一问题,却常常引发公众的疑问…...
Vue3+Node/Express支付宝沙箱支付与确认支付
Vue3Node/Express支付宝沙箱支付与确认支付 支付宝沙箱配置进入沙箱选择自定义密钥 密钥工具下载生成密钥格式转换 自定义密钥设置Express安装依赖项目目录创建alipay.js请求(打开支付)代码router/pay.jsapp.js 前端代码前端封装接口前端调用 实现支付查…...
什么是大语言模型
大语言模型(Large Language Model,LLM)是一种基于深度学习技术的人工智能模型,旨在理解和生成人类语言。以下是大语言模型的详细介绍: 一、基本概念 大语言模型通常包含数百亿甚至数千亿个参数,通过在海量…...
本地部署Embedding模型API服务的实战教程
大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于大模型算法的研究与应用。曾担任百度千帆大模型比赛、BPAA算法大赛评委,编写微软OpenAI考试认证指导手册。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。授权多项发明专利。对机器学…...
postgresql postgis扩展相关
项目 下载地址 http://rpmfind.net/linux/rpm2html/search.php?queryprotobuf(x86-64) Postgis Index of /postgis/source/ proj4 Index of /proj/ geos Index of /geos/ libxml2 ftp://xmlsoft.org/libxml2/ Index of /sources Json-c Releases json-c/json-c G…...
FFmpeg-chapter3-读取视频流(原理篇)
ffmpeg网站:About FFmpeg 1 库介绍 (1)libavutil是一个包含简化编程函数的库,包括随机数生成器、数据结构、数学例程、核心多媒体实用程序等等。 (2)libavcodec是一个包含音频/视频编解码器的解码器和编…...
入门基础项目(SpringBoot+Vue)
文章目录 1. css布局相关2. JS3. Vue 脚手架搭建4. ElementUI4.1 引入ElementUI4.2 首页4.2.1 整体框架4.2.2 Aside-logo4.2.3 Aside-菜单4.2.4 Header-左侧4.2.5 Header-右侧4.2.6 iconfont 自定义图标4.2.7 完整代码 4.3 封装前后端交互工具 axios4.3.1 安装 axios4.3.2 /src…...
C#调用CANoeCLRAdapter.dll文章(二)
一、引言 在上一篇指南中,我们介绍了如何通过C#调用CANoeCLRAdapter.dll实现基础功能,包括COM接口操作、DLL导入和PANL面板集成。本文将进一步探讨高级功能开发,涵盖事件驱动编程、CAPL脚本双向通信以及异步任务处理,帮助开发者构…...
ai大模型自动化测试-TensorFlow Testing 测试模型实例
AI大模型自动化测试是确保模型质量、可靠性和性能的关键环节,以下将从测试流程、测试内容、测试工具及测试挑战与应对几个方面进行详细介绍: 测试流程 测试计划制定 确定测试目标:明确要测试的AI大模型的具体功能、性能、安全性等方面的目标,例如评估模型在特定任务上的准…...
QT——c++界面编程库
非界面编程 QT编译的时候,依赖于 .pro 配置文件: SOURCES: 所有需要参与编译的 .cpp 源文件 HEADERS:所有需要参与编译的.h 头文件 QT:所有需要参与编译的 QT函数库 .pro文件一旦修改,注意需要键盘按 ctrls 才能加载最新的配置文…...
postman--接口测试工具安装和使用教程
postman–接口测试工具 postman是一款支持http协议的接口调试与测试工具,其主要特点就是功能强大,使用简单且易用性好 。 无论是开发人员进行接口调试,还是测试人员做接口测试,postman都是我们的首选工具之一 。 下面先通过一张…...
如何用python画一棵分形树
这个代码会生成一个彩色的分形树图案,可以通过调整draw_tree函数中的参数来改变树的形状和大小 import turtle import random# 递归函数绘制分形树 def draw_tree(branch_len, t):if branch_len > 5:t.color(random.choice(colors))t.pensize(branch_len / 10)t…...
【leetcode】二分查找专题
文章目录 1.二分查找1.题目2.解题思路3. 解题代码 2.在排序数组中查找元素的第一个和最后一个位置1.题目2.算法原理3. 代码 3.x的平方根1.题目2.代码 4.搜索插入位置1.题目2.解题思路3.解题代码 5.山脉数组的索引1.题目2.解题思路3. 代码 6.寻找峰值1.题目2.解题思路3.代码 7. …...
深度学习笔记17-马铃薯病害识别(VGG-16复现)
目录 一、 前期准备 1. 设置GPU 2. 导入数据 二、手动搭建VGG-16模型 1. 搭建模型 三、 训练模型 1. 编写训练函数 3. 编写测试函数 4. 正式训练 四、 结果可视化 1. Loss与Accuracy图 2. 指定图片进行预测 3. 模型评估 前言 🍨 本文为🔗365天深度学习训…...
【LeetCode】131.分割回文串
目录 题目描述输入输出示例及数据范围思路C 实现 题目描述 这道题目来自 LeetCode 131. 分割回文串。 题目描述如下: 给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。 输入输出示例及数据…...
【AIGC系列】5:视频生成模型数据处理和预训练流程介绍(Sora、MovieGen、HunyuanVideo)
AIGC系列博文: 【AIGC系列】1:自编码器(AutoEncoder, AE) 【AIGC系列】2:DALLE 2模型介绍(内含扩散模型介绍) 【AIGC系列】3:Stable Diffusion模型原理介绍 【AIGC系列】4࿱…...
基于C++“简单且有效”的“数据库连接池”
前言 数据库连接池在开发中应该是很常用的一个组件,他可以很好的节省连接数据库的时间开销;本文基使用C实现了一个简单的数据库连接池,代码量只有400行左右,但是压力测试效果很好;欢迎收藏 关注,本人将会…...
vulnhub靶场【kioptrix-4】靶机
前言 靶机:kioptrix-4,IP地址为192.168.1.75,后期IP地址为192.168.10.8 攻击:kali,IP地址为192.168.1.16,后期IP地址为192.168.10.6 都采用VMware虚拟机,网卡为桥接模式 这里的靶机…...
科普:ROC AUC与PR AUC
在评价二分类模型性能时,有许多评价指标,其中,有一对是用面积AUC(Area Under the Curve)做评价的:ROC AUC与PR AUC 本文我们对ROC AUC与PR AUC进行多维度对比分析: 一、定义与核心原理 维度RO…...
服务器IPMI用户名、密码批量检查
背景 大规模服务器部署的时候,少不了较多的网管和监测平台,这些平台会去监控服务器的性能、硬件等指标参数,为了便于管理和控制,则需要给服务器IPMI带外管理添加较多的用户,这就需要对较多的服务器检查所对应的IPMI用…...
51单片机中reg52.h与regx52.h在进行位操作时的不同
reg52.h中不能使用例如 P2_0;这样的定义 而只能使用 P2^0;这样的定义 但是都不可以对位进行直接赋值操作; 而 regx52.h中可以使用 P2_0和P2^0;但是只有使用下划线的才可以对位进行赋值操作 例如P2_0 1; 但不可以是P2^0 1; 在 C 语言中,…...
Apollo Cyber 学习笔记
目录 0 Introduction What Why Advantage 1 Example 2 Concept 3 Flow Chart 4 Module 4.1 Transport 4.1.1 Share Memory 4.1.1.1 Segment 4.1.1.1.1 State 4.1.1.1.2 Block 4.1.1.1.3 Common 4.1.1.2 Notifier 4.1.1.2.1 ConditionNotifier 4.1.1.2.2 Multi…...
【Electron入门】进程环境和隔离
目录 一、主进程和渲染进程 1、主进程(main) 2、渲染进程(renderer) 二、预加载脚本 三、沙盒化 为单个进程禁用沙盒 全局启用沙盒 四、环境访问权限控制:contextIsolation和nodeIntegration 1、contextIsola…...
拉链表介绍
拉链表 是处理 缓慢变化维(SCD) 的一种常用方法,特别适用于需要保留历史记录的场景。以下是拉链表的详细说明及实现方法: 1. 什么是拉链表? 拉链表是一种用于记录维度数据历史变化的表结构,通过 开始时间 …...
Spring Boot 日志配置与常见问题解析(详解)
目录 Spring Boot 日志配置与常见问题解析引言什么是日志?日志的重要性日志使用打印日志 日志框架介绍日志格式的说明⽇志级别日志级别的分类日志级别的使用 Spring Boot 日志配置1. 设置日志级别和格式2. 配置日志收集器3. 查看和分析日志4.日志的持久化5.设置日志…...
-bash: lsof: command not found
一、问题说明 执行如下命令时报错: # lsof |grep deleted > deleted_file -bash: lsof: command not found二、处理方法 # yum -y install lsof安装完成后可成功执行上面的命令。...