在最近很火的大语言模型和其它好多模型中,背后都是Transformer模型以及它的变种;Transformer模型的核心原理主要在下面2个方面:注意力机制(Attention)和Embedding(嵌入);今天我就给大家介绍一个通过在线编码,实际上手,深入理解transformer里面的embedding,它的原理以及用处的
视频介绍:
transformer的embedding视频介绍
embedding是用一个向量代表一个的词汇,所谓向量,就是一组数字,用一组数字来代表这个词就是嵌入(embedding);embedding能表达词汇的特征;比如‘斑马’这个embedding可能包含了属性特征,包括:动物,草原,条纹相间,四足,食草动物等等。不同embedding向量的大小不一样,有50位,有512, 768或者更多的;这些词嵌入是通过专门的AI模型训练好的,在transformer中我们直接调用训练好的模型,得到词汇的嵌入值;
我们假设一组词嵌入只需3个数字表示,我们把这3个数字对应3维空间的坐标xyz轴,‘斑马’所在的位置,与‘羚羊’所在的位置相对比较近,因为这两个东西有相近的特征;而‘飞机’会在比较远的地方;当然现实中的嵌入至少都是50位数字表示,我们无法放到空间坐标中去;projector.tensorflow.org这个网站可以将高维的向量转换成低维,可以直观的看到某个词嵌入和它相邻的词汇;
衡量2个向量的近似程度,一般用dot product或者cos距离
dot product: a.b = a1 * b1 + a2 * b2 + a3 * b3
或者cos近似度:只计算两个向量之间的角度,我们知道,cos(90)值是0,表示两个向量相似度为0,cos(0)的值是1表示两个相似度为100%
打开网页:https://chn.ai/embedding.html
这个页面是我给大家专门准备的,在网页浏览器里面可以运行的AI编程环境,大家不用安装,编程需要的库,模型都已经准备好,直接输入代码就可以运行;
这套环境用js编程,原因是:
- 不用安装;我们学的是人工智能,不是学怎么搭建python,解决依赖,科学上网,配置cuda,大多数小伙伴把这些搞定了,学习的热情都消耗了一半
- 可以使用webgl使用gpu,
- 学习够用
- 编程语言不是问题,问题在于机器学习的陌生
第一次需要点击左上角的“加载模型”,直到提示:模型加载成功:
在界面里输入代码:
import { AutoModel, AutoTokenizer, dot } from 'https://res.chn.ai/module/transformers@2.15.1/transformers@2.15.1.js'
let tokenizer = await AutoTokenizer.from_pretrained('Xenova/jina-embeddings-v2-base-zh')
let model = await AutoModel.from_pretrained('Xenova/jina-embeddings-v2-base-zh')
function stringify(obj) {
return JSON.stringify(obj, (key, value) => {
return typeof value === 'bigint'
? value.toString()
: value
}, null, 2)
}
var tokens = await tokenizer(['鲜花', '牛粪', '白云'], {padding: true})
var tokenIds = Array.from(tokens.input_ids.data)
var words = await tokenizer.decode(tokenIds).split(' ')
console.log(words)
var embeddings = await model(tokens)
console.log(stringify(embeddings))
我们把右边的结果放到JSON查看器里面,看到输入词的embedding拿到了,具体的解释大家可以看视频讲解:
我给大家提供了第二个例子,这个例子是比较同一个词“苹果”在不同上下文语境中,它的embedding是不一样的,比如:第一个句子里面“苹果”是指苹果公司;第二个里面指的是水果,我们可以看到它们的embedding不一样,通过点积发现单独“苹果”这个词的位置介于这两个语境的“苹果”的中间。具体讲解请大家看视频。
import { AutoModel, AutoTokenizer, dot } from 'https://res.chn.ai/module/transformers@2.15.1/transformers@2.15.1.js'
let tokenizer = await AutoTokenizer.from_pretrained('Xenova/jina-embeddings-v2-base-zh')
let model = await AutoModel.from_pretrained('Xenova/jina-embeddings-v2-base-zh')
function stringify(obj) {
return JSON.stringify(obj, (key, value) => {
return typeof value === 'bigint'
? value.toString()
: value
}, null, 2)
}
var sentences = ['苹果这次发布会水分很大', '一个苹果里面含有丰富的水分', '保持土壤水分', '水分', '苹果']
var tokens = await tokenizer(sentences, {padding: true})
var tokenIds = Array.from(tokens.input_ids.data)
var words = await tokenizer.decode(tokenIds).split(' ')
console.log(words.map((w, i) => {
return `${w}(${tokenIds[i]})`
}).join(' '))
// <s>(0) 苹果(27691) 这次(27937) 发布会(40770) 水分(37459) 很大(29075) </s>(2) <pad>(1) <s>(0) 一个(21752) 苹果(27691) 里面(29468) 含有(31173) 丰富的(28195) 水分(37459) </s>(2)
var embeddings = (await model(tokens)).last_hidden_state
var vectorLen = embeddings.dims[2]
var embeddingData = Array.from(embeddings.data)
var wordEmbeddings = []
for(var i = 0; i < embeddingData.length; i += vectorLen) {
var wordEmbedding = embeddingData.slice(i, i + vectorLen)
// console.log(`${words[i/vectorLen]} ${wordEmbedding.length}`)
wordEmbeddings.push({index: i/vectorLen, word: words[i/vectorLen], wordEmbedding})
}
console.log(stringify(wordEmbeddings))
//苹果
var tt = {1: '苹果这次发布会水分很大', 10: '一个苹果里面含有丰富的水分', 33: '苹果'}
for(var i1 of [1, 10, 33]) {
for(var i2 of [1, 10, 33]) {
console.log(`${tt[i1]} - ${tt[i2]} ${Math.floor(dot(wordEmbeddings[i1].wordEmbedding, wordEmbeddings[i2].wordEmbedding) * 10) / 10}`)
}
}
接下来,我将介绍通过编程了解transformer里面最重要的模块:attention注意力机制,敬请期待。。。