当前位置: 首页 > news >正文

【机器学习14】深度学习推荐系统、降维技术PCA

文章目录

  • 一 推荐系统的高级应用与方法
    • 1.1 利用特征向量寻找相似物品
    • 1.2 协同过滤的局限性与混合方法
    • 1.3 协同过滤与基于内容的过滤对比
    • 1.4 基于深度学习的推荐系统
    • 1.5 大规模推荐系统:召回与排序
    • 1.6 TensorFlow实现概览
  • 二 降维与主成分分析(PCA)
    • 2.1 降维的动机
    • 2.2 PCA的应用:数据可视化
    • 2.3 主成分分析 (PCA) 算法
    • 2.4 PCA与线性回归的区别
    • 2.5 数据重建与实践
    • 2.6 PCA的应用总结


视频链接
吴恩达机器学习p120-128


一 推荐系统的高级应用与方法

在上一篇文章中,我们学习了协同过滤的基础知识。现在,我们将探讨如何利用其学习成果,并介绍一种更现代的、基于深度学习的推荐系统架构。

1.1 利用特征向量寻找相似物品

[在此处插入图片1]

协同过滤算法的一个强大副产品是,它为每个物品(如电影i)学习到了一个特征向量x^(i)

  • 特征的可解释性:虽然我们可能将这些特征维度想象成“浪漫”、“动作”等,但算法自动学习到的特征通常是抽象的,其具体含义很难直接解释。
  • 寻找相似物品:尽管特征难以解释,但它们在向量空间中的位置是有意义的。要找到与物品i相似的其他物品k,我们可以在特征空间中寻找与x^(i)最接近的向量x^(k)
  • 计算方法:通过计算两个物品特征向量之间的欧氏距离的平方 ||x^(k) - x^(i)||^2。这个值最小的物品k,就是与物品i最相似的。

1.2 协同过滤的局限性与混合方法

[在此处插入图片2]

传统的协同过滤算法存在一些固有的局限性,最主要的就是冷启动问题(Cold start problem)

  • 新物品问题:如何为一个几乎没有用户评分的新物品进行推荐?
  • 新用户问题:如何为一个几乎没有评分记录的新用户提供合理的推荐?

解决方案:引入额外信息(side information)来辅助推荐,这通常被称为混合推荐系统

  • 物品的额外信息:电影的类型、主演、制片公司等。
  • 用户的额外信息:用户的年龄、性别、地理位置等人口统计学信息,或用户明确表示的偏好。

1.3 协同过滤与基于内容的过滤对比

[在此处插入图片3]

让我们再次明确两种核心推荐思想的区别:

  • 协同过滤 (Collaborative Filtering):其核心是“协同”。它向你推荐物品,是基于那些与你品味相似的用户(即给出了与你相似评分的用户)也喜欢的物品。它不依赖于物品或用户的固有特征。
  • 基于内容的过滤 (Content-based Filtering):其核心是“匹配”。它向你推荐物品,是基于用户特征和物品特征之间的匹配程度。它需要明确的特征作为输入。

1.4 基于深度学习的推荐系统

现代推荐系统通常会结合协同过滤和基于内容的思想,并利用深度学习来学习用户和物品的复杂特征表示。

[在此处插入图片4]

1. 定义用户与物品特征

  • 我们首先为用户和物品收集丰富的原始特征,形成用户特征向量x_u物品特征向量x_m
  • 用户特征示例:年龄、性别、国家、观看过的电影列表、对各类型电影的平均评分等。
  • 物品特征示例:年份、类型、影评文本、平均评分等。
  • 这些原始特征向量的维度和类型都可以是多样的。

[在此处插入图片5]

2. 学习特征向量(Embedding)

  • 之前,我们的预测是基于 w^(j)•x^(i) + b^(j)。现在,我们引入一个更强大的思路。
  • 我们不再直接使用原始特征x_ux_m,而是分别学习出两个新的、低维度的特征向量(或称嵌入向量, embedding)
    • v_u^(j):代表用户j的偏好,从原始用户特征x_u^(j)计算得出。
    • v_m^(i):代表电影i的属性,从原始电影特征x_m^(i)计算得出。
  • 例如,学习到的v_u可能表示用户对“喜欢”的各种抽象概念的倾向,而v_m表示电影在“浪漫”、“动作”等抽象概念上的得分。

[在此处插入图片6]

