为什么Spark的Word2Vec返回一个向量?

运行Spark的Word2Vec示例时,我发现它接收一个字符串数组并输出一个向量。我的问题是,它不应该返回一个矩阵而不是一个向量吗?我原本期望每个输入词对应一个向量。但它返回的却只是一个向量!

或者,它应该接受单个字符串(一个词)作为输入,而不是字符串数组。这样的话,是的,它可以返回一个向量作为输出。但接受字符串数组并返回单个向量对我来说毫无意义。

[更新]

根据@Shaido的请求,这里是我的微小改动以打印输出模式的代码:

public class JavaWord2VecExample {    public static void main(String[] args) {        SparkSession spark = SparkSession                .builder()                .appName("JavaWord2VecExample")                .getOrCreate();        // $example on$        // 输入数据:每行是一个句子或文档中的词袋。        List<Row> data = Arrays.asList(                RowFactory.create(Arrays.asList("Hi I heard about Spark".split(" "))),                RowFactory.create(Arrays.asList("I wish Java could use case classes".split(" "))),                RowFactory.create(Arrays.asList("Logistic regression models are neat".split(" ")))        );        StructType schema = new StructType(new StructField[]{                new StructField("text", new ArrayType(DataTypes.StringType, true), false, Metadata.empty())        });        Dataset<Row> documentDF = spark.createDataFrame(data, schema);        // 学习从词到向量的映射。        Word2Vec word2Vec = new Word2Vec()                .setInputCol("text")                .setOutputCol("result")                .setVectorSize(7)                .setMinCount(0);        Word2VecModel model = word2Vec.fit(documentDF);        Dataset<Row> result = model.transform(documentDF);        for (Row row : result.collectAsList()) {            List<String> text = row.getList(0);            System.out.println("模式: " + row.schema());            Vector vector = (Vector) row.get(1);            System.out.println("文本: " + text + " => \n向量: " + vector + "\n");        }        // $example off$        spark.stop();    }}

它打印出以下内容:

模式: StructType(StructField(text,ArrayType(StringType,true),false), StructField(result,org.apache.spark.ml.linalg.VectorUDT@3bfc3ba7,true))文本: [Hi, I, heard, about, Spark] => 向量: [-0.0033279924420639875,-0.0024428479373455048,0.01406305879354477,0.030621735751628878,0.00792500376701355,0.02839711122214794,-0.02286271695047617]模式: StructType(StructField(text,ArrayType(StringType,true),false), StructField(result,org.apache.spark.ml.linalg.VectorUDT@3bfc3ba7,true))文本: [I, wish, Java, could, use, case, classes] => 向量: [-9.96453288410391E-4,-0.013741840076233658,0.013064394239336252,-0.01155538750546319,-0.010510949650779366,0.004538436819400106,-0.0036846946126648356]模式: StructType(StructField(text,ArrayType(StringType,true),false), StructField(result,org.apache.spark.ml.linalg.VectorUDT@3bfc3ba7,true))文本: [Logistic, regression, models, are, neat] => 向量: [0.012510885251685977,-0.014472834207117558,0.002779599279165268,0.0022389178164303304,0.012743516173213721,-0.02409198731184006,0.017409833287820222]

如果我错了,请纠正我,但输入是一个字符串数组,输出是一个单一的向量。我原本期望每个词都被映射到一个向量中。


回答:

这是试图为Spark的这一设计提供合理的解释,并应被视为对已提供的出色编程解释的补充…

首先,如何精确地组合单个词嵌入并不是Word2Vec模型本身的特征(它是关于单个词的),而是“更高阶”模型关心的问题,如Sentence2Vec、Paragraph2Vec、Doc2VecWikipedia2Vec等(我想你可以再列出几个…)。

话虽如此,事实证明,要获得更大文本片段(短语、句子、推文等)的向量表示,组合词向量的最初方法确实是像Spark ML那样简单地平均各个词的向量表示。

从实践者社区来看,我们有以下内容:

如何连接词向量以形成句子向量(Stack Overflow回答):

至少有三种常见的方法来组合嵌入向量;(a)求和,(b)求和并平均或(c)连接。 […] 参见gensim.models.doc2vec.Doc2Vecdm_concatdm_mean – 它允许你使用这三种选项中的任何一种

Sentence2Vec : 评估流行理论 – 第一部分(词向量的简单平均)(博客文章):

那么,当你有词向量并需要计算句子向量时,你脑海中首先想到的是什么?

只是平均它们?

是的,这就是我们要做的。enter image description here

Sentence2Vec(GitHub仓库):

Word2Vec可以帮助找到具有相似语义含义的其他词。然而,Word2Vec每次只能处理一个词,而一个句子由多个词组成。为了解决这个问题,我编写了Sentence2Vec,它实际上是对Word2Vec的封装。为了获得一个句子的向量,我只是简单地获取句子中每个词的向量和的平均值。

显然,至少对于实践者来说,这种单个词向量的简单平均绝非出乎意料。

这里预期的反驳是,博客文章和Stack Overflow的回答可能并不是那么可信的来源;那么研究人员和相关的科学文献呢?事实证明,这种简单的平均在这里也绝非罕见:

来自句子和文档的分布式表示(Le & Mikolov,Google,ICML 2014):

enter image description here

来自NILC-USP在SemEval-2017任务4:Twitter情感分析的多视图集成(SemEval 2017,第2.1.2节):

enter image description here


现在应该很清楚,Spark ML中的这一特定设计选择绝非随意,甚至并不罕见;我曾就Spark ML中看似荒谬的设计选择写过博客(见Spark 2.0中的分类:“输入验证失败”及其他奇妙的故事),但看起来这并不是这种情况…

Related Posts

为什么我们在K-means聚类方法中使用kmeans.fit函数?

我在一个视频中使用K-means聚类技术,但我不明白为…

如何获取Keras中ImageDataGenerator的.flow_from_directory函数扫描的类名?

我想制作一个用户友好的GUI图像分类器,用户只需指向数…

如何查看每个词的tf-idf得分

我试图了解文档中每个词的tf-idf得分。然而,它只返…

如何修复 ‘ValueError: Found input variables with inconsistent numbers of samples: [32979, 21602]’?

我在制作一个用于情感分析的逻辑回归模型时遇到了这个问题…

如何向神经网络输入两个不同大小的输入?

我想向神经网络输入两个数据集。第一个数据集(元素)具有…

逻辑回归与机器学习有何关联

我们正在开会讨论聘请一位我们信任的顾问来做机器学习。一…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注