很多货色,只有在了解了外部原理和运作机制后,能力更好地改良和加强。然而有些货色,生来就是「不可了解」的,例如卷积神经网络(CNN)。那么该如何进一步欠缺它?
CNN 在图像分类与指标检测等理论工作当中,领有相当杰出的理论体现,也因而被引入多种利用场景当中,包含在主动驾驶畛域检测街道上的交通标志与物体、在医疗保健畛域精确对基于图像的数据异样进行分类、以及在批发畛域进行库存治理等等。
然而,CNN 的运作机制如同黑匣子,如果无奈了解预测的推理过程,咱们很可能在应用时遭逢问题。同样的,在模型部署实现之后,与专门用于模型训练的数据相比,用于推理的数据可能遵循齐全不同的数据分布。这种景象通常被称为数据漂移(Data drift),有可能导致模型预测谬误。在这种状况下,了解并解释导致模型预测谬误的起因就成了冲出迷雾的惟一心愿。
类激活映射(Class activation maps)与显著性映射(Saliency maps)等技术办法可能帮忙咱们直观查看 CNN 模型如何做出决策。这些图体现为热图模式,可能提醒图像素材当中决定预测后果的要害局部。以下示例来自德国交通标志数据集:左侧图像作为通过优化的 ResNet 模型的输出素材,模型预测后果为该图属于类别 25(路线施工)。右图所示为笼罩有热图的输出图像,其中红色示意与类别 25 预测论断相关度最高的像素,越偏蓝则代表相关度越低。
如果模型做出谬误的预测且无奈给出明确起因,这时咱们就须要对 CNN 决策进行可视化。这种办法还能帮忙大家确定是否须要为训练数据集增加更具代表性的样本,或者判断数据集中是否存在偏差。例如,如果一套物体检测模型负责查找道路交通中的障碍物,但应用的训练数据集仅涵盖冬季周期内的采集样本,那么因为模型从未见过被冰雪笼罩的物体,因而可能无奈在夏季场景下带来良好的推理后果。
在本文中,咱们将部署一套用于交通标志分类的模型,并设置 Amazon SageMaker Model Monitor 以自动检测与预期不符的模型行为,例如始终较低的预测得分或者对某些图像类别的适度预测。当 Model Monitor 发现问题时,咱们将应用 Amazon SageMaker Debugger 获取对于已部署模型的直观阐明。大家能够更新推理端点,通过在推理期间发送张量,并应用这些张量计算出显著性映射。要重现本文中波及的各种步骤与后果,请将 amazon-sagemaker-analyze-model-predictions repo 克隆至咱们本人的 Amazon SageMaker notebook 实例或 Amazon SageMaker Studio 当中,而后运行该 Notebook。
定义一个 SageMaker 模型
本文将应用经过训练的 ResNet18 模型,这套模型应用德国交通标志数据集 [2] 以辨别 43 种交通标志。当给定一幅输出图像时,该模型将输入不同图像类别的对应概率。每个类别对应一种不同的交通标志类型。咱们曾经对模型进行了调优,并将其权重上传至 GitHub repo。
在将模型部署至 Amazon SageMaker 之前,须要首先对模型权重进行归档,并上传至 Amazon Simple Storage Service(Amazon S3)。请在 Jupyter notebook 单元中输出以下代码:
sagemaker_session.upload_data(path=’model.tar.gz’, key_prefix=’model’)
大家能够应用 Amazon SageMaker 托管服务来设置长久化的端点,通过这个端点从模型中获取预测后果。为此,咱们须要定义一个 PyTorch Model 对象,负责从 Amazon S3 门路提取模型归档。定义一个 entry_point file pretrained_model.py 文件,实现 model_fn 与 transform_fn 函数。大家能够在托管期间应用这些函数,保障模型已被正确加载至推理容器当中,且可能正确处理传入申请。具体参见以下代码:
from sagemaker.pytorch.model import PyTorchModel
model = PyTorchModel(model_data = 's3://' + sagemaker_session.default_bucket() + '/model/model.tar.gz',
role = role,
framework_version = '1.5.0',
source_dir='entry_point',
entry_point = 'pretrained_model.py',
py_version='py3')
设置 Model Monitor 并部署模型
Model Monitor 会主动监控生产环境中的机器学习模型,并在检测到数据品质问题时向您收回警报。在这套解决方案中,咱们将捕获端点的输出与输入,并创立监控打算以保障 Model Monitor 可能查看收集到的数据以及相干模型预测后果。咱们应用 DataCaptureConfig API 指定 Model Monitor 在指标 Amazon S3 存储桶上存储模型输出与输入的比例。在以下示例中,采样百分比设置为 50%:
from sagemaker.model_monitor import DataCaptureConfig
data_capture_config = DataCaptureConfig(
enable_capture=True,
sampling_percentage=50,
destination_s3_uri='s3://' + sagemaker_session.default_bucket() + '/endpoint/data_capture')
要将端点部署至 ml.m5.xlarge 实例,请输出以下代码:
predictor = model.deploy(initial_instance_count=1,
instance_type='ml.m5.xlarge',
data_capture_config=data_capture_config)
endpoint_name = predictor.endpoint
对测试图像进行推理
当初,大家能够应用蕴含序列化后的图像输出载荷调用该端点了。端点又将进一步调用 transform_fn 函数,在执行模型推理之前对数据进行预处理。该端点会以整数列表的模式返回图像的预测分类后果,而后编码为 JSON 格局,具体参见以下代码:
#invoke payload
response = runtime.invoke_endpoint(EndpointName=endpoint_name, Body=payload)
response_body = response['Body']
#get results
result = json.loads(response_body.read().decode())
当初,咱们能够对测试图像及其预测出的分类后果进行可视化了。在以下可视化过程中,咱们将交通标志图像作为待预测内容发送至该端点,上方标签则是从端点处接管到的相应预测。下图所示,为端点正确预测了类别 23(湿滑路面)。
下图所示,为端点正确预测了类别 25(路线施工)。
创立一项 Model Monitor 打算
接下来,咱们将演示如何应用 Model Monitor 建设监控打算。Model Monitor 提供一款内置容器用于创立基准,借此计算约束条件与统计数据,例如平均值、分位数以及标准差等等。以此为根底,咱们能够启动监控打算,由该打算定期启动解决作业以查看收集到的数据、将数据与给定的约束条件进行比拟,并可生成违规报告。
在本次用例当中,咱们将创立一个自定义容器,该容器可能执行简略的模型完整性检查,即运行评估脚本、并由该脚本对预测的图像分类进行计数。如果模型对于特定交通标志的辨认比例始终高于其余类别,或者置信度始终较低,则表明模型中存在问题。
例如,对于给定的输出图像,模型将返回基于置信度得分排名的预测类列表。如果前三项预测对应于息息相关的三种类别,且每项预测的置信度得分均低于 50%(例如第一项预测为停车标记,第二项为左转标记,第三项为限速 180km/ h 标记),则三项论断恐怕都不能确切采信。
对于构建自定义容器并将其上传至 Amazon Elastic Container Registry(Amazon ECR)的更多详细信息,请参阅 Notebook。以下代码将创立一个 Model Monitor 对象,咱们能够在其中指定 Docker 镜像在 Amazon ECR 上的地位,以及评估脚本所须要的环境变量。容器的入口点文件即为这套评估脚本。
monitor = ModelMonitor(
role=role,
image_uri='%s.dkr.ecr.us-west-2.amazonaws.com/sagemaker-processing-container:latest' %my_account_id,
instance_count=1,
instance_type='ml.m5.xlarge',
env={'THRESHOLD':'0.5'}
)
接下来,定义一个 Model Monitor 打算并将其附加至端点当中。此打算每小时运行一次自定义容器,具体参见以下代码:
from sagemaker.model_monitor import CronExpressionGenerator
from sagemaker.processing import ProcessingInput, ProcessingOutput
destination = 's3://' + sagemaker_session.default_bucket() + '/endpoint/monitoring_schedule'
processing_output = ProcessingOutput(output_name='model_outputs', source='/opt/ml/processing/outputs', destination=destination)
output = MonitoringOutput(source=processing_output.source, destination=processing_output.destination)
monitor.create_monitoring_schedule(
output=output,
endpoint_input=predictor.endpoint,
schedule_cron_expression=CronExpressionGenerator.hourly())
如前所述,脚本 evaluation.py 会执行简略的模型完整性检查,即对模型预测后果进行计数。Model Monitor 在 Amazon S3 中将模型的输出与输入另存为 JSON 行格局的文件。这些文件将被下载至 /opt/ml/processing/input 的解决容器当中。接下来,大家能够通过 ’captureData'[‘data’] 加载这些预测后果,具体参见以下代码:
for file in files:
content = open(file).read()
for entry in content.split('n'):
prediction = json.loads(entry)['captureData']['endpointOutput']['data']
咱们能够在 CloudWatch 与 SageMaker Studio 中跟踪解决作业的状态。在以下截屏中,SageMaker Studio 显示未发现任何问题。
捕捉意外模型行为
在定义了打算之后,咱们就能够实时监控模型了。若须要验证该设置是否正确捕获意外行为,咱们须要先执行谬误的预测。为此,咱们应用 AdvBox 工具包 [3],其可能在像素层级退出烦扰,保障模型无奈持续辨认出正确的类。这种烦扰也被称为反抗攻打,其中的调整往往无奈被人类所觉察。咱们对几张被正确预测为停车标记的测试图像进行了转换。在以下图像集中,左侧图像为原始图像,两头为反抗图像,右侧为二者之间的差别。原始图像与反抗图像在直观上简直没有任何区别,但反抗图像无奈在推理过程中被正确分类。
下图所示,为另一项判断谬误的交通标志:
在 Model Monitor 打算下一项解决作业时,它会剖析那些曾经捕获并被存储在 Amazon S3 当中的预测后果。该作业会计算预测的图像类别;如果其中某一特定类别有超过 50% 的几率被选定为预测后果,则证实存在问题。因为咱们曾经将反抗图像发送至端点,因而大家当初能够看到图像在类别 14(进行)上产生了异样计数。大家能够在 SageMaker Studio 中跟踪解决作业的状态。以下截屏中,SageMaker Studio 显示在最初一项打算作业中发现了问题。
大家能够从 Amazon CloudWatch Logs 中获取更多详细信息:解决作业将输入一份字典,其中的键为 43 种图像类别之一,而值则为对应计数量。例如,在以下输入当中,端点认为图像类别 9(禁止通行)呈现了 2 次,而类别 14(进行)则呈现了反常的计数。在全副 400 次预测中,端点有 322 次做出了类别 14 的预测,曾经高于 50% 的阈值程度。字典的值也被存储为 CloudWatch 指标,因而大家能够应用 CloudWatch 控制台为指标数据创立展现图表。
Warning: Class 14 ('Stop sign') predicted more than 80 % of the time which is above the threshold
Predicted classes {9: 2, 19: 2, 25: 1, 14: 322, 13: 5, 5: 1, 8: 10, 18: 1, 31: 4, 26: 8, 33: 4, 36: 4, 29: 20, 12: 8, 22: 4, 6: 4}
既然解决作业发现了问题,接下来必定是要进一步理解假相了。察看后面的测试图像,咱们发现原始图像与反抗图像之间没有显著差别。为了更好地了解模型「眼中」的内容,咱们能够采纳论文《Full-Gradient Representation for Neural Network Visualization》[1] 中提到技术。该技术可能对输出特色与两头特色映射(Feature map)的重要性整顿出相应评分。在后文当中,咱们将展现如何配置 Debugger 轻松抽取这些变量(张量),而无需批改模型自身。此外,咱们还将具体介绍如何应用这些张量以计算显著性映射。
创立 Debugger hook 配置
要抽取张量,咱们须要更新之前建设 Amazon SageMaker PyTorch Model 那一步中的预训练模型的 Python 脚本 pretrained_model.py。咱们在 model_fn 当中创立一项 Debugger hook 配置,该 Hook 定义一组正则表达式 include_regex,这些正则表达式匹配的张量将会被收集。在后文中,咱们将具体介绍如何计算显著性映射。此项计算须要应用中间层(例如 BatchNorm 以及下采样层)及模型输出的偏差与梯度。要获取张量,请指定以下正则表达式:
‘.bn|.bias|.downsample|.ResNet_input|.*image’
将张量存储在 Amazon SageMaker 默认存储桶当中,具体请参见以下代码:
def model_fn(model_dir):
#load model
model = resnet.resnet18()
model.load_state_dict(torch.load(model_dir))
model.eval()
#hook configuration
save_config = smd.SaveConfig(mode_save_configs={smd.modes.PREDICT: smd.SaveConfigMode(save_interval=1)
})
hook = Hook("s3://" + sagemaker_session.default_bucket() + "tensors",
save_config=save_config,
include_regex='.*bn|.*bias|.*downsample|.*ResNet_input|.*image' )
#register hook
hook.register_module(model)
#set mode
hook.set_mode(modes.PREDICT)
return model
应用新的入口点脚本 pretrained_model_with_debugger_hook.py,创立一个新的 PyTorch 模型:
model = PyTorchModel(model_data = 's3://' + sagemaker_session.default_bucket() + '/model/model.tar.gz',
role = role,
framework_version = '1.3.1',
source_dir='code',
entry_point = 'pretrained_model_with_debugger_hook.py',
py_version='py3')
应用新的 PyTorch model 对象更新现有端点,该对象应用通过批改、带有 Debugger hook 的模型脚本:
predictor = model.deploy(
instance_type = 'ml.m5.xlarge',
initial_instance_count=1,
endpoint_name=endpoint_name,
data_capture_config=data_capture_config,
update_endpoint=True)
当初,每次做出推理申请时,端点都会记录张量并将后果上传至 Amazon S3。当初,咱们能够计算显著性映射,并从模型中取得直观的解释。
应用 Debugger 剖析不正确预测
分类模型的输入通常为介于 0 和 1 之间的概率数组,其中各个条目对应于数据集中的标签。例如在 MNIST(10 个类别)的状况下,模型可能会对图像为数字 8 的输出预测为:[0.08, 0, 0, 0, 0, 0, 0.12, 0, 0.5, 0.3],示意图像被预测为 0 的概率为 8%,6 的概率为 12%,8 的概率为 50%,9 的概率为 30%。要生成显著性映射,咱们须要抉择概率最高的类别(在本用例中,天然就是 8),而后将得分映射回网络中的原有图层,借此辨认做出这项预测的重要神经元。CNN 由多个层组成,因而各个两头值的重要性得分将体现如何计算各个值对于以后预测后果的奉献。
大家能够将模型输出的预测后果梯度与输出进行比拟,借此确定重要性得分。梯度代表着在输出变更时,输入会对应产生怎么水平的变动。要记录后果,请在层输入上注册一个反向 Hook,并在推理过程中触发反向调用。咱们曾经配置了 Debugger hook 以捕获相干的张量。
在更新端点并执行一些推理申请之后,大家能够创立一个 trial 对象,借此拜访、查问并过滤 Debugger 保留的数据。具体请参见以下代码:
from smdebug.trials import create_trial
trial = create_trial('s3://' + sagemaker_session.default_bucket() + '/endpoint/tensors')
应用 Debugger,咱们能够通过 trial.tensor().value() 拜访数据。例如,要获取第一条推理申请中第一个 BatchNorm 层的偏差张量,请输出以下代码:
trial.tensor('ResNet_bn1.bias').value(step_num=0, mode=modes.PREDICT).
函数 trial.steps(mode=modes.PREDICT) 会返回可用的步数,这里的步数对应于已记录的推理申请数。
在以下步骤中,咱们将基于 FullGrad 办法计算显著性映射。这种办法将把输出梯度与特色层级的偏差梯度聚合起来。
计算隐性偏差
在 FullGrad 办法中,ResNet18 的 BatchNorm 层会引入隐性偏差。大家能够通过获取运行平均值、方差与层权重的形式来计算隐性偏差,具体参见以下代码:
weight = trial.tensor(weight_name).value(step_num=step, mode=modes.PREDICT)
running_var = trial.tensor(running_var_name).value(step_num=step, mode=modes.PREDICT)
running_mean = trial.tensor(running_mean_name).value(step_num=step, mode=modes.PREDICT)
implicit_bias = - running_mean / np.sqrt(running_var) * weight
梯度偏差相乘
偏差是指显性与隐性偏差的总和。大家能够获取特色映射的输入梯度,并计算偏差与梯度的乘积,具体参见以下代码:
gradient = trial.tensor(gradient_name).value(step_num=step, mode=modes.PREDICT)
bias = trial.tensor(bias_name).value(step_num=step, mode=modes.PREDICT)
bias = bias + implicit_bias
bias_gradient = normalize(np.abs(bias * gradient))
插值与聚合
中间层的维度通常与输出图像不同,因而咱们须要对其进行插值。大家能够针对所有偏差梯度执行插值操作,并汇总相应后果。其总和即为咱们以热图模式叠加在原始输出图像上的显著性映射,具体参见以下代码:
for channel in range(bias_gradient.shape[1]):
interpolated = scipy.ndimage.zoom(bias_gradient[0,channel,:,:], image_size/bias_gradient.shape[2], order=1)
saliency_map += interpolated
后果
在本节中,咱们引入了一些反抗图像示例,模型将这些图像识别为进行标记。右侧图像显示的是模型输出图像与显著性映射的叠加后果。红色代表在模型预测中影响最大的局部,同时也很可能代表着像素烦扰所处的地位。能够看到,在烦扰影响之下,模型不再能正确思考到相干的对象特色,而且提供的大多数预测的置信度得分也很低。
为了进行比拟,咱们还应用原始(非反抗)图像进行了推理。在以下图像集中,左侧图像为类别「进行」所对应的反抗图像与显著性映射。右侧图像则为正确类判断所对应的原始输出图像(非反抗图像)与显著性映射。在非反抗图像当中,模型显著仅关注相干的对象特色,因而更有可能做出正确的图像类别预测。而在解决反抗图像时,模型思考到相干对象之外的泛滥其余特色,而这显著是由随机像素烦扰所引起。
总结
本文展现了如何应用 Amazon SageMaker Model Monitor 与 Amazon SageMaker Debugger 自动检测意外模型行为,并从 CNN 中获取直观解释。对于更多详细信息,请参阅 GitHub repo。
参考文献
[1] Suraj Srinivas, Francois Fleuret,《神经网络可视化的全梯度示意》(Full-gradient representation for neural network visualization), Advances in Neural Information Processing Systems (NeurIPS), 2019 年
[2] Johannes Stallkamp, Marc Schlipsing, Jan Salmen, Christian Igel,《德国交通标志辨认基准:多类分类比赛》(The German traffic sign recognition benchmark: A multi-class classification competition,)2011 年国内神经网络联结会议,2011 年
[3] Dou Goodman, Hao Xin, Wang Yang, Wu Yuesheng, Xiong Junfeng, Zhang Huan,《Advbox:一款用于生成反抗示例以烦扰神经网络判断的工具箱》(Advbox: a toolbox to generate adversarial examples that fool neural networks)