Maching Learning Yearning-Technical Strategy for AI Enginners吴恩达

一、机器学习策略的原因

    机器学习是无数重要应用程序的基础,包括网络搜索,电子邮件反垃圾邮件,语音识别,产品推荐等。我假设您或您的团队正在开发机器学习应用程序,并且您希望快速取得进展。这本书将帮助你这样做。

    示例:构建猫图片启动说您正在建立一个为猫爱好者提供源源不断的猫图片的创业公司。


    您使用神经网络构建计算机视觉系统,用于检测图片中的猫。

但悲惨的是,你的学习算法的准确性还不够好。您正面临着改善猫探测器的巨大压力。你是做什么?

您的团队有很多想法,例如:

•获取更多数据:收集更多猫的照片。

 •收集更多样化的培训集。例如,猫在异常位置的照片;猫有不寻常的颜色;用各种相机设置拍摄的照片; ...。

 •通过运行更多梯度下降迭代来更长时间地训练算法。 

•尝试更大的神经网络,具有更多层/隐藏单元/参数。

•尝试更小的神经网络。

 •尝试添加正则化(例如L2正则化)。

 •更改神经网络架构(激活功能,隐藏单元数等)

•......

        如果您在这些可能的方向中做出选择,您将构建领先的猫图片平台,并引领您的公司走向成功。如果你选择不好,你可能会浪费几个月。你怎么办?

        这本书将告诉你如何。大多数机器学习问题都会留下线索,告诉你尝试什么是有用的,什么是没用的尝试。学习阅读这些线索将为您节省数月或数年的开发时间。


二、如何使用本书来帮助您的团队

        完成本书后,您将深入了解如何为机器学习项目设置技术方向。但是你的队友可能不明白为什么你推荐一个特定的方向。也许您希望您的团队定义单一数字评估指标,但他们并不相信。你怎么说服他们?

        这就是为什么我让章节简短:这样你就可以将它们打印出来并让你的队友只阅读你需要知道的1-2页。优先级的一些变化会对团队的工作效率产生巨大影响。通过帮助您的团队进行一些此类更改,我希望您能成为团队的超级英雄!

三、先决条件和符号

        如果您参加过机器学习课程,例如我在Coursera学习MOOC,或者您有应用监督学习的经验,您将能够理解本文。

        我假设您熟悉有监督的学习:使用标记的训练样例(x,y)学习从x到y映射的函数。监督学习算法包括线性回归,逻辑回归神经网络。机器学习有很多种形式,但今天机器学习的大部分实用价值来自于有监督的学习。

        我会经常提到神经网络(也称为“深度学习”)。您只需要基本了解它们遵循本文的内容。

        如果您不熟悉这里提到的概念,请在Coursera上的机器学习课程中观看前三周的视频,网址为http://ml-class.org

四、规模推动机器学习进步

        许多深度学习(神经网络)的想法已经存在了几十年。为什么这些想法现在起飞了?

        最近取得进展的两个最大驱动因素是:

     •数据可用性。人们现在将更多时间花在数字设备(笔记本电脑,移动设备)上。他们的数字活动产生了大量的数据,我们可以提供给我们的学习算法。

     •计算规模。几年前我们就开始能够训练足够大的神经网络,以利用我们现在拥有的庞大数据集。

        详细地说,即使你积累了更多的数据,通常是较老的学习算法的性能,例如逻辑回归,“平稳”。这意味着它的学习曲线“变平”,即使你给它更多的数据,算法也会停止改进:


    就好像旧的算法不知道如何处理我们现在拥有的所有数据。如果您在同一个监督学习任务上训练一个小型神经网络(NN),您可能会获得稍微好一点的性能:


这里,“小型神经网络”是指仅具有少量隐藏单元/层/参数的神经网络。最后,如果你训练越来越大的神经网络,你可以获得更好的性能。


        当您(i)训练一个非常大的神经网络时,您将获得最佳性能,以便您处于上方的绿色曲线上; (ii)拥有大量数据。

        许多其他细节,如神经网络架构也很重要,这里有很多创新。但是,目前提高算法性能的一种更可靠的方法仍然是(i)训练更大的网络和(ii)获得更多数据

    如何完成(i)和(ii)的过程令人惊讶地复杂。本书将详细讨论细节。我们将从对传统学习算法和神经网络都有用的一般策略开始,并构建最现代的构建深度学习系统的策略。



设置开发和测试集

五、您的开发和测试集

        让我们回到我们之前的猫图片示例:您运行移动应用程序,用户正在将许多不同内容的图片上传到您的应用程序。你想自动找到猫图片。

        您的团队通过从不同网站下载猫(正样本)和非猫(负样本)的图片获得大量训练集。他们将数据集70%/ 30%分成训练和测试集。使用这些数据,他们构建了一个可在训练和测试集上运行良好的猫探测器。

      但是当您将此分类器部署到移动应用程序中时,您会发现性能非常差!

      您发现用户上传的图片与构成您的训练集的网站图片的外观不同:用户正在上传使用手机拍摄的照片,这些照片往往分辨率较低,模糊不清,光线不足。由于您的训练/测试集是由网站图像组成的,因此您的算法并不能很好地概括您所关注的实际分布:手机图片。

        在大数据的现代时代之前,机器学习中的常见规则是使用随机的70%/ 30%分割来形成训练和测试集。这种做法可行,但是在越来越多的应用程序中,这是一个坏主意,其中培训分发(上面示例中的网站图像)与您最终关注的分发(手机图像)不同。

    我们通常定义:

•训练集 - 您运行学习算法。 

