机器学习(三)

1. 引言

k 近邻(KNN)算法原理、矩阵分解及其演变、双线性模型的定义,以及因子分解机(FM)的完整推导与实验表现。推荐系统核心问题------如何利用用户历史行为预测未知偏好------贯穿全文。

2. 个性化推荐与协同过滤

2.1 推荐系统与信息过滤

  • 个性化推荐是一种广义信息检索:用户的信息需求是隐含的,没有显式查询。
  • 两类方法:
    • 基于内容的过滤:推荐与用户过去喜欢的物品具有相似属性(演员、导演、类型等)的物品。
    • 协同过滤(Collaborative Filtering):利用其他类似用户的偏好进行推荐。

2.2 评分矩阵与协同过滤目标

数据通常表现为一个稀疏的用户-物品评分矩阵(显式反馈)。协同过滤的核心任务是预测矩阵中的空评分。以电影推荐为例:

  • 用户 Boris 看过一些电影,我们需要预测他对《Love Actually》的评分。
  • 思路:找到与 Boris 相似的用户(如 Dave、George),取他们对《Love Actually》评分的平均值作为预测。

这引出了两种经典的基于近邻的协同过滤:基于用户(user-based)基于物品(item-based)

3. 基于近邻算法的协同过滤

3.1 基于用户的 KNN

  1. 为每个用户构建画像向量(已知物品的评分)。
  2. 计算用户间的相似度:
    • 余弦相似度
      sucos(ua,ub)=ua⊤ub∥ua∥∥ub∥ s_u^{cos}(u_a, u_b) = \frac{u_a^\top u_b}{\|u_a\|\|u_b\|} sucos(ua,ub)=∥ua∥∥ub∥ua⊤ub
    • 皮尔森相关系数
      sucorr(ua,ub)=∑m(xa,m−xˉa)(xb,m−xˉb)∑m(xa,m−xˉa)2∑m(xb,m−xˉb)2 s_u^{corr}(u_a, u_b) = \frac{\sum_m (x_{a,m} - \bar x_a)(x_{b,m} - \bar x_b)}{\sqrt{\sum_m (x_{a,m} - \bar x_a)^2} \sqrt{\sum_m (x_{b,m} - \bar x_b)^2}} sucorr(ua,ub)=∑m(xa,m−xˉa)2 ∑m(xb,m−xˉb)2 ∑m(xa,m−xˉa)(xb,m−xˉb)
  3. 评分预测公式(基于目标用户的平均评分校正):
    x^t,m=xˉt+∑ua∈Nu(ut)su(ut,ua)(xa,m−xˉa)∑ua∈Nu(ut)∣su(ut,ua)∣ \hat x_{t,m} = \bar x_t + \frac{\sum_{u_a \in N_u(u_t)} s_u(u_t, u_a)(x_{a,m} - \bar x_a)}{\sum_{u_a \in N_u(u_t)} |s_u(u_t, u_a)|} x^t,m=xˉt+∑ua∈Nu(ut)∣su(ut,ua)∣∑ua∈Nu(ut)su(ut,ua)(xa,m−xˉa)

3.2 基于物品的 KNN

  • 对目标用户未评分的物品 aaa,寻找该用户已评分且与 aaa 最相似的 kkk 个物品。
  • 物品相似度衡量同样有余弦相似度、调整余弦相似度和皮尔森相关。
  • 预测公式(直接用目标用户已有的评分,无需用户平均校正):
    x^t,a=∑ib∈Ni(ut,ia)si(ia,ib)xt,b∑ib∈Ni(ut,ia)∣si(ia,ib)∣ \hat x_{t,a} = \frac{\sum_{i_b \in N_i(u_t, i_a)} s_i(i_a, i_b) x_{t,b}}{\sum_{i_b \in N_i(u_t, i_a)} |s_i(i_a, i_b)|} x^t,a=∑ib∈Ni(ut,ia)∣si(ia,ib)∣∑ib∈Ni(ut,ia)si(ia,ib)xt,b

3.3 实验结论与 KNN 方法局限性

Movielens ML‑100k 数据集(943 用户 × 1682 电影,稀疏度 93.69%)上的实验表明:

  • 基于物品的 KNN 通常优于基于用户------物品间的相似度更稳定、更客观。
  • 评估指标:MAE、RMSE;随着训练集增大和邻居数 kkk 调整(约 30 最佳),效果提升。
  • KNN 方法的局限 :无可学习参数(仅超参数 kkk),效率随数据规模急剧下降,因此需要参数化、可学习的模型。
python 复制代码
import numpy as np
import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity

# 1. 加载数据:使用 MovieLens 100k 的 u.data 文件
columns = ['user_id', 'item_id', 'rating', 'timestamp']
ratings = pd.read_csv('u.data', sep='\t', names=columns)

# 构建用户-物品评分矩阵,缺失值填 0
rating_matrix = ratings.pivot_table(index='user_id',
                                    columns='item_id',
                                    values='rating').fillna(0)

# 2. 计算用户间的余弦相似度
user_similarity = cosine_similarity(rating_matrix)
user_ids = rating_matrix.index  # 用户 ID 列表

