加载数据报错‘expected sequence of length 4 at dim 1 (got 0)’
使用 transformer 将字符串转为 id 序列,字符串为中英文混杂形式,
运行中出现报错:'expected sequence of length 4 at dim 1 (got 0)'
发现是在encoder_plus转换时,将输入的文本根据max_length截断了,导致[MASK]等字段没剪除了,生成的 mask_pos (mask 在字符串中的位置)为空,这样在转为 Tensor 时产生了维度错误。
在预处理时,虽然通过设置的最大长度的对字符串做了筛选,但长度是通过空格split计算的,在encoder转换时,每个汉字对应一个id,英文(注:英文是单词或英文字符的拼接) 则根据vocab.txt中的词替换为 id,这样句长就会超过max_length,截断后会将最后的 [MASK] 删除。
解决方法:
在预处理中用 encode 将字符串转为id序列,根据 id 序列长度及max_length过滤样本
BertTokenizer 中的 encoder、encode_plus 参数 truncation
Sentence-Pair 分类任务中,遇到有关句子长度不一致的报错,可将 truncation设为'longest_first',这样就会依次删除较长句子的最后一个token,直到符合max_length的最大token数量为止。
例如:设置句子最大长度是256,报错为最后一行显示不同的输入中,句子长度不一致问题。但在encode中已经设置了padding='max_length'和truncation=True,truncation=True 默认是only_first,仅对前面一句话做截断,不对后面一句做截断。当遇到sent1长度是50,sent2 长度是300的极端情况,使用“truncation=True”,总长度还是会超出256;truncation='longest_first' 会依次删除较长句子的最后一个token,直到符合 maxlength 的最大 token 数量为止(最新的tokenizer中True和longest_first已经等价了,暂未验证,Tokenizer (huggingface.co))
tokenizer时出现‘##’的词
Bert 有三个tokenizer:FullTokenizer,BasicTokenizer,WordpieceTokenizer;
FullTokenizer 会调用后面两个。
BasicTokenizer:清理特殊字符,去除控制符以及替换空白字符为空格,一些序列标注任务输入需要保持输入长度不变,否则标注无法对上,一般要么使用BasicTokenizer把原数据过一遍,再把标注对上,要么使用list方法代替 bert 的 tokenizer;中文分割:将中文每个汉字单独作为一个token
小写:可选,如果小写,还会对字符做做NFD标准化;标点符号分割:除中文汉字外,其它字符通过标点符号分割开
WordpieceTokenizer:对输入进行split,得到token列表,如果token的一部分在vocab中存在,就将token继续分割,分割后,除开第一部分,其它部分都会加上##,这就是wordpiece,例如visiable分割为:‘vi’, ‘##sia’, ‘##ble’,这个主要针对英文,但是在中文的全词mask,会利用这个特点,把一个词分割开,如“图书馆”分割为:图,#书,#馆
FullTokenizer:调用 BasicTokenizer 得到初步的token列表,对于token再用WordpieceTokenizer生成更细的token。
tokenizer 处理数据中的 attention_mask:多句子输入需要标准化,使其能够整齐划一的进行比较。如短句填充 padding 使其长度一致。由此产生的问题是训练时,模型不理解填充值,仍按照填充值计算,可能引入错误信息。为此,"attention_mask" 会告诉模型返回的数字编码中哪些是需要注意的实际数据,哪些是不需要关心的填充数据。
参考:
BERT句子对(sentence pair)分类任务的truncation='longest_first'之我见 - 知乎 (zhihu.com)