•开发(开发)集 - 用于调整参数,选择要素以及做出有关学习算法的其他决策。有时也称为保持交叉验证集。

 •测试集 - 用于评估算法的性能,但不用于决定使用哪种学习算法或参数。

        一旦定义了开发集(开发集)和测试集,您的团队就会尝试很多想法,例如不同的学习算法参数,以查看最有效的方法。开发和测试集允许您的团队快速查看算法的运行情况。

        换句话说,开发和测试集的目的是指导您的团队完成对机器学习系统所做的最重要的更改。

        因此,您应该执行以下操作:选择开发和测试集以反映您希望将来获得的数据,并希望做得好。换句话说,您的测试集不应该只是可用数据的30%,特别是如果您希望未来的数据(手机图像)与训练集(网站图像)的性质不同。

        如果您尚未启动移动应用,则可能还没有任何用户,因此可能无法获得准确反映您将来要做的事情的数据。但你可能仍然试图近似模拟这种情况。例如,请您的朋友拍摄猫的手机照片并发送给您。启动应用程序后,您可以使用实际用户数据更新您的开发/测试集。

        如果您真的没有任何方法可以获得接近您期望获得的数据,也许您可​​以从使用网站图像开始。但是你应该意识到这种风险会导致系统不能很好地概括(和预期不一致)。

        它需要判断决定对开发集和测试集的投资程度。但是,不要假设您的培训分布与您的测试分发相同。

        尝试选择反映您最终想要表现的内容的测试示例,而不是您碰巧用于培训的任何数据。



六、您的开发和测试集应该来自相同的样本集分配


        根据您最大的市场,您的猫应用程序图像数据分为四个区域:(i)美国,(ii)中国,(iii)印度,以及(iv)其他。组成开发集合测试集,比如我们把美国和印度放在开发集中;中国和其他国家在测试集。换句话说,我们可以随机将其中的两个分配给开发集,另外两个分配给测试集,对吗?

        定义开发和测试集后,您的团队将专注于提高开发集性能。因此,开发集应该反映出你想要最大限度地改进的任务:要在所有四个地理位置上做得好,而不仅仅是两个。

        第二个具有不同分配的开发集和测试集导致的问题:您的团队有可能构建在开发集上运行良好的东西,但却发现它在测试集上表现不佳。我看到这个结果非常沮丧和浪费精力。避免让这件事发生在你身上。

        例如,假设您的团队开发了一个在开发集上运行良好但在测试集上运行不好的系统。如果您的开发集和测试集样本数据来自同一区域的样本数据,那么您可以非常清楚地确定出现了什么问题:您已经过度设置了开发集。显而易见的解决方法是获得更多开发集数据。

    但是如果开发集和测试集样本数据来自不同的区域,那么你的选择就不那么明确了。有些事情可能会出错:

    1.你的算法对开发集过度拟合了。 

    2.测试集比开发集更难。因此,您的算法可能会像预期的那样做得很好,并且不可能进一步显着改进。

    3.测试集不一定比开发集更难,但也不一样。那么在开发集(dev set)上运行良好的方法在测试集(test set)上效果不佳。在这种情况下,您为改善开发集性能所做的大量工作可能会浪费精力。

        研究机器学习应用程序已经足够困难了。具有不匹配的开发集和测试集,对是改进开发集性能还是改善测试集的性能带来了额外的不确定性。由于开发集(dev set)和测试集不匹配,因此很难弄清楚什么是有效的,哪些无效,从而使得优先处理工作变得更加困难

        如果您正在处理第三种情况的问题,他们的创建者可能已指定来自不同样本区域的开发集和测试集。与开发集和测试集来自样相同本区域的情况相比,运气而非技能会对算法性能产生更大的影响。开发学习算法是一个重要的研究问题,这些算法在一个样本区域训练并且很好地对另一个样本区域的概括。但是,如果您的目标是在特定的机器学习应用程序上取得进展而不是进行研究进展,我建议您尝试选择从样本区域中提取的开发和测试集。这将使您的团队更有效率。

七、开发/测试集需要多大?

        发集应足够大,以检测您正在尝试的算法之间的差异。例如,如果分类器A的准确度为90.0%,分类器B的准确度为90.1%,那么100个示例的开发设置将无法检测到这0.1%的差异。与我见过的其他机器学习问题相比,100个示例开发设置很小。大小从1,000到10,000的开发示例很常见。有10,000个例子,你很有可能发现0.1%的改善。

        对于成熟和重要的应用程序 - 例如,广告,网络搜索和产品推荐 - 我也看到团队的对提高0.01%正确率又很大的积极性,因为它对公司的利润有直接影响。在这种情况下,开发设置可能远大于10,000,以便检测甚至更小的改进。

        测试集的大小如何?它应该足够大,以便对系统的整体性能给予高度信任。一种流行的启发式方法是将30%的数据用于测试集。当你有一些适当数据量的例子时,这很好用 - 例如100到10,000个例子。但是在大数据时代,我们现在有机器学习问题,有时超过十亿个例子,分配给开发/测试集的数据的比例一直在缩小,但是开发集测试集的数据量也是一直在成长。除了评估算法性能所需的开发/测试集之外,不需要过多的开发/测试集。

八、为您的团队建立单数评估指标以进行优化

        分类准确性是单数评估度量的一个示例:您在开发集(或测试集)上运行分类器,并返回一个单独的数字,表示它正确分类的示例的分数。根据该值度量,如果分类器A获得97%的准确度,并且分类器B获得90%的准确度,则我们判断分类器A是优越的。

        相比之下,Precision和Recall不是单数评估指标:它为评估您的分类器提供了两个3数字。拥有多个数字评估指标会使比较算法变得更加困难。假设您的算法执行如下:

