InceptionTime时间序列分类实战从理论到代码实现时间序列分类Time Series Classification, TSC是机器学习领域中一个极具挑战性的研究方向它专注于为时间序列数据分配类别标签。在医疗诊断、工业设备监测、金融预测等领域TSC技术正发挥着越来越重要的作用。本文将带您深入探索InceptionTime这一革命性的时间序列分类方法从核心原理到完整代码实现一步步构建属于自己的高性能分类系统。1. InceptionTime架构解析InceptionTime的灵感来源于计算机视觉领域的Inception-v4架构但针对时间序列数据的特点进行了专门优化。与传统的全连接神经网络不同InceptionTime采用了一种独特的模块化设计通过堆叠多个Inception模块来捕获时间序列中不同时间尺度的特征模式。核心组件分析Bottleneck层这是Inception模块的第一个关键部分使用1×1卷积核来降低输入数据的维度。例如对于一个M维的多元时间序列bottleneck层会将其转换为m维mM显著减少后续计算的复杂度。# PyTorch实现bottleneck层示例 self.bottleneck nn.Conv1d(in_channelsinput_dim, out_channelsreduced_dim, kernel_size1)多尺度卷积Inception模块的核心创新在于并行使用多个不同长度的卷积核如10、20、40时间步长同时处理输入数据。这种设计使模型能够捕获短期、中期和长期的时序模式。# 多尺度卷积实现 self.conv10 nn.Conv1d(reduced_dim, filters, kernel_size10, paddingsame) self.conv20 nn.Conv1d(reduced_dim, filters, kernel_size20, paddingsame) self.conv40 nn.Conv1d(reduced_dim, filters, kernel_size40, paddingsame)残差连接每个Inception模块的输出会与原始输入相加形成残差连接。这种设计有效缓解了深层网络中的梯度消失问题使模型能够训练得更深。感受野计算感受野决定了网络能够看到的时间序列范围。对于步长为1的卷积网络感受野计算公式为1 Σ(k_i - 1) 其中k_i是第i层卷积核的大小通过调整卷积核大小和网络深度InceptionTime可以灵活控制感受野范围适应不同长度的时间序列模式识别需求。2. 实验环境搭建与数据准备2.1 硬件与软件要求推荐配置组件最低要求推荐配置CPU4核8核及以上GPU4GB显存NVIDIA RTX 2080 Ti及以上内存8GB16GB及以上存储50GB空间SSD硬盘Python环境依赖# 创建conda环境 conda create -n inceptiontime python3.8 conda activate inceptiontime # 安装核心依赖 pip install torch1.10.0 torchvision0.11.0 pip install numpy pandas scikit-learn matplotlib pip install tslearn # 时间序列处理专用库2.2 UCR数据集处理UCR时间序列归档是TSC领域的标准基准数据集集合包含85个不同领域的时间序列数据集。我们需要从 UCR官网 下载数据并按照以下结构组织UCR_TS_Archive_2018/ ├── Adiac/ │ ├── Adiac_TRAIN.tsv │ └── Adiac_TEST.tsv ├── Beef/ │ ├── Beef_TRAIN.tsv │ └── Beef_TEST.tsv └── ...其他数据集数据预处理流程标准化处理对每个时间序列进行z-score标准化使其均值为0标准差为1缺失值处理用线性插值填补可能的缺失值数据增强通过时间扭曲、添加噪声等方式扩充训练数据from tslearn.preprocessing import TimeSeriesScalerMeanVariance # 数据标准化示例 scaler TimeSeriesScalerMeanVariance() X_train scaler.fit_transform(X_train) X_test scaler.transform(X_test)3. 完整模型实现与训练3.1 Inception模块实现import torch import torch.nn as nn class InceptionModule(nn.Module): def __init__(self, input_dim, reduced_dim, filters): super(InceptionModule, self).__init__() # Bottleneck层 self.bottleneck nn.Conv1d(input_dim, reduced_dim, kernel_size1) # 多尺度卷积 self.conv10 nn.Sequential( nn.Conv1d(reduced_dim, filters, kernel_size10, paddingsame), nn.BatchNorm1d(filters), nn.ReLU() ) self.conv20 nn.Sequential( nn.Conv1d(reduced_dim, filters, kernel_size20, paddingsame), nn.BatchNorm1d(filters), nn.ReLU() ) self.conv40 nn.Sequential( nn.Conv1d(reduced_dim, filters, kernel_size40, paddingsame), nn.BatchNorm1d(filters), nn.ReLU() ) # 最大池化分支 self.maxpool nn.Sequential( nn.MaxPool1d(kernel_size3, stride1, padding1), nn.Conv1d(input_dim, filters, kernel_size1), nn.BatchNorm1d(filters), nn.ReLU() ) # 残差连接适配层 self.residual nn.Sequential( nn.Conv1d(input_dim, 4*filters, kernel_size1), nn.BatchNorm1d(4*filters) ) self.relu nn.ReLU() self.dropout nn.Dropout(0.2) def forward(self, x): residual self.residual(x) # 通过bottleneck层 bt self.bottleneck(x) # 并行卷积处理 conv10_out self.conv10(bt) conv20_out self.conv20(bt) conv40_out self.conv40(bt) pool_out self.maxpool(x) # 拼接各分支输出 out torch.cat([conv10_out, conv20_out, conv40_out, pool_out], dim1) out self.dropout(out) # 残差连接 out residual return self.relu(out)3.2 完整InceptionTime模型class InceptionTime(nn.Module): def __init__(self, input_dim, num_classes, num_modules6, reduced_dim32, filters32): super(InceptionTime, self).__init__() # 堆叠多个Inception模块 self.inception_modules nn.Sequential() for i in range(num_modules): self.inception_modules.add_module( finception_{i}, InceptionModule( input_dim if i 0 else 4*filters, reduced_dim, filters ) ) # 全局平均池化和分类层 self.gap nn.AdaptiveAvgPool1d(1) self.fc nn.Linear(4*filters, num_classes) def forward(self, x): # 输入形状: (batch_size, input_dim, seq_len) x self.inception_modules(x) x self.gap(x).squeeze(-1) return self.fc(x)3.3 模型训练与评估训练流程关键参数参数推荐值说明学习率0.001使用Adam优化器的默认学习率Batch Size64平衡内存使用和梯度稳定性训练轮数500配合早停法使用权重初始化Glorot均匀分布有助于缓解梯度问题from torch.optim import Adam from torch.utils.data import DataLoader, TensorDataset def train_model(model, train_loader, val_loader, num_epochs500, lr0.001): device torch.device(cuda if torch.cuda.is_available() else cpu) model model.to(device) criterion nn.CrossEntropyLoss() optimizer Adam(model.parameters(), lrlr) best_acc 0.0 patience 20 patience_counter 0 for epoch in range(num_epochs): model.train() train_loss 0.0 for inputs, labels in train_loader: inputs, labels inputs.to(device), labels.to(device) optimizer.zero_grad() outputs model(inputs) loss criterion(outputs, labels) loss.backward() optimizer.step() train_loss loss.item() * inputs.size(0) # 验证阶段 val_acc evaluate(model, val_loader, device) train_loss train_loss / len(train_loader.dataset) print(fEpoch {epoch1}/{num_epochs} - Train Loss: {train_loss:.4f} - Val Acc: {val_acc:.4f}) # 早停机制 if val_acc best_acc: best_acc val_acc patience_counter 0 torch.save(model.state_dict(), best_model.pth) else: patience_counter 1 if patience_counter patience: print(fEarly stopping at epoch {epoch1}) break # 加载最佳模型 model.load_state_dict(torch.load(best_model.pth)) return model def evaluate(model, data_loader, device): model.eval() correct 0 total 0 with torch.no_grad(): for inputs, labels in data_loader: inputs, labels inputs.to(device), labels.to(device) outputs model(inputs) _, predicted torch.max(outputs.data, 1) total labels.size(0) correct (predicted labels).sum().item() return correct / total4. 结果分析与对比4.1 性能对比实验在UCR 85数据集上的对比结果显示InceptionTime与当前最先进的HIVE-COTE算法精度相当但在训练效率上具有显著优势指标InceptionTimeHIVE-COTE平均准确率92.3%92.1%训练时间(1500样本)1小时8天可扩展性可处理800万样本限于数千样本Win/Tie/Loss40/6/39-关键发现集成规模5个Inception网络的集成在精度和计算成本之间取得了最佳平衡。增加更多网络带来的提升有限而减少网络数量会导致性能下降。感受野影响对于长序列分类任务较大的感受野通过增加网络深度或使用更长的卷积核能显著提升模型性能。但在短序列任务中过大的感受野可能导致性能下降。计算效率InceptionTime的训练时间随序列长度线性增长而HIVE-COTE的时间复杂度为O(N²·T⁴)使其难以应用于大规模数据集。4.2 可视化分析训练过程监控import matplotlib.pyplot as plt def plot_training(history): plt.figure(figsize(12, 4)) plt.subplot(1, 2, 1) plt.plot(history[train_loss], labelTrain Loss) plt.title(Training Loss) plt.xlabel(Epoch) plt.ylabel(Loss) plt.subplot(1, 2, 2) plt.plot(history[val_acc], labelValidation Accuracy) plt.title(Validation Accuracy) plt.xlabel(Epoch) plt.ylabel(Accuracy) plt.tight_layout() plt.show()特征可视化通过t-SNE或PCA降维技术我们可以将InceptionTime学习到的高维特征投影到二维空间直观展示不同类别时间序列的分离情况from sklearn.manifold import TSNE def visualize_features(model, dataloader, device): model.eval() features [] labels [] with torch.no_grad(): for inputs, lbls in dataloader: inputs inputs.to(device) feat model.inception_modules(inputs) feat model.gap(feat).squeeze() features.append(feat.cpu()) labels.append(lbls) features torch.cat(features).numpy() labels torch.cat(labels).numpy() # t-SNE降维 tsne TSNE(n_components2, random_state42) reduced tsne.fit_transform(features) # 绘制散点图 plt.figure(figsize(10, 8)) scatter plt.scatter(reduced[:, 0], reduced[:, 1], clabels, alpha0.6) plt.legend(*scatter.legend_elements(), titleClasses) plt.title(t-SNE Visualization of Learned Features) plt.show()5. 高级技巧与优化策略5.1 迁移学习策略InceptionTime在不同数据集间展现出良好的迁移学习能力。我们可以采用以下策略预训练-微调在大规模时间序列数据集上预训练模型然后在目标数据集上进行微调特征提取固定Inception模块权重仅训练最后的全连接层渐进式解冻从顶层开始逐步解冻和微调模型层def transfer_learning(model, source_loader, target_loader, freeze_layersTrue): if freeze_layers: for param in model.inception_modules.parameters(): param.requires_grad False # 仅训练分类层 optimizer Adam(filter(lambda p: p.requires_grad, model.parameters())) # 训练过程与之前类似 train_model(model, target_loader, ...)5.2 超参数优化通过网格搜索或贝叶斯优化方法我们可以找到特定数据集上的最优超参数组合关键超参数范围参数搜索范围影响Inception模块数量3-9模型深度和感受野初始filter数量16-64模型容量Bottleneck维度16-64计算效率学习率1e-4到1e-3收敛速度和稳定性Batch Size32-128内存使用和梯度估计from sklearn.model_selection import ParameterGrid param_grid { num_modules: [4, 6, 8], filters: [32, 64], reduced_dim: [16, 32], lr: [0.0005, 0.001] } best_acc 0 best_params None for params in ParameterGrid(param_grid): model InceptionTime(input_dim1, num_classesN_CLASSES, **params) trained_model train_model(model, train_loader, val_loader, lrparams[lr]) acc evaluate(trained_model, test_loader, device) if acc best_acc: best_acc acc best_params params print(fBest Accuracy: {best_acc:.4f} with params: {best_params})5.3 模型解释性理解模型决策过程对于许多应用场景至关重要。我们可以使用以下方法增强InceptionTime的解释性梯度类激活图Grad-CAM可视化时间序列中对分类决策最重要的区域特征重要性分析分析不同时间尺度特征对最终预测的贡献度原型分析通过反卷积找到最能激活特定神经元的输入模式def grad_cam(model, input_tensor, target_class, device): model.eval() input_tensor input_tensor.to(device).requires_grad_() # 获取最后一个Inception模块的输出 features model.inception_modules(input_tensor.unsqueeze(0)) # 获取目标类别的梯度 output model.fc(model.gap(features).squeeze()) output[:, target_class].backward() # 计算权重 gradients input_tensor.grad pooled_gradients torch.mean(gradients, dim[0, 2]) # 加权特征图 features features.squeeze(0) for i in range(features.shape[0]): features[i, :] * pooled_gradients[i] heatmap torch.mean(features, dim0).detach().cpu() heatmap np.maximum(heatmap, 0) heatmap / torch.max(heatmap) return heatmap.numpy()
InceptionTime 时间序列分类实战:5模型集成在UCR 85数据集上精度持平HIVE-COTE
发布时间:2026/7/5 11:44:02
InceptionTime时间序列分类实战从理论到代码实现时间序列分类Time Series Classification, TSC是机器学习领域中一个极具挑战性的研究方向它专注于为时间序列数据分配类别标签。在医疗诊断、工业设备监测、金融预测等领域TSC技术正发挥着越来越重要的作用。本文将带您深入探索InceptionTime这一革命性的时间序列分类方法从核心原理到完整代码实现一步步构建属于自己的高性能分类系统。1. InceptionTime架构解析InceptionTime的灵感来源于计算机视觉领域的Inception-v4架构但针对时间序列数据的特点进行了专门优化。与传统的全连接神经网络不同InceptionTime采用了一种独特的模块化设计通过堆叠多个Inception模块来捕获时间序列中不同时间尺度的特征模式。核心组件分析Bottleneck层这是Inception模块的第一个关键部分使用1×1卷积核来降低输入数据的维度。例如对于一个M维的多元时间序列bottleneck层会将其转换为m维mM显著减少后续计算的复杂度。# PyTorch实现bottleneck层示例 self.bottleneck nn.Conv1d(in_channelsinput_dim, out_channelsreduced_dim, kernel_size1)多尺度卷积Inception模块的核心创新在于并行使用多个不同长度的卷积核如10、20、40时间步长同时处理输入数据。这种设计使模型能够捕获短期、中期和长期的时序模式。# 多尺度卷积实现 self.conv10 nn.Conv1d(reduced_dim, filters, kernel_size10, paddingsame) self.conv20 nn.Conv1d(reduced_dim, filters, kernel_size20, paddingsame) self.conv40 nn.Conv1d(reduced_dim, filters, kernel_size40, paddingsame)残差连接每个Inception模块的输出会与原始输入相加形成残差连接。这种设计有效缓解了深层网络中的梯度消失问题使模型能够训练得更深。感受野计算感受野决定了网络能够看到的时间序列范围。对于步长为1的卷积网络感受野计算公式为1 Σ(k_i - 1) 其中k_i是第i层卷积核的大小通过调整卷积核大小和网络深度InceptionTime可以灵活控制感受野范围适应不同长度的时间序列模式识别需求。2. 实验环境搭建与数据准备2.1 硬件与软件要求推荐配置组件最低要求推荐配置CPU4核8核及以上GPU4GB显存NVIDIA RTX 2080 Ti及以上内存8GB16GB及以上存储50GB空间SSD硬盘Python环境依赖# 创建conda环境 conda create -n inceptiontime python3.8 conda activate inceptiontime # 安装核心依赖 pip install torch1.10.0 torchvision0.11.0 pip install numpy pandas scikit-learn matplotlib pip install tslearn # 时间序列处理专用库2.2 UCR数据集处理UCR时间序列归档是TSC领域的标准基准数据集集合包含85个不同领域的时间序列数据集。我们需要从 UCR官网 下载数据并按照以下结构组织UCR_TS_Archive_2018/ ├── Adiac/ │ ├── Adiac_TRAIN.tsv │ └── Adiac_TEST.tsv ├── Beef/ │ ├── Beef_TRAIN.tsv │ └── Beef_TEST.tsv └── ...其他数据集数据预处理流程标准化处理对每个时间序列进行z-score标准化使其均值为0标准差为1缺失值处理用线性插值填补可能的缺失值数据增强通过时间扭曲、添加噪声等方式扩充训练数据from tslearn.preprocessing import TimeSeriesScalerMeanVariance # 数据标准化示例 scaler TimeSeriesScalerMeanVariance() X_train scaler.fit_transform(X_train) X_test scaler.transform(X_test)3. 完整模型实现与训练3.1 Inception模块实现import torch import torch.nn as nn class InceptionModule(nn.Module): def __init__(self, input_dim, reduced_dim, filters): super(InceptionModule, self).__init__() # Bottleneck层 self.bottleneck nn.Conv1d(input_dim, reduced_dim, kernel_size1) # 多尺度卷积 self.conv10 nn.Sequential( nn.Conv1d(reduced_dim, filters, kernel_size10, paddingsame), nn.BatchNorm1d(filters), nn.ReLU() ) self.conv20 nn.Sequential( nn.Conv1d(reduced_dim, filters, kernel_size20, paddingsame), nn.BatchNorm1d(filters), nn.ReLU() ) self.conv40 nn.Sequential( nn.Conv1d(reduced_dim, filters, kernel_size40, paddingsame), nn.BatchNorm1d(filters), nn.ReLU() ) # 最大池化分支 self.maxpool nn.Sequential( nn.MaxPool1d(kernel_size3, stride1, padding1), nn.Conv1d(input_dim, filters, kernel_size1), nn.BatchNorm1d(filters), nn.ReLU() ) # 残差连接适配层 self.residual nn.Sequential( nn.Conv1d(input_dim, 4*filters, kernel_size1), nn.BatchNorm1d(4*filters) ) self.relu nn.ReLU() self.dropout nn.Dropout(0.2) def forward(self, x): residual self.residual(x) # 通过bottleneck层 bt self.bottleneck(x) # 并行卷积处理 conv10_out self.conv10(bt) conv20_out self.conv20(bt) conv40_out self.conv40(bt) pool_out self.maxpool(x) # 拼接各分支输出 out torch.cat([conv10_out, conv20_out, conv40_out, pool_out], dim1) out self.dropout(out) # 残差连接 out residual return self.relu(out)3.2 完整InceptionTime模型class InceptionTime(nn.Module): def __init__(self, input_dim, num_classes, num_modules6, reduced_dim32, filters32): super(InceptionTime, self).__init__() # 堆叠多个Inception模块 self.inception_modules nn.Sequential() for i in range(num_modules): self.inception_modules.add_module( finception_{i}, InceptionModule( input_dim if i 0 else 4*filters, reduced_dim, filters ) ) # 全局平均池化和分类层 self.gap nn.AdaptiveAvgPool1d(1) self.fc nn.Linear(4*filters, num_classes) def forward(self, x): # 输入形状: (batch_size, input_dim, seq_len) x self.inception_modules(x) x self.gap(x).squeeze(-1) return self.fc(x)3.3 模型训练与评估训练流程关键参数参数推荐值说明学习率0.001使用Adam优化器的默认学习率Batch Size64平衡内存使用和梯度稳定性训练轮数500配合早停法使用权重初始化Glorot均匀分布有助于缓解梯度问题from torch.optim import Adam from torch.utils.data import DataLoader, TensorDataset def train_model(model, train_loader, val_loader, num_epochs500, lr0.001): device torch.device(cuda if torch.cuda.is_available() else cpu) model model.to(device) criterion nn.CrossEntropyLoss() optimizer Adam(model.parameters(), lrlr) best_acc 0.0 patience 20 patience_counter 0 for epoch in range(num_epochs): model.train() train_loss 0.0 for inputs, labels in train_loader: inputs, labels inputs.to(device), labels.to(device) optimizer.zero_grad() outputs model(inputs) loss criterion(outputs, labels) loss.backward() optimizer.step() train_loss loss.item() * inputs.size(0) # 验证阶段 val_acc evaluate(model, val_loader, device) train_loss train_loss / len(train_loader.dataset) print(fEpoch {epoch1}/{num_epochs} - Train Loss: {train_loss:.4f} - Val Acc: {val_acc:.4f}) # 早停机制 if val_acc best_acc: best_acc val_acc patience_counter 0 torch.save(model.state_dict(), best_model.pth) else: patience_counter 1 if patience_counter patience: print(fEarly stopping at epoch {epoch1}) break # 加载最佳模型 model.load_state_dict(torch.load(best_model.pth)) return model def evaluate(model, data_loader, device): model.eval() correct 0 total 0 with torch.no_grad(): for inputs, labels in data_loader: inputs, labels inputs.to(device), labels.to(device) outputs model(inputs) _, predicted torch.max(outputs.data, 1) total labels.size(0) correct (predicted labels).sum().item() return correct / total4. 结果分析与对比4.1 性能对比实验在UCR 85数据集上的对比结果显示InceptionTime与当前最先进的HIVE-COTE算法精度相当但在训练效率上具有显著优势指标InceptionTimeHIVE-COTE平均准确率92.3%92.1%训练时间(1500样本)1小时8天可扩展性可处理800万样本限于数千样本Win/Tie/Loss40/6/39-关键发现集成规模5个Inception网络的集成在精度和计算成本之间取得了最佳平衡。增加更多网络带来的提升有限而减少网络数量会导致性能下降。感受野影响对于长序列分类任务较大的感受野通过增加网络深度或使用更长的卷积核能显著提升模型性能。但在短序列任务中过大的感受野可能导致性能下降。计算效率InceptionTime的训练时间随序列长度线性增长而HIVE-COTE的时间复杂度为O(N²·T⁴)使其难以应用于大规模数据集。4.2 可视化分析训练过程监控import matplotlib.pyplot as plt def plot_training(history): plt.figure(figsize(12, 4)) plt.subplot(1, 2, 1) plt.plot(history[train_loss], labelTrain Loss) plt.title(Training Loss) plt.xlabel(Epoch) plt.ylabel(Loss) plt.subplot(1, 2, 2) plt.plot(history[val_acc], labelValidation Accuracy) plt.title(Validation Accuracy) plt.xlabel(Epoch) plt.ylabel(Accuracy) plt.tight_layout() plt.show()特征可视化通过t-SNE或PCA降维技术我们可以将InceptionTime学习到的高维特征投影到二维空间直观展示不同类别时间序列的分离情况from sklearn.manifold import TSNE def visualize_features(model, dataloader, device): model.eval() features [] labels [] with torch.no_grad(): for inputs, lbls in dataloader: inputs inputs.to(device) feat model.inception_modules(inputs) feat model.gap(feat).squeeze() features.append(feat.cpu()) labels.append(lbls) features torch.cat(features).numpy() labels torch.cat(labels).numpy() # t-SNE降维 tsne TSNE(n_components2, random_state42) reduced tsne.fit_transform(features) # 绘制散点图 plt.figure(figsize(10, 8)) scatter plt.scatter(reduced[:, 0], reduced[:, 1], clabels, alpha0.6) plt.legend(*scatter.legend_elements(), titleClasses) plt.title(t-SNE Visualization of Learned Features) plt.show()5. 高级技巧与优化策略5.1 迁移学习策略InceptionTime在不同数据集间展现出良好的迁移学习能力。我们可以采用以下策略预训练-微调在大规模时间序列数据集上预训练模型然后在目标数据集上进行微调特征提取固定Inception模块权重仅训练最后的全连接层渐进式解冻从顶层开始逐步解冻和微调模型层def transfer_learning(model, source_loader, target_loader, freeze_layersTrue): if freeze_layers: for param in model.inception_modules.parameters(): param.requires_grad False # 仅训练分类层 optimizer Adam(filter(lambda p: p.requires_grad, model.parameters())) # 训练过程与之前类似 train_model(model, target_loader, ...)5.2 超参数优化通过网格搜索或贝叶斯优化方法我们可以找到特定数据集上的最优超参数组合关键超参数范围参数搜索范围影响Inception模块数量3-9模型深度和感受野初始filter数量16-64模型容量Bottleneck维度16-64计算效率学习率1e-4到1e-3收敛速度和稳定性Batch Size32-128内存使用和梯度估计from sklearn.model_selection import ParameterGrid param_grid { num_modules: [4, 6, 8], filters: [32, 64], reduced_dim: [16, 32], lr: [0.0005, 0.001] } best_acc 0 best_params None for params in ParameterGrid(param_grid): model InceptionTime(input_dim1, num_classesN_CLASSES, **params) trained_model train_model(model, train_loader, val_loader, lrparams[lr]) acc evaluate(trained_model, test_loader, device) if acc best_acc: best_acc acc best_params params print(fBest Accuracy: {best_acc:.4f} with params: {best_params})5.3 模型解释性理解模型决策过程对于许多应用场景至关重要。我们可以使用以下方法增强InceptionTime的解释性梯度类激活图Grad-CAM可视化时间序列中对分类决策最重要的区域特征重要性分析分析不同时间尺度特征对最终预测的贡献度原型分析通过反卷积找到最能激活特定神经元的输入模式def grad_cam(model, input_tensor, target_class, device): model.eval() input_tensor input_tensor.to(device).requires_grad_() # 获取最后一个Inception模块的输出 features model.inception_modules(input_tensor.unsqueeze(0)) # 获取目标类别的梯度 output model.fc(model.gap(features).squeeze()) output[:, target_class].backward() # 计算权重 gradients input_tensor.grad pooled_gradients torch.mean(gradients, dim[0, 2]) # 加权特征图 features features.squeeze(0) for i in range(features.shape[0]): features[i, :] * pooled_gradients[i] heatmap torch.mean(features, dim0).detach().cpu() heatmap np.maximum(heatmap, 0) heatmap / torch.max(heatmap) return heatmap.numpy()