3. 神经网络架构

  • 我们使用两个独立的神经网络来学习这两个嵌入向量:
    • 用户网络 (User network):输入是原始用户特征x_u,经过多层神经网络处理后,输出一个固定长度(例如32维)的嵌入向量v_u
    • 物品网络 (Movie network):输入是原始物品特征x_m,经过另一个独立的神经网络处理后,输出一个同样长度(32维)的嵌入向量v_m
  • 预测:用户j对电影i的评分(或交互概率)可以通过计算两个嵌入向量的点积v_u^(j) • v_m^(i)来预测。对于二元分类问题,这个点积结果会被送入一个Sigmoid函数。

[在此处插入图片7]

4. 整体模型与代价函数

  • 整个模型由用户网络、物品网络以及最后的点积预测层组成。
  • 代价函数
    • J = Σ [ (v_u^(j) • v_m^(i) - y(i,j))² ] + NN regularization term
    • 代价函数的主体是所有已知评分的预测误差(例如均方误差)。求和 Σ 只对那些有评分的 (i,j) 对进行。
    • 同时,还需要加上神经网络的正则化项(如L2正则化)来防止过拟合。

[在此处插入图片8]

5. 寻找相似物品

  • 在模型训练完成后,我们得到了每个物品i的嵌入向量v_m^(i)
  • 与之前的协同过滤一样,我们可以通过计算嵌入向量之间的距离 ||v_m^(k) - v_m^(i)||^2 来找到与物品i最相似的物品k
  • 由于这些计算不依赖于具体用户,可以预先计算并存储好所有物品之间的相似度,以便快速查询。

1.5 大规模推荐系统:召回与排序

[在此处插入图片9]

当物品库非常庞大时(例如上百万首歌曲或商品),为用户与每一个物品都计算一次预测得分是不可行的。工业界通常采用一个两阶段的流程。

[在此处插入图片10]

第一阶段:召回 (Retrieval)

  • 目标:从海量的物品库中,快速筛选出一个规模较小(例如几百个)的候选物品列表。这个阶段追求的是“快”和“全”,即快速找出所有可能相关的物品,宁可错杀一千,不可放过一个。
  • 常用方法
    1. 基于相似度的召回:例如,对于用户最近看过的10部电影,分别找出与它们最相似的10部电影。
    2. 基于规则的召回:例如,找出用户最常看的3个电影类型中,排名最高的10部电影。
    3. 其他策略:例如,推荐本地区的热门电影。
  • 最后,将所有召回策略生成的物品合并,并移除用户已经看过或购买过的物品以及重复项。

[在此处插入图片11]

第二阶段:排序 (Ranking)

  • 目标:对召回阶段生成的几百个候选物品,使用我们训练好的、复杂的深度学习模型进行精准的预测打分。
  • 流程
    1. 将候选列表中的每一个物品,与当前用户的特征一起,输入到我们的双塔神经网络模型中。
    2. 模型会为每个候选物品计算出一个精确的预测得分(例如,用户喜欢的概率)。
    3. 根据这个得分对候选列表进行降序排序
    4. 将排序最高的若干个物品展示给用户。

[在此处插入图片12]

召回与排序的权衡

  • 召回的物品越多,最终推荐效果可能会越好,但排序阶段的计算成本也越高,导致推荐变慢。
  • 为了优化这个权衡,可以进行离线实验,分析增加召回数量(例如从100增加到500)是否能显著提升最终推荐列表的质量(例如,预测y=1的物品比例是否更高)。

1.6 TensorFlow实现概览

[在此处插入图片13]

使用TensorFlow中的Keras API可以模块化地、清晰地构建出我们所讨论的用于推荐系统的双塔神经网络模型。下面是一个详细的代码实现与解释。

1. 定义基础网络 (User and Movie Networks)

首先,我们为用户和电影分别定义独立的神经网络。这两个网络的作用是将高维、异构的原始特征,转换为低维、稠密的嵌入向量 v_uv_m

import tensorflow as tf
from tensorflow import keras# 定义用户网络的结构
user_NN = tf.keras.models.Sequential([tf.keras.layers.Dense(256, activation='relu'),tf.keras.layers.Dense(128, activation='relu'),tf.keras.layers.Dense(32)  # 输出32维的用户嵌入向量
])# 定义物品(电影)网络的结构
item_NN = tf.keras.models.Sequential([tf.keras.layers.Dense(256, activation='relu'),tf.keras.layers.Dense(128, activation='relu'),tf.keras.layers.Dense(32)  # 输出32维的物品嵌入向量
])

