TowardsDataScience 博客中文翻译 2020(一百四十五)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

银行机构定期存款预测模型

原文:https://towardsdatascience.com/bank-institution-term-deposit-predictive-model-9f0b7c2fd38f?source=collection_archive---------18-----------------------

不同机器学习模型在银行定期存款预测中的比较。

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

蒂姆·埃文斯在 Unsplash 上拍摄的照片

简介

葡萄牙银行的投资和投资组合部门希望能够识别出有可能认购其定期存款的客户。由于营销经理越来越有兴趣仔细调整他们的定向活动,以严格选择联系人,手头的任务是找到一个模型,可以预测哪些未来客户将订阅银行的定期存款。
在这篇文章中,我将讨论数据探索、数据清理、特征提取、处理类别不平衡,以及开发一个强大的机器学习算法来预测哪些潜在客户将使用不同的机器学习库来订阅定期存款。包含所有代码的 Github 库在这里可以找到

套餐

下面是使用的不同的机器学习和 python 包。

探索性数据分析

探索性数据分析通常是每个数据科学项目的初始过程。通常,对数据进行初步调查以识别模式、异常值、不平衡以及检验先前的假设是至关重要的。汇总统计和可视化主要用于执行探索性数据分析。

"没有常规的统计问题,只有可疑的统计常规."大卫·考克斯爵士

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

定期存款的认购利率

从上面的输出中,可以提取数据的一些模式。根据潜在客户是否认购定期存款对数据进行分组表明,大多数客户没有认购定期存款,88.7%的客户拒绝认购,而 11.3%的客户接受了认购要约。我们试图预测的这种阶层比例的显著差异导致了不平衡的数据。

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

一组基于婚姻状况的订阅费率

上面的输出显示了订阅定期存款的客户群和根据婚姻状况拒绝订阅的客户群。

数据预处理

使用 PyOD 清除异常值

异常值是与其他观察值显著不同的数据点,这可能是由于测量中的可变性,或者它可能表明实验误差。在不检查和处理异常值的情况下训练机器学习模型的诱惑通常是失败的原因。数据中的异常值会极大地影响模型的准确性,但是简单地从数据中移除异常值而不考虑对结果的影响是一种不好的做法,因为异常值并不总是一件坏事。

“离群值不一定是坏事。这些只是观察结果,与其他观察结果没有遵循相同的模式。但是异常值可能是非常有趣的。例如,如果在一个生物实验中,一只老鼠没有死,而其他所有的老鼠都死了,那么理解为什么会这样会很有趣。这可能会导致新的科学发现。因此,检测异常值非常重要。”皮埃尔·拉法叶·德·米肖,作家和统计学家。

检测异常值的常见做法是使用箱线图、直方图和散点图。这种方法在大型数据集中可能效率不高。PyOD,python 库有不同的算法,可以用来检测和清除异常值。对于这种情况,我们使用 k-最近邻检测器。

一键编码

数据集通常包含数字和分类变量,但机器学习算法只理解数字而不理解文本,这就是为什么我们需要转换或变换分类变量,这一过程称为分类编码。有两种类型的分类编码:

  • 标签编码
  • 一键编码

当分类列中的类别包含具有某种顺序或层次结构的数据时,标签编码非常有用。One-Hot 编码的工作方式是,根据列中类别的数量,将要编码的列分成多个列。然后,根据哪一列有什么值,类别被替换为 1 和 0。我们还使用 StandardScaler 来重新调整所有数字列。这是有用的,因为一些变量经常在不同的尺度上测量,并且不会对模型拟合做出同等贡献,这可能导致训练的模型产生一些偏差。

处理不平衡数据

在不平衡的数据集上训练机器学习模型可能会导致不准确的预测。在这种情况下,我们使用随机抽样技术来处理不平衡数据。随机过采样的工作原理是从少数类中随机采样数据,并复制它以创建更多的样本,这个过程一直重复,直到分布相等。
随机采样技术的缺点之一是,它可能会导致过度拟合,因为它会复制现有的少数数据集。

利用主成分分析进行维数约简

降维是一种减少数据集中输入变量或特征数量的技术。更多的输入特征通常会使预测建模任务对模型更具挑战性,这被称为维数灾难。有不同的降维技术,如自动编码器和 t-SNE,这是一种概率技术。对于我们的情况,我们使用主成分分析(PCA)进行降维。PCA 执行数据到低维空间的线性映射,使得低维表示中数据的方差最大化。我们只对特征进行了 PCA,不包括标签。

系统模型化

下面的代码片段显示了我在比较不同建模算法时使用的一种方法。初始化参数时需要四个参数

  1. 型号类型。对于这个案例,我使用了 XGBoost 分类器、多层感知器分类器**、**逻辑回归和支持向量机。
  2. 交叉验证技术,即 k 倍或分层 k 倍
  3. x 是数据集的特征
  4. 哪个是标签

不同模型的初始化

结果和结论

在所有选择的模型中,即使使用超参数调整,XGBoost 分类器也具有更高的准确度分数。下图显示了所使用的 XGBoost 模型的不同指标得分。使用分层 k 倍和 k 倍交叉验证时,得分略有显著差异。分层 k 倍比 k 倍有更高的分数。

Accuracy scores of the model: 0.88

 Classification report of the model
--------------------------------------
              precision    recall  f1-score   support

           0       0.89      0.87      0.88      3442
           1       0.88      0.90      0.89      3537

    accuracy                           0.88      6979
   macro avg       0.89      0.88      0.88      6979
weighted avg       0.89      0.88      0.88      6979

 Confusion Matrix of the model
--------------------------------------
[[2993  449]
 [ 354 3183]]

我们的模型的准确率为 0.88,精确度和召回率高于 0.87。

使用 k 倍交叉验证时的 ROC 图显示得分为 0.88。

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

k 倍 ROC 图

当使用分层 k 倍时,得分增加了 0.01

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

分层 k 倍 ROC 图

由于 XGBoost 对少数类具有更高的精确度、召回率和 f1 分数,而少数类是潜在客户是否会认购定期存款的更重要的分类,因此银行应使用 XGBoost 模型。通过不同的超参数调整技术,模型可以得到更高的分数。

尊重并感谢我所有的同学和10 学院的工作人员,感谢他们的支持。

参考

