机器学习=人工智能?NoNoNo,看完这篇你就明白了!

一、什么是机器学习?

机器学习是人工智能领域的核心组成部分,它致力于开发能够从数据中自动学习并改进的算法模型。通过对历史数据进行分析、提取其中的模式和规律,机器学习算法能够构建预测模型,进而应用于对未知数据的预测、分类、聚类等任务。例如,支付宝“扫福字”功能背后,正是利用图像识别模型来识别福字图像;垃圾邮件过滤系统则是通过分析历史邮件数据,学习区分垃圾邮件与正常邮件的模式,从而实现自动分类。

机器学习就像教电脑从经验(数据)中学习,让它自己变得更聪明,能更好地解决问题。仅仅让电脑拥有大量的数据并不能让它自动变得更擅长任何任务,需要利用这些数据来训练一个算法,让它能够学习到特定的模式或规律,从而提升在特定任务上的表现。

机器学习系统中学习和预测的部分被称为模型

机器学习的发展历程:

  • 早期阶段(1950-1960年代): 这一时期,机器学习的研究主要集中在符号逻辑和简单的决策模型上。

  • 复兴期(1980年代): 反向传播算法的出现以及多层感知机(MLP)的发展,为神经网络的研究注入了新的活力,推动了神经网络的初步发展。

  • 现代阶段(21世纪后): 随着深度学习技术的兴起,特别是2012年AlexNet在图像识别领域取得的突破性进展,机器学习开始在更为复杂的任务中得到广泛应用,例如自然语言处理、自动驾驶等领域。

二、为什么要使用机器学习?

传统的编程方式,需要我们为每一个问题编写明确的规则,这在很多情况下变得异常复杂且难以维护。例如,假设我们需要创建一个可以自动识别猫狗图片的程序。

  1. 首先,需要仔细研究大量的猫和狗的照片,试图找出区分它们的特征。比如,猫的耳朵通常比狗的耳朵更尖,鼻子更短。
  2. 然后,编写代码,基于这些特征来判断图片中是猫还是狗。

在这里插入图片描述

这种方法会遇到很多问题。光是“尖耳朵”这个特征,不同品种的猫和狗差异就很大,使得代码变得冗长且容易出错。而且,如果图片拍摄角度不好,或者光线不足,程序就很难准确判断。

相比之下,使用机器学习方法,我们可以提供给算法大量的猫和狗的图片。
在这里插入图片描述

算法会自动分析这些图片,学习猫和狗的各种特征,并建立一个模型来区分它们。这个程序通常比传统方法更简洁,更容易维护,并且往往更准确。

更重要的是,机器学习具有适应性。假设我们发现算法经常把某种特定品种的狗误识别为猫。

  • 使用传统编程,我们需要手动修改代码,添加新的规则来处理这种特殊情况。
  • 而使用机器学习,我们只需要向算法提供更多这种狗的图片,让它重新学习并改进模型,无需人工干预。

在这里插入图片描述

机器学习的另一个优点是可以解决那些传统方法难以解决的问题,例如自动驾驶。 想要编写一个能应对各种复杂路况、行人、交通信号的自动驾驶程序,难度远超想象。 我们很难预先定义所有可能的场景和应对策略。 但是,通过机器学习,我们可以让汽车通过大量的实际驾驶数据进行学习,逐渐掌握驾驶技能,从而实现自动驾驶。

最后,机器学习还能帮助我们人类进行学习,并发现隐藏的模式

在这里插入图片描述

我们可以分析机器学习模型,了解它们是如何做出决策的,从而洞察之前未知的关联。 例如,训练了一个机器学习模型来预测房价。训练完成后,我们可以分析这个模型,找出哪些因素对房价的影响最大。也许我们发现,除了传统的房屋面积、地段等因素外,房屋的朝向(例如,朝南的房屋更受欢迎)对房价的影响也非常显著。

这种发现可能完全出乎意料,帮助我们更好地理解房地产市场。 甚至可以提醒我们之前忽略的影响房价的因素,例如房屋附近是否有公园,小区绿化率等等。

通过分析大量数据来发现隐藏模式的过程,被称为数据挖掘。 而机器学习正是进行数据挖掘的强大工具。 它可以帮助从海量数据中提取有价值的信息,从而更好地理解世界,做出更明智的决策。 机器学习模型发现的模式,有时甚至可以颠覆我们之前的认知,为我们打开新的研究方向。

总结一下,机器学习非常适合:

  • 需要大量人工调整或存在冗长规则的问题:机器学习模型通常可以通过自动学习模式来简化代码,并且在性能上超越传统的基于规则的方法。
  • 使用传统方法难以解决的复杂问题。
  • 当环境发生变化时,传统方法需要不断修改代码,而机器学习系统可以通过使用新的数据进行重新训练,来快速适应变化,保持最新的状态。
  • 从复杂的和大量的数据中提取隐藏的模式和关联。

三、机器学习系统类型

机器学习系统种类繁多,可以根据以下几个关键维度进行分类:

  • 训练方式:机器学习模型如何从数据中学习,包括监督学习(使用带有标签的数据)、无监督学习(使用无标签的数据)、半监督学习(同时使用有标签和无标签的数据)、自监督学习(从数据本身生成标签)以及强化学习等。

  • 学习方式:模型如何适应新数据,分为在线学习(可以逐步学习新数据)和批量学习(需要一次性处理所有数据)。

  • 泛化方式:模型如何进行预测,是基于实例学习(直接比较新数据与已知数据)还是基于模型学习(先构建模型,再用模型进行预测)。

