<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>推荐系统相关博客 on 清雨影的Blog</title><link>http://blog.tsingjyujing.com/ml/recsys/</link><description>Recent content in 推荐系统相关博客 on 清雨影的Blog</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Thu, 06 Nov 2025 00:00:00 +0900</lastBuildDate><atom:link href="http://blog.tsingjyujing.com/ml/recsys/index.xml" rel="self" type="application/rss+xml"/><item><title>关于AA测试和AB测试的一些思考</title><link>http://blog.tsingjyujing.com/ml/recsys/ab_testing/</link><pubDate>Sat, 19 Sep 2020 00:00:00 +0900</pubDate><guid>http://blog.tsingjyujing.com/ml/recsys/ab_testing/</guid><description>&lt;h1 id="关于aa测试和ab测试的一些思考"&gt;关于AA测试和AB测试的一些思考&lt;a class="anchor" href="#%e5%85%b3%e4%ba%8eaa%e6%b5%8b%e8%af%95%e5%92%8cab%e6%b5%8b%e8%af%95%e7%9a%84%e4%b8%80%e4%ba%9b%e6%80%9d%e8%80%83"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;h2 id="起因"&gt;起因&lt;a class="anchor" href="#%e8%b5%b7%e5%9b%a0"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;一般的AA/AB测试都怎么做呢？正常来说，取一部分用户，然后把用户分成2组（也可以是多组，本文中我们只讨论最典型的2组的情况），在一段时间的运行以后，比较其结果。&lt;/p&gt;</description></item><item><title>随想： BPR Loss 与 Hinge Loss</title><link>http://blog.tsingjyujing.com/ml/recsys/bpr_and_hinger/</link><pubDate>Mon, 03 Aug 2020 00:00:00 +0900</pubDate><guid>http://blog.tsingjyujing.com/ml/recsys/bpr_and_hinger/</guid><description>&lt;h1 id="随想-bpr-loss-与-hinge-loss"&gt;随想： BPR Loss 与 Hinge Loss&lt;a class="anchor" href="#%e9%9a%8f%e6%83%b3-bpr-loss-%e4%b8%8e-hinge-loss"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;在之前的文章里，我们在&lt;a href="../ranknet/"&gt;加速Ranknet&lt;/a&gt;的时候意外的得到了BPR Loss：&lt;/p&gt;&#10;&lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;math xmlns="http://www.w3.org/1998/Math/MathML" display="block"&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;msub&gt;&lt;mi&gt;L&lt;/mi&gt;&lt;mi&gt;ω&lt;/mi&gt;&lt;/msub&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;munder&gt;&lt;mo&gt;∑&lt;/mo&gt;&lt;mrow&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mo separator="true"&gt;,&lt;/mo&gt;&lt;mi&gt;j&lt;/mi&gt;&lt;mo&gt;∈&lt;/mo&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;/mrow&gt;&lt;/munder&gt;&lt;mrow&gt;&lt;mi&gt;l&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mo stretchy="false"&gt;(&lt;/mo&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;g&lt;/mi&gt;&lt;mi&gt;m&lt;/mi&gt;&lt;mi&gt;o&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;mi&gt;d&lt;/mi&gt;&lt;mo stretchy="false"&gt;(&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;i&lt;/mi&gt;&lt;/msub&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;msub&gt;&lt;mi&gt;s&lt;/mi&gt;&lt;mi&gt;j&lt;/mi&gt;&lt;/msub&gt;&lt;mo stretchy="false"&gt;)&lt;/mo&gt;&lt;mo stretchy="false"&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;/mrow&gt;&lt;annotation encoding="application/x-tex"&gt;&#10;L_{\omega} = - \sum_{i,j \in S}{log(sigmoid(s_i-s_j))}&#10;&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class="katex-html" aria-hidden="true"&gt;&lt;span class="katex-base"&gt;&lt;span class="katex-strut" style="height:0.8333em;vertical-align:-0.15em;"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;L&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist" style="height:0.1514em;"&gt;&lt;span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"&gt;&lt;span class="pstrut" style="height:2.7em;"&gt;&lt;/span&gt;&lt;span class="katex-sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight" style="margin-right:0.0359em;"&gt;ω&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist" style="height:0.15em;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace" style="margin-right:0.2778em;"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace" style="margin-right:0.2778em;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="katex-base"&gt;&lt;span class="katex-strut" style="height:2.4804em;vertical-align:-1.4304em;"&gt;&lt;/span&gt;&lt;span class="mord"&gt;−&lt;/span&gt;&lt;span class="mspace" style="margin-right:0.1667em;"&gt;&lt;/span&gt;&lt;span class="mop op-limits"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist" style="height:1.05em;"&gt;&lt;span style="top:-1.8557em;margin-left:0em;"&gt;&lt;span class="pstrut" style="height:3.05em;"&gt;&lt;/span&gt;&lt;span class="katex-sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;span class="mpunct mtight"&gt;,&lt;/span&gt;&lt;span class="mord mathnormal mtight" style="margin-right:0.0572em;"&gt;j&lt;/span&gt;&lt;span class="mrel mtight"&gt;∈&lt;/span&gt;&lt;span class="mord mathnormal mtight" style="margin-right:0.0576em;"&gt;S&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="top:-3.05em;"&gt;&lt;span class="pstrut" style="height:3.05em;"&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="mop op-symbol large-op"&gt;∑&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist" style="height:1.4304em;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace" style="margin-right:0.1667em;"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal" style="margin-right:0.0197em;"&gt;l&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal" style="margin-right:0.0359em;"&gt;g&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;span class="mord mathnormal" style="margin-right:0.0359em;"&gt;g&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist" style="height:0.3117em;"&gt;&lt;span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"&gt;&lt;span class="pstrut" style="height:2.7em;"&gt;&lt;/span&gt;&lt;span class="katex-sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist" style="height:0.15em;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace" style="margin-right:0.2222em;"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace" style="margin-right:0.2222em;"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;s&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist" style="height:0.3117em;"&gt;&lt;span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"&gt;&lt;span class="pstrut" style="height:2.7em;"&gt;&lt;/span&gt;&lt;span class="katex-sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight" style="margin-right:0.0572em;"&gt;j&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist" style="height:0.2861em;"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose"&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;p&gt;我们说过，Ranknet不一定用NN，任何可微的模型都可以塞到后端去。其实我们一直没有用贝叶斯的观点来看Ranknet，只是给分数的差值加了一层 sigmoid 之后使用 二元交叉熵损失函数，四舍五入一个亿…啊不对…等于是Logistic回归了，结果就导出了BPR Loss一样的形式。&lt;/p&gt;</description></item><item><title>资料收集</title><link>http://blog.tsingjyujing.com/ml/recsys/collection/</link><pubDate>Wed, 03 Jun 2020 00:00:00 +0900</pubDate><guid>http://blog.tsingjyujing.com/ml/recsys/collection/</guid><description>&lt;h1 id="资料收集"&gt;资料收集&lt;a class="anchor" href="#%e8%b5%84%e6%96%99%e6%94%b6%e9%9b%86"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;h2 id="博客"&gt;博客&lt;a class="anchor" href="#%e5%8d%9a%e5%ae%a2"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="https://zhuanlan.zhihu.com/p/142958834"&gt;见微知著，你真的搞懂Google的Wide&amp;amp;Deep模型了吗？&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://zhuanlan.zhihu.com/p/143155437"&gt;知识蒸馏在推荐系统的应用&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://zhuanlan.zhihu.com/p/142086309"&gt;Ctr 预估之 Calibration&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://zhuanlan.zhihu.com/p/141517705"&gt;推荐系统中稀疏特征Embedding的优化表示方法&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://zhuanlan.zhihu.com/p/66514492"&gt;Learning to Rank学习笔记&amp;ndash;ListwiseRank&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://zhuanlan.zhihu.com/p/143763320"&gt;推荐系统 embedding 技术实践总结&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="开源项目"&gt;开源项目&lt;a class="anchor" href="#%e5%bc%80%e6%ba%90%e9%a1%b9%e7%9b%ae"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/wzhe06/CTRmodel"&gt;wzhe06/CTRmodel&lt;/a&gt;:Spark上的CTR模型&#10;&lt;ul&gt;&#10;&lt;li&gt;Naive Bayes&lt;/li&gt;&#10;&lt;li&gt;Logistic Regression&lt;/li&gt;&#10;&lt;li&gt;Factorization Machine&lt;/li&gt;&#10;&lt;li&gt;Random Forest&lt;/li&gt;&#10;&lt;li&gt;Gradient Boosted Decision Tree&lt;/li&gt;&#10;&lt;li&gt;GBDT + LR&lt;/li&gt;&#10;&lt;li&gt;Neural Network&lt;/li&gt;&#10;&lt;li&gt;Inner Product Neural Network (IPNN)&lt;/li&gt;&#10;&lt;li&gt;Outer Product Neural Network (OPNN)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/jrzaurin/pytorch-widedeep"&gt;jrzaurin/pytorch-widedeep&lt;/a&gt;:Pytorch实现的Deep &amp;amp; Wide&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/allegro/allRank"&gt;allegro/allRank&lt;/a&gt;: Pytorch 实现的 Learning To Rank&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/haowei01/pytorch-examples"&gt;haowei01/pytorch-examples&lt;/a&gt;: Pytorch的，L2R，CF算法的例子。&lt;/li&gt;&#10;&lt;li&gt;&lt;a href="https://github.com/microsoft/recommenders"&gt;microsoft/recommenders&lt;/a&gt;: 微软的推荐系统最佳实践&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title>向量稳定化</title><link>http://blog.tsingjyujing.com/ml/recsys/embedding_stablization/</link><pubDate>Thu, 06 Nov 2025 00:00:00 +0900</pubDate><guid>http://blog.tsingjyujing.com/ml/recsys/embedding_stablization/</guid><description>&lt;h1 id="向量稳定化"&gt;向量稳定化&lt;a class="anchor" href="#%e5%90%91%e9%87%8f%e7%a8%b3%e5%ae%9a%e5%8c%96"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;最近接触到的一篇论文：&lt;a href="https://dl.acm.org/doi/10.1145/3705328.3748141"&gt;Orthogonal Low Rank Embedding Stabilization&lt;/a&gt;&lt;/p&gt;&#10;&lt;h2 id="为什么我们要向量稳定化"&gt;为什么我们要向量稳定化？&lt;a class="anchor" href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e6%88%91%e4%bb%ac%e8%a6%81%e5%90%91%e9%87%8f%e7%a8%b3%e5%ae%9a%e5%8c%96"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;在训练机器学习模型的时候，尤其是推荐系统的模型的时候，有很多的模型会输出User或者Item的Embedding。这些Embedding一般来说很难在下游的任务中使用，其原因是不够稳定。&#10;在训练稍微复杂一点的模型——哪怕只是一个几层的神经网络——我们也不能保证每一次输出的向量都是一样的，因为在Loss函数中我们约束的往往是User和Item求得的Score（内积或者Cosine Similarity之类），然后基于这个内积我能对物品进行正确的排序以保证用户感兴趣的物品在前面。&lt;/p&gt;</description></item><item><title>Understanding LightGCN in a visualized way</title><link>http://blog.tsingjyujing.com/ml/recsys/light_gcn/</link><pubDate>Fri, 09 Oct 2020 00:00:00 +0900</pubDate><guid>http://blog.tsingjyujing.com/ml/recsys/light_gcn/</guid><description>&lt;h1 id="understanding-lightgcn-in-a-visualized-way"&gt;Understanding LightGCN in a visualized way&lt;a class="anchor" href="#understanding-lightgcn-in-a-visualized-way"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;In this article, I&amp;rsquo;m going to introduce LightGCN, a new algorithm for collaborative filtering problem.&lt;/p&gt;&#10;&lt;h2 id="whats-lightgcn"&gt;What&amp;rsquo;s LightGCN&lt;a class="anchor" href="#whats-lightgcn"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;LightGCN is short for Light Graph Convolutional Neural-network, it&amp;rsquo;s a new approach for collaborative filtering which published in SIGIR 2020.&lt;/p&gt;&#10;&lt;p&gt;So, let&amp;rsquo;s talk about what&amp;rsquo;s the graph, what&amp;rsquo;s the convolution and why it&amp;rsquo;s called &amp;ldquo;light&amp;rdquo;.&lt;/p&gt;&#10;&lt;h3 id="graph"&gt;Graph&lt;a class="anchor" href="#graph"&gt;&lt;/a&gt;&lt;/h3&gt;&#10;&lt;p&gt;This is the graph we have:&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="2020-10-09-20-08-40.png" alt="" /&gt;&lt;/p&gt;&#10;&lt;p&gt;It can be represented as a heap of (user, item, interaction) triplets Of course, LightGCN is capable to use more than one kind of interaction (just create more LightGCN and concatenate them together).&lt;/p&gt;</description></item><item><title>无采样的矩阵分解</title><link>http://blog.tsingjyujing.com/ml/recsys/non_sampling_mf/</link><pubDate>Sun, 20 Jun 2021 00:00:00 +0900</pubDate><guid>http://blog.tsingjyujing.com/ml/recsys/non_sampling_mf/</guid><description>&lt;h1 id="无采样的矩阵分解"&gt;无采样的矩阵分解&lt;a class="anchor" href="#%e6%97%a0%e9%87%87%e6%a0%b7%e7%9a%84%e7%9f%a9%e9%98%b5%e5%88%86%e8%a7%a3"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;h2 id="前言"&gt;前言&lt;a class="anchor" href="#%e5%89%8d%e8%a8%80"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;很久以前，有个大佬说过，集体负责制就是不负责制，真正的负责是要落实到人的。 那么反过来企业级理解，无采样其实就是全采样的意思。&lt;/p&gt;&#10;&lt;p&gt;&lt;img src="2021-06-19-21-55-53.png" alt="" /&gt;&lt;/p&gt;&#10;&lt;p&gt;这里的采样，指的是负采样，所谓负，指的就是负样本，负样本是相对正样本而言的。&lt;/p&gt;</description></item><item><title>Learning To Rank 之 RankNet</title><link>http://blog.tsingjyujing.com/ml/recsys/ranknet/</link><pubDate>Wed, 03 Jun 2020 00:00:00 +0900</pubDate><guid>http://blog.tsingjyujing.com/ml/recsys/ranknet/</guid><description>&lt;h1 id="learning-to-rank-之-ranknet"&gt;Learning To Rank 之 RankNet&lt;a class="anchor" href="#learning-to-rank-%e4%b9%8b-ranknet"&gt;&lt;/a&gt;&lt;/h1&gt;&#10;&lt;p&gt;先记录一下自己的梯度简化推导过程，我自己纸上推了3遍，每次纸丢了就要重新推。 特此记录，省的全尼玛忘了。&lt;/p&gt;&#10;&lt;h2 id="标准的-ranknet-loss-推导"&gt;标准的 RankNet Loss 推导&lt;a class="anchor" href="#%e6%a0%87%e5%87%86%e7%9a%84-ranknet-loss-%e6%8e%a8%e5%af%bc"&gt;&lt;/a&gt;&lt;/h2&gt;&#10;&lt;p&gt;对于Ranknet，其实是将一个排序问题（比如Top N推荐）演变成一个分类问题。 假设我们已经有一个训练好的评分器，输入User ID和Item ID能给出一个评分，那么，这个评分应该满足越相关（或者用户越喜欢）数值越大。 那么在训练这个评分器的时候，我们假定有i和j两个item，且i更加相关，那么对于分类来说满足：&lt;/p&gt;</description></item></channel></rss>