# 3. 基于 KNN 的评分预测函数
def predict_rating(user_id, item_id, k=30):
    """
    基于用户相似度的 KNN 协同过滤预测评分。
    user_id: 目标用户 ID(从 1 开始)
    item_id: 目标物品 ID(从 1 开始)
    k: 最近邻用户数量
    """
    # 如果目标物品已有评分,直接返回
    if rating_matrix.loc[user_id, item_id] > 0:
        return rating_matrix.loc[user_id, item_id]

    # 获取目标用户在相似度矩阵中的位置索引
    user_idx = user_ids.get_loc(user_id)
    sim_scores = user_similarity[user_idx]

    # 找到相似度最高的 k 个用户(排除自身)
    nearest_indices = np.argsort(sim_scores)[::-1][1:k+1]

    # 收集邻居评分并加权平均
    ratings_sum = 0.0
    sim_sum = 0.0
    for idx in nearest_indices:
        neighbor_id = user_ids[idx]
        r = rating_matrix.loc[neighbor_id, item_id]
        if r > 0:  # 只考虑有过评分的邻居
            ratings_sum += sim_scores[idx] * r
            sim_sum += np.abs(sim_scores[idx])

    if sim_sum == 0:
        return 0  # 若无邻居评分,返回 0 或全局平均分
    return ratings_sum / sim_sum

# 示例:预测用户1对物品10的评分
pred = predict_rating(user_id=1, item_id=10, k=30)
print(f"预测评分: {pred:.2f}")

4. k 近邻算法(KNN)本身

4.1 经典 KNN

  • 非参数方法,可用于分类和回归。
  • 对于输入 xxx,在特征空间中找到 kkk 个最近邻 Nk(x)N_k(x)Nk(x):
    • 回归 :y^(x)=1k∑xi∈Nk(x)yi\hat y(x) = \frac{1}{k} \sum_{x_i \in N_k(x)} y_iy^(x)=k1∑xi∈Nk(x)yi
    • 分类:多数投票。

4.2 广义 KNN 与超参数

引入相似度函数 s(x,xi)s(x, x_i)s(x,xi) 后:

y^(x)=∑xi∈Nk(x)s(x,xi)yi∑xi∈Nk(x)s(x,xi) \hat y(x) = \frac{\sum_{x_i \in N_k(x)} s(x, x_i) y_i}{\sum_{x_i \in N_k(x)} s(x, x_i)} y^(x)=∑xi∈Nk(x)s(x,xi)∑xi∈Nk(x)s(x,xi)yi

  • 实际上有 NNN 个参数(每个实例即一个参数),有效参数约 N/kN/kN/k。
  • 超参数 kkk 必须在验证集上选择,k=1k=1k=1 虽然训练误差为 0,但泛化极差。

5. 矩阵分解------双线性模型的基础

5.1 基本矩阵分解模型

将评分矩阵 RRR 近似为两个低秩矩阵的乘积:

r^u,i=pu⊤qi \hat r_{u,i} = p_u^\top q_i r^u,i=pu⊤qi

  • pup_upu、qiq_iqi 分别是用户和物品的隐因子向量。
  • 损失函数(加入 L2 正则):
    L=∑(u,i)∈D12(ru,i−pu⊤qi)2+λ2(∥pu∥2+∥qi∥2) \mathcal{L} = \sum_{(u,i) \in D} \frac{1}{2}(r_{u,i} - p_u^\top q_i)^2 + \frac{\lambda}{2}(\|p_u\|^2 + \|q_i\|^2) L=(u,i)∈D∑21(ru,i−pu⊤qi)2+2λ(∥pu∥2+∥qi∥2)
  • 梯度下降更新参数。

5.2 带偏置的矩阵分解

预测值加入全局偏置、用户偏置和物品偏置:

r^u,i=μ+bu+bi+pu⊤qi \hat r_{u,i} = \mu + b_u + b_i + p_u^\top q_i r^u,i=μ+bu+bi+pu⊤qi

这种方法显著提高了预测精度。

5.3 时间动态与 SVD++

评分行为本身随时间演变(用户口味变化、物品热度变化等)。带时间的模型:

ru,i(t)=μ+bu(t)+bi(t)+pu(t)⊤qi r_{u,i}(t) = \mu + b_u(t) + b_i(t) + p_u(t)^\top q_i ru,i(t)=μ+bu(t)+bi(t)+pu(t)⊤qi

SVD++ 进一步结合邻居信息,为每个物品引入两个向量(表示自身的 qiq_iqi 和用于度量相似度的 yiy_iyi):

r^u,i=bu,i+qi⊤(pu+∣N(u)∣−12∑j∈N(u)yj) \hat r_{u,i} = b_{u,i} + q_i^\top \left( p_u + |N(u)|^{-\frac{1}{2}} \sum_{j \in N(u)} y_j \right) r^u,i=bu,i+qi⊤ pu+∣N(u)∣−21j∈N(u)∑yj

在 Netflix 奖比赛中,矩阵分解和 KNN 的变体都取得了优异表现。