这些分类标准并不是互斥的,可以灵活组合。 举个例子,一个现代化的信用卡欺诈检测系统可能就是一个基于模型的在线监督学习系统。 它利用带有标签的交易数据(标记为欺诈或非欺诈)来训练一个模型,并能够实时地更新模型,以适应不断变化的欺诈行为。

3.1、训练监督方式

机器学习系统可以根据训练过程中所获得的监督信息的多少和类型进行分类。 虽然类别繁多,但这里重点介绍以下几种主要的学习方式:监督学习、无监督学习、自监督学习、半监督学习和强化学习。

3.1.1、监督学习

监督学习: 在监督学习中,提供给算法的训练数据集包含预期的输出结果,这些输出结果被称为“标签”。 例如,你要训练一个识别猫狗的图像分类器。 你需要提供带有标签的图片:每张图片都必须被明确地标注为“猫”或“狗”,以便算法学习将图像特征与正确的类别关联起来。
在这里插入图片描述

典型的监督学习任务包括以下两种:

  • 分类:目标是将数据分配到不同的类别中。 例如,一个医疗诊断系统可以利用患者的病史、症状和检查结果作为输入,来预测患者是否患有某种疾病(比如糖尿病或心脏病)。系统需要学习将输入数据与正确的疾病类别关联起来。

  • 回归:目标是预测一个连续的数值。 例如,一个房屋价格预测模型可以基于房屋的面积、地理位置、房间数量等特征来预测房屋的市场价值。 为了训练该模型,需要提供大量房屋的实例,每个实例包含房屋的特征及其对应的实际售价。

注意,某些回归模型也可以用于分类任务,反之亦然。 比如,逻辑回归虽然是一种回归模型,但经常被用于分类问题。 它可以输出一个概率值,表示数据属于某个特定类别的可能性(例如,判断某个客户是否会购买某款产品,并输出他/她购买该产品的概率)。

在这里插入图片描述

在监督学习的语境下,“目标(target)”和“标签(label)”这两个术语是同义的。但是,“目标”更常见于回归任务中,“标签”则更常用于分类任务。

此外,用于预测的输入变量,也就是数据的特征,也可能被称为“预测因子(predictor)”或“属性(attribute)”。 这些术语可以指代单个数据点的某个特征(例如,“这名学生的考试成绩属性为 90 分”),也可以指代整个数据集的某个特征的整体特性(例如,“考试成绩属性与学生的出勤率具有显著相关性”)。

3.1.2、无监督学习

在无监督学习中,与监督学习不同,训练数据没有被预先标记。系统需要在没有任何“老师”指导的情况下,自行发现数据中的模式和结构。
在这里插入图片描述

举个例子,假设你拥有一家在线音乐平台的用户的听歌记录。 你可以使用聚类算法(一种机器学习算法,用于将数据集中的对象分组成具有相似特征的多个类别。) 来尝试识别具有相似音乐品味的用户群体(如图)。你不需要事先告诉算法任何关于用户的偏好信息,它会根据用户的听歌行为,自动将他们分成不同的群体。例如,算法可能会发现一部分用户主要听流行音乐,另一部分用户更喜欢古典音乐,还有一部分用户偏好电子音乐。如果使用层次聚类算法 ,还可以将这些大群体进一步细分为更小的、更具体的音乐偏好群体。这些发现可以帮助平台进行个性化推荐,从而提高用户满意度。
在这里插入图片描述

可视化算法 是无监督学习的另一个有力应用。这类算法接收高维度、未标记的数据作为输入,并将其转化为二维或三维的可视化结果(如图)。

在这里插入图片描述

算法的目标是在降维的同时,尽可能保留原始数据的结构信息。例如,如果原始数据中存在明显的簇,算法会尽量保证这些簇在可视化结果中仍然保持分离状态。通过可视化,我们可以更好地理解数据的内在结构,并发现潜在的、意想不到的模式。

与可视化密切相关的任务是降维(定义:一种数据处理技术,用于减少数据集中特征的数量,以便更有效地分析和处理数据。通过降维,可以减少计算复杂性、提高模型的训练速度和性能,并且可以帮助发现数据中的隐藏模式和结构。),它旨在在尽可能少丢失信息的前提下,简化数据的表示形式。一种常用的降维方法是将多个相关的特征合并为一个新的特征,这种方法被称为特征提取。例如,在分析房价时,房屋的卧室数量和居住面积可能具有很强的相关性。降维算法可以将这两个特征结合起来,提取出一个新的特征,例如“居住空间指数”,来更好地代表房屋的整体空间大小。

通常,在将训练数据输入到其他机器学习算法(比如监督学习算法)之前,先使用降维算法来减少数据的维度是一个非常好的选择。这样做可以加快算法的运行速度,减少数据占用的存储空间和内存,而且在某些情况下,还可以提高算法的性能。简单来说,降维可以帮助算法更快更有效地学习。

另一个关键的无监督学习任务是异常检测。其目标是识别数据集中不寻常的实例,例如在网络安全中检测异常的网络流量以防止攻击,或是在工业生产中检测设备运行中的异常参数以预警故障,或者是在数据清洗阶段自动剔除数据集中的噪声数据。 训练时,模型主要接触的是“正常”的数据样本,从而学习识别这些正常模式。当遇到新的数据实例时,模型能够评估它是否符合已知的正常模式,并将那些显著偏离正常模式的实例标记为异常。

在这里插入图片描述

