ConvNeXt特征图降维可视化:t-SNE与UMAP方法全解析

ConvNeXt特征图降维可视化:t-SNE与UMAP方法全解析

【免费下载链接】ConvNeXt Code release for ConvNeXt model 【免费下载链接】ConvNeXt 项目地址: https://gitcode.com/gh_mirrors/co/ConvNeXt

1. 特征可视化的痛点与解决方案

你是否曾困惑于深度神经网络(Deep Neural Network, DNN)中间层输出的高维特征图(Feature Map)究竟代表什么?当输入一张图像经过ConvNeXt网络的stem层处理后,会生成96×56×56的三维张量(以Tiny模型为例),直接可视化这种高维数据如同雾里看花。本文将通过t-SNE(t-Distributed Stochastic Neighbor Embedding)与UMAP(Uniform Manifold Approximation and Projection)两种主流降维算法,结合PyTorch Hooks技术,手把手教你提取并可视化ConvNeXt各层特征,让神经网络的"黑箱"变得可解释。

读完本文你将掌握:

  • ConvNeXt特征图提取的三种方法(前向钩子/修改forward/特征层切片)
  • t-SNE与UMAP算法的参数调优指南( perplexity/low_memory设置)
  • 10+可视化代码模板(含Matplotlib/Plotly实现)
  • 特征聚类质量评估指标(Silhouette Score/Davies-Bouldin Index)

2. 技术原理与ConvNeXt特征结构

2.1 降维算法工作原理对比

算法核心思想时间复杂度空间复杂度聚类效果
t-SNE基于概率分布的非线性降维,保留局部结构O(N²)O(N²)局部结构清晰
UMAP基于流形学习和拓扑数据分析,保留全局结构O(N log N)O(N)全局结构完整

mermaid

2.2 ConvNeXt特征提取关键点

ConvNeXt网络包含4个Stage,每个Stage输出特征图尺寸减半、通道数翻倍:

  • 空间维度:224→56→28→14→7(步长为2的卷积下采样)
  • 通道维度:3→96→192→384→768(通道数指数增长)
  • 特征粒度:浅层(Stage 1-2)保留边缘/纹理信息,深层(Stage 3-4)抽象语义概念

3. 特征图提取实战

3.1 环境准备与模型加载

import torch
import torchvision.transforms as T
from models.convnext import convnext_tiny
import matplotlib.pyplot as plt
from sklearn.manifold import TSNE
from umap import UMAP
import numpy as np
from PIL import Image

# 加载预训练模型
model = convnext_tiny(pretrained=True)
model.eval()

# 图像预处理
transform = T.Compose([
    T.Resize(256),
    T.CenterCrop(224),
    T.ToTensor(),
    T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])

3.2 基于Forward Hook的特征提取

# 存储中间层特征
features = {}

def get_features(name):
    def hook(model, input, output):
        # 输出形状: (B, C, H, W),展平为(B, C, H*W)
        features[name] = output.flatten(2).detach().cpu().numpy()
    return hook

# 注册钩子到指定层
model.downsample_layers[0].register_forward_hook(get_features('stem'))  # Stem层
model.stages[2].register_forward_hook(get_features('stage3'))           # Stage 3输出

# 前向传播
img = Image.open("test_image.jpg").convert("RGB")
x = transform(img).unsqueeze(0)  # 添加批次维度
with torch.no_grad():
    _ = model(x)

# 提取特征: (1, C, H*W) → (H*W, C)
stem_feats = features['stem'][0].transpose(1, 0)    # 56×56=3136个特征点
stage3_feats = features['stage3'][0].transpose(1, 0)  # 14×14=196个特征点

3.3 特征降维实现

# t-SNE降维 (推荐样本数<5000)
tsne = TSNE(
    n_components=2,          # 降维到2D
    perplexity=30,           # 困惑度,通常5-50
    random_state=42,
    n_iter=1000,             # 迭代次数
    verbose=1
)
tsne_results = tsne.fit_transform(stage3_feats)  # 196×2

# UMAP降维 (推荐样本数>1000)
umap = UMAP(
    n_components=2,
    n_neighbors=15,          # 邻域大小,影响聚类粒度
    min_dist=0.1,            # 最小距离,控制点间距
    metric='cosine',         # 距离度量
    random_state=42
)
umap_results = umap.fit_transform(stem_feats)    # 3136×2

4. 可视化方案与代码实现

4.1 基础散点图可视化

def plot_2d_features(features, title, save_path=None):
    plt.figure(figsize=(10, 8))
    scatter = plt.scatter(
        features[:, 0], 
        features[:, 1],
        c=np.arange(features.shape[0]),  # 按位置编码颜色
        cmap='viridis', 
        alpha=0.7,
        s=50
    )
    plt.colorbar(scatter, label='Feature Position Index')
    plt.title(title, fontsize=16)
    plt.xlabel('Dimension 1', fontsize=14)
    plt.ylabel('Dimension 2', fontsize=14)
    plt.grid(linestyle='--', alpha=0.5)
    if save_path:
        plt.savefig(save_path, dpi=300, bbox_inches='tight')
    plt.show()

# 可视化Stage 3特征的t-SNE结果
plot_2d_features(tsne_results, "ConvNeXt Stage 3 Features (t-SNE)", "tsne_stage3.png")

4.2 高级交互可视化(Plotly)

import plotly.express as px