(有关准确率(Accuracy),精确率(Precision),召回率(Recall)和F1-Measure。https://www.cnblogs.com/sddai/p/5696870.html


        在这里,两个分类器都没有明显的优势,所以它不会立即引导你选择一个。


        在开发过程中,您的团队将尝试大量有关算法架构,模型参数,功能选择等的想法。拥有单数评估指标(如准确性)允许您根据其在此指标上的表现对所有模型进行排序,以及快速决定什么是最好的。

        如果你真的关心Precision和Recall,我建议使用一种标准方法将它们组合成一个数字例如,可以采用精确度和召回率的平均值,最终得到一个数字。或者,您可以计算“F1score”,这是一种计算平均值的修改方式,并且比简单地采用均值更好。


        当您在大量分类器中进行选择时,使用单数评估指标可以加快您做出决策的能力。它在所有这些中给出了明确的偏好排名,因此明确了进展的方向。

        作为最后一个例子,假设您在四个主要市场中分别跟踪猫分类器的准确性:(i)美国,(ii)中国,(iii)印度,以及(iv)其他。这给出了四个指标。通过获取这四个数字的平均值或加权平均值,您最终得到一个数字指标。采用平均或加权平均值是将多个指标合并为一个的最常见方法之一。

九、优化和满足指标

        这是组合多个评估指标的另一种方法。

        假设您关心学习算法的准确性和运行时间。您需要从以下三个分类器中进行选择:


        通过将准确性和运行时间放入单个公式来推导单个度量似乎不自然,例如:

                            Accuracy - 0.5 * RunningTime

        以下是您可以做的事情:首先,定义什么是“可接受的”运行时间。让我们说任何在100毫秒运行的东西都是可以接受的。然后,根据您的分类器满足运行时间标准,最大限度地提高准确性。在这里,运行时间是一个“令人满意的指标” - 您的分类器必须在此指标上“足够好”,因为它应该最多需要100毫秒。准确性是“优化指标”。

        如果您正在处理N个不同的标准,例如模型的二进制文件大小(这对于移动应用程序很重要,因为用户不想下载大型应用程序),运行时间和准确性,您可以考虑设置N-1标准为“令人满意”的指标。即,你只需要它们满足一定的价值。然后将最后一个定义为“优化”度量。例如,为二进制文件大小和运行时间可接受的值设置阈值,并尝试在给定这些约束的情况下优化准确性。

        作为最后一个示例,假设您正在构建一个硬件设备,该设备使用麦克风来监听用户说出特定的“唤醒词”,然后唤醒系统。

        例子包括Amazon Echo收听“Alexa”; Apple Siri正在收听“Hey Siri”; Android正在收听“Okay Google”;和百度应用程序听“你好百度。”你关心的是误报率 - 系统醒来的频率,即使没有人说出唤醒词 - 以及假阴性率 - 它经常无法唤醒当有人说出唤醒词。该系统性能的一个合理目标是最小化假阴性率(优化度量),每24小时操作(满足度量)不超过一个误报。

        一旦您的团队与评估指标保持一致以进行优化,他们就能够更快地取得进展。

十、具有开发集和度量标准可加快迭代速度


        事先很难知道哪种方法最适合新问题。即使是经验丰富的机器学习研究人员,在发现令人满意的事情之前,通常会尝试许多想法。在构建机器学习系统时,我经常会:

        1.首先了解如何构建系统。

        2.在代码中实现这个想法。

         3.进行一项实验,告诉我这个想法有多好。 (通常我的前几个想法不起作用!)基于这些学习,回过头来产生更多的想法,并继续迭代。


        这是一个迭代过程。围绕这个循环越快,你进步的速度就越快。这就是为什么拥有开发/测试集和度量标准很重要的原因:每次尝试一个想法时,在开发集上测量你的想法的性能可以让你快速决定你是否朝着正确的方向前进。

        相反,假设您没有特定的开发集和指标。因此,每当您的团队开发新的猫分类器时,您必须将其合并到您的应用程序中,并使用该应用程序几个小时,以了解新分类器是否是一项改进。这将非常慢!此外,如果您的团队将分类器的准确度从95.0%提高到95.1%,您可能无法检测到使用该应用程序的效率提高了0.1%。然而,通过逐渐累积数十个0.1%的改进,您的系统将取得很多进展。拥有开发集和指标可以让您快速检测哪些想法成功地为您提供了小的(或大的)改进,因此可以让您快速决定要改进哪些想法以及丢弃哪些想法。

十一、何时更改开发/测试集和指标

        在开始新项目时,我尝试快速选择开发/测试集,因为这为团队提供了明确定义的目标。

        我通常会要求我的团队在不到一周的时间内提出初始开发集/测试集和初始指标 - 很少。最好是想出一些不完美的东西并快速前进,而不是过度思考。但这一周的时间表不适用于成熟的应用程序。例如,反垃圾邮件是一种成熟的深度学习应用程序。我已经看到在已经成熟的系统上工作的团队花费数月时间来获得更好的开发/测试集。

        如果您后来意识到您的初始开发集/测试集或度量标准错过了标记,则无论如何都要快速更改它们。例如,如果您的开发集+指标将分类器A排在分类器B之上,但您的团队认为分类器B实际上对您的产品更优越,那么这可能表示您需要更改您的开发/测试集或评估指标。

        设置开发集/度量标准,错误地将分类器A的评级排名设置较高有三个主要可能原因:

1.您需要做的实际分配与开发/测试集不同。

        假设您的初始开发集(dev set)/测试集(test set)主要是成年猫的照片。您运行您的检测猫的应用程序,并发现用户正在上传的小猫图像比预期要多。因此,开发集(dev set)/测试集(test set)的样本分布对实际样本分布没有很好的代表性。 在这种情况下,请更新您的开发集(dev set)/测试集(test set)以使其更具代表性。

2.您的算法对DEV集过度拟合。

        在开发集上重复评估的处理会导致您的算法“过度拟合”到开发集。 完成开发后,您将在测试集上评估您的系统。 如果您发现您的算法在开发集(dev set)上的性能远远优于在测试集性能,则表明您的算法已经对开发集(dev set)过度拟合了。 在这种情况下,获得一个新开发集(dev set)。

        如果您需要跟踪团队的进度,您还可以在测试集上定期评估您的系统 - 例如每周一次或每月一次 。 但是,不要根据测试集做出有关算法的任何决定,包括是否回滚到前一周的系统。 如果你这样做,你将开始过度拟合测试集(test set),并且不再指望它对你的系统性能进行完全无偏见的评估(如果你发表研究论文,或者你可能需要使用这个指标 做出重要的商品决定)。

3.该指标衡量的是项目需要优化的内容。

        假设对于您的cat检测应用程序,您的度量标准是分类准确性。 该度量标准将分类器A排序优于分类器B.但是假设您尝试了两种算法,并且发现分类器A允许偶尔的色情图像通过。 即使分类器A更准确,偶尔的色情图片留下的坏印象也意味着它的表现是不可接受的。 你该做什么?

        在这里,对于您的产品,度量标准未能确定算法B比算法A更好的事实。 因此,您无法再信任该指标来选择最佳算法。 是时候改变评估指标了。 例如,您可以更改指标,严重惩罚通过色情图片。 我强烈建议选择一个新指标并使用新指标明确定义团队的新目标,而不是在没有可信指标的情况下继续进行太长时间并且还原为在分类器之间手动选择。

        在项目期间,更改开发集(dev set)/测试集(test set)或评估指标(metrics)是很常见的。 拥有初始开发集(dev set)/测试集(test set)或评估指标(metrics)可帮助您快速迭代。 如果您发现开发集(dev set)/测试集(test set)或评估指标(metrics)不再帮助您的团队指定正确的方向,那就没什么大不了的! 只需更改它们,确保您的团队了解新方向。

12.小贴士:建立发展和测试集


       • 从样本分布中选择开发集(dev set)/测试集(test set),该样本分布反映了您希望将来获得的数据,并希望做得好。 这可能与您的训练数据分布不同。

        •尽可能在同样的样本内分布中选择开发集(dev set)和测试集(test set)。

         •为您的团队选择一个单一的评估指标进行优化。 如果您关注多个目标,请考虑将它们合并到一个公式中(例如平均多个错误指标)或定义满意度和优化指标。

        •机器学习是一个高度迭代的过程:在找到一个你满意的想法之前,你可能要尝试许多想法。

        •拥有开发集(dev set)和测试集(test set)单个的评估指标可帮助您快速评估算法,从而更快地迭代。

        •在开始使用全新的应用程序时,请尝试快速建立开发集(dev set)和测试集(test set)评估指标,比如说不到一周。 在成熟的应用程序上花费更长时间可能是可以的。

        •70%/ 30%的开发集(dev set)和测试集(test set)不适用于您拥有大量数据的问题; 开发集(dev set)和测试集(test set)可以远低于数据的30%。

        •您的开发集应该足够大,在准确性情况下,以检测算法的有意义变化,但不一定要大得多。 您的测试集应该足够大,以便您对系统的最终性能有一个可靠的估计。

        •如果您的开发集(dev set)评估指标不再为您的团队指定正确的方向,请快速更改它们:(i)如果您过度拟合了开发集(dev set),请获取更多开发集(dev set)数据。 (ii)如果您关心的实际样本分布开发集(dev set)和测试集(test set)样本分布不同,请获取新的开发集(dev set)和测试集(test set)数据。 (iii)如果您的评估指标不再衡量对您最重要的指标,请更改评估指标



                                                            基本错误分析

13.快速构建您的第一个系统,然后迭代.

        您想构建一个新的电子邮件反垃圾邮件系统。 您的团队有几个想法:

        •收集大量垃圾邮件培训。 例如,设置一个“蜜罐”:故意向已知的垃圾邮件发送者发送虚假的电子邮件地址,以便您可以自动收获他们发送到这些地址的垃圾邮件。

        •开发用于理解电子邮件文本内容的功能。

        •开发用于理解电子邮件信封/标题功能的功能,以显示消息所经历的Internet服务器集。

        • 和更多。

        即使我在反垃圾邮件方面做了大量工作,我仍然很难选择其中一个方向。 如果您不是应用领域的专家,那就更难了。

        因此,不要试图设计和构建完美的系统。 相反,可以在短短几天内快速构建和培训基本系统。 即使基本系统远离您可以构建“的最佳”的5个系统,检查基本系统如何运作也很有价值:您将很快找到线索,向您展示投入时间的最有希望的方向。 接下来的几章将向您展示如何阅读这些线索。

14.错误分析:查看开发设置示例以评估想法


        当你玩你的猫应用程序时,你会注意到几个例子,它会误认为猫的狗。有些狗看起来像猫!

        团队成员建议合并第三方软件,使系统在狗图像上做得更好。这些变化需要一个月的时间,团队成员也很热情。你应该让他们继续吗?

        在为这项任务投入一个月之前,我建议您首先估计它​​实际上会提高系统准确性的程度。然后你可以更合理地决定这是否值得花数月的开发时间,或者利用同样的时间,你能否在其他任务发挥更大的效益。

        详细说明,这是你可以做的:

        1.收集系统错误分类的100个开发示例示例。即,您的系统出错的示例。

        2.手动查看这些示例,并计算它们中的哪一部分是狗图像。

        查看错误分类示例的过程称为错误分析。在这个例子中,如果您发现只有5%的错误分类图像是狗,无论您在狗图像上提高多少算法的性能,您都不会摆脱超过5%的错误。换句话说,5%是拟议项目可以提供多少帮助的“上限”(意味着最大可能数量)。因此,如果您的整个系统目前90%准确率(10%错误率),这种改进可能最多导致90.5%的准确率(或9.5%的误差率,误差比原始10%误差少0.5%)。

        相反,如果你发现50%的错误都是狗,那么你可以更加确信对项目会产生很大的影响。 它可以将准确度从90%提高到95%(误差相对减少50%,从10%降低到5%)。

        这种简单的错误分析计数程序为您提供了一种快速估算将第三方软件纳入狗图像的可能价值的方法。 它为决定是否进行此项投资提供了定量依据。

        错误分析通常可以帮助您弄清楚不同方向的前景。 我见过很多工程师都不愿意进行错误分析。 只是跳进去实施一些想法通常会感觉更令人兴奋,而不是质疑这个想法是否值得投入时间。这是一个常见的错误:这可能会导致你的团队花一个月的时间才意识到它后来导致了一点点效益。

         手动检查100个示例并不需要很长时间。 即使你每张图片需要一分钟,你也可以在两小时内完成。 这两个小时可以为你节省一个月的精力。

         错误分析是指检查错误的您的分类算法开发集(dev set)错误的过程,以便您可以了解错误的根本原因。 这可以帮助您确定项目的优先级 - 如本例所示 - 并启发新的方向,我们将在下面讨论。 接下来的几章还将介绍进行错误分析的最佳实践。


15.在错误分析期间并行评估多个想法

        您的团队有几个改进猫探测器的想法:

        •修复算法将狗识别为猫的问题。

        •修复算法识别猫(狮子,黑豹等)作为家猫(宠物)的问题。

        •提高系统在模糊图像上的性能。

        •......

        您可以并行地有效地评估所有这些想法。 我通常会在查看~100个错误分类开发集(dev set)图像时,创建一个电子表格并填写它。 我还记下了可能有助于我记住具体例子的评论。 为了说明这个过程,让我们看一下你可能用一个小的开发集(dev set)开发的四个例子生成的电子表格:

        上面的第三个image同时检查了Great Cat和Blurry列。 此外,因为一个示例可能与多个类别相关联,所以底部的百分比可能不等于100%。

        虽然您可能首先制定类别(狗,大猫,模糊),然后手动对示例进行分类,在实践中,一旦您开始查看示例,您可能会受到启发,提出新的错误类别。 例如,假设你经历了十几张图片,并意识到Instagram过滤后的图片会出现很多错误。 您可以返回并在电子表格中添加新的“Instagram”列。 手动查看算法错误分类。并询问您作为人类如何/是否可以正确标记图片的示例,通常会激发您提出新的错误类别和解决方案。

        最有用的错误类别是您有改进意见的错误类别。 例如,如果您想要“撤消”Instagram过滤器并恢复原始图像,那么Instagram类别将最有助于添加。 但是,您不必仅限于您知道如何改进的错误类别; 这个过程的目标是建立你对最有希望关注的领域的直觉。

        错误分析是一个迭代过程。 如果您没有考虑类别,请不要担心。在查看几个图像之后,您可能会想出一些关于错误类别的想法。在手动对某些图像进行分类后,您可能会想到新的类别并重新检查 根据新类别的图像,等等。

        假设您完成了对100个错误分类的开发集进行错误分析并获得以下内容:


        您现在知道,处理Dog错误的项目可以最多消除8%的错误。 处理Great Cat或Blurry图像错误有助于消除更多错误。 因此,您可以选择后两个类别中的一个来关注。 如果您的团队有足够的人员同时追求多个方向,您也可以让一些工程师与Great Cats和其他人一起工作来处理模糊图像。

        错误分析不会产生严格的数学公式,告诉您最高优先级的任务应该是什么。 您还必须考虑到您希望在不同类别上取得多少进展以及解决每个类别所需的工作量。

16.清理开发集和测试集中错误标记的样本

        在错误分析过程中,您可能会注意到开发集中的一些示例被错误标记。当我在这里说“错误标记”时,我的意思是即使在算法遇到它之前,图片也已经被人类贴标机贴错了标签。 即,示例(x,y)中的类标签具有y的值不正确。 例如,也许一些不是猫的图片被错误标记仅仅因为包含猫,反之亦然。 如果您怀疑错误标记图像的分数很重要,请添加一个类别以跟踪错误标记的示例部分:


        你应该更正开发套装中的标签吗? 请记住,开发集(dev set)的目标是帮助您快速评估算法,以便您可以判断算法A和算法B哪个更好。 如果设置错误标记的开发集(dev set)阻碍了您做出这些判断的能力,那么值得花些时间来修复开发集(dev set)的错误标签。

        例如,假设您的分类器的性能是:

        •开发集(dev set)的总体准确度.................. 90%(总体错误率为10%)

        •错误标记的例子导致的错误....... 0.6%(开发集的错误率6%)

        •由于其他原因导致的错误..................... 9.4%(设置错误的94%)

        在这里,由于错误标记导致的0.6%不准确性可能不够显着,相对于您可能改进的9.4%的错误。 手动修复设备中错误标记的图像没有什么害处,但这样做并不重要:可能没问题,您的系统是否有10%或9.4%的总体错误。

        假设您不断改进cat分类器并达到以下性能:

        •开发集的总体准确度.................. 98.0%(总体错误率2.0%)

        •错误标记的例子导致的错误.......0.6%。 (开发集错误的30%。)

        •由于其他原因导致的错误..................... 1.4%(开发集错误的70%)

        开发集中,30%的错误是由于错误标记的图像造成的,这会对您的准确度估计值产生重大误差。 现在值得提高开发集标签的质量。处理错误标记的示例将帮助您确定分类器的误差接近1.4%或2% - 显着的相对差异。

        开始容忍一些错误标记的开发/测试集示例并不常见,只是稍后在系统改进时改变主意,以便错误标记的示例的比例相对于总错误集增加。

        最后一章解释了如何通过算法改进来改进Dog,Great Cat和Blurry等错误类别。 您已经在本章中了解到,您可以通过改进数据的标签来处理错误标记的类别。

        无论您对开发集标签应用什么处理过程,请记住,将其同样应用于测试集标签,以便保证您的开发和测试集是从同一样本分布中提取的。将您的开发集和测试集放在一起处理,可以防止我们在第6章讨论的问题 ,您的团队仅仅优化开发集性能,导致稍后实现基于不同测试集的不同标准。

        如果您决定提高标签质量,请考虑仔细检查系统错误分类的示例标签以及正确分类的示例标签。 在一个例子中,原始标签和学习算法都可能是错误的。 如果仅修复系统错误分类的示例标签,则可能会在评估中引入偏差。 如果您有1,000个开发集示例,并且如果您的分类器具有98.0%的准确度,则更容易检查错误分类的20个示例,而不是检查所有正确分类的980个示例。 因为在实践中更容易检查错误分类的示例,所以偏差会蔓延到某些开发集中。 如果您只对开发产品或应用程序感兴趣,这种偏见是可以接受的,但如果您计划在学术研究论文中使用结果或需要完全无偏见的测试集准确度测量,那么这将是一个问题。


17.如果您有一个大型开发集,一分为二,只查看一个

        假设您有一个包含5,000个示例的大型开发集(dev set),其中您的错误率为20%。因此,您的算法错误地分类了1,000个开发集图像。 手动检查1,000张图像需要很长时间,因此我们可能决定在错误分析中不使用所有图像。

        在这种情况下,我会明确地将开发集拆分为两个子集,其中一个是您看到的,另一个是您不看的。 您将更快速地过度配合您手动查看的部分。 您可以使用未手动查看的部分来调整参数。

        让我们继续上面的例子,其中算法错误地分类了5,000个开发示例中的1,000个。 假设我们想要手动检查大约100个错误以进行错误分析(10%的错误)。 你应该随机选择开发集中的10%并将其放入我们称之为Eyeball dev set文件,以提醒自己我们正用眼睛看着它。 (对于有关语音识别的项目,您可能会在其中收听音频剪辑,或许您会将此设置称为Ear dev set)。 因此,Eyeball dev set有500个例子,我们希望我们的算法可以错误地分类出100个。

        开发集的第二个子集,称为Blackbox开发集,将包含剩余的4500个示例。 您可以使用Blackbox dev set通过测量错误率来自动评估分类器。 您还可以使用它来选择算法或调整超参数。 但是,你应该避免用眼睛看它。 我们使用术语“Blackbox”,因为我们只使用这个数据子集来获得分类器的“Blackbox”评估。

        为什么我们明确地将开发集分为Eyeball和Blackbox开发集? 由于您将获得关于Eyeball开发集中的示例的直觉,您将开始更快地过度拟合Eyeball开发集。 如果你看到Eyeball开发集的性能提升比Blackbox开发集的性能提升得快得多,你就会过度使用Eyeball开发集。在这种情况下,你可能需要丢弃它,并从Blackbox dev set找到一个新的样本放在Eyeball开发集或者通过获取新的标记数据。

        将您的开发集明确拆分为Eyeball和Blackbox开发集,可让您了解手动错误分析过程,何时导致您过度拟合Eyeball集。

18.Eyeball和Blackbox开发集应该有多大?


        您的Eyeball开发集应该足够大,以便您了解算法的主要错误类别。如果你正在做一项人类做得好的任务(比如识别图像中的猫),这里有一些简单的指导方针:

       • 一个开发集中,你的分类器犯10个错误将一般认为是非常小的。只有10个错误,很难准确估计不同错误类别产生的影响。但是如果你的数据非常少而且把更多的数据添加到Eyeball集,那么它总比没有好,并且有助于项目优先排序。

       • 如果你的分类器在Eyeball集中犯了大约20个错误,你就会开始大致了解主要的错误来源。

       • 有大约50个错误,你会很好地理解主要的错误来源。

        •如果出现大约100个错误,您将非常了解错误的主要来源。我看到人们手动分析更多的错误 - 有时甚至多达500个。只要你有足够的数据,就没有任何害处。

        假设您的分类器的错误率为5%。为了确保在Eyeball集中有大约100个错误标记的例子,Eyeball开发套装必须有大约2,000个例子(因为0.05 * 2,000 = 100)。分类器的错误率越低,您的Eyeball集需要越大,以便分析足够大的错误集。

        如果你正在处理甚至人类都做不好的任务,那么检查一个Eyeball集的练习将没有那么有用,因为很难弄清楚为什么算法没有正确地对一个例子进行分类。在这种情况下,您可能会省略设置Eyeball开发。我们将在后面的章节中讨论这些问题的指导原则。

        Blackbox dev设置如何?我们之前曾说过大约1,000-10,000个示例的开发常见。为了优化该语句,Blackbox dev设置1,000-10,000个示例通常会为您提供足够的数据来调整超参数并在模型中进行选择,尽管获得更多数据几乎没有什么害处。 Blackbox dev设置为100,虽然很小但仍然有用。

        如果你有一个小的开发集,那么你可能没有足够的数据可以分成Eyeball和Blackbox开发集,并且保证这些开发集都足够大,可以满足他们的目的。相反,您的整个开发集可能必须用作Eyeball集 - 即,您将手动检查所有开发集数据。

        在Eyeball集和Blackbox集之间,我认为Eyeball集更重要(假设您正在解决人类可以很好地解决的问题,并且检查示例可以帮助您获得洞察力)。如果您只设置了Eyeball集,则可以在该组上执行错误分析,模型选择和超参数调整。仅设置Eyeball集的缺点是过度拟合开发集的风险更大。

        如果您有足够的数据访问权限,那么Eyeball开发集的大小主要取决于您有多少时间手动分析。 例如,我很少见到有人手动分析超过1,000个错误。

19.小贴士:基本的错误分析


        •当您开始一个新项目时,特别是如果它不是您擅长的区域,很难正确地猜出最有希望的方向。

        •所以不要试图设计和构建完美的系统。 而是尽可能快地建立和训练基本系统 - 也许在几天之内。 然后使用错误分析来帮助您识别最有希望的方向,并从那里迭代地改进您的算法。

        •通过手动检查100 dev set样本进行错误分析,算法错误分类并计算主要错误类别。 使用此信息可以确定要修复的错误类型的优先级。

        •考虑将开发集拆分为您将手动检查的Eyeball开发集和Blackbox开发套件,您将不用手动检查。 如果Eyeball开发集的性能远远优于Blackbox开发集,那么你已经过度拟合了Eyeball集,应考虑为其获取更多数据。

        •Eyeball开发设置应该足够大,以便您的算法错误分类足够的示例供您分析。 对于许多应用程序,Blackbox dev设置为1,000-10,000个就足够了。

        •如果您的开发集不够大,无法通过这种方式进行拆分,只需使用Eyeball集进行手动错误分析,模型选择和超参数调整。

20.偏见和方差:两大来源错误

        假设您训练的开发集和测试集都来自同一个样本区域。 那么你应该总是尝试获得更多的训练数据,因为这只会提高性能,对吧?

        即使拥有更多数据也不会有什么不好的,但不幸的是,它并不总是像您希望的那样有用。 获取更多数据可能是浪费时间。 那么,您如何决定何时添加数据,何时不用呢?

        机器学习中存在两个主要的误差来源:偏差和方差。 了解它们将帮助您确定是否添加数据,以及其他提高性能的策略,是否能充分利用时间。

        假设您希望构建一个误差为5%的猫识别器。 现在,您的训练集的错误率为15%,您的开发集的错误率为16%。 在这种情况下,添加训练数据可能无济于事。 您应该专注于其他更改。 实际上,在训练集中添加更多示例只会使您的算法更难以在训练集上取得好成绩。 (我们将在后面的章节解释原因。)

        如果训练集上的错误率为15%(或准确度为85%),但目标误差为5%(准确率为95%),那么要解决的第一个问题是提高算法在训练集上的性能。 您的开发/测试集性能通常比训练集性能差。 因此,如果您在算法所见的示例上获得85%的准确率,那么您在算法甚至没有看到的示例上无法获得95%的准确率。

        假设如上所述,您的算法在开发集上有16%的误差(84%准确度)。 我们将16%的错误分解为两个组件:

        •首先,算法在训练集上的错误率。 在这个例子中,它是15%。 我们非正式地将此视为算法的偏见。

        •其次,算法在开发(或测试)集上比训练集更糟糕。在这个例子中,它在开发集上比训练集差1%。 我们非正式地将此视为算法的方差。

        对学习算法的一些更改可以解决错误偏差的第一个组成部分,并提高其在训练集上的性能。 一些更改解决了第二个组件 - 方差 - 并帮助它从训练集到开发/测试集更好地概括。 要选择最有希望的变化,理解2这两个错误组成部分中哪一个更难以解决是非常有用的。

        培养关于偏差和方差的良好直觉将帮助您为算法选择有效的变化。

21.偏差和方差的例子

        考虑我们的猫分类任务。 “理想”分类器(例如人类)可能在此任务中实现近乎完美的性能。

        假设您的算法执行如下:

        •训练集误差= 1%

        •开发集错误= 11%

        它有什么问题?应用前一章的定义,我们估计偏差为1%,方差为10%(= 11%-1%)。因此,它具有很大的差异。分类器具有非常低的训 练错误,分类器无法概括为开发集。这也称为过度拟合。

        现在考虑一下:

        •训练集误差= 15%

        •开发集错误= 16%

        我们估计偏差为15%,方差为1%。这个分类器对训练集的拟合很差,误差为15%,但它在开发集上的误差几乎不高于训练误差。因此,该分类器具有高偏差,但方差低。我们说这个算法是不合适的。

        现在,考虑一下:

        •训练集误差= 15%

        •开发集错误= 30%

        我们估计偏差为15%,方差为15%。该分类器具有高偏差和高方差:它在训练集上表现不佳,因此具有高偏差,并且其在开发集上的性能更差,因此它也具有高方差。该由于分类器的原因,过度拟合/欠配合术语很难应用于此同时过度拟合和欠拟合。

        最后,考虑一下:

        •训练集误差= 0.5%

        •开发集错误= 1%

        该分类器表现良好,因为它具有低偏差和低方差。 祝贺实现这个伟大的表现!

22.比较最佳错误率

        在我们的猫识别示例中,“理想”错误率 - 即“最佳”分类器可实现的错误率 - 几乎为0%。 看着图片的人几乎可以一直识别它是否包含一只猫; 因此,我们可以希望一台能做得同样的机器。

        其他问题更难。 例如,假设您正在构建一个语音识别系统,并发现14%的音频片段具有如此多的背景噪音或者是如此难以理解,即使是人类也无法识别所说的内容。 在这种情况下,即使是最“最佳”的语音识别系统也可能有大约14%的误差。

        假设在这个语音识别问题上,您的算法实现了:

        •训练集误差= 15%

        •开发集错误= 30%

        训练集的性能已经接近14%的最佳错误率。 因此,在偏差方面训算法练集性能方面没有太大的改进空间。但是,该算法并没有很好地推广到开发集; 因此,由于方差导致的误差存在,该算法还有很大改进空间。

        这个例子类似于前一章的第三个例子,它的训练误差为15%,dev误差为30%。 如果最佳错误率为0%,那么15%的训练误差留下了很大的改进空间。 这表明减少偏差可能是富有成效的。 但如果最佳错误率为14%,则相同的训练集性能告诉我们,分类器的偏差几乎没有改进的余地。

        对于最佳错误率远为零的问题,这里是算法错误的更详细分类。 继续上面的语音识别示例,30%的总设置错误可以分解如下(类似的分析可以应用于测试集错误):

        •最佳错误率(“不可避免的偏差”):14%。 假设我们决定,即使世界上最好的语音系统,我们仍会遭受14%的错误。 我们可以将此视为学习算法偏差的“不可避免”部分。

        •可避免的偏见:1%。这是根据训练误差和训练误差之间的差异来计算的最优错误率

        •方差:15%。 dev集错误率和训练集错误率之间的区别。

        为了将其与我们之前的定义联系起来,偏差和可避免偏差的关系如下:

        偏差=最佳错误率(“不可避免的偏差”)+可避免的偏差

“       可避免的偏差”反映了您的算法在训练集上执行的程度而不是“最佳分类器”。

        方差的概念与以前一样。从理论上讲,我们总能减少通过大规模训练集的训练,方差几乎为零。因此,所有方差都是“可以避免的”

拥有足够大的数据集,所以没有“不可避免的差异”这样的东西。

        再考虑一个例子,最佳错误率为14%,我们有:

        •训练集误差= 15%

        •开发集错误= 16%

        在前一章中我们称之为高偏差分类器,现在我们可以这么说可避免偏差的误差为1%,方差误差约为1%。因此,算法已经做得很好,几乎没有改进的余地。它比最佳值差2%错误率。

        我们从这些例子中看到,了解最佳错误率有助于指导我们的下一步。在统计中,最佳错误率也称为贝叶斯错误率或贝叶斯率。

        我们如何知道最佳错误率是多少?对于人类相当不错的任务在识别图片或抄录音频片段时,您可以要求人提供然后标签测量人体标签相对于训练集的准确性。这个将给出最佳错误率的估计。如果你正在解决一个问题,甚至人类很难解决(例如,预测要推荐的电影或向用户展示的广告),很难估计最佳错误率。在“与人类绩效比较”一节(第33至35章) ),我将更详细地讨论将学习算法的性能与人类水平进行比较的过程性能。

        在最后几章中,您学习了如何估计可避免/不可避免的偏差和通过观察训练和开发设置错误率来实现差异。 下一章将讨论如何使用此类分析中的见解来优先考虑减少偏差的技术与减少差异的技术。 根据项目当前问题是高(可避免)偏差还是高差异,您应该应用非常不同的技术。 继续阅读!

