TowardsDataScience 博客中文翻译 2020(三百四十六)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

无人谈论的基本数据科学技能。

原文:https://towardsdatascience.com/essential-data-science-skills-that-no-one-talks-about-74bca9ec4892?source=collection_archive---------34-----------------------

老式的工程技能是你促进数据科学事业所需要的

谷歌“一个数据科学家的必备技能”。顶部结果是一长串技术术语,命名为硬技能。Python、代数、统计和 SQL 是最受欢迎的一些。后来,出现了软技能——沟通、商业头脑、团队合作精神等。

让我们假设你是一个拥有以上所有能力的超人。你从五岁开始编码,你是一个围棋大师,你的会议论文肯定会获得最佳论文奖。你知道吗?您的项目仍有很大的机会努力达到成熟,并成为成熟的商业产品。

最近的研究估计,超过 85%的数据科学项目无法进入生产阶段。这些研究为失败提供了许多原因。而且我也没有看到所谓的必备技能作为潜在原因被提及过一次。

我是不是在说上面的技巧不重要?当然,我不是。软硬技能都至关重要。关键是它们是必要的,但还不够。此外,它们很受欢迎,出现在每次谷歌搜索中。所以机会是你已经知道你是否需要提高你的数学水平或者团队合作。

我想说的是和流行的软硬技能互补的技能。我称之为工程技能。它们对于用真实的客户构建真实的产品特别有用。遗憾的是,数据科学家很少学习工程技能。它们伴随着经验而来。大多数初级数据科学家缺乏这些。

工程技能与数据工程领域无关。我用工程技能这个术语来区分它们和纯粹的科学或研究技能。根据剑桥词典, 工程 是运用科学原理设计和建造机器、结构和其他物品。在本文中,工程是将科学转化为产品的促成因素。如果没有适当的工程,模型将继续在预定义的数据集上运行。但是他们永远不会接触到真正的顾客。

外卖:

重要但经常被忽视的技能是:

  1. 简单。确保你的代码和模型简单,但不要过于简单化。
  2. 鲁棒性。你的假设是错误的。喘口气,继续编码。
  3. 模块化。分而治之。深入挖掘最小的问题,然后找到一个开源解决它。
  4. 水果采摘。不要只关注那些唾手可得的果实。但是要确保你总是有东西可以挑选。

简单

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

图片来源:shutterstock

"没有必要,实体不应相乘 " —奥卡姆的威廉。“简单是最高级的复杂”—莱昂纳多·达芬奇。一切都应该尽可能简单,但不要简单到极点。“这是我的座右铭之一——专注和简单”——史蒂夫·乔布斯。

我本可以用一整页的篇幅来引用关于简洁的内容。研究人员、设计师、工程师、哲学家和作家都称赞简约,并表示简约有其自身的价值。他们的理由变了,但结论是一样的。你达到完美不是因为没有什么可以添加,而是因为没有什么可以去除。

软件工程师绝对意识到简单的价值。关于如何让软件变得更简单,有很多书籍和文章。我记得接吻原则——保持简单,笨蛋——甚至在我的一门本科课程中也教过。简单的软件维护起来更便宜,更容易修改,也不容易出现 bug。对此有广泛的共识。

在数据科学中,情况非常不同。有很多文章,例如,Kristian Bondo Hansen 的《简单的优点:算法交易中的 ML 模型》或者 Alfredo Gemma 的《简单在数据科学革命中的作用》。但它们是例外,而不是规律。数据科学家的主流往好里说不在乎,往坏里说更喜欢复杂的解决方案。

在继续解释为什么数据科学家通常不关心,为什么他们应该关心,以及如何处理之前,让我们看看简单意味着什么。根据剑桥词典的解释,是容易理解或做的品质,是朴素的品质,没有不必要或多余的东西或装饰

我发现定义简单最直观的方式是通过否定,作为复杂的反义词。根据同一字典,复杂性是由许多相互连接的部分或元素组成的*;错综复杂*。虽然我们不能总是说某事简单,但我们通常可以说某事复杂。我们可以力求不复杂,不创造复杂的解决方案。

在数据科学中寻求简单的原因与在所有工程学科中的原因是一样的。更简单的解决方案要便宜得多。现实生活中的产品不是 Kaggle 比赛。需求是不断修改的。当一个复杂的解决方案需要适应新的条件时,它很快就变成了维护的噩梦。

很容易理解为什么数据科学家,尤其是应届毕业生,更喜欢复杂的解决方案。他们刚从学院回来。他们已经完成了论文,甚至可能发表了论文。一个学术出版物是由准确性、数学优雅性、新颖性、方法论来评判的,但很少由实用性和简单性来评判。

一个复杂的想法,提高 0.5%的准确率,对任何一个学生来说都是巨大的成功。对于数据科学家来说,同样的想法是失败的。即使它的理论是合理的,它也可能隐藏着被证明是错误的潜在假设。在任何情况下,增量改进几乎不值得复杂性的代价。

那么,如果你、你的老板、你的同事或你的下属喜欢复杂和“最优”的解决方案,该怎么办呢?如果是你的老板,你很可能在劫难逃,你最好开始找份新工作。在其他情况下,保持简单,愚蠢。

稳健性

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

图片来源:shutterstock

俄罗斯文化中有一个概念叫做“avos”。维基百科将其描述为“盲目相信天意,指望纯粹的运气”。“Avos”是卡车司机超载决定的幕后黑手。它隐藏在任何不可靠的解决方案后面。

什么是稳健性?或者具体来说,数据科学中的鲁棒性是什么?与我们的讨论最相关的定义是“算法的健壮性是它对假设模型和现实之间的差异的敏感性”,来自 Mariano Scain 论文。对现实不正确的假设是数据科学家问题的主要来源。他们也是上面卡车司机的问题来源。

细心的读者可能会说,鲁棒性也是算法在执行过程中处理错误的能力。他们可能是对的。但它与我们的讨论不太相关。这是一个技术问题,有明确的解决方案。

在前大数据时代和前深度时代,构建强大系统的必要性显而易见。功能和算法设计是手动的。测试通常在成百上千个例子上进行。即使是最聪明的算法创造者也从未假设他们能想到所有可能的用例。

大数据时代是否改变了鲁棒性的本质?我们为什么要关心我们是否可以使用代表所有可想象场景的数百万数据样本来设计、训练和测试我们的模型呢?

它指出,鲁棒性仍然是一个重要的和未解决的问题。每年顶级期刊都会通过发表关于算法鲁棒性的论文来证明这一点,例如,“提高深度神经网络的鲁棒性”和“基于模型的鲁棒深度学习”。数据的数量并没有转化为质量。用于培训的大量信息并不意味着我们可以涵盖所有用例。

而如果人参与其中,现实总是出乎意料,难以想象的。我们大多数人都不知道午餐吃什么,更不用说明天了。数据很难帮助预测人类行为。

那么,怎样做才能使你的模型更健壮呢?第一种选择是阅读适当的论文并实施他们的想法。这很好。但是这些论文并不总是通用的。通常,你不能把一个想法从一个领域复制到另一个领域。

我想介绍三种常规做法。遵循实践并不能保证健壮的模型,但是它显著地减少了脆弱解决方案的机会。

性能安全裕度。安全裕度是任何工程的基础。为了安全起见,通常的做法是获取需求并增加 20–30%。一个能装 1000kg 的电梯,会轻松装 1300kg。而且测试的是能装 1300kg 而不是 1000kg。工程师为意外情况做准备。

数据科学中的安全边际相当于什么?我认为是 KPI 或成功标准。即使发生了意想不到的事情,你依然会在门槛之上。

这种实践的重要结果是你将停止追逐增量改进。如果你的模型增加了 1%的 KPI,你就不可能稳健。在所有的统计显著性测试中,环境的任何微小变化都会扼杀你的努力。

过度测试。忘记单一测试/培训/验证部门。你必须在所有可能的组合中交叉验证你的模型。你有不同的用户吗?按照用户 ID 划分,做几十遍。您的数据会随着时间的推移而改变吗?根据时间戳划分,并确保每天在验证组中出现一次。用随机值或在数据点之间交换某些特征的值来“垃圾”您的数据。然后对脏数据进行测试。

我发现假设我的模型有错误是非常有用的,直到被证明不是这样。

关于数据科学和 ML 测试的两个有趣来源——Alex Gude 的博客和“用 Python 进行机器学习,一种测试驱动的方法”。

**不要把城堡建在沙滩上。**减少对其他未测试组件的依赖。永远不要在另一个高风险和未经验证的组件之上构建您的模型。哪怕那个组件的开发者信誓旦旦说什么都不会发生。

模块性

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

图片来源:快门股票

模块化设计是所有现代科学的基本原则。这是分析方法的直接结果。分析方法是一个将大问题分解成小问题的过程。分析方法是科学革命的基石。

你的问题越小越好。这里的“更好”并不意味着拥有它是件好事。这是必须的。这会节省大量的时间、精力和金钱。当一个问题很小,定义明确,并且没有大量假设时,解决方案是准确的,并且易于测试。

大多数数据科学家都熟悉软件设计环境中的模块化。但是,即使是最好的程序员,他们的 python 代码非常清晰,也常常无法将模块化应用于数据科学本身。

失败是很容易证明的。模块化设计需要一种方法将几个较小的模型组合成一个大模型。不存在这样的机器学习方法。

但是有一些实用的指导方针我觉得很有用:

  • 迁移学习。迁移学习简化了现有解决方案的使用。你可以把它想成把你的问题分成两部分。第一部分创建低维特征表示。第二部分直接优化相关 KPI。
  • 开源。尽可能使用现成的开源解决方案。根据定义,它使您的代码模块化。
  • 忘了被优化。从头开始构建一个针对您的需求而优化的系统,而不是修改现有的解决方案,这是很有诱惑力的。但是只有当你能证明你的系统明显优于现有系统时,它才是合理的。
  • 模型组合。不要害怕采取几种不同的方法,把它们扔进一个锅里。这是因为大多数卡格尔比赛都赢了。
  • 划分你的数据。不要试图创造“一个伟大的模式”,虽然从理论上讲,这是可能的。例如,如果你处理预测客户行为,不要为一个全新的客户和已经使用你的服务一年的人建立相同的模型。

查看组合深度学习了解更多关于深度学习构建模块的细节。阅读修剪过的神经网络惊人地模块化以获得科学证明。

采果

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

图片来源:shutterstock

产品经理和数据科学家之间的关系一直很紧张。产品经理希望数据科学家专注于唾手可得的成果。他们的逻辑很清楚。他们说企业只关心水果的数量和它们生长的地方。水果越多,我们做得越好。他们加入了各种流行词汇——帕累托、MVP、最好是最好的敌人等等。

另一方面,数据科学家指出,挂在低处的水果容易腐烂,味道也不好。换句话说,解决简单的问题影响有限,而且治标不治本。通常,这是学习新技术的借口,但通常他们是对的。

就我个人而言,我在两种观点之间徘徊。在阅读了 P. Thiel 的《零比一》之后,我确信那些低挂的果实是在浪费时间。在初创企业呆了近 7 年后,我确信创造一个容易实现的 MVP 是正确的第一步。

最近,我开发了自己的方法,将这两个极端统一起来。数据科学家的典型环境是一个动态而怪异的世界,树木向四面八方生长。这些树一直在变换方向。它们可以倒着或横着生长。

最好的果实确实在顶端。但是如果我们花太多时间搭梯子,树就会移动。因此,最好的办法是瞄准顶部,但要不断监控顶部在哪里。

从隐喻到实践,在漫长的发展过程中,事情总有可能会发生变化。原来的问题将变得无关紧要,新的数据源将出现,原来的假设将被证明是错误的,KPI 将被取代,等等。

瞄准顶端是很好的,但是记住在每隔几个月推出一个工作产品的时候也要这么做。该产品可能不会带来最好的水果,但你会更好地了解水果是如何生长的。

Python 和 R 之间翻译的基本指南

原文:https://towardsdatascience.com/essential-guide-to-translating-between-python-and-r-7cb18b786e5d?source=collection_archive---------12-----------------------

使用 Python 或 R 知识有效学习另一种语言的简单方法。

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

作为一个以英语为母语的人,当我小时候开始学习西班牙语时,三个关键的练习帮助我从笨拙地试图将我的英语单词翻译成西班牙语,到直接用西班牙语思考和回应(偶尔甚至做梦)。

  1. 把新的西班牙语单词和我已经知道的英语单词联系起来。对比西班牙语和英语单词使我能很快理解新单词的意思。
  2. 多次重复这个词,并在许多不同的场景中使用它,让这些词在我脑海中反复出现。
  3. 利用上下文的线索让我更好地理解了这个词是如何以及为什么要用在它的同义词上。

当你第一次学习编码时,重复和语境化是必不可少的。通过不断的重复,你开始记忆词汇和语法。当您开始看到在不同的上下文环境中使用的代码时,通常通过项目开发,您能够理解不同的功能和技术是如何以及为什么被使用的。但是,不一定有一种简单的方法可以将新的思维方式与您所说的语言联系起来,这意味着您不仅仅是记住一个单词,而是必须对每个编程概念形成新的理解。甚至你写的第一行代码,打印(“Hello World!”)需要你学习 print 函数的工作原理,编辑器如何返回 print 语句,以及何时使用引号。当你学习第二种编程语言时,你可以将概念从你所知道的语言翻译到新的语言中,从而更有效、更快速地学习。

数据科学领域分为 Python 拥护者和 R 爱好者。但是,任何已经学习了其中一种语言的人都应该利用他们的优势,一头扎进另一种语言中,而不是宣布支持哪一方。Python 和 R 之间有无限的相似之处,有了这两种语言,您可以用最好的方式解决挑战,而不是把自己限制在工具棚的一半。下面是连接 R 和 Python 的简单指南,便于两者之间的转换。通过建立这些联系,反复与新语言交互,并与项目联系起来,任何懂 Python 或 R 的人都可以很快开始用另一种语言编程。

基础知识

将 Python 和 R 放在一起看,你会发现它们的功能和外观非常相似,只有语法上的细微差别。

数据类型

# Python                              # R
type()                                class()
type(5) #int                          class(5) #numeric
type(5.5) #float                      class(5.5) #numeric
type('Hello') #string                 class('Hello') #character
type(True) #bool                      class(True) #logical

分配变量

# Python                              # R
a = 5                                 a <- 5

导入包

# Python                              # R
pip install packagename               install.packages(packagename)import packagename                    library(packagename)

数学:是一样的——数学在所有语言中都是一样的!

# Python                              # R
+ - / *                               + - / *# The same goes for logical operators
< #less than                          < #less than
> #greater than                       > #greater than
<= #less than or equal to             <= #less than or equal to
== #is equal to                       == #is equal to
!= #is not equal to                   != #is not equal to
& #and                                & #and
| #or                                 | #or

调用函数

# Python                              # R
functionname(args, kwargs)            functionname(args, kwargs)print("Hello World!")                 print("Hello World!")

If / Else 语句

# Python                              # R
if True:                              if (TRUE) {
    print('Hello World!')                 print('Go to sleep!')
else:                                 } else {
    print('Not true!')                    print('Not true!') 
                                      }

列表和向量:这个有点夸张,但是我发现这个联系很有帮助。

  • 在 python 中,列表是任何数据类型的有序项目的可变集合。在 Python 中索引列表从 0 开始,并且不包含。
  • 在 R 中,向量是同一类型有序项目的可变集合。索引 R 中的向量从 1 开始,包括 1 和 1。
# Python                              # R
ls = [1, 'a', 3, False]               vc <- c(1, 2, 3, 4)# Python indexing starts at 0, R indexing starts at 1
b = ls[0]                             b = vc[1]
print(b) #returns 1                   print(b) #returns 1c = ls[0:1]                           c = vc[1:2]
print(c) #returns 1                   print(c) #returns 1, 2

对于循环

# Python                              # R
for i in range(2, 5):                 for(i in 1:10) {
    a = i                                 a <- i }

数据操作

python 和 R 都提供了简单而流畅的数据操作,使它们成为数据科学家的必备工具。这两种语言都配备了能够加载、清理和处理数据帧的包。

  • 在 python 中,pandas 是使用 DataFrame 对象加载和操作数据框最常用的库。
  • 在 R 中,tidyverse 是一个类似的库,它使用 data.frame 对象实现简单的数据帧操作。

此外,为了简化代码,两种语言都允许多个操作通过管道连接在一起。在 python 中。在 r 中使用%>%管道时,可以用来组合不同的操作。

读取、写入和查看数据

# Python                              # R
import pandas as pd                   library(tidyverse) # load and view data
df = pd.read_csv('path.csv')          df <- read_csv('path.csv')df.head()                             head(df)df.sample(100)                        sample(df, 100)df.describe()                         summary(df) # write to csv
df.to_csv('exp_path.csv')             write_csv(df, 'exp_path.csv')

重命名和添加列

# Python                              # R
df = df.rename({'a': 'b'}, axis=1)    df %>% rename(a = b)df.newcol = [1, 2, 3]                 df$newcol <- c(1, 2, 3)df['newcol'] = [1, 2, 3]              df %>% 
                                         mutate(newcol = c(1, 2, 3))

选择和过滤列

# Python                              # R
df['col1', 'col2']                    df %<% select(col1,col2)df.drop('col1')                       df %<% select(-col1)

筛选行

# Python                              # R
df.drop_duplicates()                  df %<% distinct()df[df.col > 3]                        df %<% filter(col > 3)

排序值

# Python                              # R
df.sort_values(by='column')           arrange(df, column)

汇总数据

# Python
df.groupby('col1')['agg_col').agg(['mean()']).reset_index()# R
df %>% 
    group_by(col1) %>% 
    summarize(mean = mean(agg_col, na.rm=TRUE)) %>%
    ungroup() #if resetting index

使用过滤器聚合

# Python
df.groupby('col1').filter(lambda x: x.col2.mean() > 10)# R
df %>% 
    group_by(col1) %>% 
    filter(mean(col2) >10)

合并数据框

# Python
pd.merge(df1, df2, left_on="df1_col", right_on="df2_col")# R
merge(df1, df2, by.df1="df1_col", by.df2="df2_col")

上面的例子是在 Python 和 r 之间建立思维上的相似性的起点。虽然大多数数据科学家倾向于使用这两种语言中的一种,但是精通这两种语言使您能够利用最适合您需求的工具。

请在下面留下您认为有用的任何相似之处和附加评论。

基于股票市场数据构建机器学习模型的基本准则

原文:https://towardsdatascience.com/essential-guidelines-for-building-machine-learning-models-on-stock-market-data-717e92d5feed?source=collection_archive---------42-----------------------

在股票市场数据上建立机器学习模型时需要考虑的三件重要事情

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

图片:Pixabay.com

注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

为股票市场投资建立一个机器学习模型似乎是一个很好的主意。如果这个模式成功了,它会让你变得富有。如果没有,你至少会知道建立一个机器学习模型需要什么。股票市场如此欢迎机器学习的另一个原因是历史数据的可用性。

但是,仅仅因为数据是广泛可用的,并不意味着你可以不加考虑地使用它。事实上,在基于历史基本面股票数据建立机器学习模型时,有三个基本问题需要考虑。忽略它们会使你的模型对现实世界的应用毫无用处。下面,我将讨论在为机器学习处理股市数据时需要遵循的三个基本准则。

在对 2020 年 1 月 1 日的模型进行训练和回溯测试时,我可以使用网飞第四季度的基本面数据吗?不,你不应该——当然,除非你想作弊。

