10 应用机器学习的建议

10.1 决定下一步做什么

依旧用房价预测的例子,假设我们使用已经正则化的线性回归的模型得到了参数,并将参数带入预测函数来预测一组新的房价,但是结果误差很大,那么为了解决问题可能会用到以下方法:

  1. 获得更多训练样本(打电话、做调查)
  2. 尝试减少特征值
  3. 尝试获得更多特征值
  4. 增加多项式特征
  5. 减少正则化程度λ
  6. 增大正则化程度λ

不过这其中有很多方法会消耗大量时间和精力也不一定能减小误差,而且这么多方法,选择哪一种不应该是随机的。而是运用一些机器学习诊断法来帮助我们知道上面哪些方法对我们的算法是有效的。“诊断法”的意思是:这是一种测试法,你通过执行这种测试,能够深入了解某种算法到底是否有用。这通常也能够告诉你,要想改进一种算法的效果,什么样的尝试,才是有意义的。

10.2 评估假设

当使用梯度下降法或者更高级的优化算法得到的使代价函数最小化的参数,将参数带入预测函数,那么这个预测函数理论上已经使误差变小,但是并不能说明它一定是一个好的假设(过拟合假设)。要判断这个假设是否为过拟合,若只有一个特征值,可以通过画图判断,但如果假设函数有成百个特征值,画图就不太可能了,因此要用评价假设的标准方法。

下面介绍这种方法。一下面给出的样本为例(只给出十组,实际可能有成百上千条数据)。将整个训练集以7:3的比例划分成训练集(m个)和测试集(个),其中test下标就表示测试集(比如就表示第一组测试样本)。当然如果按7:3分配数据,最好整个数据集是随机排列的。

展示线性回归算法的训练/测试过程:

-对训练集进行学习得到参数θ(最小化训练误差J(θ)),这里用70%的训练数据

- 接下来,计算出测试误差(表示)

展示逻辑回归算法的训练/测试过程:

-首先从70%的训练数据中,学习得到参数θ

-用如下式子计算测试误差,用的是个训练样本

- 误分类的比率,对于每一个测试集实例,计算:

- 然后对计算结果求平均

10.3 模型选择和训练、验证、测试集

假设现在从是个不同次数的多项式构成的假设函数中进行模型选择,此处用参数d表示多项式的次数。接下来,想要确定这个d,也就是说选择哪个模型就选择哪个多项式的次数,拟合这个模型并估计这个拟合好的模型对新样本的泛化能力。

可以这样做:首先选择第一个模型,然后最小化训练误差,会得到一个参数θ;再选择第二个模型,也就是二次函数来拟合训练集,又得到一个θ;以此类推会得到10个θ,给他们加上上标,。接下来就是对所有模型求出测试集误差,可以算出,为了选出最好的模型,应该看哪个模型的测设误差最小。最终这个例子选择了多项式次数为5(d=5)的模型,那么接下来看这个模型对测试集的拟合情况,但是这样做仍然不能公平地估计出这个假设的泛化能力,原因是还拟合了一个额外的参数d,也就是用测试集拟合了参数d,进而选择了能最好地拟合测试集的参数d的值,所以假设对于测试集的表现好过于新的样本,但是模型好不好是针对新的样本的。

为了解决这一模型选择出现的问题,通常采用如下方法来评估一个假设。

给定一个数据集,不把它分为训练集和测试集,而把他分为三个部分,第一部分叫训练集,第二部分数据叫交叉验证(cv,沿用之前的下标习惯,验证集数据数量,样本),最后一部分还叫测试集。这三个部分的划分的比例为:6:2:2(最典型)。

有了训练集、交叉验证集、测试集,就可以对应定义训练误差、交叉验证误差和测试误差,以下为公式:

在选择模型时就需要使用到验证集或者叫做交叉验证集,而不是测试集。首先选择第一个模型,然后最小化代价函数,得到一个参数;选择第二个模型,最小化代价函数,得到,以此类推,可以得到十个参数。下一步是关键,不再用测试集来测试这些假设,而是用交叉验证集测试,计算出结果看看这些假设再交叉验证集上的效果,选择交叉验证误差最小的那个假设作为模型,最后这就意味着参数d有了结果,假设d=4,而我们是用交叉验证集来确定的这个参数,所以参数d不再用测试集拟合,这样就省下了测试集,可以用测试集衡量或者估计算法选出的模型的泛化误差了。

