本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:SHAP方法是一种基于博弈论的模型解释技术,旨在为机器学习模型的预测提供可理解的解释。本文档展示了使用SHAP分析方法对MNIST数据集进行解释性分析的实验代码重现。MNIST数据集广泛用于计算机视觉任务,尤其是手写数字识别。实验使用Python的PyTorch库来构建和训练神经网络模型,并使用SHAP库解释模型在数据集上的预测行为。代码包括Jupyter Notebook文件、Markdown文档和Python源代码文件,通过遮掩实验观察模型预测的变化,理解特征对预测结果的贡献。
SHAP分析Mnist数据集遮掩实验复现代码

1. SHAP解释性分析方法

1.1 解释性分析的重要性

在机器学习和深度学习领域中,模型的预测结果解释性越来越受到重视。这是因为良好的解释性能够提升模型的透明度,帮助开发者和使用者理解模型是如何得出特定预测的。这对于信任构建、决策支持以及模型改进至关重要。

1.2 SHAP(SHapley Additive exPlanations)的基本概念

SHAP是一种基于博弈论中Shapley值的模型解释方法,它通过量化每个特征对于预测结果的贡献度,来解释模型的预测。该方法不仅适用于线性模型,还能很好地扩展到非线性、复杂模型,如深度神经网络。

1.3 SHAP的工作流程

使用SHAP进行模型解释的过程通常包括以下步骤:
- 准备模型:确保你有一个训练好的模型,可以进行预测。
- 计算SHAP值:通过SHAP库提供的接口来计算各个特征的SHAP值,这表示每个特征对于预测结果的贡献。
- 结果分析:通过可视化工具展示SHAP值,从而直观地理解模型预测的决策过程。

import shap

# 一个简单的例子,使用SHAP解释一个预训练模型
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_test)

# 可视化第一个预测的SHAP值
shap.initjs()
shap.force_plot(explainer.expected_value, shap_values[0,:], X_test.iloc[0,:])

在上述代码中,我们使用 TreeExplainer 来解释一个树模型, shap_values 中包含了对测试集 X_test 中每条数据的特征贡献值。 shap.force_plot 是一个便捷的方式来可视化特定预测的特征贡献。

2. MNIST数据集在计算机视觉中的应用

2.1 MNIST数据集概述

2.1.1 数据集的来源与组成

MNIST数据集是机器学习与计算机视觉领域的”Hello World”,它由Yann LeCun、Corinna Cortes和Christopher J.C. Burges共同收集。此数据集包含手写数字0到9的灰度图,图像是28x28像素的大小,被统一标准化到[0, 1]范围内的浮点数,其中0表示纯黑,1表示纯白。

数据集分为两个部分:训练集和测试集。训练集包含60,000个样本,用于训练模型;测试集包含10,000个样本,用于测试训练后的模型性能。每个样本都附有一个标签,表示图像中的数字。

2.1.2 数据集在计算机视觉中的地位

作为最广泛使用的数据集之一,MNIST在机器学习和计算机视觉的研究中具有重要的地位。它不仅用于基准测试和模型验证,也常被作为教学案例,帮助初学者理解和掌握各种学习算法。

在计算机视觉发展史上,MNIST验证了许多重要的技术,例如卷积神经网络(CNN)。事实上,MNIST已成为评估新技术的一个简单但有效的测试平台。它的成功应用,证明了深度学习在图像识别领域中的潜力和有效性。

2.2 MNIST数据集的预处理

2.2.1 数据加载与标准化

在深度学习模型训练之前,数据预处理是至关重要的一步。对于MNIST数据集,首先需要将其加载到内存中,并进行必要的预处理步骤。

加载数据通常借助深度学习框架中的数据加载器完成。以PyTorch为例,可以使用 torchvision 库中的 datasets.MNIST 来加载数据集,并利用 DataLoader 进行批量处理。

import torch
from torchvision import datasets, transforms
from torch.utils.data import DataLoader

