【TensorRT】TensorRT从安装到推理——Python 环境下 MobileNetV4 三分类任务

我想开发一个基于深度学习的分类小软件,逐渐了解到了TensorRT在模型推理速度上的优势,经过一下午资料的查找实现了将onnx模型转为TensorRT格式模型的推理及测试过程。将实现过程记录下来方便日后查看。

本文实验设备是MX350显卡 2G显存
在这里插入图片描述

一 、安装TensorRT

点击TensorRT下载链接,选择合适的TensorRT版本下载,读者选择使用TensorRT进行推理,默认已经配置好cuda和cudnn环境,如果没配置好请移步这篇博客Windows配置深度学习环境(从查询合适的torch版本开始)——torch+CUDA+cuDNN

TensorRT与cuda版本对应方式查看如下:

  1. 点击TensorRT版本
    在这里插入图片描述

  2. 点击同意
    在这里插入图片描述

  3. 点击版本号
    在这里插入图片描述

  4. 查看cuda版本是否符合你设备,点击下载即可
    在这里插入图片描述

二、环境配置

  1. 下载后得到文件结构如下所示
    在这里插入图片描述
  2. 添加环境变量,右键此电脑点击属性,根据图中序号依次点击并添加环境变量
    我的环境变量如下所示
D:\Software\TensorRT-8.6.1.6\lib
D:\Software\TensorRT-8.6.1.6\bin

在这里插入图片描述

三、模型转换

打开命令行窗口,切换到D:\Software\TensorRT-8.6.1.6\bin目录,执行如下命令

trtexec --onnx=mymodel.onnx --saveEngine=model.trt --fp16

这里的–fp16应该也可以改成int8,但是精度损失会有点大,我没有实验
这个mymodel.onnx需要你自己的onnx文件名,这个model.trt 就随便起名字了
在这里插入图片描述
如下图所示为转换成功
在这里插入图片描述

四、TensorRT与ONNX推理速度与精度测试

推理时间测试

  1. TensorRT推理时间测试代码
