1. 获取tokenizer对象
from transformers import BertTokenizer
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
2. encode的几种方法对比
总结:tokenizer默认和encode_plus含义一样,即加好了token_type_ids,mask等label,类似于dict一样访问这个函数
tokenizer.encode 只是把 input_ids的结果拿下来,然后后面的属性可以自己在dataload定义, 比如是否加入 【sep】等
.join()的含义:
‘a’.join(‘b b b’) = ‘ba aba ab’
这样预处理是为了对于 tokenizer的中文没有区别,但是对于处理电话,如果不区分可能会导致 电话变成 unknow,切割开 可以使得这个token保留下来
3. tokenizer加入指定的vocab
way1:
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese', additional_special_tokens=['用户1:', '用户2:'])
这样可能会导致embedding的矩阵维度不对,会导致重新训练
这时候,可以考虑vocab.txt里面unused的label,这样可以避免重新train
way2:
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
tokenizer.vocab['用户1:'] = tokenizer.vocab.pop('[unused1]')
tokenizer.vocab['用户2:'] = tokenizer.vocab.pop('[unused2]')
4. 关于 替代 unused# token的问题
1. 存在的问题:unused 直接切分 并不能像 PAD 类似一样,做到不切分,这意味我们使用 unused 去赋值自己的special token是没有用的
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
print(tokenizer.encode('[unused9]'))
print(tokenizer.tokenize('[unused9]'))
print(tokenizer.convert_tokens_to_ids('[unused9]'))
print(tokenizer.encode('[SEP]'))
result:
[101, 138, 163, 11316, 8303, 8160, 140, 102]
['[', 'u', '##nus', '##ed', '##9', ']']
9
[101, 102, 102]
如何解决:
2. 替换vocab中的unused + never_split
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese',never_split=['[unused1]','[咨询师:]'])
tokenizer.vocab['[咨询师:]'] = tokenizer.vocab.pop('[unused2]')
print(tokenizer.tokenize('[unused1]'))
print(tokenizer.encode('[unused1]'))
print(tokenizer.tokenize('[咨询师:]'))
print(tokenizer.encode('[咨询师:]'))
tokenizer.save_vocabulary("./")
tokenizer = BertTokenizer.from_pretrained('./vocab.txt',never_split=['[unused1]','[咨询师:]'])
print(tokenizer.tokenize('[unused1]'))
print(tokenizer.encode('[unused1]'))
print(tokenizer.tokenize('[咨询师:]'))
print(tokenizer.encode('[咨询师:]'))
print(len(tokenizer.get_vocab()))
result:
['[unused1]']
[101, 1, 102]
['[', '咨', '询', '师', ':', ']']
[101, 138, 1486, 6418, 2360, 8038, 140, 102]
['[unused1]']
[101, 1, 102]
['[', '咨', '询', '师', ':', ']']
[101, 138, 1486, 6418, 2360, 8038, 140, 102]
21128
还是把咨询师切开了, 修改vocab文件,重新打开也没用
这时候,我想到 stackoverflow上面说修改文件时可行的,那么有可能是中文的问题,所以把咨询师改成英文huawei,测试效果如下:
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
tokenizer.vocab['[huawei]'] = tokenizer.vocab.pop('[unused2]')
print(tokenizer.tokenize('[unused1]'))
print(tokenizer.encode('[unused1]'))
print(tokenizer.tokenize('[huawei]'))
print(tokenizer.encode('[huawei]'))
print('-------------------------------------------------------')
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese',never_split=['[unused1]','[huawei]'])
tokenizer.vocab['[huawei]'] = tokenizer.vocab.pop('[unused2]')
print(tokenizer.tokenize('[unused1]'))
print(tokenizer.encode('[unused1]'))
print(tokenizer.tokenize('[huawei]'))
print(tokenizer.encode('[huawei]'))
print('-------------------------------------------------------')
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese',never_split=['[unused1]','[hua wei]'])
tokenizer.vocab['[hua wei]'] = tokenizer.vocab.pop('[unused3]')
print(tokenizer.tokenize('[unused1]'))
print(tokenizer.encode('[unused1]'))
print(tokenizer.tokenize('[hua wei]'))
print(tokenizer.encode('[hua wei]'))
print(len(tokenizer.get_vocab()))
结果:
```python
['[', 'u', '##nus', '##ed', '##1', ']']
[101, 138, 163, 11316, 8303, 8148, 140, 102]
['[', 'huawei', ']']
[101, 138, 12247, 140, 102]
-------------------------------------------------------
['[unused1]']
[101, 1, 102]
['[huawei]']
[101, 2, 102]
-------------------------------------------------------
['[unused1]']
[101, 1, 102]
['[', 'hu', '##a', 'wei', ']']
[101, 138, 12199, 8139, 11875, 140, 102]
21128
得出结论:如果是 英文 且没用空格区分,则never_split函数有效
3. 使用add_token() 操作
tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
print(tokenizer.vocab_size)
tokenizer.add_tokens('客户1')
print(tokenizer.encode('客户1'))
print(tokenizer.vocab_size)
未完待续(embedding维度不对了)