Datawhale X 李宏毅苹果书(入门) AI夏令营 task03笔记

官方学习文档:https://linklearner.com/activity/16/14/56

往期task01链接:http://t.csdnimg.cn/xxrO4

往期task02链接:http://t.csdnimg.cn/zhTOH

李宏毅老师对应视频课程可供食用:https://www.bilibili.com/video/BV1JA411c7VT/?p=4

实践方法论

        在应用机器学习算法时,实践方法论能够帮助我们更好地训练模型,更容易地解决问题。

       例如,如果在 Kaggle 上的结果不太好(虽然 Kaggle 呈现的是测试数据的结果,但要先检查训练数据的损失),就先看看模型在训练数据上面,有没有学起来,再去看测试的结果,如果训练数据的损失很大,显然它在训练集上面也没有训练好。接下来再分析一下在训练集上面没有训练好的原因。

模型偏差

        模型偏差可能会影响模型训练。

        举个例子,假设模型过于简单,将θ1代入一个有未知参数的函数 得到一个函数 fθ1(x),同理可得另一个函数 fθ2(x),把这些所有的函数集合起来得到一个函数的集合。但是该函数的集合还是太小,显然没有包含任何一个函数,让损失变低的函数有可能不在模型可以描述的范围内。

        在这种情况下,就算找出了一个 θ∗,虽然它是这些蓝色的函数里面最好的一个,但损失还是不够低。这种情况就是想要大海捞针(一个损失低的函数),结果针根本就不在海里。

        

        此时需要重新设计一个模型,给模型更大的灵活性。以往期task的预测未来观看人数为例,可以用深度学习,增加输入的特征,本来输入的特征只有前一天的信息,假设用前一天的信息预测接下来的观看人数效果不够好,那么就用 56 天前的信息,模型的灵活性就比较大了。

                 

        所以如果模型的灵活性不够大,可以增加更多特征,设一个更大的模型,用深度学习来增加模型的灵活性,这是第一个可以的解法。但是并不是训练的时候,损失大就代表一定是模型偏差,可能会遇到另外一个问题:优化做得不好

优化问题

        一般只会用到梯度下降进行优化,这种有优化的方法很多问题,比如可能会卡在局部最小值的地方,无法找到一个真的可以让损失很低的参数,如图 2.3(a) 所示。如图 2.3(b) 所示蓝色部分是所有模型可以表示的函数所形成的集合。

        这个蓝色的集合里面,确实包含了一些函数,这些函数它的损失是低的。但问题是梯度下降这个算法无法找出损失最低的函数,它找到上图的 θ∗ 就结束了。但 θ∗ 的损失显然不够低。

        这个模型里面存在着某一个函数的损失是够低的,但是梯度下降没有给出这个函数。这就像是大海捞针,针确实在海里,但是无法把针捞起来。

        训练数据的损失不够低的时候,到底是模型偏差,还是优化的问题呢?找不到一个损失低的函数,到底是因为模型的灵活性不够,海里面没有针。还是模型的灵活性已经够了,只是优化梯度下降不给力,它没办法把针捞出来,到底是哪一个。到底模型已经够大了,还是它不够大,怎么判断这件事呢?

        一个建议判断的方法是通过比较不同的模型来判断模型现在到底够不够大举个例子,这一个实验是从残差网络的论文“Deep Residual Learning for Image Recognition”里面节录出来的。这篇论文在测试集上测试两个网络,一个网络有 20 层,一个网络有 56 层。图 2.4(a)横轴指的是训练的过程,就是参数更新的过程,随着参数的更新,损失会越来越低,但是结果20 层的损失比较低,56 层的损失还比较高。残差网络是比较早期的论文,2015 年的论文。很多人看到这张图认为这个代表过拟合,深度学习不奏效,56 层太深了不奏效,根本就不需要这么深。但这个不是过拟合,并不是所有的结果不好,都叫做过拟合。在训练集上,20 层的网络损失其实是比较低的,56 层的网络损失还是比较高的,如图 2.4(b) 所示,这代表 56 层的网络的优化没有做好,它的优化不给力。

Q:如何知道是 56 层的优化不给力,而不是模型偏差,56层的网络的模型灵活性还不够大,它要 156 层才好?