[## 如何配置 k 倍交叉验证-机器学习精通

k-fold 交叉验证过程是评估机器学习性能的标准方法。

machinelearningmastery.com](https://machinelearningmastery.com/how-to-configure-k-fold-cross-validation/) [## Python -机器学习掌握中的 4 种自动离群点检测算法

分类或回归数据集中异常值的存在会导致拟合不佳和预测性降低…

machinelearningmastery.com](https://machinelearningmastery.com/model-based-outlier-detection-and-removal-in-python/) [## 使用 PyOD 库学习 Python 离群点检测的精彩教程

我最近的数据科学项目涉及预测特定商店中每种产品的销售额。有几个…

www.analyticsvidhya.com](https://www.analyticsvidhya.com/blog/2019/02/outlier-detection-python-pyod/) [## 。神经网络。MLP 分类器-sci kit-学习 0.23.2 文档

sklearn.neural_network 类。MLP classifier(hidden _ layer _ sizes =(100,),activation='relu ',*,solver=‘adam’…

scikit-learn.org](https://scikit-learn.org/stable/modules/generated/sklearn.neural_network.MLPClassifier.html) [## Python API 参考-xgboost 1 . 3 . 0-快照文档

本页给出了 xgboost 的 Python API 参考,更多内容请参考 Python 包介绍…

xgboost.readthedocs.io](https://xgboost.readthedocs.io/en/latest/python/python_api.html) [## 3.2.4.3.1.sk learn . ensemble . randomforestclassifier-sci kit-learn 0 . 23 . 2 文档

class sk learn . ensemble . RandomForestClassifier(n _ estimators = 100,*,criterion='gini ',max_depth=None…

scikit-learn.org](https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html)

依靠人工智能

原文:https://towardsdatascience.com/banking-on-ai-27d4d39bda1c?source=collection_archive---------63-----------------------

利用人工智能在新的十年里重塑银行业

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

UnsplashNeONBRAND 拍摄的照片

我们的银行系统今天面临着日益激烈的竞争。创新服务正在兴起,从而使我们几十年来所熟知的传统银行业慢慢过时。对客户来说,更便宜、更方便的 24 小时自助银行服务似乎成为一种趋势。所有这一切都发生在一个全球环境中,在这个环境中,法规遵从性变得越来越严格,安全风险呈指数级增长。最后,随着交易以光速进行,数据量正以创纪录的速度增长,从而使有效决策变得困难。当然,所有这些目标对传统银行来说可能听起来令人生畏,但在人工智能(AI)的帮助下,它们可以轻松实现。让我们来看看将传统银行转变为金融科技机构的技术。

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

照片由奥斯丁·迪斯特尔Unsplash 上拍摄

数字银行助理为用户提供金融指导和访问银行提供的各种服务。人们可以把他们看作是一个个性化的收银员,他们知道每个客户的名字,并随时准备给他们提供他们想要的所有信息。这种系统利用人类语言技术(HLTs ),该技术使用自然语言(例如英语、汉语等)与用户对话。).这项技术极大地提高了用户的整体体验,因为用户与虚拟助理进行交互,就好像他在与另一个人交谈一样。此外,该助理能够追加销售其他银行产品,从而帮助客户探索新的可能性。

客户档案是人工智能可以提供帮助的另一个领域。通过查看人口统计和历史数据,银行可以根据客户的风险状况自动对客户进行分类。然后,顾问可以利用这些信息,根据客户的个人资料,以自动化的方式为客户提供不同的金融产品。使用这种系统的优点是客户不会受到数据引起的偏差的影响。此外,由于人工智能不断更新客户的资料,它可以立即注意到任何增长的风险,并在为时过晚之前向银行发出警报。

合同分析是一项有些重复的任务,需要大量资源。正因为如此,经理和顾问可以将这项任务分配给人工智能助理。光学字符识别(OCR)可用于将文件(打印和手写)数字化,并将其发送至合同分析器。然后,自然语言处理(NLP)模块将解释文本、分析文本并应用业务规则。所应用的业务规则可以不同;从简单的(比如检查复选框的状态)到极其复杂的(比如检查文本背后的逻辑)。人工智能模型使用过去的合同进行训练,从而大幅提高其准确性。像 JP 摩根这样的大公司报告说,使用这种方法;他们设法将每年 36 万小时的工作压缩到几秒钟内完成。一旦系统完成处理,它会以非常高的速度提供带有建议纠正的警报,并由经理或顾问进行审查。

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

内森·杜姆劳Unsplash 上拍摄的照片

在这样一个竞争激烈的环境中,客户流失是另一个令人头疼的问题。人工智能有利于根据客户与银行的互动(或缺乏互动)来预测客户流失。该系统可以快速分析有关客户的所有数据,做出预测,并创建一个优先客户名单,这些客户可能会终止与该银行的业务。然后,经理可以直接干预客户,希望留住他们,或者至少理解他们为什么选择一家与之竞争的银行。研究表明,获得一个新客户比留住一个现有客户要困难和昂贵得多。在这种情况下,大众营销会失败,因为顾客是如此的多样化,以至于信息无法传递。因此,客户分析和流失预测对于创建针对特定客户的营销计划至关重要。

算法交易利用人工智能技术交易股份、股票等。它通过分析来自不同来源的数据来实现这一点,如过去的历史数据、新闻条目等。做出难以置信的快速决策。在这些数据中发现的模式很难被人发现,或者说一个人不可能迅速处理这些海量信息。当然,计算机可以相当快地自动执行交易,并以闪电般的速度完成买卖。

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

米歇尔·汉德森在 Unsplash 上的照片

自动化研究工具处理批准或拒绝金融投资所需的背景研究。这项任务对于人类来说非常耗时,但对于人工智能来说,却相当简单。该系统能够对关于个人或公司的信息进行情感分析。它可以检测人们对该实体的看法是消极还是积极,从而为管理者提供关键信息。先进的语言处理技术可以帮助研究人员通过放大关键主题和自动突出特定段落来快速浏览公司的财务报告。

投资的自动估价是人工智能的另一个应用。使用诸如年龄、历史值等各种特征。;该系统可以计算资产的价值。传统上,这种系统最初用于房地产,以计算房屋的估价。然而,金融公司通过查看经济指标、增长预测等采取了类似的方法。以得出最终的估计。

这些只是银行业使用人工智能的几个例子。在未来几年,我们预计会看到更多的创新,涉及运营、营销、销售、客户体验、收入和交易质量等方面。人工智能是一种工具,它将永远改变我们的银行方式,并引领现代银行时代的到来。我们的银行不能停滞不前,否则就会倒闭。正如一句古老的中国谚语所说…

“不要害怕慢慢成长;只怕站着不动。”

本文原载于https://www.businesstoday.com.mt请在下面留下你的想法评论。如果你喜欢这篇文章,请跟我来🐦推特,🔗 LinkedIn 或者😊脸书

* [## 一个全新的人工智能世界

疫情之后人工智能的兴起

towardsdatascience.com](/a-whole-new-ai-world-6a5e9e49aa12) [## 杀死汽车保险商

正如我们所知,人工智能正在如何改变汽车保险

towardsdatascience.com](/killing-the-motor-underwriter-cb11317cda98) [## 在 2020 年推动您的小型企业

毫无疑问,2019 年是人工智能(AI)年。我们听说了很多,但很多人不确定…

towardsdatascience.com](/boosting-your-small-business-in-2020-6ae3529cbfb0)

阿列克谢·丁力教授 是马耳他大学的 AI 教授。二十多年来,他一直在人工智能领域进行研究和工作,协助不同的公司实施人工智能解决方案。他的工作被国际专家评为世界级,并赢得了几个当地和国际奖项(如欧洲航天局、世界知识产权组织和联合国等)。他出版了几本同行评审的出版物,并且是马耳他的一部分。由马耳他政府成立的人工智能工作组,旨在使马耳他成为世界上人工智能水平最高的国家之一。*

Python 条形图竞赛动画:新冠肺炎案例

原文:https://towardsdatascience.com/bar-chart-race-animation-with-python-covid-19-cases-43655a47ed23?source=collection_archive---------20-----------------------

变更数据

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

条形图比赛 GIF

八个多月来,新冠肺炎已经摧毁了许多国家。100 万病例已经得到证实,而且这个数字每天都在增加。

感谢谷歌为我们公开和免费提供了 Corona 数据集。它使我们有可能做我们自己的与这个疫情相关的分析,例如,创建条形图比赛动画。数据存储在谷歌云平台上,可以在这里访问

收集数据

首先在bigquery-public-data数据集中找到名为covid19_open_dataBigQuery 表。

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

新冠肺炎数据集。作者图片

共 45 栏,逐日呈现各个国家(和地区)的电晕案例信息。您可以根据要进行的分析类型,专门选择要下载的数据。例如,我运行下面的 SQL 来检索日期、国家、地区和发生的案例数。

SELECT
  date,
  country_code,
  country_name,
  subregion1_name,
  COALESCE(new_confirmed,0) AS new_confirmed,
  COALESCE(new_deceased,0) AS new_deceased,
  COALESCE(cumulative_confirmed,0) AS cumulative_confirmed,
  COALESCE(cumulative_deceased,0) AS cumulative_deceased,
  COALESCE(cumulative_tested,0) AS cumulative_tested
FROM
  `bigquery-public-data.covid19_open_data.covid19_open_data`

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

查询结果。作者图片

您可以将结果保存到。CSV 文件,稍后使用 Python 打开它。

准备数据

现在,让我们用 Python 来转换数据。首先要做的是打开 Jupyter 笔记本,然后导入必要的包来转换和可视化数据。之后,打开。csv 文件并将其保存为 DataFrame 对象。

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import matplotlib.animation as animation
import numpy as np
import matplotlib.colors as mcimport colorsys
from IPython.display import HTML
from datetime import datetime
from random import randintdf = pd.read_csv ('covid19-20200917.csv')

为了利用数据,我们需要首先了解数据的特征。您可以通过查看数据类型和每一列的值来探索它。

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

作者图片

从上面的结果中,我们知道在国家代码子区域 1 名称列中有空值。

就我而言,分析的目的是创建一个从 2020 年初到去年 8 月每个国家确诊病例总数的条形图。我们可以依赖数据集中的三个主要列;日期国家名称累计确认。这些列没有空值,所以我们可以继续下一步。

通过使用熊猫,总结每个国家每天的累计确认总数。然后,检查结果。例如,我使用2020-08-31作为日期参数

df = pd.DataFrame(df.groupby(['country_name','date'])['cumulative_confirmed'].sum()).reset_index()current_date = '2020-08-31'
dff = df[df['date'].eq(current_date)].sort_values(by='cumulative_confirmed', ascending=False).head(15)

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

8 月确诊病例最多的 15 个国家。作者图片

将数据可视化

然后,我们可以开始使用 Matplotlib 来可视化它。

fig, ax = plt.subplots(figsize=(15, 8))
sns.set(style="darkgrid")
ax.barh(dff['country_name'], dff['cumulative_confirmed'])

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

作者图片

要创建条形图比赛动画,我们需要用某种颜色将每个国家分组。所以,不管国家的位置在哪里,看它的颜色还是可以追踪到的。

主代码在。ipynb 格式。由于美观的需要,这个特定的功能被分离到一个. py 文件中。

这个方法的主要作用是给每个国家颜色,这个颜色是随机确定的。定义了颜色的变换方式后,我们就可以继续画柱状图了。

主代码在。ipynb 格式。由于美观的需要,这个特定的功能被分离到一个. py 文件中。

在上面的方法中,我们对数据框中的数据进行了排序,因此只有每个日期确诊病例最多的 15 个国家将出现在条形图中。然后,我们给颜色的酒吧和它的属性。对于每个日期,我们提取要在条形右侧强调的月份名称。

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

条形图设计

如果我们使用2020-08-31作为日期参数,上面的图表就是 draw_barchart 方法的结果。你可以根据自己的喜好调整代码来装饰条形图。

完成条形图设计后,我们需要做的就是定义将要出现在条形图动画范围内的日期。

dates=pd.Series(pd.to_datetime(df[‘date’].unique()))dates=dates.where(dates < ‘2020–09–01’)dates.dropna(inplace=True)
dates = dates.astype(str)

就我而言,我排除了 2020 年 9 月之前的日期。日期范围如下所示:

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

日期范围。作者图片

**最后,**我们到了神奇的部分,动画!我们可以利用 matplotlib.animation 创建一个动画。

import matplotlib.animation as animation
from IPython.display import HTMLfig, ax = plt.subplots(figsize=(15, 8 ))
animator = animation.FuncAnimation(fig, draw_barchart, frames=dates)
HTML(animator.to_jshtml())

瞧啊。这是结果。

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

条形图竞赛

要将动画保存为 GIF 格式,我们可以使用以下简单的代码行。

animator.save('covid_til_august.gif', writer='Pillow')

结论

有很多方法可以处理数据,因为有很多工具可以支持我们。BigQuery 帮助我们获取和查询数据,Pandas 帮助我们转换和聚合数据,Matplotlib 帮助我们可视化数据。尽管如此,仍有很大的探索空间。

现在,您可以创建自己的条形图并进行自己的分析。你可以在这里看到 Jupyter 笔记本文件的完整代码。快乐尝试,保持健康!

参考

[1] P. Vardhan,用 Matplotlib 在 Python 中进行条形图竞赛(2019),https://medium.com/r/?URL = https % 3A % 2F % 2f pratapvardhan . com % 2f blog % 2f bar-chart-race-python-matplotlib % 2F

[2] G. Berardi,用 Python 创建平滑条形图竞赛(2020),https://www . datasciencecoffee . com/2020-Smooth-Bar-Chart-Race/

与 Plotly 进行条形图竞赛

原文:https://towardsdatascience.com/bar-chart-race-with-plotly-f36f3a5df4f1?source=collection_archive---------22-----------------------

巴塞罗那最常见的婴儿名字

最近,动画条形图变得非常流行,尽管它们看起来很难创建,但事实是使用像这样的库,它们很容易执行。在这篇文章中,我们将一步一步地解释如何制作一个条形图比赛plottly来可视化从 1996 年到 2017 年在巴塞罗纳市最常见的婴儿名字。

你想知道这个动画条形剧情是怎么制作的吗?继续阅读🌈

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

数据集

该数据集可以在巴塞罗那公开数据中找到,包含了**巴塞罗那市最常见的 25 个婴儿名字,**按性别分类。

[## 巴塞罗那最常见的 25 个宝宝名字,按性别分类-25 _ noms _ padro _ any _ sexe _ 1996 _ 2018 . CSV…

这个数据集包含了出生到出院的 25 个最常见的孩子名字的频率数据

open data-a jument . Barcelona . cat](https://opendata-ajuntament.barcelona.cat/data/en/dataset/est-noms-nadons/resource/e1b5dd1f-a88e-43eb-86d1-d3880d9a6718)

探索性数据分析和数据清理

探索性数据分析包括分析数据集的主要特征,通常采用可视化方法汇总统计。目标是理解数据,发现模式和异常,并在我们执行进一步评估之前检查假设。

下载完 csv 文件后,我们可以使用Pandas . read _ CSV函数将其加载到 Pandas 数据框中,并使用 pandas 可视化前 5 行。data frame . head方法。

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

前五排

不合适的数据类型缺失值是数据集最常见的问题。我们可以使用 熊猫轻松分析这两者。DataFrame.info 方法。此方法提供了数据框的简明摘要,包括每列的数据类型、非空值的数量以及内存使用情况。

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

信息方法

数据集不包含空值数据类型是预期的。

如上所示,数据帧包含 5 列:(1) Ordre,(2) Nom,(3) Sexe,(4) Any,和(5) Nombre。巴塞罗那开放数据提供了大部分加泰罗尼亚语的数据集。因此,在开始可视化之前,我们必须将数据集翻译成英语。首先,我们用 熊猫翻译列名。DataFrame.rename 功能如下:

使用熊猫。DataFrame.columns 属性,我们可以检查翻译是否正确执行。接下来,我们用熊猫翻译列 Sex 的值。DataFrame.replace** 功能。**

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

翻译数据帧

当检查列名的唯一值时,我们可以观察到多个条目包含尾随空格。

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

多个条目包含尾随空格

我们删除了 **熊猫的尾随空格。**串联方法。该方法对 Series 对象的每个元素(列名)调用 Python 函数( lambda x: x.strip() )。

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

如上所示,尾部空格被成功删除。

数据清理完毕!!👏现在!我们准备好开始条形图竞赛了!

色彩设计

该数据集包含了 25 个最常见的男女婴儿名字。由于我们将制作两个交互式条形图**,一个用于女性姓名,另一个用于男性姓名,我们将数据分为两个数据集,如下所示:**

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

女性名字

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

男性名字

请注意,我们只选择了 10 个最常见的婴儿名字。

接下来,我们将为每个名称分配一种独特的颜色。为此,我们创建了一个函数,它接受系列RGB (红、绿、蓝)颜色格式(从 0 到 255 的整数值)的每个参数的最小和最大强度作为输入。该函数返回一个字典**,其中是系列的唯一名称,而是 RGB 颜色。这些颜色是使用函数 random.randint(a,b) 随机分配的,该函数返回一个介于 ab 之间的随机整数(两者都包括在内)。**

利用上面的函数,我们创建了两个字典,一个用于女性名字,另一个用于男性名字。字典的值是字符串( ‘rgb({},{},{})’ ),因为这是我们稍后将用来给条分配颜色的符号。

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

女性名字词典

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

男性名字词典

正如你所观察到的,对于女性名字来说,主要颜色是红色。相反,男性的名字主要是蓝色调。

现在,我们在两个数据框中创建一个名为 Color 的列,使用**熊猫为每个名字(根据字典)指定一种颜色。**方法如下:

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

df_man 数据帧前五行

现在,我们准备创建条形图!

条形图竞赛

要制作一个条形图竞赛**,首先我们必须创建一系列。每个包含一年的柱状图(从 1996 年到 2017 年)。**

如上图所示,我们使用 plotly.graph_objects 创建了一个条形图。 栏功能(在库中定义)Plotly** 。一个条形图显示了分类变量数值变量之间的关系。在这个可视化中,每个条代表一个名字( x 轴—分类变量),其高度与婴儿数量成比例( y 轴—数值变量)。条的颜色是我们之前分配给每个名称的颜色。此外,我们在横条上包含一个文本**,显示婴儿的名字(轴 x )和数量(轴 y )。由于我们不想在鼠标悬停在条上时显示任何信息,我们将参数 hoverinfo 设置为等于**‘无’。******

我们创建的第二个元素是使用 plotly.graph_objects 的布局。布局功能,这里我们定义了轴**、标题背景颜色等等。可以看出,在处理颜色时, Plotly 不仅支持 rgb 还支持十六进制符号。为了指定背景颜色,我们使用形式为 #RRGGBB 的字符串,其中 RR (红色)、 GG (绿色)和 BB (蓝色)是介于 00 和 FF 之间的十六进制数,代表颜色的强度。**

接下来,我们使用 plotly.graph_objects 创建框架对象。框架功能,输入条对象**(数据参数)和布局对象(布局参数)。最后,我们将框架对象添加到一个列表中。**

在创建了帧列表后,我们准备好使用 plotly.graph_objects 生成条形图比赛图。图功能,提供输入:

  • 初始年份的柱状图(数据自变量)
  • 初始地块的布局(布局自变量)
  • 帧列表(自变量)

现在,我们准备创建两个动画条形图!💪

对女孩来说👧

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

动画条形图-巴塞罗那最受欢迎的婴儿名字

对于男孩来说👦 😃

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

动画柱状图——巴塞罗那最受欢迎的婴儿名字

录像

一定不要忘了提一下启发我写这篇文章的视频!

阿曼达:)

Python 中的条形码和 QR 码解码器

原文:https://towardsdatascience.com/barcodes-and-qr-codes-decoder-in-python-59615c5f2b23?source=collection_archive---------5-----------------------

利用 pyzbar 解码一维条形码和 QR 码

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

procylink 访客管理系统Unsplash 上拍摄的照片

通过阅读本文,您将了解生成不同格式的一维条形码以及快速响应码(QR 码)生成的技巧和诀窍。此外,本教程将概述使用相同的 Python 库解码条形码和 QR 码的方法。之前,我已经介绍过一个关于如何用 Python 生成和解码二维码的教程,Python 使用 OpenCV 解码二维码。在本教程中,我将使用另一个名为pyzbar的模块进行解码。基于官方文件pyzbar

“…一个使用 zbar 库读取一维条形码和 QR 码的纯 Python 库,zbar 库是一个开源软件套件,用于从各种来源读取条形码,如视频流、图像文件和原始强度传感器。它支持许多流行的符号(条形码类型),包括 EAN-13/UPC-A、UPC-E、EAN-8、Code 128、Code 39、Interleaved 2 of 5 和 QR 码。”

根据我所做的实验,在解码二维码的准确性方面,pyzbarpython-opencv表现更好。最重要的是,pyzbar还能够解码条形码。

让我们继续下一部分,开始安装必要的模块。

1.设置

强烈建议您在继续安装之前设置一个虚拟环境。您可以通过pip install轻松安装所有模块。

python-条形码

我们的第一个模块是 python-barcode 包,它有助于根据我们指定的格式生成一维条形码。运行以下命令来安装它

pip install python-barcode

默认情况下,结果将被导出为 SVG。您需要安装额外的依赖项,如Pillow。您可以选择独立安装依赖项,或者与python-barcode一起安装,如下所示:

pip install python-barcode[images]

二维码

您可以通过以下命令单独安装qrcode

pip install qrcode

可选地,您也可以在标准安装中包含Pillow依赖项

pip install qrcode[pil]

皮兹巴尔

pyzbar的安装有点复杂,取决于您机器的操作系统。对于 Windows 用户,zbar DLL 与 Windows Python 轮子一起提供。

对于 Mac OS X,您可以通过以下命令安装zbar共享库

brew install zbar

如果您使用的是 Linux,应该使用下面的命令。

sudo apt-get install libzbar0

完成后,运行下面的命令来安装pyzbar Python 包。

pip install pyzbar

事实上,它还支持命令行功能,允许您直接在命令行中运行它。为此,您应该按如下方式安装它:

pip install pyzbar[scripts]

2.条形码生成

在本节中,我们将使用python-barcode包生成条形码。

支持的格式

在撰写本文时,这个包支持以下格式:

  • EAN-8
  • EAN-13
  • EAN-14
  • 刚果爱国者联盟
  • 一月
  • ISBN-10
  • ISBN-13
  • 国际标准系列出版物编号
  • 代码 39
  • 代码 128
  • PZN

我将使用 EAN13 格式生成一个新的条形码。结果将是 PNG 格式。

导入

让我们添加下面的导入语句。如果将结果保存为图像,则需要ImageWriter。否则,它将被默认为 SVG。

from barcode import EAN13
from barcode.writer import ImageWriter

创建条形码并保存为图像

继续在它下面追加下面的代码。因为我们正在编写一个图像,所以您需要将 filemode 指定为wb。供您参考,EAN13 接受包含 12 位而不是 13 位的字符串。最后一位是校验和,将自动生成。如果您输入的是一个 13 位的字符串,最后一位将被忽略。

with open('barcode.png', 'wb') as f:
    EAN13('123456789102', writer=ImageWriter()).write(f)

完整的代码片段如下:

当您运行 Python 文件时,它应该会生成以下图像。

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

作者图片

3.二维码生成

与条形码相比,QR 码的生成稍微复杂一些,因为 QR 码是二维的。

导入

添加以下导入语句

import qrcode
from PIL import Image

用以下参数创建一个QRCode对象的实例

qr = qrcode.QRCode(
    version=1,
    error_correction=qrcode.constants.ERROR_CORRECT_H,
    box_size=10,
    border=4,
)
  • version —控制二维码的大小。它接受 1 到 40 之间的整数。版本 1 由 21×21 矩阵组成。
  • error_correction —控制用于二维码的纠错。
  • box_size —控制二维码每个方框的像素数。
  • border —控制边框的框厚度。缺省值为 4,这也是规范中的最小值。

有 4 个常量可用于error_correction。可以纠正的错误越多越好。

  • ERROR_CORRECT_L —大约 7%或更少的错误可以被纠正。
  • ERROR_CORRECT_M —大约 15%或更少的错误可以被纠正。这是默认值。
  • ERROR_CORRECT_Q —大约 25%或更少的错误可以被纠正。
  • ERROR_CORRECT_H —大约 30%或更少的错误可以被纠正。

继续在它下面追加下面的代码片段。根据您自己的使用案例替换add_data的输入参数。

qr.add_data("https://medium.com/@ngwaifoong92")
qr.make(fit=True)img = qr.make_image(fill_color="black", back_color="white")
img.save("qrcode.png")

你可以在下面的要点中找到完整的代码。

你应该得到一个二维码一旦你运行代码。我的情况是这样的。

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

作者图片

一旦你完成了,继续下一部分,开始实现我们的解码器。

4.用 pyzbar 解码

pyzbar的一个主要特点是直接使用同一个函数进行解码。此外,它支持解码单个图像中的多个条形码或 QR 码。从模块导入decode()函数,如下所示:

from pyzbar.pyzbar import decode

你可以传递一个PIL.Image的实例或者一个numpy.ndarray的实例。您可以使用OpenCV轻松地将图像加载到numpy.ndarry中。用PIL加载时,使用以下代码

from PIL import Imageimg = Image.open('qrcode.png')

下面是一个如何使用OpenCV加载图像的例子。

import cv2img = cv2.imread('qrcode.png')

在它下面附加以下代码。它将以字符串形式打印出结果。

result = decode(img)

decode()函数返回一个名为Decodednamedtuple列表。其中每个都包含以下字段:

  • data —以字节为单位的解码后的字符串。你需要用 utf8 解码得到一个字符串。
  • type —仅对条形码有用,因为它概括了条形码格式。
  • rectRect对象,表示捕获的定位区域。
  • polygon —代表条形码或 QR 码的Point实例列表。

如果您要打印出整个返回结果,您应该得到以下输出

[Decoded(data=b'[https://medium.com/@ngwaifoong92'](https://medium.com/@ngwaifoong92'), type='QRCODE', rect=Rect(left=40, top=40, width=330, height=330), polygon=[Point(x=40, y=40), Point(x=40, y=369), Point(x=370, y=370), Point(x=369, y=40)])]

使用以下代码循环遍历每个元素,并打印出解码后的字符串

for i in result:
    print(i.data.decode("utf-8"))

完整的代码可以在下面的要点中找到。

5.结论

让我们回顾一下今天所学的内容。

我们从解释python-barcodeqrcodepyzbar背后的基本概念开始。

之后,我们继续安装必要的模块。使用pip install安装非常简单。

完成后,我们使用我们选择的配置参数实现了条形码和 QR 码的生成。

最后,我们利用pyzbar模块对之前生成的图像进行解码。

感谢你阅读这篇文章。希望在下一篇文章中再见到你!

参考

  1. python-barcode Github
  2. 二维码 Github
  3. pyzbar Github

Bardvja 推荐系统:同行评议文章的个人图书馆员

原文:https://towardsdatascience.com/bardvja-recommender-system-a-personal-librarian-for-peer-reviewed-articles-5cd590ef001a?source=collection_archive---------25-----------------------

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

Bardvja 将为你的下一次期刊俱乐部或小组会议提供合适的论文,以减轻拖延症!

推荐系统在我们的生活中变得无处不在——激发和引导我们的兴趣。这些系统主要利用协作基于内容的过滤来提出符合个人兴趣的建议。在这篇博客中,我们讨论了一个基于内容的推荐系统,推荐来自康奈尔大学 arXiv 的开源出版物。

arXiv 是一项免费分发服务,是一个开放的学术文章档案库,涵盖物理、数学、计算机科学、定量生物学、定量金融学、统计学、电气工程和系统科学以及经济学等领域。arXiv 由康奈尔大学维护和运营,是由 Paul Ginsparg 于 1991 年创建的一个合作资助、社区支持的资源。这是学术文章的极好来源,通常是提交给同行评审期刊的文章的预印本。

研究人员和研究生中用于类似任务的流行工具是 Mendeley ,这是一个具有多种服务的优秀工具。它的一个功能是根据用户的同行评审出版物库进行推荐。本项目的目标绝不是模仿或替代门德利的目的或用途。

创建 Bardvja 的动机源于我本地机器上以 PDF 文件形式存在的大量学术文章。这些不一定是期刊文章,它们可以是报告、提案、海报、论文、学位论文、小册子等。任何具有有用科学信息的文章都可能是有价值的,包含可能直接影响一个人的研究或为未来的提议提供新想法的信息。不管是有意还是无意,研究都是人类的努力和团队的努力。有时,一种方法或途径可能与相邻的研究领域、学科或过去十年大量研究的主题相关。如果能构想出一种工具,在过滤了数万篇论文之后,能够解释一个人的兴趣,并提出跨学科或跨领域的推荐,那将是极其方便的。

Bardvja 有望成为这个无所不知的工具,成为每个研究者的助手。Bardvja 这个名字的灵感来自于围绕着 Bharadwaja 的古印度神话,Bharadwaja 是一个决心获取宇宙中所有知识的圣人。剧透:他失败了,事实证明,他有幸在学习的道路上继续的几世证明是不够的和无关紧要的。虽然 Bharadwaja 的故事可能看起来令人沮丧,但不像他和神,我们有机器学习!

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

在机器学习出现之前,Bharadwaja 正在思考和摆弄他的头发。图片来自维基百科

Bardvja 的目标是将自然语言处理和 web 抓取结合起来,以提供来自康奈尔大学 arXiv 的推荐。arXiv 有一个优秀的 API,可以用来获取大量元数据。对于那些有兴趣了解 arXiv API 及其在这项工作中的应用的人,请考虑阅读 arXiv 手册,并在这里使用托管的 Jupyter 笔记本

接近

Bardvja 推荐系统有三个阶段:

  • 使用关键字作为 API 请求中的搜索查询来创建 arXiv 元数据的数据库。可以在 API 请求中调整不同的变量。
  • 使用 PyPDF2 解析位于本地目录中的 PDF 文件,以训练机器学习模型并提取主题词汇。
  • 开发一个推荐引擎来识别与当地报纸最匹配的 arXiv 文章。

这三个步骤的每一个都在下面描述。

a)使用 PyPDF2 进行解析

尽管 PDF 文件具有漂亮的渲染和可移植的特性,但从其中提取信息却是丑陋的二进制文件。 PyPDF2 是一款流行的工具,易于实施并提供最佳结果,但是存在以下挑战:

  • 并非所有的 PDF 文件都可以被解析,有些给出了错误,有些不包含可解析的信息。**
  • 解析的大多数文件包含不带空格的文本。thisprovedparticularlychalingtoextractanyusefulinformation from。学术文章中出现的大量数学符号和乳胶符号使这变得更加复杂。

虽然有些文件可能无法解析或读取(这些文件通常是扫描文件或旧的 PDF 文件),但是使用 PyPDF2 可以处理大量的文章。在本研究分析的 25 篇文章中,只有 2 篇是不可分析的。

第二个挑战更有趣也更令人沮丧。幸运的是, StackOverflow 讨论解决了这个问题,并导致了 Python 库的创建。 WordNinja 是一个 Python 库,它将不带空格的句子解析成单词列表!使用 WordNinja 和 RegularExpression,PDF 文件在输入到 CountVectorizer 之前被转换成句子。GitHub 资源库中提供了模型的细节和这些工具的使用顺序。

arXiv

在这一步中,创建了一个包含 arXiv 开源文章的摘要、标题、PDF 链接和其他元数据的库。例如,我使用的当地论文广泛来自粒子和流体动力学领域。因此,用于创建 arXiv 数据库的搜索查询是单词物理、流体、粒子。请注意,这些关键字是使用先前的主题专业知识选择的。然而,Bardvja 的未来版本可能会包含完整的 arXiv 元数据,在这种情况下,主题专业知识是不必要的。对于这项工作,在几分钟内总共获得了大约 72,000 篇论文。

一旦使用早期的机器学习模型刮出标题和摘要,每篇论文都被矢量化。使用在本地文件上训练的模型转换 arXiv 数据,确保 arXiv 矢量表示使用相似的词汇。

Bardvja 推荐系统

最后,推荐系统寻找 arXiv 向量与本地向量的相似性。在这项工作中,我们使用余弦相似度进行推荐。然后,arXiv 论文按相似性降序排列,并导出到包含所有 arXiv 论文的标题和链接的 csv 文件中。

如前所述,这项工作的灵感来自我自己在研究生院发现论文的经历,尤其是跨领域和学科的论文。在学术界任职期间,我研究了各种流动中流体与粒子相互作用的理论和计算。然而,作为一名工程师,我的研究领域主要涉及工业流、燃烧和环境现象。因此,令人惊喜的是,Bardvja 推荐的前 10 篇论文中有两篇来自天体物理学,题目如下:

粒子吸积到带有流体动力湍流的圆盘中的行星上

垂直剪切不稳定性产生湍流时圆盘中的粒子动力学

在我的 Macbook 上,整个系统的执行花费了不到半个小时的真实时间和大约 12 分钟的 CPU 时间。

结论

开发了一个推荐系统来利用本地 PDF 文件并推荐来自 arXiv 的开源论文。Bardvja 系统仅使用论文的标题和摘要,因此其识别大量细节的能力有限。目标是广泛搜索跨学科和跨领域的论文,并提出研究者可能感兴趣的建议。Bardvja 只是作为个人图书馆员或研究生院同事集思广益,它仍然希望专家阅读和推断论文。然而,这是一个从大量同行评议的论文中筛选并获得新灵感的宝贵工具。

最后,请考虑使用 Bardvja 并提供可能有助于推进该项目的反馈。GitHub 提供了使用它的代码和步骤,你可以在这里派生和克隆它。请随时联系我的 GithubLinkedIn 个人资料了解详情或提出问题。

医疗保健中自主人工智能的障碍

原文:https://towardsdatascience.com/barriers-to-ai-in-healthcare-41892611c84a?source=collection_archive---------38-----------------------

人工智能就在我们身边——它彻底改变了购物、电视和音乐——但它还没有到达医疗保健领域。是什么阻碍了它?

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

卡尔·比维克在 Unsplash 上的照片

简介

人工智能在当今社会无处不在——它通过我们的手机与我们交谈,推荐我们观看新的节目,并过滤掉与我们无关的内容。它无处不在,以至于我们大多数人在日常生活中没有理解它在我们生活中的作用。但它还没有像彻底改变我们的购物一样改变医疗保健行业的面貌。这是为什么呢?

答案不止一个。在我看来,至少有三个很好的理由让你看不到人工智能在医疗保健领域的广泛应用。不过,只要有足够的时间,我相信我们会克服所有这些障碍。

明确地说,我在这篇文章中讨论的人工智能是那种代替医疗专业人员的人工智能。被动人工智能只是帮助支持提供商的决策过程,已经得到了大量的研究,并改变了我们对待医疗保健的方式。

联邦法规

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

廷杰伤害律师事务所关于 Unsplash 的照片

人工智能要在医疗保健领域发挥作用,必须克服的最大障碍之一是旨在保护消费者的众多联邦法规。虽然不同国家有许多独特的管理机构,但我将把这个主题的范围缩小到美国 FDA。根据 FDA 的官方指南,医疗器械有几种不同的类别[1,2]。

I 级—这类设备被定义为最小风险,也就是说,产品的设计者可以很容易地向 FDA 证明,该设备对消费者没有伤害威胁,或者非常类似于已经获得 FDA 批准的设备。大约 47%的医疗设备属于这一类别。

第二类—该类装置定义为中度风险。大约 43%的医疗设备属于这一类别。你可以将这一类别视为医疗器械,它类似于已有的产品,但具有一些可能伤害消费者的独特功能。这方面的一个例子是电动轮椅,因为它非常类似于现有技术(即非电动轮椅),但具有电子元件,如果这些电子元件发生故障,可能会伤害用户。

III 类—这是为对消费者构成高风险的其余 10%医疗器械保留的。如果这些设备出现故障,可能会导致死亡(例如心脏起搏器)。

医疗保健中的自主人工智能应用大多属于第三类。一个护士可以用来识别黑色素瘤而不需要咨询专家的设备?自动检测乳腺癌的算法?一个为医生区分病人优先级的神经网络?都是三级。

虽然可以说这些例子中的每一个都可以用来帮助医务人员,而不是取代专家,但很难说这些设备是否会超越医疗保健专业人员的判断。当然,放射科医师可以像她应该做的那样手动检查病人的影像,但当工具似乎在大多数时候都是正确的时,她可能会在行使自己的判断时变得自满——这可能会付出生命的代价。

但这让我想到了下一个障碍:即使 FDA 批准了这些医疗设备,医疗服务提供者和他们的病人会信任它们吗?

患者和提供者信任度

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

国立癌症研究所Unsplash 上拍摄的照片

让我们从医疗保健中一个糟糕的人工智能实施的例子开始。想象你是一名医生。像你的其他同事一样,你花了十几年的时间参加富有挑战性的大学课程,努力完成住院医师培训,或者努力工作以在你的职业中取得成功。经过多年的努力,你终于成功了。你是一家知名医院受人尊敬的医疗保健专家,你经常阅读你所在领域的最新创新,你知道如何优先考虑病人的需求。

突然,你从阅读的许多学术期刊中熟悉的人工智能开始在你的医院中使用。在这种特殊情况下,也许它可以预测病人的住院时间,这样你就可以更好地计划临床试验。你会注意到,有时,它的预测是完全错误的。你甚至开始怀疑算法可能遇到了困扰人工智能的许多问题之一,例如模型漂移。你不信任它,并开始为了自己的利益而推翻它的判断——毕竟,你是医生,这是你学习的目的!你的工作是给你的病人提供极好的护理,但最终,你觉得算法不允许你这么做。

当人工智能试图为你做更多的工作时,会发生什么?你会相信吗?

上述场景中问题的核心是所描述的模型的不透明性。在那种情况下,算法背后的开发者没有考虑到医生和病人都想知道为什么以及什么。即使上述人工智能实现实际上对患者的住院时间进行了非常准确的评估,它也从未试图支持其预测背后的推理。

一个更理想的模型应该包含类似 SHAP 值的东西,你可以在 Dataman 博士的这篇优秀文章中读到更多。本质上,它们允许模型提供所谓的局部特征重要性,用简单的英语来说,这意味着对为什么这种特殊情况具有它所具有的预测结果的估计[3]。尽管它不会以任何方式改变算法本身,但它让提供者和患者都能洞察其判断,在医疗保健这样的循证行业中,这是非常宝贵的。

当人工智能解释其决策过程时,患者和提供者更容易信任它。

事实上,人工智能有巨大的能力来帮助临床决策。它能够发现复杂的模式,这些模式只有在综合查看患者数据时才会变得明显——我们不可能合理地期望人类医生检测到的事情。虽然他们不能取代个人医疗保健提供者的位置,但他们可以提供决策支持,并帮助医疗工作者看到他们否则不会注意到的趋势。但是这种决策支持只有在算法自我解释的时候才有可能。

人工智能驱动的医疗保健的伦理

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

阿诺·弗朗西斯卡在 Unsplash 上的照片

人工智能是一个复杂的话题,不仅在它的实现方面,而且在它给我们带来的伦理困境方面。2015 年,谷歌的机器学习驱动的照片标记器引发了争议,当时它错误地将一名黑人妇女标记为大猩猩[4]。社交媒体的反弹无可非议地巨大。一个简单的错误分类就足以将全世界的目光吸引到人工智能的状态上。发生这样的事情,谁来负责?我们应该如何回应?

不幸的是,这样的问题即使在 5 年后也并不少见。就在过去的一个月里,麻省理工学院不得不关闭广泛使用的微型图像数据集,因为在其中发现了种族主义和攻击性的内容[5]。现在使用的算法中有多少是从这些数据中学来的?

从表面上看,这些问题可能与医疗保健中的人工智能无关,但我提出它们有几个原因:

  1. 他们证明,即使我们有最好的意图,偏见也可能在我们的模型中表现出来
  2. 经常发生的情况是,只有当模型已经发布到世界上并且犯了错误时,这些偏见才变得明显

我们能自信地说这不会发生在医疗保健领域吗?我不相信我们可以。作为研究人员,还有更多的工作要做,以过滤掉我们的数据、我们的预处理技术、我们的模型和我们自己的固有偏见。人工智能在医疗保健领域的最大障碍是缺乏对任何给定模型在所有潜在用例中的公平性、安全性和有效性的保证。

已经在努力改善这种状况。像 Aequitas 这样的库使得开发者比以往任何时候都更容易测试他们的模型和数据的偏差。与此同时,研究人员和开发人员都越来越意识到模型偏差的影响,这将导致检测和处理模型偏差的工具、技术和最佳实践的进一步发展。人工智能可能还没有为今天医疗保健的黄金时间做好准备,但我和其他许多人将努力工作,让它成为现实。只要给予适当的照顾和关注,我相信人工智能有能力改变我们所知的医疗保健的面貌。

关于我

我叫 Josh Cardosi,是一名研究人工智能在医疗保健中的应用的硕士生。你可以在这篇文章中阅读更多关于我是如何来到这里的信息。虽然我上面谈到的问题非常真实,需要解决,但我坚信我们会克服它们,并通过这样做,改善医疗保健状况。我相信这将导致更好的卫生服务利用,降低患者死亡率,并提高患者和提供者对治疗计划的信心。

请随时在 LinkedIn 上与我联系。我喜欢阅读你的消息,并谈论医疗保健或机器学习方面的人工智能。

参考文献

[1] 对您的医疗器械进行分类 (2020),美国美国食品药品监督管理局

[2]FDA 医疗器械分类有什么区别? (2020),BMP 医疗

[3] Dataman,用 SHAP 价值观 (2019)向数据科学解释你的模型

[4] J. Snow,谷歌照片仍然对大猩猩有问题 (2018),《麻省理工科技评论》

[5] K. Johnson,由于种族主义和攻击性内容,麻省理工学院关闭了 8000 万个微型图像数据集 (2020),Venture Beat

[6] 机器学习的偏见和公平审计工具包 (2018),数据科学和公共政策中心

BART 用于解释简单的变压器

原文:https://towardsdatascience.com/bart-for-paraphrasing-with-simple-transformers-7c9ea3dfdd8c?source=collection_archive---------5-----------------------

释义是用不同的词表达某事,同时保留原来的意思的行为。让我们看看如何利用 BART(一种序列间变压器模型)实现这一点。

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

亚历山德拉Unsplash 上的照片

介绍

BART 是一个去噪自动编码器,用于预处理序列到序列模型。通过(1)用任意噪声函数破坏文本,以及(2)学习模型以重建原始文本来训练 BART。

如果这听起来有点复杂,不要担心;我们将对其进行分解,看看这一切意味着什么。在我们深入 BART 之前,添加一点背景知识,现在是时候用自我监督的模型来进行迁移学习了。在过去的几年里,人们已经说过很多次了,但是变形金刚确实在各种各样的自然语言处理(NLP)任务中取得了令人难以置信的成功。

BART 使用标准的转换器架构(编码器-解码器),就像最初用于神经机器翻译的转换器模型,但也结合了来自 BERT(仅使用编码器)和 GPT(仅使用解码器)的一些变化。更多细节可以参考 BART 论文2.1 架构部分。

培训前 BART

通过最小化解码器输出和原始序列之间的交叉熵损失来预训练 BART。

掩蔽语言建模(MLM)

诸如 BERT 之类的 MLM 模型被预先训练来预测屏蔽令牌。这个过程可以分解如下:

  1. 用一个掩码标记[MASK]替换输入的随机子集。(添加噪音/损坏)
  2. 该模型预测每个[掩码] 记号的原始记号。(去噪)

重要的是,当试图预测原始标记时,BERT 模型可以“看到”完整的输入序列(一些标记被替换为[MASK])。这使得 BERT 成为双向模型,即它可以“看到”屏蔽令牌之前和之后的令牌。

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

BART 论文中的图 1 ( a)

这适用于分类等任务,在这些任务中,您可以使用全序列中的信息来执行预测。但是,它不太适合于文本生成任务,在这种任务中,预测只依赖于前面的单词。

自回归模型

用于文本生成的模型(如 GPT2)被预先训练,以在给定前一个记号序列的情况下预测下一个记号。这种预先训练的目标导致模型非常适合文本生成,但不适合分类之类的任务。

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

来自 BART 论文的图 1 ( b)

BART 序列到序列

巴特既有编码器(像伯特)又有解码器(像 GPT),基本上是两全其美。

编码器使用类似于 BERT 的去噪目标,而解码器试图使用先前的(未损坏的)令牌和编码器的输出,逐个令牌地再现原始序列*(自动编码器)*。

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

BART 论文中的图 1 ( c)

这种设置的一个显著优点是选择讹误方案的无限灵活性;包括改变原始输入的长度。或者,用更花哨的术语来说,文本可能被任意噪声函数破坏。

本文中使用的腐败方案总结如下。

  1. 令牌屏蔽—输入的随机子集被替换为[屏蔽]令牌,就像在 BERT 中一样。
  2. 令牌删除-从输入中删除随机令牌。模型必须决定丢失了哪些位置(因为标记只是被删除了,而没有被其他任何东西替换)。
  3. 文本填充—许多文本跨度(长度可变)都被替换为单个[MASK]标记。
  4. 句子置换—输入基于句点(.),而且句子都是混排的。
  5. 文档旋转—随机选择一个令牌,并旋转序列,使其从所选令牌开始。

作者指出,用文本填充来训练 BART,可以在许多任务中产生最稳定的表现。

对于我们感兴趣的任务,即转述,预训练的 BART 模型可以直接使用输入序列(原始短语)和目标序列(转述句子)作为序列到序列模型进行微调。

这也适用于总结和抽象问题回答。

设置

我们将使用简单变形金刚库,基于抱脸变形金刚库来训练模型。

1.从这里安装 Anaconda 或者 Miniconda 包管理器。

2.创建新的虚拟环境并安装软件包。

conda create -n st python pandas tqdmconda activate st

3.如果使用 CUDA:

conda install pytorch>=1.6 cudatoolkit=10.2 -c pytorch

否则:

conda install pytorch cpuonly -c pytorch

4.安装简单变压器。

pip install simpletransformers

数据准备

我们将组合三个数据集,作为 BART 释义模型的训练数据。

  1. Google PAWS-Wiki 标注(最终版)
  2. Quora 问题对数据集
  3. 微软研究院释义语料库 (MSRP)

下面的 bash 脚本可以用来轻松下载和准备前两个数据集,但是 MSRP 数据集必须从链接中手动下载。(微软没有提供直接链接😞)

确保将文件放在同一个目录( *data* )中,以避免示例代码中文件路径的麻烦。

我们还有几个助手函数,一个用于加载数据,一个用于清理训练数据中不必要的空间。这两个功能都在utils.py中定义。

有些数据的标点符号前有空格,我们需要删除。 *clean_unnecessary_spaces()* 功能就是用于这个目的。

向 BART 解释

一旦准备好数据,训练模型就相当简单了。

注意,你可以在 这里 找到简单变形金刚例子中的所有代码。

首先,我们导入所有必要的东西并设置日志记录。

接下来,我们加载数据集。

然后,我们设置模型和超参数值。请注意,我们正在使用预训练的facebook/bart-large模型,并在我们自己的数据集上对其进行微调。

最后,我们将为测试数据中的每个句子生成释义。

这将把预测写到 *predictions* 目录中。

超参数

超参数值被设置为常规、合理的值,而不进行超参数优化。对于这个任务,基本事实并不代表唯一可能的正确答案(也不一定是最佳答案)。因此,调整超参数以使生成的文本尽可能接近基本事实没有多大意义。

我们的目标是生成好的释义序列,而不是从数据集中产生精确的释义序列。

如果你对简单变压器的超参数优化感兴趣(对分类等其他模型/任务特别有用),请点击这里查看我的指南。

[## 最佳变压器模型的超参数优化

如何使用简单的转换器调整超参数,以实现更好的自然语言处理。

towardsdatascience.com](/hyperparameter-optimization-for-optimum-transformer-models-b95a32b70949)

所使用的解码算法(和相关的超参数)对生成的文本的质量和性质有相当大的影响。我选择的值(如下所示)通常适合生成“自然”文本。

更多信息请参考优秀抱脸指南 这里

用你自己的句子试一下这个模式

你可以使用下面的脚本在任何句子上测试这个模型。

结果

让我们来看看模型为测试数据生成的一些转述序列。对于每个输入序列,该模型将生成三个(num_return_sequences)释义序列。

Orignal:A recording of folk songs done for the Columbia society in 1942 was largely arranged by Pjetër Dungu.Truth:A recording of folk songs made for the Columbia society in 1942 was largely arranged by Pjetër Dungu.Prediction:A recording of folk songs made in 1942 for the Columbia Society was largely arranged by Pjetr Dungu.A recording of folk songs for the Columbia society in 1942 was largely arranged by Pjetr Dungu.A recording of folk songs done for the Columbia Society in 1942 was largely arranged by Pjetr Dungu.
Original:In mathematical astronomy, his fame is due to the introduction of the astronomical globe, and his early contributions to understanding the movement of the planets.Truth:His fame is due in mathematical astronomy to the introduction of the astronomical globe and to his early contributions to the understanding of the movement of the planets.Prediction:His fame in mathematical astronomy is due to the introduction of the astronomical globe and his early contributions to understanding the movement of the planets.In mathematical astronomy, his fame is due to the introduction of the astronomical globe and his early contributions to understanding the motion of the planets.In mathematical astronomy his fame is due to the introduction of the astronomical globe and his early contributions to understanding the movement of the planets.
Original:Why are people obsessed with Cara Delevingne?Truth:Why are people so obsessed with Cara Delevingne?Prediction:Why do people fall in love with Cara Delevingne?Why is everyone obsessed with Cara Delevingne?Why do people like Cara Delevingne?
Original:Earl St Vincent was a British ship that was captured in 1803 and became a French trade man.Truth:Earl St Vincent was a British ship that was captured and became a French merchantman in 1803.Prediction:Earl St Vincent was a British ship captured in 1803 and became a French trader.Earl St Vincent was a British ship captured in 1803 and became a French trade man.Earl St Vincent was a British ship that was captured in 1803 and became a French trade man.
Original:Worcester is a town and county city of Worcestershire in England.Truth:Worcester is a city and county town of Worcestershire in England.Prediction:Worcester is a town and county of Worcestershire in England.Worcester is a town and county town in Worcestershire in England.Worcester is a town and county town of Worcestershire in England.

6.域外句子

Original:The goal of any Deep Learning model is to take in an input and generate the correct output.Predictions >>>
The goal of any deep learning model is to take an input and generate the correct output.The goal of a deep learning model is to take an input and generate the correct output.Any Deep Learning model the goal of which is to take in an input and generate the correct output.

从这些例子中可以看出,我们的 BART 模型已经很好地学会了生成释义!

讨论

潜在的问题

生成的释义有时会有一些小问题,下面列出了其中一些。

  1. 生成的序列几乎与原始序列完全相同,只有一两个词的细微差别。
  2. 不正确或笨拙的语法。
  3. 在域外(来自训练数据)输入上可能没有那么好。

令人鼓舞的是,这些问题似乎非常罕见,并且最有可能通过使用更好的训练数据来避免(同样的问题有时也可以在训练数据中看到)。

包裹

像 BART 这样的序列到序列模型是 NLP 实践者箭筒中的另一支箭。它们对于涉及文本生成的任务特别有用,例如释义、摘要和抽象问题回答。

解释可用于数据扩充,您可以通过解释可用数据来创建更大的数据集。

R 中的基本绘图

原文:https://towardsdatascience.com/base-plotting-in-r-eb365da06b22?source=collection_archive---------34-----------------------

在 R 中使用基本的绘图系统看起来让人不知所措,但事实并非如此。

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

R 中的基本 xy 散点图(左)与使用一些快速技巧的散点图(右)

R 中的基本绘图可能会令人生畏。它采用画布的方式来绘制,允许你在图形上绘制一层又一层的细节。因此,需要学习的函数和属性似乎是无穷无尽的,但是没有必要惊慌失措或者直接跳到 ggplot。本文强调了 base plot()函数的多功能性,同时为您提供了一些创建漂亮绘图的快速技巧。

在本文中,我使用了 Edgar Anderson 的 Iris 数据集,因此您可以复制代码并查看它的运行情况。我们将使用该数据集来创建和比较四个图表:

  1. 你可以在 R 中创建的最基本的图,一个 XY 散点图
  2. 使用颜色将 iris 数据集的散点图按物种分组的图
  3. 具有自定义字体、颜色和大小的绘图,以及
  4. 带有背景色和网格的绘图。

要加载数据集包并了解 Iris 数据集,请在 RStudio 控制台中输入以下代码:

**library**(datasets)
**help**(iris)

基本图与由数据子集着色的图

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

上面,我用基数 R 绘制了花瓣宽度和花瓣长度的关系图。左边的图是您可以在 R 中创建的最基本的图:一个带有 x 和 y 变量的散点图。

右边的图表传达了更多的信息,用颜色按物种对数据进行了细分。它看起来也更好,有轴标签、标题、颜色和图例。使用 ifelse()根据虹膜种类应用颜色。只需要多花几秒钟的时间来编写这种详细程度的代码,并增加信息和清晰度。

您可以使用以下代码在 R 中重新创建这两个图形:

##par lets us set global parameters for our graphs.
par(mfrow = c(1,2), mar = c(5,5,4,1))##Simple plot (left)
plot (iris$Petal.Length,iris$Petal.Width)##Plot showing species subsets (right)
plot(iris$Petal.Length, iris$Petal.Width, 
     xlab = "Petal Length",
     ylab = "Petal Width",
     main = "Petal Width vs Petal Length",
     pch = 20,
     col=ifelse(iris$Species == "setosa","coral1", 
                ifelse(iris$Species == "virginica","cyan4", 
                       ifelse(iris$Species ==  "versicolor",
                              "darkgoldenrod2", "grey"))))
##legend
legend("bottomright", c("setosa","virginica", "versicolor"),
       col = c("coral1","cyan4", "darkgoldenrod2"), pch=20)

物种子集的代码可分为三个部分:

  1. 因素
  2. 绘图属性
  3. 传奇

1.因素

参数部分固定所有图的设置。这里我们没有添加很多论点。我们有m flow,它指定我们有一行和两列图——也就是说,两个图并排。 mar 属性是我们的边距宽度的向量,第一个值表示绘图下方的边距(5),第二个值表示绘图左侧的边距(5),第三个值表示绘图顶部的边距(4),第四个值表示左侧的边距(1)。

par(mfrow = c(1,2), mar = c(5,5,4,1))

剧情

第二部分是情节的核心。您可以看到,通过向我们的 plot()函数添加五个参数,我们改进了图形的外观和有用性。这些论点是:

  • xlab:指定绘图的 x 轴标签
  • ylab:指定 y 轴标签
  • 主:标题您的图表
  • pch:指定图形的符号系统
  • col:指定图形的颜色。
##Plot with some customization
plot(iris$Petal.Length, iris$Petal.Width, 
     xlab = "Petal Length",
     ylab = "Petal Width",
     main = "Petal Width vs. Petal Length",
     pch = 20,
     col=ifelse(iris$Species == "setosa","coral1", 
                ifelse(iris$Species == "virginica","cyan4", 
                       ifelse(iris$Species ==  "versicolor",
                              "darkgoldenrod2", "grey"))))

对你的图表外观影响最大的参数是 col 。当你开始的时候,我建议你记住这篇文章末尾的备忘单上的三到四种颜色的名称。

传奇

legend("bottomright", c("setosa","virginica", "versicolor"),
       col = c("coral1","cyan4", "darkgoldenrod2"), pch= c(20))

图例功能允许用户定义其位置、显示为标签的字符串以及显示在每个标签旁边的符号。像这样创造传奇是一把双刃剑:事实上,它不是自动的,这让你对你的传奇看起来有很大的控制,但也很容易给你的符号贴错标签,所以 ojo

字体和颜色自定义

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

如果您要为一般流通或有严格品牌指导原则的组织创建图形,这种级别的自定义可能是必要的。代码看起来很长,因为我包含了第二个萼片长度图来显示全局参数的应用,但是代码本质上有相同的三个部分:参数、图和图例。您可以看到,我没有对这些图做任何重大的修改,我只是添加了一些属性来定制我的图形的颜色、字体和字体大小。

这些图与第一部分中的图之间的一个重要变化是在开始的 par()函数中。在这里添加属性来指定字体、字体大小和颜色,为您的绘图创建了“全局”设置,使您的所有后续图形摆脱了 1980 年代的粗糙外观。我添加的属性是:

  • 字体:par()表达式中的字体改变绘图函数外项目的字体。在这种情况下,它适用于图例,但也适用于您可能有的任何边距文本。
  • font.axis :轴数值标签的字体。
  • fg :前景颜色,表示文本和图形轮廓。
  • col.axis :坐标轴刻度和文字的颜色。
  • cex.axis :坐标轴刻度和文本的大小,相对于默认值 1。

我还在代码的 plot 部分添加了一些类似的属性:

  • font.lab :指定标签的字体
  • col.lab :指定标签的颜色
  • font.main :指定主标题的字体
  • 主栏:指定主标题的颜色

这些属性的指定方式与其父属性(col 和 font)的指定方式完全相同。很简单,对吧?

我没有对图例做任何修改;par()函数为我做到了这一点。

##global settings
par(mfrow = c(1,2), mar = c(5,5,4,1),font = 7,font.axis = 7, 
    fg = "azure4",  col.axis = "azure4", cex.axis = .75)## First plot
   plot(iris$Petal.Length, iris$Petal.Width, 
       xlab = "Petal Length", 
       ylab = "Petal Width", 
       font.lab = 7,
       col.lab = "azure4",
       main = "Petal Width vs Petal Length",
       font.main = 7,
       col.main = "black",
       pch = 20,
       col=ifelse(iris$Species == "setosa","coral1", 
                ifelse(iris$Species == "virginica","cyan4", 
                       ifelse(iris$Species ==  "versicolor",
                              "darkgoldenrod2", "grey"))))
  ##legend
  legend("bottomright", c("setosa","virginica", "versicolor"),
       col = c("coral1","cyan4", "darkgoldenrod2"), pch=20)##Second plot
   plot(iris$Sepal.Length, iris$Sepal.Width, 
     xlab = "Sepal Length",
     ylab = "Sepal Width",
     font.lab = 7,
     col.lab = "azure4",
     main = "Sepal Width vs Sepal Length",
     font.main=7,
     col.main = "black",
     pch = 17,
     col=ifelse(iris$Species == "setosa","coral1", 
                ifelse(iris$Species == "virginica","cyan4", 
                       ifelse(iris$Species ==  "versicolor",
                              "darkgoldenrod2", "grey"))))
  ##legend
  legend("bottomright", c("setosa","virginica", "versicolor"),
       col = c("coral1","cyan4", "darkgoldenrod2"), pch=17)

背景

使用 r 中的基本绘图时,图表的背景很复杂。par()函数有一个背景属性, bg ,但是它将图表的整个区域都着色为背景色。例如:

par(mfrow = c(1,1), mar = c(5,5,4,1),bg = "grey") 
plot(iris$Petal.Length, iris$Petal.Width)

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

不是我们想要的。

在 base R 中,没有简单的方法在你的绘图背景上着色。您可以使用 rect 功能绘制一个与您的轴对齐的矩形,或者您可以使用 ablineabline 函数非常通用,用它来为我们的图形创建背景迫使我们以稍微不同的方式创建我们的情节。

我们将在前几节工作的基础上,给花瓣宽度和花瓣长度的关系图添加一个带有网格线的彩色背景。

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

花瓣宽度与花瓣长度的图表,带有使用 abline 创建的背景

##global parameters
par(mfrow = c(1,1), mar = c(5,5,4,1),font = 7,font.axis = 7,
    fg = "azure4",  col.axis = "azure4", cex.axis = .75) ##Create the empty plot
plot(NULL, ylim=c(0,2.5),xlim=c(0,7), 
     xlab = "Petal Length", 
     ylab = "Petal Width", 
     font.lab = 7,
     main = "Petal Width vs. Petal Length",
     font.main = 7,
     col.main = "black",)##Add the background color
abline(v = 0:7, col = "aliceblue", lwd = 200)
abline(v = 0:7, col = "white")
abline(h=0:2.5, col = "white")##Add the data points
points(iris$Petal.Length, iris$Petal.Width, 
       pch = 20,
       cex = 1.5,
       col=ifelse(iris$Species == "setosa","coral1", 
                  ifelse(iris$Species == "virginica","cyan4", 
                         ifelse(iris$Species ==  "versicolor",
                                "darkgoldenrod2", "grey"))))
##legend
legend("bottomright", c("setosa","virginica", "versicolor"),
       col = c("coral1","cyan4", "darkgoldenrod2"), pch=20)

如果您查看此图的代码,您会发现它创建情节的方式略有不同。首先,它建立了一个空白图,然后绘制信息层,从背景色开始,然后是数据点,然后是图例。背景颜色是使用粗 ab 线创建的纯色,使用细白线创建的网格:

##Add the background color
abline(v = 0:7, col = "aliceblue", lwd = 200)
abline(v = 0:7, col = "white")
abline(h=0:2.5, col = "white")

您可以看到,我们已经将我们的点属性(数据集、pch 和 col)移动到了 points() 函数中,但是我们没有更改它们。我添加了属性 cex 来增加点的大小。

备忘单

图表是向任何受众传达分析结果的最有效方式之一。像适当的标签、按颜色或符号设置数据子集以及字体调整这样简单的添加既增加了信息又提高了清晰度,然而我们始终看到 R 中的图形看起来就像是 30 年前创建的。在花时间清理、总结和分析你的数据之后,花一分钟在你的图上是有意义的。

下面是一些不错的备忘单,可以帮助你进行定制。

绘图的属性()

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

绘图函数的一些属性及其相关值(源代码)。对于 col,您可以看到只有 7 种不同的颜色值有一个数字名称,然后它们开始重复。

颜色;色彩;色调

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

42 个 R 颜色名称的备忘单(源代码

字体

在 R 中有许多处理字体的方法,但是这里有一个基本的备忘单,它使用 font = x 处理与不同字体相关的数值。

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

本文使用的所有代码都可以在这里找到。

根据你的活跃程度,你应该喜欢这个:Instagram vs 抖音!

原文:https://towardsdatascience.com/based-on-your-activity-you-should-like-this-instagram-vs-tiktok-5fcfa1c07e46?source=collection_archive---------29-----------------------

通过比较 Instagram 和抖音来评估推荐系统如何了解用户

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

图片作者:特里斯特·约瑟夫

“根据您的活动,我们认为您可能会喜欢这个。”这句话是几乎每个社交媒体平台上最常见的短语之一,而且有一个很好的理由。这些平台上的转化率是推动业务的因素。这个转换率本质上是看到帖子的总人数中对帖子采取了一些行动的人数。从帖子中采取的行动可以是简单地参与一条内容,访问与帖子链接的网站,甚至购买帖子中提到的商品。

在任何一种情况下,都可以看出为什么转换率越高越好。人们更有可能对他们感兴趣的事情或激发反应需求的事情采取行动。此外,在用户已经与他们感兴趣的东西交互之后,平台的目标是显示更多相似的内容,因为参与度将是相似的。这是推荐系统的本质;它确定一个用户可能感兴趣的列表,评估列表中哪些项目表现最好,然后向用户重复显示那些表现最好的项目。

如果你是一个有兴趣成为数据科学家的人,但你对动漫也不感兴趣,你更有可能点击一个写着“数据科学 5 大算法”的帖子,而不是一个写着“2020 年 5 大动漫”的帖子。在那之后,继续看到关于数据科学的帖子将是理想的。因此,平台用户可以看到的每一条内容都需要优化,以实现其最大潜力。最大化这种潜力的最好方法是只向用户展示他们感兴趣的内容。但是现在大问题来了,平台如何知道用户会对什么感兴趣?

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

图片作者:特里斯特·约瑟夫

平台可以通过两种主要的、通用的方式来确定用户的兴趣。这就是内容过滤协同过滤,两种方式各有千秋。内容过滤使用关于用户和帖子的已知信息将事情联系起来。它包括从一组预定义的类别中给每个用户和帖子贴上标签,然后对这些联系进行评分。一旦分数被确定,就假设用户将偏好具有较高分数的内容。

让我们通过一个例子来更好地理解这个过程。为了简单起见,假设 Instagram 上的内容只有两类:爱情和喜剧。Julia 是一名 Instagram 用户,她喜欢喜剧,但不喜欢浪漫,所以她会被赋予喜剧 4 分,浪漫 0 分。现在有两个不同的职位可以推荐给朱莉娅。《邮报》A 只讲述浪漫,而《邮报》B 则兼具浪漫和喜剧。根据总分,茱莉亚应该对岗位 B 更感兴趣,这就是将向她推荐的岗位。

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

图片作者:特里斯特·约瑟夫

现在有更多的东西可以用来确定用户是否对一个帖子感兴趣,这些可以包括年龄、位置,甚至种族或民族;但概念保持相对一致。为了收集这些信息,平台通常要求用户创建某种偏好列表。这实际上可以通过填写一张表格来完成,“你喜欢喜剧还是爱情片?”,或者通过开发一个社交图

社交图是将用户映射到他们表示感兴趣的所有内容的记录。在 Instagram 上,这将是关注另一个 Instagram 用户、喜欢其他用户的帖子以及在平台上分享帖子的行为。通过这样做,用户开发了一个他们认为最感兴趣的网络。这给用户一种感觉,他们可以控制自己在提要中看到的内容。这种方法面临的挑战是,对用户来说,填写他们喜欢的内容或与一组用户实际联系似乎是一项工作,人们并不像他们想象的那样擅长列出他们的偏好。

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

图片作者:特里斯特·约瑟夫

这让我们想到了平台可以用来确定用户兴趣的第二种方法;协同过滤。它的工作原理是,一个用户可能会对具有相似观看习惯的其他用户感兴趣的内容感兴趣。这在某种程度上可以被认为是颠倒了内容过滤方法。协作过滤方法不是有预定义的类别、映射和分数,而是调查用户在参与什么,然后从那里“向后”工作。使用一组参与度数据,目标是确定哪些特征将相似的帖子相互链接。这些特点是未知的,通常不会有一个标签,如喜剧,附在它身上。相反,它们被称为潜在特征,因为它们产生于数据中的潜在模式。

抖音是一个使用协同过滤的平台,所以让我们通过抖音算法来更好地理解这种方法是如何工作的。当一个新用户开始使用抖音时,他们不必提供偏好列表,也不必明确地追随任何人。相反,他们被带到一个欢迎页面,视频开始播放,最重要的指标是他们看了一个视频多长时间。该算法然后分析这些观看时间数据,以及有多少视频被重新观看或退出,以了解用户对什么感兴趣。假设如果用户观看视频的时间较长,如果他们多次重新观看视频,并且如果他们退出视频的频率较低,那么他们对该段内容感兴趣。

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

图片作者:特里斯特·约瑟夫

当用户再次访问时,他们会收到基于之前视频观看时间分析的个性化内容。这个方法绕过了社交图,而是创建了一个兴趣图。顾名思义,它是基于各种性能指标的用户到他们可能感兴趣的内容的映射。现在,抖音不是第一个使用这种方法的平台。YouTube 算法以类似的方式工作。然而,抖音视频通常比 YouTube 视频短得多,用户可以轻松发布更多内容。因此,抖音有很多数据可以借鉴。

这就是协同过滤方法的力量。有大量的数据可以学习和提取潜在的特征,然后可以用来更好地了解消费者,然后开发出惊人准确的推荐。这种方法的另一个优点是,用户不必通过建立联系或填写表格来表明他们感兴趣的内容。然而,这也可能导致用户陷入一个“相似内容”的兔子洞,他们不会明确搜索。

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

图片作者:特里斯特·约瑟夫

人们有时会说,任何足够先进的技术都和魔法没什么区别。通常,用户认为当一个平台向他们推荐他们真正感兴趣的东西时,那一定是奇迹。这不是魔法。相反,它是足够先进的技术。内容过滤和协同过滤都利用用户过去行为的一些数据来预测他们的一些情况。内容过滤要求用户建立一个社交图,并根据偏好将用户划分到自定义的类别中。另一方面,协同过滤让用户创建兴趣图,并根据从用户活动中学到的东西将内容特征聚集在一起。

那么平台如何知道用户会对什么感兴趣呢?用户会通过这些方法之一告诉他们。

参考文献:

pitt.edu/~peterb/2480-012/ContentBasedFiltering.pdf

live book . manning . com/book/practical-recommender-systems/chapter-10/

developers . Google . com/机器学习/推荐/基于内容/基础知识

developers . Google . com/machine-learning/推荐/协作/基础知识

link.springer.com/chapter/10.1007/978-3-540-72079-9_9

ieeexplore.ieee.org/document/5197422

其他有用的材料:

or eilly . com/library/view/intelligent-projects-using/9781788996921/

arxiv.org/ftp/arxiv/papers/1503/1503.07475.pdf

towards data science . com/introduction-to-recommender-systems-6 c 66 cf 15 ada

Bash 命令在你的袖子里

原文:https://towardsdatascience.com/bash-commands-up-your-sleeve-fc77b10fb09c?source=collection_archive---------38-----------------------

我最近遇到的 5 个 Bash 工具非常棒

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

Kelly SikkemaUnsplash 上拍摄的照片

Shell 脚本非常有趣!一旦你对这些工具和它们的作用有所了解,情况会变得更好。

我将使用终端展示这些工具。任何时候你想在 Windows 上运行 Linux 命令行,打开 PowerShell 或命令提示符并输入 bash 。您也可以在搜索栏中搜索 bash 并选择在命令窗口中打开 bash

其中一些工具没有预装,因此需要brew安装。Homebrew 是一个 MacOS 的软件包管理器。

家酿网站的一个片段:

家酿安装你需要的苹果(或你的 Linux 系统)没有的东西。

Homebrew 将软件包安装到它们自己的目录中,然后将它们的文件符号链接到/usr/local中。

事情是这样的:

$ brew install <name-of-package>

tldr

  • $ brew install tldr : tldr是一个给你如何使用特定 bash 命令的例子的工具。例如
    $ tldr grep

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

tldr grep

$ tldr find

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

tldr find

您能想到的任何可能的 bash 命令,使用tldr并查看您可以使用它的许多方式。

TL;博士代表“太久;没读过”是man的一种备忘单。

外壳检查

  • $ brew install shellcheck : shellcheck用于对您的脚本进行检查。注意 ShellCheck 只支持sh/bash/
    $ shellcheck <name-of-bash-file>

ShellCheck 的目标是:

指出并澄清典型的初学者语法问题,这些问题会导致 shell 给出模糊的错误消息。

指出并澄清典型的中级语义问题,这些问题会导致 shell 行为怪异且违反直觉。

指出可能导致高级用户的工作脚本在未来环境中失败的微妙警告、死角和陷阱。

来源: github

为了演示,我使用了我在这里找到的 bash 脚本。在 Vim 中打开的脚本如下:

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

example.sh

当我运行 shellcheck 命令时,结果如下:

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

shellcheck example.sh

这个工具我印象超级深刻!

历史

  • $ history:该命令输出 bash 终端上最近使用的命令列表。比起使用向上箭头键来浏览最近使用的命令(总是迷路,从来没有真正找到你要找的命令),这是一种更好的方式来筛选你过去运行过的命令。

fzf

  • $ brew install fzf : fzf是一个让你交互使用grep的工具(grep是一个模式匹配工具)。
    给定一个脚本example2.sh,我们可以通过将文件的内容输入fzf :
    cat example2.sh | fzf来交互式地搜索文件中的任何内容

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

cat example2.sh | fzf

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

要退出搜索模式,请按ESC + q + ENTER

显然,使用的示例文件不足以展示强大的工具fzf

布鲁特

  • $ brew install broot : ls不总是容易看的。仅将所有文件和目录输出到您的终端屏幕上,在导航和定位某些文件/文件夹时效率低下。所以,我们用broot。这是一个工具,列出您的目录和文件,在一个简单的方式,让你看看。在所需的目录中,键入broot并输入。一个目录和文件列表显示出来(颜色与类型相匹配)。你可以在一个目录上ENTER进一步查看它的内容。broot还可以让你直接从终端的默认应用程序中打开文件。

如果你想找出使用上述命令的更高级的方法,tldr它!注意,对于某些工具,GitHub 页面可能不存在。

这些不是很光滑吗?亲自尝试一下吧!

基本人工智能算法

原文:https://towardsdatascience.com/basic-ai-algorithms-a7607b9ecdce?source=collection_archive---------4-----------------------

旅行商问题的搜索算法

为了用计算机解决问题,有必要用数字或符号的形式来表示问题,并用编程语言提供一个特定的过程。然而,在人工智能(AI)领域解决问题时,很难从一开始就指定一个问题的公式。因此,在观察状态变化的过程中,选择求解过程的灵活性是非常需要的。有些问题可以用图形或树形结构来表示,其中每个节点代表问题的一个状态。这种问题表述方法称为状态空间表示法。

状态空间表示

在状态空间表示方法中,问题的每个状态由图或树结构的节点表示。在这种情况下,该问题被转化为在特定的算子和约束下确定目标的搜索问题。在这篇文章中,我将以旅行商问题(TSP)为例进行介绍。

表示状态空间表示需要的一个问题:
(1)。问题的一组状态
(2)。一组操作符在问题的状态之间进行操作
(3)。初始状态和最终状态(目标)

旅行推销员问题

考虑以下情况。给你一个 n 个城市的列表,其中有任意两个城市之间的距离。现在,你必须从你的办公室开始,每个城市只去一次,然后回到你的办公室。你能走的最短路径是什么?这个问题被称为旅行推销员问题(TSP)。

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

TSP 问题的公式化

为了使问题简单,我们考虑 3 个城市的问题。
让我们分别给办公室(A)和 3 个城市(B ) ( C ) ( D)打电话。我们通过{A}表示销售员离开了他的办公室来初始化问题状态。作为一个操作员,当他访问 city-B 时,问题状态更新为{A,B},其中考虑了{ 0 }中元素的顺序。当销售人员访问了所有城市时,在这种情况下为{A,B,C,D},离开的点 A 被自动添加到状态中,这意味着{A,B,C,D,A}。因此,这个 TSP 的初始状态是{A},最终状态(目标)是{A,X1,X2,X3,A},在这里旅行距离最小化。

把每个状态作为一个树结构的节点,我们可以把这个 TSP 表示为下面的树搜索问题。

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

强力搜索

深度优先搜索

深度优先搜索算法从根节点开始,在进行回溯之前沿着每个分支尽可能深地探索。在我们的 TSP 中,当一个带有所有城市标签的状态节点被访问时,它的总距离被存储。该信息稍后将用于定义最短路径。

设访问是一个 来保存访问过的节点,路径是一个集合来保存从根节点到目标的距离。深度优先算法可以写成

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

广度优先搜索

深度优先搜索算法从根节点开始,在移动到下一个深度级别的节点之前,探索当前深度级别的所有节点。在我们的 TSP 中,当一个带有所有城市标签的状态节点被访问时,它的总距离被存储。该信息稍后将用于定义最短路径。

设访问是一个 队列 来保存访问过的节点,路径是保存从根节点到目标的距离的集合。广度优先算法可以写成

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

启发式搜索

在强力搜索中,访问所有节点,并且不考虑来自每个节点的信息(从节点到节点的距离)。这导致了大量的时间和内存消耗。为了解决这个问题,启发式搜索是一种解决方案。每个状态节点的信息用于考虑是否访问一个节点。该信息由通常由用户经验建立的启发式函数来表示。例如,我们可以通过从根节点到当前访问节点的距离,或者从当前访问节点到目标节点的距离来定义启发式函数。

最佳优先搜索

在最佳优先搜索中,我们使用到根节点的距离信息来决定首先访问哪个节点。设 g(X)为根节点到 node-X 的距离,因此,根节点访问 node-X 到 node-Y 的距离为 g(Y)=g(X)+d(X,Y),其中 d(X,Y)为 X 和 Y 之间的距离。

让 VISIT 成为一个 列表 来保存访问过的节点。最佳优先算法可以写成

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

A 算法(a*-算法)

在 A 算法搜索中,我们使用从当前访问节点到目标的距离信息作为启发式函数 h(X)。设 g(X)是根节点到 node-X 的距离,在这种情况下,我们按 f(X)=g(X)+h(X)考虑节点访问顺序的优先级。

在现实问题中,不可能获得 h(X)的精确值。在这种情况下,使用 h(X)的估计值 h’(X)。然而,设置 h’(X)有陷入局部最优解的风险。为了防止这个问题,建议选择 h’(X)其中 h’(X)≤h(X)用于所有 X。在这种情况下,它被称为 a*-算法,并且可以表明所获得的答案是全局最优答案。

在下面描述的实验中,我们将 h’(X)设置为从当前访问节点标签中未出现的每个城市到当前城市的所有可能路线的最小距离之和。例如,如果当前节点是{A,D},则城市 B 和 C 不会出现在标签中。因此,h’(D)=min(从 C 开始的所有可能的路线距离)+min(从 B 开始的所有可能的路线距离)+min(从 D 开始的所有可能的路线距离)。

让 VISIT 成为一个 列表 来保存访问过的节点。A 算法可以写成

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

搜索算法之间的比较

我们用每一个引入的算法模拟 TSP,并把重点放在搜索问题的有效性上。在这里,搜索问题的有效性通过到达答案所访问的节点数和与树的深度级别相比的
有效分支数来评估。一个问题的有效分支数 b是通过
N+1 = 1 + b
+ (b*) +(b*) +…+(b*)^d 来计算的,b越小的算法越有效。在这个实验中,我们用牛顿法求解这个方程,得到 b的近似值。

关于访问节点数的讨论

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

关于有效分枝数的讨论

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

用 Python 实现

**# Randomly generate problem**import randommax_city_number = 8Gs = []for NN in range(2,max_city_number):Gs.append([[random.randint(1,10) for e in range(NN+1)] for e in range(NN+1)])**# Problem state representation: Tree structure**class node(object):def __init__(self,number=None):self.pre = Noneself.no = numberself.label = []self.child = []self.cost = None def add_child(self,number):tmp_node = node(number=number)tmp_node.pre = selftmp_node.label=[i for i in self.label]tmp_node.label.append(number)tmp_node.cost= get_bound(tmp_node.label)self.child.append(tmp_node)**# Evaluate Function for A Algorithm**def get_bound(label):f = 0for i in range(0,len(label)-1):f = f+graph[label[i]-1][label[i+1]-1]remain = city.difference(set(label))remain = list(remain)remain.append(label[-1])for i in remain:f = f+min_bound[i-1]if len(remain)==2:f=0label.append(remain[0])label.append(1)for i in range(0,len(label)-1):f = f+graph[label[i]-1][label[i+1]-1]return f**# Evaluate Function for Best-first Algorithm**def get_bound(label):f = 0remain = city.difference(set(label))remain = list(remain)remain.append(label[-1])for i in remain:f = f+min_bound[i-1]if len(remain)==2:f=0label.append(remain[0])label.append(1)for i in range(0,len(label)-1):f = f+graph[label[i]-1][label[i+1]-1]return f**# Evaluate Function for Depth-first/Breadth-first Algorithm**def get_bound(label,n_city):f = 0for i in range(0,len(label)-1):f = f+graph[label[i]-1][label[i+1]-1]if len(label)==len(graph):f = f+graph[label[-1]-1][0]return f**# Effective Branch Number calculation (Newton's Method)**def f(N,d,x):return (x**(d+1) - (N+1)*x + N)**2def df(N,d,x):return 2*f(N,d,x)*((d+1)*x**d-(N+1))def ddf(N,d,x):return 2*df(N,d,x)*((d+1)*x**d-(N+1))+2*f(N,d,x)*((d+1)*d*x**(d-1))def solve(N,d):x = 1.9delta = 1.0count = 0while abs(delta)>0.000001 and count<10000:delta = df(N,d,x)/(ddf(N,d,x)+0.00001)x = x - deltacount = count + 1return x**# EXPERIMENT1/2: 
# Search for GOAL (for A algorithm/Best-first Algorithm)**tree = node(number=1)tree.label.append(1)tree.cost=0 for i in range(len(Gs)):print("----------i=%d------------"%i)graph = Gs[i]NN = len(graph)for idx in range(NN):graph[idx][idx] = float('inf')city = range(1,len(graph)+1)city = set(city)min_bound = [min(graph[i]) for i in range(len(graph))] tree = node(number=1)tree.label.append(1)tree.cost=0 visit=[]visit.append(tree)count = 0fcnt = 0ans = 0while len(visit)>0:N = visit[0]if len(N.label)==(len(city)-2):fcnt = fcnt+1del(visit[0])count = count+1child_list = set(city).difference(set(N.label))if len(child_list)==0:ans = 1breakfor c in child_list:N.add_child(number=c)tmp = N.childfor i in tmp:visit.append(i)visit = sorted(visit,key= lambda x:x.cost) if ans==1:print("RESULT:",N.label,N.cost)b = solve(count,NN-2)print("d=%d ,N= %d ,  b*=%f"%(NN-2,count,b))print("ROUTEs: %d"%(fcnt))resultsA.append((NN-2,count,b))else:print("FAILED")**# EXPERIMENT3: 
# Search for GOAL (for Depth-first algorithm)**tree = node(number=1)tree.label.append(1)tree.cost=0for i in range(len(Gs)):print("----------i=%d------------"%i)graph = Gs[i]NN = len(graph)for idx in range(NN):graph[idx][idx] = float('inf')city = range(1,len(graph)+1)city = set(city)tree = node(number=1,n_city=len(city))tree.label.append(1)tree.cost=0visit=[]paths = []count = 0fcnt = 0visit.append(tree)while len(visit)>0:if len(visit)==0:breakN = visit.pop()if len(N.label)==(len(graph)+1):paths.append(N)fcnt = fcnt+1paths=sorted(paths,key= lambda x:x.cost)count = count+1child_list = set(city).difference(set(N.label))if len(child_list)==0:continuefor c in child_list:N.add_child(number=c)tmp = N.childfor i in tmp:visit.append(i)print("RESULT:",paths[0].label,paths[0].cost)print("d=%d ,N= %d ,  b*=%f"%(NN-2,count,solve(count,NN-2)))print("ROUTEs:%d"%(fcnt))**# EXPERIMENT4: 
# Search for GOAL (for Breadth-first algorithm)**tree = node(number=1)tree.label.append(1)tree.cost=0for i in range(len(Gs)):print("----------i=%d------------"%i)graph = Gs[i]NN = len(graph)for idx in range(NN):graph[idx][idx] = float('inf')city = range(1,len(graph)+1)city = set(city)tree = node(number=1,n_city=len(city))tree.label.append(1)tree.cost=0visit=[]paths = []count = 0fcnt = 0visit.append(tree)while len(visit)>0:if len(visit)==0:breakN = visit[0]
del(visit[0])if len(N.label)==(len(graph)+1):paths.append(N)fcnt = fcnt+1paths=sorted(paths,key= lambda x:x.cost)count = count+1child_list = set(city).difference(set(N.label))if len(child_list)==0:continuefor c in child_list:N.add_child(number=c)tmp = N.childfor i in tmp:visit.append(i)print("RESULT:",paths[0].label,paths[0].cost)print("d=%d ,N= %d ,  b*=%f"%(NN-2,count,solve(count,NN-2)))print("ROUTEs:%d"%(fcnt))

基本算法—计数求逆

原文:https://towardsdatascience.com/basic-algorithms-counting-inversions-71aaa579a2c0?source=collection_archive---------18-----------------------

分裂-征服方法在随机数组中找到反转对的效率比暴力方法高多少

尽管近年来计算能力有了显著的提高,但是在大型数据集上操作仍然是昂贵的。因此,编写经济高效的代码是数据科学家的关键技能之一。虽然成本与输入数据大小成线性关系的算法可能与成本为平方的算法差别不大,但当数据集增加到数百万时,前者具有巨大的优势。

编写更有效算法的一个基本方法是分治法,在这种方法中,我们编写一个嵌套函数,递归地将相同的函数应用于输入子集。在这篇文章中,我们将比较分裂征服法和蛮力法在计算随机数组中的反转对。

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

亨利&公司在 Unsplash 上拍摄的照片

我们得到一组没有任何重复的数字,并被要求计算反转数。求逆是两个整数的数组中第Ij、I 个元素大于第 j 个元素的情况。

如果数组由(2,3,8,6,1)组成,我们可以找到(2,1),(3,1),(8,6),(8,1),(6,1)的五个逆。

最简单和最容易的方法是比较数组中的所有对。用数组长度 n 我们正好可以比较 n(n-1)/2 对,代价是*θ(n)。*下面是一个不到十行的简单代码示例:

def bf_inversion_count(array):
    count = 0
    for i in range(len(array)):
        j = i + 1
        while j < len(array):
            if array[i] > array[j]:
                count +=1
            j += 1
    return count

让我们想一个更好更有效的方法。我们可以修改合并排序算法。分治算法的成本是:

T(n) = 2T(n/2) + f(n)

其中,总成本 T(n) 是两个半大小数组的成本 T(n/2) 和对两个数组之间的反转进行计数的成本 f(n) 之和。我们应该可以使f(n)=θ(n)使得T(n)=θ(nlgn)。

这是我的示例代码,主要是添加了计数行的合并排序代码。

def sc_inversion_count(array):

    length = len(array) if length == 1: 
        return array, 0 if length == 2:
        if array[0] > array[1]:
            return np.array([array[1], array[0]]), 1
        else:
            return array, 0

    elif length > 2:
        array_l = array[:length//2]
        array_r = array[length//2:]
        array_l_df = sc_inversion_count(array_l)
        array_r_df = sc_inversion_count(array_r)
        array_l_sorted = array_l_df[0]
        array_r_sorted = array_r_df[0] length_l = len(array_l)
        length_r = len(array_r) count = array_l_df[1] + array_r_df[1] l = 0
        r = 0

        sorted_list = []

        for i in range(length):
            if r == length_r:
                sorted_list.append(array_l_sorted[l])
                l += 1 elif l == length_l:
                sorted_list.append(array_r_sorted[r])
                r += 1             

            elif array_l_sorted[l] > array_r_sorted[r]:
                sorted_list.append(array_r_sorted[r])
                r += 1
                count += len(array_l_sorted) - l

            elif array_l_sorted[l] < array_r_sorted[r]:
                sorted_list.append(array_l_sorted[l])
                l += 1

        return np.array(sorted_list), count

现在,我们可以比较分裂-征服方法与蛮力方法的效率。随着数组大小的增加,显然分裂-征服方法在计算成本方面提供了巨大的优势。这个结果清楚地描述了高效编写算法的重要性。

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

来源:作者的计算

基本算法—寻找最接近的一对

原文:https://towardsdatascience.com/basic-algorithms-finding-the-closest-pair-5fbef41e9d55?source=collection_archive---------4-----------------------

用分裂-征服算法确定二维平面上两点的最近对

编写性价比高的算法是作为一名数据科学家成功的关键之一,而在上一篇文章中我们在计算一个数组中的求逆时使用了分裂-征服法,这种方法的成本远低于蛮力法。这一次,我们将看到另一种分裂-征服算法如何从二维平面上的一组点中找到最近的一对点。

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

Unsplash 上由雷米·佩内特拍摄的照片

在时代广场或东京市中心仰望天空,我们会很容易找到最近的一对星星,因为在那里你只能看到几颗星星。如果你在一个不知名的地方,黑暗的夜空中无限多的星星会让你无法确定这一对。

对计算机来说也没什么不同;当他们确定平面上最接近的点对时,数据集的点越多,算法寻找距离最小的点对所需的时间就越长。成本的增加不仅仅是点的数量的线性增加,我们试图编写一个尽可能低的包含成本增加的算法。分裂-征服法在这个挑战中工作得很好,以类似的方式与算法计数倒置。

强力法——寻找最接近的一对

蛮力方法是,像在一个数组中计算反转一样,计算宇宙中每一对点的距离。对于 n 个点,我们需要测量 n(n-1)/2 个距离,成本是 n 的平方,即*θ(n)。*有了两个循环,这个算法的代码可以写成如下。

def **find_closest_brute_force**(array):

    result = {}
    result["p1"] = array[0]
    result["p2"] = array[1]
    result["distance"] = np.sqrt((array[0][0]-array[1][0])**2
                                +(array[0][1]-array[1][1])**2)

    for i in range(len(array)-1):
        for j in range(i+1, len(array)):
            distance = np.sqrt((array[i][0]-array[j][0])**2
                              +(array[i][1]-array[j][1])**2)
            if distance < result["distance"]:
                result["p1"] = array[i]
                result["p2"] = array[j]
                result["distance"] = distance
    return resultreturn result

现在我们想一个更好的方法,它的成本是。使用预分类和分治法是可能的。为了在一个坐标上对数组进行预排序,我们还使用了狭缝征服法,即合并排序算法。

合并排序

我们用一种叫做合并排序的算法对数组进行排序,这种算法比强力排序算法要快。merge-sort 算法拆分数组,对子数组进行排序(作为递归步骤),比较两个子数组中最年轻的数字并挑选较年轻的,并重复该操作,直到两个子数组都用完为止。每个递归步骤的开销仅为θ(n),因此算法的总开销保持在θ(nlgn)。

def **merge_sort**(array, coordinate=0):

    length = len(array) if length == 1:
        return array if length == 2:
        if array[0][coordinate] > array[1][coordinate]:
            return np.array([array[1], array[0]])
        else:
            return array

    elif length > 2:
        array_l = array[:length//2]
        array_r = array[length//2:]
        array_l_sorted = **merge_sort**(array_l, coordinate)
        array_r_sorted = **merge_sort**(array_r, coordinate)

        l_length = len(array_l)
        r_length = len(array_r) l = 0
        r = 0

        sorted_list = []

        for i in range(length):
            if r == r_length:
                sorted_list.append(array_l_sorted[l])
                l += 1 elif l == l_length:
                sorted_list.append(array_r_sorted[r])
                r += 1             

            elif array_l_sorted[l][coordinate] > array_r_sorted[r][coordinate]:
                sorted_list.append(array_r_sorted[r])
                r += 1

            elif array_l_sorted[l][coordinate] < array_r_sorted[r][coordinate]:
                sorted_list.append(array_l_sorted[l])
                l += 1

        return np.array(sorted_list)

分治法——寻找最接近的一对

如上所述,我们的目标是写一个算法,以 O(nlgn)的代价找到最近的一对点。使用分治算法,其递归步骤花费 O(n) 每一步就足够了。该算法将阵列划分为子阵列,关键是看两个子阵列中最近的一对是否。

分裂征服算法按 X 坐标对数组进行排序,将排序后的数组一分为二,将该算法递归应用于子数组,并检查是否存在一个距离比子数组中的距离短的数组对。

def **find_closest_nest**(array):
    X = **merge_sort**(array, 0)
    length = len(X)
    if length < 4:
        return **find_closest_brute_force**(array)

    else:
        array_l = X[:length//2]
        array_r = X[length//2:] dict_l = **find_closest_nest**(array_l)
        dict_r = **find_closest_nest**(array_r)

        if dict_l["distance"] > dict_r["distance"]:
            dict_both = dict_r
        else:
            dict_both = dict_l

        Y_list = []
        for i in range(length):
            if X[length//2-1][0]-dict_both["distance"] < array[i][0] < X[length//2-1][0]+dict_both["distance"]:
                Y_list.append(array[i]) Y = **merge_sort**(np.array(Y_list), 1)

        if len(Y) == 1:
            dict_final = dict_both
        elif len(Y) < 8:
            dict_y = **find_closest_brute_force**(Y)
            if dict_both["distance"] > dict_y["distance"]:
                dict_final = dict_y
            else:
                dict_final = dict_both            
        else:
            for i in range(len(Y)-7):
                dict_y = **find_closest_brute_force**(Y[i:i+7])        

                if dict_both["distance"] > dict_y["distance"]:
                    dict_final = dict_y
                else:
                    dict_final = dict_both

        return dict_final

最后一步,查看跨子阵列的对,需要一些技巧来将成本保持在线性水平(例如 O(n) ) *。*首先,我们将制作一个输入子集,它由距离 X 坐标中点 d 距离内的点组成; d 是子阵列内的一对之间的最短距离。如果我们在子阵列上找到最近的一对点,这对点应该存在于距离将阵列分成子阵列的线的距离 d 内。

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

在右手侧所示的例子中,子阵列中最近的一对在右侧子阵列中确定(注意虚线上的点属于左侧子阵列),其距离为 d

如果最接近的一对存在于左右子阵列中,那么这些点应该在从将阵列分成两个子阵列的虚线开始的 d 的范围内。因此,我们可以查看阴影范围内的子集。

其次,我们通过 Y 坐标对上一步中获得的子集进行排序。我们表明,我们必须着眼于只有八个连续点的集合,每个在排序子集。

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

如图所示,横跨左右子阵列的 2d* d 矩形中最多可以存在 8 个点(虚线上的点重复;两个属于左侧子阵列,另外两个在右侧)。

第三,我们查看按 Y 坐标排序的子集中的每组八个连续点。如果我们发现距离小于 d 的一对,这意味着最近的一对存在于子阵列中。这一步开销 O(n) ,这个递归算法的总开销停留在 O(nlgn)。

性能检查

我们了解到我们开发的分裂征服算法比暴力破解算法执行得更快。我们来比较两种算法的实际表现。在下面的图表中,两种算法的成本(执行时间)由不同大小的数组显示。这两条线清楚地表明,随着样本量的增加,分治法具有优势。这个结果证明了高效编码的重要性,这在上一篇文章中也讨论过。

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

来源:作者的计算

基本算法—堆排序

原文:https://towardsdatascience.com/basic-algorithms-heapsort-31d64d6919a1?source=collection_archive---------14-----------------------

用“堆”数据结构对数组排序

在以前的帖子中,我们看到了不同的排序算法,如合并排序快速排序,这次讨论的是另一种排序算法 Heapsort。Heapsort,顾名思义,使用“堆”数据结构。

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

苏珊·霍尔特·辛普森在 Unsplash 拍摄的照片

许多

堆是一种数据结构,堆是二叉树的数组。二叉树的每个节点对应于数组的一个元素。由于一个节点有零个、一个或两个子节点,对于数组的第 i- 个元素,第 2i- 个和第( 2i+1 )个元素分别是其左右子节点。

下图描述了一个示例堆,其中节点数等于 12 元素数组中的顺序数。根是数组中的第一个元素,它的左右子元素分别是第二个和第三个元素。第六个元素只有一个左子,第七个没有。

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

最小堆示例

有两种堆:最小堆和最大堆。在最小堆中,父节点比子节点小(根节点最小),而在最大堆中则相反(根节点最大)。在本文中,我们将使用 max-heap 属性进行堆排序。

堆排序

策略如下:I)将数组转换成最大堆;ii)挑选根,这是最大数;iii)将剩余的数组保持为最大堆;iv)递归 ii)和 iii)。

下面是步骤 iii)的代码,它也用于步骤 I)。这个“Max-Heapify”函数有两个输入:一个数组和一个整数。该函数将给定顺序的节点(输入整数)与其两个子节点进行比较。如果节点比任何一个子节点都小,它将与两个子节点中最大的一个交换。

def **max_heapify**(array, i):
    l = (i+1) * 2 - 1
    r = (i+1) * 2
    length = len(array) if l < length and array[l] > array[i]:
        largest = l
    else: 
        largest = i

    if r < length and array[r] > array[largest]:
        largest = r

    if largest != i:
        largest_value = array[largest]
        array[largest] = array[i]
        array[i] = largest_value
        **max_heapify**(array, largest)

    return array

虽然 Max-Heapify 不会耗尽整个堆,但是通过对除了叶子(堆的末端节点)之外的所有节点操作该函数,我们可以将任何数组转换为 max-heap。

def **build_max_heap**(array):
    length = len(array)
    for i in range(length//2, -1, -1):
        **max_heapify**(array, i) return array

现在我们准备实现 Heapsort。

def **heap_sort**(array):
    length = len(array)
    array = **build_max_heap**(array)
    for i in range(length-1, 0, -1):
        largest = array[0]
        array[0] = array[i]
        array[i] = largest
        **max_heapify**(array[:i], 0)

    return array

下图解释了 Heapsort 如何处理一个 12 元素数组;I)首先,我们将数组转换为最大堆;ii)取根 12,用最后一个元素 3 代替;iii)在剩余的 11 元素数组的根上处理 Max-Heapify,受影响的节点以深蓝色显示;iii)递归 ii)和 iii)。最后我们将得到一个按升序排序的数组。堆排序就地操作,在输入数组之外只存储恒定数量的数据。

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