1.不要使用未来的数据进行回溯测试

想象一下,你正在建立一个机器学习模型,它将在每个季度初预测股票的季度表现。这种模型应该为投资者提供准确的指导,例如在 2020 年 1 月 1 日,一只股票在 2020 年 3 月 30 日之前是上涨、下跌还是横盘整理。当建立这样一个模型时,你需要确保你没有使用未来的数据。在我们的例子中,这意味着你的训练集不能包含 2020 年 1 月 1 日及以后的数据。

要使历史股票市场数据变得复杂一点,您还需要考虑数据何时可用。让我们回到我们的例子,看看网飞截至 2020 年 12 月 31 日的第四季度业绩。在对 2020 年 1 月 1 日的模型进行训练和回溯测试时,我可以使用网飞第四季度的基本面数据吗?不,你不应该——当然,除非你想作弊。原因是 2020 年 1 月 21 日公布了 Q4 业绩。这是测试和训练你的模型的截止日期之后的 20 天。因此,在你的模型中使用第四季度的结果意味着你要么有内部消息,要么有一个神奇的水晶球。下面是说明市场数据可用性问题的时间表。

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

网飞第四季度业绩的公布和归档

对此我能做些什么?如何确保我的模型中没有使用未来的数据?

有三种方法可以解决这个问题。第一个解决方案是使用所谓的即时市场数据。时间点数据会考虑数据何时公开。这确保了当您查看网飞在 2020 年 1 月 1 日的最新收入时,您将获得第三季度的数据,而不是第四季度的数据,因为那时还没有这些数据。大多数主要的付费市场数据提供商都允许您访问这些即时数据。例如,彭博允许您使用他们的 BQL API 检索时间点数据。

如果你无法获得即时市场数据,那么你可以使用滞后市场数据。美国证券交易委员会(SEC)规定,公司必须在前三个季度结束后 35 天内、最后一个季度结束后 60 天内提交收益报告。在我们的示例中,我们可以强制模型使用 2019 年 10 月 16 日发布的第三季度结果。

第三种选择是在 SEC 的 EDGAR 网站【https://www.sec.gov/edgar/searchedgar/companysearch.html的帮助下创建自己的即时市场数据库。EDGAR 网站包括每份年度和季度报告的归档日期信息。多亏了几个很棒的免费 Python 包,可以相对容易地搜集这些信息。

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

SEC EDGAR 网站上的网飞 10-K 年度报告提交日期信息

然而,使用滞后的市场数据或通过抓取 SEC 的 EDGAR 网站建立自己的时间点数据库,都无法击败专门的时间点数据提供商的准确性。它不考虑重述,滞后数据可能“过于滞后”。即使您精心构建时间点数据库也会包含不准确性。例如,网飞在 2020 年 1 月 21 日发布了第四季度的业绩,但在 8 天后的 2020 年 1 月 29 日提交了报告。但是,如果你没有时间点市场数据提供商,使用滞后数据或建立自己的时间点数据库是下一个最好的选择。

使用静态股票列表进行回溯测试意味着你忽略了所有破产或因其他原因退市的公司。

2.当心不断变化的股票市场,避免生存偏差

每当你为股市投资建立机器学习模型时,你都必须决定要考虑哪些股票。这可以是一个指数,如标准普尔 500 或美国所有公开交易的股票。无论你选择什么样的股票,你都需要意识到它的构成在不断变化。让我们把标准普尔 500 指数作为我们的股票宇宙,我们将使用它作为我们的机器学习模型。标准普尔 500 指数目前包括 505 家公司。2015 年,目前构成标准普尔 500 指数的公司中只有 75%是该指数的一部分。剩下的 25%是因为业绩不佳而被摘牌或者干脆从标准普尔 500 指数中剔除的公司。2010 年,这个数字是 65%,而在 2000 年,只有 45%的标准普尔 500 成份股构成了该指数。

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

标准普尔 500 指数构成变化

忽视不断变化的股票市场会把你的模型引入所谓的生存偏差。使用静态股票列表进行回溯测试意味着你忽略了所有破产或因其他原因退市的公司。此外,在他们真正成为“赢家”之前,你就在考虑“赢家”。再来看 AMD。2016 年 AMD 股价从 2.10 到 11.30。然后在 2017 年 3 月,AMD 取代 Urban Outfitters 加入了标准普尔 500 指数。因此,在 2016 年你的标准普尔 500 宇宙中有 AMD 会被认为是作弊。

解决这个问题的方法很简单。不要在你的股票市场中使用静态的股票列表。确保你对每个时期进行调整,以反映任何给定时间点的真实成分。

3.使用调整后的价格

在为机器学习处理股市数据时,要考虑的最后一件重要事情很简单。使用调整后的股票价格。对于有经验的甚至是新手的股票交易者来说,这似乎是显而易见的。但对于没有股市经验的数据科学家来说,调整后的价格可能是一个新概念。这里有一个简短的解释为什么我们使用调整后的股票价格。

例如,公司可能会决定进行二对一的股票分割。这意味着,如果你拥有 100 股,在股票分割后,你将拥有 200 股。这样的股票分割会如何影响股价?自然,价格会减半,因为公司的价值没有变化。调整后的股票价格考虑了影响价格但不影响基础价值的股票分割和其他类似事件,并对其进行调整以反映更准确的股票价值。

幸运的是,大多数主要的股市数据提供商默认使用调整后的价格,因此使用非调整后价格的可能性很低。只要仔细检查你是否真的在使用调整后的价格,你不应该在事后担心它。

这是你在股市数据上建立机器学习模型时应该考虑的三个基本准则。遵循它们能确保成功的机器学习模型吗?肯定不是!建立一个模型有无数种可能性。知道哪个可行哪个不可行,几乎是不可能的。但是,遵循这些准则将确保您的模型建立在坚实的基础上。

ROC 曲线下面积和积分

原文:https://towardsdatascience.com/essential-math-for-data-science-area-under-the-roc-curve-and-integrals-8a0f718dc9df?source=collection_archive---------17-----------------------

数据科学的基本数学

使用 ROC 曲线下的面积了解积分和模型性能比较

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

( 图片作者 )

积分和曲线下的面积

微积分是数学的一个分支,它通过两个主要领域提供研究函数变化率的工具:导数和积分。在机器学习和数据科学的背景下,您可能会使用积分来计算曲线下的面积(例如,评估具有 ROC 曲线的模型的性能,或者根据密度来计算概率。

在本文中,您将学习积分和曲线下面积,使用 ROC 曲线下面积的实际数据科学示例来比较两种机器学习模型的性能。从这个例子开始,你会从数学的角度看到曲线下面积和积分的概念(来自我的书《数据科学基础数学》)。

实际项目

比方说,你想从葡萄酒的各种化学特性来预测葡萄酒的质量。你想做一个质量的二元分类(区分非常好的葡萄酒和不太好的葡萄酒)。您将开发一些方法,允许您在考虑受试者操作特征(ROC)曲线下面积不平衡数据的情况下评估您的模型。

资料组

为此,我们将使用一个数据集来显示红葡萄酒的各种化学特性及其质量评级。数据集来自这里:https://archive.ics.uci.edu/ml/datasets/wine+quality。相关论文是 Cortez,Paulo 等人的“通过物理化学性质的数据挖掘对葡萄酒偏好建模”决策支持系统 47.4(2009):547–553。

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

*图 1:葡萄酒质量建模示意图。(*图片作者 )

如图 1 所示,数据集代表了葡萄酒的化学分析(特性)和质量评级。这个评级是目标:这是你要尝试评估的。

首先,让我们加载数据,看看特性:

Index([‘fixed acidity’, ‘volatile acidity’, ‘citric acid’, ‘residual sugar’,
 ‘chlorides’, ‘free sulfur dioxide’, ‘total sulfur dioxide’, ‘density’,
 ‘pH’, ‘sulphates’, ‘alcohol’, ‘quality’],
 dtype=’object’)

最后一列quality很重要,因为您将使用它作为您分类的目标。质量由从 3 到 8 的等级来描述:

array([5, 6, 7, 4, 8, 3])

既然目标是对非常好质量的红酒进行分类,那么让我们决定当评级为 7 或 8 时红酒是非常好的,否则就不是非常好。

让我们创建一个数据集,其中y是质量(因变量,0 表示评分小于 7,1 表示评分大于或等于 7),而X包含所有其他特征。

在查看数据之前,要做的第一件事是将数据分成一部分用于训练算法(训练集)和一部分用于测试算法(测试集)。这将使您能够评估模型在培训期间不可见的数据上的性能。

预处理

作为第一步,让我们标准化数据,以帮助算法的收敛。你可以使用 Sklearn 的类StandardScaler

请注意,您不希望考虑来自测试集的数据来进行标准化。方法fit_transform()计算标准化所需的参数并同时应用。然后,您可以对测试集应用相同的标准化,而无需再次拟合。

第一个模型

作为第一个模型,让我们在训练集上训练逻辑回归,并在测试集上计算分类准确度(正确分类的百分比):

0.8729166666666667

准确度约为 0.87,这意味着 87%的测试示例已被正确分类。你应该对这个结果感到高兴吗?

不平衡数据集的度量

不平衡数据集

由于我们将数据分为非常好的葡萄酒和不太好的葡萄酒,因此数据集是不平衡的:每个目标类别对应的数据量不同。

让我们看看你在消极类(不是很好的葡萄酒)和积极类(很好的葡萄酒)中有多少观察结果:

0.8650580875781948
0.13494191242180517

它表明大约有 86.5%的例子对应于 0 类,13.5%对应于 1 类。

简单模型

为了说明关于准确性和不平衡数据集的这一点,让我们创建一个模型作为基线,并查看其性能。这将有助于您了解使用准确性之外的其他指标的优势。

利用数据集不平衡这一事实的非常简单的模型将总是估计具有最大数量观察值的类。在你的例子中,这样一个模型将总是估计所有的葡萄酒都是坏的,并得到相当的准确性。

让我们通过创建低于 0.5 的随机概率来模拟这个模型(例如,0.15 的概率意味着该类有 15%的可能性是正的)。我们需要这些概率来计算准确性和其他指标。

array([2.08511002e-01, 3.60162247e-01, 5.71874087e-05, …,
 4.45509477e-01, 1.36436118e-02, 2.61025624e-01])

假设如果概率高于 0.5,则该类被估计为正:

array([0, 0, 0, …, 0, 0, 0])

变量y_pred_random只包含零。让我们评估一下这个随机模型的准确性:

0.8625

这说明,即使是随机模型,精度一点都不差:不代表模型好。

总的来说,每一类都有不同数量的观察值,你不能依靠精确度来评估你的模型的性能。在我们的例子中,模型可以只输出零,你会得到大约 86%的准确性。

您需要其他指标来评估具有不平衡数据集的模型的性能。

ROC 曲线

精度的一个很好的替代方法是接收机工作特性(ROC)曲线。你可以在 Géron,Aurélien 查看 Aurélien Géron 关于 ROC 曲线的非常好的解释。使用 Scikit-Learn、Keras 和 TensorFlow 进行机器学习:构建智能系统的概念、工具和技术。奥莱利媒体,2019。

主要思想是将模型中的估计分为四类:

  • 真阳性(TP):预测值为 1,真实类别为 1。
  • 误报(FP):预测是 1,但真实类别是 0。
  • 真负值(TN):预测值为 0,真实类别为 0。
  • 假阴性(FN):预测值为 0,但真实类别为 1。

让我们为您的第一个逻辑回归模型计算这些值。可以使用 Sklearn 的函数confusion_matrix。它提供了一个组织如下的表格:

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

*图 2:混淆矩阵的图示。(*图片作者 )

array([[414, 0],
 [ 66, 0]])

你可以看到,没有一个积极的观察已被正确分类(TP)与随机模型。

决定阈值

在分类任务中,您希望估计数据样本的类别。对于像逻辑回归这样输出 0 到 1 之间概率的模型,您需要使用决策阈值或仅使用阈值将该分数转换为 0 或 1 类。高于阈值的概率被认为是正类。例如,使用决策阈值的默认选择 0.5,当模型输出高于 0.5 的分数时,您认为估计的类是 1。

但是,您可以选择其他阈值,用于评估模型性能的指标将取决于此阈值。

使用 ROC 曲线,您可以考虑 0 到 1 之间的多个阈值,并根据每个阈值的假阳性率来计算真阳性率。

可以使用 Sklearn 的函数roc_curve来计算假阳性率(fpr)和真阳性率(tpr)。该函数还输出相应的阈值。让我们用我们模拟的随机模型来试试吧,在这个模型中,输出只有低于 0.5 的值(y_pred_random_proba)。

让我们来看看输出结果:

array([0\. , 0\. , 0.07246377, …, 0.96859903, 0.96859903,
 1\. ])
array([0\. , 0.01515152, 0.01515152, …, 0.98484848, 1\. ,
 1\. ])
array([1.49866143e+00, 4.98661425e-01, 4.69443239e-01, …,
 9.68347894e-03, 9.32364469e-03, 5.71874087e-05])

现在,您可以根据这些值绘制 ROC 曲线:

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

*图 3:随机模型对应的 ROC 曲线。(*图片作者 )

图 3 显示了对应于随机模型的 ROC 曲线。它给出了真阳性率,作为每个阈值的假阳性率的函数。

但是,要小心,阈值是从 1 到 0。例如,左下方的点对应于阈值 1:有 0 个真阳性和 0 个假阳性,因为不可能有大于 1 的概率,所以阈值为 1 时,没有观察结果可以归类为阳性。在右上方,阈值是 0,因此所有的观察都被分类为阳性,导致 100%的真阳性和 100%的假阳性。

对角线周围的 ROC 曲线意味着模型不比随机模型好,这里就是这种情况。对于所有假阳性率值,完美的模型将与真阳性率为 1 的 ROC 曲线相关联。

现在让我们来看看与您之前训练的逻辑回归模型相对应的 ROC 曲线。你将需要来自模型的概率,你可以使用predict_proba()而不是predict得到:

array([[0.50649705, 0.49350295],
 [0.94461852, 0.05538148],
 [0.97427601, 0.02572399],
 …,
 [0.82742897, 0.17257103],
 [0.48688505, 0.51311495],
 [0.8809794 , 0.1190206 ]])

第一列是类 0 的分数,第二列是分数 1(因此,每行的总和是 1),所以您可以只保留第二列。

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

*图 logistic 模型对应的 ROC 曲线。(*图片作者 )

您可以在图 4 中看到,您的模型实际上比随机模型更好,这是您无法从模型精度中得知的(它们是等价的:随机模型大约为 0.86,而您的模型为 0.87)。

目视检查是好的,但是用一个单一的数字指标来比较你的模型也是至关重要的。这通常由 ROC 曲线下的面积提供。在接下来的章节中,你会看到曲线下的面积是多少,以及如何计算。

积分

积分是微分的逆运算。取一个函数 f(x)并计算它的导数 f’(x),f’(x)的不定积分(也称为反导数)返回 f(x)(直到一个常数,你很快就会看到)。

您可以使用积分来计算曲线下的面积,这是由函数界定的形状的面积,如图 5 所示。

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

*图 5:曲线下的区域。(*图片作者 )

定积分是特定区间上的积分。它对应于这个区间内曲线下的面积。

例子

通过这个例子你会看到如何理解函数的积分和曲线下面积的关系。为了说明这个过程,您将使用曲线下面积的离散化来近似函数 g(x) = 2x 的积分。

示例描述

让我们再以行驶中的火车为例。你看到速度是时间的函数,距离是时间的导数。这些功能如图 6 所示。

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

*图 6:左图显示 f(x ),它是距离与时间的函数,右图显示它的导数 g(x ),它是速度与时间的函数。(*图片作者 )

图 6 左图所示的函数定义为 f(x) = x。其导数定义为 g(x)=2x。

在这个例子中,你将学习如何找到 g(x)曲线下面积的近似值。

分割函数

要估算一个形状的面积,可以使用切片法:用简单的形状(如矩形)将形状切割成小切片,计算每个切片的面积,然后求和。

你要做的就是找到 g(x)曲线下面积的近似值。

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

*图 7:通过将速度曲线下的面积离散化为时间的函数,得到曲线下面积的近似值。(*图片作者 )

图 7 显示了 f’(x)的曲线下的区域,该区域被切成一秒钟的矩形(我们称之为差值δx)。请注意,我们低估了面积(查看丢失的三角形),但我们稍后会解决这个问题。

让我们试着理解切片的含义。拿第一个来说:它的面积被定义为 2 ⋅ 1。切片的高度是一秒钟的速度(值为 2)。所以第一个切片有两个单位的速度乘以一个单位的时间。面积相当于速度和时间的乘积:这是一个距离。

例如,如果你以每小时 50 英里的速度行驶了两个小时,你行驶了 50 ⋅ 2 = 100 英里的距离。这是因为速度的单位对应于距离和时间的比率(比如英里每小时)。你得到:(距离/时间)⋅时间=距离。

总结一下,距离对时间函数的导数就是速度对时间的函数,速度对时间函数的曲线下面积(它的积分)给你一个距离。这就是导数和积分的关系。

履行

让我们用切片来近似函数 g(x)=2x 的积分。首先,让我们定义函数 g(x):

如图 7 所示,您将认为该函数是离散的,并以δx = 1 为步长。您可以创建一个值从 0 到 6 的 x 轴,并对每个值应用函数g_2x()。您可以使用 Numpy 方法arange(start, stop, step)创建一个数组,用从startstop的值填充(不包括):

array([0, 1, 2, 3, 4, 5, 6])
array([ 0, 2, 4, 6, 8, 10, 12])

然后,您可以通过迭代并将宽度(δx)乘以高度(此时的 y 值)来计算切片的面积。切片的。正如您所看到的,这个区域(下面代码中的delta_x * y[i-1])对应于一个距离(移动的火车在第 I 个片段中行驶的距离)。最后,您可以将结果追加到一个数组中(下面代码中的slice_area_all)。

注意y的索引是i-1,因为矩形在我们估计的 x 值的左边。例如,对于 x=0 和 x=1,面积为零。

array([ 0., 0., 2., 4., 6., 8., 10.])

这些值是切片的面积。

要计算从起点到相应时间点(不对应每个切片)的距离,可以用 Numpy 函数cumsum()计算slice_area_all的累计和:

array([ 0., 0., 2., 6., 12., 20., 30.])

这是 g(x)的曲线下面积作为 x 的函数的估计值,我们知道函数 g(x)是 f(x)=x 的导数,所以我们要通过对 g(x)的积分把 f(x)取回来。

让我们画出我们的估计和 f(x),我们称之为“真实函数”,来比较它们:

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

*图 8:估算函数和原始函数的比较。(*图片作者 )

图 8 中表示的估计表明该估计并不差,但是可以改进。这是因为我们错过了图 9 中用红色表示的所有三角形。

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

图 9:速度函数切片中的缺失部分(红色)。δx 越小误差越小 ( 图片作者 )

让我们估计δx = 0.1 的积分函数:

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

*图 10:切片宽度越小,对原始函数的估计越好。(*图片作者 )

如图 10 所示,我们恢复了(至少,直到一个附加常数)我们对其导数进行积分的原始函数。

延长

在我们之前的例子中,您对函数 2x 进行了积分,这是一个线性函数,但是对于任何连续函数,原理都是相同的(例如,参见图 11)。

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

*图 11:切片方法可用于许多线性或非线性函数,包括所有连续函数。(*图片作者 )

黎曼和

使用这种切片方法近似积分被称为黎曼和。黎曼和可以用不同的方法计算,如图 12 所示。

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

*图 12:积分逼近的四种黎曼和。(*图片作者 )

如图 12 所示,使用左黎曼和,曲线与矩形的左角对齐。使用右黎曼和,曲线与矩形的右角对齐。使用中点规则,曲线与矩形的中心对齐。对于梯形法则,使用梯形形状而不是矩形。曲线穿过梯形的两个顶角。

数学定义

在上一节中,您看到了曲线下面积和积分之间的关系(您从导数中恢复了原始函数)。现在让我们看看积分的数学定义。

函数 f(x)关于 x 的积分表示如下:

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

符号 dx 被称为 x 的微分,指的是 x 的无穷小变化的想法,它是 x 中接近 0 的差。积分的主要思想是对无限个宽度无限小的切片求和。

符号∫是整数符号,表示无限个切片的总和。

每个切片的高度是值 f(x)。f(x)的乘法

因此 dx 是每个切片的面积。最后,∫ f(x) dx 是无限个切片的切片面积之和(切片的宽度趋于零)。这是曲线下的区域。

你在上一节看到了如何近似函数积分。但是如果你知道一个函数的导数,你就可以在知道它是逆运算的情况下检索积分。例如,如果您知道:

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

可以得出 2x 的积分是 x,但是,有一个问题。如果你给我们的函数加一个常数,导数是一样的,因为常数的导数是零。举个例子,

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

不可能知道常数的值。因此,您需要在表达式中添加一个未知常数,如下所示:

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

其中 c 是常数。

定积分

定积分的情况下,用整数符号上下的数字表示积分区间,如下所示:

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

它对应于 x=a 和 x=b 之间函数 f(x)曲线下的面积,如图 13 所示。

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

图 13:x = a 和 x=b 之间曲线下的面积 ( 图片作者 )

ROC 曲线下面积

现在你知道了曲线下的面积与积分的关系,让我们来看看如何计算它来比较你的模型。

请记住,您的 ROC 曲线如图 14 所示:

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

*图 14:随机模型(蓝色)和逻辑回归模型(绿色)的 ROC 曲线。(*图片作者 )

先说随机模型。您希望将每个真阳性率值乘以 x 轴上的宽度(即相应的假阳性率值与前一个值之差)进行求和。您可以通过以下方式获得这些差异:

array([0.00241546, 0.01207729, 0\. , …, 0.01207729, 0\. ,
 0.06038647])

所以随机模型的 ROC 曲线下的面积是:

0.5743302591128678

或者您可以简单地使用 Sklearn 的函数roc_auc_score(),将真实目标值和概率作为输入:

0.5743302591128678

ROC 曲线下 0.5 的面积对应于不比随机更好的模型,面积 1 对应于完美的预测。

现在,让我们将该值与您的模型的 ROC 曲线下的面积进行比较:

0.8752378861074513

这表明你的模型实际上并不差,你对葡萄酒质量的预测也不是随机的。

在机器学习中,你可以用几行代码来训练复杂的算法。然而,正如你在这里看到的,一点数学知识可以帮助你充分利用它,加快你的工作。它会让你在学科的各个方面更加轻松,甚至,例如,理解像 Sklearn 这样的机器学习库的文档。

原载于 2020 年 11 月 6 日https://hadrienj . github . io

这篇文章是我的书数据科学基础数学的样本!

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

在此获取图书!

帮助您开始学习计算机视觉的基本 OpenCV 函数

原文:https://towardsdatascience.com/essential-opencv-functions-to-get-you-started-into-computer-vision-743df932e60?source=collection_archive---------59-----------------------

计算机视觉

了解常见的 OpenCV 函数及其应用

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

作者图片

计算机视觉是人工智能的一个领域,它训练计算机解释和理解视觉世界。因此,许多项目涉及使用相机和视频中的图像,以及使用多种技术,如图像处理和深度学习模型。

OpenCV 是一个旨在解决常见计算机视觉问题的库,它在该领域非常受欢迎,非常适合在生产中学习和使用。这个库有多种语言的接口,包括 Python、Java 和 C++。

在整篇文章中,我们将介绍 OpenCV 中不同的(常见的)函数,它们的应用,以及如何开始使用每一个函数。尽管我将提供 Python 中的例子,但是对于不同的支持语言,概念和函数是相同的。

我们今天到底要学什么?

  • 读取、写入和显示图像
  • 更改色彩空间
  • 调整图像大小
  • 图像旋转
  • 边缘检测

读取、写入和显示图像

在我们可以用计算机视觉做任何事情之前,我们需要能够阅读和理解计算机是如何处理图像的。计算机唯一能处理的信息是二进制信息(0 和 1),包括文本、图像和视频。

计算机是如何处理图像的

为了理解计算机是如何“理解”一幅图像的,你可以画出一个图像大小的矩阵,在这个矩阵中,你在每个单元格上指定一个值,代表该位置图像的颜色。

让我们以灰度图像为例:

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

对于这种特殊情况,我们可以为图像中的每个块(或像素)分配一个数值(可以解释为二进制)。这个数值可以是任何范围的,尽管习惯上用 0 代表黑色,255 代表白色,中间的所有整数代表强度。

当我们处理彩色图像时,根据库和我们选择的表示颜色的方式,情况会有所不同。我们将在后面的文章中详细讨论,然而,它们都或多或少地分享相同的想法,即使用不同的通道来表示颜色,RGB(红色、绿色和蓝色)是最受欢迎的选项之一。对于 RGB,我们需要 3 个通道来构建每个像素,因此我们的 2d 矩阵现在是深度为 3 的 3d 矩阵,其中每个通道都是特定颜色的强度,当混合时,我们得到像素的最终颜色。

使用 OpenCV 处理图像

现在让我们进入代码来执行处理图像时最重要的三个功能,读取,显示,保存

import cv2
import matplotlib.pyplot as plt# Reading the image
image = cv2.imread('sample1.jpg')# Showing the image
plt.imshow(image)
plt.show()# Saving the image
cv2.imwrite('sample1_output.jpg', image)

如果您运行我们的代码,现在您将得到一个保存到磁盘的图像,以及另一个作为绘图结果的图像。

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

作者图片,来自 Berkay Gumustekin 在 Unsplash 发布的原始图片

左边的图像是我们绘制的,而右边的是保存到磁盘的图像。除了尺寸上的差异(由于剧情原因),左边的图像看起来很奇怪,看起来是蓝色的,但为什么会不同呢?(对了,右图没错)。

左边的图像看起来颜色奇怪的原因与 OpenCV 默认读取图像的方式有关。OpenCV imread()函数将使用 BGR 通道读取图像,假定为 RGB ,由绘图函数使用。这对于 OpenCV 来说是正常的,我们接下来会讨论修复它的方法。

更改色彩空间

什么是色彩空间?在我们之前的例子中,我们看到了计算机是如何处理图像的,我们看到,为了表示颜色,我们需要使用通道,当组合时,我们得到图像的最终颜色。设置这些通道的配置是色彩空间。不知不觉中,我们已经在之前的代码片段中涵盖了 2 种不同的色彩空间,我们使用了 RGBBGR ,但是还有更多具有非常特殊和有趣的属性。其他一些流行的颜色空间包括 LABYCrCb 、 **HLS、**和 HSV 。由于每个颜色空间都有自己的属性,一些算法或技术在一个空间中可能比其他空间中工作得更好,因此在这些颜色空间之间改变图像是很重要的,谢天谢地,OpenCV 为我们提供了一个非常容易使用的函数来实现这一目的。

满足 cvtColor ,让我们看看如何用它来修复我们上面的情节

import cv2
import matplotlib.pyplot as plt# Reading the image
image = cv2.imread('sample1.jpg')# Change color space
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)# Showing the image
plt.imshow(image)
plt.show()