A:因为比较 56 层跟 20 层,20 层的损失都已经可以做到这样了,56 层的灵活性一定比 20 层更大。56 层的网络要做到 20 层的网络做到的事情对它来说是轻而易举的。它只要前 20 层的参数,跟这个 20 层的网络一样,剩下 36 层就什么事都不做,复制前一层的输出就好了。如果优化成功,56 层的网络应该要比 20 层的网络可以得到更低的损失。但结果在训练集上面没有,这个不是过拟合,这个也不是模型偏差,因为 56 层网络灵活性是够的,这个问题是优化不给力,优化做得不够好。

过拟合是指一个模型在训练过程中学到了训练数据的细节和噪声,以至于它在新的、未见过的数据上表现不佳。

我们可以用一个比喻来形象地解释过拟合:

        想象你在准备一场考试。如果你只是死记硬背了过去试卷上的所有题目(这类似于模型过度学习训练数据),那么当你面对类似的但不是完全相同的题目时(就像模型面对新数据时),你就可能无法正确解答。因为你学到的是具体的答案,而不是解题的方法。这就是过拟合:模型过于专注于记忆训练数据中的细节,以至于它失去了泛化能力——即在新数据上做出正确预测的能力。

        ​​​​​​​这里的“死记硬背”不会导致模型灵活性降低,这里的灵活性更多的是指模型的能力范围,即模型能拟合什么样的函数。如果模型“死记硬背”了训练数据,那么它的确会在新数据上表现得不够灵活,因为它无法泛化到未见的数据。但这并不意味着模型的整体灵活性降低,只是它的表现受到了限制,仅限于已知的训练数据。

        过拟合的一个常见原因是模型复杂度过高,以至于它可以几乎完美地拟合训练数据中的每一个点,包括数据中的随机噪声。这样虽然模型在训练数据上的表现非常好(如误差极低),但在实际应用中(即对新数据进行预测)表现却很差。

这里显然不是过拟合,因为56层的网络在训练数据上也表现的没有20 层的网络好。

下面补充了关于过拟合的另一种理解方式

        这边给大家的建议是看到一个从来没有做过的问题,可以先跑一些比较小的、比较浅的网络,或用一些非深度学习的方法,比如线性模型、支持向量机(Support Vector Machine,SVM),SVM 可能是比较容易做优化的,它们比较不会有优化失败的问题。也就是这些模型会竭尽全力地在它们的能力范围之内,找出一组最好的参数,这样可以先知道这些简单的模型到底可以得到什么样的损失。

        接下来还缺一个深的模型,如果深的模型跟浅的模型比起来,深的模型明明灵活性比较大,但损失却没有比浅的模型压得更低,这代表优化有问题,梯度下降不给力,那么就用一些其它的方法来更好地进行优化。

        举个观看人数预测的例子,如图 2.5 所示,在训练集上面,2017 年到 2020 年的数据是训练集,1 层的网络的损失是 280,2 层就降到 180,3 层就降到 140,4 层就降到 100。但是测 5 层的时候结果变成 340。损失很大显然不是模型偏差的问题,因为 4 层都可以做到 100了,5 层应该可以做得更低。这是优化的问题,优化做得不好才会导致这样子。

                          

        如果训练损失大,可以先判断是模型偏差还是优化。如果是模型偏差,就把模型变大;如果是优化的问题,就用其他的方法。假设经过努力可以让训练数据的损失变小,接下来看测试数据损失,如果测试数据损失也小,比这个较强的基线模型还要小,就结束了。

        但如果训练数据上面的损失小,测试数据上的损失大,可能是真的过拟合。在测试上的结果不好,不一定是过拟合。要把训练数据损失记下来,先确定优化没有问题,模型是不是够大了。接下来才看看是不是测试的问题,如果是训练损失小,测试损失大,这个有可能是过拟合。

