调用 NLTK 并在 databricks pyspark 上找不到“punkt”错误
Posted
技术标签:
【中文标题】调用 NLTK 并在 databricks pyspark 上找不到“punkt”错误【英文标题】:NLTK is called and got error of "punkt" not found on databricks pyspark 【发布时间】:2020-08-16 04:32:20 【问题描述】:我想调用 NLTK 来通过 pyspark 在数据块上做一些 NLP。 我已经从 databricks 的库选项卡中安装了 NLTK。它应该可以从所有节点访问。
我的 py3 代码:
import pyspark.sql.functions as F
from pyspark.sql.types import StringType
import nltk
nltk.download('punkt')
def get_keywords1(col):
sentences = []
sentence = nltk.sent_tokenize(col)
get_keywords_udf = F.udf(get_keywords1, StringType())
我运行上面的代码得到:
[nltk_data] Downloading package punkt to /root/nltk_data...
[nltk_data] Package punkt is already up-to-date!
当我运行以下代码时:
t = spark.createDataFrame(
[(2010, 1, 'rdc', 'a book'), (2010, 1, 'rdc','a car'),
(2007, 6, 'utw', 'a house'), (2007, 6, 'utw','a hotel')
],
("year", "month", "u_id", "objects"))
t1 = t.withColumn('keywords', get_keywords_udf('objects'))
t1.show() # error here !
我收到错误:
<span class="ansi-red-fg">>>> import nltk
PythonException:
An exception was thrown from the Python worker. Please see the stack trace below.
Traceback (most recent call last):
LookupError:
**********************************************************************
Resource punkt not found.
Please use the NLTK Downloader to obtain the resource:
>>> import nltk
>>> nltk.download('punkt')
For more information see: https://www.nltk.org/data.html
Attempted to load tokenizers/punkt/PY3/english.pickle
Searched in:
- '/root/nltk_data'
- '/databricks/python/nltk_data'
- '/databricks/python/share/nltk_data'
- '/databricks/python/lib/nltk_data'
- '/usr/share/nltk_data'
- '/usr/local/share/nltk_data'
- '/usr/lib/nltk_data'
- '/usr/local/lib/nltk_data'
- ''
我已经下载了“punkt”。它位于
/root/nltk_data/tokenizers
我已经用文件夹位置更新了 spark 环境中的 PATH。
为什么找不到?
NLTK. Punkt not found 和这个How to config nltk data directory from code? 的解决方案 但它们都不适合我。
我已经尝试更新了
nltk.data.path.append('/root/nltk_data/tokenizers/')
它不起作用。 好像nltk看不到新添加的路径!
我还将 punkz 复制到 nltk 将搜索的路径。
cp -r /root/nltk_data/tokenizers/punkt /root/nltk_data
但是,nltk 还是看不到它。
谢谢
【问题讨论】:
你检查了所有节点下载该文件吗? 您能告诉我如何检查所有节点吗?谢谢 我有一个类似的问题,你的代码失败的原因是你只在主节点上安装了包,而不是在工作节点上。当您的代码在所有机器上并行运行时,工作节点会出错。您需要找到一种在集群创建/设置期间将下载的文件从主服务器复制到工作服务器的方法,或者如果您的集群可以访问互联网,请在函数中下载它(不是最好的方法,但会解除阻止) @KaranSharma,谢谢,但是,我已经从 databricks 的库选项卡中安装了 NLTK。它应该可以从所有节点访问。 另一个潜在问题可能是因为 nltk 库在每个节点上下载 'punkt' 并且节点可能无法访问 Internet,我会检查集群配置并确保 Internet 可用。您甚至可以在所有节点上运行类似 ping 命令的命令来检查问题。 【参考方案1】:当启动 Databricks 单节点集群时,这将正常工作。通过 pip 安装 nltk,然后使用 nltk.download 模块获取预构建的模型/文本作品。
假设:用户在 Databricks 笔记本中使用 Python 作为默认语言进行编程。
在启动多节点集群时,您会遇到几个问题。
您正在注册一个依赖于另一个模块的代码的 UDF。为了使 UDF 在集群中的每个节点上工作,模块需要安装在集群级别(即 nltk 安装在驱动程序和所有工作节点上)。该模块可以像这样在集群启动时通过 init 脚本安装,也可以通过 Databricks Compute 部分中的 library 部分安装。更多信息在这里......(我还在下面给出代码示例) https://docs.microsoft.com/enus/azure/databricks/libraries/cluster-libraries.
现在,当您运行 UDF 时,该模块将存在于集群的所有节点上。
使用nltk.download()
获取模块引用的数据。当我们在多节点集群中交互式地执行 nltk.download() 时,它只会下载到驱动程序节点。因此,当您的 UDF 在其他节点上执行时,这些节点将不会在默认情况下查找的指定路径中包含所需的引用。要查看这些路径,默认路径运行nltk.data.path
。
为了克服这个问题,我探索了两种可能性。其中一个有效。
(不起作用)使用初始化脚本,安装 nltk,然后在同一个初始化脚本中,在安装后通过单线 bash python 表达式调用 nltk.download...
python -c 'import nltk; nltk.download('all');'
我遇到了安装 nltk 但安装后找不到的问题。我假设虚拟环境在这里发挥了作用。
(有效)使用初始化脚本,安装 nltk。
-
创建脚本
dbutils.fs.put('/dbfs/databricks/scripts/nltk-install.sh', """
#!/bin/bash
pip install nltk""", True)
-
检查一下
%sh
head '/dbfs/databricks/scripts/nltk-install.sh'
-
配置集群以在启动时运行初始化脚本
Databricks Cluster Init Script Config
在集群配置中创建环境变量 NLTK_DATA="/dbfs/databricks/nltk_data/"。 nltk 包使用它来搜索数据/模型依赖项。
Databricks Cluster Env Variable Config
启动集群。
在安装并运行集群后检查以确保环境变量已正确创建。
import os
os.environ.get("NLTK_DATA")
然后检查以确保 nltk 指向正确的路径。
import nltk
nltk.data.path
如果 '/dbfs/databricks/nltk_data/ 在列表中,我们很高兴。 下载你需要的东西。
nltk.download('all', download_dir="/dbfs/databricks/nltk_data/")
请注意,我们已将依赖项下载到 Databricks 存储中。现在每个节点都可以访问 nltk 默认依赖项。因为我们在导入 nltk 时在集群创建时指定了环境变量 NLTK_DATA,所以它会在该目录中查找。这里唯一的区别是我们现在将 nltk 指向每个节点都可以访问的 Databricks 存储。
现在,由于数据存在于集群启动时挂载的存储中,我们不需要每次都重新下载数据。
按照这些步骤操作后,您应该已准备好使用 nltk 及其所有默认数据/模型。
【讨论】:
【参考方案2】:这帮助我解决了问题:
import nltk
nltk.download('all')
【讨论】:
我在 Databricks 上遇到了同样的问题。它并不能解决问题。 :(以上是关于调用 NLTK 并在 databricks pyspark 上找不到“punkt”错误的主要内容,如果未能解决你的问题,请参考以下文章
nltk包返回TypeError:'LazyCorpusLoader'对象不可调用