23.解决偏见和差异

        这是解决偏差和方差问题的最简单公式。

        •如果您具有较高的可避免偏差,请增加模型的大小(例如,通过添加图层/神经元来增加神经网络的大小)。

        •如果您的方差很大,请将数据添加到训练集。

        如果您能够无限制地增加神经网络大小并增加训练数据,则可以在许多学习问题上做得很好。

        实际上,增加模型的大小最终会导致计算问题,因为训练非常大的模型很慢。 您也可能无法获得更多的培训数据。 (即使在互联网上,只有有限数量的猫图片!)

        不同的模型体系结构(例如,不同的神经网络体系结构)将针对您的问题具有不同的偏差/方差。 最近的许多深度学习研究已经开发出许多创新的模型架构。 因此,如果您使用神经网络,学术文献可以成为灵感的重要来源。 github上还有很多很棒的开源实现。 但是,尝试新架构的结果比增加模型大小和添加数据的简单公式更难以预测。

        增加模型尺寸通常会减少偏差,但也可能会增加方差和过度拟合的风险。 但是,这种过度拟合问题通常仅在您不使用正则化时出现。 如果您包含精心设计的正则化方法,那么通常可以安全地增加模型的大小而不会增加过度拟合。

        假设您正在应用具有L2正则化,其中正则化参数在开发集上表现最佳。 如果您增加模型大小,通常您的性能将保持不变或改善; 它不太可能显着恶化。避免使用更大模型的唯一原因是计算成本增加。

