Unsupervised Continual Anomaly Detection with Contrastively-learned Prompt
1、Background
无监督异常检测(UAD)专注于在没有先验知识或标记实例的情况下识别数据中的不寻常模式或异常值,仅依赖于“正常”数据的内在分布(Chandola, Banerjee, 和 Kumar 2009)。这种方法在工业制造中特别有用,因为获取标记良好的缺陷数据可能既困难又昂贵。
最近关于 UAD 的研究涉及为不同类别训练不同的模型,这在测试阶段不可避免地依赖于类别身份的知识(Liu et al. 2023b)。此外,迫使不同的模型顺序学习也会导致随着类别增加而沉重的计算负担。
一些其他方法专注于训练一个可以处理多个类别的统一模型,例如 UniAD(You et al. 2022)。在实际生产中,训练是顺序进行的,这使得 UniAD 要求所有数据同时训练变得不切实际。
此外,统一模型仍然缺乏在顺序训练期间持续适应频繁产品变更时保留先前学习知识的能力。灾难性遗忘和计算负担阻碍了 UAD 方法在现实世界场景中的应用。
持续学习(CL)以其解决灾难性遗忘问题而闻名,尤其是在由于隐私原因无法使用先前数据时(Li et al. 2023)。
最近关于持续学习的研究可以根据测试阶段是否需要任务身份进行分类。任务感知方法明确使用任务身份指导学习过程并防止任务间的干扰(Aljundi et al. 2018; Kirkpatrick et al. 2017)。然而,在推理过程中获取任务身份并不总是可能的。因此,任务不可知方法是必要的,也更为普遍。
Aljundi, Kelchtermans, 和 Tuytelaars 逐步修改数据分布以适应在线设置中的各种任务。L2P(Wang et al. 2022)动态学习提示作为任务身份。尽管任务不可知 CL 方法在监督任务中有效,但它们在 UAD 中的有效性尚未得到证明。
在工业中获得大规模异常数据是困难的,因为高生产成功率和隐私问题。因此,探索 CL 在 UAD 中的应用至关重要。到目前为止,除了高斯分布估计器(DNE)(Li et al. 2022)之外,没有已知的努力将 CL 纳入 UAD。然而,DNE 仍然依赖于增强(Li et al. 2021)来提供伪监督,并且不适用于异常分割。DNE 可以被认为是一个持续的二元图像分类方法,而不是持续的异常检测(AD)方法。在实际的工业制造中,准确分割异常区域对于异常标准化量化至关重要。因此,迫切需要一种能够同时执行无监督持续 AD 和分割的方法。
为了解决上述问题,我们提出了一个名为 UCAD 的新颖的无监督持续异常检测框架,它可以顺序地使用单个模型学习检测不同类别的异常,如图 1 所示。UCAD 整合了一个持续提示模块(CPM)以在无监督 AD 中启用 CL,以及一个基于结构的对比学习(SCL)模块以提取各种任务之间的更紧凑的特征。CPM 学习了一个“键提示知识”记忆空间,以存储自动选择的任务查询、任务适应提示和不同类别的“正常”知识。给定一张图像,键会自动选择以检索相应的任务提示。基于提示,图像特征被进一步提取,并与其正常知识进行比较以进行异常检测,类似于 PatchCore(Roth et al. 2022)。
然而,CPM 的性能受到限制,因为冻结的骨干(ViT)无法提供跨各种任务的紧凑特征表示。为了克服这一限制,引入了 SCL 以提取更具优势的特征表示,并通过利用 SAM(Kirillov et al. 2023)的通用分割能力来减少域间差距。有了 SCL,同一结构(分割区域)的特征被拉近,与其他结构的特征被推开。因此,提示对比学习以更好地提取不同任务的特征。
传统分离模型方法与UCAD(Unsupervised Continual Anomaly Detection,无监督持续异常检测)方法之间的比较:
-
分离模型方法(a):
- 在传统的分离模型方法中,每个任务(或类别)都有自己的独立模型。这意味着对于每一个新的异常检测任务,都需要从头开始训练一个新的模型。
- 这种方法的缺点在于,随着任务数量的增加,需要维护和存储的模型数量也会增加,这会导致计算资源和存储资源的需求大幅上升。
- 此外,这种方法无法实现知识在不同任务之间的迁移,每个模型只能处理特定任务的数据,无法泛化到其他任务。
-
UCAD方法(b):
- 相比之下,UCAD方法使用单一模型来处理所有任务,而不需要知道具体任务的身份。这种方法的核心在于利用持续学习和对比学习技术,使得模型能够在学习新任务的同时保留对旧任务的知识。
- 在连续的数据流中,UCAD只需要当前任务的数据集进行训练,并且能够将学到的知识应用到之前的任务上。这意味着模型能够持续地适应新的任务,而不会忘记旧任务的知识。
- 这种方法的优势在于它的灵活性和效率。单一模型可以适应多个任务,减少了模型维护的复杂性和资源消耗。同时,它还能够在新任务上实现更好的泛化能力,因为它能够利用在旧任务上学到的知识。
总的来说,UCAD方法相比于传统分离模型方法的优势,特别是在处理多任务学习、持续学习和无监督异常检测的场景中。UCAD通过单一模型处理所有任务,不仅提高了资源利用效率,还增强了模型的适应性和泛化能力。
2、Method
文献中的Figure 2描述了无监督持续异常检测(UCAD)框架的主要组成部分,包括持续提示模块(CPM)和基于结构的对比学习(SCL)模块,这些模块与SAM(Segment Anything Model)网络集成在一起。
以下是对UCAD框架的解释:
-
持续提示模块(CPM):
- CPM是UCAD框架的核心,负责建立一个高效的键-提示-知识系统。这个系统能够维护训练数据信息,同时减少内存和计算资源的使用。
- 在训练阶段,CPM通过使用最远点采样(FPS)方法来选择代表性的特征作为“键”,这些键代表了不同的任务身份。
- 同时,CPM利用可学习的“提示”来传递任务特定的信息,这些提示被注入到模型中以指导模型对当前任务的学习。
- “知识”则作为模型学习到的正常样本的表示,用于后续的异常检测。
-
基于结构的对比学习(SCL)模块:
- SCL模块利用SAM网络的分割能力来增强特征表示。SAM网络能够为输入图像生成分割图,将图像分割成不同的区域或结构。
- 通过对比学习,SCL模块拉近同一分割区域(结构)内的特征表示,并将不同区域的特征推开,从而使得特征更具区分性。
- 这种对比学习方法有助于模型学习到更紧凑和更具代表性的特征,从而提高异常检测的准确性。
-
异常检测过程:
- 在异常检测阶段,UCAD框架通过比较当前样本的特征与检索到的特定任务的“知识”来检测异常。
- 这一过程涉及到特征的提取和比较,其中CPM和SCL模块共同作用,以确保模型能够有效地从当前任务中学习,并保留对之前任务的知识。
总的来说,UCAD框架通过CPM和SCL模块的协同工作,实现了在无监督环境下对连续任务的持续学习和异常检测。CPM负责任务的识别和适应,而SCL模块则通过对比学习增强特征表示,最终实现对异常的准确检测。这种设计使得UCAD能够在处理新的异常检测任务时,不会遗忘之前学到的知识,从而在连续学习场景中表现出色。
pseudo-code
# 导入必要的库
from torchvision import transforms
from torch import nn
from your_model import VisionTransformer, SegmentAnythingModel
# 定义UCAD类
class UCAD:
def __init__(self):
self.vit = VisionTransformer() # 预训练的视觉变换器(ViT)
self.sam = SegmentAnythingModel() # Segment Anything Model(SAM)
self.cpm = ContinualPromptingModule() # 持续提示模块
self.scl = StructureBasedContrastiveLearning() # 结构基对比学习模块
def train(self, train_loader):
# 训练UCAD模型
for data, target in train_loader:
self.cpm.task_identification(data) # 任务识别
self.scl.train(data, self.sam) # 结构基对比学习训练
self.cpm.task_adaptation(data) # 任务适应
def test(self, test_loader):
# 测试UCAD模型
for data in test_loader:
task_identity = self.cpm.test_time_task_selection(data) # 测试时任务选择
anomaly_score = self.cpm.adapt_and_detect(data, task_identity) # 适应和检测异常
anomaly_map = self.scl.generate_anomaly_map(data) # 生成异常图
return anomaly_score, anomaly_map
# 定义持续提示模块
class ContinualPromptingModule(nn.Module):
def __init__(self):
super(ContinualPromptingModule, self).__init__()
self.keys = {} # 存储任务键
self.prompts = {} # 存储任务提示
self.knowledge = {} # 存储任务知识
def task_identification(self, data):
# 使用ViT提取特征并进行任务识别
features = self.vit(data)
task_key = self.select_task_key(features)
return task_key
def task_adaptation(self, data):
# 任务适应和知识更新
prompts = self.get_prompts(task_key)
adapted_features = self.adapt_features(data, prompts)
self.update_knowledge(adapted_features)
def test_time_task_selection(self, data):
# 测试时任务选择
features = self.vit(data)
task_key = self.find_closest_key(features)
return task_key
def adapt_and_detect(self, data, task_key):
# 适应和检测异常
prompts = self.get_prompts(task_key)
adapted_features = self.adapt_features(data, prompts)
anomaly_score = self.calculate_anomaly_score(adapted_features)
return anomaly_score
# 定义基于结构的对比学习模块
class StructureBasedContrastiveLearning(nn.Module):
def train(self, data, sam):
# 使用SAM生成分割图并进行对比学习
segmentation_map = sam(data)
features = self.extract_features(data)
self.update_features(features, segmentation_map)
def generate_anomaly_map(self, data):
# 生成异常图
features = self.extract_features(data)
anomaly_map = self.compare_features(features)
return anomaly_map
# 实例化UCAD并训练测试
ucad = UCAD()
ucad.train(train_loader) # 训练UCAD模型
anomaly_score, anomaly_map = ucad.test(test_loader) # 测试UCAD模型
3、Experiments
4、Conclusion
- 提出用于无监督异常检测和分割的任务不可知持续学习框架 UCAD 方法。
- UCAD 的新颖性在于学习一个键提示知识记忆空间,以实现自动任务指令、知识转移、无监督异常检测和分割。
- 提出使用对比学习的提示来改善无监督特征提取,通过利用 SAM 的通用能力来改善各种类别之间的特征提取。