6. 双线性模型与因子分解机

6.1 双线性(Bilinear)的含义

二元函数 f:Rn×Rm→Rlf: \mathbb{R}^n \times \mathbb{R}^m \to \mathbb{R}^lf:Rn×Rm→Rl 是双线性的,当固定某一侧向量时,它对另一侧是线性的。向量内积是最简单的双线性函数,因此:

矩阵分解模型 r^=pu⊤qi\hat r = p_u^\top q_ir^=pu⊤qi 正是一种双线性模型。

6.2 基于特征的矩阵分解(因子分解机,FM)

将推荐问题中所有信息(用户 id、物品 id、时间、类别等)统一视为特征,并学习特征间的两两交互:

y^(x)=w0+∑i=1dwixi+∑i=1d−1∑j=i+1d⟨vi,vj⟩xixj \hat y(\mathbf{x}) = w_0 + \sum_{i=1}^d w_i x_i + \sum_{i=1}^{d-1} \sum_{j=i+1}^d \langle v_i, v_j \rangle x_i x_j y^(x)=w0+i=1∑dwixi+i=1∑d−1j=i+1∑d⟨vi,vj⟩xixj

  • 每个特征(包括每个类别特征的独热编码)学习一个隐向量 viv_ivi。
  • 基于向量内积的双线性交互项使模型能够拟合稀疏特征间的关联。

6.3 计算效率优化

原始二次交互复杂度为 O(kd2)O(kd^2)O(kd2),利用恒等式可降到 O(kd)O(kd)O(kd):

∑i=1d−1∑j=i+1d⟨vi,vj⟩xixj=12∑f=1k((∑i=1dvi,fxi)2−∑i=1dvi,f2xi2) \sum_{i=1}^{d-1} \sum_{j=i+1}^d \langle v_i, v_j \rangle x_i x_j = \frac{1}{2} \sum_{f=1}^k \left( \left(\sum_{i=1}^d v_{i,f} x_i \right)^2 - \sum_{i=1}^d v_{i,f}^2 x_i^2 \right) i=1∑d−1j=i+1∑d⟨vi,vj⟩xixj=21f=1∑k (i=1∑dvi,fxi)2−i=1∑dvi,f2xi2

这使得 FM 在大规模稀疏数据上高效实用。

6.4 实验结果与对比

在 Criteo 和 iPinYou 数据集上,线性模型(Logistic Regression)、双线性模型(FM)与非线性模型(Deep Neural Networks)的 AUC/Log Loss 对比显示:

  • FM 作为双线性模型,比完全线性的 LR 有显著提升;
  • 深度模型虽性能更强,但 FM 在可解释性、效率和标准化的便捷性上仍有明显优势。

7. 总结

  • 协同过滤的核心是学习数据点(用户/物品)之间的相似性,并据此进行预测。
  • KNN 是最简单的非参数化协同过滤方法,解释性强但缺乏参数学习和可扩展性。
  • 矩阵分解通过隐因子内积将评分矩阵参数化,是最基础的双线性模型;加入偏置、时间动态和邻居信息后,性能大幅提升。
  • 双线性模型指固定一侧变元时对另一侧呈线性变换的映射,向量内积是其典型操作------对一边参数求梯度正好得到另一边的参数。
  • 因子分解机(FM) 将矩阵分解推广为通用特征交互学习器,在推荐系统和点击率预估中兼具效率与表达能力,是双线性模型向全特征空间拓展的代表。

从 KNN 到矩阵分解再到 FM,体现了从非参数邻居相似性到参数化双线性交互的演进路径,也为理解后续深度推荐模型奠定了理论基础。

相关推荐
是上好佳佳佳呀2 小时前
【机器学习|DAY03】K近邻算法(KNN)笔记
笔记·机器学习·近邻算法
To_OC9 小时前
大模型蒸馏是啥?说白了就是大厨带徒弟的学问
人工智能·llm·agent
新手来了@click9 小时前
JAVA+AI 简化开发操作|文章被 AI Agent 技术社区收录分享
人工智能
GuWenyue9 小时前
Cursor黑盒拆解!1套LangChain.js手写Mini编程Agent,自动生成React项目,效率提升60%
前端·数据库·人工智能
GuWenyue9 小时前
传统Agent工具两大痛点!300行代码落地MCP跨语言工具,彻底解耦LLM与工具
前端·人工智能·算法
老云讲算力市场10 小时前
WAIC首日观察:国产算力与机器人加速落地,奇点算力迎来产业新机遇
人工智能·科技
糖果店的幽灵10 小时前
【DeepAgents 从入门到精通】Context Management 上下文管理
java·人工智能·后端·spring·中间件·langgraph·deepagents
小林ixn10 小时前
大模型随机说话的秘密:Temperature 和 Top K 深度解析,LangChain 实战调优
人工智能·langchain
ALINX技术博客10 小时前
ALINX 亮相 2026 WAIC 世界人工智能大会,展示 AI 视觉 FPGA+GPU 异构计算与电子后视镜解决方案
人工智能·ai·fpga·世界人工智能大会·电子后视镜