import tensorrt as trt
import pycuda.driver as cuda
import pycuda.autoinit
import cv2
import os
import numpy as np
import time
from typing import Tupledef softmax(x: np.ndarray) -> np.ndarray:"""计算softmax"""e_x = np.exp(x - np.max(x))  # 防止数值溢出return e_x / e_x.sum(axis=0)class TensorRTPredictor:def __init__(self, engine_path: str):"""初始化TensorRT预测器"""self.logger = trt.Logger(trt.Logger.WARNING)self.engine = self._load_engine(engine_path)self.context = self.engine.create_execution_context()self.input_shape = tuple(self.engine.get_tensor_shape(self.engine.get_tensor_name(0)))self.output_shape = tuple(self.engine.get_tensor_shape(self.engine.get_tensor_name(1)))self.is_warmed_up = Falsedef _load_engine(self, engine_path: str) -> trt.ICudaEngine:"""加载TensorRT引擎"""load_start_time = time.time()with open(engine_path, "rb") as f, trt.Runtime(self.logger) as runtime:engine = runtime.deserialize_cuda_engine(f.read())load_end_time = time.time()load_time = (load_end_time - load_start_time) * 1000print(f"加载引擎时间: {load_time:.2f} ms")return enginedef preprocess_image(self, image_path: str) -> np.ndarray:"""图像预处理"""preprocess_start_time = time.time()if not os.path.exists(image_path):raise FileNotFoundError(f"图像文件不存在: {os.path.abspath(image_path)}")image = cv2.imread(image_path)if image is None:raise ValueError("无法读取图像,请检查文件格式和完整性")try:image = cv2.resize(image, (224, 224))image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)image = np.ascontiguousarray(image.transpose(2, 0, 1).astype(np.float32) / 255.0)mean = np.array([0.362, 0.279, 0.258]).reshape(3, 1, 1)std = np.array([0.222, 0.191, 0.185]).reshape(3, 1, 1)image = (image - mean) / stdexcept Exception as e:raise RuntimeError(f"图像预处理失败: {str(e)}")preprocess_end_time = time.time()preprocess_time = (preprocess_end_time - preprocess_start_time) * 1000print(f"  预处理时间: {preprocess_time:.2f} ms")return imagedef warmup(self, iterations: int = 10):"""模型预热"""if self.is_warmed_up:print("模型已经预热,跳过预热步骤")returnwarmup_start_time = time.time()input_size = int(np.prod(self.input_shape)) * np.float32().itemsizeoutput_size = int(np.prod(self.output_shape)) * np.float32().itemsized_input = cuda.mem_alloc(input_size)d_output = cuda.mem_alloc(output_size)stream = cuda.Stream()dummy_input = np.random.rand(*self.input_shape).astype(np.float32)for _ in range(iterations):cuda.memcpy_htod_async(d_input, dummy_input, stream)self.context.execute_async_v2(bindings=[int(d_input), int(d_output)],stream_handle=stream.handle)stream.synchronize()d_input.free()d_output.free()warmup_end_time = time.time()warmup_time = (warmup_end_time - warmup_start_time) * 1000print(f"  预热时间: {warmup_time:.2f} ms")self.is_warmed_up = Truedef infer(self, image: np.ndarray) -> Tuple[float, np.ndarray]:"""执行TensorRT推理"""if not self.is_warmed_up:print("警告:模型尚未预热,推理性能可能受影响")input_size = int(np.prod(self.input_shape)) * np.float32().itemsizeoutput_size = int(np.prod(self.output_shape)) * np.float32().itemsized_input = cuda.mem_alloc(input_size)d_output = cuda.mem_alloc(output_size)stream = cuda.Stream()input_data = np.ascontiguousarray(np.expand_dims(image, axis=0), dtype=np.float32)# 正式推理infer_start_time = time.time()cuda.memcpy_htod_async(d_input, input_data, stream)self.context.execute_async_v2(bindings=[int(d_input), int(d_output)],stream_handle=stream.handle)stream.synchronize()infer_end_time = time.time()infer_time = (infer_end_time - infer_start_time) * 1000print(f"  TensorRT 推理时间: {infer_time:.2f} ms")# 获取输出output_data = np.empty(self.output_shape, dtype=np.float32)output_start_time = time.time()cuda.memcpy_dtoh_async(output_data, d_output, stream)stream.synchronize()output_end_time = time.time()output_time = (output_end_time - output_start_time) * 1000print(f"  获取输出时间: {output_time:.2f} ms")# 置信度confidence = softmax(output_data[0])d_input.free()d_output.free()return infer_time, output_data, confidenceif __name__ == "__main__":# 配置路径PATHS = {"image_folder": "D:/Desktop/DATA/balance_bei_liao_hu/temp",  # 图片文件夹路径"engine": "mnv4.engine"  # TensorRT引擎文件路径}# 验证文件夹和文件存在if not os.path.exists(PATHS["image_folder"]):print(f"错误: 图片文件夹不存在 -> {os.path.abspath(PATHS['image_folder'])}")exit(1)if not os.path.exists(PATHS["engine"]):print(f"错误: 引擎文件不存在 -> {os.path.abspath(PATHS['engine'])}")exit(1)# 获取文件夹中所有图片文件(包括子文件夹)image_files = []for root, _, files in os.walk(PATHS["image_folder"]):for file in files:if file.endswith(('.jpg', '.png', '.bmp', '.jpeg')):image_files.append(os.path.join(root, file))if not image_files:print(f"错误: 文件夹中没有图片文件 -> {PATHS['image_folder']}")exit(1)# 初始化预测器predictor = TensorRTPredictor(PATHS["engine"])predictor.warmup(iterations=10)  # 预热模型total_time = 0total_preprocess_time = 0for image_path in image_files:try:print(f"处理图片: {image_path}")img = predictor.preprocess_image(image_path)trt_time, trt_out, trt_confidence = predictor.infer(img)print(f"  TensorRT 输出: {np.argmax(trt_out)} (置信度: {np.max(trt_confidence):.4f})")total_time += trt_timeexcept Exception as e:print(f"处理图片时出错: {image_path} -> {str(e)}")avg_time = total_time / len(image_files)print(f"\n平均推理时间: {avg_time:.2f} ms")