与异常检测相似的是新颖性检测,它的目的是识别与训练集中所有实例都不同的“新”实例。新颖性检测的关键在于训练集必须非常干净,不能包含任何你希望算法标记为新颖的实例。举例来说,假设你有一个包含各种鸟类图片的数据库,其中包含少量天鹅的图片。一个新颖性检测算法的目标是识别出图片中的企鹅,而不是将天鹅标记为新颖的,因为它已经在训练集中见过类似的鸟类。而一个异常检测算法,可能会将天鹅标记为异常,因为它认为这种鸟类与其他常见的鸟类有很大的差异。

最后,关联规则学习是另一种常见的无监督学习任务,旨在从海量数据中发现变量之间隐藏的关联模式。 例如,一个在线书店通过分析用户的购买记录,关联规则学习可能会发现,购买了科幻小说的用户也经常购买仙侠小说。因此,书店可以考虑将这两类书籍放在推荐栏目一起展示,或者推出组合购买优惠,以提高销量。

3.1.3、半监督学习

由于标注数据往往成本高昂且耗时,现实场景中常常存在大量未标注的数据,以及少量已标注的数据。 某些机器学习算法具备处理这种混合数据集的能力,这类学习方法被称为半监督学习
在这里插入图片描述

图片存储服务就是一个很好的半监督学习的例子。用户上传大量照片后,服务会自动将相似的照片进行分组——比如识别出哪些照片中包含了特定的地标建筑,哪些照片中出现了相似的宠物。这是算法的无监督聚类部分。接下来,用户只需要手动给几个代表性的照片加上标签,比如“埃菲尔铁塔”或“小狗旺财”,系统就能自动识别出所有包含该地标或宠物的其他照片。

大多数半监督学习方法都结合了无监督学习和监督学习的思想。例如,可以先使用聚类算法将相似的样本聚集成不同的簇,然后利用簇内已标注样本的标签信息,推断未标注样本的标签,将占比最高的标签赋予整个簇。 完成这个过程后,就可以利用整个标注数据集进行标准的监督学习。

3.1.4、自监督学习

另一种机器学习策略是利用完全未标注的数据集来生成一个完整的标注数据集。 生成标注数据集后,就可以使用任何标准的监督学习算法进行训练。 这种方法被称为自监督学习

举例来说,有一堆没有标签的图片。自监督学习就像玩一个“拼图游戏”。我们随机地把每张图片遮住一部分,然后让机器去猜被遮住的部分是什么,把它还原成完整的图片。

在这里插入图片描述

通过自监督学习“创造”出来的模型,有时候本身就很有用,比如它可以修复破损的照片,或者从照片里P掉不想要的东西。 但更多时候,自监督学习只是个跳板,真正目的是训练一个能解决其他问题的模型。

这就好比,先让模型练习“举一反三”的能力,然后再教它解决具体的问题。 先让它通过自监督学习掌握图像的一些基本特征和规律,然后才用它来解决真正关心的任务。

比如,真正想要的是一个能识别各种花朵的模型,它可以告诉我们一张图片里是什么花。 我们可以先用一大堆没有标注的花朵照片,训练一个自监督模型,让它学会区分不同颜色的花瓣,不同形状的叶子等等。 训练方法可以是,给模型看一张旋转过的花朵图片,然后让它猜出原本花朵是哪个方向的。 通过这个训练过程,模型就能学到很多关于花朵的特征信息。

一旦这个自监督模型表现得足够好,就可以把它改造一下,让它专门识别花朵种类。 因为模型已经学过了花朵的基本特征,所以只需要用少量的人工标注数据,告诉它哪些特征对应着什么花,就能很快地训练出一个花朵识别模型。这就像是,老师先教会了学生认识字,然后再教他们阅读课文,理解其中的含义。 最后,用带有花朵种类标签的数据集进行微调,让模型更好地将它学到的特征与特定的花朵类别关联起来。

把从一个任务中学到的东西,用到另一个任务上去,这叫做“知识迁移”,或者更常用的说法是“迁移学习”。迁移学习是现在机器学习里非常重要的技术,特别是在使用“深度神经网络”(也就是由很多层“神经元”组成的网络)的时候,效果尤其明显。 神经网络的层数越多,就像搭积木一样,一层层地学习特征,迁移能力就越强。

对于自监督学习的归类,存在一些争议。 有人觉得它应该算作无监督学习,毕竟它用的是完全没有标注的数据。 但也有人认为它更接近监督学习,因为它在训练过程中会自己生成“标签”。 无监督学习通常用于处理聚类、降维和异常检测等任务,侧重于发现数据本身的内在结构。 而自监督学习则更关注分类和回归这些监督学习的任务。 因此,最好把自监督学习看作是独立的一类,它介于两者之间,既利用了无监督学习的未标注数据,又实现了监督学习的目标。

3.1.5、强化学习

定义:一种通过在模拟环境中进行反馈的探索式学习的机器学习类型。

强化学习是一种独特的学习范式,它与前面的监督和无监督学习有着根本的不同。 在这种学习方式中,有一个被称为“智能体(agent)”的学习系统,它与一个“环境”(environment)进行交互。 智能体能够观察环境的状态,并基于这些观察选择一个“动作”(action)来执行。 每次执行动作后,智能体会收到来自环境的“奖励”(reward),奖励可以是正面的(鼓励智能体),也可以是负面的(惩罚智能体)。 智能体的目标是学习一个最优的“策略”(policy),这个策略指导智能体在任何给定状态下应该采取哪个动作,以最大化其长期累积奖励。 举个例子,训练一个AI来玩电子游戏,AI就是智能体,游戏环境就是环境,AI在游戏中采取的操作(例如:跳跃、射击)就是动作,游戏得分就是奖励。 智能体通过不断地试错和学习,最终学会最佳的游戏策略,以获得最高的分数。

