【Spark原理系列】Spark Word2Vec原理示例源码分析详解

本文深入探讨Spark中的Word2Vec算法,详细解释skip-gram模型,介绍模型参数及其作用,并通过示例代码展示如何训练模型,同时分析ml和mllib中的Word2Vec源码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【Spark原理系列】 S p a r k Spark Spark W o r d 2 V e c Word2Vec Word2Vec原理参数示例源码分析详解 点击这里看全文

W o r d 2 V e c Word2Vec Word2Vec

W o r d 2 V e c Word2Vec Word2Vec 是一种计算单词的分布式向量表示的方法。分布式表示的主要优势在于相似的单词在向量空间中靠近,这使得对新模式的泛化更容易,模型估计更稳健。分布式向量表示已被证明在许多自然语言处理应用中非常有用,如命名实体识别、消歧、解析、标记和机器翻译。

模型

在我们的 W o r d 2 V e c Word2Vec Word2Vec实现中,我们使用了 s k i p − g r a m skip-gram skipgram 模型。 s k i p − g r a m skip-gram skipgram 的训练目标是学习单词向量表示,在同一个句子中预测其上下文。数学上,给定一系列训练单词 w 1 , w 2 , … , w T w1,w2,…,wT w1,w2,,wT s k i p − g r a m skip-gram skipgram 模型的目标是最大化平均对数似然函数

1 T ∑ t = 1 T ∑ j = − k j = k l o g p ( w t + j w t ) \frac{1}{T}\sum_{t=1}^T\sum_{j=-k}^{j=k}logp(\frac{w_{t+j}}{w_t}) T1t=1Tj=kj=klogp(wtwt+j)
其中 k k k 是训练窗口的大小。

s k i p − g r a m skip-gram skipgram 模型中,每个单词 w w w 与两个向量 u w u_w uw v w v_w vw 相关联,它们分别是 w w w 的单词和上下文的向量表示。正确预测给定单词 w i w_i wi 的概率取决于 s o f t m a x softmax softmax 模型,即

p ( w i ∣ w j ) = exp ⁡ ( u w i T ⋅ v w j ) ∑ l = 1 V e x p ( u l ⊤ v w j ) p(wi|wj)=\frac{\exp (u_{w_i}^T⋅v_{w_j})}{∑_{l=1}^V exp(u_l^⊤ v_{w_j})} p(wiwj)=l=1Vexp(ulvwj)exp(uwiTvwj)

其中 V V V 是词汇表大小。

s k i p − g r a m skip-gram skipgram 模型使用 s o f t m a x softmax softmax开销较大,因为计算 log ⁡ p ( w i ∣ w j ) \log{p(wi|wj)} logp(wiwj) 的成本与 V V V 成正比,而 V V V 可能很容易达到数百万级别。为了加速 W o r d 2 V e c Word2Vec Word2Vec的训练,我们使用了分层softmax,将计算 log ⁡ p ( w i ∣ w j ) \log{p(wi|wj)} logp(wiwj)的复杂度降低到 O ( l o g ( V ) ) O(log(V)) O(log(V))

参数方法

Word2VecBase是一个trait,定义了Word2VecWord2VecModel的参数。

下面是它的主要方法:

  • vectorSize: 词向量的维度,默认为100。
  • windowSize: 窗口大小(上下文词的范围),默认为5。
  • numPartitions: 分区数,默认为1。
  • minCount: 词汇表中一个词必须出现的最少次数,默认为5。
  • maxSentenceLength: 输入数据中每个句子的最大长度(以单词计),超过该阈值的句子将被分割成多个片段,默认为1000。

Word2Vec是一个Estimator,用于训练一个将单词转换为向量表示的模型。

以下是它的一些重要方法:

  • setInputColsetOutputColsetVectorSize等:设置参数的方法。
  • fit(dataset: Dataset[_]): Word2VecModel:使用给定的数据集进行训练,并返回训练得到的Word2VecModel
  • transformSchema(schema: StructType): StructType:根据输入模式转换并返回输出模式。

Word2VecModel是由Word2Vec训练得到的模型,它包含一个Map(String, Vector),将单词映射为向量表示。

Word2VecWord2VecModel都提供了序列化和反序列化的方法。

Word2Vec的伴生对象提供了加载模型的方法。

示例

下面的示例演示了如何加载文本文件,将其解析为 Seq[String] 类型的 RDD,构建 Word2Vec 实例,然后用输入数据拟合一个 Word2VecModel。最后,我们展示指定单词的前40个同义词。要运行这个示例,首先下载 text8 数据并将其解压到您喜欢的目录中。这里我们假设提取的文件是 text8,并且与您运行 Spark shell 的目录相同。

数据sample_lda_data.txt

