目录

1. 速度 vs 精度分析

mvit:

r2plus1d_r50 推理代码:

x3d_xs推理代码:

R(2+1)D

X3D(轻量级,速度快)

I3D(经典 3D CNN)

替换分类层(适配你的任务)


https://github.com/facebookresearch/pytorchvideo/blob/main/docs/source/model_zoo.md

archdepthpretrainframe length x sample ratetop 1top 5Flops (G) x viewsParams (M)Model
C2DR50-8x871.4689.6825.89 x 3 x 1024.33link
I3DR50-8x873.2790.7037.53 x 3 x 1028.04link
SlowR50-4x1672.4090.1827.55 x 3 x 1032.45link
SlowR50-8x874.5891.6354.52 x 3 x 1032.45link
SlowFastR50-4x1675.3491.8936.69 x 3 x 1034.48link
SlowFastR50-8x876.9492.6965.71 x 3 x 1034.57link
SlowFastR101-8x877.9093.27127.20 x 3 x 1062.83link
SlowFastR101-16x878.7093.61215.61 x 3 x 1053.77link
CSNR101-32x277.0092.9075.62 x 3 x 1022.21link
R(2+1)DR50-16x476.0192.2376.45 x 3 x 1028.11link
X3DXS-4x1269.1288.630.91 x 3 x 103.79link
X3DS-13x673.3391.272.96 x 3 x 103.79link
X3DM-16x575.9492.726.72 x 3 x 103.79link
X3DL-16x577.4493.3126.64 x 3 x 106.15link
MViTB-16x478.8593.8570.80 x 1 x 536.61link
MViTB-32x380.3094.69170.37 x 1 x 536.61link

1. 速度 vs 精度分析

模型计算量/速度精度适合你需求的程度
X3D⭐⭐⭐⭐⭐ 最快⭐⭐⭐⭐ 较高🏆 最佳选择
R(2+1)D⭐⭐⭐ 中等⭐⭐⭐⭐⭐ 很高⭐⭐⭐ 不错但稍慢
I3D⭐⭐ 最慢⭐⭐⭐⭐ 较高⭐⭐ 不太适合
pip install pytorchvideo
import torch
from pytorchvideo.models import hubbackbone = getattr(hub, "r2plus1d_r50")(pretrained=False)backbone = torch.hub.load("facebookresearch/pytorchvideo", model="r2plus1d_r50", pretrained=True)

mvit:


import torch
import time
from torch import nn# 如果你用的是官方实现,可以替换成 mvit_v2_s/mvit_v2_b 等
# pip install torchvision>=0.13
from torchvision.models.video import mvit_v2_sdef val_mvit_inference_speed(device="cuda", warmup=10, test_iter=50):"""测试 MViT 网络推理速度:param device: 设备 ('cuda' or 'cpu'):param warmup: 预热次数(避免初次运行不稳定):param test_iter: 测试迭代次数"""# 1. 构建模型model = mvit_v2_s(pretrained=False)  # 可以换成 mvit_v2_bmodel = model.to(device)model.eval()# 2. 构造一个随机输入 (N, C, T, H, W)# 例如 1 帧视频片段 (16 帧, 3 通道, 224x224)dummy_input = torch.randn(1, 3, 16, 224, 224).to(device)# 3. 预热with torch.no_grad():for _ in range(warmup):_ = model(dummy_input)# 4. 正式测试torch.cuda.synchronize() if device.startswith("cuda") else Nonestart = time.time()with torch.no_grad():for _ in range(test_iter):_ = model(dummy_input)torch.cuda.synchronize() if device.startswith("cuda") else Noneend = time.time()avg_time = (end - start) / test_iterfps = 1 / avg_timeprint(f"设备: {device}")print(f"平均推理时间: {avg_time * 1000:.2f} ms/iter")print(f"推理速度: {fps:.2f} FPS")if __name__ == "__main__":val_mvit_inference_speed("cuda")   # GPU 测试# test_mvit_inference_speed("cpu")    # CPU 测试

r2plus1d_r50 推理代码:

224*224 分类需要60ms