示例堆排序过程

堆集成本

我们可以通过检查 Max-Heapify 和 Build-Max-Heap 的子函数来分析 Heapsort 的开销。

Max-Heapify 的代价是 O(lgn) 。比较一个节点和它的两个子节点的成本θ(1),在最坏的情况下,我们递归 ⌊logn⌋ 次到底部。或者,Max-Heapify 的成本可以用堆的高度hO(h)来表示。

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

Build-Max-Heap 的开销是 O(n) 。由于一个 n 元素堆的深度为 ⌊lgn⌋ ,并且在任意高度,除了叶子之外还有 ⌈n/2ʰ⁺ ⌉ 节点,我们可以将成本导出为 Max-Heapify 成本的总和 O(h) ,如左图所示。

Heapsort 的总开销是 O(nlgn) ,因为它调用 Build-Max-Heap ( O(n) )和 Max-Heapify ( O(lgn) )超过 (n-1) 次。

性能检查

下图描述了不同的排序算法。正如预期的那样,Heapsort 遵循其他的 O(nlgn) -cost 算法,尽管它不如隐藏在 O 符号中的常数更高的 Quicksort 便宜。

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

来源:作者的计算

尽管 Heapsort 在排序算法上不如 Quicksort,但是 Heap 作为数据结构提供了许多不同的用途,其中最值得注意的是在优先级队列中。作为对堆的介绍,我们将在后面看到堆是如何应用于一个有效的优先级队列算法的。

