简而言之:矩阵→ReLU激活→矩阵
在解释机器学习模型方面,稀疏自编码器(SAE)是一种越来越常用的工具(虽然SAE在1997年左右就已经问世了)。
机器学习模型和LLM正变得越来越强大、越来越有用,但它们仍旧是黑箱,我们并不理解它们完成任务的方式。理解它们的工作方式应当大有助益。
SAE可帮助我们将模型的计算分解成可以理解的组件。近日,LLM可解释性研究者AdamKarvonen发布了一篇博客文章,直观地解释了SAE的工作方式。
可解释性的难题
神经网络最自然的组件是各个神经元。不幸的是,单个神经元并不能便捷地与单个概念相对应,比如学术引用、英语对话、HTTP请求和韩语文本。在神经网络中,概念是通过神经元的组合表示的,这被称为叠加(superposition)。
之所以会这样,是因为世界上很多变量天然就是稀疏的。
举个例子,某位名人的出生地可能出现在不到十亿分之一的训练token中,但现代LLM依然能学到这一事实以及有关这个世界的大量其它知识。训练数据中单个事实和概念的数量多于模型中神经元的数量,这可能就是叠加出现的原因。
近段时间,稀疏自编码器(SAE)技术越来越常被用于将神经网络分解成可理解的组件。SAE的设计灵感来自神经科学领域的稀疏编码假设。现在,SAE已成为解读人工神经网络方面最有潜力的工具之一。SAE与标准自编码器类似。
常规自编码器是一种用于压缩并重建输入数据的神经网络。
举个例子,如果输入是一个100维的向量(包含100个数值的列表);自编码器首先会让该输入通过一个编码器层,让其被压缩成一个50维的向量,然后将这个压缩后的编码表示馈送给解码器,得到100维的输出向量。其重建过程通常并不完美,因为压缩过程会让重建任务变得非常困难。
一个标准自编码器的示意图,其有1x4的输入向量、1x2的中间状态向量和1x4的输出向量。单元格的颜色表示激活值。输出是输入的不完美重建结果。
解释稀疏自编码器
稀疏自编码器的工作方式
稀疏自编码器会将输入向量转换成中间向量,该中间向量的维度可能高于、等于或低于输入的维度。在用于LLM时,中间向量的维度通常高于输入。在这种情况下,如果不加额外的约束条件,那么该任务就很简单,SAE可以使用单位矩阵来完美地重建出输入,不会出现任何意料之外的东西。但我们会添加约束条件,其中之一是为训练损失添加稀疏度惩罚,这会促使SAE创建稀疏的中间向量。
举个例子,我们可以将100维的输入扩展成200维的已编码表征向量,并且我们可以训练SAE使其在已编码表征中仅有大约20个非零元素。
稀疏自编码器示意图。请注意,中间激活是稀疏的,仅有2个非零值。
我们将SAE用于神经网络内的中间激活,而神经网络可能包含许多层。在前向通过过程中,每一层中和每一层之间都有中间激活。
举个例子,GPT-3有96层。在前向通过过程中,输入中的每个token都有一个12,288维向量(一个包含12,288个数值的列表)。此向量会累积模型在每一层处理时用于预测下一token的所有信息,但它并不透明,让人难以理解其中究竟包含什么信息。
我们可以使用SAE来理解这种中间激活。SAE基本上就是「矩阵→ReLU激活→矩阵」。
举个例子,如果GPT-3SAE的扩展因子为4,其输入激活有12,288维,则其SAE编码的表征有49,512维(12,288x4)。第一个矩阵是形状为(12,288,49,512)的编码器矩阵,第二个矩阵是形状为(49,512,12,288)的解码器矩阵。通过让GPT的激活与编码器相乘并使用ReLU,可以得到49,512维的SAE编码的稀疏表征,因为SAE的损失函数会促使实现稀疏性。
通常来说,我们的目标让SAE的表征中非零值的数量少于100个。通过将SAE的表征与解码器相乘,可得到一个12,288维的重建的模型激活。这个重建结果并不能与原始的GPT激活完美匹配,因为稀疏性约束条件会让完美匹配难以实现。
一般来说,一个SAE仅用于模型中的一个位置举个例子,我们可以在26和27层之间的中间激活上训练一个SAE。为了分析GPT-3的全部96层的输出中包含的信息,可以训练96个分立的SAE——每层的输出都有一个。如果我们也想分析每一层内各种不同的中间激活,那就需要数百个SAE。为了获取这些SAE的训练数据,需要向这个GPT模型输入大量不同的文本,然后收集每个选定位置的中间激活。
下面提供了一个SAE的PyTorch参考实现。其中的变量带有形状注释,这个点子来自NoamShazeer,参见:https://medium.com/@NoamShazeer/shape-suffixes-good-coding-style-f836e72e24fd。请注意,为了尽可能地提升性能,不同的SAE实现往往会有不同的偏置项、归一化方案或初始化方案。最常见的一种附加项是某种对解码器向量范数的约束。更多细节请访问以下实现:
OpenAI:https://github.com/openai/sparse_autoencoder/blob/main/sparse_autoencoder/model.py#L16SAELens:https://github.com/jbloomAus/SAELens/blob/main/sae_lens/sae.py#L97dictionary_learning:https://github.com/saprmarks/dictionary_learning/blob/main/dictionary.py#L30
importtorch
importtorch.nnasnn
#D=d_model,F=dictionary_size
#e.g.ifd_model=12288anddictionary_size=49152
#thenmodel_activations_D.shape=(12288,)andencoder_DF.weight.shape=(12288,49152)
classSparseAutoEncoder(nn.Module):
Aone-layerautoencoder.
def__init__(self,activation_dim:int,dict_size:int):
super().__init__()
self.activation_dim=activation_dim
self.dict_size=dict_size
self.encoder_DF=nn.Linear(activation_dim,dict_size,bias=True)
self.decoder_FD=nn.Linear(dict_size,activation_dim,bias=True)
defencode(self,model_activations_D:torch.Tensor)->torch.Tensor:
returnnn.ReLU()(self.encoder_DF(model_activations_D))
defdecode(self,encoded_representation_F:torch.Tensor)->torch.Tensor:
returnself.decoder_FD(encoded_representation_F)
defforward_pass(self,model_activations_D:torch.Tensor)->tuple[torch.Tensor,torch.Tensor]:
encoded_representation_F=self.encode(model_activations_D)
reconstructed_model_activations_D=self.decode(encoded_representation_F)
returnreconstructed_model_activations_D,encoded_representation_F
标准自编码器的损失函数基于输入重建结果的准确度。为了引入稀疏性,最直接的方法是向SAE的损失函数添加一个稀疏度惩罚项。对于这个惩罚项,最常见的计算方式是取这个SAE的已编码表征(而非SAE权重)的L1损失并将其乘以一个L1系数。这个L1系数是SAE训练中的一个关键超参数,因为它可确定实现稀疏度与维持重建准确度之间的权衡。
请注意,这里并没有针对可解释性进行优化。相反,可解释的SAE特征是优化稀疏度和重建的一个附带效果。下面是一个参考损失函数。
#B=batchsize,D=d_model,F=dictionary_size
defcalculate_loss(autoencoder:SparseAutoEncoder,model_activations_BD:torch.Tensor,l1_coeffient:float)->torch.Tensor:
reconstructed_model_activations_BD,encoded_representation_BF=autoencoder.forward_pass(model_activations_BD)
reconstruction_error_BD=(reconstructed_model_activations_BD-model_activations_BD).pow(2)
reconstruction_error_B=einops.reduce(reconstruction_error_BD,/'BD->B/',/'sum/')
l2_loss=reconstruction_error_B.mean()
l1_loss=l1_coefficient*encoded_representation_BF.sum()
loss=l2_loss+l1_loss
returnloss
稀疏自编码器的前向通过示意图。
这是稀疏自编码器的单次前向通过过程。首先是1x4大小的模型向量。然后将其乘以一个4x8的编码器矩阵,得到一个1x8的已编码向量,然后应用ReLU将负值变成零。这个编码后的向量就是稀疏的。之后,再让其乘以一个8x4的解码器矩阵,得到一个1x4的不完美重建的模型激活。
假想的SAE特征演示
理想情况下,SAE表征中的每个有效数值都对应于某个可理解的组件。
这里假设一个案例进行说明。假设一个12,288维向量[1.5,0.2,-1.2,...]在GPT-3看来是表示「GoldenRetriever」(金毛犬)。SAE是一个形状为(49,512,12,288)的矩阵,但我们也可以将其看作是49,512个向量的集合,其中每个向量的形状都是(1,12,288)。如果该SAE解码器的317向量学习到了与GPT-3那一样的「GoldenRetriever」概念,那么该解码器向量大致也等于[1.5,0.2,-1.2,...]。
无论何时SAE的激活的317元素是非零的,那么对应于「GoldenRetriever」的向量(并根据317元素的幅度)会被添加到重建激活中。用机械可解释性的术语来说,这可以简洁地描述为「解码器向量对应于残差流空间中特征的线性表征」。
也可以说有49,512维的已编码表征的SAE有49,512个特征。特征由对应的编码器和解码器向量构成。编码器向量的作用是检测模型的内部概念,同时最小化其它概念的干扰,尽管解码器向量的作用是表示「真实的」特征方向。研究者的实验发现,每个特征的编码器和解码器特征是不一样的,并且余弦相似度的中位数为0.5。在下图中,三个红框对应于单个特征。
稀疏自编码器示意图,其中三个红框对应于SAE特征1,绿框对应于特征4。每个特征都有一个1x4的编码器向量、1x1的特征激活和1x4的解码器向量。重建的激活的构建仅使用了来自SAE特征1和4的解码器向量。如果红框表示「红颜色」,绿框表示「球」,那么该模型可能表示「红球」。
那么我们该如何得知假设的特征317表示什么呢?目前而言,人们的实践方法是寻找能最大程度激活特征并对它们的可解释性给出直觉反应的输入。能让每个特征激活的输入通常是可解释的。
举个例子,Anthropic在ClaudeSonnet上训练了SAE,结果发现:与金门大桥、神经科学和热门旅游景点相关的文本和图像会激活不同的SAE特征。其它一些特征会被并不显而易见的概念激活,比如在Pythia上训练的一个SAE的一个特征会被这样的概念激活,即「用于修饰句子主语的关系从句或介词短语的最终token」。
由于SAE解码器向量的形状与LLM的中间激活一样,因此可简单地通过将解码器向量加入到模型激活来执行因果干预。通过让该解码器向量乘以一个扩展因子,可以调整这种干预的强度。当Anthropic研究者将「金门大桥」SAE解码器向量添加到Claude的激活时,Claude会被迫在每个响应中都提及「金门大桥」。
下面是使用假设的特征317得到的因果干预的参考实现。类似于「金门大桥」Claude,这种非常简单的干预会迫使GPT-3模型在每个响应中都提及「金毛犬」。
defperform_intervention(model_activations_D:torch.Tensor,decoder_FD:torch.Tensor,scale:float)->torch.Tensor:
intervention_vector_D=decoder_FD[317,:]
scaled_intervention_vector_D=intervention_vector_D*scale
modified_model_activations_D=model_activations_D+scaled_intervention_vector_D
returnmodified_model_activations_D
稀疏自编码器的评估难题
使用SAE的一大主要难题是评估。我们可以训练稀疏自编码器来解释语言模型,但我们没有自然语言表示的可度量的底层groundtruth。目前而言,评估都很主观,基本也就是「我们研究一系列特征的激活输入,然后凭直觉阐述这些特征的可解释性。」这是可解释性领域的主要限制。
研究者已经发现了一些似乎与特征可解释性相对应的常见代理指标。最常用的是L0和LossRecovered。L0是SAE的已编码中间表征中非零元素的平均数量。LossRecovered是使用重建的激活替换GPT的原始激活,并测量不完美重建结果的额外损失。这两个指标通常需要权衡考虑,因为SAE可能会为了提升稀疏性而选择一个会导致重建准确度下降的解。
在比较SAE时,一种常用方法是绘制这两个变量的图表,然后检查它们之间的权衡。为了实现更好的权衡,许多新的SAE方法(如DeepMind的GatedSAE和OpenAI的TopKSAE)对稀疏度惩罚做了修改。下图来自DeepMind的GatedSAE论文。GatedSAE由红线表示,位于图中左上方,这表明其在这种权衡上表现更好。
GatedSAEL0与LossRecovered
SAE的度量存在多个难度层级。L0和LossRecovered是两个代理指标。但是,在训练时我们并不会使用它们,因为L0不可微分,而在SAE训练期间计算LossRecovered的计算成本非常高。相反,我们的训练损失由一个L1惩罚项和重建内部激活的准确度决定,而非其对下游损失的影响。
训练损失函数并不与代理指标直接对应,并且代理指标只是对特征可解释性的主观评估的代理。由于我们的真正目标是「了解模型的工作方式」,主观可解释性评估只是代理,因此还会有另一层不匹配。LLM中的一些重要概念可能并不容易解释,而且我们可能会在盲目优化可解释性时忽视这些概念。
总结
可解释性领域还有很长的路要走,但SAE是真正的进步。SAE能实现有趣的新应用,比如一种用于查找「金门大桥」导向向量(steeringvector)这样的导向向量的无监督方法。SAE也能帮助我们更轻松地查找语言模型中的回路,这或可用于移除模型内部不必要的偏置。
SAE能找到可解释的特征(即便目标仅仅是识别激活中的模式),这一事实说明它们能够揭示一些有意义的东西。还有证据表明LLM确实能学习到一些有意义的东西,而不仅仅是记忆表层的统计规律。
SAE也能代表Anthropic等公司曾引以为目标的早期里程碑,即「用于机器学习模型的MRI(磁共振成像)」。SAE目前还不能提供完美的理解能力,但却可用于检测不良行为。SAE和SAE评估的主要挑战并非不可克服,并且现在已有很多研究者在攻坚这一课题。
有关稀疏自编码器的进一步介绍,可参阅CallumMcDougal的Colab笔记本:https://www.lesswrong.com/posts/LnHowHgmrMbWtpkxx/intro-to-superposition-and-sparse-autoencoders-colab
https://www.reddit.com/r/MachineLearning/comments/1eeihdl/d_an_intuitive_explanation_of_sparse_autoencoders/
https://adamkarvonen.github.io/machine_learning/2024/06/11/sae-intuitions.html
未经允许不得转载:头条资讯网_今日热点_娱乐才是你关心的时事 » 稀疏自编码器是如何工作的,这里有一份直观说明