在这里插入图片描述

许多机器人采用强化学习算法来学习如何走路。DeepMind的AlphaGo程序也是强化学习的一个很好的例子:在2017年5月击败世界排名第一的棋手柯洁而成为头条新闻。

3.2、批量学习与在线学习

区分机器学习系统的另一个关键标准是 系统是否可以从传入的数据流中逐步学习

3.2.1、批量学习

在批量学习模式下,机器学习系统无法进行增量学习,必须利用所有可用数据进行一次性训练。这种训练方式通常耗时且计算资源密集,因此一般离线进行。系统首先完成训练,然后部署到生产环境,之后便停止学习,仅应用已习得的知识进行工作。这被称为离线学习

然而,随着时间的推移,模型的性能往往会逐渐下降。这是因为现实世界不断变化,而模型却保持静态不变,导致模型与现实之间的差距逐渐拉大。这种现象通常被称为模型衰退或数据漂移。为了应对这个问题,需要定期使用最新的数据重新训练模型。重新训练的频率取决于具体的应用场景。例如,识别猫狗图片的模型性能衰退会相对缓慢,而预测快速变化的金融市场的模型则可能衰退得很快,需要更频繁地重新训练。但也不是绝对的,区分猫狗图片的模型,也可能需要定期重新训练。这并非因为猫狗本身会发生变化,而是由于图像采集和处理方式的不断演变。例如,相机技术不断更新,图像格式、分辨率、亮度和尺寸比例等都在不断变化。

如果希望批量学习系统学习新数据(例如识别新型垃圾邮件),需要使用包含新旧数据的完整数据集重新训练整个系统,并用新模型替换旧模型。尽管训练、评估和部署机器学习系统的整个流程可以实现自动化,即使是批量学习系统也能适应变化,只需定期更新数据并重新训练系统即可。但这并非最佳方案。

这种方法虽然简单有效,但由于需要使用完整数据集重新训练,耗时可能很长,通常需要每24小时甚至每周才能训练一次新模型。如果系统需要处理快速变化的数据(例如预测股票价格),这种方法的响应速度就显得不足。

此外,使用完整数据集进行训练会消耗大量的计算资源(CPU、内存、磁盘空间、磁盘I/O、网络I/O等)。如果数据量庞大且系统每天都从零开始重新训练,将会带来高昂的成本。对于极大的数据集,甚至可能无法使用批量学习算法。

最后,如果你的系统需要具备自主学习能力,并且资源有限,那么存储大量训练数据并耗费大量资源进行每日数小时的训练将会是巨大的挑战。在这种情况下,更有效的方案是采用增量学习算法。 这些算法能够逐步学习新数据,而无需重新训练整个模型,从而节省宝贵的计算资源和存储空间。

3.2.2、在线学习

定义:使用随机梯度下降和小批量大小为一的方法来训练神经网络的机器学习方法。

在“online learning”中,系统通过逐步接收数据实例进行增量训练。这些数据可以逐个提供,也可以以 mini-batch 的分组形式输入。每次训练步骤都相对高效且计算成本低,因此系统能够在新数据到来时实时地进行动态调整和学习。
在这里插入图片描述

在线学习非常适合需要迅速响应环境变化的系统。当计算资源有限时,它也是一种理想选择;例如,在边缘设备或嵌入式系统上进行模型训练。

此外,在线学习算法还适用于处理无法完全装载到单台机器内存中的超大规模数据集(通常称为外存学习)。这种方法通过逐步加载数据块,对每个数据块依次执行训练操作,重复这一过程,直到完成整个数据集的学习。这种方式能够有效地在资源有限的环境中实现模型训练。
在这里插入图片描述

在线学习系统中,一个关键参数是衡量系统对数据变化响应速度的指标,这通常称为学习率。如果将学习率设置得较高,系统能够迅速适应新数据,但这种快速适应往往会导致模型迅速遗忘过去学到的信息。反之,若设定较低的学习率,系统的调整会显得更为缓慢,具有更大的“惯性”。这种较缓的适应速度使模型对新数据中的噪声或偶发的异常值不那么敏感。

特别说明:外存学习通常在离线环境中执行(即不是在实时流数据上运行),因此称其为“在线学习”容易引起混淆。实际上,可以将这种方法看作是一种增量学习策略,即模型逐步整合新数据以不断完善,从而有效地应对数据集的不断扩展和变化。

在线学习面临的主要挑战之一是模型对错误或恶意数据的脆弱性。如果模型接收到有偏差或被污染的数据,其性能可能会迅速下降(速度取决于学习率和数据质量)。尤其是在生产环境中,这种性能退化会导致用户体验下降,造成实际损失。

例如,一个在线广告推荐系统。如果竞争对手或恶意用户通过大规模点击欺诈来人为抬高某些广告的点击率,在线学习模型会错误地将这些广告识别为高质量的广告,并增加它们的展示频率。用户看到的是不相关或低质量的广告。

为了减轻这种风险,需要对在线学习系统进行严密的监控,并建立完善的反馈和干预机制。

  • 性能监控: 持续监测模型的性能指标,一旦检测到异常下降,立即采取行动。
  • 学习暂停/回滚: 当性能下降超过预设阈值时,自动暂停学习过程,甚至回滚到之前的模型版本,以避免进一步的损害。
  • 对输入数据进行实时监控,检测异常值或可疑模式。
  • 建立人工审核和干预机制,对于可疑数据进行人工确认和清理。

3.3、基于实例与基于模型的学习