24.偏差与差异权衡


        你可能听说过“偏差与方差权衡”。你可以对大多数学习算法做出的改变,有一些可以减少偏差,但代价是增加方差,反之亦然。 这在偏差和方差之间产生了“折衷”。

        例如,在神经网络中增加模型、添加神经元/层的大小,或添加输入特征 - 通常会减少偏差,但可能会增加方差。 或者,添加正则化通常会增加偏差但会减少方差。

        在现代,我们经常可以访问大量数据,并且可以使用非常大的神经网络(深度学习)。 因此,有较少的权衡,现在有更多的选择来减少偏差而不会损害方差,反之亦然。

        例如,您通常可以增加神经网络大小并调整正则化方法以减少偏差而不会显着增加方差。 通过添加训练数据,您通常还可以在不影响偏差的情况下减少方差。

        如果选择适合您任务的模型体系结构,则还可以同时减少偏差和方差。 选择这样的架构可能很困难。

        在接下来的几章中,我们将讨论用于解决偏差和方差的其他特定技术。

25.减少可避免偏差的技术

        如果您的学习算法存在高度可避免的偏差,您可以尝试以下方法技巧:

        •增加模型大小(例如神经元/层数):这种技术可以减少偏差,因为它可以让您更好地适应训练集。如果您发现这会增加方差,则使用正则化,这通常会消除方差的增加。

        •根据错误分析的见解修改输入特征:假设您的错误分析激发您创建其他功能,帮助算法消除特定类别的错误。 (我们将在下一章进一步讨论这个问题。)这些新功能可能有助于偏见和差异。理论上,添加更多功能可能会增加差异;但如果你发现这种情况,那就使用正则化,这通常会消除方差的增加。

        •减少或消除正则化(L2正则化,L1正则化,丢失):这将减少可避免的偏差,但会增加差异。

        •修改模型体系结构(例如神经网络体系结构)以使其更多适合您的问题:这种技术可以影响偏差和方差。

        一种无用的方法:

        •添加更多培训数据:此技术有助于解决方差问题,但通常也是如此对偏差没有显着影响。

