用 Keras 和 tf 微调 BERT。组件
在这个实验中,我们将预训练的 BERT 模型检查点转换为可训练的 Keras 层,我们使用它来解决文本分类任务。
我们通过使用 tf 来实现这一点。模块,这是一个简洁的抽象,旨在处理预先训练好的 Tensorflow 模型。
导出的模块可以很容易地集成到其他模型中,这有助于使用强大的神经网络架构进行实验。
这个实验的计划是:
- 获得预训练的 BERT 模型检查点
- 定义 tf 的规格。组件
- 导出模块
- 构建文本预处理管道
- 实现自定义 Keras 层
- 训练一个 Keras 模型来解决句子对分类任务
- 保存和恢复
- 优化用于推理的训练模型
这本指南里有什么?
本指南是关于将预先训练的 Tensorflow 模型与 Keras 集成。它包含两个东西的实现:一个 BERT tf。模块和构建在它上面的 Keras 层。它还包括微调(见下文)和推理的例子。
需要什么?
对于熟悉 TensorFlow 的读者来说,完成本指南大约需要 60 分钟。代码用 tensorflow==1.15.0 测试。
好吧,给我看看代码。
这个实验的代码可以在 T2 的实验室里找到。独立版本可以在库中找到。
步骤 1:获得预训练模型
我们从一个预先训练好的基于 BERT 的检查点开始。在这个实验中,我们将使用由谷歌预先训练的英语模型。当然,在构建 tf.Module 时,您可以使用更适合您的用例的模型。
步骤 2:构建一个 tf。组件
tf。模块旨在提供一种简单的方法来操作 Tensorflow 中预训练机器学习模型的可重用部分。谷歌在 tf 维护了一个此类模块的精选库。轮毂。然而,在本指南中,我们将自己从头开始构建一个。
为此,我们将实现一个包含模块内部工作的完整规范的 module_fn 。
我们从定义输入占位符开始。BERT 模型图由通过配置路径传递的配置文件创建。然后提取 we 模型输出:最终的编码器层输出被保存到 seq_output 并且汇集的“CLS”令牌表示被保存到 pool_output。
此外,额外的资产可以与模块捆绑在一起。在这个例子中,我们将一个包含单词表的 vocab_file 添加到模块资产中。因此,词汇文件将与模块一起导出,这将使它成为自包含的。
最后,我们定义了签名,它是输入到输出的特定转换,向消费者公开。人们可以把它看作是与外界的一个模块接口。
这里添加了两个签名。第一个将原始文本特征作为输入,并将计算后的文本表示作为输出返回。另一个不接受输入,返回词汇表文件的路径和小写标志。
步骤 3:导出模块
既然已经定义了 module_fn ,我们就可以用它来构建和导出模块了。将 tags_and_args 参数传递给 create_module_spec 将导致两个图变量被添加到模块中:用 tags*{“train”}*进行训练,以及用一组空的 tags 进行推断。这允许控制退出,这在推理时被禁用,而在训练期间被启用。
步骤 4:构建文本预处理管道
BERT 模型要求将文本表示为包含input _ id、 input_mask 和segment _ id的 3 个矩阵。在这一步中,我们构建了一个管道,它接受一个字符串列表,并输出这三个矩阵,就这么简单。
首先,原始输入文本被转换成 InputExamples。如果输入文本是由特殊的“|||”序列分隔的句子对,则句子被拆分。
然后,使用来自原始存储库的convert _ examples _ to _ features函数,将 InputExamples 标记化并转换为 InputFeatures。之后,特征列表被转换成带有特征 _ 到 _ 数组的矩阵。
最后,我们将所有这些放在一个管道中。
全部完成!
步骤 5:实现 BERT Keras 层
使用 tf 有两种方法。带有 Keras 的模块。
第一种方法是用 hub 包裹一个模块。角斗士。这种方法很简单,但是不太灵活,因为它不允许在模块中加入任何定制的逻辑。
第二种方法是实现包含该模块的自定义 Keras 层。在这种情况下,我们可以完全控制可训练变量,并且可以将池化操作甚至整个文本预处理管道添加到计算图中!我们将走第二条路。
为了设计一个定制的 Keras 层,我们需要编写一个继承自 tf.keras.Layer 的类,并覆盖一些方法,最重要的是构建和调用。
build 方法创建模块的资产。它从实例化来自 bert_path 的 BERT 模块开始,该路径可以是磁盘上的路径或 http 地址(例如,对于来自 tf.hub 的模块)。然后建立可训练层的列表,并填充该层的可训练权重。将可训练权重的数量限制在最后几层可以显著减少 GPU 内存占用并加快训练速度。它还可能提高模型的准确性,特别是在较小的数据集上。
build_preprocessor 方法从模块资产中检索单词表,以构建步骤 4 中定义的文本预处理管道。
initialize_module 方法将模块变量加载到当前的 Keras 会话中。
大多数有趣的事情都发生在调用方法内部。作为输入,它接受一个张量 tf。字符串,使用我们的预处理管道将其转换成 BERT 特征。使用 *tf.numpy_function 将 python 代码注入到图中。*然后将特征传递给模块,并检索输出。
现在,根据在 init,中设置的池参数,额外的变换被应用于输出张量。
如果 pooling==None ,则不应用池,输出张量具有形状 [batch_size,seq_len,encoder_dim] 。此模式对于解决令牌级任务非常有用。
如果 *pooling=='cls ',*仅检索对应于第一个 ‘CLS’ 标记的向量,并且输出张量具有形状 [batch_size,encoder_dim] 。这种池类型对于解决句子对分类任务很有用。
最后,如果 *pooling=='mean ',*所有记号的嵌入都是平均池化的,并且输出张量具有形状 [batch_size,encoder_dim] 。这种模式对于句子表达任务特别有用。它的灵感来自伯特即服务的 REDUCE_MEAN 池策略。
BERT 层的完整列表可以在库中找到。
第六步:句子对分类
现在,让我们在真实数据集上尝试该图层。对于这一部分,我们将使用 Quora 问题对数据集,它由超过 400,000 个潜在的问题重复对组成,标记为语义等价。
建立和训练句子对分类模型很简单:
顺便说一句,如果你不喜欢在图形中进行预处理,你可以通过设置 do_preprocessing=False 来禁用它,并使用 3 个输入来构建模型。
仅微调最后三层就可以获得 88.3%的验证准确率。
Train on 323432 samples, validate on 80858 samples
Epoch 1/5323432/323432 [==============================] - 3197s 10ms/sample - loss: 0.3659 - acc: 0.8255 - val_loss: 0.3198 - val_acc: 0.8551
Epoch 2/5
323432/323432 [==============================] - 3191s 10ms/sample - loss: 0.2898 - acc: 0.8704 - val_loss: 0.2896 - val_acc: 0.8723
Epoch 3/5
323432/323432 [==============================] - 3231s 10ms/sample - loss: 0.2480 - acc: 0.8920 - val_loss: 0.2833 - val_acc: 0.8765
Epoch 4/5
323432/323432 [==============================] - 3205s 10ms/sample - loss: 0.2083 - acc: 0.9123 - val_loss: 0.2839 - val_acc: 0.8814
Epoch 5/5
323432/323432 [==============================] - 3244s 10ms/sample - loss: 0.1671 - acc: 0.9325 - val_loss: 0.2957 - val_acc: 0.8831
步骤 7:保存和恢复模型
模型权重可以通过常规方式保存和恢复。模型架构也可以序列化为 json 格式。
如果到 BERT 模块的相对路径不变,从 json 重建模型将会工作。
步骤 8:优化推理
在某些情况下(例如,当服务时),人们可能想要优化训练模型以获得最大的推理吞吐量。在 TensorFlow 中,这可以通过“冻结”模型来实现。
在“冻结”过程中,模型变量由常数代替,训练所需的节点从计算图中删除。生成的图形变得更加轻量级,需要更少的 RAM,并获得更好的性能。
我们冻结训练好的模型,并将序列化的图形写入文件。
现在我们还原一下冻结图,做一些推断。
为了运行推理,我们需要得到图的输入和输出张量的句柄。这部分有点棘手:我们在恢复的图中检索所有操作的列表,然后手动获取相关操作的名称。列表是排序的,所以在这种情况下,只需进行第一个和最后一个操作。
为了得到张量名称,我们将 “:0” 附加到 op 名称上。
我们注入到 Keras 层中的预处理函数是不可序列化的,并且没有在新图中恢复。不过不用担心——我们可以简单地用相同的名称再次定义它。
最后,我们得到了预测。
array([[9.8404515e-01]], dtype=float32)
结论
在这个实验中,我们创建了一个可训练的 BERT 模块,并用 Keras 对其进行了微调,以解决句子对分类任务。
通过冻结训练好的模型,我们消除了它对自定义层代码的依赖性,使它变得可移植和轻量级。
本系列中的其他指南
解雇你的商务智能团队
改变 BI 的授权和参与模式
“商业智能”一词在 20 世纪 90 年代广泛流行,最初是被定义为“通过使用基于事实的支持系统来改进商业决策的概念和方法”显然,对于任何公司来说,这听起来都是一项具有战略重要性的职能。
那么,为什么会有这样刺耳的标题呢?虽然上面的描述可能捕捉到了 BI 团队在 20 世纪 90 年代所做的事情,但这并不是 BI 团队在过去十年所做的事情。随着数据分析的采用和复杂性发生变化,BI 团队成为分析生态系统的底层支持者,而数据科学家获得了所有的乐趣和荣耀。BI 团队最终成为订单接受者,执行那些不以分析为生的人提出的精确要求。这严重削弱了它们的影响。
但是不一定要这样。你也不需要解雇你的商务智能团队。**我们可以通过改变商业智能的任务和他们与利益相关者互动的方式来恢复商业智能在分析生态系统中的地位。这将带来更有影响力的见解,同时确保分析师自己感受到专业的所有权和目的。
让我们看一下为什么和如何做。
****要了解目前 BI 的问题,只需考虑常见的基于票证的参与模型:BI 分析师收到票证,执行请求,返回答案,通过更多票证获得反馈,然后循环继续。对话甚至可能不会发生。
现在,如果你是与 BI 团队一起工作的人,你可能会认为这种参与模式正是你想要的。很公平——听起来确实很有效率和条理。
但相信我,这不是你想要的。
只要想想提取有意义和可操作的见解所需的工作性质。即使目标是保持分析的简单性,您也总是会在分析之旅中结束,这涉及到将数据分段、创建基线、构建派生的度量标准等等。这需要分析师的所有权和创造力。
但是在 BI 参与模型中,分析师仅仅是跟随其他人的思路。失去了所有权和创造力。
那么这里有什么解决办法呢?**首先,总是用这两个问题开始任何“BI”分析或仪表板:(1)我们试图解决的问题是什么?(2)我们希望采取什么行动?从那时起,分析师就有责任寻找问题背后的问题,并在问题浮出水面时分享见解。门票将被面对面的会议取代,并形成共生的伙伴关系。如果人们找不到时间,那么这个问题从一开始就不重要。
如果你已经走到这一步,你可能会认为我是在建议将所有的商业智能分析师转变为数据科学家。但事实并非如此。虽然 ETL 和数据探索是任何将数据转化为现金流的团队的核心,但还是有一些关键的区别:
数据科学家应该(主要)致力于开发基于先进方法的“数据产品”。这可能是推动产品推荐或定价和匹配算法的 ML 模型。
另一方面,分析师的关注点可能是提供一个带有战略建议的幻灯片或一个仪表板。事实上,我更喜欢用“战略分析”这个术语来称呼这些团队,因为它描述了他们角色的目的。
数据科学和战略分析这两个职能都非常重要,有明确的目的,需要不同的能力,并提供有益的职业道路。大多数公司都需要这两个团队,但不需要 BI 团队。因此,如果你正在管理一个 BI 团队,是时候改变他们的任务和利益相关者的参与模式了。让我们彻底告别“商业智能”这个术语。
第一场民主党初选辩论:初步情绪分析
在佛罗里达州迈阿密举行的 2020 年初选的第一场辩论中,美国民主党的 20 名候选人在两个晚上相互指责,试图让别人听到自己的声音,有时会忘记回答问题。无论你是已经关注了一段时间,还是刚刚开始关注,都很难区分候选人,也很难感受到每个人在如此拥挤的领域中的表现。
以下图表是从第一场辩论前 7 小时到第二场辩论后 7 小时推特对每位候选人的反应快照。计数值是根据每条推文中信息的测量情绪而被标记为负面、中性或正面的推文。由于数据量少,一些候选人被排除在外。
对 15 名候选人的看法
Count of reaction sentiment for each candidate
第一夜集锦
Indicators of good reception
朱利安·卡斯特罗(Julian Castro)和图尔西·加巴德(Tulsi Gabbard)在首场演出中的表现似乎受到了好评。用户参与度明显上升,这是相当积极的。在第二场辩论后,这种兴趣可以被视为随着对话的进行而逐渐消退,但看看他们的竞选活动如何利用最初的关注热潮将是有趣的。
Indicators of waning attention
在第一场辩论开始时,贝托和布克似乎受到了高度关注,尽管被认为基本上是负面的。第二天,对这两个人的提及逐渐减少,第二天晚上就完全消失了。对于大多数候选人来说,这种下降从第一天晚上开始就是典型的。
第二晚亮点
Strong momentum going in and coming out
卡玛拉·哈里斯被认为是初选的领先者之一,这可以从她在辩论前的势头中看出。在第二个晚上的强劲表现之后,她似乎保持了一些这种膨胀,情绪的平衡从负面进入到正面出来。
Sustained momentum before and after
尽管在较小规模的推文中,皮特市长设法在辩论前后保持用户的一致参与,就数量而言,很少有候选人能够做到。此外,情绪的分布从相当平衡的进入(积极和消极反应的数量相似)变为基本积极的离开。
这些只是从上面的信息中提取的一些信息。请在下面分享自己的想法和评论!欢迎对分析的批评(但请保持中立或更高的情绪!).
关于分析的注释
使用 Tweepy 对与每位候选人的 Twitter 账户相关的推文样本进行流式传输。每条推文的情绪(即情绪反应)是使用 VADER 计算出来的。
查看这些图表时,应考虑几个限定条件。只有直接提到候选人的推文被计算在分析中,这可能会倾向于更极端的反应。此外,第二场辩论后的推文量似乎低得令人怀疑,这让我相信大多数讨论都从与候选人的直接互动转向围绕辩论主题本身的讨论。这种音量的下降也可能是我的数据被捕获和存储的一个缺陷,因为推文的速度对我苦苦挣扎的 MacBook Air 来说往往太快了。在未来,我将着眼于围绕#DemDebate 这样的标签进行更广泛的讨论,并使用实体识别将它们与候选人联系起来。
参考
项目资源库
https://github.com/danjizquierdo/1stPrimaryDebateNight2020
使用维达
进行情绪分析 https://medium . com/analytics-vid hya/simplified-social-media-opinion-Analysis-using-Vader-in-python-f9e 6 EC 6 fc 52 f作者 Parul Pandey
流媒体推文教程
https://www.youtube.com/watch?v=wlnx-7cm4Gg由 Lucid 编程
第一次 Kaggle 比赛经历
我第一次参加 kaggle 比赛的经历
Photo by Victoire Joncheray on Unsplash
在我今年自学机器学习之旅的最初计划中,我曾承诺在任何两场(直播)Kaggle 比赛中进入前 25%。
这是一篇关于“rm-rf /”团队如何在我们有史以来的第一次 kaggle 比赛中进入前 30%的记录:“快,抽!涂鸦识别挑战”,由谷歌人工智能团队主办,在 kaggle 上。
特别说明:团队“rm-rf /”是由我的商业伙伴和朋友 Rishi Bhalodia 和我组成的两人团队。
经验
想象一下:一场持续三个月的比赛。没有终点线,有高分。你是学校里经验丰富的跑步运动员。
有什么问题吗?
你反对我光着脚跑的时候有人开着超跑超速(经验丰富的特级大师)。当然,我很擅长对付我的朋友,但是对付一辆车呢?
从某种意义上说,这就像一个 PUBG 游戏,我们自由落体到战斗中,抓住任何我们能抓住的枪,试图到达“安全区”。
对我们来说,安全区是奖牌区。
那么为什么大家都那么沉迷 Kaggle 呢?
就我个人而言,在这一个月的比赛中,我学到的东西比我参加的任何一个月的 MOOC 都要多。
kaggle 上的“专家”总是慷慨地给出他们的想法。我们感到惊讶的是,许多人几乎给出了他们的完整解决方案——在最高的 LB 位置上!
每天晚上我们都会做一个很好的提交,第二天你醒来的时候,你会在磅上下降 20 级!点击重置,再次朝着更好的提交工作,然后每天重复一次。
最后,我们在 Private LB 上得到了 385/1316:我们在给定计算上的想法只允许达到这个等级。这绝对是一次奇妙的经历,我一定会参加更多的比赛,努力表现得更好。
在许多情况下,当我们在熟睡后设法获得前 100 名提交时,我们会醒来发现一个公共内核会将我们完全抛下 LB 50 个位置!!
参加竞赛的人是真正有激情的,总是有溢出的想法,总是有溢出的才华。对我们来说,这只是尽我们最大的努力,用最少的睡眠生活几个星期,打破和建立 conda 环境,同时试图将讨论中分享的想法转换成代码。
最终,我真正了解了为什么 Kaggle 是数据科学之家。
目标
在高尔夫比赛中表现出色一直是我的梦想目标。首先,我保持了前 25%提交的门槛。
涂鸦挑战:
尽管比赛有大量的文件大小和一些有趣的挑战,我们的目标是我们最好的奖牌。
竞争
**目标:**目标是从包含“绘制”或创建涂鸦信息的 CSV(s)文件数据集中识别涂鸦。
挑战是:挑战中的文件数量约为 5000 万!
就我个人而言,我已经完成了大量的 MOOC(s ),而且我很有信心,因为我已经过了多少次 CNN 的定义,获得铜牌是相当容易的。当然,我错得很离谱。
不起作用的东西
我们非常感谢 Kaggle 大师 Radek Osmulski 分享他的 Fast.ai 入门包——我们是在它的基础上加上白鲸大师的一些技巧构建的。
错误 1:作为初学者,在竞争还新鲜的时候开始一场纸牌游戏比赛总是有启发性的。
为什么?
竞赛中溢出的想法数量是巨大的!即使是 LB 的最高得分者也非常慷慨地分享他们的方法——这只是一个我们是否能找出丢失的信息并能将他们的想法转换成代码的问题。
自从比赛开始以来,我们已经进行了将近一半。
错误 2:我们学习了“实验”,验证。
starter pack 适用于 1%的数据,我尝试用 5%的数据进行试验,然后用 10%的数据进行试验,结果显示性能持续提高。
接下来:我决定把所有的数据都扔给模型,训练在我的 8 GB GPU 上运行了大约 50 个小时。我们期望这种方法能获得最高分,但是模型的准确性却下降了!
经验教训:实验非常重要,验证也是如此。starter pack 依赖于将图像“绘制”到内存中,然后在其上训练模型。Linux 的问题是,它对文件的数量有限制,除非有专门的格式。
我们没有进行验证检查,而是根据一部分数据进行训练。反射验证集肯定是您在开始时必须安装的东西。
有效的想法
渐进式训练和调整规模:
- 用 256 图像大小对 1%的数据训练模型。
- 将模型微调为 128 图像大小的 5%的数据。
- 此外,微调模型到 20%的数据与 64 图像大小。
- 当在数据集的相同部分上进行训练时,ResNet 18 < ResNet 34 < ResNet 50 < ResNet 152。
这种方法显示了性能的持续提高。
集成:我们最好的提交是在 20%的数据集上用 fastai (v1)训练的 ResNet 152 和 Kaggle GM Beluga 的 MobileNet 内核的“混合”。
摘要
你会在竞赛讨论中发现许多更好的讨论,所以如果这些想法没有让你获得最高的 LB 分数,请原谅这篇文章。
这真的是我在比赛中学到的东西的个人总结。
最后,我保证会参加更多的比赛,希望你会在最近的比赛中发现“rm-rf /”队。
我已经被“Kaggle Bug”咬了一口,比起注册更多的 MOOC,我可能更喜欢未来的比赛
LB 上见,快乐的卡格林!
如果你觉得这些面试很有趣,并且想成为我的学习之路的一部分,你可以在 twitter 上找到我 。
如果你有兴趣阅读关于深度 学习 和计算机视觉的新闻,可以查看我的 简讯这里 。
第一个为初学者讲解的神经网络(带代码)
理解并创造一个感知机
Photo by Clément H on Unsplash
所以你想创建你的第一个人工神经网络,或者只是发现这个主题,但不知道从哪里开始?按照这个快速指南来理解所有的步骤!
什么是神经网络?
基于自然,神经网络是我们对大脑的通常表示:神经元与其他神经元相互连接,形成一个网络。一个简单的信息在变成一个实际的东西之前会在它们当中传递,就像“移动手来拿起这支铅笔”。
完整的神经网络的操作非常简单:输入变量作为输入(例如,如果神经网络应该告诉图像上的内容,则输入图像),经过一些计算后,返回输出(按照第一个示例,给出猫的图像应该返回单词“cat”)。
现在,你应该知道人工神经网络通常放在列上,所以列 n 的一个神经元只能连接到来自列 n-1 和 *n+1 的神经元。*使用不同架构的网络类型很少,但我们现在将关注最简单的。
所以,我们可以这样描述一个人工神经网络:
Figure 1 — Representation of a neural network
神经网络通常可以从左向右阅读。这里,第一层是输入的层。有两个内部层(称为隐藏层)做一些数学,最后一层包含所有可能的输出。不要为每一列底部的“+1”而烦恼。这就是所谓的“偏见”,我们稍后会谈到这一点。
顺便说一下,术语“深度学习”来自包含几个隐藏层的神经网络,也称为“深度神经网络”。图 1 可以被认为是一个。
神经元做什么?
每个神经元完成的操作非常简单:
Figure 2 — Operations done by a neuron
首先,它将它所连接的前一列中的每个神经元的值相加。在图 2 中,有 3 个输入(x1,x2,x3)到达神经元,因此前一列的 3 个神经元连接到我们的神经元。
该值在相加之前乘以另一个称为“权重”的变量(w1,w2,w3),该变量决定两个神经元之间的连接。神经元的每个连接都有自己的权重,这些是在学习过程中唯一会被修改的值。
此外,可以将偏差值加到计算的总值上。它不是来自特定神经元的值,而是在学习阶段之前选择的,但对网络是有用的。
在所有这些求和之后,神经元最终对获得的值应用一个称为“激活函数”的函数。
Figure 3 — Sigmoid function
所谓的激活函数通常用于将之前计算的总值变为 0 和 1 之间的数(例如通过图 3 所示的 sigmoid 函数来实现)。其他函数存在并可能改变我们函数的极限,但保持限制值的相同目标。
这就是一个神经元所做的一切!将连接神经元的所有值乘以各自的权重,相加,并应用激活函数。然后,该神经元准备好将其新值发送给其他神经元。
在一列中的每个神经元完成之后,神经网络传递到下一列。最后,最后获得的值应该是可用于确定期望输出的值。
既然我们了解了神经元的功能,我们就有可能创造任何我们想要的网络。然而,要使神经网络学习,还需要执行其他操作。
神经网络是如何学习的?
是的,创造变量并让它们相互作用是很棒的,但这不足以让整个神经网络自我学习。我们需要准备大量数据提供给我们的网络。这些数据包括神经网络的输入和输出。
让我们来看看学习过程是如何进行的:
首先要记住,给神经网络一个输入,它就返回一个输出。在第一次尝试中,它自己无法获得正确的输出(除非运气好),这就是为什么在学习阶段,每个输入都带有标签,解释神经网络应该猜测什么输出。如果选择是正确的,则保留实际参数,并给出下一个输入。但是,如果获得的输出与标签不匹配,权重就会改变。这些是在学习阶段唯一可以改变的变量。这个过程可以想象成多个按钮,每次输入没有猜对时,这些按钮就变成不同的可能性。
为了确定修改哪个权重更好,需要进行一个称为“反向传播”的特殊过程。我们不会在这一点上停留太久,因为我们将构建的神经网络不使用这一确切的过程,但它包括回到神经网络并检查每个连接,以检查输出如何根据权重的变化而表现。
最后,要控制神经网络的学习方式,还需要知道最后一个参数:“学习速率”。名称说明了一切,这个新值决定了神经网络学习的速度,或者更具体地说,它将如何一点一点地或以更大的步长修改权重。1 通常是该参数的一个好值。
感知器
好了,我们知道了基础知识,让我们检查一下我们将要创建的神经网络。这里解释的一个被称为感知器,是有史以来第一个神经网络。它由输入列中的 2 个神经元和输出列中的 1 个神经元组成。这种配置允许创建一个简单的分类器来区分 2 个组。为了更好地理解可能性和局限性,让我们来看一个快速的例子(除了理解之外没有太大的兴趣) :
假设您希望您的神经网络能够根据“包含或”规则返回输出。提醒:
- 如果 A 为真,B 为真,那么 A 或 B 为真。
- 如果 A 为真,B 为假,那么 A 或 B 为真。
- 如果 A 为假,B 为真,那么 A 或 B 为真。
- 如果 A 为假,B 为假,那么 A 或 B 为假。
如果你用 1 代替“真”的 s,用 0 代替“假”的 s,并把这 4 种可能性作为平面图上的坐标点,那么你会发现最后两组“假”和“真”可能被一条直线分开。这是感知器可以做到的。
另一方面,如果我们检查“异或”的情况(在这种情况下,“真”或“真”(点(1,1))为假),那么我们可以看到一条简单的线不能分开两个组,感知器不能处理这个问题。
因此,感知器确实不是一个非常有效的神经网络,但它很容易创建,并且仍然可以用作分类器。
创造我们自己简单的神经网络
让我们用 Python(下面例子中的 3.x)从头开始创建一个神经网络。
**import** numpy, random, os
lr = 1 #learning rate
bias = 1 #value of bias
weights = [random.random(),random.random(),random.random()] #weights generated in a list (3 weights in total for 2 neurons and the bias)
程序的开始只是定义了库和参数值,并创建了一个包含将要修改的权重值的列表(这些值是随机生成的)。
**def** Perceptron(input1, input2, output) :
outputP = input1*weights[0]+input2*weights[1]+bias*weights[2]
**if** outputP > 0 : #activation function (here Heaviside)
outputP = 1
**else** :
outputP = 0
error = output – outputP
weights[0] += error * input1 * lr
weights[1] += error * input2 * lr
weights[2] += error * bias * lr
这里我们创建一个定义输出神经元工作的函数。它需要 3 个参数(神经元的 2 个值和预期输出)。“outputP”是对应于感知器给出的输出的变量。然后我们计算误差,用于修改每个连接到输出神经元的权重。
**for** i in range(50) :
Perceptron(1,1,1) #True or true
Perceptron(1,0,1) #True or false
Perceptron(0,1,1) #False or true
Perceptron(0,0,0) #False or false
我们创建了一个循环,让神经网络将每种情况重复几次。这部分是学习阶段。迭代的次数是根据我们想要的精度来选择的。但是,请注意,过多的迭代可能会导致网络过度拟合,从而导致网络过于关注已处理的示例,因此在学习阶段没有看到的情况下,它无法获得正确的输出。
然而,我们这里的情况有点特殊,因为只有 4 种可能性,我们在神经网络的学习阶段将所有可能性都给了它。一个感知器应该给出一个正确的输出,而不需要看到它正在处理的案例。
x = int(input())
y = int(input())
outputP = x*weights[0] + y*weights[1] + bias*weights[2]
**if** outputP > 0 : #activation function
outputP = 1
**else** :
outputP = 0
**print**(x, "or", y, "is : ", outputP)
最后,我们可以要求用户输入自己的值来检查感知器是否在工作。这是测试阶段。
在这种情况下,使用激活函数 Heaviside 是很有趣的,因为它将所有值精确地恢复为 0 或 1,因为我们正在寻找一个假或真的结果。我们可以尝试使用 sigmoid 函数,获得一个介于 0 和 1 之间的十进制数,通常非常接近其中一个极限。
outputP = 1/(1+numpy.exp(-outputP)) #sigmoid function
我们还可以将神经网络刚刚计算出的权重保存在一个文件中,以便稍后使用,而无需进行另一个学习阶段。对于更大项目来说,这个阶段可能会持续几天或几周。
就是这样!你已经完成了自己完整的神经网络。你创造了它,让它学习,检查它的能力。你的感知器现在可以被修改来用在另一个问题上。只要改变迭代过程中给定的点,如果你的情况更复杂,调整循环次数,让你的感知器做分类。
您是否希望列出最近的森林中的两种类型的树,并能够确定新树是 A 型还是 B 型?选择两个可以分离两种类型的特征(例如高度和宽度),并为感知器创建一些点以放置在平面上。让它推导出一个方法来分开 2 组,并输入任何新树的点,以了解它是哪种类型。
你以后可以扩展你的知识,看到更大更深的神经网络,这是非常强大的!
还有多个方面我们没有治疗,或者仅仅够你得到基本的,所以不要犹豫进一步。我很想写一些更复杂的神经网络,所以请继续关注!
感谢阅读!
我希望这个小指南有用,如果你有任何问题和/或建议,请在评论中告诉我。
激光诱导击穿光谱中的一阶多元校正
激光诱导击穿光谱(LIBS)是最简单和最强大的光谱化学技术。本文介绍了 LIBS 光谱定量分析中常用的线性回归方法。
激光诱导击穿光谱
L 激光诱导击穿光谱(LIBS)是目前分析化学中最简单也是最强大的技术之一。其多功能性允许对复杂样品进行详细的定性和定量分析,无论是固体、液体还是气体形式。此外,被分析的样品可以是任何尺寸或形状,包括粉末、浆体和气溶胶。LIBS 仪器可以做得坚固耐用,便于携带,可以在任何环境下使用,包括危险的环境。只需要对样品进行光学访问,并且可以在几十米的距离进行测量。数据采集速度快,LIBS 仪器的操作可以很容易地自动化。
在现有的不同分析技术中,LIBS 可以归类为多元素光谱化学技术,它由激光-物质相互作用的物理学控制(这种相互作用对 LIBS 测量有巨大的影响,因为它控制所有中间物理过程,如电子和离子加热、热扩散、粒子烧蚀和动力学以及等离子体形成和膨胀)。
A short-pulsed high-power laser beam is focused onto a sample surface, producing dense hot plasma plume for spectroscopic analysis. Image credit: Applied Spectra, Inc.
在实践中,LIBS 是通过将强激光束(通常来自脉冲纳秒 Nd:YAG 激光器)聚焦到样品表面上以产生烧蚀材料的热离子化气体(所谓的等离子体羽流)来进行的。来自受激物质复合的等离子体光发射出样品中存在的元素的原子发射谱线特征,然后被收集并引入光谱仪,在光谱仪中被分散成离散的波长。一旦等离子体温度和电子密度充分下降,并且观察原子谱线的条件是最佳的,就进行 LIBS 光谱的采集(使用门控 CCD 照相机)。
下图显示了从土壤样品中获得的典型 LIBS 光谱,显示了各种化学元素的强发射线。
Typical LIBS spectrum (in 210–850 nm range) of a soil sample.
由于其独特的特点,人们对 LIBS 的兴趣迅速蔓延。每年发表的研究论文数量很好地说明了这种兴趣。工业应用的数量也是如此,近年来增长迅速,例如在环境分析、冶金工业、考古学、生物学、安全和空间探索方面。例如,自 2012 年 8 月 19 日以来,作为美国宇航局火星科学实验室好奇号任务的一部分,由美国能源部洛斯阿拉莫斯国家实验室和法国 CESR 实验室开发的用于探索火星盖尔陨石坑的 ChemCam LIBS 仪器已经提供了数千次对火星岩石和土壤元素组成的宝贵分析。超级摄像机是 ChemCam 的改进版本,计划于 2020 年夏天通过火星车任务发射,并于 2021 年冬天在 Jezero 陨石坑内着陆。
SuperCam instrument. Image credit: NASA.
一阶多元校准
在过去的几十年里,在 LIBS 使用化学计量学方法,尤其是一阶多元校准曲线,已经显著提高了其分析性能,因为多元统计方法已经允许利用 LIBS 光谱中通常存在的冗余信息。在化学计量学中,在从未知样品预测分析物浓度之前,校准模型通过多元回归方法建立,并被训练以学习光谱-浓度关系。但首先让我们定义术语“一阶校准”。
光谱数据的结构数据
在数学中,张量是代数对象,可以用一个标量(秩为 0 的 0 阶张量)、一个向量(秩为 1 的 1 阶张量)和一个矩阵(秩等于其矩阵秩的 2 阶张量)来表示。在化学计量学中,张量的阶指的是张量所跨越的模式或空间的数量。张量的秩(尽管没有完全理解,特别是对于高阶张量)可以定义为其线性组合再现该张量的秩为 1 的张量的最小数量。这与矩阵的秩不同,矩阵的秩在线性代数中被定义为线性独立元素(行或列的向量)的最大数量。换句话说,或者用化学计量学的术语来说,
双向矩阵的秩是复制矩阵所需的双线性(PCA)分量的最小数目。而三路数组的秩是再现该数组所需的三线性(PARAFAC)分量的最小数目。拉斯莫斯兄弟
当来自多个样品的测量响应是标量(零阶张量)时,它们可以排列在一个向量中,从而给出一个单向数据结构(例如多个溶液的 pH 测量)。另一方面,如果响应是一阶张量,则它们产生双向数据结构(例如,LIBS 光谱数据,其提供一组不同波长的发射强度)。最后,使用两种仪器(例如 LIBS 与拉曼光谱仪协同工作)或一组二阶响应(例如瞬态系统的 LIBS 测量)涉及处理三维数据阵列,即三向结构。概括地说,来自每个分析样本的一组 i 阶数据创建了一个( i +1)向结构。
Examples of data structure.
单变量校准模型
我们将校准曲线定义为一个模型,该模型由一组经认证的参考材料或标准物质(即,其性质由经认证的实验室或机构准确定义和认证的样品)或参考样品(即,之前通过成熟方法分析的样品)开发而成,其中分析物含量和 LIBS 光谱是已知的(下图说明了典型的线性和二次校准曲线)。注意,建立在来自一组校准样品的单值响应(例如发射线的信号)上的经典校准曲线是零阶校准模型的一个例子。
Linear (left panel) and non-linear (right panel) calibration curves. Note that LOD, LOQ, and LOL refer to the limit of detection, of quantification, and of linearity. These parameters are respectively defined as (1) the lowest analyte concentration likely to be reliably distinguished from a blank sample and at which detection is feasible, (2) the lowest concentration at which the analyte can not only be reliably detected but at which some predefined goals for bias and imprecision are met and, (3) the upper limit of the dynamic range for which the relationship is linear. The slope of the regression line defines the sensitivity of the calibration model.
校准曲线通常与相应的置信限和预测限一起提供,如下图所示。
Confidence and prediction intervals for the classical least-squares straight-line fit. LCL and UCL are the lower and upper confidence limits. Likewise, LPL and UPL are the lower and upper prediction limits. ĉ is the predicted concentration from the measured signal of an unknown sample.
置信限(LCL 和 UCL)给出了估计平均值的一个区间(即通过重复测量计算得出),该区间覆盖了概率为 1-α的总体平均值(α = 0.05,置信水平为 95%)。然而,预测极限(LPL 和 UPL)给出了概率为 1α的新样品( ĉ )浓度的预测不确定性。
Example of univariate calibration curves for the detection of Ca, Sr, K, and Li in aqueous solutions. Source: Goueguel et al., Matrix effect of sodium compounds on the determination of metal ions in aqueous solutions by underwater laser-induced breakdown spectroscopy, Applied Optics, 54, 6071, 2015.
重要的是要注意,单变量校准模型的灵敏度(即回归线的斜率)将取决于发射线的光谱特征。通常根据三个主要标准选择该谱线:(1)最强,(2)不可能自吸收,以及(3)没有光谱干扰。另一方面,在多变量校准模型中,灵敏度将根据是选择考虑整个光谱还是选择一些谱线而受到影响。此外,使用曲线下的面积(峰面积)而不是峰强度通常更合适。估算峰面积的直接方法是用高斯或洛伦兹曲线拟合峰,或使用数值积分技术,如牛顿-科特斯公式(如梯形法则)或高斯积分。
多元校准模型
因此,在熟悉了单变量校准曲线的基础知识后,现在有趣的是注意到多变量校准可以根据光谱-浓度关系分为直接校准或反向校准。在直接多元校准模型中,假设 LIBS 信号与分析物浓度成比例。该模型似乎是经典单变量模型的推广,可以通过经典最小二乘(CLS)回归进行估计。而在逆多元校准中,假设浓度与 LIBS 信号成比例。在这种方法中,通过反最小二乘法(ILS)从一组校准样本中估计回归系数。
在下文中,我们将看到 ILS 回归(即多元线性回归(MLR) )具有有限的适用性,尤其是在处理高度相关的预测因子(LIBS 光谱)或样本少于包含复杂矩阵效应的变量时。幸运的是,已经提出了许多替代的回归方法来处理这种情况。
直接多元校准
光谱 = f ( 成分)
信号=灵敏度×浓度+误差
逆多元校准
构图 = f ( 光谱)
浓度=信号××回归系数+误差
使用反向校准优于直接校准的原因在于,当我们只知道校准样品中目标分析物的浓度,而对其他成分的浓度一无所知时,可以应用字母。因此,逆多元校准不仅能够预测分析物的浓度,还能够预测样品的物理性质(例如,我们发表了一篇研究文章,其中我们能够仅根据 LIBS 光谱预测土壤颗粒大小的分数)。这个基本概念是应用于 LIBS 定量分析的化学计量学方法的基础。因此,在下面的讨论中,我们将只对反校准方程感兴趣,它可以写成:
其中 c 是分析物浓度(或样品物理特性)的 n ×1 向量, S 是包含在 p 不同波长测量的n×p 校准样品的 LIBS 信号的n×p 矩阵,b是p因此,未知回归系数的普通最小二乘(OLS)估计值可使残差的误差平方和最小化,由下式给出:**
这导致了
随着
S +是 S 的摩尔-彭罗斯伪逆。上标“t”的意思是“转置”。预测浓度 ĉ 由下式给出:
其中 H 为帽子矩阵 S ᵗ S 为协方差矩阵(维数 p × p ),为方阵。对上述方程的一个几何解释是:将***【c】***正交投影到 S- 空间,以 H 为正交投影矩阵,得到 ĉ 。
值得一提的是,逆校准方程代表一个由 n 个方程(i )组成的系统。 e *。*校准样本的数量)与 p 未知数(i )之比。 e *。*待估计的回归系数个数,与光谱波长个数重合)。在 LIBS,不同波长的紫外光、可见光和近红外光的数量一般都在数万的数量级上(使用任何一种中分辨率的宽带阶梯光栅光谱仪),这样 p > > n (也就是俗称的维度诅咒 ) 。
我们在这里面临的第一个问题是 MLR 应用于 LIBS 数据,因为求解方程需要比波长更多的校准样本。
制备大量校准样品通常不被认为是可行的选择,因为除了耗时之外还需要额外的成本。此外,即使我们能够添加更多的校准样本来求解该方程,协方差矩阵也必须是可逆的(即,非奇异矩阵)。另一方面,如果至少一个预测变量(1)与另一个变量成比例,(2)是其他变量的线性组合,(3)是常数,以及(4)变量多于观测值,则协方差矩阵是奇异的。
我们现在面临第二个问题,因为高维 LIBS 数据中的多重共线性使得协方差矩阵奇异*。*
方阵 S ᵗ S 不是满秩 p 的事实对几种机器学习方法的选择和适用性有着深远的影响。事实上,正是由于这个原因,化学计量学从业者更喜欢不需要协方差矩阵的逆矩阵的机器学习方法。这就是为什么,分解和收缩回归方法被提出来处理这样的病态问题。众所周知的线性方法有:
- 主成分回归 (PCR)
- 偏最小二乘回归 (PLSR)
- 岭回归 (RR)
- 连续回归 (CR)
- 主协变量回归 (PCovR)
在下文中,我将简要介绍这些回归方法,尤其是 PCR、PLSR 和 RR。
主成分回归
PCR 已经被提议作为一种技术,其将预测因子的数量减少到不相关成分(潜在变量)的较小集合,并且对这些成分执行最小二乘回归。在 PCR 中,从预测数据的主成分分析(PCA) 中获得成分作为主成分(PCs),即校准光谱 S 。通过这样做,当预测因子高度共线时,PCR 提供了一种替代方法。 S 被分解(或分解)为(对象)得分 T ( n × r )和(可变)载荷P(P×r)的乘积。 T 总结被分析样本之间的关系(相似或不同),而 P 总结变量(或波长)之间的关系(正相关或负相关)。 T 和 P 中的列数等于 S 的秩 r ,通常小于 n 或P
Illustration of the PCA decomposition of matrix S.
在下面的中,我们假设 T 和 P 只包含第一个 j 列,指的是保留的 PCs 数量,通常通过交叉验证来选择。通常, S 是通过减去它的平均值而以平均值为中心的。
逆校准公式可以改写为:
PC 分数 T 用作浓度的回归量,由 T = SP 决定。因此,通过应用逆校准方程,分析物浓度 c 与分数 T 相关,而不是原始数据矩阵 S. 大小为 j ×1 的回归系数向量由下式给出:
预测浓度 ĉ 由下式给出
其中 T +是 T 的 Moore-Penrose 伪逆。这解决了多重共线性问题,因为 T ᵗ T 的反演是微不足道的,因为这是一个对角矩阵,因为 T 的列是正交的。回想一下,对角矩阵的逆矩阵简单地由一个对角矩阵给出,它的元素是原始元素的逆矩阵。
偏最小二乘回归
已经提出 PLSR 作为改进 PCR 的方法,通过在潜在变量的估计中引入关于分析物浓度的信息。换句话说,PLSR 采用依赖于 c 的潜在变量,而 PCR 采用独立于 c 的潜在变量。如同在 PCR 中一样,通过将分析物浓度***【c】***与样本分数 T 相关联来开发反向校准模型。该数学关系在形式上与 PCR 的数学关系相同。差异在于估算 PLSR 得分矩阵的方式。可以看出,回归系数向量由下式给出:
可以写成
随着
R (或通常称为 W* )是权重矩阵,而 W 是载荷权重。与 PCR 相反, T 由 T = SR 决定。 PLSR 容易处理多重共线性,因为在 P ᵗ W 的反演中没有发现问题,因为 P 和 W 分别是正交和正交矩阵。在继续之前,我想在这里提一下正交偏最小二乘(OPLS) 回归,它是 PLSR 的修改版本,将是未来讨论的主题。
你听说过正交偏最小二乘法(OPLS)吗?
towardsdatascience.com](/an-overview-of-orthogonal-partial-least-squares-dc35da55bd94)
里脊回归
虽然 PLSR 是化学计量学中最流行的回归方法,但其他基于正则化最小二乘方法 的现代机器学习方法,如岭回归,也经常用于多变量校准。在 RR 中,要最小化的目标函数可以写成:
因此,
I 是单位矩阵,λ是通过交叉验证确定的正则化参数。关于 LIBS 数据,岭回归中最重要的方面是确定b 所需的矩阵求逆总是可能的,即使当协方差矩阵是奇异的并且不能求逆时。因此,RR 通过惩罚高方差系数来处理多重共线性。
连续回归
PLSR(Setc之间的最大协方差)形成了 MLR(Setc之间的最大相关)和 PCR(S中的最大方差)之间的折衷。这使得 Stone 和 Brooks 开发了一种方法,它是上述回归方法的延续,MLR、PLSR 和 PCR 是其特例。****
主协变量回归
PCovR 是一种连续回归,它结合了 PCR 和降秩回归。
更进一步:二阶多元分析
为了选择最合适的化学计量方法,必须考虑影响数据线性的任何物理性质或化学相互作用。正是由于这个原因,多路尤其是三路数据分析已经成为化学计量学中的一个重要课题(例如,基于低秩张量分解的众所周知的方法是 Tucker3、PARAFAC 和 N -PLS)。Tucker3 (T3)和并行因子分析(PARAFAC)也称为规范分解(CANDECOMP)或规范多点分解(CP),是矩阵奇异值分解(SVD)和双线性 PCA 的高阶推广,而 N -PLS 推广了双线性 PLS。如前所述,三向数据阵列(即二阶张量)是由 n 行(模式 1)、 p 列(模式 2)和 k 水平切片(通常称为管)定义的。
三向分析的一个简单方法是将三向数据数组展开成k×(n×p*)、n×(k×p)和p×(n×k)两向表,然后可以根据回归分析这些表然而,对这些展开数据中的每一个进行分析都不太可能产生可靠的结果来真正揭示复杂的化学相互作用,此外还会受到过量输入和计算成本的影响。*
从动手项目开始机器学习
黑进去
你如何从一开始就着手动手做项目
探索精神是生命中最珍贵的礼物,它非常热衷于学习,没有任何评判的眼光 ― 眼虫
谁能学?
如果你是一个机器学习爱好者,热衷于学习,那么开始你在数据科学和机器学习领域的旅程永远不会太迟。
由于数据的数量每天都呈指数级增长,并且有许多免费资源可用,这为我们研究数据并从中提取一些有意义的输出提供了一个很好的机会。
但是为什么入门这么难呢?
对于像我们这样的初学者来说,这是一项具有挑战性的任务。数据科学和机器学习是计算机爱好者中最热门的话题,因此互联网上有许多分散的资源,很容易使我们偏离道路。
在其核心,数据科学是一个研究领域,旨在使用科学的方法从数据中提取意义和见解
另一方面,机器学习是指数据科学家使用的一组技术,允许计算机从数据中学习。
如果你只是谷歌搜索任何关于数据科学和机器学习的主题,你可能会被大量的资源淹没,并且很难抓住一个路线图并遵循它。
Overwhelming resources
动机
因此,在这篇文章中,我将分享我是如何通过做一些实践项目来开始自己的旅程的,并为每个人提供一些神圣的学习资源。
我将分享你如何用一些 ML 算法和数据弄脏你的手。
入门指南
首先,每个人都可以通过谷歌搜索或简单的 YouTube 搜索来轻松学习入门部分。
如果你像我一样,更喜欢视觉+音频教程来更好地理解,那么你可以从 谷歌的机器学习食谱 开始。这是一个很好的资源,可以从一些例子开始。从那里你可以了解机器学习算法,并建立一些。
掌握概念
在这个过程中,你也可以查看其他资源,并很好地掌握机器学习的内容、方式和原因。这不是一蹴而就的事情,所以要学会有些耐心,优雅地感受数据科学的美好。
在与数据科学的每一次交流中,一个人得到的要比他寻求的多得多。
— 任何人
由于网上有很多可用的资源,一个人应该学会找到适合自己水平的丰富和优质的资源。
例如:如果你想学习一些算法在运行中的样子,尝试一些使用库的小教程,并开发一些小东西。之后,你可以通过简单的谷歌搜索来了解这个算法:“数学背后的 <算法>”。
这需要时间,但一旦你找到适合你的好资源,你就可以轻松地学习。
基础知识之后的动手项目
有了一些基础知识之后,就可以学习其他各种算法了。对你来说,从一开始就知道一切并不重要。你可以:
- 从一个开始,从不同的作者和资源中了解它。例如:尝试在谷歌搜索*“线性回归初学者指南”*,从你得到的第一个帖子开始。
- 从中创造一些东西;一些能激励你并让你感到快乐的事情。保持动力非常重要,这就是为什么阅读+在一些项目中运用这些知识非常重要。它帮助你看到你所学的实际输出。
我是怎么开始的?
在做了一些基础之后,我实现了一个梯度下降:这是 这个 项目中的一个学习算法,它帮助我理解了一个机器学习模型是如何学习的。在这里,你可以在任何地方绘制两个或更多的点,它试图学习(减少误差)并最好地拟合这些点之间的直线。
Linear Regression using Gradient Descent
很有趣,不是吗😁?你可以在 YouTube 上找到一个关于这个和其他一些算法的很棒的视频,通过编码训练 这里 。
如果你是一个爱看书的人,试着用 sci-kit learn 和 Tensorflow 阅读 手动机器学习。
最后的话
我真的希望你会喜欢这次旅行。总是从小事开始,不断成长。
一个人永远不应该停止学习这个领域的新东西。每天都有新的有趣的事情被研究,所以,继续学习,保持好奇!😄
迈向数据科学的第一步
数据科学之旅
kaggle 竞赛入门
Source: https://miro.medium.com/max/1053/1*gO6yZ3Z855MW26FuEiQjKw.png
Kaggle 是数据科学家的 AirBnB 这是他们度过夜晚和周末的地方。这是一个众包平台,旨在吸引、培养、培训和挑战来自世界各地的数据科学家,以解决数据科学、机器学习和预测分析问题。— 齐山-乌尔-哈桑·乌斯马尼
介绍
如果你想涉足数据科学,Kaggle 是最好的起点。如果你愿意,那么你可以阅读所有的什么和为什么在:https://www.kaggle.com/getting-started/44916。相信我,这是值得的。
让 Kaggle 如此棒的一个主要原因是,你可以找到数据集,而没有任何数据收集的麻烦,并且可以在云中编写和运行代码。你也可以使用谷歌的ColabJupyter 笔记本和他们的 GPU & TPU 来编写和运行你的代码。他们是自由的。
您可以轻松注册 平台 和 入门比赛 。我将通过参加 房价:高级回归技术 竞赛向大家展示如何预测房价。会很棒的,我们开始吧。
入门指南
让我们转到笔记本部分,在 Kaggle 上创建一个新的笔记本:
Notebook on Kaggle
启动笔记本后,你会看到一个漂亮的笔记本平台,左边有一个可用的数据集列表。
Kaggle’s Notebook
现在在开始写一些代码之前,我们先要了解一下机器学习流水线
ML 管道
虽然 Kaggle 通过提供数据集使我们变得容易,但处理和清洗数据并从中提取相关特征以及识别数据集中的异常值仍然具有挑战性。这整个过程被称为 数据角力 ,是特征工程的一部分。
让我们看看我们得到了什么类型的数据;我们将使用 Pandas:数据分析库来分析数据集。正如你在笔记本中看到的,Pandas 和 NumPy 库已经被导入。我们有两个数据集文件:train.csv 和 test.csv 另一个 sample_submission.csv 只是我们的提交应该是什么样子的示例。
代码部分
让我们看看训练和测试集的头部数据。
train and test set
如您所见,我们在训练集中有 81 列,在测试集中有 80 列;这是因为在测试集中没有给出标签列(SalePrice)* 。我们必须通过基于训练集训练模型来预测给定功能的销售价格。我们还应该拥有该领域的专业知识,这样我们就更容易知道自己在做什么。例如:对于这个项目,我们预测房子的销售价格,最重要的领域特征是:房子状况,位置如何,房子有什么特征等等。***
我们已经给出了一组特征和一个标签,我们预测的是给定特征的连续值,而不是分类值;所以这是一个明显的 回归问题而不是一个 分类问题 。
Classification and Regression
现在我们要用训练集(train.csv)来玩一下,检查 SalePrice 数据的偏斜度。
正态分布的数据更容易分析
The skewness of the SalePrice data
正如我们可以看到的,SalePrice 是右(正)倾斜的,我们使用 matplotlib 和 seaborn 来可视化数据。
现在是数据转换的时候了。我们可以使用日志将数据转换成正态分布的数据:
log transform of the data
我们使用了一个以为基数 10 的对数,现在数据呈正态分布。要了解我们为什么使用日志来转换数据,请观看此视频。
Logarithms — Real-Life Applications
之后,我们可以检查我们的概率图:
Probability Plot
看起来不错,我们可以前进了。
checking the correlation
现在我们必须检查高度相关的数据。首先,我们提取所有数字数据类型的特征,并检查这些特征与销售价格的相关性。
前五个特征与销售价格高度相关;意思是——这些值是线性相关的,对销售价格有很大影响。
正如我们所看到的,GarageArea 也与销售价格高度相关。让我们来看一下数据:
visualizing garage area data
x 轴上高于 1200 的几个点是我们数据的异常值。这几个数据会影响模型,所以我们必须消除它们。
removing outlier data points
简单地说,我们通过获取小于 1200 的数据来删除它们。😄只是一个简单的方法。
converting string data to numerical
在我们的数据集中,街道要素有两个唯一值:Pave 和 Grvl。这也是一个有用的特性,但它是字符串数据类型;所以我们正在创建一个函数 mapStreet,将这些数据转换为 Pave 的 0 和 Grvl 的 1。
Sale price with respect to Sale Condition
现在是时候看看相同条件下房子的销售价格了。从上图中我们可以看到,部分销售条件是以高销售价格出售的,因此,为了方便起见,我们将部分销售条件分组为 1,其他销售条件分组为 0。
现在,为了使我们的数据集更好,我们可以删除或使用另一种方法来消除所有的 NAN 或 null 值。现在,我们只是删除它,只保留训练集和测试集上的数值。
现在,我们对 SalePrice 进行 log 转换,并将 train.csv 数据集拆分为两部分: y 用于标签,而 x 用于特征,并再次使用scikitlelarnstrain _ test _ split 方法将它们拆分为训练集和测试集。
终于!现在我们准备训练模型。
首先,我们从 Sci Kit learn 导入一个回归模型库,并给我们的训练集进行训练。您可以为该任务使用任何合适的模式。现在,我们使用线性回归。
我们可以通过在模型上调用一个 fit() 方法来训练我们的数据。它训练我们的模态,我们可以通过使用来检查分数。得分()法。
目前,我们有大约 84%的准确率。没那么糟糕,但是你可以通过调整一些数据和更好的特征工程来提高精确度。
现在是时候准备一个提交文件,在 Kaggle 上提交了。
preparing a submission file
我们使用相同的模型来预测 test.csv 文件中特性的标签,并将所有带有 ID 的输出保存在 submission.csv 文件中。现在,您可以看到您的提交文件并将其提交到 Kaggle 的提交部分,并在公共排行榜中看到自己。
kaggle leaderboard of Hose Price prediction
最后的想法
Kaggle 竞赛是一个接触真实世界数据集的好地方。我希望你学到了一些东西。你可以继续探索 kaggle 上的其他数据集,并通过做令人兴奋的项目继续数据科学之旅。不断学习,保持好奇心。
回归分析的 f 检验
The F-distribution (Source: Wikimedia Commons under CC BY-SA 4.0)
如何使用它,如何解释它的结果
当用于回归分析时,f 检验允许您比较两个竞争回归模型“解释”因变量方差的能力。
f 检验主要用于方差分析和回归分析。我们将研究它在线性回归中的应用。
为什么在回归分析中使用 f 检验
在线性回归中,f 检验可用于回答以下问题:
- 你能通过使你的线性回归模型变得更复杂来改进它吗,例如,通过增加更多的线性回归变量?
- 如果您已经有了一个复杂的回归模型,您是否会更好地用仅截距模型(这是您可以构建的最简单的线性回归模型)来交换您的复杂模型?
第二个问题是第一个问题的特例。在这两种情况下,这两个模型被称为是嵌套。更简单的模型被称为**限制模型。这就好像我们在限制它使用更少的回归变量。复杂模型被称为无限制模型。**它包含了受限模型的所有变量和至少一个以上的变量。
受限模型被称为嵌套在非受限模型中。
Linear regression models: unrestricted, restricted and intercept-only restricted (Image by Author)
让我们通过一个真实世界的时间序列示例来探索 f 检验的使用。我们将首先构建一个仅拦截模型,即受限模型。
简单看一下仅拦截模型
以下时间序列显示了道琼斯工业平均指数在 3 个月内的每日收盘价。
Dow Jones Industrial Average closing price over a 3-month period (Image by Author)
假设我们希望为这个时间序列创建一个回归模型。但是我们不知道什么因素影响收盘价。我们也不想在数据集中假设任何通货膨胀、趋势或季节性。
在没有任何关于通货膨胀、趋势、季节性或存在解释变量的假设的情况下,我们能做的最好的事情是仅截距模型(有时被称为均值模型)。对于我们的时间序列示例,它采用以下形式:
Intercept-only model for the DJIA data set (Image by Author)
在仅截距模型中,所有预测都采用截距 Beta_0 的值。下图显示了实际时间序列背景下拟合的仅截距模型:
Actual and predicted Closing Price of DJIA using the mean model (Image by Author)
下面是产生上述结果的 Python 代码:
导入所有必需的包:
**import** pandas **as** pd
**import** numpy **as** np
**import** matplotlib.pyplot **as** plt
将数据集读入熊猫数据框:
df = pd.read_csv(**'djia.csv'**, header=0, infer_datetime_format=**True**, parse_dates=[0], index_col=[0])
计算样本平均值,并将所有预测值设置为该平均值:
mean = round(df[**'Closing Price'**].mean(),2)y_pred = np.full(len(df[**'Closing Price'**]), mean)
绘制实际值和预测值:
fig = plt.figure()fig.suptitle(**'DJIA Closing Price'**)actual, = plt.plot(df.index, df[**'Closing Price'**], **'go-'**, label=**'Actual Closing Price'**)predicted, = plt.plot(df.index, y_pred, **'ro-'**, label=**'Predicted Closing Price'**)plt.xlabel(**'Date'**)plt.ylabel(**'Closing Price (USD)'**)plt.legend(handles=[predicted, actual])plt.show()
我们能比均值模型做得更好吗?也许我们可以。让我们试着为这个时间序列开发一个竞争性的、无限制的模型。
竞争模型
假设通过一些分析,我们已经推断出 DJIA 收盘价的今天的值可能是明天收盘价的一个很好的预测值。
为了测试这一理论,我们将开发一个由单个回归变量组成的线性回归模型。该变量将是时间序列的时间滞后值。以下 Python 代码说明了回归过程:
导入所需的包:
**import** pandas **as** pd
**import** numpy **as** np
**import** statsmodels.api **as** sm
将数据集读入熊猫数据框:
df = pd.read_csv(**'djia.csv'**, header=0, infer_datetime_format=**True**, parse_dates=[0], index_col=[0])
添加延时栏:
df['CP_LAGGED'] = df['Closing Price'].shift(1)
以下是修改后的数据框的前几行。第一行包含一个 NaN,因为该值后面没有任何东西:
**Closing Price CP_LAGGED
Date** 2019-07-24 27269.97070 NaN
2019-07-25 27140.98047 27269.97070
2019-07-26 27192.44922 27140.98047
2019-07-29 27221.34961 27192.44922
2019-07-30 27198.01953 27221.34961
让我们去掉第一行,去掉 NaN:
df_lagged = df.drop(df.index[0])
接下来,让我们创建我们的训练和测试数据集:
split_index = round(len(df_lagged)*0.8)split_date = df_lagged.index[split_index]df_train = df_lagged.loc[df_lagged.index <= split_date].copy()df_test = df_lagged.loc[df_lagged.index > split_date].copy()X_train = df_train[**'CP_LAGGED'**].values*#Add a placeholder for the constant so that model computes an intercept value. The OLS regression equation will take the form: y = Beta_0 + Beta_1*x* X_train = sm.add_constant(X_train)y_train = df_train[**'Closing Price'**].valuesX_test = df_test[**'CP_LAGGED'**].values*#Add a placeholder for the constant* X_test = sm.add_constant(X_test)y_test = df_test[**'Closing Price'**].values
构建 OLS ( O 副 L 东 S 方)回归模型并将其拟合到时间序列数据集;
ols_model = sm.OLS(y_train,X_train)ols_results = ols_model.fit()
使用拟合的模型对训练和测试数据集进行预测:
y_pred_train = ols_results.predict(X_train)y_pred_test = ols_results.predict(X_test)
对照测试数据集绘制模型的性能:
fig = plt.figure()fig.suptitle('DJIA Closing Price')actual, = plt.plot(df_test.index, y_test, 'go-', label='Actual Closing Price')predicted, = plt.plot(df_test.index, y_pred_test, 'ro-', label='Predicted Closing Price')plt.xlabel('Date')plt.ylabel('Closing Price (USD)')plt.legend(handles=[predicted, actual])plt.show()
结果看起来像这样:
Predicted versus actual Closing Price of DJIA using the OLS regression model on the test data set (Image by Author)
乍一看,这个模型的性能看起来比我们从均值模型中得到的要好得多。但是仔细观察发现,在每一个时间步,模型只是学会了预测实际上是先前观察到的值偏移了一定的量。
但是,这种滞后变量模型可能在解释收盘价的变化量时在统计上比仅截距模型表现得更好。我们将使用 f 检验来确定这是否属实。
测试方法
我们的测试方法如下:
我们从两个假设开始:
- **h0:零假设:**滞后变量模型并不能比单纯截距模型更好地解释 DJIA 收盘价的变化。
- **h1:替代假设:**滞后变量模型比仅截距模型更好地解释了 DJIA 收盘价的变化(以统计显著的方式)。
我们将对两个模型使用 f 检验:仅截距模型和滞后变量模型,以确定是否:
- 在一定的误差范围内,可以拒绝零假设(并接受替代假设),或者
- 应该接受零假设。
使用 f 检验的分步过程
为了实现上述目标,我们将遵循以下步骤:
- 制定 f 检验的检验统计量,即 F 检验统计量。
- 在假设零假设为真的情况下,确定 F 统计量所代表的随机变量的 P 概率 D 密度 F 函数。
- 将这些值代入 F 统计的公式,并使用步骤 2 中找到的 P 概率 D 密度 F 函数计算相应的概率值。这是假设零假设为真时观察到 F 统计值的概率。
- 如果步骤 3 中发现的概率小于误差阈值,例如 0.05,则拒绝零假设,并接受置信水平为(1.0 —误差阈值)的替代假设,例如 1–0.05 = 0.95(即 95%置信水平)。否则,接受误差概率等于阈值误差的零假设,例如 0.05%或 5%。
让我们深入这些步骤。
步骤 1:开发测试统计的直觉
回想一下,f 检验衡量的是一个复杂模型在解释因变量方差的能力上比同一模型的一个简单版本好多少。
考虑两个回归模型 1 和 2:
- 设模型 1 有 k_1 参数。模型 2 有 k_2 参数。
- 让k _ 1<k _ 2
- 因此,模型 1 是模型 2 的简化版本。即模型 1 是受限模型,而模型 2 是非受限模型。模型 1 可以嵌套在模型 2 中。
- 设 RSS_1 和 RSS_2 为模型 1 和模型 2 拟合到同一数据集后的残差平方和。
- 设 n 为数据样本数。
有了上述定义,回归的 f 检验的检验统计量可以表示为如下比率:
Formula for the F-statistic when applied to regression analysis (Image by Author)
F 统计公式允许您计算因变量中有多少方差,简单模型与复杂模型相比不能解释,表示为复杂模型中未解释方差的分数。
在回归分析中,拟合模型的均方误差是无法解释的方差的极好度量。这解释了分子和分母中的 RSS 项。
使用相应的可用自由度来适当地缩放分子和分母。
F 统计量本身就是一个随机变量。
让我们确定 F-统计量服从哪一个 P 概率 D 强度 F 函数。
步骤 2:确定 F 统计的概率密度函数
请注意,测试统计的分子和分母都包含残差平方和。还记得在回归中,残差恰好是具有某种概率密度(或概率质量)函数的随机变量,即 PDF 或 PMF,取决于它是连续的还是离散的。在这种情况下,我们关心的是找到 F 统计的 PDF。
如果我们假设两个模型的残差 1)是独立的,2)是正态分布的,这恰好是二次回归的要求,那么可以看到 F 统计公式的分子和分母包含独立的正态分布随机变量的平方和。
可以证明 k 个独立的标准正态随机变量的平方和遵循卡方(k)分布的 PDF。
PDF of the Chi-Squared distribution (Source: Wikimedia Commons under CC BY 3.0)
因此,F 统计公式的分子和分母可以显示为各自服从两个卡方分布的缩放版本。
利用一点数学知识,还可以证明两个适当缩放的卡方分布随机变量的比率本身是一个随机变量,遵循 F 分布,其 PDF 如下所示。
The F-distribution (Source: Wikimedia Commons under CC BY-SA 4.0)
换句话说:
如果随机变量 X 具有带参数D1和D2的 f 分布的 PDF,即:
(Image by Author)
然后, X 可以表示为两个适当缩放的随机变量 X_1 和 X_2 的比值,每个随机变量都具有卡方分布的 PDF。即:
An F-distributed random variable X, expressed as the ratio of two scaled Chi-squared distributed random variables X_1 and X_2 (Image by Author)
现在回想一下,k1 和 k2 是之前 M1 和 M2 介绍的简单和复杂模型中的变量个数, n 是数据样本的个数。
将 D1 和 D2 替换如下:
d_1 = (k_2 — k_1 ),这是要比较的两个模型 M1 和 M2 的残差的自由度差,以及
D2 =(n—k2)是复模型 M2 残差的自由度,
通过这些替换,我们可以将 F 分布的公式改写如下:
Alternate formula for the F-distribution’s PDF (Image by Author)
让我们将上面的公式与 F 统计量的公式(复制如下)进行比较,其中我们知道分子和分母包含适当缩放的卡方分布的 pdf:
Formula for the F-test’s test statistic (Image by Author)
比较这两个公式,很明显:
- 分子中卡方分布的自由度’ a’ 为(k1 — k2)。
- 分母中卡方分布的自由度’ b’ 为(n — k2)。
- f 检验的检验统计量具有与 f 分布相同的 PDF。
换句话说,F 统计量遵循 F 分布。
步骤 3:计算 F 统计值
如果您使用 statsmodels 的 s OLS 估计器,这一步是一行操作。你需要做的就是打印 OLSResults.summary() 然后你会得到:
- F 统计量的值,
- 对应的“p”值,即在 F 分布的 PDF 中遇到该值的概率。
statsmodels 库将完成这两种计算的繁重工作。
print(ols_results.summary())
这会打印以下内容:
Output of OLSResults.summary() (Image by Author)
步骤 4:确定是否可以接受零假设
因为 OLSResults.summary() 在假设零假设为真的情况下打印出 F 统计的出现概率,所以我们只需要将这个概率与我们的阈值 alpha 值进行比较。在我们的例子中,返回的 p 值。summary() 是 4.84E-16 这是一个极小的数。远小于甚至α= 0.01。因此,在一个有效的零假设的假设下,136.7 的 F-统计量偶然出现的概率远小于 1%。
因此,我们拒绝零假设,接受另一个假设 h1,即复杂模型,即滞后变量模型,尽管有明显的缺陷,但它能够比仅截距模型更好地解释因变量收盘价的方差。
下面是本文中显示的完整 Python 源代码:
包含 DJIA 收盘价的数据文件在这里。
结论
- f 检验可用于回归分析,以确定在解释因变量的方差时,复杂模型是否优于同一模型的简单版本。
- f 检验的检验统计量是一个随机变量,其概率函数是假设零假设为真时的 f 分布。
- 回归的 f 检验的检验程序在结构上与其他重要的参数检验(如 t 检验)相同。
感谢阅读!我撰写关于数据科学的主题,重点是时间序列分析和预测。
如果你喜欢这篇文章,请关注我的Sachin Date获取关于时间序列分析和预测主题的提示、操作方法和编程建议。
从头开始用梯度下降拟合线性回归模型
实施梯度下降以找到简单线性回归的最佳权重。
我们都知道 sklearn 可以为我们试衣模特。但是当我们调用.fit()
时,我们知道它实际上在做什么吗?请继续阅读,寻找答案。
今天我们将编写一组实现梯度下降以拟合线性回归模型的函数。然后,我们将我们的模型的重量与一个合适的 sklearn 模型的重量进行比较。
所需背景
拟合 =找出模型的偏差和系数,使误差最小化。
误差 =均方误差(MSE)。数据集内实际值和预测值之间的平方差的平均值。
简单线性回归 =基于一条线的方程的模型,“y=mx+b”。它将单个特征作为输入,应用偏差和系数,并预测 y。
此外,系数和偏差有时也统称为“权重”。
准备数据集
从 kaggle 下载加州住房数据集,并将其加载到数据框架中。
import pandas as pd
df = pd.read_csv('california-housing-dataset.csv')
df.head()
对于这个数据集,我们通常尝试使用所有其他特征来预测median_house_value
。
但是在我们的例子中,我们关心的是拟合一个简单的线性回归(它只接受一个单一的输入特征),所以我们将选择median_income
作为那个特征,忽略其他的。这不会创建可能的最佳模型,但会使梯度下降的实现更简单。
对数据集中的示例进行计数。
len(df)
#=> 20640
这是大量的数据。让我们把尺寸缩小 75%。
df = df.sample(frac=0.25)
len(df)
#=> 5160
那更容易管理。
收集我们的输入要素和标注。
X = df['median_income'].tolist()
y = df['median_house_value'].tolist()
用梯度下降拟合线性回归
根据维基百科,
梯度下降是一种寻找函数局部极小值的一阶迭代优化算法。为了使用梯度下降找到函数的局部最小值,在当前点采取与函数的梯度(或近似梯度)的负成比例的步骤。
我的翻译:
梯度下降使用误差函数的梯度来预测系数m
和偏差b
应该在哪个方向更新,以减少给定数据集的误差。
单独计算每个权重的梯度m
和b
。梯度是通过对所有例子的重量偏导数取平均值来计算的。
梯度的方向和陡度决定了权重的更新方向和更新量。后者也受一个超参数,即学习率的影响。
该算法反复迭代训练集并更新权重,直到代价函数最小。
履行
你可以在互联网上找到 MSE 函数的偏导数(如下),所以我们在这里不推导它。
我们将用下面的代码实现上面的代码,同时遍历数据集。
m_gradient += -(2/N) * x * (y - y_hat)
b_gradient += -(2/N) * (y - y_hat)
让我们写一个函数,它接受当前的权重、特征、标签和学习率,并输出更新后的权重。
def bias_coef_update(m, b, X, Y, learning_rate):
m_gradient = 0
b_gradient = 0
N = len(Y)
# iterate over examples
for idx in range(len(Y)):
x = X[idx]
y = Y[idx]
# predict y with current bias and coefficient
y_hat = (m * x) + b m_gradient += -(2/N) * x * (y - y_hat)
b_gradient += -(2/N) * (y - y_hat)
# use gradient with learning_rate to nudge bias and coefficient
new_coef = m - (m_gradient * learning_rate)
new_bias = b - (b_gradient * learning_rate)
return new_coef, new_bias
该函数的后半部分将梯度乘以学习率,并使用结果来更新当前权重。学习率越高,模型拟合得越快,代价是找到精确的局部最小值(注意:它实际上永远不会达到真正的最小值)。
编写另一个函数,迭代应用上述函数一个设定的历元数。这是一种不太复杂的方法(为了简单起见),比在某个预定的梯度陡度返回拟合的权重要简单。
def run(epoch_count=1000):
# store output to plot later
epochs = []
costs = []
m = 0
b = 0
learning_rate = 0.01 for i in range(epoch_count):
m, b = bias_coef_update(m, b, X, y, learning_rate)
print(m,b)
C = cost(b, m, x_y_pairs)
epochs.append(i)
costs.append(C)
return epochs, costs, m, bepochs, costs, m, b = run()
让我们输出拟合模型的最终成本和权重。
print(m)
print(b)
print(costs[-1])# I've rounded these myself so they're nicer to look at
#=> 46,804
#=> 19,963
#=> 7,261,908,362
并绘制出它是如何随着时代而改进的。
import matplotlib.pyplot as pltplt.xlabel('Epoch')
plt.ylabel('Error')
plt.suptitle('Cost by epoch')plt.plot(epochs,costs, linewidth=1)
酷毙了。我们可以看到它的大部分进步都是在前 100 个纪元内取得的。
用 Sklearn 拟合线性回归
现在,我们将在装有 sklearn 的模型中检查相同的值。
重塑要素。
import numpy as np
X_array = np.array(X).reshape(5160,1)
符合模型。
from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.fit(X_array,y)
检查重量和误差。
from sklearn.metrics import mean_squared_errorm = model.coef_[0]
b = model.intercept_mse = mean_squared_error(y_test, y_pred, sample_weight=None, multioutput='uniform_average')print(m)
print(b)
print(mse)# rounded
#=> 42,324
#=> 41,356
#=> 7,134,555,443
我们表现如何?
Sklearn 的调音以微弱优势超过我们,7,134,555,443
对7,261,908,362
,但我们非常接近。
我们的偏见也与 sklearn 发现的偏见大相径庭,41,356
VS 19,963
。
不用深入研究每个时期后值是如何变化的(这很容易做到),我想我们可以通过降低学习率和增加时期的数量来改进我们的模型。
用于机器学习的 SciKit 库中的 Fit 与 Transform
我们已经在很多 SciKit 的库中看到了 fit()、transform()和 fit_transform()这样的方法。而且几乎所有的教程,包括我写过的,都只告诉你只用其中一种方法。这里出现的一个明显的问题是,这些方法是什么意思?你说的适合某样东西,改造某样东西是什么意思?transform()方法有一定的意义,它只是转换数据,但是 fit()呢?在这篇文章中,我们将试着理解两者之间的区别。
为了更好地理解这些方法的含义,我们将以 import 类为例,因为 import 类有这些方法。但是在我们开始之前,请记住,拟合像估算器这样的东西不同于拟合整个模型。
您使用一个估算器来处理数据集中的缺失数据。Imputer 为您提供了用列的平均值或甚至中值替换 NaNs 和空格的简单方法。但是在替换这些值之前,它必须计算将用于替换空白的值。如果您告诉估算者,您希望用该列中所有值的平均值替换该列中的所有变量,估算者必须首先计算平均值。计算该值的这一步称为 fit()方法。
接下来,transform()方法将使用新计算的值替换列中的 nan,并返回新的数据集。这很简单。fit_transform()方法将在内部完成这两项工作,并且通过只公开一个方法来简化我们的工作。但是有些情况下,您只想调用 fit()方法和 transform()方法。
在训练模型时,您将使用训练数据集。在该数据集上,您将使用估算器,计算值,并替换空白。但是,当您在测试数据集上拟合这个训练好的模型时,您不需要再次计算平均值或中值。您将使用与训练数据集相同的值。为此,您将对训练数据集使用 fit()方法,仅计算该值并将其保存在 input 中。然后,您将使用相同的 Inputer 对象对测试数据集调用 transform()方法。这样,为训练集计算的值(保存在对象内部)也将用于测试数据集。
简单地说,您可以对训练集使用 fit_transform()方法,因为您需要拟合和转换数据,并且您可以对训练数据集使用 fit()方法来获取值,然后用它来转换()测试数据。如果你有任何意见或不能理解,请告诉我。
Fitbit + Google AI + 5G =?
Brussels marathon runners — Photo by @mzemlickis
谷歌以 21 亿美元收购 Fitbit
the Verge 发表的一篇文章 2019 年 11 月 1 日宣布谷歌收购 FitBit:
谷歌刚刚宣布以 21 亿美元收购可穿戴公司 Fitbit 。在宣布这一消息的博客文章中,谷歌设备和服务 SVP 公司的里克·奥斯特洛表示,收购 Fitbit 是“一个在 Wear OS 上进行更多投资以及将谷歌可穿戴设备引入市场的机会。”
这可能是一项复杂的投资,但我看到了一些关于为何进行此次收购的不同观点:
- 谷歌希望投资可穿戴设备,但未能独自开发出足够可行的解决方案。因此,它收购 FitBit 是为了提供这种服务。
- 谷歌收购 FitBit 是为了专有技术。
- 谷歌收购 FitBit 是为了它的数据——不是为了增加广告,而是为了协助其在健康技术方面的投资(这构成了 Alphabet 投资组合的很大一部分)。
可能有更多的原因,然而,在保护消费者健康数据方面,消费者似乎有很强的意识。11 月 1 日直接来自 FitBit 的声明如下:
“消费者信任对 Fitbit 至关重要。强有力的隐私和安全指导方针从第一天起就是 Fitbit DNA 的一部分,这一点不会改变。Fitbit 将继续让用户控制他们的数据,并将对其收集的数据及其原因保持透明。该公司从不出售个人信息,Fitbit health and wellness 数据也不会用于谷歌广告。”
Rick Osterloh,谷歌设备与服务高级副总裁。表示他们将把 FitBit 在硬件方面的人才与软件和人工智能结合起来,打造更好的可穿戴设备。
与此同时,拥有谷歌的 Alphabet 正在扩大对 Verily 和 Calico 的投资。这是 Alphabet Inc .的季度报表中反复提到的两家公司。健康数据是一个热门话题。
尽管谷歌可能不会将 FitBit 数据用于广告,但它很可能会将这些聚合数据用于 Verily 和 Calico 的药物开发或健康洞察。是什么阻止了 Google/Alphabet 这样做?
我从 Alphabet 的投资者关系页面的 2019 年第三季度(Q3)页面中获取了一份描述。以下两节摘自 Q3。
印花布
Calico 是一家生命科学公司,其使命是利用先进技术来增加我们对控制寿命的生物学的了解。
【2014 年 9 月,艾伯维公司(AbbVie)和 Calico 签署了一项研发合作协议,旨在帮助两家公司发现、开发和向市场推出针对年龄相关疾病患者的新疗法,包括神经退行性疾病和癌症。在 2018 年第二季度,艾伯维和 Calico 修订了合作协议,导致总承诺量增加。截至 2019 年 9 月 30 日,艾伯维已根据协议出资 7.5 亿美元资助合作,并承诺额外出资 5 亿美元,将于 2019 年第四季度支付。截至 2019 年 9 月 30 日,Calico 已出资 5 亿美元,并承诺追加 7.5 亿美元。
Calico 利用其科学专业知识建立了世界级的研发机构,专注于药物发现和早期药物开发;艾伯维提供科学和临床开发支持及其商业专业知识,将新发现推向市场。两家公司平等分享本协议项下项目的成本和利润。艾伯维的出资在 Calico 的财务报表中被记录为负债,由于 Calico 产生了符合条件的研发费用,因此该负债被减少并反映为研发费用的减少。
截至 2019 年 9 月 30 日,我们已向 Calico 出资 4.8 亿美元,以换取 Calico 可兑换优先股单位,并承诺根据需要和特定条件额外出资 7.5 亿美元。
的确
Verily 是一家生命科学公司,其使命是利用世界健康数据,让人们享受更健康的生活。2018 年 12 月,Verily 获得了 10 亿美元投资轮的 9 亿美元现金。剩余的 1 亿美元于 2019 年第一季度收到。截至 2019 年 9 月 30 日,Verily 已从向外部投资者出售股权证券中获得总计 18 亿美元的收入。这些交易作为权益交易入账,没有确认任何收益或损失。
你对 21 亿美元有什么期待?
当你以难以想象的金额(对大多数人来说)收购一家公司时,预期投资回报并非不可思议。
另据Quartz:Alphabet报道称,来自谷歌广告业务的收入为 326 亿美元,比去年同期增长了约 16%
尽管 Alphabet 收益丰厚,但这是一个相当大的赌注。自 2015 年首次公开募股以来,Fitbit 的股票下跌了~ 80。
在收购之前的几年里,FitBit 的销售额和收入似乎一直在下降。
谷歌正在购买进入可穿戴设备市场的方式,并可能大幅增加 FitBit 的扩张以及该平台的可能性。
Retrieved from IDC on the 2nd of November
FitBit + 5G
这个赌注会有回报吗?有关系吗?这为理解人类提供了更多的力量,这无疑是谷歌成功的一部分。
亚马逊 Alexa 可能会和你说话,但随着 5G 的发展,在你身上安装一个可以做到这一点的设备,同时持续传输结果可能会达到更高的程度。
今年早些时候,有人预测 5G 将提振 FitBit 的股价:
“通过让可穿戴设备做更多的事情,让它们变得更加不可或缺,5G 将让可穿戴设备变得更加流行和有价值,提振这些公司的财务状况。"
5G 的到来还将使可穿戴设备能够更精确地监测个人的身体、情感和精神健康。
换句话说,谷歌的这项投资有望获得回报。
这里是#500daysofAI,您正在阅读的是第 152 条。500 天来,我每天都写一篇关于人工智能或与之相关的新文章。
使用 Python 中的随机优化来拟合神经网络
如何使用随机化优化来为机器学习模型(如神经网络和回归模型)找到最佳权重
Python 的 mlrose 包提供了实现一些最流行的随机化和搜索算法的功能,并将它们应用于一系列不同的优化问题领域。
在本教程中,我们将讨论如何使用 mlrose 来寻找机器学习模型的最佳权重,如神经网络和回归模型。即解决机器学习权重优化问题。
这是关于使用 mlrose 解决随机优化问题的三个系列教程中的第三个。第 1 部分可以在这里找到,第 2 部分可以在这里找到**。******
什么是机器学习权重优化问题?
对于许多不同的机器学习模型,拟合模型参数的过程包括找到最小化给定训练集的预先指定的损失函数的参数值。
这种模型的例子包括神经网络、线性回归模型和逻辑回归模型,并且这种模型的最佳模型权重通常使用诸如梯度下降的方法来找到。
然而,拟合机器学习模型的参数(或权重)的问题也可以被视为连续状态优化问题,其中损失函数充当适应度函数的角色,并且目标是最小化该函数。
通过以这种方式构建问题,我们可以使用任何适用于连续状态优化问题的随机优化算法来拟合模型参数。
用 mlrose 解决机器学习权重优化问题
mlrose 包含内置功能,用于解决三种机器学习模型的权重优化问题:(标准)神经网络、线性回归模型和逻辑回归模型。这是分别使用NeuralNetwork()
、LinearRegression()
和LogisticRegression()
类完成的。
这些类中的每一个都包括一个fit
方法,该方法实现了在前面的教程中为给定的训练集定义的解决优化问题的三个步骤。也就是说,
- 定义一个适应度函数对象。
- 定义一个优化问题对象。
- 选择并运行随机优化算法。
然而,在拟合机器学习模型时,找到最佳模型权重仅仅是达到目的的一种手段。
我们希望找到最佳的模型权重,以便我们可以使用拟合的模型尽可能准确地预测未来观测值的标签,而不是因为我们实际上对知道最佳权重值感兴趣。
因此,上面提到的类还包括一个predict
方法,如果在fit
方法之后调用,它将使用拟合的模型预测给定测试集的标签。
使用 mlrose 解决机器学习权重优化问题所涉及的步骤通常是:
- 初始化机器学习权重优化问题对象。
- 通过调用在步骤 1 中初始化的对象的
fit
方法,找到给定训练集的最佳模型权重。 - 通过调用在步骤 1 中初始化的对象的
predict
方法来预测测试集的标签。
为了拟合模型权重,用户可以选择使用随机爬山、模拟退火、遗传算法或梯度下降。
【在 mlrose 中,梯度下降算法仅可用于解决机器学习权重优化问题,主要用于基准测试,因为这是拟合神经网络和回归模型时最常用的算法之一。]
我们现在将通过一个示例来说明如何使用 mlrose 来将神经网络和回归模型拟合到给定的数据集。
在开始这个例子之前,您需要导入 mlrose 和 Numpy Python 包。
**import mlrose
import numpy as np**
示例:虹膜数据集
Iris 数据集是一个著名的多元分类数据集,由统计学家和生物学家罗纳德·费雪在 1936 年的一篇研究论文中首次提出。
Irises (1889) by Vincent Van Gogh
它包含鸢尾花的三个类(种)的 150 个观察值(每个类 50 个观察值),每个观察值提供所考虑的每个花的萼片长度、萼片宽度、花瓣长度和花瓣宽度(即特征值),以及类标签(即目标值)。
虹膜数据集包含在 Python 的 sklearn 包中。
数据集中第一个观测值的特征值和标注以及每个要素的最大值和最小值和唯一标注值如下所示:
**The feature values for Obs 0 are: [5.1 3.5 1.4 0.2]The feature names are: ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']The target value for Obs 0 is: 0The target name for Obs 0 is: setosaThe minimum values of the four features are: [4.3 2\. 1\. 0.1]The maximum values of the four features are: [7.9 4.4 6.9 2.5]The unique target values are: [0 1 2]**
由此我们可以看出,虹膜数据集中的所有特征都是数字的,尽管范围不同,并且类别标签已经由整数表示。
在接下来的几节中,我们将展示如何使用 mlrose 将神经网络和逻辑回归模型拟合到该数据集,从而根据其特征值预测鸢尾花的种类。
数据预处理
在我们可以将任何类型的机器学习模型拟合到数据集之前,有必要将我们的数据处理成 mlrose 所期望的形式。
由 mlrose 支持的三个机器学习模型中的每一个都期望以 Numpy 数组的形式接收特征数据,每个观察值一行,并且只有数字特征(任何分类特征在传递到机器学习模型之前必须被一键编码)。
模型还期望接收以下目标值:数值列表(用于回归数据);0-1 指标值的列表(针对二元分类数据);或者作为独热编码标签的 Numpy 数组,每个观察值一行(用于多类分类数据)。
在虹膜数据集的例子中,我们所有的特征都是数字的,所以不需要一次性编码。然而,有必要对类别标签进行一次性编码。
为了与标准的机器学习实践保持一致,还需要将数据分成训练和测试子集,并且由于虹膜数据的范围从特征到特征变化很大,因此需要标准化我们的特征变量的值。
这些预处理步骤实现如下:
神经网络
一旦数据经过预处理,在 mlrose 中拟合神经网络只需遵循上面列出的步骤。
假设我们希望将神经网络分类器适配到具有一个包含 2 个节点的隐藏层和一个 ReLU 激活函数的 Iris 数据集( mlrose 支持 ReLU、identity、sigmoid 和 tanh 激活函数)。
对于此示例,我们将使用随机爬山算法来查找最佳权重,该算法最多迭代 1000 次,并且在每一步尝试 100 次来查找更好的权重集。
我们还将包括一个偏差项;使用步长(学习率)0.0001(查找当前权重集的邻居);并将我们的权重限制在-5 到 5 的范围内(以减少算法为了找到最佳权重而必须搜索的范围)。
该模型已初始化,并符合我们的预处理数据,如下所示:
模型拟合后,我们可以使用它来预测我们的训练集和测试集的标签,并使用这些预测来评估模型的训练和测试准确性。
**Training accuracy: 0.45Test accuracy: 0.533333333333**
在这种情况下,我们的模型实现了 45%的训练精度和 53.3%的测试精度。这些精度水平比随机选择标签要好,但仍有改进的空间。
我们可以通过调整初始化神经网络对象时设置的参数来提高模型的准确性。假设我们决定将优化算法改为梯度下降,但保持所有其他模型参数不变。
**Training accuracy: 0.625Test accuracy: 0.566666666667**
这导致训练准确率提高了 39%,达到 62.5%,但测试准确率的提高要小得多,达到 56.7%。
线性和逻辑回归模型
线性和逻辑回归模型是神经网络的特例。线性回归是没有隐藏层和身份激活函数的回归神经网络,而逻辑回归是没有隐藏层和 sigmoid 激活函数的分类神经网络。
因此,我们可以使用NeuralNetwork()
类,通过适当地设置参数,将这些模型中的任何一个与我们的数据相匹配。
例如,假设我们希望使用随机爬山算法和上一节示例中设置的所有其他参数对虹膜数据进行逻辑回归拟合。我们可以这样初始化一个NeuralNetwork()
对象:
然而,为了方便起见, mlrose 提供了LinearRegression()
和LogisticRegression()
包装类,它们简化了模型初始化。
因此,在 Iris 数据集示例中,我们可以如下初始化和拟合我们的逻辑回归模型:
**Training accuracy: 0.191666666667Test accuracy: 0.0666666666667**
该模型实现了 19.2%的训练精度和 6.7%的测试精度,这比我们通过随机选择值来预测标签的情况更差。
尽管如此,如前一节所述,我们可以通过调整初始化时设置的参数来提高模型的准确性。
假设我们把学习率提高到 0.01。
**Training accuracy: 0.683333333333Test accuracy: 0.7**
这极大地提高了训练和测试的准确性,现在训练的准确性达到了 68.3%,测试的准确性达到了 70%。
摘要
在本教程中,我们讨论了如何使用 mlrose 来寻找三种机器学习模型的最佳权重:神经网络、线性回归模型和逻辑回归模型。
将随机优化算法应用于机器学习权重优化问题肯定不是解决该问题的最常见方法。然而,它用来展示 mlrose 软件包和一般随机优化算法的多功能性。
要了解更多关于 mlrose 的信息,请访问这个包的 GitHub 资源库,这里有。********
Genevieve Hayes 博士是数据科学家、教育家和人工智能及分析专家,拥有Genevieve Hayes Consulting。你可以在LinkedIn或者Twitter上关注她。她还是 价值驱动数据科学 的主持人,这是一个每月两次的播客,面向希望最大化其数据和数据团队价值的企业。**
想要发掘企业数据的价值,但不知道从哪里开始?下载免费的数据科学项目发现指南。**
基于计数的数据拟合线性回归模型
Python 中的实践者指南和分步教程
本文的重点
我们将讨论三个主题:
- 拟合一个线性回归模型,特别是一个基于计数的数据的线性回归模型,是明智的吗?
- 如何在基于计数的真实数据集上配置和拟合 OLS 模型。
- 与主流回归模型相比,OLS 的表现如何,比如泊松和负二项分布?
什么是基于计数的数据?
基于计数的数据集包含一些事件的发生,如在英仙座流星雨事件中你发现流星的所有时间,或更实际的事情,如汽车在加油站停下的时间。
基于计数的数据集出现在各种领域,例如:
- **人类行为和心理:**例如,一个时间序列的数据点(每小时捕获一次),包含我每小时查看电子邮件的次数。
- **制造和零售:**每小时的时间序列,包含该小时制造或销售的小部件数量。
- **餐饮服务:**一个日期的时间序列,其中每个数据点包含木瓜大王当天提供的热狗数量。
- **云基础设施:**你的电子商务网站宕机的所有时间。
- 科学:自 1988 年以来发现系外行星的所有日期。
关于 counts 数据集,我们马上就能看到三件事:
- 数据是整数,即没有负数。
- 它经常是偏斜的,因此不是正态分布的,而且
- 它可以非常稀少。
这种数据集通常需要特殊的处理和专门的回归技术。
The Perseids radiating from the constellation Perseus (US National Park Service)
关于 OLS 的快速复习
OdL东 S 方( OLS )线性回归模型的工作原理是将一个 n 维线性函数拟合到 n 维数据上,使拟合值与实际值之间的平方和最小化。
由于数据的偏斜度和稀疏度,以及回归误差的异方差性,即误差的方差不是常数,而是相关计数变量的函数,基于 OLS 的线性回归模型在基于计数的数据上可能会失败。
此外,OLS 生成负预测和分数预测的倾向会导致数据计数的预测看起来很尴尬。
那么,为什么要为这些数据费心摆弄线性回归模型呢?我们很快就会看到,这样做有一些强有力的理由。
为计数数据建立使用 OLS 回归的案例
在之前的一组文章中,我展示了如何为基于计数的数据集训练以下两个常用的回归模型:
在这些文章中,我们根据布鲁克林大桥上骑自行车的人的真实数据来训练和测试这些模型:
Source: Bicycle Counts for East River Bridges (NYC OpenData) (Image by Author)
尽管泊松和 NB 模型表现得“如广告所说”:
Negative Binomial regression model’s predictions (Image by Author)
…我们还想知道以下内容:
- 是否有可能使用OrL东 S 方回归技术成功地对基于计数的数据进行建模?
- 如何判断对给定的基于计数的数据集使用 OLS 回归的适当性?如何在这样的数据集上测量 OLS 回归的性能?
- 在拟合优度和预测能力方面,不起眼的 OLS 模型如何与更复杂的模型相媲美,如 泊松 和 NB ?
我们将在本文中回答这些问题。
总的来说,我们会看到两件事:
- OLS 模型可以作为一个好的快速基线模型,同时为计数数据集建立更复杂的回归模型。
- 我们还将看到,对于此类数据集,OLS 模型中最具统计意义的回归参数也是泊松和 NB 模型中最具统计意义的回归参数。卡梅伦和特里维迪在他们被大量引用的著作《计数数据回归分析》中对这一发现背后的数学原理做了精彩的解释。
在整篇文章中,我们将使用纽约自行车数据集,以便我们可以对 OLS 与泊松和 NB 车型进行比较。
文章的布局
- 我们将对自行车统计数据集进行 E 探索 D ata A 分析( EDA ),以判断 OLS 的适用性,并查看是否需要进行任何数据转换。
- 使用 Python 、 Pandas 和 statsmodels ,我们将在这个数据集上构建、训练和测试一个 OLS 模型。
- 我们将比较 OLS 回归模型与泊松和 NB 模型的性能。
建议(但非必需)阅读
骑自行车者计数数据集的探索性数据分析
下表包含了骑自行车的人在纽约市各种桥梁上行驶的次数。从 2017 年 4 月 1 日到 2017 年 10 月 31 日每天测量计数。我们会集中在布鲁克林大桥上。
Source: Bicycle Counts for East River Bridges (NYC OpenData) (Image by Author)
I have cut out the Brooklyn Bridge counts into a separate data set. This data set is available for download [**over here**](https://gist.github.com/sachinsdate/c17931a3f000492c1c42cf78bf4ce9fe).
以下是该数据集的前几行:
(Image by Author)
让我们将数据加载到一个 pandas 数据框中,并绘制 BB_COUNT 变量:
import pandas as pdfrom matplotlib import pyplot as pltdf = pd.read_csv('nyc_bb_bicyclist_counts.csv', header=0, infer_datetime_format=True, parse_dates=[0], index_col=[0])fig = plt.figure()fig.suptitle('Bicyclist counts on the Brooklyn bridge')plt.xlabel('Date')plt.ylabel('Count')actual, = plt.plot(df.index, df['BB_COUNT'], 'go-', label='Count of bicyclists')plt.legend(handles=[actual])plt.show()
时间序列图如下所示:
Time series plot of the number of bicyclists on the Brooklyn bridge (Image by Author)
让我们也创建一个直方图,看看这个数据集是如何正态分布的:
plt.hist(df['BB_COUNT'], bins=20)plt.show()
Histogram of counts (Image by Author)
不出所料,骑自行车的人的统计数据是有偏差的。让我们打印出一些描述性的统计数据:平均值、中位数、偏斜度和峰度。
对于偏度和峰度,我们将对 BB_COUNT 变量运行 Jarque-Bera 正态性测试 。
相关帖子: 使用偏度和峰度测试正态性
JB 检验不仅会给出偏度和峰度,还会检验偏离正态性是否具有统计显著性。
**from** statsmodels.stats.stattools **import** jarque_bera **as** jb**from** statsmodels.stats.stattools **import** omni_normtest **as** omb**from** statsmodels.compat **import** lzipprint('**Mean**='+str(round(df['BB_COUNT'].**mean**(), 2)))print('**Median**='+str(round(df['BB_COUNT'].**median**(), 2)))name = ['Jarque-Bera', 'Chi^2 two-tail probability', 'Skewness', 'Kurtosis']test_results = jb(df['**BB_COUNT**'])lzip(name, test_results)
这会产生以下输出:
Mean=2680.04Median=2857.0[('**Jarque-Bera**', 30.572383357990116), ('**Chi^2 two-tail probability**', 2.2976893142533207e-07), ('**Skewness**', -0.8746427375174667), ('**Kurtosis**', 3.6071892903122973)]
平均值和中间值没有很大的不同,这表明分布不是很不平衡。
正如所料,测试报告的偏斜度是负的,而且很小。相比之下,正态分布的偏斜度为零。测试报告的过度峰度(=峰度-3.0)也非常小。相比之下,正态分布的峰度为 3.0,而过度峰度为零。
另一方面,Jarque-Bera 测试的 t 统计值 30.57 将其置于卡方(2)的 PDF 的正态性拒绝区(见下图)。
Acceptance and rejection zones for the Null hypothesis in the Chi-squared(2) PDF for two-tailed α=0.05 (Image by Author)
因此我们拒绝数据正态分布的零假设 h0,而接受数据不正态分布**。**
在这一点上,我们可以接受少量的偏斜,并在其上拟合一个 OLS 模型,或者我们可以尝试修复偏斜。后者可以通过对因变量 BB_COUNT 进行对数变换或平方根变换来尝试。
我们将尝试这两种转换方法,看看是否会产生预期的结果。
我们将向数据框添加两个新列:一个 LOG(BB_COUNT)列和一个 SQRT(BB_COUNT):
import numpy as np#Add a column to the Data Frame that contains log(BB_COUNT):
df['LOG_BB_COUNT'] = np.log(df['BB_COUNT'])#All another column containing sqrt(BB_COUNT)
df['SQRT_BB_COUNT'] = np.sqrt(df['BB_COUNT'])
让我们对 LOG 和 SQRT 列再次运行 Jarque-Bera:
name = ['**Jarque-Bera**', '**Chi^2 two-tail probability**', '**Skewness**', '**Kurtosis**']test_results = omb(df['LOG_BB_COUNT'])lzip(name, test_results)test_results = omb(df['SQRT_BB_COUNT'])lzip(name, test_results)
这会打印出以下内容:
[('**Jarque-Bera**', 888.0352308852536), ('**Chi^2 two-tail probability**', 1.4641977846577634e-193), ('**Skewness**', -2.5832340081063463), ('**Kurtosis**', 11.538169851408346)][('**Jarque-Bera**', 135.86010800784334), ('**Chi^2 two-tail probability**', 3.15030346376236e-30), ('**Skewness**', -1.5270456576564704), ('**Kurtosis**', 5.430879236979477)]
让我们将这些发现与未转换的 BB_COUNT 的正态性度量进行比较:
[('**Jarque-Bera**', 30.572383357990116), ('**Chi^2 two-tail probability**', 2.2976893142533207e-07), ('**Skewness**', -0.8746427375174667), ('**Kurtosis**', 3.6071892903122973)]
(Image by Author)
似乎不太顺利,是吧?!转换 BB_COUNT 不仅没有修复偏斜,实际上使数据更加偏斜!从这次转型事故中可以学到一些东西:
人们应该抵制诱惑,不仔细检查数据转换对数据的影响,就盲目接受任何数据转换的结果。
我们又回到起点了吗?
事实上,恰恰相反。我们从对数据进行 ed a 中获益良多。我们最大的收获是认识到我们不应该再花更多的时间去尝试修复数据集中存在的少量偏度和峰度。
此外,因变量的正态性不是进行 OLS 回归的先决条件。过度偏离因变量的正态性只会使 OLS 估计量有可能(但不一定)产生有偏拟合。
因此,让我们承担接受偏态的计算风险,并在原始的、未转换的骑自行车者计数数据上拟合 OLS 回归模型。
我们的回归目标和回归策略
我们的回归目标是预测任何一天有多少骑自行车的人穿过布鲁克林大桥。
我们的回归策略将是建立和训练一个 OLS 回归模型,其中:
- ****回归变量将是 X 矩阵中的变量(见下图),加上一些额外的派生变量,我们将把它们添加到 X (我们将在几秒钟后看到如何做)。
- 回归的因变量 y 将是骑自行车的人数(我们数据集中的 BB_COUNT 列)。
The slice of the bicyclist counts data set showing the regression variables matrix X and the vector of counts y (Image by Author)
一旦模型经过训练,我们将在维持测试数据集上测试其性能,该数据集是模型在训练期间未显示的数据。
使用 Python、Pandas 和 Statsmodels 将 OLS 回归模型拟合到 counts 数据集的分步指南
我们将从导入所有需要的包开始。
**import** pandas as pd**from** patsy **import** dmatrices**import** numpy **as** np**import** statsmodels.api **as** sm**import** statsmodels.formula.api **as** smf**import** matplotlib.pyplot **as** plt
让我们将数据集读入熊猫数据帧:
df = pd.read_csv('nyc_bb_bicyclist_counts.csv', header=0, infer_datetime_format=True, parse_dates=[0], index_col=[0])
我们将向 X 矩阵添加一些派生的回归变量。
ds = df.index.to_series()df['MONTH'] = ds.dt.monthdf['DAY_OF_WEEK'] = ds.dt.dayofweekdf['DAY'] = ds.dt.day
以下是熊猫数据框的前几行,左侧显示了回归变量和 BB_COUNT 因变量:
Pandas Data Frame (Image by Author)
让我们创建训练和测试数据集。
mask = np.random.rand(len(df)) < 0.8df_train = df[mask]df_test = df[~mask]print('Training data set length='+str(len(df_train)))print('Testing data set length='+str(len(df_test)))
在 patsy 符号中设置回归表达式。我们告诉 patsy,BB_COUNT 是我们的因变量,它取决于回归变量:DAY、DAY_OF_WEEK、MONTH、HIGH_T、LOW_T 和 PRECIP:
expr = 'BB_COUNT ~ DAY + DAY_OF_WEEK + MONTH + HIGH_T + LOW_T + PRECIP'
为训练和测试数据集设置 X 和 y 矩阵。patsy 让这变得非常简单:
y_train, X_train = dmatrices(expr, df_train, return_type='dataframe')y_test, X_test = dmatrices(expr, df_test, return_type='dataframe')
配置并适应 OLSR 模型。在 statsmodels 中,这是一行代码:
olsr_results = smf.ols(expr, df_train).fit()
打印回归输出:
print(olsr_results.summary())
它打印出以下内容:
Summary of the fitted OLSR model (Image by Author)
我们稍后将检查回归输出的单个元素。同时,让我们根据测试数据生成模型的预测:
olsr_predictions = olsr_results.get_prediction(X_test)
让我们把它们打印出来:
predictions_summary_frame = olsr_predictions.summary_frame()print(predictions_summary_frame)
以下是最初的几个预测计数:
Predicted values (Image by Author)
注意预测计数不是整数**,这是将线性回归模型应用于基于计数的数据的典型缺点。在这种情况下,我们可以通过向上舍入或向下舍入预测来解决这个缺点。**
让我们也画出预测值和实际值。
predicted_counts=predictions_summary_frame['mean']actual_counts = y_test['BB_COUNT']fig = plt.figure()fig.suptitle('Predicted versus actual bicyclist counts on the Brooklyn bridge')predicted, = plt.plot(X_test.index, predicted_counts, 'go-', label='Predicted counts')actual, = plt.plot(X_test.index, actual_counts, 'ro-', label='Actual counts')plt.legend(handles=[predicted, actual])plt.show()
The plot of actual versus predicted counts (Image by Author)
注意一个预测的骑自行车的人数是负的**。当应用于基于计数的数据时,这是线性回归模型的另一个经典缺点。在某些情况下,我们可以通过简单地将负值四舍五入为零来解决这个缺点。**
解读 OLSR 模型的结果
抛开产生分数计数和负数计数的倾向,让我们客观地评估一下我们的 OLS 回归模型在自行车计数数据集上的表现。
检验回归参数的显著性:
Parameter significance using the two-tailed t-test (Image by Author)
t 检验显示所有回归参数分别和统计显著。在双尾 t 检验中,每个参数的 t 统计的绝对值在 95%显著性水平上大于指定的阈值 t 值。**
接下来,让我们检查 F 统计量:
The F-test for regression analysis (Image by Author)
F-stat 的 p 值 3.26E-26 远小于具有 6 个自由度的卡方分布的 0.025 误差阈值,表明所有回归参数都共同显著**。**
相关帖子: 回归分析的 f 检验
最重要的 R 平方值:
R-squared (Image by Author)
Adjusted-R 是对 R 的一个小修正,以说明在进行估算时损失了 7 个自由度,即 6 个回归变量+截距)。
0.530 的调整后 R 告诉我们,OLSR 模型能够解释骑自行车者数量因变量中超过 50%的方差。
顺便说一句,如果我们对模型本身的选择是错误的,那么 R 的值就没有意义了!但到目前为止,我们还没有看到 OLS 出现这种情况的任何迹象。
让我们再检查一下 OLS 回归模型的两件事:
- ****残差的正态性:如果我们发现模型的残差不是正态分布的,我们就不能相信模型预测的 F 统计量或置信区间。
- ****残差间的自相关:时间序列中的自相关是指时间序列中的值与同一时间序列中的先前值相关。如果我们在模型的残差中发现显著的自相关,这表明我们遗漏了重要的回归变量,导致相关计数变量中的一些“信号”泄漏到残差中。这是一个严重指定的 OLSR 模型的迹象。
为了检查回归的残差是否是正态分布的,并且它们不是自相关的,我们需要查看 OLS 模型摘要的页脚部分。页脚部分显示了回归残差的正态性检验和自相关性检验的结果。
(Image by Author)
残差的正态性:
Jarque-Bera 的残差正态性检验统计量为 11.917,将其置于卡方(2) PDF 的正态性拒绝区域**。综合 K 平方检验的统计值 7.347 刚好跨越了正态性拒绝区的边界。见下图:**
Acceptance and rejection zones for the Null hypothesis in the Chi-squared(2) PDF for two-tailed α=0.05 (Image by Author)
JB 和正态性综合检验告诉我们的是 OLSR 残差不是正态分布的。同时,残差的极低偏斜度(0.147)以及综合统计量处于卡方(2) PDF 的正态/非正态边界意味着误差接近正态分布。残余误差的直方图直观地证实了这一判断:
plt.hist(olsr_results.resid, bins=20)plt.show()
Histogram of residual errors (Image by Author)
请注意误差在零均值附近或多或少呈正态分布。
这是残差的 Q-Q 图,在很大程度上看起来也是线性的:
fig = sm.qqplot(olsr_results.resid)plt.show()
Q-Q plot of the residual errors of OLSR (Image by Author)
总之,我们的结论是,OLS 回归模型的残差大体上正态分布在一个零均值附近。
残差的自相关:
Durbin-Watson 检验让我们了解了残差是否是自相关的。显著小于 2 的 DW 测试值表示显著的自相关。在这种情况下,DW 检验的值是 1.772,这意味着在回归的残差中没有强自相关的证据。
(Image by Author)
我们还可以通过绘制残差的 ACF 图来验证自相关的缺失:
**from** statsmodels.graphics.tsaplots **import** plot_acfplot_acf(olsr_results.resid, title='ACF of residual errors')plt.show()
Auto-correlation plot of residual errors of the OLSR model (Image by Author)
正如所料,ACF 图显示残差之间没有显著的自相关
总而言之,OLS 模型似乎已经最佳地拟合了数据,没有系统性的信息泄漏到模型的误差中。
最后,让我们比较一下 OLSR 模型与泊松和 NB 回归模型的性能,这两个模型在我之前的两篇关于基于计数的数据的回归模型的文章中都有涉及。
OLSR 与泊松和负二项模型的比较
如果我们对所有三个模型的回归参数——OLS、泊松、负二项式——在相同的自行车计数数据集上进行并排比较,我们会看到OLSR 发现的最重要的参数(从参数的 t 统计的绝对值来看)也是其他两个模型确定的最重要的参数。
见下图。我根据 T 值注释了前三个重要参数:PRECIP、HIGH_T 和 LOW_T。它们在所有三个模型中都是相同的:
A comparison of parameter significance among OLS, Poisson and NB models (Image by Author)
OLSR、泊松和 NB 模型的拟合优度比较:
让我们来看看 OLSR 模型与泊松和 NB 模型相比,对骑自行车者计数数据的拟合程度如何。
让我们再一次将 OLS 结果与泊松和 NB 回归结果放在一起。(你可能想参考我关于泊松和 NB 回归模型的文章,了解如何使用 statsmodels 得到泊松和 NB 回归模型的结果)。
(Image by Author)
使用最大对数似然作为拟合优度的卷尺,我们看到:
- ****NB 车型排名第一最高最大 LL-1309.6,
- OLSR 车型以-1339.4 的最高 LL 值意外获得第二名。
- 泊松回归模型以-12616.0 的成绩远远排在第三位。
Goodness-of-fit rankings as per Maximum Log-Likelihood (Image by Author)
这就完成了我们对符合骑自行车者计数数据集的 OLSR 模型的分析,以及它与泊松和负二项式回归模型的性能比较。
以下是本文中使用的完整 Python 源代码:
四个关键要点
- 尽管计数数据存在偏斜,且 OLSR 模型有产生负数和小数计数的倾向,对于基于计数的数据集而言,OLSR 模型可能是一个可行的回归模型。
- 仅仅因为 OLSR 模型在自行车计数数据集上表现良好,OLSR 模型并不总是在所有计数数据集上都表现得很好。OLS 回归在计数数据上的固有弱点必然会在更具“挑战性”的数据集上显现出来。
- 然而,OLSR 模型可以作为基于计数的数据的合理基线模型,它可以为我们提供一种方法,快速测试哪些模型参数对基于计数的数据建模最具统计意义。
- OLSR 模型也给了我们一种客观地比较好(或坏)多少的方法。)是一种复杂的基于计数的模型,如泊松模型、负二项式模型、梯度推进决策树模型或基于计数数据集的递归神经网络模型,有时会产生令人惊讶的结果。
感谢阅读!我撰写关于数据科学的主题,重点是时间序列分析和预测。
如果你喜欢这篇文章,请关注我的Sachin Date获取关于如何使用 Python 进行时间序列分析和预测的技巧、操作方法和编程建议。
伟大 R 程序员的五种行为
有这么多的人加入数据科学的行列,你如何从其他人中辨别出一个伟大的 R 程序员呢?
在新的数据科学时代,每个人都在赶时髦。招聘人员收到的简历和履历表中包含了所有的术语:R、Python、Javascript 等等。在许多情况下,人们会在大学一周的课程或几次数据营课程的基础上,将一项技能写进简历。
确定某人在特定编程语言方面的技能的最好方法是给他们设置一个任务,然后看看他们做得如何。在这些事情上,你不能只相信口口相传,你真的不希望你的团队或组织中有人在你需要的关键技能上达不到要求。
设置实用的编码练习有两个好处。首先,您可以测试个人是否知道如何处理和解决手头的问题,并能在工作中独立行事。第二,您可以识别编码行为,这些行为表明编码人员技术高超。
这里有五种特别针对 R 程序员的行为,我相信其中许多行为适用于其他各种编程语言:
评论
不管是什么语言,伟大的编码者都经常做好注释。这表明了对再现性的关注,也可能表明他们从经验中知道评论的重要性。
在哪里以及多久评论一次是一个判断的问题,取决于任务的复杂性,但是伟大的程序员会在一个合理详细的层次上评论。例如:
# load libraries
library(dplyr)#' Function to search starwars names by first letter of name
#'
#' [@param](http://twitter.com/param) x Character value to search as first letter
#'
#' [@return](http://twitter.com/return) a vector of namesfirst_letter_char_search <- function(x) {
starwars %>%
dplyr::mutate(first_letter = substr(name, 1, 1)) %>%
dplyr::filter(first_letter == x) %>%
dplyr::select(name)
}
格式化
代码格式对于轻松阅读和理解工作非常重要。正确格式化的代码表明编码者花费了时间和精力来确保他或她的代码尽可能的可读,这又影响了可再现性和未来的合作。
良好的格式还表明编码者知道他们语言的格式约定,这通常表明他们在这方面有相当丰富的经验。您将在上面的代码块中看到一些典型的 R 格式约定(尽管根据您查看本文的设备不同,可能不会像我希望的那样呈现)。间距和缩进是强格式最基本的方面。
命名空间
这取决于所使用的语言,但是在像 R 这样的语言中,命名空间显示了对编码者工作环境的关注。明确地说,命名空间意味着在代码中同时调用和函数及其包,而不仅仅是函数。比如调用lubridate::ymd()
而不仅仅是ymd()
。同样,在上面的代码块中,您将看到适当的函数命名空间。
命名空间有两个优点。首先,它防止了来自不同包的两个函数同名的问题。如果你加载两个包,并且它们都有一个共同的函数名,R 将总是使用最近加载的包中的函数,除非你命名你的函数。其次,如果另一个用户正在查看您的代码片段,它可以帮助他们确定需要安装哪些包。
码效率
伟大的程序员会关心他们代码和过程的效率。这可以采取多种形式:
- 重复的代码可以被抽象,以便单个功能可以执行重复的工作。更多信息见我的文章这里。
- 具有高计算强度的代码可以被重构以减少不必要的重复或低效的操作。
- 处理数据库对象的代码可以尽可能地操纵服务器上的数据,以避免将大量数据带到本地机器上——参见我的另一篇文章这里。
这可能是识别优秀程序员的一个重要区别。有人提交给我的代码荒谬且毫无意义地低效——用几百行代码完成了几行代码就能完成的事情。同样,我也见过在抽象和效率方面如此优雅的代码,以至于你不得不坐下来欣赏这位大师的作品。
打扫
伟大的程序员会自我清理。他们不会将可能与下一个任务冲突或导致安全漏洞的东西留在环境中。我见过的最常见的问题是,人们在获取了他们需要的东西后,却忽略了断开与数据库的连接。我喜欢看到漂亮整洁的代码块,在那里编码员已经打了招呼,说了再见。有礼貌是很好的,即使是数据库。
如果你正在寻找或雇佣程序员,考虑如何设置实践练习来测试他们的技能,看看你是否能发现一些积极的行为。我真的很推荐。
最初我是一名纯粹的数学家,后来我成为了一名心理计量学家和数据科学家。我热衷于将所有这些学科的严谨性应用到复杂的人的问题上。我也是一个编码极客和日本 RPG 的超级粉丝。在LinkedIn或Twitter上找我。
数据科学的五个命令行工具
从终端上你可以做比你想象的更多的数据科学
Photo by Toa Heftiba on Unsplash
数据科学最令人沮丧的一个方面是工作时不断在不同工具之间切换。您可以在 Jupyter 笔记本中编辑一些代码,必须在命令行上安装一个新工具,并且可能在 IDE 中编辑一个函数,所有这些都是在处理相同的任务时进行的。有时候,在同一个软件中找到做更多事情的方法是很好的。
在下面的帖子中,我将列出一些我发现的在命令行上进行数据科学研究的最佳工具。事实证明,通过简单的终端命令可以完成的任务比我最初想象的要多,我想在这里分享一些。
卷曲
这是一个通过各种协议(包括 HTTP)从任何服务器获取数据的有用工具。
我将给出几个获取公开可用数据集的用例。 UCI 机器学习资源库是获取机器学习项目数据集的绝佳资源。我将使用一个简单的 curl 命令下载一个来自台湾新竹市输血中心的数据集。如果我们简单地运行curl [url]
,在我们的例子中是curl [https://archive.ics.uci.edu/ml/machine-learning-databases/blood-transfusion/transfusion.data](https://archive.ics.uci.edu/ml/machine-learning-databases/blood-transfusion/transfusion.data)
,这将把数据打印到终端。
添加一些额外的参数将使用指定的文件名下载和保存数据。该文件现在可以在您当前的工作目录中找到。
curl -o data_dl.csv https://archive.ics.uci.edu/ml/machine-learning-databases/blood-transfusion/transfusion.data
为数据科学项目获取数据的另一种常见方法是通过 API。这个工具还支持与 API 交互的GET
和POST
请求。运行以下命令将从 OpenWeatherMap API 获得一条记录,并保存为一个名为weather.json
的 JSON 文件。关于 cURL 的更全面的教程,请看这篇优秀的文章。
curl -o weather.json -X GET \'https://api.openweathermap.org/data/2.5/weather?lat=37.3565982&lon=-121.9689848&units=imperial&appid=fd4698c940c6d1da602a70ac34f0b147' \-H 'Postman-Token: dcf3c17f-ef3f-4711-85e1-c2d928e1ea1a' \-H 'cache-control: no-cache'
csvkit
csvkit 是一组用于处理 CSV 文件的命令行工具。它可以执行的任务可以分为三个部分:输入、处理和输出。让我们来看一个如何使用它的快速真实示例。
首先让我们使用 pip install 安装工具。
pip install csvkit
出于这个例子的目的,我将使用我通过上面的 curl 命令从 UCI 机器学习库中创建的同一个 CSV 文件。
首先,让我们使用csvclean
来确保我们的 CSV 文件格式正确。该函数将自动修复常见的 CSV 错误并删除任何坏行。这个函数的一个有用的方面是,它自动输出一个新的干净的 CSV 文件版本,以便保留原始数据。新文件总是有下面的命名约定[filename]_out.csv
。如果你希望原始文件被覆盖,你可以添加可选的-n
参数。
csvclean data_dl.csv
在我的示例文件中,没有错误,但这是一种非常有用的方法,可以在处理 CSV 文件时进一步减少错误。
现在,假设我们想要快速检查文件。我们可以用csvcut
和csvgrep
来做到这一点。
首先让我们打印出列名。
csvcut -n data_dl_out.csv | cut -c6-Recency (months)Frequency (times)Monetary (c.c. blood)Time (months)whether he/she donated blood in March 2007
现在让我们确定目标列whether he/she donated blood in March 2007
中有多少个类。
csvcut -c "whether he/she donated blood in March 2007" data_dl_out.csv | sed 1d | sort | uniq01
csvgrep
函数允许您基于正则表达式匹配过滤 CSV 文件。
让我们使用这个函数只提取与类 1 匹配的行。
csvgrep -c "whether he/she donated blood in March 2007" -m 1 data_dl_out.csv
您还可以使用csvkit
功能执行简单的数据分析。
简单地运行csvstat data_dl_out.csv
将整个文件的描述性统计数据打印到命令行。您也可以使用可选命令只请求一个统计的结果。
csvstat --mean data_dl_out.csv1\. a: 373.52\. Recency (months): 9.5073\. Frequency (times): 5.5154\. Monetary (c.c. blood): 1,378.6765\. Time (months): 34.2826\. whether he/she donated blood in March 2007: None
IPython
IPython 允许从 shell 访问增强的交互式 Python。本质上,这意味着您可以从命令行完成在 Jupyter 笔记本中可以完成的大部分事情。
如果您的终端中还没有它,您可以按照这些步骤来安装它。
要启动 IPython,只需在命令行输入ipython
。您现在处于交互式 shell 中。在这里,您可以导入 python 安装的库,我发现这个工具对于在命令行上进行快速数据分析非常有用。
让我们在已经使用的数据集上执行一些基本任务。首先,我将导入 pandas,读入文件并检查前几行数据。
import pandas as pddata = pd.read_csv('data_dl_out.csv')data.head()
文件列名相当长,所以接下来,我将使用 pandas 对它们进行重命名,然后将结果数据帧导出到一个新的 CSV 文件中,供以后使用。
data = data.rename(columns={'Recency (months)': 'recency',
'Frequency (times)': 'frequency',
'Monetary (c.c. blood)': 'volumne',
'Time (months)': 'time',
'whether he/she donated blood in March 2007': 'target'})data.to_csv('data_clean.csv')
作为最后一个练习,让我们使用 pandas corr()
函数检查特征和目标变量之间的相关性。
corr_matrix = data.corr()
corr_matrix['target'].sort_values(ascending=False)
要退出 IPython,只需输入exit
。
csvsql
有时,您可能还想通过数据库上的 SQL 查询来获取数据集。工具 csvsql 也是 csvkit 工具的一部分,它支持直接在数据库上查询、写入和创建表。它还支持查询 CSV 文件的 SQL 语句。让我们对清理后的数据集运行一个示例查询。
csvsql --query "select frequency, count(*) as rows from data_clean where target = 1 group by frequency order by 2 desc" data_clean.csv
SciKit-Learn 实验室
是的,你可以在命令行执行机器学习!这方面有一些工具,但 SciKit-Learn 实验室可能是最容易使用的工具之一。让我们使用献血数据集建立一个模型。
SciKit-Learn 实验室依赖于将正确的文件放在命名一致的目录中。因此,首先我们将创建一个名为train
的目录,并将数据文件复制、移动并重命名为features.csv
。
mkdir train
cp data_clean.csv train/features.csv
接下来,我们需要创建一个名为predict-donations.cfg
的配置文件,并将它放在我们的data
目录中。
[General]
experiment_name = Blood_Donations
task = cross_validate[Input]
train_directory = train
featuresets = [["features.csv"]]
learners = ["RandomForestClassifier", "DecisionTreeClassifier", "SVC", "MultinomialNB"]
label_col = target[Tuning]
grid_search = false
objective = accuracy[Output]
log = output
results = output
predictions = output
然后我们简单地运行这个命令run_experiment -l predict-donations.cfg
。
这将自动运行实验,并创建一个包含结果的输出文件夹。
我们可以运行一个 SQL 查询来总结Blood_Donations_summary.tsv
文件中的结果。
cd output< Blood_Donations_summary.tsv csvsql --query "SELECT learner_name, accuracy FROM stdin "\
> "WHERE fold = 'average' ORDER BY accuracy DESC" | csvlook
还有许多其他命令行工具对数据科学有用,但我想在这里强调一下我在工作中发现有用的工具。要全面了解命令行中的数据科学,我发现《命令行中的数据科学》这本书非常有用,这本书可以在网上免费获得。
五种常见分析失败
统计学课上他们永远不会告诉你的事情
在我从事专业分析的这段时间里,我看到了一些常见的错误。我不一定会责怪犯下这些错误的人,因为他们从来没有被教导过这些是不好的事情。
大学的统计学课仍然过于理论化。现在,数据科学鼓励更多基于真实数据和案例研究的学习,这不像以前那么糟糕。但仍然有太多的公式,而没有足够的基于一旦进入现实世界就可能发生的事情的实用建议。毕竟,这不正是统计学应该做的吗?
如果我在大学教统计学,我可能会称之为“现实世界统计学 101”。这里有一些我会让人们失望的事情。
1.平均平均值
这是我经常看到的。有人计算了一大群子群的平均指标,然后想要给出整个群体的平均指标。所以他们只是取平均值。这几乎总是错误的做法。
除非每个亚组的数据都是可公度的,具有大致相同的基数和相似的代表性——这基本上是不可能的——那么平均化平均值只会人为地夸大或缩小整个群体的真实指标。这里有一个简单的例子,如果你尝试用世界银行关于女性在劳动力中的代表性的数据,会发生什么——让它看起来比实际高得多:
2.忽略范围限制
如果您在任何必须分析数据点随时间退化的流程的环境中工作,就会经常出现这种情况,例如,选择流程。一种常见的情况是,人们想知道过程早期的信息是否可以预测过程后期的事情。例如,您可能希望将面试评分与随后的工作表现相关联。
我经常看到人们忽略了这样一个事实,即流程中较晚的数据点是流程中较早的数据点的子集。由于中间的选择,数据点已被删除。他们经常得出结论,相关性很低或为零,并以此为基础贬低该过程的早期阶段,认为其不能预测后期阶段。
这可能是一个主要的问题,特别是如果这个过程是高度选择性的——就像如果只有一小部分处于早期阶段的人能够进入后期阶段。通常通过的数据点的统计值很高并且被压缩,因为统计值较低的数据点没有通过。
有多种方法可以校正范围限制的相关性。下面是一个常用的公式:
但是我想澄清一点——如果限制是实质性的,那么所有的公式都是不可靠的。在这些情况下,如果相关性分析没有揭示任何值得注意的东西,我简单地宣布,由于范围限制问题,我们不能得出任何结论。
3.对二元结果使用线性回归
我认为当人们这样做的时候,他们要么完全忘记了他们的统计课,要么就是睡过了头。
线性回归是一个非常简单的过程,它基本上有助于预测一个具有连续数值范围的变量。比如汽车的价格。截距和系数被确定并直接应用于新的输入以确定预测值。使用平方和(毕达哥拉斯定理计算距离的扩展)很容易确定模型拟合。
试图在二元结果上使用这种方法是一个非常糟糕的主意。违反了线性回归中关于方差和残差的大多数基本假设,并且输出不是为了预测简单的二元结果而设计的。这是疯狂的,这表明做这件事的人在统计学方面不是特别训练有素,或者害怕逻辑回归,或者别的什么!
有些人尝试用线性概率模型来让线性回归方法处理二元结果数据。我一点也不相信这一点,它没有解决[0,1]范围之外的概率仍然可能发生的事实。
4.把你所有的鸡蛋放在 p 篮子里(或者根本没有 p 篮子)
p-hacking 正成为近年来统计和数据科学界越来越多关注的话题。人们越来越不愿意接受这样一种观点,即一条冷酷的显著性线是决定一件事是否值得作为分析性见解进行交流的唯一决定因素。
我经常看到这个问题的两个极端。我经常看到 p 值被完全忽略,因此一些 p 值为 0.5 的模式被提出来作为一种见解。而且我也看到了对 p < 0.05 边界的过分依赖。
这就是常识被抛弃的地方。从直觉上来说,数据中的模式是否显著取决于它所产生的影响,以及这种影响是否可以被认为是“不寻常的”。这说明了统计学家的一些判断:
- 如果数据确实很大,即使是极小的影响也能通过 p < 0.05 的条件。重要的是这种影响微乎其微。
- 如果数据不是很大,但效果似乎是,那么 p < 0.05 不应该是这种洞察力是否显著的唯一考虑因素。
5.使用不良语言
我不是说脏话(尽管我已经用我必须处理的一些数据集做了很多)。我的意思是没有准确地写出你的见解和结论。
语言在帮助他人理解他们可以从分析中得出的结论方面非常重要。我经常看到拙劣的语言会导致人们得出错误的结论,例如,在没有证据的情况下暗示因果关系存在,或者没有适当的限定结论。
例如,看看詹姆斯·邦德电影的相关矩阵:
说邦德的酗酒和杀人是增加电影预算的原因是很诱人的,但这假设了一种因果关系,我们还没有证明。更有可能的是,更长的电影涉及更多的饮酒和杀戮,制作成本也更高。但这一点我们也不能下定论。我在这里使用的语言很简单:“电影预算主要与喝多少马提尼酒和邦德杀死多少人有关。”这仍然是一个非常有趣的结论!
最初我是一名纯粹的数学家,后来我成为了一名心理计量学家和数据科学家。我热衷于将所有这些学科的严谨性应用到复杂的人的问题上。我也是一个编码极客和日本 RPG 的超级粉丝。在 LinkedIn 或Twitter上找我。
Courtesy of DigitalSpyUK