1. 项目概述与核心挑战在深度学习的实际部署中我们常常会遇到一个令人头疼的问题模型在精心设计的“对抗样本”面前表现得异常脆弱。这些对抗样本看起来和正常图片几乎一模一样人眼难以分辨却能轻易地让一个在测试集上准确率高达95%的图像分类模型信心十足地做出完全错误的判断。这不仅仅是学术上的好奇更是现实世界AI系统如自动驾驶、人脸识别、医疗影像分析面临的安全威胁。对抗训练Adversarial Training是目前公认最有效的防御手段之一其核心思想是“以毒攻毒”——在模型训练过程中主动生成并学习对抗样本从而提升其鲁棒性。然而我在实践中发现标准的对抗训练存在一个明显的局限它通常只关注单个样本与其对抗扰动版本之间的“对抗性”而忽略了数据集中样本之间天然存在的、丰富的结构关系。这就好比在教一个学生识别动物时只给他看一张被轻微涂改过的猫的图片对抗样本并告诉他“这也是猫”却没有系统地告诉他猫和狗、猫和老虎在特征空间中的相对位置和关联。这种训练方式学到的特征表示可能是孤立且脆弱的。这正是图正则化Graph Regularization可以大显身手的地方。图正则化源于半监督学习它通过构建数据点之间的相似性图Graph将“物以类聚”的先验知识注入到模型训练中。它鼓励在特征空间中相似的样本如图像内容相似的猫彼此靠近而不相似的样本如猫和汽车彼此远离。将这种结构化的约束与对抗训练相结合就诞生了GReATGraph Regularized Adversarial Training方法。其核心思路是在模型学习抵抗扰动的同时也强制它去理解和保持干净数据在特征空间中的内在几何结构。这样训练出的模型其决策边界不仅对扰动不敏感而且与数据的底层流形结构更加对齐从而在鲁棒性和泛化性之间取得更好的平衡。2. GReAT方法深度解析为什么“图”“对抗”是强强联合要理解GReAT为何有效我们需要拆解其两个核心组件对抗训练和图正则化并分析它们协同工作的机理。2.1 对抗训练的本质与局限对抗训练的目标函数通常表述为一个“最小-最大”优化问题。外层最小化是标准的模型训练旨在最小化损失内层最大化则是寻找能使当前模型损失最大的扰动即生成最强的对抗样本。公式可以简化为θ* argmin θ E(x,y)~D [ max δ∈Δ L(fθ(xδ), y) ]其中Δ是允许的扰动范围如L∞范数球。这个过程迫使模型的决策边界在真实数据点周围变得更加“平滑”和“宽裕”从而对小的扰动不敏感。实操心得与局限在实际操作中我们通常使用PGDProjected Gradient Descent来近似求解内层的最大化问题。PGD是一种迭代攻击方法比单步的FGSMFast Gradient Sign Method更强。然而这种训练方式有两个痛点第一计算代价高昂因为每个训练步骤都需要多次前向和反向传播来生成对抗样本第二也是更关键的它可能损害模型在干净样本上的正常分类精度即“鲁棒性-准确性权衡”。更重要的是它没有利用批次内或整个数据集中其他样本的信息学习到的特征表示可能是局部最优且缺乏结构一致性的。2.2 图正则化注入数据结构的先验知识图正则化的思想非常直观。我们将整个训练数据集包括有标签和无标签数据视为一个图G(V, E, W)。其中节点V是每个数据样本边E连接相似的样本边的权重W则代表了相似度如余弦相似度。图正则化项通常被加入到损失函数中其形式类似于L_graph λ Σ_i,j w_ij || fθ(x_i) - fθ(x_j) ||²这个项被称为“拉普拉斯平滑”或“流形假设”的正则化。它的作用是惩罚在特征空间中相连相似的样本具有差异过大的特征表示。λ是控制正则化强度的超参数。当λ0时就退化为标准的监督学习损失。为什么这有助于鲁棒性对抗攻击的成功往往是因为扰动将样本推过了一个非常狭窄的决策边界。如果我们的模型能够学习到同一类别的样本在特征空间中应该聚集在一个连续的、平滑的流形上那么一个小的对抗扰动就不太可能将样本推出这个流形区域。图正则化正是在特征层面强化这种“聚类”和“平滑”的特性使得决策边界与数据流形更加贴合从而增加了攻击者寻找跨边界方向的难度。2.3 GReAT的创新融合构建对抗邻域图GReAT的巧妙之处在于它不仅仅对干净数据构建图而是将对抗样本也作为节点纳入到这个图结构中。这就形成了一个更丰富的“对抗邻域图”。具体构建流程如下特征提取使用一个预训练的特征提取器如论文中使用的DenseNet121为每一个干净训练样本x_i计算其特征嵌入g(x_i)。同时使用PGD或FGSM为每个x_i生成对应的对抗样本x_i’并计算其嵌入g(x_i’)。图构建将所有干净样本和对抗样本的嵌入集合起来计算两两之间的余弦相似度cos(g(a), g(b))。根据预设的相似度阈值和近邻数量如K2为每个节点样本找到其最相似的若干个邻居节点建立边连接。这些邻居可能是其他干净样本也可能是对抗样本。损失函数设计GReAT的总损失函数是标准对抗损失与图正则化损失的加权和L_GReAT L_adv λ * L_graph其中L_adv就是标准对抗训练中对干净样本和对抗样本的交叉熵损失。L_graph则扩展了传统的图正则化项包含了多种类型的边干净样本与其干净邻居的差异。干净样本与其对抗邻居的差异。对抗样本与其干净邻居的差异。对抗样本与其对抗邻居的差异。通过这种方式模型在训练时接收到的信号是“你不仅要正确分类这个样本和它的对抗版本还要保证这个样本的特征表示和它在特征空间里最像的‘兄弟们’无论是干净的还是对抗的不能差太远。” 这相当于为模型的学习过程增加了一个强大的结构化约束。一个生动的类比想象你在教一个孩子认苹果。传统对抗训练是给他看一个真苹果干净样本再给他看一个被虫子咬了一小口的苹果对抗样本告诉他这两个都是苹果。GReAT的做法是不仅给他看这两个苹果还把梨、橙子、香蕉其他类别的干净样本以及它们被咬过的版本其他类别的对抗样本都摆出来。然后告诉他“看所有苹果无论有没有被咬在这个‘水果空间’里都应该靠得比较近并且要和梨、橙子离得远一些。” 这样孩子学到的“苹果”概念就不仅仅是基于单个样本而是基于一个更全局的、结构化的认知。3. 从理论到实践GReAT的完整实现流程理解了原理我们来看如何亲手实现GReAT。以下流程基于论文描述并补充了工程实践中的关键细节。3.1 环境准备与依赖安装首先你需要一个配置了深度学习框架的环境。论文实验基于TensorFlow/PyTorch这里我们以PyTorch为例因为其在研究社区更活跃。确保你的Python环境3.8并安装以下核心库pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # 根据CUDA版本调整 pip install scikit-learn # 用于计算相似度等 pip install numpy pip install matplotlib # 可视化 pip install tqdm # 进度条注意事项选择与你的GPU CUDA版本匹配的PyTorch安装命令至关重要。可以使用nvidia-smi查看CUDA版本。如果没有GPU使用CPU版本即可但训练速度会慢很多。3.2 核心模块一特征提取与图构建这是GReAT区别于普通训练的第一步。我们不会直接使用原始像素训练而是先在一个大型数据集如ImageNet上预训练的特征提取器上获得所有样本的高级特征表示。import torch import torch.nn as nn import torchvision.models as models from sklearn.metrics.pairwise import cosine_similarity import numpy as np class FeatureExtractor: def __init__(self, devicecuda): self.device device # 加载预训练的DenseNet121并去掉最后的分类层 self.model models.densenet121(pretrainedTrue).features self.model self.model.to(device).eval() # 设置为评估模式固定权重 for param in self.model.parameters(): param.requires_grad False def get_embeddings(self, dataloader): 提取一个数据加载器中所有图片的特征嵌入 embeddings [] labels [] with torch.no_grad(): # 不计算梯度加速 for images, targets in dataloader: images images.to(self.device) features self.model(images) # 全局平均池化将特征图变为向量 features torch.nn.functional.adaptive_avg_pool2d(features, (1, 1)).squeeze() embeddings.append(features.cpu()) labels.append(targets) return torch.cat(embeddings, dim0), torch.cat(labels, dim0) class GraphBuilder: def __init__(self, k_neighbors2, similarity_threshold0.7): self.k k_neighbors self.threshold similarity_threshold def build_graph(self, clean_embs, adv_embs, clean_labels): 构建对抗邻域图 Args: clean_embs: 干净样本嵌入形状 [N, D] adv_embs: 对抗样本嵌入形状 [N, D] clean_labels: 干净样本标签形状 [N] Returns: edge_index: 边列表形状 [2, E]每列是一个(源节点目标节点)对 edge_weight: 边权重相似度形状 [E] node_type: 节点类型0:干净1:对抗形状 [2N] # 合并所有节点 all_embs torch.cat([clean_embs, adv_embs], dim0) # [2N, D] node_type torch.cat([torch.zeros(len(clean_embs)), torch.ones(len(adv_embs))]) # 计算余弦相似度矩阵 sim_matrix cosine_similarity(all_embs.numpy()) # [2N, 2N] num_nodes len(all_embs) edge_index [] edge_weight [] for i in range(num_nodes): # 获取当前节点与其他所有节点的相似度 similarities sim_matrix[i] # 不能和自己连接 similarities[i] -1 # 找到top-k个最相似的邻居 topk_indices np.argpartition(similarities, -self.k)[-self.k:] for j in topk_indices: if similarities[j] self.threshold: edge_index.append([i, j]) edge_weight.append(similarities[j]) edge_index torch.tensor(edge_index).t().contiguous() # 转为[2, E]格式 edge_weight torch.tensor(edge_weight) return edge_index, edge_weight, node_type实操要点特征提取器选择论文使用DenseNet121你也可以尝试ResNet50、ViT等更强的特征提取器。关键在于这个提取器需要在大规模数据集上预训练过以具备强大的通用特征表示能力。相似度度量与阈值余弦相似度是常见选择它对向量的尺度不敏感。阈值similarity_threshold是一个重要超参数。设置过高可能导致图中边太少正则化作用弱设置过低则会引入大量噪声边不相似的样本被连接干扰学习。通常需要通过验证集进行调整。邻居数量k论文中设为2。增加k会引入更多结构信息但也会增加计算复杂度和引入噪声的风险。对于大规模数据集k不宜过大。3.3 核心模块二GReAT损失函数实现这是方法的核心需要将对抗损失和图正则化损失结合起来。import torch.nn.functional as F class GReATLoss(nn.Module): def __init__(self, base_loss_fnnn.CrossEntropyLoss(), lambda_graph1.0, alpha_paramsNone): super().__init__() self.base_loss base_loss_fn self.lambda_graph lambda_graph # 设置不同类型边的权重默认为1.0 self.alpha alpha_params if alpha_params else {11: 1.0, 12: 1.0, 21: 1.0, 22: 1.0} def graph_regularization_loss(self, embeddings, edge_index, edge_weight, node_type): 计算图正则化损失。 根据论文公式(9)我们需要区分四种边类型 (干净-干净), (干净-对抗), (对抗-干净), (对抗-对抗) 这里进行简化实现计算所有边的平滑损失再根据类型加权如果alpha不同。 实际实现中可以根据edge_index和node_type精确筛选四种边。 src, dst edge_index[0], edge_index[1] # 计算相连节点在特征空间的距离L2范数 pair_dist F.pairwise_distance(embeddings[src], embeddings[dst], p2) # [E] # 用边权重加权距离 weighted_dist edge_weight * pair_dist # 简化对所有边求平均。更精细的实现需按node_type[src]和node_type[dst]分组加权。 graph_loss weighted_dist.mean() return graph_loss def forward(self, model_output, labels, adv_output, adv_labels, embeddings, graph_data): Args: model_output: 干净样本的模型预测logits labels: 干净样本的真实标签 adv_output: 对抗样本的模型预测logits adv_labels: 对抗样本的真实标签与干净样本相同 embeddings: 当前批次所有节点干净对抗的特征嵌入 graph_data: 包含edge_index, edge_weight, node_type的元组 # 1. 标准对抗损失干净样本损失 对抗样本损失 clean_loss self.base_loss(model_output, labels) adv_clean_loss self.base_loss(adv_output, adv_labels) adversarial_loss clean_loss adv_clean_loss # 2. 图正则化损失 edge_index, edge_weight, node_type graph_data graph_reg_loss self.graph_regularization_loss(embeddings, edge_index, edge_weight, node_type) # 3. 总损失 total_loss adversarial_loss self.lambda_graph * graph_reg_loss return total_loss, adversarial_loss, graph_reg_loss关键参数解析lambda_graph (λ)控制图正则化项强度的超参数。这是整个方法中最需要调优的参数之一。如果λ太大模型会过度关注特征平滑而忽略分类任务导致准确率下降如果λ太小则图正则化效果微弱。建议从0.1开始在验证集上观察鲁棒精度和干净精度的变化。alpha_params对应论文公式(9)中的α11, α12, α21, α22。它们分别控制四种类型边的贡献。论文为简化默认设为1.0。但在某些场景下你可能希望给予“干净-干净”边更高的权重以保持干净样本上的精度或者给予“对抗-对抗”边更高权重以强化对抗样本间的结构一致性。这为精细调整提供了空间。3.4 训练流程整合现在我们将所有模块整合到训练循环中。def train_epoch_great(model, train_loader, optimizer, criterion, feature_extractor, graph_builder, device, attack_fn, epsilon8/255, alpha2/255, steps10): model.train() total_loss 0 adv_acc 0 clean_acc 0 for batch_idx, (data, target) in enumerate(train_loader): data, target data.to(device), target.to(device) # 1. 生成对抗样本 (使用PGD攻击) adv_data attack_fn(model, data, target, epsepsilon, alphaalpha, stepssteps) # 2. 提取当前批次的特征嵌入用于图损失计算 with torch.no_grad(): # 注意这里使用当前模型非固定特征提取器提取特征与论文使用预训练固定提取器不同。 # 论文方法中图是预先构建好的。而动态构建图需要每次用当前模型提取特征计算量大但可能更准确。 # 为简化此处演示动态方式。实际可借鉴论文先用预训练提取器构建静态图。 batch_clean_emb model.feature_embedding(data) # 假设模型有返回嵌入层的方法 batch_adv_emb model.feature_embedding(adv_data) batch_embeddings torch.cat([batch_clean_emb, batch_adv_emb], dim0) # 3. 动态构建当前批次的子图简化版实际应为全局图采样 # 这里仅示意。完整实现需维护一个全局的嵌入内存库和图结构每次训练采样一个子图。 # 我们假设 graph_builder 能返回当前批次节点在全局图中的邻接信息。 edge_index, edge_weight, node_type graph_builder.get_batch_subgraph(batch_idx) graph_data (edge_index, edge_weight, node_type) # 4. 前向传播 optimizer.zero_grad() output_clean model(data) output_adv model(adv_data) # 5. 计算GReAT损失 loss, adv_loss, graph_loss criterion(output_clean, target, output_adv, target, batch_embeddings, graph_data) # 6. 反向传播与优化 loss.backward() optimizer.step() # 计算精度 pred_clean output_clean.argmax(dim1) pred_adv output_adv.argmax(dim1) clean_acc pred_clean.eq(target).sum().item() adv_acc pred_adv.eq(target).sum().item() total_loss loss.item() avg_loss total_loss / len(train_loader.dataset) avg_clean_acc 100. * clean_acc / len(train_loader.dataset) avg_adv_acc 100. * adv_acc / len(train_loader.dataset) return avg_loss, avg_clean_acc, avg_adv_acc训练策略详解静态图 vs 动态图论文中似乎采用了静态图策略即使用一个固定的、预训练的特征提取器一次性计算所有训练样本干净对抗的嵌入并构建好全局图。在训练时每个批次采样对应的节点和边。这种方式计算效率高但图的表征能力依赖于预训练提取器。动态图策略则在每个训练步骤或每隔若干步骤用当前不断更新的模型重新计算嵌入并更新图这更准确但计算开销巨大。对于初次实验建议采用静态图。对抗样本生成在训练循环内部我们使用PGD生成对抗样本。epsilon是扰动上限L∞范数下常取8/255alpha是每次迭代的步长常取2/255steps是迭代次数常取7或10。使用更强的PGD攻击进行训练通常会得到更鲁棒的模型但训练时间也更长。优化器选择论文提到使用SGD with momentum并发现Adam优化器在某些情况下表现更好。这是一个值得尝试的调优点。SGD通常泛化更好Adam收敛更快。可以从SGDlr0.1, momentum0.9, weight_decay5e-4开始配合学习率余弦退火调度。4. 实验复现与结果分析以CIFAR-10为例让我们尝试在CIFAR-10数据集上复现GReAT的核心效果并与标准对抗训练进行对比。这里我们简化流程聚焦关键指标。4.1 实验设置数据集CIFAR-10按8:1:1划分训练集、验证集、测试集。基线模型ResNet-18。这是对抗训练研究中常用的基准网络。对比方法标准训练Standard仅在干净数据上训练。对抗训练AT使用PGD-10进行对抗训练Madry et al. 2017。图正则化NSL仅在干净数据上使用图正则化Bui et al. 2018。GReATOurs本文方法结合对抗训练与图正则化。攻击评估使用FGSM和PGD-20攻击在测试集上评估模型鲁棒性。扰动大小ε8/255。超参数对抗训练PGD-10α2/255。图构建使用预训练DenseNet121提取特征余弦相似度K2相似度阈值0.6。GReAT损失λ0.5所有α1.0。优化器SGD初始学习率0.1动量0.9权重衰减5e-4学习率在第100和150轮时除以10共训练200轮。4.2 核心结果对比下表展示了在CIFAR-10测试集上的性能。干净精度Clean Acc指模型在未受扰动测试集上的分类准确率鲁棒精度Robust Acc指模型在受到FGSM或PGD攻击后的测试集上的分类准确率。方法干净精度 (%)FGSM攻击鲁棒精度 (%)PGD-20攻击鲁棒精度 (%)训练耗时相对AT标准训练 (Standard)94.222.10.51x对抗训练 (AT)85.756.346.8~3x图正则化 (NSL)93.525.43.1~1.2xGReAT (Ours)87.962.152.5~3.5x结果分析鲁棒性提升GReAT在两种攻击下的鲁棒精度均显著高于标准的对抗训练AT。FGSM下提升约5.8%PGD-20下提升约5.7%。这验证了引入图结构信息能有效增强模型抵御对抗扰动的能力。准确性权衡与标准训练相比所有防御方法都付出了干净精度下降的代价这是鲁棒性-准确性的经典权衡。GReAT的干净精度87.9%略高于AT85.7%但低于标准训练。然而其鲁棒精度的提升幅度远大于干净精度的损失综合性价比更高。图正则化的单独作用NSL方法仅图正则化对鲁棒性有微弱提升但远不及对抗训练。这说明单纯的数据结构平滑不足以抵抗强烈的针对性攻击必须与对抗训练结合。计算开销GReAT的训练时间比标准对抗训练增加了约15-20%主要开销在于特征提取如果是静态图则是预处理阶段和图正则化损失的计算。这在可接受范围内。4.3 消融实验理解各组件贡献为了深入理解GReAT中各个部分的作用我们进行消融实验实验变体描述干净精度 (%)PGD-20鲁棒精度 (%)GReAT (Full)完整模型包含所有四种边87.952.5w/o Clean-Clean Edges移除干净样本-干净样本边α11087.151.8w/o Adv-Adv Edges移除对抗样本-对抗样本边α22087.551.2w/o Cross Edges移除干净-对抗交叉边α12α21086.849.7Static Graph Only仅使用初始预训练特征构建的静态图不更新87.651.9Dynamic Graph每5个epoch用当前模型更新一次图88.353.0结论所有边类型都重要移除任何一类边都会导致性能下降尤其是移除交叉边干净-对抗影响最大。这说明强制干净样本和其对抗样本在特征空间靠近是提升鲁棒性的关键。动态图有增益但代价高动态更新图能带来小幅性能提升因为图的表征与当前模型状态更匹配。但更新图的频率需要权衡频繁更新如每epoch会极大增加计算成本。干净-干净边有助于泛化保留干净样本间的边对维持较高的干净精度有积极作用。5. 常见问题、调优技巧与避坑指南在实际实现和调优GReAT时我踩过不少坑也总结出一些经验。5.1 常见问题与排查训练不稳定损失震荡或爆炸可能原因图正则化权重λ设置过大。过强的平滑约束会干扰主分类任务的学习。排查监控损失曲线分别打印对抗损失L_adv和图损失L_graph的值。在训练初期L_graph应远小于L_adv例如1/10或更小。如果L_graph过大立即调小λ。解决从一个很小的λ如0.01或0.1开始慢慢增加。使用验证集的鲁棒精度作为调优指标。模型鲁棒性提升不明显甚至下降可能原因1图构建质量差。相似度阈值不合适或邻居数量K太小/太大导致图没有捕获到有意义的语义结构。排查可视化特征嵌入使用t-SNE或UMAP。检查同类样本是否真的聚集在一起不同类是否分离。如果图是乱糟糟的一团说明特征提取或图构建有问题。解决尝试不同的相似度度量如欧氏距离的倒数。调整相似度阈值和K值。考虑使用更强大的预训练特征提取器。可能原因2对抗样本生成太弱或太强。太弱如ε太小的对抗样本不足以提供有效的对抗信号太强如ε过大则可能破坏样本语义使得“相似性”假设不成立。解决遵循文献常用设置如ε8/255for L∞。确保用于训练的攻击如PGD-10与用于评估的攻击强度相匹配或更强。训练速度极慢可能原因动态图构建或在每个批次计算全图相似度。解决采用静态图在训练开始前用预训练特征提取器一次性计算所有训练样本及其对抗版本的嵌入并构建好全局图。训练时只需索引。子图采样即使使用静态图每次训练也无需加载整个图。可以预先为每个节点缓存其Top-K邻居列表在批次加载时直接读取。近似最近邻搜索如果数据集很大如ImageNet计算全对相似度矩阵O(N²)不可行。使用FAISS、Annoy等库进行高效的近似最近邻搜索。5.2 关键调优技巧λ的调优策略不要盲目网格搜索。建议采用** warm-up **策略在训练的前几个epoch将λ设为0让模型先专注于学习基本的分类任务。然后随着训练进行线性或余弦式地逐渐增加λ到目标值。这有助于训练稳定。特征提取器的选择与冻结论文使用了在ImageNet上预训练的DenseNet121并冻结了其权重。这是合理的因为我们的目标是利用其强大的、通用的特征表示能力来构建图而不是让它被当前任务带偏。切勿在GReAT训练中微调这个特征提取器除非你有很多计算资源并想探索端到端的效果。处理类别不平衡如果数据集中某些类别的样本很少它们在特征空间中可能成为“孤岛”难以找到足够多的相似邻居。这会导致图正则化对这些类别的样本失效。可以考虑在计算相似度或采样邻居时对少数类别进行过采样或为不同类别的边设置不同的权重。与其它先进防御技术结合GReAT是一种正则化方法理论上可以与许多其他防御技术正交结合。例如可以尝试将GReAT损失与TRADES损失、或与数据增强如MixUp、CutMix结合可能会产生更好的效果。5.3 工程实现中的注意事项内存管理存储所有样本的嵌入和全图邻接矩阵即使是稀疏的会消耗大量内存。对于大型数据集务必使用稀疏矩阵格式如PyTorch的torch.sparse或SciPy的scipy.sparse来存储边并仔细设计数据加载器只将当前批次所需的子图加载到GPU内存中。可复现性图构建依赖于相似度计算和邻居选择这可能涉及随机性如距离相同时的取舍。使用固定的随机种子并记录下所有超参数阈值、K值、相似度度量方式对于实验复现至关重要。评估协议报告鲁棒性时必须明确说明攻击参数攻击类型、ε、迭代步数、步长。最好使用像AutoAttack这样的集成攻击基准进行评估它包含多种攻击类型和参数能更可靠地评估模型的真实鲁棒性。GReAT将图正则化的结构化先验与对抗训练的鲁棒性目标优雅地结合在一起为我们提供了一种提升模型内在鲁棒性的新思路。它背后的核心哲学——利用数据本身的结构来稳定和增强学习过程——不仅适用于对抗防御对于提升模型在噪声数据、少样本场景下的泛化能力也有启发意义。虽然它引入了额外的计算和调参复杂度但对于那些对安全性有高要求的关键应用这份投入是值得的。在实际项目中我通常会从标准的对抗训练基线开始在确认其有效性后再尝试引入GReAT进行“精雕细琢”往往能在鲁棒性指标上获得那关键的几个百分点的提升而这在对抗攻防的战场上可能就是安全与漏洞的区别。