【问题标题】:Fastai - failed initiation of language model in Sentence Piece Processor, cache_dir parameterFastai - 句子处理器中语言模型的启动失败,cache_dir 参数
【发布时间】:2020-01-17 13:30:23
【问题描述】:

我已经浏览网页好几个小时来为我找到解决方案,我认为这可能是一个非常小问题。

我在语言模型启动的最初步骤中使用了 fastai 的句子处理器 (SPProcesor)。

这些步骤的代码如下所示:

bs = 48

processor = SPProcessor(lang='pl')

data_lm = (TextList.from_csv('', target_corpus, processor=processor)
            .split_by_rand_pct(0.1)
            .label_for_lm()           
            .databunch(bs=bs)
          )
data_lm.save(data_lm_file)

执行后出现如下错误:

~/x/miniconda3/envs/fastai/lib/python3.6/site-packages/fastai/text/data.py in process(self, ds)
    466             self.sp_model,self.sp_vocab = cache_dir/'spm.model',cache_dir/'spm.vocab'
    467         if not getattr(self, 'vocab', False):
--> 468             with open(self.sp_vocab, 'r', encoding=self.enc) as f: self.vocab = Vocab([line.split('\t')[0] for line in f.readlines()])
    469         if self.n_cpus <= 1: ds.items = self._encode_batch(ds.items)
    470         else:

FileNotFoundError: [Errno 2] No such file or directory: 'tmp/spm/spm.vocab'

上面执行的代码的正确结果应该如下:
创建了名为“tmp”的文件夹,
包含文件夹“spm”,
其中应放置2个文件,分别命名为:spm.vocab和spm.model。

相反,“tmp”文件夹与我当前目录中名为“cache_dir”.vocab 和“cache_dir”.model 的文件一起创建。
找不到文件夹“spm”。

我找到了一种解决方法。
它包括在 'tmp' 中手动创建一个 'spm' 文件夹并将上述其他 2 个
文件移入其中,并将它们的名称更改为 spm.vocab 和 spm.model。

这使我可以继续我的处理,但我想找到一种方法来跳过
手动移动创建的文件等的必要性。

也许我需要在处理之前传递一些具有特定值的参数(可能是 cache_dir)?

如果您对如何解决该问题有任何想法,请指出这些。
我将不胜感激。

【问题讨论】:

  • 您找到解决方案了吗?我有同样的问题
  • @Ahmad - 如果我的回答有帮助,请告诉我。如果您有包含quotemarkfastai/text/data.py 的较新版本,您仍然可以手动对包含model_prefix 的行应用相同的更改(将其恢复为f"--model_prefix={cache_dir/'spm'} --vocab_size={vocab_sz} --model_type={model_type}"])) 的状态)。
  • @AlexanderPivovarov 谢谢,我会测试你的解决方案并接受它。如果在任何情况下我忘记了,请提醒我

标签: python caching directory fast-ai


【解决方案1】:

如果我将 fastai/text/data.py 中的代码切换到 this commit 的早期版本,我会看到类似的错误。然后,如果我从同一个提交中应用更改,一切都会很好。现在,同一文件的最新版本(应该帮助处理带空格的路径)似乎又引入了另一个错误。

看来问题在于 fastai 试图用引号将参数 --model_prefix 提供给 sentencepiece .SentencePieceTrainer.Train,这使其“行为不端”。

您的一种可能是 (1) 更新到更高版本的 fastai(由于新版本中的另一个错误可能无济于事),或者 (2) 手动将 here 的更改应用于您的安装fastai/text/data.py。这是一个非常小的更改 - 只需删除该行:

cache_dir = cache_dir/'spm'

替换

f'--model_prefix="cache_dir" --vocab_size={vocab_sz} --model_type={model_type}']))

f"--model_prefix={cache_dir/'spm'} --vocab_size={vocab_sz} --model_type={model_type}"]))

如果您对更新安装代码不满意,您可以通过在代码中编写固定版本来替换现有的train_sentencepiece 函数,然后在其他调用之前执行fastai.text.data.train_sentencepiece = my_fixed_train_sentencepiece 之类的操作,从而对模块进行猴子补丁。

