我想在pyspark应用程序中使用预训练的嵌入模型(快速文本)。
因此,如果我广播文件(.bin),则会引发以下异常: 追溯(最近一次通话):
cPickle.PicklingError: Could not serialize broadcast: OverflowError: cannot serialize a string larger than 2 GiB
相反,我尝试使用sc.addFile(modelpath)
,其中modelpath=path/to/model.bin
如下:
我创建一个名为fasttextSpark.py的文件
import gensim
from gensim.models.fasttext import FastText as FT_gensim
# Load model (loads when this library is being imported)
model = FT_gensim.load_fasttext_format("/project/6008168/bib/wiki.en.bin")
# This is the function we use in UDF to predict the language of a given msg
def get_vector(msg):
pred = model[msg]
return pred
和testSubmit.sh:
#!/bin/bash
#SBATCH -N 2
#SBATCH -t 00:10:00
#SBATCH --mem 20000
#SBATCH --ntasks-per-node 1
#SBATCH --cpus-per-task 32
module load python/2.7.14
source "/project/6008168/bib/ENV2.7.14/bin/activate"
module load spark/2.3.0
spark-submit /project/6008168/bib/test.py
和test.py:
from __future__ import print_function
import sys
import time
import math
import csv
import datetime
import StringIO
import pyspark
import gensim
from operator import add
from pyspark.sql import *
from pyspark.sql import SparkSession
from pyspark import SparkContext, SparkConf
from gensim.models.fasttext import FastText as FT_gensim
appName = "bib"
modelpath = "/project/6008168/bib/wiki.en.bin"
conf = (SparkConf()
.setAppName(appName)
.set("spark.executor.memory", "12G")
.set("spark.network.timeout", "800s")
.set("spark.executor.heartbeatInterval", "20s")
.set("spark.driver.maxResultSize", "12g")
.set("spark.executor.instances", 2)
.set("spark.executor.cores", 30)
)
sc = SparkContext(conf = conf)
#model = FT_gensim.load_fasttext_format(modelpath)
sc.addFile(modelpath)
sc.addPyFile("/project/6008168/bib/fasttextSpark.py")
# Import our custom fastText language classifier lib
import fasttextSpark
print ("nights = ", fasttextSpark.get_vector("nights"))
print ("done")
现在,每个节点都将拥有一个预训练数据集的副本。有些单词的词汇量不足,因此每次我面对这些单词时,我都想为其创建一个随机但固定的向量并将该词及其向量添加到字典中。
那么,如何在每个节点中维护这样的字典?
实际上,假设我的rdd遵循my_rdd =(id,句子),并且我想通过将其单词的向量相加来找到该句子的嵌入向量。嵌入模型将被加载多少次。例如:
假设rdd=("id1", "motorcycle parts")
,我的实现是否两次加载模型:一次用于摩托车,一次用于零件?如果是,我的方法是无效的吗?在这种情况下,应该采用哪种最佳方法?
答案 0 :(得分:1)
在Python模块变量被装载模块时计算一次。因此该变量将在每个解释器中加载一次并保持活动状态,只要解释器保持活动状态即可。
但是,Spark辅助进程不共享内存,因此每个辅助进程将有一个字典副本。如果你有一个广播变量相同的情况是真实的。
因此,您当前的解决方案尽可能地接近您想要的解决方案,而无需使用低级原语(例如内存映射)或外部存储。