10.4 诊断偏差与方差

当运行一个学习算法时,如果这个算法的表现不理想,大概率只有两种情况:要么偏差比较大;要么方差比较大;即要么欠拟合要么过拟合。所以就要判断问题是偏差问题还是方差问题,这样就能很快找到有效的方法和途径来改进算法。

以下图为例:用很简单的假设会导致欠拟合,用很复杂的假设会过拟合,而用中等复杂的假设,次数不大不小对数据拟合得刚刚好。

再看下图:横坐标越往右得位置表示多项式得次数越大,最左边表示较为简单的预测函数,而最右边,d的值越大,对应的预测函数图像就是由较为复杂的函数表示的。那么现在将训练集误差和交叉验证集误差画在这张图上。

先看训练集误差:随着增大多项式的次数,对训练集的拟合越来越好,如果d=1,则对应较大的训练误差,而如果多项式次数很高时,训练误差会变得很低,甚至趋于零,因为训练集拟合的很好,所以随着d增大,训练误差逐步减小。

再看交叉验证集误差(其实和测试集误差结果类似):当d=1时,对应较大的交叉验证集误差,因为不能很好的拟合数据,如果用中等大小次数的多项式来拟合时,那么交叉验证集误差会变小,因为此时的d能更好的拟合数据,同样,如果d取很大,就会过拟合,此时又会得到一个较大的交叉验证误差,所以随着d的增大,交叉验证集误差的图像是一条如下图的图像(红色的线),先降低后升高。

那如何判断学习算法出现了高偏差的问题还是高方差的问题。

交叉验证误差比较大的情况:对应着曲线的最左边和最右边,左边的一端对应的就是高偏差(欠拟合)的问题,也就是使用了一个过于小的d,但是实际上需要一个较高的多项式次数来拟合数据。相反的,右边一端对应的就是高方差(过拟合)问题,也就是说多项式次数d对于数据来讲太大。

同时也会发现,对应高偏差时,它的交叉验证误差和训练误差都很大,所以,如果算法有偏差问题,那么训练集误差将会比较大,交叉验证误差也会很大,很接近训练误差,可能会比训练误差稍微大一些。如果存在这种组合,那就表示算法有高偏差问题。

反过来,如果算法存在高方差问题, 那么训练误差会很小,这代表对训练集数据拟合的很好,而交叉验证误差很大。所以交叉验证误差远远大于训练集误差。如果出现这种组合情况,就意味着学习算法出现了高偏差问题。

区分这两种问题的关键:如果算法处于高偏差情况,训练集误差和交叉验证误差都很大;而高方差情况的训练误差通常都会很小并且远远小于交叉验证误差。

10.5 正则化和偏差、方差

了解一下偏差和方差与算法的正则化之间的关系以及正则化是如何影响偏差和方差的。

假设,对下面这个高阶多项式进行拟合,为了防止过拟合,要给它加上一个正则化项来让参数的值尽可能小,正则化项的求和范围依旧取j等于1~m而非0~m。然后来分析以下三种情形:

        第一种情形是非常大的正则化参数λ,在这种情况下,所有的θ参数将被惩罚的很重,这些θ值大部分都接近于0,并且假设函数也会等于或接近于,假设函数大概为一条垂直于y轴的直线,所以这种情形的假设处于高偏差,对数据严重欠拟合。另一种极端情况即第三种情形,λ非常小(比如λ=0),在这种情况下让他拟合一个高阶多项式,通常会出现过拟合的情况,如果还没有正则化,或者正则化程度很小,通常会得到高方差,因为当λ=0时相当于没有正则化。只有去一个大小适中的λ时第二种情形,才能得到一组对数据拟合比较合理的θ值。

那如何选择一个这么合适的正则化参数λ呢。依旧使用上面的模型。

重新定义训练集误差,不考虑正则化项也就是平均的误差和,类似的,也定义交叉验证误差和测试误差如下:

选择一些可能的正则化参数λ(一般将步长设为2倍速度增长,直到一个比较大的值),然后开始从第一个λ开始试用。取第一个λ=0,然后最小化代价函数,这样就得到了某个参数向量θ,用表示;然后选取第二个λ,同样的步骤,得到,最后可以得到十二个参数向量。然后用交叉验证集来评价它们,选取这十二个交叉验证集误差最小的模型作为最终选择。此例选择了第五个模型。