代码解释

  • tf.keras.models.Sequential([...]): 我们使用Sequential模型来构建一个线性的层堆栈。这是一个简单快捷的建网方式。
  • tf.keras.layers.Dense(units, activation='relu'): Dense层是全连接层,是标准的神经网络层。
    • 第一个参数(如256)是该层中的神经元数量。
    • activation='relu' 指定使用ReLU作为激活函数,它能为模型引入非线性,增强模型的表达能力。
  • tf.keras.layers.Dense(32): 网络的最后一层不使用激活函数(或可视为使用线性激活)。它的输出就是我们最终想要的32维嵌入向量 v_uv_m

2. 构建完整的双塔模型

接下来,我们将上述两个基础网络组合起来,构建一个接收用户和物品两路输入,并计算它们匹配度的完整模型。

# 1. 定义模型的输入层
num_user_features = 100 # 假设用户原始特征有100维
num_item_features = 80  # 假设物品原始特征有80维
input_user = tf.keras.layers.Input(shape=(num_user_features,))
input_item = tf.keras.layers.Input(shape=(num_item_features,))# 2. 将输入连接到对应的基础网络,得到嵌入向量
vu = user_NN(input_user)
vm = item_NN(input_item)# (可选步骤) 对嵌入向量进行L2归一化,这有助于稳定训练
vu = tf.linalg.l2_normalize(vu, axis=1)
vm = tf.linalg.l2_normalize(vm, axis=1)# 3. 计算两个嵌入向量的点积作为预测输出
output = tf.keras.layers.Dot(axes=1)([vu, vm])# 4. 定义完整的模型
model = tf.keras.Model(inputs=[input_user, input_item], outputs=output)# 5. 编译模型
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.01),loss=tf.keras.losses.MeanSquaredError())

代码解释

  • tf.keras.layers.Input(shape=...): 我们使用Input层来定义模型期望接收的数据的形状。这里我们定义了两个独立的输入:一个给用户特征,一个给物品特征。
  • vu = user_NN(input_user): 这被称为函数式API的用法。我们将input_user这个“符号张量”作为输入,传递给之前定义好的user_NN网络,其输出vu就是用户嵌入向量。
  • tf.linalg.l2_normalize(...): 这一步对嵌入向量进行L2归一化,使其长度变为1。这样做可以使模型更关注向量的方向(代表偏好或属性的方向)而不是其大小,有时能提升模型性能。
  • tf.keras.layers.Dot(axes=1): Dot层专门用于计算输入的点积。axes=1指定沿着特征维度进行点积运算。我们将vuvm作为列表传入,该层会计算它们的点积,其结果就是模型的最终预测评分。
  • tf.keras.Model(...): 我们使用Model类来定义一个具有多输入、单输出的复杂模型。inputs参数接收一个输入列表,outputs参数指定模型的最终输出。
  • model.compile(...): 在训练之前,我们必须“编译”模型。
    • optimizer: 指定用于更新模型参数的优化算法,Adam是一个常用且高效的选择。
    • loss: 指定代价函数。对于评分预测这样的回归任务,MeanSquaredError(均方误差)是一个标准的选择。

二 降维与主成分分析(PCA)

现在我们转向另一个重要的无监督学习主题:降维(Dimensionality Reduction)

2.1 降维的动机

[在此处插入图片14]

[在此处插入图片15]

在很多数据集中,特征之间存在高度的相关性或冗余。

  • 例如,在汽车测量数据中,特征x₁(车长)和x₂(车宽)都反映了汽车的“大小”。x₁的变化范围远大于x₂。如果目标是减少特征数量,一个简单粗暴的方法是直接丢掉方差较小的特征x₂,只保留x₁

[在此处插入图片16]

  • 然而,直接丢弃特征会损失信息。一个更好的方法是创造一个新的特征z,它能同时捕捉x₁(长度)和x₂(高度)的信息。例如,我们可以找到一个新的z轴,它代表了汽车的整体“尺寸”。这样,我们就成功地将2个特征压缩为了1个特征。
  • 降维的目标:用更少的特征来表示数据,同时尽可能多地保留原始数据中的信息。

2.2 PCA的应用:数据可视化

[在此处插入图片17]

[在此处插入图片18]

[在此处插入图片19]

[在此处插入图片20]

降维的一个主要应用是数据可视化

  • 人类的视觉系统很难理解超过三维的数据。
  • 如果我们的数据集有50个特征,我们无法直接将其画出来。
  • 通过使用降维算法(如PCA),我们可以将50个特征压缩为2个新的特征z₁z₂
  • 然后,我们可以在一个二维平面上绘制这些新的(z₁, z₂)坐标,从而观察数据的分布、聚类和异常点,获得对高维数据的直观理解。

2.3 主成分分析 (PCA) 算法

