论文阅读:Generative Recommendation with Semantic IDs: A Practitioner’s Handbook

基本信息 论文标题:Generative Recommendation with Semantic IDs: A Practitioner’s Handbook 作者单位:Snap 论文链接:https://arxiv.org/pdf/2507.22224 来源:CIKM 2025 这是CIKM 2025的一篇resource文章,比较简单。核心内容是开源了一个基于semantic id的生成式推荐框架GRID,可以很方便地做各种消融对比实验。 主要内容 主要结论如下: 对于semantic id生成算法,简单的RQ-KMeans效果反而是最好的,好于R-VQ和RQ-VAE 生产pretrain emb的LLM模型参数量越大,效果越好,但是提升幅度有限 生产semantic id的codebook size和网络层数并不是越大越好,常规的3层,每层256个id效果反而最好 生成式推荐时,是否需要在用户行为序列基础上增加一个user id,实验发现增加user id效果反而变差,不增加user id效果最好 生成式网络结构encoder-decoder对比decoder-only,发现前者效果更好,因为前者能充分学习到行为序列完整的信息 对行为流进行滑动窗口数据增强能提升模型的泛化能力 当semantic id到item存在映射冲突时,随机选一个item的效果和对冲突item追加一个区分标识(digit),两者效果差不多 在生成式beam search的时候,限制只输出合法semantic id和不增加限制,两者效果差不多 评论 看这篇文章主要是想看看不同semantic id生产方法的对比,发现RQ-KMeans居然比RQ-VAE更好。个人感觉这两个方法效果应该差不多,后者应该更好点才对。首先,RQ-VAE的量化loss本质上和KMeans聚类是一个意思;其次,RQ-VAE还增加了一个重构loss,感觉产出来的semantic id和原始emb的信息损失应该更少。 此外,本文的所有实验都是基于亚马逊的公开数据集,数据量肯定不能和真正的工业数据集相提并论,所以文中很多结论有可能只适用于本文的设定,换一个场景估计结论就变了,所以看看就好。 最后,文中很多结论只写了现象,要是能增加原因分析就好了。

October 7, 2025 · 1 min

论文阅读:Progressive Semantic Residual Quantization for Multimodal-Joint Interest Modeling in Music Recommendation

基本信息 论文标题:Progressive Semantic Residual Quantization for Multimodal-Joint Interest Modeling in Music Recommendation 作者单位:网易云音乐 论文链接:https://arxiv.org/pdf/2508.20359 来源:CIKM 2025 Motivation:论文要解决的问题是什么 多模态emb在搜推的应用方式,通常是先将多模态emb转换成semantic id,然后把semantic id用到搜推模型中,这种方式有如下两个问题: 模态内语义退化:多模态emb转换成semantic id通常使用RQ-VAE或者RQ-KMeans的方法,这种方法在不断残差的过程中,后续残差聚类结果已经不能反映初始emb的聚类效果了。其实就是semantic id的沙漏问题,具体可以看这篇文章,后续有空再分享这个问题。 简单来说,如下图所示,初始有DJ、Rock、Lullaby、Choir四个类,但是对残差emb(即RQ-VAE的第二层)聚类的话,初始的四个类的item就打散了,会聚到不同的簇中,也就是RQ-VAE的后续层的聚类效果已经和初始emb的聚类效果很不一样了,这就是文中说的语义退化问题 模态间建模差异:搜推场景的item通常有多种模态特征,比如文本、图像、音频等,传统方法在多模态融合方面比较简单,不能很好地捕捉多模态之间的关系。 PSRQ生产semantic id 本文是音乐推荐场景,主要用到两种模态:text和audio,分别用百川和MERT提取text和audio的模态emb。 生产semantic id的方法如下图所示: fig2a是传统的RQ-KMeans的方法,每一层都用上一层的残差进行聚类。如上文所述,由于沙漏问题,会导致后续层次的semantic id存在语义退化问题 fig2b是本文新提出的PSRQ量化方法,在RQ-KMeans基础上,每一层除了有上一层的残差向量,还会concat上初始emb减去残差emb后的向量。这样就能区分出残差相似,但初始emb不同的item了,也就避免了RQ方法的沙漏问题,后续semantic id也能保留初始emb的语义信息。fig1d能看出来第二层semantic id仍然能够反映初始emb的分类效果。 Semantic id在下游的应用方法 如下图所示: 每个item有两套多模态emb:text和audio,但是有三套semantic id,除了text和audio各自产一套semantic id之外,还会把text和audio的emb concat起来,再产一套semantic id,相当于多模态融合的semantic id semantic id的emb在排序模型中随机初始化,然后端到端训练 semantic id在用户建模时,使用DIN模型,query用的是多模态融合的semantic id emb,行为流分别用text和audio的semantic id emb。作者说这种方法既能捕捉到单模态细粒度的信息,又能建模跨模态的交互信息 评论 可借鉴 PSRQ的semantic id生产方法确实很有意思,在每一层都用上原始emb,这样不同簇的item在每一层都能分开,不会出现沙漏问题,使得每一层的semantic id都能保留原始emb的语义聚类信息 产了多套semantic id,单模态semantic id是常规操作;多模态emb concat后也产一套semantic id,是个创新点 用户建模时query用多模态semantic id,行为流用单模态semantic id,也是个创新点,虽然论文说这种方法效果最好,但是有点存疑 论文有个实验结果对比了不同semantic id量化方法的效果,结论是:PSRQ > RQ-KMeans = RQ-VAE > VQ > PQ 可改进 pretrain emb和semantic id的生产都没有对齐协同信号 semantic id在下游应用时直接端到端训练,而没有使用codebook初始化,会不会丢失信息比较多? 产semantic id的过程中,模态内语义退化的问题,描述了现象,但是没有用定量的指标来说明问题,感觉可以借鉴【论文阅读:Empowering Large Language Model for Sequential Recommendation via Multimodal Embeddings and Semantic IDs】的方法,定量说明后续层的semantic id的聚类效果或者说区分能力相比初始emb已经相差甚远了 fig2b中,第一层的codebook的dim=d,后续层的codebook的dim=2d,那么后续层的残差dim也是2d,那么初始emb怎么和后续的残差emb相减呢,维度对不上啊?我理解可能是这样的,后续层聚类的时候用的是concat的dim=2d的emb,但是算聚类中心的时候只用了残差本身的emb,这样就能解释得通了,但是文中对这部分的细节没有解释。

