PyTorch应用实战三:构建神经网络

简介: PyTorch应用实战三:构建神经网络

神经网络

构建神经网络的一般步骤如下:

  1. 确定网络的结构:这包括输入层、输出层和隐藏层的数量以及每层中的节点数等。
  2. 收集和准备数据:这包括收集训练数据、清洗数据、转换数据格式等。
  3. 初始化权重:权重是神经元之间的连接强度,需要在训练前随机初始化。
  1. 前向传播计算:根据输入数据和权重计算输出结果。
  2. 计算损失函数:损失函数衡量预测输出和真实输出之间的误差。
  3. 反向传播计算:反向传播是一种优化算法,用于调整权重以最小化损失函数。
  4. 更新权重:根据反向传播算法计算出的梯度更新权重,以优化模型。
  5. 重复以上步骤:反复执行前向传播和反向传播,调整权重,直到损失函数收敛。
  6. 测试和评估模型:使用测试数据集对模型进行评估和测试。
  1. 使用模型进行预测:使用已训练的模型对新数据进行预测。

1.继承Module构建神经网络

构建神经网络

import torch
import torch.nn as nn
from torch import optim
from torchvision import datasets, transforms
from torch.nn.functional import conv2d, cross_entropy 
class SimpleCNN(nn.Module):
    def __init__(self, in_channel=1):
        super(SimpleCNN, self).__init__()
        self.conv1 = nn.Conv2d(in_channel, 4, 5, 2, 0)
        self.relu1 = nn.ReLU()
        self.conv2 = nn.Conv2d(4, 8, 3, 2, 0)
        self.relu2 = nn.ReLU()
        self.linear = nn.Linear(200, 10)
    def forward(self, x):
        x = self.conv1(x)
        x = self.relu1(x)
        x = self.conv2(x)
        x = self.relu2(x)
        x = x.view(-1, 200)
        x = self.linear(x)
        return x

这个程序定义了一个简单的CNN模型 SimpleCNN,用于进行图像分类任务。它包含以下几个部分:

  1. 导入所需的 PyTorch 模块。这些模块是 torchnnoptimdatasetstransformsnn.functional
  1. 定义了一个名为 SimpleCNN 的类,继承了 nn.Module

__init__ 函数中定义模型的结构。这个模型包含两层卷积层和一个全连接层:

  • 第1层卷积层:输入通道数为 in_channel,输出通道数为 4,卷积核大小为 5x5,步长为 2,填充为 0。
  • 第1个ReLU激活函数:将卷积层的输出进行非线性变换。
  • 第2层卷积层:输入通道数为 4,输出通道数为 8,卷积核大小为 3x3,步长为 2,填充为 0。
  • 第2个ReLU激活函数:再次对卷积层的输出进行非线性变换。
  • 平铺层:将卷积层的输出展成一维向量。
  • 全连接层:输入大小为 200,输出大小为 10,用于输出分类结果。
  1. forward 函数中实现模型的前向传播过程。将输入 x 依次经过卷积层、ReLU激活函数、卷积层、ReLU激活函数和全连接层处理,最终输出分类结果。
#测试
model = SimpleCNN()
data = torch.randn(3, 1, 28, 28)
output = model(data)
output.shape
torch.Size([3, 10])

卷积层计算

(28-5)/2+1=12

(12-3)/2+1=5

3×1×28×28

3×4×12×12

3×8×5×5

3×200

3×10

神经网络模型

model
SimpleCNN(
  (conv1): Conv2d(1, 4, kernel_size=(5, 5), stride=(2, 2))
  (relu1): ReLU()
  (conv2): Conv2d(4, 8, kernel_size=(3, 3), stride=(2, 2))
  (relu2): ReLU()
  (linear): Linear(in_features=200, out_features=10, bias=True)
)
for key, value in model._modules.items():
    print(key, value)
conv1 Conv2d(1, 4, kernel_size=(5, 5), stride=(2, 2))
relu1 ReLU()
conv2 Conv2d(4, 8, kernel_size=(3, 3), stride=(2, 2))
relu2 ReLU()
linear Linear(in_features=200, out_features=10, bias=True)
model = SimpleCNN()
model.parameters()
for p in model.parameters():
    print(p.shape)
