有没有办法加载Google's或Glove's预先训练的向量(模型),例如 GoogleNews-vectors-negative300.bin.gz进入 Spark 并执行 Spark 提供的诸如 findSynonyms 之类的操作?还是我需要从头开始加载和操作?
在这篇文章中Load Word2Vec model in Spark ,Tom Lous 建议将 bin 文件转换为 txt 并从那里开始,我已经这样做了..但是下一步是什么?
在我昨天发布的一个问题中,我得到了一个答案,即 Parquet 格式的模型可以加载到 Spark 中,因此我发布这个问题是为了确保没有其他选择。
最佳答案
免责声明:我对 Spark 还很陌生,但以下至少对我有用。
诀窍在于弄清楚如何从一组词向量构建 Word2VecModel 以及处理尝试以这种方式创建模型时遇到的一些问题。
首先,将词向量加载到 map 中。例如,我已将单词向量保存为 Parquet 格式(在名为“wordvectors.parquet”的文件夹中),其中“term”列保存字符串单词,“向量”列将向量保存为数组[float],我可以像 Java 中那样加载它:
// Loads the dataset with the "term" column holding the word and the "vector" column
// holding the vector as an array[float]
Dataset<Row> vectorModel = pSpark.read().parquet("wordvectors.parquet");
//convert dataset to a map.
Map<String, List<Float>> vectorMap = Arrays.stream((Row[])vectorModel.collect())
.collect(Collectors.toMap(row -> row.getAs("term"), row -> row.getList(1)));
//convert to the format that the word2vec model expects float[] rather than List<Float>
Map<String, float[]> word2vecMap = vectorMap.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey, entry -> (float[]) Floats.toArray(entry.getValue())));
//need to convert to scala immutable map because that's what word2vec needs
scala.collection.immutable.Map<String, float[]> scalaMap = toScalaImmutableMap(word2vecMap);
private static <K, V> scala.collection.immutable.Map<K, V> toScalaImmutableMap(Map<K, V> pFromMap) {
final List<Tuple2<K,V>> list = pFromMap.entrySet().stream()
.map(e -> Tuple2.apply(e.getKey(), e.getValue()))
.collect(Collectors.toList());
Seq<Tuple2<K,V>> scalaSeq = JavaConverters.asScalaBufferConverter(list).asScala().toSeq();
return (scala.collection.immutable.Map<K, V>) scala.collection.immutable.Map$.MODULE$.apply(scalaSeq);
}
现在您可以从头开始构建模型。由于 Word2VecModel 工作方式的一个怪癖,您必须手动设置向量大小,并且以一种奇怪的方式进行设置。否则,它默认为 100,并且在尝试调用 .transform() 时会出现错误。这是我发现的一种可行的方法,不确定是否一切都必要:
//not used for fitting, only used for setting vector size param (not sure if this is needed or if result.set is enough
Word2Vec parent = new Word2Vec();
parent.setVectorSize(300);
Word2VecModel result = new Word2VecModel("w2vmodel", new org.apache.spark.mllib.feature.Word2VecModel(scalaMap)).setParent(parent);
result.set(result.vectorSize(), 300);
现在您应该能够像使用自训练模型一样使用 result.transform() 。
我没有测试其他 Word2VecModel 函数来查看它们是否正常工作,我只测试了 .transform()。
关于scala - 是否可以将 word2vec 预训练的可用向量加载到 Spark 中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45506511/