基本算法—快速排序

原文:https://towardsdatascience.com/basic-algorithms-quicksort-b549ea9ef27?source=collection_archive---------18-----------------------

用随机选择的枢轴对数组排序

我在的上一篇文章中介绍了一种叫做 Merge-Sort 的排序算法,并在这篇文章中继续讨论另一种排序算法 Quicksort。快速排序的期望代价是θ(nlgn),而代价为θ(n)的最坏情况只会以 2 /n 的概率出现!。我将在稍后的性能比较中展示隐藏在θ符号中的常数在 Quicksort 中更低,因此该算法优于成本相同的 Merge-Sortθ(nlgn)。

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

安德鲁·布坎南在 Unsplash 上拍摄的照片

插入排序

插入排序是一种强力算法,它比较数组中的所有对来排序。这是人们在 porker 或其他纸牌游戏中常用的发牌方式。代价是θ(n)。

def **insertion_sort**(array):
    for j in range(1, len(array)):
        key = array[j]
        i = j - 1
        while i >= 0 and array[i] > key:
            array[i+1] = array[i]
            i -= 1
        array[i+1] = key
    return array

合并排序

之前的文章中,我们讨论了作为基本分治算法之一的合并排序算法。这一次,我们将使用一个更简单的版本,因为我们只处理一维数组。

