目录

模型和预训练权重

该分包包含用于寻址的模型的定义 不同的任务,包括:图像分类、像素语义 分割、对象检测、实例分割、人员 关键点检测、视频分类和光流。torchvision.models

有关预训练权重的一般信息

TorchVision 为每个提供的架构提供预训练的权重,使用 PyTorch .实例化预训练模型将下载其 weights 添加到缓存目录。可以使用 TORCH_HOME 环境变量设置此目录。有关详细信息,请参阅

注意

此库中提供的预训练模型可能具有自己的许可证或 从用于训练的数据集派生的条款和条件。这是你的 负责确定您是否有权将模型用于 您的用例。

注意

可以保证向后兼容性,以加载序列化到使用旧 PyTorch 版本创建的模型。 相反,加载整个保存的模型或序列化(使用旧版本的 PyTorch 序列化) 不得保留历史行为。请参阅以下文档state_dictScriptModules

初始化预训练模型

从 v0.13 开始,TorchVision 提供了一个新的 Multi-weight support API,用于将不同的权重加载到现有的模型构建器方法中:

from torchvision.models import resnet50, ResNet50_Weights

# Old weights with accuracy 76.130%
resnet50(weights=ResNet50_Weights.IMAGENET1K_V1)

# New weights with accuracy 80.858%
resnet50(weights=ResNet50_Weights.IMAGENET1K_V2)

# Best available weights (currently alias for IMAGENET1K_V2)
# Note that these weights may change across versions
resnet50(weights=ResNet50_Weights.DEFAULT)

# Strings are also supported
resnet50(weights="IMAGENET1K_V2")

# No weights - random initialization
resnet50(weights=None)

迁移到新 API 非常简单。这两个 API 之间的以下方法调用都是等效的:

from torchvision.models import resnet50, ResNet50_Weights

# Using pretrained weights:
resnet50(weights=ResNet50_Weights.IMAGENET1K_V1)
resnet50(weights="IMAGENET1K_V1")
resnet50(pretrained=True)  # deprecated
resnet50(True)  # deprecated

# Using no weights:
resnet50(weights=None)
resnet50()
resnet50(pretrained=False)  # deprecated
resnet50(False)  # deprecated

请注意,该参数现已弃用,使用它将发出警告,并将在 v0.15 中删除。pretrained

使用预训练模型

在使用预训练模型之前,必须对图像进行预处理 (使用正确的分辨率/插值调整大小,应用推理变换, rescale the values 等)。没有标准方法可以做到这一点,因为它取决于 给定模型的训练方式。它可能因型号系列、变体或 偶数重量版本。使用正确的预处理方法至关重要,并且 否则可能会导致准确性降低或输出不正确。

每个预训练的推理转换的所有必要信息 model 在其权重文档中提供。为了简化推理,TorchVision 将必要的预处理转换捆绑到每个模型权重中。这些是 可通过 attribute 访问:weight.transforms

# Initialize the Weight Transforms
weights = ResNet50_Weights.DEFAULT
preprocess = weights.transforms()

# Apply it to the input image
img_transformed = preprocess(img)

一些模型使用具有不同训练和评估的模块 行为,例如批量规范化。要在这些模式之间切换,请根据需要使用 或。有关详细信息,请参阅 model.train()model.eval()

# Initialize model
weights = ResNet50_Weights.DEFAULT
model = resnet50(weights=weights)

# Set model to eval mode
model.eval()

使用 Hub 中的模型

大多数预训练模型都可以通过 PyTorch Hub 直接访问,而无需安装 TorchVision:

import torch

# Option 1: passing weights param as string
model = torch.hub.load("pytorch/vision", "resnet50", weights="IMAGENET1K_V2")

# Option 2: passing weights param as enum
weights = torch.hub.load("pytorch/vision", "get_weight", weights="ResNet50_Weights.IMAGENET1K_V2")
model = torch.hub.load("pytorch/vision", "resnet50", weights=weights)

上述情况的唯一例外是 上包含的检测模型。这些模型需要 TorchVision 进行安装,因为它们依赖于自定义 C++ 运算符。torchvision.models.detection

分类

以下分类模型可用,无论是否经过预训练 权重:


以下是如何使用预先训练的图像分类模型的示例:

from torchvision.io import read_image
from torchvision.models import resnet50, ResNet50_Weights

