Google Research Activation Clustering:基于无监督聚类的深度神经网络可解释性实战指南
【免费下载链接】google-researchGoogle Research项目地址: https://gitcode.com/gh_mirrors/go/google-research
导读
本文围绕 google-research 仓库中的activation_clustering项目,讲解如何利用"激活聚类"(Activation Clustering)技术,对已训练好的深度分类模型进行解释:通过无监督聚类模型学习网络中间层激活的潜在结构,进而得到可替代原模型的白盒"代理模型"(surrogate model),并据此检索与测试样本相似的训练样本、提炼网络内部"概念"(concept)。读完本文,你将掌握该模型的完整安装启动流程、训练与可视化配置方法,以及其核心实现原理。
项目定位与核心思想
activation_clustering是论文 Explaining Deep Neural Networks using Unsupervised Clustering(arXiv:2007.07477)的官方实现。其核心思想可概括为:
- 深度网络分类模型可以视为"特征提取器 + 线性分类头"的组合,其中间层激活(activation)编码了从低级视觉特征到高级语义特征的多层次信息;
- 对每个指定层的激活分别执行无监督聚类(本项目使用 Deep Embedding Clustering,即 DEC),使激活空间被划分为若干簇;
- 每个簇可视为该层网络学习到的"概念",聚类结果再与类别标签建立经验后验概率映射,从而构成一个可解释的代理模型。
从仓库结构看,activation_clustering目录下包含三个主要部分:
- 核心实现:
ac_model.py(ACModel 类)、utils.py(激活提取与可视化工具)、__init__.py; - CIFAR-10 示例:
train.ipynb(训练代理模型)、similar_images_concepts.ipynb(相似样本与概念可视化); - Dockerfile 与 setup.py:一键构建含示例模型与数据的环境。
安装与运行:Docker 一键启动 Jupyter
仓库 README 给出了完整的 5 步上手流程,全程基于 Docker,包含示例模型与数据下载,无需手工配置 Python 环境。
步骤 1:克隆仓库
git clone https://github.com/google-research/google-research.git --depth=1使用--depth=1只拉取最新提交,可显著减小克隆体积;这是官方 README 推荐的用法。
步骤 2:构建 Docker 镜像
cd google-research/activation_clustering && docker build -t activation_clustering .结合 Dockerfile 可以看到该镜像构建时自动完成的关键工作:
- 基于
python:3.6基础镜像,并安装git与 Google Cloud SDK(用于gsutil/gcloud storage下载数据); - 克隆仓库后,从
gs://cloud-samples-data/research/activation_clustering/下载两类数据:work_dir(预训练好的激活聚类模型工作目录,供similar_images_concepts.ipynb直接使用);model.h5(在 CIFAR-10 上训练好的 ResNet 基线分类模型);
- 执行
pip install -e .安装本项目及其依赖; - 预下载 CIFAR-10 数据集(通过
tensorflow_datasets)并缓存进镜像。
依赖清单在 setup.py 中可查:scikit-learn==0.19.2、tensorflow-gpu==2.1.0、tensorflow-datasets==2.1.0、matplotlib==2.2.4、scipy==1.2.2、PyYaml==5.3、jupyter==1.0.0,以及从 GitHub 指定 commit 安装的dec_da(DEC-DA 聚类库,提供ConvIDEC卷积聚类模型)。注意:依赖锁定在较老的 TensorFlow 2.1 与 Python 3.6 时代,因此官方以 Docker 作为推荐的运行方式,以隔离版本冲突。
步骤 3:启动容器内 Jupyter 服务
docker run -it -p 8888:8888 activation_clustering镜像的ENTRYPOINT为:
jupyter notebook --ip=0.0.0.0 --no-browser --allow-root --notebook-dir=google-research/activation_clustering/examples/cifar10即容器启动后直接在examples/cifar10/目录下开启 Jupyter Notebook,监听所有网卡,并通过-p 8888:8888将 8888 端口映射到宿主机。
步骤 4:浏览器访问
在浏览器中打开docker run输出的地址,形如:
http://127.0.0.1:8888/?token=1234abcd...token 由 Jupyter 启动时自动生成并打印在终端中,注意完整复制。
步骤 5:跟随示例 Notebook
按 examples/cifar10/ 下的两个 Notebook 依次操作:先用train.ipynb从基线模型训练激活聚类模型,再用similar_images_concepts.ipynb做相似图像检索与概念可视化,具体用法见下文。
训练激活聚类模型:train.ipynb 详解
examples/cifar10/train.ipynb 展示了如何从已训练好的 Keras 基线模型(CIFAR-10 ResNet,即model.h5)出发训练激活聚类模型。
数据预处理与激活缓存
Notebook 先定义与基线模型训练一致的预处理函数(图像归一化到[0,1]),随后加载基线模型:
model = tf.keras.models.load_model('model.h5')关键一步是缓存激活:对训练集与测试集分别调用cache_activations,把指定层的激活写入磁盘,便于后续迭代训练而不必反复前向传播:
batch_size = 500 ds = input_fn(batch_size, train_ds) new_acm.cache_activations(ds, tag='train')在源码 ac_model.py 中,cache_activations将激活写入{work_dir}/activations/activations_{tag}.npz,每个文件以npz格式保存以激活名为 key 的 numpy 数组字典;之后用load_activations_dict读取:
activations_dict = new_acm.load_activations_dict( activations_filename=work_dir + '/activations/activations_train.npz')聚类配置与模型构建
聚类配置是一组(激活层名, 配置字典)对。Notebook 中的完整示例:
clustering_config = [ ('activation', {'n_clusters': 15}), ('activation_18', {'n_clusters': 15}), ('activation_36', {'n_clusters': 15}), ('activation_54', {'n_clusters': 15}) ]其中第一项是基线模型中的层名(activation、activation_18、activation_36、activation_54是 ResNet 各阶段的激活层),其输出激活将被聚类;第二项中的n_clusters指定该层聚类的簇数(即概念数)。Notebook 也给出了一段供调试/测试用的精简配置注释:
# clustering_config = [ # ('activation', {'n_clusters': 10}), # ('activation_54', {'n_clusters': 10, 'filters': [16, 16, 16, 8]}) # ]创建 ACModel 并构建聚类模型:
new_acm = ac_model.ACModel(model, clustering_config, work_dir=work_dir) new_acm.build_clustering_models()从源码看,build_clustering_models(ac_model.py)会为每个激活层实例化一个ConvIDEC(来自 dec_da 库的卷积 DEC 模型),自动读取该层激活的input_shape,并用 Adam 优化器、loss=['kld', 'mse']、loss_weights=[0.1, 1.0]编译——其中kld对应 DEC 的 KL 散度聚类损失,mse对应自编码器重构损失。
训练循环
epochs = 15 maxiter = 980 new_acm.fit(activations_dict=activations_dict, epochs=epochs, maxiter=maxiter)fit(ac_model.py)依次完成三件事:
- 拟合各层聚类模型:对每个激活执行 DEC 的两阶段训练——先用自编码器以
epochs个 epoch 预训练(pretrain),再以maxiter次迭代做聚类精调(fit),batch_size 固定为 32,模型保存到{work_dir}/clustering_{activation_name}/; - 拟合经验后验概率:将训练样本的簇分配与真实类别做计数统计并归一化,得到
(n_clusters, n_classes)的经验后验矩阵,存入{work_dir}/empirical_posteriors/; - 缓存训练嵌入:用训练好的聚类编码器将所有训练样本映射为嵌入向量,保存为
{work_dir}/training_embeddings.npz,供后续最近邻查询使用。
Notebook 注释也提示:epochs=2, maxiter=280可用于缩短训练时间做调试;该实现基于 DEC,dec_da 库中还有其他参数,可通过修改activation_clustering库暴露后配置。
相似样本与概念可视化:similar_images_concepts.ipynb 详解
examples/cifar10/similar_images_concepts.ipynb 直接复用镜像中预下载的work_dir恢复已训练模型:
acm = ac_model.ACModel.restore('work_dir')restore(ac_model.py)会按顺序恢复:clustering_config.yaml配置 →baseline_model.h5(及可选的activation_model.h5)→ 各层聚类模型权重model_final.h5→ 经验后验empirical_posteriors.joblib→ 训练嵌入training_embeddings.npz。
作为代理模型评估
Notebook 首先验证激活聚类模型可作为基线模型的代理:
# 代理模型自身精度 print('surrogate model accuracy: ', acm.evaluate(features=test_features, y=test_labels)) # 保真度:代理模型与基线模型预测的一致性 baseline_labels = np.argmax(acm.baseline_model.predict(test_features), axis=-1) print('fidelity: ', acm.evaluate(features=test_features, y=baseline_labels))源码中evaluate通过predict得到代理模型预测的类别,再与y计算准确率:当y为真实标签时得到代理模型精度;当y为基线模型预测时得到保真度(fidelity)。predict_proba的实现(ac_model.py)说明其原理:将各层簇分配的软分数s与该层经验后验矩阵h做矩阵乘法得到该层对类别的概率贡献,再按权重w加权平均。
查询相似训练样本
Notebook 随机抽取 10 个测试样本,用query检索嵌入空间中最近的训练样本:
equal = [1.0, 1.0, 1.0, 1.0] low = [2.0, 1.0, 0.0, 0.0] high = [0.0, 0.0, 1.0, 2.0] ind = acm.query(features=test_feat, weights=equal) train_image_arrays_list = train_features[ind] utils.visualize_similar( test_image_arrays=test_feat, train_image_arrays_list=train_image_arrays_list, test_labels=test_labels[test_indices].tolist(), train_labels=train_labels[ind].tolist())weights列表与clustering_config一一对应,控制各层嵌入在距离计算中的相对权重。源码query(ac_model.py)先对各层提取测试嵌入,再用scipy.spatial.distance.cdist计算与训练嵌入的欧氏距离矩阵,按权重求和后取最近的前k个(默认k=10)训练样本索引。示例表明:偏重浅层(低权重给高层)会得到视觉上更相似的图像,偏重深层则更强调语义相似。
Notebook 还对比了"仅用最后一层原始激活距离"检索的效果,结论是它无法捕捉低级视觉特征——这正是激活聚类在嵌入空间中做最近邻的优势所在。
提取与可视化概念
将每个聚类簇视作一个"概念",用距各簇质心最近的训练图像代表该概念:
concept_indices = acm.concept_indices() activation_index = 0 print('Concepts based on {}'.format(acm.activation_names[activation_index])) train_image_arrays_list = train_features[concept_indices[activation_index]] utils.visualize_concepts(train_image_arrays_list)concept_indices(ac_model.py)先从各聚类模型的clustering层取出簇质心(get_centroids_list),再对每个质心返回训练嵌入中最近的前k个样本索引,形状为(n_clusters, k)。Notebook 依次可视化第 0、2、3 个激活层的概念,并明确指出:越早的激活层捕捉低级视觉特征,越深的层则对应更高级的语义概念。可视化函数(visualize_similar、visualize_concepts)实现在 utils.py,后者会为每行图片标注 "Top N training images of concept i"。
核心参数与自定义说明
综合源码与 Notebook,可自定义的关键参数如下:
| 参数 | 所属位置 | 含义与取值 | 默认值 |
|---|---|---|---|
activation_names | clustering_config | 基线模型待聚类激活的层名列表 | 无(必填) |
n_clusters | clustering_config每项 | 该层激活划分的簇/概念数 | 无(必填) |
filters | clustering_config每项(可选) | 内部卷积自编码器各层滤波器数与嵌入维度,必须为长度为 4 的正整数列表,最后一位为嵌入维度;违反时抛出NotImplementedError | [32, 64, 128, 20] |
work_dir | ACModel构造参数 | 缓存激活、聚类模型、经验后验与训练嵌入的工作目录 | /tmp/acmodel |
restore | ACModel构造参数 | 是否从work_dir恢复模型 | False |
activation_model | ACModel构造参数 | 用于提取激活的模型,缺省时即基线模型 | baseline_model |
epochs | fit | DEC 自编码器预训练 epoch 数 | 3 |
maxiter | fit | DEC 聚类精调的最大迭代次数 | 280 |
weights | query/predict_proba | 各激活层距离/概率的加权系数,无需归一化 | 全1.0(等权) |
k | query/concept_indices | 返回最近邻样本数量 | 10 |
工作原理与适用限制
从实现结构看,整个激活聚类模型是一条"可解释代理流水线":
- 激活提取:
utils.get_activations通过tf.keras.backend.function将模型输入占位符映射到指定层的输出张量,按 1024 的 batch 分批前向计算(utils.py); - 聚类建模:每个激活层对应一个
ConvIDEC(卷积 DEC),自编码器负责降维嵌入,聚类层负责将嵌入划分到n_clusters个簇;build_clustering_models还会用batched_predict_on_batch(batch_size=1024)monkey-patch 各模型的predict方法,规避大数组推理的内存压力; - 经验后验:簇分配经训练标签统计归一化后,构成从簇到类别的概率映射(ac_model.py);
- 推理与解释:
predict_proba输出代理模型的类别概率;query/concept_indices在训练嵌入空间中做加权欧氏最近邻,分别回答"与某测试样本相似的训练样本有哪些"与"某概念的代表图像是什么"。
需要注意的是:本项目以 TensorFlow 2.1、Python 3.6 及固定版本依赖运行,且示例仅覆盖 CIFAR-10 图像分类场景,迁移到其他数据集/模型时需要自行准备基线模型与层名清单;filters必须为 4 个正整数(最后一个为嵌入维度),这是 dec_da 库的硬性约束。
结语
activation_clustering提供了一个完整的"无监督聚类解释深度网络"参考实现:从 Docker 一键环境、CIFAR-10 端到端训练,到相似样本检索与概念可视化,再到ACModel/utils的源码级机制,均可直接在 examples/cifar10/ 的 Notebook 中复现。对于希望在图像分类模型上获得白盒式解释、检索训练数据证据或提炼概念原型的开发者,这套实现是值得直接上手与二次开发的基线。
【免费下载链接】google-researchGoogle Research项目地址: https://gitcode.com/gh_mirrors/go/google-research
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考