我们现在有了一只漂亮的棕色狗:

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

让我们探索一些其他的色彩空间:

import cv2
import matplotlib.pyplot as plt# Reading the image
original = cv2.imread('sample1.jpg')fig = plt.figure(figsize=(8, 2))
axarr = fig.subplots(1, 3)# Change color space
image = cv2.cvtColor(original, cv2.COLOR_BGR2RGB)
axarr[0].imshow(image)image = cv2.cvtColor(original, cv2.COLOR_BGR2GRAY)
axarr[1].imshow(image)image = cv2.cvtColor(original, cv2.COLOR_BGR2LAB)
axarr[2].imshow(image) plt.show()

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

调整图像大小

既然我们能够加载、显示和更改图像的颜色空间,接下来我们需要关注的是调整大小。在计算机视觉中调整图像的大小很重要,因为 ML 中的学习模型使用固定大小的输入。大小将取决于模型,但为了确保我们的图像将在模型上工作,我们需要相应地调整它们的大小。

OpenCV 提供了一个名为 resize 的实用方法,让我们看一个如何使用它的例子。

import cv2# Reading the image
original = cv2.imread('sample1.jpg')# Resize
resized = cv2.resize(original, (200, 200))print(original.shape)
print(resized.shape)

哪些输出

(1100, 1650, 3)
(200, 200, 3)

图像旋转

训练模型的一个关键部分是我们将用来训练它的数据集。如果数据集没有足够的样本和分布良好的样本,训练好的模型很可能会失败。但有时我们没有足够大的数据集,或者我们没有我们想要训练模型的所有情况,所以我们运行改变图像的过程来生成新的图像。在很多情况下,将图像旋转到不同的角度可以帮助我们提高模型的效率,但我们不会在这里一一介绍。相反,我想向您展示如何使用 OpenCV 来旋转图像。

让我们看一个 OpenCV 中的旋转函数的例子

import cv2
import matplotlib.pyplot as plt# Reading the image
image = cv2.imread('sample1.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)image = cv2.rotate(image, cv2.ROTATE_90_CLOCKWISE)plt.imshow(image)
plt.show()

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

尽管这种方法非常容易使用,但它也限制了我们的选择,我们不能以任何角度旋转。为了更好地控制旋转,我们可以使用 getRotationMatrix2DwarpAffine 来代替。

import cv2
import matplotlib.pyplot as plt# Reading the image
image = cv2.imread('sample1.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)rows, cols = image.shape[:2]
deg = 45
# (col/2,rows/2) is the center of rotation for the image
# M is the coordinates of the center
M = cv2.getRotationMatrix2D((cols/2, rows/2), deg, 1)
image = cv2.warpAffine(image, M, (cols, rows))plt.imshow(image)
plt.show()

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

边缘检测

边缘是图像中图像亮度急剧变化或不连续的点。这种不连续性通常对应于:

  • 深度的不连续性
  • 表面方向的不连续性
  • 材料特性的变化
  • 场景照明的变化

边缘是图像的一个非常有用的特征,可以用作 ML 管道的一部分,我们已经看到了一些边缘如何帮助我们检测道路上的形状或线条的例子。

[## 使用 Hough 变换和 OpenCV & Python 理解和实现形状检测

用几行 Python 代码在图像中找到车道和眼睛

medium.com](https://medium.com/@bajcmartinez/understanding-implementing-shape-detection-using-hough-transform-with-opencv-python-cd04346115c0) [## 不用深度学习就能找到车道

今天我们将在一个项目中合作,使用 python 在图像和视频中寻找车道。对于该项目,我们…

medium.com](https://medium.com/@bajcmartinez/finding-lanes-without-deep-learning-5407053560cb)

CV2 为我们提供了这个任务的 Canny 函数,下面是它的使用方法:

import cv2
import matplotlib.pyplot as plt# Reading the image
original = cv2.imread('sample2.jpg')fig = plt.figure(figsize=(6, 2))
axarr = fig.subplots(1, 2)axarr[0].imshow(cv2.cvtColor(original, cv2.COLOR_BGR2RGB))threshold1 = 50
threshold2 = 200
grey = cv2.cvtColor(original, cv2.COLOR_BGR2GRAY)
image = cv2.Canny(original, threshold1, threshold2)
axarr[1].imshow(image, cmap='gray') plt.show()

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

摘要

OpenCV 是一个非常棒的处理图像和视频的库,它提供了大量有用的工具和函数,可以处理从最简单到更复杂的场景。我们今天讨论的函数只是图库中的几个。如果你有兴趣探索库文档,看看样本,有很多,从简单的图像处理,如转置,到更高级的功能,如轮廓检测,特征检测,甚至人脸检测。

我希望你喜欢阅读这篇文章,并且请加入到关于你最喜欢的 OpenCV 函数的讨论中来。

感谢阅读!

基本编程|控制结构

原文:https://towardsdatascience.com/essential-programming-control-structures-2e5e73285df4?source=collection_archive---------0-----------------------

节目的骨干

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

如果你想开始编程,我必须承认前景并不好:不同的操作系统,如此多的编程语言,以及达到相同结果的无尽方式。这些情况要么让你逃跑(尽可能快、尽可能远,希望你再也不会碰到编程),要么让你面对野兽。如果你决定面对它,那么你将不知道从哪里开始,或者如何处理它。你只会有问题,甚至可能没有一个答案,但你知道吗?这是一个很好的开始方式。实际上,我就是这样开始编程的。我相信,如果我想理解程序,我必须回答这个问题:

程序是如何工作的,你如何构建它们?

当然不是一个简单的问题,但是拜托,更难的问题已经有答案了,对吧?看一看马文·明斯基。被认为是人工智能之父之一的明斯基写了 【心灵的社会】 来回答我们这个时代最困难的问题之一:*什么是人类的心灵,它是如何工作的?*从一个革命性的角度来看,明斯基认为我们的思维是由小思维(或更基本的成分)的集合组成的,这些思维已经进化成执行高度特定的任务。根据他的说法,这些微小心灵中的大多数缺乏我们认为的智力属性,并且受到严重限制,只能通过与其他组件的相互作用来达到感觉,想法或有目的的行动。

这个想法包含了一个强有力的概念:复杂的事情可以被认为是一组简单的主题,也可以被分割成更基本的东西,直到你达到一个正确的理解。如果你这样想的话,任何有效的系统都可以被解释为一组更简单的功能,当这些功能组合在一起时,与它们各自的性能相比,可以达到更好的效果。

出于这个原因,如果我想理解计算机程序(并学习如何制作它们),我需要理解它们的构建模块。你看,当一个程序运行时,代码被计算机逐行(从上到下,从左到右)读取,就像你读一本书一样。在某个时候,程序可能会遇到需要做出决定的情况,例如跳转到程序的不同部分或再次运行某个片段。这些影响程序代码流程的决策被称为控制结构。

控制结构可以被认为是计算机程序的构建模块。它们是使程序能够“做出决定”的命令,遵循这样或那样的路径。一个程序通常不局限于线性的指令序列,因为在它的处理过程中,它可能会分叉、重复代码或绕过某些部分。控制结构是分析变量并根据给定的参数选择前进方向的模块。

编程语言中的基本控制结构是:

  • 条件句(或选择):,用于在满足条件的情况下执行一条或多条语句。
  • **循环(或迭代)😗*其目的是将一个语句重复一定的次数或在满足一个条件的时候。

现在,让我们来看看这些概念中的每一个。下面我们将深入使用 R 编程语言(数据科学中最常用的语言之一),但是同样的思想和解释适用于任何其他编程语言。

条件式

“条件”是编程的核心。它们背后的思想是,它们允许你控制基于程序中不同条件执行的代码流(例如,来自用户的输入,或者运行程序的机器的内部状态)。在本文中,我们将探讨**“If 语句”“If-Else 语句”**的条件控制结构。

1) If 语句

“If 语句”在满足条件时执行一条或多条语句。如果该条件的测试为真,则执行该语句。但是如果它是假的(条件不满足),那么什么都不会发生。让我们想象一下:

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

如果语句

“If 语句”的语法是:

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

示例

举个简单的例子,假设您想要验证变量(x)的值是否为正:

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

在本例中,首先我们将值 4 赋给变量(x ),并使用“If 语句”来验证该值是否等于或大于 0。如果测试结果为真(如本例),该函数将打印句子:“变量 x 是一个正数”

输出

[1] "variable x is a positive number"

但是由于“If 语句”只在测试条件为真时执行语句,如果变量值为负会发生什么呢?要在测试条件下执行一个结果为假的语句,我们需要使用“If-Else 语句”。

2) If-Else 语句

这种控制结构允许程序遵循可选的执行路径,无论条件是否满足。

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

If-Else 语句

“If-Else 语句”的语法是:

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

指令的“else 部分”是可选的,仅当条件测试为假时才进行评估。

例 1

按照我们的示例,我们通过添加“else 部分”来扩展前面的条件“If 语句”,以测试变量的值是正还是负,并在测试结果为真还是假时执行操作。

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

在本例中,我们将值-4 赋给变量(x ),并使用“If 语句”来验证该值是否等于或大于 0。如果测试结果为真,函数将打印句子:“变量 x 是一个正数”。但是在测试结果为假的情况下(就像在这种情况下),函数继续执行替代表达式并打印句子:“变量 x 是负数”

输出

[1] "variable x is a negative number"

例 2

比方说,你需要定义两个以上的条件,就像给考试评分一样。在这种情况下,你可以评分 A,B,C,D 或 F (5 个选项),那么,你会怎么做呢?

“If-Else 语句”可以有多个可选语句。在下面的例子中,我们定义了一个初始分数,以及一个包含 5 个评级类别的“If-Else 语句”。这段代码将遍历每一个条件,直到得到一个真实的测试结果。

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

输出

[1] “C”

“循环语句”只不过是通过组织动作序列和对需要重复的部分进行分组来实现多步骤过程的自动化。作为编程的核心部分,迭代(或循环)赋予了计算机强大的能力。他们可以根据需要经常重复一系列步骤,简单步骤的适当重复可以解决复杂的问题。

一般来说,有两种类型的“循环技术”:

  1. **“For Loops”😗*是在计数器或索引的控制下,执行规定次数的程序。
  2. **“While 循环”“重复循环”😗*基于逻辑条件的开始和验证。在循环构造的开始或结束时测试条件。

让我们来看看它们:

1)对于循环

在这种控制结构中,语句以连续的顺序在一系列值上一个接一个地执行,这些值只有在“For 循环”启动时才被求值(从不重新求值)。在这种情况下,迭代次数是固定的,并且是预先知道的。

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

For 循环

如果对变量(可以采用指定序列中的值)的条件评估结果为真,将对该值字符串顺序执行一个或多个语句。一旦第一个条件测试完成(结果为真),就执行语句并再次评估条件,经历一个迭代过程。“序列中的变量”部分对序列中的每个值执行这个测试,直到它覆盖了最后一个元素。

如果不满足条件,并且结果为假(例如,“序列中的变量”部分已经完成了序列的所有元素),则循环结束。如果条件测试在第一次迭代中的结果为假,则“For 循环”永远不会执行。

“For 循环”的语法是:

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

例 1

为了展示“For 循环”是如何工作的,首先我们将创建一个序列,通过连接不同的水果名称来创建一个列表(称为“fruit_list”):

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

我们将使用这个水果列表作为“For 循环”中的“序列”,并让“For 循环”为序列中提供的每个值(水果列表中的不同水果)运行一次语句(打印每个值的名称):

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

这样,“For 循环”的结果如下:

## [1] "Apple"
## [1] "Kiwi"
## [1] "Orange"
## [1] "Banana"

好了,我们打印了列表中每个值的名字。没什么大不了的,对吧?好的一面是“For 循环”可以用来产生更有趣的结果。看看下面的例子。