过拟合

        为什么会有过拟合这样的情况呢?举一个极端的例子,假设根据训练集,某一个很废的机器学习的方法找出了一个一无是处的函数。这个一无是处的函数,只要输入 x 有训练集里面出现过,就把它对应的 y 输出;如果 x 没有出现在训练集里面,就输出一个随机的值。这个函数啥事也没有干,是一个一无是处的函数,但它在训练数据上的损失是 0。因为把训练数据通通丢进这个函数里面,它的输出跟训练集的标签是一模一样的,但是在测试数据上面,它的损失会变得很大,因为它其实什么都没有预测,这是一个比较极端的例子,但是在一般的情况下,也有可能发生类似的事情。

        如图 2.6 所示,举例来说,假设输入的特征为 x,输出为 y,x 和 y 都是一维的。x 和 y之间的关系是 2 次的曲线,曲线用虚线来表示。

                   

        因为通常没有办法直接观察到这条曲线。我们真正可以观察到的是训练集,训练集可以想像成从这条曲线上面,随机采样出来的几个点。这个模型灵活性很大,因为只给它这 3 个点,在这 3 个点上面要让损失低,所以模型的这个曲线会通过这 3 个点,但是没有其它为训练集做限制的地方,因此它的灵活性很大,模型可以变成各式各样的函数。

        如果再丢进测试数据,测试数据和训练数据当然不会一模一样,它们可能是从同一个分布采样出来的,测试数据是橙色的点,训练数据是蓝色的点。用蓝色的点找出一个函数后,在橘色的点上测试不一定会好。因为如果模型的自由度很大的话,它可以产生非常奇怪的曲线,导致训练集上的结果好,但是测试集上的损失很大。

怎么解决过拟合的问题呢,有两个可能的方向:

        第一个方向增加训练集往往是最有效的方向。因此如果训练集,蓝色的点变多了,虽然模型它的灵活性可能很大,但是因为点非常多,它就可以限制住,这样它的形状会很像产生这些数据背后的 2 次曲线,如图 2.7 所示。可以做数据增强(data augmentation),这个方法并不算是使用了额外的数据。

        数据增强就是根据问题的理解创造出新的数据。举个例子,在做图像识别的时候,常做的一个招式是,假设训练集里面有某一张图片,把它左右翻转,或者是把它其中一块截出来放大等等。对图片进行左右翻转,数据就变成两倍。

        但是数据增强不能够随便乱做。在图像识别里面,很少看到有人把图像上下颠倒当作增强。因为这些图片都是合理的图片,左右翻转图片,并不会影响到里面的内容。但把图像上下颠倒,可能不是一个训练集或真实世界里面会出现的图像。如果给机器根据奇怪的图像学习,它可能就会学到奇怪的东西。所以数据增强,要根据对数据的特性以及要处理的问题的理解,来选择合适的数据增强的方式。

        另外一个解法是给模型一些限制,让模型不要有过大的灵活性。假设 x 跟 y 背后的关系其实就是一条 2 次曲线,只是该 2 次曲线里面的参数是未知的。如图 2.8 所示。因为一开始的模型是自己设计的,设计出不同的模型,结果不同。假设模型是 2 次曲线,在选择函数时有很大的限制,因为 2 次曲线来来去去就是几个形状而已。所以虽然说只给了 3 个点,但是因为能选择的函数有限,可能就会正好选到跟真正的分布比较接近的函数,在测试集上得到比较好的结果。

                     

        解决过拟合的问题,要给模型一些限制,最好模型正好跟背后产生数据的过程是一样的,这样就有机会得到好的结果。给模型制造限制可以有如下方法:

给模型比较少的参数。如果是深度学习的话,就给它比较少的神经元的数量,本来每层一千个神经元,改成一百个神经元之类的,或者让模型共用参数,可以让一些参数有一样的数值。

        全连接网络(fully-connected network)其实是一个比较有灵活性的架构,而卷积神经网络(Convolutional Neural Network,CNN)是一个比较有限制的架构,它针对图像的特性来限制模型的灵活性。所以全连接神经网络可以找出来的函数所形成的集合其实是比较大的,CNN 的相对而言较小,包含在全连接网络的里面。但是就是因为CNN 给了比较大的限制,所以 CNN 在图像上反而会做得比较好,这个之后都还会再提到。

用比较少的特征,本来给 3 天的数据,改成用给两天的数据,其实结果就好了一些。

• 还有别的方法,比如早停(early stopping)、正则化(regularization)丢弃法(dropoutmethod)