img = read_image("test/assets/encode_jpeg/grace_hopper_517x606.jpg")

# Step 1: Initialize model with the best available weights
weights = ResNet50_Weights.DEFAULT
model = resnet50(weights=weights)
model.eval()

# Step 2: Initialize the inference transforms
preprocess = weights.transforms()

# Step 3: Apply inference preprocessing transforms
batch = preprocess(img).unsqueeze(0)

# Step 4: Use the model and print the predicted category
prediction = model(batch).squeeze(0).softmax(0)
class_id = prediction.argmax().item()
score = prediction[class_id].item()
category_name = weights.meta["categories"][class_id]
print(f"{category_name}: {100 * score:.1f}%")

预训练模型输出的类可以在 中找到。weights.meta["categories"]

所有可用分类权重表

使用单个裁剪在 ImageNet-1K 上报告精度:

重量

Acc@1

Acc@5

参数

示例

AlexNet_Weights.IMAGENET1K_V1

56.522

79.066

61.1 米

链接

ConvNeXt_Base_Weights.IMAGENET1K_V1

84.062

96.87

88.6 米

链接

ConvNeXt_Large_Weights.IMAGENET1K_V1

84.414

96.976

197.8 分钟

链接

ConvNeXt_Small_Weights.IMAGENET1K_V1

83.616

96.65

50.2 米

链接

ConvNeXt_Tiny_Weights.IMAGENET1K_V1

82.52

96.146

28.6 分钟

链接

DenseNet121_Weights.IMAGENET1K_V1

74.434

91.972

8.0 分钟

链接

DenseNet161_Weights.IMAGENET1K_V1

77.138

93.56

28.7 分钟

链接

DenseNet169_Weights.IMAGENET1K_V1

75.6

92.806

14.1 分钟

链接

DenseNet201_Weights.IMAGENET1K_V1

76.896

93.37

20.0 米

链接

EfficientNet_B0_Weights.IMAGENET1K_V1

77.692

93.532

5.3 米

链接

EfficientNet_B1_Weights.IMAGENET1K_V1

78.642

94.186

7.8 中

链接

EfficientNet_B1_Weights.IMAGENET1K_V2

79.838

94.934

7.8 中

链接

EfficientNet_B2_Weights.IMAGENET1K_V1

80.608

95.31

9.1 米

链接

EfficientNet_B3_Weights.IMAGENET1K_V1

82.008

96.054

12.2 分钟

链接

EfficientNet_B4_Weights.IMAGENET1K_V1

83.384

96.594

19.3 分钟

链接

EfficientNet_B5_Weights.IMAGENET1K_V1

83.444

96.628

30.4 分钟

链接

EfficientNet_B6_Weights.IMAGENET1K_V1

84.008

96.916

43.0 分钟

链接

EfficientNet_B7_Weights.IMAGENET1K_V1

84.122

96.908

66.3 分钟

链接

EfficientNet_V2_L_Weights.IMAGENET1K_V1

85.808

97.788

118.5 米

链接

EfficientNet_V2_M_Weights.IMAGENET1K_V1

85.112

97.156

54.1 米

链接

EfficientNet_V2_S_Weights.IMAGENET1K_V1

84.228

96.878

21.5 分钟

链接

GoogLeNet_Weights.IMAGENET1K_V1

69.778

89.53

6.6 米

链接

Inception_V3_Weights.IMAGENET1K_V1

77.294

93.45

27.2 中

链接

MNASNet0_5_Weights.IMAGENET1K_V1

67.734

87.49

2.2 米

链接

MNASNet0_75_Weights.IMAGENET1K_V1

71.18

90.496

3.2 米

链接

MNASNet1_0_Weights.IMAGENET1K_V1

73.456

91.51

4.4 分钟

链接

MNASNet1_3_Weights.IMAGENET1K_V1

76.506

93.522

6.3 米

链接

MobileNet_V2_Weights.IMAGENET1K_V1

71.878

90.286

3.5 分钟

链接

MobileNet_V2_Weights.IMAGENET1K_V2

72.154

90.822

3.5 分钟

链接

MobileNet_V3_Large_Weights.IMAGENET1K_V1

74.042

91.34

5.5 分钟

链接

MobileNet_V3_Large_Weights.IMAGENET1K_V2

75.274

92.566

5.5 分钟