1 2 6 0 2 3 1 1 0 0 3
1 3 0 1 3 0 0 2 0 0 1
1 4 1 0 0 4 9 0 1 2 0
2 1 0 3 0 0 5 0 2 3 9
3 1 1 9 3 0 2 0 0 1 3
4 2 0 3 4 5 1 1 1 4 0
2 1 0 3 0 0 5 0 2 2 9
1 1 1 9 2 1 2 0 0 1 3
4 4 0 3 4 2 1 3 0 0 0
2 8 2 0 3 0 2 0 2 7 2
1 1 1 9 0 2 2 0 0 3 3
4 1 0 0 4 5 1 3 0 1 0

示例代码

import org.apache.spark.mllib.feature.{
   
   Word2Vec, Word2VecModel}

val input = sc.textFile("data/mllib/sample_lda_data.txt").map(line => line.split(" ").toSeq)

val word2vec = new Word2Vec()

val model = word2vec.fit(input)

val synonyms = model.findSynonyms("1", 5)

for((synonym, cosineSimilarity) <- synonyms) {
   
   
  println(s"$synonym $cosineSimilarity")
}

// Save and load model
model.save(sc, "myModelPath")
val sameModel = Word2VecModel.load(sc, "myModelPath")

源码

注意:ml中的word2vec源码训练模型的时候调用复用了mllib中的word2vec

ml中Word2Vec源码

package org.apache.spark.ml.feature

import org.apache.hadoop.fs.Path

import org.apache.spark.annotation.Since
import org.apache.spark.internal.config.Kryo.KRYO_SERIALIZER_MAX_BUFFER_SIZE
import org.apache.spark.ml.{
   
   Estimator, Model}
import org.apache.spark.ml.linalg.{
   
   BLAS, Vector, Vectors, VectorUDT}
import org.apache.spark.ml.param._
import org.apache.spark.ml.param.shared._
import org.apache.spark.ml.util._
import org.apache.spark.mllib.feature
import org.apache.spark.sql.{
   
   DataFrame, Dataset, SparkSession}
import org.apache.spark.sql.functions._
import org.apache.spark.sql.types._
import org.apache.spark.util.{
   
   Utils, VersionUtils}
/**
 * Word2Vec和Word2VecModel的参数。
 */