这里TensorRT推理150张224×224图片平均速度为5.50ms
在这里插入图片描述

  1. ONNX推理时间测试代码
import onnxruntime as ort
import numpy as np
from PIL import Image
from torchvision import transforms
from timm.data import IMAGENET_DEFAULT_MEAN, IMAGENET_DEFAULT_STD
import time
import osdef softmax(x: np.ndarray) -> np.ndarray:"""计算softmax"""e_x = np.exp(x - np.max(x))  # 防止数值溢出return e_x / e_x.sum(axis=0)class ONNXPredictor:def __init__(self, model_path="mobilenetv4_hybrid_medium.onnx", size=224):# 自动检测可用providerself.providers = self._get_available_providers()print(f"可用推理后端: {self.providers}")# 初始化ONNX Runtime会话self.session = ort.InferenceSession(model_path, providers=self.providers)# 获取当前使用的provider信息current_provider = self.session.get_providers()print(f"实际使用的推理后端: {current_provider}")# 获取输入输出名称self.input_name = self.session.get_inputs()[0].nameself.output_name = self.session.get_outputs()[0].name# 预处理变换self.transform = self.build_transform(size)# 预热标志self.is_warmed_up = Falsedef _get_available_providers(self):"""获取可用的推理后端,优先使用CUDA且仅使用CUDA(如果可用)"""available_providers = ort.get_available_providers()# 优先使用CUDA且仅使用CUDAif 'CUDAExecutionProvider' in available_providers:return ['CUDAExecutionProvider']  # 仅返回CUDA# 如果没有CUDA,则回退到CPUelif 'CPUExecutionProvider' in available_providers:return ['CPUExecutionProvider']else:raise RuntimeError("没有可用的执行提供程序(既没有CUDA也没有CPU)")def build_transform(self, size: int):"""构建图像预处理流水线"""return transforms.Compose([transforms.Resize(size, interpolation=transforms.InterpolationMode.BICUBIC),transforms.CenterCrop(size),transforms.ToTensor(),transforms.Normalize(IMAGENET_DEFAULT_MEAN, IMAGENET_DEFAULT_STD)])def preprocess(self, image):"""预处理图像"""# 如果输入是文件路径,先加载图像if isinstance(image, str):image = Image.open(image).convert('RGB')# 应用变换并添加batch维度return self.transform(image).unsqueeze(0).numpy()def warmup(self, iterations=10):"""预热模型"""dummy_input = np.random.rand(1, 3, 224, 224).astype(np.float32)for _ in range(iterations):self.session.run([self.output_name], {self.input_name: dummy_input})self.is_warmed_up = Trueprint(f"模型已预热 {iterations} 次")def predict(self, image):"""执行预测"""# 预处理input_data = self.preprocess(image)# 运行模型outputs = self.session.run([self.output_name], {self.input_name: input_data})[0]confidence = softmax(outputs[0])return outputs, confidenceif __name__ == "__main__":# 配置路径PATHS = {"image_folder": "D:/Desktop/DATA/balance_bei_liao_hu/temp",  # 图片文件夹路径"model_path": "mobilenetv4_hybrid_medium.onnx"  # ONNX模型文件路径}# 验证文件夹和文件存在if not os.path.exists(PATHS["image_folder"]):print(f"错误: 图片文件夹不存在 -> {os.path.abspath(PATHS['image_folder'])}")exit(1)if not os.path.exists(PATHS["model_path"]):print(f"错误: 模型文件不存在 -> {os.path.abspath(PATHS['model_path'])}")exit(1)# 获取文件夹中所有图片文件(包括子文件夹)image_files = []for root, _, files in os.walk(PATHS["image_folder"]):for file in files:if file.endswith(('.jpg', '.png', '.bmp', '.jpeg')):image_files.append(os.path.join(root, file))if not image_files:print(f"错误: 文件夹中没有图片文件 -> {PATHS['image_folder']}")exit(1)# 初始化预测器predictor = ONNXPredictor(model_path=PATHS["model_path"], size=224)predictor.warmup(iterations=10)  # 预热模型total_time = 0for image_path in image_files:try:print(f"处理图片: {image_path}")start_time = time.time()predictions, confidence = predictor.predict(image_path)end_time = time.time()inference_time = (end_time - start_time) * 1000  # 转换为毫秒print(f"  ONNX 推理时间: {inference_time:.2f} ms")print(f"  ONNX 输出: {np.argmax(predictions)} (置信度: {np.max(confidence):.4f})")total_time += inference_timeexcept Exception as e:print(f"处理图片时出错: {image_path} -> {str(e)}")avg_time = total_time / len(image_files)print(f"\n平均推理时间: {avg_time:.2f} ms")