链接

MobileNet_V3_Small_Weights.IMAGENET1K_V1

67.668

87.402

2.5 米

链接

RegNet_X_16GF_Weights.IMAGENET1K_V1

80.058

94.944

54.3 分钟

链接

RegNet_X_16GF_Weights.IMAGENET1K_V2

82.716

96.196

54.3 分钟

链接

RegNet_X_1_6GF_Weights.IMAGENET1K_V1

77.04

93.44

9.2 中

链接

RegNet_X_1_6GF_Weights.IMAGENET1K_V2

79.668

94.922

9.2 中

链接

RegNet_X_32GF_Weights.IMAGENET1K_V1

80.622

95.248

107.8 米

链接

RegNet_X_32GF_Weights.IMAGENET1K_V2

83.014

96.288

107.8 米

链接

RegNet_X_3_2GF_Weights.IMAGENET1K_V1

78.364

93.992

15.3 分钟

链接

RegNet_X_3_2GF_Weights.IMAGENET1K_V2

81.196

95.43

15.3 分钟

链接

RegNet_X_400MF_Weights.IMAGENET1K_V1

72.834

90.95

5.5 分钟

链接

RegNet_X_400MF_Weights.IMAGENET1K_V2

74.864

92.322

5.5 分钟

链接

RegNet_X_800MF_Weights.IMAGENET1K_V1

75.212

92.348

7.3 米

链接

RegNet_X_800MF_Weights.IMAGENET1K_V2

77.522

93.826

7.3 米

链接

RegNet_X_8GF_Weights.IMAGENET1K_V1

79.344

94.686

39.6 分钟

链接

RegNet_X_8GF_Weights.IMAGENET1K_V2

81.682

95.678

39.6 分钟

链接

RegNet_Y_128GF_Weights.IMAGENET1K_SWAG_E2E_V1

88.228

98.682

644.8 百万

链接

RegNet_Y_128GF_Weights.IMAGENET1K_SWAG_线性_V1

86.068

97.844

644.8 百万

链接

RegNet_Y_16GF_Weights.IMAGENET1K_V1

80.424

95.24

83.6 米

链接

RegNet_Y_16GF_Weights.IMAGENET1K_V2

82.886

96.328

83.6 米

链接

RegNet_Y_16GF_Weights.IMAGENET1K_SWAG_E2E_V1

86.012

98.054

83.6 米

链接

RegNet_Y_16GF_Weights.IMAGENET1K_SWAG_线性_V1

83.976

97.244

83.6 米

链接

RegNet_Y_1_6GF_Weights.IMAGENET1K_V1 版本

77.95

93.966

11.2 中

链接

RegNet_Y_1_6GF_Weights.IMAGENET1K_V2

80.876

95.444

11.2 中

链接

RegNet_Y_32GF_Weights.IMAGENET1K_V1

80.878

95.34

145.0 米

链接

RegNet_Y_32GF_Weights.IMAGENET1K_V2

83.368

96.498

145.0 米

链接

RegNet_Y_32GF_Weights.IMAGENET1K_SWAG_E2E_V1

86.838

98.362

145.0 米

链接

RegNet_Y_32GF_Weights.IMAGENET1K_SWAG_线性_V1

84.622

97.48

145.0 米

链接

RegNet_Y_3_2GF_Weights.IMAGENET1K_V1

78.948

94.576

19.4 分钟

链接

RegNet_Y_3_2GF_Weights.IMAGENET1K_V2

81.982

95.972

19.4 分钟

链接

RegNet_Y_400MF_Weights.IMAGENET1K_V1

74.046

91.716

4.3 米

链接

RegNet_Y_400MF_Weights.IMAGENET1K_V2

75.804

92.742

4.3 米

链接

RegNet_Y_800MF_Weights.IMAGENET1K_V1

76.42

93.136

6.4 分钟

链接

RegNet_Y_800MF_Weights.IMAGENET1K_V2

78.828

94.502

6.4 分钟

链接

RegNet_Y_8GF_Weights.IMAGENET1K_V1

80.032

95.048

39.4 分钟

链接

RegNet_Y_8GF_Weights.IMAGENET1K_V2

82.828

96.33

39.4 分钟

链接

ResNeXt101_32X8D_Weights.IMAGENET1K_V1

79.312

94.526

88.8 米

链接

