【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.pswp.cn/web/74008.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/74008.shtml
英文地址,請注明出處:http://en.pswp.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;北京國信華源科技有限公司攜自主研發的入戶叫應預警系統及覆蓋防汛抗旱全鏈條的智慧化場…