如果要知道这个模型的测试误差,就可以用选出来的,观察它在测试集上的表现。

但最终要理解当λ变化时,训练误差和交叉验证集误差是怎么变化的。

如果λ很小,就表示几乎没有使用正则化,很大可能会过拟合;而λ过大时,会出现高偏差情况。所以当λ很小时,对训练集拟合相对较好,正则化项几乎不存在,只需要最小化平方误差项,最终会得到很小的训练误差;λ过大,高偏差问题,训练集不能很好的拟合,训练集误差会增大。而交叉验证误差,左右两端都很大,右边欠拟合,高偏差,左边过拟合,高方差。

10.6 学习曲线

要想看看学习算法运行的是否正常或者表现,就可以绘制学习曲线,它可以判断学习算法是出于偏差方差问题还是二者都有。

绘制学习曲线,通常会先绘制出也就是训练集的平均误差平方和,或者交叉验证平均误差平方和。将其绘制成一个以m(样本总数)为横坐标的曲线。如下图右方的假设模型来看,当样本很少(m=1、2、3),模型拟合得很好,训练误差也会小。随着训练集容量增大,平均训练误差也在增大。再看交叉验证集误差,当训练集很小时,泛化新样本就不会很好,只有当使用一个很大的训练集时,才能得到一个更好拟合数据得假设,那么交叉验证误差会随着样本总数的增多而逐渐减小,会有愈来愈好的泛化表现。

假设出现高偏差问题,以一条直线拟合数据为例(如图),这个假设函数不能很好地拟合数据。如果增多训练样本,用一条直线拟合数据还是不行,那么随着m不断增大,交叉验证误差会逐渐减小;而训练误差一开始会很小,但随着m的增大,会趋于交叉验证误差。这就是处于高偏差情形下,学习曲线的大致走向(高偏差情况下,样本越多,误差图像基本变平,最后不再变化了)。

假设出现高方差问题,训练集很小的时候,用高阶多项式拟合,用很小的λ,会对数据你和的很好,会出现过拟合,训练误差会很小;随着样本增多,拟合过程变得困难,训练误差也会变大,但总的来说还是很小。但交叉验证误差会随着样本数量增大而逐渐减小,但总的来说还是很大,所以交叉验证误差于训练误差之间相差很多。但在高方差情形下,随着m增大,交叉验证误差总归是下降的,所以增大样本数量对改进算法还是有帮助的。

10.7 决定接下来做什么

需要弄清楚哪些方法有助于改进学习算法的效果。

回到最初的例子,当一个正则化了的线性回归不能很好预测新的房子数据的房价时,当时提出了6种方法。现在就是判断以下哪些方法有效,哪些无效。

  1. 获得更多训练样本(打电话、做调查)
  2. 尝试减少特征值
  3. 尝试获得更多特征值
  4. 增加多项式特征
  5. 减少正则化程度λ
  6. 增大正则化程度λ

第1种方法适用于高方差

第2种方法适用于高方差

第3种方法适用于高偏差

第4种方法适用于高偏差

第5种方法适用于高偏差

第6种方法适用于高方差

神经网络的方差和偏差:

使用较小的神经网络,类似于参数较少的情况,容易导致高偏差和欠拟合,但计算代价较小使用较大的神经网络,类似于参数较多的情况,容易导致高方差和过拟合,虽然计算代价比较大,但是可以通过正则化手段来调整而更加适应数据。

​      通常选择较大的神经网络并采用正则化处理会比采用较小的神经网络效果要好。

​对于神经网络中的隐藏层的层数的选择,通常从一层开始逐渐增加层数,为了更好地作选择,可以把数据分为训练集、交叉验证集和测试集,针对不同隐藏层层数的神经网络训练神经网络, 然后选择交叉验证集代价最小的神经网络。

11 机器学习系统的设计

11.1 确定执行的优先级

以垃圾邮件分类器为例,用监督学习方法,通过邮件的特征x,和最终分类(y=1 or 0),用逻辑回归来分类。那么如何选取邮件的特征:比如用单词判断(购买、交易等是垃圾邮件,名字,现在可能就不是垃圾邮件),可以将典型的垃圾邮件单词按字典顺序排列,然后与邮件中的单词一一对比,出现了,其向量值为一,否则为0。