ResNeXt101_32X8D_Weights.IMAGENET1K_V2

82.834

96.228

88.8 米

链接

ResNeXt101_64X4D_Weights.IMAGENET1K_V1

83.246

96.454

83.5 分钟

链接

ResNeXt50_32X4D_Weights.IMAGENET1K_V1

77.618

93.698

25.0 分钟

链接

ResNeXt50_32X4D_Weights.IMAGENET1K_V2

81.198

95.34

25.0 分钟

链接

ResNet101_Weights.IMAGENET1K_V1

77.374

93.546

44.5 分钟

链接

ResNet101_Weights.IMAGENET1K_V2

81.886

95.78

44.5 分钟

链接

ResNet152_Weights.IMAGENET1K_V1

78.312

94.046

60.2 米

链接

ResNet152_Weights.IMAGENET1K_V2

82.284

96.002

60.2 米

链接

ResNet18_Weights.IMAGENET1K_V1

69.758

89.078

11.7 分钟

链接

ResNet34_Weights.IMAGENET1K_V1

73.314

91.42

21.8 分钟

链接

ResNet50_Weights.IMAGENET1K_V1

76.13

92.862

25.6 分钟

链接

ResNet50_Weights.IMAGENET1K_V2

80.858

95.434

25.6 分钟

链接

ShuffleNet_V2_X0_5_Weights.IMAGENET1K_V1

60.552

81.746

1.4 米

链接

ShuffleNet_V2_X1_0_Weights.IMAGENET1K_V1

69.362

88.316

2.3 米

链接

ShuffleNet_V2_X1_5_Weights.IMAGENET1K_V1

72.996

91.086

3.5 分钟

链接

ShuffleNet_V2_X2_0_Weights.IMAGENET1K_V1

76.23

93.006

7.4 中

链接

SqueezeNet1_0_Weights.IMAGENET1K_V1

58.092

80.42

1.2 米

链接

SqueezeNet1_1_Weights.IMAGENET1K_V1

58.178

80.624

1.2 米

链接

Swin_B_Weights.IMAGENET1K_V1

83.582

96.64

87.8 分钟

链接

Swin_S_Weights.IMAGENET1K_V1

83.196

96.36

49.6 分钟

链接

Swin_T_Weights.IMAGENET1K_V1

81.474

95.776

28.3 分钟

链接

VGG11_BN_Weights.IMAGENET1K_V1

70.37

89.81

132.9 分钟

链接

VGG11_Weights.IMAGENET1K_V1

69.02

88.628

132.9 分钟

链接

VGG13_BN_Weights.IMAGENET1K_V1

71.586

90.374

133.1 米

链接

VGG13_Weights.IMAGENET1K_V1

69.928

89.246

133.0 百万

链接

VGG16_BN_Weights.IMAGENET1K_V1

73.36

91.516

138.4 米

链接

VGG16_Weights.IMAGENET1K_V1

71.592

90.382

138.4 米

链接

VGG16_Weights.IMAGENET1K_功能

138.4 米

链接

VGG19_BN_Weights.IMAGENET1K_V1

74.218

91.842

143.7 米

链接

VGG19_Weights.IMAGENET1K_V1

72.376

90.876

143.7 米

链接

ViT_B_16_Weights.IMAGENET1K_V1

81.072

95.318

86.6 米

链接

ViT_B_16_Weights.IMAGENET1K_SWAG_E2E_V1

85.304

97.65

86.9 米

链接

ViT_B_16_Weights.IMAGENET1K_SWAG_线性_V1

81.886

96.18

86.6 米

链接

ViT_B_32_Weights.IMAGENET1K_V1

75.912

92.466

88.2 米

链接

ViT_H_14_Weights.IMAGENET1K_SWAG_E2E_V1

88.552

98.694

633.5 米

链接

ViT_H_14_Weights.IMAGENET1K_SWAG_线性_V1

85.708

97.73

632.0 米

链接

ViT_L_16_Weights.IMAGENET1K_V1

79.662

94.638

304.3 米

链接

ViT_L_16_Weights.IMAGENET1K_SWAG_E2E_V1

88.064

98.512

305.2 米

链接

ViT_L_16_Weights.IMAGENET1K_SWAG_线性_V1

85.146

97.422

304.3 米

链接

ViT_L_32_Weights.IMAGENET1K_V1