根据机器学习系统如何进行泛化来对其进行分类。机器学习本质上是关于预测的:系统通过学习大量训练数据中的模式,从而能够对未知数据做出准确的预测。仅仅在训练集上表现良好是不够的,真正的挑战在于如何将学到的知识推广到未见过的新数据上。

泛化主要有两种策略:基于实例的学习和基于模型的学习。

3.3.1、基于实例的学习

定义:一种机器学习方法,通过存储和分析训练实例来进行学习和预测。

一种最直接但可能不太有效的学习方法是“死记硬背”。如果一个学生只是简单地记住问题和对应的答案,而不去理解事件之间的联系和因果关系,那么当遇到稍微不同的问题时(例如,改变提问方式或要求推断),他就无法正确回答。

相比于死记硬背,更有效的学习方式是找到数据之间的相似性并进行泛化。

这种方法比死记硬背更灵活,因为它允许系统识别与已知实例相似但并不完全相同的新实例。 但是,这种方法也存在局限性,例如,选择合适的相似度度量标准至关重要,并且需要考虑各种因素。

我们将这种学习方式称为“基于案例的学习”。 在这种方法中,系统通过存储训练数据集中的每一个实例来“学习”。 当需要预测一个新实例的结果时,系统会寻找训练集中与该新实例最相似的实例(或一小部分实例),并基于这些相似实例的结果来进行预测。 关键在于定义一个合适的相似度度量标准。

在这里插入图片描述

3.3.2、基于模型的学习

另一种从数据中学习并进行预测的关键方法是构建一个数据的抽象表示,也就是所谓的“模型”。 这种方法被称为“基于模型的学习”。 系统不再简单地记住每一个例子,而是尝试找到数据背后隐藏的模式和规律,并将这些规律抽象成一个模型。

在这里插入图片描述

与基于实例的学习不同,基于模型的学习的重点在于构建一个通用的预测函数,而不是记住每一个训练实例。 通过学习数据的内在结构,模型可以对未见过的数据进行有效的泛化。 这种方法的优点是能够更高效地利用存储空间,并且通常具有更好的预测性能。

3.3.3、典型的机器学习工作流程

例如,要预测房价。 基于模型的学习方法会尝试建立一个房价与房屋特征之间的关系模型,例如房屋面积、地理位置、卧室数量等等。 这个模型可以是线性的(例如线性回归),也可以是非线性的(例如神经网络)。 一旦模型建立起来,就可以将新的房屋特征输入到模型中,从而预测出它的价格。

y = a + b x y = a + bx y=a+bx

决定用某个线性函数来建立模型,这一步被称为模型选择。

那么,如何才能找到这些参数的最佳取值,使模型能够做出准确的预测呢? 这就需要定义一个衡量模型表现的指标。

可以定义一个损失函数或者成本函数(Cost Function),来量化模型预测与实际值之间的差距。 损失函数关注于单个样本的预测误差,而成本函数则通常是所有训练样本损失的平均值或总和。 目标是找到能够最小化这个成本函数的那组参数。

寻找最佳参数的过程,称之为模型训练(Model Training)。 最终,经过训练的模型能够对新的、未见过的图像进行准确分类。 训练好的模型就是利用训练数据学到的知识,用来预测新的数据。

一个典型的机器学习项目流程:

  1. 深入分析并理解手头的数据。这包括探索数据的特征、分布、潜在的偏差以及可能存在的缺失值等等。

  2. 基于对数据的理解,选择一个合适的机器学习模型。 选择模型取决于多种因素,例如数据的类型、任务的性质(例如,分类、回归、聚类等)以及对模型复杂度和可解释性的要求。

  3. 选定模型后,我们使用训练数据来训练模型。 训练过程本质上是一个优化过程,算法会搜索能够最小化损失函数(或最大化效用函数)的模型参数。 这个过程也称为“学习”,模型会逐渐从训练数据中提取有用的模式和规律。

  4. 训练完成后,就可以使用训练好的模型来对新的、未见过的数据进行预测或决策。 这个过程被称为推理(Inference)。 一个好的模型不仅应该在训练数据上表现良好,更重要的是能够对未见过的数据进行泛化(Generalization),也就是做出准确的预测。 模型泛化能力的好坏是衡量机器学习模型优劣的关键指标。

四、机器学习技术的应用

  1. 工业质检:自动识别产品缺陷。图像分类任务,利用卷积神经网络 (CNN) 或 Transformer。

  2. 辅助医生诊断肿瘤。语义图像分割,主要利用卷积神经网络 (CNN) 或 Transformer。分析CT、MRI等医学影像,辅助医生诊断肿瘤、评估病情发展,并制定个性化的治疗方案。

  3. 自动分类海量新闻资讯。文本分类 (属于自然语言处理 NLP 领域),利用循环神经网络 (RNN)、CNN 或 Transformer。

  4. 自动识别攻击性评论。文本分类 (属于自然语言处理 NLP 领域),与新闻文章分类类似,使用 RNN、CNN 或 Transformer。

  5. 信息提取。文本摘要 (属于自然语言处理 NLP 领域)。与文本分类类似,使用 RNN、CNN 或 Transformer。

  6. 智能客服与虚拟助手。复杂任务,涉及多个 NLP 组件。自然语言理解 (NLU)、问答模块等。 需要理解用户的意图,并生成流畅自然的回复。

  7. 商业预测,利用 线性回归、多项式回归、回归支持向量机、回归随机森林、人工神经网络。 如果需要考虑过去业绩指标的时间序列,可以使用 RNN、CNN 或 Transformer。

  8. 语音助手。属于语音识别任务,主要利用RNN、CNN 或 Transformer。这些模型能够有效处理音频的时序信息,识别语音中的内容。

  9. 自动侦测信用卡诈骗。属于异常检测任务,主要利用隔离森林、高斯混合模型 或自动编码器。

  10. 个性化推荐。推荐系统,使用人工神经网络。