值得注意的是,减少特征和减少训练集并不是同一个意思,它们分别对应不同的方法来应对过拟合问题:
        减少特征是指从原始数据集中选择一部分最有代表性的特征,丢弃那些无关紧要或冗余的特征。这个过程称为特征选择或特征工程。减少特征的主要目的是降低模型的复杂度,同时保持尽可能多的重要信息。这样做的好处是可以降低过拟合的风险,提高模型的泛化能力。特征选择可以通过多种方法实现,如过滤式方法(filter methods)、包裹式方法(wrapper methods)或嵌入式方法(embedding methods)。此外,还可以使用降维技术,如主成分分析(PCA)、线性判别分析(LDA)等,将高维数据转换成低维空间表示。
        减少训练集则是指使用更少的数据样本进行训练。这通常是通过采样技术实现的,如随机抽样、留出法(holdout method)、交叉验证(cross-validation)等。减少训练集的目的在于限制模型的学习能力,防止它过度拟合训练数据中的噪声和细节。这种方法也可以降低过拟合风险,但需要注意的是,减少训练集可能会牺牲模型的准确性,因为模型缺乏足够的数据来学习潜在的关系。

但是根据上文增加训练集也可以解决过拟合问题,证明了训练集的大小应当适度。

        总结一下,减少特征侧重于精简输入数据的维度,而减少训练集则涉及减少训练数据的数量。两者都可以作为缓解过拟合的策略,但作用机制不同。在实践中,通常结合使用这两者以及其他技术,如正则化、早停、Dropout 等,来获得最优的模型性能。

        但也不要给太多的限制。在假设模型是线性的模型的情况下,图 2.9 中有 3 个点,没有任何一条直线可以同时通过这 3 个点。只能找到一条直线跟这些点相比,它们的距离接近。这个时候模型的限制就太大了,在测试集上也不会得到好的结果。

        这种情况下的结果不好并不是因为过拟合了,而是因为给模型太大的限制,大到有了模型偏差的问题。

        举一个过拟合的例子,在模型的复杂程度或者说模型的灵活性越来越大时(比较复杂的模型通俗易懂一点就是包含的函数和参数比较多),如图 2.10 所示,训练损失越来越低,但测试时,当模型越来越复杂的时候,刚开始,测试损失会跟着下降,但是当复杂的程度超过某一个程度以后,测试损失就会突然暴增。

        这就是因为当模型越来越复杂的时候,复杂到某一个程度,过拟合的情况就会出现。所以在训练损失上面可以得到比较好的结果,但在测试损失上面,会得到比较大的损失。所以要选一个中庸的模型,不是太复杂也不是太简单,刚刚好可以在训练集上损失最低,测试损失最低。

        假设 3 个模型的复杂程度不太一样,不知道要选哪一个模型才会刚刚好,在测试集上得到最好的结果。选太复杂的就过拟合,选太简单的有模型偏差的问题。该怎么办呢?

        可以把这 3 个模型的结果都跑出来,上传到 Kaggle 上面,损失最低的模型显然就是最好的模型,但是不建议这么做。举个极端的例子,假设有 1 到 10^{12}个模型,这些模型学习出来的函数都是一无是处的函数。它们会做的事情就是,训练集里面有的数据就把它记下来,训练集没看过的,就直接输出随机的结果。把这 10^{12}个模型的结果,通通上传到 Kaggle 上面,得到 10^{12}个分数,这10^{12}的分数里面,结果最好的,模型也是最好的。

        虽然每一个模型没看过测试数据,其输出的结果都是随机的,但不断随机,总是会找到一个好的结果。也许某个模型找出来的函数,正好在测试数据上面的结果比较好,就选这个模型当作最后上传的结果。该模型是随机的,它恰好在公开的测试数据上面得到一个好结果,但是它在私人测试集上可能仍然是随机的。

        测试集分成公开的数据集跟私人的数据集,公开的分数可以看到,私人的分数要截止日期以后才知道。如果根据公开数据集来选择模型,可能会出现这种情况:在公开的排行榜上面排前十,但是截止日期一结束,可能掉到 300 名之外。因为计算分数的时候,会同时考虑公开和私人的分数。

Q:为什么要把测试集分成公开和私人?

