LLM大模型: 多模态特征提取网络架构侧的奇技淫巧
传统的机器学习,用的分类器或回归模型,诸如logistics regression/softmax、svm、naive bayes、decision tree、random forest、GBDT、xgboost等,最核心的要点就是要人工构造特征了。好的特征能让准确率、覆盖率等指标提升十几个~几十个点,直接决定了模型效果的下限;而同样的数据,在不同模型之间尝试,准确率、覆盖率的提升最多几个点,效果远不如好的特征明显,所以传统机器学习诞生了一个分支:feather engineering,专门用来构造各种区分度高的特征!做传统的机器学习时,真正用于训练模型、调参的时间可能不到20%,超过80%的时间都用在了feather engineering上了,比如:
- 数据清洗:
- 缩放特征值(归一化):将浮点特征值从自然范围(如 100 到 900)转换为标准范围(如 0 到 1)。特征集包含多个特征时,缩放特征可以加快梯度下降的收敛过程,并可以避免 NaN 陷阱。特征缩放的方法一般为 scaled-value = (value-mean)/stddev
- 处理极端离群值,如取对数、限制最大最小值等方法
- 分箱(离散化)
- 填补遗漏值
- 移除重复样本、不良标签、不良特征值等
- 平滑
- 正则化
降维 dimension reduction:
- 主成分分析法(PCA)
- 核化线性降维(KPCA)
- 主成分回归(PCR)
- 偏最小二乘回归(PLSR)
- 多维尺度分析法(MDS)
- 投影寻踪法(PP)
- 线性判别分析法(LDA)
- 混合判别分析法(MDA)
- 二次判别分析法(QDA)
- 灵活判别分析法(Flexible Discriminant Analysis,FDA)
- 特征选择 feather selection:把冗余的、无关的特征去掉,避免干扰后续的model
- 过滤式选择:先对数据集进行特征选择,然后再训练学习器,特征选择过程与后续学习器无关。典型算法为 Relief 算法。
- 方差选择法
- 相关系数法
- 卡方检验
- 互信息法
- 包裹式选择:选择直接把最终将要使用的学习器的性能作为特征子集的评价标准。典型算法为 LVM(Las Vegas Wrapper)。
- 递归特征消除法
- 嵌入式选择:将特征选择过程与学习器训练过程融为一体,两者在同一个优化过程中完成,即在学习器训练过程中自动地进行了特征选择。典型算法为岭回归(ridge regression)、LASSO 回归(Least Absolute Shrinkage and Selection Operator)等。
- 基于惩罚项的特征选择法
- 基于树模型的特征选择法
- 过滤式选择:先对数据集进行特征选择,然后再训练学习器,特征选择过程与后续学习器无关。典型算法为 Relief 算法。
- 特征组合 feather cross:比如特征N阶组合,Neroul netword的通过tylor展开,核心就是这个N阶特征组合的效果
看吧,feather engineering就有这个多内容,所以训练个模型,80%多的时间全都耗费在这上面了!DNN和这两年LLM流行后,feather engineering很少再被频繁提起了,是不是feather engineering完全不需要了?以现在大红大紫的AI来说,不管是discriminative AI,还是generative AI,不管loss function是cross entropy,还是MSE,要想效果好,最后一步生成的embedding一定要好;embedding本质不就是input经过层层运算转换后生成的feather vector么?只要embedding质量好了,有明显的强特征维度,何愁最终的softmax质量不好了?multi large language model有很多,比如blip系列、clip、flamingo、 llava、llama vision等,这些业界知名的multi LLM在提取特征时都有哪些“靓点”了?
1、vit网络架构如下:做nlp任务时,有两个特殊的token:CLS和EOS,分别表示句子的开头和结尾;一般可以EOS的embedding作为整个sentence全句的语义表达!对于image,vit的处理方式是先切割成patch,然后把patch当成token处理,但是每个patch只承载了image的局部信息,对于图片整体的描述、分类、检索等任务,直接用patch提供的局部信息明显是肯定是不够的,应该怎么得到image的全局信息了?
方式之一是把所有patch的embedding相加,然后取均值,思路类似average pooling;另一种方式的就是效仿nlp的CLS或EOS,用这种special token承载全局信息。在vit模型中,在0位置,有个特殊的token,用*表示,这个位置的token就代表了image的全局信息,通过encoder中的attention机制,可以吸收其他所有patch的信息,达到整个、代表image全局信息的目的!
2、MOCO:Momentum Contrast for Unsupervised Visual Representation Learning
constractive learning 是非常重要的一种机器学习思路,常用于计算两个事务的相似度、距离,能在推荐系统、检索等业务场景使用。对于无监督的unsupervised constractive learning,以image instance discrimination为例,通常把image拉伸变形后作为positive sample,其他作为负样本,比如:
这种constractive learning有个显著特点:没有固定的label,同一个样本生成的embedding会随着配对样本的变化而变化!这种学习方式面临1个问题:
- batch size:bs过小,可能导致负样本分布不均,比如第一个batch某个负样本被模型放在A位置,训练第二个batch的时候,模型不知道上个batch在A点有负样本,可能又在A点附近放置了新的负样本,这就让不同batch之间的负样本对距离接近,导致后续的推理出错!如果每个epoch都拿所有sample去训练了,显存扛不住啊,相当烧钱!
- 负样本最好是同一个模型来分配空间,避免同一个样本被不同的模型分配在了差距较大的空间
MOCO的解决办法:把constractive learning看成是字典检索问题,根据query从字典中找到唯一匹配的样本!
每个batch训练后,模型的参数都会变化,导致同一个样本,在每个batch训练后生成的embedding都不同!这么变来变去的,会导致后续的收敛困难!既然困难都是同一个样本embedding变化太大导致的,那就让变化减少呗!梯度下降不是有学利率lr超参数么?人为设置小一点,让梯度下降时的步伐小一点,避免loss来回震荡,这里是不是能借鉴一下了? 这里采用动量系数的思路:
- 每次更新seta参数只更新一点点,让同一个样本在不同batch训练后得到的embedding差值不要太大来解决收敛问题!
- 正样本都有固定的负样本队列(队列的大小甚至可以>>batch size,保证负样本的多样性),每次batch训练时负样本都从队列里面找一定数量,不会随机从数据集抽取,保证负样本的随机性和多样性,以及embedding的稳定性;
- 由于负样本更新非常慢,非常平滑,负样本的位置几乎不动,所以每次训练主要更新正样本的位置。举例:A样本作为正样本时移动,其他负样本几乎不动,A找到合适的位置;A作为负样本时,因为A在做正样本时已经找到了合适的位置,所以几乎不动,其他正样本动。每个样本在做正样本的时候都能找到合适的位置,做负样本的时候几乎不动,整个epoch训练往后,每个样本都能找到自己合适的位置了!
3、(1)ALBEF:Align before fuse: Vision and LanguageRepresentation Learning with Momentum Distillation
从模型算法的命名就能看出来这个模型的特点:align before fuse,这个怎么理解了?fuse肯定指的时image和text做cross attention啦,那在做corss attention之间的align怎么理解了?注意看上面的图text和image的input 经过self attention后,进入了image-text contrastive loss:Image用的0号位置的embedding(代表image的global sematic),text用的CLS或EOS token的embedding做constrastive learning,这就是所谓的alignment,最重要的一点就是:为啥要这么干了?image和text,各自经过transformer block后得到了各自的representation embedding,但是这是两个在独立空间生成的embedding啊,相当于牛和马,完全不是一个物种,这两个独立空间生成的embedding直接做cross attention,效果能好么?所以作者的思路是先把这两个embedding拉近到同一个空间后再做cross attention,ITC loss就这么诞生了! 这本质还是在做feather engineering,目的是为后续的ITM和MLM准备高质量的特征数据!
(2)image-text配对的数据大部分都是从互联网爬取的,这种公网爬取的数据肯定不可能100%正确;即使语义匹配正确,有些描述可能也不完美,举例如下:
如果让人挨个检查,成本得多高啊!而且人工检查,也可能犯错啊!怎么使用模型算法自动纠正或避免这些错误了?正常情况下,错误的样本应该是少数,大部分都是正确的(如果训练数据大部分都是错误的,还有必要训练模型么?),所以模型的参数要平滑移动,避免遇到错误的noisy数据时突然大幅移到错误的位置,这个思路是不是和上面的EMA很像啊!思路如下:
动量系数alpha=0.999,动量模型的表示更具“历史一致性”,它反映的是过去多个训练步骤的累计状态,而非当前某个 batch 的瞬时状态,就算偶尔遇到noisy样本,已经训练好的参数也不会受大影响,这里体现了鲁棒性。思路确定后,接下来就要考虑怎么落地实施了!MoCo的方式是建立了一个负样本队列,并使用encoder提取负样本的embedding,对该encoder使用EMA的策略更新参数,相当于把历史负样本的信息都记录在负样本队列的decoder啦,并且非常缓慢地更新!MoCo针对的是单模态,而这里是多模态,该怎么做了?正样本的encoder不适用EMA,参数正常更新。负样本的encoder使用EMA策略,参数缓慢更新;这里借鉴MoCo的思路,干脆来票大的,把整个模型都使用EMA策略了?ALBEF使用的网络结构如下所示:
右边是专门的Momentum Mode,使用EMA策略缓慢更新参数,核心目的是保留历史信息用于平滑更新,避免noisy影响;左边的模型不使用EMA策略,正常更新参数、快速学习新知识!
- student model(mainly model)可以快速适应新数据,但可能会过拟合到 noisy 数据。
- teacher model(Momentum Mode)通过历史平滑的方式避免了 noisy 数据的影响,从而对学生模型形成有效的监督,指导其学习更稳定的特征表示。
这就是论文标题里面的Momentum Distillation!
从作者自己公布的结果看,效果还是很不错的:
4、 blip2,网络架构如下:
普通的多模态融合,直接让text和image的token直接做运算,比如:
- cross attention,fuse feather
- ITC:双方的feather align到同一个空间
但Q-Former很奇怪,image通过encoder后并未直接和text做ITC,而是先和learned queries做cross attention,这又是在干啥了?大部分时候,image是有冗余信息的,比如上图例子:text的核心是cat、sunglasses,对应image就是猫和太阳镜,其他部分都是冗余无用的;如果直接把整个image的全局信息和text做ITC,这些冗余信息是有可能干扰结果的!理想情况是:image只保留cat、sunglasses相关patch的信息,其他信息全部去掉,然后再和text embedding做ITC,这个该怎么实现了?这里就要用到learned queries了!
learned queries初始值是随机的,随着loss值来调整,最终得到合适的值!learned queries核心作用两个:
- 从original image提取与text匹配的patch 信息,去掉不相干的信息,减少对ITC 的干扰!
- 上述功能也可以看成是降维,减少token数量,从而减少后续的计算和传输
blip2的效果:做了ITC,在做feather fuse前align了特征,效果比不做ITC好很多哦!
5、 llava:单纯从网络架构看,llava独树一帜,没有任何花里胡哨的结构,非常”朴实无华“,如下:
image和text分别经过encoder后,把image的token和text的token顺序排列,然后送入LLM处理,期间没有做ITC,也没有learnned queries,也没有momentum model,但从作者自己的对比数据看,效果还很好:
这难道印证了中国人的那句古话:大道至简?既然网络结构简单,llava效果还好,那就只能是llava的训练数据好了?https://arxiv.org/pdf/2304.08485 llava的论文作者使用GPT-4 生成各种数据,如下:
好吧,这个是真鸡贼啊!
总结:
1、最近十几各种网络结构风靡,本质还是在提取特征,只不过提取特征的方式方法和10多年前的不一样啦!
参考:
1、https://www.bilibili.com/video/BV1QrBEY3Eax?spm_id_from=333.788.player.switch&vd_source=241a5bcb1c13e6828e519dd1f78f35b2
2、https://feisky.xyz/machine-learning/basic/feature-engineering.html