例二

如果我们想修改值,或者按顺序执行计算,该怎么办?您可以使用“For Loops”对向量的每个值(相同类型的元素,在本例中为数字元素)依次执行数学运算。

在本例中,我们将创建一个数字序列(从 1 到 10),并设置一个“For 循环”来计算和打印该序列中每个值的平方根:

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

在这种情况下,“For 循环”的结果是:

[1] 1
[1] 1.414214
[1] 1.732051
[1] 2
[1] 2.236068
[1] 2.449490
[1] 2.645751
[1] 2.828427
[1] 3
[1] 3.162278

您可以在一个数字序列上使用任何类型的数学运算符,正如我们将在本文后面看到的,在不同的控制结构之间进行各种组合,以获得更复杂的结果。

2) While 循环

在“While Loops”中,首先评估一个条件,如果测试该条件的结果为真,则重复执行一个或多个语句,直到该条件变为假。

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

While 循环

与“If 语句”不同,在“If 语句”中,测试为真的条件只执行一次表达式就结束了,“While 循环”是反复执行某个表达式直到条件变为假的迭代语句。如果条件永远不会为假,那么“While 循环”将永远继续下去,程序将会崩溃。反之,如果循环开始时条件测试结果为假,表达式将永远不会执行。

“While 循环”的语法是:

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

例 1

让我们看一个例子。首先,我们将创建一个变量(x ),并给它赋值 1。然后,我们设置一个“While 循环”来迭代测试该变量上的条件,直到条件测试结果为假:

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

它是这样工作的:变量(x)的初始值是 1,所以当我们测试条件“变量(x)小于 10 吗?”,结果计算为 TRUE,执行表达式,打印变量(x)的结果,在第一种情况下是 1。但随后发生了一些事情:变量(x)在函数结束前增加 1,在下一次迭代中,x 的值将为 2。

这种变量的重新分配是很重要的,因为它最终会达到假条件,循环退出(x = 10)。未能改变“While 循环”中的初始条件将导致无限循环和程序崩溃。

输出

[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9

例二

你听说过斐波那契数列吗?这是一系列数字,其特点是序列中的下一个数字是通过将它前面的两个数字相加得到的:0、1、1、2、3、5、8、13、21……这个序列可以在几个自然现象中找到,在金融音乐建筑等学科中有不同的应用。

让我们使用“While 循环”来计算它。

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

在这种情况下,我们将序列中的最大值设置为停止条件,这样循环只打印小于 100 的斐波纳契数列。当一个序列元素(不管它是什么)变得大于 100 时,循环周期结束。

[1] 0
[1] 1
[1] 1
[1] 2
[1] 3
[1] 5
[1] 8
[1] 13
[1] 21
[1] 34
[1] 55
[1] 89

例 3

用“While 循环”生成斐波纳契数列的另一种方法是,不将数列的最大值设置为停止条件,而是设置您想要生成的数列元素的数量**。**

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

这个“While 循环”将序列中的下一个元素追加到前一个元素的末尾,直到达到停止条件。在这种情况下,当序列达到 10 个元素时(无论是哪个值),循环结束。

输出

[1] 0 1 1 2 3 5 8 13 21 34

3)重复循环

与“While Loops”紧密相连,“Repeat Loops”迭代执行语句,但直到满足停止条件。这样,不管条件的结果是什么,语句都至少执行一次,并且只有当某个条件为真时才退出循环:

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

重复循环

“重复循环”的语法是:

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

“重复循环”使用“中断语句”作为停止条件。“中断语句”与中断循环内循环的条件测试相结合,因为当程序遇到中断时,它会在循环结束后立即将控制传递给指令(如果有)。

如果不满足中断条件,“重复循环”将永远运行。请看这两个例子

例 1

首先我们创建一个变量(x)并给它赋值 5。然后,我们设置一个“重复循环”来迭代地打印变量的值,修改变量的值(增加 1),并在该变量上测试一个条件(如果它等于 10),直到条件测试结果为真。

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

当变量(x)达到 10 时,触发“中断条件”,循环结束。

输出

[1] 5
[1] 6
[1] 7
[1] 8
[1] 9

例二

现在让我们假设我们产生一个随机数列表,我们不知道它的生成顺序。

在这个例子中,我们将使用一个“重复循环”来生成一个正态分布的随机数序列(您可以使用任何其他分布来生成 random,我们只选择这一个),并在其中一个数大于 1 时破坏该序列。因为我们不知道哪些数字会先出现,所以我们不知道序列会有多长:我们只知道破缺条件。

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

首先,我们使用“set.seed”指令来固定随机数(总是生成相同的随机数),并使这个例子可再现。

然后,我们通过生成一个正态分布的随机数,打印它,并检查该数是否大于 1 来启动“重复循环”。只有当这个条件为真时(可能是第一个生成的数字,也可能不是),循环才会传递到 break 语句并结束。

输出

[1] -0.9619334
[1] -0.2925257
[1] 0.2587882
[1] -1.152132
[1] 0.1957828
[1] 0.03012394
[1] 0.08541773
[1] 1.11661

这再一次表明了设定一个合适的破裂条件的重要性。否则将导致无限循环。

最后的想法

我们已经看到并解释了孤立的概念,但是“控制结构”可以按照你想要的任何方式组合:循环可能包含几个内部循环;条件句可能包含循环和条件句,选项是无穷无尽的。(事实上,在回顾“重复循环”时,我们发现示例中包含嵌套的“If 语句”)。

您可以通过组合我们在本文中解释的“控制结构”来开发高级解决方案。正如明斯基所说,我们可以通过简单成分的相互作用达到复杂的结果。控制结构构成了计算中决策过程的基本模块。它们改变了程序的流程,使我们能够从简单的构件中构造出复杂的指令集。

我的建议是: 了解一下他们

它会让你更容易编码和理解程序,并帮助你找到解决问题的新方法。

对这些话题感兴趣?在 LinkedinTwitter 上关注我

基本编程|排序算法

原文:https://towardsdatascience.com/essential-programming-sorting-algorithms-76099c6c4fb5?source=collection_archive---------13-----------------------

基本编程工具指南

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

埃菲社在 Unsplash 上拍摄的照片

你日历中的下一个任务,你最喜欢的运动队在联盟中的排名位置,你手机中的联系人列表,所有这些都是有顺序的。当我们处理信息时,顺序很重要。我们用秩序来理解我们的生活,优化我们的决定。想象一下,在一个混合字母顺序的字典中查找一个单词,或者试图在一个无序的定价列表中找到最便宜的产品。我们订购东西是为了做出更合理的决定(这实际上是一种错觉),这让我们对结果更有信心。

但有一个问题:这个世界是混乱的,是天生无序的(至少从我们人类的感知来看)。今天的数据又乱又多,真是糟糕的组合。我们怎样才能以一种对我们有意义的方式来整理这个海量的信息漩涡?这就是计算机排序算法发挥关键作用的地方。

排序算法的世界

简单来说,算法就是解决问题的一步一步的方法。算法的基础是接受一个输入并执行一系列特定的动作以达到一个结果。它们被广泛应用于计算机编程、数学,甚至我们的日常生活中(例如,一个烹饪食谱就是一个算法)。

算法远在计算机发明之前就存在了,但是自从现代技术的爆炸以来,计算机算法已经扩展并到处复制。现在,从计算机算法的巨大宇宙中,我认为排序算法值得一个特殊的章节。

排序算法是计算机科学的基础。它们将无序的数据转化为按照某种标准排序的数据,例如字母顺序、最高到最低值或最短到最长距离。

它们基本上以项目列表作为输入,对这些列表执行特定的操作,并以有序的方式交付这些项目作为输出。排序算法的许多应用包括在零售网站上按价格组织商品,以及确定网站在搜索引擎结果页面上的顺序

有许多不同的排序算法,但它们有一个共同点,那就是可视化后更容易理解。在下面的例子中,我们取一个无序列表,用 5 种不同的算法进行排序:选择排序插入排序冒泡排序合并排序快速排序。让我们来看看。

选择排序

选择排序算法基于这样的思想:在未排序的列表中找到最小或最大元素,然后以排序的方式将其放在正确的位置。在升序排序的情况下,最小的元素将在第一个,在降序排序的情况下,最大的元素将在开始。

因此,当按升序排序时,选择排序的工作方式是反复从列表的未排序部分中找到最小元素,并将其放在开头。在每次迭代中,从列表的未排序部分选取最小元素,并将其移动到列表的排序部分。为了做到这一点,该算法在进行传递时寻找最小值(在升序的情况下),并在完成传递后,将其放置在适当的位置。

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

选择排序算法(升序)

看上面的例子。需要升序排序的列表分为两部分,左端排序的部分和右端未排序的部分。最初,已排序的部分是空的,未排序的部分是整个列表。从未排序列表中选择最小的元素(本例中为 2)(用洋红色标记),并与最左边的元素交换,该元素成为排序数组的一部分(现在为橙色)。这个过程通过将未排序的元素从未排序的列表一个接一个地移动到已排序的列表来继续,直到没有元素剩下为止。

选择排序非常直观,但由于它需要扫描整个列表来查找下一个小值,所以在处理大量数据时会非常慢。

插入排序

你在游戏中整理过扑克牌吗?如果答案是肯定的,那么这就是插入排序。

与选择排序类似,插入排序将元素分为排序列表和未排序列表。在该算法中,按顺序搜索元素,将未排序的项目移动并插入到排序列表中,直到覆盖所有未排序的值。

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

插入排序算法(升序)

在我们的示例中,从左边开始,算法将第一个元素(29)标记为已排序。然后,它选取位于未排序列表中的第二个元素(10),并将其与位于排序列表中的前一个元素进行比较。因为 10 小于 29,所以它将较高的元素向右移动,并将较小的元素插入第一个位置。现在,元素 10 和 29 表示排序后的列表。该算法通过从右侧的未排序列表中提取元素并将其与左侧的排序列表中的元素进行比较来顺序执行这一练习,以确定将它们插入到哪个位置。

插入排序是自适应的,这意味着如果提供部分排序的数组作为输入,它会减少总的步骤数,从而提高效率。像选择排序一样,插入排序不适合大数据量,因为它不适合其他排序算法。

冒泡排序

冒泡排序基于这样一种思想,即反复比较相邻元素对,然后如果它们以错误的顺序存在,就交换它们的位置。

如果一个元素列表必须按升序排序,那么冒泡排序将从比较列表的第一个元素和第二个元素开始。如果第一个元素大于第二个元素,它将交换两个元素,并继续比较第二个和第三个元素,依此类推。

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

冒泡排序算法(升序)

在我们的例子中,算法从比较第一个元素(29)和第二个元素(10)开始。因为 29 比 10 大,所以它交换它们并将 29 作为列表中的第二个元素。然后,它对第二个元素(29)和第三个元素(14)执行相同的操作,并对所有列表元素重复该操作。因此,在第一遍中,列表中最高的元素(41)将被放置在列表的末尾(右侧)。该算法将多次遍历所有元素,直到它们都被排序,“冒泡”每个元素到它所属的位置。

冒泡排序通常被认为是一种低效的排序工具,因为它必须在知道元素的最终位置之前交换项目。然而,如果在一次传递中没有交换,那么我们知道列表必须被排序。如果冒泡排序发现一个列表已经被排序,它可以被修改为提前停止,这为它提供了识别排序列表的能力。

合并排序

合并排序是一种非常有效的算法,它将元素列表分成相等的两半,然后以排序的方式组合它们。

该算法从重复地将一个列表分解成几个子列表开始,直到每个子列表由一个元素组成并且不能再被分割(创建一个元素的分区)。每个子列表的第一个元素在它们之间进行比较,并且如果以升序排序,则两者中较小的元素成为新的合并排序列表的新元素。重复该过程,直到所有子列表都为空,并且一个新合并的列表覆盖了所有子列表的所有元素,从而得到一个排序列表。

这里的秘密是一个只有一个元素的列表已经被排序了,所以一旦我们把原始列表分解成只有一个元素的子列表,我们就成功地把问题分解成了基本问题。这种方法被称为**【分而治之】**,其基本思想是将一个单一的大问题分解成更小的子问题,解决更小的子问题,并组合它们的解决方案,以找到原始大问题的解决方案。

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

合并排序算法(升序)

在我们的例子中,算法首先将元素列表分成 1 个分区。然后,它合并第一个(29)和第二个(10)元素,对它们进行排序(在本例中是按升序),并将它们放回列表中。然后,它合并第一个(现在是 10 个)、第二个(现在是 29 个)和第三个(14 个)元素,对它们进行排序,并将它们放回列表中。它对所有子列表执行这个过程,合并子结果,直到得到一个唯一的排序列表。

由于合并排序将输入分成多个块,因此可以同时并行地对每个块进行排序,从而产生极快的结果。

快速排序

快速排序是最有效的排序算法之一,它基于将数据集划分为子组,然后再将子组递归划分为更小的组,以优化排序过程。该算法的工作原理是在数据集中找到一个**“pivot element”**,并将其作为排序的基础。

快速排序还使用了**“分而治之”的方法来划分和组织 pivot 周围的元素,这样:pivot 的左侧包含所有小于 pivot 元素的元素,右侧包含所有大于 pivot 的元素(这称为“分区”**)。这样,pivot 值从将整个元素分成两部分开始,通过为每个子部分找到一个 pivot 递归工作,直到所有部分只包含一个元素。

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

快速排序算法

在上面的例子中,未排序分区的第一个元素被选作 pivot 元素(用黄色突出显示)。比它小的元素用绿色标记并排序在左边,比它大的元素用紫色突出显示并排序在右边。

我们来看看顺序。开始时,选择 29(左边的第一个元素)作为支点。当枢轴被放置在适当的位置时,所有比它小的元素被放置在左边(一个子组),比它高的元素被放置在右边(另一个子组)。然后选取 5(左侧未排序列表的第一个元素)作为新的 pivot 元素,整个过程不断迭代,直到这一侧排序完毕。

一旦左侧组被排序,算法就移动到右侧未排序的组,并挑选 41(左侧的第一个元素)作为中枢,并在这一侧执行相同的过程,直到整个数据集从最低到最高排序。

在快速排序中,可以选择数据集中的任何元素作为轴心:第一个元素、最后一个元素或任何其他随机元素。那么最好的办法是什么呢?和往常一样,没有一个直接的解决方案,这取决于你试图解决的问题。您可以:

  1. 总是选择第一个元素作为轴心
  2. 总是选择最后一个元素作为轴心
  3. 选择一个随机元素作为轴心
  4. 选择中线作为轴心

如果分区后产生的子划分是不平衡的(也就是说,在轴心的一侧得到的元素很少,而在另一侧得到的元素很多),那么快速排序将需要更多的时间来完成。为了避免这种情况,您可以选择随机枢纽元素并分散获得不平衡分区的风险。

选哪个?

自然,计算机科学家不断发明额外的排序算法,它们各有利弊,所以要谨慎选择你的排序算法。选择正确的排序算法,你的程序就能快速运行。选择错误的排序算法,你的程序对用户来说可能会慢得让人无法忍受。一般来说,插入排序最适合小列表,冒泡排序最适合已经排序的列表,快速排序通常是日常使用中最快的。

你明白了:一些算法在管理相对少量的项目时速度很快,但是如果你强迫它们管理大量的项目,速度就会很慢。另一方面,其他算法在对最初几乎正确排序的项目进行排序时非常快速和有效,但如果对列表中随机分散的项目进行排序时则非常慢。

但是如果你能从每一个中取其精华呢?混合算法是我们要走的路。

混合算法结合了解决同一问题的两种或多种其他算法,或者选择一种,或者在处理过程中在它们之间切换。

这样做是为了组合每个组件的所需功能,以便整体性能优于单个组件的性能。例如 Tim Sort 是一种混合排序算法,源自合并排序和插入排序,旨在实现真实世界数据的高性能。该算法查找已经排序的数据的子序列(称为“自然运行”),并使用它们更有效地对剩余部分进行排序。

对这些话题感兴趣?在 Linkedin或 Twitter 上关注我

基本编程|时间复杂性

原文:https://towardsdatascience.com/essential-programming-time-complexity-a95bb2608cac?source=collection_archive---------1-----------------------

如何衡量算法的效率

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

Icons8 团队Unsplash 上的照片

在计算机编程中,就像在生活的其他方面一样,解决一个问题有不同的方法。这些不同的方法可能意味着不同的时间、计算能力或您选择的任何其他指标,因此我们需要比较不同方法的效率,以选择正确的方法。

现在,你可能知道,计算机能够根据算法解决问题。

算法是告诉计算机做什么和如何做的程序或指令(一组步骤)

如今,它们进化得如此之快,以至于即使完成同样的任务,它们也可能有很大的不同。在最极端的情况下(顺便说一下,这很常见),用不同编程语言编写的不同算法可能会告诉不同硬件和操作系统的不同计算机以完全不同的方式执行相同的任务。太疯狂了,不是吗?

事情是这样的,一种算法需要几秒钟才能完成,而另一种算法即使是很小的数据集也需要几分钟。我们如何比较不同的性能并选择最佳算法来解决特定的问题?

幸运的是,有很多方法可以做到这一点,我们不需要等到算法工作时才知道它是否能快速完成工作,或者它是否会在输入的压力下崩溃。当我们考虑一个算法的复杂性时,我们不应该真的关心所执行的操作的确切数量;相反,我们应该关心运算的数量如何与问题大小相关。想一想:如果问题规模翻倍,运算次数保持不变吗?他们会加倍吗?它们会以其他方式增加吗?为了回答这些问题,我们需要测量算法的时间复杂度。

时间复杂度代表一条语句被执行的次数。算法的时间复杂度不是执行特定代码所需的实际时间,因为它取决于其他因素,如编程语言、操作软件、处理能力等。时间复杂性背后的思想是,它只能以一种仅依赖于算法本身及其输入的方式来度量算法的执行时间。

为了表达算法的时间复杂度,我们使用了一种叫做*“大 O 符号”*的东西。**大 O 符号是我们用来描述算法时间复杂度的语言。**这是我们比较解决问题的不同方法的效率的方式,有助于我们做出决策。

大 O 符号根据算法相对于输入(该输入称为“n”)的增长速度来表示算法的运行时间。这样,举例来说,如果我们说一个算法的运行时间“按照输入大小的数量级”增长,我们可以用“O(n)”来表示。如果我们说一个算法的运行时间“与输入大小的平方成正比”,我们可以用“O(n)”来表示。但是这到底是什么意思呢?

理解时间复杂性的关键是理解事物增长的速率。这里讨论的速率是每个输入大小所用的时间。有不同类型的时间复杂性,所以让我们检查最基本的。

恒定时间复杂度:O(1)

当时间复杂度恒定时(记为“O(1)”),输入(n)的大小无关紧要。时间复杂度恒定的算法运行时间恒定,与 n 的大小无关。它们不会根据输入数据改变运行时间,这使它们成为最快的算法。

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

恒定时间复杂度

例如,如果您想知道一个数字是奇数还是偶数,您可以使用具有恒定时间复杂度的算法。不管这个数字是 1 亿还是 90 亿(输入“n”),算法都只会执行一次相同的操作,然后给你结果。

此外,如果您想一次性打印出一个短语,如经典的“Hello World ”,那么您也应该以恒定的时间复杂度运行,因为无论您使用哪种操作系统或哪种机器配置,这个短语或任何其他短语的操作量(在本例中为 1)都将保持不变。

