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

原文:TowardsDataScience

协议:CC BY-NC-SA 4.0

优秀工程师、差劲工程师和恶劣工程师——数据领导者的轶事

原文:towardsdatascience.com/good-engineers-bad-engineers-and-evil-engineers-an-anecdote-for-data-leaders-6cceb82c8c3e?source=collection_archive---------4-----------------------#2023-11-29

我区分优秀工程师、差劲工程师和恶劣工程师的黄金框架,适用于所有领域,包括数据领域

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

·

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

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

图片由作者提供(使用 Canva 的 Magic Media 应用生成)

工程就是利用科学原理设计或建造某物——《剑桥词典》。

我们都喜欢优秀的工程师,他们建造了出色的桥梁、道路、火箭、应用程序和数据结构,让我们的生活更加便捷和愉快。

按照相同的逻辑,差劲的工程师不会使生活变得更好。如果我们雇用他们,他们将设计和构建某些东西,但会消耗更多的时间、金钱和精力。

但你是否知道,在优秀和差劲之外,还有恶劣的工程师,他们的思维方式不是构建,而是不构建

作为一名工程师,同时也是曾经担任产品负责人/项目经理的人员,我的经历告诉我关于优秀、差劲和恶劣工程师的一些事情。我喜欢优秀的工程师,对差劲的工程师有同情心,而对恶劣的工程师感到厌恶。

在本文结束时,我将告诉你从根本上看,这些工程师类型之间的区别。但首先,让故事从一个更具趣味性的角度讲述。

对优秀、差劲和恶劣工程师的一些普遍观察

回顾你自己的经历和对工程世界的了解,你认为优秀、差劲和恶劣的工程师有哪些共同的行为?

以下是我的观察:

优秀的工程师:

  • 他们能识别问题

  • 他们以可持续的方法解决问题

  • 他们还解决与已识别根本原因相关的其他问题

差劲的工程师:

  • 他们能识别问题

  • 他们解决短期问题

  • 他们通过解决原始问题创造更多的问题

恶劣的工程师:

  • 他们假装看不到问题

查看一个具体的例子

让我通过描述数据工程世界中的一个具体例子来更容易地想象这三种工程师角色。

以一个数据工程师为例,他构建了一个管道,将一组原始数据表从事务数据仓库复制到云中的容器中。按照勋章架构,数据经过青铜层、银层和金层,他们首先清理数据并将其倒入指定数据湖仓中的一组青铜层表中。接下来,他们在银层中对表进行规范化,并建立它们之间的关系。最后,他们将多个表连接在一个视图中,并创建新特征以表示业务指标,以供 Tableau 仪表板使用。

在仪表板测试过程中,发现某些记录中的某一列存在缺失值。业务用户担心看到该列中超过 50%的记录缺失数据,但他们也承认数据在源头可能不完整。现在,工程师需要调查和解决问题。

优秀的工程师将

  • 首先,他们非常清楚该列如何从青铜层转变为金层和银层。换句话说,他们会知道缺失数据列的确切数据血统。

  • 在金层中识别一个缺失数据的样本记录,但该列在源数据中有数据。如果他们在整个数据集中无法识别任何记录,他们就会宣布数据本身不完整。

  • 如果发现一个有效的记录中存在缺失数据,他们将再次对该样本记录应用转换逻辑,看看为什么该列数据未能传递过来。这里会有 2 种场景:

  • 场景 1:采样记录包含一些意外的特征,使得它们的列值被排除在金标准层之外。简而言之,这是一个设计问题。在这种情况下,好的工程师会与产品负责人讨论这些意外特征,并确定处理方案。要么他们决定可以安全地忽略这一人群,因为具有这些特征的数据与业务目标无关;要么他们会为这些数据制定自定义转换逻辑,以将数据引入。

  • 场景 2:在他们的手动转换中,列值出现了,这意味着他们对初始数据来源的理解是错误的。简而言之,这是一个执行问题。好的工程师会回去检查数据管道在做什么,或者数据来源实际是什么。然后他们重复其余步骤。

一个坏工程师会:

  • 对数据来源有一个较差的理解。

  • 在金标准层中识别一个缺失数据的样本记录,但在源头对该列有数据。如果他们无法识别任何记录,他们宣布数据本身不完整。

  • 如果发现一个有效的记录中存在缺失数据,尝试对这个缺失数据的记录应用手动逻辑转换,看看为什么该列数据未能传递过来。

  • 得出错误的结论,为什么列值没有传递过来,主要是因为他们对数据来源和整体数据管道的理解是错误的。

  • 如果他们的观察结果使他们得出上面所述的场景 1 的结论(设计问题),他们将通知团队这是一个数据质量问题,然后打住。他们假设设计是完美的,没有什么需要改进的地方。

  • 一个更具伦理但也更灾难性的工程师会尝试为受影响的记录制定自定义处理方案(即修改设计),然而,由于他们对数据来源的理解一开始就不正确,他们会造成更大的混乱。

  • 如果他们的观察结果使他们得出场景 2 的结论(执行问题),他们将回去研究实施的数据管道与设计的数据管道之间的差距,并可能在下一次找到正确的解决方案。

一个邪恶的工程师会怎么做?

  • 他们可能知道也可能不知道正确的数据来源,这无关紧要。

  • 他们宣布,因为该列的数据在源头就不完整(根据业务告诉他们的情况),所以数据在仪表板中会缺失。

  • 然后他们假设数据管道没有问题,因为数据本身就是不完整的。

  • 他们就此打住,回家去了。

好的、坏的和邪恶的工程师之间的根本区别

希望我上面的例子为你提供了三个类型工程师的更清晰的描绘。然而,例子只能在你掌握了好、坏和邪恶工程师之间的基本差异后才会对你长期有帮助。为了系统地区分这三者,找出他们的基本特征至关重要:

这是我的看法:

  • 一个好的工程师具备三种品质:卓越的知识对真相的承诺对结果的承诺

  • 一个坏工程师缺乏卓越的知识对结果的承诺。然而,他们确实对真相有中等程度的承诺。

  • 一个邪恶的工程师对真相的承诺几乎为零。结果对他们来说并不重要。他们关心其他方面(也许是结果的外观),或者他们根本不在乎任何事情。邪恶的工程师很少具备卓越的知识,但如果他们具备,那也无关紧要,因为他们既不关心真相,也不关心结果。

你们中的一些人可能会发现这里的坏工程师和邪恶工程师之间没有明确的区别。通常,邪恶往往会造成伤害——因此你会期望邪恶的工程师引入恶意代码或掩盖他们过去的错误。我同意这一点。然而,我想在这里强调的是我如何区分坏和邪恶:

工程师不一定需要采取恶意行动就能变得邪恶,一旦工程师开始忽视眼前的真相(即假装看不到问题),他们就进入了邪恶的领域。

他们忽视的事实越多,他们就会变得越邪恶。

如何识别好、坏和邪恶的工程师?

所以下次当你遇到一个工程师时,寻找这三种品质的指标。如果你只是发现了一些资历、认证或几十年的经验——这些只是卓越知识的指标,那么你还不能太确定。

承诺是一种主动的心态。寻找对真相或结果的承诺的指标需要仔细调查历史行为模式、持续分析一个人的思维过程,以及观察他们对挑战的反应。

忽视对承诺或真相的指标的寻找就是忽视你自己的成功,让它由所谓的‘知识渊博’的工程师决定。

最终,这与你对自己招聘/合作决策的责任有关。如果你不想浪费你的钱,开始识别好、坏和邪恶的工程师吧。


你好,如果你在阅读这些内容,那么你很可能关心数据。你认为可以从数据中提取宝贵的价值,并且你渴望找到最佳的策略、实施实践和工具,以从你所在组织(或你自己)的数据资产中提取尽可能多的价值。

如果这是真的,那请查看我的每周通讯——数据与超越快报。每期将为你带来来自数据社区的深刻内容,这些内容经过精心挑选和总结,为你提供关于真正有效的数据领袖的使命、愿景、策略和工具箱的新鲜、条理清晰和实用的视角。

告别 os.path:15 个 Pathlib 技巧迅速掌握 Python 文件系统

原文:towardsdatascience.com/goodbye-os-path-15-pathlib-tricks-to-quickly-master-the-file-system-in-python-881213ca7c21

不再有os.path带来的头疼和难以阅读的代码

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

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

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

机器人伙伴。 — 来自 Midjourney

Pathlib 可能是我最喜欢的库(显然在 Sklearn 之后)。考虑到有超过 13 万个库,这已经很说明问题了。Pathlib 帮助我将像这样的代码从 os.path 转换过来:

import os

dir_path = "/home/user/documents"

# Find all text files inside a directory
files = [os.path.join(dir_path, f) for f in os.listdir(dir_path) \
        if os.path.isfile(os.path.join(dir_path, f)) and f.endswith(".txt")]

转换为如下内容:

from pathlib import Path

# Find all text files inside a directory
files = list(dir_path.glob("*.txt"))

Pathlib 于 Python 3.4 中推出,作为替代 os.path 的噩梦。它还标志着 Python 语言的一个重要里程碑:他们终于将每一件事都变成了对象(即使是 nothing)。

os.path 的最大缺陷是将系统路径视为字符串,这导致了难以阅读、混乱的代码和陡峭的学习曲线。

通过将路径表示为完全成熟的 对象,Pathlib 解决了所有这些问题,并为路径处理带来了优雅、一致性和一丝清新。

这篇我一直拖延的文章将概述一些 pathlib 的最佳函数/特性和技巧,以执行那些在 os.path 中会是极其糟糕的任务。

学习这些 Pathlib 的功能将使你作为数据专业人士处理路径和文件变得更容易,特别是在需要处理成千上万的图像、CSV 文件或音频文件的数据处理工作流中。

让我们开始吧!

路径操作

1. 创建路径

pathlib的几乎所有功能都可以通过其 Path 类访问,你可以用它来创建文件和目录的路径。

有几种方法可以使用 Path 创建路径。首先,有像 cwdhome 这样的类方法,用于当前工作目录和用户主目录:

from pathlib import Path

Path.cwd()
PosixPath('/home/bexgboost/articles/2023/4_april/1_pathlib')
Path.home()
PosixPath('/home/bexgboost')

你也可以从字符串路径创建路径:

p = Path("documents")

p
PosixPath('documents')

使用正斜杠操作符在 Pathlib 中连接路径是轻而易举的:

data_dir = Path(".") / "data"
csv_file = data_dir / "file.csv"

print(data_dir)
print(csv_file)
data
data/file.csv

请不要让任何人看到你在使用 os.path.join

要检查路径是否存在,你可以使用布尔函数 exists

data_dir.exists()
True
csv_file.exists()
True

有时,整个 Path 对象可能不可见,你需要检查它是目录还是文件。因此,你可以使用is_diris_file函数来判断:

data_dir.is_dir()
True
csv_file.is_file()
True

你处理的大多数路径相对于当前目录。但有时你需要提供文件或目录的确切位置,以便从任何 Python 脚本中访问它。这时你使用absolute路径:

csv_file.absolute()
PosixPath('/home/bexgboost/articles/2023/4_april/1_pathlib/data/file.csv')

最后,如果你不幸要处理仍然需要字符串路径的库,你可以调用 str(path)

str(Path.home())
'/home/bexgboost'

数据栈中的大多数库很早就支持了 Path 对象,包括 sklearnpandasmatplotlibseaborn 等。

2. 路径属性

Path 对象有许多有用的属性。让我们看看一些使用指向图像文件的路径对象的示例。

image_file = Path("images/midjourney.png").absolute()

image_file
PosixPath('/home/bexgboost/articles/2023/4_april/1_pathlib/images/midjourney.png')

parent 开始。它返回一个路径对象,该对象在当前工作目录上一级。

image_file.parent
PosixPath('/home/bexgboost/articles/2023/4_april/1_pathlib/images')

有时,你可能只想要文件的 name 而不是整个路径。这里有一个属性可以做到这一点:

image_file.name
'midjourney.png'

只返回带有扩展名的文件名。

还有 stem 用于没有后缀的文件名:

image_file.stem
'midjourney'

或带有点的 suffix 本身作为文件扩展名:

image_file.suffix
'.png'

如果你想将路径划分为其组件,你可以使用 parts 代替 str.split('/')

image_file.parts
('/',
 'home',
 'bexgboost',
 'articles',
 '2023',
 '4_april',
 '1_pathlib',
 'images',
 'midjourney.png')

如果你想要那些组件本身成为 Path 对象,你可以使用 parents 属性,它创建一个生成器:

for i in image_file.parents:
    print(i)
/home/bexgboost/articles/2023/4_april/1_pathlib/images
/home/bexgboost/articles/2023/4_april/1_pathlib
/home/bexgboost/articles/2023/4_april
/home/bexgboost/articles/2023
/home/bexgboost/articles
/home/bexgboost
/home
/

处理文件

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

分类文件。— Midjourney

要创建文件并向其中写入内容,你不再需要使用 open 函数。只需创建一个 Path 对象,然后 write_textwrite_bytes 即可:

markdown = data_dir / "file.md"

# Create (override) and write text
markdown.write_text("# This is a test markdown")

或者,如果你已经有一个文件,你可以 read_textread_bytes

markdown.read_text()
'# This is a test markdown'
len(image_file.read_bytes())
1962148

但请注意,write_textwrite_bytes会覆盖文件中现有的内容。

# Write new text to existing file
markdown.write_text("## This is a new line")
# The file is overridden
markdown.read_text()
'## This is a new line'

要向现有文件添加新信息,你应该使用 Path 对象的 open 方法,模式为 a(附加):

# Append text
with markdown.open(mode="a") as file:
    file.write("\n### This is the second line")

markdown.read_text()
'## This is a new line\n### This is the second line'

重命名文件也很常见。rename 方法接受重命名文件的目标路径。

要在当前目录中创建目标路径,即重命名文件,你可以在现有路径上使用 with_stem,它替换原始文件的 stem

renamed_md = markdown.with_stem("new_markdown")

markdown.rename(renamed_md)
PosixPath('data/new_markdown.md')

上述,file.md 被转为 new_markdown.md

通过 stat().st_size 查看文件大小:

# Display file size
renamed_md.stat().st_size
49 # in bytes

或文件上次修改的时间,这是几秒钟前的事:

from datetime import datetime

modified_timestamp = renamed_md.stat().st_mtime

datetime.fromtimestamp(modified_timestamp)
datetime.datetime(2023, 4, 3, 13, 32, 45, 542693)

