【机器学习13】异常检测优化、推荐系统、协同过滤
文章目录
- 一 异常检测的高级主题
 - 1.1 异常检测与监督学习的对比
 - 1.2 异常检测的错误分析与特征工程
 
- 二 推荐系统入门
 - 2.1 问题定义:电影评分预测
 - 2.2 基于内容的推荐算法
 - 2.3 基于内容的代价函数
 
- 三 协同过滤 (Collaborative Filtering)
 - 3.1 问题的另一视角:学习电影特征
 - 3.2 协同过滤算法:同时学习
 
- 四 协同过滤的扩展与实践
 - 4.1 二元标签推荐
 - 4.2 冷启动问题与均值归一化
 
- 五 算法实现:TensorFlow中的梯度下降
 - 5.1 梯度下降回顾
 - 5.2 TensorFlow中的自定义训练循环
 - 5.3 协同过滤的TensorFlow实现
 
视频链接
 吴恩达机器学习p112-119
一 异常检测的高级主题
在上一篇文章中,我们学习了异常检测的基本算法。现在,我们将探讨其适用场景,以及如何通过错误分析和特征工程来优化算法性能。
1.1 异常检测与监督学习的对比
![[在此处插入图片1]](https://i-blog.csdnimg.cn/direct/aaffe2c814b24e329524d20959e5779e.png)
异常检测和监督学习(具体指二元分类)在某些场景下似乎都可以使用,但它们的核心适用条件有本质区别。
何时使用异常检测 (Anomaly Detection):
- 正样本(异常样本)数量极少:通常只有0-20个异常样本,但有大量的负样本(正常样本)。
 - 异常类型多样:异常的种类繁多,模型很难从少数的正样本中学到异常的普遍规律。未来的异常可能与已知的完全不同。
 - 应用案例: 
- 欺诈检测:欺诈手段层出不穷。
 - 制造业:寻找前所未见的新型产品缺陷。
 - 数据中心监控:任何导致服务器异常的原因都可能是独特的。
 
 
何时使用监督学习 (Supervised Learning):
- 正负样本数量都比较充足:拥有足够多的正样本(y=1)和负样本(y=0)。
 - 正样本具有共性:有足够的正样本,可以让算法学习到它们的共同特征,从而能够泛化到新的、类似的正样本上。
 - 应用案例: 
- 垃圾邮件分类:有大量的垃圾邮件和正常邮件样本。
 - 制造业:寻找已知的、以前见过的缺陷类型(例如划痕)。
 - 天气预测、疾病分类等。
 
 
1.2 异常检测的错误分析与特征工程
![[在此处插入图片2]](https://i-blog.csdnimg.cn/direct/d58f92630be04a6abf6a4c017ef60706.png)
异常检测算法的目标是,对于正常样本x,模型输出的概率p(x)应该很大(>= ε);对于异常样本x,p(x)应该很小(< ε)。
- 最常见的问题:算法失效时,往往是因为对于某些异常样本,模型也给出了很高的概率
p(x),导致无法将其与正常样本区分开。 - 原因分析:这通常意味着我们选择的特征不足以区分这种特定的异常。例如,在欺诈检测中,一个异常用户的交易次数
x₁可能与正常用户差不多,但他的打字速度x₂可能异常地高。如果我们的模型只使用了特征x₁,就无法检测出这个异常。 
![[在此处插入图片3]](https://i-blog.csdnimg.cn/direct/08e2f4017bfe4d3cad56327650b4a46b.png)
解决方案:特征工程 (Feature Engineering)
- 核心思想:创建新的、更能揭示异常行为的特征。
 - 案例:数据中心监控 
- 假设一个异常情况是:某个程序卡死,导致CPU负载
x₃很高,但网络流量x₄却很低。 - 单独看
x₃(高CPU负载)或x₄(低网络流量)可能都不是异常的。 - 我们可以创建一个新特征 
x₅ = CPU load / network traffic。对于上述异常,x₅的值会变得异常大,从而很容易被模型检测出来。 
 - 假设一个异常情况是:某个程序卡死,导致CPU负载
 - 通过组合现有特征(如创建比例、多项式特征等),我们可以构造出在异常发生时,会呈现出异常大或异常小值的特征,从而显著提升模型的性能。
 
二 推荐系统入门
现在,我们转向一个全新的、在工业界应用极其广泛的领域:推荐系统(Recommender Systems)。
2.1 问题定义:电影评分预测
![[在此处插入图片4]](https://i-blog.csdnimg.cn/direct/cfa679bfa3914c479b592de4681edcfe.png)
推荐系统的核心任务之一是预测用户对物品的评分。以电影评分为例:
- 我们有一个矩阵,行代表电影,列代表用户。
 - 符号定义: 
n_u= 用户数量 (number of users),例如n_u = 4。n_m= 电影数量 (number of movies),例如n_m = 5。r(i, j) = 1如果用户j对电影i进行了评分,否则为0。y(i, j)= 用户j对电影i的评分值(只有当r(i, j) = 1时才被定义)。
 - 目标:对于那些用户还未评分的项(在矩阵中标为“?”),预测出用户可能会给出的评分。
 
2.2 基于内容的推荐算法
![[在此处插入图片5]](https://i-blog.csdnimg.cn/direct/607e5fd5875e481ab97b8266ee3997fd.png)
基于内容的推荐(Content-based recommendation)是一种构建推荐系统的方法,它依赖于我们拥有物品(电影)的特征。
- 假设每部电影 
i都有一个特征向量x^(i)。例如,x₁代表电影的浪漫程度,x₂代表动作程度。 - 核心思想:为每一个用户 
j单独学习一个线性回归模型。- 该模型使用电影的特征 
x^(i)作为输入,来预测该用户j对电影i的评分。 - 模型参数为 
w^(j)和b^(j),它们代表了用户j的个人偏好。例如,如果用户Alice喜欢浪漫电影,她的w^(1)中对应浪漫特征的权重就会很高。 
 - 该模型使用电影的特征 
 - 预测公式:用户 
j对电影i的预测评分为(w^(j)) • x^(i) + b^(j)。 - 如图中计算所示,基于Alice的参数 
w^(1)和b^(1),以及电影“Cute puppies of love”的特征x^(3),可以预测出她对该电影的评分约为4.95。 
2.3 基于内容的代价函数
![[在此处插入图片6]](https://i-blog.csdnimg.cn/direct/db14794eb3c2446589052af1a749ebf9.png)
为了学习每个用户的参数 w^(j) 和 b^(j),我们需要定义一个代价函数。这本质上就是我们熟悉的带正则化的线性回归的代价函数。
- 对单个用户 
j的代价函数:min J(w^(j), b^(j))=(1 / 2m^(j)) * Σ [ (w^(j)•x^(i) + b^(j) - y(i,j))² ] + (λ / 2m^(j)) * Σ (w_k^(j))²- 其中,第一个求和 
Σ只对那些用户j已经评过分的电影i(即r(i,j)=1)进行计算。m^(j)是用户j评过分的电影数量。 - 第二个求和是L2正则化项,用于防止过拟合。
 
 
![[在此处插入图片7]](https://i-blog.csdnimg.cn/direct/56e3dab0e17c4c44803b155af538cd0a.png)
- 对所有用户的总代价函数: 
- 为了学习所有用户的参数,我们只需将每个用户的代价函数相加即可。
 min J(w^(1)...w^(n_u), b^(1)...b^(n_u))=(1/2) * Σ [ Σ [ (w^(j)•x^(i) + b^(j) - y(i,j))² ] ] + (λ/2) * Σ [ Σ (w_k^(j))² ]- 这个总代价函数是对所有用户的所有已知评分的误差平方和,加上对所有用户的所有参数的正则化。通过最小化这个总代价函数,我们就可以用梯度下降等算法,为所有用户找到最佳的参数 
w和b。 
 
三 协同过滤 (Collaborative Filtering)
基于内容的推荐有一个前提:我们需要拥有物品的特征。但在很多情况下,这些特征是难以获取的。协同过滤算法解决了这个问题。
3.1 问题的另一视角:学习电影特征
![[在此处插入图片8]](https://i-blog.csdnimg.cn/direct/882725aabee44f8db372434a96dd3cff.png)
让我们换一个角度思考问题:
- 假设我们不知道电影的特征 
x^(i),但是我们通过某种方式已经知道了每个用户的偏好参数w^(j)和b^(j)。 - 在这种情况下,我们能否推断出电影的特征 
x^(i)呢? - 例如,已知Alice和Bob都喜欢浪漫电影(
w^(1)和w^(2)的第一个元素很大),并且他们都给电影“Love at last”打了5分高分,而Carol和Dave(不喜欢浪漫电影)都给了0分。我们可以据此推断,电影“Love at last”的特征x^(1)应该是一个接近[1, 0]的向量,即它是一部纯粹的浪漫电影。 
![[在此处插入图片9]](https://i-blog.csdnimg.cn/direct/c21463cd88b04754a44c645d1771b424.png)
- 学习电影特征的代价函数: 
- 我们可以固定用户的参数 
w和b,将电影特征x视为需要学习的变量。 - 代价函数的形式与之前类似,但这次的优化目标是 
min J(x^(1)...x^(n_m))。 - 它衡量的是,在给定用户偏好的情况下,我们学习到的电影特征能够多好地预测已有的评分。
 
 - 我们可以固定用户的参数 
 
3.2 协同过滤算法:同时学习
![[在此处插入图片10]](https://i-blog.csdnimg.cn/direct/7c2fc6596d0840d683061a5d3f538a5a.png)
协同过滤的精妙之处在于,它将上述两个问题结合了起来:
- 我们既没有电影特征 
x,也没有用户参数w和b。 - 算法的目标是同时学习这两者。
 - 协同过滤代价函数: 
min J(w, b, x)=(1/2) * Σ [ (w^(j)•x^(i) + b^(j) - y(i,j))² ] + (λ/2) * Σ (w_k^(j))² + (λ/2) * Σ (x_k^(i))²- 这个代价函数将 
w,b,x全部视为需要优化的参数。 - 它包含了三部分:对已知评分的预测误差、对用户参数的正则化、以及对电影特征的正则化。
 
 
![[在此处插入图片11]](https://i-blog.csdnimg.cn/direct/a842e88c5f5b46528ad984211565e63e.png)
- 协同过滤的梯度下降: 
- 由于 
w,b,x都是参数,我们在梯度下降的每一步中,需要同时更新它们:w_k^(j) := w_k^(j) - α * (∂/∂w_k^(j))Jb^(j) := b^(j) - α * (∂/∂b^(j))Jx_k^(i) := x_k^(i) - α * (∂/∂x_k^(i))J
 - 这个算法之所以被称为“协同”,是因为用户对电影的评分数据,帮助算法协同地学习了用户的偏好和电影的特征。
 
 - 由于 
 
四 协同过滤的扩展与实践
4.1 二元标签推荐
![[在此处插入图片12]](https://i-blog.csdnimg.cn/direct/5e8976ba0bbb4ae19884e377a9bcf560.png)
![[在此处插入图片13]](https://i-blog.csdnimg.cn/direct/0c5e447ad6af44cea720c0fee6bf2134.png)
在很多推荐场景中,我们没有明确的1-5星评分,而是只有二元标签(Binary labels),代表用户是否与物品发生了某种交互。
y=1:用户进行了交互(例如,购买、喜欢、点击、观看超过30秒)。y=0:用户被展示了物品但没有交互。?:物品还未被展示给用户。
![[在此处插入图片14]](https://i-blog.csdnimg.cn/direct/fe9161f44a9d4350aa89c1e9daab60f0.png)
从回归到分类:
- 对于二元标签,问题从一个回归问题(预测评分)转变为一个二元分类问题(预测交互的概率)。
 - 我们的预测模型需要做出改变:不再直接输出 
w•x + b,而是将其输入到一个Sigmoid函数g(z)中,来预测y=1的概率。 P(y=1) = g(w^(j)•x^(i) + b^(j))
![[在此处插入图片15]](https://i-blog.csdnimg.cn/direct/04b29582a3964907bb0ceebcad716f73.png)
- 二元协同过滤的代价函数: 
- 相应地,代价函数也需要从线性回归的均方误差,改为我们熟悉的逻辑回归的对数损失函数(log loss)。
 - 总代价函数 
J(w, b, x)是对所有已知交互(r(i,j)=1)的对数损失之和。正则化项保持不变。 
 
4.2 冷启动问题与均值归一化
![[在此处插入图片16]](https://i-blog.csdnimg.cn/direct/10d70e4729c64078b18a5a1d413eb5eb.png)
冷启动问题(Cold start problem):
- 当一个新用户(如Eve)加入系统,他/她没有任何评分历史。
 - 在使用协同过滤算法时,由于没有
y^(i,5)的数据,代价函数中与用户Eve相关的预测误差项为0。 - 为了最小化总代价,正则化项会迫使Eve的参数 
w^(5)和b^(5)都变为0。 - 这导致对Eve的所有电影评分预测都为0,这是一个没有意义的推荐结果。
 
![[在此处插入图片17]](https://i-blog.csdnimg.cn/direct/10efe1ce9d5b4c3ca3061c0c478ce32c.png)
解决方案:均值归一化(Mean Normalization)
- 计算均值:对评分矩阵的每一行(每一部电影),计算所有已有评分的平均值 
μ。 - 归一化:从每个电影的所有已有评分中,减去该电影的平均分,得到一个均值为0的归一化评分矩阵。
 - 训练:在归一化的评分矩阵上运行协同过滤算法,学习参数 
w,b和特征x。 - 预测:对于用户 
j和电影i,进行预测时,在模型输出的基础上,必须将该电影的平均分加回来。- 预测公式:
(w^(j)) • x^(i) + b^(j) + μ_i 
 - 预测公式:
 - 对新用户的预测:对于新用户Eve,其参数 
w^(5)和b^(5)仍然会是0。但现在的预测结果是0 + μ_i,即该电影的平均分。这是一个远比预测0分更合理、更有意义的初始推荐。 
五 算法实现:TensorFlow中的梯度下降
5.1 梯度下降回顾
![[在此处插入图片18]](https://i-blog.csdnimg.cn/direct/ce4e67820b66448d9d3c0a904d8b7ba0.png)
梯度下降是优化代价函数 J(w,b) 的核心算法。它通过在每一步迭代中,沿着代价函数梯度的反方向更新参数 w 和 b,来逐步找到使 J 最小化的参数值。更新规则的核心是偏导数 ∂J/∂w。
5.2 TensorFlow中的自定义训练循环
![[在此处插入图片19]](https://i-blog.csdnimg.cn/direct/3d101bf0f2274df2a5b2989b8491a6cd.png)
在TensorFlow中实现梯度下降,尤其是对于像协同过滤这样自定义的代价函数,我们需要构建一个自定义训练循环。
tf.Variable: 用于定义我们想要优化的参数(如w)。tf.GradientTape: 这是TensorFlow实现**自动微分(Auto Diff)**的核心工具。- 在一个 
with tf.GradientTape() as tape:的代码块中,执行所有计算代价函数J的前向传播步骤(例如costJ = (f(w,x) - y)²)。 GradientTape会像磁带一样“记录”下所有这些操作。- 然后,调用 
tape.gradient(costJ, [w]),TensorFlow会自动计算出costJ相对于参数w的梯度∂J/∂w。 - 最后,我们手动执行梯度下降的更新步骤,例如 
w.assign_add(-alpha * dJdw)。 
- 在一个 
 
5.3 协同过滤的TensorFlow实现
![[在此处插入图片20]](https://i-blog.csdnimg.cn/direct/63cd1758b2214ec7b61ec2f130556133.png)
将上述概念应用到协同过滤算法中:
- 初始化:将 
w,b,x都定义为tf.Variable。 - 创建优化器:例如 
optimizer = keras.optimizers.Adam()。 - 训练循环: 
- 在 
with tf.GradientTape() as tape:块内,编写计算协同过滤总代价J(w,b,x)的函数。 - 调用 
tape.gradient(cost_value, [X, W, b])来自动获取代价函数相对于所有参数(电影特征X,用户权重W,用户偏置b)的梯度。 - 调用 
optimizer.apply_gradients(zip(grads, [X, W, b])),优化器会自动执行梯度下降的更新步骤,同时更新X,W,b。 
 - 在 
 
通过这种方式,我们可以高效地实现并训练复杂的协同过滤模型。