为了保持恒定,这些算法不应该包含循环、递归或对任何其他非恒定时间函数的调用。对于常数时间算法,运行时间不会增加:数量级始终为 1。

线性时间复杂度:O(n)

当时间复杂度与输入的大小成正比时,您将面临线性时间复杂度,即 O(n)。具有这种时间复杂度的算法将在“n”次运算中处理输入(n)。这意味着随着输入的增加,算法完成的时间也相应增加。

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

线性时间复杂度

在这种情况下,您必须查看列表中的每一项才能完成任务(例如,找到最大值或最小值)。或者你也可以思考一些日常任务,比如读一本书或者找一张 CD(还记得吗?)在 CD 堆栈中:如果必须检查所有数据,输入大小越大,操作次数就越多。

线性运行时间算法非常常见,它们与算法从输入中访问每个元素的事实有关。

对数时间复杂度:O(log n)

具有这种复杂性的算法使得计算速度惊人。如果一个算法的执行时间与输入大小的对数成正比,则称该算法在对数时间内运行。这意味着不是增加执行每个后续步骤的时间,而是以与输入“n”成反比的幅度减少时间。

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

对数时间复杂度

它的秘密是什么?这些类型的算法从来不需要检查所有的输入,因为它们通常在每一步都丢弃大量未经检查的输入。这个时间复杂度一般与每次将问题分成两半的算法有关,这是一个被称为“分而治之”的概念。分治算法使用以下步骤解决问题:

1.他们将给定的问题分成相同类型的子问题。
2。他们递归地解决这些子问题。
3。他们恰当地组合子答案来回答给定的问题。

考虑这个例子:假设你想在一个所有单词都按字母顺序排序的字典中查找一个单词。至少有两种算法可以做到这一点:

算法 A:

  • 从书的开头开始,按顺序进行,直到找到您要查找的联系人。

算法 B:

  • 从中间打开书,检查上面的第一个单词。
  • 如果你要找的单词按字母顺序排列比较大,那么它会出现在右半部分。否则,它看起来在左半部。

两者哪一个更快?算法 A 一个字一个字地进行 O(n),而算法 B 在每次迭代 O(log n)时将问题分成两半,以更有效的方式获得相同的结果。

对数时间算法(O(log n))是仅次于常数时间算法(O(1))的最快算法。

二次时间复杂度:O(n)

在这种类型的算法中,运行时间与输入大小的平方成正比(类似于线性,但为平方)。

在大多数情况下,特别是对于大型数据集,具有二次时间复杂度的算法需要大量时间来执行,应该避免使用。

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

二次时间复杂度

嵌套的 For 循环在二次时间上运行,因为您正在另一个线性操作中运行一个线性操作,或者 nn* 等于 n .

如果你面对这些类型的算法,你要么需要大量的资源和时间,要么你需要想出一个更好的算法。

指数时间复杂度:O(2^n)

在指数时间算法中,输入(n)每增加一次,增长率就增加一倍,通常会遍历输入元素的所有子集。每当一个输入单位增加 1,就会导致您执行的操作数量加倍。这听起来不太妙,对吧?

具有这种时间复杂度的算法通常用在你对最佳解决方案了解不多的情况下,你必须对数据尝试每一种可能的组合或排列。

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

指数时间复杂度

指数时间复杂度通常见于蛮力算法。这些算法盲目地迭代整个可能解的域,以搜索一个或多个满足条件的解。他们试图通过尝试每一种可能的解决方案来找到正确的解决方案,直到碰巧找到正确的方案。这显然不是执行任务的最佳方式,因为它会影响时间复杂度。在密码术中,暴力算法被用作攻击方法,通过尝试随机字符串直到找到解锁系统的正确密码来破解密码保护。

与二次时间复杂度一样,您应该避免运行时间为指数的算法,因为它们不能很好地伸缩。

如何度量时间复杂度?

一般来说,我们已经看到算法的运算越少,速度就越快。这看起来是一个很好的原则,但我们如何将它应用到现实中呢?

如果我们有一个算法(不管它是什么),我们如何知道它的时间复杂度?

在某些情况下,这可能相对容易。假设您有一个循环的外部**,它遍历输入列表中的所有项,然后有一个嵌套的循环的内部,它再次遍历输入列表中的所有项。执行的总步骤数是 n * n,其中 n 是输入数组中的项数。**

但是怎么求复杂函数的时间复杂度呢?

为了找到答案,我们需要将算法代码分解成几个部分,并尝试找出各个部分的复杂性。是的,很抱歉告诉你,但是没有一个按钮可以告诉你一个算法的时间复杂度。你必须自己去做。

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

主要时间复杂性

**作为一条经验法则,最好是尝试让你的函数运行在线性时间复杂度之下或之内,**但显然这并不总是可能的。

有不同的大 O 符号,像*【最佳情况】一般情况】【最坏情况】*,但真正重要的是最坏情况**;这些会严重破坏一切。它们直击为什么时间复杂性很重要的核心,并指出为什么一些算法不花几十亿年就不能解决一个问题。

最坏情况分析给出了算法执行期间必须执行的基本操作的最大数量。它假设输入处于最糟糕的状态,必须做最大的努力来纠正错误。例如,对于旨在以升序对数组进行排序的排序算法,当输入数组以降序排序时,会出现最坏的情况。在这种情况下,必须执行最大数量的基本操作(比较和赋值)来以升序设置数组。请这样想:如果您必须在目录中通过阅读每个名字来搜索一个名字,直到找到正确的名字,最坏的情况是您想要的名字是目录中的最后一个条目。

综上所述,**一个算法的时间复杂度越好,算法在实际中执行工作的速度就越快。**你在设计或管理算法的时候应该考虑到这一点,考虑到这对于一个算法是实用还是完全无用有很大的影响。

对这些话题感兴趣?在 LinkedinTwitter 上关注我

任何认真的程序员都需要知道的基本 Python 概念和结构,解释

原文:https://towardsdatascience.com/essential-python-concepts-any-serious-programmer-needs-to-know-explained-429aad86b92e?source=collection_archive---------14-----------------------

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

来源: Pixabay

生成器、面向对象编程、闭包、装饰器等等

本文将概述一些重要的 Python 概念,任何认真的程序员都应该知道并理解这些概念才能实现。这些概念形成了高级 Python 编程的框架,以智能地处理和实现问题。

发电机

用 Python 构建一个迭代器,一个可以迭代的对象,需要做大量的工作。一个类(面向对象的编程)必须用一个__iter__()__next__()方法构建,内部状态必须被存储和更新,当没有值要返回时,必须产生一个StopIteration错误。

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

Python 中的迭代。作者创建的图像。

为了避免这个冗长的过程,Python 生成可以自动创建迭代器。上面描述的创建迭代器的所有过程都是由 Python 和生成器自动完成的。生成器是一个函数,它返回一个可以迭代的对象(迭代器)(一次覆盖一个值)。

生成器函数被定义为一个函数,但是使用了关键字yield而不是传统的return。如果函数体包含yield,那么它将自动成为一个生成器函数。

def simple_generator():
     yield 1
     yield 2
     yield 3for value in simple_generator():
     print(value)

前四行代码定义了生成器,它将迭代返回123。最后两行通过迭代打印输出值来演示迭代,输出:

1
2
3

一个生成器对象仍然需要一个函数来描述对象,但是需要设置为等于一个变量,在本例中为x

x = simple_generator()
print(next(x))
print(next(x))
print(next(x))

例如,下面的代码创建一个斐波那契数列生成器,其中每一项都是前面两项(0、1、1、2、3、5、8、13、…)的和。

def fibonacci(limit):
     a, b = 0, 1

     while a < limit:
          yield a
          a, b = b, a+b

用于跟踪序列的两个数字是ab,它们分别被初始化为 0 和 1。当a低于限值(函数中指定为参数的数字)时,程序产生(返回)a 的值。然后,ab同时更新,其中a设置为b,而b设置为自身加上a。这将序列 1 向右移动,同时保留用于生成下一个序列值(前两个数字)的相关信息。

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

斐波那契序列发生器逻辑。作者创建的图像。

然后可以迭代生成器,在这种情况下使用 for 循环:

for i in fibonacci(8):
     print(i)

因此,输出将遍历 Fibonacci 序列中值为 8 的所有元素:

0
1
1
2
3
5

面向对象编程

面向对象编程是 Python 的一个特性,它允许对方法和变量进行干净和有组织的存储。Python 中的面向对象编程(OOP)由class对象组成,其中包含关于该对象的信息。

例如,假设我们想用 Python 创建一只虚拟狗。一个类的个人属性存储在一个__init__函数中。必须包括self参数,以及创建时需要定义的该对象的任何其他属性,例如狗的speciesage

class dog:
     def __init__(self, species, age):
          self.species = species
          self.age = age

可以用.class对象内部调用对象的变量和函数,前面的元素引用对象,句号后面的项目引用被调用的对象。self.species = species将内部变量设置为输入参数species的值。

我们还可以在类中创建函数:

class dog:
     def __init__(self, species, age):
          self.species = species
          self.age = age def bark(self, call='Woof!'):
          print(call) def reveal_information(self):
          print('I am a', self.species)
          print('I am', self.age, 'years old')

这两个内部函数barkreveal_information是由类执行和附加的方法。然后,我们可以为 dog 类设置一个变量pepper。我们必须指定初始化参数,speciesage

pepper = dog(species='German Shepard', age=3)

然后,我们可以调用pepper的属性:

pepper.reveal_information()

这将输出:

I am a German Shepard
I am 3 years old

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

面向对象的可视化类。作者创建的图像。

Python 中的面向对象编程适用于许多目的。尽管它可能需要更多的输入来设置,但它允许更多的可读代码。

关闭

闭包可以避免使用全局值,并提供了一种数据隐藏形式,为问题提供了一种面向对象的解决方案。当一个类中要实现的方法很少时,闭包可以提供一种替代的、更优雅的解决方案。当属性和方法的数量增加时,一个类就更合适了。以下标准演示了当嵌套函数引用其封闭范围内的值时 Python 中的闭包:

  • 存在嵌套函数(函数中的函数)
  • 嵌套函数引用封闭函数中声明的值
  • 封闭函数返回嵌套函数

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

闭合图。作者创建的图像。

让我们用一个示例函数make_multiplier来演示闭包,它接受一个参数*n*并返回一个带有该参数的函数。

def make_multiplier(n):
    def multiplier(x):
        return x * n
    return multiplier

创建一个将某物乘以 3 的函数的过程如下:

times3 = make_multiplier(3)

因为函数make_multiplier返回一个函数,times3是一个函数。

print(times3(9))

…返回…

27

…因为 3 乘以 9 等于 27。闭包可能是用 Python 完成这项任务的最佳方式。

内置枚举

Python 内置枚举牛逼。也许开发人员面临的最常见的任务是在跟踪索引的同时遍历列表中的一项。在许多没有枚举的其他语言中,程序员需要手动完成这项工作,例如在 Python 中:

counter = 0
for item in a_list:
     do_something_with(item)
     do_something_else_with(counter)
     counter += 1

然而,Python 的enumerate()函数通过返回一个不可打包的元组来自动跟踪每次迭代的计数器:

for index, item in enumerate(a_list):
     do_something_with(item)
     do_something_with(index)

作为演示,下面的代码…

for index, item in enumerate(['a','b','c']):
     print(index,item)

…会输出…

0 a
1 b
2 c

装修工

装饰者接受一个函数,向该函数添加一些功能,然后返回它。这在需要父函数的小变化的情况下非常有用,因为可以用装饰器来改变函数,而不是为需要的函数的每个变化重写函数。

假设我们有一个函数ordinary(),它的唯一目的是打印出一个字符串“I am an ordinary function.”

def ordinary():
    print("I am an ordinary function.")

假设我们还想添加另一条消息,“I was decorated!”我们可以创建一个函数decorate(),它接收一个函数,打印添加的消息,然后调用原始函数,其对象作为参数输入到函数decorate()中。添加额外字符串和调用原始函数的过程可以存储在一个内部函数中,其对象用decorate()返回。

def decorate(function):
    def inner_function():
        print("I was decorated!")
        function()
    return inner_function

为了修饰原始函数ordinary(),我们将在原始函数上调用函数decorate()。我们存储decorate()输出到decorated的变量是一个函数(函数decorate()中的inner_function)。

decorated = decorate(ordinary)
decorated()

调用decorated()产生输出…

I was decorated!
I am an ordinary function.

装饰者使用@符号来自动装饰一个功能。

@decorate
def ordinary():
    print("I am an ordinary function.")

在函数定义前使用@符号会自动修饰函数。它的计算方式与前面概述的修饰函数的方法相同。

通过在一个函数前添加几行@decorate,多个 decorators 可以相互链接。

感谢阅读!

如果您对代码示例或概念有任何疑问,请在下面的回复中提问。

数据科学项目的基本软件工具

原文:https://towardsdatascience.com/essential-software-tools-for-data-science-projects-32c86ac54ca6?source=collection_archive---------26-----------------------

Python,Matplotlib 样式,Git,Git 自述文件,Git 页面,VSCode,概念,语法

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

如有疑问,请始终选择“黑暗模式”选项!由克莱门特 Photo】在 Unsplash 拍摄的照片

在本文中,我们将研究如何设置一些工具,以实现更具可重复性和协作性的工作流。本指南将有助于人们开始他们的第一个 ML 项目,或者数据科学领域的资深人士在☕️意外洒出咖啡后重新设置他们的 MacBook🤦‍♂️.然而,鉴于这篇文章是在周五起草的,啤酒溢出的可能性要大得多。

免责声明:这里将描述的“基本软件”是基于作者的个人偏好和必然存在的一套更好的工具—请在评论中添加您的建议。本文绝不试图宣传或推广任何特定的软件,所有程序都可以免费获得。

需求:这里的指令将基于 MAC OS(v 10.15);然而,安装 Linux 或 Windows 也是可行的。

大纲:

这里的部分基本上是独立的,请随意跳过!

  1. Git:版本控制和代码备份是必须的。GitHub 允许你为你的项目创建一个吸引人的自述文件,甚至可以免费托管你的网站。
  2. Python:设置一个虚拟环境,用于包安装和分配一个默认的漂亮的绘图风格宏。
  3. VSCode:使用 Python 笔记本的一种更高级的方式。
  4. 理念:创建并分享关于你的项目的漂亮笔记。
  5. 语法上:提高你的写作技巧。

1.饭桶

这里,我们将假设对git和 GitHub 有一些熟悉。如果你真的想学习更多关于版本控制的知识,或者需要复习,去看看 Anne Bonner 的这篇令人惊叹的文章。与 GitHub 存储库交互的最有效方式是通过 iTerm2 这样的终端应用程序,它提供了惊人的 git 集成、自动建议和语法高亮显示,正如这里描述的。此外,它允许直接在终端中打开图像(和 gif)。

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

带有自动建议和语法高亮显示的 iterm 2(图片由作者提供)

你的项目不应该只有一个平淡无奇的自述页面,所以像这里描述的一样写一个吸引人的项目描述,并附上一些徽章(盾牌),如下所示。

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

https://github.com/badges/shields资源库的自述页面。(图片作者)

最后,如果你需要一个网站来托管你的项目,或者需要一个在线作品集来展示多个项目,GitHub 提供了工具来轻松做到这一点,正如埃米尔·吉尔在这里描述的。学习 HTML 和 CSS 技能的一个好方法是从 HTML5 UP 下载一个免费的网站模板,然后开始修补。

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

一个免费的 HTML5 模板,Strata,来自https://html5up.net/strata(作者提供图片)

2.计算机编程语言

这里我们将继续用pipvirtualenv进行 Python 包的 本地 安装。

如果你需要获得最新版本的 Python 使用 *brew install python* ( 看这里 如果你的笔记本电脑上没有 *brew* )。这将安装最新版本的 *python* *pip* 。如果您已经安装了旧版本的 Python(例如 v2)并且 *python* 命令链接到它(检查 *python --version* ),brew 会使 *python3* *pip3* 可用。

首先,安装环境管理器*(如果* *python --version* 为 v2,则使用 *pip3* )

接下来,创建一个新目录,并在该目录中实例化一个新的 Python 环境

这将允许我们在那个环境中直接安装 Python 包,而不是“全局”安装。该环境需要用以下命令激活(每次登录)

您应该会在终端中看到(my_project_env)。如果您有许多要安装的软件包,只需将它们列在一个文件中——您也可以在其中指定版本— requirements.txt

然后让pipmy_project_env中一次性安装好

默认 Python Matplotlib 样式

如果希望您的绘图看起来比使用默认 Matplotlib 选项的绘图更有吸引力,可以设置自定义 Matplotlib 样式。这里有一个例子:

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

资料来自 奥雷连·杰龙的《动手机器学习》一书 ( 作者图片)

为了实现这种风格,下载这个宏文件 ml_style.mplstyle (随意修改/分发该文件),并将这些行添加到您的 Python/Jupyter 代码中

3.虚拟代码

Jupyter 在大笔记本之间切换标签时反应迟钝,令人有些沮丧。自从过渡到 VSCode 之后,Jupyter 就没有什么可错过的了:Python 笔记本的所有功能都在。此外,VSCode 是 Python、C、LaTeX 和其他文件的快速而强大的编辑器。此外,可以将 VSCode 设置为与其他更熟悉的编辑器(如 Sublime 或 Atom)具有相同的快捷方式和行为——答对了!

Bikash Sundaray 写了一篇关于为 Python 笔记本设置 VSCode 的伟大文章。此外,你可以连接到一个远程 Jupyter 会话上运行,例如,你的 GPU Ubuntu 服务器(更多关于这个在这里)用于神经网络训练。

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

VSCode Python 笔记本中的内联绘图和代码自动建议。(图片作者)

4.概念

一个强大的平台来做笔记和创建文档是必须的。它有两个目的:1)让你自己有条理,2)让你可以轻松地与他人分享你的笔记。概念允许你组织你的文档,并使任务、模板、会议、代码嵌入变得轻而易举。 Sergio Ruiz 写了一份综合指南,介绍如何利用这个概念的许多特性。

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

注意语法突出显示。(图片作者)

一封学术风格的电子邮件(即以。edu、英国等。)会免费授予你一个 Pro 版本。如果你以前使用过 Evernote,那么它提供了一个迁移工具,对我来说,它的效果和预期的一样。

注意:截至 2020 年 8 月,仅支持美国英语和韩语,英国英语(拼写检查)以及其他语言。

5.语法上

在你的模型上获得高准确度的分数是很棒的;然而,一个成功的数据科学项目需要有效地交流你的发现和方法。Grammarly——一个人工智能支持的语法、语气和风格助手——让你提高写作技能。

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

语法在行动!(图片作者)

请注意,ideal 将很快实现语法集成(与独立应用程序),希望如此。同时,只有通过浏览器打开概念时,Grammarly 才起作用。

编后记

我希望这篇文章有助于您开始数据科学项目。如果您有任何意见或建议,请告诉我。即将到来的后续文章将描述其他健壮的工具和方法(DevOps)来改进您的工作流。

推荐引擎的本质:基于内容和协同过滤

原文:https://towardsdatascience.com/essentials-of-recommendation-engines-content-based-and-collaborative-filtering-31521c964922?source=collection_archive---------25-----------------------

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

来源: altkom 软件&咨询

两种推荐引擎的描述和比较

你有没有想过为什么脸书上的广告与你感兴趣的东西如此相关,或者网飞上的“电影匹配”是如何工作的?是魔法吗?不会。在这两种情况下,推荐引擎或系统都会根据你的历史行为做出预测。