fig = px.scatter(
    x=umap_results[:, 0],
    y=umap_results[:, 1],
    color=np.arange(umap_results.shape[0]),
    title="Stem Layer Features (UMAP)",
    labels={"x": "UMAP 1", "y": "UMAP 2"},
    color_continuous_scale=px.colors.sequential.Viridis,
    hover_data={"index": np.arange(umap_results.shape[0])}
)
fig.update_traces(marker=dict(size=8, opacity=0.8))
fig.update_layout(
    plot_bgcolor='white',
    xaxis=dict(showgrid=True, gridcolor='lightgrey'),
    yaxis=dict(showgrid=True, gridcolor='lightgrey')
)
fig.write_html("umap_stem_interactive.html")  # 保存为交互HTML

4.3 不同Stage特征对比

# 提取所有Stage特征
stage_outputs = []
for i in range(4):
    model.stages[i].register_forward_hook(get_features(f'stage{i+1}'))
    
with torch.no_grad():
    _ = model(x)
    
# 降维对比
tsne_comparison = {}
for i in range(4):
    feats = features[f'stage{i+1}'][0].transpose(1, 0)
    tsne_comparison[i+1] = TSNE(n_components=2, perplexity=min(30, feats.shape[0]//2), 
                               random_state=42).fit_transform(feats)

# 4个子图对比
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
axes = axes.flatten()
for i in range(4):
    axes[i].scatter(tsne_comparison[i+1][:,0], tsne_comparison[i+1][:,1], 
                   c=np.arange(tsne_comparison[i+1].shape[0]), cmap='plasma')
    axes[i].set_title(f'Stage {i+1} (Dims: {[96,192,384,768][i]})', fontsize=14)
plt.tight_layout()
plt.savefig("stage_comparison.png", dpi=300)

5. 聚类质量评估与参数调优

5.1 评估指标计算

from sklearn.metrics import silhouette_score, davies_bouldin_score

# 计算轮廓系数 (越接近1越好)
sil_score = silhouette_score(stage3_feats, np.argmax(tsne_results, axis=1))
print(f"Silhouette Score: {sil_score:.4f}")

# 计算Davies-Bouldin指数 (越小越好)
db_score = davies_bouldin_score(stage3_feats, np.argmax(tsne_results, axis=1))
print(f"Davies-Bouldin Index: {db_score:.4f}")

5.2 t-SNE参数调优对比

perplexities = [5, 15, 30, 50]
tsne_tuning = {}
for p in perplexities:
    tsne = TSNE(n_components=2, perplexity=p, random_state=42, verbose=0)
    tsne_tuning[p] = tsne.fit_transform(stage3_feats)

# 绘制参数对比图
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
axes = axes.flatten()
for i, p in enumerate(perplexities):
    axes[i].scatter(tsne_tuning[p][:,0], tsne_tuning[p][:,1], cmap='viridis')
    axes[i].set_title(f'Perplexity={p}', fontsize=14)
plt.tight_layout()

mermaid

6. 高级应用与扩展

6.1 特征图热力图叠加

def visualize_feature_map(feat_map, original_img, channel_idx=0):
    # feat_map shape: (C, H, W)
    img = original_img.resize((feat_map.shape[2], feat_map.shape[1]))
    heatmap = feat_map[channel_idx].detach().cpu().numpy()
    heatmap = (heatmap - heatmap.min()) / (heatmap.max() - heatmap.min() + 1e-8)
    
    plt.figure(figsize=(10, 8))
    plt.imshow(img)
    plt.imshow(heatmap, cmap='jet', alpha=0.5)
    plt.axis('off')
    plt.title(f'Feature Channel {channel_idx} Heatmap', fontsize=14)
    plt.tight_layout()

6.2 大规模特征降维优化

# 针对>10000样本的优化方案
def large_scale_tsne(features, chunk_size=2000):
    """分块处理大规模特征"""
    n_chunks = (features.shape[0] + chunk_size - 1) // chunk_size
    all_results = []
    for i in range(n_chunks):
        start = i * chunk_size
        end = min((i+1)*chunk_size, features.shape[0])
        chunk = features[start:end]
        tsne = TSNE(n_components=2, perplexity=30, verbose=0)
        all_results.append(tsne.fit_transform(chunk))
    return np.vstack(all_results)

7. 总结与最佳实践

  1. 特征选择策略

    • 可视化局部特征:选择Stage 1-2输出(高分辨率)
    • 可视化语义特征:选择Stage 3-4输出(高通道数)
    • 样本量控制:t-SNE建议<5000样本,UMAP可处理>10000样本
  2. 参数调优清单

    • t-SNE: perplexity=10-30(小数据集→小perplexity)
    • UMAP: n_neighbors=10-30,min_dist=0.01-0.5
    • 统一随机种子(random_state=42)确保结果可复现
  3. 常见问题解决

    • 点云重叠:增加min_dist参数或使用UMAP
    • 计算缓慢:启用t-SNE的low_memory=True或UMAP的angular_rp_forest=True
    • 特征模糊:检查是否使用了BatchNorm层(建议关闭推理时的track_running_stats)

通过本文方法,你可以系统地分析ConvNeXt网络的特征学习过程,为模型改进(如注意力机制插入、特征融合策略)提供可视化依据。建议结合TensorBoard的Projector插件进行交互式探索,进一步挖掘特征空间的结构特性。

【免费下载链接】ConvNeXt Code release for ConvNeXt model 【免费下载链接】ConvNeXt 项目地址: https://gitcode.com/gh_mirrors/co/ConvNeXt

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值