这只是冰山一角,展示了机器学习任务的广度和复杂性,以及可以用于解决这些任务的技术类型。

五、机器学习的主要挑战

模型训练的核心,可以简化为选择合适的模型并在数据上训练。因此,成功与否往往取决于两个关键因素:模型选型的优劣 以及 数据质量的高低。这两者就像硬币的两面,任何一方面的缺陷都可能导致训练失败,产生偏差,甚至得出错误的结论。

坏数据:

  1. 训练的数据量不足。机器学习模型需要从大量数据中学习模式和关系,从而实现准确的预测或决策。对于诸如简单的线性回归或者逻辑回归等问题,可能只需要数千个示例,模型就能够学习到有效的规律。然而,当处理图像识别、自然语言处理等复杂问题时,数据需求会呈指数级增长。这些问题涉及大量的特征和复杂的非线性关系,模型需要从数百万甚至数十亿个示例中进行学习,才能达到理想的性能。数据量不够,模型只能根据不完整的信息进行推断,这必然导致预测结果的不准确。
  2. 非代表性训练数据。机器学习模型的终极目标是泛化,即在未见过的新数据上也能做出准确预测。而模型泛化能力的基础,在于训练数据的代表性。如果训练数据不能有效地反映真实世界的分布,那么模型就如同盲人摸象,只能学习到片面的、甚至错误的规律,从而在新数据上表现不佳。
  3. 数据质量过低。数据往往是杂乱的,充满了错误、异常值和噪声,就像未经过滤的原矿,蕴藏着价值,但也掺杂着大量的杂质。如果直接将这些杂乱的数据喂给模型,模型就很难从中学习到真正的模式,最终导致性能下降。这就需要数据清洗
  4. 无关的特性。“巧妇难为无米之炊”。再精妙的机器学习算法,也离不开高质量的特征作为驱动力。如果训练数据中充斥着大量无关紧要的特征,而真正有用的特征却凤毛麟角,那么模型就如同在信息噪音中迷失方向,难以学习到数据背后蕴藏的规律。

坏算法:

  1. 训练数据过拟合:人常常会不自觉地进行过度概括,即根据有限的经验得出过于宽泛的结论。 例如,如果一个人只见过几只黑天鹅,就断言所有的天鹅都是黑色的,这就是一种过度概括。同样的,机器学习模型也会面临同样的风险。 如果模型过于复杂,并且在训练数据上学习得“太好”,它可能会记住训练数据中的噪声和细节,而忽略了数据背后真正的模式,从而导致过拟合 (Overfitting)。
  2. 训练数据欠拟合:如果说过度拟合是模型学习得“太过火”,那么欠拟合 (Underfitting) 则恰恰相反,指的是模型学习得不够充分,无法捕捉到数据背后蕴藏的复杂模式。当模型过于简单,表达能力不足以描述数据的底层结构时,就会发生欠拟合。模型在训练数据和测试数据上的表现都不佳,准确率都很低。 模型无法捕捉到数据中的关键信息,因此做出的预测往往偏差很大。欠拟合就像一个“懒惰”的学习者,不愿意深入挖掘数据中的信息,只是停留在表面,因此无法做出准确的预测。 解决欠拟合的方案也很简单,选择更强大的模型或者提供更好的特征,亦或者减少对模型的限制。

六、总结

本文介绍了机器学习中一些最重要的概念。目前,已经掌握了机器学习的核心理念,但面对如此多的概念,很难记住。总结概括一下:

  • 机器学习的核心思想: 机器学习的本质在于让计算机通过学习数据中的规律,在特定任务上实现性能的提升,而无需人为地编写复杂的规则。

  • 机器学习包含了众多类型迥异的系统,例如:监督或非监督,批处理或在线,基于实例或基于模型。

  • 机器学习项目的工作流程: 首先收集与任务相关的数据,并将其整理成训练集。然后,将训练集提供给学习算法。 算法会根据训练数据调整模型参数,目标是使模型能够准确地预测训练集中的数据(即在训练集上表现良好)。 算法会记住训练集中的所有样本。当需要预测新样本时,算法会将新样本与训练集中的样本进行比较,并根据相似度来进行预测。

  • 影响模型性能的关键因素:数据质量、模型复杂度

在这里插入图片描述