在这里插入图片描述

两种格式的模型分别预测了150张尺寸为224×224的三类图片,每一类有50张,调用TensorRT平均每张图片需要5.17ms,而onnx平均每张图片需要11.11ms,TensorRT模型的推理速度缩短为onnx的二分之一,根据查找的资料显示,转换后的模型推理时间的缩短可能与设备有关。

精度测试

  1. TensorRT推理代码
import tensorrt as trt
import pycuda.driver as cuda
import pycuda.autoinit
import cv2
import os
import numpy as np
import time
from typing import Tuple
from sklearn.metrics import classification_report, accuracy_score, f1_score
from collections import Counterclass TensorRTPredictor:def __init__(self, engine_path: str):"""初始化TensorRT预测器"""self.logger = trt.Logger(trt.Logger.WARNING)self.engine = self._load_engine(engine_path)self.context = self.engine.create_execution_context()self.input_shape = tuple(self.engine.get_tensor_shape(self.engine.get_tensor_name(0)))self.output_shape = tuple(self.engine.get_tensor_shape(self.engine.get_tensor_name(1)))self.is_warmed_up = Falseself.warmup(iterations=10)  # 在初始化时进行预热def _load_engine(self, engine_path: str) -> trt.ICudaEngine:"""加载TensorRT引擎"""load_start_time = time.time()with open(engine_path, "rb") as f, trt.Runtime(self.logger) as runtime:engine = runtime.deserialize_cuda_engine(f.read())load_end_time = time.time()load_time = (load_end_time - load_start_time) * 1000print(f"加载引擎时间: {load_time:.2f} ms")return enginedef preprocess_image(self, image_path: str) -> np.ndarray:"""图像预处理"""preprocess_start_time = time.time()if not os.path.exists(image_path):raise FileNotFoundError(f"图像文件不存在: {os.path.abspath(image_path)}")image = cv2.imread(image_path)if image is None:raise ValueError("无法读取图像,请检查文件格式和完整性")try:image = cv2.resize(image, (224, 224))image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)image = np.ascontiguousarray(image.transpose(2, 0, 1).astype(np.float32) / 255.0)mean = np.array([0.362, 0.279, 0.258]).reshape(3, 1, 1)std = np.array([0.222, 0.191, 0.185]).reshape(3, 1, 1)image = (image - mean) / stdexcept Exception as e:raise RuntimeError(f"图像预处理失败: {str(e)}")preprocess_end_time = time.time()preprocess_time = (preprocess_end_time - preprocess_start_time) * 1000print(f"  预处理时间: {preprocess_time:.2f} ms")return imagedef warmup(self, iterations: int = 10):"""模型预热"""if self.is_warmed_up:print("模型已经预热,跳过预热步骤")returnwarmup_start_time = time.time()input_size = int(np.prod(self.input_shape)) * np.float32().itemsizeoutput_size = int(np.prod(self.output_shape)) * np.float32().itemsized_input = cuda.mem_alloc(input_size)d_output = cuda.mem_alloc(output_size)stream = cuda.Stream()dummy_input = np.random.rand(*self.input_shape).astype(np.float32)for _ in range(iterations):cuda.memcpy_htod_async(d_input, dummy_input, stream)self.context.execute_async_v2(bindings=[int(d_input), int(d_output)],stream_handle=stream.handle)stream.synchronize()d_input.free()d_output.free()warmup_end_time = time.time()warmup_time = (warmup_end_time - warmup_start_time) * 1000print(f"  预热时间: {warmup_time:.2f} ms")self.is_warmed_up = Truedef infer(self, image: np.ndarray) -> Tuple[float, np.ndarray]:"""执行TensorRT推理"""if not self.is_warmed_up:print("警告:模型尚未预热,推理性能可能受影响")input_size = int(np.prod(self.input_shape)) * np.float32().itemsizeoutput_size = int(np.prod(self.output_shape)) * np.float32().itemsized_input = cuda.mem_alloc(input_size)d_output = cuda.mem_alloc(output_size)stream = cuda.Stream()input_data = np.ascontiguousarray(np.expand_dims(image, axis=0), dtype=np.float32)# 正式推理infer_start_time = time.time()cuda.memcpy_htod_async(d_input, input_data, stream)self.context.execute_async_v2(bindings=[int(d_input), int(d_output)],stream_handle=stream.handle)stream.synchronize()infer_end_time = time.time()infer_time = (infer_end_time - infer_start_time) * 1000print(f"  TensorRT 推理时间: {infer_time:.2f} ms")# 获取输出output_data = np.empty(self.output_shape, dtype=np.float32)output_start_time = time.time()cuda.memcpy_dtoh_async(output_data, d_output, stream)stream.synchronize()output_end_time = time.time()output_time = (output_end_time - output_start_time) * 1000print(f"  获取输出时间: {output_time:.2f} ms")d_input.free()d_output.free()return infer_time, output_dataif __name__ == "__main__":# 配置路径PATHS = {"image_folder": "D:/Desktop/DATA/balance_bei_liao_hu/temp",  # 图片文件夹路径"engine": "mnv4.engine"  # TensorRT引擎文件路径}# 验证文件夹和文件存在if not os.path.exists(PATHS["image_folder"]):print(f"错误: 图片文件夹不存在 -> {os.path.abspath(PATHS['image_folder'])}")exit(1)if not os.path.exists(PATHS["engine"]):print(f"错误: 引擎文件不存在 -> {os.path.abspath(PATHS['engine'])}")exit(1)# 获取文件夹中所有图片文件(包括子文件夹)image_files = []for root, _, files in os.walk(PATHS["image_folder"]):for file in files:if file.endswith(('.jpg', '.png', '.bmp', '.jpeg')):image_files.append(os.path.join(root, file))if not image_files:print(f"错误: 文件夹中没有图片文件 -> {PATHS['image_folder']}")exit(1)# 初始化预测器predictor = TensorRTPredictor(PATHS["engine"])# 初始化分类结果统计true_labels = []predicted_labels = []label_mapping = {0: "B", 1: "D", 2: "E"}total_time = 0for image_path in image_files:try:print(f"处理图片: {image_path}")img = predictor.preprocess_image(image_path)trt_time, trt_out = predictor.infer(img)print(f"  TensorRT 推理时间: {trt_time:.2f} ms")predicted_label = np.argmax(trt_out)predicted_labels.append(predicted_label)# 从文件路径中提取真实标签true_label = os.path.basename(os.path.dirname(image_path))true_labels.append(true_label)total_time += trt_timeexcept Exception as e:print(f"处理图片时出错: {image_path} -> {str(e)}")avg_time = total_time / len(image_files)print(f"\n平均推理时间: {avg_time:.2f} ms")# 计算分类结果true_labels = [label for label in true_labels]predicted_labels = [label_mapping[label] for label in predicted_labels]print("\n分类结果统计:")print(f"图片总数: {len(image_files)}")print(f"分类结果: {Counter(predicted_labels)}")# 计算准确率和 F1 分数accuracy = accuracy_score(true_labels, predicted_labels)f1 = f1_score(true_labels, predicted_labels, average='weighted')print(f"准确率: {accuracy:.4f}")  # 保留四位小数print(f"F1 分数: {f1:.4f}")  # 保留四位小数# 输出详细的分类报告print("\n分类报告:")print(classification_report(true_labels, predicted_labels, digits=4))  # 保留四位小数
  1. onnx推理代码