如何在有限的时间内,让这个分类器有较高的精准度呢?①可以收集更多数据,数据越多,算法越精准;②用更复杂的特征变量来描述邮件(通过邮件的标题构建一个更加复杂的特征来捕捉邮件的来源信息,以此判断是否为垃圾邮件);③还可以关注邮件的主体部分,构建更复杂的特征;④设计一些更复杂的算法检测单词故意拼写错误的这种情况。

大多数情况下,这些方法都是通过试用来选择最佳方法,或者随机决定。

11.2 误差分析

误差分析可以帮助我们更系统地在众多改进学习算法的方法中做出选择。

如果要设计机器学习系统,最好一开始用一个较为简单的算法快速实现它,用交叉验证集来测试;然后就能出相应的学习曲线,用图像来判断这个模型是否存在高偏差或者高方差的问题或其他问题,然后相应解决,比如获得更多数据或特征等;然后进行误差分析,比如要实现一个垃圾邮件分类器的时候,需要观察交叉验证集的情况,再观察一下被算法错误分类的文件有什么共同的特征和规律,这样可以有助于设计一些新特征,更快知道此时的系统的优缺点,然后想办法改进。

举例:假如做一个垃圾邮件分类器,交叉验证集中有500个样本,算法有较高的错误率,它分错了100个邮件的类别,现在就需要手工核查,观察它们的类型、特征,改进算法能更正确的分类。比如发现这100个邮件中,有12封卖药的、4封卖假货的、53封盗取密码的、其他类型31封,那么说明算法在辨别盗取密码这个类型的垃圾邮件时精准度不高,然后就可以通过设计新特征为他们正确分类。

改进算法的另一个途径:数值估计。如果算法在评估时能返回一个数值来估计算法执行的效果,是很有帮助的。比如一些垃圾邮件中会出现一些相似的单词,通过词干提取可以视为同一单词(dicount/discounts/discounted/discounting),如果想快速判断这种方法判断垃圾邮件准确率怎么样,就可以考虑数值估计,它可以快速返回一个数值判断效果,比如在交叉验证集上做误差分析验证,提取词干错误率为3%,不提取为5%,那么就可以初步判断这是一个好的方法。类似的例子还有是否区分大小写。这种数值估计法更快、更直接、可以加快整个机器学习系统设计的进程。

11.3 不对称性分类的误差评估

使用一个合适的误差度量值有时会对学习算法造成非常微妙的影响,这就是偏斜率问题。类偏斜情况表现为我们的训练集中有非常多的同一种类的实例,只有很少或没有其他类的实例。例如我们希望用算法来预测癌症是否是恶性的,在我们的训练集中,只有0.5%的实例是恶性肿瘤。假设我们编写一个非学习而来的算法,在所有情况下都预测肿瘤是良性的,那么误差只有0.5%。然而我们通过训练而得到的神经网络算法却有1%的误差。这时,误差的大小是不能视为评判算法效果的依据的。

  • 查准率Precision和查全率Recall

算法预测的结果分成四种情况:

​  1. 正确肯定True Positive,TP):预测为真,实际为真

​ 2.正确否定True Negative,TN):预测为假,实际为假

​ 3.错误肯定False Positive,FP):预测为真,实际为假

​ 4.错误否定False Negative,FN):预测为假,实际为真

查准率 = TP/(TP+FP),在预测有恶性肿瘤的病人中,实际上有恶性肿瘤的病人的百分比越高越好。

查全率 = TP/(TP+FN) ,在所有实际上有恶性肿瘤的病人中,成功预测有恶性肿瘤的病人的百分比越高越好。

所以,如果有一个模型,它的预测y总等于0(没有癌症),那么它的查全率为0,所以他不是一个好的模型。

11.4 查准率和查全率之间的权衡

很多应用中,我们希望能够保证查准率和召回率的相对平衡。

继续用癌症分类的例子,病人患癌症y=1,没患癌症y=0。假设用逻辑回归模型训练了数据,其输出概率在0-1之间的值,所以如果假设输出值大于等于0.5,那么y=1;假设输出值小于0.5,则y=0。而我们希望只有在非常确信的情况下告诉他们预测值为y=1(患癌症),若要非常精确,那么这个阈值不应该设为0.5,可以设成大于等于0.7,才能预测y=1,这样这个模型就有了较高的查准率,如果还需要较低的查全率,就可以将阈值设为0.9。这样也能比较精准的预测病人的患病结果。