A:假设所有的数据都是公开,就算是一个一无是处的模型,它也有可能在公开的数据上面得到好的结果。如果只有公开的测试集没有私人测试集,写一个程序不断随机产生输出就好,不断把随机的输出上传到 Kaggle,这样就可以随机出一个好的结果。但这个显然没有意义。

交叉验证

        选择模型比较合理的方法是把训练的数据分成两半,一部分称为训练集(training set),一部分是验证集(validation set)。比如 90% 的数据作为训练集,有 10% 的数据作为验证集。在训练集上训练出来的模型会使用验证集来衡量它们的分数,根据验证集上面的分数去挑选结果,再把这个结果上传到 Kaggle 上面得到公开分数。

        因为在计算分数时是用验证集来挑模型,所以公开测试集分数就可以反映正确的分数,接着根据结果来继续调整模型。但假设这个循环做太多次,根据公开测试集上的结果调整模型太多次,就又有可能在公开测试集上面过拟合,在私人测试集上面得到差的结果。

        不过因为上传的次数有限制,所以无法走太多次循环,可以避免在公开的测试集上面的结果过拟合。根据过去的经验,就在公开排行榜上排前几名的,往往私人测试集很容易就不好。

        其实最好的做法,就是用验证损失,最小的直接挑就好了,不要管公开测试集的结果。在实现上,不太可能这么做,因为公开数据集的结果对模型的选择,可能还是会有些影响的。理想上就用验证集挑就好,有过比较好的基线(baseline)算法以后,就不要再去动它了,就可以避免在测试集上面过拟合。

        但是这边会有一个问题,如果随机分验证集,可能会分得不好分到很奇怪的验证集,会导致结果很差,如果有这个担心的话,可以用 k 折交叉验证(k-foldcross validation),如图 2.11 所示。k 折交叉验证就是先把训练集切成 k 等份,在这个例子,训练集被切成 3 等份,切完以后,拿其中一份当作验证集,另外两份当训练集,这件事情要重复 3 次。即第1份第 2 份当训练,第 3 份当验证;第1份第 3 份当训练,第 2 份当验证;第 2 份第 3 份当训练,第1份当验证。

        假设有 3 个模型,不知道哪个最好。把这 3 个模型在这 3 个设置下通通跑过一次,然后把这 3 个模型在这 3 种情况的结果都平均起来,再看谁的结果最好。假设结果是模型 1 最好,再把模型 1 用在全部的训练集上,训练出来的模型再用在测试集上面。

不匹配

        接下来也许我们要问的一个问题是,之前的案例预测 2 月 26 日,也就是上周五的观看人数的结果到底怎么样呢?如图 2.12 所示,之前说明了3层网络的效果最好。所以把 3 层的网络拿来测试一下。

        图 2.13 中横轴就是从 2021 年的 1 月 1 号开始一直往下,红色的线是真实的数字,蓝色的线是预测的结果。2 月 26 日是 2021 年实际观看人数最多的一天了,但是与机器的预测差距非常的的大。

        再跑 1 层、2 层跟4层之后显示,所有的模型的结果都不好,2层跟 3 层的错误率都是 2 千多,其实4层跟1层比较好,都是 1800 左右,但是这四个模型不约而同的觉得 2 月 26 日应该是个低点,但实际上 2 月 26 日是一个峰值,模型其实会觉得它是一个低点,也不能怪它,因为根据过去的 数据,周五晚上大家都出去玩了。但是 2 月 26 日出现了反常的情况。这种情况应该算是另外一种错误的形式,这种错误的形式称为不匹配(mismatch)

        不匹配跟过拟合其实不同,一般的过拟合可以用搜集更多的数据来克服,但是不匹配是指训练集跟测试集的分布不同,训练集再增加也没有帮助。假设数据在分训练集跟测试集的时候,使用 2020 年的数据作为训练集,使用 2021 年的数据作为测试集,不匹配的问题可能就很严重,根本预测不准。因为 2020年的数据跟 2021 年的数据背后的分布不同。

        图 2.14 是图像分类中的不匹配问题,增加数据也不能让模型做得更好。所以这种问题要怎么识别呢?这就要看对数据本身的理解了,我们可能要对训练集跟测试集的产生方式有一些理解,才能判断它是不是遇到了不匹配的情况。


感谢您的学习,让我们共同探索机器学习的奥秘!我们下期再见!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值