import timeimport torch
import numpy as np
from PIL import Image
import torchvision.transforms as transformsdevice = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"使用设备: {device}")def load_x3d_xs_model():"""加载 X3D-XS 模型,更适合小分辨率"""# model = torch.hub.load('facebookresearch/pytorchvideo', 'x3d_xs', pretrained=True)# model = torch.hub.load('facebookresearch/pytorchvideo', 'x3d_s', pretrained=True)model = torch.hub.load("facebookresearch/pytorchvideo", model="r2plus1d_r50", pretrained=True)model = model.to(device)model.eval()return modeldef preprocess_for_x3d_xs(video_frames, target_size=182, crop_size=72):"""为 X3D-XS 预处理X3D-XS 设计用于较小分辨率,推荐 160×160"""mean = [0.45, 0.45, 0.45]std = [0.225, 0.225, 0.225]num_frames = 13  # X3D-XS 使用4帧# 帧数处理if len(video_frames) > num_frames:indices = np.linspace(0, len(video_frames) - 1, num_frames, dtype=int)video_frames = [video_frames[i] for i in indices]transform = transforms.Compose([transforms.Resize(target_size), transforms.CenterCrop(crop_size), transforms.ToTensor(), transforms.Normalize(mean=mean, std=std)])processed_frames = []for frame in video_frames:if isinstance(frame, np.ndarray):frame = Image.fromarray(frame)processed_frame = transform(frame)processed_frames.append(processed_frame)video_tensor = torch.stack(processed_frames).permute(1, 0, 2, 3)return video_tensor.unsqueeze(0)# 使用示例
model = load_x3d_xs_model()for i in range(10):dummy_frames = [np.random.randint(0, 255, (200, 200, 3), dtype=np.uint8) for _ in range(13)]input_tensor = preprocess_for_x3d_xs(dummy_frames)print(input_tensor.shape)input_tensor = input_tensor.to(device)start = time.time()with torch.no_grad():output = model(input_tensor)torch.cuda.synchronize()print(f"输出形状: {output.shape}", time.time() - start)  # 应该能正常工作

x3d_xs推理代码:

