spaCy 对于例如日语的NLP管道的最大长度,

ddarikpa  于 2个月前  发布在  其他
关注(0)|答案(4)|浏览(42)

不确定这是否是预期发生的情况,还是我自己的误解。我假设是误解,所以我选择了文档报告。

Language (nlp) 类有一个 max_length 参数,对于日语等语言似乎表现不同。

我目前正尝试通过考虑 max_length 并将文本拆分为基于该值的块来对过长的文本进行分块。例如,英语文本在这种情况下似乎没有任何问题。

基本方法代码:

if len(content) > nlp.max_length:
    for chunk in __chunk_text(content, nlp.max_length-100):
        doc = nlp(chunk)
        #....

然而,对于配置字符串 ja_core_news_sm,这不起作用。
经过一些分析,我注意到不是长度而是字节量需要考虑。

def __utf8len(s:str):
    return len(s.encode('utf-8'))

if __utf8len(content) > nlp.max_length:
    #...

然而,即使采用字节方法,我也遇到了一个错误,看起来像是与 max_length 相关的,但也许不是?
稍微减少的错误跟踪:

doc = nlp(content)
  File "/usr/local/lib/python3.9/site-packages/spacy/language.py", line 1014, in __call__
    doc = self._ensure_doc(text)
  File "/usr/local/lib/python3.9/site-packages/spacy/language.py", line 1105, in _ensure_doc
    return self.make_doc(doc_like)
  File "/usr/local/lib/python3.9/site-packages/spacy/language.py", line 1097, in make_doc
    return self.tokenizer(text)
  File "/usr/local/lib/python3.9/site-packages/spacy/lang/ja/__init__.py", line 56, in __call__
    sudachipy_tokens = self.tokenizer.tokenize(text)
Exception: Tokenization error: Input is too long, it can't be more than 49149 bytes, was 63960

我还仔细检查了 max_length(1000000)、字符串长度(63876)和字节长度(63960)的值。
手动将 max_length 设置为 1100000 没有改变错误信息,所以我假设可能是其他东西(也许是 Sudachi 本身?)定义了输入太长的错误信息。
实际问题是什么以及如何解决它(用于查找大小限制)对于文档来说会很有趣。

此问题与哪个页面或部分相关?

不确定在哪里添加,因为如果直接与日语有关的话就不确定了。然而,在 https://spacy.io/models/ja 或者 https://spacy.io/usage/models#japanese 中添加一条注解可能会很有意义。此外,关于 max_length 的一般说明可能需要扩展(如果正确地假设的话,也许类似于 character length isn't the classic python len(<string>) function but the byte size (e.g. letter "I" - len 1 - byte 1 & kanji "私" - len 1 - byte 3))。

pxy2qtax

pxy2qtax1#

nlp.max_length 不是一个硬性的内部约束,而是一种笨拙的方式来保护用户免受令人困惑的OOM错误的困扰。它是用 "核心" 管道和一个并不特别新的消费级笔记本电脑设置的。如果你的系统实际上并没有内存耗尽,你可以放心地增加它,尤其是对于像分词这样的简单任务。
另一方面,核心管道中的任何组件都不会从非常长的上下文中受益(通常,一个段落或一页就足够了),因此拆分文本通常是最佳方法。非常长的文本可能会占用大量RAM,尤其是对于 parserner
这个日语限制与 nlp.max_length 完全分开,直接来自 sudachipy(我之前实际上没有遇到过)。
他们的错误信息似乎还不错(比带有令人困惑的解析器中间的OOM消息要好得多),所以我不知道是否有必要在 spacy 日本分词器中添加另一个检查,这可能会在未来与上游 sudachipy 约束不同步。
但你是对的,nlp.max_length 不会直接帮助限制字节长度,除非你将其设置得非常低。但再次,较低的限制在实践中可能没问题。
我们会考虑将其添加到文档中!

j2cgzkjk

j2cgzkjk2#

感谢您的解释,这帮助我消除了困惑,我知道如何为我的用例继续进行。

如果有人偶然遇到这个问题,以下是我使用的字节拆分代码(尽管可能仍然有很多优化潜力)

# splits not after x bytes but ensures that max x bytes are used without destroying the final character 
def __chunk_text_on_bytes(text: str, max_chunk_size: int = 1_000_000):
    factor = len(text) / __utf8len(text)
    increase_by = int(max(min(max_chunk_size*.1,10),1))
    initial_size_guess = int(max(max_chunk_size * factor - 10,1))
    final_list = []
    remaining = text
    while len(remaining):
        part = remaining[:initial_size_guess]
        if __utf8len(part) > max_chunk_size:
            initial_size_guess = max(initial_size_guess - min(max_chunk_size *.001,10),1) 
            continue
        cut_after = initial_size_guess
        while __utf8len(part) < max_chunk_size and part != remaining:
            cut_after = min(len(remaining), cut_after+increase_by)
            part = remaining[:cut_after]
            
        if __utf8len(part) > max_chunk_size:
            cut_after-=increase_by
        final_list.append(remaining[:cut_after])
        remaining = remaining[cut_after:]

    return final_list
14ifxucb

14ifxucb3#

现有文档

"""
...
max_length (int): 用于处理的文本的最大允许长度。
...
"""

更新后的文档

"""
...
max_length (int): 用于处理的文本的最大允许长度。max_length的行为可能因不同的语言而有所不同。请参阅针对特定语言的文档以获取更多详细信息。
...

tgabmvqs

tgabmvqs4#

感谢您的建议!我认为这个描述对用户来说有些困惑,因为nlp.max_length本身对所有语言的行为都是相同的。我们需要强调的是,一些单独的分词器或组件,尤其是那些 Package 第三方库的组件,可能有自己的内部长度限制。

相关问题