python - 将 Spacy Parser 应用于具有多处理功能的 Pandas DataFrame

标签 python nlp multiprocessing spacy

假设我有一个数据集,比如

iris = pd.DataFrame(sns.load_dataset('iris'))

我可以使用 Spacy.apply 将字符串列解析为标记(我的真实数据集当然每个条目有 >1 个单词/标记)

import spacy # (I have version 1.8.2)
nlp = spacy.load('en')
iris['species_parsed'] = iris['species'].apply(nlp)

结果:

   sepal_length   ... species    species_parsed
0           1.4   ... setosa          (setosa)
1           1.4   ... setosa          (setosa)
2           1.3   ... setosa          (setosa)

我还可以使用这个方便的多处理函数 (thanks to this blogpost) 在数据帧上并行执行大多数任意应用函数:

from multiprocessing import Pool, cpu_count
def parallelize_dataframe(df, func, num_partitions):

    df_split = np.array_split(df, num_partitions)
    pool = Pool(num_partitions)
    df = pd.concat(pool.map(func, df_split))

    pool.close()
    pool.join()
    return df

例如:

def my_func(df):
    df['length_of_word'] = df['species'].apply(lambda x: len(x))
    return df

num_cores = cpu_count()
iris = parallelize_dataframe(iris, my_func, num_cores)

结果:

   sepal_length species  length_of_word
0           5.1  setosa               6
1           4.9  setosa               6
2           4.7  setosa               6

...但出于某种原因,我无法通过这种方式将 Spacy 解析器应用于使用多处理的数据帧。

def add_parsed(df):
    df['species_parsed'] = df['species'].apply(nlp)
    return df

iris = parallelize_dataframe(iris, add_parsed, num_cores)

结果:

   sepal_length species  length_of_word species_parsed
0           5.1  setosa               6             ()
1           4.9  setosa               6             ()
2           4.7  setosa               6             ()

还有其他方法吗?我喜欢 NLP 的 Spacy,但我有很多文本数据,所以我想并行化一些处理功能,但遇到了这个问题。

最佳答案

Spacy 经过高度优化,可以为您进行多重处理。因此,我认为最好的办法是将数据从 Dataframe 中取出并将其作为列表传递给 Spacy 管道,而不是尝试直接使用 .apply

然后您需要整理解析结果,并将其放回 Dataframe 中。

因此,在您的示例中,您可以使用如下内容:

tokens = []
lemma = []
pos = []

for doc in nlp.pipe(df['species'].astype('unicode').values, batch_size=50,
                        n_threads=3):
    if doc.is_parsed:
        tokens.append([n.text for n in doc])
        lemma.append([n.lemma_ for n in doc])
        pos.append([n.pos_ for n in doc])
    else:
        # We want to make sure that the lists of parsed results have the
        # same number of entries of the original Dataframe, so add some blanks in case the parse fails
        tokens.append(None)
        lemma.append(None)
        pos.append(None)

df['species_tokens'] = tokens
df['species_lemma'] = lemma
df['species_pos'] = pos

这种方法适用于小型数据集,但它会占用您的内存,因此如果您要处理大量文本则效果不佳。

关于python - 将 Spacy Parser 应用于具有多处理功能的 Pandas DataFrame,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44395656/

相关文章:

python - tensorflow 基本word2vec示例: Shouldn't we be using weights [nce_weight Transpose] for the representation and not embedding matrix?

Python multiprocessing.Pool map() "TypeError: string indices must be integers, not str"

python - 转换为大写/小写时,字符串会变短吗?

python - 在 for 循环中搜索字符串,而不在循环中单独引用每个字符串

Python inspect 是方法

python - 网络抓取数据的词形还原

Python循环遍历字符串并将其与通配符模式匹配

python - 在整个数据集上计算 TF-IDF 还是仅在训练数据上计算 TF-IDF?

Python 从另一个多处理函数调用一个多处理函数。

python - 为什么我在从不同进程读取文件时出现竞争条件?