TowardsDataScience 2023 博客中文翻译(一百四十六)

原文:TowardsDataScience

协议:CC BY-NC-SA 4.0

使用 Python 按位置获取气温数据

原文:towardsdatascience.com/get-temperature-data-by-location-with-python-52ed872dd621

按经纬度检索历史气温数据。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Gustavo Santos

·发表于Towards Data Science ·阅读时长 3 分钟·2023 年 5 月 18 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Tom BarrettUnsplash上的照片

介绍

我一直在处理一些项目,需要按位置找到平均气温,以便将其作为可能的变量添加到我的模型中。在经过一段时间的研究后,我发现了一个非常棒且易于使用的 Python 包,叫做meteostat

这个包有一些有趣的方法,其中一个正是我需要的:如果我输入经纬度,它可以检索该地点的历史气温。此外,你还可以按时间范围请求数据。所以,你可以获取一年的数据或多年的数据。

另一个很酷的功能是,你可以请求你的数据为每日或每月数据。太棒了!

让我们看看代码是如何工作的。

代码

首先,让我们使用pip install meteostat安装 meteostat。接下来,我们可以导入所需的包。

# Import packages
import pandas as pd
from datetime import datetime
import matplotlib.pyplot as plt
from meteostat import Point, Monthly

如果你访问文档,你会看到这段入门代码,这基本上是你需要的工作内容。我们设置了一个时间范围——我用了 2022 年。然后我们创建一个变量来保存经纬度信息。我将使用这个Point(40.78325, -73.96565),它是纽约市中央公园的经纬度。最后,我们会请求在选定日期之间的Monthly数据,然后获取这些数据。

# Set time period
start = datetime(2022, 1, 1)
end = datetime(2022, 12, 31)

# Create Point for New York, NY
tpr = Point(40.78325, -73.96565)

# Get monthly data for 2022
data = Monthly(tpr, start, end)
data = data.fetch()

这就是你需要做的基本内容。以下是获取的数据的样子。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2022 年纽约市——曼哈顿的气温(摄氏度)。作者提供的图片。

如果你需要每日数据,可以导入Daily而不是Monthly,并在代码中进行替换。

你也可以使用 Pandas 轻松绘制数据。

# Plot line chart including average, minimum and maximum temperature
data.plot(y=['tavg', 'tmin', 'tmax'], 
          title='Temperature 2022 - Central Park, NYC')
plt.show()

代码生成的图如下所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

温度图。图片由作者提供。

如果我们想查看提供这些结果的站点,以下是代码。

# Import Meteostat library
from meteostat import Stations

# Get nearby weather stations from our interest point
stations = Stations()
stations = stations.nearby(40.78325, -73.96565)
# Fetching 5 stations
station = stations.fetch(5)

# Print DataFrame
pd.DataFrame(station)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5 个位于中央公园附近的气象站。图片由作者提供。

离开之前

就这些了。一个快速但有用的教程。

GitHub 仓库:

[## Studying/Python/meteostat at master · gurezende/Studying

目前你无法执行该操作。你在另一个标签页或窗口中登录了。你在另一个标签页或窗口中登出了…

github.com

如果你需要用于项目的温度数据,我相信meteostat可以帮助你。查看他们的文档获取更多信息。

如果你喜欢这个内容,记得关注我以获取更多信息。

[## Gustavo Santos - Medium

在 Medium 上阅读 Gustavo Santos 的文章。数据科学家。我从数据中提取见解,以帮助个人和公司…

gustavorsantos.medium.com

另外,可以在 LinkedIn 上找到我,或在 topmate 上预约时间与我讨论数据科学。

参考

[## Python 库 | Meteostat 开发者

Meteostat Python 库提供了通过 Pandas 简单访问开放天气和气候数据的功能。历史数据…

dev.meteostat.net

从 Pandas GroupBy 中获得最大收益

原文:towardsdatascience.com/get-the-most-from-pandas-groupby-fa2b6db3eccc

从基础示例到实际练习

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Kurt Klingensmith

·发表于 Towards Data Science ·6 min read·2023 年 10 月 6 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Alex SuprunUnsplash 上的照片。

Python 的 pandas 库包含许多用于查询和操作数据的有用工具,其中之一是强大的 GroupBy 函数。该函数允许按各种类别对观察值进行分组,并以多种方式进行聚合。

这可能一开始听起来有些困惑,但本指南将详细介绍如何使用该函数及其各种功能。该操作包括:

  • GroupBy 的介绍。

  • 将 GroupBy 应用于实践数据集。

  • 各种 GroupBy 技术。

  • 实际练习和应用。

代码和数据:

本文档中使用的数据和完整的 Python 代码的 Jupyter notebook 可在链接的 GitHub 页面上获取。下载或克隆该仓库以跟随操作。本指南使用了由作者为本文生成的合成数据和虚假姓名;数据可在链接的 GitHub 页面上获取。

代码需要以下库:

# Data Handling
import pandas as pd
import numpy as np

# Data visualization
import plotly.express as px

1.1. 开始使用——数据加载和 GroupBy 基础

第一步是加载数据集:

# Load Data:
df = pd.read_csv('StudentData.csv')
df.head(3)

这将得到以下数据框,包含了参加了一系列学校测试的学生的信息。它包括他们的年龄、三次测试分数、上课时间、平均成绩、字母等级以及他们是否通过了:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图

Pandas 的 GroupBy 允许将数据框分割成感兴趣的元素,并对其应用某种函数。思考 GroupBy 的最简单方法是提出一个 GroupBy 操作可以解决的问题。一个简单的起点是问有多少学生通过了课程:

df.groupby('CoursePass')['CoursePass'].count()

在上述代码行中,GroupBy 对“CoursePass”列进行分组,然后对“CoursePass”列执行计数函数。这返回一个简单的计数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者提供。

这与 value_counts() 操作非常相似,执行方式如下:

df.CoursePass.value_counts()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者提供。

这只是一个好的开始,但 GroupBy 可以执行更多高级操作。让我们查看多个列以及关于学生数据的更复杂问题。

1.2. 使用多个列的 GroupBy()

假设我们想知道每节课程(下午、晚上和早晨)有多少学生及格。以下 GroupBy 代码可以迅速回答这个问题:

df.groupby(['ClassSession', 'CoursePass'])['CoursePass'].count()

上述代码按“ClassSession”和“CoursePass”列进行分组,同时返回每个 CoursePass 状态(“是”或“否”)的计数。结果是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者提供。

注意,括号内列的顺序很重要。交换“ClassSession”和“CoursePass”的顺序会得到以下结果:

df.groupby(['CoursePass', 'ClassSession'])['ClassSession'].count()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者提供。

在进一步探索 GroupBy 的更高级应用之前,让我们看看如何清理输出以获得更好的展示效果。

1.3. 清理 GroupBy 输出

有几种方法可以将标准 GroupBy 输出转换为更干净的 dataframe 格式。让我们以其中一个示例为例,将“.to_frame()”添加到代码末尾:

df.groupby(['ClassSession', 'CoursePass'])['CoursePass'].count().to_frame()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者提供。

注意,这会返回多层列而没有索引。同时注意到有两个列名为“CoursePass”。要展平列、调整名称并添加索引,请使用以下代码:

df.groupby(['ClassSession', 'CoursePass'])['CoursePass'].count().reset_index(name='Count')

这会返回如下结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者提供。

将 reset_index() 添加到操作中会展平列并添加索引;在 reset_index() 中传递一个名称可以将计数列(在此情况下为“CoursePass”)命名为“Count”。如果未在 reset_index() 中重命名列,则会因两个列名为“CoursePass”而返回错误。

这可以通过完全隐藏索引进一步改进:

df.groupby(['ClassSession', 'CoursePass'])['CoursePass'].count().reset_index(name='Count').style.hide_index()

输出是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者提供。

接下来,让我们查看更高级的 GroupBy 函数。

1.4. 高级 GroupBy 功能

GroupBy 可以创建所选列的对象。下面的代码基于两个感兴趣的列创建了一个 GroupBy 对象;对该对象应用 mean() 函数,并传递另外两列,返回这些列的均值:

# Create a groupby object:
dfGroupby = df.groupby(['LetterGrade', 'CoursePass'])
dfGroupby[['Test1', 'Test2']].mean()

结果是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者提供。

注意输出是如何按“LetterGrade”和“CoursePass”列分组的,并返回“Test1”和“Test2”列的平均值,这两个列是从初始 GroupBy 对象中选择用于 mean() 函数的。

通过使用多个聚合,这可以提升到更高级的水平。考虑以下代码:

dfGroupby = df.groupby(['LetterGrade', 'CoursePass'])
dfGroupby[['Grade', 'Age']].agg(['mean', 'min', 'max']).reset_index()

这返回:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图。

上述代码回答了几个问题:按 LetterGrade 和 CoursePass 排序,每个学生的平均值、最小值和最大值的成绩以及每个学生的平均值、最小值和最大值的年龄?

创建 GroupBy 对象并非总是必要的;agg() 函数可以回答相当复杂的问题。假设我们想要通过 CoursePass 和 ClassSession 进行筛选,以查找每个学生的平均年龄和成绩;以下代码提供了答案:

df.groupby(['CoursePass', 'ClassSession']).agg({'Age':'mean', 'Grade':'mean'})

输出是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图。

aggregate 函数还可以传递 numpy 操作:

data = df.groupby(['CoursePass', 'ClassSession'])['Grade'].agg([np.mean, np.max, np.min]).reset_index()

data = data.rename(columns={'mean':'AverageGrade',
                            'amax':'HighestGrade',
                            'amin':'LowestGrade'})

data.style.hide_index()

这产生了:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图。

aggregate 函数也可以直接重命名列:

df.groupby(['CoursePass', 'ClassSession'])\
        .agg(AverageGrade=('Grade', 'mean'),
             HighestGrade=('Grade', 'max'),
             LowestGrade=('Grade', 'min'))

这返回:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图。

GroupBy 的语法可能性数量意味着对有关数据框的复杂问题,可能存在一个优雅的代码解决方案。现在我们已经探讨了基础知识,让我们看看如何应用 GroupBy 的一些实际示例。

2. 练习:快速可视化成绩计数

要求: 给定学生课程的测试成绩,在一个图表上可视化每个班级会话中每个字母成绩的总数。

让我们先看看数据:

df.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图。

需求关注的是字母成绩和班级会话;这意味着 GroupBy 将按 ClassSession 和 LetterGrade 列排序。需求还需要总数;让我们使用 count() 函数看看返回的结果:

session = df.groupby(['ClassSession', 'LetterGrade'])['LetterGrade'].count().reset_index(name='Count')

session = session.sort_values(by='LetterGrade', ascending = True)

session

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图。

上述代码按班级会话和字母成绩对数据进行了分组,同时计算了每个分组组合中每个字母成绩的出现次数。sort_values() 代码按字母成绩 A 到 F 排序。剩下的就是可视化数据:

# Generate plot:
plot = px.histogram(session,
               y='Count',
               x='LetterGrade',
               color='ClassSession')
plot.update_layout(
    title={'text': "Grade Distribution\
                    <br><sup>Number of Grades by Type and Class Session</br>",
           'xanchor': 'center',
           'yanchor': 'top',
           'x': 0.47},
    xaxis_title='Letter Grade',
    yaxis_title='Count')
plot.show()

这生成了以下图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图。

只需几行代码,问题就得到了解答!

3. 结论。

Pandas 的 GroupBy 函数是一个强大的工具,可以快速对数据框中的特定数据分组执行聚合和数学操作。通常,一次函数执行就足以回答一个看似复杂的问题。掌握 GroupBy 的使用为数据科学家提供了一个有效的数据准备和处理工具。随意使用提供的笔记本和 链接到 GitHub 页面上的代码,进一步尝试 GroupBy 的功能吧!

从 AI/ML 入手,构建智能供应链

原文:towardsdatascience.com/getting-started-with-ai-ml-to-build-intelligent-supply-chains-76829f492ef8

您应该如何考虑在供应链中应用 AI/ML 技术,以最大化投资回报?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Ramkumar K

·发表于 Towards Data Science ·7 分钟阅读·2023 年 4 月 10 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Volodymyr Hryshchenko 提供,发布在 Unsplash

背景

供应链优化是一个广泛的研究领域。在供应链中,有大量用例可以从 AI/ML 技术的应用中受益。组织往往难以确定从何入手以及如何开始。供应链高管通常寻求投资团队(已经非常紧张)的时间和精力,以从这些方法中获得最大价值。在本文中,我们探讨了一组小而多样的用例,作为供应链组织进入 AI/ML 领域的起点。供应链领导者可以期望从这些应用中获得高程度的成本和效率改善。

我们将供应链管理分为五个组成部分:计划、采购、生产、交付、逆向物流,并概述了与这五个组成部分对应的 需求感知供应商细分设备故障预测交付时间预测客户退货预测 的用例。根据经济价值、可追踪性、结果可解释性、洞察可操作性和应用可持续性等标准,我们对每个用例的整体效益进行了定性评估。

用例探索

智能供应链 集成了数据、自动化和先进的分析技术,为供应链的不同部分带来效率和成本降低。它通过提升客户体验,成为组织的战略优势来源。通常,它由优化和 AI/ML 技术的组合支持。我们探讨了五个用例,并将其映射到供应链管理的五个要素:计划 → 采购 → 制造 → 交付 → 逆向物流。

1. 短期需求感知(计划):库存管理是供应链中至关重要的活动。营运资本和存储成本与库存水平相关,而库存水平又依赖于准确预测需求等因素。高水平的预测准确性有助于通过在正确的地点和时间生产合适数量的产品来减少库存成本和缺货情况。这有助于优化仓库中的库存,降低安全库存水平,从而减少成本,同时避免可能导致长期业务和收入损失的缺货现象。一个启用了 AI 的应用可以识别客户订单中的模式,并将某些领先指标与短期需求相关联,从而比传统方法更准确。通过实时订单信息,我们可以自动化当前和下一个月的需求预测,并定期更新。

2. 供应商细分(采购):大型组织可能有数百或数千个供应商,这些供应商是其供应链的重要组成部分。不同的原材料以不同的数量从供应商处采购。为了在增加供应可靠性的同时降低采购成本,应用不同的策略于不同的供应商将会非常有帮助。考虑到供应商数量众多,将供应商分为几个关键组将会很有益。这种细分可以实现对原材料价格、数量和供应时间的有针对性的合同谈判,从而优化支出。一个启用了 AI 的应用可以基于特征如数量、价格、战略关系和可靠性来细分供应商,使采购专家能够对一个集群内的供应商采用类似的采购策略。此细分可以每月或每季度更新,以适应供应商的变化。

  1. 设备故障预测(制造):由于可靠性故障导致的计划外停机在制造操作中很常见。这往往会影响产品库存位置,并可能导致客户履约延迟。预测这些停机可能发生的时间可以帮助工厂采取措施减少设备故障风险,或提前准备库存以应对停机。这些预测和相应的缓解措施可以帮助避免缺货和收入损失,同时推动对预防性维护选项的投资,以避免昂贵的维修。启用人工智能的应用可以将设备故障与关键测量(如产量、压力、温度等)相关联,提供故障发生时间的见解。根据测量的粒度,该应用可能每天或每几天运行一次,以评估故障风险。

  2. 交货时间预测(交付):准时交付给客户是衡量供应链表现的关键指标,这直接影响客户体验。组织会测量这一指标,并根据历史延迟趋势积极尝试改进。能够准确预测交货时间可以帮助在要求的时间内将产品送到客户手中,从而避免糟糕的客户体验和由此带来的商业损失,并避免因迟交而产生的罚款和其他费用。启用人工智能的应用可以基于开始日期和时间、季节、承运人、来源和目的地等属性预测交货时间。这样的预测可以使每次发货时保持客户知情,提升客户体验和客户留存。此外,这还提供了优化路线和选择表现更佳的承运人的机会。

  3. 客户退货预测(逆向物流):由于未达到质量规格或运输延迟等原因,客户会退回一定比例的销售产品。为了准备退货运输、储存和处理,公司需要准确估算退回产品的数量。这有助于减少储存和处理成本。启用人工智能的应用可以根据过去几周的客户发货量提供退货的总体量。此预测可以每周更新一次。

用例优先级排序

我们通过五个关键标准来评估这些用例:经济价值、可处理性、结果可解释性、洞察行动性和应用可持续性。经济价值包括任何成本节约或收入损失避免。可处理性指的是数据的可用性以及提供合理时间内预测的稳健 AI/ML 方法。结果可解释性指的是如何使用业务驱动因素向利益相关者解释观察和预测。洞察行动性描述了组织在 AI/ML 应用结果上的行动能力。最后,应用可持续性描述了长期积极维护和更新 AI 应用输入的可行性。

(i) 经济价值:由于运输量巨大,我们预计需求感知交货时间预测的经济价值为‘高’。对于供应商细分设备故障预测,由于采取措施的零散性,其经济价值评估为‘中’;而由于客户退货量相对较低,因此选择了‘低’评估。

(ii) 可处理性:根据用例数据规模和我们拥有的计算能力,大多数用例的可处理性预期为‘高’,除了设备故障预测,如果故障发生不够频繁,可能会数据有限。

(iii) 结果可解释性:推荐对需求感知客户退货预测应用多元线性回归,这会获得‘高’的可解释性评分。对供应商细分应用无监督方法(如 k-means 聚类)可以显示每个簇中的特征接近,因此可解释性标记为‘高’。对设备故障预测交货时间预测应用更复杂的集成方法(如随机森林、Xgboost)则导致‘中’的可解释性。

(iv) 洞察行动性:对于需求感知客户退货预测,行动性标记为‘高’,因为这是基于预测变化来改变生产和处理的内部决策;而交货时间预测供应商细分的洞察则需要与外部方(包括承运人和供应商)谈判,这可能会限制我们的灵活性。对于设备故障预测,行动性为‘中’,我们可能能够采取措施降低风险,但可能无法完全消除故障。

(v) 应用可持续性:假设五个用例中的四个具有较高的可持续性,因为数据可能以适当的速度生成,允许频繁更新 AI/ML 应用,除了设备故障预测,可能数据有限。

从下表汇总的这些用例来看,需求感知 在所有这些标准中评分最高——在这种情况下,建议从这个用例的 AI/ML 应用开始。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

用例定性评分对比多个标准

结论

在许多行业中,AI/ML 技术在供应链和业务优化中的应用仍然是一个新兴领域。采取“爬行、行走、奔跑”的方法来整合 AI/ML 进入操作并非不合理。通过“低垂的果实”来展示 AI/ML 为团队创造价值的有效性,可以产生飞轮效应。然而,重要的是在较小的成功基础上构建可持续的长期商业模式,使 AI/ML 融入价值链的每个方面。

感谢阅读。希望你觉得有用。欢迎将你的评论发送至 rkumar5680@gmail.com。我们可以在 LinkedIn 上联系。

开始使用 Databricks

原文:towardsdatascience.com/getting-started-with-databricks-11af3db4f595

Databricks 初学者指南

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Sadrach Pierre, Ph.D.

·发布于 Towards Data Science ·9 分钟阅读·2023 年 5 月 8 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Alexander Grey 提供,来源于 Pexels

Databricks 使数据科学家能够轻松创建和管理用于研究、实验和部署的笔记本。像 Databricks 这样的平台的吸引力包括与云服务的无缝集成、模型维护工具和可扩展性。

Databricks 对于模型实验和维护非常有用。Databricks 拥有一个机器学习库,称为 MLflow,提供了用于模型开发和部署的有用工具。使用 MLflow,你可以记录模型以及与模型相关的元数据,例如性能指标和超参数。这使得运行实验和分析结果变得非常简单。

许多 Databricks 功能对于在机器学习工作流中的步骤进行扩展非常有用,例如数据加载、模型训练和模型日志记录。Koalas 是 Databricks 中一个更高效的替代 pandas 的库。Pandas 用户定义函数(UDF)允许你以分布式的方式应用自定义函数,这些函数通常计算成本较高,这可以显著减少运行时间。Databricks 还允许你在更大的机器上配置作业,这对于处理大型数据和繁重计算非常有用。此外,模型注册表允许你运行和存储数百甚至数千个模型的实验结果。这在扩展研究人员开发并最终部署的模型数量方面非常有用。

在本文中,我们将介绍一些 Databricks 的基础知识。首先,我们将通过一个简单的数据科学工作流程来构建一个流失分类模型。然后,我们将看看如何使用 Koalas 和 Pandas UDF 等工具来加快特定操作的速度。最后,我们将看到如何使用 Mlflow 来帮助我们运行实验并检查结果。

在这里,我们将使用Telco 流失数据集。该数据包含一个虚构电信公司客户的账单信息。它指定了客户是否停止或继续使用服务,即流失。该数据公开可用,并可以在Apache 2.0 许可证下免费使用、分享和修改。

入门指南

首先,访问Databricks网站并点击“免费试用”:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者拍摄

您应该看到以下内容:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者拍摄

输入您的信息并点击继续。接下来,系统会提示您选择一个云平台。本文不会涉及任何外部云平台。在右侧面板底部点击“开始使用社区版”。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者拍摄

接下来,按照步骤创建一个社区版账户。

导入数据

让我们从左侧面板中的“数据”选项卡开始:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者拍摄

接下来点击“数据”,然后点击“创建表”:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者拍摄

接下来,将流失 CSV 文件拖放到标记为“拖放文件上传,或点击浏览”的区域。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者拍摄

上传 CSV 后,您应该看到以下内容:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者拍摄

接下来点击“在笔记本中创建表”。一个 Databricks 文件存储(DBFS)示例笔记本,将弹出并包含将文件写入 Databricks 文件存储的逻辑:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者拍摄

DBFS 允许 Databricks 用户上传和管理数据。该系统是分布式的,因此非常适合存储和管理大量数据。

第一个单元指定了读取我们上传的流失数据的逻辑:

# File location and type
file_location = "/FileStore/tables/telco_churn-1.csv"
file_type = "csv"

# CSV options
infer_schema = "false"
first_row_is_header = "false"
delimiter = ","

# The applied options are for CSV files. For other file types, these will be ignored.
df = spark.read.format(file_type) \
  .option("inferSchema", infer_schema) \
  .option("header", first_row_is_header) \
  .option("sep", delimiter) \
  .load(file_location)

display(df)

如果我们运行这个单元,我们会得到以下结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者拍摄

我们看到表格中包含了一些不太有用的列名(_c0, _c1,等等)。为了解决这个问题,我们需要指定 first_row_is_header= “true”:

first_row_is_header = "true"

当我们运行这个单元时,我们现在得到:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者拍摄

如果你点击表格,可以向右滚动查看数据中的额外列:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者拍摄

构建分类模型

我们接下来使用在 Databricks 中上传的数据构建流失分类模型。在左侧面板中点击“创建”:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者拍摄

接下来点击笔记本:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者拍摄

我们将笔记本命名为“churn_model”:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者拍摄

现在我们可以复制 DBFS 示例笔记本中的逻辑,以便访问数据:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者拍摄

接下来,我们将 Spark 数据框转换为 Pandas 数据框:

df_pandas = df.toPandas()

我们来构建一个 Catboost 分类模型。Catboost 是一种基于树的集成机器学习算法,它使用梯度提升来提高集成中连续树的性能。

我们来通过 pip 安装 Catboost 包。我们在笔记本顶部的一个单元格中执行此操作:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者拍摄

接下来,我们构建一个 Catboost 流失分类模型。我们将使用任期、每月费用和合同来预测流失结果。我们将流失列转换为二进制值:

import numpy as np 
df_pandas['churn_label'] = np.where(df_pandas['Churn']== 'No', 0, 1)
X = df_pandas[["tenure", "MonthlyCharges", "Contract"]]
y = df_pandas['churn_label']

Catboost 允许我们直接处理分类变量,无需将其转换为机器可读的代码。为此,我们只需定义一个包含分类列名称的列表:

cats = ["Contract"]

在定义 Catboost 模型对象时,我们将 cat_features 参数设置为此列表。我们将数据分为训练集和测试集:

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

然后我们可以训练 Catboost 模型。我们将使用默认参数值:

model = CatBoostClassifier(cat_features= cats, random_state=42)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)

我们可以评估模型性能:

from sklearn.metrics import accuracy_score, precision_score
accuracy = accuracy_score(y_pred, y_test)
precision = precision_score(y_pred, y_test)

print("Accuracy: ", accuracy )
print("Precision: ", precision )

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

截图由作者拍摄

Koalas

这里我们将一个 Spark 数据框转换为 Pandas 数据框。这对于我们的小数据集来说很好,但随着数据量的增加,Pandas 变得缓慢且效率低下。Pandas 的替代方案是 Koalas 库。Koalas 是 Databricks 开发的一个分布式版本的 Pandas。要使用 Koalas,我们可以在笔记本顶部使用 pip 安装 Databricks:

%pip install -U databricks

我们从 databricks 导入 Koalas:

from databricks import koalas as ks

要将我们的 Spark 数据框转换为 Koalas 数据框,我们可以执行以下操作:

df_koalas = ks.DataFrame(df)
df_koalas.head()

Pandas UDF

Pandas UDF 是 Databricks 中的另一个有用工具。它允许你以分布式方式应用函数到数据框上。这对于提高对大数据框进行计算的效率非常有用。例如,我们可以定义一个函数,该函数接受一个数据框并构建一个 Catboost 模型。然后我们可以使用 Pandas UDF 在分组或分类层次上应用这个函数。让我们为每个互联网服务值构建一个模型。

首先,我们需要定义 Pandas UDF 的函数和模式。模式简单地指定了列名及其数据类型:

from pyspark.sql.functions import pandas_udf, PandasUDFType

churn_schema = StructType(
    [
        StructField("tenure", FloatType()),
        StructField("Contract", StringType()),
        StructField("InternetService", StringType()),
        StructField("MonthlyCharges", FloatType()),
        StructField("Churn", FloatType()),
        StructField("Predictions", FloatType()),

    ]
)

接下来我们将定义我们的函数。我们将把之前定义的逻辑简单地包含在一个名为‘build_model’的函数中。为了使用 Pandas UDF,我们添加装饰器‘@pandas_udf’:

@pandas_udf(churn_schema, PandasUDFType.GROUPED_MAP)
def build_model(df: pd.DataFrame) -> pd.DataFrame:

我们还可以在我们的函数中包含模型构建逻辑。我们还会将预测和真实流失值存储在我们的数据框中:

@pandas_udf(churn_schema, PandasUDFType.GROUPED_MAP)
def build_model(df: pd.DataFrame) -> pd.DataFrame:
    df['churn_label'] = np.where(df['Churn']== 'No', 0, 1)
    X = df[["tenure", "MonthlyCharges", "Contract"]]
    y = df['churn_label']
    cats = ["Contract"]
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
    model = CatBoostClassifier(cat_features= cats, random_state=42)
    model.fit(X_train, y_train)
    y_pred = model.predict(X_test)
    output = X_test
    output['Prediction'] = y_pred
    output['Churn'] = y_test
    output['InternetService'] = df['InternetService']
    output['churn_label'] = df['churn_label']
    return output

最后,我们可以将这个函数应用到我们的数据框中。让我们将我们的 Koalas 数据框转换回 spark 数据框:

 df_spark = df_koalas.to_spark()
churn_results = (
df_spark.groupBy('InternetService').apply(build_model))

然后我们可以将生成的 spark 数据框转换为 Pandas 数据框(也可以转换回 Koalas),并显示前五行:

churn_results = churn_results.toPandas()
churn_results.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图

即使我们存储了预测结果,你也可以使用 Pandas UDF 来存储你在数据框计算结果中获得的任何信息。一个有趣的练习是将准确度评分和精确度评分包含在输出的 spark 数据框中,每个互联网服务值都有。

开始使用 MLflow

在 Databricks 中,另一个有用的工具是 MlFlow。MlFlow 允许你轻松运行、记录和分析实验。在本演示中,我们将使用之前在笔记本中定义的第一个模型对象。让我们在笔记本的顶部使用pip install Mlflow

%pip install -U mlflow

并导入 Mlflow:

import mlflow

让我们通过设置实验名称继续:

mlflow.set_experiment(
      f"/Users/spierre91@gmail.com/churn_model"
  )

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图

我们可以记录的一件事是 Catboost 特征重要性,这将帮助我们分析哪些特征对预测流失重要:

feature_importance = pd.DataFrame(
      {"variable": model.feature_names_, "importance": model.feature_importances_}
  )
feature_importance.to_csv("/feature_importance.csv")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图

然后我们可以使用log_model方法记录我们的 Catboost 模型:

with mlflow.start_run(run_name=f"churn_model"):
    mlflow.sklearn.log_model(model, "Catboost Model")

我们收到通知,说明“已记录 1 次实验运行到 Mlflow”:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图

我们可以点击运行并查看以下内容:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图

在这里我们可以看到模型性能和模型工件(如特征重要性)的指标。我们将很快展示如何在 Mlflow 中记录这两者。

我们还可以点击实验:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图

这里我们可以看到与实验相关的每次运行。这对于跟踪实验如修改 Catboost 参数、训练数据、工程特征等非常有用。

最后,让我们将特征重要性记录为工件,将准确度分数和精确度分数记录为指标,并将分类输入列表记录为参数:

with mlflow.start_run(run_name=f"churn_model"):
    mlflow.sklearn.log_model(model, "Catboost Model")
    mlflow.log_artifact("/feature_importance.csv")
    mlflow.log_metric("Precison", precision)    
    mlflow.log_metric("Accuracy", accuracy)       
    mlflow.log_param("Categories", cats)

如果我们点击运行,我们可以看到记录了特征重要性、准确度分数和精确度分数,以及分类输入:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者截图

Databricks notebook 中的代码已移植到一个 ipython 文件,并可以在GitHub上获取。

结论

在这篇文章中,我们讨论了如何开始使用 Databricks。首先,我们展示了如何将数据上传到 DBFS。然后,我们创建了一个 notebook,并展示了如何在 notebook 中访问上传的文件。接着,我们讨论了 Databricks 中的一些工具,这些工具可以帮助数据科学家和研究人员扩展数据科学解决方案。首先,我们展示了如何将 spark 数据框转换为 Koalas 数据框,后者是 Pandas 的更快替代品。然后,我们展示了如何使用 Pandas UDF 将自定义函数应用于 spark 数据框。这对于需要在大型数据框上执行的重计算任务非常有用。最后,我们展示了如何记录与建模实验相关的指标、参数和工件。对这些工具的熟悉对于从事数据科学、机器学习和机器学习工程的人员来说非常重要。

入门 Great Expectations:Python 中的数据验证指南。

原文:towardsdatascience.com/getting-started-with-great-expectations-a-guide-to-data-validation-in-python-95a8ffc2b747

学习如何用几行 Python 代码防止数据质量问题。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Eugenia Anello

·发表于 Towards Data Science ·阅读时间 5 分钟·2023 年 7 月 12 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片来源:Link HoangUnsplash

当你与公司合作进行数据科学项目时,通常没有唯一的测试集,不像大学和研究那样,而是不断从客户那里收到更新的样本。

在将机器学习模型应用于新样本之前,你需要验证其数据质量,例如列名、列类型以及字段分布,这些应该与训练集和旧测试集相匹配。

手动分析数据可能非常耗时,尤其是当数据很脏且具有超过 100 个特征时。幸运的是,有一个救命的 Python 库,叫做Great Expectations。这是否引起了你的兴趣?让我们开始吧!

什么是 Great Expectations?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者插图。来源:flaticon

Great Expectations 是一个开源 Python 库,专门解决管理数据的三个重要方面:

  • 验证数据是否符合一些重要条件或期望。

  • 自动化数据分析,快速测试数据而无需从头开始。

  • 格式化文档,包含期望和验证结果。

在本教程中,我们将专注于验证数据,这在处理实际数据时是主要问题之一。

阿姆斯特丹的 Airbnb 房源

我们将分析由 Inside Airbnb 提供的 Airbnb 列表数据。我们将使用来自 阿姆斯特丹 的数据集。数据集已经分为训练集和测试集。正如你从数据集的名称中可能猜到的那样,目标是预测房源价格。如果我们仅关注评论数量,我们可以注意到测试数据的评论数量变异性大于训练集的评论数量。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者插图

我们应该问自己一个问题:“我们还遗漏了哪些差异?让我们开始使用这个库吧!

目录:

  • 需求

  • 加载文件

  • 创建期望

需求

在安装库之前,建议 安装 Python 3 并创建虚拟环境。在激活环境后,我们可以安装 Python 库:

pip install great_expectations

你还需要从 Kaggle 下载数据以跟随教程。文件应包含在“data”文件夹中。

加载文件

就像在 Pandas 中一样,great expectations 库也有相应的方法来导入 CSV 文件:

import pandas as pd
import great_expectations as gx
test_df = gx.read_csv('data/test.csv')

如果你有其他类型的数据,比如 JSON、parquet 和 XLSX,你可以直接使用 Pandas 方法。

test_df.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者插图

这是对我们测试数据和我们将在下一步分析的变量的快速概述。

创建期望

在这个库中,期望值 由几个测试组成,验证你的数据质量。这个库的优点是你不需要手动检查,因为已经实现了 300 多个具有直观名称的期望值。

  1. 检查列名是否与之前相同

假设客户给我们发送了一个新样本,我们想检查它是否包含与训练集相同的列名。如果你问 ChatGPT,Pandas 中有很多方法可以做到这一点,但使用 great expectations 有一种更直观的方法:

l_train_column_names = ['id','neighbourhood','room_type','price',
 'minimum_nights','number_of_reviews','last_review','availability_365']
test_df.expect_table_columns_to_match_set(column_set=l_train_column_names)

输出:

{
  "success": false,
  "meta": {},
  "exception_info": {
    "raised_exception": false,
    "exception_traceback": null,
    "exception_message": null
  },
  "result": {
    "observed_value": [
      "availability_365",
      "last_review",
      "minimum_nights",
      "number_of_reviews",
      "price",
      "room_type"
    ],
    "details": {
      "mismatched": {
        "missing": [
          "id",
          "neighbourhood"
        ]
      }
    }
  }
}

从结果中,我们可以看到该方法找到了大部分列,除了 id 和 neighbourhood 字段。由于条件没有完全满足,“success” 键的值为 false。

2. 检查 last_review 中是否没有空值

缺失值是处理真实数据时的主要问题之一:

test_df.expect_column_values_to_not_be_null('last_review')

输出:

{
  "success": false,
  "meta": {},
  "exception_info": {
    "raised_exception": false,
    "exception_traceback": null,
    "exception_message": null
  },
  "result": {
    "element_count": 1522,
    "unexpected_count": 143,
    "unexpected_percent": 9.395532194480946,
    "unexpected_percent_total": 9.395532194480946,
    "partial_unexpected_list": []
  }
}

从这个测试中,我们可以看到该列中有 143 个缺失值。

3. 检查 minimum_nights 的类型是否为整数

这可能看起来平淡无奇,但你可能会发现错误,因为模型是在不同类型的列上训练的。因此,这个期望对于避免浪费时间是有用的:

test_df.expect_column_values_to_be_in_type_list('minimum_nights', ['int'])

输出:

{
  "success": true,
  "meta": {},
  "exception_info": {
    "raised_exception": false,
    "exception_traceback": null,
    "exception_message": null
  },
  "result": {
    "observed_value": "int64"
  }
}

期望得到了遵守,突出显示为"success":true

4. 检查最大价格是否在特定区间内

我们之前已经看到价格在训练集和测试集中的分布不同。我们尝试调查最大价格是否在 413 和 12000 之间,这分别对应训练集的第 90 百分位数和最大值:

test_df.expect_column_max_to_be_between(column='price', min_value=413,  max_value=12000)

输出:

{
  "success": true,
  "meta": {},
  "exception_info": {
    "raised_exception": false,
    "exception_traceback": null,
    "exception_message": null
  },
  "result": {
    "observed_value": 7900,
    "element_count": 1522,
    "missing_count": null,
    "missing_percent": null
  }
}

输出结果告诉我们,最大价格为 7900,并且在该区间内。

最后的思考:

我刚刚介绍了 Great Expectations 的概述,以介绍其主要功能:期望。你可以从官方网站探索其他声明性语句或期望。在下一篇文章中,我将介绍数据分析和所有期望的可视化自动化,并汇集在一个文档中。你可以在这里找到 GitHub 代码。感谢阅读!祝你有美好的一天!

免责声明:该数据集的许可为 4.0 国际 (CC BY 4.0)

有用的资源:

开始使用 JAX

原文:towardsdatascience.com/getting-started-with-jax-a6f8d8d0e20

推动高性能数值计算和机器学习研究的未来

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Pier Paolo Ippolito

·发表于 Towards Data Science ·阅读时间 5 分钟·2023 年 7 月 7 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Lance Asper 提供的照片,来源于 Unsplash

介绍

JAX 是 Google 开发的一个 Python 库,用于在任何类型的设备(CPU、GPU、TPU 等)上进行高性能数值计算。JAX 的主要应用之一是机器学习和深度学习研究开发,尽管该库主要设计用于提供执行通用科学计算任务(高度维度矩阵操作等)的所有必要功能。

考虑到特别关注高性能计算,JAX 被设计为在 XLA(加速线性代数)的基础上极其快速。XLA 实际上是一个编译器,旨在加速线性代数操作,并且可以在 TensorFlow 和 Pytorch 等其他框架的后台工作。此外,JAX 数组被设计为遵循与 Numpy 相同的原则,使得迁移旧的 Numpy 代码到 JAX 变得非常容易,并通过 GPU 和 TPU 获得性能提升。

JAX 的主要特点包括:

  • 即时编译(JIT):JIT 和加速硬件使 JAX 比普通的 Numpy 快得多。使用 jit() 函数可以编译并缓存自定义函数与 XLA 内核。通过缓存,我们将增加首次运行函数的总体执行时间,从而大幅减少随后的运行时间。在使用缓存时,确保在需要时清除缓存以避免过时结果(例如,全局变量变化)是很重要的。

  • 自动并行化:异步调度使得 JAX 向量可以延迟计算,仅在访问时才生成内容(在计算完成之前控制权返回程序)。此外,为了实现图优化,JAX 数组是不可变的(类似的概念包括延迟计算和图优化,适用于 Apache Spark)。pmap() 函数可以用于在多个 GPU/TPU 上并行计算。

  • 自动矢量化:可以使用 vmap() 函数进行自动矢量化以并行化操作。在矢量化过程中,算法从对单个值的操作转变为对一组值的操作。

  • 自动微分grad() 函数可以用于自动计算函数的梯度(导数)。特别是,JAX 自动微分使得在深度学习领域之外开发通用的微分程序成为可能。可以通过递归、分支、循环进行微分,执行高阶微分(例如,雅可比矩阵和海森矩阵),并使用前向和反向模式微分。

因此,JAX 能为我们提供构建先进深度学习模型所需的所有基础,但没有提供一些最常见深度学习操作(例如,损失/激活函数、层等)的开箱即用的高级工具。例如,在 ML 训练过程中学到的模型参数可以存储在 JAX 的 Pytree 结构中。考虑到 JAX 提供的所有优势,不同的深度学习框架已经在其基础上构建,例如 Haiku(由 DeepMind 使用)和 Flax(由 Google Brain 使用)。

演示

作为本文的一部分,我们将看到如何使用 JAX 和 Kaggle 移动价格分类数据集 [1] 来解决一个简单的分类问题,以预测手机的价格范围。本文中使用的所有代码(以及更多!)都可以在 我的 GitHubKaggle 账户 上找到。

首先,我们需要确保在环境中安装了 JAX。

pip install jax

目前,我们已经准备好导入必要的库和数据集(图 1)。为了简化分析,我们不使用所有标签中的类别,而是过滤数据以仅使用 2 个类别,并减少特征的数量。

import pandas as pd
import jax.numpy as jnp
from jax import grad
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
import matplotlib.pyplot as plt

df = pd.read_csv('/kaggle/input/mobile-price-classification/train.csv')
df = df.iloc[:, 10:]
df = df.loc[df['price_range'] <= 1]
df.head()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1:移动价格分类数据集(图片由作者提供)。

数据集清理完成后,我们可以将其划分为训练集和测试集,并标准化输入特征,以确保它们都位于相同范围内。此时,输入数据也被转换为 JAX 数组。

X = df.iloc[:, :-1]
y = df.iloc[:, -1]

X_train, X_test, y_train, y_test = train_test_split(X, y, 
                                                    test_size=0.20, 
                                                    stratify=y)

X_train, X_test, y_train, Y_test = jnp.array(X_train), jnp.array(X_test), \
                                   jnp.array(y_train), jnp.array(y_test)

scaler = StandardScaler()
scaler.fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)

为了预测手机的价格范围,我们将从零开始创建一个逻辑回归模型。为此,我们首先需要创建几个辅助函数(一个用于创建 Sigmoid 激活函数,另一个用于二元损失函数)。

def activation(r):
    return 1 / (1 + jnp.exp(-r))

def loss(c, w, X, y, lmbd=0.1):
    p = activation(jnp.dot(X, w) + c)
    loss = jnp.sum(y * jnp.log(p) + (1 - y) * jnp.log(1 - p)) / y.size
    reg = 0.5 * lmbd * (jnp.dot(w, w) + c * c) 
    return - loss + reg 

我们现在准备创建训练循环并绘制结果(图 2)。

n_iter, eta = 100, 1e-1
w = 1.0e-5 * jnp.ones(X.shape[1])
c = 1.0
history = [float(loss(c, w, X_train, y_train))]
for i in range(n_iter):
    c_current = c
    c -= eta * grad(loss, argnums=0)(c_current, w, X_train, y_train)
    w -= eta * grad(loss, argnums=1)(c_current, w, X_train, y_train)
    history.append(float(loss(c, w, X_train, y_train)))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2: 逻辑回归训练历史(作者提供的图片)。

一旦对结果感到满意,我们可以将模型在我们的测试集上进行测试(图 3)。

y_pred = jnp.array(activation(jnp.dot(X_test, w) + c))
y_pred = jnp.where(y_pred > 0.5, 1, 0) 
print(classification_report(y_test, y_pred))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3: 测试数据分类报告(作者提供的图片)。

结论

如本简要示例所示,JAX 具有非常直观的 API,紧密遵循 Numpy 的约定,同时使得在 CPU/GPU/TPU 上使用相同的代码成为可能。利用这些构建块,可以创建高可定制的深度学习模型,这些模型在设计时已优化以提高性能。

联系方式

如果你想保持更新我的最新文章和项目,请在 Medium 上关注我并订阅我的邮件列表。以下是我的一些联系方式:

参考文献

[1] “移动价格分类”(ABHISHEK SHARMA)。访问地址:thecleverprogrammer.com/2021/03/05/mobile-price-classification-with-machine-learning/(MIT 许可证: github.com/alifrmf/Mobile-Price-Prediction-Classification-Analysis/tree/main

开始使用 LangChain:构建 LLM 驱动应用程序的初学者指南

原文:towardsdatascience.com/getting-started-with-langchain-a-beginners-guide-to-building-llm-powered-applications-95fc8898732c

使用大型语言模型在 Python 中构建任何东西的 LangChain 教程

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Leonie Monigatti

·发表于Towards Data Science ·11 分钟阅读·2023 年 4 月 25 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

“随机的鹦鹉对其他的说了什么?”(作者绘制的图像)

自 ChatGPT 发布以来,大型语言模型(LLMs)已经获得了极大的关注。尽管你可能没有足够的资金和计算资源在地下室从头训练一个 LLM,但你仍然可以使用预训练的 LLM 来构建一些很酷的东西,比如:

LLM 正在改变我们构建 AI 驱动产品的方式

通过其奇特的 API 和提示工程,LLM 正在改变我们构建 AI 驱动产品的方式。这就是为什么新的开发者工具在“LLMOps”的名义下不断涌现的原因。

这些新工具之一是LangChain

[## GitHub - hwchase17/langchain: ⚡ 通过组合性构建 LLM 应用 ⚡

⚡ 通过组合性构建 LLM 应用 ⚡ 生产支持:当你将 LangChains 迁移到…

github.com](https://github.com/hwchase17/langchain?source=post_page-----95fc8898732c--------------------------------)

LangChain 是什么?

LangChain 是一个框架,旨在通过提供以下内容来帮助你更轻松地构建 LLM 驱动的应用程序:

  • 一种通用接口,用于各种不同的基础模型(见 Models),

  • 一个帮助你管理提示的框架(见 Prompts),以及

  • 一个中央接口,用于长期记忆(见 Memory)、外部数据(见 Indexes)、其他 LLMs(见 Chains)以及其他 LLM 无法处理的任务(例如计算或搜索)(见 Agents)。

这是一个开源项目(GitHub 仓库),由 哈里森·查斯 创建。

由于 LangChain 具有许多不同的功能,因此一开始可能很难理解它的作用。这就是为什么我们将在本文中介绍(目前的)六个关键模块,以便让你更好地理解其功能。

先决条件

要跟随本教程,你需要安装 langchain Python 包,并准备好所有相关的 API 密钥。

安装 LangChain

在安装 langchain 包之前,确保你有 Python 版本 ≥ 3.8.1 且 <4.0。

要安装 langchain Python 包,你可以使用 pip 进行安装。

pip install langchain

在本教程中,我们使用的是版本 0.0.147。由于 GitHub 仓库 非常活跃,请确保你使用的是最新版本。

一旦你完成所有设置,导入 langchain Python 包。

import langchain

API 密钥

使用 LLM 构建应用程序需要一些服务的 API 密钥,并且一些 API 可能会产生费用。

LLM 提供者(必需) — 你首先需要一个用于所需 LLM 提供者的 API 密钥。我们目前正经历“AI 的 Linux 时刻”,在这一时刻,开发者必须在性能和成本之间权衡,选择专有或开源基础模型

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

LLM 提供者:专有和开源基础模型(图像由作者提供,灵感来源于 Fiddler.ai,首次发布在 W&B 的博客

专有模型 是由拥有大型专家团队和大额 AI 预算的公司拥有的封闭源基础模型。它们通常比开源模型大,因此性能更好,但它们的 API 也很昂贵。专有模型提供商的例子包括 OpenAIco:hereAI21 LabsAnthropic

大多数可用的 LangChain 教程使用 OpenAI,但请注意 OpenAI API(虽然实验使用不贵,但)并非免费。要获取 OpenAI API 密钥,你需要一个 OpenAI 账户,然后在 API 密钥 下“创建新秘密密钥”。

import os
os.environ["OPENAI_API_KEY"] = ... # insert your API_TOKEN here

开源模型 通常是比专有模型小的模型,能力较低,但它们比专有模型更具成本效益。开源模型的例子包括:

许多开源模型被组织和托管在 Hugging Face 作为一个社区中心。要获取 Hugging Face API 密钥,你需要一个 Hugging Face 账户,并在 访问令牌 下创建一个“新令牌”。

import os

os.environ["HUGGINGFACEHUB_API_TOKEN"] = ... # insert your API_TOKEN here

你可以免费使用 Hugging Face 来访问开源 LLM,但你将被限制使用性能较低的小型 LLM。

个人备注—— 我们诚实地说一句:当然,你可以在这里尝试开源基础模型。我试图只使用在 Hugging Face 上托管的开源模型(google/flan-t5-xl 和 sentence-transformers/all-MiniLM-L6-v2)来制作这个教程,并使用普通账户进行操作。大多数示例都能正常工作,但也有一些示例很难让它们正常运行。最后,我决定购买一个 OpenAI 的付费账户,因为 LangChain 的大多数示例似乎都为 OpenAI 的 API 进行了优化。总的来说,制作这个教程的几个实验花费了我大约 1 美元。

向量数据库(可选) —— 如果你想使用特定的向量数据库,如 PineconeWeaviateMilvus,你需要注册并获取一个 API 密钥,并查看它们的定价。在这个教程中,我们使用的是 Faiss,它不需要注册。

工具(可选) — 根据你希望 LLM 与之交互的工具,如 OpenWeatherMap 或 SerpAPI,你可能需要注册以获得 API 密钥,并查看它们的定价。在本教程中,我们仅使用不需要 API 密钥的工具。

你可以用 LangChain 做什么?

该包提供了与许多基础模型的通用接口,支持提示管理,并作为其他组件的中央接口,如提示模板、其他 LLM、外部数据以及通过代理访问的其他工具。

在撰写本文时,LangChain(版本 0.0.147)涵盖了六个模块:

  • 模型:从不同的 LLM 和嵌入模型中选择

  • 提示:管理 LLM 输入

  • 链:将 LLM 与其他组件结合

  • 索引:访问外部数据

  • 记忆:记住先前的对话

  • 代理:访问其他工具

以下部分中的代码示例是从LangChain 文档中复制和修改的。

模型:从不同的 LLM 和嵌入模型中选择

目前,许多不同的 LLM 正在出现。LangChain 提供了与各种模型的集成,并为所有模型提供了简化的接口。

LangChain 区分三种类型的模型,它们在输入和输出上有所不同:

  • LLMs 将一个字符串作为输入(提示),并输出一个字符串(完成)。
# Proprietary LLM from e.g. OpenAI
# pip install openai
from langchain.llms import OpenAI
llm = OpenAI(model_name="text-davinci-003")

# Alternatively, open-source LLM hosted on Hugging Face
# pip install huggingface_hub
from langchain import HuggingFaceHub
llm = HuggingFaceHub(repo_id = "google/flan-t5-xl")

# The LLM takes a prompt as an input and outputs a completion
prompt = "Alice has a parrot. What animal is Alice's pet?"
completion = llm(prompt)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

LLM 模型(图片由作者提供)

  • 聊天模型类似于 LLM。它们将聊天消息列表作为输入,并返回一条聊天消息。

  • 文本嵌入模型将文本输入并返回一个浮点数列表(嵌入),这些嵌入是输入文本的数值表示。嵌入帮助从文本中提取信息。这些信息可以在后续使用,例如,计算文本之间的相似性(例如电影摘要)。

# Proprietary text embedding model from e.g. OpenAI
# pip install tiktoken
from langchain.embeddings import OpenAIEmbeddings
embeddings = OpenAIEmbeddings()

# Alternatively, open-source text embedding model hosted on Hugging Face
# pip install sentence_transformers
from langchain.embeddings import HuggingFaceEmbeddings
embeddings = HuggingFaceEmbeddings(model_name = "sentence-transformers/all-MiniLM-L6-v2")

# The embeddings model takes a text as an input and outputs a list of floats
text = "Alice has a parrot. What animal is Alice's pet?"
text_embedding = embeddings.embed_query(text)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

文本嵌入模型(图片由作者提供)

提示:管理 LLM 输入

LLM 的 API 很奇怪。虽然用自然语言输入提示应该是直观的,但需要对提示进行相当多的调整,才能从 LLM 中获得期望的输出。这个过程被称为提示工程

一旦你拥有了一个好的提示,你可能希望将其用作其他用途的模板。因此,LangChain 为你提供了所谓的PromptTemplates,这些模板帮助你从多个组件构建提示。

from langchain import PromptTemplate

template = "What is a good name for a company that makes {product}?"

prompt = PromptTemplate(
    input_variables=["product"],
    template=template,
)

prompt.format(product="colorful socks")

上述提示可以视为零-shot 问题设置,你希望 LLM 在足够相关的数据上进行训练,从而提供令人满意的响应。

提高 LLM 输出的另一个技巧是添加几个示例到提示中,将其设为少量示例问题设置

from langchain import PromptTemplate, FewShotPromptTemplate

examples = [
    {"word": "happy", "antonym": "sad"},
    {"word": "tall", "antonym": "short"},
]

example_template = """
Word: {word}
Antonym: {antonym}\n
"""

example_prompt = PromptTemplate(
    input_variables=["word", "antonym"],
    template=example_template,
)

few_shot_prompt = FewShotPromptTemplate(
    examples=examples,
    example_prompt=example_prompt,
    prefix="Give the antonym of every input",
    suffix="Word: {input}\nAntonym:",
    input_variables=["input"],
    example_separator="\n",
)

few_shot_prompt.format(input="big")

上述代码将生成一个提示模板,并根据提供的示例和输入组成以下提示:

Give the antonym of every input

Word: happy
Antonym: sad

Word: tall
Antonym: short

Word: big
Antonym:

链:将 LLM 与其他组件结合

在 LangChain 中,链式操作简单地描述了将 LLM 与其他组件结合以创建应用程序的过程。一些示例包括:

  • 将 LLM 与提示模板结合(参见本节)

  • 通过将第一个 LLM 的输出作为第二个 LLM 的输入来依次结合多个 LLM(参见本节)

  • 将 LLM 与外部数据结合,例如,用于回答问题(参见 索引)

  • 将 LLM 与长期记忆结合,例如,用于聊天记录(参见 记忆)

在上一节中,我们创建了一个提示模板。当我们想将其与 LLM 一起使用时,可以按如下方式使用 LLMChain

from langchain.chains import LLMChain

chain = LLMChain(llm = llm, 
                  prompt = prompt)

# Run the chain only specifying the input variable.
chain.run("colorful socks")

如果我们想将第一个 LLM 的输出作为第二个 LLM 的输入,可以使用 SimpleSequentialChain

from langchain.chains import LLMChain, SimpleSequentialChain

# Define the first chain as in the previous code example
# ...

# Create a second chain with a prompt template and an LLM
second_prompt = PromptTemplate(
    input_variables=["company_name"],
    template="Write a catchphrase for the following company: {company_name}",
)

chain_two = LLMChain(llm=llm, prompt=second_prompt)

# Combine the first and the second chain 
overall_chain = SimpleSequentialChain(chains=[chain, chain_two], verbose=True)

# Run the chain specifying only the input variable for the first chain.
catchphrase = overall_chain.run("colorful socks")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 PromptTemplates 和 LLMs 在 LangChain 中的 SimpleSequentialChain 的输出(作者截图)

索引:访问外部数据

LLM 的一个限制是缺乏上下文信息(例如,访问某些特定文档或电子邮件)。你可以通过让 LLM 访问特定的外部数据来解决这个问题。

为此,你首先需要用文档加载器加载外部数据。LangChain 提供了各种加载器,用于不同类型的文档,从 PDFs 和电子邮件到网站和 YouTube 视频。

让我们从 YouTube 视频中加载一些外部数据。如果你想 加载一个大型文本文档并使用 文本分割器 将其拆分,可以参考官方文档。

# pip install youtube-transcript-api
# pip install pytube

from langchain.document_loaders import YoutubeLoader

loader = YoutubeLoader.from_youtube_url("https://www.youtube.com/watch?v=dQw4w9WgXcQ")

documents = loader.load()

现在你已经准备好将外部数据作为 documents,你可以使用 文本嵌入模型(参见 模型)在向量数据库中进行索引——一个 VectorStore。流行的向量数据库包括 PineconeWeaviateMilvus。在本文中,我们使用 Faiss,因为它不需要 API 密钥。

# pip install faiss-cpu
from langchain.vectorstores import FAISS

# create the vectorestore to use as the index
db = FAISS.from_documents(documents, embeddings)

你的文档(在这种情况下是视频)现在作为嵌入存储在向量存储中。

现在,你可以使用这些外部数据做各种事情。让我们用它来进行一个信息检索器的问答任务:

from langchain.chains import RetrievalQA

retriever = db.as_retriever()

qa = RetrievalQA.from_chain_type(
    llm=llm, 
    chain_type="stuff", 
    retriever=retriever, 
    return_source_documents=True)

query = "What am I never going to do?"
result = qa({"query": query})

print(result['result'])

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

检索问答的输出(作者截图)

等一下——你刚刚被恶搞了?是的,你确实被恶搞了。

记忆:记住先前的对话

对于聊天机器人等应用程序来说,能够记住先前的对话至关重要。但默认情况下,LLM 不具有任何长期记忆,除非你输入聊天记录。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

带有和不带有对话记忆的聊天(图片由 ifaketextmessage.com 制作,灵感来自 Pinecone

LangChain 通过提供几种处理聊天记录的不同选项来解决这个问题:

  • 保留所有对话,

  • 保留最近的 k 个对话,

  • 总结对话。

在这个示例中,我们将使用ConversationChain来为这个应用程序提供对话记忆。

from langchain import ConversationChain

conversation = ConversationChain(llm=llm, verbose=True)

conversation.predict(input="Alice has a parrot.")

conversation.predict(input="Bob has two cats.")

conversation.predict(input="How many pets do Alice and Bob have?")

这将导致上图中右侧的对话。如果没有ConversationChain来保持对话记忆,对话将会像上图中左侧的那样。

代理:访问其他工具

尽管 LLM 相当强大,但它们有一些局限性:缺乏上下文信息(例如,无法访问训练数据中未包含的特定知识),可能会很快过时(例如,GPT-4 是在 2021 年 9 月之前的数据上训练的),并且在数学方面表现不佳。

LLM 在数学方面表现不好

因为 LLM 在无法自行完成任务时可能会产生幻觉,我们需要提供额外的工具,如搜索(例如,Google 搜索)、计算器(例如,Python REPLWolfram Alpha),以及查找(例如,维基百科)。

此外,我们需要代理程序来根据 LLM 的输出决定使用哪些工具来完成任务。

请注意,一些 LLM 例如 [*google/flan-t5-xl*](https://github.com/hwchase17/langchain/issues/1358) 可能不适用于以下示例,因为它们不符合 [*conversational-react-description*](https://github.com/hwchase17/langchain/issues/1358) 模板。 对我来说,这是我在 OpenAI 上设置付费账户并切换到 OpenAI API 的时刻。

以下是一个示例,其中代理首先用维基百科查找巴拉克·奥巴马的出生日期,然后用计算器计算他在 2022 年的年龄。

# pip install wikipedia
from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType

tools = load_tools(["wikipedia", "llm-math"], llm=llm)
agent = initialize_agent(tools, 
                         llm, 
                         agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, 
                         verbose=True)

agent.run("When was Barack Obama born? How old was he in 2022?")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

LLM 代理的输出(作者截图)

总结

就在几个月前,我们所有人(或者至少大多数人)都对 ChatGPT 的能力印象深刻。现在,像 LangChain 这样的新开发工具使我们能够在几小时内在笔记本电脑上构建同样令人印象深刻的原型——这些确实是令人兴奋的时代!

LangChain 是一个开源的 Python 库,使任何能够编写代码的人都可以构建 LLM 驱动的应用程序。该包提供了对许多基础模型的通用接口,支持提示管理,并作为其他组件(如提示模板、其他 LLM、外部数据和通过代理的其他工具)的中央接口——在撰写时。

图书馆提供的功能远超本文提到的。随着发展速度的加快,本文在一个月内也可能会过时。

在撰写本文时,我注意到图书馆和文档集中在 OpenAI 的 API 上。虽然许多示例使用的是开源基础模型[google/flan-t5-xl](https://github.com/hwchase17/langchain/issues/1358),但我中途切换到了 OpenAI API。尽管不是免费的,但在本文中使用 OpenAI API 的实验仅花费了大约$1。

享受这个故事了吗?

免费订阅 以便在我发布新故事时获得通知。

[## 每当 Leonie Monigatti 发布新内容时,你将收到一封电子邮件。

每当 Leonie Monigatti 发布新内容时,你会收到一封电子邮件。通过注册,你将创建一个 Medium 账户,如果你还没有的话……

medium.com](https://medium.com/@iamleonie/subscribe?source=post_page-----95fc8898732c--------------------------------)

LinkedInTwitter,以及 Kaggle上找到我!

参考资料

[1] Harrison Chase (2023). LangChain 文档(访问日期:2023 年 4 月 23 日)

多模态入门

原文:towardsdatascience.com/getting-started-with-multimodality-eab5f6453080

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Microsoft Designer 创建

理解大型多模态模型的视觉能力

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Valentina Alto

·发表于Towards Data Science ·阅读时间 9 分钟·2023 年 12 月 27 日

生成 AI 的最新进展使得大型多模态模型(LMMs)的发展成为可能,这些模型能够处理和生成不同类型的数据,例如文本、图像、音频和视频。

LMMs 与“标准”大型语言模型(LLMs)共享一般化和适应能力,这些能力是大型基础模型所特有的。然而,LMMs 能够处理超越文本的数据,包括图像、音频和视频。

大型多模态模型的一个最突出的例子是 GPT4V(ision),它是生成预训练变换器(GPT)系列的最新迭代。GPT-4 可以执行各种需要自然语言理解和计算机视觉的任务,例如图像字幕生成、视觉问答、文本到图像合成以及图像到文本翻译。

GPT4V(以及其更新版本 GPT-4-turbo vision)展现了非凡的能力,包括:

  • 数值问题的数学推理:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供

  • 从草图生成代码:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供

  • OCR:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供

  • 艺术遗产的描述:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供

以及许多其他功能。

在这篇文章中,我们将重点关注 LMMs 的视觉能力,以及它们如何与标准计算机视觉算法不同。

什么是计算机视觉

计算机视觉(CV)是人工智能(AI)领域的一部分,它使计算机和系统能够从数字图像、视频和其他视觉输入中获取有意义的信息。它使用机器学习和神经网络来教会计算机看、观察和理解。其目标是模仿人类视觉系统,自动化人类视觉系统能够完成的任务。例如,计算机视觉可以用于识别图像中的物体、检测事件、估计 3D 姿势和修复图像。

由于计算机视觉依赖于神经网络,这些网络不过是数学模型,我们需要将图像转换为数值输入,以便它们可以被我们的模型处理。

图像是像素的多维数组。对于灰度图像,这是一个 2D 数组,每个像素对应于不同的灰色阴影。对于彩色图像,它是一个 3D 数组(高度、宽度和颜色通道),每个颜色通道(红色、绿色、蓝色 — RGD)都有一个单独的 2D 像素强度数组。

每个像素强度是一个数值。最常见的情况是这个值范围从 0(黑色)到 255(白色)。这些像素的组合构成了我们视觉上感知到的图像。

以下插图展示了一个 RGD 图像的例子(注意:像素值仅作为示例,并不代表真实值)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供

现在的问题是如何预处理这些多维数组,使得计算机视觉模型能够理解它们并尽可能保留信息。

在多模态模型出现之前,计算机视觉通常依赖于为特定任务设计和训练的专用模型,如目标检测、人脸识别、场景分割和光学字符识别。在这个领域中,卷积神经网络是最受欢迎的模型之一。

卷积神经网络

卷积神经网络不过是展示了至少一层数学操作卷积的神经网络。

卷积是两个矩阵之间的逐元素乘法(分别代表一个专门用于检测特定特征的滤波器和处理图像的同样大小的区域),并对输出结果进行最终的求和。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供

让我们将以下插图作为一个例子。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由作者提供

在图中,我检查了一个简单的任务:我们有一个由四个字母组成的字母表——A、B、C 和 D——并且我们的算法被要求识别输入字母(在我们的例子中是‘C’)。输入图像通过一个专门的滤波器(例如,用于角点检测)进行处理,然后降维、展平,并通过全连接层处理。

视觉转换器

Vision Transformer(原始论文这里)作为 CNN 的第一个替代方案被提出,它与 LLM 共享核心架构(编码器/解码器)。

与传统的转换器一样,在这种情况下核心机制也是注意力(原始论文这里),它允许模型在进行预测时选择性地关注输入序列的不同部分。这个概念通过教模型关注输入数据的某些部分并忽略其他部分,从而更好地解决当前任务。

变革性的注意力机制在转换器中的一个方面是,它摆脱了递归(可以在这里了解更多关于递归神经网络(RNN)的内容)和卷积,这些都是以前模型广泛依赖的。转换器是第一个完全依赖注意力来计算输入和输出表示的模型,而不使用序列对齐的 RNN 或卷积。这使得转换器能够捕捉句子中单词之间更广泛的关系,并学习输入的更微妙的表示。

在视觉转换器中,图像的处理方式与 CNN 不同。实际上,一张图像被划分为所谓的补丁,通常为 16x16 像素大小。然后,每个补丁被展平为 1D 向量并进行标记,就像我们在标准转换器(如 GPT-3.5)中处理文本数据一样。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图像

现在,这些经过标记的补丁将被输入到视觉转换器模型中,并通过线性投影层进一步转换为低维向量,这样我们可以在保留信息的同时减少内存和计算能力的需求。此外,与标准转换器一样,每个标记都通过位置嵌入层与其在图像整体上下文中的位置指示器相关联。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图像

最终,位置嵌入的标记被传递到模型的主要块,即转换器编码器。下面你可以看到一个视觉转换器的插图(在这个案例中,场景是分类任务):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源: arxiv.org/pdf/2010.11929v2.pdf

如你所见,转换器编码器展示了上述注意力机制

总结

其思想是将图像的嵌入投影到与语言相同的潜在空间中,这样,当给定由图像和文本组成的人类输入时,模型能够从覆盖图像和文本的嵌入空间中获取相关的上下文。

OpenAI 引入的第一个图像和文本模型是 CLIP(对比语言-图像预训练)。

CLIP

CLIP是 OpenAI 开发的一个模型,旨在同时理解图像和文本。它就像是连接图像世界和文字世界的桥梁。

想象一下你有一堆图像和句子,你想将每张图像与最能描述它的句子匹配。这就是 CLIP 的核心功能。它被训练以理解哪些图像和句子彼此相似。

CLIP 的酷炫之处在于它不需要专门针对某个任务进行训练就能表现良好。例如,如果你有一组 CLIP 从未见过的新图像和句子(即所谓的零样本方法),它仍然可以很好地将它们匹配起来。这是因为 CLIP 从大量数据中学习了对图像和文本的普遍理解。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:CLIP: 连接文本和图像 (openai.com)

尽管 CLIP 仍然是一个预测模型,但最先进的 LMMs 旨在作为 AI 助手与人类互动。换句话说,它们是指令模型。

LLaVA

一个很好的助手 LMM 的例子是开源模型LLaVA (Large Language and Vision Assistant),它结合了前面提到的 CLIP 用于图像编码和基础 LMM Vicuna,用于指令理解。

LLaVA 的思想是拥有一个线性层,将 CLIP 生成的图像特征连接到语言模型 Vicuna 的词嵌入空间中。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:2304.08485.pdf (arxiv.org)

为此,研究人员引入了一个可训练的投影矩阵 W,它将图像特征转换为与语言模型处理的词嵌入具有相同维度的嵌入向量。

Kosmos-1

另一个例子是 Kosmos-1,由微软研究院在这篇论文中介绍。该模型的理念是使用一个变压器解码器以统一的方式感知通用模态:输入被展平为 1D 令牌向量,并用特殊的开始和结束序列标记(文本如*text,图像如image*)标记。一旦标记化,输入通过嵌入模块(特定于数据格式)进行编码,然后输入解码器。

在他们的论文中,作者描述了模型的训练过程,其中包括以下数据语料库:

  • 单模态文本语料库 → 用于表示学习(即,产生有意义的语言表示,保持其潜在语义结构)和一般语言任务,例如遵循指令、上下文学习等。

  • 图像-文本对 → 作为模型将图像与其描述关联的桥梁

  • 交错的图像-文本数据 → 需要进一步将一般模态的感知与语言模型对齐,并提高模型的少样本能力。

下面的图片展示了一些 Kosmos-1 的能力示例:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源: 2302.14045.pdf (arxiv.org)

总体而言,创建一个图像和词汇的共同嵌入空间的趋势,使模型能够“感知”这两种数据格式——文本和图像——正在为强大的大型多模态模型铺平道路。此外,像 CLIP 这样的预训练模型被广泛用于生成图像表示,然后可以进一步转换为词嵌入空间。

超越视觉

一般来说,多模态模型的主要思想是创建不同模态中给定概念的一致表示。在前一部分中,我们看到如何使用视觉变换器将图像嵌入到潜在空间中的低维向量中。同样,我们可以为每种模态创建编码器,并使用目标函数来鼓励模型为相似的数据对生成相似的嵌入。

比如,我们可以考虑模型 MACAW-LLM,这是一个多模态语言模型,能够处理图像、视频、音频和文本数据,基于 CLIP(图像和视频)、Whisper(音频)和LLaMA(文本)的基础构建。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源: lyuchenyang/Macaw-LLM: Macaw-LLM: 多模态语言建模,集成图像、视频、音频和文本 (github.com)

如你所见,不同的嵌入模块被用来生成“共享”的嵌入空间,该空间与 LLM 使用的词嵌入空间(在本例中为 Meta AI 的 LLaMA)对齐。

结论

多模态正在为新一波应用和用例铺平道路。这也是实现人工通用智能(AGI)概念的进一步里程碑,因为它使 AI 系统越来越容易像人类一样“感知”。

不用说,大型多模态模型在伦理考量方面带来了更大的责任:偏见、歧视、隐私侵犯以及许多其他风险都是 LMM 研究的核心,现在比以往任何时候都更加需要关注人类对齐

参考文献

开始使用 NumPy 和 OpenCV 进行计算机视觉 (CV-01)

原文:towardsdatascience.com/getting-started-with-numpy-and-opencv-for-computer-vision-555f88536f68

开始使用 Python 进行计算机视觉编程

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Md. Zubair

·发表于 Towards Data Science ·8 分钟阅读·2023 年 3 月 15 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Dan Smedley 通过 Unsplash 提供的照片

动机

我们人类通过视觉系统感知环境和周围事物。人眼、大脑和四肢协同工作以感知环境并做出相应的动作。一个智能系统能够执行那些如果由人类完成则需要某种程度智力的任务。因此,为了执行智能任务,人工视觉系统是计算机的重要组成部分。通常,使用相机和图像来收集完成工作的所需信息。计算机视觉和图像处理技术帮助我们完成类似人类的任务,如图像识别、对象跟踪等。

在计算机视觉中,相机像人眼一样捕捉图像,处理器像大脑一样处理捕捉到的图像并生成重要结果。但人类和计算机之间有一个基本的区别。人脑自动工作,智力是与生俱来的。而计算机没有智力,除非有人的指令(程序)。计算机视觉就是提供适当的指令,使计算机能够与人类视觉系统兼容。然而,其能力是有限的。

*在接下来的部分中,我们将讨论图像如何形成及如何使用 Python 进行操作的基本概念。*

目录

*点击目录直接跳转到相应章节*

  1. **图像如何形成和显示**

  2. **计算机如何在内存中存储图像?**

  3. **灰度图像和彩色图像**

  4. **NumPy 基础以处理图像**

  5. **OpenCV 基础**

  6. **玩转 NumPy**

图像的形成与显示

图像只不过是具有不同颜色强度的像素组合。‘像素’和‘颜色强度’这两个术语可能对你来说是陌生的。不要担心。阅读完文章后,一切都会变得清晰明了。

像素是数字图像的最小单位/元素。详细信息见下图。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者提供的图像

显示屏由像素构成。在上图中,有 25 列和 25 行。每个小方块被视为一个像素。这个设置可以容纳 625 个像素。它表示一个具有 625 个像素的显示屏。如果我们用不同的颜色强度(亮度)来照亮这些像素,它将形成一个数字图像。

计算机如何将图像存储在内存中?

如果我们仔细观察图像,可以将其与 2D 矩阵进行比较。矩阵有行和列,其元素可以通过索引访问。矩阵结构类似于数组。计算机将图像存储在计算机内存的数组中。

每个数组元素保存强度值。通常,强度值范围从**0 到 255**。为了演示目的,我提供了图像的数组表示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

灰度图像的示例数组表示(作者提供的图像)

灰度图像与彩色图像

灰度图像是一种黑白图像。它由一种颜色形成。接近 0 的像素值代表黑暗,强度值越高,图像就越亮。最高值是 255,代表白色。一个 2D 数组足以存储灰度图像,正如最后的图示所示。

彩色图像不能仅由一种颜色形成;可能有成千上万种颜色组合。主要有三种基本颜色通道**红色 (R)、绿色 (G) 和蓝色 (B)**。每个颜色通道存储在一个2D 数组中,并保存其强度值,最终图像是这三个颜色通道的组合。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

RGB 颜色通道(作者提供的图像)

这种颜色模型具有 (256 x 256 x 256) = 16,777,216 种可能的颜色组合。 [***你可以在这里可视化这些组合。***](https://csunplugged.jp/csfg/data/interactives/rgb-mixer/index.html)

但在计算机内存中,图像的存储方式有所不同。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

存储在计算机内存中的图像(作者提供的图像)

计算机不知道 RGB 通道。它知道的是强度值。红色通道以高强度存储,绿色和蓝色通道分别以中等和低强度值存储。

NumPy 基础知识以便与 Python 一起使用

NumPy 是一个用于科学计算的基础 Python 包。它主要作为数组对象工作,但它的操作不限于数组。然而,该库可以处理各种数字和逻辑操作[1]。你可以在[***这里***](https://numpy.org/doc/stable/user/absolute_beginners.html)找到 NumPy 的官方文档。

让我们开始我们的旅程。首先是第一步。

  • 导入 NumPy 库。

现在是使用 NumPy 的时候了。正如我们所知,NumPy 与数组一起工作。所以,让我们尝试创建第一个全零的 2D 数组。

  • 创建 NumPy 数组

就这么简单。我们也可以创建一个全为 1 的 NumPy 数组,方法如下。

有趣的是,NumPy 还提供了一种方法来用任意值填充数组。简单的语法array.fill(value)可以完成这项工作。

数组‘b’中所有的元素现在都被填充为3

  • 随机数生成中的种子功能

只需看看以下的代码示例。

在第一个代码单元格中,我们使用了**np.random.seed(seed_value)**,但其他两个代码单元格中没有使用任何种子。在有种子和无种子的随机数生成之间有一个主要区别。在随机种子的情况下,生成的随机数对于特定的种子值保持不变。另一方面,没有种子值的情况下,每次执行时随机数都会变化。

  • 使用 NumPy 的基本操作(最大值、最小值、均值、重塑等)

NumPy 通过提供大量函数来执行数学运算,使我们的生活更轻松。array_name.min(), array_name.max(), array_name.mean()语法帮助我们找到数组的最小值、最大值和均值。编码示例 —

最小值和最大值的索引可以通过语法array_name.argmax(), array_name.argmin()提取。示例 —

数组重塑是NumPy.array_name.reshape(row_no, column_no)的一个重要操作,用于重塑数组。在重塑数组时,我们必须注意重塑前后数组元素的数量。在两种情况下,总元素数必须相同。

  • 数组索引和切片

每个数组元素可以通过其列和行编号进行访问。我们来生成另一个具有 10 行和列的数组。

假设我们想找出数组的第一个值。可以通过传递行和列索引(0 , 0)来提取。

可以使用语法array_name[row_no,:], array_name[:,column_no]来切片特定的行和列值。

让我们尝试切片数组的中心元素。

OpenCV 基础

OpenCV是由英特尔开发的开源 Python 计算机视觉库[2]。我将讨论 OpenCV 的一些用法,尽管它的范围很广。你可以在[**这里**](https://docs.opencv.org/4.x/d6/d00/tutorial_py_root.html)找到官方文档。

我使用了以下图像进行演示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图像由jackouille21提供,来源于Pixabay

  • 导入 OpenCV 和 Matplotlib 库

Matplotlib 是一个可视化库。它有助于可视化图像。

  • 使用 OpenCV 加载图像并用 matplotlib 可视化

我们已经用OpenCV读取了图像,并用matplotlib库对其进行了可视化。颜色发生了变化,因为OpenCVBGR格式读取图像,而matplotlib期望图像为RGB格式。因此,我们需要将图像从BGR 转换为 RGB

  • 将图像从 BGR 格式转换为 RGB 格式

现在,图像看起来还不错。

  • 将图像转换为灰度

我们可以轻松地使用cv2.COLOR_BGR2GRAY将图像从 BGR 转换为灰度图像,操作如下。

尽管图像已经转换为灰度图像,但上述图像并不完全灰色。它已通过 matplotlib 进行了可视化。默认情况下,matplotlib 使用的是不同于灰度的颜色映射。为了正确可视化它,我们需要在 matplotlib 中指定灰度颜色映射。让我们来做一下。

  • 旋转图像

旋转也是一个简单的任务,使用OpenCVcv2.rotate()函数可以帮助我们完成这项工作。顺时针和逆时针 90 度以及 180 度旋转如下所示。

  • 调整图像大小

我们可以通过将宽度和高度的像素值传递给cv2.resize()函数来调整图像大小。

  • 在图像上绘制

有时我们需要在现有图像上绘制。例如,我们需要在图像对象上绘制一个边界框以进行识别。让我们在花朵上绘制一个矩形。cv2.rectangle()函数帮助我们在其上绘制。它需要一些参数,比如我们绘制矩形的图像、左上角坐标点 *(pt1)* 和右下角坐标点 *(pt2)*,以及边界线的厚度。下面是一个编码示例。

还有其他绘图函数[***cv.line()***](https://docs.opencv.org/4.x/d6/d6e/group__imgproc__draw.html#ga7078a9fae8c7e7d13d24dac2520ae4a2)*,* [***cv.circle()***](https://docs.opencv.org/4.x/d6/d6e/group__imgproc__draw.html#gaf10604b069374903dbd0f0488cb43670) *,* [***cv.ellipse()***](https://docs.opencv.org/4.x/d6/d6e/group__imgproc__draw.html#ga28b2267d35786f5f890ca167236cbc69)*,* [***cv.putText()***](https://docs.opencv.org/4.x/d6/d6e/group__imgproc__draw.html#ga5126f47f883d730f633d74f07456c576)*,* 等。完整的官方文档可以在这里`**[3]**中找到。

玩转 NumPy

我们将改变图像的强度值。我会尽量保持简单。因此,考虑之前显示的灰度图像。找出图像的形状。

它显示这是一个2D 数组,大小为**1200 x 1920**。在基本的 NumPy 操作中,我们学习了如何切片数组。

使用该概念,我们提取了灰度图像数组片段**[400:800, 750:1350]**并将强度值替换为**255**。最后,我们对其进行可视化,得到了上述图像。

结论

计算机视觉是现代计算机科学技术中一个有前途的领域。我总是强调任何领域的基础知识。我仅讨论了计算机视觉的基本知识,并展示了一些实践编码。这些概念非常简单,但对于计算机视觉的初学者可能起到重要作用。

***完整*** [***代码***](https://github.com/Zubair063/ML_articles/blob/main/Getting%20Started%20with%20NumPy%20and%20OpenCV/Numpy_OpenCV.ipynb) ***可在此处*** [***获取***](https://github.com/Zubair063/ML_articles/tree/main/Getting%20Started%20with%20NumPy%20and%20OpenCV) ***。***

这是计算机视觉系列的第一篇文章。请保持关注,以阅读即将发布的文章。

[注:讲师 Jose Portilla 的课程帮助我获取知识。]

参考文献

  1. NumPy 文档 — NumPy v1.25.dev0 手册

  2. OpenCV — 维基百科

  3. OpenCV:OpenCV 中的绘图函数

您可以阅读下面提供的其他系列文章。

## 数据科学的终极统计指南

数据科学概述:标准指南

[towardsdatascience.com [## 数据科学的终极数据可视化指南

数据科学概述:标准指南

medium.datadriveninvestor.com

开始使用 Weaviate:初学者的向量数据库搜索指南

原文:towardsdatascience.com/getting-started-with-weaviate-a-beginners-guide-to-search-with-vector-databases-14bbb9285839?source=collection_archive---------1-----------------------#2023-07-18

如何在 Python 中使用 OpenAI 和 Weaviate 进行语义搜索、问答和生成搜索

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Leonie Monigatti

·

关注 发表在Towards Data Science ·12 分钟阅读·2023 年 7 月 18 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果你看到这篇文章,我假设你已经开始尝试构建使用大语言模型(LLM)的应用,并遇到了“向量数据库”这一术语。

伴随着构建 LLM 应用的工具快速增长,诸如LangChainLlamaIndex等工具正变得越来越受欢迎。

在最近的一篇文章中,我描述了如何开始使用 LangChain,在这篇文章中,我想通过玩弄Weaviate来继续探索 LLM 工具的景观。

什么是 Weaviate?

Weaviate 是一个开源向量数据库。它使你能够存储数据对象和向量嵌入,并根据相似性度量查询它们。

## GitHub - weaviate/weaviate: Weaviate 是一个开源向量数据库,既存储对象也存储向量…

Weaviate 是一个开源向量数据库,存储对象和向量,允许进行向量搜索的结合…

github.com

向量数据库自从 LLM 媒体关注度上升以来,受到了大量关注。可能最流行的向量数据库在 LLM 上下文中的应用是“为 LLM 提供长期记忆”。

如果你需要重新了解向量数据库的概念,你可能想查看我之前的文章:

## 解释向量数据库的三种难度级别

从新手到专家:解密不同背景下的向量数据库

towardsdatascience.com

在本教程中,我们将演示如何用数据集的嵌入填充 Weaviate 向量数据库。然后,我们将介绍三种从中检索信息的方法:

  • 向量搜索

  • 问答系统

  • 生成搜索

前提条件

要跟随本教程,你需要具备以下条件:

  • Python 3 环境

  • OpenAI API 密钥(或选择 Hugging Face、Cohere 或 PaLM 的 API 密钥)

关于 API 密钥的说明: 在本教程中,我们将通过一个推理服务(在这种情况下是OpenAI)从文本中生成嵌入。根据你使用的推理服务,请确保检查提供商的定价页面以避免意外费用。例如,使用的阿达模型(版本 2)在撰写时的费用为每 1,000 个令牌 $0.0001,在本教程中推理费用不到 1 美分。

设置

你可以在自己的实例上运行 Weaviate(使用 Docker、Kubernetes 或嵌入式 Weaviate),也可以通过 Weaviate Cloud Services (WCS) 作为托管服务运行。对于本教程,我们将使用 WCS 运行 Weaviate 实例,因为这是推荐的最简单的方法。

如何使用 Weaviate Cloud Services (WCS) 创建集群

要能够使用该服务,你首先需要 注册 WCS

注册后,你可以通过点击“创建集群”按钮来创建一个新的 Weaviate 集群。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Weaviate Cloud Services 的截图

对于本教程,我们将使用免费的试用计划,该计划为你提供 14 天的沙盒。(你无需添加任何支付信息。相反,沙盒将在试用期结束后过期。但你可以随时创建一个新的免费试用沙盒。)

在“免费沙盒”标签下,进行以下设置:

  1. 输入集群名称

  2. 启用身份验证(设置为“是”)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Weaviate Cloud Services 计划的截图

最后,点击“创建”以创建你的沙盒实例。

如何在 Python 中安装 Weaviate

最后,但同样重要的是,使用 pipweaviate-client 添加到你的 Python 环境中

$ pip install weaviate-client

并导入库:

import weaviate

如何通过客户端访问 Weaviate 集群

对于下一步,你将需要以下两项信息来访问你的集群:

  • 集群 URL

  • Weaviate API 密钥(在“启用 — 身份验证”下)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Weaviate Cloud Services 沙盒的截图

现在,你可以实例化一个 Weaviate 客户端以访问你的 Weaviate 集群,如下所示。

auth_config = weaviate.AuthApiKey(api_key="YOUR-WEAVIATE-API-KEY")  # Replace w/ your Weaviate instance API key

# Instantiate the client
client = weaviate.Client(
    url="https://<your-sandbox-name>.weaviate.network", # Replace w/ your Weaviate cluster URL
    auth_client_secret=auth_config,
    additional_headers={
        "X-OpenAI-Api-Key": "YOUR-OPENAI-API-KEY", # Replace with your OpenAI key
        }
)

如你所见,我们使用additional_headers下的 OpenAI API 密钥来访问嵌入模型。如果你使用的是不同于 OpenAI 的提供者,请将密钥参数更改为以下之一:X-Cohere-Api-KeyX-HuggingFace-Api-KeyX-Palm-Api-Key

要检查是否一切设置正确,请运行:

client.is_ready()

如果返回True,你已为下一步做好准备。

如何创建和填充 Weaviate 向量数据库

现在,我们准备在 Weaviate 中创建一个向量数据库并用一些数据填充它。

对于本教程,我们将使用 Kaggle 上的 200,000+ Jeopardy 问题 数据集的前 100 行 [1]。

import pandas as pd

df = pd.read_csv("your_file_path.csv", nrows = 100)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Kaggle 上的 200,000+ Jeopardy 问题 数据集的前几行 [1]。

关于令牌数量和相关成本的说明:在以下示例中,我们将为前 100 行嵌入“category”、“question”和“answer”列。根据与 *tiktoken* 库的计算,这将产生大约 3,000 个令牌用于嵌入,这 大约会导致 OpenAI 的 Ada 模型(版本 2)在 2023 年 7 月的推理成本为 $0.0003

第一步:创建模式

首先,我们需要定义底层数据结构和一些配置:

  • class:这个向量空间中的对象集合将被称为什么?

  • properties:对象的属性,包括属性名称和数据类型。在 Pandas Dataframe 类比中,这些就是 DataFrame 中的列。

  • vectorizer:生成嵌入的模型。对于文本对象,通常你会选择一个[text2vec](https://weaviate.io/developers/weaviate/modules/retriever-vectorizer-modules)模块(text2vec-coheretext2vec-huggingfacetext2vec-openaitext2vec-palm),具体选择取决于你使用的提供商。

  • moduleConfig:在这里,你可以定义所用模块的详细信息。例如,向量化器是一个模块,你可以定义使用哪个模型和版本。

class_obj = {
    # Class definition
    "class": "JeopardyQuestion",

    # Property definitions
    "properties": [
        {
            "name": "category",
            "dataType": ["text"],
        },
        {
            "name": "question",
            "dataType": ["text"],
        },
        {
            "name": "answer",
            "dataType": ["text"],
        },
    ],

    # Specify a vectorizer
    "vectorizer": "text2vec-openai",

    # Module settings
    "moduleConfig": {
        "text2vec-openai": {
            "vectorizeClassName": False,
            "model": "ada",
            "modelVersion": "002",
            "type": "text"
        },
    },
}

在上述模式中,你可以看到我们将创建一个名为"JeopardyQuestion"的类,具有三个文本属性"category""question""answer"。我们使用的向量化器是 OpenAI 的 Ada 模型(版本 2)。所有属性都将被向量化,但类名("vectorizeClassName" : False)不会。如果你有不希望嵌入的属性,可以指定这一点(见文档)。

一旦定义了模式,你可以使用create_class()方法创建类。

client.schema.create_class(class_obj)

要检查类是否已成功创建,你可以如下查看其模式:

client.schema.get("JeopardyQuestion")

创建的模式如下所示:

{
  "class": "JeopardyQuestion",
  "invertedIndexConfig": {
    "bm25": {
      "b": 0.75,
      "k1": 1.2
    },
    "cleanupIntervalSeconds": 60,
    "stopwords": {
      "additions": null,
      "preset": "en",
      "removals": null
    }
  },
  "moduleConfig": {
    "text2vec-openai": {
      "model": "ada",
      "modelVersion": "002",
      "type": "text",
      "vectorizeClassName": false
    }
  },
  "properties": [
    {
      "dataType": [
        "text"
      ],
      "indexFilterable": true,
      "indexSearchable": true,
      "moduleConfig": {
        "text2vec-openai": {
          "skip": false,
          "vectorizePropertyName": false
        }
      },
      "name": "category",
      "tokenization": "word"
    },
    {
      "dataType": [
        "text"
      ],
      "indexFilterable": true,
      "indexSearchable": true,
      "moduleConfig": {
        "text2vec-openai": {
          "skip": false,
          "vectorizePropertyName": false
        }
      },
      "name": "question",
      "tokenization": "word"
    },
    {
      "dataType": [
        "text"
      ],
      "indexFilterable": true,
      "indexSearchable": true,
      "moduleConfig": {
        "text2vec-openai": {
          "skip": false,
          "vectorizePropertyName": false
        }
      },
      "name": "answer",
      "tokenization": "word"
    }
  ],
  "replicationConfig": {
    "factor": 1
  },
  "shardingConfig": {
    "virtualPerPhysical": 128,
    "desiredCount": 1,
    "actualCount": 1,
    "desiredVirtualCount": 128,
    "actualVirtualCount": 128,
    "key": "_id",
    "strategy": "hash",
    "function": "murmur3"
  },
  "vectorIndexConfig": {
    "skip": false,
    "cleanupIntervalSeconds": 300,
    "maxConnections": 64,
    "efConstruction": 128,
    "ef": -1,
    "dynamicEfMin": 100,
    "dynamicEfMax": 500,
    "dynamicEfFactor": 8,
    "vectorCacheMaxObjects": 1000000000000,
    "flatSearchCutoff": 40000,
    "distance": "cosine",
    "pq": {
      "enabled": false,
      "bitCompression": false,
      "segments": 0,
      "centroids": 256,
      "encoder": {
        "type": "kmeans",
        "distribution": "log-normal"
      }
    }
  },
  "vectorIndexType": "hnsw",
  "vectorizer": "text2vec-openai"
}

步骤 2:将数据导入 Weaviate

在此阶段,向量数据库已有模式但仍为空。因此,让我们用数据集填充它。这一过程也称为“upserting”。

我们将以每批 200 条的方式进行数据的 upsert。如果你注意到了,你会知道这里不需要这样做,因为我们只有 100 行数据。但一旦你准备好进行更大规模的数据 upsert,你会希望以批量方式进行。这就是为什么我在这里留下批处理代码:

from weaviate.util import generate_uuid5

with client.batch(
    batch_size=200,  # Specify batch size
    num_workers=2,   # Parallelize the process
) as batch:
    for _, row in df.iterrows():
        question_object = {
            "category": row.category,
            "question": row.question,
            "answer": row.answer,
        }
        batch.add_data_object(
            question_object,
            class_name="JeopardyQuestion",
            uuid=generate_uuid5(question_object)
        )

尽管 Weaviate 会自动生成一个通用唯一标识符(uuid),我们将通过question_objectgenerate_uuid5()函数手动生成uuid,以避免导入重复的项目。

进行完整性检查时,你可以使用以下代码片段查看导入对象的数量:

client.query.aggregate("JeopardyQuestion").with_meta_count().do()
{'data': {'Aggregate': {'JeopardyQuestion': [{'meta': {'count': 100}}]}}}

如何查询 Weaviate 向量数据库

你最常做的操作是检索对象。要检索对象,你可以使用get()函数查询 Weaviate 向量数据库:

client.query.get(
    <Class>,
    [<properties>]
).<arguments>.do()
  • Class:指定要检索的对象类的名称。这里是"JeopardyQuestion"

  • properties:指定要检索的对象属性。这里包括"category""question""answer"中的一个或多个。

  • arguments:指定检索对象的搜索标准,例如限制条件或聚合。在以下示例中,我们将介绍一些这些标准。

让我们用get()函数从JeopardyQuestion类中检索一些条目,以查看它们的样子。在 Pandas 的类比中,你可以将以下内容视为df.head(2)。由于get()函数的响应是 JSON 格式的,我们将导入相关库以以视觉上吸引人的格式显示结果。

import json

res = client.query.get("JeopardyQuestion", 
                      ["question", "answer", "category"])
                  .with_additional(["id", "vector"])
                  .with_limit(2)
                  .do()

print(json.dumps(res, indent=4))
{
    "data": {
        "Get": {
            "JeopardyQuestion": [
                {
                    "_additional": {
                        "id": "064fee53-f8fd-4513-9294-432170cc9f77",
                        "vector": [ -0.02465364, ...] # Vector is trunkated for better readability 
                    },
                    "answer": "(Lou) Gehrig",
                    "category": "ESPN's TOP 10 ALL-TIME ATHLETES",
                    "question": "No. 10: FB/LB for Columbia U. in the 1920s; MVP for the Yankees in '27 & '36; \"Gibraltar in Cleats\""
                },
                {
                    "_additional": {
                        "id": "1041117a-34af-40a4-ad05-3dae840ad6b9",
                        "vector": [ -0.031970825, ...] # Vector is trunkated for better readability
                    },
                    "answer": "Jim Thorpe",
                    "category": "ESPN's TOP 10 ALL-TIME ATHLETES",
                    "question": "No. 2: 1912 Olympian; football star at Carlisle Indian School; 6 MLB seasons with the Reds, Giants & Braves"
                },
            ]
        }
    }
}

在上述代码片段中,你可以看到我们从"JeopardyQuestion"类中检索对象。我们指定了检索属性"category""question""answer"

我们指定了两个额外的arguments:首先,我们使用.with_additional()参数指定检索关于对象 ID 和向量嵌入的额外信息。然后,使用.with_limit(2)参数,我们指定只检索两个对象。这种限制很重要,你将在后续示例中再次看到。这是因为从矢量数据库中检索对象不会返回完全匹配的结果,而是基于相似性返回对象,这需要通过阈值来限制。

矢量搜索

现在,我们准备进行一些矢量搜索!从矢量数据库中检索信息的酷炫之处在于,你可以例如要求它检索与"concepts"相关的 Jeopardy 问题。

为此,我们可以使用.with_near_text()参数,并传入我们感兴趣的"concepts",如下所示:

res = client.query.get(
    "JeopardyQuestion",
    ["question", "answer", "category"])\
    .with_near_text({"concepts": "animals"})\
    .with_limit(2)\
    .do()

指定的vectorizer将输入文本("animals”)转换为向量嵌入,并检索两个最接近的结果:

{
    "data": {
        "Get": {
            "JeopardyQuestion": [
                {
                    "answer": "an octopus",
                    "category": "SEE & SAY",
                    "question": "Say the name of <a href=\"http://www.j-archive.com/media/2010-07-06_DJ_26.jpg\" target=\"_blank\">this</a> type of mollusk you see"
                },
                {
                    "answer": "the ant",
                    "category": "3-LETTER WORDS",
                    "question": "In the title of an Aesop fable, this insect shared billing with a grasshopper"
                }
            ]
        }
    }
}

你可以看到这有多酷:我们看到矢量搜索返回了两个问题,其答案都是动物,但来自两个完全不同的类别。使用传统的关键词搜索,你必须首先定义一个动物列表,然后检索所有包含其中一个定义动物的问题。

问答功能

问答是将 LLMs 与矢量数据库结合使用时最受欢迎的示例之一。

要启用问答功能,你需要在模块配置中指定一个矢量化器(你应该已经有了)和一个问答模块,如下例所示:

# Module settings
    "moduleConfig": {
        "text2vec-openai": {
          ...
        },
        "qna-openai": {
          "model": "text-davinci-002"
        }
    },

对于问答功能,你需要添加with_ask()参数,并且检索_additional属性。

ask = {
  "question": "Which animal was mentioned in the title of the Aesop fable?",
  "properties": ["answer"]
}

res = (
  client.query
  .get("JeopardyQuestion", [
      "question",
      "_additional {answer {hasAnswer property result} }"
  ])
  .with_ask(ask)
  .with_limit(1)
  .do()
)

上述代码会查找所有可能包含问题"Which animal was mentioned in the title of the Aesop fable?"答案的提问,并返回答案"The ant"

{
    "JeopardyQuestion": [
        {
            "_additional": {
                "answer": {
                    "hasAnswer": true,
                    "property": "",
                    "result": " The ant"
                }
            },
            "question": "In the title of an Aesop fable, this insect shared billing with a grasshopper"
        }
    ]
}

生成搜索

通过结合 LLMs,你还可以在返回搜索结果之前转换数据。这一概念称为生成搜索。

要启用生成搜索,你需要在模块配置中指定一个生成模块,如下例所示:

# Module settings
    "moduleConfig": {
        "text2vec-openai": {
          ...
        },
        "generative-openai": {
          "model": "gpt-3.5-turbo"
        }
    },

对于生成搜索,你只需在之前的矢量搜索代码中添加with_generate()参数,如下所示:

res = client.query.get(
    "JeopardyQuestion", 
    ["question", "answer"])\
  .with_near_text({"concepts": ["animals"]})\
  .with_limit(1)\
  .with_generate(single_prompt= "Generate a question to which the answer is {answer}")\
  .do()

上述代码做了以下操作:

  1. 搜索最接近"animals"概念的问题

  2. 返回问题 "说出你看到的这种软体动物的名字",答案是 "章鱼"

  3. 为提示 "生成一个答案是章鱼的问题" 生成一个完成的结果:

{
    "generate": {
        "error": null,
        "singleResult": "What sea creature has eight arms and is known for its intelligence and camouflage abilities?"
    }
}

摘要

LLM 领域的流行不仅带来了许多有趣的新开发者工具,如 LangChain 或 LLaMaIndex,还展示了如何利用现有工具(如向量数据库)来增强 LLM 驱动的应用程序的潜力。

在这篇文章中,我们开始尝试使用 Weaviate,不仅利用向量数据库进行向量搜索,还结合 LLM 进行问答和生成搜索。

如果你对更深入的教程感兴趣,我推荐查看这门全面的四部分课程,内容涉及向量数据库和 Weaviate:

[## 1. 从零到 MVP | Weaviate — 向量数据库

课程概述

weaviate.io](https://weaviate.io/developers/academy/zero_to_mvp?source=post_page-----14bbb9285839--------------------------------)

免责声明:撰写本文时,我是 Weaviate 的开发者倡导者。

喜欢这个故事吗?

免费订阅 以在我发布新故事时收到通知。

[## 每当 Leonie Monigatti 发布时获取电子邮件通知。

每当 Leonie Monigatti 发布时获取电子邮件通知。通过注册,如果你还没有 Medium 账户,将创建一个…

medium.com](https://medium.com/@iamleonie/subscribe?source=post_page-----14bbb9285839--------------------------------)

LinkedInTwitter Kaggle 上找到我!

参考资料

数据集

[1] Ulrik Thyge Pedersen (2023). 200,000+ Jeopardy 问题 在 Kaggle 数据集中。

许可证: 4.0 国际版(CC BY 4.0)

图片参考

如果没有另行说明,所有图片均由作者创作。

网络与文献

[2] Weaviate (2023). Weaviate 文档(访问日期:2023 年 7 月 14 日)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值