最近人工智能非常火爆,大家可能经常听到AI、深度学习、大语言模型等名词。但真正能够将它们拆开来细致讲解的内容并不多。我大学就是学这个的,毕业后一直从事这个领域的工作。所以我打算今年陆续做一些这方面的科普,也借此机会复习巩固一下自己的知识体系。
今天就算是第一期,我们从机器学习这个概念讲起。其实机器学习是个非常庞杂的概念,很多事情都可以归到这个领域,像预测电影票房、识别人脸,以及计算机自动打游戏等,这都属于机器学习。但这个系列我打算专注在语言这个任务上,目的是让大家以及我自己更深入地了解大语言模型、GPT等横空出世的人工智能技术。所以在介绍各种技术概念时,我都会围绕语言领域展开。
在语言分析和语言生成的视角下,机器学习是什么呢?首先我们回顾一下自己当年是如何学习一门新语言的。比如学英语,一开始就是背单词死记硬背。单词表左边是意义不明的字母组合,右边是我们能看懂的中文解释。我们要做的就是记住这些英文词汇和它们的含义。通过将陌生词汇与它们的含义对照,我们就逐步建立起对新语言的认知。这个过程就可以被称为监督学习。监督学习的主要特征是用到了大量标记数据,也就是需要学习的内容通过学习者能够理解的方式做了标记。于是我们才能够将未知信息与已知信息一一对应起来,建立关系,然后再往陌生的更复杂情况去推导。
除了这种监督学习,还有一种情况是我们得不到明确的指导,就像刚出生时我们连中文都不会,或者上世纪很多人出国时外语也没怎么学。但这两种情况最后大家都能适应下来。这时就只能通过阅读听力或观察语言在日常生活中的使用来进行学习。在这种情况下,我们可能会开始识别模式,比如某些词汇总是在类似情境下反复出现,或某些词似乎具有相似结构或音韵特征。
就这样我们逐渐就会摸索出一套潜在的规则和分类。这种无监督学习和监督学习,构成了机器学习领域的两个基本类型。由此衍生的还有诸如半监督学习、自监督学习等混合学习模式。
但归根结底,这些方法都是为了让机器能够像人一样学习,通过算法自行找出数据间的关系和模式,而不需要人直接编程具体步骤来执行任务。这一概念正是机器学习与传统编程的根本区别所在。
它的深远意义在于,只要我们找到一套能有效学习到东西的算法,它就可以广泛适用于不同任务。比如我们搞了一套算法为给他人脸照片,它就能学会定位人脸。同样的算法,你让它学定位人手也是可以的,只需给它看大量包含人手的照片就行,而不像传统编程那样需要重新编写规则告诉它人手长什么样。
当我们真正按照这个思路走时,许多具体问题就出来了,主要有数据和模型两个问题。我们已经知道机器学习本质上是构建一套神经网络模型,让模型从大量数据中学习。那怎么获取足够多高质量的数据?怎么构建能力强、学习效率高的模型?就成了影响学习效果的关键。整个机器学习研究史基本上就是围绕着这两点展开的。
今天人工智能领域的热词大语言模型,它就是在这两方面都取得了突破。这一期我们先讲讲模型。在学术界,模型通常被用来表示对现实世界现象的简化和抽象。而在机器学习领域,我们可以把模型看作一个函数,或者说是一个有输入有输出的黑盒子。这个黑盒子内部结构可能无比复杂,但我们不用管,只关心它能否针对输入给出正确的输出,比如输入一张狗的照片,它输出就应该是狗。
在神经网络模型里,每个单元之间的连接都是一个权重数值,这些数值可以在输入输出之间建立无数种映射关系。但怎么才能确定这大量权重数值每个应该是多少呢?这就要靠反向传播算法了。不过在讲反向传播之前,我还要先回顾一下函数和导数的概念。
函数说白了就是一个写死的对应关系,比如y=2x,你输入2它就输出4。而导数就是用来衡量输出相对于输入变化的速度。如果输入变量调大一点从2变成2.1,y=2x这个函数输出就会增加0.2,那它的导数就是2。而神经网络要复杂得多,输入变量远不止一个,比如一张200x200的图片就有4万个像素变量,这就涉及到偏导数的概念了。
总之,神经网络模型通过调整每个神经元之间的权重连接,就能学会从输入映射到正确的输出,这正是机器学习的核心所在。接下来我会继续讲解反向传播算法以及数据获取的相关内容。
那到底哪个因素作用最大呢?这就是偏导数要求解的东西。偏导数要求解的就是这些不同的输入变量分别对应的权重是多少。实际在计算机里,训练一个神经网络的流程是这样的:首先训练程序会为每个输入变量随机分配一个0-1的权重值,比如场景的权重是0.5,人物是0.1,服装是0.4。然后我们假设这三方面都是可以量化的,比如在某一个游戏时刻,场景的精美度是0.1,人物的美观度是0.1,服装的优雅度是0.4。 那这第一轮随机权重计算下来,分数就是0.22。这就完成了一轮前向传播,根据输入把输出算了出来。但这时候,我们发现这个结果是错的,他算出来0.22这个分数并不高,但实际上我可能对着这个0.4分的服装已经兴奋起来了,我的兴奋值可能已经达到了0.6。
所以这个预测值和实际情况就有了偏差。但这个偏差该怎么衡量呢?这就要用到损失函数了。
损失函数通常是基于统计学的数学模型,常见的有均方误差、交叉熵损失、绝对误差等等。损失函数的结果永远是一个非负数值,它不能小于0。而这个数就被用来衡量模型的判断和实际情况的偏差有多大。比如说,咱们用绝对误差,那这个模型的输出和我的实际兴奋值的偏差就是0.38。
那要怎么让这个偏差缩小,让模型真正做到看到一个游戏画面就能准确的知道我有没有兴奋呢?首先我们知道,这个模型的输入输出之间的关系完全是由权重数值决定的,同样的输入,这些权重一变,输出就会完全不一样。可是这些权重该怎么改呢?这时候,我们就可以把这个偏差看成是一个关于这些权重值的函数,也就是刚说的损失函数。我们希望找到的就是损失函数变化最快的方向,也就是梯度。梯度可以看作是一个函数在特定点上的斜率或者坡度,它总是指向函数增长最快的方向。
咱们现在想象你站在某座山上,梯度告诉你的就是往哪个方向走能最快的上山,相应的,加个负号,原地转180度就是下山最快的方向。一直让权重数值沿着这个方向走,损失函数的值,也就是模型预测和实际情况的偏差就会越来越小。这个过程就叫梯度下降。
那回到刚才那个例子,咱们说那三个输入是X1、X2、X3,而对应的三个权重值分别是W1、W2、W3。那现在这个模型给出的映射关系就是y=W1X1+W2X2+W3X3。这时候,如果咱们反过来把它看成是一个y关于权重w的线性函数,那对这三个权重值分别求偏导,结果就是X1、X2、X3。想让偏差减小,就需要把0.22往0.6上拉,也就是沿着1、1、4这个方向走就可以了。
但这只是三个变量,在神经网络的实际使用里面,变量权重的数量可能有上千万,乃至数十亿数百亿个,而且是层层向下传导,这要怎么解决呢?这就要借助链式法则。
链式法则是一种计算复合函数导数的方法,当一个函数是由多个函数嵌套而成的时候,它的导数就等于外部函数的导数再乘以内部函数的导数。按照这个法则,我们就可以把一个很复杂的函数一层层拆解,得到每一层每一个权重值的导数,最后汇集成一个超高维度的梯度,就像是把洋葱一层层剥开一样。
这整个过程就像是倒着看一遍电影,从结尾开始,逐步回溯到开头,理解每个事件、每个线索是如何影响后续事件,最终影响整个故事走向的这一整个流程。运行完这个过程,先把输出算出来,再反向把权重的梯度找出来,最后再让所有的权重沿着这个梯度的方向前进一点点,我们就完成了一步更新模型,朝着更准确的方向又靠近了一些。
一开始,所有权重都是随机生成的,所以模型的修正速度会快一些,但越往后,准确率提得越来越高,这个速度就会逐渐慢下来,这时候就说这个模型的训练收敛了。
等模型收敛是个耐心活,打个形象的比方,就是钓鱼时候那个浮漂。扔下去的时候,它剧烈抖动,然后抖动幅度逐渐变小,但这时候它并没有真的稳下来,稍微再来点刺激,比如小风一吹或者水底一股小暗流,它就又抖起来了。这时候很多人就会忍不住提竿一看,结果啥都没了。但成熟的人就需要再忍耐一会、再坚持一下,这时候,这浮漂往往就会真正的越来越稳,直到最后完全和水面融为一体,真正收敛。
但也并不是所有的模型在训练过程中都一定能收敛。像模型本身有问题、训练数据有问题,或者超参数设置的有问题,都可能会导致模型训不出来,一直在波动,就好比说浮漂本身有破损,或者水太浅,钩沉底了。
咱们先说超参数。常见的超参数包括批量大小、迭代步数、激活函数、优化器选择等,它们不改变模型结构,但会控制模型怎么训练这个过程。这里最重要的一个超参数是学习率。学习率决定的是模型参数的更新幅度。前面咱们说梯度能指出偏差减小最快的那个方向,但这只是基于损失函数这一刻所在的这一个点。那要是一步迈大了,反而可能一下子跳到更高的地方,上去了老也下不去。但你如果步子老是非常小的也不好,一方面你移动的速度会特别慢,另一方面,假设说前面还有个小坑,你可能就直接陷进这个小坑里,再也走不出来了,永远摸不到更低的那个点。所以这也是需要反复测试、积累经验,直到和模型融为一体。
其他的超参数设置也都是类似,各有各的特征和局限,都是需要反复磨练,需要研究人员根据模型的表现,依赖直觉和试验去反复调整。这也是为什么机器学习有时候被叫做炼丹。然而超参数还不是最麻烦的,甚至现在如果你经费充足的话,你都可以直接把超参数丢给机器去学习让电脑自己去试验。
真正从底层决定训练能不能成的,其实是模型的结构本身。当年深度学习曾经差点没发展下去,就是发现层数增加到一定程度之后,模型就学不明白了。前面说模型的输出越来越准,靠的是通过反向传播的过程调整每一层的权重。但是在一个层数非常多的模型里,这个反向传播的过程会把很多导数值接连相乘,层数越多,乘的就越多。模型的权重值一开始都是随机给的,所以这些导数值也都是不确定的。假如有很多值都是大于1的,那这些数乘起来就会导致梯度爆炸,模型开始剧烈波动。而反过来的话,就是梯度消失,模型可能还远远没学明白,但就是不动了。所以深度学习刚有点火的意思就发展不下去了,直到残差网络的出现。
残差网络做的事很简单,他就是在计算网络层输出的时候,从前面再拽一层加到一块。这样在计算梯度的时候,下一层的变化就被上一层的原始信息给稀释了,一部分没有被完全清除掉。从头到尾,梯度变化的稳定性就增强了很多,不会爆炸,也不会消失了。这样一来,构建足够深的神经网络才成为了可能。在残差网络之前,神经网络的深度通常在几层到几十层之间,像著名的AlexNet有8层,VGG是16-19层,那时候这都已经是相当深了。可残差网络出来之后,神经网络都是上百乃至上千层啊,也就具备了解决更加复杂问题的能力。残差网络的作者何凯明,也因此拿到了2016年CVPR的最佳论文奖。今天,残差网络已经成了神经网络里一个几乎必备的结构了,几乎所有的大模型里都可以看到它。
但是走到这里,把超参数调好,把模型深度拉大,就一定能让电脑学明白了吗?其实未必,数据也是很重要的。我让你12年只学数学,然后高考考你英语,你不得干死我。但机器学习领域的学者不会犯这么低级的错误。但有些时候,可能数据太复杂了,以至于模型能力根本不足以找到合适的关系,这就会导致过拟合,也就是模型准确率升到一定程度之后就升不上去了。但这个问题出来的话,其实还挺明显的,所以危害不大,改进就完事了。有时候,模型能力太强了,它干脆把数据全原样背下来了,甚至会记住一些干扰因素。比如我告诉它现在这个视频画面里是林哥,结果它可能继承了有这个键盘的画面就是林哥,换只狗坐这啊,它还是觉得这是林哥,那就坏了。它其实并没有学到真正具备普遍性的规律,这就是过拟合。
过拟合的模型看上去表现很好,但只是在它学习过的数据上,真正拿出去解决实际问题反而解决不了。真正学明白了的模型是要具备泛化能力的。在机器学习里面,泛化指的是模型遇到从未见过的数据的时候能不能整明白,它是衡量模型性能的一个关键指标。一个具有良好泛化能力的模型应该能够适应陌生的数据环境,而不仅仅只是在训练数据上表现出色。因为真实世界的变化是无穷无尽的,只有真正从数据里面学到了底层的规律,才能推而广之,解决更多的同类问题。
那怎么来评估一个模型的泛化能力呢?我们会把数据划分为训练集、验证集和测试集来做这件事。训练集就像是平常的作业和习题,模型通过学习训练集上的数据来识别模式和规律。验证集就像是模拟考试,用来阶段性的评估模型表现。模型通过训练集的数据更新内部的权重值,然后经过验证集检测能力,检测出来发现效果不好的话,我们就调整超参数或者修改网络结构,直到它在验证集这个模拟考试上能拿到高分。这时候就到测试集了,测试集就是最终的高考,它评估的就是模型未来放到真实世界之后最终的性能大概会是什么样。
在之前的过程里,模型只学习过训练集,然后通过对训练过程的调整,它又做到了能把规律推广到验证
标签:这个,入门,权重,模型,通俗易懂,学习,就是,函数 From: https://blog.csdn.net/2401_84572204/article/details/139252780