torch.Size([4, 1, 5, 5])
torch.Size([4])
torch.Size([8, 4, 3, 3])
torch.Size([8])
torch.Size([10, 200])
torch.Size([10])

导入数据集

train_batch_size = 100  #一共60000个数据,100个数据一组,一共600组(N=100)
test_batch_size = 100   #一共10000个数据,100个数据一组,一共100组(N=100)
# 训练集
train_loader = torch.utils.data.DataLoader(
    datasets.MNIST(
        './data',train=True,download=True,  
        transform=transforms.Compose([
            transforms.ToTensor(),  #转为tensor
            transforms.Normalize((0.5),(0.5)) #正则化
        ])
    ),
    batch_size = train_batch_size, shuffle=True  #打乱位置
)
# 测试集
test_loader = torch.utils.data.DataLoader(
    datasets.MNIST(
        './data',train=False,download=True,
        transform=transforms.Compose([
            transforms.ToTensor(),
            transforms.Normalize((0.5),(0.5))
        ])
    ),
    batch_size = test_batch_size, shuffle=False
)

这段代码主要用于加载 MNIST 数据集,并生成对应的数据加载器 train_loadertest_loader。具体包含以下几个步骤:

  1. 定义训练集的批次大小 train_batch_size,设为 100。
  2. 定义测试集的批次大小 test_batch_size,也设为 100。
  3. 调用 torch.utils.data.DataLoader 函数生成训练集加载器 train_loader,加载器将使用 datasets.MNIST 函数加载 MNIST 数据集,并进行以下操作:
  • 设置 MNIST 数据集的路径为 ./data
  • 将数据集设置为训练集,下载数据集。
  • 对数据进行transforms.Compose序列变换操作,包括:
  • transforms.ToTensor():将数据转为 Tensor 类型。
  • transforms.Normalize((0.5),(0.5)):将数据进行正则化。
  • 将训练集数据划分为大小为 train_batch_size 的批次,进行随机打乱。
  1. 调用 torch.utils.data.DataLoader 函数生成测试集加载器 test_loader,加载器将使用 datasets.MNIST 函数加载 MNIST 数据集,并进行相同的处理流程,但测试集不需要随机打乱。

这样生成的 train_loadertest_loader 可以用于对数据进行批量加载,方便后续的模型训练和评估。

训练测试

alpha = 0.1  #学习率
epochs = 100  #训练次数
interval = 100  #打印间隔
for epoch in range(epochs):
    optimizer = optim.SGD(model.parameters(), lr=0.1)
    for i, (data, label) in enumerate(train_loader):
        output = model(data)
        optimizer.zero_grad()  #梯度归零
        loss = cross_entropy(output, label)  #交叉熵函数
        loss.backward()   #反向求导
        optimizer.step()  #更新参数
        if i % interval == 0:
            print("Epoch %03d [%03d/%03d]\tLoss:%.4f"%(epoch, i, len(train_loader), loss.item()))
    correct_num = 0
    total_num = 0
    with torch.no_grad():
        for data, label in test_loader:
            output = model(data)
            pred = output.max(1)[1]
            correct_num += (pred == label).sum().item()
            total_num += len(data)
    acc = correct_num / total_num
    print('...Testing @ Epoch %03d\tAcc:%.4f'%(epoch, acc))