import torchimport osfrom torch import nnos.environ["FFCV_DISABLE_IOPATH"] = "1"
import torch.nn.functional as Ffrom pytorchvideo.models.x3d import create_x3d
import torchvision.transforms as T
from torchvision.io import read_video
import numpy as np
from PIL import Image
import cv2
import osclass VideoNormalize(nn.Module):def __init__(self, mean, std):super().__init__()self.register_buffer("mean", torch.tensor(mean).view(-1, 1, 1, 1))  # [C,1,1,1]self.register_buffer("std", torch.tensor(std).view(-1, 1, 1, 1))    # [C,1,1,1]def forward(self, x):# x: [C, T, H, W]return (x - self.mean) / self.stdclass X3DVideoClassifier:def __init__(self, model_type='x3d_xs', num_classes=2, device='auto'):"""初始化X3D视频分类器Args:model_type: 模型类型 ('x3d_xs', 'x3d_s', 'x3d_m')num_classes: 分类数量device: 运行设备 ('auto', 'cuda', 'cpu')"""self.model_type = model_typeself.num_classes = num_classesself.device = deviceif device == 'auto':self.device = 'cuda' if torch.cuda.is_available() else 'cpu'self._load_model()self._setup_transforms()def _load_model(self):"""加载预训练模型"""# model_map = {'x3d_xs': x3d_xs, 'x3d_s': x3d_s, 'x3d_m': x3d_m}# if self.model_type not in model_map:#     raise ValueError(f"不支持的模型类型: {self.model_type}")# 加载预训练模型self.model = torch.hub.load("facebookresearch/pytorchvideo", "x3d_s", pretrained=True)# 替换最后的分类层in_features = self.model.blocks[-1].proj.in_featuresself.model.blocks[-1].proj = torch.nn.Linear(in_features, self.num_classes)self.model.to(self.device)self.model.eval()print(f"已加载 {self.model_type} 模型到 {self.device}")def _setup_transforms(self):"""设置数据预处理流程"""self.transform = T.Compose([T.Lambda(lambda x: x / 255.0),  # 归一化到 [0, 1]T.Lambda(lambda x: x.permute(3, 0, 1, 2)),  # [T, H, W, C] -> [C, T, H, W]T.Resize((72, 72)),  # 调整到72x72VideoNormalize(mean=[0.45, 0.45, 0.45], std=[0.225, 0.225, 0.225]), ])def load_video(self, video_path, max_frames=16):"""加载视频文件Args:video_path: 视频文件路径max_frames: 最大帧数"""if not os.path.exists(video_path):raise FileNotFoundError(f"视频文件不存在: {video_path}")# 使用OpenCV读取视频cap = cv2.VideoCapture(video_path)frames = []while len(frames) < max_frames:ret, frame = cap.read()if not ret:break# 转换BGR到RGBframe_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)frames.append(frame_rgb)cap.release()if len(frames) == 0:raise ValueError("无法从视频中读取帧")# 转换为tensor [T, H, W, C]video_tensor = torch.from_numpy(np.array(frames)).float()return video_tensordef preprocess_video(self, video_tensor):"""预处理视频数据"""# 应用变换processed = self.transform(video_tensor)# 添加batch维度 [1, C, T, H, W]processed = processed.unsqueeze(0)return processed.to(self.device)def predict(self, video_path, class_names=None):"""对视频进行分类预测Args:video_path: 视频文件路径class_names: 类别名称列表"""# 加载视频print(f"正在加载视频: {video_path}")video_tensor = self.load_video(video_path)print(f"视频帧数: {video_tensor.shape[0]}")# 预处理input_tensor = self.preprocess_video(video_tensor)print(f"输入张量形状: {input_tensor.shape}")# 推理with torch.no_grad():outputs = self.model(input_tensor)probabilities = F.softmax(outputs, dim=1)confidence, predicted_idx = torch.max(probabilities, 1)# 处理结果confidence = confidence.item()predicted_idx = predicted_idx.item()if class_names and len(class_names) > predicted_idx:predicted_class = class_names[predicted_idx]else:predicted_class = f"Class {predicted_idx}"return {'predicted_class': predicted_class, 'confidence': confidence, 'class_index': predicted_idx, 'probabilities': probabilities.cpu().numpy()[0]}def predict_from_tensor(self, video_tensor, class_names=None):"""直接从张量进行预测"""input_tensor = self.preprocess_video(video_tensor)with torch.no_grad():outputs = self.model(input_tensor)probabilities = F.softmax(outputs, dim=1)confidence, predicted_idx = torch.max(probabilities, 1)confidence = confidence.item()predicted_idx = predicted_idx.item()if class_names and len(class_names) > predicted_idx:predicted_class = class_names[predicted_idx]else:predicted_class = f"Class {predicted_idx}"return {'predicted_class': predicted_class, 'confidence': confidence, 'class_index': predicted_idx, 'probabilities': probabilities.cpu().numpy()[0]}# 使用示例
def main():# 初始化分类器classifier = X3DVideoClassifier(model_type='x3d_s',  # 使用超小版本,速度最快num_classes=2,  # 2分类任务device='auto'  # 自动选择设备)# 类别名称(根据你的任务修改)class_names = ["类别A", "类别B"]# 示例1: 从文件预测video_path = r"C:\Users\Administrator\Videos\xiaoxia.mp4"try:result = classifier.predict(video_path, class_names)print("\n" + "=" * 50)print("视频分类结果:")print(f"预测类别: {result['predicted_class']}")print(f"置信度: {result['confidence']:.4f}")print(f"类别索引: {result['class_index']}")print("各类别概率:")for i, prob in enumerate(result['probabilities']):class_name = class_names[i] if i < len(class_names) else f"Class {i}"print(f"  {class_name}: {prob:.4f}")print("=" * 50)except Exception as e:print(f"错误: {e}")print("使用随机张量进行演示...")# 示例2: 使用随机张量演示random_video = torch.randn(16, 72, 72, 3)  # [T, H, W, C]result = classifier.predict_from_tensor(random_video, class_names)print("\n随机张量演示结果:")print(f"预测类别: {result['predicted_class']}")print(f"置信度: {result['confidence']:.4f}")if __name__ == "__main__":main()

R(2+1)D

R(2+1)D 将 3D 卷积分解为空间 2D 卷积和时间 1D 卷积,在性能和效率上取得了很好的平衡。

import torch
from pytorchvideo.models import resnet# R(2+1)D-18, 预训练在 Kinetics-400
model = resnet.create_r2plus1d(input_channel=3,         # RGBmodel_depth=18,          # ResNet18 backbonemodel_num_class=400,     # Kinetics-400 分类数pretrained=True
)

X3D(轻量级,速度快)


from pytorchvideo.models import x3d# X3D-Medium (还有 XS, S, L 版本)
model = x3d.create_x3d(input_channel=3,model_num_class=400,   # Kinetics-400model_depth=50,pretrained=True,model_variant="M"      # XS / S / M / L
)

I3D(经典 3D CNN)

from pytorchvideo.models import i3dmodel = i3d.create_kinetics_resnet50(pretrained=True,model_num_class=400   # Kinetics-400
)