因此,如果您使用的是较新版本的库,代码可能如下所示:

import fastai
from fastai.core import PathOrStr
from fastai.text.data import ListRules, get_default_size, quotemark, full_char_coverage_langs
from typing import Collection

def train_sentencepiece(texts:Collection[str], path:PathOrStr, pre_rules: ListRules=None, post_rules:ListRules=None,
    vocab_sz:int=None, max_vocab_sz:int=30000, model_type:str='unigram', max_sentence_len:int=20480, lang='en',
    char_coverage=None, tmp_dir='tmp', enc='utf8'):
    "Train a sentencepiece tokenizer on `texts` and save it in `path/tmp_dir`"
    from sentencepiece import SentencePieceTrainer
    cache_dir = Path(path)/tmp_dir
    os.makedirs(cache_dir, exist_ok=True)
    if vocab_sz is None: vocab_sz=get_default_size(texts, max_vocab_sz)
    raw_text_path = cache_dir / 'all_text.out'
    with open(raw_text_path, 'w', encoding=enc) as f: f.write("\n".join(texts))
    spec_tokens = ['\u2581'+s for s in defaults.text_spec_tok]
    SentencePieceTrainer.Train(" ".join([
        f"--input={quotemark}{raw_text_path}{quotemark} --max_sentence_length={max_sentence_len}",
        f"--character_coverage={ifnone(char_coverage, 0.99999 if lang in full_char_coverage_langs else 0.9998)}",
        f"--unk_id={len(defaults.text_spec_tok)} --pad_id=-1 --bos_id=-1 --eos_id=-1",
        f"--user_defined_symbols={','.join(spec_tokens)}",
        f"--model_prefix={cache_dir/'spm'} --vocab_size={vocab_sz} --model_type={model_type}"]))
    raw_text_path.unlink()
    return cache_dir
        
fastai.text.data.train_sentencepiece = train_sentencepiece

如果您使用的是旧版本,则如下所示:

import fastai
from fastai.core import PathOrStr
from fastai.text.data import ListRules, get_default_size, full_char_coverage_langs
from typing import Collection

def train_sentencepiece(texts:Collection[str], path:PathOrStr, pre_rules: ListRules=None, post_rules:ListRules=None, 
    vocab_sz:int=None, max_vocab_sz:int=30000, model_type:str='unigram', max_sentence_len:int=20480, lang='en',
    char_coverage=None, tmp_dir='tmp', enc='utf8'):
    "Train a sentencepiece tokenizer on `texts` and save it in `path/tmp_dir`"
    from sentencepiece import SentencePieceTrainer
    cache_dir = Path(path)/tmp_dir
    os.makedirs(cache_dir, exist_ok=True)
    if vocab_sz is None: vocab_sz=get_default_size(texts, max_vocab_sz)
    raw_text_path = cache_dir / 'all_text.out'
    with open(raw_text_path, 'w', encoding=enc) as f: f.write("\n".join(texts))
    spec_tokens = ['\u2581'+s for s in defaults.text_spec_tok]
    SentencePieceTrainer.Train(" ".join([
        f"--input={raw_text_path} --max_sentence_length={max_sentence_len}",
        f"--character_coverage={ifnone(char_coverage, 0.99999 if lang in full_char_coverage_langs else 0.9998)}",
        f"--unk_id={len(defaults.text_spec_tok)} --pad_id=-1 --bos_id=-1 --eos_id=-1",
        f"--user_defined_symbols={','.join(spec_tokens)}",
        f"--model_prefix={cache_dir/'spm'} --vocab_size={vocab_sz} --model_type={model_type}"]))
    raw_text_path.unlink()
    return cache_dir
        
fastai.text.data.train_sentencepiece = train_sentencepiece

【讨论】:

    猜你喜欢
    • 2019-07-25
    • 1970-01-01
    • 2019-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-21
    • 1970-01-01
    相关资源
    最近更新 更多