26.训练集的误差分析


        您的算法必须在训练集上运行良好,才能期望它在开发/测试集上表现良好。

        除了前面描述的用于解决高偏差的技术之外,我有时还会根据类似于Eyeball开发集的错误分析的方法对训练数据进行错误分析。 如果您的算法具有高偏差,即如果它不能很好地拟合训练集,则这可能很有用。

        例如,假设您正在为应用程序构建语音识别系统,并从志愿者那里收集了一组音频剪辑。 如果您的系统在训练集上表现不佳,您可能会考虑收听一组约100个算法,这些算法很难理解训练集错误的主要类别。 与dev set error analysis类似,您可以计算不同类别的错误:


        在此示例中,您可能会发现您的算法在使用具有大量背景噪音的训练示例时会遇到特别困难。 因此,您可以专注于允许其更好地适应具有背景噪声的训练示例的技术。

        在给定与学习算法相同的输入音频的情况下,您还可以仔细检查一个人是否可以转录这些音频片段。 如果有太多的背景噪音,任何人都无法弄清楚所说的内容,那么期望任何算法正确识别这些话语可能是不合理的。 我们将在后面的部分讨论将算法与人类级别性能进行比较的好处。


27.减少方差的技术

        如果您的学习算法存在高方差,您可以尝试以下方法技巧:

        •添加更多训练数据:这是解决方差的最简单,最可靠的方法,只要您可以访问更多的数据和足够的计算能力来处理数据。

        •添加正则化(L2正则化,L1正则化,丢失):此技术可减少方差但增加偏差。

        •减少输入要素数量/类型的特征选择:此技术可能有助于解决方差问题,但也可能会增加偏差。稍微减少功能的数量(比如从1000个功能到900个)不太可能对偏差产生巨大影响。只要你没有排除太多有用的功能,减少它(例如从1000个功能减少到100个减少10倍)就更有可能产生重大影响。在现代深度学习中,当数据充足时,已经从特征选择中转移,现在我们更有可能将所有特征赋予算法,并让算法根据数据选择使用哪些特征。 。但是当您的训练集很小时,功能选择可能非常有用。

        •减小模型大小(例如神经元/层数):谨慎使用。该技术可以减少方差,同时可能增加偏差。但是,我不推荐这种技术来解决方差。添加正则化通常会提供更好的分类性能。减小模型尺寸的优势在于降低了计算成本,从而加快了训练模型的速度。如果加速模型训练是有用的,那么一定要考虑减小模型大小。但是如果你的目标是减少方差,并且你不关心计算成本,那么考虑添加正则化。

        以下是关于解决偏见的前一章重复的另外两种策略:

        •根据错误分析的见解修改输入功能:假设您的错误分析激发您创建其他功能,帮助算法消除特定类别的错误。这些新功能可能有助于偏见和差异。

        •理论上,添加更多功能可以增加方差; 但如果你发现这种情况,那就使用正则化,这通常会消除方差的增加。

        •修改模型体系结构(例如神经网络体系结构),使其更适合您的问题:此技术可以影响偏差和方差。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容