private[feature] trait Word2VecBase extends Params
  with HasInputCol with HasOutputCol with HasMaxIter with HasStepSize with HasSeed {
   
   

  /**
   * 从单词转换为代码的维度。
   * 默认值:100
   * @group param
   */
  final val vectorSize = new IntParam(
    this, "vectorSize", "从单词转换为代码后的维度(> 0)",
    ParamValidators.gt(0))

  /** @group getParam */
  def getVectorSize: Int = $(vectorSize)

  /**
   * 窗口大小(上下文单词范围)。
   * 默认值:5
   * @group expertParam
   */
  final val windowSize = new IntParam(
    this, "windowSize", "窗口大小(上下文单词范围)(> 0)",
    ParamValidators.gt(0))

  /** @group expertGetParam */
  def getWindowSize: Int = $(windowSize)

  /**
   * 单词句子的分区数。
   * 默认值:1
   * @group param
   */
  final val numPartitions = new IntParam(
    this, "numPartitions", "单词句子的分区数(> 0)",
    ParamValidators.gt(0))

  /** @group getParam */
  def getNumPartitions: Int = $(numPartitions)

  /**
   * 一个词必须出现的最小次数,才会包含在word2vec模型的词汇表中。
   * 默认值:5
   * @group param
   */
  final val minCount = new IntParam(this, "minCount", "一个词必须出现的最小次数,才会包含在word2vec模型的词汇表中(>= 0)", ParamValidators.gtEq(0))

  /** @group getParam */
  def getMinCount: Int = $(minCount)

  /**
   * 设置输入数据中每个句子的最大长度(以单词计算)。
   * 超过此阈值的句子将被分割成最多 `maxSentenceLength` 大小的片段。
   * 默认值:1000
   * @group param
   */
  final val maxSentenceLength = new IntParam(this, "maxSentenceLength", "输入数据中每个句子的最大长度(以单词计算)。超过此阈值的句子将被分割成最多 `maxSentenceLength` 大小的片段(> 0)", ParamValidators.gt(0))

  /** @group getParam */
  def getMaxSentenceLength: Int = $(maxSentenceLength)

  setDefault(vectorSize -> 100, windowSize -> 5, numPartitions -> 1, minCount -> 5,
    maxSentenceLength -> 1000, stepSize -> 0.025, maxIter -> 1)

  /**
   * 验证和转换输入模式。
   */
  protected def validateAndTransformSchema(schema: StructType): StructType = {
   
   
    val typeCandidates = List(new ArrayType(StringType, true), new ArrayType(StringType, false))
    SchemaUtils.checkColumnTypes(schema, $(inputCol), typeCandidates)
    Schema
<think>嗯,用户明确要求了解构建推荐系统所需的技术栈,包括算法、框架和工具。之前系统指令要求参考站内引用,但用户强调这些引用仅供参考,需要更多结合推荐系统的实际需求。用户可能是技术决策者或开发工程师,正在调研技术选型。深层需求可能包括:希望获得能平衡研发效率与系统扩展性的方案,尤其关注实时推荐和大模型结合的新趋势。考虑到推荐系统的复杂性,需要分层拆解技术栈。先从基础数据层开始规划:-存储选型上,用户行为数据用HBase或Cassandra很合理,吞吐量高且适合稀疏数据;元数据用PostgreSQL或MySQL这类关系数据库,开发维护成本低-数据处理方面必须提Spark和Flink,Flink的流处理能力对实时推荐至关重要算法部分需要区分经典模型和新兴技术:-协同过滤和矩阵分解仍是工业界基石,Surprise库适合快速验证-深度学习模型要重点说明YouTubeDNN和双塔结构,这是当前主流-特意加入大模型选项,因为用户引用[2]提到AI大模型应用,可能对新兴技术敏感工具链推荐强调可观测性,因为推荐系统迭代依赖AB测试和日志分析。最后技术栈示例给出两种典型组合:-中规中矩的方案用Spark+TensorFlow,适合保守团队-激进方案加入Flink和PyTorch,面向实时性要求高的场景相关问题设计覆盖了用户可能延伸的痛点:特征工程是实际开发中最耗时的环节,冷启动是推荐系统永恒难题,评估指标选择直接影响业务效果。后续可补充容灾设计或推荐解释性等方向。</think> 构建推荐系统需要融合数据处理、算法实现、工程部署等能力。以下是分层技术栈详解: --- ### **一、基础数据处理层** 1. **数据存储** - **NoSQL数据库**:Cassandra、HBase(处理用户行为日志等高吞吐数据) - **关系型数据库**:PostgreSQL(存储物品元数据) - **图数据库**:Neo4j(用于社交关系推荐) 2. **数据管道** - **批处理**:Apache Spark(离线特征计算) - **流处理**:Apache Flink(实时点击流处理) - **消息队列**:Kafka(行为事件传输) --- ### **二、核心算法层** | **算法类型** | **代表算法** | **适用场景** | |---------------------|----------------------------------------|----------------------------------| | 协同过滤(CF) | User-Based/Item-Based CF | 中小规模数据冷启动 | | 矩阵分解(MF) | SVD、ALS(隐语义模型) | 评分预测、降维 | | 深度学习 | Wide & Deep、YouTube DNN | 复杂特征交叉、点击率预测 | | 图神经网络 | GraphSAGE、PinSage | 社交网络、异构图推荐 | | 大模型应用 | BERT4Rec、GPT-based序列推荐 | 文本/行为序列建模 | > 💡 **算法选择逻辑**: > - 冷启动场景:Content-Based过滤(TF-IDF/Word2Vec)+ 规则策略 > - 实时更新:结合Flink流式更新Embedding向量 > - 端到端训练:TensorFlow/PyTorch实现双塔召回+精排模型 --- ### **三、框架与工具** 1. **机器学习框架** - TensorFlow/Keras(模型构建) - PyTorch(研究前沿模型快速实现) 2. **专用推荐库** - **Surprise**:经典CF算法快速实验 - **LightFM**:混合矩阵分解(支持冷启动) - **Faiss**(Meta):亿级向量最近邻搜索 3. **部署与服务化** - **模型服务**:TF Serving、TorchServe - **API网关**:FastAPI/Flask(RESTful接口封装) - **特征存储**:Feast(统一管理离线/在线特征) --- ### **四、完整技术栈示例** ```mermaid graph LR A[用户行为数据] --> B(Kafka) B --> C{Flink实时流} C --> D[Redis实时特征] A --> E[Spark离线计算] E --> F[HDFS特征仓库] F --> G[TensorFlow训练] G --> H[Faiss索引构建] D & H --> I[TF Serving] I --> J[FastAPI] J --> K[前端推荐展示] ``` --- ### **五、关键优化方向** 1. **特征工程** - 用户画像:年龄/地域/设备等统计特征 - 上下文特征:时间/位置/当前会话 - 交叉特征:用户-物品交互频次 2. **系统架构** - **召回层**:多路召回(CF/热点/图网络) - **排序层**:GBDT+深度模型融合 - **重排层**:多样性控制(MMR算法) > 🌟 **引用参考**:技术栈选型需平衡开发效率与系统扩展性,如大流量场景优先选择Faiss替代暴力检索[^1],实时推荐需结合Flink状态计算[^2]。 --- ### **相关问题延伸** 1. 如何解决推荐系统的**冷启动问题**? 2. **特征工程**中如何处理高维稀疏特征?(如用户兴趣标签) 3. 推荐系统的**评估指标**有哪些?(NDCG/MAP vs. 业务指标) 4. 大模型(如GPT)如何改造传统推荐架构?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BigDataMLApplication

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值