《开放的 GPT 2》为《权力的游戏》写了不同的结局
我在 GRRM 的书系列*《冰与火之歌》*上训练了 GPT-2 语言模型,并让它完成了 HBO 节目的故事情节。它能比 HBO 的第八季《火车残骸》更好吗?
Game of Thrones season 8 storyline has left its fandom divided with millions of fans disappointed by its rushed and unsatisfactory ending. Disclaimer: Opinions expressed in this article are solely my own.
《权力的游戏》第八季的故事情节让粉丝们产生分歧,数百万粉丝(包括我自己)对其仓促且不尽如人意的结局感到失望。许多人呼吁重写这部电视剧的最后一季,而其他人则提出了他们自己版本的结局,以获得一个满意的结局。其他人正在等待 GRRM 完成他的书,希望他能为人物的不可信行为提供一个更令人信服的构建,但这可能需要很多年。因此,我想让一个人工智能学习 GRRM 的写作风格,并让它完成节目的结尾。
在这篇文章中,我将解释我们如何通过使用名为 GPT-2 的文本生成语言模型来实现这一点,该模型由 Open AI 的研究人员在 2019 年初推出。然后,我将分享这一季三个主要反派的故事情节的模型预测结果:夜王、瑟曦·兰尼斯特和丹妮莉丝·坦格利安。
生成式预训练变压器 2 (GPT-2)
GPT-2 是目前人工智能语言建模中最先进的文本生成模型。它能够产生类似人类的连贯句子,并且能够长时间专注于一个主题。与其他语言模型相比,它令人印象深刻的改进归功于这项研究的两个主要贡献
- **大量数据:**搜集并整理了 800 万个网页,形成了一个 40GB 的文本语料库,可以对其进行无监督训练。它涵盖了各种各样的主题,这就是为什么预训练模型非常适合将学习转移到特定领域,就像我们的 GoT 书籍一样。
- **大量计算:**它使用 15 亿(!!)在其基于变压器的网络架构中的参数。然而,他们只发布了这个模型的一个较小版本,包含“仅”3.45 亿个参数,引用了安全原因。我们将使用这个版本的预训练模型来执行 GoT 脚本的迁移学习。
变压器模型
GPT-2 使用变压器网络架构,而不是通常用于序列建模的传统 RNN/LSTM/GRU 网络。Transformer 使用基于注意力的机制和一对编码器/解码器,而不是带有“记忆”门和时间步长的循环单元。
编码器在字节对和位置嵌入的帮助下处理输入,字节对和位置嵌入描述输入句子中单词的“是什么”和“在哪里”(嵌入)。同一个编码器将字节和位置嵌入转换为矢量编码,然后进入解码器,解码器的任务是将编码转换为目标文本序列。该输出和来自前一步骤的编码被馈送到下一编码-解码步骤,并且被重复多次以产生进一步的文本。这里有一篇优秀的文章详细解释了这个模型架构。
Overview of a general attention-based Transformer model. [source: Attention Is All You Need’ by Vaswani et al.]
请注意,GPT-2 被训练为预测给定输入句子中的下一个单词,其假设是,为了相当准确地预测下一个单词,模型将被迫学习到目前为止它遇到的所有单词的上下文含义。如果不理解文本,语言模型可能只能预测语法正确的单词,但生成的文本不会完全有意义。因此,这种使网络预测足够好的下一个单词的公式,GPT-2 能够获得对输入文本的深刻理解。这里是伊利亚·苏茨基弗对这个概念的一个很好的解释。
GPT-2 在文本生成期间不需要编码器,因为它不是像语言翻译那样的 seq2seq 转换任务。所以一旦训练结束,编码器就不再需要了。GPT-2 仅使用来自预训练转换器的解码器来生成后续文本。
训练模特
我从乔治·R·R·马丁的书系列*“冰与火之歌”*的所有 5 本书中提取了文本,并将它们连接起来准备训练文本。使用具有 345M 参数的预训练的 GPT-2 模型对该文本执行迁移学习。
George R.R. Martin’s Book Series “A Song of Ice and Fire”.
令人惊讶的是,我注意到预先训练的模型也非常擅长写关于《权力的游戏》角色的内容,这意味着它在 800 万网页的初始训练中接触过这些内容。不管怎样,我决定缩小这个“一般化”模型的范围,只按照 GRRM 的风格编写,所以继续在我们的 GoT 数据集上进行训练。该模型在 Google Colab 的 K80 GPU 上训练了大约 12 个小时。
结果
让我们尝试解决一些令人失望的结局或故事情节的转折,并尝试使用我们训练有素的 GPT-2 模型预测这些场景的替代结局。
下面是视频格式的结果,后面是文本格式的结果。选择自己的冒险。
失望 1:夜王虎头蛇尾的结局
**输入:**夜王慢慢走到三眼乌鸦面前。琼恩被冰龙挡住,丹妮莉丝被怀特一家团团围住。夜王伸出他的冰剑想要杀死布兰,但突然
**输出:**阿多阻止了他,他仍然用他的大手抓着冰原狼。“阿多!”乌鸦叫道。“阿多!阿多!”黑魔王脸上带着失落的表情。他用树桩刺穿布兰的背部,开始搏斗、翻滚、旋转。怀特,巨人,半身人,稻草人。布兰与夏莫、老鹰、笨狗和陌生人并肩作战,但光之王绝不会以剑挡剑。乌鸦在说,只是爬上阿多的厚雪白的腿。
据 GPT 2 号说,阿多还活着,他来营救布兰,真是个意外!或者它可能是被布兰注入的阿多的不死之身。但是之后我就不知道模特想说什么了,哈哈!
**输入:**夜王慢慢走向三眼乌鸦。琼恩被冰龙托起,丹妮莉丝被狼人包围。夜王伸出他的冰剑想要杀死布兰,但突然意想不到的事情发生了。
**输出:**剑发出炽热的红光。当剑刃击中夜之眼时,它周围的绿色玻璃裂开了,光溶解了,剑像死冰一样发光。然后乌鸦开始尖叫,远处的猫头鹰在龙的左边和右边,有东西正在还击,撞开门,杀死所有长着娃娃脸的傻瓜。我猜 Osha 在给 Rickon 演示如何装弹。也许战斗结束后,他们都会是很好的倾诉对象。
尽管节目主持人忘记了,GPT-2 记得亚梭尔·亚亥的预言,并围绕着杀死夜王的剑光明使者的想法起舞。如果夜王的冰剑最终被证明是光明使者并杀死他,那该有多酷啊?!
输入:布兰说,“席恩,你是个好人。谢谢大家。”!席恩,带着他的救赎之弧,奔向夜王的死亡。就在他要用长矛刺穿夜王的时候,
**输出:**龙——还是另一个?——朝他的脸开了一枪,而夜王平静地看着。世界缩小到三个人,肩并肩站在一起;红色的牧师和他的长矛,国王穿着蓝色,他的皇冠在他的头上。一股寒风穿过冰冷的空气吹进席恩的脑袋,他也能听到他的兄弟们在喊叫。如果我不是那么坚强。。。杀了他,他想喊,但是勇气从他身上消失了,就像他身体的一部分被迫保持沉默。取而代之的是,他弯曲他残废的手臂,扔掉他的矛杆。他告诉自己,给自己留点伤,尽你所能跑吧。
这一篇让我大吃一惊,不是因为它写得很棒(其实不是),而是因为模型知道龙实际上是一个“他者”(这意味着书中的白行者)。它怎么会知道维塞隆是一条被夜王控制的不死龙呢?韦赛里翁向席恩喷火,折断了他的长矛。席恩,在这一刻,决定在恐惧中逃跑,就像他在这个节目中所做的一样。把所有这些细节都写在一段话里,这太巧合了。令人惊讶的是,模特已经知道了角色的这些细节!
失望 2: 瑟曦·兰尼斯特在没有任何计划和适当战斗的情况下被轻易击倒
**输入:**巨龙已经烧毁了整个兰尼斯特的军队,钢铁舰队和黄金军团,但是瑟曦依然坚信红堡不会陷落。当恶龙即将烧毁红堡的塔楼时,詹姆前来营救瑟曦。此时此刻,
他的心提到了嗓子眼,手掐着喉咙……他不知道如何呼吸……”艾莉亚颤抖着提利昂说兰尼斯特家有刀。"“他说他们有剑,”詹姆承认道。"詹姆杀托曼不是为了保住托曼的贞操,”艾莉亚说,把自己的故事告诉了身旁脸红的男孩提利昂·兰尼斯特。他的小弟弟只是咧嘴一笑。”不,我没有。"詹姆狠狠地瞪了她一眼。“很好。你撒谎。是的,你对那个吻撒了谎。你用嘴杀死了托曼,这既不是吻也不是承诺。只有一两把剑。你伤得很重,小家伙。不管怎样,只要那个脏男孩珍惜你给他的礼物,你姐姐就会把他留在她的床上。”
嗯,好吧,这个完全是垃圾。但我还是留着它,因为它太傻了,实际上很有趣。不管怎样,让我们再试一次!
**输入:**龙族已经烧毁了整个兰尼斯特军、铁血舰队和黄金连队的军队,但瑟曦依然坚信红堡不会陷落。当恶龙即将烧毁红堡的塔楼时,詹姆前来营救瑟曦。此时此刻,
**输出:**根据她的预言,疯王将进攻这座城市……“瑟曦,”詹姆又说了一遍,尽量让声音听起来严厉而遥远,“静静地,哦,甜蜜,哦,甜蜜。”他给特罗特写道:“瑟曦,记住,你是凯岩城的国王。记住你是谁,你是什么。还记得你是如何杀死疯王的吗?原谅我,如果我让你犹豫不决。”她没有回答。“原谅我,”他热情地重复道,“为了我从未有过的母亲,你从未有过的母亲,一个所有人都认识并爱着却不认识的母亲。”当刀刃入鞘时,鹰在油的波纹上闪着微光,天花板上的字闪闪发光,又亮又暗…
这次稍微好一点!虽然这个模型在某些细节上出错了,特别是关于疯王的,但我确实喜欢詹姆在那一刻试图给瑟曦力量的想法。也许在这个时候使用某种野火会给她的故事情节带来一些正义感。两个疯狂的女王,以火攻火,烧毁了城市的其余部分。这将是一个更好的结局,表明为什么争夺铁王座的战争是不好的。
失望 3: 丹妮莉丝不劳而获的脚后跟转弯
**输入:**丹妮莉丝在埃索斯和弥林拥有爱和恐惧。但在维斯特洛,她觉得自己只有恐惧。在她赢得铁王座之战的那一刻,她只能想着给她将要统治的人民灌输恐惧。丹妮莉丝在君临坐在她的龙上,她决定要
**输出:**吃。“有牙齿的食物,”乔拉爵士说。“我想尝尝那个,”丹妮抱怨道。"吃红肉喝麦芽酒不太像多斯拉克人."她想起了过去的时光,那时她的卡拉萨在长枪党统治时期是国王的住所,多斯拉克人肥胖的卡拉萨在骑马南下消灭其他多斯拉克人之前,会在他们的杯子里倒满美酒、鱼餐和烤芜菁。这只是供思考的食粮。我会大吃大喝,假装休息,直到龙再次出现,杀死我们所有人。
总是吃喝的好时机,对吧?我听说君临有一家不错的咖啡店,丹妮可以去试试(如果它还没被烧毁的话)。这很糟糕,让我们再试一次。
丹妮莉丝在埃索斯和弥林拥有爱和恐惧。但在维斯特洛,她觉得自己只有恐惧。在她赢得铁王座之战的那一刻,她只能想着给她将要统治的人民灌输恐惧。丹妮莉丝在君临坐在她的龙上,她决定要
保护这座城市,并为任何试图逃跑的人准备好坦格利安的灾难和恐怖,是的,包括人类。有人告诉她,一些巨人可能会杀死她,但丹妮莉丝摇摇头说:“没有巨人喜欢长得像巨人一样大。后来,后来,没有人愿意孤独地死在树林里。”她又读了一遍信。“昆汀王子,我忠诚的仆人们,我见过你们这样愚蠢的傻瓜,但我从未见过你们这样愚蠢的傻瓜。你的生命在众目睽睽之下被夺走了。丹妮莉丝是唯一能救你的人。”
所以这也没什么意义,但似乎坚持了丹妮想把君临的人民从那些准备“屈膝”且不打算逃跑的暴君手中解放出来的叙事。
结论
我试图为这些故事情节生成更多的样本,但没有一个在整个节目的背景下有很大的意义。即使对故事情节的理解不是很好,该模型也清楚地展示了学习该剧角色及其某些特质的能力,并在其输出中创建这些角色之间的关联。比如,我看到乔拉爵士在故事情节中出现在谈论丹妮的时候,阿多在谈论布兰的时候出现。而且它往往把这些角色之间的关系处理得恰到好处,真的让人印象深刻!
我认为这显示了随着 OpenAI 的 GPT-2 研究工作,NLP 研究已经前进了多远。我很想知道最大的 GPT-2 型号在这项任务中表现得有多好。也许如果更大的模型被发布,我会回来更新这篇文章。
至于想要一个令人满意和明智的《权力的游戏》结局,我想当代的人工智能帮不了我们,我们必须等待乔治·R·R·马丁完成他的书。愿他万岁!
想在你的浏览器上试试《GPT 2》的《权力的游戏》模型吗?用于测试预训练模型的 Google Colab 笔记本链接如下(为该笔记本提供)。
权力的游戏 GPT-2 文本生成器
colab.research.google.com](https://colab.research.google.com/drive/18pLqrk1j4RQ1RNh69Fa-5WkoTeD4uzwq)
参考文献
感谢您的阅读。如果你喜欢这篇文章,你可以在媒体、 GitHub 上关注我的更多作品,或者订阅我的 YouTube 频道。动手吧。弯曲膝盖。或者面对我的龙。
基于 TensorFlow Keras 的古腾堡开放 GPT 语言建模
Photo by Camille Orgel on Unsplash
1.介绍
2018 年对于深度自然语言处理社区来说是不平凡的一年。大型预训练模型,open ai【GPT】和 GPT-2 和 Google BERT ,在几个监督和非监督任务上取得了 SOTA(“最先进”)的结果。发布这些模型有助于在许多 NLP 任务中获得更好的结果(就像 ImageNet 在视觉领域所做的那样)。
我们一直在做的项目(一种讲故事的方式)需要一个强大的语言模型来促进自然语言的生成。本文介绍了在这项任务上所做的努力,包括技术细节和结果。完整代码以回购的形式发布在我们的团队 GitHub 中:
[## ShenakhtPajouh/GPT-语言-模型-tf.keras
在 GitHub 上创建一个帐户,为 ShenakhtPajouh/GPT-语言-模型-tf.keras 开发做出贡献。
github.com](https://github.com/ShenakhtPajouh/GPT-language-model-tf.keras)
2.动机
根据 Tensorflow 的网站:
Keras 是一个高级 API,用于构建和训练深度学习模型。它用于快速原型制作、高级研究和生产,具有三个关键优势:user friendly*,* 模块化和可组合 ,以及 易于扩展 。
此外,您可以在会话模式和快速执行模式下运行 TensorFlow Keras 模型。
OpenAI GPT,简称ggeneratepre-trainedttransformer**,**是一个在庞大语料库上训练出来的多层单向 transformer 解码器 ⁴。它的开发目标是通过微调来很好地执行各种任务。OpenAI 于 2018 年 6 月发布了 GPT 的论文、代码和预训练的权重。
2019 年 2 月,OpenAI 发布了 GPT-2,这是 GPT 的继任者,其参数超过 10 倍,数据量超过 10 倍。它被训练来预测下一个单词,并在 8 个测试语言建模数据集的 7 个上达到 SOTA 结果,而没有任何特定任务的微调!不可思议,不是吗?为了把樱桃放在最上面,OpenAI 决定不完全发布训练模型,而是发布一个小得多的模型,因为他们担心恶意应用程序 T2。
由于 OpenAI 成就和无法访问 GPT-2 完整模型,并且由于从空白状态学习更难取得成功,我们决定受益于转移学习技术并使用 TensorFlow Keras 实现 GPT。
3.履行
原始 GPT 被实现以在语言模型和分类任务上表现良好。因为我们只需要一个语言模型,所以我决定简化它的架构。有一个由 Ceshine Lee 设计的重构满足了这个需求。查看他解释原始和修改模型的帖子:
练习:从微调后的模型重建语言模型
medium.com](https://medium.com/the-artificial-impostor/notes-improving-language-understanding-by-generative-pre-training-4c9d4214369c)
上面的帖子包含了对变形金刚、GPT 和修改的详细解释,所以这篇帖子的其余部分将涵盖我所做的其他更改。
3.1.数据迭代器
我们使用 Guttenberg 数据集来重新训练模型。它包含超过 140,000 个段落。每一个样本都是一段被 BPE ⁵符号化的段落(带着尊重的面具)。所以在[iter_data](https://github.com/ShenakhtPajouh/last-sentence-generation-transformer/blob/master/utils.py#L51)
函数中,段落被打乱并通过小批量返回:
3.2.将张量流模型转换为 tf.keras 模型
整个变压器网络已经改造成 tf.keras 。作为网络一部分的每个张量流函数都被重新实现。model
、embed
、block
、attn
、mlp
、norm
、cov1d
函数被转换为Transformer
、EmbeddingLayer
、Block
、Attention
、MLP
、Norm
、Conv1D
类,这些类是 tf.keras 模型和层。
3.3.添加自回归模块
开发 GPT 的初衷并不是为了成为一个语言生成器。因此,它不具备生成文本的自回归模块。所以我们决定设计一个快速语言生成器,采用贪婪解码(它在每一步选择最有可能的下一个标记)。
在生成的每一步,该模块应该处理并获取下一个令牌的 logits,选择最可能的令牌,并在下一步为新序列执行该过程。
获取下一个令牌的 logits 的一个简单方法是传递整个令牌序列(带有生成令牌的早期令牌)。但是太慢了!*为什么?*因为它在每一步都有一个重复的操作:对于每一个 i,j < k ,计算 i 和 j 之间的注意力来预测第 k 个令牌。
我们的方法简单地省略了这个重复的操作。我用mem_k
和mem_v
来记忆键和值矩阵。首先, init_model 对输入序列进行预处理,将关键字和值存储在mem_k
和mem_v
中,并选择下一个令牌。
然后在每次迭代中, gen_model 获得查询、密钥和前一个令牌的值。然后将关键字和查询添加到mem_k
和mem_v
,并计算关注度。
有一些方法可以根据其分布生成下一个令牌。最简单的方法是贪婪解码。我们在每一步选择最可能的记号。波束搜索是另一种试图解决贪婪解码问题的著名技术。但是他们都有相同的内在问题,导致他们无法产生人类文本。(在这篇论文中,⁶解释了这些方法的缺点)
因此,在一些论文中,这两种方法被基于抽样的替代方法所取代。在这些方法中,在每一步,我们从下一个令牌分布中进行采样。我们实现了两个强大的解码器,称为 top-k 采样和 nucleus(top-p) 采样(【2】、【6】、【7】)。这确实提高了我们模型的世代。
您可以在实用程序中找到解码器的代码:
4.重新训练模型
我用 Adam optimizer 尝试了几种常用的训练方法,都失败了。然后,根据 ULMFiT 的论文,我做了一些改变:
- 亚当换成梯度下降。亚当技术极有可能让你的模型忘记预先训练好的权重。
- 我还使用了倾斜的三角形学习率(STLR)。它在一小部分训练步骤中线性地增加了学习率。然后,它在剩余步骤中线性降低学习速率。如论文中所述,“我们希望模型在训练开始时快速收敛到参数空间的合适区域,然后优化其参数。”于是 STLR 提出了。经过一些失败之后,我为 STLR 找到了一些好的超参数:
在和 STLR 一起训练后,我用一个简单的非线性衰减学习率继续训练:lr -= lr * (1 / t ** 0.5)
5.结果
下面的学习曲线清楚地显示了 STLR 技术的效率。(因为仅在 2400 步之后,列车困惑度就显著下降)
train ppl in 30,000 steps.
验证集的复杂度从 130.21 降低到 22.57。
validation ppl
6.承认
我衷心感谢实现了一些 Transformer 模块的茯苓 Yavari 和实现采样解码器的 Mehrnaz Mofakhami。
7.参考
[1] 利用无监督学习提高语言理解作者:亚历克·拉德福德、卡蒂克·纳拉西姆汉、蒂姆·萨利曼斯和伊利亚·苏茨基弗
[2] 更好的语言模型及其含义作者:亚历克·拉德福德、杰夫·吴、雷文·柴尔德、大卫·栾、达里奥·阿莫代伊和伊利亚·苏茨基弗
[3] BERT:用于语言理解的深度双向转换器的预训练作者:Jacob Devlin,张明蔚,Kenton Lee,Kristina Toutanova
[5] 由 Rico Sennrich,Barry Haddow,Alexandra Birch 编写的具有子词单元的罕见词的神经机器翻译
OpenAI 的克里斯汀·佩恩谈人工智能产生的音乐和超级智能之路
她在普林斯顿学习物理,在斯坦福学习神经科学和医学。
她是受过古典音乐训练的钢琴家。
她刚刚发明了一种算法,可以让音乐家失业。(嗯,可能不会,但这确实是一个令人印象深刻的算法)
克里斯汀·佩恩是 MuseNet 的作者,这是一个基于 OpenAI 的现在臭名昭著的 GPT-2 模型的深度神经网络,可以自动生成几乎任何你想要的风格的歌曲。
我们和 Christine 坐下来谈论 MuseNet,人工智能的未来,以及 OpenAI 防止机器人启示录的任务。请点击这里查看,别忘了在 Twitter 上关注她, @mcleavey !
OpenAI 的 GPT-2:模型、宣传和争议
上周四,OpenAI 发布了一个叫做 GPT-2 的超大型语言模型。该模型可以基于一些种子文本生成各种风格的真实文本,从新闻文章到同人小说。有争议的是,他们决定不公布他们最大模型的数据或参数,理由是担心潜在的滥用。已经是挺 大 大了。
我决定开一个博客,这样我就可以写这个了,因为我还没有看到一个帖子说了我想说的所有事情。我认为,对于机器学习社区来说,处理机器学习研究的潜在滥用是非常重要的。我还谈到了这项研究的技术价值,人类语言生成的社会意义,以及对 OpenAI 受炒作生成驱动的指责。
(免责声明:2017 年 2-8 月在 OpenAI 实习,认识一些参与这项研究的人。这里陈述的观点是我自己的。)
这项研究有什么好处吗?
我曾经致力于基于神经网络的对话系统,它被训练成在给定对话中先前响应的情况下预测下一个响应。我记得在 2016 年末,我浏览了我们的模型生成的样本,试图找到一个听起来似乎符合对话背景的句子。
所以当我读到 GPT 2 的讲英语独角兽的故事时,我相当震惊(如果你还没读过,我强烈推荐)。这个故事并不完美,中间有一些摇摆,但总的来说,它非常连贯。这实际上听起来像是一篇人类可以写的新闻文章。对我来说,不管采摘了多少樱桃,这都是一个令人难以置信的结果。如果有一个语言模型能够在没有显式记忆机制的情况下,在整篇文档中正确地回忆起豪尔赫·佩雷斯的名字,我会对这个语言模型有一定的印象。这完全是另一回事。我可能对最近的语言生成文学有点过时,但我不知道有任何模型接近这种水平的连贯性、语法性、长期上下文的使用和世界知识。
要明确的是:这里没有算法的贡献。他们“只是扩大了”之前的研究。但是我认为确切地看到这些放大的模型有多强本身就是一个重要的贡献。回想起来,“当然,更多的数据和计算会给你更好的模型”,这很容易,但如果我上周三向一位同事展示了独角兽的故事,并告诉他们这是人工智能生成的,我认为他们不会相信我。
一些人怀疑这个模型是否只是记忆文本的“模板”并在正确的时间重复它们。在的论文(附录 8.2)中讨论了这一问题,其中作者表明 GPT-2 的样本和它们的训练集之间的词重叠小于测试集和训练集之间的重叠。换句话说,GPT-2 表现出的记忆行为比随机选择的一部分人类文本要少。这似乎是相当令人信服的证据,表明该模型具有重要的泛化能力。
Figure 5 from the OpenAI GPT-2 paper. It shows the probability that GPT-2 samples (‘samples’) and human text from the test set (‘real’) have a certain % overlap with the training set. Much more of the ‘samples’ probability is at a lower % overlap.
我们应该对他们的结果持怀疑态度吗?关于 OpenAI 是否准确地呈现了他们模型的生成能力,有一个合理的问题。我个人希望看到他们输入 GPT-2 的输入数量,以获得显示的样本(即他们所谓的“元樱桃采摘”的程度)。然而,他们确实提供了数百个原始 GPT-2 样本的转储,这让我们对他们模型的能力有了更清晰的了解。他们还指出,对于每一篇高质量的 GPT-2 写作,需要多少样本才能实现,这在其他论文(包括我自己的论文)中并不常见。随着代码的发布,对我来说 OpenAI 的方法符合其他已发表的 NLP 论文的标准。
人为素质造假文本的社会影响
现在谈谈争议。OpenAI 决定不公布其最大的 GPT-2 模型的权重,并表示担心“大型语言模型被用来大规模产生欺骗性、偏见或辱骂性的语言。”让我们暂时把 GPT-2 是否能做到这一点的问题放在一边,首先问一下:如果我们有一个开源模型,可以生成无限的人类质量的带有特定信息或主题的文本,那会是坏事吗?
我想答案是肯定的。的确,人类已经可以写假新闻,政府已经招募了成千上万的人来为他们的议程写有偏见的评论。但是一个自动化系统可以:(1)让那些没有资源雇佣成千上万人的坏人发动大规模的虚假信息运动;以及(2)大幅增加国家行为者已经在进行的虚假信息运动的规模。这些活动之所以有效,是因为人们在很大程度上受到他们周围持有某种观点的人的影响,即使这种观点毫无意义。扩大规模应该相应地增加政府和公司对我们信仰的影响力。
为了解决这个问题,我们需要开始研究人工智能生成文本的检测方法。与虚假视频和语音检测相比,这将提出不同的挑战:虽然只需要一个高质量的虚假视频来影响人们的观点,但视频是非常高维的,并且可能更容易检测到由 ML 模型产生的 【伪像】。另一方面,人工智能生成的假文本必须在大规模下才能产生影响(否则人类可以做到),但由于文本由离散的单词组成,因此可能更难区分特定的文本片段是否是人工智能生成的,特别是如果它很短。
因此,有合理的理由认为,广泛发布一个完美的人类级别的文本生成器,而不考虑其含义,可能是一个坏主意。
AI 炒作,以及 OpenAI 的动机
还有另一个原因,许多人假设为什么 OpenAI 保留了他们的模型参数——为他们的研究增加宣传价值。理论是,OpenAI 知道新闻媒体如果可以编造“AI 是危险的”叙事,就会更多地报道这项研究,因此保留了他们的模型,以便耸人听闻的新闻报道可以报道它们,从而增加公众对 OpenAI 的认可,并进一步巩固 OpenAI 的 AI 安全工作的感知价值。
OpenAI 还没有写他们与记者互动的方法,但我们可以填补一些空白。像其他工业实验室一样,OpenAI 显然关心公众的看法和认可。他们也明确地邀请记者写关于他们研究的故事(否则他们不会让 GPT 2 号接触他们)。最重要的是,由于 OpenAI 是一个非营利组织,他们获得了更大的优势来宣传他们的研究,因为这可能会增加捐款,从而增加他们做更多研究的预算。很难知道 OpenAI 对关于他们的新闻有多大的控制力,但是一些关于 GPT-2 的头条和文章相当具有启示性。
那么我们怎么知道 OpenAI 的首要动机不是为了获得更多的影响力和金钱呢?简短的回答是:我们没有。我们不得不相信他们的话,他们真的关心他们研究的社会影响。对我来说,这并不特别难以置信,因为我个人认识很多这样的人。
但许多研究人员似乎不愿意给出积极的意图:他们认为 OpenAI 要么是一个认为他们将拯救世界的“比你更神圣”的机构,要么是一个被“AI 奇点”概念误导并致力于制造恐惧的团体,要么是埃隆·马斯克旨在最大限度地扩大新闻报道的自我傀儡,或者是两者的某种组合。他们名字中的“开放”一词,加上他们对媒体的过度关注和与埃隆的联系,似乎酝酿了一种特殊的仇恨,这种仇恨已经蔓延到 Twitter 和 Reddit 上,作为对 GPT-2 宣布的回应。
这些批评值得讨论,也包含了一些事实(除了,据我所知,埃隆已经不再是 OpenAI 董事会的了,而且已经有一段时间没有影响他们的决策了)。媒体对人工智能研究的扭曲是一个真正的问题,因为媒体炒作导致工业实验室受到过度关注,这欺骗了其他地方的研究人员。关于大实验室公关在影响公众对人工智能的看法方面的作用,将会有一场重要的讨论。
但是我敦促旁观者暂时把他们对 OpenAI 的判断放在一边(你可以稍后继续),想想这里到底发生了什么。作为 ML 研究人员,我们正在创造影响人们的东西。迟早,我们会越过一条线,我们的研究可以被恶意利用来做坏事。我们是否应该等到这种情况发生时再决定如何处理可能有负面副作用的研究?
机器学习社区中的杰出人物不屑一顾的讽刺性回应让我特别失望。我不会详细讨论这一点,但我认为这使人们对 ML 的社会影响的轻视态度正常化了。如果你是这个领域的新手,你看到一个很酷的著名研究人员对那些没有发布他们愚蠢的 ML 模型的书呆子开了一个玩笑,你很可能会吸收这些判断而不进行批判性思考(至少,我在硕士期间很容易受到著名人工智能研究人员的影响)。我觉得这个帮助不大。
一名研究人员在 Twitter 上评论说,DeepMind 本可以在发布 WaveNet 时做一些类似的事情,这是一种生成高质量人类语音的模型,他们对没有这样做负有更大的社会责任(他们在的首次发布中根本没有提到道德影响)。诚然,OpenAI 的研究没有什么特别或神奇的地方——其他实验室已经做了一些研究,这些研究本可以被搁置。一些工业实验室确实有公平团队在发布前审查研究,但我们作为一个领域不知道他们使用什么规范或他们执行什么标准。OpenAI 似乎是唯一一个公开考虑他们的机器学习研究的伦理影响的工业实验室*。即使他们的主要动机是贪婪或炒作,我认为他们提出的问题值得认真对待。*
继续前进:开始关于社会影响的对话
GPT-2 模型真的保证了这种程度的谨慎吗?很难说。诸如此类的决定引发了许多问题:这种做法真的会让不良行为者推迟多久才能重现这一结果?再现性的代价是什么?无害的研究和危险的研究之间的界限在哪里?我们如何负责任地与记者接触,以准确报道这些进展?在这种情况下,GPT-2 是否足够良性,应该完全释放?OpenAI 是否应该向研究人员提供有限的访问权限,以确保可重复性?或者他们根本就不应该发布那篇论文?OpenAI 似乎愿意参与关于这些问题的讨论(他们在博客帖子的底部发了一封电子邮件征求反馈),但这还不够:这些讨论应该公开进行,而不是通过电子邮件交流。
这是最重要的一点:机器学习社区真的真的需要开始公开讨论我们的伦理研究发布标准。 我们需要一个不是推特的场地。一种可能是一个研讨会,可能与 ICLR、ICML 或 NeurIPS 等大型 ML 会议设在同一地点,在那里我们可以集思广益,讨论我们希望作为一个领域采用什么规范。我可以想象一种“安全清单”(类似于最近的“再现性清单”),鼓励研究人员在发布他们的工作之前遵守。像生物技术和网络安全领域一样,我们正在接近这样一个点,即一小部分 ML 论文有可能被滥用。这应该足够让我们开始做些什么了。
有机器学习研究人员正在阅读这种思维:“这整个情况是荒谬的,AI 无论如何都不会真正工作。让我回去训练我的模型。”这是问题的一部分:从内部来看,经常感觉进步是递增的,没有什么事情像它应该的那样工作(尤其是 RL)。但是 ML research 已经在现实世界中产生了影响(例如,对贷款申请做出决策、、法院判决、人员招聘等)。).这些算法中的偏见现在正在被暴露出来,但这是在它们首次实施多年之后,同时它们对人们的生活产生了严重影响。
随着我们的系统变得更有能力(它们最终会变得更有能力),我们将能够做越来越棒的事情,并有希望让世界变得更好。但是滥用的可能性也将显著增加。如果大多数人工智能研究人员在发布他们的研究成果之前没有考虑到它们的社会影响,那些关心的人将不断地追赶。如果我们想把机器学习给世界带来的伤害降到最低,这是不够的。
感谢 Alex Irpan 和 Jean Harb 在这篇文章中给出了非常棒的反馈,感谢 Natasha Jensen 提出了“安全清单”的想法。
OpenAI 的捉迷藏发现,系统视角
是的,代理商作弊了,但这对系统意味着什么?
OpenAI 发布了一个关于多智能体捉迷藏模拟中获得的一些结果的神奇作品,在该模拟中,多个隐藏者和多个寻找者玩这种流行的儿童游戏。
该模拟有一些有趣的方面,如工具(盒子、斜坡、墙壁),代理可以使用这些工具来帮助他们实现有效隐藏/寻找的目标。然而,更值得注意的结果是,环境的扩展模拟导致了涌现行为;也就是说,根本没有计划或意想不到的行为。
例如,一些预期的行为是隐藏者最终将学会用墙和/或盒子建造一个围栏,以隐藏坡道,不让搜索者看到。这样,坡道就不能被用来越过墙壁,从上面进入已建成的围墙。现在,环境设计者没有预料到的(紧急行为)是,搜索者会知道他们可以使用斜坡到达一个盒子的顶部,然后使用一个奔跑的动作来基本上“冲浪”盒子到他们喜欢的任何地方!
使用这种方法,搜索者找到了一种从上方接近隐藏建筑的方法,这不是系统设计者的意图!
探索者欺骗了系统。
现在,你认为隐藏者对这种行为的反应是什么?你们中的一些人可能会认为,既然搜索者已经在某种程度上了解了系统的未定义行为,那么隐藏者可能会做出一些荒谬的反应,因为系统现在处于混乱状态。
但是仔细想想。系统没有处于任何未知状态。
虽然它可能处于设计者没有明确打算创造的状态,但代理人继续以他们认为对他们期望的结果最佳的方式运作。
因此,隐藏者学会了瘫痪搜索者的冲浪能力!
他们通过使用预先分配的初始时间来做到这一点,在该时间内,搜索者被冻结锁定所有的箱子和坡道。然后,他们利用剩下的任何时间,用可移动的墙壁建造一个快速的围栏,然后锁定墙壁。这样,搜索者现在再一次没有办法进入围栏内部(至少,这是他们的想法……)。干得好,伙计们。
我认为这很吸引人,但与 OpenAI 的大多数分析所关注的水平不同。他们确实提到代理会找到进入系统的方法:
“[……]代理制定了[……]战略和反战略,其中一些我们不知道我们的环境支持”
然而,他们随后只深入到代理人了解的场景的细节,而完全忽略了环境设计缺陷本身。我觉得后者是更有趣的现象!我想颠倒一下分析——现在让我们保持代理设计不变,改变环境的状态结构和奖励系统。分析不同的激励/响应系统如何诱导不同的代理策略。强化学习的领域进展惊人,尤其是在最近几年。短短几十年间,我们已经从跳棋解算者变成了围棋冠军——我们的智能体建模越来越棒了。现在,我们的多智能体环境建模怎么样了?
多智能体环境设计
OpenAI 当然也想过。根据他们的最后一段,
构建环境并不容易,通常情况下,代理会找到一种方法,以一种意想不到的方式利用您构建的环境或物理引擎。
由 @BonsaiAI 在 Medium 上写的一篇关于奖励函数设计的文章提到“你得到你所激励的,而不一定是你想要的。”这很好地总结了为某一特定结果设计奖励系统的内在困境。你当然知道你的激励系统将如何使整个系统达到期望的状态,但是你有没有考虑到你的系统中可能存在一些“裂缝”的所有细微之处?显然,这说起来容易做起来难。这种“意图与结果”的分歧在我们的日常生活中随处可见,无论是职业还是非职业:
- 软件工程师打算将文档化的规范转化为功能软件,忠实地再现文档化的变更。
- 公司高管打算根据员工为公司整体提供的价值,给予他们适当的报酬。
- 运动队经理打算运用比赛计划和球员阵容来战胜每一个连续的对手。
- 等等…
对于所有这些情况来说,一个坚定而简洁的事实是,系统的行为完全符合其设计的;没有意料之外的后果,只有意料之外的后果。
为了让这个想法更清楚,让我们把补偿场景看得更远一点。假设有接近公司中层的员工对他们的薪酬不满意,并且对薪酬结构的整体设计有异议(假设整个组织都知道该结构)。这些员工可能会说“这个系统坏了”或“这里发生的事情是错误的”。然而,在这种情况下(假设有一个富有同情心和公正的设计者),不能说的是“这个系统没有做它被设计的事情。”
当然是啦!它正在做它被指示做的事情!如果它应该做一些与现在不同的事情,那么它就应该这样改变。现在,我们可能已经打算让系统做一件事,但这可能是也可能不是最终的设计。然而,不管意图如何,正在发生的事情是被选中的系统的完美再现。
新领域
我很高兴看到更多的理论围绕环境激励系统的有效设计而发展,尤其是在多主体场景中。像这样的理论应用在我们的日常生活中随处可见,甚至是我们试图回答的关于彼此生活的最重要的问题。以下是一些例子:
- 我们治理自己和他人的最佳方式是什么?[ ]
- 组织我们如何定义和相互交换价值的最佳方式是什么?
- 为了共同的最终产品或创作,相互协作的最佳方式是什么?
只要举一两个这样的例子,你就会有足够的动力去做这件事。这很好……因为这一领域的研究在某些方面刚刚起步。例如,我想象有太多的历史出版物对政府、经济体系和管理层级等事物进行系统层面的分析。然而,所有这些优势将很快与多智能体 RL 的最新进展结合起来。这些理论家族之间的重要相似性和差异有可能导致人类系统和计算机代理系统等主题的知识和应用的爆炸。
结论
无论代理人是人类还是数字,系统总是被游戏化的。
对于防止/检测/打击利用激励系统的有效方法,您有什么想法?
你所知道的一些有趣的“永恒的”学术著作是什么,它们分析了人类/智能体系统?
多智能体 RL 中的奖励设计也是如此吗?
您在这里还看到了哪些我没有提到的应用?
[ ]:我期待着有一天,选举候选人提出的政策可以通过模拟来评估,让电视辩论的马戏变得毫无用处
OpenCV 静态显著性检测简而言之
寻找佼佼者
Photo by Justin Ha on Unsplash
显著性是图像的突出部分,使我们的大脑能够专注于该部分。当我们看到一幅图像时,这就是我们所关注的,引人注目的区域。比如,你有没有在广告中看到一些有趣的东西,让你停下来看一会儿?这就是广告的显著之处,即使你只是看了一眼,也能吸引你的兴趣。
安装 OpenCV
首先,你需要安装 OpenCV 库。如果您已经安装了 pip,您可以通过运行这些命令来完成。
> pip install opencv-python
> pip install opencv-contrib-python
要验证安装,您可以运行以下命令。
> python
Python 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 18:11:49)
Type "help", "copyright", "credits" or "license" for more information.
>> import cv2
>> cv2.saliency
<module 'cv2.saliency'>
静态显著性检测
有许多方法来检测显著性。在 OpenCV 中,为显著性检测提供的算法分为三类:
Saliency Diagram. Source : OpenCV Documentation
我们将讨论静态显著性。静态显著性检测算法使用允许检测非动态图像的显著对象的不同图像特征。OpenCV 中已经实现了两种算法,谱残差算法和细粒度算法。
光谱剩余
该算法分析输入图像的对数谱,在谱域中提取图像的谱残差,并提出一种快速构建显著图的方法,该显著图给出了原型物体的位置。
相似意味着冗余。对于以最小化冗余视觉信息为目标的系统,它必须知道输入刺激的统计相似性。因此,在可以观察到相当大的形状相似性的不同对数谱中,值得我们注意的是从平滑曲线中跳出的信息。我们认为,光谱中的统计奇点可能是图像中出现异常区域的原因,在这些区域中会弹出原型物体。
而如果你绘制显著图,你会得到下面的输出图像。
Spectral Residual
参考:侯、晓迪、。"显著性检测:一种谱残差方法."计算机视觉与模式识别,2007。07 年的 CVPR。IEEE 会议。IEEE,2007 年。
细粒
人眼的视网膜由神经节细胞组成。有两种类型的神经节细胞,位于中心和偏离中心。中央对黑暗背景包围的明亮区域做出反应。偏心对明亮背景包围的黑暗区域做出反应。
该算法基于中心和偏心差计算显著性。
On-center and off-center ganglion cells and their approximation on computational models of visual saliency. Source: B. Wang and P. Dudek “A Fast Self-tuning Background Subtraction Algorithm”, in proc of IEEE Workshop on Change Detection, 2014
在我们的例子中,通过使用通过所谓的积分图像的
中心-周围差异的有效实现,我们演示了一种在原始图像分辨率下实时生成视觉显著性的细粒度特征图的方法。
如果你绘制显著图,你会得到下面的输出图像。
参考:B. Wang 和 P. Dudek,“一种快速自调整背景减除算法”,IEEE 变化检测研讨会论文集,2014 年
参考
[## OpenCV:cv::studential::studential 类引用
公共成员函数|受保护成员函数|受保护属性|所有成员的列表
docs . opencv . org https://docs . opencv . org/3.4/d9/DCD/classcv _ 1 _ 1 saliency _ 1 _ 1 saliency . html](https://docs.opencv.org/3.4/d9/dcd/classcv_1_1saliency_1_1Saliency.html)
打开黑盒:如何利用可解释的机器学习
可解释-ML
使用 PDP、LIME 和 SHAP 制定可解释的决策,为利益相关方创造价值
随着机器学习和人工智能变得越来越受欢迎,越来越多的组织正在采用这项新技术。预测建模帮助流程变得更加高效,同时也让用户受益。人们可以根据你的专业技能和经验来预测你可能会挣多少钱。输出可能只是一个数字,但是用户通常想知道为什么给出这个值!
在本文中,我将展示一些创建可解释预测的方法,并引导您打开这些黑盒模型。
本文中使用的数据是美国成人收入数据集,通常用于预测某人的收入是低于 50K 还是高于 50K,这是一个简单的二元分类任务。你可以在这里获得数据,或者你可以在这里跟随笔记本。
关于个人关系、职业、种族、性别等信息的数据相对简单。
建模
分类变量是一次性编码的,目标设置为 0 (≤50K)或 1 (>50K)。现在,假设我们想要使用一个模型,该模型以其在分类任务上的出色性能而闻名,但是高度复杂,并且输出难以解释。这个模型应该是 LightGBM,它与 CatBoost 和 XGBoost 一起经常用于分类和回归任务。
我们首先简单地拟合模型:
from lightgbm import LGBMClassifier
X = df[df.columns[1:]]
y = df[df.columns[0]]
clf = LGBMClassifier(random_state=0, n_estimators=100)
fitted_clf = clf.fit(X, y)
我应该注意到,为了防止任何过度拟合,你最好将训练/测试分割为附加的维持数据。
接下来,我使用 10 重交叉验证快速检查模型的性能:
from sklearn.model_selection import cross_val_score
scores_accuracy = cross_val_score(clf, X, y, cv=10)
scores_balanced = cross_val_score(clf, X, y, cv=10,
scoring="balanced_accuracy")
有趣的是,scores_accuracy 给出了 87%的 10 倍平均准确度,而 scores_balanced 给出了 80%。事实证明,目标变量是不平衡的,25%的目标属于 1,75%属于 0。因此,选择正确的验证方法非常重要,因为它可能会错误地指出一个好的模型。
现在我们已经创建了模型,接下来将解释它到底做了什么。由于 LightGBM 使用高效的梯度推进决策树,因此解释输出可能会很困难。
部分相关性图(PDP)
部分相关性图(DPD)显示了某个特性对基于预测的模型的结果的影响。为了提取感兴趣特征的重要性,它在特征的分布上忽略了模型输出。我使用的包 PDPbox 可以在这里找到。
假设
这种重要性计算基于一个重要的假设,即感兴趣的特征与所有其他特征(除了目标)不相关。这样做的原因是它将显示很可能是不可能的数据点。例如,体重和身高是相互关联的,但是 PDP 可能会显示目标体重较大而身高很小的影响,而这种组合是极不可能的。这可以通过在 PDP 底部展示一块地毯来部分解决。
相互关系
因此,我们检查特性之间的相关性,以确保没有问题:
import seaborn as sns
corr = raw_df.corr()
sns.heatmap(corr,
xticklabels=corr.columns,
yticklabels=corr.columns)
我们可以看到,这些特征之间不存在强相关性。但是,稍后我将进行一些一次性编码,为建模准备数据,这可能会导致相关特征的创建。
连续变量
PDP 图可用于显示变量对所有数据点输出的影响。让我们先从一个显而易见的开始,一个连续变量,即资本收益,对目标的影响:
from pdpbox import pdp
pdp_fare = pdp.pdp_isolate(
model=clf, dataset=df[df.columns[1:]], model_features=df.columns[1:], feature='Capital_gain'
)
fig, axes = pdp.pdp_plot(pdp_fare, 'Capital_gain', plot_pts_dist=True)
x 轴表示 capital_gain 可以取的值,y 轴表示它对二元分类概率的影响。很明显,随着一个人的资本收益增加,他们赚< 50K 的机会也随之增加。请注意,底部的数据点有助于识别不常出现的数据点。
独热编码变量
现在,如果你有一次性编码的分类变量呢?您可能希望单独查看类别的效果,而不必单独绘制它们。使用 PDPbox,您可以同时显示对多个二元分类变量的影响:
pdp_race = pdp.pdp_isolate(
model=clf, dataset=df[df.columns[1:]],
model_features=df.columns[1:],
feature=[i for i in df.columns if 'O_' in i if i not in
['O_ Adm-clerical',
'O_ Armed-Forces',
'O_ Armed-Forces',
'O_ Protective-serv',
'O_ Sales',
'O_ Handlers-cleaners']])
fig, axes = pdp.pdp_plot(pdp_race, 'Occupation', center=True,
plot_lines=True, frac_to_plot=100,
plot_pts_dist=True)
在这里,你可以清楚地看到,无论是管理职位还是技术职位,都积极地影响着挣更多钱的可能性。如果你在捕鱼业工作,这种机会会减少。
变量之间的相互作用
最后,变量之间的交互可能会有问题,因为 PDP 将为组合创建值,如果变量高度相关,这是不可能的。
inter1 = pdp.pdp_interact(
model=clf, dataset=df[df.columns[1:]],
model_features=df.columns[1:], features=['Age', 'Hours/Week'])
fig, axes = pdp.pdp_interact_plot(
pdp_interact_out=inter1, feature_names=['Age', 'Hours/Week'],
plot_type='grid', x_quantile=True, plot_pdp=True)
这个矩阵告诉你,如果一个人 49 岁左右,每周工作大约 50 个小时,他可能会赚得更多。我应该注意的是,记住数据集中所有交互的实际分布是很重要的。有可能这个情节会向你展示一些很少或永远不会发生的有趣的互动。
局部可解释的模型不可知解释(LIME)
LIME 基本上试图远离导出全局特征的重要性,而是近似局部预测的特征的重要性。它通过获取行(或一组数据点)来进行预测,并基于该行生成虚假数据。然后,它会计算假数据和真实数据之间的相似性,并根据假数据和真实数据之间的相似性来估计更改的影响。我用的包可以在这里找到。
from lime.lime_tabular import LimeTabularExplainer
explainer = LimeTabularExplainer(X.values, feature_names=X.columns,
class_names=["<=50K", ">50K"],
discretize_continuous=True,
kernel_width=5)i = 304
exp = explainer.explain_instance(X.values[i], clf.predict_proba,
num_features=5)
exp.show_in_notebook(show_table=True, show_all=False)
The output of LIME for a single row
输出显示了前 5 个变量对预测概率的影响。这有助于确定为什么您的模型会做出某种预测,而且还允许向用户进行解释。
不足之处
注意,LIME 试图为初始行寻找不同值的邻域(内核宽度)在某种程度上是一个可以优化的超参数。根据数据,有时您需要更大的邻域。找到正确的内核宽度需要一点反复试验,因为这可能会损害解释的可解释性。
沙普利附加解释(SHAP)
一个(相当)近期的发展是 Shapley 值在机器学习应用中的实现。本质上,SHAP 使用博弈论来跟踪每个变量的边际贡献(T2)。对于每个变量,它从数据集中随机抽取其他值,并计算模型得分的变化。然后,对每个变量的这些变化进行平均,以创建一个汇总分数,但也提供了某些变量对于特定数据点的重要性的信息。
点击此处查看我在分析中使用的软件包。要更深入地了解 SHAP 的理论背景,请点击这里。
可解释性的三个公理
SHAP 因其满足可解释性三个公理的能力而广受好评:
- 任何对预测值没有影响的要素的 Shapley 值都应该为 0(虚拟)
- 如果两个特征将相同的值添加到预测中,则它们的 Shapley 值应该相同(可替代性)
- 如果您想要合并两个或更多预测,您应该能够简单地添加根据单个预测计算的 Shapley 值(可加性)
二元分类
让我们看看,如果我们要计算单行的 Shapley 值,结果会是什么:
import shap
explainer = shap.TreeExplainer(clf)
shap_values = explainer.shap_values(X)
shap.initjs()
shap.force_plot(explainer.expected_value, shap_values[1,:],
X.iloc[1,:])
Shapley values for a single data point
该图显示了用于指示预测方向的基值。由于大多数目标都是 0,所以看到基值为负并不奇怪。
红色条表示如果 Eeducation _ num为 13,目标为 1 (>50K)的概率增加了多少。高等教育通常会带来更多的收入。
蓝条显示这些变量降低了概率,其中年龄的影响最大。这是有道理的,因为年轻人通常挣得更少。
回归
当涉及回归(连续变量)而不是二元分类时,Shapley 直观地工作得更好。仅举一个例子,让我们训练一个模型,从相同的数据集中预测年龄:
# Fit model with target Age
X = df[df.columns[2:]]
y = df[df.columns[1]]
clf = LGBMRegressor(random_state=0, n_estimators=100)
fitted_clf = clf.fit(X, y)# Create Shapley plot for one row
explainer = shap.TreeExplainer(clf)
shap_values = explainer.shap_values(X)
shap.initjs()
i=200
shap.force_plot(explainer.expected_value, shap_values[i,:], X.iloc[i,:])
Shapley values for a single data point
在这里,你可以很快观察到,如果你从未结过婚,预测的年龄会降低大约 8 岁。与分类任务相比,这更有助于解释预测,因为您直接谈论的是目标的值而不是其概率。
独热编码特征
加法公理允许对所有数据点上的每个特征的 Shapley 值求和,以创建平均绝对 Shapley 值。换句话说,它赋予全局特征重要性:
shap.summary_plot(shap_values, X, plot_type="bar", show=False)
但是,您可以立即看到使用一次性编码要素的 Shapley 值的问题,这些值是为每个一次性编码要素显示的,而不是它们最初表示的内容。
幸运的是,加法公理允许将每个一位热编码生成特征的 Shapley 值相加,作为整个特征的 Shapley 值的表示。
首先,我们需要对独热编码特征的所有 Shapley 值求和:
summary_df = pd.DataFrame([X.columns,
abs(shap_values).mean(axis=0)]).T
summary_df.columns = ['Feature', 'mean_SHAP']mapping = {}
for feature in summary_df.Feature.values:
mapping[feature] = featurefor prefix, alternative in zip(['Workclass', 'Education',
'Marital_status', 'O_',
'Relationship', 'Gender',
'Native_country', 'Capital',
'Race'],
['Workclass', 'Education',
'Marital_status', 'Occupation',
'Relationship', 'Gender',
'Country', 'Capital', 'Race']):
if feature.startswith(prefix):
mapping[feature] = alternative
break
summary_df['Feature'] = summary_df.Feature.map(mapping)
shap_df = (summary_df.groupby('Feature')
.sum()
.sort_values("mean_SHAP", ascending=False)
.reset_index())
现在,所有 Shapley 值都是所有要素的平均值,并对唯一热码编码要素求和,我们可以绘制最终的要素重要性:
import seaborn as sns
import matplotlib.pyplot as plt
sns.set(style="whitegrid")
f, ax = plt.subplots(figsize=(6, 15))
sns.barplot(x="mean_SHAP", y="Feature", data=shap_df[:5],
label="Total", color="b")
我们现在可以看到职业比最初的 Shapley 概要情节显示的要重要得多。因此,在向用户解释特性的重要性时,一定要充分利用附加性。他们可能更感兴趣的是职业有多重要,而不是具体的职业。
结论
虽然这肯定不是第一篇讨论可解释和可说明的 ML 的文章,但是我希望这有助于您理解在开发您的模型时如何使用这些技术。
围绕 SHAP 有一个重要的讨论,我希望使用一键编码的特性来演示可加性公理会给如何使用这种方法带来更多的直觉。
感谢您的阅读!
如果你像我一样,对人工智能、数据科学或心理学充满热情,请随时在 LinkedIn 上添加我,或者在 Twitter 上关注我。
本文中的所有示例和代码都可以在这里找到:
https://github.com/MaartenGr/InterpretableML
任何反馈和意见,一如既往,非常感谢!
OpenML:作为社区的机器学习
OpenML 是一个在线机器学习(ML)实验数据库,每个人都可以免费使用。其核心思想是拥有一个数据集和 ML 实验结果的单一存储库。尽管近年来获得了很大的流行,现在有太多的工具可用,大量的 ML 实验继续在筒仓中发生,并且不一定作为一个完整的共享社区。
在这篇文章中,我们将尝试简要了解 OpenML 提供了什么,以及它如何适应我们当前的机器学习实践。
让我们直接通过建立一个简单的机器学习模型来让我们的手变脏。如果我们寻找的是简单性,那就是我们将要使用的 虹膜数据集 。在下面的示例脚本中,我们将加载 scikit-learn 提供的 Iris 数据集,使用 10 重交叉验证来评估 10 棵树的随机森林。听起来很琐碎,而且实际上不到 10 行代码。
一个简单的脚本,我们实现了平均准确率为 95.33%。那很容易。令人惊讶的是,我们已经在 ML 工具上取得了如此大的进步,使得入门变得非常容易。因此,我们每天都有成千上万的人使用这些工具。这不可避免地导致了车轮的重新发明。每个单独的 ML 从业者执行的任务通常有很大的重叠,可以通过重用来自社区的人已经完成的任务来省略。说到底,我们并没有从头开始构建一个随机的森林模型。我们很乐意重用来自社区的慷慨人士编写的代码。我们这个物种的特殊属性是作为一个集体工作的能力,在这个集体中,我们的智慧总和大于个体的总和。为什么不为 ML 做同样的事情呢?我的意思是,我可以看看其他 ML 从业者做了什么来在 Iris 数据集上获得更好的分数吗?
回答这个问题是这篇文章的目标之一。我们将随后在 OpenML 的帮助下探索这是否可行。然而,首先,我们应该简单地熟悉一些术语,看看我们如何将前面看到的例子分解成模块化组件。
OpenML 组件
Image Source: https://medium.com/open-machine-learning/openml-1e0d43f0ae13
数据集 : OpenML 容纳了超过 2k+ 的活跃数据集,用于各种回归、分类、聚类、生存分析、流处理任务等。任何用户都可以上传数据集。一旦上传,服务器计算数据集上的某些元特征— 类的数量、缺失值的数量、特征的数量等。关于我们前面的例子,下面一行相当于从 OpenML 中获取一个数据集。
X, y = datasets.load_iris(return_X_y=True)
任务:一个任务链接到一个特定的数据集,定义目标/因变量是什么。还规定了评估措施,如— 准确度、精度、曲线下面积等。或者要使用的估计程序的种类,例如 10 重交叉验证、n%维持集等。关于我们之前的例子,下面函数调用的参数捕获了任务的思想。
scores = cross_val_score(clf, X, y, cv=5, scoring='accuracy')
流程:描述要执行的建模种类。它可以是一个流程或一系列步骤,即 scikit-learn 管道。现在,我们已经使用了一个简单的随机森林模型,它是这里的流组件。
clf = RandomForestClassifier(n_estimators=10, max_depth=2)
运行:将一个流程和任务配对在一起,产生一个运行。运行具有由服务器转化为评估的预测。这被该行的执行有效地捕获:
scores = cross_val_score(clf, X, y, cv=5, scoring='accuracy')
现在,这可能看起来有点混乱,因为我们正在尝试划分一个简单的 10 行代码,它工作得很好。然而,如果我们花几秒钟浏览一下上面解释的 4 个组件,我们可以看到,它使我们在 Iris 上对随机森林的训练成为一系列模块化任务。模块是计算机科学中的一个基本概念。它们就像乐高积木。一旦我们有了模块,就意味着我们可以轻松地即插即用了。下面的代码片段试图使用所描述的 OpenML 组件的思想重写前面的例子,以展示我们在实验中可能获得的收益。
因此,我们可以组合各种不同的任务、流程,它们是独立的操作。然后,运行可以将任何这样的任务和流配对,以构建一个 ML 工作流并返回评估的分数。这种方法可以帮助我们一次性定义这样的组件,并且我们可以将其扩展到数据集、模型的任何组合,以及将来的任何数量的评估。想象一下,如果整个 ML 社区定义这样的任务和他们在日常实践中使用的各种简单到复杂的流程。我们可以构建定制的 ML 工作流水线,甚至可以将我们的技术在同一个任务上的表现与其他人进行比较!OpenML 正是以此为目标。在这篇文章的下一部分,我们将触及 OpenML 的表面,看看我们是否真的可以用 OpenML 做它承诺的事情。
使用 OpenML
OpenML-Python 可以使用 pip 或者通过克隆 git repo 并安装当前开发版本来安装。那么我们应该安装 OpenML 吗?;)如果在阅读本文时试用代码片段,将会非常有益。包含所有代码的 Jupyter 笔记本可以在这里找到。
现在我们已经有了 OpenML,让我们直接来弄清楚如何从那里获得 Iris 数据集。我们可以随时浏览 OpenML 网站搜索 Iris。那是一条容易的路线。让我们熟悉编程方法,并学习如何钓鱼。OpenML-Python API 可以在这里找到。
从 OpenML 中检索虹膜
在下面的例子中,我们将列出 OpenML 中所有可能的数据集。我们可以选择输出格式。我将使用数据框架,这样我们就可以获得一个熊猫数据框架,并且可以得到一个简洁的表格表示来搜索和排序特定的条目。
列名表明它们包含关于每个数据集的元信息,在这种情况下,我们可以访问由数据帧形状表示的 2958 数据集。我们将尝试在名称列中搜索“虹膜,并使用版本列对结果进行排序。
好的,所以版本为 1 的虹膜数据集的 ID 为 61 。为了验证,我们可以在网站上查看数据集 ID 61 。我们可以看到,我们感兴趣的是原始的虹膜数据集——3 类 50 个实例,具有 4 个数字特征。然而,我们将按照承诺,以编程方式检索相同的信息。
有了合适的数据集,让我们简单回顾一下我们之前讨论过的术语。到目前为止,我们只使用了数据集组件。数据集组件与任务组件紧密相连。重申一下,任务将描述如何使用数据集。
从 OpenML 中检索相关任务
我们将首先列出 Iris 数据集的所有可用任务。然而,我们只是将 Iris 视为一个监督分类问题,因此将相应地进行过滤。接下来,我们将只收集与我们相关的任务的任务 id。
这也解决了任务组件。请注意,对于一个数据集 (61),我们获得了 11 个我们感兴趣的任务 id。这应该说明了数据集-任务组件可以具有的一对多关系。我们还有 2 个组件需要探索— 流、运行。我们可以列出所有可能的流,过滤出我们想要的,即随机森林。然而,让我们取而代之的是使用我们上面收集的 11 个任务在 Iris 数据集上进行的所有评估。
随后,我们将使用上传/使用最多的基于 scikit-learn 的任务。然后,我们将根据是否使用了随机森林,从所选任务中进一步筛选出评估列表(在本例中为 task_id= 59 )。
从 OpenML 中检索性能最佳的模型
因为我们是一群雄心勃勃的 ML 从业者,他们只满足于最好,也因为如果不匹配或击败最先进的技术,大多数结果将不会被认为是值得努力的。我们将根据分数或’值 ’ 对过滤后的结果进行排序,然后从那个运行—任务和流程中提取组件。
好吧,让我们暂停一下,重新评估一下。从全球多个将跑步上传到 OpenML 的用户来看,对于 Iris 上的随机森林跑步,目前看到的最好成绩是 96.67% 。这当然比我们当初构建的幼稚模型要好,以达到 95.33% 。我们使用了一个基本的 10 重交叉验证来评估一个最大深度为 2 的 10 棵树的随机森林。让我们看看最佳跑步使用了什么,以及它是否与我们的方法不同。
显然,我们最初的方法在两个方面是不同的。我们没有明确使用分层抽样进行交叉验证。而随机森林超参数也略有不同( max_depth=None )。这听起来绝对像是一件要做的事情,然而,我们没有理由把自己限制在随机森林中。记住,我们的目标是大这里。考虑到 OpenML 用户的数量,肯定有人在 Iris 上用其他模型得到了更好的分数。然后让我们检索这些信息。当然是程序性的。
总之,我们现在将根据任务定义,使用 task_id=59 对 Iris 数据集上所有基于 scikit-learn 的模型的性能进行排序。
在所需任务上运行最佳性能流程
瞧啊!我们达到了神奇的数字。我个人从来没有尝试过 NuSVC,并且一直在调整随机森林的超参数。这无疑是一个新的发现。我想知道是否有人在 Iris 上尝试过 XGBoost?
无论如何,我们现在可以使用以下代码将这次运行的结果上传到 OpenML:
r.publish()
人们需要登录到https://www.openml.org/并生成他们各自的 apikey 。然后,结果将可供每个人查看,谁知道呢,你可以在 Iris 数据集上用你的名字来对比有史以来最好的性能!
这篇文章并不打算成为 OpenML 的终极指南。主要目标是帮助形成对 OpenML 术语的了解,介绍 API,建立与一般 ML 实践的联系,并让我们先睹为快作为一个社区一起工作的潜在好处。为了更好地理解 OpenML,请浏览文档。如果你想继续这篇文章中给出的例子并进一步探索,请参考 API 。
OpenML-Python 是一个开源项目,非常欢迎每个人以问题和请求的形式做出贡献。对 OpenML 社区的贡献实际上不仅限于代码贡献。每一个用户都可以通过使用 OpenML 共享数据、实验和结果来丰富社区。
作为 ML 从业者,我们可能依赖工具来完成我们的任务。然而,作为一个集体,我们可以在更大程度上挖掘其潜力。让我们一起,让 ML 更透明,更民主!
特别感谢 Heidi 、bulge、 Sahithya 、 Matthias 、 Ashwin 的想法、反馈和支持。
参考链接:
OpenPose,PNASNet 5 进行姿势分类比赛(Fastai)
我最近参加了一个当地的人工智能比赛,挑战包括 15 个不同类别的人体姿势分类。这是我第一次参加人工智能比赛,这是一次令人羞愧的经历。基于我们的模型准确性、创造力和团队合作,我的团队获得了亚军。我肯定会推荐学习者参加竞赛或黑客马拉松,因为它们是一个很好的网络平台和训练场地,可以磨练你的技术技能。在这里,我将向您介绍我们的模型构建过程,该过程最终帮助我们在最终测试集上实现了 83%的高准确率。
我们面临的挑战是开发一种图像分类算法,可以区分 15 种不同的人类姿势。
姿势是:
椅子式、儿童式、轻拍式、手枪式、握手式、HulkSmash 式、KoreanHeart 式、KungfuCrane 式、KungfuSalute 式、敬礼式、战士式、鹰式、胸部撞击式、高跪式和蜘蛛侠式
根据竞赛条款和条件,我们无权发布数据集。因此,以下所有图片都是我们在比赛期间拍摄的。
Left to Right— KoreanHeart, KungfuCrane, HandShake
训练数据集中的每个类包含大约 100 幅图像,而验证集中的每个类有 25 幅图像。对于 15 个类别的分类任务来说,这是相对少量的数据,说明了我们需要通过拍摄自己的图像来增加数据集。
penPose 是一种人体姿态估计和特征提取步骤,用于检测图像中的人体。使用该模型来标识各个身体部位的关键点,并且可以绘制连接这些关键点的人体骨架。从每幅图像中提取人体姿态作为预处理步骤,以减少数据中的噪声。
通过大量参考这个站点,我们使用预先训练好的 MPII 模型生成了每张图像的关键点。
cwd = os.getcwd()# Specify the paths for the 2 files
protoFile = "{}/pose_deploy_linevec_faster_4_stages.prototxt".format(cwd)
weightsFile = "{}/pose_iter_160000.caffemodel".format(cwd)
nPoints = 15
POSE_PAIRS = [[0,1], [1,2], [2,3], [3,4], [1,5], [5,6], [6,7], [1,14], [14,8], [8,9], [9,10], [14,11], [11,12], [12,13] ]
# Read the network into Memory
net = cv2.dnn.readNetFromCaffe(protoFile, weightsFile)frameWidth = 640
frameHeight = 480
threshold = 0.1# Forward training set into OpenPose model to generate outputinWidth = 299
inHeight = 299m = train_images.shape[0]
train_outputs = np.zeros((1,44,38,38))for i in range(m):
inpBlob = cv2.dnn.blobFromImage(train_images[i], 1.0/255, (inWidth, inHeight),(0, 0, 0), swapRB=True, crop=False)net.setInput(inpBlob)
output = net.forward()
train_outputs = np.vstack((train_outputs,output))
outputs = np.delete(train_outputs,(0),axis=0)
H = train_outputs.shape[2]
W = train_outputs.shape[3]
print(train_outputs.shape)# Generate keypoints for training set
m = 973
H = 38
W = 38train_points = np.zeros((m,15,2))for sample in range(m):
for i in range(nPoints):
# confidence map of corresponding body's part.
probMap = train_outputs[sample, i, :, :]# Find global maxima of the probMap.
minVal, prob, minLoc, point = cv2.minMaxLoc(probMap)# Scale the point to fit on the original image
x = (frameWidth * point[0]) / W
y = (frameHeight * point[1]) / H
if prob > threshold :
train_points[sample,i,0] = int(x)
train_points[sample,i,1] = int(y)
接下来,使用存储在变量 train_points 中的关键点,在每幅图像上绘制一个人体骨架。
# Processed images with sticks on original image
train_processed = np.copy(train_images).astype(np.uint8)for sample in range(m):
for point in range(nPoints):
if train_points[sample,point,0] !=0 and train_points[sample,point,1] !=0 :
cv2.circle(train_processed[sample], (int(train_points[sample,point,0]), int(train_points[sample,point,1])), 10, (255,255,0), thickness=-1, lineType=cv2.FILLED)
# draw lines
for pair in POSE_PAIRS:
partA = pair[0]
partB = pair[1]if train_points[sample,partA,0] != 0 and train_points[sample,partA,1] != 0 and train_points[sample,partB,0] != 0 and train_points[sample,partB,1] != 0:
cv2.line(train_processed[sample], (int(train_points[sample,partA,0]),int(train_points[sample,partA,1]))
, (int(train_points[sample,partB,0]),int(train_points[sample,partB,1])), (255,255,0), 3)# Processed images with sticks on a black backgroundtrain_processed_grey = np.zeros((m,train_images.shape[1],train_images.shape[2],1)).astype(np.uint8)for sample in range(m):
for point in range(nPoints):
if train_points[sample,point,0] !=0 and train_points[sample,point,1] !=0 :
cv2.circle(train_processed_grey[sample], (int(train_points[sample,point,0]), int(train_points[sample,point,1])), 10, (1), thickness=50, lineType=cv2.FILLED)
# draw lines
for pair in POSE_PAIRS:
partA = pair[0]
partB = pair[1]if train_points[sample,partA,0] != 0 and train_points[sample,partA,1] != 0 and train_points[sample,partB,0] != 0 and train_points[sample,partB,1] != 0:
cv2.line(train_processed_grey[sample], (int(train_points[sample,partA,0]),int(train_points[sample,partA,1]))
, (int(train_points[sample,partB,0]),int(train_points[sample,partB,1])), (1), 3)
通过这一步,我们获得了 3 个不同的数据集;
- 原象
- 原始图像+骨架叠加
- 背景空白的骨架
T 转移学习允许我们使用比从头开始训练算法所需的数据少得多的数据来训练深度神经网络。它还经常导致更高精度的模型,因为来自大数据集的信息被转移和训练以适合我们的数据。对于这次比赛,我的团队决定测试 3 个预训练模型的性能,即 ResNet-50、ResNeXt-101 和 PNASnet-5。所有模型都是使用 fastai 库构建的。
import fastai
from fastai.metrics import error_ratefrom torchvision.models import *
import pretrainedmodels
from fastai.callbacks.tracker import SaveModelCallback
from fastai.vision import *
from fastai.vision.models import *
from fastai.vision.learner import model_metabs = 8# Importing of datasetdata = ImageDataBunch.from_folder(base_dir,train='train',valid='val', ds_tfms = get_transforms(), size =299, bs=bs).normalize(imagenet_stats)#ResNet-50
models.resnet50#ResNeXt-101def resnext101_64x4d(pretrained=True):
pretrained = 'imagenet' if pretrained else None
model = pretrainedmodels.resnext101_64x4d(pretrained=pretrained)
all_layers = list(model.children())
return nn.Sequential(*all_layers[0], *all_layers[1:])#PASNet-5def identity(x): return xdef pnasnet5large(pretrained=True):
pretrained = 'imagenet' if pretrained else None
model = pretrainedmodels.pnasnet5large(pretrained=pretrained, num_classes=1000)
model.logits = identity
return nn.Sequential(model)# Training of modellearn = cnn_learner(data, model, metrics = accuracy)learn.fit(20,callbacks=[SaveModelCallback(learn,monitor='accuracy',every="improvement",name ="top_acc")])learn.lr_find()
learn.recorder.plot()learn.unfreeze()
learn.fit_one_cycle(5,callbacks=[SaveModelCallback(learn,monitor='accuracy',every="improvement",name="top_acc_1")])
我们总共构建了 9 个模型,每个模型都用我们生成的数据集进行了预训练。以下是结果;
对于最终的测试集,我们使用在原始模型上训练的 PNASnet-5 模型预测了未知数据集的分类,并获得了 83%的准确率,使我们在比赛中获得了第三名。
这就是使用 PNASnet-5 预训练模型的人体姿势分类。令人失望的是,OpenPose 特征提取没有提高模型的准确性,但我相信在比赛的时间限制下,我们做得很好。对于那些想知道 PNASnet-5 如何比其他预训练模型表现得更好的人,下面是作者对算法的总结。
https://cs.jhu.edu/~cxliu/posters/pnas_poster.pdf
R-指派问题的运筹学
r 代表工业工程师
探索“LP solve”R包
Image by Momentista available at Unsplash
分配问题
指派问题是线性规划问题的特例;它是数学中最优化或运筹学分支中的基本组合优化问题之一。它的目标在于将 m 资源(通常是工人)一对一地分配给 n 任务(通常是工作),同时最小化分配成本。一般来说,所有的工作都必须由一个工人来完成,并且每个工人都必须被指派专门的工作。任何工人都可以被指派执行任何工作,产生一些费用,这些费用可能因工作任务的不同而不同。
基本符号:
- m =职工人数( i = 1 … m
- n =工作数量( j = 1 … n
- c i,j =将工人 i 分配到工作 j 的单位成本
- x i,j =分配给作业 j 的工人 i (如果分配则为 1,否则为 0)
注: m (工作人数)必须等于 n (工作人数)。
配方:
LP Assignment Problem — Formulation
LP Assignment Problem — Diagram
来自 R 的 lpSolve 包包含了解决线性规划指派问题的特定函数。对于下面的例子,让我们考虑下面要求解的数学模型:
LP Assignment Problem — Example
我们来看看 R 代码!
Assignment Problem R Code
解决方案:
LP Assignment Problem — Solution
总分配成本:27 美元
上表显示了在满足约束条件的情况下,分配给工作 j 的工人 i 的最佳组合。必须分别将员工 1 分配给职务 2,将员工 2 分配给职务 1,将员工 3 分配给职务 3。没有其他可能的分配组合会导致更低的分配成本。
总结想法
指派问题代表了用于以最佳方式分配资源(主要是劳动力)的线性规划问题的特殊情况;对于运营和项目经理来说,这是优化成本的一个非常有用的工具。LP solve R 包允许我们只用很少几行代码就能解决 LP 赋值问题。虽然有其他免费的优化软件(如 GAMS、AMPL、TORA、LINDO),但在您的个人代码库中存储 LP 分配问题 R 代码可以节省您大量的时间,因为您不必从头开始编写公式,而只需更改相应矩阵的系数和符号。
— —
如果你觉得这篇文章有用,欢迎在 GitHub 上下载我的个人代码。你也可以直接在 rsalaza4@binghamton.edu 给我发邮件,在LinkedIn上找到我。有兴趣了解工程领域的数据分析、数据科学和机器学习应用的更多信息吗?通过访问我的媒体 个人资料 来探索我以前的文章。感谢阅读。
罗伯特
R-运输问题的运筹学
r 代表工业工程师
探索“LP solve”R包
Image by iplenio available at HDqwalls
运输问题
运输问题是一种特殊类型的线性规划问题,其中目标在于最小化给定商品从多个来源或起点(例如工厂、制造设施)到多个目的地(例如仓库、商店)的运输成本**。每个来源都有有限的供应(即可以从其发送的最大数量的产品),而每个目的地都有需要满足的需求(即需要运送到其的最小数量的产品)。从源头到目的地的运输成本与运输的数量成正比。**
基本符号:
- m =信号源数量( i = 1 … m )
- n =目的地数量( j = 1 … n )
- c i,j =从来源地 i 到目的地 j 的单位运输成本
- x i,j =从来源 i 运送到目的地 j 的金额
- a i =源头供应 i
- b j =目的地需求 j
LP Transportation Problem Diagram
源由行表示,而目的地由列表示。一般来说,一个运输问题有 m 行和 n 列。如果恰好有( m + n -1)个基本变量,问题是可解的。
LP Transportation Problem Simplex Tableau
运输问题的类型
基于初始给定的信息,有两种不同类型的运输问题:
- **均衡运输问题:**总供给等于总需求的情况。
- **不平衡运输问题:**总供给不等于总需求的情况。当供给高于需求时,在等式中引入一个虚拟目的地,使其等于供给(运输成本为 0 美元);超额供应被认为会进入库存。另一方面,当需求高于供应时,在等式中引入一个虚拟源,使其等于需求(在这些情况下,不满足需求通常会产生惩罚成本)。
为了着手解决任何给定的运输问题,第一步是检验它是否平衡。如果不是,就要相应的平衡。
R 的 lpSolve 包包含了求解线性规划运输问题的特定函数。对于下面的例子,让我们考虑下面要求解的数学模型:
LP Transportation Problem — Mathematical Model
LP Transportation Problem — Simplex Tableau
我们来看看 R 代码!
Transportation Problem R Code
解决方案:
LP Transportation Problem Example — Solution
总运输成本:435 美元
上表显示了在满足供需约束的情况下,从供应商 i 到客户 j 的最优产品组合。没有其他可能的变量组合会导致更低的运输成本。
总结想法
运输问题代表了用于以最佳方式分配资源的特定类型的线性规划问题;对于经理和供应链工程师来说,这是一个优化成本的非常有用的工具。LP solve R 包只需要几行代码就可以解决 LP 运输问题。虽然有其他免费的优化软件(如 GAMS、AMPL、TORA、LINDO),但在你的个人代码库中存储一个 LP 运输问题 R 代码可以节省你大量的时间,因为你不必从头开始编写公式,而只需改变相应矩阵的系数和符号。
— —
如果你觉得这篇文章有用,欢迎在GitHub上下载我的个人代码。你也可以直接在 rsalaza4@binghamton.edu 给我发邮件,在LinkedIn上找到我。有兴趣了解工程领域的数据分析、数据科学和机器学习应用的更多信息吗?通过访问我的媒体 简介 来探索我以前的文章。感谢阅读。
-罗伯特
阿片类药物危机:政府在做什么?
现实世界中的数据科学
NIH 如何资助与阿片类药物相关的研究
如果你一直生活在岩石下,美国一直面临着巨大的公共健康危机。大约在 2006 年至 2012 年的高峰期,处方阿片类药物危机导致近 10 万人死亡(据《华盛顿邮报》报道)。
美国卫生与公众服务部(HHS)已经加大了各种努力,以打击用药过量,提高公众意识,并控制处方阿片类药物的供应。今天,我们想特别关注一下联邦政府是如何研究危机的各个方面的。你可以在这里找到这篇文章的代码,它涉及到更多的技术细节:https://github.com/TheLastQuestion/nihOpioidData。
数据
每年,美国国立卫生研究院、国家科学基金会和其他联邦机构通过数百亿美元的拨款资助大约 100,000 个科研项目。关于受资助项目、赞助机构和受资助研究性质的数据可在 https://federalreporter.nih.gov下载。
NIH 每年在阿片类药物研究项目上花费多少?
项目术语字段提供了一个指示器,指示哪些项目与阿片类药物有关。NIH 在 2018 财年花费了 5.64 亿美元,占 NIH 在 2018 财年投入的以“阿片类药物”为关键术语的研究项目的 330 亿美元的 1.7%。在过去的几个财年中,这一研究领域在项目数量和总拨款方面都有了显著增长,从 2008 年到 2015 年,这一领域在 NIH 研究组合中所占的比例一直保持稳定。
哪些类型的项目属于“阿片类药物”范畴?
阿片类药物相关项目仅占过去十年 NIH 资助项目总数的 1%左右[注:实际数据是 11 个财政年度的项目]。但是对于一个人来说,它们仍然太多了,无法通读和综合。这就是自然语言处理可以助一臂之力的地方!
每个联邦记者项目都有一段很长的摘要(除了少数缺失的记录)。一种无监督的机器学习方法,称为“主题建模”,可以帮助我们摄取所有这些简单语言的摘要,然后根据这些摘要共有的和没有共有的单词将它们聚类成主题(更多技术细节见链接代码)。运行我们的模型将摘要分成 10 个主题,得到如下分布。
也许不出所料,最大的摘要集将健康研究术语(例如,“试验”、“试点”、“调查者”和“大学”)作为其最流行的主题。当然,这些只是对我来说有意义的标签——主题建模只提供最好地描述一个主题的单词列表,并在数学意义上将其与其他主题区分开来。解释是留给人类的(在链接的代码中有更多关于这个主题的说明)。
用这种方法发现的其他主题似乎涉及:
2)处方阿片类药物有助于解决的病症(疼痛、镰状细胞病、癌症、炎症……)
3)阿片类药物与 HIV 和其他免疫系统相关感染的交叉,
4)阿片类药物滥用的康复途径(戒断、渴求、结果、美沙酮…),
5)阿片样物质作用和滥用的分子基础(κ、配体、拮抗剂…),
6)神经系统相关(神经、抑制、通道、脊髓…),
7)不同的患者群体(退伍军人、孕妇、儿童、老人…),
8)抑郁和焦虑,
9)与阿片类药物(谷氨酸盐、γ-氨基丁酸、摄入……)相关的细胞机制,以及
10)阿片类药物与其他物质(吸烟者、烟草、注射、物质使用)的重叠。
随着时间的推移,阿片类药物的研究组合发生了怎样的变化?
现在我们有了一个粗略的方法来描述过去十年中资助了哪些类型的阿片类药物相关研究,我们可以检查这种组合是否随着时间的推移而发生了变化。
我们的分析表明,提及特定患者人群的项目最近流行率增加,而神经系统相关项目略有下降。但是,请注意,这只是阿片类药物标记项目的百分比趋势。就数量而言,在我们有数据可查的过去三个财年中,所有以阿片类药物为主题的家庭获得资助的项目数量都有所增加。
Project counts by topic over time
阿片类药物项目获得的资助金额与哪些因素有关?
对主题、组织状态和控制预算随时间的增长对财年成本进行线性回归,我们观察到与主题 4(“恢复之路”主题)相关的项目与第一个主题(“健康研究术语”)中的项目相比,增加了 100,000 美元。其他主题或者与第一个主题相比成本更低,或者与第一个主题没有显著差异(即 p 值超过 0.05)。
Truncated table of regression coefficients sorted by lowest p-value then highest coef value
与佛蒙特州和俄克拉荷马州组织相关的阿片类药物项目的项目成本/资金溢价最高。与这些州的组织相关联的项目比基线项目成本多 700,000 美元(在这种情况下,以阿拉巴马州相关联的项目为代表)。然而,请注意,这些州的数据相对较少——OK 组织只有 7 个阿片类药物项目,而 VT 组织只有 23 个。
结束
正如媒体记录的那样,阿片类药物的流行给美国家庭和社区带来了巨大而痛苦的代价。通过分析国家卫生研究院的资金数据,我们发现了联邦政府对此正在做些什么的几个答案。
1)研究滞后于当前事件——尽管阿片类药物危机(就死亡率而言)在 21 世纪后期已经开始,但 NIH 的阿片类药物相关研究组合直到很久以后才出现资金激增,大约从 2016 年开始。这种激增表现为获得阿片类药物项目的数量以及获得阿片类药物项目的美元的增加。
2)使用自然语言处理和主题建模,我们观察到涉及特定患者亚组的研究越来越重要。然而,从整体上看,过去 11 个财政年度的多个阿片类药物项目往往涉及阿片类药物的处方条件、艾滋病毒和其他感染以及依赖性和康复。
3)虽然项目总成本往往不会因主题领域的不同而有很大差异,但那些与复苏之路相关的项目似乎比大多数其他主题的项目获得了大约 100,000 美元的资助。某些国家的组织往往有较高的项目成本,但这可能是那些获得阿片类药物项目赠款相对较少的组织的人为因素。
*这篇文章和附带的分析不是美国联邦政府的官方观点。
最佳控制:LQR
在最优控制问题中吃掉你的蛋糕
在这篇文章中,我将谈论最优控制。更具体地说,我将谈论令人难以置信的令人敬畏的线性二次调节器,它在最优控制领域中经常使用,并且还将讨论最优控制和最近大肆宣传的强化学习之间的一些相似之处。令人着迷的是,它们的名称不同,但它们在连续的决策过程中处理类似的问题。也就是说,给读者一个友好的数学警告:
这篇文章包含了一些线性代数和微积分,但是不要惊慌,它很简单,你可以做到。
既然我们已经解决了这个问题,让我们开始吧。首先让我们定义一个一般的最优控制问题,或者更好地说一个最优化问题。这仅仅意味着我们想要最大化或最小化某个函数,该函数受变量的某些约束。典型的最优控制问题如下所示:
这是非常直接的,最小化一个函数***【f】***服从一些约束(s.t .是 subject to 的简称)。现在,在优化世界里,基于目标函数的样子和约束,这可能是任意困难的。当然,约束可以是基于问题的等式约束或不等式约束。不用说,优化问题中的非凸函数很难优化,但是在凸函数的情况下,我们可以高效快速地解决问题。无论如何,它是如此重要,以至于你在问题中寻找凸性的反应应该是这样的:
在控制问题中,我们优化我们的轨迹,以最小化成本函数,或者更确切地说,最大化回报,就像在强化学习中所做的那样。自然地,环境的动态,即基于当前动作和当前状态给出我们下一个状态的函数,是优化约束的一部分。因此,我们可以将控制优化问题写成如下:
这是直到 n 的有限范围的情况。让我们简单地分解它。x 是我们在每个时间步的状态变量,是我们的动作。 E 将是最终状态的最终成本, g 每个状态-动作对的成本函数。 x 条是我们想要优化的起始状态,而 f 是我们的动力学函数。在这种情况下,我们没有不等式约束。事实证明,如果我们的函数 f 是一次函数xu而函数 g 是二次函数和 u ,这就让问题简单了很多。这就是我们如何得出线性二次调节器问题的定义:**
这里, Q , R 和 E 是定义我们多项式系数的代价矩阵。我们也可以用分块矩阵表示法写出每个时间步长的成本,以使表达式更简单:
In the upper case we leaved out the S or better to say we assumed that S = 0, but this doesn’t change the math greatly, S can also be some kind of matrix for interplay between x and u in the cost function.
我们将利用最优性原理,该原理陈述了一个自然事实,即如果在 A 点和 C 点之间有一条最优路线,如果我们在这条路线上选择 B 点,那么从 A 到 B 的子路线也是从 A 到 B 的最优路线。基于此,我们可以递归地定义我们轨迹的最优剩余成本,或总成本。这就是我们如何得出汉密尔顿-雅可比-贝尔曼方程的:
其中 J star 是我们的最佳出发成本。在我们的例子中,我们将目标函数描述为一个多项式函数,所以从逻辑上来说,我们可以假设我们的最佳行驶成本是一个多项式函数,我们可以这样写:
根据我们对优化问题的定义,逻辑上我们的最终成本如下:
现在,如果我们把函数 g 的定义和环境动力学代入贝尔曼方程,我们会得到这样的结果:
由于二次成本假设,我们如何找到这个函数的最小值?很简单,我们取相对于 u 的梯度,并使其等于 0,我们将所有项组合成一个大的中心矩阵:
为了节省空间,我们用下列矩阵代替这些术语(这是不言自明的):
将所有内容相乘后,只看包含的项,因为我们要对求导,所以我们得到以下中间结果:**
在计算梯度和重新排列之后,我们得到 u star 的表达式,它使成本最小化,即最优操作:
或许可以思考一下这个问题。这是什么意思?这意味着我们有最优行动的封闭解!这真是太棒了。那么我们需要什么来解决这个问题呢?我们需要时间步长 k+1 的矩阵 P。我们可以根据以下等式,从上一时间步开始递归计算:
这也是众所周知的代数黎卡提方程。在我们想要一个不动点解的情况下,对于无限长的地平线,方程可以求解一个固定的 P. 在这种情况下,我们甚至不需要一个递归。我们只是免费得到最优反馈控制。
基本上就这些了。你不得不欣赏 LQR 的力量。当然,许多问题不能简化为线性动力学,但是如果我们进行简化,我们会得到什么样的解决方案是令人惊讶的。这种方法甚至用在我们的动力学是非线性的情况下,通过泰勒展开使它们在固定点附近线性化。这是一种在复杂问题的轨迹优化中经常使用的方法,称为微分动态规划(DDP),其一个实例是 iLQR(迭代 LQR),go figure。
既然你获得了一些 LQR 赋,你就获得了理解最优控制中许多事情的工具。
我希望 LQR 的这个解释能让你有所启发。这是一个非常简单而强大的概念,也是许多最优控制算法的基础。
最佳估计算法:卡尔曼和粒子滤波器
介绍卡尔曼和粒子滤波器及其在机器人和强化学习等领域的应用。
Photo by Daniel Jerez on Unsplash
最优估计算法
最优估计算法在我们的日常生活中起着非常重要的作用。今天,我将使用一些实际示例向您介绍其中的两种(卡尔曼滤波器和粒子滤波器)。
让我们想象一下,我们正驾驶着一辆无人驾驶汽车,我们即将穿过一条长长的隧道。在这个例子中,我们的汽车使用不同的传感器,如 GPS 估计、加速度计和摄像头,以便跟踪它在地图中的位置以及它与其他车辆或行人的交互。尽管如此,当在隧道中行驶时(特别是在一个很长的隧道中),我们的 GPS 信号会因为干扰而变弱。因此,我们的汽车估计它的位置可能变得更加困难。为了解决这个问题,我们能做些什么呢?
一个简单的解决方案是将我们的加速计传感器数据与微弱的 GPS 信号结合使用。事实上,对我们的加速度进行二重积分,我们就能计算出我们的车的位置。虽然这种简单的测量会包含一些漂移,因此不会完全准确,因为我们的测量误差会随着时间传播(图 1)。为了解决这个问题,我们可以使用卡尔曼滤波器或粒子滤波器。
Figure 1: Autonomous car position estimation against time
卡尔曼滤波器
卡尔曼滤波器在机器人学(例如 SLAM 系统)和强化学习中有常见的应用。卡尔曼滤波器可用于 Robotis,以跟踪环境中一群机器人的运动,也可用于强化学习,以跟踪不同的软件代理。
卡尔曼滤波器是一种迭代数学过程,当测量值包含不确定性或误差时,它使用一组方程和连续数据输入来估计物体的真实位置、速度等。[1]
因此,卡尔曼滤波器可以简化为机器学习模型。他们获取一些输入数据,执行一些计算以进行估计,计算其估计误差,并反复重复该过程以减少最终损失。卡尔曼滤波器执行的迭代过程可以总结为 3 个主要步骤:
- 卡尔曼增益计算:利用输入数据和估计中的误差进行计算。
- 当前估计计算:使用原始输入数据、我们先前的估计和卡尔曼增益进行计算。
- 估算误差计算:最终使用卡尔曼增益和我们当前的估算值进行计算。
图 2 简要总结了这一过程。
Figure 2: Kalman Filter WorkFlow (Adapted from [1])
存在不同种类的卡尔曼滤波器,一些例子是:线性卡尔曼滤波器、扩展卡尔曼滤波器和无迹卡尔曼滤波器。如果你对卡尔曼滤波器更详细的数学解释感兴趣,麻省理工学院托尼·莱西的这个教程是一个很好的起点。
卡尔曼滤波器的一个主要问题是,它们只能用于模拟可以用高斯噪声描述的情况。尽管许多非高斯过程可以用高斯项来近似,或者通过某种形式的变换(如对数、平方根等)转换成高斯分布…).
为了克服这种类型的限制,可以使用另一种方法:粒子滤波器。
粒子过滤器
可以使用粒子滤波器来解决非高斯噪声问题,但是粒子滤波器通常比卡尔曼滤波器在计算上更昂贵。这是因为粒子滤波器使用模拟方法而不是分析方程来解决估计任务。
粒子过滤器通常用于:
- 金融市场分析(特别是在随机过程分析
- 强化学习
- 机器人本地化(例如直接全局策略搜索)
粒子滤波器基于蒙特卡罗方法,通过将原始数据离散成粒子(每个粒子代表一个不同的状态)来处理非高斯问题。粒子数量越多,我们的粒子过滤器就越能更好地处理任何可能的分布类型。
像卡尔曼滤波器一样,粒子滤波器也利用迭代过程来产生它的估计。每次迭代可以分为三个主要步骤[3]:
- 从原始分布中取出多个样本( 粒子 )。
- 按照重要性的顺序对所有采样粒子进行加权(在给定间隔内落下的粒子越多,它们的概率密度就越高)。
- 通过用更可能的粒子替换更不可能的粒子进行重采样(就像在进化算法中,只有种群中最适合的元素才能存活)。
图 3 总结了这一过程。正如我们可以从下图中看到的,在这个例子中,我们的粒子过滤器能够在一次迭代后了解哪个范围更可能是我们的对象。反复重复这个过程,我们的滤波器将能够进一步限制其色散范围。
Figure 3: Single Particle Filter Iteration
如果你对用 Python 实现最优估计算法感兴趣,那么 FilterPy 或 Pyro 库是两个很好的解决方案。特别地,Pyro 是由优步开发的通用概率编程语言,其可以使用 PyTorch 作为后端用于各种贝叶斯分析。
我希望你喜欢这篇文章,谢谢你的阅读!
联系人
如果你想了解我最新的文章和项目,请通过媒体关注我,并订阅我的邮件列表。以下是我的一些联系人详细信息:
文献学
[1]专题—简单示例(单个测量值)的卡尔曼滤波器(55 个中的第 2 个)流程图,Michel van Biezen。访问地点:https://www.youtube.com/watch?v=CaCcOwJPytQ
[2]第十一章。教程:卡尔曼滤波器,托尼莱西。访问网址:http://web . MIT . edu/kirt ley/kirt ley/binlustuff/literature/control/Kalman % 20 filter . pdf
[3]粒子滤波器和蒙特卡罗定位简介,Cyrill Stachniss。访问网址:http://ais . informatik . uni-freiburg . de/teaching/ws12/mapping/pdf/slam 09-particle-filter-4 . pdf
黑洞成像的最优实时调度
为了观测黑洞,如何协调 11 台望远镜?
队员:、、子怡()周
本文的主要目的是分享作者在哈佛大学应用计算科学研究所(IACS)John a . Paulson 工程和应用科学学院的顶点课程项目中的发现和贡献。他们的顾问是塞西莉亚·加拉夫和帕夫洛斯·普罗托帕帕斯。在这个跨越整个学期的项目中,我们与事件视界望远镜 (EHT)合作,对人类发现宇宙产生影响。
你可能以前见过这张著名的图片——人类历史上第一张黑洞的图片。2019 年 4 月 10 日,EHT 发布了这张照片,他们获得了 2020 年基础物理学突破奖。
谢泼德·多勒曼是 EHT 的创始董事之一。在拍摄完黑洞的照片后,他找到了顶点计划的主要指导者 Pavlos Protopapas,寻求帮助。
他说,为了实现黑洞图像的高分辨率,他们使用了甚长基线干涉测量技术,其中全球各地的无线电碟形天线同步形成一个虚拟望远镜,具有目前从地球表面可能达到的最高角分辨率。这个分辨率有多高?这相当于坐在波士顿时能够在洛杉矶阅读一份报纸,或者相当于能够看到一臂之遥的一个原子。为了以这种方式运行,“EHT”号要求阵列的大部分地区同时有相当好的天气。目前该阵列中有 11 个天线。一些地方的观测条件可能非常好,但是如果由于其他地方天气不好,没有足够的望远镜可以参与,观测就无法进行,因为它们不会产生高质量的数据。
然而,操作这些巨型望远镜非常昂贵,科学家们不断争夺观测时间,因此 EHT 每年只有 10 天的时间,可供望远镜一起使用。每一年,10 天的窗口都是不同的。不仅如此,在这 10 天的窗口中,由于其他一些限制,他们只能触发 5-6 晚。目前,他们团队中的一个人,也就是 Shep,手动决定是否触发夜晚。他通过给他在每台望远镜前工作的朋友打电话,问他们:“你对天气有什么看法?”
你可能知道,当前的决策过程并没有达到应有的效率和深度。因此,Shep 希望我们建立一些实时算法,可以促进他的决策过程。我们的目标是最大化高质量黑洞照片的数量。给定天气数据和日期信息,算法应该随时提出建议,即是否在当天触发,以及未来剩余几天的最佳策略。总的来说,我们只能从连续 10 天中选择 5 天。
如果可能的话,EHT 还希望我们的模型输出置信水平和次优策略。
下面是这个问题的一个演示。x 轴表示 10 天窗口中的日期,而 y 轴表示到目前为止已经触发的天数。在每一天,如果我们决定在第二天触发,我们在对角线上向上移动,如果我们建议跳过第二天,我们在水平方向上移动。最终,我们必须到达顶线中的一个点。这里的绿线显示了一条可能的路径,建议触发 10 月 6、8、10、13 和 14 日。
Solution Space
动机
我们的动机是双重的。目前,EHT 由人类做出决定。如果我们的模型成功了,他们肯定会用它来帮助他们做决定。这对我们来说是一个巨大的动力,因为我们知道通过增加捕捉黑洞的机会,我们也为人类发现宇宙做出了贡献。
数据
我们从 GFS 收集数据,这是国家环境信息中心制作的天气预报模型。它是公开可用的。它提供全球逐层大气预报。你可以把它的数据想象成一个 3D 的形状。每 6 个小时,GFS 产生一组预测,我们提取与我们相关的数据:每个望远镜位置的天气情况。我们通过指定望远镜的经度、纬度和高度来做到这一点。
在我们提取了一些数据后,我们开始了探索性的数据分析过程,并绘制了这张图表。这里有五个图,因为 GFS 一次预测五个变量。在每张图上,你可以看到有一条黑线和七条灰线。这对应于每 6 小时预报的每组天气预报数据。黑线代表最新的预测数据,而灰线是在过去 48 小时内做出的预测。每次预测涵盖未来 16 天。我们可以看到,前 5 天的预报相当准确,但之后就变得非常不确定了。专家告诉我们,第一个变量 Tau-225 是表明大气透明度的最重要的变量,因为它是头顶上方的吸收率。较小的 Tau-225 比较大的 Tau-225 更优选。
Only the first graph of Tau-225 is relevant.
这就是我们得到的所有数据。在与合作伙伴会面和查看数据之前,我们考虑使用强化学习来解决这个问题。然而,在我们与合作伙伴会面并看到数据后,我们意识到这是一个优化问题,我们必须创造性地设计出非常适合它的模型。当我们找不到任何做类似事情的文献或以前的作品时,我们设计了这个基线模型,它作为我们后来创建的所有其他模型的基本框架。
基线模型
我们从强化学习中借鉴了奖励函数的概念。每个望远镜将根据其天气状况获得一个奖励值。每个望远镜的奖励函数被称为小 f。每天都被分配一个奖励值,奖励函数被称为大 f。在基线模型中,我们使用 Tau-225 的预测构建奖励函数。小 f 被定义为在望远镜的观察窗上τ-225 的负期望值。(负号的原因是因为直觉上我们希望奖励值越大越好,但是 Tau-225 总是正的,接近零的时候是最好的。)大 F 被定义为小 F 的一些加权平均值。我们用望远镜的大小作为权重的一部分,因为更大的望远镜在阵列中更重要。我们还在公式中加入了距离矩阵,因为我们希望望远镜分布在地球表面。
Baseline model: formula of the reward functions. Each telescope is represented as i. T_i is the observation of the telescope i. r_i is the diameter of the telescope i. D is the baseline length matrix, which includes pairwise telescopes’ distance information.
一旦我们计算出每天的奖励值,我们就想解决最优化问题。例如,在第 0 天,我们计算从第 1 天到第 10 天的奖励值。由于我们有 5 天的触发时间,并且我们没有使用其中的任何一天,我们找到五个最大的奖励,并查看第 1 天是否是其中的一天。这里,粉色方框代表最大的五个值。在第 1 天,我们有从第 2 天到第 10 天的奖励值。请注意,这些值会更新,因为已经进行了新的天气预报。因为我们已经触发了第一天,我们还有四天的触发时间。我们找到奖励值最大的四天。我们看到第二天在其中一个,所以建议触发第二天。在第 2 天,我们希望在剩余的几天中找到前 3 名奖励。我们看到第三天不在其中。然后在第 3 天,我们继续寻找前 3 个奖励,看看第 4 天是否在其中。
这些是基线模型的基础。现在我们转向考虑不确定性的更先进的模型。不确定性意味着我们只能在一定程度上相信政府统计处的预测数据。我们的合作伙伴多次强调,为了将风险降至最低,他们宁愿早一点而不是晚一点触发观察。
Example for solving the optimization problem
方法一:单一折扣系数
我们考虑的第一种不确定性仅取决于 GFS 对未来多远的预测,即时滞。为了体现这一点,我们可以将每天的奖励乘以一个折扣因子来获得现值。然后执行我们在基线模型中使用的相同优化技术。单一折扣因子被认为是一个超参数,需要从交叉验证中进行调整。
Method 1: Example
方法二:预测罚款
我们认为单一的贴现因子不足以解释未来的不确定性,因此我们引入了不同的不确定性量化来构建第二种方法。在这种方法中,我们基于时间滞后来寻找 GFS 模型准确性的模式。因此,我们使用历史数据来计算基于未来多少天预测的平均误差。我们将结果绘制在左侧,其中 x 轴是未来的天数,y 轴是误差的度量。我们看到,GFS 模型在超过六天后就不那么准确了。就像前面模型中的折扣因子一样,我们对奖励值使用了一个乘法惩罚项。(我们可以通过小 F 值或大 F 值来实现这一点)。惩罚项取决于时滞和一个称为“惩罚水平”的超参数。
Method 2: formula used
方法三:具体时间的预测难度
前两个模型假设不确定性来自时滞。这个模型和下一个模型假设不确定性与预测的具体日期有关。还记得 GFS 在接下来的 16 天中每 6 小时进行一次预测吗?因此,对于每个时间点,都有多个预测。图中的黄色区域以 Tau-225 的最小和最大预测数据为界。
对于这种方法,我们希望找到某个时间点的最新预测,并计算其他预测相对于该最新预测的均方根误差(RMSE)。然后,我们使用与之前类似的公式来获得奖励值,但是这次奖励和惩罚都是针对时间点定制的。
Method 3: formula used
方法 4:正态分布抽样
最后,我们仍然假设每个时间点的不确定性不同,但是我们希望获得与我们建议的最佳路径相关联的置信度。我们假设真实的天气来自正态分布。在蒙特卡罗方法的指导下,我们从分布中随机抽取每个时间点的奖励值足够多的次数,每次都找到一条最优路径。最后,我们总结了路径的频率,得出最佳路径是频率最高的路径。我们还使用它的频率来表示我们对建议路径的置信度。我们相信,如果我们的合作伙伴看到这个数字,他们可以做出更明智的决定。
Method 4: formula used
车型评测
我们通过将不同模型给出的建议路径与实际路径进行比较,对我们的模型进行了回溯测试。这是一个例子。我们对 11 月 9 日至 11 月 18 日的预测数据进行了模拟,因此每个模型都会给我们一个建议路径。我们也知道基本事实路径,所以我们比较了每个模型的平均奖励和最佳路径的分数。在本例中,只有基线法和分布抽样法未能生成最佳路径。缺乏进一步的惩罚导致了一天后的预测。
Example of outputs from models
我们收集了从 10 月 25 日到 11 月 30 日的 GFS 数据,并在每个连续的 10 天窗口中运行模拟。总共有 26 个 10 天的窗口。人们可以把我们在一个 10 天的窗口中收到的所有数据想象成 x,当我们回头看时的平均回报想象成预测的 y。我们可以自然地将我们预测的 y 与最佳路径进行比较,并计算均方误差。我们还计算一个分数,该分数在下面的公式中定义。这是一个相对分数。如果我们的预测路径等于最佳路径,那么它将等于 1。如果我们的预测路径等于随机路径,得分将为 0。
Metrics used to compare models
有了这两个指标,我们就能够决定每种方法的最佳惩罚级别,以及最佳模型。在这里,方法 3 是性能最好的模型,这是意料之中的,因为它包含了每天天气预测方差的不确定性。方法 2 是第二好的方法,因为它只考虑了天气预报在未来多远的不确定性。这里的抽样方法和基线一样好,因为它不包含任何惩罚。然而,它仍然是有用的,因为它是输出所选路径的置信度的唯一模型。
Comparison among models
软件
我们制作了一个软件包,供 EHT 将来使用。该软件包括处理数据、运行优化模型和利用提供的不确定性测量提出建议的程序。
以下是如何使用该软件的演示:
Software Demo
结论
这个项目发展到现在这个阶段并不容易。最初,当我们得到分配的项目时,我们想到了奇特的机器学习模型来解决问题。然而,在看到数据并与合作伙伴会面后,我们意识到一个更简单的模型更适合解决这个问题。有一段时间,从 GFS 中提取的数据中有意外的零,我们花了相当长的时间在合作伙伴的帮助下解决这个问题。构建软件需要我们构建一个图形用户界面(GUI ),并将 GUI 与所有的模型输入和输出连接起来。我们以前没有任何做这种建模的经验,但我们能够学到很多东西,并在最后征服每个概念。我们为这个项目感到非常自豪,并希望它对其他人有用。
优化快速文本模型以提高准确性
快速文本系列
理解精确度和召回率。
最初发表于我的博客。
在我们之前的帖子中,我们看到了什么是 n-grams 以及它们如何有用。在那篇文章之前,我们使用脸书的 fastText 库构建了一个简单的文本分类器。在本帖中,我们将看到如何优化模型以获得更好的准确性。
精确度和召回率
为了更好地理解模型的准确性,我们需要知道精确度和召回率这两件事。而且这两件事也不是很难理解。Precision 是由 fastText 模型预测的正确标签数,recall 是正确标签中成功预测的标签数。这可能有点令人困惑,所以让我们看一个例子来更好地理解它。
假设一句话,我们给模型分类,从我们的栈交换烹饪样本,当然,模型预测标签食品安全,烘焙,设备,替代品和面包。堆栈交换中的实际标签是设备、清洁和刀具。这里,在模型预测的前五个标签中,只有一个是正确的。所以精度变成了 1 / 5,或者 0.20。另外,在三个正确的标签中,模型只正确预测了一个标签(设备),因此召回率为 1 / 3 或 0.33。这就是精确和回忆的含义。
有一种方法可以让我们在 fastText 中使用一个简单的命令来测试模型的精度和召回率。在这一点上,确保你已经阅读了我之前写的快速文本介绍文章,因为我将在这里使用那篇文章中的同一个例子。假设您已经这样做了,并且希望您已经从那篇文章中获得了数据,我们将在根目录中运行以下命令来获得我们的精度并召回数据:
./fasttext test cooking_question_classification_model.bin testing_data.txt
运行此命令后,您应该会得到类似于以下内容的输出:
N 3080
P@1 0.139
R@1 0.0602
正如您从输出中看到的,我们得到了 P@1 和 R@1 的结果,结果是精度为 1,召回为 1。我们将在这篇文章中看到如何改进这些。
清理数据
如果你看我们的数据文件,你可以看到有一些大写字母。这些对于我们的模型来说并不重要,我们可以去掉它们来在一定程度上提高性能。但是我们不能检查所有的数据并清理它们。所以我们将使用一个简单的命令将所有大写字母转换成小写字母。为此,请运行以下命令:
cat cooking.stackexchange.txt | sed -e “s/\([.\!?,’/()]\)/ \1 /g” | tr “[:upper:]” “[:lower:]” > cooking.preprocessed.txt
在这个命令中,我们使用 cat 将数据打印到标准输出,使用管道将数据重定向到 sed 命令,对输入数据运行正则表达式,然后使用另一个管道将这个新输出运行到 translate 命令,将所有大写字母转换为小写字母。我们将这个最终输出重定向到一个名为“cooking.preprocessed.txt”的文件中,这也是官方 fastText 网站上提供的一个简单示例。在真实的生产场景中,这可能不是一个简单的任务。无论如何,一旦我们有了这个新的预处理文件,让我们看看它有什么。
➜ head cooking.preprocessed.txt
__label__sauce __label__cheese how much does potato starch affect a cheese sauce recipe ?
__label__food-safety __label__acidity dangerous pathogens capable of growing in acidic environments
__label__cast-iron __label__stove how do i cover up the white spots on my cast iron stove ?
__label__restaurant michelin three star restaurant; but if the chef is not there
__label__knife-skills __label__dicing without knife skills , how can i quickly and accurately dice vegetables ?
__label__storage-method __label__equipment __label__bread what ‘ s the purpose of a bread box ?
__label__baking __label__food-safety __label__substitutions __label__peanuts how to seperate peanut oil from roasted peanuts at home ?
__label__chocolate american equivalent for british chocolate terms
__label__baking __label__oven __label__convection fan bake vs bake
__label__sauce __label__storage-lifetime __label__acidity __label__mayonnaise regulation and balancing of readymade packed mayonnaise and other sauces
如你所见,数据现在清晰多了。现在,我们不得不再次分割它来测试和训练数据集。为此,我们将运行以下两个命令:
➜ head -n 12324 cooking.preprocessed.txt > preprocessed_training_data.txt
➜ tail -n 3080 cooking.preprocessed.txt > preprocessed_testing_data.txt
我们必须根据这些新数据再次训练我们的模型,因为我们已经更改了数据。为此,我们将运行以下命令,输出应该类似于您在这里看到的内容:
➜ ./fasttext supervised -input preprocessed_training_data.txt -output cooking_question_classification_model
Read 0M words
Number of words: 8921
Number of labels: 735
Progress: 100.0% words/sec/thread: 47747 lr: 0.000000 avg.loss: 10.379300 ETA: 0h 0m 0s
为了检查精确度和召回率,我们将在新的测试数据上测试这个模型:
➜ ./fasttext test cooking_question_classification_model.bin preprocessed_testing_data.txt
N 3080
P@1 0.171
R@1 0.0743
如你所见,准确率和召回率都有所提高。这里要注意的另一件事是,当我们用新数据训练模型时,我们只看到 8921 个单词,而上次,我们看到了 14492 个单词。因此,由于大写和小写的差异,该模型具有相同单词的多个变体,这在一定程度上降低了精确度。
纪元
如果你有软件开发背景,你就知道 epoch 和时间有关系。你是对的。在这个上下文中,epoch 是模型看到一个短语或一个示例输入的次数。默认情况下,模型会将一个示例查看五次,即 epoch = 5。因为我们的数据集只有大约 12k 的样本,少了 5 个时期。我们可以使用- ecpoch 选项将它增加到 25 次,使模型“看到”一个例句 25 次,这可以帮助模型更好地学习。现在让我们试试:
➜ ./fasttext supervised -input preprocessed_training_data.txt -output cooking_question_classification_model -epoch 25
Read 0M words
Number of words: 8921
Number of labels: 735
Progress: 100.0% words/sec/thread: 43007 lr: 0.000000 avg.loss: 7.383627 ETA: 0h 0m 0s
你可能已经注意到,现在完成这个过程花了一点时间,这是我们增加纪元时所期望的。无论如何,现在让我们测试我们的模型的精度:
➜ ./fasttext test cooking_question_classification_model.bin preprocessed_testing_data.txt
N 3080
P@1 0.518
R@1 0.225
如你所见,我们在精确度和召回率上有了显著的提高。那很好。
算法的学习速率
算法的学习率表示在每个例句被处理后模型改变了多少。我们既可以提高也可以降低算法的学习速度。学习率为 0 表示学习没有变化,或者变化率正好为 0,所以模型根本没有变化。通常的学习率是 0.1 比 1。对于我们这里的例子,我们将保持学习率为 1,并重新训练我们的模型。为此,我们将使用 -lr 选项:
➜ ./fasttext supervised -input preprocessed_training_data.txt -output cooking_question_classification_model -lr 1.0
Read 0M words
Number of words: 8921
Number of labels: 735
Progress: 100.0% words/sec/thread: 47903 lr: 0.000000 avg.loss: 6.398750 ETA: 0h 0m 0s
我们将再次测试模型,看看改变学习率后是否有任何改进:
➜ ./fasttext test cooking_question_classification_model.bin preprocessed_testing_data.txt
N 3080
P@1 0.572
R@1 0.248
绝对有进步。但是,如果我们一起增加纪元和学习率,会发生什么呢?
一起增加纪元和学习率
现在,我们将保持纪元为 25,学习速率为 1。让我们看看精确度和召回率会发生什么变化:
➜ ./fasttext supervised -input preprocessed_training_data.txt -output cooking_question_classification_model -epoch 25 -lr 1.0
Read 0M words
Number of words: 8921
Number of labels: 735
Progress: 100.0% words/sec/thread: 41933 lr: 0.000000 avg.loss: 4.297409 ETA: 0h 0m 0s
现在让我们测试模型:
➜ ./fasttext test cooking_question_classification_model.bin preprocessed_testing_data.txt
N 3080
P@1 0.583
R@1 0.253
我们可以很容易地看到这里的改进。
所以,我们在这个帖子中学到了很多(我希望)。不过还有更多事情要做(比如 n-grams )。我们将在以后的帖子中看到这一点。如果你对此有任何补充,请在下面留下评论。
优化算法 I
新加坡元和动量
我们将有一个简短的优化概述,因为为什么需要它,稍后我们将讨论几个突出的算法。
为什么我们需要优化算法?
机器学习中的所有问题,无论是回归还是分类,都有一个要达到最佳性能的目标。模型的好坏与预测的好坏直接相关,即对于分类问题,模型应该能够正确地识别事物,而对于回归问题,模型的预测应该足够接近真实值。为了开发一个“好模型”,我们通常会将经验风险与问题联系起来,并试图通过迭代过程来降低它。机器学习优化算法与其他优化算法的一个重要区别是,它们不会在达到局部最小值后停止,而是在满足停止标准时停止。在深度学习和一般人工神经网络中,我们可能经常使用代理损失函数而不是经验风险最小化,因为它们容易过度拟合。
神经网络训练面临额外的问题。由于导致非常慢的步骤的病态 Hessian 矩阵、可能与局部最小值混淆的鞍点以及使训练不稳定的爆炸梯度,可能会出现问题。此外,使用小批训练样本的梯度近似可能导致不精确的估计,并使梯度在不同于最佳方向的方向上移动,所述最佳方向可能是利用整个数据集上的梯度获得的。
虽然 SGD 是经典的,并且仍然可以在许多问题中找到应用,但是使用自适应算法已经成为一种趋势。
1。随机梯度下降
对于初学者来说,随机梯度下降是一个容易理解的算法。它在许多方面类似于其前身批量梯度下降,但在某种意义上提供了一个优势,即它通过更少的数据集在降低风险目标方面取得了快速进展。算法如下:
该算法本质上是在每次迭代中选择 m 个数据点,计算它们的平均梯度,更新参数,并对各种学习速率这样做以获得最佳模型。它重复这个过程,直到满足某个收敛标准。
为什么我们需要改变学习率? 训练样本的随机采样给梯度增加了随机噪声,即使在局部最小值时也不会减少。因此,为了保证收敛,我们允许学习率在一些初始迭代中降低,并在之后保持不变。保证收敛的充分条件是,
matcha.io
这里,ε-k 是第 k 次迭代后的学习率。
mathcha.io
根据深度学习的书,我们将ε的最终固定值设定为初始值的 1%左右。SGD 的一个重要性质是每次迭代的参数更新仅取决于批量 m,因此每次迭代的计算时间不随训练样本数量的增加而改变。对于一个凸问题,推广误差(当前迭代后损失函数值与损失函数值最小值之差)每一步递减O(1/sqrt(k))
。根据 Cramer-Rao 界,这种推广误差在一次迭代中不能减少超过 O(1/k)
。
2。势头
使用 SGD 的动量来克服与 SGD 相关的病态 Hessian 矩阵和梯度方差的问题。它通过保持梯度的移动平均值来实现这一目标。现在,更新不仅依赖于当前梯度,而且依赖于来自过去的梯度序列。它基本上维护另一个变量 v,该变量将累积梯度,并使用该变量来更新参数。算法如下:
Momentum with SGD
需要注意的重要一点是,我们现在要考虑另一个超参数。在下图中,红线显示了渐变随动量的移动。它更快,更直接地指向目标,因为它一直在考虑过去梯度的方向,并通过平均它们。等高线代表平方损失函数
参考资料:
[## 深度学习
深度学习教材是一个资源,旨在帮助学生和从业人员进入机器领域…
www.deeplearningbook.org](https://www.deeplearningbook.org/)
即将推出自适应方法的优化算法 2。
深度学习中的优化算法
AdaGrad、RMSProp、带动量的梯度下降和 Adam 优化器揭秘
在本文中,我将向您介绍深度学习中最复杂的优化算法,这些算法可以让神经网络更快地学习,并实现更好的性能。
这些算法是带动量的随机梯度下降、AdaGrad、RMSProp 和 Adam Optimizer。
【https://www.deeplearning-academy.com】最初发表于。
如果你喜欢这篇文章,想分享你的想法,问问题或保持联系,请随时通过 LinkedIn 与我联系。
目录
- 为什么我们需要更好的优化算法?
- 带动量的随机梯度下降
- 阿达格拉德
- RMSProp
- Adam 优化器
- 深度学习的最佳优化算法是什么?
1.为什么我们需要更好的优化算法?
为了训练神经网络模型,我们必须定义损失函数,以便测量我们的模型预测和我们想要预测的标签之间的差异。我们所寻求的是一组特定的权重,利用这些权重,神经网络可以做出准确的预测,从而自动导致损失函数值更低。
我想你现在一定知道了,它背后的数学方法叫做梯度下降。
Eq. 1 Gradient Descent for parameters θ with loss function L.
在该技术(等式 1)中,我们必须计算损失函数 L 相对于我们想要改善的权重(或参数 θ )的梯度。随后,在梯度的负方向上更新权重/参数。
通过周期性地对权重应用梯度下降,我们将最终达到最佳权重,使损失函数最小化,并允许神经网络做出更好的预测。
目前为止这个理论。
不要误解我,梯度下降仍然是一个强大的技术。然而,在实践中,这种技术在训练期间可能会遇到某些问题,这些问题会减慢学习过程,或者在最坏的情况下,甚至会阻止算法找到最佳权重
这些问题一方面是损失函数的鞍点和局部最小值,其中损失函数变得平坦,梯度变为零:
Fig. 1 Saddle Points and Local Minima
接近零的梯度不会改善权重参数,并且会妨碍整个学习过程。
另一方面,即使我们有不接近零的梯度,为来自训练集的不同数据样本计算的这些梯度的值在值和方向上也可能不同。我们说梯度是有噪声的,或者有很多方差。这导致向最佳重量的曲折移动,并使学习速度变慢:
Fig. 3 Example of zig-zag movements of noisy gradients.
在下面的文章中,我们将学习更复杂的梯度下降算法。所有这些算法都是基于我们到目前为止所知道的规则梯度下降优化。但是,我们可以通过一些数学技巧来扩展这种常规的权重优化方法,以建立更有效的优化算法,使我们的神经网络能够充分处理这些问题,从而学习更快,实现更好的性能
2.带动量的随机梯度下降
我想向你们展示的第一个复杂算法叫做带动量的随机梯度下降。
Eq. 2 Equations for stochastic gradient descent with momentum.
在等式的左边。2,您可以看到权重根据规则随机梯度下降进行更新的等式。右边的等式显示了根据具有动量的 SGD 的权重更新的规则。动量作为添加到常规更新规则中的附加项**【ρ】**乘以 v 出现。
直观地说,通过增加这个动量项,我们让我们的梯度在训练期间建立一种速度 v 。速度是由 ρ 加权的梯度的运行和。
ρ 可以认为是一点点减缓速度的摩擦力。一般来说,你可以看到速度随着时间的推移而增加。通过使用动量项,鞍点和局部极小值对梯度变得不那么危险。因为朝向全局最小值的步长现在不仅取决于当前点的损失函数的梯度,还取决于随时间推移而增加的速度。
换句话说,在某一点上,我们更多的是朝着速度的方向移动,而不是朝着梯度的方向。
如果你想有一个有动量的随机梯度下降的物理表示,想象一个球滚下山坡,并随着时间的推移增加速度。如果这个球在途中碰到一些障碍物,比如一个洞或没有向下斜坡的平地,速度 v 会给球足够的力量滚过这些障碍物。在这种情况下,平地和洞代表鞍点或损失函数的局部最小值。
在下面的视频中(图 4),我想给大家展示一个正则随机梯度下降和带动量项的随机梯度下降的直接对比。两种算法都试图达到三维空间中损失函数的全局最小值。请注意动量项是如何使梯度具有更小的方差和更少的曲折移动的。
**
Fig. 4 SGD vs. SGD with Momentum
一般来说,动量项使得向最优权重的收敛更稳定和更快。
3.阿达格拉德
另一种优化策略叫做 AdaGrad。这个想法是你在优化过程中保持梯度平方和的运行。在这种情况下,我们没有动量项,而是一个表达式 g 它是梯度平方的和。
Eq. 3 Parameter update rule for AdaGrad.
当我们更新一个权重参数时,我们将当前梯度除以该项的根 g 。为了解释 AdaGrad 背后的直觉,想象一个二维空间中的损失函数,其中损失函数在一个方向上的梯度非常小,而在另一个方向上非常高。
沿着梯度较小的轴对梯度求和会导致这些梯度的平方和变得更小。如果在更新步骤中,我们将当前梯度除以一个非常小的梯度平方和**【g】**,该除法的结果变得非常高,反之亦然,对于具有高梯度值的另一个轴也是如此。
因此,我们强制算法以相同的比例在任何方向进行更新。
这意味着我们通过增加沿着轴的梯度来加速沿着具有小梯度的轴的更新过程。另一方面,沿着具有大梯度的轴的更新稍微慢了一些。
但是,这种优化算法有一个问题。想象一下,当训练需要很长时间时,梯度的平方和会发生什么。随着时间的推移,这一项会变得更大。如果当前梯度除以这个大的数,则权重的更新步长变得非常小。这就好像我们使用了非常低的学习,随着训练时间的延长,这种学习会变得更低。在最坏的情况下,我们会被困在阿达格拉德,训练将永远继续下去。
4.RMSProp
AdaGrad 有一个名为 RMSProp 的细微变化,它解决了 AdaGrad 的问题。对于 RMSProp,我们仍然保持梯度平方的运行总和,但是我们没有让该总和在训练期间持续增长,而是让该总和实际上衰减。
Eq. 4 Update rule for RMS Prop.
在 RMSProp 中,我们将梯度的平方和乘以衰减率 α ,并加上由(1- α) 加权的当前梯度。RMSProp 中的更新步骤看起来与 AdaGrad 中的完全相同,我们将当前梯度除以梯度的平方和,以获得沿一个维度加速运动并沿另一个维度减慢运动的良好特性。
让我们看看 RMSProp 在寻找最优权重方面与 SGD 和 SGD with momentum 相比做得如何。
**
Fig. 5 SGD vs. SGD with Momentum vs. RMS Prop
虽然具有动量的 SGD 能够更快地找到全局最小值,但这种算法需要更长的路径,这可能是危险的。因为更长的路径意味着更多可能的鞍点和局部极小值。另一方面,RMSProp 直接走向损失函数的全局最小值,而不走弯路。
5.Adam 优化器
到目前为止,我们已经使用了矩项来建立梯度的速度,以朝着该速度的方向更新权重参数。在 AdaGrad 和 RMSProp 的例子中,我们使用梯度的平方和来缩放当前梯度,因此我们可以在每个维度中以相同的比率进行权重更新。
这两种方法看起来都是不错的主意。为什么我们不把两个世界的优点结合到一个单一的算法中呢?
这就是最终优化算法 Adam 背后的确切概念,我想向大家介绍一下。
算法的主要部分由以下三个等式组成。乍一看,这些方程似乎令人不知所措,但如果你仔细观察,你会发现对以前的优化算法有些熟悉。
Eq. 5 Parameter update rule for Adam Optimizer
第一个方程看起来有点像带动量的 SGD。在这种情况下,这一项就是速度和摩擦力。在亚当的例子中,我们称之为第一动量,它只是一个超参数。
然而,与具有动量的 SGD 的差异是因子(1- β1 ),该因子与电流梯度相乘。
另一方面,方程的第二部分可以被视为 RMSProp,其中我们保持梯度平方的运行和。同样,在这种情况下,存在与平方梯度相乘的因子(1- β2 )。
方程中的项称为第二动量,也是一个超参数。最终的更新方程可以看作是 RMSProp 和 SGD 与动量的组合。
到目前为止,Adam 已经集成了前两个优化算法的良好特性,但这里有一个小问题,那就是开始时会发生什么的问题。
在第一时间步,第一和第二动量项被初始化为零。第二次动量第一次更新后,这一项还是很接近零的。当我们更新最后一个等式中的权重参数时,我们除以非常小的第二动量项 v ,导致非常大的第一更新步长。
这个第一个非常大的更新步骤不是问题几何的结果,而是我们已经将第一个和第二个动量初始化为零这一事实的产物。为了解决大的首次更新步骤的问题,Adam 包括一个修正条款:
Eq. 6 Bias Correction for Adam Optimizer
你可以看到,在第一和第二动量的第一次更新之后,我们通过考虑当前的时间步长,对这些动量做了一个无偏的估计。这些校正项使得第一和第二动量的值在开始时比没有偏差校正的情况下更高。
因此,神经网络参数的第一个更新步骤不会变得太大,并且我们不会在开始时搞乱我们的训练。额外的偏差修正为我们提供了完整形式的 Adam 优化器。
现在,让我们在寻找损失函数的全局最小值方面相互比较所有算法:
**
Fig. 6 Comparison of all optimization algorithms.
6.深度学习的最佳优化算法是什么?
最后,我们可以讨论什么是最佳梯度下降算法的问题。
一般来说,普通的梯度下降算法对于较简单的任务来说已经足够了。如果您对模型的准确性不满意,您可以尝试 RMSprop 或在梯度下降算法中添加动量项。
但是根据我的经验,神经网络的最佳优化算法是 Adam。这种优化算法对于你将会遇到的几乎任何深度学习问题都非常有效。尤其是当您将超参数设置为以下值时:
- β1=0.9
- β2=0.999
- 学习率= 0.001–0.0001
…这将是一个非常好的起点,可以解决任何问题,事实上也可以解决我曾经使用过的所有类型的神经网络架构。
这就是为什么 Adam Optimizer 是我想解决的每个问题的默认优化算法。只有在极少数情况下,我才会切换到我之前介绍的其他优化算法。
从这个意义上说,我建议您总是从 Adam 优化器开始,而不管您正在处理的问题领域的神经网络的架构如何。
原载于https://www.deeplearning-academy.com*。*
用 Python 优化:如何用最少的风险赚最多的钱?
我们展示了如何将获得诺贝尔奖的经济理论应用于股票市场,并使用简单的 Python 编程解决由此产生的优化问题。
介绍
现代数据科学和分析企业的主要目标之一是为商业和技术公司解决复杂的优化问题以实现利润最大化。
在我的文章“用 Python 进行线性编程和离散优化”中,我们谈到了基本的离散优化概念,并介绍了一个用于解决此类问题的 Python 库 PuLP 。
线性和整数规划是离散优化的关键技术,它们在现代数学中随处可见
towardsdatascience.com](/linear-programming-and-discrete-optimization-with-python-using-pulp-449f3c5f6e99)
虽然线性规划(LP)问题仅由线性目标函数和约束条件定义,但它可以应用于从医疗保健到经济、商业到军事等不同领域的各种问题。
在本文中,我们展示了一个在经济规划领域使用 Python 编程的 LP 的惊人应用— 最大化股票市场投资组合的预期利润,同时最小化与之相关的风险 。
听起来很有趣?请继续读下去。
如何在股市中实现利润最大化,风险最小化?
1990 年诺贝尔经济学奖授予了哈里·马科维茨,他因著名的现代投资组合理论(MPT)而被认可,这在金融市场的说法中是众所周知的。最初的论文发表于 1952 年。
Source: AZ Quotes
这里的关键词是平衡。
一个好的、平衡的投资组合必须提供保护(最小化风险)和机会(最大化利润)。
单个资产的集合相互作用,影响整个投资组合。所以当几项投资都…
www.dummies.com](https://www.dummies.com/business/accounting/auditing/how-to-optimize-portfolio-risk/)
并且,当涉及到最小化和最大化这样的概念时,很自然地用 数学最优化理论 来投射问题。
基本思想相当简单,植根于人类天生的风险厌恶本性。
一般来说,股票市场的统计数据表明,风险越高,回报越高的可能性越大,风险越低,回报越小的可能性越大。
MPT 假设投资者厌恶风险,这意味着给定两个提供相同预期回报的投资组合,投资者会更喜欢风险较小的一个。想想吧。只有当高风险股票有很高的回报率时,你才会收集它们。
但是如何量化风险?这肯定是一个模糊的概念,对不同的人有不同的含义。然而,在普遍接受的经济理论中,股票价格的可变性(波动性)(在固定时间范围内定义)等同于风险。
因此,中心优化问题是在保证一定的利润回报的同时,使风险最小化。或者,最大化利润,同时将风险保持在某个阈值以下。
一个例题
在本文中,我们将展示投资组合优化问题的一个非常简化的版本,它可以被转换到一个 LP 框架中,并使用简单的 Python 脚本高效地解决。
我们的目标是展示这种优化求解器处理复杂现实问题的能力和可能性。
我们使用三只股票的 24 个月股价(月平均)——微软、Visa 和沃尔玛。这些是旧数据,但它们完美地展示了这一过程。
Fig: Monthly stock price of three companies over a certain 24-month period.
如何定义退货?我们可以简单地通过从当月减去上月的平均股价并除以上月的价格来计算滚动月回报率。
下图显示了返回结果,
优化模型
股票的回报是一个不确定的量。我们可以将其建模为一个随机向量。
投资组合也可以被建模为向量。
因此,某个投资组合的回报由这些向量的内积给出,它是一个随机变量。最重要的问题是:
如何比较随机变量(对应不同的投资组合)来选择一个“最佳”的投资组合?
根据马科维兹模型,我们可以将问题公式化为:
给定固定数量的资金(比如 1000 美元),我们应该在三只股票中的每只股票上投资多少,以便(a)至少有给定阈值的一个月预期回报,以及(b)最小化投资组合回报的风险(方差)。
我们不能投资负的数量。这就是非消极约束,
假设没有交易成本,总投资受到手头资金的限制,
投资回报,
但这是一个随机变量。因此,我们必须处理预期数量,
假设我们想要一个最小预期收益。因此,
现在,为了模拟风险,我们必须计算方差,
综合起来,最终的优化模型是,
接下来,我们将展示使用一个流行的 Python 库来阐述和解决这个问题是多么容易。
使用 Python 解决优化问题:CVXPY
这个问题我们要用的库叫做 CVXPY 。它是一种用于凸优化问题的 Python 嵌入式建模语言。它允许你以一种遵循数学模型的自然方式来表达你的问题,而不是以求解者所要求的限制性标准形式。
本 Jupyter 笔记本 中给出了 的全部代码。在这里,我只展示核心代码片段。
要建立必要的数据,关键是从每月价格的数据表中计算出回报矩阵。代码如下所示,
现在,如果您并排查看原始数据表和返回表,看起来如下所示:
接下来,我们简单地从这个回报矩阵计算平均(预期)回报和协方差矩阵,
之后,CVXPY 允许简单地按照我们上面构建的数学模型来设置问题,
注意 CVXPY 框架中非常有用的类的使用,如**quad_form()**
和**Problem()**
。
瞧啊。
我们可以编写一个简单的代码来解决**Problem**
,并显示最佳投资数量,确保最低回报率为 2%,同时也将风险保持在最低水平。
最终结果由下式给出:
延伸问题
不用说,我们模型的设置和简化假设会使这个问题听起来比实际情况更简单。但是一旦您理解了解决这种优化问题的基本逻辑和机制,您就可以将其扩展到多种场景,
- 数百只股票,更长时间范围的数据
- 多重风险/回报比率和阈值
- 最小化风险或最大化回报(或两者兼而有之)
- 一起投资一组公司
- 非此即彼的情景——要么投资 Cococola,要么投资百事可乐,但不能两者都投资
你必须构建更复杂的矩阵和更长的约束列表,使用指示变量将这变成一个****-混合整数问题,但所有这些都是 CVXPY 这样的包所固有的支持。
查看 CVXPY 包的示例页面,了解使用该框架可以解决的优化问题的广度。
摘要
在本文中,我们讨论了如何从一个开创性的经济理论的关键概念可以用来制定一个简单的股票市场投资优化问题。
为了说明这一点,我们选取了三家公司的月平均股价样本数据集,并展示了如何使用基本的 Python 数据科学库(如 NumPy、Pandas)和一个名为 CVXPY 的优化框架来快速建立线性规划模型。
拥有这种灵活而强大的软件包的工作知识为未来的数据科学家的技能组合增加了巨大的价值,因为解决优化问题的需求出现在科学、技术和商业问题的所有方面。
鼓励读者尝试这个投资问题的更复杂版本,以获得乐趣和学习。
#数据科学,#编程,#统计
如果您有任何问题或想法要分享,请通过tirthajyoti【AT】Gmail . com联系作者。此外,您可以查看作者的 GitHub 资源库中其他有趣的 Python、R 或 MATLAB 代码片段和机器学习资源。如果你像我一样对机器学习/数据科学充满热情,请随时在 LinkedIn 上添加我或在 Twitter 上关注我。
** [## Tirthajyoti Sarkar - Sr .首席工程师-半导体、人工智能、机器学习- ON…
佐治亚理工学院理学硕士- MS,分析这一 MS 计划传授理论和实践…
www.linkedin.com](https://www.linkedin.com/in/tirthajyoti-sarkar-2127aa7/)**
SciPy 优化及其在机器学习中的应用
对于各种各样的业务和技术流程来说,优化通常是最终的边界,需要被征服才能交付真正的价值。我们展示了如何使用 Python 中最流行的科学分析包 SciPy 进行优化,并讨论了在机器学习领域的独特应用。
介绍
你可能还记得高中时代的一个简单的微积分问题——在给定一个盒子的体积限制的情况下,找出建造一个盒子所需的最少材料。
够简单吗?
思考一下这个问题,并认识到这里应用的相同原理在复杂、大规模的商业和社会问题中广泛使用,这是有益的。
仔细看上面的问题。约束是固定的体积。把它想成一个商业可交付成果(也就是对客户的承诺)。
但是问题的目标是找到所需的(就表面积而言)的最小材料。认为这与生产商的利润率有关(需要的材料越少,相同售价的生产成本越低,因此利润率更高)。
数学优化是解决工程、金融、医疗保健和社会经济事务中主要商业问题的核心。几乎所有的商业问题都可以归结为某种资源成本的最小化或给定其他约束条件下某种利润的最大化。
优化过程也是运筹学的灵魂,运筹学与现代数据驱动的商业分析密切相关。以这种方式,它也与数据科学管道密切相关,几乎在今天的所有业务中使用。
虽然已经有很多关于数据科学项目的数据争论和预测建模方面的文章,但最终的前沿通常涉及使用数据驱动模型解决优化问题,这些模型可以通过降低成本或提高生产力来提高业务的底线。
对于现实生活中的业务问题,数据驱动分析的现代实践总是一个复杂的混合体…
medium.com](https://medium.com/analytics-vidhya/why-a-business-analytics-problem-demands-all-of-your-expertise-at-once-1290170808c4)
除了纯粹的商业驱动动机,优化的主题本身也值得研究,因为它是所有机器学习 (ML)算法的核心,从简单线性回归一直到深度神经网络。理解优化问题的各种算法、限制和公式化可以产生有效解决 ML 问题的有价值的洞察力。
我们展示了最流行的机器学习/统计建模技术背后的核心优化框架。
towardsdatascience.com](/a-quick-overview-of-optimization-models-for-machine-learning-and-statistics-38e3a7d13138)
因此,对于一名数据科学家来说,学习解决优化问题的基本工具和框架以产生实际影响是必不可少的。
Python 和 SciPy 用于优化
Python 已经成为分析、数据科学和机器学习的事实上的通用语言。因此,在 Python 生态系统中讨论优化包和框架是有意义的。
多年来,R 一直是那些进入数据科学领域的人的显而易见的选择。近年来,有些事情发生了变化…
www.netguru.com](https://www.netguru.com/blog/how-did-python-become-the-language-of-choice-for-data-science)
在我之前的帖子中,我已经涵盖了使用 Python 的 线性规划 和其他 离散优化方法论 并介绍了强大的包,如纸浆和 CVXPY 。
在这篇文章中,我将介绍 SciPy 生态系统中可用的优化算法。SciPy 是用于科学和数学分析的最广泛使用的 Python 包,难怪它拥有强大而易用的优化例程来解决复杂的问题。
相关的示例代码可以在作者的 GitHub 资源库中找到。
开始简单—单变量标量优化
我们从一个简单的标量函数(一个变量)最小化的例子开始。假设,我们想要最小化下面的函数,它绘制在 x = -10 到 x = 10 之间。该函数如下所示。在函数域内,它有一个全局最小值和一个局部最小值。
定义该函数的代码是,
def scalar1(x):
return np.sin(x)*np.exp(-0.1*(x-0.6)**2)
用 SciPy 确定全局最小值的代码非常简单。在这种情况下,我们可以使用**minimize_scalar**
函数。
from scipy import optimize
result = optimize.minimize_scalar(scalar1)
就是这样。信不信由你,优化完成了!我们可以打印出结果对象,以获得更多有用的信息。
print(result)>> fun: -0.6743051024666711
nfev: 15
nit: 10
success: True
x: -1.2214484245210282
达到最小值的值存储在result['x']
变量中。
print("Minimum occurs at: ",result['x'])
>> Minimum occurs at: -1.2214484245210282
剩余量产生关于函数求值次数、迭代次数、解的状态(成功与否)以及最终解的函数值的信息。
如果变量是有界的呢?
上面的代码实现了所谓的无约束/无界优化,即没有对问题施加任何类型的限制。然而,大多数实际优化问题涉及复杂的约束。一个简单的例子是约束自变量( x )。
正如我们看到的,这个函数有两个极小值,如果我们只考虑 x 的正值,结果会不同。使用 bound 进行搜索的代码与上面的代码略有不同。
result = optimize.minimize_scalar(scalar1, bounds = (0,10),method='Bounded')
因此,我们必须用一个合适的包含最小和最大边界的元组传递**bounds**
参数,并使用**method='Bounded'**
参数。
print("When bounded between 0 and 10, minimum occurs at: ",result['x'])>> When bounded between 0 and 10, minimum occurs at: 4.101466164987216
引入其他功能约束
在这个问题中,我们可能有其他复杂的约束。假设,我们希望满足以下条件以及找到全局最小值的目标。
注意,其中一个是不等式,另一个是等式约束。
将约束作为函数放入字典中
SciPy 允许通过更通用的方法**optimize.minimize**
处理任意约束。约束必须按照特定的语法写在 Python 字典中。不等式约束需要分解成形式为 f(x) < 0 的单个不等式。下面的代码演示了这个想法。
选择合适的方法
之后,我们可以通过选择支持约束的合适方法来运行优化(函数 **minimize**
中并非所有方法都支持约束和界限)。这里我们选择 SLSQP 方法,代表 序列最小二乘二次规划 。
初步猜测和第一次试运行
此外,为了使用minimize
,我们需要以x0
参数的形式传递一个初始猜测。假设,我们通过x0=0
进行试运行。
result = optimize.minimize(scalar1,x0=0,method='SLSQP',
constraints=cons,options={'maxiter':1000})
失败!
如果我们打印结果,我们会看到与简单的无约束优化结果不同的东西。
fun: 0.7631695862891654
jac: array([0.59193639])
message: 'Iteration limit exceeded'
nfev: 1254
nit: 101
njev: 101
status: 9
success: False
x: array([0.8773752])
优化参数 success: False 表示没有成功达到全局最小值。消息为**“迭代限制超过**”,即它尝试了 101 次迭代,但无法达到最小值。
但是,为什么呢?
答案在于数学优化(和相关算法)的深层理论,但可以说最初的猜测起了很大的作用。一般来说,非凸优化问题没有成功解决的数学保证,我们这里的问题的本质是非凸的。要了解更多关于最优化问题的凸性,请看这个视频,
怎样才能提高优化(搜索)?
一般情况下,我们做不了多少。然而,在这个玩具例子中,我们已经有了函数的图形,并能看到最优解。因此,我们可以给算法一个更好的初始猜测。我们给**x0=-2**
。
result = optimize.minimize(scalar1,x0=-2,method='SLSQP',
constraints=cons,options={'maxiter':100})
现在结果是有利的!
fun: -0.2859494456768613
jac: array([-0.4675066])
message: 'Optimization terminated successfully.'
nfev: 811
nit: 71
njev: 67
status: 0
success: True
x: array([-2.37569791])
迭代次数呢?
如果我们限制算法执行的迭代次数会怎么样?仅出于演示目的,我们将迭代次数严格限制为 3 次。
result = optimize.minimize(scalar1,x0=-20,method='SLSQP',
constraints=cons,options={'maxiter':3})
不出所料,结果并不令人满意。
fun: -0.4155114388552631
jac: array([-0.46860977])
message: 'Iteration limit exceeded'
nfev: 12
nit: 4
njev: 4
status: 9
success: False
x: array([**-2.10190632**])
请注意,优化接近全局最小值,但没有完全达到——当然,这是因为不允许迭代足够的次数。
为什么考虑这一点很重要?
这是因为每次迭代等于计算(有时不是计算而是实际物理)成本。
这是优化过程的一个业务方面。在现实生活中,如果单个函数评估耗费大量资源,我们可能无法长时间运行优化。
当优化不涉及简单的数学评估,而是涉及复杂、耗时的模拟或成本和劳动密集型实验时,就会出现这种情况。
当每次评估都要花费金钱或资源时,那么不仅算法的选择,而且更精细的细节都变得需要考虑。
变得更复杂—多变量函数
尽管我们在前面的章节中考虑了解决一个标准优化问题的所有基本方面,但是这个例子由一个简单的单变量分析函数组成。
但事实并非如此!
SciPy 方法适用于任何 Python 函数,不一定是封闭形式的一维数学函数。
让我们展示一个多值函数的例子。
高斯混合的最大化
通常在一个化学或制造过程中,多个随机子过程被组合起来产生一个高斯混合。可能需要通过选择单个子过程中的最佳操作点来最大化最终的合成过程输出(在一定的过程限制内)。
诀窍是使用一个向量作为目标函数的输入,并确保目标函数仍然返回单个标量值。此外,因为这里的优化问题是关于目标函数的最大化,我们需要改变符号并返回高斯函数和的负数作为目标函数的结果。
同样的result['x']
将单个程序的最佳设置存储为一个向量。这就是优化单值函数和多元函数的唯一区别,我们得到的是一个向量,而不是一个标量。
x: array([-1.00017852, 0.29992313, 2.10102748])
有界输入
不用说我们可以改变这里的界限来反映实际的约束。例如,如果子过程设置只能占用一定范围的值(一些必须是正的,一些必须是负的,等等。)那么解决方案将略有不同—它可能不是全局最优的。
这里,解决方法如下。这表示将第三个子过程设置推至最大可能值(零),同时适当调整其他两个子过程设置。
x: array([-1.00000644e+00, 3.00115191e-01, -8.03574200e-17])
多变量优化的约束处理方式类似于单变量优化。
更详细的文档和示例
SLSQP 并不是 SciPy 生态系统中唯一能够处理复杂优化任务的算法。有关更详细的文档及其用法,请参见以下链接:
用 Scipy 进行线性编程
简单、直接的线性规划(LP)问题也可以通过 Scipy 解决。在 2014 年之前,它没有内置的 LP 求解器,但从那时起它已经发生了变化。
让我们举一个实际的工厂生产问题(借用了这个例子并略有改动)
一个工厂生产四种不同的产品,第一种产品的日产量是 x1 ,第二种产品的日产量是 x2 ,以此类推。目标是确定每种产品的利润最大化日产量,有以下约束条件:
- 第一个、第二个、第三个和第四个产品的单位产品利润分别是 20、12、30 和 15。
- 由于人力的限制,每天生产的总数量不能超过五十(50)。
- 对于每单位的第一种产品,消耗三单位的原材料 A。第二种产品的每单位需要两个单位的原料 A 和一个单位的原料 b。第三种产品的每单位需要两个单位的 A 和五个单位的 b。最后,第四种产品的每单位需要三个单位的 b。
- 由于运输和储存的限制,工厂每天可以消耗一百单位的原材料 A 和九十单位的 B。
在 Scipy 中设置这个问题很容易。
然后用一行代码解决它,
所以,解决方案说,
- 工厂每天应生产 26.66 台 x1 ,10 台 x3 ,13.33 台 x4 。与 x2 相对应的极小数字实质上表示不应该产生任何数量的 x2 。
- 在这种安排下,可获得的最大利润是 1033.33 美元。
值得注意的一点是,该解决方案表示分数选择,这在实际情况下可能不可行。这就是 Scipy solver 的局限性,它不能解决所谓的整数规划问题。其他 Python 包如 PuLP 可能是解决这类问题的一个选择。在这里看我的文章。
线性和整数规划是离散优化的关键技术,它们在现代数学中随处可见
towardsdatascience.com](/linear-programming-and-discrete-optimization-with-python-using-pulp-449f3c5f6e99)
将该过程扩展到机器学习领域
老实说,只要您能够定义一个合适的目标函数来生成一个标量值以及与实际问题场景相匹配的合适的边界和约束,那么您可以推动这种方法的复杂程度是没有限制的。
机器学习中的误差最小化
几乎所有机器学习(ML)算法的关键是定义合适的误差函数(或损失度量),迭代数据,并找到最小化总误差的 ML 模型参数的最佳设置。通常,误差是模型预测和实际情况(给定数据)之间某种距离的度量。
因此,完全可以使用 SciPy 优化例程来解决 ML 问题。
这使您能够深入了解算法的实际工作,因为您必须自己构建损失度量,而不依赖于一些现成的开箱即用的函数。
ML 中超参数优化
调整 ML 模型的参数和超参数通常是一项麻烦且容易出错的任务。虽然有网格搜索方法可用于搜索最佳参数组合,但通过在参数空间上运行优化循环**,可以轻松引入一定程度的自动化。在这种情况下,目标函数必须是 ML 模型预测质量的某种度量(例如,均方误差、复杂性度量或 F1 分数)。**
使用机器学习作为函数评估器
在许多情况下,你不可能有一个好的、封闭形式的分析函数来作为优化问题的目标。
但是当我们有了深度学习的时候,谁会在乎变好呢?
想象一下的威力,一个由众多模型(针对其目标函数和约束条件)提供的优化模型——在基本性质上不同,但在输出格式上是标准化的,因此它们可以协调一致地行动。
你可以自由选择一个解析函数,一个深度学习网络(也许是作为回归模型),甚至是一个复杂的仿真模型,把它们一起扔进优化的坑里。
可能性是无限的!
如果您有任何问题或想法要分享,请联系作者在tirthajyoti【AT】Gmail . com。另外,你可以查看作者的 GitHub 资源库中其他有趣的 Python、R 或 MATLAB 代码片段和机器学习资源。如果你像我一样对机器学习/数据科学充满热情,请随时在 LinkedIn 上添加我或在 Twitter 上关注我。
[## Tirthajyoti Sarkar - Sr .首席工程师-半导体、人工智能、机器学习- ON…
佐治亚理工学院理学硕士- MS,分析这一 MS 计划传授理论和实践…
www.linkedin.com](https://www.linkedin.com/in/tirthajyoti-sarkar-2127aa7/)