October 6, 2025 · 1 min

论文阅读:DAS: Dual-Aligned Semantic IDs Empowered Industrial Recommender System

基本信息 论文标题:DAS: Dual-Aligned Semantic IDs Empowered Industrial Recommender System 作者单位:快手 论文链接:https://arxiv.org/pdf/2508.10584 来源:CIKM 2025 Motivation:论文要解决的问题是什么 Semantic id生产时,要么没有和协同信号对齐(fig2(1)),要么是两阶段对齐方式(fig2(2)): 例如LETTER先生成协同emb,然后和semantic id对齐 或者例如QARM,先协同对齐emb,再生产semantic id 把协同对齐和生产semantic id分成两个阶段,天然有信息损失,不是最优的。本文的目的就是把生产协同emb,以及semantic id的协同对齐放到一个模型中联合训练完成,尽量减少信息损失(fig2(3))。 主模型 主模型如上图所示,中间的ICDM是user和item的双塔模型,用于学习user和item的协同id-based emb;两边分别是生产user和item的semantic id的量化模型。 中间的ICDM就是经典的召回双塔模型,使用点击样本进行训练,唯一不同的是,在user和item塔都有流行度去偏模块,用于学习user和item的无偏emb,后续user和item的semantic id协同对齐用的也是无偏的emb。 两边分别是user和item的semantic id量化模型,两者比较类似,以item为例: 先把item的各种信息,如title、desc、ocr等信息用文本构造成prompt,输入到LLM,借助LLM的summary和reasoning能力,产出item的详细描述 然后把LLM产出的描述再输入到一个预训练的embedding模型PLM,文中用的是bge m3模型,得到item emb 后续就是标准的RQ-VAE过程了 需要注意的是,上述前两步,分别用到了LLM和PLM两个大模型,而且看图上这两个模型都是freeze的,也就是说并不微调这两个大模型。后续协同对齐用的emb是RQ-VAE重构emb的中间层结果,即图中的item quantized emb。 semantic id的协同对齐方面,有三大类对齐任务: U2I对齐:量化user emb和协同item emb对齐、量化item emb和协同user emb对齐 U2U和I2I对齐:量化user emb和协同user emb对齐、量化item emb和协同item emb对齐 U2U和I2I的共现对齐:点击相同item的两个量化user emb对齐、同一个user点击的两个item的量化item emb对齐 由于fig3中的协同模型和semantic id模型是联合训练的,总共有3大类loss: 中间的ICDM的双塔召回模型的loss 两边的产semantic id的loss 三个模块的对齐loss 评论 可借鉴 把semantic id的生产和协同信号对齐统一成一阶段的模式,信息损失更少 中间的ICDM模型生产协同emb时进行了去偏,协同对齐的时候用的是去偏的emb,这是其他论文很少提到的 可改进 太复杂了!3个模块,3大类loss,每类loss又有很多个小loss,总loss数量加起来有十多个。。。 任务太多,各种去偏、对齐loss,真的不会互相影响吗? 中间的ICDM模块有必要吗?我理解ICDM本质是为了训练产出协同emb,但是因为训练样本本身是点击样本,样本本身已经包含了搜推场景的协同信号,也就是ICDM本身没必要存在了,直接用相同的样本训练两边的semantic id量化模型就行了,也能实现在训练semantic id的过程中,完成协同信号的对齐 生产semantic id的emb来自LLM和PLM,但是这两个大模型都是freeze的,如果把这两个模型也sft,效果会不会更好?其实我原本以为的一阶段就是这样的,这也是我在【论文阅读:Empowering Large Language Model for Sequential Recommendation via Multimodal Embeddings and Semantic IDs】中提到的一阶段方法。

October 5, 2025 · 1 min

论文阅读:QARM: Quantitative Alignment Multi-Modal Recommendation at Kuaishou

