增强的大型语言模型作为推理引擎
原文:
towardsdatascience.com/enhanced-large-language-models-as-reasoning-engines-582bff782113
·发表于 Towards Data Science ·阅读时长 12 分钟·2023 年 12 月 23 日
–
人工智能软件被用来增强本文文本的语法、流畅性和可读性。
最近,大型语言模型(LLMs)在自然语言处理能力方面的指数级进步引起了人们对其实现人类水平智能的巨大兴奋。它们在暴露于大量数据集后,能够生成异常连贯的文本并进行对话,这似乎表明了灵活的通用推理能力。
然而,越来越多的声音敦促对未受限制的乐观情绪保持谨慎,突出了限制神经方法的基本盲点。大型语言模型仍然经常犯基本的逻辑和数学错误,暴露了其回应背后缺乏系统性的问题。它们的知识仍然本质上是统计性的,没有更深层次的语义结构。
更复杂的推理任务进一步暴露了这些局限性。大型语言模型在因果、反事实和组合推理挑战中挣扎,这些挑战需要超越表面模式识别。与人类通过学习抽象的模式来灵活地重新组合模块概念不同,神经网络记忆的是共同出现的术语之间的相关性。这导致了在狭窄的训练分布之外的脆弱泛化。
这种鸿沟凸显了人类认知如何利用结构化的符号表示来实现系统的可组合性和因果模型以概念化动态。我们通过基于有效推理规则操控模块化的符号概念、链式逻辑依赖、利用心理模拟和假设变量关系机制来推理。神经网络固有的统计性质使得难以发展这种结构化推理。
尽管大语言模型(LLMs)具有亚符号基础,但符号类似现象的出现仍然令人费解。然而,更清晰地认识到这种“混合差距”是必要的。真正的进步需要融合互补的优势——神经方法的灵活性与结构化知识表示和因果推理技术——以创建集成推理系统。
我们首先概述了越来越多的分析揭示神经网络在系统性、因果理解和组合泛化方面的不足——强调与先天人类能力的差异。
接下来,我们详细介绍“推理差距”的显著方面,包括模块化技能协调的困难、解开动态和反事实模拟。我们揭示了当代机器学习所缺乏的先天人类能力,并解释了由此产生的脆弱性。
寻求解决方案时,我们讨论了知识图谱作为明确概念关系的支架,这些关系在统计学习中缺失。我们强调了结构化知识注入的方法——查询接口和向量化图谱嵌入——以将神经生成上下文化。
我们介绍了诸如嵌入中的维度类型和并行知识检索等技术,以改善逻辑推理和高效推断的归纳偏差。最后,我们主张耐心培养高质量知识图谱,作为追求实质性人工智能进展的战略资产。
推理差距:
语言模型代理(LMA)最近成为多步骤决策任务中的一种有前景的范式,通常…
arxiv.org [## 让我们逐步验证
近年来,大型语言模型在执行复杂多步骤推理的能力上有了显著提升…
arxiv.org [## 为什么要逐步思考?推理源于经验的局部性
人类具有强大而神秘的推理能力。通过一系列心理步骤,我们能够进行…
arxiv.org [## 大语言模型能否学会因果推理?
因果推理——理解和分析事件之间因果关系的能力——长期以来一直是…
一种新兴观点解释了 LLM 表现出的许多逻辑矛盾和系统性泛化不足,认为这是由于基本的“推理差距”——即无法自发地通过中间推理步骤将事实和推论串联起来。
人类具有使用结构化背景知识和将注意力指向相关路径的直觉能力。我们利用现有的模式和因果模型,将概念连接起来,以编织连贯的叙事。例如,人类可以通过使用首都关系连接孤立的事实——巴黎是法国的首都,法国气候温和,从而可靠地确定一个国家首都的气候。
然而,像 LLM 这样的神经网络仅积累了文本语料库中经常一起出现的术语之间的统计关联。它们的知识依然是隐性的和无结构的。由于没有对概念之间高阶语义关系的理解,它们难以弥合预训练过程中从未直接链接过的概念。需要通过中间步骤进行推理的问题揭示了这种脆弱性。
新基准测试特别评估系统性——模型是否能够以新颖的方式组合已知的构建块。虽然 LLM 在概念必须相关且已经出现在训练数据中的情况下可以达到高准确率,但当概念分开出现并相互影响时,性能显著下降。这些模型无法将孤立的统计知识串联起来,与人类通过间接关系链接概念不同。
这种现象在 LLM 无法在通过逐步提示展开的查询中提供一致的逻辑叙事中得到了实证。当轻微扰动探索新方向时,会触发不可预测的模型失败,因为学习到的统计关联会崩溃。没有结构化的表示或程序化操作符,LLM 无法维持连贯的、目标导向的推理链——暴露了组合泛化的缺陷。
“推理差距”有助于解释 LLM(大型语言模型)的反直觉行为。它们的知识通过深度学习编码在数十亿个参数中,仅从表面统计模式中获取,缺乏人类在概念一致性和探索中固有的有纪律、可解释的逻辑推理框架。这为混合神经符号方法的优先事项提供了启示。
组合推理
LLM 在系统性组合泛化方面仍然存在困难——灵活地通过重新组合已知技能来组装新颖的解决方案。例如,分别学习制作咖啡和吐司并不能直接使你能够协调这两者的联合例程。人类本质上发展出更丰富的模块化、层次化表示。
因果推理
虽然相关性对统计驱动模型来说很自然,但没有明确的概念框架,揭示涉及实验、干预和反事实的因果机制仍然难以捉摸。我们具备对对象、代理和动态的天生理解。
时间推理
事件、计划和叙事的顺序性和瞬态特征要求维持内部时间线,并展望未来。然而,LLMs 展现出的有限情节记忆无法维持连贯性,缺乏心理情境建模。
常识
我们广泛的日常框架,包括对象、空间和直观心理学,提供了在探索世界时的可能性证据。未能模拟这种对朴素物理学、语用学和社会动态的理解限制了暴露的统计知识。
元学习
人类在处理自身推理漏洞时展示了元认知,能够引导注意力并有意识地寻求信息以增强模型。而神经网络中的模糊性和缺乏更高阶的不确定性或自我反思限制了对模型的控制性、战略性改进。
总体而言,LLMs 不具备支持多样化系统化归纳的模式归纳、因果表示、模拟能力、自回归预测、社会启发式或元认知架构。缺乏结构化的归纳偏见,组合爆炸使得学习明确的组合变得不可行。推理漏洞的众多阻碍了达到由理解引导的人类般的灵活性。
这进一步突显了混合神经符号范式的紧迫性,这些范式将天生的神经能力与结构化的组合性和因果约束相结合。这样的整合有望实现更强大、可信的系统,能够流畅地推理。
通过知识图谱增强推理:
引言
towardsdatascience.com [## 知识图谱嵌入作为符号与子符号 AI 之间的桥梁
结构的复兴
medium.com [## 使用混合知识架构增强大型语言模型
使用符号链跟踪向量相关性:一种平衡的方法,用于增强检索增强型推理中的稳健性……
作者的模式
知识图谱提供了一种有前景的方法来克服现代大型语言模型(LLMs)所面临的“推理差距”。通过将概念明确建模为节点,将关系建模为边,知识图谱提供了结构化的符号表示,这可以增强 LLMs 中的灵活统计知识。
建立概念之间的解释性连接可以增强跨遥远领域的系统化、可解释的推理。LLMs 很难仅通过学习的数据模式来连接不同的概念。但知识图谱可以通过提供相关的中介节点和关系,有效地关联文本语料中没有直接共现的概念。这种支撑结构弥合了统计知识的空白,实现逻辑链条。
这种知识图谱还增加了对 LLM 基础推理的透明度和信任度。要求模型展示基于显式图关系的完整推理链可以减轻不当统计幻觉带来的风险。暴露图路径使统计输出建立在经过验证的连接上。
在本质上统计的 LLMs 与结构化因果表示之间构建干净的接口显示出克服当前脆弱性的潜力。将神经知识的广度与外部知识的深度相结合,可以促进 AI 系统的开发,使其在学习和推理方面既灵活又系统化。
知识图谱查询和图算法
知识图谱查询和图算法是从大数据集中提取和分析复杂关系的强大工具。以下是它们的工作原理及其可能达到的效果:
知识图谱查询:
知识图谱将信息组织为实体(如书籍、人物或概念)和关系(如著作关系、亲属关系或主题连接)。查询语言如 SPARQL 和 Cypher 使得可以构造查询,从这些图谱中提取特定信息。例如,你示例中的查询通过匹配与相关主题节点连接的书籍节点,找到与“人工智能”相关的书籍。
图算法:
除了查询,图算法还可以以更深层次的方式分析这些结构。一些典型的图算法包括:
-
路径寻找算法(如 Dijkstra 算法、A* 算法):找到两个节点之间的最短路径,适用于路线规划和网络分析。
-
社区检测算法(如 Louvain 方法):识别图中的聚类或社区,有助于社交网络分析和市场细分。
-
中心性测量(如 PageRank、介数中心性):确定网络中不同节点的重要性,适用于分析社交网络中的影响力或交通网络中的关键基础设施。
-
推荐系统:通过分析用户-项目图,这些系统可以基于过去的互动进行个性化推荐。
大型语言模型(LLMs)可以基于自然语言输入生成对知识图谱的查询。尽管它们在理解和生成类似人类的文本方面表现出色,但其统计性质意味着它们在结构化逻辑推理方面较弱。因此,将它们与知识图谱和结构化查询接口配对,可以利用两者的优势:LLM 用于理解和上下文化用户输入,知识图谱用于精确、逻辑的数据检索。
将图算法纳入其中可以进一步增强这种协同。例如,LLM 可以建议在社交网络图上使用社区检测算法,以识别特定兴趣小组中的影响力人物。然而,挑战在于以高效且可解释的方式集成这些不同的系统。
知识图谱嵌入
知识图谱嵌入将实体和关系编码为密集的向量表示。这些向量可以在 LLM 中动态集成,使用融合模型。
例如,交叉注意机制可以通过将语言模型的令牌嵌入与检索到的图嵌入进行匹配,从而为语言模型的令牌嵌入提供上下文。这注入了相关的外部知识。
数学上将这些互补向量融合,既为模型提供了基础,又允许在两个组件之间进行梯度流动。LLM 继承了关系模式,改善了推理能力。
因此,查询和嵌入机制都提供了将结构化知识图谱与 LLMs 的统计能力连接起来的方法。这有助于生成可解释的、基于策划事实的上下文响应。
通往安全、高效和可解释 AI 的道路无疑在于设计具有不同推理模块的混合系统,这些模块适合其各自的优势,同时通过共生集成来减轻各自的弱点。知识图谱提供了结构性的支撑,将 LLMs 从模式识别器提升为具有上下文感知和严格推理能力的推理器。
知识图谱嵌入可以通过加入额外的约束和结构进一步增强,而不仅仅是编码事实实体和关系。这提供了有用的归纳偏差,以更可靠的方式定向语义相似性和推理。
一些例子包括:
维度类型
在嵌入空间中分配专门的维度,以建模特定的层次知识类别(如类型、属性、时间段等),可以解释向量运算和对称操作。
逻辑规则作为向量方程
将逻辑规则如传递性建模为关系嵌入上的向量方程,使得在查询向量空间时符合一阶逻辑。
v(loves) - v(likes) ≈ v(likes) - v(feels_neutral_about)
实体链接正则化
添加链接损失将相同真实世界实体的向量表示拉近,改善跨表面形式的泛化能力。
时间排序
通过按时间顺序排列实体嵌入来编码时间序列知识,有助于进行时间上的类比推理。
总的来说,通过结构化的归纳偏差——无论是通过类型维度、向量逻辑还是时间排序——美化知识图谱嵌入,使得向量运算更好地符合现实世界约束。这增强了它们解决复杂推理任务的能力,提供了有用的支撑,同时提升了集成语言模型的性能。
核心好处在于将领域知识注入以精确方式定向潜在几何,从而增强连接主义模型在与向量空间互动时的推理能力。通过结构化初始化指导神经引擎操作的原始数据,促进了通过查询进行更系统的组合计算。
互补方法:
首先在查询完整知识图谱之前检索相关的知识图谱嵌入。这种两步法允许高效集中图形操作:
步骤 1:向量嵌入检索
给定自然语言查询,相关的知识图谱嵌入可以通过对索引向量的近似最近邻搜索迅速检索。
例如,使用类似“哪些书讨论了人工智能”的查询,向量搜索会识别出 Book、Topic 和 AI Concept 实体的嵌入。
这在不需要扫描整个图谱的情况下聚焦搜索,改善延迟。嵌入提供了有用的查询扩展信号,用于下一步。
步骤 2:图查询/算法执行
选定的实体嵌入建议有用的切入点和关系,用于结构化的图形查询和算法。
在我们的示例中,Book、Topic 和 AI Concept 的匹配引导了 BOOK-TOPIC 和 TOPIC-CONCEPT 连接的探索。
执行如下查询:
MATCH (b:Book)-[:DISCUSSES]->(t:Topic)-[:OF_TYPE]->(c:Concept)
WHERE c.name = "Artificial Intelligence"
RETURN b
这遍历了与 AI 主题相关的书籍以生成相关结果。
总体而言,高层次流程是:
-
使用向量搜索识别有用的符号句柄
-
执行由这些句柄种子生成的图算法
这种紧密耦合将相似性搜索的强度与多跳推理相结合。
主要好处在于使用快速的初始嵌入匹配来聚焦复杂的图算法。这通过避免对每个查询进行详尽的图扫描,改善了延迟和相关性。这种组合使得对广泛知识的可扩展、高效的语义搜索和推理成为可能。
并行查询多个图谱或相同图谱
大型语言模型(LLMs)展示了令人印象深刻的少量学习能力,能够迅速适应新任务…
towardsdatascience.com
使用多个知识图谱并行的关键思想是为语言模型提供更广泛的结构化知识来源,以便在推理过程中进行借鉴。让我进一步阐述一下其合理性:
-
知识广度:没有任何一个知识图谱可以囊括所有人类在各个领域的积累的知识。通过并行查询多个知识图谱,我们可以最大化语言模型可利用的事实信息。
-
推理多样性:不同的知识图谱可能使用不同的本体、规则、约束等来建模领域。这种知识表示的多样性使语言模型能够接触到更多样的推理模式进行学习。
-
效率:并行查询知识图谱允许同时检索相关信息。这比顺序查询提高了延迟效率。并行搜索允许更快速地收集上下文细节进行分析。
-
鲁棒性:拥有多个知识来源提供了冗余,以防某个特定图谱不可用或缺乏特定推理链的信息。
-
迁移学习:接触到多种推理方法为语言模型提供了更多可迁移的学习示例。这增强了少量学习的适应能力。
总结来说,协调多个知识图谱提供了广泛和多样化的基础知识,以克服单一知识库的局限性。并行检索提高了效率和鲁棒性。跨多样化推理模式的迁移学习也加速了语言模型的适应。这种组合旨在扩展结构化知识注入,实现更接近人类的多功能理解。
大型语言模型作为结构化模块之间流动的语义粘合剂
虽然向量搜索和知识图谱提供了结构化的符号表示,但像 GPT-3 这样的语言模型(LLMs)提供了非结构化但适应性强的语义知识。LLMs 已经展示了卓越的少量学习能力,能够在只有少量示例的情况下快速适应新领域。
这使得 LLMs 非常适合在结构化模块之间充当流动的语义胶——吸收符号知识,解释指令,通过泛化处理边缘情况,并生成上下文输出。它们利用其广泛的参数知识迅速与外部程序和数据表示集成。
因此,我们可以将 LLMs 视为动态的、不断优化的语义层。它们吸收结构化知识的形式,并根据新的输入和查询上下文进行即时适应。LLMs 不是替代符号方法,而是通过快速绑定和上下文响应生成来增强它们。这种流动的整合节省了手动处理所有符号基础和边缘情况的努力。
利用 LLMs 的固有语义泛化能力,使结构化程序能够专注于提供逻辑约束和清晰接口。LLM 随后通过自适应少量学习处理不一致性和空白。这种共生的方法强调了以适应其固有优势的独特推理能力来构建 AI 系统。
结构化知识作为 AI 的基石
关于人工智能的指数级炒作风险让组织追求短视的脚本,承诺快速回报。但有意义的进展需要耐心地培养高质量的知识基础。这体现在结构化知识图谱中,系统地将人类专业知识编码为网络化的表示。
将复杂领域策划成相互关联的实体、约束和规则并非小事。这需要有意的本体工程、严谨的数据治理和迭代的改进。这种渐进性可能会让习惯于快速软件周期的商业领袖感到沮丧。
然而,结构化知识是 AI 缺失的支柱——通过基础信号遏制不受控制的统计模型。知识图谱提供了注入领域知识的支撑结构,同时实现了透明的查询和分析。其可组合的特性也允许与不同系统的互操作。
所有这些都使得企业知识图谱作为战略资产具有了令人信服的理由。正如数据库从灵活的电子表格发展而来,结构的约束最终乘以能力。企业知识图谱中的实体和关系成为推动从对话助手到分析的一切的可靠接触点。
在冲向 AI 前沿的过程中,放任不受约束的模型进行处理是很诱人的。但正如过去每一波自动化浪潮一样,精心编码人类知识以提升机器潜力仍然是至关重要的。如果管理得当,保持这种结构优势在应用中会随着时间的推移而不断增加,巩固市场领导地位。知识推动更好的决策——使得企业知识图谱成为不可或缺的 AI 基础。
由作者使用 Dall-E-3 生成的图像
增强型目标检测:如何有效实现 YOLOv8
原文:
towardsdatascience.com/enhanced-object-detection-how-to-effectively-implement-yolov8-afd1bf6132ae
一本关于在图像、视频和实时摄像头画面中使用 CLI 和 Python 进行目标检测的实用指南。
· 发布在 Towards Data Science · 阅读时间:7 分钟 · 2023 年 3 月 23 日
–
视频由 Camilo Calderón 制作,发布在 Pexels。由作者转换为 GIF 格式。
介绍
目标检测是计算机视觉的一个子领域,主要关注于以一定的置信度识别和定位图像或视频中的对象。被识别的对象通常会用一个边界框进行标注,这为观众提供有关对象性质和在场景中位置的信息。
2015 年,YOLO 的首次发布,即 You Only Look Once,震撼了计算机视觉界,因为它的系统能够以惊人的准确性和速度进行实时目标检测。从那时起,YOLO 经过了几次改进,提高了预测准确性和效率,最终推出了其最新的家族成员:由 Ultralytics 推出的 YOLOv8。
YOLOv8 有五个版本:nano (n)、small (s)、medium (m)、large (l) 和 extra large (x)。它们各自的改进可以通过它们的平均精度均值(mAP)和延迟来展示,这些是通过 COCO val2017 数据集进行评估的。
图片由 Ultralytics 提供。许可证: GNU 通用公共许可证。
与之前的版本相比,YOLOv8 不仅更快更准确,还需要更少的参数来实现其性能,而且,如果这还不够,它还配备了一个直观且易于使用的命令行接口(CLI)以及一个Python 包,为用户和开发者提供了更无缝的体验。
在本文中,我将演示如何使用 CLI 和 Python 将 YOLOv8 应用于静态图像、视频和实时摄像头中的对象检测。
不再赘述,让我们开始吧!
安装
要开始使用 YOLOv8,你只需在终端中运行以下命令:
pip install ultralytics
这将通过ultralytics
pip 包安装 YOLOv8。
图像检测
静态图像中的对象检测在许多领域中都被证明是有用的,如监控、医学成像或零售分析。无论你选择将检测系统应用于哪个领域,YOLOv8 都使这一过程变得极其简单。
下面是我们将进行对象检测的原始图像。
为了运行 YOLOv8,我们将探讨 CLI 和 Python 实现。虽然在这个具体的例子中我们将使用一张jpg
图像,但 YOLOv8 支持多种不同的图像格式。
CLI
假设我们想在图像(我们称之为img.jpg
)上运行超大 YOLOv8x,可以将以下命令输入 CLI:
yolo detect predict model=yolov8x.pt source="img.jpg" save=True
在这里,我们指定以下参数:detect
用于对象检测,predict
用于执行预测任务,model
用于选择模型版本,source
用于提供图像的文件路径,以及save
用于保存带有对象边界框及其预测类别和类别概率的处理图像。
Python
在 Python 中,完全相同的任务可以通过以下直观且低代码的解决方案来完成:
from ultralytics import YOLO
model = YOLO('yolov8x.pt')
results = model('img.jpg', save=True)
无论你使用 CLI 还是 Python,在任何情况下,保存的处理后图像如下所示:
詹姆斯·科尔曼拍摄,发布于Unsplash。经作者使用 YOLOv8 处理。
我们可以清楚地看到它检测到的每个对象周围的边界框,以及它们对应的类别标签和概率。
视频检测
对视频文件进行对象检测与图像文件几乎相同,唯一的区别是源文件格式。与图像一样,YOLOv8 支持多种不同的视频格式作为模型的输入。在我们的案例中,我们将使用一个mp4
文件。
让我们再次查看 CLI 和 Python 实现。为了加快计算速度,我们现在使用 YOLOv8m 模型,而不是超大版本。
CLI
yolo detect predict model=yolov8m.pt source="vid.mp4" save=True
Python
from ultralytics import YOLO
model = YOLO('yolov8m.pt')
results = model('vid.mp4', save=True)
首先,在对vid.mp4
文件进行物体检测之前,让我们检查一下原始文件:
视频由Camilo Calderón提供,发布在Pexels上。作者转换为 GIF 格式。
视频展示了一个繁忙城市的场景,交通繁忙,包括汽车、公交车、卡车和骑自行车的人,以及右侧的一些人显然在等公交车。
使用 YOLOv8 的中等版本处理此文件后,我们得到了以下结果:
视频由Camilo Calderón提供,发布在Pexels上。使用 YOLOv8m 处理并由作者转换为 GIF 格式。
再次看到,YOLOv8m 在准确捕捉场景中的物体方面做得非常好。它甚至能够检测到大整体中的小物体,例如骑自行车背着背包的人。
实时检测
最后,让我们看看在实时网络摄像头喂送中检测物体需要什么。为此,我将使用我的个人网络摄像头,并像之前一样,采用 CLI 和 Python 方法。
为了减少延迟和视频中的滞后,我将使用 YOLOv8 的轻量级 nano 版本。
CLI
yolo detect predict model=yolov8n.pt source=0 show=True
这些参数大多与我们之前在图像和视频文件中看到的一致,不同之处在于source
,它允许我们指定使用的视频源。在我的情况下,它是内置的网络摄像头(0)。
Python
from ultralytics import YOLO
model = YOLO('yolov8n.pt')
model.predict(source="0", show=True)
再次,我们可以通过超低代码解决方案在 Python 中执行相同的任务。
这是 YOLOv8n 在实时网络摄像头上显示的插图:
GIF 由作者制作。使用 YOLOv8n 从网络摄像头录制。
令人印象深刻!尽管视频质量较低且光线条件较差,它仍然相当好地捕捉了物体,甚至检测到了一些背景中的物体,比如左侧的橄榄油和醋瓶以及右侧的水槽。
值得注意的是,尽管这些直观的 CLI 命令和低代码 Python 解决方案是快速开始物体检测任务的好方法,但在自定义配置方面确实存在局限性。例如,如果我们想要配置边框的美观或执行一些简单任务,比如统计和显示在任何给定时间检测到的物体数量,我们就必须使用cv2或supervision等包自行编写自定义实现。
实际上,上面的摄像头视频是使用以下 Python 代码录制的,以调整摄像头的分辨率和自定义定义边界框及其注释。(注意:这主要是为了使上面的 GIF 更具可观赏性。上述的 CLI 和 Python 实现已经足以产生类似的效果。)
import cv2
import supervision as sv
from ultralytics import YOLO
def main():
# to save the video
writer= cv2.VideoWriter('webcam_yolo.mp4',
cv2.VideoWriter_fourcc(*'DIVX'),
7,
(1280, 720))
# define resolution
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
# specify the model
model = YOLO("yolov8n.pt")
# customize the bounding box
box_annotator = sv.BoxAnnotator(
thickness=2,
text_thickness=2,
text_scale=1
)
while True:
ret, frame = cap.read()
result = model(frame, agnostic_nms=True)[0]
detections = sv.Detections.from_yolov8(result)
labels = [
f"{model.model.names[class_id]} {confidence:0.2f}"
for _, confidence, class_id, _
in detections
]
frame = box_annotator.annotate(
scene=frame,
detections=detections,
labels=labels
)
writer.write(frame)
cv2.imshow("yolov8", frame)
if (cv2.waitKey(30) == 27): # break with escape key
break
cap.release()
writer.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
main()
尽管本文中的代码细节超出了讨论范围,但这里有一个很好的参考,采用了类似的方法,如果您有兴趣提升您的目标检测技能:
结论
YOLOv8 不仅在准确性和速度上超越了其前辈,而且通过极易使用的 CLI 和低代码 Python 解决方案显著提升了用户体验。它还提供了五种不同的模型版本,用户可以根据个人需求和对延迟及准确性的容忍度选择合适的版本。
无论您的目标是对静态图像、视频还是实时摄像头进行目标检测,YOLOv8 都可以无缝完成。然而,如果您的应用需要自定义配置,您可能需要依赖其他计算机视觉包,例如 cv2
和 supervision
。
更多资源
喜欢这篇文章吗?
让我们联系吧!您可以在 Twitter 和 LinkedIn 上找到我。
如果您希望支持我的写作,您可以通过 Medium 会员 来实现,这样您可以访问我所有的故事,以及 Medium 上其他成千上万作家的文章。
## 通过我的推荐链接加入 Medium - Thomas A Dorfer
阅读 Thomas A Dorfer 的每一篇文章(以及 Medium 上成千上万的其他作家的文章)。您的会员费用直接支持……
提升 ChatGPT 中 CSV 文件查询性能
基于自定义 CSV 加载器的 LangChain 自查询
·
关注 发表在 Towards Data Science · 9 分钟阅读 · 2023 年 7 月 31 日
–
高级语言模型的出现,如 ChatGPT,为查询表格数据带来了新颖而有前途的方法。然而,由于令牌限制,直接执行查询变得具有挑战性,尤其是在没有像检索器这样的 API 协助的情况下。因此,查询的准确性严重依赖于查询的质量,标准检索器往往无法返回所需的确切信息。
在这篇文章中,我将深入探讨传统检索方法在某些使用案例中失败的原因。此外,我们提出了一种革命性解决方案,即一种自定义的 CSV 数据加载器,它整合了元数据。通过利用LangChain的自查询 API 及新 CSV 数据加载器,我们可以以显著提高的性能和精度提取信息。
有关本文中使用的详细代码,请查看这里的笔记本。我想强调的是,这个笔记本展示了使用 LLM 查询大型表格数据可以实现显著准确性的可能性。
在疾病人口数据集上的检索
我们希望查询作者创建的以下合成 SIR 数据集:我们基于一个简单的SIR 模型模拟 10 个城市在 90 天内的三组人口。为了简单起见,我们假设每个城市的人口范围从 5e3 到 2e4,并且城市之间没有人口流动。此外,我们生成了十个介于 500 到 2000 之间的随机整数作为原始感染人数。
作者提供的图像:10 个城市的疾病人口
表格的形式如下,有五列:“time”表示测量人口的时间,“city”表示测量数据的城市,“susceptible”、“infectious”和“removed”表示人口的三组。为了简单起见,数据已保存为本地 CSV 文件。
time susceptible infectious removed city
0 2018-01-01 8639 8639 0 city0
1 2018-01-02 3857 12338 1081 city0
2 2018-01-03 1458 13414 2405 city0
3 2018-01-04 545 12983 3749 city0
4 2018-01-05 214 12046 5017 city0
我们希望向 ChatGPT 提出与数据集相关的问题。为了让 ChatGPT 与这种表格数据交互,我们按照以下标准步骤使用 LangChain:
-
使用 CSVLoader 加载数据,
-
创建一个 vectorstore(我们这里使用 Chroma)来存储带有 OpenAI 嵌入的嵌入数据,
-
使用检索器返回与给定非结构化查询相关的文档。
你可以使用以下代码实现上述步骤。
# load data fron local path
loader = CSVLoader(file_path=LOCAL_PATH)
data = loader.load()
# Create embedding
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(data, embeddings)
# Create retriever
retriever=vectorstore.as_retriever(search_kwargs={"k": 20})
我们现在可以定义一个ConversationalRetriverChain来查询 SIR 数据集。
llm=ChatOpenAI(model_name="gpt-4",temperature=0)
# Define the system message template
system_template = """The provided {context} is a tabular dataset containing Suspectible, infectious and removed population during 90 days in 10 cities.
The dataset includes the following columns:
'time': time the population was meseaured,
'city': city in which the popoluation was measured,
"susceptible": the susceptible population of the disease,
"infectious": the infectious population of the disease,
"removed": the removed popolation of the disease.
----------------
{context}"""
# Create the chat prompt templates
messages = [
SystemMessagePromptTemplate.from_template(system_template),
HumanMessagePromptTemplate.from_template("{question}")
]
qa_prompt = ChatPromptTemplate.from_messages(messages)
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
qa = ConversationalRetrievalChain.from_llm(llm=llm, retriever=vectorstore.as_retriever(), return_source_documents=False,combine_docs_chain_kwargs={"prompt": qa_prompt},memory=memory,verbose=True)
在上述代码中,我定义了一个对话链,它将使用在上一步中定义的检索器在 SIR 数据集中搜索查询的相关信息,并根据检索到的信息给出答案。为了给 ChatGPT 更清晰的指示,我还给出了一个提示,说明了数据集中所有列的定义。
现在我们来问一个简单的问题:“2018 年 2 月 3 日哪个城市的感染人数最多?”
出乎意料的是,我们的聊天机器人说:“提供的数据集中不包括 2018 年 2 月 3 日的数据。”
这怎么可能?
为什么检索失败了?
为了调查聊天机器人为何未能回答一个其答案仅存在于提供的数据集中的问题,我查看了它用问题“2018 年 2 月 3 日哪个城市的传染病人数最多?”检索到的相关文档。我得到了以下几行:
[Document(page_content=': 31\ntime: 2018-02-01\nsusceptible: 0\ninfectious: 1729\nremoved: 35608\ncity: city3', metadata={'source': 'sir.csv', 'row': 301}),
Document(page_content=': 1\ntime: 2018-01-02\nsusceptible: 3109\ninfectious: 9118\nremoved: 804\ncity: city8', metadata={'source': 'sir.csv', 'row': 721}),
Document(page_content=': 15\ntime: 2018-01-16\nsusceptible: 1\ninfectious: 2035\nremoved: 6507\ncity: city7', metadata={'source': 'sir.csv', 'row': 645}),
Document(page_content=': 1\ntime: 2018-01-02\nsusceptible: 3481\ninfectious: 10873\nremoved: 954\ncity: city5', metadata={'source': 'sir.csv', 'row': 451}),
Document(page_content=': 23\ntime: 2018-01-24\nsusceptible: 0\ninfectious: 2828\nremoved: 24231\ncity: city9', metadata={'source': 'sir.csv', 'row': 833}),
Document(page_content=': 1\ntime: 2018-01-02\nsusceptible: 8081\ninfectious: 25424\nremoved: 2231\ncity: city6', metadata={'source': 'sir.csv', 'row': 541}),
Document(page_content=': 3\ntime: 2018-01-04\nsusceptible: 511\ninfectious: 9733\nremoved: 2787\ncity: city8', metadata={'source': 'sir.csv', 'row': 723}),
Document(page_content=': 24\ntime: 2018-01-25\nsusceptible: 0\ninfectious: 3510\nremoved: 33826\ncity: city3', metadata={'source': 'sir.csv', 'row': 294}),
Document(page_content=': 33\ntime: 2018-02-03\nsusceptible: 0\ninfectious: 1413\nremoved: 35924\ncity: city3', metadata={'source': 'sir.csv', 'row': 303}),
Document(page_content=': 25\ntime: 2018-01-26\nsusceptible: 0\ninfectious: 3173\nremoved: 34164\ncity: city3', metadata={'source': 'sir.csv', 'row': 295}),
Document(page_content=': 1\ntime: 2018-01-02\nsusceptible: 3857\ninfectious: 12338\nremoved: 1081\ncity: city0', metadata={'source': 'sir.csv', 'row': 1}),
Document(page_content=': 23\ntime: 2018-01-24\nsusceptible: 0\ninfectious: 1365\nremoved: 11666\ncity: city8', metadata={'source': 'sir.csv', 'row': 743}),
Document(page_content=': 16\ntime: 2018-01-17\nsusceptible: 0\ninfectious: 2770\nremoved: 10260\ncity: city8', metadata={'source': 'sir.csv', 'row': 736}),
Document(page_content=': 3\ntime: 2018-01-04\nsusceptible: 487\ninfectious: 6280\nremoved: 1775\ncity: city7', metadata={'source': 'sir.csv', 'row': 633}),
Document(page_content=': 14\ntime: 2018-01-15\nsusceptible: 0\ninfectious: 3391\nremoved: 9639\ncity: city8', metadata={'source': 'sir.csv', 'row': 734}),
Document(page_content=': 20\ntime: 2018-01-21\nsusceptible: 0\ninfectious: 1849\nremoved: 11182\ncity: city8', metadata={'source': 'sir.csv', 'row': 740}),
Document(page_content=': 28\ntime: 2018-01-29\nsusceptible: 0\ninfectious: 1705\nremoved: 25353\ncity: city9', metadata={'source': 'sir.csv', 'row': 838}),
Document(page_content=': 23\ntime: 2018-01-24\nsusceptible: 0\ninfectious: 3884\nremoved: 33453\ncity: city3', metadata={'source': 'sir.csv', 'row': 293}),
Document(page_content=': 16\ntime: 2018-01-17\nsusceptible: 1\ninfectious: 1839\nremoved: 6703\ncity: city7', metadata={'source': 'sir.csv', 'row': 646}),
Document(page_content=': 15\ntime: 2018-01-16\nsusceptible: 1\ninfectious: 6350\nremoved: 20708\ncity: city9', metadata={'source': 'sir.csv', 'row': 825})]
令人惊讶的是,尽管我明确要求了解 2018 年 2 月 3 日发生了什么,但没有返回该日期的任何行。由于该日期的信息从未发送给 ChatGPT,因此当然毫无疑问它无法回答这样的问题。
深入研究检索器的源代码,我们可以看到get_relevant_dcouments默认调用similarity_search。该方法根据计算的距离度量(默认使用余弦距离)返回前 n 个片段(默认 4 个,但我在代码中将数量设置为 20),这些片段的距离范围从 0 到 1,用于测量查询向量与文档片段向量之间的“相似性”。
回到 SIR 数据集,我们注意到每行几乎讲述了相同的故事:哪个日期、哪个城市、以及多少人被标记为哪个组。毫不奇怪,代表这些行的向量彼此相似。快速检查相似度得分发现很多行的得分接近 0.29。
因此,相似度得分不足以区分行与查询的相关性:这在表格数据中总是如此,因为行之间没有显著差异。我们需要更强的过滤器来处理元数据。
带有自定义元数据的 CSVLoader
显然,聊天机器人的性能提升在很大程度上依赖于检索器的效率。为此,我们首先定义了一个自定义的 CSVLoader,它可以将元数据与检索器进行通信。
我们编写了以下代码:
class MetaDataCSVLoader(BaseLoader):
"""Loads a CSV file into a list of documents.
Each document represents one row of the CSV file. Every row is converted into a
key/value pair and outputted to a new line in the document's page_content.
The source for each document loaded from csv is set to the value of the
`file_path` argument for all doucments by default.
You can override this by setting the `source_column` argument to the
name of a column in the CSV file.
The source of each document will then be set to the value of the column
with the name specified in `source_column`.
Output Example:
.. code-block:: txt
column1: value1
column2: value2
column3: value3
"""
def __init__(
self,
file_path: str,
source_column: Optional[str] = None,
metadata_columns: Optional[List[str]] = None,
content_columns: Optional[List[str]] =None ,
csv_args: Optional[Dict] = None,
encoding: Optional[str] = None,
):
# omitted (save as original code)
self.metadata_columns = metadata_columns # < ADDED
def load(self) -> List[Document]:
"""Load data into document objects."""
docs = []
with open(self.file_path, newline="", encoding=self.encoding) as csvfile:
# omitted (save as original code)
# ADDED CODE
if self.metadata_columns:
for k, v in row.items():
if k in self.metadata_columns:
metadata[k] = v
# END OF ADDED CODE
doc = Document(page_content=content, metadata=metadata)
docs.append(doc)
return docs
为节省空间,我省略了与原始 API 相同的代码,仅包含了主要用于将需要特别注意的某些列写入元数据的附加几行代码。确实,在上面的打印数据中,你可以注意到两个部分:页面内容和元数据。标准 CSVLoader 将表格的所有列写入页面内容,只将数据资源和行号写入元数据。定义的“MetaDataCSVLoader”允许我们将其他列写入元数据。
现在我们重新创建向量存储,步骤与上述章节相同,只是数据加载器中添加了两个元数据列“time”和“city”。
# Load data and set embeddings
loader = MetaDataCSVLoader(file_path="sir.csv",metadata_columns=['time','city']) #<= modified
data = loader.load()
自查询元数据通知的向量存储
现在我们准备使用 LangChain 的SelfQuerying API:
根据 LangChain 的文档:自查询检索器顾名思义,就是可以对自身进行查询的检索器。… 这使得检索器不仅可以使用用户输入的查询与存储文档的内容进行语义相似性比较,还可以从用户查询中提取关于存储文档的元数据的过滤器,并执行这些过滤器。
图片来源于 LangChain:自查询示意图
你现在可以理解为什么我在上一章强调元数据:这是基于元数据,ChatGPT 或其他 LLM 能够在其上构建过滤器,以从数据集中获取最相关的信息。我们使用以下代码构建这样的自查询检索器,通过描述元数据和文档内容描述来构建一个性能良好的过滤器,以提取准确的信息。特别地,我们给检索器提供一个metadata_field_info,指定我们希望检索器更多关注的两列的类型和描述。
llm=ChatOpenAI(model_name="gpt-4",temperature=0)
metadata_field_info=[
AttributeInfo(
name="time",
description="time the population was meseaured",
type="datetime",
),
AttributeInfo(
name="city",
description="city in which the popoluation was measured",
type="string",
),
]
document_content_description = "Suspectible, infectious and removed population during 90 days in 10 cities "
retriever = SelfQueryRetriever.from_llm(
llm, vectorstore, document_content_description, metadata_field_info, search_kwargs={"k": 20},verbose=True
)
我们现在可以定义一个类似的ConversationalRetriverChain来查询 SIR 数据集,但这次使用SelfQueryRetriever。让我们看看当我们问同样的问题时会发生什么:“2018 年 2 月 3 日哪个城市传染人数最多?”
聊天机器人说:“2018 年 2 月 3 日传染人数最多的城市是 city3,传染人数为 1413。”
各位女士们先生们,结果是正确的!聊天机器人在使用更好的检索器时表现更好!
这次查看检索器返回了哪些相关文档是没有害处的,结果是:
[Document(page_content=': 33\ntime: 2018-02-03\nsusceptible: 0\ninfectious: 1413\nremoved: 35924\ncity: city3', metadata={'source': 'sir.csv', 'row': 303, 'time': '2018-02-03', 'city': 'city3'}),
Document(page_content=': 33\ntime: 2018-02-03\nsusceptible: 0\ninfectious: 822\nremoved: 20895\ncity: city4', metadata={'source': 'sir.csv', 'row': 393, 'time': '2018-02-03', 'city': 'city4'}),
Document(page_content=': 33\ntime: 2018-02-03\nsusceptible: 0\ninfectious: 581\nremoved: 14728\ncity: city5', metadata={'source': 'sir.csv', 'row': 483, 'time': '2018-02-03', 'city': 'city5'}),
Document(page_content=': 33\ntime: 2018-02-03\nsusceptible: 0\ninfectious: 1355\nremoved: 34382\ncity: city6', metadata={'source': 'sir.csv', 'row': 573, 'time': '2018-02-03', 'city': 'city6'}),
Document(page_content=': 33\ntime: 2018-02-03\nsusceptible: 0\ninfectious: 496\nremoved: 12535\ncity: city8', metadata={'source': 'sir.csv', 'row': 753, 'time': '2018-02-03', 'city': 'city8'}),
Document(page_content=': 33\ntime: 2018-02-03\nsusceptible: 0\ninfectious: 1028\nremoved: 26030\ncity: city9', metadata={'source': 'sir.csv', 'row': 843, 'time': '2018-02-03', 'city': 'city9'}),
Document(page_content=': 33\ntime: 2018-02-03\nsusceptible: 0\ninfectious: 330\nremoved: 8213\ncity: city7', metadata={'source': 'sir.csv', 'row': 663, 'time': '2018-02-03', 'city': 'city7'}),
Document(page_content=': 33\ntime: 2018-02-03\nsusceptible: 0\ninfectious: 1320\nremoved: 33505\ncity: city2', metadata={'source': 'sir.csv', 'row': 213, 'time': '2018-02-03', 'city': 'city2'}),
Document(page_content=': 33\ntime: 2018-02-03\nsusceptible: 0\ninfectious: 776\nremoved: 19753\ncity: city1', metadata={'source': 'sir.csv', 'row': 123, 'time': '2018-02-03', 'city': 'city1'}),
Document(page_content=': 33\ntime: 2018-02-03\nsusceptible: 0\ninfectious: 654\nremoved: 16623\ncity: city0', metadata={'source': 'sir.csv', 'row': 33, 'time': '2018-02-03', 'city': 'city0'})]
你可能会立刻注意到在检索到的文档中现在有“时间”和“城市”这些“元数据”。
结论
在这篇博客文章中,我探讨了 ChatGPT 在查询 CSV 格式数据集时的局限性,以 10 个城市的 SIR 数据集在 90 天内为例。为了应对这些局限性,我提出了一种新方法:一种感知元数据的 CSV 数据加载器,使我们能够利用自查询 API,显著提高聊天机器人的准确性和性能。
使用实时先进物体识别技术构建乐高技术件分类器
·
关注 发布于 Towards Data Science · 9 分钟阅读 · 2023 年 11 月 2 日
–
在我于 Nullspace Robotics实习期间,我有幸参与了一个提升公司能力的项目。我们集成了物体检测和机器学习图像识别,开发了一台能够实时分类乐高技术件的机器。
在这篇博客文章中,我将带你了解遇到的挑战以及我们如何成功完成这个项目。
阿莫斯·科赫和我在 22 年夏天教学生编程和机器人技术,同时为 Nullspace 工作。你可以在文章下方的链接找到我们。
Nullspace Robotics 是新加坡领先的中小学机器人和编程教育提供商。他们的大部分操作涉及使用乐高 Technic 部件构建机器人,这些部件被分类到特定的托盘中。你可以想象,让一个充满精力的 8 岁小孩帮忙把积木放回托盘是一个噩梦般的任务,而他们只想做更多的东西。
Nullspace 让我们制作一台可以将乐高 Technic 积木分类到特定类别的机器,以最小化人工干预,从而解决进行机器人教学时的关键效率挑战之一。
确定挑战
该项目涉及三个主要部分:实时物体和运动检测、图像识别以及机器的硬件建设。由于实习的时间限制,我们主要关注了前两个项目,这涉及到项目的软件方面。
一个关键挑战是识别移动部件并在同一帧内确定它们的位置。我们考虑了两种方法:将机器学习图像识别集成到物体检测相机中,或保持过程分开。
最终,我们决定将物体检测和识别分开。这种方法首先在检测到物体后捕捉合适的图片,然后运行模型对图像进行分类。将这些过程整合在一起需要在几乎每一帧上运行模型,以对每个检测到的物体进行分类。将它们分开消除了模型需要保持持续处理模式的需求,从而确保了操作更加流畅和计算更高效。
物体检测
我们借鉴了文章下方引用的项目中的想法,实施了我们的物体/运动检测程序,并将其定制为乐高积木。
在我们的案例中,我们使用了类似的运动检测概念,因为我们的机器将涉及一个统一颜色的传送带系统,因此检测到的任何运动都是由于乐高积木在传送带上移动。
我们对所有帧应用了高斯模糊以及其他图像处理技术,并与之前的帧进行比较。进一步处理用于隔离(绘制边界框)造成运动的物品,如下所示:
for f in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True):
frame = f.array # grab the raw NumPy array representing the image
text = "No piece" # initialize the occupied/unoccupied text
# resize the frame, convert it to grayscale, and blur it
frame = imutils.resize(frame, width=500)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (21, 21), 0)
# if the average frame is None, initialize it
if avg is None:
print("[INFO] starting background model...")
avg = gray.copy().astype("float")
rawCapture.truncate(0)
continue
# accumulate the weighted average between the current frame and
# previous frames, then compute the difference between the current
# frame and running average
cv2.accumulateWeighted(gray, avg, 0.5)
frameDelta = cv2.absdiff(gray, cv2.convertScaleAbs(avg))
# threshold the delta image, dilate the thresholded image to fill
# in holes, then find contours on thresholded image
thresh = cv2.threshold(frameDelta, conf["delta_thresh"], 255,
cv2.THRESH_BINARY)[1]
thresh = cv2.dilate(thresh, None, iterations=2)
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
# loop over the contours
for c in cnts:
# if the contour is too small, ignore it
if cv2.contourArea(c) < conf["min_area"]:
continue
# compute the bounding box for the contour, draw it on the frame,
# and update the text
(x, y, w, h) = cv2.boundingRect(c)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
piece_image = frame[y:y+h,x:x+w]
text = "Piece found"
# cv2.imshow("Image", image)
为了确保运动实际上是由乐高积木造成的,我们使用了一个运动计数器来评估运动检测的稳定性,该计数器检查了在得出运动确实是由于乐高积木而非杂音之前,是否在一定数量的帧内检测到了运动。最终图像被保存并输入到我们的 CNN 中进行分类。
if text == "Piece found":
# to save images of bounding boxes
motionCounter += 1
print("motionCounter= ", motionCounter)
print("image_number= ", image_number)
# Save image if motion is detected for 8 or more successive frames
if motionCounter >= 8:
image_number +=1
image_name = str(image_number)+"image.jpg"
cv2.imwrite(os.path.join(path, image_name), piece_image)
motionCounter = 0 #reset the motion counter
# classify the saved image with our model, see below
创建模型
建立数据集
我们自己创建了图像数据集,而不是使用在线找到的 Lego Technic 零件图像,因为我们想要模拟模型最终检测和分类零件的条件。因此,我们设计了一个简单的传送带系统,完全使用 Lego Technic 零件!然后我们将其连接到 Lego Spike Prime 电机,以保持传送带的运转。
设计模型架构
为了解决挑战的核心问题,我调整了我在 Aladdinpersson 的 GitHub 仓库中找到的一个机器学习模型。这个模型采用了从 128 到 64 再到 32 再到 16 的卷积层序列,这种架构设计旨在提高图像识别能力。
我们没有使用预训练模型,而是设计了自己的卷积神经网络,因为:
-
我们不需要特别深的特征提取来处理我们的图像。
-
我们希望保持模型的小巧并降低其复杂性,同时减少运行模型的计算成本。这将使 CNN 在 Pi 上以 tflite 模型更高效地运行。
数据归一化是确保一致训练准确性的关键步骤,特别是考虑到不同图像由于光照差异而捕获的值范围不同。
在这个模型中,诸如 ReLU、dense、softmax 和 flatten 等不同层发挥了关键作用。例如,ReLU 激活对于图像分类至关重要,因为它减轻了图像识别中的梯度消失问题。另一方面,Dense 层在 Tensorflow 模型中是标准配置,有助于实现密集连接的神经网络。Softmax 激活用于计算数据集中每个类别的概率。
对于损失函数,我们使用了 Keras 的稀疏类别交叉熵,这是多类分类任务的合适选择。我们使用了以其效率著称的 Keras Adam 优化器来微调模型。
训练和优化
训练轮次被精心选择,以在训练和过拟合之间取得平衡,倾向于选择低于 200 的轮次,以确保模型性能最佳。为了加快模型训练,我们利用了 Google Colab,它提供了 GPU 资源,相比我们自己的笔记本电脑,训练速度显著更快。
完整的模型架构如下所示:
data_augmentation = keras.Sequential([
layers.RandomFlip("horizontal",
input_shape=(img_height,
img_width,
1)),
layers.RandomRotation(0.2),
layers.RandomZoom(0.1),
])
model = keras.Sequential(
[
data_augmentation,
layers.Rescaling(1./255, input_shape = (img_height,img_width,1)), #normalize the data input
layers.Conv2D(128, 3, padding="same", activation='relu'),
layers.MaxPooling2D(pool_size=(2,2)),
layers.Conv2D(64, 3, padding="same", activation='relu'), #should this be 16 or 32 units? try with more data
layers.MaxPooling2D(pool_size=(2,2)),
layers.Conv2D(32, 3, padding="same", activation='relu'),
layers.MaxPooling2D(pool_size=(2,2)),
layers.Conv2D(16, 3, padding="same", activation='relu'),
layers.MaxPooling2D(pool_size=(2,2)),
layers.Dropout(0.1),
layers.Flatten(),
layers.Dense(10,activation = 'relu'),
layers.Dense(7,activation='softmax'), # number of output classes
]
)
model.compile(
optimizer=keras.optimizers.Adam(),
loss=[keras.losses.SparseCategoricalCrossentropy(from_logits=False),],
metrics=["accuracy"],
)
model_history = model.fit(x_train, y_train, epochs=200, verbose=2, validation_data=(x_test,y_test), batch_size=25) #i think 25/32 is the best batch size
选择架构
在大多数常见的 CNN 架构中,过滤器的数量会增加,以尝试在更高层捕捉更复杂的特征。然而,对于区分我们的 Lego 零件,类别之间的相似度很高,我们需要网络寻找如弯曲和孔洞等特定特征。我认为,在更深层中使用较少的过滤器可能有助于专注于这些较少的细微差别,而不是查看可能不利于区分零件的多个特征。
我们测试了两种架构,一种是减少滤波器,另一种是增加滤波器,结果是减少滤波器的模型表现显著更好。因此,减少滤波器的数量可以让网络专注于关键部分,减少复杂特征图中的噪声。
当然,这取决于你的使用案例和数据集中的特征。例如,人脸识别需要更复杂的特征图,因此增加滤波器的方法可能效果更好。
模型结果
该模型使用 6000 张图像,涵盖 7 类乐高技术块进行训练。最终验证准确率达到了93%。下面展示了训练过程的图示以及用于评估性能的混淆矩阵:
在树莓派上实施模型
在树莓派上运行神经网络的最有效方法是使用 tflite(tensorflow lite)模型。我们将模型保存到本地,然后加载到树莓派上。
from tflite_runtime.interpreter import Interpreter
# Load TFLite model and allocate tensors.
interpreter = Interpreter(model_path="lego_tflite_model/detect.tflite") # insert path to the tflite model
interpreter.allocate_tensors()
继续使用上面提到的运动计数器循环,将适当的图像输入神经网络进行分类:
# continuing from if text == "Piece found":
# Open the image, resize it and increase its contrast
input_image = Image.open('lego-pieces/'+ image_name)
input_image = ImageOps.grayscale(input_image)
input_image = input_image.resize((128,128))
input_data = img_to_array(input_image)
input_data = increase_contrast_more(input_data)
input_data.resize(1,128,128,1)
# Pass the np.array of the image through the tflite model. This will output a probablity vector
interpreter.set_tensor(input_details[0]['index'], input_data)
interpreter.invoke()
output_data = interpreter.get_tensor(output_details[0]['index'])
# Get the index of the highest value in the probability vector.
# This index value will correspond to the labels vector created above (i.e index value 1 will mean the object is most likely labels[1])
category_number = np.argmax(output_data[0])
# Return the classification label of the image
classification_label = labels[category_number]
print("Image Label for " + image_name + " is :", classification_label)
else:
motionCounter = 0 # reset motion counter to look for new objects
灵活性是一个关键考虑因素。运动计数器可以根据捕捉图像以构建数据集的过程或设置图像分类时的捕捉阈值进行调整,从而提升系统的多功能性。
演示
我们努力的最终成果是展示系统的整体准确性,辅以捕捉其操作的照片和视频。传送带设置(如上图)是此次演示的关键部分:
未来工作及改进方向
软件:未来的扩展还将包括在操作中加入质量检查模型,以确保用于分类部件的图像合适。
硬件:该模型无疑将受益于更高级的相机以获得更高质量的图像。此外,临时建造的传送带系统需要扩展以容纳更多部件。还需制定并实施一种方法来分离多个乐高部件,确保相机帧中每次只显示一个部件。网上有类似的项目详细介绍了可能的方法。
结论
我在 Nullspace Robotics 的经历是我首次尝试为实际用途构建自己的神经网络。在过去的培训课程中设计模型的经历与创建用于实际生产的模型完全不同,我们需要考虑资源、使用目的,并找到如何调整数据集和模型以适应我们需求的方法。我期待继续我的机器学习之旅,并利用最新的 AI 技术构建更具创新性的解决方案。
我想感谢 Nullspace 给我提供了这个项目的机会,我很期待看到公司在推进机器人教育的边界时接下来会有什么发展。
查看 Github 或 HuggingFace 上的完整代码库,获取代码、数据集图像以及更多项目信息:
Github: github.com/magichampz/lego-sorting-machine-ag-ak/
HuggingFace: huggingface.co/magichampz
认识开发者
Aveek: www.linkedin.com/in/aveekg00/
Amos: www.linkedin.com/in/ak726/
参考文献:
[## 使用 Python 和 OpenCV 进行基本运动检测和跟踪 — PyImageSearch
在本教程中,我将向你展示如何使用 Python 和 OpenCV 执行基本的运动检测和跟踪。了解如何……
pyimagesearch.com](https://pyimagesearch.com/2015/05/25/basic-motion-detection-and-tracking-with-python-and-opencv/?source=post_page-----7ba5d70c9902--------------------------------) ## 使用 OpenCV 检测运动 — 初学者图像分析
如何使用 OpenCV 检测和分析移动物体
towardsdatascience.com [## Machine-Learning-Collection/ML/TensorFlow/Basics/tutorial15-customizing-modelfit.py 在主分支 ·…
一个关于机器学习和深度学习的资源……
github.com](https://github.com/aladdinpersson/Machine-Learning-Collection/blob/master/ML/TensorFlow/Basics/tutorial15-customizing-modelfit.py?source=post_page-----7ba5d70c9902--------------------------------)
未使用的内容
除非另有说明,所有图片均为作者提供
增强 Python 文档:逐步指南以链接源代码
·发表于 Towards Data Science ·4 分钟阅读·2023 年 12 月 7 日
–
你阅读了这个类方法的描述,但仍然不了解发生了什么。如果你能快速阅读源代码就好了…
弥合文档与代码之间的差距:简化 Python 学习
Python 的强大不仅体现在它的简洁和高效,还在于其庞大的社区和丰富的文档。但是,如果你能够使这些文档变得更加互动和信息丰富呢?今天,我将带你通过将你的 Sphinx 生成的 Python 文档直接链接到 GitHub 上的相应源代码来增强文档。
作者使用 Dalle-3 创建的图像。提示“抽象图像,浅奶油色画布上的黑色水彩,展示与机器内部工作相关的手写片段,带有细箭头”。
第一步:使用 Sphinx 进行文档编写
当我们在 Python 代码中编写适当的文档字符串时,我们为生成全面的 API 文档奠定了基础。像 Sphinx 的 autodoc
和 automodule
这样的工具非常适合从我们的模块、类和函数中提取这些文档字符串。然而,它们通常未能提供直接链接到源代码的功能。
如果你需要开始使用 Sphinx,请查看这些教程:
在教程的上一部分中,你手动在 Sphinx 中记录了一个 Python 函数。然而,描述…
www.sphinx-doc.org [## 使用 Sphinx 构建文档项目 - Sphinx 和文档的简介]
为了本教程的目的,我们将使用 reStructuredText 编写文档。如果你希望使用…
sphinx-intro-tutorial.readthedocs.io
第 2 步:设置 Sphinx linkcode
要添加此功能,首先我们需要修改 Sphinx 配置。这包括在文档源的 conf.py
文件中将 sphinx.ext.linkcode
添加到扩展列表中:
# docs/conf.py
extensions = [
...,
"sphinx.ext.linkcode",
]
...
第 3 步:基本的 Linkcode 实现
我们的下一步是定义 linkcode_resolve
函数。这个函数负责确定文档应该指向的 URL:
# docs/conf.py
...
def linkcode_resolve(domain, info):
if domain != "py":
return None
if not info["module"]:
return None
filename = "src/" + info["module"].replace(".", "/")
github_repo = "https://github.com/username/my-package"
return f"{github_repo}/blob/main/{filename}.py"
在这里,我们只是指向 GitHub 仓库中的文件,而不是特定的代码行。
第 4 步:查找行号
获取模块对象
首先,你需要获取定义目标类、方法、属性或函数(以下简称“对象”)的模块对象。在 Python 中,每个加载的模块都存储在一个名为 sys.modules
的字典中。你需要访问这个字典,以根据其名称检索模块对象:
module = sys.modules.get(info[“module”])
遍历完全限定名称
接下来,你需要遍历对象的完全限定名称。完全限定名称包括访问对象所需的所有层级,例如 module.class.method
。这个遍历过程帮助你深入模块结构,找到你需要的确切对象:
obj = module
for part in info[“fullname”].split(“.”):
obj = getattr(obj, part, None)
使用 Inspect 模块查找行号
最后,你使用 inspect
模块找到源代码中定义该对象的行号:
line = inspect.getsourcelines(obj)[1]
创建一个函数来检索行号
为了使函数适用于所有情况,我们需要添加一些额外的检查:
def get_object_line_number(info):
"""Return object line number from module."""
try:
module = sys.modules.get(info["module"])
if module is None:
return None
# walk through the nested module structure
obj = module
for part in info["fullname"].split("."):
obj = getattr(obj, part, None)
if obj is None:
return None
return inspect.getsourcelines(obj)[1]
except (TypeError, OSError):
return None
总之,这一步骤涉及定位目标对象所在的模块,遍历模块结构以找到确切的对象(无论是类、方法、属性还是函数),然后使用 inspect
模块找到该对象在源代码中定义的行号。
第 6 步:完成 Linkcode 解析
我们将行号检索集成到 linkcode_resolve
函数中:
def linkcode_resolve(domain, info):
...
line = get_object_line_number(info)
if line is None:
return None
return f"{github_repo}/blob/{github_branch}/{filename}.py#L{line}"
这种方法使你的文档能够提供指向源代码中特定行的直接链接,从而提高文档的清晰度和实用性。
额外:ReadTheDocs 的分支适配
对于使用 ReadTheDocs 的用户,你可以调整这个函数以参考不同的分支(如 main
或 develop
)。那么如何构建两个不同的文档来指向这两个分支呢?
当 ReadTheDocs 构建文档时,它使用自己的环境,其中包含一个名为 READTHEDOCS_VERSION
的变量,通常为 ‘stable’ 或 ‘latest’。我添加了一个名为 ‘develop’ 的构建,它指向我的 Git 仓库中的同名分支。
我们可以在 linkcode_resolve
函数中添加以下内容:
def linkcode_resolve(domain, info):
...
rtd_version = os.getenv("READTHEDOCS_VERSION", "latest")
github_branch = "develop" if rtd_version == "develop" else "main"
return f"{github_repo}/blob/{github_branch}/{filename}.py#L{line}"
请注意,如果在本地构建,或者更一般地在未定义READTHEDOCS_VERSION
的环境中,默认链接的分支将是main
。
结论
有了这个设置,你的 Sphinx 文档现在将直接链接到源代码,大大提升了其实用性和用户体验。这一小小的增加可以显著提高文档的可用性和有效性,使其成为新手和经验丰富的开发者的宝贵工具。
记住,编码的旅程不仅仅是解决问题,也关乎分享知识和解决方案。所以,如果你觉得这个教程对你有帮助,我鼓励你传播这个消息,帮助其他人进行他们的编码冒险。
祝编码愉快,下次见!
在我的 Gumroad 个人资料 或 个人网站上发现更多我的作品和独家内容。
免责声明:我与 Sphinx 没有任何关系,我只是觉得它是一个很棒的开源工具。
提升 Haystack 中的 RAG 流水线:引入 DiversityRanker 和 LostInTheMiddleRanker
最新的排名器如何优化 LLM 上下文窗口在检索增强生成(RAG)流水线中的利用
·
关注 发表在 Towards Data Science · 8 分钟阅读 · 2023 年 8 月 8 日
–
最近在自然语言处理(NLP)和长文问答(LFQA)方面的改进,几年前听起来简直像科幻小说中的内容。谁能想到现在我们会有能够像专家一样精确回答复杂问题的系统,同时从庞大的资源库中即时合成这些答案?LFQA 是一种检索增强生成(RAG),最近取得了显著进展,利用了大型语言模型(LLMs)最优秀的检索和生成能力。
但如果我们能进一步优化这个设置呢?如果我们可以优化 RAG 如何选择和利用信息以提升其性能呢?本文介绍了两个创新组件,旨在通过基于最新研究和我们的经验,从 LFQA 中提取具体示例来改善 RAG——DiversityRanker 和 LostInTheMiddleRanker。
将 LLM 的上下文窗口视为一顿美味的餐点,其中每段文字都是一种独特且富有风味的配料。就像一件精美的烹饪作品需要多样化的高质量配料一样,LFQA 问答也要求上下文窗口充满高质量、多样化、相关且不重复的段落。
在 LFQA 和 RAG 的复杂世界中,最大限度地利用 LLM 的上下文窗口至关重要。任何浪费的空间或重复的内容都会限制我们提取和生成答案的深度和广度。合理布置上下文窗口的内容是一项微妙的平衡工作。本文提出了掌握这一平衡的全新方法,这将提升 RAG 提供准确、全面响应的能力。
让我们探索这些令人兴奋的进展以及它们如何改善 LFQA 和 RAG。
背景
Haystack 是一个开源框架,提供实践 NLP 构建者的端到端解决方案。它支持从问答和语义文档搜索到 LLM 代理等广泛的用例。其模块化设计允许集成最先进的 NLP 模型、文档存储和当今 NLP 工具箱中所需的各种其他组件。
Haystack 中的一个关键概念是管道的思想。管道表示一个特定组件执行的一系列处理步骤。这些组件可以执行各种类型的文本处理,允许用户通过定义数据如何在管道中流动以及执行处理步骤的节点顺序,轻松创建强大且可定制的系统。
在基于网络的长篇问答中,管道发挥了关键作用。它从 WebRetriever 组件开始,该组件在网络上搜索和检索与查询相关的文档,自动将 HTML 内容剥离成原始文本。但一旦我们获取了与查询相关的文档,我们如何充分利用它们?我们如何填充 LLM 的上下文窗口以最大化答案的质量?如果这些文档尽管高度相关,但却重复且数量众多,有时会溢出 LLM 上下文窗口,该怎么办?
今天我们将介绍的组件正是在这里发挥作用的——DiversityRanker 和 LostInTheMiddleRanker。它们的目标是解决这些挑战并改善 LFQA/RAG 管道生成的答案。
DiversityRanker 增强了上下文窗口中选定段落的多样性。LostInTheMiddleRanker 通常在流水线中位于 DiversityRanker 之后,有助于减轻模型在长上下文窗口中必须访问相关信息时观察到的性能下降。接下来的部分将深入探讨这两个组件,并展示它们在实际使用案例中的效果。
DiversityRanker
DiversityRanker 是一个新型组件,旨在增强 RAG 流水线中上下文窗口选定段落的多样性。它基于一个原则,即多样化的文档集可以提高 LLM 生成答案的广度和深度。
图 1:DiversityRanker 算法文档排序过程的艺术表现,由 MidJourney 提供。请注意,此可视化更多是说明性的,而非精确的。
DiversityRanker 使用句子变换器来计算文档之间的相似度。句子变换器库提供了强大的嵌入模型,用于创建句子、段落甚至整个文档的有意义表示。这些表示或嵌入捕捉了文本的语义内容,使我们能够测量两段文本的相似性。
DiversityRanker 使用以下算法处理文档:
1. 它首先使用句子变换器模型计算每个文档和查询的嵌入。
2. 然后选择语义上最接近查询的文档作为第一个选择的文档。
3. 对于每个剩余的文档,它计算与已经选择的文档的平均相似度。
4. 然后选择平均上与已经选择的文档最不相似的文档。
5. 这个选择过程持续进行,直到所有文档都被选择,结果是一个文档列表,从对整体多样性贡献最大的文档到贡献最小的文档。
需要记住的技术说明:DiversityRanker 使用贪婪的局部方法来选择下一个文档,这可能无法找到文档的最优整体顺序。DiversityRanker 更注重多样性而非相关性,因此它应该在 TopPSampler 或其他更注重相关性的相似性排序器等组件之后放置在流水线中。通过在选择最相关文档的组件之后使用它,我们确保从已经相关的文档池中选择多样化的文档。
LostInTheMiddleRanker
LostInTheMiddleRanker 优化了所选文档在 LLM 上下文窗口中的布局。这个组件是解决最近研究中识别出的一个问题的一种方法[1],该研究表明 LLM 难以关注长上下文中间的相关段落。LostInTheMiddleRanker 将最佳文档交替放置在上下文窗口的开头和结尾,使 LLM 的注意力机制更容易访问和使用它们。为了理解 LostInTheMiddleRanker 如何排序给定的文档,可以想象一个简单的例子,其中文档由从 1 到 10 的单个数字按升序排列。LostInTheMiddleRanker 将这十个文档按以下顺序排序:[1 3 5 7 9 10 8 6 4 2]。
尽管这项研究的作者专注于一个问答任务——从文本中提取相关的答案片段——我们推测 LLM 的注意力机制在生成答案时,也会更容易关注上下文窗口开头和结尾的段落。
图 2. LLM 在提取上下文中间的答案时遇到困难,改编自 Liu 等(2023)[1]
LostInTheMiddleRanker 最适合作为 RAG 管道中的最后一个排名器,因为所给的文档已经基于相似性(相关性)进行选择,并按多样性排序。
在管道中使用新的排名器
在本节中,我们将探讨 LFQA/RAG 管道的实际应用案例,重点是如何集成 DiversityRanker 和 LostInTheMiddleRanker。我们还将讨论这些组件如何相互作用以及与管道中的其他组件的互动。
管道中的第一个组件是 WebRetriever,它使用程序化搜索引擎 API(如 SerperDev、Google、Bing 等)从网络中检索查询相关的文档。检索到的文档首先去除 HTML 标签,转换为原始文本,并可选择性地预处理成较短的段落。然后,这些文档会传递给 TopPSampler 组件,该组件根据与查询的相似性选择最相关的段落。
在 TopPSampler 选择相关段落集之后,它们会传递给 DiversityRanker。DiversityRanker 则根据段落的多样性对其进行排序,减少 TopPSampler 排序文档的重复性。
选定的文档随后传递给 LostInTheMiddleRanker。如前所述,LostInTheMiddleRanker 将最相关的段落放置在上下文窗口的开头和结尾,同时将排名最差的文档推到中间。
最终,合并的段落会传递给 PromptNode,PromptNode 将 LLM 调整为基于这些选定的段落回答问题。
图 3. LFQA/RAG 管道 — 作者提供的图像
新排序器已经合并到 Haystack 的主分支中,并将在 2023 年 8 月底的 1.20 版本中发布。我们在项目的示例文件夹中添加了新的 LFQA/RAG 管道演示。
演示展示了 DiversityRanker 和 LostInTheMiddleRanker 如何轻松集成到 RAG 管道中,以提高生成答案的质量。
案例研究
为了展示包含两个新排序器的 LFQA/RAG 管道的有效性,我们将使用一个包含半打问题的小样本,这些问题需要详细的回答。问题包括:“俄罗斯和波兰长期敌对的主要原因是什么?”,“全球和地方尺度上气候变化的主要原因是什么?”等等。要很好地回答这些问题,LLM 需要广泛的历史、政治、科学和文化来源,这使得它们非常适合我们的用例。
比较 RAG 管道生成的答案与两个新排序器(优化管道)以及没有这些排序器的管道(未优化管道)会涉及复杂的评估,需要人工专家的判断。为了简化评估并主要评估 DiversityRanker 的效果,我们改为计算注入 LLM 上下文中的上下文文档的平均成对余弦距离。我们将两个管道的上下文窗口大小限制为 1024 个词。通过运行这些示例 Python 脚本[2],我们发现优化管道中注入 LLM 上下文的文档的平均成对余弦距离增加了约 20–30%[3]。这种成对余弦距离的增加本质上意味着所使用的文档更具多样性(而且重复性更少),从而为 LLM 提供了更广泛和丰富的段落供其回答参考。我们将把对 LostInTheMiddleRanker 及其对生成答案的影响的评估留到我们即将发布的文章中。
结论
我们探索了 Haystack 用户如何通过使用两个创新排序器:DiversityRanker 和 LostInTheMiddleRanker 来增强他们的 RAG 管道。
DiversityRanker 确保 LLM 的上下文窗口中填充了多样且不重复的文档,为 LLM 提供了更广泛的段落以便综合答案。同时,LostInTheMiddleRanker 优化了最相关段落在上下文窗口中的位置,使得模型更容易访问和利用最支持的文档。
我们的小案例研究通过计算注入 LLM 上下文窗口中的文档的平均成对余弦距离,确认了 DiversityRanker 的有效性,比较了优化的 RAG 管道(使用两个新排序器)和未优化管道(未使用排序器)。结果显示,优化的 RAG 管道使得平均成对余弦距离增加了约 20–30%。
我们已经展示了这些新型排名器如何有可能增强长篇问答和其他 RAG 管道。通过继续投资并扩展这些及类似的想法,我们可以进一步提升 Haystack 的 RAG 管道的能力,使我们更接近于打造看起来更像魔法而非现实的 NLP 解决方案。
参考文献:
[1] “迷失在中间:语言模型如何使用长上下文” arxiv.org/abs/2307.03172
[2] 脚本: gist.github.com/vblagoje/430def6cda347c0b65f5f244bc0f2ede
[3] 脚本输出(答案): gist.github.com/vblagoje/738253f87b7590b1c014e3d598c8300b
增强 RAG 的答案:自我调试技术和认知负荷减少
要求 LLM 自我诊断并自我修正提示,以提高答案质量。
·发表于 Towards Data Science ·阅读时间 22 分钟·2023 年 11 月 26 日
–
LLM 进行自我调试(图像由 MidJourney 生成)
检索增强生成(RAG)无疑是一种强大的工具,使用像 LangChain 或 LlamaIndex 这样的框架可以轻松构建。这样的集成便利性可能会让人觉得 RAG 是一种对于每个使用案例都容易构建的神奇解决方案。然而,在我们升级编辑文章搜索工具以提供语义更丰富的搜索结果和直接答案的过程中,我们发现基本的 RAG 设置存在不足,并遇到了许多挑战。构建一个用于演示的 RAG 既快速又简单,通常能在少量场景中产生足够令人印象深刻的结果。然而,实现生产就绪状态的最后阶段,即要求卓越质量的阶段,面临着重大挑战。特别是在处理包含成千上万篇领域特定文章的庞大知识库时,这种情况尤为明显,这种情况并不罕见。
我们对 RAG 的方法包括两个不同的步骤:
-
相关文档检索 通过采用密集和稀疏嵌入的融合,我们从 Pinecone 数据库中提取相关的文档块,考虑内容和标题。这些文档块随后根据与标题、内容以及文档年龄的相关性重新排序。然后选择排名前四的文档:既作为潜在的搜索结果,也作为生成直接答案的文档上下文。值得注意的是,这种方法不同于常见的 RAG 设置,更有效地解决了我们独特的文档检索挑战。
-
直接答案生成 在这里,问题、指令以及之前检索到的前四个文档片段(文档上下文)被输入到大型语言模型(LLM)中,以生成直接答案。
RAG 架构
我之前深入探讨了通过使用混合搜索和层次化文档排名技术来提升文档检索质量。在这篇博客中,我旨在分享关于优化和故障排除直接答案生成过程的见解。
确保高质量的文档检索
当输入低质量的文档上下文时,即使有一个高效的 LLM 进行直接答案生成也是徒劳的。例如,如果文档部分缺乏必要的信息来推导出某个问题的答案,那么 LLM 的有效性就会降低,无论模型的规模和认知能力如何。实现这一目标非常具有挑战性,因为它需要同时优化召回率和准确率。召回率对于避免忽略包含关键答案信息的文档片段至关重要,而准确率则对于减少传输的文档片段数量,专注于最相关的内容也很重要。这种考虑需要考虑到限制的上下文窗口大小和传输大量文档上下文的相关成本。因此,所选的 top-k 文档片段应代表最高质量。
LLM 扫描了文档以寻找高质量的内容(图像由 MidJourney 生成)。
因此,如果你发现生成的直接答案不令人满意,第一步应该是仔细审查你的文档检索过程。在我们的案例中,这占据了生成答案不准确的半数问题。检查完整的提示信息以确保在提示的文档上下文中存在必要的相关信息。如果缺失或不足,考虑使用混合搜索、层次化文档排名或评分提升等技术来改进你的文档检索策略。
在本博客的其余部分,我将向你介绍我用来提高直接回答质量的四种技术,以及我如何将这些技术融入我的提示中。请注意,我在博客中分享的提示可能会为简洁起见进行编辑,某些部分可能被省略,以突出讨论的相关方面,并避免使博客内容过于繁琐。此外,虽然我在整个博客中始终使用“2019 年马自达 CX-9 的燃油效率是多少?”作为示例,但重要的是要理解,我们的评估不仅限于这个问题。我们已使用类似问题的集合进行评估,以确保我们观察到的行为在大量评估样本中具有代表性。那么,我们开始吧。
清晰至关重要:在你的指令中要明确。
确保你给 LLM 的提示是明确且定义良好的至关重要。例如,如果你希望 LLM 在文档上下文中没有必要信息时避免生成答案,你必须明确指定这一点。以下是一个示例提示。
You are a friendly chatbot who are required to respond to questions using
details from excerpts taken from documents about cars. Do not source
information from other than the document excerpts provided. If you don't know
the answer simply return nothing.
特别强调指令**“如果你不知道答案,就什么也不要返回。”** LLM 面临与界限相关的挑战,就像你高中时那个聪明但让人讨厌的朋友,总是举手回答老师的问题,无论他们对回答的信心如何。他们不确定提供一个错误答案(称为虚幻)的影响是否比完全不回答更糟。因此,通过包含这一指令,你在表达你的偏好。
此外,具体要求根据你的使用案例而异。对于我们的需求,我们期望 LLM 仅依赖于我们的知识库,这意味着它应该仅从提供的文档片段中的信息生成答案。所有 LLM 都在大量的互联网、书籍和其他媒介数据上进行过训练。尽管这些来源可能包含潜在的答案信息,但它们的可靠性和与我们知识库的一致性无法保证。因此,我们加入了额外的指令:“不要从提供的文档摘录以外的地方获取信息。”
LLM 正在仔细阅读提供的指令(图像由 MidJourney 生成)。
通过直接和精确的提示,你可以大大减少 LLM 产生毫无根据或“虚幻”答案的可能性。
让 LLM 自我诊断和自我修正。
没错!可以要求 LLM 识别并纠正自身错误。与传统算法相比,LLM 具有推理能力,这使得它能够执行多种任务,包括自我调试。
LLM 正在进行自我诊断(图像由 MidJourney 生成)。
例如,在我们的项目中,我们遇到了一个问题,查询“2019 年 Mazda CX-9 的燃油效率是多少?”时,LLM 生成了一个不准确的回答,声称“2019 年 Mazda CX-9 的燃油效率是 8.8L/100km。”经过仔细检查,我们确认确实提供了正确的文档上下文。相关信息包含在我们提示中的一篇标题为“2019 年 Mazda CX-8 与 Mazda CX-9 比较”的文章中。然而,不知为何,LLM 却从 2018 年 Mazda CX-9 的文章中提取了燃油效率信息。下面是我们的原始提示。
You are a friendly chatbot who are required to respond to questions using
details from excerpts taken from documents about cars. Do not source
information from other than the document excerpts provided. If you don't know
the answer simply return nothing.
At the end of your answer please provide the source(s) of the article
you source the answer from in the following format.
SOURCE: 123-pl, 555-pl, etc.
QUESTION: what is mazda cx9 2019 fuel efficiency?
=========
EXTRACTED DOCUMENTS:
------------------------------
Source: 5466-pl
Title: Mazda CX-9 2018 Review
Content:
... Fuel use is a constant consideration,
too, we’ve piled on thousands of kilometres, mostly with two people on board,
and the reading still hovers around 10.0L/100km. Note: this latest
consumption figure is marginally up on the two-wheel drive version
of the CX-9, which clocked an average of 9.2L/100km according to both
the trip computer and our own independent testing. Both are well up on
their claims.
------------------------------
Source: 6248-pl
Title: Mazda CX-8 v Mazda CX-9 2019 Comparison
Content:
... Which wins, and why? So, we’ve saved the fuel consumption
figures till last. The Mazda CX-8 averaged 7.1L/100km for our tour from
Adelaide, up to the Flinders Ranges and back again. The CX-9 averaged
10.1L/100km. As both cars have a 74-litre fuel tank you’re going to
get further between refuels in the CX-8, paying a little more for it at
the bowser and pumping less CO2 into the atmosphere ...
------------------------------
...
使用 GPT3.5 turbo,它生成了以下不正确的回答(正确答案是 10.1L/100 km)。
The fuel efficiency of the Mazda CX-9 2019 varies depending on factors
such as driving conditions and load. In one of the provided sources,
it was mentioned that the fuel consumption for the CX-9 2019
was around 10.0 liters per 100 kilometers when driven with
two people on board...
SOURCE: 5466-pl
当我使用 GPT4.0 测试相同的提示时,得到了正确的答案。
The Mazda CX-9 2019 model's fuel efficiency is not explicitly listed
in the provided documents, but the 2018 model has a consumption figure
of around 10.0L/100km, and it is noted that this is marginally up on
the two-wheel drive version which clocked an average of 9.2L/100km.
The 2017 review of the Mazda CX-9 also indicated a consumption of
9.2L/100km over 2500km, which is higher than Mazda's claimed 8.4L/100km.
The 2019 comparison between the CX-8 and CX-9 suggests that the CX-9
averaged 10.1L/100km. These figures could be considered roughly
equivalent for the 2019 model, barring any major changes between
the 2018 and 2019 models.
尽管如此,GPT4 在我们的使用案例中并不经济,因为它的成本是 GPT3.5 Turbo 的 10 倍。因此,这一挑战促使我们寻找与 GPT3.5 Turbo 兼容的解决方案,激发了自我调试的概念。
想象一下,让某人根据您提供的文档回答问题,而他们给出了错误的回应。您会采取什么步骤来了解错误发生的原因?您可以通过展示正确答案和来源材料来简单地询问他们为什么犯错。与 LLM 也是一样。我们询问 LLM,但为了有效地进行此操作,我们需要能够在 LLM 提供答案后继续与其对话。
通过使用如www.poe.com这样的平台,我们可以重现与 LLM 的交互。我们选择相同的 LLM 模型,将整个提示输入控制台。生成的输出与我们代码中遇到的精确错误答案相符。随后,我们与 LLM 进行对话,这在促进自我调试过程中是一个关键步骤,如下所述。
poe.com 网络界面
这是我与 LLM 的完整对话记录。
我:您给我的答案不正确。它是 2018 年 Mazda CX-9 的燃油效率,如文章标题“Mazda CX-9 2018 Review”所述。正确的答案是 10.1L/100km,如文章标题“Mazda CX-8 与 Mazda CX-9 2019 比较”所述。
LLM:我为这个错误道歉。您说得对,正确的信息确实在您提到的文章中提供了。
我:没关系。你为什么犯了这个错误?
LLM:我没有意识到文章中引用的年份是汽车的型号年份。我以为这是文章的年份。
根据最后的回应,我现在已识别出 LLM 错误的原因。这激发了另一个想法:如果 LLM 可以理解并解释其误解,也许它还可以调整我的初始提示,以防未来重复同样的错误。这绝对值得一试!
我:我应该如何修改我的提示,以便下次你不会重复这个错误?
LLM:你可以具体说明文章标题/内容可能包含汽车型号年份,这应该与问题中询问的型号年份匹配。
我:请你修改我的提示以包含你的建议吗?
在第二次请求时,LLM 向我提供了一个整合了建议改进的修订提示。
You are a friendly chatbot who is required to respond to questions
using details from excerpts taken from documents about cars. Do not
source information from other than the document excerpts provided.
If you don't know the answer, simply return nothing.
Please ensure that the article title/content might contain car
model year information, which should match the model year asked
in the question.
At the end of your answer, please provide the source(s) of the article
you source the answer from in the following format.
SOURCE: 123-pl, 555-pl, etc.
QUESTION: What is Mazda CX9 2019 fuel efficiency?
尽管使用了这个调整后的提示,但观察到它仍然对我之前的问题产生了错误的回答,这让人感到相当沮丧。
The 2019 Mazda CX-9's fuel efficiency is not mentioned in the provided
documents. Therefore, I do not have information on the fuel efficiency
of the 2019 Mazda CX-9 based on the excerpts available.
尽管如此,它还是给了我一些关于需要包含模型年份的信息的见解。因此,我决定手动修改提示,加入了推荐提到的模型年份。我甚至提供了一个简短的期望行为示例来指导 LLM。
基于 LLM 建议的修订提示
You are a friendly chatbot who are required to respond to questions
using details from excerpts taken from documents about cars of
particular model years.
These documents may have information about the model year of car in
review within its content or title. Eg. Volvo XC90 2018 Review, means
the review is only for
Volvo XC90 model year 2018\. If a user provides the model year in
their question, ensure that your answer is sourced from an article
from the corresponding model year.
Eg. When the user is asking for "What is the safety feature of
Volvo XC90 2019?", you should not use any information within the
previous article as they are of different model year.
When the model year or the car make and model is not mentioned in
this article content, you can assume it is the same as the make,
model and model year as mentioned in the article title.
At the end of your answer please provide the source(s) of the
article you source the answer from in the following format.
SOURCE: 123-pl, 555-pl, etc.
QUESTION: what is mazda cx9 2019 fuel efficiency?
=========
EXTRACTED DOCUMENTS:
------------------------------
Source: 5466-pl
Title: Mazda CX-9 2018 Review
Content:
... Fuel use is a constant consideration,
too, we've piled on thousands of kilometres, mostly with two people on board,
and the reading still hovers around 10.0L/100km. Note: this latest
consumption figure is marginally up on the two-wheel drive version
of the CX-9, which clocked an average of 9.2L/100km according to both
the trip computer and our own independent testing. Both are well up on
their claims.
------------------------------
Source: 6248-pl
Title: Mazda CX-8 v Mazda CX-9 2019 Comparison
Content:
... Which wins, and why? So, we've saved the fuel consumption
figures till last. The Mazda CX-8 averaged 7.1L/100km for our tour from
Adelaide, up to the Flinders Ranges and back again. The CX-9 averaged
10.1L/100km. As both cars have a 74-litre fuel tank you're going to
get further between refuels in the CX-8, paying a little more for it at
the bowser and pumping less CO2 into the atmosphere ...
------------------------------
...
新的提示现在给了我正确的答案!
The fuel efficiency of the Mazda CX-9 for the 2019 model year can be
found in the article titled "Mazda CX-8 v Mazda CX-9 2019 Comparison."
According to the article, the Mazda CX-9 averaged 10.1L/100km in
fuel consumption for their test. This figure provides information
about the fuel efficiency of the Mazda CX-9 for the 2019 model year.
SOURCE: 6248-pl
然而,需要记住的是,这种方法可能不会始终产生积极的结果。我使用这种方法获得关于 LLM 解释为何犯错的见解的成功率约为 75%,而让 LLM 为我修改提示以产生正确答案的效果约为 25%。尽管如此,拥有这种方法总比没有方法要好。
意识到认知负荷。
保持指示准确对于引导 LLM 产生期望的答案至关重要。然而,过于详细的提示可能会对像 GPT-3.5 Turbo 这样较小的 LLM 产生不利影响,因为它们的认知能力比 GPT-4 低。想知道为什么吗?让我们通过一个示例来演示这一点。
LLM 正在经历认知负荷(图像由 MidJourney 生成)。
我们最初使用 Langchain 模板构建的提示采用了一次性技术。例如,它包括了一个完整互动的单一示例,希望 LLM 能够更好地理解我们的意图。然而,当使用 GPT3.5 Turbo 时,我们观察到一次性提示比零次提示产生了更模糊的回答。
以下是我们基于Langchain模板的一次性提示。提供的示例来自一个完全不同的领域(非汽车),提示是通用的,没有提及汽车相关的文章。
Given the following extracted parts of a long document (with its source)
and a question, create a final answer with references ("SOURCES").
If you don't know the answer, just say that you don't know. Don't try to
make up an answer.
ALWAYS return a "SOURCES" part in your answer.
QUESTION: Which state/country's law governs the interpretation
of the contract?
=========
Content: This Agreement is governed by English law and the parties
submit to the exclusive jurisdiction of the English courts in relation
to any dispute (contractual or non-contractual)...
Source: 28-pl
Content: No Waiver. Failure or delay in exercising any right or remedy
under this Agreement shall not constitute a waiver of such (or any other)
right or remedy.
11.7 Severability.
Source: 30-pl
Content: (b) if Google believes, in good faith, that the Distributor
has violated or caused Google to violate any Anti-Bribery Laws (as
defined in Clause 8.5) or that such a violation is reasonably likely to
occur,
Source: 4-pl
=========
FINAL ANSWER: This Agreement is governed by English law.
SOURCES: 28-pl
...
QUESTION: what is mazda cx9 2019 fuel efficiency?
=========
------------------------------
Title: Mazda CX-9 2018 Review
Content:
Fuel use is a constant consideration, too, we’ve piled on thousands of
kilometres, mostly with two people on board, and the reading still hovers
around 10.0L/100km.
Note: this latest consumption figure is marginally up on the two-wheel
drive version of the CX-9, which clocked an average of 9.2L/100km
according to both the trip computer and our own independent testing.
...
------------------------------
Title: Mazda CX-8 v Mazda CX-9 2019 Comparison
Content:
nomads. Which wins, and why? So, we’ve saved the fuel consumption figures
till last. The Mazda CX-8 averaged 7.1L/100km for our tour from Adelaide,
up to the Flinders Ranges and back again. The CX-9 averaged 10.1L/100km.
As both cars have a 74-litre fuel tank you’re going to get further
between refuels in the CX-8, paying a little more for it at the bowser
and pumping less CO2 into the atmosphere. Health-affecting particulates?
Well, that’s another story.
...
FINAL ANSWER:
给出的回答极其不清晰,提到了不同车型年份的马自达 CX-9 的燃油效率。
The fuel efficiency of the 2019 Mazda CX-9 varies depending on driving
conditions and other factors. According to available information:
In one source, it is mentioned that the trip computer indicated fuel
consumption of 9.2L/100km in 2500km worth of driving, which is
considerably higher than Mazda's claimed 8.4L/100km for the CX-9\.
This figure was achieved with one or two people in the car, not a
full family and their belongings. However, further testing and simulations
were mentioned to corroborate fuel consumption.
In another source comparing the Mazda CX-8 and CX-9, it is stated that
the CX-8 averaged 7.1L/100km on a specific tour, while the CX-9
averaged 10.1L/100km. These figures indicate that the CX-8 is more
fuel-efficient than the CX-9 in this particular comparison.
In a different source discussing the 2023 Mazda CX-8, the official
combined fuel consumption claim for the CX-8 Touring Active is 6.0L/100km,
achieved with the assistance of the i-Stop function. However, during a
test drive on open roads with one passenger and little luggage, the
Touring Active averaged 8.6L/100km.
So, the fuel efficiency of the 2019 Mazda CX-9 may vary depending
on driving conditions and the specific model/configuration. It's
recommended to refer to the official manufacturer's specifications
and conduct real-world testing to determine the exact fuel efficiency
of a specific CX-9 model.
初始提示的模糊性质,加上一个无关的单次示例,可能部分地导致了这个问题。为验证这个理论,我制定了一个更具针对性的提示,其中包含了特定领域的指令和一个与我们实际用例紧密相关的示例。以下是这个新提示的详细信息,这将有助于确定它是否能带来显著的差异。
You are a friendly chatbot who are required to respond to questions
using details from excerpts taken from documents about cars of
particular model years.
These documents may have information about the model year of car in
review within its content or title. Eg. Volvo XC90 2018 Review, means
the review is only for
Volvo XC90 model year 2018\. If a user provides the model year in
their question, ensure that your answer is sourced from an article
from the corresponding model year.
Eg. When the user is asking for "What is the safety feature of
Volvo XC90 2019?", you should not use any information within the
previous article as they are of different model year.
When the model year or the car make and model is not mentioned in
this article content, you can assume it is the same as the make,
model and model year as mentioned in the article title.
At the end of your answer please provide the source(s) of the
article you source the answer from in the following format.
SOURCE: 123-pl, 555-pl, etc.
QUESTION: What is Volvo XC90 2020 fuel efficiency?
=========
EXTRACTED DOCUMENTS:
------------------------------
Source: 22858-pl
Title: Volvo XC90 2020 Review
Content:
costs) Engine: 2.0-litre four-cylinder turbocharged and supercharged
petrol Output: 246kW/440Nm Transmission: Eight-speed automatic
Fuel: 8.5L/100km (ADR Combined) CO2: 199g/km (ADR Combined) ...
------------------------------
Source: 22855-pl
Title: Volvo XC90 2020 Review
Content:
The brakes also need a hefty prod for downhill corners. All that weight
impacts fuel consumption. Volvo claims an 8.5L/100km average, but we
consumed premium unleaded at a rate of 11.8L/100km during our test ...
------------------------------
Source: 23987-pl
Title: Volvo XC90 T6 R-Design 2019 Review
Content:
the engine’s progress: there is minimal turbo lag and the gearbox is
such that the four-pot transitions cleanly out of corners and
intersections, slickly picking up a new gear. Fuel consumption is
something of a misnomer, however. The claim reads 8.5L/100 but
in reality we used 9.4L/100km with quite a bit of highway driving ...
------------------------------
...
===========
FINAL ANSWER: The fuel efficiency of the volvo xc90 2020 is 8.5l/100km
(adr combined). this information is based on the review of the
Volvo XC90 2020.
SOURCES: 22858-pl
QUESTION: what is mazda cx9 2019 fuel efficiency?
=========
EXTRACTED DOCUMENTS:
------------------------------
Source: 5466-pl
Title: Mazda CX-9 2018 Review
Content:
Fuel use is a constant consideration, too, we’ve piled on thousands
of kilometres, mostly with two people on board, and the reading still
hovers around 10.0L/100km. Note: this latest consumption figure is
marginally up on the two-wheel drive version of the CX-9, which clocked an
average of 9.2L/100km according to both the trip computer and our own
independent testing ...
------------------------------
Source: 6248-pl
Title: Mazda CX-8 v Mazda CX-9 2019 Comparison
Content:
Which wins, and why? So, we’ve saved the fuel consumption
figures till last. The Mazda CX-8 averaged 7.1L/100km for our tour
from Adelaide, up to the Flinders Ranges and back again. The CX-9
averaged 10.1L/100km. As both cars have a 74-litre fuel tank you’re
going to get further between refuels in the CX-8, paying a little
more for it at the bowser and pumping less CO2 into the atmosphere ...
------------------------------
...
===========
FINAL ANSWER:
提供的回答仍然不准确。它还声称没有必要的信息来回答问题,这也是不准确的。
The fuel efficiency of the Mazda CX-9 in the year 2019 is not available
in the provided documents. The information in the documents pertains to
the Mazda CX-9 in 2017 and earlier years. Therefore, I cannot provide
the fuel efficiency for the Mazda CX-9 in 2019 based on the provided
documents.
SOURCES: 5466-pl, 4900-pl, 6248-pl, 168-pl
通过省略示例并选择零次提示方法,我们成功地使 LLM 生成了正确的答案。
You are a friendly chatbot who are required to respond to questions
using details from excerpts taken from documents about cars of
particular model years.
These documents may have information about the model year of car in
review within its content or title. Eg. Volvo XC90 2018 Review, means
the review is only for
Volvo XC90 model year 2018\. If a user provides the model year in
their question, ensure that your answer is sourced from an article
from the corresponding model year.
Eg. When the user is asking for "What is the safety feature of
Volvo XC90 2019?", you should not use any information within the
previous article as they are of different model year.
When the model year or the car make and model is not mentioned in
this article content, you can assume it is the same as the make,
model and model year as mentioned in the article title.
At the end of your answer please provide the source(s) of the
article you source the answer from in the following format.
SOURCE: 123-pl, 555-pl, etc.
QUESTION: what is mazda cx9 2019 fuel efficiency?
=========
EXTRACTED DOCUMENTS:
------------------------------
Source: 5466-pl
Title: Mazda CX-9 2018 Review
Content:
Fuel use is a constant consideration, too, we’ve piled on thousands
of kilometres, mostly with two people on board, and the reading still
hovers around 10.0L/100km. Note: this latest consumption figure is
marginally up on the two-wheel drive version of the CX-9, which clocked an
average of 9.2L/100km according to both the trip computer and our own
independent testing ...
------------------------------
Source: 6248-pl
Title: Mazda CX-8 v Mazda CX-9 2019 Comparison
Content:
Which wins, and why? So, we’ve saved the fuel consumption
figures till last. The Mazda CX-8 averaged 7.1L/100km for our tour
from Adelaide, up to the Flinders Ranges and back again. The CX-9
averaged 10.1L/100km. As both cars have a 74-litre fuel tank you’re
going to get further between refuels in the CX-8, paying a little
more for it at the bowser and pumping less CO2 into the atmosphere ...
------------------------------
...
===========
FINAL ANSWER:
The fuel efficiency of the Mazda CX-9 for the 2019 model year can be
found in the article titled "Mazda CX-8 v Mazda CX-9 2019 Comparison."
According to the article, the Mazda CX-9 averaged 10.1L/100km in
fuel consumption for their test. This figure provides information
about the fuel efficiency of the Mazda CX-9 for the 2019 model year.
SOURCE: 6248-pl
为进一步验证问题是否源于认知过载,我们使用 GPT-4 进行了单次提示测试,结果如预期地得到了正确的回答。
The fuel efficiency of the Mazda CX-9 2019 is not directly stated in
the documents provided. However, the closest information from a 2019
comparison mentions that the CX-9 averaged 10.1L/100km during a test.
It's important to note that actual fuel efficiency can vary based on
driving conditions, habits, and vehicle maintenance.
SOURCE: 6248-pl
为了验证我们的假设,我们对其他语言模型,如 Claude Instant 和 Claude 2,进行了类似的测试,结果显示了相同的模式。Claude 2 成功处理了我们的单次提示,提供了正确的答案,而 Claude Instant 则没有。Claude 2 和 GPT-4 具有相似的认知能力,均优于 Claude Instant 和 GPT-3.5 Turbo。这支持了我们的理论,即认知能力较低的模型在处理复杂指令时会遇到困难。我对这些结果感到非常满意,因为零次提示法可以使提示更简洁,从而降低成本,并且它适用于像 GPT-3.5 Turbo 或 Claude Instant 这样的较便宜、更小的模型。
要求提供证明。
要求语言模型提供其生成答案的来源是一种非常有效的策略,能够减少幻觉并防止幻觉,特别是当相关信息不在提供的文档上下文中时。
LLM 正在追踪源材料的来源(图像由 MidJourney 生成)。
实现这个目标可以通过使用不同的提示来引导语言模型。一个策略是指导 LLM 识别出影响其响应的文档上下文的特定部分。加入一个命令,要求 LLM 在回答中引用文档源 ID,可以让你忽略没有源 ID 或源 ID 错误的回应。虽然不常见,但 LLM 可能会引用你文档块中未包含的外部来源,例如它在训练期间接触到的网站。
At the end of your answer please provide the source(s) of the
article you source the answer from in the following format.
SOURCE: 123-pl, 555-pl, etc.
另一种策略是指导 LLM 通过明确引用回答问题的文档块中的句子来回应。
Please answer by quoting the exact sentence(s) within the provided
document excerpts..
At the end of your answer please provide the source(s) of the
article you source the answer from in the following format.
SOURCE: 123-pl, 555-pl, etc.
这种方法可能对 LLM 施加额外的约束,并不总是实用,就像我们文档的情况一样。我们的文档经常缺乏明确回应常见问题的句子。因此,LLM 没有特定的句子可供引用,这导致没有回应。如果我们允许 LLM 使用文档中嵌入的知识来构造自己的句子,它将能够提供答案。
结论
使用语言模型(LLM)构建应用程序与使用传统算法截然不同。传统算法中,详细的指令使你完全控制过程,调试涉及观察变量值,确保这些指令是正确的。相比之下,使用 LLM 就像是雇用一个人来在你的软件中执行这些过程。由于 LLM 的反应类似于人类,故障排除和调试需要类似于确定一个人可能犯错的技术,主要通过提问。
尽管语言模型(LLM)技术仍在发展中,且可能出现错误和不准确,但它显示出了相当大的潜力,并且有有效的策略可以大大减轻这些问题。鉴于 LLM 技术的快速发展以及不断创新的方法和工具,关于这一领域在不久的将来可能带来的变革前景,充满了强烈的兴奋感。
我们即将部署我们的 RAG 设置用于生产,并且在我们继续学习的过程中,我期待在即将发布的博客中分享更多见解。
如果你发现这篇文章有趣且有帮助,我将感激你用 20 次鼓掌来支持我。我也渴望从你的见解和经验中学习,所以欢迎通过回复分享你的想法。此外,如果你有兴趣,我欢迎你在 LinkedIn 上与我联系。
最后,我想向 Carsales.com 的杰出团队表达我的感谢,感谢他们在这一旅程中的支持。
医学信号处理中的集成平均
简单却强大的方法
·
关注 发布在 Towards Data Science ·6 分钟阅读·2023 年 5 月 2 日
–
作为研究人员、数据科学家/分析师,甚至在任何科学领域处理数据是不可避免的。因此,你处理的数据的可靠性至关重要,因为它决定了你工作的可靠性。
在本文中,我们将介绍集成平均方法,一种简单但强大的方法,并介绍其在信号数据上的应用。
图片由 Eran Menashri 拍摄于 Unsplash
背景
平均值是一个可以描述一组数值的单一值。它可以定义为变量的总和除以变量的数量。如果我们有一组变量 {x1, x2, …, xn},则可以按如下方式计算平均值:
你可以考虑一个简单的例子来介绍集成平均的概念,即测量在测量过程中温度稳定的溶液的温度。可以使用电子传感器在十秒钟内测量三次温度。集成平均可以通过取这三次测量的平均值来完成。
从上述示例来看,集成平均方法要求能够重复你所进行的实验,并保持测量系统的相同属性 [1]。这在许多实际情况中很难应用。因此,在许多情况下可能考虑的解决方案是一次性进行实验,但同时使用多个传感器 [1],以产生多个相应实验的观测值。
在信号类型的数据(时间序列)的情况下,集成平均方法是通过逐点平均信号样本来完成的 [2]。因此,在应用该方法之前,一个先决条件是生成的信号在时间上对齐 [1]。下面是应用集成平均于信号数据的示例。
使用两个实验应用集成平均方法。注意信号的样本在时间上是对齐的。 [作者提供的图像]
为什么使用集成平均方法?我们为什么要重复实验?
我第一次接触到集成平均是在生物力学实验室,该实验室专门研究步态模式和分析人体运动。当我的教授指示对同一患者进行实验以获得至少三个成功的实验时,我问为什么要三次而不是一次成功的实验?!
答案是计算这三个实验的集成平均值,以获得具有更高可靠性且不易受到随机噪声影响的最终信号。
常识上,重复实验确保你获得的数据是感兴趣的数据。但当然,实验重复的成本和时间也需要考虑。
从信号处理的角度来看,集成平均在增强信号数据方面有许多优点。这些优点可以总结如下:
真实世界的医学示例
集合平均方法的应用是无限的。医学领域的一个很好的例子是视觉诱发响应/潜能测试(VER 或 VEP 测试)的理念。该测试的目的是测量对视觉刺激的响应,该响应以电信号的形式产生在大脑的视觉皮层中。该测试依赖于特定时间间隔的重复刺激 [3]。视觉刺激通过黑白棋盘图案的屏幕进行 [3]。重复刺激的信号逐点平均(集合平均)以确定 VER 信号 [1],请记住信号在刺激过程中是时间对齐的。以下是如何使用集合平均方法提取 VER 信号的示例。
我们将使用的信号数据可以通过以下链接(MIT 许可)获取。数据包括 100 个以 200 Hz 采样率记录的电信号。
使用 Python 进行集合平均
首先,我们将导入所需的 Python 包:
-
Numpy:用于数组操作和算术计算。
-
Matplotlib:用于可视化 VER 响应的信号数据。
-
Scipy:我们将使用 scipy.io 模块读取数据文件(.MAT 文件类型)。
# Import the required packages
import matplotlib.pyplot as plt
import numpy as np
from scipy import io
现在,我们使用scipy.io.loadmat方法读取包含电信号的数据文件。输出是文件内容的字典。电信号可以在“ver”项中找到。
# Read a Mat file using scipy.io
mat = io.loadmat('ver.mat')
# Exract the electrical signals
ver = mat['ver']
让我们探索一下我们正在处理的数据的大小。
# The size of variable "ver"
print(ver.shape)
(100, 500)
这意味着我们有 100 个信号,每个信号有 500 个样本。对这些数据应用集合平均方法将平均这 100 个信号,并生成一个包含 500 个样本的信号。
提取信号数据后,我们将定义采样率以生成信号的时间轴。
# Calculate the sampling rate
sampling_rate = 200.0
# Calculate the duration of the recordings
duration = ver.shape[1]/sampling_rate
# Generate the time axis of the recordings
time_axis = np.arange(0, duration, 1/sampling_rate)
现在我们有了时间轴和要研究的信号,我们可以在同一时间轴上可视化一些信号,以查看单一视觉响应的样子。我们将仅可视化前 10 个信号。
# Subplot figure with 10 rows and one column
fig, axs = plt.subplots(10, figsize=(10,5), sharex=True)
# Plot the first 10 recordings
for i in range(10):
axs[i].plot(time_axis, ver[i,:])
# Hide the values of y-axis
axs[i].set_yticks([])
# Fit the x-axis along the signal
axs[i].set_xlim([time_axis[0], time_axis[-1]])
# Set a title and xlabel
axs[0].set_title('The first 10 Signals')
axs[9].set_xlabel('Time [Sec]')
plt.show()
数据的前 10 个信号。[作者提供的图像]
注意,单一信号中无法识别视觉响应。因此,我们将使用集合平均法来确定 VER。
# Apply the ensamble averaging method on the Recordings.
ver_signal = np.mean(ver, axis=0)
# Extract the actual VER from the Mat file
actual_ver = np.reshape(mat['actual_ver'], [500])
# Plot the ensambled EEG recordings and the actual VER
plt.plot(time_axis, ver_signal, color='green', label='Ensamble Averaging')
plt.plot(time_axis, actual_ver, color='red', label='Actual VER')
plt.xlim([time_axis[0], time_axis[-1]])
plt.xlabel('Time [sec]')
plt.ylabel('Average')
plt.title('Visual Evoked Response')
plt.legend()
plt.show()
使用集合平均法对 100 个信号进行 VER 分析。[作者提供的图像]
结论
-
我们介绍了集成平均法,这是一种简单但非常有用的方法,你可以用来提取可靠的数据。
-
我们指出了重复实验的原因及其如何提升数据的可靠性。
-
应用集成平均法能将信号的信噪比(SNR)提高到 N(重复次数)的平方根。此外,最终的信号数据也不容易受到随机噪声的影响。
-
我们介绍了一个例子,利用集成平均法来确定视觉诱发反应(VER),基于特定时间的重复刺激。
参考文献
[1] Semmlow, J. (2018). 时间域的信号分析。在生物工程师的电路、信号与系统(第 51-110 页)。Elsevier。 doi.org/10.1016/B978-0-12-809395-5.00002-3
[2] Thomas, T. (2005). 集成平均滤波器用于噪声降低。国际计算机与通信工程高级研究期刊,5(8)。
[3] Tripathy, K., Hsu, J., & Lim, J. (2022 年 11 月 10 日). 视觉诱发电位/反应(VEP/VER)。美国眼科学会。 eyewiki.aao.org/Visual_Evoked_Potential/_Response_(VEP/VER)
集成学习:袋装和提升
·
关注 发表在 Towards Data Science ·11 分钟阅读·2023 年 2 月 23 日
–
你想把你的数据科学技能提升到一个新水平吗?你是否希望提高模型的准确性,并基于数据做出更明智的决策?那么是时候探索袋装和提升的世界了。运用这些强大的技术,你可以提升模型的性能,减少错误,并做出更准确的预测。
图片由 Unsplash 提供
无论你是在处理分类问题、回归分析,还是其他数据科学项目,bagging 和 boosting 算法都可以发挥关键作用。在本文中,我们#1 总结了集成学习的主要思想,介绍了#2 bagging和#3 boosting,然后#4 对比了这两种方法,以突出相似性和差异。
所以,让我们准备好 bagging 和 boosting 取得成功吧!
#1:介绍和主要思想:集成学习
那我们什么时候应该使用它呢?显然,当我们看到模型的过拟合或欠拟合时。让我们从 bagging 和 boosting 的关键概念开始,这两者都属于集成学习技术的范畴:
作者提供的图片
集成学习的主要思想是使用多个算法和模型一起完成相同的任务。虽然单一模型仅使用一个算法来创建预测模型,但 bagging 和 boosting 方法旨在结合多个算法,以实现比单独学习更高一致性的更好预测。
示例:图像分类
本质概念通过涉及图像分类的教学插图来概括。假设有一组图像,每张图像都附有一个类别标签,表示动物的种类,用于训练模型。在传统建模方法中,我们会尝试几种技术并计算准确性,以选择一种优于其他的技术。假设我们在这里使用逻辑回归、决策树和支持向量机,这些模型在给定的数据集上表现不同。
作者提供的图片
在上述示例中,我们观察到逻辑回归和决策树模型将特定记录预测为狗,而支持向量机将其识别为猫。由于各种模型对特定记录有各自的优缺点,集成学习的关键思想是结合这三种模型,而不是选择表现出最高准确度的单一方法。
这个过程称为聚合或投票,它结合了所有基础模型的预测,以得出一个被认为比任何单独模型更精确的预测。
偏差-方差权衡
下一个图表可能对你们中的一些人来说很熟悉,但它很好地表示了测试误差率上偏差和方差之间的关系和权衡。
你可能对以下概念很熟悉,但我认为它有效地说明了偏差和方差与测试误差率之间的相关性和权衡。
作者提供的图片
模型的方差与偏差之间的关系是方差的减少会导致偏差的增加,反之亦然。为了实现最佳性能,模型必须处于一个平衡点,在这个点上测试错误率最小化,同时方差和偏差得到适当平衡。
集成学习可以帮助将这两种极端情况平衡到更稳定的预测中。一种方法叫做袋装(bagging),另一种方法叫做提升(boosting)。
#2:袋装(自助聚合)
一个随机的袋子。图片来源于Unsplash
让我们首先关注一种叫做自助聚合的袋装技术。自助聚合旨在通过减少模型的方差来解决前一个图表中的右侧极端问题,以避免过拟合。
作者提供的图片
目的在于拥有多个相同学习算法的模型,这些模型通过原始训练数据的随机子集进行训练。这些随机子集称为袋子,可以包含数据的任何组合。每个数据集都用于拟合一个独立的模型,该模型对给定数据产生独立的预测。然后将这些预测聚合成一个最终分类器。这种方法的想法实际上非常接近我们最初的玩具示例中的猫和狗。
通过使用随机数据子集,过拟合的风险被减少和通过对子模型结果进行平均来平滑。所有模型并行计算,然后在之后进行聚合。
最终的集成聚合计算使用简单平均(用于回归问题)或简单多数投票(用于分类问题)。为此,每个随机样本中的每个模型都会为该特定子集产生一个预测。对于平均值,这些预测只是相加然后除以创建的袋子数量。
作者提供的图片
简单多数投票的工作原理类似,但使用预测的类别而不是数值。算法确定预测最多的类别,并假设多数就是最终的聚合结果。这再次非常类似于我们的玩具示例,其中三种算法中的两种预测图片为狗,因此最终聚合结果也是狗的预测。
随机森林
对于袋装方法,一个著名的扩展是随机森林算法,它利用了袋装的思想,但也使用特征的子集,而不仅仅是条目的子集。另一方面,袋装方法会考虑所有给定的特征。
袋装的代码示例
接下来,我们将探讨一些来自sklearn.ensemble
库的有用 python 函数。名为BaggingClassifier
的函数有一些参数,可以在文档中查阅,但最重要的参数是base_estimator、n_estimators和max_samples。
from sklearn.ensemble import BaggingClassifier
# define base estimator
est = LogisticRegression() # or est = SVC() or est = DecisionTreeClassifier
# n_estimators defines the number of base estimators in the ensemble
# max_samples defines number of samples to draw from X to train each base estimator
bag_model = BaggingClassifier(base_estimator= est, n_estimators = 10, max_samples=1.0)
bag_model = bag_model.fit(X_train, y_train)
Prediction = bag_model.predict(X_test)
-
base_estimator: 你需要在第一个参数中提供随机子集在袋装过程中应该使用的基础算法。例如,这可以是逻辑回归、支持向量分类、决策树或更多其他算法。
-
n_estimators: 估计器的数量定义了你希望在这里创建多少个袋,默认值为 10。
-
max_samples: 最大样本数定义了从 X 中抽取多少样本来训练每个基础估计器。默认值为 1.0,意味着应该使用所有现有条目。你也可以通过将其设置为 0.8 来表示只使用 80%的条目。
设置场景后,该模型对象的工作方式类似于许多其他模型,可以使用fit()
过程进行训练,包括来自训练集的 X 和 y 数据。对测试数据的相应预测可以使用predict()
完成。
#3: 提升
提升你的模型!图片来自 Unsplash
提升是袋装算法的一种小变体,使用序列处理而不是并行计算。袋装旨在减少模型的方差,而提升方法则旨在减少偏差以避免数据的欠拟合。基于这个理念,提升还使用数据的随机子集来创建一个平均性能的模型。
图片由作者提供
为此,它使用弱模型的错误分类条目以及一些其他随机数据来创建一个新模型。因此,不同的模型不是随机选择的,而是主要受到前一个模型错误分类条目的影响。这种技术的步骤如下:
-
训练初始(弱)模型
你创建一个数据子集并训练一个弱学习模型,此时假设它是最终集成模型。然后,你分析给定训练数据集上的结果,并可以识别那些被错误分类的条目。
-
更新权重并训练新模型 你创建一个原始训练数据的新随机子集,但对那些错误分类的条目赋予更高的权重。然后使用这个数据集来训练新模型。
-
将新模型与集成模型进行汇总
下一个模型应该在更难的条目上表现更好,并将与之前的模型合并(汇总)成新的最终集成模型。
从本质上讲,我们可以多次重复这个过程,并不断更新集成模型,直到我们的预测能力足够好。这里的关键思想显然是创建能够预测更困难数据条目的模型。这可以导致模型更好地拟合数据,并减少偏差。
图片作者
与 Bagging 相比,这种技术使用基于模型系数的加权投票或加权平均,这些模型与它们的预测一起考虑。因此,这种模型可以减少欠拟合,但有时也可能会过拟合。
Boosting 的代码示例
接下来,我们将查看一个类似的代码示例,但用于 boosting。显然,存在多种 boosting 算法。除了GradientDescent
方法外,AdaBoost
是最受欢迎的之一。
-
base_estimator: 类似于 Bagging,你需要定义希望使用的基础算法。
-
n_estimators: 估计量的数量定义了 Boosting 终止的最大迭代次数。它被称为“最大”数量,因为如果算法在更早时达到良好性能,它会自行停止。
-
learning_rate: 最后,学习率控制新模型对之前模型的贡献程度。通常,迭代次数与学习率的值之间存在权衡。换句话说,当学习率较小的时候,你应该考虑更多的估计量,以便基础模型(弱分类器)继续改进。
from sklearn.ensemble import AdaBoostClassifier
# define base estimator (requires support for sample weighting)
est = LogisticRegression() # or est = SVC() or est = DecisionTreeClassifier ….
# n_estimators defines maximum number of estimators at which boosting is terminated
# learning_rate defines the weight applied to each classifier at each boosting iteration
boost_model = AdaBoostClassifier(base_estimator= est, n_estimators = 10, learning_rate=1)
boost_model = boost_model.fit(X_train, y_train)
Prediction = boost_model.predict(X_test)
fit()
和predict()
方法的工作方式与之前的 bagging 示例类似。正如你所见,使用现有库中的这些函数非常简单。不过,你也可以实现自己的算法来构建这两种技术。
#4: 结论:差异与相似性
图片来源:Unsplash
由于我们简要了解了 bagging 和 boosting 的工作原理,现在我想将重点放在对比这两种方法。
相似性
-
集成方法
从一般的角度来看,这两种技术的相似性始于它们都是集成方法,旨在通过多个学习器来改善单一模型的结果。
-
多个样本与聚合
为了实现这一目标,这两种方法都会生成随机样本和多个训练数据集。Bagging 和 Boosting 的相似之处在于,它们都通过对基础模型进行聚合来得出最终决策:要么通过计算平均结果,要么通过投票排名。
-
目的
最终,两者的目标都是为了提高数据的稳定性和预测能力。
差异
-
数据划分 | 整体数据与偏差
由于 bagging 在所有模型中独立地使用训练数据的随机包,而 boosting 对误分类数据给予更高的重要性。因此,这里的数据划分不同。
-
模型 | 独立 vs. 序列
Bagging 创建独立的模型并将其聚合在一起。然而,boosting 会用新的模型按顺序更新现有模型。因此,模型会受到之前构建的影响。
-
目标 | 方差与偏差另一个区别是,bagging 旨在减少方差,而 boosting 尝试减少偏差。因此,bagging 有助于减少过拟合,而 boosting 可以减少欠拟合。
-
函数 | 加权与非加权
最终预测结果的函数在 bagging 技术中使用等权重平均或等权重投票汇聚。Boosting 使用加权多数投票或加权平均函数,对训练数据表现更好的部分赋予更多权重。
含义
研究表明,两种方法的主要思想是结合多个模型以实现比单一学习模型更好的预测。然而,并没有绝对优于对方的说法来选择 bagging 还是 boosting,因为两者都有优点和缺点。
虽然 bagging 减少了方差并减少了过拟合,但它很少能产生更好的偏差。另一方面,boosting 减少了偏差,但可能比 bagged 模型更过拟合。
回到方差-偏差权衡图,我尝试可视化每种方法看起来合适的极端情况。然而,这并不意味着它们能在没有任何缺点的情况下实现结果。目标应该始终是保持偏差和方差在合理的平衡中。
Bagging 和 boosting 都使用所有给定特征,仅随机选择条目。另一方面,随机森林是对 bagging 的扩展,也创建特征的随机子集。因此,随机森林在实践中比 bagging 使用得更频繁。
阅读 Jonas Dieckmann 在 Medium 上的文章。分析经理 & 产品负责人 @ Philips | 热情并撰写关于……
medium.com](https://medium.com/@jonas_dieckmann?source=post_page-----23f9336d3cb0--------------------------------)
希望你觉得这有用。请告诉我你的想法!也欢迎在 LinkedIn 上与我联系,链接为 www.linkedin.com/in/jonas-dieckmann/
或在 medium 上关注我。
另请参见我其他的一些文章:
你是否曾遇到过尝试分析复杂且高度相关的数据集的情况……
towardsdatascience.com ## 如何使用 Keras API 和 Google Colab 开始使用 TensorFlow
分步教程分析人类活动与神经网络
towardsdatascience.com
参考文献
[1]: Bühlmann, Peter. (2012). Bagging、Boosting 与集成方法。计算统计学手册. 10.1007/978–3–642–21551–3_33.
[2]: Machova, Kristina & Puszta, Miroslav & Barcák, Frantisek & Bednár, Peter. (2006). 使用决策树分类器对 Bagging 和 Boosting 方法的比较。计算机科学与信息系统. 3. 57–72. 10.2298/CSIS0602057M.
[3]: Banerjee, Prashant. Bagging 与 Boosting @kaggle: www.kaggle.com/prashant111/bagging-vs-boosting
使用 Scikit-Learn 进行集成学习:友好的介绍
原文:
towardsdatascience.com/ensemble-learning-with-scikit-learn-a-friendly-introduction-5dd64650de6c
像 XGBoost 或随机森林这样的集成学习算法是 Kaggle 比赛中的顶尖模型之一。它们是如何工作的?
·发布于 Towards Data Science ·阅读时长 7 分钟·2023 年 9 月 9 日
–
来源:unsplash.com
基础学习算法如逻辑回归或线性回归通常过于简单,无法为机器学习问题提供足够的结果。虽然使用神经网络可能是一种解决方案,但它们需要大量的训练数据,这种数据很少有。集成学习技术可以在数据量有限的情况下提升简单模型的性能。
想象一下,让一个人猜测一个大罐子里有多少颗糖豆。一个人的答案不太可能是准确的估计数字。相反,如果我们问一千个人同样的问题,平均答案可能会接近实际数字。这种现象被称为集体智慧[1]。在处理复杂的估计任务时,集体往往比个体更为精准。
集成学习算法利用这一简单原理,通过聚合一组模型(如回归模型或分类器)的预测来提升性能。对于分类器的聚合,集成模型可以简单地选择低级分类器预测中最常见的类别。相反,对于回归任务,集成模型可以使用所有预测的均值或中位数。
图片来源于作者。
通过集成大量的弱学习者,即那些仅比随机猜测略好一点的分类器或回归器,我们可以取得难以想象的结果。考虑一个二分类任务。通过集成 1000 个独立的分类器,每个分类器的准确率为 51%,我们可以创建一个准确率为 75% 的集成模型 [2]。
这就是为什么集成算法在许多机器学习竞赛中常常获胜的原因!
现有几种技术可以构建集成学习算法。主要有 bagging、boosting 和 stacking。以下部分我将简要描述每一种原理,并介绍实现这些原理的机器学习算法。
Bagging
形成集成算法的第一种技术称为 bagging,它是bootstrap aggregating的缩写。核心思想是为每个弱学习者提供一个略有不同的训练集。这是通过随机抽样原始训练集来完成的。
如果采样是有放回的,这种技术称为bagging,否则如果采样是没有放回的,这种技术则被称为pasting。
bagging(套袋)和 pasting(粘贴)的关键思想是尽可能创建多样化的弱学习者,这通过使用随机生成的训练集来完成。由于采样是有放回的,bagging 引入了比 pasting 略多的多样性,因此通常更受青睐。
让我们通过一个例子来看看 bagging 的工作原理。假设原始训练集包含 10 个示例,我们想要构建一个由 3 个不同的弱学习者组成的集成。此外,我们希望在原始训练集的一个维度为 5 的子集上训练每个学习者。以下图片展示了训练集的可能划分方式:
图片由作者提供。
而 pasting 不允许在模型的训练子集中重复相同的训练示例:
图片由作者提供。
随机森林
最常见的 bagging 模型是随机森林。随机森林是决策树的集成,每棵树都在一个略有不同的训练集上训练。
对于随机森林中每棵决策树的每个节点,算法会随机选择特征来搜索最佳的分裂点。换句话说,算法不会在所有特征中寻找最佳的分裂点,而是在一部分可用特征中寻找最佳的分裂点。这就是“随机”一词的解释。
以下代码片段展示了如何在一些训练数据上创建和拟合一个随机森林分类器。
一些属性非常重要,我建议通过网格搜索方法对其进行调优。n_estimators定义了弱学习器的数量,max_features是每次分裂时考虑的特征数量,max_depth是树的最大深度。这些超参数在正则化中起着基础性作用。增加n_estimators和min_sample_leaf或减少max_features和max_depth有助于创建尽可能多样化的树,从而避免过拟合。
对于所有其他属性,请查看全面的文档。
极端随机树(Extra Trees)
为了进一步增加树的随机性,我们可以使用极端随机树算法,简称为极端随机树(Extra Trees)。它的工作方式类似于随机森林,但在每个决策树的每个节点,算法在每个特征的随机阈值范围内寻找最佳可能的分裂。而随机森林则在特征的整个值范围内寻找最佳分裂。
相较于随机森林,极端随机树有一个额外的随机组件。因此,它用更高的偏差换取了较低的方差[2]。
极端随机树的第二个优势是训练比随机森林更快,因为它不需要在选定特征的整个值域中寻找最佳分裂。相反,它仅考虑其中的一部分。
使用 Scikit-Learn 实现极端随机树回归器或分类器与实现随机森林一样简单:
参数与随机森林模型相同。
通常很难预测随机森林(Random Forest)或极端随机树(Extra Trees)对于特定任务的表现哪个更好。因此,我建议同时训练这两种模型,并在之后进行比较。
特征重要性
随机森林和极端随机树的一个优点是它们提供了每个特征减少数据集纯度的能力的度量:这称为特征重要性。换句话说,一个重要性高的特征比一个重要性低的特征能提供更好的分类或回归问题的见解。
训练模型后,我们可以通过属性**feature_importances_**
访问这个度量。
图片由作者提供。
一旦模型训练完成,Scikit-Learn 会自动计算特征的重要性。输出分数被缩放到[0,1]范围内,意味着接近 1 的分数分配给最重要的特征。
在上面的例子中,‘花瓣长度’和‘花瓣宽度’的分数显著高于其他特征。虽然‘萼片长度’对我们的模型有中等重要性,但‘萼片宽度’在这个分类任务中似乎毫无用处。
提升法
继续探讨另一种值得注意的集成技术,我们深入了解 boosting 技术。这种方法在机器学习领域是 bagging 的有力对手。
Boosting,即假设提升,遵循一种有趣的理念。它不是通过随机抽样创建多样化的学习者,而是通过顺序训练预测器来提升单个弱学习者的表现。每个预测器旨在纠正其前一个预测器的错误。这就像教练在球员的弱点上加练,以使他们成为全能明星。
Boosting 由于其强调自我改进和渐进细化,通常在对精度和细节关注的场景中表现优于 bagging 技术。
我们现在将看到最著名且获奖的 boosting 集成技术:XGBoost。
XGBoost
XGBoost,全称极端梯度提升,是一种集成学习方法,采用梯度下降优化,旨在系统性地提高弱学习者的预测性能。
在 XGBoost 中,每个弱学习者根据其错误率被分配一个权重。表现不佳的学习者会被赋予更高的权重,以优先纠正这些错误。这个迭代过程持续进行,模型调整其重点以解决最具挑战的数据点。
XGBoost 是数据科学家和机器学习从业者的热门选择,因为它能够提取有价值的见解并提供卓越的预测准确性。它也因其速度和可扩展性而被广泛应用于 ML 竞赛中。
在这里我们可以看到如何将 XGBoost 应用到实际数据中:
在没有调整超参数的情况下,模型能够实现 98% 的准确率。
结论
当我们结束这次关于机器学习中集成算法的初步旅程时,重要的是要认识到我们的旅程仅仅奠定了更深层次和更专业研究的基础。虽然我们触及了一些基本概念,但这一领域远远超出了这些入门见解。
我推荐深入研究附带的资源和参考文献。这些来源提供了有关高级集成方法、算法优化和实际实施技巧的详细见解。
如果你喜欢这个故事,请考虑关注我,以便接收我即将发布的项目和文章的通知!
下面是我过去的一些项目:
## 欧洲旅行优化:遗传算法和 Google Maps API 解决旅行推销员问题
使用遗传算法和 Google Maps API 浏览欧洲 50 个最受欢迎城市的魅力,开启高效…
towardsdatascience.com ## 从头开始使用 Numpy 构建卷积神经网络
随着计算机视觉应用在我们生活中的普及,理解其工作原理…
towardsdatascience.com
参考文献
[1] 群体智慧 — 剑桥大学数学系
[2] 使用 Scikit-Learn、Keras 和 TensorFlow 的动手机器学习(第 2 版)— Aurélien Géron
[4] XGBoost 文档
[5] 集成方法基础与算法