如果你是科幻电影迷,看过《星球大战》,推荐引擎可能会建议你看《阿凡达》。这种方法被称为基于内容的过滤,因为它分析每个项目的内容并找到相似的项目。虽然非常有用,但它需要对每个项目有透彻的了解,以便找到相似的项目。

我们还可以想到另一种情况,你的一个和你有很多相似之处的朋友告诉你“昨天,我去电影院看了乔治·卢卡斯的新电影,太棒了!你真应该去看看”。与其他用户有共同点也可以是推荐电影的好方法。下面是第二种推荐引擎:协同过滤

在本文中,我将回顾基于内容的过滤和协作过滤背后的原理,然后对它们进行比较。

基于内容的过滤

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

这里的想法是推荐与你之前喜欢的物品相似的物品。该系统首先找到所有文章对之间的相似性,然后使用与用户已经评估的文章最相似的文章来生成推荐列表。

但是一个新的问题出现了:如何才能找到物品之间的相似之处?

为了比较两个项目,我们需要将它们转换为向量等数学对象,在此基础上,我们可以计算度量标准,如欧几里德距离、皮尔逊系数余弦相似度
以下是上述不同指标的公式:

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

一种常用的技术是 TF-IDF (频率术语—倒置文档频率)。它是一种统计度量,用于评估一个单词与一组文档中的一个文档的相关性。这是通过将两个度量相乘来实现的:单词在文档中出现的次数(术语频率)和该单词出现在文档中的次数的倒数(逆文档频率)。如果一部电影是像《星球大战》is 那样的科幻片,科幻这个词可能会在电影描述中出现很多,所以词条频率会高,如果电影语料库中科幻片不多,词条频率的倒数也会高。最后归一化后,TF-IDF 的值会接近 1。

如果我们将这种技术应用于一组胶片,在归一化之后,我们可以获得下表。此表中的数字是随机的似是而非的值。

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

现在我们有了描述电影的向量,我们可以计算这些向量中的两个向量之间的欧几里德距离、皮尔逊系数或余弦相似度。比如《星球大战》和《阿凡达》向量之间的欧氏距离是 0.05,而《星球大战》和《泰坦尼克号》之间的距离是 1.5。结果越接近 0,元素越相似。这样,我们就可以根据自己选择的特点(科幻、动作、言情)清楚地看到《星球大战》和《阿凡达》有多接近,《星球大战》和《泰坦尼克号》有多远。

正如您所看到的,对于这个方法,了解每个元素的内容是非常重要的。在下一部分中,我们将深入研究协作方法,它是一种同时基于用户和对象之间相似性的方法。

协同过滤

协同过滤不需要任何东西,只需要用户对一组项目的历史偏好。

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

协同过滤的标准方法被称为 最近邻 算法。我们有一个 n × m 的评级矩阵,我们称之为 r,用户矩阵表示为 u,项目矩阵表示为 p。用户 I 由向量 uᵢ表示,他们是 n 个用户,所以 i = 1,…n。项目由向量 pⱼ表示,他们是 m 个项目,所以 j=1, …m .现在,如果目标用户 I 没有观看/评价项目 j,我们想要预测评价 rᵢⱼ。该过程是计算目标用户 I 和所有其他用户之间的相似性,选择前 x 个相似用户,并且取这些具有相似性的 x 个用户的评价的加权平均值作为权重。 评级 rᵢⱼ的定义是:

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

然而,人们有不同的评分标准,有些人往往比其他人给出更高的分数。这种偏差可以通过在计算加权平均值时减去每个用户在所有项目上的平均分,再加上目标用户的平均分来避免,如下所示。

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

然后,我们使用皮尔逊相关、余弦相似度欧几里德距离来计算相似度。

但是这种方法有一些限制。它没有很好地处理稀疏性,例如,当邻居中没有人对你试图为目标用户预测的项目进行评级时。

由于稀疏性和可伸缩性是标准 CF 方法的两个最大挑战,这里出现了一种更先进的方法,将原始稀疏矩阵分解为具有潜在因子/特征和更少稀疏性的低维矩阵。这种方法被称为矩阵分解。回想一下,R 是矩阵评级,我们想把 R 写成两个矩阵的乘积:U 是用户矩阵,P 是项目矩阵。由于分解不可能完全相等(R 与 U 和 P 的乘积稍有不同),我们引入了另一个称为 R '的矩阵,它表示预测的等级。它被定义为 p 与 U 乘积的结果。

矩阵 U 的行数等于用户数。矩阵 P 的列数等于项目数。矩阵 U 的列数等于矩阵 P 的行数,矩阵 P 等于潜在向量的数量。

在下面的例子中,我选择的潜在向量的数量等于 2。为了理解这种选择,我们需要查看 SVD 分解,其中潜在向量的数量是确保 r '能够捕捉原始矩阵 r 内的大部分方差的向量的数量,因此 r ‘是 r 的近似值,R’ ≈ R。我们注意到 rᵢⱼ’是用户 I 对项目 j 的近似评级。因此,我们有:

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

这个想法是为了尽量缩小 rᵢⱼ和 rᵢⱼ’.之间的差异问题暴露如下:

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

但是,我们如何找到最优向量 uᵢ和 pⱼ呢?

回想一下,这些向量代表用户 I 和物品 j。如果您熟悉机器学习,为了进行预测,我们总是使用我们希望最小化的损失函数:

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

优化过程的目的是找到使损失函数最小的最佳 U 和 P。此外, L2 正则化已被添加,以防止用户和项目向量的过度拟合。

两种技术的比较

尽管在基于内容的过滤中,该模型不需要其他用户的数据,因为推荐是特定于该用户的,但它是协同过滤算法的核心。然而,对元素的透彻了解对于基于内容的算法是必不可少的,而在协同过滤方法中只需要元素评估。

与这一点密切相关的是引入新元素的问题,也称为“冷启动问题”。如果在训练期间没有看到某个元素,则系统不能为其创建嵌入,也不能使用该元素查询模型。虽然一些技术作为 WALS 中的投影或试探法存在,以生成新的嵌入,但是添加新的功能将增强基于内容的过滤方法。

PS:我现在是柏克莱大学的工程硕士,如果你想讨论这个话题,请随时联系我。 这里的 是我的邮箱。

你的模型的对数损失比随机猜测的对数损失好吗?

原文:https://towardsdatascience.com/estimate-model-performance-with-log-loss-like-a-pro-9f47d13c8865?source=collection_archive---------23-----------------------

在二元或多类分类问题中,如何获得考虑类不平衡的随机猜测对数损失基线得分

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

照片由帕特里克·福尔Unsplash 拍摄

介绍

你做了一个分类模型。

您在某处读到过关于对数损失作为一种评估模型性能的方法。关于对数损失幻数。

但与准确性不同,使用它并衡量你的模型得到的对数损失是好是坏并不是很直观,对吗?尤其是当你的班级不平衡的时候。

如果是,那么你点击了正确的链接!

在这篇文章中,我试图回答这些问题:

  1. 为什么是日志丢失?
  2. 什么是日志丢失?
  3. 与随机猜测相比,如何衡量模型性能?
  4. 班级不平衡怎么办?
  5. 当目标是多类时该怎么办?
  6. 你能给我适用于所有这些情况的代码吗?(当然,我可以!)

为什么是日志丢失?

建立一个模型只是完成了一半的工作。需要有一个评估指标来衡量模型的性能。在行业中,不同种类的度量标准被用来评估模型。度量标准的选择是模型类型和目标的函数。对于分类任务,混淆矩阵提供了几个度量标准可供选择,如准确度、精确度和召回率。

虽然分类准确性是最广泛使用的度量标准,但它可能是最容易误导的。准确度被定义为正确预测与总预测的比率。事实上,准确性并不能给出错误预测的信息。

具体来说,在两种情况下,准确性度量失败。第一,两个班以上的时候。模型可能会忽略一个或多个类。在这种情况下,该指标不会给出关于每个类别的个体准确性的信息。第二,当数据存在不平衡类时。例如,如果二进制分类数据集具有 90:10 的类别不平衡比率,那么具有 90%分类准确度的模型是不提供信息的模型。

为了解决这些限制,F1 分数是另一个度量,它被定义为精确度和召回率的调和平均值。精度是被正确识别的阳性病例的比例,而召回是被正确识别的实际阳性病例的比例。提高 F1 分数有助于同时提高准确率和召回率。取调和平均值是有意义的,因为与算术平均值相比,调和平均值对极值的惩罚更大。

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

作者图片

尽管作为一种度量,F1 分数比准确性好,但在分类模型中仍然存在缺点,其中类别预测是基于类别概率的。

考虑两个模型,其中对于特定观察,第一个模型预测概率为 0.6 的类别,而另一个模型预测概率为 0.9 的类别。F1 分数将对这些模型一视同仁,因为这两个模型都预测了此次观察的相同类别。它没有考虑预测的确定性。如果实际值为 1,那么两个模型都是正确的。但是第二种模式显然更好,不是吗?

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

比较精确度和 F1 与对数损失(图片由作者提供)

为了考虑分类概率,可以使用对数损失。Log-loss 是每个实例的校正预测概率对数的负平均值。

什么是日志丢失?

Log-loss 是每个实例的校正预测概率对数的负平均值。

对于具有真实标签 y {0,1}和概率估计 p=Pr(y=1)的二元分类,每个样本的对数损失是给定真实标签的分类器的负对数似然性:

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

作者图片

这延伸到如下的多类情况。假设一组样本的真实标签被编码为 1-of-K 二进制指示矩阵 y,即如果样本 I 具有取自一组 k 个标签的标签 k,则 yᵢ,ₖ = 1。设 p 是概率估计的矩阵,pᵢ,ₖ = Pr(tᵢ,ₖ=1).那么整个集合的对数损失为

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

作者图片

好了,理论到此为止。让我们直接讨论眼前的问题,好吗??

与随机猜测相比,如何衡量模型性能?

想象一下。我有一盒巧克力。它有 5 块黑巧克力和 5 块白巧克力。如果我让你不偷看盒子里的巧克力并猜它是哪一种,你会说有 50%的机会是黑色的,对吗?换句话说,你的随机猜测准确率是 50%。

也就是说,准确度分数在 50%以上的模型比随机猜测要好。在这里,你直观的知道 100%的准确率是最好的,0%是最差的。

对于日志丢失,事情不那么明显,也不那么直观。你需要把你的猜测代入上面给出的公式。

考虑一个有 10 个观察值的数据集。目标 y 有五个 1 代表黑巧克力,五个 0 代表白巧克力。如果你随机猜测,得到一个黑巧克力的概率,p = Pr(y =黑)=0.5。用 1 代替黑巧克力,用 0 代替白巧克力,上面的公式给出了下面的计算。

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

平衡二元分类的随机猜测对数损失(图片由作者提供)

取最后一列的平均值,瞧!你有你的随机猜测日志损失。因此,如果你的模型的对数损失小于(损失是负的,记住!?)0.693,肯定比乱猜强!

这就引出了我们的下一个问题,如果机会不是 50-50 呢?

班级不平衡怎么办?

还记得我那盒著名的巧克力吗?如果现在我告诉你它有三块黑巧克力和七块白巧克力,你不会说取出黑巧克力的机会是 50-50,对吗?

这里选一个黑巧克力的概率就变成了,p = Pr(y =黑)=3/10=0.3。现在,用 1 代替黑巧克力,用 0 代替白巧克力,看看下面的计算。

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

不平衡二元分类的随机猜测对数损失(图片由作者提供)

看看随机猜测 log-loss 是怎么从 0.693 降到 0.611 的?这意味着酒吧被设置了更严格的条件,嗯?该模型的性能需要优于 0.611。

最后,让我们看看当你的盒子里有更多种类的巧克力时会发生什么!美味,不是吗!?

当目标是多类时该怎么办?

这次我在盒子里放了 10 块牛奶巧克力。现在计算更加不直观了,但是请耐心听我说。这次我们有三种标签——黑巧克力、白巧克力和牛奶巧克力。

注意 y 代表拿起一种巧克力的事件。之前我们取 y=1 代表黑巧克力。于是 1-y 自动变成了白巧克力。然而,这一次,我们明确地说出了巧克力的类型。我们取 y1 =拿起一块黑巧克力的事件,y2 =拿起一块白巧克力的事件,y3 =拿起一块牛奶巧克力的事件。然后,根据随机猜测,

选择黑巧克力的概率=3/20=0.15

选择白巧克力的概率=7/20=0.35

选牛奶巧克力的概率=10/20=0.5

现在这些计算就有意义了。

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

不平衡多类分类的随机猜测对数损失(图片由作者提供)

这就对了。这个不平衡多类问题的随机猜测对数损失为 0.999。

请注意,每行的最后一个单元格表示上一节中给出的公式的内部求和。当将列相加时,在计算平均值时,表示外部求和。

好的,你明白了,但是当你遇到一个具有不同类别和患病率的新数据集时,该怎么办呢?你接着读下一部分,傻瓜。

你能给我适用于所有这些情况的代码吗?

这是一个 python 函数,它将类的比率列表作为输入,并输出一个随机猜测的对数损失。如果你的模型的对数损失小于这个数字,你的工作就完成了!

看到那个论点“多”了吗?我用它来按照输入的比率创建随机的观察样本。如果您给 multi=1000,代码将按照提供的比率创建 1000 个观察值。然后使用 sklearn 的 log-loss 函数得到你的基线。整洁,是吧!?

结论

在本文中,我解释了为什么 log-loss 是评估分类模型性能的好选择。我解释了它是什么,并展示了如何针对三种场景计算它——平衡二进制、不平衡二进制和不平衡多类分类。最后提供的 python 函数可以帮助您获得分类问题的基线。

参考

https://sci kit-learn . org/stable/modules/model _ evaluation . html # log-loss

LinkedIn 上和我联系!

GitHub 上看看我的一些很酷的项目!

估计人工智能项目成本和时间表:4 条经验法则

原文:https://towardsdatascience.com/estimating-ai-project-costs-timescales-4-rules-of-thumb-707ccf49a768?source=collection_archive---------25-----------------------

规划人工智能项目的实用指南

对于人工智能项目的“正确”方法还没有达成共识。你也不会找到专门针对人工智能项目成本和持续时间的公认的、经过验证的估算模型或基准。

关于常规 IT 开发需要多长时间有很多指导,但是大部分都倾向于关注从用户那里引出需求的活动,或者构建技术设计和编写代码。对于处于人工智能工作核心的更非结构化的工作来说,帮助要少得多——例如处理数据、评估算法和处理训练数据。

目前,估计人工智能工作的非传统部分往往更多地依赖于个人经验和预期,而不是更客观的东西。

这里有四条经验法则,可以帮助你决定为人工智能项目投入多少时间和精力,或者评估提交给你的评估。他们强调的是避免可能导致最令人不快的意外的陷阱。他们特别适用于那些在人工智能项目方面经验不足的人。

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

但是,首先提醒一下 IT 项目评估的一些基础知识。估计人工智能项目的成本是一种进化和适应。

可靠的 IT 项目评估的基础

IT 工作有一个当之无愧的名声,那就是大规模超支,尤其是大型的多年项目。然而,在过去的几十年里,现实发生了变化。IT 项目仍然会延迟,但是巨大的、引人注目的失败已经不那么常见了。

这种变化有几个原因。一个是更灵活的开发过程和更短的项目周期的流行。另一个是采用项目质量度量和持续改进。卡内基·梅隆大学的 CMM 著作在第二部中发挥了重要作用,对于 IT 新手来说仍然是无价的读物。

关于 IT 流程和项目管理方法仍然存在激烈的争论。然而,在给定相同信息的情况下,对 IT 项目报价的请求会产生来自大多数供应商的大致可比的估计。这将包括如何将整个工作分解成阶段或活动的类似分解,例如要求等。

这与人工智能项目相关,因为我们目前处于许多年前一般 IT 评估的位置:不一致,通常不可靠。一个很大的原因是人工智能开发过程各不相同,就像关于质量对人工智能交付品意味着什么的观点一样。因此,关于评估的讨论通常是由个人经验或项目约束驱动的,而不是更客观的东西。

在你如何构建人工智能方面创造一致性将会为评估未来的人工智能项目带来更客观的基础。这也将允许你改善和优化你的人工智能工作,并在与供应商的讨论中保持自己的优势。

评估人工智能项目:经验法则 1

没有可信的基准,最好是你自己的基准,不要计划大项目

不管你得到了什么样的承诺或数字表明了什么,你都应该明智地着手大型人工智能项目。如果你有人工智能工作的经验,你可能对所涉及的内容有一些基准。这些是验证大型预测人工智能项目成本的最佳方式。即便如此,要求其他客观数据来支持评估是值得的,最好是你可以验证的数据。客户推荐尤其有用。

如果你第一次体验人工智能,从大型项目开始的风险会更大。我总是建议从一个短时间的、相对低成本的练习开始

这样,你的团队和合作伙伴将在你的组织中体验人工智能。这将是开发使用你的数据并连接到你的 IT 系统的人工智能解决方案的真实体验。对于人工智能项目成本和时间尺度的未来估计,这是一个比一般或行业数字更现实的基础。在第二个或第三个小项目之后,你将有一个更可靠的起点来评估更雄心勃勃的人工智能工作。

当开始使用人工智能时,有用的小项目可以短至 2-3 个月,而不是几个季度或几年。用几万或非常小的几十万英镑/美元/欧元就可能得到现实的结果;数十万或数百万的成本对结果造成了更大的压力。一个个位数规模的核心团队可能比几十个人中的一个更有效率和生产力。

如果建议你的人不这么认为,那么你可能要重新考虑选择范围或目标。当然,可能会有组织或商业因素影响观点。

评估人工智能项目:经验法则 2

接受某些阶段在本质上是“实验性的”,但是要控制住它们

人工智能工作的一个有时被误解的特点是,几天或几周的工作被“浪费”是正常的。这不一定是团队缺乏经验或缺乏能力的标志——尽管生产力当然会随着实践而提高。这是基础人工智能技术的反映,需要实验和一定程度的试错。

估算人工智能项目成本和时间表的一个挑战是,它们可能会成为——也许是无意的——“空白支票”,尤其是对人工智能供应商而言。诀窍是在有效结果的足够空间和允许“漂移”的工作之间找到正确的平衡。

大部分的 AI 课程,包括非技术类的,都参考了 EDA(或者某种等同物)的概念。这是探索性数据分析,大多数人工智能项目的关键早期部分。

处理“实验性”工作评估的技巧

一种常见的方法是将人工智能项目成本和时间表的估计分成两部分。对于 EDA,可能会有一个确定的估计,而对于项目的其余部分,可能会有一个更加试探性的估计。第二个估计只有在 EDA 结束时才被确认。到那时,对数据、业务问题和更广泛的 IT 环境会有更好的理解。

另一个选择是使用 IT 开发技术,比如时间盒来限制实验工作的持续时间。这反过来又将项目的其余部分限制在时间盒中发现的内容。这涉及到对像敏捷这样的开发方法的讨论。除了指出敏捷不是糟糕的评估的借口之外,在这里讨论细节是不合适的。

你如何处理一个人工智能项目的“实验”方面,不如认识到它们的特征重要。对于一个好的人工智能项目,评估的诀窍是限制实验阶段的持续时间,而不过度损害它们的有用性。

理想情况下,通过很好地使用这些阶段,您的团队可以在几天或几周后发现不可避免的错误或死胡同,而不是几个月。