76.972

93.07

306.5 分钟

链接

Wide_ResNet101_2_Weights.IMAGENET1K_V1

78.848

94.284

126.9 米

链接

Wide_ResNet101_2_Weights.IMAGENET1K_V2

82.51

96.02

126.9 米

链接

Wide_ResNet50_2_Weights.IMAGENET1K_V1

78.468

94.086

68.9 米

链接

Wide_ResNet50_2_Weights.IMAGENET1K_V2

81.602

95.758

68.9 米

链接

量化模型

以下架构支持 INT8 量化模型,无论是否 预训练权重:


以下是如何使用预训练量化图像分类模型的示例:

from torchvision.io import read_image
from torchvision.models.quantization import resnet50, ResNet50_QuantizedWeights

img = read_image("test/assets/encode_jpeg/grace_hopper_517x606.jpg")

# Step 1: Initialize model with the best available weights
weights = ResNet50_QuantizedWeights.DEFAULT
model = resnet50(weights=weights, quantize=True)
model.eval()

# Step 2: Initialize the inference transforms
preprocess = weights.transforms()

# Step 3: Apply inference preprocessing transforms
batch = preprocess(img).unsqueeze(0)

# Step 4: Use the model and print the predicted category
prediction = model(batch).squeeze(0).softmax(0)
class_id = prediction.argmax().item()
score = prediction[class_id].item()
category_name = weights.meta["categories"][class_id]
print(f"{category_name}: {100 * score}%")

预训练模型输出的类可以在 中找到。weights.meta["categories"]

语义分割

警告

分割模块处于 Beta 阶段,不保证向后兼容性。

可以使用以下语义分割模型,带或不带 预训练权重:


以下是如何使用预先训练的语义分割模型的示例:

from torchvision.io.image import read_image
from torchvision.models.segmentation import fcn_resnet50, FCN_ResNet50_Weights
from torchvision.transforms.functional import to_pil_image

img = read_image("gallery/assets/dog1.jpg")

# Step 1: Initialize model with the best available weights
weights = FCN_ResNet50_Weights.DEFAULT
model = fcn_resnet50(weights=weights)
model.eval()

# Step 2: Initialize the inference transforms
preprocess = weights.transforms()

# Step 3: Apply inference preprocessing transforms
batch = preprocess(img).unsqueeze(0)

# Step 4: Use the model and visualize the prediction
prediction = model(batch)["out"]
normalized_masks = prediction.softmax(dim=1)
class_to_idx = {cls: idx for (idx, cls) in enumerate(weights.meta["categories"])}
mask = normalized_masks[0, class_to_idx["dog"]]
to_pil_image(mask).show()

预训练模型输出的类可以在 中找到。 模型的输出格式在 语义分割模型 中进行了说明。weights.meta["categories"]

所有可用语义分割权重的表

所有模型都是 COCO val2017 的一个子集,在 Pascal VOC 数据集中存在的 20 个类别中进行评估:

重量

平均 IoU

像素级 Acc

参数

示例

DeepLabV3_MobileNet_V3_Large_Weights.COCO_WITH_VOC_LABELS_V1

60.3

91.2

11.0 分钟

链接

DeepLabV3_ResNet101_Weights.COCO_WITH_VOC_LABELS_V1

67.4

92.4

61.0 分钟

链接

DeepLabV3_ResNet50_Weights.COCO_WITH_VOC_LABELS_V1

66.4

92.4

42.0 分钟

链接

FCN_ResNet101_Weights.COCO_WITH_VOC_LABELS_V1

63.7

91.9

54.3 分钟

链接

FCN_ResNet50_Weights.COCO_WITH_VOC_LABELS_V1

60.5

91.4

35.3 分钟

链接

LRASPP_MobileNet_V3_Large_Weights.COCO_WITH_VOC_LABELS_V1

57.9

91.2

3.2 米

链接

对象检测、实例分割和人员关键点检测

用于检测、实例分割和 关键点检测使用分类模型进行初始化 在 TorchVision 中。模型需要 . 检查模型的构造器以获取更多信息。Tensor[C, H, W]

警告

检测模块处于 Beta 阶段,不保证向后兼容性。

对象检测

可以使用以下对象检测模型,无论是否经过预训练 权重:


以下是如何使用预训练对象检测模型的示例:

from torchvision.io.image import read_image
from torchvision.models.detection import fasterrcnn_resnet50_fpn_v2, FasterRCNN_ResNet50_FPN_V2_Weights
from torchvision.utils import draw_bounding_boxes
from torchvision.transforms.functional import to_pil_image

img = read_image("test/assets/encode_jpeg/grace_hopper_517x606.jpg")

# Step 1: Initialize model with the best available weights
weights = FasterRCNN_ResNet50_FPN_V2_Weights.DEFAULT
model = fasterrcnn_resnet50_fpn_v2(weights=weights, box_score_thresh=0.9)
model.eval()

# Step 2: Initialize the inference transforms
preprocess = weights.transforms()

# Step 3: Apply inference preprocessing transforms
batch = [preprocess(img)]

# Step 4: Use the model and visualize the prediction
prediction = model(batch)[0]
labels = [weights.meta["categories"][i] for i in prediction["labels"]]
box = draw_bounding_boxes(img, boxes=prediction["boxes"],
                          labels=labels,
                          colors="red",
                          width=4, font_size=30)
im = to_pil_image(box.detach())
im.show()

预训练模型输出的类可以在 中找到。 有关如何绘制模型边界框的详细信息,您可以参考 实例分割模型weights.meta["categories"]

实例分段

可以使用以下实例分割模型,无论是否经过预训练 权重:


有关如何绘制模型掩码的详细信息,您可以参考 实例分割模型

所有可用 Instance 分段权重表

框和掩码 MAP 在 COCO val2017 上报告:

重量

箱图

蒙版映射

参数

示例

MaskRCNN_ResNet50_FPN_V2_Weights.COCO_V1

47.4

41.8

46.4 分钟

链接

MaskRCNN_ResNet50_FPN_Weights.COCO_V1

37.9

34.6

44.4 分钟

链接

关键点检测

可以使用以下人员关键点检测模型,带或不带 预训练权重:


预训练模型输出的类可以在 中找到。 有关如何绘制模型边界框的详细信息,您可以参考 可视化关键点weights.meta["keypoint_names"]

所有可用关键点检测权重表

Box 和 Keypoint MAP 在 COCO val2017 上报告:

重量

箱图

关键点映射

参数

示例

KeypointRCNN_ResNet50_FPN_Weights.COCO_LEGACY

50.6

61.1

59.1 米

链接

KeypointRCNN_ResNet50_FPN_Weights.COCO_V1

54.6

65

59.1 米

链接

视频分类

警告

视频模块处于 Beta 阶段,不保证向后兼容性。

可以使用以下视频分类模型,无论是否 预训练权重:


以下是如何使用预先训练的视频分类模型的示例:

from torchvision.io.video import read_video
from torchvision.models.video import r3d_18, R3D_18_Weights

vid, _, _ = read_video("test/assets/videos/v_SoccerJuggling_g23_c01.avi", output_format="TCHW")
vid = vid[:32]  # optionally shorten duration

# Step 1: Initialize model with the best available weights
weights = R3D_18_Weights.DEFAULT
model = r3d_18(weights=weights)
model.eval()

# Step 2: Initialize the inference transforms
preprocess = weights.transforms()

# Step 3: Apply inference preprocessing transforms
batch = preprocess(vid).unsqueeze(0)

# Step 4: Use the model and print the predicted category
prediction = model(batch).squeeze(0).softmax(0)
label = prediction.argmax().item()
score = prediction[label].item()
category_name = weights.meta["categories"][label]
print(f"{category_name}: {100 * score}%")

预训练模型输出的类可以在 中找到。weights.meta["categories"]

所有可用视频分类权重表

在 Kinetics-400 上使用剪辑长度 16 的单一裁剪报告准确性:

重量

Acc@1

Acc@5

参数

示例

MC3_18_Weights.KINETICS400_V1

53.9

76.29

11.7 分钟

链接

R2Plus1D_18_Weights.KINETICS400_V1

57.5

78.81

31.5 分钟

链接

R3D_18_Weights.KINETICS400_V1

52.75

75.45

33.4 分钟

链接

光流

以下光流模型可用,带或不带预训练

文档

访问 PyTorch 的全面开发人员文档

查看文档

教程

获取面向初学者和高级开发人员的深入教程

查看教程

资源

查找开发资源并解答您的问题

查看资源