def **merge_sort**(array):

    length = len(array)

    if length == 1:
        return array

    elif length == 2:
        if array[0] > array[1]:
            return np.array([array[1], array[0]])
        else:
            return array

    elif length > 2:
        array_l = array[:length//2]
        array_r = array[length//2:]
        array_l_sorted = **merge_sort**(array_l)
        array_r_sorted = **merge_sort**(array_r) l = 0
        r = 0

        l_length = len(array_l)
        r_length = len(array_r)

        sorted_list = []

        for i in range(length):
            if r == r_length:
                sorted_list.append(array_l_sorted[l])
                l += 1 elif l == l_length:
                sorted_list.append(array_r_sorted[r])
                r += 1               

            elif array_l_sorted[l] > array_r_sorted[r]:
                sorted_list.append(array_r_sorted[r])
                r += 1

            elif array_l_sorted[l] < array_r_sorted[r]:
                sorted_list.append(array_l_sorted[l])
                l += 1

        return np.array(sorted_list)

快速排序

快速排序算法从一个数组中随机选取一个轴心,并将原始数组分成两个子数组:一个子数组由小于轴心的数字组成,另一个子数组由较大的数字组成。通过递归地这样做,我们将最终获得排序后的数组。

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

这里有一个简单的例子,你有一个 8 个数字的数组。在这种情况下,随机选择的支点变成了 6 个。然后,将小于 6 的数字分配给左边的子数组,将较大的数字分配给右边的子数组。

下一步是将算法递归应用到子阵列;随机枢轴现在在左(较小)子阵列中有两个,在右(较大)子阵列中有七个。通过递归地这样做,你将得到一个排序后的数组。

def **quick_sort**(array):
    length = len(array)

    if length <= 1:
        return array

    if length == 2:
        if array[0] > array[1]:
            return [array[1], array[0]]
        else:
            return array

    else:
        pivot = np.random.randint(0, length)
        small = []
        large = []

        for element in array:
            if element < array[pivot]:
                small.append(element)
            elif element > array[pivot]:
                large.append(element)

        if not small:
            return [array[pivot]] + **quick_sort**(large)
        elif not large:
            return **quick_sort**(small) + [array[pivot]]
        else:
            return (**quick_sort**(small)
                    + [array[pivot]]
                    + **quick_sort**(large))

在最坏的情况下,你可以按升序或降序随机选择支点(例如,在上面的例子中,1 比 8 或 8 比 1),成本将是θ(n)。然而,这是可以忽略的,因为它发生的概率只有 2/n!(例中 21600 次一次)。所以我们考虑算法的期望成本。

排序算法的成本取决于它们比较了多少对。让我们考虑一下一个数组中的两个数 ZiZj (i < j) 进行比较的概率。 ZiZj 只有在 ZiZj 被选作支点时才直接比较,如果 ZiZj 之间的任意一个数被选作支点,则从不直接比较( ZiZj 被分配给单独的子阵)。当在Zj、之外选择一个支点时,不会影响概率,因为Zj 在同一个子阵列中。这样,Zj 直接比较的概率是 2/(j - i+1)

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

因此,预期的比较次数是数组中所有数字对的 2/(j - i+1) 之和。

通过一些如左图所示的变形,我们发现该数字收敛到熟悉的θ(nlgn)。我们可以说快速排序算法的期望代价是θ(nlgn)。

就地快速排序

我们可以就地编写 Quicksort 算法,这意味着该算法只存储原始数组之外的常量数据。就地算法具有占用内存少的优点。下面是就地快速排序算法的代码。

def **quick_sort_in_place**(array, start, end):
    if start < end:

        if start + 1 == end:
            if array[start] > array[end]:
                larger = array[start]
                array[start] = array[end]
                array[end] = larger

        pivot = np.random.randint(start, end+1)
        pivot_value = array[pivot]

        array[pivot] = array[-1]
        array[-1] = pivot_value

        border = start - 1

        for i in range(start, end):
            if array[i] < pivot_value:
                border += 1
                border_value = array[i]
                array[i] = array[border]
                array[border] = border_value
        array[-1] = array[border+1]
        array[border+1] = pivot_value

        array = **quick_sort_in_place**(array, start, border+1)
        array = **quick_sort_in_place**(array, border+2, end) return array

性能检查

现在我们比较插入排序(θ(n))、合并排序(θ(nlgn))和快速排序(预期θ(nlgn))的性能。

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

来源:作者的计算

显然,合并排序和快速排序比插入排序有优势,它们的斜率比插入排序平缓。由于隐藏在*θ(nlgn)*符号中的常数较低,快速排序算法比合并排序更快,而快速就地排序与合并排序花费的时间一样多(即就地优势被一些其他成本抵消)。

由于快速排序算法包含一些随机性,所以查看试验的成本分布是有用的。这是快速排序和合并排序算法处理 2 个⁰数 10,000 次试验的成本直方图。注意,如图所示,合并排序也容易出现随机性。两种分布都向最便宜的一端倾斜(左)。

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

来源:作者的计算

我们从快速排序算法中学到的一件事是,随机性可以成为我们的朋友。快速排序比其他排序算法更有效地处理大量数字。有了适当的概率论知识,我们也许能够写出成本较低的算法。

作为数据科学家,您需要了解的基本业务概念

原文:https://towardsdatascience.com/basic-business-concepts-you-need-to-know-as-a-data-scientist-faeaaf5056f?source=collection_archive---------17-----------------------

初学者指南和基本商业基础的复习

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

肖恩·波洛克在 Unsplash 上的照片

目录

  1. 一个企业的首要目标
  2. 收入最大化:产品和营销
  3. 成本最小化:运营和客户服务
  4. okr 和 KPI
  5. 机器学习生命周期的规划阶段

如果我问你数据科学是什么,你会怎么想?

我敢打赌,你们很多人都会想到大数据、机器学习模型和人工智能。但是我敢打赌,你没有考虑到业务,这是完全合理的。如果数据科学完全是关于商业的,公司就不会雇佣那些有 STEM 背景的人。

也就是说,对于所有数据科学家来说,对业务基础有一个基本的了解是必不可少的。通过了解业务,您将更好地理解每个数据科学项目背后的动机,以及每个项目如何使整个公司受益。

话虽如此,让我们来谈谈企业的主要目标。

企业的主要目标

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

照片由莎伦·麦卡琴Unsplash 上拍摄

企业的首要目标是为其所有者获取最大利润

所有者是指公司的创始人,如果公司是上市公司,也指公司的股东。你必须理解这一点,因为每个公司的决策都围绕着利润最大化。

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

利润等于收入和成本之间的差额。收入定义为收益。成本又称费用,定义为公司运营产生收益所花费的金钱。

为什么了解这一点对您很重要?因为业务中的每一项举措(例如数据科学项目)都是为了增加收入或降低成本以实现利润最大化。从本质上来说,不同的业务部门可以归为两类:收入最大化和成本最小化。

收入最大化

属于这一类别的两个主要部门是产品营销:

产品和数据科学

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

轴箱Unsplash 上拍照

一个产品可以是一件商品、一项服务或一个想法,是为了满足一种需求而创造的。例如,汽车是一种商品,是为了满足运输的需要而产生的。

然而,对于业务部门来说,产品是指与产品研发、开发和维护相关的所有活动。不要把这个“产品”的定义和上面的混淆了!

就产品而言,数据科学有两个目的:创造新产品和增强现有产品。自动驾驶汽车是数据科学如何帮助创造新产品的一个例子。然而,更常见的是,数据科学用于增强现有产品。这方面的一个流行的例子是网飞如何开发一个最先进的推荐系统。

营销和数据科学

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

摄影师Unsplash 上拍摄的照片

营销的正式定义是所有与促进购买或销售产品相关的活动。营销包括广告、定价和了解目标市场等内容。市场营销曾经是一门艺术,而不是一门科学,但数据科学已经彻底改变了公司进行市场营销的方式。

数据科学在营销中的应用示例包括:

  • 营销归属:一个公司可以使用的营销渠道有几十种。社交媒体、联盟营销、SEO、SEM、博客、电视、广播等等。但是一个公司怎么知道哪些营销渠道比其他的更有效呢?数据科学用于尝试通过归因建模营销组合建模等方法来衡量各种营销渠道的影响。
  • **定价和折扣优化:**通过提高产品价格,利润变得更高,但想购买该产品的顾客会更少,反之亦然。这意味着每种产品都有一个最优价格来实现利润最大化。数据科学被用来寻找最优价格。
  • 顾客细分:虽然看起来令人惊讶,但许多企业并不十分了解他们的顾客。聚类方法通常用于更好地了解客户群的特征。例如,如果一家公司通过集群意识到他们的产品在青少年中受欢迎,而不是中年人,那么该公司可以重新调整他们的广告策略。
  • 流失预测建模:当客户流失时,意味着他们决定停止与该公司的业务往来。例如,如果一家公司与手机公司 A 合作,但转到了公司 B,那么客户就会从公司 A 流失。公司现在正在开发模型来预测客户何时会流失,并制定留住客户的计划。

成本最小化

属于这一类别的数据科学活动可以用一个词来描述;自动化。数据科学发挥巨大作用的两个主要部门是运营和客户服务。

运营和数据科学

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

Ruchindra GunasekaraUnsplash 上拍摄的照片

企业经营是指企业每天从事的活动。通常,运营的主要目标是尽可能提高任务和流程的效率,这意味着在最大限度减少错误的同时最大限度地增加完成任务的时间。人类效率低,成本高,但自动化可以代替人类完成重复而平凡的任务。运营自动化的一个流行例子是亚马逊的仓库机器人。

客户服务和数据科学

客户服务是指公司向客户提供的支持。随着公司规模的增长,有理由认为需要支持的客户数量也会相应增加。就像我之前说的,人类效率低,成本高,这就是为什么数据科学也给客户服务带来了革命。最普遍的例子是聊天机器人的开发。虽然聊天机器人还不能完全取代人类,但它们可以回答简单的问题,并通过 NLP 算法将客户重定向到正确的服务代表。

okr 和 KPI

既然你已经知道了企业的主要目标,以及每一项举措是如何增加收入或降低成本的,我们就可以谈论一下 OKRs 和 KPI 了。

目标&关键结果的简称,它是一个定义和跟踪目标及其结果的框架——你可以把它们看作目标。通常情况下,每个部门都有自己的 okr,每个季度设置一次。例如,营销部门可能有一个 OKR 来增加从 X 到 y 的转化率

KPI 是关键绩效指标的缩写,它们本质上是显示公司如何有效实现其业务目标的指标。继续以营销为例,上述目标的 KPI 可以是网站流量的增加或营销 ROI 的增加。

作为一名数据科学家,了解这两个术语非常重要,因为它们是机器学习生命周期规划阶段的一部分,我接下来会谈到这一点。

机器学习生命周期的规划阶段

在你开始任何机器学习项目之前,你需要计划一些事情。这一步的主要目的是让公司了解一个给定的项目将如何为公司增加价值,是通过增加收入还是降低成本。

规划包括以下任务:

  • 陈述你试图解决的问题。这似乎是一个简单的步骤,但你会惊讶地发现,人们经常试图为一个不存在的问题或一个实际上并不存在的问题找到解决方案。
  • 定义你为解决问题而努力实现的业务目标。这听起来像是在定义 OKR,不是吗?这不是巧合。
  • 确定目标变量(如适用)和您可能想要关注的潜在特征变量。例如,如果目标是减少欺诈性交易的数量,您很可能需要欺诈性和非欺诈性交易的标记数据。您可能还需要像交易时间、帐户 ID 和用户 ID 这样的特性。
  • 考虑任何限制、意外和风险。这包括但不限于资源限制(缺少资金、员工或时间)、基础设施限制(例如缺少训练复杂神经网络的计算能力)和数据限制(非结构化数据、缺少数据点、无法解释的数据等)
  • 建立你的成功标准。这听起来像是一个 KPI,不是吗?你如何知道你已经成功实现了你的目标?如果你的机器学习模型有 90%的准确率是成功的吗?85%呢?准确性是最适合您的业务问题的衡量标准吗?查看我关于 的文章,数据科学家使用这些指标来评估他们的模型

感谢阅读!

如果你喜欢我的工作,想支持我…

  1. 支持我的最好方式是在媒体上关注我这里
  2. Twitter 这里成为第一批关注我的人之一。我会在这里发布很多更新和有趣的东西!
  3. 此外,成为第一批订阅我的新 YouTube 频道 这里
  4. LinkedIn 上关注我这里
  5. 在我的邮箱列表** 这里报名。**
  6. 看看我的网站,terenceshin.com

用 Python 实现科学数据的基本曲线拟合

原文:https://towardsdatascience.com/basic-curve-fitting-of-scientific-data-with-python-9592244a2509?source=collection_archive---------0-----------------------

Python 科学绘图

使用 Python 将非线性函数拟合到实验数据点的基本指南

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

克里斯·利维拉尼在 Unsplash 上拍摄的照片

除了从我们的实验中绘制数据点之外,我们还必须经常将它们拟合到理论模型中,以提取重要的参数。这篇短文将指导如何将一组点拟合到一个已知的模型方程,我们将使用scipy.optimize.curve_fit函数来完成。用 Python 为科学出版物绘制数据的基础知识可以在我之前的文章这里中找到。我将介绍三种常见的非线性拟合:(1)指数拟合,(2)幂律拟合,以及(3)高斯峰值拟合。

为了使用curve_fit函数,我们使用下面的import语句:

# Import curve fitting package from scipy
from scipy.optimize import curve_fit

在这种情况下,我们只使用scipy包中的一个特定函数,所以我们可以直接导入只是 curve_fit

指数拟合

假设我们有一个如下形式的一般指数函数,我们知道这个表达式适合我们的数据(其中 ab 是我们将适合的常数):

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

一般指数函数

首先,我们必须定义如上所示的指数函数,以便curve_fit可以使用它来进行拟合。

# Function to calculate the exponential with constants a and b
def exponential(x, a, b):
    return a*np.exp(b*x)

我们将从生成一个“虚拟”数据集来适应这个函数开始。要为我们的 x 值生成一组均匀分布在指定间隔上的点,我们可以使用np.linspace函数。

# Generate dummy dataset
x_dummy = np.linspace(start=5, stop=15, num=50)

start —我们序列的起始值

stop —序列的结束值(将包括该值,除非您提供额外的参数endpoint=False)

num —将间隔分割成的点数(默认为50)

注意,您不需要显式地写出输入名称— np.linspace(-5, 5, 100)同样有效,但是对于本文的目的来说,它使事情更容易理解。

对于我们的虚拟数据集,我们将把 ab 的值都设置为 0.5。

# Calculate y-values based on dummy x-values
y_dummy = exponential(x_dummy, 0.5, 0.5)

为了确保我们的数据集不是完美的,我们将使用np.random.normal在我们的数据中引入一些噪声,它从正态(高斯)分布中抽取一个随机数。然后,我们将这个随机值乘以一个标量因子(本例中为 5 ),以增加噪声量:

# Add noise from a Gaussian distribution
noise = 5*np.random.normal(size=y_dummy.size)
y_dummy = y_dummy + noise

size —随机数输出数组的形状(在这种情况下与y_dummy的大小相同)

现在,让我们绘制我们的虚拟数据集,以检查它看起来像什么。因为我们有一个噪声数据点的集合,我们将做一个散点图,我们可以很容易地使用ax.scatter函数。我将跳过许多情节美学上的修改,这些在我的上一篇文章中详细讨论过。为了指定点的颜色,我直接使用了十六进制代码。

# Plot the noisy exponential data
ax.scatter(x_dummy, y_dummy, s=20, color='#00b3b3', label='Data')

s —以(点)为单位的标记大小,因此当该值增加四倍时,标记大小加倍

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

添加高斯噪声的虚拟指数数据散点图

一种通常更有用的可视化指数数据的方法是使用半对数图,因为它将数据线性化。为了将 y 轴的刻度从线性设置为对数,我们添加以下行:

# Set the y-axis scaling to logarithmic
ax.set_yscale('log')

由于对数函数中的渐近线,我们现在还必须将 y 轴下限设置为大于零。此外,对于刻度线,我们现在将使用LogLocator功能:

# Set the y-ticks
ax.yaxis.set_major_locator(mpl.ticker.LogLocator(base=10.0))# Set the y-axis limits
ax.set_ylim(0.1, 1000)

base —用于对数轴主刻度的基数

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

带有对数 y 轴的虚拟指数数据散点图

我们现在可以将我们的数据拟合到一般的指数函数中,以提取参数 ab ,并将拟合叠加到数据上。请注意,尽管我们在上面给出了半对数图,但我们实际上并没有改变y 数据——我们只是改变了 y 轴的刻度。因此,我们仍然在拟合非线性数据,这通常更好,因为在拟合之前对数据进行线性化会改变拟合的残差和方差。

# Fit the dummy exponential datapars, cov = curve_fit(f=exponential, xdata=x_dummy, ydata=y_dummy, p0=[0, 0], bounds=(-np.inf, np.inf))

输入

f —用于装配的功能(在本例中为exponential)

xdata —拟合的 x 数据数组

ydata —拟合的 y 数据数组

p0 —拟合参数的初始猜测值数组(aa和 bb均为 0)

bounds —参数的界限(-∞到∞)

输出

pars —来自 fit 的参数数组(在本例中为[a, b])

covpars的估计协方差,可用于确定拟合参数的标准偏差(对角线的平方根)

我们可以从curve_fit输出中提取参数及其标准偏差,并通过从实际观察值(我们的虚拟数据)中减去计算值(从我们的拟合中)来计算残差

# Get the standard deviations of the parameters (square roots of the # diagonal of the covariance)
stdevs = np.sqrt(np.diag(cov))# Calculate the residuals
res = y_dummy - exponential(x_dummy, *pars)

*pars —允许我们展开pars数组, [a, b]作为a, b输入

拟合参数和标准偏差

a =0.509 0.017

b = 0.499 0.002

我们看到两个拟合参数都非常接近我们的输入值a = 0.5b = 0.5,因此curve_fit函数收敛到正确的值。现在,我们可以将拟合叠加到散点数据上,还可以绘制残差,残差应该是随机分布的,并且接近于 0,从而确认我们有很好的拟合。

# Plot the fit data as an overlay on the scatter data
ax.plot(x_dummy, exponential(x_dummy, *pars), linestyle='--', linewidth=2, color='black')

linestyle —绘制线的线型(--表示虚线)

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

拟合线重叠的虚拟指数数据散点图

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

指数拟合的残差图

幂律拟合

另一种常用的拟合函数是幂律,其一般公式可以是:

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

一般幂律函数

与之前的拟合类似,我们首先定义函数:

# Function to calculate the power-law with constants a and b
def power_law(x, a, b):
    return a*np.power(x, b)

然后,我们可以再次创建一个虚拟数据集,添加噪声,并绘制我们的幂律函数。

# Generate dummy dataset
x_dummy = np.linspace(start=1, stop=1000, num=100)
y_dummy = power_law(x_dummy, 1, 0.5)# Add noise from a Gaussian distribution
noise = 1.5*np.random.normal(size=y_dummy.size)
y_dummy = y_dummy + noise

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

添加了高斯噪声的虚拟幂律数据的散点图

与指数拟合情况类似,幂律函数形式的数据可以通过绘制对数图来线性化,这一次, xy 轴都被缩放。

# Set the x and y-axis scaling to logarithmic
ax.set_xscale('log')
ax.set_yscale('log')# Edit the major and minor tick locations of x and y axes
ax.xaxis.set_major_locator(mpl.ticker.LogLocator(base=10.0))
ax.yaxis.set_major_locator(mpl.ticker.LogLocator(base=10.0))# Set the axis limits
ax.set_xlim(10, 1000)
ax.set_ylim(1, 100)

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

对数轴虚拟幂律数据散点图

现在,我们可以遵循与指数数据相同的拟合步骤:

# Fit the dummy power-law data
pars, cov = curve_fit(f=power_law, xdata=x_dummy, ydata=y_dummy, p0=[0, 0], bounds=(-np.inf, np.inf))# Get the standard deviations of the parameters (square roots of the # diagonal of the covariance)
stdevs = np.sqrt(np.diag(cov))# Calculate the residuals
res = y_dummy - power_law(x_dummy, *pars)

拟合参数和标准偏差

a = 1.057 0.096

b = 0.492 0.014

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

具有重叠拟合线的虚拟幂律数据散点图

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

幂律拟合的残差图

高斯峰值拟合

在诸如 X 射线衍射和光致发光的实验中,非常普遍地使用高斯函数、洛伦兹函数或两者组合的峰值拟合来确定线宽和其他属性。在这个例子中,我们将使用下面的通用公式来处理高斯峰值的拟合:

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

一般高斯函数

# Function to calculate the Gaussian with constants a, b, and c
def gaussian(x, a, b, c):
    return a*np.exp(-np.power(x - b, 2)/(2*np.power(c, 2)))# Generate dummy dataset
x_dummy = np.linspace(start=-10, stop=10, num=100)
y_dummy = gaussian(x_dummy, 8, -1, 3)# Add noise from a Gaussian distribution
noise = 0.5*np.random.normal(size=y_dummy.size)
y_dummy = y_dummy + noise

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

添加了噪声的虚拟高斯数据的散点图

就像在指数和幂律拟合中一样,我们将尝试进行高斯拟合,每个参数的初始猜测值为 0。

# Fit the dummy Gaussian data
pars, cov = curve_fit(f=gaussian, xdata=x_dummy, ydata=y_dummy, p0=[0, 0, 0], bounds=(-np.inf, np.inf))# Get the standard deviations of the parameters (square roots of the # diagonal of the covariance)
stdevs = np.sqrt(np.diag(cov))# Calculate the residuals
res = y_dummy - power_law(x_dummy, *pars)

但是,当我们这样做时,我们会得到以下结果:

print(pars)
>>> [0\. 0\. 0.]print(stdevs)
>>> [inf inf inf]

似乎我们的初始猜测不允许拟合参数收敛,所以我们可以用更真实的初始猜测再次运行拟合。您可以通过检查要拟合的峰值并选择合理的初始值来实现这一点。

# Fit the dummy Gaussian data
pars, cov = curve_fit(f=gaussian, xdata=x_dummy, ydata=y_dummy, p0=[5, -1, 1], bounds=(-np.inf, np.inf))

这一次,我们的拟合成功了,我们得到了以下拟合参数和残差:

拟合参数和标准偏差

一个 = 8.074 0.128

b=–0.948 0.054

c = 2.945 0.054

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

覆盖拟合的虚拟高斯数据散点图

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

高斯拟合的残差图

结论

希望,在前面例子的引导下,你现在应该能够将你的实验数据拟合到任何非线性函数!我希望你喜欢这个教程,这里展示的所有例子都可以在这个 Github 仓库找到。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值