评估人工智能项目:经验法则 3

决定如何平衡“好”和“足够好”之间的矛盾

数据科学家的一个关键角色是探索解决业务问题的不同方法,评估备选方案以确定最佳方案。而人工智能团队的业务成员是保持专注于人工智能工作的业务结果。从这个角度来看,人工智能是达到目的的一种手段,要尽可能快速、经济地达到目的。

这可能导致两种观点,即什么使一项任务“完成”,或者需要更多的努力。例如,如果一个算法达到 95%的“准确率”,数据科学家可能会认为这很差,但业务用户可能会不这么认为。

当然,正确的答案取决于算法的用途。这包括理解获得 95%正确答案的价值,以及 5%错误的成本/风险。这就是像精度、召回和 F1 分数这样的术语变得相关的地方,并导致诸如假阳性与假阴性的相对重要性的讨论。

这种平衡在实践中是什么样的?

为了更好地理解这一点,我们来看一个医学诊断的例子,比如癌症检测。“5%的误差”的含义是模糊的。一种可能性是,5%接受筛查的患者认为他们没有癌症,但实际上患有癌症。相反,这可能意味着 5%被标记为患有癌症的患者实际上都是健康的。

决定追求更精确的算法还是停留在 95%的精确度需要理解这样的差异。理想情况下,还要意识到相关的商业价值。

  • 为了获得更高的精确度,可能需要进一步调整模型;
  • 如果 95%接近算法性能的极限,则可能需要其他算法;
  • 第三种选择可能是重新审视各种选择,以获取或准备更好的数据;
  • 正确的答案可能是接受 95%的准确率,即使可能更好。

这只是一个例子。在人工智能工作期间,在“正确”答案上可能会有几个这样的潜在冲突。每个都会影响人工智能项目的评估。

人工智能项目领导的角色就是平衡这两种心态。项目期间已经够棘手的了。即使有事实,两种观点都可能有令人信服的论据。

很难——可以说是不可能——在这种可能性出现之前准确地考虑到它们。因此,在一开始估计人工智能项目的成本和持续时间时,需要考虑到这一点。这包括在团队内部就如何处理此类决策达成一致。

评估人工智能项目:经验法则 4

对数据“运作”有现实的预期和意外情况

第四条经验法则的出现是因为人工智能的结果通常需要大量的数据准备工作。在项目评估中,这项工作经常被忽视。

获得足够的适当数据来“喂”一个人工智能解决方案可能是人工智能工作中的一个黑洞,尤其是对粗心的人来说。数据准备可能会耗费过多的精力,有时甚至可能不是供应商报价的一部分。

一个挑战是知道你的环境真正需要多少数据。另一个是确保它被适当地包含在估算中。

请特别仔细地查看供应商对此处问题的评估。数据准备有时会完全从报价中消失,被埋没在提案假设中。另一种方法是允许一个象征性的几天,知道它会立即扩大。

估计数据准备工作

为了涵盖这些可能性,你的团队需要了解哪些相关数据是可用的。这包括它有多完整、准确和可靠,以及可以和不可以用它做什么(例如法律、监管、道德)。

没有这种理解,任何人都不可能可靠地预测准备数据的工作量和成本。这种理解包括真正的数据是什么,数据处于什么状态(完整性、准确性等),以及准备和清理数据的工作。这是估计人工智能项目成本和时间表的另一个棘手的部分。

如果你的组织已经在你考虑的领域做了人工智能或分析工作,这些信息可能是可用的。它可能不会出现在正式的文档中,但是希望有具备相关知识的人来帮助确定数据准备工作的规模。

如果您没有理解数据准备的知识,您将需要一个范围界定练习,称为探索性数据分析(ed a)。如果供应商这样做,您应该期望数据准备活动和评估作为可交付成果是清晰的。

估算人工智能项目成本&时间表:总结

人工智能流程和基准是长期评估准确性的关键

估计人工智能项目的成本和时间比常规的 IT 工作更难。这在一定程度上是由于缺乏 AI 行业流程和基准。结果是更多地依赖于你的人工智能专家和供应商的经验、判断和意见。

如果人工智能是你经常做的事情,考虑在你的前几个项目中创造你自己的人工智能工作方法。您将为自己的组织获取人工智能项目成本和工作数据。对你来说,这将比行业数据更可靠,并为持续改进提供基准。这不一定是一个困难的练习,也不会增加太多的开销。事实上,它应该通过未来工作中的储蓄迅速收回成本。

评估较小的项目更容易,尤其是在早期

与此同时,在开始人工智能项目时,从小处着手通常是必经之路。

不管项目大小如何,有一些明显的领域的估计可能是过度的或过于乐观的。如果你依靠供应商来交付你的工作,尤其如此。

考虑在进行过程中评估每个阶段

有效地使用 EDA,以及良好的项目管理实践会非常有帮助——尤其是像敏捷这样的迭代方法。你还需要平衡不同团队角色的本能和优先级,尤其是在工作的“实验”阶段。

这篇文章最初发表于www.aiprescience.com

用机器学习估算建筑物的反事实能耗

原文:https://towardsdatascience.com/estimating-counterfactual-energy-usage-of-buildings-with-machine-learning-8ca91ec66c08?source=collection_archive---------21-----------------------

我们可以制作 ML 模型来预测建筑的能源使用吗?绝对的!

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

目录表

  1. 摘要
  2. 背景
  3. 材料和方法
  4. 结果和结论
  5. 参考

1.摘要

美国供暖、制冷和空调工程师协会(ASHRAE)是世界上最大的能源效率研究协会之一。它们成立于 1894 年,拥有 54 000 多名成员,服务于 132 个国家。自 1993 年以来,他们已经举办了 3 次大型数据竞赛,旨在预测建筑能耗。最近的一次是 2019 年 10 月在 Kaggle 上举办的。在这次比赛中,前 5 名选手分享了总计 25,000 美元的奖金。第一名团队获得 10,000 美元奖金。比赛于 2019 年 12 月 19 日结束。我参加比赛较晚,但由于我的机械工程背景(ME)和对机器学习的热情(ML),我对比赛非常感兴趣。因此,我决定在到期日之后解决这个问题,以便更好地理解 ML 以及它如何应用于我的领域,即我。因此,本文试图根据最近 2019 年 10 月 Kaggle 的数据,调查一座建筑将消耗多少能源。为什么?因为正如竞赛状态:

评估能效改进的价值可能具有挑战性,因为没有办法真正知道一座建筑在没有改进的情况下会使用多少能源。我们能做的最好的事情就是建立反事实模型。建筑物大修后,新的(较低的)能耗将与原始建筑物的模拟值进行比较,以计算改造后的节约量。更准确的模型可以支持更好的市场激励,并实现更低成本的融资。

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

图 0.0 来自 IPMVP 的节能干预预测模型的使用。此图说明了预测模型的使用,并与长期建筑性能模型的节能进行了比较。⁴

2.背景

为了进行这种分析,使用来自 ASHRAE 及其贡献者的数据,用 Python 构建了四个 Jupyter 笔记本。⁴ ⁵ ⁶ ⁷

  1. Part-1-Divide.ipynb
  2. Part-2-And.ipynb
  3. Part-3-Conquer.ipynb
  4. Part-4-all siteids . ipynb

原始输入数据来自 6 个不同的文件,其中有 17 个独特的特征。

如上图,有16独特的site ids,托管1448独特的建筑。建筑的主要用途(primary_use)属于16的独特类别(即办公、教育等)。除此之外,还有4独特的仪表来测量能源使用情况(1.chilled water2.electric3\. hot water4\. steam)。

此外,由于时间范围在 2015 年和 2018 年之间,因此有超过6100 万个唯一时间戳!这是大量的数据。事实上,那些用于训练和测试的文件的大小分别为 ~0.7 和 1.4 GBs ,需要一种不简单的数据处理方法!

快速免责声明:出于教育目的,允许在比赛之外使用数据:

数据访问和使用。您可以出于任何商业或非商业目的访问和使用竞赛数据,包括参加竞赛和 Kaggle.com 论坛,以及学术研究和教育。

这些模型的准确性基于均方根对数误差(RMSLE)进行评估:

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

方程式 0。用于模型评估的均方根对数误差(RMSLE)。

其中:

  • ϵ是 RMSLE 值(分数)
  • n是(公共/私有)数据集中的观测值总数,
  • pi是你预测的目标,而
  • aii的实际目标。
  • log(x)x的自然对数。

3.材料和方法

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

图 0.1 所用 Jupyter 笔记本的整体流程图。

有一件事变得很明显,那就是这个问题的“泄露”数据的来源。⁹:我不想使用“泄露”的数据,因为我想对我的模型如何在未知的未来数据上工作进行公平的评估。在我看来,这是一个更有价值的方法,尤其是因为我不是为了比赛而这样做。在比赛中,这很常见,而且似乎是获胜的唯一途径。

我的方法的独特之处在于,我用Site_ID分解了问题。因此,我的方法将数据分成 16 个模型,因为有 16 个唯一的Site_ID数字。这大大减少了一次训练的数据量。这也让我能够专注于每个Site_ID的独特差异。无论我在Site_ID中注意到什么趋势,我都能够更好地为其建模。基本的总聚集方法不会出现这种情况。

大多数人似乎聚集了所有的数据来形成预测,产生一个 ML 模型来预测未来的能源使用。一些人尝试按仪表类型分割数据,因此有 4 种不同的型号。⁸的一些人试图根据一年中训练的时间将数据一分为二。获胜的⁰团队对“泄露”的数据以及Site_IDMeterBuilding & Meter的组合进行了混合和堆叠。

在网上做了一些挖掘后,我找到了威廉·海登·⁵最近的一篇论文,其中描述了一些与获胜团队有相似之处的方法。他的论文不是专门针对这个问题,而是针对 187 种家庭能源使用。

“首先,每个家庭被独立地建模,产生总共 187 个模型,这些模型的预测被聚合以形成总预测。第二,将家庭汇总,开发一个单一模型,将客户群视为一个单一单元。第三种选择是根据每个家庭的平均日负荷情况对类似的家庭进行分组⁵

我们的问题有 1448 个独特的建筑,这意味着理论上我们可以制作 1448 个独特的模型,就像威廉的第一种方法一样。然而,这种方法在威廉的论文中并不是最优的。最佳方法是根据每个家庭的平均日负荷概况对数据进行聚类(选项 3)。

因此,我的方法是对每个Site ID使用类似于最优方法的东西,因为它们通过单向 ANOVA ( p 值~0 )似乎具有统计上不同的平均值meter readings。这意味着我们可以拒绝零假设(每个站点都有相同的平均值meter reading),假设异常值和杂乱的数据没有掩盖真实的平均值。

import pingouin as pgaov = pg.anova(data=data_train, dv=’meter_reading’, between=[‘site_id’], detailed=True)

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

图 0.2 原始训练数据的箱线图,通过将 y 轴限制为 2000 千瓦时排除异常值。请注意,站点 13 的平均值甚至不在此范围内。

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

图 1.0Part-1-divide . ipynb .流程图

第一部分。按唯一的站点 ID 划分数据

Part-1-Divide.ipynb 是一个很短的笔记本,但是非常有效。

**制作输出文件的目录。**这是我制作 16 个独特的输出文件夹的地方,如图 1 所示。为每个站点 ID 创建唯一模型时,这些文件夹是导入和导出文件的占位符。

Splits =['Site_ID_0',
         'Site_ID_1',
         'Site_ID_2',
         'Site_ID_3',
         'Site_ID_4',
         'Site_ID_5',
         'Site_ID_6',
         'Site_ID_7',
         'Site_ID_8',
         'Site_ID_9',
         'Site_ID_10',
         'Site_ID_11',
         'Site_ID_12',
         'Site_ID_13',
         'Site_ID_14',
         'Site_ID_15']

**导入和查看数据。**在用 unique Site ID分割数据之前,我只是确保数据如上所述在那里。我确保Site ID没有空值,并且我还确保我可以捕获每个时间戳的索引或引用。这对于在过程结束时将所有东西粘在一起是至关重要的。

building = **file_loader**(building)
weather_train_data = **file_loader**(weather_train_data)
data_train = **file_loader**(data_train)
weather_test_data = **file_loader**(weather_test_data)
data_test = **file_loader**(data_test)

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

图 1.1。部分数据来自 Part-1-Divide.ipynb Jupyter 笔记本。

减少数据内存。这些文件非常大!光是 T2 的文件就超过了 1 GB。因此,我需要找到一种方法来减少这些文件的内存,而不丢失有用的信息。我在 Kaggle 讨论板上发现了一些非常有用的数据缩小策略,我认为它们不仅对这个项目,而且对未来的项目都非常有用。本质上,您可以通过搜索数据类型并分别对其进行更改,将数据减少到最少的信息量。当您试图一次运行所有数据来训练 ML 模型时,为了保持脚本运行并且不使您的计算机崩溃,这是绝对必要的。我在余下的工作流程中使用了这个策略。

building = **reduce_mem_usage**(building)
weather_train_data = **reduce_mem_usage**(weather_train_data)
weather_test_data = **reduce_mem_usage**(weather_test_data)
data_train = **reduce_mem_usage**(data_train)
data_test = **reduce_mem_usage**(data_test)

合并数据。在我把主要文件简化成最小的有用形式后,我把它们合并在一起。

merge()

data_train**.merge**(building, on=’building_id’, how=’left’)
data_train**.merge**(weather_train_data,
                  on=[‘site_id’,‘timestamp’], how=’left’)data_test**.merge**(building, on=’building_id’, how=’left’)
data_test**.merge**(weather_test_data,
                  on=[‘site_id’,‘timestamp’], how=’left’)

划分&导出数据。pickle功能是在这些文件合并和分离后导出它们的一个很好的工具。

count=0
for Split_Number in list(Splits): 
    dummy = data_train[(data_train[‘site_id’]==count)]
    # OUTPUTS: Folder for storing OUTPUTS
    print(Split_Number)
    dummy.to_pickle(os.path.join(OUTPUT_split_path[count],
                    ‘site_id-{}-train.pkl’.format(count)))
count+=1

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

图 2.0Part-2-and . ipynb .流程图

第二部分。探索性数据分析和清理

我开始盲目地研究这个问题,没有看讨论板。这让我走上了一条痛苦的道路,寻找并试图理解如何处理缺失和零值数据。然而,这并没有走多远,因为原始数据是如此的杂乱和庞大。

于是,我开始阅读人们对大量杂乱数据所做的工作,并发现了几种解决方法。人们很快指出他们发现的异常值:

  1. 建造前显示电表读数的建筑物。⁰
  2. 长时间的持续读数。
  3. 大正负尖峰。
  4. 具有在相同频率下出现仪表读数异常的建筑物的站点。
  5. 一般来说,建筑物缺少数据或值为零(这是我马上注意到的一个明显的问题)。

对于缺失的数据,我做了这个小函数,missing_table,为了捕捉和总结。

missing_table()

**def** **missing_table(**data_name**):**
    non_null_counts = data_name.count() 
    null_counts = data_name.isnull().sum() 
    total_counts = non_null_counts+null_counts
    percent_missing= round(100*null_counts/total_counts,1)
    min_non_null = data_name.min()
    median_non_null = data_name.quantile(q=0.5)
    max_non_null = data_name.max()
    missing_data=pd.concat([total_counts,non_null_counts,
                            null_counts,percent_missing,
                            min_non_null,median_non_null,
                            max_non_null],axis=1,keys=   
                       ['Total Counts','Non-Null Counts',
                       'Null Counts','Percent Missing(%)',
                       'Non-Null Minimum','Non-Null Median',
                       'Non-Null Maximum'])
    **return** missing_data

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

图 2.1。站点 ID 15 中缺失数据表摘要的示例。有很多数据缺失!

我是如何处理这些混乱的?良好的…我首先对数据进行了每小时一次的向上采样,因为这是数据以原始形式出现的最频繁的时间。但是这样做会增加更多的空值,因为它会为未记录的小时数创建时间戳。因此,我做了以下工作,通过一系列的删除、填充空值、插值、向前填充、向后填充以及最后再次填充空值来填充这些空白和之前缺失的大量内容。

**重采样(“H”)。**均值()

我对数据进行了向上采样,取平均值,然后按其独特的building_idmetersite_idprimary_usesquare feet进行分组。这为其他项目如air_temperaturedew_temperaturewind_speed等留出了一些空间。不过这不是问题。插值将处理大部分这些差距。

pd.to_datetime(data_train["timestamp"],format='%Y-%m-%d %H')
data_train=data_train.set_index('timestamp')

pd.to_datetime(data_test["timestamp"],format='%Y-%m-%d %H')
data_test=data_test.set_index('timestamp') grouplist=['building_id','meter','site_id',
           'primary_use','square_feet']

data_train.groupby(grouplist)**.resample('H').mean()**
data_train.drop(grouplist,axis=1)

data_test.groupby(grouplist)**.resample('H').mean()**
data_test.drop(grouplist,axis=1)

dropna()

如果一个列有我认为太多丢失的数据,我会将其删除。因此,对于一个站点中丢失数据超过 40%的列,我执行了以下操作:

thresh = len(data_train)*.6
data_train**.dropna**(thresh = thresh, axis = 1, inplace = True)

thresh = len(data_test)*.6
data_test**.dropna**(thresh = thresh, axis = 1, inplace = True) 

菲尔娜()

当对数据进行上采样时,我不想失去对索引的跟踪,因此,我通过将新值设置为-1 来跟踪原始索引以供参考。

data_train['index']**.fillna**(-1, inplace = True)
data_test['index']**.fillna**(-1, inplace = True)

内插()

以下连续参数因缺失值而被插值。

data_train['meter_reading']**.interpolate()**
data_train['air_temperature']**.interpolate()**
data_train['dew_temperature']**.interpolate()**
data_train['cloud_coverage']**.interpolate()**
data_train['precip_depth_1_hr']**.interpolate()**
data_train['sea_level_pressure']**.interpolate()**       data_train['wind_direction']**.interpolate()**data_test['air_temperature']**.interpolate()**
data_test['dew_temperature']**.interpolate()**
data_test['cloud_coverage']**.interpolate()**
data_test['precip_depth_1_hr']**.interpolate()**
data_test['sea_level_pressure']**.interpolate()**       data_test['wind_direction']**.interpolate()**

pad()

通常在这一点上不会丢失太多数据。这个前向填充函数, pad() ,通常得到最后一位。它使用最后一个已知的值,如果缺少该值,则将其向前移动到下一个值。

grouplist=['building_id','meter','site_id',
           'primary_use','square_feet']data_train=data_train.groupby(grouplist)**.pad()**
data_test=data_test.groupby(grouplist)**.pad()**

isnull()

此时,我将使用 isnull() 函数来检查我是否遗漏了什么。如果是,我就用之前的 fillna() 带中值或者完全丢弃。此外,我还在 Jupyter 笔记本上记下了每个站点的 ID,以备不时之需。

data_train.isnull().sum()
data_test.isnull().sum()

好了,现在数据至少是完整的了。离群值呢?

我主要做了两件事:

  1. 降低了超出正常值的仪表读数(峰值)。

我认为它们会使我们很难做出一个精确的 ML 模型,因为还有很多其他的假设。

data_train.drop((data_train.loc[data_train['meter_reading']> 1.5e+04])['meter_reading'].index)

2.降低了零值仪表读数。