替换分类层(适配你的任务)

假设你的视频只有 num_classes=5

 
num_classes = 5# 替换掉最后的分类层 (fc 或 proj depending on model)
if hasattr(model, "blocks"):  # R(2+1)D / I3D 用这种方式model.blocks[-1].proj = torch.nn.Linear(model.blocks[-1].proj.in_features, num_classes)
else:# X3Dmodel.head.proj = torch.nn.Linear(model.head.proj.in_features, num_classes)

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

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

相关文章

OpenTiny NEXT 内核新生:生成式UI × MCP,重塑前端交互新范式!

近期&#xff0c;我们推出 OpenTiny NEXT —— OpenTiny的下一代企业级前端智能开发解决方案。这不仅是一次技术升级&#xff0c;更是一场用户交互范式的变革&#xff1a;从传统的人机交互升级成为人机交互范式和智能体交互范式的融合。我们坚信&#xff0c;每一个企业应用都值…

深度神经网络1——梯度问题+标签数不够问题

要解决一个复杂问题&#xff0c;可能要训练更深的神经网络&#xff0c;可能会10层及以上&#xff0c;每层包含数百个神经元&#xff0c;成千上万个连接。这样大的神经网络在训练的时候可能会遇到以下问题&#xff1a;这样在进行反向传播的时候&#xff0c;随着层数越来越低会遇…

(笔记)内存文件映射mmap

内存文件映射是一种将文件内容映射到进程的虚拟地址空间的技术&#xff0c;使得文件可以被视为内存的一部分&#xff0c;从而允许程序直接对这部分内存进行读写操作&#xff0c;而无需传统的文件 I/O 调用。这种方法不仅简化了文件操作&#xff0c;还提高了处理效率。 在Linux…

Golang中的NaN(Not a Number)

Golang中的NaN&#xff08;Not a Number&#xff09; 在Go语言中&#xff0c;NaN是浮点数&#xff08;特别是float32和float64&#xff09;中的一个特殊值&#xff0c;表示未定义或不可表示的数值。 go中&#xff0c;除数为0时并不会返回error或者nil&#xff0c;而是返回无穷大…

微软图引擎GraphEngine深度解析:分布式内存计算的技术革命

❝ "在大数据的汪洋中&#xff0c;图引擎就像是一艘能够高速穿越复杂关系网络的超级快船" 引言&#xff1a;当内存遇上图计算的火花 在这个数据爆炸的时代&#xff0c;传统的关系型数据库已经难以应对复杂关系数据的查询挑战。当Facebook的社交网络拥有数十亿用户关…

catkin工程和CMakelist.txt的基本使用

catkin工程和CMakelist.txt的基本使用1.catkin工程和CMakelist.txt的基本使用1. 顶部基本信息2. 编译选项 / C 标准3. 依赖查找&#xff08;catkin 包&#xff09;4. 第三方库查找&#xff08;非 catkin&#xff09;5. 导出包信息&#xff08;catkin_package&#xff09;6. 头文…

uniapp打包前端项目

打包前的准备工作确保项目开发已完成&#xff0c;并且已安装最新版本的HBuilderX。检查项目中所有依赖是否已正确安装&#xff0c;配置文件如manifest.json已根据H5需求进行适配。在HBuilderX中打包在 HBuilderX 中&#xff0c;点击顶部菜单栏的 “发行” -> “网站-H5手机版…

Dify + Bright Data MCP:从实时影音数据到可落地的智能体生产线

一、引言&#xff1a;AI 应用与实时影音数据的融合价值 内容生态近年的“视频化、实时化、社交化”浪潮&#xff0c;将数据获取链路推到了更靠前的位置。真正驱动业务的&#xff0c;不是某一帧漂亮的模型输出&#xff0c;而是“数据—理解—动作”的持续闭环。无论是品牌内容策…

【Linux】make/Makefile工具篇

目录一、自动化构建二、make/Makefile2.1 见识一个简单的make/Makefile2.2 Makefile的基本语法2.3 Makefile的语法细节个人主页<—请点击 Linux专栏<—请点击 一、自动化构建 自动化构建是指通过构建工具&#xff08;如make&#xff09;解析构建脚本&#xff08;如Make…

如何在企业微信上以 HTTPS 方式访问内网 OA/ERP 等系统?

