这一年来,AI领域层出不穷的技术和应用,真的有点让人疲于奔命。其中AIGC领域的diffusion model 和 NLP领域的 ChatGBT 引领了这一轮风潮。AI取代越来越多脑力工作者的趋势已经不可逆转,在这经济下行内卷严重的当代,竞争将越发的残酷。作为走在风口前沿的技术人,用stable diffusion绘制过逼真的画作,也用ChatGPT生产修改过样板代码,AI带给我的危机感是实实在在的,在ChatGPT风头正劲的那段时间,焦虑一度让我夜不能寐。
在AI狂潮告一段落的当下,是时候冷静下来思考,我们应该怎么看待AI,对待 AI 的正确态度是什么,这篇文章观点我大体上赞同:
ChatGBT像一个吸收了所有人类知识、但需要别人帮忙才能把这些知识串起来的应届毕业生。看来我今年的工作是安全的。但是,我需要好好学习 ChatGPT,精通它的使用,让我明年也是安全的。
AI 会大大增强程序员的生产力,并创造过去不可能的产品。AI 本质是生产力工具,跟高级语言、云服务、开源代码等是一个性质。写代码的门槛会降低,更多的人会进入 IT 行业,软件市场将变大。
我们要成为这个过程的一部分,需要让自己积极主动,不断更新技能,接受新工具。
是的,我们要成为这个AI落地各行各业过程的一部分,也是我这一年来自学机器学习、深度学习的动力和缘由,也陆陆续续在工作中落地了一些简单的ai项目,而这个机器学习和深度学习的系列就是我学习过程的一个记录和总结。
内容大纲
- 人工智能、机器学习和深度学习
- 机器学习
- 欠拟合、过拟合
- 机器学习通用流程
- 神经网络
人工智能、机器学习和深度学习
人工智能可以被定义为将通常由人类完成的智力任务自动化。因此,人工智能是一个综合性的领域,不仅包括机器学习与深度学习,还包括更多不涉及学习的方法。人工智能的真正挑战在于解决那些对人来说很容易执行、但很难形式化描述的任务,比如识别人们所说的话或图像中的脸。对于这些问题,我们人类往往可以凭直觉轻易地解决。
那什么是机器学习?机器学习就是自动发现解决复杂问题的规则的过程。计算机通常的工作方式:程序员编写规则(计算机程序),计算机遵循这些规则将输入数据转换为正确的答案。而机器学习却是把这个过程反过来:机器读取输入数据和对应的答案,然后从中找出合适的规则。与统计学不同,机器学习经常要处理复杂的大型数据集(比如包含数百万张图片的数据集,每张图片又包含数万个像素),用经典的统计分析(比如贝叶斯分析)来处理这种数据集是不切实际的。因此,机器学习(尤其是深度学习)呈现出相对较少的数学理论,从根本上来说是一门工程学科。机器学习是一门非常注重实践的学科,由经验发现所驱动,并深深依赖于软硬件的发展。
深度学习是机器学习的一个分支领域:它是从数据中学习表示的一种新方法,强调从连续的层(layer)中进行学习,这些层对应于越来越有意义的表示。“深度学习”中的“深度”指的并不是利用这种方法所获取的更深层次的理解,而是指一系列连续的表示层。数据模型中包含多少层,这被称为模型的深度(depth)。
机器学习
有三种技术力量在推动着机器学习的进步:
硬件
数据
算法
有一句形象的比喻:如果AI的发展是制造火箭,那么算法就是引擎,数据就是燃料,而硬件就是加速器,这三者缺一不可。在机缘巧合的10年前,它们共同推动了一直延续至今的第三波人工智能的浪潮,虽然我们不知道这次还能持续多久,但在各个领域落地开花后仍然足够改变这个世界。
机器学习的四个分支
监督学习:指用带标签的样例来逐步减小模型输出误差的方法,叫作监督式学习(supervised learning)。主要应用于标量回归,图像分类,目标检测,图形分割等。
无监督学习:指从无标签的数据中寻找输入数据的变换,包括聚类和异常检测,其目的在于数据可视化、数据压缩、数据去噪或更好地理解数据中的相关性。
自监督学习:在没有人工标注的标签的监督学习,你可以将它看作没有人类参与的监督学习。标签仍然存在(因为总要有什么东西来监督学习过程),但它们是从输入数据中生成的,通常是使用启发式算法生成的。
强化学习:强调智能体通过与环境的直接互动来学习,主要应用在游戏,自动驾驶、机器人等。
训练和推断
以监督学习为例,机器学习的工作流程由两个阶段构成:训练阶段和推断阶段。
训练阶段:机器自动发现数据与对应答案之间的规则,这个过程中发现的规则会封装在训练好的模型中。它们是训练阶段的成果,并且为推断阶段奠定基础。根据训练数据的多少、模型架构的复杂度和硬件的快慢,训练阶段会持续几毫秒到几天不等。
推断阶段:运用习得的模型为新的数据获取答案。
欠拟合与过拟合
如果模型不能很好地捕捉数据中的模式,那么就称该现象为欠拟合(underfit);反之,如果模型过度学习这些模式,以至于它不能将所学到规则的泛化到新数据上,那么就称该现象为过拟合(overfit)
当模型出现过拟合时,可以通过正则化(regularization)这样的应对措施将其拉回正轨。
要想应对欠拟合,我们通常会通过加大模型的规模来增加模型的表示能力。一般的应对策略是给模型添加更多使用非线性激活函数的层,并增加各层的尺寸(比如增加密集层中的单元数)。
模型能力的增强会带来一个副作用:它会使模型对训练集的拟合能力远超出对验证集的拟合能力,而后者包含模型训练时未曾见过的数据。这个现象就是过拟合。这种情况下,模型“过度关注”数据集中不相关的细节,以至于它的预测能力不能很好地泛化到未见过的数据上。
机器学习的根本问题在于优化与泛化之间的矛盾。优化(optimization)是指调节模型使其在训练数据上得到最佳性能的过程(对应机器学习中的学习),泛化(generalization)则是指训练好的模型在前所未见的数据上的性能。机器学习的目标是得到良好的泛化,但你无法控制泛化,只能让模型对训练数据进行拟合。如果拟合得太好,就会出现过拟合,从而影响泛化。
为了实现完美的拟合,你必须首先实现过拟合。由于事先并不知道界线在哪里,因此你必须穿过界线才能找到它。在开始处理一个问题时,你的初始目标是构建一个具有一定泛化能力并且能够过拟合的模型。得到这样一个模型之后,你的重点将是通过降低过拟合来提高泛化能力。
降低或提高学习率。学习率过大,可能会导致权重更新大大超出正常拟合的范围,就像前面的例子一样。学习率过小,则可能导致训练过于缓慢,以至于几乎停止。增加批量大小。如果批量包含更多样本,那么梯度将包含更多信息且噪声更少(方差更小)。最终,你会找到一个能够开始训练的配置。
机器学习通用流程
确定机器学习是否是合适的解决方案
定义机器学习问题和数据预测的目标。
定义一种能够可靠地评估模型训练成功与否的度量指标。对于简单的任务,使用预测准确率、精确率、召回率、ROC曲线和AUC值就足够了
为模型性能评估做准备。设计用于模型评估的验证过程。具体而言,应该将数据划分成3个分布一致但互无重叠的数据集:训练集、验证集和测试集。验证集和测试集的数据一定不能和训练集重叠。
向量化数据。将数据转换为张量,或者说多维数组。张量中的值应该缩放到较小且居中的范围,例如在[-1, 1]或[0, 1]区间中。
配置最后一层的激活函数:它能对模型的输出实现有效的约束。激活函数的选择应该和当前的问题类型匹配。
配置损失函数:和最后一层的激活函数类似,损失函数也应该和当前的问题类型匹配。例如,对于二分类问题应该使用binaryCrossentropy;对于多分类问题应该使用categoricalCrossentropy;对于回归问题,则应该使用meanSquaredError。
配置优化器:优化器负责驱动神经网络的权重更新。
开发容量充足的模型并刻意地过拟合数据集。通过手动改变超参数,可以逐渐扩展模型的架构,最终达到一个刚好过拟合训练集的模型。之前介绍过,监督式机器学习的一个共通且核心的问题是如何在优化(即拟合训练时见到的数据)和泛化(即针对未见过的数据进行预测)之间取得平衡。在理想情况下,模型应该介于欠拟合和过拟合之间。也就是说,模型的容量应该在容量过低和容量过高之间取得平衡。但只有先跨过平衡的临界点,才能找到这个临界点在哪里。
通过以下方法开发过拟合的模型:
添加更多层;
增加每层的尺寸;
使用更多的训练轮次。
应该时常用可视化手段监测训练和验证集上的损失,以及其他你所关心的度量指标(例如AUC)的性能。当你发现模型在验证集上的准确率开始下降时,就说明模型开始过拟合了。
给模型添加正则化并调整超参数
给模型添加正则化并调整超参数,从而尽可能接近介于欠拟合和过拟合之间的理想模型。在这一步中,你会需要不断地修改模型,训练它,在验证集上评估它(这一步还不需要在测试集上评估)。然后再重复这一过程,直到模型足够接近其理想状态。就正则化而言,可以尝试以下步骤。
添加使用不同丢弃率的dropout层。
尝试L1或L2正则化。
尝试不同的模型架构,比如对层数稍加调整。
调整其他超参数(例如密集层的单元数)。
神经网络
神经网络就是函数的级联。神经网络的每一层都可以看作一个函数,将这些层叠加在一起就意味着级联这些函数,这样得到的更复杂的函数就是神经网络。在深度学习的语境下,将输入特征映射到输出目标上的函数叫作模型(model),模型还可以叫作网络(network)。
构建多层神经网络时注意要在隐藏层中添加非线性激活函数,最常用的是relu函数。引入了非线性(nonlinearity)目的是增强神经网络的表示能力,使用得当可以提高各种预测任务的准确率。
神经网络的核心组成部分是层(layer),它是一个数据处理模块,可以看作张量之间的一个可调函数。
从本质上讲,密集层就是执行每组输入与输出之间的可调的乘积累加(multiply-add)运算。因为只有一个输入和一个输出,所以这个模型就是简单的线性方程:y = m * x + b。在密集层中,m叫作核(kernel),b叫作偏差(bias)。
为了得到较好的预测值,必须让模型从数据中学习,自动为核与偏差寻找恰当的数值。这个寻找的过程就是训练过程(training process)。
训练神经网络主要围绕以下四个方面。
- 层,多个层组合成网络(或模型)。
- 输入数据和相应的目标。
- 损失函数,即用于学习的反馈信号。
- 优化器,决定学习过程如何进行。
你可以将深度网络看作多级信息蒸馏操作:信息穿过连续的过滤器,其纯度越来越高(即对任务的帮助越来越大)。
神经网络的数据表示
- 张量(tensor)是一个数据容器。它包含的数据几乎总是数值数据。我们很熟悉的矩阵就是二维张量。张量是将矩阵概念泛化到任意维度的结果。
- 标量(0D张量):仅包含一个数字的张量叫作标量(scalar,也叫标量张量、零维张量、0D张量)。标量张量有0个轴(ndim==0)。张量轴的个数也叫作阶(rank)。
- 向量(1D张量):数字组成的数组叫作向量(vector)或一维张量(1D张量)。一维张量只有一个轴。
- 矩阵(2D张量):向量组成的数组叫作矩阵(matrix)或二维张量(2D张量)。矩阵有2个轴(通常叫作行和列)。你可以将矩阵直观地理解为数字组成的矩形网格。第一个轴上的元素叫作行(row),第二个轴上的元素叫作列(column)。
- 3D张量与更高维张量:将多个矩阵组合成一个新的数组,可以得到一个3D张量,可以将其直观地理解为数字组成的立方体。将多个3D张量组合成一个数组,可以创建一个4D张量,以此类推。深度学习处理的一般是0D到4D的张量,但处理视频数据时可能会遇到5D张量。
- 梯度:梯度(gradient)是张量运算的导数。它是导数这一概念向多元函数导数的推广。多元函数是以张量作为输入的函数。
- 随机梯度下降:给定一个可微函数,理论上可以用解析法找到它的最小值(函数的最小值是导数为0的点),因此你只需找到所有导数为0的点,然后计算函数在其中哪个点具有最小值。将这一方法应用于神经网络,就是用解析法求出最小损失函数对应的所有权重值。可以通过对方程gradient(f)(W)=0求解W来实现。
总结
在深度学习中,一切都是向量,一切都是几何空间中的点。首先将模型的输入(文本、图像等)和目标向量化,即将其转换为初始输入向量空间和目标向量空间。深度学习模型的每一层都对通过该层的数据做简单的几何变换。模型中的一连串层共同构成了一个非常复杂的几何变换,它可以分解为一系列简单的几何变换。这个复杂的几何变换试图将输入空间逐点映射到目标空间。它由层的权重来参数化,权重是根据模型当前的表现来迭代更新的。深度学习的神奇之处:将意义转化为向量,再转化为几何空间,然后逐步学习将一个空间映射到另一个空间的复杂几何变换。你需要的只是维度足够大的空间,以便捕捉到原始数据中的所有关系。
参考资料
《Python深度学习》
《Javascript深度学习》