我认为这些应该是数据,或者它们是在前面的步骤中填充的,因为那里实际上什么也没有。这在后来可能有点多余,但至少是包容性的。

data_train.drop((data_train.loc[data_train['meter_reading']== 0])['meter_reading'].index)

现在我们可以看到一些东西了!

很难查看混乱且缺少大量值的数据。既然数据已经清理完毕,我只想验证一下。这里有几幅图显示了几个站点的air_temperature分布。你可以看到这些地方有他们自己的季节,可能在地理上有不同的气候。请注意,位置 13 为左偏斜,位置 12 为正常,位置 14 为双峰分布。

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

图 2.1。一些不同地点的气温数据显示了它们独特的分布。

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

图 3.0Part-3-convert . ipynb流程图。

第三部分。特征工程、特征提取和机器学习。

特征工程()

**def** **feature_engineering(**data**)**:
    data[**"hour"**] = data["timestamp"].dt.hour
    data[**"week"**] = data["timestamp"].dt.week
    data[**"month"**] = data["timestamp"].dt.month
    data[**"weekday"**] = data["timestamp"].dt.weekday data[**'Sensible_Heat'**] = 0.5274*(10.**
    (-4.))*data['square_feet']*(75.-data['air_temperature'])

    data[**'log_square_feet'**] = np.log(data['square_feet'])
    data[**'log_floor_count'**] = np.log(data['floor_count'])

    data[**'square_dew_temperature'**]    
    =np.square(data['dew_temperature'])

    *# Holidays*
    holidays = ["2016-01-01", "2016-01-18", "2016-02-15", "2016-05-30", "2016-07-04",
            "2016-09-05", "2016-10-10", "2016-11-11", "2016-11-24", "2016-12-26",
            "2017-01-01", "2017-01-16", "2017-02-20", "2017-05-29", "2017-07-04",
            "2017-09-04", "2017-10-09", "2017-11-10", "2017-11-23", "2017-12-25",
            "2018-01-01", "2018-01-15", "2018-02-19", "2018-05-28", "2018-07-04",
            "2018-09-03", "2018-10-08", "2018-11-12", "2018-11-22", "2018-12-25",
            "2019-01-01"]
    data["**is_holiday"**] =(data.timestamp.dt.date.astype("str").isin(holidays)).astype(int)

    **return** data

大多数人似乎把工程师的使用时间放在他们一边。例如,一年中的星期是与目标能量使用有很强相关性的常见特征。这是有意义的,因为一年有冬天和夏天之类的季节,而周数(即 52 周中的 51 周,冬季周)会告知你处于哪个季节。我使用了其中的一些时间策略,但是在问题的机械工程方面更深入了一些。我将所有这些基本特征视为我在日常工程生活中使用和处理的方程的输入。我想我可以设计一些可能与目标结果有关系的新功能。

因此,我钻研了热力学和暖通空调的定律。

我们希望根据建筑使用数据和环境天气数据,预测给定电表的能源使用量。了解所涉及的因素以及它们之间的关系非常重要。

大图观点来自热力学第一定律:

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

等式 1。热力学第一定律。

其中:

  • 问:系统是否增加了热量
  • w 是系统做的功
  • δU 是内能的变化。

因此,这些建筑根据环境条件(即air temperaturedew temperaturewind_speedwind_directioncloud_coverage)改变它们添加或移除的热量,需要能量形式的工作(电、蒸汽等)。

每栋建筑与热力学第一定律之间的一个重要联系是建筑的供暖、通风和空调(HVAC) 单元。

影响这些 HVAC 装置添加或移除热量的效率的因素可能与建筑物的年龄有关(year_built)。由于过时的 HVAC 设备,旧建筑在添加或移除热量方面可能效率较低(除非它们被翻新!).如果暖通空调系统多年来没有得到适当的维护,那么它可能会由于制冷剂或气流问题而产生不像正常情况下那么多的冷空气。

基于房间居住者显热的排热通风率可表示为:

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

等式 2a。排热的房间通风率。

其中:

  • q_dot是房间的显热去除率。
  • rho是房间的平均空气密度。
  • cp是室内空气的恒定比热。
  • Vroom是房间的体积。
  • Tid是房间的室内设计温度(通常为 75 华氏度)。
  • Tin是进入室内空气的温度。

因此,由于更多的人和更大的空气量,更大的建筑可能需要更多的能源或 HVAC 容量。建筑物内的空气体积与房间的数量及其各自的体积成正比。因此,建筑的平方英尺(square_feet)与建筑空气量成正比,而建筑空气量与通风所需的显热移除量成正比。然而,所需的最小通风率取决于建筑类型和各个房间的独特要求,如 ASHRAE 标准 62.1 中所述。对于粗略的比例关系,我们可以在此基础上设计一个新变量qs,即每栋建筑的显热去除率,如下所示:

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

等式 2b。显热去除的特征工程步骤概要。

尽管有标准! ASHRAE 标准 62.1 ,规定了所需的呼吸区室外空气(即呼吸区的室外通风空气)Vbz,作为区域占用量Pz和区域占地面积Az的函数。⁶第一项(RpAz)说明了占用产生的污染物,而第二项(RaAz)说明了建筑产生的污染物。ASHRAE 标准 62.1 要求在所有负载条件下运行期间保持以下速率:

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

等式 3。ASHRAE 标准 62.1 最低要求呼吸区室外空气流速。⁶

其中:

  • Vbz是呼吸区所需的最小室外空气流量
  • Rp是人室外空气流速
  • Pz是区域占用
  • Ra是该区域的室外空气流速
  • Az为分区建筑面积。

因此,每栋建筑(building_id)可能都有其自己独特的设计要求,这是基于通用的 ASHRAE 62.1 标准。进入该标准的输入是基于占据该房间的设计人数和被占据的建筑或房间的类型。例如,一个Educational区域可能需要一个10 cfm/person,而一个Office Building区域可能需要该房间中的5 cfm/person。⁶:这意味着我们可以根据建筑类型来预测不同的能源使用组合(primary_usesite_id)。

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

图 3.1。最终运行中不同站点 ID 结果的特征重要性图。

拆分数据

我对数据进行了分割,以便在每个季节捕捉一部分数据,用机器学习(ML)算法进行训练和验证。所以冬天是 1 月(1)攻陷,春天是 4 月(4)攻陷,夏天是 7 月(7)攻陷,秋天是 10 月(10)攻陷。因为我们有如此多的数据,我进一步把它分成两半。因此,其中一半的测试月被用于培训。根据Site_ID的不同,这在 75%到 90%的训练范围内,这在 80%的经验法则范围内。这是一个时间序列回归问题,因此重要的是不要在一个月内获得所有数据,也不要因为过度拟合而过于频繁。我相信我分割它的方式是一个公平的方法,因为只有全年的训练数据。它大致等间隔地预测未来两年。

final_test = test

test = train[(train['timestamp'].dt.month.isin([1,4,7,10]))]

train_w, test = train_test_split(test,test_size=.50,random_state=42)

train = train[(train['timestamp'].dt.month.isin([2,3,5,6,8,9,11,12]))]

train=pd.concat([train,train_w],axis=0)

缩放数据

我使用了minmax scaler()为 ML 算法获取 0 到 1 之间的值。我意识到使用standard scaler()可能会更好,因为可能会有异常值。

*#Scale Data*
scalerTrain = MinMaxScaler(feature_range=(0,1))

X_train=scalerTrain.fit_transform(X_train)
X_test=scalerTrain.transform(X_test) 
X_final_test=scalerTrain.transform(X_final_test)

机器学习用light GBM

在最终决定使用 LightGBM 回归器之前,我尝试使用随机森林回归和 XGBoost 回归器。从我的初步运行来看,随机森林的准确性要差得多,训练的时间也要长得多。XGBoost 不如 LightGBM 精确,而且耗时更长。针对这些问题的培训可能需要几个小时,这取决于如何设置。

最初,当我把所有的数据都扔给算法时,需要一夜的时间,通常我的内核会崩溃。我甚至上了谷歌云平台,开始从云端运行模型。连那些内核都崩溃了…哈哈。这是另一个原因,我决定去与 16 个不同的模型更小。这些数据对我来说是可以管理的。我可以看到我在做什么,并且在需要的时候可以修理东西。我还可以完成工作,而不会让我的计算机从所有的 RAM 分配到本地运行中变慢到停止。

所以我最终微调了一些超参数,但可能还不够好。主要是因为做这些事花了这么长时间。但是在我写这篇文章的时候,我看到了我的跑垒和上一次跑垒之间的巨大进步。基本上,我的基本跑的均方根对数误差(RMSLE)是 1.566,我的最终跑是 1.292(好了大约 20%)。我知道这些分数不是最大的,但这不是整件事的重点,因为这是后期比赛。这是一次学习经历。

我对 LightGBM 的最佳超参数是:

best_params = {
    "objective": "regression",
    "boosting": "gbdt",
    "num_leaves": 1500,
    "learning_rate": 0.05,
    "feature_fraction": ([0.8]),
    "reg_lambda": 2,
    "num_boost_round": 300, 
    "metric": {"rmse"},
}

我将已经像前面提到的那样分割的训练数据分割成 3 个 K 倍,用于训练/验证,如下所示:

kf = KFold(n_splits=3,shuffle=**False**)
count =0
models = []
**for** params **in** list(params_total):
    print('Parms: ',count )
    **for** train_index,test_index **in** kf.split(features_for_train):
        train_features = features_for_train.loc[train_index]
        train_target = target.loc[train_index]

        test_features = features_for_train.loc[test_index]
        test_target = target.loc[test_index]

        d_training = lgb.Dataset(train_features, 
                                 label=train_target, 
                                 free_raw_data=**False**)
        d_test = lgb.Dataset(test_features, 
                             label=test_target,
                             free_raw_data=**False**)

        model = lgb.train(params, 
                          train_set=d_training, 
                          valid_sets=[d_training,d_test], 
                          verbose_eval=100, 
                          early_stopping_rounds=50)   

        models.append(model)
    count += 1

然后我在测试集上预测(不是最终测试集!),该模型的性能如何,如下所示。注意,因为有 3 个折叠,所以产生了 3 个优化的最佳模型(best_iteration)。因此,对我来说,最后的结果是基于这三个的平均值。

我在最后的测试中使用了相同的方法,这意味着在训练/验证之后,我没有改变我使用的模型。我只是看了看下面显示的数字,看看模型在我可以与之比较的数据上的表现如何,然后再扔向我无法与之比较的数据(看不见的未来测试数据,2017 年至 2019 年)。他们看起来表现很好!RMSLE 小于 1,对于大多数 all (>0.9),相关系数很强。

results = []
**for** model **in** models:
    **if**  results == []:
        results = np.expm1(model.predict(features_for_test, num_iteration=model.best_iteration)) / len(models)
    **else**:
        results += np.expm1(model.predict(features_for_test, num_iteration=model.best_iteration)) / len(models)

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

图 3.2。用 LightGBM 对实际目标测试数据与预测值进行线性回归比较。

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

图 4.0Part-4-all siteids . ipynb 流程图

4.结果和结论

第四部分。一起评估所有模型。

所以…现在是时候总结所有 16 个site_id预测的所有结果了。

count=0
**for** Split_Number **in** list(Splits):  
        dummy= os.path.join(OUTPUT_split_path[count],
              "test_Combined_Site_ID_**{}**.csv".format(count)) dummy2 = pd.DataFrame(file_loader(dummy))

        **if** count == 0:
                    test_Combined = dummy2
        **else**:
                    test_Combined = 
                    pd.concat([test_Combined,dummy2],axis=0)
        count+=1

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

图 4.1。显示出比跑垒有进步。

就像前面提到的,RMSLE 有了很大的提高,公开分数和私人分数都提高了近 20%。显然,进一步调整 ML 超参数和数据清理可能有助于获得更好的分数。我觉得印象比较深刻的是下图!

那么…这些数字到底是什么样子的呢?!

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

图 4.2 每个站点 ID 上所有建筑物的所有仪表读数的平均每小时消耗量(kWh)。

**嗷。我认为那看起来令人印象深刻!这是我们在训练模型时不知道的未来两年(红线),从直觉上看,这非常合理。蓝色的线显示了我们对数据的预测,这看起来也是合理的。**我认为我们可以有把握地说,我们可以制作机器学习(ML)模型来预测建筑物未来的能源使用。多么有趣又刺激的项目啊!在这次旅行中,我学到了很多东西,也学到了很多我不知道的东西。感谢您的阅读!

5.参考

  1. ASHRAE。关于 ASHRAE。从 https://www.ashrae.org/about检索到 2020 年 1 月
  2. 卡格尔。ASHRAE-大能量预测三(2019)。从https://www.kaggle.com/c/ashrae-energy-prediction/overview检索到 2020 年 1 月
  3. ASHRAE。ASHRAE 技术委员会 4.7 数据驱动建模(DDM)分委员会:能量计算
  4. 辛伯贝斯特。新加坡伯克利建筑在热带地区的效率和可持续性
  5. 巴德实验室。建筑和城市数据科学
  6. 德克萨斯 A&M 大学工程实验站
  7. ASHRAE 竞赛管理小组成员 Chris Balbach 先生
  8. 杰夫·哈伯博士,ASHRAE 竞赛管理团队成员
  9. Krishnan Gowri 博士,ASHRAE 竞赛管理团队成员
  10. 沃帕尼,卡格尔笔记本,“ASHRAE:一半一半。”从https://www.kaggle.com/rohanrao/ashrae-half-and-half检索到 2020 年 1 月
  11. 凯撒勒普姆,卡格尔笔记本,“ASHRAE——从这里开始:一个温和的介绍。”2020 年 1 月检索自https://www . ka ggle . com/caesarlupum/ASHRAE-start-here-a-gentle-introduction
  12. CeasarLupum,Kaggle 笔记本,“ASHRAE—lightgbm simple Fe。”2020 年 1 月检索自https://www . ka ggle . com/caesarlupum/ASHRAE-ligthgbm-simple-Fe
  13. 罗曼,卡格尔笔记本,“埃达为 ASHRAE。”从https://www.kaggle.com/nroman/eda-for-ashrae#meter检索到 2020 年 1 月
  14. Sandeep Kumar,“ASHRAE-KFold light GBM-无泄漏(1.08)”2020 年 1 月检索自https://www . ka ggle . com/ai tude/ASHRAE-kfold-light GBM-without-leak-1-08
  15. SciPy。保利·维尔塔宁、拉尔夫·戈默斯、特拉维斯·奥列芬特、马特·哈伯兰、泰勒·雷迪、戴维·库尔纳波、叶夫根尼·布罗夫斯基、皮鲁·彼得森、沃伦·韦克塞、乔纳森·布赖特、斯蒂芬·范德沃特、马修·布雷特、约书亚·威尔逊、贾罗德·米尔曼、尼古拉·马约罗夫、安德鲁·纳尔逊、埃里克·琼斯、罗伯特·克恩、埃里克·拉森、希杰·凯里、i̇lhan·波拉特、余峰、埃里克·摩尔、杰克·范德普拉斯、丹尼斯·拉克萨尔德、约瑟夫·佩尔(2019)SciPy 1.0-Python 中科学计算的基本算法。预印本 arXiv:1907.10121
  16. Python。特拉维斯·奥列芬特。用于科学计算的 Python,《科学与工程中的计算》, 9,10–20(2007 年 b) K. Jarrod Millman 和 Michael Aivazis。面向科学家和工程师的 Python,科学与工程中的计算,13,9–12(2011)
  17. NumPy。特拉维斯·奥列芬特。美国 NumPy 指南:特雷戈尔出版公司(2006 年)。(b)斯蒂芬·范德沃特、克里斯·科尔伯特和盖尔·瓦洛夸。NumPy 数组:高效数值计算的结构,科学与工程中的计算,13,22–30(2011)
  18. IPython。费尔南多·佩雷斯和布莱恩·格兰杰。IPython:用于交互式科学计算的系统,科学与工程中的计算,9,21–29(2007)
  19. Matplotlib。亨特,“Matplotlib:2D 图形环境”,《科学与工程中的计算》,第 9 卷,第 3 期,第 90–95 页,2007 年。
  20. 熊猫。韦斯·麦金尼。Python 中统计计算的数据结构,第 9 届科学中的 Python 会议录,51–56(2010)
  21. sci kit-学习。法比安·佩德雷戈萨、加尔·瓦洛夸、亚历山大·格拉姆福特、文森特·米歇尔、贝特朗·蒂里翁、奥利维尔·格里塞尔、马蒂厄·布隆德尔、彼得·普雷登霍弗、罗恩·韦斯、文森特·杜伯格、杰克·范德普拉斯、亚历山大·帕索斯、戴维·库尔纳波、马蒂厄·布鲁彻、马蒂厄·佩罗特、爱德华·杜谢斯奈。sci kit-learn:Python 中的机器学习,机器学习研究杂志,12,2825–2830(2011)
  22. sci kit-图像。斯蒂芬·范德沃特、约翰内斯·l·舍恩伯格、胡安·努涅斯-伊格莱西亚斯、弗朗索瓦·布洛涅、约书亚·d·华纳、尼尔·雅戈、伊曼纽尔·古亚尔特、托尼·于和 scikit-image 供稿者。sci kit-Image:Python 中的图像处理,PeerJ 2:e453 (2014)
  23. 作者:Plotly Technologies Inc .书名:协作数据科学出版社:Plotly Technologies Inc .出版地点:马萨诸塞州蒙特利尔出版日期:2015 URL: https://plot.ly
  24. 越来越多的建筑产生越来越通用的模型——基于开放电表数据的基准预测方法。马赫。学习。知道了。Extr。2019, 1, 974–993.
  25. W.Hedén,“使用随机森林和支持向量回归预测每小时住宅能耗:分析家庭聚类对性能准确性的影响”,学位论文,2016 年。
  26. 林德堡,迈克尔 R. 机械工程参考手册。第十三版。,专业出版物,2013。
  27. ASHRAE。技术资源,“消费者应该知道的关于空调的十大事情。”2020 年 1 月检索自https://www . ASHRAE . org/technical-resources/free-resources/十大空调消费者须知
  28. NZ,“按仪表类型对齐时间戳-LGBM”2020 年 1 月检索自https://www . ka ggle . com/NZ 0722/aligned-timestamp-lgbm-by-meter-type
  29. 卡格尔。ASHRAE-大能量预测三(2019)-讨论板。“对于数据泄露将采取什么措施?”检索 2020 年 1 月[https://www . ka ggle . com/c/ASHRAE-energy-prediction/discussion/116739](http://ASHRAE-Great Energy Predictor III (2019). Retrieved January, 2020)
  30. 卡格尔。ASHRAE-大能量预测三(2019)-讨论板。"在建成之前消耗能源的建筑."检索到 2020 年 1 月。https://www . ka ggle . com/c/ASHRAE-energy-prediction/discussion/113254
  31. 卡格尔。ASHRAE-大能量预测三(2019)-讨论板。“第一名解决方案团队 Isamu & Matt。”检索到 2020 年 1 月。https://www . ka ggle . com/c/ASHRAE-energy-prediction/discussion/124709
  32. 康斯坦丁·雅科夫列夫。卡格尔笔记本,“ASHRAE——数据缩小”检索到 2020 年 1 月。https://www.kaggle.com/kyakovlev/ashrae-data-minification
  33. 效率评估组织。国际性能测量和验证协议。可在线查询:https://Evo-world . org/en/products-services-main menu-en/protocols/IP MVP(2020 年 1 月 26 日访问)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值