PCA是最常用和最基础的降维算法。

[在此处插入图片21]

1. 数据预处理

  • 在运行PCA之前,必须对数据进行预处理。
  • 均值归一化 (Mean normalization):将每个特征的均值调整为0。
  • 特征缩放 (Feature scaling):将每个特征的取值范围缩放到相似的区间。

[在此处插入图片22]

[在此处插入图片23]

[在此处插入图片24]

2. 寻找主成分

  • PCA的核心思想是,寻找一个新的坐标轴(或方向),称为主成分(Principal Component)
  • 这个主成分的方向被选择为能使原始数据投影(project)到该轴上后,投影点的方差最大的方向。
  • 最大化方差的意义:方差越大,意味着数据点在投影后散布得越开,这等同于保留了原始数据中最多的信息。如果投影后所有点都挤在一起(方差小),则意味着大量原始信息丢失了。

[在此处插入图片25]

[在此处插入图片26]

3. 计算新坐标

  • 找到了主成分轴(由一个单位向量表示)后,原始数据点 x 在这个新轴上的坐标 z,可以通过计算 x 与该单位向量的点积(dot product得到。

[在此处插入图片27]

4. 多个主成分

  • 如果想将数据降到k维,PCA会找到k个相互正交(perpendicular的主成分。
  • 第一个主成分 z₁ 是最大化投影方差的方向。
  • 第二个主成分 z₂ 是在与z₁正交的所有方向中,最大化投影方差的方向,以此类推。

2.4 PCA与线性回归的区别

[在此处插入图片28]

[在此处插入图片29]

PCA有时会被误认为是线性回归,但它们是完全不同的算法。

  • 线性回归
    • 是一个监督学习算法,有输入x和输出y
    • 目标是找到一条线,最小化预测值与真实值y之间的垂直距离(预测误差)。
  • PCA
    • 是一个无监督学习算法,只有输入数据x,没有y
    • 目标是找到一个低维度的子空间(由主成分轴定义),最小化原始数据点到这个子空间的正交投影距离,其等价于最大化投影后的方差。

2.5 数据重建与实践

[在此处插入图片30]

从低维重建高维数据

  • 降维是一个有信息损失的过程,但我们也可以从降维后的坐标z近似地重建(reconstruct出原始的高维坐标。
  • 方法是将降维后的坐标值z乘以其对应的主成分单位向量。

[在此处插入图片31]

[在此处插入图片32]

[在此处插入图片33]

Scikit-learn库提供了非常易于使用的PCA实现。下面我们将通过一个具体的例子,来展示如何使用它,并详细解释每一步的含义和结果。

准备工作与数据

首先,导入必要的库并创建示例数据。

import numpy as np
from sklearn.decomposition import PCA# 创建一个2D的示例数据集X,包含6个样本点
X = np.array([[1, 1], [2, 1], [3, 2], [-1, -1], [-2, -1], [-3, -2]])

案例1:将数据从2D降至1D

我们的目标是找到一个最佳的一维直线来表示这6个点。

# 1. 初始化PCA模型,指定要降到的维度 n_components=1
pca_1 = PCA(n_components=1)# 2. 拟合数据:让PCA算法学习数据的结构
pca_1.fit(X)# 3. 查看方差解释比例
print(f"Explained variance ratio (1 component): {pca_1.explained_variance_ratio_}")# 4. 转换数据:将原始数据投影到新的1D主成分轴上
X_trans_1 = pca_1.transform(X)
print("Transformed data (1D):\n", X_trans_1)# 5. (可选) 重建数据:从1D数据近似恢复回2D
X_reconstructed_1 = pca_1.inverse_transform(X_trans_1)
print("Reconstructed data from 1D:\n", X_reconstructed_1)

代码解释与结果分析

  • pca_1 = PCA(n_components=1): 创建一个PCA类的实例。n_components=1告诉算法,我们的目标是找到1个主成分,即将数据降到1维。
  • pca_1.fit(X): 这是PCA的核心步骤。.fit()方法会执行以下操作:
    • 对数据X进行均值归一化。
    • 计算数据的协方差矩阵。
    • 找到能最大化数据投影后方差的那个方向(即第一个主成分),并将其存储在对象内部。
  • pca_1.explained_variance_ratio_: 这是一个非常有用的属性。它返回一个列表,表示每个主成分所能解释的原始数据方差的比例。
    • 输出 [0.992] 意味着我们找到的这一个主成分就捕捉了原始2D数据中99.2%的信息(方差)。这是一个非常高的比例,说明降到1维是合理且有效的。
  • X_trans_1 = pca_1.transform(X): .transform()方法使用已经拟合好的主成分,将原始数据X的每个点都投影到这个新的1D轴上。
    • 输出 X_trans_1 是一个 (6, 1) 的数组,每一行只有一个数值,这个数值就是原始2D点在新1D坐标系中的坐标。
  • X_reconstructed_1 = pca_1.inverse_transform(X_trans_1): .inverse_transform()是一个逆向操作。它将1D的坐标“投射”回原始的2D空间。
    • 输出 X_reconstructed_1 是一个 (6, 2) 的数组。注意,它只是原始数据X的一个近似,因为在降维过程中,那0.8%的方差信息已经丢失了。所有重建后的点都精确地落在那条由第一个主成分定义的直线上。

案例2:将数据从2D转换到新的2D坐标系

n_components等于原始数据的维度时,PCA不会减少维度,而是会找到一组新的正交基(坐标系),即所有主成分。

# 1. 初始化PCA模型,n_components=2
pca_2 = PCA(n_components=2)# 2. 拟合数据
pca_2.fit(X)# 3. 查看方差解释比例
print(f"Explained variance ratio (2 components): {pca_2.explained_variance_ratio_}")# 4. 转换数据到新的2D坐标系
X_trans_2 = pca_2.transform(X)
print("Transformed data (2D):\n", X_trans_2)

代码解释与结果分析

  • pca_2 = PCA(n_components=2): 创建PCA实例,目标是找到2个主成分。
  • pca_2.explained_variance_ratio_:
    • 输出 [0.992, 0.008] (数值可能略有不同) 意味着:
      • 第一个主成分(新坐标系的z₁轴)解释了99.2%的方差。
      • 第二个主成分(新坐标系的z₂轴,与z₁正交)解释了剩余的0.8%的方差。
  • X_trans_2 = pca_2.transform(X):
    • 输出 X_trans_2 是一个 (6, 2) 的数组。这不再是降维,而是对原始数据的一次坐标系旋转
    • 第一列是每个点在z₁轴上的坐标,第二列是每个点在z₂轴上的坐标。因为没有信息丢失,这次的inverse_transform可以完美地恢复出原始数据X

2.6 PCA的应用总结

[在此处插入图片34]

PCA的主要应用场景:

  • 数据可视化:将数据降至2维或3维进行绘图,是其最主要和最可靠的应用。
  • 数据压缩:将数据降维以减少存储空间或传输成本。
  • 加速监督学习:在将数据喂给一个监督学习模型之前,先用PCA进行降维,可以减少模型的训练时间。但这种做法需要谨慎,应优先考虑在原始数据上训练,只有在性能瓶颈确实存在时才尝试使用PCA。
http://www.dtcms.com/a/574078.html

相关文章:

  • 烟台网站建设薇企汇互联见效付款静态网站制作流程
  • 2.1 ShaderLab - 渲染状态
  • 在Android设备上打开Perfetto调试日志开关
  • 大型门户网站源码线上培训网站开发
  • 拓扑排序的实现
  • 手机网站模板怎么用网络竞价托管公司
  • 【linux】基础开发工具(3)gcc/g++,动静态库
  • 零基础入门C语言之枚举和联合体
  • PostIn零基础学习 - 如何快速导入PostMan数据,实现数据迁移
  • linux安装mysql说明
  • 大良陈村网站建设广东建设信息网行业版
  • Electron开发应用完整指南
  • 蓝牙音箱东莞网站建设wordpress 有赞云
  • 150.ddr写入数据时数据帧边界对齐问题
  • 济南 制作网站 公司凡科网站怎么做外链
  • 沈阳做网站推广的公司878网站正在建设中
  • Java基础语言进阶学习——4,Java异常体系和自定义异常
  • junit使用
  • 电商网站开发需要掌握哪些知识技能做黑彩网站会怎样处罚
  • 自制51单片机开发板:STC89C52RC最小系统+LCD1602A屏幕
  • 崇州网站制作网站下载软件
  • 实现El-table 每行后面加验证
  • 淘宝网站制作广州公共资源交易
  • 在IAR Embedded Workbench for Arm中开发和调试Infineon MOTIX™ MCU
  • 贵阳市花溪区建设局网站商河做网站公司
  • JDK Maven Tomcat部分配置细节(自用)
  • 网站开发文档步骤应该怎么写开网站设计公司多少钱
  • 城市超级智能体破解落地难题,联想开启智慧城市4.0时代
  • 小型企业门户网站源码电商平台开发系统软件平台
  • 【16】Selenium+Python 接管已打开谷歌浏览器