from datasets.split_data import read_split_data
from datasets.mydataset import MyDataset
from torchvision import transforms
from timm.data import IMAGENET_DEFAULT_MEAN, IMAGENET_DEFAULT_STD
import torch
from estimate_model import Predictor, Plot_ROC
from timm.models import create_model
import os, cv2, json, random
import pandas as pd
from tqdm import tqdm
import matplotlib.pyplot as pltdef read_test_data(root, plot_image=False):filepaths = []labels = []bad_images = []random.seed(0)assert os.path.exists(root), 'Your root does not exists!!!'classes = [cla for cla in os.listdir(root) if os.path.isdir(os.path.join(root, cla))]classes.sort()class_indices = {k: v for v, k in enumerate(classes)}json_str = json.dumps({v: k for k, v in class_indices.items()}, indent=4)with open('output/classes_indices.json', 'w') as json_file:json_file.write(json_str)every_class_num = []supported = ['.jpg', '.png', '.jpeg', '.PNG', '.JPG', '.JPEG', '.bmp']for klass in classes:classpath = os.path.join(root, klass)images = [os.path.join(root, klass, i) for i in os.listdir(classpath) if os.path.splitext(i)[-1] in supported]every_class_num.append(len(images))flist = sorted(os.listdir(classpath))desc = f'{klass:23s}'for f in tqdm(flist, ncols=110, desc=desc, unit='file', colour='blue'):fpath = os.path.join(classpath, f)fl = f.lower()index = fl.rfind('.')ext = fl[index:]if ext in supported:try:img = cv2.imread(fpath)filepaths.append(fpath)labels.append(klass)except:bad_images.append(fpath)print('defective image file: ', fpath)else:bad_images.append(fpath)Fseries = pd.Series(filepaths, name='filepaths')Lseries = pd.Series(labels, name='labels')df = pd.concat([Fseries, Lseries], axis=1)print(f'{len(df.labels.unique())} kind of images were found in the dataset')test_image_path = df['filepaths'].tolist()test_image_label = [class_indices[i] for i in df['labels'].tolist()]sample_df = df.sample(n=50, replace=False)ht, wt, count = 0, 0, 0for i in range(len(sample_df)):fpath = sample_df['filepaths'].iloc[i]try:img = cv2.imread(fpath)h = img.shape[0]w = img.shape[1]ht += hwt += wcount += 1except:passhave = int(ht / count)wave = int(wt / count)aspect_ratio = have / waveprint('{} images were found in the dataset.\n{} for test'.format(sum(every_class_num), len(test_image_path)))print('average image height= ', have, '  average image width= ', wave, ' aspect ratio h/w= ', aspect_ratio)if plot_image:plt.bar(range(len(classes)), every_class_num, align='center')plt.xticks(range(len(classes)), classes)for i, v in enumerate(every_class_num):plt.text(x=i, y=v + 5, s=str(v), ha='center')plt.xlabel('image class')plt.ylabel('number of images')plt.title('class distribution')plt.show()return test_image_path, test_image_labeltest_image_path, test_image_label = read_test_data('D:/Desktop/DATA/balance_bei_liao_hu/temp', False)def build_transform(img_size):t = []t.append(# to maintain same ratio w.r.t. 224 imagestransforms.Resize(img_size, interpolation=3),)t.append(transforms.CenterCrop(img_size))t.append(transforms.ToTensor())t.append(transforms.Normalize(IMAGENET_DEFAULT_MEAN, IMAGENET_DEFAULT_STD))return transforms.Compose(t)test_transform = build_transform(224)test_set = MyDataset(test_image_path, test_image_label, test_transform)sampler_val = torch.utils.data.SequentialSampler(test_set)data_loader_val = torch.utils.data.DataLoader(test_set, sampler=sampler_val,batch_size=int(1.5 * 24),num_workers=0,pin_memory=True,drop_last=False
)
model_predict = create_model('mobilenetv4_hybrid_medium')model_predict.reset_classifier(num_classes=3)
model_predict.to('cuda')
device = torch.device('cuda')Predictor(model_predict, data_loader_val, f'./output/mobilenetv4_hybrid_medium_best_checkpoint.pth', device)
Plot_ROC(model_predict, data_loader_val, f'./output/mobilenetv4_hybrid_medium_best_checkpoint.pth', device)
  1. 结果:
  • TensorRT:
    在这里插入图片描述

  • onnx:
    在这里插入图片描述