# 定义数据转换
transform = transforms.Compose([
    transforms.ToTensor(),  # 将数据转换为Tensor
    transforms.Normalize((0.1307,), (0.3081,))  # 标准化,MNIST数据集的均值和标准差
])

# 加载训练集和测试集
train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform)

# 数据加载器
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=1000, shuffle=False)

数据标准化的目的是为了加快模型的收敛速度,同时降低对模型权重初始化的敏感性。标准化参数 mean std 是根据数据集的统计特性计算得出的,这里(0.1307,)和(0.3081,)是MNIST数据集的全局均值和标准差。

2.2.2 数据增强技术

数据增强是一种扩展数据集规模的技术,通过应用一系列变换如旋转、平移、缩放等来生成新的训练样本,以此提高模型的泛化能力。

在处理图像数据时,数据增强尤其重要,因为它有助于模拟现实世界中数据的多样性。对于MNIST数据集,常见的数据增强包括图像的轻微旋转和位移。以下是使用PyTorch进行数据增强的一个例子:

# 定义数据增强
train_transforms = transforms.Compose([
    transforms.RandomAffine(degrees=0, translate=(0.1, 0.1)),  # 随机平移
    transforms.RandomRotation(5)  # 随机旋转
])

# 应用数据增强
augmented_train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=train_transforms)
augmented_train_loader = DataLoader(augmented_train_dataset, batch_size=64, shuffle=True)

在上述代码中, RandomAffine 变换允许图像在水平和垂直方向上随机平移10%的图像宽度和高度,而 RandomRotation 则在-5度到5度之间随机旋转图像。

数据增强技术在训练深度学习模型时是一个重要的环节,它可以显著提高模型在现实世界应用中的性能,特别是在数据量有限的情况下。

MNIST数据集的预处理对于深度学习模型的成功训练至关重要。通过对数据进行合适的加载和标准化,可以确保数据被模型以正确的方式处理。此外,数据增强技术是提升模型泛化能力的有效手段,它通过引入数据多样性来模拟现实世界条件,进而提高模型在新数据上的表现。

3. PyTorch深度学习模型构建

3.1 PyTorch框架简介

3.1.1 PyTorch框架的优势与特点

PyTorch是一个开源机器学习库,它在研究社区和工业界都受到广泛的欢迎。PyTorch的主要优势和特点可以概括如下:

  • 动态计算图 :PyTorch采用了称为Autograd的系统,它支持动态计算图。这意味着在执行时构建图形,每个运算符都会在运行时构建计算图的一部分。这种动态性让研究人员可以更直观地设计模型并进行调试。

  • 易于使用 :PyTorch提供了简洁而直观的API,可以轻松地实现复杂的神经网络操作和算法。

  • 灵活的开发环境 :它支持动态的计算图,适合进行探索性研究,并且可以轻松适应变化中的网络架构。

  • 强大的社区支持 :PyTorch有一个活跃的开源社区,不断地贡献新的模块和算法。

  • 广泛的应用范围 :从自然语言处理到计算机视觉,PyTorch被用于各种深度学习领域。

3.1.2 PyTorch基本操作与接口

PyTorch中的基本操作涉及了Tensor的创建、操作和转换,以下是一些关键的API和它们的作用:

import torch

# 创建一个未初始化的5x3矩阵
x = torch.empty(5, 3)
# 创建一个随机初始化的矩阵
x = torch.rand(5, 3)
# 创建一个填充零的矩阵
x = torch.zeros(5, 3, dtype=torch.long)

# 创建一个从Python列表创建的Tensor
x = torch.tensor([5.5, 3])
# 使用现有的Tensor创建一个新的Tensor
x = x.new_ones(5, 3, dtype=torch.double) 

# 计算x的梯度
x.requires_grad_(True)
# 操作一个张量作为另一个张量的输入将会追踪历史
y = x + 2
# 对y进行反向传播,计算dy/dx
y.backward()
# 输出梯度
print(x.grad)

# 将张量移动到CPU或GPU上
if torch.cuda.is_available():
    x = x.to('cuda')
    y = y.to('cuda')