企业微信可以将 ZeroNews 平台上添加的内网应用集成到企业微信的工作台。这样&#xff0c;用户即使在外部网络环境中&#xff0c;也可以通过企业微信访问内网的 OA、ERP 等应用。以下是企业在 Linux 服务器上部署 OA 系统&#xff0c;并通过 ZeroNews 通过互联网访问 OA 系统的…

Windows 11 安装使用 nvm,Node.js、npm多版本管理、切换

Windows 11 安装使用 nvm&#xff0c;Node.js、npm多版本管理、切换 文章目录Windows 11 安装使用 nvm&#xff0c;Node.js、npm多版本管理、切换1. nvm 简介2. 安装、配置 nvm2.1. 卸载现有 Node.js&#xff08;非常重要&#xff01;&#xff09;2.2. 下载 nvm-windows 安装包…

在LazyVim中配置Rust开发环境

要在LazyVim中配置Rust开发环境&#xff0c;包括代码补全、格式化、调试等功能&#xff0c;可以按照以下步骤进行配置&#xff1a; 1. 确保基础环境 首先确保你已经安装了&#xff1a; Rust工具链 (rustup, rustc, cargo)LazyVim已正确安装 # 安装Rust工具链 curl --proto http…

LeetCode热题100--114. 二叉树展开为链表--中等

1. 题目 给你二叉树的根结点 root &#xff0c;请你将它展开为一个单链表&#xff1a; 展开后的单链表应该同样使用 TreeNode &#xff0c;其中 right 子指针指向链表中下一个结点&#xff0c;而左子指针始终为null 。展开后的单链表应该与二叉树 先序遍历 顺序相同。 示例 …

REST API 设计最佳实践指南 - 如何用 JavaScript、Node.js 和 Express.js 构建 REST API

过去几年里&#xff0c;我创建并使用过很多 API。在此过程中&#xff0c;我遇到过各种好的和坏的实践&#xff0c;也在开发和调用 API 时碰到过不少棘手的问题&#xff0c;但也有很多顺利的时刻。 网上有很多介绍最佳实践的文章&#xff0c;但在我看来&#xff0c;其中不少都缺…

MyCat

文章目录18.1 MySQL 读写分离概述18.1.1 工作原理18.1.2 为什么要读写分离18.1.3 实现方式18.2 什么是 MyCat18.3 MyCat 安装与配置1. 下载与解压2. 创建用户并修改权限3. 目录说明4. Java 环境要求18.4 MyCat 启动与配置1. 配置环境变量2. 配置 hosts&#xff08;多节点集群&a…

使用 Spring Boot 搭建和部署 Kafka 消息队列系统

使用 Spring Boot 搭建和部署 Kafka 消息队列系统 摘要 本文将引导您在 Kafka 上搭建一个消息队列系统&#xff0c;并整合到您的 Spring Boot 项目中。我们将逐步实现这一方案&#xff0c;探讨其中的关键原理&#xff0c;避开可能遇到的坑&#xff0c;并最终将其部署到 Kuberne…

daily notes[45]

文章目录basic knowledgereferencesbasic knowledge the variable in Rust is not changed. let x5; x6;Rust language promotes the concept that immutable variables are safer than variables in other programming language such as python and and are in favour of th…

技术奇点爆发周:2025 年 9 月科技突破全景扫描

技术奇点爆发周&#xff1a;2025 年 9 月科技突破全景扫描当中国 "祖冲之三号" 量子计算机在特定任务上超越经典超级计算机一千万亿倍的算力新闻&#xff0c;与 OpenAI 宣布 100 亿美元定制芯片量产协议的消息在同一周密集爆发时&#xff0c;我们真切感受到了技术革命…

分布式专题——10.3 ShardingSphere实现原理以及内核解析

1 ShardingSphere-JDBC 内核工作原理当往 ShardingSphere 提交一个逻辑SQL后&#xff0c;ShardingSphere 到底做了哪些事情呢&#xff1f;首先要从 ShardingSphere 官方提供的这张整体架构图说起&#xff1a;1.1 配置管控在 SQL 进入 ShardingSphere 内核处理&#xff08;如解析…

移动语义的里里外外:从 std::move 的幻象到性能的现实

我们都已经听过这样的建议&#xff1a;“使用 std::move 来避免昂贵的拷贝&#xff0c;提升性能。” 这没错&#xff0c;但如果你对它的理解仅止于此&#xff0c;那么你可能正在黑暗中挥舞着一把利剑&#xff0c;既可能披荆斩棘&#xff0c;也可能伤及自身。 移动语义是 C11 带…