自然语言处理中使用约束波束搜索的智能解释
原文:https://towardsdatascience.com/smart-paraphrasing-using-constrained-beam-search-in-nlp-9af6fd046e5c
套用保留搜索引擎优化和文案的特定关键字

来自 Pixabay 的无版权图片
Huggingface 最近在变形金刚库中引入了带有约束波束搜索的引导文本生成。
您可以使用受约束的波束搜索来指导哪些单词需要包含在解码的输出文本中。
这在文案和 SEO 中有一些有趣的用例。
用例 1: SEO(搜索引擎优化)
例如,如果你正在写一篇关于**“模因营销”**的文章,你想要确保“模因营销”这个词在整个博客或文章中被多次使用,以便它在谷歌搜索(SEO)中排名更高,并在该主题上建立权威。
这个概念叫做**“关键词填充”**,当然需要适度使用,不要显得垃圾。所以这促使我们使用“模因营销”这个短语,即使我们是在转述,也不要改变它。因此,在这种情况下,有必要重写(意译)任何旧的内容,保持短语“模因营销”完好无损。
这是一个完美的受约束的 beam 用例,在你想要解释的地方搜索,同时在解释的版本中保持一个短语或关键字不变。
通常,SEO 专家会识别出长尾关键词,即搜索量较好但相关结果较少的小众短语(例如:平足的最佳跑鞋),并在其上撰写文章。这有助于他们在谷歌搜索中排名更快,并在第一页显示他们的网站。有时,他们想改写自己写的一句话,但又想原封不动地保留“平足的最佳跑鞋”等短语。
用例 2:文案
文案是为任何营销材料撰写内容,无论是博客、网站、传单等。
有效的文案写作是理解人类的心理,并写一个文案,推动客户走向最终目标,如推动注册,销售产品等。
让我们来看看 Marketingexamples.com 的一个文案技巧,建议使用简单的语言而不是多余的语言。
例如,如果我们将登录页面复制为“通过构建真实项目增强您的前端技能”,则建议可以将像 Supercharge、unleash、exceed、empower 这样的登录页面单词替换为更简单的单词,听起来更自然、更真实。
因此,在我们的例子中,我们理想地将这句话解释为“通过构建真正的项目增强你的前端技能”,但是使用词语**“改进”**听起来更自然。
这也是约束波束搜索的一个完美用例,我们可以将**“改进”**作为强制字。

作者图片
输入和输出
我们的解释模型的输入将是-
**Supercharge your data science skills by building real world projects.**
带波束搜索的解释器输出(无约束):
**1\. By implementing real world projects, you can improve your data science skills.
2\. By implementing real world projects, you can boost your data science skills.
3\. By implementing real world projects, you can enhance your data science skills.**
如果我们用强制字**【提高】**,则转述输出带约束的光束,搜索结果是:
**1\. By implementing real world projects, you can improve your data science skills.
2\. By executing real world projects, you can improve your data science skills.
3\. Build real world projects to improve your data science skills.**
你可以看到“**improve”**在每个句子中生成,因为我们限制了对它的波束搜索。
项目
现在让我们进入项目的编码部分!这里,我们将使用我们上面讨论的文案示例,并使用约束波束搜索来解释我们的原始句子。
这里可以找到 colab 笔记本。
- 在 Google Colab 中安装必要的库
**!pip install -q sentencepiece
!pip install -q transformers==4.18.0**
2.下载我们为 SaaS 应用 Questgen 训练的和开源的转述器模型。这个转述器只被训练来转述短句,所以适用于转述标题等。
将模型加载到 GPU 内存中。
**import torch****from transformers import AutoTokenizer, AutoModelForSeq2SeqLM****model = AutoModelForSeq2SeqLM.from_pretrained("ramsrigouthamg/t5-large-paraphraser-diverse-high-quality")
tokenizer = AutoTokenizer.from_pretrained("ramsrigouthamg/t5-large-paraphraser-diverse-high-quality")****device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print ("device ",device)
model = model.to(device)**
现在让我们运行波束搜索和约束波束搜索,输入句子**“通过构建真实世界的项目来增强您的数据科学技能。”**和 force_word “提高”。
**# Copy writing example - Use a given word in paraphrasing****context = "Supercharge your data science skills by building real world projects."
force_words = ["improve"]****text = "paraphrase: "+context + " </s>"****input_ids = tokenizer(text,max_length =128, padding=True, return_tensors="pt").input_ids
input_ids = input_ids.to(device)****# Beam search****outputs = model.generate(
input_ids,
num_beams=10,
num_return_sequences=3,
max_length=128,
early_stopping=True,
no_repeat_ngram_size=1,
remove_invalid_values=True,
)****print ("\nNormal beam search\n")
print ("Original: ",context)
for beam_output in outputs:
sent = tokenizer.decode(beam_output, skip_special_tokens=True,clean_up_tokenization_spaces=True)
print (sent)****# Constrained Beam search****force_words_ids = tokenizer(force_words, add_special_tokens=False).input_ids****outputs = model.generate(
input_ids,
force_words_ids=force_words_ids,
max_length=128,
early_stopping=True,
num_beams=10,
num_return_sequences=3,
no_repeat_ngram_size=1,
remove_invalid_values=True,
)****print ("\nConstrained beam search\n")
print ("Original: ",context)
for beam_output in outputs:
sent = tokenizer.decode(beam_output, skip_special_tokens=True,clean_up_tokenization_spaces=True)
print (sent)**
这是输出结果:
**Normal beam search****Original: Supercharge your data science skills by building real world projects.
paraphrasedoutput: By implementing real world projects, you can improve your data science skills.
paraphrasedoutput: By implementing real world projects, you can boost your data science skills.
paraphrasedoutput: By implementing real world projects, you can enhance your data science skills.****Constrained beam search****Original: Supercharge your data science skills by building real world projects.
paraphrasedoutput: By implementing real world projects, you can improve your data science skills.
paraphrasedoutput: By executing real world projects, you can improve your data science skills.
paraphrasedoutput: Build real world projects to improve your data science skills.**
您可以看到,常规波束搜索的输出仅在生成的一个的中包含“改进”,而它出现在约束波束搜索生成的所有三个句子中。
结论:
条件文本生成一直是语言模型文本生成中的一个活跃的研究领域,我们希望将输出导向生成某些关键字或主题。随着在 HuggingFace 中引入约束波束搜索,我们已经向那个目标迈进了一步。
在许多文本生成应用中,如翻译、图像字幕、释义等,我们经常会遇到在生成的输出文本中使用/保留某个关键字/关键短语的需要。
无论是 SEO 还是文案,我们都需要在转述时保持某个关键字/关键短语不变,我们需要强制某个关键字出现以适应文案意图的语气,我们在本教程中已经看到了几个现实世界中的约束波束搜索用例。
祝 NLP 探索愉快,如果你喜欢它的内容,请随时在 Twitter 上找到我。
如果你想学习使用变形金刚的现代自然语言处理,看看我的课程使用自然语言处理的问题生成
智能道路:人工智能在交通中如何保护司机安全
原文:https://towardsdatascience.com/smart-roads-how-ai-in-transportation-keeps-drivers-safe-98e4dfd4a7e8

Marc-Olivier Jodoin 在 Unsplash 上拍摄的照片
道路技术已经成熟了吗?我们已经看到了非常光滑和耐用的沥青,它适用于任何运输类型。这条路还能怎么改善?
例如,温哥华提议在沥青中加入可回收的塑料颗粒,这样可以增加沥青的耐久性,并允许在重铺路面时部分重复使用。但它只是改善了现有的路面。下一个里程碑是什么?
人工智能在交通领域的运用让他们变得“聪明”。对道路使用者意味着什么?
重新定义未来的道路
许多国家已经在实施与智能城市相关的项目,以改变、简化人们的生活并改善基础设施,包括交通。智能基础设施是全球智能城市市场的最大部分。Statista 估计其收入将在 2025 年超过 1030 亿美元。
人口以及汽车、自行车、摩托车和公共交通数量的持续增长引发了交通问题,增加了事故和交通拥堵的风险。
根据世卫组织的统计,每年大约有 130 万人死于交通事故。死亡不取决于年龄、性别、经济或社会地位。超速、分心驾驶、酒精、手机——任何,甚至是轻微的分心因素——都可能导致不可挽回的灾难。
智能道路提高了能见度,与自动驾驶和互联车辆进行交互,并控制路线,使驾驶体验更加安全。
他们使用许多智能设备:
- 速度和声音传感器
- IP 闭路电视摄像机
- 智能交通灯和路灯
- 条件和天气监控系统
- 数字标牌
人工智能智能道路使用来自数千个摄像头,检测器,交通灯和停车计时器的交通数据,主要是为了减少车祸,提高道路效率,缓解拥堵,并从长远来看,帮助城市规划者消除瓶颈。
将如何改善交通体验?
- 道路压力传感器有助于实时测量车辆的重量和速度,以执行交通法规。
- 智能交通标志指导司机如何更安全、更高效地使用道路。该技术可以发送语音信息,告诉智能汽车司机应该遵循什么,以避免与多个交通标志混淆。
- 采用速度摄像头的交通管理网络将通过及时提醒司机危险情况并发送自动交通转换信号进行交通管制,来提高道路安全并减少拥堵。例如,车辆可以改变路线,以防止像雪堆这样的情况。
- 使用监控摄像头或智能车辆数据的智能交通灯将收集道路和十字路口的当前交通数据。根据这些信息,他们将根据路况变化管理信号。例如,优先安排急救车辆,如救护车和消防车,这样就不会有人在此刻过马路或占用车道。
人工智能与交通管理
智慧城市概念对交通管理提出了新的要求。它涉及交通繁忙的十字路口,那里经常发生拥堵和事故。简单的交通灯不足以进行交通流量分配,相反,我们需要适应道路上特定情况的系统。这是人工智能在大都市和小城镇广泛使用的地方,成功地在具有挑战性的驾驶情况下保持交通流量。
联合国通过了一项关于安全道路运输的决议,该决议强调了创新汽车和数字技术的作用,并符合联合国秘书长的数字合作路线图。该倡议还应有助于到 2030 年将全球道路交通伤亡人数减半,并确保获得安全、负担得起和可持续的运输系统。
Itransition 的创新分析师安德烈·科普特洛夫(Andrey Koptelov)表示:“事实证明,交通领域的人工智能能够让我们比以往任何时候都更快、更安全、更清洁”。
“GPS、传感器、计算机视觉驱动的摄像机和其他互联的物联网设备被部署来收集关于天气、交通、堵塞或事故的数据。然后,这些工具与基于人工智能的分析系统相结合,处理这些信息,通过机器学习算法识别重复出现的交通模式,并将数据转化为有价值的路线建议或潜在道路拥堵预测,”他补充道。
智能交通管理系统
智能交通管理系统(ITMS)的使用不仅限于监测和报告交通拥堵。该系统确保了交通的效率和安全。
ITMS 提供必要的实时信息,以减少乘客的旅行时间,提高驾驶员的安全性和舒适性。例如,它可以与现有的视频监控系统配合工作,对违反交通法规的车辆进行检测和分类。因此,交通违规者可以依法得到交通罚单。
此外,ITMS 还通过以下方式帮助控制交通流量、减少拥堵和预防事故:
- 监控十字路口移动车辆和行人之间的距离;
- 阅读车牌;
- 检测闯红灯、超速、驾驶不当和丢失安全带。
交通灯控制系统
很久以前,交通灯是手动控制的,使用定时器来平稳运行。今天,它们在机器上运行。然而,我们可以让交通灯更有效地工作,更智能地管理时间。
比如人工智能分析视觉信息,定义特定时间道路某一部分的交通拥堵情况。在十字路口交通管制的情况下,计算机统计车辆,确定它们的类型和速度,然后选择交通灯的最佳操作。
自动距离识别
自动距离识别(ADR)使用传感器来确定车辆与前方物体之间的距离。主要目标是防止拥挤的交通。众多汽车制造商提供 ADR 系统,包括特斯拉、沃尔沃和梅赛德斯-奔驰。
安全和紧急情况
当紧急情况发生时,紧急服务需要迅速有效地采取行动,以确保所有公民的安全。ITMS 自动调节信号灯,提醒司机注意分心的事物。新系统有助于快速过渡到救护车和消防车等紧急车辆。它还可以在即将发生拥堵时警告驾车者改道。
人工智能摄像机如何防止道路交通事故
道路监控和交通管理应用程序使用来自数千个交通摄像头和视频监控系统的数据。与传统的计算机视觉方法相比,人工智能提供了更好的传感性能,通过自动适应不断变化的照明和天气条件的算法,提供了对所有道路使用者更可靠和准确的跟踪。
交通摄像头中的人工智能将更准确地模拟所有用户的运动和行为,从行人和骑自行车的人到公共汽车和卡车,以及新的交通工具,如电动滑板车,这些都可能导致额外的道路事故。
装有智能夜视摄像头的车辆给司机多了一双眼睛来监控路况。这些摄像头很容易检测到交通威胁,包括动物、行人和其他车辆。
人工智能数字录像机(DVR)改善了视觉感知。他们可以识别物体与驾驶员的相关性,并采取必要的预防措施,建议减速、改变方向或继续行驶。即使没有特殊标记,智能夜视仪表盘也能为驾驶员提供安全路线。
澳大利亚 Acusensus 将人工智能应用于道路安全问题。他们的摄像头使用高分辨率图像来检测危险的驾驶模式,跟踪和记录车内的行为。
AI Aware 是沃尔沃、HERE、Carmenta Automotive、爱立信、Zenseact、Trafikverket 和瑞典运输协会之间的合作项目。AI Aware 使用人工智能算法来预测一辆车与另一辆车、行人或物体相撞的风险,然后发出警告以防止事故发生。
与此同时,西班牙一直在城市公交车上测试计算机视觉技术,以绘制道路上车辆和行人可能发生问题的位置,从而确定最高的事故风险。在这里,计算机视觉使用人工智能来理解来自公交车摄像头的原始视频数据,这些数据记录了道路位置、行人和车辆位置以及行驶速度。
底线
交通领域的人工智能有助于提高乘客安全,减少交通事故和拥堵。今天的技术让我们习惯于更谨慎地驾驶,从而提供了舒适的驾驶和更高的道路安全性。人工智能智能道路提醒司机遵守特定的交通规则,保持车辆之间的安全距离,防止与行人相撞,保持在正确的车道上,并采取一切必要的预防措施。创新越多,人工智能就越重视安全,帮助司机管理拥堵的道路并意识到危险。
来源列表:
- https://www . statista . com/statistics/1111642/world wide-smart-city-market-revenue-segment/
- https://royal society publishing . org/doi/10.1098/rspa . 2019.0439
- https://singularityhub . com/2020/01/29/how-smart-roads-will-make-driving-easy-safe-and-green/
- https://www . Intel . co . uk/content/www/uk/en/transportation/smart-road-infra structure . html
- https://www . who . int/news-room/fact-sheets/detail/road-traffic-injuries
- https://press.un.org/en/2022/ga12432.doc.htm
- https://vrio Europe . com/en/smart-road-technology-digital-highways-of-the-future/
- https://www . McKinsey . com/~/media/McKinsey/industries/automotive % 20 and % 20 assembly/our % 20 insights/the % 20 road % 20 to % 20 artificial % 20 intelligence % 20 in % 20 mobility % 20 smart % 20 moves % 20 required/smart-moves-required-the-road-on-artificial-intelligence-in-mobility . pdf
- https://www . science direct . com/science/article/pii/s 2215098621000872
- https://www . Intel . com/content/www/us/en/transportation/urban-mobility . html
吸烟贝叶斯符合逻辑回归
贝叶斯推理结合广义线性模型比较吸烟者和非吸烟者死亡率的例子