st_mtime 返回一个时间戳,这是自 1970 年 1 月 1 日以来的秒数。为了使其可读,你可以使用 datetimefromtimestamp 函数。

要删除不需要的文件,你可以 unlink 它们:

renamed_md.unlink(missing_ok=True)

missing_ok 设置为 True,如果文件不存在不会引发任何警报。

处理目录

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

办公室中的文件夹。— Midjourney

在 Pathlib 中处理目录有几个很棒的技巧。首先,让我们看看如何递归创建目录。

new_dir = (
    Path.cwd()
    / "new_dir"
    / "child_dir"
    / "grandchild_dir"
)

new_dir.exists()
False

new_dir还不存在,所以让我们创建它及其所有子目录:

new_dir.mkdir(parents=True, exist_ok=True)

默认情况下,mkdir只会创建给定路径的最后一个子目录。如果中间的父目录不存在,你必须将parents设置为True

要删除空目录,你可以使用rmdir。如果给定的路径对象是嵌套的,则只会删除最后一个子目录:

# Removes the last child directory
new_dir.rmdir()

要列出目录的内容,就像终端中的ls一样,你可以使用iterdir。结果将是一个生成器对象,一次产生一个路径对象的目录内容:

for p in Path.home().iterdir():
    print(p)
/home/bexgboost/.python_history
/home/bexgboost/word_counter.py
/home/bexgboost/.azure
/home/bexgboost/.npm
/home/bexgboost/.nv
/home/bexgboost/.julia
...

要捕捉所有具有特定扩展名或名称模式的文件,你可以使用带有正则表达式的glob函数。

例如,下面我们将使用glob("*.txt")在我的主目录中找到所有文本文件:

home = Path.home()
text_files = list(home.glob("*.txt"))

len(text_files)
3 # Only three

要递归搜索文本文件,即包括所有子目录内的文件,你可以使用递归 globrglob

all_text_files = [p for p in home.rglob("*.txt")]

len(all_text_files)
5116 # Now much more

了解正则表达式 这里

你也可以使用rglob('*')递归列出目录内容。这就像iterdir()的超级增强版。

其中一个用例是统计目录中出现的文件格式数量。

为此,我们从collections中导入Counter类,并在home的文章文件夹中提供所有文件后缀:

from collections import Counter

file_counts = Counter(
    path.suffix for path in (home / "articles").rglob("*")
)

file_counts
Counter({'.py': 12,
         '': 1293,
         '.md': 1,
         '.txt': 7,
         '.ipynb': 222,
         '.png': 90,
         '.mp4': 39})

操作系统差异

对不起,但我们必须讨论这个噩梦般的问题。

到目前为止,我们一直在处理PosixPath对象,它们是 UNIX-like 系统的默认对象:

type(Path.home())
pathlib.PosixPath

如果你在 Windows 上,你会得到一个WindowsPath对象:

from pathlib import WindowsPath

# User raw strings that start with r to write windows paths
path = WindowsPath(r"C:\users")
path
NotImplementedError: cannot instantiate 'WindowsPath' on your system

实例化另一个系统的路径会引发类似上述的错误。

但如果你被迫处理来自其他系统的路径,比如同事们用 Windows 写的代码呢?

作为解决方案,pathlib提供了像PureWindowsPathPurePosixPath这样的纯路径对象:

from pathlib import PurePosixPath, PureWindowsPath

path = PureWindowsPath(r"C:\users")
path
PureWindowsPath('C:/users')

这些是原始路径对象。你可以访问一些路径方法和属性,但本质上,路径对象仍然是一个字符串:

path / "bexgboost"
PureWindowsPath('C:/users/bexgboost')
path.parent
PureWindowsPath('C:/')
path.stem
'users'
path.rename(r"C:\losers") # Unsupported
AttributeError: 'PureWindowsPath' object has no attribute 'rename'

结论

如果你注意到,我在文章标题中撒了谎。实际上新技巧和函数的数量是大约 30 个,而不是 15 个。

我不想吓到你。

但我希望我已经足够说服你放弃os.path,开始使用pathlib来进行更简单和更可读的路径操作。

锻造一个新的路径,如果你愿意 😃

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

Path. — Midjourney

如果你喜欢这篇文章,并且,老实说,其怪异的写作风格,考虑通过注册成为 Medium 会员来支持我。会员费用为每月 4.99 美元,可以无限制访问我所有的故事以及成千上万篇更有经验的作者写的文章。如果你通过 这个链接 注册,我将赚取少量佣金,而不会增加你的额外费用。