如果要避免遗漏患有癌症的患者,也就是希望避免假阴性,FN,这种情况下,我们希望y=1,在这样的例子中不再设置高的阈值,而是设置的低一些,比如0.3,这样的情况下有30%的情况下病人会患癌症,我们会以更加保守的方式告诉他们结果,因此可以让病人更进一步治疗。这种情况下就属于高查全率,但是低查准率。

通常情况下,大部分回归模型的查全率和查准率需要权衡,改变临界值,画出图来权衡两个值。图像的最左边表示高查准,低查全;最右边表示高查全,低查准。他的图像不止一种有很多可能性,取决于回归模型的具体算法。

我们希望有一个帮助我们选择这个临界值的方法。有一种方法是计算平均值,,看看哪个模型有最高的均值,但这种方法不适用于预测值y总等于0或者1的情况,因为它的平均值较高,但实际上它不是一种很好的算法。

所以存在另一种方法叫做计算F1值,公式是,选择使得F1值最高的临界值 。

11.5 机器学习数据

虽然之前说 一开始不要盲目的花大量时间收集大量数据,因为大量数据只在一些情况下起作用。但是在一定条件下,得到大量的数据并在某种类型的学习算法中进行训练,可以是一种有效的方法来获得一个具有良好性能的学习算法。而这种情况往往出现在这些条件对于我们的问题都成立。 并且你能够得到大量数据的情况下。这可以是一个很好的方式来获得非常高性能的学习算法。

举例,吴恩达老师和Banko 、Brill三人共同做了一项研究,尝试通过机器学习算法来区分常见的易混淆的单词,他们尝试了许多种不同的算法,并发现数据量非常大时,这些不同类型的算法效果都很好。比如,在这样的句子中:早餐我吃了__个鸡蛋(to,two,too),在这个例子中,“早餐我吃了2个鸡蛋”,这是一个易混淆的单词的例子。于是他们把诸如这样的机器学习问题,当做一类监督学习问题,并尝试将其分类,什么样的词,在一个英文句子特定的位置,才是合适的。他们用了几种不同的学习算法。

他们所做的就是改变了训练数据集的大小,并尝试将这些学习算法用于不同大小的训练数据集中,这就是他们得到的结果。趋势很明显,随着训练集中样本数量的增大,这些算法的性能也得到了增强。

"取得成功的人不是拥有最好算法的人,而是拥有最多数据的人",这句话有时对,有时不对。

先来看对的情况,就是大量数据是有帮助的 。假设特征值有足够的信息来预测 y 值,假设我们使用一种需要大量参数的学习算法,比如有很多特征的逻辑回归或线性回归,或者用带有许多隐藏单元的神经网络,这些参数可以拟合非常复杂的函数,所以这个算法是低偏差。

再来看不对的情况。 现在假设我们使用了非常非常大的训练集,在这种情况下,尽管我们希望有很多参数,但是如果训练集比参数的数量还大,甚至是更多,那么这些算法就不太可能会过度拟合。也就是说训练误差有希望接近测试误差。

一个高性能的学习算法,我们希望它不要有高的偏差或者方差,因此偏差问题,我么将通过确保有一个具有很多参数的学习算法来解决,以便我们能够得到一个较低偏差的算法,并且通过用非常大的训练集来保证。

如果我们有大量的数据,而且还训练了一种带有很多参数的学习算法,那么这将会是一个很好的方式,来提供一个高性能的学习算法。

