AIGC-机器学习-深度学习-强化学习-...(一)
@TOC
前言
刚进公司,需要学开发需要的新框架及现成框架,完成自己的需求。那么在此期间,遇到新东西,就可以以此为基础,学习新语言新框架新工具…,可能会学到一些新技术、新知识,总结一下,以供后面参考学习,查看。肯定大家都有一定差异啦,大家作为参考哦,与诸君共勉。
一、pgc -> ugc -> aigc
- 最初的AIGC通常基于小模型展开,这类模型一般需要特殊的标注数据训练,以解决特定的场景任务,通用性较差,很难被迁移,而且高度依赖人工调参。后来,这种形式的AIGC逐渐被基于大数据量、大参数量、强算法的大模型(Foundation Model)取代,这种形式的AIGC无须经过调整或只经过少量微调(Fine-tuning)就可以迁移到多种生成任务。
- 不少元宇宙选择同时利用PGC和UGC的方式来丰富这些模型,无论是专业机构还是感兴趣的个人,都可以借助官方提供的编辑器来创作各种类型的3D物品模型,或者在创作好3D物品模型后导入元宇宙世界。
- 在此过程中,产生了一种很重要的位置,提示词(Prompt)工程师
- 提示词(Prompt)工程师这个“咒语”就是被用来激发创作与思考的提示词。提示词可以是一个问题、一个主题、一个想法或一个概念,在AI绘画的语境下可以简单理解为“喂给”AI进行创作的一组灵感词组,通常是对自己设想作品的简要描述。
1.在智能创作时代,创作者生产力的提升主要表现为三个方面:
- 代替创作中的重复环节,提升创作效率。
- 将创意与创作相分离,内容创作者可以从人工智能的生成作品中找寻灵感与思路。
- 综合海量预训练的数据和模型中引入的随机性,有利于拓展创新的边界,创作者可以生产出过去无法想出的杰出创意。
2.对于人的智能,主要认知有两种流派:
- 符号主义认为人的智能来自逻辑推理,世界上所有信息都可以抽象为各种符号,而人类的认知过程可以看作运用逻辑规则操作这些符号的过程。在这样的前提假设下,如果计算机能够自动化地执行和人脑一样的各种规则,说不定就可以实现完全的智能化。
- 联结主义则认为,让机器模拟人类智能的关键不是去想办法实现跟思考有关的功能,而是应该模仿人脑的结构。联结主义把智能归结为人脑中神经元彼此联结成网络共同处理信息的结果,希望能够运用计算机模拟出神经网络的工作模式来打造人工智能,并在“人工智能”领域正式形成之前就开始了各种尝试。
3.人工智能的发展小插曲
- 人工智能诞生于20世纪50年代,当时计算机科学这个新兴领域的少数先驱者开始提出疑问:能否让计算机“思考”?今天,我们仍在探索这一问题的答案。虽然许多基本理念在数年前甚至数十年前就已经开始酝酿,但“人工智能”最终在1956年明确成为一个研究领域。当时,达特茅斯学院年轻的数学系助理教授John McCarthy根据以下提案组织了一场夏季研讨会。
- 该研究(人工智能研究)是基于以下猜想进行的:学习的各个方面或其他任何智能特征原则上都可以被精确描述,从而可以制造一台机器来模拟。我们将试图找到一种方法,让机器能够使用语言、形成抽象思维和概念、解决人类目前还不能解决的各种问题,并自我提升。我们认为,如果一组优秀的科学家在一起工作一个夏天,那么可以在其中一个或多个问题上取得重大进展。夏天过去了,研讨会在结束时没有完全解开它一开始打算研究的谜题。然而,许多参会者后来成为这一领域的先驱,这次研讨也启动了一场延续至今的知识革命。 简而言之,人工智能可以被描述为试图将通常由人类完成的智力任务自动化。因此,人工智能是一个综合领域,不仅包括机器学习和深度学习,还包括更多不涉及学习的方法。
- 事实上,在相当长的时间内,大多数专家相信,只要程序员手动编写足够多的明确规则来处理存储在显式数据库中的知识,就可以实现与人类水平相当的人工智能。 这一方法被称为符号主义人工智能(symbolic AI) ,从20世纪50年代到80年代末,它是人工智能的主流范式。在20世纪80年代的专家系统(expert system)热潮中,这一方法的热度达到顶峰。虽然符号主义人工智能适合用来解决定义明确的逻辑问题,比如下国际象棋,但它难以给出明确规则来解决更复杂、更模糊的问题,比如图像分类、语音识别或自然语言翻译。于是, 一种替代符号主义人工智能的新方法出现了,这就是机器学习(machine learning)。
二、机器学习
1.机器学习
卡耐基梅隆大学计算机学院教授汤姆·米切尔(Tom Michell)的定义,机器学习是指“计算机程序能从经验E中学习,以解决某一任务T,并通过性能度量P,能够测定在解决T时机器在学习经验E后的表现提升”。
- 假如老师想让小明好好学习,在考试中取得好成绩,他可能会给小明布置很多习题,并观察每次的考试成绩以判断小明学习的效果。如果把这里的“小明学习”替换成“机器学习”,那么经验E就是反复的刷题过程,任务T就是参加考试,而性能度量P就是考试成绩。小明在反复刷题训练、参加考试的过程中,让成绩不断提升以达到预期的分数水平,当他走上高考考场时就能取得好成绩。而机器也是类似的,在经过反复的训练并达标后,执行任务时就可以取得比较好的性能,只不过这里的训练指的是输入数据。
机器学习模型将输入数据变换为有意义的输出,这是一个从已知的输入输出示例中进行“学习”的过程。因此,机器学习和深度学习的核心问题在于有意义地变换数据,换句话说,在于学习输入数据的有用表示(representation)——这种表示可以让数据更接近预期输出。
- 什么是表示?这一概念的核心在于以一种不同的方式来查看数据(表征数据或将数据编码)。
- 举例来说,彩色图像可以编码为RGB(红−绿−蓝)格式或HSV(色相−饱和度−明度)格式,这些是对同一数据的两种表示。在处理某些任务时,使用某种表示可能会很困难,但换用另一种表示就会变得很简单。 举个例子,对于“选择图像中所有红色像素”这项任务,使用RGB格式会更简单,而对于“降低图像饱和度”这项任务,使用HSV格式则更简单。机器学习模型旨在为输入数据寻找合适的表示(对数据进行变换),使其更适合手头的任务。
- 什么是表示?这一概念的核心在于以一种不同的方式来查看数据(表征数据或将数据编码)。
机器学习是将输入(比如图像)映射到目标(比如标签“猫”)的过程。这一过程是通过观察许多输入和目标的示例来完成的。你还知道,深度神经网络通过一系列简单的数据变换(层)来实现这种输入到目标的映射,这些数据变换都是通过观察示例学习得到的。
2.机器学习可以简单划分为监督学习【我把他叫做have…belongs to…】和无监督学习
监督学习:
- 分类学习。分类就是最经典的监督学习场景,机器先学习具备什么样特征的数据属于什么样的类别,然后当获取新的数据后,它就可以根据数据特征将数据划分到正确的类别。
- 在机器学习中,分类问题中的某个类别叫作类(class),数据点叫作样本(sample),与某个样本对应的类叫作标签(label)。
- 用一条简单的规则就可以描述黑白分类问题:。这种新的数据表示加上这条简单的规则,巧妙地解决了该分类问题。比如在“黑点”或“白点”例子中,我们手动定义了坐标变换,利用人类智慧想出了适当的数据表示。对于这样一个极其简单的问题来说,这样做没什么问题,但如果任务是对手写数字进行分类,你还能做得到吗?你能明确地写出计算机可执行的图像变换规则,以分辨6和8、1和7以及各种不同的笔迹吗?这在一定程度上是可以做到的。基于数字表示的规则(比如“圆圈个数”或垂直像素直方图和水平像素直方图)可以很好地区分手写数字。但是手动寻找这样的有用表示是很困难的,而且可以想象,由此得到的基于规则的系统很脆弱,系统维护将是一场噩梦。每当遇到一个新的手写数字不符合你精心设计的规则时,你都不得不添加新的数据变换和新的规则,还要考虑它们与之前每条规则之间的相互作用。你可能在想,既然这个过程如此痛苦,那么能否将其自动化呢?如果我们尝试系统地搜索自动生成的数据表示与基于这些表示的规则之间的不同组合,利用正确分类的数字所占百分比作为反馈信号,在某个开发数据集上找到那些好的组合,那会怎么样呢?那样一来,我们做的就是机器学习。机器学习中的学习指的是,寻找某种数据变换的自动搜索过程。在反馈信号的指引下,这种变换可以生成有用的数据表示,这种表示则可以用更简单的规则来解决手头的任务。这种变换既可以是坐标变换(比如前面的二维坐标分类示例),也可以是像素直方图和圆圈个数(比如前面的数字分类示例),还可以是线性投影、平移、非线性操作(比如“选择的所有点”)。机器学习算法在寻找这些变换时通常没有创造性,仅仅是遍历一组预先定义的操作,这组操作叫作假设空间(hypothesis space)。例如,所有可能的坐标变换组成的空间就是上述二维坐标分类示例的假设空间。
- 简而言之,机器学习就是指在预先定义的可能性空间中,利用反馈信号的指引,在输入数据中寻找有用的表示和规则。这个简单的想法可以解决相当多的智力任务,从语音识别到自动驾驶都能解决。
- 感知器算法就是典型的监督学习的案例。
- 小明在大学里选修了一门课程,这门课程并没有公布详细的合格评价标准,只知道平时的两次作业和一次考试会影响这门课程的通过与否,于是小明希望从往届的学长、学姐那里搜集他们的作业、考试及最终是否通过的相关数据,来帮助判断自己是否会在这门课程中挂科。在搜集完学长、学姐的数据后,小明决定先假设一个老师的评价标准:
- 第一次作业×0.3+第二次作业×0.3+考试×0.4=课程评分。如果课程评分>=60,则课程及格;否则课程挂科。在写完假设的评价标准后,小明迫不及待地想把学长、学姐的成绩带入评价标准中,结果发现,按照现在的计算方式,所有的学长、学姐都不满60分,全都挂科了。这也就说明,作业和考试的评价系数假设得太小了,小明于是把它们调大了一些,但又发现,包括挂科的学长、学姐在内的所有人又全都及格了,这说明评价系数又调得太大了,需要调小一点。在反复调整的过程中,评价标准的公式会找到一组相对合适的系数,将学长、学姐是否挂科划分准确,此时,小明就可以输入自己的成绩来看看自己是合格还是挂科。如果我们让程序来执行上面小明的工作流程,一个简易的感知器也就形成了。学长、学姐两次作业和考试的成绩就是三个输入节点,好比接收外界刺激信息的神经元。最终判断是否挂科的输出节点,也可以看作一个神经元,而根据分数情况算出合格与挂科的函数叫作激励函数(Activation Function)。输入节点和输出节点之间神经信号的通信就是由评价标准公式的计算来传递的,而传递信号的强弱就是作业和考试分数所对应系数的大小。通过将传递信号的强弱反复调整到一个合适的值,也就完成了模型的学习,可以用于分类等任务。- 无监督学习:
- 聚类是最经典的无监督学习场景,机器获得数据后并不知道每种特征的数据分别属于什么类别,而是根据数据特征之间的相似或相异等关系,自动把数据划分为几个类别。
三、人工神经网络
1.神经网络
- 神经网络中进行的处理总体上可以分为“学习”和“推理”两部分
- 这种学习过程是如何发生的?
- 在神经网络中,每层对输入数据所做的具体操作保存在该层的权重(weight)中,权重实质上就是一串数字。用术语来讲,每层实现的变换由其权重来参数化(parameterize)。权重有时也被称为该层的参数(parameter)。在这种语境下,学习的意思就是为神经网络的所有层找到一组权重值,使得该神经网络能够将每个示例的输入与其目标正确地一一对应。但问题来了:一个深度神经网络可能包含上千万个参数,找到所有参数的正确取值似乎是一项非常艰巨的任务,特别是考虑到修改一个参数值将影响其他所有参数的行为。要控制某个事物,首先需要能够观察它。若要控制神经网络的输出,需要能够衡量该输出与预期结果之间的距离。这是神经网络损失函数(loss function)的任务,该函数有时也被称为目标函数(objective function)或代价函数(cost function)。损失函数的输入是神经网络的预测值与真实目标值(你希望神经网络输出的结果),它的输出是一个距离值,反映该神经网络在这个示例上的效果好坏
- 由于一开始对神经网络的权重进行随机赋值,因此神经网络仅实现了一系列随机变换,其输出值自然与理想结果相去甚远,相应地,损失值也很大。但是,神经网络每处理一个示例,权重值都会向着正确的方向微调,损失值也相应减小。这就是训练循环(training loop),将这种循环重复足够多的次数(通常是对数千个示例进行数十次迭代),得到的权重值可以使损失函数最小化。具有最小损失值的神经网络,其输出值与目标值尽可能地接近,这就是一个训练好的神经网络。再次强调,一旦具有足够大的规模,这个简单的机制将产生魔法般的效果。
- 一节介绍到,对于第一个模型示例,每个神经层都对输入数据进行如下变换。output = relu(dot(input, W) + b)在这个表达式中,W和b是张量,均为该层的属性。它们被称为该层的权重(weight)或可训练参数(trainable parameter),分别对应属性kernel和bias。这些权重包含模型从训练数据中学到的信息。
- 一开始,这些权重矩阵取较小的随机值,这一步叫作随机初始化(random initialization)。当然,W和b都是随机的,relu(dot(input, W) + b)不会得到任何有用的表示。虽然得到的表示没有意义,但这是一个起点。下一步则是根据反馈信号逐步调节这些权重。这个逐步调节的过程叫作训练(training),也就是机器学习中的“学习”过程。
- 上述过程发生在一个训练循环(training loop)内,其具体流程如下。在一个循环中重复下列步骤,直到损失值变得足够小。
- (1)抽取训练样本x和对应目标y_true组成的一个数据批量。
- (2)在x上运行模型[这一步叫作前向传播(forward pass)],得到预测值y_pred。
- (3)计算模型在这批数据上的损失值,用于衡量y_pred和y_true之间的差距。
- (4)更新模型的所有权重,以略微减小模型在这批数据上的损失值。最终得到的模型在训练数据上的损失值非常小,即预测值y_pred与预期目标y_true之间的差距非常小。模型已“学会”将输入映射到正确的目标。乍一看,这可能像魔法一样,但如果你将其简化为基本步骤,那么会发现它变得非常简单。
- 第1步看起来很简单,只是输入/输出(I/O)的代码。第2步和第3步仅仅是应用了一些张量运算,所以你完全可以利用在2.3节学到的知识来实现这两步。难点在于第4步:更新模型的权重。对于模型的某个权重系数,你怎么知道这个系数应该增大还是减小,以及变化多少?一种简单的解决方案是,保持模型的其他权重不变,只考虑某一个标量系数,让其尝试不同的取值。假设这个系数的初始值为0.3。对一批数据做完前向传播后,模型在这批数据上的损失值是0.5。如果将这个系数改为0.35并重新运行前向传播,那么损失值增大为0.6。但如果将这个系数减小到0.25,那么损失值减小为0.4。在这个例子中,将系数减小0.05似乎有助于让损失值最小化。对于模型的所有系数都要重复这一过程。但这种方法非常低效,因为系数有很多(通常有上千个,有时甚至多达上百万个),对每个系数都要计算两次前向传播,计算代价很大。幸运的是,有一种更好的方法:梯度下降法(gradient descent)。梯度下降是驱动现代神经网络的优化方法,其要点如下。我们的模型用到的所有函数(比如dot或+),都以一种平滑、连续的方式对输入进行变换。举个例子,对于z = x + y,y的微小变化只会导致z的微小变化。如果你知道y的变化方向,就可以推断出z的变化方向。用数学语言来讲,这些函数是可微(differentiable)的。将这样的函数组合在一起,得到的函数仍然是可微的。尤其是,将模型系数映射到模型在数据批量上损失值的函数,也是可微的:模型系数的微小变化,将导致损失值发生可预测的微小变化。我们可以用一个叫作梯度(gradient)的数学运算符来描述:模型系数向不同方向移动时,损失值如何变化。计算出梯度,就可以利用它来更新系数,使损失值减小(在一次更新中全部完成,而不是一次更新一个系数)。假设有一个光滑的连续函数f(x) = y,将一个数字x映射到另一个数字y。由于函数是连续的,因此x的微小变化只会导致y的微小变化——这就是函数连续性(continuity)的直观解释。如果a为负,那么说明x在p点附近的微增将导致f(x)减小(如图2-17所示);如果a为正,那么x的微增将导致f(x)增大。此外,a的绝对值(导数大小)表示这种增大或减小的速度。对于每个可微函数f(x)(可微的意思是“可以被求导”,比如光滑的连续函数可以被求导),都存在一个导数函数f’(x),将x的值映射为f在该点局部线性近似的斜率。举例来说,cos(x)的导数是-sin(x),f(x) = a * x的导数是f’(x) = a。优化的目的就是找到使f(x)最小化的x值,就此而言,函数求导是一个非常强大的工具。如果你想将x改变一个很小的因子epsilon_x,目的是将f(x)最小化,并且你知道f的导数,那么问题已经解决了:导数描述的就是,改变x后f(x)会如何变化。如果你想减小f(x)的值,那么只需将x沿着导数的反方向移动一小步。
- 这种学习过程是如何发生的?
- 神经网络完全由一系列张量运算组成,而这些张量运算只是输入数据的简单几何变换。因此,你可以将神经网络解释为高维空间中非常复杂的几何变换,这种变换通过一系列简单步骤来实现。
- 基本操作见第六部分
- 人工神经网络,就可以看作一个多层的感知器。在人工神经网络中,除了和感知器一样拥有包括输入节点的输入层和包括计算出输出结果的输出层外,还加入了若干隐藏层。隐藏层中间的神经元节点可以与输入节点和输出节点一一相连,每条连接的链条上都有各自的权重系数,最终构成了一个网络的结构。
- 与感知器一样,人工神经网络也需要在训练数据的过程中反复调整各神经元连接的权重,以完成模型的学习过程。而调整的依据是对比数据和模型的结果来查看神经网络有没有犯错误。如果在数据上存在误差,就相当于造成了损失,输出每个样本数据损失的函数叫作损失函数(Loss Function)。而所有的损失综合在一起的平均情况,会反应在代价函数(Cost Function)里,描述训练这一个模型产生的错误代价。不过,需要注意的是,这里的代价并非越小越好。根据前面的例子,我们当然希望能好好利用先前学长、学姐给到的经验数据,避免产生经验风险;但是,每一届的课程情况可能有变化,过多地利用过去经验产生结构复杂的模型,可能无法很好地适应新一届学生的情况,从而造成无法使用,产生结构风险。所以,调整后的合适标准应该是综合考虑经验风险和结构风险的结果。
2.深度学习
- 现代深度学习模型通常包含数十个甚至上百个连续的表示层,它们都是从训练数据中自动学习而来的。与之相对,其他机器学习方法的重点通常是仅学习一两层的数据表示(例如获取像素直方图,然后应用分类规则),因此有时也被称为浅层学习(shallow learning)。
- 深度学习的基本技巧是将损失值作为反馈信号,来对权重值进行微调,以降低当前示例对应的损失值。这种调节是优化器(optimizer)的任务,它实现了所谓的反向传播(backpropagation)算法,这是深度学习的核心算法。
- 虽然深度学习的一些核心概念是从人们对大脑(特别是视觉皮层)的理解中汲取部分灵感而形成的,但深度学习模型并不是大脑模型。没有证据表明大脑的学习机制与现代深度学习模型的学习机制相同。你可能读过一些科普文章,这些文章宣称深度学习的工作原理与大脑相似或者是在模拟大脑,但事实并非如此。对于这一领域的新人来说,如果认为深度学习与神经生物学存在任何关系,那将使人困惑,只会起到反作用。你无须那种“就像我们的头脑一样”的神秘包装,最好也忘掉读过的深度学习与生物学之间的假想联系。就我们的目的而言,深度学习是从数据中学习表示的一种数学框架。
- 可以将深度神经网络看作多级信息蒸馏(information distillation)过程:信息穿过连续的过滤器,其纯度越来越高(对任务的帮助越来越大)。
- 但是有一点,当前工业界所使用的大部分机器学习算法不是深度学习算法。深度学习不一定总是解决问题的正确工具:有时没有足够的数据,深度学习不适用;有时用其他算法可以更好地解决问题。如果第一次接触的机器学习就是深度学习,那么你可能会发现手中只有一把深度学习“锤子”,而所有机器学习问题看起来都像是“钉子”。为了避免陷入这个误区,唯一的方法就是熟悉其他机器学习方法并在适当的时候进行实践。
四、强化学习
- 区别于监督学习和无监督学习,强化学习并不是要对数据本身进行学习,而是在给定的数据环境下,让智能体学习如何选择一系列行动,来达成长期累计收益最大化的目标。强化学习本质上学习的是一套决策系统而非数据本身。
- 整个强化学习的过程,是为了学到好的策略(Policy),本质上就是学习在某个状态下应该选择什么样的行动,就相当于马里奥游戏的通关秘籍,输入马里奥每次的状态,秘籍会输出告诉你马里奥应该采取的行动,如此循环往复就能通关。因此,强化学习就是让人工智能通过不断的学习试错,找到合适的策略去选择一系列行动,来达成目标。
- 强化学习算法的工作过程。例子:马里奥左跳右跳吃蘑菇。
- 整个强化学习的过程,是为了学到好的策略(Policy),本质上就是学习在某个状态下应该选择什么样的行动。强化学习其实可以看作一个从试错到反馈的过程,通过不断地试错,来找到一个合适的策略。不过,每一个行动的反馈其实都是有延迟的,大多数状态下,马里奥都不会因为跳起或左右移动而输掉游戏或赢得游戏,从而获得惩罚或奖励,但这并不代表这个行动就没有价值,因为未来的胜利或失败就是一系列行动所导致的,现在的行动会影响未来的奖励。
- 只不过嘞,机器贪心呀,他会说,我要继续尝试, 一定要找到我认为价值最大的方向,利用找到的现有信息,达到目的。
五、GAN
1.GAN
- GAN综合了深度学习和强化学习的思想,通过一个生成器和一个判别器的相互对抗,来实现图像或文字等元素的生成过程。打一个并不严谨的比方,假设:
- 生成器收到的输入是[0.1,-0.5,0.2 … 0.9],据此生成了一张小猫的图片,而第一个数是和小猫的颜色相关的,当你把0.1换成0.2时,小猫可能就从橘猫变成了白猫。因为随机数是可以随意构造的,因此我们就可以利用生成器生成各种各样的新图片。不过,和一般的神经网络一样,在生成之前会有提前训练的过程,我们需要准备一个全是各种各样小猫图片的数据集供生成器训练。
- 生成器就好像一个学习画画的学生,而判别器就是评价学生画作的老师。
- 判别器(Discriminator)用于评价生成器生成的图像或句子到底看起来有多么真实。我们可以向判别器输入一个生成的图像或句子,判别器会输出一个数值(也被称为得分)。一般来说,我们会使用0到1的区间来表示得分,如果这个图像或句子非常像数据集里的真实数据,得分就会靠近1;反之,得分就会靠近0。
- 生成器就好像一个学习画画的学生,而判别器就是评价学生画作的老师。
- 生成器和判别器对抗过程的基本思想
- 生成器就好像一个学习画画的学生,而判别器就是评价学生画作的老师。一开始,学生读一年级,他看了一堆小猫的图片,然后随便画了一只猫,老师看了看学生画的猫,说画得不够逼真,看不清小猫的两只眼睛,这就是最开始的生成器和判别器的交互过程。学生努力练习画画,终于画好了小猫的两只眼睛,老师一看说合格了,然后学生升到了二年级,老师也开始依照二年级的评价标准去评价学生的画作,相当于生成器和判别器的性能都提升了。升到二年级后,学生再拿出原来的小猫画作肯定就无法令老师满意了,老师会觉得画得不够真实,无法看清小猫的脸部轮廓,于是学生又反复练习修改,直到令老师满意,于是学生升到三年级。如此循环往复,学生画画的水平会越来越精湛,画作看起来越来越真实。而老师判别画作的标准也会越来越严苛,督促学生完善画技,这就是生成器和判别器对抗过程的基本思想
- 生成器收到的输入是[0.1,-0.5,0.2 … 0.9],据此生成了一张小猫的图片,而第一个数是和小猫的颜色相关的,当你把0.1换成0.2时,小猫可能就从橘猫变成了白猫。因为随机数是可以随意构造的,因此我们就可以利用生成器生成各种各样的新图片。不过,和一般的神经网络一样,在生成之前会有提前训练的过程,我们需要准备一个全是各种各样小猫图片的数据集供生成器训练。
六、基本理论与基本数据操作
1.张量
- 我们的数据存储在多维NumPy数组中,也叫作张量(tensor)。
- 张量是由以下3个关键属性来定义的。
- 轴的个数(阶数)。举例来说,3阶张量有3个轴,矩阵有2个轴。这在NumPy或TensorFlow等Python库中也叫张量的ndim。
- 形状。这是一个整数元组,表示张量沿每个轴的维度大小(元素个数)。举例来说,前面的矩阵示例的形状为(3, 5),3阶张量示例的形状为(3, 3, 5)。向量的形状只包含一个元素,比如(5,),而标量的形状为空,即()。
- 数据类型(在Python库中通常叫作dtype)。这是张量中所包含数据的类型。举例来说,张量的类型可以是float16、float32、float64、uint8等。在TensorFlow中,你还可能会遇到string类型的张量。
- 导数这一概念可以应用于任意函数,只要函数所对应的表面是连续且光滑的。张量运算(或张量函数)的导数叫作梯度(gradient)。梯度就是将导数这一概念推广到以张量为输入的函数。还记不记得,对于一个标量函数来说,导数是如何表示函数曲线的局部斜率(local slope)的?同样,张量函数的梯度表示该函数所对应多维表面的曲率(curvature)。它表示的是,当输入参数发生变化时,函数输出如何变化。
- 动量解决了SGD的两个问题:收敛速度和局部极小值。
- 在某个参数值附近,有一个局部极小点(local minimum):在这个点附近,向左和向右移动都会导致损失值增大。如果使用学习率较小的SGD对参数进行优化,那么优化过程可能会陷入局部极小点,而无法找到全局极小点。使用动量方法可以避免这样的问题,这一方法的灵感来源于物理学。一个有用的思维模型是将优化过程想象成小球从损失函数曲线上滚下来。如果小球的动量足够大,那么它不会卡在峡谷里,最终会到达全局极小点。动量方法的实现过程是,每一步移动小球,不仅要考虑当前的斜率值(当前的加速度),还要考虑当前的速度(由之前的加速度产生)。这在实践中的含义是,更新参数w不仅要考虑当前梯度值,还要考虑上一次参数更新,将链式法则应用于神经网络梯度值的计算,就得到了一种叫作反向传播的算法。我们来具体看一下它的工作原理。用计算图进行自动微分思考反向传播的一种有用方法是利用计算图(compu- tation graph)。计算图是TensorFlow和深度学习革命的核心数据结构。它是一种由运算(比如我们用到的张量运算)构成的有向无环图。
- 计算图是计算机科学中一个非常成功的抽象概念。有了计算图,我们可以将计算看作数据:将可计算的表达式编码为机器可读的数据结构,然后用于另一个程序的输入或输出。举个例子,你可以想象这样一个程序:接收一个计算图作为输入,并返回一个新的计算图,新计算图可实现相同计算的大规模分布式版本。这意味着你可以对任意计算实现分布式,而无须自己编写分布式逻辑。或者想象这样一个程序:接收一个计算图作为输入,然后自动计算它所对应表达式的导数。如果将计算表示为一个明确的图数据结构,而不是.py文件中的几行ASCII字符,那么做这些事情就容易多了反向传播就是将链式法则应用于计算图,仅此而已。反向传播从最终损失值开始,自下而上反向运行,计算每个参数对损失值的贡献。这就是“反向传播”这个名称的由来:我们“反向传播”计算图中不同节点对损失值的贡献。
- 张量是由以下3个关键属性来定义的。
- 标量(0阶张量)
- 仅包含一个数字的张量叫作标量(scalar),也叫标量张量、0阶张量或0维张量。在NumPy中,一个float32类型或float64类型的数字就是一个标量张量(或标量数组)。可以用ndim属性来查看NumPy张量的轴的个数。标量张量有0个轴(ndim == 0)。张量轴的个数也叫作阶(rank)。下面是一个NumPy标量。
1
2
3
4
5
6>>> import numpy as np
>>> x = np.array(12)
>>> x
array(12)
>>> x.ndim
0
- 仅包含一个数字的张量叫作标量(scalar),也叫标量张量、0阶张量或0维张量。在NumPy中,一个float32类型或float64类型的数字就是一个标量张量(或标量数组)。可以用ndim属性来查看NumPy张量的轴的个数。标量张量有0个轴(ndim == 0)。张量轴的个数也叫作阶(rank)。下面是一个NumPy标量。
- 向量(1阶张量)
- 数字组成的数组叫作向量(vector),也叫1阶张量或1维张量。1阶张量只有一个轴。下面是一个NumPy向量。
1
2
3
4
5>>> x = np.array([12, 3, 6, 14, 7])
>>> x
array([12, 3, 6, 14, 7])
>>> x.ndim
1 - 这个向量包含5个元素,所以叫作5维向量。不要把5维向量和5维张量混为一谈!5维向量只有一个轴,沿着这个轴有5个维度,而5维张量有5个轴(沿着每个轴可能有任意个维度)。维度(dimensionality)既可以表示沿着某个轴上的元素个数(比如5维向量),也可以表示张量的轴的个数(比如5维张量),这有时会令人困惑。对于后一种情况,更准确的术语是5阶张量(张量的阶数即轴的个数),但5维张量这种模糊的说法很常见。
- 数字组成的数组叫作向量(vector),也叫1阶张量或1维张量。1阶张量只有一个轴。下面是一个NumPy向量。
- 矩阵(2阶张量)
- 向量组成的数组叫作矩阵(matrix),也叫2阶张量或2维张量。矩阵有2个轴(通常叫作行和列)。你可以将矩阵直观地理解为矩形的数字网格。下面是一个NumPy矩阵。
1
2
3
4
5
6>>> x = np.array([[5, 78, 2, 34, 0],
[6, 79, 3, 35, 1],
[7, 80, 4, 36, 2]])
>>> x.ndim
2
//第一个轴上的元素叫作行(row),第二个轴上的元素叫作列(column)。在上面的例子中,[5, 78, 2, 34, 0]是x的第一行,[5, 6, 7]是第一列。 - 在实际的实现过程中并不会创建新的2阶张量,因为那样做非常低效。重复操作完全是虚拟的,它只出现在算法中,而没有出现在内存中。但想象将向量沿着新轴重复10次,是一种很有用的思维模型。
- 向量组成的数组叫作矩阵(matrix),也叫2阶张量或2维张量。矩阵有2个轴(通常叫作行和列)。你可以将矩阵直观地理解为矩形的数字网格。下面是一个NumPy矩阵。
- 下面是一个3阶NumPy张量。
1
2
3
4
5
6
7
8
9
10
11
12>>> x = np.array([[[5, 78, 2, 34, 0],
[6, 79, 3, 35, 1],
[7, 80, 4, 36, 2]],
[[5, 78, 2, 34, 0],
[6, 79, 3, 35, 1],
[7, 80, 4, 36, 2]],
[[5, 78, 2, 34, 0],
[6, 79, 3, 35, 1],
[7, 80, 4, 36, 2]]])
>>> x.ndim
3
将多个3阶张量打包成一个数组,就可以创建一个4阶张量,以此类推。深度学习处理的一般是0到4阶的张量,但处理视频数据时可能会遇到5阶张量。
2.基本变换
- 我们使用语法train_images[i]来沿着第一个轴选择某张数字图像。选择张量的特定元素叫作张量切片(tensor slicing)。我们来看一下对NumPy数组可以做哪些张量切片运算。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15//下面这个例子选择第10~100个数字(不包括第100个),并将它们放在一个形状为(90, 28, 28)的数组中。
>>> my_slice = train_images[10:100]
>>> my_slice.shape
(90, 28, 28)
//它等同于下面这个更详细的写法——给出切片沿着每个张量轴的起始索引和结束索引。注意,:等同于选择整个轴。
>>> my_slice = train_images[10:100, :, :] ←----等同于前面的例子
>>> my_slice.shape
(90, 28, 28)
>>> my_slice = train_images[10:100, 0:28, 0:28] ←----也等同于前面的例子
>>> my_slice.shape
(90, 28, 28)
//一般来说,可以沿着每个张量轴在任意两个索引之间选择切片。举例来说,要在所有图像的右下角选出14像素×14像素的区域,可以这么做:
my_slice = train_images[:, 14:, 14:]
//也可以使用负数索引。与Python列表类似,负数索引表示与当前轴终点的相对位置。要在图像中心裁剪出14像素×14像素的区域,可以这么做。
my_slice = train_images[:, 7:-7, 7:-7] - 神经网络的“齿轮”:张量运算
- 所有计算机程序最终都可以简化为对二进制输入的一些二进制运算(AND、OR、NOR等),与此类似,深度神经网络学到的所有变换也都可以简化为对数值数据张量的一些张量运算(tensor operation)或张量函数(tensor function),如张量加法、张量乘法等。
- 数据批量的概念
- 通常来说,深度学习中所有数据张量的第一个轴(也就是轴0,因为索引从0开始)都是样本轴[samples axis,有时也叫样本维度(samples dimension)]。在MNIST例子中,样本就是数字图像。此外,深度学习模型不会一次性处理整个数据集,而是将数据拆分成小批量。具体来看,下面是MNIST数据集的一个批量,批量大小为128。batch = train_images[:128].然后是下一个批量。batch = train_images[128:256]再然后是第[插图]个批量。n = 3。batch = train_images[128 * n:128 * (n + 1)]。对于这种批量张量,第一个轴(轴0)叫作批量轴(batch axis)或批量维度(batch dimension)。在使用Keras和其他深度学习库时,你会经常遇到“批量轴”这个术语。
3.深度学习的数据流:你要处理的数据几乎总是属于下列类别。
- 向量数据:形状为(samples, features)的2阶张量,每个样本都是一个数值(“特征”)向量。
- 时间序列数据或序列数据:形状为(samples, timesteps, features)的3阶张量,每个样本都是特征向量组成的序列(序列长度为timesteps)。
- 图像数据:形状为(samples, height, width, channels)的4阶张量,每个样本都是一个二维像素网格,每个像素则由一个“通道”(channel)向量表示。
- 图像通常具有3个维度:高度、宽度和颜色深度。虽然灰度图像(比如MNIST数字图像)只有一个颜色通道,因此可以保存在2阶张量中,但按照惯例,图像张量都是3阶张量。对于灰度图像,其颜色通道只有一维。因此,如果图像大小为256×256,那么由128张灰度图像组成的批量可以保存在一个形状为(128, 256, 256, 1)的张量中,由128张彩色图像组成的批量则可以保存在一个形状为(128, 256, 256, 3)的张量中,如图2-4所示。
- 由图像数据组成的4阶张量
- 图像张量的形状有两种约定:通道在后(channels-last)的约定(这是TensorFlow的标准)和通道在前(channels-first)的约定(使用这种约定的人越来越少)。
- 通道在后的约定是将颜色深度轴放在最后:(samples, height, width, color_depth)。
- 与此相对,通道在前的约定是将颜色深度轴放在紧跟批量轴之后:(samples, color_depth, height, width)。如果采用通道在前的约定,那么前面两个例子的形状将变成(128, 1, 256, 256)和(128, 3, 256, 256)。Keras API同时支持这两种格式。
- 图像张量的形状有两种约定:通道在后(channels-last)的约定(这是TensorFlow的标准)和通道在前(channels-first)的约定(使用这种约定的人越来越少)。
- 视频数据:形状为(samples, frames, height, width, channels)的5阶张量,每个样本都是由图像组成的序列(序列长度为frames)。
- 三维情况的思维模型:
- 对于三维的情况,下面这个思维模型是很有用的。想象有两张彩纸:一张红色,一张蓝色。将一张纸放在另一张上,然后把它们一起揉成一个小球。这个皱巴巴的纸团就是你的输入数据,每张纸对应分类问题中的一个数据类别。神经网络要做的就是,找到可以让纸团恢复平整的变换,从而再次让两个类别明确可分。利用深度学习,这一过程可以通过三维空间中一系列简单变换来实现,比如用手指对纸团所做的变换,每次一个动作。
- 解开复杂的数据流形。让纸团恢复平整就是机器学习的目的:为高维空间中复杂、高度折叠的数据流形(manifold)找到简洁的表示。流形是指一个连续的表面,比如揉皱的纸。现在你应该能够很好地理解,为什么深度学习特别擅长这一点:它可以将复杂的几何变换逐步分解为一系列基本变换,这与我们展开纸团所采取的策略大致相同。深度神经网络的每一层都通过变换使数据解开一点点,而许多层堆叠在一起,可以实现极其复杂的解开过程。
- 对于三维的情况,下面这个思维模型是很有用的。想象有两张彩纸:一张红色,一张蓝色。将一张纸放在另一张上,然后把它们一起揉成一个小球。这个皱巴巴的纸团就是你的输入数据,每张纸对应分类问题中的一个数据类别。神经网络要做的就是,找到可以让纸团恢复平整的变换,从而再次让两个类别明确可分。利用深度学习,这一过程可以通过三维空间中一系列简单变换来实现,比如用手指对纸团所做的变换,每次一个动作。
巨人的肩膀
- 周志明老师的凤凰架构
- AIGC:智能创作时代
- Python深度学习
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.