基本信息 论文标题:QARM: Quantitative Alignment Multi-Modal Recommendation at Kuaishou 作者单位:快手 论文链接:https://arxiv.org/pdf/2411.11739 来源:CIKM 2025 Motivation:论文要解决的问题是什么 多模态emb在搜推场景应用时通常采用如下图的两阶段方式,先预训练多模态emb,然后作为一个冻结特征放到搜推模型中。这种方式存在2个问题: 表征不对齐:多模态emb预训练的任务通常是图片分类或者文本的MLM,和下游搜推任务不对齐 表征不更新:多模态emb在搜推任务中作为冻结特征,没有更新 本文的方法就是想要解决上述2个问题。 对齐搜推任务的多模态emb预训练 为了解决多模态emb表征不对齐的问题,本文提出的多模态emb预训练任务直接对齐搜推场景,使用U2I和I2I召回模型,挖掘出相似item pair,然后通过对比学习微调多模态大模型。 具体来说,通过U2I和I2I模型,能够拿到item emb;然后用每一个target item emb去行为流中检索出最相似的商品,作为trigger item emb。<trigger, target>构成一对正样本,然后进行对比学习训练。 通过召回模型构造的训练样本,和搜推场景的协同信号对齐了,解决了开头提到的第一个问题,即表征不对齐的问题。 Semantic id生产方法 Semantic id的生产方法如上图右半部分所示,有两种方式: VQ:直接圈定一定数量(如N)的item emb作为底池,编号1~N,然后任意来一个item emb,通过对底池emb进行KNN搜索,找出top-k相似商品,假设是(a,b,…,k),则VQ编码的semantic id就是(a,b,…,k)。文中取k=25,感觉挺大的。。。 RQ-Kmeans:对圈定的N个item emb不断进行Kmeans聚类、求残差、残差继续Kmeans聚类的过程。文中取迭代次数为L=6,但是没说每次聚到多少个类。 注意:文中的RQ-Kmeans方法和RQ-VAE还不一样,RQ-Kmeans没有训练过程,也没有重构loss,纯粹是每次进行聚类,然后选聚类中心作为码本的过程。文中也没有对比过为啥不用RQ-VAE。 产出两套semantic id之后,直接在下游排序任务中进行端到端更新,解决开头提到的表征不更新的问题。具体建模方法比较常规,不是本文的重点,略讲。 评论 可借鉴 多模态emb预训练任务是i2i的,直接和下游搜推任务对齐 semantic id有两种产出方式,VQ和RQ-Kmeans,尽可能多地保留原始多模态emb的信息 可改进 多模态emb预训练和下游任务对齐,在2025年不算新鲜事了,常规操作。而且文中i2i的构造过程依赖U2I和I2I召回模型,有外部依赖,不够漂亮 VQ的方法,k=25这也太长了吧,相当于一个小型行为流了,会导致下游任务的特征处理更复杂 为什么用RQ-Kmeans而不是RQ-VAE,没有任何说明与对比 从pretrain emb量化成semantic id的过程中,存在严重的信息丢失,这在Empowering Large Language Model for Sequential Recommendation via Multimodal Embeddings and Semantic IDs论文中有讨论

October 4, 2025 · 1 min

论文阅读:Empowering Large Language Model for Sequential Recommendation via Multimodal Embeddings and Semantic IDs

基本信息 论文标题:Empowering Large Language Model for Sequential Recommendation via Multimodal Embeddings and Semantic IDs 作者单位:香港城市大学&腾讯 论文链接:https://arxiv.org/pdf/2509.02017 来源:CIKM 2025 Motivation:论文要解决的问题是什么 LLM4SR的基本范式如下,即用LLM直接来做搜推的范式(这种方式在学术界常见,但在工业界不常见)。由于LLM的输入词表范围是有限的(通常比较小),因此其token emb dim通常比较大,比如2048或者4096;而搜推场景的item量级很大,而且在不断更新,因此工业界经典的id-based的搜推模型的item emb dim通常比较小,比如64或128。经典的id-based的搜推模型能比较好地学习到搜推场景的协同信号,为了让LLM模型也能感知这种信息,LLM4SR范式通常会先预训练一个id-based的经典搜推模型,然后将其中的item id emb通过下图的Linear Projection的映射层,映射到LLM token emb的空间,让LLM也能感知搜推的协同信号。 上述LLM4SR范式存在两个问题: 维度坍缩:id-based训出来的id emb dim比较小(如64),LLM token emb dim比较大(如4096),在由id emb通过Linear Projection映射到toen emb的过程中,虽然64映射到4096空间了,但扩维后的矩阵存在低秩问题,即还是只利用了4096中的64维的空间。 论文中,作者分两种情况进行了分析,如果Linear Projection只是一个线性层的话,通过公式推导能得出上述结论;如果Linear Projection包含非线性变换,作者通过实验分析也发现了维度坍缩的现象。 灾难遗忘:除了使用id-based模型产出的id emb,LLM4SR也常用多模态模型产出item emb表征,然后转换成semantic id输入到LLM4SR中。在这种情况下,产出的semantic id通过会遗忘多模态item emb的信息,导致下游LLM4SR的效果不佳。 论文中,作者用公式9来衡量semantic id保留pretrain多模态emb的信息量。具体来说,如果行为流中的商品序列是{A,B,C,D},target item是E。使用pretrain多模态emb能计算出E和A~D的相似度,例如相似度<E,A> > <E,B>。如果将pretrain多模态emb转换成semantic id,然后由semantic id恢复出新的A~E的emb之后,再计算E和A~D的相似度,如果仍然有<E,A> > <E,B>,则认为一致(concordant),否则不一致(disconcordant)。这个分析方法挺好的,通过这个指标能估算出转换成semantic id之后,仍然保留原有pretrain多模态emb对搜推场景的序关系的保留程度。 作者发现,转换成semantic id之后,信息只保留了37.14%;进一步,如果semantic id是在下游任务中端到端训练的,则信息只保留了5.5%,也就是说94.5%的pretrain emb的序的信息都丢掉了,也就是灾难遗忘。 Semantic id构建方法 3套emb来源,一套id-based经典搜推模型产出的包含协同信号的emb,另外两套是LLM2CLIP产出的多模态文本和图片emb。作者提到传统CLIP对长文本处理能力较弱,所以升级到LLM2CLIP,能更好地处理长文本。 Semantic id构建方法是经典的RQ-VAE的方法,但有如下两个改进点: 将emb的重构loss由MSE升级成MMD (maximum mean discrepancy),MSE是计算原始emb和重构emb的欧式距离的误差,而MMD是计算两个分布的diff,实验表明能MMD比MSE能保留更多的pretrain多模态emb信息(即上述公式9),保留44.36% 对量化后的emb做了对齐,因为LLM2CLIP本身进行了图文模态的对齐,所以文中只新增了id emb分别和文本、图片模态的对齐 此外,还有一点论文没提但可能和常规RQ-VAE不同之处,就是原始emb在进行RQ-VAE之前,有一个Encoder升维的操作,在重构loss前对应有一个Decoder降维的操作,而semantic id量化恢复emb是Decoder之前的那个。这一升一降,估计也有助于缓解维度坍缩。 ...