[## 通过我的推荐链接加入 Medium — Bex T.

获得对我所有⚡高级⚡内容和 Medium 上所有内容的独家访问权限,没有限制。通过购买我一份支持我的工作…

ibexorigin.medium.com](https://ibexorigin.medium.com/membership?source=post_page-----881213ca7c21--------------------------------)

如何在 Python 中设置 GOOGLE_APPLICATION_CREDENTIALS

原文:towardsdatascience.com/google-application-credentials-python-ace518208a7

配置应用程序默认凭据并修复 oauth2client.client.ApplicationDefaultCredentialsError

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

·发布于 Towards Data Science ·阅读时间 3 分钟·2023 年 1 月 19 日

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

照片由 Daniel K Cheung 提供,来源于 Unsplash

欢迎来到我们的教程,了解如何为 Google Cloud 和 Python 配置应用程序默认凭据。在本文中,我们将介绍如何在 Python 中正确设置 GOOGLE_APPLICATION_CREDENTIALS

为了能够以编程方式与 Google Cloud Platform 服务(如 Google BigQuery)进行交互,首先需要正确认证应用程序并授予所有所需权限。这是通过定义应用程序默认凭据来指向包含所需凭据的文件来实现的。

当漏掉此步骤时,常见的错误是:

oauth2client.client.ApplicationDefaultCredentialsError: The Application Default Credentials are not available. They are available if running in Google Compute Engine. Otherwise, the environment variable GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining the credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.

订阅数据管道,这是一个专注于数据工程的新闻通讯

Google Cloud 中的应用程序默认凭据如何工作

应用程序默认凭据 (ADC) 是 Google Cloud 上用于根据应用程序环境推断凭据的策略。这意味着应用程序代码可以在不同的环境中运行,而无需更改代码认证 GCP 服务或应用程序编程接口 (APIs) 的方式。

对于本地开发,通常有两种不同的方法来提供 ADC 凭据:

  • 用户凭据

  • 服务帐户密钥

创建凭据 JSON 文件

为了创建包含所需凭据的 JSON 文件,首先需要确保在主机机器上安装了 [gcloud](https://cloud.google.com/sdk/docs/install) CLI

对于本地开发,您最好使用与您个人 Google Cloud 帐户相关联的用户凭据。为此,您需要运行以下命令,这将会在您的(默认)浏览器中显示一个登录提示:

gcloud auth application-default login

登录到 Google Cloud 后,您的凭据将存储在一个 JSON 文件中,位于以下默认位置:

  • Mac/Linux: $HOME/.config/gcloud/application_default_credentials.json

  • Windows: %APPDATA%\gcloud\application_default_credentials.json

如果您使用的是服务帐户,可以通过访问Google Cloud 上的服务帐户服务生成 JSON 令牌。不过请注意,服务帐户密钥存在安全风险,不推荐使用。更强大且可能更安全的方法包括冒充和 工作负载身份池

设置 GOOGLE_APPLICATION_CREDENTIALS 环境变量

为了提供凭据 JSON 文件的位置,您需要使用 GOOGLE_APPLICATION_CREDENTIALS 环境变量。

因此,在使用 Python 时,您可以使用以下代码片段以编程方式设置环境变量:

import os 

os.environ['GOOGLE_APPLICATION_CREDENTIALS'] ='$HOME/.config/gcloud/application_default_credentials.json'

另外,您还可以创建 google.oath2.service_account.Credentials 的实例,然后在开始与 Google 客户端交互之前将其传递给 Google 客户端。

以下示例演示了如何在 Python 中对 Gmail 客户端进行身份验证:

from google.oauth2 import service_account
from googleapiclient.discovery import build

credentials = service_account.Credentials.from_service_account_file(
  '$HOME/.config/gcloud/application_default_credentials.json'
)

service = build('gmail', 'v1', credentials=credentials)

请注意,上述代码片段假设您的 JSON 凭据文件在创建时存储在默认目录下。如果与默认目录不同,请确保指向正确的目录。

最终想法

总之,本教程介绍了如何为 Google Cloud 和 Python 正确设置应用程序默认凭据 (ADC),以便对应用程序进行身份验证,并授予对 Google Cloud Platform 服务的所有必需权限。

ADC 是 Google Cloud 上的一种策略,用于根据应用程序环境推断凭据,使代码可以在不同的环境中运行而无需更改身份验证过程。

在本教程中,我们还介绍了如何创建所需的 JSON 凭据文件,无论是使用用户凭据还是服务帐户,以及如何设置 GOOGLE_APPLICATION_CREDENTIALS 环境变量以提供文件的位置。

订阅数据管道,这是一个致力于数据工程的新闻通讯

您可能也喜欢的相关文章

Python 中的图示代码

使用 Python 创建云系统架构图

图表作为代码(Python) ## SQL 反模式在 BigQuery 中

在 Google Cloud BigQuery 上运行 SQL 时的最佳实践和需要避免的事项

标准 SQL 与遗留 SQL 在 BigQuery 中的比较 ## 标准 SQL 与遗留 SQL 在 BigQuery 中的比较

在 Google Cloud BigQuery 上理解标准 SQL 和遗留 SQL 的区别

SQL 反模式在 BigQuery 中

Google Cloud 的 Cloud Composer 替代品

原文:towardsdatascience.com/google-cloud-alternatives-to-cloud-composer-972836388a3f

观点

不要用锤子打苍蝇

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

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

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

作者提供的图片,火焰标志设计由 Freepik¹

你知道吗,作为 Google Cloud 的用户,你可以选择许多服务来编排你的作业?对于批处理作业,Cloud Composer 长时间以来一直是自然的选择。然而,这种情况不必持续下去。本文介绍了 Google Cloud 中两个替代 Cloud Composer 的作业编排工具。

本内容的主要主题如下:

Cloud Composer 表现出色的用例

Cloud Composer 的两个替代品

优势与劣势基准

总结

Cloud Composer 表现出色的用例

一个作业编排工具需要满足一些要求才能称之为编排工具。就个人而言,我期望在一个作业编排工具中至少看到 3 点:

  • 首先,一个编排工具必须能够编排任何具有任务间依赖关系的任务组,无论这些任务执行什么工作

  • 其次,一个编排工具必须支持任务间的数据共享

  • 第三,一个编排工具必须允许周期性作业执行和按需作业执行

Cloud Composer 满足上述 3 个标准及更多。它是一个功能强大的全面编排工具,基于 Apache Airflow,支持像回填、补充、任务重跑和 动态任务映射 等良好功能。

权力是危险的。权力吸引最坏的人,腐蚀最优秀的人(爱德华·阿比)

权力是危险的。这一说法对 Cloud Composer 同样适用。我总是建议尝试更简单的解决方案(更多内容在接下来的部分),将 Cloud Composer 保留用于复杂的情况。在我看来,以下是使用 Cloud Composer 完全合理的一些情况:

  1. 你需要运行一个大规模的作业编排系统,涉及数百或数千个作业

  2. 你有任务之间存在复杂和/或动态依赖关系的作业。例如,你的作业的最终结构取决于作业中第一个任务的输出。

  3. 你有具有非平凡触发规则和约束的任务。例如,你希望任务在其任何上游任务失败后立即触发。

Cloud Composer 的两个替代方案

在寻找 Cloud Composer 的作业编排器时,还有更简单的解决方案可以考虑。

替代方案 1:Vertex AI Pipelines

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

Vertex AI Pipeline 中的管道运行示例,图片来源于作者

Vertex AI Pipelines 是基于Kubeflow Pipelines(它基于 Kubernetes)的作业编排器。它是一个无服务器产品,这意味着无需创建虚拟机或集群。尽管该编排器最初用于机器学习(ML)管道,但它足够通用,可以适应任何类型的作业。在我看来,将 Vertex AI Pipelines(更广泛地说,Kubeflow Pipelines)绑定到 ML 上更像是一种陈词滥调,反而影响了该解决方案的受欢迎程度。

替代方案 2:Cloud Workflows (+ Cloud Scheduler)

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

Cloud Workflows 中的工作流运行示例,图片来源于作者

Cloud Workflows 是一种无服务器、轻量级的服务编排器。它有两个主要要求:

  1. 需要编排的任务必须是基于 HTTP 的服务(通常使用Cloud FunctionsCloud Run

  2. 作业的调度外部化到Cloud Scheduler

人们通常会使用它来编排 API 或微服务,从而避免单体架构。

优势与劣势基准

当需要在多个选项中做出选择时,通常将选项根据明确的成功标准进行排名是个好主意。我在这里选择了 4 个标准(0:差 — 2:一般 — 5:好)

  1. 简洁性:团队学习和使用该解决方案的难易程度如何?

  2. 可维护性:在工作流创建后,修改工作流的难易程度如何?

  3. 可扩展性:当工作流数量增加时,解决方案的稳定性如何?

  4. 成本

注意:请注意,标准以及评估是主观的,仅代表我的观点

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

解决方案比较,图片来源于作者

由于其陡峭的学习曲线,Cloud Composer 不是最容易上手的解决方案。尽管如此,Cloud Workflows 本身没有任何处理能力,这也是为什么它总是与其他服务如 Cloud Functions 或 Cloud Runs 一起使用的原因。此外,调度必须由 Cloud Scheduler 处理。

就可维护性和可扩展性而言,Cloud Composer 是佼佼者,因为它具有无限的可扩展性,并且系统非常可观察,所有组件都有详细的日志和指标。在这方面,Cloud Composer 紧随其后的是 Vertex AI Pipelines。

就成本而言,Cloud Composer 是最昂贵的,而 Cloud Workflows 在这三者中无疑是最便宜的解决方案。

总结

根据你对工作流编排的需求,Google Cloud 中可能有比 Cloud Composer 更合适的解决方案。一方面,Cloud Workflows 便宜得多,并且满足了工作流编排器的所有基本要求。另一方面,Vertex AI Pipelines 更加集成到 Kubernetes 中,对于已经对 Kubernetes 有较好了解的团队来说,可能更容易上手。

感谢您的时间,请继续关注更多内容。

[1] www.freepik.com

Google Foobar Challenge: Level 3

原文:towardsdatascience.com/google-foobar-challenge-level-3-f487fa3f204b

探索二进制数字、动态编程和马尔可夫链

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

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

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

图片来源于 Rajeshwar BachuUnsplash

Foobar 挑战是什么? 🧐

Foobar 挑战是由 Google 主办的编码挑战,可以用 Python 或 Java 完成。我用 Python 完成了挑战。这个挑战有自己专属的服务器,使用特定的终端风格命令。问题的难度各异,共分为 5 个级别。每个问题必须在一定时间限制内解决。较高级别的挑战会给予更多时间。

要了解更多关于 Foobar 挑战的信息,我推荐阅读我之前的文章,其中提供了对第 1 级问题的概述和分析。

## Google Foobar Challenge: Level 1

对神秘编码挑战的介绍以及问题的分析

towardsdatascience.com

第 3 级开始变得严肃起来。第 1 级和第 2 级测试了基础知识,大约需要 15 分钟解决。第 3 级测试了问题解决技能,需要几个小时的研究。与之前的级别不同,我没有立即知道如何解决这些问题。我不得不多次阅读问题并在纸上进行测试。此外,我还需要研究和实践一些新的概念。

研究并不意味着仅仅通过 Google 搜索问题名称并查看其他人的解决方案。相反,我尝试重新表述问题或搜索那些看起来特别具体的短语,以找到相关的方程和模型。

起初,我有些犹豫。谷歌会跟踪我的搜索记录吗?他们会认为这是一种作弊吗?然而,随着我在这一关卡的进展,我意识到这些问题很可能是为了迫使你查看外部材料。我非常怀疑谷歌会期望开发者记住马尔可夫链公式。

当你解决这些问题时,我鼓励你研究不熟悉的概念,尤其是当你的解决方案变得冗长和不结构化时。这些问题的设计目的是为了找到优雅的解决方案。如果你想不出一种优雅的解决方法,那说明可能存在某个公式或方法能简化它。记住,编码的一部分是研究最佳的方法。

问题与概念 📚

警告 — 含有剧透 ⛔️

在下面,我将详细讲解这些问题并解释我的思考过程。我也提供了解决方案。不过,我强烈建议你先尝试解决这个问题。挑战中最好的部分就是解决一个难以捉摸的问题所带来的惊喜和满足感。

我曾考虑不发布解决方案,仅仅解释基础概念。然而,编码的一部分是学习如何排查故障和定位代码失败的地方。因此,我决定发布解决方案,以便当你卡住时,可以准确看到你的逻辑在哪里偏离了正确的路径。

第 3 关:问题 1

在第 3 关的所有问题中,这对我来说是最困难的。我在纸上做了很多示例。处理一个 309 位长的数字的要求似乎暗示着尝试用二进制数来解决这个问题。

问题的目标是用最少的操作达到一个弹珠。最有效的操作是将弹珠对半分,因为这样n会呈指数级衰减。

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

图片来自作者。

不过,完美的指数衰减仅在n是 2 的幂时有效。如果不是,n最终将减少到一个奇数,并且不能被除以 2。在这种情况下,是加 1 还是减 1 更好?最佳的操作是使数字可以被最多次地除以 2 的那个选项。幸运的是,二进制形式提供了这些信息。一个二进制数中的尾随零的数量就是一个数字可以被 2 除以多少次。

例如,考虑n = 15,如下所示。这两个序列说明了第一步的两个选项:加 1(n = 16)和减 1(n = 14)。尽管 14 离期望的最终状态 1 更近,但 16 是更好的选择,因为它可以被更多次地除以 2。正如你在右侧图表上看到的,二进制形式中的尾随零的数量对应于一个数字可以被除以 2 的次数。

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

图片来自作者。

为了解决这个问题,我首先使用内置的bin函数将输入字符串(n)转换为二进制(b)。我使用了一个 while 循环将b减少到 1。如果b是偶数,我通过去掉尾部零来将其减半。尽可能多地将b减半将最小化总操作次数。如果b是奇数,我选择具有最多尾部零的最近邻整数。

如前所述,尾部零的数量表示一个给定的数字可以被二除的次数。尾部零更多的数字优先,因为它们允许更多的减半。换句话说,尾部零最多的数字提供了最有效的方法来达到 1。

级别 3:问题 2

开始时,我在纸上完成了大量的练习题。通过这样做,我意识到较大楼梯的解决方案包括了较小楼梯的解决方案。解决n涉及首先解决较小楼梯的子问题,这使得这是一个动态规划问题。

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

图片来自作者。

我在解决这个问题的累积特性时真的很挣扎。虽然我理解较小的楼梯如何贡献于较大的楼梯,但我无法弄清楚如何计算两个步骤的楼梯。例如,当n = 7时,我看到n = 3是解决方案的一部分,但我不知道如何计算其他两个步骤的楼梯。

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

图片来自作者。

作为一个练习,我简化了这个问题,并只是试图找出给定高度和n的楼梯数量。换句话说,我将上面的图表转为表格形式。

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

图片来自作者。

当我填充表格时,我找到了算法。对于每个单元格,我从n中减去楼梯高度。然后,我取余数并访问该列(n = remainder)。该列的总和等于解决方案的数量。在某些情况下,余数足够建造 1 步。为了计算这些情况,我在对角线上加了 1。请参见下图左侧的绿色数字。

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

图片来自作者。

例如,当n = 8staircase height = 5时,余数为n = 3。3 列包含两个解决方案:staircase height = 3staircase height = 2。因此,对于n = 8staircase height = 5,共有两个解决方案。

这种方法有效,但可能更高效。与其访问列中的每个单元格,不如将表格结构化,使得行表示最大楼梯高度。例如,max staircase height = 3将是给定n的高度为 1、2 和 3 的解决方案之和。下方的紫色数字代表这种累积方法。现在,找到解决方案只需要访问一个单元格。

注意下图中包含了一个n=0列。这样,列索引号等于n值。这一小变化大大简化了代码。

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

图片由作者提供。

第三级:问题 3

阅读问题后,我想到了几个短语。我搜索了诸如“固定概率状态”和“概率状态转移”等术语,最终找到了马尔可夫链。由于从每个状态到终端状态都有路径,这就是一个吸收马尔可夫链。终端状态,也称为吸收状态,意味着无法离开该状态(即,转移到其他状态的概率为零)。

我以前从未听说过马尔可夫链,所以在开始编写代码之前,我做了一些研究。这里 是对马尔可夫链的很好的概述。

吸收马尔可夫链的转移矩阵 P,对于有 t 个过渡状态和 s 个吸收状态的情况如下:

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

图片由作者提供。

然后可以使用转移矩阵来找到基本矩阵:

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

图片由作者提供。

基本矩阵提供了很多信息。但为了求解问题,还必须计算一个矩阵:

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

图片由作者提供。

M 中,行表示起始状态,列表示吸收状态。M[i][j] 的值是从过渡状态 i 开始被吸收到终端状态 j 的概率。因此,M 的行数由过渡状态的数量决定,而列数等于终端状态的数量。

首先,我需要找出过渡状态和吸收状态的数量及位置。然后,对于过渡状态,我需要将整数转换为分数。

给定以下输入:

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

图片由作者提供。

上面的代码将其转换为:

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

图片由作者提供。

接下来,我需要计算 IQ 矩阵以求解 N。由于我不能使用库,我复习了像 点积 和 矩阵求逆 这样的矩阵运算。

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

图片由作者提供。

现在,我需要求解 R

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

图片由作者提供。

现在,RN 都已经求解,我可以计算概率矩阵 M

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

图片由作者提供。

现在,M 必须格式化以匹配输出规范。由于问题只要求从状态 0 开始的概率,因此只需要第一行。正如上面所示,M 是以分数形式表示的。为了将答案格式化为表示概率分子的一维数组,我需要找到最小公倍数。最小公倍数将是概率之间的公分母。

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

图片来自作者。

这个问题中最棘手的部分是分数和重新学习矩阵操作。正如我在 Level 1 文章中提到的,这个挑战对接受的输出类型非常具体。

这是完整的解决方案。

结论

在级别结束时,我有机会提交我的联系信息给 Google 招聘人员。然而,那是超过一年前的事情了,Google 还没有联系我。

总体来说,我觉得这些问题的设计不仅仅是测试基础编码技能。解决这些类型的问题证明了你能够在处理复杂边缘情况和内存限制时开发解决方案。具有讽刺意味的是,我发现随着难度级别的提升,问题变得更容易了。然而,每解决一个新问题,我也开始更加聪明地工作,而不是更努力地工作。我重新阅读问题,暂停并在纸上绘制一些例子,而不是立即开始编码想到的第一个解决方案。最重要的是,我利用现有资源来学习新概念和巩固旧知识。

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

感谢你阅读我的文章。如果你喜欢我的内容,可以在 Medium上关注我。

LinkedIn Twitter* 或* Instagram上与我联系。

所有反馈都是受欢迎的。我总是渴望学习新的或更好的做事方式。

随时可以留下评论或通过 katyhagerty19@gmail.com 联系我。

谷歌生成式 AI 转型

原文:towardsdatascience.com/google-generative-ai-transformations-edb4164935cb

ETL 即将被改造

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

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

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

图片来源:Suzanne D. WilliamsUnsplash

这是什么?

大型语言模型(LLMs)可以提取信息并生成信息,但它们也可以转换信息,这使得提取、转换和加载(ETL)可能完全是一项不同的工作。我将提供一个例子来说明这些想法,这也应当展示 LLM 如何以及应该用于包括将非结构化文本转换为结构化文本在内的许多相关任务。

谷歌最近公开了其大型语言模型(LLM)系列产品,并将其中一部分命名为“生成式 AI 工作室”。简而言之,Google Cloud Platform 控制台中的 GenAI Studio 是谷歌 LLM 的用户界面。然而,与谷歌 Bard(一个使用 LLM 的商业应用)不同,谷歌不会出于任何原因保存你的数据。请注意,谷歌还发布了一个涵盖许多此处所述功能的 API。

使用 GenAI Studio

进入 GenAI Studio 非常简单——在 GCP 控制台中,只需使用左侧的导航栏,悬停在 Vertex AI 上,然后选择 概览 下的 生成式 AI 工作室

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

作者提供的图片

截至 2023 年 5 月底,有两个选项——语言和语音。(不久后,谷歌预计还会在此处发布视觉类别。)每个选项包含一些示例提示样式,这些样式可以帮助你激发想法并将现有的想法集中为有用的提示。但更重要的是,这是一个“安全”的类似 Bard 的体验,因为你的数据不会被谷歌保存。

语言

语言的登录页面是这个例子中唯一使用的功能,它有多个不同的功能,同时也包含了一个简单的方法来调整基础模型(目前调整只能在特定区域进行)。

创建提示

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

图片来源:作者

开始使用区域是快速创建与 Google 模型(取决于时间和交互类型,可能是一个或多个)的无指导交互的地方。

选择文本提示会调用一个类似 Bard 的用户界面,但有一些重要的区别(除了数据隐私之外):

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

图片来源:作者。

  • 底层的 LLM 可以更改。目前,text-bison001 模型是唯一可用的,但其他模型会随着时间出现。

  • 模型参数可以调整。Google 提供了每个参数的解释,旁边有问号。

  • 用于阻止不安全回复的过滤器可以调整(选项包括“阻止少数”、“阻止一些”和“阻止大多数”)。

  • 不适当的回复可以轻松报告。

除了与 Bard 的明显区别外,这种方式使用模型还缺乏一些 Bard 的“附加功能”,如时事。例如,如果输入一个询问昨天芝加哥天气的提示,这个模型不会给出正确答案,但 Bard 会。

大文本区域是输入提示的地方。

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

图片来源:作者

通过在提示部分输入文本、(可选地)调整参数,然后选择提交按钮来创建提示。在这个例子中,提示是“1+1 等于多少?”使用的是 text-bison001 模型和默认参数值。注意,模型仅返回数字 2,这是温度对回复影响的一个好例子。重复这个提示(通过重复选择提交大多数时候会得到“2”,但有时会随机给出不同的回复。将温度调整为 1.0 会得到:“答案是 2。1+1=2 是每个人在小学时学习的最基本的数学方程之一。它是以后学习的所有其他数学的基础。”这是因为温度调整了对标记的概率选择,值越低,回复的变化越少(即越确定)。如果在这个例子中将值设置为 0,模型将始终返回“2”。这很酷,非常类似 Bard,但更好。你还可以保存提示并查看提示的代码。以下是“1+1 等于多少?”的代码。

import vertexai
from vertexai.preview.language_models import TextGenerationModel

def predict_large_language_model_sample(
    project_id: str,
    model_name: str,
    temperature: float,
    max_decode_steps: int,
    top_p: float,
    top_k: int,
    content: str,
    location: str = "us-central1",
    tuned_model_name: str = "",
    ) :
    """Predict using a Large Language Model."""
    vertexai.init(project=project_id, location=location)
    model = TextGenerationModel.from_pretrained(model_name)
    if tuned_model_name:
      model = model.get_tuned_model(tuned_model_name)
    response = model.predict(
        content,
        temperature=temperature,
        max_output_tokens=max_decode_steps,
        top_k=top_k,
        top_p=top_p,)
    print(f"Response from Model: {response.text}")
predict_large_language_model_sample(
  "mythic-guild-339223", 
  "text-bison@001", 0, 256, 0.8, 40, 
  '''What is 1+1?''', "us-central1")

生成的代码包含提示信息,但很明显,函数predict_large_language_model_sample是通用的,可用于任何文本提示。

赶紧进入 ETL 吧!

在我的日常工作中,我花费大量时间来确定如何从文本(包括文档)中提取信息。LLM 可以以令人惊讶的简单和准确的方式做到这一点,并且在这样做时还可以更改数据。一个例子说明了这种潜力。

假设为了这个例子,以下电子邮件消息由一个虚构的 ACME Incorporated 接收:

Purchaser: Galveston Widgets

Dear Purchasing,

Can you please send me the following items, and provide an invoice for them?

Item        Number
Widget 11    22
Widget 22     4
Widget 67     1
Widget 99    44

Thank you.

Arthur Galveston
Purchasing Agent
(312)448-4492

还假设系统的目标是从电子邮件中提取特定数据,为每个输入项应用价格(和小计),并生成总计。

如果你认为 LLM 无法做到这些,重新考虑一下!

有一种提示风格叫做extractive Q&A,在某些情况下(如果通过调整模型而不是简单的提示工程应用,它可能在所有情况下都适用)非常合适。其思路很简单:

  1. 提供一个Background,即原始文本。

  2. 提供一个Q(即问题),应该是一些提取性的,例如“将所有信息提取为 JSON。”

  3. 可选择性地提供一个A(即答案),以获得所需的输出。

如果没有提供A,则应用零样本工程(这效果比我预期的要好)。你也可以提供一次性或多次样本,但有一定限制。提示的大小有限制,这限制了你可以提供的样本数量。

总结一下,提取性 Q&A 提示的形式如下:

**Background**: [the text]
**Q:** [the extractive question]
**A:** [nothing, or an example desired output]

在这个例子中,电子邮件是文本,而“将所有信息提取为 JSON”是提取性问题。如果没有提供A:,LLM 将尝试进行提取(零样本)。(JSON 代表 JavaScript 对象表示法。它是一种轻量级的数据交换格式。)

以下是零样本输出:

**Background**: Purchaser: Galveston Widgets

Dear Purchasing,

Can you please send me the following items, and provide an invoice for them?

Item        Number
Widget 11    22
Widget 22     4
Widget 67     1
Widget 99    44

Thank you.

Arthur Galveston
Purchasing Agent
(312)448-4492

**Q:** Extract all information as JSON
**A:**

你不需要加粗Background:, Q:, 和 A:,我这样做只是为了清晰。

在 UI 中,我将提示保持为FREEFORM,并在提示区域中输入了上述提示。然后,我将Temperature设置为 0(我希望每次相同的输入得到相同的回答),并将Token limit增加到 512,以允许更长的响应。

以下是零样本提示和回复的样子:

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

作者提供的图像

“E”xtract 有效,甚至能够很好地将条目列表放入 JSON 中。但这已经足够好了。假设我的要求是为数据提供特定的标签,并且假设我还希望捕捉采购代理及其电话。最后,假设我希望有行项目小计和总计(这一假设要求存在行项目价格)。

我理想的输出,即“E”xtract 和“T”ransform,如下所示:

{"company_name": "Galveston Widgets",
"items" : [
   {"item_name": "Widget 11",
    "quantity": "22",
    "unit_price": "$1.50",
    "subtotal": "$33.00"},
   {"item_name": "Widget 22",
    "quantity": "4",
    "unit_price": "$50.00",
    "subtotal": "$200.00"},
   {"item_name": "Widget 67",
    "quantity": "1",
    "unit_price": "$3.50",
    "subtotal": "$3.50"},
   {"item_name": "Widget 99",
    "quantity": "44",
    "unit_price": "$1.00",
    "subtotal": "$44.00"}],
"grand_total": "$280.50",
"purchasing_agent": "Arthur Galveston",
"purchasing_agent_phone": "(312)448-4492"}

对于这个提示,我将 UI 从FREEFORM更改为STRUCTURED,这使得数据布局稍微容易一些。使用这个 UI,我可以为 LLM 设置一个Context(这可能对模型响应产生惊人的效果)。然后,我提供一个Example——包括输入文本和输出文本——以及一个Test输入。

参数对于 STRUCTURED 和 FREEFORM 是相同的。这里是上下文示例(包括输入输出)用于发票 ETL 示例。

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

作者提供的图片

我添加了一个测试电子邮件,数据完全不同(尽管小部件相同)。以下是 UI 中显示的所有内容。我然后选择了**提交,**这填充了测试 JSON,在图片的右下角窗格中。

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

作者提供的图片。

那就是巫术魔法。 是的,数学完全正确。

那么 “L” 呢?

到目前为止,我已经展示了提取和转换——现在是加载部分。那部分其实很简单,对于零-shot(如果通过 API 完成,则需要两个调用——一个用于 E+T,一个用于 L)。

我将上一步的 JSON 作为背景,并将Q: 更改为“将 JSON 转换为 SQL 插入语句。”以下是结果,它推断出一个invoices 表和一个invoice_items 表。(你可以通过提问和/或示例 SQL 来微调 SQL。)

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

作者提供的图片

这意味着什么

这个示例展示了一个相当惊人的 LLM 能力,这可能会改变 ETL 工作的性质。我毫不怀疑 LLM 在这个领域的能力有限,但我还不知道那些限制是什么。与模型一起解决你的问题对于理解 LLM 能做什么、不能做什么,以及应该做什么至关重要。

未来看起来光明,GenAI Studio 可以让你迅速上手。记住,UI 提供了一些简单的复制/粘贴代码,以便你可以使用 API 而不是 UI,这对于实际进行此类工作的应用程序是必要的。

这也意味着锤子仍然不能建造房子。我的意思是模型没有搞定这个 ETL 示例。LLM 就是那个非常复杂的“锤子”——我就是木匠,就像你一样。

免责声明

本文是作者的观点和看法,并不反映其雇主的立场。(以防万一 Google 在观看。)

Google Med-PaLM:AI 临床医生

原文:towardsdatascience.com/google-med-palm-the-ai-clinician-a4482143d60e

人工智能 | 医学 | 自然语言处理 |

谷歌的新模型经过训练以回答医学问题。怎么做到的?

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

·发布于 Towards Data Science ·14 min read·2023 年 3 月 17 日

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

作者使用 OpenAI DALL-E 制作的图片

医学还基于患者和医生之间的互动。此外,尽管患者接受了不同的检查和影像技术,但总是会有书面报告。那么,为什么医疗和健康领域的 AI 模型未能充分利用语言呢?

医学的基础模型?

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

图片由 Myriam Zilles 在 Unsplash 上拍摄

近年来的趋势是尝试限制大型 语言模型 (LMs),然后 微调 以满足所需的应用。类似的方法可以应用于大量医学文本,使模型能够学习有用的表征。对医学主题有良好理解的模型可能对无数应用有帮助(例如,患者分诊、知识检索、关键发现的总结、诊断辅助等)。

问题在于医学领域是一个特殊领域。与其他领域相比,这里有不同的问题,甚至更大的安全问题。正如我们所见,像 ChatGPT 这样的模型也可能产生幻觉,并且可能传播错误信息。

[## 关于 ChatGPT 的一切你需要知道的内容

了解已知信息、最新消息、其影响以及正在变化的情况。所有这些都在一篇文章中。

medium.com

谷歌的一项新研究专注于利用广泛的语言模型编码临床知识,并评估其在医学中的潜力。他们决定从一个具体任务开始:医学问答。这是因为它是一个基本但也困难的任务:模型必须提供高质量的医学问题答案。为此,模型还必须理解医学背景,找到相关信息,并依据专家的问题进行推理。

[## 大型语言模型编码临床知识

大型语言模型(LLMs)在自然语言理解方面展示了令人印象深刻的能力…

arxiv.org

事实上,为医学创建语言模型(LM)的想法并不新鲜。事实上,多年来已经有过尝试。这是因为 LM 可以通过大量文本(通常是书籍或维基百科等通用文本)以无监督的方式进行训练。

模型在没有具体任务的情况下进行训练,但正如扩展法则所示,LM 能够展现出使其能够适应特定任务的突现行为,而无需梯度更新。一个例子是在上下文少样本学习中,模型能够“快速概括到未见任务,甚至表现出明显的推理能力,配合适当的提示策略。”此外,模型隐式地充当知识库,但也有放大训练数据集中存在的偏见的缺点。

无论如何,已经尝试了几种方法,因为有数百万篇医学文章和无数医学数据可以利用。早期模型基于BERT(sciBERT、BioBERT、PubMedBERT、DARE、ScholarBERT)。此外,也尝试过基于 GPT 架构的模型,如最近的 BioGPT。

[## 微软 BioGPT:迈向生命科学的 ChatGPT?

BioGPT 在不同生物医学自然语言处理任务中实现了SOTA

levelup.gitconnected.com

那么这项研究带来了什么新的东西呢?

  • 一个允许更好评估语言模型在医学问答中的新数据集。

  • 在医学问答基准上达到最先进的结果。

  • 指令提示调整以提高对医学领域的对齐。

  • 对语言模型在医学领域的局限性的深入分析。

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

“我们贡献的概述:我们策划了 MultiMedQA,一个涵盖医学考试、医学研究和消费者医学问题的医学问答基准。我们在 MultiMedQA 上评估了 PaLM 及其指令调整变体 Flan-PaLM。通过组合提示策略,Flan-PaLM 在 MedQA(USMLE)、MedMCQA、PubMedQA 和 MMLU 临床主题上超越了 SOTA 性能。特别是,它在 MedQA(USMLE)上的表现比之前的 SOTA 提高了超过 17%。接下来,我们提出了指令提示调整以进一步将 Flan-PaLM 与医学领域对齐,生成了 Med-PaLM。在我们的人类评估框架下,Med-PaLM 对消费者医学问题的回答与临床医生生成的回答相比表现良好,展示了指令提示调整的有效性”。图像来源:这里

如何评估医学中的语言模型?

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

图片来源:在线营销 在 Unsplash

首先,我们需要一个好的数据集。作者指出,尽管有几个用于研究的数据集,但每个数据集都关注于特定的方面或任务:医学考试问题、医学考试问题和医学信息需求的有用答案。

我们承认医学知识在数量和质量上都是巨大的。现有基准固有地有限,只提供了医学知识空间的部分覆盖。然而,将多个不同的数据集合并用于医学问答,使得对 LLM 知识的评估比选择题准确性或诸如 BLEU 这样的自然语言生成指标更为深入。(来源)

作者换句话说,一个数据集是不够的,因为该领域相当广泛。此外,评估诸如BLEU(或其他指标)这样的指标并不能展示模型理解领域的能力。

新构建的数据集要求模型能够回答选择题、开放性问题(长形式)、封闭领域(答案必须在参考文本中找到)和开放领域问题(特定来源中信息有限)。

总结来说,作者通过结合已经使用的数据集和策划的常见健康查询数据集,构建了一个新的基准。整个数据集均为英文,并涵盖了医学考试、医学搜索,甚至是消费者查询。还有标签和元数据。

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

(source)

鉴于领域的复杂性,他们通过临床医生编写的答案丰富了数据集。此外:

其次,鉴于医疗领域的安全关键要求,我们认为有必要超越使用 BLEU 等指标的自动化长答案生成质量测量,转向涉及更细致的人类评估框架,如本研究中提出的框架。

一个多项选择题的示例:

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

(source)

以及长答案问题:

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

(source)

作者们随后定义了一个框架,以便临床医生能够衡量模型的稳健性。的确,尽管使用指标很有用,但它忽略了许多重要细节,在医学背景下可能会产生误导。

作者们使用了来自英国、美国和印度的临床医生的焦点小组和访谈来定义评估轴。此外,他们强调了“与科学共识的一致性、伤害的可能性和概率、答案的完整性和缺失情况以及偏见的可能性。”

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

“总结了临床医生在我们的消费者医疗问题回答数据集中评估答案的不同方面。这些包括与科学共识的一致性、伤害的可能性和概率、理解证据、推理和检索能力、不适当、错误或缺失内容的存在以及答案中的偏见可能性。我们使用了一组临床医生来评估模型和人工生成答案在这些方面的质量。” (source)

表格总结了表单呈现的问题种类。正如作者所述,伤害和偏见都是复杂的概念,没有单一答案。例如,伤害可以在不同层面上定义:“身体健康、心理健康、道德、财务等。”因此,作者创建了一个包含不同问题的表单,并将其提供给不同国家(美国、英国和印度)的临床医生。

另一方面,并非每个人都有医学知识,因此作者决定评估答案对消费者的帮助性和实用性。他们创建了一个表单,并由没有医学背景的人进行评分:

这项工作旨在评估答案如何应对问题背后的感知意图,以及答案的帮助性和可操作性如何。 (source)

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

“总结了普通用户在我们的消费者医学问答数据集中评估答案实用性的不同轴向。我们使用了 5 位非专家普通用户来评估模型和人工生成答案在这些轴向上的质量。” (source)

哪种模型?

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

图片由 Kimon Maritz 提供,来源于 Unsplash

作者开始使用 Pathways 语言模型(PaLM)和 Flan-PaLM 家族。

PaLM 是“一种密集激活的解码器-only 变换器语言模型,使用 Pathways 进行训练。” 该模型使用了包括互联网数据、维基百科、源代码、社交媒体对话和书籍在内的大规模语料库进行训练。PaLM 最大版本包含 540 B 的参数,并在多个基准测试中达到了最先进的水平。

Flan-PaLM 是 PaLM 的指令调整版。Flan-PaLM 使用了不同的数据集进行指令调整。如上所示,使用思维链使模型能够更好地泛化。

## 多模态思维链:在多模态世界中解决问题

世界不仅仅是文本:如何将思维链扩展到图像和文本?

towardsdatascience.com

一旦我们拥有模型,主要的问题就是如何将其适应医学领域:

然而,考虑到医学领域的安全关键性质,有必要将模型适应并对齐领域特定的数据。 (source)

作者决定使用提示和提示调整作为策略。正如所示,语言模型是少量示例学习者(需要少量示例)以进行上下文学习。换句话说,通过一些精心挑选的提示示例,模型可以在没有任何梯度更新或微调的情况下学习新任务。作者使用了三种提示策略:

  • 少量提示。通过基于文本的描述(输入-输出对)描述任务的少量示例。最佳演示是在与合格临床医生一致的情况下完成的(针对每个数据集)。

  • 思维链提示。在提示中添加一系列中间推理步骤以得出最终答案(这种方法模仿了人类在解决问题时的推理过程)。这些提示也与临床医生一起创建。

  • 自一致性提示。 提高模型在多项选择题中表现的一种策略是从模型中采样多个解码输出(最终答案将是获得多数票的那个)。‘其背后的想法是,在复杂领域中,可能有多条路径可以达到正确答案。

如前所述,提示方法使得相对低成本地改进模型成为可能(微调如此大型的模型计算成本高)。但是提示对许多任务来说是不够的,它们将从微调中受益。

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

Anton Shuvalov在 Unsplash 拍摄

如何对 540B 模型进行微调?

答案:提示微调。 简而言之,提示微调是一些提示(由人类或 AI 模型生成的向量)用于引导模型完成预期任务。提示有两种类型,一种是由人类编码的(硬提示),另一种是通过反向传播学习到的(软提示)。这将可学习的参数缩小到仅表示少量标记(其余模型被冻结)。

该研究的作者使用了软提示和相关任务特定的人类设计提示(硬提示)。

我们将这种提示微调的方法称为“指令提示微调”。指令提示微调因此可以被视为一种轻量级的方法(数据高效、参数高效、训练和推理过程中计算高效)来训练模型以遵循一个或多个领域的指令。 (source)

然后,他们在一小部分示例上使用了指令提示微调,将 Flan-PaLM 适配到医学领域。由于这些示例较少,它们必须是“医学理解、临床知识回忆和医学知识推理方面的良好示例,不容易导致患者伤害。” 换句话说,这些示例特别与医学专家(来自不同学科的临床医生)合作精心策划。

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

医疗领域的指令提示微调 (source)

Med-PaLM:它是否比其他模型更好?

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

图像由Steven Lelham在 Unsplash 拍摄

模型已达到并超越了现有技术水平:

  • MedQA, 涵盖一般医学知识的多项选择题(美国医学执照考试)。

  • MedMCQA, 来自印度的医学入学考试问题(多项选择题)。

  • PubMedQA, 生物医学科学文献。

  • MMLU, 多项选择题涵盖临床知识、医学和生物学的各种主题。相关主题

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

左侧:SOTA LLMs 在 MMLU 临床主题上的比较。右侧:PaLM 和 Flan-PaLM 模型在不同模型尺寸变体上的表现总结。改编自这里

结果在不同临床主题类别中也保持一致,显示出 Flan-PaLM 在所有类别中都达到了 SOTA 水平。

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

(source)

作者们还决定评估模型在不同模型尺寸下的表现,使用了 MultiMedQA 中的医学问答数据集。这表明,当使用少量示例提示时,扩展模型规模可以提升模型性能。同时,结果还表明,指令微调相比基线提高了性能。

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

(source)

此外,作者提到了两个有趣的因素:

  • 首先,思维链(CoT)提示在这种情况下并没有带来改进(这实际上令人惊讶)。

  • 自一致性(SC)在多项选择题表现上带来了显著改善(这是预期中的结果)。

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

左侧:Flan-PaLM 模型在少量示例和思维链(CoT)提示下的表现总结。右侧:Flan-PaLM 模型在有无自一致性提示(SC)下的表现总结。改编自这里

该模型也能够生成解释,说明它为何选择了特定的响应:

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

“Flan-PaLM 540B 模型生成的示例解释,以支持其多项选择答案”(source

语言模型(LMs)可能会产生幻觉,在医学背景下,这可能是灾难性的。因此,作者调查了 LLM 不确定性与陈述准确性之间的关系。换句话说,他们使用了模型置信度,发现更高的置信度对应着更高的准确性。

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

Flan-PaLM 540B 模型的推迟行为分析(source

该模型是否能说服临床医生?

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

图片由Sander Sammy提供,来自 unsplash

最佳准确性是否足以在临床中使用该模型?

指标很重要,但可能会产生误导。特别是在像医学这样敏感的领域中,需要的不仅仅是基准测试的结果。

作者选择了 100 个可能代表真实消费者询问的问题。随后,他们使用 Flan-PaLM 和 Med-PaLM(两个 540B 模型)来预测回答,并将其提交给了一个由 9 位临床医生(来自美国、英国和印度)组成的评审小组。

尽管临床医生在 92%的问题上达成了科学共识,但 Flan-PaLM 在 61%的情况下达成了一致。

这表明,单独的通用指令微调不足以产生科学和临床上可靠的答案。然而,我们观察到 92.9%的 Med-PaLM 答案被评定为符合科学共识,展示了指令提示微调作为对齐技术在产生科学基础答案方面的优势。 (source)

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

(source)

模型是在以前发布的文章和书籍上进行训练的,因此作者指出这可能是失败的原因之一,未来应继续探索学习。

然后,作者询问临床医生模型在理解、知识检索和医学知识推理能力方面是否存在错误。在这里,Med-PaLM 再次表现优于 Flan-PaLM。

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

(source)

作者询问答案是否包含错误或缺失内容(生成答案的完整性和正确性)。也就是说,模型是否遗漏了应有的信息,或者答案中是否有不应包含的信息。Med-PaLM 的答案在 15%的情况下显示了重要信息的遗漏(相比之下,Flan-PaLM 为 47%)。令人惊讶的是,Med-PaLM 的错误率高于 Flan-PaLM(18%对 16%)。作者对此结果的解释如下:

指令提示微调使 Med-PaLM 模型生成的答案显著比 Flan-PaLM 模型更详细,从而减少了重要信息的遗漏。然而,较长的答案也增加了引入不正确内容的风险。 (source)

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

作者还探讨了生成响应可能带来的潜在危害的严重性和可能性。换句话说,他们询问这些响应是否可能导致临床医生或消费者/患者采取可能造成健康相关伤害的行动。尽管定义是相对的,评分在这种情况下是主观的,但与基线模型相比,指令微调产生了更安全的响应。

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

(source)

此外,作者分析了模型在医疗保健中放大偏见的潜在风险。该模型可能反映或放大训练数据中存在的反映健康结果和护理获取差异的模式。结果显示,新方法显著降低了偏见风险。

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

(source)

最后,作者分析了非专家如何评估答案。

尽管 Flan-PaLM 的回答被评估为在 60.6%的情况下有帮助,但 Med-PaLM 的回答这一数字提高到了 80.3%。 (source)

但仍然不如临床医生。通过询问非专家消费者回答是否直接回答了用户的问题,得到了类似的结果。

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

(source)

模型的局限性

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

Joshua Hoehne 在 unsplash 拍摄

作者指出了研究的若干限制和未来方向:

  • 他们提出的数据集(MultiMedQA)并不全面(尽管包含了多个来源)。例如,它在生物学方面存在不足。此外,模型还应包括更贴近现实世界的问题和答案(多项选择题容易填补,但与现实世界相距甚远)。

  • 与专家的性能评估显示该模型尚不具备临床医生的水平

  • 相同的人类评估方法可以改进。 当然,它是有限的,专家的数量应该增加。共识的概念是与上下文和时间相关的。此外,科学共识往往没有考虑到少数群体,因此可能本身就是偏见的来源。更不用说它受到了临床医生自身背景的影响。

  • 偏见和伤害的分析是有限的,考虑到这是探索性工作。另一方面,医疗领域是一个极其敏感的领域,这些都是不能忽视的伦理问题。因此,分析应该扩展到包括患者。此外,缺乏类似任务的特定基准数据集。

最后的思考

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

Amine rock hoovr 在 Unsplash 拍摄

这篇论文展示了如何通过指令提示调优来改善模型在医疗问答等复杂领域的表现。然而,这种行为随着模型规模的增加而出现。此外,与其他模型相比,该模型实现了最先进的技术水平。

PaLM 的 540 B 版本单独仍然能够取得显著的成果。可能训练数据包含了多个医学来源,模型在参数中存储了这些信息。

与人类专家的评估显示,仅仅扩大规模并不够。即使是 Med-PaLM 自身也可能产生不完整或错误的回答。

无论如何,目前仍然为时尚早,尚无法在医疗保健中使用这样的模型。首先,需要更多的研究以确保模型的安全性。虽然目前很难假设使用它来治疗疾病,但可以考虑作为一种向患者提供有关疾病和药物信息的方法。

另一方面,医生也有偏见,而语言模型可能是高效的助手。未来,语言模型还可能在减轻偏见和提供更广泛的治疗选择方面发挥作用。

最后,谷歌发布了 PaLM 的 API,旨在用于原型设计和构建生成型 AI 应用程序(更多信息

如果你觉得这很有趣:

你可以查看我的其他文章,也可以订阅以便在我发布文章时收到通知,还可以在LinkedIn上联系我

这里是我的 GitHub 库链接,我计划在这里收集与机器学习、人工智能等相关的代码和资源。

[## GitHub - SalvatoreRa/tutorial: 机器学习、人工智能、数据科学的教程…

机器学习、人工智能、数据科学的教程,包含数学解释和可重用的代码(Python…

github.com](https://github.com/SalvatoreRa/tutorial?source=post_page-----a4482143d60e--------------------------------)

或者你可能对我最近的文章感兴趣:

[## PCA:生物信息学家的最爱工具可能具有误导性

一项新的研究评估了一个最常用的技术可能存在的问题

pub.towardsai.net](https://pub.towardsai.net/pca-bioinformaticians-favorite-tool-can-be-misleading-fe139262a576?source=post_page-----a4482143d60e--------------------------------) [## 稳定扩散与大脑:AI 如何读取我们的思想

研究人员能够使用 fMRI 数据重建图像

levelup.gitconnected.com](https://levelup.gitconnected.com/stable-diffusion-and-the-brain-how-ai-can-read-our-minds-45398b395ea9?source=post_page-----a4482143d60e--------------------------------) [## 稳定扩散填补医疗图像数据的空白

一项新的研究表明,稳定扩散可能有助于医学图像分析和稀有疾病。如何?

levelup.gitconnected.com 为什么我们有庞大的语言模型和小型视觉变换器?

Google ViT-22 为新一代大型变换器铺平了道路,并有望革新计算机视觉

towardsdatascience.com 为什么我们有庞大的语言模型和小型视觉变换器?

简单的 Google Pub/Sub 到 BigQuery 方法

原文:towardsdatascience.com/google-pub-sub-to-bigquery-the-simple-way-de116234fb87

实施 BigQuery 订阅的动手指南,适用于 Pub/Sub 简单消息和流式数据摄取

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

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

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

Google 最新的行星规模数据仓库订阅基础的流式摄取水下军事能力:BigSub。在这种情况下,Pub 从未达到正式发布状态,因此你必须去其他地方寻找你的啤酒。照片由 Thomas Haas 提供,来源于 Unsplash

动机

我过去遇到过许多情况,我想将 Pub/Sub 消息导入 BigQuery 表中,但我从未找到一种特别简单的方法来实现这一点。

你可以设置一个 dataflow pipeline,但这需要额外的基础设施来理解、配置、管理和调试。而且 Dataflow(作为一种托管的 Apache Beam 服务)设计用于高吞吐量流式处理,因此对于简单的消息日志记录或监控系统来说总是显得过于复杂。

而且它是 Java。可是 Python 😀!而 Java… 😫!

public static string args void main... public static string args void main... public static string args void main... public static string args void main... public static string args void main... arrrrrrrrrrrrgh

对不起,我仍然会对我第一次尝试在 Java 中学习编码(上个世纪)时的经历感到闪回。请不要尝试使用那个代码片段……远离代码片段。

然后我偶然发现了 这个,虽然它承诺简单性,但似乎比之前的方法(Debezium wtf?)还要复杂!

也可以部署一个轻量级的 Cloud Function 以在接收到 Pub/Sub 消息时触发,并将其流式传输或加载到 BigQuery 中,但这似乎仍然有些复杂,因为这本应是原生功能。

现在它已经实现了!

谷歌云的友善团队宣布了一段时间前从 Pub/Sub 到 BigQuery 的直接连接,太棒了!然而,尝试(并且失败)快速设置测试几次后,我终于有了一个实际的用例,需要为一个客户使其正常工作。

结果发现有几个细微之处,所以这篇文章旨在帮助你尽快地让这一切运行起来。

现状

Pub/Sub 是 Google Cloud 生态系统中一个极其有用、强大且可扩展的服务,具有两个核心用例:流式传输和消息传递。我将让 Google 自行解释(令人失望的剧透:这与位于潜艇上的公共房屋无关)。

Pub/Sub 用于流式分析和数据集成管道,以摄取和分发数据。它同样有效地作为服务集成的消息中介或作为队列来并行化任务。

Pub/Sub 使你能够创建事件生产者和消费者系统,称为发布者订阅者。发布者通过广播事件而不是通过同步远程过程调用(RPC)与订阅者异步通信。

消息被发布到一个主题,主题的订阅者可以接收消息并相应地采取行动。发布者对订阅者一无所知,但当消息被发布时,订阅者可以根据消息内容采取行动。

客户端库或Cloud Storage Buckets 上的通知使发布包含可配置元数据的消息变得简单,而 Pub/Sub 会将这些消息发送到其他 Google Cloud 目的地以触发 Cloud Functions或各种不同的操作,只有你的想象力限制了这些操作。

现在我们可以将这些数据原生地导入 BigQuery(显然很简单),所以我抓住机会在几分钟内完成这个工作!但结果证明并没有那么简单。不过我完成了这个任务,所以我想写这篇文章来帮助其他需要快速设置的人,尽量减少麻烦。

解决方案

那么从哪里开始呢?我们从文档开始吧。

BigQuery 订阅在接收到消息时会将其写入现有的 BigQuery 表。你不需要单独配置订阅客户端。使用 Google Cloud 控制台、Google Cloud CLI、客户端库或 Pub/Sub API 来创建、更新、列出、分离或删除 BigQuery 订阅。

很好。我们开始吧。

作为简单数据摄取管道的替代方案,这些管道通常使用 Dataflow 写入 BigQuery,BigQuery 订阅具有以下优点:

简单部署。 你可以通过控制台、Google Cloud CLI、客户端库或 Pub/Sub API 通过一个工作流设置 BigQuery 订阅。

提供低成本。 除去了类似 Pub/Sub 管道中包含 Dataflow 作业的额外成本和延迟。这种成本优化对那些在存储前不需要额外处理的消息系统特别有用。

减少监控。 BigQuery 订阅是多租户 Pub/Sub 服务的一部分,无需你运行单独的监控作业。

听起来不错!继续前往模式部分。我必须承认,阅读几遍后,我对需要做的事情感到有些困惑。

在普通环境中,管理模式可能相当复杂,在这种情况下,我需要创建一个 BigQuery 表,其模式完全镜像输入的 JSON 数据:

使用主题模式。 这个选项允许 Pub/Sub 使用Pub/Sub 主题的模式,即订阅所附加的主题。此外,Pub/Sub 将消息中的字段写入 BigQuery 表中的相应列。当你使用此选项时,请记得检查以下额外要求:

主题模式中的字段和 BigQuery 模式中的字段必须具有相同的名称,并且它们的类型必须兼容。

哎呀。实际的输入数据可能非常复杂。它可能是嵌套的,包含数组并可能有数百个字段。JSON 和 BigQuery 结构映射得相当干净(数组 = ARRAY,对象 = STRUCT),但生成一个完全匹配的空 BigQuery 表并不是一件简单的事。

但也有另一种选择。

如果你没有选择 使用主题模式 选项,请确保 BigQuery 表中有一个名为 dataBYTESSTRING 类型的列。Pub/Sub 将消息写入这个 BigQuery 列。

好的,这看起来可能是一个可行的方法。我们先将数据导入 BigQuery,然后再处理解码 JSON 的问题。实际上,我倾向于这种架构,因为任何不合规的数据仍会被接收,我们可以尝试在下游解码它。

演变模式也是如此。将原始 JSON 导入 BigQuery 的好处在于——由于它仅仅是文本——这是一个极其稳健的数据导入点。然后我们可以使用最近扩展的BigQuery JSON 函数来执行各种操作。

下游转换也更为稳健:尝试选择在普通 SQL 中不存在的列会导致查询错误,而尝试从 JSON 对象中提取等效的不存在字段将简单地返回 NULL。这样处理后,会得到一个更为稳健的流程。

输入表创建

接下来是创建用于接收原始 JSON 数据的输入表。

你可以在 UI 中创建表格,但实际上通过DDL在 BigQuery 控制台中完成这一操作非常简单(而且对我来说比截图更快 😀),然后当你第一次做错时,改变一个参数(或添加缺失的字符)并点击运行就会少很多挫败感。

表格模式实际上在文档的编写元数据部分中解释,这几乎总是增加上下文和调试支持的好主意。

创建表格的 DDL(包含所有可能的字段)如下:

CREATE OR REPLACE TABLE 
`[project_id].[dataset_name].[table_name]` 
(
subscription_name STRING,
message_id STRING,
publish_time TIMESTAMP,
data JSON,
attributes JSON
)
PARTITION BY TIMESTAMP_TRUNC(_PARTITIONTIME, DAY)

表格分区

在 BigQuery 中,分区几乎总是一个好主意(有时是必不可少的方法),因为它将数据物理上隔离到不同的分区中,这样可以直接查询这些分区,而无需昂贵的全表扫描。

表格分区有许多不同的选项,但需要注意的是,目前有一个4000 个分区的限制,因此每日分区将在近 11 年后达到上限,但每小时分区将在不到 24 周后达到上限。

这里有一个附注,有时由于流数据的量,确实需要使用每小时分区(例如,我们已经实现了从Tealium 的 EventStream 数据)。在这种情况下,需要部署额外的架构,将历史数据备份到 Google Cloud Storage,并设置分区过期

另一个附注:为了简洁起见,我省略了我们为使这个过程可靠运行而采取的测试步骤。这就是从他人经验中学习的美妙之处:你可以跳过繁琐的部分,直接得到答案!

设置 Pub/Sub 主题

现在是实际设置 Pub/Sub 主题和 BigQuery 订阅的部分,这应该是一个相当快速的过程。前往Cloud Console 中的 Pub/Sub并点击[+] CREATE TOPIC按钮。你在这里有相当大的命名自由度,所以我倾向于给它和目标dataset_id完全相同的名称,不带project_id(即dataset_id.table_name)。取消勾选Add a default subscription框(因为我们接下来要创建一个 BigQuery 订阅),然后点击CREATE

设置 Pub/Sub 订阅

一旦主题设置好,就可以开始创建订阅了。

点击你刚刚创建的主题,你应该看到一个底部区域,里面有多个选项卡,默认情况下选中的是SUBSCRIPTIONS。在这个区域点击CREATE SUBSCRIPTIONS并为订阅命名(实际上你可以将订阅名称与主题名称相同,我从未遇到过问题)。

Delivery Type部分,选中Write to BigQuery旁边的单选按钮,选择之前创建的表的project_iddataset_idtable_name。勾选Write Metadata复选框(我们喜欢元数据),并且—为了简单起见—将其他选项保留为默认设置。虽然建议 BigQuery 订阅应该启用死信队列,但这需要额外的主题,所以在这种情况下我们不启用。同时,由于我们不依赖使用主题模式,我们遇到失败消息的可能性也大大降低。

完成!

哦,等等。稍等一下。

权限

你很可能会看到一个错误信息,阻止你成功创建订阅。

Service account service-#############@gcp-sa-pubsub.iam.gserviceaccount.com is missing permissions required to write to the BigQuery table: bigquery.tables.get, bigquery.tables.updateData.

实际上,这很简单,但你有几个选择。

最安全的选项,符合最小权限原则,是创建一个具有精确权限(bigquery.tables.getbigquery.tables.updateData)的自定义角色,然后将此角色分配给服务账户。

但是,由于这是一个在我的项目中从未用于其他用途的 Google Cloud 服务账户,我愿意给予它一个更简单、更宽松的角色。

无论如何,复制消息中的服务账户邮箱,进入入站表,点击SHAREADD PRINCIPAL。将服务账户邮箱复制到New Principals字段中。将BigQuery Data Editor角色或创建的自定义角色添加到分配角色中,然后SAVE

希望这将顺利完成,你将拥有一个完全功能、简单的无服务器数据摄取流程,来自任何任意的 Pub/Sub 主题。

做得好!

下一步

现在你的数据摄取流程正常运行,我需要去做一些实际工作,所以我将留下来让你用一些真实的 Pub/Sub 消息进行测试。

使用最简单的方法之一是设置 BigQuery 定时查询的 Pub/Sub 通知,然后运行几次。你将看到每次运行时表格中都会增加一行,其中的JSON数据在dataattributes列中包含了每次运行的所有有用数据。

我的下一篇文章将解释将JSON有效负载解码为 BigQuery 数据类型的最佳设置,以便你可以开始使用和可视化数据。

如果你想接收第二部分(希望下周发布),记得关注我!

如何使用 Python 更改 Google 表格权限

原文:towardsdatascience.com/google-sheet-permissions-python-fee1ff80363

使用 Python API 以编程方式与特定用户共享 Google 表格

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

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

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

Artur TumasjanUnsplash 上拍摄

与他人共享 Google 表格是一个简单直接的任务,可以通过用户界面完成。然而,如果您需要将多个 Google 表格与特定用户或服务帐户共享呢?

想象一下,您在 BigQuery 上创建了数百个外部表,这些表从各种 Google 表格中获取数据。如果其他服务,例如 Apache Airflow,执行引用这些表的查询,您需要确保 Airflow 的服务帐户对所有这些表格具有足够的权限。但是,手动共享(即授予 ViewerEditor 权限)数百个表格给特定主体几乎是不可能的,并且需要几个小时。

在本教程中,我们将演示如何使用 Python 和 Google Drive API 一次性更改数百个 Google 表格的权限

先决条件

我们首先需要确保成功获得了带有所需作用域的用户访问凭证。为此,只需运行以下命令:

gcloud auth application-default login --scopes=https://www.googleapis.com/auth/spreadsheets,https://www.googleapis.com/auth/drive,https://www.googleapis.com/auth/iam.test

然后会弹出一个窗口,在默认浏览器中请求您登录 Google 帐户。请登录,因为凭证将适用于所有使用我们将在接下来几节中演示的应用程序默认凭证客户端库的 API 调用。

然后确保通过 pip 安装 Python API 客户端 google-api-python-client(最好在一个全新的虚拟环境中):

$ python3 -m pip install google-api-python-client

查找 Google 表格的 ID

在开始编写自动化解决方案以授予 Google Sheet 文件权限之前,我们首先需要找出所有感兴趣的每个文件的 ID。

要查找 Google Sheet 的文件 ID,只需在你喜欢的网页浏览器中打开它。链接应类似于下面显示的内容:

https://docs.google.com/spreadsheets/d/abc-defg-1234/edit#gid=0 

abc-defg-1234对应于 Google Sheet 的 ID。

https://docs.google.com/spreadsheets/d/spreadsheetId/edit#gid=0

有关 Google Sheets URL 是如何构建的更多详细信息,请参阅Google Sheets API概述。

使用 Python Google API 客户端更改 Google Sheet 权限

首先,让我们创建一个包含我们将要更改权限的 Google Sheet 文件 ID 的列表:

google_sheet_ids = [
  'abc-1234',
  'def-5678',
  'ghi-9123',
]

现在我们需要做的第二件事是推断应用程序默认凭证,并创建 Google Drive 服务。

import google.auth
from googleapiclient.discovery import build 

def create_service() -> Resource:
    """
    Creates a Google Drive (v3) service to interact with the API
    """
    scopes = [
        'https://www.googleapis.com/auth/spreadsheets',
        'https://www.googleapis.com/auth/drive',
    ]

    creds, project_id = google.auth.default(scopes=scopes)
    service = build('drive', 'v3', credentials=creds, cache_discovery=False)

    return service

现在,让我们创建一个只包含指定权限所需字段的 dataclass,基于权限 REST 资源

from dataclasses import dataclass

@dataclass
class Permission:
    """
    Class that corresponds to the `permission` REST resource
    https://developers.google.com/drive/api/reference/rest/v3/permissions#Permission
    """
    type: str
    role: str
    emailAddress: str

    def __post__init__(self):
        """Validate input"""
        allowed_types = ['user', 'group', 'domain', 'anyone']
        if self.type not in allowed_types:
            raise ValueError(f'`{self.type}` is not a valid type. {allowed_types=}')

        allowed_roles = ['commenter', 'reader', 'writer', 'fileOrganizer', 'organizer', 'owner']
        if self.role not in allowed_roles:
            raise ValueError(f'`{self.role}` is not a valid role. {allowed_roles=}')

在下一步中,我们将编写一个函数,该函数本质上接受服务和权限的实例以及文件 ID,并尝试创建一个新的权限。

from typing import Optional

from googleapiclient.discovery import Resource
from googleapiclient.errors import HttpError

def create_permission(
    service: Resource,
    permission: Permission,
    file_id: str,
    skip_on_failure: Optional[bool] = True,
):
    """
    Creates a new `permission` for the specified `file_id`
    """
    logging.info(f'Creating new permission {permission} for {file_id=}')
    try:
        request = service.permissions().create(
            fileId=file_id,
            body=asdict(permission),
            sendNotificationEmail=False,
        )
        response = request.execute()
        logging.info(f'New permission for {file_id=}: {response=}')
    except HttpError as error:
        logging.error(f'An error has occurred while trying to grant {permission=} to {file_id=}')
        logging.error(f'Error was: {error}')

        if not skip_on_failure:
            raise error

现在,让我们编写我们的main()方法,将所有部分整合在一起,最终与目标用户共享感兴趣的 Google Sheets。

def main():
    google_sheet_ids = [
        'abc-1234',
        'def-5678',
        'ghi-9123',
    ]

    service = create_service()
    permission = Permission(type='user', role='writer', emailAddress='example@example.com')

    for file_id in google_sheet_ids:
        create_permission(service=service, permission=permission, file_id=file_id)

完整代码

这里有一个完全修订的代码版本,你可以用来指定新的

import logging
from dataclasses import asdict, dataclass
from typing import Optional

from googleapiclient.discovery import build, Resource
from googleapiclient.errors import HttpError
import google.auth

logging.basicConfig(
    format='[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s',
    level=logging.INFO,
)

def create_service() -> Resource:
    """
    Creates a Google Drive (v3) service to interact with the API
    """
    scopes = [
        'https://www.googleapis.com/auth/spreadsheets',
        'https://www.googleapis.com/auth/drive',
    ]

    creds, project_id = google.auth.default(scopes=scopes)
    service = build('drive', 'v3', credentials=creds, cache_discovery=False)

    return service

def create_permission(
    service: Resource,
    permission: Permission,
    file_id: str,
    skip_on_failure: Optional[bool] = True,
):
    """
    Creates a new `permission` for the specified `file_id`
    """
    logging.info(f'Creating new permission {permission} for {file_id=}')
    try:
        request = service.permissions().create(
            fileId=file_id,
            body=asdict(permission),
            sendNotificationEmail=False,
        )
        response = request.execute()
        logging.info(f'New permission for {file_id=}: {response=}')
    except HttpError as error:
        logging.error(f'An error has occurred while trying to grant {permission=} to {file_id=}')
        logging.error(f'Error was: {error}')

        if not skip_on_failure:
            raise error

def main():
    google_sheet_ids = [
        'abc-1234',
        'def-5678',
        'ghi-9123',
    ]

    service = create_service()
    permission = Permission(type='user', role='writer', emailAddress='example@example.com')

    for file_id in google_sheet_ids:
        create_permission(service=service, permission=permission, file_id=file_id)

if __name__ == '__main__':
    main()

最终思考

授予用户对单个 Google Sheet 的访问权限是一个简单的任务,可以通过用户界面完成。只需点击电子表格右上角的‘分享’,输入用户的电子邮件地址,并选择他们的角色即可。然而,当涉及到为数百个电子表格或用户共享权限时,这一过程可能变得耗时且繁琐。

在本教程中,我们演示了如何使用 Google Drive API 和 Python Google API 客户端以编程方式为多个 Google Sheets 分配权限。我希望你觉得这篇文章有用。如果你在运行特定用例的代码片段时遇到任何困难,请在下面的评论中告诉我,我将尽力帮助你。

👉 成为会员 并阅读 Medium 上的每一个故事。你的会员费用直接支持我和你阅读的其他作者。你还将完全访问 Medium 上的每个故事。

[## 使用我的推荐链接加入 Medium — Giorgos Myrianthous

作为 Medium 会员,你的会员费用的一部分将支付给你阅读的作者,你可以完全访问每一个故事…

gmyrianthous.medium.com](https://gmyrianthous.medium.com/membership?source=post_page-----fee1ff80363--------------------------------)

👇相关的文章你也可能喜欢 👇

## 什么是 dbt(数据构建工具)

轻松介绍 dbt,它正在主宰数据领域

towardsdatascience.com ## ETL 与 ELT:有什么区别?

在数据工程背景下对 ETL 和 ELT 的比较

towardsdatascience.com ## setup.py 与 setup.cfg 在 Python 中的区别

使用 setuptools 管理依赖项并分发你的 Python 包

towardsdatascience.com

谷歌对多模态基础模型的最新方法

原文:towardsdatascience.com/googles-latest-approaches-to-multimodal-foundational-model-beedaced32f9

多模态基础模型比大型语言模型更令人兴奋。让我们回顾谷歌研究的最新进展,以窥见前沿技术。

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

·发表于 Towards Data Science ·7 min read·2023 年 8 月 12 日

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

图片来源:unsplash.com/photos/U3sOwViXhkY

背景

虽然大型语言模型(LLM)的炒作在业界依旧火热,但领先的研究机构已经将目光转向多模态基础模型——这些模型具有与 LLM 相同的规模和多功能特性,但可以处理文本之外的数据,如图像、音频、传感器信号等。许多人认为,多模态基础模型是解锁人工智能(AI)下一阶段进步的关键。

在这篇博客文章中,我们将更详细地了解谷歌如何处理多模态基础模型。本文的内容基于谷歌最近论文中的关键方法和见解,我们在文章末尾提供了相关参考。

你为什么应该关心

多模态基础模型令人兴奋,但你为什么应该关心?你可能是:

  • 一位希望跟上该领域最新研究进展的 AI/ML 从业者,但又没有耐心阅读几十篇新论文和数百页的综述。

  • 一位当前或即将成为行业领导者的人,想知道大型语言模型之后会发生什么,并考虑如何将你的业务与科技界的新趋势对齐。

  • 一位好奇的读者,可能会成为当前或未来多模态 AI 产品的消费者,并希望对幕后工作的原理有一个直观的了解。

对于以上所有读者,本文将提供一个很好的概述,帮助你启动对多模态基础模型的理解,这是未来更易于访问和有用的 AI 的基石。

在我们深入探讨之前还有一点需要注意:当人们谈论多模态基础模型时,他们通常指的是输入是多模态的,包括文本、图像、视频、信号等。然而,输出总是只是文本。原因在于文本是最通用的沟通格式。如果我们能输出文本,就能输出代码并将其输入到下游工具中,以生成所需的多媒体格式。更不用说现在有很多 AI 工具可以将自然语言作为输入,生成图像和声音。

从文本开始

首先需要包含的格式是文本,或者用研究术语来说,是语言。研究人员喜欢称之为语言,因为语言意味着文本来源于具有连贯语义意义的语言系统,无论是任何自然语言、代码、命令、符号等等。通俗来说,我们在这篇博客文章中就称之为文本。

关于构建大型语言模型的材料在线上有很多,所以我们在这里不会深入讨论。只需注意,谷歌最近在 LLMs 和多模态基础模型上的结果都是建立在 PaLM [1]之上的。如果你不熟悉它,可以将其视为类似于 ChatGPT 的黑箱,尽管它们的内部机制差异很大。

这里需要掌握的基本概念是,输入文本被分解为标记。每个标记随后被映射到一个嵌入空间中。实际上,每个标记变成了一个向量。然后,这些向量的列表被输入到由注意力机制网络层组成的模型中。模型的输出也是一个向量列表,可以被转换回标记,然后拼接形成最终的文本输出。

该模型拥有数百亿个参数,并在大量的文本数据上进行训练,执行一些简单的预测任务,例如给定一个文本前缀,预测下一个标记。

生成的模型将需要经过进一步的微调才能变得更直接有用。例如,谷歌已经将其 PaLM 模型应用于医学领域,并创建了 MedPaLM [2]。你可以参考这篇文章以获取更多关于如何将大型语言模型适应到特定领域的见解。

到目前为止,我们拥有一个大型语言模型。下一步是融入其他媒体格式。

融入图像

为了融合图像,首先要做的是将图像转换为可以被大语言模型处理的格式。因为我们已经有了大语言模型,并且希望多模态信息能够被统一处理,自然的选择是将图像转换为嵌入向量列表。回想一下,文本也被转换成了上述的嵌入向量列表。显然,图像和文本的向量应具有相同的维度。

谷歌在采用 Transformer 架构进行图像处理方面做了令人印象深刻的工作[3][4]。这被证明非常适合图像到向量的转换。

具体来说,每张图像被调整为 224×224 的分辨率,然后被拆分成 14×14 像素的片段。这会产生 224×224/14/14=256 个片段。每个片段经过相同的可学习线性变换以转换为向量。每个向量与一个可学习的位置嵌入进行拼接。这些拼接的向量然后输入到 Transformer 模型[5]中。谷歌研究将这一模型架构称为 ViT——视觉 Transformer。ViT 模型的输出也是 256 个向量。然后,将一个浅层网络附加到 ViT 模型的输出向量上,并对整个架构进行训练,以进行图像分类、图像描述和其他图像处理任务。有关示意图,请参见图-1。

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

图-1:ViT 架构的示意图。图片来自作者。

一旦完成图像处理训练,丢弃顶部的浅层网络,我们可以使用 ViT 的 256 个输出向量作为图像的嵌入表示。核心思想是,通过大规模训练,ViT 模型已经学会用一系列向量表示输入图像,这些向量可以轻松用作各种图像处理任务的输入特征。

这里有一个特别的说明,即谷歌研究发现 ViT 在图像处理上的结果优于最先进的 CNN。他们将这一优越性能归因于规模(基于 Transformer 的架构被认为有更好的扩展性)以及注意力机制可以在网络早期直接作用于任何两个输入片段的事实。

在 ViT 中完成的图像表示学习可以转移到多模态环境中,正如你所猜到的那样。来自预训练 ViT 的输出向量可以作为大语言模型的输入。

对于输入提示如what happened between <imgA> and <imgB>,词语按惯例转换为大语言模型的嵌入向量;每张图像通过 ViT 转换为 256 个向量。所有向量一起形成大语言模型的输入。最后,大语言模型在多模态训练数据上进行端到端微调(或冻结其各个部分),最终得到的模型就是多模态基础模型。有关示意图,请参见图-2。

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

图-2: 多模态基础模型架构的示意图。图片来自作者。

显然,上述维度数字只是谷歌研究论文使用的其中一种配置[6]。如果你愿意,可以尝试自己的配置。但要注意,ViT 输出向量的维度应与较大的语言模型输入向量的维度匹配。如果不同,你可以调整任一模型,或者在 ViT 输出和大型语言模型输入之间插入一个线性变换,以压缩或扩展 ViT 输出以匹配大型语言模型的输入维度。

扩展到其他媒体和领域

既然我们知道了如何整合图像,我们可以采用类似的方案来包含其他媒体类型。它们不一定要使用 Transformer 架构。谷歌研究在机器人领域[7]中使用了多模态基础模型,通过将状态、场景中的对象和其他输入源转换为相同的向量嵌入空间来实现。这些输入格式中的许多实际上是通过非常简单的变换转换到嵌入空间的。谷歌研究最近还将这一方法适应于医疗领域,并创建了一个用于医疗保健的多模态基础模型[8]。有关它们的用途,请参见图-3。

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

图-3: 多模态基础模型在 (a) 机器人技术和 (b) 医疗领域的应用示例。图片来源于参考文献[7]和[8]

结论

在这篇博客文章中,我们窥见了多模态基础模型领域的前沿。核心思想有两个方面:(1)将多媒体编码到相同的嵌入空间,以便可以由 LLM 架构统一处理;(2)将大型预训练模型(它们通常在单模态设置中预训练)结合在一起,并使用多媒体训练数据进行微调。

谷歌研究最近的一些突破确实开始接近人们希望并可以在日常生活中使用的 AI 代理。虽然还有很长的路要走才能让 AI 更加易用和有帮助,但毫无疑问,多模态基础模型是 AI 的拐点,未来的发展将会更加激动人心。

参考文献

[1] PaLM: 使用路径扩展语言建模 arxiv.org/abs/2204.02311

[2] 大型语言模型编码临床知识 arxiv.org/abs/2212.13138

[3] 一张图胜过 16x16 个词:用于大规模图像识别的 Transformer arxiv.org/abs/2010.11929

[4] 扩展视觉 Transformer arxiv.org/abs/2106.04560

[5] 注意力机制是你所需要的一切 arxiv.org/abs/1706.03762

[6] PaLI: 联合缩放的多语言语言-图像模型 arxiv.org/abs/2209.06794

[7] PaLM-E:一种具身的多模态语言模型 arxiv.org/abs/2303.03378

[8] 朝向通用生物医学人工智能 arxiv.org/abs/2307.14334

Google 的 MusicLM:从文本描述到音乐

原文:towardsdatascience.com/googles-musiclm-from-text-description-to-music-23794ab6955c

一个新模型仅凭文本提示就能生成令人印象深刻的音乐

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

·发表于 Towards Data Science ·阅读时间 8 分钟·2023 年 2 月 1 日

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

图片由作者使用 OpenAI DALL-E 生成

Google 发布了一种新模型,能够从 文本描述生成音乐。结果?令人印象深刻。

实际上,将生成性人工智能应用于音乐并不是一个新概念。 近年来已经有几个尝试,包括 Riffusion、Dance Diffusion、微软的 Museformer 和 OpenAI 的 Jukebox。Google 自身之前发布过一个名为 AudioML 的模型。为什么这个模型会有所不同?

[## Microsoft 的 Museformer:人工智能音乐是新前沿

人工智能艺术正在蓬勃发展,音乐可能是下一个。

medium.com

为什么用人工智能生成音乐如此困难?

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

图片由 Marius Masalar 在 unsplash.com 提供

与此同时,之前的模型显示出明显的技术和质量问题。结果陈旧,歌曲复杂度不高,常常重复,并且音质依然不高。

生成音乐并不容易,正如众多尝试所示。 作者们常使用 MIDI,但生成高保真音乐是另一回事。音乐还有复杂的结构,你必须考虑旋律和和声,并且有重复的模式,这些模式在时间上和距离上都会重复。

正如文章的作者指出的那样,生成文本到图像相对容易,而文本到音乐的尝试仅限于:“由几个声音事件组成的简单声学场景,持续几秒钟。”

在这里,我们谈论的是从单一文本说明开始,并生成具有长期结构的复杂音频。他们是如何实现这一点的?

[## 谷歌的 AudioLM:通过听歌曲片段生成音乐

无论是音乐还是语音,谷歌的新模型都能继续播放所听到的内容。

pub.towardsai.net

同时,正如他们所解释的,AudioLM 被用作起点。之前的模型能够将旋律继续下去,并且保持一致性。然而,仍然有几个技术限制需要克服

  • 这种模型的第一个主要限制是“音频-文本配对数据的稀缺”。事实上,文本到图像的训练得以实现是因为有大量的图像,且可以使用替代文本作为说明。

  • 用几句话描述音乐的显著特征,如声学场景或旋律的音色,并不容易。

  • 此外,音乐在时间维度上展开,因此有可能出现说明和音乐之间的链接较弱的风险(与静态图像相比)。

MusicLM:结构、训练、结果和限制

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

图片来源:James Stamler 于 unsplash.com

这个模型的第一个组件是 MuLan(也是核心部分)。这个模型用于构建音乐-文本联合嵌入,由两个嵌入塔组成(一个用于文本输入,一个用于音乐输入)。这两个塔是预训练的 BERTResNeT-50 的变体,用于音频。

MuLan 在音乐片段及其相应的文本注释对上进行训练。

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

MusicLM 的三个组件已分别进行预训练。其他两个组件如下文所述。图片来源:这里

正如我们在图像中看到的那样,作者提到还有两个其他组件。正如作者解释的:

我们使用 SoundStream 的自监督音频表示作为声学标记,以实现高保真合成,并使用 w2vBERT 作为语义标记,以促进长期一致的生成。在条件表示方面,我们在训练期间依赖 MuLan 音乐嵌入,在推断时依赖 MuLan 文本嵌入。

尽管这个系统看起来很复杂,但它有几个优点:它可以快速扩展,并且使用对比损失进行嵌入训练可以提高鲁棒性。此外,单独拥有预训练模型可以更好地处理带有文本输入的音乐

在训练期间,模型学习将 MuLan 生成的标记映射转换为语义标记(w2w-BERT)。然后,声学标记在 MuLan 音频标记和语义标记(SoundStream)的条件下进行处理。

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

训练期间的模型。图片来源:这里

在推断期间,过程是将文本描述提供给 MuLan,MuLan 将其转换为条件信号,接着 w2w-BERT 将其转换为音频标记,然后由 SoundStream 解码器将其转换为波形。

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

推断期间的模型。图片来源:这里

使 MusicLM 如此强大的原因之一是它在 500 万条音频剪辑上进行了训练(总共 280,000 小时的音频)。此外,作者还创建了一个包含 5500 个由专业音乐家编写字幕的音乐剪辑的数据集(该数据集已发布这里)。每个字幕描述了音乐的四句话,并附有音乐方面的列表(如流派、情绪、节奏等)。

正如结果所示,MusicML 在音频质量和文本一致性方面都优于之前的模型(Mubert 和Riffusion)。而且在听觉质量方面也是如此。实际上,听众被展示了剪辑并被要求选择哪个剪辑最能代表文本描述(胜利意味着听众在对比中更喜欢该模型)。

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

“使用来自 MusicCaps 数据集的字幕对生成样本进行评估。通过 Frechet 音频距离(FAD)比较音频质量,使用 Kullback–Leibler 散度(KLD)和 MuLan 循环一致性(MCC)以及人类听力测试中的胜利次数(Wins)来比较与文本描述的一致性。” 图片来源:这里

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

人类听众研究的用户界面。图片来源:这里

听到结果时,难免令人印象深刻,考虑到模型中没有音乐家参与。毕竟,该模型能够捕捉到音乐细节,如乐器即兴演奏和旋律。

此外,该模型不仅限于文本描述,还可以以其他音频作为输入并继续处理(“可以以哼唱、歌唱、吹口哨或演奏乐器的形式提供”)。

作者还描述了一种称为“故事模式”的方法,即生成长音频序列,其中文本描述随着时间的推移而变化。该模型生成具有“平滑过渡、节奏一致且语义合理的音乐序列,同时根据文本描述改变音乐背景”的音乐序列。这些描述还可以包含“冥想时间”或“跑步时间”的描述,从而创建一个将适当音乐与之关联的叙事。

简而言之,该模型并不仅限于对某一乐器或音乐流派的描述,还可以根据活动、时代、地点或情绪的描述进行调整。因此,MusicLM 也可以用于电影配乐、锻炼应用等。

在此链接中,你还可以阅读字幕并听到模型的结果。

[## MusicLM

Andrea Agostinelli, Timo I. Denk, Zalán Borsos, Jesse Engel, Mauro Verzetti, Antoine Caillon, Qingqing Huang, Aren…

google-research.github.io

尽管模型令人印象深刻,但并不完美,一些音频片段的质量存在失真(但未来可能通过训练调整得到改善)。此外,该模型还可以生成合唱和人声,但歌词通常不是英语,而是一种无意义的语言,并且声音听起来更像是多位歌手的混合,而非连贯的人声。因此,作者如是说:

未来的工作可能会集中在歌词生成上,同时改进文本条件和声音质量。另一个方面是建模高级的歌曲结构,如引言、诗句和副歌。以更高的采样率建模音乐是一个额外的目标。

Google 决定不分发该模型:“我们的模型及其处理的用例存在一些风险。”正如作者所指出的,该模型反映了训练数据中存在的偏见,这在为数据集中代表性不足的文化生成音乐时会带来问题。他们还指出,该模型提出了关于文化挪用的伦理问题。

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

“MusicCaps 中所有 5.5k 示例的流派分布,基于 AudioSet 分类器”。图片来源:这里

另一个问题是,在 1%的情况下,模型生成了在训练期间听到的音乐,复制了现有歌曲的部分(甚至是受版权保护的元素)。TechCrunch 认为这足以劝阻谷歌发布模型(尤其是在机构有意规范人工智能和生成工具的情况下)。

他们认识到与使用案例相关的创意内容潜在的误用风险,并进一步强调了深入研究和分析的必要性,得出结论:

我们强烈强调需要更多的未来工作来应对与音乐生成相关的这些风险——目前我们没有发布模型的计划。

## 欧盟想要规范你最喜欢的人工智能工具

欧盟正在准备一项新的人工智能法案,生成式人工智能也被包含在内。

medium.com

结论

MusicLM 在从文本描述生成音乐方面表现出色,相较于之前的模型是一个质的飞跃。它生成连贯的音乐,长序列能够捕捉音乐的细微差别。尽管它已经用大量数据进行了训练,但仍然不完美。

同样,正如作者所描述的,由于模型生成了受版权保护的音乐,他们没有计划发布它。这可能也源于一些程序员最近起诉了 GitHub CopilotGetty images 起诉了 Stability AI以及 MidJourney。

此外,正如作者所指出的,生成音乐模型正在从训练集中引入偏见。MusicLM 不仅生成器乐音乐,还可以生成声乐和合唱,这可能导致生成的音乐中包含偏见和有害内容。

此外,正如多位音乐家所指出的,流媒体已经稀薄了音乐家和作曲家的收入,而生成式人工智能可能进一步减少他们的收入

相反,作者建议这些模型将不会取代音乐家和作曲家,而是很快成为辅助人类的一组工具。

如果你觉得有趣:

你可以查找我的其他文章,你也可以订阅以在我发布新文章时收到通知,还可以在LinkedIn上联系我。感谢你的支持!

这是我 GitHub 代码库的链接,我计划在这里收集与机器学习、人工智能等相关的代码和资源。

GitHub - SalvatoreRa/tutorial: Tutorials on machine learning, artificial intelligence, data science…

包含数学解释和可重用代码(Python)的机器学习、人工智能、数据科学教程……

GitHub - SalvatoreRa/tutorial: Tutorials on machine learning, artificial intelligence, data science…

GPT-3.5 更擅长翻译段落

原文:towardsdatascience.com/gpt-3-5-translates-paragraphs-better-5ed0031ece08

并且在翻译文学作品方面优于 Google 翻译

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

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

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

图片来源于 Pixabay

根据 以往研究,GPT 模型的表现与标准机器翻译系统相当,例如 Google 翻译。

这些研究主要集中在句子级翻译:机器翻译中默认的做法是逐句翻译,没有任何上下文。

翻译段落或整个文档对于标准机器翻译系统来说是非常困难的挑战。这些系统通常需要拆分输入或进行大量工程改造以接受和利用更长的输入。

然而,从直观上看,并遵循人工翻译者的工作流程,我们可以期待机器翻译系统在处理上下文时表现更好,例如翻译整个文档或段落。

这就是大型语言模型如 GPT 模型可以大放异彩的地方。它们可以接受比典型机器翻译系统显著更长的提示词输入。

但仍需评估以下内容:

  1. 利用更多上下文是否有助于提高 GPT 的机器翻译质量。

  2. GPT 模型在翻译长文本时的表现,与标准机器翻译系统相比。

对于翻译段落的大型语言模型的评估面临几个挑战。

  1. 用于机器翻译评估的自动化指标并未设计用于段落级评估。

  2. 评估数据在被评估系统训练期间不得出现过。

  3. 评估应在多样的语言对上进行,以准确了解大型语言模型的翻译质量。

  4. 提示词必须设计成利用整个段落,即不仅仅是像以往工作中那样的句子。

这些挑战都由Karpinska 和 Iyyer (2023) 的“大型语言模型有效利用文档级上下文进行文学翻译,但仍存在关键错误解决。

在这篇博客文章中,我回顾并评论了他们的工作。我们将看到他们对 GPT-3.5 的评估如何表明“在提供段落级上下文时,LLMs 产生更好的翻译”,并且对于非常多样化的语言对,其翻译质量优于最先进的神经机器翻译系统。

段落翻译的人工评估

在机器翻译中常用的自动化评估指标是不适用的。在评估段落级翻译时,它们与人工判断的相关性尚不明确。

我们不能依赖自动化指标。

人工评估仍然是具有高可信度评估的主要选择,因此该研究的作者主要依赖于 MQM 框架(Lommel et al., 2014):

  • 标记翻译错误的范围并对其进行分类

  • 做出两种翻译中哪一种质量更高的偏好判断

  • 提供自由形式的偏好判断理由。

在此次评估中,他们收集了总共 720 对翻译段落,涵盖了 18 种语言对。

数据量真是惊人!我迫不及待想看看数据集。它将发布在 GitHub 上,这里

文学作品的机器翻译

在评估中,这项工作选择专注于翻译文学作品。由于大多数以前的机器翻译工作集中在其他体裁/领域(新闻、用户生成文本等),因此这可能看起来是一个奇怪的选择。

文学文本的机器翻译研究不足且极具挑战性,特别是对于以句子级别工作的大型机器翻译系统。

在这种类型的文本中,上下文的细微差别非常重要,但如果系统独立翻译句子,就无法捕捉这些细微差别。通常,人工翻译者必须重组整个段落,以准确翻译成目标语言。

文学文本的翻译直观上是一个任务,其中系统以文档或段落作为输入会比仅接受较短输入的系统表现更好。

但在评估大型语言模型时,我们面临的一个主要限制是评估使用的数据必须是最新的。这对评估的可信度很重要。通过使用最近发布的数据进行评估,我们可以避免翻译可能用于训练评估模型的文本,即避免数据污染。

## GPT-4 的去污染评估

GPT-4 很快不会成为你的律师

[towardsdatascience.com

在这项工作中,用于评估的大部分翻译都是在 2021 年后发布的。这些特定的翻译很可能不在 GPT-3.5 的训练数据中,因为 GPT-3.5 是基于 2022 年之前发布的数据进行训练的,依据 OpenAI 的说法。

然而,被翻译的原文要老得多(出版时间从 1884 年到 2020 年)。这些原文很可能已被在这项工作中评估的系统(GPT-3.5 和 Google Translate)见过。

此外,尽管被评估的系统不太可能见过这些特定的翻译,但它们可能见过其他语言中的翻译,或者同一语言中但较早发布的翻译。

数据污染有限但仍然存在。我认为完全防止文学文本的数据污染没有更好的办法。但对于新闻等其他类型的文本,这是可能的。

一个非常多样的语言对集合

这是这项工作的一个强项:作者评估了非常多样的语言对。

作为源语言,他们选择了来自不同语言家族的语言:印欧语系(罗曼语族、日耳曼语族、斯拉夫语族)、汉藏语系和日琉语系。通过这种方式,他们确保评估能够更准确地识别 GPT-3.5 在翻译具有不同形态特征和书写系统的语言方面的优缺点。

用于评估的翻译语言包括英语(en)、波兰语(pl)、俄语(ru)、捷克语(cs)、法语(fr)、德语(de)、日语(ja)和中文(zh)。

对于目标语言,他们选择了创建“简单”(相似语言)和“困难”(不相似语言)源目标语言对的语言。

例如,捷克语-波兰语是一个简单的语言对,因为这两种语言有很多共同点。另一方面,日语-波兰语是一个极其困难的语言对,因为这两种语言来自非常不同的语言家族,具有不同的语法和书写系统。对这个语言对的机器翻译研究也非常有限。

每种源语言的选定目标语言是英语(en)、日语(ja)和波兰语(pl)。

使用 GPT-3.5 进行翻译的提示工程

评估大型语言模型时最关键的步骤之一是设计提示。

机器翻译有许多可能的提示。理想情况下,我们应该广泛评估几个提示,以评估提示选择的影响程度。

我们还必须记住,科学工作得出的结论可能仅对我们评估的非常特定的提示有效。

在评估中包括许多提示是昂贵的,因为我们必须对每个提示运行大型语言模型的推理。实际上,这意味着我们只能选择有限数量的提示进行评估。

他们使用了 5-shot 上下文学习来翻译 GPT-3.5. 提示中有 5 个翻译示例,更精确地指明了对 GPT-3.5 的期望。

选定的翻译示例对语言模型的翻译质量有着至关重要的影响。正如 Vilar et al. (2022) 所证明的,示例的翻译质量才是最重要的。

关于示例选择,他们写道:

我们从文学文本中手动策划了每对 18 种语言中的五个示例,共计 90 个示例。这些示例来自于不在我们翻译数据集中的小说,因此可能存在主题和风格上的差异 […]

这不是很详细。特别是,我不清楚“策划”涉及什么。策划标准没有提供。

一旦选择,它们包括了三种提示中的例子,这些例子利用了不同大小的上下文。

句子级提示模板

使用这个模板,待翻译的段落句子会一个接一个地提供给 GPT。这是标准的序列到序列神经机器翻译系统的工作方式。

原文在 [SRC LANG] 中:

源句子

翻译到 [TRG LANG]:

目标句子

注意:[SRC LANG]和[TRG LANG]分别表示源语言和目标语言。

带上下文提示模板的句子级翻译

翻译仍然是在句子级别进行,但句子是带有上下文的提供给 GPT-3.5 的:段落中句子之前和之后的内容都包含在提示中。

原文在 [SRC LANG] 中:

源前缀

src sent

源后缀

翻译到 [TRG LANG]:

目标前缀

trg sent

我发现这个设计非常有创意,但也很冒险。根据我的经验,如果我们没有明确地定义标签,GPT 模型可能会很容易混淆。在这种情况下,如果 GPT 只是翻译所有内容,包括标签( 和 ),我也不会感到惊讶。

段落级提示模板

模板与第一个相同,但这里提供的是整段文本而非句子。

原文在 [SRC LANG] 中:

源段落

翻译到 [TRG LANG]:

目标段落

现在我们有了提示,我们可以用它们来评估 GPT-3.5 的翻译质量。

对 GPT-3.5 段落翻译的评估

这次评估主要旨在回答两个问题:

  • 像 GPT-3.5 这样的语言模型在翻译整段文本时是否比翻译单句时表现更好?

  • 与 Google 翻译相比,GPT-3.5 在翻译整段文本时表现如何?

对于这次评估,作者主要依靠使用 MQM 框架的人类评估。

如果你对我的工作很熟悉,你已经知道我在写机器翻译评估时有多么苛刻。

## 机器翻译研究中的科学可信度:陷阱与有希望的趋势

我们是否处于一个转折点?我从对 1000 多篇科学论文的注释中得出的结论。

[towardsdatascience.com

对于这项工作,作者以非常高的科学可信度评估了他们的机器翻译系统。如果你在寻找一个优秀的机器翻译评估的例子,这就是其中之一。注意:我还推荐阅读“Prompting PaLM for Translation: Assessing Strategies and Performance”(Vilar 等,2022 年),这是另一个好的例子,就像我在博客文章“How Good Is Google PaLM at Translation?”中详细介绍的那样。

他们没有依赖自动化指标,但仍然提供了更多分析的指标分数。所有复现这些分数的细节也一并提供。这非常罕见。

他们甚至测试了他们人工评估的统计显著性。

结果:

  • GPT-3.5 在翻译段落时比翻译单个句子要好。

  • GPT-3.5 优于 Google Translate。

但这些结果在语言对之间有所不同。

对于德语到日语的翻译方向,翻译单个句子的结果更好。这是唯一的例外。根据作者的说法,这是因为用于这个翻译方向的数据有非常长的句子。

令我最惊讶的是,GPT-3.5 在翻译单个句子时也优于 Google Translate。

自动化指标也产生了非常相似的结果:COMET、BLEURT、BERTScore 和 COMET-QE 都一致认为 GPT-3.5 在任何 3 种提示模板下都优于 Google Translate。

论文展示了对其人工评估的非常详细的分析。我不会在本文中进一步讨论,但邀请你阅读。这非常有洞察力。

GPT 模型在翻译中的局限性。

论文中有一个“局限性”部分(第七部分),作者在这里讨论了使用 GPT 模型进行翻译的局限性。

作者指出,翻译段落时出现的翻译错误与翻译单个句子时的错误不同。

在翻译段落时,GPT-3.5 有时会跳过和忘记段落的一部分内容,导致翻译不正确。我在使用ChatGPT 进行翻译时也观察到了类似的行为。

这个问题可以通过对 GPT-3.5 进行机器翻译的微调来纠正。注意:不要忘记,这里评估的 GPT-3.5 模型尚未针对机器翻译进行微调。

除此之外,GPT-3.5 仍然会出现一些较为常见的错误,例如翻译错误和语法错误,但这些错误远少于谷歌翻译,评估结果表明了这一点。

这项工作的局限性

我努力寻找这项工作的局限性,但在我看来至少有一个。

提示模板的影响尚不清楚。用于段落翻译的具体模板比用于句子翻译的模板表现更好。

但我们是否可以在这种设置下得出结论,即 GPT-3.5 在翻译整段文本时表现更好?

如果我们更改模板,我们是否仍会得出相同的结论?

我们无法轻易回答这个问题。我预计这一局限性将会在所有未来评估语言模型的机器翻译研究中出现。

此外,这项工作专注于翻译文学文本。我们不能确定这项工作的结论是否适用于其他类型的文本。我期待阅读未来将填补这一空白的研究。

结论

这项工作是机器翻译领域的一个里程碑。

这表明,一个大型语言模型可以超越更标准的神经机器翻译系统,如谷歌翻译,具有非常高的科学可信度。同时,它还表明,大型语言模型在段落级别翻译中能提供比句子级别翻译更好的翻译质量。

通过这项工作和之前的 PaLM 翻译质量研究,我们有越来越多的证据表明,机器翻译的未来将基于大型语言模型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值