我没有发现 Bayes 是否吸烟的信息。然而,我可以通过结合先验知识(当时男性吸烟的比例)和数据(画像上的他不吸烟)来估计他是吸烟者的概率。作者图片
前段时间在看抽烟:数据集(这个数据集原来是在的 mosiac R 包里找到的。)在 calmcode.io 上的系列视频。他们向你展示如何分析和比较吸烟者和非吸烟者的 10 年死亡率。(注意,不是吸烟的影响——而是作为一名吸烟者——因为吸烟者的生活方式与那些除了吸烟以外在其他方面没有区别的人不同。)
在这篇文章中,我将使用贝叶斯推理和一个广义线性模型,来计算与 calmcode 的视觉方法相比,作为一个吸烟者的影响。首先,让我们看看他们发现了什么。
视觉方法
吸烟数据集中的每一行代表一个人,她是否吸烟,十年后是否还活着。
[library](https://rdrr.io/r/base/library.html)([tidyverse](https://tidyverse.tidyverse.org))
[library](https://rdrr.io/r/base/library.html)(rethinking)
[library](https://rdrr.io/r/base/library.html)([tidybayes.rethinking](http://mjskay.github.io/tidybayes.rethinking))
[library](https://rdrr.io/r/base/library.html)([tidybayes](https://mjskay.github.io/tidybayes/))
df_raw <- readr::[read_csv](https://readr.tidyverse.org/reference/read_delim.html)("smoking.csv", col_types = "cfi")
df <- df_raw [%>%](https://magrittr.tidyverse.org/reference/pipe.html)
[transmute](https://dplyr.tidyverse.org/reference/mutate.html)(
age,
is_smoker = smoker,
is_dead = [if_else](https://dplyr.tidyverse.org/reference/if_else.html)(outcome == "Dead", 1L, 0L)
)[head](https://rdrr.io/r/utils/head.html)(df_raw)# A tibble: 6 × 3
outcome smoker age
<chr> <fct> <int>
1 Alive Yes 23
2 Alive Yes 18
3 Dead Yes 71
4 Alive No 67
5 Alive No 64
6 Alive Yes 38
我们还稍微调整了数据集,并将其保存到df。这将在以后派上用场。从现在开始,我们将关注死亡率而不是存活率。
最基本(也是最天真)的方法是计算每种吸烟状态的死亡率。
df [%>%](https://magrittr.tidyverse.org/reference/pipe.html)
[group_by](https://dplyr.tidyverse.org/reference/group_by.html)(is_smoker) [%>%](https://magrittr.tidyverse.org/reference/pipe.html)
[summarise](https://dplyr.tidyverse.org/reference/summarise.html)(death_rate = [mean](https://rdrr.io/r/base/mean.html)(is_dead))# A tibble: 2 × 2
is_smoker death_rate
<fct> <dbl>
1 Yes 0.239
2 No 0.314
哇,似乎吸烟者的死亡率更低!但是…我们不会因为年龄而“控制”。让我们比较一下每个年龄组的死亡率:
df_agg <- df [%>%](https://magrittr.tidyverse.org/reference/pipe.html)
[mutate](https://dplyr.tidyverse.org/reference/mutate.html)(round_age = plyr::[round_any](https://rdrr.io/pkg/plyr/man/round_any.html)(age, 10)) [%>%](https://magrittr.tidyverse.org/reference/pipe.html)
[group_by](https://dplyr.tidyverse.org/reference/group_by.html)(round_age, is_smoker) [%>%](https://magrittr.tidyverse.org/reference/pipe.html)
[summarise](https://dplyr.tidyverse.org/reference/summarise.html)(death_rate = [mean](https://rdrr.io/r/base/mean.html)(is_dead), .groups = "drop")[ggplot](https://ggplot2.tidyverse.org/reference/ggplot.html)(df_agg, [aes](https://ggplot2.tidyverse.org/reference/aes.html)(round_age, death_rate, color = is_smoker)) +
[geom_line](https://ggplot2.tidyverse.org/reference/geom_path.html)() +
[labs](https://ggplot2.tidyverse.org/reference/labs.html)(
title = "Mortality rates of smokers are higher for all age groups",
y = "10-year mortality rate",
x = "Age group"
)

作者图片
这就展现了一个完全不同的画面!在所有年龄组中,吸烟者的死亡率都较高。之前,由于数据集中吸烟者和不吸烟者的年龄比例不同,我们得到了不同的汇总结果。这就是著名的辛普森悖论。
Calmcode 视频到此为止。但是我想知道,如果没有宁滨时代,如何更精确地估计差异?
贝叶斯方法
我们将使用带有二项式可能性的广义线性模型。在我们的案例中,当数据被组织到单个试验案例中时(无论该人是否在未来 10 年内死亡),该模型的通用名称是逻辑回归。我们将使用 logit link 对年龄和死亡率之间的关系进行建模。为了确保所有的p值从[∞,∞]映射到[0,1],这种转换是必要的,否则我们在定义先验时必须小心。
这里是logit(p) ~ age在图上的样子:
[ggplot](https://ggplot2.tidyverse.org/reference/ggplot.html)(df_agg, [aes](https://ggplot2.tidyverse.org/reference/aes.html)(round_age, logit(death_rate), color = is_smoker)) +
[geom_line](https://ggplot2.tidyverse.org/reference/geom_path.html)() +
[labs](https://ggplot2.tidyverse.org/reference/labs.html)(
title = "We will approximate logit(p) ~ age with linear function.",
y = "logit(10-year mortality rate)",
x = "Age group"
)

作者图片
通过观察该图,我们似乎可以将logit(death_rate)建模为某一年龄死亡率的线性组合(截距)和代表死亡率随年龄变化的斜率。两组的斜率似乎也是一样的。
由此,我们可以为我们的模型构建一个公式列表并运行它:
formulas <- [alist](https://rdrr.io/r/base/list.html)(
is_dead ~ [dbinom](https://rdrr.io/r/stats/Binomial.html)(1, p),
logit(p) <- a[is_smoker] + b * (age - 60),
a[is_smoker] ~ [dnorm](https://rdrr.io/r/stats/Normal.html)(-0.3, 0.25),
b ~ [dnorm](https://rdrr.io/r/stats/Normal.html)(0.1, 0.05)
)
model <- [ulam](https://rdrr.io/pkg/rethinking/man/ulam.html)(formulas, data = df, warmup = 200, iter = 500, chains = 4, cores = 4)
我来解释一下formulas:
is_dead遵循 1 次试验的二项分布(也称为伯努利分布),而p代表成功的概率(在我们的例子中,成功等于未来 10 年的死亡)。- 关联函数
logit(p)是十年死亡率的线性组合,取决于一个人是否吸烟,由截距a表示,斜率b在吸烟者和非吸烟者之间共享。基于上面的情节,我决定使用这样的模型。logit(death_rate)似乎与年龄呈线性相关。两组的斜率似乎是相同的。唯一不同的是截距。我决定在 60 岁而不是 0 岁时计算,因为这更直观,而且该模型对低年龄没有意义。 - 代表两组 60 岁死亡率的截距
a的先验值相同。这是基于目测,但它足够广泛,在有意义的范围内。我也可以从其他在线数据集中重用它。 - 斜率的先验
b也是基于目测,但也可以从在线数据集提前确定,在理想情况下更严格。
在查看模型之前,让我们仔细检查一下先验知识:
prior <- [extract.prior](https://rdrr.io/pkg/rethinking/man/extract.samples.html)(model, n = 200)[tibble](https://tibble.tidyverse.org/reference/tibble.html)(
sample = 1:200,
a = prior$a[,1], # you get two priors for intercepts (one for each group) but they are the same
b = prior$b
) [%>%](https://magrittr.tidyverse.org/reference/pipe.html)
tidyr::[crossing](https://tidyr.tidyverse.org/reference/expand.html)(age = [min](https://rdrr.io/r/base/Extremes.html)(df$age):[max](https://rdrr.io/r/base/Extremes.html)(df$age)) [%>%](https://magrittr.tidyverse.org/reference/pipe.html)
[mutate](https://dplyr.tidyverse.org/reference/mutate.html)(p = [pmap_dbl](https://purrr.tidyverse.org/reference/map2.html)([list](https://rdrr.io/r/base/list.html)(a, b, age), \(a, b, age) [inv_logit](https://rdrr.io/pkg/rethinking/man/rethinking-internal.html)(a + b * (age - 60)))) [%>%](https://magrittr.tidyverse.org/reference/pipe.html)
[ggplot](https://ggplot2.tidyverse.org/reference/ggplot.html)() +
[geom_line](https://ggplot2.tidyverse.org/reference/geom_path.html)([aes](https://ggplot2.tidyverse.org/reference/aes.html)(age, p, group = sample), alpha = 0.2) +
[geom_point](https://ggplot2.tidyverse.org/reference/geom_point.html)(data = df_agg, [aes](https://ggplot2.tidyverse.org/reference/aes.html)(round_age, death_rate, color = is_smoker)) +
[labs](https://ggplot2.tidyverse.org/reference/labs.html)(title = "Priors seem fine", y = "10-year mortality rate")

作者图片
前科看起来不错——信息足够丰富,但也很灵活。链的跟踪和 trank 图看起来也不错——你必须相信我。
以下是该模型的摘要:
[summary](https://rdrr.io/r/base/summary.html)(model)Inference for Stan model: 49f5d62bf6172f02e3638f3ae2372250.
4 chains, each with iter=500; warmup=200; thin=1;
post-warmup draws per chain=300, total post-warmup draws=1200.mean se_mean sd 2.5% 25% 50% 75% 97.5%
a[1] -0.04 0.00 0.12 -0.26 -0.13 -0.05 0.04 0.20
a[2] -0.20 0.00 0.10 -0.39 -0.26 -0.20 -0.14 0.01
b 0.12 0.00 0.01 0.11 0.12 0.12 0.13 0.14
lp__ -474.88 0.06 1.23 -478.10 -475.46 -474.57 -473.98 -473.49
n_eff Rhat
a[1] 627 1
a[2] 678 1
b 1177 1
lp__ 494 1
Samples were drawn using NUTS(diag_e) at Mon Jan 10 19:35:02 2022.
For each parameter, n_eff is a crude measure of effective sample size,
and Rhat is the potential scale reduction factor on split chains (at
convergence, Rhat=1).
我们可以看到,与不吸烟者的截距a[2]相比,吸烟者的截距a[1]具有更高的死亡率。我们可以使用tidybayes软件包中的便捷函数绘制这两个参数的整体分布图(已经转换为 60 岁时的死亡率)及其差异:
samples_a <- model [%>%](https://magrittr.tidyverse.org/reference/pipe.html)
[recover_types](http://mjskay.github.io/tidybayes/reference/recover_types.html)(df) [%>%](https://magrittr.tidyverse.org/reference/pipe.html)
[spread_draws](http://mjskay.github.io/tidybayes/reference/spread_draws.html)(a[is_smoker]) [%>%](https://magrittr.tidyverse.org/reference/pipe.html)
[mutate](https://dplyr.tidyverse.org/reference/mutate.html)(p = [inv_logit](https://rdrr.io/pkg/rethinking/man/rethinking-internal.html)(a)) [%>%](https://magrittr.tidyverse.org/reference/pipe.html)
[bind_rows](https://dplyr.tidyverse.org/reference/bind.html)(., [compare_levels](http://mjskay.github.io/tidybayes/reference/compare_levels.html)(., p, by = is_smoker)) [ggplot](https://ggplot2.tidyverse.org/reference/ggplot.html)(samples_a, [aes](https://ggplot2.tidyverse.org/reference/aes.html)(p, is_smoker)) +
[stat_halfeye](http://mjskay.github.io/ggdist/reference/stat_sample_slabinterval.html)() +
[labs](https://ggplot2.tidyverse.org/reference/labs.html)(title = "Posterior distributions for intercepts and their difference")

作者图片
这些分布基于后验样本。有了它们,我们还可以计算出不吸烟者死亡率较低的概率:
samples_a [%>%](https://magrittr.tidyverse.org/reference/pipe.html)
[filter](https://dplyr.tidyverse.org/reference/filter.html)(is_smoker == "No - Yes") [%>%](https://magrittr.tidyverse.org/reference/pipe.html)
[summarise](https://dplyr.tidyverse.org/reference/summarise.html)(prob = [mean](https://rdrr.io/r/base/mean.html)(p < 0))# A tibble: 1 × 2
is_smoker prob
<chr> <dbl>
1 No - Yes 0.845
吸烟者有 85%的几率会有更高的死亡率。我们还可以看到死亡率的差异是如何随年龄变化的(注意,差异的形状是由我们的模型定义的,而不是大小):
newdata <- tidyr::[crossing](https://tidyr.tidyverse.org/reference/expand.html)(
age = 20:90,
is_smoker = [unique](https://rdrr.io/r/base/unique.html)(df$is_smoker)
)linpreds <- [add_linpred_draws](http://mjskay.github.io/tidybayes/reference/add_predicted_draws.html)(model, newdata = newdata, value = "p") linpreds [%>%](https://magrittr.tidyverse.org/reference/pipe.html)
[group_by](https://dplyr.tidyverse.org/reference/group_by.html)(age, .draw) [%>%](https://magrittr.tidyverse.org/reference/pipe.html)
[summarise](https://dplyr.tidyverse.org/reference/summarise.html)(
p_diff = p[is_smoker == "Yes"] - p[is_smoker == "No"]
) [%>%](https://magrittr.tidyverse.org/reference/pipe.html)
[ggplot](https://ggplot2.tidyverse.org/reference/ggplot.html)([aes](https://ggplot2.tidyverse.org/reference/aes.html)(x = age)) +
[stat_lineribbon](http://mjskay.github.io/ggdist/reference/stat_lineribbon.html)([aes](https://ggplot2.tidyverse.org/reference/aes.html)(y = p_diff), .width = 0.9, fill = "gray") +
[labs](https://ggplot2.tidyverse.org/reference/labs.html)(
title = "Mean difference in mortality rate with 90% credible interval",
subtitle = "Shape of the difference was imposed by our model.",
y = "Difference in 10-year mortality rate with 90% CI"
)

作者图片
60 岁左右人群的 10 年死亡率似乎平均增加了约 4%(90%可信区间在 10%和-2.5%之间),年龄越小死亡率越低。这可能是有道理的:
- 对于年轻人来说,吸烟的影响还没有那么大(而且他们的死亡率也更低);
- 即使不吸烟,老年人也更容易死亡。
我们可以通过除以而不是减去死亡率来计算死亡率的相对上升。在这种情况下,年轻人的相对上升幅度约为 20%,然后开始缓慢下降,在 60 岁时约为 10%,然后几乎可以忽略不计。
我们还可以看到所有年龄组中两组死亡率的 90%可信区间:
[ggplot](https://ggplot2.tidyverse.org/reference/ggplot.html)(linpreds, [aes](https://ggplot2.tidyverse.org/reference/aes.html)(x = age, color = is_smoker, fill = is_smoker)) +
[stat_lineribbon](http://mjskay.github.io/ggdist/reference/stat_lineribbon.html)([aes](https://ggplot2.tidyverse.org/reference/aes.html)(y = p), .width = 0.9, alpha = 0.5) +
[geom_point](https://ggplot2.tidyverse.org/reference/geom_point.html)(data = df_agg, [aes](https://ggplot2.tidyverse.org/reference/aes.html)(x = round_age, y = death_rate)) +
[labs](https://ggplot2.tidyverse.org/reference/labs.html)(
title = "Mortality rate ~ age with 90% credible intervals",
y = "10-year mortality rate"
)

作者图片
结论
使用logit链接函数使我们能够将伯努利变量p (10 年死亡率)建模为年龄的线性函数。另一方面,贝叶斯方法使我们能够获得参数值的分布——对于任何年龄和吸烟状态。我们可以按照我们喜欢的方式进行汇总:这是否是吸烟者死亡率更高的可能性,死亡率(差异)的可信区间(最终有意义的置信区间)……
贝叶斯推理和广义线性模型代表了一种灵活而强大的组合。但是,正确地指定模型背后的假设(公式集)是我们的责任。从这些发现中学习——所以,不要吸烟。并使用吸烟贝叶斯。
通气管——构建训练数据的人在回路平台
原文:https://towardsdatascience.com/snorkel-programmatically-build-training-data-in-python-712fc39649fe
停止手工标记您的数据。而是以编程方式对其进行标记
动机
想象一下,你试图判断一份招聘启事是不是假的。你想出了一些关于虚假招聘的假设,比如:
- 几乎没有描述要求的招聘信息很可能是假的。
- 没有公司简介或标识的招聘信息很可能是假的。
- 一份需要一些教育或经验的工作很可能是真实的。
如何测试这些特征在预测欺诈方面的准确性?如何将不同要素的冲突预测合并到一个标注中?

作者图片
这时候浮潜就派上用场了。
什么是浮潜?
snuck是一个开源的 Python 库,用于以编程方式构建训练数据集,无需手动标记。有了通气管,用户可以在几小时或几天内创建一个训练数据集,而不是在几周或几个月内手动标记它们。
通气管支持不同的操作,但本文将只回顾标记操作。
要安装通气管,请键入:
pip install snorkel
加载数据
我们将在 Kaggle 的数据集真实/虚假职位发布预测上使用浮潜来预测职位发布是虚假还是真实。I 对数据进行预处理,并将其分成训练集和测试集。
让我们看看训练数据集是什么样的:
import pandas as pd
train_df = pd.read_pickle("https://github.com/khuyentran1401/Data-science/blob/master/feature_engineering/snorkel_example/train_fake_jobs.pkl?raw=true")
test_df = pd.read_pickle("https://github.com/khuyentran1401/Data-science/blob/master/feature_engineering/snorkel_example/test_fake_jobs.pkl?raw=true")
train_df
fraudulent栏表示招聘信息是否是假的。
现在我们有了数据,我们如何给每个招聘信息贴标签呢?
创建标签功能
让我们根据对假公司的假设创建标签函数:
- 假公司没有公司简介或标识
- 真正的公司需要背景调查
- 真正的公司需要一定的经验或教育水平
让我们使用 scupco 的labeling_function装饰器来测试这些假设。labeling_function装饰器允许我们使用函数快速标记数据集中的实例。
from snorkel.labeling import labeling_function
# Give a meaningful name to each value
FAKE = 1
REAL = 0
ABSTAIN = -1
# Create labeling functions
@labeling_function()
def no_company_profile(x: pd.Series):
return FAKE if x.company_profile == "" else ABSTAIN
@labeling_function()
def no_company_logo(x: pd.Series):
return FAKE if x.has_company_logo == 0 else ABSTAIN
@labeling_function()
def has_background_check(x: pd.Series):
return REAL if "background check" in x.requirements else ABSTAIN
@labeling_function()
def required_experience(x: pd.Series):
return REAL if x.required_experience else ABSTAIN
@labeling_function()
def required_education(x: pd.Series):
return REAL if x.required_education else ABSTAIN
关于上述标签功能的详细信息:
- 每个函数都试图根据一些条件来确定样本是否是假的。
ABSTAIN或-1表示预测是不确定的。
对数据应用标注函数
让我们使用这些标注函数来标注我们的训练数据集:
lfs = [
no_company_profile,
no_company_logo,
has_background_check,
required_experience,
required_education,
]
applier = PandasLFApplier(lfs=lfs)
L_train = applier.apply(df=train_df)
查看训练数据集:
# Get the shape
>>> L_train.shape
(13410, 5)
# View the first two samples
>>> L_train[0:2]
array([[-1, -1, -1, 0, 0],
[-1, -1, -1, -1, -1]])
L_train的第一维是样本数。L_train的第二维度是来自五个标记函数的预测。
使用真实标签评估标签功能
既然我们已经使用每个标注函数创建了标签,那么我们如何确定这些标签的准确性呢?有了LFAnalysis,这可以很快完成。
让我们将预测与实际标签进行比较,以评估每个标签功能:
from snorkel.labeling import LFAnalysis
LFAnalysis(L=L_train, lfs=lfs).lf_summary(Y=train_df.fraudulent.values)

上表中的详细统计数据:
- 极性:该 LF 输出的唯一标签集合(不包括弃权)
- 覆盖率:数据集被标记的部分
- 重叠:这个 LF 和至少一个其他 LF 一致的数据集部分
- 冲突:该 LF 与至少一个其他 LF 不一致的数据集部分
- 修正:该 LF 标注的数据点数正确
- 不正确:该 LF 标注的数据点数不正确
- 经验精度:该 LF 的经验精度,通过以下公式计算:

作者图片
从表中可以看出has_background_check、required_experience、required_education标注函数的精度都在 0.95 以上。
如果不进行测试,我们就无法猜测这些特征是虚假招聘的有力证据。
评估没有真实标签的标签功能
在评估没有真正标签的标签功能时,通气管也是理想的选择。
LFAnalysis(L=L_train, lfs=lfs).lf_summary()

评估冲突
我们可以看到标签功能之间存在一些冲突。这可能意味着一个标注函数预测一个职位发布是假的,而另一个标注函数预测一个职位发布是真的。
可能会有一些招聘广告要求特定的经验,但没有公司的标志。让我们用get_label_buckets找到这些招聘信息。
from snorkel.analysis import get_label_buckets
buckets = get_label_buckets(L_train[:, 1], L_train[:, 3])
train_df.iloc[buckets[(FAKE, REAL)]].sample(10, random_state=1)[
["has_company_logo", "required_experience", "fraudulent"]
]
上表可以看出,很多公司要求具体经验,但是没有公司 logo。这导致了两个标记函数之间的预测差异。
组合预测
在本节中,您将学习两种在不同标注函数的预测不一致时组合它们的方法。

作者图片
多数标签投票人
一个简单的方法是使用多数票。如果有两个1s和一个0,那么预测将是1。

作者图片
如果没有连接,忽略-1(无标签)。

作者图片
如果有平局,则返回-1。

作者图片
让我们尝试一下这个标签模型,看看它在测试集上的表现如何:
from snorkel.labeling.model import MajorityLabelVoter
# Create the model
majority_model = MajorityLabelVoter()
preds_train = majority_model.predict(L=L_train)
# Get test predictions
L_test = applier.apply(df=test_df)
# Get train and test labels
Y_train = train_df["fraudulent"]
Y_test = test_df["fraudulent"]
# Evaluate
majority_acc = majority_model.score(L=L_test, Y=Y_test)[
"accuracy"
]
print(f"{'Majority Vote Accuracy:':<25} {majority_acc * 100:.1f}%")
Majority Vote Accuracy: 80.7%
成绩还算不错!
标签模型
注意,MajorityLabelVoter没有考虑不同标记函数的变化统计以及这些函数之间的相关性。如果两个特征高度相关,特定信号将在基于多数投票的模型中被过度表示。
LabelModel通过产生噪声感知训练标签来更恰当地处理这些问题。你可以在本文中了解更多关于LabelModel的信息。
from snorkel.labeling.model import LabelModel
label_model = LabelModel(cardinality=2, verbose=True)
label_model.fit(L_train=L_train, n_epochs=500, log_freq=100, seed=1)
# Evaluate the model
label_model_acc = label_model.score(L=L_test, Y=Y_test)["accuracy"]
print(f"{'Label Model Accuracy:':<25} {label_model_acc * 100:.1f}%")
Label Model Accuracy: 72%
LabelModel的精确度不如MajorityLabelVoter的精确度。然而,在不同的数据集或不同的标记函数集中,LabelModel可能比MajorityLabelVoter执行得更好。
结论
恭喜你!您刚刚学会了使用不同的标注函数进行快速测试,并使用通气管为您的训练数据集创建标注。我希望这篇文章能激励你自动化你的标注过程,而不是花费数周或数月来手工标注你的数据。
随意发挥,并在这里叉这篇文章的源代码:
https://github.com/khuyentran1401/Data-science/tree/master/feature_engineering/snorkel_example
我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 Twitter 上与我联系。
如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:
[## 使用 dirty_cat 对脏类别进行相似性编码
towardsdatascience.com](/similarity-encoding-for-dirty-categories-using-dirty-cat-d9f0b581a552)
参考
Shivam Bansal 。2020–02–29.真/假职位发布预测。
CC0:公共领域。从https://www . ka ggle . com/shivamb/true-or-fake-fake-job posting-prediction检索 2022–01–25。
针对用户、角色和权限的雪花最佳实践
原文:https://towardsdatascience.com/snowflake-best-practices-for-users-roles-and-permissions-3cd9d286b82a
正确设置数据仓库的指南

在 Unsplash 上由Towfiqu barb huya拍摄的照片
数据仓库中的安全性是雪花架构中最重要的部分,也是经常被搁置的部分。很多时候,我们认为它没有数据本身重要。然而,设置正确的角色和权限是保持数据完整性的关键。从一开始就对此进行配置可以确保防止出现问题。
让我描述一下可能会出错的地方。您可以在 Snowflake 中创建一个角色,供业务中的所有用户使用。分析师、营销人员和工程师对每个数据库都有相同类型的访问权限。您有一个用于一次性分析的报告和数据分析(RDA)数据库,以及一个存储所有原始数据的数据库。一名营销人员正在寻找一份在 RDA 数据库中运行的报告,但意外地在原始数据库上运行了一个命令。他们覆盖数据,现在原始数据永远消失了。
你明白了。不是组织中的每个人都知道如何使用雪花或者正确地查询数据。您希望降低风险,以便他们可以使用这些数据,而您可以放心地生活,知道它是安全的。
当配置您的雪花环境时,我发现从创建您的用户开始更容易,然后使用用户来确定您的环境所需的雪花角色。在这里,您可以创建相应的仓库,并重置每个用户的默认值。让我们从创建我们的用户开始。
用户管理
**每个访问你的数据仓库的人和工具都应该有自己的用户。**这意味着分析师 Josh 需要自己的雪花用户,工程师 Sarah 需要自己的用户,连接到您的数据仓库的每个工具都需要自己的用户。这将严格控制谁有权访问某些资源。它还允许您跟踪信用使用情况和所做的更改。
让每个人和工具都有自己的用户名和密码是最佳的安全做法。这样,密码就不会到处乱放,而且你知道每个人都可以访问你公司的数据。此外,请记住,您可能不希望公司的每个人都可以访问雪花。
创建用户
要在雪花中创建用户,请运行以下命令:
CREATE USER <user’s name> PASSWORD=<dummy password> DEFAULT_ROLE=<role name> DEFAULT_WAREHOUSE=<warehouse name> MUST_CHANGE_PASSWORD=true
创建用户时,您必须为他们分配一个临时密码。出于安全目的,请确保设置 MUST_CHANGE_PASSWORD=true。这将强制用户在首次登录时更改密码。您也可以在用户界面上这样做,只需选中底部的复选框:

作者图片
但是,如果您正在为工具创建用户,您不希望选择此项。例如,如果您使用 Airbyte 作为您选择的数据集成工具,您将创建一个用户 AIRBYTE_USER。您不希望选中需要更改密码的复选框。该工具无法在登录时更改其密码,因此请确保您从一开始就为其分配了安全密码,并将其存储在 1Password 等密码管理器应用程序中。
请注意,在使用命令创建用户时,我还设置了某些默认值,如角色和仓库。这很重要,尤其是当用户第一次学习如何使用雪花的时候。他们可能不明白如何改变自己的角色或使用正确的角色。为他们分配一个默认角色,以帮助管理他们拥有的权限。例如,分析师将最经常地分析数据,因此他们的默认角色应该是与报告相关的角色,即使他们有时可能会转换数据。
设置默认仓库
您还需要设置一个默认仓库来帮助管理数据仓库的成本和使用。这不一定是一项安全功能,但它将帮助您了解您的雪花积分被用于何处。为用户分配与其角色相关的仓库。接下来我们将更多地讨论具体的角色。
您创建的仓库应该与您创建的角色相匹配。这意味着,对于每一个角色,你都应该有一个对应的仓库。我有一个“加载 _WH”,“转换 _WH”,“分析 _WH”,“报告 _WH”。每个仓库对应于我将在下一部分中提到的角色。这将有助于组织资源,并允许您跟踪数据管道的哪些部分使用了最多的雪花配额。
角色管理
我们刚刚讨论了与您应该设置的默认仓库相关的角色,但是您首先应该在您的仓库中创建什么角色呢?在这里,我们将讨论不同类型的角色以及他们应该拥有的特定权限。虽然这因业务而异,并且取决于访问您的仓库的用户类型,但原则是相同的。
在深入研究角色类型和应该授予它们的权限之前,让我们简单讨论一下我是如何组织我的雪花数据仓库的。我有一个原始数据库,它吸收了我所有的原始数据。我的基本数据库从这个原始数据库中读取数据,以创建供我的数据模型使用的视图。然后我有了 DATA_MART_DEV 和 DATA_MART_PROD 数据库,用于在开发和生产中运行我的核心数据模型。最后,我有一个用于一次性报告和查询的 RDA(报告和数据分析)数据库。你可以在这里阅读更多关于我为什么这样组织我的雪花数据仓库的信息。
现在,我们来谈谈角色吧!
角色类型
最佳实践是为组织内的摄取工具、分析师、工程师和业务用户创建不同的角色。您还可以为 BI 工具或者反向 ETL 工具(如果您使用的话)创建特定的角色。为每个用户和工具创建不同的角色将允许您控制每个用户在每个数据库及其模式中可以做什么和不可以做什么。
摄取工具权限:
- 获取原始数据
- 可以查看、选择和创建 RAW
是的,你没看错——你的摄取工具应该有自己的角色!这是应该允许写入原始数据库的唯一角色。您的摄取工具是唯一应该在原始数据位置创建模式和表的工具。绝不允许公司内的任何人写入此内容。
摄取工具是将原始数据写入数据库的唯一方法。
这是数据库中最重要的角色,因为它拥有访问原始数据的能力。您的原始数据需要尽可能地安全,因为所有数据模型的完整性都依赖于它。如果公司内部的人在戳戳这些原始数据,你永远无法确定它是 100%准确的。这一角色的存在增加了人们对该数据可靠性的信心。
我将这个角色称为“加载器”,因为它是将原始数据加载到您的数据仓库中的工具。这是在将数据源中的数据接收到雪花中时,您将为 Airbyte 提供的角色。你可以阅读更多关于为了正确使用 Airbyte 你需要给角色的特定权限的信息。为特定工具创建角色时,阅读该工具文档中的需求总是很有帮助的。

作者图片
Airbyte 提供了一个脚本来设置所有需要的权限,以便该工具将数据接收到您的仓库中。
分析工程师权限:
- 访问 RAW、BASE、DATA_MART_DEV、DATA_MART_PROD 和 RDA
- 可以从原始、基本和数据集市产品中查看和选择
- 可以在 DATA_MART_DEV 和 RDA 中查看、选择和创建
分析工程师,或者任何编写 dbt 数据模型的人,应该是唯一能够访问原始数据库的人。但是,他们应该只能查看和选择,而不能创建或删除。这样他们就无法更改原始数据。
在我的数据仓库中,我将这个角色称为“转换器”。它由转换数据的人和工具使用。具有此角色的用户有权从原始数据库中读取数据,并向存储模型的所有其他数据库中写入数据。
分析师权限:
- 对 BASE、DATA_MART_PROD 和 RDA 的访问
- 可以查看和选择基本数据和数据集市产品
- 可以在 RDA 中查看、选择和创建
因为分析师不创建基础模型,他们没有理由访问原始数据。他们需要的所有东西都应该放在基地里,减少意外删除原始数据的风险。此外,他们应该只拥有对 BASE 和 DATA_MART_PROD 的查看和选择权限,因为他们只是在查询中选择这些内容,而不是写入这些内容。
我把这个角色叫做“分析者”。他们不直接在数据仓库中转换任何数据,而是使用数据模型运行查询,并将它们写入“RDA”。
业务用户权限:
- 对 BASE、DATA_MART_PROD 和 RDA 的访问
- 可以查看并从中选择
业务用户应该能够查看数据和进行基本选择,但不能以任何方式修改数据。
我称这个角色为“报告者”,因为这个角色仅仅是报告数据,而不是写数据。Tableau 和 Looker 等数据可视化工具也使用这个角色。
创建角色和分配权限
为了在雪花中创建角色,您可以运行以下命令:
CREATE_ROLE <role_name>;
为了向雪花中的角色授予权限,您可以运行以下命令:
GRANT <privledge> to ROLE <role_name>;
最后,确保将您的角色分配给适当的用户。您可以通过以下方式实现:
GRANT ROLE <role_name> to USER <user_name>;
雪花的权限层次结构
您需要授予数据库、模式、表/视图和未来的表/视图一定的权限。Snowflake 的权限是独一无二的,因为您不能将权限分配给数据库,并期望它也应用于数据库中的模式和表/视图。

作者图片
授予数据库权限
首先,让我们回顾一下您可以在数据库级别授予角色的最重要的权限。
- 监视器允许角色查看对象的详细信息;您需要将此权限授予所有希望查看数据库的角色。
- 用法允许角色使用数据库;您需要将此权限授予任何希望查询数据库的角色。
- CREATE 授予角色在数据库中创建对象的能力。这对于在数据库“BASE”、“DATA_MART_DEV”和“DATA_MART_PROD”上分配您的 TRANSFORMER 角色非常重要。您的 LOADER 角色应该被授予“RAW”权限,而 ANALYZER 角色应该被授予“RDA”权限。
向架构授予权限
现在,让我们回顾一下模式级别的重要权限。
- 同样,您需要将数据库中模式的 MONITOR 权限授予角色。
- 用法允许角色使用架构;您需要将此权限授予任何希望查询模式的角色。
- CREATE 也存在于模式级别。您需要将它分配给我上面提到的数据库中模式的所有角色。

作者图片
授予表和视图权限
最后,这是事情变得不同的地方。表和视图拥有来自数据库和模式的独有特权。
- SELECT 允许角色从表或视图中进行选择。您会希望将它分配给允许查询某个对象的每个角色。
- INSERT 和 DELETE 都是应该授予您的 TRANSFORMER 角色在“DATA_MART_DEV”和“DATA_MART_PROD”上的权限。因为这是分配给 dbt 用户的角色,所以它需要能够对表进行更改。dbt 需要这些权限来运行增量模型。请记住,这些权限只适用于表,不适用于视图。
对于表、视图和模式,您还需要确保对模式或数据库中的未来表和视图授予权限。这将使您不必对创建的新对象授予访问权限。
-- for tables
grant select on future tables in schema FACEBOOK to role ANALYZER;-- for views
grant select on future schemas in database BASE to role TRANSFORMER;
结论
在运行任何雪花命令之前,最好记录您的雪花架构,尤其是每个角色的权限。如果您没有清楚地记录每件事,授予权限可能会令人困惑。我知道当你认为你已经授予了所有需要的权限,然后一个角色仍然不能访问你需要的权限时,会很沮丧。
慢慢来。不要因为沮丧就授予一个角色所有可用的权限。记录良好的雪花用户、角色和权限是安全数据仓库的关键。随着您的组织的成长,并且开始越来越依赖于您已经建立的数据生态系统,最初的工作会有很长的路要走。
更多分析工程领域的最佳实践,订阅我的时事通讯。
所以,你认为你可以数据科学?这里有 4 件事你应该知道。
一些你应该知道的关于荣耀领域的重要事实。

“哦,哇,你在研究数据科学?你已经准备好了。”
当我不情愿地默认人们关于我在攻读博士学位的问题时,我经常得到这样的回答。如果不是口头上的,那就用眼神。从技术上讲,我的项目叫做以人为中心的设计和工程,但我花了大部分时间来磨练我的数据科学技能,因为这是我的主要研究兴趣。
虽然我真诚地感谢人们的赞美,但我也认为它们源于对整个数据科学的误解。我不是天才,我认为自己很幸运能参加这个项目——我每天都在尽可能多的学习。在此过程中,我发现了一些关于数据科学的重要事实,我认为这个领域应该有更多的人知道。
在本文中,我将讨论数据科学幕后的一些鲜为人知的现实——我希望通过阅读它,您可以更清楚地了解进入该领域的真正意义。
1.不仅仅是“数据科学家”
数据科学的核心是一项简单的任务:从数据中获得更清晰的洞察力。这绝不是一个简单的或独特的技术技能。它包括许多不同的活动部分,并且从许多不同的学科中汲取灵感。
仅仅因为某人没有“数据科学家”的正式头衔并不意味着他们没有研究数据科学。根据它的定义,这个领域需要许多不同类型的工作者的帮助才能繁荣。以下是它们的随机样本(是的,那是数据科学参考):
- 数据工程师:研究如何清理、存储和处理数据的基础设施。没有他们,有效和高效的数据科学几乎是不可能的。
- UX 的研究人员:使用定量和定性技术的结合来收集关于产品用户的信息,并使用他们的发现来提出改进建议,以增强用户体验[2]。
- 统计学家:他们是一群人中在数学方面有天赋的。如果你需要从头开始开发一个机器学习模型,或者找出正确的超参数来使用,是时候召集统计学家了。
- 社会科学家:不可否认,这个问题有点争议,但是我决定把它包括进来,因为它经常被忽视。如果不是数据科学家本身,社会科学家至少是整个数据科学过程的重要组成部分,因为他们可以提供数据集背景下急需的洞察力,并就任何结论的伦理影响提供指导。
长话短说,术语“数据科学家”是一个笼统的术语,实际上可能包括以上任何一种。要点很简单:数据科学不仅仅是调整一些奇特的机器学习模型来神奇地解决你所有的问题 [3]。它有许多不同的方面,所有这些都在从数据中收集有意义的见解这一主要目标中发挥着作用。
如果你想要证明这一点,你需要做的就是去 LinkedIn 浏览一下。你会发现上面的标题用得相当流畅。有些人是“机器学习工程的负责人”,但拥有统计学博士学位,有些数据科学家以前的头衔是 UX 研究员,有些数据工程师决定离开高级模型,更多地进入数据管理的本质,等等。我很好奇你会在评论中发现什么。
2.你永远也不会知道的足够多
大学二年级时,我参加了一门基础概率论课程。但是因为那个学期我很忙也很累,所以我几乎没有去上课。
我至今后悔那个决定。由于缺少必备的知识,我在大学期间无法学习更高级的课程,而现在,作为一名研究生,我的知识基础中有一个缺口,我正在拼命地寻找时间来填补。概率方法的坚实基础是数据科学许多方面的重要先决条件。
然而,我最近意识到,也许我对自己逃课太苛刻了。如果我真的知道概率,那我今天还需要学些别的东西。数据科学是一个不断扩展的领域,总会有知识空白需要填补。
没有人能知道一切。这里有一些证据:
- 我的导师在博士期间辅修了统计学——但她告诉我,在开始教授生涯后,她不得不花大量时间自学实用的统计方法,因为她课程中的理论知识都不适用于她的工作。
- 大学时,我给我的一位教授看了一张我制作的图表。尽管他被认为是全国推动数据科学的领军人物之一,但他喜欢我的图表,而且之前从未听说过这种类型的编码(这是一张氯普图 [4】)。直到那一刻,我都不认为自己有能力创作出任何他会觉得新奇或有趣的东西。
这里的要点是:这不是你已经知道什么,而是你有多大的意愿继续学习。
3.这些数据可能没什么有趣的
当我开始攻读博士学位时,我的导师警告我说,研究是一项充满压力的工作,特别是因为一个强有力的原因:你可能花几个月甚至几年的时间研究一个问题,但随后发现你的解决方案不起作用或者根本不可行。
虽然所有的研究都是如此,但在数据科学领域,这是一个特别相关的事实。作为一名数据科学家,你的工作是发现数据中固有的已经存在的 T2。你不能从伦理上重塑它以适应你的需要;因此,不管你的最终目标是什么,你总是至少在冒险。你的发现可能会揭示出与你预期相反的东西,或者根本不会揭示任何东西。
或者,你也完全有可能搞砸原本是好的数据。我的一个朋友曾经和一位验光师一起在参加了两年的研究学习。在最后一次会议上,验光师问了一些总结性的问题,并兴奋地讨论她能从这些数据中学到多少。但是,当我的朋友回答其中一个问题时,验光师意识到她一直在错误地记录数据的一个重要方面——导致她所有的样本实际上都无法使用。
无论是由于人为错误还是数据中固有的错误,总有一天你的所有工作都将化为乌有。这可能感觉像是浪费投资,但请放心,这不是——你会从这个过程中学到很多东西,没有人能从你那里拿走。
这里有两个教训:小心,但要原谅自己。
4.这些钱并不值得
我想这在技术上不是数据科学特有的,但我提到它是因为数据科学似乎是人们加入“快速致富”努力的一长串领域中的最新一个。
但问题是。如上所述,数据科学是很难的,压力也很大。最重要的是,如果你对自己的工作没有激情,你就会陷入悲惨的境地。无论您从事理论统计、软件开发还是领域专业,您都需要确保从数据中获取重要见解的核心目标是一项让您兴奋的任务。
我个人可以担保这件事的重要性。2020 年夏天,我有了第一次技能实习。因为是在工业界,每小时的报酬比我以前从事的教学和研究工作要好。
然而,这项工作对我来说非常无聊和复杂。这是一个糟糕的组合,因为它会导致你不知道自己在做什么,也没有尝试和改进的欲望。虽然我的实习更多地是面向软件工程,但我认为数据科学也是这种情况的温床。
我不是说钱不重要。确实如此——但这是另一篇文章的主题。在这里,我只想强调,如果你鄙视你正在做的事情,金钱不会让你的日常生活变得更好。
如果你做数据科学,应该是因为你喜欢做数据科学。
最后的想法和总结
接受以上关于数据科学的现实让我对这个领域的视野更加清晰,我希望它也能为你做同样的事情。以下是对上述观点的快速回顾:
- 术语数据科学包含了广泛的活动和职业——不要认为你不适合它,因为你不符合某些传统模式。
- 总会有更多的东西需要学习——愿意和开放比以专家的身份进来更重要。
- 做好准备,可能会从事一个漫长、令人厌倦的项目,最终结果令人失望。
- 不要仅仅为了钱而进入数据科学。你需要享受它,否则你将永远痛苦。
祝您的数据工作好运,下次再见!
想擅长 Python? 获取独家,免费获取我简单易懂的指南在这里 。想在介质上无限阅读故事?用我下面的推荐链接注册!
我叫 Murtaza Ali,是华盛顿大学研究人机交互的博士生。我喜欢写关于教育、编程、生活以及偶尔的随想。
参考
[1]https://towards data science . com/the-three-building-blocks-of-data-science-2923 DC 8 C2 d 78
【2】https://boot camp . learn . utoronto . ca/blog/what-is-a-UX-research/
【3】https://towards data science . com/when-did-data-science-become-与-machine-learning-2d7d9f 同义
所以你得到了一个非常大的数据集。这是你清洁它的方法。
原文:https://towardsdatascience.com/so-youve-got-a-dataset-here-s-how-you-clean-it-5d0b04a2ed86
用 Python 进行数据清理的详细分步指南,并附有示例代码。

图片来自马库斯·斯皮斯克 (Unsplash)
在抓取、合并或直接从互联网上下载之后,你就有了一个数据集。你在想你能在上面运行的所有漂亮的模型,但是首先,你必须清理它。你可以有一百万种不同的开始方式,老实说,每次我开始的时候都会让我选择麻痹。
在处理了几个杂乱的数据集之后,下面是我如何构建我的数据清理管道。如果您有更有效的代码或对这些步骤的修改来减少偏见,请留下评论,我会将它合并到文章中!
查看我制作的这个概览图,并继续阅读每个步骤的更多细节。我提供的代码片段是用 Python 编写的,将主要使用 Pandas 和 matplotlib 库。

过滤器
如果您正在处理数据的子集,您希望确保数据代表感兴趣的子集。筛选特定列的特征以确保。
对于地理数据,使用感兴趣区域的 shapefile 和 geopandas sjoin 函数过滤掉外部数据。
# Dataframe of point coordinates
points_gdf **=** geopandas**.**GeoDataFrame(
df[['uprn', 'LATITUDE', 'LONGITUDE']],
geometry**=**geopandas**.**points_from_xy(df**.**LONGITUDE, df**.**LATITUDE),
crs**=**'epsg:4326') # make sure shp_file crs is the same*# Filter for points within boundary*
points_in_boundary **=** geopandas**.**tools**.**sjoin(points_gdf, shp_boundary, how**=**'right')
标准化缺失的数据标签
有时,丢失的数据被编码为“无数据”、“0”、“不适用”或只是一个空字符串。为了便于清理,将所有这些转换成 np.nan.
df **=** df**.**replace(['NO DATA','N/A', 0, ''],np**.**nan)
干净因变量
如果您预测的变量没有值,那么在最终数据集中包含该条目就没有意义。检查最大值和最小值是否在变量的逻辑界限内,以及所有行是否都属于同一数据类型。
删除重复条目
有重复表示数据输入可能有错误。在删除所有重复项之前,请询问:
为什么数据集中有重复项?
答案会改变你去除它们的策略。例如,如果在同一个数据库中根据一个惟一的属性标识符更新一所房子的记录,我们可能会发现最近的条目最相关。这是否意味着我们应该简单地扔掉所有的旧条目?使用旧记录来估算任何缺失的字段有意义吗?
在另一个场景中,我们可能有玩家的游戏记录。最近的条目可能是最新的,但是通过聚合过去的记录我们会得到更丰富的数据吗?游戏的机制使得只有最近或第一个记录重要吗?
不要这么快删除重复的!
检查每个变量的缺失值百分比
percent_missing **=** df**.**isnull()**.**sum() ***** 100 **/** len(df)percent_missing**.**sort_values(ascending**=False**)
如果缺少的值太多,您会希望删除该列。但是分界点是什么呢?
一般来说,丢失超过 50%的数据会使该列看起来毫无用处,但是在删除任何列之前要理解为什么会有这么多数据丢失。
该列可能只在某些情况下被填充。例如,如果表单要求提供饮食限制,而您选择了“其他”,表单可能会提示您填写另一个字段来指定限制。在这种情况下,包含有用信息的缺失值的百分比会非常高。该信息可以被清除并与另一列合并以保留数据。
类似地,如果具有互补数据的两列具有高百分比的缺失值,则可以使用它们来精确地估算数据。例如,如果一列显示一所房子是否有太阳能热水,另一列显示太阳能电池板覆盖的屋顶的百分比,我们可以创建一列来显示太阳能电池板的缺失值。
每一列数据都是费了一番功夫才收集起来的,并且显示了一些可能很重要的东西。如果你决定放弃这个专栏,要清楚为什么,并确保你已经想清楚了!
检查每行缺失值的百分比
如果整行没有数据或数据很少,删除它可能比以后用估算数据填充整个条目更好。在删除行之前,一定要问清楚为什么行是空的!
percent_missing_rows = df.isnull().sum(axis=0) / len(df.columns)missing_plt = percent_missing_rows.hist()missing_plt.set_xlabel('Percent missing')missing_plt.set_ylabel('Number of rows')

每行 null 百分比直方图。[图片来自作者]
对于这个数据集,我没有删除任何行,因为我处理的调查数据后来添加了新字段,增加了早期数据中缺失的百分比。
按变量类型清理
我们希望确保每一列都有我们期望的数据。如果有很多列,那么按类型(广义地说):布尔型、日期时间型、数值型(int/float)、分类型和文本型来审计变量会更容易。
df**.**select_dtypes(include**=** 'INSERT_TYPE')**.**columns**.**tolist()
布尔代数学体系的
将所有布尔列标准化,以 True/False 作为对象,而不是其他形式,如 Y/N 或 Yes/No。
日期时间
将该列转换为 datetime 对象,并在直方图中绘制日期,以确保它在逻辑范围内。
数字的
对于数字数据,绘制箱线图以获得分布的快照,并查看哪些变量具有不合理的最大/最小值,应该进行剪裁。但是在剪辑之前,请确保您理解变量的含义。
num_var **=** df**.**select_dtypes(include**=** 'number')**.**columns**.**tolist()plt**.**figure(figsize**=**(20,10))
**for** i, var **in** enumerate(num_var):
plt**.**subplot(4,7,1**+**i)
plt**.**boxplot(df[var]**.**dropna())
plt**.**xlabel(var,fontsize**=**8, weight**=**'bold')
plt**.**tight_layout()

在这个关于房屋的数据集中,一个房子有 50 个壁炉和超过 60 个加热房间是没有意义的。这表明应该对这些变量进行剪裁。[图片来自作者]
audit_num **=** df[clip_var]**.**describe(percentiles **=** [0.01, 0.99])*# Clips the variables with the upper bound of the 99% confidence
# interval for variables with many outliers variance (no lower clip)*plt**.**figure(figsize**=**(20,10))
**for** i, var **in** enumerate(clip_var):
df[var]**.**clip(lower**=-**9999.0, upper**=**audit_num[var]['99%'], inplace**=True**)
plt**.**subplot(3,4,1**+**i)
plt**.**boxplot(df[var]**.**dropna())
plt**.**xlabel(var,fontsize**=**8, weight**=**'bold')
plt**.**tight_layout()

剪切变量后的方框图。[图片来自作者]
绝对的
打印每个分类列的所有唯一变量,并确保这些值是它们应有的值。否则,合并列。如果类别太多,考虑将它们分组以降低复杂性。
文本
有时你会得到文本形式的数据,这是一种标准化的形式,但大多数是不同输入的一大堆东西。尽可能使用正则表达式来标准化条目,然后我们可以使用 **CHAID(卡方自动交互检测器)**来减少唯一值的数量。
通常,该算法会创建一个决策树。它将独特的反应随机分组到一个节点中,并确定节点中的哪个分裂使我们更接近准确预测结果。它使用的度量是卡方,这是一个统计测试,告诉我们两个分类变量是否独立。我们将获取完成的树中具有唯一响应的最佳分组的节点,并使用它们来减少列中唯一值的数量。
你可以在这里阅读关于方法的更深入的内容。下面的原码来自这里。
**from** CHAID **import** Treechaid_dict **=** {}
**for** var **in** cat_var:
*#Set the inputs and outputs*
*#The imputs are given as a dictionary along with the type*
*#The output must be of string type*
*#I have assume all features are nominal, we can change the features dictionary to include the ordinal type*
features **=** {var:'nominal'}
label **=** 'VARIABLE_TO_PREDICT'
*#Create the Tree*
chaid_dict[var] **=** {}
tree **=** Tree**.**from_pandas_df(df, i_variables **=** features, d_variable **=** label, alpha_merge **=** 0.0)
*#Loop through all the nodes and enter into a dictionary*
print('\n\n\nVariable: %s' **%** var)
print('p-value: %f' **%** tree**.**tree_store[0]**.**split**.**p)
print('Chi2: %f' **%** tree**.**tree_store[0]**.**split**.**score)
**for** i **in** range(1, len(tree**.**tree_store)):
count **=** tree**.**tree_store[i]**.**members[0] **+** tree**.**tree_store[i]**.**members[1]
**if** count **!=** 0:
rate **=** tree**.**tree_store[i]**.**members[1] **/** count
print('\nNode %i:\n\tCount = %i\tRate = %f' **%** (i,count,rate))
print('\t%s' **%** tree**.**tree_store[i]**.**choices)
chaid_dict[var]['node' **+** str(i)] **=** tree**.**tree_store[i]**.**choices
作为一种启发,您可以按原样进行分组,但值得将其作为一个起点,看看如何对唯一的条目进行分组。
估算缺失数据
如果有丢失的数据,你就不能运行一个模型,所以这里有一些我们可以填充丢失数据的方法。
一种简单的方法是根据列中的其他值来填充缺失的数据。如果该列有倾斜的数据,则取中值(数值)或众数(非数值),以便从大多数数据中提取数据,而不会最终改变分布。如果该列有未分块的数据,基于同样的原因取平均值!
另一种方法叫做迭代插补,依次使用每个特征的数据来填充缺失数据。我们预测缺失值百分比最低的要素中的缺失值,就像我们在解决回归问题一样。然后,它使用清理后的要素来预测缺失值百分比次低的要素,直到所有要素都被估算完毕。见此处为教程。
对于分类数据或文本数据,您也可以通过将 np.nan 替换为‘MISSING’来将缺失数据视为一个数据类别。也许数据丢失的事实本身就具有预测性。
编码非数字数据
计算只对数字起作用,所以我们需要通过编码将文本转换成数字。
如果你有顺序数据,你可以使用标签编码将一个按字母排序的类别转换成一个数字序列。[‘A ‘,’ B ‘,’ C’] = [1,2,3]。
当顺序与数字的递增值相对应时,效果最佳,例如:[‘short ‘,’ average ‘,’ tall’] = [1,2,3]。但是当应用于像:[‘苹果’,‘梨’,‘香蕉’]=[1,2,3]这样的无序数据时,模型得到的感觉是香蕉>梨>苹果,这是不正确的!
**from** sklearn.preprocessing **import** LabelEncoderlabel_encoder **=** LabelEncoder()
df[var] **=** label_encoder**.**fit_transform(df[var])
相反,我们使用一键编码,将数字转换成向量。所以数据像:[‘苹果’,‘梨’,‘香蕉’] = [[0,0,1],[0,1,0],[1,0,0]]。但是,在基数较高的地方(很多唯一值),这些向量会变得非常大,占用大量内存,所以要小心。
*# One hot encode non-ordinal variable* **from** sklearn.preprocessing **import** OneHotEncoder
enc **=** OneHotEncoder(handle_unknown**=**'ignore')
df[var] **=** enc**.**fit_transform(np**.**array(df[var])**.**reshape(**-**1,1))**.**toarray()
准备建模!
这绝不是一个关于清理数据的详尽指南。根据您的数据集,您可以执行更多的步骤,但我发现这是一个至少对开始有帮助的管道。请让我知道,如果有其他步骤,我应该添加和其他功能,可能有助于使这个过程更容易。
至少现在,去运行一些模型吧!
测量特征重要性的 Sobol 指数
原文:https://towardsdatascience.com/sobol-indices-to-measure-feature-importance-54cedc3281bc
理解模型的输出在业务驱动的项目中起着重要的作用,Sobol 可以提供帮助

马丁·桑切斯在 Unsplash 上的照片
简介
每个数据项目自然包括一个初始阶段的预处理来获得:
- 适当格式的数据,允许项目的下一阶段正常运行。
- 高质量数据确保最佳性能。
这第二点包括数据科学家的两个众所周知的步骤:特征选择和特征工程。
- 特征选择是丢弃相对“不重要”的变量同时最小化信息损失的过程。
- 特征工程是从现有变量中创建新变量的过程,这些变量在直觉上或“统计上”很重要。通常,变量的变换或交互。
然而,要执行这些步骤,一个关键问题出现了:如何衡量一个变量的重要性?
在本文中,我将介绍一个鲜为人知的方法来回答这个问题:Sobol 指数
衡量重要性
目标是排列每个输入对输出的影响。论文【2】提出变量的重要性通过两个因素依赖于其分布**😗*
- 其权重:其分布可以增加或减少其重要性。比方说,我们正在研究性别和其他因素在泰坦尼克号死亡概率中的重要性:在女性群体中,我们预计性别占主导地位,而对于男性,另一个因素可能更重要。
- 相互作用:一个变量的分布会受到另一个变量分布变化的影响
通常有三种方法来衡量变量的重要性:
- 通过线性回归近似模型,并通过 p 值分析权重
- 执行更多的高级统计测试 (chi2,t student,fisher,ANOVA …)
- 功能分解
Sobol 指数尤其基于后者——应用于方差的函数分解。
Sobol 指数
直觉
一个输入变量 X_i 的重要性由其负责的 Y 的方差的部分来衡量,即如果我们固定 X_i ,我们看(Y 的)方差减少了多少**。如果显著下降,那么变量 X_i 测量的是 Y 的大部分方差,因此 X_i 是一个重要变量。因此,Y 的不确定性归因于X _ I的不确定性,因为它主要代表其方差。**
一阶
Sobol 指数有不同的顺序,反映了相互影响的变量数量。因此,一阶量化了由于唯一变量 X_i 导致的 Y 中的方差份额**。如果有 p 变量,就会有 p 一阶指数。数学上,关系如下:**

一阶 Sobol 指数
期望值 𝔼(Y|X_i) 是 Y 的平均值,其中只有 X_i 的值是有条件的(固定)。
除以总方差 V(Y) 简化了结果的解释:指数越接近 1,变量(如果顺序为 1)或变量组(顺序为> 1)越重要。
k 阶的索引使得 k 个变量相互作用 X_i1 , X_i2 ,…,以及 X_ik 通过以与第一阶相同的方式固定它们的值。下一部分的目的是尽可能简单地描述到达广义公式(针对每一个订单)的路径。
通式
起点是 ANOVA 的功能分解。将其他假设(例如正交性)添加到这个定理中,Sobol 证明了这个分解是唯一的。他将定理中的方差积分,得到如下等式:

Sobol 的泛函分解是基于 ANOVA 的分解(在某些假设下)
最后,阶 k 的 Sobol 指数的正式定义是:

所有订单的 Sobol 索引(1 到 p)
这种方法的缺点是它的算法成本。的确,有“p 选 1”的一阶指数,有“p 选 2”的二阶指数或 p*(p-1)/2 指数,…,也只有一个 p 阶指数,综上,有 2^p — 1 指数。这种指数级的复杂性使得在高维空间中研究灵敏度变得困难。
幸运的是, Homma 和 Saltelli 已经找到了解决这个问题的方法:计算变量的总索引。该指数汇总了感兴趣的变量出现的所有指数。例如,对于 3 个变量,S_T1 = S_1 + S_12 + S_13 + S_123。
他们建立了以下关系:

总指数
【v(𝔼(y|x~i】)这一项是 X~i 的一阶效应,即这一项是 y 条件作用对所有变量的期望方差,除了**x _ I所考虑的变量。
如果我们用一阶指数减去总数,我们就可以得到特定变量的指数之和大于 1 。当然,我们没有每一阶的精确值,但是这允许我们对更高阶的一组值有所了解。
在实践中
现实中,直接计算是不可能的。因此,我们使用估计器,特别是蒙特卡罗方法。
后者基于来自原始数据集的 N 个示例的两个样本,从而使用了两个不同的矩阵,如下所示:

对于 p 变量的 N 示例的数据的 2 个样本
如果 i1、… ik 是我们感兴趣的指数的 k 变量,我们定义一个三阶矩阵等于 B ,但是用的值来表示 k 变量:

矩阵 B 中 k 个变量的值来自 A
3 个输出写如下:

输出符号
对于一阶,Sobol 的方法在于重写等式,如下所示:

Sobol 方法下的一阶指数
因此,可以估计每个量,以获得第 k 个变量的一阶指数:

第 k 个变量的一阶估计量(Y_i 是向量列 Y 的第 I 个元素)
以同样的方式,总索引被重写:

计算第 k 个变量总指数的 Sobol 方法
这导致以下估计量:

变量 k 总效应的估计量
根据定义, S_Tk 大于 S_k ,因为它包含了输入变量 X_k 的主要效应和所有交互作用
现在,让我们把这个方法应用到一个玩具的例子中!
应用
我将使用一个 数据集 ,根据一些天气变量(温度、降雨量(毫米)、能见度……)以及下表所示的其他变量,给出首尔每小时租赁的自行车数量。
使用的原始数据集
预处理阶段将被省略,因为主题是索引。但是,必须提到一个步骤:需要在 0 和 1 之间标准化数据。事实上,ANOVA 函数分解依赖于一个强假设*:函数的定义域必须在 0 和 1 之间,才能有一个唯一的分解(必要条件)。***
代码可分为 3 块。
第一区
在清理数据后,我实现了 3 个函数,分别创建矩阵 A、矩阵 B 和矩阵 AB。代码如下:
为了简单起见,为了生成两个数据样本,我应用了最简单的样本替换技术。(可选择其他样品技术)
第二区
然后,我创建了一个主函数,它将为一个特定的变量计算它的一阶效应和总效应,这样:
计算变量的 Sobol 索引(第一个和全部)的函数(在参数中称为“varaible_index”)
第三区
最后,我展示了一个简单的函数来绘制一个堆叠条形图,以方便地表示每个变量的第一阶效应和总:
plot 函数得到下图(X 是训练数据)
结果

将上述 3 个模块的应用结果应用于之前显示的数据集
经过几次测试和不同的数据后,我注意到对于 1000 个例子来说,估计量是无效的。从 5000 开始,我开始得到如上的不错的成绩。
Sobol 指数从的另一个角度提供结果:
- 温度在每小时租赁自行车的数量中起着主导作用,因为几乎 80%的 Y 的变化似乎是由温度估计的。
- 对于除温度之外的所有变量,由于相互作用 产生的 Sobol 指数在一阶上占优势。也就是说,单独来看,这些变量对输出没有主要贡献,但是它们与其他变量的相互作用使得变量更加重要。
- 值得注意的是,在没有提及标准偏差的情况下,数值分析仍然统计性较差。比如我们看到变量“露点温度”有一个负一阶,理论上不可能。如果我们有标准偏差和 p 值,我们可能会看到这个变量对模型来说可能不重要。
结论
在一个项目中,这种方法可以用来支持其他更传统的测量变量重要性的方法(线性回归,统计测试)。此外,对于非科学观众来说,这个解释可能很难。然而,它通过估计器和统计效率进行计算的简单性可能会吸引那些想用另一种方法来衡量独立变量重要性的科学家。
***注:*每一个手工人物都是我亲手制作的。
来源
- https://artowen.su.domains/pubtalks/siamUQ.pdf(索博尔指数的深层数学解释)
- [2]https://foundation . SCOR . com/sites/default/files/2022-01/Silvia _ Bucci _ Memoire _ ia-light . pdf(一篇有趣的提到 Sobol 指数的法国论文)
使用 Python 和 VADER 进行社交媒体情感分析——无需培训!
词典和基于规则的情感分析库。

介绍
建立一个模型可能比你想象的要容易得多。不是每个分类任务都需要机器学习模型。即使非常简单的方法也能给你带来好的表现。本文涵盖了**VADER**,这是一个基于词典和规则的情感分析模型。我们将首先了解什么是 VADER,最后评估它在分类任务中的性能。
什么是 VADER?
价感知词典和情感推理机或简称 VADER 是一个词典和简单的基于规则的情感分析模型。
它可以有效地处理词汇、缩写、大写、重复标点符号、表情符号(😢,😃,😭等。),等等。通常在社交媒体平台上采用来表达个人情感,这使得它非常适合社交媒体情感文本分析。
VADER 的优势在于评估任何给定文本的情感,而不需要之前的训练,因为我们可能需要机器学习模型。
VADER 生成的结果是一个由 4 个关键字 neg 、 neu 、 pos 和 compound 组成的字典:
neg 、 **neu、**和 pos 分别表示阴性、中性和阳性。它们的和应该等于 1,或者用浮点运算接近 1。
复合词对应于词典中每个单词的价分值之和,并且确定情感的程度,而不是与之前的值相反的实际值。其值介于-1(最极端的负面情绪)和+1(最极端的正面情绪)之间。使用复合分数足以确定文本的潜在情感,因为:
- 一个正向情绪,复合≥ 0.05
- 一个负情绪,复合≤ -0.05
- 一个中性情绪,复合在-0.05,0.05[ 之间
现在我们已经理解了主要概念,让我们深入到实现中。
如何使用 VADER?
本节的目标是为您提供所有的先决条件,如依赖性、数据集和 VADER 的实际实现。
如果您喜欢视频,可以观看本文的视频演示:
先决条件和基础知识
正如标题中提到的,我们将使用 VADER 库,为此我们需要安装[nltk](https://www.nltk.org/_modules/nltk/sentiment/vader.html) **,**下载,并按照以下说明导入词典。
vader_basics.py
SentimentIntensityAnalyzer.polarity_score()功能提供文本的极性,呈现之前解释的字典格式。为了能够执行预测,我们需要预先创建一个SentimentIntensityAnalyzer(行 12 )的实例。
让我们通过预测以下例子的潜在情绪来热身。
示例 1.py
# Output of example1
{'neg': 0.0, 'neu': 0.585, 'pos': 0.415, 'compound': 0.75}
观察例 1 :上一个结果显示该句没有任何负面信息(neg=0)。它有一些中性和积极的音调(neu=0.585 和 pos=0.415)。不过,总体情绪是积极的,因为复利> 0.05
示例 2.py
# Output of example2
{'neg': 0.0, 'neu': 0.373, 'pos': 0.627, 'compound': 0.8284}
观察例 2: 从这个例子可以看出,复合词跳到了 0.82,这使得句子比第一个例子的句子更加肯定。
# Output of example3
{'neg': 0.619, 'neu': 0.381, 'pos': 0.0, 'compound': -0.8449}
观察例 3: 从这最后一句话,我们可以看出,该句没有任何正面信息(pos=0)。它有一些中性和消极的音调(neu=0.424 和 neg=0.576)。总的来说,由于复合得分接近-1,它具有最极端的负面情绪。我的猜测是,去掉感叹词会让情绪不那么消极。为什么不试试呢:)
大型数据集上的性能
既然我们了解了基础知识,让我们尝试评估 VADER 在大数据上的性能。在此之前,我们将需要执行一些预处理。
加载数据进行预处理
我们将使用感知 140 网站上的这个 免许可 推特数据集,以便了解 VADER 做得有多好。
vader_read_data.py

数据集的前 3 行(图片由作者提供)
我们只对两个主要栏目感兴趣。
- ****‘4’,对应推文极性(0:负极,2:中性,4:正极)。
- “@stellargi”…右’,对应实际推文。
下面的函数将这些列重命名为更容易理解的格式,然后在数字和极性的字符串格式之间建立对应关系,最后返回格式化的数据。
格式 _ 数据. py
下图对应于对原始数据集应用format_data()函数后的前 3 行(行 16 和 17 )。

对原始数据应用 format_data 函数后的前 3 行(图片由作者提供)
VADER 的数据有多好?
在此之前,我们将使用以下助手函数,这些函数将立即返回极性( pos 、 neg 或 neu ),而不是字典输出。
维德 _ 预测 _ 助手. py
在行** 19 上,我们创建一个新列vader_prediction()对应 VADER 的预测。然后,在第 22 行我们显示了 5 行随机数据**

包含原始标签和 VADER 预测的 5 行随机数据(图片由作者提供)
从最初的极性栏和 VADER 的预测,我们可以最终生成运行这几条指令的性能(精度、召回和 f1 分数)。
维德 _performance.py

VADER 对数据的准确性和分类报告(图片由作者提供)
该模型似乎做得很好,因为它比随机猜测(精确度= 0.5)好得多!从每个极性的f1-分数中可以得出相同的观察结果。
结论
恭喜你!🎉 🍾您刚刚学习了如何使用 VADER 进行社交媒体情感分类。在进一步构建机器学习模型之前,VADER 可以成为一个很好的起点,并可以用作此类任务的基线模型。我希望您喜欢阅读这篇文章,并且它给了您执行分析所需的技能。请在下面找到更多资源来帮助您进一步学习。
欢迎在 LinkedIn 上添加我,或者在 Twitter 上关注我。讨论人工智能,人工智能,数据科学,自然语言处理的东西总是令人愉快的!
再见🏃🏾
图和网络中的社会网络分析和谱聚类
图的中心性度量和划分技术简介

图片来源——由作者使用 Jupyter 笔记本准备。
1.介绍
1.1 图和网络的基础
网络被定义为由线连接的点组成的图。这些点是节点、顶点,甚至是角色,而连接被称为边。例如,当考虑大学中的学生的社交网络时,每个学生代表一个节点,并且任何一对彼此熟悉的学生表示他们之间的边(友谊)。假设我们将节点定义为 V(与顶点同义)为{V1,V2,V3,…,Vn},那么图的大小为|V|=n,即图中节点的数量。类似地,边被定义为给定节点对之间的关系。考虑将边定义为 E = {E1,E2,E3,……,Em},那么边的数量表示为|E|=m。

**图一。**有向图的例子。网络或图中的边可以具有方向,例如,w.w.w(万维网)是有向图。边通常使用端点来表示,并且通常被定义为弧。在无向图中,这些定义方向的箭头通常是缺失的——这是作者准备的图像。
表示一个图很简单,但是我们需要处理某些组件。下面的网络是无向图的一个例子。对于图中的任何节点 V,例如 Sharanya,它通过边连接到的节点集被称为它的邻居,并被表示为 N(v)。例如 N(Sharanya) = {Tabish,Angel,Panini}。类似地,连接到任何节点的边的数量被称为该节点的度(在下图中表示为每个节点顶部的数量)。在下面的例子中,Sharanya 连接到三个节点,因此度为 3。

**图二。**说明了一个无向图。每个节点代表一个个体,而节点之间的连接则代表程度——作者准备的图像。
1.2 学位与分布
在剩下的文章中,我们将考虑图 2 所示的无向图的例子。在无向图中,度数的总和是图中边数的两倍。

例如,图 2 中的总边数是 6。如果我们对每个节点的度数求和(1+3+2+4+1+1) = 12,则定理本身成立。
在处理可拓图时,节点的度分布是一个需要分析的关键概念,被定义为度分布。例如,让我们考虑 R(d)作为上图中可能的度数序列。R(d) ={1,2,3,4}。我们将分数定义为图中节点总数上度数为“d”的节点数。这可以用来分析幂律度分布。许多用户在像脸书这样的社交网站上朋友较少,然而也有一小部分用户拥有大量的朋友。

计算:P1=3/6 = 50%(图中 3 个节点的度数为 1,6 个节点)。P2 = 1/6 = 17% (1 个度为 2 的节点,参考上图中的 Tabish,共 6 个节点)。
1.3 邻接矩阵
捕捉图中节点之间连接的矩阵表示是邻接矩阵。
Ai,j = 1,如果在节点 Vi 和 Vj 之间有边,否则我们将其标记为 0。这是表示社会网络、学术研究中的引用网络等的常用方法。该图的邻接矩阵如下所示。

**图三。**说明了一个无向图。每个节点代表一个个体,而节点之间的连接则代表程度——作者准备的图像。

**图四。**显示了上图的邻接矩阵以及每个节点的度数。图片由作者准备。
2.节点的中心性度量
中心性允许我们计算数据中每个节点的重要性。假设在墨尔本有一场澳大利亚和韩国之间的足球世界杯预选赛,组织者想向上面网络中最有影响力的人分发一些免费门票。量化中心性的一种方式是通过使用邻接矩阵计算每个节点的度,即给定行中所有 1 的总和。在上面的例子中,帕尼尼拥有最高的度,值为 4,表明他在网络中有多个连接。然而,这可能并不总是正确的方法。想象帕尼尼有多个朋友,但他的朋友只有更少的朋友。为了避免这样的问题,我们可以使用特征向量来计算中心性。
特征向量给每个节点一个与其所有邻居分数之和成比例的分数。给定一个邻接矩阵 A,V 是 A 的一个特征向量,如果乘以 A 并不改变 V 所指的方向,它只是将它缩放一个因子λ,即 A×V =λ×V
2.1 Zachary 的空手道俱乐部网络数据用 Python 中的 NetworkX
在这个例子中,我们将使用 Zachary 的空手道俱乐部网络数据来学习一些图形的基本概念。我们将研究图的节点、边、度、视觉表现等。我们还将学习如何使用谱聚类算法来执行图聚类。
# !pip install networkx%matplotlib inlineimport networkx as nx
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as snsimport warnings
warnings.filterwarnings(‘ignore’) # — — — — — — to get rid of warning messages# — — — — — — — Remove scientific notations and display numbers with 2 decimal points instead — — — — — — — pd.options.display.float_format = ‘{:,.2f}’.format# — — — — — — — Update default background style of plots — — — — — — —
sns.set_style(style=’darkgrid’)
L 加载数据。请注意,数据是作为 networkx 库的一部分出现的。
# — — — — — — — — — — — -Reading Data — — — — — — — — — — — kn=nx.karate_club_graph()# — — — — — — — — — — — -The example below is a network from Zachry’s Karate club — — — — — — — — — — — # — — — — — — — — — — — -Display Number of Nodes — — — — — — — — — — — num_nodes = kn.number_of_nodes()print(‘number of nodes: ‘ + str(num_nodes))print(“-”*50)# — — — — — — — — — — — -Display Number of Edges — — — — — — — — — — — num_edges = kn.number_of_edges()print(‘number of edges: ‘ + str(num_edges))

**输出 1。**说明了网络中节点和边的数量。图片由作者使用 Jupyter 笔记本制作。
with sns.axes_style(‘darkgrid’):
fig = plt.subplots(1, figsize=(12,10))
nx.draw_networkx(kn, edge_color=’#a7a7a5', with_labels=True, font_color=’white’)
plt.axis(‘off’)

**输出 2。**说明了数据的网络表示。图片由作者使用 Jupyter 笔记本制作。
2.2 度中心性
节点 v 的度中心性是它所连接的节点的分数。度中心性值通过除以简单图 n-1 中的最大可能度来归一化,其中 n 是 g 中的节点数。

**一级方程式赛车。**举例说明度中心性的计算。图片由作者使用 Jupyter 笔记本和 Latex 制作。
# — — — — — — — — — let us store the degree centralities for each nodes for a graph in a dictionarydeg_cen = {}graphs=[kn]for g in graphs:
deg_cen[g] = nx.degree_centrality(g)print(deg_cen)
我们可以使用上面定义的公式进行计算。我们选择图中的第 4 个节点进行验证。
num_nodes = graphs[0].number_of_nodes()print(‘number of nodes: ‘ + str(num_nodes))list_nodes=list(graphs[0].nodes)print(list_nodes)num_neighbors = graphs[0].degree(list_nodes[4])print(‘degree of node ‘, list_nodes[4], ‘is ‘, num_neighbors )print(“Degree of Centrality:”, round(num_neighbors/(num_nodes-1),3))
2.3 中间性
该度量确定网络中的哪些节点充当其他节点之间的“桥梁”。这是通过首先识别所有最短路径,然后计算每个节点落在其中一条路径上的次数来实现的。

**配方二。**说明了之间中心性的计算。图片由作者使用 Jupyter 笔记本和 Latex 制作。
# Betweenness Centralitybetw_cen = {}
for g in graphs:
betw_cen[g] = nx.betweenness_centrality(g)betw_cen
理解一个节点的最短路径序列。
paths= nx.all_pairs_shortest_path(graphs[0])path_5_1=nx.all_shortest_paths(graphs[0],5,1)for p in paths:
if p[0]==5:
print(p)
print(“-”*50)
for p in path_5_1:
print(p)
2.4 紧密中心性
图中任何节点(比如 v)的接近中心性可以通过在所有 n-1 个可到达的节点上找到到 v 的平均最短路径距离,然后取它的倒数来计算。

**配方三。**说明了亲密度中心性的计算。图片由作者使用 Jupyter 笔记本和 Latex 制作。
# Closeness Centralityclo_cen = {}for g in graphs:
clo_cen[g] = nx.closeness_centrality(g)
clo_cen
我们可以使用上面定义的公式进行计算。我们选择图中的第 5 个节点进行验证。
s=0print(len(list_nodes))for node in list_nodes:
if node!=5:
shortest_path_length=nx.shortest_path_length(graphs[0],5,node)
s+=shortest_path_length
print((len(list_nodes)-1)/s)
2.5 特征向量中心性
特征向量中心性使用其邻居的中心性来计算节点的中心性。对于节点 I,特征向量中心性是 A’X X =λX X,其中 A’被定义为具有λ特征值的图 G 的邻接矩阵。
# Eigen Vector Centralityeig_cen = {}for g in graphs:
eig_cen[g] = nx.eigenvector_centrality(g)eig_cen

**图 5。**说明了现实世界问题中不同中心性测量的用例(迪士尼,2019)。图片由作者用 Excel 制作。
2.6 可视化图中的重要节点
# let us now sort the degree centrality measure and identify the important nodes.for ix, g in enumerate(graphs):
temp_dict = {}
for w in sorted(deg_cen[g], key=deg_cen[g].get, reverse=True):
temp_dict[w] = deg_cen[g][w]
print(“Sorted Importance of nodes in terms of deg_cen for Graph {} is {}”.format(ix+1, list(temp_dict.keys())[:5]))
print()
对于图 1,根据 deg_cen,节点的排序重要性是[33,0,32,2,1]。
graph2 = kn
color = []fig = plt.subplots(1, figsize=(12,10))for node in graph2:
if (node == 33 or node == 0 or node == 32 or node==2 or node==1):
color.append(‘red’)
else:
color.append(‘blue’)
nx.draw_spring(graph2,node_color=color,with_labels=True)

**输出 3。**用重要节点说明数据的网络表示。图片由作者使用 Jupyter 笔记本制作。
3.谱聚类
谱聚类算法用于根据图的连通性将图分成 K 个组。谱聚类中涉及的步骤包括:
- 预处理:构造图的拉普拉斯矩阵。拉普拉斯矩阵是邻接矩阵和对角矩阵之间的差异。L = D — A。
- 分解——计算拉普拉斯矩阵的特征值和特征向量,然后我们需要将每个点映射到一个更低维的表示。
- k 表示算法—使用上述数据创建聚类组。
3.1 预处理
G_p1=graphs[0]A=nx.adjacency_matrix(G_p1)print(“ — — — — — — — — — -ADJACENCY MATRIX — — — — — — — — — — — -”)print(A.todense())print(“-”*50)print(“ — — — — — — — — — -DIAGONAL MATRIX = DEGREE OF EACH NODE — — — — — — — — — — — -”)print(G_p1.degree)L = nx.laplacian_matrix(G_p1).astype(float)print(“-”*50)print(“ — — — — — — — — — -LAPLACIAN MATRIX — — — — — — — — — — — -”)print(L.todense())

**输出 4。**说明了网络的拉普拉斯矩阵、邻接矩阵和对角矩阵。图片由作者使用 Jupyter 笔记本制作。
3.2 分解
import scipy as spw,v = sp.sparse.linalg.eigsh(L, k = 3, which=’SM’)print(w)
print(v)
3.3 K 表示聚类
请注意,我们已经创建了 3 个集群作为假设场景。然而,在现实世界的应用中,使用轮廓分数、间隙统计,甚至肘图来验证 K 的良好值是很重要的。对于图划分,更常见的度量是 F-Measure、Precision、Recall、Purity、Mutual Information 和 Normalized Mutual Information。
from sklearn.cluster import KMeansX = v*wkmeans = KMeans(init=’k-means++’, n_clusters=3, n_init=10)
kmeans.fit_predict(X)
centroids = kmeans.cluster_centers_
labels = kmeans.labels_
error = kmeans.inertia_fig = plt.subplots(1, figsize=(12,10))colors = ['#d7191c', '#ffffbf', '#2b83ba']
node_colors = [ colors[labels[v]] for v in G_p1.nodes()]
nx.draw(G_p1, node_color=node_colors, with_labels='True')

**输出 5。**用三个集群说明了数据的网络表示。图片由作者使用 Jupyter 笔记本制作。
4.参考
- 布兰德斯大学(2001 年)。中间中心性的快速算法。《数理社会学杂志》, 25 (2),163–177 页。https://doi.org/10.1080/0022250x.2001.9990249
- 在线创建图形并寻找最短路径或使用其他算法。(未注明)。https://graphonline.ru/en/
- 迪士尼,A. (2019 年 7 月 26 日)。社交网络分析:中心性测量。剑桥情报局。https://Cambridge-intelligence . com/keylines-FAQ-social-network-analysis/
- NetworkX。(2022).between ness _ centrality—NetworkX 2 . 7 . 1 文档。Networkx.org。https://networkx . org/documentation/stable/reference/algorithms/generated/networkx . algorithms . between ness _ centrality . html # networkx . algorithms . centrality . between ness _ centrality
关于作者:高级分析专家和管理顾问,通过对组织数据的商业、技术和数学的组合,帮助公司找到各种问题的解决方案。一个数据科学爱好者,在这里分享、学习、贡献;可以和我在 上联系 和 推特;
软件即服务:小型 IT 部门的游戏规则改变者
软件即服务简介,与内部解决方案进行比较

在 Unsplash 上由 Austin Distel 拍摄的照片
软件即服务(SaaS)是云计算领域中的一个类别,其中软件可以在没有安装在本地计算机上的情况下使用。最终用户通过网站访问程序,因此只使用软件的功能。另一方面,硬件和 IT 基础设施的供应由提供商处理。
软件即服务是如何工作的?
软件即服务使用云环境向客户提供服务。根据应用程序的不同,软件提供商使用自己的服务器或云服务提供商来托管应用程序,存储数据并更新系统。
另一方面,最终客户只需要互联网连接,并通过网络浏览器使用应用程序。在大多数情况下,他与提供商签订了一份订阅协议,授权他在有限的时间内使用软件。
然后,提供商还面临着调整应用程序的任务,以使其尽可能平稳地为最终客户服务。在大量使用的情况下,必须相应地预订新的云资源,或者必须增加本地服务器。
内部部署和 SaaS 有什么区别?
随着云计算的普及,软件即服务变得更加流行。在此之前,公司购买他们使用一次的软件,然后在他们的本地设备上安装和维护它是很正常的。
对于公司来说,当他们必须决定是在云中还是在本地使用软件时,以下几点至关重要:
设置和维护
对于内部软件,内部 IT 部门需要负责安装、维护、保护,最后是硬件的扩展,以防更多用户开始使用它。这些任务可能无法由一个小团队来完成,这使得中型公司尤其困难。
对于软件即服务,您只需注册应用程序并选择订阅类型。在大多数情况下,甚至有机会在签署订阅之前免费试用。因此,设置和维护甚至可以由非 IT 人员来完成。
费用结构
在大多数情况下,与内部解决方案相比,SaaS 是更具成本效益的替代方案。费用是非常透明的,因为您只需支付固定的订阅费,该费用可能会随着用户的增加而变化。对于内部部署,通常对软件的一次性投资非常高,而经常性的维护成本较低。因此,从长远来看,内部部署可能会成为更便宜的选择,但前提是经常性成本保持在较低水平。
对信息技术人员的需求
SaaS 解决方案的主要优势是对训练有素的 IT 人员的需求低,因为大多数软件使用无代码前端,这使得即使没有技术背景的员工也很容易操作。这样,用户只需要互联网接入和一个打开的浏览器就可以使用该应用程序。对于内部部署,IT 人员需要随时待命,以便在出现中断或错误时做出反应。这意味着他们不能用于其他项目,整个部门需要发展。
集成其他应用程序
对于大多数 SaaS 应用程序,有一堆其他软件可以轻松集成。在某些情况下,订阅需要更改为更高级的订阅,但集成速度非常快。然而,如果所需的软件不在给定的堆栈中,可能需要很长时间,或者甚至不可能让制造商添加它。
在内部部署的情况下,新应用程序的集成通常非常复杂,可能需要大量的时间和资源。然而,有可能添加新软件,只要它在技术上是兼容的,并且不依赖于提供商的堆栈。
可量测性
由于软件即服务的透明成本结构,它还具有完美的可扩展性。新用户只会导致额外的订阅,这意味着更高的成本。但不需要改进硬件等。因为供应商会处理这些问题。
在内部部署的情况下,可伸缩性要难得多,因为通常有固定成本。在设置时,高成本正在发生,对于最初的几个用户来说可能不会真正改变。然而,可能存在一个用户阈值,此时需要进行另一次硬件改进来维持性能。再者,由于硬件昂贵,投资相当高。
哪些应用程序已经作为软件即服务提供?
由于软件即服务的诸多优势及其受客户欢迎的程度,现在几乎所有的新应用程序都以 SaaS 的形式提供。此外,多年来在内部提供的软件产品也正在被转换。这方面最著名的例子是微软 Office。
以下软件产品是 SaaS:
- 销售力量
- 微软 365
- 网飞
- 一款云视频会议软件
- 松弛的
- 特雷罗
软件即服务的优势是什么?
如前所述,使用软件即服务是有益的,因为它对企业来说更具成本效益。详细来说,还有以下优点:
- 安装和维护的成本和工作量低
- 快速部署,不损失安装时间
- 可量测性
- 自动无故障更新
- 轻松扩展其他服务
- 按用户付费,从而实现最大的成本透明度
使用 SaaS 有什么问题?
当使用软件即服务时,使用外部服务自然也会带来风险。特别是对于公司来说,必须仔细权衡与内部解决方案相比的优势和劣势。
在将软件作为服务使用之前,必须始终详细检查数据保护情况。根据软件的应用,敏感数据有时会离开公司。因此,必须确保信息也安全存储,并保证数据安全。这有时可能是一个耗时且昂贵的过程。
在软件运行过程中,服务的可访问性和性能会出现风险。SaaS 提供商负责确保软件始终可用,很少停机,并且及时进行更新。如果不是这样,采购公司可能会经历超出他们控制的昂贵的停机时间。
因此,应该仔细检查服务级别协议,并在签订合同之前重新协商。这些规则规定了 SaaS 提供商在出现故障时的行为方式,以及服务必须在多长时间内恢复运行。如果提供商无法满足这一服务水平,客户可能有权获得补偿,这取决于协议。
无论是内部解决方案还是 SaaS,提供商的后续变更都需要付出巨大的努力。累积的数据量必须迁移到新系统,员工可能需要重新培训。因此,软件和提供商的选择应该是经过深思熟虑的。
PaaS、IaaS 和 SaaS 有何不同?
除了软件即服务,其他服务也在“X 即服务”领域得到了发展。通常,在这些产品中,提供商专注于管理,客户不再需要承担很少甚至任何任务。
与此相反的是所谓的现场或内部软件。在这里,操作、数据、服务器以及更多的责任由最终使用系统的组织承担。尽管这种架构涉及大量工作和责任,但一些公司仍然依赖这种方法,因为它确保敏感数据不会离开公司。
借助基础设施即服务(IaaS),服务器、数据存储和网络的管理由云中的外部提供商负责。另一方面,客户通过接口访问和使用租用的基础设施。但是,用户仍然负责系统的其余部分,例如应用程序、数据或操作系统。这也意味着用户对可能的故障或维修承担全部责任。
下一个阶段是平台即服务(PaaS),除了基础设施之外,软件平台也在提供商的云中提供。例如,当应用程序要被编程时,使用该选项。它相当于由提供商提供的虚拟机。用户仍然可以控制已安装的程序,但所有其他责任都由提供商承担。
这种结构的最后一个阶段是软件即服务(SaaS),其中所有之前的阶段和软件本身都由云中的提供商运营。
为什么 SaaS 对数据科学家很重要?
在日常工作中,许多数据科学家已经开始使用软件即服务产品。这部分是因为一些程序只能作为 SaaS 使用,部分是因为根据用例它更有意义。
许多数据科学家使用的 SaaS 产品之一是谷歌分析。web 界面提供了直接评估 web 跟踪数据、显示数据并从中得出可能结论的可能性。谷歌分析也可以用作 SaaS 工具。即使你想自己保存数据,这也不会那么容易,因为从 Google Analytics 导出数据实际上是不可能的。只有现有的报告可以下载为 pdf,或者基础数据可以导出为 CSV。因此,在这种情况下,没有软件即服务产品甚至是不可能的。
然而,也有足够多的例子表明,从内部解决方案转向 SaaS 解决方案确实是有意义的。例如,在机器学习领域,已经出现了机器学习即服务的领域,其中购买了底层架构。
目前很多机器学习模型,比如变形金刚,都需要快速训练图映射。在传统的 CPU 上,训练通常需要多倍的时间。然而,使用显卡构建基础架构不仅更复杂,而且成本也很高。因此,求助于外部资源是值得的,这些外部资源的环境是专门为机器学习和数据科学设计的,因此能够 100%地专注于项目。
这是你应该带走的东西
- 软件即服务(SaaS)是云计算领域中的一个类别,其中软件可以在没有安装在本地计算机上的情况下使用。
- 对于用户来说,这尤其带来了低成本的优势,以及安装和维护费用的降低。
- 除了 SaaS,还有基础设施即服务(IaaS)和平台即服务(PaaS)作为使用云的替代选项。
如果你喜欢我的作品,请在这里订阅https://medium.com/subscribe/@niklas_lang或者查看我的网站 数据大本营 !还有,medium 允许你每月免费阅读 3 篇 。如果你希望有无限制的 访问我的文章和数以千计的精彩文章,不要犹豫,点击我的推荐链接:【https://medium.com/@niklas_lang/membership】每月花$5*获得会员资格*
* *
软件开发几乎 100%与沟通有关
原文:https://towardsdatascience.com/software-development-is-almost-100-about-communication-1bb9bc60810f
…我们应该正确地生产高质量的产品

在 Unsplash 上由 Austin Distel 拍摄的照片
沟通通常不会与编程怪胎联系在一起,请原谅……软件工程师。有些人可能会认为开发人员是独自呆在地下室的害羞的书呆子,他们更喜欢自己的计算机而不是其他人的陪伴。我没见过多少这样的人。
事实上,软件开发中的沟通无处不在,我认为几乎 100%的软件开发都与沟通有关。
任何设计系统(广义定义的)的组织都会产生一个设计,其结构是组织的沟通结构的复制。
梅尔文·康威— 康威定律
在软件开发中,沟通几乎无处不在,在客户和用户之间,在项目团队中,在产品所有者、设计师、架构师、开发人员和技术解决方案测试人员之间。最后,当我们的开发团队给计算机下达解决问题的指令并“编码”我们的产品时。
这不是我们是否交流的问题,而是我们如何交流和交流什么的问题。在本文中,我们将探讨软件开发过程中可能出现的一些沟通挑战,并提供一些如何克服这些挑战的建议。
愿景,又名北极星
软件开发意味着实现某种能力差距的解决方案的过程,这种能力差距理想地以需求的形式来描述。需求可能来自各种来源,有不同的意图,并且与不同的涉众相关。他们是项目方向的最强驱动力之一,所以清楚他们并为他们建立一个框架是很重要的。
一切都从这里开始——我们需要有一个愿景,以便达成共识。有人称之为“北极星”,它将有助于为我们提供指导方针、界限和奋斗的总体目标。愿景在协调项目团队方面也起着重要的作用。任何不属于愿景的东西都应该被视为无效而拒绝。顺便说一下,在过去,这是一种有效的方法,可以终止任何关于不合适的需求的讨论。愿景将为我们提供“为什么”的信息,因此它将提供关于我们的目标受众及其目标的信息,这将有助于我们确立起点和方向。
好,那么你对你的产品有一个愿景,太好了!让我们来看看你可能会陷入的一些陷阱。
团队规模和直接联系
项目团队中的直接沟通是有成本的,这部分可以用直接点对点沟通所需的连接数来描述:connections = teamMembers * (teamMembers-1) / 2。
加入团队的人越多,直接连接的数量就越多,开销也随之增加:
- 3 个人— 3 个直接连接
- 5 个人— 10 个直接连接
- 10 个人— 45 个直接连接
- 15 个人— 105 个直接连接
当然,我们试图通过每天的 scrums、每周的 demos、playbacks、retro-perspectives 和其他形式来弥补这一挑战,将点对点的交流转变为一对多的交流,但是直接交流的需求永远不会完全消失。
弗雷德·布鲁克斯早在 1975 年就描述了这一事实的逻辑后果:
给一个后期的软件项目增加人力会使它变得更晚。弗雷德·布鲁克斯的布鲁克定律
在现实世界中,我更喜欢在一个团队中与最多 5 个人一起工作,应该给这个团队一个具有挑战性但仍然可以实现的功能或能力,并且可以完全归这个团队所有。许多软件项目需要大量的劳动力;然而,模式应该保持不变:分而治之 —将一个较大的产品分成几个部分,由更小的团队分配和拥有,从而在团队内进行范围有效的沟通,并创建另一个级别的跨团队沟通,仅限于与需要标准化和治理的领域相关的功能-支配性主题—更多详细信息可在此处找到:
信息的丢失
几年前,我们在大学进行了一个有趣的测试,叫做“传递信息的方式”。一个人单独给另一个人讲了一个 10 点的故事,然后这个故事就这样流传下去。在整个小组经历了这一过程后,结果相当令人惊讶:大约三个点原封不动地保留了下来,七个点完全丢失了,还有几个点被创造性地添加了进去。信息的丢失非常明显。当我们考虑沟通时,我们需要考虑损失,这样我们才能更好地验证收到的内容或重复理解的内容。
透视约束
不同的人有不同的观点,通常会导致不同的结论、观点和优先事项——这些都不应该被认为是故事的全部。用户受众越多,就越应该考虑这些视角中的约束。你可能会看到一群潜在的非常直言不讳的用户对你的应用中的搜索行为尖叫,商业利益相关者对应用内仪表板小题大做,程序管理可能最关注工具的改进。希望能够看到全貌的可能是项目或投资组合的所有者和/或首席架构师。优先化现在成为几种力量之间的平衡行为,我在这里唯一的概括建议是确定什么是最大化业务成果真正需要的,而不是特定利益相关者群体想要的。在这种情况下,沟通显然是至关重要的,可以提出以下问题:
- 用户和利益相关者需要什么来实现?
- 他们目前是如何实现的?
- 是什么让今天很难甚至不可能实现?
在这种情况下,用户研究是关键,但是我不建议进行解决方案的研究**——而是研究问题。**
无声信息和信息隐藏
无论我们是否认为沉默信息的原因仅仅是无效,而不是缺乏沟通,甚至是有意隐藏信息,关键后果都是相似的——团队成员之间不共享信息导致的风险**,有时被称为总线因素。**
如果你意识到你团队中的某个人既是关键人物又是不可替代的 T2,那么是时候控制局面,敦促并促进沟通、文档和知识转移了。从我的经验来看,防止信息隐藏的最有效的方法是建立一种开放和尊重的工作文化,在这种文化中,所有团队成员的贡献都受到赞赏,反馈不断流动,微观跟踪不存在。一旦分享相对于隐藏的好处变得非常明显,公开有效的交流通常会自然而然地随之而来。
预期
从项目团队的角度来看,多个涉众不断地提出期望,这显然需要理解。以我的经验来看,“什么”通常需要最高层次的关注,但是“为什么”以及目的在达成共识和协议方面要重要得多,所有这些都必须符合我们的愿景。
另一方面,为了避免不可避免地导致不满的不切实际的期望,涉众的期望可以而且必须在软件开发项目中得到管理。开始时的知识量通常会在完成一个项目所需的时间长度上产生更高水平的不确定性。这种不确定性带来了风险以及范围和时间之间的权衡,所有各方都应该从一开始就意识到这一点。你可能会问,期望管理的有效沟通是什么样的?
这里的关键是对未知的透明度、对已知的明确承诺、交付团队创建的调整、对承诺的可靠交付、过程修正的灵活性,以及向期望的方向迈出的许多微小但稳定的步骤,这些步骤展示了持续的改进并由此创造了信任。就我个人而言,我从来不热衷于试图将范围锁定在时间上的项目计划——我的思维方式与瀑布不兼容。我们只需要一份计划,在地图上选择大致的路线,细节可以边走边想。然而,在你的计划中留些缓冲空间也无妨😜。
摘要
我们已经知道,在任何软件开发项目中,沟通都是一个普遍而关键的因素。解释了为什么远景是定位和构建需求的基础,我们已经看到团队规模、信息损失、视角约束、无声信息和期望是软件开发项目中的潜在挑战,可以通过高效和有效的沟通来克服。
进一步阅读
**** **https://www.hdwebsoft.com/blog/most-important-skill-software-developer-communication.html **
关于 Thomas Reinecke —在过去几年中,我作为 IBM 内部几个关键转型项目的首席架构师,拥有独一无二的机会来共同领导和影响 IBM 内部一些最复杂、最全面和最有影响力的活动,例如支持、销售和业务合作伙伴生态系统的转型。我一直是一个非常好奇和善于思考的人,所以多年来我一直试图理解沟通对软件开发的影响,显然我已经实践了😁。我本质上仍然是一名 IT 工程师,所以我最感兴趣的是事情的实际方面,我在 medium 上分享我自己的真实世界经验。
如果你喜欢这个故事,并想在 medium 上阅读成千上万个这样的故事,你可以成为 medium 会员,每月仅需 5 美元。如果你愿意支持我的写作,请使用我下面的推荐链接,我将免费获得你的一部分会员资格。
【https://medium.com/@thomas.reinecke/membership】T5T6
https://twitter.com/reineckethefox
数据科学的软件工程工具和最佳实践
伟大的代码带来伟大的机器学习

如果你对数据科学感兴趣,你可能对这个工作流程很熟悉:你通过启动一个 jupyter 笔记本开始一个项目,然后开始编写你的 Python 代码,运行复杂的分析,甚至训练一个模型。
随着包含所有函数、类、图表和日志的笔记本文件变得越来越大,您会发现自己面前有一大堆完整的代码。如果你幸运的话,事情会很顺利。那对你有好处!
但是,jupyter 笔记本是万恶之源。它们隐藏了一些严重的陷阱,可能会将您的编码变成人间地狱。
本文讨论了 Jupyter 笔记本电脑何时以及为何会产生反效果,并介绍了一些可改善您的数据科学工作流程的软件实践。
事不宜迟,让我们来看看🔍。
Jupyter 笔记本的问题

由 Kelly Sikkema 在 Unsplash 上拍摄的照片
如果您想让 jupyter 原型更上一层楼,事情往往不会如您所愿。以下是我过去使用这个工具时遇到的一些情况。
希望您对此耳熟能详:
- 所有的对象(函数或类)都在一个地方定义和实例化,可维护性变得非常困难:即使你想对一个函数做一个小的改变,你也必须在笔记本的某个地方找到它,修复它,然后重新运行代码。你不想那样的,相信我。将逻辑和处理功能分离在外部脚本中不是很简单吗?
- 由于其交互性和即时反馈,jupyter 笔记本推动数据科学家在全局名称空间中声明变量,而不是使用函数。这在 python 开发中被认为是糟糕的实践,因为它**限制了有效的代码重用。**它还会损害再现性,因为您的笔记本变成了一个保存所有变量的大型状态机。在这种配置中,您必须记住哪个结果被缓存,哪个没有,并且您还必须期望其他用户遵循您的单元执行顺序。
- 笔记本在幕后格式化的方式(JSON 对象)使得**代码版本化变得困难。**这就是为什么我很少看到数据科学家使用 GIT 来提交笔记本的不同版本,或者为特定功能合并分支。因此,团队协作变得低效和笨拙:团队成员开始通过电子邮件或 Slack 交换代码片段和笔记本,回滚到以前的代码版本是一场噩梦,文件组织开始变得混乱。以下是我在使用 jupyter 笔记本两三周后,在没有正确版本控制的项目中常见的情况:
analysis . ipynb
analysis _ COPY(1)。ipynb
分析 _ 复制(2)。ipynb
analysis _ FINAL . ipynb
analysis _ FINAL _ 2 . ipynb - Jupyter 笔记本有利于探索和快速原型开发:它们是 EDA 和快速特别分析的最佳工具。
然而,它们肯定不是为可重用性或生产用途而设计的。如果您使用 jupyter 笔记本开发了一个数据处理管道,您最多只能说您的代码只能在您的笔记本电脑或 VM 上按照单元的执行顺序以线性同步的方式工作。这并没有说明您的代码在更复杂的环境中的行为方式,例如,更大的输入数据集、其他异步并行任务或更少的分配资源。笔记本实际上很难测试,因为它们的行为有时是不可预测的。 - 作为一个将大部分时间花在 VSCode 上,利用强大的代码扩展林挺、样式格式化、代码结构化、自动完成和代码库搜索的人,当切换回 jupyter 时,我不禁感到有些无力。与 VSCode 相比,jupyter notebook 缺少实施编码最佳实践的扩展。
好了,伙计们,现在抨击够了。我真的很喜欢 jupyter,我认为它的设计非常棒。你肯定可以用它来启动小项目或快速原型想法。
但是为了将这些想法以工业的方式传播,你必须遵循软件工程的原则,而当数据科学家使用笔记本时,这些原则碰巧被遗忘了。
让我们一起回顾一下其中的一些,看看它们为什么重要。
让你的代码再次变得伟大的 8 个技巧🚀
这些技巧是从不同的项目、我参加的聚会以及与我过去共事过的软件工程师和架构师的讨论中收集来的。如果你有其他的建议和想法分享,请在评论中告诉我。
1 —遵循 PEP8 命名约定,使用林挺并格式化您的代码

代码质量最重要的方面之一是清晰:清晰易读的代码对于协作和可维护性至关重要。
以下可能有助于您获得更清晰的代码:
- 使用有意义的变量名,它们是描述性的和隐含的类型。例如,如果您声明一个关于属性(例如年龄)的布尔变量来检查一个人是否老,您可以通过使用 is_old 使它既具有描述性又提供类型信息。同样的道理也适用于你声明数据的方式:让它具有解释性。
**# not good ...** import pandas as pd
df = pd.read_csv(path)**# better!** transactions = pd.read_csv(path)
- 避免除了你没人能理解的缩写和没人能忍受的长变量名**。**
- **不要硬编码【幻数】**直接编码。将它们定义在一个变量中,以便每个人都能理解它们所指的内容。
**# not good ...**
optimizer = SGD(0.0045, momentum=True)**# better !**
learning_rate = 0.0045
optimizer = SGD(learning_rate, momentum=True)
- 命名对象时遵循 PEP8 约定:例如,函数和方法名用小写,单词用下划线分隔,类名遵循 UpperCaseCamelCase 约定,常量全部大写,等等。点击了解更多关于这些习俗的信息。
- 使用缩进和空格让你的代码呼吸。有一些标准约定,比如“每个缩进使用 4 个空格”,“单独的部分应该有额外的空白行”……因为我从来不记得这些,所以我使用了一个非常好的 VSCode 扩展,叫做 更漂亮的 ,当按 ctrl+s 时,它会自动重新格式化我的代码
在怀疑和不确定的时刻,我总是参考这个回购,它聚合了一组非常有用和实用的概念,以获得一个干净的代码。
2 —使您的代码模块化📁
当你开始构建你认为可以在一个或多个项目中重用的东西时,你必须将你的代码组织成逻辑函数和模块。这有助于更好地组织和维护。
例如,当你在一个 NLP 项目中工作,并且有不同的处理函数来处理文本数据(标记化、剥离 URL、词条化等。),可以把这些单元都放在一个名为 text_processing.py 的 python 模块中,并从中导入。你的主程序会轻松很多。
以下是我学到的一些关于编写模块化代码的好技巧:
- 干:不要重复自己。尽可能概括和巩固你的代码。
- 功能要做一件事。如果一个函数做多种运算,那么泛化就变得更加困难。
- 在函数中抽象你的逻辑,但是 **不要过度设计它:**有一点点可能性,你最终会有太多的模块。运用你的判断力,如果你没有经验,看看流行的 GitHub 库,比如 scikit-learn ,看看他们的编码风格。
3 —重构您的代码📦
重构旨在重组代码的内部结构,而不改变其功能。它通常是在一个工作的(但还没有完全组织好的)代码版本上完成的。它有助于消除重复的功能,重新组织文件结构,并增加更多的抽象。
要了解更多关于 Python 重构的知识,这篇文章是一个很好的资源。
4 —让您的代码高效⏱
编写执行速度快、占用内存和存储空间少的高效代码是软件开发中的另一项重要技能。
编写高效的代码需要多年的经验,但这里有一些快速的提示,可以帮助你发现你的代码是否运行缓慢,以及如何提高它:
- 在运行任何东西之前,检查算法的复杂性,以评估它的执行时间
- 通过检查每个操作的运行时间来检查脚本的可能瓶颈
- 尽可能避免 for 循环,对操作进行向量化,尤其是当你使用像 NumPy 或 pandas 这样的库时
- 通过使用多重处理来利用计算机的 CPU 内核
5 —使用 GIT 或任何其他版本控制系统🔨
以我个人的经验,使用 GIT + Github 帮助我提高了编码技能,更好地组织了我的项目。因为我在与朋友和/或同事合作时使用它,它让我坚持我过去不遵守的标准。

图片由作者修改
使用版本控制系统有很多好处,无论是在数据科学还是软件开发方面。
- 跟踪您的更改
- 回滚到代码的任何先前版本
- 团队成员之间通过合并和拉取请求进行高效协作
- 代码质量的提高
- 代码审查
- 向团队成员分配任务并监控他们的进度
Github 或 Gitlab 等平台甚至更进一步,提供了持续集成和持续交付挂钩,以自动构建和部署您的项目。
如果你是 Git 新手,我推荐你看看这个教程。
或者你可以看看这个备忘单:

图片由作者修改
如果你想具体了解机器学习模型如何版本化,可以看看这篇文章。
6 —测试您的代码📐
如果您正在构建一个执行一系列操作的数据管道,确保它按照设计目的执行的一种方法是编写检查预期行为的测试。
测试可以简单到检查输出形状或函数返回的预期值。

作者图片
为您的函数和模块编写测试有很多好处:
- 它提高了代码的稳定性,使错误更容易被发现
- 它防止意外输出
- 它有助于检测边缘情况
- 它防止将损坏的代码推向生产
7-使用🗞测井
一旦代码的第一个版本运行,您肯定希望在每一步都监控它,以了解发生了什么,跟踪进度,或者发现错误的行为。这里是您可以使用日志记录的地方。
以下是一些有效使用日志记录的技巧:
- 根据您想要记录的消息的性质,使用不同的级别(调试、信息、警告)
- 在日志中提供有用的信息,以帮助解决相关问题。
**import** **logging**
logging.basicConfig(filename='example.log',level=logging.DEBUG)
logging.debug('This message should go to the log file')
logging.info('So should this')
logging.warning('And this, too')
8 —使用可靠的原则。
如果您想编写更好的代码,并以可维护性、可读性和可扩展性为目标,请考虑 Robert C. Martin 的《坚实的原则》。
- 单一责任:每个软件组件(一个类,一个方法,一个函数)应该只有一个责任。
- 开闭原则。每个实体都应该对扩展开放,对修改关闭。这意味着添加新功能不会改变现有代码。
- Liskov 替换:你需要能够用子类替换每个类。这意味着子类的接口应该以与基类相同的方式运行。
- 接口分离:每个对象都应该有一个接口(=一组方法),在内聚性方面尽可能小。它应该做一件事。
- 依赖倒置:与另一个类交互的类不应该知道它的内部工作方式。例如,如果您使用数据库,请不要在代码中使用原始查询。你需要将它们隐藏在抽象背后。
参考
- https://github . com/A2Amir/Software-Engineering-Practices-in-Data-Science。
- https://towards data science . com/5-reasons-why-jupyter-notebooks-suck-4d c201 e 27086
- https://medium . com/@ _ orca man/jupyter-notebook-is-the-cancer-of-ml-engineering-70b 98685 ee71
- https://data pastry . com/blog/why-I-dont-use-jupyter-notebooks-and-you-should not-than/
- https://visual git . readthe docs . io/en/latest/pages/naming _ conventi on . html
- https://towards data science . com/unit-testing-for-data-scientists-DC 5 E0 CD 397 FB
结论
数据科学家通过制作不与公司系统和基础设施进行任何通信的报告和 jupyter 笔记本找到出路的日子已经一去不复返了。
如今,数据科学家开始开发可测试和可运行的代码,与 IT 系统无缝集成。因此,遵循软件工程最佳实践成为必须。我希望这篇文章能让你对这些最佳实践有一个大致的了解。
感谢阅读!
新到中?您可以每月订阅 5 美元,并解锁各种主题的无限文章(技术、设计、创业……)您可以通过点击我的推荐链接来支持我
https://ahmedbesbes.medium.com/membership 
软件!在!太空!
原文:https://towardsdatascience.com/software-in-space-23a6c5aa0521
当人们想到太空探索时,他们往往会想到直冲云霄的火箭。但是成功的任务不仅仅是宇宙飞船。

是的,太空中已经有软件了!作者图片
当我们想到太空探索时,我们往往会想到宇航员、火箭或国际空间站。也许我们还会想到坐在中国或美国航天局办公室里的一组专家,当他们成功地在火星上着陆时,爆发出阵阵喜悦。
我们往往会忽略那些编写软件的人,这些软件让卫星在轨道上运行,让火箭在轨道上运行。许多人在火箭发射前筛选来自卫星传感器的数据或模拟火箭发射。他们也在做火箭科学。但是这样想就不那么直观了。
我们在媒体上看到的许多图像显示,专家团队在庆祝自己,或者酷的漫游者和火箭在外层空间巡航。它们满足了我们人类的好奇心和我们对跨越新的边界和扩展我们视野的永恒渴望。同时,这些类型的故事让事情变得足够简单。任何人都可以意识到人类已经在火星上登陆了一些漫游者。另一方面,需要大量的专业知识来了解火星车是如何建造的,驾驶它需要什么,以及哪些技术使它适合火星上的生活。
许多人想了解太空。他们想知道它看起来像什么,以及人类正在做什么来探索它。但是如果没有详细的知识,很难理解太空技术到底是如何工作的。
这就是成为一名软件工程师的好处。即使你不太了解物理,或者火箭材料,编码人员也能理解太空中使用了什么类型的软件技术,以及为什么。
虽然美国宇航局公开了很多代码,但很难找到空间技术软件工程师日常活动的细节。不过,埃隆·马斯克的项目中也有一些故事。考虑到在 SpaceX 或 Starlink 工作是许多工程师的梦想,这些将是我在这里的重点。
[## 艾是来找你工作的吗?
towardsdatascience.com](/is-ai-coming-for-your-job-2f593ab72b55)
Starlink,卫星计算自己的路线
早在 1945 年,当科幻作家亚瑟·C·克拉克第一次提出卫星电视时,这听起来像是一个白日梦。尽管花了三十年,这项技术最终成为现实。现在,许多人在他们的屋顶上有卫星接收器,并且认为它没什么。卫星相对于有线电视的主要优势是它们可以到达农村地区,这对于很长的有线电视来说是不划算的。
同样,卫星互联网对许多人来说听起来仍然像是白日梦。但是需求是存在的:四分之一的美国农村人认为他们缺乏高速互联网接入是一个主要问题。断断续续的互联网接入也是火车、飞机和轮船等移动物体的一个问题。任何试图在旅行中使用 WiFi 的人都可以证明这一点。
然而,这些问题可能很快就会得到解决。Starlink 是私营部门火箭先锋 SpaceX 的一个分支,正在为更广泛的互联网接入奠定基础。Starlink 互联网于 2015 年首次发布,如今已经在美国许多地方推出。
为了确保互联网不会太慢,卫星需要离地球非常近。因此,它们每次只能在头顶上停留几分钟。因此,与它们通信的地面天线需要经常改变与哪个卫星通信。并且卫星网络需要足够密集,以便在任何给定时刻为天线提供信号。
该网络由数百颗卫星组成;新的不断被添加,旧的不断被替换。因此,Starlink 软件负责人 Andy Bohn 说团队没有时间将每颗卫星送入自己指定的轨道。相反,每颗 Starlink 卫星都自己导航。为了管理繁忙的交通状况,地球端的网络给每颗卫星一个位置,卫星把自己控制在它的位置上。
这个过程需要巨大的计算量。首先,卫星不仅有相互碰撞的风险。它们也可能与低轨道上的飞机和其他卫星相撞。Starlink 卫星已经参与了一半的太空中的近碰撞,其中两个物体彼此之间的距离小于 1 公里(0.6 英里),所以这种风险是真实存在的。

卫星需要处理大量数据。作者图片
第二,干扰的可能性导致大量的计算需求。当两颗卫星的信号重叠时,它们可能会失真,甚至相互抵消。为了避免干扰,需要将信号放入稍微不同的频段。但这并不像听起来那么简单,而且可能的频段数量有限。因此,波段过于相似的两颗卫星不能靠得太近。这一要求使卫星导航更加复杂。
你可能想知道为什么卫星的位置需要在地球上计算,而不是直接在卫星上计算。首先,如果卫星内部出了问题,去那里修理就困难多了。此外,在外层空间,事情比在地球上更容易出错。因为地球大气层外的太阳辐射强得多,比特更容易翻转。比特是所有计算机的 0 或 1 编码单位,当它们翻转它们的值时,会破坏整个软件程序。为了防止这种情况扰乱卫星的轨道,不同的机器共享软件,如果软件损坏,可以重新加载正确的副本。
Starlink 的软件是用众所周知的编程语言编写的。由于其可靠性和裸机编程能力,Starlink 在其卫星中使用 C++编写大部分代码。该公司还使用 Python 进行一些原型开发,因为它通常内置起来更快。这反映了开发者在自动驾驶汽车技术中的应用。
卫星互联网是一个非常雄心勃勃的项目,它伴随着许多困难的挑战。Starlink 无疑是这一领域的先驱,但其他公司和太空机构也在迅速跟进。一二十年后,它可能会像今天的卫星电视一样成为标准。
https://uxdesign.cc/product-designers-are-clashing-with-developers-and-its-ugly-59e9875d9866
SpaceX,还是努力不失败
同样雄心勃勃的是 SpaceX,Starlink 是它的一个分支。向外太空发射火箭、与国际空间站对接,或者瞄准火星都需要近乎完美的硬件和软件工程。测试当然可能会失败。但在最后的任务中,不允许出现任何差错。如果火箭系统的一部分不能正常工作,所有其他部分都需要补偿这一故障。
SpaceX 火箭的所有飞行软件都是围绕控制周期构建的。首先,读取所有输入,例如来自传感器的数据或来自地面的命令。然后,这些数据得到处理,重要的事情得到计算,如火箭的位置或生命支持系统的状态。然后程序进入睡眠状态几分之一秒,以节省计算能力,之后整个循环再次开始。
不同的子系统控制火箭的不同部分。为了防止大的灾难,这些需要彼此隔离。例如,如果驾驶飞机的导航系统出了问题,生命支持系统也不需要陷入混乱。如果有一件事出了差错,演出必须继续进行。
这种设置与许多其他科技公司的运营方式不同。以谷歌为例。他们记录每一次失败,选择那些看起来最重要的,并试图从中为未来吸取教训。换句话说,谷歌让失败发生,并试图从失败中吸取教训。
对于谷歌来说,这种方法非常有效。但是搜索引擎(以及翻译器、文档编辑器、云服务提供商等等)的操作与火箭略有不同。如果谷歌的一个进程失败了,也许一个搜索查询会返回可怕的结果。然而,如果载人火箭转向错误的方向,人类的生命将处于危险之中。
由于所解决问题的高风险性质,SpaceX 尽最大努力避免失败。虽然该公司的工程师确实接受火箭测试失败,但在这些情况下,他们几乎是故意让项目失败,以便为未来学习。然而,当火箭开始真正的任务时,一切都需要工作。这意味着即使火箭的一部分发生故障,它也必须保持完整。

虫子永远不会让太空任务失败。作者图片
测试、测试和测试代码
火箭软件需要尽可能的可靠。因此,毫不奇怪,美国国家航空航天局(NASA)和 T2 太空探索技术公司(SpaceX)的质量要求很高,尤其是与常规商业应用相比。精心设计的系统已经到位,以确保没有人通过将错误的东西与主分支合并来破坏代码。也就是说,SpaceX 的测试相关工具在软件开发领域都是前所未闻的。
在开发人员可以发出拉请求之前,他们需要满足一组详细的标准。在合并之前,代码要经过两次测试,在实际合并之后还要再测试一次。
SpaceX 的持续集成环境很大程度上基于 HTCondor,其元数据用 PostgreSQL 管理。此外,该公司使用 Python 进行后端测试运行,构建流程编排和 web 服务。对于这些 web 服务的前端,它使用 Angular,JavaScript 和一些 TypeScript。在集装箱化方面,SpaceX 使用 Dockers,以及一点点 Kubernetes。
因此,工具和语言的选择与你在陆地公司的期望非常相似。然而,满足质量要求和合并要严格得多。
构建帮助建造火箭和卫星的软件
除了部署在火箭和卫星内部和周围的软件,航天项目还涉及应用软件。这种类型有助于将火箭带到发射台,并准备发射,涉及供应链、制造、金融、库存等领域。
随着许多行业的趋势,SpaceX 的应用软件已经从单一架构转向微服务,具体来说就是从 AngularJS、C#和 MySQL 转向 Angular、PostgreSQL 和容器化。其优势在很大程度上与 SpaceX 的所有其他系统相同:如果一个部件损坏或等待维修,这种延迟不会对其他部件产生太大影响。
SpaceX 的应用软件部门与其他公司的同类部门不同之处在于,他们有四个非常不同的项目需要支持:向外太空运送货物的猎鹰、专注于载人航天的龙、专注于星际运输的 Starship 和卫星互联网的 Starlink。这个项目范围甚至使它与美国国家航空航天局有所不同。
与其他领域一样,太空技术公司使用的工具和遵循的趋势与其他公司基本相同,但项目的范围和种类比大多数地面公司要多得多。
换句话说,如果你是一名经验丰富的软件开发人员,并且正在考虑在 NASA、SpaceX 或 Starlink 工作,那么你不需要学习更多的工具和框架。但是你应该为更多样的任务、更高的质量要求和更紧张的工作做好准备。

我们应该大肆宣传太空飞行吗?作者图片
太空软件也让地球人受益
当我们甚至不能正确处理我们在地球上的问题时,我们有理由问为什么要探索外层空间。在持续的疫情,种族和社会不平等,洪水和野火,加上所有生活中的小问题,难道我们不应该把目光从天空移开一分钟吗?
不。这是真的,每一次火箭发射都燃烧了数量惊人的燃料。没错,每一个在星际飞船上工作的软件开发人员都不是在开发一个打败疫情的应用程序,或是为贫困社区开发一个支付处理器。诚然,投资于外层空间的每一美元并没有投资于公平的住房、更好的教育或保护野生动物。
那些火箭发射、工人和美元以其他方式回来。例如,美国国家航空航天局的开源软件可以帮助减少飞机排放,计算太阳能系统的大小和功率需求,或者优化风力涡轮机的效率。因此,通过为外层空间编写代码,一些开发人员可能只是在为其他领域变得更加绿色做出贡献。
此外,私营公司在太空中的崛起并不一定是件坏事。如果一小群富人因为把自己发射到月球或更远的地方而损失了一部分钱,那就这样吧。
通过制定明智的法规,我们确实需要确保这些人不会殖民太空和重复历史。这些法规的存在确保没有一个国家将太空称为自己的领土,每个国家都可以自由探索太空,不允许任何实体对太空或环境造成损害,等等。只要我们确保这些规则得到尊重,我们就不会拿不太富裕的人的未来冒险,我们不会浪费税收,我们可以获得开源代码的好处,我们可以满足人类对新领域的好奇心。听起来对我来说是三赢三赢。
本文原载于 内置于 。
成为 中等会员 对我的内容拥有完全访问权限。
太阳能电池板发电分析
原文:https://towardsdatascience.com/solar-panel-power-generation-analysis-7011cc078900
你的太阳能电池板能产生多少能量?做出你自己的计算来保持控制

玛丽安娜·普罗恩萨在 Unsplash 上的照片
在过去的几个月里,我一直在选择一家供应商为我的房子安装太阳能电池板。我注意到的是,所有供应商都使用他们自己的计算方法,而我的房子没有默认朝向,这让他们很难接受。我的处境很不幸,大部分太阳能电池板需要安装在垂直的墙上,而不是屋顶上。
因此,为了比较不同供应商的发电量,并对倾斜 90 度的电池板进行良好的计算,我开始自己进行计算。为此,我创建了一个计算方法,您可以为几个具有各自特征的配线架位置输入自己的配置。这些位置的结果将被合并。例如,不同的位置可以是你房子的前后屋顶。
获取太阳辐射信息
我开始做自己的太阳路径计算,但在 github 找到了优秀的 pvlib 包。它帮我解决了大部分问题,拯救了我的一天。
pvlib 包用于确定太阳辐射量和太阳能电池板的发电量。在我的案例中,它使用了欧洲委员会提供的 2005 年到 2020 年的太阳辐射数据。使用真实生活数据,而不是一直有阳光照射的一些最佳情况。
以下代码获取一组面板的数据:
获取太阳能电池板电网的太阳辐射和发电
这种方法采用位置(纬度、经度)和面板配置来获取辐射和功率数据。面板配置包括面板数量、方位角、倾斜角和峰值功率。else 语句和以下代码需要能够指定零个面板。当未指定面板时,库无法处理“0”的峰值功率。对于不同布局选项的比较,指定零可能是有用的。所使用的数据源包含 2005 年至 2020 年的数据。
一个请求产生一个数据帧:

获取 _ 面板 _ 功率 _ 数据的结果(图片由作者提供)
该数据框包含 2005 年 1 月 1 日到 2020 年 12 月 31 日之间每天每小时的太阳辐射和发电量。
请注意,方位角“0”是指南方,而不是北方。正方位是东方,负方位是西方。
面板位置
并非所有面板都可以放置在同一个屋顶上,因此我们希望能够指定几个位置的配置(例如,屋顶、棚子上、地面上、墙上等)。这种配置如下:
[{'name': 'front', 'tilt': 35, 'azimuth': 30, 'nopanels': 2, 'power': 0.385},
{'name': 'back', 'tilt': 35, 'azimuth': 150, 'nopanels': 8, 'power': 0.385}]
可以指定每个部分的方位角(南= 0°)、倾斜度、面板数量和每个面板的峰值功率。如果使用不同的面板,则需要最后一个。
围绕obtain_power_panel_data方法构建了一个包装器,它接受配置并获取每个屋顶/部分的数据。
此方法接受包含面板位置的字典,并返回包含所有面板的太阳能数据的数据框。它还获得太阳位置(第 27-30 行)并将其添加到太阳辐射信息中。为了方便起见,增加了月份和季节栏。
一个示例用法是:
这指定了位置名称“front ”,两个面板在屋顶上以 35 度角向西南方向看。第二个位置朝向西北方向,包含 8 个相同角度为 35 度的面板。使用相同的太阳能电池板,峰值性能为 0.385 kW。
可以用一行代码创建字典,但是数组是为了可读性。生成的数据帧为:

综合太阳数据(作者截图)
这是我们评估所需的完整数据集;对于每组太阳能电池板,每天的每个小时都有太阳辐射和产生的电力可用。每个记录还包含太阳在天空中的位置。我们现在准备评估太阳能电池板的性能。
一天中的表现
首先,我们将评估一天的表现。为此,我们首先在数据集中搜索辐射最高的一天。然后我们画出这一天的发电量。每个屋顶和总发电量。
首先,我们搜索产量最高的一天。在这种情况下是 2020 年(第 35 行)。过滤今年的数据集(第 2 行),然后计算每天的发电量总和(列“P”)(第 3 行),返回一个数据框,其中日期为索引,发电量为列。用idxmax (第 4 行)找到最大值后,相应的日期以字符串形式返回,格式为 2020–05–28 第 5 行)。
这个日期和完整的数据帧被提供给plot_a_day方法,该方法产生:

一天的发电量(图片由作者提供)
在过滤给定日期的数据(第 7 行)后,生成了两个图。左图显示了一天内每单位时间的发电量,右图显示了一天内的累计发电量。单独的面板位置用虚线标出,所有面板的总数用实线标出。
第 9 行为图形创建了两个轴。第 10 行遍历所有面板位置。第 11 行过滤当前位置的数据,并在左图中用虚线绘制每小时的数据(day_data[day_data.location == name][‘P’])。第 12 行绘制了右侧图中的累积数据(…[‘P’].cumsum())。第 13 行和第 14 行将每日总数添加到图表的右侧。第 16 行到第 19 行做了同样的事情,但是是针对所有位置的合计。最后,第 21 到 31 行格式化轴、图表并添加适当的标签。
过去几个月的业绩
下一步是查看一年中几个月的表现:
这将生成每月发电量和全年累计发电量的概览:

一年的发电量(图片由作者提供)
代码遵循的结构与一天的图表大致相同,但过滤是在一年的水平上完成的,而汇总是在几个月内完成的。
此外,第 8 行计算每月的平均值,第 9 行将该值绘制为水平虚线,第 10 行在该行旁边绘制平均值。
多年来的业绩
数据框包含 2005 年至 2020 年的数据。这意味着我们可以计算多年来的性能(不考虑性能下降)。这模拟了太阳能电池板在此期间已经就位的情况:
导致:

历年表现(图片由作者提供)
同样,该方法从汇总数据开始,但现在是每年一次。然后(第 5-7 行)画出每月发电量和累计总和。添加每月的平均值(第 13-14 行),最后格式化图表。
正如我们在这张图表中看到的,每年的业绩远非稳定。在本例中,每年的发电量在 2800 千瓦时和 3200 千瓦时之间波动,具体取决于每年的天气情况。
奖励:季节性表现
有了太阳能电池板,你一年的总发电量就差不多了。但是在这一年中,会有一些惊人的结果,这取决于你的地理位置。太阳的路径在一年中是不同的,这会影响太阳能电池板的效率。当我们选取本文中的面板位置并绘制每个季节中的一天(发电量最高的一天)时,可以看到一些显著的结果:

季节性表演(图片由作者提供)
该图显示了一天中的太阳位置、太阳的高度以及每个电池板位置的发电量。在秋季和夏季,面板“背面”比面板“正面”表现更好(3 倍)。但在冬季和秋季,差异很小(约 1.2 倍)。“前”面板的性能在一年中相对稳定,除了秋季。
绘制这些图表有点复杂:
plot_seasons 方法过滤请求年份的数据(第 22 行)并确定最大发电功率(第 23-24 行),四舍五入到十位,这将用于为所有图表提供相同的 y 轴限值。接下来,为这四个图创建一个网格(第 26–27 行)。
对于每个季节,发电量最高的一天由get_best_day_of_season 确定,这一天绘制在四个网格区域之一。
plot_day_extended方法将轴分为左轴和右轴,并在左轴(第 9-10 行)绘制太阳高度和天顶,在右轴(第 11-12 行)绘制面板性能。第 13–19 行完成了图形的格式化。
结论
pvlib 库简化了太阳能电池板性能的计算。这使得比较不同承包商的报价更加容易。他们的报价都使用不同的方法来计算有效性,与上述代码,他们可以比较等效。
财务影响的计算不在此比较范围内,因为这高度依赖于经济环境和低点。比较产生的功率更透明。
完整的笔记本可以在 github 上找到。作为额外的奖励,它包含将地址地理编码为经度坐标的代码,以简化使用。可以在倒数第三个单元格中指定地址和面板位置。尽情享受吧!
遗言
我希望你喜欢这篇文章。要获得更多灵感,请查看我的其他文章:
如果你喜欢这个故事,请点击关注按钮!
免责声明:本文包含的观点和看法仅归作者所有。
908

被折叠的 条评论
为什么被折叠?



