admin管理员组

文章数量:1631701

chatGPT的横空出世给人工智能注入一针强心剂,它是历史上以最短时间达到一亿用户的应用。chatGPT的能力相当惊人,它可以用相当流利的语言和人对话,同时能够对用户提出的问题给出相当顺畅的答案。它的出现已经给各个行业带来不小冲击,据说有很多公司已经使用chatGPT来替代人工,于是引起了不少裁员事件。

chatGPT是人类科技史上一个里程碑。它基于一种叫大语言模型的技术,使得计算机具备了相当于人乃至超越人的能力,chatGPT的发明者openAI据说在推进下一代模型的开发,据说已经能达到通用AI的程度,我对此表示怀疑。无论如何基于大模型技术的AI将人类带入一个新时期,我们必须有所准备,我们既不需要过分狂热,以为它又是一个暴富风口;也不能漠不关心,认为它完全与自己无关,如果你从事信息技术行业,你必须要特意留一手,如果它真的是进入新纪元的钥匙,那么我们不会被落下,如果只是一阵骚动,那么基于技多不压身的原则,咱花点心思多学一门技术也不亏。

我们这个系列着重于探究发明出chatGPT的技术,我们基于可用的算力和数据从零开始做一个“类”chatGPT,也就是我们做出来的模型不可能有chatGPT那么厉害,但是我们掌握和使用的原理跟它一样,只不过我们没有对应的资源训练它而已。同时chatGPT底层还有一种技术叫transformer,基于这个技术我们可以把chatGPT的开源模型拿过来,然后使用小样本数据就能将其训练成某个特定领域的AI专家,于是chatGPT就能为我所用。

这个系列分为两部分,首先是介绍NLP(自然语言处理)的基本原理和技术,然后我们看看如何使用开源的大语言模型进行特定的开发,由此打造出属于我们自己的chatGPT.首先需要声明的是,涉及到人工智能和深度学习,它具有一定的门槛,那就是你至少要比较熟练大学阶段的高数,你要了解微积分相关内容,熟悉向量,矩阵等线性代数概念,要不然很难在这个领域发展。

现在我们回到技术层面。人工智能要解决的主要是传统算法处理不了的问题,传统算法之所以对一些问题束手无措,主要是因为要处理的对象无法使用结构化的数据结构进行表达。例如给定一张人脸图片,我们如何使用传统数据结构来描述呢,是使用链表,二叉树,哈希表吗,显然不行。由于这个原因,传统算法处理不了这些范畴的问题。那么人工智能怎么用数据区描述例如人脸,单词都这些对象呢,方法是用向量,面对的对象性质越复杂,向量的长度就越大,例如人脸通常用长度为256或者更大的实数向量来表示。对NLP而言,它处理的对象是文本,因此它会使用向量来表示文本的基本单位,如果文本是英语,那么就用向量来表示单词,如果是中文,那么就用向量表示一个字。

我们看一个具体例子,假设我们有一段英语文本:

Times flies like an arrow 
Fruit flies like a banana.

显然传统数据结构是无法表达上面的句子和单词,因此我们转向向量来表达。首先我们把所有单词转换为小写,然后将其排列起来,单词排列的先后顺序没有关系,于是有:

time fruit flies like a an arrow banana

接下来我们使用一种叫one-hot-vector的向量来表示单词,可以看到上面有8个不同的单词,因此向量包含8个元素,由于time排在第一个,于是我们把向量第一个元素设置为1,其他元素设置为0,因此time的向量表示就是[1,0,0,0,0,0,0], 同理fruit排在第2位,因此它对应的向量就是第二个元素为1,其他元素为0,于是其对应向量为[0,1,0,0,0,0,0,0],其他以此类推。这种对单词的向量描述方式在我们后面的深度学习算法中会发挥很大作用。对于一个句子而言,它的向量描述方式就是把单词对应的向量进行“或”操作,例如句子like a banana,组成它三个单词的向量是[0,0,0,1,0,0,0,0], [0,0,0,0,1,0,0,0],[0,0,0,0,0,0,0,1], 进行“或”操作后结果就是[0,0,0,1,1,0,0,1],我们用代码来实践看看:

from sklearn.feature_extraction.text import CountVectorizer
import seaborn as sns 

corpus = ['Time flies flies like an arraw.', 'Friut flies like a banana']
one_hot_vectorizer = CountVectorizer(binary = True)
one_hot = one_hot_vectorizer.fit_transform(corpus).toarray()
vocab = one_hot_vectorizer.get_feature_names_out()
sns.heatmap(one_hot, annot=True, cbar = False, xticklabels = vocab, yticklabels=['Sentence 1','Sentence 2'])

上面代码运行后结果如下:

从上图我们能看到图形化的,两个句子对应的向量表示,如果给的单词在句子中出现了,他们向量对应位置设置为1,要不然就设置为0.one-hot-vector只是对单词或句子最基本的数学描述方式,事实上在不同的文本或应用场景下,单词或句子的向量绝对不会那么简单,他们依然需要以向量来表示,但是向量的长度和每个元素的取值都得靠深度学习算法来分析出来,具体情况在后面章节详细阐明。

下面我们看看深度学习的基本原理。有过微积分基础的同学会了解,对于一个连续函数f(x),如果在某一点求导所得结果为0:f’(x)=0,那么这个点就可能是在局部范围内的最大值或最小值。深度学习本质上就是通过微分求极小值的过程,只不过它对应的函数包含不止一个变量,例如chatGPT对应的模型就是一个包含1750亿个参数的函数,训练的目的就是找出这1750亿参数的合适取值,这样它才能根据输入的句子给出合适的回复,因此用于它训练的算力和数据无疑是及其巨大的,以下我们给出深度学习网络训练的基本流程:

对深度学习基本原理不熟悉的同学可以参考《神经网络与深度学习实战》,或者我在云课堂上的课程:http://m.study.163/provider/7600199/index.htm?share=2&shareId=7600199

下面我们看运算图的概念。在上图中“模型”其实可以使用传统数据结构中的“图论”来表示。“含有很多个参数的函数”其实可以使用链表来表示,当算法对函数的参数进行求导时,这些运算就可以通过链表来完成,我们看一个具体例子,对于函数y = wx+b,我们可以用链表表示如下:

参数x, w, b, y使用矩形节点表示,运算符则使用圆形节点表示。箭头上的值表示对应参数的值,他们经过圆形节点后执行对应运算然后输出结果。前面我们提到过chatGPT的参数有1370亿个,那意味着其对应的运算图将非常庞大和复杂,因此我们通常使用特定框架来完成运算图的构建以及执行基于其的运算,常用的框架有tensorflow, pytorch还有百度的飞桨,目前用的比较多的还是meta的pytorch框架。

在具体的深度学习应用中,参数节点往往不会像上面那么简单,他们通常是高维度向量,我们上面显示的是0维度的向量,也就是他们是单个参数,在实际应用中x,b通常是一维向量,w是二维向量也就是矩阵。如果我们要处理的输入是图片,那么x可能就是二维向量,如果处理的是视频,那么可能就是三维向量,因为视频是具有时间维度的图片,对于NLP而言,也就是自然语言处理而言,输入的x通常是一维或者二维向量.接下来我们看看如何在基于pytorch框架的基础上实现向量的各自运算。

我们所有代码将运行在谷歌的colab开发环境,这个环境好在于集成了pytorch框架,同时还能让我们免费使用gpu加快运算效率。首先我们用一段代码展示如何使用pytorch创建各种维度的向量:

import torch 
def describeTensor(tensor):
  #输出向量的维度,类型,以及元素值
  print(f"Type: {
     tensor.type()}")
  print(f"shape/size: {
     tensor.shape}")
  print(f"values: {
     tensor}")

describeTensor(torch.Tensor(2,3)) #创建二维向量,也就是2*3矩阵

上面代码执行后输出如下:

Type: torch.FloatTensor
shape/size: torch.Size([2, 3])
values: tensor([[-7.9076e-20,  4.5766e-41, -7.7950e-20],
        [ 4.5766e-41, -7.7948e-20,  4.5766e-41]

本文标签: 向量概念操作自己动手做chatGPT