TowardsDataScience-博客中文翻译-2020-八-
TowardsDataScience 博客中文翻译 2020(八)
原文:TowardsDataScience Blog
协议:CC BY-NC-SA 4.0
预测房地产价格的数据科学网络应用程序
原文:https://towardsdatascience.com/a-data-science-web-app-to-predict-real-estate-price-d2366df2a4fd?source=collection_archive---------27-----------------------
数据科学+机器学习+ Web 开发
Web 开发和数据科学一直是我的激情所在。把这两个兴趣结合起来,融合在一起,做一个项目,一直是一个思路。最后,我通过构建一个 web 应用程序来完成这项任务,该应用程序可以预测印度 Bengaluru 市的房地产价格。这是一个巨大的项目,已经花了一段时间。我会确保带你走完我跟随的每一步。
斯蒂芬·道森在 Unsplash 上拍摄的照片
该项目主要有 4 个步骤:
- 数据科学
- 机器学习
- 后端
- 前端
应用程序的架构
数据科学
第一步是典型的数据科学工作,我们从 Kaggle 获取一个名为“ Bengaluru 房价数据”的数据集。我们将对它执行一些广泛的数据清理工作,以确保它在预测过程中给出准确的结果。
这个名为'realestepricepredictor . ipynb'的 jupyter 笔记本是我们执行所有数据科学相关工作的地方。因为 jupyter 笔记本是不言自明的,所以我将简要地谈一下我所实现的概念。我们的数据集需要大量的数据清理工作。事实上,笔记本 70%的内容都是关于数据清理的,我们删除空行,删除对预测没有帮助的不必要的列。
下一步是特征工程,即从数据集中提取对成功预测贡献最大的有用和重要信息的过程。
最后一步是处理异常值。异常值是对数据和预测造成巨大破坏的异常现象。从逻辑上来说,要从数据集中发现并去除这些异常值,需要了解很多东西。
同样,所有这些都已经在 jupyter 笔记本中解释过了。
最终,原始数据集从大约 13000 行和 9 列减少到大约 7000 行和 5 列。
机器学习
获得的最终数据服从于机器学习模型。我们将主要使用 K-fold 交叉验证和 GridSearchCV 技术来执行超参数调整,以获得模型的最佳算法和参数。
结果表明,线性回归模型为我们的数据提供了最好的结果,得分超过 80%,这还不错。
现在,我们的模型需要导出到一个 pickle 文件(Bengal uru _ House _ data . pickle)中,该文件将 python 对象转换成字符流。此外,我们需要将位置(列)导出到一个 json( 列. json )文件中,以便能够从前端与它进行交互。
计算机网络服务器
我们将使用 Flask 服务器作为我们的后端来本地托管应用程序。在服务器文件夹中,我们将建立两个文件:
- server.py
server.py 文件将负责处理获取位置名称和预测房价的路径。它还从前端获取表单数据,并将其馈送给 util.py。这些路线可以使用 Postman app 进行测试。
- util.py
util.py 文件是后端的主脑。它有一个加载 JSON 和 pickle 文件的函数。该文件采用来自 server.py 的表单数据,并使用该模型来预测房产的估计价格。
前端
前端由简单的 HTML 、 CSS 和 JavaScript 组成。用户可以在表格中选择平方英尺的面积,BHK,浴室和位置的数量,并点击“估计”按钮,以获得估计的价格。JavaScript 文件负责与后端 flask 服务器路由和前端 HTML 交互。它获取用户填写的表单数据,并调用使用预测模型的函数,以 10 万卢比(10 万卢比= 100000)来呈现估计价格。
结果
让我们看看我们的项目是如何运作的。在后台运行 server.py 文件,打开我们创建的 HTML 网页。输入房产的面积(平方英尺)、BHK 的数量、浴室的数量和位置,然后点击“估算”。😲耶!我们预测了某人梦想中的房子的价格。
奖励—部署
这一部分相当棘手,所以请务必跟着我做每一步。
到目前为止,该项目只是本地的,我们将学习如何使用 AWS EC2 实例将应用程序部署到 web。
体系结构
我们将使用 nginx,它是一个可以服务 HTTP 请求的 web 服务器。nginx 可以与我们的 Flask 服务器交互。
从这里下载 nginx 并安装。
- 步骤 1: 为了进行估算,在 script.js 文件中,最初我们有这两行:
var url = "http://127.0.0.1:5000/predict_home_price";
var url = "http://127.0.0.1:5000/get_location_names";
这两行只是为了在本地运行我们的应用程序,现在我们必须将这两行改为:
*var url = "/api/predict_home_price";
var url = "/api/get_location_names";*
我们需要在 nginx 服务器上配置反向代理,以便所有对'/api '的请求只被路由到端口 5000。
- 第二步:登录您的 AWS 控制台。您需要知道如何免费启动 AWS EC2 实例。在按照步骤 6 启动实例时,请确保添加 HTTP 和 HTTPS 请求类型,以确保人们可以访问您的网站。
- 第三步:创建新的密钥对,输入名称,下载密钥(。pem 文件)并启动 EC2 实例。
- 步骤 4: 点击“启动实例”旁边的“连接”选项,在“示例”下会有一个命令。
复制此命令。它看起来会像这样。
- 步骤 5: 打开 bash shell 并粘贴这个命令,但是用下载的 pem 文件的路径替换涂黑的区域。
现在,您已经连接到 AWS cloud 上的 Linux 机器。
- 步骤 6: 现在你需要使用 WinSCP 将你的项目复制到那个虚拟机上。下载并启动 WinSCP。
- 第 7 步:在您的 AWS 上,如果我们再次单击“连接”,在“示例”上方会出现一个命令,类似于:
将此复制到您的 WinSCP 主机名,因为这是您的虚拟机的主机名。
- 第七步:用户名为' ubuntu '。在输入密码之前,我们需要将。pem 文件放入。使用 PuTTYgen 的 ppk 文件。请从这个链接下载 PuTTYgen。
- 单击密码字段下的“高级”按钮。选择下载的。pem 文件,它将打开 PuTTYgen 来转换。pem 文件到。ppk 文件。选择新的。ppk,然后单击“确定”。
- 点击“登录”。
- 将您的整个根项目文件夹(RealEstatePricePrediction)从您的机器复制到云服务器。
- 在服务器的 ubuntu shell 上执行以下命令:
sudo apt-get update
sudo apt-get install nginx
- 将我们之前看到的“连接”对话框中的主机名复制粘贴到浏览器中。
你应该会看到 nginx 运行的主页。
- 步骤 8: 执行以下命令:
cd /etc/nginx/sites-enabled/
sudo unlink default
cd ../sites-available/
sudo vim BengaluruHousePrediction.conf
将下面的代码复制粘贴到。会议文件。这是反向代理设置。
server {
listen 80;
server_name BegaluruHousePrediction;
root /home/ubuntu/RealEstatePricePrediction/client;
index index.html;
location /api/ {
rewrite ^/api(.*) $1 break;
proxy_pass [http://127.0.0.1:5000;](http://127.0.0.1:5000;)
}
}
- 退出 vim 并执行以下命令:
cd ../sites-enabled/
ln -v -s /etc/nginx/sites-available/BengaluruHousePrediction.conf inside /etc/nginx/sites-enabled
我们在上面的命令中所做的是建立一个符号链接。
- 使用以下命令重新启动服务器:
sudo service nginx restart
- 使用以下方式检查状态:
sudo service nginx status
- 转到您的浏览器,在 url 中输入主机名链接。您应该看到您的应用程序前端加载,但后端还没有工作。
- 第 9 步:返回终端,键入:
cd ~
cd RealEstatePricePrediction/server/
sudo apt-get python3-pip
sudo pip3 install Flask
sudo pip3 install scikit-learn
sudo pip3 install numpy
- 使用以下方式启动后端服务器:
python server.py
您的应用程序现已在互联网上运行,可从世界任何地方访问。
我知道部署阶段有点艰难。如果你遇到任何问题,可以通过我的 LinkedIn 联系我。在我的 GitHub 上随意检查整个代码库。
我希望你们都明白并学到了很多东西。
谢谢 !
数据科学家的方法:使用 Docker 运行 Postgres SQL
原文:https://towardsdatascience.com/a-data-scientist-approach-running-postgres-sql-using-docker-1b978122e5e6?source=collection_archive---------17-----------------------
面向数据科学家的 Docker 应用程序
面向数据科学家的 Postgres docker 容器
在这篇简短的教程中,我解释了设置在 Docker 中运行的 PostgreSQL 本地实例并使用 python 与数据库交互的步骤。已采取以下步骤来设置流程。
1.为 PostgreSQL
2 设置 docker。用 Pgadmin4
3 连接 Postgres。使用 Python 与 Postgresql 交互
我用过 Ubuntu 18.04 和 Python 3.7
Docker 中的 Postgres
Postgres 是一个流行的开源数据库,被从网络应用到数据科学项目的数据库应用广泛使用。
Postgress 是现代数据相关应用的主干
有许多数据库框架可供数据科学家选择。在为您的目标应用程序选择最佳框架时,需要考虑的一些因素可能是
- 您的应用程序需要关系数据库吗?
- 数据库和表计数的大小是多少?
- 数据库将驻留在哪里?
- 开源很重要吗?
- 您的前端有与 DB 交互的工具吗?
因为这里的目标受众是热爱开源的数据科学家,所以使用 Python 的 Postgres 是事实上的选择。
在过去的几年中,Docker 在开发人员和数据科学家中变得非常流行。Docker 帮助数据科学家共享开发环境,以便在任何机器上重现结果。此外,扩大生产规模是码头工人使用的额外好处。
我用的是由【bitnami】(https://bitnami.com/)和docker-compose
开发维护的 Postgres docker。下面是我在 docker 中运行 Postgress 的内容。
version: '2'services:
postgresql12:
image: 'bitnami/postgresql:12'
ports:
- '5432:5432'
volumes:
- 'postgresql_data_12:/bitnami/postgresql12'
environment:
- POSTGRESQL_USERNAME=postgres
- POSTGRESQL_PASSWORD=pwd0123456789
- POSTGRESQL_DATABASE=my_database
- ALLOW_EMPTY_PASSWORD=yesvolumes:
postgresql_data_12:
driver: local
当我们在 python 中连接这个实例时,这些信息非常有用。按照以下步骤运行docker-compose
。
- 如果之前没有安装 Docker(为 Ubuntu 安装 Docker)。
- 如果之前没有安装
docker-compose
(安装 Docker-Compose for Ubuntu ) - 从
docker-compose.yml
所在的目录运行docker-compose up
。
按照以上步骤操作后,可以去 http://localhost:5432/ 。
对于通过 Python 连接到 Postgres,我们使用docker-compose.yml.
中定义的信息
连接到 Postgres
我们已经通过 docker 成功剥离了 Postgress 服务器,可以通过 post 5432 的 localhost 访问。连接到 Postgres 服务器的一些最常见的方法是
- 使用 PgAdmin4
- 使用 psql 客户端工具
- 使用 Python
由于我们的重点是使用 Python 连接 Postgres 服务器,所以我们不打算讨论 1 和 2。
使用 Python 与 Postgres 交互
在本节中,我们将学习如何使用 python 与本地运行的 Postgres 进行交互。
code snip pts Credits:https://auth 0 . com/blog/sqlalchemy-ORM-tutorial-for-python-developers/
按照上面的链接,一行一行地详细描述下面的代码。
# To install sqlalchemy
! pip install sqlalchemy
安装完上面的包后,让我们连接到 Postgres 引擎。
```python
# Import objects
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmakerfrom datetime import date# Settings as shown in docker-compose.yml
engine = create_engine('postgresql://postgres:pwd0123456789@localhost:5432/my_database')
Session = sessionmaker(bind=engine)Base = declarative_base()from sqlalchemy import Column, String, Integer, Date, Table, ForeignKey, Boolean
from sqlalchemy.orm import relationship, backref
# from base import Base
创建一些表格
movies_actors_association = Table(
'movies_actors', Base.metadata,
Column('movie_id', Integer, ForeignKey('movies.id')),
Column('actor_id', Integer, ForeignKey('actors.id'))
)class Movie(Base):
tablename M= 'movies'id = Column(Integer, primary_key=True)
title = Column(String)
release_date = Column(Date)
actors = relationship("Actor", secondary=movies_actors_association)def init(self, title, release_date):
self.title = title
self.release_date = release_dateclass Actor(Base):
tablename = 'actors'id = Column(Integer, primary_key=True)
name = Column(String)
birthday = Column(Date)def init(self, name, birthday):
self.name = name
self.birthday = birthdayclass Stuntman(Base):
tablename = 'stuntmen'id = Column(Integer, primary_key=True)
name = Column(String)
active = Column(Boolean)
actor_id = Column(Integer, ForeignKey('actors.id'))
actor = relationship("Actor", backref=backref("stuntman", uselist=False))def init(self, name, active, actor):
self.name = name
self.active = active
self.actor = actorclass ContactDetails(Base):
tablename = 'contact_details'id = Column(Integer, primary_key=True)
phone_number = Column(String)
address = Column(String)
actor_id = Column(Integer, ForeignKey('actors.id'))
actor = relationship("Actor", backref="contact_details")def init(self, phone_number, address, actor):
self.phone_number = phone_number
self.address = address
self.actor = actor
按照下面的代码块将数据插入到使用上面的代码片段创建的数据库中。
from datetime import date# 2 - generate database schema
Base.metadata.create_all(engine)# 3 - create a new session
session = Session()# 4 - create movies
bourne_identity = Movie("The Bourne Identity", date(2002, 10, 11))
furious_7 = Movie("Furious 7", date(2015, 4, 2))
pain_and_gain = Movie("Pain & Gain", date(2013, 8, 23))# 5 - creates actors
matt_damon = Actor("Matt Damon", date(1970, 10, 8))
dwayne_johnson = Actor("Dwayne Johnson", date(1972, 5, 2))
mark_wahlberg = Actor("Mark Wahlberg", date(1971, 6, 5))# 6 - add actors to movies
bourne_identity.actors = [matt_damon]
furious_7.actors = [dwayne_johnson]
pain_and_gain.actors = [dwayne_johnson, mark_wahlberg]# 7 - add contact details to actors
matt_contact = ContactDetails("415 555 2671", "Burbank, CA", matt_damon)
dwayne_contact = ContactDetails("423 555 5623", "Glendale, CA", dwayne_johnson)
dwayne_contact_2 = ContactDetails("421 444 2323", "West Hollywood, CA", dwayne_johnson)
mark_contact = ContactDetails("421 333 9428", "Glendale, CA", mark_wahlberg)# 8 - create stuntmen
matt_stuntman = Stuntman("John Doe", True, matt_damon)
dwayne_stuntman = Stuntman("John Roe", True, dwayne_johnson)
mark_stuntman = Stuntman("Richard Roe", True, mark_wahlberg)# 9 - persists data
session.add(bourne_identity)
session.add(furious_7)
session.add(pain_and_gain)session.add(matt_contact)
session.add(dwayne_contact)
session.add(dwayne_contact_2)
session.add(mark_contact)session.add(matt_stuntman)
session.add(dwayne_stuntman)
session.add(mark_stuntman)# 10 - commit and close session
session.commit()
session.close()
下面是从 Postgres 服务器提取/读取数据的 python 代码片段。如果失去连接,请重新连接。
movies = session.query(Movie)
.filter(Movie.release_date > date(2015, 1, 1))
.all()print('### Recent movies:')
for movie in movies:
print(f'{movie.title} was released after 2015')
print('')# 6 - movies that Dwayne Johnson participated
the_rock_movies = session.query(Movie)
.join(Actor, Movie.actors)
.filter(Actor.name == 'Dwayne Johnson')
.all()print('### Dwayne Johnson movies:')
for movie in the_rock_movies:
print(f'The Rock starred in {movie.title}')
print('')# 7 - get actors that have house in Glendale
glendale_stars = session.query(Actor)
.join(ContactDetails)
.filter(ContactDetails.address.ilike('%glendale%'))
.all()print('### Actors that live in Glendale:')
for actor in glendale_stars:
print(f'{actor.name} has a house in Glendale')
print('')
## 结论
在这个简短的教程中,我们学习了如何使用 docker 设置一个本地 Postgres 服务器,并使用 python 与之交互。
由于 Postgres 运行在 docker 中,我们可以将这个 docker 部署到任何云上,只需做很少的更改。我们必须用主机的 IP 地址替换本地主机,这样一切都可以正常工作了。
# 收入多样化的数据科学家指南
> 原文:<https://towardsdatascience.com/a-data-scientist-guide-to-income-diversification-5b0f21b7deb0?source=collection_archive---------37----------------------->
## 当你可以有五种收入来源时,为什么要坚持单一收入来源呢?
作为一名数据科学家,你有点像独角兽——你知道一些编程、数据库、统计,当然还有数据。不利用每一点知识不会让你走得太远,朝九晚五也不像以前那样安全了。那么,你能做什么呢?多元化。

由[安妮·斯普拉特](https://unsplash.com/@anniespratt?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)在 [Unsplash](https://unsplash.com/s/photos/income?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上拍摄
***来自《走向数据科学》编辑的提示:*** *虽然我们允许独立作者根据我们的* [*规则和指南*](/questions-96667b06af5) *发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的* [*读者术语*](/readers-terms-b5d780a700a4) *。*
一开始就很难找到数据科学的工作。这不应该是最终目标,至少对千禧一代和更年轻的人(比如我)来说是这样,因为:
* 它不再那么安全了(COVID 危机证明了这一点)
* 我们不太关心安全
但即使我们做到了,依赖单一收入来源也不是一个人能做的最好的事情——至少对于数据科学家的技能来说不是。
问问你自己下面的问题:如果我现在失业了,这笔钱会持续多久?直到下个月 1 号?还是 10 号?无论如何,你得到了要点。只要你工作,你就能挣钱。
那个想法一点也不能让我兴奋。这就是为什么一年前,我决定分散我的收入来源,现在我有 5 个。
这怎么可能呢?下面你会发现五个部分,每个部分都描述了一个单一的收入来源以及我是如何维持它的。你也可以这样做,只要:
* **你有一些适销对路的技能** —数据科学家和软件工程师优先。这不是必须的,但如果这不是你的背景,你将不得不找出更多的东西
* 你愿意工作,我说的工作是指真正的工作。12 小时以上的工作日和周末工作对于接下来的事情来说是一个小小的代价
此外,不需要高于平均水平的智力。一个愿意努力工作的普通人每次都能打败有才华的懒蛋万事通。
让我们从第一个收入来源开始。
# 朝九晚五
我想这个对你们大多数人来说是显而易见的。我说普通工作不再那么安全了,但这并不意味着你应该辞职。至少在开始的时候。我来详细说明一下。
如果你已经开始工作了,放弃你唯一的收入来源去做其他事情是没有意义的。对个人项目的一些兴奋是很棒的,但更多的时候,它的回报恰恰是 0 美元,甚至从口袋里掏出一些钱。你现在还负担不起那种生活方式,但这只是时间问题。
朝九晚五会让你获得**相关工作经验**。你永远不会像你正在从事的一个新的企业级数据科学项目那样,把自己置身于舒适区之外。这是做得更好的必要条件。
让我再重复一遍——朝九晚五不应该是任何想要建立多种收入来源的人的最终目标。不管这份工作是在谷歌还是微软,或者薪水是 50 万美元。一旦你停止工作,这种收入流就停止了(换句话说,这是*主动收入*)。
# 副业
这一次也不应该让人感到意外。如果你有一些空闲时间,并且不介意在工作中抽出时间,试试*自由职业者*或者提供一些其他 B2B 服务也无妨。你会惊讶于一周只工作几个小时就能挣多少钱。
可能性是无限的——从在像 *UpWork* 这样的网站上做自由职业者,到开始自己的事业并在几年内扩大规模——这取决于你的抱负和你能投入的时间。同样,作为一名数据科学家,你的技能范围很广,所以你可以申请比前端开发人员更多的职位。
如果有一件事比找一份没有经验的工作更难的话,那就是得到你的第一个自由客户,至少在你的名字完全不为人知的情况下。所以做好被拒绝一个月的准备吧。这只是暂时的。
# 博客
这是我最喜欢的一个。对于任何数据科学家来说,这都是一个宝贵的工具,因为:
* 让你从人群中脱颖而出——阅读:招聘者来找你,而不是你来找他们(从长远来看)
* 让你更深刻地理解事物——因为你必须尽可能用最简单的方式解释它们
* 让你不断地学习新的东西——数据科学正在快速发展,所以你总是紧跟时代的步伐,你没有办法写不完的东西
* 兼职收入——每月几百到几千美元,取决于你投入的工作
如果你想作为一名数据科学家(或技术专家)了解更多关于博客的知识,请查看这篇文章:
[](/how-having-a-blog-can-advance-your-career-as-a-data-scientist-245270cc281e) [## 拥有一个博客如何推进你作为数据科学家的职业生涯
### 提示:这也适用于其他职业
towardsdatascience.com](/how-having-a-blog-can-advance-your-career-as-a-data-scientist-245270cc281e)
老实说,如果你想让自己和你的收入更上一层楼,这应该是显而易见的。当然,中型是一个很好的起点,但是您也可以选择托管您的内容。第一个选项是免费的,会更快地显示结果,但如果你想要 100%的内容控制,阶梯更好。
# 联盟营销
偶尔,我会读一本书或看一门比其他课程更好的课程。如果我发现它有益,没有理由不与我的观众分享它。此外,这种收入流自然伴随着博客而来,因为没有理由不让任何产品链接成为附属链接。
如果你不确定什么是代销商链接,请继续阅读。本质上,它是一个推荐链接,这意味着你将从通过你的链接购买的任何商品中获得一小笔佣金。最终用户的价格保持不变,甚至在某些情况下有所降低。
我经常用科技书籍来做这件事,这些书籍帮助我在工作中变得更好。请参阅下面的文章了解一下情况:
[](/the-single-best-introductory-statistics-book-for-data-science-a2601ea7c0be) [## 数据科学的最佳入门统计学书籍
### 了解数据科学最重要的支柱
towardsdatascience.com](/the-single-best-introductory-statistics-book-for-data-science-a2601ea7c0be)
如果你没有时间阅读,以下是我对联盟内容的思考过程:
1. 我读过/看过一本精彩的书/课程
2. 我的观众可以从中受益——写一篇简短的评论
3. 给这本书/课程添加一个附属链接,并确保公开它
这是一个简单的策略,每月无需额外努力就能赚几百美元——因为无论如何我都会写书评/课程评论。
亚马逊和 T2【Udemy】有很好的会员计划。
# 写书
有时候,我有一个内容想法,但不能写进一篇博文,因为它需要 45 分钟的阅读时间。没有人希望这样。那么,为什么不把它做成一本简短的*电子书*?
我进入这个收入流只有一周左右的时间,但是已经有一些人购买了我的[时间序列预测和 XGBoost](https://www.amazon.com/Time-Forecasting-Python-XGBoost-supervised-ebook/dp/B08KPM6TM5/ref=sr_1_1?dchild=1&keywords=dario+rade%26%23269%3Bi%26%23263%3B&qid=1602062782&sr=8-1) 电子书。
而且非常容易上手。最具挑战性的部分是,嗯,写和编辑这本书。出版很容易。让我们讨论两个选项:
* 通过你的网站——如果你有的话,WordPress/WooCommerce 组合也可以
* 通过亚马逊——首先我选择了这个选项,因为他们有很好的 Kindle 直接出版服务
我不能确切地告诉你这种收入流的利润会有多高,但这是一个让你出名并赚点钱的好方法。
# 结论
现在你知道了——确切地说,如何从一个收入来源增加到五个收入来源。这里有很多技术细节没有提到,因为,同样,这将是一个 45 分钟的阅读,但我希望你得到要点,并将自己进一步探索。
如有任何问题,请随时联系。请在 LinkedIn 上找到我并发送消息,我很乐意提供帮助。
感谢阅读。
[**加入我的私人邮件列表,获取更多有用的见解。**](https://mailchi.mp/46a3d2989d9b/bdssubscribe)
*喜欢这篇文章吗?成为* [*中等会员*](https://medium.com/@radecicdario/membership) *继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。*
[](https://medium.com/@radecicdario/membership) [## 通过我的推荐链接加入 Medium-Dario rade ci
### 作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)
*原载于 2020 年 10 月 9 日 https://betterdatascience.com*[](https://betterdatascience.com/a-data-scientist-guide-to-income-diversification/)**。**
# 数据科学家的数据架构指南
> 原文:<https://towardsdatascience.com/a-data-scientists-guide-to-data-architecture-bac00b0913f?source=collection_archive---------23----------------------->
## 构建强大的数据流程需要了解的内容
# 第 1 部分—基于一家主要保险公司的案例研究
> 你应该总是准备你自己的数据。
这句话来自人工智能领域的一位高管,几年前我问他对数据的看法。
他不是唯一有这种想法的人。在我的第一份工作中,部门主管不信任另一个团队来构建数据管道,最终自己编写了很大一部分 ETL 代码,并让数据团队直接向他汇报。
为什么这些高管如此重视数据?
因为如果没有很好地掌握数据,你就不会(也不应该)对你从数据中得出的见解和建议有太多信心。
对于从原始形式一直到准备好进行分析的数据,它经历了许多过程。一名优秀的数据科学家必须坚持不懈地质疑流程的每一步,并提出如下问题:
* 是否收集了正确的数据?
* 数据质量怎么样?
* 端到端的数据流程是怎样的?
本文的目的是使用真实世界的例子来浏览一些与数据架构相关的主题,这样您就有了一些基本的背景知识,并且知道应该向您的数据团队提出什么问题。

照片由 [JJ 英](https://unsplash.com/@jjying?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)在 [Unsplash](https://unsplash.com/s/photos/pipeline?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
# 生产与暂存
如前所述,我的职业生涯始于为一家大型保险公司工作,在一个所有数据处理都由我们自己完成的团队中。
每个月,我们都会从生产数据库中取出一长串表的副本,并将其放在我们的 SQL server 上,我们称之为临时数据库。
> **生产数据库**:各部门用于实时管理保单和理赔的交易数据库。
>
> **暂存数据库**:这是用于各种分析工作的生产数据库的快照。通常情况下,快照每月拍摄一次,但有时会根据临时请求更频繁地拍摄。
临时数据库的目的是为了不干扰正常的业务运营。
这种情况不应该发生,但由于数据连接设置问题,确实发生过一次。我们每 5 分钟就接到 IT 部门的电话,因为每个人都在抱怨系统冻结了…
对于分析团队来说,暂存环境是安全的。此外,只要对临时数据库运行代码,就一定会得到相同的结果。
# 规范化与非规范化表
一旦所有的表都被复制到临时数据库中,我们就执行一系列的数据处理步骤,将这些表转换成一些非规范化的表。
生产系统中的原始表称为规范化表,这是关系数据库背后的核心概念。每个表包含不同事物的数据,可以通过主键和外键链接在一起。

一个关系数据库的例子。omnisi.com[礼貌](https://www.omnisci.com/technical-glossary/relational-database)
出于分析的目的,在获得有用的东西之前,需要大量的表连接。
例如,假设您想要预测在给定建筑物特征的情况下获得建筑物保险索赔的概率。理想情况下,你需要一个平的桌子
* 目标是一个“是/否”标志,表示是否有索赔
* 这些特征/预测因素包括保险金额、建筑年龄、郊区等。
要创建平面表,您需要将索赔表(告诉您是否有索赔)、保险单表(包含保险单信息)和风险表(包含建筑物信息)连接在一起。
这个过程叫做**反规格化**。结果是一个**反规格化的**或**平面表**,其中的数据被很好地组织起来并准备好进行分析。

雷蒙德·拉斯姆森在 [Unsplash](https://unsplash.com/s/photos/organised?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上拍摄的照片
# 反规范化过程的陷阱
你可能认为这没什么大不了的。我们只需要执行一些连接就可以了,不是吗?什么会出错?
很多事情都会出错。您可能有重复的记录。您可能会无意中获得或丢失记录。
这是我开始第一份工作时被告知要做的,我相信我今天仍然受益于这些好习惯。
* 在每次连接之前,检查 by 变量的唯一性
* 我们在做什么样的加入?我们在做左连接、右连接、内连接还是外/笛卡尔连接?
* 我们从多少记录开始,每一步我们获得/失去了多少记录?
如果我们跳过这些步骤,我们可能会浪费更多的时间。这是我在许多不同的项目中反复学到的一课。

劳尔·纳杰拉在 [Unsplash](https://unsplash.com/s/photos/danger?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上的照片
# 交付核心数据集
经过大量努力,我们最终得到了满足整个团队需求的几个核心表,包括:
* 策略标题:每个策略一行,显示关于该策略的最新信息
* 风险标题:每个风险占一行,显示关于该风险的最新信息(如建筑物或汽车)。每份保单下可能有多种风险。
* 索赔标题每份保单一行,显示保单的最新信息
这些都是平面表,每月生产一次,放在一个公共服务器上。无论谁需要做任何分析,只要复制这些平面表,就知道数据是可信的。
# 抽取、转换、加载至目的端(extract-transform-load 的缩写)
ETL 代表 **E** 提取, **T** 转换, **L** oad。这听起来可能有点不可思议,但是你已经看到了这个过程。“提取”是指我们将数据从生产数据库复制到临时数据库。“加载”是指我们交付最终核心数据集的时间。“转换”是介于两者之间的所有工作。
# 数据完整性检查
在整个过程中,我们每一步都进行了可靠的数据检查:
* 当将数据从生产数据库复制到临时数据库时,我们会对总记录数和金额进行调节。
* 在转换的每个阶段,我们跟踪有多少数据流入不同的桶(我们保留的和我们丢弃的,如果有的话)。
* 我们根据财务部门提供的总账核对核心数据集中的保费、索赔支付金额和案例估计。必须调查大的移动。
* 我们将本月的值与上月的值进行比较,以发现任何重大变化。
* 我们使用仪表板来检测任何异常的分布变化。
当时,大部分数据完整性检查,以及最初的 ETL 过程都是用 SAS 程序编写的。通常,添加这些检查后,SAS 程序的大小会增加 3 倍。
的确,检查比做更费力气!
这值得吗?绝对的。
团队中的每个人都可以拿起数据集,并立即自信地使用它,因为知道它已经被检查过了。

Joshua Hoehne 在 [Unsplash](https://unsplash.com/s/photos/confidence?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上拍摄的照片
# 了解数据是如何创建的
除了强大的数据检查之外,我们还花了很多时间学习数据最初是如何生成的。
这是通过每天与输入数据的人坐在一起完成的。在我们的例子中,销售部门负责保单数据,理赔部门负责理赔数据。
我们坐在一线员工旁边,听他们回答客户的问题,将数据输入系统。我们尽力去理解他们是如何工作的,并积累了大量的领域专业知识。查看 [**这篇文章**](/domain-expertise-why-is-it-important-for-data-scientists-2d6a406d544d) 是我写的关于建立领域专业知识重要性的文章。
# 数据质量反馈回路
虽然上述过程可能有助于检测数据质量问题,但它并不能解决这些问题。这就是为什么需要一个反馈回路。
每个月,我们都会发布一组数据质量报告,并与管理团队分享。我们寻找的一些东西是
* 缺失或可疑的地址
* 出生日期
数据质量绩效与员工的 KPI 相关联,并构成驱动其薪酬的指标的一部分。这为每个人关心数据质量提供了强大的激励。
没有公司高级管理层的支持,这是不可能的。我认为,数据驱动的决策文化永远无法自下而上驱动。它需要自上而下。
# 第二部分——街区的新成员
到目前为止,我已经解释了传统的方法。我们当时用的是 SAS。人们没有使用数据工程师或数据科学家这个词。如今,很多事情都变了,但这些概念仍然适用。
接下来,我将讨论几个近年来变得越来越重要的话题。
# 内部与外部数据
从 IT 系统中提取的数据称为内部数据,因为它是内部生成的。
外部数据非常强大,可以极大地丰富和补充内部数据。外部数据的类型因上下文而异。
对于建筑保险,以下是一些可以使用的外部数据示例:
* 显示每个地区人口统计信息的普查数据
* 显示犯罪率的警方数据
* 建筑信息
* 卫星图像和高分辨率航空地图
* 国家洪水地图
* 气象资料
就汽车保险而言,以下是一些可以使用的额外外部数据示例:
* 车辆信息
* 驾驶行为/远程信息处理数据
# 结构化与非结构化数据
上面讨论的大多数数据都是结构化数据。非结构化数据的示例包括:
* 索赔描述——使用自然语言处理,我们可以得出客户情绪等特征
* 卫星图像——通过图像识别,我们可以推断出一些特征,比如游泳池的存在
如您所见,非结构化数据通常需要一些额外的处理才能对我们的任务有用,例如保险风险建模。
# 实时分析
到目前为止,我只讨论了批处理。ETL 过程至少需要 2-3 天。再加上几天的分析时间,至少在数据可用一周后,你才会有任何产出。
实时分析则不同。数据一进来,就被处理和分析。
你能想象你买一件商品的那一刻,亚马逊对你说:
> “尊敬的客户,感谢您的购买。请等一周,我们会推荐一些您感兴趣的产品。”
这从来没有发生过。他们会立即提供推荐。这使得他们从 Amazon.com 的推荐中获得 35%的收入。
实时分析通常属于数据工程师的领域。以新冠肺炎为例,这些是我创建的基于批处理的静态仪表板结果。更新结果是一件痛苦的事。当我发表这些文章时,这些数字已经过时了。
[*冠状病毒(新冠肺炎)疫情状态更新*](https://medium.com/@zemingyu/status-update-of-the-coronavirus-covid-19-outbreak-31da9389b04a)*—3 月 17 日发布*
[*冠状病毒(新冠肺炎)疫情状态更新*](https://medium.com/@zemingyu/state-of-the-coronavirus-outbreak-in-10-charts-and-key-findings-721f62c08a9e)*—2 月 29 日发布*
[*冠状病毒爆发—大数据五问*](/coronavirus-outbreak-5-questions-to-ask-big-data-3550794d2fe9)*—2 月 1 日发表*
将上述内容与[互动仪表盘](https://da-team-sg.shinyapps.io/covid-19/)进行比较,该仪表盘显示了自 1 月下旬以来新冠肺炎病毒在全球尤其是新加坡的传播情况。当新数据进来时,整个过程自动发生。

慕尼黑再保险 SG 分析团队制作的交互式仪表盘
真实世界的分析会在最需要的时候提供结果——谁会关心一周前的新冠肺炎数据呢?
让我们把同样的逻辑应用到保险领域。为什么保险公司的首席执行官要关心 3 个月前的销售额或损失率?然而,今天大多数保险公司仍然使用月度或季度报告。
除了实时欺诈分析等一些例外情况,保险业在采用这些新技术方面往往较为缓慢。随着像 R-Shiny 和 Dash 这样的工具使部署实时分析变得更加容易和经济实惠,我预计它在不久的将来会获得动力。
# 结论
在数据科学世界里,有很多性感的话题——人工智能、深度学习、大数据……
数据架构不是这些性感的话题之一。公司高管永远不会通过说“我们已经建立了世界级的数据完整性检查”来吸引任何媒体的注意。这是艰苦的工作。做好这件事需要很大的自律。然而,如果你真的成功了,它可能会比那些性感的话题更有价值。
作为一名数据科学家,花一些时间学习这些概念是值得的,这样您就可以与您的数据团队有效地沟通,并确保您拥有一个强大的数据流程,为您的所有分析工作奠定坚实的基础。
# 黑客啤酒节数据科学家指南
> 原文:<https://towardsdatascience.com/a-data-scientists-guide-to-hacktoberfest-8135b8bf2c01?source=collection_archive---------67----------------------->
## 如何对开源做出有意义的贡献

Justin Jairam 摄自 [@jusspreme](https://www.instagram.com/jusspreme/?hl=en) (经允许)
# 什么是 Hacktoberfest
开源项目是数据行业的支柱,没有它们,熊猫、Numpy Sci-kit Learn 和整个大数据 Apache 堆栈等项目就不会存在。Hacktoberfest 是一个为期一个月的活动,开发者可以在 Github 上贡献开源项目,并获得免费赠品。要有资格获得免费赠品,您必须提交四个成功的项目拉请求,这些项目都选择了 Hacktoberfest。为了尝试并轻松获得免费赠品,一些贡献者提交了无意义的贡献,导致项目维护者不高兴。

无意义的贡献示例
在本帖中,我们将讨论如何回馈社区,为开源项目做出有意义的贡献。
# 我是如何进入开源领域的
我第一次接触开源是在我参与两个项目的时候,[解释](https://github.com/interpretml/interpret)和[熊猫-总结](https://github.com/mouradmourafiq/pandas-summary)。在这两种情况下,项目的使用并没有完全覆盖我的用例,尽管它们非常小。
使用 interpret,我试图使用库来解释/解释 Sklearn 分类器。潜在的问题是`.predict`方法返回一个整数(0,1,等等。)用于分类器。当这些整数值用于计算 Morris 敏感度时,会抛出一个错误,指出数据必须是一个`float`。在这种情况下,[修复很简单](https://github.com/interpretml/interpret/pull/64)——将 Sklearn 分类器返回的整数转换为浮点数!在修复之前,任何试图解释 Sklearn 分类器的人都会得到一个错误,这个简单的贡献允许所有用户解释 Sklearn 分类模型。
对于 pandas-summary,我使用这个库来自动化列数据的描述和统计分析。唯一的问题是,每次我使用这个库时,总会绘制一个直方图,这很讨厌。作为对生活质量的修正,我[添加了一个简单的标志](https://github.com/mouradmourafiq/pandas-summary/pull/20),用户可以指定他们是否想要绘制直方图。
我的前两个贡献没什么特别的,也很简单,但是从这两个贡献中,我学到了如何向远程项目发出拉请求、遵循贡献指南以及通过 Github、Slack 等与项目维护者互动和交流的基本知识。
从那以后,我成为了 [pandas-bokeh](https://github.com/PatrikHlobil/Pandas-Bokeh) 库的主要贡献者,为[interact](https://github.com/nteract/nteract)贡献了错误修复和 UI 改进,并为 [Prefect](https://github.com/PrefectHQ/prefect) 添加了主要的功能集成。
# 技巧
## 了解如何提出拉取请求
拉请求是将您的代码贡献给项目的一种方法。首先,找到一个你想参与的项目,点击项目页面右上角的`fork`按钮,开始这个项目。这将在您的存储库下创建一个当前状态的项目副本。

一旦您分叉了项目,导航到 Github 中您的项目下的存储库。在项目名称下应该显示`forked from ...`。
将分叉的项目克隆到您的本地计算机上。
为你的变更或 bug 修复创建新的分支:`git checkout -b your_branch_name`。
做出你的改变,按照项目的贡献指南提交它们。
将您的更改推送到分叉的项目存储库:`git push -u origin your_branch_name`。
导航到分叉存储库项目页面。您将看到创建拉取请求的提示。如果您没有导航到 pull requests 选项卡并从那里通过选择`New Pull Request`创建一个。

填写“拉”请求模板(如果有),或者填写相关指南中概述的模板。一旦完成,你的拉动请求就可以开始了,等待反馈!
## 从你经常使用的图书馆开始,无论大小
第一个开源贡献的第一步是选择一个你想贡献的项目。我经历过的最好的方法是为你经常使用或正在积极使用的项目做贡献。如果你已经广泛地使用了一个项目,你可能会遇到一些会提高项目质量的 bug 或增强。这就是我如何开始我的开源之旅的,通过尝试改进我日常使用的项目。
## 看看现有的 Github 问题
如果你正在寻找一个问题或者为一个项目做贡献的方法,一个好的起点是 Github 的内置`Issues`标签。这是用户和项目维护人员可以记录错误和特性增强的地方。项目维护人员将仔细检查这些问题并标记它们,收集更多信息,添加元数据等。他们将添加的标签之一是“好的第一个问题”标签,以通知潜在的贡献者,这个问题对于第一次贡献者或项目的新贡献者是好的。

这些问题推荐给那些对开放源码或项目本身不熟悉的贡献者,以帮助他们开始并做出贡献。如果您找不到自己要修复的 bug 或要添加的增强功能,请利用这些工具。
## 阅读投稿指南
没有什么比投入所有这些寻找项目、隔离 bug 或开发新功能的工作更糟糕的了,因为你没有遵循编码、格式化或提交消息标准,它被拒绝或甚至没有被关注。好消息是所有这些都是可用的,通常在项目自述文件的贡献部分或项目的贡献指南部分。当您创建一个拉请求时,项目通常会运行自动格式检查,并且在这些基本检查通过之前,您的拉请求通常不会被查看。
如果你没有看到贡献部分或者一个项目没有贡献指南,不要想做什么就做什么。1)尽可能地遵循项目中的编码和文档风格。2)遵循编码和文档最佳实践。
## 每一份贡献都很重要
开源的每一项贡献都很重要,无论大小。无论是从可用性的角度还是从阅读文档的角度来看,如果你正在经历一个项目的 bug 或抱怨,其他人也会经历。文档是开源软件的重要组成部分,因为每个项目都需要它。当你开始了解一个项目是关于什么的时候,这通常是开始为一个项目做贡献的好地方。它提供了设计决策和项目考虑的背景信息,这反过来将帮助您理解代码。
文档是用户查找信息的第一个地方,一个项目的文档越完整,它的用户群就越多。开发人员喜欢文档化的项目,当一个项目没有文档,或者文档很差时,开发人员在将它添加到他们的工作流程之前会三思。添加文档或修复哪怕是最小的 bug 都可能影响成百上千每天使用该项目的用户,许多人会为此感谢你。
# 接下来会发生什么
你的贡献很少会马上被合并。几天之内,项目团队会有人对他们的反馈进行评论,或者通知你他们正在审查你的拉动式需求。处理评论,提出问题,澄清你不明白的地方,提出修改建议,如果有的话,你的修改很快就会被合并!
如果你在一周内没有收到任何关于你的拉请求的反馈,给项目维护者发信息,礼貌地询问他们状态如何。在较大的项目中,经常有大量的拉请求,他们可能已经忘记了拉请求,或者还没有抽出时间来检查它。
如果此时你还没有收到回复,这并不经常发生(在我身上从来没有发生过),从这个项目中吸取技能和学习点,继续下一个项目。一旦你提出了拉取请求,并通知了项目维护人员,剩下的就不在你的掌控之中了。这是开源唯一真正令人遗憾的地方,也是你不应该放在心上的地方。
# 利益
## 成为更好的工程师或科学家
无论你是数据工程师、ML 工程师还是数据科学家,贡献开源都有助于你在自己的领域变得更好、进步。从了解项目是如何构建和组织的,到深入了解关键库,导航大型代码库,编写生产级代码,甚至是学习解决问题的新方法。所有这些技能将直接转化为你的职业或你的下一个项目。
## 结识新的工程师、开发人员和科学家
为开源做贡献的最大好处是有机会与那些创造了一个被全世界成千上万人使用的工具的人一起工作和互动。你可以直接看到他们是如何创造一个解决方案来解决一个普遍问题的。此外,你们最终可能会联系起来,互相交换想法,并在未来的项目上合作。就我个人而言,我已经和我参与过的项目的维护人员取得了联系,并在 Twitter 和 LinkedIn 上与他们保持联系。
# 结论
今天,你可能不能贡献一个新的特性,但是在项目周围,阅读代码,阅读文档,所有这些都会给你对项目的洞察力。从那里,对文档的一个小贡献,可能会导致一个被记录的 bug 修复,这导致对项目的更高理解,然后导致你的第一个特性。
这个故事的寓意是,尽你所能地做出贡献,最终你会达到开发新功能的目标,开始你自己的操作系统项目,甚至成为一个项目的关键贡献者。
# 反馈
我鼓励任何人对我的帖子提出反馈。你可以在推特上给我发信息,或者在 sidhuashton@gmail.com 给我发电子邮件。
# Python 模块和包的数据科学家指南
> 原文:<https://towardsdatascience.com/a-data-scientists-guide-to-python-modules-and-packages-9193a861c26b?source=collection_archive---------14----------------------->

杰西·拉米雷斯在 Unsplash[拍摄的照片](https://unsplash.com/s/photos/package?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
## 如何创建、导入和使用您自己的 python 包
数据科学代码通常是非常线性的。从源中提取一些数据,应用一系列转换,然后执行一些分析、计算或训练模型。然而,为了可读性、效率和可重复性,模块化和打包代码对于重用和协作是有用的。
当我第一次开始学习数据科学编程时,我发现很难找到创建模块和包的简单解释和教程,特别是对于数据科学项目。在这篇文章中,我将给出一个非常简单的教程,介绍如何为数据科学和机器学习项目创建和使用自己的包和模块。
在整篇文章中,我将使用可以从 [UCI 机器学习库](https://archive.ics.uci.edu/ml/datasets/Adult)下载的成人数据集。这是一个通常用于建立分类机器学习模型的数据集,其目标是预测给定的成年人每年是否会赚超过 5 万美元。
## 模块的数据科学用例
python 模块只是一组 python 操作,通常是函数,放在一个带有`.py`扩展名的文件中。然后,这个文件可以导入到 Jupyter 笔记本、IPython shell 或其他模块中,以便在您的项目中使用。
让我们看一个例子。
在下面的代码中,我已经阅读了 CSV 文件,我将使用熊猫。
import pandas as pddata = pd.read_csv('adults_data.csv')
data.head()

该数据集包含大量分类特征。如果我们打算用它来训练一个机器学习模型,我们首先需要进行一些预处理。
分析完这些数据后,我决定在训练模型之前采取以下步骤对数据进行预处理。
* 一次性编码下列栏目:工作类,婚姻状况,关系,种族和性别。
* 取最常出现的值,将剩余的值分组为“其他”,并对结果特征进行一次性编码。这将需要为以下各列执行,因为它们具有大量的唯一值:教育、职业、本国。
* 缩放剩余的数值。
我们需要编写来执行这些任务的代码将会非常大。此外,这些都是我们可能希望多次执行的任务。为了使我们的代码更具可读性,并且能够轻松地重用它,我们可以将一系列函数编写到一个单独的文件中,该文件可以导入到我们的笔记本中使用——一个模块。
## 编写模块
要创建一个模块,你需要首先创建一个新的空白文本文件,并用扩展名`.py`保存。你可以使用一个普通的文本编辑器,但是很多人使用 IDE(集成开发环境)。IDE 为编写代码提供了许多额外的功能,包括编译代码、调试和与 Github 集成的工具。有许多不同类型的 IDE 可供使用,值得尝试几种,以找到最适合您的一种。我个人更喜欢 [PyCharm](https://www.jetbrains.com/pycharm/) ,所以我将在示例中使用它。
为了开始编写 python 模块,我将创建一个新的 python 文件。

我将它命名为`preprocessing.py`。

让我们在这个文件中编写我们的第一个预处理函数,并在 Jupyter 笔记本中测试导入和使用它。
我在`preprocessing.py`文件的顶部写了下面的代码。给代码添加注释是一个很好的做法,这样可以使代码更具可读性。我在下面的代码中添加了一些注释。
def one_hot_encoder(df, column_list):
"""Takes in a dataframe and a list of columns
for pre-processing via one hot encoding""" df_to_encode = df[column_list]
df = pd.get_dummies(df_to_encode)
return df
要将这个模块导入到 Jupyter 笔记本中,我们只需编写以下代码。
import preprocessing as pr
IPython 有一个方便的神奇扩展,叫做`autoreload`。如果您在导入之前添加了以下代码,那么如果您对模块文件进行了任何更改,这些更改将自动反映在笔记本中。
%load_ext autoreload
%autoreload 2import preprocessing as pr
让我们测试使用它来预处理一些数据。
cols = ['workclass', 'marital-status', 'relationship', 'race', 'gender']one_hot_df = pr.one_hot_encoder(data, cols)

现在我们将剩余的预处理函数添加到我们的`preprocessing.py`文件中。
def one_hot_encoder(df, column_list):
"""Takes in a dataframe and a list of columns
for pre-processing via one hot encoding returns
a dataframe of one hot encoded values""" df_to_encode = df[column_list]
df = pd.get_dummies(df_to_encode)
return df
def reduce_uniques(df, column_threshold_dict):
"""Takes in a dataframe and a dictionary consisting
of column name : value count threshold returns the original
dataframe""" for key, value in column_threshold_dict.items():
counts = df[key].value_counts()
others = set(counts[counts < value].index)
df[key] = df[key].replace(list(others), 'Others')
return df
def scale_data(df, column_list):
"""Takes in a dataframe and a list of column names to transform
returns a dataframe of scaled values""" df_to_scale = df[column_list]
x = df_to_scale.values
min_max_scaler = preprocessing.MinMaxScaler()
x_scaled = min_max_scaler.fit_transform(x)
df_to_scale = pd.DataFrame(x_scaled, columns=df_to_scale.columns)
return df_to_scale
如果我们回到笔记本电脑,我们可以使用所有这些功能来转换数据。
import pandas as pd
from sklearn import preprocessing%load_ext autoreload
%autoreload 2import preprocessing as prone_hot_list = ['workclass', 'marital-status', 'relationship', 'race', 'gender']
reduce_uniques_dict = {'education' : 1000,'occupation' : 3000, 'native-country' : 100}
scale_data_list = data.select_dtypes(include=['int64', 'float64']).columnsone_hot_enc_df = pr.one_hot_encoder(data, one_hot_list)
reduce_uniques_df = pr.reduce_uniques(data, reduce_uniques_dict)
reduce_uniques_df = pr.one_hot_encoder(data, reduce_uniques_dict.keys())
scale_data_df = pr.scale_data(data, scale_data_list)final_data = pd.concat([one_hot_enc_df, reduce_uniques_df, scale_data_df], axis=1)final_data.dtypes
我们现在有了一个完全数值化的数据集,它适合于训练一个机器学习模型。

已转换列的快照
## 包装
在进行机器学习项目时,创建几个相关的模块并将它们打包以便一起安装和使用通常是理想的或者有时是必要的。
举个例子,在我的工作中,我目前正在使用一个名为 [AI 平台](https://cloud.google.com/ai-platform/)的机器学习模型的 Google Cloud 部署解决方案。该工具要求您将机器学习模型中的预处理、训练和预测步骤打包上传并安装在平台上,以部署最终模型。
python 包是包含模块、文件和子目录的目录。该目录需要包含一个名为`__init__.py`的文件。该文件表明它所在的目录应该被视为一个包,并指定应该导入的模块和函数。
我们将为预处理管道中的所有步骤创建一个包。__init__ 的内容。py 文件如下。
from .preprocessing import one_hot_encoder
from .preprocessing import reduce_uniques
from .preprocessing import scale_data
from .makedata import preprocess_data
同一个包中的模块可以导入到另一个模块中使用。我们将向我们的目录添加另一个名为 makedata.py 的模块,该模块使用 preprocessing.py 模块来执行数据转换,然后将最终数据集导出为 CSV 文件供以后使用。
import preprocessing as pr
import pandas as pd
def preprocess_data(df, one_hot_list, reduce_uniques_dict, scale_data_list, output_filename):
one_hot_enc_df = pr.one_hot_encoder(data, one_hot_list)
reduce_uniques_df = pr.reduce_uniques(data, reduce_uniques_dict)
reduce_uniques_df = pr.one_hot_encoder(data, reduce_uniques_dict.keys())
scale_data_df = pr.scale_data(data, scale_data_list)
final_data = pd.concat([one_hot_enc_df, reduce_uniques_df, scale_data_df], axis=1)
final_data.to_csv(output_filename)
新目录现在看起来像这样。

现在我们可以回到 Jupyter 笔记本,使用这个包来执行所有的预处理。我们的代码现在非常简单明了。
import pandas as pd%load_ext autoreload
%autoreload 2
import preprocessing as prdata = pd.read_csv('adults_data.csv')one_hot_list = ['workclass', 'marital-status', 'relationship', 'race', 'gender']
reduce_uniques_dict = {'education' : 1000,'occupation' : 3000, 'native-country' : 100}
scale_data_list = data.select_dtypes(include=['int64', 'float64']).columnspr.preprocess_data(data, one_hot_list, reduce_uniques_dict,scale_data_list, 'final_data.csv')
在我们当前的工作目录中,现在将有一个名为`final_data.csv`的新 CSV 文件,它包含预处理过的数据集。让我们回过头来检查几行,以确保我们的包按预期执行。
data_ = pd.read_csv('final_data.csv')
data.head()

在这篇文章中,我已经说明了在数据科学和机器学习项目中使用模块和包是如何提高代码的可读性和可重复性的。在我寻找这些过程的简单解释的过程中,我发现这个[博客帖子](https://timothybramlett.com/How_to_create_a_Python_Package_with___init__py.html)非常有用,并且很好地浏览了 [python 如你所愿](https://www.pythonlikeyoumeanit.com/Module5_OddsAndEnds/Modules_and_Packages.html)项目。
感谢阅读!
# 数据科学家的侧推指南💰
> 原文:<https://towardsdatascience.com/a-data-scientists-guide-to-the-side-hustle-3dd93a554eb8?source=collection_archive---------2----------------------->
## 将你的发展技能货币化,开始赚取被动收入

信用: [@garrhetsampson](https://unsplash.com/@garrhetsampson) 通过 [Unsplash](https://unsplash.com/photos/CmF_5GYc6c0)
***来自《走向数据科学》编辑的提示:*** *虽然我们允许独立作者根据我们的* [*规则和指导方针*](/questions-96667b06af5) *发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的* [*读者术语*](/readers-terms-b5d780a700a4) *。*
啊,[侧扑](https://www.entrepreneur.com/article/293954)。有一个额外的收入流,一个有利可图的激情项目,或一个次要的奖金演出,是如此诱人。我们中的许多人至少都有一些兼职赚外快的方法,即使只是简单地投资零花钱。整个行业都在迎合旁门左道:优步/ Lyft 会在下班时间付钱给赞助人;AirBnB 提供了一个完整的用户网络,有兴趣租用你的房子;Instagram 奖励向粉丝兜售商品和服务的有影响力的人。对我来说,开始是为了攒钱上大学(在 Craigslist 上翻运动器材🤸♂)已经发展成为通过**教学、写作、构建软件以及更多**创造额外收入来传播数据科学。
那么,*你如何*利用你的数据科学技能赚点外快呢?我们将探索一些我最喜欢的方法来赚取一些🍞并培养数据技能。
来源: [VH1](https://vh1.tumblr.com/post/129219230256/me-on-payday) 通过[吉菲](https://giphy.com/gifs/vh1-all-new-twinning-tonight-at-10-ji-and-le-fLNQD3RQpAEYE)
也许你想创造额外的收入来支付那些讨厌的订阅服务。或者也许你计划乘飞机去巴厘岛,拥抱一种更有田园风味的远程工作。不管是什么原因,我建议设定一个切实的目标,并列出你需要达到的步骤或微观目标。
> 我的目标很简单。我想每周多花几个小时来提高我的数据科学知识,并为此获得报酬。我把目标定为每周 50 美元,并着手记录我在收入和数据科学技能方面的里程碑。
## 我将从以下几个方面对我最喜欢的赚钱方法进行排名
1. 努力:一般来说,我每周需要投入多少时间?
2. **价值**:努力正常化,多少是可行的支出?
3. **难度**:我需要多少领域和/或技术专长?
4. 一致性:我多久能得到一次报酬?
# 为介质书写
> “通过算法和编辑管理的结合,媒体上的帖子基于兴趣和参与度得到传播。有些书拥有成千上万的读者——并不是因为它们是名人写的。媒介不是关于你是谁或你认识谁,而是关于你必须说什么。”
>
> —中等
作为一名读者,你对 Medium 和这个平台上令人振奋的观点非常熟悉。提炼你的品牌并把内容推向世界似乎令人生畏,但它可以赋予*和*利润。经过几个月的随意观察(许多令人鼓舞的👏),我终于打开了水龙头,开始发布内容。拿着一台旧的 MacBook 和对散文的初步理解,我开始在我最喜欢的媒体出版物上发表文章,并赚到足够支付每年 50 美元的订阅费。
如果你不熟悉出版商如何赚钱,请查看概述媒体合作伙伴计划的指南。基本上,你可以发布有资格获得与浏览量、点击量、阅读时间和转化率相称的收入的内容(非会员注册为 Medium)。作为媒介生态系统中的一个“新鲜”视角,我从像苏珊·李和凯西·科济尔科夫这样的知名作家身上寻找灵感。
Effort: 3
Value: 1
Difficulty: 2
Consistency: 2
Overall Score: 2
你可以在写作技巧、研究、网络等方面投入无限的资源。对获得正投资回报的信心不足。虽然大多数作家都很难获得足够的持续曝光率来赚钱(2019 年 1 月只有 8.1%的作家赚了[超过 100 美元),但这也是推销你的才华和练习写作的好方法。在媒体上取得成功需要强大的声音、吸引人的原创内容、高效的分销渠道和一点运气。像其他任何事情一样,这是一门需要大量时间和细致入微的改进来找到你的最佳状态的学科。](https://medium.com/blogging-guide/how-much-money-can-you-make-writing-for-medium-a3cf0c9c7533)
我花了 30 天实现了总收入 50 美元的目标,只用了 10 天就把我的内容发布到了《走向数据科学》上。现在,我的重点是每周写一篇文章,迭代增长我的粉丝;这当然是一项正在进行的工作!
来源:[@世界之星](https://www.worldstarhiphop.com/videos/video.php?v=wshhqL2nd9UaksR76X35)经由[吉菲](https://giphy.com/gifs/worldstar-dj-khaled-worldstarhiphop-3o8dFwgfYgpff1u5H2)
# 发布和货币化 API
> “API 是新生态系统的窗口。”
>
> **— Bala Iyer 在** [**哈佛商业评论**](https://hbr.org/2015/01/the-strategic-value-of-apis)
开发人员使用 API 在他们自己的程序中利用外部软件。通过促进互连,公司和技术人员可以共享他们的工作,并让越来越多的数据专业人员能够构建各种规模的惊人解决方案。尽管开源软件鼓励“通过教育、合作和基础设施实现社会自由”,但 API 的收入为世界上一些最受欢迎和最赚钱的科技公司提供了燃料。据《哈佛商业评论》(Harvard Business Review)报道,“Salesforce.com通过 API 产生 50%的收入,Expedia.com[产生 90%,易贝](http://www.slideshare.net/faberNovel/why-shouldicareaboutap-is4/45)产生 60%”。哇哦。
> 许多最流行的 API 是由公司而不是个人开发的。但是随着有才华的数据专业人员数量的增加,对使用开源技术构建的廉价、复杂替代品的需求也会增加。
那么如何开始呢?一个 [API marketplace](https://rapidapi.com/blog/api-glossary/api-marketplace/) 允许开发者发布和货币化他们的工作,而不必管理定制的支付系统和复杂的基础设施。 [RapidAPI](https://rapidapi.com/) 是*我的*最爱,以“免费增值”和你能想到的每种 API 的付费订阅计划为特色。你可能不会马上获得被动收入,但是你已经展示了独特的才能和企业家精神。
Effort: 2
Value: 1
Difficulty: 4
Consistency: 1
Overall Score: 2
下面是如何将您有价值的工作部署到 API 的快速指南:
[](/earn-money-with-machine-learning-by-publishing-an-api-dc6694121ba5) [## 通过部署 API 利用机器学习赚钱
### 使用 FastAPI、uvicon/guni corn 和 Python 将您的作品发布到 RapidAPI 市场
towardsdatascience.com](/earn-money-with-machine-learning-by-publishing-an-api-dc6694121ba5)
用这种方法我还没有赚到一分钱;我选择写体验(^),而不是最大化我的 API 的价值。然而,**天空才是真正的极限:**对于自然语言处理(NLP)和文本分类、图像识别、高效的数据管道等,有很多很酷的途径。你可以快速出版并赚钱。
来源:[Yahoo entertainment](https://yahooentertainment.tumblr.com/post/115712365116)via[Giphy](https://giphy.com/gifs/mlb-opening-day-field-of-dreams-qVtmVS0eailqg)
RapidAPI 有几类定制的 API 解决方案,比如体育、旅游、数据、金融等等。一个快速的查询会告诉你哪个 API 在给定的类别中最受欢迎,从而知道付费解决方案的市场有多大。
你建了,他们就来了!
# 卡格尔。
显而易见的选择!Kaggle 是一个增强技能和探索数据集的好地方。作为谷歌的子公司,它是一个为数据科学家和机器学习工程师量身定制的在线社区,旨在合作提升该领域的技术水平。他们提供[竞赛](https://www.kaggle.com/competitions),让大胆的技术人员在 [**CA$H 奖**](https://www.youtube.com/watch?v=C9mfuifkZgc) 的争夺中测试他们的技能(是的,你没看错)。
无论你是数据新手还是成熟的独角兽,Kaggle 竞赛都将考验你的专业知识。话题的广度*和深度*,从[新冠肺炎预测](https://www.kaggle.com/c/covid19-global-forecasting-week-5)到[神经成像](https://www.kaggle.com/c/trends-assessment-prediction)以及介于两者之间的一切。这也是一个公司/组织众包人才的惊人平台;zillow(120 万美元💰),通用电气(25 万美元💰)和国土安全部(150 万美元💰)post [Excalibur](https://en.wikipedia.org/wiki/Excalibur) 级挑战获得巨额现金奖励🏆。更有可能的是,你只是远远地欣赏这些尖端的解决方案,而不是把熏肉带回家,但你不妨试试!
Effort: 3
Value: 2
Difficulty: 5
Consistency: 2
Overall Score: 3
很简单:Kaggle 比赛很有趣!无论你是否套现,你都将享受一个挑战性的机会来检验你的技能。就我个人而言,我只收到过伴随胜利而来的无形的奖励,比如“荣誉”和“知识”,但我有一些同行从 Kaggle 那里赚了很多钱。
竞赛也是扩展你的网络和深入数据科学未探索领域的好方法。 [LeetCode](https://leetcode.com/) 是通过参加有趣的挑战来扩展您的数据科学技能的另一个平台,重点是面试过程。不管具体结果如何,如果你选择参与,你肯定会成为一名更好的技术专家。
# 自由职业平台:Upwork、Toptal 和 Guru
就像飞蛾扑火一样,智能招聘平台将自由职业者(🦋)和经过审核的机会(🔥).你只需支付一定比例的费用,在公开市场上劫持数据角色,而不是管理自己的业务开发渠道。从全职机会到一次性培训,这些平台可以根据您的需求和市场需求进行扩展。
根据你的专业水平,自由职业可以不仅仅是一个兼职。我知道许多数据专业人士已经放弃了传统的朝九晚五,转而从事全职自由职业——你也可以!但是就本文的目的而言,我将把重点放在低维护时间承诺的有限机会上。
Effort: 3
Value: 4
Difficulty: 2
Consistency: 3
Overall Score: 3
我对这种方法的评级标准感觉特别主观。我专门使用了 [Upwork](https://www.upwork.com/ab/find-work/domestic) 和[to tal](https://www.toptal.com/),两者都拥有高效的入职流程和大量数据科学/开发人员角色。为演出投标需要一些时间来适应,找到合适的时薪比仅仅依靠几年的经验要多得多。也就是说,如果你很勤奋,并且接受一个平台扣除大约 20%的费用,那么赚钱是很容易的。
通过自由职业,我每个月能挣 100 美元,但是我对自己感兴趣的职位很挑剔。作为一名白天的顾问,我知道我的小时工资和高度重视的特定技能/技术:我把时间集中在寻找充斥着文本分析和/或 NLP 的机会上。
来源: [ESPN](https://www.espn.com/) 经[吉菲](https://giphy.com/gifs/espn-S85obJAx8r6GO7gIn3)
# 教一个班
学习数据科学和一般编程技能有无数种方法。幸运的是,在线学习有巨大的市场,因为它涉及到建立有价值的技能和令人印象深刻的工作组合。虽然许多电子学习倡导者建议建立和/或管理你自己的个性化课程,但我更感兴趣的是帮助管理别人审核过的课程。去年年底,我通过明尼苏达大学双城分校报名参加了一个著名的数据训练营。
Effort: 4
Value: 2
Difficulty: 3
Consistency: 5
Overall Score: 4
这门特殊的课程以 6 个月为增量,涵盖了你在任何数据科学手册中都能找到的大部分技术:Python / R 编程、数据库查询和管理、前端 web 开发、统计学、机器学习等等。因为我不必管理课程更新、新生入职或任何与课程建设相关的管理任务,所以我可以专注于教学艺术。我每周花将近 15 个小时的时间来支持学生学习课程材料,而报酬相对较低。尽管付出了努力,但时间承诺非常一致,我可以和各种学术/专业背景的学生一起工作。查看一些即将推出的课程,寻找灵感📚:
[](https://www.switchup.org/rankings/best-data-science-bootcamps) [## 2020 年最佳数据科学训练营
### By: SwitchUp SwitchUp 根据校友的评论,对全球 18 个最佳数据科学训练营进行了排名。这些…
www.switchup.org](https://www.switchup.org/rankings/best-data-science-bootcamps) [](https://www.coursereport.com/blog/best-data-science-bootcamps-the-complete-guide) [## 我们的最佳数据科学训练营终极指南
### 当你听到数据科学这个术语时,你会想到电子表格和庞大的数字吗?数据科学帮助我们了解所有…
www.coursereport.com](https://www.coursereport.com/blog/best-data-science-bootcamps-the-complete-guide)
与构建自己的课程相比,这种方法需要的前期投资明显较低,但会限制您的潜在收入上限;像我一样,你可能会收到一笔不多的两年期津贴。你要做的就是联系你的母校或者联系一个该领域的盟友(比如我!),并充实你对各种主题的知识。
如果您有兴趣了解更多关于结构、需求、物流和/或入职流程的信息,欢迎在下方留言或直接给我发消息😃。
# 辅导课程
如果你没有足够的带宽在结构化的环境中投入 6 个多月的时间来教学,或者对如此广泛的话题进行社交感到不舒服,那么**辅导**可能正合你的胃口。通过支持日益增长的在线学习需求,辅导服务高度个性化,利润越来越大。
来源:[威福莱吉](https://wifflegif.com/)通过[吉菲](https://giphy.com/gifs/teachers-kevin-hart-you-gon-learn-today-4nRiHFFTzmJZC)
许多私人公司提供辅导服务,以降低流失率,提高学生满意度。与其他昂贵的支持机制相比,导师提供了更高的价值。
Effort: 3
Value: 3
Difficulty: 2
Consistency: 5
Overall Score: 4.2
我设定我的时间,我想和多少学生一起工作,以及我想教的话题。我负责策划一个高效、舒适的学习体验,以换取每小时 30 美元的诱人报酬。它的低维护性、灵活性和盈利性足以成为我在数据科学生态系统中最喜欢的副业。
# …可能性是无限的!
有如此多的选择可以产生额外收入*和*一路学习:
* 出版您自己的数据科学教科书/课程
* 导致[堆栈溢出](https://stackoverflow.com/)
* 通过联盟营销创建内容
* [打造酷炫 app](https://blog.inkdrop.info/how-ive-attracted-the-first-500-paid-users-for-my-saas-that-costs-5-mo-7a5b94b8e820)
* 预测[域名](https://www.pickydomains.com/make-money)
* …这样的例子不胜枚举!
> 在写这篇文章的时候,我通过以上列举的方法每周可以赚到 350 美元。对于一个侧推来说还不错!我超过了最初设定的 50 美元/周的目标,并且一路走来,我学到了很多东西。最精彩的部分?这些方法是完全可重复的,并且已经成熟。你所需要的只是一点决心和学习的欲望。
来源:[通过](https://www.youtube.com/watch?v=JU9TouRnO84) [YouTube](https://www.youtube.com/) 的
我目前是一名教育工作者和家庭教师(兼职),同时尽可能多地写我在媒体上的经历。我经常在 Kaggle 上寻找挑战,试图每季度向市场发布一个 API,并不断地争取有趣的自由职业机会。这是我在有利可图的副业中找到的最佳组合*,它帮助我提高了我的网络和数据科学技能。根据您的专业水平、兴趣和可用性,您可以使用这些方法来启动和/或增加您自己的机会。*
感谢阅读!请在下面评论任何额外的想法或建设性的反馈。关注我( [Garrett Eichhorn](https://medium.com/u/dbec1257daf4?source=post_page-----3dd93a554eb8--------------------------------) )或在 [LinkedIn](https://www.linkedin.com/in/garretteichhorn/) 上与我联系。
# 数据科学家对 Dask 并行计算的介绍
> 原文:<https://towardsdatascience.com/a-data-scientists-intro-to-parallel-computing-with-dask-4c1b4a464579?source=collection_archive---------11----------------------->
## 利用 Dask 并行化您的 Python 代码
在这篇文章中,我们讨论了利用 python 中的 [*Dask*](https://docs.dask.org) *的基础知识,使用它来执行一些简单的并行化任务(*令人尴尬的并行*),了解一些最常见的可能用例(*数据管理、数据探索、机器学习*),然后触及一些更复杂的工作流,这些工作流可以通过将不同的 ML 库与 *Dask* 相结合来构建。在这篇文章中,我们将重点关注运行一个令人尴尬的与 Dask* 并行的任务。
**什么是并行计算?**
你可能听说过这个短语,但是除了所有实际的复杂算法之外,它真正的核心含义是:你执行你想做的工作,这样多个步骤同时发生,而不是总是等待前一个任务完成。难度随着你实际想要完成的事情的性质而增加。
彼此独立的操作/任务,即除了每个任务的开始和结束之外,不存在任何数据依赖性——通常最容易并行化,并被称为*令人尴尬的并行* ***、*** ,而在开始和结束之间涉及大量数据传输/通信的任务则难以并行化。
> 作为一名数据科学家/分析师,您并不总是有足够的时间或所需的技能来思考如何并行化您的任务,并从头开始用其他语言实施解决方案,例如,花费数周、甚至数月时间来发现最佳的分组方式并不是您所期望的!
**什么是 *Dask* ?**
> Dask:在 Python 中并行化计算任务的框架
`Dask`是一个旨在帮助促进:
* 超大型数据集的数据管理,以及
* 跨大量内核(具有多个工作人员的本地集群)或物理计算机(具有多个节点的集群)的计算分布
它提供的功能类似于 Apache Spark 的[](https://spark.apache.org)*,但是它被紧密地集成到了`numpy`和`pandas`中,对于那些库的用户来说,它比 Spark 更容易学习和使用。*
*并行化一项任务,如果你是一个从头开始构建框架的人,那么任何任务都是困难的。有 python 模块(例如*多重处理*)可以帮助你跳过这一部分,执行和管理(在某种程度上)不同的线程。但是,从用户的角度来看,即使这样也需要大量的努力和特殊的技能。在这种情况下,监控、日志记录等通常也是次要的。*
****Dask*** 去掉了所有复杂的*(虽然重要)*内部抽象,给你一个干净的 api,让你在 python 中并行化你现有的代码。取决于你如何编写你的代码——你可能甚至不需要修改你现有的函数来使它们与 ***Dask*** 一起工作!*
*让我们从使用下面的 ***Dask*** 和接下来的几篇文章开始。*
**
***获取 *Dask* :***
*我会推荐以下选择之一:*
* *为您的 python 环境安装 [Anaconda](https://www.anaconda.com/distribution) (我的首选,Dask 随基本设置一起安装。你也可以[创建一个新的环境](https://docs.conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html)来保持你的 *Dask* 环境在你学习、安排工作等的时候是独立的*
conda create --name dask python=3.7 anaconda dask
* *创建一个新的 [python 虚拟环境](https://docs.python-guide.org/dev/virtualenvs)并在其中安装 *Dask**
* *在您当前的环境中安装 *Dask**
# Anaconda environmentconda install dask# pip based installationpip install "dask[complete]"
***创建你的 *Dask* 客户端:***
import dask
from dask.distributed import Client, progresstry:
client.close()
client = Client(threads_per_worker=1,
n_workers=5,
memory_limit='2GB')
except:
client = Client(threads_per_worker=1,
n_workers=5,
memory_limit='2GB')client
*在这里,我们已经创建了一个**本地集群**,定义了要运行多少本地工作者以及要为每个工作者分配的资源。
这个客户端一次最多可以运行 5 个任务(*n _ workers*)*Dask*处理定义单个线程的所有细节,在一个任务完成时在不同线程之间进行协调,下一个任务开始时,从我们的环境向每个工作线程传输数据,等等*
**
## *您的第一个 Dask 示例:*
*任务:计算给定数据集中每个类别的平均值和标准偏差*
***步骤 01:创建一个样本模拟** 在我们的例子中,我模拟了一个包含 **k** 操作和 **g** 类别的数据集。该模拟的输出是每个模拟的平均值和标准偏差。*
*def simulate_dataset(i):
g = 10
k = 100000
categories = np.random.choice(a = np.arange(g), size= k)
values = [(j+1)*np.random.random(k//g) for j in range(g) ]
values = np.concatenate(values)
data = pd.DataFrame({'category':categories,
'values':values})
data_out = data.groupby('category').apply(lambda df: [
df.loc[:,'values'].mean(),
df.loc[:,'values'].std()
])return(data_out)*
***这个**函数可以是你想要的任何东西,任何复杂的分析/模拟任务——只要它是独立的。每次迭代都可以独立运行,不需要与其他线程进行任何通信,只需要在模拟开始时进行输入。*
***步骤 02:在 for 循环中运行 n 次模拟***
*%%timeitresults = {}for i in range(n):
results[i] = simulate_dataset(i)*
***步骤 03:用 *Dask* 运行 n 次**模拟*
%%timeitresults_interim = {}
for i in range(n):
results_interim[i] = delayed(simulate_dataset)(i)results_scheduled = delayed(list)(results_interim)
results = results_scheduled.compute()
# *比较:*
*在这个独立的例子中,我们看到了大约 3 倍的加速。当您增加计算/模拟的重量时,加速会更加明显(增加独特的**类别**或**总样本量**(在我们的例子中为 **)***
**
*For 循环 vs Dask*
*这种增长不是线性的,因为启动和管理不同的员工会产生管理费用。每个工人的计算量越大,这种开销的影响就越小。*
****Dask 仪表板上的进度可视化:****
**
*工人利用率*
**
*任务图*
**
*任务流*
# 数据科学家对冠状病毒爆发的看法
> 原文:<https://towardsdatascience.com/a-data-scientists-perspective-on-the-wuhan-coronavirus-4d1110446478?source=collection_archive---------4----------------------->
## 约翰·霍普斯金大学对冠状病毒数据集的 EDA。

[疾控中心](https://unsplash.com/@cdc?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 拍摄的照片
一种最初在中国武汉市报道的病毒,现在已经传播到世界上十几个国家,引发了前所未有的健康和经济危机。
世界卫生组织(世卫组织)宣布武汉冠状病毒*爆发为国际关注的突发公共卫生事件*。
在本文中,我们将简要了解当前的危机,然后深入研究 Kaggle 的“[小说电晕病毒 2019 数据集](https://www.kaggle.com/sudalairajkumar/novel-corona-virus-2019-dataset)”。我还创建了一个 [GitHub 知识库](https://github.com/kamahmad/EDA-Wuhan-Coronavirus-Dataset),供任何想要重新创建步骤并添加自己见解的人使用。
# 什么是冠状病毒?
据世卫组织报道,冠状病毒(CoV)是一个大的病毒家族,可导致从普通感冒到更严重疾病的疾病,如中东呼吸综合征(MERS-CoV)和严重急性呼吸综合征(SARS-CoV)。
[一种新型冠状病毒(nCoV)](https://www.who.int/emergencies/diseases/novel-coronavirus-2019) 是一种新的毒株,此前未在人类中发现。被确定为最近爆发的原因的病毒被称为 2019-nCoV 或武汉冠状病毒。
# **危机,截至今日**
根据《纽约时报》的最新报道,中国确诊感染人数上升至 37198 人,死亡人数上升至 811 人,超过了非典造成的死亡人数。
中国的 16 个城市,总人口超过 5000 万,处于封锁状态。全球各地的航空公司都取消了往返中国的航班。一些国家正在用特别航班疏散他们的公民,并进一步对他们进行严格的隔离。
更糟糕的是,中国股市暴跌,全球市场都感受到了影响。一些分析师预测,疫情对全球经济构成威胁,并有可能引发深远的地缘政治后果。
# 数据集简介
在 [Kaggle](https://www.kaggle.com/) 上发布的“[小说电晕病毒 2019 数据集](https://www.kaggle.com/sudalairajkumar/novel-corona-virus-2019-dataset),已被[约翰·霍普斯金大学](https://www.jhu.edu/)收藏。该小组从世卫组织、当地疾病预防控制中心和媒体等各种渠道收集了数据。他们还创建了一个实时仪表板来监控病毒的传播
**免责声明**:请注意,数据集没有更新,因此下面记录的观察结果可能不是当前场景的真实反映。
# 导入库和加载数据
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns#reading data from the csv file
data= pd.read_csv("/kaggle/input/novel-corona-virus-2019-dataset/2019_nCoV_data.csv")
# 了解数据集
让我们首先对数据集有一个基本的了解,并在必要时执行数据清理操作。
checking the number of rows and columns
data.shape
输出:(770,8)。数据集中有 770 个观察值和 8 列。
checking the top 5 rows
data.head()

列的名称是不言自明的。第一列' *Sno* '看起来像一个行号,并没有给分析增加任何值。第五列'*上次更新*'显示与'*日期*'列相同的值,除了一些后来更新数字的情况。让我们在继续之前删除这两列。
dropping the 1st and 5th column
data.drop("Sno", axis=1, inplace=True)
data.drop("Last Update", axis=1, inplace=True)#getting a summary of the columns
data.info()

除了'*省/州*'之外,所有列都没有空值。进一步的分析显示,英国、法国和印度等国家缺少省份名称。在这种情况下,我们不能假设或填充任何主列表中的缺失值。让我们继续看数字列。
data.describe()

`describe()`方法返回数据帧中数字列的一般统计数据。
从输出中直接得出的结论是,数据是累积报告的,即任何特定一天报告的病例数包括以前报告的病例。死亡人数的“最大”值是 479 人,这与几天前媒体报道(该数据公布时)一致。
checking for duplicate rows
duplicate_rows=data.duplicated(['Country','Province/State','Date'])
data[duplicate_rows]

`duplicated()`方法返回一个布尔序列,然后用作原始数据帧的掩码。输出显示没有两条记录具有相同的国家、州和日期。因此,我们可以得出结论,数据集中的所有观察值都是唯一的。
listing all the countries where the virus has spread to
country_list=list(data['Country'].unique())
print(country_list)
print(len(country_list))

数据显示,该病毒已经传播到亚洲、欧洲和美洲的 32 个国家。出于分析目的,我们可以合并“中国”和“Mainland China”的数据。
merging China and Mainland China
data.loc[data['Country']=='Mainland China','Country']='China'
在继续之前,让我们检查一下“*日期*栏中的日期。
print(list(data['Date'].unique()))
print(len(list(data['Date'].unique())))

看起来数据在每天不同的时间被更新。我们可以从时间戳中提取日期,并使用它们进行进一步的分析。这将有助于我们保持日期一致。
converting 'Date' column to datetime object
data['Date'] = pd.to_datetime(data['Date'])#extracting dates from timestamps
data['Date_date']=data['Date'].apply(lambda x:x.date())
让我们了解一下疫情对每个国家的影响。
getting the total number of confirmed cases for each countrydf_country=data.groupby(['Country']).max().reset_index(drop=None)
print(df_country[['Country','Confirmed','Deaths','Recovered']])

由于数据是累积的,我们需要将`max()` 函数与`groupby()` 一起使用,以便获得每个国家报告的最大病例数。如果我们使用`sum()`,我们会被重复计算。
该数据证实,中国是报告病例最多的国家,迄今为止几乎所有的 481 例死亡病例都发生在中国。从更积极的方面来看,中国也有 522 起复苏,其次是泰国,有 7 起。
preparing data for a time-series analysisdf_by_date=data.groupby(['Date_date']).sum().reset_index(drop=None)df_by_date['daily_cases']=df_by_date.Confirmed.diff()
df_by_date['daily_deaths']=df_by_date.Deaths.diff()
df_by_date['daily_recoveries']=df_by_date.Recovered.diff()
print(df_by_date)

我们已经完成了数据准备步骤,因此让我们继续将数据可视化,以寻找任何正在出现的趋势和模式。
# 绘制数据
对于数据可视化,我们将使用两个强大的 python 库——Matplotlib 和 Seaborn。Matplotlib 是大多数数据科学家使用的默认 2D 可视化库。Seaborn 构建在 matplotlib 之上,有助于构建更好看和更复杂的可视化,如热图。
让我们根据数据的不同方面创建五个可视化。
1. *一段时间内确诊病例数*
plotting a bar chart of confirmed cases over timesns.axes_style("whitegrid")sns.barplot(
x="Date_date",
y="Confirmed", data=data.groupby(['Date_date']).sum().reset_index(drop=None)
)plt.xticks(rotation=60)
plt.ylabel('Number of confirmed cases',fontsize=15)
plt.xlabel('Dates',fontsize=15)

2.*死亡率与恢复率*
plotting two line plots for deaths and recoveries respectivelyplt.plot('date_updated', 'Deaths', data=data.groupby(['date_updated']).sum().reset_index(drop=None), color='red')plt.plot('date_updated', 'Recovered', data=data.groupby(['date_updated']).sum().reset_index(drop=None), color='green')plt.xticks(rotation=60)
plt.ylabel('Number of cases',fontsize=15)
plt.xlabel('Dates',fontsize=15)
plt.legend()
plt.show()

3.*除中国外的 10 个受影响最严重的国家*
We know that China is the most affected country by a large margin, #so lets create a bar plot to compare countries other than China#increasing the figure size
plt.rcParams['figure.figsize']=(15,7)sns.barplot(
x="Country",
y="Confirmed",
data=df_country[df_country.Country!='China'].nlargest(10,'Confirmed'),
palette=sns.cubehelix_palette(15, reverse=True)
)plt.ylabel('Number of cases',fontsize=15)
plt.xlabel('Countries',fontsize=15)
plt.xticks(fontsize=13)
plt.yticks(fontsize=13)

4.*一段时间内的死亡率*
The mortality rate, at any point in time, can be roughly calculated #by dividing the number of deaths by the number of confirmed casesdf_by_date['mrate']=df_by_date.apply(lambda x: x['Deaths']*100/(x['Confirmed']), axis=1)plt.plot('Date_date','mrate',data=df_by_date, color='red')
plt.show()

5.*深入了解中国 10 个受灾最严重的省份*
creating a separate dataframe for provincesdf_province=data[data['Country']=='China'].groupby(['Province/State']).max().reset_index(drop=None)#selecting 10 most affected provinces
df_province=df_province.nlargest(10,'Confirmed')df_province=df_province[['Province/State','Deaths','Recovered']]#for multi-bar plots in seaborn, we need to melt the dataframe so #that the the deaths and recovered values are in the same column
df_province= df_province.melt(id_vars=['Province/State'])
sns.barplot(
x='Province/State',
y='value',
hue='variable',
data=df_province
)plt.xlabel('Provinces',fontsize=15)
plt.ylabel('Number of cases',fontsize=15)

# 观察
1. 自 1 月 28 日以来,每天报告的病例数量增加了近 250%。2 月 4 日报告的病例数是 3915。这说明病毒传染性很强,传播速度很快。
2. 在第一周,死亡率高于康复率。自 1 月 31 日以来,恢复率迅速上升,并呈现积极趋势。2 月 4 日有 255 人康复,相比之下有 66 人死亡。随着越来越多的人了解症状并及时寻求药物治疗,治愈率将继续增加。
3. 在地理上靠近中国的国家,如泰国、日本和新加坡,比其他亚洲和欧洲国家报告了更多的病例。德国是一个例外,它是欧洲病例最多的国家。
4. 死亡率从未超过 3%,正在逐渐降低到 2%。未来几周更多的复苏可能会进一步减少这种情况。
5. 中国湖北省是疫情爆发的中心。该省报告的病例比所有其他省份加起来都多。有些省份没有出现死亡病例,所有受影响的患者都已康复。
# 结论
分析显示了武汉冠状病毒传播的惊人速度。至少有 811 人在当前的疫情中死亡,超过了七年前 SARS 爆发时报道的 774 人死亡。我祈祷并希望病毒尽快被控制住。
*编者按:*[*【towardsdatascience.com】*](https://slack-redir.net/link?url=http%3A%2F%2Ftowardsdatascience.com)*是一家以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家。想了解更多关于疫情冠状病毒的信息,可以点击* [*这里*](https://slack-redir.net/link?url=https%3A%2F%2Fwww.who.int%2Femergencies%2Fdiseases%2Fnovel-coronavirus-2019) *。*
# 在 6 分钟内学会如何使用 KMeans
> 原文:<https://towardsdatascience.com/a-data-scientists-practical-guide-to-using-kmeans-ff180878e13b?source=collection_archive---------51----------------------->

图片来自 [Pixabay](https://pixabay.com/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=2546)
# 介绍
聚类是一种属于无监督学习类别的机器学习技术。在不进入不同机器学习类别的大量细节的情况下,我将给出无监督学习的高级描述。
简而言之,我们不是预先决定我们希望我们的算法找到什么,而是提前给算法提供很少甚至没有指导。
换句话说,我们不是明确地告诉我们的算法我们想要预测或解释什么,而是踢回去,把接力棒交给算法来识别给定特征中的突出模式。
如果你想了解更多关于这个划分,你可以看看[这个帖子](/machine-learning-in-a-nut-shell-df251f480f77)。
聚类具有广泛的应用,是数据科学工具箱中非常有用的工具。
我们将讨论集群的一个非常具体的实现,Kmeans。也就是说,对集群的基本理解是实际应用的前提。我们不会在这里深入探讨,但是你可以通过[这篇文章](/what-every-data-scientist-needs-to-know-about-clustering-cf8f860a1883?source=your_stories_page---------------------------)从概念层面了解更多。
# Kmeans 入门
# 克曼语中的 K
k 代表您要识别的组或集群的数量。如果您正在执行聚类分析,而您已经知道有三个分组,您将使用该上下文通知算法您需要三个分组。你并不总是知道有多少自然分组,但是你可能知道你需要多少分组。在以下示例中,我们将使用 iris 数据集,它是与各种 Iris 物种相关的测量值的集合,但还有许多其他用例..基于用途、尺寸等的客户。或者基于购买可能性和可能的购买量等的前景。在商业、生物学和其他领域有广泛的应用。
# 了解质心
一旦我们确定了 k,算法将随机分配 k 个点;这些点将作为你的“质心”。你可能会问,什么是质心?质心指的是每个聚类的中心点。
一旦这些中心点或质心被随机分配…欧几里德距离被计算在每个点和每个质心之间。
一旦计算出距离,每个点被分配到最近的质心。
我们现在有了这些星团的第一个版本。但我们还没完。当我们到达第一个版本的聚类时,质心被移动到分配给每个质心的点组的绝对中心。发生欧几里德距离的重新计算,并且在给定点现在更接近备选质心的情况下,它被相应地分配。同样的过程发生,直到质心达到稳定,点不再被重新分配。分配给给定质心的点的组合构成了每个聚类。
# 让我们建立我们的第一个模型
# 开始一点探索
对于这个分析,我们将使用我前面提到的经典虹膜数据集。这个数据集被一次又一次地用来教授聚类的概念。埃德加·安德森收集了三种鸢尾的萼片和花瓣的长度/宽度数据。如果你对这方面的更多信息感兴趣,查看维基百科的解释([https://en.wikipedia.org/wiki/Iris_flower_data_set](https://en.wikipedia.org/wiki/Iris_flower_data_set))
# 快速 EDA
head(iris)

glimpse(iris)

我们将在散点图中显示花瓣的长度和宽度,并用颜色覆盖物种。
ggplot(iris, aes(x = Petal.Length, y = Petal.Width, color = factor(Species))) +
geom_point()

为了好玩,我们再做几个不同的组合。
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = factor(Species))) +
geom_point()

ggplot(iris, aes(x = Sepal.Length, y = Petal.Length, color = factor(Species))) +
geom_point()

为了简洁起见,我们可以对每一个变量组合详尽地进行同样的练习;我们会继续。
# 构建我们的第一个聚类模型
set.seed(3)
k_iris <- kmeans(iris[, 3:4], centers = 3)
当我们将种子设置为一个给定的数字时,我们确保可以重现我们的结果。
我们调用 kmeans 函数并传递相关的数据和列。在这种情况下,我们使用花瓣长度和宽度来构建我们的模型。我们宣布三个中心,因为我们知道有三个不同的物种。
如果你调用你的集群模型。您将得到类似如下的输出:

值得强调的几件事:
你会看到一些有用的信息:
* 簇的数量,先前由“中心”参数确定
* 跨自然确定的聚类的每个值的平均值。
* “在聚类平方和内”-这表示每个点和聚类质心之间的绝对距离
* 可用组件——在这里,模型提供了一些其他的信息。我们将很快利用“集群”组件!
# 性能评价
在这里,我们允许一种无监督的机器学习方法来识别我们的数据中自然出现的群体,但我们也可以访问实际的物种;因此,让我们来评估算法的性能!
一个非常简单的方法是查看一个包含物种和指定集群的表格。在这里,您将看到我们将引用模型对象,并通过记录调用确定的集群。
table(k_iris\(cluster, iris\)Species)

在这里我们可以看到所有的刚毛藻都被归为一类,没有其他的物种加入到同一个类中。对于 versicolor,我们可以看到 kmeans 准确地捕获了簇 3 中 48/50 的 veriscolor 和簇 1 中 46/50 的 virginica。
我们可以很容易地使用来自`dplyr`库的`mutate`函数将这个分类分配给我们的 iris 数据集
iris <- mutate(iris, cluster = k_iris$cluster)
现在让我们重新创建我们的第一个散点图,把物种换成集群
ggplot(iris, aes(x = Petal.Length, y = Petal.Width, color = factor(cluster))) +
geom_point()

上面我们可以看到这两个数据点基于其物种的自然分组的几乎相同的表示。
我们当然可以测试各种变量组合,以达到更好的近似每一种鸢尾,但现在你有基本的工具需要这样做!
# 结论
在短短的几分钟内,我们已经了解了 Kmeans 集群的工作原理以及如何实现它。
* 聚类是一种无监督的学习方法
* Kmeans 是最流行的聚类技术之一
* k 是簇的预定数量
* 该算法实际上是如何工作的
* 如何创建我们自己的集群模型
我希望这篇关于 Kmeans 实际应用的快速帖子对您应用该技术有所帮助。
祝数据科学快乐!
# 数据科学家的工具包
> 原文:<https://towardsdatascience.com/a-data-scientists-tool-kit-ecf9eda285ad?source=collection_archive---------10----------------------->

由[谷仓图片](https://unsplash.com/@barnimages?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)在 [Unsplash](https://unsplash.com/s/photos/tools?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上拍摄
## 数据科学的基本工具
数据科学家的主要角色是将机器学习、统计方法和探索性分析应用于数据,以获取见解并帮助决策。编程和计算工具的使用对这一角色至关重要。事实上,许多人用这句名言来描述这个领域。
> 一个**数据科学家**是在统计**方面**比任何软件工程师**更好**并且在软件工程**方面**比任何统计学家**更好**的人****
如果您正在开始学习数据科学,或者想要提高现有技能,那么很好地了解有效履行这一职责所需的工具是至关重要的。
用于数据科学的 Python 在过去的十年中逐渐流行起来,现在是该领域从业者最流行的编程语言。在下面的文章中,我将概述数据科学家使用的核心工具,主要集中在基于 python 的工具上。
## **数字价格**
NumPy 是一个强大的库,用于使用 python 执行数学和科学计算。您会发现许多其他数据科学库需要它作为一个依赖项来运行,因为它是基础科学包之一。
该工具作为一个 **N 维数组**对象与数据交互。它提供了操纵数组、执行数组运算、基本统计和常见线性代数计算(如叉积和点积运算)的工具。
## 熊猫
熊猫库简化了 python 中数据的操作和分析。Pandas 使用两种基本的数据结构。分别是**系列**,一维标签数组,和**数据帧**,二维标签数据结构。Pandas 包有许多工具可以从各种来源读取数据,包括 CSV 文件和关系数据库。
一旦数据作为这些数据结构中的一种可用,pandas 就提供了一系列非常简单的功能来清理、转换和分析数据。其中包括处理缺失数据的内置工具、简单的绘图功能和类似 excel 的数据透视表。
## SciPy
SciPy 是另一个核心科学计算 python 库。这个库是为了与 NumPy 数组交互而构建的,并且依赖于 NumPy 提供的许多功能。然而,尽管要使用这个包,您需要安装并导入 NumPy,但是不需要直接导入功能,因为这是自动可用的。
Scipy 有效地建立在 NumPy 中可用的数学功能之上。NumPy 提供非常快速的数组操作,而 SciPy 处理这些数组并支持高级数学和科学计算的应用。
## sci kit-学习
[Scikit-learn](https://scikit-learn.org/stable/user_guide.html) 是一个用户友好的、全面的、功能强大的机器学习库。它包含将大多数机器学习技术应用于数据的功能,并且对每种功能都有一致的用户界面。
该库还提供了用于数据清理、数据预处理和模型验证的工具。它最强大的功能之一是机器学习管道的概念。这些流水线使得机器学习中的各种步骤,例如预处理、训练等等,能够被链接在一起成为一个对象。
## 克拉斯
[Keras](https://keras.io/) 是一个 python API,旨在为神经网络的工作提供一个简单的接口。Tensorflow 等流行的深度学习库因不太用户友好而臭名昭著。Keras 位于这些框架之上,提供了一种友好的交互方式。
Keras 支持卷积和递归网络,支持多后端,可以在 CPU 和 GPU 上运行。
## Matplotlib
Matplotlib 是 python 中的基本绘图库之一。许多其他流行的绘图库依赖于 matplotlib API,包括 pandas 绘图功能和 Seaborn。
Matplolib 是一个非常丰富的绘图库,包含创建各种图表和可视化的功能。此外,它还包含创建动画和交互式图表的功能。
## Jupyter 笔记本
Jupyter 笔记本是一个交互式 python 编程接口。在笔记本环境中编写 python 的好处在于,它允许你直接在程序中轻松地呈现可视化、数据集和数据摘要。
这些笔记本也是分享数据科学工作的理想选择,因为它们可以通过包含直接与代码和可视化一致的标记文本来进行高度注释。
## Python IDE
Jupyter 笔记本是为数据科学编写代码的有用地方。然而,在很多情况下,需要将代码编写到可重用的模块中。如果您正在编写代码以将机器学习模型投入生产,情况尤其如此。
在这些情况下,IDE(集成开发环境)是有用的,因为它们提供了许多有用的功能,如集成 python 风格指南、单元测试和版本控制。我个人使用 PyCharm,但也有很多其他可用的。
## 开源代码库
[Github](https://github.com/) 是一个非常流行的版本控制平台。数据科学的一个基本原则是,代码和结果应该可以在未来的某个时间点被自己或他人复制。版本控制提供了一种跟踪和记录在线工作更改的机制。
此外,Github 支持安全的项目协作形式。这是通过一个人克隆一个分支(实际上是您的项目的副本),在本地进行更改,然后在将它们集成到项目中之前将它们上传以供审查来实现的。关于 Github 的数据科学家入门指南,请参见我之前的文章[这里](/5-tools-for-reproducible-data-science-c099c6b881e5)。
本文简要介绍了数据科学工作的核心工具包。在我的下一篇文章中,我将介绍如何设置您的计算机以进行有效的数据科学工作,并将更详细地介绍这些工具和其他工具。
感谢阅读!
我每月都会发一份简讯,如果你想加入,请点击此链接注册。期待成为您学习旅程的一部分!
# 数据团队的产品是决策
> 原文:<https://towardsdatascience.com/a-data-teams-product-is-decisions-bbd7a6b4cfbe?source=collection_archive---------41----------------------->

弗兰基·查马基在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄的照片,经作者许可编辑
# 数据团队不是内置的
对于大多数不以数据为主要产品的公司来说,大多数数据团队都不是“内置”的。
通常会有一个团队负责销售和分销(销售、营销、增长、运营),一个团队负责产品采购或开发(产品、工程),以及一般行政管理(财务、领导、人力资源)。
当公司开始考虑数据团队的概念时,他们已经达到了一定的规模。
这并不意味着数据团队没有实际用途,只是意味着在初创公司或大公司中发现自己是数据第一人的人通常会遇到这样的问题,要么找到他们或他们的团队可以负责的领域,要么证明业务的相关性或附加值。
我发现非常有用的一件事是让你的数据团队的产品围绕**决策**。
# 数据团队的产品是决策
无论数据工作的类型在数据工程、分析、商业智能或建模之间的光谱中处于什么位置,数据团队的产品都不是上述内容,而是决策。
在 First Circle,我们团队的目标是确保**所有决策,无论是战略决策还是运营决策,都通过数据得到增强或自动化。**
# 决策的类型
有两种类型的决策通常是数据团队的目标:(a)定制的、奢侈的战略决策,以及(b)大规模生产的、可重复的、快速的运营决策。

作者照片
# 战略决策
战略决策是奢侈的、定制的和手工的决策;不常做出但影响很大的决策。有很大的不确定性,不太可能会有频繁的反馈循环。为了增强这些决策,人们将受益于商业思维、沟通技巧和从有限的数据中提取信息的能力(高度定制的线性模型,或贝叶斯技术)。
战略决策的例子包括产品/市场扩张、预算和人员规划、竞争分析、合并和收购。
# 运营决策
运营决策是大规模生产的、可重复的决策,一天要做成百上千次。它们单独来看可能没有那么大的影响力,但是庞大的数量也使得优化这类决策变得非常重要。为了节省成本,运营决策背后的决策系统通常是算法,需要机器学习、数据科学和强大的数据工程来生产系统。
运营决策的例子是任何每笔交易的决策,如银行的个人贷款授权算法、拼车公司的司机调度算法或电子商务公司的推荐算法。
进入数据科学领域的个人通常只考虑运营决策,但如果数据团队是唯一处理数据的团队,那么他们必须同时考虑这两种决策,这一点至关重要,因为成功运营企业需要两种决策都由数据驱动。
# 在数据团队的路线图中考虑这两种类型
在设计数据团队的路线图时,我发现意识到两种类型的“产品”之间的差异并确保组合适合业务非常重要。
在运营决策上花费太多可能意味着实现第一个价值需要漫长的努力,因为必须进行大量的数据收集和实验。
在战略决策上花费太多可能意味着你的公司实际上没有从数据中认识到真正的技术价值,然后你将像传统公司一样运营,只是对他们的信息稍微聪明一点。
更糟糕和更常见的是混淆两者;将战略决策视为运营决策,反之亦然。我见过很多这样的情况,人们使用随机森林变量重要性进行一次性决策(“洞察”),或者人类在流程中的角色只是按按钮,并不实际应用任何判断(很容易自动化)。
我的建议是把这些放在一块板上,并在两个桶中突出高优先级的项目。这个练习应该与你的团队的计划周期一起完成。
在未来的新闻稿中,我将讲述如何组建一个团队,以整体的方式解决这些问题,并避免与许多新数据团队采用的[“pin factory”模型](https://multithreaded.stitchfix.com/blog/2019/03/11/FullStackDS-Generalists/)相关的常见陷阱。
*最初发表于*[T5【https://tjpalanca.com】](https://tjpalanca.com/posts/2020-10-11-data-team-value/)*。*
# AWS 上的数据仓库实现
> 原文:<https://towardsdatascience.com/a-data-warehouse-implementation-on-aws-a96d0e251abd?source=collection_archive---------8----------------------->
## 使用 AWS S3、AWS 胶水、DBT 和 AWS 红移的实现

亚历克斯·库利科夫在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片
在过去的帖子中,我一直在谈论数据仓库,它们的基本架构,以及一些可以帮助您构建数据仓库的基本原则。今天,我想向您展示**基于几个月前进行的案例研究**在 AWS** 上实现数据仓库。**
这个实现使用 AWS S3 作为数据湖(DL)。AWS 粘合为数据目录。以及 AWS 红移和红移谱作为数据仓库(DW)。
> 注意:如果你不熟悉我在这里使用的一些术语和概念,这篇文章可能会令人困惑。关于这些术语和概念的更多信息,我建议你看一看其他涉及这些主题的帖子。
[](/what-is-a-data-warehouse-basic-architecture-ea2cd12c9bb0) [## 什么是数据仓库:基本架构
### 数据仓库主要概念介绍
towardsdatascience.com](/what-is-a-data-warehouse-basic-architecture-ea2cd12c9bb0) [](/building-a-data-warehouse-basic-architectural-principles-66bd7059ffd0) [## 构建数据仓库:基本架构原则
### 一种简化数据仓库的方法
towardsdatascience.com](/building-a-data-warehouse-basic-architectural-principles-66bd7059ffd0) [](/building-a-data-warehouse-pipeline-basic-concepts-roadmap-d14032890ab6) [## 构建数据仓库管道:基本概念和路线图
### 提高数据管道可操作性和性能的五个过程
towardsdatascience.com](/building-a-data-warehouse-pipeline-basic-concepts-roadmap-d14032890ab6)
# 体系结构
该实施中遵循的架构基于 ELT 流程。首先,从数据源中提取数据,然后加载到数据湖中,最后在数据仓库中进行转换。

一个数据仓库体系结构的抽象——作者举例说明
这篇文章中提到的实现是基于几个月前的一个案例研究——更多信息请查看这篇[文章](/building-a-data-warehouse-basic-architectural-principles-66bd7059ffd0)。架构看起来是这样的:

自动气象站中的数据仓库架构——作者举例说明
它使用 AWS S3 作为 DL。AWS 粘合为数据目录。而 AWS 的红移和红移谱作为 DW。
此外,它使用 Apache Spark 进行数据提取,使用 Airflow 作为编排器,使用 Metabase 作为 BI 工具。但是,特别是对于这个职位,范围仅限于**DL 和 DW** 的实施。
# 数据湖
这个案例研究的第一部分是数据湖。
> 数据湖是存储来自多个来源的数据的存储库。它允许处理结构化和非结构化数据。
在这个案例研究中,数据湖被用作允许集中所有不同数据源的临时区域。
来自这些来源的数据以其原始格式存储。在将数据加载到数据湖之前,不涉及任何转换过程。所以,可以认为是一个**不可改变的集结地**。
## 数据湖架构
数据湖架构可能会根据您的需求而有所不同。在这个案例研究中,使用了一个简单的架构。它由两个区域组成:T4 原始区域和沙盒区域。
如果您正在处理具有复杂格式的数据,*例如,*,某个创意开发人员决定编写的一些复杂嵌套的 JSON,**您可能需要在将数据加载到数据仓库之前对其进行处理**。因此,您可能需要实现另一个数据湖区域。这就是 Ben Sharma 在他的书[中所说的数据湖](https://www.oreilly.com/library/view/architecting-data-lakes/9781492033004/)精炼区。
但是,现在,我会保持简单。
* **原始区**是以原始格式存储数据的地方。然后,通过在 [DBT](https://www.getdbt.com/) 上运行一些转换过程,将其加载到数据仓库中
* 沙盒区是数据分析师、数据工程师或数据科学家可以做一些疯狂实验的地方
在原始区域中,数据根据其来源和加载日期进行分区,*例如*,2020 年 9 月 15 日加载的名为“source”的源中的文件存储在/source/2020/09/15 中。
> 值得一提的是,您在数据湖中构建分区的方式应该根据您的特定需求。有关 S3 分区的信息,请参见本[帖子](https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-etl-partitions.html)和本[帖子](https://docs.aws.amazon.com/athena/latest/ug/partitions.html)。
您可以在下图中找到数据湖的建议体系结构的图形表示。

数据湖体系结构——作者制作的插图
这是它在 AWS S3 的实现方式。

数据湖—0 级—作者制作的插图

数据湖—1 级—作者制作的插图

数据湖—2 级—作者制作的插图

数据湖—级别 3 —作者制作的插图
最后,在最后一层,使用 parquet 文件存储数据。我使用了一个开源数据集来举例说明这个案例研究。

数据湖—级别 4 —作者制作的插图
## 数据目录
现在我们已经将数据存储在数据湖中,我们需要能够使用 SQL 查询数据。因此,我们可以使用 DBT 执行一些数据转换。
我们将使用 AWS Glue 数据目录数据库和爬虫来允许我们在 DL 之上运行 SQL 查询。
第一步是[在 AWS Glue 中创建一个数据库](https://docs.aws.amazon.com/glue/latest/dg/console-databases.html)。

AWS 胶水数据目录中的数据库—作者制作的插图
然后,可以使用 AWS Glue 爬虫填充数据库。更多信息请看这个[帖子](https://docs.aws.amazon.com/glue/latest/dg/console-crawlers.html)。
创建并运行爬虫后的最终结果可能如下所示。

AWS 胶水目录中的一个表格—第一部分—作者制作的插图

AWS 胶水目录中的表格—第二部分—作者制作的插图
现在,我们可以开始工作了。有了数据目录中映射的表,现在我们可以使用 AWS 红移光谱从 DW 中访问它们。因此,我们最终可以在数据仓库中具体化数据。
# 数据仓库
如前所述,DW 是使用 AWS 红移、红移光谱和 DBT 构建的。
[AWS 红移](https://docs.aws.amazon.com/redshift/latest/mgmt/welcome.html)是 AWS 提供的数据仓库服务。[红移光谱](https://docs.aws.amazon.com/redshift/latest/dg/c-getting-started-using-spectrum.html) 是一项服务,可以在红移集群内部使用,直接从亚马逊 S3 上的文件中查询数据。并且, [DBT](https://www.getdbt.com/) 是一个允许您使用 SQL 在数据仓库内部执行转换的工具。
DW 的关键组件之一是红移光谱,因为它允许您将粘合数据目录与红移联系起来。因此,您可以使用 DBT 查询红移星团中的 DL 数据。**这很重要,因为 DBT 不会移动数据。它只是转换数据仓库中的数据。**
将红移光谱与之前在 AWS 粘合目录中映射的数据连接起来的方法是通过在外部模式中创建**外部表。更多信息见[本](https://docs.aws.amazon.com/redshift/latest/dg/c-getting-started-using-spectrum-create-external-table.html)。**
这样做之后,外部模式应该如下所示:

而且,如果您使用的是我在本案例研究中使用的相同的数据集,您的元数据应该是这样的:

在 DBeaver 中可视化的源表—作者制作的插图
## 数据实体化
在用红移光谱映射数据之后,我们可以继续进行 AWS 红移中的数据具体化。
这种具体化允许您将数据放入红移表中。一个关键的区别是,当您查询红移表中的数据时,您不需要为查询付费,因为您已经为红移集群付费了。**而如果你查询外部表中的数据,*即*红移光谱,你将按查询中处理的数据**收费。更多信息见[本](https://aws.amazon.com/redshift/pricing/)。
另一个关键区别是 **AWS 红移在处理海量数据**时表现优于红移频谱。更多信息见[本](https://www.concurrencylabs.com/blog/starburst-presto-vs-aws-redshift/)。
因此,如果我们想对前面给出的表进行一些转换,我们可以编写一个 DBT 模型,并用红移来具体化数据。
这是本案例研究的一个简单的 DBT 模型:

DBT 模型——作者创作的插图
这就是这个模型在红移表中的样子。

红移表——作者制作的插图
# 结论
在本文中,我们为 AWS 中的数据湖和数据仓库实现了一个简单的架构。
此外,我们还讨论了这样做所必需的一些关键步骤。一些要点如下:
* 该架构遵循 ELT 方法。因此,在将数据加载到数据湖之前,不涉及任何转换过程
* 数据湖被用作不可变的暂存区,用于将数据直接加载到数据仓库中
* 数据湖由两个区域组成:原始区域和沙盒区域。如果您需要在加载到数据仓库之前处理数据,您应该为数据湖设置另一个区域:精化区域
* 数据湖中的分区应该根据您的用例来定义
* AWS 红移光谱是一项服务,可以在红移集群中直接从亚马逊 S3 上的文件中查询数据。这是对 AWS 红移的额外服务
* AWS 红移光谱允许你连接胶水数据目录与红移
* 转换逻辑使用 DBT 模型
* DBT 不移动数据。它只是转换数据仓库中的数据
我希望这些信息对你有用。
感谢阅读到最后。
下期帖子再见!
*如果您想随时更新我的作品,* ***请加入我的*** [***简讯***](https://metadatacommunity.substack.com/) ***!偶尔,我会和我的读者分享一些东西。如果你加入我会很感激的:)***
[](https://ajhenaor.medium.com/interested-in-data-warehousing-424b49ec97e4) [## 对数据仓库感兴趣?
### 我已经写了几篇关于它的文章。这就是如何阅读它们!
ajhenaor.medium.com](https://ajhenaor.medium.com/interested-in-data-warehousing-424b49ec97e4)
# 数据集是一种世界观
> 原文:<https://towardsdatascience.com/a-dataset-is-a-worldview-5328216dd44d?source=collection_archive---------23----------------------->
## 关于主观数据,为什么数据集应该过期,以及数据破坏。
*这是 2019 年 9 月在国会图书馆发表的一次演讲的略微扩展版本。*
# 数据集是一种世界观
我叫汉娜·戴维斯,是一名研究艺术家、生殖音乐家和从事机器学习的数据科学家。我的大部分工作都是围绕情感数据、算法组合和数据集创建的想法。
我的一个更大的项目是一个叫做 TransProse 的算法,它通过编程将书籍翻译成音乐。它的工作原理是找到潜在的情感内容,并利用这些内容创作出具有相同情感基调的音乐作品。

http://musicfromtext.com/
为了做到这一点,我使用了几种资源,包括本质上是一个带有各种情绪标签的单词数据集。
在深入研究这个数据集之前,我花了很长时间研究它,当我这样做的时候,我发现了这个:

“分娩”这个词被认为是完全不带感情色彩的。
我对此很感兴趣。这是怎么发生的?给这个贴标签的人是谁?我可以想到一个场景来检查任何一种情绪,但不能选择任何一种情绪。
我没有得到那些答案,但我确实了解到每个单词只被三个人标记过。这在数据集创建中很常见,因为标注很快就变得昂贵——甚至每个词三个人就可以变成数千美元。
但是因为**一个机器学习模型从它的输入数据**中学习它的世界的边界,只有三个人告知任何使用该数据集的模型将如何解释“分娩”是否是情绪化的。
这引出了一个贯穿我所有作品的观点:**数据集就是世界观**。它包含了搜集和收集数据的人的世界观,无论他们是研究人员、艺术家还是公司。它包含了贴标签者的世界观,无论他们是手动地、不知不觉地给数据贴标签,还是通过像 Mechanical Turk 这样的第三方服务贴标签,这本身就带有人口统计学偏见。它包括组织者创造的固有分类法的世界观,在许多情况下,组织者是其动机与高质量生活直接不相容的公司。
# 数据集应该过期
除了创建者的特定偏见,数据集还编码了创建时的一般文化价值观。过时的社会世界观是某些迪士尼电影被锁在地下室的原因——因为我们的社会已经改变和发展,这些电影中的思想(即种族主义和厌恶女性的思想)不再合适。
数据集不会发生这种过期。以 2008 年创建的 Wild 数据集中标记的人脸为例。这是第一批不受约束的面部识别数据集之一,由从互联网上搜集的 13,000 张主要是名人的图像组成。但是由于时间的原因,只有 3 个人占了这个数据的 7%,这意味着是可概括的:乔治·布什,科林·鲍威尔和托尼·布莱尔。
这种历史偏见存在于各种题材中。巨大而令人惊叹的数据集 ImageNet 于 2009 年创建,至今仍在使用,它改变了整个机器学习领域。如果您在原始数据集中搜索“手机”,它会返回一系列翻盖手机,因为这是在智能手机普及之前。
机器学习数据集被视为客观的。它们被机器学习算法和创造者视为基础真理。数据集的制作困难、耗时且昂贵,因此数据集一旦创建,通常会使用很长时间。但是,当我们作为一个社会向前发展时,没有理由坚持过去的价值观;同样,也没有理由让未来社会受制于我们当前的状况。我们的 **数据集可以也应该有截止日期。**考虑特朗普政府将收集的数据类型及其标注方式;我们有什么理由希望这能告诉我们的未来吗?
# “人工智能做到了”
这些问题中有许多是更广泛的分类和分类学中的问题。但这对于机器学习来说更重要也更可怕,原因有两个:首先,机器学习数据集影响现实世界中投入生产的模型——通常很快,没有任何检查——并对我们的日常生活产生重大而直接的影响。它们影响着一切,从我们的搜索结果到工作前景,再到信用评分,这些都是无形的,没有责任,没有上诉程序,也没有补救选项。
第二:机器学习研究人员、记者、政府、企业和其他相关方一直将人工智能作为一个黑匣子,完全无法解释,最重要的是,对自己负责。这使得所有这些偏见和世界观的问题都可以被认为是“只是人工智能”**对于那些利用机器学习进行伤害的人来说,这是一个非常方便的叙述。**
# 主观数据
为了解决这些问题,我提倡的一个想法是“主观数据”这意味着接受数据集有世界观这一事实,并明确该世界观包含什么。这也意味着有机会做得更好——创造我们自己的理想或实验性的世界观,并超越我们被迫继承的世界观。我们可以用数据和标签创建一个数据集,来模拟一个理想的或更健康的社会,而不仅仅是反映它的现状。我们可以创建独特的和实验性的分类法和标签,并把有害的排除在外。我们可以让数据集积极支持那些为更美好的未来而战的人,而不是成为战斗途中的另一个障碍。
这已经发生在机器学习艺术领域(见下文),但我相信它也与其他领域相关;我相信我们在数据集上的影响力比我们想象的要大。我们应该考虑如何尽可能地包含细微差别——例如,通过腾出空间来包含每一条输入数据,而不是截断它以适应几个类别。我们应该优先考虑那些让我们远离单一世界观的实践。**我们不应该让人们独特的生活环境被算法平均值所评判,从而导致现实世界的后果**。我们应该考虑是谁的世界观在强加给我们。
# 数据破坏
我想以一个可能会让我们所有关心数据和归档的人感到不安的提示来结束这篇文章,但在这个时代,思考这个问题是很重要的:故意破坏数据的想法。你们中的许多人已经知道这个故事了,但是雷内·卡米利是一个早期的例子;第二次世界大战期间,他是一名秘密的法国抵抗战士,在法国维希的纳粹统治下管理国家统计局。他负责将纳粹人口普查数据转换成穿孔卡片,他决定删除第 11 列,即表示宗教的那一列。他拯救了许多人的生命,仅仅是因为他决定不收集关于他们的某些数据。
在当今时代,我们围绕数据做出决策的重要性是相似的。关于一个人的种族、性别、心理健康、移民身份和其他分类的数据很可能会被用于伤害,而现在还没有。对于那些与此相关的人来说,提前与你的团队(或你自己)讨论并决定你将在哪个点采取行动是很重要的,这样你就能够在那一刻到来时识别并采取行动。
在错误的手里,或者甚至在完全善意但欠考虑的手里,**归类为暴力**。如果没有对这个想法与您自己的机器学习工作的关系进行严格的思考,很容易通过收集和标记数据这样看似简单的事情意外地造成伤害。
许多例子中的几个!)使用和/或探索主观数据集的机器学习艺术项目:
[笑屋](http://www.hannahishere.com/project/the-laughing-room-with-jonny-sun/),孙燕姿和汉娜·戴维斯
[分类. 01](http://mimionuoha.com/classification01) ,咪咪欧诺哈
[女权主义数据集](https://carolinesinders.com/feminist-data-set),卡罗琳·辛德斯
[动物分类器](http://ssbkyh.com/works/animal_classifier/),Shinseungback Kimyonghun
[丝芙兰提及“哭泣”的评论数据集](https://github.com/everestpipkin/datagardens/tree/master/students/khanniie/5_newDataSet),康妮·叶
这就是问题、解决方案、过去和未来
*感谢* [*米科拉*](https://medium.com/u/cfa215f81d3f?source=post_page-----5328216dd44d--------------------------------)*[*萨拉·k·哈拉彻*](https://medium.com/u/6cff342b475e?source=post_page-----5328216dd44d--------------------------------)*[*路易斯·丹尼尔*](https://medium.com/u/64078905d77a?source=post_page-----5328216dd44d--------------------------------) *的反馈!***
# Kaggle 上有 170 万篇 ArXiv 文章的数据集
> 原文:<https://towardsdatascience.com/a-dataset-of-1-7-million-arxiv-articles-available-on-kaggle-8a11075cac32?source=collection_archive---------31----------------------->
## 所有科学家的伟大资源。

在 [Unsplash](https://unsplash.com/s/photos/library?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上由 [Fitore F](https://unsplash.com/@daseine?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 拍摄的照片
“arXiv 是一项免费分发服务,是 170 万篇学术文章的开放存取档案,涉及物理、数学、计算机科学、定量生物学、定量金融学、统计学、电气工程和系统科学以及经济学等领域”,正如其编辑所说。ArXiv 是知识的金矿。你挖掘得越多,你学到的有价值的信息就越多。这也使得跟踪科学趋势变得更加容易。
如果您对数据科学领域感兴趣,您可能已经阅读过关于 arXiv 的文章。如果你还没有这样做,你应该这样做。由于数据科学仍然是一个不断发展的领域,每天都有新的论文发表,带来新的增强。这使得像 arXiv 这样的平台更有价值。
arXiv 已经将其整个语料库作为一个[数据集](https://www.kaggle.com/Cornell-University/arxiv?select=arxiv-metadata-oai-snapshot.json)放在 Kaggle 上。该数据集包含 arXiv 上 170 万篇学术文章的相关特征,如文章标题、作者、类别、内容(包括摘要和全文)和引用。
这个数据集是进行机器学习和深度学习应用的惊人资源。可以完成的一些应用有:
* 自然语言处理(NLP)和理解(NLU)用例
* 利用文章内容进行深度学习的文本生成
* 预测分析,如文章的类别预测
* 不同科学领域的主题趋势分析
* 论文推荐引擎

由[斯凯工作室](https://unsplash.com/@skyestudios?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)在 [Unsplash](https://unsplash.com/s/photos/light-bulb?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 拍摄的照片
深度学习模型需要大量数据。随着计算和处理的进步,模型可以吸收比以往更多的数据。如此庞大的科学文本数据集对于自然语言处理、NLU 和文本生成来说是非常有价值的原材料。我们甚至可以有一个模型来写一些主题的学术文章。OpenAI 的新文本生成器 GPT-3 让我们超越极限地思考。因此,我认为拥有一个深度学习模型来写科学并不太遥远。
arXiv 执行董事埃莉诺拉·普雷萨尼表示,“通过提供 Kaggle 上的数据集,我们超越了人类通过阅读所有这些文章所能学到的东西,我们以机器可读的格式向公众提供 arXiv 背后的数据和信息”。我完全同意她关于学习机会的观点。将所有这些文章作为一个数据集可以超越通过阅读来学习。通过数据分析和机器学习,可以从这个文章金矿中发现大量有价值的见解。例如,不同技术之间的一些不太明显的联系可以被点亮。
将整个 arXiv 文章转换成一个结构良好、组织有序的数据集有可能加速科学发现。科学是在自身的基础上成长和进步的。当我们能够专注于改进轮子时,就没有必要重新发明轮子。通过分析这个 arXiv 数据集,我们可以获得科学发展的简明摘要,并阐明我们未来需要关注的问题。
这个数据集有太多的工作要做。我强烈建议你至少看一看。你不必创建一个机器学习产品,但它也将是练习数据分析和处理技能的有用资源。
感谢您的阅读。如果您有任何反馈,请告诉我。
# **参考文献**
* 【https://www.kaggle.com/Cornell-University/arxiv? select = arxiv-metadata-OAI-snapshot . JSON
* [https://blogs . Cornell . edu/arxiv/2020/08/05/levelling-machine-learning-to-fuel-new-discoveries-with-the-arxiv-dataset/](https://blogs.cornell.edu/arxiv/2020/08/05/leveraging-machine-learning-to-fuel-new-discoveries-with-the-arxiv-dataset/)
# 用格拉克描述的一天
> 原文:<https://towardsdatascience.com/a-day-described-in-grakn-part-i-46bb7e3cd82a?source=collection_archive---------31----------------------->
## Graphbits:一堆关于图形的 5 分钟文章
## Grakn 模式
先说超图!长话短说,超图可以有同时连接两个以上节点的边。所以一定有超图模型的数据库对吧?是的,有,而且是[**Grakn**](https://grakn.ai)……这就是这篇文章(以及其他一些文章)将要讨论的内容。
# Grakn

[来源](https://camo.githubusercontent.com/a4b2afa276e152da35ecbd6454755fc14182b891/68747470733a2f2f6772616b6e2e61692f6173736574732f696d672f6772616b6e2d6c6f676f2d6e616d652e706e67)
Grakn 被称为“智能数据库”,它允许您通过扩展实体关系方法(主要用于 SQL 数据库)来为不同领域建模知识库。由自动推理引擎驱动,它能够在大型数据集上执行逻辑推理。Grakn 有自己的声明式查询语言 Graql,同时也有自己的可视化工具**Grakn 工作库**。(稍后将详细介绍)
说得够多了…让我们言归正传。
## Grakn 模式
在将任何数据加载到数据库之前,应该创建一个模式。
可以将模式视为数据库的蓝图,它为您提供了一个关于如何构建数据的清晰思路。
请注意!模式设计是创建数据库的第一步,也是最关键的一步。几乎所有其他操作都取决于模式的定义方式。
让我们用一个例子创建一个简单的模式。
考虑这个场景
> Whatsville 市在新年前夕举办了一场 Gina Goodvoice 的音乐会,该市期待着来自邻近城市的游客激增。鲍比是其中之一。想要探索这个城市,博比决定提前到达。那天早上,他从 WhoTown 乘火车到达 Whatsville,和他的朋友 Tim 在附近的一家咖啡馆共进早餐。然后他决定去参观城市博物馆,并顺便买了一本书。午餐,他从食品车买了一个三明治,在湖边坐了一会儿。傍晚时分,他前往将举行音乐会的城市体育场。他在音乐会上玩得很开心,听着 Gina Goodvoice 的曲子。音乐会一直持续到深夜,之后,博比乘最后一班火车回家。
为什么我跑题这么多?原因很简单。
想象一下鲍比的世界。或者说,鲍比的一天。他遇到了一些人;他去过的地方;他买的东西等等。只是一整天发生的一系列事件。现在,我们要在同一天在格拉克做这个模型。
要创建模式,首先需要确定实体、属性、关系和角色。以下是对它们的简要描述
* **实体**独立存在。它们是实际存在的东西。
* **关系**通常代表实体之间某种形式的联系。
* 实体或关系的特征可以使用**属性**指定。
* 最后,在任何关系中,实体(或属性)总是扮演某种**角色**
迷茫?在我们的例子中,让我们来识别每一个。
可以称为实体的东西有哪些?一个简单的方法是识别人、地点和事物(如果有动物的话,还有动物)
所以我们有博比、蒂姆、吉娜·古德沃斯、Whatsville、WhoTown、博比乘坐的火车、他吃早餐的咖啡馆、举行音乐会的体育场、他买的三明治等等。那里!我们有基本的实体:人、地点和事物。
这些实体的特征是什么?所以一个人可以有一个**名字和一个年龄,比如**。一个城市(或任何地方)可以有一个**名字**,一个**母国家/州,一个纬度,一个经度**等等来标识它。同样,一个事物也可以有一个名称和其他某些特征。这些都可以成为你的属性。
接下来,如果你仔细想想,是什么把所有这些实体联系在一起?**一个**一个**事件**。
Gina Goodvoice 的演唱会是一个联系 Bobby,Tim,Gina 的活动,在新年前夕在体育场举行。那是一个事件,是你的图式中连接一个人、一个地方和一件事物的关系。
此外,一个人在事件中扮演**参与者**的**角色**,地点扮演事件地点的角色。在那里,我们为关系中的实体分配角色。
# 一直到代码
好了,是时候开始敲打了。我们将创建之前为 Grakn 定义的模式。
**但是首先!安装:**
确保您已经安装了 Grakn 服务器和工作库。如果没有,那就在这里绕道[再回来。](https://grakn.ai/download)
## 创建模式
该模式可以在带有“.”的文件中定义。 **gql** 扩展。
模式定义总是以关键字“ **define** ”开始。
接下来,我们定义实体。所以我们有一个**人、地点和事物**作为我们的实体。此外,我们可以定义实体的属性和角色。
比如一个**人有一个属性名,在一个事件中扮演参与者**的角色。
* 关键字**“sub”**用于指定一个**实体、关系或属性**。
* **实体或关系的属性**使用“**has”**关键字定义。
* 使用关键字**“plays”**定义**角色**。

定义实体
接下来,我们需要定义模式中提到的所有**属性**。定义每个属性时,必须指定属性的数据类型。这可以使用“**数据类型**”关键字来完成。

定义属性
最后,说到人际关系。**关系**定义类似于实体定义。**关系可以有属性,甚至可以扮演角色**。
定义中使用了关键字“ **relates** ”来指定关系连接哪些角色。一个关系可以连接属性、实体甚至关系!
例如,事件关系与角色“ **eventParticipant** ”和“ **eventLocation** ”相关,这两个角色分别由实体 person 和 Location 扮演。
(注意,关系可以连接角色,而不是实体)

定义关系
既然我们已经定义了模式。我们需要把它载入 Grakn。
## **将模式加载到 Grakn 中**
前往您的终端并启动 Grakn 服务器:
grakn server start
现在使用以下命令加载模式:
grakn console -k grakn_example -f schema.gql
这里的 **-k** 自变量代表“**键槽**”。请将密钥空间视为数据库的名称。而这里的 **-f** 则是模式文件的**文件路径**。
## 最终检查
如果您得到如下输出
Successful commit: schema.gql
那么这意味着您的模式已经加载。现在您可以前往 Grakn Workbase 并查看您的模式。它看起来应该有点像这样:

Grakn 模式:(黄色箭头将告诉您每个形状的含义)

解读模式图的简单方法
搞定了。下一步是将数据加载到数据库中。这本身就值得一整篇文章。所以我只能说敬请期待!祝阅读愉快!
链接到以前的博客:
[](/the-graph-epiphany-4050e96ddcf6) [## 图形顿悟
### Graphbits:一堆 5 分钟的文章:都是关于图形的
towardsdatascience.com](/the-graph-epiphany-4050e96ddcf6) [](/the-graph-models-656a0005aa21) [## 图形模型
### Graphbits:一堆关于图形的 5 分钟文章
towardsdatascience.com](/the-graph-models-656a0005aa21)
# 大数据工程师的一天
> 原文:<https://towardsdatascience.com/a-day-in-the-life-of-a-big-data-engineer-a286e4a5ae29?source=collection_archive---------30----------------------->
## 为巴黎的一家广告技术巨头工作
*事实:*我处理大约 **200 PB** 的数据
> 根据 [Gizmodo](https://gizmodo.com/how-large-is-a-petabyte-5309889) :
>
> 1 PB 相当于 2000 万个四屉文件柜,里面装满了文本或大约 13 年的高清电视视频。
>
> 50 PB 是人类有史以来所有语言的全部书面作品

这是我们的数据中心的样子。来自 [Pexels](https://www.pexels.com/photo/interior-of-office-building-325229/?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels) 的[曼纽尔·盖辛格](https://www.pexels.com/@artunchained?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels)的照片
我在早上 7 点醒来
我给自己冲了第一杯咖啡。滚动浏览科技新闻,我启用了电子邮件通知。*你不应该在开始工作前打开电子邮件*,但是我们的数据随时可能发生任何事情,我们必须随时了解情况。
我大约在早上 8:30 到达办公室
还没有人在这里,因为我是空地上最早的鸟儿之一。安顿下来后,我看了看我们的数据监控工具:*资源消耗图、存储条形图、异常警报*。如果数据有问题,我必须检查一下。一些数据可能会丢失或具有不寻常的值。有时数据交易崩溃,我们最终没有数据。万一发生那些不好的事情,我需要第二杯咖啡。

斯蒂芬·道森在 [Unsplash](https://unsplash.com/s/photos/graph?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 拍摄的照片
接下来,我检查我们的**数据调度器**。我们每天摄入数百万亿字节。我们不能手工处理从一个管道到另一个管道的所有数据。我们需要数据调度程序,通过它我们可以执行查询,在数据库之间复制数据,最重要的是,为这些命令设置一个计时器。调度器是数据管道的重要组成部分,数据量超过了人工处理的能力。我们所有的数据调度程序都是内部的,因为我们工程师喜欢手工制作。
AN EXAMPLE INSTRUCTION FOR A SCHEDULER1. Create table if not exists
- Schema:
- Column 1: name + data type
- Column 2: name + data type
- Storage format: text
- Table name: Table A2. SQL query
INSERT INTO Table A
SELECT Column 1, Column 2
FROM Table B
WHERE $CONDITIONS3. Frequency = Daily
我每天早上 **10:30** 和队友开每日例会。*我们互相告诉对方前一天我们做了什么,那天我们要做什么,以及是否有什么阻碍了我们。我们尽量说得简洁,以节省每个人的时间,因为我们讨厌冗长的会议。我发现这些紧凑的聚会很有帮助,因为它保持了每个团队成员之间最少的互动。*
我通过做一些代码审查回到我的日常任务中。*你的编程在融入生产之前需要经过同行的评判*。他们可以批准、拒绝或调整你的一些工作。我意识到,不亲自和某人交谈,很难评估他们的代码。我通常选择来到他们的办公桌前,确保我们达成共识。你不想成为一个 ***【批准荡妇】***——一个总是不审核队友工作就批准他们工作的工程师。用你希望自己的代码被评估的方式来评估他们的代码。

凯文·Ku 在 [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上拍摄的照片
中午,我的团队在公司食堂一起吃午饭。我们聊生活、工作、技术问题。每个人都可以开诚布公地讨论任何事情。我们的午休时间不长,很快我们就聚在厨房里喝另一杯咖啡——这是我的第三杯咖啡。
大约下午 **2 点左右**我又开始了我的软件开发工作。我们数据工程师仍然使用与数据相关的软件。我读取 SQL 查询,在 Hadoop 生态系统中运行测试,验证修改是否不会给存储带来太大压力,最后提交更改。开发可能会因为各种原因而停滞不前:代码无法编译,生产和测试环境不匹配,查询中的拼写错误。我重新倒了一杯咖啡。我数不清了。
下午晚些时候,我通常会接到执行产品发布的要求。我们希望更新表格,刷新查询,或者启动一个全新的管道。在一家专注于工程的公司工作,我很高兴看到我们自动化了每一个软件程序。我只需要按下一些按钮,让脚本处理整个事情。如果一切顺利,我们将有一个新版本的数据系统开始运行。
**下午 6 点**,该收工了。我确保数据调度程序仍按预期运行,监控仪表板中没有警告,没有人抱怨数据丢失或不正确。我们与世界各地的员工合作,所以我不会对半夜收到错误信息感到惊讶。现在,一切似乎都很好,所以我拿起我的电脑和我的同事说再见。

由[礼来朗姆酒](https://unsplash.com/@rumandraisin?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)在 [Unsplash](https://unsplash.com/s/photos/reading-books?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上拍摄的照片
关闭所有与工作相关的通知后,我通过阅读非技术书籍来享受一天的最后一刻,从而结束大数据工程师典型的一天。
# 旧金山数据科学家的一天
> 原文:<https://towardsdatascience.com/a-day-in-the-life-of-a-data-scientist-in-san-francisco-ffe32ca52d20?source=collection_archive---------19----------------------->
## 数据科学家通常在工作中会做些什么?

我在办公桌前的一张有点尴尬的照片
有抱负的数据科学家经常问我两个问题:
* 数据科学家实际上是做什么的?
* 对于数据科学家来说,典型的一天是怎样的?
这些都不是特别容易回答的问题,因为我遇到的每个数据科学家都是不同的。他们喜欢的工作方式反映了这些差异。
此前,我在一家硅谷医疗保健初创公司担任了两年的数据科学家。在这篇文章中,我将特别关注那段经历,让你了解在旧金山做一名数据科学家是什么感觉。那段时间,我是一名医疗保健数据科学家。该公司正在处理一个大型健康保险索赔数据集(数十亿行数据),以帮助人们做出更明智的医疗保健决策。数据科学团队正在创建数据集,用于我们网站上面向用户的产品。
我希望有抱负的数据科学家会发现这个故事很有用,可以让他们更好地了解数据科学家的实际工作。在整个故事中,我还将强调许多我认为对于在初创公司成为一名成功的数据科学家很重要的技能。
# 典型的一天是怎样的?
作为一名数据科学家,有些日子很突出:
* 开始一个新项目
* 推出数据产品
* 参加会议
* 截止日期紧迫的一天
* 新的数据科学团队成员开始工作的那一天
然而,在这两者之间有许多日子遵循着相似的模式,至少对我来说是这样。
这些日子里,我正在进行一个项目,或者可能是几个项目,我需要继续工作。通常,全天会召开会议,与项目负责人和数据科学团队的其他成员进行交流。

我制作了一张我每天时间表的信息图
# 早上 7:00 开始我的一天
我是一个早起的人,所以我通常在 7 点左右起床。我会冲个澡,穿好衣服,在早上 7:30 左右离开家。
当我住在旧金山时,我在米申湾巨人体育场附近有一套公寓。我真的很喜欢那个地方,因为它就在水边。它比旧金山的市区干净得多,闻起来也不像尿。办公室在金融区,离轮渡大楼不远。所以大多数时候我喜欢走路去上班。
# 上午 8:30 一天的第一项任务
当我到达办公室时,通常是早上 8:30 左右。通常有几个其他人已经在那里了,但我几乎总是数据科学团队的第一个人。我的大多数队友都不是早起者,但是我在早上更有效率。
公司允许我们有灵活的工作时间,只要我们参加任何需要我们参加的会议。我的许多同事会在上午 10 点左右进入办公室,然后加班完成工作。我喜欢我们被信任以最适合我们的方式完成任务。
当我打开电脑时,我通常会做的第一件事是检查我整夜运行的代码。我们有一个机器集群,可以用于我们共享的数据科学工作。我们中的许多人会等到晚上才运行计算密集型工作。这样我们就不会让更多的实验性代码在白天运行缓慢。
同时进行两三个项目是我的惯例。这样我就可以进行多任务处理,而不会在等待代码运行时陷入困境。我们必须等待分析完成的时间从几分钟到几天不等,但最常见的是几个小时。如果我改为线性工作,我将不得不花费大量时间闲荡拇指和等待。

[https://imgs.xkcd.com/comics/compiling.png](https://imgs.xkcd.com/comics/compiling.png)
如果我的通宵工作产生了结果,我通常会观察它,看看它是否合理。之后,我会去给自己泡一杯茶,从办公室里的健康零食中抓一些早餐。我从来不喝咖啡,这让我的许多同事很反感😆
一般来说,到那个时候,其他团队的一些人应该已经到了,我经常喜欢在他们喝咖啡的时候和他们聊他们的项目。这种非正式的交流对于了解其他团队的进展和他们正在积极进行的项目非常有帮助。
然后,我会把早餐和茶放在办公桌上,同时检查是否有新的空闲时间或电子邮件需要我立即开始工作或回复。如果没有什么紧急的事情,我会打开一天的工作准备开始。
# 每日站立
当我完成所有的晨间仪式时,通常是起立的时候了。站立会议是敏捷框架的一部分。对我们来说,他们包括简短的日常会议,数据科学团队会站成一圈,告诉小组我们前一天在做什么,我们当天计划做什么,以及我们是否有任何障碍。
有时,我们的站立会议将与其他工程团队结合在一起,特别是当我们一起工作来完成一个项目时。例如,当我们将要发布一个新的数据产品,它将成为网站上的一个功能时,我们需要与产品工程和数据工程团队密切协调,以使其顺利进行,没有延迟。
# 早上的工作
在站立会议之后,我通常会有一段时间可以投入到我当时正在做的事情中。我发现,如果我不在一天中划出大量的时间,人们会一直和我安排会议。这不利于我完成工作,因为我有时发现我需要相当多的时间来让我的头脑进入正确的流程,以便在特别具有挑战性的任务上取得进展。
在那段时间,我也经常戴上我的降噪耳机。耳机可以向你周围的人传递一个信息,那就是你正在集中注意力,不想被打扰。这可能看起来有点粗鲁,但我发现这很有帮助,因为人们知道什么时候可以打断你,什么时候你不希望他们打断你。即使它更多的是一个潜意识的信息。我们工作的办公室是开放式的,每个团队都有很多桌子,所以如果不小心的话,很容易被谈话分散注意力。
因为我是一个早起的人,我会一直计划在这段时间里处理最具挑战性的工作。我总觉得我在午饭前就完成了大部分工作,之后我的效率就大大降低了。所以我想充分利用我的大脑处于最佳工作状态的时间。
在此期间,我主要是写代码。我花了大量时间将数据转换成运行更复杂分析所需的格式。实际上,构建模型并对它们进行查询占用了我的一些时间,但是到目前为止,我工作中最耗时的部分是准备好数据。
幸运的是,我们有优秀的数据工程师,他们为我们的数据提供了高效的 ETL 管道。他们负责维护管道。然而,我们拥有的数据集包含数十亿行,因此找到我们需要的子集并对其进行操作以便运行算法仍然是一项耗时的工作。
因此,当人们说数据科学家的大部分时间都花在数据清理上时,我发现这是真的。尽管由于我们的数据工程师的巨大努力,我们的数据集已经相对干净,但总是有一些特定的方面需要修改。例如,我经常需要将多个诊断列合并成一个,然后为每个唯一值创建一个新的二进制变量。
在我们的办公室,我们有曲柄办公桌,让我们可以坐着或站着。一般来说,我会在早上精力最充沛、腿还不累的时候努力站起来。我发现这种练习对我的背部和颈部非常有益。符合人体工程学的工作站对于长时间使用电脑的人来说非常重要。如果你在工作时照顾好自己的身体,你可以有更长的数据科学家生涯。
# 午饭时间
一天中我最喜欢的时间之一总是午餐时间。我们有可爱的餐饮,全公司都会分享。我们会坐在长桌旁一起吃饭。我曾经有过的一些最好、最有趣的对话都是在午餐时间进行的。
我的许多同事来自技术和软件工程之外的不同背景。我发现听到他们在工作之外做些什么以及他们在过去的职业生涯中做了些什么非常有趣。我的一些同事甚至在业余时间创办了一本科技杂志。与如此有趣的人一起工作是一次有益的经历。
我们会在午餐时间谈论各种话题。我记得有一次关于未被发现的人的特别有趣的对话。我们都非常专注于这次谈话,以至于我们决定放一部关于它的纪录片,让全公司的人在我们的会议大屏幕上观看。
午餐时间是让我的大脑从思考工作中休息一下的好时机。当我不积极思考问题的时候,我经常会有很好的想法来解决问题。因此,我真的很高兴我们没有在办公桌前吃饭,并在午餐时间继续工作。
每周一次,我们会在午餐时间听取公司人员或特邀演讲者的报告。人们会展示他们一直在做的事情,或者他们提出的与我们正在做的工作相关的想法。我认为这是一次很好的实践,因为它让我接触到了其他团队正在使用的不同技术和技巧,否则我永远也不会知道。
当我们必须在会议上展示我们的作品时,这也是一个很好的练习。我认为首先在友好的观众面前测试演示总是一个好主意。
# 会议,会议和更多的会议
我会尽量把大部分会议安排在午饭后。这样我一天中就有了第二大块时间来做我的项目。
我们试图将会议减少到最低限度,但会议蠕变是一个真实的事情。然而,有时他们有必要让每个人都在同一页上,特别是当一个项目跨几个团队运行时。会议的数量有时确实开始增加。我会召开的会议类型包括:
* 与我的主管进行一对一会谈(每周一次)
* 与首席执行官一对一会谈(大约每季度一次)
* 项目启动会议(在项目开始时召开一次)
* 项目进度会议(根据项目需要,通常每周一次)
* 项目后评审(在项目结束时)
* 医疗审查会议(每个项目一次)
* 统计评审会议(每个项目一次)
* 数据科学团队会议(每周)
在这些会议中,我经常需要向不同的利益相关者交流我的分析方法或结果。我认为这对于任何数据科学家来说都是一项非常重要的技能。宣传你的项目,同时承认局限性并准确传达你的发现是很难做好的。然而,这可能是项目成功或失败的区别。
只要有可能,我会边走边谈。我发现走出办公室,在新鲜的空气中让我的血液循环起来是令人振奋的。我还认为,当人们不害怕被偷听时,他们可以更加开放。
我们很幸运,在我们位于金融区的办公地点附近,有许多可爱的地方可以步行。附近有一个公园,有时我们会去那里,在阳光下举行会议。或者再远一点是轮渡大楼,那里经常有市场和街头艺人。能够欣赏旧金山美丽的风景和声音真是太好了。
# 采访未来的数据科学家
在我的一天中,我经常会有面试潜在数据科学团队雇员的任务。我对何时安排面试没有多少发言权,因为面试必须与多个其他团队成员协调。
我喜欢采访。对我来说非常重要的一点是,在数据科学团队中,我们每个人都有发言权。即使我们没有雇用候选人,我通常会发现面试是一个非常积极的经历。我喜欢认识新的人,听他们讲述他们过去做过的项目。
只要有可能,我会向候选人提供反馈。我知道当我面试我的第一个数据科学职位时,我发现这是非常宝贵的。
参加面试小组非常有趣。我在公司工作期间,我们根据资历聘用了全方位的数据科学家。我们雇佣了非常早期的职业数据分析师,还雇佣了数据科学团队的新负责人。在雇佣我未来的老板时,我当然非常关注。我非常幸运地接触到了很多将数据科学作为职业的不同思考方式。
# 下午的工作
和早上一样,我会尽我所能在下午获得一大块不受打扰的时间。整个下午,我经常在办公室四处走动,在沙发上工作,或者在会议室工作,甚至在午餐区工作。
我有时发现,如果我不在座位上,我会少被打扰。风景的改变有时也会给我新的灵感来解决我正在处理的任何问题。
# 一天快结束的时候
接近下班时间时,我常常对我的工作感到非常沮丧,尤其是如果那天工作给我带来麻烦的话。有时我会在离开前和同事聊天,听取汇报,减压。这是我工作过程中的一个重要部分。这是一种非正式的获得反馈的方式,也许是一种用不同的方式看待问题的建议,这是我可能没有想到的。
对我来说,数据科学一直是一个非常协作的过程,尽管大多数实际工作都是你一个人完成的。尽管我们通常会为不同的团队成员准备不同的项目,但我总觉得整个数据科学团队都对我们完成的每个项目做出了贡献。即使只是充当一个传声筒或提供建设性的批评。
下午 5:30 左右,我会结束一天的工作,下班后可能会和朋友去喝一杯。我通常是当天最先离开的人之一,因为我也是最先到达的人之一。我从不担心比别人早离开,因为我们总是被鼓励要平衡工作和生活。
为一家真正重视员工的初创公司工作,而不是把他们嚼碎再吐出来,这种感觉真好。我听说过许多其他科技公司以这种方式利用员工的可怕故事,我非常感激那不是我的经历。
# 结论
我希望您已经发现了这个故事的信息,它让您对数据科学工作中可能涉及的不同类型的事情有了更好的了解。正如我所说的,我的经验绝不是普遍的,但它可以让您深入了解数据科学家除了进行数据分析和设计数据项目之外的一些职责。
除了数据,我的另一个爱好是绘画。你可以在 www.katemarielewis.com 找到我的野生动物艺术
[](/how-i-went-from-zero-coding-skills-to-data-scientist-in-6-months-c2207b65f2f3) [## 我如何在 6 个月内从零编码技能成为数据科学家
### 我用来自学数据科学的 4 个工具没有花一美元
towardsdatascience.com](/how-i-went-from-zero-coding-skills-to-data-scientist-in-6-months-c2207b65f2f3) [](/7-questions-you-should-ask-yourself-before-starting-any-data-science-project-51c29093c641) [## 在开始任何数据科学项目之前,你应该问自己的 7 个问题
### 如何成为一名负责任的数据大师
towardsdatascience.com](/7-questions-you-should-ask-yourself-before-starting-any-data-science-project-51c29093c641)
# 营销分析实习生的一天
> 原文:<https://towardsdatascience.com/a-day-in-the-life-of-a-marketing-analytics-intern-2bed4d11d30f?source=collection_archive---------37----------------------->
## 实习/营销分析
## 营销分析的日常观察

[来源](https://www.pexels.com/photo/analytics-blur-business-close-up-590045/)
“营销分析的日常工作到底是什么样的?”。作为达拉斯-沃斯堡地区一家公司的营销自动化和分析实习生,我的暑期实习已经过半。我有很多同事问我这到底是什么样的,因为他们中的许多人取消了实习或转向了在线形式。
我在这次实习中获得的技能令人惊叹!然而,我事先做了很多研究,老实说,我没有找到太多关于日常运营中营销分析的信息。我喜欢和我的同龄人谈论我的经历,然而,我想把我的经历放在一个平台上,让更多对它感兴趣的人可以亲眼看到,并展示从我一天的开始到结束是什么样子的。所以,让我们准备好醒来吧!
*免责声明:我不是全职营销分析专家,我只是简单地转述我的所见所闻。这并不意味着教你所有营销分析中使用的技巧和工具,因为我还在学习。如需了解此信息,请查看* [*走向数据科学*](https://towardsdatascience.com/) *。如果你对营销分析实习生或初级职位感兴趣,请继续阅读!*
# 早上 6:15:起床,准备好
我通常会在工作日之前的早上 6:15 左右醒来。这给了我大约一个小时的时间来阅读其他优秀作家的中型文章,并给了我一些小的、可管理的学习内容!除了我们都做的基本的早晨例行公事之外,我还泡了一杯咖啡,因为这是一个需要你在一天的大部分时间里进行批判性思考的角色,我保证你会在某个时候累的!喝了些咖啡后,我换好衣服,收拾好行李,去上班了!
# **上午 7:45:通过大门和清晨活动**
我走进门,找到我的办公桌,准备开始一天的工作!这是我在一天开始时做的几件事:
* 查看来自不同利益相关者和团队成员的电子邮件
* 查看我当天的日历,留意即将到来的会议和电话
* 检查我的团队研究项目的调查结果
* 花些时间向终身市场分析师学习
在新冠肺炎,电子邮件和视频通话现在是主要的沟通方式,即使是在办公室里。我们被要求戴上口罩,保持社交距离,但如果可能的话,我们也会尽最大努力坚持使用电子邮件和视频通话。在这个夏天,实习生们会有两个主要的项目,一个是团队项目,你可以针对高管团队给你的问题提出一个解决方案,另一个是你自己做一个项目,然后提交给你的部门,在我的案例中,这个部门就是市场部。我也总是试着花一些时间和市场分析师在一起,看他解决问题,以及他是如何解决问题的。
# **上午 9:00:Python 和分析实践**
在我为一天做好准备后,我通常会花一些时间练习我的 Python 和分析技能,将它们应用到营销分析师给我的数据集。这不是针对客户或利益相关者的,而是巩固我那天早上从营销分析师那里学到的东西的一种方式。我可能会使用 sklearn 构建一个线性回归模型,尝试使用 Pandas 提高我的数据清理效率,或者使用 matplotlib 创建快速可视化。我注意到的是,你如何完成工作并不重要。在我的左边屏幕打开 Stack Overflow,在我的右边打开 Jupyter 笔记本,这是完全可以接受的。我发现分析师总是在做许多不同的项目,知道如何在你的代码中变得高效是你在实习或初级职位中需要改进的技能。
# 上午 10:00:实习生活动
通常在上午,所有的实习生将通过一个 Zoom 电话会议,或者一个允许社交距离的非常大的会议室见面,并听取公司内部不同的发言者。这些演讲者通常是副总裁或高级副总裁,他们将讲述自己的经历,提供建议,并留出提问时间。对于一个入门级的职位,一天的下一部分通常会在这个时候开始!
# **上午 11 点:项目工作**
午饭前我要做的最后一件事是开始做我的项目。这是我珍惜的时间,因为我发现分析师有很多会议和其他业务要参加,当你坐下来分析你喜欢的项目时,这是一天中非常平静的一部分!今天这段时间,我开始使用 CRISP-DM 方法为我的部门演示整理项目计划。我研究了我的项目如何对组织有价值,我将如何与营销分析师合作从我们的自动化工具中提取数据,以及确保我按时完成项目的时间表。
# 中午 12:30:午餐!
我们赶上吃午饭了!我在这篇文章中包括了这一部分,因为午餐是一天中唯一可以休息的时间。作为一名营销分析实习生节奏非常快,因为我们在学习、倾听,同时也在做自己的项目。午餐也是在轻松的环境中与其他实习生见面的好时机。这个项目中的许多实习生变得很亲密,因为我们真的在午餐时间建立了关系!
# 下午 1:30:与实习生项目团队接触
当我吃完午饭回来时,有时我会做项目,但大多数时候,我会和我的实习生项目组的一个或多个成员接触。今天,我们完成了准备好调查数据供我分析的最后步骤。我们还讨论了我们希望如何展示我们的数据,我们一眼就发现了哪些有趣的东西,以及我们如何交流我们发现的数据。
# 下午 2:30:其他项目工作
我要做的下一件事是花更多的时间在我的个人项目上。在这个阶段,我花更多的时间在项目的后期,而不是早期。我尽量把上午的时间花在计划和执行前期任务上,比如提取和清理数据,把下午的时间花在后期任务上,比如分析和记录我的工作。我这样做是因为我个人在早上有更多的精力,可以在更长的时间里做更高层次的思考任务,比如计划和清洁,而不是在下午。作为一名实习生,我还将帮助完成营销自动化团队需要完成的任何其他浮动任务。这可能是任何事情,从拉基本报告,修复电子邮件活动,或采取一些工作,从营销分析师,让他们可以喘口气。
# 下午 3:30:营销自动化会议
营销自动化通常会在傍晚开会,所以这是我们召开战略或分析会议的时候。今天,我们开会讨论了活跃率非常低的用户,以及我们如何进一步吸引他们,让他们与我们的内容互动。我们通常会让营销自动化经理、营销分析师、营销策略师和我一起讨论解决问题的方法。
# 下午 4:30:一天任务结束
在一天工作结束时,我通常会检查最后一分钟的电子邮件,检查我的同事,并为第二天制定一个计划。作为一名营销分析实习生,或者实际上任何一名分析师,一个重要的细节是,你几乎不会有和前一天一样的一天。在我实习的公司,整个 60 人的部门只有一名营销分析师。他从事从内容分析、电子邮件性能、社交媒体参与或新产品战略的所有工作。在一天结束时花些时间来计划下一天是至关重要的!
# 下午 6:00:下班后任务
下班回来后,我通常会花一些额外的时间来提高自己的个人分析技能。这时,我将尝试学习不同语言和工具的新部分,例如学习新的 Python 包或 SQL 函数,阅读其他媒体作者的新建模工具,或者学习新的数学理论以帮助更好地理解我所做的工作。
# 晚上 7 点:自由活动时间!
在我完成我的个人工作后,我会在晚上的剩余时间放松或参加休闲活动。与普遍的看法相反,做一名营销分析师需要的创造力和分析能力一样多。让你的大脑休息一下对保持创造力流动很重要!
如果这有帮助,请让我知道!我真的很喜欢写关于数据的文章,我很想再写一篇文章,谈谈我从技术角度学到的一些关键知识,如果你想进入入门级营销分析职位或实习,你应该知道什么,如何抓住实习机会,等等!大家注意安全,祝你们有美好的一天!
若要联系我或接收更多内容,请在 Twitter 上关注我@[*BMNAnalytics*](https://twitter.com/BMNAnalytics)*!*
# 一位决策科学家给新冠肺炎的十大禁忌
> 原文:<https://towardsdatascience.com/a-decision-scientists-10-dos-don-ts-for-covid-19-805577bccd67?source=collection_archive---------25----------------------->
## 在疫情期间,照顾好你的大脑,聪明对待数据,做出更明智的决定

如果你最喜欢的新零食是新冠肺炎更新,这里有一些提示可以帮助你在大量错误信息中保持漂浮。(你在期待洗手的提示吗?这是一份非常不同的清单。)
> 提高你对新冠肺炎错误信息的抵抗力。
无论你是在分析病毒数据,制定战略决策,还是只是在社交媒体上大吃大喝,这都是为你准备的;我写的每一篇链接文章都是为了取悦初学者和专家。你可以把它想象成一次与这些天特别相关的主题之旅。
***作者简介:*** *By day,*[*Cassie Kozyrkov*](https://bit.ly/decisionleader)*leads*[*决策智能*](http://bit.ly/quaesita_di) *at Google。晚上,她写关于数据科学的博客供你娱乐。*

# 不要
1. 不要混淆数据和客观事实。[【更多】](http://bit.ly/quaesita_hist)
2. 别忘了你的大脑看到的都是假图案。【[更多】](http://bit.ly/quaesita_inkblot)
3. 不要成为确认偏见的受害者。[【更多】](http://bit.ly/quaesita_confirmation)
4. 不要忽视结论背后的假设。[【更多】](https://twitter.com/quaesita/status/1247888569386983426)
5. 不要指望人工智能能神奇地拯救世界。[【更多】](http://bit.ly/quaesita_fad)
6. 不要把分析性的“见解”看得太重。[【更多】](http://bit.ly/quaesita_versus)
7. 不要假设每个人衡量事物的方式都一样。【[更多](http://bit.ly/quaesita_dmguide2)】
8. 不要拿苹果和橘子比较。[【更多】](http://bit.ly/quaesita_tiger)
9. 不要盲目相信数据模型和预测。[【更多】](http://bit.ly/quaesita_fault)
10. 不要忽视领域知识的重要性。【[更多](http://bit.ly/quaesita_covidappendix)】
# 磁盘操作系统
1. 对于重要的决策,一定要遵循一个结构化的流程。【[更多](http://bit.ly/quaesita_covid)
2. 一定要考虑你的默认行为。[【更多】](http://bit.ly/quaesita_damnedlies)
3. 在查看数据之前,一定要设定决策标准。[【更多】](http://bit.ly/quaesita_inspired)
4. 一定要检查你是否理解统计学的基本逻辑。【[更多](http://bit.ly/quaesita_statistics)
5. 一定要仔细选择你的人口。[【更多】](http://bit.ly/quaesita_incompm2)
6. 一定要思考这些数据是从哪里来的。[【更多】](http://bit.ly/quaesita_provenance)
7. 在解释不是你自己收集的数据时一定要小心。[【更多】](http://bit.ly/quaesita_notyours)
8. 一定要坚持数据拆分。[【更多】](http://bit.ly/quaesita_sydd)
9. 一定要让自己了解偏见。[【更多】](http://bit.ly/quaesita_bias)
10. 一定要原谅自己觉得暧昧有压力。[【更多】](http://bit.ly/quaesita_ellsberg)
> 如果您发现此信息有帮助,请与其他人分享。
# 现在是完全不同的东西…
感谢阅读!如果你在这里玩得开心,并且对人工智能感兴趣,这里有一个初学者友好的介绍供你娱乐:
在这里欣赏整个课程播放列表:[bit.ly/machinefriend](http://bit.ly/machinefriend)
# 与凯西·科兹尔科夫联系
让我们做朋友吧!你可以在[推特](https://twitter.com/quaesita)、 [YouTube](https://www.youtube.com/channel/UCbOX--VOebPe-MMRkatFRxw) 和 [LinkedIn](https://www.linkedin.com/in/kozyrkov/) 上找到我。有兴趣让我在你的活动上发言吗?用[这个表格](http://bit.ly/makecassietalk)联系。
# 俄罗斯推特巨魔深度剖析
> 原文:<https://towardsdatascience.com/a-deep-analysis-of-russian-trolls-with-apache-pinot-and-superset-590c8c4d1843?source=collection_archive---------30----------------------->

俄罗斯虚假信息背后的历史是一个密集和不断发展的主题。世界上最好的研究似乎还没有触及主流,这使得这成为一个绝佳的机会,看看我是否可以使用一些开源工具来展示新的分析证据。
可供研究人员使用的首个数据集有很长的历史。来自克莱姆森大学的研究人员达伦·林威尔和 T2 的帕特里克·沃伦发布了一个数据集,其中包含来自爱尔兰共和军的 2848 个虚假账户网络的 2973371 条推文。这些年来,达伦和帕特里克在这个主题上增加了非凡的深度,以帮助监控和解决[在社交媒体平台上的外国恶意影响](https://www.law.cornell.edu/uscode/text/50/3059)。
> “本质上,如果整个民主世界的安全机构和政治行为者要在未来发现并阻止此类行动,关键是我们要了解此类战略性社交媒体活动的模式,并在它出现时开发出抵制它的工具。”
>
> [*“俄罗斯人在黑我的大脑!”*](https://www.sciencedirect.com/science/article/pii/S074756321930202X?dgcid=coauthor)
>
> *—达伦·林威尔、帕特里克·沃伦、布兰登·博特赖特和威尔·格兰特*
大数据集由克莱姆森的研究人员发布,并通过 GitHub 上的 [FiveThirtyEight](https://github.com/fivethirtyeight/russian-troll-tweets) 开源。您可以在 [git 存储库上阅读更多关于数据集背后的历史和模式信息。](https://github.com/fivethirtyeight/russian-troll-tweets)
## 开源仓库
在这篇博客文章中,我将向您展示如何使用 [Apache Pinot](https://pinot.apache.org) 和 [Superset](https://superset.apache.org/) 来分析由 FiveThirtyEight 开源的互联网研究机构(IRA)发布的 300 万条推文。
为了启动并运行我在这篇博文中讨论的示例项目,请访问我的开源存储库,获取引导程序配方。
[https://github.com/kbastani/russian-troll-analysis](https://github.com/kbastani/russian-troll-analysis)
# 分析数据集
要对数百万条推文进行高效的实时探索性分析,需要一个专门为此设计的快速数据存储。Apache Pinot 提供了后端查询功能,使我能够进行这项研究。更进一步,我需要一个工具在 Pinot 上创建图表和仪表板,Apache Superset 在这方面扮演了一个完美的角色。
我的分析始于一些基于我之前对这个主题的研究的基本假设。首先,我想从现有的观点后退一步,即巨魔利用策略来影响预期的选举结果。这种假设是臭名昭著的,可能导致了 2016 年后新闻媒体和国会议员政治化的复杂调查。
所以,我对自己说,如果利用社交媒体干预选举在技术上是不可能的呢?
## 探索数据
将原始数据加载到 Apache Pinot 后,第一步是验证最初由 FiveThirtyEight 于 2018 年提供的[分析。他们展示的第一个图表是一个简单的活动视图,试图显示 2016 年可能的选举干扰。](https://fivethirtyeight.com/features/why-were-sharing-3-million-russian-troll-tweets/)

图片由[达伦·林维尔](https://www.clemson.edu/cbshs/faculty-staff/profiles/darrenl)和[帕特里克·沃伦](http://pwarren.people.clemson.edu/)拍摄
为了验证我有相同的数据集,我使用 Pinot 和 Superset 生成了一个 SQL 查询和可视化。

2015 年至 2018 年俄罗斯巨魔推文活动
在验证了我的查询与克莱姆森研究人员的图表匹配之后,我进一步了解了数据集中的其他特征。

图片由[达伦·林威尔](https://www.clemson.edu/cbshs/faculty-staff/profiles/darrenl)和[帕特里克·沃伦](http://pwarren.people.clemson.edu/) |来自 [FiveThirtyEight](https://fivethirtyeight.com/features/why-were-sharing-3-million-russian-troll-tweets/)
上图显示了克莱姆森研究人员为分类虚假爱尔兰共和军账户的意图和行为所做的大量工作。对我来说,这种数据观点打破了选举干预的假设。Twitter 是一个复杂的行动和反应的动态系统,它发生得如此之快,以至于很难让这个系统达到任何预期的结果。
我决定开发一个图表,更容易地讲述数据集中不同类型 Twitter 账户的行为。

按标签账户类别分类的俄罗斯 Troll Twitter 活动
我想出的图表平滑了“五个三十八”可视化中显示的活动。这里我们看到,2015 年以来有尖峰活动,可能与选举干预无关。我需要看到的是每一个尖峰的叙述。我认为,看看主流新闻媒体中的特定话题或主题是否解释了这些飙升,可能会有所帮助。

俄罗斯巨魔与福克斯新闻频道有关的推特活动
上面的图表显示了与福克斯新闻频道相关的所有提及。这个查询显示了一些有趣的峰值活动,所以我决定查看 2015 年 6 月 10 日福克斯新闻频道的头条。

[https://web . archive . org/web/20150610010931/http://www . fox news . com/](https://web.archive.org/web/20150610010931/http://www.foxnews.com/)
这个结果让我震惊的是,它与 2020 年 5 月乔治·弗洛伊德(George Floyd)悲惨去世后的叙述惊人地相似。为了了解这个关于 Twitter 数据集的特别标题是否有什么意义,我决定将福克斯新闻频道与其他新闻媒体进行比较。

[https://web . archive . org/web/20150610080013/http://www . CNN . com/](https://web.archive.org/web/20150610080013/http://www.cnn.com/)
上面是 CNN 网站截图,几个小时前福克斯新闻频道报道了他们的标题。这两个网站在新闻报道上的最大区别是,福克斯新闻频道在爱尔兰共和军的推文中使用了叙述性术语,而 CNN 没有。虽然这只是一个数据点,但我需要了解叙事是否推动了新闻周期,反之亦然。哪个先出现,新闻报道是如何随着时间的推移而变化的?
下面的图表显示了警察和种族不公正作为一个叙事开始的起源事件。我用来过滤结果的查询是基于相关性的搜索,使用的是福克斯新闻频道网站 6 月 10 日头条中的关键词。Apache Pinot 有一个基于 Apache Lucene 的全文索引实现,它允许我返回与我的查询相关的结果。

使用 FoxNews.com 标题的基于文本的搜索:“一个德克萨斯白人警察拍摄了摔跤…
在这里,我们看到了 2015 年 6 月 10 日围绕种族不公正和警察的叙事有一个明确的起源事件。故事从右翼巨魔控制的尖峰活动开始。在这些蓝色的尖峰之间,我们有左侧巨魔的持续活动。最后的尖峰,再次被右巨魔所控制。

与白人至上和警察有关的 Twitter 巨魔活动
在对数据进行平滑处理后,我能够看到图表中最大的峰值是 2017 年 8 月的整个月。我使用 Wayback 机器检查了那个月的新闻标题,并将这些叙述与 2015 年 6 月的正确巨魔叙述进行了比较。

[https://web . archive . org/web/20170813011501/http://www . fox news . com/](https://web.archive.org/web/20170813011501/http://www.foxnews.com/)
新闻媒体的叙述现在与两年前的意识形态内容完全一致。一贯的主题?恐怖、恐惧、愤怒和愤慨。

[https://web . archive . org/web/20170813011501/http://www . CNN . com/](https://web.archive.org/web/20170813011501/http://www.cnn.com/)
在这一点上,我的收获是,爱尔兰共和军数据集中的有毒意识形态和短语在最近的新闻媒体标题中变得普遍。为了理解意识形态和叙事是如何演变的,我决定使用来自开源的命名实体识别来丰富原始数据集[斯坦福 CoreNLP 库](https://stanfordnlp.github.io/CoreNLP/)。
# 命名实体识别
要进一步理解爱尔兰共和军推文的语义内容和叙述,需要基于时间序列的自然语言处理。理想情况下,我想避免将时间序列图表的内容与单个 tweet 相关联,而是与所有 tweet 中包含的文本实体相关联。
Stanford NLP 项目提供了一个基于 JDK 的库,用于执行[命名实体识别(NER)](https://nlp.stanford.edu/software/CRF-NER.html) 。我过去在 tweets 上使用过这个库,它运行得相当好。

上面的图表显示了包含特定类别的命名实体的推文数量。
下一个图表显示了属于每个类别的不同实体名称的数量。对于这个图表,我已经过滤掉了`handle`和`url`,它们与理解假账背后的不同叙述无关。

既然我们已经对实体和类别的分布有了相当好的理解,我们可以开始看看每个类别包含什么。具体来说,我们想看看对不同虚假账户的叙述进行分类的命名实体。
# 人
该图表包含了个人实体的虚假账户类别的推文数量。

# 组织
该图表包含了组织实体的虚假账户类别的推文数量。

# 刑事指控
这张图表包含了因刑事指控而被分类的虚假账户的推文数量。

# 死亡原因
这张图表包含了死亡原因的虚假账户类别的推文数量。

# 多方面的
这个图表包含了各种实体的虚假账户的推文数量。

# 标题
该图表包含了代表不同头衔的实体的虚假账户类别的推文数量。

# 意识形态
这张图表包含了意识形态类虚假账户的推文数量。

# 意识形态时间序列
这个图表是一个时间序列,显示了推文中提到的意识形态的平滑分布。

# 右翼巨魔意识形态
下一张图表显示了正确的巨魔账户所使用的意识形态。

# 左翼巨魔意识形态
这张图表显示了左巨魔账户的意识形态。

# 得出结论
爱尔兰共和军有没有可能成功干涉了美国的选举?要回答这个问题,我觉得有必要了解一下*选举干预*是什么意思。
## 什么是选举干预?
*选举干预*是一个模糊的政治术语,政客使用时几乎没有法律效力。[然而,外国恶意影响](https://www.law.cornell.edu/uscode/text/50/3059)是一个描述民族国家资助的用来影响选民舆论的活动的术语。当外国试图影响公众舆论,以及选举的选民时,这是一个国家安全问题。
现在, ***国内选举干涉*** 呢?
*国内选举干预*是一个完全虚构的术语,大致翻译为“*为政治候选人竞选*”只要政客们遵守竞选财务法,不参与任何形式的选举舞弊,他们就可以自由地干预选举,而无需承担国内的法律责任。我能找到的唯一例外是社交媒体上的政治言论对国家安全或公共安全构成威胁。
**爱尔兰共和军在推特上的活动是否干预了美国选举?**
当然,但不是因为大多数人认为的原因。在广泛分析这些推文后,我很清楚选举干预不是重点。相反,这三百万条推文的目的是放大恐怖、愤怒、恐惧,并在公共广场上制造不和。这些推文造成的损害是任何人都无法断定他们的最终目标是什么。仅仅通读这些推文就会向读者反映他们在练习前持有的任何偏见或结论。
社交媒体真正的危险是混乱的迷雾,让人相信没有人说真话。事实上,我认为可能没有简单的真相,或者对于那些知道真相的人来说,没有简单的解释。
政党成员之间确实存在美德信号,但这并不新鲜。Twitter 可能会放大这种效应,一些政治家可能会发现自己通过发出个人叙事信号而具有不成比例的影响力。政治家们应该明白,在激烈的政治竞选中,发出分裂的美德信号是有代价的。
Twitter 对信任其订阅源的用户有着过多的控制。毕竟,我们是群居动物。Twitter 给了我们空间,让我们更好地理解如何认同我们的群体,比如迷因和美德信号。美德信号往往会获得更多的喜欢、转发和追随者。
一个群体的行为会以这样或那样的方式影响每个人,在 Twitter 上,没有人能免受恶意影响。美德信号是保持群体内部界限的关键,这一观点似乎滋生了不良影响。通过引入在意识形态上与 Twitter 用户的内部群体对立的虚假外部群体,该群体的影响者屈服于更极端形式的美德,向他们的追随者发出信号。这是我认为 2015 年多米诺骨牌开始倒下的地方。
# 解决问题
那么,我们如何通过美德信号阻止恶意影响者传播有毒或极端的意识形态叙事呢?我认为如果不对数字美德信号背后的心理学进行更多的研究,我们就做不到。恶意的影响者只需要找到一种方法进入群体中善意成员的饲料中。转发和点赞都容易受到这种影响,只需要一个你信任的人就能在整个群体中传播恶意影响。
至于解决办法?
我认为在 Twitter 上解决这个问题需要减少转发量的放大,重新思考推荐算法。话题应该集中在美德信号的非政治来源,而不是建立在恐惧、愤怒或愤慨上的。这不是一个容易解决的问题,我希望随着 Twitter 的发展,看到更多的数据和研究。
## 最后的想法
我希望这篇文章有趣,对读者有帮助。如果您有任何反馈、意见、更正或建议,请随时在这里或通过 [Twitter](https://www.twitter.com/kennybastani) 联系我。我鼓励那些足够勇敢的人去探索我整理的开源项目,它将允许你复制我的发现,并对数据进行你自己的分析。
这对我来说是一个充满激情的话题,我希望对你也是如此。我不遗余力地让设置您自己的分析环境变得尽可能容易。
为了启动并运行我在这篇博文中讨论的示例项目,请访问我的开源存储库,获取引导程序配方。
https://github.com/kbastani/russian-troll-analysis
## 特别感谢
特别感谢 [Apache Pinot](https://pinot.apache.org) 社区的人们对本文的反馈。此外,感谢 [Darren Linvill](https://www.clemson.edu/cbshs/faculty-staff/profiles/darrenl) 和 [Patrick Warren、](http://pwarren.people.clemson.edu/)以及其他致力于让决策者了解外国对社交媒体的恶意影响的人。
# 深入探究区块链
> 原文:<https://towardsdatascience.com/a-deep-dive-into-blockchain-d1eb753fb74c?source=collection_archive---------16----------------------->
## 你需要知道的关于这项成长中的技术的一切

# 你信任我吗?😈
我们整个社会都建立在信任之上。你相信你的老板会付你钱。你相信政府会保证你的安全。你相信你的银行不会偷你的钱然后逃跑。**我们盲目地信任如此多的机构和人,却毫不犹豫。**
但是如果发生了什么呢?你的老板不给你发工资。政府垮台了。你的银行把你所有的钱投入股市,股市崩盘,导致你失去所有的积蓄(咳咳…2008 年股市崩盘)。这些可怕的事情似乎不可能发生。但事实是,信任是支撑这些系统的唯一东西。信任让你变得脆弱,易受伤害,但你依赖这些系统。你必须信任政府、银行和机构,因为别无选择。嗯,在**区块链出现之前,一直没有替代方案,区块链旨在创建一个不依赖信任的系统。**所以你不必相信你的银行会卷走你的钱。你不必相信你的政府会垮台。
你可能会问自己,‘区块链似乎很神奇!它是如何工作的?这真的很神奇,但是**要深入了解区块链是如何运作的,以及如何被用来扰乱当前的系统,你首先必须了解当前的机构是如何运作的。**
# **集权的问题🌐**
假设你想给你在世界另一端的朋友寄钱。你不会给他们寄支票或现金。那会花太长时间。相反,你可以通过 Paypal 或银行的电子转账系统汇款。快速且易于访问…对吗?不对。您的银行需要确认从该账户中流出的钱是您的,并且您授权了支付。然后,他们需要确认你把钱汇给了一个可靠的来源,这可能需要你事先授权。但是在你知道之前,你的朋友刚刚收到了 100 美元,而你支付了额外的 10 美元手续费。
银行或机构促进转账的想法就是集中化的想法。所有的东西都经过它们,然后从两边出来。他们看到了一切,没有人可以访问你的文件。在很大程度上,这个系统是有效的,我们作为一个社会非常依赖它。但是,有几个问题出现了。
漏洞——由于所有东西都隐藏在一个“安全”的数据库中,这使得每个人的信息都很容易受到攻击。只需一次数据库泄露,你所有的信用卡信息就会被泄露。我们一次又一次地看到大公司突然遭到黑客攻击。这发生在易贝、Adobe、Canva 和其他著名的大公司身上。
费用和财务激励——和其他公司一样,促进转账的机构也想赚钱。他们通常通过在服务中增加手续费来做到这一点。你没有真正的选择,因为你可能会依赖这些机构。
权力不稳定——如果只有少数公司促进我们社会需要的所有转移,那么**就给了那些公司很大的权力。**他们可以改变系统,产生难以形容的影响。现在你的银行改变系统的可能性非常小。事实上,他们有能力做到这一点,这是非常可怕的。他们可以利用自己的地位,这一点以前已经做到了。
实施缓慢——如果公司服务的某一部分对一部分人产生了负面影响,那么解决这个问题最多需要几个月的时间**。**这是因为大公司内部漫长的官僚程序。重大的改变需要很长的时间,这真的伤害了那些需要立即改变的人。
所有,我是说所有这些问题都是用区块链的想法解决的。你可能已经猜到了,区块链运行在中央集权制度的对立面。区块链是分散的,拥有许多对人们非常有利的属性。区块链是这样工作的。
# **区块链的基础:转移的新观点💻**
区块链是一个分散的点对点传输系统。没有人控制区块链,但它无限期地运行着。一件事怎么去中心化?这意味着每个人都帮助运行区块链。技术上来说,你创造了区块链。区块链运行在一个单一的概念上,在一个区块中,这些区块被链接在一起,因此区块链。
## *块+链:*
块在其中存储一条信息或数据。这些可能是交易、信息或任何东西。该块与散列相关联,散列是由特殊加密函数创建的唯一字符串。每个散列都是唯一的,有点像块的 id。每个块还包含前一个块的散列,这就是被链接在一起的想法的来源。每个块引用最后一个散列,依此类推。
## *如何创建块:*
在将块添加到当前区块链之前,需要对其进行验证。交易需要被核实,以确保一切都检查出来。通常的做法是通过工作证明。人们需要通过解决一个非常难的数学问题来验证该块是合法的,通常是用计算机来完成。但是谁会愿意放弃他们宝贵的计算机能力去创造一个新的街区呢?这种激励通常是区块链会用少量的钱奖励验证该块的用户。这就是比特币和以太坊的工作方式,验证这些区块的人被称为矿工。他们被称为矿工,因为他们通过他们的计算机能力挖掘这些钱。大多数人第一次听说区块链和这个概念是通过采矿的概念,但这可能会产生误导。我将在文章的后面更多地讨论挖掘。
## *公共总账:*
任何人都可以访问区块链,任何人都可以查看任何特定的街区。这种透明性使得区块链与正常的中央集权体制如此不同。在集中式系统中,只有公司或机构有权访问分类账。通过公开账本,每个人都可以监控链条的健康状况,看看是否有人试图做什么见不得人的事。
## *哈希依赖:*
理解散列依赖于块的内容是很重要的。内容的微小变化都会极大地改变散列。由于这种依赖性以及每个人都有权查看区块链的事实,这使得系统不可攻击。这是因为如果有人为了自己的利益改变块的内容,它将改变散列,并且它前面的块将不会匹配相同的散列。这样,区块链可以很容易地识别变化。

## *块可以容纳什么数据?*
这个想法是任何东西都可以嵌入到这些块中。最大的例子是货币转移,其中一个块保存显示用户之间货币转移的信息。但更酷的应用包括不动产证明、某些物品的证明,甚至是药品。
## *通过协议自行运行:*
一旦区块链启动,它将永远自行运行。它不需要任何人看管。如果有足够多的矿工和事务,它将继续工作。这是因为它由一个协议运行,本质上存在于每个人的计算机上。除非互联网本身消亡,否则区块链也会消亡。
这些是每个区块链的基本属性。但是随着技术的发展,新的属性将会出现…
# **✔️区块链的额外(但有用)特性**
如果区块链的最低要求都能满足,那么任何额外的东西都可以添加进去。许多区块链大公司创造了很酷的功能,让更多的人使用他们的区块链。区块链的一些值得注意的额外属性包括:
## *智能合约:*
智能合约可能是区块链最受欢迎的功能之一,它允许人们之间进行几乎任何交易。它本质上就像一个真实的合同,但由协议强制执行,一旦创建,就不可逆转。它概述了协议验证和促进双方贸易的要求。例如,如果我想创建一个智能合同,为我向雇主提供的每一小时的工作支付报酬,我的雇主和我可以创建一个智能合同,并使用传感器来跟踪我的工作时间。我每做一个小时,协议就会自动从他的账户里取出 X 美元,放到我的账户里。智能合约可以做很多事情,这也是它们如此酷的原因。
## *分叉:*
区块链并不完全安全。有时候,黑客会在区块链上获取你的账户信息,然后偷走你所有的东西。这种情况时有发生,但通常是账户所有人的错。通常只是很小的一笔钱,但如果黑客窃取了数百万美元,那就太可怕了。谢天谢地,有办法找回钱。分叉区块链意味着返回到某个时间点的某个块,并从该块重新开始所有操作。就像什么都没发生过一样。但是分叉只有在区块链上 51%(或者大多数)的用户想要分叉的时候才会发生。这使得区块链的权力掌握在集体手中,使其成为一个更加民主化的体系。
## *物价稳定:*
一些有货币的区块链正在试验价格稳定系统,这实质上意味着他们的硬币的价值是不变的。公司通过创建一个协议来匹配流通中的硬币数量,并将其保存在一个私人银行账户中。任何时候硬币增值,他们可以立即添加更多的硬币,反之亦然。美元硬币是以美元为基础的,通常价值为 1 美元。这使得加密货币更加可靠和易于使用。
## 不同程度的权力下放:
许多公司正在创建区块链,它们的分权程度较低,而集权程度更高。例如,他们可能拥有除公共分类账之外的所有基本区块链属性,使其更像一个中央系统。有时,一个更加集权的区块链可能会更好,这取决于区块链的用途。
## *区块链的类型:*
有三种类型的区块链,都有其独特的优势和劣势。3 种类型的区块链是:公共,私人和财团。他们都以不同的方式工作,但或多或少仍然是分散的。

还有很多,但这些是最著名的一些。
# **区块链的应用**📝
区块链的应用是无穷无尽的。它几乎可以用于任何事情。以下是我想到的一些最酷的区块链应用。
## *加密货币*
我不能写一篇关于区块链的文章而不提到加密货币。第一个区块链是基于一种加密货币,也是其中最著名的区块链,比特币。加密货币是一种可以通过点对点区块链交易的货币。它使用了区块链的所有基本原理,理论上是最容易创建的区块链。有超过数千种加密货币。
## *太阳能币*
SolarCoin 是一种能源交易区块链与货币。人们可以根据商定的价格,用他们拥有的能量换取别人的太阳能硬币。它使用智能合约来促进贸易。
## *物品确认*
所有权证明也是区块链被使用的另一种令人兴奋的方式。人们可以拥有验证某个项目的 id。它可以代表一件珠宝,甚至是一所房子的契约。这些 id 可以在人与人之间交易,随后是物品本身。
## *Wifi 共享*
像 HotSpot 和 Helium 这样的公司正在创建区块链,在那里人们可以通过付费来共享 wifi。费率通常较低,并且在适用时使用智能合同。
# **区块链的挑战(及解决方案)**
即使区块链技术可以用于一些非常酷的应用,仍然有各种各样的事情阻止区块链成为最佳选择。
## *速度*
在促进用户之间的交易方面,区块链的速度是出了名的慢。比特币转账的平均时间为每笔交易 10 分钟左右。考虑到中央银行做同样的事情所花费的时间,这个速度慢得令人难以置信。
这个问题的解决方案是在用户之间创建一个照明网络。如果两个用户一致认为他们都是可信任的,他们可以在他们之间创建一个直接的链接,而不需要区块链来验证。比特币已经开始实现类似这样的东西了。
## *内存问题*
存储有关交易的所有信息会占用大量数据和空间。如果每个人都需要区块链的副本,那么使用该协议就不可行。
解决方案是在 X 年后自动删除链条中最老的部分。这样,链条就可以一直有一个固定的长度,并且会无限地运行下去。
## *非法使用*
由于许多区块链是匿名的,许多人使用加密货币和区块链作为转移非法物品资金的一种方式。黑暗网络专门使用区块链进行交易
解决这个问题的方法是创建不匿名的区块链。这些将被视为私人链,并会导致更大的透明度。
## 电力使用效率低下
当每个人在挖掘时都试图解决一个加密哈希函数时,有时多个用户会试图解决同一个函数,导致电力的低效使用。
这个问题的解决方案是为挖掘创建一个新的协议。有人提出了股权证明协议,人们出价硬币(但实际上不会输掉)来开采某个区块。
# 关键要点
* 区块链是一个分散的系统,而大多数机构是集中的
* 区块链由包含数据并链接在一起的块组成
* 哈希函数用于加密数据块
* 区块链可用于在两方或多方之间转移项目
* 区块链面临着许多挑战,但也有新的创新解决方案使这项技术更加可行。
# Hough 变换在车道检测中的应用
> 原文:<https://towardsdatascience.com/a-deep-dive-into-lane-detection-with-hough-transform-8f90fdd1322f?source=collection_archive---------7----------------------->

来源([此处](https://i.ytimg.com/vi/EZcHGsPX55Y/maxresdefault.jpg))
## 从零到英雄指南在 OpenCV 中构建车道线检测算法
车道线检测是自动驾驶汽车必不可少的组件之一。有许多方法可以做到这一点。在这里,我们将看看使用**霍夫变换的最简单的方法。**好吧,让我们开始吧!
# 准备
所以在我们开始之前,我们需要一个地方来写我们的代码。我推荐的 IDE(环境)是 Jupyter 笔记本。它有一个漂亮的,简约的界面,但同时又非常强大。此外,Jupyter 笔记本非常适合可视化数据。以下是下载链接:
[## 安装- Anaconda 文档
### 在安装 Anaconda 个人版之前,请阅读下面列出的系统要求。如果你不想要…
docs.anaconda.com](https://docs.anaconda.com/anaconda/install/)
现在您已经安装了 Anaconda 并且 Jupyter 正在工作,让我们获取一些数据吧!可以从我的 [Github repo](https://github.com/Nushaine/lane-detection/blob/master/Untitled33.ipynb) 下载算法的**测试图片**、**视频**和**源代码**。现在我们准备好构建算法了。
本文分为三个部分:
* 第 1 部分:高斯模糊+精明的边缘检测
* 第 2 部分:霍夫变换
* 第 3 部分:优化+显示线条
第 1 部分和第 3 部分侧重于编码,第 2 部分更侧重于理论。好吧,让我们开始第一部分。
# 第 1 部分:高斯模糊+ Canny 边缘检测
我们需要做的第一件事是导入所需的库。
import numpy as np
import cv2
import matplotlib.pyplot as plt
这里我们导入了 3 个库:
* **第 1 行** : Numpy 用于进行数学计算。我们要用它来创建和操作数组
* **第二行:** OpenCV 是一个库,用来让任何人都可以做计算机视觉(也称为简化初学者)。
* **第 3 行:** Matplotlib 用于可视化图像。
接下来,让我们加载一张图片来测试我们的算法
image_path = r"D:\users\new owner\Desktop\TKS\Article Lane Detection\udacity\solidWhiteCurve.jpg"
image1 = cv2.imread(image_path)
plt.imshow(image1)
这里,我们在**第 4 行**将图像加载到笔记本中,然后我们将在**第 5 行和第 6 行读取图像并将其可视化。**
现在是处理图像的时候了。我们将特别做三件事:
def grey(image):
return cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)def gauss(image):
return cv2.GaussianBlur(image, (5, 5), 0)def canny(image):
edges = cv2.Canny(image,50,150)
return edges
在最后一个代码块中,我们定义了 3 个函数:
**灰度图像**:这有助于增加颜色的对比度,更容易识别像素强度的变化。
**高斯滤波器:**高斯滤波器的目的是减少图像中的噪声。我们这样做是因为 Canny 中的梯度对噪声非常敏感,所以我们希望尽可能消除噪声。 *cv2。GaussianBlur* 函数有三个参数:
* *img* 参数定义了我们将要归一化(减少噪声)的图像。
* 参数 *ksize* 定义了我们将要对图像进行卷积(传递)的内核的尺寸。这种核卷积就是降噪的方式。该函数使用一个名为*高斯内核*的内核,用于标准化图像。
* *西格玛*参数定义沿 x 轴的标准偏差。标准差衡量图像中像素的分布。我们希望像素分布一致,因此标准偏差为 0。
**Canny** :这是我们检测图像边缘的地方。它的作用是计算图像中某一部分的像素强度变化(亮度变化)。幸运的是,OpenCV 使这变得非常简单。
*cv2。Canny* 函数有 3 个参数,(img,threshold-1,threshold-2)。
* *img* 参数定义了我们将要检测边缘的图像。
* *threshold-1* 参数过滤低于该数字的所有渐变(它们不被视为边缘)。
* *threshold-2* 参数决定了一个边沿的有效值。
* 如果连接到高于*阈值-2* 的另一个梯度,则两个阈值之间的任何梯度都将被考虑。

多么精明的形象啊
既然我们已经定义了图像中的所有边缘,我们需要隔离与车道线对应的边缘。这就是我们要做的
def region(image):
height, width = image.shape
triangle = np.array([
[(100, height), (475, 325), (width, height)]
])
mask = np.zeros_like(image)
mask = cv2.fillPoly(mask, triangle, 255)
mask = cv2.bitwise_and(image, mask)
return mask
该功能将隔离图像中车道线所在的特定硬编码区域。它接受一个参数,Canny 图像,并输出隔离区域。
在**第 1 行,**我们将使用 *numpy.shape* 函数提取图像尺寸。在**第 2–4 行,**我们将定义一个三角形的尺寸,这是我们想要隔离的区域。
在**第 5 行和第 6 行,**我们将创建一个黑色平面,然后我们将定义一个白色三角形,其尺寸与我们在第 2 行中定义的尺寸相同。
在**第 7 行**中,我们将执行逐位运算,这允许我们隔离与车道线对应的边。让我们更深入地了解一下操作。
## 对按位 And 运算的深入解释
在我们的图像中,有两个像素的强度:黑色和白色。**黑色像素的值为 0** ,白色像素的值为 255 。在 8 位二进制中,0 转换为 00000000,255 转换为 1111111。对于按位 and 运算,我们将使用像素的二进制值。
现在,奇迹发生了。我们将在 img1 和 img2 上完全相同的位置乘以两个像素(我们将 img1 定义为具有边缘检测的平面,img2 定义为我们创建的遮罩)。

左:Img1。右图:Img2(实际上,它是白色的,但为了给你看,我把它做成黄色的)
例如,img1 上(0,0)处的像素将与 img2 中点(0,0)处的像素相乘(图像上每隔一个位置的每隔一个像素也是如此)。
如果 img1 中的(0,0)像素是白色的(意味着它是一条边),而 img2 中的(0,0)像素是黑色的(意味着该点不是我们的车道线所在的隔离部分的一部分),则操作看起来像 11111111* 0000000,这等于 000000(一个黑色像素)。
我们将对图像上的每个像素重复这一操作,从而只输出蒙版中的边缘。

仅输出隔离区域中的边缘。其他的都被忽略了
现在我们已经定义了我们想要的边,让我们定义将这些边变成线的函数。
lines = cv2.HoughLinesP(isolated, rho=2, theta=np.pi/180, threshold=100, np.array([]), minLineLength=40, maxLineGap=5)
所以这一行发生了很多事情。这一行代码是整个算法的核心。它被称为**霍夫变换**,将孤立区域中的白色像素簇转化为实际线条的部分。
* 参数 1 *:* 孤立梯度
* 参数 2 和 3:定义面元大小,2 是ρ的值,np.pi/180 是θ的值
* 参数 4 *:* 每个箱被认为是一条线所需的最小交叉点(在我们的例子中,是 100 个交叉点)
* 参数 5:占位符数组
* 参数 6:最小线路长度
* 参数 7:最大线间隙
现在**如果这些看起来像是胡言乱语**,下一部分将深入算法背后的具体细节。所以你可以在读完第二部分后回到这一部分,希望这样会更有意义。
# 第 2 部分:霍夫线变换
快速注意一下,这部分只是理论。如果您想跳过这一部分,可以继续阅读第 3 部分,但是我鼓励您通读一遍。霍夫变换下的数学真的很壮观。不管怎样,这就是了!
我们来谈谈霍夫变换。在笛卡尔平面(x 和 y 轴)中,直线由公式 *y=mx+b,*定义,其中 *x* 和 *y* 对应于该直线上的一个**特定点**,而 *m* 和 *b* 对应于斜率和 y 截距。

笛卡尔坐标空间中的直线([来源](https://s3-us-west-2.amazonaws.com/courses-images-archive-read-only/wp-content/uploads/sites/924/2015/09/25200328/CNX_CAT_Figure_02_02_007.jpg)
在笛卡尔平面中绘制的常规直线有两个参数( *m* 和 *b* ,意味着直线由这些值定义**。**此外,需要注意的是,笛卡尔平面中的线是作为它们的 *x* 和 *y* 值的函数绘制的,这意味着我们显示的线是关于有多少(x,y)对组成这条特定的线(有无限数量的 *x,y* 对组成任何线,因此线延伸到无穷大)。
然而,可以将线绘制成 m 和 b 值的函数。这是在一个叫做**霍夫空间**的平面上完成的。为了理解霍夫变换算法,我们需要理解霍夫空间是如何工作的。
## 霍夫空间的解释
在我们的用例中,我们可以将霍夫空间总结为两行
* 笛卡尔平面上的点变成霍夫空间中的线
* 笛卡尔平面中的线变成霍夫空间中的点
但是,为什么呢?
想想线的概念。一条线基本上是一组无限长的点,一个接一个地有序排列。由于在笛卡尔平面上,我们绘制了作为 *x* 和 *y* 的函数的线,线显示为无限长,因为有无限数量的(x,y)对组成这条线。
现在,在霍夫空间中,我们绘制直线作为它们的 *m* 和 *b* 值的函数。并且由于每条线在每条笛卡尔线中只有一个 *m* 和 *b* 值,所以这条线将被表示为一个点。
**例如**方程 y=2x+1 表示笛卡尔平面上的一条直线。它的 *m* 和 *b* 值分别为‘2’和‘1’,这是这个方程唯一可能的 *m* 和 *b* 值。另一方面,这个等式可能有许多值用于使这个等式实现的 *x* 和 *y* (左侧=右侧)。
所以如果我要用它的 *m* 和 *b* 值来画这个方程,我只会用点(2,1)。如果我用它的 *x* 和 *y* 值来画这个方程,我将有无限多的选项,因为有无限多的(x,y)对。

把 **θ** 想成 b,把 r 想成 m,我会在文章的后面解释 **θ** 和 r 的相关性([来源](https://www.researchgate.net/profile/Prabal_Patra/publication/335738299/figure/fig1/AS:801797773996033@1568174894886/A-line-in-cartesian-plane-is-represented-as-a-point-in-Hough-Space-or-space.png))。
那么,为什么霍夫空间中的线被表示为笛卡尔平面中的点呢(如果你从前面的解释中很好地理解了这个理论,我挑战你在不阅读解释的情况下找出这个问题。).
现在让我们考虑笛卡尔平面上的一个点。笛卡尔平面上的点只有**一个**可能的(x,y)对可以表示它,因此它是一个点并且不是无限长的。
关于一个点同样成立的是,有无限多条可能的线可以通过这个点。换句话说,这个点可以满足的方程(形式为 y=mx + b)有无穷多个(LS=RS)。
目前,在笛卡尔平面中,我们正在绘制这个点相对于它的 *x* 和 *y* 的值。但是在霍夫空间中,我们相对于它的 *m* 和 *b* 值来绘制这个点,由于有无限多条线穿过这个点,霍夫空间中的结果将是一条无限长的线。
**比如**,我们来取点(3,4)。可能通过该点的一些线是:y= -4x+16,y= -8/3x + 12 和 y= -4/3x + 8(有无限多条线,但为了简单起见,我使用 3)。

我之前提到的三行。它们都穿过点(3,4)
如果您将在霍夫空间([-4,16],[-8/3,12],[-4/3,8])中绘制这些线中的每一条线,那么在笛卡尔空间中表示每一条线的点将在霍夫空间中形成一条线(这是与点(3,4)相对应的线)。

每个点代表之前显示的线条(匹配颜色)。注意这些点是如何形成一条线的。
很整洁,是吧?如果我们在笛卡尔平面上再放一个点呢?这在霍夫空间中会是什么结果呢?嗯,通过使用霍夫空间,我们实际上可以找到笛卡尔平面上这两点的最佳拟合线。
我们可以通过在霍夫空间中绘制与笛卡尔空间中的 2 个点相对应的线,并找到这 2 条线在霍夫空间中相交的点(也称为它们的 POI,交点)来做到这一点。
接下来,获取霍夫空间中两条线相交点的 *m* 和 *b* 坐标,并使用这些 *m* 和 *b* 值在笛卡尔平面中形成一条线。这条线将是最适合我们数据的线。
## 中间解释摘要
总结一下我们一直在谈论的事情,
* 笛卡尔平面中的线被表示为霍夫空间中的点
* 笛卡尔平面中的点被表示为霍夫空间中的线
* 您可以**通过在霍夫空间中找到与两点对应的两条线的 POI 的 *m* 和 *b* 坐标,然后根据这些 *m* 和 *b* 值形成一条线,来找到笛卡尔空间中两点的最佳拟合线**。
## 回到解释:)
虽然这些概念真的很酷,但它们为什么重要呢?还记得我之前提到的 Canny 边缘检测吗,它使用梯度来测量图像中的像素强度并输出边缘。
本质上,渐变只是图像上的点。所以我们能做的是找到每组点的最佳拟合线(图像左边的梯度簇和图像右边的梯度)。这些最适合的线就是我们的车道线。为了更好地理解这是如何工作的,让我们再深入研究一下!
所以我刚才解释了我们如何通过查看与霍夫空间中的点相对应的两条线的 POI 的 *m* 和 *b* 值来找到最佳拟合的线。然而,当我们的数据集增长时,并不总是有一条线完全符合我们的数据。
这就是为什么我们要使用**垃圾桶**来代替。当合并面元时,我们将把霍夫平面分成等间距的部分。每个部分称为一个容器。通过关注某个条块中 POI 的数量,我们可以确定一条与我们的数据具有良好相关性的线。

在此图像中,与最暗的蓝色条柱相对应的 m 和 b 值将是最佳拟合线
找到交集最多的容器后,您将使用与该容器对应的 *m* 和 *b* 值,并在笛卡尔空间中形成一条线。这条线将是最适合我们数据的线。
但是**撑得住!**不是这个。我们几乎忽略了一个巨大的错误!
在垂直线中,斜率是无穷大。我们无法在霍夫空间中表示无穷大。这将导致程序崩溃。所以我们不用 **y=mx+b** 来定义一条线的方程,而是用 *P* (rho)和θ (theta)来定义一条线。这也被称为**极坐标系统。**
在极坐标系中,直线用方程 **P=xsinθ + ysinθ表示。在我们深入探讨之前,让我们定义一下这些变量的含义:**
* *P* 代表从垂直于直线的原点的距离。
* θ表示从 x 轴正方向到直线的俯角。
* *xcos* θ表示在 *x* 方向的距离。
* *ysin* θ表示在 *y* 方向的距离。

极坐标含义的直观解释
通过使用极坐标系统,不会有任何误差,即使我们有一条垂直线。比如我们取点(6,4),代入方程 *P=xcos* θ *+ysin* θ。现在,让我们取一条穿过该点的垂直线,x=6,并将其代入直线的极坐标方程,*P = 6 cos(90)*+*4 sin(90)。*
* 对于垂直线来说,θ是 90 度,因为从正 x 轴到线本身的俯角是 90 度。θ的另一种表示方式是π/2(单位为弧度)。如果你想了解更多关于弧度的知识以及我们为什么使用它们,这里的[是一个很好的视频,然而,没有必要知道弧度是什么。](https://www.youtube.com/watch?v=VsN6UuBVmYY)
* *X* 和 *Y* 取点(6,4)的值,因为这是我们在本例中使用的点。
现在让我们解出这个等式
P = 6cos(90) + 4sin(90)
P = 6(1) + 4(0)
P = 6
如你所见,我们最终没有出错。事实上,我们甚至不需要做这个计算,因为我们在开始之前就已经知道 P 是什么了。注意 *P* 如何等于 *x* 值。因为线是垂直的,所以唯一垂直于它的线是水平线。因为这条水平线是从原点开始的,这和说从原点在 x 轴上移动的距离是一样的。

我想要解释的东西的图像。
那么现在这已经解决了,我们准备好继续编码了吗?还没有。还记得以前当我们在笛卡尔平面上绘制点时,我们会在霍夫空间中以线结束吗?当我们使用极坐标时,我们会得到一条曲线,而不是直线。

正弦曲线是指曲线的类型,正弦曲线。([来源](https://miro.medium.com/max/2022/0*VPVsLApWiEayRGdQ.jpg))
然而,概念是相同的。我们将找到具有最多交叉点的箱,并使用这些 *m* 和 *b* 值来确定最佳拟合线。
原来如此!我希望你喜欢深入研究霍夫变换背后的数学。现在,让我们回到编码上来!
# 第 3 部分:优化+显示线条
现在,这部分关于平均线的内容是为了优化算法。如果我们不平均线,他们显得非常起伏,因为 *cv2。HoughLinesP* 输出一串小线段,而不是一条大直线。

这是没有平均线。很不稳定,是吧。
为了平均这些线,我们将定义一个名为“平均”的函数。
def average(image, lines):
left = []
right = []
for line in lines:
print(line)
x1, y1, x2, y2 = line.reshape(4)
parameters = np.polyfit((x1, x2), (y1, y2), 1)
slope = parameters[0]
y_int = parameters[1]
if slope < 0:
left.append((slope, y_int))
else:
right.append((slope, y_int))
该功能对 *cv2 中的线进行平均。HoughLinesP* 功能。它将找到左边和右边线段的平均斜率和 y 截距,并输出两条实线(一条在左边,另一条在右边)。
在 *cv2 的输出中。HoughLinesP* 功能,每个线段有 2 个坐标:一个表示线的起点,另一个标记线的终点。使用这些坐标,我们将计算每条线段的斜率和 y 轴截距。
然后,我们将收集所有线段的斜率,并将每个线段分类到对应于左线或右线的列表中(负斜率=左线,正斜率=右线)。
* 第 4 行:循环遍历该行数组
* 第 5 行:从每个线段中提取 2 个点的(x,y)值
* 第 6–9 行:确定每条线段的斜率和 y 截距。
* 第 10–13 行:将负斜率添加到左侧线的列表中,将正斜率添加到右侧线的列表中。
注意:通常,正斜率=左线,负斜率=右线,但是在我们的例子中,图像的 y 轴是反转的,这就是斜率反转的原因(OpenCV 中的所有图像都有反转的 y 轴)。
接下来,我们必须从两个列表中取斜率和 y 截距的平均值。
right_avg = np.average(right, axis=0)
left_avg = np.average(left, axis=0)
left_line = make_points(image, left_avg)
right_line = make_points(image, right_avg)
return np.array([left_line, right_line])
注意:不要将这段代码放在 for 循环中。
* 第 1–2 行:取两个列表(左侧和右侧)中所有线段的平均值。
* 第 3–4 行:计算每条线的起点和终点。(我们将在下一节定义 make_points 函数)
* 第 5 行:输出每行的 2 个坐标
现在我们有了两个列表的平均斜率和 y 轴截距,让我们定义两个列表的起点和终点。
def make_points(image, average):
slope, y_int = average
y1 = image.shape[0]
y2 = int(y1 * (3/5))
x1 = int((y1 — y_int) // slope)
x2 = int((y2 — y_int) // slope)
return np.array([x1, y1, x2, y2])
这个函数有两个参数,一个是车道线的图像,一个是车道线的平均斜率和 y_int 的列表,并输出每条车道线的起点和终点。
* 第 1 行:定义函数
* 第 2 行:获得平均斜率和 y 截距
* 第 3–4 行:定义线条的高度(左右两边都一样)
* 第 5–6 行:通过重新排列一条线的方程,从 *y=mx+b* 到 *x = (y-b) / m* 计算 *x* 坐标
* 第 7 行:输出坐标集
更详细地说,在第 1 行,我们使用 *y1* 值作为图像的高度。这是因为在 OpenCV 中,y 轴是反的,所以 0 在顶部,图像的高度在原点(参考下图)。
同样,在第 2 行,我们将 *y1* 乘以 3/5。这是因为我们希望直线从原点( *y1* )开始,在图像上方 2/5 处结束(因为 y 轴是 2/5,而不是从 0 向上 3/5,我们看到从最大高度向下 2/5)。

应用于左线的 make_points 函数的可视化示例
但是,该函数不显示线条,它只计算显示这些线条所需的点数。接下来,我们要创建一个函数,用这些点组成线条。
def display_lines(image, lines):
lines_image = np.zeros_like(image)
if lines is not None:
for line in lines:
x1, y1, x2, y2 = line
cv2.line(lines_image, (x1, y1), (x2, y2), (255, 0, 0), 10)
return lines_image
该函数接受两个参数:我们想要显示线条的图像和从*平均值*函数输出的车道线。
* 第 2 行:创建一个涂黑的图像,尺寸与原始图像相同
* 第 3 行:确保包含行点的列表不是空的
* 第 4–5 行:遍历列表,提取两对(x,y)坐标
* 第 6 行:创建线条并粘贴到涂黑的图像上
* 第 7 行:输出带有线条的黑色图像
你可能想知道,为什么我们不把这些线条附加到真实的图像上,而不是黑色的图像上。嗯,原始图像有点太亮了,所以如果我们将它变暗一点,以便更清楚地看到车道线就好了(是的,我知道,这没什么大不了的,但找到使算法更好的方法总是好的)

左:直接向图像添加行。右图:使用 cv2.addWeighted 函数
所以我们要做的就是调用 *cv2.addWeighted* 函数。
lanes = cv2.addWeighted(copy, 0.8, black_lines, 1, 1)
该函数为实际图像中的每个像素赋予 0.8 的权重,使它们略暗(每个像素乘以 0.8)。同样,我们将权重 1 赋予所有车道线的涂黑图像,因此其中的所有像素保持相同的强度,使其突出。
我们几乎走到了路的尽头。我们要做的就是调用这些函数,所以现在就开始吧:
copy = np.copy(image1)
grey = grey(copy)
gaus = gauss(grey)
edges = canny(gaus,50,150)
isolated = region(edges)lines = cv2.HoughLinesP(isolated, 2, np.pi/180, 100, np.array([]), minLineLength=40, maxLineGap=5)
averaged_lines = average(copy, lines)
black_lines = display_lines(copy, averaged_lines)
lanes = cv2.addWeighted(copy, 0.8, black_lines, 1, 1)
cv2.imshow("lanes", lanes)
cv2.waitKey(0)
在这里,我们简单地调用我们之前定义的所有函数,然后在第 12 行输出结果。 *cv2.waitKey* 函数用于告诉程序图像显示多长时间。我们将“0”传递给该函数,这意味着它将等待,直到按下一个键来关闭输出窗口。
下面是输出的样子

输出应该是什么样子
我们也可以将同样的算法应用于视频。
video = r”D:\users\new owner\Desktop\TKS\Article Lane Detection\test2_v2_Trim.mp4"
cap = cv2.VideoCapture(video)
while(cap.isOpened()):
ret, frame = cap.read()
if ret == True:#----THE PREVIOUS ALGORITHM----#
gaus = gauss(frame)
edges = cv2.Canny(gaus,50,150)
isolated = region(edges)
lines = cv2.HoughLinesP(isolated, 2, np.pi/180, 50, np.array([]), minLineLength=40, maxLineGap=5)
averaged_lines = average(frame, lines)
black_lines = display_lines(frame, averaged_lines)
lanes = cv2.ad1dWeighted(frame, 0.8, black_lines, 1, 1)
cv2.imshow(“frame”, lanes)
----THE PREVIOUS ALGORITHM----#
if cv2.waitKey(10) & 0xFF == ord(‘q’):
break
else:
break
cap.release()
cv2.destroyAllWindows()
这段代码将我们为图像创建的算法应用到视频中。请记住,视频只是一堆图片,一个接一个地快速出现。
* 第 1–2 行:定义视频的路径
* 第 3–4 行:捕获视频(使用 *cv2.videoCapture* ),并遍历所有帧
* 第 5–6 行:读取框架,如果有框架,继续
* 第 10–18 行:复制前面算法中的代码,将所有使用 *copy* 的地方替换为 *frame* ,因为我们要确保我们操作的是视频的帧,而不是前面函数中的图像。
* 第 22–23 行:显示每一帧 10 秒,如果按下按钮“q ”,退出循环。
* 第 24–25 行:它是第 5–6 行 if 语句的延续,但是它所做的就是如果没有任何框架,就退出循环。
* 第 26–27 行:关闭视频
好吧,你刚刚建立了一个算法,可以检测车道线!我希望你喜欢构建这个算法,但不要就此打住,这只是进入计算机视觉世界的一个介绍项目。尽管如此,你可以向你的朋友炫耀你的产品:)
# 关键要点
* 使用高斯模糊移除图像中的所有噪点
* 使用 canny 边缘检测来隔离图像中的边缘
* 使用按位 And 函数隔离对应于车道线的边
* 使用霍夫变换将边缘变成线条
# 关键词
如果你很好奇,这里有与这个算法相关的关键术语,你可以更深入地研究。
* 高斯模糊
* 按位和二进制
* Canny 边缘检测
* 霍夫变换
* 梯度
* 极坐标
* OpenCV 车道线检测
# 要考虑的其他资源
* 制作超级精良的 [youtube](https://www.youtube.com/watch?v=eLTLtUVuuy4) 视频。这是我了解车道检测的地方,事实上,我在这篇文章中的代码大部分来自这个视频。
* 我朋友写的一篇关于同一主题的[文章](https://medium.com/@kael.lascelle/lane-detection-how-cars-see-the-world-8ff3de8ddcc0)。
# 后续步骤
那么在这之后去哪里呢?在计算机视觉的世界里,有许多东西需要探索。以下是一些选择:
* 研究更先进的探测线路的方法。提示:查看 Udacity 自动驾驶汽车纳米学位教学大纲。
* 调查不同的计算机视觉算法,[这里有一个很棒的网站](https://madewithml.com/topics/)
* 看看 CNN 的,这里有我关于[理论](/a-simple-guide-to-convolutional-neural-networks-751789e7bd88)和[代码](/building-a-road-sign-classifier-in-keras-764df99fdd6a)的文章。
* 将其应用于 Arduino/RasperryPi 上的自动驾驶遥控汽车
* 还有更多…
# 这是一个总结!
感谢阅读我的文章,我真的希望你喜欢它,并从中获得一些价值。我是一名 16 岁的计算机视觉和自动驾驶汽车爱好者,喜欢构建各种机器学习和深度学习项目。如果你有任何问题,顾虑,对教程的要求,或者只是想打个招呼,你可以通过 [Linkedin](https://www.linkedin.com/in/nushaine-ferdinand-a2ba12177/) 或者 [Email](mailto:nushainef@gmail.com) me 联系我。
# 对回归概念的深入探究
> 原文:<https://towardsdatascience.com/a-deep-dive-into-the-concept-of-regression-fb912d427a2e?source=collection_archive---------33----------------------->

弗兰基·查马基在 [Unsplash](https://unsplash.com/s/photos/machine-learning?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上拍摄的照片
## 回归背后的数学
回归是机器学习中最重要的概念之一。在这篇博客中,我们将讨论不同类型的回归和基本概念。
回归类型的变化如图所示:

回归的详细表示
我们将详细讨论所有要点。
## 线性回归
回归任务处理从一组独立变量(即提供的特征)中预测因变量的值。比方说,我们想预测一辆汽车的价格。因此,它成为一个因变量,比如 Y,而发动机容量、最高速度、级别和公司等特征成为自变量,这有助于构建方程以获得价格。
现在,如果有一个特征,比如说 x。如果因变量 y 线性依赖于 x,那么它可以由 y=mx+c 给出,其中 m 是方程中该特征的系数,c 是截距或偏差。M 和 C 都是模型参数。

说红叉是点。X1 是特征值,Y1 是预测值,Y_pred 1 是实际目标值。这里我们可以看到 X1 的预测值和实际值是相同的。但是,对 X2 来说,它们是不同的。因此,我们的工作是给出一条最佳拟合线,准确地描绘出因变量和目标变量之间的关系。现在,首先随机初始化模型参数 M 和 C,比如 M1 和 C1,如图中第 1 行所示。很明显,这条线不太合适。然后我们移到由参数 M2 和 C2 给出的第 2 行。这条线提供了一个更好的拟合,并作为我们的回归。它不会总是给出精确的拟合,但它给出了可能的最佳拟合。
那么,问题就来了,我们如何从第一行到达第二行?答案在于成本函数和梯度下降的概念。为了获得最佳拟合线,我们在一组给定值上训练模型,该给定值由特征值和相应的目标值(Y 实际值)组成。因此,我们在目标方程 y=Mx+C 中拟合特征值,我们获得 Y _ 预测值。我们的目标是减少 Y _ 预测值和 Y _ 实际值之间的差异。
为此,我们使用一个损失函数或成本函数,称为均方误差(MSE)。它由因变量的实际值和预测值之差的平方给出。
> MSE = 1/2m *(Y _ actual-Y _ pred)
如果我们观察这个函数,我们会看到它是一条抛物线,也就是说,这个函数本质上是凸的。这个凸函数就是梯度下降法中用来获得 M2 和 C2 值的原理。
## 梯度下降
这种方法是最小化损失函数和实现我们目标的关键,我们的目标是预测接近原始值。

在这张图中,我们看到了损失函数图。为了找到最小损失函数值,我们需要找到一个特定的全局最小值。因此,我们总是试图使用一个凸形的损失函数来得到一个合适的最小值。现在,我们看到预测结果取决于等式 Y=Mx +C 或 Y=Wx+C 中的权重/系数。图中 X 轴上的权重和 Y 轴上的相应损失值。最初,模型为特征分配随机权重。假设它初始化了权重=a,我们可以看到它产生了一个损失,这个损失远离最小点 L-min。
现在,我们可以看到,如果我们将权重更多地移向 x 轴的正方向,我们可以优化损失函数并实现最小值。但是,模型怎么知道呢?我们需要优化权重以最小化误差,因此,显然,我们需要检查误差如何随权重变化。为此,我们需要找到误差相对于重量的导数。这个导数叫做梯度。
> ***渐变= dE/dw***
其中 E 是误差,w 是重量。
让我们看看这是如何工作的。比方说,**如果损失随着重量的增加而增加,那么梯度将是正的,**那么我们基本上在 C 点,我们可以看到这个陈述是正确的。**如果损失随着重量的增加而减少,那么梯度将为负**。我们可以看到 A 点,对应着这样一种情况。现在,从 A 点我们需要向 x 轴的正方向移动,梯度是负的。从 C 点开始,我们需要向负 x 轴移动,但是梯度是正的。**因此,梯度的负值总是表示权重应该移动的方向,以便优化损失函数。**因此,梯度以这种方式指导模型是增加还是减少权重,以便优化损失函数。
模型找到了移动的方向,现在模型需要找到应该移动多少重量。这由称为**的参数决定,学习率由α**表示。我们看到的图表中,重量从 A 点移动到距离为 *dx 的 B 点。*
> ***dx = alpha * | dE/dw |***
因此,移动的距离是学习率参数α和误差变化幅度与该点权重变化的乘积。
现在,我们需要非常仔细地决定学习率。如果它很大,权值会有很大的变化,会超过最佳值。如果它非常低,它需要很小的步骤,需要很多步骤来优化。根据以下公式改变更新的权重。
> ***w = w—alpha * | dE/dw |***
其中 w 是之前的权重。
对于每个时期,模型根据梯度移动权重以找到最佳权重。
因此,使用该过程,我们获得了模型参数 M2 和 C2 的最终值,这给了我们实际的最佳拟合线。
## 回归的类型
1. **单变量、双变量和多变量**
我们在上面的例子中看到,我们将因变量表示为单个自变量的函数,因此我们使用 y=wx+c。这种类型的回归称为**单变量**,因为只有一个自变量。
如果方程中有两个自变量,则变成:
> Y=w1x1+w2x2+c
这被称为双变量回归。
现在,如果有两个以上的独立变量,即因变量依赖于两个以上的特征,则相应地修改等式。
> Y=w1x1+w2x2+w3x3+…………..+wkxk+c

这叫做**多元**回归。
2.**线性和多项式**
到目前为止,我们已经看到了线性回归问题,即每个自变量的次数为 1。
现在,如果我们有一个如下所示的非线性曲线,我们就不能画了

非线性曲线
最佳拟合线,如果我们使用线性回归。在这种情况下,我们必须选择多项式回归。多项式回归将要素或独立变量提升到幂,并创建多项式方程而不是线性方程。它被给出为:
> Y=w1x1 +w2x2 + w3x3 +w4x4⁴ +………..+wkxk^k +c
现在,这里的 w1,w2,w3 …..wk 是模型的参数,幂是模型的超参数。所以,多项式的次数也是一个超参数。
假设 y=ut+1/2gt 是一个给定的方程,u 和 1/2g 是模型系数或参数。
这被称为**多项式回归**。
## 里脊回归
让我们考虑一种情况:

现在,这里的红点表示训练集的点,蓝点表示测试集的点。我们可以看到,如果我们使用红点进行训练,我们将获得红线(1),作为回归直线,但是非常明显的是,线(1)将具有非常差的泛化能力,并且不会在测试数据上令人满意地执行。这种情况被认为具有导致过度拟合的高方差。这就是**岭回归**发挥作用的地方。它修改了成本函数并增加了正则项。如果我们仔细观察,我们会发现第(2)行是一个更好的概括,并且会执行得更好。线(1)对于以下等式具有非常高的权重和系数值:
> Y=w1x1+w2x2+……………..+wkxk。
这导致了过度拟合。岭回归背后的思想是惩罚权重或系数的平方和,以带来正则化效果。比方说,我们的等式是
> Y_pred=w1x1+w2x2
损失函数变成:
> 损耗= 1/2m。(Y _ actual—Y _ pred)+λ/2m。(w1 + w2)
第二部分是正则化部分,其集中于惩罚权重或系数,并防止它们达到高值。由于该函数是我们的损失函数,梯度下降也导致对权重的检查,因为权重的增加反过来增加了损失函数。
**λ**参数是通过交叉验证决定的,它是衡量我们在多大程度上专注于调整我们的权重的指标。λ的值越大,正则化程度越大。因此,lambda 解决了一个权衡问题。
这种技术也用于神经网络的 L2 正则化。
## 套索回归
Lasso 回归也解决了线性回归中同样的过度拟合问题。区别在于损失函数的修改方式。套索回归惩罚的是权重之和的绝对值,而不是权重的平方。
如果我们的等式是
> Y_pred=w1x1+w2x2
损失函数变成:
> 损耗= 1/2m。(Y _ actual—Y _ pred)+λ/2m。(|w1| + |w2|)
现在,如果权重值太小,它们几乎等于 0。如果 w2 等于 0,w2x2 变为 0,这表明特征 x2 对于 y 的预测不重要
因此,套索回归被用于特征选择机制。
相同的逻辑用于神经网络的 L1 正则化。
## 分类任务
任务的类型包括基于一组特征将实体分类到一些给定的类中。逻辑回归用于分类任务。
## 为什么不是线性回归?
线性回归通常基于构建最佳拟合线。让我们先看看如何使用线性回归进行分类。

如果我们观察上面的图像,“1”表示一个类,“0”表示另一个类。如果我们得到最佳拟合线和虚线边界(如图所示),我们就可以很容易地用它来分类。当投影到最佳拟合线上时,蓝点或 0 级总是小于 0.5,这是由虚线提供的判定边界值。相应地,1 级或红点给出大于 0.4 的值。
现在,让我们来看看问题。
让我们考虑下面的情况:

在这里,我们可以看到由于异常值而导致的最佳拟合线偏移,这可能会在分类中产生错误,从而导致不令人满意的结果。同样,一些点将给出小于 0 和大于 1 的 y 值。因此,使用线性回归,y 可以取从-无穷大到+无穷大的值,但是对于分类问题,y 的范围必须从 0 到 1。
以上几点是线性回归不能用于分类任务的原因。
## 逻辑回归
我们知道,
> Y= w1x1+w2x2+w3x3……..wkxk
用作线性回归的方程式。
现在,RHS -infinity 到+infinity 的值。因此,我们必须将 LHS 变换到从-无穷到+无穷的范围内。
为了实现这一点,我们使用 log(Y/1-Y)作为 LHS。
> log(Y/1-Y)= w1x1+w2x2+w3x3……..wkxk
>
> = > y = 1/1+e^-(**w1x 1+w2x 2+w3x 3……..wkxk)**
>
> => Y= 1/(1+e^-transpose(theta).x)
>
> 其中,转置(θ)。x=( **w1x1+w2x2+w3x3……..wkxk)**
现在,
> Y=1/(1+e^(-转置(θ)。x))
也称为 Sigmoid 函数,范围从 0 到 1。θ描述系数向量或矩阵的权重,x 是特征矩阵。

上图显示了 Sigmoid 函数。0.5 是函数的边界,不取小于 0 大于 1 的值。
现在,如果 sigmoid 函数由 Y 轴上的 h(x)给出,则是 g 的函数(transpose(theta)。X)在 X 轴上,那么,
> h(x)=g(转置(θ)。x)
我们可以得出以下结论,
> h(x)>0.5
>
> =>g(转置(θ)。x)>0.5
>
> = >转置(θ)。x>0
再说一遍,
> h(x) <0.5
>
> => g(转置(θ)。x) <0.5
>
> =>转置(theta)。x <0
So, if *转置(theta)。x,即* **w1x1+w2x2+w3x3……..wkxk > 0 如果 w1x1+w2x2+w3x3,则实体被分类为 1 类..wkxk < 0,实体归类为 0 类。**
决策边界如下所示:

绿线表示决策边界,等式表示该线的等式。现在,从线性代数中,我们知道,如果我们选择一个点(a,b,c,d)并将其拟合到方程中,如果它在线上,结果将大于 0,如果它在线下,结果将小于 0。这个类比和我们上面看到的非常相似,class 1 if **w1x1+w2x2+w3x3……..wkxk > 0** 和 class 0 if **w1x1+w2x2+w3x3……..wkxk < 0。**
这就是逻辑回归的工作原理。
## 损失函数
在线性回归的情况下,我们使用 MSE 或均方差。MSE 由下式给出:
> MSE =(Y _ actual-h(x))
>
> h(x)= **w1x1+w2x2+w3x3……..wkxk**
在这种情况下,MSE 是一个抛物线函数,并且是一个具有明显最小值的纯凸函数。但是在这种情况下,
> h(x)= 1/(1+e^-(**w1x 1+w2x 2+w3x 3……..wkxk))**
现在,成本函数的修改扭曲了它的凸性,并且现在有多个最小值。除此之外,如果我们使用 MSE,误差的大小将非常小,最大值(1–0)= 1,因为 Y 可以取的最大值是 1,最小值是 0,惩罚也是如此。
由于该区域,我们使用对数损失或二元交叉熵进行逻辑回归。
比如说,Y_pred=h(x),那么,**成本(h(x),Y_actual)=**
> —Y _ actual = 1 时的 log(h(x))
>
> -Y _ actual = 0 时的 log(1 — h(x))
将两者结合起来,该方程被构造为:
> 损失=—Y _ 实际。log(h(x))—(1—Y _ actual . log(1—h(x)))
如果 Y_actual=1,第一部分给出误差,否则第二部分给出误差。

上图显示了对数损失或二元交叉熵。如果实际标签为 0,而预测标签向 1 移动,则损失函数接近无穷大,反之亦然。所以,损失多了,罚款也多了。
## 逻辑回归的类型
有三种逻辑回归,
1. 二项式回归
2. 多项式回归
3. 有序回归
定义在开头的图表中给出。我们将讨论二项式和多项式逻辑回归。
二项式回归是对两个类别进行分类,比如猫和狗。它的行为方式与上面讨论的方式相同。
## 多项式逻辑回归或多类分类
在这种情况下,存在多个类别,一个实体可以被分类为。例如,有四个类,猫、狗和狮子。图像可以被分类为这三类中的任何一类。这是多项式分类的一个例子。需要注意的一点是,这三个类是相互独立的。
为了解决这些问题,我们主要是将多项逻辑回归转换为二项式回归。
有两种方法:
1. **简单方法:**该方法为 K 个单独的类中的每一个创建 K 个单独的逻辑回归模型。每个模型都有一个 sigmoid 输出节点,表示该特定类的输出。对于我们的模型,将有 3 个乙状结肠节点,第一个用于猫,第二个用于狗,等等。现在,第一个节点给出图像是猫 P_c 的概率,第二个节点给出图像是 P_d 的概率,类似地,我们得到狮子的 P_l。现在,比较分数以获得最终答案。如果 P_c 在所有 3 个中具有最大值,则图像被预测为猫。
2. **同步方法:**该方法创建 K-1 个独立的逻辑回归。每一个概率都被认为是一组独立的事件,即节点不是决定一幅图像是猫还是狮子(0/1),而是决定这幅图像是猫还是狮子(A/B)。
现在,我们已经看到了逻辑回归:
> log(Y/1-Y)= w1x1+w2x2+w3x3……..wkxk
如果 Y = > 0.5 类 else 类所以,Y 可以说 P(A),1-Y 等价于 P(C)。这被称为**赔率。**因此,对于第一个模型:
> log(P(A)/P(C))= w1 _ 1x1 _ 1+w2 _ 1x 2 _ 1+w3 _ 1x 3 _ 1……..wk_1xk_1+b_1
>
> 比如说,R1 = w1 _ 1x 1 _ 1+w2 _ 1x 2 _ 1+w3 _ 1x 3 _ 1……..wk_1xk_1+b_1
>
> P(A)/P(C)= exp(R _ 1)———1
再次对于第二个模型,
> log(P(B)/P(C))= w1 _ 2 x1 _ 2+w2 _ 2 x2 _ 2+w3 _ 2 x3 _ 2……..wk_2xk_2 + b_2
>
> 比如说,R _ 2 = w1 _ 2 x1 _ 2+w2 _ 2 x2 _ 2+w3 _ 2 x3 _ 2……..wk_2xk_2 + b_2
>
> P(B)/P(C)= exp(R _ 2)———2
现在,根据上面的等式 1 和 2:
> P(A)=P(C)*exp(R_1)
>
> P(B)=P(C)*exp(R_2)
现在, **P(A)+P(B) +P(C) =1**
所以,P(C)* exp(R1)+P(C)* exp(R2)+P(C)= 1
> p(C)= 1/(1+exp(R1)+exp(R2))
因此,我们可以将它们联系起来。
## Softmax 回归
Softmax 回归由下式给出:

softmax 图层用作多类分类的最终图层或输出图层。该函数是一种指数方法。所有类别的概率之和等于 1。最大可能类作为输出给出。
## 结论
在本文中,我们已经讨论了与回归相关的所有概念。希望这有所帮助。
# 深入了解变压器架构—变压器模型的开发
> 原文:<https://towardsdatascience.com/a-deep-dive-into-the-transformer-architecture-the-development-of-transformer-models-acbdf7ca34e0?source=collection_archive---------11----------------------->
## 自然语言处理转换器

[来源](http://unsplash.com)
# 自然语言处理转换器
自从自然语言处理(NLP)的世界被*由[瓦斯瓦尼*等人*](https://arxiv.org/abs/1706.03762) 发表的开创性的“注意力是你所需要的”论文*所改变以来,似乎已经过去了很长时间,但事实上那还不到 3 年。变压器架构的引入相对较晚,并且它们已经颠覆了语言任务,这表明了机器学习和人工智能的快速发展。现在是深入了解变压器架构内部工作原理的最佳时机,尤其是变压器模型在各种新应用中取得巨大进展,如[预测化学反应](https://pubs.acs.org/doi/10.1021/acscentsci.9b00576)和[强化学习](https://arxiv.org/abs/1910.06764)。
无论您是老手还是第一次关注 transformer 风格的架构,本文都应该为您提供一些帮助。首先,我们将深入探讨用于构建最初的 2017 Transformer 的基本概念。然后,我们将触及后续 transformer 模型中实现的一些开发。在适当的地方,我们将指出一些限制,以及从原始变压器继承思想的现代模型如何试图克服各种缺点或提高性能。
# 变形金刚是做什么的?
变压器是当前处理序列的最先进的模型类型。也许这些模型最突出的应用是在文本处理任务中,其中最突出的是机器翻译。事实上,变形金刚及其概念后代已经渗透到自然语言处理(NLP)的几乎每一个基准排行榜[中,从问题回答到语法纠正。在许多方面,变压器架构正在经历发展的高潮,类似于我们在 2012 年 ImageNet 竞赛后看到的卷积神经网络,有好有坏。](https://nlpprogress.com/)

[来源](https://blog.exxactcorp.com/)
*变压器表示为一个黑匣子。整个序列(图中的 x)以前馈方式同时解析,产生变换的输出张量。在这个图中,输出序列比输入序列更简洁。对于实际的 NLP 任务,词序和句子长度可能会有很大的不同。*
不同于 NLP 的先前最先进的架构,例如 RNNs 和[lstm](https://blog.exxactcorp.com/5-types-lstm-recurrent-neural-network/)的许多变体,没有循环连接,因此没有先前状态的真实记忆。变形金刚通过同时感知整个序列来解决记忆缺失的问题。也许一个变形神经网络感知世界有点像电影[中的外星人*到来*](https://en.wikipedia.org/wiki/Arrival_(film)) *。严格地说,未来元素通常在训练期间被掩盖,但除此之外,该模型可以在整个序列中自由学习长期语义依赖性。*

[来源](https://blog.exxactcorp.com/)
*变形金刚去掉了循环连接,同时解析整个序列,有点像* Arrival 中的七足动物。*你可以使用 flxb 2(*[https://github.com/FlxB2/arrival_logograms](https://github.com/FlxB2/arrival_logograms)*)的开源 python2 库制作自己的 logograms。*
作为仅前馈模式,变压器对硬件的要求略有不同。变形金刚实际上更适合在现代机器学习加速器上运行,因为与递归网络不同,它没有顺序处理:模型不必处理一串元素来开发有用的隐藏细胞状态。转换程序在训练期间可能需要大量内存,但是以降低的精度运行训练或推理有助于减轻内存需求。
迁移学习是在给定的基于文本的任务中达到最先进水平的一个重要捷径,坦白地说,对于大多数预算有限的实践者来说是必要的。培训一台大型现代变压器的能源和财务成本很容易使单个研究人员的[年总能耗](https://arxiv.org/abs/1906.02243)相形见绌,如果使用云计算,成本将高达数千美元。幸运的是,类似于计算机视觉的深度学习,专门任务所需的新技能可以转移到大型预训练的变形金刚上,例如从[拥抱脸库](https://github.com/huggingface/transformers#model-architectures)下载。
# 变压器架构中的注意机制是什么?
变压器架构中的秘密酱料是纳入了某种注意力机制,2017 年的原版也不例外。为了避免混淆,我们将把瓦斯瓦尼*等人*演示的模型称为“变形金刚”或“普通变形金刚”,以区别于类似名称的继任者,如 Transformer-XL。我们将从关注机制开始,向外构建整个模型的高层次视图。

[来源](https://blog.exxactcorp.com/)

[来源](https://blog.exxactcorp.com/)
注意力是一种有选择地对输入数据中的不同元素进行加权的手段,这样它们将对下游层的隐藏状态产生调整后的影响。vanilla Transformer 通过将输入单词向量解析为键、查询和值向量来实现注意力。键和查询的点积提供了注意力权重,使用 softmax 函数对所有注意力权重进行压缩,使得总权重总和为 1。对应于每个元素的值向量在被馈送到后续层之前根据它们的注意力权重被求和。一下子理解这些可能有点复杂,所以让我们放大图片,一步一步地看一下。
# 词向量嵌入赋予语义
从构成句子的单词序列开始,序列中的每个元素(单词)首先被转换成称为单词向量的嵌入式表示。词向量嵌入是一种更微妙的表示,而不是像 Salakhutidinov 和 Hinton 在他们 2007 年的语义散列论文中使用的一次性编码词袋模型。
单词嵌入(有时也称为记号)是有用的,因为它们以神经网络可以理解的数字方式传递语义。习得的单词嵌入可以包含上下文和关系信息,例如,“dog”和“puppy”之间的语义关系大致相当于“cat”和“kitten”,因此我们可以像这样操作它们的单词嵌入:

[来源](https://blog.exxactcorp.com/)
# 点产品注意细节

[来源](https://blog.exxactcorp.com/)
*香草变压器注意机制详解。*
从上图的左上角开始,一个输入单词首先被一个嵌入函数标记化,用一个数字向量替换字符串“ALL ”,该向量将作为注意力层的输入。注意,唯一具有嵌入功能的层是第一编码器,每隔一层仅将前面的输出向量作为输入。关注层(图中的 **W** )根据输入计算三个向量,称为键、查询和值。键和查询的点积是一个标量,是给定位置的相对权重。
注意力机制并行应用于序列中的每个元素,因此每个其他元素也有一个注意力分数。这些注意力分数服从 softmax 函数,以确保总加权和为 1.0,然后乘以相应的值向量。所有元素的值,现在由它们的注意力分数加权,被加在一起。产生的矢量是构成输入序列的内部表示的矢量序列中的新值,该新值然后将被传递到前馈完全连接层。
到目前为止可能已经丢失的另一个重要细节是用于稳定 softmax 函数的缩放因子,*即*在将值输入到关注层使用的 softmax 函数之前,数字与关键向量中单元数量的平方根成反比。无论键和查询向量的大小如何,这对于让学习很好地工作是很重要的。在没有比例因子的情况下,当使用长键和查询向量时,点积将趋向于大值,将 softmax 函数的梯度推入相对平坦的区域,并且使得错误信息难以传播。
# 编码器层:6 种不同类型的普通变压器
如前所述,去除循环连接的一个有用的结果是,整个序列可以以前馈方式一次处理。当我们将上述自我关注层与密集前馈层结合时,我们得到一个编码器层。前馈层由两个线性层组成,其间有一个整流线性单元(ReLU)。也就是说,输入首先被线性层变换(矩阵乘法),然后结果值被限幅为总是 0 或更大,最后结果被馈送到第二线性层以产生前馈层输出。

[来源](https://blog.exxactcorp.com/)
Vanilla Transformer 使用了其中的六个编码器层(自我关注层+前馈层),然后是六个解码器层。Transformer 使用一种称为多头关注的自我关注的变体,因此事实上关注层将为每个序列元素计算 8 个不同的键、查询、值向量集。然后,这些将被连接成一个矩阵,并通过另一个矩阵乘法,产生适当大小的输出向量。
# 解码器层:6 种不同类型的香草变压器
解码器层拥有我们在编码器层中看到的许多功能,但增加了第二个关注层,即所谓的编码器-解码器关注层。与自我关注层不同,只有查询向量来自解码器层本身。键值向量取自编码器堆栈的输出。每个解码器层也包含一个自我关注层,就像我们在编码器中看到的那样,输入自我关注层的查询、键和值都是在解码器堆栈中生成的。

[来源](https://blog.exxactcorp.com/)
*解码器层,不同于编码器层,增加了一个编码器-解码器注意子层。这六个组成了香草变压器的解码器。*
现在我们有了编码器和解码器层的配方。要用这些组件构建转换器,我们只需制作两个堆栈,每个堆栈包含六个编码器层或六个解码器层。编码器堆栈的输出流入解码器堆栈,解码器堆栈中的每一层也可以访问编码器的输出。但是,要完全理解普通变压器是如何组装的,只剩下一些细节了。

[来源](https://blog.exxactcorp.com/)
*全变压器概述。*
# 最终部分:剩余连接、图层标准化和位置编码
像许多其他具有许多参数的极深度神经网络一样,当梯度没有像我们希望的那样从输入流向输出时,训练它们有时会很困难。在计算机视觉中,这导致了强大的 [ResNet](https://arxiv.org/abs/1512.03385) 风格的卷积神经网络。ResNets 是 residual networks 的缩写,它将最后一层的输入明确地添加到自己的输出中。通过这种方式,残差被保留在整个层堆栈中,梯度可以更容易地从输出处的损失函数一直流回输入。 [DenseNet](https://arxiv.org/abs/1608.06993) 架构旨在通过将输入张量和输出张量连接在一起,而不是相加,来解决相同的问题。在 vanilla Transformer 模型中,残差求和操作之后是[层归一化](https://arxiv.org/abs/1608.06993),这是一种用于改进训练的方法,与批处理归一化不同,它对小批处理大小不敏感。

[来源](https://blog.exxactcorp.com/)
*残差连接和图层归一化图。vanilla Transformer 的编码器和解码器层中的每个子层都采用了这种方案。*
在 LSTMs 这样的递归体系结构中,模型可以在内部学习计数和测量序列距离。Vanilla Transformer 不使用递归连接,并同时感知整个序列,因此它如何了解哪个元素来自序列的哪个部分,尤其是当序列长度允许变化时?答案是基于衰减正弦函数的位置编码,它与序列元素嵌入连接。瓦斯瓦尼*等人*。还对学习的位置编码进行了实验,得到了几乎相同的结果,但推断使用正弦编码应该允许模型更好地概括训练期间看不到的序列长度。
# 变形金刚在深度学习中的影响和未来
2017 年推出的 vanilla Transformer 极大地破坏了基于序列的深度学习。通过完全去除循环连接,transformer 架构更适合在现代机器学习加速硬件上进行大规模并行计算。令人惊讶的是,vanilla Transformer 可以学习序列中的长期依赖性,事实上,vanilla Transformer 可以轻松学习关系的距离是有上限的。
Transformer-XL 是由[戴*等人于 2019 年*](https://arxiv.org/abs/1901.02860)推出的,旨在通过一种新的位置编码来解决这一问题,并且还引入了一种伪递归连接,其中键和值向量部分取决于先前的隐藏状态以及当前的隐藏状态。其他变压器变体包括仅解码器变压器(*例如* OpenAI 的 GPT 和 GPT-2)、添加双向(即基于 BERT 的变压器)等。变压器是为序列设计的,在自然语言处理中有着最突出的应用,但变压器架构也适用于[图像生成](https://arxiv.org/abs/1802.05751)、[强化学习](https://arxiv.org/abs/1910.06764)(通过修改 Transformer-XL),以及[化学](https://pubs.acs.org/doi/10.1021/acscentsci.9b00576)。
# 有用的变压器架构资源
希望这篇文章已经帮助你建立了使用 NLP 和其他现代转换器架构的直觉。但是你不必为了尝试你自己的想法而成为一个英雄,从零开始建造和训练一个新的变形金刚。像 [HuggingFace](https://github.com/huggingface/transformers#model-architectures) 这样的开源库提供了预先训练好的模型,你可以对这些模型进行微调以支持你的 NLP 项目。谷歌提供了一个笔记本,你可以用它来修改 tensor2tensor 库中的变形金刚模型。当然你也可以和变形金刚对话或者玩一个基于文本的地牢冒险游戏,由 OpenAI 的 GPT 2 作为地牢主人。根据你喜欢的抽象层次,上面的资源可能已经足够了,但是如果你不把代码放到概念中就不会开心,你可能会对哈佛 NLP 实验室的亚历山大·拉什和其他人的论文的[代码注释版本](http://nlp.seas.harvard.edu/2018/04/03/attention.html)感兴趣。
快乐变身!
# R 中向量自回归的深入研究
> 原文:<https://towardsdatascience.com/a-deep-dive-on-vector-autoregression-in-r-58767ebb3f06?source=collection_archive---------1----------------------->
## 让数据说话!让我们抛弃先验的期望。

# 什么是 VAR?
Christopher Sims 提出了向量自回归模型,这是一个多元线性时间序列模型,其中系统中的内生变量是所有内生变量滞后值的函数。这为传统的结构方程系统提供了一种简单而灵活的替代方案。VAR 可以对宏观经济数据进行信息建模,而不会强加非常强的限制或关系。本质上,这是一个宏观经济模型,没有太多的先验预期。
# 风险值的用途
var 非常有用,尤其是在宏观经济学领域。它被广泛用于模拟对实体经济的宏观经济冲击,并被大量用于政策模拟和预测。这是向量自回归的主旨和主要用途。首先,它是一个复杂的*预测工具*。我们将展示 var 如何比标准的单变量预测模型更好,特别是在确定长期趋势方面。大多数关于预测的实证研究表明,VAR 已经超越了传统的单变量预测模型和基于理论的结构方程模型。
除了预测,var 也是*结构分析*的有用工具。我们注意到 var 可以研究对冲击的反应。它可以精确定位传统单变量模型无法解决的波动来源。此外,var 有助于区分相互竞争的理论模型。
# VAR 看起来怎么样
正如我们之前提到的,VAR 是一个多元线性时间序列模型,其中系统中的内生变量是所有内生变量的滞后值的函数。简单地说,VAR 本质上是一元自回归模型的推广。通常,我们将 VAR 记为 VAR(p ),其中 *p* 表示系统中自回归滞后的数量。考虑一个只有两个变量的 VAR 系统。

二元 VAR 系统
我们也可以把它写成矩阵形式

矩阵形式变量
VAR 的估计是一个由 OLS 方程得出的*方程。我们基本上在每个方程上运行 OLS。我们发现估计是一致的,因为只有内生变量的滞后值在等式的右边。此外,估计也是有效的,因为所有的方程都有相同的回归量,这使得每个方程的变化最小化。这样做表明它本质上等价于一个*广义最小二乘*。在这方面,无序列相关性的假设也成立。*
# 使用 Sims (1992)框架
我们现在将在一个实际的例子中应用在 VAR 中学到的许多概念。特别是,我们将使用 Sims (1992)利用菲律宾数据开发的框架。在这个模型中,我们将使用四个变量。这些是:
*隔夜逆回购利率*由菲律宾央行设定。从各方面来看,这是菲律宾央行控制的主要政策利率。
*M1 货币供应量*可从 BSP 网站获得
*CPI 通货膨胀率*由菲律宾统计局每月公布,根据拉斯佩里斯价格指数衡量价格的相对涨幅。
*工业生产*衡量工业部门所有商品的价值。
我们将首先估计一个反映关键经济反应的标准风险值。理论上和西姆斯都认为,对名义利率的冲击代表着货币政策冲击。对政策变量的冲击会同时影响所有其他变量。该变量受周期内所有其他变量的影响,并且排序在最后。最后,央行只观察具有滞后性的非政策变量。
# 预赛
我们从安装所需的包并使用 library()命令加载它们开始。对于这一部分,我们需要安装“VAR”包,该包将包含运行 VAR 和 SVAR 以及后续诊断测试和应用程序所需的大量命令。然后我们看到每个变量的图,并判断一些初始条件,如非平稳性。
如前所述,我们需要安装“vars”包。使用 install.packages("vars ")命令可以做到这一点。在此之后,我们将加载这个包以及我们的标准包和库套件,以便我们继续进行评估。
install.packages("vars")
library(vars)
library(mFilter)
library(tseries)
library(TSstudio)
library(forecast)
library(tidyverse)
安装和加载之后,是时候加载我们的数据集了。我们将使用 Sample_VAR.csv 文件,其中包含从 2003 年 1 月到 2020 年 2 月的所有变量的数据。该数据每月公布一次,可从 BSP 和 PSA 获得。我们使用 read_csv()命令读取数据集和 file.choose()命令打开一个对话框,供我们选择数据。在本例中,我们将数据集放在名为“mp”的对象下。如果你喜欢,随便你怎么命名。然后,我们使用 head()命令查看数据集的前几行,以检查它是否正确加载。文件和代码可以在这里找到:[https://drive . Google . com/drive/u/0/folders/11 max h0 trxjuf 1y _ yh-AJXgxulHQwcBEn](https://drive.google.com/drive/u/0/folders/11mAXh0trxjuf1y_yh-AJXgxulHQwcBEn)
mp <- read_csv(file.choose())
head(mp)
接下来,我们需要使用 ts()命令将数据集中的每个变量声明为一个时间序列。我们使用$符号从数据集中调用一个变量。所有变量都从 2003 年的同一天同一个月的 1 月 1 日开始。我们将频率设置为 12,因为我们要处理月度数据。
lnIP <- ts(mp\(lnIP, start = c(2003,1,1), frequency = 12)
M1 <- ts(mp\)M1, start = c(2003,1,1), frequency = 12)
CPI <- ts(mp\(CPI, start = c(2003,1,1), frequency = 12)
RRP <- ts(mp\)RRP, start = c(2003,1,1), frequency = 12)
我们也可以使用 autoplot()或 ts_plot()命令来可视化我们的系列。和以前一样,ts_plot()命令是一个更具交互性的版本,它使用 plot.ly 包作为基础。
ts_plot(lnIP)
ts_plot(M1)
ts_plot(CPI)
ts_plot(RRP)

时间序列图
同样,评估所研究的变量是否稳定也很重要。正如我们已经说过的,在我们的 VAR 中有稳定的变量是一个理想的情况,即使我们没有这些也能运行它。正如我们已经习惯的,让我们使用我们熟悉的测试。为简单起见,我们将使用 Phillips Perron,因此不需要指定滞后的数量。
pp.test(lnIP)
pp.test(M1)
pp.test(CPI)
pp.test(RRP)
在上面的估计中,我们发现所有的变量都是非平稳变量。请记住,拒绝零假设表明数据是稳定的。然而,我们仍然可以使用这些水平数据进行 VAR 估计。然而,你可以选择不同的数据,看看是否能提供更好的结果和预测。
# 正确估计
是时候正式评估我们的风险值了。我们首先需要将我们的 VAR 变量绑定在一起以创建系统。此后,我们将选择我们将使用的 VAR 后面的最佳滞后阶数。然后,我们将运行一个无限制的风险值估计,并看到结果。最后,我们将运行一些诊断,如自相关、稳定性和正态性测试。
第一步是建立 VAR 系统。这是通过 cbind()命令完成的,该命令实质上是对我们的时间序列进行分组。我们将按照我们认为合适的顺序来点这道菜。我们将把它存储在一个名为“v1”的对象中。然后,我们将使用 colnames()命令将变量重命名为下面的列表。
v1 <- cbind(RRP, lnM1, CPI, lnIP)
colnames(v1) <- cbind("RRP","M1","CPI", "lnIP")
在我们绑定变量并创建 VAR 系统后,我们将确定我们将使用的一些滞后顺序。为此,我们使用 VARselect()命令并使用我们刚刚创建的 v1 对象。我们将使用最大滞后阶数 15。该命令将根据 AIC、SBIC、HQIC 和 FPE 的多元迭代自动生成首选滞后阶数。
lagselect <- VARselect(v1, lag.max = 15, type = "const")
lagselect$selection
运行这些命令表明要使用的滞后阶数是 2。在西姆斯的研究中,他使用了 14 个滞后,这在美国数据中可能更为熟练,因为这些影响反映了更大的持久性。
我们现在将评估一个模型。我们使用 VAR()命令来估计 VAR。p 选项指的是使用的滞后数量。因为我们确定 2 lags 是最好的,所以我们把它设置为 2。我们让它成为一个典型的带有常数的无限制 VAR,我们将在系统中不指定任何外生变量。summary()命令列出了结果。
Model1 <- VAR(v1, p = 2, type = "const", season = NULL, exog = NULL) summary(Model1)
我们通常不解释 VAR 的系数,我们通常解释应用的结果。但是你会看到,我们在 VAR 中有每个滞后和每个方程的系数。每个等式代表 VAR 系统中的一个等式。
# 模型诊断
一个假设是残差应该尽可能地**不自相关**。这也是基于我们的假设,即残差是白噪声,因此与之前的周期不相关。为此,我们运行 serial.test()命令。我们将结果存储在对象 Serial1 中。
Serial1 <- serial.test(Model1, lags.pt = 5, type = "PT.asymptotic")Serial1
在这个测试中,我们看到残差没有显示自相关的迹象。然而,如果我们改变最大滞后阶数,有可能会出现自相关现象。因此,最好尝试多个滞后订单。
另一个要考虑的方面是**异方差**的存在。在时间序列中,我们称之为*拱形效应*,它本质上是时间序列中聚集的波动区域。这在一系列事件中很常见,比如当发布盈利电话时,股价可能会大幅上涨或下跌。在该区域或窗口中,可能会有过度的波动,从而改变残差的方差,远离我们的恒定方差假设。我们有模型来解释这些,这些模型是条件波动率模型,我们将在后面的章节中讨论。
Arch1 <- arch.test(Model1, lags.multi = 15, multivariate.only = TRUE)Arch1
同样,ARCH 检验的结果没有表明异方差的程度,因为我们没有拒绝零假设。因此,我们得出结论,在这个模型中没有拱效应。然而,像自相关测试一样,在后续的滞后阶数上记录滞后效应是可能的。
一个软的先决条件,但也是一个理想的条件是残差分布的正态性。为了测试残差的正态性,我们在 R 中使用 normality.test()命令,它引入了 Jarque-Bera 测试、峰度测试和偏斜度测试。
Norm1 <- normality.test(Model1, multivariate.only = TRUE)Norm1
基于所有三个结果,这一特定模型的残差似乎不是正态分布的。
稳定性测试是对结构断裂存在的一些测试。我们知道,如果我们不能测试结构突变,如果碰巧有一个,整个估计可能会被打乱。幸运的是,我们对此有一个简单的测试,它使用递归残差和的图。如果在图中的任何一点,总和超出红色临界界限,则可以看到该点的结构性断裂。
Stability1 <- stability(Model1, type = "OLS-CUSUM")plot(Stability1)

稳定性试验
根据测试结果,似乎没有明显的结构断裂。因此,我们的模型通过了这个特殊的测试
# 政策模拟
我们现在将转向常规 VAR 中的政策模拟。我们将做三个主要的,这是格兰杰因果关系,预测误差方差分解,以及脉冲响应函数。
我们将测试系统中每个变量与所有其他变量的总体格兰杰因果关系。我们说过,变量之间可能存在单向、双向或无因果关系。
GrangerRRP<- causality(Model1, cause = "RRP")
GrangerRRPGrangerM1 <- causality(Model1, cause = "M1")
GrangerM1GrangerCPI <- causality(Model1, cause = "CPI")
GrangerCPIGrangerlnIP <- causality(Model1, cause = "lnIP")
GrangerlnIP
所使用的命令适用于二元情况,但我们现在将在四元系统中使用它。你们中的一些人可能会尝试将 VARmodels 减少到两个变量,以查看更直接的解释。为了执行 Granger 因果关系测试,我们使用 causality()命令。根据研究结果,我们得出结论,CPI 格兰杰原因的其他变量,但没有看到相反的情况。也许粒度变量到变量的关系比变量到组的关系更有意义。
我们现在将转向脉冲响应函数。虽然我们可以获得比下面更多的脉冲响应函数,但我们将关注 RRP 中的冲击对系统中其他变量的影响
RRPirf <- irf(Model1, impulse = "RRP", response = "RRP", n.ahead = 20, boot = TRUE)
plot(RRPirf, ylab = "RRP", main = "RRP's shock to RRP")M1irf <- irf(Model1, impulse = "RRP", response = "M1", n.ahead = 20, boot = TRUE)
plot(M1irf, ylab = "M1", main = "RRP's shock to M1")CPIirf <- irf(Model1, impulse = "RRP", response = "CPI", n.ahead = 20, boot = TRUE)
plot(CPIirf, ylab = "CPI", main = "RRP's shock to CPI")lnIPirf <- irf(Model1, impulse = "RRP", response = "lnIP", n.ahead = 20, boot = TRUE)
plot(lnIPirf, ylab = "lnIP", main = "RRP's shock to lnIP")

脉冲响应函数
irf()命令生成 IRF,其中我们需要指定模型、脉冲序列和响应序列。我们还可以指定未来的周期数,以了解影响或冲击将如何随时间发展。然后,我们使用 plot()命令来绘制这个 IRF。IRF 的结果相当令人费解。请记住,RRP 中的这种增加不可能是 BSP 对其他变量所发生的事情的反应,因为它是首先订购的。如你所见,在(a)中,对 RRP 的冲击当然会增加 RRP,这将导致货币供应量(b)的轻微下降和产出(d)的下降。我们还发现,价格在短期内会上升,但之后会适度下降。克里斯托弗·西姆斯认为,这是一个令人困惑的结果。结果表明,上调存款准备金率后,价格会上涨。如果货币紧缩降低了总需求(lnIP ),从而降低了产出,那么它不可能与通胀联系在一起。他接着说,VAR 可能会被错误指定。例如,可能有一个 BSP 将达到的通胀领先指标,但它被错误地从 VAR 中忽略了。BSP 可以知道通胀压力即将到来,并通过提高利率来抵消通胀压力。
如果你回想一下基本的宏观经济学,像提高政策利率(利率)这样的紧缩性货币政策会导致产出下降。产出的下降通常会抑制通货膨胀,导致价格下降。然而,我们在这个模型中看到的是,在很大程度上,价格上涨了,这令人费解。据推测,在先前的估计中,政策利率的外生变动并不完全是外生的。换句话说,没有正确识别外部冲击。为了解决这个问题,西姆斯将商品价格加入其中。
我们现在把注意力转向预测误差方差分解。同样,我们可以追踪系统中冲击的发展来解释系统中所有变量的预测误差方差。为此,我们使用 fevd()命令。像 IRF 一样,我们也可以指定未来的周期数。在这种情况下,让我们只关注 RRP。
FEVD1 <- fevd(Model1, n.ahead = 10)
FEVD1
plot(FEVD1)

预测误差方差分解
我们可以在窗口(a)中清楚地看到,短期的 RRP(列 1)的预测误差是由于它本身。这是因为 RRP 在排序中被放在第一位,并且没有其他冲击同时影响 RRP。在更长的时间范围内,比如 10 个月,我们可以看到 CPI 现在约占 16%,货币供应量约占 2%。
# 使用 VAR 进行预测
正如我们已经说过的,我们也可以使用 VAR 进行预测。为此,我们使用 predict()命令并生成一个称为*扇形图*的东西,它通常用于以图形方式确定预测的置信度。我们将预测范围设定为未来 12 个月或全年预测。
forecast <- predict(Model1, n.ahead = 12, ci = 0.95)fanchart(forecast, names = "RRP", main = "Fanchart for RRP", xlab = "Horizon", ylab = "RRP")fanchart(forecast, names = "M1", main = "Fanchart for M1", xlab = "Horizon", ylab = "M1")fanchart(forecast, names = "CPI", main = "Fanchart for CPI", xlab = "Horizon", ylab = "CPI")fanchart(forecast, names = "lnIP", main = "Fanchart for lnIP", xlab = "Horizon", ylab = "lnIP")forecast

VAR 中的预测
该图显示,RRP 预计将略有下降,然后上升,M1 预计将下降,IP 也是如此。预计 CPI 将在最初几个月略有下降,然后温和反弹。请注意,这与 IRFs 不同,只是因为我们使用风险值作为预测工具,而不是政策工具。
# 结论
总之,我希望通过这个例子,你可以看到风险值方法的许多使用案例,以及为什么许多经济学家继续使用它的灵活性。除了纯粹的预测模型,它还有更多应用,如政策模拟、线性因果分析和预测误差分解。在 VAR 创立之前,经济学把一切都寄托在理论和实践上,认为经济变量必须遵循它们的规则。然而,在实践中,我们知道经济变量的行为方式可能与我们先入为主的观念不同。因此,预先设定预期可能会欺骗我们。
如果想要更实际的方法,可以考虑观看我在 YouTube 上上传的关于这个主题的视频。
# 参考
[1] Lütkepohl,H. *多重时间序列分析新入门*。(2005).斯普林格科学&商业媒体。
[2]恩德斯,W. *应用计量经济学时间序列*。约翰·威利的儿子们。
# 对抗错误信息的深度学习方法*
> 原文:<https://towardsdatascience.com/a-deep-learning-approach-to-combating-misinformation-a7cac00bde1c?source=collection_archive---------30----------------------->
*标题由人工智能生成
## 作者:[马丁·贝克](https://www.linkedin.com/in/martbeck/)、[蕾切尔·米德](https://www.linkedin.com/in/rachelmmeade/)、达拉西米·奥卢瓦尼伊、[萨沙·奥佩拉](https://www.linkedin.com/in/alexandra-opela/)、[塞巴斯蒂安·奥索里奥](https://www.linkedin.com/in/sebastianosorioagudelo/?locale=en_US)、[杰克森·罗斯](http://www.linkedin.com/in/jackson-r-ross)、[德罗夫·苏布拉曼尼安](http://www.linkedin.com/in/dhrov-s/)
假新闻的兴起迫使每个拥有社交媒体账户的人成为一名侦探,负责在分享之前确定一篇帖子是否真实。然而,假新闻仍然逃过我们的防线,在网上泛滥,由于真实用户的无知和粗心而被放大。正如 NBC 新闻的这篇文章所示,除了散布恐慌和错误信息,假新闻还有可能对公司和个人的声誉造成真正的损害。为了防止误传的直接和间接成本,需要更好的方法来检测假新闻。虽然一些假新闻是由真实的人写的,只是可信的虚构,但假新闻也可以通过深度学习模型大量生成,加剧了问题。到目前为止,计算机生成的文本很容易与真实的文字区分开来。然而,这个问题已经变得更加紧迫,因为这些自然语言生成模型的巨大改进意味着它们现在可以生成比以往任何时候都更可信的文本。

假新闻无处不在——问题是如何阻止它。
在过去的三年里,变形金刚席卷了自然语言处理任务。像长短期记忆架构这样的残余神经网络在几年前还是最先进的,但已经被 BERT(变形金刚的双向编码器表示)和 OpenAI 强大的新模型 GPT-2(生成式预训练变形金刚 2)等变形金刚超越。这些变形金刚现在以精确的分类和听起来像人类的文本生成引领着行业。作为一个例子,GPT-2 生成的样本如此逼真,以至于 OpenAI 最初拒绝发布完整的训练模型,理由是“担心该技术的恶意应用”
区分真假新闻很重要,但却是一个难以解决的问题,而且随着新模式的出现,这个问题变得更加困难。该项目旨在探索围绕假新闻的产生和检测的挑战性现实。
# 项目目标
* 通过比较来自长短期记忆(LSTM)残差神经网络和来自 OpenAI 的最新转换器(称为 GPT-2)的生成文本,创建自然语言生成模型改进的简要演示。
* 使用鉴别器来尝试准确地分类文本是由最先进的深度学习模型生成的还是由人类生成的。
# 项目概述
该项目分为两个主要部分,如上所述。第二部分——寻找、训练和使用鉴别器对生成的文本进行分类——预计将是一个重大挑战,因为计算机生成的文本已经变得非常难以与人类书写区分开来。
在这个过程的开始,研究和评估了许多模型。通常选择经过训练的模型版本,因为它们能够实现最先进的性能,而不需要几天的训练。LSTM 模型使用 Kaggle 数据集的子集进行了微调。用于微调的数据由来自纽约时报、布莱巴特、CNN、商业内幕、大西洋、福克斯新闻频道、谈话要点备忘录、Buzzfeed 新闻、国家评论、纽约邮报、卫报、NPR、路透社、Vox 和华盛顿邮报的文章组成。根据 Kaggle 上的文档,大多数文章来自 2016 年和 2017 年,少部分来自 2015 年及之前。OpenAI 在 GPT-2 的文档中写道,它应该在特定内容的任务上表现良好,如生成假新闻,无需微调或重新训练,因此使用了 GPT-2 的原始权重。
为了检测假新闻,GPT-2 模型被传递来自真实新闻文章的句子。从这个种子开始,模型生成了长达 500 多个标记的长文本。(记号可以认为是单词和标点符号。)结果,对于每一篇“真正的”文章,都有一个长格式的生成文本,它们共享一个共同的第一句话。每一个生成的文本和真实的文章都通过一个叫做 GLTR 的工具来比较它们的特征。最后,所有的文章被分成一个训练集或测试集,一个 BERT 二元分类器被训练来分类“假”文本。
# 第一部分:LSTM 与变形金刚

自从引入变形金刚以来,自然语言的生成已经有了很大的改进
## 模型选择和基本原理
该团队使用 LSTM(长短期记忆)架构和 transformer 架构探索了文本生成。在 2017 年推出变压器之前,LSTMs 一直被视为 NLP 任务的标准。这样可以进行比较,也可以检查该领域取得的进展。
LSTM(长短期记忆)是一种递归神经网络,它是一种试图对依赖于序列的行为进行建模的模型。这使得 LSTM 成为文本生成的可行候选。在 LSTM 架构中,有 LSTM 单元块来代替标准的神经网络层。这些单元由输入门、遗忘门和输出门组成。要深入了解 LSTM 的建筑(尤其是喀拉斯),可以在这里找到指南。
LSTM 模型最初是由德国计算机科学家于尔根·施密德胡伯和塞普·霍克瑞特尔于 1997 年提出的。他们的出版物描述了他们所做的研究,可以在这里阅读。自 1997 年以来,对 LSTM 进行了改进,例如增加了遗忘门以及在架构中从单元到门的连接。
该代码取自官方的 Keras 文档,最初用于[从尼采的著作中生成文本](https://keras.io/examples/lstm_text_generation/)。使用 LSTM 模型产生的一个问题是随机的,很难[每次固定随机种子以获得 100%可重复的结果](https://machinelearningmastery.com/text-generation-lstm-recurrent-neural-networks-python-keras/)。因此,尽管 LSTM 模型的结果很有趣,但对于项目的目标来说,它并不是非常有用。
除了使用 LSTM 检查文本生成,该团队还使用 OpenAI 的转换器 GPT-2 生成了文本。自 2017 年 Vaswani 等人发表学术论文[“注意力是你所需要的全部”以来,变压器架构通过使用一种称为注意力的技术,已经超越了以前模型的性能。米格尔·罗梅罗·卡尔沃在他写于 Medium 的文章](https://arxiv.org/abs/1706.03762)中很好地解释了注意力是如何在转换器的编码器部分工作的,以及编码器和解码器是如何组合在一起形成一个转换器的。如果您已经熟悉这些架构,或者您对了解它们如何工作的更多技术方面不感兴趣,请继续阅读本文。你不需要应用这些概念来理解项目或其结果。
OpenAI 的 GPT-2 是代表从变形金刚模型生成最先进文本的明显选择。该架构是为文本生成而设计的,不像谷歌人工智能语言研究人员的另一个著名转换器 BERT。GPT 2 号也因其类似人类的性能产生了大量新闻。
GPT-2 模型是使用变压器解码器模块构建的,并且像传统语言模型一样,一次输出一个令牌。它使用字节对编码在其词汇表中创建标记。这意味着标记通常是单词的一部分。
GPT-2 是在一个 800 万网页的数据集上训练的,[被认为是大约 40Gb 的互联网数据](https://openai.com/blog/better-language-models/)。根据 OpenAI 的说法,他们只使用由人类管理/过滤的页面——具体来说,他们使用来自 Reddit 的至少收到 3 个 karma 的出站链接。这给了模型一个自然书写的好主意。
这个语言模型有一个简单的目标:在给定某个文本中所有前面的单词的情况下,预测下一个单词。
GPT-2 至少有四个版本:
* “小型”模型:1.24 亿个参数,500MB 磁盘空间
* “中”:3.55 亿个参数,1.5GB 磁盘空间
* 【大】:7.74 亿个参数
* “超大”:15.58 亿个参数,称为“完整”或“真实模型”,可能占用超过 6.5 GBs 的空间
在所有这些模型可用的情况下,需要进行权衡:较大的模型往往整体表现更好,这意味着当使用较大的模型时,它们会创建更可信的文本,但需要更长的时间来微调和生成文本。为了利用所谓的类似人类的性能,同时仍然有一个足够轻的模型来运行许多文本生成,GPT-2 的“中等”版本被选择来代表模型的变压器类。
## 比较性能

LSTM 示例生成的文本(种子文本以粗体显示):
****‘面对现实的本来面目,而不是本来的样子,或者如你所愿的样子’,说把 l*** *吃了,gadantural 就可以查斯而进入苏塞克斯和王子和萨门特的危局。最后一周的状态和比较和保护和病人的皇家剑桥的领导和帕特查尔斯和案件和地带第一次是从皇家和 raching 她是已知的和说的理由和条件根据免费的迪斯科舞厅,和接触的国家和一个和 retarry 报告君主和自我反省流浪的日子。以生为例,她说君主股自愿为天下之群而生。**
*给定文本,这种情况下的结果并不好。句子不连贯,有些词似乎没有意义。鉴于这是一个旧的 LSTM,一个基于 RNN 的生成器的新版本也被用来生成示例文本。这些改进的示范文本可以更好地比较 RNN 的性能。*
**
*RNN 示例生成的文本(种子文本以粗体显示):*
*****德克萨斯大学奥斯汀分校,*** *tex。而且,一群记者从俄罗斯运动员的名单中,也同样,因为特朗普先生说,他将无法让开,但这在过去五年中并不罕见。华盛顿大学的一组研究人员在一份声明中说:“我们不会让我去学校,告诉我们他们在老房子外面的一个小镇上。“我们不会把你送到大学或学校。”我不想这么做,”特朗普组织的律师迈克尔说,他说,“我觉得我可以把他留在公寓里,这座城市的房子,美国总统说,政府已经“超过”证据。特朗普曾是叙利亚恐怖袭击的目标。*这个国家大概有多少人口**
**这段文字虽然有点荒诞不经,不拘一格,但似乎更有条理,证明了基于 LSTM 的生成器可以很好地生成文本。相同的种子被传递给 GPT-2 生成器,以便更好地进行比较。**
****
**新 GPT 协议生成的文本样本(种子文本以粗体显示):**
**德克萨斯大学奥斯汀分校为想要帮助自己职业生涯的女性机器人学学生提供了一笔高达 6 万美元的奖学金。在该计划的在线部分,参与者将与该大学的一个研究团队合作,创建一个可以在物理空间导航的动画机器人。**
**普通大学生希望设计一个产品,实现一个想法,并有可能获得一份工作。提出“智能机器人实验室”概念的艺术家 Aritappa Chatterjee 说,这通常是不可能的,所以这种类型的项目创造了更多的就业机会。**
**奖学金提供给高中二年级、三年级或四年级的学生。**
***“学生们正在确定这些女性占主导地位的领域,所以我们…”***
**结果与预期相符:GPT-2 创造了可信的短文本,短文本越长,越偏离真实文本。虽然该模型能够保持一个连贯的结构,但仔细观察,其内容可能显得牵强。**
**该模型有一个“温度”设置,一个可以在 0 和 1 之间选择的超参数。温度越高,模型变得越“有创造性”,这意味着它不会添加最有可能的下一个单词,而是从更大的池中取样。因为使用了 0.7 的比较性能温度,这给出了看起来最一致的内容创建。**
**从例子中可以明显看出,GPT-2 在生成文本方面比基于 LSTM 的模型表现得更好。这里选择的例子可以被看作是“樱桃采摘”,但随机选择,通常代表了整体观察到的模式。**
## **正在使用的文本生成的玩具示例**
**这篇文章的标题是由 arxiv.org 过去 6 个月的机器学习相关文章标题微调的 GPT-2 模型生成的。**
****
**生成标题**
**种子短语是本文的第一段:“假新闻的兴起迫使每个拥有社交媒体账户的人都成为一名侦探,负责在分享之前确定一篇帖子是否真实……”**
**完整的输出是:“调查社交媒体上的假新闻:**首先打击错误信息的深度学习方法**?”,粗体文本被保留为标题(!).**
# **第二部分:假新闻检测**
****
## **鉴别器**
**鉴别器是一种深度学习模型,它对不同生成过程产生的样本进行分类(鉴别)。鉴别器通常用于生成对抗神经网络(GANs ),它与生成模型一起工作,以迭代地改进生成过程,使其输出越来越接近“真实”的例子。一种类似的鉴别器被用来鉴别 GPT-2 产生的文本,但所用的过程并不包括对发生器和鉴别器的迭代训练。此外,人类很难识别生成的文本,因此对这种模型的潜在性能有很多怀疑。**
**从另一个角度来看这个问题,如果生成的文本和真实的文章共享相同的主题,那么生成的文本和真实的对应文本之间的相似性的度量可能有助于了解生成的文本的特征。基于“相似性”比较文本的第一种方法是一种称为 bertScore 的改进度量,它计算两个句子中单词的余弦相似性。**
**这种实现虽然表面上看起来很有前途,但并没有说明所使用的生成模型所展示的“创造性”。虽然相似性确实可以计算和进一步分析,但生成的文本在内容上与原始文本有很大差异。从一条关于新奖学金获得者的新闻中提取的种子句子可能会导致关于一个年轻而聪明的策划者的珠宝抢劫案的生成文本。在完全不同的上下文中评估相似性被证明对提供洞察力没有帮助,因为度量标准只是报告生成的文本与原始文章非常不同。**
**在评估这种相似性度量时,观察到生成的文本倾向于使用不太复杂的词汇,并且经常依赖于重复的短语。相比之下,最初的新闻文章更倾向于通过逻辑故事线流动,沿途经过不同的主题和想法。这一观察刺激了对诸如巨型语言模型测试室等工具的进一步研究,这些工具似乎也依赖于生成文本的复杂性和多样性。**
****
**这个 **G** iant **L** 语言模型**T**est**R**oom([GLTR](http://gltr.io/dist/index.html))是由哈佛 NLP 和麻省理工学院-IBM 沃森人工智能实验室合作创建的。这个工具利用了一个模型,伯特或 GPT-2,它一个字一个字地查看这个词在句子中被选中的概率。在下面的图片中,绿色代表最有可能的前 10 个单词中的一个单词,黄色是前 100 个,红色是前 1000 个,紫色大于 1000 个。这意味着绿色单词是模型可能输出为下一个单词的单词,并且随着该单词变得不太可能被模型选择,它落入其他颜色箱中的一个。例如,下面的图片是一个人写的纽约时报文章的片段。这篇文章有几个可预测的词,但也包括许多生成模型不太可能选择的词。那是因为人类在书写时没有考虑到 ***最有可能是*** 的下一个单词;他们会考虑哪个词最适合文章的上下文以及他们想要表达的意思。**
****
**单词分布的差异显示在所示的四幅图像中。当使用带有 GPT-2 鉴别器的 GLTR 工具时,虚假文章(左上)比真实文章(右上)具有更高的高预测性单词分布。当对假文本(左下)和真文本(右下)使用 BERT 鉴别器时,发现了类似的模式。有了这两种鉴别器,在发电机和人类的词汇选择上就有了明显的区别。这支持了我们的直觉,即生成器只会基于单词的概率而不是基于上下文来构造文本。虽然这个项目没有开发一个数字度量来确定一个文本是否是计算机生成的,但是查看 GLTR 的输出可以提供一些见解。**
**针对上述限制,寻求第二种鉴别器。在研究假新闻鉴别器时,一些作者分享了他们使用 BERT 编码器结合某种分类器的成功经验。出于输出/输入兼容性的考虑,选择了 BERT 编码器和 BERT 二进制分类器的组合,并按照本例中的[用 Python 实现了分类器。尽管原始 Medium 文章的作者对这种分类器寄予厚望,但该模型的计算成本很高(运行一个时期估计需要 15-21 小时),并且在该项目的实验运行中,无法以比简单猜测更好的速度对“真实”和生成的文本进行分类。有可能我们的实现过于简单,应该在传递到 BERT 编码器之前对输入进行额外的特性工程处理。或者,这种特征增强在 BERT 编码器和 BERT 二进制分类器之间可能是有用的。然而,为这个项目所做的工作没有提供任何有希望的迹象,表明这种额外的努力可能会产生预期的精度增益。](/fake-news-classification-with-bert-afbeee601f41)**
**BERT 分类器的缺点表明了最先进的自然语言生成模型的优异性能。依靠复杂性和创造性的措施,结合整体一致性的措施的鉴别器是有潜力的。像 GPT-2 这样的模型可以骗过一个鉴别器,它只是简单地设置一个阈值,看看单词不在最有可能被选择的前 10 名或前 100 名中的频率。人们可以通过提高模型的温度来做到这一点,给它更多的自由来探索鉴别者可能认为“不太可能”的单词和概念。但是如果鉴别者也可以测量整篇文章的连贯性,那么它将更容易识别出这些文本是生成的,因为更多“创造性”的文本往往对阅读它们的人来说最没有意义。**
## **未来工作的领域**
* **创建一个侧重于复杂性/创造性的评分标准**
* **创建一个使用此度量的虚假文本分类器**
* **进一步考察“虚假”的特征**
* **使用白盒对抗性攻击来观察哪些特征使文本更有可能是假的**
# **结论**
**这个项目展示了自然语言生成模型在过去三四年中的进展:从 LSTMs 的不连贯到现在由 OpenAI 开发的听起来很流畅的 GPT-2 模型。撇开发展生成模型的这些进展不谈,人们可以看到这可能留给我们的危险境地。生成文本模型没有“真实”或“虚假”之分,因此听起来真实的生成模型几乎肯定会产生可信的“假新闻”展望未来,人工智能研究人员、学者和行业领袖将面临越来越不可能的任务,即找到识别生成文本的方法。**
# **链接到 GitHub Repo**
**[认知计算 GitHub](https://github.com/stevenoluwaniyi/cognitive_computing)**
# 使用 Ubuntu 18.04 设置深度学习工作站的权威指南
> 原文:<https://towardsdatascience.com/a-definitive-guide-for-setting-up-a-deep-learning-workstation-with-ubuntu-18-04-5459d70e19c3?source=collection_archive---------2----------------------->

## DL 钻机
## CUDA,CuDNN,Python,Pytorch,Tensorflow,RAPIDS
Lambda 和其他供应商提供预建的[深度学习工作站](https://lambdalabs.com/gpu-workstations/vector?utm_source=medium-rahul-agarwal&utm_medium=blog-shout-out&utm_campaign=blogin),配备新的安培 RTX 3090、3080 和 3070 GPU——但如果你有兴趣构建自己的工作站,请继续阅读。
创建自己的工作站至少是我的一个梦想。我知道这个过程,但不知何故,我从来没有去过。
但这次我不得不这么做。因此,我找了一些空闲时间,在 NVIDIA 的帮助下创建了一个深度学习平台,他们非常有帮助。在这方面,特别感谢[乔希·帕特森](https://medium.com/u/a994b4ad25d0?source=post_page-----5459d70e19c3--------------------------------)和迈克尔·库帕。
现在,每当我从安装角度创建整个深度学习设置时,我都会面临类似的挑战。这就像是带着各种各样的依赖和错误在兜圈子。这一次,我也不得不在整个配置没有错误的情况下尝试很多东西。
*所以这一次,在我自己的系统中安装所有需求和它们的依赖关系时,我特意记录了所有的东西。*
***这篇帖子是关于设置你自己的 Linux Ubuntu 18.04 系统,用于深度学习,拥有你可能需要的一切。***
*如果首选预建的深度学习系统,我可以推荐工作站和服务器的* [*Exxact 的 line*](https://www.exxactcorp.com/Deep-Learning-NVIDIA-GPU-Solutions?utm_source=web%20referral&utm_medium=backlink&utm_campaign=Rahul%20Agarwal) *。*
我假设你已经安装了新的 Ubuntu 18.04。我从 2017 年的[斯拉夫·伊万诺夫的](https://blog.slavv.com/@slavivanov?source=post_page-----148c5ebe6415----------------------)精彩[帖子中获得了关于创建深度学习盒子的灵感。从设置的角度来看,你可以将它称为同一篇文章的 2020 版本,但从那时起许多事情都发生了变化,并且有许多关于 Tensorflow 和 Pytorch 不支持的特定 CUDA 版本的警告。](https://blog.slavv.com/the-1700-great-deep-learning-box-assembly-setup-and-benchmarks-148c5ebe6415)
# 启动

由 [Serghei Trofimov](https://unsplash.com/@sergeytrofimov?utm_source=medium&utm_medium=referral) 在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄
在对我们的安装做任何事情之前,我们需要将我们的 Linux 系统更新到最新的包。我们可以简单地通过使用:
sudo apt-get update
sudo apt-get --assume-yes upgrade
sudo apt-get --assume-yes install tmux build-essential gcc g++ make binutils
sudo apt-get --assume-yes install software-properties-common
sudo apt-get --assume-yes install git
# 该过程
现在我们已经做好了一切准备,我们要安装以下四样东西:
1. GPU 驱动程序:为什么你的电脑不支持高图形分辨率?或者你的显卡如何与你的 python 接口对话?
2. **CUDA** :提供访问 GPU 指令集和并行计算单元的层。简单地说,它允许我们为 GPU 编写代码
3. **CuDNN** :为深度学习网络提供原语的库
4. **Pytorch、Tensorflow 和 Rapids** :编码深度神经网络的高级 API
## 1.GPU 驱动程序
第一步是添加最新的 NVIDIA 驱动程序。18.04 版本可以选择 GPU 产品类型,Linux 64 bit,下载类型为“Linux 长寿命”。

点击搜索将带您进入下载页面:

您可以从这里下载驱动程序文件`NVIDIA-Linux-x86_64–440.44.run`并使用以下命令运行它:
chmod +x NVIDIA-Linux-x86_64–440.44.run
sudo sh NVIDIA-Linux-x86_64–440.44.run
对于您来说,该文件可能会有不同的名称,这取决于最新的版本。
## 2.库达
我们现在需要安装 CUDA 工具包。不知何故,Pytorch 和 Tensorflow 仍然不支持 CUDA toolkit 10.2,所以我们将使用两者都支持的 CUDA Toolkit 10.1。
此外,CUDA 10.1 产品页面上的命令对我不起作用,我最终使用的命令是:
sudo apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub && echo "deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64 /" | sudo tee /etc/apt/sources.list.d/cuda.listsudo apt-get update && sudo apt-get -o Dpkg::Options::="--force-overwrite" install cuda-10-1 cuda-drivers
下一步是创建 LD_LIBRARY_PATH,并将安装 CUDA 的路径附加到 PATH 变量中。只需在您的终端上运行以下命令。
echo 'export PATH=/usr/local/cuda-10.1/bin\({PATH:+:\){PATH}}' >> ~/.bashrc && echo 'export LD_LIBRARY_PATH=/usr/local/cuda-10.1/lib64\({LD_LIBRARY_PATH:+:\){LD_LIBRARY_PATH}}' >> ~/.bashrc && source ~/.bashrc && sudo ldconfig
之后,可以使用以下命令检查 CUDA 是否安装正确:
nvcc --version

如你所见,CUDA 版本是我们想要的 10.1。另外,检查您是否可以使用该命令:
nvidia-smi
对我来说,当我第一次使用它时,它显示了一个错误,但是一个简单的重启就解决了这个问题。我的两个 NVIDIA 显卡都光彩照人。不用担心显示屏上说支持的 CUDA 版本是 10.2。我也被[弄糊涂了](https://stackoverflow.com/questions/53422407/different-cuda-versions-shown-by-nvcc-and-nvidia-smi),但这只是`nvidia-smi`中显示的图形驱动程序支持的最高 CUDA 版本。

## 3.CuDNN
如果我们不打算训练神经网络,那么所有这些库有什么用?CuDNN 提供了深度学习的各种原语,后来被 PyTorch/TensorFlow 使用。
但是我们首先需要得到一个[开发者帐号](https://developer.nvidia.com/rdp/form/cudnn-download-survey)来安装 CuDNN。一旦你填写了注册表格,你会看到下面的屏幕。选择适合您的 CUDA 版本的 cuDNN 版本。对我来说,CUDA 版本是 10.1,所以我选择第二个。

选择合适的 CuDNN 版本后,屏幕会展开:

对于我的用例,我需要为 Ubuntu 18.04 下载三个文件:
cuDNN Runtime Library for Ubuntu18.04 (Deb)cuDNN Developer Library for Ubuntu18.04 (Deb)cuDNN Code Samples and User Guide for Ubuntu18.04 (Deb)
下载这些文件后,您可以使用这些命令进行安装。如果未来发生任何变化,您还可以看到确切的[命令](https://docs.nvidia.com/deeplearning/sdk/cudnn-install/index.html):
Install the runtime library:
sudo dpkg -i libcudnn7_7.6.5.32-1+cuda10.1_amd64.deb#Install the developer library:
sudo dpkg -i libcudnn7-dev_7.6.5.32-1+cuda10.1_amd64.deb#Install the code samples and cuDNN User Guide(Optional):
sudo dpkg -i libcudnn7-doc_7.6.5.32-1+cuda10.1_amd64.deb
## 4.蟒蛇,Pytorch,张量流和急流
最后,我们到达了症结所在。我们将安装大部分时间都要使用的软件。
我们需要在虚拟环境中安装 Python。我已经下载了 python3,因为它是目前最稳定的版本,是时候和 Python 2.7 说再见了。当它持续的时候,它是伟大的。我们还将安装 Pytorch 和 Tensorflow。在适用的特定任务中,我更喜欢他们两个。
你可以去 [anaconda 发行版](https://www.anaconda.com/distribution/)页面下载这个包。

下载后,您只需运行 shell 脚本:
sudo sh Anaconda3-2019.10-Linux-x86_64.sh
您还需要在您的 shell 上运行这些命令,将一些命令添加到您的`~/.bashrc`文件中,并使用最新的库版本更新 conda 发行版。
cat >> ~/.bashrc << 'EOF'
export PATH=\(HOME/anaconda3/bin:\){PATH}
EOFsource .bashrc
conda upgrade -y --all
下一步是为你的深度学习追求创造一个新的环境,或者使用一个现有的环境。我使用以下工具创建了一个新的 Conda 环境:
conda create --name py37
这里,py37 是我们为这个新的 conda 环境提供的名称。您可以使用以下方式激活 conda 环境:
conda activate py37
您现在应该能够看到类似这样的内容:

请注意终端中命令开头的 py37
我们现在可以使用 pip 或 conda 将所有需要的包添加到这个环境中。正如我已经提到的,从 [pytorch 网站](https://pytorch.org/get-started/locally/)看到的最新版本 1.3 还不能用于 CUDA 10.2,所以我们很幸运有了 CUDA 10.1。此外,我们需要将 TensorFlow 的版本指定为 2.1.0,因为这个版本是使用 10.1 CUDA 构建的。
我还安装了 RAPIDS,这是一个将各种数据科学工作负载转移到 GPU 的库。为什么 GPU 只用于深度学习而不用于数据处理?您可以从 [rapids 发布选择器](https://rapids.ai/start.html)中获得安装 rapids 的命令:

sudo apt install python3-pipconda install -c rapidsai -c nvidia -c conda-forge -c defaults rapids=0.11 python=3.7 cudatoolkit=10.1pip install torchvision
由于 PyTorch 安装会干扰 TensorFlow,所以我在另一个环境中安装了 TensorFlow。
conda create --name tf
conda activate tf
pip install --upgrade tensorflow
现在,我们可以通过在 TF 和 Pytorch 各自的环境中使用以下命令来检查它们的安装是否正确:
Should print True
python3 -c "import tensorflow as tf; print(tf.test.is_gpu_available())"# should print cuda
python3 -c "import torch; print(torch.device('cuda' if torch.cuda.is_available() else 'cpu'))"
如果安装显示 TensorFlow 出现一些错误,或者 GPU 测试失败,您可能需要在`bashrc`文件的末尾添加这两行,然后重新启动终端:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/extras/CUPTI/lib64:/usr/local/cuda/lib64export CUDA_HOME=/usr/local/cuda
你可能还想安装`jupyter lab`或`jupyter notebook`。感谢开发者,这个过程就像在你的终端上运行`jupyter lab`或`jupyter notebook`一样简单,无论你喜欢哪个。我个人更喜欢没有不必要的杂物的笔记本。
# 结论
***在这篇文章中,我谈到了你将需要毫不费力地在你的深度学习装备中安装的所有软件。***
你可能仍然需要一些帮助和面对一些问题,我最好的建议是去看看不同的 NVIDIA 和 Stack Overflow 论坛。
因此,我们已经有了深度学习装备设置,现在是进行一些测试的时候了。在接下来的几篇文章中,我将对 GPU 进行一些基准测试,并尝试编写更多关于各种深度学习库的文章,这些库可以包含在他们的工作流中。敬请关注。
# 继续学习
如果你想了解更多关于[深度学习的知识,这里](https://coursera.pxf.io/7mKnnY)是一门优秀的课程。您可以免费开始 7 天的免费试用。
谢谢你的阅读。将来我也会写更多初学者友好的帖子。在 [**媒体**](https://medium.com/@rahul_agarwal?source=post_page---------------------------) 关注我或者订阅我的 [**博客**](https://mlwhiz.ck.page/a9b8bda70c) 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter[**@ mlwhiz**](https://twitter.com/MLWhiz?source=post_page---------------------------)联系
此外,一个小小的免责声明——这篇文章中可能会有一些相关资源的附属链接,因为分享知识从来都不是一个坏主意。
# 影响大小的权威指南
> 原文:<https://towardsdatascience.com/a-definitive-guide-to-effect-size-9bc93f00db86?source=collection_archive---------8----------------------->

由 [Kaboompics 拍摄的照片。com](https://www.pexels.com/@kaboompics?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels) 来自 [Pexels](https://www.pexels.com/photo/scientific-calculator-ii-5775/?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels)
## 了解如何正确计算和解释 A/B 测试的影响大小!
作为一名数据科学家,在进行某种 A/B 测试时,您很可能会遇到影响大小的问题。一种可能的情况是,公司希望对产品进行更改(无论是网站、移动应用程序等。)而你的任务是确保这种改变在一定程度上会带来更好的 KPI 表现。
这就是假设检验发挥作用的时候了。然而,统计测试只能告知影响存在的可能性。就效果而言,我只是指一种差异——它可以是两个方向上的差异,但也可以是一种假设的更精确的变体,即一个样本实际上比另一个样本更好/更差(根据给定的指标)。为了知道影响有多大,我们需要计算影响大小。
在本文中,我将提供一个关于效果大小的简单理论介绍,然后展示一些如何在 Python 中计算它的实际例子。
# 理论介绍
从形式上来说,**效应大小**是我们正在研究的现象的量化大小。如前所述,统计测试得出了观察到一种效应的概率,然而,它们并没有具体说明这种效应实际上有多大。这可能会导致这样的情况:我们检测到统计上的显著影响,但它实际上非常小,对于实际情况(业务)来说,它可以忽略不计,一点也不有趣。
此外,在计划 A/B 测试时,我们希望估计测试的预期持续时间。这与**功耗分析**的主题有关,我在[的另一篇文章](/introduction-to-power-analysis-in-python-e7b748dfa26)中提到过。快速总结一下,为了计算所需的样本量,我们需要指定三件事:显著性水平、检验的功效和效应大小。保持其他两个不变,效应大小越小,就越难以某种确定性来检测它,因此统计检验所需的样本量就越大。
一般来说,可能有数百种不同的效果大小的测量方法,每一种都有一些优点和缺点。在这篇文章中,我将只介绍一些最流行的。在深入研究兔子洞之前,效应大小的度量可以根据它们定义效应的方法分为三类。这些群体是:
* 基于相关性的度量
* 基于差异的指标(例如,平均值之间)
* 分类变量的度量
前两个系列涵盖连续随机变量,而最后一个系列用于分类/二元特征。举一个现实生活中的例子,我们可以将前两个应用于一个指标,如在一个应用程序中花费的时间(以分钟为单位),而第三个系列可以用于转换或保留-以布尔值表示。
我将在下面描述一些效果大小的度量,以及 Python 实现。

Vishwarajsinh Rana 在 [Unsplash](https://unsplash.com/s/photos/calculator?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上拍摄的照片
# Python 中的示例
在这一部分中,我将更详细地描述每个效果大小系列的几个例子,并展示如何使用流行的库在 Python 中计算它们。当然,我们也可以自己编写这些函数,但是我认为没有必要重新发明轮子。
作为第一步,我们需要导入所需的库:
## 1.相关家族
这个组的名字(也称为“r 族”)来自两个变量之间关联的度量——相关性。到目前为止,最流行的相关性度量是皮尔逊相关系数(皮尔逊的 *r* )。
在深入研究指标之前,我们将从多元正态分布中生成一些随机的相关变量。它们有不同的含义,因此我们实际上可以检测到一些影响,同时为了简单起见,我们将方差保持为 1。
请记住,我们生成的随机观察越多,它们的分布就越像我们指定的分布。
**皮尔森的*r***
这并不奇怪,因为这个家族的名字就是基于这个标准。皮尔逊相关系数衡量两个实值变量之间的线性关联程度。该度量是无单位的,表示为[-1,1]范围内的数字。为简洁起见,我只描述极端情况的解释:
* 值-1 表示变量之间完全负相关,
* 值 0 表示没有线性关系,
* 值为 1 表示完美的正关系。
由于这通常是最常用的指标之一,因此在 Python 中有许多计算相关系数的方法:
* `pearsonr`在`scipy.stats`中——除了相关系数,我们还接收相关测试的 p 值。引用[文档](https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.pearsonr.html):"*p 值大致表示不相关系统产生的数据集的皮尔逊相关性至少与从这些数据集计算出的值一样极端的概率。*
stats.pearsonr(x[:,0], x[:,1])
(0.6023670412294826, 0.0)
* `numpy.corrcoef` —返回相关矩阵,使用`rowvar`指示随机变量的观察值是存储在行中还是列中。
np.corrcoef(x, rowvar=False)
array([[1. , 0.60236704],
[0.60236704, 1. ]])
* `pandas`数据帧/系列的`corr`方法。
* `pingouin`的`corr`函数——默认情况下,它返回皮尔逊的 *r* 系数(也可以使用其他相关性度量)。与`scipy`相反,该函数返回相关性测试的更详细的结果。我们也可以使用检验的单侧变量。
pg.corr(x[:, 0], x[:, 1])

**决定系数(R )**
在这个家族中,效应大小的第二个度量是决定系数,也称为 R。它说明了自变量解释(可预测)的因变量方差的比例。换句话说,这是一个衡量观察到的结果如何被模型复制的标准。
决定系数有几种定义,然而,对我们来说最相关的是与皮尔逊的 r 相关的定义。当使用包含截距的简单线性回归(有一个因变量)时,决定系数就是皮尔逊的 *r* 的平方。如果有更多的因变量,R 是多重相关系数的平方。
在上述任何一种情况下,决定系数通常在 0 和 1 之间。但是,如果使用另一个定义,这些值也可能变成负值。由于我们平方相关系数的事实,决定系数不传达任何关于相关方向的信息。
我们可以通过运行简单的线性回归并检查报告值来计算决定系数:
* 使用`pingouin`:
pg.linear_regression(x[:, 0], x[:, 1])

* 使用`statsmodels`:

在这两种情况下,决定系数接近 0.36,这是相关系数(0.6)的平方。
**η平方( *η* )**
该系列中最后考虑的度量是 eta 平方。它是一个预测因子在因变量中解释的方差比率,同时控制其他预测因子,这使它类似于 r。

其中 SS 代表平方和。 *η* 是模型解释的总体方差的有偏估计量,因为它仅估计所考虑样本中的效应大小。这意味着 eta 平方将总是高估实际效应大小,尽管这种偏差随着样本大小的增加而变小。Eta-squared 也有 r 的弱点——每个额外的变量都会自动增加 *η* 的值。
为了用 Python 计算 eta 的平方,我们可以使用`pingouin`库:
pg.compute_effsize(x[:, 0], x[:, 1], eftype='eta-square')
0.057968511053166284
此外,该库包含一个名为`convert_effsize`的有用函数,它允许我们将 Pearson 的 *r* 或 Cohen 的 *d* 测量的效果大小转换为 eta-squared 等。
## 2.“差异”家庭
第二个家族被称为差异家族,这可能是衡量效应大小的最常用方法——计算样本平均值之间的差异。通常,该差异也通过除以标准偏差(任一或两个群体)来标准化。
实际上,人口数值是未知的,只能通过抽样统计来估计。这就是为什么有多种方法来计算均值之间的差异的影响大小——它们在使用的样本统计方面有所不同。
另一方面,这种估计效应大小的形式类似于计算 *t* 统计量,不同之处在于标准偏差除以 *t* 统计量分母中 *n* 的平方根。与 T21 统计不同,效应大小旨在估计总体水平的值,不受样本大小的影响。
这一族也被称为“ *d 族*”,以估计效应大小的最常见方法——Cohen 的 *d.* 命名
在深入研究指标之前,我们先定义两个来自正态分布的随机变量。我们使用不同的均值和标准差来确保变量有足够的差异来获得合理的效应大小。

两个随机变量的分布
**科恩的 d**
科恩的 *d* 测量两个变量的均值之间的差异。差异以标准差的数量表示,因此在公式中有除法。科恩的 *d* 定义为:

其中 *s* 为合并标准差,S1、S2 为两个独立样本的标准差。
**注**:一些来源使用不同的集合标准差公式,并且分母中不包括-2。
对效应大小的最常见解释如下:
* 小效果尺寸:d=0.2
* 中等效果尺寸:d=0.5
* 大效果尺寸:d=0.8
Cohen 的 *d* 经常用于估算 A/B 测试所需的样本量。一般来说,Cohen 的 *d* 值越低,表明需要更大的样本量,反之亦然。
在 Python 中计算 Cohen 的 *d* 的最简单方法是使用`pingouin`库:
pg.compute_effsize(x, y, eftype='cohen')
-0.5661743543595718
## 玻璃'δ'
Glass 的δ与 Cohen 的 *d* 非常相似,不同之处在于使用了第二个样本(A/B 测试中的对照组)的标准偏差,而不是混合标准偏差。

仅使用对照组的标准差的基本原理是基于这样的事实,即如果我们将多个治疗组与同一对照组进行比较,这样我们将在所有情况下具有共同的标准。
pg.compute_effsize(x, y, eftype='glass')
-0.6664041092152272
**对冲的 g**
Cohen 的 *d* 是总体水平效应大小的有偏估计量,尤其是对于小样本(n < 20)。这就是为什么 Hedge 的 *g* 通过将 Cohen 的 *d* 乘以修正系数(基于伽马函数)来进行修正:

pg.compute_effsize(x, y, eftype='hedges')
-0.5661722311818571
我们可以看到科恩的 *d* 和对冲的 *g* 的差别非常小。对于较小的样本量,这种情况会更明显。
## 3.绝对家族
这一族用于估计分类(以及在一些简单的情况下——二元)随机变量的效应大小。我们通过运行以下代码片段来生成该部分的随机变量:
**φ(φ系数)**
phi 系数是卡尔·皮尔逊引入的两个二元变量之间关联的度量,与 2x2 [列联表](https://en.wikipedia.org/wiki/Contingency_table)的卡方统计相关。在机器学习术语中,列联表基本上与混淆矩阵相同。

当大部分数据落在列联表的对角线上时,两个二元随机变量是正相关的(想想真正的正和真正的负)。相反,当大部分数据脱离对角线时,变量是负相关的(想想假阳性和假阴性)。
事实上,为两个二元变量计算的皮尔逊相关系数( *r* )会得出 phi 系数(我们将用 Python 来证明)。然而,phi 系数的范围不同于相关系数,尤其是当至少一个变量取两个以上的值时。
此外,在机器学习中,我们看到马修斯相关系数作为评估分类模型性能的一种度量标准越来越受欢迎。事实上,MCC 就是皮尔逊的 phi 系数。
Phi/MCC 考虑了混淆矩阵/列联表的所有元素,这就是为什么它被认为是一个平衡的评估指标,也可以在类别不平衡的情况下使用。
运行代码会产生以下输出:
Phi coefficient: 0.000944
Matthews Correlation: 0.000944
Pearson's r: 0.000944
**克莱默 V**
cramér’s V 是分类变量之间关联的另一种度量(不限于二元情况)。

其中 *k* 和 *r* 代表列数和行数,φ是上面计算的φ系数。
克拉默的 V 取值范围为 0(变量之间没有关联)到 1(完全关联)。请注意,对于 2x2 列联表(两个二元变量)的情况,Cramér 的 V 等于 phi 系数,我们将很快在实践中看到这一点。
对克拉默 V 的大小最常见的解释如下:
* 小效果尺寸:V ≤ 0.2
* 中等效果尺寸:0.2 < V ≤ 0.6
* Large Effect Size: 0.6 < V
Cramer's V: 0.000944
We have indeed obtained the same value as in the case of the phi coefficient.
**科恩的 w**
Cohen 提出了效应大小的另一种度量,它“随着替代假设指定的分布与代表零假设的分布之间的差异程度而增加”(更多详细信息,请参见[1]第 216 页)。在这种情况下,我们处理的是比例(所有观察值的一部分),而不是之前度量的列联表。

其中:
* p_{0i} —零假设下单元格 *i* 中的比例,
* p_{1i} —替代假设下单元格 *i* 中的比例,
* m —细胞数量。
Cohen 的 *w* 测量的效应大小被认为对于接近 0.1 的值是小的,对于大约 0.3 是中等的,对于大约 0.5 是大的。
Cohen's w: 0.173820
**科恩的 h**
另一种用于比较两个独立样本比例的方法是科恩的 *h* ,定义如下:

其中 P1 代表第一个样本中阳性病例的比例。为了评估影响大小的大小,作者提出了与科恩的 *d* 相同的指示值范围。
Cohen's h: 0.174943
**优势比**
通过比值比测量的效应大小通过注意到治疗组中事件发生的比值比对照组高/低 X 倍来计算。

Odds Ratio: 1.374506
事件(例如转化)发生的几率在`x`组中比在`y`组中高约 1.37 倍,这与生成数据时提供的概率一致。
## **加成:通用语言效果大小**
最后一个指标非常有趣,因为——顾名思义——它旨在用每个人都能理解的简单语言来表达效果大小。也不属于上面提到的家庭。作者在[2]中将这一指标描述为:
> 从一个分布中随机抽取的分数大于从其他分布中抽取的分数的概率。
为了使描述尽可能清楚,我将转述文中提到的例子。假设我们有一个成年男女的身高样本,CLES 是 0.8。这将意味着在 80%随机选择的配对中,男性将高于女性。或者换个说法,10 次相亲中有 8 次,男方会高于女方。

随机生成的高度的分布
# **结论**
在本文中,我介绍了影响大小的不同度量,并展示了如何在 Python 中计算它们。了解这些,或者每个家族至少有一个关键指标,在使用 frequentist 方法计划 A/B 测试时肯定会派上用场。
您可以在我的 [GitHub](https://github.com/erykml/medium_articles/blob/master/Statistics/effect_size.ipynb) 上找到本文使用的代码。一如既往,我们欢迎任何建设性的反馈。可以在 [Twitter](https://twitter.com/erykml1?source=post_page---------------------------) 或者评论里联系我。
如果您对本文感兴趣,您可能也会喜欢:
[](/the-new-kid-on-the-statistics-in-python-block-pingouin-6b353a1db57c) [## Python 统计块中的新成员:pingouin
### 图书馆的快速参观,以及它是如何从老守卫中脱颖而出的
towardsdatascience.com](/the-new-kid-on-the-statistics-in-python-block-pingouin-6b353a1db57c) [](/one-tailed-or-two-tailed-test-that-is-the-question-1283387f631c) [## 单尾还是双尾检验,这是个问题
### 了解统计测试的两种变体之间的区别,以及如何在 Python 中实现它们
towardsdatascience.com](/one-tailed-or-two-tailed-test-that-is-the-question-1283387f631c) [](/introduction-to-power-analysis-in-python-e7b748dfa26) [## Python 中的功耗分析简介
### 了解概念的重要性,如显著性水平、效应大小、统计功效和样本大小
towardsdatascience.com](/introduction-to-power-analysis-in-python-e7b748dfa26)
# 参考
[1]科恩,J. (2013)。*行为科学的统计功效分析*。学术出版社。
[2] McGraw,K. O .,& Wong,S. P. (1992 年)。一种常见的语言效应大小统计。*心理通报,111* (2),361–365。https://doi.org/10.1037/0033-2909.111.2.361
# 使用 Azure 将 CSV 文件转换为 Power BI 视觉效果的权威指南
> 原文:<https://towardsdatascience.com/a-definitive-guide-to-turn-csv-files-into-power-bi-visuals-using-azure-4483cf406eab?source=collection_archive---------30----------------------->
## 使用 Microsoft Azure 产品将新冠肺炎数据转化为惊人的 Power BI 视觉效果的分步指南。

照片由[马太·亨利](https://burst.shopify.com/@matthew_henry)在[上爆](https://burst.shopify.com/)
云、大数据和商业智能是这十年的三个热门词汇。每个人都在谈论他们。每个人都想做。但是没人告诉你怎么做。你如何使用*云*来处理你的*大数据*并围绕它构建*智能*来做出*业务*决策?
这个问题有多种答案,在本指南中,我们试图使用微软的云解决方案(Azure)和微软的 BI 工具(Power BI)来回答这个问题,以帮助您朝着正确的方向开始。
微软 Azure 是领先的云解决方案提供商之一,提供一套端到端的工具和技术来摄取、分析和消费大量的数据源和数据格式。
**注意:** *Microsoft Azure 是一项付费服务,遵循本文可能会导致您或您的组织承担财务责任。*
*在继续阅读本文之前,请阅读我们的使用条款:*[*https://dhyanintech . medium . com/disclaimer-disclosure-disclosure-terms-of-use-fb3 BF BD 1e 0e 5*](https://dhyanintech.medium.com/disclaimer-disclosure-terms-of-use-fb3bfbd1e0e5)
# 先决条件
1. 有效的 Microsoft Azure 订阅
如何获得 Azure 订阅?
[](https://azure.microsoft.com/en-us/free/) [## 立即创建您的 Azure 免费帐户| Microsoft Azure
### 利用人工智能创造个性化体验构建互联的跨平台体验-为客户互动量身定制…
azure.microsoft.com](https://azure.microsoft.com/en-us/free/)
以一种简单、易于理解和可用的形式表示数据的第一步是识别数据的来源和格式。传统上,数据专业人员专注于*提取、转换&加载(ETL)* 加载和转换数据。Azure 的出现打开了在无限和前所未有的规模上处理无结构数据的大门。此变更将转换和加载数据转移到*提取、加载&转换(ELT)* 。基本原理和步骤保持不变;他们只是遵循不同的顺序。Azure 中的数据项目通常包括以下步骤:
1. **获取:**确定加载数据的工具、技术和方法
2. **准备和培训:**确定转换数据的工具、技术和方法
然后是两个额外的步骤来分析和使用清理后的数据
* **建模和服务:**确定建模和分析数据的工具和方法
* **消费:**确定消费或呈现数据的工具和技术
在这篇文章中,我们将借助一个例子,通过 ELT 的不同阶段,了解在 Azure 中转换和加载数据的整体方法。为了开始我们的旅程,我们将:
* 从 GitHub 获取公开的新冠肺炎数据(*来源*)
* 借助 Azure Data Factory ( *摄取*)将 CSV 文件存储到 Azure Data Lake Storage Gen2
* 将 CSV 文件转换并清理为 Azure Databricks 中的关系数据(*准备和培训*)
* 将清理后的数据存储在 Azure Synapse Analytics 数据仓库*(建模和服务)*
* 最后,以 Power BI 视觉效果的形式呈现准备好的数据(*消耗*)
# 体系结构
下图提供了我们旅程的高度可视化:

典型的现代数据仓库架构(图片由作者提供)
# 数据流
1. 使用 Azure Data Factory 以网页的形式从 GitHub 获取 CSV 数据。
2. 将传入的数据作为 CSV 文件保存在 Azure Data Lake 存储中。
3. 利用 Azure Databricks 来执行可扩展的分析,并实现清理和转换的数据(或者使用 PolyBase 来清理、转换和直接加载到 Azure Synapse Analytics 数据仓库)。
4. 将清理和转换后的数据移动到 Azure Synapse Analytics 数据仓库,以与现有的结构化数据相结合。
5. 在 Azure Synapse Analytics 数据仓库的基础上使用 Power BI 构建报告和仪表板,以从数据中获得洞察力。
# 成分
* [**Azure Data Factory**](https://azure.microsoft.com/en-us/services/data-factory/):一种混合数据集成服务,用于创建、调度和编排 ETL 和 ELT 工作流
* [**Azure 数据湖存储**](https://azure.microsoft.com/en-us/services/storage/data-lake-storage/) :面向非结构化数据、图像、视频、音频、文档等的大规模可扩展且经济高效的存储。
* [**Azure data bricks**](https://azure.microsoft.com/en-us/services/databricks/):快速、简单、可扩展和协作的基于 Apache Spark 的分析平台
* [**Azure Synapse Analytics**](https://azure.microsoft.com/en-us/services/synapse-analytics/):基于大规模并行处理架构的可扩展弹性云数据仓库,将企业数据仓库和大数据分析结合在一起
* [**Power BI**](https://powerbi.microsoft.com/en-us/) :一套业务分析工具,提供来自数百个数据源的见解,简化数据准备,并推动即席分析
下一步是设置完成数据项目所需的资源和组件。在典型设置中,数据工程师可能会执行一些常规任务:
* **提供**:提供数据平台技术存储数据
* **过程**:创建数据处理管道,在不同的数据存储之间移动数据
* **安全**:确保数据安全,防止未经授权的访问和网络攻击
* **监控**:设置主动和被动监控和警报,以确保解决方案满足所需的性能、可用性和成本限制
* **灾难恢复**:确保在发生灾难时能够恢复数据
在本指南中,我们将重点介绍资源调配和处理,因为其他任务超出了我们项目的范围。让我们开始吧。
# 创建资源组
在 Azure 中,每个资源都属于且仅属于一个资源组。资源组是资源的逻辑分组,以简化管理、访问、成本等。我们的资源组将保存所有我们提供的组件。
[](https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-portal#what-is-a-resource-group) [## 管理资源组- Azure 门户- Azure 资源管理器
### 了解如何通过 Azure 资源管理器使用 Azure 门户来管理您的 Azure 资源组。对于管理 Azure…
docs.microsoft.com](https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-portal#what-is-a-resource-group)
登录 [Azure 门户](https://portal.azure.com/)。在左上角选择 **+创建资源**,搜索**资源组**,在新*刀片上,*点击**创建**开始创建过程。在**Create a resource group**blade 上,选择您将用于这个项目的订阅,为您的资源组键入一个名称,并从列表中选择一个适当的区域。
> 刀片指的是 Azure 门户中的窗格。

Azure 门户:搜索资源或服务(图片由作者提供)

Azure 门户:创建资源组(图片由作者提供)
您可以自由选择资源的名称;但是,遵循命名约定是一个好习惯。
[](https://docs.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/naming-and-tagging) [## 推荐的命名和标记约定—云采用框架
### 组织您的云资产,以支持运营管理和会计要求。定义良好的命名和…
docs.microsoft.com](https://docs.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/naming-and-tagging)
# 创建 Azure 密钥库
Azure Key Vault 是一款安全存储和访问机密的工具。秘密是您想要严格控制访问的任何东西,比如 API 密钥、密码、访问令牌或证书。
搜索 **Key vault** 与我们对资源组所做的类似(步骤 1-3 ),并填写所示的设置,将其余部分保留为默认设置,请注意,我们的资源组可在下拉列表中选择。

Azure 门户:创建 Azure 密钥库(图片由作者提供)
# 创建 Azure 数据工厂
在 Azure 门户搜索**数据工厂**,填写如图所示的设置;将其余部分保留为默认值。

Azure 门户:创建数据工厂实例(图片由作者提供)
# 调配 Azure 数据湖存储
在 Azure 门户中搜索**存储账号**,填写如图所示的设置;将其余部分保留为默认值。这里需要注意的重要一点是 *Azure Data Lake Storage Gen2* 提供的分层名称空间,它构建在低成本的 Azure blob 存储之上。分层命名空间将对象组织到目录的层次结构中,以增强性能、管理和安全性。
[](https://docs.microsoft.com/en-us/azure/storage/blobs/data-lake-storage-introduction) [## Azure 数据湖存储第二代简介
### Azure Data Lake Storage Gen2 是一组专用于大数据分析的功能,构建于 Azure Blob 存储之上…
docs.microsoft.com](https://docs.microsoft.com/en-us/azure/storage/blobs/data-lake-storage-introduction) 
Azure 门户:提供 Azure 数据湖存储 Gen2(图片由作者提供)
选择工具栏上的**通知**图标,查看创建进度。部署后,您会收到一个弹出通知。使用它转到新创建的资源。在**概述**页面,找到**容器**选项;我们将使用它来制作一个容器,作为存储下载文件的仓库。按照所示步骤创建容器 CSV*-数据存储*。点击打开新容器,选择 **+添加目录,**创建新目录,命名为*covid 19-data;这个*文件夹将保存我们的文件。

在 Azure 数据湖存储 Gen2 中创建一个容器(图片由作者提供)
# 创建 Azure Databricks 工作区
在左上角,选择 **+创建资源**。选择**Analytics>Azure data bricks**开始创建过程,如图所示填写设置。

Azure 门户:创建一个 Azure Databricks 工作区(图片由作者提供)
# 在 Azure Synapse Analytics 中创建数据仓库
在左上角,选择 **+创建资源**。选择**数据库> Azure Synapse Analytics(以前的 SQL DW)** 开始创建过程,填写如图所示的设置。我们已经在 Azure Synapse Analytics 中成功创建了一个数据仓库。

Azure 门户:创建 Azure Synapse 分析数据仓库(图片由作者提供)
> ***一台服务器,多个数据库***
>
> 当我们创建第一个 Azure SQL 数据库时,我们也创建了一个 Azure SQL(逻辑)服务器。可以把服务器想象成我们数据库的管理容器。我们可以通过服务器控制登录、防火墙规则和安全策略。我们还可以在服务器中的每个数据库上覆盖这些策略。目前,我们只需要一个数据库。
部署完成后,转到资源,为我们的新数据库打开**概述**页面。浏览概览页面上的数据库详细信息;我们对**服务器名**和**连接字符串**特别感兴趣。我们稍后将需要这些来连接到我们的数据库。

Azure Synapse 分析:概述(图片由作者提供)
# 设置 Microsoft Power BI
Microsoft Power BI 存在于 Azure 产品之外,有三种不同的定价风格——桌面版、专业版和高级版。桌面版对个人用户是免费的,非常适合我们的锻炼。从 Microsoft store 下载并安装 Power BI Desktop。
[](https://www.microsoft.com/en-us/download/details.aspx?id=58494) [## 超级商务智能桌面
### Microsoft Power BI Desktop 专为分析师打造。它结合了最先进的互动可视化,与…
www.microsoft.com](https://www.microsoft.com/en-us/download/details.aspx?id=58494)
伙计们,就这样吧。喝杯咖啡,我们将在后续的系列文章中继续讨论各个组件的详细处理步骤。
# 结论
我们看了新时代的 ETL 过程和数据工程师必须执行的任务。我们提出并讨论了一个数据工程项目,并设置了 Microsoft Azure 组件来构建我们的项目。
# 后续步骤
跟随我们的后续文章,与我们一起构建您的项目。我们将详细讨论和解释所有组件的处理过程。
* 使用 Azure 数据工厂摄取文件
[](https://medium.com/@dhyanintech/using-azure-data-factory-to-incrementally-copy-files-based-on-url-pattern-over-http-569476b625fc) [## 使用 Azure Data Factory 基于 HTTP 上的 URL 模式增量复制文件
### 一个创新的 Azure 数据工厂管道,通过 HTTP 从第三方网站增量复制多个文件…
medium.com](https://medium.com/@dhyanintech/using-azure-data-factory-to-incrementally-copy-files-based-on-url-pattern-over-http-569476b625fc)
* 在 Azure 数据块中清理和转换 CSV 文件
[](https://medium.com/@dhyanintech/cleansing-and-transforming-schema-drifted-csv-files-into-relational-data-in-azure-databricks-519e82ea84ff) [## 在 Azure Databricks 中将模式漂移的 CSV 文件清理并转换为关系数据
### 使用 PySpark 处理模式漂移文件并将其加载到 Azure Databricks 中的 Azure Synapse Analytics 数据仓库
medium.com](https://medium.com/@dhyanintech/cleansing-and-transforming-schema-drifted-csv-files-into-relational-data-in-azure-databricks-519e82ea84ff)
* 使用 PolyBase 在 Azure Synapse Analytics 中加载数据
[](https://dhyanintech.medium.com/loading-csv-data-into-azure-synapse-analytics-by-using-polybase-5ae942ce3059) [## 使用 PolyBase 将 CSV 数据加载到 Azure Synapse Analytics
### 使用 PolyBase 将 CSV 数据从 ADLS Gen2 导入 Azure Synapse Analytics 的分步指南
dhyanintech.medium.com](https://dhyanintech.medium.com/loading-csv-data-into-azure-synapse-analytics-by-using-polybase-5ae942ce3059)
* 用 Power BI 建模和呈现数据—无限期推迟
## 喜欢这个帖子?与 Dhyan 联系
让我们做朋友吧!你可以在 [LinkedIn](https://www.linkedin.com/in/dhyans/) 上找到我或者在 [Medium](https://dhyanintech.medium.com/membership) 上**加入**我。
# RShiny 演示——您的下一个基于代码的仪表板解决方案?
> 原文:<https://towardsdatascience.com/a-demonstration-of-rshiny-your-next-code-based-dashboard-solution-3e964d66c86c?source=collection_archive---------40----------------------->
## 建立一个个人支出仪表板应用程序来检查我的财务状况
市场上最好的两个 dashboarding 工具,Tableau 和 Power BI,使用起来完全是一种享受(好吧,也许不是 Power BI……)。然而,在可行的情况下,我总是倾向于使用 r,而不是使用他们争论数据的产品(Prep 和 PowerQuery)。
r 更快,有非常优雅的语法(如果你对 Tidyverse 感兴趣的话),可重复(因为它是代码),并且对它可以完成的各种数据争论任务(包括数据检索)几乎没有限制。
但是 R 也提供了各种各样的表示/报告选项。r 可以通过编程*构建 pdf 报告、PowerPoints、Word 文档和网页,所有这些都以图表和表格为特色,这些图表和表格利用了一些最新的 web 可视化库(也可以设置为在预定的基础上自动通过电子邮件发送这些输出)。*
*这篇文章的主要焦点是 R 的交互式仪表板/应用程序解决方案,通常被称为“闪亮”。*
*在许多情况下,*定制的*仪表盘/应用程序(并不闪亮)使用 JavaScript、React 和 D3(我当然不是专业的定制应用程序开发专家),然而,存在许多 R 包作为这些技术的“包装器”,使得从 R 代码生成相同类型的专业输出成为可能。*
*当然,与这些语言的本地编码者可能产生的东西相比,可能会有一些限制;但是对于一个 R 程序员来说,能够*进入下一步*并产生一个工作原型(最终可能完全足够)而不是引入一个新专业人员,是相当有价值的。*
*鉴于目前 R 在一大堆本科科学课程中的受欢迎程度,预计未来几年将会有越来越多崭露头角的 R 开发人员涌入。因此,为了展示 R 在这方面的能力,我制作了一个个人财务应用程序(显示的值是半虚拟的旧交易数据)。*
**
*初始输入和交易检查页面*
**
*主费用汇总页面*
**
*累计费用和收入预测页*
*如果你想看视频,这里有一个可能比你希望的更详细的演示(但它有一个额外的目的,所以请继续阅读,在最后找出它是什么)。*
*对于那些经过一些整洁的小技巧的人来说,这里是带有代码的 GitHub repo。是的,有 2000 多行(我喜欢危险的生活)。*
*[](https://github.com/Tadge-Analytics/Personal-expense-shiny-dashboard) [## 数据分析/个人支出闪亮仪表板
### 此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/Tadge-Analytics/Personal-expense-shiny-dashboard)
仅仅因为 R 是开源的,并不意味着这些仪表板项目一定会比使用流行的付费工具便宜。虽然您可能会节省最初的订购费用,但大多数人会意识到,一个专有的拖放式工具能够让您在更少的计费时间内启动并运行。使用一个也可能使过程更容易转移,因为 Tableau 和 Power BI 开发人员比闪亮的开发人员多得多。
然而,当使用代码时,在**再现性**方面有相当大的优势。例如,如果为多个客户端创建同一个仪表板;有了 R,每当需要更新时,不再需要完全独立的仪表板构建工作和对每个文件的单独编辑。使用(正确的)代码,您只需更改相关的函数(或特定的参数)就可以实现更改。
但是,当然,通过代码获得*美学*可能会很麻烦(对于最初的尝试来说**也是如此**)。默认情况下,许多软件包都产生了不错的设计,并且您可以完全控制几乎所有的元素(但这就是问题所在——选项太多了。有时,仅仅通过拖动或简单地从一个漂亮的用户调色板中“挑选”你想要的颜色来调整图表的大小要容易得多。*
*对于我的应用程序来说,数据争论非常复杂。虽然这个*可以*作为一个单独的数据预处理过程来完成,但是争论层和表示层之间的迭代和*交织*本质意味着将它们放在同一个软件中是理想的。最终结果更加无缝(这也是我想象中的最终用户真正使用产品的唯一方式)。*
*该应用包括 Tableau / Power BI 用户熟悉的许多功能:*
* *“点击”过滤器(点击一个图表以过滤另一个图表)*
* *点击高亮显示(基本相同,通常在一个图表中,尽管看到虚线下面的灰色条)*
* *单击参数更新(出现并被更改的虚线)*
* *工具提示(虽然我没有费心整理这些,因为它只是一个 MVP)*
**
*还有一些*流行的付费工具*的功能是闪亮仪表盘中不存在的(据我所知)。例如,将图例浮动在任何位置,并且在工具提示图表中有“*”。**
* *通过表示层将“客户端”CSV 直接上传到流程中*
* *将有争议的 CSV 摘要下载到 Excel 文件中(包含多个工作表和格式化表格)。这样做是为了让用户可以选择在最熟悉的环境中对他们的交易进行手动分类。*
* *利用与 Googlesheets 的连接来存储汇总数据(作为使用 Excel 文件的替代方案),并利用检索和“写回”功能,只需点击一个按钮。这使得用户不必在保存和上传多个 Excel 文件之间进行迭代(它还允许跟踪更改——这非常简洁)。*
*我闪亮的仪表板能够做的关键事情(在*付费工具中不可能做到的)是*:*
*这款应用的主要特点是它可以帮助对银行交易进行分类。本质上,随着用户收集更多的关键字,所需的工作(正确识别新交易)大大减少。*
*第二页是洞察力开始的地方。特别是,主要功能是支出率图表。对我来说,关键的一点是,这让我可以看到我的总体“消耗率”和按特定类别细分的支出率。尤其是我在外出就餐、公共交通和日常不可避免的开支上花了多少钱。*
*第三页是由用户说明引导的关于费用的推断。在这里,您可以看到每个类别的贡献。*
**
*通过 Excel 电子表格(或 Googlesheet),可以:*
* *加入尚未发生的预期事件*
* *修改那些已经发生的(通过指定正在进行的费率/时间表,规定它们不会再次发生)。*
* *限制用于每日消费率计算的历史数据的范围(例如,仅使用我外出就餐的最近 20 笔交易来预测未来,或仅使用自[某个日期]以来的交易)。*
**
# *最终注释*
*这个项目是一个经典的案例,一些*看起来很简单的东西*被发现实际上非常复杂。即使作为一个爱好项目和(广告)博客帖子的组合,它也占用了相当多的额外时间。最后,它被证明是一个无论是用 Tableau 还是 Power BI 都无法真正完成的项目(至少没有那样的凝聚力),所以我想这并不是真正最公平的比较。*
*对于像这样的应用程序的安全(启用身份验证)、基于网络的交付系统, [Shinyapps.io](https://www.shinyapps.io/) 提供了这项服务,但也有许多自托管选项可用。然而,因为我预计大多数个人和企业都非常不愿意将他们的私人交易数据上传到第三方(即使这是一个相当改进的、安全的在线版本的应用程序)——这就是为什么我一直将该文件作为可以在个人电脑上本地使用的东西。*
*此外,我已经决定让这个项目开源。希望它的某些部分可能对 R 社区有所帮助。项目本身也可以从他们的推荐/建议中受益,所以请随意使用 Youtube 视频和脚本来检测可能的改进。如果你愿意合作,请随时给我发电子邮件。*
**原载于 2020 年 1 月 21 日 https://tadge-analytics.com.au*[](https://tadge-analytics.com.au/personal-finances-dashboard/)**。***
# 迁移学习的一个糟糕例子:VGG 预训练模型在 Keras 中的应用
> 原文:<https://towardsdatascience.com/a-demonstration-of-transfer-learning-of-vgg-convolutional-neural-network-pre-trained-model-with-c9f5b8b1ab0a?source=collection_archive---------8----------------------->
## 使用特征提取过程对 Mnist 数字数据进行分类的迁移学习演示

[T. Q.](https://unsplash.com/@tq_photos?utm_source=medium&utm_medium=referral) 在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄的照片
迁移学习是机器学习中最先进的技术之一,已广泛应用于图像分类。在这篇文章中,我将讨论迁移学习,VGG 模型和特征提取。在最后一部分,我将展示一个有趣的迁移学习的例子,其中迁移学习技术在对 **MNist 数字数据集**进行分类时表现出乎意料地差。
V VGG 小组参加了一年一度的计算机视觉竞赛——ImageNet 大规模视觉识别挑战赛( [ILSVRC](http://www.image-net.org/challenges/LSVRC/) ),并提交了著名的 VGG 模型,用于参加对象定位(检测来自 200 个类别的图像中的对象)和图像分类任务(1000 个类别的分类)的竞赛。ImageNet 数据集是比赛中使用的主要计算机视觉基准数据集,包括属于 1000 个类别的超过 1400 万张图像。VGG 模型以 92.7%的前 5 名测试准确率超越了其他模型,并在 2014 年 ILSVRC 竞赛中获得了第一名和第二名。
**VGG 建筑**
VGG 有两种不同的架构:VGG-16 包含 16 层,VGG-19 包含 19 层。在本文中,我们将重点关注 VGG-16,它主要包含三个不同的部分:卷积、池和全连接层——它从两个卷积层开始,然后是池,然后是两个卷积,然后是池,再重复三个卷积,然后是池,最后是三个全连接层。下图显示了 VGG-16 模型的架构。VGG 模型最有趣的部分是模型权重可用于不同的平台(如 Keras ),并可用于进一步的分析——开发模型和应用程序。将模型的权重用于进一步任务的想法引发了迁移学习的想法。

VGG-16 建筑
我们可以运行以下三行代码,用 python 绘制 VGG-16 模型架构:
from keras.applications.vgg16 import VGG16
from keras.utils import plot_model
model = VGG16()
plot_model(model)
**迁移学习**
我们知道,随着神经网络架构的增加/深化,训练时间呈指数增长。一般来说,用大规模数据集训练一个 3-5 层的神经网络可能需要几个小时/几天。因此,由于模型架构中完全连接的图层/节点的深度和数量,在大规模数据集上从头开始部署 VGG 是一项令人厌倦且计算量巨大的任务。另一个挑战是从零开始构建 VGG 需要相当大的内存空间和带宽,因为 ImageNet 训练的 VGG-16 砝码的大小为 *528* MB。然而,我们可以执行**转移学习,即**,利用权重等知识以及之前训练过的(例如预训练的 VGG)模型的特征,来解决类似的问题,而不是从零开始构建 VGG。例如,如果我们想开发一个二进制图像分类器,那么我们可以使用一个预先训练的模型,它是在像 VGG 这样的大型基准图像数据集上训练的。因此,迁移学习是一种机器学习方法,其中为一项任务开发的模型被重新用作第二项任务的模型的起点。迁移学习通常用于加快训练时间,最终提高模型的性能。在利用迁移学习的同时,我们必须考虑到使用迁移学习的好处并不明显。
**什么时候使用迁移学习?**
可以阅读深度学习的世界 *中的文章 [*迁移学习的意义,解释什么时候使用迁移学习。*](https://analyticsindiamag.com/transfer-learning-deep-learning-significance/)*
当训练数据不足时,机器学习算法尤其是深度神经网络可能无法正确学习。迁移学习可以在解决这一问题和调整模式以适应新任务方面发挥重要作用。在应用迁移学习时,我们可以寻找一些因素[1]:
1. **更高的起点:**有迁移学习的模型初始阶段的表现应该会优于没有迁移学习的模型。
2. **更高的斜率:**在源模型的训练阶段,性能斜率或改进率比其他情况下更陡。
3. **更高的渐近线:**预训练的应该更平滑地收敛。
**为什么要用 VGG 模式进行迁移学习?**
假设给定数量的训练样本(图像)不足以构建分类器,在这种情况下,VGG 可以很容易地用于特征提取,因为它是在数百万个图像上训练的。VGG 是在 2014 年推出的,尽管如此,通过 2014 年之后出现的许多最先进的图像分类器,它在一些特定任务上比其他分类器具有更好的准确性。
在这篇文章中,我们将用 VGG 模型展示迁移学习的一个例子,它表明迁移学习方法没有达到标准。在以后的文章中,我们将展示另一个例子,在这个例子中,利用迁移学习方法,模型的性能得到了预期的提高。
在这次演示中,我们使用著名的 MNIST 数字数据集。我们使用仅包含数字 8 和 6 的 MNIST 数据集的一部分。总共有 8200 个样本,每个样本有 784 个特征。我们使用 VGG 预训练的权重为 MNIST 数据集提取特征。
**步骤 1 —数据准备**
我们将数据集从本地硬盘上传到 Google Colab,并将标签从 8 和 6 转换为 1 和 0。
from google.colab import files
uploaded = files.upload()

从本地驱动器上传数据到 Colab
现在,我们读取数据集。下图显示标签为 8 & 6。在后面的部分中,我们将应用逻辑回归,我们将标签转换为 1 和 0。

数据片段
运行这一行代码将转换标签:
data['label'] = np.where(data['label'] == 8, 1, 0)

转换数据集的标签
**步骤 2——从 VGG-16 模型中提取特征**
在提取特征之前,只需观察 VGG-16 模型的总结:

VGG-16 模型综述
总之,VGG-16 包含 16 层,其中在展平最后一个卷积层(第一个突出显示)之后,特征的数量是 25,088,并且在最后一层(预测或最终密集层)中,节点的数量是 1000,因为 VGG-16 主要针对 1000 类分类问题进行训练(第二个突出显示)。
出于迁移学习的目的,我们可以使用 VGG 模型从 MNIST 数据集中提取 25088 个特征。红色垂直线显示特征提取的切割。

VGG-16 的特征提取
下面的代码部分将在最后的卷积层之后剪切 VGG 模型:
from keras import models
base_model = VGG16(weights='imagenet')
model_VGG16 = models.Model(inputs=base_model.input, outputs=base_model.get_layer('flatten').output)
输出:

VGG 模型在去掉最后三层后的总结

利用 VGG-16 模型的特征提取
在使用 VGG 模型从数字数据中提取特征之后,我们用这些特征训练了逻辑回归二元分类器,并执行 10 重交叉验证。同时,我们还对原始的 mnist 数字数据进行了逻辑回归,并进行 10 重交叉验证,以将结果与迁移学习的性能进行比较。
以下两个表显示了对原始数据和从原始数据中提取的特征应用逻辑回归的结果。在没有迁移学习的情况下,即将 LR 应用于原始数字数据实现了大约 98%的准确度,而利用迁移学习特征的模型仅实现了 50%的准确度,这类似于二进制分类问题的随机猜测。总的来说,我们期望随着迁移学习的进行,模型的性能会提高。然而,在这个演示中,我们发现随着迁移学习,模型性能急剧下降。

逻辑回归应用于 Mnist 数字数据的结果

VGG16 性能不佳的可能原因:
1. VGG-16 是为 3 通道 RGB 图像训练的,而 Mnist 数字数据是 1 通道灰度
2.通过 VGG-16 高级代表性特征学习的 ImageNet 数据中的背景噪声
3.VGG-16 训练用于 1000 级分类,而对于这个任务,我们使用它进行二进制分类
虽然具有迁移学习的模型在该实验中没有提供有益的结果,但是利用 VGG 的其他层进行特征提取过程或者微调参数可以产生更好的准确性。总之,迁移学习是一种最先进的机器学习技术,可以提高模型的性能。然而,灵活运用迁移学习技术是获得适当优势的必要条件。
# 阅读默罕默德·马苏姆博士(以及媒体上成千上万的其他作家)的每一个故事。
你的会员费将直接支持和激励穆罕默德·马苏姆和你所阅读的成千上万的其他作家。你还可以在媒体上看到所有的故事—[](https://masum-math8065.medium.com/membership)
****阅读愉快!****
**参考:**
**[1][https://analyticsindiamag . com/transfer-learning-deep-learning-significance/](https://analyticsindiamag.com/transfer-learning-deep-learning-significance/)**
**[https://keras.io/guides/transfer_learning/](https://keras.io/guides/transfer_learning/)**
**[3][https://www . Alibaba cloud . com/blog/part-1-image-class ification-using-features-extracted-by-transfer-learning-in-keras _ 595289](https://www.alibabacloud.com/blog/part-1-image-classification-using-features-extracted-by-transfer-learning-in-keras_595289)**
# PyTorch 中使用视觉转换器的实际演示:MNIST 手写数字识别
> 原文:<https://towardsdatascience.com/a-demonstration-of-using-vision-transformers-in-pytorch-mnist-handwritten-digit-recognition-407eafbc15b0?source=collection_archive---------15----------------------->
在本文中,我将给出一个实际操作的示例(带代码),说明如何使用流行的 PyTorch 框架将视觉转换器应用到实际的计算机视觉任务中,该框架是在论文“ [**中提出的,一幅图像相当于 16x16 个单词:按比例进行图像识别的转换器**](https://openreview.net/pdf?id=YicbFdNTTy) (我在 [**的另一篇文章**](https://medium.com/@stankriventsov/an-image-is-worth-16x16-words-transformers-for-image-recognition-at-scale-brief-review-of-the-8770a636c6a8) 中对此进行了评论)。

视觉转换器的原理图(来自[https://openreview.net/pdf?id=YicbFdNTTy](https://openreview.net/pdf?id=YicbFdNTTy))
为此,我们将使用众所周知的 [**MNIST 数据集**](https://en.wikipedia.org/wiki/MNIST_database) 来研究手写数字识别的问题。

使用 Pyplot 生成的 MNIST 手写数字示例
我想马上提供一个警告,只是为了说明这一点。我选择 MNIST 数据集进行这次演示,因为它足够简单,可以在几分钟内,而不是几小时或几天内,在没有任何专门硬件的情况下,从头开始训练模型并用于预测,因此几乎任何有计算机的人都可以做到这一点,并看看它是如何工作的。我没有尝试过优化模型的超参数,我当然也没有用这种方法达到最先进的精确度(目前这个数据集的精确度约为 99.8%)的目标。
事实上,虽然我将展示视觉转换器可以在 MNIST 上获得令人尊敬的 98%以上的准确性,但可以说它不是这项工作的最佳工具。由于该数据集中的每个图像都很小(只有 28x28 像素),并且由单个对象组成,因此应用全局注意力只能具有有限的效用。稍后我可能会写另一篇文章,研究如何在包含更大图像和更多种类的更大数据集上使用该模型。现在,我只想展示它是如何工作的。
在实现方面,我将依赖来自王飞的 [**这个**](https://github.com/lucidrains/vit-pytorch) 开源库的代码,特别是来自 *vit_pytorch.py* 文件的以下 Vision Transformer (ViT)类:
与任何 PyTorch 神经网络模块类一样,它具有初始化( **__init__** )函数,其中定义了所有可训练参数和层,以及**转发**函数,该函数建立了将这些层组装到整个网络架构中的方式。
为了简洁起见,这里只给出了 ViT 类本身的定义,没有给出依赖类。如果你想在你的电脑上使用这段代码,你需要导入整个[***vit _ py torch . py***](https://github.com/kriventsov/vit-pytorch/blob/main/vit_pytorch/vit_pytorch.py)文件(这个文件出奇的小,只有一百行左右的代码;我在 GitHub 上给出了我自己的分叉版本的链接,以防将来原始文件发生变化),以及最近版本的 [**PyTorch**](https://pypi.org/project/torch/) (我使用的是 1.6.0)和用于张量操作的 [**einops**](https://pypi.org/project/einops/) 库。
要开始使用 MNIST 数据集,我们需要首先加载它,我们可以这样做(从这一点开始,这篇文章中的所有代码都是我的,尽管其中很多都很标准):
上面代码中的 **transform_mnist** 转换用于归一化图像数据,使其均值为零,标准差为 1,这有助于神经网络训练。 **train_loader** 和 **test_loader** 对象包含已经随机分成批次的 MNIST 图像,以便它们可以方便地输入到训练和验证程序中。
数据集中的每个项目都包含一个带有相应地面实况标签的图像。一旦在数据集的训练部分(60,000 个手写数字图像)上进行训练,我们的转换器的目标将是基于图像来预测测试部分(10,000 个图像)中每个样本的正确标签。
我们将使用以下函数为每个时期训练我们的模型:
该函数对 [**data_loader**](https://pytorch.org/docs/stable/data.html#torch.utils.data.DataLoader) 对象中的每个批次进行循环。对于每一批,它计算模型的输出(作为一个 [**log_softmax**](https://pytorch.org/docs/master/nn.functional.html#torch.nn.functional.log_softmax) )和这个输出的 [**负对数似然损失**](https://pytorch.org/docs/stable/generated/torch.nn.NLLLoss.html#torch.nn.NLLLoss) ,然后通过 **loss.backward()** 计算这个损失关于每个可训练模型参数的梯度,并通过 **optimizer.step()更新参数。**每第 100 批,它提供一份关于训练进度的打印更新,并将当前损失值附加到 **loss_history** 列表中。
在每个时期的训练之后,我们将能够使用以下函数来查看我们的当前模型在测试集上的表现:
虽然这类似于上面的训练程序,但现在我们不计算任何梯度,而是将模型的输出与地面实况标签进行比较,以计算准确性并更新损失历史。
一旦定义了所有的函数,就该初始化我们的模型并运行训练了。我们将使用以下代码:
在这里,我们用 7x7 的面片大小(对于 28x28 的图像,这意味着 4 x 4 =每个图像 16 个面片)、10 个可能的目标类别(0 到 9)和 1 个颜色通道(因为图像是灰度)来定义我们的视觉转换器模型。
在网络参数方面,我们使用 64 个单元的嵌入维数,6 个变换器块的深度,8 个变换器头,以及输出 MLP 头的隐藏层中的 128 个单元。对于优化器,我们将使用学习率为 0.003 的 Adam(如论文中所示)。我们将对我们的模型进行 25 个时期的训练,并观察结果。
使用上面的超参数值没有特别的理由。我只是选了一些看起来合理的东西。当然有可能优化这些将导致更高的精度和/或更快的收敛。
一旦代码运行了 25 个时期(在一个普通的免费 [**谷歌实验室**](https://colab.research.google.com/) 笔记本电脑上,配有一个特斯拉 T4 GPU),它会产生以下输出:

嗯,98.36%的准确率还不算太差。这比人们期望从全连接网络中得到的要好得多(我在那里得到了大约 97.8-97.9%,没有任何技巧),所以注意力层肯定有好处。当然,正如我上面提到的,视觉转换器并不特别适合这项任务,即使是几层的简单卷积网络也可以达到 99%或以上的精度。在优化了超参数之后,这个变压器模型可能会做得更好。
但关键是,它是可行的,而且,正如 [**论文**](https://openreview.net/pdf?id=YicbFdNTTy) 中所描述的,当应用于更大、更复杂的问题时,它可以与最好的卷积模型相媲美。希望这篇简短的教程向读者展示了如何在自己的工作中使用它。
# 揭开形式概念分析(FCA)的神秘面纱
> 原文:<https://towardsdatascience.com/a-demystifying-introduction-to-formal-context-analysis-fca-ab8ce029782e?source=collection_archive---------26----------------------->
## 在复杂数据中寻找结构和规则。

结构(图片作者提供)。
这种情况多久发生一次?一个新的数据仓库出现了,或者有人给你指出一个不错的新数据集,从中你可以看到可能有一些有趣的事情要做。然后你看着它,嗯…它是一串数字。你可以运行一些统计数据,并四处打探,但这到底意味着什么呢?
也许[形式概念分析](https://en.wikipedia.org/wiki/Formal_concept_analysis) (FCA)能有所帮助。这看起来可能很复杂,但它基于一个相当简单的想法:T2 概念 T3。概念(有点像面向对象编程中的类)表示共享一组属性的一组对象。通常,在 FCA 中,这些属性是二进制的。
例如,假设我们正在查看关于四个国家的数据,这四个国家可大可小,人们可能会在左侧或右侧驾驶。我们可以用下面的二进制矩阵来表示每个国家的属性。

一个非常简单的数据集的形式上下文。
这个矩阵就是所谓的*形式背景*,我们可以看到这里有意义的概念包括大国的概念,或者说大国在右侧行驶的概念。包含在第一个对象(称为概念的*范围*中的对象(国家)集合是国家 1、国家 2 和国家 3 **、**,第二个对象仅包含国家 1 和国家 3。每个概念的*意图*,即共享的属性集合,对于前者为*【size:big】*,对于后者为*【size:big,driving:right】*。
有一件事我们需要添加到概念的定义中,这是 FCA 的核心:概念必须是封闭的。这意味着范围中的对象集应该正好是共享意图属性的对象集,*和*意图中的属性集应该正好是范围中的对象共享的属性集。
从那个定义来看,*【大小:大】**【大小:大,驾驶:右】* 是封闭的,但是*【大小:小】*这个概念不是。的确,只有 country4 有这个属性,但它也有*【驾驶:右】*。因此,要使其封闭,必须通过范围元素共享的两个属性来定义概念:*【size:small,driving:right】*。同样适用于*【驾驶:左】*。这种情况下的封闭概念是*【大小:大,行驶:左】*。
现在,寻找封闭的概念当然很有趣,但是让整个事情变得真正强大的是这些概念是由*包容*自然组织起来的。直觉上,一个概念包含另一个更一般的概念。更正式的说法是,它的意图(属性)包含在对方概念的意图中,它的范围(对象)包含对方概念的范围。基本上,*【大小:大】*归入*【大小:大,驾驶:左】*。
这种包含关系是一种*偏序*,这意味着一个概念可能包含另一个概念,被另一个概念包含,或者都不包含。因此,给定数据集(形式背景)的所有封闭概念都自然地组织在一个层次结构中(一个*点阵*),从更一般到更具体。

由一个小例子创建的概念格。
当然,对于这样一个小例子,它实际上并没有多大帮助。那么,让我们看看它在一个更重要的例子上做了什么。
# 乡村的例子,但是真实的
为了得到一个更真实的例子,我使用了 [Wikidata](https://www.wikidata.org) 来检索国家列表以及与它们相关的信息(属性)。跳过细节(用于重新创建数据集的所有代码都可以通过 FCA 的基本实现以及在[github.com/mdaquin/fca.js](https://github.com/mdaquin/fca.js)的示例获得),数据集包括来自国家/地区的信息,这些国家/地区具有超过 90%的国家/地区共享的属性值,并且具有数值或少于 5 个唯一分类值。对于这些国家,属性值通过以下方式转换为二进制属性:
* 对于分类属性,为每个可能的值创建一个属性,例如*驾驶侧:左侧*(机器学习从业者称之为 [*一个热编码*](https://en.wikipedia.org/wiki/One-hot) )。
* 对于数字属性,根据 33%和 67%的百分点创建低、中和高值的属性,例如*人口:低*(一种非常基本的[离散化](https://en.wikipedia.org/wiki/Discretization_of_continuous_features)方法)。
结果是 147 个对象(国家)和 33 个二元属性的正式上下文。例如,法国由以下属性表示:
France:[
"area:high",
"population:high",
"mains voltage:medium",
"driving side:right",
"inflation rate:low",
"total fertility rate:low",
"PPP GDP per capita:high",
"life expectancy:high",
"has quality:free country",
"nominal GDP per capita:high",
"nominal GDP:high"
]
看这个正式的上下文感觉有点像看矩阵。一列接一列的 x,感觉有点随机,但也有点不随机:这里面有模式,所以让我们试着找到它们。

正式的上下文看起来都是矩阵。
# 构建概念格
构建概念格是一项复杂的任务,但是为了这个例子的目的,我使用了一个基本的方法。首先,我通过添加每个对象的意图以及与现有概念的意图的任何交集来构建所有相近的概念。然后我迭代概念来建立包含关系。最后,我用它们的范围填充每个概念。这远远不是最有效的算法(参见[这篇文章](http://ceur-ws.org/Vol-42/paper3_kuznetsov.pdf)中更好的算法列表), javascript 也不是最好的语言,但在我的笔记本电脑上,只需要几分钟就可以完成,所以还不算太差。
首先要注意的是,该算法找到了 8,840 个概念。这听起来可能很多,但是这远远没有达到我们用这个数量的属性所能找到的最大概念数量!我想这就是为什么大多数关于 FCA 的教程和例子倾向于只使用非常基本的例子。复杂的不是技术,而是结果。
然而,即使逐个检查所有这些概念是乏味且毫无意义的工作,这里的关键是它们不是作为属性集的列表,而是通过导航结构来探索它们。事实上,从网格的顶部开始(即没有属性作为意图,所有对象作为范围的概念),我们可以将注意力集中在下一个级别,例如低预期寿命的国家(*【预期寿命:低】*),发现有 20 个次级概念,包括人口也低的国家(其中 14 个)。在第三个层次,我们发现只有 5 个可能的其他概念,除了低预期寿命和人口之外,还有:
* 低名义 GDP,
* 高总和生育率,
* 中等电源电压,
* 低购买力平价人均国内生产总值,或
* 高通货膨胀率
可能有许多其他概念,但只有这五个,而且 FCA 基于封闭的属性集,这意味着这些其他概念根本不存在于数据中。在我们列出的国家中,你不可能预期寿命和人口都很低,也不可能不属于那 5 个类别之一。网格更深入地细分了这组国家,并提供了一种便捷的方式来探索数据集。但是它能做得更多吗?
# 提取关联规则
除了提供一个(相当庞大的)导航结构之外,一旦构建好,网格还可以用来识别数据中应用的规则。这里简单的直觉是,如果概念 C 的意图包括不在其任何父概念的意图中的属性(即包含概念),那么这些属性暗示了父概念的属性。这也是因为概念是封闭的:如果 C 自己的属性(其正确的意图)可以在没有父属性的情况下出现,那么它们就已经出现在更高的层次上了。
不幸的是,这种情况在我们国家的数据集中没有出现。然而,我们可以看到这种情况何时会发生。一个概念的支撑是其范围内的对象(国家)的数量。比如*【预期寿命:低,人口:低】*的支持度是 14,如上图。如果一个概念 C 的支持度几乎与它的一个父概念 D 的支持度相同,那一定意味着 D 的意图的属性几乎隐含了 C 的意图的属性。换句话说,如果 C 具有意图*【a,b,C】*的支持度为 9,并且包含概念 S 具有意图*【a,b】*,的支持度为 10,我们可以说,任何具有属性 a 和 b 的对象在 90%的情况下也具有 C。我们有一个*关联规则*说明 a 和 b 隐含 c,置信度 90%(支持度 9)。
那个,我们国家数据集有很多。仅关注置信度高于 95%且支持度至少为 25 的规则,我们可以发现例如以下规则:
inflation rate:high,total fertility rate:high -> life expectancy:low s:25 c:0.9615384615384616
其中指出,在 96.1%的置信度下,高通胀率和高生育率的国家预期寿命也低,这适用于我们数据集中的 25 个国家。
# 结论
FCA 和关联规则提取的应用还有很多,但对我来说,数据集探索和理解是最重要的应用之一。上面的规则和网格的结构可能反映了世界的某种现实,或者可能是数据集构建方式的人工产物。它可能会说明一些国家的情况,或者在数据中显示出一些偏差。无论是哪种情况,在数据过程的可解释性变得越来越重要的时候,一个可以告诉我“这是你的数据所说的东西”或“这是我在你的数据集的一个角落里发现的一个重要模式”的过程,对于理解数据和我们对数据所做的任何事情的结果都是无价的。
# 注意 U-Net 的详细说明
> 原文:<https://towardsdatascience.com/a-detailed-explanation-of-the-attention-u-net-b371a5590831?source=collection_archive---------7----------------------->
## U-网中的注意门
## 了解新颖的注意力门,它可以自动聚焦于图像中的目标结构
在这个故事中,我解释了 Oktay 等人写的 [Attention U-Net:学习在哪里寻找胰腺](https://arxiv.org/abs/1804.03999)中的 Attention U-Net。艾尔。该论文写于 2018 年,提出了一种新颖的注意力门(AG)机制,允许 U-Net 专注于不同大小和形状的目标结构。
# 概述
1. 什么是注意力?
2. 为什么 U-Net 需要关注
3. 注意力是如何实现的?
4. 分析
# 1.什么是注意力?
在图像分割的背景下,注意力是一种在训练期间仅突出相关激活的方式。这减少了浪费在无关激活上的计算资源,为网络提供了更好的泛化能力。本质上,网络可以“关注”图像的某些部分。
**答:努力关注**
注意力有两种形式,**硬**和**软**。硬注意的工作原理是通过裁剪图像或迭代区域提议来突出相关区域。由于硬注意一次只能选择一个图像的一个区域,所以它有两层含义,它是不可微的,需要强化学习来训练。
由于它是不可微的,这意味着对于图像中的给定区域,网络可以“关注”或不关注,没有中间状态。因此,无法进行标准的反向传播,需要蒙特卡罗采样来计算反向传播各个阶段的精度。考虑到准确性取决于采样的好坏,因此需要其他技术(如强化学习)来使模型有效。
**b .软注意**
软注意通过对图像的不同部分进行加权来工作。高相关性区域乘以较大的权重,低相关性区域用较小的权重标记。随着模型被训练,更多的焦点被给予具有较高权重的区域。与硬注意不同,这些权重可以应用于图像中的许多小块。

当处理句子中的不同单词时,图像上的软注意力权重的可视化。较亮的区域具有较高的权重。[(徐等,2015)](http://proceedings.mlr.press/v37/xuc15.pdf)
由于软注意的确定性,它仍然是可区分的,可以用标准的反向传播来训练。随着模型被训练,权重也被训练,使得模型在决定关注哪些部分方面变得更好。
强烈关注:
1. 一次只挑补丁注意
2. 不可微,需要强化学习
软性关注:
1. 对图像的不同块进行加权以确定相关性
2. 可微分的,可以用反向传播来训练
# 2.为什么在 U-Net 中需要注意力?
为了理解为什么注意力在 U-Net 中是有益的,我们需要看看所使用的跳跃连接。

灰色箭头表示 U 形网络中使用的长跳线连接。 [(Ronneberger 等人,2015)](https://arxiv.org/abs/1505.04597)
在扩展路径中的上采样期间,重新创建的空间信息是不精确的。为了解决这个问题,U-Net 使用跳过连接,将来自下采样路径的空间信息与上采样路径相结合。然而,这带来了许多冗余的低级特征提取,因为初始层中的特征表示很差。
**在跳过连接处实施的软**注意将主动抑制不相关区域中的激活,减少带来的冗余特征的数量。
# 3.注意力是如何实现的?
Oktay 等人推出的注意门使用的是**加性软**注意。
**a .注意门的故障**

**顶部**:注意门(AG)示意图。**底部**:AGs 是如何在每个 skip 连接上实现的。
1. 注意力门接受两个输入,向量 ***x*** 和 ***g*** 。
2. 向量 ***g*** 取自网络的下一个最低层。该矢量具有更小的维度和更好的特征表示,因为它来自网络的更深处。
3. 在上面的示例图中,矢量***×矢量*×矢量**的尺寸为 64×64×64(滤镜×高度×宽度),矢量**×g×的尺寸为 32×32×32。**
4. 向量 ***x*** 经过步长卷积,其尺寸变为 64×32×32,向量 ***g*** 经过 1×1 卷积,其尺寸变为 64×32×32。
5. 这两个向量按元素求和。该过程导致**对齐的权重变大**,而非对齐的权重变得相对较小。
6. 合成向量经过 ReLU 激活层和 1x1 卷积,将维度折叠为 1x32x32。
7. 这个向量经过一个 sigmoid 层,该层在范围[0,1]之间缩放向量,产生注意系数(权重),其中系数越接近 1 表示越相关的特征。
8. 使用三线性插值将关注系数上采样到矢量***×矢量*** 的原始尺寸(64×64)。关注系数被逐元素地乘以**原始** ***x*** 向量,根据相关性缩放该向量。然后像往常一样在 skip 连接中传递。
Oktay 等人还提出了一种基于网格的门控机制,该机制从上采样路径而不是下采样路径(除了最低层)获取 ***g*** 向量,因为该向量已经通过先前的注意门被调节到来自多个尺度的空间信息。

注意系数在 3、6、10 和 150 个时期显现,其中红色突出了较高的注意系数。(Oktay et。阿尔,2018)
如上图所示,随着训练的进行,网络学会聚焦于所需的区域。注意门的可微分性质允许它在反向传播期间被训练,这意味着注意系数在突出相关区域方面变得更好。
**b .在 Keras 的实施情况**
# 4.分析

CT-150 数据集上的结果(Oktay 等人,2018 年)
Oktay 等人获得的结果表明,在整体骰子系数得分方面,注意力 U-Net 比普通 U-Net 的表现好得多。虽然注意 U-Net 有更多的参数,但并没有显著增加,推理时间也只是略微延长。
总之,注意门是一种在大量数据集上一致地改进 U-Net 的简单方法,并且在计算成本方面没有显著的开销。
要获得预先实施了注意力、递归和初始层的 U-Net 的完整实施,请检查[https://github.com/robinvvinod/unet/](https://github.com/robinvvinod/unet/)。
# 理解数据库伸缩基础的开发人员指南
> 原文:<https://towardsdatascience.com/a-developers-guide-to-understanding-the-basics-of-database-scaling-37c8fef94c11?source=collection_archive---------42----------------------->
## 如何扩展数据库以承受传入的流量,以及如何降低其潜在性并提高其性能

菲德尔·费尔南多在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片
假设我们有一个服务,用一个数据库服务器处理每月几千个请求,这个服务器处理来自应用服务器的所有读/写请求。
到目前为止,一切都运行良好,但是随着时间的推移,您开始观察到传入流量的峰值,即使尝试了以下方法,您也无法减少**延迟**和**数据库故障**:
* 拥有一个拥有大量内存和高性能闪存的数据库。
* 实现了最佳缓存以减少延迟。
* 对数据库查询进行适当的索引和优化。
因此,现在您需要**解决您的数据库基础设施**,以便它能够承受传入的流量。
让我们看看数据库**分片**和**复制**如何提供一个高度可靠和高性能的数据库系统,能够承受数百万的规模。
# 分身术
数据复制是将相同的数据存储在多个数据库服务器上的过程,可减少延迟、提高读取可伸缩性、简化数据恢复和提高数据可用性。
通常,数据副本存储在单独的硬件组件中,因为如果该硬件崩溃,您不希望副本崩溃。
最常用的复制策略是**单领导者复制。**
## 单头复制
在这种复制中,有一个主节点负责所有写入,并处理所有其他节点上的数据复制。
领导节点通常称为主节点,其他从属节点称为从节点。
读取和写入仅在主服务器上启用,从服务器只能处理读取查询。

*作者图片—* 单头主从复制
现在,要更新从属服务器上的数据,我们可以选择同步复制或 T21 异步复制。这两者各有利弊。
**1。同步复制:**一旦收到确认,它就完成写入并通知客户端。
***同步复制的好处***
* 它通过确保所有节点都拥有更新的数据来提供数据一致性,因为所有从节点都与主节点同步。
* 如果主节点出现故障,任何从节点都可以轻松成为主节点,而不会丢失任何数据。
***同步复制的缺点***
* 有时,当主设备等待来自所有从设备的确认时,系统可能是高度潜伏的。
* 如果任何从属服务器不可用或出现故障,则主服务器会阻止所有写入,直到同步副本再次可用。因此导致较低的可用性。
**2。异步复制:**
这样,即使所有从节点都出现故障,主节点也可以继续进行写入。
***异步复制的好处***
* 它提供了低延迟,因为主设备不等待从设备上的数据更新。
* 更高的可用性,因为即使任何从节点发生故障,也不会影响主节点。
***异步复制的缺点***
* 由于**复制滞后**,可能导致数据不一致。即主设备到从设备的数据复制可能需要很长时间。
因此,如果在主服务器和从服务器上运行相同的查询(并发执行),可能会得到不同的结果。
* 如果异步系统中的主节点发生故障,新指定的主节点可能无法完成前一个主节点的所有写操作。如果先前的主设备重新联机并成为从设备,它将具有冲突的写入。
因此,对数据库的**读取规模**可以通过复制来实现。
但是怎么加一个**写尺度**?答案是**分片**。
# 分片
比方说,你有一个比萨饼,你不能一个人吃整个,所以你把它切成片,然后打电话给你的朋友。
现在,这些朋友中的每一个都将得到一片比萨饼。你所做的是根据每个朋友的份额有效地划分比萨饼,就像我们可以有多个数据库服务器,它们将承担发送到它的请求的负载。

照片由 [mahyar motebassem](https://unsplash.com/@mahyarmotebassem?utm_source=medium&utm_medium=referral) 在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄
因此,从技术上讲,我们将在分片中将完整的数据库负载分配给 N 个数据库服务器。
每个传入请求的子集将由一个单独的服务器提供服务。现在,每个分区都位于完全不同的物理机器上,并受具有相同数据库模式的独立数据库实例的控制。
这被称为**分片**。它也可以称为水平分区,因为分片基本上是跨不同物理机器/节点的水平分区。
**分片提供了更高的可用性,减少了读/写数据库延迟,并且可以高效地处理高数据库负载。**
在为数据库启用分片时,需要考虑多种因素。需要考虑的两个主要问题如下:
## **碎片键:**
我们需要一些标识符来决定一个特定的请求应该从哪个数据库服务器得到服务。也就是说,应该有一个键,我们应该根据这个键来决定一个请求应该放在哪个碎片上。我们称之为**碎片密钥**或**分区密钥**。
一般我们选择表格的任意一列作为 **shard_key** 。
## **哈希函数**:
哈希是使用**数学函数将任意长度的输入转换成固定大小的文本字符串的过程。** 这意味着任何文本无论多长都可以转换成数字和字母的数组。
这个用于生成散列值的数学函数**被称为**散列函数**。**
因此,我们使用散列函数计算 shard_key 的散列值,然后将该散列值映射到 DB 服务器。
在下图中,**散列函数**将 shard_key (row-id)作为输入,并返回一个值,通过这个值我们可以确定它应该进入哪个 shard。

*作者提供的图片-* 带有 4 个碎片集群的数据库碎片
现在, **NoSQL** 像 Mongo DB 这样的数据库为分片提供了一个内置的标准实现。
更多在数据库级别提供分片的数据库是 Cassandra、Hadoop 和 Apache H-Base e.t.c。
而在 MySQL 这样的关系数据库中,没有分片的标准实现。因此,通常的做法是让**应用程序级分片**用于关系数据库。
# 由于分片可能产生的问题
## 1.数据的重新分布:
如果在一个数据库集群中,一个数据库服务器出现故障,或者您正在向集群添加一个新的数据库碎片,那么您可能需要重新分发或重新散列数据。
这种开销直接依赖于我们用来在不同碎片之间分发数据的散列函数。
如果散列函数是一个简单的取模函数,它采用**行 id** 的**取模**和**个碎片**来决定请求应该到达的碎片,那么在这种情况下,它将导致数据的完全重新散列,如下所示:

*作者提供的图片-* **在添加服务器的情况下重新散列数据**
*在上图中,我们可以看到 4 个碎片的数据映射基于 id 模 4(碎片数)*
12%4 ->第 0 分片
29%4 - >第 1 分片
27%4 - >第 3 分片
*对于 5 个分片,数据映射基于 id 模 5(分片数)*
12%5 ->第二碎片
29%5 - >第四碎片
27%5 - >第二碎片
因此,我们在这里观察到,当我们向现有的 **four shard 集群**添加一个 DB shard 时,所有的行都需要重新映射。
这种**重新分配**通常需要系统停机,这对您的系统来说是有风险的。
## 如何避免:
* 为了避免这种情况,我们可以使用一种特殊的散列技术,名为 [***一致散列***](https://en.wikipedia.org/wiki/Consistent_hashing) ,它通常只需要重新映射`k/N`个键,其中`k`是键的数量,`N`是数据库服务器的数量(更具体地说,是服务器的初始和最终数量的最大值)。
## 2.数据非规范化(关系数据库)
对于单个数据库服务器,需要连接的查询可以很容易地完成,但是我们知道在分布式架构中,数据跨越多个区域。因此,驻留在多个区域上的表的连接将需要大量的处理,并且是相当潜在的。
因此,您可能需要进行数据反规范化,以尽可能避免连接。
## 如何避免:
* 你也可以去 NoSQL 数据库的情况下,你想避免这一点。但是在某些情况下,你可能对关系数据库有一个确切的需求。
* **共享连接:** 一般来说,为了避免关系数据库中的连接,我们尝试将同一碎片中的行的 FK 映射放在不同的表中。因此,所有需要连接的行都位于同一个片上。
为了实现这一点,我们选择可以连接的列作为 **shard_key** 。因此,不同表中具有相同的 **shard_key** 列值的行将位于同一个 shard 中。

*作者图片——共享加入*
在上面医院数据库的例子中,我们选择 **patient-id** 作为分片键。
因此,具有相同**患者 id** 的不同表格的所有条目将位于相同的碎片中。
## 3.热点关键问题
对同一分片中的一个或多个特定键的过度访问会导致节点耗尽。
也就是说,大部分请求由一小部分碎片提供服务,而其他碎片在大部分时间保持理想状态。这可能会导致节点故障或过载,从而导致延迟和故障激增。

*作者图片-* **大多数请求由 shard-1** 提供服务
在上图中,我们可以看到大多数请求由 **shard-1** 提供服务,因此负载很重。而**碎片-2** 和**碎片-3** 几乎是理想的。
这可能导致 shard-1 所服务的所有请求的延迟和失败增加。
一个真实的例子是,假设脸书选择**用户名**作为其用户表的**碎片键**。所有访问量最大的个人资料,如克里斯蒂亚诺·罗纳尔多的
**、Lady Gaga 的**和贾斯汀比伯的最终都在同一个碎片中。那么与其他碎片相比,该特定碎片将是请求的热点。
## 如何避免:
* 为了避免这种情况,我们需要选择碎片键和散列函数,使得整个应用程序负载几乎平均分布在所有数据库碎片中。
# 结论
分片是以一种巧妙的方式抵御传入流量的绝佳方式。但是你需要确定什么时候是分片的确切需求,因为你可以看到数据分区和分片会带来很多额外的复杂性。
因此,在决定共享数据库之前,您应该考虑其他选项来提高数据库的性能,比如索引或缓存。
但是如果您仍然决定设计一个分布式数据库系统,那么您还必须考虑其他的权衡。
感谢阅读。编码快乐!
# WiDS 2020 数据马拉松的另一种方法
> 原文:<https://towardsdatascience.com/a-different-approach-to-the-wids-2020-datathon-c1eb07d7f3a4?source=collection_archive---------21----------------------->
## 使用随机森林分类器对 ICU 中的患者进行分类
虽然今年的 [WiDS Datathon](http://dataset) 要求数据科学家预测重症监护室中的患者存活率,但我决定对[数据集](https://www.kaggle.com/c/widsdatathon2020/overview/description)提出一个不同的问题。源于几年前我参加的一个急诊医学课程,我想知道,除了宣布一个病人是否会存活,我们是否可以用存活的概率来相应地对 ICU 中的病人进行分类。
# 设计
问题的第一步是确定分类级别,并确定分配标签的标准。为此,我利用了 [medicinenet](https://www.medicinenet.com/medical_triage_code_tags_and_triage_terminology/views.htm) 上展示的分类层级,并确定了以下模式。

由 Molly Liebeskind 创建的图像
为了确定幸存的机会,我在一个分类模型中预测该类‘幸存’的概率。虽然 Kaggle 竞赛基于 AUC 分数评估模型,但我在这里又一次偏离了,而是选择了针对回忆进行优化。当标记 ICU 中的患者时,我觉得捕捉所有潜在的高风险患者是最重要的,我愿意牺牲一些精确性。也就是说,我确实确保了 AUC 不会随着我的调整而显著下降。一旦我对模型感到满意,我就使用阈值调整来分配分类标签,以确定存活概率与上述模式一致的患者。
# 模型
我的目标是创建一个简单的模型,以便它可以在快节奏的医院环境中有效地部署,我自下而上地设计了这个模型。如下所示,使用数据字典,我根据列所属的类别将较大的数据集分成多个表。

由 Molly Liebeskind 创建的图像
从那里,我评估了存活组和未存活组之间哪些特征有显著差异,以及哪里有机会通过特征工程放大信号。当我从每个类别中选择特征时,我测试了将它们添加到两个不同的模型中,逻辑回归和随机森林,并观察了影响。
有了完整的特性集,我对两个模型都进行了调优。通过五重交叉验证,我认为随机森林优于逻辑回归和我测试的总体变化。最终代码可以在这里找到[。](https://github.com/mollyliebeskind/ICU_Triage_Through_Classification_Modeling)
# 输出
为了证明询问数据的力量,我们可以如何对病人进行分类,而不是预测存活率,我创建了一个简单的 Tableau 仪表板,向医生和医院管理人员显示高风险病人在 ICU 的位置,以便他们可以相应地进行规划和资源配置。下面是该工具的简要演示。
板 1:用于管理人员,显示每个分流组中的患者数量、他们所在的位置以及他们从哪里进入 ICU。board 2:For physicians and filters by department in the ICU,显示该部门中每个风险级别的患者,然后提供每个患者的进一步信息以便快速获取。注意:所有患者 ID 都是我出于演示目的随机生成的,并非来自原始数据集。Molly Liebeskind 设计的仪表盘。
# 持续的挑战
不幸的是,这个模型的最佳特性集包括许多变量,这需要医生和患者的开销。这些特征不仅需要时间、金钱和身体耐力来为每个患者生成,而且输入结果的手动过程会妨碍该工具提供实时益处的能力。由于这只是概念的演示,真正的目标是建立一个模型,在进行医学测试时自动获取数据,并实时协助医生进行分类。
我希望你喜欢 WiDS Datathon 挑战赛的这种不同。请在下面添加任何问题或评论。作为参考,你可以在这里找到[的完整代码](https://github.com/mollyliebeskind/ICU_Triage_Through_Classification_Modeling)。
# 可视化分类结果的不同方式
> 原文:<https://towardsdatascience.com/a-different-way-to-visualize-classification-results-c4d45a0a37bb?source=collection_archive---------25----------------------->
## 用不常见的分类图升级你的机器学习报告。

我喜欢好的数据可视化。早在我攻读粒子物理学博士学位的时候,我就被我的同事们构建的直方图和在一个单独的图中积累的信息量惊呆了。
## **图中的信息**
改进现有的可视化方法或从其他研究领域移植方法确实具有挑战性。你必须考虑你的情节中的维度和增加更多维度的方法。一个很好的例子是从箱线图到紫线图再到群集图的路径。这是一个不断增加维度和信息的过程。
给情节添加信息或维度的可能性几乎是无穷无尽的。可以使用不同的标记形状添加类别,像热图中的颜色图可以作为另一个维度,标记的大小可以提供对进一步参数的洞察。
## 分类器性能图
当谈到机器学习时,有许多方法来绘制分类器的性能。有大量的度量标准来比较不同的评估者,如准确度、精确度、召回率或有用的 MMC。
所有常见的分类指标都是从*真阳性、真阴性*、*假阳性*和*假阴性*事件中计算出来的。最受欢迎的图无疑是 ROC 曲线、PRC、CAP 曲线和混淆矩阵。
我不会深入三条曲线的细节,但是有许多不同的方法来处理混淆矩阵,比如添加热图。

混乱矩阵的 seaborn 热图。
## 分类镶嵌图
在许多情况下,这可能就足够了,并且很容易获得所有相关的信息,但是对于一个多类的问题,要做到这一点会变得更加困难。
在阅读一些文件时,我偶然发现:
> *雅各布·雷梅克斯、彼得·j·罗瑟夫、米娅·休伯特。可视化分类结果。arXiv:2007.14495[统计。ML]*
从那里到
> 很友好,迈克尔。"多向列联表的镶嵌显示."*美国统计协会杂志*,第 89 卷,第 425 号,1994 年,第 190-200 页。JSTOR ,[www.jstor.org/stable/2291215.](http://www.jstor.org/stable/2291215.)2020 年 8 月 13 日访问。
作者建议使用镶嵌图来绘制离散值。我们可以将这种想法转移到机器学习领域,将预测的类别作为离散值。
在多类环境中,这样的图看起来像下面这样:

具有四个类别的分类结果的镶嵌图。
与经典的混淆矩阵相比,它有几个优点。人们可以容易地看到 y 轴上的预测类别和 x 轴上的每个类别的数量比例。与简单的柱状图最大的不同是柱状图的宽度,它给出了阶级不平衡的概念。
你可以在这里找到这样一个带有混淆矩阵的图的代码:
祝您在绘制下一个分类结果时愉快!
# 对决策树的探究
> 原文:<https://towardsdatascience.com/a-dive-into-decision-trees-a128923c9298?source=collection_archive---------3----------------------->

马里乌斯·马萨拉尔在 [Unsplash](https://unsplash.com/s/photos/machine-learning?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上的照片
## 决策树是如何工作的?
决策树是一些最常用的机器学习算法。它们用于分类和回归。它们可用于线性和非线性数据,但主要用于非线性数据。顾名思义,决策树是根据数据及其行为做出的一系列决策。它不使用线性分类器或回归器,因此其性能与数据的线性性质无关。Boosting 和 Bagging 算法已经被开发为使用决策树的基本原理的集成模型,该决策树经过一些修改以克服决策树的一些重要缺点并提供更好的结果。使用树模型的另一个最重要的原因是它们非常容易解释。
## 决策树
决策树可用于分类和回归。虽然原理是相同的,但方法略有不同。决策树使用 CART 算法(分类和回归树)。在这两种情况下,决策都基于任何特性的条件。内部节点表示条件,叶节点表示基于条件的决策。

## 分类
> 决策树是基于特定条件的决策的所有可能解决方案的图形表示。
在用于分类的决策树的每个步骤或节点上,我们尝试在特征上形成一个条件,以最大限度地分离数据集中包含的所有标签或类。让我们看看这个想法是如何运作的。

比方说,上面给出的表格是我们的数据集。如果我们尝试分析数据集并基于数据集创建决策树,我们将获得类似下面给出的树

在根节点中,我们首次使用“Feat 2 ≥3”作为分离数据集的条件。我们可以看到,如果答案是假的,我们到达一片叶子,它只有标签为 3 的条目。所以,标签 3 是完全分离的。但是,如果答案是真的,我们到达一个中间节点。在这种情况下,有 3 个条目,其中 2 个属于标签 2,一个属于标签 1。因此,这个结果有杂质,因为有两个标签混合。我们对中间态应用另一个条件,得到纯分离的标签。在叶 2 上,我们仅获得了标签 1 条目,而在叶 3 上,我们仅获得了标签 2 条目。
现在,可能出现的问题是:
1. 在数字特征的情况下,例如“feat 2≥3”,我们如何确定决定值?
2. 我们如何决定应该使用哪些特性来创建我们的内部条件节点?
3. 如何决定首先使用哪个特性,例如,在前面的例子中,我们有特性 1 和特性 2,那么,我们应该使用哪个特性作为根?
随着我们的前进,我们将会看到这些问题的答案。
在我们开始讨论这些答案的细节之前,让我们先来看看在回答这些问题时起主要作用的一些定义。
**熵:**它给出了数据中杂质或随机性的度量。它由下式给出:
> 熵= — P(类 1) x Log(P(类 1)) — P(类 2) x Log(P(类 2))
其中 P 表示概率。
如果有两个数量相等的类别,类别 1 和类别 2,即类别 1 的条目数量等于类别 2 的条目数量,并且我们随机选择一个条目,则它将以 50%的概率属于任何类别 1 或类别 2。在这种情况下,熵将会很高。
如果某个数据集的所有数据都属于类 1 或类 2,则获得的熵为 0,因为在这种情况下,P(类 1)或 P(类 2)将等于 0。如果 P(class1)=0,那么 P(class2)应该等于 1。因此,很明显,如果数据集中有不纯或混合的类别标签,熵将会很高。

Pr(x==1)
上图显示了标签概率随熵的变化。我们可以看到如果一个标签的概率是 0.5,熵是最大的。
如果数据集中总共有 20 个条目或行,其中 14 个属于标签 1,6 个属于标签 2,则熵将等于:
> = — P(标签 1)。log(P(标签 1)) — P(标签 2)。日志(P(标签 2))
>
> =—14/20 . log(14/20)—6/20 . log(6/20)
>
> =0.880
**信息增益:**信息增益是数据集基于属性拆分后熵的减少。构建决策树取决于找到返回最高信息增益的属性。它有助于选择在特定点使用哪个特征或属性来创建决定性的内部节点。
它由下式给出:
> 信息增益=熵(s) — [(加权平均)x(每个特征的熵)
那么,这实际上是如何操作的呢?

比方说,这是我们的数据集。所以,我们有特性 1 和特性 2,它们应该是我们的根节点。上述决定是基于每个特征提供的信息增益量。所以,让我们检查一下。
首先,我们想要检查基于每个特征的标签的分布,以便深入了解一个特征将提供多少信息增益。
例如对于特征 1,

我们可以看到,如果我们选择条件“特征 1==2”,我们可以成功地将标签 2 从数据集中纯粹地分离出来。
> 现在,熵(E(s))=—4/10 * log(4/10)—6/10 * log(6/10)= 0.97
>
> 对于功能 1:
>
> e(feature _ 1 = = 1)=—3/4 * log(3/4)—1/4 * log(1/4)= 0.81
>
> e(feature _ 1 = = 2)=—3/3 log(3/3)=—1 log 1 = 0
>
> e(feature _ 1 = = 3)=—2/3 * log(2/3)—1/3 * log(1/3)= 0.91
>
> 对于功能 1,加权平均值=
>
> 4/10*0.81+3/10*0+3/10*0.91=0.597
>
> 信息增益= 0.97–0.597 = 0.313
同样,让我们对特性 2 做同样的事情:
对于功能 2:

> 对于功能 2:
>
> e(feature _ 2 = = 1)=—2/3 * log(2/3)—1/3 * log(1/3)= 0.91
>
> e(feature _ 2 = = 2)=—2/3 * log(2/3)—1/3 * log(1/3)= 0.91
>
> e(feature _ 2 = = 3)=—3/4 * log(3/4)—1/4 * log(1/4)= 0.81
>
> 对于特性 2,加权平均值=
>
> 3/10*0.91+3/10*0.91+4/10*0.81=0.87
>
> 因此,特征 2 的信息增益= 0.97–0.87 = 0.1
现在,我们发现特征 1 在该点的信息增益大于特征 2。因此,我们将使用特性 1 来形成根节点。
**基尼指数:**基尼指数也是一种衡量杂质的指标,用于使用 CART 机制构建决策树。
它由下式给出:
> 基尼系数= 1 —(“第一类”的概率)——(第二类”的概率)
让我们看看它的工作情况,

比方说,这是我们在 100 个条目的数据集上的分布。应用于特征 1 的条件给出了上述结论。
> 叶的基尼系数 1:1-(35/43)—(8/43)= 0.302
>
> 叶 2 的基尼系数:1 — (15/57) — (42/57) =0.38
>
> 现在,特征 1 的总体基尼系数杂质:
>
> 基尼系数的加权平均值:
>
> =43/100* 0.30+ 57/100*38=0.34
同样,我们还计算了其他特征的基尼系数。
需要注意的一点是,如果数据集中的每个条目只属于一个类,即类 1 或类 2,
> 基尼杂质:1-(1/(0+1) )-(0/(0+1) )=0
因此,我们可以看到,对于一个纯粹的分布,基尼系数是 0。
Gini 杂质指数也可以用于决定应该使用哪个特征来创建条件节点。选择产生较小基尼系数杂质指数的特征,以在该点创建内部条件节点。
我们已经看到了一些概念,为了理解决策树的工作原理,我们需要知道这些概念。我想我们已经找到了第二个和第三个问题的答案,即特征是如何决定的,以及哪个特征被用来形成结论的条件。我们现在需要找到第一个问题的答案,即在连续数字特征的情况下,如何获得用于形成条件的值。
寻找最合适的值来创建条件的过程非常简单。首先,我们基于数值特征以升序方式对数据集进行排序。接下来,我们找到相邻数值对的平均值。

比方说,我们获得了如上所示的平均值。所以,avg_1=(val_1+val_2)/2。接下来,根据我们使用的方法,我们拟合条件中的平均值,以检查哪个提供了最小的基尼系数或哪个提供了最大的信息增益。平均值用作我们为该特征形成的条件中的截止值。
类似地,对于基于离散值或基于类的特征,我们尝试拟合集合中存在的每个值并创建条件。最后,我们选择给出最小基尼系数的值或条件。我们的第一个查询到此结束。
现在,我们已经看到,我们考虑基尼系数或信息增益来决定我们应该考虑哪种情况。在某些情况下,一些特征显示根本没有改进或者没有信息增益,这样的特征从不在决策树中使用。决策树就是这样进行自动特征选择的。
决策树的主要挑战之一是它会导致数据过度拟合。这主要是因为它为训练数据创建了基于条件的方法。所以,它与训练数据非常吻合。现在,对树中的训练数据应用的条件越多,树就长得越深,它就越适合数据。但是在一个点之后,它开始考虑一些特征上的非常小的变化,这给出非常低的信息增益,通常这些点破坏了模型的泛化,并且在测试数据上表现得像异常值。我们可以通过使用信息增益的阈值来限制这些条件,这样,如果条件提供的信息增益小于给定值,我们就不会考虑该条件。这部分地防止了过度拟合,并有助于创建通用模型。
剪枝是一种删除节点以获得最优解和降低复杂度的树的方法。它删除分支或节点,以便创建降低过拟合倾向的子树。一旦我们完成了回归树,我们将讨论这个概念。
## 回归
要理解回归树的概念,必须对回归和线性回归的概念有一个清晰的认识。如果需要,请随意阅读我关于回归的文章。
让我们考虑两个条件:

在第一个分布中,我们可以看到,我们可以很容易地拟合一条线。所以,在这种情况下,我们可以用线性回归来预测一个值。但是,在第二种分布的情况下,很明显,我们不能用任何特定的直线来拟合分布来预测值,因为分布在不同的范围内表现非常不同。换句话说,在第二种情况下,分布是非线性的。在这种非线性情况下,使用回归树。一个论点是,我们可以对非线性数据使用多项式回归,但有时分布分析和决定多项式相当复杂,因此,决策树的基于条件的方法是首选。
在回归树中,叶子代表一个连续的数值,而分类树通常在叶子上代表布尔值或离散值。

上图展示了回归树的基本结构。当多个特征加入并且特征集的维度增加时,树变得更加复杂和难以分析。
现在,让我们看看如何决定我们应该选择哪个值来创造条件。这与我们在分类树中所做的有点不同。
假设我们有一个由三个特性组成的特性集:特性 1、特性 2 和特性 3。

功能 1 的分布
让我们把上面的图像看作是特性 1 的分布。y 轴具有我们需要拟合回归的值,X 轴具有特征值。因此,我们将图表中显示的值 Val 1、Val 2 等视为构成要素 1 条件的截止值。这些值只是两个对应点的特征 1 值的平均值。现在,让我们看看计算是如何进行的。

现在,让我们考虑上面的图表。这些图不是按比例绘制的,所以 avg_2 不等于 avg_4。当我们将 val_1 视为要素 1 的临界值时,我们将线左侧点的所有 Y 值的平均值视为 avg_1,同样,我们将线右侧所有点的平均值视为 avg_2。因此,对于条件 feature 1>val_1 为真的任何值,树提供 avg_2 作为预测,反之亦然。
接下来,我们计算所有点的平方误差。因此,对于线右侧的任何点,该点的平方误差为(实际值-预测值(即 avg_2)),类似地,对于左侧的任何点,该点的平方误差为(实际值-预测值(即 avg_1))。所以,我们找到所有点的平方误差,然后求和。这叫做误差平方和。比方说,对于值 1,误差平方和是 S_1。
类似地,对于值 4,计算误差平方和为 S_4。我们可以观察到 S_4 会比 S_1 小很多。因此,我们找到所有我们观察的值的误差平方和,作为创建条件的截止值。如果我们绘制它们,我们将获得如下所示的图。

在上图中,我们可以看到特征 1 的 val_4 提供了该点的最小误差平方和。现在,我们已经看到了特定值的截止值是如何确定的。
现在,如果我们有多个特征,如何决定我们应该使用哪个特征来创建节点。为此,我们创建候选人。例如,对于特征 1,val_4 给出最小的误差平方和。因此,它被称为功能 1 的候选。类似地,我们找到特征 2 和特征 3 的候选者。假设特征 2 的候选对应的 SSR 是 S2 _ 3,特征 3 的候选对应的 SSR 是 S3 _ 5。我们将比较 S_4、S_2_3 和 S_3_5,并选择最小值。对应于最小值的特征将被用于创建决定节点。
上述方法被递归地用于创建回归树。至此,我们已经看到了 CART 机制是如何工作的,以及分类树和回归树是如何形成的。现在,简单回顾一下树木中一个非常重要的概念:修剪。
## 修剪
该方法用于树中以减少过度拟合。这是一个减少树的节点和分支以减少树的深度的过程。

上图显示了修剪的概念是如何工作的。
基本上有两种类型的修剪:
1. 预修剪
2. 后期修剪
在预修剪中,我们在创建树的过程中设置参数,如“最小样本数”、“最大深度”和“最大叶子数”。所有参数都需要超参数调整,并使用交叉验证和网格搜索方法找到。它将树限制在一定的深度或一定数量的叶子。
后期修剪方法大多是在树已经形成之后进行的。成本复杂性修剪是最常用的后修剪方法。
## 结论
决策树具有巨大的重要性,因为它们在 bagging 和 boosting 的情况下形成了集成学习模型的基础,bagging 和 boosting 是机器学习领域中最常用的算法。同样,由于其简单的结构和可解释性,决策树被用在一些人类可解释的模型中,如 LIME。
在本文中,我们已经看到了决策树是如何使用 CART 原理工作的。
希望这有所帮助。
# 元数据中心工具探究
> 原文:<https://towardsdatascience.com/a-dive-into-metadata-hub-tools-67259804971f?source=collection_archive---------35----------------------->
## 如今,“元数据中心”正在发生一些变化

作者图片
元数据中心(有时也称为元数据搜索和发现工具)似乎是分析领域正在发生的另一种趋势/运动。仅在过去的两年里,我们已经看到许多元数据中心项目被主要的技术公司发布、撰写或开源。其中包括:
* Airbnb 的[数据门户](https://medium.com/airbnb-engineering/democratizing-data-at-airbnb-852d76c51770)
* 网飞的[元卡特](https://github.com/Netflix/metacat)
* 优步的[数据手册](https://eng.uber.com/databook/)
* LinkedIn 的[数据中心](https://github.com/linkedin/datahub)
* Lyft 的[阿蒙森](https://www.amundsen.io/)
* Spotify 的 [Lexikon](https://engineering.atspotify.com/2020/02/27/how-we-improved-data-discovery-for-data-scientists-at-spotify/)
* 以及谷歌云平台的[数据目录](https://cloud.google.com/data-catalog)(虽然我只是把它包括进来,因为它看起来像是对当前市场上元数据中心趋势的回应)。
在这篇文章中,我将快速总结这些产品旨在解决的问题,快速概述每个项目,然后深入研究看起来最有希望的两个项目:LinkedIn 的 Datahub 和 Lyft 的 Amundsen。
# 什么是元数据中心?
假设您是一家大型公司的数据用户或数据分析师,该公司在全球有许多办公室。您的数据组织分布在这些位置,您在不同的数据仓库和 BI 工具中有数千个表,还有分布在整个公司不同分析阶段的数百个报告、数据集和数据模型。你需要找到你需要的报表,或者你想要的数据集。如果你找不到这些东西,那么你需要找到下一个最好的东西:你需要知道向谁询问,或者向组织中的哪个团队询问。
进入元数据中心。
元数据中心的目标是充当公司内整个数据生态系统的“搜索引擎”。名称中的“元数据”意味着“关于数据的数据”。这包括表模式、列描述、访问记录以及与每个数据库或数据仓库相关联的 SLA 等信息,还包括“哪个团队负责这个数据集”以及“最后一个从这个数据集创建报告的人是谁?”
当然,正如 LinkedIn 数据中心的 Mars Lan 所说:“如果你能通过问你公司的一个人来找到所有东西的位置,那么你肯定*不需要这个。”只有当您是一个大型组织,并且您需要跨整个组织扩展数据访问时,元数据中心才变得重要。你会听到像“数据民主化”和“数据可发现性”这样的词被抛来抛去;他们真正指的是随机数据分析师跟上一个非常大的数据生产和数据消费组织的能力。*
> 只有当您是一个大型组织,并且您需要跨整个组织扩展数据访问时,元数据中心才变得重要。
概括地说,*我上面提到的所有*元数据中心项目都提供了以下内容的某种组合:
* **搜索:**终端用户的搜索界面。
* **Discovery:** 一个可探索的界面,供用户浏览和导航不同的数据源,并深入到表或行级别。
* **自动化:**一个 API 服务,公开元数据供其他内部数据服务使用。
* **管理:**选择、保存和管理元数据集合的能力。
某些项目,如 Airbnb 的 Dataportal 和 Spotify 的 Lexikon,能够公开用户资料,以便你可以找到最近接触过你感兴趣的数据集的个人或团队。但其他人没有。
# 这些项目,简单来说
我将按时间顺序浏览这些项目,如果你愿意,我会给你足够的外部链接,让你可以去寻找最初的公告帖子、存储库(如果有的话)和技术讲座。但是,如果您想了解好的部分,我建议您浏览这一部分(特别注意关于 Amundsen 和 Datahub 的部分),然后跳到下一部分,在那里我将比较这两个项目。这两个人似乎是目前社区活动最多的人。
# Airbnb 的数据门户,2017 年 5 月 11 日

Airbnb 公布数据门户的博文截图。到目前为止,它不是开源的,也没有任何更新。图片作者。
这个列表中最早的项目是 Airbnb 的 Dataportal。克里斯·威廉姆斯和约翰·博德利在 GraphConnect Europe 2017 的舞台上首次描述了 Dataportal(此处提供幻灯片)。一天后,也就是 2017 年 5 月 12 日,他们发表了一篇博文,描述了这个系统。
Dataportal 跟踪谁在 Airbnb 内生产或消费数据资源。该项目将这些关系建模为 neo4j 中的图表,这意味着他们可以提供一个搜索引擎,使用 Pagerank 算法,将这些关系展现给用户。
Dataportal 从来都不是开源的,有趣的是,它也没有出现在[https://airbnb.io/projects/](https://airbnb.io/projects/)上。从那以后我们再也没有听说过这件事。
# 网飞的 Metacat,2018 年 6 月 15 日
大约一年后,网飞发表了一篇[博文](https://netflixtechblog.com/metacat-making-big-data-discoverable-and-meaningful-at-netflix-56fb36a53520)描述他们的元数据系统,命名为 Metacat。这个项目是为了填补网飞数据栈中的一个漏洞而构建的——本质上,他们需要一个元数据服务来介于他们的 Pig ETL 系统和 Hive 之间。
Metacat 系统是网飞数据基础设施中的一个联合服务。它提供了一个统一的 API 来访问网飞内部生态系统中各种数据存储的元数据,但它是根据网飞自己的工具和数据堆栈高度定制的。它看起来没有特别好的可扩展性。

Metacat 的 Github 页面。作者照片。
Metacat 是[开源的](https://github.com/Netflix/metacat),正在积极开发中,但似乎不是为外部采用而设计的。截至发稿时,他们的 Github 自述文件包含一个标题为“Documentation”的部分,下面写有“TODO”字样。
# 优步的数据手册,2018 年 8 月 3 日
优步的数据手册是在网飞的 Metacat 发布后一个月左右在一篇博客文章中公布的。

优步公布数据手册的博客文章——作者照片。
Databook 从 Hive、Vertica、MySQL、Postgres 和 Cassandra 获取元数据,并在一个界面中展示表模式、列描述、来自数据库的样本数据、统计数据、沿袭、新鲜度、SLA 保证和数据所有者等内容。它还允许 Databook 用户在其用户界面中组织和管理这些元数据。在早期阶段,Databook 建立在一个爬虫架构上(也就是说,Databook 将运行爬虫,从各种数据源收集元数据),但随着时间的推移,优步的数据工程团队最终将系统切换到一个建立在 Kafka 之上的系统。他们还从 MySQL 转换到 Cassandra,以便支持多个数据中心,同时不会增加延迟。
Databook 并不是开源的,我们也没有听说过它。据推测,它仍然在优步广泛使用。
# Lyft 的阿蒙森,2019 年 8 月 3 日
Lyft 的 Amundsen 是在 2019 年 8 月 3 日[宣布](https://eng.lyft.com/amundsen-lyfts-data-discovery-metadata-engine-62d27254fbb9)的,然后几个月后[开源](https://eng.lyft.com/open-sourcing-amundsen-a-data-discovery-and-metadata-platform-2282bb436234),同年 10 月 31 日。
阿蒙森的书出版后引起了一些轰动。dbt [的 Tristan Handy 写了关于 Amundsen 开源的](http://roundup.fishtownanalytics.com/issues/amundsen-s-launch-scaling-a-data-team-resampling-evolutionary-algorithms-open-source-segment-dsr-205-209650):
> *这款产品非常重要,我真的相信在未来五年内,该产品类别将成为数据领域最重要的产品类别。所有东西都需要放入目录中。*
阿蒙森的 DNA 中有过去系统的痕迹。与 Dataportal 一样,它允许您在公司内部搜索数据资源,并为它可以访问的每个数据源中的每个表公开一个可发现的界面,一直到行级别。在发布时,创建者还谈到了他们打算如何与 Workday 等工具集成,以便在 Amundsen 的搜索图中显示员工信息,这样您就可以联系到与您感兴趣的数据集有关联的同事。

Lyft 的博客文章宣布阿蒙森。作者照片。
Amundsen 由许多不同的部件组成([来源](https://eng.lyft.com/open-sourcing-amundsen-a-data-discovery-and-metadata-platform-2282bb436234)):
* **元数据服务**处理来自前端服务以及其他微服务的元数据请求。默认情况下,持久层是 Neo4j。
* **搜索服务**由 Elasticsearch 支持,处理来自前端服务的搜索请求。这个搜索引擎也可以被替代。
* **前端服务**是一个 Flask webapp,托管一个 React 前端。这是用户交互的主要界面。
* **Databuilder** 是一个通用的数据摄取框架,它从各种来源提取元数据。它受 Apache[goblin](https://eng.lyft.com/open-sourcing-amundsen-a-data-discovery-and-metadata-platform-2282bb436234)的启发,作为 ETL 工具将元数据推送到 Amundsen 的元数据服务中。它使用气流作为工作流程工具。
* 最后, **Common** 是一个库 repo,它保存了阿蒙森所有微服务的公共代码。
在阿蒙森发布的博客文章中,作者[注意到](https://eng.lyft.com/amundsen-lyfts-data-discovery-metadata-engine-62d27254fbb9)发现数据假象的时间已经降低到阿蒙森之前基线的 5%。阿蒙森的社区可能是这里涵盖的所有项目中最大的,并且它今天仍在快速增长。
# 领英的数据中心,2019 年 8 月 14 日
[宣布](https://engineering.linkedin.com/blog/2019/data-hub)在阿蒙森之后不到两周,LinkedIn 的数据中心实际上是他们建立元数据中心的第二次尝试。2016 年,LinkedIn 开源了 [WhereHow](https://engineering.linkedin.com/blog/2016/03/open-sourcing-wherehows--a-data-discovery-and-lineage-portal) ,这影响了本文提到的其他一些项目。但 Datahub 是从头开始编写的,旨在解决 LinkedIn 在 WhereHow 方面遇到的一些问题。
最有趣的是,Datahub 建立在“基于推送”的架构之上。这意味着必须修改组织中的每个数据服务,以便将元数据推送到数据中心,而不是让数据中心从服务中抓取数据。在实践中,这并不太难做到,因为 Datahub 是建立在 Kafka 流之上的,Kafka 已经在 LinkedIn 中广泛使用(Kafka 是在那里创建的)。

DataHub 的 Github 页面。你可以看到这个项目正在进行中。作者照片。
Datahub 的架构带来了许多有趣的好处。首先,它允许增量摄取(而不是每隔一段时间进行一次抓取或快照)。其次,它允许近乎实时的更新,因为任何推送到数据中心的更改都会立即传递给下游用户。火星兰,创作者之一,笔记(播客;大约在 [18:20](https://www.dataengineeringpodcast.com/datahub-metadata-management-episode-147/) 左右)这种设置允许您构建使用从 Datahub 发出的 changestream 的应用程序,并且他们已经在 LinkedIn 中广泛地这样做了。
事实上,[整集播客](https://www.dataengineeringpodcast.com/datahub-metadata-management-episode-147/)值得一听。Lan 谈到了他们在 Datahub 中提出可扩展但通用的数据模型时需要做出的一些权衡(“当人们花 90%的时间讨论如何正确地对元数据建模,然后花 10%的时间实际编码时,你知道你已经成功了。”).它让你感受到工程师们给这个项目带来的丰富经验。
Datahub 在今年二月被[开源](https://engineering.linkedin.com/blog/2020/open-sourcing-datahub--linkedins-metadata-search-and-discovery-p)。稍后会有更多的介绍。
# Spotify 的 Lexikon,2020 年 2 月 27 日(尽管建于 2017 年)
Spotify 的 [Lexikon](https://engineering.atspotify.com/2020/02/27/how-we-improved-data-discovery-for-data-scientists-at-spotify/) 与之前的项目覆盖了大部分相同的领域。Lexikon 的最初版本建于 2017 年,以应对 Spotify 转移到 GCP 和 BigQuery 后数据集的爆炸。

Spotify 公布 Lexicon 的博文。到目前为止,这个项目还没有开源。作者照片。
该项目的最新颖之处在于,它为数据用户提供了算法生成的个性化数据集建议。(如果你仔细想想,*这是 Spotify 应该做的事情*)。像 Dataportal 一样,Lexikon 提供了一种搜索体验,同时也提供了可能对你正在查看的数据集有所帮助的用户。像 Amundsen 和 Datahub 一样,Lexicon 向您显示表级和列级的统计信息。
Lexikon 不是开源的。
# 谷歌云的数据目录,2020 年 5 月 1 日
[谷歌云的数据目录](https://cloud.google.com/data-catalog)是一种类似的元数据服务,但它只适用于 GCP 服务,如 BigQuery、Pub/Sub 和云存储文件集。这个想法是,你将数据目录添加到一个现有的 GCP 主持的项目中,打开开关,享受谷歌数据目录的好处。
我只包括这个项目有两个原因。首先,谷歌[宣布它已经在 2020 年 5 月 1 日](https://cloud.google.com/blog/products/data-analytics/data-catalog-metadata-management-now-generally-available)全面上市,就在不久之前。对于外部观察者来说,这似乎是对该领域当前活动的回应,这对整个数据生态系统来说是个好兆头。
其次,谷歌表示,数据目录是建立在从他们的*商品*数据系统中提取的洞察力之上的,该数据系统过去是(现在是?)作为一种非常有效的数据目录服务在谷歌内部使用了很多年。描述这个系统的论文可以在[这里](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/45390.pdf)找到。
# 观看阿蒙森和数据中心
在这组项目中,Amundsen 和 Datahub 似乎是领先者。阿蒙森有一个热闹的社区,一个非常时髦的 [网站](https://www.amundsen.io/),以及许多有趣的案例研究:[edmunds.com](https://technology.edmunds.com/2020/05/27/Adding-Data-Quality-into-Amundsen-with-Programmatic-Descriptions/)、 [ING](https://medium.com/wbaa/facilitating-data-discovery-with-apache-atlas-and-amundsen-631baa287c8b) 和 [Square](https://developer.squareup.com/blog/using-amundsen-to-support-user-privacy-via-metadata-collection-at-square/) 。其他采用 Amundsen 的公司包括 Workday、Asana 和 iRobot。
Amundsen 在 Datahub 上有一点领先,因为它在去年 10 月开源。社区更大,截至 8 月 11 日,阿蒙森现在是 Linux Foundation 的 AI 基金会孵化项目。更重要的是,你可以在[新闻稿](https://lfai.foundation/blog/2020/08/11/amundsen-joins-lf-ai-as-new-incubation-project/)中看到项目创建者 Mark Grover 的声明:
> *“成为 LF AI 基金会的一员是该项目在成为事实上的开源数据发现和元数据引擎的旅程中的一个重要里程碑。看到 Lyft 采用 Amundsen,以及其开源社区的增长,现在已经有超过 750 名成员,真是令人惊讶。我很高兴看到这个项目在 LF AI 基金会的支持下持续增长并取得成功。”*
另一方面,Datahub 应该受到重视,因为 LinkedIn 在开源项目方面的记录(他们创建了 Kafka,然后开源了 Kafka,Kafka 现在是云基础设施领域的一个主要项目,Datahub 建立在 Kafka 之上*……用创建者的话说,使扩展它的工作成为一个“解决的问题”)。根据他们的 Github 页面,采用 Datahub 的组织数量也相当可观:其中包括 Expedia、Saxo Bank、TypeForm 和 Experius 等公司。*
这是值得注意的,因为 DataHub 仅在六个月前开源。Mars Lan 和 Pardhu Gunnam 最近在[数据工程播客](https://www.dataengineeringpodcast.com/datahub-metadata-management-episode-147/)上接受了采访,他们指出,采用的速度和不断增长的社区让他们有些吃惊。兰还认为,他们的方法优于市场上的其他任何方法,因为四年多前在 LinkedIn 内建立 [WhereHow](https://engineering.linkedin.com/blog/2016/03/open-sourcing-wherehows--a-data-discovery-and-lineage-portal) 的经验来之不易(应该指出,兰没有参与 WhereHow,但 WhereHow *的使用为 Datahub 的设计提供了*)。
# 结论
当我写这篇文章的时候,距离这些项目公开发布已经一年多了,距离开始采用开源还不到一年,距离它们成熟还有很长的路要走。
鉴于这些项目解决了非常相似的问题,并得到了强大的技术公司的支持,而且大多数项目都选择了开源方法,看看哪些项目会走在前面以及是什么让它们这样做将会很有趣。
# 推动分类数据的测试
> 原文:<https://towardsdatascience.com/a-drive-to-tests-on-categorical-data-2154cb89093?source=collection_archive---------52----------------------->

阿克希特·普里耶什
## 什么是数据的分类分析?
C 分类数据分析是将响应变量分成一组互斥的有序(如信用评分组)或无序(如贷款类型)类别的数据分析。
## 用更简单的话说
> 在统计学中,我们使用总体样本进行分析,在该样本中,属于特定组的数据点总数称为频率,因此这种分类数据分析称为频率分析。定量描述一组数据特征的研究称为描述统计学。频率分析是描述统计学的一部分。在统计学中,频率是一个事件发生的次数。频率分析是统计学的一个重要领域,它处理出现的次数(频率)并分析集中趋势、离差、百分位数等的度量。对于这种频率分析,我们有许多统计测试。我们将在本文中讨论一些重要的测试。
# 卡方检验
这是最常见、最常用和最重要的假设检验之一。一个**卡方检验**,也被写为**T5χ2 检验**,是一个[统计假设检验](https://en.wikipedia.org/wiki/Statistical_hypothesis_testing),当检验统计量在[零假设](https://en.wikipedia.org/wiki/Null_hypothesis)下为[卡方分布](https://en.wikipedia.org/wiki/Chi-squared_distribution)时[有效](https://en.wikipedia.org/wiki/Validity_(statistics))执行,特别是[皮尔逊卡方检验](https://en.wikipedia.org/wiki/Pearson%27s_chi-squared_test)及其变体。皮尔逊卡方检验用于确定在[列联表](https://en.wikipedia.org/wiki/Contingency_table)的一个或多个类别中,预期[频率](https://en.wikipedia.org/wiki/Frequency_(statistics))和观察到的频率之间是否存在[统计显著性](https://en.wikipedia.org/wiki/Statistical_significance)差异。
卡方检验有两种类型**。两者都将卡方统计和分布用于不同的目的:**
**卡方拟合优度测试**确定样本数据是否与总体匹配。
一个**卡方独立性检验**比较列联表中的两个变量,看它们是否相关。在更一般的意义上,它测试分类变量的分布是否彼此不同。
* **非常小的卡方检验统计量**意味着您的观察数据与您的预期数据非常吻合。换句话说,是有关系的。
* 非常大的卡方检验统计量意味着数据不是非常吻合。换句话说,没有关系。
## 用简单的话,用简单的例子
> 卡方检验给出了一个“p”值来帮助我们决定哪一个应该是完美的和首选的蜜月目的地。

举例。阿克希特·普里耶什
> **性别影响蜜月目的地吗?**
>
> 如果性别确实影响首选蜜月目的地,我们说他们是依赖。
>
> 通过简单的计算,我们可以很容易地找到 p 值。
>
> p 值为 0.101
>
> 现在, **p < 0.05** 是对**依赖性**的通常测试。
>
> 在这种情况下 **p 大于 0.05** ,因此我们认为变量是独立的**。**
>
> **换句话说,男人和女人可能对泰姬陵和巴黎有不同的偏好,而不是 T21。这只是我们在收集数据时预期的随机差异。**
****
**卡方公式。**
> **使用 python 进行卡方检验**
>
> **t,p = stats.chisquare(dataframe)**
# **费希尔精确试验**
**从前面的例子中,我们知道卡方检验是近似的,所以我们需要一个精确的检验。对于这个精确的测试,费希尔的精确测试进入了框架。**
****费希尔精确检验是一种用于列联表分析的统计显著性检验。尽管在实践中,当样本量很小时使用它,但它对所有样本量都有效。****
> **使用 python 导入**
>
> **stats.fisher_exact**
**它返回 p 值,用于查找极端值或比观察值更极端的值。**
**例如,x 是度假目的地海滩或山区,y 是旅游目的地海滩或山区的数量。如果果阿旅游了 5 次,珠穆朗玛峰旅游了 1 次,果阿没有山和 4 个不同的海滩。那么相关的矩阵将是**
****
**举例。阿克希特·普里耶什**
**实际上总和为 1。小于或等于 Pcutoff= 0.0238 的 p 值之和是 0.0476,因为它小于 0.05,所以[有效](https://mathworld.wolfram.com/Significance.html)。因此,在这种情况下,在目的地和出现的目的地类型之间将存在统计上显著的关联。**
# **麦克内马试验**
**在统计学中,麦克内马检验是一种用于成对名义数据的统计检验。它应用于具有二分特征的 2 × 2 列联表,具有匹配的受试者对,以确定行和列的边际频率是否相等。它是以奎因·麦克尼马尔的名字命名的,他在 1947 年引进了它。**
> **在 python 中**
>
> **从 statsmodels.sandbox.stats.runs 导入 mcnemar**
# **科克伦 Q 检验**
**在统计学中,在双向随机区组设计的分析中,响应变量只能采用两种可能的结果,Cochran 的 Q 检验是一种非参数统计检验,用于验证 k 处理是否具有相同的效果。它是以科克伦命名的。**
> **在 python 中**
>
> **从 statsmodels.sandbox.stats.runs 导入 cochrans _ q**
## **结束注释
本文的重点是收集&演示分类数据测试的概念。这种方法提供了一个自然的框架来处理参数和模型的不确定性,并且已经变得非常流行,特别是在像机器学习这样的领域。然而,它的计算量要大得多,因此通常需要借助现有的工具(如 statsmodels 或 stats)来实现。这也显示了像 Python 这样的自由和开放语言的优势之一,因为它们提供了一种建立在科学界现有工作基础上的方法,并且只需要我们的热情和奉献。**
# 错误的选择:拯救生命还是拯救经济
> 原文:<https://towardsdatascience.com/a-false-choice-save-lives-or-the-economy-4a420822b510?source=collection_archive---------37----------------------->
## 生命可以被拯救,但经济总是会受到冠状病毒的沉重打击
***编者按:*** [*走向数据科学*](http://towardsdatascience.com/) *是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击* [*这里*](https://www.who.int/emergencies/diseases/novel-coronavirus-2019/situation-reports) *。*

周日晚上,川普总统在推特上表示,他不希望解决新冠肺炎问题的方法比问题本身更糟糕。其他人,包括非常严肃的人如[埃隆·马斯克](https://twitter.com/elonmusk/status/1239756900255903744?s=20)和[杨安泽](https://twitter.com/AndrewYang/status/1236395050441027584?s=20),都说对抗病毒的经济损失超过了如果我们选择什么都不做或反应软弱可能导致的死亡。得克萨斯州副州长丹·帕特里克说得更直白,他认为很多祖父母会愿意为他们的孙辈牺牲经济。
这种思维有两种解读方式。一是人们不相信公共卫生专家的说法,即冠状病毒的致命性是季节性流感的十倍,季节性流感在美国每年导致 3-4 万人死亡,即使有疫苗(冠状病毒疫苗可能要到明年的 T32 才能准备好)。另一个解释是,美国老年人的生命没有得到适当的重视,这比专家对病毒危险的估计更有可能是不正确的。
## 珍惜生命
人们怎么能把这些生命的价值与试图拯救它们的代价相比较呢?人们可能会觉得生命是无价的,但保险公司和政府机构等组织会给人的生命贴上价格标签,以衡量不同的政策决定。以 2020 年的美元计算,美国环保署估计一个人的生命价值为 1050 万美元。这比其他估算生命价值的方法都要高,比如用一个人一生的收入来估算(2020 年价值 280 万美元)。但它抓住了人们在经济贡献之外还有价值的直觉。
利用环境保护局的生命价值和其他一些指标,人们可以比较不同政策选择的成本。我们有[按年龄组估计的](https://www.imperial.ac.uk/media/imperial-college/medicine/sph/ide/gida-fellowships/Imperial-College-COVID19-NPI-modelling-16-03-2020.pdf)病毒致命程度,我们知道每个年龄组有多少[人。我们还对最终处于严重或危急状态的冠状病毒病例的比例以及每种类型的病例可能花费的费用有所了解。最后,研究人员估计了在人们行为的各种假设下,病毒的致命性。](https://data.census.gov/cedsci/table?q=Population%20Total&hidePreview=false&t=Population%20Total&tid=ACSDP1Y2018.DP05&vintage=2018)
在没有政策应对措施和很少或没有行为应对措施的情况下,[早期最坏情况](https://www.nytimes.com/2020/03/13/us/coronavirus-deaths-estimate.html)估计冠状病毒将在美国导致 170 万到 220 万人死亡。然而,这种灾难不太可能在现实中发生。即使政府对这样的疫情无所作为,人们也会改变他们的习惯,许多其他机构如企业和学校也会改变他们的行为来减缓病毒的传播。更有可能的情况是,死亡人数估计在 20 万到 48 万之间,中间值为 34 万,是季节性流感每年死亡人数的十倍。
## 比较政策成本
下表显示了将所有这些数字放在一起的结果。很难说当前的政策会属于哪种情况。尽管鉴于迄今为止的行动,我们不太可能看到最坏的情况估计,但根据图 1 所示的数据,很明显,美国的反应看起来更像意大利,而不是中国或韩国。我的假设是,目前的政策符合更有可能的 20-48 万人死亡的估计。

更有可能的情况是直接成本占 GDP 的-1.2%到-2.8%。这包括 160 万或更多重症或危重病例的住院费用以及生命价值损失。这还不包括*不能*因集中资源治疗冠状病毒而造成的影响(在最糟糕的情况下,这一影响会更高)。这些数字也不包括对经济的后续影响。
高盛[估计](https://www.goldmansachs.com/insights/pages/us-daily-20-march-2020.html)由于公共卫生状况,经济将在 2020 年收缩 3.8%。但总的影响不仅仅是-3.8%,而是这种增长与没有冠状病毒的情况有多么不同。[过去五年的平均经济增长率](https://fred.stlouisfed.org/series/GDPC1)为 2.3%,但在病毒来袭前[市场预计会出现衰退](https://markets.businessinsider.com/news/stocks/next-recession-trump-survey-shows-most-economists-predict-downturn-2021-2019-8-1028456445)。我的方法使用了一个介于平均增长率和 1990 年、2001 年和 2009 年的平均值 0.3%之间的值,结果为 1.3%。总体而言,该病毒的经济影响为 GDP 的-5.1%-3.8%-1.3%。
这个数字应该与更可能发生的情况的直接成本结合起来,以计算我们当前政策的总成本,结果是 GDP 的-6.3%到-7.9%。与最坏的情况相比,这个成本就相形见绌了。无所作为的直接成本(不包括经济状况)估计为 GDP 的-9.8%到-12.7%,远远高于现行政策。
## 面对威胁,人们会改变行为
然而,说什么都不做就意味着经济将继续沿着同样的增长道路前进是错误的。最糟糕的情况表明,1370-1780 万人将因严重或危急病例而住院。由于对人们产生了如此巨大的影响,从某种意义上来说,一旦佛罗里达的春假孩子因为危及父母和祖父母的安全而受到严厉指责,他们就会停止外出。联邦政府之外的机构会制定政策来保证人们的安全。综合来看,这些措施会减缓经济增长。
即使美国选择什么都不做以避免衰退,其他国家仍然会让[关闭](https://www.youtube.com/watch?v=KxtGJsnLgSc)他们的大部分经济活动,这将会减缓全球经济,降低美国的增长。我在这里的假设是,在最糟糕的情况下,对美国经济的影响将是一半(-2.6%,而不是-5.1%),导致总成本为 GDP 的-12.4%至 15.2%,远远高于美国迄今为止采取的黯淡应对措施的成本。
如果一个人对生活有不同的价值观,或者认为经济在最坏的情况下会更好,那会怎样?任何人都可以在这里下载电子表格模型[,并利用输入来观察影响。这些结果对许多关于最坏情况下经济增长和生命价值的合理假设选择是稳健的。](https://github.com/tgwhite/Public_Policy/blob/master/Projects/COVID-19/Economic%20costs%20of%20coronavirus.xlsx?raw=true)
## 但是拯救经济需要多少成本呢?
这篇文章的早期反馈正确地指出,目前国会正在辩论的财政刺激方案(约 2 万亿美元)的价格高于当前的政策(占 GDP 的 7.1%,约 1.5 万亿美元)。然而,财政刺激计划旨在让经济恢复活力,目标是让经济比没有刺激时增长得更快。
这意味着刺激的净成本低于其初始价格。例如, [TARP](https://en.wikipedia.org/wiki/Troubled_Asset_Relief_Program) 是一项 7 亿美元的计划(实际投资约 4 亿美元),旨在帮助 2008 年金融危机后的[最终实现盈利](https://money.cnn.com/2014/12/19/news/companies/government-bailouts-end/)。很难说这项刺激计划的最终成本是多少,但值得指出的是, [2017 年特朗普减税](/which-party-adds-more-to-deficits-a6422c6b00d7)仅在 2018 年就使政府收入减少了大约[5000 亿美元](https://www.cnbc.com/2019/12/05/us-tax-revenue-dropped-sharply-due-to-trump-tax-cuts-report.html)。危机过后回到奥巴马时代的收入水平将有助于为当前的刺激买单。
## 人们不仅仅是经济贡献者
事实是,从来就没有什么也不做的选择。各州命令人们就地避难是一件好事,这不仅仅是因为拯救生命的价值。上面的功利算计,错过了以尊严和尊重待人的价值。这种尊重有助于一个有凝聚力的社会,并支持个人权利。
未来的问题是,特朗普政府和州/地方政府会坚持到底吗?我最担心的是,人们会变得如此担心经济,以至于放松限制和他们自己的个人安全措施,这将导致病毒传播的死灰复燃,就像在台湾看到的那样。鉴于迄今为止的经济损失和许多人对传播病毒的恐惧,放松限制不太可能让经济起死回生。
*数据仓库和脚本可以在* [*这里找到*](https://github.com/tgwhite/Public_Policy/tree/master/Projects/COVID-19) *。*
# 虚假的安全感
> 原文:<https://towardsdatascience.com/a-false-sense-of-security-when-investment-firms-tell-you-they-ran-1000-simulations-11673ffc9572?source=collection_archive---------60----------------------->
## 或者,当投资公司告诉你他们进行了 1000 次模拟时,你为什么要小心翼翼
所以,几天前,我和我爸爸就如何处理我银行里的一些现金发生了一点小争执。我想用这笔钱来产生比大多数银行提供的可怜的 0.5%的利率更好的利率。我父亲更倾向于把我的钱存放在一个随机的顾问那里,并相信他们会投资,而我更倾向于自己管理这笔钱。由于无法得出结论,我们决定进行一次实验,并决定以 2:1 的比例分割这笔钱,将 2/3 的钱存放在这家新的、受欢迎的投资公司,并将 1/3 的钱留给我投资。
然而,当我开始调查这家公司时,我变得有点警惕——特别是因为他们一直宣传自己是一家“数据驱动”的公司,并拥有所有这些很酷的图形。下面是文章大纲(和 TL;博士)
# TL;博士;医生
1. 这家公司是新加坡金融公司,拥有数据驱动解决方案和专有系统
2. 问题:
a .模拟的不准确性/不可靠性:模拟/模型的准确性取决于其输入的准确性。如果输入一开始就有缺陷,那么运行一个模型 1000 或 1000000 次并不会提高它的预测准确性。因此,他们的 1000 次模拟预测并不令人印象深刻。
b .历史回报+费用:历史回报(公司用于预测)从不具有指示性或提供未来回报的确定性。此外,费用会影响回报率。
3. 结论:投资公司做这样的预测没有错,但作为消费者,我们必须意识到,它们并不总是最准确的
# 公司
该公司标榜自己是一家“总部位于新加坡的 ***金融科技公司*** ,让人们能够掌控自己的财务未来”。我强调了“金融技术公司”部分,因为这是这家公司真正高度推销自己的地方,将这种“先进”的技术方法与传统的财务顾问形成对比。他们的使命声明继续解释说,他们使用“专有系统,在构建个性化解决方案时提供数据驱动的财富建议。”哇——对普通人来说,这一切听起来真的很酷,而且(用新加坡的俗语)很俗气。数据驱动的建议?专有系统?帮我报名吧,宝贝。
当你第一次在他们那里开户时,你可以选择设定一些财务目标。你投入你的初始投资,你的每月供款,以及你的风险承受能力(用最大提取百分比表示)。这就是令人印象深刻的数据奇迹发生的地方。在运行了一些**密集的**计算后,它吐出了一个预计的投资组合增长图(基于 ***1000 次*** 模拟;是的一千)。它看起来是这样的:

很漂亮不是吗?因此,这种所谓的数据驱动方法似乎向潜在投资者传达了这样的信息——嘿!我们使用一些尖端技术来管理您的资金,因此您可以信任我们。但是事情是这样的…真的有那么令人印象深刻吗?让我们找出答案。
# 问题
# 模拟的不准确性
首先,运行 1000 次模拟听起来很酷。我的意思是,如果我们尝试 1000 次,它肯定是准确的,对不对?但是让我们回顾一下,想想这意味着什么。运行 1000 次模拟以获得一系列可能性可以被认为是蒙特卡洛模拟**。这被定义为任何“当随机变量的干预存在时,用于预测不同结果的概率的模型”。本质上,它允许您使用重复采样来解释潜在的随机性。**
这真的是一个“先进”的概念吗?当然,这听起来和看起来令人印象深刻,但实际上很容易复制。因此,我创建了一个函数来估计回报,给定预期回报和标准差(这也是模拟的另一个关键问题,我们将在后面讨论)
创建函数后,我运行了一个循环,允许用户输入他们的初始投资、年回报率和标准偏差(根据公司的模拟)。
在我的模拟中,我使用了他们 60/40 投资组合的年回报率和标准差——这是一个保守但面向增长的策略。

how much is your initial investment? 10000
What is the yearly rate of return? 0.0771
What is the standard deviation of return 0.0870
How many years are you investing for? 30
How many times to simulate? 1000
在输入我的设置(遵循给定的回报率)后,我计算了投资组合的第 10 个百分点、中间值和第 75 个百分点(模仿公司模拟给出的结果)
The median return of the portfolio is 71657.24.
The 10th percentile is 38651.81 and the 75th percentile is 96055.78. The highest amount is 438889.69, and the lowest is 16925.8.

将我的结果与他们的进行比较(如下图),我必须说这是非常接近的。我的模拟超出了中位数约 7000 美元,但这很可能是因为我没有考虑费用等因素。前 25%的人也超出了大约 6000 美元,但后 10%的人非常相似,只有大约 2000 美元的差异。总的来说,我对这个结果很满意。

在这一点上,你可能会说,“扎克!看到了吗?太准了!这家公司有什么让人不喜欢的地方?”这让我想到了模特的问题。模型的输出完全取决于模型的输入。这似乎是显而易见的,但这正是这些花哨的萨满的问题,告诉你他们运行了 1000 次模拟。我可以运行 1,000,000 次模拟(事实上我确实这么做了),如果我的输入完全错误,它不会增加我的准确性一点。例如,我用不同的输入再次运行这个模型(并模拟 10,000 次)。

我运行这个模型 10,000 次会让它更精确吗?不要!如果我的输入是有缺陷的(在这种情况下,70%的年回报率),我的输出仍然是有缺陷的,不管我运行了多少次模拟。因此,这些东西看起来很好,很花哨,但它们不能成为“准确性”的标志,因为它们严重依赖于输入。这就引出了我的下一个观点…
# 历史回报+费用
作为一家公司,该公司自 2010 年代末才成立,因此预期回报率来自他们所投资基金的历史回报率。预计回报率,当用图表表示时,看起来像这样:

标准差为 8.7%,这意味着有 68%的机会(一个标准差),你的年回报率将在 6.9%和 8.4%之间。原则上,该公司不“选股”,而是通过买入股票和债券 ETFs 共同基金(并为智能再平衡收取管理费),帮助客户实现多元化。因此,预测的不是公司投资组合的历史回报,而是这些基金历史回报的合并(加权)!我们都知道使用历史回报的问题……正如 David Blanchett(晨星投资管理公司退休研究负责人)指出的那样,使用历史回报来衡量未来回报“隐含了历史事件的重复发生,并且只考虑了有限的数据”。此外,他认为,“蒙特卡洛工具的一个问题是,它们往往能描绘出一幅不切实际的回报图景”,给人一种确定性的假象,而实际上,“确定性要小得多”。
另一个影响回报的潜在因素是费用。我明白每一笔投资都要收费。毕竟,有人*要拿*的工资来维持公司运转。该公司将其 0.6%的费用(低于 20 万美元的投资组合)与行业平均水平约 2%进行了比较。虽然这个数字肯定更低,但我们必须再次记住,这家公司本身并不是一家投资公司。相反,他们将资金分配到基金中,而基金经理就是投资这些资金的人。这些基金*也*收取管理费(合计约 0.5%)。
# 结论
那么,这一切给我们留下了什么?我写这篇文章的意图并不是要败坏这家公司的名声,或者阻止任何人投资这种“数据驱动型”投资公司。相反,通过剖析该公司背后的“奇特”技术,我想提出两个关键点。
1. 首先,警惕漂亮的视觉效果和 *cheem* sounding 的东西。运行 1000 次模拟听起来真的很酷,但你必须记住,一个模型的预测输出只和它的输入一样准确。如果输出不准确,1000 或 100 万次模拟真的不会对模型的准确性产生太大影响。
2. 第二,历史回报不能为未来回报提供确定性。我们当然可以用历史回报来估计未来的回报,但我们需要记住,无论图表看起来有多好,都没有确定性。
所以,我没有责怪他们。该公司显然收取较低的费用,而且确实有健全的多样化战略等。但是,作为一个潜在的投资者,请注意,他们作为“优势”呈现的美丽的数据驱动模型是有局限性的。
*最初发表于*[https://zachlim98.github.io/me/](https://zachlim98.github.io/me/)*。*
# 一个幻想草案秩序彩票使用 R 闪亮
> 原文:<https://towardsdatascience.com/a-fantasy-draft-order-lottery-using-r-shiny-6668a5b275d2?source=collection_archive---------49----------------------->
## 作为 web 应用程序编写的 NBA 风格的彩票系统

迪伦·诺尔特在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上的照片
新冠肺炎影响了体育运动,进而影响了梦幻体育运动。然而,我们的梦幻足球联盟仍然准备好为一个不确定的赛季进行选秀。我们的联盟竞争激烈,为了确保没有人在第一次选秀权时出局,我们实施了 NBA 风格的抽签系统,让每个人都有机会获得梦寐以求的第一次选秀权。在本文中,我将解释如何为我们的梦幻联盟创建一个 web 应用程序来实现 NBA 风格的彩票系统。
## NBA 风格彩票(加权彩票)
NBA 在 1990 年采用了加权抽签系统,给战绩最差的球队最好的机会获得状元签。与 NBA 内的加权彩票系统相关联的赔率多年来一直在调整,以减少彩票中最佳球队的第一次整体选秀权的数量,并减少最差球队获得第一次整体选秀权的整体赔率,以防止故意失败。在我们的联盟中,第一次选秀权没有保证的威慑和最后一次选秀权的耻辱目前足以防止任何故意的失败。
## 我们的系统
2 的幂有一些美丽的东西,我们的系统以 2 的幂增加了赢得第一次选秀权的几率。联赛冠军只有一次机会(0.1%)赢得第一次选秀权。亚军有 2 次机会(0.2%)赢得第一次选秀权。第三名和第四名的赔率分别为 0.4% (4 次机会)和 0.8% (8 次机会)。你看到一种模式出现了吗?这种情况一直持续到我们联盟的最后一名,有 512 次机会或 50%的几率赢得第一次选秀权。
## 代码
当我们实现这个系统时,我们同时使用了 R 和 python,但是为了本文的目的,我们将只详细描述 R 版本。*** *注意:R 和 python 会有不同的结果,因为两者之间的随机数生成器不同。**** 为了实现我们的系统,我们创建了长度为 N 的联盟成员姓名列表,N(机会的数量)由他们的位置决定。
Create Member Lists of Length N by Finish Position
first <- "Mack"
second <- rep("Colin", 21)
third <- rep("Frank", 22)
...
last_place <- rep("Matt", 2**9)
为了简洁起见,上面的代码被截断了,但是,一旦我们有了不同大小的列表,我们就将列表名称汇集在一起并随机抽样。这就是设定种子发挥作用的地方,我们使用年份作为设定种子以获得可重复性。最后,在随机抽样之后,我们通过使用 unique 命令返回成员名称的第一次出现来返回选择顺序。
Establish set.seed
year <- 2020
set.seed(year)## Pool and randomly sample
pool <- c(first, second, third, fourth, fifth, sixth, seventh, eighth, ninth, last_place)sampled_pool <- sample(pool)## Get unique output
pick_selection_order <- unique(shuffled_pool)
## 让联盟中的每个人都可以使用它
为了增加程序的透明度,我们使用 [R Shiny](https://shiny.rstudio.com/) 创建了一个 web 应用程序。运行应用程序的代码可以在我的 [**GitHub**](https://github.com/glickmac/Fantasy_Draft_Order) 上找到。在本地运行应用程序需要闪亮的包。由于输入被列为选项,web 应用程序目前只适用于我们的联盟。为了使它对你的联盟来说是独一无二的(如果你有 10 名球员),只需在应用程序中的每个位置改变列表。
selectInput("last", h5("Select the Loser"),
choices = c("Mack", "Fish", "Todd", "Colin", "Andrew",
"Jake", "Frank", "Matt","Cody", "Jim"))
在[**Fantasy _ Draft _ Order**](https://glickman.shinyapps.io/Fantasy_Draft_Order/)**可以通过 [shinyapps.io](https://www.shinyapps.io/) 访问 web 应用。**下面是应用程序的截图。
[## 草稿订单生成器
我们梦幻联盟的梦幻选秀订购工具 glickman.shinyapps.io](https://glickman.shinyapps.io/Fantasy_Draft_Order/) 
马特是最后一名,以第三顺位结束比赛。坏运气和糟糕的幻想足球。
## 我们专员的智慧

敬我们英明的专员!
虽然该应用程序由专员运行并在联盟范围内得到验证,但有些人对他们的选秀位置(第二或第三)不满意,因为他们希望在我们的 snake 选秀格式中接近第 9 或第 10 顺位。专员改变了草稿选择生成器的目的,不是定义草稿中的位置,而是选择选择位置的顺序。例如,在上面的排序中,吉姆可以选择第一轮的第一个选择或其他任何地方。作为第二人选,我可以选择任何职位,除了那些已经被我上面的人选中的职位。在过去的 4 年里,这个系统已经被 10 个极具竞争力的梦幻足球运动员接受来组织我们的选秀位置。它具有随机性和可控性。
## 感谢阅读
一如既往地感谢您的阅读。我叫科迪·格利克曼,可以在 LinkedIn 上找到我。R Shiny 应用程序的代码可以在我的 [GitHub](https://github.com/glickmac/Fantasy_Draft_Order) 上找到。如果有赛季的话,祝你好运!
## 附加文章
[](/creating-photo-mosaics-using-python-49100e87efc) [## 使用 Python 创建照片镶嵌
### 一步一步的教程,让你自己的美丽的图像
towardsdatascience.com](/creating-photo-mosaics-using-python-49100e87efc) [](/dashing-through-christmas-songs-using-dash-and-sql-34ef2eb4d0cb) [## 使用 Dash 和 SQL 快速浏览圣诞歌曲
### 使用 SQL 数据库创建 Dash 仪表板的简单项目
towardsdatascience.com](/dashing-through-christmas-songs-using-dash-and-sql-34ef2eb4d0cb) [](/building-a-beautiful-static-webpage-using-github-f0f92c6e1f02) [## 使用 GitHub 创建漂亮的静态网页
### 查找模板和为静态网页创建表单的位置
towardsdatascience.com](/building-a-beautiful-static-webpage-using-github-f0f92c6e1f02)
# Python 中使用自然启发算法的快速超参数调整
> 原文:<https://towardsdatascience.com/a-faster-hyper-parameter-tuning-using-nature-inspired-algorithms-in-python-33a32eb34f54?source=collection_archive---------46----------------------->
## Bat 算法与网格搜索的性能比较
受自然启发的算法非常强大,通常用于解决 NP 难问题(如旅行推销员问题)或其他计算量大的任务。它们也被称为**优化算法。**受自然启发的算法试图找到问题的最佳解决方案,然而**并不保证会找到最佳解决方案**。
超参数调整通常使用网格搜索或随机搜索来完成。*网格搜索*的问题在于它非常昂贵,因为它尝试了所有可能的参数组合。*随机搜索*会尝试一定数量的随机参数组合。它不太可能找到参数的最佳组合,但是,它比网格搜索要快得多。

蝙蝠的**回声定位**是蝙蝠算法的基础部分(杨新社 2010)。照片由 [Igam Ogam](https://unsplash.com/@igamogam) 在 [Unsplash](https://unsplash.com/?utm_source=medium&utm_medium=referral) 上拍摄
接下来是**自然启发算法**。它们比网格搜索更快,并且有可能找到最佳解决方案——超参数的最佳组合。然而,算法与算法之间的结果会有所不同(有许多受自然启发的算法,例如:[蝙蝠算法](https://en.wikipedia.org/wiki/Bat_algorithm)、[萤火虫算法](https://en.wikipedia.org/wiki/Firefly_algorithm)……),这些算法也有自己的参数,这些参数控制它们如何搜索解决方案。如果您知道这些算法是如何工作的,您可能希望设置这些参数来改进搜索过程。
# 使用自然启发的算法开始超参数调谐
如果您在您的机器学习项目中使用 [Scikit-Learn](https://scikit-learn.org/) ,您可以使用一个名为 [**Sklearn 自然启发算法**](https://github.com/timzatko/Sklearn-Nature-Inspired-Algorithms) 的 python 库,它将允许您使用自然启发算法进行超参数调整。我们将在本教程中使用这个库,通过 pip 安装它。
pip install sklearn-nature-inspired-algorithms
假设我们想要优化我们的*随机森林分类器*的参数。
from sklearn.ensemble import RandomForestClassifierclf = RandomForestClassifier(random_state=42)
现在我们需要定义我们将尝试的参数集,用法类似于 scikit-learn 的 [GridSearchCV](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html) 。这组参数总共有 216 种不同的组合。
param_grid = {
'n_estimators': range(10, 80, 20),
'max_depth': [2, 4, 6, 8, 10, 20],
'min_samples_split': range(2, 8, 2),
'max_features': ["auto", "sqrt", "log2"]
}
此外,我们需要一个数据集。我们将使用 *make_classification 人工创建一个。*
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_classificationX, y = make_classification(n_samples=1000, n_features=10, class_sep=0.8, n_classes=2)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)print(f'train size - {len(X_train)}\ntest size - {len(X_test)}')
**现在我们可以使用自然启发的算法进行超参数调整。**我们正在使用 [Bat 算法](https://en.wikipedia.org/wiki/Bat_algorithm)进行优化。我们将训练 25 个个体的种群规模,如果算法在 10 代内找不到更好的解决方案,我们将停止该算法。我们将这样做 5 次,并将使用 5 倍交叉验证。*要了解关于 NatureInspiredSearchCV 参数的更多信息,请参考其* [*文档*](https://sklearn-nature-inspired-algorithms.readthedocs.io/en/stable/introduction/nature-inspired-search-cv.html) *,您也可以使用 Bat 算法之外的其他算法。*
from sklearn_nature_inspired_algorithms.model_selection import NatureInspiredSearchCVnia_search = NatureInspiredSearchCV(
clf,
param_grid,
cv=5,
verbose=1,
algorithm='ba',
population_size=25,
max_n_gen=100,
max_stagnating_gen=10,
runs=5,
scoring='f1_macro',
random_state=42,
)
nia_search.fit(X_train, y_train)
花费了一些时间,大约 1 分钟(GridSearch 大约需要 2 分钟,参数网格越大,差异越大)。现在,您可以用找到的最佳参数来拟合您的模型。最佳参数存储在*nia _ search . best _ params _*中。
from sklearn.metrics import classification_reportclf = RandomForestClassifier(**nia_search.best_params_, random_state=42)
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
print(classification_report(y_test, y_pred, digits=4))
现在,您已经使用受自然启发的算法选择的最佳参数成功训练了模型。这是完整的例子。
我还做了一个 *GridSearchCV* 和 NatureInspiredSearchCV 的比较(在本[笔记本](https://github.com/timzatko/Sklearn-Nature-Inspired-Algorithms/blob/master/examples/notebooks/hyper_parameter_tuning_nia_vs_grid_search.ipynb))。我使用了更大的数据集和更多的超参数(总共 1560 个组合)。*natureinspiredsearchv***找到了与 *GridSearchCV* 相同的解决方案**,并且**比**快了 4.5 倍!花了***GridSearchCV*2h 23 分 44 秒**找到了**最佳**方案,***natureinspiredsearchv*在 31 分 58 秒**找到了。
受自然启发的算法非常强大,在超参数调整方面优于网格搜索,因为它们能够更快地找到相同的解决方案(或非常接近)。在本教程中,我们使用 Bat 算法,其默认参数由 [Sklearn 自然启发的算法](https://github.com/timzatko/Sklearn-Nature-Inspired-Algorithms)库设置,但也有许多其他自然启发的算法可用于超参数调整。
# 改善数据展示的一些技巧
> 原文:<https://towardsdatascience.com/a-few-tips-to-improve-you-data-presentations-8a5fd6dc3853?source=collection_archive---------44----------------------->
## 7 个简单步骤的例子
在这篇文章中,我将展示一个如何改进结果图的例子。假设你致力于通过修改神经网络的稀疏性和丢弃的使用来改进某种神经网络(它显然可以是其他东西)。原始数据看起来像这样:

作者图片
在此图中,我们可以看到不同的颜色稀疏值、x 轴的 dropout 值和 y 轴的 accuracy 值。
## 步骤 1:通过删除值和使用百分比来修复轴标签
由于两个轴中的值太多,我们希望通过删除一些值并使用百分比来提高可读性:

作者图片
## 步骤 2:显示稀疏值,而不是使用图例
当查看不同的线条时,我们需要在图例和线条之间来回移动,以了解哪种颜色对应于哪种稀疏度值。这样做对读者来说心理上并不舒服,我们选择显示每行的稀疏值:

作者图片
## 第三步:使用连续的调色板
稀疏值实际上是连续的,但是当前的调色板不使用它。当不同的值是有序的时,默认颜色是很好的,但是在这个例子中,我们可以改进调色板。为了选择一个调色板,我使用了 chroma.js 调色板网站。我想要从蓝色到绿色的 5 种颜色。我选择了两种亮度大约为 50-60%的颜色,这样它在白色背景下是可读的(例如,而不是< 40%的亮度)。这些颜色不是完全色盲安全的(但仍然可以,因为亮度是不一样的),可以改进。

[chroma.js 调色板网站](https://vis4.net/palettes/#/5|s|0078cf,38a476|ffffe0,ff005e,93003a|1|1)

作者图片
现在更明显的是,不同的稀疏度/颜色是连续的,图形看起来更专业,因为初学者经常使用默认的调色板,专业人员使用他们自己的调色板(顺便说一下,我不是数据可视化专业人员)。
## 步骤 4:显示一个代表稀疏度的条形
我们有一个连续的调色板,它在“颜色空间”中是线性间隔的,但是稀疏值实际上根本不是均匀间隔的。很难想象我们正在处理的稀疏性的数量。为了澄清这一点,我们添加了一个表示稀疏度的线段:

作者图片
## 第五步:降低对比度,删除顶部和右边的部分
图形看起来有点奇怪,因为 x 轴对右边部分没有太大意义。我们删除 30%后的 x 轴,并删除没有实现任何东西的右边和顶部部分。我们还把黑色换成了不那么咄咄逼人的灰色。同样,它使图形更加专业。大多数专业人士使用深灰色而不是纯黑色。在 Medium 中,默认情况下,我写的文本是 84%不透明度的黑色,这使它成为深灰色。我们还把标题做得高一点,大一点,为几个字幕做准备。

作者图片
## 第六步:展示一些价值观
查看图表时,我们很想找到精度值,但很难读懂,因为我们只有 y 轴上的 4 个值来计算。此外,最有趣的值是 10%的下降值,这似乎是最佳下降值。所以我们把这些值加起来,写一个副标题解释一下(可选) :

作者图片
## 第七步:增加百分比来回答读者的问题
我们现在很想量化 10%压差精度对 0%压差设置的帮助有多大。为了帮助读者理解这一点,我们增加了这个百分比:

作者图片
我们完事了。
最终的 matplotlib 代码是:
## 结论
在这些步骤中,它们是几种类型的转换:
-清理:例如,当我们移除一些刻度标签时,我们试图使绘图更干净。当你在做演示时,寻找要删除的东西,而不是要添加的东西(在开始的时候)。
-预见读者的问题:试着设身处地为读者着想,你想了解数据中的哪些内容,但又很难了解?在我的例子中,我们需要添加一些数值和百分比
——视觉上很难理解的是什么?在我的例子中,不容易看出稀疏值不是均匀分布的。
# 获得你梦想中的远程数据科学工作的现场指南
> 原文:<https://towardsdatascience.com/a-field-guide-to-landing-your-dream-remote-data-science-job-84da4ec1c0a4?source=collection_archive---------29----------------------->
## 找到一份完全远程的数据科学工作并不是一件容易的事情,但是这些提示将帮助你实现这个目标。
最近,[维基·博伊基斯](https://twitter.com/vboykis),数据科学推特圈的标志性人物,[宣布](https://twitter.com/vboykis/status/1272492249071390724)她加入[automatic](https://automattic.com/)(Wordpress 背后的公司)成为一名机器学习工程师。
Automattic 是第一批完全分布式的公司之一,并已成为如何实现远程化的参考。事实上,它已经成为求职者梦寐以求的远程工作最明显、最有吸引力的目标之一。
虽然这听起来对 Vicky 和 Automattic 来说都是一个好消息,但对于寻找远程工作的候选人来说,这也可能会挫伤他们的积极性,因为这提醒他们,他们可能会与地球上最引人注目和最有才华的专业人士竞争。但是不要失去希望,找到一份远程工作还是有可能的。
以下建议主要基于我的个人经验(我已经在两份不同的工作上远程工作了 4 年多)以及与其他远程工作者的交谈。它还包括一个我得到目前工作的故事。

每篇远程工作文章都有一张强制性的热带海滩图片,这里就有一张。照片由[埃里佐·迪亚斯](https://unsplash.com/@elishavision?utm_source=medium&utm_medium=referral)在 [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral) 上拍摄
# 是的,竞争是艰难的
让我们不要设定不切实际的期望,找到一份完全远程的全职数据科学工作并不容易。如前所述,你将与这个星球上最合格的专业人士竞争,而且一年没有那么多的空缺。
不要因为每天在 Linkedin 上收到现场工作的邀请,就认为几个月后你会找到工作,就马上辞职。你应该设定一个现实的期望,并把它视为一个长期的项目,其中包含了大量的奉献和失望。
希望事情会变得更容易,因为许多知名公司如 Twitter,Shopify 或 Slack 宣布,即使在 Covid 危机结束后,他们也将完全或部分远程化。
# 从…你目前的工作开始
你会在任何地方读到:**远程工作都与信任有关**,例如,相信你会在没有密切监督的情况下完成任务。利用你与时间建立的关系应该是你的第一步,没有比现在的工作更好的起点了。
如果您的经理对您很满意,并且您的公司没有明确的反远程工作政策,您应该开始讨论。
2016 年,我的妻子得到了一个 500 公里外的工作机会,我们认为这是一个与家人一起生活在一个更小更平静的城市的机会。接下来的问题是如何处理我的工作。她漫不经心地提到“你可以要求在家工作”,我觉得自己很愚蠢,以前甚至没有考虑过这个问题。不久之后,我开始和我的经理交谈,说我想在不久的将来开始远程工作,最好的办法是仍然和他们一起工作。一个月后,我离开了巴塞罗那,开始远程工作,不需要寻找新的工作(但转到了一个不同的团队)。
这并不总是可能的,即使在同一个公司里,这在很大程度上取决于你在和谁交谈。就我而言,如果换一个经理,这可能是不可能的。但可以肯定的是,如果你不问,肯定不会发生。
# 使用你的网络
寻找已经信任你的人的第二个好地方是你的关系网。很可能有一些你过去共事过的人欣赏你的专业素养,他们现在在不同的公司工作,很乐意再次与你共事。
联系他们吧。在 LinkedIn 上给他们发一条信息,询问他们的近况,祝贺他们最近的相关变动,并随意提及你正在寻找新的机会——理想情况下,这将允许全职远程工作。因为你有私人关系,他们会给你一个诚实的答案,甚至可能接触不同的人(可能在不同的公司)来询问潜在的机会。
# 询问招聘人员
如果你在 LinkedIn 上有一个数据科学家的头衔,你可能会通过 LinkedIn 定期收到邀请。
利用这些机会与招聘人员联系,询问工作是否可以完全远程化。在 99%的情况下,情况可能并非如此(根据我的经验,尽管这可能会在 Covid 之后发生变化),但这也是一种非常省力的方法,因为您只需快速回复收到的消息。
招聘人员会感谢你回答他们(他们并不都是坏人!)可能会考虑让你去做他们正在做的另一份工作,而且是远程友好型的。
# 在你的申请中投入额外的爱
请记住,远程职位竞争激烈,公司可能会收到[千份申请](https://twitter.com/amix3k/status/936233634322960385)一个空缺职位。不用说,你应该确保你发送了一个顶级的申请脱颖而出。
* 根据职位定制你的简历。这可以适用于任何求职,但当你与成千上万的其他候选人竞争时,你必须确保你的简历反映出你有多适合这个职位。
* 破解你的求职信或演示邮件。远程工作需要很强的沟通技巧。如果你不能用几段话来表达为什么目标公司应该考虑你作为候选人,这会破坏你的申请。
* 找到如何连接。找出你在公司的对话者可能是谁,他们喜欢什么。招聘经理可能活跃在社交网络上,写了一些文章或书……研究他们是谁,他们的文化背景,他们的成就,这样你就有更好的机会了解如何最好地抓住他们的注意力。
# 使用正确的工具
虽然,人们可能首先会认为寻找现场或远程工作没有区别,但有一些方法可以改善你的远程求职:
* 使用正确的过滤器。像 [StackOverflow](https://stackoverflow.com/jobs) 这样的网站可以选择只显示远程工作。
* 跟随正确的公司。这里有远程招聘公司的[名单](https://remotive.io/remote-companies),还有一些非常显眼的名单,比如[自动招聘](https://automattic.com/)、[缓冲招聘](https://buffer.com/)、[扎皮尔](https://zapier.com/)、 [Hotjar](https://www.hotjar.com/) 、……留意他们的工作页面,以防有新的职位空缺。
* 看看初创企业。初创企业更有可能采用新的工作方式,因为它们从零开始建立自己的工作文化(而且租赁办公室的资金更少)。像 AngelList 这样的网站提供了大量的创业工作,有些完全是远程的。
* 看看专门的董事会和社区。有大量专门从事远程空缺职位的工作委员会或社区(例如[remove](https://remotive.io/)、 [RemoteOK](https://remoteok.io/) 、…)。密切关注他们,并设置你的提醒,尽管数据科学的工作机会不如开发人员那么频繁。
# 做自由职业者
如果你的申请运气不好,你仍然可以考虑做自由职业者。由于自由职业者通常是经验丰富的专业人士,与公司的合作时间较短,所以他们通常更愿意让自由职业者远程工作。
自由职业者的生活当然不适合每个人,找到一份远程自由职业者的工作也不一定更容易。你仍然可以通过在 UpWork(或更专业的本地网站)等平台上创建个人资料来测试这些理由,看看获得一些体面的第一份工作有多容易(或多难)。
# 有创造力
虽然有些人会假装如此,但找工作并没有金科玉律。一些通常对其他人有效的方法可能对你无效,反之亦然。因此,如果你足够幸运得到一些反馈,建议你尝试不同的方法并从中学习(我们仍然可以说,得到 ghosted 是反馈的最小单位)。
如果你能找到招聘经理,试着直接联系他们,发送没有列出的工作申请(公司可能会给你回复),如果这是你唯一的选择,通过公司的在线表格申请,尽管每个人都会告诉你这永远不会成功(有时会这样,我通过这种方式获得了多次面试和一份工作),总的来说,试着找到与打电话的人联系的最佳方式。
举个例子,我在不和谐中得到现在的工作… *!对于一份我大材小用的工作。*
我对一家年轻的初创公司感兴趣,该公司正在寻找一名数据分析师,而我正在寻找一个更高级的职位,最好是主管/总监级别的职位。经过一些研究,我意识到他们还没有任何数据科学家,他们可以使用更有资历的人。此外,他们有一个链接到他们的 Discord 服务器(他们在游戏领域运营),在那里我可以直接联系首席执行官,并介绍自己是一名数据主管。几通电话后,我被录用了。
像任何类型的方法一样,这肯定不是每次都有效的方法。但这表明,如果你足够坚持,花足够的精力去了解你的目标公司,他们将需要什么,以及如何获得他们的关注,你最终会脱颖而出。
# 坚持不懈
最后,记住你只控制招聘过程的一小部分。即使你发出了最好的申请,并且非常适合这个职位,也有很多因素是你无法控制的:你的竞争对手、与招聘者的个性匹配、公司战略的变化、适合这个职位的预算、时间安排等等
求职是一个数字游戏,对于远程工作更是如此。你可能不会在第一次申请时就得到一份工作,但也许你会得到!只要确保使用本文中强调的各种方法,并在每个应用程序上尽最大努力,以增加成功的几率,并获得梦想中的数据科学远程工作。
# 一个用于 quants 的金融神经网络
> 原文:<https://towardsdatascience.com/a-financial-neural-network-for-quants-45ec0aaef73c?source=collection_archive---------37----------------------->
## 阿尔法-贝塔分类器
## 背景
从我们应该观看的 YouTube 视频的建议,到运行我们在华尔街的高频交易的算法,人工智能(AI)正在不断成为我们今天所做的不可或缺的一部分。事实上,谷歌算法知道我们更喜欢什么,而不是我们想要什么。这是 Twitter 首席执行官兼创始人杰克·多西的说法。如果不是模式识别和分类,这不会被提及,而模式识别和分类是人工智能的主要基本原则。

图 1 人形机器人的图像。图片来源: [Franck V.](https://unsplash.com/@franckinjapan?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 在 [Unsplash](https://unsplash.com/s/photos/artificial-neural-network?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) 上的照片
尽管几个世纪以来,这两个原则完全是通过传统的统计推断和数学来实现的,但我们(作为一个文明)花了一段时间才认识到这些过程还不够好,相反,它们可能难以置信地难以解决,至少可以说是笨拙和耗时的。人工神经网络构成了人工智能的核心,因为它们是用来成功模仿不必要的自愿行为的主要实体,但在许多情况下,显然是正确的决定。这里我们指的是自动驾驶汽车、语音和面部识别、物体跟踪,甚至人形机器人。
因此,有许多类型的神经网络已经被用于各种目的。例如:前馈神经网络、径向基函数神经网络、递归神经网络、卷积神经网络、模块化神经网络和 Kohonen 自组织神经网络。作为 Teuvo Kohonen 教授,后一种观点对我来说尤其珍贵——自从我开始了解神经网络及其功能以来,它的支持者恰好是我最大的鼓舞人心的人物之一。我关于神经网络的第一个项目是关于风速和风向的预测,作为在芬兰不同城市建立风力农场的可行性研究的一部分。尽管这个概念很先进,但在这篇参考文献中讨论了非常基础的内容,例如神经网络的类型以及哪种网络适合什么问题。然而,本文不是关于神经网络的类型,而是如标题所示的一种特殊的神经网络— *金融神经网络*。你会注意到它没有出现在上面列出的神经网络类型中,并且可能目前根本不会出现在其他地方。这是我们在相对较新的人工智能领域遇到的模式之一。
## 为 quants 引入α-β分类器
想象一下这个场景,假设皇家邮轮泰坦尼克号(1912 年 4 月)的幸存者可以被预先决定和预言?这意味着你必须假设你已经知道事故会发生——这有点令人毛骨悚然。让我们把它变得更有趣,如果男人,女人和孩子的数量可以被告诉一部分,并根据他们将承受的伤害进行分类,只是根据他们在游轮上的位置。这是一个不幸的事件——让我们考虑一下资产交易。
以类似的方式,假设你将要购买的资产,比如股票、期货、债券,甚至是加密货币,已经可以预先确定,这样你就可以知道哪些交易会盈利,哪些不会,甚至在你进入这些交易之前。你会更明智地知道该交易什么,对吗?这就是 *alpha-beta* 金融神经网络的意义所在。有了这种类型的神经网络,你可以尝试对你将要进入的交易进行分类,并确定它是否有利可图,是否值得参与的概率。这些决定通常决定了你策略中的“买入”和“卖出”信号,特别是在你为算法交易编写代码的时候。

图:2 图片来源:[克里斯·利维拉尼](https://unsplash.com/@chrisliverani?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)在 [Unsplash](https://unsplash.com/s/photos/trading?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
## 阿尔法-贝塔分类器的数学
这类神经网络是一个分类器,其输入是当前最高收盘比率、“高”和“开”比率的比率,作为单个输入,偏差为-1。这些通过逻辑激活函数传递,该函数将输入缩放到 0 和 1 之间的概率分布函数。要对此进行说明:

图 3:作者对 ABC 神经网络的说明
设高为 **z** ,开为 **x** ,权重为 **w** :

情商。(1)
符号 *β* 是偏差,在这种情况下是负常数-1。激活函数 *α* 是权重的函数,权重在开始时被初始化,并随着分类的进行而被估计。梯度下降是模型性能效率的最终衡量标准。最小化梯度相当于增加概率分布函数的值,在这个过程中我们得到如下结果:

图 4:α-β分类器的激活函数

情商。(2)
## 实用指南
如果你真的想在编写下一个交易算法的时候考虑使用这种技术,遵循这种方法总是可行的。我们将首先列出帮助您完成这项任务的要求:
* 首先,您需要熟悉在 python 中使用数据框。
* 接下来,您需要在系统上安装 python3.6。你还需要有熊猫和 numpy 基础。
* 最后,这不是必须的,但安装 jupyter notebook 或 ipython 将在很大程度上减轻您的工作。
## 数据采集
我们将利用标准的资产信息,以表格的形式呈现,列有:“日期”、“开盘”、“高”、“低”、“收盘”、“调整收盘”、“成交量”。你可以从雅虎财经网站下载到你的项目文件夹中。在本案例研究中,我们将使用股票代号“AAPL”和“谷歌”,分别对应于 Aple inc .和 Google Inc .的历史股票数据。这将有效地将数据下载到您的项目中。
## 导入库
首先,导航到您的项目文件夹。当您可以在命令提示符或 Unix 终端上工作时,这(更确切地说是整个项目)是最好的。为此,我将假设 Linux 终端。因此,请确保您已经安装了所有必需的软件,并运行以下命令开始安装:
$ cd /your/project/root/directory/
$ jupyter notebook
上面的代码应该会在您的浏览器中弹出一个文本编辑器窗口,类似于下面这个:

图 Jupyter 笔记本项目文件夹的外观
单击红圈区域创建一个新文档,我们将在其中放置代码。然后,我们将继续导入前面提到的库。这些是:熊猫,熊猫和时间如下:
import libraries
import pandas as pd
import numpy as np
import time
Read in the data from the downloaded csv file(s) into a data frame
df = pd.read_csv('AAPL.csv')
## 检查数据和预处理
要检出导入到您的工作区的数据,请键入以下内容并运行单元格—单击图 2 中的红色矩形选择:

图 6:在 Jupyter 笔记本中执行命令
这将导致类似这样的结果:

图 7:用命令 df.head()检查熊猫数据帧的内容
为了简化代码,我们希望更改列名的大小写。因此,我们通过运行以下代码来替换现有的:
df.columns = ['date', 'open', 'high', 'low', 'close', 'adjclose', 'volume']
你可以在这里做很多练习,例如,你可以只过滤掉你希望进入的积极交易(pos)——也就是说,如果你当时进入,就会产生利润的交易。为此,只需键入以下代码:
pos = df[df['change'] > 0 ]
你可以对那些最终产生负收益或亏损的交易做同样的事情。你可能希望不要参与这些交易,或者只参与买入——用它们创造一个买入信号。然后你可以输入:
neg = df[df['change']< 0 ]
## 填充指标
这个分类器使用有史以来最简单的指标。这些是:
* 关闭率与打开率之比,将作为神经网络的输入,以及
* 我们也将计算我们将用作指导的变化,更像控制实验。因此,相应的代码放置如下:
df['change'] = df['close'] - df['open']
df['ind'] = (df['high']/df['open']) -1
df.head()
上面的代码将创建两个额外的列,一个是我们讨论过的比率——我们称之为“ind ”,另一个简单地称之为“change ”,就像我们一直知道的那样。请注意,变量“ind”已经是等式 2 的 LHS 的镜像。(1).现在,我们将在以下几节中继续计算 RHS。
## 权重初始化
我们将从使用 numpy 库分配一组线性权重开始,如下所示:
w = np.linspace(-6,6,len(df))
上述代码将定义一组线性参数,这些参数将用于计算概率分布函数——或等式中的激活函数。(2).Alpha 的计算方法如下:
alpha = 1/(1+np.exp(-w))
## 评估算法
我们完了。现在,我们需要在数据框中实现实际的方程并检查结果。用最简单的话来说,你将为你从上面计算的每个 alpha 值输入下面的内容。
test = df[df['ind'] >= alpha]
eval = test[test['change'] > 0 ]
## 总结一下
我们已经看到,it 资产交易与其他存在预测理论方法的现象没有什么不同。因此,资产交易可以根据它们的潜力来分类——更确切地说,交易本身可以以决定是否进入为唯一目的来分类。关键参数是预期的盈利状态。以下代码总结了上述所有步骤:
import pandas as pd
import numpy as np
import time
from termcolor import colored# Read in the data from the csv file
df = pd.read_csv('AAPL.csv')# Reduce the column names to lower case
df.columns = ['date', 'open', 'high', 'low', 'close', 'adjclose', 'volume']# compute the change to use as a guide in backtesting
df['change'] = df['close'] - df['open']# populate the classifier
df['ind'] = (df['high']/df['open']) -1# Initialize the weights
param = np.linspace(-6,6,len(df))# Fire the neural network
eta = 0
while eta < 100:
for i in param:
alpha = 1/(1+np.exp(-i))
test = df[df['ind'] >= alpha]
if len(test) > 0:
pos = test[test['change'] > 0]
eta = len(pos)*100/len(test)
#time.sleep(1)
print(colored (i, 'green'), alpha, len(test), colored(eta, 'red'))
else:
pass
else:
print('done classifying')
一旦你确定了进入交易的概率或阿尔法的最小值,买入和卖出信号可以简单地写成:
dataframe[dataframe['ind'] < min_alpha ] ----> buy
dataframe[dataframe['ind'] >= min_alpha ] ---> sell
## 主要结果
生成的表格是上面打印到屏幕上的(较长的)代码的标准输出。看看这个场景:
让我们假设你选定的最终权重 **w** 是“-4.23”,激活函数 *α* 将产生“0.0143”,因此概率是 0.90566——如图 8 所示。如表中所示,首先有三列:权重,第二列:alpha 值,第三列是模型的效率,最后是输入的交易数量。
这意味着如果你进入了这个交易,有 90.6%的机会你会盈利,相反,有 9.4%的机会你会亏损。至于如何计算这个百分比,我们简单地计算“评估”数据帧中变量“变化”大于零的数据帧的长度,并与“测试”数据帧的总长度进行比较。

图 8:指导性案例研究代码的标准输出
## 关于利弊和从哪里获得帮助的说明
**优点**
* Alpha-Beta 分类器相当准确——至少从回溯测试结果来看是如此。
* 理论上可以保证高达 100%的分类效率。
* 然而,最好的特点是,模型效率越高,意味着交易越少,不仅回报越高,而且亏损的机会也越少。因此,这个特征就像某种止损。这意味着你可以选择进入少数几个交易,但盈利潜力很大。另一方面,你可能选择进入许多行业,每一个都没什么好处。这将帮助你分散风险,而不是集中在一个地方。
* 最后,阿尔法-贝塔分类器支持不重复自己(干)。一个模型可能适合多种情况。例如,下载 Google Inc .的历史数据(保存为 GOOG.csv ),在其他一切保持不变的情况下,您应该会发现该模型仍然有效——有时甚至更好。
**缺点**
* 然而,一个主要的挫折是,模型效率越高,你的交易次数就越少。
**F1 #帮助**
这是一个新的概念,可能会被证明是有帮助的,特别是对于那些喜欢试验和建立在它之上的定量分析师。如果你是这样的人,以此为起点,需要帮助,请告诉我,我会尽可能给予支持。
## 参考
[1]n . k .罗蒂奇、j .拜克曼、l .林南宁和丹尼尔,2014 年。基于神经网络的风资源评估和预测规划。*《能源、水与环境系统可持续发展杂志*, *2* (2),第 174–190 页。
# 用视觉故事讲述财政状况
> 原文:<https://towardsdatascience.com/a-fiscal-state-of-the-union-with-visual-storytelling-bf58896659c8?source=collection_archive---------29----------------------->
## 可视化 2021 财年美国政府预算和当前财政状况
你有没有想过你的税金去了哪里?政府如何赚钱?
最近,特朗普总统发布了 2021 财年政府预算。随着民主党人抨击大规模支出和国防预算是不负责任和不可持续的,共和党人称赞预算是经济刺激,政治接管了。
真实的故事是什么?数据怎么说?钱是从哪里来的,去了哪里?美国的财政状况如何?
使用[这个仪表板](https://public.tableau.com/profile/jordan8097#!/vizhome/USGovernmentFY21BudgetandFiscalState/GovtFiscalState)与您自己的数据进行交互,并继续阅读了解更多详情。

[仪表盘](https://public.tableau.com/profile/jordan8097#!/vizhome/USGovernmentFY21BudgetandFiscalState/GovtFiscalState)截图
# **收入和成本**

2021 财年,政府预计预算赤字为 5890 亿美元,预计支出为 44.5 亿美元,收入为 38.6 亿美元。
换句话说,政府每收到 1 美元,就要支出 1.15 美元;每 1 美元收入中的 75 美分已经通过强制性项目支出。
赤字并不是本届政府独有的现象——自 1980 年以来,只有 4 年政府收入超过支出,并且在最近的 2007 年至 2009 年经济衰退期间赤字达到顶峰(下图中的阴影部分)。

政府支出和收入占国内生产总值的百分比;阴影区域是 2007 年至 2009 年的衰退。[来源](https://fred.stlouisfed.org/series/FYFRGDA188S)。
在政府约 44.5 亿美元的支出中,约 66%被分配给指定为“强制性”的项目,主要包括医疗保险和医疗补助(卫生与人类服务部/ HHS)以及社会保障。[访问仪表盘](https://public.tableau.com/profile/jordan8097#!/vizhome/USGovernmentFY21BudgetandFiscalState/GovtFiscalState)并将鼠标悬停在树形图中的每个框上,查看更多消费详情。

强制性联邦支出
在可自由支配的支出中,约 40%(约 6400 亿美元)用于国防,其次是退伍军人事务(约 1050 亿美元)、HHS(约 960 亿美元)和教育(约 660 亿美元)。

自由支配的联邦支出
过渡到收入,个人所得税占政府预期收入的约 50%,其次是社会保险税(~35%)和企业所得税(~7%)。

预计政府收入,2011 财年
收入赶不上支出的一个潜在原因是,过去 30 年来,主要的收入驱动因素——个人所得税——在家庭收入中所占的比例一直在下降,特朗普总统最近的减税政策导致这一比例显著下降。

平均值。按收入百分比计算的联邦税率。[来源](https://www.taxpolicycenter.org/statistics/historical-average-federal-tax-rates-all-households)
此外,第三大收入来源——公司税大幅下降。自 2000 年以来,有效公司税率的一个衡量标准——利润税——已经下降了 66%以上。

隐含的公司所得税是通过公司税前和税后利润之间的差额计算的。[源 1](https://fred.stlouisfed.org/series/A053RC1Q027SBEA) 和[源 2](https://fred.stlouisfed.org/series/CP) 。
总的来说,政府三个主要收入来源中的两个正以较低的税率征收。这意味着,企业利润或家庭收入的任何增长(如果存在的话)中,至少有一部分会流入政府,被税率的下降所抵消。
# 债务和赤字
因此,如果支出持续超过收入,那么政府就会出现年度赤字,导致债务增加。
作为一个快速入门,赤字是政府在某一年的收入和支出之间的差额;债务是政府借出和欠贷方的累计金额。
几十年来,政府一直在增加国债的绝对值和相对值(相对于 GDP)。最近的数据显示国家债务超过 25 万亿美元——相当于财富 500 强公司总收入的两倍——超过 GDP 的 106%。

1920 年以来的国债和债务与 GDP 的比率
历史上,债务与 GDP 之比一直是衡量一个国家借贷的标准,100%左右是债务过多的“门槛”。
然而,我认为 GDP 不是正确的判断标准,至少对美国来说是这样。如前所示,财政收入约占 GDP 的 16%。这意味着将每一美元的收入用于偿还债务需要超过 6.5 年的时间,更不用说 1)这是不可能的,2)政府每年都有赤字。
很难想象,如果没有巨大的变化,这笔钱如何能够全部收回。
另一个新出现的担忧是外国政府持有的美国债务越来越多。数据显示,这一群体代表了当前债务持有人的最大部分,自衰退以来显著增加。

按所有者类型划分的公共债务。[来源](https://www.sifma.org/resources/research/us-treasury-securities-holders/)
美国政府很幸运,利率处于历史低点,否则债务问题将(并且有一天,可能或将要)给国家带来更大的负担。
那么,美国的财政状况如何?数据显示不太好。
支出超过收入,没有一位总统一直找到扭转这一趋势的方法。长期指标同样没有带来积极的结果。当前的税收——尽管我们都不希望它们变得更高——无法维持政府的支出速度。
国债从来都是“改天的问题”。虽然政府的信用评级仍然很高,但人们相信可以借新钱来偿还到期债务。“另一天”将会到来,要么全额账单到期,要么信心丧失。
我鼓励你[查看仪表盘](https://public.tableau.com/profile/jordan8097#!/vizhome/USGovernmentFY21BudgetandFiscalState/GovtFiscalState),了解政府支出、收入和财政健康的更多细节。我很想听听您对这种情况的看法,以及您认为与讨论相关的任何其他数据。
# 一个推荐图片的 Flask 应用程序
> 原文:<https://towardsdatascience.com/a-flask-app-for-image-recommendations-a865e1496a0d?source=collection_archive---------13----------------------->
## PyTorch 中基于卷积神经网络的相似图像推荐网站的实现

图片库和对所选图片的推荐(来源:M. D. Korzec)
在创建了一个基于 Python 的机器学习应用程序后,你可能想让它在网站上运行。
在这篇文章中,解释了如何通过基于图像的推荐系统的微框架 Flask 来实现这一点。
我们在一个网站上实现了一个图像库,可以选择图像,并显示相似的图像。这种解决方案可以用于例如在线商店。
如前一篇文章所述,相似性是通过比较由预训练的 Resnet18 网络[导出的特征向量获得的。这项工作的结果是熊猫数据帧(本质上是表格),其中包含最相似图像的名称,以及每幅图像的相似值在 0(不相似)和 1(最相似)之间。这些在这里储存和使用。](/recommending-similar-images-using-pytorch-da019282770c)
在下一张图中,( a)概述了理论和实施的步骤。本文主要讨论(b)部分,其中的数据框架已经离线计算,可以在网站上使用。

[相似度矩阵计算(a](/recommending-similar-images-using-pytorch-da019282770c?source=your_stories_page---------------------------) )和排序后的推荐前 k 列表(b)。在本文中,Flask 用于为一个网站使用结果(来源:M. D. Korzec, [Flask 标识,作者阿明·罗纳彻](http://flask.pocoo.org/static/logo/flask.svg),版权所有[免费使用](https://commons.wikimedia.org/w/index.php?curid=19501815)
我们将了解如何
* 安装 Flask 并在调试服务器上本地运行应用程序
* 定义所需的路径-用于图库和建议的 URL
* 将所需的信息从用户输入传输到后端,并将建议返回给用户
* 实现一个建议相似图像的 html/JavaScript 库
* 基于我的前两篇文章创建 pickle 文件([理论](/effortlessly-recommending-similar-images-b65aff6aabfb)、[实现](/recommending-similar-images-using-pytorch-da019282770c?source=your_stories_page---------------------------)与 [Jupyter 笔记本](https://github.com/MathMagicx/JupyterNotebooks/tree/master/ImageRecommenderResnet18))。将它们用于定义推荐图像的 top-k 列表。
更新:在我的后续文章中,您可以找到所介绍方法的扩展。它解释了使用 PostgreSQL 数据库的所有相关代码、合适的打包,并包含了部署到 Heroku 的分步描述。代码链接在帖子里,演示者可以在这里联系到[。](http://image-recommender-demo.herokuapp.com/)
# 1.瓶

标志由[阿明·罗纳彻](http://flask.pocoo.org/static/logo/flask.svg)制作,版权所有[免费使用](https://commons.wikimedia.org/w/index.php?curid=19501815)
Flask 是一个非常流行的用 Python 编写的微框架。它被称为“微型”,因为它没有完整的功能集、数据库的抽象层、用户管理或类似的功能,但它可以通过覆盖所有需求的可用库进行扩展。
与像 [Django](https://docs.djangoproject.com/) 这样功能丰富的框架相比,这听起来可能是一个缺点,但是,它也降低了复杂性,给用户留下了更多的选择,并允许对应用程序进行更好的概述。
你*可以*轻松完成的事情:在后端使用你的 python 代码,将结果传递给前端,你可以用 html、JavaScript 和 css 编写结果——你也可以使用 Vue.js 这样的前端框架。
Flask 提供了基于 Jinja2 语法的模板使用,简化了网页的可重用性和动态创建。
如果你打算第一次玩 Flask,我推荐你看一些科里·斯查费的教程,他创作了一个简洁的 Flask 系列,可以让你很快上手。
第一步如何运行 Flask(在 Windows 上)?创建合适的虚拟环境后,安装它,例如使用 pip
pip install Flask
并导入它以使所有代码可用于构建 Flask web 应用程序
from flask import Flask
要运行本地调试 web 服务器,可以使用包含主 Python 文件的批处理文件
set FLASK_DEBUG=1
set FLASK_APP=recommenderFlask.py
flask run
FLASK_APP 只是设置应用文件。然后你可以通过
[http://localhost:5000/](http://localhost:5000/)
设置 FLASK_DEBUG 会导致调试信息直接显示在浏览器中。
印出“你好,世界!python 文件应该是这样的
from flask import Flaskapp = Flask(name)
@app.route(‘/’)
def hello_world():
return ‘Hello, World!’
对于本文,我使用 Flask 版本 1.1.1 和 Python 版本 3.5.4。
# **2。路线**
让我们设置应用程序的主文件,recommendFlask.py
**from flask import Flask
app = Flask(name)****@app.route(“/”)
@app.route(“/home”)
Need to write a function that is called when opening the site****@app.route(“/recommend”)
Need to write a function that is called when opening recommendations****if name == ‘main’:
app.run(debug=True)**
* 我们导入 Flask 类来创建 Flask web 应用程序。
* 创建 Flask 实例应用程序,如果直接调用脚本,它将在最后一行运行,因为 Python 设置了 **__name__ == '__main__ '。**如果*推荐的 flash . py*是从另一个脚本导入的,情况就不一样了。将 debug 设置为 true 的好处是,您可以在网站本身的开发过程中看到错误。
* 在这两者之间是还没有做任何事情的家庭和推荐路线。它们将触发在下一节中编写和解释的相应功能。我们将通过 **localhost:5000/home/或 localhost:5000/,**到达包含图库的主页,而推荐将显示在**localhost:5000/recommend/**上
让我们创建一个图像库。
# **3。画廊**
我们将把位于一个文件夹中的感兴趣的图像名称放入位于 recommenderFlask.py 文件顶部的虚拟数组中。
images = [
{
‘name’:’buildings0.jpg’,
‘caption’: ‘Lisboa’
},
{
‘name’: ‘buildings1.png’,
…
我们使用这些数据来创建画廊。对于一个生产系统,这一部分需要移动到数据库中——这将是后续文章的一部分。
使用一个函数调用 home route,该函数根据与图像相关的可变内容呈现 html 页面。
因此,添加用于 html 呈现的库
from flask import render_template
并用图像数组调用画廊创建
@app.route(“/home”)
def home():
return render_template(‘home.html’, images = images)
**home.htm**l 是一个放入 Flask template 文件夹中的模板,该文件夹允许在 div 块中迭代图像。
Flask 允许使用传递的变量,例如使用 for 循环和花括号中的变量,如下所示
{% for image in images %}
在模板中,您可以添加 css 和脚本来使图库工作。对于图库中的分页,我添加了一个位于静态文件夹中的脚本(由 Flask 默认配置)。
<script src=”{{ url_for(‘static’, filename=’js/pagination.js’) }}”></script>
总的来说,您可以创建自己喜欢的方法和风格来显示和迭代图像。
图片库(来源:M. D. Korzec)
对于测试和上述网站,我使用 GitHub 存储库中提供的图像进行 top-k 列表计算。由于 21 幅图像中的几个不同类别,它有助于测试所提供的建议。
当点击其中一个图像时
<a href=”{{ url_for(‘recommend’, selectedImage=’’) }}{{image.name }}”>
到推荐路线进场。我们希望生成一个新的 html 页面,显示与所选内容最相似的图像。
4。推荐人
我们刚刚看到,触发图像会将变量 selectedImage 设置为图像数组中图像的名称,并调用推荐路线。点击图像时,您可以在 URL 中看到它(例如,点击集合中的 camper2.jpg)
让我们在应用程序文件中使用这个变量。
from flask import request@app.route(“/recommend”)
def recommend():
selectedImage = request.args.get(‘selectedImage’)
inputImage, images, values = getImages(selectedImage)
return render_template(‘recommend.html’, title=’Recommendations’, customstyle=’recommend.css’, inputImage=inputImage, similarImages=images, similarityValues = values)
请求变量后会发生什么:
- getImages 函数向输入返回相似图像的数组
- 从模板【recommend.html 的 ,基于输入和与输入相关的相似图像,生成一个 html 站点。自定义样式用于 html 页面。
在模板中,根据相应的变量输入图像显示原始图像
<div class=”originalImage”>
<h3> Input image</h3>
<img src=”{{ url_for(‘static’, filename=’site_imgs/images/’) }}{{inputImage}}” alt=”{{inputImage}}” id=”showSimilarInPopup”>
</div>
并且基于相似图像数组列出相似图像
<div class=”galleryContent”>
<h3> Similar images</h3>
{% for image in similarImages %}
<div class=”item”>
<img id=”popupImage{{loop.index}}” onclick=”imageClicked(this.id)” src=”{{ url_for(‘static’, filename=’site_imgs/images/’) }}{{image}}” alt=”{{image}}” id=”showSimilarInPopup”>
</div>
{% endfor %}
</div>
这就是核心烧瓶元素。所做的一切都是为了让网站更好,让画廊更实用。
最后要讨论的是上面的 getImages 函数。
5。使用前 k 列表
当比较从不同图像的卷积神经网络的评估导出的特征向量时,创建 top-k 列表(对于每个图像,记录来自图像集的 k 个最相似的图像)。
参考上一篇文章中介绍的实现(Jupyter 笔记本可以在 GitHub 上找到,包括示例图片),我们将已经从该笔记本中导出的熊猫数据帧 similarNames 和 similarValues 存储为 Pickle 文件,包含相似的名称和相应的相似值
**import pickle
similarNames.to_pickle("similarNames.pkl")
similarValues.to_pickle("similarValues.pkl")**
在网站上,这些可以被视为静态内容,加载并用于提供最相似的图像,但对于画廊,数据库应该在生产中完成这项工作。
下面的代码片段用于返回指定数量( recLength )的最相似图像和相似性值。
import pickle
import os
import sys
from numpy.testing import assert_almost_equalglobal recLength
recLength = 3def getNames(inputName, similarNames, similarValues):
images = list(similarNames.loc[inputName, :])
values = list(similarValues.loc[inputName, :])
if inputName in images:
assert_almost_equal(max(values), 1, decimal = 5)
images.remove(inputName)
values.remove(max(values))
return inputName, images[0:recLength], values[0:recLength]def getImages(inputImage):
similarNames = pickle.load(open(os.path.join(“static/pickles/similarNames.pkl”), ‘rb’))
similarValues = pickle.load(open(os.path.join(“static/pickles/similarValues.pkl”), ‘rb’)) if inputImage in set(similarNames.index):
return getNames(inputImage, similarNames, similarValues)
else:
print(“‘{}’ was not found.”.format(inputImage))
sys.exit(2)
getImages 加载 pickle 文件。getNames 从它们中创建简单的列表,并从这些列表中删除相同的图像。 recLength 是您想要处理的相似图像的数量,应该将其移动到配置文件中。
现在,我们已经为这个 Python 函数提供了用户输入,该函数返回所选的相似图像。然后,如前所述,将它们用于 html 呈现。
展望:生产前景
在之前的文章中展示了如何用 PyTorch 实现推荐系统。本文描述了如何在本地使用基于 Flask 的网站上的结果。如果你想用原型工作,这是很棒的。它也适用于很少扩展的小型项目。
对于具有一些可伸缩性需求的不断发展的应用程序的生产,您可以使用 Flask,但是您可能需要关注更多的主题,这些主题的优先级可能会因范围而异:
- 项目结构
- 使用数据库
- 部署到生产系统/云环境→总的来说,一个可靠的持续集成链覆盖了一个合适的测试策略
- 配置处理
- 上传新数据(新图像)并自动更新 top-k 列表
- 错误处理、记录和监控
- 根据您的项目规模,这些可能成为最大的主题:可伸缩性、可靠性和可维护性[1]
- 根据特定的用例,在建议和一般调整中产生更多的多样性
- 安全性、负载平衡……
您的生产应用程序还有一些工作要做!
在下一篇文章中,我将解释如何为这个用例使用 PostgreSQL 数据库,如何构建项目以及如何将它部署到 Heroku。
尽管如此,通过所介绍的步骤,您已经拥有了一切,可以在浏览器前开始连接 Python 代码和用户的旅程了!
[1] Martin Kleppmann ,数据密集型应用:可靠、可扩展和可维护系统背后的伟大理念,奥莱利英国有限公司,2017 年
感谢阅读!喜欢这个话题吗?
如果你觉得这本书有趣,你可能想看看我的相关文章:
[## 轻松推荐相似图片
使用来自训练的卷积神经网络的特征来产生可比性
towardsdatascience.com](/effortlessly-recommending-similar-images-b65aff6aabfb) [## 使用 PyTorch 推荐相似图片
使用 Resnet18 实现完全迁移学习
towardsdatascience.com](/recommending-similar-images-using-pytorch-da019282770c) [## py torch+Flask+PostgreSQL+Heroku 部署的映像建议
用 Flask 封装一个基于 PostgreSQL/ PyTorch 的图像推荐系统,导入数据并在 Heroku 上运行
towardsdatascience.com](/image-recommendations-with-pytorch-flask-postgresql-heroku-deployment-206682d06c6b) [## 成功互联网企业推荐系统的核心价值
推荐系统的重要性评估
medium.com](https://medium.com/swlh/the-core-value-of-recommender-systems-for-successful-internet-enterprises-7164a7bacdc6)
满满一瓶威士忌(WSGI)
原文:https://towardsdatascience.com/a-flask-full-of-whiskey-wsgi-e89525d6f9da?source=collection_archive---------18-----------------------
有了目前由我们支配的 WSGI 服务器套件,提供 python web 应用程序变得前所未有的简单。Nginx 背后的 uWSGI 和 gunicorn 都是提供 Flask 应用程序的优秀执行者……
是的,在生活中你还能要求什么呢?也有许多品种,以适应个人的喜好。玩笑归玩笑,这篇文章是关于配置和压力测试几个 WSGI (Web 服务器网关接口)来提供一个 Python web 应用程序。以下是我们在本帖中涉及的内容
- 用 Flask web 开发框架编写了一个简单的应用程序。唯一公开的 API 是通过查询后端资源生成随机报价。在这种情况下,是 Elasticsearch 索引了大量的引用。
- 看看下面这些独立的 WSGI web 服务器— gunicorn 、 uWSGI ,以及 Flask 捆绑的默认 werkzeug 。
- 看看使用 Nginx 来转发客户端请求的好处,这些请求被代理回上面的请求。
- 使用 supervisor 管理 WSGI 服务器,使用 Locust 驱动负载测试。
为了便于说明,我们在这里浏览了一些代码/配置片段,但是完整的代码可以从 github 获得。
1.WSGI 服务器
除非一个网站完全是静态的,否则 web 服务器需要一种方式来使用外部应用程序来获取一些动态数据。随着时间的推移,已经实现了许多方法来使这种练习变得精简、高效和简单。我们有好的旧 CGI,它为每个请求产生一个新的进程。然后是 mod_python,它将 python 嵌入到 web 服务器中,接着是 FastCGI,它允许 web 服务器接入一个长时间运行的进程池,将请求分派给它。他们都有自己的长处和短处。例如,请参见此堆栈溢出页面上的讨论和链接。
目前最受欢迎的是 WSGI 协议,它允许 web 服务器和它们需要访问的应用程序完全分离。这是一个总的示意图。
图一。web 服务器和 python 应用程序通过中间的 wsgi 服务器进行通信,该服务器在 http 和 WSGI 协议之间进行转换。当然,WSGI 服务器不仅仅是一个翻译器。它是线程化的,将传入的请求分布在 Flask 应用程序的多个实例上。
- WSGI 服务器本身支持 Http,所以客户机/Nginx 可以通过 Http 与它们对话。在 uWSGI 服务器的情况下,对于 Nginx,也可以选择 uwsgi 协议,并从命令行进行测试。
- Nginx 将请求代理回一个为 URI 配置的 WSGI 服务器。
- WSGI 服务器配置了 Python 应用程序来调用请求。结果会一路传回。
2.应用
应用程序很简单。这个应用程序只有一个文件——T2 报价。它允许一个 GET 请求。
/quotes/byId?id=INTEGER_NUMBER
该应用程序从 Elasticsearch 索引中获取报价文档,将 INTEGER_NUMBER 作为文档 ID,并将其呈现如下。
图二。我们从这篇博文中学到了什么?
图片和 CSS 由 Nginx 提供。
在没有 Nginx 的情况下,它们是从静态文件夹中发送的。
这就是应用程序的全部。无论我们选择使用哪种 WSGI 服务器都是一样的。这是目录和文件布局。
.
├── config.py # Config options for gunicorn
├── quotes.py
├── static
│ ├── css
│ │ └── quote.css
│ ├── favicon.ico
│ └── images
│ ├── eleanor-roosevelt.jpg
│ ├── martha washington.jpg
│ └── maya angelou.jpg
├── templates
│ └── quote.html
└── wsgi.py # Used by uWSGI
当使用内置的 werkzeug 作为 WSGI 服务器时,我们在 quotes.py 模块中提供运行时配置。调用服务时会提供 uWSGI 和 gunicorn 的配置。接下来我们将讨论 Nginx 和服务经理主管的问题。
3.配置
任何 WSGI 服务器使用的并发进程/工作进程的数量都会对性能产生影响。建议值约为内核数量的两倍,但如果不降低性能,也可以更大。在这里,我们不会弄乱每个工作线程,因为我们应用程序的内存占用很小。参见这篇文章中关于工人 vs 线程使用的一些讨论。
我们从 6 个工人开始,并改变它来衡量影响。我们对 gunicorn 和 uWSGI 服务器使用相同的数字,所以比较是苹果对苹果的。不幸的是,似乎没有办法在服务器上做同样的事情。
3.1 主管
我们使用 supervisord 来管理 WSGI 服务器进程。这允许更容易的配置、控制、通过 app/wsgi 和 UI 引导的日志的清晰分离。每台服务器的配置文件放在/etc/supervisor/conf.d 中,并启动 supervisord 服务。
[/etc/supervisor] ls conf.d/*
conf.d/gunicorn.conf conf.d/uwsgi.conf conf.d/uwsgi-http.conf conf.d/werkzeug.conf[/etc/supervisor] sudo systemctl start supervisor.service
这里是一个 UI 截图(默认为 localhost:9001 ),显示了正在运行的 WSGI 服务器,以及停止/启动、跟踪日志等控件。
图 3。Supervisor service 支持对 WSGI 服务器进行干净简单的管理
uwsgi 和 uwsgi-http 的区别在于,后者有一个 http 端点,而前者使用二进制 uwsgi 协议。我们在图 1 的上下文中讨论了这一点。让我们来看看每一个的配置文件。请注意,下面配置文件中的路径是带有“…”的占位符,将根据磁盘上的确切路径进行适当替换。
3.2 gunicorn
配置中的命令字段调用 gunicorn 。 gunicorn 服务器使用 quotes.py 中的 app 对象,并使 web api 在端口 9999 可用。下面是配置文件/etc/conf . d/guni corn . conf
一个单独的文件 config.py 用于提供线程数量、日志细节等等。
3.3 uWSGI
正如我们前面提到的, uWSGI 服务器可以提供 Http 或 uWSGI 端点。当 uWSGI 服务器位于类似 Nginx 的 web 服务器之后时,建议使用 uwsgi 端点。以下配置适用于 Http 端点。对于 uwsgi 端点,我们将“ -http 127.0.0.1:9997 ”替换为“ -socket 127.0.0.1:9998
配置类似于 gunicorn 的配置,但是我们不使用单独的配置文件。关键的区别是参数'-wsgi-file ',它指向由 uWSGI 服务器使用的带有应用程序对象的模块。
3.4 werkzeug
默认 werkzeug 服务器的选项作为 quotes.py 模块中 app.run (…)调用的一部分给出。我们禁用日志记录是为了不影响性能数字。
supervisord 唯一要做的就是让 werkzeugrun 成为一个守护进程。
3.5 Nginx
当使用 Nginx 时,我们需要它将请求正确地路由到上述 WSGI 服务器。我们使用 URI 签名来决定应该联系哪个 WSGI 服务器。下面是来自 nginx.conf 的相关配置。
我们通过 URI 的前导部分识别 WSGI 服务器,并小心地将它代理回我们定义的该服务器要监听的正确端口。
3.5 总结
有了这些,下面是 Nginx 就位时从客户端到后端的调用流的概要图。
图 4。当 Nginx 面向 WSGI 服务器时,来自客户端的请求的流程和路由。
在没有 Nginx 的情况下,客户机直接向由 WSGI 服务器支持的 Http 端点发送请求。足够清楚——不需要另一张图。
4.用蝗虫进行负载测试
Locust 是一个针对 Python 的负载测试框架。测试可以方便地在代码中定义,统计数据以 csv 文件的形式收集。这里有一个简单的脚本,它在收集系统指标的同时使用了 Locust。我们使用 cmonitor_collector 来收集负载和内存使用指标。
- 启动系统监视器来收集负载、内存使用等统计数据
- 在本地主机上运行 load_tests.py 中描述的测试
- 将结果保存到文件“results_stats.csv”和“results_stats_history.csv”。
- 测试开始时,总共模拟了 500 个用户,每秒增加 10 个用户
- 测试运行 60 分钟
- Locust 还启用了一个带有绘图等功能的 UI(localhost:5557 ),但这里没有使用
- 停止系统监视器
- 对来自 Locust 的 csv 数据和系统度量数据进行后处理,以生成可以在不同的 WSGI 备选方案之间进行比较的图形
我们必须定义的唯一测试是命中我们已经公开的单个 API 是 …/quotes/byId?id=xxxx
该代码模拟一个用户,在再次点击 API 之前等待 1 到 3 秒钟,并使用一个随机整数作为要获取的报价的 ID。
5.结果
终于到了公布结果的时候了。花了一段时间来确定,但我们有相当多的移动件。绘制收集的数据很简单(我在这里使用 matplotlib ),因此我们将跳过这方面的代码。可以从 github 中获取 plots.py 。
我们有两个系列的运行——(a)6 个工人,和(b)60 个工人。每个系列有 7 次 locust 运行,如上面的代码片段所示。Locust 生成各种指标的数据——请求数、失败数、响应时间等……作为时间的函数。同样,cmonitor 收集硬件的负载、内存使用等数据。下面的图 5 显示了工人的结果。
图 5。6 名工人的绩效结果。gunicorn 和 uWSGI (uwsgi protcol)在有/没有 Nginx 的情况下性能最佳
从图 5 (E & F)中得出的主要结论如下。
- 性能:我们考虑平均响应时间(图 5F)。 uWSGI 和 gunicorn 服务器的性能在有/没有 Nginx 的情况下都不相上下。Flask 自带的默认服务器 werkzeug 是最差的,这是他们推荐的原因之一——不要在生产中使用它。另外,如果你喜欢 uWSGI 协议,那么选择二进制 uwsgi 协议,把它放在 Nginx 之后,因为它是最好的。下面是明确的顺序。
- Nginx 后面的 uWSGI 服务器( uwsgi )
- 没有 Nginx 的 gunicorn 服务器
- Nginx 后面的 uWSGI 服务器(Http)
- Nginx 背后的 gunicorn 服务器
- 无 Nginx 的 uWSGI 服务器(Http)
- werkzeug ,带/不带 Nginx
- 为什么响应时间增加?原因不是因为服务器性能随着时间而下降。更确切地说,这是工作中清晨喝咖啡的星巴克现象!Locust 在这里报告的是从发出请求到收到响应之间的总时间。我们发出请求的速率大于服务器清除请求的速率。因此请求被排队,队伍随着时间变得越来越长。较早进入队列的请求比较晚进入队列的请求等待时间短。当然,这表现为后续请求的响应时间更长。
- 为什么中值的阶跃增加而平均值的阶跃平滑?中位数(或任何百分位数)只是一个整数(毫秒),而平均值当然是所有数字的平均值(浮点数)。百分位数基于其当前值两侧的计数,并给定随机性— 缓慢增加,并通过量子跳跃。另一方面,平均值持续增加。
但是从图 A-D 中我们可以学到更多的东西。
- (A)请求的总数随着时间的推移而增加——当然!有点线性,但不完全线性,在运行之间也有一些变化。这仅仅是因为模拟用户连续请求之间的等待时间在上面的代码片段中被随机化了。
- (B)有一些失败,但是与被服务的请求总数相比非常非常少。或许还不足以得出重大结论。
- (C & D)在任何情况下都有足够的空闲内存,没有太多的负载。但是看起来当不使用 Nginx 时,服务器会消耗更多的内存,负载也会稍微高一些。
很明显,我们不会用 6 名员工来增加服务器的负担。让我们把工人增加到 60 人,看看我们会得到什么。这在下面的图 6 中。
图 6。60 名工人的绩效与 6 名工人的绩效在质量上是相同的。gunicorn 和 uWSGI (uwsgi protcol)不管有没有 Nginx 都还是最好的。
我们明显增加了负载和内存使用量(C & D),但我们从图 5 中得出的所有结论仍然适用,首先是 uWSGI 服务器,其次是 gunicorn 。在结束这篇文章之前,让我们来看看 6 个和 60 个工人在同一个地块上的响应时间结果,只关注 uWSGI 和 gunicorn 。
图 7。在我们的案例中,增加工人数量不会产生巨大的影响。Nginx 后面的 uWSGI 服务器表现最好,其次是带/不带 Nginx 的 gunicorn。
6.结论
我们在这篇文章中了解到:
- Nginx 后面的 uWSGI 服务器表现最好
- 不管有没有 Nginx,gunicorn 都不会出错
- 我们希望避免将 uWSGI Http 服务器放在 Nginx 之后,就像他们在其网站上推荐的那样
- 我们在生产中不使用默认的 werkzeug 服务器!
快乐学习!
原载于 2020 年 2 月 16 日 http://xplordat.com。
一个灵活的实体解析框架
原文:https://towardsdatascience.com/a-flexible-framework-for-entity-resolution-da970732884a?source=collection_archive---------70-----------------------
活动讲座
Hoyoung Jang & Cheng Lin | TMLS2019
【https://torontomachinelearning.com/ 号
关于扬声器
- ThinkData Works 首席数据科学家 Hoyoung Jang
- 程林,麦吉尔大学优等生
关于谈话
数据管理和丰富管道的一个关键组成部分是连接来自各种来源的大型数据集,以形成一个整体视图;在跨数据源的实体之间建立连接。通常,这些实体(如个人、组织或地址)可能没有可用作检测重复项或合并数据集的关键字的唯一标识符。ThinkData 开发了一个可扩展的实体解析引擎来解决这些问题。在试验了深度学习和传统的 NLP 技术之后,该团队找到了准确性和性能的最佳平衡。具体来说,与 Magellan(研究中领先的实体解析项目)相比,我们已经实现了近乎对等的准确性,尽管具有更好的性能指标和更大的可扩展性。本次讲座将讨论实体解析的重要性,我们解决现实世界挑战的方法,以及将实体解析和图形关系结合使用的潜力。
一个灵活的实体解析框架
一个被遗忘的苏联人工智能故事
原文:https://towardsdatascience.com/a-forgotten-story-of-soviet-ai-4af5daaf9cdf?source=collection_archive---------23-----------------------
阿波罗-联盟号试验项目是苏联太空探索中最受欢迎的项目之一。然而,苏联在人工智能方面的早期工作在很大程度上被遗忘了。 图片来源 。
西方计算机科学和人工智能的创始人图灵、明斯基和麦卡锡的名字现在为每个人所熟悉。然而,人们对苏联铁幕下的人工智能发展史知之甚少,尽管有时两个系统之间的竞争并不像在太空中那样激烈。下面是一个被遗忘的苏联人工智能的故事,通过这些事件的英雄,安德烈·莱曼和他的同事的生活镜头呈现。
安德烈·莱曼。图片来源:Igor Faradzhev 的个人档案。
1955 年可以被认为是苏联人工智能的开始,当时一群数学家接触到了计算机 M-2,并开始了软件工程来解决科学问题和数学难题。
Andrey Leman(1940–2012),现在因与人合著 Weisfeiler-Leman 算法、对第一个苏联数据库国际核事故等级和第一个国际象棋世界冠军 Kaissa 的贡献而闻名,他是 Kronrod 团队的早期成员之一,当时该团队正在开发第一批人工智能程序。
他的一生,从在学校数学奥林匹克竞赛中获胜,到在人工智能实验室工作,再到后来移民到硅谷,是苏联天才工程师和数学家一代的象征。
数学奥林匹克
安德烈·莱曼(Andrey Leman)所受的教育是那个时代聪明男孩的典型教育:数学成绩优异,在数学奥林匹克竞赛中表现优异,就读于美国最好的大学。在没有互联网的时代,数学奥林匹克是追求数学职业生涯的灵感来源,安德烈很自然地被吸引到这一领域。
给 1958 年数学奥林匹克冠军颁奖。图像来源。
可以说,这种对谜题的兴趣贯穿了安德烈的一生,他开始作为数学家,然后作为程序员,继续解决难题。他后来将这些问题收集成一本书,多年来,这本书是苏联学生准备的主要来源。
17 岁时,安德烈是苏联顶尖学校莫斯科国立大学的新生。他与鲍里斯·魏斯费勒一起学习,并一直合作到鲍里斯 1975 年移民国外。他于 1962 年毕业于莫斯科国立大学,并加入了苏联的“第一个人工智能实验室”。
人工智能实验室
亚历山大·克朗罗德。苏联 AI 创始人。图片来源。
如果有一个人应该被命名为苏联人工智能的创始人,那将是实验室的负责人亚历山大·克朗罗德。Kronrod 作为一名科学家有一条非常有趣的道路,开始是一名有前途的年轻数学家,从事复分析和微分方程的研究,他在第二次世界大战开始时自愿参军,这使他获得了几枚勇敢勋章,但也导致了两次受伤,使他无法继续服役。1945 年,他加入了库尔恰托夫的研究所,从事数值数学研究,直到他意识到计算可能比“纯”数学更有成果。
理论和实验物理研究所(ITEP)。图像来源。
四年后他成为新的理论和实验物理研究所(ITEP) 数学系的负责人,目标是领导核物理的创新(计算基本粒子的核反应堆和加速器,处理云室中的观察结果等)。)—这个方向对这个国家来说至关重要。如果不是 Kronrod 对人工智能的坚定信念,实验室只会进行数值模拟,人工智能可能不会出现在这个研究所。然而,Kronrod 的高声誉让他和他的团队也可以研究可以玩纸牌游戏和国际象棋的智能系统。
在 AVL 树中插入元素,这是 ITEP 发明的。
当时计算机科学的一个热门话题是离散算法的计算复杂性,Kronrod 的团队也对此做出了贡献。团队中的两名成员 G. Adelson-Velsky 和 E. Landis 提出了第一个自平衡二叉查找树,现在被称为 AVL 树。
引入了多项式可解问题和 NP-完全性的第一个概念,实验室对寻找各种问题的快速算法感兴趣。
大多数问题很快被排除在 P 或 NP-完备集之外,但是两个实际上很重要的问题,线性规划和图同构,不属于这一类。
后来,另一位苏联数学家 Leonid Khachiyan 构造了线性规划的多项式时间算法,但是图同构问题仍然不属于 p 类。
自然,克朗罗德实验室的成员包括安德烈·莱曼和鲍里斯·魏斯费勒都对图同构问题感兴趣。他们的第一个重要成果就是今天众所周知的魏斯费勒-莱曼算法 (1968)。
安德烈·莱曼和鲍里斯·魏斯费勒。图片来源:Igor Faradzhev 的个人档案。
最近,由于图的机器学习的发展,对 Weisfeiler-Leman 算法的兴趣增加了,它为图神经网络奠定了基础。
这项关于图同构的工作最终导致了 1971 年在 Kronrod 指导下的 Leman 的第一篇论文;然而,高级认证委员会(HAC)负责人与 Andrey 导师的个人敌意导致论文被拒绝,其表述为“这不是数学”。
“我不是数学家,我是程序员。”——安德烈苦涩地回应道。
随后,他将兴趣从组合学转向更像程序员的问题,并于 1973 年在 V. Arlazarov 的指导下就数据库管理对他的第二篇论文进行了答辩。他对苏联第一个数据库国际核事故等级的贡献为他赢得了苏联部长理事会奖,该数据库在苏联被广泛使用。
Andrey 没有将自己局限于数据库编程,而是致力于软件工程的其他问题。其中之一是人工智能棋手的发展,他们成为了第一个世界冠军。
艾下棋
克劳德·香农、约翰·麦卡锡、埃德·弗雷德金和约瑟夫·韦岑鲍姆 (1966)。来源。
艾伦·图灵发明他的“通用图灵机”几年后,信息论之父克劳德·香农试图教计算机下棋。这个想法后来流行起来,并且有平行的倡议,一个在美国,另一个在苏联,来开发一个可以学习下棋的算法。
在美国,这是麻省理工学院的约翰·麦卡锡和他的学生开发的程序。 约翰·麦卡锡等人在 1952 年与图灵讨论时创造了“人工智能”一词,是这个新兴领域的先驱。
在苏联,这是由 ITEP 的 Kronrod 小组开发的程序。Kronrod 的实验室于 1963 年开始了这项研究,其中包括许多天才数学家,如 G. Adelson-Velskyi、V. Arlazarov 和 Andrey Leman。一家苏联报纸《共青团员报》的读者与它有过一场比赛,他们决定称它为 凯萨——象棋女神。
1965 年,j .麦卡锡访问了苏联,并与 Kronrod 达成协议,在 1967 年举行了两个程序之间的第一次国际象棋比赛。在 4 场比赛中,凯萨展示了强大的开局知识和分析能力,以 3:1 赢得了系列赛。但这只是世界杯前的热身。
计算机之间的第一场国际象棋比赛:苏联(白)和美国(黑)。lichess.orgT2 制造的图像。
1969 年,克朗罗德和其他数学家在信上签名,为另一位遭到不公正谴责的苏联数学家叶赛宁-沃尔平辩护。这种活动在大学里是严格禁止的,不幸的是,克朗罗德被解雇了,他的实验室也被解散了。
V. Arlazarov 带领 Kaissa 集团参加了第一届国际象棋锦标赛。图像来源。
他的实验室成员加入了控制问题研究所(ICP);但克朗罗德并没有加入新的实验室v . Arlazarov成为领导 Kaissa 为首届 AI 棋手世界杯开发的团队负责人。
1974 年,在斯德哥尔摩,来自 8 个国家的 13 个项目争夺世界冠军的头衔。比赛在这个城市最大的酒店的音乐厅举行了五个晚上。六场比赛同时进行。凯萨 赢下全部四局 赢得金牌,以各 3 分超越美国对手 Chess-4、Chaos、Ribbit。看到他们的科学家为国际象棋带来第一枚金牌,这是整个国家的胜利。
Tech-2(美国)对 Kaissa(苏联),1974 年,斯德哥尔摩。右边的唐斯科伊先生正在通过电话接收这些动作。图片来源。
随后,克朗罗德说:“国际象棋是人工智能的果蝇”。这是一种极好的实验动物,研究人员可以用它来测试他们的假设。
硅谷
Andrey 继续与他在 Kronrod 实验室的 AI 朋友一起工作:首先是 1968-76 年在 ICP,然后是 1976-90 年在系统分析研究所,直到铁幕倒塌。1990 年安德烈加入了硅谷的“登陆党”组织。**
楔形文字 OCR 是 Andrey 和他的同事在登陆硅谷后的第一个成功产品。图片来源。
在那里成立的初创公司认知技术公司,他们开发了光学识别系统,成为识别不同语言扫描文本的领导者。他们的楔形文字 OCR 解决方案被许多 IT 巨头使用,如甲骨文、IBM 和三星。
从 1995 年到 2012 年,Andrey 在多家高科技初创公司担任程序员。他最后的雇主是基因公司 Invitae,在那里他开发了基础设施系统,至今仍被员工大量使用。他是生物信息学的新手,但他对解决挑战性问题的好奇心也帮助他在这一领域取得了成功。
美国的安德烈·莱曼。图片来源:Igor Faradzhev 的个人档案。
安德烈于 2012 年去世,但在人们的记忆中,他是一位可靠的同事和忠诚的朋友,极具幽默感,总是乐于助人。
他和他的同事们的贡献帮助人工智能从一个数学分支发展成为最有影响力的科学领域之一,他们的工作现在是苏联人工智能历史的一部分。
— — — — — — —
鸣谢:大部分历史资料收集自 Andrey 的同事:Igor Faradzhev、Michael Furman、Ilia Ponomarenko、Olga Weisfeiler、Vladimir Arlazarov。这篇文章中的一些信息可以在“对称性与规律性:它是如何开始的,它导致了什么?伊戈尔·法拉吉夫。Igor Faradzhev 授予的文本中使用的一些照片。我感谢阿列克塞·伊万诺夫对编辑文本提出了有益的建议。
P.S .我会继续写关于图机器学习的文章,所以如果你有兴趣,可以在 medium 上关注我或者订阅我的 电报频道 (我每天都更新)或者 我的 twitter (我每周更新一次)。
前技术实习生成为好实习生的指南
原文:https://towardsdatascience.com/a-former-tech-interns-guide-to-being-a-good-intern-f9d18c60da9e?source=collection_archive---------54-----------------------
我可以和熊猫一起玩。
图多尔·巴休在 Unsplash 上的照片
“你熟悉 Python 吗?”
我尽最大努力令人信服地点头,同时一直在想“python…为什么我们要谈论蛇?”
*引发读者哄堂大笑
我毕业时获得了国际商业管理学士学位。我大学毕业后的第一次实习?“客户数据智能”。我不知道我在做什么。
我们入职一个月后,一位资深员工把他的一个项目交给了我们。在他给我们的第一封邮件中,他写道:
“这是 Gitlab 的链接。我主要使用 Pandas 进行数据处理,但是一些数据来自我们的数据仓库,所以我只使用 SQL 查询。如果你对目前为止的 60 行有任何问题,请告诉我。否则,您可以开始开发。”
呃…
我有几个问题:
- 什么是 gitlab?
- 熊猫?喜欢..吃竹子的那种?(是的,我会开些糟糕的玩笑)
- 如何在 Python 脚本中执行 SQL?你是魔术师吗?
我快速搜索了一下,想出了一些答案。我了解到:
- Gitlab 是一个基于 web 的分布式版本控制系统,由团队用于开发项目。
- Pandas 是一个用于数据分析的 Python 库。
- 您可以使用 ODBC(开放式数据库连接)驱动程序将 Python 连接到数据库并执行 SQL 命令。
澄清这些介绍性的问题是一个开始。一个月后,我们有了一个最小可行的产品。五个月后,我和另一个实习生已经把那 60 行代码变成了一个 600 行的庞然大物,并根据用户反馈进行了功能扩展和调整。所有这一切都需要边做边学,因为我们之前都没有接触过 Python。当我们的实习结束时,我们移交了这个项目,感觉有点似曾相识。我们已经从学生变成了大师。或者可能只是中级生。(那是 HIMYM 的参考。)
陷入困境给了我一个独一无二的机会来快速掌握一项新技能。我知道我离成为一名合格的开发人员还有很长的路要走。单单回顾那个项目,我就能想到一千件我会以不同方式去做的事情。但这半年的经历让我建立了足够的兴趣,想进一步从事这种工作。
在实习期间,我也一路接触了 SQL、Tableau、Splunk 和 AWS。我从未想过我会使用这些工具,更不用说我喜欢学习它们了。在大学里,每当我们有任何与数据相关的任务时,我都会避开它们。我更喜欢在团队中担任与写作相关的角色。现在,我的全职工作每天都涉及开发工作!
我还是觉得自己不够格。我学得越多,就越意识到自己有多少不知道。这让人望而生畏,因为人们期望我去实现。到目前为止,我学得足够跟上,但我担心这不会永远持续下去。
我现在的经历和我当实习生时的感受相似。每天我都在学习,学习,这样我就能向每个人证明我不只是说说而已。实习结束时,我的一个队友为我和另一个实习生计划了一次与团队的告别会。在我们开始吃蛋糕之前,他说(转述):
“你们真的展示了实习生应该是什么样的。你最终给公司带来了切实的影响。”
这对我意义重大,因为我觉得花在学习新东西、观察代码崩溃、学习更多新东西和调试代码上的所有时间实际上都有意义。他的话打破了我长久以来“编码对我来说太难了”的心态。
因此,我非常感激我的实习经历。现在让我坚持下来的是,我的实习证明了我可以学习并适应工作中的新要求。因此,我想分享我在实习期间做的事情,每个人都可以做(即使你不是实习生)。
如何充分利用你的实习:
1.做一块海绵。会游泳的海绵。
仅仅吸收同事教给你的东西是不够的。实习是一份让你学习新事物的工作。我把每天努力学习至少一件新东西作为目标。你永远不知道什么时候你偶然得到的一个小消息会让你帮助一个需要帮助的同事。你知道的越多,你能做的就越多。
当有人能做他们不能做的事情,或者有人能做他们能做但更快的事情时,人们总是印象深刻。更让人印象深刻的是因为你是一个(年轻?)实习生。做那个实习生!
2.不要坐在办公桌前等着有事做。请随机的人做随机的事。
我很幸运,有一位经理告诉我,除了我的工作描述之外,还要探索其他项目。我牢记在心,最后列出了一长串与“客户数据智能”无关的事情。
其中一部分就是在 Slack 上给随机的人发消息,看看他们是否需要帮助。我还经常把我的办公椅转过来,问那个总是需要 Excel 帮助的家伙是否还需要我做什么(我有点夸张,但只是一点点)。
如果你想让人们认真对待你,你需要向他们展示你愿意工作。
3.积极推广自己的项目。
尽可能频繁的交流意味着和我一起工作的每个人都知道我在做什么。再说一次,我很幸运有一个提醒我大胆发言的经理。我养成了一个习惯,总是和我的项目主管、经理、队友和乒乓球伙伴谈论我正在做的工作和我面临的问题。人们听说了好的一面,主动提出帮助坏的一面。
4.请首席执行官喝咖啡。
这一次,我没有请我喝咖啡,而是主动请我的同桌喝一杯。作为一个人,他们站起来,从座位上跳起来,冲向食堂(我有点夸张,但只是一点点)。当我们排队时,首席执行官走过来站在我们身后。
在下单之前,我们和他谈了一会儿。我的一位同事告诉咖啡师,这轮由我买单,开玩笑地说我也可以为首席执行官买单。CEO 先生笑着说可以自己买咖啡。
当我为我们的订单付款时,我注意到它比应该的价格多了大约一欧元。然后我意识到咖啡师确实包括了 CEO 的订单。
当我意识到我(不小心)刚买了 CEO 的咖啡时,我眨了几下眼睛。
他笑了,和我们聊了一会儿,然后在离开前对我说“谢谢你的咖啡”。
也许你不必给首席执行官买咖啡,但充分利用你的经历很大一部分是从中获得乐趣。午餐时打乒乓球,将一名高级员工的代码修复称为“圣书”和 XXX 都绝对不是工作的一部分。但它们是我记忆最深的部分。
新的一章
在大学期末考试前的几个月,我对自己说,我迫不及待地想完成学业。同时又害怕离开学校这个安全的泡泡。置身于“真实世界”意味着我必须找工作,支付账单,做所有其他学校无法做的成人事情。除此之外,我甚至不知道我想要什么样的工作。
实习改变了我的生活,不仅因为它给我提供了一些急需的工作经验。它让我接触到 Excel 之外的数据分析工具,什么是“云计算”,以及为什么这幅漫画有意义:
再次,一个夸张,但几乎无关紧要的项目漫画故事,来自委员会旅行
我的实习开启了一条与我想象的完全不同的职业道路。它帮助我在一个我真正喜欢的领域和职能中找到了我的第一份全职工作。如果你正在努力寻找大学毕业后想做什么,尝试在不熟悉的领域实习。
它对你的帮助可能超乎你的想象。
还有,有人还没给我买咖啡。
另外,再给你讲一个笑话:
宠物蛇…哈哈哈哈——我创作的 gif,笑话来源于 devrant
对比自我监督学习的框架和新方法的设计
原文:https://towardsdatascience.com/a-framework-for-contrastive-self-supervised-learning-and-designing-a-new-approach-3caab5d29619?source=collection_archive---------2-----------------------
在一篇新论文中,我们讨论了在自我监督学习中驱动性能的关键思想,并展示了什么是重要的。
成批输入。
这是与我们的新论文相匹配的合作伙伴博客: 对比自我监督学习的框架和设计新方法 (作者威廉·法尔孔和赵京云)。
在过去的一年里,一系列“小说”自我监督学习算法在人工智能研究领域创造了新的最新成果:AMDIM、CPC、SimCLR、BYOL、Swav 等
在我们最近的论文中,我们提出了一个概念框架来描述对比自我监督学习方法。我们使用我们的框架分析了这些领先方法的三个例子,SimCLR、CPC、AMDIM,并表明尽管这些方法表面上看起来不同,但实际上它们都是彼此的细微调整。
在这篇博客中,我们将:
- 复习自我监督学习。
- 复习对比学习。
- 提出一个框架来比较最近的方法。
- 使用我们的框架比较 CPC、AMDIM、MOCO、SimCLR 和 BYOL。
- 使用我们的框架制定一个新的方法— YADIM。
- 描述一下我们的一些结果。
- 描述实现这些结果的计算要求。
这项工作的大部分是在脸书人工智能研究所进行的。
履行
您可以发现我们在本文中描述的所有增强和方法都在 PyTorch Lightning 中实现,这将允许您在任意硬件上进行训练,并使每种方法的并排比较更加容易。
AMDIM
BYOL
CPC V2 (据我们所知,仅验证了 DeepMind 之外的实现)。
V2 莫科
SimCLR
自我监督学习
回想一下在监督学习中,系统被给定输入(x)和标签(y),
监督学习:左边是输入,右边是标签。
在 自我——监督学习中,系统只给出(x)。代替 a (y),系统“学习从其输入的其他部分预测其输入的一部分”参考。
在自我监督学习中,输入被用作源和目标
事实上,这个公式是如此的通用,以至于你可以创造性地“分割”输入。这些策略被称为借口任务,研究人员已经尝试了各种方法。这里有三个例子:(1) 预测两个补丁的相对位置 , (2) 解决拼图游戏 , (3) 给图像着色。
借口任务的示例
尽管上面的方法充满了创造性,但它们在实践中并不奏效。然而,最近一系列使用对比学习的方法实际上已经开始显著缩小 ImageNet 上监督学习之间的差距。
最新的方法(Swav)正在缩小在 ImageNet 上训练的监督变异的差距
对比学习
大多数机器学习算法背后的一个基本思想是,相似的例子应该被分组在一起,并且远离其他相关例子的集群。
这种想法是关于对比学习的最早作品之一的背后,Chopra 等人在 2004 年有区别地学习相似性度量,并应用于人脸验证。
下面的动画说明了这一主要思想:
对比学习通过使用三个关键要素来实现这一点,即积极、锚定和消极(s)表征。为了创建一个正对,我们需要两个相似的例子,而对于一个负对,我们使用第三个不相似的例子。
但是在自我监督学习中,我们不知道例子的标签。所以,没有办法知道两个图像是否相似。
然而,如果我们假设每个图像是它自己的类别,那么我们可以想出各种方式来形成这些三元组(正负对)。这意味着在一个大小为 N 的数据集中,我们现在有 N 个标签!
现在我们知道了每张图片的标签,我们可以使用数据扩充来生成这些三元组。
特征 1:数据增强管道
我们可以表征对比自我监督学习方法的第一种方式是通过定义数据扩充管道。
一个数据扩充管道 A(x) 将一系列随机变换应用于相同的输入。
应用于输入的随机数据扩充管道
在深度学习中,数据扩充旨在构建对原始输入中的噪声不变的表示。例如,网络应该将上面的猪识别为猪,即使它被旋转,或者如果颜色消失,或者即使像素周围“抖动”。
在对比学习中,数据扩充管道有一个次要目标,即生成锚、正面和负面示例,这些示例将被提供给编码器,并用于提取表示。
CPC 管道
CPC 引入了一个应用变换的管道,如颜色抖动、随机灰度、随机翻转等,但它也引入了一个特殊的变换,将图像分割成重叠的子块。
关键 CPC 转换
使用此管道,CPC 可以生成多组正样本和负样本。在实践中,这一过程应用于一批样品,其中我们可以使用该批样品中的其余样品作为阴性样品。
从一批图像中生成正对、锚对和负对。(批量= 3)。
AMDIM 管道
AMDIM 采用了一种稍微不同的方法。在执行标准变换(抖动、翻转等)后,它通过对同一图像应用两次数据扩充管道来生成图像的两个版本。
这个想法实际上是由 Dosovitski 等人在 2014 年通过本文提出的。这个想法是使用一个“种子”图像来生成同一图像的多个版本。
西姆 CLR、Moco、Swav、BYOL 管道
AMDIM 中的管道工作得如此之好,以至于随后的每种方法都使用相同的管道,但对之前发生的转换进行了细微的调整(有些添加了抖动,有些添加了高斯模糊,等等)。然而,与 AMDIM 中引入的主要思想相比,这些变换中的大多数都是无关紧要的。
在我们的论文中,我们对这些变换的影响进行了评估,发现变换的选择对该方法的性能至关重要。事实上,我们认为这些方法的成功主要是由特定的转换选择所驱动的。
这些发现与西姆 CLR 和 BYOL 公布的类似结果一致。
下面的视频更详细地说明了 SimCLR 管道。
特征二:编码器
我们表征这些方法的第二种方式是编码器的选择。上述大多数方法使用各种宽度和深度的网。
ResNet 架构(鸣谢:原 ResNet 作者)
当这些方法开始出现时,CPC 和 AMDIM 实际上设计了定制编码器。我们的消融发现,AMDIM 不能很好地概括,而 CPC 则较少受到编码器变化的影响。
CIFAR-10 上的编码器鲁棒性
自 CPC 以来,每种方法都采用 ResNet-50。虽然我们可能还有更好的架构有待发明,但在 ResNet-50 上实现标准化意味着我们可以专注于改善其他特征,从而通过更好的培训方法而不是更好的架构来推动改进。
一个发现确实适用于每一次消融,更宽的编码器在对比学习中表现得更好。
特征 3:表示提取
表征这些方法的第三种方式是通过它们用来提取表示的策略。这可以说是所有这些方法中“神奇”的地方,也是它们最不同的地方。
为了理解为什么这很重要,让我们首先定义一下我们所说的表示是什么意思。一个表示是一组独特的特征,允许系统(和人类)理解是什么制造了那个对象,那个对象,而不是一个不同的对象。
这篇 Quora 帖子使用了一个尝试对形状进行分类的例子。为了成功地对形状进行分类,一个好的表示可能是在该形状中检测到的角的数量。
在这个对比学习方法的集合中,这些表征以不同的方式被提取出来。
CPC
CPC 引入了通过预测潜在空间中的“未来”来学习表征的思想。实际上,这意味着两件事:
1)将一幅图像视为一条时间线,过去在左上方,未来在右下方。
CPC“未来”预测任务
2)预测不会发生在像素级别,而是使用编码器的输出(即:潜在空间)
从像素空间到潜在空间
最后,通过使用编码器(H)的输出作为投影头(作者称之为上下文编码器)生成的上下文向量的目标来制定预测任务,来进行表示提取。
CPC 表示提取
在本文中,我们发现,只要数据扩充管道足够强大,这种预测任务是不必要的。虽然有很多关于什么是好的管道的假设,但我们认为,一个强大的管道会产生积极的配对,它们共享相似的全球结构,但具有不同的局部结构。
AMDIM
另一方面,AMDIM 使用从卷积神经网络(CNN)的中间层提取的特征图的视图间比较表示的思想。让我们把它分成两个部分,1)图像的多个视图,2)CNN 的中间层。
1)回想一下,AMDIM 的数据扩充管道生成同一图像的两个版本。
2)将每个版本传递到相同的编码器中,以提取每个图像的特征图。AMDIM 不会丢弃编码器生成的中间特征图,而是使用它们在空间尺度上进行比较。回想一下,当一个输入通过 CNN 的各层时,感受野对不同尺度的输入信息进行编码。
参考文献【1】【2】。
AMDIM 通过对 CNN 的中间输出进行比较来利用这些想法。下面的动画演示了如何对编码器生成的三个特征图进行比较。
AMDIM 表示提取 : AMDIM 使用相同的编码器提取 3 组特征图。然后,它在特征地图之间进行比较。
这些方法的其余部分对 AMDIM 提出的想法进行了细微的调整。
SimCLR
SimCLR 使用与 AMDIM 相同的思想,但是做了 2 处调整。
a)仅使用最新的特征地图
b)通过投影头运行特征图,并比较两个向量(类似于 CPC 上下文投影)。
Moco
正如我们前面提到的,对比学习需要反面样本才能起作用。通常,这是通过将一批中的图像与一批中的其他图像进行比较来完成的。
Moco 做了与 AMDIM 相同的事情(仅使用最近的特征图),但是保留了它所看到的所有批次的历史,并且增加了阴性样本的数量。其效果是,用于提供对比信号的阴性样本的数量增加,超过了单个批次的大小。
鸣谢:Moco 原创作者。(来源)
BYOL
使用与 AMDIM 相同的主要思想(但是只有最后的特性图),但是有两个变化。
鸣谢:Deepmind ( 来源
- BYOL 使用两个编码器,而不是一个。第二个编码器实际上是第一个编码器的精确副本,但它不是在每次通过时更新权重,而是在滚动平均值上更新权重。
- BYOL 不使用阴性样本。而是依赖滚动权重更新作为向训练给出对比信号的方式。然而,最近的一次消融发现这可能是不必要的,事实上添加批量标准化是为了确保系统不会生成琐碎的解决方案。
Swav
将他们的表示提取任务框定为“在线聚类”之一,其中他们强制“来自同一图像的不同增强的代码之间的一致性”【参考】。因此,这与 AMDIM 的方法相同(仅使用最后的特征图),但他们不是直接比较向量,而是计算一组 K 个预计算代码的相似性。
鸣谢:Swav 作者(来源)
在实践中,这意味着 Swav 生成 K 个簇,并且对于每个编码的向量,它与这些簇进行比较以学习新的表示。这项工作可以被视为混合了 AMDIM 和 Noise 作为目标的思想。
特点 3,外卖
这些方法的不同之处在于表示提取策略。然而,这些变化是非常微妙的,没有严格的消融,很难判断到底是什么驱动了结果。
从我们的实验中,我们发现 CPC 和 AMDIM 策略对结果的影响可以忽略不计,反而增加了复杂性。使这些方法起作用的主要驱动力是数据扩充管道。
特征 4:相似性度量
我们可以用来比较这些方法的第四个特征是它们使用的相似性度量。以上所有方法都使用点积或余弦相似度。虽然我们的论文没有列出这些消融,但我们的实验表明,相似性的选择在很大程度上是无关紧要的。
特征 5:损失函数
我们用来比较这些方法的第五个特征是损失函数的选择。所有这些方法(除了 BYOL)都集中在使用 NCE 损失。NCE 损失有两部分,分子和分母。分子鼓励相似的向量靠近,分母推动所有其他向量远离。
如果没有分母,损耗很可能变成常数,因此所学的表示法将没有用。
然而,BYOL 不再需要分母,而是依靠对第二编码器的加权更新来提供对比信号。然而,如前所述,最近的消融表明这实际上可能不是对比信号的驱动因素。
在本视频中,我以 SimCLR 为例,对 NCE 损耗进行了全面解释。
又一个 DIM(亚迪姆)
我们希望通过生成一种新的自我监督学习方法来展示我们框架的有用性,这种方法没有借口动机或涉及的表征提取策略。我们称这种新方法为另一种 DIM (YADIM)。
YADIM 的特点如下:
特点一:数据增强管道
对于 YADIM,我们合并了 CPC 和 AMDIM 的管道。
特点二:编码器
我们使用 AMDIM 的编码器,尽管任何编码器如 ResNet-50 也可以工作
特征 3:表示提取
亚迪姆策略很简单。对图像的多个版本进行编码,并使用最后的特征图进行比较。没有投影头或其他复杂的比较策略
特征 4:相似性度量
对于 YADIM,我们坚持点积
特性 5:损失函数
我们也使用 NCE 损失。
YADIM 结果
尽管我们唯一有意义的选择是合并 AMDIM 和 CPC 的管道,但与其他方法相比,YADIM 仍然做得很好。
与所有相关的方法不同,我们通过实际实现每种方法来生成上面的结果。事实上,据我们所知,我们对 CPC V2 的实现是 DeepMind 之外的首次公开实现。
更重要的是,我们使用 PyTorch Lightning 来标准化所有实现,这样我们就可以客观地提炼出上述结果的主要驱动因素。
计算效率
上述方法是使用大量计算资源训练的。高昂的成本意味着我们没有进行严格的超参数搜索,而是简单地使用 STL-10 的超参数在 ImageNet 上进行训练。
使用 PyTorch Lightning 来有效地分配计算,我们能够通过 ImageNet 使用 16 位精度将一个时期降低到每个时期大约 3 分钟。
这些是我们用于每种方法的计算资源
基于每小时 31.212 美元的 23dn . 24x 大型实例
基于每小时 31.212 美元的 23dn . 24x 大型实例
基于每小时 31.212 美元的 23dn . 24x 大型实例
基于每小时 31.212 美元的 23dn . 24x 大型实例
关键要点
- 我们引入了一个概念框架来比较和更容易地设计对比学习方法。
- AMDIM、CPC、SimCLR、Moco、BYOL 和 Swav 在细微方面彼此不同。主要的区别在于他们如何提取表示。
- AMDIM 和 CPC 介绍了其他方法使用的主要关键思想。SimCLR、Moco、BYOL 和 Swav 可以被视为 AMDIM 的变体。
- 编码器的选择并不重要,只要它是宽的。
- 只要数据扩充管道生成良好的正面和负面输入,表示提取策略就无关紧要。
- 使用我们的框架,我们可以制定新的 CSL 方法。我们设计了 YADIM(另一个 DIM ),作为一个可以与竞争对手的方法相媲美的例子。
- 训练这些方法的成本意味着世界上只有少数研究小组能够继续取得进展。尽管如此,我们以一种标准化的方式发布所有这些算法至少缓解了实现这些算法和验证这些实现的问题。
- 由于大多数结果是由更广泛的网络和特定的数据增强管道驱动的,我们怀疑当前的研究路线可能有有限的改进空间。
感谢
正如我们在论文中提到的,我要感谢 CPC、AMDIM 和 BYOL 的一些作者进行了有益的讨论。
这项工作的大部分是在脸书人工智能研究所进行的。没有公平的计算资源,消融和长的训练时间是不可能的。
我还要感谢费尔和 NYU CILVR 的同事们,他们进行了有益的讨论,他们是 Stephen Roller、Margaret Li、Tullie、Cinjon Resnick、Ethan Perez、Shubho Sengupta 和 Soumith Chintala。
PyTorch 闪电
此外,这恰好也是创建 PyTorch Lightning 的主要原因之一,PyTorch Lightning 是一种利用大量计算资源快速迭代想法的技术,而不会陷入训练这种规模的模型所需的所有工程细节中。
最后,我要感谢我的顾问 Kyunghyun Cho 和 Yann LeCun 在平行建造 PyTorch Lightning 的同时进行这项研究的耐心。
快速学习新数据科学概念的框架
原文:https://towardsdatascience.com/a-framework-for-learning-new-data-science-concepts-quickly-4a691250dc5c?source=collection_archive---------21-----------------------
数据科学
时间有限。潜在的知识是无限的。以下是我如何学习新的模型和概念
来自 Pexels 的 Andrea Piacquadio 的照片
数据科学和软件工程的成功取决于我们不断学习新模型和概念的能力。
这两个领域都是无限大的嵌套思想的保护伞。
虽然你可以在 NLP 的一个特定分支花上几十年时间,但许多人都是多面手,需要不断获取新知识。
这是我快速做到这一点的框架。
不要从数学或科学论文开始
数学被高估了。
它有两个用处:
- 它给人一种事物如何运作的直觉。
- 它允许在不使用现有包的情况下编码算法
趣闻:
前者在优化模型时很有用。
当我需要 Ruby 中的算法,但支持它的包只存在于 Python 中时,后者是有用的。
数学从来不是第一步。
观看 youtube 视频,从高层次上理解它
看几个视频。你可以发现它们涵盖了大多数概念。
此时不要试图理解具体的技术细节。只要对它的作用以及它与相关概念的不同之处有一个高层次的概念。
视频很棒,因为图像穿透了技术术语,这些术语常常使书面解释看起来比现实更复杂。
直奔主题,用几句话就能描述出这个概念。在这一点上,想象你正在向一个非技术同事解释它是很有用的。
让一些代码工作起来
在线查找代码片段。
可以经常 google“概念”+“python 教程”找代码。否则,找到一个相关的库并查看文档,或者在 Stack Overflow 上搜索相关的标签。
在这一点上,预计会与不同版本之间的冲突包和 API 发生冲突。始终使用虚拟环境来保持机器清洁!
让一些代码工作起来。改变变量。打破它。
看看每一步数据是如何变化的。
你在打基础,你会在精神上对它有更深的理解。
分解概念中的步骤
回到 youtube。
在纸上写出它的步骤。画一个流程图,当你更好地理解这个概念时修改它。
高级—出现了哪些组件和不同的步骤?
将设置(预处理)与您正在学习的模型本身隔离开来。
(可选)复习数学和阅读试卷
深入每一步。
理解数学。
如果你已经有了相邻概念的经验,这是最有益的。回顾一篇你没有经验的领域的高级论文会浪费很多时间。
现在把数学放在你之前的步骤之上。同样,可汗学院和 YouTube 在这方面也很有帮助。
我通常只在以下情况下采取这一步骤:
- MVP(基础案例)已经完成,可以进行优化了
- 这真的很有趣
- 我需要评估技术选项之间的权衡
用它造点东西
使用它或者失去它。
就我个人而言,我不记得任何我只读过的东西。
将它应用到您自己的用例中。这里重要的一点是在一个完全不同于你所学的例子的情况下运用它。
虽然回顾一个领域中的概念是很有用的,但是如果你以前应用过的话,(当你需要的时候)你会更容易得到它。
建造一些简单的东西。
结论
就是这样。
此外,学习你已经知道的东西。基金会被低估了。没有基础算术学不了微积分。
现在去学点东西吧。并且使用它(为善)!
新冠肺炎数据的快速原型数据科学建模框架——民主化新冠肺炎相关数据科学和分析
原文:https://towardsdatascience.com/a-framework-for-rapid-prototyping-data-science-modelling-of-covid-19-data-with-countries-cd8be3f35ad8?source=collection_archive---------59-----------------------
项目的标志 。
介绍
新冠肺炎成为全球性的疫情,对人类生活的各个方面都产生了影响。由于这种感染正在迅速传播并危及人类生命,需要立即采取行动在社区一级预防这种疾病。到目前为止,每个国家都面临着新冠肺炎疫情和他们的统计数据显示更大的差异。为了有效应对新冠肺炎和类似的流行病,短期和长期的质量、因素和策略应该是什么还不是很明显[1,2]。
由于这是一个超越简单想象的多维挑战,数据科学是理解与新冠肺炎相关的数据的模式和趋势的有效策略。虽然数据科学是揭示洞察力的有效技术,但广泛的社区和专业人员目前依赖于开放的可视化框架,这些框架主要涵盖描述性分析技术。如果用户友好的开放数据科学框架可用,主题专家(SME)可以有效地采用和有效地解释对社会和人类利益的见解[3]。
这是一个利用国家统计数据快速构建新冠肺炎数据的数据科学模型的框架。这将有助于将大数据集与新冠肺炎数据联系起来,然后应用基于机器学习的高级建模技术。这有助于新冠肺炎相关数据科学和分析的民主化,并促进数据驱动的决策和创新。
采纳框架
这个框架是使用Jupyternotebook 和 Python 库开发的。用户可以通过安装 Anaconda 轻松安装 Jupyter 笔记本。可以使用任何支持 Jupyter notebook 的平台(例如 AWS Sagemaker )。社区可以从Github克隆/下载框架。
数据集
为了演示该框架,使用了两个广泛使用的数据集。它们是:
1) 约翰霍普金斯大学(JHU) 和 Worldometers.info 公开数据为新冠肺炎统计的国家
2) 世界银行公开各国数据和统计数据
这些数据以 Python 库的形式提供。用户可以通过导入库来访问这些数据。这些库有适当的 API 来访问数据。
以下是所用库的重要参考。
*[## 冠状病毒肺炎
编辑描述
ahmednafies.github.io](https://ahmednafies.github.io/covid/)* *[## 欢迎阅读 wbdata 的文档!- wbdata 0.2.7 文档
Wbdata 是一个简单的 python 接口,用于从世界银行的各种数据库中查找和请求信息,作为…
wbdata.readthedocs.io](https://wbdata.readthedocs.io/en/stable/)* * [## 世界银行数据
这是用 Python 实现的世界银行 API v2。使用此包探索世界发展…
pypi.org](https://pypi.org/project/world-bank-data/) [## 冠状病毒肺炎
Python 包来获得关于由约翰霍普金斯大学和…
pypi.org](https://pypi.org/project/covid/)
然而,用户不希望局限于上述数据或库,因为有许多数据源可以轻松地与该框架集成。
方法学
该平台是使用【JHU】约翰霍普金斯大学和 Worldometers.info 开放数据为新冠肺炎【4】和 世界银行开放数据为各国【5】进行演示的。使用已发布的 Python 库将数据导入框架(如上一节所述)。
在 约翰霍普金斯大学(JHU) 和 Worldometers.info 公开的新冠肺炎数据中, 提供了与确诊、活跃、康复和死亡病例相关的国家统计数据以及更新日期。
另一方面, 世界银行各国公开数据 是一个通用和通用的数据集,提供与多个主题相关的多样化统计数据。它不是针对新冠肺炎危机开发的。该数据集包含与以下 21 个主题相关的国家统计数据。
世界银行数据集中与国家相关的主题
使用 Python 的 Jupyter notebook 有助于高效地探索和准备数据。在整个框架中,数据被作为 Pandas 数据帧来处理。根据需要使用 pythonmatplotlib和 seaborn 库来可视化和探索数据。由于世界银行数据集具有许多特征,因此需要探索性分析技术来有效地为精确建模准备数据。
新冠肺炎数据与国家数据/统计数据的快速原型数据科学建模框架。
该框架采用 LightGBM 基于梯度推进决策树的机器学习算法来设计和实现分类和回归模型。该算法在行业中被非常有效地用于结构化数据建模。它具有以下优点[6]:
- 训练速度更快,效率更高,
- 更低的内存使用率,
- 精确度更高,
- 支持并行和 GPU 学习
- 能够处理大规模数据。
一旦该模型被训练,该框架然后促进基于light GBM算法的高等级特征的重要特征分析。这包括对【SHAP】(沙普利附加解释) 库的改编,该库能够使用博弈论方法使用整合的功能来评估经过训练的机器学习模型[7]。这使得与假设相关的推理和处方成为可能。该框架还有助于评估培训和测试绩效。重要特性分析和性能分析阶段对于通过调整和重新训练模型来优化模型非常重要。****
结论
已经发布了许多与新冠肺炎相关的研究数据,需要对这些数据进行快速分析,并向社区传达见解(即规定分析),以改善健康和福祉。由于数据的高维度,围绕这一新冠肺炎数据分析的数据科学能力需要得到加强。这一提议的框架使得新冠肺炎数据与国家统计数据的数据科学模型快速原型化成为可能,从而有效地使新冠肺炎相关的数据科学和分析民主化。
未来工作
许多数据集正在出现,如果以统一的方式对它们进行适当的分析,它们将增强知识。计划将以下数据集纳入提议的框架。
**** [## 新冠肺炎资源
编辑描述
dataverse.harvard.edu](https://dataverse.harvard.edu/dataverse/2019ncov) [## 数据集/新冠肺炎
冠状病毒疾病 2019(新冠肺炎)时间序列列出了确诊病例、报告的死亡和报告的恢复。数据…
github.com](https://github.com/datasets/covid-19) [## 新冠肺炎冠状病毒数据资源中心
新冠肺炎数据中心新冠肺炎案件的数据是目前最重要的数据。这是我们看待事物的基础…
www.tableau.com](https://www.tableau.com/covid-19-coronavirus-data-resources) [## 冠状病毒源数据
我们完整的新冠肺炎数据集是由我们的数据世界维护的新冠肺炎数据的集合。它每天更新…
ourworldindata.org](https://ourworldindata.org/coronavirus-source-data) [## 新型冠状病毒(新冠肺炎)病例数据
自 2020 年 1 月 22 日以来的新型冠状病毒(新冠肺炎)流行病学数据。这些数据是由约翰·霍普金斯大学汇编的…
data.humdata.org](https://data.humdata.org/dataset/novel-coronavirus-2019-ncov-cases) [## 新南威尔士州新冠肺炎数据
新南威尔士州政府提供了新南威尔士州新冠肺炎病例和测试的数据集。点击下面的链接访问…
data.nsw.gov.au](https://data.nsw.gov.au/nsw-covid-19-data) [## 新冠肺炎开放研究数据集(CORD-19)
关于这个数据集的完整描述以及更新的信息可以在这里找到。作为对新冠肺炎的回应…
zenodo.org](https://zenodo.org/record/3727291#.Xq0HEpkRWUk)
此外,郊区一级的数据分析正在通过整合国家的人口普查数据进行规划。
[## 人口普查
普查地理基础如何使用统计地理进行普查输出的步骤
www.abs.gov.au](https://www.abs.gov.au/census) [## 新南威尔士州新冠肺炎病例按位置-新冠肺炎病例按通知日期和邮编,当地卫生…
URL…
data.nsw.gov.au](https://data.nsw.gov.au/data/dataset/covid-19-cases-by-location/resource/21304414-1ff1-4243-a5d2-f52778048b29) [## Census.gov
人口普查局的使命是作为美国人口和经济的高质量数据的主要提供者。
www.census.gov](https://www.census.gov/)
参考
[1]徐,b,Gutierrez,b,Mekaru,s .等.疫情流行病学资料,实时病例信息。 Sci 数据 7、 106 (2020)。https://doi.org/10.1038/s41597-020-0448-0
[2]董,e,杜,h .,,加德纳,L. (2020).实时跟踪新冠肺炎的交互式网络仪表板。柳叶刀传染病。https://doi . org/10.1016/s 1473-3099(20)30120-1
[3]卡拉汉·s·新冠肺炎是一个数据科学问题。模式。2020 年 4 月 7 日:100022。doi:10.1016/j . pattern . 2020.100022 .印刷前 Epub。PMCID: PMC7144860。
https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7144860/
[4]数据集由约翰·霍普金斯大学和 world ometers . info
https://ahmednafies.github.io/covid/提供
[5]世界银行公开数据
https://data.worldbank.org/
[6] LightGBM,https://github.com/microsoft/LightGBM
T4 灯光渐变增力机
[7]https://github.com/slundberg/shapSHAP【SHapley Additive exPlanations】*****
重新审视聚类算法
原文:https://towardsdatascience.com/a-fresh-look-at-clustering-algorithms-c3c4caa1a691?source=collection_archive---------19-----------------------
吉列尔莫·费拉在 Unsplash 上拍摄的照片
视频教程
深入研究一种新的聚类识别方法。
这个项目绝不是到了最后阶段。分享当前的想法,详细检查代码,获得一些反馈,看看是否值得进一步开发。出于对当前方法(至少是可通过标准库获得的方法)的失望,特别是所有主要方法的特殊性质,包括大众喜爱的 KMeans。我并不是说所提出的代码是以最有效的方式完成的,但是我确实努力做到了。如能提供改进建议,我们将不胜感激。
视频教程
设置问题
让我先介绍一下背景。由于 Medium 是一个博客平台,而不是一个科学研究的地方,所以我可以讲述这个故事,而不是以一种非常枯燥的形式呈现结果。如果这让你失望了,请原谅我——这基本上有点像“展示和讲述”。
几年前,我试图解决分析光栅文件的问题。如果您以前从未使用过这些工具,请查看我的地理空间冒险系列以了解更多详细信息:
[## 地理空间冒险。第五步。离开平地或飞越多边形的海洋。
顾名思义,是时候让我们做一些真正酷的事情,用“激光”去飞行了。字面上。我们是…
towardsdatascience.com](/geospatial-adventures-step-5-leaving-the-flatlands-or-flying-over-the-sea-of-polygons-846e45c7487e)
简而言之——这些是通过飞越你试图分析的区域,定期向其发射激光束并测量响应而获得的高度数矩阵。得到的矩阵可用于提取关于表面上各种物体的信息。这些物体可以是任何东西,从山和树到建筑物和桥梁。我对提取建筑物信息特别感兴趣,这意味着我有密集点的集合,我需要将它们解释为多边形。如果你在田野中间有一座孤零零的独立建筑——这很容易,你所要做的就是应用现成的凸包算法(来自 shapely library)。同样,如果你是这方面的新手——看看我的初级读本这里。但是如果我们着眼于一个人口密集的城市中心区域呢?
我最终通过编写一个自定义聚类算法来解决这个问题,该算法基本上将表示建筑物的点集合视为一个图形,其中每个节点(我们的栅格像素)都连接到它的近邻,如果它们满足高度标准的话。识别建筑物多边形的问题基本上是通过计算不连通图,然后对它们应用凸包来解决的。
现在,随着 COVID 危机的到来,我在找工作时有了大量的空闲时间,我认为重新审视这个问题并推广算法是一个好主意。我在这里展示的是结果。
唷…这是一个很长的介绍。让我们开始吧。
聚类的一个基本问题是,我们真的很擅长直观地判断它,但我们很少考虑它的机制。因此,很容易就能找到迷惑不经意的观察者得出错误结论的方法。如果我放大 2D 图上的一组点——我可以说它们是均匀分布的,如果我缩小——它们看起来像一个集群。所以从一开始,我们就需要定义问题的尺度,这将是驱动模型的主要参数之一。
最简单的方法是在我们的问题空间中定义一个基本单元的大小。如果这是一个简单的 2D,这意味着我们在包含该数据集的边界正方形中展开数据集中的所有点,并在每个点周围绘制正方形单元。如果我们在谈论一个更复杂的 n 维问题,例如 word2vec 文本表示的集合,这将是 n 维空间中的一个单位体积单元。当您看不到数据的图形表示时,很难识别数据的分组,因此拥有定义比例的正确方法非常重要。如果你有分类变量,它们总是可以简化为一组二进制变量(1/0 ),或者如果你想在它们之间建立一些有意义的关系,你可以选择一个使用实数的更复杂的版本。在任何情况下,每个维度所需的单元/分区数量的近似值可以构建为:
其中 N 是数据集中点(向量)的数量, n 是维度(连续变量)的数量, k 是分类变量的数量。我在这里假设分类变量减少到只有 1/0。
这个数字背后的直觉是:大大超过它将导致分割太小,因此除非聚类非常明显,否则您将无法检测到它。明显低于这个值会有使单元格变得太大的风险,以至于您只是掩盖了数据中的任何不规则性。在我的建筑物问题示例中,这一点特别重要,因为为了检测所有的建筑物,我们希望划分的数量比临界数量少很多。这是因为我们的点之间的距离在任何地方都是相同的,改变的是它们的类型(它们的高度轮廓)。最终,我们使划分足够大,以包括两层相邻的点。
为了这篇文章的目的,我不打算处理多维度的问题,我可能会在其他时间回来。这里给出的代码应该能够处理它们,如果您想包含分类变量,只需做一些小的修改。毕竟这里的目的是论证原理。
该算法
给你一个我们正在做的事情的浓缩的、简单的版本:
- 对数据进行归一化,这样每个变量现在都在 0 到 1 的区间内。
- 将每个变量乘以 D,取整数部分。通过将每个点放入特定的网格单元中,这有效地标准化了每个点。
- 计算每个格网像元中的点数,并丢弃点数低于特定阈值的像元。这是我们将要传递到模型中的另一个重要参数。在这个实现中,我看到了特定的百分位数,但它可以由任意数字驱动。
- 得到的结构可以表示为树的集合(或者更确切地说是图,但是让我们用树来滚动),我们所要做的就是运行广度优先搜索(BFS)算法来计算不相连树的实例,以识别我们的聚类。
- 最后,一旦识别出主要聚类,由于其细胞没有超过阈值而被遗漏的点需要被归属。这里,我在 main 函数之外通过计算到已识别的簇的质心的最小距离来做这件事。这不是唯一的选择,我相信也不是最好的选择。虽然它现在已经够用了。)实现起来简单快捷。
好了,让我们言归正传。
让我们从创建一个将要使用的虚拟数据集开始。在这篇文章的最后,我还将分享通过 scikit 的一些标准聚类算法运行这个数据集的比较结果。
加载我们需要的库:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
pd.plotting.backend='seaborn'
import time
import itertools
大部分时间我会尽量避免使用熊猫,它会在我们设置的最开始使用,然后在最后帮助观想和保持所有东西在一个地方。在大部分内容中,我们将使用 numpy 数组、列表和字典。保持简单(并对性能有所帮助)。顺便说一句,我已经使用 numba 和 cython 进行了代码加速,但我对结果并不满意,所以我们暂时将它们放在一边。
Matplotlib 和 Seaborn 实现可视化,也使用 Seaborn 作为熊猫的后端。使用时间模块来比较性能,并使用 itertools 来避免循环(至少以显式 python 形式)。
数据集:
本质上,这是四个集群,每个集群的中心点很好地聚集在一起,加上一些基本的拉伸,所以它们看起来不太规则。它们最终也会有些重叠,所以看看我们如何处理这些情况会很有帮助。
我们将使它们正常化:
现在继续想象:
plt.figure(figsize=(10, 10))
sns.scatterplot(ttf.x, ttf.y, alpha=0.5)
太好了。
在我们的例子中,细胞的数量可以计算为:
D = int(np.sqrt(len(ttf_norm)))
tolerance = 50
这就给出了 D=63。因此,我们可以使用的模型参数将是 D = 60(只是一个很好的整数),我们将在每个像元的点数(容差)方面寻找第 50 个百分位数。一般来说——容差的选择取决于我们的数据分布的好坏。如果无法通过视觉或其他方式进行检查,那么在不同的容差级别运行模型并查看不同级别找到了多少个聚类以及哪个结果最有意义(最稳定)不失为一个好主意。
我们还将把输入数据集转换成一个 numpy 数组。在这种情况下,它将只有两列,如果有更多的维度/变量,它将有更多。
X = ttdf_norm[['x', 'y']].values
好了,我们准备好了。我会一步一步来。
- 缩放和离散化:
Xint = (X * D).astype(int)
2.为每个单元格创建字符串 id:
Xstr = np.apply_along_axis(
''.join,
1,
np.char.zfill(
Xint.astype(str),
len(str(D))
)
)
这里发生的事情是,我们将每个坐标转换成一个字符串,然后用前面的零填充它,这样每个零的长度都与代表划分数(D)的字符串的长度相同。最后一步,将它们合并成一个 ID。我以这种方式创建 id 的原因是,这使我能够找到每个单元的最近邻居,而不必在大型数组中进行昂贵的查找,我可以从当前 id 中推断出它们的 id。
3.使用所有单元格的出现频率计数创建字典。简单如:
unique, counts = np.unique(Xstr, return_counts=True)
tree = dict(zip(unique, counts))
4.计算阈值:
mincount = int(
np.percentile(
np.array(
list(
tree.values()
)
)[
np.array(
list(tree.values())
) >1
],
tolerance
)
)
这一个有点忙,所以让我们看看是怎么回事。我们正在用树中的所有值创建一个 numpy 数组,并丢弃所有只有一点或更少的值。我们不希望这些影响百分点太多,因为它们不会带来任何价值。在得到的数组中,我们计算与我们的公差变量设置的百分比相对应的值。最简单的情况 50%对应中值。
5.修剪树木:清除所有低于最小数量的东西。使用简单的字典理解:
tree = {k: v for k, v in tree.items() if v > mincount}
顺便提一下——在玩 numba.jit 的时候,我不得不用一个简单的 python 来代替循环(当我这么做的时候,我的心都流血了)——因为 numba 在当前的实现中不能处理 list/dict 理解。现在,考虑一下这个——使用 numpy 数组作为键和值,可以完全不使用循环来完成这个任务。这应该会使代码更快,尽管这不是主要的瓶颈,所以这不会实质性地改变计算时间。
主要部分已经完成了。留给我们的是一个字典,其中的键对应于所有有意义的单元格,需要对这些单元格进行计数。
本质上,我们需要对这些进行广度优先搜索。这意味着我们将从我们的树中选择一个随机 id,将其标记为已访问,并将其所有邻居分配到“tocheck”列表(经典实现中的队列),然后我们从“tocheck”列表中选择任何值,并重复相同的过程。在经典实现中,这需要是来自“tocheck”的第一个值,因此使用了队列,但是,在我们的例子中,我们必须遍历所有的队列,所以顺序并不重要。一旦我们用完了‘to check’列表中的条目,我们就完成了第一棵树。我们可以将它分配给第一个集群,并从原始列表中选取下一个 id。
我不打算在这里讨论具体的实现细节,因为这不是特别新颖或有趣——我仍然试图让它更快,因为这是花费时间最多的地方。然而,我将向您展示邻居选择,因为这部分不是微不足道的(尤其是没有循环)。
首先,我们为坐标生成位移列表。我们正在寻找所有最近的邻居。在 2D 的例子中,是 9 个点(包括原点,在 3D 中是 27 个点,以此类推。我们需要能够在 x 定义的任意数量的维度上进行转换。这就是 itertools 派上用场的地方。
l = list(itertools.product([-1, 0, 1], repeat=Xint.shape[1]))
l=list(map(list, l))
l.remove([0] * Xint.shape[1])
这里发生的是——首先我们在 X 矩阵的水平维度上创建-1、0 和 1 的所有可能排列(在我们的例子 2 中,因为我们只有 2 个变量)。
这些是以元组的形式返回的,所以我们需要将它们转换成列表——这是第二行的工作。
最后一步——我们去掉零点漂移,因为它对我们没用。
结果如下:
[[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]]
现在,让 lD 作为我们的 D 参数的字符串表示长度,并且id作为我们试图寻找邻居的单个 id。我知道,使用 id 会更合理,但是 Python 有优先权,所以我们不得不用 ids 代替。
*nbrs = np.array(
[
list(
[
int(
''.join(
list(ids)[i * lD: (i + 1) * lD]
)
) for i in range(len(l[0]))
]
)
] * len(l)
) + np.array(l)*
好了,这里发生了很多事情,现在来分解一下:获取一个字符串列表——将它转换成组成它的字符列表。然后,我们获取列表中元素数量对应于 D 参数( lD )长度的部分,并使用 join 将它们粘合成字符串。完成后,我们再次将它们转换为整数值,这就给出了 X 矩阵中相应行的副本,也就是说,所有变量都对应于这个晶胞。然后,我们复制这个列表,复制的次数与我们试图达到的邻居数量一样多(T2 列表中重音的数量)。最后一步-将结果列表和应力列表转换为 numpy 数组,并将它们相加。这给了我们元素的总和,因此所有邻居的坐标。注意,这对于任意数量的变量都适用,所以这对于 n 维向量来说是很好的。当进入大量变量时,问题可能会出现,但我们现在不用担心这个。
最后,我们重复到 ids 的转换:
*nbrs = np.apply_along_axis(
''.join,
1,
np.char.zfill(
nbrs.astype(str),
lD
)
)*
瞧,我们有了邻居的身份证。剩下的就是快速检查我们以前没有访问过它们,并且它们确实属于被识别的树。
听着,妈,不要“循环”!!!
环境资源管理(Environmental Resources Management 的缩写)..实际上有一个列表理解,尽管它很短。但是,如果你找到了一种不用它的方法,请告诉我!
一旦我们数完树,我们差不多就完成了。我们所要做的就是将我们遗漏的单位细胞进行属性化,然后标记出相应的点。
来看图吧!
是时候将运行我们函数的结果与标准聚类方法进行比较了。如果你想回顾后者,这里有一个非常好的帖子,有一大堆——10 个!
事实上,我们将在我们的数据集上运行所有这些方法(除了光学方法,因为它是垃圾),然后将它们与这里描述的方法进行比较(我称之为 DenseTrees,因为我们正在使用树结构寻找高密度区域)。
只是给你一个快速的例子来运行它
加载模型:
*import sklearn
from sklearn.cluster import AffinityPropagation
model = AffinityPropagation(damping=0.9)*
并运行拟合:
*%%time
model.fit(X)*
第一行是获取执行时间。
最后一步
*ttf_norm['Affinity'] = model.predict(X)*
在我的笔记本电脑上,这种特殊的方法耗时最长——大约 21 秒。
其他人也一样。我对驱动它们的参数进行了一些调整,以获得最佳结果。就亲和力而言,这并没有多大帮助。
我必须强调的是,一些方法——k means(直线和迷你批次)、Spectral、Gaussian mixture、Agglomerative 和 Birch——都将聚类数作为输入,这在某种程度上违背了目的。在应用集群之前,您必须知道集群的数量。事实上,我们可以直接丢弃它们,因为它们对我们将要尝试和解决的任何有趣的问题都没有用。让我们把它们留在里面,只是为了练习。
策划:
可以看到 MeanShift,Birch,DBSCAN,Affinity 都表现很差。顺便说一句,DBSCAN 在获得正确的参数方面特别复杂,甚至到了这一步。高斯混合看起来是最好的。我们的 DenseTrees 方法与 KMeans 方法表现相当。如果我们改变第二条路径的属性,我们可能会得到和 GM 一样好的结果(事实上我们可以使用 GM 进行最终的属性)。顺便说一句,高斯混合比 DenseTrees 快 6 倍,所以也有一些改进的空间(我们仍然用 300 毫秒做得很好——第六快)。这里的主要结论是——我们已经超越了每一个没有将聚类数作为输入的算法,而且我们离最好的算法也不远了。不算太寒酸。
最后一个音符
我确实提到了从栅格文件中识别建筑物的问题,这是它的灵感来源,所以不展示该算法在数据集上的表现是很遗憾的。
只是给你一些背景。经过一些过滤和清理后,绘制成散点图的光栅文件如下所示:
给那些知道这是哪里的人额外的荣誉。
这些只是标绘在标准尺度上的点。任何低于 10 米的都被设置为零。你几乎可以看到我们在网里抓到了一些树。不幸的是,我们对此无能为力。至少现在是这样。这个正方形具有 2000×2000 的分辨率(总共 4mln 数据点),每个像素对应于 0.5m×0.5m 的正方形。我们必须非常细致地捕捉建筑之间的空隙,所以为了处理这个,我使用了 D=500 和 10%的容差。注意,这个临界值太大了,因为所有点都是均匀分布的。在我的笔记本电脑上,这花了大约 5 个小时来处理。不太好。最初为 2D 优化的算法花了大约半个小时,所以肯定有很大的改进空间。
该算法返回 247 个聚类。在这里,他们都是彩虹色的荣耀:
你可以看到,无论如何,我们在树木方面都很幸运——所有的灰点都被遗漏了。对于这个问题,不需要额外的属性步骤,这就是为什么我把它从主函数中去掉了。
今天到此为止。期待大家的批评和建议。
暹罗网络的友好介绍
原文:https://towardsdatascience.com/a-friendly-introduction-to-siamese-networks-85ab17522942?source=collection_archive---------0-----------------------
你不总是需要大量的数据来训练你的模型,学习如何创建一个每类只有少量图像的模型
丽莎·阿尔格拉在 Unsplash 上的照片
在现代深度学习时代,神经网络几乎擅长每一项任务,但这些神经网络依赖于更多的数据才能表现良好。但是,对于某些问题,如人脸识别和签名验证,我们不能总是依赖于获得更多的数据,为了解决这类任务,我们有一种新型的神经网络架构,称为暹罗网络。
它仅使用少量图像来获得更好的预测。从很少的数据中学习的能力使得暹罗网络在最近几年更受欢迎。在本文中,我们将探讨它是什么以及如何使用 Pytorch 开发一个使用暹罗网络的签名验证系统。
什么是暹罗网!?
暹罗网用于图章
连体神经网络是一类神经网络架构,其中包含两个或更多相同的子网络。这里的‘相同’是指,它们具有相同的配置,具有相同的参数和权重。参数更新在两个子网络上都是镜像的。它用于通过比较其特征向量来发现输入的相似性,因此这些网络被用于许多应用中
传统上,神经网络学习预测多个类别。当我们需要向数据中添加/删除新的类时,这就带来了问题。在这种情况下,我们必须更新神经网络,并在整个数据集上重新训练它。此外,深度神经网络需要大量的数据来进行训练。另一方面,SNNs 学习相似性函数。因此,我们可以训练它来看看这两个图像是否相同(我们将在这里这样做)。这使我们能够对新的数据类别进行分类,而无需再次训练网络。
暹罗网络的利弊:
暹罗网络的主要优势是,
- 对类别不平衡更鲁棒:在一次性学习的帮助下,给定每个类别的一些图像足以使暹罗网络在将来识别这些图像
- 对于具有最佳分类器的集成来说很好:鉴于其学习机制与分类有些不同,使用分类器对其进行简单平均可以比平均 2 个相关监督模型(例如 GBM & RF 分类器)做得更好
- 从语义相似性中学习: Siamese 侧重于学习将相同的类/概念紧密放置在一起的嵌入(在更深的层中)。于是,可以学习的语义相似度。
连体网络的缺点是,
- 比普通网络需要更多的训练时间:由于暹罗网络涉及二次对学习(查看所有可用信息),它比普通分类类型的学习(逐点学习)要慢
- 不输出概率:由于训练涉及成对学习,它不会输出预测的概率,而是输出与每个类的距离
暹罗网络中使用的损失函数:
对比缺失,作者创造的形象
由于连体网络的训练通常涉及成对学习,所以在这种情况下不能使用交叉熵损失,主要有两个损失函数主要用于训练这些连体网络,它们是
三重损失是一个损失函数,其中基线(锚)输入与正(真)输入和负(假)输入进行比较。从基线(锚)输入到正(真)输入的距离最小,从基线(锚)输入到负(假)输入的距离最大。
在上面的等式中,α是用于“拉伸”三元组中相似和不相似对之间的距离差异的余量项,fa、fp、fn 是锚定图像、正图像和负图像的特征嵌入。
在训练过程中,将图像三元组(锚图像、负图像、正图像)(锚图像、负图像、正图像)作为单个样本输入到模型中。这背后的想法是锚和正图像之间的距离应该小于锚和负图像之间的距离。
对比损失:是目前使用频率很高的一种流行损失函数,它是一种 基于距离的损失 而不是更为传统的 误差预测损失 。这种损失用于学习嵌入,其中两个相似的点具有低的欧几里德距离,而两个不相似的点具有大的欧几里德距离。
我们将 Dw 定义为欧几里德距离:
Gw 是我们的网络对一幅图像的输出。
使用暹罗网络进行签名验证:
用于签名验证的暹罗网络,图片由作者创建
由于连体网络主要用于验证系统,如人脸识别、签名验证等…让我们在 Pytorch 上实现一个使用连体神经网络的签名验证系统
数据集和数据集预处理:
ICDAR 数据集中的签名,图像由作者创建
我们将使用 ICDAR 2011 数据集,该数据集由荷兰用户的签名(包括真品和伪造品)组成,数据集本身被分为序列和文件夹,在每个文件夹中,它由分为真品和伪造品的用户文件夹组成,数据集的标签也以 CSV 文件的形式提供,您可以从这里下载数据集
现在,要将这些原始数据输入到我们的神经网络中,我们必须将所有图像转换为张量,并将 CSV 文件中的标签添加到图像中,为此,我们可以使用 Pytorch 中的自定义数据集类,下面是我们的完整代码
现在,在预处理数据集之后,在 PyTorch 中,我们必须使用 Dataloader 类加载数据集,我们将使用 transforms 函数将图像大小减少到 105 像素的高度和宽度,以便进行计算
神经网络架构:
现在,让我们在 Pytorch 中创建一个神经网络,我们将使用类似的神经网络架构,如 Signet 论文中所述
在上面的代码中,我们创建了如下的网络,第一个卷积层使用 96 个大小为 11 的核过滤 105*105 的输入签名图像,步长为 1 个像素。第二卷积层将第一卷积层的(响应归一化和汇集的)输出作为输入,并用 256 个大小为 5 的核对其进行滤波。第三和第四卷积层彼此连接,没有任何层的汇集或标准化的介入。第三层具有 384 个大小为 3 的内核,连接到第二卷积层的(归一化、汇集和丢弃)输出。第四卷积层具有 256 个大小为 3 的核。这导致神经网络对于较小的感受域学习较少的较低级特征,而对于较高级或更抽象的特征学习更多的特征。第一全连接层具有 1024 个神经元,而第二全连接层具有 128 个神经元。这表明来自 SigNet 每一侧的最高学习特征向量具有等于 128 的维度,那么另一个网络在哪里呢?
由于两个网络的权重被限制为相同,所以我们使用一个模型并连续输入两个图像。之后,我们使用两幅图像计算损失值,然后反向传播。这节省了大量内存,也提高了计算效率。
损失函数:
对于这个任务,我们将使用对比损失,其学习嵌入,其中两个相似的点具有低的欧几里德距离,而两个不相似的点具有大的欧几里德距离,在 Pytorch 中,对比损失的实现将如下:
训练网络:
暹罗网络的训练过程如下:
- 初始化网络、损失函数和优化器(我们将在这个项目中使用 Adam)
- 通过网络传递图像对的第一个图像。
- 通过网络传递图像对的第二个图像。
- 使用来自第一和第二图像的输出来计算损失。
- 反向传播损失以计算我们模型的梯度。
- 使用优化器更新权重
- 保存模型
该模型在 google colab 上训练了一个小时的 20 个时期,损失随时间变化的图表如下所示。
一段时间内的损耗图
测试模型:
现在让我们在测试数据集上测试我们的签名验证系统,
- 使用 Pytorch 中的 DataLoader 类加载测试数据集
- 传递图像对和标签
- 找出图像之间的欧几里德距离
- 基于欧几里得距离打印输出
预测如下:
结论:
在本文中,我们讨论了暹罗网络与普通深度学习网络的不同之处,并使用暹罗网络实现了一个签名验证系统,您可以在这里找到完整的代码
参考资料:
https://hacker noon . com/one-shot-learning-with-siamese-networks-in-py torch-8d daab 10340 e
[## SigNet:用于独立于书写者的离线签名验证的卷积暹罗网络
离线签名验证是生物特征识别和文档取证中最具挑战性的任务之一。不像其他人…
arxiv.org](https://arxiv.org/abs/1707.02131)
https://innovationincubator . com/siamese-neural-network-with-py torch-code-example/
[## PyTorch 中与暹罗网络的面部相似性
PyTorch 中用连体网络实现人脸相似性
hackernoon.com](https://hackernoon.com/facial-similarity-with-siamese-networks-in-pytorch-9642aa9db2f7)
https://Neptune . ai/blog/content-based-image-retrieval-with-siamese-networks
文本聚类的友好介绍
原文:https://towardsdatascience.com/a-friendly-introduction-to-text-clustering-fa996bcefd04?source=collection_archive---------0-----------------------
用于聚类单词和文档的大量方法乍一看似乎令人不知所措,但是让我们仔细看看。
本文涉及的主题包括 k-means、brown 聚类、tf-idf、主题模型和潜在 Dirichlet 分配(也称为 LDA)。
聚集,还是不聚集
聚类是数据科学中最大的主题之一,如此之大,以至于你会很容易地找到大量的书籍讨论它的每一个细节。文本聚类子课题也不例外。因此,本文无法提供详尽的概述,但它涵盖了主要方面。话虽如此,让我们从什么是集群和什么不是集群的共同点开始。
你刚刚按簇滚动了!
事实上,集群只不过是包含相似对象的组。聚类是用于将对象分成这些组的过程。
集群中的对象应该尽可能相似。不同集群中的对象应该尽可能不同。但是谁来定义“相似”的含义呢?我们将在以后的某个时刻回到这个问题上来。
现在,你可能听说过分类。在对对象进行分类时,您也可以将它们归入不同的组,但是有一些重要的区别。分类意味着将新的、以前未见过的对象根据已知的对象分组,即所谓的训练数据。这意味着我们有可靠的东西来比较新对象——当集群化时,我们从空白画布开始:所有对象都是新的!因此,我们称分类为监督的方法,聚类为非监督的方法。
这也意味着对于分类来说,正确的组数是已知的,而在聚类中没有这样的数目。请注意,它不仅仅是未知的——它根本就不存在。根据我们的目的选择合适数量的簇是由我们决定的。很多时候,这意味着尝试几个,然后选择一个提供最好结果的。
聚类方法的种类
在我们深入研究具体的聚类算法之前,让我们首先建立一些描述和区分它们的方法。有几种方法可以做到这一点:
在硬 聚类中,每个对象都属于恰好一个聚类。在软 聚类中,一个对象可以属于一个或多个聚类。成员资格可以是部分的,这意味着对象可能属于某些集群多于属于其他集群。
在分层聚类中,聚类以分层的方式迭代组合,最终在一个根中结束(或者超级聚类,如果你愿意的话)。您也可以将分层聚类视为一棵二叉树。所有不遵循这一原则的聚类方法都可以简单地描述为扁平聚类,但有时也被称为非分层或划分。通过在您选择的级别上水平“切割”树,您总是可以将分层聚类转换为平面聚类。
层次聚类的树形图称为树状图。在较低层次上连接的对象比在树的较高层次上连接的对象更相似。
分层方法可以进一步分为两个子类别。凝聚(“自下而上”)方法首先将每个对象放入自己的集群,然后不断统一它们。分割(“自顶向下”)方法则相反:它们从根开始,一直分割下去,直到只剩下单个对象。
聚类过程
应该很清楚聚类过程是什么样子的吧?你得到一些数据,应用你选择的聚类算法,然后,你就完成了!虽然这在理论上是可能的,但通常不是这样。尤其是在处理文本时,在聚类之前和之后,您必须采取几个步骤。在现实中,文本聚类的过程往往是混乱的,并且有许多不成功的尝试。但是,如果您试图以理想化的线性方式绘制它,它可能看起来像这样:
相当多的额外步骤,对吗?不要担心——无论如何,凭直觉你可能已经做对了。但是,单独考虑每一步是有帮助的,并且要记住可能存在解决问题的备选方案。
聚类单词
恭喜你!你已经通过了介绍。在接下来的几个段落中,我们将看看单词的聚类方法。让我们来看看下面这组照片:
对我们来说,哪些单词应该放在一起马上就变得很明显了。显然应该有一个包含单词土豚和斑马的动物集群,以及一个包含副词上的和下的的集群。但是对于一台计算机来说同样明显吗?
当谈到意思相近的单词时,你经常会读到语言学中的分布假设。这一假设认为,具有相似意义的词会出现在相似的语境中。你可以说“这个盒子在架子上”,而且还“盒子是在下面的架子上”并且仍然产生一个有意义的句子。上的和下的在一定程度上可以互换。
当创建单词嵌入时,利用该假设。单词嵌入将词汇表中的每个单词映射到一个 n 维向量空间。具有相似上下文的单词将大致出现在向量空间的相同区域。其中一个嵌入是由韦斯顿,拉特&科洛伯特在 2008 年开发的。你可以在这里看到单词 vectors 的一个有趣片段(用 t-SNE 减少到二维):
来源:约瑟夫·图瑞安,看全图这里
请注意月份、姓名和地点是如何整齐地组合在一起的。这将在下一步对它们进行聚类时派上用场。要了解更多关于单词嵌入到底是如何创建的以及它们的有趣特性,请看一下由 Hunter Heidenreich 撰写的这篇文章。它还包括关于更高级的单词嵌入的信息,如 word2vec 。
k 均值
我们现在来看看最著名的基于向量的聚类算法:k-means。k-means 所做的是为每个对象返回 k 个可能聚类之一的聚类分配。概括一下我们之前学到的,这是一种硬的、平坦的聚类方法。让我们看看 k-means 过程是什么样子的:
来源: Chire ,via 维基百科
K-means 在向量空间中分配 k 个随机点作为 k 个聚类的初始虚拟平均值。然后,它将每个数据点分配给最近的聚类平均值。接下来,重新计算每个聚类的实际平均值。基于均值的偏移,数据点被重新分配。这个过程不断重复,直到聚类的均值停止移动。
为了更直观、更形象地理解 k-means 的功能,请观看 Josh Starmer 制作的短片。
k-意味着它不是唯一的基于向量的聚类方法。其他经常使用的方法包括 DBSCAN ,这是一种有利于人口密集的聚类的方法,以及期望最大化(EM),这是一种假设每个聚类的潜在概率分布的方法。
棕色聚类
也有用于聚类单词的方法,这些方法不要求单词已经作为向量可用。可能引用最多的这种技术是布朗聚类,由布朗等人于 1992 年提出(与布朗文集无关,该文集以罗德岛布朗大学命名)。
布朗聚类是一种层次聚类方法。如果在树中的正确位置切割,还会产生漂亮、扁平的簇,如下所示:
改编自:布朗等人(1992)
您还可以查看小的子树,找到包含接近同义词的词对的簇,如评估和评估或对话和讨论。
改编自:布朗等人(1992)
这是如何实现的?同样,这种方法依赖于分布假设。它引入了一个质量函数,该函数描述了周围的上下文单词如何预测当前聚类中单词的出现(所谓的互信息)。然后,它遵循以下过程:
- 通过将每个单词分配给它自己的唯一的簇来初始化。
- 直到只剩下一个聚类(根):合并产生的并集具有最佳质量函数值的两个聚类。
这就是为什么评估和考核合并这么早的原因。由于两者出现在极其相似的上下文中,上面的质量函数仍然提供了一个非常好的值。我们从逐渐统一的单元素簇开始的事实意味着这个方法是凝聚的。
布朗聚类沿用至今!在 Owoputi 等人(2013)的出版物中,布朗聚类被用于在在线会话语言中寻找新的词簇,这些词应该有自己的词性标签。结果有趣而准确:
来源: Owoputi 等人(2013 年)
如果你有兴趣了解更多关于布朗聚类是如何工作的,我强烈推荐你观看哥伦比亚大学迈克尔·科林斯的讲座。
虽然这一段总结了我们关于单词聚类的部分,但是还有很多方法没有在本文中讨论。一种非常有前途和有效的单词聚类方法是基于图的聚类,也称为谱聚类。使用的方法包括基于最小生成树的聚类、马尔可夫链聚类和汉语耳语。
聚类文档
一般来说,聚类文档也可以通过查看矢量格式的每个文档来完成。但是文档很少有上下文。你可以想象在一个整洁的书架上,一本书挨着其他书,但通常这不是大量数字文档(所谓的语料库)的样子。
对文档进行矢量化的最快(也可以说是最简单的)方法是给字典中的每个单词指定自己的向量维数,然后统计每个单词和每个文档的出现次数。这种不考虑词序的方式被称为单词袋方法。《牛津英语词典》包含 30 多万个主要词条,还不包括同形异义词。这是一个很大的维度,其中大部分可能会得到零值(或者你多久会读到一次无精打采的、 peristeronic 和业余爱好者?).
在一定程度上,您可以通过删除文档集合(语料库)中不使用的所有单词维度来抵消这一点,但最终仍会有很多维度。如果您突然看到一个新文档包含一个以前没有使用过的单词,您将不得不更新每一个文档向量,添加这个新的维度和它的零值。因此,为了简单起见,让我们假设我们的文档集合没有增长。
tf-idf
看看下面的玩具示例,它只包含两个短文档 d1 和 d2 以及生成的单词向量包:
你可以看到,不太具体的词,如 I 和 love ,与实际识别两个文档的词,如 pizza 和chocolate获得相同的值。抵消这种行为的一种方法是使用 tf-idf ,这是一种数字统计,用作加权因子来抑制不太重要的单词的影响。
Tf-idf 代表术语频率和逆文档频率,这两个因子用于加权。词频就是一个单词在特定文档中出现的次数。如果我们的文档是“我爱巧克力和巧克力爱我”,单词爱的术语频率将是两个。该值通常通过除以给定文档中的最高词频来归一化,从而得到介于 0(对于文档中未出现的单词)和 1(对于文档中最频繁出现的单词)之间的词频值。术语频率是按单词和文档计算的。
另一方面,逆文档频率仅按单词计算。它表示一个单词在整个语料库中出现的频率。这个值通过取它的对数来求逆。还记得我们想要摆脱的那个无处不在的单词吗?由于一的对数是零,它的影响就完全消除了。
基于这些公式,我们为我们的玩具示例获得以下值:
看最后两列,我们看到只有最相关的词得到高 tf-idf 值。所谓的停用词,意思是在我们的文档集合中普遍存在的词,得到的值等于或接近于 0。
接收到的 tf-idf 向量仍然与原始单词包向量一样高维。因此,诸如潜在语义索引(LSI)之类的降维技术经常被用来使它们更容易处理。k-means、DBSCAN 和 EM 等算法也可以用于文档向量,就像前面描述的单词聚类一样。可能的距离度量包括欧几里德距离和余弦距离。
潜在狄利克雷分配
通常,仅仅拥有文档簇是不够的。
主题建模算法是一种统计方法,通过分析原文的词语来发现贯穿其中的主题,这些主题之间是如何相互联系的,以及它们是如何随时间变化的( Blei,2012 )。
所有主题模型都基于相同的基本假设:
- 每个文件都包含一个分布在主题上的文件,并且
- 每个主题由一个单词分布组成。
除了概率潜在语义分析(pLSA)等其他主题模型之外,潜在狄利克雷分配 (LDA)是最著名和使用最广泛的一种。只要看看它的名字,我们就已经可以了解它的工作原理了。
潜在是指隐藏变量,狄利克雷分布是相对于其他概率分布的概率分布,分配是指基于两者分配一些值。为了更好地理解这三个方面是如何发挥作用的,让我们看看 LDA 给出了什么结果。下面的主题是从《科学》杂志的 17000 篇文章中选取的 100 个主题。
改编自:博莱(2012)
你应该如何解读这些话题?一个题目是单词的概率分布。有些词在一个话题中出现的可能性比较大,有些则比较少。上面你看到的是每个话题最常出现的 10 个词,不包括停用词。值得注意的是,这些主题实际上没有名字遗传学或进化论。这些只是我们人类用来概括这个话题的术语。尽量把题目看成了字概率分布 1 或者字概率分布 23 而不是。
但这并不是 LDA 提供给我们的全部。此外,它告诉我们每个文档中出现了哪些主题以及出现的百分比。例如,一篇关于可以检测你 DNA 中特定疾病流行率的新设备的文章可能由 48% 疾病、31% 遗传学和 21% 计算机的主题组合组成。
为了理解我们如何让计算机知道什么是好的主题以及如何找到它们,我们将再次构建一个小的玩具示例。让我们假设我们的语料库词汇只包含几个表情符号。
该词汇表中可能的主题或单词概率分布可能如下所示:
作为人类,我们可能会把这些话题归类为食物、微笑和动物。我们假设题目给定了。为了理解 LDA 所做的基本假设,让我们看看文档的生成过程。即使它们看起来不太现实,作者也会采取以下步骤:
- 选择您想要在文本中写多少个单词。
- 选择你的文章应该涵盖的混合主题。
- 对于文档中的每个单词:
- 从混合物中引出一个单词应该与之相关的主题
- 从所选主题中画出一个单词的单词分布
基于这些步骤,可能会产生以下文档:
请注意,尽管披萨表情符号不太可能来自主题 3,但它仍然有可能源自主题 3。既然我们已经得到了想要的结果,我们只需要找到一种方法来逆转这个过程。只有?事实上,我们面临着这样的情况:
理论上,我们可以让我们的计算机尝试每一种可能的单词和主题的组合。除了这可能要花很长时间这一事实之外,我们最终如何知道哪个组合有意义,哪个没有意义呢?为此,狄利克雷分布派上了用场。不要像上图那样绘制分布,让我们在各自的位置上绘制主题单纯形的文档。
我们还可以从紧挨着这个的语料库中提取许多其他文档。它可能看起来像这样:
或者,如果我们事先选择了其他主题,像这样:
在第一种变体中,文档清晰可辨,并表示不同的主题,而在第二种变体中,文档或多或少都是相似的。这里选择的主题无法以有意义的方式分隔文档。这两种可能的文档分布无非是两种不同的狄利克雷分布!这意味着我们已经找到了一种方法来描述“好的”主题分布是什么样子的!
同样的道理也适用于话题中的词语。好的主题在单词上有不同的分布,而坏的主题和其他主题有相同的单词。Dirichlet 分布的这两种表现在 LDA 模型中由两个超参数α和β描述。一般来说,您希望将狄利克雷参数保持在 1 以下。在大卫莱特伊尔制作的这个精彩的动画中,看看不同的价值观是如何改变分布的。
来源:大卫·莱蒂尔
好的单词和主题分布通常通过使用诸如折叠吉布斯抽样或期望传播的技术来近似。这两种方法都迭代地改进了随机初始化的单词和主题分布。然而,可能永远也找不到“完美”的分配。
如果你想试试 LDA 对你选择的数据集交互地做了什么,点击你的方式通过这个伟大的浏览器内演示,作者是 David Mimno。
还记得简介中介绍的集群流程图吗?尤其是最后一步叫终评?使用聚类方法时,您应该始终记住,即使某个特定的模型可能导致最小的矢量均值移动或最低的概率分布值,这并不意味着它是“正确的”。有许多数据集 k-means 不能正确聚类,甚至 LDA 也可以产生对人类没有任何意义的主题。
简而言之:所有的模型都是错的,但有些是有用的。祝你短信群发愉快,保重!
资源
Anastasiu,D. C .,Tagarelli,a .,Karypis,G. (2014 年)。文档聚类:下一个前沿。在 Aggarwal,C. C .和 Reddy,C. K .(编辑)、数据聚类、算法与应用(第 305–338 页)。明尼阿波利斯:查普曼&大厅。
布莱博士,Ng,A. Y .,&约旦医学研究所(2003 年)。潜在狄利克雷分配。《机器学习研究杂志》,3(1 月),993–1022。
布莱医学博士(2012 年)。概率主题模型:调查为管理大型文档档案提供解决方案的一套算法。ACM 的通信,55 (4),77–84。
布朗,P. F .,彼得拉,V. J .,苏扎,P. V .,赖,J. C .,&默瑟,R. L. (1992)。自然语言的基于类的 n 元模型。计算语言学,18,467–479。
费尔德曼和桑格(2007 年)。文本挖掘手册。分析非结构化数据的高级方法。剑桥:剑桥大学出版社。
米科洛夫(2014 年)。句子和文档的分布式表示。第 31 届机器学习国际会议论文集,PMLR 32 (2),1188–1196。
c .曼宁和 h .舒策(1999 年)。聚类,统计自然语言处理基础。马萨诸塞州剑桥。:麻省理工学院出版社。
奥沃普提、奥康纳、戴尔、金佩尔、施耐德和史密斯(2013 年)。改进的在线会话文本词性标注。人类语言技术:计算语言学协会北美分会会议,会议录,2013 年 6 月 9-14 日,美国佐治亚州亚特兰大(第 380-390 页)。
全栈机器学习项目
原文:https://towardsdatascience.com/a-full-stack-machine-learning-project-7ab80e46e1c4?source=collection_archive---------39-----------------------
从模型创建到部署—一个端到端的机器学习项目
亚历山大·奈特在 Unsplash 上拍照
当我还是个孩子的时候,我曾经痴迷于哈利波特(书,而不是电影)。我是赫敏·格兰杰的超级粉丝,并且被西弗勒斯·斯内普这个角色深深吸引。
所以当我发现一个 MBTI 性格预测数据集时,我决定没有比 创建一个哈利波特性格预测模型更好的使用它的方法了。
这是最终产品的样子:
如您所见,该接口接受一些文本作为输入,调用后端模型,并生成一个预测。
为什么要创建前端接口?
作为(有抱负的)数据科学家,我们的重点主要是数据和构建模型。我们的大多数机器学习项目都存在于一个精心格式化的 Jupyter 笔记本中,并且可能会永远留在那里。
然而,创造一个人们可以互动的产品是一项重要的技能。
招聘人员每天要查看数百份简历。
他们会有时间查阅你所有的博客文章,阅读你所有的代码,来看看你的项目是关于什么的吗?
大概不会。
然而,如果你创造了一个他们可以互动并实际使用的环境,他们会对你的项目更感兴趣。
现在,我将回顾我完成这个机器学习项目的所有步骤。
构建和训练模型
法斯泰
我使用这个 MBTI 人格类型数据集来创建和训练模型。我使用了 fastai 库来做这件事。
从头开始构建分类器来处理文本数据需要花费大量时间,并且需要大量的数据清理和预处理。相反,我使用了 fastai 的文本模块中预先训练好的模型。
如果你想创建一个类似的文本分类模型,我建议遵循他们的指南这里。
您需要做的就是安装所需的库,并使用您的数据集来训练预先存在的模型。
我使用 Google Colab 在我的数据集上训练模型,因为它允许用户免费连接到 GPU 后端。这使得训练深度学习模型的速度快了很多。
如果你以前没有用过 Colab,这里的是入门指南。
在 Colab 中创建和训练了模型之后,我将其导出到我的 Jupyter 笔记本中,并使用它用随机句子进行预测。
做预测
我得到的预测是张量:
pred = learn.predict('Happiness is not something ready-made.')
我必须将它们转换成字符串:
print(str(pred[0]))
输出:“ENFJ”
现在,剩下要做的就是创建一个前端界面,并为每种性格类型输出哈利波特角色的名字。
前端接口
Dash 应用
Dash 应用程序是一种软件,允许您在工作环境中创建前端界面。它易于使用,无需了解 HTML、CSS 和 JavaScript 等前端语言。
作为数据科学家,我们的大部分工作都在 Jupyter 笔记本上完成。这是我们最熟悉的地方,用不同的扩展名创建单独的文件可能很耗时。
解决办法?
JupyterDash !
JupyterDash 是一个库,允许你直接从你的 Jupyter 笔记本上创建 Dash 应用程序。
它使用起来非常简单,下面是一些帮助您入门的代码:
# imports
from jupyter_dash import JupyterDash
import dash
from dash.dependencies import Input, Output, State
import dash_core_components as dcc
import dash_html_components as html
from dash import no_updateexternal_stylesheets = ['[https://codepen.io/chriddyp/pen/bWLwgP.css'](https://codepen.io/chriddyp/pen/bWLwgP.css')]app = JupyterDash(__name__, external_stylesheets=external_stylesheets)app.layout = html.Div([
html.H1(children="Personality prediction: Which Harry Potter character are you?", style={'textAlign': 'center'}),
html.Img(src='data:image/png;base64,{}'.format(encoded_image.decode()),style={'height':'350px','width':'550px'}),
dcc.Markdown('''
###### Step 1: Type a sentence that you feel represents your personality.
###### Step 2: Click submit
###### Step 3: Wait for your prediction to appear!
''',style={'textAlign': 'center'}),
dcc.Input(id='username',type='text'),
html.Button(id='submit-button', type='submit', children='Submit'),
html.Div(id='output_div')
],style={'textAlign': 'center','justify':'center','align':'middle','verticalAlign':'middle'})learn = load_learner("C:/Users/natassha selvaraj/Desktop")[@app](http://twitter.com/app).callback(Output('output_div', 'children'),
[Input('submit-button', 'n_clicks')],
[State('username', 'value')],
)
def update_output(clicks, input_value):
answ = learn.predict(input_value)
if clicks is not None:
if input_value is not None:
if(str(answ[0])=='ISTP'):
return(html.H2(children='Harry Potter (ISTP)', style={'textAlign': 'center'}))
elif(str(answ[0])=='ENFP'):
return(html.H2(children='Ron Weasley (ENFP)', style={'textAlign': 'center'}))
elif(str(answ[0])=='INTP'):
return(html.H2(children='Hermione Granger (INTP)', style={'textAlign': 'center'}))
elif(str(answ[0])=='ENFJ'):
return(html.H2(children='Albus Dumbledore (ENFJ)', style={'textAlign': 'center'}))
elif(str(answ[0])=='ESTP'):
return(html.H2(children='Ginny Weasley (ESTP)', style={'textAlign': 'center'}))
elif(str(answ[0])=='ISFJ'):
return(html.H2(children='Neville Longbottom (ISFJ)', style={'textAlign': 'center'}))
elif(str(answ[0])=='INFP'):
return(html.H2(children='Luna Lovegood (INFP)', style={'textAlign': 'center'}))
elif(str(answ[0])=='ESFP'):
return(html.H2(children='Fred and George Weasley (ESFP)', style={'textAlign': 'center'}))
elif(str(answ[0])=='ISFP'):
return(html.H2(children='Rubeus Hagrid (ISFP)', style={'textAlign': 'center'}))
elif(str(answ[0])=='ISTJ'):
return(html.H2(children='Severus Snape (ISTJ)', style={'textAlign': 'center'}))
elif(str(answ[0])=='ENTJ'):
return(html.H2(children='Minerva McGonagall (ENTJ)', style={'textAlign': 'center'}))
elif(str(answ[0])=='ESFJ'):
return(html.H2(children='Fleur Delacour (ESFJ)', style={'textAlign': 'center'}))
elif(str(answ[0])=='INFJ'):
return(html.H2(children='Remus Lupin (INFJ)', style={'textAlign': 'center'}))
return('Please enter a valid sentence')
app.run_server(mode='external')
输出单元格如下所示:
只需点击网址,您就会发现您的 Dash 应用程序正在运行:
如果你想要更深入的 Jupyter-Dash 教程,我推荐以下资源:
- 介绍 JupyterDash —中篇
- JupyterDash 教程 — YouTube 视频
- 在 Jupyter 中设置 Dash Plotly—YouTube 视频
部署
现在,您的 Dash 应用程序正在本地服务器上运行。您需要将它托管在某个地方,以便其他人能够访问它。
一个受欢迎的选择是 Heroku。Heroku 允许你直接从远程服务器托管你的应用程序。你不需要支付托管费用,而且设置非常快捷,易于操作。这里的是用 Heroku 部署你的应用的指南。
对于这个项目,我用了 n grok 。Ngrok 是一个应用程序,它允许您以最少的努力将开发服务器公开给 Internet。
它通常用于在部署之前测试站点,而不是实际托管 web 应用程序。此外,如果您使用免费层,URL 可能会在您每次运行应用程序时发生变化。
然而,ngrok 非常容易设置,如果你想与朋友或潜在雇主分享一些快速应用程序或仪表板,它非常棒。
以下是使用 ngrok 的方法:
! pip install pyngrok
然后,访问他们的网站并登录(或者注册,如果你是第一次的话)。
您将会看到这样一个页面,其中第 2 个标记是:
复制令牌。在您的笔记本中运行以下代码行,并在“xxxxx”处插入令牌:
! ngrok authtoken xxxxxx
添加以下代码行:
from pyngrok import ngrok# Open a HTTP tunnel on the default port 80
public_url = ngrok.connect(port='8050')
print(public_url)
复制粘贴出现在你的浏览器中的 URL,你的网站将会运行!
这里的是我在 ngrok 上部署的 Dash app(加载需要一些时间)。
这里的是一个关于 ngrok 的综合视频教程。
本文到此为止!感谢阅读:)
永远不要停止学习。生活从不停止教导。
对抗性机器学习的博弈论方法
原文:https://towardsdatascience.com/a-game-theoretical-approach-for-adversarial-machine-learning-7523914819d5?source=collection_archive---------29-----------------------
如何运用博弈论解决对抗性风险?
人工智能近年来取得了巨大的成功,因为它为我们提供了强大的算法,这些算法使用大型数据库进行准确的预测或分类。它们越来越多地用于不同的目的,包括高风险的目的。
然而,他们不是绝对可靠的。
事实上,这些算法中的大多数都是根据数据训练的,这些数据可以被试图误导它犯错误的对手故意操纵。
让我们举一个简单的例子:垃圾邮件检测。起初,朴素贝叶斯等标准分类器在准确性方面效率极高。然而,垃圾邮件制造者很快学会了如何通过改变同义词来愚弄他们,并添加更多的“非垃圾邮件”世界。因此,垃圾邮件过滤器被改变来检测这些伎俩。但是垃圾邮件发送者用新的来回应。因此,这就导致了防守者和进攻者之间的无休止的博弈,直到达到均衡状态。
在这种情况下,博弈论可能非常有用,因为它提供了在防御和攻击策略方面对防御者的行为和对手的行为进行建模所需的数学工具。
更具体地说,基于博弈论的模型使我们能够考虑:
- ****攻击者在适应分类器的成本和他从攻击中获得的收益之间做出的权衡。
- ****防御方在正确攻击检测的好处和错误警报的代价之间进行权衡。
因此,基于博弈论的模型可以确定需要什么样的合适的策略来减少防守方在对抗性攻击中的损失。
垃圾邮件过滤并不是这些模型能够带来有价值信息的唯一案例。这个视角可以用来描述许多其他风险更高的情况:计算机入侵检测、欺诈检测、空中监视。
在这篇文章中,我将与你分享我关于如何将博弈论用于对抗性机器学习的的关键发现。****
阅读本文后,您将了解到:
- 博弈论如何应用于机器学习?
- 博弈论如何帮助解决对抗性学习问题?
- 如何让你的机器学习算法对对抗性攻击具有鲁棒性?
基于博弈论方法的一个例子
先说一个简单的例子:垃圾邮件检测。****
以下部分描述了 W. Liu 和 S. Chawal 在论文中为对抗性学习开发的博弈论模型。
一般设置
它可以被建模为在垃圾邮件发送者(S)** 和防御者(D) 之间的双人游戏。**
- ****垃圾邮件发送者可以选择 1) 通过改变垃圾邮件并让它们通过垃圾邮件过滤器来攻击分类器,或者 2) 在知道一些垃圾邮件可能通过的情况下不进行攻击。
- ****防御方可以选择 1) 重新训练分类器,以保持较低的误分类率,或者选择 2) 不重新训练分类器,尽管误分类的垃圾邮件可能会增加。
我们将假设垃圾邮件发送者将是第一个采取行动的人。
有 4 种可能的结果,如下图所示。可以将每个场景与两个玩家的收益相关联,以反映最终结果的相对排名。
例如,场景 2** 对防御者来说是最坏的场景,对垃圾邮件发送者来说是最好的场景,因为他对未经过训练的分类器的攻击将导致大量错误分类的垃圾邮件。**
垃圾邮件制造者和防御者之间的博弈树
模型定义
这种情况可以建模为一个 Stackelberg 博弈,即一个顺序博弈,其中有一个领导者(这里是垃圾邮件发送者)和一个跟随者(防守者 D)。
Stackelberg 博弈 通常用于模拟存在等级竞争的市场中理性主体之间的战略互动。
在这种情况下,每个玩家通过分别为 S 和 D 从一组可能的动作 U 和 V 中选择一个动作来对另一个玩家的动作做出反应。假设这些集合是有界的和凸的。
每个结果都与一个收益函数 Js、和 Jd 相关联。** 收益函数 Ji 是两次可微映射 Ji(U,V) → R 其中 R 是反应。**
因此,有可能将参与人 I 的反应 Ri 预期为使其收益最大化的反应,即:
此外,第一个采取行动的人可以预测跟随者会如何理性反应,并在他的第一个决定中考虑到这一点。这就是所谓的倒推或倒推。
这意味着垃圾邮件发送者的第一个行动是解决下面的优化问题:
因此,防守者会选择最优解:
这个解(u,v)就是 Stackelberg 平衡。
请注意,它不同于纳什均衡,其中游戏的两个参与者同时行动,联立方程的解是 (0,0) ,即两个参与者都没有反应。****
模型设定
现在我们已经定义了一般的设置,我们仍然需要确定在一个分类问题的特殊情况下玩家的收益函数。
为了简化,我们首先只考虑一个属性。然后可以很容易地推广到多个属性,假设它们是条件独立的,给定它们的类标签。
一、选手招式的影响是什么?
让我们定义以下分布:
- P(μ',σ) :垃圾邮件分布
- Q (μ,σ) :非垃圾邮件的分布
用 μ' < μ,因为非垃圾邮件比垃圾邮件多
对手通过移动μ’到μ’+u(即朝向 μ )进行攻击。防守方的反应是将边界从 1/2 ( μ'+μ') 移动到(也向 μ 移动)****
第二,玩家的收益是什么?
为了评估一个变换 u 对数据的重要性,可以使用kull back–lei bler 散度 KLD (也叫相对熵)。它衡量一个概率分布如何不同于另一个参考概率分布。
垃圾邮件发送者的收益:因为他的目标是增加错误分类的垃圾邮件的数量,所以他的收益可以表示如下:
其中 FNR 是假阴性率的增加。因此,α代表成本损失的强度。
防守者的收益:由于他的目标是提高分类的准确性,他的收益可以表示如下:
其中 TPR 和 TNR 代表真实正利率和真实负利率的增加。因此,β控制重新训练分类器的成本的强度。
在这种情况下,下面的等式可以使用 遗传算法 来求解:
论文的作者应用这种方法在合成数据和真实数据之间寻找平衡。根据生成攻击和重新训练分类器(通过α和β建模)所产生的成本的重要性,他们找到不同的均衡。
基于博弈论的方法的其他变体
前一个例子依赖于一组假设:它模拟了一个游戏,其中攻击者和防御者相互竞争。假设攻击者首先采取行动。它还假设两个玩家都知道他们各自对手的收益和成本。
然而,这些假设并不总是成立的。幸运的是,存在大量基于博弈论方法的模型。它们可以分类如下。
零和与非零和游戏
在两人零和游戏中,进攻者的收益等于防守者损失的成本,反之亦然。这意味着玩家的效用总和为 0。这种假设可能非常悲观,因为防守方的效用损失可能不如对手的效用。
同时博弈与顺序博弈
在同时移动游戏中,玩家同时选择他们的策略,而不观察对方的策略。在顺序博弈中,他们一个接一个地选择他们的行动。
对抗性学习主要被建模为一个序列游戏,防守者是领导者。事实上,人们通常认为,一旦防御者选择了分类器,攻击者就可以观察它并决定自己的策略。
上一节描述的模型是少数几个认为攻击者在选择策略之前无法观察分类器的模型之一。
贝叶斯博弈
贝叶斯游戏模拟了一种游戏,其中玩家拥有关于其他玩家的不完全信息。这更有可能是因为防御者可能不知道生成敌对数据的确切成本,并且攻击者可能不知道防御者的确切分类成本。他们只相信这些成本。
著名经济学家约翰·C·海萨尼在博弈论方面做出了重大贡献,他特别是在不完全信息环境下,他这样描述贝叶斯博弈:
游戏中的每个玩家都与一组类型相关联,该组中的每种类型都对应于该玩家的一个可能的支付函数。除了游戏中的实际玩家,还有一个特殊的玩家叫做自然。大自然根据玩家类型空间的概率分布为每个玩家随机选择一个类型。所有玩家都知道这个概率分布(“常见先验假设”)。这种建模方法将不完全信息博弈转化为不完全信息博弈。
来源:维基百科
如何让对抗性学习变得健壮?
依赖于基于博弈论的框架的对抗性学习技术可能是相关的,因为它基于重新训练模型和生成攻击者所产生的收益和成本来模拟学习者和对手的行为。
但是,如果最初的模型已经能够抵御恶意攻击呢?
提高这种稳健性的最常见方法之一是对恶意数据进行建模,这些恶意数据可能是由对手事先生成的,并将其包含在训练阶段。
在本节中,我们将考虑用于生成对抗数据的 3 种主要技术:扰动技术、转移对抗实例、生成对抗网络(GAN)。
扰动技术
这个想法是为了产生可以被潜在对手利用的合成对抗数据。要做到这一点,有必要了解并预测对手是如何发起攻击的。
这些技术中的大多数依赖于向有效的示例添加少量的噪声或扰动。让我们来看看一些众所周知的例子:
BFGS
让我们注意一下:
- f:用于给定观察值 x 的分类器映射,包括 m 特征并返回类别标签
- **损失:关联的连续损失函数
- **居:微扰
如果攻击者的目标是生成一个被错误分类为 a1 的示例,他必须解决以下优化问题:
这可以通过执行线搜索来找到最小值 c > 0 来完成,对于该最小值 c > 0,以下问题的极小值 r 满足 f(x + r) = l :
请注意,对于深度神经网络等复杂模型,该优化问题没有封闭形式的解决方案。但是,可以使用迭代数值方法,这会使生成速度变慢。然而,它的成功率很高。
【快速梯度征法】
让我们注意一下:
- X :清洁观察
- ∇J(X,y): 模型损失函数相对于 X 的梯度
- ϵ: 参数*控制对抗性扰动的重要性*
该方法通过增加损失函数值来产生对抗性扰动,如下所示:
请注意,在梯度方向上增加一个扰动可以有意地改变观测结果,从而使模型对其进行错误分类。
与前一种方法相比,这种方法实现起来更快,计算上更可行。但其成功率较低。
Goodfellow 等人描述该方法的论文也导致了有趣的观察结果,例如:
- 使用干扰的方向比干扰的数量更能有效地创造对立的例子
- 用对立的例子训练分类器类似于分类器的正则化
迭代快速梯度符号
也可以以较小的步长多次应用 fgsm并对总数进行限幅,同时使干净样本和对立样本之间的失真低于ϵ.
转移抗辩示例
上面描述的大多数技术都假设攻击者知道所使用的模型。它们属于所谓的白盒攻击,与黑盒攻击相对。然而,在现实生活中,情况并非总是如此。
那么,攻击者通常采用哪些技术呢?
对手可以通过探测来重建模型,即向模型发送有效的和敌对的例子并观察输出。这使得他能够形成数据集,该数据集可用于训练替代模型。然后,可以使用白盒算法来实现对抗性示例的生成。
然而,在某些情况下,探测可能会受到被接受的查询的最大数量或对手产生的成本的限制。为了处理这个问题,对手可以生成对抗性的例子来欺骗分类器,并同时训练另一个模型。然后,他可以重复使用这些对立的例子来愚弄多个不同的分类器。
注意,使用通过模型生成的对立例子来欺骗黑盒模型是可能的,并且依赖于转移属性。
【乾坤】
生成敌对网络(GANs)完全依赖于一种博弈论方法。在这些模型中,扰动的例子从对手那里生成,同时用于训练学习者的模型,如下图所示。
生成对抗性网络框架,来源:文章来自 FreeCodeCamp ,Thalles Silva
如上图所示,学习者使用的函数称为鉴别器,而对手函数使用的函数称为生成器。
鉴别器和发生器通过零和游戏相互作用,因为它们都在寻求优化不同的和相反的目标函数,或损失函数。
在这种情况下,鉴别器和生成器分别不断调整它们的预测和数据损坏机制。
结论
如今,随着个人和企业拥抱数字革命,人工智能算法越来越多地用于解决多种背景下的复杂问题,其中一些可能会有很高的风险。
因此,当他们在敌对环境中面临对抗性攻击时,不要低估他们的弱点是很重要的。
这些例子就像它们揭示的一样多:用于访问私人空间或有价值信息的图像识别系统,保护个人和公司财富的欺诈检测算法,等等。
在这种情况下,博弈论为对手和学习者的行为建模提供了有用的工具,因为它一方面包括对手攻击的收益和生成对手数据的成本,另一方面包括学习者更新模型的成本。
因此,基于博弈论的方法揭示了对手和学习者都做出的权衡,并可用于评估实施特定技术的风险。因此,它是一个强大的决策工具,需要在类似的环境中更广泛地使用。
参考
[1] W. Liu 和 S. Chawla, 对抗性学习的博弈理论模型 ,2009 年 IEEE 国际数据挖掘研讨会,佛罗里达州迈阿密,2009 年,第 25–30 页。
[2] P. Dasgupta,J. B. Collins, 网络安全任务中对抗性机器学习的博弈论方法调查 ,信息管理&决策架构(IMDA)分部,美国华盛顿特区美国海军研究实验室信息技术部,2019 年 12 月**
[3] N .达尔维等人, 对抗性分类 ,西雅图华盛顿大学计算机科学与工程系,2004 年 8 月
[4] P. L .巴霍, 对抗性机器学习:如何攻防 ML 模型
[5] C. Molnar, 可解释的机器学习 ,制作黑盒模型的指南可解释的,2020 年 4 月
【6】s . sa xena, 游戏(理论)对于 AI?给大家一个图文并茂的指南2019 年 11 月
用于商家订单欺诈检测的通用数据科学架构。
原文:https://towardsdatascience.com/a-generalised-data-science-architecture-for-merchant-order-fraud-detection-9382ad61daad?source=collection_archive---------39-----------------------
数据科学如何帮助阻止预计将增加我们所有人成本的 500 亿美元商业损失。
数字时代礼遇 Pixabay
当客户不是你的客户时…
显然,当作者爱德华·贝拉米在他的小说《回望过去:2000-1887》中首次想到信用卡的概念时,所有公民都获得了等量的存储在现代借记卡上的信用额度。
澳大利亚只有一种信用卡,即银行卡,最早于 1974 年问世。现在,像 Visa 或 MasterCard 这样的全球信用卡网络提供了多种支付方式;奖励忠诚计划,如利润丰厚的澳航飞行常客或 Coles Flybuys 和移动钱包支付。
最初,银行卡的用途是补充现金。现金为王,有趣的是,教育项目伴随着负责任地使用信用卡的引入,这有助于降低违约率。随着 EFTPOS 网络、磁条和现在的 EMV 芯片的引入,包含加密细节并为每次购买生成 UID 的芯片增加了卡的安全性,但不能验证操作者。
不幸的是,信用卡和现金一样,无法完全弥合资金所有者和经营者之间的差距。不幸的是,持有该卡或泛 CVV 号码本身就充当了自己的认证者,为欺诈打开了方便之门。信用卡欺诈损失由发卡机构承保,例如,Visa 的零责任保单。卡不在场的损失是商家的责任。
2019 年,无卡(CNP)欺诈让澳大利亚商家每年损失约 5 亿美元。在美国,2015 年的估计表明,虽然 2020 年所有信用卡欺诈为120 亿美元,但其中的 60%或70 亿美元可能是由于不存在信用卡。当时,人们希望 EMV 标准芯片的出现能够抑制这种活动,但 CNP 卡欺诈的经历表明,这并不是全部的解决方案。
众所周知,信用卡欺诈策略是匿名黑客通过电子邮件或陌生电话渠道,使用设备浏览信用卡详细信息,或使用社交工程窃取账户的网络钓鱼信用卡详细信息。在此之后,发卡机构在其实时支付平台附近的实时欺诈检测系统将在支付点检测或不检测、分类和阻止交易。在数据科学术语中,这是一个实时分类的问题。
家庭诈骗
越来越多的不涉及犯罪集团或黑客的欺诈类型实际上是所谓的“友好”欺诈,其中欺诈发生在支付指令处理完毕后的,由持卡人质疑交易的合法性。
这些退款影响商户的余额,由发卡机构自动处理。发卡方对争议进行调解,并将费用转嫁给商家。
据说,到 2020 年,全球商家的退款成本可能在 500 亿美元左右。显然,经营一家电子商务商店的成本仅次于劳动力成本。这必须考虑到价格上涨,商家需要通过涨价来弥补他们的损失。
因此,除了授权持卡人之外的某人使用卡数据,无论卡是否存在,来进行授权持卡人不同意的购买。
授权持卡人的亲戚、同事,甚至可能是孩子,在线购买商品,注册在线服务,使用通过缓存登录电子商务门户访问的储值卡凭证购买应用程序,只需点击一下即可轻松购物。或者,在我知道的一个案例中,一个青少年在午夜从父母的钱包里拿走了卡片。
双因素认证(2FA)可能也无济于事,因为家庭成员或同事会知道账单地址和出生日期。
在这些情况下,争议是合法的,因为持卡人没有授权购买,但不知何故失去了对令牌或凭证的控制。
在我们能够对在线身份进行权威认证之前…
现金在我手里或钱包里或保险柜里;除非我把它掉了,忘了它在哪里,或者它被偷了,否则它是安全的。把你的信用卡拿在手中没有现金安全,因为凭证是数字联邦在你的手机、浏览器、你的实体钱包上,由 PayPal 等存储,甚至可以被我们的亲戚写下来。
这个问题正在由生物识别解决。虽然 2FA 似乎是一种安全的身份验证机制(我们有的,我们知道的),但指纹是我们有的其他东西。
信用卡供应商正在将生物识别技术嵌入卡中。虽然这不能防止 CNP 欺诈,但它将有助于使用 POS 终端对卡进行未经授权的操作。
在我们能够权威认证在线身份之前,我们必须做的是通过数据科学分类和推理技术评估和验证来自电子商务客户的购买模式是否合法,然后我们才能接受订单。
在过去的实体店,我们可以看到顾客在我们面前,他们用现金或支票支付。现在不行了。我们希望能够信任每一位顾客,让商家做正确的事情,也许我们做不到,因为我们不能 100%确定谁是交易的参与者。
也许不仅仅是为了 CRM 和创造销售,也是为了向商家保证购买有较低的退款可能性,我们现在可能需要在处理订单之前评估订单的合法性,而不管付款是否可以在事后处理,,特别是如果客户以前有过退款。
用于检测商家订单欺诈的通用数据科学架构。
亚当·哈特博士
商户订单欺诈检测的通用架构有 13 个组成部分:
- 客户身份是他们在电子商务平台上的个人资料;
- 客户了解你的客户是你在你的电子商务平台上验证他们时收集的详细信息。许多人会将此视为“空”。风险概况是实施欺诈的人口统计倾向;
- 客户社交环境是客户已经链接或者甚至用来认证的社交账户;
- 客户财务背景是购买历史和客户终身价值(CLV);
- 客户合作伙伴是朋友和朋友的层次结构;
- 模型管理是分类器,如最近邻或随机森林,用于将订单分类为合法或非法;
- 变量库是为模型提供的争论和混杂的数据存储;
- 数据流是订单流和“是/否”标志,在潜在的非法订单进行支付之前拦截它们;
- 连通性和安全性是不言而喻的;
- 元数据服务包含规范和其他结构以及变量的含义;
- 数据质量、数据验证和客户 UID 协同工作,以确保使用相同帐单和送货地址创建新帐户的客户相匹配;
- 可视化和图表有助于将数据汇集在一起,形成一个整体客户视图(WOCV ),包括可能有机会和动机了解客户付款方式的员工。这有助于复杂欺诈调查的发现和确认阶段;和
- 由于平台的组装性质,这些数据可以提供给 CRM 或其他可能从组装中受益的企业功能。
将支付验证与订单合法性分离
如果退款是仅次于劳动力的第二大成本,这是一件大事。然而,对于商人来说,最不需要做的事情就是拒绝订单而拒绝顾客。虽然一些商家使用客户终身价值来传递退款,但如果客户之前有过退款,则有证据表明,由于客户所处的友好或家庭网络,可能需要增加订单审查。
在友好欺诈之前,客户在电子商务平台上进行认证就足以使的任何订单合法。并且商家依赖于发卡方的支付欺诈验证服务。现在,也许商家有责任验证每张订单的合法性,而不是仅仅依靠付款验证来确保顾客确实是顾客。
如果上面概述的平台由于异常值而标记了订单,那么,假设友好的欺诈者无法访问主要客户的设备,使用客户拥有的(不知道的)东西的简单挑战-响应可能会验证订单的合法性,就像谷歌通过浏览器登录 Gmail 时所做的那样,根据挑战-响应放弃订单将非常明显,因为我们大多数人都带着智能手机。
例如,有人试图进行善意的欺诈,并且订单超出了过去的购买模式或价值,则会发出请求打开应用程序的质询响应,如果质询未通过,订单将被暂停。
这肯定是一种平衡行为,但使用无监督的数据科学分类算法在所有数据中实时自动评估订单,不仅建立了购买上下文,还建立了客户自己的社交和关联上下文,这可能有助于抑制导致价格上涨的损失,同时保持误报水平可控。
对 Clojure 的温和介绍
原文:https://towardsdatascience.com/a-gentle-intro-to-clojure-ad6c6802babe?source=collection_archive---------25-----------------------
一个小的真实世界的例子;探索 GitHub repos
照片由 Arian Darvishi 在 Unsplash 上拍摄
这个计划
我们将使用 HttpKit 来访问 GitHub API,并获取关于一个组织的存储库的信息。然后,我们将利用 Clojure 的内置特性来操作和探索集合。现在,我们不会尝试任何异步或复杂的东西——我们可以把它留到以后的文章中:)
入门指南
在某个新目录中,我创建了一个deps.edn
文件,具有以下依赖关系:
然后我们可以在与deps.edn
文件相同的目录下启动一个clj
REPL:
**❯** cljClojure 1.10.1user=>
并要求(粘贴)我们在 REPL 的属地:
快速地图提醒
map 中的键也是函数,它允许我们非常简洁地从 map 中访问键值。假设我们用:error
和:status
属性定义了一个名为test-map
的地图。我们可以像这样访问属性:status
:
提出 API 请求
👋生成个人访问令牌来使用 API 是最容易的。
此时,最好尝试访问 GitHub API,以确保我们的身份验证和 URL 是正确的。将下面的def's
调整为您自己的信息/设置,并将其粘贴到 REPL 中:
承诺
HttpKit (http/get)
函数返回一个承诺。一旦完成,这个承诺将解析为一张地图。我们可以使用@ symbol: @(http/get .. ..)
进行阻塞,直到这个承诺完成。一旦完成,我们就可以访问各种键值,比如:status
,应该是 200:
头球
GitHub 有一个很好的分页模型,我们将利用它来告诉我们是否需要发出更多的请求。如果我们查看响应头,有一个名为link
的属性,它包含一个逗号分隔的链接数组以及它们相对于当前页面的位置。我们可以通过get-in
函数从响应图中访问它。然后,如果链接字符串包含rel="next"
,我们可以判断是否有下一页要获取:
我们现在可以创建一个get-repos
函数来将上述所有内容放在一起。它需要两个参数;page
和per_page
—当前页码和每页返回的库数量,分别为:
⚠️:到目前为止,GitHub API 的最大值是 100。
注意,我们的get-repos
函数返回一个包含响应:body
的映射,作为一个解析的 json 数组和:has_next
作为一个布尔值。
循环浏览 GitHub 页面
我们有发出请求和检索 GitHub 库的所有小逻辑。接下来,我们需要遍历所有页面的数据,并将回购添加到一个不断增长的列表中。
快速循环提醒
Clojure 中的循环要么很棒,要么是一场灾难,这取决于您的背景。让我们从一个简单的循环开始。这里我们将i
绑定到0
,只有在i < 5
时才调用recur
。当我们调用recur
时,我们将i
绑定到i + 1
的值,从而递增i
并打印其值:
上述表达式的值就是loop
函数最后返回的值。这种情况下,5
。如果我们将这个表达式设置为一个def
,我们将把那个def
的值设置为5
:
循环浏览页面
我们可以快速检查自己,以确保在请求一个存储库后有更多的页面。
👋请确保您的组织有多个存储库!😅
请注意下面我们有多个字母绑定。首先,resp
被设置为表达式(get-repos 1 1)
的结果,然后has_next
将访问新设置的resp
变量,所有这些都在同一行代码中:
我们可以将上述内容与一些循环逻辑结合起来,以获取所有存储库。我将所有存储库放在一个名为repos
的全局列表中:
我知道我的组织中有 200 多个存储库,所以我将变量
per_page
设置为最大值 100。
运行一个快速检查以确保存储库的数量与您预期的相匹配:
(println (count @repos))
; => 233
太好了!我们所有的库都在一个全局原子列表中。我们现在可以按照我们认为合适的方式对数据进行分割。
过滤
让我们试试看有多少回购处于活动状态,即没有archived
。我们可以使用 Clojure 的filter
和一个匿名函数来实现这一点。匿名函数接受一个存储库映射作为输入,并检查:archived
属性是否为假:
我们做到了!active-repos
包含属性:archived
等于false
的存储库。
我希望这是进入 Clojure 的一个有用的方法!我们利用一个库来发出 http 请求,然后利用核心语言特性来进行一些基本的循环、过滤、多 let 和状态管理。
一个温和的介绍:自动化机器学习管道
原文:https://towardsdatascience.com/a-gentle-introduction-automating-machine-learning-pipelines-71f97192eabf?source=collection_archive---------27-----------------------
入门
昂斯佩上的厄伦德·埃克塞斯
部署很难
定期可靠地部署软件很难。定期可靠地部署利用机器学习(ML)模型的软件可能更加困难。最终,您最新模型管道的长期价值将(部分)取决于您的公司或客户对最终服务的信任程度,以及您通过迭代管道解决不断变化的客户需求的速度。
这就是自动化可以派上用场的地方:ML 管道的仔细的自动化可以通过允许您快速迭代管道以考虑新的业务逻辑或建模变化,同时还确保这些变化在投入与您的利益相关者/客户的服务之前满足关键性能标准,从而大大提高您的生产力。
听起来很酷,对吧?但是你需要自动化的 ML 流水线吗?这个问题很大程度上可以归结为以下问题
- 你能够(作为一个 ML 实践者)快速并且自信地通过一次
git
提交发布变更“进入生产”吗?
换句话说:您能快速自信地发布模型和管道的更新吗?你有一个系统的过程来评估和测试你的模型和管道(包括业务逻辑,转换等等)的行为吗?
如果这类问题的答案是“不”(或者你不确定!),那这个帖子就送给你了!
你会学到什么
以下是你应该从这篇文章中得到的:
- 对运动背后的一些关键思想和动机的理解集中于提高 ML 系统(通常称为 MLOps)的可靠性和自动化水平。
- 了解如何使用 GitHub Actions 和 Google Cloud 来自动化一个基本的 ML 管道。你将使用免费服务(或免费等级/介绍性服务),所以它不应该花你一毛钱!
- 这是一个演示项目,允许您将 Scikit-Learn 管道部署为“生产就绪”的无服务器功能!它也是一个模板项目,所以你可以用它作为你自己的 ML 项目的基础!
和往常一样,对于那些想要深入了解代码的人,请查看这里的 GitHub 工作流文件(.github/workflows/pipeline.yml
):
[## markdouthwaite/无服务器-scikit-learn-demo
一个提供演示代码的存储库,用于部署基于轻量级 Scikit-Learn 的 ML 管道心脏病建模…
github.com](https://github.com/markdouthwaite/serverless-scikit-learn-demo)
如果你知道 MLOps 是什么,只是想按照教程,请随意跳过。
什么是 MLOps?
在过去十年左右的时间里,“DevOps”运动在软件工程领域获得了大量专业人士的支持,大量专门的 DevOps 角色在世界各地的开发团队中涌现出来。这一运动的动机是将软件开发(Dev)的各个方面与操作(Ops)软件活动的元素相结合,目的是在持续的基础上加速可靠的、工作的软件的交付。
DevOps 运动的主要焦点是建立和维护持续集成和持续交付(CI/CD)管道。在实践中,设计良好且实施干净的 CI/CD 管道为团队提供了持续修改其软件系统的能力,以(原则上)显著减少新软件补丁和功能的价值实现时间,同时最小化与发布这些补丁和功能相关的错误和中断带来的负面风险。运行这种交付机制的成熟实现的团队通常每小时发布一次更新(或者更快!)能够在变更引入 bug 时快速、干净地回滚变更(尽管大多数这些应该在管道中的某个地方被捕获)。
相比之下,发布软件的“传统”方法本质上是为预定义的发布窗口(可能是每周、每月或每季度)储备补丁和特性。虽然这种方法并不是一致认为一个糟糕的方法,但它确实在发布窗口周围引入了很多压力,会在产品集成和发布过程周围产生很多复杂性,并最终增加了严重服务中断的风险,进而损害品牌。
这对机器学习意味着什么?
在这一点上,你可能会想‘这一切都很好,但这与机器学习有什么关系?’。就像成功的商业软件产品一样,成功的商业机器学习(ML)项目需要ML 服务的用户信任他们消费的服务的有效性和稳定性。重要的是,这必须持续进行——可能一次持续数年。
因此,临时模型培训和评估活动需要大量人工干预,类似于数据科学团队的“传统”软件交付流程——这在数据科学领域是司空见惯的——可能会给服务的生命周期带来严重的技术和业务风险,应被视为特别有害的技术债务形式。
与成功的商业软件产品非常相似,成功的商业机器学习(ML)项目要求 ML 服务的用户信任他们所消费的服务的有效性和稳定性。
这就是 MLOps 的用武之地。这个新生的运动可以被视为 DevOps 运动的超集:它的目标是在持续的基础上加速可靠的、工作的 ML 软件的交付。因此,它以与 DevOps 非常相似的方式关注 CI/CD 管道,但也增加了这些 CI/CD 问题的特定变化。最值得注意的是,持续培训(CT)的概念被加入到组合中。你问 CT 是什么?
- 持续培训 —许多 ML 服务需要在某个固定的基础上或在特定事件发生时(如数据变化、上游模型更新)对其基础 ML 模型进行再培训。此外,重要的是,这些新重新训练的模型符合定义有问题的模型的先前版本的基本假设和行为。因此,持续培训是关于建立健壮的、自动化的流程,用于培训和部署模型,作为传统持续交付管道的一个专门变体,包括作为更广泛的软件服务的一部分的 ML 模型的预处理、评估、选择和服务。
这里的目标是允许 ML 从业者快速自信地将他们最新最好的模型部署到生产中,同时保持依赖它们的服务的稳定性。
胸怀大志
整个 ML 世界越来越认识到需要能够开发和部署“生产级”ML 解决方案的团队——特别是在以产品为中心的 ML 应用中——以及由此产生的拥有组织孤立的 ML/技术能力的潜在技术(和商业)风险。在许多方面,这与更广泛的软件工程社区认识到“传统”软件应用程序的类似需求(和风险)的知识是一致的。
与之前更广泛的软件工程生态系统一样,ML 工具链正在商品化:进入壁垒(成本、专业知识)正在逐渐降低,市场竞争越来越激烈。
这种认识导致了一个围绕上述许多问题的新兴生态系统。每个月都有新的工具和平台推出,明确针对 ML/MLOps 挑战。正如之前更广泛的软件工程生态系统一样,ML 工具链正在商品化:进入壁垒(成本、专业知识)正在逐渐降低,市场竞争越来越激烈。对于那些希望开始 MLOps(或一般意义上的 ML)的人来说,这是一个非常令人兴奋的参与时机:你可以以很低的成本走一条漫长的道路,实现“生产就绪”的 ML 管道。以下是方法。
创建 ML 管道
好了,该上教程了!
这里展示的 ML 管道是使用GitHub Actions——GitHub 的工作流自动化工具构建的。如果你注册了一个 GitHub 账户,你就可以免费使用这个功能。有使用和资源限制(如你所料),但作为免费提供,这些限制出奇的慷慨。如果你能保持你的模型相对轻量级,你可以单独在免费提供的基础上构建一个小产品,所以对于那些有一些很酷的 MVP 想法的人来说,这可能是一个很好的起点。此外,如果免费资源不适合你,你也可以创建“自主”行动。
那么这里给出的管道示例将会做什么呢?该管道将是一个基本的 CT/CD 管道,构建在上,即上一篇文章中讨论的无服务器 ML 示例之上。如果你还没有读过,值得一读:
* [## 无服务器 ML:大规模部署轻量级模型
将 ML 模型作为可伸缩的 API“部署到生产中”可能会很棘手。这篇文章着眼于一个选择,使模型…
towardsdatascience.com](/serverless-ml-deploying-lightweight-models-at-scale-886443d88426)
以下是您的新管道将完成的工作:
- 设置您的环境并安装依赖项。
- 下载数据集的最新可用版本。
- 在最新数据集上训练和评估模型的新版本。
- 上传新模型和评估结果。
- 如果前面的步骤成功,那么触发新模型作为 API 的重新部署。
此外,您将看到如何安排这个工作流作为[cron](https://en.wikipedia.org/wiki/Cron)
作业定期运行(同样使用 GitHub 动作)。
开始之前
如果你想运行演示项目,你需要注册一个谷歌云账户。在撰写本文时,您的帐户中将增加 300 美元的信用点数。这将比运行本教程中代码的成本还要多(无论如何,这基本上是免费的!).您可以在此找到更多信息:
[## GCP 免费等级免费扩展试用和永远免费|谷歌云
20 多种免费产品免费体验热门产品,包括计算引擎和云存储,最高可达…
cloud.google.com](https://cloud.google.com/free)
和往常一样,如果你注册了,但不想继续使用谷歌云,确保取消你的帐户!
以下是您将需要的模板库:
[## markdouthwaite/无服务器-scikit-learn-demo
一个提供演示代码的存储库,用于部署基于轻量级 Scikit-Learn 的 ML 管道心脏病建模…
github.com](https://github.com/markdouthwaite/serverless-scikit-learn-demo)
接下来,您应该在您的个人 GitHub 帐户中创建一个模板库的分支,或者从模板创建一个新的库。完成这些后,您需要设置几个 GitHub 秘密来允许您的管道访问您的 Google 云服务。你可以在 GitHub 文档中找到如何设置秘密。具体来说,您需要添加:
GCP_PROJECT_ID
-唯一的谷歌云项目 ID。你可以在谷歌云控制台找到你的项目 ID。如果您不确定,Google 提供了一个文档来查找这个值。GCP_SA_KEY
-服务账户(SA)密钥。这是一个安全密钥,用于访问项目中的特定云服务。在本例中,为了简单起见,您将使用一个具有提升权限的默认 SA。在实践中,您应该考虑创建一个特权减少的服务协议。您需要为您的 SA 创建一个新密钥,并将其作为一个秘密复制到 GitHub。同样, Google 有一个关于如何生成这个密钥的详细文档。
注意:像对待机密/安全信息一样,不要与任何人共享您的 SA 密钥!理想情况下,当您完成这个示例时,删除它(当然,除非您想在自己的项目中继续使用它)。
完成这些设置后,您需要启用您的 Google 云构建、云功能和云存储 API。要做到这一点,只需浏览谷歌云控制台左侧的导航栏,并选择相关的云服务。如果相关的 API 没有被激活,当你点击服务的时候,你可以选择激活它。
最后,在下面的管道定义中,您需要在您的 Google 云存储中定义一个唯一的bucket 名称。示例管道定义(如下)中使用的名称是pipeline-example
。您应该在分叉之后,但在尝试运行示例之前,用您自己的 bucket 的名称替换它。此外,您还需要将存储库中的datasets/default.csv
数据集上传到{your-bucket-name}/heart-disease/dataset.csv
。
现在,不管是好是坏,是时候来点 YAML 了——云的语言。
管道定义
管道被定义为 YAML 文件。如果你想看得更透彻,你也应该看看 GitHub 的工作流文件格式介绍。如果你喜欢 YAML,这可能很容易做到,但不管怎样,下面是它的分解方式:
0.作业设置和调度
文件的这一部分将工作流命名为Train and Deploy
(这将是 GitHub 如何在 GitHub UI 中显示您的工作流),然后提供事件触发器来触发您的管道运行。在这种情况下,您会看到有两个触发器:push
和schedule
。
在push
的情况下,管道将在每次更新您的存储库的master
分支时运行(具体的分支可以在branches
字段中列出)。实际上,这意味着每当您将库中的代码变更合并到master
中时,管道将重新训练模型并重新部署它。这对于将代码变更立即传播到活动的 ML 服务是非常有用的。
对于schedule
触发器,您只需为您的管道设置一个运行的cron
时间表。换句话说:管道运行的固定时间表。下面提供的示例值将在每个工作日早上 08:00 运行管道。如果你不确定如何配置一个cron
时间表,这里有一个很棒的交互式编辑器供你使用。
name: Train and Deployon:
push:
branches:
- master
schedule:
- cron: '0 8 * * MON-FRI'
随意玩其他触发。此外,你也可以编写自定义触发器,如果你觉得有趣的话。这些自定义触发器可以帮助您建立一个“真正的”事件驱动架构。只是一个想法。
1.环境设置
现在是无聊但非常重要的一步。键train
定义了步骤的名称。在这里你有一个单一的工作。在其中,您必须定义将要在其上运行作业的虚拟机(runs-on
)。在这种情况下,示例使用的是ubuntu-latest
。接下来,定义作业中的每个steps
。
首先,运行actions/checkout@v2
。这将运行 GitHub 提供的checkout
动作。这将克隆并检出您的存储库的默认(通常是master
)分支。
接下来,作业设置gcloud
命令行工具。这一步使用 Google Cloud 提供的动作让你的生活变得更简单。这允许后续步骤访问gcloud
和gsutils
命令行工具。稍后,您将使用这些工具从/向 Google Cloud 下载/上传数据,并重新部署您的模型 API。
在这之后,您有两个 Python 相关的步骤。第一部分设置了一个基本的 Python 3.7 环境。第二步安装顶层requirements.txt
文件中的所有依赖项。这样,您的工作就可以正确地运行您的管道了。现在是有趣的部分。
train:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2 - name: Setup GCP client
uses: GoogleCloudPlatform/github-actions/setup-gcloud@master
with:
version: '290.0.1'
project_id: ${{ secrets.GCP_PROJECT_ID }}
service_account_key: ${{ secrets.GCP_SA_KEY }}
export_default_credentials: true
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: 3.7
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
注意,run
键允许你在虚拟机的外壳中执行命令——这里是默认的 Ubuntu 外壳。
2.下载数据集
首先,作业从pipeline-example
桶下载最新的可用数据集。在实践中,管道将在提供的路径上获得最新版本的数据集。这允许您创建一个独立于的数据管道来加载和转换数据集,以便 ML 管道在下次运行时拾取。
- name: Download the latest dataset
run: |
gsutil cp gs://pipeline-example/heart-disease/dataset.csv datasets/default.csv
你会看到这个步骤使用了gsutil
,谷歌的云存储命令行实用程序。这让你可以从谷歌云复制文件。简单!
3.训练和评估模型
现在作业已经加载了最新的数据集,是时候运行“核心”训练任务了。在这种情况下,这与之前的无服务器 ML 教程中给出的示例相同。
- name: Run training task
run: |
python steps/train.py --path=datasets/default.csv
另外,steps/train.py
脚本将以下元数据和指标写入artifacts/metrics.json
路径。正如您将看到的,这也会上传到 Google Cloud,因此您可以查看模型性能(和训练持续时间)如何随时间变化。这可以派上用场!
metrics = dict(
elapsed = end - start,
acc = acc,
val_acc = val_acc,
roc_auc = roc_auc,
timestamp = datetime.now().strftime(TIMESTAMP_FMT)
)
新训练的模型被写入artifacts/pipeline.joblib
。这也将上传到谷歌云存档。
4.上传模型和指标
下一步是将您的新模型和指标推送到 Google 云存储。您将看到管道上传了三个文件:
latest.joblib
-模型的“最新”版本。这将是管道生产的最新“有效”模型。${{ env.GITHUB_RUN_ID }}.joblib
-上述模型的存档版本(由生产它的惟一 GitHub 运行 ID 标识)。metrics/${{ env.GITHUB_RUN_ID }}.json
-上述模型指标的存档版本(由产生它的唯一 GitHub 运行 ID 标识)。可以按创建日期对它们进行排序,以生成显示模型性能随时间变化的时间序列。
- name: Upload new model and associated metrics
run: |
gsutil cp artifacts/pipeline.joblib gs://pipeline-example/heart-disease/models/latest.joblib
gsutil cp artifacts/pipeline.joblib gs://pipeline-example/heart-disease/models/${{ env.GITHUB_RUN_ID }}.joblib
gsutil cp artifacts/metrics.json gs://pipeline-example/heart-disease/models/metrics/${{ env.GITHUB_RUN_ID }}.joblib
现在你有了一个新的模型,一些指标,所有这些都整齐地存档在谷歌云存储中。
5.将模型部署为云功能
最后,完成所有这些工作后,是时候重新部署您的最新模型了。
- name: Deploy model as Cloud Function
run: |
gcloud functions deploy heart-disease --entry-point=predict_handler --runtime=python37 --project=${{ secrets.GCP_PROJECT_ID }} --allow-unauthenticated --trigger-http
这将触发您的模型的云功能与您的最新模型一起重新部署。如果你想了解传递给gcloud
的参数是做什么的,请确保查看本系列的前一篇文章。几分钟后,你的新型号将被投入使用。
收尾工作
仅此而已。如果您的管道成功完成,您将能够为每个成功的步骤看到一个漂亮的绿色勾号列表。
现在,您已经有了一个自动化的管道来加载新数据、重新训练模型、归档新模型及其指标,然后按照固定的时间表重新部署您的模型 API。很酷,是吧?
后续步骤
这只是一个婴儿 ML 管道。你可以做很多事情让它变得更复杂。一些初步想法可能是:
- 创建一个云函数,当模型性能下降到给定值以下时,它会在上传模型指标时触发,以通知您(可能通过 Slack 或电子邮件)。
- 如果评估结果比先前的模型(或者一些测试用例)更差,添加一个步骤来中止模型重新部署。
- 添加自定义云函数触发器,以便在数据集更新时运行工作流(而不是在固定的基础上运行,这可能是不必要的)。
- 添加一个 StreamLit 控制面板,以便随时查看模型和指标。
如果你有任何问题,请随时联系我们!*
计算 TF-IDF 值的简明介绍
原文:https://towardsdatascience.com/a-gentle-introduction-to-calculating-the-tf-idf-values-9e391f8a13e5?source=collection_archive---------4-----------------------
图片来自皮查拜 &图片来自米哈尔·贾莫鲁克图片来自皮查拜,CC0
一步一步的数学和基于代码的指南,通过计算鲁米的一首神秘的诗来揭示 TF-IDF 值。
当你浏览了上面的标题和副标题时,你已经形成了这个帖子相当专业的想法。最有可能的是,你会先浏览一下这篇文章,浏览一下标题,然后再决定是否要阅读整篇文章。也许,公式和代码会诱使你去读这篇文章。或者,这可能会导致你推迟阅读这篇文章。如您所见,您有一个非常好的机制来非常有效地处理文本。
在自然语言处理领域,我们试图让算法理解文本。大多数算法都是数学函数。因此,他们需要用数字来表示文本,以便有效地工作。本文深入研究了一种非常古老的将文本表示为数字的机制,称为 TF-IDF,也称为术语频率逆文档频率。
那么,什么是 TF-IDF 呢?
直觉上,为了理解文本是关于什么的,我们寻找频繁出现的单词。术语频率通过捕捉每个单词在文本中出现的次数来涵盖这一方面。然而,在这篇文章中,单词 、 、 出现了 200 多次,而单词 TF (也包括使用的代码)只出现了 55 次。为了降低过于频繁出现的单词的相对重要性,引入了反向加权来缩小过于频繁出现的单词。这种反向加权被称为反向文档频率。总的来说,TF-IDF 捕获了一组文档或一组文本中单词的相对重要性。
有许多关于 TF-IDF 背后的直觉的优秀文章,但关于如何推导出 TF-IDF 的精确值的文章却不多。本文的重点是将所涉及的各种计算拼凑在一起,并提供如何用 python 代码导出每一步,以便您可以在正在处理的文本上导出它。
为什么 TF IDF 仍然相关?
在自然语言处理领域,2013 年单词嵌入和 2018 年语言模型的发现改变了格局,并导致了 NLP 的许多令人兴奋的发展。因此,在 2020 年,我选择写 2000 多字关于 TF IDF 的文章,这似乎有点奇怪,TF IDF 最初是在 20 世纪 70 年代制定的。以下是我认为理解底层计算是有好处的两个原因。
- 理解 TF-IDF 使理解和解释您在 TF-IDF 上应用的算法的结果更容易一步。
- 在实际的商业环境中,文本分类问题是自然语言处理中常见的问题之一。在文本分类问题中,算法必须根据它训练过的一组预定义的主题来预测主题。2018 年,谷歌发布了一个基于对几个不同文本集的 450K 实验的文本分类框架。基于 450K 的实验,谷歌发现当样本数量/字数< 1500, TF IDF was the best way to represent text. When you have a smallish sample size for a relatively common problem, it helps to try out TF IDF.
Overview
We will be using a beautiful poem by the mystic poet and scholar Rumi as our example corpus. First, we will calculate TF IDF values for the poem using TF IDF Vectorizer from the sklearn package. Then, we will pull apart the various components and work through various steps involved in calculating TF-IDF values. Mathematical calculations and Python code will be provided for each step.
So, let’s go!
First things first — Introducing the Corpus
To illustrate the concept of TF-IDF, we need a corpus. A corpus is a collection of documents. In a typical Natural Language Processing problem, a corpus can vary from a list of call center logs/ transcripts, a list of social media feedback to 大量收集研究文档时。
为了说明所涉及的各个步骤,我们需要保持语料库尽可能小,以便矩阵能够整齐地放在一页上。我偶然发现了 13 世纪波斯诗人和苏菲派神秘主义者鲁米T2【jalāl ad-děn Muhammad rūmé】的这句名言/美丽的诗,它非常符合我们的使用案例。因此,我们将使用这首诗作为我们的文档列表,每个句子都被视为一个文档。
鲁米的诗
那不是一首真正美丽的诗吗?当我们通过代码和一点数学来提升自己时,这是很好的。
我们将上面的 8 个句子表示为 Python 中的字符串列表。
corpus = ["you were born with potential",
"you were born with goodness and trust",
"you were born with ideals and dreams",
"you were born with greatness",
"you were born with wings",
"you are not meant for crawling, so don't",
"you have wings",
"learn to use them and fly"
]
展望最终产出
在这一步,我们将把这首美丽的诗抽取成神秘的小数。但是,嘿,毕竟,我们正试图通过理解 TF-IDF 中涉及的计算来揭开这些小数的神秘面纱。如前所述,通过 sklearn 包导出是相当容易的。
#transform the tf idf vectorizer
from sklearn.feature_extraction.text import TfidfVectorizer
tf_idf_vect = TfidfVectorizer()
X_train_tf_idf = tf_idf_vect.fit_transform(corpus)
terms = tf_idf_vect.get_feature_names()
在下面的矩阵中,每一行代表上述诗中的一句话。每一列代表一个独特的词在诗中按字母顺序排列。如你所见,矩阵中有很多零。因此,一个节省内存的稀疏矩阵被用来表示这一点。为了便于可视化,我将其转换为数据框。
TF-IDF 对鲁米诗歌《作者的形象》的评价
让我们解释一下迄今为止我们收到的数字。你可能已经注意到了,【你出生了】这几个词在整首诗中反复出现。因此,我们预计这些词不会得到很高的 TF-IDF 分数。如果你看看这三个词的值,你会发现它们通常在 0.2 到 0.3 之间。
我们来看文档 0— 你天生就有潜力。字势 突出 。如果您查看矩阵第一行中的各种 TF-IDF 值,您会看到单词潜在具有最高的 TF-IDF 值。
让我们看看文件 4(第 5 行): 你生来就有翅膀 。还是那句话,和之前一样,单词“wings”在那句话里价值最高。
请注意,单词“wings”也出现在文档 6 中。文件 6 中单词" wings" 的 TF-IDF 值与文件 4 中单词" wings" 的 TF-IDF 值不同。在文件 6 中,单词“wings”被认为不如文件 6 中的单词“have”重要。
本文的目的是研究如何从头开始计算上述 TF-IDF 值。我们将特别关注对单词 【翅膀】 和 潜能 的计算,以得出上面显示的矩阵中以红色突出显示的值。
我们将把各种部件拆开,然后再把它们组装起来。我们将分三步进行:
- 步骤 1:从头开始推导词频值
- 步骤 2:从头开始推导逆文档频率值
- 步骤 3:使用乘法和归一化将上述两个值聚合起来
步骤 1:计算词频值
频率这个术语非常简单。它是以单词/术语在文档中出现的次数来计算的。
对于句子,“你生来就有潜力”和“你生来就有翅膀”,下面是词频值。
字数统计矩阵,作者图片
同样的,对于诗中的所有 8 个句子,我们得到下面的字数统计矩阵。和以前一样,行代表句子,列代表诗中按字母顺序排列的单词。计数矢量器返回一个稀疏矩阵,该矩阵被转换为数据框以便于可视化。
字数统计矩阵,作者图片
以上是通过下面的代码计算的。
from sklearn.feature_extraction.text import CountVectorizer
count_vect = CountVectorizer()
X_train_counts = count_vect.fit_transform(corpus)
terms = count_vect.get_feature_names()
让我们找出词语翅膀的词频。
- 词频为字 势 在 Doc 0= 1
- 文档 4 中的词 翼 的词频= 1
- 文档 6 中 翼 词的词频= 1
然而,如果我们只是把频率这个词作为重要性的衡量标准,我们就会陷入一个主要的陷阱,正如下面来自可怕地图的推文所代表的,它代表了美国每个州最频繁出现的单词。
步骤 2:反转文档频率
我们需要一种机制来降低在所有文档中出现太频繁的单词的相对重要性。进入 逆文档频率 。直观地说,如果一个单词出现在所有文档中,那么它可能不会在区分文档中发挥如此大的作用。
类似于词频,
文档频率(术语 t) =具有术语 t 的文档数/文档总数= d(t)/n
逆文档频率= 文档总数/带有术语的文档数 t = n / d(t)
如果一个单词出现在所有文档中,我们希望它在 0-1 范围的底部。因此,对数标度在这里直观地使用是有意义的,因为 log 1 是 0。然而,有一些实际的考虑,如避免臭名昭著的除以 0 的错误,1 被加到分母。
sklearn 中 TF IDF 矢量器默认设置的逆文档频率计算如下(默认设置有 *smooth_idf=True*
,它将“1”加到分子和分母上,就好像看到一个额外的文档恰好包含集合中的每个术语一次,这防止了零除法)。
- n 是文档集中的文档总数。
- d(t)是文档集中包含术语的文档数。
让我们为这些词确定各自的价值— 潜能 和 翅膀 。
- 文件数量= 8
- 语料库中包含单词 潜在 的文档数量= 1
- 语料库中包含单词 wings 的文档数= 2
应用逆文档频率的公式,我们得到
****
可以通过运行以下 Python 代码来获得这首诗的 IDF 值。
**# explore idf
# idf_ attribute can be used to extract IDF values
# transpose the 1D IDF array to convert to a dataframe to make it easy to visualise
df_idf = idf2df(vectorizer.idf_[:,np.newaxis].T ,terms)
display(HTML(df_idf.to_html()))**
我们获得如下所示的值,我们可以交叉检查单词 【潜力】 和 翅膀 的计算值。注意,语料库中的一个单词只有一个 IDF 值。
逆文献频率论鲁米的诗,由作者意象
第三步:相乘并归一化
顾名思义,TF-IDF 是术语频率(TF)和逆文档频率(IDF)的组合,通过将两个值相乘获得。sklearn 实现然后在 TF 和 IDF 之间的乘积上应用规范化。让我们详细看看其中的每一个步骤。
步骤 3 a:将 TF 和 IDF 相乘
在将这两个矩阵相乘时,我们对项频率矩阵和逆文档频率进行逐元素相乘。考虑第一句——“你生来就有潜力”。求这句话的 TF 和 IDF 的乘积,计算如下。
这可以通过针对整个数据帧的以下代码来完成:
**df_mul = df_count.mul(df_idf.to_numpy())
display(HTML(df_mul.to_html()))**
将其应用于语料库,我们得到以下矩阵:
你可能会注意到 TF 和 IDF 的乘积可以大于 1。现在,最后一步是归一化这些值,使 TF-IDF 值始终介于 0 和 1 之间。
步骤 3 b:标准化 TF 和 IDF 的乘积
在日常生活中,当我们想要将数值标准化以便于比较时,我们使用百分比或比例。因此,我们可以假设计算一个句子中不同单词的 TF-IDF 值的比例。请注意,TF 和 IDF 都是非负值,因为术语频率和逆文档频率的最低可能值是 0。因此,去掉比例就相当于 L1 归一化。在 L1 归一化中,向量中的每个元素(想想一个句子的各种 TF-IDF 值)除以所有元素的绝对值之和。在 sklearn 中有一个 L1 归一化值的选项,但这不是默认设置。
在 sklearn 中,应用的默认归一化是 L2 归一化。考虑 L2 归一化最简单的方法是,考虑三角形的一个角在原点的直线长度或毕达哥拉斯定理。
作者图片
在上图中,线的长度是 5。在这种情况下,直线是一个 1D 矢量。当向量是 n 维时,向量的长度类似于一条线的长度,但扩展到 n 维。因此,如果向量 v 由 n 个元素组成,向量的长度计算如下
在 L2 归一化中,我们实际上是将向量除以向量的长度。关于 L1 和 L2 范数的更多数学解释,请参考维基百科。
为了应用 L2 范数,对于每个句子,我们需要计算 TF 和 IDF 乘积的平方和的平方根。
它可以在 Python 中完成,如下所示:
**from sklearn.preprocessing import Normalizer
df_mul.iloc[:,:] = Normalizer(norm='l2').fit_transform(df_mul)
display(HTML(df_mul.to_html()))**
以下是获得的值:
最后,我们准备计算最终的 TF-IDF 分数!
TF-IDF 为字 势 在 你天生就有势 (Doc 0): 2.504077 / 3。66856427 = 0.682895
TF-IDF 为单词 翅膀 在 中你生来就有翅膀(Doc 4)=2.098612/3。402882126 = 0.616716
TF-IDF 为字 翼中的翼**(Doc 6)=2.098612/3。452116387 = 0.607744
这可以用下面的代码来计算。
**from sklearn.preprocessing import Normalizer
df_mul.iloc[:,:] = Normalizer(norm=’l2').fit_transform(df_mul)display(HTML(df_mul.to_html()))**
当您运行上面的代码时,您会得到如下的结果,这与上面的展望输出部分中的矩阵相同。
TF-IDF 对鲁米诗歌《作者的形象》的评价
到目前为止,我们已经完成了以下工作
限制
TF-IDF 的主要局限是没有考虑词序,而词序是理解句子意义的一个重要部分。
此外,文档长度会在 TF IDF 值中引入大量差异。
假设
以下是本帖中使用的假设和约定。
- 四舍五入-为了便于显示,小数四舍五入到小数点后 4 位。我已经注意不四舍五入作为例子的数字。你在不同单元格中发现的任何舍入变化都是因为这个原因。
- 正如 sklearn 文档中提到的,大多数教科书中的 IDF 公式与 sklearn 中的实现略有不同。
- 为了简单起见,我使用了 sklearn TF IDF 矢量器的默认设置。有多种方法可以改变这一点,例如 a)使用 L1 归一化代替 L2 归一化& b)设置 smooth_idf=False,这样不会将“1”加到分子和分母上。
- 上例中没有删除停用词。对于各种用例,可以删除相关的停用词。
- 我使用这么小的语料库只是为了举例说明。在真实的用例中,插图中显示的语料库、词汇表和矩阵要大得多。
Github 参考
GitHub 中有用于计算 TF-IDF 值的 Jupyter 笔记本。
参考资料:
[1]sci kit-学习文档
[2] 文本分类框架,谷歌,2018
【3】如何在介质上写数学
循环一致对抗网络的温和介绍
原文:https://towardsdatascience.com/a-gentle-introduction-to-cycle-consistent-adversarial-networks-6731c8424a87?source=collection_archive---------16-----------------------
由于图像问题和损失函数,不成对图像到图像的翻译是最有趣和最具挑战性的课题。
循环一致对抗网络的图像到图像翻译(来源:使用循环一致对抗网络的不成对图像到图像翻译)
通过这篇文章,我们旨在了解什么是循环 GAN 以及这种模型的现有应用是什么。我们给出的场景是输入一个图像,输出是这个输入图像的不同版本,根据我们的指导方针进行更改。该翻译的基本目标是使用训练集学习输入图像和输出图像之间的映射。在缺少成对数据的情况下将图像从 X 平移到 Y 的初始方法。因此该模型包含两个函数 G: X -> Y 和 F: Y -> X,其中 X 是源域,Y 是目标域。
关于这种技术,我们应该知道的第一件事是,它使用了生成式对抗网络。在这种情况下,我们有两个神经网络相互竞争。因此,生成器试图创建一个真实的图像和鉴别器,它试图了解真实和虚假图像之间的差异。循环一致性损失函数被引入到优化问题中,这意味着如果我们将斑马图像转换成马图像,然后再转换回斑马图像,我们应该得到完全相同的输入图像。
这个美丽概念背后的技术是生成对抗网络。
生成对抗网络(GANs)是由两个网络组成的深度神经网络架构,其中一个网络对抗另一个网络。
2014 年,蒙特利尔大学的 Ian Goodfellow 和其他研究人员在一篇论文中介绍了 gan。
我们为什么使用 CycleGAN
提出了循环 GAN 体系结构,即不成对的图像到图像翻译循环一致对抗网络。Jan-Yan Zhu 和他的同事(2017)建议:
PIX2PIX 可以产生真正惊人的结果,但挑战在于训练数据。根据我们要翻译的图像,将一个图像转换成另一个图像有点困难,也很耗时,不可行,甚至有时是不可能的(两个图像之间一对一的匹配)。这就是 CycleGAN 的用武之地。
CycleGAN 背后的关键思想是,它们允许你将模型指向两个不成对的图像集合。例如,一组图像,A 组是斑马,而另一组是马。所以 Cycle-GAN 模型可以学习翻译不成对的图像。
甘循环的简单翻译
G 的作用: G 试图将 X 翻译成输出,输出通过 Dy 馈入,根据域 y 检查是真是假
F 的角色: F 试图将 Y 翻译成输出,这些输出通过 Dx 馈入,以检查它们是否与域 x 无法区分
这个项目的主要部分是循环一致性损失,例如,如果我们的输入图像 A 来自域 X,通过生成器 G 转换为目标图像或域 Y 的输出图像 B,然后域 Y 的图像 B 通过生成器 f 转换回域 X,此时这两个图像之间的差异称为循环一致性损失。
这种方法需要创建两对生成器和鉴别器:一对用于 A2B(源到输出转换),另一对用于 B2A(输出到源转换)。
Cycle-GAN 的简化架构(来源:Hardik Bansal on GAN)
因此,如果我们考虑在那个循环中将图像从源域转换到目标域(马转换成斑马)的例子,g an 需要两个生成器。
发电机 A2B 把马变成了斑马,B2A 把斑马变成了马。
两者一起训练,保证输入的马图像和生成的斑马图像。
两个鉴别器确定马和斑马的真假图像。
建造发电机
发电机可以在下图中看到。
发电机有三个部分:
I .编码器(提取特征)
第一步是通过卷积网络从图片中分离出高光。作为输入,卷积网络拍摄一张图片,我们在输入图片上移动以提取特征的过滤窗口的大小,以及选择每次前进后我们将移动过滤窗口的量的步长。每个卷积层都提示提取动态更高级别的高光。
二。变压器(添加先前的结果)
你可以看到这些层通过图像的特征连接不同的细节,然后根据这些特征决定如何改变图片的元素编码,从一个开始到下一个。为此,我们使用了 6 到 9 层 resnet 块,如下所示:
Resnet 块是一个神经网络层,由两个卷积层组成,其中信息的累积被添加到产量中。这样做是为了保证过去层的贡献的属性对于后面的层是可访问的,并且目标是它们的产出不会偏离唯一信息太多,在任何情况下,唯一图片的质量都不会保持在产出中,并且结果将是意想不到的。这项任务的一个要点是保持独特信息的特征,如文章的大小和状态,所以遗留系统非常适合这种变化。Resnet 块可以在随附的图像中勾勒出来。
三。解码器(解码结果)
解码步骤是步骤 1 的特定逆步骤,我们将从元素向量再次返回低级特征。这是通过应用反卷积(或转置卷积)层来完成的。
发电机的高级结构(来源:GAN 上的 Hardik Bansal)
构建鉴别器
现在我们有了一个发电机,下一个目标是制造一个鉴别器。我们之前定义了如何创建一个生成器,同时,我们还需要构建一个鉴别器。鉴别者会拍摄图像,并试图预测它是真的还是假的。下图显示了一个生成器。
鉴别器的高级结构(来源:GAN 上的 Hardik Bansal)
因为我们的情况鉴别器只是一个网络。我们需要做的是从输入图片中提取特征。然后,我们的下一个目标是检查这些特征是否依赖于这些分类。
损失函数
现在我们有了两个发生器和两个鉴别器,所以我们的下一个目标是以某种方式设计损失函数来实现我们的目标。损失函数可以看到有一些部分:
I .第一步是 D 必须接受所有类别的所有图像。
二。第二步是拒绝所有生成器试图欺骗他们的图像。
三。生成器试图批准来自鉴别器的所有图像来愚弄他们。
四。生成的图像返回原始图像,因此生成器使用 A→B 生成一个假图像,然后我们几乎肯定应该使用另一个生成器 B→A 返回到一个唯一的图像——它必须满足循环一致性。
循环损失
最关键的损失之一是循环损失。我们可以使用另一个生成器来获得原始图像,并且初始图像和最后图像之间的差异应该尽可能小。
目标函数
周期目标函数的两个组成部分,对抗性损失和周期一致性损失
单独的对抗损失不足以产生好的图像,但是循环一致性损失解决了这个问题。
现在,我们可以通过将这些损失项放在一起,并用超参数λ对循环一致性损失进行加权,来创建完整的目标函数。我们建议设置λ = 10
减少模型振荡
- 为了防止模型从一次迭代到另一次迭代发生剧烈变化,鉴别器被输入生成图像的历史,而不仅仅是由最新版本的生成器生成的图像。
- 为此,我们保存了 50 张最近生成的图像。基于这种技术,我们减少了模型振荡以及模型过拟合。
优化算法
优化算法用于更新权重和偏差,即模型的内部参数,以减少误差。它们可以分为两类:
- 恒定学习率算法:
2.自适应学习算法:
使用优化函数:
有不同优化函数
- 随机梯度下降
- 阿达格拉德
- 圣经》和《古兰经》传统中)亚当(人类第一人的名字
Adam 代表自适应矩估计。 Adam 是深度学习领域的一种流行算法,因为它能快速取得好的结果。
在训练的前半部分,学习率被设置为 0.0002,然后在剩余的迭代中线性降低到零。
就像最初的 GAN 实现一样,我们将创建单独的优化器,这些优化器只能更新网络的某些部分。我们希望两个网络都变得更好。
我们将在这里做同样的事情,只是现在我们有 3 个网络要优化,因此我们需要 3 个优化器:
G_xy 和 G_yx 变量将作为生成器进行优化,
而 D_x 和 D_y 应该更新两个不同的鉴别器。
应用
I .复活古城:将巴比伦(伊拉克)、耶路撒冷和伦敦的古代地图转换为现代谷歌地图和卫星视图。
二。动物调整:把黑熊翻译成熊猫。
三。肖像到娃娃脸:王座游戏角色看起来像一个洋娃娃。
四。脸↔拉面:与 CycleGAN 一起表演了一场神奇而欢闹的脸↔拉面翻译。
动词 (verb 的缩写)彩色传统照片:把黑白照片变成彩色版本。
不及物动词将堡垒之夜转换为 PUBG:使用 CycleGAN 在堡垒之夜和 PUBG 这两个拥有数亿用户的流行皇家战役游戏之间进行翻译。现在你可以在一个游戏的视觉效果中享受另一个游戏的游戏性。
摘要
这是对循环持续对抗网络的温和介绍。循环氮化镓是一个开放的研究领域,在这个领域还有很多工作要做
CycleGAN 是通过 GAN 架构利用来自两个不同区域的不成对图片集合来训练无监督图像翻译模型的过程。
图像到图像的翻译解释包括图像的受控改变,并且需要组合图像的巨大数据集,这些数据集令人难以置信地难以准备好或者偶尔不存在。
在我的下一篇文章中,我将简要描述定义循环 GAN 的数学方法以及提高循环 GAN 模型效率的一些步骤。
感谢阅读!
随时给我发信息。
Twitter:aamirjarda
LinkedIn:aamirjarda
insta gram:aamirjarda
你有什么问题吗?
请在下面的评论中提出你的问题,我会尽力回答。
数据素养的简明介绍
原文:https://towardsdatascience.com/a-gentle-introduction-to-data-literacy-98b950ac68fa?source=collection_archive---------38-----------------------
万花筒在 Unsplash 上拍摄的照片
数据是新的石油;要将它转化为火箭燃料,你需要教你的人民如何使用它。
随着人工智能和其他技术创新的发展,许多公司忽视了任何企业的主要资产:人力资本。人类产生数据;数据是新的石油;它是新的货币。
如果你觉得你以前听过这句话……“数据是新的石油”这句话不是我说的..但是据说——自从 2006 年英国数学家 Clive Humby 创造了这个词以来,这个词一直被重复使用——来表示我们商业生活中数据的价值和力量。
数据不仅仅是数字;它们是文本、视频、图像、音频和各种编码的信息。数据甚至是人。数百万、数十亿和数万亿信息的组合构成了我们所说的大数据。
活动创建者在 Unsplash 上的照片
什么是数据素养
数据素养是一个相对较新的概念,同时出现在使用商业智能做出更好决策的公司中。
它的理念是,每个人都应该知道如何利用数据做出决策,以充分发挥他们的职能。
Gartner 将数据素养定义为“在上下文中读写和交流数据的能力,包括对数据源和结构、分析方法和应用技术的理解,以及描述用例、应用和最终价值的能力。”
数据素养是对一个人的母语素养过程的完美类比:它需要努力、重复、阅读、陪伴该领域的专业人员和兴趣……但是,一旦迈出这一步,过程就会流动。当人们有文化时,他们用这种语言阅读、写作、工作、交流、思考、推理和辩论。数据素养也是如此。
数据本身没有任何意义。你可以断章取义,像一个字母或一个数字,让它几乎毫无意义。
一个常规但简单的例子:谷歌搜索只有“植物”这个词结果是不连贯的,多种多样的,提到:种大豆,种香蕉树,种芯片,怎么种树……所以,所以有必要将搜索情境化、具体化,让找到的数据更有主张,更准确。
数据——没有人的解读——没有本身的意义。然而,人类推理能力与人工智能的结合产生了关于信息的一些结论。虽然数据分析可以在几个方面为组织提供显著的差异,但人们不能忽视所有这些背后的东西,确切地说是人。
数据科学家和分析师 Susan Etlinger 在她的 TED 演讲中说:“我们有机会自己赋予数据意义。坦率地说,数据不会创造这些感觉;我们愿意”。 我们又该如何为数据创造这些意义呢?
“我们不是数据和技术的被动消费者。我们塑造了它们在我们生活中扮演的角色,以及我们赋予它们意义的方式。但是要做到这一点,我们需要同样关注我们如何思考我们的编码方式。数据科学家 Susan Etlinger 表示:“我们必须提出问题,一些棘手的问题,以便从‘讲述’事物的时刻进入理解它们的时刻。”。
照片由斯科特·格雷厄姆在 Unsplash 上拍摄
为什么重要?
这种阅读、工作、分析和论证数据的能力必须落实到所有职能部门和所有能力水平的员工身上。
一个好的数据分析策略能让你的员工中的每个人都有能力做出能带来改变的发现。
这就是为什么所有组织成员都必须能够利用数据推动结果、重塑业务流程、更深入地了解客户、发现新的收入来源以及更好地平衡风险和回报。
在下面的 TED 演讲中,你可以概述适当的数据素养如何帮助我们在不成为数据科学家的情况下辨别真伪,或者我们如何利用这些信息做出更好的决策。看一看:
[## 为什么每个人都应该懂数据| Jordan Morrow | TEDxBoise
我们如何在不成为数据科学家的情况下辨别真假呢?我们如何利用这些信息来…
www.ted.com](https://www.ted.com/talks/jordan_morrow_why_everyone_should_be_data_literate?utm_campaign=tedspread&utm_medium=referral&utm_source=tedcomshare)
数据扫盲项目
最近,Qlik 和 Accenture 调查了超过 9000 次采访(来自北美、欧洲和亚太地区九个国家/地区的不同行业部门的人员,从 C-light 到初学者),并且编写了一份关于公司数据素养当前情况的报告。
该报告带来了一个有些令人担忧的现实:尽管管理者认为他们正在制定由数据指导的行动(数据驱动),但一些变化的极快速度最终导致了员工的焦虑、恐惧、超负荷、不确定性甚至悲伤。
根据调查数据,74%的受访者报告在处理数据时感到不开心(没有准备,没有安全感)。
这些机器可以更加复杂和灵活地处理越来越多的数据和信息,进行数千种组合,甚至模仿人类行为,向服务用户建议特定的响应。
因此,不可避免的是,它们将越来越受到人们的欢迎,并被用于自动化各种公司的流程。然而,事实证明,如上所述,这给那些必须每天处理堆积如山的信息、更新和新工具的员工带来了压力和负担。
即使他们对处理数据感到不舒服,他们也认识到这是他们工作的组织的资产,并相信数据素养培训会使他们更有效率。
数据素养允许运营主管向首席执行官传达成功的衡量标准。当销售部门没有达到季度和年度目标时,它有助于财务传达紧迫性。
提高业务数据素养会对毛利率、资产回报率、股本回报率和销售回报率产生积极影响,导致关注和不关注数据素养的公司价值产生 3.2 亿至 5.34 亿美元的差异(数据由数据素养指数提供)。
该研究还发现,76%的顶级商业决策者不信任他们的数据素养技能。
威廉·艾文在 Unsplash 上的照片
数据素养的影响
因此,关键点是让人们参与进来,让所有部门都参与到数据分析中来,打破壁垒,克服技术问题,使数据的获取民主化和去神秘化。这样公司才能整体受益。
这也影响了文化的相关方面,促进了经验和知识的交流、同龄人之间的合作(无论在哪个领域)以及持续学习。
拥有一个健康和强大的文化,并让人们准备好平稳和高效地处理基于数据的决策,是建立一个更加人性化和愉快的企业环境(这些特征越来越受到市场的重视)和优化结果(包括财务)的战略问题。
不满意和焦虑的员工可能会不知不觉地污染公司文化,变得消极。
当考虑到与数据和技术相关的问题所带来的压力导致的医疗流程和许可证执行缓慢时,公司每年平均每个员工损失超过 5 个工作日(43 小时)。
当然,文化的变化不会在一夜之间发生,但它处于不断的运动中是一个事实。了解这一点以及这在多大程度上是一个基本支柱,管理者必须始终关注,寻求分担这一责任,以开发基于对团队有意义的价值观的公平文化,符合组织的利益。
因此,数字包容成为一个压力更小、结果更好的过程,因为人们将更加开放,更愿意将新工具纳入他们的工作程序,不仅更深入地理解与这些技术和数据相关的功能,而且更深入地理解她可以从中获得的收益,从而对分析、数据等更感兴趣。
因此,在向数据使用项目投资数百万之前,投资于人,因为他们是数据科学战略和其他项目的关键。如果有必要后退一步或减缓分析的实施,以更谨慎地教育员工有关数据的知识,包括使数据对这些人有吸引力——而不仅仅是那些习惯于数据的人——一定要犹豫。中期和长期的结果将是合理的。
照片由克里斯·利维拉尼在 Unsplash 上拍摄
结论
正如我们所看到的,数据素养是指每个人都应该知道如何利用数据做出决策,以最大限度地发挥他们的作用。
它对我们商业文化的各个方面都有相关的影响,促进了经验和知识的交流、同事之间的协作(无论在哪个领域)以及持续学习。
由于与压力相关的数据和技术,公司每年平均每个员工损失超过 5 个工作日(43 小时)。减轻这种压力的唯一方法是数据教育和意识。
作为第二语言的数据意识对于现在是必要的,而不仅仅是未来。你和你的公司正在努力实现它吗?在评论里说说吧!
还有一件事…
如果你想在学习之旅中走得更远,我为你准备了一份很棒的清单,上面有 60 多门关于人工智能、机器学习、深度学习和数据科学的培训课程,你现在就可以免费参加:
- 什么是预测分析,你今天如何使用它?
- 今日最佳免费课程学习人工智能、ML 和数据科学。
- 60 多门课程,有评分,有总结(当然是 A.I .做的)。
- 是不是我们所知道的作品的终结?世界经济论坛 报告《2020 年就业前景》简析
假设你想在我的电子书中继续发现新的资源和学习人工智能。在这种情况下,我在网上分享关于人工智能、机器学习、深度学习、数据科学、商业智能、分析和其他方面的最佳文章、网站和免费培训课程,以帮助你开始学习和发展你的职业生涯。
学习 AI 在线:200 多种资源在线开始学习 AI
另外,我刚刚在亚马逊上发布了其他有趣的电子书,我相信其中一些可能会让你感兴趣……让我们保持联系,关注我,一起做吧。
- 、人工智能、机器人和编码(给父母):模拟父母与数字孩子的实用指南
- 终结者悖论:神经科学如何帮助我们理解移情和对人工智能的恐惧
- 人工智能从 A 到 Z:揭秘人工智能的本质概念
- 2020 年人工智能:写人工智能的一年
你愿意支持我吗?
为了获得无限的故事,你也可以考虑 注册 成为一个中等会员,只需 5 美元。此外,如果您使用我的链接注册了 ,我会收到一小笔佣金(无需额外付费)。
[## 通过我的推荐链接加入媒体- Jair Ribeiro
阅读我分享的每一个故事(以及媒体上成千上万的其他作者)。你的会员费直接支持其他…
jairribeiro.medium.com。](https://jairribeiro.medium.com/membership)
差分隐私的温和介绍
原文:https://towardsdatascience.com/a-gentle-introduction-to-differential-privacy-330434437cdf?source=collection_archive---------31-----------------------
什么是差分隐私?为什么我们会想要它?如何才能实现?
想象一下,一位社会学家来找你,希望你回答关于各种话题的是/否问题,以了解你所在城镇的人口统计数据。你被问到的大多数问题都很平常,但是有几个问题你不愿意透露你的答案。“不要担心隐私”,研究人员向你保证,“在我公布数据之前,我会删除任何会让你的答案追溯到你的信息。这将是完全匿名的。”
作为一个有隐私意识的人,你知道严格来说这不是真的:例如,通过比较网飞电影评级和 IMDB 评级,Netflix 奖数据集成功地去匿名化,尽管去除了姓名和地址等识别特征[1]。也许你已经公开通过各种社交媒体发布了足够多的世俗问题的答案,以至于有人可以追踪到你的答案。毕竟学过海洋学的热爱动漫和奶酪的自由市场资本家能有几个?
你决定用一点随机性来修饰你的答案,以此来保护自己。对于每个问题,你抛硬币。如果是正面,你如实回答;如果是反面,你再掷一次来决定你将给出哪个答案。
恶作剧问题。答案是肯定的。
现在,即使有人计算出你是社会学家数据集中的记录 X,他们也无法知道与你相关的答案是否是真的。你也让别人更难将你的匿名回答与任何现有信息联系起来。通过以这种方式给你的数据添加噪声,你已经不知不觉地确保了你的数据在某种程度上是本地差分隐私。
定义隐私
差分隐私所追求的隐私定义是某些东西(数据集、模型、统计数据等)的结果。)不要在数据中删除或添加任何个人时更改。也就是说,不可能发现任何一个人的贡献,因为无论他们的数据是否存在,你正在寻找的数据都是相同的。
有些人可能会觉得这样的要求超出了应该被认为是“隐私”的范围:也许可以接受的是,数据集中至少一半的个人是安全的,而不是每个人。这没有什么无可争议的错误——隐私是一个道德和政策问题,而不是宇宙中的绝对常数——但差别隐私是商业、政府和研究中隐私的黄金标准。
差分隐私的数学概念(我们不会在这里表达——毕竟这是一个温和的介绍)不是一个单一的算法——你不能简单地在某些东西上“运行差分隐私”。相反,这是一个界限,如果满足,意味着您的数据在某种程度上受到保护。在实践中,事情不会触及隐私的最终定义(当某人被移除时,什么都不会改变),但它可能会使了解个人数据变得更加困难。
使某些东西有差别地私人化“简单地”是向来自非常特定的分布的数据添加噪声的情况。困难在于确定你是否添加了正确的噪声级别,并以正确的方式应用它。对于复杂的数据集和函数来说,这可能会变得非常棘手。
只有几个数字
有两个数字决定保护级别,ε(ε)和δ(δ)。私有机制(你对你的数据集/模型/统计数据做的事情,使之成为有差别的私有)被表述为(ε,δ)-有差别的私有。选择这些数字是为了确定隐私和结果准确性之间的折衷,这对于特定情况是可接受的。
ε与泄露的私人信息的级别有关。如果你想让你的数据得到更好的保护(一个更小的ε),你必须给你的机制增加更多的噪声。ε 越大,意味着隐私保护越少,但也意味着结果更有效,因为它们更接近真实值。
δ 本质上是发生灾难性错误以及某人的隐私被泄露的可能性。对于一个由 N 个个体组成的数据集,你希望 δ 至多为 1/N,这样预期的灾难数量将小于 1。
保护隐私所需的噪声量不仅取决于这两个值,还取决于数据和对数据的查询。例如,考虑一个人的年龄列表,其值为【10】, 20,30 。如果你想找出平均值(20),去掉 10 岁或 30 岁的人会使平均值改变 5。但是,如果您想知道最大值(30),删除 30 岁将使您的查询改变 10。对于ε和 δ 的给定值,您必须为最大值查询添加比平均值查询更多的噪声,以说明个体贡献的相对影响。如果年龄改为[11,12,13,您将不得不添加更少的噪声,因为与使用[10,20,30时相比,查询变化更少。
混淆单个数据确实会扭曲批量数据的结果,但随着数据集的增长,单个噪声会被抵消,从总体计算的统计数据会更接近无噪声值。
这能有多难
在我们的第一个例子中,随机更改您的答案是局部差异隐私,因为它直接应用于数据,然后才进行任何处理。另一种公式是全局差分隐私,其中噪声被添加到作为整体对数据集进行的查询中——在上面的均值/最大值示例中,如果我们将噪声添加到人口统计中,我们将实现全局差分隐私。一般来说,对于相同的保护级别,全局差异隐私比本地差异隐私产生更准确的答案。缺点是,您必须能够信任数据收集器来正确应用全局差异隐私,并在此之前保护您的数据。建立信任是一项比差分隐私困难得多的任务,这就是为什么本地差分隐私是一个流行的解决方案。
虽然差别隐私不是一个新的概念,但它只是在过去几年才开始成为政府和企业共同关注的问题。如果你使用苹果或谷歌的产品,你发送给他们的数据可能会被保密。除了大型科技公司中的几个例子,差分隐私领域是一个很少有人涉足的领域。虽然,这正在慢慢改变:2020 年的美国人口普查将是第一个差分隐私[3],差分隐私的开源工具正在积极开发[4]。
如前所述,差分隐私的最大困难是确保你认为是差分隐私的东西。使用不完美实现的噪声分布会使差分隐私机制变得不安全[5],对于那些没有 Google 式资源来保证隐私的人来说,即插即用隐私的基础设施尚不存在。
当然,即使存在可证明正确的差分隐私,隐私和匿名问题仍然存在。在社会学家问卷的例子中,如果有人知道你给出的随机答案,没有什么能阻止他们假装这是事实;如果人们选择忽视,一些不同的隐私不会保护你免受负面影响。如果你在 100 份其他问卷中被问到同样的问题,你嘈杂的答案会开始向真实值靠拢,因为噪音会自己抵消掉。在某些情况下,即使仅仅知道某人在数据集中,也可能暴露私人信息。
由于这些原因,理解差异隐私并不能“解决”隐私是很重要的。隐私是一个需要立法的政治意愿、实施和促进隐私的广泛文化动力以及建设隐私基础设施的技术专长的问题。在我们的数据真正隐私化之前还有一段路要走,但是如果没有差分隐私,我们将走不了多远。
资源
[1]https://www.cs.utexas.edu/~shmat/shmat_oak08netflix.pdf
[2]https://machine learning . apple . com/2017/12/06/learning-with privacy-at-scale . html
[3]https://www . census . gov/about/policies/privacy/statistical _ safeguard/disclosure-avoidance-2020-census . html
https://www.openmined.org/
http://citeseerx.ist.psu.edu/viewdoc/download?[5]doi = 10 . 1 . 1 . 366 . 5957&rep = re P1&type = pdf
对 HDBSCAN 和基于密度的聚类的简要介绍
原文:https://towardsdatascience.com/a-gentle-introduction-to-hdbscan-and-density-based-clustering-5fd79329c1e8?source=collection_archive---------6-----------------------
用大约 5 分钟解释 HDBSCAN
“带噪声的应用程序的基于层次密度的空间聚类”(多么拗口…), HDBSCAN,是我的首选聚类算法之一。我觉得每个人都应该将这种方法纳入他们的数据科学工具箱。
我在的上一篇博客中写了这方面的内容,我试图尽可能深入地解释 HDBSCAN。这一次我采取了相反的方法:我将尽可能简洁地解释 HDBSCAN 和基于密度的集群的主要思想。
我认为(也希望)这本关于 HDBSCAN 的入门书对数据科学的初学者和新手会更友好。
为什么选择基于密度的聚类?
让我们从一个样本数据集开始。
如果你用肉眼试着识别这些集群,你可能会识别出 6 个集群。
6 个“直观”集群
即使提供了正确数量的聚类,K-means 也明显给出了不好的结果。我们上面确定的一些集群被分成两个或多个集群。另一方面,HDBSCAN 为我们提供了预期的集群。
与 K-means 不同,基于密度的方法即使在数据不干净和聚类形状怪异的情况下也能很好地工作。
HDBSCAN 如何做到这一点?从高层次来看,我们可以将基于密度的聚类过程简化为以下步骤:
- 估计密度
- 选择高密度区域
- 合并这些选定区域中的点
估计密度
我们需要某种方法来估计某些点周围的密度。一种常见的方法是使用“核心距离”这是一个点到它的第 K 个最近邻居的距离。
K=7 时的核心距离
较密集区域中的点将具有较小的核心距离,而较稀疏区域中的点将具有较大的核心距离。核心距离是这些方法“基于密度”的原因。
给定地核的距离,我们可以通过求密度的倒数来估计密度。有了这些估计,我们就可以知道密度景观是什么样子了。
根据我们的样本数据集估计的密度
如果我们画出这些密度,我们可以看到这种密度景观的山脉对应于数据的不同聚类。
简单聚类选择
选择聚类的一种方法是选择全局阈值。通过获取密度高于阈值的点,并将这些点分组在一起,我们得到我们的聚类。
将下面的插图视为上面的表面图的横截面。
基于不同阈值的两种不同聚类
想象海洋上的岛屿,海平面是门槛,不同的岛屿是你的集群。海平面以下的土地是噪音。随着海平面的下降,新的岛屿出现,一些岛屿结合起来形成更大的岛屿。
这是我们降低海平面时产生的几个集群。
这种方法接近于 DBSCAN 所做的。虽然简单,但这需要我们找到合适的阈值来获得有意义的聚类。
如果您将阈值设置得太高,则太多的点会被认为是噪声,并且您会分组不足。如果设置得太低,可能会使点过度分组,所有的东西都只是一个簇。
不同密度的聚类选择
使用全局阈值方法,当聚类具有不同的密度时,你可能会遇到困难。如果我们在下面的例子中只使用一个阈值,我们要么过度分组蓝色和黄色集群,要么没有包括整个红色集群。
最佳聚类需要不同的阈值
您可能会认为密度中的每个峰值应该是一个集群,但是,这并不总是最佳的。
看下图。左边应该有 3 个集群,右边应该有 2 个集群。
HDBSCAN 首先建立一个层次结构,以确定哪些峰值最终合并在一起以及以什么顺序合并,然后对于每个集群,它会询问,是保留这个集群还是将其分成其子集群?在上图中,我们应该选择蓝色和黄色的区域还是绿色的区域呢?
鉴于密度景观,你可以认为每座山是一个集群。我们必须确定两座山峰是否属于同一座山。是有两座山,还是只有一座山有两座峰?
以下是说明这一点的例子
“3 个集群数据集”
"两个群集数据集"
如果您使用 sklearn 的 HDBSCAN,您可以绘制集群层次结构。
要选择,我们看哪一个更“坚持”。我们看到的山峰更靠近还是分开?聚类稳定性(持久性)由层次图中不同颜色区域的面积表示。我们用集群稳定性来回答我们的山区问题。
当两座山峰实际上是两座山时,两座山峰的体积之和大于其底部的体积。当山峰只是一座山的特征时,那么底部的体积将大于山峰体积的总和。
使用这种启发式方法,HDBSCAN 能够决定是否将一个集群细分为其子集群。这样,它会自动选择要提取的聚类。
结论和更多资源
- 我们基于核心距离估计密度,并形成密度景观(是什么使这些基于密度)
- 我们可以使用一个全局阈值来设定海平面并识别岛屿(T2)
- 我们可以试着决定,这是几座山还是一山多峰?(HDBSCAN)
我希望这能让你知道 DBSCAN/HDBSCAN 是如何工作的,以及是什么让这些方法“基于密度”。其他方法,如光学或 DeBaCl,使用类似的概念,但在选择区域的方式上有所不同。
如果你想了解更多关于 HDBSCAN 的统计动机,点如何组合在一起的实现细节,或者 HDBSCAN 如何构建层次结构,你可以查看我的博客文章,在那里我会更详细地介绍。
技术提示:这里绘制的估计密度不仅仅是1 / core_distance
。我必须对数据进行一些转换,使其在视觉上更具吸引力。
[## 了解 HDBSCAN 和基于密度的聚类
HDBSCAN 是由 Campello、Moulavi 和 Sander 开发的聚类算法[8]。它代表“等级……
pberba.github.io](https://pberba.github.io/stats/2020/01/17/hdbscan/) [## HDBSCAN 的工作原理- hdbscan 0.8.1 文档
HDBSCAN 是由 Campello、Moulavi 和 Sander 开发的聚类算法。它通过将 DBSCAN 转换成一个…
hdbscan.readthedocs.io](https://hdbscan.readthedocs.io/en/latest/how_hdbscan_works.html) [## 加速分层密度聚类
提出了一种基于层次密度聚类的加速算法。我们的新算法改进了…
arxiv.org](https://arxiv.org/abs/1705.07321)
马科斯·曼特的照片
C++和 Python 中迭代器的简明介绍
原文:https://towardsdatascience.com/a-gentle-introduction-to-iterators-in-c-and-python-4eb8c6e2238f?source=collection_archive---------34-----------------------
第 2 部分:使用 itertools 了解 Python 中的迭代器
来源:恰兰·库尼(用 Powerpoint 绘制)。
在我之前的文章中(此处),我对在代码中使用迭代器的优点进行了一般性的讨论,并浏览了一些 C++初学者的例子。在这里,我将扩展迭代器的介绍,看看它们是如何在 Python 中实现的,以及如何使用它们来改进代码。
Python 迭代的基础
作为一名使用 Python 的数据科学家,您肯定会遇到存储在一系列容器中的各种数据类型,比如列表、元组和字典。在 Python 中,这些容器都是可迭代的对象,这意味着我们可以从它们那里获得一个迭代器(和在 C++中一样,Python 字符串也是可迭代的对象)。在 Python for 循环中对这些可迭代数据容器进行操作需要一个迭代器方法和一个 next 方法的执行来创建迭代器并前进[1]。这些内置方法如下所示,其中 iter(name) 从列表中返回一个迭代器,而 next(it) 允许我们遍历迭代器并打印出每个元素。
name = ["Ciaran", "Cooney"]
it = iter(name)
print(next(it))
print(next(it))#output
Ciaran
Cooney
Python 附带了几个内置函数,如 zip 和 map ,它们有助于数据容器的迭代。一旦你对何时和如何使用它们有了直觉,这些都是非常有用和省时的工具。zip 函数的有效工作方式是使用 iter()和 next() to 调用并遍历每个输入参数,然后返回一个迭代器,该迭代器可以返回包含具有公共索引的输入数据的元组。
a = zip([1,2,3], ['a','b','c'])
print(list(a))#output
[(1, 'a'), (2, 'b'), (3, 'c')]
在前进到下一个元素之前,Map 将函数应用于交互变量中的每个元素。这里,对第二个参数调用 iter(),并将输入函数应用于相应的元素。然后调用 Next(),直到遍历完迭代器。
b = map(len, ['hello', 'world'])
print(list(b))
构建自己的迭代器
在将来的某个时候,您可能希望将自己的类或对象制作成迭代器,也许是为了提高数据处理管道的性能。为此,您需要实现 iter() 和 next() 方法。iter()方法返回迭代器对象,而 next()方法在每次迭代中简化操作(这里只是返回元素)。重要的是要小心不要创建一个将继续无限前进的迭代器,所以我们使用 if-else 语句,并在迭代器用尽时抛出 StopIteration 。
class MyClass():
def __init__(self, container):
self.container = container
def __iter__(self):
self.count = 0
return self
def __next__(self):
if self.count < len(self.container):
x = self.container[self.count]
self.count += 1
return x
else:
raise StopIterationmyclass = MyClass(["Hello", "my", "name", "is", "Ciaran"])
myiter = iter(myclass)for x in myiter:
print(x)#output
Hello
my
name
is
Ciaran
Itertools
尽管知道幕后发生了什么总是好的,但事实是,您与迭代器的交互通常是通过内置函数和 itertools 包进行的。Itertools 有这么多优秀的迭代器工具,所以花时间翻一翻文档看看有什么吸引你的眼球是很值得的。
我喜欢的一个函数是 dropwhile() ,它允许你创建一个迭代器,只要谓词为真,它就从 iterable 中删除元素,之后返回所有元素。 Groupby() 是一个常见的迭代器算法,它从 iterable 返回连续的键和组。it itertools 的另一个有用的功能是 permutations() 。正如您可能已经猜到的,这个函数返回包含在输入 iterable 中的元素的排列。置换的长度可以由第二个参数约束, r ( 参见下面的代码),否则置换将是输入 iterable 的长度。我编写了一些使用这些函数的例子:
print(list(dropwhile(lambda x: x<=3, [1,2,3,4,5,6,7,8,9,3])))
#output: [4, 5, 6, 7, 8, 9, 3]print(list(list((list(g), k)) for k, g in groupby([1,2,2,2,2,3,4,4,4,4,5,5,2,1,1,1,1])))
#output: [[[1], 1], [[2, 2, 2, 2], 2], [[3], 3], [[4, 4, 4, 4], 4], [[5, 5], 5], [[2], 2], [[1, 1, 1, 1], 1]]print(list(permutations([1,2,3])))
[(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]print(list(permutations([1,2,3], 2)))
[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
迭代器代数
术语“迭代器代数”在 itertools 文档中用于描述组合迭代器工具以提高整体代码效率和性能的一般概念[2]。组合 itertools 函数一开始可能需要一点思考,并且可以很快获得相当大的进步,但是在这篇文章中,我将向您展示一个使用 itertools 如何提高处理时间的简单示例。
让我们考虑一个简单的例子,其中我们想要获取两个包含正整数的列表,确定列表中(不在列表中)所有可能的元素组合,并返回每个组合的总和。下面,我用几个 for 循环实现了一个典型的函数来遍历列表并执行求和操作。
a = [1,2,3]
b = [4,5,6]
def sum_combinations(a, b):
combinations, results = [], []
for i in a:
for j in b:
combinations.append(tuple((i,j)))
results.append(sum((i,j)))
return combinations, resultscombs, res = sum_combinations(a,b)
print(combs, res)#output
[(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]
[5, 6, 7, 6, 7, 8, 7, 8, 9]
这对于我在这个例子中使用的 3 元素列表来说很好。但是,如果我们将输入扩展为每个包含 10000 个整数,会发生什么呢?为了测试这一点,我导入了时间模块,以查看该功能在我公认不太特别的笔记本电脑上会运行多长时间:
import time
a = np.random.randint(5, size=10000)
b = np.random.randint(5, size=10000)
start = time.time()
combs, res = sum_combinations(a,b)
stop = time.time()
print(f"time: {stop-start}")#output:
time: 108.07000184059143
好吧, 108s 等待一些基本操作似乎是一段相当长的时间。幸运的是,我们有一个替代方案:迭代器代数!
这里我使用 itertools 函数 product() 以及上面提到的 map 函数。这个函数为我们提供了输入 iterables 的笛卡尔乘积,有点像使用嵌套的 for 循环。然后,当我们遍历输入时,我们使用 map 来应用 sum 函数。
start = time.time()
res_1 = list(map(sum,itertools.product(a,b, repeat=1)))
stop = time.time()
print(f"time: {stop-start}")#output: time: 34.44488835334778
看这里的时差!当我们实现一个标准的循环函数时需要 108 秒,当我们使用 iterator 代数的 itertools 时需要 34 秒。如果你没有从这篇文章中得到什么,至少注意到当数据的维度扩展时迭代器可以提供的潜在的时间增益。
我希望这篇文章对那些为了更有效的数据处理而冒险进入迭代器世界的人有用。
我用过的所有 Python 例子和任何附加函数都可以在这里找到:【https://github.com/cfcooney/medium_posts
来源
[1]w3schools.com,《Python 迭代器》,w3schools.com,2020 年。【在线】。可用:https://www.w3schools.com/python/python_iterators.asp.
[2] S. Jaiswal,《Python 迭代器教程》, DataCamp ,2018。【在线】。可用:https://www . data camp . com/community/tutorials/python-iterator-tutorial?UTM _ source = AdWords _ PPC&UTM _ campaignid = 898687156&UTM _ adgroupid = 48947256715&UTM _ device = c&UTM _ keyword =&UTM _ match type = b&UTM _ network = g&UTM _ adpossion =&UTM _ creative = 332602034343【t24
C++和 Python 中迭代器的简明介绍
原文:https://towardsdatascience.com/a-gentle-introduction-to-iterators-in-c-and-python-dafece4b0f4f?source=collection_archive---------44-----------------------
第 1 部分:用 C++中的例子介绍迭代器
来源:恰兰·库尼(用 Powerpoint 绘制)。
对于所有级别和学科的程序员,包括寻求实现高效数据处理管道的数据科学家,畸胎器是一个非常有用的编程范例。即使你没有显式地编写自己的代码来包含迭代器,它们也很可能已经在后台帮助你对容器中的元素进行操作了。简单地说,迭代器用于遍历容器中的元素,在执行操作时实现高效的处理。迭代器有助于处理无限序列,而不需要为所有可能的序列重新分配资源[1]。这有助于高效的资源配置和更干净的代码。
当然,不同编程语言的实现是不同的。这是关于这个主题的两篇文章中的第一篇,我将重点介绍 C++中迭代器的简单介绍。在第二篇文章中,我将看看迭代器是如何在 Python 中实现的。Python 附带了一个名为 itertools 的内置模块,它允许创建迭代器来增强循环性能,以及许多其他特性。如果您想了解更多关于 itertools 的信息,请阅读第 2 部分。
迭代器简介
D 不同的编程语言将订阅作为一种直接访问容器中元素的方法(如向量、数组)。例如,在 Python 中,可以从列表 x = ['Today ',' is ',' Monday'] 中访问单词“Monday”,代码为 x[2] 。然而,一个更通用的方法,称为迭代器,给程序员间接访问元素(这是一个类似于 C++中指针的想法)【2】。基本上,迭代器抽象了数据结构中不同元素的地址,并且是一个非常强大的工具,允许数据结构与算法进行交互,而算法不一定知道它们正在操作的结构。
迭代器的主要功能之一是它能够处理容器的元素,同时将用户与数据的内部结构隔离开来[3]。迭代器在时间和内存性能方面提高了程序员的效率,尤其是在处理大型数据集时。它们还提供了便利,因为我们不需要如此关心列表或向量的大小,例如在 C++中,我们可以简单地使用 end() 方法。迭代器的使用还可以增强代码的可重用性,尤其是在我们改变所使用的容器类型的情况下。
当然,有些情况下迭代器可能不是最好的工具,或者根本不起作用。例如,以某种复杂的方式同时遍历两个独立的数据结构,特别是当其中一个数据决定了另一个数据的位置时,会导致迭代器出现问题[4]。然而,这些是更高级的案例,不属于本文的范围。
用 C++中的迭代器编码
在强类型语言 C++中,有迭代器的类型有返回迭代器的成员。这些类型有名为 begin 和 end 的成员,它们分别返回对应于第一个元素和“超过结尾的那个”的迭代器[5]。这对迭代器被定义为迭代器范围,表示容器中要操作的元素的范围(见上图)。
并非所有的迭代器都是相同的,它们可以根据功能分为五个子类型,其中最强大的是随机访问迭代器,顾名思义,它允许随机访问容器中的任何元素,而不是顺序访问[5]。在本教程中,我们将把重点放在随机访问迭代器上,因为我们将一些基本操作应用到字符串和向量上,但是关于其他类型迭代器的更多细节参见[5]。
您还应该知道迭代器类型是由其容器定义的。例如,如果你有一个 const 类型的 vector,那么它对应的迭代器将是 const_iterator 类型,可以从这个 vector 中读取元素,但不能向其中写入元素。从 C++11 开始,有两个新函数允许程序员特别请求 const_iterator 类型。这些是 cbegin 和 cend ,是上述的常量版本。如果我们使用这些函数,返回的迭代器将是常量,即使底层容器不是。
所以,让我们看一些代码…
在第一个例子中,我们只想使用 toupper() 函数将字符串中的第一个字母大写。在初始化字符串之后,我们检查它是否为空(if (s.begin()!= s.end()))。在 if 语句中,我们将第一个值的迭代器(s.begin())赋给变量名 it 。然后迭代器被解引用(*it),以便将实际值' c' '传递给函数,并且在赋值的左侧被解引用,以便将大写字母赋给字符串, s 。注意:解引用意味着我们从迭代器中提取实值。
std::string s("ciaran cooney");
if (s.begin() != s.end()){
auto it = s.begin();
*it = toupper(*it);
}
std::cout << s << std::endl;//Output: Ciaran cooney
这将返回首字母大写的字符串,即 s = "Ciaran cooney" 。如果我们想大写字符串中的每个元素,我们可以使用++操作符遍历它。这里,我们简单地使用迭代器依次遍历每个字符,大写该字符,然后递增迭代器。这个 for 循环中的条件检查迭代器在退出循环之前何时到达字符串的末尾(s.end())。
for (auto it = s.begin(); it != s.end(); it++){
*it = toupper(*it);
}
std::cout << s << std::endl;//Output: CIARAN COONEY
这一次,迭代器用于遍历字符串中的每个元素,然后将其大写:“CIARAN COONEY”。
对于数据科学家和机器学习工程师来说,自然语言编程显然是一个很大的领域,尽管 python 是 NLP 事实上的家,但看看其他语言如何处理数据总是好的。让我们看几个使用 NLP 中常见的一些非常基本的过程的例子。
这里的想法是取一个字符串(这里是名和姓),只将两个名字的首字母大写。为了帮助实现这一点,我使用了一个名为 split_string() 的函数,它根据一个分隔符分割字符串,并在一个向量中返回各个名称。首先,我们创建一个名为 cont 的向量<字符串>,它是一个用于返回分隔字符串的容器,以及一个分隔符( dlim ),它用于确定用来实例化拆分的字符。然后使用范围运算符 : 依次从 cont 向量中选择每个单词。接下来,我们在第一个元素的位置创建迭代器 it 之前做一个检查,确保向量不为空。和前面的例子一样,toupper()函数用于执行首字母的大写,产生输出“Ciaran 库尼”。
std::vector<std::string> cont; //container for split strings
char dlim = ' '; //where to split the inputsplit_string(s, cont, dlim);for (std::string &str : cont){
if (str.begin() != str.end()){
auto it = str.begin();
*it = toupper(*it);
}
}
std::string strUp = cont[0] + ' ' + cont[1];
std::cout << strUp << std::endl;//Output: Ciaran Cooney
在最后一个考虑字符串的例子中,让我们想象我们读入一个文本文件,并把它放在一个向量中,用空格隔开。然后,我们可以使用迭代器遍历向量,打印它发现的每个单独的元素(或执行一些其他操作),然后在到达迭代器末尾时停止,或者发现一个空元素。
在这个例子中,我们递增迭代器,直到到达末尾或者发现一个空元素。它->empty())。在每次递增时,我们简单地取消对迭代器的引用,打印出相应的文本字符串。
std::vector<std::string> text = {"Hello", "there,", "my", "name", "is", "Ciaran"};for (auto it = text.cbegin(); it != text.cend() && !it->empty(); it++){
std::cout << *it << " ";
}//Output: Hello there, my name is Ciaran
结果输出是“你好,我的名字是 Ciaran”。
现在我将通过几个例子,使用包含整数的向量。在第一个示例中,我们希望比较两个向量在每个索引处的元素,当元素匹配时返回包含 1 的向量,当元素不匹配时返回包含 0 的向量。
这里,我们从被比较的两个向量中创建了两个迭代器, itA 和 ItB 。然后实例化一个 while 循环,并保持为真,直到迭代器 itA 到达向量 vecA 的末尾。在每次迭代中,通过解引用 itA 和 ItB,对两个迭代器中的元素进行比较,当这些元素相等时,将 1 附加到结果中。++操作符再次用于递增两个迭代器,直到到达序列的末尾。
std::vector<int> vecA = {0,1,0,0,0,1,0,1,1,1};
std::vector<int> vecB = {0,1,1,1,0,0,0,1,0,0};
std::vector<int> result;
auto itA = vecA.begin();
auto itB = vecB.begin();while (itA != vecA.end()){
if (*itA == *itB){
result.push_back(1);
}
else{
result.push_back(0);
}
itA++;
itB++;
}
print_results(result); //function for printing contents of vectors//Output: 1 1 0 0 1 0 1 1 0 0
在与迭代器交互时,C++中有许多方法可以促进额外的功能。这些范围从初学者到专家水平,但在这里我将演示一些更基本的例子。 advance 方法用于将迭代器向前移动一定的位置。 next 方法执行类似的任务,除了它接受一个迭代器作为它的一个参数,并返回另一个已经前进了许多步的迭代器。正如您可能猜到的那样, prev 方法是 next 方法的逆方法,它返回一个已经后退了许多步的迭代器。下面的代码是这些迭代器方法的简单演示。
std::vector<int> nums = {1,2,3,4};std::vector<int>::iterator it = nums.begin();
advance(it, 2); //increments an iterator
std::cout << *it << "\n"; //Output: 3 auto it2 = next(it, 1); //returns an iterator
std::cout << *it2 << std::endl; //Output: 4auto it3 = prev(it2, 1);
std::cout << *it3 << std::endl; //Output: 3
让我们看看 C++中迭代器的最后一个介绍性例子。这一个稍微高级一点,因为它试图使用迭代器通过 advance 和 inserter 方法将一些值插入到现有的向量中。插入器是一个迭代器适配器,它接受一个容器并产生一个迭代器,将元素添加到指定的容器中[2]。
对于这个玩具示例,我们有两个向量:一个包含整数序列,另一个包含该序列中缺失的整数。在迭代器 it 创建之后,从第一个序列开始,我们将迭代器向前推进 3 步,到达我们想要放置新序列的位置。我们希望复制的序列范围是用 begin()和 end()方法建立的。这允许我们使用迭代器 it 将数字 3、4 和 5 复制到第一个序列中。
std::vector<int> sequence1 = {1,2,3,7,8,9,10};
std::vector<int> sequence2 = {4,5,6};
auto it = sequence1.begin();advance(it, 3);
copy(sequence2.begin(), sequence2.end(), inserter(sequence1, it));for (int &i : sequence1){
std::cout << i << ", ";}//Output: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
现在,第一个序列包含缺失的值,并打印为:1,2,3,4,5,6,7,8,9,10。
这就是我们对 C++中迭代器的浅显探讨的结束,但我希望它能让你们中的一些人开始研究所有提供的功能。必须指出的是,迭代器是一个抽象概念,一开始不容易完全理解,所以不要担心,我们仍然不完全清楚它们是如何操作的。我的建议是先尝试一些编码,然后你会开始看到好处。
我用过的所有 C++例子和附加函数都在这里:https://github.com/cfcooney/medium_posts
来源
[1] S. Jaiswal,《Python 迭代器教程》, DataCamp ,2018。【在线】。可用:https://www . data camp . com/community/tutorials/python-iterator-tutorial UTM _ source = AdWords _ PPC&UTM _ campaignid = 898687156&UTM _ adgroupid = 48947256715&UTM _ device = c&UTM _ keyword =&UTM _ match type = b&UTM _ network = g&UTM _ ADT
[2] S. B. Lippman,J. Lajoie,和 B. E. Moo, C++初级读本,第 5 版。皮尔森教育。
[3]《迭代器》,2020。【在线】。可用:https://de.wikipedia.org/wiki/Iterator.
[4] S. Gardner,“Scott Gartner 对‘编程语言中迭代器的一些缺点/不足是什么?,' " Quora ,2015。【在线】。可用:https://www . quora . com/What-is-some-visibilities-defect-of-iterators-in-programming-languages。
[5] M. Singh,《C++中迭代器的介绍》, GeeksforGeeks ,2019。【在线】。可用:https://www.geeksforgeeks.org/introduction-iterators-c/.
面向 Tableau 开发人员的 Python 简介(第 1 部分)
原文:https://towardsdatascience.com/a-gentle-introduction-to-python-for-tableau-developers-part-1-862b9bdd1c85?source=collection_archive---------32-----------------------
使用 Python 探索数据
Tableau 让你迷上了数据,但为什么要止步于此呢?
认识你的数据分析新朋友(照片由 Unsplash 上的 Allie 拍摄)
像许多其他人一样,我走进数据世界的第一步是穿着 Tableau 开发人员的鞋子。随着 Tableau 技能的提高,我对 SQL 和 Python 等其他东西的接触也增加了。
随着时间的推移,对这些相邻工具的了解增强了我的日常能力。随着我学习更多的 SQL,我更好地理解了如何以最佳方式将数据输入 Tableau。这使我能够在 Tableau 本身之外,对更广泛的数据流拥有更多的所有权。
Python 是自然的下一步。它通过 Tableau Server REST API 提供了对 Tableau 生态系统的灵活控制,并且语法简单明了。
在领略了 Python 在处理数据、构建可视化和创建预测模型方面带来的好处之后,我想鼓励那些精通 Tableau 但还不习惯 Python 的人尝试一下。
步骤 1:跳过基础知识,避免教程地狱
我们不打算在这里涵盖 Python 语言的绝对基础。如果你曾经学过另一种口语,这有点像在理解如何问候某人或如何说“是”和“不是”之前学习语法的所有细微差别。
如果你想深入研究 Python 的构建模块,我强烈推荐你阅读一些这种经典的(免费的)材料,直到你感到自信为止。
我鼓励您从一开始就将 Python 视为一种有价值的工具,而不是一种在使用之前需要掌握的语言。就这样,让我们开始吧!
第二步:喂养熊猫
如果您正在处理 Python 和数据,那么熊猫包将是您最好的朋友之一。
对于你与熊猫的第一次约会,我们将重温每个 Tableau 开发者都熟悉的东西:全球超市数据集!只需下载文件并保存在运行 python 笔记本/文件的本地目录中。
把这些数据输入熊猫是多么简单:
import pandas as pdstore_df = pd.read_excel('Global Superstore.xls')
下面的代码行执行以下操作:
- 导入 pandas 包,我们将其别名为“pd”。
- 将 Excel 文件“Global Superstore.xls”加载到名为“store_df”的变量中
不必深入太多细节,值得注意的是,数据世界中一个常见的东西是“数据框架”的概念。如果你想知道为什么我们把数据存放在一个名为“store_df”的变量中,你可以把它想成“store dataframe”。在 Python 世界中,“dataframe”的常见缩写是“df”。
第三步:我们刚刚到底给熊猫喂了什么?
使用熊猫套餐的一个好处是它为我们提供了各种便利。例如,让我们看看我们刚刚从“Global Superstore.xls”文件中加载的数据。
store_df.head()
快速简单地查看我们的数据。
不错!使用任何 Pandas 数据帧都可以访问的“head()”函数,我们查看了加载到“store_df”中的数据。这很像我们在 Tableau 工作簿中单击“数据源”选项卡时看到的底层数据。
第四步:选择一个目标,瞄准它
不要抽象地谈论 Python,让我们瞄准一个熟悉的、容易理解的目标。
这是我用 Tableau 的“全球超市”数据整理出来的一张图片:
啊,好熟悉啊!
作为我们在 Python 中的第一个任务,让我们尝试重新创建这个可视化的核心方面。
步骤 5:如何将数据与熊猫分组
在上图中,你可以说我们已经按子类别对数据进行了分组,以显示每个子类别的总销售额。
在 Tableau 世界中,我们的做法是将子类别字段拖到行中,将销售字段拖到列中,如下所示:
请注意,Tableau 已经自动指定了“SUM(Sales)”而不仅仅是“Sales”。在 Tableau 中,很多事情都是自动为你做的。
在 Python 世界中,您的指尖拥有强大的功能和灵活性。还记得蜘蛛侠的名言吗?
"巨大的权力(和灵活性)意味着巨大的责任."…撕了本叔叔。
这里的教训是,我们为 Python 的所有灵活性付出的代价是,我们必须使用代码阐明我们试图用数据做什么。在这种情况下,我们希望按“子类别”对数据进行分组,然后对我们的“销售额”值求和。
下面是我们如何向 Python 阐述这一点:
subcat_sales_df = store_df\
.groupby(['Sub-Category'])\
.agg({'Sales': 'sum', 'Profit': 'sum'})\
.reset_index()\
.sort_values('Sales', ascending=False)
不要介意代码中那些花哨的反斜杠字符,Python 中所做的就是说我们将代码延续到新的一行。我经常这样做是为了让我的代码更易读。拥有可读的代码比最终得到一行你看不懂的失控代码要好。
以下是我们得到的结果:
销售是一个常规数字,不要让显示的格式迷惑你。
所以,让我们一行一行地剖析这段代码。
- 我们声明一个新变量‘subcat _ sales _ df’
- 我们按照“子类别”对“商店 _df”进行了分组
- 合计得出“销售额”和“利润”的总和
- 然后我们重置索引(现在不要担心这个,这是装饰性的)
- 最后,我们按照“销售额”对结果进行降序排序
别太疯狂,好吗?您可能已经熟悉了这些概念,但是您不是在 Tableau 中单击和拖动东西,而是显式地编写代码。
第六步:锻炼你的航海能力
虽然 Pandas 确实有一些基本的可视化功能,但让我们介绍另一个包:Seaborn,它以较少的开销提供了良好的视觉效果。
让我们尝试使用 Seaborn 包复制我们之前的 Tableau 视觉效果:
import seaborn as sns
from matplotlib import pyplot as plt f, ax = plt.subplots(figsize=(10, 6))viz = sns.barplot(
data=subcat_sales_df,
x='Sales',
y='Sub-Category',
color='cornflowerblue',
saturation=0.7
)ax.tick_params(axis='both', which='both', length=0)
ax.set_xlabel("Sales ($M)")
sns.despine(left=True, bottom=True)
哇哦。代码太多了,对吧?试着这样想。当你在 Tableau 中创建一个视觉效果时,你需要做大量的点击来获得合适的格式,不是吗?
例如,您可以双击坐标轴,将其重命名为“Sales ($M)”,或者右键单击并设置格式,去掉网格线和坐标轴刻度。
编写代码时的权衡是,您可以创建一些可重复和可重用的东西,但您确实要为第一次就把它做好付出前期成本。
让我们仔细分析一下赋予这种视觉效果的代码:
- 我们导入了 Seaborn 库(一个可视化库),并将其命名为“sns”
- 我们导入了著名的 matplotlib 库的 pyplot 功能(我们这样做是因为 matplotlib 和 Seaborn 之间有一个有用的交叉——Google 一下可以找到更多!你很快就会比我知道得更多!)
- 我们基本上划分出一些 10 个单位宽、6 个单位高的可视化不动产;请注意,我们可以通过在后面的代码行中修改“ax”变量来修改这个不动产。
- 我们定义视觉。在这种情况下,我们调用 Seaborn 包的‘bar plot’函数,它根据我们的规范构造一个条形图。我们可以看到,我们的条形图基于我们创建的 dataframe,它提供了所需的子类别和销售数据。
- 为了做一些收尾工作,我们修改了在上面(3)中创建的“ax”变量的一些格式。这通过去除刻度线和重新标记轴来清理图表。
挑战自我
此时,您可以选择尖叫着逃离 Python。事实是,如果你已经非常擅长 Tableau,那么你最初几次尝试用 Python 构建任何东西都会很困难。
罗马不是一天建成的,对吗?有一部分可能是。但它可能是一些非常基本的东西,就像我们刚刚在这里建立的一样!
我保证如果你有耐心,花一点时间学习 Python,你会从中受益。最终,你可能会像我一样发现,有些事情你可以在 Python 中完成,而在 Tableau 中却做不到。完成工作很大程度上依赖于拥有合适的工具,所以扩大你的工具箱没有坏处。
包装它
我们能做的还有很多。我们刚刚为自己建造了一个发射台,在下一篇文章中,我们将比这里更进一步。
在下一期文章中,我们将探索将 Tableau 的计算字段知识转移到 Python 世界有多容易。我们还将看到如何通过盈利能力来渲染我们在这里构建的视觉效果。
希望能在那里见到你!
面向 Tableau 开发人员的 Python 简介(第 2 部分)
原文:https://towardsdatascience.com/a-gentle-introduction-to-python-for-tableau-developers-part-2-c18095a03e0e?source=collection_archive---------52-----------------------
使用 PYTHON 探索数据
感受计算和颜色渐变
Joyce McCown 在 Unsplash 上的照片
我们回来了!让我们从本系列的第一篇文章中停止的地方开始,使用我们在那里构建的视觉效果作为起点。
在我们开始之前,让我们为我们将在这里实现的目标做好准备:
- 基于我们对在 Tableau 中创建计算字段的了解,展示如何将其转化为 Python
- 展示我们如何使用颜色来增加视觉效果的深度
在 Tableau 中,你经常会被一个棘手的情况困扰,这个情况需要你进行各种级别的计算。你们中的一些人可能已经通过谷歌搜索到了这一点,如果你在搜索栏中键入“级别”,它会自动完成“细节级别表”(我感觉到你)。
虽然学习 Python 的所有细微差别需要时间,但使用任何编程语言的一个强大方面是您可以自由地创造性地解决问题。您会发现,在 Tableau 中,可能有几种不同的方法来获得正确的结果,而在 Python(或任何编程语言)中,选项几乎是无限的。
我认为 Tableau 做得很好的一件事是标记卡。在这个区域中,你可以拖动字段来修改视觉效果的各个方面,比如大小、颜色、标签和工具提示中提供的细节。让我们来探索一下如何用 Tableau 中的 marks card 将点击过的东西拿走,并用 Python 重新创建它的输出。
在今天的练习中,我们将使用“利润”和“销售额”值创建一个新列(类似于计算字段),并将其命名为“利润比率”。然后,我们将应用这个新列来增强我们在第一篇文章中创建的视觉效果,这样,利润率就决定了视觉效果中的颜色。
首先,让我们在 Tableau 中建立一个基线来进行比较。
第一步:设定目标,首先在 Tableau 中建立目标
让我们回顾一下上周的内容:
作为一个曾经教授 Tableau 培训的人,这勾起了我的回忆。
好吧,那么除了删除网格线(又名非数据墨水),还有什么可以让它变得更好呢?
我们可以尝试按盈利能力着色…让我们通过将“盈利”拖到 marks 卡上的“颜色”来尝试一下:
按子类别销售,按利润着色
给视觉效果添加颜色渐变是很有价值的。但是让我们记住,现在我们是根据总利润来着色的。如果你忽略了“表格”,这是一种引人注目的东西,那么这种视觉效果中的颜色传达了一个明显的信息:销量较高的子类别也有较高的利润。
但是如果我们更想知道哪个子类别相对来说更有利可图呢?仅通过数量分析盈利能力并不能提供全部情况,因为你可以以 0.1%的利润率销售 100 万件商品,比以 50%的利润率销售 1000 件商品获得更多利润。如果我们知道这些产品是什么,也许我们的业务可以将重点转移到每销售单位更有利可图的产品上。
所以让我们看看,从不同的角度来看这些相同的数据,是否能给我们一些启示。
在 Tableau 中,利润率的计算如下所示:
SUM([Profit]) / SUM([Sales])
上面的计算将总利润除以总销售额,得到利润率。
当我们用利润率而不是原始利润来着色时,我们的视觉效果是这样的:
按子类别销售,按利润率着色
这里的差别很微妙,但我们可以立即看到颜色不再遵循以前的规则“顶部较暗,底部较亮”。
纸张和标签,这是底部饲料在我们以前的视觉,似乎带来了最高的利润每销售。
当我们按利润率着色时,我们获得了一个更相关的画面,让我们看到每单位销售的,纸张和标签都做得很好。虽然这些产品带来的销售额较低,但它们带来的收入利润却很高。如果没有这种洞察力,也许我们会忽视这个有利可图的业务领域。
第二步:用 Python 计算利润率
没必要把事情弄得不必要的复杂。首先,就 Python 代码而言,让我们回顾一下上一篇文章中我们离开的地方。
我们有一个名为“subcat_sales_df”的 Pandas 数据框架,它包含“子类别”、“销售额”和“利润”列。
它看起来是这样的:
给定这个数据框架,下面是创建一个新的“利润率”列的步骤:
subcat_sales_df['Profit Ratio'] = subcat_sales_df['Profit'] / subcat_sales_df['Sales']
用简单的英语来说,我们将“利润率”一栏定义为“利润”除以“销售额”。别太疯狂,好吗?
请记住,我们的“subcat_sales_df”数据框架是根据上一篇文章中的原始数据进行预处理的。这又回到了我们之前说过的关于 Python 中的自由和灵活性:你掌控自己的命运。想重塑你的数据并像我们在这里做的那样存储在不同的变量中吗?你完全可以这样做。
我们的“利润率”看起来是这样的:
步骤 3:用 Python 绘制颜色渐变
在我们的上一篇文章中,我们创建了一个条形图,显示每个子类别的销售量。
让我们看看如何实现这一点。下面是我用来为图表添加“利润率”作为颜色渐变的代码:
from matplotlib import cmfig, ax = plt.subplots(figsize=(10, 6))ax = sns.barplot(
data=subcat_sales_df,
x='Sales',
y='Sub-Category',
palette=cm.RdBu(subcat_sales_df['Profit Ratio'] * 7.5)
)ax.tick_params(axis='both', which='both', length=0)
ax.set_xlabel("Sales")
sns.despine(left=True, bottom=True)
不要担心这里所有的“ax”和“fig”废话,这主要与格式(轴标签等)有关。随意摆弄这里看到的标量(7.5);调整它将改变颜色渐变的性质。
这里的关键是“调色板”被设置为 matplotlib 颜色图值。“RdBu”表示该颜色映射从红色到蓝色。颜色映射的值由我们传入的值决定,在本例中是“利润率”数据。
它看起来是这样的:
步骤 4:调和差异
您可能已经注意到,Tableau 的颜色和我们在这里构建的颜色并不完全匹配。那也行!在 Tableau 中,很多事情都是为你决定的,这就是为什么它是一个如此伟大的点击拖动工具。在 Python 中,您控制细节。
在下一篇文章中,我们将更仔细地看看这些细节是如何与更高级的计算结合在一起的!接下来,我们将探索如何加入来自其他来源的数据。
那里见!
Tableau 开发人员对 Python 的简明介绍(第 3 部分)
原文:https://towardsdatascience.com/a-gentle-introduction-to-python-for-tableau-developers-part-3-8634fa5b9dec?source=collection_archive---------67-----------------------
使用 PYTHON 探索数据
将熟悉的数据探索从 Tableau 转换为 Python
Tableau 最大的优势之一是它让你在数据中游来游去。您并不总是需要一个微调的仪表板来找到有意义的见解,因此即使对 Tableau 有相当基本了解的人也可以产生重大影响。
在本文中,我们将探讨这样一个主题,即不需要了解工具的所有信息就可以用它来构建有用的东西。在我们的上一篇文章中,我们谈到了如何在 Python 中创建自定义计算和彩色视觉效果,以获得看起来与我们在 Tableau 中构建的非常相似的视觉效果。
今天,让我们扩展一下到目前为止我们所学的内容。让我们看看如何将我们到目前为止所看到的应用到一个常见的场景:数据探索。
搭建舞台
以前,我们采用“销售”和“利润”列,并创建了一个名为“利润比率”的新列。然后,我们修改了第一篇文章中的图表,显示了每个产品子类别的销售额,并使用我们新的“利润率”指标为视觉效果添加了颜色:
按子类别销售,按利润率着色
每当我教 Tableau 的新人如何使用这个软件时,我总是在混合的某个地方插入这个视觉效果。
我认为数据可视化的一个常见错误是,人们经常认为仅仅因为他们可以使用他们总是应该使用的颜色。如果我们在视觉效果上随机添加颜色,结果通常不会比一个简单的表格更好。一些迷失在调味汁中的视觉效果会让人完全迷惑。
在我们的用例中,颜色是合适的,因为它有助于快速聚焦于期望的“啊哈”启示:更高的销量不一定导致更高的利润。
如果这些数据代表了一个真实的企业,那么随之而来的一个自然的问题可能是:发生了什么,使得我们的一些高销售额项目利润较低(假设这是坏的),而我们的一些低销售额项目利润很高(假设这是好的)?
为了给这个问题提供任何有意义的答案,我们需要做一些数据探索。
第一步:决定关注我们最具影响力的客户
首先,语境很重要。这些数据的背景是,我们是一家销售产品的零售店。顾客只能买我们卖的东西,而且他们是按照我们设定的价格购买的。因此,如果我们有任何负利润,这是我们自己造成的问题。也许我们在某些产品上故意赔钱,降低价格来吸引那些购买其他产品来弥补最初损失的顾客。
我的观点是,不管我们发现了什么,我们都想找到可操作的东西。我们需要能够用我们产生的洞察力做一些事情,否则还有什么意义呢?
因此,与其分析我们所有的客户,不如让我们专注于我们的顶级客户。如果你的外联和客户服务预算有限,将这些资源集中在顶级客户身上通常是有意义的。在本练习中,我们将“顶级客户”定义为每份订单花费最多的客户。简单来说,我们有兴趣了解我们前 10%客户的销售和盈利情况。
对于这个超市数据,这意味着我们正在寻找前 159 名客户。
步骤 2:为我们的客户获取每份订单的销售额
在 Tableau 中,我们将达到一个计算字段。在 Python 中,我们希望首先在适当的聚合级别创建一个数据帧,然后添加一个新列来存储每个订单的平均销售额。
我们想知道每个客户的每个订单的销售额,所以这里合适的聚合级别是客户级别(客户 ID)。
为了计算每个客户的订单销售额,我们需要计算总销售额并计算每个客户的订单数量。
我们可以使用 Pandas 数据帧(注意,“store_df”是存储所有超市数据的数据帧)来拼凑这些数据:
orders_per_customer_df = store_df\
.groupby('Customer ID')\
.agg({
'Order ID': pd.Series.nunique,
'Sales': 'sum'
})\
.reset_index()\
.rename(columns={'Order ID': 'order_count'})\
.sort_values('Sales', ascending=False)
所以让我们像读一本书一样一行一行地读一遍:
- 我们的输出将存储在一个名为“orders_per_customer_df”的变量中
- 我们按照“客户 ID”列对商店数据进行分组
- 我们聚合了两列;“订单 ID”的唯一计数(由 pd 表示。Series.nunique 函数)和“销售额”之和
- 我们正在重置结果数据帧的索引;如果您不知道这意味着什么,那么尝试运行没有该语句的代码,看看结果有什么不同!
- 我们将“订单 ID”列重命名为“order_count ”,这是一个更合适的名称,因为我们不再查看实际的 ID 值
- 我们按照销售额对结果数据框架进行排序,最高值在顶部
步骤 3:计算每个客户的每份订单的总销售额
首先,让我们欣赏一下我们在上一步中创建的数据帧的一个片段:
好的,我们有一个客户的数据框架,这些客户下的订单数量,以及消费总额。
为了计算每份订单的总销售额,我们需要做的就是将“销售额”列除以“订单计数”列。
orders_per_customer_df['avg_sales_per_order'] = \
orders_per_customer_df['Sales'] / orders_per_customer_df['order_count']
在上面的代码片段中,我们定义了一个新列“avg_sales_per_order ”,并将其设置为“sales”列除以“order_count”列的结果。
下面是它的样子,现在按‘avg _ sales _ per _ order’降序排序。
您可以使用。head()函数来得到这样的预览!
步骤 4:查看订单计数分布
让我们做一个快速的侧面探索。比较第 3 步开始时和第 3 步结束时的订单数,我们客户的订单数似乎有很大差异。
为了更好地理解客户行为,让我们来看一下订单数量的分布。
sns.distplot(orders_per_customer_df['order_count'])
运行上面的代码行给我们带来了这个结果:
所有客户的订单计数分布
啊,看起来顾客自然分成两个阵营。一组平均 5 单左右,另一组平均 25 单左右。
这可能反映了我们的产品组合;一些顾客可能购买少量昂贵的商品,而另一些顾客则更频繁地购买较便宜的商品。
步骤 4:过滤我们的数据,只考虑前 10%的客户
在 Tableau 中,一种方法是根据“avg_sales_per_order”的计算字段为“Customer ID”字段创建一个筛选器,并且只包含前 159 个结果。
在 Python 中,一个可能的解决方案是这样的:
top_customers_df = \
store_df[store_df['Customer ID']\
.isin(orders_per_customer_df.head(159)['Customer ID'])]
我们来剖析一下这个。
首先,我们将结果存储在一个名为“top_customers_df”的变量中。
第二,我们使用 Pandas 数据帧符号,本质上是说“给我们满足这个条件的‘store _ df’数据帧的所有行。”在我们的例子中,需要满足的条件是,遇到的任何给定“客户 ID”也必须在“orders_per_customer_df”数据帧的前 159 行的“客户 ID”列中。
换句话说,我们正在过滤我们的商店数据,以便我们只看到包含我们的顶级客户的数据帧的前 159 行中的客户 ID 值的数据。
如果没有点击,请返回查看我们是如何定义“orders_per_customer_df”数据框架的。记住这个。head(x) 函数返回调用它的任何数据帧的前 x 行数。
第五步:为我们的顶级客户预览数据
现在让我们快速看一下结果,我们已经过滤了商店数据,只包括前 159 名客户。让我们按“子类别”进行分组,并汇总数据以查看总销售额、平均折扣百分比、总利润和订单总数。
subcat_top_customers_df = top_customers_df\
.groupby('Sub-Category')\
.agg({
'Sales': 'sum',
'Discount': 'mean',
'Profit': 'sum',
'Order ID': pd.Series.nunique
})\
.rename(columns={
'Discount': 'Avg Discount',
'Order ID': 'Num Orders'
})\
.sort_values('Profit', ascending=False)\
.reset_index()
你感觉到这些熊猫数据框架是如何工作的了吗?我建议您将代码插入自己的程序中,并对其进行试验。如果将“sum”改为“median”、“min”或“max”,会发生什么?
步骤 6:可视化前 10%客户的结果
在查看创建这种视觉效果的代码之前,让我们花点时间深入了解一下。我们在看什么?
在左边,我们看到子类别的总利润。所有利润高于零的柱线都是蓝色的。这里只有一个无利可图的子类别,那就是“桌子”。
还记得上一篇文章中的“表格”吗?这是一个引人注目的子类别。有趣的是,Tables 不仅仅是无利可图,甚至在我们前 10%的客户中也是无利可图。为什么无利可图?
这就是右侧的视觉效果突出显示平均折扣的原因。“桌子”又一次引起了人们的关注,在这里我们可以看到我们的桌子上有一些异常高的折扣。
可能有一个很好的商业理由来大幅打折桌子(也许这是一个亏损的领导者),但至少现在我们知道为什么桌子是无利可图的:它们的折扣率超过 25%,远远高于任何其他产品子类别。
第七步:理解视觉效果是如何组合在一起的
上面的视觉效果是这样的:
fig, axs = plt.subplots(1, 2, figsize=(16, 8), sharey=True)sns.barplot(data=subcat_top_customers_df,
x='Profit', y='Sub-Category', ax=axs[0],
palette=cm.RdBu(subcat_top_customers_df['Profit']), ci=False)sns.barplot(data=subcat_top_customers_df,
x='Avg Discount', y='Sub-Category', ax=axs[1],
palette=cm.RdBu(subcat_top_customers_df['Avg Discount'] * 5.5), ci=False)axs[0].tick_params(axis='both', which='both', length=0)
axs[1].tick_params(axis='both', which='both', length=0)
axs[1].set_ylabel('')sns.despine(left=True, bottom=True)
第一行是您在使用 Python 绘图库时经常看到的内容。我们正在建立一个图形和一组坐标轴。图形就像画布,视觉效果就在上面,而轴充当我们的数字和分类数据的脊梁。在第一行中,我们定义了一个包含两块不动产的图形:一行包含两块并排的地块。“sharey”参数表示两种视觉效果将共享一个 y 轴,因此没有必要列出两次子类别。
然后,我们调用 Seaborn 库,它在前面以别名‘SNS’导入,来绘制我们的条形图。这里我们定义了提供数据的 dataframe,提供 x 轴和 y 轴的列,以及每个视图的颜色渐变。将“ci”参数设置为“False”以删除额外的行,否则这些行会向我们显示置信区间。继续把它翻转到“真”,看看视觉效果如何变化。
最后几行是修饰性的格式,去掉刻度线之类的。我强烈建议对其进行修改,以适应通过代码而不是通过 Tableau 这样的点击-拖动界面进行格式化的概念。通过代码定义格式的好处在于,您可以构建可重用的函数,这些函数总是应用您喜欢的格式技巧。
包装完毕
所以,我们到了。我们的吸引注意力的表格得到了他们一直想要的关注,我们有更多的机会使用熊猫数据框来塑造和控制我们的数据。
这里的数据探索并不是惊天动地的,但是如果您对我们到目前为止编写的 Python 代码感到满意,那么您已经准备好进入我们的下一个会话了!
下次请继续收听,届时我们将探索如何连接不同表中的数据。Pandas 让我们很容易做到这一点,所以对我们来说,将我们的“订单”数据加入到我们的“退货”数据中,并回答这个问题:我们有多少产品被退回了?由于退货,我们的收入减少了多少?
希望在那里见到你!
面向 Tableau 开发人员的 Python 简介(第 4 部分)
原文:https://towardsdatascience.com/a-gentle-introduction-to-python-for-tableau-developers-part-4-a6fd6b2f46b1?source=collection_archive---------58-----------------------
使用 PYTHON 探索数据
用连接和熊猫让你的数据更美味
班农·莫里西在 Unsplash 拍摄的照片
在数据混合、连接和处理 Tableau 中产生的细节层次之间,管理数据之间的关系可能很棘手。
穿上你闪亮的新蟒蛇鞋,世界变得开阔了一些。您可以选择自己的战斗,而不是试图将所有内容都压缩到一个数据源中来统治它们。
在我们以前的文章中,我们已经看到:
- 熊猫分组表情和基本可视化
- 按盈利能力计算和着色销售额
- 高级视觉数据探索
搭建舞台
在本文中,我们将关注在任何生态系统中使用数据的最重要的方面之一:连接。
幸运的是,我们一直在玩的 Tableau 数据附带电池!在我们一直在分析的虚拟商店的上下文中,我们有一些数据详细说明了被返回的各种商品。
让我们在订单和退货上使用这些数据,以便使用 Pandas 库轻松地在 Python 中连接数据。在这个过程中,我们将看到不同类型的连接如何帮助我们实现不同的目标。
步骤 1:快速浏览一下我们想要加入的数据
还记得我们一直在处理的订单数据吗?让我们很快好好看看它。
回想一下 head()函数获取最上面的行,在本例中我们要求获取最上面的 2 行!
啊,很熟悉。现在让我们看看 2 号门后面有什么。但是首先,本着感受熊猫如何工作的精神,让我们强调一下我们是如何得到这些数据的。
在第一篇文章中,我们使用 Pandas read_excel() 函数从 excel 文件中获取订单数据。原来这个文件有多张:
- 命令
- 返回
- 人
让我们暂时忽略“People”表(反正没人喜欢它们),简单地承认这样一个事实:当我们在没有指定表名的情况下使用 read_excel() 函数时,该函数获取了 excel 工作簿中可用的第一个表。
下面是我们如何指定要从“Returns”表中获取数据:
returns_df = pd.read_excel('Global Superstore.xls', sheet_name='Returns')
这些数据是这样的:
没有比这个数据集更简单的了
第二步:避免盲目约会你的数据
在数据加入的世界里,包办婚姻比相亲要好。也就是说,我们希望成为专横的家长,检查我们将要加入数据的列,寻找任何可能导致不匹配的不一致之处。仅仅因为我们假设列匹配就盲目地将我们的数据连接在一起可能会导致一些不希望的结果。
为了证明这一点,让我们走进一次相亲,看看会发生什么。
首先,让我们观察我们的两个数据集有哪些列是相同的。
这些是我们订单的栏目…
这些是我们返回的列
在我看来,我们有共同的“订单 ID”和“市场”。当然,在许多真实的场景中,相同的信息可能以不同的名称存储,但这不是真实的世界。是个例子!
顺便说一下,这里有一个快捷方式,您可以使用它来查找同时存在于两个列列表中的值:
common_cols = [col for col in store_df.columns if col in returns_df.columns]
你刚才看到的叫做列表理解。如果你最终爱上了 Python,这些将成为你的第二天性。它们非常有用。在这种情况下,我们的列表理解为我们提供了列表 X 的任何值,它的值也出现在列表 y 中。
既然我们知道我们有两个共同的专栏,我们还在等什么呢!?发起相亲!
第三步:好吧,让我们给相亲对象一个机会…
所以我们的订单和退货之间有共同的“订单 ID”和“市场”。让我们加入他们。
在 Pandas 中,您可以使用 join() 方法,也可以使用 merge() 方法。不同的人用不同的笔画。在几乎任何场景中,我都更喜欢使用 merge() 方法,所以这就是我们在这里要使用的方法。团队合并,终身。
blind_date_df = store_df.merge(returns_df, on=['Order ID', 'Market'], how='left')
让我们看看结果是什么样的:
我们左连接的结果
首先我们跑了。在生成的数据帧上塑造以获取行数和列数的值(按此顺序)。因此,我们得到的数据帧有 51,290 行和 25 列,而原始订单数据帧有 51,290 行和 24 列。
这个连接有效地为我们的每一行添加了新数据,提供了一个名为“Returned”的附加列,如果订单被返回,该列的值为“Yes”。
注意,在我们的连接中,我们指定了要连接的列以及如何执行连接。这个“左”连接是什么?这仅仅意味着首先出现在那里的表(在本例中是我们的 store_df )将保持原样,新表的数据将分散到相关的地方。
让我们将其与内部连接进行比较:
内连接产生的行数比左连接少
这个内部连接的行为不同于我们的左连接,因为它只保留了两个表之间的交集。如果我们只关心分析返回的订单,这种类型的连接会很有用,因为它会过滤掉所有没有返回的订单。
第四步:那么相亲有什么不好呢?
有时候你认为你什么都知道,这是你最痛苦的时候。在这个例子中,我们认为我们知道我们有两个匹配的列:“订单 ID”和“市场”。但是,我们的两个数据集在什么是市场上达成一致了吗?
让我们来点刺激的。订单,你如何定义你的市场?
store_df['Market'].unique()
一份令人尊敬的市场列表…除了你拼写了加拿大,并对其他市场使用了首字母缩略词
这行代码查看整个“Market”列,并输出在其中找到的唯一值。
好吧。回报,你如何定义你的市场?
一份令人尊敬的名单……等等,“美国”被拼出来了?
看起来我们的订单和退货团队都需要在是否使用市场的首字母缩略词或拼写它们方面达成一致。
在订单方面,为了避免将来的问题,我们可能应该将“Canada”转换为类似“CA”的缩写值。
在回报方面,为了避免将来的问题,我们可能应该将“美国”改为“美国”
但是等等,这只能解决未来的问题…现在这会导致什么样的问题呢?
步骤 5:盲连接后的清理
要了解我们所处的困境,让我们看看每个市场有多少回报(使用前面的内部连接):
丢了什么吗?
万岁,看起来我们的美国市场是完美的,没有回报!或者等等,是美国市场吗…啊,哎呀。
因为包含订单的数据将市场称为“美国”,而包含退货的数据将市场称为“美国”,所以连接将永远不会匹配这两个市场。
幸运的是,给我们的市场重新命名真的很容易。在这种情况下,有一种快速的方法可以做到这一点,因为只有一个不匹配导致了问题。这引入了 lambda 函数的概念,如果它对你没有意义,你可以忽略它。
returns_df['Market'] = returns_df['Market'].apply(lambda market: market.replace('United States', 'US'))
基本上,这是在运行中创建一个函数,我们可以用它在一行代码中快速执行一个有用的操作。运行上面那行代码的结果是,任何出现的“美国”市场都被重命名为“US”。
现在,如果我们运行 store_df 和 returns_df 之间的内部连接,结果看起来会有点不同:
如果我们检查每个市场有多少回报,我们得到这个:
第六步:对数据上瘾者的一点挑战
现在我们知道了如何连接我们的订单和我们的退货,您能想出如何拼接一个如下所示的表格吗?
看起来“桌子”子类别再次引起了人们的注意!我们无法逃避它。
运用到目前为止我们在这个系列中学到的知识,您能自己重新创建这个表吗?如果你是一个真正的超额完成者,那就继续在 Tableau 中构建它,并比较这个过程。你如何处理 Tableau vs Python 中的市场不匹配?有多种方法可以破解这个案子——去试试吧!
包装它
如果您正在大规模处理数据,连接数据绝对是一项至关重要的技能。请记住,理解您要连接的内容与了解如何执行连接的技术细节一样重要!
如果你在一次相亲中发送你的数据以加入另一个表,要意识到风险。在将数据集与其他数据一起发送到约会地点之前,请清理数据集。脏数据往往会留下一堆乱七八糟的东西,而您将是解决这些问题的人。
希望下次在我们深入研究使用函数制作可重用代码时能见到您!
Python 正则表达式的简明介绍
原文:https://towardsdatascience.com/a-gentle-introduction-to-regular-expressions-with-python-4f3fce46dcb4?source=collection_archive---------40-----------------------
教程| Python
正则表达式是数据科学家对付非结构化文本最强大的武器
照片由 Marius Masalar 在 Unsplash 上拍摄
我们生活在一个以数据为中心的时代。数据已被描述为新油。但是就像石油一样,原始数据并不总是有用的。一种在其原始形式下特别难以使用的数据形式是 非结构化数据 。
很多数据是非结构化数据。非结构化数据不太适合用于分析的格式,比如 Excel 电子表格或 pandas DataFrame 。文本数据是一种常见的非结构化数据,这使得它很难处理。输入 正则表达式 ,简称 regex 。一开始它们可能看起来有点吓人,但是一旦你开始使用它们,你很快就会像这条蛇一样舒服了🐍!
更适应 python?试试我的教程,用 R 代替 regex:
[## R 正则表达式的简明介绍
正则表达式是数据科学家对付非结构化文本最强大的武器。他们曾经是野餐…
medium.com](https://medium.com/@atseewal/a-gentle-introduction-to-regular-expressions-with-r-df5e897ca432)
正则表达式模块(re)
我们将使用正则表达式模块。要将其导入 python 项目,请使用以下命令:
看到多简单了吗?re
模块内置在 python 中,不需要安装。让我们来看看本模块中提供的几个功能:
re.findall(pattern, string)
:该函数返回一个包含string
中pattern
所有实例的列表re.sub(pattern, repl, string)
:该函数返回string
,将string
中的pattern
实例替换为repl
蒂姆·柯林斯在 Unsplash 上拍摄的照片
您可能已经使用过这些功能。他们有非常简单的应用程序,不需要添加正则表达式。回想一下社交距离之前的时代,想象一下在公园里的一次美好野餐。这里有一个例子,是每个人带去野餐的东西。我们可以用它来演示 regex 函数的基本用法:
basic_string = 'Drew has 3 watermelons, Alex has 4 hamburgers, Karina has 12 tamales, and Anna has 6 soft pretzels'
如果我想从这个字符串中提取一个人名字的每个实例,我只需将名字和basic_string
传递给re.findall()
:
re.findall()的基本用法
结果将是一个包含该模式所有实例的列表。使用这个例子,basic_find
将是一个带有一个条目的列表:
['Drew']
现在让我们想象一下,亚历克斯把他的 4 个汉堡包忘在野餐的地方,被肖恩偷走了。re.sub()
可以用 Shawn 替换 Alex 的任何实例:
re.sub()的基本用法
结果字符串将显示 Shawn 现在有 4 个汉堡包。多么幸运的家伙🍔。
Drew has 3 watermelons, Shawn has 4 hamburgers, Karina has 12 tamales, and Anna has 6 soft pretzels
到目前为止,这些例子都很基本。他们有一个时间和地点,但是如果我们想知道野餐中总共有多少食物呢?有物品的都是些什么人?如果我们需要熊猫数据框架中的这些数据来进行进一步分析,该怎么办?这就是你开始看到 regex 的好处的地方。
正则表达式词汇
驱动正则表达式的有几个概念:
- 字符集
- 元字符
- 量词
- 捕获组
这不是一个详尽的列表,但足以帮助我们立即行动。
字符集
字符集表示括号内的选项,正则表达式只匹配其中一个选项。我们可以对字符集做很多事情:
- 匹配一组字符:我们可以通过将每个元音放在括号中找到字符串中的所有元音,例如
[aeiou]
用括号组查找所有元音
['e', 'a', 'a', 'e', 'e', 'o', 'e', 'a', 'a', 'u', 'e', 'a', 'i', 'a', 'a', 'a', 'a', 'e', 'a', 'a', 'a', 'o', 'e', 'e']
- 匹配一个范围的字符:通过使用连字符、
[A-F]
,我们可以找到从“A”到“F”的任何大写字母。字符集区分大小写,所以[A-F]
和[a-f]
不一样
查找所有带括号组的大写字母
['D', 'A', 'K', 'A']
- 匹配一个范围的数字:我们可以通过添加数字到我们的字符集来查找一个范围内的数字,
[0-9]
查找任何数字。
用括号组查找所有数字
['3', '4', '1', '2', '6']
字符集可以同时包含这一部分的所有内容,所以类似于[A-Ct-z7-9]
的内容仍然有效。它将匹配从大写字母“A”到大写字母“C”、小写字母“t”到小写字母“z”以及 7 到 9 的所有字符。
到目前为止,我们还不能回答之前提出的关于括号组的任何问题。让我们为我们的正则表达式库添加更多的武器。
元字符
元字符代表一种类型的字符。它们通常以反斜杠\
开头。每一个都匹配一个字符。以下是一些最重要的例子:
\s
:这个元字符代表空格。这将匹配每个空格、制表符和换行符。您还可以分别为制表符和换行符指定\t
和\n
。附注:我们的示例字符串没有任何制表符,但是在寻找它们时要小心。许多集成开发环境或 IDE 都有一个设置,当你输入时,它会用空格替换所有的制表符。在示例字符串中,\s
返回一个包含 17 个空格的字符串,这正好是示例字符串中的空格数!
动作中的元角色
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
\w
:该元字符代表字母数字字符。这包括所有字母 a-z,大写和小写,以及数字 0-9。这相当于括号组[A-Za-z0-9]
,只是写起来更快。注意记住\w
元字符本身只捕获单个字符,而不是整个单词或数字。你会在例子中看到。别担心,我们很快就会知道如何处理。
\w 活动中的元字符
['D', 'r', 'e', 'w', 'h', 'a', 's', '3', 'w', 'a', 't', 'e', 'r', 'm', 'e', 'l', 'o', 'n', 's', 'A', 'l', 'e', 'x', 'h', 'a', 's', '4', 'h', 'a', 'm', 'b', 'u', 'r', 'g', 'e', 'r', 's', 'K', 'a', 'r', 'i', 'n', 'a', 'h', 'a', 's', '1', '2', 't', 'a', 'm', 'a', 'l', 'e', 's', 'a', 'n', 'd', 'A', 'n', 'n', 'a', 'h', 'a', 's', '6', 's', 'o', 'f', 't', 'p', 'r', 'e', 't', 'z', 'e', 'l', 's']
\d
:该元字符代表数字。使用我们之前的野餐例子,看看它如何只找到字符串中的数字。你会注意到,像括号组一样,它选取 5 个数字,而不是我们期望的 4 个。这是因为它寻找的是每个单独的数字,而不是一组数字。接下来我们将看到如何用量词来解决这个问题。
\d 活动中的元字符
['3', '4', '1', '2', '6']
量词
正如我们在上一节中看到的,单个元字符的功能有限。当涉及到单词或数字时,我们通常希望一次找到 1 个以上的字符。这就是量词的用武之地。它们允许你量化你期望的字符数量。他们总是在被量化的人物之后出现,有几种类型:
+
量化 1 个或多个匹配。让我们看一个新的例子来开发一些关于每个量词将返回什么的直觉:quant_example
显示量词的示例字符串
当我们在quant_example
上使用+
量词时,它将返回 4 个匹配。提到 regex 寻找非重叠匹配是一个很好的理由。在这种情况下,它会查看每个 B 及其后面的字符。因为我们使用了+
量词,所以它继续匹配,直到到达一组 B 的末尾。
实际中的+量词
['B', 'BB', 'BBB', 'BBBB']
{}
量化特定数量或范围的匹配。当像{2}
这样书写时,它将精确匹配前面的 2 个字符。我们会看到一些有趣的结果。它找到了 4 根火柴。这是因为它正在寻找每个不重叠的 2 B 组。第 1 组中有一个匹配,第 2 组中只有 1 个非重叠匹配,第 4 组中有 2 个非重叠匹配。
['BB', 'BB', 'BB', 'BB']
当写成类似{2,4}
的形式时,它将匹配出现 2 到 4 次的任意数量的 B。注意,在正则表达式中放一个空格是无效的。它将返回一个空列表。
['BB', 'BBB', 'BBBB']
我们也可以写这个量词,像{2,}
一样省略上界。这将匹配 2 个或更多实例。对于quant_example
,它将返回与{2,4}
完全相同的结果。
*
量化零个或多个匹配项。这在我们寻找可能在字符串中也可能不在字符串中的东西时很有帮助。
*
量词单独使用时会返回一些奇怪的匹配,所以我们可以省略一个用quant_example
的例子。我们将在下面的例子中看到,当某人在我们的野餐中带了一个有多个单词名称的食物时,它是如何应用的。没有它,我们就不会正确地捕捉到安娜带来了软椒盐卷饼!
让我们结合目前所知的字符集、元字符和量词来回答一些关于我们的野餐字符串的问题。我们想知道字符串中的所有单词,以及字符串中的数字。
对于单词,我们可以使用一个全部大写和小写字母的字符集,给它添加一个+
量词。这将找到任何长度的字母字符组合在一起。换句话说,它会找到所有的单词。Regex 看起来越来越有用了。
['Drew', 'has', 'watermelons', 'Alex', 'has', 'hamburgers', 'Karina', 'has', 'tamales', 'and', 'Anna', 'has', 'soft', 'pretzels']
为了找到每种食物的数量,我们可以使用\d
元字符和量词{1,2}
。这将查找长度为 1 或 2 个字符的数字组。这是一个更有用的输出,因为我们有同样数量的食物和人!
['3', '4', '12', '6']
为了找到每种食物的数量和名称,我们可以将量词和元字符结合起来。我们知道每个数字后面都有一个食物项目,所以我们可以添加到前面的例子中。我们知道有一个空格和一个单词(\s\w+
)后面可以跟另一个单词,比如“软椒盐卷饼”是如何出现的。要指定第二个词可能不在那里,我们可以用量词*
与第二个词连用。就像这样,我们有一份清单,上面列有野餐中所有物品的数量和名称。
['3 watermelons', '4 hamburgers', '12 tamales', '6 soft pretzels']
捕获组
捕获组允许您查找整个短语,并且只返回其中的一部分。以我们的例子为例,我需要每个人的名字,他们带了什么,带了多少。
['Drew has 3 watermelons',
'Alex has 4 hamburgers',
'Karina has 12 tamales',
'Anna has 6 soft pretzels']
我们在capture_group1
中使用的正则表达式正在寻找一个名称,它以一个大写字母开始,后面有任意数量的小写字母([A-Z][a-z]+
)。然后在一个空格之后,它匹配模式空格,单词,空格\s\w+\s
。接下来,我们要寻找一个 1 到 2 位数的数字,后跟一个空格和一个单词(\d{1,2}\s\w+
)。您可以在输出中看到,我们得到了一个字符串,其中包含每个人的详细信息。
现在这是从我们开始的地方前进了一大步,但是我们真的不在乎“有”这个词,我们希望能够从数量上制作一个熊猫的数据框架。让我们添加捕获组。通过使用捕获组,我们可以返回一个包含所需信息的元组。我们将创建包含每个名称、数量和项目的捕获组。捕获组只是用括号括起来的正则表达式的一部分。
[('Drew', '3', 'watermelons'), ('Alex', '4', 'hamburgers'), ('Karina', '12', 'tamales'), ('Anna', '6', 'soft pretzels')]
就这样,我们现在有了一个元组列表,其中包含了我们想要的确切信息!
将我们的文本组合成一个数据帧
在进行数据分析时,最有用的 python 数据结构之一是 pandas 数据框架。毫无疑问,如果你点击了这篇文章,你就已经知道了。数据框架支持计算列统计数据和绘制数据。因为我们有一个元组列表,其中包含了我们想要的数据帧中的所有信息,所以我们可以遍历这个列表,构建我们的数据帧。
| Name | Quantity | Item |
| ------ | -------- | ------------- |
| Drew | 3 | watermelons |
| Alex | 4 | hamburgers |
| Karina | 12 | tamales |
| Anna | 6 | soft pretzels |
结论和进一步学习
我们只讨论了 regex 如何帮助处理非结构化文本数据的一小部分。这是一个很好的入门基础,但是不久之后你将需要知道一些概念,比如如何找到除了一个字符之外的所有内容(否定),或者找到紧接在其他内容之前或之后的内容(环视)。查看我关于这些概念的另一篇文章。
[## 起锚!更多你希望知道的 Python 正则表达式
使用 Python 中的高级正则表达式工具处理文本的秘密
towardsdatascience.com](/anchors-away-more-python-regular-expressions-you-wish-you-knew-8a7780ac54e9)
这里有更多的资源可以帮助您了解 regex 中的其他概念:
- 官方
[re](https://docs.python.org/3/library/re.html)
文档:虽然文档看起来令人生畏,但是学习如何阅读它只会在你编程的时候对你有所帮助 - w3schools 参考资料:庞大的编码和脚本语言参考资料知识库,包括 python。他们的许多例子都可以通过点击“自己尝试”按钮直接在浏览器上运行
- Datacamp 课程(付费链接):一个致力于数据科学、机器学习和数据可视化的在线学习社区。查看他们的课程“Python 中的正则表达式”网站上每门课程的第一章都是免费的!
[## 通过我的推荐链接加入 Medium-Drew Seewald
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
realdrewdata.medium.com](https://realdrewdata.medium.com/membership)
R 正则表达式的简明介绍
原文:https://towardsdatascience.com/a-gentle-introduction-to-regular-expressions-with-r-df5e897ca432?source=collection_archive---------13-----------------------
教程| R |正则表达式(Regex)
正则表达式是数据科学家对付非结构化文本最强大的武器
蒂姆·柯林斯在 Unsplash 上拍摄的照片
我们生活在一个以数据为中心的时代。数据已被描述为新油。但是就像石油一样,原始数据并不总是有用的。一种在其原始形式下特别难以使用的数据形式是 非结构化数据 。
很多数据是非结构化数据。非结构化数据不太适合分析格式,比如 Excel 电子表格或数据框。文本数据是一种常见的非结构化数据,这使得它很难处理。输入正则表达式,简称 regex 。一开始它们可能看起来有点吓人,但是一旦你开始使用,使用它们将会很容易!
更适应 python?请尝试我的教程来使用 python 的正则表达式:
[## Python 正则表达式的简明介绍
正则表达式是数据科学家对付非结构化文本最强大的武器
towardsdatascience.com](/a-gentle-introduction-to-regular-expressions-with-python-4f3fce46dcb4)
stringr
图书馆
我们将使用stringr
库。stringr
库是基于 C 库构建的,所以它的所有功能都非常快。
要在 R 中安装和加载stringr
库,使用以下命令:
看到多简单了吗?更简单的是,stringr
包中的大多数函数名都以str
开头。让我们来看看本模块中提供的几个功能:
str_extract_all(string, pattern)
:该函数返回一个包含string
中pattern
所有实例的向量列表str_replace_all(string, pattern, replacement)
:该函数返回string
,将string
中的pattern
实例替换为replacement
您可能已经使用过这些功能。他们有非常简单的应用程序,不需要添加正则表达式。回想一下社交距离之前的时代,想象一次公园里的野餐,就像上面的图片。这里有一个例子,是每个人带去野餐的东西。我们可以用它来演示 regex 函数的基本用法:
basicString <- "Drew has 3 watermelons, Alex has 4 hamburgers, Karina has 12 tamales, and Anna has 6 soft pretzels"
如果我想从这个字符串中提取一个人名字的每个实例,我只需将名字和basic_string
传递给str_extract_all()
:
结果将是一个包含该模式所有实例的列表。使用这个例子,basicExtractAll
将有下面的列表,其中 1 个向量作为输出:
[[1]]
[1] "Drew"
现在让我们想象一下,亚历克斯把他的 4 个汉堡包忘在野餐的地方,被肖恩偷走了。str_replace_all
可以用 Shawn 替换 Alex 的任何实例:
结果字符串将显示肖恩现在有 4 个汉堡。多么幸运的家伙🍔。
"Drew has 3 watermelons, Shawn has 4 hamburgers, Karina has 12 tamales, and Anna has 6 soft pretzels"
到目前为止,这些例子都很基本。他们有一个时间和地点,但是如果我们想知道野餐中总共有多少食物呢?有物品的都是些什么人?如果我们需要数据框中的这些数据来进行进一步分析,该怎么办?这就是你开始看到 regex 的好处的地方。
正则表达式词汇
驱动正则表达式的有几个概念:
- 字符集
- 元字符
- 量词
- 捕获组
这不是一个详尽的列表,但足以帮助我们立即行动。
字符集
字符集表示括号内的选项,正则表达式只匹配其中一个选项。我们可以对字符集做很多事情:
- 匹配一组字符:我们可以通过将每个元音放在括号中找到字符串中的所有元音,例如
[aeiou]
[[1]]
[1] "e" "a" "a" "e" "e" "o" "e" "a" "a" "u" "e" "a" "i" "a"
[15] "a" "a" "a" "e" "a" "a" "a" "o" "e" "e"
- 匹配一个范围的字符:我们可以通过使用连字符、
[A-F]
找到从“A”到“F”的任何大写字母。字符集区分大小写,因此[A-F]
与[a-f]
不同
[[1]]
[1] "D" "A" "K" "A"
- 匹配一个范围的数字:我们可以通过添加数字到我们的字符集中来查找一个范围内的数字,
[0-9]
来查找任何数字。请注意,这些数字是作为字符串提取的,而不是转换成数字
[[1]]
[1] "3" "4" "1" "2" "6"
字符集可以同时包含这一部分的所有内容,所以类似于[A-Ct-z7-9]
的内容仍然有效。它将匹配从大写字母“A”到大写字母“C”、小写字母“t”到小写字母“z”以及 7 到 9 的所有字符。
到目前为止,我们还不能回答之前提出的关于括号组的任何问题。让我们为我们的正则表达式库添加更多的武器。
元字符
元字符代表一种类型的字符。它们通常以反斜杠\
开头。由于反斜杠\
是 R 中的一个特殊字符,每次和另一个反斜杠一起使用时都需要进行转义。换句话说, R 在使用元字符时需要 2 个反斜杠。每个元字符将匹配单个字符。以下是一些最重要的例子:
\\s
:这个元字符代表空格。这将匹配每个空格、制表符和换行符。您还可以分别为制表符和换行符指定\\t
和\\n
。附注:我们的示例字符串没有任何制表符,但是在寻找它们时要小心。许多集成开发环境或 IDE 都有一个设置,当你输入时,它会用空格替换所有的制表符。在示例字符串中,\\s
返回一个包含 17 个空格的向量列表,这是示例字符串中空格的确切数目!
[[1]]
[1] " " " " " " " " " " " " " " " " " " " " " " " " " " " "
[15] " " " " " "
\\w
:该元字符代表字母数字字符。这包括所有字母 a-z,大写和小写,以及数字 0-9。这相当于括号组[A-Za-z0-9]
,只是写起来更快。记住\\w
元字符本身只捕获单个字符,而不是整个单词或数字。你会在例子中看到。不要担心,我们将在下一节处理这个问题。
[[1]]
[1] "D" "r" "e" "w" "h" "a" "s" "3" "w" "a" "t" "e" "r" "m"
[15] "e" "l" "o" "n" "s" "A" "l" "e" "x" "h" "a" "s" "4" "h"
[29] "a" "m" "b" "u" "r" "g" "e" "r" "s" "K" "a" "r" "i" "n"
[43] "a" "h" "a" "s" "1" "2" "t" "a" "m" "a" "l" "e" "s" "a"
[57] "n" "d" "A" "n" "n" "a" "h" "a" "s" "6" "s" "o" "f" "t"
[71] "p" "r" "e" "t" "z" "e" "l" "s"
\\d
:该元字符代表数字。使用我们的野餐例子,看看它如何只找到字符串中的数字。你会注意到,像括号组一样,它选取 5 个数字,而不是我们期望的 4 个。这是因为它寻找的是每个单独的数字,而不是一组数字。接下来我们将看到如何用量词来解决这个问题。
[[1]]
[1] "3" "4" "1" "2" "6"
量词
正如我们在上一节中看到的,单个元字符的功能有限。当涉及到单词或数字时,我们通常希望一次找到 1 个以上的字符。这就是量词的用武之地。它们允许你量化你期望的字符数量。他们总是在被量化的人物之后出现,有几种类型:
+
量化 1 个或多个匹配。让我们看一个新的例子来开发一些关于每个量词将返回什么的直觉:quantExample
当我们在quantExample
上使用+
量词时,它将返回 4 个匹配。提到 regex 寻找非重叠匹配是一个很好的理由。在这种情况下,它会查看每个 B 及其后面的字符。因为我们使用了+
量词,所以它继续匹配,直到到达一组 B 的末尾。
[[1]]
[1] "B" "BB" "BBB" "BBBB"
{}
量化特定数量或范围的匹配。当像{2}
这样书写时,它将精确匹配前面的 2 个字符。我们会看到一些有趣的结果。它找到了 4 根火柴。这是因为它正在寻找每个不重叠的 2 B 组。第 1 组中有一个匹配,第 2 组中只有 1 个非重叠匹配,第 4 组中有 2 个非重叠匹配。
[[1]]
[1] "BB" "BB" "BB" "BB"
当写成类似{2,4}
的形式时,它将匹配出现 2 到 4 次的任意数量的 B。注意,在正则表达式中放一个空格是无效的。它将返回一个空列表。
[[1]]
[1] "BB" "BBB" "BBBB"
我们也可以写这个量词,像{2,}
一样省略上界。这将匹配 2 个或更多实例。对于quantExample
,它将返回与{2,4}
完全相同的结果。
*
量化零个或多个匹配项。这在我们寻找可能在字符串中也可能不在字符串中的东西时很有帮助。
*
量词单独使用时会返回一些奇怪的匹配,所以我们可以省略一个用quantExample
的例子。我们将在下面的例子中看到,当某人在我们的野餐中带来一个有多个单词名称的食物时,它是如何应用的。没有它,我们就不会正确地捕捉到安娜带来了软椒盐卷饼!
让我们结合目前所知的字符集、元字符和量词来回答一些关于我们的野餐字符串的问题。我们想知道字符串中的所有单词,以及字符串中的数字。
对于单词,我们可以使用一个全部大写和小写字母的字符集,给它添加一个+
量词。这将找到任何长度的字母字符组合在一起。换句话说,它会找到所有的单词。Regex 看起来越来越有用了。
[[1]]
[1] "Drew" "has" "watermelons" "Alex"
[5] "has" "hamburgers" "Karina" "has"
[9] "tamales" "and" "Anna" "has"
[13] "soft" "pretzels"
为了找到每种食物的数量,我们可以使用\\d
元字符和量词{1,2}
。这将查找长度为 1 或 2 个字符的数字组。这是一个更有用的输出,因为我们有同样数量的食物和人!
[[1]]
[1] "3" "4" "12" "6"
为了找到每种食物的数量和名称,我们可以将量词和元字符结合起来。我们知道每个数字后面都有一个食物项目,所以我们可以添加到前面的例子中。我们知道有一个空格和一个单词(\\s\\w+
)后面可以跟另一个单词,比如“软椒盐卷饼”是如何出现的。要指定第二个词可能不在那里,我们可以用量词*
与第二个词连用。就像这样,我们有一份清单,上面列有野餐中所有物品的数量和名称。
[[1]]
[1] "3 watermelons" "4 hamburgers" "12 tamales"
[4] "6 soft pretzels"
捕获组
捕获组允许您查找整个短语,并且只返回其中的一部分。以我们的例子为例,我需要每个人的名字,他们带了什么,带了多少。到目前为止,我们一直使用str_extract_all
。它有一个清晰的输出,对于我们的例子来说很容易阅读,但是它实际上不能与捕获组一起工作。有帮助的是,stringr
提供了str_match_all
,它确实可以与捕获组一起工作。但是,它输出的结果是包含矩阵的列表,而不是包含向量的列表。
[[1]]
[,1]
[1,] "Drew has 3 watermelons"
[2,] "Alex has 4 hamburgers"
[3,] "Karina has 12 tamales"
[4,] "Anna has 6 soft pretzels"
我们在captureGroup1
中使用的正则表达式正在寻找一个名称,它以一个大写字母开始,后面有任意数量的小写字母([A-Z][a-z]+
)。然后在一个空格之后,它匹配模式空格、单词、空格\\s\\w+\\s
。接下来,我们寻找一个 1 到 2 位数的数字,后跟一个空格和一个单词(\\d{1,2}\\s\\w+
)。您可以在输出中看到矩阵的每一行都是一个字符串,包含每个人的详细信息。
现在,这是从我们开始的地方迈出的一大步,但我们并不真正关心“有”这个词,我们希望能够从数量中制作一个数据框。让我们添加捕获组。通过使用捕获组,我们可以返回一个矩阵,其中每一列包含一条特定的信息。我们将创建包含每个名称、数量和项目的捕获组。捕获组只是用括号括起来的正则表达式的一部分。
[[1]]
[,1] [,2] [,3] [,4]
[1,] "Drew has 3 watermelons" "Drew" "3" "watermelons"
[2,] "Alex has 4 hamburgers" "Alex" "4" "hamburgers"
[3,] "Karina has 12 tamales" "Karina" "12" "tamales"
[4,] "Anna has 6 soft pretzels" "Anna" "6" "soft pretzels"
矩阵中的第一列包含整个正则表达式,忽略了捕获组。矩阵的其余列分别对应于我们为名称、数量和项目定义的捕获组。
将我们的文本合并到一个数据框中
在进行数据分析时,最有用的 R 数据结构之一是数据帧。毫无疑问,如果你点击了这篇文章,你就已经知道了。数据框支持计算列统计数据和绘制数据等功能。因为我们有一个包含所有我们想要的信息的矩阵,把它转换成一个数据框架并不太难。除了矩阵的第一列,我们将对所有内容使用data.frame
函数。data.frame
给出了默认的列名,所以我们将修改它们以匹配每一列中的内容。
关于符号的一个快速注释:在captureGroup2
( [[1]]
)之后的第一组括号访问列表的第一个元素,我们的矩阵。第二组括号([,-1]
)选择除第一行以外的所有行和列。
| | Name | Quantity | Item |
| - | ------ | -------- | ------------- |
| 1 | Drew | 3 | watermelons |
| 2 | Alex | 4 | hamburgers |
| 3 | Karina | 12 | tamales |
| 4 | Anna | 6 | soft pretzels |
结论和进一步学习
我们只讨论了 regex 如何帮助处理非结构化文本数据的一小部分。这是一个很好的入门基础,但是不久之后你将需要知道一些概念,比如如何找到除了一个字符之外的所有内容(否定),或者找到紧接在其他内容之前或之后的内容(环视)。你可以在我的后续文章中了解这些:
[## 起锚!R 中更多的正则表达式概念
更先进的正则表达式工具,为您的 R 文本争论武器库
medium.com](https://medium.com/@atseewal/anchors-away-more-regex-concepts-in-r-f00fe7f07d52)
这里有更多的资源可以帮助您了解 regex 中的其他概念:
- tidy verse 网站官方
[stringr](https://stringr.tidyverse.org/index.html)
页面: RStudio 的伙计们整理了资源帮助学习stringr
之类的软件包。他们甚至包括一个[stringr](https://github.com/rstudio/cheatsheets/blob/master/strings.pdf)
备忘单,你可以打印出来参考。 - R for Data Science :作者 Hadley Wickham,
stringr
package 的作者,这本书对于 R 中的任何东西都是一个很好的参考。甚至有一章涵盖了 R 中更高级的正则表达式。它可以在网上免费获得这里,或者你可以在这里购买硬拷贝。免责声明:我通过此链接收到您购买的佣金。 - Datacamp 课程:一个致力于数据科学、机器学习和数据可视化的在线学习社区。查看他们的课程“用 r 中的 stringr 进行字符串操作”,网站上每个课程的第一章都是免费的!免责声明:如果您使用 此 链接注册每月 Datacamp 订阅,您将获得订阅折扣,我将获得佣金。在你学习的同时支持我的写作!
[## 通过我的推荐链接加入 Medium-Drew Seewald
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
realdrewdata.medium.com](https://realdrewdata.medium.com/membership)
自我训练和半监督学习简介
原文:https://towardsdatascience.com/a-gentle-introduction-to-self-training-and-semi-supervised-learning-ceee73178b38?source=collection_archive---------1-----------------------
用 Python 编写一个利用未标记数据进行分类的自我训练示例
照片由珍妮·希尔在 Unsplash 拍摄
当涉及到机器学习分类任务时,可用于训练算法的数据越多越好。在监督学习中,这些数据必须根据目标类进行标记,否则,这些算法将无法学习自变量和目标变量之间的关系。但是,在构建用于分类的大型标记数据集时,会出现一些问题:
- 标注数据可能非常耗时。假设我们有 1,000,000 张狗的图像要输入到一个分类算法中,目标是预测每张图像中是否包含一只波士顿梗。如果我们想将所有这些图像用于监督分类任务,我们需要一个人来查看每张图像,并确定是否存在波士顿梗。虽然我有朋友(和妻子)不介意整天浏览狗狗照片,但这可能不是我们大多数人想要的周末。
- 标注数据可能会很贵。请看原因 1:为了让某人费力地搜索 100 万张狗的照片,我们可能不得不支付一些现金。
那么,如果我们只有足够的时间和金钱来标记大型数据集的某些部分,而选择不标记其余部分,会怎么样呢?这种未标记的数据可以用在分类算法中吗?
这就是半监督学习的用武之地。在采用半监督方法时,我们可以在少量标记数据上训练分类器,然后使用分类器对未标记数据进行预测。因为这些预测可能比随机猜测更好,所以未标记的数据预测可以在分类器的后续迭代中被用作“伪标记”。虽然半监督学习有很多种风格,但这种特定的技术被称为自我训练。
自我训练
自我训练
在概念层面上,自我训练是这样的:
步骤 1: 将标记的数据实例分割成训练集和测试集。然后,在标记的训练数据上训练分类算法。
步骤 2: 使用训练好的分类器来预测所有未标记数据实例的类别标签。在这些预测的类别标签中,正确概率最高的被采用作为'伪标签'。
(步骤 2 的几个变体: a) 所有预测的标签可以一次被采用为‘伪标签’,而不考虑概率,或者 b) 【伪标签】数据可以通过预测的置信度来加权。)
步骤 3: 将“伪标记的”数据与标记的训练数据连接起来。在组合的“伪标记”和标记的训练数据上重新训练分类器。
步骤 4: 使用训练好的分类器来预测标记的测试数据实例的类别标签。使用您选择的度量评估分类器性能。
(可以重复步骤 1 至 4,直到步骤 2 中不再有预测的类别标签满足特定的概率阈值,或者直到不再有未标记的数据剩余。)
好的,明白了吗?很好!让我们看一个例子。
示例:使用自我训练来改进分类器
为了演示自我训练,我使用了 Python 和 surgical_deepnet 数据集,可从 Kaggle 上的这里获得。该数据集旨在用于二元分类,包含 14.6k+手术的数据。这些属性是 bmi、年龄和各种其他指标,而目标变量并发症记录了患者是否因手术而出现并发症。显然,能够准确预测患者是否会遭受手术并发症,将符合医疗保健和保险提供商的最大利益。
进口
对于本教程,我导入了 numpy 、 pandas 和 matplotlib 。我还将使用来自 sklearn 的 LogisticRegression 分类器,以及 f1_score 和 plot_confusion_matrix 函数进行模型评估。
加载数据
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 14635 entries, 0 to 14634
Data columns (total 25 columns):
bmi 14635 non-null float64
Age 14635 non-null float64
asa_status 14635 non-null int64
baseline_cancer 14635 non-null int64
baseline_charlson 14635 non-null int64
baseline_cvd 14635 non-null int64
baseline_dementia 14635 non-null int64
baseline_diabetes 14635 non-null int64
baseline_digestive 14635 non-null int64
baseline_osteoart 14635 non-null int64
baseline_psych 14635 non-null int64
baseline_pulmonary 14635 non-null int64
ahrq_ccs 14635 non-null int64
ccsComplicationRate 14635 non-null float64
ccsMort30Rate 14635 non-null float64
complication_rsi 14635 non-null float64
dow 14635 non-null int64
gender 14635 non-null int64
hour 14635 non-null float64
month 14635 non-null int64
moonphase 14635 non-null int64
mort30 14635 non-null int64
mortality_rsi 14635 non-null float64
race 14635 non-null int64
complication 14635 non-null int64
dtypes: float64(7), int64(18)
memory usage: 2.8 MB
数据集中的属性都是数值型的,没有缺失值。因为我在这里的重点不是数据清理,所以我将继续对数据进行分区。
数据分割
为了试验自我训练,我需要将数据分成三部分:一个训练集,一个测试集,和一个未标记集。我将按照以下比例分割数据:
1%列车(贴有标签)
25%测试(贴有标签)
74%未标注
对于未标记的集合,我将简单地删除目标变量complexity,并假装它从未存在过。因此,在这种情况下,我们假设 74%的手术病例没有关于并发症的信息。我这样做是为了模拟这样一个事实,即在现实世界的分类问题中,许多可用的数据可能没有类标签。然而,如果我们确实有一小部分数据的类别标签(在这种情况下是 1%),那么半监督学习技术就可以用来从未标签数据中得出结论。
下面,我重组数据,生成索引来划分数据,然后创建测试、训练和未标记的分割。然后我检查裂缝的尺寸,以确保一切按计划进行。
X_train dimensions: (146, 24)
y_train dimensions: (146,)
X_test dimensions: (3659, 24)
y_test dimensions: (3659,)
X_unlabeled dimensions: (10830, 24)
班级分布
多数阶级(不复杂)的实例是少数阶级(复杂)的两倍多。在这种不平衡的分类情况下,我想对我选择的分类评估标准非常挑剔— 准确性可能不是最好的选择。
我选择 F1 得分作为分类度量来判断分类器的有效性。F1 分数对类别不平衡的鲁棒性大于准确性,这在类别大致平衡时更合适。F1 分数可以计算如下:
其中精度是被正确预测的预测阳性实例的比例,而召回是被正确预测的真阳性实例的比例。
初始分类器(监督)
为了实地验证半监督学习的结果,我首先只使用标记的训练数据训练一个简单的逻辑回归分类器,并在测试数据集上进行预测。
Train f1 Score: 0.5846153846153846
Test f1 Score: 0.5002908667830134
分类器的测试 F1 值为 0.5。混淆矩阵告诉我们,分类器可以非常准确地预测没有并发症的手术,准确率为 86%。然而,分类器更难正确识别有并发症的手术,准确率只有 47%。
预测概率
对于自训练算法,我们想知道逻辑回归分类器做出预测的概率。幸运的是, sklearn 提供了。predict_proba() 方法,它允许我们查看属于任一类的预测的概率。如下所示,在二元分类问题中,每个预测的总概率总和为 1.0。
array([[0.93931367, 0.06068633],
[0.2327203 , 0.7672797 ],
[0.93931367, 0.06068633],
...,
[0.61940353, 0.38059647],
[0.41240068, 0.58759932],
[0.24306008, 0.75693992]])
自训练分类器(半监督)
现在我们知道了如何使用 sklearn 获得预测概率,我们可以继续编码自我训练分类器。以下是一个简要的概述:
第一步:首先,在标注的训练数据上训练一个逻辑回归分类器。
步骤 2 :接下来,使用分类器预测所有未标记数据的标签,以及这些预测的概率。在这种情况下,我只会对概率大于 99%的预测采用‘伪标签’。
步骤 3 :将“伪标记”数据与标记训练数据连接,并在连接的数据上重新训练分类器。
第四步:使用训练好的分类器对标注的测试数据进行预测,并对分类器进行评估。
重复第 1 步到第 4 步,直到没有任何预测的概率大于 99%,或者没有未标记的数据。
参见下面的代码,我用 Python 实现了这些步骤,使用了一个 while 循环。
Iteration 0
Train f1: 0.5846153846153846
Test f1: 0.5002908667830134
Now predicting labels for unlabeled data...
42 high-probability predictions added to training data.
10788 unlabeled instances remaining.
Iteration 1
Train f1: 0.7627118644067796
Test f1: 0.5037463976945246
Now predicting labels for unlabeled data...
30 high-probability predictions added to training data.
10758 unlabeled instances remaining.
Iteration 2
Train f1: 0.8181818181818182
Test f1: 0.505431675242996
Now predicting labels for unlabeled data...
20 high-probability predictions added to training data.
10738 unlabeled instances remaining.
Iteration 3
Train f1: 0.847457627118644
Test f1: 0.5076835515082526
Now predicting labels for unlabeled data...
21 high-probability predictions added to training data.
10717 unlabeled instances remaining.
...Iteration 44
Train f1: 0.9481216457960644
Test f1: 0.5259179265658748
Now predicting labels for unlabeled data...
0 high-probability predictions added to training data.
10079 unlabeled instances remaining.
自我训练算法经历了 44 次迭代之后,才能够以> 99%的概率预测到更多的未标记实例。尽管最初有 10,830 个未标记的实例,但其中 10,079 个在自我训练后仍未标记(且未被分类器使用)。
经过 44 次迭代,F1 分数从 0.50 提高到 0.525!虽然这只是一个很小的增加,但看起来自我训练已经提高了分类器在测试数据集上的性能。上图的顶部显示,这种改进大部分发生在算法的早期迭代中。类似地,底部面板显示了添加到训练数据中的大多数“伪标签”出现在最初的 20-30 次迭代中。
最终混淆矩阵显示有并发症的手术的分类有所改善,但无并发症的手术的分类略有下降。在 F1 评分提高的支持下,我认为这是一个可接受的改进——识别将导致并发症的手术病例(真阳性)可能更重要,为了达到这一结果,可能值得增加假阳性率。
注意事项
所以你可能在想:用这么多未标记的数据进行自我训练有风险吗?答案当然是肯定的。请记住,尽管我们将“伪标签”数据与带标签的训练数据包含在一起,但某些“伪标签”数据肯定是不正确的。当足够多的“伪标签”是不正确的时,自训练算法可以加强差的分类决策,并且分类器性能实际上可以变得更差。
然而,这种风险可以通过遵循既定的实践来减轻,如使用分类器在训练期间未见过的测试数据集,或使用“伪标签”预测的概率阈值。
SQL 子查询简介
原文:https://towardsdatascience.com/a-gentle-introduction-to-sql-sub-queries-ee288174d285?source=collection_archive---------19-----------------------
SQL 变得简单
了解为什么以及何时应该使用它们!
有时候学习 SQL 感觉像是我们在矩阵里面,但是不需要那样!马库斯·斯皮斯克在 Unsplash 上的照片
SQL 是任何数据科学家为了探索数据库都应该掌握的基本工具之一。它有简单易用的美誉。但是并不是所有的事情都是轻而易举的,对于新手来说,最大的挑战之一就是理解子查询的使用。
在我们开始之前,有代码的笔记本一如既往地在这里等着你。
假设您熟悉 SQL,我们首先要学习的一件事是主语句的顺序必须如下:
**1- SELECT** column_name,
**2- FROM** table_name,
**3- WHERE** condition;
但是有一点不太明显,那就是这不是处理查询的方式!实际上,几乎是反过来的:
**1- FROM the** table_name
**2- WHERE this** condition **is true
3- SELECT the rows of the** column_name;
为什么知道这一点很重要?因为如果理解了这个逻辑,以后就更容易可视化子查询的需求了。对于 SQL,理解幕后的工作与知道如何编写查询一样重要。
假设您有下表 team_data :
| **team** | **country** | **season** | **total_goals** |
|-------------|---------|--------|-------------|
| Real Madrid | Spain | 2019 | 53 |
| Barcelona | Spain | 2019 | 47 |
| Arsenal | UK | 2019 | 52 |
| Real Madrid | Spain | 2018 | 49 |
| Barcelona | Spain | 2018 | 45 |
| Arsenal | UK | 2018 | 50 |
如果我们想按团队检索平均目标,查询将是:
**SELECT** team,
**AVG**(total_goals) AS avg_goals
**FROM** team_data
**GROUP BY** team;
这将给出以下结果:
按团队分组的平均目标
到目前为止,没有神秘,对不对?但是如果我们只想过滤平均得分高于 50 的团队呢?通常,我们的第一种方法是这样的:
**SELECT** team **AS** team_name,
**AVG**(total_goals) **AS** avg_goals
**FROM** team_data
**WHERE** avg_goals > 50
**GROUP** BY team;
第一次尝试会产生聚合错误。
这给了我们一个聚合错误,但是为什么呢?让我们根据查询的处理方式来执行这些步骤:
- 1: FROM team_data —好的,表格存在,我们继续;
- 2:WHERE avg _ goals>50—嗯,这里我们有一个错误,如果计算还没有完成,如何过滤这些值呢?
这是一个需要使用子查询的完美例子。我们需要做的是首先生成字段 avg_goals,,这样当 WHEN 语句开始过滤时,计算就已经完成了!根据查询逻辑,这个过程需要在来自语句的上完成,因为它在时出现在过滤器之前。让我们看看这个查询是怎样的:
**SELECT** team_name, avg_goals**FROM** (-- Here we make our sub-query:
**SELECT** team AS team_name,
**AVG**(total_goals) AS avg_goals
**FROM** team_data
**GROUP BY** team) tp
-- End of the sub-query**WHERE** avg_goals > 50;
成功!
你现在能看到发生了什么吗?
- 1:来自语句的生成了我们需要的分组值;
- 2: 当按照我们的规范过滤后;
- 3:最后,选择获取我们指定的列。
基本上,我们需要子查询大多数时候我们需要过滤聚集字段。写的时候给你一些帮助:
- 不要忘记在子查询之后创建一个别名。在这个例子中,在它的结尾有一个“tp ”,但是它可以是你想要的任何东西。
- 即使 SQL 不区分大小写,将语句大写也是一个好习惯。使用缩进也很好,因为它提高了查询的可读性。即使是很小的查询也很容易迷路。
今天就到这里。我希望现在子查询对你来说更加神秘了!请在评论中告诉我你的想法,并随时添加一些更实际的例子!
理解气流执行器的简单介绍
原文:https://towardsdatascience.com/a-gentle-introduction-to-understand-airflow-executor-b4f2fee211b1?source=collection_archive---------13-----------------------
柯蒂斯·麦克牛顿在 Unsplash 上的照片
Apache Airflow 是一个用于调度任务的著名开源 python 框架。气流生态系统中有很多新概念;其中一个你不能跳过的概念是 气流执行器 ,它是所有预定任务的“工作站”。气流对于最终用户来说通常是用户友好的,并且很好地理解气流执行器对于个人使用以及生产气流环境是至关重要的。在这篇文章中,我们将详细讨论什么是气流执行器,比较不同类型的执行器,以帮助您做出决定。
什么是气流执行器
气流执行器有很多种选择,我们先把那些选择放在一边,先把重点放在气流执行器在气流生态系统中做什么。恰当地说,规程“执行者”是一种执行任务的机制。worker 是运行实际任务的节点或处理器。Airflow 调度程序不会运行任何任务,而是将任务移交给执行器。执行者充当中间人,处理资源利用和如何最好地分配工作。
来自 giphy.com的奴才们的 GIF 图
虽然 Airflow 作业是在 DAG 级别上组织的,但是作业的执行阶段更加精细,执行器在任务级别上运行。如下图所示,如果 DAG 以六个任务结束,Airflow 调度程序会将每个任务分别分配给执行者。无论这些任务是并行完成还是顺序完成,都是由执行器类型决定的。
DAG 示例(按作者)
执行者参与气流生命周期的哪一部分?
就目前而言,Airflow(1 . 10 . 10 版)是一个单调度程序系统。在这种情况下,所有任务只由一个调度程序调度。调度器控制任务何时被发送到执行器,并监控来自执行器的任务状态。
任务从调度器到执行器的生命周期包括以下步骤:
- 在调度器发出命令让执行器运行哪个任务之前,根据执行器的类型,执行器本身的资源保持空闲或不可用。
- 一旦预定时间到了,气流调度器就把命令发送给执行器。
- 收到调度器的信号后,执行器开始分配资源,并将任务放入队列。当工作可用时,它将从队列中选取任务来执行它。同时,调度程序每隔一段时间(称为心跳)探测一次任务,以获取任务的当前状态,然后在后端数据库中更新其状态。
- 一旦任务完成,并且调度器从执行器接收到完成状态,为运行任务分配的资源就被清理掉了。
图片来自气流生命周期
为什么气流有不同类型的执行器?
大多数类型的 Airflow executor 工具任务以分布式方式运行,这些任务运行在多处理或多个工作节点上。气流生产环境通常有数百个 Dag,其中包括数千个要运行的任务。凭借在如此大的规模上并行运行各种任务的能力,Airflow executor 在密集型工作负载上大放异彩。
您拥有各种类型的执行器的原因之一是,您可以根据自己的需求和基础设施进行选择。气流提供了执行者的“工具包”,不同种类的执行者提供了灵活性,让气流与您的环境顺利集成。
由拍摄的谷仓图片上的 Unsplash
气流是可扩展的,支持各种执行器。最初,Airflow 只有 SequentialExecutor、LocalExecutor、CeleryExecutor 和 MesosExecutor 可用。最近两年,自从气流 1.9.0 以来,气流得到了更多的关注,更多的执行者被贡献给了社区,这些执行者包括 DaskExecutor,KubernetesExecutor,DebugExecutor。
执行器之间的区别在于上的机制,执行器在上运行任务。在我看来,并不是所有的遗嘱执行人都被同等对待,有些人你甚至想跳过,除非你有特定的理由必须使用他们。下面是对每个遗嘱执行人的描述,以及当你倾向于选择其中一个时应该考虑的因素。
气流执行器(作者)
- SequentialExecutor 是现成的默认执行器。顾名思义,任务将按顺序执行。即使你有一个分支操作符,任务仍然会按照
’branch_a’, ‘branch_b’, ‘branch_c’, ‘branch_d’
的顺序一个接一个的执行 - LocalExecutor 非常适合并行测试多个气流作业,为小规模生产环境执行任务。LocalExecutor 在与气流调度程序相同的节点上运行任务,但在不同的处理器上运行。有其他执行者在分配实际工作时使用这种类型;例如,KubernetesExecutor 将在每个 pod 中使用 LocalExecutor 来运行任务。
- CeleryExecutor 是最成熟的气流选项,因为大多数早期气流采用的是 CeleryExecutor。它还需要基础设施支持——芹菜和芹菜的后端(Redis 或 RabbitMQ)。然而,你可以从 Airflow 社区获得更好的帮助,因为很多公司都在使用这个选项。
- MesosExecutor 是早期的社区贡献之一。然而,由于 Kubernetes 比 Mesos 被广泛采用,气流社区也在讨论退役 MesosExecutor。除非您的公司正在运行 Mesos,并且您在未来几年内不会迁移到 Kubernetes,并且您希望使用 Mesos 来管理您的 Airflow executor 资源,否则您可能希望选择此选项。否则,您可能希望避免选择 MesosExecutor。
- Dask.org 激发了 DaskExecutor。有一些关于移除 DaskExecutor 的讨论,也是由于缺乏使用,DaskExecutor 在 Airflow master 上失败了几个月,但没有人注意到。我个人喜欢达斯克;不幸的是,气流和 Dask 的使用较少。不幸的是,由于使用和支持较少,您可能希望避免选择 DaskExecutor。
- KubernetesExecutor 是在 1.10.0 版本中引入的,由彭博贡献。这一贡献为 Airflow 与 Kubernetes 生态系统的集成树立了一个里程碑。虽然最初的几个次要版本有问题,但最近的版本更稳定了。如果贵公司广泛采用 Kubernetes,KubernetesExecutor 可能是气流执行器的最佳选择。KubernetesExecutor 的另一个优点是你可以为你的任务准备不同的 docker 图像,这给了你更多的灵活性。
- DebugExecutor 是在 1.10.8 中引入的。它可能不会被归类为遗嘱执行人;这个 DebugExecutor 的目的是与 IDE 一起运行。它类似于 SequentialExecutor,一次运行一个任务,并且支持使用传感器。
总之,CeleryExecutor 和 KubernetesExecutor 将是您的生产环境的绝佳选择。LocalExecutor 也是生产环境中需要考虑的首选项。如果您的工作负载较轻,或者大部分任务都在 AWS 或 Azure service 等云服务中运行,Airflow Executor 充当中间人,在不实际运行不同服务的情况下与它们对话,LocalExecutor 也是可行的选择。SequentialExecutor 和 DebugExecutor 用于本地测试。你可能会在生产中跳过它们。MesosExecutor 和 DaskExecutor 你可能想避开他们,因为对他们在气流生态系统中的未来路线图有矛盾心理。
气流执行器怎么设置?
气流执行器上的大部分配置都是由air flow . CFG文件控制的。不同的功能部分在括号中组织文件。对于执行程序的选择,您会在 core 部分看到,SequentialExecutor 被选为缺省值。它允许你在不设置太多依赖的情况下运行 Airflow。SequentialExecutor 可以直接使用 SQLite,SQLite 应该与 Python 一起安装。正如我们上面所讨论的,您可以选择不同类型的执行器,但是每一种都需要在 AirflowAirflow 中进行额外的设置。cfg 文件。
[core]executor = SequentialExecutor
LocalExecutor 也很容易设置,它要求元数据数据库是 MySQL 或 PostgreSQL,而不是 SQLite。一旦 LocalExecutor 设置好了,气流执行器 90%的功能就展现出来了。执行器的另外 10%功能是以分布式方式运行气流。
CeleryExecutor 有其配置部分— [celery]
。有两个主要组成部分:芹菜和芹菜后端。芹菜是异步任务队列。有了芹菜,气流可以将其任务扩展到多个工人,以更快地完成工作。更多设置可在气流芹菜页面找到
由于 Kubernetes 的流行,KubernetesExecutor 是气流中的宠儿。如果您的环境中有 Kubernetes,在 Airflow 中设置 kubernetexecutor 不会太麻烦,我在以前的文章中已经介绍了基本的设置:探索 AWS 和 kops 上的 Airflow kubernetexecutor
最后的想法
为气流基础设施设置合适的执行器是关键的一步。如果您希望 Airflow 不仅处理调度部分,还在您的 worker 节点上运行任务,Airflow executor 通过其分布式功能提供了更多额外的潜力。希望这篇文章能给你一些关于气流执行器的基本思路。干杯!
希望这个故事对你有帮助。本文是我的工程&数据科学系列的部分,目前包括以下内容:****
**
赵承志**
数据工程和数据科学故事
View list47 stories
你也可以 订阅我的新文章 或者成为 推荐媒介会员 可以无限制访问媒介上的所有故事。
如果有问题/评论,请不要犹豫,写下这个故事的评论或者通过 Linkedin 或 Twitter 直接联系我。****
用 Python 温和地介绍 Web 抓取
原文:https://towardsdatascience.com/a-gentle-introduction-to-web-scraping-with-python-b914a64b2fb8?source=collection_archive---------20-----------------------
如何用几行代码编写你的第一个 scraper
照片由潘卡杰·帕特尔在 Unsplash 拍摄
数据科学只有在有数据的情况下才有可能,而在现实世界中,数据通常不会在一个里等着你。csv 文件。你必须去追求它。这就是为什么网络抓取对你的数据科学工具箱非常重要。
但是如果你是一个完全的初学者,刮擦看起来有点复杂。如果你正在寻找开始抓取,并想知道如何写你的第一个网页抓取工具在一个简单,快速的方式,这篇文章是给你的。
理解这篇文章不需要以前的刮痧知识。我只是假设你知道什么是网络抓取,并且你也知道一些 Python 的基础知识。
在本文中,我们将以 quotes.toscrape.com 网站为例。这个网站包含数百个著名的报价,他们的作者,也有一些标签来描述每一个报价。这是我们要收集的信息。还有,从网站名称可以推断出是为刮痧而做的。但并不是互联网上的每个页面都是如此,所以在你开始抓取之前,确保你抓取的网站允许你这样做。
代码
对于我们将在本文中编写的 scraper,我们需要三个库:
- 熊猫,用于数据操作。如果你知道一些用于数据分析的 Python,你可能已经熟悉它了;
- Urllib ,打开并阅读页面;
- BeautifulSoup ,解析 HTML,使得提取数据更加容易。
如果你还没有安装,BeautifulSoup 是你唯一需要手动安装的。如果您使用 pip ,只需运行以下命令:
pip install beautifulsoup4
安装好所有东西后,我们可以导入,用 urllib 获取 URL,用 BeautifulSoup 解析源代码。
import pandas as pd
from urllib.request import urlopen
from bs4 import BeautifulSoupurl = 'https://quotes.toscrape.com'
page = urlopen(url)
soup = BeautifulSoup(page, 'html.parser')
追寻数据
因此,如果你在网站上按下键盘上的 F12 键,你会看到它的源代码。我鼓励你花些时间去理解它。您可以在 Windows 上按下 Ctrl + shift + C 来检查页面上的每个元素。
在这样做的时候,注意引号存储在带有名为“quote”的类的div
标签中,就像下面的代码一样。我们需要做的就是抓住这些元素。
选择元素一点也不难。一切都在soup
里面。例如,如果这里的目标是抓取页面的标题,正如您可能已经看到的那样,它存储在title
标签中,我们所要做的就是:
print(soup.title)
输出将是:
<title>Quotes to Scrape</title>
为了只检索文本,我们只需要指定这就是我们想要的:
print(soup.title.text)
然而,由于源代码中有许多div
标签,我们不能使用这种方法。相反,我们将使用find_all
方法。这个方法检索页面上所有符合我们规范的元素。这里我们使用标记名和类来检索所有的引号:
quotes = soup.find_all('div', class_='quote')
这一行的另一种写法是:
quotes = soup.find_all('div', {'class': 'quote'})
使用这种语法,我们甚至可以指定更多要过滤的类:
quotes = soup.find_all('div', {'class': {'quote', 'tags'}})
我们还可以使用limit
参数来限制要检索的元素数量。有很多不同的可能性。确保检查文档。
好了,我们现在有了所有的报价。如果您在页面源代码中打开这些元素之一,您将看到以下内容:
这里存储了我们需要的所有信息。我们只要抓住它。我们将抓取引用本身,即在带有类“text”的span
标签中;作者,那是在一个small
标签中加上“作者”一类的;以及在具有类“tag”的一个div
标签内的几个具有类“tag”的a
标签中的标签。
然后,我们遍历quotes
并获取它们中每一个的信息。首先是文本和作者:
for quote in quotes:
text = quote.find('span', class_='text').text
author = quote.find('small', class_='author').text
现在,仍然在循环内部,我们将使用find
方法获取类“标签”,然后使用find_all
获取内部的a
标签。这些方法基本上做同样的工作,除了find
只返回下一个符合你的规范的元素。
然后,我们将把每个标签中的文本追加到一个列表中:
tags = quote.find('div', class_='tags').find_all('a')
tags_list = []
for tag in tags:
tags_list.append(tag.text)
存储数据
抓取工作已经完成,但是我想你并不是只对用print
在控制台中显示数据感兴趣,而是希望数据存储在一个文件中,以便以后使用。
有几种方法可以做到这一点。最简单的方法是将每个报价的数据放在一个列表中,并将所有这些列表附加到另一个列表中。然后我们可以很容易地将列表转换成数据帧,并导出为。csv 文件。
single_quote = [text, author, tags_list]
all_quotes.append(single_quote)# Outside the loop
df = pd.DataFrame(all_quotes, columns=['quote', 'author', 'tags'])
df.to_csv('quotes.csv', index=False)
获取更多数据
虽然每一页只包含十个报价,我想你会想刮更多。要获得更多报价,我们需要进入下一页。同样,根据你抓取的网站,有很多方法可以做到这一点。
对于这种情况,我们可以将 URL 改为“https://quotes.toscrape.com/page/1/”,而不是“https://quotes . toscrape . com ”,并在另一个for
中更改页面的编号。
在这个例子中,我们抓取了前十页。这是该任务的完整代码:
25 行代码!这再简单不过了。易于理解、易于编写、实用且有效。
为了向你证明这是可行的,这里是前一百个引用的数据:
作者图片
更多挑战和更多工具
不幸的是,不全是阳光和彩虹。回想一下quotes.toscrape.com是一个网站被刮。所以从定义上来说刮擦它是容易的。
当你开始抓取真实的、更复杂的网站时,你会遇到新的挑战。你必须让你的代码防错,这样它才不会在抓取的成千上万的页面中崩溃。您必须处理 BeautifulSoup 无法解析的 JavaScript 渲染页面,甚至还要处理根据用户动作改变页面的交互式内容。
幸运的是,您还会遇到处理这些挑战的新工具。熟悉请求库很重要,这是一个比 urllib 更强大的工具; Selenium 是 JavaScript 渲染页面的一个很好的选择,因为它实际上打开了自动浏览器,可以抓取所有内容并与页面进行交互;你也可以使用代理提供商,比如 Infatica ,来保护你和你的连接,避免你的 IP 被屏蔽。
随着你目标的发展,确保你的工具也在发展!
我希望你喜欢这本书,它可能会有用。如果你有问题,有建议,或者只是想保持联系,请随时通过 Twitter 、 GitHub ,或者 Linkedin 联系我。
海湾地区数据科学面试幸存女孩指南
原文:https://towardsdatascience.com/a-girls-guide-to-surviving-bay-area-data-science-interviews-40b66ba4d7e8?source=collection_archive---------6-----------------------
旧金山湾区中级数据科学职位面试六个月后的关键收获。
在我的第一个数据科学职位工作了大约 1.5 年后,我决定开始申请新的职位,因为我目前的职位缺乏职业发展,缺乏引人入胜的项目,并且数据科学的应用不是这家小型创业公司的优先事项。因此,我踏上了穿越湾区技术面试文化的旅程,以找出我的数据科学职业生涯的下一步应该是什么。
在转到数据科学之前,我是建筑行业的一名土木工程师(点击了解我向数据科学的转变)。我很幸运,通过我的网络获得了我的第一份数据科学工作,没有花太多时间面试。这意味着我之前的大部分面试经历都是在建筑行业。不用说,在找出一个可行的流程之前,导航技术面试需要一些反复试验。
以下是我学到的六条重要经验,我将在下面详细解释:
- 旧金山湾区有一种科技面试文化,围绕这种文化建立了一个完整的行业。学习如何玩这个游戏。
- 数据科学是一个广阔的领域。找到你的定位,花时间专注于这些职位。
- 每天编码。
- 每天练习一道面试题。
- 熟记这本百页机器学习书中所有的粗体术语。
- 大型科技公司的招聘人员可能会有所帮助。第三方招聘人员可能是浪费时间。
1.旧金山湾区有一种科技面试文化,围绕这种文化建立了一个完整的行业。学习如何玩这个游戏。
因为数据科学职位竞争如此激烈,所以通过面试过程几乎有一个秘密的“代码”。我花了一些时间来真正理解这个概念,尽管我参加了一些旨在让女性受雇于科技行业的会议,试图解释这一点。
典型的面试过程是这样的:
- 提交你的简历和求职信。
- 找公司的人给你推荐。
- 招聘人员会主动打电话给你。
- 打电话给招聘人员,讨论你过去的经历,并回答几个一般性的技术问题。
- 进行第一轮技术面试,通常涉及以下一项或多项内容:(I)在共享您屏幕的平台上进行现场编码。(ii)讨论您之前完成的课后考试。㈢浏览案例研究。㈣统计和建模问题。
- 进行面对面的最后一轮技术面试,同时评估与团队的文化契合度。
以下是我发现的一些优化这一过程的秘密:
确保你的简历看起来“现代”
简历格式会让建筑行业的招聘人员畏缩不前,但在科技领域却是公平竞争的对象。加点颜色。添加一些符号。让它脱颖而出!在我的简历上添加小星星来传达我在某些技能上的经验水平,似乎对招聘经理很有吸引力。然而,一位朋友指出,与男性对自己的评价相比,我对自己的评价可能过于苛刻了。
我简历中的一个例子,展示了我对某些技术技能的熟练程度。
顺便说一句,我对批判性地评估或评价自己(甚至是谈判薪水)的建议是,想想你生活中的一个人,他/她总是问你想要什么。可能是同事、朋友或导师。对我来说,我会想起我是如何看着我的前任年复一年地争取大幅加薪,直到他的薪水明显高于我,尽管我们在同一个行业。我试着思考他会如何评价自己,或者在我的情况下他会提出什么要求。我敢肯定,在你人生的某个时刻,你见过有人自信而无情地谈判。试着去模仿,即使你没有感觉到。如果所有这些都失败了,我会想到,如果我不谈判,我会对世界各地的女性造成伤害,并陷入性别成见。是的,我需要那种紧迫感来推动自己去谈判。已经有很多关于谈判薪水的文章了,所以我不会在这里深究。我建议从阅读科技行业女性谈判薪资的(初级)指南开始。
如有疑问,提交求职信
我听到了赞成和反对提交求职信的观点。如果有提交的选项,那就提交吧。花点时间写一封好的求职信,具体说明你为什么想在那家公司工作。如果求职信在科技行业有作用的话,那就是解释你为什么对这家公司的这个职位感兴趣。它只需要是几个段落。不要提交一份冗长的、泛泛而谈的求职信,重复你简历上所列的内容。
推荐是金奖券
如果你想确保招聘人员或招聘经理看到你的简历,你需要公司里有人推荐你。或者你最好在简历搜索引擎优化方面非常出色。
你以前的经验和投资组合是必要的,但不相关
你应该能够讨论你之前的数据科学经验和你投资组合中的项目,但最终它们是不相关的。虽然他们会帮你打开大门,但你必须能够通过技术面试,以表明你有资格获得这个职位。
在面试中问一些澄清性的问题
很多次,我被招聘人员纠正,因为我做了一个假设,而我本应该澄清这个问题。这也适用于带回家的作业。要求澄清也无妨,即使是多次。我肯定有一次课后考试不及格,因为在我要求澄清一次后,我不好意思要求第二次澄清。
明智地选择你的时间和金钱的去处
技术面试已经成为一个行业;不要被骗花钱去面试。人们会主动联系你,将你的个人资料添加到他们的招聘网站上,为技术面试帮助付费,为简历写作付费,为练习面试问题付费,等等。在我看来,这是关于纪律和试错,你不需要支付这些服务的大部分。
谈判从第一次通话开始
招聘人员第一次打电话时会问薪资期望值的问题,对此我有些纠结。我通常会给出一个范围或中值,这个数字会吓跑一些招聘人员,而其他招聘人员会暗示这个数字太低。一个职位的工资范围在不同的公司之间差别很大。记住你期望的工资范围的下限是有帮助的,而且,如果你认为你对这个职位来说可能是大材小用,试着在第一次打电话时问招聘人员这个职位的工资范围。大多数资源都说要完全避免回答薪水期望值的问题,但是招聘人员非常坚持要知道他们是否在你期望的范围内。
不要把拒绝放在心上
意识到在湾区获得一份工作机会是靠运气和获得面试经验。如果你没有得到一份工作,并不是因为你对那家公司不够熟练或者不够聪明。试着保持乐观,记下你可以如何改进,并将注意力转移到下一份申请上。如果你很难保持积极的态度,或者感觉技术面试让你精疲力尽,也许是时候休息几周了。
来源:https://media.giphy.com/media/3oz8xHL8780wscO8hi/giphy.gif
2.数据科学是一个广阔的领域。找到你的定位,花时间专注于这些职位。
在我面试的时候,我去了旧金山的一个聚会,问了一些人他们如何决定申请哪些工作,因为有太多的工作机会。他们都说‘适用于一切’。我认为这种逻辑是有缺陷的,因为为一个职位定制一份简历和求职信,并找到一个关系给你引荐是非常耗时的。更不用说可能需要 2-4 周的技术面试过程,还可能包括带回家的作业。我想把大部分时间花在学习技术面试上,只有有限的时间用来申请职位。
我认为有必要缩小你感兴趣的数据科学工作的具体类型(研究与应用、建模与统计、通才与专家)以及你想加入的公司类型(私营与上市、初创与老牌、B2C 与 B2B)。为了优化我的时间,我制定了以下流程来决定申请哪些工作。
- 第一步是确保我符合这个职位的最低要求。有些人认为,即使你还没有足够的经验,也应该申请,但我认为最低资格通常是公司的绊脚石。“最好拥有”是有回旋余地的地方。公司正在寻找方法来缩小大量候选人的范围,而最低资格是一个简单的方法。
- 因为我已经有了几年的经验,所以我也需要确保自己不会大材小用。我经历了几次面试过程,在意识到公司无法击败我目前的工资,并在寻找更入门级的人之前,我已经完成了技术面试。
- 第三步是评估我的技能是否符合工作描述。我可以修改我的简历,让招聘人员想和我谈谈吗?为了确保我的技能符合我感兴趣的职位,我花了一些时间学习新技能或 Python 库,以填补我经验中的任何空白。例如,我对统计决策感兴趣,所以我参加了在线 Coursera 推理统计学课程,并使用 Kaggle 产品分析数据集为我的投资组合构建了一个项目。最终,我在风险分析和产品分析领域找到了一个合适的位置,至少能让我和招聘人员通一次电话。
- 下一步是确保我对这个职位感到兴奋(很明显)。一般来说,在写求职信的时候,我就能判断出自己对这个职位的兴奋程度。如果我很难在求职信中解释我对这个职位的热情,那么我会停止申请。
- 最后一步是检查我的关系网中是否有人可以推荐我,尤其是当我申请一家大公司的时候。这不一定是一个交易破坏者,但它确保了我的应用程序被移动到堆的顶部。
使用这个过程,我会接到招聘人员的电话,至少有大约 2/3 的时间可以参加第一轮技术面试。我喜欢这种可能性。
3.每天编码。
现场编码采访绝对是我的克星。不是因为我不知道如何编码,而是因为我对自己的编码能力缺乏信心。如果知道有人在看我打字并判断我的思维过程,我会感到恐慌。我会催促自己,因为我担心自己走得太慢。恐慌和匆忙的结合导致我将简单的问题复杂化,并阻止我有效地调试我的代码。我有一个理论,这可能比男人更经常地影响女人。
为了获得自信,我确保自己每天都在编码,并在 Kaggle 上把自己的代码和别人的代码进行比较。我本应该尝试下面的一些资源来更好地进行现场编码面试,但我最终在探索这些选项之前得到了一个提议:
- 参加一个全女性的编码研讨会(像女孩开发它)。
- 试试 Pramp ,一个练习与同行进行现场编码面试的软件平台。
- 参加黑客马拉松,尝试与软件开发人员配对。
- 试试 HackerRank ,一个有练习代码面试题的软件平台。
4.每天练习一道面试题。
一旦你解决了足够多的实践技术面试问题,你开始看到一个模式,并对自己的能力有了信心。我发现有几个服务可以一周几次给你发邮件询问一个问题,然后单独发一封邮件告诉你解决方案(收取订阅费)。
- 面试查询
- 面试提问
然而,对练习题的在线解答要持怀疑态度。我在技术面试时收到的脸书阅读材料包括以下警告:“虽然我们承认候选人可能会利用外部网站/资源发布面试问题和答案,但我们鼓励谨慎,因为我们发现许多建议的解决方案是不正确的。”
5.背下百页机器学习书里所有的粗体术语。
我买了这本一百页的机器学习书,打算把它作为我工作的资源。这本书实际上对通过技术面试问题非常有帮助。我建议记住书中的关键术语,并确保你理解并能解释关键概念。
更具体地说,有人反复问我以下问题:
- 计算精度的公式是什么?精度?回忆?
- 解释偏倚和方差权衡。
- 解释逻辑回归。
- 什么是正规化?
- 分类和回归有什么区别?
轻松地说,我也被问及这些问题:
- 你的精神动物是什么?
- 别人问过你的最好的面试问题是什么?
- 你能接受的最低工资是多少?
来源:https://makeameme.org/meme/My-face-when-p0u24n
6.大型科技公司的招聘人员可能会有所帮助。第三方招聘人员可能是浪费时间。
一旦你有了大约一年的数据科学经验,你将经历与第三方招聘人员打交道的四个阶段。起初(第一阶段),关注是奉承。你会想“我成功了!公司正在联系我面试。”然后(第二阶段),它变得令人沮丧。你会想“这个招聘人员看过我的 LinkedIn 个人资料吗?我显然不适合这个职位。”第三阶段是不知所措。你要回复招聘人员才能让你的 LinkedIn 求职状态保持在“积极应聘”,但是不相关的就那么多。第四阶段是冷漠。你主动忽略所有第三方招聘人员。
下面的堆积条形图显示了我申请的 20 个职位的进展情况。我自己申请或通过公司招聘人员申请的职位导致了六个面试过程,其中我进入了第一轮面试,一个面试过程中我进入了最后一轮面试,三个面试过程中我收到了录用通知。我通过与第三方招聘人员通电话申请了六个职位,第三方招聘人员在将简历交给招聘经理之前会对候选人进行筛选,最终导致实际公司的面试为零。即使它们通常只持续 15 分钟,我也不得不围绕这些电话来计划我的一天。它们占用了我本可以用来做更有影响力的事情的时间。有时,我觉得招聘人员被要求寻找一定数量的“多样化”候选人,我被加入进来以满足这一要求,即使我的技能不一定与职位描述相符。但那可能只是我的幻觉。不管怎样,如果你想和第三方招聘人员合作,先询问职位描述,在安排电话之前评估你是否适合这个职位。
一个堆积柱形图显示了我申请的 20 个职位的面试进展情况。左栏显示我自己或通过公司招聘人员找到的工作,右栏显示我通过第三方招聘人员找到的工作。
另一方面,我认为脸书面试的招聘人员对我的面试过程帮助很大。脸书似乎为我提供了公平的竞争环境,他给我时间在把简历发给招聘经理之前更新我的简历,详细解释技术面试将如何进行,并在技术面试之前给我提供阅读材料和练习题的链接。在其他公司,我只是在瞎猜应该在简历中突出哪些技能,以及我将面临的问题类型。
摘要
总而言之,面试过程紧张、耗时,有时还有点丢脸。充分利用你的时间,找到那些通常能让你进入第一轮技术面试的职位类型。征服技术面试,熟能生巧。技术面试失败只是练习技术面试的一部分,不要对自己太苛刻。只要有一点点运气和严格的纪律,你就会得到那份工作。
来源:https://media.giphy.com/media/kLLDVeWnNwRXO/giphy.gif
一个好的机器学习分类器对扑克牌数据集的精度度量
原文:https://towardsdatascience.com/a-good-machine-learning-classifiers-accuracy-metric-for-the-poker-hand-dataset-44cc3456b66d?source=collection_archive---------30-----------------------
马库斯·温克勒在 Unsplash 上的照片
一个非常适合高度不平衡数据集的指标
什么是数据集?
扑克手数据集【Cattral 等人,2007 年】是公开可用的,并且在 UCI 机器学习知识库【Dua 等人,2019 年】中有非常好的记录。[Cattral 等人,2007 年]将其描述为:
对于分类算法来说,这是一个具有挑战性的数据集
这是一个 11 维的数据集,有 25K 个样本用于训练,超过 100 万个样本用于测试。每个数据集实例都是一手 5 张牌的扑克,每张牌使用两个特征(花色和级别)和一手扑克标签。
为什么很难?
它有两个特性使得分类算法特别具有挑战性:它全是分类特征和它极度不平衡。分类特征很难,因为典型的距离(又称相似性)度量不能自然地应用于此类特征。例如,该数据集有两个特征:等级和套件,计算“黑桃”和“红桃”之间的欧几里德距离根本没有意义。不平衡的数据集很难,因为机器学习算法假设了良好的平衡,机器学习大师的Jason Brownlee将这个问题描述为:
不平衡的分类对预测建模提出了挑战,因为用于分类的大多数机器学习算法是围绕每个类别的相等数量的样本的假设而设计的
那么,为什么我会得到好的结果呢?
那么,如果这个数据集被认为是困难的,为什么一个简单的神经网络可以在没有任何特殊调整或数据预处理的情况下达到 90%以上的准确性?
在这篇文章 , Aditya Bhardwaj 显示他的神经网络达到了 90.04 的准确率。下面,我展示了一个简单的多层感知器神经网络 k 实现了超过 99%的准确率。发生这种情况的一个原因是由于职业不平衡问题。[Ling 等人,2011 年]解释说:
当类别分布高度不平衡时,数据被认为遭受了类别不平衡问题。在这种情况下,许多分类学习算法对非频繁类的预测精度较低。
扑克手数据集碰巧非常不平衡,在训练集和测试集中,前两个类代表了 90%的样本。一个学习如何正确分类这两个类别,但完全错误分类其余类别的分类器,仍将达到 90%的预测准确率。这不是一个好的分类器!。分类器仍然获得高分的原因很简单,因为类别不平衡考虑到了,即优势类别的正确预测被赋予了与样本数量成比例的权重。“非频繁类的低预测准确性”被来自那些有大量样本可供学习的类的较好预测所掩盖。
我们能做些什么呢?
一个不考虑阶级不平衡的度量标准,例如,对所有阶级给予同等的权重,而不考虑他们的主导地位,可以提供更“真实”或准确的结果。 Scikit-learn 的分类报告有一个这样的指标。 F1 得分结合了精确度和召回率两方面的结果,分类报告包括一个F1宏观平均度量,即未加权的每个标签的 F1 得分平均值!。正如 Scikit-learn 关于 F-metrics 的文档中提到的:
在非频繁类仍然重要的问题中,宏平均可能是突出其性能的一种方法
这是一个很好的度量示例,可用于衡量分类器在这种高度不平衡的数据集上的性能。
在机器学习文献中已经提出了许多其他方法和度量来处理这里提到的一些问题。例如,Boriah 等人在他们的论文“分类数据的相似性度量:比较评估”中讨论了用于处理分类特征的一些现有方法。讨论这个不是这篇文章的范围,因此我会简单地给你留下一个论文的链接这里。
请出一些结果?
我继续运行一个多层感知器神经网络,这是我得到的结果。这个网络使用 3 个隐层,每个隐层 100 个神经元,alpha=0.0001,学习率=0.01。下面是 混淆矩阵 。可以观察到,神经网络总体上做得很好,正确地分类了前 6 个类别中的大多数,对于类别 7 和 9(四个同花和同花)有一些特别差的结果。
混淆矩阵
该分类器报告的准确率为 99% 。尽管第 7 类和第 9 类的表现非常糟糕,但它们只贡献了 100 万个测试样本中的 233 个。几个非主导类的坏结果完全被其他类掩盖了。这显然给人一种成功的错觉!神经网络错误分类了 66%和 77%的皇家同花顺和四张一类的手牌,但它得到了正确但误导性的 99%的准确性结果。
下面显示的分类报告包括前面提到的所有类别的宏观平均 F1 分数。这种未加权的平均值更好地概括了分类器的表现。可以看出,大多数班级实际上做得很好,但也有几个班级做得特别差。但更重要的是,可以观察到报告的宏观平均值为 78%。对于观察到的结果,这是一个更合适的分数!2/10 的班级表现很差,而其他班级表现得更好,这反映在指标中,当指标被仔细选择时。
precision recall f1-score support 0 1.00 0.99 0.99 501209
1 0.99 0.99 0.99 422498
2 0.96 1.00 0.98 47622
3 0.99 0.99 0.99 21121
4 0.85 0.64 0.73 3885
5 0.97 0.99 0.98 1996
6 0.77 0.98 0.86 1424
7 0.70 0.23 0.35 230
8 1.00 0.83 0.91 12
9 0.04 0.33 0.07 3 accuracy 0.99 1000000
**macro avg 0.83 0.80 0.78 1000000**
weighted avg 0.99 0.99 0.99 1000000
参考
[1]卡特拉尔和奥帕彻(2007 年)。扑克手数据集[https://archive.ics.uci.edu/ml/datasets/Poker+Hand]
卡尔顿大学计算机科学系。
智能系统研究小组
[2]Dua d .和 Graff c .(2019 年)。http://archive.ics.uci.edu/ml 的 UCI 机器学习知识库。加州欧文:加州大学信息与计算机科学学院。
[3]凌春霞,盛诉生(2011)阶层失衡问题。在:萨姆特 c,韦伯 G.I .(编辑)机器学习百科全书。马萨诸塞州波士顿斯普林格。https://doi.org/10.1007/978-0-387-30164-8_110
初学者开始机器学习的好方法
原文:https://towardsdatascience.com/a-great-way-for-beginners-to-get-started-with-machine-learning-833cce028620?source=collection_archive---------38-----------------------
如何使用 Weka 实现您的第一个机器学习算法
资料来源:Weka GUI
介绍
无论你是机器学习的新手,还是尝试过用 Python 或其他语言建立模型但失败了,Weka 都可能是你的完美起点。
Weka 是建立在 Java 之上的数据可视化和算法工具的集合。不过不要担心!由于 Weka 的图形用户界面(GUI ),您不必了解任何 Java 就可以使用它。使用这个 GUI,您可以在数据上运行流行的机器学习模型,而无需编写任何代码!
然而,在使用 Weka 之前,您需要学习一些机器学习算法的基础知识。
基础知识
数据
在开始运行机器学习算法之前,您需要一个数据集。寻找数据集的好地方是 Kaggle ,这是一个为数据科学家提供挑战、数据集等内容的网站。只需在您感兴趣的领域搜索数据集并下载即可!在本指南中,我将使用鸢尾花数据集,如果你愿意跟随,可以在这里找到。我建议寻找 CSV 格式的数据集,以便最容易实现。CSV 代表逗号分隔值,是一个简单的文本文档,其中每行是一个表格的一行,各列之间用逗号分隔。下载 CSV 文件后,在文本编辑器中打开它,查看其格式。
回归
回归是您将在本指南中学习的一种方法。回归问题侧重于预测一个连续的数。例如,脸书喜欢一个帖子的数量,或者房子的销售价格。查看一下从 Kaggle 获得的数据集,通过寻找连续值来尝试识别任何回归问题,并确定它们是否有预测价值。
分类
分类是您将在本指南中学习的另一种方法。分类问题预测记录的类别。比如这花是玫瑰吗?或者说,这饮料是汽水吗?查看您的数据集,通过查找类别来尝试识别任何分类问题,并确定它们是否有预测价值。
数据类型
数据可以有多种类型。在本指南中,我将向您介绍对 Weka 有价值的数据类型。重要的数据类型有数字、字符串和类。数字数据类型由数字组成。例如,您为回归确定的任何连续值都是数字。字符串数据是文本数据。单词、句子和段落都是字符串数据类型。类别数据是具有预定义类别或列表的数据。例如,IMDB 星级或狗的种类。这三种数据类型将构成数据的主要部分。
履行
现在你对机器学习中使用的一些基本术语有了更好的了解,让我们开始构建你的第一个模型吧!
第一步是在这里下载 Weka GUI 。安装程序后,你应该会看到下面的窗口。
资料来源:Weka GUI
Weka GUI 有五个主要区域:资源管理器、实验者、知识流、工作台和简单的 CLI。开始时,你可以忽略除了浏览器标签以外的所有标签,直到你有了更多的 Weka 经验。点击浏览器按钮进入下面的屏幕。
资料来源:Weka GUI
资源管理器选项卡有 7 个选项卡:预处理、分类、聚类、关联、选择属性、可视化和预测。对于本指南,我们将坚持使用预处理和分类选项卡。预处理选项卡如上所示。这是您将加载数据的地方。但是,我们需要将 csv 数据集转换成 ARFF 文件。要做到这一点,你需要一个文本编辑器和崇高的文本。Sublime 是一个免费的代码编辑器,可以从这里下载。
下载 Sublime 后,在文本编辑器中打开您的 csv 文件并复制内容。然后,将它们粘贴到一个新的 Sublime 文件中。保存该文件,并用。arff 在最后。
ARFF 文件有三个部分:关系、属性和数据。我们需要将这些部分添加到文件中。在第一行添加关系组件并命名数据集。
@RELATION iris
跳过一行,然后添加属性组件。您的属性将是数据集的列。每个属性都需要一个名称和数据类型。当输入一个类数据类型时,列出每个类别,用逗号分隔在花括号内。
@ATTRIBUTE Id NUMERIC
@ATTRIBUTE SepalLengthCm NUMERIC
@ATTRIBUTE SepalWidthCm NUMERIC
@ATTRIBUTE PetalLengthCm NUMERIC
@ATTRIBUTE PetalWidthCm NUMERIC
@ATTRIBUTE Species {Iris-setosa, Iris-versicolor, Iris-virginica}
跳过另一行,然后在您复制的 CSV 数据上方添加数据组件。如果您的数据有标题行,请确保删除标题行。
@DATA
1,5.1,3.5,1.4,0.2,Iris-setosa
2,4.9,3.0,1.4,0.2,Iris-setosa
3,4.7,3.2,1.3,0.2,Iris-setosa
4,4.6,3.1,1.5,0.2,Iris-setosa
5,5.0,3.6,1.4,0.2,Iris-setosa
6,5.4,3.9,1.7,0.4,Iris-setosa
7,4.6,3.4,1.4,0.3,Iris-setosa
8,5.0,3.4,1.5,0.2,Iris-setosa
....
最后,再次保存这个文件,您就可以将它加载到 Weka 中了!
在 Weka 的预处理选项卡上,单击打开文件并导航到新的 ARFF 文件。
资料来源:Weka GUI
如果您在预处理选项卡的右下角看到一个分布图,您将知道数据已经正确导入。
资料来源:Weka GUI
加载数据后,单击分类选项卡。这是我们将运行回归和分类模型的地方(尽管名称为 classify,回归模型也在这里运行)。您应该会看到下面的屏幕。
资料来源:Weka GUI
在测试选项部分,我们有 4 个选项:使用训练集、提供的测试集、交叉验证和百分比分割。为了衡量预测所选列的模型的准确性,我们需要向它提供以前没有见过的新数据。一种方法是将数据集分成两部分,称为测试和训练。但是,我推荐使用 10 倍交叉验证。这将把数据集分成测试和训练(10%的数据用于测试)10 次。这通常是最佳实践。
资料来源:Weka GUI
我们还需要选择我们想要预测的列。对于 iris 数据集,我将使用花卉种类,但是,您应该使用您在浏览数据集时确定的列。
资料来源:Weka GUI
然后,我们需要选择我们将使用的机器学习算法。因为鸢尾物种是一个分类问题,所以我将使用分类算法。其中一种基本的分类算法是逻辑回归(不要被逻辑回归中的“回归”所迷惑——它是一种分类算法)。逻辑回归将输出一个介于 0 和 1 之间的数字来对记录进行分类。在本指南中,我将跳过数学,但是理解这些算法是如何工作的非常重要。你可以在这里了解更多关于逻辑回归的知识。要选择逻辑回归算法,单击分类器下的选择,然后单击分类器>功能下的逻辑。
资料来源:Weka GUI
现在,我们要做的就是点击开始!模型运行后,您应该会得到类似如下所示的输出。
资料来源:Weka GUI
如果你在做回归问题,过程是一样的。但是,不要在分类器>函数下选择逻辑,而要选择线性回归。像逻辑回归一样,我将跳过线性回归的数学,但是,你可以在这里找到更多信息。
现在你可能会说,“太好了!我让模型运行了…但现在怎么办?”运行您的模型后,您需要学习如何读取输出并评估模型的成功。
模型评估
对于分类和回归问题,Weka 的输出会有所不同。然而,理解如何阅读和解释 Weka 的输出对于理解您的模型预测得有多好很重要。我们将检查分类和回归问题的输出。
分类
在 Weka 的分类输出中有三个重要部分用于评估模型的成功。这些是摘要、分类准确度和混淆矩阵。
在摘要部分,注意正确分类的实例。这是模型正确分类的记录数量,可以用百分比表示。在 iris 数据集的情况下,我们对 100%的记录进行了正确分类。这在真实世界的数据集里是极其罕见的,所以不要期望你的准确度会这么高。良好的准确性因数据集和应用领域而异,但是,如果您的准确性低于随机概率,则肯定需要进行一些改进。
资料来源:Weka GUI
在按类划分的精度部分,请注意 f-measure 和 ROC 面积。f-measure 是一个介于 0 和 1 之间的指标,它同时考虑了精确度和召回率。评估 f 度量值时,f 度量值越接近 1,模型表现越好。ROC 面积是受试者工作特征曲线下的面积。该输出将介于 0 和 1 之间,并且将表示模型能够区分类别的程度。评估 ROC 面积时,数字越接近 1 越好。您还可以看到,Weka 为每个类别提供了 f-measure 和 ROC 面积以及加权平均值。我建议关注加权平均值来评估整个模型,但是,如果您有多个类,这可以帮助识别模型在分类时遇到特定问题的类。
资料来源:Weka GUI
混淆矩阵也是一个重要的评估特征。它是一个矩阵,显示了 a 类记录是什么以及模型将其分类为什么类。顶行表示它被分类为什么,侧栏表示记录实际上是什么类别。对角线显示正确分类的记录。混淆矩阵可以帮助您识别模型难以分类的记录。
资料来源:Weka GUI
回归
Weka 的回归模型有一个评估部分——总结。但是,如果您运行线性回归,您还会有一个称为线性回归模型的部分。现在我说我会跳过线性回归的数学,但是先等等。线性回归将创建最能代表数据的线性函数(考虑最佳拟合线)。线性回归模型部分显示了模型得出的函数。例如,对于虹膜数据集,预测花瓣宽度的线性回归函数为:
PetalWidthCm = 0.0035 * Id-0.1591 * sepallenghtcm+0.2095 * SepalWidthCm+0.4272 * petallenghtcm-0.3811
资料来源:Weka GUI
总结部分将提供评估模型成功与否的指标。相关系数会告诉你变量之间有多少线性关联。相关系数越接近 1 越好。此外,平均绝对误差将告诉您平均误差的绝对值(预测过高或过低)。绝对值用于捕捉负误差。平均绝对误差越低越好,但是,什么是“低”将取决于数据,需要一些直觉。
讨论
虽然本指南绝不是关于机器学习、Weka 或所用方法的包罗万象的指南,但它应该让你开始使用实际数据进行实际预测。Weka 是一个开始探索机器学习的好地方,因为你不用写任何代码就可以实现通用算法。
你也可以用 Weka 来增长你的技能,以使用不同的和更先进的方法。可以用于分类的其他算法有 C4.5 决策树(在 Weka 中称为 J48)、随机森林和朴素贝叶斯。如果您有信心,Weka 还有一个名为 SMOreg 的支持向量机(SVM)实现——仔细选择您的内核!
使用 python 设计 A/B 测试的成长型营销人员指南
原文:https://towardsdatascience.com/a-growth-marketer-guide-to-designing-a-b-tests-using-python-5c0729d8eacc?source=collection_archive---------32-----------------------
提高实验效果的 3 个基本步骤
图片来自 Unsplash
在我在 Waze 工作的 7 年里,我开发了各种各样的产品和功能,从 Waze 应用程序(在全球拥有超过 1.3 亿用户)到 Waze 首次推出时的拼车。
我在营销的多个领域工作,亲眼目睹了它对用户参与度的影响。它激励我更深入地挖掘业绩和增长的世界。在这个过程中,我学会了如何挖掘数据以发现有意义的见解,相应地设计实验,以及分析和解释实验结果。
我现在是绩效营销团队的一员,我们的任务是通过利用 Waze 拥有和运营的渠道和工具,提高整个产品漏斗中的用户参与度。我们直接与用户沟通,最终促使他们采取最有效的行动来完成他们的用户之旅。
为了了解我们活动的效果,我们进行了实验,主要以“假设检验”的形式,即 A/B 检验。在进行了数百次实验后,我确定了一系列最佳实践,以及将它们付诸实践的具体步骤,以便进行有效的 A/B 测试,你可以在下面的帖子中找到。
注意:这篇文章中分享的观点是我自己的,并不反映 Waze 或 Google 的任何标准或具体协议。
第一步:探索现有的关系,定义你的关键绩效指标(KPI)
首先,您进行的任何 A/B 测试都应该与公司的 KPI 保持一致,以确保您的工作集中在最重要的业务优先级上。开始吧-
进行探索性数据分析,以发现数据中的现有关系
识别 KPI 需要结合领域知识和 EDA,即探索性数据分析。您需要深入了解业务领域,以便评估什么是最重要的驱动因素。然后,您可以使用 EDA 来发现影响他们的关系,因为 EDA 还允许您确定产品漏斗中具有最大增长机会的相关领域。
如果您是第一次浏览数据,您会希望遵循以下基本步骤:
- 检查您的数据:对于每个数据集,您首先要了解数据的组织方式及其包含的内容。
- 清理&组织您的数据:删除不需要的列、地址空值,并根据需要添加额外的列。
- 使用 Group by &聚合函数 运行汇总统计数据以探索组之间任何有趣的差异。
- 进行可视化数据探索(VDE) 以发现各组之间可能的关系。
用于揭示数据不同部分之间潜在关系的 pairplot 示例(图片由作者提供)
我给做了一个笔记本,里面有一些基本功能可以帮助你入门。您需要根据数据集的性质更改/删除一些函数,但总的来说,我发现这种结构有助于保持一切有序和清晰。
确定与业务优先级/目标相关的可行指标
您选择的指标应该与产品粘性(参与度)相关联,并且是长期保留的有力指标。总的来说,KPI 应该是可衡量和可操作的。也就是说,您应该能够采取某些措施来提高数字以支持业务目标。此外,您需要关于这个指标的足够的现有数据,或者能够容易地收集关于它的数据。最终,您会希望避免长时间的迭代。例如:关注每日或每周活跃用户,而不是每月活跃用户,因为 MAU 会要求你等待一整个月才能分析数据并采取行动。
关注更少的指标以产生更大的影响。
当涉及到 KPI 时,您通常希望遵循“少即是多”的方法,这样公司就可以专注于更少的指标,以产生更大的全面影响。
在设计 A/B 测试时,你也应该遵循这种方法。您尝试优化的指标越多,您的实验就会越复杂,这可能需要运行更长时间,需要更多的设计&开发资源&最终需要更多的资金。
一旦您发现了数据中的关系,您就需要更深入地进行分析,以准确构建您的 KPI,然后在设计您的实验和定义您的成功指标时使用这些 KPI。
第二步:定义你实验的范围和目标
一旦您对数据中的关系有了更好的理解,并确定了相关的 KPI,您就可以开始定义您的实验范围了。任何实验设计(坦率地说,任何项目)都应该从回答这 4 个问题开始:
1.这个实验重要吗?
从很多方面来说,这是最重要的问题,因为你不想在一个结果不会影响业务、产品或营销决策的实验上浪费时间、金钱和资源。在开始实验工作之前,确保与组织中的相关利益相关者保持一致。
2.你能在这个实验中测量相关的 KPI 吗?如果可以,如何测量?
永远不要说“让我们启动这个实验,看看会发生什么”(你会惊讶我以前听到过多少次)。你最不希望的事情就是意识到你实际上不能测量你想要影响的指标。确定您想要影响的指标(或 KPI ),然后确保它们是可测量的,并且实际上可以应用到实验中。
3.如果这种影响存在,你能检测到吗?
为了评估你试图衡量的变化是否有意义,你需要有足够大的样本量。多大?这将取决于多种因素,包括置信度、功效和效果大小。我们将在设计实验的第三步更详细地探讨这些问题,但总的来说,重要的是要记住,要检测产品漏斗深处的影响,需要更大的样本量。如果一个变化在漏斗顶部,如点击,打开一条消息等,你可能不需要那么大的样本量。类似地,你需要更大的样本量来检测小的效应大小。
在可能的情况下,从为您的产品所做的类似工作中确定转换基准,以粗略估计进行实验所需的用户数量。
4.如果成功,这个实验会‘动针’吗?
从商业的角度来看,你也应该考虑实验的影响,如果成功的话,是否有意义。换句话说,即使你的实验导致了统计上的显著提升,如果它只影响了一小部分用户,它也不值得运行。
如果你对以上任何一个问题的回答是“否”,那就不要浪费你的时间来设计这个实验了。否则,请继续阅读——是时候开始你的实验设计了!
步骤 3:定义、设计和启动你的实验
在确认了实验的需求并确定了你的成功标准之后,你就可以继续设计实验了。我建议使用一个包括实验所有部分的笔记本:定义、计划和报告。任何阅读你的笔记本的人都应该很容易理解实验的基本原理、目标和范围,以及实验是如何进行的,以及你从实验中学到了什么。笔记本包括 3 个部分:定义,设计和启动。
定义
提供了实验的背景。它概述了需求、如何做出决策以及使用的术语。这里,您将使用步骤 1 中进行的分析,以及步骤 2 中定义的基本原理,为实验提供背景和框架。
具体来说,在这一部分,您需要回答以下问题:
- 这个实验是关于什么的?
- 这个实验的商业理由是什么?
- 这个实验的结果将如何影响商业决策?特别是在与本实验相关的部门——营销、产品等
- 如何定义本实验中使用的指标和术语?
确保实验报告的所有利益相关者和读者引用实验中使用的所有术语的相同定义是很重要的。这将影响实验的每个部分,如果你没有定义实验的关键部分,可能会导致完全不同的结论。例如,如果你正在进行一个旨在复活休眠用户的实验,你对休眠用户的定义或者什么构成了复活必须在实验计划中完全定义。其他人可能对你的目标受众以及整个实验的结果和成功有不同的看法。
设计
这是实验计划的核心。它包括感兴趣人群的定义、机会大小、抽样方案、假设定义和所需的最小样本量。确保包括以下内容:
兴趣人群
详细定义你的目标人群定义。
机会大小
应根据您感兴趣的人群和为实验定义的 KPI 来定义。正如第一步中提到的,你需要集中精力测试那些有可能“移动指针”的东西。
抽样方案 你计划对你感兴趣的人群进行抽样的方式。我还建议包括任何潜在的采样偏差,以确保你的利益相关者意识到它们以及它们对实验结果的潜在影响。
无效&替代假设 这是实验定义的核心。简明扼要地描述你的零选择假设是什么。你的零假设应该是你的默认行为或现有状态。你的替代假设是你正在测试的新理论或变化。你在实验中的目标是看看是否有足够的证据拒绝无效并接受改变(替代假设)。
统计误差是假设检验的关键部分。具体来说,我们看两种类型的错误:假阳性(第一类错误)和假阴性(第二类错误)。说明这两种错误之间差异的一个常见例子是,将第一类错误视为判一个无辜者有罪的概率,而第二类错误是指判一个有罪者无罪的概率。
就你的实验而言,你会想要减少错误地拒绝零假设的机会,从而增加找到一个效果的概率(如果存在的话)。以上面的例子为例,你可以认为零假设是无辜的,而另一个假设是有罪的。如果一个无辜的人确实是无辜的(Null 为真),你会希望减少这个人被定罪的机会(拒绝 Null)。
显著性水平&功效统计 通过显著性水平(a)定义你对犯 I 类错误的适应程度,通常设置为 0.05 或 5% (95%置信水平)。通过使用功率统计来克服类型 II 误差。实验的功效统计是实验检测实验组之间差异的能力,如果这种差异存在的话。使用 80%的功率是很常见的。
效果大小
作者图片
重要的是要了解影响的大小,或者在给定的人群中会有什么样的结果。因此你需要一个有效尺寸。你希望在测试中看到的变化越大,效果越大,最小样本量就越小。我们希望看到的变化越小,影响大小就越小,我们需要的最小样本量就越大。换句话说,如果你想检测大的差异,你可以在测试中用较少的用户来做,但是如果你想找到更精细的小差异,你需要在测试中包含更多的用户。
最小样本量 一旦定义了显著性水平、功效和效果量,您就可以运行功效分析来确定您需要的最小用户数,以便检测您正在测试的变化是否有意义。
通常使用 p 值来解释检验,p 值是假设零假设为真时观察到结果的概率。在解释显著性检验的 p 值时,必须指定显著性水平。如果 p 值小于显著性水平,则显著性检验的结果被认为是“统计显著的”。这意味着零假设(即没有差异)被拒绝。
- p<= alpha:拒绝 H0,不同分配
- p>alpha:未能拒绝 H0,同分配
使用 Python 的 statsmodels 库你可以很容易地计算 min。需要的样本大小,知道期望的显著性水平、效应大小和功效(笔记本可用此处):
# Import library #from statsmodels.stats.power import TTestIndPower# parameters for power analysis (change as needed)effect = 0.05
alpha = 0.05
power = 0.8# perform power analysis ## change to TTestPower() in case of a paired sample t-testanalysis = TTestIndPower()
result = analysis.solve_power(effect, power=power, nobs1=None, ratio=1.0, alpha=alpha)print('Sample Size: %.2f' % result)
启动&监视器
你现在已经准备好启动你的实验了!不要忘记对实验的每一部分进行质量保证,以确保它如你所期望的那样运行,并且数据正常流动。此外,确保继续全程监控实验。最重要的是,在发布后的最初几个小时内密切监控它,以尽快发现任何潜在的问题。
步骤 3:分析和报告结果
运行 A/B 测试后,您需要分析并清楚地报告实验结果。不要羞于报告负面影响或没有影响。通常,在找到最有影响力的假设之前,你需要测试多个假设。但是,以可操作的方式清楚地传达结果可以帮助您和所有相关利益相关者协调一致,并继续推动您的 KPI 的影响。
分析实验结果的第一步是从验证开始,以确保测试正确运行。具体来说,您需要确认:
- 实验组的大小是相同的,即如果测试被分配给每组 50%-50%。如果您决定以不同的方式划分实验组,您需要确保每个组的大小与分配给它的百分比相对应。
- 实验组是随机分配的:一定要检查你的实验组中的亚群,以确保没有潜在的偏见影响你的实验结果。例如,您可以按性别或国家对您的实验组进行分组,以确保两组具有相对相似的规模。
一旦您确认了您的实验的有效性,您需要基于为测试定义的度量和 KPI 来分析每个组的表现。虽然一组可能看起来比另一组表现更好,但您必须观察结果是否具有统计显著性,以便能够确定结果是随机的还是可重复的结果(实际影响)。
如何知道结果是否具有统计学意义?如果你的变量之间的关系不仅仅是偶然的可能性!显著性以 P 值衡量,即概率值,它将反映您的结果是否像您在统计假设检验中观察到的结果一样极端的概率。P 值假设您的零假设一开始就是正确的。
请记住,P 值取决于测试组的样本大小。P 值表示为 0%到 100%,但通常表示为小数。例如,5%的 P 值是 0.05。低 P 值是好的;他们表明这个结果不是偶然发生的。您可以将高 P 值视为反对空值的弱证据,而将低 P 值视为反对空值的强证据:
- 高 P 值: 您的数据很可能为真 null(保留 Null)
- 低 P 值: 您的数据不太可能为真 null(拒绝 Null)
我听过很多次人们试图通过说“结果几乎具有统计学意义”来软化他们的报告。让我们明确一点:
没有“几乎显著”这种说法。您的测试结果可能有统计学意义,也可能没有。
除了确定您的测试结果是否具有统计显著性,您还需要定义效果的大小,或者您的无效假设和替代假设之间的差异大小。为了确定这一点,您需要进行一个测试统计。不同的假设检验根据零假设中假设的概率模型使用不同的检验统计量。一些常用的测试包括:
- Z 检验(Z 统计):测量原始分数低于或高于总体平均值的标准偏差。z 分数也称为标准分数。
- T 检验(T 统计):T 检验告诉你两组之间的差异有多显著;换句话说,它让你知道这些差异(以平均值/平均值衡量)是否可能是偶然发生的。
- ANOVA (F 统计):与 T 检验类似,ANOVA 可以告诉你组间的差异有多显著。t 检验比较两组,而方差分析检验可以比较两组以上。
- 卡方检验(卡方统计):帮助您找到包含零假设和替代假设的变量之间的关系类型。
进行分析时,您需要选择最适合您的实验的 T 统计量,并计算两个 T & P 值来评估您的实验性能。Statsmodels 库包括一些很棒的函数,可以帮助您进行上面提到的一些 t 测试。
来自 statsmodel 网站的截图
使用本笔记本中的代码计算基本 A/B 测试的 T-测试,该测试由两个互斥组组成,将为您提供 P & T 值。
总而言之..
虽然“A/B 测试”经常被用作增长努力的时髦词,但花时间适当地计划它们以最大化它们的影响是非常重要的。最终,如果您投入时间来正确设计、启动和衡量您的实验,您将为您的组织带来巨大的影响。更重要的是,你将在自己的职业生涯中推动真正的范式转变。
关于如何使用 SQLAlchemy 和 PostgreSQL 在 Python 和数据库之间进行交互的指南
原文:https://towardsdatascience.com/a-guide-on-how-to-interact-between-python-and-databases-using-sqlalchemy-and-postgresql-a6d770723474?source=collection_archive---------12-----------------------
来源: Toa Heftiba , unsplash
使用 SQLAlchemy Python 库解释 Python 和 PostgreSQL 之间的联系,以及如何使用它的一些提示。
在进行数据科学项目时,您可能希望将 Python 脚本与数据库连接起来。一个名为 SQLAlchemy 的库在 SQL 和 Python 之间架起了一座桥梁。
存储数据库的一种方法是使用关系数据库管理系统,这是一种常见的数据库类型,数据存储在表中。但是,托管这些数据库需要软件。PostgreSQL 是允许这样做的开源软件。虽然不是必须的,但是在处理大量不同的复杂数据库时,可视化工具非常有用。可视化工具可以让您清楚地了解正在使用的数据库。在这些工具中,我选择了 TablePlus(Mac 版)和 phpMyAdmin(Windows 版)。
在本文中,我将向您展示配置您的系统需要遵循的不同步骤,以及在使用 Postgres 和 SQLAlchemy 时您需要知道的一些命令。
1.下载 SQLAlchemy 和 PostgreSQL
要安装 SQLAlchemy,您需要在计算机的终端中输入以下命令:
pip install SQLAlchemy
要安装 PostgreSQL,你需要进入那个网站。我也给你一个 mac 和 windows 的教程。在配置 PostgreSQL 时记下您使用的登录名和密码是非常重要的,因为您将在与 TablePlus 和 Python 的连接中需要它。
2.下载可视化工具
它们是许多不同的可视化工具,但并不是所有的都有免费版本。此外,无论你用的是 mac 还是 window,用来可视化数据库的软件都会有所不同。我选择了 TablePlus,因为它非常容易使用,免费版本也非常好。这里是下载 TablePlus 的链接。
现在软件已经下载完毕,需要在 tablePlus 和 PostgreSQL 之间创建一个连接。这里是关于如何在 TablePlus 上做到的教程。
3.在 PostgresSQL 中创建数据库
在通过 SQLAlchemy 使用 Python 与数据库交互之前,我们需要在 PostgreSQL 中创建数据库。在这一节中,我还将向您展示一些与 PostgreSQL 交互的命令。
首先,您需要通过在终端中键入以下命令来连接到 PostgreSQL 服务器:
psql -U postgres
然后,你可以创建你的数据库,我们称之为“飞行”(避免使用大写字母)。
CREATE DATABASE flight*;*
既然已经创建了数据库,那么就可以创建表,使用 PostgresSQL 或 SQLAlchemy 插入值。我将向你展示这两种方法。
4.使用 PostgresSQL 创建表和插入值
您必须首先连接到要使用的数据库。以下命令必须在最后一节中的命令之后在同一终端中执行。所以这里我们要连接到数据库“航班”:
\connect flight;
现在我们想创建一个带有一些属性的表。我将把这个表称为“flights ”,其属性是航班的 id 、出发地、目的地和持续时间。
CREATE TABLE flights (
id SERIAL PRIMARY KEY,
origin VARCHAR NOT NULL,
destination VARCHAR NOT NULL,
duration INTEGER NOT NULL
);
如果要创建没有任何属性的表,需要输入以下命令:
CREATE TABLE flights();
现在我们已经创建了属性,我们需要插入一些值。但是,要插入值,您需要先创建属性。
INSERT INTO flights (origin, destination, duration) VALUES ('New York', 'London', 415);
INSERT INTO flights (origin, destination, duration) VALUES ('Shanghai', 'Paris', 760);
INSERT INTO flights (origin, destination, duration) VALUES ('Istanbul', 'Tokyo', 700);
INSERT INTO flights (origin, destination, duration) VALUES ('New York', 'Paris', 435);
然后,您可以在 TablePlus 中可视化您的表,您应该看到:
现在我将向您展示 Python 中的命令以及如何使用 SQLAlchemy 库。
5.使用 SQLAlchemy 创建表并插入值
如前所述,在与 Python 建立连接之前,您需要在 PostgreSQL 中创建一个数据库。因此,在本节中,所有代码都必须在 Python 脚本中实现。
首先要做的是创建一个引擎,它是一个用于管理数据库连接的对象。
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmakerengine = create_engine("postgresql://login:password@localhost:5432/flight")
创建引擎的一般格式是:
create _ engine(" PostgreSQL://log in:passeword @ localhost:5432/name _ database ")
在这里,由于我们想要在数据库 flight 上工作,我们将 flight 替换为 name_database 。登录和密码对应的是你设置 PostgreSQL 时的那个。并且 5432 是端口,但是因为它是本地服务器,所以它是 5432。
然后,我们需要创建一个表和属性,还要向该表中插入值。首先,我们需要通过点击下面一行来创建一个作用域会话:
db = scoped_session(sessionmaker(bind=engine))
它与我们的应用程序并不十分相关,但在很多例子中却非常重要。想象一下这样一种情况,当我们将 web 应用程序放到互联网上,有多人同时尝试使用我们的网站时,我们希望确保 A 对数据库的操作与 B 对数据库的操作是分开的。
接下来,我们需要运行下面一行来创建一个表 flights ,其属性为 id、 出发地、目的地和持续时间。小心,语法与 PostgreSQL 中的有点不同:我们需要在末尾声明密钥。
# to create the table flights with all the attributes
db.execute("CREATE TABLE test (id INTEGER NOT NULL, origin VARCHAR NOT NULL, destination VARCHAR NOT NULL, duration INTEGER NOT NULL, PRIMARY KEY (id));")# to insert values into the table flights
db.execute("INSERT INTO flights (origin, destination, duration) VALUES ('New York', 'London', 415);")db.execute("INSERT INTO flights (origin, destination, duration) VALUES ('Shanghai', 'Paris', 760);")db.execute("INSERT INTO flights (origin, destination, duration) VALUES ('Istanbul', 'Tokyo', 700);")db.execute("INSERT INTO flights (origin, destination, duration) VALUES ('New York', 'Paris', 435);")
然后,为了在 PostgreSQL 服务器上执行,我们需要提交更改:
db.commit()
在最后一步中,我们结束了会话:
db.close()
因此,整个代码总结如下:
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker# creation of an engine
engine = create_engine("postgresql://login:password@localhost:5432/flight")# creation of a session
db = scoped_session(sessionmaker(bind=engine))# creation of the table flights with all the attributes
db.execute("CREATE TABLE test (id INTEGER NOT NULL, origin VARCHAR NOT NULL, destination VARCHAR NOT NULL, duration INTEGER NOT NULL, PRIMARY KEY (id));")# insertion of values into the table flights
db.execute("INSERT INTO flights (origin, destination, duration) VALUES ('New York', 'London', 415);")db.execute("INSERT INTO flights (origin, destination, duration) VALUES ('Shanghai', 'Paris', 760);")db.execute("INSERT INTO flights (origin, destination, duration) VALUES ('Istanbul', 'Tokyo', 700);")db.execute("INSERT INTO flights (origin, destination, duration) VALUES ('New York', 'Paris', 435);")# commit the changes
db.commit()# close the session
db.close()
6.SQLAlchemy 中的一些实用方法
可以想象,如果您有一个 10000 行的 csv 文件,逐行插入值会非常漫长和痛苦。幸运的是,pandas 库能够将 pandas 数据帧转换成 SQL 表。此外,pandas 理解元素的类型,因此在创建表时不再需要指定类型,但是我建议仍然输入类型。了解你正在处理的元素的类型极其重要。
为了展示它是如何工作的,我使用了这个数据集。该数据集是关于 2015 年美国航班的。你可以在这里找到数据集。
我们将在相同的数据库上工作,而不是以前的飞行。我们将创建一个名为“airlines_2015”的表。
进口熊猫作为 pd
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmakerengine = create_engine("postgresql://login:password@localhost:5432/flight")db = scoped_session(sessionmaker(bind=engine))db.execute("CREATE TABLE airlines_2015();")dataframe.to_sql('airlines_2015', engine, if_exists='replace')db.commit()
db.close()
7.PostgreSQL 中的一些实用技巧
在这一节中,我将为您提供一些命令,您可以在终端中输入这些命令来与数据库进行交互。但首先,我将简要回顾一下我们到目前为止所看到的内容。
连接到 PostgreSQL 服务器:
psql -U postgres
创建数据库:
CREATE DATABASE *name_database ;*
连接到数据库:
\connect *name_database* ;
所有数据库的列表:
\l
创建表格:
CREATE TABLE name_table();
在下一个命令中,您需要连接到您想要查看的表的数据库:
\dt
如果您想要一个表格的描述:
\d table_name
最后,如果您想要关闭一些仍然打开的连接,您需要打开一个新的终端并运行以下命令(在每一行之后按 enter,因此您总共需要按 3 次 enter):
# first command
psql -U postgres# second command
\connect *nom_database*;# third command
select pg_terminate_backend (pg_stat_activity.pid) from pg_stat_activity where datname = current_database() and pid <> pg_backend_pid();
8.结论和提示
我希望你在这篇文章中找到了你想要的东西。在从事数据科学项目时,您可能希望处理大量数据,并且需要通过创建数据库来组织数据。创建清晰架构的一种方法是绘制 UML 图。
如果你喜欢阅读这样的故事,并想支持我成为一名作家,考虑注册成为一名灵媒成员。每月 5 美元,你可以无限制地阅读媒体上的故事。如果你使用我的链接注册,我将赚取一小笔佣金,你仍需支付 5 美元。谢谢大家!!
[## 通过我的推荐链接加入媒体-乔纳森·莱班
阅读乔纳森·莱班的每一个故事(以及媒体上成千上万的其他作家)。您的会员费直接支持…
medium.com](https://medium.com/@jonathan_leban/membership)
PS:我现在是柏克莱大学的工程硕士,如果你想讨论这个话题,请随时联系我。 这里的 是我的邮箱。
如何阅读统计表的指南
原文:https://towardsdatascience.com/a-guide-on-how-to-read-statistical-tables-8fcfdb9e1a56?source=collection_archive---------31-----------------------
一个计算主要概率分布概率的闪亮应用程序
闪亮的应用程序来计算主要概率分布的概率
作为我教学助理活动的一部分,我很快意识到学生们通常很难在统计表中找到概率。下面一个闪亮的应用程序帮助你阅读主要的统计表:
- 统计-101
这个闪亮的应用程序帮助你计算主要概率分布的概率。
以下是完整的代码,如果你想加强它(见一个例子,如何使用这个应用程序后,嵌入式代码):
请注意,如果应用程序已经达到每月使用限额,链接可能会失效。如果是这种情况,请稍后再试。
这个 app 怎么用?
- 通过此链接打开应用程序
- 选择发行版
- 设置分布的参数(参数当然取决于所选择的分布)
- 选择是要查找较低的尾部、较高的尾部还是一个区间
- 选择 x 的值
在右侧面板(或下方,取决于屏幕大小)上,您将看到:
- 你刚刚输入的数据的摘要
- 数值解(即概率)
- 解决方案的可视化
- 概率密度函数以及平均值、标准差和方差
例子
这里有一个最常见分布的例子:正态分布。
想象一下下面的问题:一家企业每周维护和修理的成本已经观察了很长一段时间,结果是按照一个平均为 402€、标准差为 22€的正态分布来分布的。已经为下周设定了 439€的预算,费用超出预算的可能性有多大?
要解决这个问题,请按照应用程序中的以下步骤操作:
- 选择正态分布,因为据说成本遵循正态分布
- 设均值μ等于 402,因为据说平均成本是 402€
- 在该语句中,给出了标准偏差(而不是方差),因此选择“标准偏差σ”并将其设置为 22
- 有人问我们成本超过预算的可能性有多大。因此,我们寻找概率高于某个 X,所以选择上尾 P(X > x)
- 我们现在被要求找出成本超过 439€的概率,所以设 x 等于 439
解决方案面板对数据进行了总结:
因此,下周成本超出 439€预算的概率为 0.0463,或 4.63%。
它还显示了正态分布(μ=402 和σ^2=484 ),阴影区域对应于我们正在寻找的概率。然后,它给出了关于密度函数,均值,标准差和方差的一些细节。
感谢阅读。我希望你会发现这个应用程序对计算主要分布的概率很有用。
和往常一样,如果您有与本文主题相关的问题或建议,请将其添加为评论,以便其他读者可以从讨论中受益。
相关文章:
- 一款闪亮的手工推断统计应用
- 一款闪亮的手工线性回归应用
- 最佳资产配置实用指南
- 用闪亮的 app 画字云
- 如何在 blogdown 中嵌入闪亮的 app
原载于 2020 年 1 月 6 日 https://statsandr.com。
营销分析指南
原文:https://towardsdatascience.com/a-guide-on-marketing-analytics-d3936f0373f2?source=collection_archive---------38-----------------------
艾萨克·史密斯在 Unsplash 上拍摄的照片
随着购买者的旅程变得更加复杂,营销被视为成本中心,营销团队必须依靠分析来衡量他们努力的影响。传统上,营销工作往往被视为难以量化对收入的影响,但借助更好的分析工具,可以更容易地将营销与收入联系起来。
虽然分析的好处显而易见,但营销团队仍然没有采用工具,只有 31%的团队在决策中真正使用了分析工具。考虑到营销自动化、网络分析、CRM 和社交媒体之间的大量数据,采用的问题可以归结为缺乏从多个来源收集数据、确定指标和收集见解的知识。为了提供帮助,本指南将提供一些关于数据源、指标和分析仪表板最佳实践的见解,这些对于成功的营销分析非常重要。
仓库存储孤立的数据
数据通常存放在不同的 SaaS 工具和业务应用程序中,不幸的是,这意味着您的营销团队不能直接访问他们自己的数据。使用 SaaS 工具中的仪表板,如营销自动化仪表板,通常意味着您无法组合多个相关的数据源,也无法获得对讲述潜在故事很重要的更深层次的见解。
像雪花这样的现代数据仓库工具允许营销团队将分散在不同数据源中的孤立数据连接起来,使其可视化,并做出更明智的决策。从您的营销自动化、web 分析、CRM、电子表格和电子邮件营销工具中提取数据,您可以创建更强大的仪表板来跟踪营销绩效,例如:
- 符合营销条件的销售线索数量
- 支出与客户购买成本、生命周期价值和回报时间
- 社交媒体覆盖面和参与度
虽然数据仓库将每一个营销数据源结合在一起,但明智地聚合数据而不是将所有数据放在一起使其工作是很重要的。由于每个业务应用程序和 SaaS 工具的工作方式不同,它们的数据定义可能会有所不同,因此我们应该批判性地考虑什么应该组合,什么不应该组合。
营销仪表板最佳实践
随着仪表板成为商业标准,仪表板的组织和设计变得至关重要。营销仪表板应该分开,以便每个仪表板都与一个营销目标相关联。仪表板上的每个图表都应该建立在一个线性故事的基础上,解释营销目标的结果。通过使用这种方法,您将构建更有针对性的仪表板,因为每个图表都建立在前一个图表的基础上,所以可以很容易地找到信息。
在设计仪表板时,考虑每个仪表板的受众非常重要。要了解您的受众以及他们期望从仪表板中获得什么价值,请考虑提出以下问题:
- 我的听众的信息需求是什么?
- 我的听众需要做出什么具体决定?
- 他们已经知道了什么?
- 此外,这个仪表板将如何增加价值?
此外,当决定每个图表显示什么时,了解您的受众是否理解图表的上下文是很重要的。例如,他们熟悉每个图表的指标/KPI 吗?他们了解数据的来源吗?他们了解跟踪这些指标的含义吗?
您选择的指标和 KPI 将为您的仪表板提供最佳布局。这里有一个你可以遵循的框架:
Chartio
营销仪表板的类型
将每个仪表板集中到一个特定的区域,可以更容易地获取信息,并提供营销绩效的精细和高级视图。以下是你如何划分你的营销仪表板。
营销归因仪表板
归因仪表板非常适合量化整个客户旅程中许多接触点的 ROI。从 CRM 和预算/支出数据中,可以在媒体、渠道和活动级别跟踪以下指标:
- 领导
- 营销合格的销售线索
- 合格销售线索
- 客户赢了
- 每个销售线索的成本
- 每次采购成本
- 年度合同价值和终身价值
- 偿还期
营销漏斗仪表板
营销漏斗仪表板显示了从漏斗顶部到转化目标的整个过程。对于这个仪表板,您可以结合 CRM、营销自动化、网络分析和数字营销数据。
由于营销包含一系列学科,几乎每个营销计划都有自己的漏斗:
- 转化漏斗:跟踪客户通过漏斗向转化结果(如销售)的进展。
- 客户获取漏斗:跟踪数字营销活动的成果。
- 内容营销漏斗:监控购买者的旅程,其中首次接触是一部分内容。
管道仪表板
管道仪表板侧重于连接来自营销和销售的数据,以显示营销如何推动公司收入。管道仪表板跟踪潜在客户在管道漏斗中的进展:
- 合格销售线索
- 销售机会
- 成交的交易
- 年度合同价值
内容营销仪表板
内容营销包括博客、门控内容、视频、信息图表等等。内容营销仪表板提供了关于内容如何推动转化的见解。这些指标可以来自内容管理系统、社交渠道和网络分析的综合数据。
可以为非门控内容显示以下指标:
- 页面视图
- 页面上的平均时间
- 新访客
- 跳出率
- 社会共享
此外,以下指标可能与门控内容相关:
- 登录页面视图
- 内容第一接触归因
- 营销合格的销售线索
- 销售机会受到影响
- 赢得的销售机会
社交媒体仪表板
随着社交媒体的持续重要性,衡量社交媒体活动的投资回报率变得越来越重要。社交媒体仪表板包含来自社交媒体渠道的聚合指标,如:
- 页面赞数和浏览量
- 社交渠道上的分享
- 点击率
- 跳出率
- 赞助帖子和广告
Web 分析仪表板
网络分析仪表板收集网站流量数据、移动分析数据、营销自动化和网站优化数据,以跟踪以下指标:
- 独特的网站访问者
- 回访者
- 跳出率
- 流量来源(直接、有机、付费、推荐)
- 按流量来源的转换
搜索引擎营销和优化仪表板
搜索引擎营销仪表板让您可以看到搜索引擎上的付费广告,以及如何优化您的广告。这些数据来自网络分析和在线广告工具等来源,可用于跟踪以下指标:
- 客户获取成本
- 点击率
- 每次转换的成本
- 每次点击成本
- 活动总成本
- 排名活动绩效
- 归因于付费搜索的线索
- 付费搜索的成功案例
- 来自搜索的流量
- 你转换目标的转换率
- 高转化率关键词
就这样
使用仪表板执行营销分析对于跟踪指标非常重要,这种方式可以让您更好地了解您的营销费用,并更深入地了解什么在起作用,以便您可以改进您的营销活动和内容。
为你的团队构建营销仪表板并不一定很难,也不一定要花很多钱。您只需了解市场上有哪些专业工具,并且这些工具将满足您收集、准备和分析数据的业务需求。
请通过 Waterfront Analytics 联系我们,我们可以帮助您选择和设置一些关键工具,开始分析您的数据并推动您的营销工作。
指南:文本分析、文本分析和文本挖掘
原文:https://towardsdatascience.com/a-guide-text-analysis-text-analytics-text-mining-f62df7b78747?source=collection_archive---------12-----------------------
它是什么、应用和用例、工具以及它如何改进业务决策的指南
传统上,企业利用他们在实体店的存在来了解他们的客户——如何吸引、吸引和取悦他们。
然而,随着我们将我们的关系转移到网上,以数字渠道作为主要的互动点(特别是通过 COVID19 带来的全球 WFH 和社交距离措施),这种理解客户的能力在这种距离状态下受到了损害。
也不是说我们和他们的互动减少了。其实恰恰相反。
企业与客户的互动比以往任何时候都多。大多数企业都感受到了全渠道和无处不在的压力。这种关系的数字化本质也意味着每一次点击、每一笔付款、每一条信息都可以被追踪和衡量。
那么,有什么问题呢?
正是因为信息太多,我们很难真正了解我们的客户。信息过载。分析麻痹。我们错过了关键的洞察力,因为实在是太多了。
这就是文本分析的用武之地。
文本分析帮助企业以可扩展、一致和公正的方式分析大量基于文本的数据。在不需要过多资源的情况下,它分析数据并提取有价值的信息,让公司自由地根据这些见解采取行动。
鉴于 80%的业务信息大多是非结构化文本数据,这种形式的智能自动化对于现代企业在竞争中保持领先地位的同时继续吸引、吸引和满足客户变得至关重要。
在本指南中,您将看到文本分析的概述,它在商业中的应用,以及一些帮助您入门的工具。请随意进入您感兴趣的部分:
1。 定义:什么是文本分析?
- 文本分析、文本挖掘、文本分析有什么区别?
- [文本分析和自然语言处理有什么区别?](http://What is the difference between text analysis and natural language processing?)
2。 文本分析有哪些应用和用例?
- 客服团队文本分析
- 营销团队的文本分析
- 聊天机器人团队的文本挖掘
3。 有哪些文字分析的软件或工具?
- 面向初学者的文本分析
- “最佳实践”文本分析工具
- 深度文本分析工具
定义:什么是文本分析?
文本分析是分析非结构化和半结构化文本数据以获得有价值的见解、趋势和模式的过程。
它通常用于需要处理大量基于文本的数据以获得洞察力的情况,但如果不这样做,人工分析将会耗费大量资源和时间。
- 使用文本分析的一些情况包括:
- 查看过去 3 年的支持票证,了解一段时间内客户关注的趋势
- 分析 1,000 份关于新产品发布反馈的客户调查
- 寻找最有影响力的话题来构建您的聊天机器人或知识库
在所有这些情况下,文本分析方法将胜过人类。不仅仅是更少的时间和资源,最终的见解也更符合更少的人为错误或偏见干扰的过程。
因此,所有行业的许多组织都在使用文本分析方法来获得对其文本数据集的定量和定性理解。然后将这些信息与数据可视化工具结合使用,以更好地将信息转化为可操作的见解,从而做出明智的决策。
维恩图显示了文本分析(或文本挖掘)与六个相关领域的交集:统计学、人工智能和机器学习、计算语言学、图书馆和信息服务、数据库和数据挖掘。来源:G.Miner 等人的 非结构化文本数据应用的实用文本挖掘和统计分析 图片由作者提供。
文本分析、文本挖掘和文本分析有什么区别?
文本分析、文本挖掘和文本分析是同一个概念,通常可以互换使用。
文本分析和自然语言处理(NLP)有什么区别?
自然语言处理实际上是更广泛的文本分析领域的一个子集,这就是为什么这两者之间的差异往往难以理解。
先说文本分析和自然语言处理的定义。
文本分析是关于检查大量的文本,以产生新的和相关的见解。
自然语言处理(NLP),或者更具体地说,自然语言理解(NLU),帮助机器“阅读”、“理解”和复制人类语音。
在文本分析的过程中,使用各种分析方法来获取洞察,自然语言处理就是其中之一。NLP 实际上是文本分析、计算语言学、AI 和机器学习之间的交叉领域。
文本分析和 NLP 的关键区别在于每个领域的目标。
图片作者为纯语音技术
文本分析旨在仅从文本或单词本身获得质量洞察。不考虑文本中的语义。它回答的问题包括单词的频率、句子的长度以及单词的存在与否。
另一方面,自然语言处理旨在理解文本背后的语言使用和语境。这里分析语法结构和语义。它可以回答诸如句子背后的意图、人们的语言习惯等问题,甚至可以将你的电子邮件分类到主要、社交、推广或更新标签中。
这两者经常一起使用,以提供对人类交流的数字和上下文的理解。
那么,这些在商业中是如何使用的呢?下一节将涵盖文本分析的用例及应用。
文本分析有哪些应用和用例?
文本分析的应用非常广泛,可以应用于任何基于文本的数据存在的地方。
无论是客户反馈、电话记录还是冗长的反馈调查,文本分析都能帮助团队相对轻松地从文本数据中获得定量和定性的意义。
由于 80%的业务信息是非结构化的,主要是文本格式的,文本分析在业务的所有功能中都很有用。
让我们来看看其中的一些应用:
- 客服团队文本分析
- 营销团队的文本分析
- 聊天机器人团队的文本挖掘
客户服务团队的文本分析
对于大量的客户通信,文本分析方法对于客户支持团队来说是非常有用的,这是显而易见的。
客户服务团队通常是最紧张的,在任何公司中都有一些最高的离职率,并且在任何给定的一天里都面临着处理大量客户互动的大量压力。
通过采用文本分析,服务团队可以自动化他们的许多日常任务,如研究、更新、路由,并减少在重复问题上花费的时间。相反,他们将在 NLP、机器学习和人工智能的支持下,增强自己超越 NPS、满意度和 CSAT KPI 的能力。
那么,文本分析在客户服务中到底是如何工作的呢?
使用下面的目录跳到您感兴趣的用例,请继续阅读🙂
用例目录:客户服务团队的文本分析
- 客户对话分析
- 早期问题检测
- 自动发送票据
- 自动确定票据优先级
- 自动检票
- 客户报告之声
- 简化知识库创建&报告
客户对话分析和洞察
图片作者为纯语音技术
作为企业和客户之间沟通的主要媒介,客户对话,无论是来自电子邮件、支持票、社交媒体还是聊天,都为了解客户需求和促进业务增长提供了丰富的信息。
- 在这些对话中,蕴含着对以下问题的宝贵见解:
- 与他人相比,表现出色的客户服务代表使用了哪些技巧和短语来超越他们的 KPI?
- 过去 5 年中,每月最大的客户趋势是什么?
- 客户互动中最大限度留住客户的关键时刻在哪里?
所有与客户沟通的企业都可以获得这些知识。然而,没有多少人使用它,更不用说能够提取它。
这就是文本分析的魔力所在。
借助文本分析工具和技术,可以大规模消化和分析客户通信数据,从而为客户服务团队找到数据驱动的洞察力,以超越他们的 KPI。
想知道顶级代理商是如何留住高价值客户的吗?文本分析不是通过高价值客户和高 CSAT 分数进行过滤,然后查看他们成千上万的对话日志,而是为你做艰苦的工作。
信息提取技巧确定表现出色的代表在这些对话中有效使用的产品、服务、关键词和短语。微观分类技术揭示细节,让您找到使用这些短语或关键词产生客户满意结果的顺序或模式。
在没有大量资源或时间的情况下,客户服务团队可以找到成功的短语、关键词、语言、语调以及这些的组合来产生出色的结果。
早期发现高价值客户和客户问题
图片作者为纯语音技术
对于任何想要做好的企业来说,发现潜在客户或像你最好的客户一样的客户的能力是非常重要的。同样有用的是快速消除任何可能升级的潜在问题的能力。
你知道什么更好吗?早期发现的能力。
作为客户和公司之间的中介,客户服务团队最适合预先筛选有价值的客户和客户问题。
- 在对话中,您可以轻松获得见解并回答如下问题:
- 高价值线索和客户的沟通模式有哪些?
- 为了防止品牌受损,我们需要迅速关注哪些客户突破话题?
- 客户使用哪些渠道来解决不同的问题,我们如何转移资源来更好地管理他们的偏好?
在潜在的客户问题成为大问题之前检测它们是客户支持中文本分析的常见用例。简单的聚类和主题建模技术可以帮助团队实时解决这些问题。
但是,它如何识别有价值的客户呢?
传统上,确定理想客户是通过客户终身价值、购买频率、宣传等指标。但是这些并不是他们唯一共有的特征。
通过结合文本分析技术,你可以发现他们购买前的路径、联系偏好,甚至是他们沟通中单词和短语组合的相似序列。
这些都可以在客户服务工具和通信中找到。
使用微分类,细微的含义被附加到文本的小部分,让客户服务团队附加灵活而详细的数据解释,以获得广泛的分析结果。然后,聚类和主题建模技术使用这些全面的类别来发现趋势和关系,以揭示数据支持的见解,从而揭示有价值的客户识别模式。
剩下的是帮助锁定和优先考虑高价值客户以实现团队 KPI 的模式和识别特征。
这一过程会耗费大量资源,但有了文本分析,深入现有数据寻找关键绩效指标的洞察力不仅更快,而且更加准确和可扩展。
自动化票证路由、优先级划分和标记
图片作者为纯语音技术
众所周知,交接对客户来说是令人沮丧的,但大多数人都忽略了它对客户服务团队来说同样令人烦恼。
效率低下或完全不正确的机票发送和优先顺序会导致客户不满,并对员工大打出手。强调尽可能多的快速浏览也不会促进有助于对话分析的高质量的互动后工作(总结时间)。
在这一点上,没有人是赢家。
- 输入,文本分析。以下是它在支持团队中帮助票证自动化的 3 种方式:
- 根据客户、问题和票证内容的紧急程度,自动将票证发送给适当的代表
- 根据自动检测到的紧急程度和情绪确定票证的优先级
通过自动对话标记减少交互后的工作和对话分析
自动化票据路由和优先级的好处是显而易见的,但是自动化标记有必要吗?
绝对的。
自动标记有助于减少客户互动后耗时的包装时间。全球平均包装时间为 6 分钟。这相当于员工在每次谈话后花了 6 分钟的宝贵时间来完成数据输入和充当人工路由器。
更重要的是,标记是在对话分析中提取价值的关键基础。没有高质量和准确的标记,分析结果毫无意义。你会相信不准确和不完善的数据集能给你带来创收和令客户满意的见解吗?没想到会这样!
那么,它是如何工作的呢?
- 提取。这种技术可以帮助您找到主题、关键字、实体,甚至紧急程度。分配标签。
- 分类。这一步让您可以控制添加额外的公司或行业特定标签,以定制您想要查看的详细程度和价值。分配标签。
- NLP 训练标记数据,应用于过去和未来的对话。
- 监控标签并根据需要添加新标签。
图片作者为纯语音技术
客户报告之声
图片作者为纯语音技术
自然,作为公司客户前线的团队,支持团队完全有能力代表公司的客户支持者。
但是,客户服务流程和员工的日常管理已经够具挑战性了。并不总是有足够的时间或资源致力于在对话中发现影响底线的见解。
这就是文本分析伸出援手的地方。
在对话中发现的一些客户意见包括:
- 潜在高价值客户表现出哪些沟通序列或模式?
- 下个季度客户最关心的 5 个问题是什么?
- 哪些问题或主题占用了团队的大量资源,但可以用自动化方法轻松回答?(如知识库或聊天机器人)
像 Intent Manager 这样的文本分析工具很大程度上为你运行分析。经过一些人为的培训,定制你希望你的团队或公司看到的价值后,它会自动挖掘洞察力。
代表你,它将不知疲倦地工作,提取有用的模式,序列和关系,你的客户。
想报告顾客渴望看到什么并将为下一季度支付什么?文本分析技术,如提取、分类和主题建模,可以结合使用,以找到热门主题,衡量他们的挫折感,并估计解决问题的价值。
想通过引入自动化聊天机器人来处理第 1 级查询,从而提高服务团队的效率吗?文本分析方法可以为您提供数据支持的信息,包括这些查询被提出的次数、被提出的频率以及解决这些查询需要多少次互动。更好的是,它为您提供了开始训练聊天机器人的主题数据,确切地说,使用什么样的训练数据,以及提供自动响应所需的所有信息。
那是为你准备的大部分工作。
这些见解可以导出到数据可视化平台,使报告更具美感,在会议中更容易理解。
文本分析简化了客户报告之声。它有助于创造可靠的、有数据支持的、直接来自客户的见解,当然也不会损害你作为公司客户代言人的地位😉。
简化知识库的创建和维护
图片作者为纯语音技术
随着客户和员工将偏好转向自助服务,知识库变得越来越重要,支持团队也在尝试自动化不太复杂的任务,以腾出代理时间。
无论是内部的还是面向外部的,3 个关键因素决定了知识库的成功:
- 相关性 —用户需要能够找到不需要代理干预的最常见、最紧迫的问题
- 清晰 —用户需要理解定义、说明和解释来解决他们的问题
- 可搜索性 —用户需要能够轻松、轻松、快速地找到信息
虽然知识库的概念和好处很容易理解,但实际的创建和维护可能是一项艰巨的任务。
您知道客户询问的不需要代理帮助的三个主要话题吗?什么事?伟大的!
你知道这些话题中最常被问到的前 5 个问题吗?什么事?太棒了!
您知道顶级支持代表如何回应,以使客户理解并满意吗?通常,这里有很多思考的面孔🤔。
拥有这三个问题的答案对于创建一个对客户和公司都有益的知识库至关重要。
拥有相关的核心主题有助于用户找到答案。包括最常见的问题有助于减少代理在回答琐碎问题上花费的宝贵时间。用容易理解的语言和结构回答问题是知识库有用性的基础。
显然,这比大多数团队签约的工作量要多得多。
好消息是,整个过程可以通过文本分析加速!
- 通过对历史客户信息进行文本分析,您可以发现:
- 自助知识库中可以解决的核心客户主题
- 每个主题中最常见的问题
- 知识库中的答案应该如何措辞和组织,以便于理解
好奇文本挖掘如何帮助创建更好的知识库?作为一个例子,让我们看看它是如何对清晰度做出贡献的。
使用信息提取和聚类技术,我们能够找到客户用来描述他们的问题的方言。这允许团队使用他们理解和搜索的语言,帮助他们在知识库中找到答案。
此外,主题建模和微分类技术可以结合起来,以找到客户在询问特定主题时可能会有的相关查询,帮助创建导航链接和资源,以全面解决问题。
毕竟,如果用户只通过自助服务解决了一半的问题,他们仍然需要与人交谈来解决剩余的问题,这违背了自助服务渠道的目的。
营销团队的文本分析
在吸引、吸引和取悦客户的业务中,营销团队通过尽可能多地了解他们的线索和客户而受益匪浅。
营销需要知道他们正在经历什么样的痛苦,他们在哪里闲逛,为什么他们对你的产品或服务有某种感觉,等等。马上,一些问题浮现在脑海里:
- 你如何进入他们的思想和鞋子?和;
- 如何在不超载的情况下捕获这么多有价值的数据?
使用文本分析有助于缓解这两个问题引起的问题。
为了了解顾客的想法和感受,公司通常通过调查、采访和反馈的形式来了解他们。这些方法都很棒,但是通常被忽视的,实际上是以最公正和不受影响的形式呈现的反馈,是客户沟通。
客户沟通可以有各种形式——社交媒体评论、私人消息、支持票、电话记录、电子邮件和实时聊天——这只是基于文本的最大数据源中的几个例子。
给定足够的数据和一些 NLP 训练,文本分析帮助营销团队处理大量的通信,并将它们转化为对客户满意度和创收有用的见解。
至于文本挖掘如何帮助信息过载,它的优势在于它的机器学习和 AI 增强。持续不懈地,营销团队可以大规模地处理大量的通信,减少信息过载对有价值的洞察力提取的影响。
听起来很方便,对吧?
让我们更深入地研究一些有形的文本分析营销用例。
用例目录:营销团队的文本分析
- 寻找新的品牌认知度和目标战略
- 早期客户趋势检测
- 抓住潜在客户机会
- 获取定量和定性营销结果的整体报告
寻找新的品牌意识和目标战略
图片作者为纯语音技术
利用随时可用的历史客户互动,文本分析技术可用于提取有价值的见解,以新的方式锁定客户并提高意识。
客户互动的发生是因为客户希望分享一个观点,无论是投诉、称赞、意见还是请求。这里重要的一点是,他们已经想尽办法去接触公司,以表明自己的观点。
这使得它们对营销人员来说很有价值,可以洞察他们客户的世界——他们担心什么,体验什么,感觉什么,计划用你的产品或服务实现什么。
遗憾的是,没有多少公司认为这是一种绝妙的营销手段。
部分问题源于交互量的巨大。从 10 多个渠道的数百万条历史信息中找出联系和模式是非常困难的。此外,它的定性性质也没有帮助,因为大多数公司更喜欢量化他们的报告和成就指标。
这就是文本挖掘变得非常方便的地方。它在定量和定性两个层面上进行报告,并且很容易扩展到处理数百万次交互。
文本分析用于客户沟通,以获得营销见解,可以回答以下问题:
- 客户问题和我们传达的信息之间是否有误解,我们如何使用他们的话?
- 有多少线索通过特定渠道、媒体或影响者接触到我们的品牌?他们对品牌的加权看法是否证明了对渠道、媒体或影响者的投资或进一步投资是合理的?
- 在客户的整个生命周期中,客户满意度在互动中的演变是怎样的?我需要瞄准哪一点才能赢回他们?
早期客户趋势检测
图片作者为纯语音技术
对营销团队来说,掌握客户趋势一直很重要。如今保持领先的问题是要跟上大量的新事物。
下一个新频道是什么?谁是最新的影响者?新的线索从何而来?
幸运的是,在您的交流中,现有客户和潜在客户已经可以回答其中的一些问题。
找出他们是通过什么渠道了解你的品牌的,哪些影响者转变了他们对你的产品的信任,以及他们以前在哪里听说过你的服务,这有助于你找到其他像他们一样的人。
这并不是建议对你所有的潜在客户和客户进行大规模采访,而是要挖掘你过去的所有互动,其中大部分信息可能已经存在。
- 通过使用文本分析,营销团队可以回答如下问题:
- 我的客户和潜在客户有兴趣尝试哪些渠道?我的品牌出现在那里有意义吗?
- 我的客户信任哪些有影响力的人,我如何定位品牌才能与之保持一致?
- 我的客户对什么话题感兴趣或关注?他们希望如何解决这个问题?
挖掘过去和正在进行的互动有助于营销团队监控客户聊天,并领先于新出现的话题。这种在客户洞察方面的领先优势使营销能够专注于制定客户支持和数据驱动的营销决策,而不会被信息和分析所淹没。
抓住潜在客户机会
图片作者为纯语音技术
优秀的营销团队能够发现一些线索转化为客户的例子。优秀的营销团队会在这些阶段找到线索,从而优化转化率。世界级的营销团队?他们发现标志着潜在客户向客户转化的模式和行为,这样他们就可以一路培养下去。
你是如何从优秀的走向世界级的?
最切实的方法之一(显然是有数据支持的😉)是文本分析。也就是说,分析客户文本数据,如对话、社交媒体互动和支持票,以确定处于考虑阶段的人们共享的沟通模式。
这可能是他们使用的沟通渠道的模式,他们问的问题的类型,甚至是他们在互动中选择单词的顺序。
文本分析有助于在您的客户的沟通风格中找到这些独特的细微差别和模式,以更好地识别处于甜蜜转换点的未来线索。
- 文本分析可以帮助营销人员回答的其他一些问题包括:
- 符合营销资格的销售线索会问什么样的问题和回答才能真正将其归类为符合销售资格?
- 是否存在一种识别潜在高价值客户的沟通模式?
- 在互动中,我使用哪一组品质来评估销售线索的潜在客户终身价值?
文本分析消除了人类在消化所有这些对话以提取潜在价值标识符的过程中产生的偏见、错误和不可避免的令人兴奋的无聊感。剩下的是营销团队可以执行的可操作的见解,充分利用潜在客户机会。
定量和定性的营销报告
图片作者为纯语音技术
客户体验的营销报告通常以量化数字为中心,例如:打开率、参与度、流失率和保留率。众所周知,这些指标通常无法捕捉客户体验及其满意或不满意的全貌。
这一差距是由于缺乏对定性见解的报告而造成的。这些见解来自非结构化数据源的内容,如客户对话、反馈和电话记录。大多数公司只获取这些数据来源的数字:票证数量、问题解决时间、电子邮件打开率、参与比例等。
更重要的是,尤其是在衡量顾客对品牌的意见和满意度时,这些互动的内容。当客户表达他们对某个品牌的快乐时,真正有意义的是他们在通过文字表达自己的观点,而不是简单地在帖子上一个“赞”。
试图获取这些定性来源的问题在于,人们认为无法对其进行衡量。营销报告由数字主导,如果用其他方式表达,会降低对营销团队工作的信任。
那么,你如何抓住营销团队在客户体验方面的全部出色工作,同时确保你用数字传达它的重要性?
答案?文本分析。
借助文本分析,可以捕捉到以前仅在定性洞察领域出现的一些要点:
- 是否有我们以前没有考虑过的“顾客表达的使用产品 X 的动机”的集群?
- 谈论产品 X 时使用的情感语言与之前在过去的互动中表达负面情绪的客户之间有关系吗
- 客户在谈论产品 X 时,表达情感的话语有哪些?
文本分析从非结构化的客户数据中获取定量和定性的见解。在获取定性数据时,需要采用定量方法来寻找能够揭示数据内容的模式和序列。
为了说明这一点,假设我们想报告本季度尝试的新的客户启发的目标定位策略。在对社交媒体评论进行文本分析后,发现许多客户使用以下顺序:“人”+我们需要这个是为了/我们需要得到这个是为了+“目的”。在评论中,这可能看起来像: @monica 我们需要在这上面认识一些新的供应商。
图片作者为纯语音技术
像 Intent Manager 这样的文本分析工具在数以千计的社交媒体评论和多个渠道中检测这一序列,将主要动机归为一类,作为了解潜在客户为何对您的产品感兴趣的关键因素。然后,这可以用于创建新的目标活动,或提出客户数据支持的新战略提案。
在不需要人工干预或过多资源的情况下,文本分析一旦得到训练,就可以让营销团队更全面地捕捉他们的劳动成果进行报告,并做出更好的数据驱动、客户支持的营销决策
聊天机器人团队的文本分析
聊天机器人团队面临许多独特的挑战。
在许多商业系统中过时的流程和协议的背景下,在对话式人工智能中追求创新的同时,他们必须最大化商业价值,鼓励采用并解决客户数据的混乱,同时仍然驾驭技术的复杂性。
毫无疑问,对于一项迅速成为现代商业必需品的技术来说,这是最艰难的工作之一。
幸运的是,文本分析有助于应对这些挑战。其扩展模式和洞察力提取的能力有助于聊天机器人团队在整个组织中加强其工作的价值,并解决聊天机器人特有的问题,如意图冲突。这些技术对于使用企业聊天机器人的团队特别有用,因为企业聊天机器人中的数据有 100,000 或数百万。
让我们通过一些用例来了解文本分析如何帮助聊天机器人团队。
用例目录:客户服务团队的文本分析
- 规模聊天机器人跨组织价值
- 发现影响深远的自动化机会
- 解决令人沮丧的意向冲突
衡量聊天机器人的跨组织价值
图片作者为纯语音技术
聊天机器人通常一开始是为专门用途而构建的,当需要为其他团队或用例改变用途时,团队会发现很难证明相同的价值或获得相同的采用。因此,许多团队努力为整个组织的关键商业价值做出贡献,而不仅仅是一个固定的用途或一小组目标。
文本分析通过微分类或“标记”方法,帮助组织中的其他团队了解聊天机器人的价值,能够根据其特定业务部门的需求对数据进行个性化解释。
为了说明这个例子,让我们假设一个客户在聊天机器人交互中响应,“我永远无法在 Slack 消息中找到我需要的文件”。根据您所在的团队,您将分配不同的下一个最佳行动“标签”。
- 客户服务团队可能会标记:“在知识库中添加更全面的操作方法搜索”。
- 开发团队然后可以标记:“为下一次更新优先改进可搜索性”。
- 营销团队可能会标记:“将此作为改进搜索功能更新的客户启发信息”。
图片作者为纯语音技术
通过让团队能够根据他们的特定需求和目标定制价值(以及“下一个最佳行动”),聊天机器人的感知价值和采用率自然会增加。更好的是,文本分析不需要聊天机器人团队的广泛协调,而是授权其他团队从一个民主化客户数据之声的渠道创造价值。
此外,随着团队将他们的解释添加到数据中,可以绘制更复杂的交叉分析和模式。结合起来,他们提供了更多的机会来寻找进一步的自动化机会,创收的想法和客户满意的战略。
识别高影响力的自动化机会
图片作者为纯语音技术
作为聊天机器人团队,你总是在寻找用智能自动化技术优化业务流程的方法。问题是,它们值得投资、时间和资源吗?
为什么不征求一些客户的意见呢?他们告诉你他们将如何花费更多,如何感到满意,如何推荐他人。你所要做的就是倾听。
借助文本分析,您的团队可以积极听取大量客户意见,包括支持票、反馈、社交媒体评论和电子邮件,而无需进行监控。
分析客户互动有助于发现以下自动化机会:
- 客户经常提到或要求
- 当被客户提及时,会联想到负面情绪
- 基于您选择的标准或过滤器的优先级
无论您希望了解哪些自动化机会将产生最大影响,还是了解对特定产品功能的关注,文本分析都有助于整理客户输入,为您的团队提供数据驱动、客户支持的见解,以便采取行动。
结果也可以根据您团队的目标进行定制。通过 NLP 的人在回路训练,你的团队可以定制主题聚类以适应焦点或目的的变化。
解决令人沮丧的意图冲突
图片作者为纯语音技术
意图冲突(也称为双重意图或意图冲突)是令人讨厌的聊天机器人问题,源于聊天机器人旅程开始时不正确的 NLP 训练。通常,这源于 T4 没有有效地管理聊天机器人收到的大量问题。
它们很难检测,更难确定如何修复以及在哪里修复,这使得修复成为一个成本高昂且耗费大量资源的问题。
有了像 Intent Manager 这样的文本分析工具,聊天机器人团队可以:
- 快速识别冲突意图
- 查明导致问题的训练短语
- 在潜在的意图冲突发生之前对其进行监控
无需投入大量资源来回溯训练,然后手动重新分类短语,文本分析技术可以帮助聊天机器人团队快速发现意图冲突,并提供快速解决冲突的解决方案。
有哪些文字分析的软件或工具?
在我们深入研究这些工具之前,这里有 3 个问题是你在为你的企业选择文本挖掘工具时应该问自己的。
1。我希望看到什么样的商业价值?
不言而喻,对于一个文本分析软件来说,最重要的标准应该是它获取商业价值的能力。洞察力不应该只停留在最“常见”或“趋势”的方面,而应该以潜在的业务目标作为过滤器进行分析。一个好的工具需要让用户定制过滤器。
2。我需要考虑我的文本数据的哪些特征?
为您的特定用例找到最佳软件或工具在很大程度上取决于:
- 文本类型
- 文本量
- 您希望在结果中看到的详细程度
- 有多少已经被人类分类或“标记”
根据这些因素,最适合您的用例的文本分析技术的类型会有所不同,每种技术的微小变化都会极大地影响您应该使用的技术。
3。它在多大程度上符合我的技术环境?虽然总是建议为工作寻找最好的工具,但当你有非常具体的技术组合时,这有时是不可避免的。在这种情况下,您需要考虑文本分析工具的集成情况。理想情况下,找到一个与技术无关的工具,并与您的堆栈配合良好。
这些是你应该问自己的第一个问题。这里有一个链接,链接到选择 NLP 工具的考虑事项的更全面的列表。
相关:会话分析的 3 个阶段,简化。
图片作者为纯语音技术
说完了,我们再来看一些文本分析工具,按初级、中级和高级三个级别的文本分析进行拆分。
初学者三重奏
- 您的 CRM
- 擅长
- 社交倾听工具
你会惊讶地发现,有多少大公司仍在混合使用他们当前的工具和 Microsoft Excel 来分析沟通。毫无疑问,这是一种开始分析的快速方法,但从长期或中期来看,它是不可扩展的。
如果你正处于这个阶段,建议你快速了解你想从文本分析中得到什么,以及你需要什么分析工具。然后,尽快升级到该工具。好处无穷。从文本分析流程的所有阶段节省了数百个小时,以及更快的业务响应以降低成本或创造收入。
“最佳实践”工具
- Google NLP 产品— AutoML 和自然语言 API
- 亚马逊领悟
- 沃森自然语言理解
- Azure 文本分析 API
许多大型组织在他们的对话分析中使用这些工具,这是正确的。它们很简单,由通用的 NLP 驱动,适用于所有部门、行业和团队。
然而,其中许多产品的一个大缺点是,它们大多能很好地与它们的产品套件配合使用,并且需要昂贵的定制、资源和培训来与企业环境中的其他技术相结合。然后,东西会很快变贵。
在分析深度方面,他们能够很好地挑选出话语中的元素,但往往过于笼统,无法获得更深层次的商业价值。
不要相信我的话,你可以在谷歌和 Azure 的登陆页面上试试它们的演示。插入一段对话,自己看看结果。他们能在多大程度上提取相关和具体的信息来推动您的组织采取富有成效的行动?
“深潜”工具
- 纯语音技术意图管理器
- 查特米尔
- 沃里克分析公司的预测
这些工具为您的客户沟通提供了更多的内容和意义。他们试图理解对话、所有的模式和细微差别,以便提供有价值的、可操作的和有意义的见解。
纯语音技术专家喜欢这些工具的另一个原因是因为它们很灵活。他们不依赖于某一套特定的产品。企业已经拥有如此复杂的技术环境。没必要再加一个和别人玩不好的工具。
外卖食品
在我们这个时代,企业和客户之间的交流量不可避免地在增加。能够管理大量信息并获得业务驱动的价值正成为一家成功或失败公司的明显标志。
因此,文本分析工具正迅速成为任何有前途的企业的必备工具。
它提供了一种工具,将直接来自客户的见解民主化到业务的所有部分。无论是营销、客户支持、产品还是创新团队,不可否认的是,直接的客户洞察可以对团队的方向和底线盈利能力产生影响。
如果你对对话式 AI 的文本分析有疑问,给我们发消息!教育是 Pure Speech Technology 的重要支柱,我们很乐意回答您的文本分析问题。
A/B 测试指南——如何制定、设计和解释
原文:https://towardsdatascience.com/a-guide-to-a-b-testing-how-to-formulate-design-and-interpret-f820cc62e21a?source=collection_archive---------8-----------------------
用 Python 实现
来源
网络世界给了我们一个很好的机会来进行实验和科学地评估不同的想法。由于这些实验是数据驱动的,没有为直觉或直觉提供空间,我们可以在变化及其对用户行为的影响之间建立因果关系。利用这些实验,许多组织可以通过避免所谓的河马效应来了解他们客户的喜好和偏好😅
A/B 测试是测试新产品或新功能的常用方法,尤其是在用户界面、营销和电子商务方面。A/B 测试的主要原理是将用户分成两组;向控制组展示现有产品或功能,向实验组展示新产品或功能。最后,评估两组用户的不同反应,决定哪个版本更好。尽管 A/B 测试是在线业务的常见做法,但从建立实验到正确解释结果,很多事情很容易出错。
在本文中,您将发现如何设计一个健壮的 A/B 测试,为您提供可重复的结果,A/B 测试中需要额外注意的主要陷阱是什么,以及如何解释结果。
您可以在我的 GitHub 上查看 Jupyter 笔记本以获得完整的分析。
来源
在深入探讨 A/B 测试之前,我们先来回答以下问题。
1。可以考什么?
可见和不可见的变化都可以用 A/B 测试来测试。可见变化的例子可以是用户界面的新增内容、设计和布局的变化或标题信息。一个非常受欢迎的例子是谷歌的 41(是,不是 2)种不同蓝色阴影实验,他们随机向每 2.5%的用户展示一种蓝色阴影,以了解哪种颜色阴影赢得更多点击。不可见变化的例子可以是页面加载时间或测试不同的推荐算法。一个流行的例子是亚马逊的 A/B 测试显示,页面加载时间每增加 100 毫秒,销售额就会下降 1%。
2。什么不能考?
新体验不适合实施 A/B 测试。因为一个新的体验可以表现出 厌恶变化 的行为,用户不喜欢变化,更喜欢坚持旧版本,或者它可以表现出 新奇效果 用户感到非常兴奋,想要测试出一切。在这两种情况下,定义比较的基线和决定测试的持续时间是困难的。
3。我们如何选择指标?
度量选择需要同时考虑灵敏度和稳健性。敏感性意味着指标应该能够捕捉到变化,而稳健性意味着指标不应该因为不相关的影响而改变太多。例如,大多数情况下,如果指标是一个“平均值”,那么它对异常值很敏感,但不够稳健。如果指标是“中值”,那么它是稳健的,但对小组变化不敏感。
为了在度量选择中考虑灵敏度和鲁棒性,我们可以在创建控制和实验样本时应用过滤和分割。过滤和细分可以基于用户人口统计(即年龄、性别)、平台语言、互联网浏览器、设备类型(即 iOS 或 Android)、群组等。
4.管道是什么?
- 阐明假设
- 设计实验
- 收集数据
- 推论/结论
A/B 测试的过程始于一个假设。基线假设,或者换句话说,零假设,假设处理是相等的,并且由于偶然性,对照组和实验组之间的任何差异是。替代假设假设零假设是错误的,控制组和实验组的结果比随机产生的结果更加不同。A/B 检验旨在以这样一种方式检验假设,即两组之间观察到的差异应该是由于随机的机会或由于两组之间的真实差异。提出假设后,我们收集数据并得出结论。结果的推断反映了应用从实验样本中得出的结论的意图,这些结论适用于整个群体。
让我们看一个例子...
假设您正在运行一个 UI 实验,想要了解初始布局和新布局的转换率之间的差异。(假设您想了解将“购买”按钮的颜色从红色改为蓝色的影响🔴🔵)
在这个实验中,零假设假设转换率相等,如果有差异,这只是由于的机会因素。相比之下,另一个假设假设转换率之间存在统计学上的显著差异。
零假设-> Ho : CR_red = CR_blue
另类假设-> H1 : CR_red ≠ CR_blue
在制定假设并进行实验后,我们在列联表中收集了以下数据。
《出埃及记》测试结果:控制组(CG)看到初始布局,实验组(EG)看到新的布局
The conversion rate of CG is: 150/150+23567 = 0.632%The conversion rate of EG is: 165/165+23230 = 0.692%From these conversion rates, we can calculate the relative uplift between conversion rates: (0.692%-0.632%)/0.632% = 9.50%
从上面截取的代码中可以看出,改变布局将转换率提高了 0.06 个百分点。但这是偶然的还是彩色 change❔的成功
我们可以通过以下两种方式来分析结果:
1。应用统计假设检验
使用统计显著性检验,我们可以衡量收集的数据是否显示了比可能产生的结果更极端的结果。如果结果超出了机会变异,那么它在统计上是显著的。在本例中,我们有偶然性数据格式的分类变量,它们遵循伯努利分布。伯努利分布有一个概率为 1,一个概率为 0。在我们的示例中,转化率=1,无转化率=0。考虑到我们使用转换率作为度量,这是一个遵循伯努利分布的分类变量,我们将使用 卡方检验 来解释结果。
卡方检验假设分类变量的观察频率与预期频率匹配。它计算具有卡方分布的检验统计量(Chi ),如果预期频率和观察频率相同,则解释为拒绝或未能拒绝零假设。在本文中,我们将使用scipy.stats
包来实现统计功能。
卡方分布的概率密度函数随自由度(df) 变化,自由度(df)取决于列联表的大小,在本例中计算为df=(#rows-1)*(#columns-1)
df = 1。
使用 Python 解释测试结果我们需要知道的关键术语是 p 值 和 alpha 。 P 值是在假设零假设正确的情况下,获得至少与实际观察到的结果一样极端的检验结果的概率。p 值是测试的结果之一。Alpha 也称为统计显著性水平,是犯I 型错误的概率(拒绝实际为真的零假设)。犯第二类错误(当零假设实际上为假时,未能拒绝零假设)的概率被称为 beta,但这超出了本文的范围。一般来说,α取 0.05,表示当没有实际差异时,得出组间存在差异的风险为 5%。
就 p 值和选定的显著性水平(α)而言,测试可解释如下:
- 如果 p 值<=α:显著结果,拒绝零假设
- 如果 p 值>α:不是显著结果,不要拒绝零假设
我们还可以通过使用测试统计和临界值来解释测试结果:
- 如果检验统计量> =临界值:显著结果,拒绝零假设
- 如果检验统计量<临界值:没有显著结果,不要拒绝零假设
### chi2 test on contingency table
print(table)
alpha = 0.05
stat, p, dof, expected = stats.chi2_contingency(table)### interpret p-value
print('significance=%.3f, p=%.3f' % (alpha, p))
if p <= alpha:
print('Reject null hypothesis)')
else:
print('Do not reject null hypothesis')
### interpret test-statistic
prob = 1 - alpha
critical = stats.chi2.ppf(prob, dof)
print('probability=%.3f, critical=%.3f, stat=%.3f' % (prob, critical, stat))
if abs(stat) >= critical:
print('Reject null hypothesis)')
else:
print('Do not reject null hypothesis')
[[150 23717]
【165 23395]]
显著性=0.050,p=0.365
不拒绝零假设
概率=0.950,临界=3.841,统计=0.822
不拒绝零假设
从结果中可以看出,我们没有拒绝零假设,换句话说,转换率之间的正相对差异并不显著。
2。执行排列测试
排列测试是我最喜欢的技术之一,因为它不要求数据是数字或二进制的,样本大小可以相似或不同。此外,不需要关于正态分布数据的假设。
置换意味着改变一组值的顺序,置换测试所做的是组合两组的结果,并通过从组合的组中随机抽取组(等于实验组的样本大小)并分析它们彼此之间的差异来测试零假设。用户决定多少次,测试就重复做多少次(比如说 1000 次)。最后,用户应该将实验组和对照组之间观察到的差异与置换差异集进行比较。如果观察到的差异位于置换差异的集合内,我们不拒绝零假设。但是,如果观察到的差异位于最大排列分布之外,我们拒绝零假设,并得出结论,因为 A/B 测试结果在统计上是显著的,而不是由于偶然。
### Function to perform permutation test
def perm_func(x, nA, nB):
n = nA + nB
id_B = set(random.sample(range(n), nB))
id_A = set(range(n)) — id_B
return x.loc[idx_B].mean() — x.loc[id_A].mean()### Observed difference from experiment
obs_pct_diff = 100 * (150 / 23717–165 / 23395)### Aggregated conversion set
conversion = [0] * 46797
conversion.extend([1] * 315)
conversion = pd.Series(conversion)### Permutation test
perm_diffs = [100 * perm_fun(conversion, 23717, 23395)
for i in range(1000)]### Probability
print(np.mean([diff > obs_pct_diff for diff in perm_diffs]))
0.823
这个结果告诉我们,大约 82%的情况下,我们会随机得出实验结果。
此外,我们可以绘制排列测试差异的直方图,并突出显示观察到的差异所在。
fig, ax = plt.subplots(figsize=(5, 5))
ax.hist(perm_diffs, rwidth=0.9)
ax.axvline(x=obs_pct_diff, lw=2)
ax.text(-0.18, 200, ‘Observed\ndifference’, bbox={‘facecolor’:’white’})
ax.set_xlabel(‘Conversion rate (in percentage)’)
ax.set_ylabel(‘Frequency’)
plt.show()
带有观察到的差异线的置换差异直方图
如图所示,观察到的差异位于大多数置换差异内,支持卡方检验的“不拒绝零假设”结果。
让我们看另一个例子..
假设我们使用平均会话时间作为度量来分析 A/B 测试的结果。我们的目标是了解页面的新设计是否会引起用户更多的关注,并增加他们在页面上的停留时间。
代表不同用户 id 的前几行如下所示:
数据样本
### Average difference between control and test samples
mean_cont = np.mean(data[data["Page"] == "Old design"]["Time"])
mean_exp = np.mean(data[data["Page"] == "New design"]["Time"])
mean_diff = mean_exp - mean_cont
print(f"Average difference between experiment and control samples is: {mean_diff}")### Boxplots
sns.boxplot(x=data["Page"], y=data["Time"], width=0.4)
实验样品和对照样品之间的平均差异为:22.85
同样,我们将从以下两个方面分析结果:
1.应用统计假设检验
在本例中,我们将使用t-检验(或学生的 t-检验),因为我们有数字数据。t-检验是最常用的统计检验之一,在这种检验中,检验统计量在零假设下遵循学生的 t 分布。在样本量较小且总体标准偏差未知的情况下,估计正态分布总体的均值时使用 t 分布。
t 分布像正态分布一样呈对称的钟形,但尾部更厚更长,这意味着它更容易产生远离平均值的值。如图所示,样本量越大,t 分布就越正常。
在此分析中,我们将使用scipy.stats.mstats.ttest_ind
来计算两个独立样本平均值的 t 检验。这是对两个独立样本具有(预期的)相同平均值的零假设的双边检验。作为参数,我们必须设置equal_var=False
来执行 Welch 的 t-检验,该检验不假设控制样本和实验样本之间的总体方差相等。
### t-Test on the data
test_res = stats.ttest_ind(data[data.Page == "Old design"]["Time"],
data[data.Page == "New design"]["Time"],
equal_var=False)
print(f'p-value for single sided test: {test_res.pvalue / 2:.4f}')
if test_res.pvalue <= alpha:
print('Reject null hypothesis)')
else:
print('Do not reject null hypothesis')
单侧检验的 p 值:0.1020
不要拒绝零假设
从结果中可以看出,我们没有拒绝零假设,这意味着实验样本和对照样本之间的正平均差异不显著。
2。执行排列测试
正如我们在前面的例子中所做的,我们可以通过迭代 1000 次来执行排列测试。
nA = data[data.Page == 'Old design'].shape[0]
nB = data[data.Page == 'New design'].shape[0]perm_diffs = [perm_fun(data.Time, nA, nB) for _ in range(1000)]larger=[i for i in perm_diffs if i > mean_exp-mean_cont]
print(len(larger)/len(perm_diffs))
0.102
这个结果告诉我们,大约有 10%的时间,我们会随机地得到实验结果。
fig, ax = plt.subplots(figsize=(8, 6))
ax.hist(perm_diffs, rwidth=0.9)
ax.axvline(x = mean_exp — mean_cont, color=’black’, lw=2)
ax.text(25, 190, ‘Observed\ndifference’, bbox={‘facecolor’:’white’})
plt.show()
带有观察到的差异线的置换差异直方图
如图所示,观察到的差异位于大多数置换差异内,支持 t 检验的“不拒绝零假设”结果。
奖金
- 为了设计一个稳健的实验,强烈建议确定不变检查的指标。这些度量标准不应该在控制组和实验组之间改变,并且可以用于健全性检查。
- 在 A/B 检验中,重要的是确定代表总体的实验组和对照组的样本量。在这样做的时候,我们需要注意两点:随机性和代表性。样本的随机性是达到无偏结果的必要条件,代表性是捕捉所有不同用户行为的必要条件。
- 在线工具可用于计算实验所需的最小样本量。
- 在运行实验之前,最好确定期望升程值。有时,即使测试结果在统计上有意义,也可能没有实际意义。如果变革不能带来预期的提升,组织可能不喜欢执行变革。
- 如果您正在处理一个样本数据集,但您希望了解人口行为,您可以在分析中包含重采样方法。你可以阅读我的文章推论分析的重采样方法(附后)了解更多⚡
[## 推理分析的重采样方法
当你有一个样本,但你想了解人口
towardsdatascience.com](/resampling-methods-for-inference-analysis-e75fecfefcb2)
我希望你喜欢阅读这篇文章,并发现它很有用!
如果你喜欢这篇文章,你可以在这里阅读我的其他文章和 关注我上媒如果您有任何问题或建议,请告诉我。✨**
喜欢这篇文章吗? 成为会员求更!
成为面向业务的数据科学家指南
原文:https://towardsdatascience.com/a-guide-to-becoming-business-oriented-data-scientist-51da5c829ffa?source=collection_archive---------42-----------------------
如何从商业角度开始思考
图片由 Unsplash 上的 Austin Distel 拍摄
技术技能有助于数据科学从业者解决复杂的问题,如发现评论的情绪或将交易分类为有风险或无风险。强大的数据科学从业者知道如何找到正确的特性,测试模型性能,然后使用适当的技术对其进行扩展。
到目前为止,一切听起来都不错,但仅此而已吗?一名优秀的数据科学从业者需要具备的全部技能是什么?
一个完整的数据科学从业者除了在技术上很强之外,还会从业务角度进行思考。这篇博客文章就是关于这个的,从商业的角度思考,将技术解决方案转化为经济上有影响力的解决方案是什么感觉。
成为面向业务的数据科学家之旅中的三堂课
图片由马丁·威尔纳在 Unsplash 上拍摄
1.量化财务影响
这是数据科学从业者需要具备的最重要的业务技能。这是提供一个大概的数字,作为实施推荐功能的业务影响的能力。我们用一个例子来理解。
假设你是一名数据科学家,在一家基于移动应用的公司工作。移动应用根据用户识别的潜在兴趣和关注的标签向用户显示图片和视频。该公司通过在应用程序中显示广告来赚取收入。作为一名数据科学家,你被要求改进推荐这些图片和视频的推荐系统。您对以前的系统做了一些改进,并对样本用户进行了测试,以发现改进/增加的时间花费。结果显示,每个用户平均花费的时间提高了 1%。
接下来,您向风险承担者展示了结果,他们对所花时间的增加/改善并不满意。他们觉得改善很少。利益相关者无法做出决定的一个原因是,将建议的推荐系统扩展到整个应用程序涉及到成本,他们不清楚 1%的改善会带来多大的收入。
通过实施推荐系统的变革,您在向利益相关者清晰展示财务影响方面可以做得更好吗?可以做的一件事是量化收益。让我们看看我们如何能做到这一点,并得到一些大概的数字。
Average time spent by a user on app per day = 20 minsImprovement in time spent per user by implementing the changes in Recommender system = 1%Total user base = 10M users.Average number of adverstisements shown to user per 2 minutes = 1
i.e 0.5 advertisements per minuteAmount earned per advertisements = $0.02Estimated Revenue gain daily on implementing the solution =
Total_users * additional_1%_time_per_user * advertisements_per_minute * amount_earned_per_advertisement
= 10M * (0.01 * 20) * 0.5 * 0.02 = $20KEstimated Revenue gain monthly = $20K * 30 = $600K
展示实施建议推荐系统的每月 60 万美元收益的量化值,将有助于利益相关者更好地决定是否承担实施和扩展建议系统的成本。
2.掌握赢得利益相关者信任的艺术
利益相关者通常是了解企业内外的人。他们可能只有非常有限的技术知识,但对什么可行什么不可行有非常强的商业直觉。这些人见证了企业的发展壮大,赢得他们的信任是一门艺术。让我们看看如何做到这一点。
假设我们正在为业务提供一个预测解决方案。在讨论我们的模型做什么或它的准确性之前,我们将展示一些从数据中获得的事实和数字,以向他们表明我们知道我们在做什么。这些事实可能是-
- 每年 11 月至 12 月期间,我们都会看到销售额在节日期间增长大约 X%。
- 与去年同期相比,中国的经济增长率约为 1.5% .
- 我会展示一些图表来增强我对事实和数据的信心。
在陈述了事实和数据之后,我将会谈到所考虑的特征,听取利益相关者的意见,因为商业知识有时会变得非常重要,并提供一种优势。
关于建模细节,我将保持非常简短和高层次的概述,甚至跳过并继续讨论对业务最重要的东西,在许多情况下是准确性或增益或输出。
有时,大声说出面临的挑战也很重要,因为这有助于赢得一些时间,否则利益相关者总是急于要交付成果。
3.建议更多
面向业务的数据科学从业者不仅很好地完成了要求他做的事情,而且还通过向利益相关者建议还可以做些什么来更进一步。一个好的数据科学从业者向利益相关者展示了更多神奇的数据科学可以改变他们的业务。
如果我们以同一家基于移动应用的公司为例,它可以向利益相关者建议向用户智能通知媒体的想法及其利益实现。还可以是基于点击率对广告进行排名,并利用该排名来决定更多地显示哪些广告。
不要停下来,继续思考。
结论
通过这篇博客,我专注于数据科学的商业方面。我们讨论了如何量化模型的财务影响。我们还讨论了如何赢得利益相关者的信任,以及如何从商业角度思考问题。希望你喜欢这篇文章。
如果你有任何疑问,请联系我。我有兴趣了解您正在解决的业务问题,以及您如何创建解决方案并量化其财务影响。
我的 Youtube 频道获取更多内容:
[## 阿布舍克·蒙戈利
嗨,伙计们,欢迎来到频道。该频道旨在涵盖各种主题,从机器学习,数据科学…
www.youtube.com](https://www.youtube.com/channel/UCg0PxC9ThQrbD9nM_FU1vWA)
关于作者-:
Abhishek Mungoli 是一位经验丰富的数据科学家,拥有 ML 领域的经验和计算机科学背景,跨越多个领域并具有解决问题的思维方式。擅长各种机器学习和零售业特有的优化问题。热衷于大规模实现机器学习模型,并通过博客、讲座、聚会和论文等方式分享知识。
我的动机总是把最困难的事情简化成最简单的版本。我喜欢解决问题、数据科学、产品开发和扩展解决方案。我喜欢在闲暇时间探索新的地方和健身。在 中 、Linkedin或insta gram上关注我,查看我以前的帖子。我欢迎反馈和建设性的批评。我的一些博客-********
- 每个数据科学家都应该避免的 5 个错误
- 以简单&直观的方式分解时间序列
- GPU 计算如何在工作中拯救了我?
- 信息论& KL 分歧第一部分和第二部分
- 使用 Apache Spark 处理维基百科,创建热点数据集
- 一种基于半监督嵌入的模糊聚类
- 比较哪种机器学习模型表现更好
- 分析 Fitbit 数据,揭开疫情封锁期间身体模式变化的神秘面纱
- 神话与现实围绕关联
在 MongoDB 上免费构建报告分析的指南
原文:https://towardsdatascience.com/a-guide-to-build-reporting-analytics-on-mongodb-for-free-52213265e45c?source=collection_archive---------14-----------------------
更新:对复杂的分析前景感到困惑?查看我们的书: 《分析学设置指南》 。
像 MongoDB 这样的 NoSQL 数据库为应用程序提供了灵活、可伸缩和快速的数据存储。然而,缺乏分析功能和连接操作使得 NoSQL 数据库中的数据难以分析。
在本教程中,我将带您通过 5 个简单的步骤,不仅构建一个实时仪表板,还使用 Holistics 在 MongoDB 上构建一个可扩展的数据分析堆栈:
- 将 SQL 数据库设置为数据仓库
- 建模数据、导入数据、转换数据
- 构建和浏览数据集以创建有意义的可视化效果
- 使用过滤器构建交互式仪表板
- 将仪表板计划为松弛状态
本指南中使用的数据是注册 Mongo Atlas 帐户时可用的 sample_mflix 数据库。该数据库包含关于电影、场次、影院、用户、和评论的数据。
什么是整体论?
Holistics 是一个 BI 平台,可帮助您设置和运行完整的数据分析堆栈:从整合多个数据源、对数据建模到生成有意义的见解。它现在提供了一个免费层,所以你现在就可以注册并按照这个指南开始构建你的仪表盘。
1.准备数据仓库
数据仓库是一个中央数据库,用于存储来自不同来源(BigQuery、MySQL、MongoDB、Google Analytics、Google Sheets……)的数据,并针对分析目的进行了优化。
由于 MongoDB 的界面对分析师(他们主要接受 SQL 培训)不友好,而且它没有连接,您需要将数据从 MongoDB 拉到 SQL 数据库(PostgreSQL、BigQuery、MySQL..)来利用它的分析功能。
如果您还没有数据仓库,请查看这些指南
- 为数据仓库设置 Google 大查询
- 使用 ElephantSQL 在 10 秒内建立一个免费的 PostgreSQL 数据库
准备好数据仓库后,您可以将它连接到 Holistics,这里我连接到我的 PostgreSQL 数据库,并将其命名为demodw
连接到您的 SQL 数据库
2.为您的数据建模
简而言之,数据建模是将业务逻辑映射到物理数据的过程,这样您就可以理解它。在整体主义中,数据建模过程旨在:
- 合并来自多个数据源的数据。
- 转换数据以生成易于查询和解释的用户友好的数据单元。
- 用元数据为系统生成的原始数据赋予业务意义
- 支持数据自助服务和协作
这一步的最终结果是一个逻辑层(一个“数据建模层”),它允许进一步的数据操作。
2.1 导入 MongoDB
在这一步中,我将把 MongoDB 数据导入到我上面连接的数据仓库 demodw 的表中,并设置一个时间表来刷新这个导入。
在数据建模视图中,从数据导入创建数据模型,选择 MongoDB。在这一步,系统还会提示您选择一个默认模式来写入导入的数据。
导入 MongoDB
接下来,添加我的 MongoDB 连接:
添加 MongoDB 连接
选择您想要导入的 MongoDB 表。这里我选择了所有的表格(评论、电影、场次、影院、用户)
选择要导入的 MongoDB 表
导入成功后,您可以打开每个数据模型来查看其结构或预览数据仓库中的实际数据。
2.2 提取 MongoDB 字段
如果您的列包含数组或嵌套文档,您需要使用 SQL 将它们提取到单独的列中。
例如,电影的记录有键imdb
,结构如下。我将把rating
值提取到imdb_rating
字段,以备后用。
"**imdb**": {
"**rating**": { "$numberDouble": "7.3" },
"**votes**": { "$numberInt": "5043" },
"**id**": { "$numberInt": "12" }
}
打开 Movies Model,选择 Add / Calculated Column ,给它一个名字,用这个查询提取 imdb_rating {{ #THIS.imdb }}::jsonb ->> 'rating'
。它将在包含rating
值的 Movies 模型中创建一个名为 IMDB Rating 的新字段。
向数据模型添加自定义维度
2.3 添加一项措施
度量是从 SQL 的聚合函数和操作创建的,例如COUNT()
、SUM()
、AVG()
、SUM(field_a) + SUM(field_b)
...通过结合度量和维度,您可以确保您的最终用户能够产生正确的计算结果并产生洞察力,而无需自己编写公式。
这里我用 SQL 公式count({{ #THIS.id }})
创建了一个简单的count_movies
度量。语法遵循您的数据库的 SQL 风格,因此您可以创建更复杂的度量,如“评分 8 及以上的电影计数”:count(case when {{#THIS.imdb_rating}} >= 8.0 then {{#THIS.id}} else null end)
拖动其他维度,可以通过released_year
、genres
、countries
来断开count_movies
...
添加度量值
2.4 添加数据模型之间的关系
关系有助于您浏览不同表中的数据,而无需显式编写联接 SQL。
例如,一部电影可以有多个评论,所以我将在comments.movie_id
和movies.id
上用多对一关系(n-1) 将comments
数据模型链接到movies
数据模型。
添加数据模型之间的关系
您也可以单击“关系”选项卡来查看关系图。
2.5.转换您的数据并从其他数据源导入
上面的步骤只涉及一个 MongoDB 数据源,并涉及一个简单的转换(从嵌套字段中提取值)。然而,您也可以在您的分析中集成来自其他来源的数据(如 CSV 文件、Google Sheets、脸书广告……),并编写更复杂的 SQL 转换。为了让本指南简单明了,我将把这些操作留给另一篇文章。
如果你想知道你还能做什么,你可以参考这些文件:
- 如何从外部数据源创建数据模型
- 数据导入
- 数据转换
3.构建和浏览数据集
数据集是共享相同兴趣并彼此有关系的数据模型的集合。
您可以通过混合不同数据模型的维度和度量来探索数据集。Holistics 的引擎将基于这些组合来生成针对您的数据仓库运行的 SQL。
3.1 创建数据集
在这里,我通过组合comments
和movies
数据模型来创建数据集。这两个模型中的所有字段和度量值都将在数据集中可用,并且由于我前面设置的关系,它们可以被组合在一起。
数据集创建
3.2 探索数据集
创建数据集后,您可以开始在熟悉的拖放界面中组合维度和度量,并选择适当的可视化。
在这个例子中,我将通过组合movies.title
、movies.imdb_rating
、count(comments.id)
来创建一个“列出电影及其 IMDB 评分和评论数”的表格
按评论数、IMDB 评分的电影
只需点击几下鼠标,就能看到按年发行的全部电影的图表:
历年电影
4.使用过滤器构建交互式仪表板
最后,您可以创建一个仪表板,将您的所有探索收集为图表和表格,您可以随时查看或与您的团队共享。
创建仪表板
添加一些过滤器
如果没有任何过滤器,仪表板有什么用?
只需点击添加过滤器图标,并从五种类型的过滤器(字段、日期、文本、数字、真/假)中进行选择,以过滤您的数据。欲了解更多信息,请访问我们关于 Holistics 的过滤器的文档。
例如,我从字段movies_dataset.movies.released_year
创建一个过滤器,并将其映射到两个小部件的movies.released_year
字段。
当查看者更改released_year
时,过滤条件将应用于两个映射的小部件并更改它们的值。
添加过滤器
5.将您的仪表板交付给 Slack
最后,每天将您的新仪表板安排到您的邮箱或 Slack,这样每个人都可以随时了解最新的数据变化,并在内部讨论中方便地使用数据。
点击仪表板上的计划图标,选择新的松弛计划。您可以在此选择发布仪表板的渠道,安排发布时间和覆盖默认过滤值。
设置时差计划
Tada,每天早上 7:00,你的 Slack 频道都会收到一个新的仪表盘,如下图所示
宽松计划
结论
我希望这份指南能够成为一份有趣的实践指南,帮助你学习如何从零开始构建自己的 MongoDB 分析基础。
当然,我们只是触及了表面。还有更有趣的事情要做,比如合并来自其他来源的数据,使用 SQL 转换数据,优化查询性能…这些我将在其他帖子中讨论。
现在,让我们来看看如何在您的具体使用案例中应用本指南!如果您面临任何问题,请不要犹豫发表评论或联系我!
原载于 2020 年 3 月 19 日https://www . holistics . io。
感谢 Ha Pham 和 TDS 团队对帖子的审核。
构建您的第一个机器学习模型并开始您的数据科学职业生涯的指南
原文:https://towardsdatascience.com/a-guide-to-build-your-first-machine-learning-model-and-start-your-data-science-career-ef487f455c9?source=collection_archive---------38-----------------------
通过本教程开始您的数据科学生涯!
目录
- 简介
- 目标
- 第一步:完成 Kaggle 的机器学习课程
- 第二步:在 Kaggle 上找到一个数据集,重新创建你的随机森林模型
- 我的第一个机器学习模型
- 接下来的步骤
介绍
进入数据科学和机器学习很难…如果没有指导,就更难了。三年前,我在几门课程、书籍和资源之间跳来跳去,希望发展我对机器学习的理解。
我最初尝试了 Udacity 的机器学习课程,但发现对初学者来说太复杂了。然后我尝试了 Coursera 的机器学习课程,这是一门很棒的课程,可以学习每个模型背后的理论,但它不是用 Python 教授的。最后,我尝试了 Udemy 的机器学习 A-Z 课程,但发现我只是简单地复制他们的代码,并没有完全理解我在做什么。
直到后来,我才发现一个简单的资源加速了我的职业生涯。在本文中,我将帮助你通过简单的两步创建你自己的机器学习模型。
目标
通过阅读这篇文章,我希望能帮助你做到以下几点:
- 为您提供资源,帮助您理解和开发您的第一个机器学习模型。
- 给你大量的数据集来实验和建立模型。
- 帮助您开始数据科学之旅!
如果你在这个过程中的任何地方卡住了,请前往关于 我的第一个机器学习模型 的部分,看看我做了什么,或者随时在Linkedin上联系我!
第一步:完成 Kaggle 关于机器学习的课程
Kaggle 的机器学习课程截图
就我个人而言,我发现 Kaggle 的机器学习入门课程是入门的最佳资源,原因是它非常基础——它实际上为你提供了构建第一个机器学习模型的最低要求。你可能会认为这是一件坏事,但作为一个初学者,有几个原因可以说明这是件好事:
- 当你面对更少的信息时,就更容易理解所有事物是如何联系在一起的。迈出许多小步就能赢得大步。
- 自信地建立你的第一个机器学习模型会给你动力去更深入地学习。类似于第一点,除了大胆的大目标之外,设定许多可以实现的小目标。
在学习本课程时,请记住以下几点:
- 专注于理解代码片段。稍后您将重用这些代码,因此如果您了解每段代码背后的基本原理,这将对您最有利。不要担心记住代码——把它作为一种资源来引用并没有错。
- 不要强调它只涵盖了决策树和随机森林模型。稍后你会发现,你只需要修改几行代码就可以改变你的机器学习模型,所以不要担心。
一旦完成这个,你就可以进入第二步,制作你自己的机器学习模型:
第二步:在 Kaggle 上找到一个数据集,重新创建你的随机森林模型
Kaggle 提供的不仅仅是在线课程,它有数以千计的数据集,你可以用来探索和创建模型。下面是完成你自己的第一个模型所需的步骤。
首先,去 Kaggle 的数据集列表这里,选择一个你感兴趣的。想想你想预测什么变量。你想预测寿命吗?房地产价格?出租车使用情况?世界是你的。
然后点击“新建笔记本”。在这里,您将复制从 Kaggle 的入门课程中学到的代码。
一旦你有了新的笔记本,剩下的就简单了。简单地复制你在 Kaggle 的机器学习入门课程中学习的代码。那么你只需要改变几件事:
- 更改的 csv 文件。read_csv() 正在读取您选择的数据集。
- 将预测变量 y 更改为您希望在所选数据集中预测的变量。
- 更改用于预测 y 变量的特征(x 变量)。
就是这样!你已经用自己选择的数据集创建了自己的机器学习模型。现在看起来可能不多,但是再过几个月,当你开始数据科学之旅时,你会回过头来看看你已经取得了多大的进步。
我的第一个机器学习模型
对于我的第一个算法,我想创造一些我认为会与我以后的生活相关的东西。我决定使用 Kaggle 的“二手车数据集”,它有超过 60 万辆二手车列表。我创建的算法旨在根据一些特征来预测二手车的价格,包括制造年份,制造商,里程表(公里数),等等。
在这里你可以看到我是如何编写我的第一个模型的,你可以看到它并不多,但是七周之后,我能够通过更多的步骤来显著地改进它(在这里看到我改进的模型)。
后续步骤
你可以学习很多东西来改进你的模型——如果你不知道下一步该怎么做,可以从下面的文章开始:
- 6 分钟内解释所有机器学习模型:这将帮助您了解数据科学领域中最常用的一些机器学习模型。
- [完整的熊猫数据科学术语表](http://A Complete Pandas Glossary for Data Science):如果你想提高你的编程能力,可以参考这个。发展强大的基本面将会在以后的道路上帮助你十倍。
- 探索性数据分析的详尽逐步指南:探索数据对于你使用的每个数据集都是必不可少的。通读这篇文章,了解什么是 EDA 以及如何进行 EDA。
- 如何用 Python 代码评价你的机器学习模型!:创建你的机器学习模型是一回事。创造一个好的机器学习模型是另一个例子。这篇文章教你如何评估你是否建立了一个好的机器学习模型。
感谢阅读!
如果你喜欢我的工作,想支持我…
- 支持我的最好方式就是在媒体上这里关注我。
- 在 Twitter 这里成为第一批关注我的人之一。我会在这里发布很多更新和有趣的东西!
- 此外,成为第一批订阅我的新 YouTube 频道 这里!
- 在 LinkedIn 这里关注我。
- 在我的邮箱列表 这里注册。
- 查看我的网站,terenceshin.com。
使用 Dialogflow 和 FireBase 构建 WhatsApp 聊天机器人指南
原文:https://towardsdatascience.com/a-guide-to-building-whatsapp-chatbots-using-dialogflow-and-firebase-4ff5e904ac3?source=collection_archive---------9-----------------------
一步一步的教程,为你的企业创建智能聊天机器人,并让他们与你的后端互动
由丹尼尔·科尔派在 Unsplash 上拍摄
聊天机器人是对话代理,能够与互联网用户进行对话的程序。在本教程中,我将带领你使用 Twilio 平台实现 WhatsApp 聊天机器人。
除了静态聊天机器人,我们还将受益于谷歌 Dialogflow 的强大功能,创造出能够理解人类语言的智能机器人。
1.WhatsApp 聊天机器人
WhatsApp 是世界上许多地方最受欢迎的 OTT 应用。有了 WhatsApp 聊天机器人,你可以在客户使用的平台上为他们提供支持,并立即回答他们的问题。
使用 Twilio、Flask 和 Heroku ,以及许多其他高级平台,如 DialogFlow ,我们可以构建令人惊叹的聊天机器人,正如我们将在本教程中所做的那样。
特维利奥
Twilio 是一家云通信平台即服务(CPaaS)公司,它允许软件开发人员以编程方式拨打和接听电话、发送和接收文本消息,以及使用其 web 服务 API 执行其他通信功能。
有了 WhatsApp 的 Twilio API,你可以发送通知,进行双向对话,或者构建聊天机器人。
免费,无需等待你的 Twilio 号码被 WhatsApp 批准,Twilio Sandbox for WhatsApp 使你能够立即创建你的聊天机器人,就像我们在这个项目中将要看到的那样。
1.创建一个 Twilio 账户
2.创建一个新项目
3.在项目控制台上,打开可编程 SMS 仪表板
4.选择 WhatsApp 测试版
作者图片
当你激活你的沙箱时,你会看到与之相关的电话号码(这里是+1 415 …)以及它的名字(这里是普通音节)
使用 Flask 创建应用程序
1.创建新的 Python 虚拟环境:
- 在新文件夹中打开终端并执行:
python -m venv myvenv
2.激活您的虚拟环境:
- 视窗:
myvenv\Scripts\activate
- Linux :
source myvenv/bin/activate
3.安装这两个 Python 包:
- Twilio :
pip install twilio
- 烧瓶 :
pip install flask
Flask 是一个用 Python 编写的微型 web 框架。这意味着 flask 为你提供了工具、库和技术,让你可以构建一个网络应用。
4.创建烧瓶应用程序:
在你的文件夹中,创建一个名为 app.py 的文件,然后复制&粘贴下面的代码:
from flask import Flask, request
from twilio.twiml.messaging_response import MessagingResponseapp = Flask(__name__)@app.route("/")
def hello():
return "Hello, World!"@app.route("/sms", methods=['POST'])
def sms_reply():
"""Respond to incoming calls with a simple text message."""
# Fetch the message
msg = request.form.get('Body') # Create reply
resp = MessagingResponse()
resp.message("You said: {}".format(msg)) return str(resp)if __name__ == "__main__":
app.run(debug=True)
这是一个基本的 flask web 应用程序,它使我们能够在/ route 中获取Hello, world!
,如果我们将消息发布到 /sms route,就可以得到我们的消息,正如我们在以下步骤中看到的
5.运行 app : python app.py
作者图片
您的应用程序现在正在运行。
你可以在浏览器中输入http://127.0.0.1:5000/
来检查。(你会得到Hello, world!
)
然而,远程机器不可能访问你的应用,因此需要 Ngrok
使用 Ngrok 获取应用程序的公共地址
Ngrok 将使我们能够为本地运行的应用程序提供一个公共的 URL。
1.下载 Ngrok 并解压
2.通过执行:./ngrok http 5000
从命令行运行它
3.现在,您可以使用提供的 URL(类似于[https://******.ngrok.io](/******.ngrok.io))
)) )从远程机器访问本地运行的应用程序
4.返回 Twilio sandbox 并将其粘贴为接收邮件的 URL:
作者图片
5.你现在可以在手机中打开 WhatsApp,添加你在之前步骤中从 Twilio 获得的号码(+1 415 …),并通过他们告诉你的代码开始对话(在这里加入常规音节)
6.你现在可以发送任何你想要的 WhatsApp 信息,机器人会通过发送回相同的信息来回复。这是一种鹦鹉机器人😃
然而,我们仍然有一个主要的问题,你的机器应该一直运行,以允许应用程序响应用户的请求。
2.使用 Heroku 摆脱你的机器
多亏了 Heroku,我们将能够在云中部署我们的应用程序,以及它有效运行所需的所有需求。因此,我们的机器将受益于关机的奢侈。为此,我们需要:
1.在我们的虚拟环境中,安装 gunicorn: pip install gunicorn
2.在您的文件夹中创建这些文件:
- Procfile :然后将该内容保存在其中
web gunicorn app:app
- runtime.txt :然后把这个内容保存在里面
python-3.7.2
- requirements . txt:你可以简单的输入
pip freeze > requirements.txt
来填充你的 app 需要的所有第三方库。 - 。gitignore :然后把这个内容保存在里面
myvenv/
*.pyc
3.下载并安装Git;然后在您的虚拟环境中:
- 在您的项目文件夹中初始化一个新的 git 存储库:
git init
- 将所有未跟踪的文件添加到 git 库:
git add .
- 将更改提交到 git 存储库:
git commit -m "first commit"
4.如果你还没有一个新的 Heroku 帐号,请创建一个。然后下载 Heroku 命令行界面(CLI) ,直接从终端轻松创建和管理您的 Heroku 应用程序。
5.使用heroku login
从您的虚拟环境连接到您的 Heroku 帐户,然后您将被转到浏览器中基于 web 的界面以完成身份验证阶段。
6.创建一个新的 Heroku 应用程序heroku create <app-name>
7.通过将您的本地 git 存储库推送到远程 Heroku 应用程序的 git 存储库来部署您的应用程序:git push heroku master
最后,当部署完成时,您将在终端中看到您可以访问应用程序的地址。-类似于https://<app-name>.herokuapp.com/sms
-复制它,回到你的沙箱,用新的HerokuURL 替换 Ngrok URL。
作者图片
恭喜你,你的鹦鹉 WhatsApp 机器人现在全天候运行,它不再需要你的机器的帮助了😃你可以关掉它。
3.更新您的代码
比方说,你明天想出另一个主意,而不是你做的这个鹦鹉机器人,你需要做的就是修改你的代码(在文件 app.py 中)。如果项目很复杂,您还可以添加更多文件)然后:
# connect to your virtual environment
<virtual_environment_name>\Scripts\activate #Windows
source <virtual_environment_name>/bin/activate #Linux# connect to your heroku account
heroku login# prepare all the modified files and push them to Heroku
git add .
git commit -m "first change"
git push heroku master
⚠️:如果你在你的虚拟环境中安装了新的软件包,你必须通过更新文件 requirements.txt 来告诉 Heroku:只需在git add .
前输入pip freeze > requirements.txt
就可以了。
4.用你自己的号码
如果你想创建一个真正的商业 WhatsApp 机器人,我之前介绍的方法有两个缺点:
(1)为了使用这个机器人,你的客户必须用一个奇怪的信息开始对话😑(此处加入正则音节);
(2)机器人想出的是 Twilio 的 logo,而不是你的。
这是因为我们使用了 Twilio 沙盒,而提供给我们的号码不是我们的。然而,Twilio 为你提供了拥有一个号码的可能性,从而解决了上述问题。为此,您需要遵循以下步骤:
第一步:买一个 Twilio 号
作者图片
第二步:通过填写 Twilio 的“请求访问”表格来请求访问,以便在 WhatsApp 上启用您的 Twilio 号码(确保您事先有您的脸书业务经理 ID)
当您的请求获得批准后,Twilio 将通过电子邮件通知您提交您的发件人资料和 WhatsApp 消息模板的后续步骤,然后另一封电子邮件将向您展示如何批准 Twilio 代表您发送消息以及如何验证您的脸书业务经理账户。
所以,在发出请求后,确保你经常检查你的电子邮件,为接下来的步骤做准备。整个过程需要 2 到 3 周。
关于流程的更多信息
5.使用 DialogFlow 的高级聊天机器人
到目前为止,我们创造了一个聊天机器人,它有能力管理简单的对话和重复一个人说的话😅这不是很酷吗🙄。实际上,我们在前面的章节中关注的是让这个机器人在流行的聊天平台 WhatsApp 上工作。
事实上,我们没有使用我们的任何数据来训练或个性化机器人。在这一部分,我们将训练和微调我们的聊天机器人,并让它与后端交互。让我们以一个购物/送货店的案例研究为例。
设置 DialogFlow 代理
Dialogflow 代理是一个虚拟代理,它处理与最终用户的对话。它是一个自然语言理解模块,可以理解人类语言的细微差别。DialogFlow 的代理使用意图对每次对话的最终用户意图进行分类,使用实体从最终用户的表达中识别和提取特定数据(我们将使用它们将数据发送到后端)。
所以首先要做的是..登录 对话流程控制台 并创建一个新的代理..在左侧菜单中,您可以启用闲聊。基本上,你的机器人现在能够自动处理“嗨,你好,你好吗,再见……”之类的事情。试试看!(右侧有一个“立即尝试”部分)
当最终用户写或说一些话时,Dialogflow 会将最终用户的表达与您的代理中的最佳意图进行匹配。为了做到这一点,您的代理必须接受一些培训短语(最终用户可能会说的示例短语)的培训。当最终用户表达式类似于这些短语之一时,Dialogflow 匹配意图。你不必定义每个可能的例子,因为 Dialogflow 的内置机器学习会在你的列表上扩展其他类似的短语。
- 在左侧菜单中,选择 Intent 并创建一个新的。
- 在“训练短语”部分,添加一些将触发这一意图的表达。当你添加它们时,你会看到一些实体被自动突出显示(如位置或日期时间等);如果需要,还可以添加自定义实体。
- 在 action and parameters 部分,您可以将一些实体标记为 required ,这样当意图被触发时,代理将总是请求它们。请注意,如果您将某个参数标记为必需,您必须在提示栏中添加代理将询问最终用户的问题。
此外,您必须有可能添加一个默认答案下的反应部分或让后端生成自定义答案。
数据库
我们将使用谷歌的 Firebase 实时数据库,这是一个云托管的 NoSQL 数据库,允许您使用 JSON 格式在您和您的用户之间实时存储和同步数据。
1-转到 Firebase 网站并添加一个新项目。
2-在左侧菜单中,选择数据库,然后在测试模式下选择实时数据库。
为了能够访问您的数据库,添加和删除数据,您必须拥有数据库凭证。
3-点击项目概述旁边的齿轮图标,然后选择项目设置。在 Firebase SDK 片段中,选择 config 并将凭证复制到您计算机中的一个单独文件中。
作者图片
4-在您的计算机/虚拟环境中,创建一个 app.py 文件并导入这些凭证,以及其他有用的库。
作者图片
5-将您的产品及其特征添加到实时数据库:
5.1.在单独的文件中,将身份验证配置为 Firebase:
import pyrebase #install pyrebase first using pip install
from firebaseconfig import config # firebase credentialsfirebase = pyrebase.initialize_app(config)
db = firebase.database()
5.2.以 JSON 格式准备您的产品,并使用以下命令将它们添加到 DB 中:
prod1 = {
"ID":"0",
"order":"0",
"number": 10,
"color": "black",
"size":"S",
"address":"-",
"date":"-"
}# add a product
db.child("products").push({"shirt":prod1})# update a product
db.child("products").update({"shirt":prod2}) #define prod2 before# remove the whole chain of products
db.child("products").remove()
您可以(实时)检查您的数据库的 web 界面,以查看您正在进行的更新。
检查我们的库存中是否有产品
在 usefulfunction.py 文件中,我们定义了我们将在实现中使用的函数,其中有 is_available() 函数,它检查给定的产品是否存在于实时数据库中
作者图片
处理来自对话流的数据
用户订单的特征来自于一个 JSON 格式的 Dialogflow。下面的函数提取这些特征,并检查是否有满足这些要求的产品。
作者图片
您可能会注意到存在两个未定义的函数: all_fields() 函数只是检查最终用户是否填写了所有必需的字段,而 location_format() 函数将位置变量的格式调整为可读格式。
把它们放在一起
在您的文件 app.py 中,我们设置了 Flask API。
/ main 根显示的只是一个 hello world ..专业人士有标准;)
/check 路径是我们接收 POST 请求、从 Dialogflow 中提取数据、处理数据、在实时数据库中检查产品的可用性并总是使用 JSON 格式回复用户的地方。
现在,您可以在本地运行 app.py 并使用 Ngrok 来获取一个公共地址,或者像我们之前所做的那样将您的应用程序推送到 Heroku。
完成
在 Dialogflow 中,默认情况下,您的代理用静态响应来响应匹配的意图。为了使用动态答案,您必须启用履行选项。
返回到您的 Dialogflow 控制台,在左侧菜单中单击 fulfillment ,启用 webhook ,将 URL 更改为托管您的应用程序的 URL,并保存更改。
作者图片
当一个启用了实现功能的意向匹配时,Dialogflow 会向您的 webhook 服务(后端应用程序)发送一个请求,其中包含关于匹配意向的信息。
现在转到您之前创建的意向(在意向部分下),在该页面的底部您会看到一个履行部分,启用 webhook 调用意向和填充空位。
作者图片
恭喜..您的聊天机器人现在运行正常,请查看立即尝试部分。
结论
当最终用户开始与聊天机器人对话时,后者会尝试将传入的表情与其意图之一进行匹配。当它设法这样做时,它将尝试填充所有必需的实体,并且它将所有这些实体(在我们的例子中是产品的特征)发送到我们在实现部分中提到的链接。
在我们的 Flask web 应用程序收到这些特征后,它会验证数据库中是否有所请求的产品,如果有,它会在 Firebase RT DB 中添加命令。然后,向最终用户发送适当的响应。
你可以按照上面提到的步骤在 WhatsApp 上使用这个聊天机器人,就像你可以使用 DialogFlow 的集成选项将其与 Facebook Messenger、Slack、你自己的网站和许多其他平台集成一样。
仅用 8 行代码构建第一个回归模型的指南
原文:https://towardsdatascience.com/a-guide-to-building-your-first-regression-model-in-just-8-lines-of-code-2d1a2a755811?source=collection_archive---------34-----------------------
Scikit-Learn 如何提供一种快速简单的方法,让您涉足线性回归和建模领域。
在 Unsplash 上 NeONBRAND 拍摄的照片
数学建模和机器学习经常让人觉得是难以探索和学习的话题,尤其是对那些不熟悉计算机科学和数学领域的人来说。我惊讶地听到我的非 STEM 朋友说,他们在自己的项目中尝试使用基本的建模技术时感到不知所措,并且他们可能会被该领域的语义所困扰。这是一个遗憾,因为线性建模在很多情况下非常有帮助,而且有了互联网上的所有开源代码,实现自己的模型从未如此简单。因此,这里是我理解和实现 Python 中基本线性回归模型的简明指南。
内容:
- 什么是线性回归?
- 如何为线性回归准备数据?
- 执行线性回归。
- 解释结果:
- 最终想法和进一步阅读
什么是线性回归?
布雷特·乔丹在 Unsplash 上拍摄的照片
线性回归是一种数学建模形式,通常用于评估因变量(如体重)和自变量(如身高)之间的关系。我们的大脑自然会这样做,只是方式不太精确。如果我让你在一个 6 英尺 2 英寸的人和一个 5 英尺 2 英寸 T23 的人之间决定谁更重,你可能会选择 6 英尺 2 英寸 T25 的人。当然,身高 5 英尺 2 英寸的人可能会更重,但我敢打赌,在你与人交往的经历中,你已经在人的身高和体重之间建立了某种关系。线性回归只是建立这种关系并从中提取意义的一种精确的数学方法。
那么它是如何工作的呢?
线性回归的工作原理是创建一条最佳拟合线。最佳拟合线是最能捕捉 x 轴和 y 轴之间关系的线。例如,该关系可以是,随着“X”增加,“Y”也增加:
随着 X 的增加,y 也增加。
或者,这种关系可以是随着“X”增加,“Y”减少。
随着 X 的增加,Y 减少。图片作者。
在上面的例子中,确定趋势的大致方向是相当容易的,然而,根据数据的不同,它可能会变得复杂得多。此外,线条的精确细节很难手工计算。在许多情况下,拥有直线的精确方程会非常有帮助,使我们能够理解两个变量之间的关系,并根据一个变量的值来推测另一个变量的值。
如何为线性回归准备数据:
为了有效地进行线性回归,你至少需要两样东西:一个你认为可能是因变量的变量,比如一个 NBA 球员的体重(公斤),一个你认为可能影响因变量的变量,比如一个 NBA 球员的身高(厘米)。
熊猫数据框架,包含与 NBA 球员相关的各种数据点,包括身高和体重。图片作者。
如果这两个变量都是连续的,线性回归效果最好。我所说的连续是指两个值之间有连续性。有人可能体重 151 磅或 152 磅或 151.5 磅或 151.72 磅,等等。这不同于离散或分类变量,如电影星级或教室中给出的等级。还有其他技术来处理这些类型的数据,但是我们现在将重点放在线性回归上。
身高和体重是连续变量的两个完美例子,主要用于建立两者之间的线性关系。如果您正在使用 Python,请确保您的两个连续变量都处于浮点形式,这将有助于后面的步骤。
如果你有兴趣用一个已经清理过的数据集来试试这个,你可以跟着我正在使用的 NBA 数据集,它在这里。
为了加载数据,我推荐 python 的熊猫包:
import pandas as pd #Load the Pandas packagedf = pd.read_csv("archive/all_seasons.csv") #Read the NBA file
df.head() #Display the NBA file's data
输出应该如上表所示。
执行线性回归:
现在我们已经加载了数据,让我们来看看 NBA 球员的体重和身高之间的关系:
df.plot.scatter("player_height","player_weight", figsize=(15,10))
NBA 球员身高(x 轴)与体重(y 轴)的散点图。图片作者。
除了少数异常值,我们已经可以看到球员的身高和体重之间存在直接的相关性。正如我们上面解释的,线性回归就像从图的左边到图的右边画一条最符合数据关系的线。对于我们的 NBA 示例,我们可以猜测最佳拟合线将从 60kg 标记附近的某个地方开始,并朝向图的右上角。问题是,我们人类远没有精确到足以画出完美捕捉数据趋势的线。相反,让我们使用一个工具。
Scikit-Learn,或 SKLearn,是一个带有各种机器学习工具的 python 包,包括一个以简单有效的方式构建线性回归模型的工具。为了使用 SKLearn,我们需要从熊猫数据框架中分离出两个变量:
from sklearn import linear_model#By calling to_numpy() we convert the series into a numpy array#We then reshape the numpy array into a format parsable for sklearn
X = df["player_height"].to_numpy().reshape(-1, 1)
y = df["player_weight"].to_numpy().reshape(-1, 1)
我们的数据现在是 NumPy 数组格式。图片作者。
如您所见,“X”数组包含所有的身高,“y”数组包含所有的体重。现在我们可以拟合模型了。在这种情况下,拟合模型意味着我们将数据呈现给函数,并允许 SKLearn 找到最能捕捉“X”和“y”之间关系的线。
#First we call the linear regression function from SKLearn linear_model
#Then using this object we fit the data to a linear model.lm = linear_model.LinearRegression()
model = lm.fit(X,y)
现在模型已经拟合好了,让我们看看它得出了什么结论。
解读结果:
国立癌症研究所在 Unsplash 上拍摄的照片
随着我们的模型拟合,是时候让我们看看它从我们提供的数据中建立了什么。首先,让我们看看它为数据评估的参数:
print(model.coef_) #prints the slope of the line[1]: [[1.13557995]]print(model.intercept_) #prints the intercept of the line[2]: [-127.40114263]
对于那些熟悉数学的人来说,你可能记得直线斜率的等式, y = mx + b 。在这种情况下,“b”是截距,可以认为是直线与 y 轴相交的地方,“m”是直线的斜率。因此,对于我们拟合的线性回归模型,方程大致为 y = 1.13x -127.4。这意味着,“x”每增加一个数字,“y”就增加 1.13,或者更确切地说,球员每高厘米,他的体重就增加 1.13 公斤。从视觉上看,如果我们在玩家身高和体重的散点图上绘制这条线,我们会得到:
import numpy as np #numpy can be used for creating a lsit of numbersX = np.arange(150,250) # create a list of example values#plot
df.plot.scatter("player_height","player_weight", figsize=(15,10)).plot(X, model.predict(X.reshape(-1,1)),color='k')
NBA 球员身高(x 轴)与体重(y 轴)的散点图,这次包括由我们的线性回归模型创建的最佳拟合线。图片作者。
在这种情况下,黑线是我们根据数据拟合的线。基于这条线,我们可以推测一个身高 180 cm 的球员体重大约在 70 kg 左右。但是,使用 SKLearn 和我们创建的模型,我们可以对此进行估计:
model.predict(np.array(180).reshape(**-**1,1))
[3]: array([[77.00324856]])
因此,一个身高 180 厘米的运动员应该大约重 77 公斤。
现在模型已经训练好了,你可以在任何值上尝试。这是我在 NBA 的体重:
model.predict(np.array(188).reshape(**-**1,1))[4]: array([[86.08788817]])
最后的想法
虽然这只是一个微不足道的例子,但是线性回归对于许多任务和项目来说是非常有用的,因此应该尽可能地为每个人所用。我的这个项目的完整代码可以在下面找到,我鼓励你自己尝试一下。此外,如果你想了解更多,我在下面提供了一些额外的阅读材料。
import pandas as pd
from sklearn import linear_modeldf = pd.read_csv("archive/all_seasons.csv")
X = df["player_height"].to_numpy().reshape(-1, 1)
y = df["player_weight"].to_numpy().reshape(-1, 1)lm = linear_model.LinearRegression()
model = lm.fit(X,y)
model.predict(np.array(188).reshape(**-**1,1))
哇!只有 8 行代码。
进一步阅读
- 耶鲁的课程页面更深入一点:【http://www.stat.yale.edu/Courses/1997-98/101/linreg.htm
- 一个很棒的解释的 Youtube 视频:
https://www.youtube.com/watch?v=zPG4NjIkCjc&ab _ channel = statistics fun
特别感谢Justinas Cirtautas提供数据集。
所有使用的图片要么是我自己创作的,要么是经作者明确许可使用的。每个图片下都有作者资料的链接。
选择正确的数据科学职位指南
原文:https://towardsdatascience.com/a-guide-to-choosing-the-right-data-science-position-79d0038fb9c4?source=collection_archive---------36-----------------------
来自世界各地的真实数据科学家的例子
科琳·库兹在 Unsplash 上的照片
我在我的播客中采访了来自世界各地的人,所以你想成为一名数据科学家?。我的客人来自非常不同的职位,他们都有数据科学家或类似的头衔。受到播客上我从我的客人那里听到的一切的启发,我准备了一份可能的职位清单,你可以在规划你的未来时考虑一下。
为了从工作中获得最大的满足感,知道你想在哪个部门工作是很重要的。我知道,当你在某个领域几乎没有经验时,这并不容易做到。在数据科学领域,你可以从事多种不同类型的工作。他们都有不同的职责,不同的职业和忙碌。但是如果你不在你喜欢的位置上,你可能会不开心。
刚开始的时候没想这么多。对我来说,这是一种试错法。我从一家大公司的顾问做起,却发现那不适合我。后来,我意识到内部职位更适合我。这就是为什么我要改变,下周我将在新的岗位上开始工作。我很高兴也很兴奋地体验到成为一名内部数据科学家将如何适合我。
如果你不想像我一样花几年时间去尝试和犯错,这里有一个数据科学家常见职位类型的列表。你可以在标题下面找到我采访那个职位的客人的那一集的链接。
顾问数据科学家
与马德莉·基维西克 讨论数据科学
典型职责:成为顾问意味着你将与雇主的客户一起工作。你的任务是客户公司的项目。你将在团队中或单独在不同的地点/团队中从事数据科学工作。
除了技术数据科学任务之外,顾问还有一些典型的职责。这些主要是,帮助提出项目的业务范围,与客户沟通你在做什么以及为什么它很重要,定期与业务人员交谈以更新他们。这是一个非常重“软技能”的职位。
项目:项目由咨询公司的销售人员开始,他们四处游说客户。你可以得到任何种类的项目。我的意思是,他们可以从事任何行业。想想能源行业、酒店、银行、金融、旅游。当然,行业会取决于你的主雇主服务于哪些公司。拥有所有的选择听起来很有趣,但是也有可能对于你喜欢做的每一个项目,你可能会被分配到几个你不喜欢的项目。
项目也可以是任何级别的。即使你想在 NLP 上工作,你也可能一次花几个月的时间来制作仪表板。所以,如果你不想失望的话,在你开始在一家公司工作之前,确保你了解这家公司做什么类型的项目。
职业发展:咨询师既有商业技能也有技术技能。所以你可以选择成长为一个管理角色或者更技术性的角色。
工作时间和压力:咨询行业的工作时间会变得很有挑战性。你不是直接为你的雇主工作,而是一个客户,咨询公司希望在他们的客户面前表现良好。这意味着当截止日期到来时,你可能会受到雇主的额外压力。
在内部职位上可能是软截止日期的事情,在咨询环境中可能会变成硬截止日期,因为你的公司承诺客户在某个时间交付。这可能会造成一个高压力的环境。但是,一些公司在管理这种压力方面做得很好。尽管我得到的印象是,长时间工作和承受压力是咨询师的“期望”。
各种行业的项目,大多收入不错,你可以学习商业方面的东西,积极运用你的软技能
坏处——你可能会被你不喜欢的项目类型困住,工作时间可能会比平均时间长,与客户一起工作的压力
内部数据科学家
成为一名 ML 工程师,与 Jigyasa Grover 一起在 Twitter 工作
****典型职责:作为一名内部数据科学家,你只对公司内部发生的事情感兴趣。你可能会在一个由数据科学家和机器学习工程师组成的团队中。项目会从公司内部的其他团队来到你这里。你可能会在同一个办公室里(如果我们再次回到办公室的话),那将是你的主要工作地点。除了从事新项目,你还负责维护你已经交付的项目。
****项目:项目由公司的其他团队发起,他们带着请求来到您的团队,您的团队提出了新功能的想法或对当前使用的系统进行更新的需求。
****工作时间和压力:视公司而定。如果公司处于一个高节奏、高压力的行业,比如金融/投资银行,你可能会工作很长时间,并承受压力。尽管许多公司都格外注意不要让员工承受不必要的压力。在你开始某个地方之前,确保你知道你报名参加的是什么。
****职业发展:对于内部数据科学家来说,一条显而易见的职业道路是成为特定公司的团队领导、经理甚至首席技术官。职业道路主要在技术方面。
优点——在同一个团队工作,有很多机会提升自己,尤其是如果你的同事经验丰富的话
你所有的项目都在同一个行业(如果你喜欢在那个行业工作,这可能是一个专家),除了开发新项目,你还需要花一部分时间维护可能会变得乏味的旧项目
自由数据科学家
自由职业者,与 Katia Stambolieva 一起创办自己的公司
****典型职责:作为一名自由职业的数据科学家,最棒的一点是你的职责是你想让他们做什么就做什么。你可以选择为你想要的行业和级别的项目工作。主要是你和你的客户一起开发项目,做技术工作,展示成果。根据你和客户达成的共识,你可能做得更多或更少。
项目:项目发生在你寻找客户和提供服务的时候。你可以在网上找到客户,接触你的网络,或者跟踪你知道可以使用一些数据科学支持的人/公司。一个经验丰富的自由职业数据科学家很可能会有一个他/她经常打交道的客户。
工作时间和压力:作为一名自由数据科学家,你可以决定工作多少。这听起来像一个梦想,但当然,这是有代价的。工作越少,赚钱越少。尤其是如果你刚刚起步,寻找项目和客户可能是压力的来源。
职业发展:在作为自由职业者获得成功后,你可以选择加入一家公司,成为一名数据科学家。或者你可以决定成为一名珠宝设计师,或者其他什么。你有选择自己道路的自由。玩笑归玩笑,你可以通过成为某个行业或技术的专家来发展你的职业生涯。(例如深度学习、对话项目专家、NLP、图像识别等。)这样,当客户在这些特定领域需要帮助时,他们就会知道来找你。
****优点——随时随地工作,选择你想合作的客户/项目
缺点——寻找客户的压力,按时交付给客户的压力,你需要在自己的小企业中成为数据科学家、会计、销售人员、网络开发人员和其他许多人
研究员数据科学家
与 Sakshi Mishra 一起研究数据科学
典型职责:在我参加播客的所有人中,我认为研究人员目前做得最好。但是当然,要达到他们现在的位置并不容易。研究人员主要朝着一个研究目标工作,他们交付工作原型和/或关于他们所做工作的论文。他们从事有趣的项目,研究新的想法,并试图推动当今的技术。
项目:你可以提出自己的研究项目,或者加入正在进行的更大的项目。当然,为了做你自己的项目,你需要资金,这意味着你需要让别人相信这个项目的价值。
工作时间和压力:据我所知,研究人员确实有一些工作压力。当你在构思一个新颖的想法时,毕竟会有很多不确定性。你不知道这个项目是否会成功,也不知道你投入的工作是否会在现实生活中使用。但是除此之外,工作时间和工作环境都很轻松。
****职业发展:如果你在一家学术机构担任研究员,你可以选择学术发展或加入该行业。如果你已经在工业界或独立的研究实验室工作,你可以进一步承担更多的责任。
****优点——非常有趣的工作,从事激情项目的可能性
对于那些希望看到自己的工作立即应用到现实生活中的人来说,这可能并不令人满意
自由数据科学家
与 Yaakov Bressler 一起成为一名自由数据科学家
****典型职责:一个自由数据科学家的职责并不多。这不是一个正式的职位,而是你可以用你的数据科学技能做的事情。一个免费的数据科学家将会为开源项目做贡献,他/她自己或者和一些朋友一起开始项目,尝试新事物,凭空创造新项目。如果不用急着为钱发愁的话,这样工作是很好玩的。它会让你获得很多经验。如果你想要的话,让公司更容易相信你的技能,因为你将来想被雇佣。
****项目:无论你想做什么。
****工作时间和压力:还是那句话,你想干多干少都可以。
职业发展:在为开源项目做出贡献并创建了几个你的项目后,公司可能已经向你发出邀请了。你也可以开始做一名自由职业的数据科学家。
****优点——你有无限的自由去做你自己的项目,随心所欲地支配你的时间,展示你的能力和技能的绝佳经历
缺点——用这种方式很难赚钱
没有数据科学家头衔但积极使用数据科学的职位
通过 Shivali Goel 在 Adobe 以一种意想不到的方式使用数据科学和生活
****典型职责:这是一个比较笼统的伞形岗位。这可以是从市场营销到产品开发到客户关系的任何事情。有时候,有些职位上的人没有数据科学家的头衔,但他们的主要工具是 ML 和数据分析,他们实际上是在做数据科学。我见过人们采取这样的立场,当他们意识到他们的热情在于工作,而不是数据科学,数据科学最终只是一个工具。
如果你想在以后的生活中成为一名数据科学家,这样的职位在经验方面是一个很好的敲门砖,如果你真的想成为一名数据科学家,在理解方面也是如此。
👉对数据科学领域以及如何开始学习感到困惑? 免费参加数据科学入门迷你课程 !
协作主题建模推荐系统指南
原文:https://towardsdatascience.com/a-guide-to-collaborative-topic-modeling-recommender-systems-49fd576cc871?source=collection_archive---------13-----------------------
具有矩阵外预测能力的推荐系统的理论与实现。
马库斯·斯皮斯克在 Unsplash 上的照片
推荐系统是一大类机器学习模型,其目的是预测用户 u 会给一个项目 i 的未观察到的评级。
在本指南中,我们将讨论由 Wang 和 Blei(2011)【3】介绍的协作主题建模/回归(CTM/CTR) ,这是一个基于文本的项目推荐系统,具有增强的准确性和矩阵外预测能力。我们还将为那些不关心模型背后的数学细节的人提供 Python3 实现。
CTM 建立在两个众所周知的模型上,即概率矩阵分解(PMF) [1]和潜在狄利克雷分配(LDA) [2],因此需要对上述模型有初步的了解。对于那些不熟悉它们的人来说,网上有很多非常好的指南,其中包括:
- 潜在的狄利克雷分配,作者 Thushan Gangedara
- 概率矩阵分解,作者 Benjamin Draves
为什么要合作主题建模
概率矩阵分解(PMF)是一种非常简单而强大的方法,当我们唯一可用的数据是一个 (U X I) 稀疏评级矩阵时,它允许我们推断项目和用户潜在的特征。
不幸的是,这种方法的简单性也导致了它的消亡,因为 PMF 无法对新的、完全未评级的项目进行归纳:因为没有对项目 j 进行评级,所以该模型无法导出其潜在的质量向量。用技术术语来说,我们说 PMF 无法进行矩阵外预测。
在未评级的项目因为没有评级而没有得到推荐,并且因为没有得到推荐而一直没有评级的情况下,这个问题特别麻烦。这种情况的一个例子是科学出版物领域,在这一领域,不太知名的作者的新论文尽管质量很好,却无法到达潜在感兴趣的读者手中。
直觉
CTM 背后的核心思想是我们可以将文档 i、Qᵢ 的潜在质量向量表示为:
其中 θᵢ 是从传统 LDA 估计中获得的项目 i 的主题比例的(k×1)向量, εᵢ 是调整主题比例的(k×1)偏移向量。偏移向量的基本原理是,它通过结合来自观察到的评级的信息来调整主题比例。
举个例子:假设你有两篇科学论文,而且都是 50%关于“机器学习”,50%关于“生物学”。现在,根据观察到的评级,可能第一篇论文对机器学习研究人员更有吸引力,而第二篇论文对生物学研究人员更有吸引力。使用偏移向量εᵢ,我们能够校准主题比例,以反映不同主题对不同个人的吸引力。
模型
就像它赖以建立的 PMF 和 LDA 一样,CTM 也有自己的生成过程:
概率矩阵分解的生成过程。注意,步骤 1.1、3.1 与 PMF 相同,步骤 2.1、2.3 与 LDA 相同。唯一建模不同的是步骤 2.2。
其中 σ _P 和 σ _Q 表示我们对 P 和 Q 中的向量元素的分布先验地施加的方差。类似地, σ 表示我们对评级分布先验地施加的方差。对于那些不熟悉贝叶斯统计的人来说,这些值可以简单地视为我们模型的正则化超参数。
通过使用平板符号表示生成过程,我们可以清楚地看到,CTM 只不过是 LDA 模型在 PMF 模型之上的堆叠版本,其中主题比例向量θᵢ被用作 Qᵢ 的生成分布的平均值。
学习参数
在推荐系统设置中,我们感兴趣的是获得对所有潜在变量的估计,这些变量有助于确定评级 rᵤᵢ.因此,我们会对 θᵢ 、 Qᵢ 、、和 Pᵤ.感兴趣 由于完全后验概率 P(θ,Q,P) 在分析上是难以处理的,我们借助于最大似然估计,其中我们数据的似然定义为:
像在大多数 MLE 场景中一样,使用对数似然法很方便:
单独导出四个分量中的每一个是很方便的。
第一部分:
第二部分:
第三十部:
为方便起见,假设α=1,上述分布变为:
第四部分:
我们的对数可能性将是:
本文最初采用的策略是使用坐标上升,在优化【P,Q】和 θ之间迭代交替。但正如同一作者指出的,使用通过标准 LDA 估计获得的对 θ 的估计,然后仅对 [P,Q] 进行优化,给出了可比较的结果,并在训练期间节省了大量时间。因此,我们将假设我们已经从 vanilla LDA 获得了我们的 θ 估计,并且我们将通过梯度上升来优化 [P,Q】。很容易得出我们的对数似然相对于【P,Q】的梯度:
上面的公式是本节的主要结果,我们将在下面的 Python3 中实现它。
代码实现
在本节中,我们将为 Steam 游戏创建一个推荐系统。我们将使用两个数据集:
- Steam 200k ,包含关于超过 200k 用户-游戏交互的每个游戏游戏时间的信息;
- Steam games 完整数据集,包含超过 40k 款不同 Steam 游戏的各种信息,包括标题和描述
注:此处报告的代码并不详尽,应作为参考。您可以在此访问包含所有代码的完整功能笔记本。
预处理
首先,我们从打开 Steam games 完整数据集开始,只保留每个游戏的名称和描述。我们也放弃那些没有文字描述的游戏。
games = pd.read_csv("steam_games.csv")# keep only the columns of interest
games = games.loc[:, ["name", "game_description"]]# Drop NaN game descriptions and names
games = games[~games.game_description.isna()]
games = games[~games.name.isna()]# Drop the introductory " About This Game " text
games.game_description = games.game_description.apply(lambda x: x.replace(" About This Game ", ""))# drop single-space descriptions
games = games[games.game_description != " "]games.head(5)
然后,我们打开 Steam 200k 数据集。我们将尝试预测的评分变量是以小时计的总播放时间,它将被调整到 0 到 1 之间。
ratings = pd.read_csv("steam-200k.csv", header = None)# drop last empty column
ratings.drop(4, axis = 1, inplace=True)# rename columns
ratings.columns = ["UserID", "Title", "Action", "Value"]# keep only "play" variables
ratings = ratings[ratings.Action != "purchase"]
# and drop the "Action" column, as now it is all "play"s
ratings.drop("Action", axis = 1, inplace = True)# to ease computations, constrain PlayTime to be between 0 and 1
pt = ratings.Value
pt_scaled = (pt - pt.min()) / (pt.max() - pt.min())
ratings.Value = pt_scaledratings.head(3)
在这一点上,我们需要找到既有稀疏的观察评分向量又有描述的游戏。我们小写所有标题,并删除特殊字符[!,.-"?:]以增加标题之间的兼容性。为了避免不匹配,我们也放弃了所有非唯一标题的游戏。我们以 1982 年的标题结束,我们有评级和描述。
我们现在转向通过组合我们预处理的两个数据集来创建 (U X I) 评级矩阵。
R = pd.pivot_table(data=ratings, values = ["Value"], index=["UserID"], columns=["Title"])# remove the level on top of game names called "Value"
R.columns = R.columns.droplevel()# remove leftover columns name from pivot operation
R.columns.name = ""# lastly, fill in the NaNs with 0's
R.fillna(0, inplace=True)R.head(3)
从这个矩阵中,我们给出了数据集中第 1105 款游戏“极品飞车卧底”的收视率向量。我们将用它来测试我们矩阵外预测能力的有效性。
到 1981 年,我们最终的收视率矩阵将为 10058 个用户,只有 0.23%的收视率被观察到。
基于 LDA 的主题建模
在训练我们的 CTM 模型之前,我们需要通过训练 LDA 模型来提取每个游戏描述中的主题及其比例。我们要做的第一件事是对游戏描述进行词汇化,以减少词汇中的差异并提高 LDA 估计。
nlp = spacy.load("en")# lemmatize game descriptions
games["lemmas"] = [[[token.lemma_ if token.lemma_ != "-PRON-" else token.text.lower() for token in sentence if token.pos_ in {"NOUN", "VERB", "ADJ", "ADV", "X"}] for sentence in nlp(speech).sents] for speech in games.game_description]
然后,我们训练我们的 LDA 模型,找出所有游戏描述中的 K =15 个主题,并确定每个主题在每个描述中出现的百分比。
## Train LDA model ##
ldacorpus = [dictionary.doc2bow(text) for text in instances]
tfidfmodel = TfidfModel(ldacorpus)
model_corpus = tfidfmodel[ldacorpus]num_topics = 15
num_passes = 30
chunk_size = len(model_corpus) * num_passes/200model = LdaMulticore(num_topics=num_topics,
corpus=model_corpus,
id2word=dictionary,
workers=multiprocessing.cpu_count()-1,
chunksize=chunk_size,
passes=num_passes,
alpha=0.1)
## ## ## obtain the matrix of topic proportions per document ##
all_topics = model.get_document_topics(model_corpus, per_word_topics=True, minimum_probability=0.0)corpus_topics = []for doc_topics, word_topics, phi_values in all_topics:
corpus_topics.append([topic[1] for topic in doc_topics])
corpus_topics = np.array(corpus_topics)theta = corpus_topics.copy().T
## #### remove the heldout game from the theta matrix ##
thet = pd.DataFrame(theta)
heldout_topics = thet.iloc[:, heldout_idx]
thet.drop(heldout_idx, axis = 1, inplace=True)
theta = thet.values
## ##
其中 theta 是 (K X I) 矩阵,它告诉我们 K =15 个主题中的每一个出现在每一个 I 游戏中的比例。
一旦我们有了评级矩阵和每项主题比例矩阵,我们就可以建立我们的 CTM 模型。
培训我们的 CTM 模型
我们首先将我们的评级矩阵分成 X_train 和 X_val。
# train - test splitdef train_test_split(ratings, percs = [0.8, 0.2]):
validation = np.zeros(ratings.shape)
train = ratings.copy()
for user in np.arange(ratings.shape[0]):
val_ratings = np.random.choice(ratings[user,:].nonzero()[0],
size = round(len(ratings[user,:].nonzero()[0]) * percs[1]),
replace=False
)
train[user, val_ratings] = 0
validation[user, val_ratings] = ratings[user, val_ratings]
return train, validationX_train, X_val = train_test_split(R.values)
我们还为我们的预测评级定义了一个 MSE 函数。
from sklearn.metrics import mean_squared_errordef mse(prediction, ground_truth):
prediction = prediction[ground_truth.nonzero()].flatten()
ground_truth = ground_truth[ground_truth.nonzero()].flatten()
return mean_squared_error(prediction, ground_truth)
最后,我们建立我们的 CTM 模型:
from tqdm import trange
import sysclass CTR():
"""
Collaborative Topic Regression Model as developed by Wang and Blei (2012).
Leverages topic proportions obtained from LDA model to improve predictions
and allow for out-of-matrix predictions.
Parameters:
- sigma2: expected variance of ratings
(variance of the ratings Normal prior)
- sigma2_P: expected variance of the elements of the
preference vector
- sigma2_Q: expected variance of the elements of the
quality vector
"""
def __init__(self, epochs=200, learning_rate=0.001, sigma2=10, sigma2_P=10, sigma2_Q=10):
self.epochs = epochs
self.learning_rate = learning_rate
self.sigma2 = sigma2
self.sigma2_P = sigma2_P
self.sigma2_Q = sigma2_Q
def fit(self, theta, X_train, X_val):
"""
Fit a CTR model.
Parameters:
- theta: (K X I) matrix of topic proportions obtained via LDA.
- X_train: (U X I) ratings matrix to train the model on.
- X_test: (U X I) ratings matrix to validate the model on.
"""
K = theta.shape[0]
U, I = X_train.shape
#initialize P and Q matrices.
# P is initialized randomly
self.P = np.random.randint(0, 10) * np.random.rand(K, U)
# Q is initialized to be equal to theta
self.Q = theta.copy()
self.train_error = []
self.val_error = []
# obtain the pairs of (u, i) indices for which we observe a rating
users, items = X_train.nonzero()
# begin training
for iteration in trange(self.epochs, file=sys.stdout, desc='CTR'):
for u, i in zip(users, items):
error = X_train[u, i] - np.dot(self.P[:, u].T, self.Q[:, i])# we are MAXIMIZING the likelihood via gradient ascent
self.P[:, u] += self.learning_rate * (-self.P[:, u]/self.sigma2_P + (self.P[:, u] * error)/self.sigma2)
self.Q[:, i] += self.learning_rate * (-(self.Q[:, i] - theta[:, i])/self.sigma2_Q + (self.Q[:, i] * error)/self.sigma2)self.train_error.append(mse(np.dot(self.P.T, self.Q), X_train))
self.val_error.append(mse(np.dot(self.P.T, self.Q), X_val))
def predict_ratings(self):
"""
Returns the matrix of predicted ratings.
"""
return np.dot(self.P.T, self.Q)
def predict_out_of_matrix(self, topics):
"""
Returns the (U X 1) vector of predicted ratings
for an unrated item, using the item's topic proportions.
Parameters:
- topics: (K X 1) array of topic proportions
for the unrated item.
"""
return np.dot(self.P.T, topics)
并训练模型:
ctr = ctr = CTR(sigma2_P=5, sigma2_Q=5, sigma2=1)
ctr.fit(theta, X_train, X_val)
在训练结束时,我们的ctr
对象将已经学习了潜在矩阵 P 和 Q,并将能够通过它们的点积来预测评分矩阵中缺失的值。
下面是 100 个时期的整个训练的 MSE 性能,在最后一个训练时期记录的验证集上有 0.126 MSE。
对单个保持观察的性能具有 0.35 的 MSE。当然,这没有矩阵内预测记录的高,但如果我们考虑到我们推荐的是矩阵外的项目,这是相当令人印象深刻的。
我们对我们的结果感到满意,但是在这种情况下,协作主题回归与传统的概率矩阵分解相比表现如何呢?显然很好。标准因式分解方法达到了 0.32 MSE,而 CTM 达到了 0.126。
附加功能
CTM 特有的潜在主题结构增加了进一步的可解释性,以做出推论。首先,CTM 相对于传统 PMF 的额外好处是,我们能够标记学习到的潜在维度,看到每个主题在每个项目中有多突出。注意:这些不是从 LDA 学习的主题比例,而是通过 CTM 模型学习的主题相关性!
我们还可以通过简单的 P 矩阵的水平求和来研究用户偏好在 K 潜在维度上的分布:
可以对项目而不是用户进行同样的操作,以查看类型如何在我们的项目中分布:
结论
在本文中,我们提出了协同主题建模,如王和 Blei (2011)所述,这是一种改进的基于文本项目的矩阵分解推荐系统。该模型的性能通常优于传统的矩阵分解方法,并具有额外的优势,如矩阵外预测和潜在维度可解释性。
一般来说,校准 CTM 模型的最大挑战是找到超参数的最佳组合,使我们的数据表现最佳。事实上,我们需要调整:
- alpha ,来自 LDA 模型。
- 话题数量 K
- 学习率
- sigma2,sigma2_P , sigma2_Q,分别关于 R,P,Q 的先验分布的超参数。
第二,由于模型的随机性质,在 LDA 阶段和 CTM 训练阶段,在单独的训练中模型的性能可能有很多可变性。
尽管不能保证比 PMF 有所改进,但 CTM 确实是一种在处理基于文本的文档推荐任务时应该考虑的方法,因为它通常具有更高的性能和矩阵外预测能力。
参考
[1] Mnih、Andriy 和 Russ R. Salakhutdinov。"概率矩阵分解."神经信息处理系统的进展。2008.
[2]布莱、戴维·m、安德鲁·Ng 和迈克尔·乔丹。"潜在的狄利克雷分配."机器学习研究杂志 3。一月(2003):993–1022。
[3]王、钟和戴维·布雷。"用于推荐科学文章的协作主题建模."第 17 届 ACM SIGKDD 知识发现和数据挖掘国际会议论文集。2011.
创建和使用自己的 Matplotlib 样式的指南
原文:https://towardsdatascience.com/a-guide-to-creating-and-using-your-own-matplotlib-style-30de6c60bac0?source=collection_archive---------32-----------------------
Python 科学绘图
创建样式模板以方便重复使用 matplotlib 设置
杰斯·贝利在 Unsplash 上拍摄的照片
虽然使用matplotlib
制作的默认图形看起来有些单调,但我真的很喜欢它的可定制性,它允许你调整图形中的每一个微小元素。
如果您发现自己每次创建一个新图形时都不断地更改matplotlib
中的一些基本设置,那么生成一个样式文件可能会很有成效。通过导入这种样式,您可以确保一致性,同时仍然能够在单个脚本中根据需要覆盖设置。例如,如果您正在为出版物生成图形,并且希望它们看起来都一样,而不必每次都复制/粘贴设置,那么这将非常有用。
你可以在matplotlib
Github 库找到一个样式文件的模板。正如你所看到的,有几乎无穷无尽的设置,你可以自定义你的愿望!我们将以此为指导创建我们自己的样式文件。
在我们开始之前,我们应该使用默认的matplotlib
参数创建一个空图作为比较的基础:
# Import packages
import matplotlib.pyplot as plt# Create figure
fig = plt.figure()# Add subplot to figure
ax = fig.add_subplot(111)# Show empty plot
plt.show()
使用默认参数的空 matplotlib 图
创建和使用一个 **.mplstyle**
文件
首先,我们必须创建一个名为your_style.mplstyle
的文件,然后我们可以用您选择的文本编辑器编辑它。我将基于我的第一篇文章的科学主题,所以我们将创建一个名为scientific.mplstyle
的风格。要运行这种风格,我们必须将它放在我们的matplotlib
配置目录中。一种简单的检查方法是运行下面的代码:
import matplotlib as mpl
mpl.get_configdir()
我的配置目录,可能与大多数目录相似,位于我的主目录的一个子文件夹中:~/.matplotlib/
我们将.mplstyle
文件放在一个名为stylelib
的子目录中。如果这个文件夹对你来说还不存在,可以创建它并把你的scientific.mplstyle
文件放到这个文件夹里。现在,当您想要使用您的样式时,在您的 Python 脚本中使用以下行:
plt.style.use('scientific')
图属性
首先,我们可以设置图形大小,通常为 6.4 x 4.8 英寸。我们将使用 4 x 4 英寸的图形作为默认图形。现在,每次我们调用plt.figure()
,我们的图形将具有 4 x 4 的尺寸:
# Figure Properties
figure.figsize: 4, 4
现在我们可以设置我们的字体和默认字体大小。我将使用字体“Avenir”和 16 号字体。
# Font Properties
font.family: Avenir
font.size: 16
轴属性
现在我们已经更改了全局图形属性,让我们编辑轴/子图形对象的属性。首先,我们想改变轴的粗细,我们使用axes.linewidth
来实现:
# Axes properties
axes.linewidth: 2
接下来,我经常发现刻度标签和轴标签之间的默认填充(空白)太小。我们可以插入自己的自定义填充值,如下所示:
axes.labelpad: 10
最后,我们将更改绘图时使用的默认颜色,这可以通过编辑颜色循环程序来完成。我们通过创建一个cycler()
对象并将其传递给属性axes.prop_cycle
来实现这一点。我很喜欢五点三十八的剧情中使用的颜色,所以会用这个作为我们的色环。我将使用十六进制代码插入颜色:
axes.prop_cycle: cycler(color=['008fd5',
'fc4f30',
'e5ae38',
'6d904f',
'8b8b8b',
'810f7c'])
让我们检查一下到目前为止的进展吧!我们使用以下代码:
# Import packages
import matplotlib.pyplot as plt# Use our custom style
plt.style.use('scientific')# Create figure
fig = plt.figure()# Add subplot to figure
ax = fig.add_subplot(111)# Show empty plot
plt.show()
已经好看多了!我们注意到刻度线与我们所做的一些轴更改不匹配,因此这将是我们的下一步。
Tick 属性
我们从默认图中注意到,刻度线指向外面,在顶部或右侧轴上没有刻度。对于我们的科学主题,我们希望刻度都指向内部,并且我们希望刻度位于所有轴上,这可以通过以下方式实现:
# Tick properties
# x-axis
xtick.top: True
xtick.direction: in# y-axis
ytick.right: True
ytick.direction: in
现在,我们想改变两个属性size
和width
。width
的值对应于线宽,所以我们将它设置为等于我们给axes.linewidth
(2)的值。size
的值是分笔成交点的长度——我们将主要分笔成交点的大小设置为 7,次要分笔成交点的大小设置为 5:
# x-axis
xtick.major.size: 7
xtick.major.width: 2xtick.minor.size: 5
xtick.minor.width: 2# y-axis
ytick.major.size: 7
ytick.major.width: 2ytick.minor.size: 5
ytick.minor.width: 2
我们现在有了下图——记号现在已经被修复了!
线条属性
如果我们想编辑调用plt.plot()
时使用的任何默认参数,我们可以通过编辑lines
的属性来实现。这可以扩展到其他绘图功能——例如,您可以编辑scatter
的属性,以影响创建散点图时的默认参数。在我们的例子中,我只打算将线条的默认宽度从默认值 1.5 更改为 2:
# Lines properties
lines.linewidth: 2
图例属性
matplotlib
中的默认图例是半透明的,并且有一个称为FancyBox
的带弯曲角的框架。要了解这一点,我们可以使用所有默认参数运行以下代码:
# Import packages
import matplotlib.pyplot as plt
import numpy as np# Create figure
fig = plt.figure()# Add subplot to figure
ax = fig.add_subplot(111)# Create some data
x = np.linspace(0, 4*np.pi, 200)
y1 = np.sin(x)
y2 = 1.5*np.sin(x)
y3 = 2*np.sin(x)# Plot data
ax.plot(x, y1, label='A = 1')
ax.plot(x, y2, label='A = 1.5')
ax.plot(x, y3, label='A = 2')# Add legend
ax.legend()# Show plot
plt.show()
默认 matplotlib 图例-半透明赋予边框灰色
让我们使图例完全不透明,并完全移除框架:
# Legend properties
legend.framealpha: 1
legend.frameon: False
最终结果
现在,让我们看看以前的情节如何与我们的新matplotlib
风格!我们使用以下代码:
# Import packages
import matplotlib.pyplot as plt
import numpy as np# Use our custom style
plt.style.use('scientific')# Create figure
fig = plt.figure()# Add subplot to figure
ax = fig.add_subplot(111)# Create some data
x = np.linspace(0, 4*np.pi, 200)
y1 = np.sin(x)
y2 = 1.5*np.sin(x)
y3 = 2*np.sin(x)# Plot data
ax.plot(x, y1, label='A = 1')
ax.plot(x, y2, label='A = 1.5')
ax.plot(x, y3, label='A = 2')# Set axis labels
ax.set_xlabel('x')
ax.set_ylabel('y')# Add legend - loc is a tuple specifying the bottom left corner
ax.legend(loc=(1.02, 0.65))# Save plot
plt.show()
三…二…一…
我们还可以做一些小的调整,比如调整 x 和 y 刻度的比例,但是通过让我们的样式设置为我们做大部分工作,我们的生活变得简单多了!
结束语
对于如何调整属性来定义matplotlib
图的样式,有无限的可能性。本文的scientific.mplstyle
文件将在这个 Github 资源库中提供。
感谢您的阅读!我感谢任何反馈,你可以在 Twitter 上找到我,并在 LinkedIn 上与我联系,以获得更多更新和文章。
Python 中所有字符串格式的指南
原文:https://towardsdatascience.com/a-guide-to-everything-string-formatting-in-python-e724f101eac5?source=collection_archive---------18-----------------------
你需要知道的关于 Python 中格式化字符串的五个方法
由萨法尔萨法罗夫在 Unsplash 上拍摄的照片
字符串是编程中最基本和最常用的数据类型之一。它允许计算机与世界进行交互和通信,例如打印指令或读取用户的输入。操纵和合成字符串的能力赋予程序员处理和操纵文本的能力,例如,从网站表单中提取用户输入,从处理的文本中提取数据,并使用这些数据执行情感分析等活动。情感分析是自然语言处理的一个子领域,它允许计算机根据一段文本对情绪进行分类——消极、积极或中性。
“所有的情绪是正确的;因为感情除了它自己之外,没有别的意义,只要一个人意识到它,它总是真实的。”—大卫·休谟
Python 是仅次于 r 的用于分析和操作数据的主要编程语言之一。Python 用于数据分析,以帮助访问数据库并与之通信。它在使用不同的 web 抓取技术导入和导出数据时也很有用。一旦获得这些数据,Python 就被用来清理和准备数据集,然后将它们输入到机器学习算法中。
使用 Python 格式化字符串有五种方式:使用模操作符格式化字符串,使用 Python 内置的 format 函数格式化,使用 Python 3.7 f-strings 格式化,手动格式化,最后使用模板字符串。我们将介绍这些方法中的每一种,以及何时使用它们。
让我们开门见山吧…
使用模运算符
图片由作者提供(使用 Canva 制作)
如果您以前使用 C 或 C++编写过代码,您会觉得非常熟悉。在 Python 中,我们可以使用模运算符(%)来执行简单的位置格式化。我在这里称之为占位符,它代表了格式化和转换字符串的控制规范。%告诉解释器下面的字符是转换字符串的规则。转换规则包括关于结果格式化字符串的期望宽度、结果的类型和精度的信息——在浮点的情况下。
图片由作者提供(使用 Canva 制作)
这种类型的字符串格式有时被称为“旧样式”格式。占位符可以直接引用值,也可以使用关键字参数指定。
formatted_str = 'Yesterday I bought %d %s for only %.2f$!' % (10, 2'bananas',2.6743)
如果我们试图打印这个字符串,我们将得到Yesterday I bought 10 bananas for only 2.67$!
。
正如你在这里看到的,我有三个占位符用于三个值,第一个整数,第字符串 —香蕉,以及香蕉的价格,这是一个浮点数。当提到浮点数时,我认为精度为 2 是我所需要的;这就是为什么小数点后只显示 67 的原因。
在前面的例子中,我们直接用值替换了占位符。还有另一种方法可以实现这种映射,那就是使用关键字参数或者传递一个字典。
name = 'John'
balance = 235765
formatted_str = 'Hello %(name)s, your current balance is %(balance)6.0f dollars.' % {"name":name, "balance":balance}
使用这种方法,我们需要使用{}
而不是()
。正因为如此,我们也可以直接使用字典来填充占位符。
dictionary = {'quantity': 10, 'name': 'bananas', 'price': 2.6743}
formatted_str = 'I got %(quantity)d %(name)s for $%(price).2f$' % dictionary
本节的完整代码:
使用格式方法
图片由作者提供(使用 Canva 制作)
在 Python 3 中,该语言引入了一种新的方法来规范%操作符语法。这是使用内置的格式方法完成的,也称为“新样式”格式。使用 format 方法与使用%运算符有许多共同点。让我们考虑重写以前的一些例子:
name = 'John'
balance = 235765
formatted_str = 'Hello %(name)s, your current balance is %(balance)6.0f dollars.' % {"name":name, "balance":balance}
会变成:
name = 'John'
balance = 235765
formatted_str = 'Hello {name:s}, your current balance is {balance:6.0f} dollars.'.format("name":name, "balance":balance)
我们可以将%运算符语法和 format 方法之间的差异总结如下:
- 通过%操作符,我们在字符串中使用了
()
,而对于格式方法,我们使用了{}
。 - 为了定义%运算符中的转换类型,我们将其设置在%之后,而在 format 函数中,我们将转换设置在
:
之后的{}
中。
但是,如果我们想将字典传递给格式字符串,我们需要稍微修改一下重新造林。我们需要传递一个指向字典的指针,而不是传递字典的名称,例如:
dictionary = {'quantity': 10, 'name': 'bananas', 'price': 2.6743}
formatted_str = 'I got {quantity:d} {name:s} for {price:.2f}$'.format(**dictionary)
此外,我们可以使用与 format 方法中使用的%运算符相同的转换规则。在 Python 3 和 3.6 版本中,format 方法比%运算符方法更受欢迎。format 方法提供了一种格式化字符串的强大方法;它没有使简单的情况变得复杂——比如上面的例子——但是,同时为我们如何格式化字符串提供了新的层次。
本节的完整代码:
使用 f 弦
图片由作者提供(使用 Canva 制作)
在我看来,这是格式化字符串最有趣、最优雅的方法。f-string 在 Python 3.8 中作为一种更直接的字符串格式化方法出现。在我们进入 f-strings 之前,让我们快速了解一下 Python 3.8 及更高版本中的三种类型的字符串。
- 正常/标准字符串:包含在“”或“”之间,例如
“Hello, world!”
。这些是最常用的字符串类型。 - 原始字符串:由 r”引导,例如
r’hello\nworld’
。在这种类型的字符串中,不对字符串进行任何处理。也就是说,转义字符在这些字符串中不起作用。相反,它们将不经过任何处理就被打印出来。这种类型的字符串主要用在正则表达式中。 - f 弦:由 f 引”,例如
f’hello John!’
。F-strings 用作格式化字符串的替代方法。
[## 程序员指南掌握正则表达式
了解语言类比
towardsdatascience.com](/programmers-guide-to-master-regular-expression-f892c814f878)
string 提供了一种简单的方法,通过直接将表达式嵌入到字符串中来格式化字符串。让我们再看一遍之前的例子。
name = 'John'
balance = 235765
formatted_str = 'Hello {name:s}, your current balance is {balance:6.0f} dollars.'.format("name":name, "balance":balance)
如果我们想使用 f 字符串重写这种格式,它将看起来像:
name = 'John'
balance = 235765
formatted_str = f'Hello {name}, your current balance is {balance} dollars.'
f-string 简化字符串格式的一种方法是,我们可以直接传递 iterables——字典、列表等。—字符串,如下所示:
dictionary = {'quantity': 10, 'name': 'bananas', 'price': 2.6743}
formatted_str = f'I got dictionary[quantity] dictionary[name] for dictionary[price]$'#f-string with lists
myList = [1,2,3,4]
formatted_str = f'The last item of the list is myList[-1]'
您还可以直接在 f 字符串中执行简单的算术或逻辑运算。
#Arithmetic
myList = [1,2,3,4]
formatted_str = f'The sum of the last and first items of the list is myList[0] + myList[-1]'
#Logic
formatted_str = f'myList[0] == myList[-1]'
string 为我们在想要格式化的字符串中使用的选项提供了更多的自由,例如列表索引、调用列表或字典方法,或者通用的 iterables 函数——例如,len
、sum
、min
和max
。我们还可以在 f 字符串中使用条件语句:
age = 21
formatted_str = f'You {"can't" if age < 21 else "can"} drink!'
本节的完整代码:
手动格式化
手动格式化是指使用标准的字符串方法来格式化字符串。大多数情况下,我们使用rjust
、 ljust
和center
来调整字符串。rjust
方法通过在左边填充空格来右对齐给定宽度的字符串。ljust
在右边添加填充,center
方法在字符串两边添加填充。这些方法不修改原始字符串;而是返回一个新的修改过的字符串。还有另一种字符串方法可以用来格式化字符串,那就是zfill
方法。此方法用一个左边带零的数值填充字符串。
使用模板字符串
图片由作者提供(使用 Canva 制作)
模板字符串是%操作符的替代物,但是模板字符串使用$符号代替%。这两种方法都提供了我们所说的替换格式。Python 中没有内置模板字符串,因此要使用它们,我们需要首先导入string
模块。模板字符串有三个规则:
$$
是转义字符。- 直接跟在
$
符号后面的是模板的占位符。默认情况下,这些占位符被限制为任何不区分大小写的字母数字字符串。$符号后的第一个非占位符字符终止了这个占位符规格,例如,一个空白字符。
这些规则和更多的规则已经在 string 模块中定义了,所以一旦导入,您就可以继续使用它们,而不需要定义它们。
模板字符串有两个主要方法:substitute
方法和safe_substitute
方法。这两种方法采用相同的参数,即替代映射。此外,两种方法都返回一个新的格式化字符串,您可以将模板对象视为未来字符串格式化的蓝图。例如:
**from** string **import** Template
formatted_str = Template('Hello $who, your current balance is $how dollars.')
formatted_str.substitute(who='John', how=235765)
要了解 substitute 和 safe_substitute 方法之间的区别,让我们尝试使用一个字典作为我们的替换映射。
**from** string **import** Template
mapping = dict(who='John', how=235765)
formatted_str = Template('Hello $who, your current balance is $how dollars.')
Returned_str = formatted_str.substitute(mapping)
假设我们的字典没有映射所需的所有键,使用substitute
方法将给出一个 keyError 。这里是safe_substitute
提供帮助的地方,如果这个方法没有找到正确的键,它将返回一个带有占位符的字符串来表示错误的键。例如,这段代码:
**from** string **import** Template
mapping = dict(who='John')
formatted_str = Template('Hello $who, your current balance is $how dollars.')
Returned_str = formatted_str.safe_substitute(mapping)
我将返回Hello John, your current balance is $how dollars.
,如果我使用了substitute
方法,我会得到一个错误。
本节的完整代码:
结论
在本文中,我们介绍了在 Python 中格式化字符串的五种不同方法:
- 模运算符。
- 格式功能。
- f 弦。
- 手动格式化。
- 模板字符串。
每种方法都有其使用优点和缺点。Dan Badar 提出了一个通用的经验法则,如果你格式化的字符串是用户获得的,那么模板字符串是一个不错的选择。否则,如果您使用 Python 3.7 或其他地方的 format 函数,请使用 f 字符串。
优秀对话管理指南
原文:https://towardsdatascience.com/a-guide-to-excellent-conversation-management-e3f7bce69336?source=collection_archive---------32-----------------------
面向拥有数十亿次对话和数百万客户的企业的必读指南。
图片来自 https://unsplash.com/的。
企业比以往任何时候都更容易被对话淹没。他们不仅要通过电子邮件、电话、社交和实时聊天等各种渠道积极回应客户,还需要给出个性化、相关且快速的回应。
为了解决这个问题,许多组织都在寻找新技术来帮助他们满足客户的期望。其中最引人注目的是人工智能聊天机器人、自助知识库和老式交互式语音应答(IVR)系统。
问题?这些都旨在减少客户与代理商相处的时间。
虽然人们确实喜欢自助服务的速度和方便,但大多数人仍然希望能够在需要的时候,或者在他们人生的重要转折点上与人交谈。奇怪的是,虽然我们正在向一个更加数字化和自助服务的世界迈进,但大多数消费者仍然希望他们的服务交流具有“人情味”。
图片来自https://unsplash.com/。
面临的挑战是提供高度个性化和相关的产品,以满足客户和业务目标,同时通过客户的自然交互媒介提供体验。与直觉相反,将人的因素带回客户对话的最有可能的解决方案是通过技术和大数据。
那么,您应该在一项技术中寻找什么,既能让您的客户满意,又能使收入最大化呢?
多渠道对话
图片经由https://unsplash.com/。
基本上,一个组织的沟通渠道应该在一个视图中。这意味着一家企业应该能够通过电子邮件、电话、实时聊天、社交媒体、论坛以及他们可能与你交谈或谈论你的任何地方,在一个平台上看到并回复客户。
为什么?便捷透明。
方便的对话
对于面向客户的代理来说,整个对话渠道的单一平台要高效得多。通常,他们不得不在多个渠道之间切换,以检查新的客户互动,不幸的是,这里或那里错过了一些沟通。通过一个对话视图,他们节省了时间,并减少了错过监控较少的频道的机会。
便利不仅仅是代理人的。顾客希望通过他们选择的媒介与品牌互动。 51%的美国消费者忠诚于通过他们喜欢的沟通渠道与他们互动的品牌。尤其是年轻的消费者,希望通过使用自然语言的即时消息渠道与大型机构互动。将所有渠道放在一个平台上,可以让代理了解所有渠道,而不是在一些渠道做得很好,而在其他渠道落后。
透明的对话
在许多组织中,不同的团队负责不同的渠道。他们只对这个渠道负责。但是顾客是动态的。他们可能会接触一个频道,一旦发现这个频道不够快或不够充实,无法解决他们的问题,他们就会换频道。
“不同团队,不同渠道”的方法没有考虑到客户的灵活性,导致来自两个不同人的多个回复或不一致的回复,都造成了糟糕的客户体验。一个视图上有多个频道,对话是透明的。来自同一个客户的对话被缝合在一起,同一个人可以处理问题,而不会使客户的旅程变得困难。
整体客户观
图片来自 https://unsplash.com/的。
在一个拥有多个部门、系统和渠道的企业中,有必要对客户有一个整体的看法。
单一客户视图(或 360 度视图)是一个完整的客户概况,由组织系统和渠道中的聚合数据点创建。它整理来自多渠道通信和客户数据平台(如 CRM、分析、营销和遗留系统)的数据。
顾客经常抱怨他们的谈话缺乏连续性,不得不重复。之所以会出现这样的问题,是因为代理不知道客户在单独的渠道上说了什么,或者在单独的系统上存在什么客户信息。因此,互动被视为全新的“门票”,在最糟糕的情况下,现有客户被视为新客户。
通过单一客户视图,代理可以在一个位置查看给定客户的对话、交易和行为数据。这不仅将回答时间缩短了 20% — 80% ,还确保了客户信息流的一致性和连续性,减少了上述尴尬时刻。
单一客户视图的使用甚至可以超越客户关怀活动。集成系统意味着可以通过对话将销售、营销和服务活动无缝融合。
拥有这一特性标志着能够集中使用关键数据源的开始。然而,关键在于如何使用客户智能。下面介绍了如何使用客户智能来控制对话,从而提供卓越的客户体验并实现收入最大化。
人工智能辅助的代理
在企业中使用人工智能(AI)并不新鲜。几十年来,它们一直被用于自动化繁重的手动过程,以提高效率、准确性和降低成本。什么是新的,是人工智能的使用超越过程的互动。
人工智能的使用开启了提供可扩展的个性化交互和高度相关产品的潜力。
图片来自 https://unsplash.com/的。
无论是人工智能本身在说话,还是算法在线或面对面地向人类代表提供帮助,人工智能都拥有在日益数字化的世界中重建人与人之间联系的惊人潜力。看看下面的一些例子。
用人工智能传递相关内容和信息
许多组织在用户体验、自助服务和知识管理工具方面进行了大量投资。然而,对于客户来说,在他们需要的时候找到正确的信息仍然是困难和耗时的。
像 Zendesk 这样的公司已经开发了人工智能虚拟助手,帮助客户自助服务。通过处理自然语言,该技术在知识库中建议文章,以帮助他们自己解决问题。研究发现,大多数人对像这样使用自助式人工智能技术持开放态度,并认为它更快、更方便。
其他组织,如 Woveon,已经建立了人工智能响应助理,以帮助代理人进行更有效的实时对话。当代理与客户交谈时,响应协助有助于引导对话,从而为客户和企业带来更好的结果。它会建议像“其他像她一样的顾客也买了”或“他提到了信用卡,链接到我们博客上的这些文章来帮助他做出决定”这样的机会。
加快解决时间
图片经由https://unsplash.com/。
平均而言,客户服务专员花费 20%的时间寻找信息和背景来解决客户的问题。那是一周工作中的一整天!
人工智能可以帮助组织信息,使其易于消化,并与客户的查询相关。例如,Woveon 的智能响应框架将根据对话流改变其显示的信息,以帮助代理。如果客户谈论他们的个人贷款,他们的贷款细节就会弹出来。如果谈话转移到他们丢失的信用卡上,他们的发货细节就会浮出水面,代理就会被提示取消丢失的信用卡。
人工智能辅助不是浪费时间寻找信息,而是让代理有更多时间建立关系,并抓住未开发的客户机会。客户也喜欢快速高效的互动。 69% 将良好的客户服务体验归因于快速解决问题。
减少重复性管理任务,为更高价值的互动打开大门
图片经由https://unsplash.com/。
像拜访后工作(ACW)这样的管理任务一直是面对客户的员工头疼的问题。虽然它们是必要的,但它是乏味的,重复的,而且占用太多时间。技术可以帮助减少花费在这些琐碎任务上的时间,让代理有更多的时间来建立客户关系,并在此过程中使他们的工作更有成效和意义。
例如,Avaya 有一个自然语言摘要工具,可以帮助代理在致电后处理客户信息。Talkdesk 自动呼叫路由,客户自动与最有能力解决其问题的代理配对。Woveon 可以根据客户的重要性、价值、紧迫性或所有因素的组合,实时确定对话的优先级。
将员工的时间从琐碎的任务中解放出来,让他们能够参与更高价值的活动。
智能分析
图片经由https://unsplash.com/。
毫无疑问,数据分析对客户对话非常有益。诀窍在于知道使用什么数据,如何使用,以及何时使用。
使用什么样的数据很重要,因为并非所有数据都是平等的。例如,与其看某个时间点的指标(客户给代理的解决率打了 4 分,满分 5 分),不如看更大的图更重要(打了 3 个电话,等了一个小时才到达那里)。
可以说,如何使用数据对对话的成功更为关键。关键在于知道哪些数据点应该联系在一起,以及从中得出什么样的分析。一系列营销和服务数据可以显示最近的营销活动如何影响对话量和 NPS。对客户对话中的相关关键词进行聚类分析,可以发现巨大的物流缺陷。
何时使用哪些数据对面向客户的代理特别重要。例如,74%的千禧一代银行客户希望他们的金融机构在他们需要的时候向他们发送服务信息。这可能是他们开始找房子时的个人贷款信息,或者是他们打算旅行前的旅行保险信息。
如今,公司拥有大量客户数据。理论上,组织应该有能力知道他们是谁,他们需要什么,是什么让他们叛逃到另一家公司。然而,缺乏对整体客户旅程和客户智能工具的可见性阻碍了他们提供这种卓越的能力。
下一节将深入探讨对管理客户对话特别有用的三种分析类型——预测、聚类和创收。
预测分析
预测分析提供对潜在客户问题和机会的预见。从现有的历史对话、交易和行为数据中提取,它可以帮助代理更好地为客户结果和趋势做准备。
一个非常常见的例子是预测客户对话的流入时间。对于电子商务企业来说,假日季节通常会出现客户对话高峰,并在下一个假日季节之前稳步下降。在更复杂的情况下,预测分析可以发现,具有特定职业、特定关注点以及处于类似生活阶段的客户实际上是组织尚未利用的利基市场。
聚类分析
这在对话技术中并不常见,但绝对值得一提。聚类分析包括对对话和客户信息进行标记,然后将相似或相关的标记聚集在一起,以获得洞察力。
聚类分析可以得出对话中的主题是如何相关的,或者特定的客户群对产品的感觉如何。这种客户情报可以反馈到业务的其他部分。它可以用来帮助创建一个新的自动化客户工作流,或者为新发现的客户群提供一个新的营销活动。
创收分析
随着重复性和琐碎的对话逐渐被自助服务解决方案所解决,代理也必须从传统的支持角色转变为混合服务销售模式。顾名思义,这类分析是为对话中的业务创造收入的分析。
例如,Woveon 的智能响应框架为银行的客户专员代表提供了向客户销售更多产品的方法。符合“通常持有黑色美国运通卡的客户”特征的客户将向代理提出建议,说服客户从其当前卡升级。处于“像他这样的客户正在考虑购买房产”这一人生阶段的客户会建议链接一些房屋贷款网页,或者与财务规划师进行免费交流。
Marketo 研究显示,B2B 公司只有 10%的收入来自初始销售。 90%的收入来自后续销售。
在最好的情况下,这种分析也会在合适的时间交付,以便代理利用机会,就像在智能响应框架中一样。
做一个数据极客,而不是讨厌鬼
图片来自 https://unsplash.com/的。
当然,重要的是要知道数据的使用应该是“酷的”,而不是“令人毛骨悚然的”。这两者之间有一条不应逾越的细微差别。此外,每个人的底线是不同的,所以一个客户可能认为很酷,可能会被其他人认为很可怕。
企业应该拥有足够的客户数据来跟踪和了解个人偏好,并了解客户在客户旅程的不同点对其信息的不同使用做出的反应。对话智能和分析工具有助于在不超出客户界限的情况下建立更好的关系。
总的来说,客户不介意公司使用他们的数据来个性化他们的体验,并推荐对他们有益的产品和服务。
虽然人类接触的数量在减少,但每次互动的质量和重要性都在增加。有远见的组织应该平衡数量和质量,以保持客户体验的竞争优势。技术可以成为实现这一目标的强大助推器。
原为 写成 。
R 中的时间序列预测
原文:https://towardsdatascience.com/a-guide-to-forecasting-in-r-6b0c9638c261?source=collection_archive---------3-----------------------
指数平滑、TBATS、ARIMA、萨里玛等
来源:https://unsplash.com/photos/pGcqw1ARGyg
Python 很棒,但是说到预测,我个人认为 R 还是占了上风。预测包是 R 或 Python 上最完整的预测包,值得了解一下。
下面是我们将在本文中看到的内容:
- 幼稚的方法
- 指数平滑(状态空间模型和 DSHW)
- 蝙蝠和蝙蝠
- SARIMA 萨里玛模型
- 如何设置提前一步预测
对于每种方法,我们将在验证集上建立一个模型,用它预测验证集的持续时间,并将预测与真实观测值进行比较,以获得平均绝对百分比误差(MAPE)。
所使用的数据将来自 r。
library(forecast)
library(MLmetrics)data=AirPassengers**#Create samples** training=window(data, start = c(1949,1), end = c(1955,12))
validation=window(data, start = c(1956,1))
1.幼稚的方法
任何预测方法都应该通过与一种简单的方法进行比较来进行评估。这有助于确保在性能方面为拥有更复杂的模型所付出的努力是值得的。
所有方法中最简单的叫做简单朴素。极其简单:对明天的预测就是我们今天所观察到的。
另一种方法,季节性天真,稍微复杂一点:对明天的预测是我们前一周/月/年(取决于我们使用的是什么样的时间范围)观察到的。
以下是如何做一个季节性的简单预测:
naive = snaive(training, h=length(validation))
MAPE(naive$mean, validation) * 100
这给了我们 27.04%的 MAPE。那是要打破的分数。顺便说一下,去掉“snaive”中的 s,你就有了简单天真的代码。以下是如何绘制预测图:
plot(data, col="blue", xlab="Year", ylab="Passengers", main="Seasonal Naive Forecast", type='l')
lines(naive$mean, col="red", lwd=2)
我们看到,在过去一年的数据中发生的事情被重复作为对整个验证集的预测。
2.指数平滑法
做指数平滑有很多方法。这个想法总是让观察的权重递减。越是最近的观察,它在我们的预测中就越重要。
也可以添加参数。例如,您可以添加一个趋势参数(霍尔特方法)或添加一个季节性参数(霍尔特-温特斯)。
2.1 状态空间模型
使用预测包,平滑方法可置于状态空间模型的结构中。通过使用这种结构,我们可以找到最优的指数平滑模型,使用 ets 函数。
ets_model = ets(training, allow.multiplicative.trend = TRUE)
summary(ets_model)
我们看到 ETS (M,Md,M)。这意味着我们有一个带有倍增误差、倍增趋势和倍增季节性的 ets 模型。基本上,乘法意味着参数随着时间被“放大”。例如,随着时间的推移,这种趋势变得越来越大(我们的情况就是如此)。
以下是如何使用估计最佳平滑模型进行预测:
ets_forecast = forecast(ets_model, h=length(validation))
MAPE(ets_forecast$mean, validation) *100
我们看到,需求的上升趋势正被一点点捕捉到(远非完美,比天真要好)。它给出了 12.6%的 MAPE。
2.2 双季节冬令
ets 功能不错,但是只允许一个季节性。有时,我们拥有的数据可以由多个季节组成(例如,每月和每年)。
双季节霍尔特-温特斯(DSHW)允许两个季节:较小的季节经常重复,较大的季节不经常重复。然而,为了使该方法有效,季节性需要嵌套,这意味着一个必须是另一个的整数倍(2 和 4,24 和 168,等等。).
这里的代码有点不同,因为我们需要指定两个季节的长度(,这并不总是我们所知道的),并且预测是在使用 dshw 函数创建模型时直接计算的。
dshw_model = dshw(training, period1=4, period2 = 12, h=length(validation))MAPE(dshw_model$mean, validation)*100
用这种方法我们得到了 3.7%的 MAPE!
3.蝙蝠和蝙蝠
DSHW 不错,但是有些流程有比较复杂的季节性,我们之前的函数无法处理。事实上,你可以同时拥有每周和每年的季节性。你甚至可以有两个以上!
蝙蝠和 TBATS 允许多个季节。 TBATS 是 BATS 的一种改型(实际上是一种改进),允许多个非整数季节性周期。
以下是如何构建 TBATS 模型并使用它进行预测:
tbats_model = tbats(training)
tbats_forecast = forecast(tbats_model, h=length(validation))MAPE(tbats_forecast$mean, validation) * 100
我们用这种方法得到了 12.9%的 MAPE。
4.SARIMA 萨里玛模型
ARIMA 模型包含三样东西:
- AR(p) :模型的自回归部分。意味着我们使用时间序列中 p 个过去的观察值作为预测值。
- 差分(d): 用于通过在适当的滞后 d 取连续观测值之间的差值,将时间序列转换为平稳序列。
- MA(q) :使用 q 个过去的预测误差作为预测值。
这就是 ARIMA 的情况,但是如果你知道你拥有的数据是季节性的,那么你需要更多。这就是萨里玛发挥作用的地方。
SARIMA 为该款增加了季节性元素。
来源:https://otexts.com/fpp2/seasonal-arima.html
p 代表季节性 AR 阶,D 代表季节性差分阶,Q 代表季节性 MA 阶,m 代表每年的观察次数。
auto . ARIMA 函数可用于返回最佳估计模型。代码如下:
arima_optimal = auto.arima(training)
该函数返回以下模型:ARIMA(0,1,1)(1,1,0)[12]。
要预测一个 SARIMA 模型(这就是我们这里的模型,因为我们有一个季节性部分),我们可以使用 astsa 包中的 sarima.for 函数。
library(astsa)
sarima_forecast = sarima.for(training, n.ahead=length(validation),
p=0,d=1,q=1,P=1,D=1,Q=0,S=12)MAPE(sarima_forecast$pred, validation) * 100
我们用这个萨里玛模型得到了 6.5%的 MAPE。
如你所知,理论上我们可以通过在 ARIMA/萨里玛模型中加入外生变量(解释变量)来使事情变得更加复杂,这将使它成为萨里玛模型。
对于这个数据,DSHW 给出了最好的结果。但是请记住,没有一个模型总是做得最好。
5.设置一步预测
在前面的例子中,我预测了未来 5 年。但是,如果您想每天进行预测,为什么要使用 5 年前的预测值,而您可以使用真实的观察值来预测明天呢?
建立提前一步预测的想法是,评估如果您在 5 年内使用最新的观测值进行提前一天的预测,模型会做得有多好。
简单地说:我们不是对未来的 60 个月进行一次预测,而是利用最新的观察结果对下个月进行 60 次预测。
编写这样的代码非常简单。我们所需要的是迭代地将最新的观察结果添加到训练数据集中,从那里进行预测并重复。下面是使用我们之前找到的 SARIMA 模型来实现它的代码。
one_step_ahead_sarima = matrix(ncol = 2, nrow = 60)for (i in 1:60){
training_observed = window(data, start = c(1949,1), end = c(1955,(12+i)), frequency = 12)
forecasted.sarima = sarima.for(training_observed,n.ahead=1,p=0,d=1,q=1,P=1,D=1,Q=0,S=12)
demandforecast = forecasted.sarima$pred
observed = validation[[i]]
one_step_ahead_sarima[i,1]= observed
one_step_ahead_sarima[i,2]= demandforecast}MAPE(one_step_ahead_sarima[,1], one_step_ahead_sarima[,2]) * 100
如您所见,对于每一次迭代,训练集增长一个观测值,计算 n.ahead=1 的新预测,结果存储在 one_step_ahead_sarima 矩阵中。
下面是如何得到这个情节:
plot(data, col="blue", xlab="Year", ylab="Passengers", main="SARIMA Forecast", type='l')
lines(ts(one_step_ahead_sarima[,2], start = c(1956,1), frequency = 12), col="red", lwd=3)
我们得到了 4.1%的 MAPE,这比我们使用相同的 SARIMA 模型预测未来 5 年的情况提高了 2%以上。
考虑到预测范围越短,预测应该越好,这并不奇怪。这就是为什么如果可能的话,你应该总是建立一个提前一步的预测!
我希望这有所帮助。非常感谢你的阅读!
成为会员:【https://francoisstamant.medium.com/membership】T4
深度学习层指南
原文:https://towardsdatascience.com/a-guide-to-four-deep-learning-layers-225c93646e61?source=collection_archive---------34-----------------------
完全连接,卷积,LSTM 和注意力都说明和解释。
作者照片-尼泊尔。
这篇帖子是关于四个重要的神经网络层架构——机器学习工程师用来构建深度学习模型的构建模块:
- 全连接层,
- 2D 卷积层,
- LSTM 层,
- 注意力层。
对于每一层,我们将了解:
- 每层如何工作,
- 每一层背后的直觉,
- 每层的感应偏置,
- 每层的重要超参数是什么,
- 何时使用每层、
- tensor flow 2.0 中各层如何编码。
所有代码示例都是使用 Keras Functional API 使用tensorflow==2.2.0
构建的。
背景——什么是感性偏差?
我在这篇文章中经常使用的一个术语是归纳偏差——一个在晚宴上听起来很聪明并给你的朋友留下深刻印象的有用术语。
归纳偏差是将假设硬编码到学习算法的结构中。这些假设使得该方法更专用,灵活性更差,但通常更有用。通过对数据结构的假设进行硬编码,我们可以在实践中学习用其他方法学不到的功能。
机器学习中的归纳偏差的例子包括最大限度(类别应由尽可能大的边界分开,在支持向量机中使用)和最近邻(在特征空间中靠近在一起的样本在同一类别中,在 k-最近邻算法中使用)。
这是机器学习中常见的一课——一点点偏差是可以的(如果你用偏差来交换的话)。这也适用于强化学习,在强化学习中,通过蒙特卡罗返回的无偏逼近比自举时间差分方法表现更差。
1.全连接层
也被称为密集或前馈层,全连接层是最通用的深度学习层。
这一层施加了我们层中最少的结构量。几乎在所有神经网络中都可以找到它——通常用于控制输出层的大小&形状。
全连接层是如何工作的?
全连接层的核心是人工神经元——这是 1943 年麦卡洛克&皮特的阈值逻辑单元的远祖。
人造神经元的灵感来自于我们大脑中的生物神经元,然而,人造神经元只是生物神经元复杂性的粗略近似。
人工神经元由三个连续的步骤组成:
1.输入的加权线性组合
不同层中节点之间的连接强度由权重控制,这些权重的形状取决于每一侧的节点层数。每个节点都有一个称为偏置的附加参数,可以用来独立于节点的输入来改变节点的输出。
学习权重和偏差——通常在现代机器学习中,反向传播用于找到这些权重的好值——好值是那些导致网络对看不见的数据有好的预测准确性的值。
2.所有加权输入的总和
在应用了权重和偏差之后,所有输入到神经元的输入被加在一起成为一个单一的数字。
3.激活功能
然后通过激活函数传递。最重要的激活功能有:
- 线性 —输出不变,
- ReLu — \(0\)如果输入为负,否则输入不变
- Sigmoid 将输入压缩到\((0,1)\)
- Tanh 将输入压缩到\((-1,1)\)
激活函数的输出被输入到下一层中的所有神经元(也称为节点或单元)。
这就是全连接层的名称来源——每个节点都完全连接到其之后的&之前的层中的节点。
具有 ReLu 激活功能的单个神经元——图片由作者提供。
对于第一层,节点从送入网络的数据中获取输入(每个数据点都连接到每个节点)。对于最后一层,输出是网络的预测。
全连接层—图片作者。
全连接层的直觉和归纳偏差是什么?
全连接层中所有连接背后的直觉是对信息如何在网络中流动没有任何限制。是没有直觉的直觉。
全连接层不强加任何结构,也不对网络将执行的数据或任务做出任何假设。由完全连接的层构建的神经网络可以被认为是一块空白的画布。直觉告诉我们,不要强加任何结构,让网络解决所有问题。
正是这种结构的缺乏赋予了完全连接层(具有足够的深度&宽度)的神经网络逼近任何函数的能力——这被称为通用逼近定理。
一开始,逼近任何函数的能力听起来都很吸引人。如果一个完全连接的层可以学习任何东西,我们为什么需要任何其他架构?
能够在理论上学习并不意味着我们可以在实践中学习。实际上,使用我们可用的数据和学习算法(如反向传播)来找到正确的权重可能是不切实际和不可实现的。
这些实际挑战的解决方案是使用不太专业的层——这些层对预期要执行的数据和任务有所假设。这种专业化就是归纳偏差。
什么时候应该使用全连接层?
全连接层是最通用的深度学习架构——除了深度之外,它对连接性没有任何限制。当您的数据没有可以利用的结构时使用它——如果您的数据是平面数组(常见于表格数据问题)。
当从平坦的环境观察中学习时,全连接层在强化学习中是常见的。例如,在 2015 年的信任区域策略优化(TRPO)论文中使用了具有单个全连接层的网络:
一个全连接层被用来为强化学习算法 TRPO 提供动力— 舒尔曼等人 2015
大多数神经网络在某处会有完全连接的层。在执行分类的卷积神经网络中,通常将它们作为倒数第二层和最后一层进行完全连接。
完全连接的输出层中的单元数量将等于类的数量,使用 softmax 激活函数创建类的分布。
什么超参数对全连接层很重要?
您通常会在全连接图层中设置的两个超参数是:
- 单位数量,
- 激活功能。
全连接层由多个节点(也称为单元)定义,每个节点都具有激活功能。虽然在不同的节点上可以有一个具有不同激活功能的层,但是大多数情况下,层中的每个节点都具有相同的激活功能。
对于隐藏层,激活函数最常见的选择是校正线性单元(ReLu)。对于输出层,正确的激活函数取决于网络预测的内容:
- 回归,目标可以是正的或负的->线性(无激活)
- 回归,目标只能是正的-> ReLu
- 分类-> Softmax
- 控制动作,限制在-1 和 1 -> Tanh 之间
通过 Keras Functional API 使用完全连接的层
下面是一个如何使用 Keras functional API 的全连接层的示例。
我们使用形状像图像的输入数据来显示完全连接层的灵活性。这要求我们在网络中使用一个Flatten
层。
import numpy as np
import tensorflow as tf
from tensorflow.keras import Input, Model
from tensorflow.keras.layers import Dense, Flatten# the least random of all random seeds
np.random.seed(42)
tf.random.set_seed(42)# dataset of 4 samples, 32x32 with 3 channels
x = np.random.rand(4, 32, 32, 3)inp = Input(shape=x.shape[1:])
hidden = Dense(8, activation='relu')(inp)
flat = Flatten()(hidden)
out = Dense(2)(flat)
mdl = Model(inputs=inp, outputs=out)mdl(x)
"""
<tf.Tensor: shape=(4, 2), dtype=float32, numpy=
array([[ 0.23494382, -0.40392348],
[ 0.10658629, -0.31808627],
[ 0.42371386, -0.46299127],
[ 0.34416917, -0.11493915]], dtype=float32)>
"""
2.2D 卷积层
如果你必须选择一个架构作为深度学习中最重要的,很难忽略卷积(我在那里做了什么?).
2012 年 ImageNet 竞赛的获胜者 AlexNet 被许多人视为现代深度学习的开端。Alexnet 是一个深度卷积神经网络,在 GPU 上训练。
卷积的另一个里程碑式的应用是 1998 年的 Le-Net-5,这是一个由 Yann LeCun 开发的 7 层卷积神经网络,用于对手写数字进行分类。
卷积神经网络是现代深度学习的主力——它可以用于文本、音频、视频和图像。卷积神经网络可以用来对图像内容进行分类,识别人脸并为图像创建字幕。它们也很容易在 GPU 上并行化,这使得它们可以快速训练。
卷积层的直觉和归纳偏差是什么?
2D 卷积层的灵感来自我们自己的视觉皮层。
在人工神经网络中使用卷积的历史可以追溯到几十年前的 neocognitron,这是由 Kunihiko Fukushima 在 1980 年推出的一种架构,其灵感来自于 Hubel & Wiesel 的工作,Hubel & Wiesel 在 20 世纪 50 年代表明,哺乳动物视觉皮层中的单个神经元是由视觉的小区域激活的。
卷积本身就是一种数学运算,常用于信号处理。卷积的一个很好的心理模型是在信号上滑动滤波器的过程,在每一点检查滤波器与信号的匹配程度。
这个检查过程就是模式识别,是卷积背后的直觉——在更大的空间中的任何地方寻找小的空间模式。这正是我们视觉皮层的工作方式。
这是卷积层的感应偏差——用于识别局部空间模式。
2D 卷积层是如何工作的?
2D 卷积层由两个组件之间的交互来定义:
- 具有形状(高度、宽度、颜色通道)的 3D 图像,
- 一个 2D 滤波器,有形状(高,宽)。
上面我们定义了卷积的直觉是在更大的空间中寻找模式。在 2D 卷积层中,我们寻找的模式是过滤器,更大的空间是图像。
过滤
卷积层由其滤波器定义。这些过滤器是经过学习的——它们相当于一个完全连接的层的权重。卷积神经网络的第一层中的过滤器检测简单的特征,例如线或边。在网络的更深处,过滤器可以检测更复杂的功能,帮助网络执行其任务。
为了进一步理解这些滤镜是如何工作的,让我们用一个小图像和两个滤镜来工作。卷积神经网络的基本操作是使用这些滤波器来检测图像中的模式,方法是执行逐元素乘法并将结果相加:
对一个小图像应用不同的滤镜——按作者分类的图像。
在整个图像上重复使用相同的过滤器允许在图像的任何部分检测到特征——这种特性被称为平移不变性。该属性非常适合于分类-无论猫出现在图像中的什么位置,您都希望检测到它。
对于较大的图像(通常是32x32
或更大),执行相同的基本操作,过滤器通过整个图像。该操作的输出充当网络已经学习的过滤器的特征检测,产生 2D 特征图。
通过对图像进行卷积生成过滤图的过滤器——作者的图像。
由每个过滤器产生的特征图被连接,产生 3D 体积(第三维的长度是过滤器的数量)。
然后,下一层使用一组新的学习滤波器对这个新的体积执行卷积。
多个过滤器的特征映射被连接以产生体积,该体积被传递到下一层——由作者生成的图像。
使用 Keras 函数 API 构建的 2D 卷积神经网络
以下是如何将 2D 卷积图层与 Keras functional API 结合使用的示例:
- 密集层之前的
Flatten
层,用来展平我们 2D 卷积层产生的体积, 8
的Dense
层大小——这控制了我们的网络可以预测多少类。
import numpy as np
import tensorflow as tf
from tensorflow.keras import Input, Model
from tensorflow.keras.layers import Dense, Flatten, Conv2Dnp.random.seed(42)
tf.random.set_seed(42)# dataset of 4 images, 32x32 with 3 color channels
x = np.random.rand(4, 32, 32, 3)inp = Input(shape=x.shape[1:])
conv = Conv2D(filters=8, kernel_size=(3, 3), activation='relu')(inp)
flat = Flatten()(conv)
feature_map = Dense(8, activation='relu')(flat)
out = Dense(2, activation='softmax')(flat)
mdl = Model(inputs=inp, outputs=out)mdl(x)
"""
<tf.Tensor: shape=(4, 2), dtype=float32, numpy=
array([[-0.39803684, -0.08939186],
[-0.48165476, -0.28876644],
[-0.32680377, -0.24380796],
[-0.45394567, -0.28233868]], dtype=float32)>
"""
对于卷积层,哪些超参数是重要的?
卷积层中的重要超参数有:
- 过滤器的数量,
- 过滤器尺寸,
- 激活功能,
- 大步流星,
- 填充,
- 扩张速度。
过滤器的数量决定了每层可以学习多少个模式。过滤器的数量随着网络的深度而增加是很常见的。滤镜大小一般设置为(3, 3)
,用一个 ReLu 作为激活函数。
步幅可用于跳过卷积中的步骤,从而生成更小的特征地图。填充可用于使图像边缘的像素看起来像是在图像的中间。膨胀允许过滤器在图像的更大区域上操作,同时仍然产生相同大小的特征图。
什么时候应该使用卷积层?
当数据具有空间结构时,卷积起作用,例如,图像具有高度和宽度的空间结构。您也可以使用傅里叶变换等技术从 1D 信号中获得这种结构,然后在频域中执行卷积。
如果你在处理图像,卷积是王道。虽然有工作将基于注意力的模型应用于计算机视觉,但由于它与我们自己的视觉皮层相似,卷积很可能在未来许多年都是相关的。
那么,除了空间结构,数据还能有其他什么结构呢?许多类型的数据都有顺序结构,这推动了我们下一个两层架构的发展。
我们的第三层是 LSTM,或长短期记忆层。LSTM 是递归的— 它按顺序处理数据。
递归允许网络体验数据的时间结构,例如句子中的单词或一天中的时间。
正常的神经网络接收单个输入张量\(x\)并生成单个输出张量\(y\)。递归结构在两个方面不同于非递归神经网络:
- 输入\(x\)和输出\(y\)数据都被作为一系列时间步长进行处理,
- 网络具有记忆信息并将其传递到下一时间步的能力。
递归架构的内存被称为隐藏状态 \(h\)。网络选择在隐藏状态下转发什么由网络学习。
一个递归神经网络——图片作者。
输入时间步长维度
使用递归架构需要熟悉时间步长的概念——知道如何正确地形成数据是使用递归的一半。
假设我们有输入数据‘x’,这是一个整数序列[0, 0] -> [2, 20] -> [4, 40]
。如果我们使用全连接层,我们可以将此数据以平面阵列的形式呈现给网络:
虽然序列对我们来说是显而易见的,但对完全连接的层来说却不明显。
一个完全连接的层所看到的只是一个数字列表——网络需要学习其顺序结构。
我们可以通过添加一个时间步长维度来重构我们的数据“x ”,以明确地模拟这种顺序结构。
我们数据中的值不会改变,只有形状会改变:
我们的数据‘x’现在由三个维度构成 — (batch, timesteps, features)
。递归神经网络将一次一个时间步长地处理特征,体验数据的顺序结构。
既然我们已经了解了如何构建用于递归神经网络的数据,我们就可以从更高的层面来了解 LSTM 层是如何工作的。
LSTM 图层是如何工作的?
LSTM 于 1997 年首次推出,并形成了基于现代序列的深度学习模型的主干,擅长于机器翻译等具有挑战性的任务。多年来,机器翻译的最新技术是 seq2seq 模型,它由 LSTM 提供支持。
LSTM 是一种特殊的 a 型递归神经网络。LSTM 解决了普通递归神经网络难以应对的挑战——长期思考的能力。
在递归神经网络中,传递到下一个时间步骤的所有信息必须适合单个通道,即隐藏状态“h”。
LSTM 通过使用两种隐藏状态来解决长期记忆问题,这两种隐藏状态被称为隐藏状态“h”和单元状态“c”。拥有两个通道可以让 LSTM 人同时进行长期和短期记忆。
在内部,LSTM 使用三个关口来控制信息流:
- 忘记 gate 来确定删除什么信息,
- 输入门来决定要记住什么,
- 输出门来决定预测什么。
使用 LSTMs 的一个重要架构是 seq2seq。通过编码器 LSTM 馈送源句子,以生成固定长度的上下文向量。第二解码器 LSTM 获取该上下文向量并生成目标句子。
seq 2 seq 型号—图片作者。
为了更深入地了解 LSTM 的内部,看看 colah 博客中对 LSTM 网络的精彩理解。
LSTM 的直觉和归纳偏差是什么?
对于 LSTM 层来说,一个很好的初始模型是将其视为一个数据库。输出、输入和删除门允许 LSTM 像数据库一样工作——匹配 REST API 的GET
、POST
、&、DELETE
,或者 CRUD 应用的read-update-delete
操作。
遗忘门就像一个DELETE
,允许 LSTM 删除无用的信息。输入门的作用就像一个POST
,LSTM 可以选择要记忆的信息。输出门的作用类似于一个GET
,其中 LSTM 选择向用户的信息请求返回什么。
递归神经网络具有将数据作为序列处理和存储记忆的归纳偏向。LSTM 在这种偏向的基础上又增加了一个长期和一个短期记忆通道。
通过 Keras 函数式 API 使用 LSTM 图层
以下是如何将 LSTM 图层与 Keras 功能 API 结合使用的示例:
import numpy as np
import tensorflow as tf
from tensorflow.keras import Input, Model
from tensorflow.keras.layers import Dense, LSTM, Flattennp.random.seed(42)
tf.random.set_seed(42)# dataset of 4 samples, 3 timesteps, 32 features
x = np.random.rand(4, 3, 32)inp = Input(shape=x.shape[1:])
lstm = LSTM(8)(inp)
out = Dense(2)(lstm)
mdl = Model(inputs=inp, outputs=out)
mdl(x)"""
<tf.Tensor: shape=(4, 2), dtype=float32, numpy=
array([[-0.06428523, 0.3131591 ],
[-0.04120642, 0.3528567 ],
[-0.04273851, 0.37192333],
[ 0.03797218, 0.33612275]], dtype=float32)>
"""
您会注意到,四个样本中的每一个都只有一个输出——其他两个时间步长在哪里?为了得到这些,我们需要使用return_sequences=True
:
tf.random.set_seed(42)
inp = Input(shape=x.shape[1:])
lstm = LSTM(8, return_sequences=True)(inp)
out = Dense(2)(lstm)
mdl = Model(inputs=inp, outputs=out)
mdl(x)"""
<tf.Tensor: shape=(4, 3, 2), dtype=float32, numpy=
array([[[-0.08234972, 0.12292314],
[-0.05217044, 0.19100665],
[-0.06428523, 0.3131591 ]],[[ 0.0381453 , 0.26402596],
[ 0.04725918, 0.34620702],
[-0.04120642, 0.3528567 ]],[[-0.21114576, 0.08922277],
[-0.02972354, 0.24037611],
[-0.04273851, 0.37192333]],[[-0.06888272, -0.01702049],
[ 0.0117887 , 0.10608622],
[ 0.03797218, 0.33612275]]], dtype=float32)>
"""
想要访问 LSTM 的隐藏状态也很常见——这可以使用参数return_state=True
来完成。
我们现在得到了三个张量——网络的输出,LSTM 隐藏态和 LSTM 晶胞态。隐藏状态的形状等于 LSTM 中的单位数:
tf.random.set_seed(42)
inp = Input(shape=x.shape[1:])
lstm, hstate, cstate = LSTM(8, return_sequences=False, return_state=True)(inp)
out = Dense(2)(lstm)
mdl = Model(inputs=inp, outputs=[out, hstate, cstate])
out, hstate, cstate = mdl(x)print(hstate.shape)
# (4, 8)print(cstate.shape)
# (4, 8)
如果您想在每个时间步访问隐藏状态,那么您可以将这两个结合起来,同时使用return_sequences=True
和return_state=True
。
哪些超参数对 LSTM 图层很重要?
对于 LSTM 图层,主要的超参数是单位数。单元的数量将决定层的容量和隐藏状态的大小。
虽然不是超参数,但在处理 LSTMs 时包含梯度裁剪会很有用,以处理可能随时间反向传播而发生的爆炸梯度。使用较低的学习速率来帮助管理梯度也是常见的。
什么时候我应该使用 LSTM 层?
处理序列数据时,LSTM(或其近亲 GRU)是一种常见的选择。LSTM 的一个主要缺点是他们训练缓慢。
这是因为处理序列不容易并行化,因为误差信号必须通过时间反向传播。
LSTM 的另一个有用特征是学习隐藏状态。这可以被其他模型用作未来的压缩表示——例如在 2017 年世界模型论文中。
注意力是我们四层中最年轻的一层——目前深度学习阶段开发的唯一一层架构。
自 2015 年推出以来,注意力已经彻底改变了自然语言处理。
首先与基于 LSTM 的 seq2seq 模型结合使用,还关注为变压器提供动力——这是一种神经网络架构,形成了 Open AI 的 GPT 系列语言模型的主干。
注意力很重要,因为它是一种有效的无递归序列模型——避免了随时间反向传播的需要,使并行化更容易,训练更快。
注意层的直觉和归纳偏差是什么?
注意力是一个简单而强大的想法——当处理一个序列时,我们应该选择从序列的哪一部分获取信息。直觉很简单——序列的某些部分比其他部分更重要。
以机器翻译为例,将德语句子Ich bin eine Maschine
翻译成英语I am a machine
。
在预测译文中的最后一个单词machine
时,我们所有的注意力都应该放在源句的最后一个单词Maschine
上。翻译这个单词时,查看源序列中较早的单词是没有意义的。
如果我们举一个更复杂的例子,把德语Ich habe ein bisschen Deutsch gelernt
翻译成英语I have learnt a little German
。在预测我们英语句子的第三个标记(learnt
)时,要注意德语句子的最后一个标记(gelernt
)。
将德语翻译成英语时要注意——作者图片。
那么我们的注意层给了我们什么样的归纳偏差呢?注意力的一个归纳偏差是基于相似性的对齐 —注意力层根据事物的相似程度选择看哪里。
注意力的另一个诱导偏差是限制&优先化信息流。正如我们将在下面看到的,softmax 的使用迫使注意力层对信息流进行权衡——一个地方的权重越大,另一个地方的权重就越小。
在完全连接的层中没有这样的限制,其中增加一个权重不会影响另一个。完全连接的层可以允许信息在后续层中的所有节点之间流动,并且理论上可以学习与关注层相似的模式。然而,我们现在知道,理论上不注意意味着它将在实践中发生。
注意力层是如何工作的?
注意层接收三个输入:
- 查询 =我们要找的东西,
- key =我们比较查询的对象,
- 价值=我们所重视的东西。
注意力层可以被认为是按顺序排列的三个机制:
- 查询和关键字的对齐(或相似度)
- softmax 将排列转换成概率分布
- 根据对准选择按键
关注层的三个步骤——对齐、softmax &键选择——作者图片。
不同的注意层(如加性注意或点积注意)在对齐步骤中使用不同的机制。softmax & key 选择步骤对于所有关注层都是通用的。
查询、键和值
同样,理解时间步长是理解递归神经网络的关键步骤,理解查询、键和值的含义是注意力的基础。
一个很好的类比是 Python 字典。让我们从一个简单的例子开始,我们:
- 查询
dog
的 - 分别与
dog
或cat
的键和1
或2
相匹配 - 并且基于对
dog
的查找来选择2
的值
在上面的例子中,我们为我们的查询'dog'
找到了一个精确的匹配。然而,在神经网络中,我们不是在与字符串打交道——我们是在与张量打交道。我们的查询、键和值都是张量:
现在,我们的查询没有精确匹配— 我们可以计算查询和关键字之间的相似度(即对齐),并返回最接近的值,而不是使用精确匹配:
小的技术细节——通常键被设置为与值相等。这仅仅意味着我们正在进行相似性比较的数量也是我们将关注的数量。
注意机制
到目前为止,我们知道关注层包括三个步骤:
- 基于相似性的比对,
- softmax 创建注意力权重,
- 根据关注度选择值。
第二和第三步是所有注意力层共有的— 差异都发生在第一步——相似性的比对是如何完成的。
我们将简要介绍两种流行的机制——加法注意力和点积注意力。要更详细地了解这些机制,请查看优秀的关注?立正!王莉莲。
附加注意力
注意力的第一次使用(称为 Bahdanau 或附加注意力)解决了 seq2seq 模型的一个限制,即使用固定长度的上下文向量。
正如 LSTM 部分所解释的,seq2seq 模型中的基本过程是将源句子编码成固定长度的上下文向量。问题是来自编码器的所有信息都必须通过固定长度的上下文向量。来自整个源序列的信息通过编码器和解码器之间的上下文向量被压缩。
在 Bahdanau et。al 2015,附加注意力用于学习所有编码器隐藏状态和解码器隐藏状态之间的对准。随着序列被处理,这种对齐的输出在解码器中被用于预测下一个令牌。
点积注意力
第二种类型的注意力是点积注意力——变压器中使用的对齐机制。点积注意力层不使用加法,而是使用矩阵乘法来度量查询和关键字之间的相似性。
点积的作用类似于键和值之间的相似性——下面是一个小程序,它绘制了随机数据的点积和余弦相似性:
余弦相似度和随机向量点积之间的关系——作者创建。
用 Keras 功能 API 实现单个注意力头
点产品的关注是重要的,因为它形成了变压器的一部分。正如你在下图中看到的,变压器使用了多个缩放的点积注意力。
变形金刚中使用的多头注意力层— 瓦斯瓦尼等人 2017
下面的代码演示了没有缩放的单个头的机制——有关 Tensorflow 2 中多头注意力层&转换器的完整实现,请参见语言理解转换器模型。
import numpy as np
import tensorflow as tf
from tensorflow.keras import Input, Model
from tensorflow.keras.layers import Denseqry = np.random.rand(4, 16, 32).reshape(4, -1, 32).astype('float32')
key = np.random.rand(4, 32).reshape(4, 1, 32).astype('float32')
values = np.random.rand(4, 32).reshape(4, 1, 32).astype('float32')q_in = Input(shape=(None, 32))
k_in = Input(shape=(1, 32))
v_in = Input(shape=(1, 32))capacity = 4
q = Dense(4, activation='linear')(q_in)
k = Dense(4, activation='linear')(k_in)
v = Dense(4, activation='linear')(v_in)score = tf.matmul(q, k, transpose_b=True)
attention = tf.nn.softmax(score, axis=-1)
output = tf.matmul(attention, v)mdl = Model(inputs=[q_in, k_in, v_in], outputs=[score, attention, output])
sc, attn, out = mdl([qry, key, values])
print(f'query shape {qry.shape}')
print(f'score shape {sc.shape}')
print(f'attention shape {attn.shape}')
print(f'output shape {out.shape}')
"""
query shape (4, 16, 32)
score shape (4, 16, 1)
attention shape (4, 16, 1)
output shape (4, 16, 4)
"""
这种架构也适用于不同长度的查询(现在是长度8
而不是16
):
qry = np.random.rand(4, 8, 32).reshape(4, -1, 32).astype('float32')
sc, attn, out = mdl([qry, key, values])
print(f'query shape {qry.shape}')
print(f'score shape {sc.shape}')
print(f'attention shape {attn.shape}')
print(f'output shape {out.shape}')
"""
query shape (4, 8, 32)
score shape (4, 8, 1)
attention shape (4, 8, 1)
output shape (4, 8, 4)
"""
注意层中哪些超参数是重要的?
使用如上所示的注意力头时,需要考虑的超参数有:
- 用于转换查询、值和键的线性图层的大小
- 注意机制的类型(如加法或点积)
- 如何在 softmax 之前缩放对齐(通常使用层长度的平方根)
什么时候应该使用关注层?
任何顺序问题都应该考虑注意层。与递归神经网络不同,它们可以很容易地并行化,从而加快训练速度。快速训练意味着更便宜的训练,或者相同计算量的更多训练。
转换器是一个没有递归的序列模型(它不使用 LSTM),允许它被有效地训练(避免随时间反向传播)。
关注层的另一个好处是能够使用对齐分数来提高可解释性。
我希望你喜欢这篇文章,并发现它很有用。下面是总结文章的简短表格:
感谢阅读!如果你喜欢这篇文章,请随时在 Medium 上关注我,或者在 LinkedIn 上与我联系。
请务必查看我的其他帖子:
[## 产生数据科学项目想法的七个步骤
通过这七个步骤找到数据科学组合项目创意
towardsdatascience.com](/seven-steps-to-generate-data-science-project-ideas-8fb69400634d) [## 应该用 Python pathlib 还是 os?
两个 Python 路径库之间的决斗
better 编程. pub](https://betterprogramming.pub/should-you-be-using-pathlib-6f3a0fddec7e) [## 你应该知道的 3 个不常见的 Bash 技巧
使用这些未充分利用的 Bash 模式,在终端上输入更少的内容
better 编程. pub](https://betterprogramming.pub/3-uncommon-bash-tricks-that-you-should-know-c0fc988065c7)
最初发表于【https://adgefficiency.com】。
获取数据科学项目想法的指南
原文:https://towardsdatascience.com/a-guide-to-getting-data-science-projects-ideas-9ba5aaeafa61?source=collection_archive---------28-----------------------
如何提出自学、作品集或商业创意?从拥有太多的人那里。
照片由来自 Pexels 的安德里亚·皮亚卡迪奥拍摄
当写关于学习或打破进入数据科学时,我总是建议建立项目。
这是学习和展示技能的最佳方式。
但是我经常收到读者的来信,问我“我到底是如何为我的项目想出点子的?”
任何经验丰富的企业家或工程师都会告诉你,他们有太多的想法。但是当你开始的时候并不总是容易的。
以下是我个人的一些想法。
参加社交活动,与人交谈
大多数人出人意料地愿意分享自己的想法。你只需要问一下。
我在社交活动中的默认问题是,“你在做什么或试图解决什么?”
上周在一次虚拟活动中,我与之交谈的每一个非技术人员都分享了他们想要构建的 ML 用例。
现在不要窃取任何人的想法。但是如果你已经花了几个小时学习数据科学,考虑免费帮助别人。你将获得可以写进简历的经验,以及可能对你的职业生涯有用的人脉。
成功人士乐于分享想法。他们明白世界上有无数的问题需要解决,分享不是零和游戏。
利用你的爱好和兴趣产生想法
许多伟大的想法来自于融合不同领域的专业知识。
例如,神经网络的发明者杰弗里·辛顿有心理学背景,他从中汲取了许多关于人工智能的早期想法。
你怎么能把这个应用到你自己的兴趣上呢?
就我个人而言,我喜欢我的狗、羽毛球和烹饪。我也知道机器学习领域的一般话题。因此,我会尝试将一种类型的 ML 与我的每个爱好相匹配,以产生一个想法。
- 我的狗——用机器学习对我的狗的不同吠叫、皱领和咆哮的音频记录进行分类。
- 羽毛球——使用机器学习检测某人挥动羽毛球拍的视频是否有适当的形式。
- 烹饪——按国家对食物图像进行分类。
如果你深入挖掘,这些都可能是非常有趣的项目。
所以问问你自己,你对什么感兴趣?数据科学能帮助你做得更好,或者提取有趣的灵感吗?
解决日常工作中的问题
你现在的工作可能不在数据科学领域。但这并不意味着没有有趣的数据科学问题需要解决。
每个公司都有手动操作任务,渴望实现自动化。如果你自己没有,你营销或客户服务部门的同事可能会有。你能帮助他们吗?
考虑自动化、决策树或数据可视化是否能帮助您组织中的某个人。
如果这超出了您的正常范围,您可能需要在自己的时间内处理它。但是,如果它增加了价值并给你带来了经验,这是一个很小的代价。
当我为一家电子商务公司管理商业智能时,我想进入软件工程领域。因此,我开始在周末编写代码,搜集销售类似产品的竞争对手网站,并自动生成关于我们定价过高的产品的报告。然后我把报告发给我们的采购部门,这样他们就可以降低价格——这个项目帮助我找到了下一份工作。
深入你目前的工作,你几乎可以保证找到一个可以应用数据科学的项目。
熟悉数据科学工具包
即使您不知道每个模型是如何工作的,了解 ML 和数据科学保护伞下的一般主题也是有价值的。
这让你有能力将这些模型应用到你周围的世界。
例如,我知道 NLP 包括“文本分类”、“信息检索”和“问答系统”。
所以当我心中有一个数据集(即:Reddit 线程)时,就很容易想到潜在的应用并产生初步的想法。
一旦你有了高级工具包,想出点子就变得更加容易了。
解决自己的数据科学问题
你在寻找数据科学工作时遇到了什么问题?机器学习能帮助你吗?
也许你可以收集工作公告板,对工作是否与数据科学相关进行分类,并对工作要求进行分析。
这将是一个了不起的项目!
你还可以添加竞争分析,显示公司之间的招聘差异,并展示给你想为之工作的公司。
作为一个雇佣工程师的人,我很想在某人的投资组合中看到这样一个项目的结果。
透过数据科学家眼镜看世界
当你在日常生活中四处走动时,问问你自己什么可以被分析、测试或自动化。
给室内植物浇水:你能分析土壤湿度以优化植物生长吗?
购物:百货公司可以用机器学习来检测盗窃吗?
烹饪:你冰箱内部的照片能发现哪些食材需要补充吗?
然后选择项目中最小的组件,并实际尝试构建它。
有无数的想法可以偶然发现。你只需要正确的心态去看待它们。
结论
当你刚起步时,想出点子是很难的。我知道是因为我曾经在那里。
但是要明白——所有伟大的想法都来自真实的经历。真空中没有想法。
这就是为什么放下你的笔记本电脑,走出去和人们交谈是很重要的。
经验丰富的企业家有太多的想法,因为他们已经在许多项目上工作,并在不同领域之间交叉传授想法。
最终,你也会有太多想法的时候。到了那里,分享一些吧!
数据科学家 Git 指南
原文:https://towardsdatascience.com/a-guide-to-git-for-data-scientists-fd68bc1c729?source=collection_archive---------28-----------------------
入门
你再也不用害怕 git 了。
照片由扬西·敏在 Unsplash 上拍摄
在相当长的一段时间里,git 对我来说是一个模糊的、可怕的东西。这有点像拿着一堆精美的瓷器走在绷紧的绳子上。是的,我知道如何做git add
、git commit
和git push
。但是如果我不得不做除此之外的任何事情,我会很快失去平衡,摔下精美的瓷器,git 将不可避免地把我的项目摔成无法辨认的碎片。
如果您是一名开发人员,您可能非常了解 git。但是 git 现在已经成为编程和协作领域的任何人不可或缺的技能,尤其是在数据科学领域。
所以我最终咬紧牙关,试图理解 git 更全面的情况,以及它的命令对我的代码做了什么。幸运的是,事实证明这并不像我想象的那么复杂,通过纠正我潜在的心理模型,我在处理新项目时更有信心,更少焦虑。
git 的四个领域
git 中有四个区域:存储区、工作区、索引和存储库。
作者图片
典型的 git 工作流从左到右工作,从工作区开始。当您对 git 存储库中的文件进行任何更改时,这些更改都会显示在工作区中。要查看哪些文件随您创建的新文件一起更改,只需执行git status
。要显示文件中具体更改了什么的更详细信息,只需执行一个git diff [file name]
。
一旦您对您的更改感到满意,您就可以使用git add
命令将更改后的文件从工作区添加到索引中。
作者图片
索引的功能就像一个临时区域。它之所以存在,是因为您可能正在尝试一些东西,并且在工作区中更改了许多代码,但是您不一定希望所有这些更改都出现在存储区中。
因此,我们的想法是有选择地将您想要的更改添加到索引中,并且您添加的更改最好是一些逻辑单元或相关事物的集合。例如,您可能决定添加所有与您用 Python 编写的新预处理函数相关的文件。
一旦将所有相关文件添加到索引中,最后通过执行git commit -m 'Explanation of my changes'
将它们移动到存储库中。您应该看到现在索引和存储库之间没有区别了——您可以用git diff --cached
来验证这一点。
作者图片
犯了错误
但是生活并不那么理想。最终你会用一个你想改变的不恰当的信息做出承诺,或者你会决定你添加的所有新东西完全破坏了一切,现在你想回到以前的样子。曾经想要将同事的更新包含到您正在处理的代码中,却发现存在文件冲突?
您可能见过一些 git 命令,如rebase
、reset
和revert
。如果这些命令吓到了你,你并不孤单。其中一些功能强大,如果您不知道如何使用它们,可能会破坏您的项目。但是不要担心,你将会学习如何使用它们。😊
向后移动
到目前为止,您习惯使用的命令git add
和git commit
已经将您的代码从左向右移动了。我们现在探索允许您在 git 区域中向后移动的命令,以便撤销您对文件所做的更改,或者完全恢复到以前的提交。
假设您正在处理一个文件,并意识到您所有的新更改都不会成功。您意识到您可以返回到上次提交时的文件版本,而不是手动计算如何撤销所有的更改。所以你执行git reset --hard HEAD [file name]
。
让我们解开这个命令。HEAD
指您之前的提交。这很有用,因为否则您将不得不寻找提交散列(尽管您可以使用git log
很容易地找到它)。
把reset
想象成那些起重机爪机器中的受控爪,你可能很高兴在小时候使用,或者更确切地说是被使用,以获得令人垂涎的填充动物玩具。
图片来自易贝
reset
允许您从存储库中的特定提交中挑选您想要的文件。然后,通过使用以下标志命令之一,您可以选择将这些文件放入哪个 git 区域:--hard
、--mixed
和--soft
。
正如你在上面看到的,git reset --hard HEAD [file name]
将从之前的提交中获取file name
,并将其应用于索引和工作区。
作者图片
另一方面,git reset --mixed HEAD [file name]
将从之前的提交中获取file name
,并将其应用于索引。**
作者图片
最后,git reset --soft HEAD [file name]
将从之前的提交中获取file name
,并将其应用于存储库。**
作者图片
恢复到以前的提交
假设您将一些东西推送到您的存储库中,但是它没有工作。只需执行一个git revert [commit hash]
,就可以轻松地返回到代码正在运行的前一次提交。记住,您可以通过执行git log
来找到您的提交散列。
就这么简单,但是有一点要注意。还原不会擦除您选择提交之前的任何历史记录。相反,它只是使用您选择恢复到的上一个提交的确切状态创建一个新的提交。这很好,因为它不会弄乱您的任何 git 历史。
编辑您的提交历史
在 git 的旅程中,您不需要花很长时间就能遇到一些您希望能够撤销的事情。例如,您向本地存储库提交了一个文件,但是您弄乱了提交消息。或者说,您进行了许多非常小的提交,您宁愿将它们组合成一个提交。这就是git rebase
大放异彩的地方。
假设您有一组小提交。
作者图片
您希望将它们合并在一起,然后给合并的提交一个新消息。要做到这一点,只需做git rebase --interactive origin/main
。
作者图片
那就去做我们想要的改变吧。在这种情况下,我们希望将最后两次提交压缩到第一次提交中。
作者图片
完成此操作后,继续保存文件并关闭,这将带您到一个新窗口来编辑最终的提交消息。
作者图片
我们对最终的提交消息进行了更改。
作者图片
现在您可以看到,我们之前的三次提交现在已经被合并或压缩为一次。
作者图片
重命名远程分支
假设有一个您想要重命名的分支,它已经被推送到您在 GitHub 或其他地方的远程存储库中。假设只有您一个人在处理这个分支(因为更改远程历史可能会有一些不好的影响),您可以通过执行以下操作来更改分支名称:
git checkout [your branch]
git branch -m [new branch name]
git push origin :[your branch] [new branch name]
git push origin -u [new branch name]
典型的 git 工作流
假设你和你的团队是 GitHub 中一个资源库的贡献者。您已经将一个main
分支作为您的默认主分支。但是你想知道如何相互协作,这样你就不会覆盖彼此的工作。以下是我过去经常使用的一个工作流程:
- 首先确保
main
分支与git checkout main; git pull
保持同步。 - 用
git checkout -b [your branch name]
从main
分支创建一个新分支。 - 添加那个新特性或者修复那个 bug,然后做一个
git push
把它推送到你的分支。 - 当您准备好将您的更改合并到
main
分支中时,在 GitHub 中创建一个 pull 请求,以便您的团队成员可以查看您的代码并提供任何改进建议。如果看起来不错,GitHub 会让你把修改合并到main
里。 - 现在只需清理您的本地存储库:1)用刚刚合并到远程
main
分支中的变更更新您的本地main
分支,用git checkout main; git merge your-branch
2)删除您工作的本地分支,git branch -d [your branch name]
。
现在,只需重复该工作流程,进行您想要的任何更改。👍
结束语
如果你想学习更多关于 git 的知识或者喜欢一个交互式的环境,请随意查看学习 Git 分支。
如果你想知道如何处理其他一些棘手的 git 场景,请查看 Dangit,git!?!。
到目前为止你已经学到了很多。您已经了解了 git 的四个区域,在这些区域中移动您的更改的命令,如何恢复到以前的提交,编辑您的提交历史,重命名分支,并且您已经看到了典型的 git 工作流的样子。
我希望这篇文章对您有所帮助,并且您已经对这些 git 命令的作用有了更好的理解!
*[## 想在数据科学方面变得更好吗?
当我在我发布独家帖子的媒体和个人网站上发布新内容时,请单击此处获得通知。](https://bobbywlindsey.ck.page/5dca5d4310)*
原载于 2020 年 10 月 7 日【https://www.bobbywlindsey.com】。
可解释机器学习指南—第 1 部分
原文:https://towardsdatascience.com/a-guide-to-interpretable-machine-learning-1-139eae78113a?source=collection_archive---------47-----------------------
我们为什么要相信模型?
机器学习模型目前正以巨大的速度变得流行。它们现在被用来解决各种领域的各种问题。在这个越来越受欢迎并因此在我们日常生活中变得越来越重要的时刻,有一个潜在的危险,现在也是非常重要的:机器学习模型的可解释性。
最近,我们看到了图像处理如何用于安全部门和卫生部门,回归和分类模型如何用于股票市场和投资部门。如果我们仔细观察,我们会依赖机器学习来做出肯定会影响我们的重要决定。所以,问题来了,我们为什么要相信模型?
换句话说,我们为什么要依赖一个智能算法做出的决定,甚至不知道它是如何操作的?你可以说有各种各样的算法,比如决策树和线性回归,它们非常容易理解和解释。但是,在当前世界中,研究人员和数据科学家正在不断尝试解决具有挑战性的问题,这些问题无法通过可解释的模型有效解决,因此需要非常复杂的算法或基于定制神经网络的算法。如果我们环顾四周,我们会发现大多数情况下,使用复杂的黑盒模型,我们很难回答这个问题“算法是如何做到的?”
事实证明这是一个合理的问题。通常,在设计模型时,数据科学家会关注一些问题或关于某些特征的一些规定,他们希望模型能够学习并用于预测。比如我可能喂人口预测“是否在该地区开店”。原因是我可能认为,如果人口多,我的销售额就会高,所以这两者之间的相关性非常高,所以我的模型将学习这一特征,该特征的重要性将会很高。我训练我的模型,它给了我很高的准确性,但它可能没有按照计划的方式学习。所以,我们需要在几种情况下确定这些事情,以增加准确性,并确定我们的预测。
我举一个经典的例子,在一个“西伯利亚哈士奇”和“狼”的图像分类中,设计了一个模型。它给出了非常高的精确度。模型分析的时候发现,模型从来没有把哈士奇和狼分类。它划分了“下雪”或“不下雪”。雪被预言为哈士奇,无雪为狼。大多数哈士奇图像有雪,准确性非常好。
所以,从上面的例子我们可以理解,实际解释我们的模型有多重要。
问题的解决方法
处理机器学习模型的解释的许多方法已经发展了多年。不同的方法使用不同的逻辑和理论来解释难以理解的“黑盒”算法,如神经网络、Xgboost 和随机森林。两种最重要和最受欢迎的方法是石灰和 SHAP。它们被用来解释局部的或观察到的预测。换句话说,它们给了我们一个清晰的直觉,让我们知道给定的特征如何影响我们模型中的预测,以及该特征对我们的模型有多重要。
在这篇文章中,我们将详细而简要地谈论石灰和 SHAP。我们将尝试使用著名的泰坦尼克号数据集来解释。
泰坦尼克号的沉没是历史上最臭名昭著的海难之一。
1912 年 4 月 15 日,在她的处女航中,被广泛认为是“不沉”的皇家邮轮泰坦尼克号在与冰山相撞后沉没。不幸的是,没有足够的救生艇容纳船上的每个人,导致 2224 名乘客和船员中的 1502 人死亡。虽然幸存有一些运气成分,但似乎某些群体比其他群体更有可能幸存。
在这个挑战中,我们要求你建立一个预测模型来回答这个问题:“什么样的人更有可能生存?”使用乘客数据(即姓名、年龄、性别、社会经济阶层等)。
现在,让我们先谈一谈数据集,然后再谈我们的目标。
数据预处理和准备
数据集看起来像这样,它有 12 列。“幸存”是我们的目标栏目,其他是专题栏目。现在,特性列需要一些预处理。
数据集提取片段:
import pandas as pd
df1=pd.read_csv('train.csv')
df2=pd.read_csv('test.csv')
df=pd.concat([df1,df2],axis=0)
我们将删除 PassengerID,因为它没有任何相关性。下一步,我们将采取“姓名”列,并根据他们的头衔将他们分配,类,像“夫人”,将类 1,“先生”类 2,等等。我们可以使用下面的代码片段做到这一点。
i=0
name=[]
while i<len(df):
#print(df.iloc[i]['Name'].type)
if "Mrs." in df.iloc[i]['Name']:
name.append(str(1))
print("a")
elif 'Mr.' in df.iloc[i]['Name']:
name.append(str(2))
print("b")
elif "Miss." in df.iloc[i]['Name']:
name.append(str(3))
print("c")
elif "Master." in df.iloc[i]["Name"]:
name.append(str(4))
print("d")
else:
name.append(str(5))
i+=1
df=df.drop(['Name'],axis=1)
df['name']=name
现在,我们转到 SibSp,这里我们也将创建一个具有两个类的特征,具有用 1 表示的兄弟,没有用 0 表示的兄弟,并将其包含在特征集中,删除原始特征。我们需要注意的一件事是,这些特征中的大多数都有 NaN,所以我们需要首先填充空值以避免错误。代码片段:
i=0
siblings=[]
df.fillna(0)
while i<len(df):
if df.iloc[i]['SibSp']>0:
siblings.append(str(1))
else:
siblings.append(str(0))
i+=1
df=df.drop(["SibSp"],axis=1)
df["Siblings"]=siblings
接下来,我们对 Parch 特性做同样的事情,我们设计了两个类,用 1 表示父类,用 0 表示父类,并使用列作为特性。
i=0
parent=[]
df.fillna(0)
while i<len(df):
if df.iloc[i]['Parch']>0:
parent.append(str(1))
else:
parent.append(str(0))
i+=1
df=df.drop(["Parch"],axis=1)
df["Parent"]=parent
我们选择“年龄”特征,也有一些 NaNs,我们将使用年龄列的平均值来填充它们。
df['Age'].fillna(df['Age'].mean())
然后,我们将创建一个具有 5 个类别的新特征列来分类和移除年龄的可变性质。我使用了给定的阶级界限:
年龄< 15 岁:1 级
15≤年龄< 30:2 级
30≤年龄< 45:3 级
45≤年龄< 60:4 级
年龄≥60 岁:5 级
15 岁以下的“年龄”归为 1 等。
代码:
i=0
age=[]
while i<len(df):
if df.iloc[i]['Age']<15:
age.append(str(1))
elif df.iloc[i]['Age']<30:
age.append(str(2))
elif df.iloc[i]['Age']<45:
age.append(str(3))
elif df.iloc[i]['Age']<60:
age.append(str(4))
else:
age.append(str(5))
i+=1
df['age']=age
df=df.drop(['Age'],axis=1)
对于“Fare”特性,我们将执行与“age”特性相同的操作。我们将用平均值填充 NaN,并将其分类到一些固定的桶中。以下是我对桶边界的估计。
票价<15: Class 1
15≤Fare<55: Class 2
55≤Fare<120: Class 3
120≤Fare<190: Class 4
Fare≥190: Class 5
Next, if we check the “Tickets” column, we will see a few special tickets with letters, and others are numeric. I have labeled the completely numeric ones 1 else 0. Snippet:
i=0
ticket=[]
while i<len(df):
if df.iloc[i]['Ticket'].isnumeric():
ticket.append(str(1))
else:
ticket.append(str(0))
i+=1
df['ticket']=ticket
df=df.drop(['Ticket'],axis=1)
Next, we do something similar to the cabin feature. Most of the entries in the “Cabin” feature are empty. We label the empty ones as 0 and others as 1.
z=0
df['Cabin'].fillna("NA")
cabin=[]
while z<len(df):
print(df.iloc[z]['Cabin'])
if 'NA' in str(df.iloc[z]['Cabin']):
cabin.append(str(0))
else:
cabin.append(str(1))
z+=1
Now, our preprocessing is complete. After the preprocessing our data looks like this.
We will now drop the Survived column and apply encoding on the categorical features. After application, we will obtain a Feature set X, of 31 columns i.e 31 features and a target set Y, of 1 column, Survived.
Index(['Survived', 'Pclass_1', 'Pclass_2', 'Pclass_3', 'Sex_female',
'Sex_male', 'Embarked_C', 'Embarked_Q', 'Embarked_S', 'name_1',
'name_2', 'name_3', 'name_4', 'name_5', 'Siblings_0', 'Siblings_1',
'Parent_0', 'Parent_1', 'age_1', 'age_2', 'age_3', 'age_4', 'age_5',
'fare_1', 'fare_2', 'fare_3', 'fare_4', 'fare_5', 'ticket_0',
'ticket_1', 'cabin_0', 'cabin_1'],
dtype='object')
These are our 31 features.
We split our dataset in X_train, Y_train, X_test, and Y_test.
from sklearn.model_selection import train_test_splitX_train,X_test,Y_train,Y_test=train_test_split(X,Y,test_size=0.3, random_state=42)
Thus we have processed our dataset and are ready for operations.
We go back to our application.
LIME
LIME stands for Linear Model Agnostic Explanation. It is used for 当地口译。它用于分析和解释底层黑盒模型的决策及其基于特定观察的预测,比如训练或测试数据集的特定行。现在,问题来了,它是怎么做到的?正如我们之前注意到的,有几个模型非常容易解释。LIME 使用这些可解释的模型来预测黑盒模型。
LIME 使用决策树和逻辑回归等模型来克隆黑盒模型给出的预测。它接收单个观察值,并通过对特征值进行一定程度的更改来创建一组观察值。因此,在尝试了所有的组合之后,LIME 获得了一个全新的特性集。然后将该特征集传递给黑盒模型,并获得相应的预测。现在,这些预测成为可解释模型的 Y 训练集或目标集,而特征集成为 X 训练集。
现在,LIME 有几个模型,如决策树、线性回归、套索回归和逻辑回归。目标可解释模型是所有可解释模型中产生最小损失的模型。这是因为最小损失函数意味着具有最大准确性的模型是克隆黑盒模型最好的模型。现在,由于可解释模型的行为类似于黑盒模型,解释它将给出黑盒模型的结果。
这是石灰的解释公式。这里,观察值 x 的解释由模型 f 或 g 中的一个示出,这取决于哪个将产生最小损失函数,并且 sigma(g)描述了保持尽可能低的解释模型的复杂性。现在,由 LIME 产生的数据的变化也给了解释模型获得特征边界的自由,例如,如果特征的值小于值 x,则它是 A 类,否则它是 b 类。
也有一些缺点。LIME 的问题在于它是一个局部算法,所以它的解释对整个数据集来说并不成立。
解释算法是如何工作的
一些最好的解释算法是决策树和逻辑回归。这里我们就来说说这两个算法。
决策树:用于非线性数据集。现在,该树接收一个数据集,并根据不同要素的边界值继续分割数据集。它多次分割数据集,并创建几个数据子集。最后的子集是叶节点。他们是分类班。内部节点是拆分节点。训练有助于树判断每个特征的边界值及其对决策路径的影响。
照片由克里斯托弗拍摄
因此,每个节点代表一个要素和一个与该要素相对应的值,该值充当边界。现在,每个决策树都想最小化基尼系数。基尼系数是实际值与预测值的差值。因此,在每个节点之后,如果我们试图判断与父节点相比系数减少了多少,我们将清楚地了解节点的权重。节点的权重描述了特征的重要性。
Logistic 回归:是基于线性回归算法的分类。这不适用于非线性模型。在线性回归中,我们用一个方程表示一个 n 维超平面来预测值。
Y=b0+b1x1+b2x2+………+bnxn
这里 b0 是截距,特征‘I’的 b{i}是回归中特征的系数或权重。它使用线性回归生成插值。
在分类中,我们预测概率,因此我们使用逻辑函数将值压缩在 0 和 1 之间。
就像这样,
照片由克里斯托弗拍摄
因此,我们获得概率为
现在,我们处理事件发生的概率和事件不发生的概率之比。P(y=1)/P(y=0)。这个比率叫做赔率。
这是我们的方程式。这里 p(y=1)/p(y=0) =n 意味着事件发生的几率是事件不发生几率的 n 倍。
现在,如果我们将特性 j (xj)的值增加 1,则等式变为:
这导致了,
因此,如果我们将一个特征增加 1 个单位,它对概率的影响将是其权重的指数。所以,它的贡献是它的重量的函数。因此,我们可以很容易地使用逻辑回归中的权重来获得特征贡献。
结论
在的下一部分,我们将看到可解释模型的应用和实际实现。我们还将看到 SHAP 应用程序。
可解释机器学习指南—第二部分
原文:https://towardsdatascience.com/a-guide-to-interpretable-machine-learning-2-fa3c4489fb53?source=collection_archive---------22-----------------------
石灰的应用
在这一部分,我们将介绍石灰的应用。我们已经在本文的第 1 部分看到了 Titanic 数据集的数据预处理和 LIME 的理论和工作。我们有了预处理过的数据。接下来,我们转到石灰应用程序。
神经网络
首先,我们将使用 LIME 应用程序来设计基于神经网络的模型。
这是我们的神经网络课。我用过 TensorFlow Keras 的几层。我们的输入层接受 31 列的数据集。它有 4 个密集层,输出层有 1 个神经元来决定“存活”或“不存活”。输出函数为 sigmoid。我们将使用 Adam 优化器和二元交叉熵。
现在我们将调用并训练模型。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import accuracy_score,f1_scoremodel_nn=Neural_Network(X_train,Y_train, X_test,Y_test)
print(model_nn.predict_classes(X_train).astype(float))
在我们的训练集上,“predict_classes”函数生成一个二维列表。
如果我们观察,每个元素有 2 个值,第一个值是事件发生的概率,第二个值是不发生的概率。
现在,我们去吃酸橙。
import lime.lime_tabular
classes=['Survived','Not_Survived']df_k=df.drop(['Survived'],axis=1)
all_feat=df_k.columns
#model_gb.fit(X_train,Y_train)
print(model_nn.predict_classes(X_train).astype(float))
predict_fn_nn= lambda x: model_nn.predict_classes(x).astype(float)explainer = lime.lime_tabular.LimeTabularExplainer(X_train,mode='classification',feature_selection= 'auto',
class_names=classes,feature_names = all_feat,
kernel_width=None,discretize_continuous=True)
接下来,我们呼叫解释者。
observation_1=24
exp=explainer.explain_instance(X_test[observation_1], predict_fn_nn, num_features=5,top_labels=1)
exp.show_in_notebook()
这将产生如图所示的结果。现在,这里最左边的方框是两类的预测概率,“幸存”类和“未幸存”类。中间的图表显示了重要的特征及其边界值,而右边的表格是所通过的观察行中实际对应的特征值。
observation_1=42
exp=explainer.explain_instance(X_test[observation_1], predict_fn_nn, num_features=5,top_labels=1)
exp.show_in_notebook()
这是第二个可供参考的例子。
XGBoost
现在,让我们检查 XGBoost 的 LIME 解释器。下面的代码片段用于启动 XGBoost 的解释器。
from xgboost import XGBClassifier
classes=['Survived','Not_Survived']
all_feat=df_k.columns
model_xgb = XGBClassifier()
model_xgb.fit(X_train, Y_train)
predict_fn_xgb = lambda x: model_xgb.predict_proba(x).astype(float)
explainer = lime.lime_tabular.LimeTabularExplainer(X_train,mode='classification',feature_selection= 'auto',
class_names=classes,feature_names = all_feat,
kernel_width=None,discretize_continuous=True)
我们称之为解释者。
observation_1=32
exp=explainer.explain_instance(X_test[observation_1], predict_fn_xgb, num_features=5,top_labels=1)
exp.show_in_notebook()
现在小字体 0.54,0.15 等是特征的对应贡献,值 1.0,0.0 是边界值。
二审:
observation_1=86
exp=explainer.explain_instance(X_test[observation_1], predict_fn_xgb, num_features=5,top_labels=1)
exp.show_in_notebook()
我们也可以用其他形式获得这些结果。
exp.as_map()
结果:
{1: [(3, 0.5441379658340547),
(24, -0.15448119146031272),
(2, -0.1233271814431237),
(9, 0.11870380100373268),
(8, -0.11796994360496856)]}
这提供了这种形式的地图。1 是预测,列表有特征号和重要性。
exp.as_pyplot_figure()
随机森林
我们还将看到一个使用随机森林的实例。
from sklearn.ensemble import RandomForestClassifier
classes=['Survived','Not_Survived']
all_feat=df_k.columns
model_rf = RandomForestClassifier()
model_rf.fit(X_train, Y_train)
predict_fn_rf = lambda x: model_rf.predict_proba(x).astype(float)
explainer = lime.lime_tabular.LimeTabularExplainer(X_train,mode='classification',feature_selection= 'auto',
class_names=classes,feature_names = all_feat,
kernel_width=None,discretize_continuous=True)observation_1=47
exp=explainer.explain_instance(X_test[observation_1], predict_fn_rf, num_features=5,top_labels=1)
exp.show_in_notebook()
用可解释的模型解释
现在,在我们的理论中,我们已经看到一些可解释的模型被用来获得直觉。所以,让我们回溯一下,看看我们是否能得出类似的结果。
现在,我们不能通过调整要素来生成数据集,因为这是由 LIME 模块针对特定观测随机完成的。所以,让我们用整个数据集来试着解释结果。我们将使用我们的神经网络模型来这样做。
model_nn=Neural_Network(X_train,Y_train, X_test,Y_test)
pred=model_nn.predict_classes(X).astype(float)
print(pred)
结果:
[[4.87956345e-01 5.12043655e-01]
[1.00000000e+00 0.00000000e+00]
[9.99990702e-01 9.29832458e-06]
...
[2.51247525e-01 7.48752475e-01]
[3.47714871e-02 9.65228498e-01]
[5.00362515e-01 4.99637485e-01]]
这是我们对整个数据集上每个类的神经网络预测。现在,让我们从结果中得出预测
Pred=[]
for j in pred:
if (j[0]/j[1])>1:
Pred.append(1)
else:
Pred.append(0)
print(Pred)
这些是我们得到的预测。现在,这个列表将作为我们的目标集和整个数据集,没有保留的列作为我们的特征集。因此,实际上我们正在尝试创建一个行为类似于我们的人工神经网络模型的模型。
先用决策树模型来解读吧。
from sklearn.tree import DecisionTreeClassifier
clf = DecisionTreeClassifier(criterion = "gini",
random_state = 100,max_depth=6, min_samples_leaf=8)
clf.fit(X,Pred)
我们用 X 作为训练集,pred 作为预测集来拟合模型。
y_pred_tree = clf.predict(X_test)
accuracy_score(Y_test,y_pred_tree)
这给出了 87%的准确度,这对于我们的目的来说是非常好的。因此,我们的决策树模型表现为 87%的黑盒模型。现在,我们来试着解读一下。
from sklearn import tree
import graphviz
tree_data = tree.export_graphviz(clf, out_file=None,
feature_names=df_k.columns,
class_names=["Survived","Not_Survived"],
filled=True, rounded=True,
special_characters=True)
graph = graphviz.Source(tree_data)
#this will create an iris.pdf file with the rule path
graph.render("titanic")
这将给我们一个可视化的节点形成的树。
这是我们的树形成。每个节点都有一个关于节点的决策,该决策决定所获得的结果。从这里我们可以获得边界值。现在,我们来谈谈特性的重要性。
feat_importance = clf.tree_.compute_feature_importances(normalize=False)
print("feat importance = " + str(feat_importance))
print(len(feat_importance))
结果
feat importance = [0.00000000e+00 3.61136190e-03 1.39727482e-02 2.77128356e-01
0.00000000e+00 1.01837874e-02 3.36657108e-03 0.00000000e+00
3.66875884e-03 0.00000000e+00 4.96683522e-03 3.87192368e-03
0.00000000e+00 4.20667376e-04 4.60591655e-03 8.34158579e-03
0.00000000e+00 4.42596721e-03 6.48457847e-03 0.00000000e+00
8.54240790e-04 2.40717013e-04 0.00000000e+00 6.19429971e-04
6.36079009e-03 8.23858955e-05 0.00000000e+00 7.82349745e-03
3.09307607e-03 6.90860184e-03 0.00000000e+00]
31
这提供了 31 个特性重要性的列表,每个特性有一个值。
import matplotlib.pyplot as plt; plt.rcdefaults()
import numpy as np
import matplotlib.pyplot as pltobjects = df_k.columns
y_pos = np.arange(len(objects))
performance = feat_importancefig, ax = plt.subplots(figsize=(20, 20))
plt.barh(y_pos, performance, align='center', alpha=0.5)
fontsize=14,
plt.yticks(y_pos, objects,fontsize=20)
plt.xticks(fontsize=20)
plt.xlabel('Contributions')
plt.title('Feature Contributions',fontsize=20)plt.show()
上图显示了要素重要性图。因此,我们可以使用决策树从整体上对我们的神经网络模型得出一个非常清晰的直觉。
现在,让我们看看我们是否能从回归模型中得出一些东西。
from sklearn.linear_model import LogisticRegression
model = LogisticRegression(solver='liblinear', random_state=0)
model.fit(X, Pred)
类似于这里的决策树,我们用 X 和 Pred 来复制我们的黑盒模型。
Weights=np.hstack((model.intercept_[:,None], model.coef_))
print(Weights)
print(len(Weights[0]))
结果:
[[ 0.12274084 0.5433339 0.21922863 -0.63982169 1.45315131 -1.33041046
0.0827389 0.22923408 -0.22390968 0.56095332 -1.14391015 -0.04797768
1.28082004 -0.52714469 0.30183458 -0.17909374 0.37075839 -0.24801754
0.37928751 0.22380996 0.12957386 -0.51560858 -0.09432191 -0.18315589
-0.00641827 0.49388734 -0.09299957 -0.08857277 0.10037632 0.02236453
-0.34099133 0.46373217]]32
因此,它返回每个特征的权重和 B0 偏差。这是一个包含 32 个元素的列表。所以,这些是我们的特征重要性。
上面的列表给了我们这个情节。所以我们看到,根据理论,我们可以从可解释的模型中得到直觉。
石灰也可以应用于图像。但是这里的做法有点不同。在那里,改变一个像素无关紧要。因此,形成了一组称为超像素的像素。这些超像素变成灰色,然后再次预测图像。通过这种方式,可以判断图像的哪些部分实际上会影响决策。
SHAP
SHAP 主张“沙普利附加解释”。它基于 Shapley 值,Shapley 值基于博弈联盟理论中的一种方法。它检查特定特征值如何影响模型预测。它首先采用两个特征,并尝试它们的组合,以检查它们如何影响预测,并为它们分配一些重要性。然后,它添加第三个特征,并检查它对预测的影响程度,再次为其分配权重,依此类推。SHAP 树解释器用于获取特性重要性。
import shapshap_values = shap.TreeExplainer(model_xgb).shap_values(X_train)
shap.summary_plot(shap_values, X_train, plot_type="bar")
这是应用 Xgb 产生的特性重要性图。
import shapshap_values = shap.TreeExplainer(model_rf).shap_values(X_train)
shap.summary_plot(shap_values, X_train, plot_type="bar")
这是通过应用随机森林生成的要素重要性图。
红色部分显示要素对 0 或“未存活”类的影响,蓝色部分显示 1 或“存活”类的影响。
结论
这是对人机学习解释库如何运行的基本洞察。希望这些文章有所帮助。
这是 Github 链接。
数据湖指南——现代批量数据仓库
原文:https://towardsdatascience.com/a-guide-to-modern-batch-data-warehousing-extraction-f63bfa6ef878?source=collection_archive---------10-----------------------
照片由 弗拉德 Chețan 发自 像素
使用“功能数据工程”重新定义批量数据提取模式和数据湖
过去几十年,数据分析领域发生了巨大的变革。随着存储成本的降低和云计算的采用,指导数据工具设计的限制变得过时,因此—数据工程工具和技术必须发展。
我怀疑许多数据团队正在进行复杂的项目,以使他们的数据工程栈现代化,并使用他们所掌握的新技术。许多其他公司正在从零开始设计新的数据生态系统,这些公司正在寻求机器学习和云计算的进步所带来的新商机。
pre-Hadoop批处理数据基础架构通常由与其存储紧密耦合的数据仓库(DW)设备(例如 Oracle 或 Teradata DW)、提取转换加载(ETL)工具(例如 SSIS 或 Informatica)和商业智能(BI)工具(例如 Looker 或 MicroStrategy)组成。在这种情况下,数据组织的哲学和设计原则是由诸如 Ralph Kimball 的The Data Warehouse Toolkit(1996)或比尔·恩门的Building The Data Warehouse(1992)等书中概述的成熟方法所驱动的。
我将这种方法与其现代版本进行了对比,后者诞生于云技术创新和降低存储成本。在现代堆栈中,由数据仓库设备处理的角色现在由专门的组件处理,如文件格式(如 Parquet 、 Avro 、胡迪)、廉价云存储(如 AWS S3 、 GS )、元数据引擎(如 Hive metastore)、查询/计算引擎(如 Hive、拖放 ETL 工具不太常见,取而代之的是一个调度器/指挥器(例如 Airflow 、 Luigi )和“特设”软件逻辑来承担这个角色。“ad-hoc”ETL 软件有时出现在单独的应用程序中,有时出现在调度程序框架中,该框架通过设计是可扩展的(气流中的操作符,Luigi 中的任务)。它通常依赖 Spark clusters 或 DWs 等外部计算系统进行大量转换。BI 方面也看到了称为超集的开源替代方案的兴起,有时由 Druid 补充,以创建汇总、在线分析处理(OLAP)立方体,并提供快速只读存储和查询引擎。
存在的理由
我发现自己正在从事从前 Hadoop 堆栈到现代堆栈的迁移。这不仅是一次技术转变,也是一次重大的范式转变。在某些情况下,在建模和架构决策中,我们应该远离过时的智慧和最佳实践,理解我们为什么这样做是很重要的。我发现 Maxime Beauchemin 的资源非常有帮助,学习/理解 Apache Airflow 的设计选择在实现他提倡的方法(Airflow 是由 Maxime 创建的)时带来了很多实际的理解。本指南旨在采用一种固执己见的方法来定义和设计数据湖。
我挑选了一些特定的技术来使本指南更加实用,我希望其中的大部分技术也适用于现代堆栈中的其他工具。选择一种技术而不是另一种技术的动机通常是我的经验(或缺乏经验)的结果。例如,我会提到 AWS 工具,因为这是我有经验的云提供商。
这篇博文定义了 ETL 的 E,并描述了数据湖的角色。
提取,血统
在数据工程中,提取应该是在给定时间点实体状态的未改变快照。
具体来说,它通常涉及调用 API、抓取网站、从安全文件传输协议(SFTP)服务器获取文件、定期对运行数据库的副本运行查询以及从 S3 帐户复制文件。提取的结果存储在一个便宜的、可扩展的、高可用性的云存储中,比如 S3,可以永久保存——或者只要合规允许就保存。这些提取产生的数据构成了数据湖。
数据湖
不同的作家、博客作者和专业人士对“数据湖”和“数据仓库”有不同的定义。有时,他们的角色没有被清楚地陈述或者有重叠——以至于造成混乱,这两个词可以互换使用。数据湖的以下定义很简单,它清楚地将数据湖从数据仓库中分离出来,并将原始数据(数据湖的一部分)从派生的数据集(数据仓库/数据集市的一部分)中分离出来。
数据湖是一个存储库,包含所有由业务产生或收集的未处理的数据。因为此时没有业务逻辑应用于数据,保持不变,如果业务需求发生变化,任何分析(表格、数据科学模型)都可以从该来源重新创建。从不同来源提取数据是必要的,因为从来源获取数据通常是昂贵的(API 调用、缓慢的 SFTP、操作数据库转储),有时是不可能的(API 发展、sftp 变空、操作数据库就地改变记录)。
结构
随着数据的民主化和分析的去中心化,发现湖泊变得非常重要,考虑以下结构:
*s3://myorg-data-lake
├── s3://myorg-data-lake/tweets_mentioning_myorg
└── s3://myorg-data-lake/salesforce_clients*
数据湖消费者希望任何摘录都是“my org-Data-Lake”S3 存储桶中的顶级前缀,以便于浏览。然而,数据不需要放在同一个桶中,因为我们可以使用 Hive metastore 将任何提取注册为同一个模式中的表,提供一个到数据湖的中央接口。
*data_lake
├── data_lake.tweets_mentioning_myorg → s3://myorg-twitter-extracts/tweets_mentioning_myorg
└── data_lake.salesforce_clients → s3://myorg-salesforce-extracts/salesforce_clients*
格式
半结构化和非结构化数据经常被认为是数据湖的一个特征。然而,我相信在提取过程中,转换成一种嵌入了模式的文件格式(比如 Parquet 和 Avro)有很大的好处。模式是定义数据集接口的一种方式,使得多个团队在需要最少通信的情况下更容易使用它。这也是一种执行轻量级验证的方式,验证源系统仍然在生成预期的数据。当模式不再有效时,提取中断,但是它降低了产生错误分析或转换过程中隐藏错误的风险。提取的数据可能已经有了某种模式(数据库和 API 提取),存储为 JSON / CSV 将意味着丢失一些有价值的元数据。
在源系统使以前的数据很快不可用的情况下,提取一次而不进行任何转换,并在原始副本上运行转换。然后,配置单元表可以指向转换后的副本。例如,如果 we 文件来自 SFTP 服务器,并且这些文件在大约 1 小时后消失:
*SFTP
├── file1.csv
└── file2.csvs3://myorg-data-lake
├── s3://myorg-data-lake/sftp_clients/raw/file1.csv
├── s3://myorg-data-lake/sftp_clients/raw/file2.csv
└── s3://myorg-data-lake/sftp_clients/parquet/…*
通过这种方式,文件在 S3 上,模式可以被修复,而不用担心丢失任何数据。
由于大数据框架利用文件元数据和特殊数据布局来优化计算,因此生成的文件处理速度通常会更快。使用这种文件格式的另一个好处是减小了文件大小。模式、编码技术和特殊的数据布局,如列存储,允许这些库避免冗余——减少表示相同信息所需的字节量。
文件大小
许多 Hadoop 系列框架在处理少量大文件时比处理大量小文件时效率更高。原因是读取每个文件的元数据有开销,启动并行下载文件的进程也有开销。因此,合并从数据库的多个查询、多个 API 调用或多个 SFTP 文件中提取的数据以减少文件数量,可以为下游转换节省大量时间。像 Snappy 这样的压缩库也可以用来减少通过网络的数据量,并且通常值得这样做,因为引入的 CPU 负载可以忽略不计。
没有变化
数据湖应该包含在给定时刻**的状态的不变真值 — 未修改快照。**此时任何转型都是不可取的— 合规流程除外(如匿名化)。
如果数据在被复制到数据湖之前被更改,它将偏离其在源系统中捕获的状态。如果源系统使以前的数据不可用,并且应用的逻辑需要撤销,数据将不得不进一步变异。这是危险的,因为它可能会导致无法回滚更改来获取原始提取。
有时,源系统中的错误会导致产生不正确的数据。在这些方面,我们可能希望它反映在我们的捕获(和分析)中,或者我们可能希望它得到纠正。在后一种情况下,重新运行相关时间窗口的提取过程可能就足够了,或者可能需要人工干预,但是在这两种情况下,物理分区仅用于覆盖相关数据。
物理分区
对提取的数据进行分区对于实现幂等性和优化提取大小非常重要。Maxime Beauchemin 在他的功能数据工程博客中为幂等 ETL 提供了一个强有力的案例。给定一个“预定的执行日期”,提取应该总是产生相同的结果。这有时是不可能的,因为我们依赖于我们无法控制的外部资源,但是这些提取仍然应该被分组到分区中,以便下游的转换可以是等幂的。
这是一个幂等每日摘录的简单示例:
*SELECT * FROM customers
WHERE last_modified_date >= 2020–01–01
AND last_modified_date < 2020–01–02*
在实践中,我们将参数化上面的 SQL 以从执行日期导出下限和上限
*SELECT * FROM customers
WHERE last_modified_date >= {{ execution date - 1 day }}
AND last_modified_date < {{ execution date }}*
将其与下面的错误示例进行比较,其中结果将根据外部因素(今天的日期)而变化:
*SELECT * FROM customers
WHERE last_modified_date > 2019–01–01*
在 Airflow 中,执行日期通常用于实现幂等。执行日期是一个强大的概念,它是一个不可变的日期在运行时赋予一个管道(气流中的有向无环图)。如果 DAG 计划在2019–01–01 00:00:00运行,这就是执行日期。如果该管道失败,或者需要重新运行,则可以清除该特定运行的状态,然后它将获得相同的执行日期并产生相同的提取,条件是提取基于执行日期和幂等。这使得并行运行多个提取过程成为可能,并且通常用于回填数据。
例如,我使用相同的(简单的)技术从 API 回填数据,并使用 Airflow 的特性来限制并行性,并自动重试或超时调用。这是气流的一个常见用例,通过幂等(非重叠)提取使其成为可能。
类似地,我们可以运行端到端 ETL 的多个实例。当试图重新处理一个不寻常的时间范围内的数据时,这尤其有用。例如,如果转换代码和定义的资源是针对每天的数据量进行测试的,那么很难知道相同的设置对于整个月的数据量会有什么样的表现。相反,ETL 的一个实例可以在被重新处理的一个月中的每一天启动——可能并行执行(这在 Airflow 中很容易实现)。
提取的物理分区应基于提取处理的计划运行日期。最简单的例子是每日批量处理的每日提取物:
*s3://myorg-data-lake/sftp_clients/parquet/ds=2020-01-01
s3://myorg-data-lake/sftp_clients/parquet/ds=2020-01-02
s3://myorg-data-lake/sftp_clients/parquet/ds=2020-01-03*
ds 代表日期戳,这里:执行日期
请注意表示 Hadoop 生态系统中的物理分区的key=value
格式——物理分区被转换为数据集的一列,当在 WHERE 子句中使用时,允许跳过所选分区之外的所有文件(分区修剪)。
提取过程应该以这样的方式编写,即根据给定的执行日期覆盖分区。然后,转换过程可以使用ds
作为过滤器来获取它们需要处理的数据。
其他时间框架遵循相同的原则,但在每小时的情况下,我们可能要考虑流——批处理系统往往会有开销,使它们无法用于非常短的批处理。
另一个有趣且常见的用例是,我们在提取数据的频率高于我们在转换数据的频率。当从源中提取一个大的时间范围使其超负荷时,就会出现这种需要,因为数据有以后不可用的风险,或者在转换之前一次提取所有数据会延迟下游过程。例如,我们可能希望创建每小时的提取,但是每 12 小时处理一次数据。为了设计这样一个需要以不同节奏调度任务的流水线,我们可以使用逻辑分支 到在我们需要的时候选择性地运行转换过程。
这种较高的提取频率会产生不希望的小文件,在这种情况下,在转换之前,我们合并要处理的批处理。当文件非常小,以至于将元数据(模式、统计数据)写入每一个文件会产生很大的开销时,应该在文件合并后转换为模式嵌入文件。在这种情况下,请考虑以下结构:
*s3://myorg-data-lake/sftp_clients/raw/ds=2020-01-01<space>00:00:00
s3://myorg-data-lake/sftp_clients/raw/ds=2020-01-01<space>01:00:00
s3://myorg-data-lake/sftp_clients/raw/ds=2020-01-01<space>02:00:00
...
s3://myorg-data-lake/sftp_clients/raw/ds=2020-01-01<space>12:00:00
--
s3://myorg-data-lake/sftp_clients/parquet/ds=2020-01-01<space>12:00:00*
其中合并+转换+压缩过程将把 12 个分区变成 1 个,并且sftp_clients
表将指向拼花版本而不是原始副本。
最后
在这篇文章中,我试图给数据湖和提供数据的提取过程添加一些结构。希望你觉得有用!
神经网络损失函数指南及其在 Keras 中的应用
原文:https://towardsdatascience.com/a-guide-to-neural-network-loss-functions-with-applications-in-keras-3a3baa9f71c5?source=collection_archive---------24-----------------------
二元交叉熵、余弦邻近度、铰链损耗,还有 6 个更多
损失函数是训练神经网络的重要部分,选择正确的损失函数有助于神经网络知道它有多远,因此它可以正确地利用其优化器。本文将讨论 Keras 支持的几个损失函数——它们是如何工作的,它们的应用,以及实现它们的代码。
交叉熵
二进制交叉熵在数学上定义为—
—给定正确的目标值 t 和预测值 p 。
给定正确目标值 0 的 p 值,二进制交叉熵值可以绘制为—
给定正确目标 1 的 p 值,二进制交叉熵值可以绘制为—
熵是对某一分布不确定性的度量,交叉熵是代表目标分布和预测分布之间不确定性的值。
#FOR COMPILING
model.compile(loss='binary_crossentropy', optimizer='sgd')
# optimizer can be substituted for another one#FOR EVALUATING
keras.losses.binary_crossentropy(y_true, y_pred, from_logits=**False**, label_smoothing=0)
分类交叉熵和稀疏分类交叉熵是二元交叉熵的版本,适用于几个类别。当一个样本有几个类别或标签是软概率时,应该使用分类交叉熵,当类别互斥时,应该使用稀疏分类交叉熵。
分类交叉熵:
#FOR COMPILING
model.compile(loss='categorical_crossentropy', optimizer='sgd')
# optimizer can be substituted for another one#FOR EVALUATING
keras.losses.categorical_crossentropy(y_true, y_pred, from_logits=**False**, label_smoothing=0)
稀疏分类交叉熵:
#FOR COMPILING
model.compile(loss='sparse_categorical_crossentropy', optimizer='sgd')
# optimizer can be substituted for another one#FOR EVALUATING
keras.losses.sparse_categorical_crossentropy(y_true, y_pred, from_logits=**False**, axis=-1)
余弦近似/余弦相似
余弦相似性是两个向量之间相似性的度量。数学表示是—
—给定两个向量 A 和 B ,其中 A 表示预测向量, B 表示目标向量。
较高的余弦接近度/相似度表示较高的准确度。完全相反的向量的余弦相似度为-1,完全正交的向量的余弦相似度为 0,相同的向量的余弦相似度为 1。
余弦近似可以在 Keras 中实现:
#FOR COMPILING
model.compile(loss='cosine_proximity', optimizer='sgd')
# optimizer can be substituted for another one#FOR EVALUATING
keras.losses.cosine_proximity(y_true, y_pred, axis=-1)
铰链损耗
铰链损耗在数学上定义为—
—给定预测 y 和目标值 t 的1。注意 y 应该是一个概率而不是一个单一的类标签。
下面是铰链损耗图,它是线性负值,直到达到 1 的 x 。
来源
#FOR COMPILING
model.compile(loss='hinge', optimizer='sgd')
# optimizer can be substituted for another one#FOR EVALUATING
keras.losses.hinge(y_true, y_pred)
Hinge 还有另外一个离经叛道的,平方 hinge ,这(正如你能猜到的)就是铰链函数,平方。
#FOR COMPILING
model.compile(loss='squared_hinge', optimizer='sgd')
# optimizer can be substituted for another one#FOR EVALUATING
keras.losses.squared_hinge(y_true, y_pred)
胡伯损失
Huber 损耗在数学上定义为
…对于系数 c ,其中 t 表示目标值和预测值之间的差值,可绘制为
…对于 c. 的各种值
这可以在 Keras 中实现为
#FOR COMPILING
model.compile(loss='huber_loss', optimizer='sgd')
# optimizer can be substituted for another one#FOR EVALUATING
keras.losses.huber_loss(y_true, y_pred, delta=1.0)
双曲余弦的对数
双曲余弦函数是 log(cosh( x )),图形如下
…其中 x 表示预测值和目标值之间的差值。
#FOR COMPILING
model.compile(loss='logcosh', optimizer='sgd')
# optimizer can be substituted for another one#FOR EVALUATING
keras.losses.logcosh(y_true, y_pred)
对数误差平方
平均绝对误差的对数或 log( x )如下图所示。
误差平方的对数比较特殊,因为如果误差更接近 0(比如 0.2 到 0.1),那么误差减少 0.1,损失函数的下降幅度会比更大(比如 1.2 到 1.1)。
这可以在 Keras 中实现为:
#FOR COMPILING
model.compile(loss='mean_squared_logarithmic_error', optimizer='sgd')
# optimizer can be substituted for another one#FOR EVALUATING
keras.losses.mean_squared_logarithmic_error(y_true, y_pred)
如果你喜欢,看看其他帖子:
- 神经网络层指南及其在 Keras 中的应用
- 神经网络优化器指南及其在 Keras 中的应用
非最小相位系统指南
原文:https://towardsdatascience.com/a-guide-to-non-minimum-phase-systems-1403350917a0?source=collection_archive---------15-----------------------
向导
为什么淋浴时打开热水旋钮时,水是先冷的?
你有没有想过,为什么当你在淋浴时打开热水旋钮,水会冷几秒钟,然后变热或反之亦然?
在本文中,我们将通过触及两个概念来回答这个问题,即最小相位 (MP)系统和传递函数 s
介绍
让我先阐述一下这个问题。我在问题中提到的现象在气候条件下尤其明显,那里的水供应与环境温度不同。我在两种极端气候下都生活过。在一个炎热的国家,夏天温度达到 45 摄氏度(113 华氏度),如果你转动冷水旋钮,供水首先是超热的,然后过一段时间,它会变冷。另一方面,我目前住在一个冬天温度达到零下 20 摄氏度甚至更低的城市。如果你转动热水旋钮,供水需要几秒钟变热。从控制工程的角度来看,这两种现象遵循相似的行为。
作者图片
本文将从控制系统理论的角度回答这个问题。简而言之,因为淋浴的供水系统是一个非最小相位(NMP)系统。
为了更好地理解 NMP 系统的行为,让我们来看一个例子。我们的系统需要一个数学模型。由于使用传递函数模型可以更好地理解 NMP,我们需要了解这个概念。然而,由于这种表示方式不如微分方程等其他数学模型常见,因此我们先简单介绍一下传递函数是什么,以及如何用这种方式表示模型。如果你已经知道什么是传递函数,那么可以直接跳到例子中。
物理系统的数学模型有几种表示方式,如微分方程、状态空间表示、传递函数。最常见的是,我们使用基于时间的函数,通过前面提到的两种方法来为物理系统建模(为了清楚起见,我们可以在频域中编写模型的微分方程,但这在物理系统的数学建模中不太常见)。然而,传递函数为我们提供了另一种看待系统的方式,即在频域中分析系统。现在,让我们看看什么是传递函数!
传递函数是什么?
传递函数模型使用多项式的比率来描述系统的输入-输出关系。因此,一个输入信号给一个系统产生一个受控输出(又名响应)。这种类型的建模不同于使用微分方程和状态空间表示,其中模型动态是可用的。
💡传递函数是观察动态系统的另一种方式,但在频域中,通过分析给定输入信号的系统响应。
控制系统的传递函数是输出信号的拉普拉斯变换 ( L {})与输入信号的拉普拉斯变换之比。简而言之,这里的目标不是使用基于时间的微分方程在时域中分析模型,而是使用变换在频域中分析模型。
输入和输出信号位于 s 域的系统框图(图片由作者提供)
假设我们有一个系统,以 u(t)和 y(t)作为输入和输出信号。传递函数可以如上所示进行计算。
分子多项式的根称为模型零点,分母多项式的根称为模型极点。零点影响系统的输入,极点影响系统响应及其稳定性。对于零极点分析,我们应该使用s-平面,它是一个复平面,拉普拉斯变换在其上绘制[1]。
注:本文中,我们只对系统的初始响应感兴趣,是为了回答为什么淋浴先冷后热?如前所述,由于初始系统响应与系统零点密切相关,因此我们将不讨论极点(这可能是另一篇文章的主题)。
什么是非最小相位系统?
现在我们已经熟悉了 NMP 系统,让我们正式定义这个系统:
👉非最小相位(NMP)系统是因果和稳定系统,它们的逆是因果的但不稳定。[2]
在我们的系统中有一个延迟或者在s-平面(又名右半平面或 RHP)的右半部分有一个零模型可能导致一个非最小相位系统。
请注意,对于给定的幅度响应,只有一个最小相位系统,但 NMP 系统的数量是无限的。这就是为什么我们听不到像最大相位系统这样的术语。关于非最小相位系统的数学描述的更多细节可在[3]中获得。
个案研究
现在我们已经熟悉了传递函数,让我们看看非最小相位系统是什么样子,并回答为什么水在变热之前会先变冷!
下面是两个极点相同但零点不同的系统。系统 1 在 s = -2 处有一个零点,而系统 2 在 s = 2 处有一个零点。
MP 和 NMP 系统示例框图(图片由作者提供)
让我们分离系统 1 的极点和零点进行分析。如前所述,您可以将零视为修改后的输入(姑且称之为 U’(s))。如前所述,我们对本文中的模型零点感兴趣,因此我们将重点关注绿色模块。
由极点和零点分隔的最小相位系统的框图(图片由作者提供)
让我们通过应用逆 L 变换来看看系统 1 的修改输入 U’(s)在时域中的情况
按照系统 2 的相同过程,系统 2 的修改后的输入将为
所以,唯一的区别是负号。让我们画出两个系统的输入和修改后的输入信号,看看两者有何不同。
让我们将用作输入信号 u(t)(顶部的灰色函数)。由于输入信号是单位阶跃,输出 y(t)被称为阶跃响应。修改后的输入 u'(t)如下图所示,它是 2u(t)和 u(t)的导数之和。u'(t)的导数分量对于系统 1 是蓝色的,对于系统 2 是红色的。
MP 和 NMP 系统的带导数方向的输入和修改输入信号(图片由作者提供)
系统 2 中 u(t)的负导数导致系统 2 的阶跃响应首先向预期响应(稳态值)的相反方向移动,然后向预期响应(红色曲线)移动。这与系统 1 的阶跃响应(蓝色曲线)形成对比,系统 1 在开始时没有这种下冲。
MP 和 NMP 系统的阶跃响应,NMP 阶跃响应在开始时有一个下冲(图片由作者提供)
参考文献中有一个很好的例子。[4].
那么,下一个问题是,当我们有一个非最小相位系统时,该怎么办?
解决办法就是等待⌛.我们必须等到下冲结束。我们也可以为这样的系统设计一个控制器/补偿器。然而,由于几个原因,如系统变得不稳定或响应较慢的风险,设计 NMP 系统的控制器更加困难。
现在,让我们回到开头的问题。为什么在还没热之前就打开热水供应,淋浴的水却先凉了?
答案是,当你打开淋浴的热水供应时,系统会经历一个欠冲,因为这是水变热之前的一个非最小阶段。在这种情况下,最好等待几秒钟,以便系统(从欠冲中)恢复。你不应该改变方向或打开另一个旋钮,因为从长远来看,这将导致更冷的淋浴!
另一个通常在控制系统书籍中使用的例子是响应升降舵偏转的飞机高度变化。在这种情况下,当飞机试图使用升降舵增加高度时,由于飞机在增加高度之前向下倾斜(导致向下的空气动力),高度会稍微降低。这个例子可以从富兰克林的《动态系统的反馈控制》(第 7 版)[5]一书第 6 章的数学模型中得到。
结论
在本文中,我们了解了什么是非最小相位系统,以及为什么这样的系统首先经历错误方向的响应(你转动热水旋钮,水首先是冷的!).我们还讨论了传递函数,以及它在系统分析中的作用。
Jupyter 笔记本包含用于创建案例研究的阶跃响应的代码,可点击此处获取。感谢阅读!
最初发表于T5【https://www.ealizadeh.com】。
参考
[1] MATLAB,什么是传递函数模型? (2020)
[2]维基百科。2020.最小相位,(2020)
[3]Jesse b . Hoagg & Dennis s . Bernstein,《非最小相位零点——无事可做(经典控制再探——第二部分)】【T3》,(2007 年 6 月),IEEE 控制系统杂志。
[4] MATLAB,实践中的控制系统,第 6 部分:什么是非最小相位系统? (2019)
[5] G. F .富兰克林,J. D .鲍威尔,a .埃马米-奈尼,动态系统的反馈控制,第七版
从推特上收集回复的指南
原文:https://towardsdatascience.com/a-guide-to-scrape-tweet-replies-from-twitter-2f6168fed624?source=collection_archive---------11-----------------------
使用 Octoparse 抓取 tweet 回复的初学者指南
照片由晨酿在 Unsplash 拍摄
我使用 Octoparse 进行抓取。我必须说,这个软件有这么容易使用的界面,他们的团队真的做了很大的工作,为您提供教程和文章,开始使用这个软件。此外,您可以将您的疑问放在他们官方网站的帮助页面上,他们团队中的某个人一定会给您一个有效的答复。
注意:这里,我用的是 OCTOPARSE 版本,先从它开始安装并注册。
如果你想购买该软件,请在这里浏览所有计划:http://agent.octoparse.com/ws/436
对于本教程,按照以下步骤收集唐纳德·特朗普的推文回复 :
第一步:登录后,你会看到这个软件的一个主页→转到最左上角的“+New”按钮→点击它→从下拉菜单中选择一个高级选项→新任务窗口将打开→新建一个组来组织你在那个(可选)→输入你要抓取的网页网址(如https://Twitter . com/realDonaldTrump/status/128711918732487444
第二步:保存后,你会看到一个弹出窗口,要求在两个选项中进行选择:要么自动让 Octoparse bot 抓取网页,要么手动选择特定元素。
- 因此,在这里我选择了第一个选项→单击它将显示如下内容:
- 当它完成 100%检测后,它会显示一个如下的窗口,有 3 个窗口界面同时打开。“提示”弹出框包含一些设置,您可以在保存前更改,也可以在自动检测结果之间切换,数据预览是一个包含数据集的界面,您可以预览抓取后的效果,Twitter 网页将在后台界面中打开。
- 在保存设置时,你会看到一个如下的窗口,有 4 个分割的窗口→现在,你可以很容易地看到工作流程和管理每个动作的设置。
- 这是机器人自动完成的所有工作,现在我们的任务是清理数据并相应地更改设置。在我们继续清理和更改设置之前,让我们创建一个分页循环。
由于 Twitter 没有下一步按钮或者被分成页面,机器人不会自动分页。否则,它会识别出来的。因此,要创建分页循环,我们必须设置一个无限滚动来通过分页加载更多数据。
- 为此,点击网页上的空白区域,如下图所示【十字】 →然后,弹出窗口将打开→点击循环点击单个元素。
- 您将在工作流程中看到以下变化:
步骤-4: 现在,我们的下一步是相应地更改设置,让我们从分页开始→转到工作流中的“单击以分页”选项→悬停在它上面&您将看到“动作设置”选项→单击它→并在设置中指定这些更改,如下图所示:
- AJAX 超时对于在滚动后加载数据是必要的,否则,它不会抓取任何数据并返回一个错误报告。因此,到目前为止,5s 是机器人可以自动加载数据的一个很好的平均值。
- 指定滚动的细节是必要的,因为我们正在为无限滚动设置分页循环。因此,选中“加载后向下滚动页面”框,选择“一屏显示”。因此,它将在 2 秒的等待时间内抓取屏幕上列出的所有内容。
- 现在转到工作流中的“分页”选项→转到其动作设置→然后选择“退出循环”设置并指定“重复次数”以获取更多数据:
步骤 5: 现在我们的下一个任务是清理数据,我只为我的项目提取推文回复。还可以提取类似“转发”、“点赞”等细节。因此,如果其他属性对您的项目有意义,您也可以选择保留它们。
- 要删除任何特定属性→转到下面的数据预览部分→然后,选择任何列标题→您可以在角上看到 3 个点“…”→右键单击它→然后从下拉列表中选择“删除”选项。
- 还有其他的选择,你也应该试试。
- 删除所有不必要的属性后,清理后的数据集将如下所示:
步骤 6: 在做了一些更改之后,如果您正在获得预期的数据,那么您就可以运行您的任务了。
- 只需简单地保存任务并点击运行以提取更多数据。
- 将出现另一个弹出窗口,询问您希望如何运行您的任务。因此,免费用户只能选择“在你的设备上运行任务”。如果您希望提取超过 10000 行的数据,并希望在预定的基础上进行所有操作,您可以升级到高级计划,该计划并不昂贵,但具有所有这些有效的功能,如果您选择升级的计划,他们甚至会在预定的基础上为您进行清理,并返回一个干净的数据集。
- 因此,我在这里选择第一个选项,因为我没有收集那么多数据。
- 这是我提取的数据的样子:
- 如果您完成了提取或如果您开始得到重复→只需简单地“停止运行”,然后单击“导出数据”。
- 现在,只需导出:
- 如果您的数据中有重复项,它会自动检测到这些重复项,您只需选择删除这些重复项。
- 数据科学的人在这里完全可以理解我,因为获得一组独特的数据是一项真正的任务。
- 导出数据后,您将看到另一个窗口,询问您机器上数据集的另存为格式。
- 简单地,选择任何格式→按下“ OK ”,在下一个弹出窗口看到你保存的文件的目录,并简单地从那里打开它。
- 看看我刮下来的 Excel 文件:
- 因此,正如你所看到的,它是多么漂亮地刮掉了所有的文字,没有图像和视频。不过,如果你去看看它的网页,你会发现每个回复里都有视频和图片。
注 —该软件的使用因网站而异。如果你想抓取除此之外的任何网页,你必须改变一些设置。请参考他们的文章和教程。大约,他们的团队已经覆盖了所有类型的网页,无论是静态的还是动态的。
所以,如果我的博客帖子对你有所帮助,而你此刻觉得很慷慨,请不要犹豫,请给我买杯咖啡。☕😍
是的,点击我。
And yes, buying me a coffee **(and lots of it if you are feeling extra generous)** goes a long way in ensuring that I keep producing content every day in the years to come.
您可以通过以下方式联系我:
- 订阅我的 YouTube 频道 视频内容即将上线 这里
- 跟我上 中
- 通过 LinkedIn 联系我
- 跟随我的博客之旅:-https://kajalyadav.com/
- 成为会员:-【https://techykajal.medium.com/membership】
也可以看看我的其他博客:
** [## 8 ML/AI 项目,让您的投资组合脱颖而出
有趣的项目想法与源代码和参考文章,也附上一些研究论文。
towardsdatascience.com](/8-ml-ai-projects-to-make-your-portfolio-stand-out-bfc5be94e063) [## 用 10 个简单的步骤搜集 1000 篇新闻文章
如果你遵循这 10 个简单的步骤,使用 python 进行网络抓取是非常简单的。
towardsdatascience.com](/scraping-1000s-of-news-articles-using-10-simple-steps-d57636a49755)**
用熊猫和 BeautifulSoup 抓取 HTML 表格的指南
原文:https://towardsdatascience.com/a-guide-to-scraping-html-tables-with-pandas-and-beautifulsoup-7fc24c331cf7?source=collection_archive---------1-----------------------
也是一个实际的例子
由马库斯·斯皮斯克在 Unsplash 上拍摄
抓取网页时碰到 HTML 表格是很常见的,如果没有正确的方法,从这些表格中提取有用的、一致的数据可能会有点棘手。
在本文中,您将看到如何使用两种不同的方法快速、高效地抓取这些元素:仅使用 Pandas 库和使用传统的抓取库 BeautifulSoup。
举个例子,我刮了英超分类表。这很好,因为这是一个常见的表格,基本上可以在任何体育网站上找到。虽然有必要通知您这一点,但当您阅读时,表被刮擦不会产生太大的影响,因为我试图使这篇文章尽可能地一般化。
pandas.read_html():快捷方式
如果你想要的只是从一个页面中获取一些表格,而不是别的,你甚至不需要设置一个完整的刮刀来完成这项工作,因为熊猫可以自己完成这项工作。pandas.read_html()
函数使用一些抓取库,如 BeautifulSoup 和 Urllib 来返回一个包含页面中所有表的列表作为数据帧。你只需要传递页面的 URL。
dfs = pd.read_html(url)
您现在需要做的就是从列表中选择您想要的数据帧:
df = dfs[4]
如果您不确定列表中帧的顺序,或者如果您不希望您的代码依赖于这种顺序(网站可能会改变),您可以随时搜索数据帧,通过其长度找到您正在寻找的数据帧…
for df in dfs:
if len(df) == 20:
the_one = df
break
…或者按其列的名称,例如。
for df in dfs:
if df.columns == ['#', 'Team', 'MP', 'W', 'D', 'L', 'Points']:
the_one = df
break
但是熊猫并没有让我们的生活变得更容易。这个函数接受一些有用的参数来帮助您获得正确的表。您可以使用match
来指定表应该匹配的正则表达式字符串;header
获取带有您传递的特定标题的表格;例如,attrs
参数允许您通过表的类或 id 来标识表。
然而,如果你不是只抓取表,而是使用,比方说,获取页面的请求,那么鼓励你将page.text
传递给函数,而不是 URL:
page = requests.get(url)
soup = BeautifulSoup(page.text, 'html.parser')
dfs = pd.read_html(page.text)
如果您使用 Selenium 的 web 驱动程序来获取页面,情况也是如此:
dfs = pd.read_html(driver.page_source)
这是因为这样做可以显著减少代码运行的时间,因为read_html()
函数不再需要获取页面。检查每个场景中一百次重复所用的平均时间:
Using the URL:
Average time elapsed: 0.2345 secondsUsing page.text:
Average time elapsed: 0.0774 seconds
使用 URL 使得代码速度慢了三倍。因此,只有当您不打算首先使用其他库获得页面时,使用它才有意义。
用 BeautifulSoup 获取表格的元素
虽然熊猫真的很棒,但它不能解决我们所有的问题。有时候,您需要按元素来抓取一个表,可能是因为您不想要整个表,或者是因为表的结构不一致,或者是出于其他任何原因。
为此,我们首先需要了解 HTML 表格的标准结构:
<table>
<tr>
<th>
<th>
<th>
<th>
<th>
<th>
<th>
</tr>
<tr>
<td>
<td>
<td>
<td>
<td>
<td>
<td>
</tr>
<tr>
<td>
<td>
<td>
<td>
<td>
<td>
<td>
</tr>
.
.
.
</table>
其中,tr
代表“表格行”,th
代表“表头”,td
代表“表格数据”,数据以文本形式存储在这里。
该模式通常是有帮助的,所以我们剩下要做的就是使用 BeautifulSoup 选择正确的元素。
首先要做的是找到桌子。find_all()
方法返回满足我们传递给它的需求的所有元素的列表。然后,我们必须在列表中选择我们需要的表:
table = soup.find_all('table')[4]
例如,根据网站的不同,有必要指定表类或 id。
剩下的过程现在几乎是直观的了,对吗?我们只需要选择所有的tr
标签和它们里面的th
和td
标签中的文本。我们可以再次使用find_all()
来查找所有的tr
标签,是的,但是我们也可以以更直接的方式迭代这些标签。
children
属性返回一个 iterable 对象,所有标签都在父标签的正下方,父标签是table
,因此它返回所有的tr
标签。因为它是一个可迭代的对象,我们需要像这样使用它。
之后,每个child
都是tr
标签。我们只需要提取其中每个td
标签的文本。以下是所有这些的代码:
for child in soup.find_all('table')[4].children:
for td in child:
print(td.text)
过程就完成了!然后你就有了你要找的数据,你可以用最适合你的方式操作它。
其他可能性
例如,假设您对表格的标题不感兴趣。不使用children
,您可以选择第一个tr
标签,它包含标题数据,并使用next_siblings
属性。这和children
属性一样,将返回一个 iterable,但是带有所有其他的tr
标签,它们是我们选择的第一个标签的兄弟标签。你将会跳过表格的标题。
for sibling in soup.find_all('table')[4].tr.next_siblings:
for td in sibling:
print(td.text)
就像孩子和下一个兄弟姐妹一样,你也可以寻找上一个兄弟姐妹、父母、后代等等。可能性是无穷无尽的,所以请务必查看 BeautifulSoup 文档,为您的铲运机找到最佳选择。
现实生活中的一个例子
到目前为止,我们已经编写了一些非常简单的代码来使用 Python 提取 HTML 表格。然而,当真正这样做时,你当然会有一些其他的问题要考虑。
例如,你需要知道如何存储你的数据。会直接写在文本文件里吗?还是将它存储在一个列表或字典中,然后创建。csv 文件?还是会创建一个空的数据帧并用数据填充它?当然有很多可能性。我的选择是将所有内容存储在一个大的列表列表中,该列表列表稍后将被转换为 DataFrame 并作为导出。csv 文件。
在另一个主题中,您可能希望在代码中使用一些try
和except
子句,让代码准备好处理一些可能会发现的异常。当然,为了不使服务器过载,您还需要插入一些随机的暂停,并且利用代理提供者,比如 Infatica ,来确保只要还有表需要清理,您的代码就会一直运行,并且您和您的连接会受到保护。
在这个例子中,我在整个 2019/20 赛季的每一轮比赛后都用我在本文中介绍的大部分内容刮出了英超积分榜。这是它的全部代码:
一切都准备好了:使用children
属性收集表中的所有元素,处理异常,将数据转换成 DataFrame,导出一个. csv 文件,并随机暂停代码几秒钟。在这一切之后,这段代码收集的所有数据生成了这个有趣的图表:
作者图片
你不会在互联网上找到绘制这样一个图表所需的数据。但是这就是抓取的好处:你可以自己去获取数据!
作为总结,我希望这是有用的,并且当你再次抓取 HTML 表时不会有问题。如果你有问题,有建议,或者只是想保持联系,请随时通过 Twitter 、 GitHub 或 Linkedin 联系。
感谢阅读!
文本注释指南——理解语言的关键
原文:https://towardsdatascience.com/a-guide-to-text-annotation-the-key-to-understanding-language-e221a69ee90e?source=collection_archive---------28-----------------------
Pixabay
命名实体识别、情感分析等等
在一个越来越受数据驱动的数字世界中,企业必须利用用户在其平台上提供的大量数据,将自己与竞争对手区分开来。文本形式的数据是最常见、最丰富、最复杂的数据之一,从产品评论到社交媒体评论,理解组织或项目环境中的大量文本至关重要。
不幸的是,随着文本中大量信息的出现,处理这些非结构化的、机器不可读的数据也面临着挑战。与图像或录音等固有的数字数据不同,文本更加复杂。虽然通过自然语言处理(NLP)中的矢量编码(处理和建模文本的机器学习领域)等方法,模型可以表示单词的表层表示,但它必须手动学习(如果它学习的话)单个单词下面的深度。
标准的简单矢量化程序。每个单词代表向量中的一个索引,所以单词之间没有实际的联系或理解。
举个例子,单词“banks”有两个意思,比如“他刚刚抢劫了那些银行!”“河水又溢出了堤岸。”不管上下文如何,标准的矢量化模型都会认为这些是相同的。单词“banks”也是“bank”的复数形式,但天真的模型将无法绘制这些智能连接,而是标记,认为它们就像“apple”和“book”一样不同。没有人类的帮助,机器的简单文本到数组的转换缺乏人类操纵和创造语言的深度和独创性。出于这个原因,为非结构化文本提供高质量、信息丰富且准确的注释,以使机器对人类语言有更深入、更丰富的理解,这一点非常重要。这包括增加人类的解释,以提高机器的智能。创建各种标签的过程被称为文本注释,这些标签对人类来说是本能的,但却为人工智能提供了大量需要的信息。
例如,考虑命名实体标记,这是文本注释中的一个常见任务,其中非结构化文本中的实体(名词)被识别并被分配一个类别。这些可能包括组织、国家、位置、时间表达式、数量、货币、百分比、名称等。由于范围和定义的利益冲突,命名实体标记通常是极其复杂的。例如,考虑文本样本:“2006 年,亚历山大在弗吉尼亚的家中购买了 200 股美国银行股份。这相当于她投资组合的 30.5%。”理想情况下,完美的命名实体识别系统应该能够输出:“亚历山大[人名]于 2006 年[时间]在她位于弗吉尼亚[位置]的家中购买了 200[数量]股美国银行[公司]。这相当于她投资组合的 30.5%。命名实体标记有许多复杂之处——例如,“America”是一个国家,但是聪明的注释者会认识到这个实体本身嵌套在一个更大的实体中——美国银行,这是一个公司。
嵌套实体的一个常见示例。
或者,考虑这个句子,“亚历山大居住在弗吉尼亚州。”亚历山大港本身是弗吉尼亚州内的一座城市,但大多数人类注释者有一种本能的预感,亚历山大港。注释者能否区分“巴黎[城市]”、“希尔顿[公司]”、“巴黎希尔顿[人名]”?能够成功执行 NER 的智能模型——命名实体识别、自动命名实体标记——依赖于最初手动标注的文本样本。通过在我们的对话中提供对象背后的含义——通常是深层次的本能,并根据上下文而变化——模型的理解得到了加强。
情感分析是另一种常用的数据注释方法,在商业中有很强的直接应用。这个过程包括将文本样本中表达的观点按照积极、中立或消极的尺度进行分类。情感分析的一个细分还包括“主观性”——衡量一段文本有多固执己见(相对于更多事实内容而言)。
巧妙运用情感分析对做出商业决策至关重要。例如,假设你是一家应用公司的业务主管。您的应用程序在 app store 中的五星评级长期保持在 4.9/5,您的分析师已确定无需对应用程序进行进一步更改,因为最佳版本已经创建。然而,看似矛盾的是,你的 app 使用量在慢慢下降。如果进步的最明显和最公开的信号——评级——表明应用程序运行良好,这怎么可能呢?在对你的应用的评论(从应用商店到流行的技术博客)进行情绪分析后,你发现对你的应用的总体情绪实际上是负面的。喜欢这个应用程序的人更有可能对它进行评级,而不是全部删除,这产生了一个有偏见和淡化的进度信号。根据您的发现,您批准了进一步的开发,并看到您的应用程序使用量飙升。
总之…
- 为了给模型更多的视角和理解,文本模型需要文本注释。
- 命名实体识别是对文本中不同实体结构的标注。
- 情感分析是一种从文本中提取人类情感和印象的方法。
文本分类和情感分析指南
原文:https://towardsdatascience.com/a-guide-to-text-classification-and-sentiment-analysis-2ab021796317?source=collection_archive---------7-----------------------
腾雅特在 Unsplash 上拍摄的照片
如何利用机器学习对语句的情绪进行分类?
动机:文本分类和情感分析是一个非常常见的机器学习问题,被用在很多活动中,比如产品预测、电影推荐和其他一些活动。目前,对于像我一样对这个领域不熟悉的每个机器学习者来说,探索这个领域已经变得非常重要。在探索这个话题后,我觉得,如果我通过一篇文章分享我的经验,它可能会帮助一些试图探索这个领域的人。所以,我会试着从一个基本的层次来构建整个东西,所以这篇文章可能看起来有点长,但是如果你想的话,它有一些部分你可以跳过。
像情感分析这样的文本分类问题可以使用多种算法以多种方式实现。这些主要分为两大类:
- 单词包模型:在这种情况下,我们数据集中的所有句子都被标记化,形成一个单词包来表示我们的词汇。现在,我们数据集中的每个单独的句子或样本都由单词包向量表示。这个向量称为特征向量。比如‘今天是晴天’,和‘太阳从东方升起’是两句话。单词包将是两个句子中唯一的所有单词。
- 第二种方法是基于时间序列的方法:这里每个单词由一个单独的向量表示。所以,一个句子被表示为一个向量的向量。
这是两种方法之间最基本的区别。现在,我们来详细看看。
为此,我们将使用 IMDB 审查数据集。它有 50,000 条评论,它们相应的情绪被标记为“正面”和“负面”。因此,首先,我们需要检查和清理我们的数据集。
初始数据集
from bs4 import BeautifulSoupdef strip_html(text):
soup = BeautifulSoup(text, "html.parser")
return soup.get_text()import redef remove_between_square_brackets(text):
return re.sub('\[[^]]*\]', '', text)def denoise_text(text):
text = strip_html(text)
text = remove_between_square_brackets(text)
return textdef remove_special_characters(text, remove_digits=True):
pattern=r'[^a-zA-z0-9\s]'
text=re.sub(pattern,'',text)
return text def Convert_to_bin(text, remove_digits=True):
if text=='positive':
text= 1
else:
text=0
return text
这些是清理评论部分所需的预处理,Convert_to_binary 用于将“正面”情感转换为 1,将“负面”情感转换为 0。因此,在预处理之后,我们得到:
预处理后
如果我们计算出我们的目标阶级划分。
我们有 25k 的正面情绪和 25k 的负面情绪。所以,让我们把数据分开。
X=df['review'].values
Y=df['sentiment'].values
X_train, X_test, Y_train, Y_test= train_test_split(X,Y, test_size=0.3)
第一种方法
矢量器:词汇袋
在这种方法中,我们使用词汇表中的所有单词来创建单个特征向量,词汇表是通过对训练集中的句子进行标记化而获得的。这个特征向量用于表示我们集合中的所有评论。基本上每个字都算是一个特征。因此,特征的数量等于词汇表中唯一单词的数量。现在,每一句话或每一篇评论都被视为一个样本或记录。如果该词存在于该样本中,则该词具有被视为特征的一些值,如果该词不存在,则该值为零。所以,如果‘今天是晴天’,和‘太阳从东方升起’是两句话。并且他们的包将具有 10 个单词,这将是特征向量大小。说矢量是:['它','是','一','晴朗','天','太阳','升起','在','东方']。所以,第一句用[a,b,c,d,e,0,0,0,0]表示,a,b,c,d,e 是值,取决于我们使用的方案
因此,每个样本具有相同的特征集大小,这等于词汇表的大小。现在,词汇表基本上是由训练集中的单词组成的。训练集和测试集的所有样本都仅使用该词汇表进行转换。因此,测试样本中可能有一些词汇不在词汇表中,它们会被忽略。
它们形成非常稀疏的矩阵或特征集。类似于普通的分类问题,单词成为记录的特征,相应的标签成为目标值。如果我们考虑作为一个数据集,样本或评论将是行或记录,每个记录的特征集,或每个记录对应的特征列将等于词汇表的大小,其中每个单词将是一个特征。因此,它实际上就像一个常见的分类问题,特征的数量等于训练集中的不同标记。
这可以通过两种方式实现:
- 计数矢量器:这里是特定样本或评论中的单词计数。该单词的计数成为相应单词特征的值。如果 vocab 中的单词没有出现在样本中,则其值为 0。因此,基本上,如果训练集中有 10 个句子,这 10 个句子将被标记化以创建包。比方说,创建的包长度为 100 个单词。因此,我们将形成一个长度为 100 的向量。对于特定的样本,如果有 15 个单词,其中有一个单词在该样本中出现三次,则对于该样本,对应于该单词的值变为 3,依此类推。
- TF-IDF 矢量器:这是一种更好的方法。它计算两个东西术语频率和逆文档频率。 词频=该词在样本中出现的次数。 和 IDF = log(该词在样本中出现的次数/该词在整个文档中出现的次数) 。这有助于注意到一些差异,如单词“the”在几乎所有句子中出现的频率相同,而像“good”这样具有重要意义的特殊单词则不同。因此,将特定样本的每个单词的 TF 和 IDF 值相乘,以获得该样本的特征向量。
我们将在这里使用 scikit-learn 的特征提取库。但这里需要注意的一点是,这也可以使用 TensorFlow 的 Tokenizer 函数来完成。使用 tokenizer 主要有三种方法:
- binary:X = tokenizer . sequences _ to _ matrix(X,mode='binary '):在这种情况下,如果单词出现在样本中,则单词特征值为 1,否则为零。
- count:X = tokenizer . sequences _ to _ matrix(X,mode='count '):在这种情况下,值是一个单词在句子中出现的次数。
- TF-IDF:X = tokenizer . sequences _ to _ matrix(X,mode='tfidf '):在这种情况下,我们考虑样本中单词的 TF 和样本中单词相对于该单词在整个文档中的出现次数的 IDF。
计数矢量器:代码实现
from sklearn.feature_extraction.text import CountVectorizer
vec = CountVectorizer()
vec.fit(X_train)
x_train=vec.transform(X_train)
x_test=vec.transform(X_test)
现在,如果我们注意到,向量只适合 X_train。这里是词汇形成的地方。所以词汇表只包含训练集中的单词。然后我们在训练集和测试集上进行转换。
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import Adam
model = Sequential()
model.add(Dense(16, input_dim=x_train.shape[1], activation='relu'))
model.add(Dense(16, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy',optimizer='Adam',metrics=['accuracy'])
这是我们计数矢量化方法的模型。我们可以看到,输入维度的大小等于每个样本的列数,也就是我们词汇表中的单词数。输出为 1,即情绪积极或消极。
该模型给出了 87.3%的准确度
TF-IDF 矢量器:代码实现
from sklearn.feature_extraction.text import TfidfVectorizer
vec = TfidfVectorizer()
vec.fit(X_train)
x_train=vec.transform(X_train)
x_test=vec.transform(X_test)
现在,我们调用 TF-IDF 矢量器,数据被转换。这里我们使用逻辑回归模型。
from sklearn.linear_model import LogisticRegression
lr = LogisticRegression()
lr.fit(x_train, Y_train)
该模型给出了 89.4%的准确度
第二种方法
单词嵌入:时间序列方法
在这种方法中,单词被单独表示为一个向量。在单词包的例子中,词汇表中的所有单词组成了一个向量。比方说,词汇表中有 100 个单词,因此,特定的单词将由大小为 100 的向量表示,其中对应于该单词的索引将等于 1,其他的将为 0。
因此,每个具有不同数量单词的样本将基本上具有不同数量的向量,因为每个单词等于一个向量。现在,为了给模型提供信息,我们需要让每个样本具有相同的维度,因此,需要填充以使每个样本中的单词数彼此相等。
基本上,在单词包或矢量器方法中,如果我们的总词汇中有 100 个单词,一个样本有 10 个单词,一个样本有 15 个单词,在矢量化之后,两个样本的大小都将是 100 个单词的数组,但在这里,对于 10 个单词,它将是(10 x 100),即,10 个单词中的每个单词的长度向量为 100,类似地,第 15 个单词的长度向量将是(15 x 100)。因此,我们需要找到最长的样本,并填充所有其他样本以匹配大小。
我们可以通过一些方式做到这一点:
一键编码:正如我们上面讨论的,它只是获取词汇表的大小,并在所有索引处创建一个大小为 0 的数组,而仅在单词索引处创建一个大小为 1 的数组。但是这些东西给我们提供的信息非常少,创建了一个非常稀疏的矩阵。
第二个选择是单词 embeddings。
一键编码器是一种非常硬的编码方法。这是一个非常高的维度和稀疏的数据量非常低。嵌入是一种创建密集矢量表示的方式。维度更低,有助于捕捉更多信息。它更像是通过词与词之间的相似性来捕捉它们之间的关系和相似性。例如,国王、王后、男人和女人会有一些关系。
比方说,我们有 10k 个单词被嵌入到 300 维的嵌入空间中。为此,我们声明嵌入层中的节点数=300。现在,10k 字的每个字都进入嵌入层。每个单词都将根据它们彼此之间的相似性被放置在一个 300 维的平面上,这是由几个因素决定的,比如单词出现的顺序。现在,被放置在 300 维平面中的单词将具有 300 长度的元组来表示它,该元组实际上是 300 维平面上的点的坐标。因此,这个 300 维的元组成为新的特征集或表示单词的向量。
因此,单词的向量从 10k 减少到 300。元组用作两个单词之间的特征向量,向量之间的余弦角表示两个单词之间的相似度。
我们可以通过两种方式做到这一点:
- 使用我们自己的嵌入
- 使用预先训练的嵌入
制作我们自己的嵌入
现在,对于嵌入,我们需要首先通过嵌入层发送每个样本,然后使用嵌入使它们变得密集。这些嵌入层查看单词是如何被使用的,也就是说,它试图查看两个单词是否总是一起出现或者被对比使用。在判断所有这些因素之后,该层将该单词放置在 n 维嵌入空间中的一个位置。
使用预先训练的嵌入式矩阵
我们可以使用预先训练的单词嵌入,如 google 的 word2vec 和 Standford 的 GloveText。他们在拥有数十亿个例子和单词的巨大语料库上接受训练。现在,他们有几十亿个单词,而我们只有一万个单词,所以用十亿个单词来训练我们的模型是非常低效的。我们只需要从预先训练的嵌入中选择出我们需要的单词的嵌入。
现在,这些嵌入是如何发现的?
对于 google 的 word2vec 实现,有两种方法:
- 滔滔不绝的话
- 跳格。
这两种算法实际上都使用具有单个隐藏层的神经网络来生成嵌入。
对于 CBOW ,单词的上下文,即所需单词之前和之后的单词,被馈送到神经网络,并且需要模型来预测单词。
对于 Skip-Gram ,给定单词,模型必须预测上下文单词。
在这两种情况下,单词的特征向量或编码向量被馈送到输入端。输出有一个 softmax 层,其节点数等于词汇大小,它给出了每个单词的预测百分比,即,它告诉所需单词是 softmax 层中的节点所表示的单词的概率。虽然我们实际上没有使用输出层。
我们去寻找隐藏层中产生的权重矩阵。隐藏层的节点数等于嵌入维数。因此,假设词汇表中有 10k 个单词,隐藏层中有 300 个节点,隐藏层中的每个节点在训练后都会有一个每个单词的 10k 维的权重数组。
因为神经网络单元工作在
y=f(w1x1+w2x2+………)。wnxn)
这里 x1,x2…xn 是单词,因此 n=词汇表中的单词数=10k。
所以对于 10k 的 x,会有 10k 的 w。现在,对于 1 个节点,有一个 10k 长的权重矩阵。对于 300 个组合,我们有一个 300 x 10k 重量的矩阵。现在,如果我们连接,我们将有 300 行和 10k 列。让我们转置矩阵。我们将得到 300 列和 10k 行。每行代表一个单词,300 个列值代表该单词的 300 个长度权重向量。
这个权重向量是所获得的长度为 300 的嵌入。
让我们看一下实现:
训练自己的嵌入
from keras.preprocessing.text import Tokenizer
tokenizer = Tokenizer(num_words=10000)
tokenizer.fit_on_texts(X_train)
Num_words 表示词汇的大小
x_train = tokenizer.texts_to_sequences(X_train)
x_test = tokenizer.texts_to_sequences(X_test)
-
tokenize.fit_on_text() →>根据词频创建词汇索引。例如,如果您有短语“我的狗与您的狗不同,我的狗更漂亮”,word_index[“狗”] = 0,word_index[“是”] = 1('狗'出现 3 次,'是'出现 2 次)
-
tokenize.text_to_sequence() →>将每个文本转换为一个整数序列。基本上,如果你有一个句子,它会给你句子中的每个单词分配一个整数。您可以访问 tokenizer.word_index()(返回一个字典)来验证分配给单词的整数。
vocab = len(tokenizer.word_index) + 1
from keras.preprocessing.sequence import pad_sequences
maxlen = 100
x_train = pad_sequences(x_train, padding='post', maxlen=maxlen)
x_test = pad_sequences(x_test, padding='post', maxlen=maxlen)
我们将所有句子填充到最大长度 100。
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Embedding,Dense, Activation, MaxPool1D
from tensorflow.keras.optimizers import Adam
emb_dim=100
model= Sequential()
model.add(Embedding(input_dim=vocab, output_dim=emb_dim, input_length=maxlen))
model.add(MaxPool1D())
model.add(Dense(16,activation="relu"))
model.add(Dense(16,activation="relu"))
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='Adam',loss='binary_crossentropy',metrics=['accuracy'])
最大池层用于挑选最能代表的特征以减少稀疏性。
模型摘要
该模型给出了 77.4%的准确度
使用预训练嵌入
我们将使用斯坦福的手套嵌入,它被训练了超过 60 亿个单词。
它有四个文件,每个文件有不同的嵌入空间,我们将使用 50d,这是一个 50 维的嵌入空间。
['glove.6B.100d.txt', 'glove.6B.200d.txt', 'glove.6B.50d.txt', 'glove.6B.300d.txt']
实施:
import numpy as np
from tensorflow.keras.preprocessing.text import Tokenizer
tokenizer = Tokenizer(num_words=10000)
tokenizer.fit_on_texts(X_train)
x_train = tokenizer.texts_to_sequences(X_train)
x_test = tokenizer.texts_to_sequences(X_test)
from keras.preprocessing.sequence import pad_sequences
maxlen=100
x_train = pad_sequences(x_train, padding='post', maxlen=maxlen)
x_test = pad_sequences(x_test, padding='post', maxlen=maxlen)
所以,让我们看看如何从给定的嵌入文件中提取我们需要的嵌入。
emb_dim=50
vocab=len(tokenizer.word_index)+1
emb_mat= np.zeros((vocab,emb_dim))
#Initializing a zero matrix for each word, they will be compared to have their final embeddingwith open(file_path+'glove.6B.50d.txt') as f:
for line in f:
word, *emb = line.split()
if word in tokenizer.word_index:
ind=tokenizer.word_index[word]
emb_mat[ind]=np.array(emb,dtype="float32")[:emb_dim]
这是一个任务的提取器,所以我们有一行嵌入和单词。所以,我们只是比较这些词来挑选出数据集中的索引。取向量,并把它们放在嵌入矩阵中对应于数据集中单词索引的索引处。
我们使用了*emb,因为嵌入矩阵的大小是可变的。
因此,我们这里有一个具有 10k 单词词汇表的特征集,每个单词由一个 50 长度的元组嵌入来表示,该元组嵌入是从手套嵌入中获得的。
接下来,我们建立我们的模型。
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Embedding,Dense, Activation, MaxPool1D
from tensorflow.keras.optimizers import Adam
emb_dim=50
maxlen=100
model= Sequential()
model.add(Embedding(input_dim=vocab, output_dim=emb_dim,weights=[emb_mat], input_length=maxlen,trainable=False))
model.add(MaxPool1D())
model.add(Dense(16,activation="relu"))
model.add(Dense(16,activation="relu"))
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='Adam',loss='binary_crossentropy',metrics=['accuracy'])
模型摘要
该模型给出了 67%的准确度,这可能是由于嵌入大小的减小。嵌入的大小越大,包含的信息就越多。
现在,这些方法是如何有益于单词袋模型的?正如我们所看到的,这些单词包模型只是看到了一个单词在文档中的表现,也就是说,我们可以知道这个单词出现的频率或这个单词出现的任何模式是什么?而这些方法也使用嵌入来考虑两个单词之间的关系。
卷积神经网络用于分类
在数学(特别是泛函分析)中,卷积是对两个函数(f 和 g)的数学运算,产生第三个函数,表示一个函数的形状如何被另一个函数修改。术语卷积既指结果函数,也指计算结果函数的过程。
因此,卷积最适合从图像的 2D 像素中提取特征值的特殊特征和行为。卷积层有一组内核,有助于从数据样本中提取几个重要特征。在文本分类的情况下,我们的特征矩阵是一维的。所以,这里用的是 Conv1D。基本上,它作为一个大小由用户决定的滑动窗口移动。我们选择了 5 个。
现在,最初在嵌入之后,我们得到 100 维嵌入。接下来使用 1D 卷积,我们试图使我们的特征集更小,并让特征集发现分类的最佳特征关系。max-pooling 层也有助于挑选具有最佳性能的特征或单词。
卷积层总是在嵌入层提供其嵌入的特征向量之后使用。
实施:
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Embedding,Dense, Activation, MaxPool1D,Conv1D
from tensorflow.keras.optimizers import Adam
emb_dim=100
model= Sequential()
model.add(Embedding(input_dim=vocab, output_dim=emb_dim,
input_length=maxlen))
model.add(Conv1D(64, 5, activation='relu'))
model.add(MaxPool1D(5))
model.add(Conv1D(128, 5, activation='relu'))
model.add(MaxPool1D(5))
model.add(Dense(16,activation="relu"))
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='Adam',loss='binary_crossentropy',metrics=['accuracy'])
模型摘要
这里我们训练了自己的 100 维嵌入矩阵。我们使用了两个卷积层,分别具有 64 个和 128 个内核滤波器。我们保持了滑动窗口=5。
该模型给出了 77%的测试准确度
使用递归神经网络进行分类
为什么选择递归神经网络?
到目前为止,我们一直试图从样本中的所有单词中一次提取一些特征。所以,它们都是非时间方法。现在,让我们看看一个人将如何判断一种情绪。他/她不仅会考虑使用了什么单词,而且人类还会考虑如何使用它们,即在什么上下文中,前面和后面的单词是什么?所以,到目前为止,我们只关注了所使用的单词,所以,现在让我们看看故事的另一部分。
因此,对于这一部分,我们需要一个递归神经网络来记忆我们的模型。如果我们想讲述某人的陈述,我们通常会逐字逐句地听完整个陈述,然后做出评论。这就是递归神经网络要完成的任务。它将逐个以时间方式查看每个单词,并尝试使用该单词的嵌入特征向量与上下文相关联。
我们知道 RNN 遭受消失和爆炸梯度问题我们将使用 LSTM。
LSTM 对两件事进行操作,一个是从前一个时间戳发送的隐藏状态,另一个是实际保持权重以抵消消失梯度效应的单元状态。
LSTM 层基本上有 4 个组成部分:一个遗忘门,一个输入门,一个单元状态和一个输出门。
现在,让我们谈谈 LSTM 的工作和数据流,因为我认为这将有助于展示特征向量实际上是如何形成的,以及它看起来是什么样子。
LSTM 方程
这些是 LSTM 运算的方程组。
LSTM 为密集层提供了一个关于最后时间戳的特征集,以使用该特征集产生结果。我们可以看到上面的方程是 LSTM 城门的方程。在这里,每个门单独充当一个神经网络。因此,在训练递归网络模型时,它们有自己的优化权重矩阵。使用这些权重矩阵,只有门学习它们的任务,例如要忘记哪些数据,以及需要将数据的哪一部分更新到单元状态。因此,门优化它们的权重矩阵,并根据它来决定操作。
现在,让我们看看它的用途。
假设我们有一个 100 维的向量空间。一批 16 个,每个样本长度= 10 个。并且每层中的节点数量= 64。
输入大小= batch_size *嵌入所以,这里是 16 x 100 矩阵= x(t)
时间戳 0 是每个样本或记录输入的第一个字。
x0 代表样本的第一个字,x1 代表第二个字,依此类推。因此,每次 1 个字来自 16 个样本,并且每个字由 100 长度的向量表示。因此,每个输入的大小是(16 x 100)。
前一隐藏状态(tiemstamp 0 的 0 向量)=批量大小 x 隐藏单元因此,这里是 16 x 64 矩阵。= h(t-1)
连接后,矩阵形成 h(t-1)= 16×64 和 x(t)= 16×100
所以 h(t-1) + x(t)矩阵被发送到所有的门 f(t),u(t)和 o(t)。
忘门
首先,隐藏状态的遗忘门权重矩阵 W{hf}的维数是 64×64,因为在隐藏状态中,对于时间戳(t-1)的 16 个字中的每一个,有来自 RNN 的 64 个节点中的每一个的 64 个值。
因此,实际上我们的隐藏状态矩阵的形状是(16 x 64):16 行记录,每条记录有 64 列或 64 个特征。
我们知道对于每个节点,
y=w1x1+w2x2+……..wnxn
等式成立。
其中 x 是要素或列值。因此,对于网络的每个节点或单元,必须有一个维护的 64 个权重的数组,一个对应于一个 x。现在有 64 个这样的单元,所以总共有(64×64)个矩阵。
同样,现在对于 shape (16 x 100)的输入向量,100 列或 100 个特征中的每一列都有 16 行或 16 条记录。因此,一个隐藏单元的权重矩阵必须有 100 个值。总共有 64 个单元。所以,权重矩阵 W{xf}的维数为。(100 x 64)
所以在遗忘之门
根据等式 1。
f { t } = sigmoid((16 x 100)x(100 x 64)+(16 x 100)x(100 x 64))
F{t}=sigmoid (16 x 64)向量
Sigmoid 给出一个介于 0 和 1 之间的值。如果该值接近 0,则该值被忽略,否则在通过 F{t}后被添加到单元状态。
现在,单元状态也具有相同的维度(16×64 ),因为它也具有 16 个样本单词乘以 64 个节点的权重,所以它们可以被容易地相加。
更新门
接下来,是输入或更新门它决定数据应该进入的部分,这意味着递归神经网络的实际更新功能。它决定是否应该更新单元状态。
这些门的权重矩阵也与遗忘门的矩阵相同,在最后一个隐藏层中具有(64×64)个值,在输入中具有(100×64)个值。
W{hu}的尺寸为 64x 64,W{xu}的尺寸为 100 x 64。下标为“h”的权重矩阵与 h(t-1)部分相乘,相应地,下标为“x”的权重矩阵与级联的{x(t) +h(t-1)}向量的 x(t)部分相乘,该级联的{ x(t)+h(t-1)}向量是通过将先前隐藏的层与当前输入相加而获得的。
每个带 h 的权重矩阵都有维数(64×64),每个带 x 的权重矩阵都有维数(100×64)。
因此,输入门的结果也是 sigmoid(16 x 64)
根据等式 2,
u { t } = sigmoid((16 x 100)x(100 x 64)+(16 x 100)x(100 x 64))
U{t}=sigmoid (16 x 64)向量
这里要注意的一件事是还有一个 tanh 层。tanh 在这里压缩 1 到-1 之间的值来处理爆炸和消失渐变。因此,它基本上像正则化值一样工作,表示该时间步长上临时单元状态的值。乙状结肠是开关。
根据等式 3,计算临时单元状态。
C1 { t } = tanh((16 x 100)x(100 x 64)+(16 x 100)x(100 x 64))
C1 { t } =双曲正切(16 x 64)向量
C1{t}和 U{t}向量矩阵具有相同的维数。因此,可以应用点积。
因此,在这之后,所获得的向量被相乘以获得 1 个结果。
关于这一点需要注意的一点是,虽然权重矩阵的维数相同,但它们并不相同。它们属于不同的门,它们的值和优化都是不同的。
细胞状态
现在,在下一步中,单元步骤被更新
它基本上是一个简单的总和。
新的 c 或单元状态是通过从上一步+当前时间步的完成中移除不需要的信息而形成的。如根据等式 5 所示。
输出门
接下来是输出门。这决定了隐藏层的下一步应该是什么。
为此,新的单元状态通过一个 tanh 门,h(t-1) + x(t)通过另一个 sigmoid。两个结果相乘。那是下一个。
根据等式 4,输出门决定下一个隐藏层。
o { t } = sigmoid((16 x 100)x(100 x 64)+(16 x 100)x(100 x 64))
O{t}=sigmoid (16 x 64)向量
这里我们可以看到 O(t)的维数和 h(t-1)匹配。
现在,这些权重随着每个单词在每个时间步更新,在第 10 个单词或时间戳(我们的情况中的最终时间戳)之后,模型已经遍历了样本中的所有单词,因此我们得到大小为 16 x 64 的矩阵,这基本上是与每个样本相对应的 64 个内部节点的权重值。但是,我们看不到同样经过优化的门的权重矩阵。这一行中的 64 个值基本上代表了由 64 个节点逐个产生的批次中的单个样品的重量。
对于所有的样本,我们获得一个值。这些值充当密集图层执行操作的要素集。
实施:
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Embedding,Dense, Activation, MaxPool1D, LSTM
from tensorflow.keras.optimizers import Adam
emb_dim=50
maxlen=100
model= Sequential()
model.add(Embedding(input_dim=vocab, output_dim=emb_dim,weights=[emb_mat], input_length=maxlen,trainable=False))
model.add(MaxPool1D())
model.add(LSTM(64, return_sequences = False))
model.add(Dense(16,activation="relu"))
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='Adam',loss='binary_crossentropy',metrics=['accuracy'])
模型摘要
这里,我们使用了预先训练的单词嵌入。我们已经使用了 1 个具有 64 个隐藏单元节点的 LSTM 层。
该模型提供了 78%的准确度
LSTM-CNN 模型
它是一个混合模型,由 LSTM 层和 CNN 层组合而成。
LSTM 图层正在为原始输入生成新的编码。然后,LSTM 层的输出被送入卷积层,我们希望卷积层能够提取局部特征。最后,卷积层的输出将汇集到一个更小的维度,并最终输出为正标签或负标签。
来源
结论
我们已经讨论了许多可以用于文本分类问题的方法,比如情感分析。
我希望这有所帮助。
Github 链接在这里是。