Epoch 000 [000/600] Loss:2.2848
Epoch 000 [100/600] Loss:0.4144
Epoch 000 [200/600] Loss:0.2014
Epoch 000 [300/600] Loss:0.2790
Epoch 000 [400/600] Loss:0.1858
Epoch 000 [500/600] Loss:0.1649
...Testing @ Epoch 000  Acc:0.9538
Epoch 001 [000/600] Loss:0.1593
Epoch 001 [100/600] Loss:0.2436
Epoch 001 [200/600] Loss:0.0649
Epoch 001 [300/600] Loss:0.2830
Epoch 001 [400/600] Loss:0.1208
Epoch 001 [500/600] Loss:0.0937
...Testing @ Epoch 001  Acc:0.9678
Epoch 002 [000/600] Loss:0.1210
Epoch 002 [100/600] Loss:0.0737
Epoch 002 [200/600] Loss:0.0857
Epoch 002 [300/600] Loss:0.0712
Epoch 002 [400/600] Loss:0.2700
Epoch 002 [500/600] Loss:0.0849
...Testing @ Epoch 002  Acc:0.9708
Epoch 003 [000/600] Loss:0.1094
Epoch 003 [100/600] Loss:0.0727
Epoch 003 [200/600] Loss:0.1756
Epoch 003 [300/600] Loss:0.1473
Epoch 003 [400/600] Loss:0.1013
Epoch 003 [500/600] Loss:0.0879
...Testing @ Epoch 003  Acc:0.9741
Epoch 004 [000/600] Loss:0.1503
Epoch 004 [100/600] Loss:0.0832
Epoch 004 [200/600] Loss:0.0731
Epoch 004 [300/600] Loss:0.1040
Epoch 004 [400/600] Loss:0.0720
Epoch 004 [500/600] Loss:0.0490
...Testing @ Epoch 004  Acc:0.9745
Epoch 005 [000/600] Loss:0.0720
Epoch 005 [100/600] Loss:0.1124
Epoch 005 [200/600] Loss:0.0674
Epoch 005 [300/600] Loss:0.0477
Epoch 005 [400/600] Loss:0.1164
Epoch 005 [500/600] Loss:0.0662
...Testing @ Epoch 005  Acc:0.9758
Epoch 006 [000/600] Loss:0.0445
Epoch 006 [100/600] Loss:0.0500
Epoch 006 [200/600] Loss:0.0236
Epoch 006 [300/600] Loss:0.1068
Epoch 006 [400/600] Loss:0.0767
Epoch 006 [500/600] Loss:0.0549
...Testing @ Epoch 006  Acc:0.9800
Epoch 007 [000/600] Loss:0.0539
Epoch 007 [100/600] Loss:0.0319
Epoch 007 [200/600] Loss:0.1369
Epoch 007 [300/600] Loss:0.0301
Epoch 007 [400/600] Loss:0.0881
Epoch 007 [500/600] Loss:0.0642
...Testing @ Epoch 007  Acc:0.9792
Epoch 008 [000/600] Loss:0.0564
Epoch 008 [100/600] Loss:0.0845
Epoch 008 [200/600] Loss:0.1877
Epoch 008 [300/600] Loss:0.0963
Epoch 008 [400/600] Loss:0.0671
Epoch 008 [500/600] Loss:0.1053
...Testing @ Epoch 008  Acc:0.9757
Epoch 009 [000/600] Loss:0.0117
Epoch 009 [100/600] Loss:0.0201
Epoch 009 [200/600] Loss:0.1933
Epoch 009 [300/600] Loss:0.0726
Epoch 009 [400/600] Loss:0.0449
Epoch 009 [500/600] Loss:0.1415
...Testing @ Epoch 009  Acc:0.9807
Epoch 010 [000/600] Loss:0.0505
Epoch 010 [100/600] Loss:0.0410
Epoch 010 [200/600] Loss:0.0325
Epoch 010 [300/600] Loss:0.0403
Epoch 010 [400/600] Loss:0.0249
Epoch 010 [500/600] Loss:0.0682
...Testing @ Epoch 010  Acc:0.9805
Epoch 011 [000/600] Loss:0.0816
Epoch 011 [100/600] Loss:0.1179
Epoch 011 [200/600] Loss:0.1244
Epoch 011 [300/600] Loss:0.0465
Epoch 011 [400/600] Loss:0.1324
Epoch 011 [500/600] Loss:0.0763
...Testing @ Epoch 011  Acc:0.9799
……

这段代码实现了简单 CNN 模型的训练和测试,具体实现步骤如下:

  1. 定义学习率 alpha,设为 0.1。
  2. 定义训练次数 epochs,设为 100。
  3. 定义打印间隔 interval,设为 100。
  4. 使用 range 函数循环 epochs 次,进行模型训练和测试。
  5. 在每个 epoch 循环中,定义优化器 optimizer,使用随机梯度下降法(SGD)优化器,对模型参数进行更新。
  6. 循环训练数据加载器 train_loader 中的数据,对数据进行前向传播,计算损失函数(交叉熵函数),通过反向传播求解梯度,并通过优化器对模型参数进行更新。
  7. 在每个间隔 interval 打印一次训练进度,输出当前训练的 epoch、批次、总批次数和当前损失函数值,以及测试集的准确率。
  8. 在每个 epoch 循环的末尾,使用 torch.no_grad() 防止梯度更新,在测试集加载器 test_loader 中进行数据的前向传播,计算模型的预测值和真实值,计算模型的准确率并输出。