可以观察到在转成TensorRT推理后模型精度下降明显,宏平均Precision下降了约4%,宏平均召回下降了约10%,宏平均F1下降了约10%。

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

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

相关文章

1.两数之和(Java)

1. 题目描述 LeetCode 1. 两数之和(Two Sum) 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回它们的索引。 示例 1: 输入:nums [2,7,11,15], target 9 …

《深入探索 Python 数据分析:用 Pandas 高效处理与可视化大型数据集》

《深入探索 Python 数据分析:用 Pandas 高效处理与可视化大型数据集》 引言:从零到分析高手 数据是当代社会最宝贵的资源,而数据分析技能是现代职业人不可或缺的一部分。在数据科学的领域中,Python 已成为当之无愧的“首选语言”,其强大的生态系统和简洁的语法让人如虎添…

将树莓派5当做Ollama服务器,C#调用generate的API的示例

其实完全没这个必要,性能用脚后跟想都会很差。但基于上一篇文章的成果,来都来了就先简单试试吧。 先来看看这个拼夕夕上五百多块钱能达到的效果: 只要对速度没要求,那感觉就还行。 Ollama默认只在本地回环(127.0.0…

python基础学习二(列表及字典的使用)

文章目录 列表列表的创建获取列表中的多个元素判断列表中元素是否存在列表元素的添加操作列表元素的删除操作列表元素的修改列表的排序列表生成式 字典字典的创建字典的常规操作字典的常用操作字典的视图操作字典元素的遍历字典的特点字典的生成式 列表 一个对象由id&#xff0…

Android设计模式之代理模式

一、定义: 为其他对象提供一种代理以控制对这个对象的访问。 二、角色组成: Subject抽象主题:声明真是主题与代理的共同接口方法,可以是一个抽象类或接口。 RealSubject真实主题:定义了代理表示的真实对象&#xff0c…

国外计算机证书推荐(考证)(6 Sigma、AWS、APICS、IIA、Microsoft、Oracle、PMI、Red Hat)

文章目录 证书推荐1. 六西格玛 (6 Sigma)2. 亚马逊网络服务 (AWS)3. 美国生产与库存控制学会 (APICS)4. 内部审计师协会 (IIA)5. 微软 (Microsoft)6. 甲骨文 (Oracle)7. 项目管理协会 (PMI)8. 红帽 (Red Hat) 证书推荐 1. 六西格玛 (6 Sigma) 介绍:六西格玛是一种…

用mkdocs写文档#自动更新github-page

https://wuyisheng.github.io/blog 背景是上一篇博客 使用mkdocs,最后提及可以部署github page。这里说明下怎么自动部署。 当然,这篇博客主要的目的还是提供下github page的链接 :) 我是这样做的: step 1: pip3 i…

QT五 文件系统,QFile,QfileInfo

总览 QIODevice:所有 I/O 设备类的父类,提供了字节块读写的通用操作以及基本接口;QFileDevice:Qt5新增加的类,提供了有关文件操作的通用实现。QFlie:访问本地文件或者嵌入资源;QTemporaryFile&a…

EF Core表达式树

文章目录 前言一、表达式树与委托的区别二、动态构建表达式树示例1示例2示例3高级技巧:表达式合并 三、ExpressionTreeToString安装方法基本用法支持的格式化风格 四、注意事项总结 前言 在 Entity Framework Core 中,表达式树(Expression T…

NVM安装速通使用手册(Windows版)NVM管理node版本命令手册 NVM使用手册

nvm(Node Version Manager)是一个用于管理Node.js版本的命令行工具。通过nvm,你可以在同一台机器上安装和切换多个Node.js版本,非常适合开发和测试在不同Node.js版本上运行的应用程序 一、安装地址 1. 官方下载: &…

vLLM命令行使用方法详解

vLLM 是一个针对大语言模型(LLMs)优化的高效推理和服务库。以下是 vLLM 命令行工具的详细使用方法解析,涵盖常见场景和参数配置: 一、核心命令行工具 vLLM 提供两个主要的命令行入口: 启动 API 服务器 用于部署 HTTP/OpenAI 兼容的 API 服务: python -m vllm.entrypoint…

# 基于 OpenCV 的选择题自动批改系统实现

在教育领域,选择题的批改工作通常较为繁琐且重复性高。为了提高批改效率,我们可以利用计算机视觉技术,通过 OpenCV 实现选择题的自动批改。本文将详细介绍如何使用 Python 和 OpenCV 实现一个简单的选择题自动批改系统。 1. 项目背景 选择题…

python黑科技:无痛修改第三方库源码

需求不符合 很多时候,我们下载的 第三方库 是不会有需求不满足的情况,但也有极少的情况,第三方库 没有兼顾到需求,导致开发者无法实现相关功能。 如何通过一些操作将 第三方库 源码进行修改,是我们将要遇到的一个难点…

第十三章:优化内存管理_《C++性能优化指南》_notes

优化内存管理 一、内存管理基础概念二、自定义分配器三、智能指针优化重点知识代码示例:智能指针性能对比 四、性能优化关键点总结多选题设计题答案与详解多选题答案设计题示例答案(第1题) 一、内存管理基础概念 重点知识 动态内存分配开销…

python笔记之函数

函数初探 python在要写出函数很简单,通过关键字def即可写出,简单示例如下 def add(a, b):return ab 以上即可以定义出一个简单的函数:接收两个变量a和b,返回a和b相加的结果,当然这么说也不全对,原因就是…

【服务器操作指南 - GPU 使用与文件传输】轻松掌握 GPU 状态查看和服务器文件传输技巧

0. 引言 在使用服务器时,高效管理 GPU 和文件传输是两项不可或缺的技能。 本指南旨在帮助您快速掌握服务器环境下的 GPU 使用状态监测方法,并简要介绍如何在服务器之间进行文件传输操作。 1. 查看服务器上的 gpu 使用状态 1.1 安装 gpustat 这条指令…

0330-YYYY-MM-DD格式日期比较大小

最简单的&#xff08;python&#xff09; from datetime import datetime def compare_time(time1,time2): time1_t datetime.strptime(time1,“%Y-%m-%d”) time2_t datetime.strptime(time2,“%Y-%m-%d”) if time1_t < time2_t: return time1_t elif time1_t > ti…

QFlightInstruments飞行仪表控件库

QFlightInstruments 是一个开源的飞行仪表控件库&#xff0c;专为基于 Qt 的应用程序设计。它提供了一系列仿真实飞机仪表的组件&#xff0c;适用于飞行模拟软件、航空电子系统或任何需要高仿真飞行仪表显示的项目。 主要功能 高仿真飞行仪表&#xff1a;包括空速表、高度表、…

VSCode 市场发现恶意扩展正在传播勒索软件!

在VSCode 市场中发现了两个隐藏着勒索软件的恶意扩展。其中一个于去年 10 月出现在微软商店&#xff0c;但很长时间没有引起注意。 这些是扩展ahban.shiba 和 ahban.cychelloworld&#xff0c;目前已从商店中删除。 此外&#xff0c;ahban.cychelloworld 扩展于 2024 年 10 月…

国信华源携AI+水利创新成果亮相第十五届防汛抗旱信息化技术交流会

直击展会现场 近日&#xff0c;以“人工智能赋能防汛抗旱 融合创新共御极端灾害”为主题的第十五届防汛抗旱信息化技术交流会在河南郑州召开。作为水旱灾害防御领域的专精企业&#xff0c;北京国信华源科技有限公司携自主研发的入户叫应预警系统及覆盖防汛抗旱全链条的智慧化场…