第06周:吴恩达 Andrew Ng 机器学习相关推荐

  1. 第01周:吴恩达 Andrew Ng 机器学习

    学习内容: 1 机器学习 1.1 机器学习定义 ①Arthur Samuel:在没有明确设置的情况下,使计算机具有学习能力的研究领域. e.g.跳棋游戏,使计算机与自己对弈上万次,使计算机学习到什么是 ...

  2. 第08周:吴恩达 Andrew Ng 机器学习

    13 聚类 聚类算法是学习的第一个无监督学习算法,它所用到的数据是不带标签的. 13.1 无监督学习 什么是无监督学习? 在无监督学习中,所有的数据不带标签,而无监督学习要做的就是将这一系列无标签的数 ...

  3. 第04周:吴恩达 Andrew Ng 机器学习

    学习内容: 8 神经网络 8.1 为什么用神经网络 当只有两个特征时(x1.x2),使用sigmoid函数得到的结果还可以,因为可以把x1.x2的所有组合都包含到多项式中.但当很多问题含有很多特征,不 ...

  4. 第05周:吴恩达 Andrew Ng 机器学习

    学习内容: 9 神经网络的运用 9.1 代价函数 其中: 假设训练集为m组的训练样本 用L表示神经网络的总层数,对于上图来说,L=4 用表示第L层的单元数,也就是神经元的数量(不包括这一层的偏差单元) ...

  5. 第07周:吴恩达 Andrew Ng 机器学习

    12 支持向量机(Support Vector Machines) 12.1 优化目标 在监督学习中,许多学习算法的性能都非常类似,因此,重要的不是你该选择使用学习算法A还是学习算法B,而更重要的是, ...

  6. 第10周:吴恩达 Andrew Ng 机器学习

    15 异常检测(Anomaly Detection) 这种算法虽然主要用于非监督学习问题,但从某些角度看,它又类似于一些监督学习问题. 15.1 问题动机 例:假想一个飞机引擎制造商,当他生产的飞机引 ...

  7. 第02周:吴恩达 Andrew Ng 机器学习

    学习目标: 完成对机器学习逻辑回归部分 完成习题 整理理论与编程题笔记 学习内容: 六.逻辑回归 6.1 分类问题Classification 二分类问题:通常结果有两种可能(0:negative c ...

  8. 第09周:吴恩达 Andrew Ng 机器学习

    14 降维(Dimensionality Reduction) 第二种类型的无监督学习问题叫降维 14.1 目标Ⅰ:数据压缩 使用降维的原因之一是数据压缩,数据压缩可以使数据占用较小的内存或硬盘空间, ...

  9. 【斯坦福公开课-机器学习】1.机器学习的动机和应用(吴恩达 Andrew Ng)

    文章目录 0三个目标 0先修课程要求 基本工具 1-网址 2-邮箱 3-本系列课程链接 1机器学习的定义 1-1非正式定义 1-2正式的定义 2监督学习(Supervised Learning) 2- ...

最新文章

  1. NP-Hard问题及组合最优化问题
  2. 智能合约重构社会契约 (2)雅阁项目智能合约
  3. Entity Framework 4.3.1 Code First 连接 PostgreSQL 9.2.3 小结
  4. jQ中的mouseleave和mouseout的区别 模仿下拉框效果
  5. hdfs中与file数组类似的数组_Chapter05 Java中的数组
  6. Entity Framework 数据库先行、模型先行、代码先行
  7. VSCode + git 代码托管【当前没有源代码管理提供程序注册】(没有‘+’加法号) - 解决篇
  8. 计算机启用远程桌面连接失败,开启局域网远程桌面连接不上怎么办
  9. Structs2 总结
  10. python问题解答网站_python问题解答网站
  11. 最少拍控制算法MATLAB仿真,最少拍控制系统.doc
  12. Android开发工程师已难找工作
  13. 445、Java框架99 -【MyBatis - 多对多】 2020.12.23
  14. C++中char类型详解
  15. UEFI是什么意思?UEFI和BIOS的区别是什么?
  16. 玲珑学院 1127 咸鱼文章
  17. HttpClient的POST请求提示302问题解决
  18. 水岸秀墅|千年石湖独一墅
  19. C语言中sizeof测量形参中数组的长度
  20. 中央气象局天气预报接口---java实现

热门文章

  1. asp.net+sqlserver婚纱影楼摄影管理系统C#
  2. vue使用wow.js
  3. 京东怎么使用礼品卡购物
  4. Mac快速查看文件路径并复制
  5. Android权限安全(4)在什么时候检验权限?
  6. 敬业福怎么得 2022年支付宝敬业福获取攻略来了
  7. 我的世界python指令攻略_我的世界之攻略大全149-指令大全又来啦
  8. “熊猫烧香”化身“金猪”危害指数再度飙升
  9. 前端程序员市场分析:前有狼,后有虎,走还是不走?
  10. 留不住时间,但留住了那美好的时光,那画面在我心中,永远不会被抹去