这样就完成了模型的训练和测试,通过输出可以了解模型的训练进度和测试效果。

2.结构化构建神经网络

构建神经网络

Model = nn.Sequential(
    nn.Conv2d(1, 4, 5, 2, 0),
    nn.ReLU(),
    nn.Conv2d(4, 8, 3, 2, 0),
    nn.ReLU(),
    nn.Flatten(),
    nn.Linear(200, 10)
)

神经网络模型

Model
Sequential(
  (0): Conv2d(1, 4, kernel_size=(5, 5), stride=(2, 2))
  (1): ReLU()
  (2): Conv2d(4, 8, kernel_size=(3, 3), stride=(2, 2))
  (3): ReLU()
  (4): Flatten(start_dim=1, end_dim=-1)
  (5): Linear(in_features=200, out_features=10, bias=True)
)
#测试
data = torch.randn(3, 1, 28, 28)
output = Model(data)
output.shape
torch.Size([3, 10])
for p in Model.parameters():
    print(p.shape)
torch.Size([4, 1, 5, 5])
torch.Size([4])
torch.Size([8, 4, 3, 3])
torch.Size([8])
torch.Size([10, 200])
torch.Size([10])

训练测试

alpha = 0.1  #学习率
epochs = 100  #训练次数
interval = 100  #打印间隔
for epoch in range(epochs):
    optimizer = optim.SGD(Model.parameters(), lr=0.1)
    for i, (data, label) in enumerate(train_loader):
        output = Model(data)
        optimizer.zero_grad()  #梯度归零
        loss = cross_entropy(output, label)  #交叉熵函数
        loss.backward()   #反向求导
        optimizer.step()  #更新参数
        if i % interval == 0:
            print("Epoch %03d [%03d/%03d]\tLoss:%.4f"%(epoch, i, len(train_loader), loss.item()))
    correct_num = 0
    total_num = 0
    with torch.no_grad():
        for data, label in test_loader:
            output = Model(data)
            pred = output.max(1)[1]
            correct_num += (pred == label).sum().item()
            total_num += len(data)
    acc = correct_num / total_num
    print('...Testing @ Epoch %03d\tAcc:%.4f'%(epoch, acc))
