不仅仅是标签:使用 ResNet-50 和 Explainable AI(Grad-CAM)构建皮肤病变分类器
Source: Dev.to
介绍
你是否曾在观看医学 AI 演示时想过,“当然,它说是皮疹,但模型到底在看什么?” 在 计算机视觉 和 医学 AI 领域,黑箱 问题不仅是技术障碍——更是信任障碍。
在构建皮肤病变筛查工具时,单纯的百分比得分并不足够。要打造真正有用的工具,我们需要 可解释 AI(XAI)。在本指南中,我们将:
- 使用 PyTorch 和 FastAI 构建深度学习流水线,以对皮肤疾病进行分类。
- 实现 Grad‑CAM,生成热图,突出显示哪些特征(纹理、颜色、边界)影响了模型的决策。
无论你对 深度学习、健康科技感兴趣,还是仅仅想让你的模型更透明,本教程都涵盖了完整的工程实现。
架构
我们的系统遵循经典的客户端‑服务器模型,并添加了可解释性层。我们使用经过微调的ResNet‑50进行推理,并使用 React Native 前端提供用户体验。
graph TD
A[User Takes Photo] --> B(React Native App)
B --> C{FastAPI Backend}
C --> D[ResNet‑50 Classifier]
D --> E[Inference Result]
D --> F[Grad‑CAM Hook]
F --> G[Heatmap Generation]
G --> H[Overlay Image]
H --> I[Result + Visualization]
E --> I
I --> B
前置条件
| 要求 | 细节 |
|---|---|
| FastAI / PyTorch | 模型训练和微调 |
| Grad‑CAM | 从最后的卷积层提取梯度 |
| React Native | 跨平台移动界面 |
| Dataset | 例如 HAM10000(Human‑Against‑Machine,1 万张训练图像) |
第 1 步:使用 FastAI 微调 ResNet‑50
FastAI 使 迁移学习 变得极其高效。下面是一段最小化脚本,用于在皮肤病变图像上微调预训练的 ResNet‑50。
from fastai.vision.all import *
# Load data – assumes images are organized in folders by label
path = Path('./skin_lesion_data')
dls = ImageDataLoaders.from_folder(
path,
valid_pct=0.2,
item_tfms=Resize(224)
)
# Initialize Learner with ResNet‑50
learn = vision_learner(dls, resnet50, metrics=accuracy)
# Find optimal learning rate and train
learn.fine_tune(5, base_lr=3e-3)
# Export for production
learn.export('skin_classifier.pkl')
第2步:实现 Grad‑CAM 以进行可解释性
Grad‑CAM(Gradient‑weighted Class Activation Mapping)利用流入最后一个卷积层的梯度来生成定位图。
import torch
import numpy as np
class GradCAM:
def __init__(self, model, target_layer):
self.model = model
self.target_layer = target_layer
self.gradients = None
self.activations = None
# Register hooks
self.target_layer.register_forward_hook(self._save_activation)
self.target_layer.register_full_backward_hook(self._save_gradient)
def _save_activation(self, module, input, output):
self.activations = output
def _save_gradient(self, module, grad_input, grad_output):
self.gradients = grad_output[0]
def generate_heatmap(self, input_tensor, category_idx):
# Forward pass
output = self.model(input_tensor)
self.model.zero_grad()
# Backward pass for the specific category
loss = output[0, category_idx]
loss.backward()
# Weight the activations by the gradients
weights = torch.mean(self.gradients, dim=(2, 3), keepdim=True)
heatmap = torch.sum(weights * self.activations, dim=1).squeeze()
# ReLU and normalize
heatmap = np.maximum(heatmap.detach().cpu().numpy(), 0)
heatmap /= np.max(heatmap)
return heatmap
注意: 将此功能集成到你的 API 中,以同时返回诊断结果(例如 “Melanocytic nevi”)和可视化热图图像。
扩展到生产环境
虽然原型是一个很好的起点,但部署医疗级 AI 需要:
- 严谨的测试与验证
- 数据隐私合规(HIPAA、GDPR 等)
- 稳健的 MLOps 流水线
欲获取生产就绪的示例、高级计算机视觉模式以及 AI 安全的深入探讨,请查看 WellAlly Tech Blog 的技术资源。
第3步:前端可视化(React Native)
在移动端,我们显示原始图像,并允许用户(或临床医生)切换热图叠加层。
import React, { useState } from 'react';
import { View, Image, Button, Text } from 'react-native';
const ResultScreen = ({ route }) => {
const { originalUri, heatmapUri, prediction } = route.params;
const [showHeatmap, setShowHeatmap] = useState(false);
return (
<View>
<Text>Result: {prediction}</Text>
<Image source={{ uri: showHeatmap ? heatmapUri : originalUri }} style={{ width: 300, height: 300 }} />
<Button
title={showHeatmap ? "Hide Heatmap" : "Show Heatmap"}
onPress={() => setShowHeatmap(!showHeatmap)}
/>
</View>
);
};
export default ResultScreen;
import React, { useState } from "react";
import { View, Switch, Text } from "react-native";
const HeatmapToggle = () => {
const [showHeatmap, setShowHeatmap] = useState(false);
return (
<View>
<Text>Show Grad‑CAM Heatmap (Logic)</Text>
<Switch
value={showHeatmap}
onValueChange={() => setShowHeatmap(!showHeatmap)}
/>
</View>
);
};
export default HeatmapToggle;
全屏控制
- 进入全屏模式
- 退出全屏模式
结论:弥合差距
通过将 FastAI 用于快速开发与 Grad‑CAM 用于透明性相结合,我们将一个简单的分类器转变为强大的诊断辅助工具。该设置不仅提供答案,还提供原因。
关键要点
- 迁移学习(ResNet‑50)可节省数周的训练时间。
- 在医学等高风险领域,可解释性是不可妥协的。
- 混合技术栈(Python 后端 + React Native 前端)为 AI 产品提供了最佳的开发者体验。
你对 AI 可解释性有什么看法?如果 AI 能通过热图向你展示它的“思考过程”,你会更信任它吗?欢迎在下方评论区讨论!
如果你喜欢本教程,别忘了 ❤️ 和 🔖!想了解更多高级 AI 实施策略,请访问 WellAlly Blog。
