创作不易,有用的话点个赞
先直接贴代码,我们再慢慢分析,代码来自openai的图像分类模型的一小段
def bytes_to_unicode():"""Returns list of utf-8 byte and a corresponding list of unicode strings.The reversible bpe codes work on unicode strings.This means you need a large # of unicode characters in your vocab if you want to avoid UNKs.When you're at something like a 10B token dataset you end up needing around 5K for decent coverage.This is a signficant percentage of your normal, say, 32K bpe vocab.To avoid that, we want lookup tables between utf-8 bytes and unicode strings.And avoids mapping to whitespace/control characters the bpe code barfs on."""bs = list(range(ord("!"), ord("~")+1))+list(range(ord("¡"), ord("¬")+1))+list(range(ord("®"), ord("ÿ")+1))cs = bs[:]n = 0for b in range(2**8):if b not in bs:bs.append(b)cs.append(2**8+n)n += 1cs = [chr(n) for n in cs]return dict(zip(bs, cs))
openai觉得图像分类,就是输入文本,然后给你一张相似的照片,例如
a facial photo of a tabby cat
这其实对文本语义文本推理要求不是很高,所以我们不需要训练出一个太长的词汇表,例如gpt2的50000多个词汇,不需要。
我们只需要一些简单的词汇表,我们可以指定我们需要哪些词汇,首先26个英文字母,一些分隔符,或者你还想兼容其它语言,都可以加,这里兼容了英语法语西班牙语,你觉得重要的语言字符都给一个独立的下标index去对待这个字符,所以就有了如下代码:
bs = list(range(ord("!"), ord("~")+1))+list(range(ord("¡"), ord("¬")+1))+list(range(ord("®"), ord("ÿ")+1))
print(list(range(ord("!"), ord("~")+1)))
print(list(range(ord("¡"), ord("¬")+1)))
print(list(range(ord("®"), ord("ÿ")+1)))
打印如下,ord("!")就是获取一个字符在unicode编码世界中的一个下标,可以看到对你重要的字符都在下面,你可以随意更改上面的字符。
[33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126]
[161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172]
[174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255]
但是实际上当你训练好模型之后,就算你要求用户使用英语法语西班牙语,但是用户可能会使用其它语言去提问,不在我们上面的区间,所以我们要兼容用户输入一些其他语言,我们想使用utf-8去实现这种兼容性。
这里讲一个东西:由于我们没有对其他语言独立给一个位置,所以当使用其他语言去跟模型提问的时候,效果可能不会很好,但我们针对的用户主要是英文法语西班牙语,这里主要是实现兼容性而已。
上面我们给下标的都只是单个字符,但是如果你觉得abc这个连词很重要,你也可以给abc一个单独的index,一个单独的index,意味着这个词有一个单独的词向量去训练,例如abc就有个单独的词向量,但是def没有,那么构成def的词向量是由三个单独的词向量组成,我认为,单独的一个词向量比多个组成的效果要好,表达意义要更准确,因为def是一个词汇,dbp也是一个词汇,他们是不同的意思,但是共享了d这个字符,d既要兼顾def的意思又要兼顾dbp的意思,很可能这两个词汇的意思又完全不相关不交集,那么d这个字符的词向量就被分散了,所以我们跟gpt问问题的时候,用英文问会更好,因为英文可以更准确表达我们的意思,而中文其实更像是很多无关的其他字符拼合起来的意思。
utf-8怎么表示文字?使用四种长度的数组表示一个符号,就是长度为1,2,3,4,每个位置取0到127中其中一个数字,可以表示计算机世界中所有词汇。如下:
【0-127】
【0-127,0-127】
【0-127,0-127,0-127】
【0-127,0-127,0-127,0-127】
原先已经拥有字符的下标,我们不去改它了,继续让他使用unicode编码的下标即可。
遍历 2的8次方 次,当缺少下标的时候,我们将最后一个字符顺序递增叠加上去,代码就是:
for b in range(2**8):if b not in bs:# 不存在的下标,就把下标append进去bs.append(b) cs.append(2**8+n) # 但是我append进去的字符却不是对应下标的unicode字符,因为我不喜欢......,我把第2**8+n字符叠加上去n += 1
打印bs
[33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 0, 1, 2, 3, 4, 5,6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 173]
打印cs
['!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':',
';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', '¡', '¢', '£', '¤', '¥', '¦', '§', '¨', '©', 'ª',
'«', '¬', '®', '¯', '°', '±', '²', '³', '´', 'µ', '¶', '·', '¸', '¹', 'º', '»', '¼', '½', '¾', '¿', 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å',
'Æ', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', '×', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'Þ', 'ß',
'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', '÷', 'ø', 'ù',
'ú', 'û', 'ü', 'ý', 'þ', 'ÿ', 'Ā', 'ā', 'Ă', 'ă', 'Ą', 'ą', 'Ć', 'ć', 'Ĉ', 'ĉ', 'Ċ', 'ċ', 'Č', 'č', 'Ď', 'ď', 'Đ', 'đ', 'Ē', 'ē',
'Ĕ', 'ĕ', 'Ė', 'ė', 'Ę', 'ę', 'Ě', 'ě', 'Ĝ', 'ĝ', 'Ğ', 'ğ', 'Ġ', 'ġ', 'Ģ', 'ģ', 'Ĥ', 'ĥ', 'Ħ', 'ħ', 'Ĩ', 'ĩ', 'Ī', 'ī', 'Ĭ', 'ĭ',
'Į', 'į', 'İ', 'ı', 'IJ', 'ij', 'Ĵ', 'ĵ', 'Ķ', 'ķ', 'ĸ', 'Ĺ', 'ĺ', 'Ļ', 'ļ', 'Ľ', 'ľ', 'Ŀ', 'ŀ', 'Ł', 'ł', 'Ń'
]