<think>好的,我现在需要帮助用户找到PHP反序列化漏洞中通过进制绕过的方法,并给出一个例子。首先,我得回忆一下PHP反序列化机制以及常见的绕过技巧。 用户提到了“进制绕过”,这可能指的是利用不同进制表示的数值在反序列化时的处理差异。例如,PHP在反序列化时,处理数字类型的方式可能允许十六进制或其他进制的表示,从而绕过某些过滤或检查。 我记得PHP的序列化字符串中,整数通常以i:数字;的形式表示,而字符串是s:长度:"内容";。如果某些过滤逻辑检查的是十进制数字,攻击者可能通过使用十六进制或其他进制来绕过。例如,使用十六进制的表示方式,可能在某些情况下被PHP解析为相同的数值,从而绕过检查。 不过,PHP的序列化格式本身并不直接支持十六进制或其他进制的数字表示。也就是说,在序列化字符串中,数字应该以十进制形式出现。那用户所说的进制绕过具体是如何实现的呢?可能需要结合其他漏洞,比如在字符串处理中的进制转换问题。 例如,如果一个应用在反序列化之前对输入进行了某种处理,如将十六进制字符串转换为十进制,或者存在字符截断、类型转换等问题,可能导致反序列化时的对象注入。比如,当开发者尝试过滤某些特定数值时,攻击者可能通过不同进制的输入来绕过过滤,因为过滤逻辑可能没有考虑到多种进制的情况。 比如,考虑一个类中的__wakeup()方法,该方法可能根据某个数值进行安全检查。如果攻击者能通过十六进制或其他方式表示该数值,可能绕过检查。例如,原本过滤的是i:10;,但攻击者使用i:0xA;(假设PHP允许),但实际上,PHP的序列化格式中i后面的值必须是十进制,所以这可能行不通。 这时候可能需要另一种方式,比如在字符串长度中使用十六进制。例如,s:0x10:"..."; 这里的长度是十六进制的16。PHP的unserialize函数是否允许长度字段使用十六进制?根据PHP的文档,序列化字符串中的长度应该是十进制的,但某些PHP版本可能存在解析差异,允许十六进制的长度表示,这可能被用来构造恶意字符串。 例如,假设有一个类在反序列化时根据字符串长度进行某种验证,攻击者可能通过使用十六进制的长度表示来绕过长度限制。例如,s:0x31:"..."; 实际长度为49,但可能绕过某些检查逻辑,认为长度是0x31(即十进制的49)。 另外,可能涉及字符逃逸的情况。例如,如果序列化字符串中的某个部分被过滤或替换,导致长度字段与实际字符串长度不符,从而改变后续的反序列化结构。例如,如果替换字符导致字符串变长,但攻击者通过十六进制或其他进制调整长度字段,使得解析器正确解析,从而实现注入。 例如,假设原本的序列化字符串是s:5:"Hello";,如果攻击者将长度改为s:0x5:"Hello";,PHP可能仍然正确解析,因为0x5等于5。但如果应用在处理输入时将某些字符替换为更长或更短的表示,攻击者可能利用进制表示来调整长度,从而避免因长度不匹配导致的解析错误。 此外,可能结合其他漏洞,如类型混淆。例如,将某个字段的类型从字符串改为整数,或者利用不同进制表示的类型值来绕过检查。 现在,我需要验证这些思路是否正确。查阅相关PHP反序列化漏洞的资料,尤其是进制绕过的例子。根据引用[2]和[4],PHP的反序列化会调用魔术方法,如__wakeup(),而漏洞常出现在这些方法中。例如,如果某个类的__wakeup()方法根据某个数值进行权限检查,攻击者可能通过进制转换绕过该检查,如果该数值的解析存在漏洞。 比如,假设有类如下: class Example { public $id; public function __wakeup() { if ($this->id == 10) { // 执行敏感操作 } } } 如果攻击者能够将$id设置为十六进制的A(即10),但序列化字符串中使用i:0xA;,但实际上PHP的序列化不允许这样,必须为i:10;。因此,这种情况下进制绕过可能不可行。除非应用在处理输入时,将字符串中的数字转换为十进制,比如存在某种过滤,将十六进制转换为十进制,导致反序列化后的数值正确。 另一种可能性是,应用在处理输入时,将用户提供的序列化字符串中的数字进行进制转换处理,例如将十六进制转换为十进制,但处理不当导致绕过。例如,用户提交的序列化字符串中的数字以十六进制表示,但应用在过滤时将其转换为十进制,而反序列化时PHP仍然正确解析,导致绕过。 例如,假设应用检查序列化字符串中是否有i:10;,但攻击者提交i:0xA;,应用可能没有识别十六进制格式,导致检查绕过,而PHP在反序列化时可能无法解析i:0xA;,导致错误。因此,这种方法可能不适用。 因此,可能更常见的是利用字符串中的十六进制或其他进制绕过,例如在字符串长度或字符表示中使用十六进制。例如,在序列化字符串中,长度字段可以使用十六进制,如s:0x10:"...";,而PHP的unserialize函数会正确解析这个长度。例如,构造一个恶意序列化字符串,其中的长度字段用十六进制表示,以绕过某些过滤逻辑。 例如,假设应用有一个过滤,不允许字符串长度超过10,但攻击者使用十六进制表示长度0xB(即11),应用可能没有检查十六进制的情况,从而绕过限制。 具体例子可能如下: 正常序列化字符串: O:4:"User":1:{s:4:"name";s:5:"admin";} 攻击者构造的字符串: O:4:"User":1:{s:4:"name";s:0x5:"admin";} 这种情况下,PHP仍然能正确解析,因为s:0x5等同于s:5。如果应用的过滤逻辑检查的是十进制的长度,而没有处理十六进制,攻击者可能绕过长度限制。 不过,这只是一个简单的例子,可能不足以构成漏洞。更复杂的场景可能涉及字符逃逸。例如,在PHP反序列化中,如果字符串的长度被错误地计算,可能导致解析器将后续的数据当作新的对象来处理,从而实现对象注入。 例如,假设存在一个替换操作,将某些字符替换为更长的字符串。例如,将'x'替换为'xx'。攻击者可以构造一个字符串,使其在替换后的长度与原始长度匹配,通过十六进制长度字段来正确解析,从而逃逸出原有的结构,插入恶意对象。 例如,原始序列化字符串: s:5:"Hello"; 如果应用将'l'替换为'xx',则替换后的字符串为"Hexxxxxxo",长度变为9。但原始长度是5,导致反序列化失败。但如果攻击者构造s:0x9:"Hlllo";,其中每个'l'被替换为'xx',则替换后的字符串长度为:假设原始字符串是"Helllo",替换后是"HeXXXXXXo",正确长度可能被0x9(即9)匹配,从而反序列化成功,并可能控制后续数据。 不过,这需要具体的应用场景和替换逻辑,可能比较复杂。 总结来说,PHP反序列化中的进制绕过可能主要涉及在序列化字符串中使用十六进制表示长度或其他数字字段,从而绕过过滤或检查逻辑。开发者可能在过滤时仅检查十进制数字,而忽略其他进制表示,导致绕过。 现在,需要给出一个具体的例子。例如,一个类在反序列化时检查某个数字是否为特定值,攻击者通过十六进制绕过。 假设存在以下类: class VulnerableClass { public $accessLevel; public function __wakeup() { if ($this->accessLevel == 1) { $this->admin = true; } } } 正常情况下,攻击者需要设置accessLevel为1。但如果应用过滤了序列化字符串中的i:1;,攻击者可能尝试使用十六进制或其他进制绕过,如i:0x1;,但PHP的序列化语法中并不支持这种写法,因此这不可行。 那可能需要其他方式。例如,如果accessLevel是一个字符串,应用检查其是否为"1",但攻击者使用其他进制字符串绕过,如"1"的八进制表示等。不过,这属于类型混淆,而非序列化字符串本身的进制绕过。 另一种情况是,攻击者通过进制转换在序列化字符串的某些部分构造有效载荷。例如,在对象属性数量处使用十六进制绕过。例如,原本序列化字符串中的属性数量为1,即O:15:"VulnerableClass":1:{...},攻击者可能改为O:15:"VulnerableClass":0x1:{...},但这同样在语法上是允许的,可能不会触发问题。 可能更实际的例子是字符串长度绕过。例如,在序列化字符串中,如果某个字符串的长度被限制为小于某个值,攻击者用十六进制表示长度以绕过。 例如,应用限制某个字段的长度为10,攻击者构造s:0xA:"...";,长度为10,但应用可能没有检查十六进制形式,从而允许更长的字符串。 不过,这仍然取决于应用的过滤逻辑是否处理了十六进制。 因此,可能的例子是,当应用在反序列化前对用户输入进行过滤,如删除某些危险字符,导致序列化字符串的长度变化,攻击者通过调整长度字段的进制表示,使得解析器正确解析,从而构造有效的反序列化载荷。 例如,字符逃逸攻击中的利用。假设应用将用户输入中的'x'替换为'xx',导致字符串长度增加。攻击者可以构造一个序列化字符串,其中长度字段使用十六进制,使得替换后的实际长度与长度字段匹配,从而逃逸出原有结构,插入恶意对象。 例如,原始载荷: s:5:"123x5"; -> 替换后为s:5:"123xx5",实际长度6,导致解析错误。但攻击者可以构造s:0x6:"123x5";,替换后字符串长度为6,长度字段0x6等于6,解析正确,从而可能后续注入其他对象。 不过,这需要具体的替换逻辑和精心构造的长度。 综上所述,PHP反序列化中的进制绕过通常涉及在序列化字符串中使用十六进制的长度或其他数值,以绕过过滤或检查机制。开发者可能未考虑到不同进制的表示,导致攻击者可以构造恶意载荷绕过防护。</think>### PHP反序列化漏洞中的进制绕过方法 在PHP反序列化漏洞中,**进制绕过**通常通过修改序列化字符串中的数值表示方式(如十进制、十六进制)来绕过过滤或类型检查逻辑。以下是一个具体示例及分析: --- #### 示例场景 假设存在一个类`User`,其`__wakeup()`方法通过检查`$role`字段的值赋予管理员权限: ```php class User { public $username; public $role; public function __wakeup() { if ($this->role === 1) { $this->is_admin = true; // 授予管理员权限 } } } ``` 开发者可能对输入进行过滤,例如阻止`role`字段的值为十进制`1`(如`i:1;`)。攻击者可通过十六进制绕过这一限制。 --- #### 进制绕过攻击步骤 1. **构造恶意序列化字符串** 正常序列化字符串为: ``` O:4:"User":2:{s:8:"username";s:5:"guest";s:4:"role";i:1;} ``` 若过滤`i:1;`,攻击者可将`role`的十进制值`1`改为十六进制`0x1`,构造以下载荷: ``` O:4:"User":2:{s:8:"username";s:5:"guest";s:4:"role";i:0x1;} ``` PHP在反序列化时会自动将`0x1`解析为十进制`1`,从而绕过过滤逻辑。 2. **利用字符串长度的十六进制表示** 若开发者检查字符串字段的长度是否为十进制数值,攻击者可使用十六进制表示长度。例如: ``` O:4:"User":2:{s:8:"username";s:0x5:"admin";s:4:"role";i:1;} ``` 这里`s:0x5:"admin"`等同于`s:5:"admin"`,但可能绕过基于十进制长度的检查。 --- #### 关键点分析 - **PHP的数值解析特性**:PHP的`unserialize()`函数允许序列化字符串中的整数以十六进制(`0x`前缀)或八进制(`0`前缀)表示[^2]。 - **类型混淆风险**:若过滤逻辑未覆盖多种进制格式,攻击者可构造特殊数值绕过检查。 - **字符逃逸扩展**:进制绕过常与字符逃逸结合,例如通过调整长度字段的进制表示,使替换后的字符串仍能被正确解析[^4]。 --- #### 防御建议 1. 严格验证反序列化输入,禁止非十进制数值表示。 2. 使用安全的反序列化库(如`json_decode`)替代`unserialize()`[^5]。 3. 对关键字段进行强类型校验,避免隐式类型转换。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lion 莱恩呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值