通过上述代码块,我们展示了如何创建张量、执行基本运算、设置梯度追踪以及如何将张量移动到不同的设备上进行计算。这些是构建深度学习模型时最常用的PyTorch操作和接口。

3.2 深度学习模型的设计原则

3.2.1 模型结构设计

深度学习模型的设计需要综合考虑多个因素,包括数据的特征、问题的性质、模型的泛化能力等。以下是设计模型结构时应当考虑的关键点:

  • 模型深度和宽度 :确定多少层和每层的神经元数量对于学习容量至关重要。更深或更宽的模型可以捕捉更复杂的模式,但也可能引起过拟合。

  • 激活函数 :选择合适的激活函数能够帮助模型捕捉非线性关系。ReLU及其变体如Leaky ReLU通常被推荐。

  • 正则化技术 :使用L1/L2正则化、Dropout等技术可以防止模型过拟合。

  • 批次归一化 :这可以加速训练过程并允许更高的学习率,同时减轻梯度消失问题。

  • 残差连接 :在深层网络中使用残差连接可以帮助缓解梯度消失问题,使得训练深层网络变得可行。

3.2.2 损失函数与优化器选择

损失函数衡量了模型预测值与实际值之间的差异,而优化器则负责调整模型参数以最小化损失函数。

  • 损失函数 :回归问题常用均方误差(MSE),二分类问题用交叉熵,多分类问题则使用对数似然损失。对于结构化预测问题,损失函数可能更为复杂,例如序列模型通常采用序列到序列的损失。

  • 优化器 :不同的优化器拥有不同的学习速率策略。常见的优化器有SGD、Adam、RMSprop等。选择合适的优化器对于模型的收敛速度和最终性能至关重要。

3.3 PyTorch中的模型实现

3.3.1 神经网络模块构建

在PyTorch中,我们通常会定义一个 nn.Module 子类来实现我们的网络架构。这包括定义层的顺序以及前向传播逻辑。

import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        # 定义第一个卷积层
        self.conv1 = nn.Conv2d(1, 32, 3, padding=1)
        # 定义第二个卷积层
        self.conv2 = nn.Conv2d(32, 64, 3, padding=1)
        # 定义全连接层
        self.fc1 = nn.Linear(7*7*64, 1024)
        self.fc2 = nn.Linear(1024, 10)

    def forward(self, x):
        # 使用ReLU激活函数
        x = F.relu(self.conv1(x))
        x = F.max_pool2d(x, 2)
        x = F.relu(self.conv2(x))
        x = F.max_pool2d(x, 2)
        x = x.view(-1, 7*7*64)
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return F.log_softmax(x, dim=1)

net = Net()

在上述代码中,我们定义了一个简单的CNN网络,并在 forward 方法中描述了数据如何流经网络。 forward 方法定义了网络的前向传播过程,这是模型实现的核心部分。

3.3.2 模型训练与验证过程

深度学习模型的训练过程涉及到多轮迭代,每轮称为一个epoch,在每个epoch中,模型会使用部分数据进行学习,并在剩余的数据上进行评估。

from torch import optim

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.01, momentum=0.9)

# 训练模型
for epoch in range(num_epochs):
    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        inputs, labels = data
        optimizer.zero_grad()   # 清空过往梯度
        outputs = net(inputs)   # 前向传播
        loss = criterion(outputs, labels)  # 计算损失
        loss.backward()         # 反向传播计算梯度
        optimizer.step()        # 更新网络权重
        running_loss += loss.item()
    print(f'Epoch {epoch + 1}, Loss: {running_loss / len(trainloader)}')