Epoch 000 [000/600] Loss:2.3005
Epoch 000 [100/600] Loss:0.3855
Epoch 000 [200/600] Loss:0.2832
Epoch 000 [300/600] Loss:0.3216
Epoch 000 [400/600] Loss:0.2495
Epoch 000 [500/600] Loss:0.0687
...Testing @ Epoch 000  Acc:0.9554
Epoch 001 [000/600] Loss:0.1364
Epoch 001 [100/600] Loss:0.2104
Epoch 001 [200/600] Loss:0.1206
Epoch 001 [300/600] Loss:0.0859
Epoch 001 [400/600] Loss:0.1187
Epoch 001 [500/600] Loss:0.1903
...Testing @ Epoch 001  Acc:0.9668
Epoch 002 [000/600] Loss:0.1893
Epoch 002 [100/600] Loss:0.1033
Epoch 002 [200/600] Loss:0.1633
Epoch 002 [300/600] Loss:0.1038
Epoch 002 [400/600] Loss:0.1250
Epoch 002 [500/600] Loss:0.2345
...Testing @ Epoch 002  Acc:0.9725
Epoch 003 [000/600] Loss:0.0566
Epoch 003 [100/600] Loss:0.1781
Epoch 003 [200/600] Loss:0.0779
Epoch 003 [300/600] Loss:0.2852
Epoch 003 [400/600] Loss:0.0428
Epoch 003 [500/600] Loss:0.1369
...Testing @ Epoch 003  Acc:0.9714
Epoch 004 [000/600] Loss:0.1098
Epoch 004 [100/600] Loss:0.1288
Epoch 004 [200/600] Loss:0.1078
Epoch 004 [300/600] Loss:0.1325
Epoch 004 [400/600] Loss:0.0649
Epoch 004 [500/600] Loss:0.0683
...Testing @ Epoch 004  Acc:0.9739
Epoch 005 [000/600] Loss:0.0984
Epoch 005 [100/600] Loss:0.1322
Epoch 005 [200/600] Loss:0.0641
Epoch 005 [300/600] Loss:0.0769
Epoch 005 [400/600] Loss:0.1507
Epoch 005 [500/600] Loss:0.0377
...Testing @ Epoch 005  Acc:0.9742
Epoch 006 [000/600] Loss:0.0954
Epoch 006 [100/600] Loss:0.0889
Epoch 006 [200/600] Loss:0.0666
Epoch 006 [300/600] Loss:0.0448
Epoch 006 [400/600] Loss:0.0285
Epoch 006 [500/600] Loss:0.0581
...Testing @ Epoch 006  Acc:0.9773
Epoch 007 [000/600] Loss:0.0305
Epoch 007 [100/600] Loss:0.0651
Epoch 007 [200/600] Loss:0.1007
Epoch 007 [300/600] Loss:0.1537
Epoch 007 [400/600] Loss:0.0233
Epoch 007 [500/600] Loss:0.0925
...Testing @ Epoch 007  Acc:0.9750
Epoch 008 [000/600] Loss:0.1807
Epoch 008 [100/600] Loss:0.0373
Epoch 008 [200/600] Loss:0.0600
Epoch 008 [300/600] Loss:0.2233
Epoch 008 [400/600] Loss:0.0469
Epoch 008 [500/600] Loss:0.0817
...Testing @ Epoch 008  Acc:0.9795
Epoch 009 [000/600] Loss:0.1331
Epoch 009 [100/600] Loss:0.1417
Epoch 009 [200/600] Loss:0.0429
Epoch 009 [300/600] Loss:0.0552
Epoch 009 [400/600] Loss:0.0117
Epoch 009 [500/600] Loss:0.0611
...Testing @ Epoch 009  Acc:0.9780
Epoch 010 [000/600] Loss:0.0386
Epoch 010 [100/600] Loss:0.2372
Epoch 010 [200/600] Loss:0.0092
Epoch 010 [300/600] Loss:0.0623
Epoch 010 [400/600] Loss:0.0530
Epoch 010 [500/600] Loss:0.0345
...Testing @ Epoch 010  Acc:0.9797
Epoch 011 [000/600] Loss:0.1051
Epoch 011 [100/600] Loss:0.0507
Epoch 011 [200/600] Loss:0.1075
Epoch 011 [300/600] Loss:0.0414
Epoch 011 [400/600] Loss:0.0256
Epoch 011 [500/600] Loss:0.0631
...Testing @ Epoch 011  Acc:0.9778
Epoch 012 [000/600] Loss:0.0873
Epoch 012 [100/600] Loss:0.0693
Epoch 012 [200/600] Loss:0.0779
Epoch 012 [300/600] Loss:0.2842
Epoch 012 [400/600] Loss:0.0314
Epoch 012 [500/600] Loss:0.0197
...Testing @ Epoch 012  Acc:0.9778
……

3.函数式操作

见《PyTorch应用实战二:实现卷积神经网络进行图像分类》