October 4, 2025 · 1 min

公告

博客数据恢复中,敬请期待! 测试图片: 测试代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 // Necessary header files for input output functions #include <iostream> using namespace std; // main() function: where the execution of // C++ program begins int main() { // This statement prints "Hello World" cout << "Hello World"; return 0; } 测试数学公式: This is an inline \(a^*=x-b^*\) equation. ...

August 15, 2025 · 1 min

CS224N(2.21)Transformers and Self-Attention For Generative Models

今天介绍大名鼎鼎的Transformer,它于2017年出自谷歌的论文《Attention Is All You Need》(https://arxiv.org/pdf/1706.03762.pdf),用Attention实现机器翻译模型,并取得了新的SOTA性能。 传统的机器翻译模型一般是结合RNN和Attention,可以看我之前的博客介绍:CS224N(1.31)Translation, Seq2Seq, Attention。虽然RNN+Attention的组合取得了不错的效果,但依然存在一些问题。由于RNN是序列依赖的模型,难以并行化,训练时间较长;且当句子很长时由于梯度消失难以捕捉长距离依赖关系。虽然相继推出的LSTM和GRU能一定程度上缓解梯度消失的问题,但这个问题依然存在。而且LSTM和GRU难以解释,我们根本不知道当前timestep依赖远的词多一点还是近的词多一点。 Transformer的思想很激进,它完全抛弃了RNN,只保留Attention,从其论文标题可见一斑。RNN无法并行化的根本原因是它的正向和反向传播是沿着句子方向(即水平方向),要想实现并行化,肯定不能再走水平方向了。于是,Transformer完全抛弃水平方向的RNN,而是在垂直方向上不断叠加Attention。由于每一层的Attention计算只和其前一层的Attention输出有关,所以当前层的所有词的Attention可以并行计算,互不干扰,这就使得Transformer可以利用GPU进行并行训练。 具体来说,Transformer的结构如下图所示。我们知道end2end的机器翻译模型一般都是Encoder+Decoder的组合,Encoder对源句子进行编码,将编码信息传给Decoder,Decoder翻译出目标句子。Transformer也不例外,下图左边即为Encoder,右边即为Decoder。 Encoder的每一层有两个子层组成,包括Self-Attention和Feed-forward neural network (FFNN)。FFNN就是常规的全连接网络,没什么可说的,下面重点介绍Self-Attention。 Encoder Self-Attention的结构如下图所示,由于此时是Encoder阶段,对于每个词,都能看到句子中所有其他的词(对应到RNN里面就是可以用双向的RNN)。假设我们想要抽取第二个词”represent”的特征表示。首先,对第二个词的词向量\(e_2\)进行线性变换,即乘以矩阵\(matmul_Q\),得到Query,这就是标准Attention中的Query。其次,对周围所有的其他词,比如\(e_1\),也进行线性变换,变换矩阵为\(matmul_K\),得到很多的Key。然后,Query和所有Key做点积,并用softmax归一化,得到了Query在周围词上的Attention score distribution。接着,周围词乘以另一个线性变换矩阵\(matmul_V\),变换为Value。最后,Value和Attention score distribution进行加权求和,并加上\(e_2\)自己,送给FFNN。图中右下角的公式中的分母只是个缩放因子。 回顾一下,一个标准的Attention包括三个向量:Q、K、V,其中Q为用来查询的Query,K表示被查询的Key,V表示被查询的Value。其中的K和V来源相同,只是经过了不同的变换。形象描述就是:计算Q在K上分配的注意力\(QK^T\),然后从V中取出这部分注意力的值\(softmax(\frac{QK^T}{\sqrt{d_k}})V\)。 Self-Attention的优点。因为每个词都和周围所有词做attention,所以任意两个位置都相当于有直连线路,可捕获长距离依赖。而且Attention的可解释性更好,根据Attention score可以知道一个词和哪些词的关系比较大。易于并行化,当前层的Attention计算只和前一层的值有关,所以一层的所有节点可并行执行self-attention操作。计算效率高,一次Self-Attention只需要两次矩阵运算,速度很快。 Transformer的Decoder部分每一层有三个子层组成,包括Self-Attention、Encoder-Decoder Attention和FFNN。Decoder的Self-Attention如下图所示,和Encoder的Self-Attentoin非常像,只不过当要Decoder第二个词时,用黑框蒙住了第三、四个词的运算(设置值为-1e9)。因为对于机器翻译来说,Encoder时能看到源句子所有的词,但是翻译成目标句子的过程中,Decoder只能看到当前要翻译的词之前的所有词,看不到之后的所有词,所以要把之后的所有词都遮住。所以这个Attention也叫Masked Self-Attention。这也说明Transformer只是在Encoder阶段可以并行化,Decoder阶段依然要一个个词顺序翻译,依然是串行的。 不要忘了我们的任务是机器翻译,Decoder Self-Attention只用到了翻译出来的目标句子的前缀信息,还没用到源句子的信息,这部分就在Encoder-Decoder Attention中。前面说了对于源句子,通过Encoder的Self-Attention+FFNN,源句子的每个词都有一个输出向量,这些输出向量作为Encoder-Decoder Attention的Keys和Values,而从目标句子当前要翻译的词的Decoder Self-Attention出来的向量就是Encoder-Decoder Attention的Query。从下图可以看到,Encoder上面出来指向右边Multi-Head Attention的两个箭头就是Keys和Values,而从下面出来指向Multi-Head Attention的一个箭头就是Query。Encoder-Decoder Attention的作用就是看看当前要翻译的词在源句子中各个词上的注意力情况。 我们知道Attention机制是位置无关的,因为对于每个词,它都和句子中的所有词直连求Attention score,跟词在句子中的位置没有关系。但是句子作为一种线性结构,词在句子中的顺序对句子的含义至关重要。为了考虑词的位置信息,词在输入Attention前,把词向量和词在句子中的位置Positional Encoding加起来,得到一个新的向量,输入到Attention中,如上图所示。这个Positional Encoding可通过公式计算得到,这里不展开。 上图的Attention前面都有一个修饰词Multi-Head,也就是下图的Parallel attention heads。前面提到一个标准的Attention包括三个向量Q、K、V,它们分别由原始的查询向量和特征向量乘以矩阵\(matmul_Q\)、\(matmul_K\)、\(matmul_V\)得到。如果一个词在计算Attention时,选用多个不同的\(matmul_Q\)、\(matmul_K\)、\(matmul_V\),得到的Attention输出向量也就不同了,这正好可以用来表示一个词在句子中的不同作用。比如句子“华为是一家中国的公司”中的“华为”,它的语义是一家公司,它在句子中的成分是主语,也就是说一个词至少有其语义信息和句法信息,如果只用一套\(matmul_Q\)、\(matmul_K\)、\(matmul_V\),则只能得到一种含义,如果设置多套\(matmul_Q\)、\(matmul_K\)、\(matmul_V\),则能提取到这个词更多的信息。于是,在对每个词进行Attention时,都会设置多套\(matmul_Q\)、\(matmul_K\)、\(matmul_V\),提取多个Attention输出向量,然后拼接起来,这就是Multi-Head Attention,或者说Parallel attention heads。我个人理解多套\(matmul_Q\)、\(matmul_K\)、\(matmul_V\)相当于CNN中不同的kernal,相当于不同的特征提取器。 课上还介绍了利用Transformer生成图片和音乐的应用,感兴趣的同学可以搜索相关论文看一看。 有关Transformer的介绍,还可参考如下三个链接: http://jalammar.github.io/illustrated-transformer/ https://zhuanlan.zhihu.com/p/48508221 https://zhuanlan.zhihu.com/p/44121378

March 4, 2020 · 1 min

CS224N(2.19)Contextual Word Embeddings

今天介绍几种新的词向量学习方法,在此之前,建议大家看看我关于word2vec或GloVe等传统词向量的介绍:CS224N(1.8)Introduction and Word Vectors。 传统词向量,比如word2vec,它在训练阶段学习到一个词的向量表示之后,在下游的各种NLP任务中,这个词向量不再变动了。也就是说传统词向量的特点是,对一个词只学习一个词向量,且在具体任务中固定不变。传统词向量有两个主要的不足: 难以表达一词多义。一个词在不同的上下文语境中可能表示不同的含义,比如“苹果”在“苹果真好吃”和“苹果手机很好用”这两个句子中表示不同的含义,但word2vec学习到的“苹果”词向量只有一个,也就是说下游任务对于这两个句子用的是同一个词向量。虽然word2vec的词向量可能同时包含了这两个含义,但它把这两个含义糅合到一个向量中了,导致在“苹果真好吃”中可能引入了“苹果手机”的干扰因素,在“苹果手机很好用”中引入了“吃的苹果”的干扰因素。总之就是,word2vec学习到的词向量粒度较粗,向量固定不变,无法根据具体的上下文语境进行改变。 难以表达不同的语法或语义信息。一个词,即使是同一个意思,在语法或语义上也可能充当不同的角色,比如“活动”这个词,既可以做名词、也可以做动词,既可以做主语、也可以做谓语等。但word2vec对一个词只给出一个词向量,无论这个词在句子中充当什么角色,词向量都是一样的。虽然word2vec训练时可能已经学到了一个词的不同语法或语义特征,但它把这些信息糅合到一个向量中了,也就是粒度较粗的问题。 其实上述两点暴露出来的word2vec的不足,本质上是同样的两个原因:1. 词向量是静态的,无法根据上下文进行调整;2. 词向量表示只有一个向量,糅合了太多信息,粒度较粗。 下图中的word type表示一个相同的词,比如“苹果”;word token表示同一个word type在不同上下文的具体实例,比如“苹果真好吃”和“苹果手机很好用”中的“苹果”就是两个不同的word token。word type和word token有点类似于类和实例的关系。 2018年艾伦人工智能研究所提出了ELMo: Embeddings from Language Models,即从语言模型中学习词向量的方法,它的原文标题为Deep contextualized word representations(https://www.aclweb.org/anthology/N18-1202.pdf),即深度的上下文词向量表示。ELMo很好地解决了上述传统词向量的两个不足,ELMo对一个词的表示由多个向量组成,并且每个向量的权重在具体的上下文中动态更新,由此不但粒度更细,而且能根据上下文动态调整一个词的最终词向量。使用ELMo词向量,作者在很多NLP任务上刷新了SOTA,在当年引起了很大的轰动。 ELMo有三个特点: 学习的是word token的词向量,根据上面的定义,word token与具体的上下文有关,不再是静态的word type的词向量; 使用很长的上下文进行学习,而不像word2vec一样使用较小的滑动窗口,所以ELMo能学到长距离词的依赖关系; 使用双向的语言模型进行学习,并使用网络的所有隐藏层作为这个词的特征表示。 下面介绍ELMo具体的训练过程,以下截图来自台湾大学李宏毅老师的教学视频。 首先,既然word2vec使用滑动窗口只能学习到局部特征,那么ELMo就用RNN来建模长距离的依赖关系。如下图所示,ELMo使用双向语言模型bi-LM学习每个词的特征。我们知道,语言模型是给定一个句子前缀,预测下一个可能出现的词,也就是说常规的语言模型是只知道t时刻前的信息,不知道t时刻之后的信息,即通常都是单向的。而ELMo则使用了bi-LM,比如下图我们要学习“退了”这个词的特征,在前向网络中,模型学到了在给定上文的情况下,“退了”的隐藏层特征;在反向网络中,模型学到了在给定下文的情况下,“退了”的隐藏层特征。最后,ELMo把两个方向的隐藏层特征拼起来,作为bi-LM学到的“退了”这个词的特征表示。 为了学到更多的特征,ELMo对双向RNN进行堆叠,每增加一层就能多学习到2个特征表示(一正一反,下图把这两个向量拼接起来作为一个整体向量h)。 ELMo文中只使用了两层的双向LSTM抽取特征,所以对一个词能抽取到4个特征表示,即下图中的h1和h2(每个h包含一正一反特征向量组合)。 在使用ELMo词向量时,每个词的最终词向量是所有隐藏层特征向量h的加权求和,系数是α。这个系数是根据词在不同的上下文中学习得来的。ELMo文章分析发现,不同的NLP任务学到的系数不尽相同,比如在Coref和SQuAD任务中,第一层的系数更大。有可能ELMo在第一层学到的是词的句法特征,第二次学到的是更高级的语义特征。有点类似于CNN中在浅层学到点、线、转角,在高层学到轮廓等高级特征。 ELMo的形式化表示如下图所示。假设堆叠的bi-LSTM有L层,则每一层都能学到前向特征\(\underset{h_{k,j}^{LM}}{\rightarrow}\)和反向特征\(\underset{h_{k,j}^{LM}}{\leftarrow}\),这两个组合起来就是\(h_{k,j}^{LM}\)(也就是上图的\(h_i\))。下图的ELMo还有个\(x_k^{LM}\),它是bi-LM的词向量输入,这相当于词最原始的输入向量,ELMo使用char-CNN抽取一个词的原始输入向量,和上一课提到的Subword model类似,这里不展开。下图j=0时的特征就是\(x_k^{LM}\) 。 所以,对于词\(k\),ELMo得到的完整词向量是\(R_k\),它其实是这个词的一系列特征向量的组合,它还不是这个词最终的词向量,因为最终的词向量要在具体的NLP任务中根据上下文来定。词\(k\)在某个任务task中的词向量\(ELMo_k^{task}\)如下图所示,它等于对所有层的特征向量的加权求和,权重\(s_j^{task}\)(即上图的α)根据当前任务动态学习得到。最终还会有一个参数\(\gamma^{task}\),控制ELMo词向量对任务的贡献程度。 不同层抽取的特征不一样,ELMo只使用了两层bi-LSTM,如果堆叠更多层的话,估计能学到更多有意思的特征。 ELMo词向量的使用方法。在下游的NLP任务中,既可以把ELMo词向量作为输入层特征,也可以将其拼接到隐藏层,反正都需要学习参数\(s_j^{task}\)和\(\gamma^{task}\)。 性能方面,ELMo刷新了很多NLP任务的SOTA,大概能提高3个百分点。 个人理解word2vec和ELMo的本质区别。其实两者在训练阶段都考虑了上下文,只不过word2vec使用的是滑动窗口,只能学习局部特征,而ELMo使用RNN,能学到长距离特征。word2vec学到embedding之后固定成一个向量了,在下游NLP任务中不再变动;而ELMo训练完之后得到这个词的多个特征向量(词的隐含特征表示,粒度更细),且在下游NLP任务中会根据上下文动态组合这些特征向量,得到在这一上下文中的词向量表示(针对性更强)。 其实,仔细想想的话,这个本质区别也没有那么大,虽然word2vec训练到的词向量只有一个,且固定了,但词向量的维度如果够大的话,可以用不同维度来表示一词多义呀。而且用到下游NLP任务时,词向量不同维度的权重也可以不一样啊,不就相当于ELMo的不同\(s_j^{task}\)吗?虽然如此,可能还是不如ELMo的多个隐藏层向量,一方面是经过隐藏层的特征抽取,另一方面是毕竟ELMo出来的特征向量有2L+1个,仅维度上就比word2vec多很多,效果好是理所应当的。 ELMo的作者在2017年发过TagLM的工作,和ELMo类似,被称为Pre-ELMo,感兴趣的可以阅读原文(https://arxiv.org/abs/1705.00108)。ELMo是把语言模型的隐藏层抽取出来作为词的特征向量,2017年的CoVe词向量是把机器翻译过程中的隐藏层提取出来作为词的特征向量,但效果没ELMo好,感兴趣的可以阅读原文(https://arxiv.org/abs/1708.00107)。 同样在2018年,OpenAI和GoogleAI借助Transformer模型,提出了更加强大的上下文词向量学习方法GPT和BERT。Transformer是为了解决RNN无法并行化的问题,提出Attention is all you need(https://arxiv.org/abs/1706.03762)。以前我们提到Attention用来提升RNN的性能,Transformer更加激进,直接不要RNN,只留下Attention,然后堆叠网络深度,使得其可以和CNN一样并行化,使用GPU之后可以大大加速训练过程。下节课将详细介绍Transformer的内容,这里我们只需要知道Transformer是一个强大的seq2seq(Encoder-Decoder)模型。 BERT就是借助Transformer学习上下文词向量的方法,它的全称是BERT (Bidirectional Encoder Representations from Transformers): Pre-training of Deep Bidirectional Transformers for Language Understanding。 ...

February 24, 2020 · 1 min

CS224N(2.14)Subword Models

今天介绍一下subword(子词)模型。之前介绍的NLP模型都是基于word的,对于英文来说是一个个单词,对于中文来说是一个个词语(需要分词)。不过,最近几年,subword模型多起来了,这就是我们今天要介绍的内容。 对于英文来说,文字的粒度从细到粗依次是character, subword, word,character和word都很好理解,subword相当于英文中的词根、前缀、后缀等,如unfortunately中的un、ly、fortun(e)等就是subword,它们都是有含义的。对于中文来说,只有两层,character和subword是同一层,表示单个的字,而word表示词语。 之前介绍的基于word的模型,存在out of vocabulary(OOV,未登录词)的问题。以英文为例,现存的英文单词数量太多了,随便加个前缀、后缀,变个时态什么的都变成新的单词了,所以英文单词的词典数量特别大,而且有很多低频稀疏词。很多模型在训练时都会去掉低频词,只保留高频词。那么这就存在一个问题,如果预测时遇到未登录词,则模型不认识,出现OOV的问题。 为了解决这个问题,一开始想到的是采用character级别的模型,即对26个字母训练word2vec,每个词由其字母的embedding拼接或者求平均得到。但是character级别的模型效果相比于word级别的模型效果差不多,并没有显著优势。而且如果用RNN来训练character级别的模型也有它的问题,就是训练起来非常慢。特别是对英文来说,原来的一个word,现在变成了七八个character,时间步长增加了很多,训练和预测都更久了,而且梯度消失(爆炸)的问题也会更严重。 后来,人们就想用subword模型作为character和word的折中模型。subword模型主要有两种,它们都能解决未登录词(OOV)的问题,如下图所示。第一种是模型结构和word模型完全一样,只不过把word换成了subword。第二种则是word和character模型的杂交模型。 对于第一种模型,关键问题是怎样得到subword。前面提到character的粒度太细,虽然能解决OOV问题,但效果并不是太好;word模型的word数量太多,存在大量稀疏word,删掉它们又会导致OOV问题,所以打算用subword模型。那么,怎样提取一个单词的subword呢?前面提到,unfortunately中的un、ly、fortun(e)等就是subword,但是对每个词都这样提取subword的话,费时费力不说,也不够智能。 有人就想出了用BPE算法来提取高频subword。BPE,全称是byte pair encoder,是上世纪提出的一种压缩算法,其核心思想是不断用字母表中不存在的char来代替最高频的char pair。举个例子,对于字符串aaabdaaabac,其字符串中最开始只出现了a/b/c/d这四个char;统计所有char pair,最高频的是aa,用不在字母表中的另一个字符Z代替aa,则原字符串变成了ZabdZabac,字母表变成了a/b/c/d/Z;如此不断进行下去,直到字母表大小达到一定的阈值,或者所有连续的char pair的频数都等于1了。关于BPE算法的进一步介绍请看这里:https://zhuanlan.zhihu.com/p/38130825。 第一种模型就是用BPE算法来得到高频subword的。比如下图的例子,语料集D中出现了5个low,2个lower等等。最开始,字母表V中是语料集中出现的所有单个字母的集合{l,o,…,d}。然后,发现e s这个char pair出现次数最多,将其作为一个subword加入到V中,同时将D中的es合并看作一个新的char。接着统计发现es t这个char pair(此时es已经是一个char了)出现次数最多,将其作为一个subword加入到V中,如此进行下去。发现没有,我们自动从D中提取了est这个subword,而est就是最高级的后缀。也就是说BPE算法自动提取到了英文的前缀、后缀等subword信息,完全避免了之前费时费力地从unfortunately中手工提取un、ly、fortun(e)的过程。这种方法也能解决未登录词问题,但是粒度又不至于太细。一方面是因为最开始的时候D中原始出现的单个字母都在V中,另一方面,由V中字母组成的未出现词也能由subword构成,比如下图中虽然less没有出现在D中,但可以由l es s这3个subword组成,而这3个subword是在最终的V中的。 得到高频subword作为V之后,后续在进行NLP任务时,encoder的时候查一下V,把char pair替换为新字符;decoder的时候查一下V,把新字符替换回原来的char pair。 最近比较流行的BERT,字典中既有相对比较常见的词,对于不太常见的词则用subwords/wordpieces来表示。 第二种被称为杂交模型的方法就相对简单了。这种方法是Manning老师提出来的,它就是在D中有这个word时就用word embedding,没有的时候就用char embedding来学习word embedding,非常简单。 fasttext就是skipgram+n-gram,一个词的embedding=组成这个词的n-gram的embedding的加权求和,所以fasttext也能解决OOV问题。

February 17, 2020 · 1 min

明朝那些事儿(伍)——帝国飘摇

严嵩倒台后,徐阶成为新的内阁首辅,把持朝政。某种程度上,徐阶和严嵩是一类人,也是独揽大权,但有一点不同的是,严嵩贪污不干活,而徐阶真的会干实事。徐阶入阁后,又推举了高拱入阁。高拱当时是嘉靖第三子朱载垕(裕王)的讲官,徐阶估计裕王未来会继承皇位,现在提拔高拱,等裕王上位后,自己退休后不至于会被清算。但是,高拱并不领情,他觉得裕王迟早要继承皇位,自己迟早要入阁,和徐阶的提拔没啥关系。高拱不但不感激徐阶,还跟徐阶对着干。于是,徐阶和高拱的斗争开始了。 此时的张居正只是翰林院的一个小官,徐阶也有意提拔他。当得知嘉靖驾崩的消息后,徐阶只叫来了张居正,让张居正拟写嘉靖的遗诏。凭借这份遗诏,徐阶的威望达到了顶点,高拱的气焰被打压下去,张居正和徐阶结为同盟。 由于嘉靖的前两个儿子都夭折了,嘉靖死后,裕王朱载垕继承皇位,史称隆庆皇帝。朱载垕继位后,采取相对宽松的政治制度,而且不怎么管理朝政,把国家大事都交给内阁处理。此时的内阁成员有徐阶、高拱、张居正等人。 内阁成员中,徐阶把高拱挤回家了。后来,徐阶觉得做官做累了,主动请辞回家了。没过多久,高拱又通过各种渠道回到内阁,并借海瑞(明朝第一清官)弹劾徐阶的儿子,弄得徐阶妻离子散,差点家破人亡。事实上,高拱和徐阶也没啥区别,只是换个人当首辅罢了。高拱掌权后,开启了历时三年的高拱改革,史称“隆庆新政”。 新政也没啥新鲜玩意,不外乎休养生息、努力干活之类的。高拱执政这几年,国泰民安、国运蒸蒸日上。值得一提的是,在此期间,明朝开启了与蒙古鞑靼之间的封贡互市,也就是明朝给鞑靼封官,鞑靼给明朝进贡,明朝回赠金银珠宝,同时开放与鞑靼的市场贸易。封贡互市之后,折腾了两百多年的明蒙战争终于落下帷幕,此后近百年中,双方未再发生大规模战争。 内阁成员中,徐阶走了之后,高拱和张居正又闹起来了,最后张居正借隆庆皇帝驾崩时发生的事把高拱挤走了。事情经过是这样的,朱载垕只当了六年皇帝就驾崩了,他的儿子朱翊钧继位,史称万历皇帝。由于万历皇帝继位时才10岁,高拱在某个场合不小心说了一句藐视皇帝的话“十岁太子,如何治天下”。张居正捕风捉影,对高拱的这句话添油加醋,大做文章,说高拱是藐视皇帝,有专权跋扈之嫌。最后,10岁的万历皇帝下令,把高拱削职为民,立即回老家,高拱的命运就此终结。自此,张居正登上历史舞台,听野史说他和万历皇帝的母亲有一腿,不知真假。由于当时万历年幼,张居正又和万历他妈有关系,于是国家大事基本是张居正说了算。 张居正掌权之后,实行了闻名的“张居正改革”。改革主要有两个内容,一条鞭法和考成法。一条鞭法最主要的内容是颁布统一规定,全国税收由实物税变为货币税,也就是说以后税收不收东西了,统一改收钱。一条鞭法以前,各地的税收都是实物税,即收税是收实物,比如收上来棉花、粮食之类的。实物税既不利于实物管理,又容易被各地官员做手脚进行贪污。一条鞭法之后,皆大欢喜,朝廷收上来的是白花花的银子,老百姓也不用听凭官员糊弄。考成法是针对官员的考勤制度,即要求所有大小官员,年初制定年度计划,年末一一对照,据此评定绩效,赏罚分明。于是,官员们一改往日作风,认真干活,兢兢业业,只求年度弄个考核合格,工作效率得以大幅提升。在张居正的严厉督促下,官员们勤勤恳恳,国家财政收入不断上升,明朝国势蒸蒸日上。 明朝内政蒸蒸日上的同时,明朝军队的实力也稳步加强,因为两位猛人的存在。即之前的抗倭名将戚继光,现在被调到蓟州当总兵,抵御蒙古入侵;辽东总兵李成梁,当时明朝最优秀的骑兵将领,手下有一支精锐的骑兵,人称“辽东铁骑”。 事实上,张居正虽然是很杰出的政治家,但爬到他这个位置上,也不是什么老实人。张居正掌权后,对他曾经的敌人、学生和盟友都下过狠手。此外,他的个人作风也有问题,作威作福,自己乘坐的娇子居然要32个人抬,轿子上什么都有,连卫生间都有。 与蒸蒸日上的帝国相反的是张居正蒸蒸日下的身体,万历十年,张居正去世,年五十八,张四维继任内阁首辅。张居正死后,无数人开始弹劾张居正。由于万历慢慢长大,发现自己的权力被张居正夺走,多少对张居正心存芥蒂,在众人的弹劾下,万历对张居正进行抄家,他的长子自杀,次子被充军,下场不得不说凄惨啊。张居正去世后,除一条鞭法,其他措施都被废除,张居正改革以失败告终。 张居正死后,万历正式执政,一直勤奋工作,日夜不息。但是万历十五年(1587)发生了三件不大不小的事:戚继光去世、海瑞去世、万历皇帝开始消极怠工不理朝政,冥冥之中预示着明朝国势的衰败。 万历二十年至二十六年爆发的抗倭援朝战争,即明朝为了援助朝鲜,抗击倭寇的战争。事情的起因是这样的,日本战国时期,丰臣秀吉统一日本,为了获得更多的土地,丰臣秀吉打算先进攻朝鲜,后进攻明朝。由于朝鲜国内承平日久、武备松弛,军队战斗力实在是太差了,很快朝鲜沦陷。明朝为了遏制日本的进攻,打算出兵援助朝鲜。抗倭援朝战争分为两个阶段,第一阶段是明朝派出李成梁长子李如松带领的辽东铁骑和吴惟忠带领的戚家军二代,战争以明朝胜利结束,但明军损失也比较大,而且远离明朝大陆,补给跟不上,明朝和倭寇展开谈判。谈判过程是,明朝派了一个大忽悠沈惟敬去和丰臣秀吉谈判,丰臣秀吉提出了一堆无理的要求,沈惟敬居然答应了,但回国后没和明朝讲,明朝以为丰臣秀吉诚服了,于是同意和丰臣秀吉讲和。但是没多久,事情败露,丰成秀吉恼羞成怒,二次举全国之力出兵朝鲜。由于在此期间,李如松在与蒙古的战争中不幸阵亡,明朝派出以麻贵为首的军队再次出征。第二阶段的战争互有胜负,局势陷入胶着状态,后来,丰臣秀吉在日本国内因病去世,日军全部撤离朝鲜,抗倭援朝战争结束。

February 15, 2020 · 1 min