# 验证模型
correct = 0
total = 0
with torch.no_grad():
    for data in testloader:
        images, labels = data
        outputs = net(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

print(f'Accuracy of the network on the test images: {100 * correct / total}%')

在这个训练和验证的示例中,我们使用了一个简单的循环来进行训练,并在每个epoch后评估模型在测试集上的性能。验证过程的关键在于确保模型的泛化能力,不使用训练集进行评估是非常重要的。

在上述训练和验证过程中的代码演示了如何在PyTorch中执行模型训练,并使用测试集来评估模型的准确率。这些步骤是深度学习项目中模型实现的核心部分。

4. 模型预测的特征贡献评估

模型预测的准确性是机器学习领域的核心问题之一,但同样重要的是对模型预测进行解释。模型解释性能够帮助我们理解模型是如何做出预测的,哪些特征对预测结果产生了重要影响。SHAP(SHapley Additive exPlanations)作为一种基于博弈论中Shapley值的模型解释性方法,能够提供精确的特征贡献评估。本章节将深入探讨SHAP值的计算原理和在模型解释中的应用。

4.1 SHAP值计算原理

4.1.1 SHAP的理论基础

SHAP值的计算基于Shapley值,这是一个在合作博弈论中用于公平地分配合作收益的概念。在这个上下文中,合作是指多个特征共同作用于一个预测结果的过程。Shapley值的目的是确保每个玩家(本例中的特征)根据其对合作的边际贡献获得公平的收益。具体到机器学习模型中,这意味着每个特征根据其对预测的贡献被赋予一个Shapley值。

4.1.2 SHAP值计算方法

计算SHAP值涉及以下关键步骤:

  1. 定义预测的收益函数 :通常情况下,收益函数可以是预测误差的减少。
  2. 组合不同特征子集的贡献 :通过计算包含不同特征组合的模型预测变化来评估各个特征的边际贡献。
  3. 计算Shapley值 :对所有可能的特征组合使用Shapley公式来计算平均边际贡献。

4.2 SHAP在模型解释中的应用

4.2.1 特征贡献评估实例

为了详细解释SHAP值在实际应用中的工作原理,考虑一个分类模型,该模型用于预测客户是否会购买产品。假设我们有一个特征集包括客户的收入水平、年龄、历史购买记录等。

import shap
import xgboost as xgb
import pandas as pd

# 加载训练好的XGBoost模型
model = xgb.XGBClassifier()
model.load_model('model.xgb')

# 加载数据集
df = pd.read_csv('data.csv')

# 创建SHAP解释器对象
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(df)

# 打印SHAP值,为每个实例计算的特征贡献
shap.summary_plot(shap_values, df)

在上面的代码中,我们使用了 shap.TreeExplainer 来解释基于XGBoost的分类器。 shap_values 对象包含了模型预测中每个特征的SHAP值。 shap.summary_plot 函数用于可视化地展示这些特征贡献。

4.2.2 SHAP值的可视化展示

SHAP值的可视化是理解模型预测的关键。SHAP库提供了一个便捷的方法来可视化特征对预测结果的贡献。以下是两种常用的可视化方法:

  1. summary plot :这个图以条形图的形式展示了每个特征的重要性和它的分布。条形的长度表示特征重要性的平均绝对SHAP值,而颜色表示特征的值。
shap.summary_plot(shap_values, df)
  1. dependence plot :这个图展示了单个特征对预测的边际影响,将SHAP值与特征值对应起来。通过这种方式,我们可以看到不同特征值如何影响模型的预测。
shap.dependence_plot('age', shap_values, df)

以上代码块通过具体指令和可视化图表演示了如何使用SHAP方法评估和解释特征的贡献。在实际应用中,开发者可以根据自身需求调整这些可视化展示,以获得对模型预测更为深入的理解。

下一章节将探讨遮掩实验的设计与实施,进一步深化模型解释性工作的应用层面。

5. 遮掩实验设计与实施

5.1 遮掩实验的理论基础

5.1.1 遮掩实验的概念与目的

遮掩实验(Masking Experiment)是一种用于模型解释性分析的实验方法,旨在通过遮蔽模型的某些输入特征来观察模型输出的变化,从而理解各个特征对模型预测的具体贡献。该方法特别适用于深度学习模型,因为这些模型通常被视为“黑盒”,难以直接理解内部特征的作用。

遮掩实验的基本思想是将输入数据中的某些特征替换为一个中性值(如0、平均值或随机值),而保持其他特征不变,然后观察模型输出的变化。如果模型的预测结果发生显著变化,那么可以推断被遮蔽的特征在模型中起着重要作用。

5.1.2 实验设计的基本原则

进行遮掩实验时,设计的合理性和准确性至关重要。以下是几个基本原则:

  • 最小化干扰原则 :遮蔽特征时应尽量减少对模型其他部分的干扰,确保实验结果的可靠性。
  • 可比性原则 :对照组应与实验组尽量保持一致,仅在需要测试的特征上有所不同。
  • 重复性原则 :每次实验应该有足够的重复次数,以确保结果的统计意义。
  • 全面性原则 :测试应当覆盖模型的所有关键特征,以及不同类型的输入数据。

5.2 遮掩实验的实现步骤

5.2.1 实验环境与工具准备

在开始遮掩实验之前,首先需要准备实验所需的环境和工具:

  • 环境准备 :确保有一套稳定运行的深度学习环境,安装了所有必要的深度学习框架和库(如PyTorch、TensorFlow、SHAP等)。
  • 数据准备 :准备包含要测试特征的数据集,并进行必要的预处理。
  • 工具准备 :安装用于特征遮掩、模型评估和数据可视化的工具和库。

5.2.2 实验的具体操作流程

以下是遮掩实验的具体操作流程:

  1. 选择特征和数据集 :确定要进行遮掩实验的特征和相应的数据集。

  2. 数据预处理

    • 加载数据集,并进行必要的预处理步骤,如归一化、标准化等。
    • 确保数据集已经分为训练集和测试集。
  3. 模型加载与评估准备

    • 加载训练好的模型,并准备进行评估的环境。
    • 如果需要,可以使用SHAP等工具来帮助模型解释。
  4. 特征遮掩与预测

    • 遍历数据集中的每个样本。
    • 对于每个样本,对于每个需要测试的特征,将其值替换为一个中性值。
    • 使用模型对遮蔽后的特征进行预测。
    • 记录和比较原始特征和遮蔽特征后的模型预测结果差异。
  5. 数据收集与分析

    • 收集每个遮蔽特征前后模型预测的差异数据。
    • 分析这些数据,确定哪些特征对模型预测有显著影响。
  6. 结果可视化

    • 使用图表展示遮掩前后预测结果的变化。
    • 可视化各个特征的重要性评分。

下面是一个简化的代码示例,演示如何在PyTorch中实现特征遮掩:

import torch

def mask_features(model, data_loader, features_to_mask):
    model.eval()  # Set the model to evaluation mode
    masking_results = []

    with torch.no_grad():
        for data in data_loader:
            original_output = model(data)
            for feature in features_to_mask:
                # Create a mask for the feature we want to mask
                mask = torch.ones_like(data)
                mask[:, feature] = 0  # Replace the feature values with zero or another neutral value
                masked_data = data * mask
                masked_output = model(masked_data)
                # Record the difference in outputs
                output_diff = original_output - masked_output
                masking_results.append(output_diff)

    return masking_results

# Example usage
# Assuming 'model' is your trained model and 'data_loader' is a DataLoader providing batches of data
features_to_mask = [3, 7]  # Indexes of the features you want to mask (zero-based indexing)
results = mask_features(model, data_loader, features_to_mask)

参数说明
- model : 预训练模型,用于进行预测。
- data_loader : 数据加载器,提供批处理数据。
- features_to_mask : 需要遮掩的特征索引列表。

代码逻辑说明
这个函数首先将模型设置为评估模式,然后遍历数据加载器中的数据。对于每个数据批次,它会记录原始模型输出,然后对指定的特征应用遮掩操作,接着记录模型对于遮掩后数据的输出,并计算输出差异。最终返回所有记录的输出差异列表。

遮掩实验是一个强大的工具,可以帮助我们深入理解模型的行为,尤其是模型如何响应不同的输入特征。通过上述步骤,研究者和工程师可以更精确地识别出对模型性能至关重要的特征,这对于模型的优化、调试和解释性分析都是极其有用的。

6. 模型解释性可视化与性能评估

6.1 模型解释性可视化技术

在机器学习模型的训练与部署过程中,模型解释性可视化技术发挥着至关重要的作用。它不仅帮助数据科学家理解模型的工作原理,而且对于最终用户来说,可视化也是理解模型预测的关键途径。

6.1.1 可视化工具选择与应用

选择合适的可视化工具是实现有效模型解释的第一步。目前,市面上存在许多出色的可视化工具,如TensorBoard、MLflow UI、Shapash等,它们针对不同的需求和使用场景提供了丰富的功能。

以TensorBoard为例,它是一个可视化工具包,可以帮助监控模型训练过程,提供损失函数值和准确率的动态图表,并能可视化模型结构和权重分布。用户可以通过以下命令启用TensorBoard服务:

tensorboard --logdir=/path/to/log-directory

然后,在浏览器中访问 http://localhost:6006 ,即可查看图表。

6.1.2 模型解释性可视化的实践技巧

可视化技术不仅限于训练过程和模型结构,还包括对模型预测的解释。SHAP库结合了多种图表来解释模型预测,例如: summary_plot 能够展示特征对模型预测贡献的总和,以及 dependence_plot 可以展示两个特征之间的关系以及它们对模型预测的影响。

以下是一个使用SHAP库进行 summary_plot 的代码示例:

import shap
explainer = shap.TreeExplainer(model)
shap_values = explainer.shap_values(X_test)

shap.summary_plot(shap_values[1], X_test, feature_names=feature_names)

通过上述代码,我们可以获得一个全局视角的特征重要性图,帮助我们评估特征对模型预测的平均影响。

6.2 模型性能评估与特征重要性排序

模型性能评估是机器学习流程中的核心环节。正确的评估方法不仅可以帮助我们了解模型的有效性,还可以指导我们进行进一步的模型优化。

6.2.1 评估指标与方法

在评估模型性能时,常见的指标包括准确率、精确率、召回率、F1分数、ROC曲线和AUC值。其中,准确率和精确率特别适用于数据集类别分布较均匀的情况。而在不平衡数据集中,F1分数、召回率、ROC-AUC等指标则更加重要,因为它们能更好地反映出模型在少数类别上的表现。

Python中常用的评估方法如 sklearn.metrics 提供了多种评估函数。例如,使用 classification_report 可以直接输出多种指标的报告:

from sklearn.metrics import classification_report
print(classification_report(y_true, y_pred))

6.2.2 特征重要性排序的分析与应用

特征重要性排序是评估模型可解释性的一个重要方面。它可以帮助我们确定哪些特征对于模型的预测结果影响最大。在许多机器学习模型中,特征重要性可以通过模型自带的属性来获取,比如随机森林的 feature_importances_

以下是如何使用随机森林模型进行特征重要性分析的示例:

from sklearn.ensemble import RandomForestClassifier
import pandas as pd

# 训练模型
rf = RandomForestClassifier()
rf.fit(X_train, y_train)

# 特征重要性排序
importances = rf.feature_importances_
indices = np.argsort(importances)[::-1]

# 将结果转换为DataFrame,以获得更好的可视化效果
feature_importances = pd.DataFrame({'feature': X.columns[indices], 'importance': importances[indices]})

在上述代码执行之后,可以通过条形图的形式展示特征的重要性排序,便于直观理解和解释模型。

通过可视化工具和性能评估,我们不仅可以直观地解释模型的预测结果,还能够对模型进行量化的性能评估,从而有效地指导模型优化和调整。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:SHAP方法是一种基于博弈论的模型解释技术,旨在为机器学习模型的预测提供可理解的解释。本文档展示了使用SHAP分析方法对MNIST数据集进行解释性分析的实验代码重现。MNIST数据集广泛用于计算机视觉任务,尤其是手写数字识别。实验使用Python的PyTorch库来构建和训练神经网络模型,并使用SHAP库解释模型在数据集上的预测行为。代码包括Jupyter Notebook文件、Markdown文档和Python源代码文件,通过遮掩实验观察模型预测的变化,理解特征对预测结果的贡献。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