目录
相关文章
|
23天前
|
机器学习/深度学习
小土堆-pytorch-神经网络-损失函数与反向传播_笔记
在使用损失函数时,关键在于匹配输入和输出形状。例如,在L1Loss中,输入形状中的N代表批量大小。以下是具体示例:对于相同形状的输入和目标张量,L1Loss默认计算差值并求平均;此外,均方误差(MSE)也是常用损失函数。实战中,损失函数用于计算模型输出与真实标签间的差距,并通过反向传播更新模型参数。
|
26天前
|
机器学习/深度学习 数据采集 数据可视化
深度学习实践:构建并训练卷积神经网络(CNN)对CIFAR-10数据集进行分类
本文详细介绍如何使用PyTorch构建并训练卷积神经网络(CNN)对CIFAR-10数据集进行图像分类。从数据预处理、模型定义到训练过程及结果可视化,文章全面展示了深度学习项目的全流程。通过实际操作,读者可以深入了解CNN在图像分类任务中的应用,并掌握PyTorch的基本使用方法。希望本文为您的深度学习项目提供有价值的参考与启示。
|
1月前
|
存储 缓存 PyTorch
使用PyTorch从零构建Llama 3
本文将详细指导如何从零开始构建完整的Llama 3模型架构,并在自定义数据集上执行训练和推理。
47 1
|
17天前
|
机器学习/深度学习 数据挖掘 TensorFlow
解锁Python数据分析新技能,TensorFlow&PyTorch双引擎驱动深度学习实战盛宴
在数据驱动时代,Python凭借简洁的语法和强大的库支持,成为数据分析与机器学习的首选语言。Pandas和NumPy是Python数据分析的基础,前者提供高效的数据处理工具,后者则支持科学计算。TensorFlow与PyTorch作为深度学习领域的两大框架,助力数据科学家构建复杂神经网络,挖掘数据深层价值。通过Python打下的坚实基础,结合TensorFlow和PyTorch的强大功能,我们能在数据科学领域探索无限可能,解决复杂问题并推动科研进步。
38 0
|
2月前
|
Java 前端开发 Apache
Apache Wicket与Spring MVC等Java Web框架大PK,究竟谁才是你的最佳拍档?点击揭秘!
【8月更文挑战第31天】在Java Web开发领域,众多框架各具特色。Apache Wicket以组件化开发和易用性脱颖而出,提高了代码的可维护性和可读性。相比之下,Spring MVC拥有强大的生态系统,但学习曲线较陡;JSF与Java EE紧密集成,但在性能和灵活性上略逊一筹;Struts2虽成熟,但在RESTful API支持上不足。选择框架时还需考虑社区支持和文档完善程度。希望本文能帮助开发者找到最适合自己的框架。
31 0
|
2月前
|
机器学习/深度学习 人工智能 TensorFlow
深度学习入门:使用Python和TensorFlow构建你的第一个神经网络
【8月更文挑战第31天】 本文是一篇面向初学者的深度学习指南,旨在通过简洁明了的语言引导读者了解并实现他们的第一个神经网络。我们将一起探索深度学习的基本概念,并逐步构建一个能够识别手写数字的简单模型。文章将展示如何使用Python语言和TensorFlow框架来训练我们的网络,并通过直观的例子使抽象的概念具体化。无论你是编程新手还是深度学习领域的新兵,这篇文章都将成为你探索这个激动人心领域的垫脚石。
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习之旅:构建你的第一个神经网络
【8月更文挑战第31天】在人工智能的浪潮下,深度学习技术正以前所未有的速度改变世界。本文将带你走进深度学习的大门,通过构建一个简单的神经网络模型,探索其背后的原理与实践。我们将从基础概念入手,逐步实现一个能够识别手写数字的神经网络,并在此过程中揭示深度学习的魅力和力量。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开一扇通往深度学习世界的新窗户。
|
2月前
|
机器学习/深度学习 自然语言处理 TensorFlow
TensorFlow 入门超简单!从零开始构建你的第一个神经网络,开启机器学习精彩之旅!
【8月更文挑战第31天】本文介绍了流行开源机器学习框架 TensorFlow,涵盖其安装与首个神经网络构建步骤。TensorFlow 由 Google 开发,适用于计算机视觉及自然语言处理等领域。掌握它不仅提升就业机会,还加深对机器学习的理解。通过安装 Python 并使用 pip 命令安装 TensorFlow,即可按照示例构建、训练并评估简单的线性回归模型,快速开启机器学习之旅。
30 0
|
2月前
|
机器学习/深度学习 人工智能 算法
使用Python构建简易神经网络
【8月更文挑战第31天】在本文中,我们将一起探索如何用Python编程语言构建一个简单的神经网络。通过这个入门级项目,读者将学会如何使用基本的编程技能来模拟人脑的神经元网络。文章不仅解释了神经网络的核心概念,还提供了代码示例来帮助初学者理解如何实现一个能够进行简单模式识别的神经网络。
|
2月前
|
机器学习/深度学习 人工智能 算法框架/工具
使用Python构建简单神经网络进行图像识别
【8月更文挑战第31天】在本文中,我们将探索如何利用Python编程语言和深度学习框架Keras来搭建一个简单的神经网络模型。通过这个模型,我们能够实现基础的图像识别功能。文章将引导读者了解神经网络的基本概念,手把手教学如何准备数据集、构建网络结构、训练模型以及评估结果。最终,我们将看到即使是简单的神经网络也能在处理图像识别任务时展现出惊人的能力。
下一篇
无影云桌面