TowardsDataScience-博客中文翻译-2021-五十一-

TowardsDataScience 博客中文翻译 2021(五十一)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

如何用几行代码运行 30 个机器学习模型

原文:https://towardsdatascience.com/how-to-run-30-machine-learning-models-with-2-lines-of-code-d0f94a537e52?source=collection_archive---------1-----------------------

机器学习

了解如何使用 lazy predict 运行多个机器学习模型——代码跟随

图片由凯拉·伯顿拍摄。来源:像素

当开始一个新的监督机器学习项目时,第一步是分析数据,了解我们试图完成什么,以及哪些机器学习算法可以帮助我们实现我们的目标。虽然scikit-learn库使得用几行代码运行模型变得更加容易,但是当你需要测试多个模型时,它也是非常耗时的。然而,如果我们可以在进入更复杂的方法之前同时运行多个普通模型,并且更好地了解我们应该在哪些模型上投入宝贵的时间,会怎么样呢?

这就是lazy predict试图(成功)完成的事情。它在几秒钟内运行 30 个机器学习模型,并让我们了解模型在数据集上的表现。为了更好地理解我们如何使用lazy predict,我创建了一个泰坦尼克号幸存者预测项目,这样你就可以跟着编码了。你可以在这里找到完整的笔记本。你可以和我一起编码。Python、Pandasscikit-learn的基本经验将帮助您更好地理解正在发生的事情。

导入和清理数据

先来导入pyforest。PyForest 用一行代码导入了 40 个最流行的 Python 库。我写了一篇关于它的文章,你可以在这里找到它。我将使用警告库关闭一些难看的警告消息。我还将导入一些度量库。我们以后会需要它。

import pyforest
import warnings
warnings.filterwarnings("ignore")
from sklearn import metrics
from sklearn.metrics import accuracy_score

现在,让我们从 Kaggle 导入将要使用的数据集。你可以在这个链接上找到数据集。注意我没有导入Pandas。那是因为它是pyforest自带的。

# importing .csv files using Pandas
train = pd.read_csv(‘train.csv’)
test = pd.read_csv(‘test.csv’)

我将在本文中跳过一些探索性的数据分析,因为我们的主要焦点是开始使用lazypredict。然而,在我最初的 EDA 中,你可以在我的 GitHub 中找到,我注意到我们需要将列性别转换成数字。我们可以用一个lambda function轻松做到这一点。

train['Sex'] = train['Sex'].apply(lambda x: 1 if x == 'male' else 2)

我们还可以删除一些我们不会用于这个微型项目的分类列。对于家庭作业,我建议你在完成这篇文章后尝试使用这些特性。

train.drop(columns=[‘Name’,’Ticket’,’Cabin’, ‘PassengerId’, ‘Parch’, ‘Embarked’], inplace=True)

列车测试拆分

现在,让我们将我们的训练集分成变量 X 和 y。我将把所有的特征寻址到 X,除了存活的,这是我们的目标标签。

X = train.drop([‘Survived’], axis=1)
y = train.Survived

现在,让我们将变量分成训练集和测试集。我将使用默认的 0.25 作为测试大小。您可以使用轻松地添加其他值。

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)

建模**LazyPredict**

现在是娱乐的时候了。如果这是你第一次使用lazypredict,你必须安装它。为此,你可以在终端中输入pip install lazypredict。如果您已经安装了它,让我们将它导入到您的项目中。既然这是一个分类项目,那我们也导入LazyClassifier吧。

import lazypredict
from lazypredict.Supervised import LazyClassifier

最后,让我们运行模型,看看效果如何。

clf = LazyClassifier(verbose=0,ignore_warnings=True)
models, predictions = clf.fit(X_train, X_test, y_train, y_test)
models

瞧。你刚刚在不到 2 秒的时间内迭代了 30 个模型。这是令人难以置信的快速和毫不费力。然而,我们如何确保这些结果是准确的呢?现在,我们可以通过运行几个模型并比较它们来检查结果。对于这个项目,我将使用随机森林和逻辑回归模型测试数据集。让我们看看我们是否能接近刚刚看到的结果。先说随机森林。

rf = RandomForestClassifier()
rf.fit(X_train, y_train)
y_pred = rf.predict(X_test)

正如我们所看到的,准确性和 F1 分数得到了非常相似的结果。现在让我们试试逻辑回归。

rf = LogisticRegression()
rf.fit(X_train, y_train)
y_pred_lr = rf.predict(X_test)

同样,我们得到了非常相似的结果。看起来结果是可信的。那很容易。

结论

lazypredict是一个简单快捷的库,它可以很好地预测我们的模型在你的数据集。请记住,用lazy predict获得的结果不应被视为最终模型。统计学是数据科学的一个重要组成部分,因为不同的模型有不同的方法,所以在选择最终的模型之前,您应该知道每个模型是如何工作的。更重要的是,数据科学是一个复杂的领域,没有利弊就没有神奇的解决方案。将它作为您的第一次迭代,以确认您计划的方法,并使用scikit-learn等工具反复检查结果。玩得开心,让我知道它是否对你有用!

如何用几行代码运行 40 个回归模型

原文:https://towardsdatascience.com/how-to-run-40-regression-models-with-a-few-lines-of-code-5a24186de7d?source=collection_archive---------4-----------------------

机器学习

了解如何使用 Lazy Predict 为回归项目运行 40 多个机器学习模型

图片由马尔特赫尔姆霍尔德拍摄。来源: Unsplash

假设你需要做一个回归机器学习项目。你分析你的数据,做一些数据清理,创建几个虚拟变量,现在是时候运行机器学习回归模型了。你想到的十大车型有哪些?你们大多数人可能甚至不知道有十种回归模型。如果你不知道,不要担心,因为到本文结束时,你将不仅能够运行 10 个机器学习回归模型,而且能够运行 40 多个!

几周前,我写了如何用几行代码运行 30 个机器学习模型的博客,反响非常积极。事实上,这是我目前为止最受欢迎的博客。在那篇博客中,我创建了一个分类项目来尝试懒惰预测。今天,我将在一个回归项目上测试懒惰预测。为此,我将使用经典的西雅图房价数据集。你可以在 Kaggle 上找到它。

什么是懒预测?

Lazy Predict 有助于在没有太多代码的情况下建立几十个模型,并有助于了解哪些模型在没有任何参数调整的情况下工作得更好。展示其工作原理的最佳方式是一个简短的项目,所以让我们开始吧。

带有惰性预测的回归项目

首先,要安装 Lazy Predict,可以把pip install lazypredict复制粘贴到你的终端上。就这么简单。现在,让我们导入一些我们将在这个项目中使用的库。你可以在这里找到完整的笔记本。

**# Importing important libraries**
import pyforest
from lazypredict.Supervised import LazyRegressor
from pandas.plotting import scatter_matrix**# Scikit-learn packages**
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import ExtraTreesRegressor
from sklearn import metrics
from sklearn.metrics import mean_squared_error**# Hide warnings** import warnings
warnings.filterwarnings(“ignore”)**# Setting up max columns displayed to 100**
pd.options.display.max_columns = 100

你可以看到我导入的是pyforest而不是熊猫和 Numpy。PyForest 非常快速地将所有重要的库导入到笔记本中。我写了一篇关于它的博客,你可以在这里找到它。现在,让我们导入数据集。

**# Import dataset**
df = pd.read_csv('../data/kc_house_data_train.csv', index_col=0)

让我们看看数据集是什么样子的。

作者图片

好,现在让我们检查数据类型。

**# Checking datatimes and null values**
df.info()

作者图片

现在,一些事情引起了我的注意。第一个是id列与这个短项目没有任何关联。但是,如果您想更深入地了解项目,您应该检查是否有重复的项目。另外,date列是一个对象类型。我们应该将其更改为日期时间类型。列zipcodelatlong可能与价格的相关性很小或者没有相关性。但是,由于这个项目的目的是展示lazy predict,我将保留它们。

现在,让我们检查一些统计数据,看看在运行我们的第一个模型之前,我们是否能找到我们应该改变的任何东西。

作者图片

好吧。我能看到一些有趣的东西。首先,有一个有 33 间卧室的房子。那不可能是对的。于是,我在网上查了一下,原来我是用它的id在网上找到的房子,它居然有三个卧室。你可以在这里找到房子。还有,貌似还有 0 卫生间的房子。我将包括至少一个浴室,我们应该完成数据清理。

**# Fixing house with 33 bedrooms**
df[df['bedrooms'] == 33] = df[df['bedrooms'] == 3]**# This will add 1 bathroom to houses without any bathroom**
df['bathrooms'] = df.bedrooms.apply(lambda x: 1 if x < 1 else x)

列车测试分离

现在,我们已经准备好进行列车测试分割,但是在此之前,让我们确保代码中没有naninfinite值:

**# Removing nan and infinite values**
df.replace([np.inf, -np.inf], np.nan, inplace=True)
df.dropna(inplace=True)

让我们将数据集分成Xy变量。我将把数据集的 75%分配给训练集,25%分配给测试集。

**# Creating train test split**
X = df.drop(columns=['price])
y = df.price**# Call train_test_split on the data and capture the results**
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=3,test_size=0.25)

娱乐时间到了!以下代码将运行 40 多个模型,并显示每个模型的 R 平方和 RMSE。准备,设置,开始…

reg = LazyRegressor(ignore_warnings=False, custom_metric=None)
models, predictions = reg.fit(X_train, X_test, y_train, y_test)print(models)

作者图片

哇!对于在这上面花费的工作量来说,这些结果是很棒的。对于普通模型来说,这些是很好的 R 平方和 RMSE。如我们所见,我们运行了 41 个普通模型,获得了我们需要的指标,您可以看到每个模型花费的时间。一点也不差。现在,你怎么能确定这些结果是正确的呢?我们可以运行一个模型并检查结果,看看它们是否接近我们得到的结果。我们要测试基于直方图的梯度推进回归树吗?如果你从未听说过这个算法,不要担心,因为我也从未听说过。你可以在这里找到一篇关于它的文章

复查结果

首先,让我们使用 scikit-learn 导入这个模型。

**# Explicitly require this experimental feature**
from sklearn.experimental import enable_hist_gradient_boosting**# Now you can import normally from ensemble**
from sklearn.ensemble import HistGradientBoostingRegressor

同样,让我们创建一个函数来检查模型指标。

**# Evaluation Functions**
def rmse(model, y_test, y_pred, X_train, y_train):
 r_squared = model.score(X_test, y_test)
 mse = mean_squared_error(y_test, y_pred)
 rmse = np.sqrt(mse)
 print(‘R-squared: ‘ + str(r_squared))
 print(‘Mean Squared Error: ‘+ str(rmse))**# Create model line scatter plot**
def scatter_plot(y_test, y_pred, model_name):
    plt.figure(figsize=(10,6))
    sns.residplot(y_test, y_pred, lowess=True, color='#4682b4',
              line_kws={'lw': 2, 'color': 'r'})
    plt.title(str('Price vs Residuals for '+ model_name))
    plt.xlabel('Price',fontsize=16)
    plt.xticks(fontsize=13)
    plt.yticks(fontsize=13)
    plt.show()

最后,让我们运行模型并检查结果。

**# Histogram-based Gradient Boosting Regression Tree**
hist = HistGradientBoostingRegressor()
hist.fit(X_train, y_train)
y_pred = hist.predict(X_test)

作者图片

瞧啊。结果非常接近我们使用惰性预测得到的结果。好像真的很管用。

最后的想法

Lazy Predict 是一个非常棒的库,易于使用,运行速度快,只需要很少几行代码就可以运行普通模型。您可以使用 2 到 3 行代码来手动设置多个普通模型,而不是手动设置。请记住,您不应该认为结果是最终的模型,您应该总是仔细检查结果,以确保库工作正常。正如我在其他博客中提到的,数据科学是一个复杂的领域,懒惰预测不能取代优化模型的专业人员的专业知识。请让我知道它如何为你工作,如果还有任何其他问题。

如何使用 Docker 容器运行 Python 脚本

原文:https://towardsdatascience.com/how-to-run-a-python-script-using-a-docker-container-ea248e618e32?source=collection_archive---------1-----------------------

轻松运行 Python

照片由 Ales NesetrilUnsplash 拍摄

在这篇文章中,我将解释如何对一个现有的 Python 项目进行 Dockerize。我将使用我的一个 Python 项目进行演示。Dockerized 应用程序有很多好处。其中最突出的一点是,其他开发人员可以在没有任何环境管理的情况下顺利运行项目。可以省时省力,开发者可以专注于开发。如果你刚刚开始使用 Docker,那么请阅读下面的帖子,我已经介绍了一些基础知识。

设置

首先,您需要安装 Docker 并从 GitHub 下载一个 git 库。对于这个设置,我使用的是 macOS。

现在,我将为孟加拉语创建一个包含 Python、Tesseract 和 train 数据的 Docker 映像。让我们来分解一下 Dockerfile 文件的各个组成部分。

FROM python:3.9.1
RUN apt-get update
RUN apt-get -y install tesseract-ocr
RUN apt-get install tesseract-ocr-ben
ADD . /tesseract-python
WORKDIR /tesseract-python
RUN pip install -r requirements.txt

From命令用于定义父图像。这里我使用的是 Docker Hub 上预建的官方图片 Python 。之后,我使用RUN命令更新了高级打包工具( APT ,用于安装 Tesseract OCR 引擎和下载列车数据。使用ADD命令,我将把当前文件夹中的所有内容添加到图像中名为 tesseract-python 的目录中。之后,我将使用WORKDIR命令将工作目录设置为 tesseract-python 。最后,使用 pip,我将安装应用程序的依赖项:pytesseract 和 Pillow。

如果你想下载特定的训练数据,那么使用下面的命令。

RUN apt-get install tesseract-ocr-[lang]

或者如果你想下载所有的训练数据,那么使用下面的命令。

RUN apt-get install tesseract-ocr-all

现在,我将创建一个 Docker 合成文件,使用我刚刚创建的 Docker 映像运行 Docker 容器。让我们来分解一下 docker-compose.yml 文件的各个组成部分。

version: "3.8"
services:
  app:
    build: .
    stdin_open: true
    tty: true
    volumes:
      - .:/tesseract-python

版本标签用于定义合成文件格式。你可以从这里阅读更多内容。在服务散列下,我们必须定义我们的应用程序想要使用的服务。对于我的应用程序,我只有一个名为 app 的服务。现在我正在用我的 Dockerfile 文件建立我的形象。stdin_opentty标签用于保持我的容器运行。卷标签用于将文件夹从主机安装到容器。

现在从 docker-compose.yml 文件所在的目录运行下面的命令。以下命令将启动并运行整个应用程序。

docker compose up

现在运行docker ps来查看所有正在运行的容器。这里,我有一个。

我可以通过运行下面的命令来访问正在运行的容器tesseract-python_app_1

docker exec -it tesseract-python_app_1 bash

现在,您可以运行以下命令来查看文件。

ls
Dockerfile  LICENSE  README.md ben.txt  docker-compose.yml  eng.txt  main.py  requirements.txt  test_ben.png  test_eng.png

让我们使用以下命令运行 Python 脚本。

python main.py

输出。

_ The'quick brown fox' .
-jumps over the lazy:
dog.

পথের দেবতা প্রসন্ন হাসিয়া বলেন-মূর্থ বালক, পথ তো
বীরু রায়ের বটতলায় কি ধলচিতের খেয়াঘাটের সীমানায়.
(তোমাদের সোনাডাঙা মাঠ ছাড়িয়ে ইচ্ছামতী পার হয়ে
পদ্যফুলে ভরা মধুখালি বিলের পাশ কাটিয়া বেব্রবতীর
খেয়ায় পাড়ি দিয়ে, পথ আমার চলে গেল সামনে, সামনে,
শুধুই সামনে...দেশ ছেড়ে দেশান্তরের দিকে, সূর্যোদয় ছেড়ে
সূর্ধান্তের দিকে, জানার গন্ডী এড়িয়ে অপরিচয়ের উদ্দেশে.

现在,您可以在主机上更改代码,并在 Docker 容器中运行它,以便进一步开发。

包裹

通过使用这种方法,您不必担心安装依赖项和管理环境。此外,其他开发人员可以快速运行项目,而无需任何额外的工作。使用这个过程,您还可以将您的 Ruby、JAVA 或其他项目 Dockerize。编码快乐!

相关职位

如何在 Altair 和 Streamlit 中运行动画

原文:https://towardsdatascience.com/how-to-run-animations-in-altair-and-streamlit-2a0624789ad?source=collection_archive---------17-----------------------

数据可视化

一个现成的教程,描述了如何使用 Altair 和 Streamlit 构建动画折线图。

作者图片

Altair 是一个非常流行的用于数据可视化的 Python 库。通过 Altair,您可以用几行代码构建非常复杂的图表,因为该库遵循 Vega-lite 语法提供的指导原则。

不幸的是,Altair 不支持本地动画,因为通过 Vega-lite 渲染它们很复杂。

在本教程中,我演示了一种将 Streamlit 的功能与 Altair 相结合的机制,以呈现动画折线图。

Streamlit 是一个非常强大的 Python 库,它允许用很少的代码行用 Python 构建 Web 应用程序。

设置

首先,我安装所需的库:

pip install streamlit
pip install altair

为了构建一个 Streamlit 应用程序,我可以编写一个 Python 脚本,它不能是 Jupyter 笔记本的形式,因为目前 Streamlit 不支持 Jupyter

因此,我创建了一个名为AltairAnimation.py的脚本,我将所有需要的库导入到我的脚本中:

import pandas as pd
import altair as alt
import streamlit as st
import time

然后,我加载数据集。例如,我利用了欧盟统计局数据库发布的 2012 年至 2020 年的意大利游客数量。我利用 Pandas 库来加载数据集:

df = pd.read_csv('../sources/tourist_arrivals.csv')

作者图片

该数据集包含每月到达的游客人数。我将日期转换成一个datetime类型:

df['date'] = pd.to_datetime(df['date'])

构建基本图表

我通过Chart()类在 Altair 中构建了一个空图。具体来说,我指定我想通过mark_line()函数画一条线。然后,我设置图表的轴(xy)以及widthheight。作为x轴的默认值,我设置了1:T,其中T表示一个时间变量。相反,对于 y 轴,我将默认值设置为0:Q,其中 Q 表示一个量,即一个数字。

lines = alt.Chart(df).mark_line().encode(
     x=alt.X('1:T',axis=alt.Axis(title='date')),
     y=alt.Y('0:Q',axis=alt.Axis(title='value'))
).properties(
    width=600,
    height=300
)

我还定义了一个函数,用作为参数传递的数据帧更新图表:

def plot_animation(df):
    lines = alt.Chart(df).mark_line().encode(
       x=alt.X('date:T', axis=alt.Axis(title='date')),
       y=alt.Y('value:Q',axis=alt.Axis(title='value')),
     ).properties(
       width=600,
       height=300
     ) 
     return lines

构建动画

我想建立一个如下的动画:

作者制作的动画

当用户点击开始按钮时,动画开始,并且最初它仅绘制数据帧的前 6 个月。然后,将另外 6 个月添加到图中,以此类推,直到数据框的大小。

这可以通过以下方式实现。首先,我定义了一些辅助变量:

N = df.shape[0] # number of elements in the dataframe
burst = 6       # number of elements (months) to add to the plot
size = burst     # size of the current dataset

现在我可以构建 Streamlit 接口了。我画了一个图表和一个按钮:

line_plot = st.altair_chart(lines)
start_btn = st.button('Start')

最后,我可以制作动画:

if start_btn:
   for i in range(1,N):
      step_df = df.iloc[0:size]
      lines = plot_animation(step_df)
      line_plot = line_plot.altair_chart(lines)
      size = i + burst
      if size >= N: 
         size = N - 1
      time.sleep(0.1)

如果用户点击开始按钮(if start_btn:),则循环开始,直到元素数量N-1。构建了部分数据帧,包括第一个size元素。然后,在该部分数据帧上构建图表,并更新变量size

运行 Web 应用程序

最终,我准备好运行 Web 应用程序了。从命令行,我可以运行以下命令:

streamlit run AltairAnimation.py

该 Web 应用程序将在以下 URL 提供:

**http://localhost:8501**

摘要

在本教程中,我展示了如何在 Altair 中利用非常强大的 Streamlit 库构建动画。

我的 Github 库中可以找到实现的 Web 应用的完整代码。

我真的要感谢 A B ,他写了这篇文章,这篇文章激发了我的灵感。

如果你想了解我的研究和其他活动的最新情况,你可以在 TwitterYoutubeGithub 上关注我。

相关文章

如何使用贝叶斯统计运行更好更直观的 A/B 测试

原文:https://towardsdatascience.com/how-to-run-better-and-more-intuitive-a-b-tests-using-bayesian-statistics-480acf4b8679?source=collection_archive---------23-----------------------

带有示例和代码的贝叶斯 A/B 测试指南

为什么你应该使用贝叶斯 A/B 测试而不是传统的方法

A/B 测试是当今技术、营销和研究中最有用的统计技术之一。它的价值在于 A/B 测试允许你确定因果关系,而大多数分析只揭示相关性(即古训“相关性而非因果关系”)。尽管 A/B 测试的力量和流行,绝大多数遵循一种基于 t-测试的单一方法,这种方法来自 frequentist 统计学派。本笔记将介绍一种使用贝叶斯统计学派的替代方法。这种方法比传统的 frequentist 方法返回更直观的结果,以及一些有用的额外见解。

传统的频率主义方法使用假设作为 A/B 测试的框架。零假设通常是现状,例如,A 的平均值等于 B 的平均值,替代假设测试是否存在差异,例如,A 的平均值大于 B 的平均值。选择一个置信水平,例如 5%,实验可以有两个结论之一:

  1. 我们拒绝零假设,接受 95%置信度的替代假设,例如,A 的均值大于 B 的均值,或者
  2. 我们不会以 95%的置信度拒绝零假设,也就是说,我们无法对 A 和 b 之间的均值差异做出结论。

这种语言不是我们在商业中倾向于说的,对于不太熟悉 A/B 测试的人来说,可能很难理解。特别是,第二个结论没有提供太多的洞察力;花费时间和金钱进行测试后,你只能得出结论,没有任何结论是可能的。(关于这种方法的更多信息,请查看我之前关于用 Python 实现 A/B 测试的帖子)。

相反,贝叶斯方法关注的是概率。如果测试上面的同一个示例,假设 A 的均值等于 B 的均值,贝叶斯方法将计算均值的估计差异以及一个大于另一个的概率,而不仅仅是均值差异是否为 0。在我看来,贝叶斯方法优于频率主义方法,因为它能以特定的概率有效地接受和拒绝零假设。这种方法提供了更有用的建议。两个示例结论(类似于 frequentist 结论)是:

  1. 平均值 A 有 99%的概率大于平均值 B(这个例子拒绝了零假设)
  2. 平均值 A 有 65%的概率大于平均值 B(这个例子不会拒绝零假设)

这种语言给出了结论的可能性,以便决策者有权选择自己的风险承受能力,并避免了无法拒绝零假设和无法得出结论的情况。

更有用的是,它可以计算均值之间的估计差值。这意味着贝叶斯检验的一个可能结论是“平均 A 估计比平均 B 大 0.8 个单位,平均 A 比平均 B 大的概率为 83%”。另外,贝叶斯方法还可以比较 A 和 B 的方差,并固有地管理异常值。

贝叶斯方法的缺点是支持它的数学可能更具挑战性。很好地理解贝叶斯统计和马尔可夫链蒙特卡罗抽样是有帮助的,但不是完全关键的。

接下来的部分将通过一个例子来展示如何使用贝叶斯方法进行 A/B 测试,以及用 r。

A/B 测试数据概述

为了演示贝叶斯方法,我将使用我在 2020 年初进行的一组调查的数据。调查包括围绕 3 个主题的 13 个问题,涉及受访者对抗击冠状病毒措施的看法(4 个问题)、受访者对政府应对冠状病毒措施的认可程度(3 个问题)和一般家庭活动问题(5 个问题)。完整的问题列表包括 此处 。在这个例子中,我们将关注那些有数字答案的问题,比如“你一天花多少时间和你的家人或室友在一起?”

调查设计包括 6 个相似但不同的调查版本。运行这些略有不同的调查的目的是 A/B 测试它们之间的差异是否会导致统计上不同的结果。每项调查的不同之处在于问题的顺序或者问题以肯定或否定的方式表达。一个积极措辞与消极措辞的例子是:

  • 正面:你认为政府建议的社会距离会持续多久?
  • 否定:你认为政府规定的社交距离会持续多久?

下表显示了不同调查版本的汇总。共记录了 291 份调查回复,每个调查版本包含 45-47 份回复。这意味着调查 1 的结果可以与调查 3 和调查 5 的排序差异进行比较,也可以与调查 2 的措辞差异进行比较。

调查版本概述

贝叶斯分析

以下分析主要基于 2012 年 Kruschke 和 R package BEST 的研究论文“贝叶斯估计取代 t 检验”。代码在我的 Github 中。

与任何贝叶斯估计一样,这种贝叶斯技术利用一组先验信念,这些信念用来自数据的证据进行更新,以返回一组后验分布。以下分析根据 Kruschke - 2012 使用 t 分布和马尔可夫链蒙特卡罗算法,以及对后验分布影响有限的不明确先验。不明确的先验对后验分布有最小的影响,这对本研究是有用的,因为本研究没有基线或先验信念集可以容易地进行比较。这种方法对于管理异常值也是有效的,并且只需要对一个出错的数据点进行调整。

如果前一段有点复杂,不用担心。您仍然可以通过下面的步骤得到一个易于解释的输出。要了解更多,请阅读 Kruschke 的论文。

第一步:加载包和数据

第一步是安装所需的软件包。我们将使用使用 JAGS 包装的最好的包装。在运行 BEST 之前先下载 JAGS 。下一个安装最佳。一旦这一切都完成了,加载包。

还要加载数据并为分析做好准备。我们使用的是 survey_data_v2.csv,可以在这里找到。

加载包和数据

第二步:创建贝叶斯分析函数

接下来,我们要创建一个函数,允许我们选择要比较的调查版本以及测试要比较的调查问题。该函数运行马尔可夫链蒙特卡罗抽样方法,构建我们测试的后验分布,即一个均值大于另一个均值的概率以及均值的估计差异。

为贝叶斯分析创建函数

第三步:运行测试

最后,选择两组数据进行比较。在本例中,我们将使用调查版本 1 和 2,并比较问题 2。改变函数变量来测试不同的调查和问题。

运行测试

步骤 4:解释输出

运行上述代码后,会弹出一个窗口,显示以下输出。它主要显示代表后验分布的 100,000 个可信参数值组合的直方图。

贝叶斯 A/B 测试的输出

A/B 测试最重要的输出是显示均值差异的中右分布。对于我们的示例,它显示平均而言,平均值 A 比平均值 B 大 0.214 个单位,平均值 A 比平均值 B 大 82.9%的概率。该结果是 A/B 测试的主要结论。注意,传统的 t 检验会简单地返回结果,即我们不能在 95%的置信度下拒绝零假设。

另一个输出显示了用于解释数据的其他有用信息。右上角的两个以 y 为轴的图表显示了测试数据的实际分布。其他图显示了后验分布。左侧图中的五个直方图显示了对应于五个先前直方图的个体后验概率。右下角的图表显示了 A 组和 b 组之间的比较。

关键要点

与传统的频繁测试方法相比,贝叶斯方法有三个主要优点:

  1. 一组更直观的结果,例如,平均值 A 比平均值 b 大 82.9%。
  2. 包括 A 和 B 之间的差的大小,例如,平均值 A 估计比平均值 B 大 0.214 个单位
  3. 不受无效假设未被拒绝的结果的约束。

这些优势结合起来形成更有用和直观的建议,使决策者能够更好地理解测试结果并选择自己的风险水平。

买我的儿童读物来支持我:mybook.to/atozofweb3

Github 知识库

https://github.com/bondicrypto/bayesian_abtesting

参考

[1]约翰·克鲁施克,“贝叶斯估计取代了 t 检验。”实验心理学杂志。第 142 卷,第 3 期,2012 年,第 142 页。573–603,2021 年 1 月 3 日访问,

[2]加洛,艾米 2017。《哈佛商业评论》A/B 测试回顾,2021 年 1 月 3 日

[3] Hussain,Noor Zainab 和 Sangameswaran,S. 2018,2018 年全球广告支出将增长 4.5%:Zenith,路透社,2021 年 1 月 3 日获取,

[4] Lavorini,Vincenzo,用 Python 进行贝叶斯 A/B 测试:面向数据科学的简易指南,2021 年 1 月 3 日访问,

[5]maza arenu,E. 2019,美国市场研究—统计与事实,Statista,2021 年 1 月 3 日访问,https:。</https:>

[6] NSS 2016。贝叶斯统计用简单的英语向初学者解释,分析 Vidhya,2021 年 1 月 3 日访问,

如何用两行代码创建复杂的数据科学项目

原文:https://towardsdatascience.com/how-to-run-complex-machine-learning-models-with-2-lines-of-code-e0a541502ee9?source=collection_archive---------25-----------------------

机器学习

使用 PyCaret 创建一个完整的数据科学项目,从数据清理到复杂的机器学习模型

图片由 Vlada Karpovich 提供。来源:像素

一位读者最近在我的博客中问我是否尝试过PyCaret。我答应我会尝试,我很高兴我做到了。PyCaret允许你用两行代码运行整个数据科学项目,从数据清理、处理类不平衡,到超调机器学习模型。不相信我?没关系,我第一次尝试的时候也不敢相信,但事实是它确实有效。让我先向您展示一下PyCaret的运行情况,然后我们可以更深入地了解这个库。出于演示的目的,我将使用 Titanic Survivor 数据集,它包括分类、数字和NaN值。结果如下:

作者图片

下面是刚刚发生的事情:PyCaret处理分类数据,将数据集分为训练集和测试集,进行日志实验,检查异常值,修复类不平衡,并在不到 30 秒的时间内运行从逻辑回归到 XGBoost 的模型。它也用两行代码得到了 0.8154 的精度。现在,让我们了解更多关于PyCaret的工作原理以及如何使用它。

PyCaret 是什么?

他们的网站是这样说的:

PyCaret 是一个用 Python 编写的开源、低代码机器学习库,允许您在自己选择的笔记本环境中,在几分钟内从准备数据到部署模型。

看来PyCaret言出必行。从准备数据到用 2 或 3 行代码部署监督和非监督模型。我在几个不同的项目中测试了它,包括一些过去工作过的旧项目,结果与我工作一周后得到的结果非常接近。为了向您展示它是如何工作的,让我们一起创建一个分类项目。你可以在这里找到我写这篇博客用的笔记本。很快我也会发布一个回归项目。敬请期待!

装置

有几种方法可以通过你的终端安装PyCaret。强烈建议使用虚拟环境,以避免与其他库冲突。第一个是在您的终端中键入pip install pycaret,这是一个精简版的PyCaret及其硬依赖。要安装完整版,可以输入pip install pycaret[full],这是我推荐的。

开始一个新项目

PyCaret对它提供的东西非常有信心,他们的团队给了我们 55 个数据集,你可以自己试试这个库。这些问题包括:异常检测,关联规则挖掘,二元和多元分类,聚类,自然语言处理和回归。

一旦您安装了PyCaret,您可以在 Jupyter 笔记本上输入以下内容,以获得他们提供的数据集列表。

# Get data
from pycaret.datasets import get_data
from pycaret.classification import *
index = get_data('index')

数据集的列表很长,我不会在此添加所有数据集,但您可以从以下分类数据集中进行选择:

作者图片

对于这个项目,我将与信用卡默认项目。这有点挑战性,而且非常接近现实生活中的问题。要选择数据集,您只需键入data = get_data('name_of_the_dataset')。由于我们将测试信用卡默认数据集,我们需要键入data = get_data('credit')并运行单元格。

现在,我们已经做好了数据准备。这需要一行代码。PyCaret将返回一个包含数据集信息的表格,我们将能够决定如何继续。为此,我们将设置数据集、目标标签、实验名称等。下面是代码中最重要的部分:

clf1 = setup(data, target = ‘default’, session_id=123, log_experiment=True, experiment_name=’default1')

运行以下代码后,我们将得到以下问题:以下数据类型已被自动推断,如果它们是正确的,请按 enter 键继续,否则键入' quit'。键入enter继续。

作者图片

上面这段代码所做的是通过数据清理、训练测试分割、测试日志转换、多项式、转换类别数据、解决类别不平衡,以及你能想到的任何其他数据准备。你可以看到我写的log_transformation = True是个例子,但是有几十个数据准备选项。我强烈建议您键入shift + tab并检查您可以做的所有数据准备工作。我可以就此写一整篇文章(我可能会这样做),但现在,让我们从基础开始。

运行模型

现在,是时候运行基线模型了。到目前为止,在加载数据集之后,我已经编写了一行代码。我们现在将使用另一行代码运行 16 个机器学习模型。我将使用 5 倍的交叉验证。

作者图片

运行所有模型花了 1 分 36 秒,包括一些复杂的集合模型。让我们来看看结果:

作者图片

这里需要注意一些事情。首先,XGBoost 失败了。没关系。我们还有 15 个模型要分析。PyCaret为我们提供了多个指标,并强调了每个指标的最佳结果。对于这个项目,我们需要考虑召回指标,当假阴性的成本很高并且我们得到了 0.90 的召回分数时,就会用到这个指标。你也可以通过输入来创建单独的模型,例如qda = create_model('qda')

作者图片

qda代表二次判别分析模型。默认情况下,PyCaret将测试集分成 10 层。你可以通过输入qda = create_model('Ada', fold = 5)来编辑。要查看您可以运行的模型的完整列表、它们使用的库以及缩写,请键入models()

作者图片

您可以键入tune_models(lr)来调整超参数。在这种情况下,提高了一些指标,但实际上降低了召回分数。

作者图片

使用PyCaret还可以做很多其他的事情,比如分析和解释模型,用维持集测试模型,保存和部署模型。

作者图片

我鼓励您访问他们的网站,查看他们的文档、项目和更多教程。我将在另一篇文章中讨论很多内容。

最后的想法

PyCaret似乎很神奇,言出必行。然而,正如我总是喜欢提醒读者的那样,数据科学是一个复杂的角色,你不能用几行代码来代替专业人员。如果你喜欢使用PyCaret作为你下一个项目的额外步骤,并且理解你的数据集的潜力,那就去做吧。我用多个数据集进行了尝试,结果非常接近我在一个项目中工作了整整一周所能得到的结果。但是,我不建议你把它用于你的最终结果或者作为一种捷径。您可以将它作为流程的一部分添加进来,无需键入几十行代码就能快速获得洞察力。祝你尝试愉快,并告诉我进展如何。

不久我也将发布一个使用PyCaret的回归项目,所以请在 Medium 上关注我,了解最新动态。如果你喜欢这篇文章,别忘了留下你的掌声👏。它激励我继续写作。

如何使用 AWS 和 GCP 上的数千个 Spot 实例运行基于 CPU 的深度学习工作负载,而不会感到头痛

原文:https://towardsdatascience.com/how-to-run-cpu-intensive-workloads-for-deep-learning-with-thousands-of-spot-instances-on-aws-and-85ce9d452f10?source=collection_archive---------40-----------------------

安德烈·沙皮洛在 Unsplash 上拍摄的照片

深度学习因在训练过程中消耗大量 GPU 资源而臭名昭著。然而,深度学习工作流程中有多个部分需要大量的 CPU 资源:

  1. 运行大规模推理作业
  2. 预处理输入数据——并将其物化在磁盘上作为
    训练准备

这些工作负载通常具有以下属性:

  1. 工作负载(作业)会定期触发(相对于持续处理)
  2. 一个作业由许多项组成。每个项目都可以独立于其他项目进行。
  3. 项目被读取、处理并写回到某个存储器(通常是对象存储器或集中式文件系统)
  4. 在单个 CPU 内核上处理一个项目可能需要几秒到几分钟的时间
  5. 用户关心作业的吞吐量,而不是处理单个项目的延迟
  6. 单个项目的大小范围从几十 KB 到几 MB 甚至几 GB 的数据
  7. 该处理是无状态的—即,如果单个项目的处理失败,可以安全地重试,而不会产生任何副作用。

当您有足够多的项目要处理,并且单个项目的处理足够繁重时,这些作业会消耗大量的 CPU 资源。

很多是多少?

工作负载示例—训练数据的 3D 渲染

假设我们想要用在不同环境中拍摄的大量真实世界对象的图像来训练一个模型。制作大量示例的一个好方法是使用合成数据——获取物体的 3D 模型,并从多个角度、照明条件等渲染这些模型的视图。

3D 渲染是众所周知的 CPU 密集型工作负载;在单个 CPU 内核上渲染一幅图像可能需要几分钟时间。

渲染 250K 的图像会消耗 30K+的 CPU 时间。

我们如何处理这样的工作量?首先,让我们形式化我们的需求。

系统需求

一般

  1. 横向扩展至数千个内核
  2. 通过 就地运行实例来最大限度地降低云成本
  3. 最大限度降低基础设施设置和维护成本

用于运行作业的 API

  1. 配置每个作业的处理逻辑
  2. 配置作业中每个项目所需的 CPU+内存
  3. 配置从何处读取/写入数据
  4. 提交要处理的作业的所有项目
  5. 取消作业(即不处理其项目)
  6. 观察每个作业的成功/剩余/失败项目数
  7. 观察 CPU/内存消耗(帮助调整资源)
  8. 查看每个项目的日志(最好有—搜索日志)

逻辑系统设计

这些需求非常适合队列+工人的设计模式。

逻辑批处理系统设计。作者图片

逻辑流程

让我们浏览图表,了解每个阶段发生了什么:

1-用户将容器推入容器注册表。
该容器包含所需的处理逻辑和依赖关系。

2-用户将包含要处理的项目的消息排入队列。

每条消息包含:

  • 存储中某个项目的 URI
  • 可选—控制处理逻辑的配置/元数据

3 —如果需要,计算会自动缩放。
准备就绪后,消息会出队并交给可用的容器。

4 —容器从存储中读取一个项目,对其进行处理,并根据消息中的指令将输出写回

最后,系统会自动收集指标并记录到一个集中的位置。

艰难的方式——在 Kubernetes 上自己构建

以下是使用 K8s 实现这一目标所需的几个步骤:

  1. 首先—您需要设置 K8s,以便能够管理数千个节点 —从冗余到调整控制平面等。
  2. 创建使用混合策略在现场运行的节点组
  3. 部署消息总线——在集群上或集群外部
  4. 弄清楚如何向外扩展:
    您是否应该让用户预先指定规模并部署一个副本集+通过更新大小和使用集群自动缩放器杀死空闲节点来找到自动向下扩展的方法?
    或者使用像 KEDA 那样的动态缩放器?
  5. 如果存储是一个共享文件系统,您需要创建持久卷,并自己将它们装入容器;如果是对象存储,我们可能需要将凭证作为秘密传入
  6. 通过集中式日志记录和监控添加完整的可观察性堆栈
  7. 用 Terraform 将它转化为红外线代码
  8. 等等。

这对于大多数团队来说是不可行的,因为工作量非常大,尤其是需要旋转和管理集群中成百上千的节点,即使是临时的

编辑—其他基于集群的解决方案

这一部分是在 LinkedIn 上热烈讨论后添加的。

除了 K8s 之外,还有其他解决方案可以帮助管理横向扩展工作负载,例如 Ray、Dask 甚至 Spark。

所有这些工具的共同点是,它们都有集群的概念,为机器之间需要交换数据的工作负载而构建,并且至少需要一些机器之间的某种形式的通信(例如,主对工人)。

当您扩展到 1000 个节点时,这种管理和通信会引入各种边缘情况,处理起来并不容易。如果您部署了集群,您就拥有了它。即使在像 EKS 这样的“托管”集群中,您仍然需要确保它正常运行。

在推理/预处理中—在节点通信的集群上运行没有任何附加价值。这些是不共享的工作负载。集群组件只是一个负担。相反,你想要的是提供你的代码和要处理的项目列表,并让计算机为你处理它。

这让我们有了更简单的选择…

注意:如果您的工作负载是用 Python 之外的语言编写的,或者需要不寻常的操作系统级库,并非所有上面提到的集群管理器都支持它。

简单的方法—利用托管解决方案

自动警报系统

AWS 为这种类型的工作负载构建了完美的工具,恰当地命名为
AWS Batch。

大规模批处理系统的 AWS 批处理解决方案。作者图片

让我们浏览图中的实体,并解释其工作原理:

计算环境

计算资源集合;可以包含多种节点类型,包括定点或按需节点。

计算环境指定其混合/最大大小,其中将最小值设置为 0 使其能够在没有工作要执行时扩展到零。
横向扩展时,计算环境基于实例模板创建实例。

AWS 批量计算环境。作者图片

实例模板

关于如何初始化实例的标准 EC2 构造。
可以包含向实例添加挂载等指令。

队列

AWS Batch 为您管理队列。每个队列都连接到一个特定的计算环境。这使我们能够轻松地为单独的作业创建单独的队列,并将作业相互隔离,使它们不会争用资源。

作业定义(注意:AWS 批处理术语中的作业是单个项目 ) 单个项目处理的模板。
指定:

  • docker 图像。变量和其他详细信息
  • 来自主机的装载点
  • 此类作业所需的计算资源(CPU/mem 甚至 GPU)
  • 如何将参数从消息传递到容器的入口点。

用户 Docker 图片

在 AWS Batch 中,用户的 docker 需要包含一个可以处理队列中单个项目的命令。它的返回代码用于确定处理是成功还是失败。

工单
要处理。与作业定义有“实例”关系,包含处理特定项目的特定参数值。

作业对象是我们插入到队列中执行的对象。

将流程整合在一起

  • 用户将作业放入队列。作业引用了一个作业定义**
  • 如果需要,c 计算机环境通过从实例模板创建一个新节点来扩展
  • 系统根据新实例上的作业定义启动一个容器
  • 系统从队列中弹出一个项目
  • 系统调用容器上的处理命令,并从作业的主体向其传递参数
  • 命令的返回值用于确定处理是成功还是失败。

可观察性

AWS Batch 提供了一个仪表板,其中显示了所有队列、多少作业(项目)正在等待/运行/成功/失败,以及对日志的访问。

日志是在项目级别上提供的,跨项目搜索日志并不容易。要获得基础架构级别的监控,您需要在底层 ECS 集群上启用容器洞察

AWS 批处理作业仪表板。作者图片

总之,AWS Batch 获得 9/10 作为大规模 CPU 作业的解决方案

GCP

GCP 没有针对此类工作负载的内置解决方案。然而,您可以使用较低级别的构建块和少量的粘合代码实现与 AWS Batch 非常相似的东西,而不会比 AWS 产生更多的持续操作开销。

该解决方案的本质依赖于 GCP 独有的一个特性:启动一个计算实例的能力,该实例在启动时自动启动带有参数的 docker 容器。

基于 GCP 计算引擎的批处理系统解决方案。作者图片

托管 Instace 组

这是一组可以根据条件放大和缩小的实例。该组的实例是从一个实例模板创建的。参见自动缩放部分。

实例模板

定义系统中单个实例的外观:

  1. 实例(即容器)的资源— CPU/Mem/GPU。
  2. 挂载点
  3. 引导时启动容器的配置:
  • Docker 图像
  • 命令+参数

这些参数是静态的,即从该模板启动的所有容器将以完全相同的命令和参数启动。

  • 为容器本身安装
  • 该模板的实例是否可抢占

队列

在这里,您需要使用自己的队列。一个好的选择是为您的环境利用一个 PubSub 队列,以及一个默认订阅。

工作

作业作为定制的 json 有效载荷写入到 PubSub 订阅中;除此之外,它们应该包含处理单个项目所需的所有信息,包括项目的 URI 和任何处理配置

用户 Docker 图像

因为 GCP 没有提供基于消息调用容器的内置框架,所以从队列中取出工作项是容器的责任。

回想一下,在启动时传递给容器的参数是为所有运行在来自同一个模板的实例上的容器指定的。利用这些参数的一个好方法是配置它们来保存容器需要读取的订阅的名称。

最后,因为容器启动一次,而且只有在它的实例启动时才启动一次,所以容器的 entry 命令需要在一个循环中提取和处理项目,直到队列为空。

自动缩放

托管实例组能够基于 Stackdriver 指标进行伸缩。
具体来说,您将希望基于“发布订阅中未传递的消息”进行缩放。详见本帖

将流程整合在一起

  • 用户将包含要处理的项目的消息排入 PubSub 队列中。
  • 托管实例组根据实例模板使用“订阅不足”缩放规则创建新实例
  • 当实例启动时,它使用实例模板中提供的命令和静态参数运行用户的容器
  • 用户的命令循环运行:从队列中弹出一个项目,处理它,等等。
  • 当队列为空时,管理实例组将缩小所有实例

可观察性

GCP 提供了比 AWS 更方便的记录和监控解决方案;您可以搜索现成的日志流,查看实例组级别的指标以及单个机器等。

GCP 管理的实例组监视仪表板。作者图片

将功能包装在 SDK 中

为了便于采用这样的系统,明智的做法是为用户提供一个 CLI/SDK 来处理具体细节。

SDK 的主要 API 用于提交新的作业进行处理,通过指定:

  1. 作业名
  2. 队列名称(或自动创建一个与作业同名的新队列)
  3. 代表计算模板的名称(可以是作业定义或具有适当 InstanceTemplate 的 ManagedInstanceGroup 的名称)
  4. URI 待加工物品清单

然后,SDK 将使用底层云提供商的 API 来:

  1. 如果需要,创建队列(在 GCP,这意味着以编程方式为作业创建新的实例模板和托管实例组)
  2. 构造消息并将其放入队列,做一些事情,如转换路径或 ID,以便远程容器可以访问它们等。

注意:
可以添加更多的 API,例如获取工作进度报告等。

摘要

随着团队在深度学习模型的开发过程中继续充分利用他们的数据,他们通常需要运行大型 sclae CPU 密集型工作负载的能力。

这些批处理作业执行一些任务,例如对大型数据集执行推理,或者将大文件预处理成更有用的表示形式。

这些大规模作业可能需要数千个 CPU 内核,并对自我管理的基础架构提出了巨大的扩展挑战。

在这篇文章中,我们介绍了如何构建一个框架,以经济高效的方式在 GCP 和 AWS 中运行这样的工作。

如何运行脸书-先知预测 X100 更快

原文:https://towardsdatascience.com/how-to-run-facebook-prophet-predict-x100-faster-cce0282ca77d?source=collection_archive---------6-----------------------

向量化先知的不确定性建模

  • 01/25/23 编辑:FB 工程师将本文中的解决方案集成到版本 1.1.2 的包中。由于一些实现上的差异,它仍然比本文最后的解决方案稍慢,但不是很慢。
  • 如果您对学习矢量化和 Prophet 的内部工作方式不感兴趣,而只想更快地运行 Prophet,您可以跳到TL;博士在最后。

脸书先知

脸书的用于时间序列预测的 Prophet 包于 2017 年发布,自此成为最受欢迎的预测算法之一:据 PyPy 称,Prophet 被下载了约 2000 万次。尽管有人批评模型的准确性以及许多机器学习应用程序向神经网络发展的总体趋势,下载流仍在继续。Prophet 的受欢迎程度可能源于其简单的开箱即用、置信区间、清晰的可视化,以及它经常胜过经典统计算法(ARIMA、ETS)的事实。

无论多受欢迎,Prophet 都有一个巨大的缺点:它非常慢,并且不能扩展到数十万个项目。

让我们尝试运行以下代码,创建一个随机时间序列:

import pandas as pd
import numpy as np
import datetime
from fbprophet import Prophetn = 100
some_data = pd.DataFrame({‘ds’:pd.date_range(datetime.datetime(2020,1,1,), freq=’W’, periods=n), ‘y’: np.random.rand(n)})

现在让我们测试运行时间:

%%timeit
prophet = Prophet(interval_width=0.8)
prophet.fit(some_data)

输出:

# 91.5 ms ± 1.66 ms per loop

大约 0.1 秒来拟合数据。但是真正的痛苦出现在“预测”阶段:

%%timeit
prophet.predict(some_data)

输出:

1.15 s ± 55.9 ms per loop

得到预测需要整整一秒以上的时间!这是令人惊讶的,因为在大多数 ML 模型中,训练是昂贵的,而预测是廉价的。

在这篇文章中,我们将看到为什么 Prophet 的 predict 函数相对较慢,以及如何让它运行快 100 倍(注意,您仍然必须首先拟合模型,因此 fit+predict 只会看到 5-20 倍的改善)。在这个过程中,我们将学习一些关于时间序列不确定性建模、统计分布和矢量化的知识。

让我们首先解释 Prophet 的不确定性建模及其部分代码,然后展示我们如何轻松地对函数进行矢量化。

寻找耗时函数

如果您剖析这个“预测”代码,您就可以看到错误在哪里。

预言家的预测简介。(图片由作者提供)

大概 98%的时间都花在“预测 _ 不确定性”上。此函数在结果数据帧中创建“yhat_upper”和“yhat_lower ”,它们是 80%(或 interval_width 中给定的任何其他值)置信区间的边缘——实际点可能位于此处。

当 Prophet 对不确定性建模时,它会做什么,这需要很长时间?

先知的不确定性

(如果你不熟悉 Prophet 的附加模型,你可能应该从一个快速概述开始)

Prophet 建模假设数据中有两个不确定性来源:

  1. 趋势线周围的高斯残差
  2. 更改坡度值

拟合时,Prophet 会在训练数据中找到趋势变化的最佳点,以最佳地拟合数据-假设趋势在任何给定点都是线性的,但趋势的斜率可能会发生变化。自然地,发现的趋势变化越多,相邻斜率之间的差值越大,未来值的不确定性就越大,如这些例子所示。

左图:当有许多变化点时,不确定性会快速增长。右图:历史变化点很少(它们之间的差值很小),不确定性主要取决于历史残差。(图片由作者提供)

如果训练数据中的趋势变化显著且频繁,则未来可能值的范围很大。相比之下,如果趋势在训练数据中相对恒定,我们更确定它将在未来以直线路径继续,在这种情况下,唯一剩余的误差源是我们已经在历史数据中看到的残差(它不随时间增长)。

我们不会讨论 Prophet 如何找到变化点及其增量,这都是在拟合阶段完成的。

预测拟合模型中的不确定性

以下是 Prophet's predict_uncertainty 的“释义代码”(压缩后,为了清晰起见,去掉了一些不重要的部分)(可以直接跳到文字描述):

让我们用文字来概括这个过程:

以下是这些趋势样本的样子:

用 fbprophet 随机抽样未来趋势。(图片由作者提供)

训练数据有两个斜率变化。图中显示了五条未来趋势线,注意每条线的变化点数量、发生时间以及斜率之间的差值都是不同的。

Prophet 将高斯噪声添加到这些趋势线中,为我们提供了:

随机抽样期货与 fbprophet,包括随机残差。(图片由作者提供)

最后,它为每个时间步长的值找到 10%和 90%的分位数,给出我们的置信区间。

优化运行时间

我们的目标是通过向量化它使这个过程更有效。对矢量化的详细解释超出了本文的范围,但可以说,如果我们去除 for 循环并在 NumPy 数组上执行所有操作,该过程将运行得更快。

在我们对代码进行矢量化之前,让我们注意到这个过程的一部分是多余的:均值周围的置信区间的大小仅取决于斜率变化的可能性和大小以及过去的残差;因此,我们不需要连接训练数据的斜率、截距和增量,并评估它们的值。该区间的平均值取决于最终趋势线 yhat,yhat 取决于训练数据截距和斜率,但它是在 predict_uncertainty 开始之前计算的。

我们可以假设斜率=0,截距=0,使用斜率变化的可能性和大小,找到所有时间步长的 10%-90%间隔(例如+/-8)。然后,我们将这个值加到 yhat(例如 17)上,得到置信区间(9-25)。

主预测已创建(虚线)

一、不确定性的大小计算在 0 左右。二。该间隔将被添加到主预测中。(图片由作者提供)

请注意,随着时间的增加,置信区间的宽度也会增加(这在直觉上是有意义的)。这是因为我们对未来的预测越多,趋势变化的影响就越大。

现在让我们向量化

请记住,我们的目标是创建一个矩阵,其中每行是一个采样趋势,每列是未来的某个日期。例如

(图片由作者提供)

但是具有 1000+行。

首先,我们需要对斜率变化的数量和位置进行采样。这是 Prophet 从每一行的泊松分布中取样,然后随机分配变点数。没有泊松,我们会得到同样的结果。在任何时间步长发生变点的可能性由训练数据中观察到的变点数量除以训练数据的长度确定。假设我们有一个经过训练的 prophet_obj 和一个预测未来日期的 forecast_df,可能性是:

prophet_obj.changepoints_t 是训练数据中发生变化点的时间列表。什么是 single_diff?这是 Prophet 对时间进程建模的结果。

先知的时间进程

在 train 和 predict 函数中,Prophet 将 Pandas 数据帧中的 time(“ds”)列转换为一个名为 t 的数组,表示时间的进展。由于种种原因,训练时 t 在 0-1 范围内比较方便。所以,在训练中,t 是通过将任意两个元素之间的间隔设置为 1/training_length 来创建的。例如,如果有 50 个训练数据点,t 等于[0,0.02,0.04,..., 0.98, 1.].对于预测,它将继续以相同的间隔[1.02,1.04...]直到 forecast_df 的长度。

因为 t 数组代表时间的进程,所以它可以用来计算一段时间的进程。例如, some_coef*t 创建线性趋势,其中 some_coef 代表斜率。因此,斜率为 4 意味着在每个时间步长中,该系列增加 4*single_diff (在本例中为 4*0.02)。

随着时间变化斜率=4 的值(y 轴)( x 轴)。作者图片

回到矢量化斜率变化

我们现在有了在任一给定点斜率变化的可能性。让我们创建一个斜率变化矩阵:

其中 k 是样本数(行数)。结果是一个布尔矩阵:

随机布尔变点矩阵。(图片由作者提供)

这就是奇迹发生的地方。取每行的总和,绘制分布图,你会得到:

随机布尔矩阵的行和是泊松分布。(图片由作者提供)

具有似然 len(future_t_time)均值的泊松分布*!准确地从哪个 Prophet 样本中为每一行设置 n_changes!

这直接来源于泊松的定义——如果你有 q 个独立的抽奖,每个抽奖都有 l 为正的可能性,那么你会得到一个平均值为 q*l 的泊松分布

我们替换了 Prophet 对一行中的变点数量的 for-loop 采样——然后对它们在时间步长中的位置进行采样——并且用整个矩阵的一行来替换它

但是我们不需要一个布尔值来判断是否发生了变化——我们需要变化的增量。这部分很简单:

我们创建一个新的样本矩阵,这个矩阵来自拉普拉斯分布,具有平均绝对训练数据增量的标度。为什么是拉普拉斯?我不知道是否有理论上的正当理由,但这就是 Prophet 所做的,所以我们遵循它(除了 Prophet 为每一行单独执行采样,我们采样一个矩阵)。取两个矩阵的乘积,得到:

斜率变化值矩阵。(图片由作者提供)

每个时间步长内每个采样趋势的斜率变化(记住行=采样趋势,列=时间步长)。

我们快完成了!现在我们需要从斜率变化过渡到实际预测值。

斜率-实际值的变化

假设我们有下面的斜率增量(相邻台阶之间斜率值的变化):【0,1,0,0,-4,0,2】。假设我们从 0 的实际斜率开始,每一步的斜率将是[0,1,1,1,-3,-3,-1],对于每一个时间步,我们取增量之和,或者换句话说:“累计”。

实际值的差值示例。(图片由作者提供)

但是这仅仅给出了每个点的斜率(而不是斜率增量)。我们想要实际值!线性斜率意味着我们在每次迭代中增加斜率值。如果 3 个时间步长的斜率为 2,实际值将为[2,4,6];很明显,这是另一个坎姆。因此,从斜率增量矩阵过渡到时间序列的实际值:

记住斜率为 4 意味着 4*single_diff 是实际值,所以我们取这个新矩阵与 single_diff 的乘积。

添加高斯残差

现在我们有了样本趋势矩阵,我们只需要添加高斯噪声:

其中 sigma 是训练数据中趋势的标准偏差。

我们完成了样本矩阵的矢量化创建。如果我们希望置信区间在 10%-90%之间,我们设置

简单地将区间的上下边缘添加到 yhat 预测中。全部完成!除了一些小问题(请随意跳过接下来的 3 个部分)。

中期趋势变化

矢量化代码和 Prophet 之间有一个微小的建模差异。Prophet 允许斜率变化在时间步长之间发生。例如,如果 t = [1.02,1.04,1.06…],斜率变化可以设置为 1.028。或者换句话说:如果您的数据代表周一的周值,Prophet 允许周六或其他任何一天的斜率变化。

我不确定这种建模是否对所有数据集都有意义。还有,从我的经验来看,差别可以忽略不计。

然而,为了完整起见:让我们考虑在第一个实际步骤之前发生的趋势变化(在 1.0–1.02 中)。如果它接近 1.0(前一个星期一),到时间步长 1.02 时,我们将得到一个完整步长的变化(4*single_diff)。但如果接近 1.02(周日),斜率变化对那个时间步长影响不大。这种变化可能发生在光谱的任何地方,最好的修正是两个极端的平均值:每一个时间步长都是前一个时间步长(第一个时间步长为 0)。

另一种方法是创建一个具有 k 倍多的列的矩阵,并且改变点的可能性是先前可能性的 1/k。该矩阵将表示比时间序列中的间隔更小的间隔。在 cumsum.cumsum 之后,我们可以提取每第 k 列。但是,这种差异可能是微不足道的。

逻辑增长

默认情况下,Prophet 假设增长是线性的,但您可以将其设置为逻辑,在这种情况下,斜率变化的创建保持不变,但从矩阵到采样趋势的转换完全不同(非线性)。Prophet 为这种转变编写的代码是巨大的,但是将代码转换成矢量化版本是微不足道的。我不会在这篇文章中解释它,但下面给出了矢量化代码供您使用。

训练数据

最后一个问题——以上所有内容都适用于对未来的预测,在这种情况下,趋势值是未知的,因此需要进行采样。但是,有时我们对训练数据调用预测函数。那里的不确定性只取决于趋势周围的高斯噪声,所以我们可以将 sample_trends 设置为零。

时间和准确度对比

矢量化版本的速度有多快?

%%timeit
add_prophet_uncertainty(p, forecast_df)

输出:

2.13 ms ± 139 µs per loop

相比之下,原始的、非矢量化的 Prophet 版本为 1s+。这是 500 倍的进步。

它返回的结果和 Prophet 一样吗?相当接近。

(图片由作者提供)

为什么结果不一样?请记住,这是一个随机过程,由 Prophet 和矢量化代码创建的 1000 个样本不会有完全相同的值。如果标准差很大— 1000 个样本不足以让大数定律生效。再次运行它,你会得到一个稍微不同的结果。事实上,由于矢量化版本快得多,我将 k 样本设置为 10000,这给出了更一致的结果,这就是为什么它比上面例子中 Prophet 的预测更平滑。即使有 10000 个样本,仍然只需要大约 13 毫秒

TL;博士

首先定义这些函数(如果您从不使用逻辑增长—您可以删除 prophet_logistic_uncertainty 及其用法,这占代码的一半以上):

给定一些 training_df,如果您需要训练和预测的不确定性区间,请运行以下代码:

在 Python Jupyter 笔记本中运行线性混合效果模型的三种方法

原文:https://towardsdatascience.com/how-to-run-linear-mixed-effects-models-in-python-jupyter-notebooks-4f8079c4b589?source=collection_archive---------4-----------------------

实践教程

关于如何在 Python 和 Jupyter 笔记本中运行线性混合效应回归(LMER)模型的教程

森林西蒙Unsplash 上拍照

我不能完全从 R 切换到 Python 进行数据分析的原因之一是线性混合效应模型只在 R 中可用。线性混合效应模型是一种强大的统计方法,在处理纵向、层次或聚类数据时非常有用。简而言之,如果您的数据具有重复的样本、相关数据或自然“分组”,例如来自同一个人的重复响应、按不同地理位置聚类的数据,甚至是来自一组交互的人的数据,您可能希望在分析中使用线性混合效应模型。

您可以从这些资源(林德斯特罗姆&贝茨,1988 ) ( 贝茨等人,2015 )中了解更多关于线性混合效应模型或线性混合效应回归(LMER)如何以及为什么有效的信息,但在本教程中,我们将重点关注如何在 Python Jupyter 笔记本环境中运行这些模型。在早期,人们从 Python 中保存数据,在 R 中打开数据并运行 LMER 模型。多年来,R & Python 对彼此有了更好的了解,出现了几种用 Python 运行 LMER 分析的选项。下面是我们将探讨的三个选项,我为每个选项提供了示例代码:

  1. 统计模型中的 LMER
  2. 使用 rpy2 和%Rmagic 访问 R 中的 LMER
  3. Pymer4 无缝接入 LMER R

这里有一个 Google Colab Jupyter 笔记本来遵循这些方法!

统计模型中的 LMER

目前,最简单的开箱即用解决方案是使用 Statsmodels 包中的 LMER 实现(示例此处为)。安装最容易,就像pip install statsmodels一样简单。安装后,您可以像下面这样运行 LMER。

为了提供更多的背景信息,我们正在分析dietox数据集(在此了解更多关于数据集的信息),以预测猪的weight作为time的函数,其随机斜率由re_formula="~Time"指定,随机截距由groups=data["Pig"]自动指定。输出如下图所示,包括系数、标准误差、z 统计、p 值和 95%置信区间。

Statsmodels LMER 输出

虽然这很好,但是用这种语法指定随机效应有些不方便,并且偏离了 LMER 在 R 中使用的传统公式表达式。例如,在 R 中,随机斜率和截距是在模型公式中指定的,在一行中,例如:

lmer('Weight ~ Time + (1+Time|Pig)', data=dietox)

这导致了我们的第二个选择,即通过 rpy2 在 Python 和 R 之间的直接接口在 R 中使用 LMER。

使用 rpy2 和%Rmagic 访问 R 中的 LMER

第二种选择是通过 rpy2 接口直接访问 R 中原来的 LMER 包。rpy2 接口允许用户在 Python Jupyter 笔记本环境和 R 环境之间来回传递数据和结果。rpy2 过去在安装上是出了名的挑剔,但是这些年来它变得更加稳定了。要使用这个选项,您需要在您的机器上安装 R 和 rpy2,这可以在 Google Colab 中通过以下代码实现:

第一行使用 Linux 语法安装 R。如果你使用的是 Mac 或 Windows,你可以简单地按照安装说明来完成。下一组命令行安装 rpy2,然后使用 rpy2 安装lme4lmerTest包。

接下来,您需要通过运行以下代码,在 Jupyter 笔记本单元中激活 Rmagic。

%load_ext rpy2.ipython

在这之后,任何以%%R开头的 Jupyter 笔记本单元都允许你从笔记本上运行 R 命令。例如,要运行我们在 statsmodels 中运行的模型,您需要执行以下操作:

请注意,该代码以%%R开头,表示该单元包含 R 代码。我们还使用了比 statsmodels 更简单的公式表达式,我们能够指定我们的分组是Pigs,并且我们正在通过(1+Time|Pig)估计随机斜率和截距。这将给出一些结果,如果您在 r 中使用过 LMER,您会更加熟悉这些结果

rpy2 的 LMER 输出

正如我前面提到的,您也可以将您的熊猫数据帧传递给 r。还记得我们之前在 statsmodels 部分加载的data数据帧吗?我们可以将它传递给 R,运行相同的 LMER 模型,并像这样检索系数:

-i data将我们的 Python 熊猫数据帧data发送到 R 中,我们用它来估计我们的模型m。接下来,我们从带有beta <- fixef(m)的模型中检索贝塔系数,该系数被导出回我们的笔记本,因为我们在第一行-o betas中指定了。

这种方法最好的部分是,在运行模型之前,您可以在 R 环境中添加额外的代码。例如,您可能希望确保名为Evit的列被识别为带有data$Evit <- as.factor(data$Evit)的因子,使用contrasts(data$Evit) <- contr.poly为该分类变量指定新的对比,或者甚至在公式本身中重新调整分类数据。当使用 rpy2 从 r 访问 LMER 时,所有这些都可以很容易地实现

总之, rpy2 接口为您提供了最大的灵活性和访问 LMER 和 R 中附加功能的能力,如果您正从 R 过渡到 Python,您可能会更熟悉这些功能。最后,我们将使用 Pymer4 包来接触一个中间选项。

LMER 与皮梅尔 4

Pymer4 ( Jolly,2018 )可以作为直接通过 rpy2 使用 LMER 和在 Statsmodels 中使用 LMER 实现之间的一个方便的中间地带。这个包基本上给你带来了使用 R 公式语法的便利,但是以一种更 Pythonic 化的方式,而不必处理 R 魔细胞。

Pymer4 的 LMER 输出

估计值包括随机截距和斜率估计值。

结论

我们介绍了在 Python Jupyter 笔记本环境中运行线性混合效果模型的 3 种方法。Statsmodels 可能是最方便的,但是对于已经使用过 R 语法中的 LMER 的用户来说,这种语法可能并不熟悉。使用 rpy2 为您提供了最大的灵活性和能力,但这可能会变得很麻烦,因为您需要使用 Rmagic 在 Python 和 R 单元之间切换。Pymer4 是一个很好的折衷方案,它提供了对 R 中 LMER 的方便访问,同时最小化了语言之间的切换成本。

这里有一个谷歌 Colab Jupyter 笔记本来运行所有的教程。

感谢您的阅读,并随时查看我的其他数据科学教程!

https://jinhyuncheong.medium.com/membership

如何在 Python 中对聚合数据运行逻辑回归

原文:https://towardsdatascience.com/how-to-run-logistic-regression-on-aggregate-data-in-python-a779ab7970b3?source=collection_archive---------24-----------------------

每个数据科学家都应该知道的 3 个简单解决方案

照片由叶小开·克里斯托弗·古特瓦尔德Unsplash 上拍摄

ι将向您展示 3 种技术,当您想要执行逻辑回归时,它们将帮助您处理 Python 中的聚集数据。

让我们创建一些虚拟数据。

import pandas as pd
import numpy as np
import statsmodels.api as sm
import statsmodels.formula.api as smf

df=pd.DataFrame(
{
'Gender':np.random.choice(["m","f"],200,p=[0.6,0.4]),
'Age':np.random.choice(["[<30]","[30-65]", "[65+]"],200,p=[0.3,0.6,0.1]),
"Response":np.random.binomial(1,size=200,p=0.2)
    }
)

df.head()Gender      Age  Response
0      f  [30-65]         0
1      m  [30-65]         0
2      m    [<30]         0
3      f  [30-65]         1
4      f    [65+]         0

非聚集数据的逻辑回归

首先,我们将对非汇总数据运行逻辑回归模型。我们将使用库统计模型,因为这是我们将用于聚合数据的库,并且更容易比较我们的模型。此外,统计模型可以以更经典的统计方式(如 r)给我们一个模型的摘要。

提示:如果您不想将分类数据转换成二进制来执行逻辑回归,您可以使用 统计模型公式 来代替 Sklearn。

model=smf.logit('Response~Gender+Age',data=df)
result = model.fit()
print(result.summary())
Logit Regression Results                           
==============================================================================
Dep. Variable:               Response   No. Observations:                  200
Model:                          Logit   Df Residuals:                      196
Method:                           MLE   Df Model:                            3
Date:                Mon, 22 Feb 2021   Pseudo R-squ.:                 0.02765
Time:                        18:09:11   Log-Likelihood:                -85.502
converged:                       True   LL-Null:                       -87.934
Covariance Type:            nonrobust   LLR p-value:                    0.1821
================================================================================
                   coef    std err          z      P>|z|      [0.025      0.975]
--------------------------------------------------------------------------------
Intercept       -2.1741      0.396     -5.494      0.000      -2.950      -1.399
Gender[T.m]      0.8042      0.439      1.831      0.067      -0.057       1.665
Age[T.[65+]]    -0.7301      0.786     -0.929      0.353      -2.270       0.810
Age[T.[<30]]     0.1541      0.432      0.357      0.721      -0.693       1.001
================================================================================

聚合数据的逻辑回归

1.使用有反应者和无反应者的逻辑回归

在下面的代码中,我们对数据进行了分组,并为响应者( Yes )和非响应者( No )创建了列。

grouped=df.groupby(['Gender','Age']).agg({'Response':[sum,'count']}).droplevel(0, axis=1).rename(columns={'sum':'Yes','count':'Impressions'}).eval('No=Impressions-Yes')
grouped.reset_index(inplace=True)
groupedGender      Age  Yes  Impressions  No
0      f  [30-65]    9           38  29
1      f    [65+]    2            7   5
2      f    [<30]    8           25  17
3      m  [30-65]   17           79  62
4      m    [65+]    2           12  10
5      m    [<30]    9           39  30
glm_binom = smf.glm('Yes + No ~ Age + Gender',grouped, family=sm.families.Binomial())
result_grouped=glm_binom.fit()
print(result_grouped.summary())
Generalized Linear Model Regression Results                  
==============================================================================
Dep. Variable:          ['Yes', 'No']   No. Observations:                    6
Model:                            GLM   Df Residuals:                        2
Model Family:                Binomial   Df Model:                            3
Link Function:                  logit   Scale:                          1.0000
Method:                          IRLS   Log-Likelihood:                -8.9211
Date:                Mon, 22 Feb 2021   Deviance:                       1.2641
Time:                        18:15:15   Pearson chi2:                    0.929
No. Iterations:                     5                                         
Covariance Type:            nonrobust                                         
================================================================================
                   coef    std err          z      P>|z|      [0.025      0.975]
--------------------------------------------------------------------------------
Intercept       -2.1741      0.396     -5.494      0.000      -2.950      -1.399
Age[T.[65+]]    -0.7301      0.786     -0.929      0.353      -2.270       0.810
Age[T.[<30]]     0.1541      0.432      0.357      0.721      -0.693       1.001
Gender[T.m]      0.8042      0.439      1.831      0.067      -0.057       1.665
================================================================================

2.加权逻辑回归

对于这个方法,我们需要创建一个新列,其中包含每个组的响应率

grouped['RR']=grouped['Yes']/grouped['Impressions']glm = smf.glm('RR ~ Age + Gender',data=grouped, family=sm.families.Binomial(), freq_weights=np.asarray(grouped['Impressions']))
result_grouped2=glm.fit()
print(result_grouped2.summary())
Generalized Linear Model Regression Results                  
==============================================================================
Dep. Variable:                     RR   No. Observations:                    6
Model:                            GLM   Df Residuals:                      196
Model Family:                Binomial   Df Model:                            3
Link Function:                  logit   Scale:                          1.0000
Method:                          IRLS   Log-Likelihood:                -59.807
Date:                Mon, 22 Feb 2021   Deviance:                       1.2641
Time:                        18:18:16   Pearson chi2:                    0.929
No. Iterations:                     5                                         
Covariance Type:            nonrobust                                         
================================================================================
                   coef    std err          z      P>|z|      [0.025      0.975]
--------------------------------------------------------------------------------
Intercept       -2.1741      0.396     -5.494      0.000      -2.950      -1.399
Age[T.[65+]]    -0.7301      0.786     -0.929      0.353      -2.270       0.810
Age[T.[<30]]     0.1541      0.432      0.357      0.721      -0.693       1.001
Gender[T.m]      0.8042      0.439      1.831      0.067      -0.057       1.665
================================================================================

3.展开聚合数据

最后,我们可以“解组”我们的数据,并将我们的因变量转换为二进制,这样我们就可以像往常一样执行逻辑回归。

grouped['No']=grouped['No'].apply(lambda x: [0]*x)
grouped['Yes']=grouped['Yes'].apply(lambda x: [1]*x)
grouped['Response']=grouped['Yes']+grouped['No']

expanded=grouped.explode("Response")[['Gender','Age','Response']]
expanded['Response']=expanded['Response'].astype(int)

expanded.head() Gender      Age Response
0      f  [30-65]        1
0      f  [30-65]        1
0      f  [30-65]        1
0      f  [30-65]        1
0      f  [30-65]        1
model=smf.logit('Response~ Gender + Age',data=expanded)
result = model.fit()
print(result.summary())
Logit Regression Results                           
==============================================================================
Dep. Variable:               Response   No. Observations:                  200
Model:                          Logit   Df Residuals:                      196
Method:                           MLE   Df Model:                            3
Date:                Mon, 22 Feb 2021   Pseudo R-squ.:                 0.02765
Time:                        18:29:33   Log-Likelihood:                -85.502
converged:                       True   LL-Null:                       -87.934
Covariance Type:            nonrobust   LLR p-value:                    0.1821
================================================================================
                   coef    std err          z      P>|z|      [0.025      0.975]
--------------------------------------------------------------------------------
Intercept       -2.1741      0.396     -5.494      0.000      -2.950      -1.399
Gender[T.m]      0.8042      0.439      1.831      0.067      -0.057       1.665
Age[T.[65+]]    -0.7301      0.786     -0.929      0.353      -2.270       0.810
Age[T.[<30]]     0.1541      0.432      0.357      0.721      -0.693       1.001
================================================================================

结论

对于所有 4 个模型,我们得出了相同的系数和 p 值。

根据我的经验,我发现获取项目的原始数据并不常见,在大多数情况下,我们处理的是聚合/分组数据。这些技术将帮助你轻松地处理它们,这就是为什么我认为是你的 Python 工具箱的一个很好的附件。

如果你正在使用 R,你可以阅读这个非常有用的帖子

以后我会写更多初学者友好的帖子。在媒体上关注我访问我的博客了解他们。

我欢迎提问、反馈和建设性的批评,你可以通过推特(Twitter)或社交网站(Instagram)联系我。

原载于https://predictivehacks.com

如何运行(与模型无关的元学习)MAML 算法

原文:https://towardsdatascience.com/how-to-run-model-agnostic-meta-learning-maml-algorithm-c73040069810?source=collection_archive---------14-----------------------

MAML 是一类元学习算法

作者图片

MAML 是一类元学习算法,由斯坦福研究中心和加州大学伯克利分校校友切尔西·芬恩博士创建。MAML 受到了这个问题背后的想法的启发,这个问题就是学习一件事情到底需要多少数据。我们能教算法学会如何学习吗?

在这样的背景下,传统的机器学习算法面临一些挑战:

  1. 需要强化训练
  2. 某些问题的标记数据可能是有限的
  3. 网络的性能可能对超参数的选择敏感

在这方面,元学习算法可以被设计来处理以下任务:

  1. 感应偏置的动态选择
  2. 构建多任务学习的元规则
  3. 学习如何通过超参数优化来学习

摘自切尔西·芬恩的原始研究:

MAML 是一种元学习算法,它与用梯度下降算法训练的任何模型兼容,并涵盖分类、强化学习(RL)和回归的问题

MAML 解决了什么样的问题?

MAML 被设计为在各种任务上训练模型,使得它可以仅用少量训练样本来学习新的学习任务。

MAML 的几个要点是:

  1. MAML 没有增加学习参数的数量。
  2. 对模型的架构或网络没有限制。
  3. 可以与其他深度学习框架结合,如递归神经网络(RNN)、卷积神经网络(CNN)和多层感知器(MLP)。

问题设置

MAML 的问题设置是从原始论文中复制的:

MAML 引入了一个叫做元训练的外部循环。

如何运行 MAML 代码?

Chelsea Finn 的 Github repo 提供了重现 MAML 结果的代码。您可以使用以下步骤来重现其结果:

  1. 我将创建一个 python 虚拟环境并安装依赖项:
    sudo apt install virtualenv virtualenv — python=python3.6 maml
    source maml/bin/activate
  2. 接下来,我们安装依赖项:
  3. pip install tensorflow==1.11.0 pip install image 我没有使用最新版本的 Tensorflow,因为 MAML 代码是几年前写的,当时 TF2 还没有公开发布。
  4. 克隆 MAML 回购:
    git clone [https://github.com/cbfinn/maml](https://github.com/cbfinn/maml)
  5. 下载 omniglot 数据,对于本文,除了正弦示例之外,我将只运行 omniglot 示例:
    wget [https://github.com/brendenlake/omniglot/raw/master/python/images_background.zip](https://github.com/brendenlake/omniglot/raw/master/python/images_background.zip) wget [https://github.com/brendenlake/omniglot/raw/master/python/images_evaluation.zip](https://github.com/brendenlake/omniglot/raw/master/python/images_evaluation.zip)
  6. 将 images_background 和 images_evaluation zip 文件解压到maml/data/omniglot文件夹,其中mamal文件夹是 Github repo 文件夹。目录结构如下所示:

7.导航到maml文件夹的data子文件夹,将omniglot的内容复制到omniglot_resized。运行调整图像大小脚本

cd maml/data
cp -r omniglot/* omniglot_resized/
cd omniglot_resized
python resize_images.py

8.现在,我们回到 maml repo
的根目录,运行两个示例:

a .正弦曲线示例:

python main.py --datasource=sinusoid --logdir=logs/sine/ --metatrain_iterations=70000 --norm=None --update_batch_size=10

b. omniglot 示例:

python main.py --datasource=omniglot --metatrain_iterations=60000 --meta_batch_size=32 --update_batch_size=1 --update_lr=0.4 --num_updates=1 --logdir=logs/omniglot5way/

每个例子的检查点都会保存在log/目录下。

更新:我发现代码库中有一个 bug。我认为这个漏洞可能是无意中引入的。在main.py中,第 160 行saver.save(sess, FLAGS.logdir + ‘/’ + exp_string + ‘/model’ + str(itr))itr变量是for循环迭代器,我认为saver.save语句应该在循环末尾的 for 循环内执行,而不是在循环外执行。

从这里开始,我相信一个中级水平的机器学习实践者应该能够修改流水线以满足他/她的要求。

如何使用 Docker 运行 PostgreSQL 和 pgAdmin

原文:https://towardsdatascience.com/how-to-run-postgresql-and-pgadmin-using-docker-3a6a8ae918b5?source=collection_archive---------0-----------------------

Docker 使 PostgreSQL 管理变得更加容易

照片由 bongkarn thanyakijPexelsGuillaume BolducUnsplash

如果您不喜欢使用命令行界面管理数据库,您可以使用 pgAdmin 作为替代解决方案。它是基于 web 的 PostgreSQL 数据库服务器的前端。

我们将使用 Docker 进行设置,因为我们不想担心环境管理。通过使用 Docker,我们不必担心 PostgreSQL 或 pgAdmin 的安装。此外,您可以使用 Docker 在 macOS、Windows 和 Linux 发行版上运行这个项目。

通过这篇文章,您将了解如何使用 Docker 将 pgAdmin 连接到 PostgreSQL 数据库服务器。

设置

首先,你需要安装 Docker 。我将使用 macOS 进行演示。

方法一

我们将使用一个 Docker compose 文件作为我们的第一个方法,我们需要将 docker-compose.yml 放在一个文件夹中。在这种情况下,文件夹的名称是 pgAdmin 。我们来分解一下 docker-compose.yml 文件的各个成分。

version: '3.8'
services:
  db:
    container_name: pg_container
    image: postgres
    restart: always
    environment:
      POSTGRES_USER: root
      POSTGRES_PASSWORD: root
      POSTGRES_DB: test_db
    ports:
      - "5432:5432"
  pgadmin:
    container_name: pgadmin4_container
    image: dpage/pgadmin4
    restart: always
    environment:
      PGADMIN_DEFAULT_EMAIL: admin@admin.com
      PGADMIN_DEFAULT_PASSWORD: root
    ports:
      - "5050:80"

首先,我们使用版本标记来定义合成文件格式,即 3.8。还有其他文件格式——1、2、2.x 和 3.x。你可以从 Docker 的文档中了解更多信息。

然后我们有一个散列叫做服务。在这里面,我们必须定义我们的应用程序想要使用的服务。对于我们的应用程序,我们有两个服务, db、pgadmin

为了方便起见,我们对两个服务都使用了标签 container_name ,将默认容器名改为 pg_containerpgadmin4_container

第二个标签图像用于定义 dbpgadmin 服务的 Docker 图像。为了使我们的设置过程快速简单,我们将使用预先构建的官方映像 PostgreSQLpgAdmin

在我以前的 Docker 帖子中,我已经谈到了重启、环境端口标签的使用。看看下面的帖子,你可以学习这些标签。

现在从 docker-compose.yml 文件所在的目录运行下面的命令。

cd pgAdmin
docker compose up

命令docker compose up启动并运行整个应用程序。恭喜你!您正在使用 Docker 在您的机器上成功运行 PostgreSQL 数据库和 pgadmin4。现在让我们将 pgadmin4 连接到我们的 PostgreSQL 数据库服务器。

首先,通过访问 URLhttp://localhost:5050/,经由您喜爱的网络浏览器访问 pgadmin4 。使用【admin@admin.com】作为邮箱地址,使用 root 作为密码登录。

创建一个服务器。

点击服务器>创建>服务器创建新的服务器。

填写名称、主机名/地址、用户名和密码的数据。

选择通用标签。对于名称字段,使用任何名称。在这种情况下,我将使用 my_db 。现在移动到连接标签。要获得主机的值,运行以下命令。

docker ps

命令 ps 将显示所有正在运行的容器的简要信息。

docker ps

请先阅读更新章节。现在我们可以获取 PostgreSQL 容器的容器 id。

docker inspect fcc97e066cc8 | grep IPAddress

命令 inspect 显示正在运行的集装箱的详细信息。此外,我们使用管道grep 命令提取 IPAddress 信息。

码头工人检查 fcc97e066cc8

最后,我们得到了主机的值,,在本例中是192.168.80.2。使用值 root 作为用户名,使用 root 作为密码,还要勾选保存密码?如果您不想在每次登录 pgadmin4 时都键入密码,请选择此框。

更新【2021 年 4 月 16 日】

今天早上我收到了一封来自 Dosenwerfer 的邮件,说这个人在再次运行服务时遇到了一些问题。因为它更改了 PostgreSQL 容器的 IP 地址,您必须再次设置配置。推荐的解决方案是使用容器名。因为容器名与主机名相同,所以您可以从这里的阅读更多内容。因此,我们当前的配置如下。

填写名称、主机名/地址、用户名和密码的数据。

您可以使用docker ps命令找到 PostgreSQL 数据库服务器的容器名称,并从 NAMES 列中获取该名称。在这篇文章中,我们在 docker-compose.yml 文件中明确地命名了容器,所以你也可以参考它。非常感谢多森威尔。

方法 2

对于第二种方法,您可以将一个 pgAdmin docker 容器连接到一个正在运行的 PostgreSQL 容器。当您的 docker-compose.yml 文件中没有 pgAdmin 服务时,这很有帮助。看看下面的帖子,在那里你可以学到这个方法。

额外的

如果您想导入一些数据进行测试,可以使用我已经准备好的 SQL 查询。点击服务器> my_db >数据库> test_db >模式>表。右键点击表格,选择查询工具。将 SQL 查询从我的 GitHub 库中复制粘贴到查询编辑器中,然后单击 play 按钮。该操作将创建两个名为的表,学生标记以及一些测试数据。

包裹

通过命令行界面管理数据库可能会很伤脑筋。为了解决这个问题,我们可以使用带有接口的工具。pgAdmin 解决了这个问题。而且,Docker 让整个流程更加流畅。此外,您可以使用我提供的测试数据来试验 PostgreSQL 查询。希望这能帮助你入门 PostgreSQL,pgAdmin,和 Docker。编码快乐!

相关职位

如何在 R 中轻松运行 Python ML 算法

原文:https://towardsdatascience.com/how-to-run-python-ml-algorithms-easily-in-r-7e3b0f7c7aee?source=collection_archive---------37-----------------------

如何让 Python 的 XGBoost 在 R 中轻松工作的例子

图片由来自 Pixabay 的 Arek Socha 提供

毫无疑问,Python 拥有所有编程语言中最广泛的 ML 算法,如果我打算进行任何形式的预测建模,Python 通常是我的第一选择。也就是说,我更喜欢用 R 来整理和准备数据,并且希望能够将 Python 算法导入 R,这样我就可以两全其美了。所以我最近决定看看是否可以在 r 中轻松运行 Python ML 算法。我选择尝试 k 倍交叉验证的 XGBoost 模型。

我认为在 RStudio 中做这件事很容易,所以我在这里写了“如何做”。我还用这个例子组合了一个 Github repo

要让这些方法工作,您需要在 R 项目中工作,并指向 Conda 环境或 Virtualenv 中包含您需要的所有 Python 包的 Python 可执行文件。您可以通过使用 R 项目目录中的一个.Rprofile文件来做到这一点。每当您在 R 中启动一个项目时,这个文件都会在启动时执行它的内容。我的.Rprofile有两行代码。第一行告诉 R 在 Conda 环境中哪里可以找到正确的 Python 可执行文件,我已经安装了所有需要的包(即pandasscipyscikit-learnXGBoost)。这需要进行编辑,以指向您机器上的正确路径。

Sys.setenv(RETICULATE_PYTHON = "/home/rstudio/.local/share/r-miniconda/envs/r_and_py_models/bin/python3")

第二行是为了我方便。它打印出正在使用的 Conda 环境的确认。这是为了在启动时让我放心,R 知道我希望它在哪里执行 Python 代码。

print(paste("Python environment forced to", Sys.getenv("RETICULATE_PYTHON")))

当我开始我的项目时,我收到这条消息来确认正在使用预期的 Conda 环境。

用 R 编写 Python 函数在数据集上运行

我创建了一个名为python_functions.py的 Python 文件,在其中我用 Python 编写了所需的函数,以便在任意 Pandas 数据帧上执行 XGBoost 模型。我这样做是为了让这些函数的所有参数都在一个名为parameters的字典中。我需要编写四个 Python 函数——一个将我的数据分成训练和测试数据,一个缩放我的要素,一个运行 XGBoost,最后一个创建分类报告作为数据帧。以下是包含四个必需函数的文件内容:

现在在我的 R 项目中,我可以使用reticulate包在 R 中获得这四个函数,使它们成为 R 函数。

library(reticulate)
source_python("python_functions.py")

示例:在 R 中使用 Python XGBoost

我们现在在 R 中使用这些函数来尝试学习预测一款高质量的葡萄酒。首先,我们下载白葡萄酒和红葡萄酒的数据集。

white_wines <- read.csv("https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-white.csv",
                        sep = ";")red_wines <- read.csv("https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv", 
                      sep = ";")

我们将创建“白色对红色”作为一个新功能,我们将“高质量”定义为 7 分或以上的质量分数。

library(dplyr)white_wines$red <- 0
red_wines$red <- 1wine_data <- white_wines %>% 
  bind_rows(red_wines) %>% 
  mutate(high_quality = ifelse(quality >= 7, 1, 0)) %>% 
  select(-quality)head(wine_data)

现在我们的数据已经为建模设置好了,是时候将我们的 Python 函数付诸实践了。

现在我们设置我们的参数列表(R 中的列表相当于 Python 中的 dict):

params <- list(
  input_cols = colnames(wine_data)[colnames(wine_data) != 'high_quality'],
  target_col = 'high_quality',
  test_size = 0.3,
  random_state = 123,
  subsample = (3:9)/10, 
  xgb_max_depth = 3:9,
  colsample_bytree = (3:9)/10,
  xgb_min_child_weight = 1:4,
  k = 3,
  k_shuffle = TRUE,
  n_iter = 10,
  scoring = 'f1',
  error_score = 0,
  verbose = 1,
  n_jobs = -1
)

现在我们已经准备好运行 XGBoost 模型,比如说,三重交叉验证。首先,我们使用我们的 Python 函数split_data分割数据——注意reticulate将在幕后把输入翻译成它们的 Python 等价物,因此wine_data将成为熊猫数据帧而params将成为字典。

split <- split_data(df = wine_data,  parameters = params)

我们的 Python 函数返回一个 dict,R 中的输出将是一个列表,我们可以将它输入到缩放函数中:

scaled <- scale_data(split$X_train, split$X_test)

同样,输出将是一个列表。现在,我们可以使用训练集上定义的参数运行 XGBoost 算法:

trained <- train_xgb_crossvalidated(
  scaled$X_train_scaled,
  split$y_train,
  parameters = params
)

最后,我们可以为我们的测试集生成一个分类报告:

generate_classification_report(trained, scaled$X_test_scaled, split$y_test)

现在我们有了。你也可以使用训练过的对象trained来生成新的预测,就像你在 Python 中做的那样。例如,我们可以看到测试集的第一行被归类为高质量。

test_data <- py_to_r(scaled$X_test_scaled)
trained$predict(test_data[1, ])[1] 1

本文展示了一个更通用的编写 Python 函数的过程,这些函数将处理任意输入,然后可以很容易地在 r 中执行。它应该很容易推广到任何其他类型的过程,无论是另一个 ML 算法还是像编写 Powerpoint 文档这样的过程。我希望它对你正在做的其他工作是一个有用的基础。

最初我是一名纯粹的数学家,后来我成为了一名心理计量学家和数据科学家。我热衷于将所有这些学科的严谨性应用到复杂的人的问题上。我也是一个编码极客和日本 RPG 的超级粉丝。在LinkedInTwitter上找我。也可以看看我在 drkeithmcnulty.com 的上的博客。

如何在 Jupyter 中运行 R 脚本

原文:https://towardsdatascience.com/how-to-run-r-scripts-in-jupyter-15527148d2a?source=collection_archive---------1-----------------------

环境设置

关于如何在 Jupyter 中安装并运行 R 内核的简短教程

图片由 Carlos Andrés Ruiz Palacio 来自 Pixabay

Jupyter Notebook 是一个允许用不同语言创建实时代码的网络应用程序。通常,开发人员利用 Jupyter 笔记本用 Python 编写代码。但是,Jupyter 也支持其他编程语言,包括 Java、R、Julia、Matlab、Octave、Scheme、Processing、Scala 等等。

Jupyter 是如何工作的

Jupyter 不提供任何编译器或解释器。相反,它是一个与实际的编译器/解释器进行通信的过程。实际上,它将代码发送给编译器/解释器,并返回结果。

为了在 Jupyter 单元中运行(给定语言的)代码片段,安装该语言的相应内核就足够了。

R 的核

在本教程中,我将演示如何为 R 软件安装 Jupyter 内核。

首先,我需要在你的电脑上安装 R 软件。我可以从的官方网站下载 R 软件。安装完成后,我可以打开一个终端并启动 R,只需在控制台上输入R,然后输入 Enter 命令。

注意:如果使用 Mac OS,需要从安装 R 的目录下运行 R 软件。通常,该目录是

/Library/Frameworks/R.framework/Versions/<version>/Resources/bin

其中<version>表示 R 版本。我可以通过在控制台上键入以下命令来运行 R:

./R

一旦启动了 R 控制台,我必须通过以下命令下载devtools包:

install.packages("devtools")

我选择镜像编号(例如,意大利是 48),然后按 Enter 键。

一旦安装完成,我可以从 Github 安装 IRKernel。我运行以下命令:

devtools::install_github("IRkernel/IRkernel")

前面的命令可能会失败。在这种情况下,我可以通过以下命令强制安装:

devtools::install_github("IRkernel/IRkernel", force=TRUE)

之后我安装了IRkernel:

IRkernel::installspec()

现在我可以通过输入退出 R

quit()

我可以经营朱庇特。当 Jupyter 在浏览器中打开时,我可以点击右上角的 New 并选择 R 作为内核。快乐享受:)

作者图片

摘要

在本教程中,我已经演示了如何在 Jupyter 中安装 R 内核。这个过程非常简单快捷。

如果你仍然遇到安装问题,请查看我的 Youtube 安装教程。

如果你想了解我的研究和其他活动的最新情况,你可以在 TwitterYoutubeGithub 上关注我。

相关文章

[## 如何在 Android 设备上安装 Python 和 Jupyter Notebook

towardsdatascience.com](/how-to-install-python-and-jupyter-notebook-onto-an-android-device-900009df743f) https://alod83.medium.com/how-to-install-xampp-bcb43fb11912 https://alod83.medium.com/how-to-import-and-export-a-dataset-in-phpmyadmin-b108288a3ca3

新到中?您可以每月订阅几美元,并解锁无限的文章— 单击此处

如何在 Python Pandas 中对数据帧进行采样

原文:https://towardsdatascience.com/how-to-sample-a-dataframe-in-python-pandas-d18a3187139b?source=collection_archive---------1-----------------------

数据预处理

使用不同的技术对 Python Pandas 中的数据集进行采样的现成代码

图片来自 Pixabay

您可能只需要 Python 数据帧中的一些行。你可以通过不同的采样技术达到这个结果。

在本教程中,我演示了通过 Python Pandas 执行行采样的以下技术:

  • 随意采样
  • 有条件抽样
  • 以恒定速率采样

完整的代码可以从我的 Github 库下载。

加载数据集

在本教程中,我利用了由scikit-learn库提供的iris数据集,并将其转换为pandas数据帧:

from sklearn.datasets import load_iris
import pandas as pddata = load_iris()
df = pd.DataFrame(data.data, columns=data.feature_names)

作者图片

数据集由 4 列 150 行组成。

随意采样

给定一个有 N 行的数据帧,随机抽样从数据帧中抽取 X 个随机行,其中 X ≤ N. Python pandas提供了一个名为sample()的函数来执行随机抽样。

要提取的样本数量可以用两种可选方式表示:

  • 指定要提取的随机行数
  • 指定要提取的随机行的百分比。百分比以 0 到 1 之间的数字表示。

确切数量

在这种情况下,您可以将参数n传递给sample()函数,如下所示:

subset = df.sample(n=100)

在前面的例子中,sample()函数提取了 100 个随机行。您可以通过shape功能检查subset结果数据集的形状:

subset.shape

它给出了以下输出:

(100, 4)

百分率

如果您想要指定要提取的随机行的百分比,您可以将frac参数作为sample()函数的输入:

subset = df.sample(frac=0.5)

在前面的例子中,sample()函数提取了 50%的随机行。注意,您只能在nfrac参数之间指定一个。

有条件抽样

有条件抽样只允许提取满足给定条件的一些行。首先,必须指定条件。例如,作为一个条件,您可以只选择sepal width (cm)列的值小于 3 的行:

condition = df['sepal width (cm)'] < 3

变量condition是一个与df大小相同的数列,包含True/False,取决于行是否满足条件。

然后,检索与满足上述条件的行相关联的索引:

true_index = condition[condition == True].index

在当前示例中,57 行满足条件,因此您最多可以采样 57 行。

sample()功能可用于执行采样,条件如下:

subset = df[condition].sample(n = 10)

以恒定速率采样

另一种采样策略是以恒定速率采样,这意味着您希望两个相邻样本之间的距离恒定。例如,您可能希望以 4 的速率进行采样,如下图所示:

作者图片

在这种情况下,首先指定速率:

rate = 10

然后,你可以简单地提取样本:

subset = df[::rate]

iris数据集中,样本数为 150,因此 10 的采样率将产生 15 行的子集:

subset.shape

它给出了以下输出:

(15, 4)

获取数据集的剩余部分

一旦提取了数据集的子集,还可以提取剩余部分。例如,如果您想在训练和测试集中分割数据集,可以使用这种策略,而不使用scikit-learn库提供的train_test_split()函数。

可以采用两种可能的解决方案来提取数据集的剩余部分。这两种解决方案产生了相同的结果。

第一种解决方案

第一种解决方案删除原始数据帧df中提取的数据帧subset的行,并将结果存储在新的数据帧中。这可以通过将待删除的索引列表传递给drop()函数来实现:

remaining = df.drop(labels=subset.index)

第二种解决方案

第二种解决方案仅选择原始数据帧df中的行,其中索引不在提取的数据帧subset的索引列表中:

remaining = df[~df.index.isin(subset.index)]

摘要

在本教程中,我演示了如何以不同的方式执行数据帧采样:

  • 随机抽样,抽取 N 个随机行;
  • 带条件抽样,应用一个条件,然后随机抽取 N 行;
  • 以恒定速率采样。

如果你想了解我的研究和其他活动的最新情况,你可以在 TwitterYoutubeGithub 上关注我。

相关文章

如何利用数据挽救网球中的破发点

原文:https://towardsdatascience.com/how-to-save-break-points-in-tennis-using-data-f0b32c026a88?source=collection_archive---------31-----------------------

任何网球比赛的关键之一是挽救破发点的能力。看一看 ATP 排行榜,你会想起这个事实,因为你会看到游戏中的顶级职业选手始终保持在破发点挽救百分比的最顶端。但是是什么让一个球员擅长挽救破发点呢?借助杰夫·萨克曼(Jeff Sackman)过去 10 年每个大满贯的逐点数据集,我们可以深入了解职业选手如何在网球的最大舞台上挽救破发点。

首先,我们开始导入相关库的:

import pandas as pd
import seaborn as sn
import matplotlib.pyplot as plt
import numpy as np

然后我们需要导入数据。从 2018 年开始,澳大利亚网球公开赛和法国网球公开赛的数据被不同地打包,所以我们现在放弃了这几场比赛。

years = [i for i in range(2011, 2021)]
slams = ['ausopen', 'frenchopen', 'usopen', 'wimbledon']
data = pd.DataFrame()for year in years:
    for slam in slams:
        if year >= 2018 and slam in ['ausopen', 'frenchopen']: #these slams did not have the same data collected
            continue
        try:
            new_data = pd.read_csv('./tennis_slam_pointbypoint-master/' + str(year) + '-' + slam + '-points.csv')
            if year == 2011 and slam == 'ausopen':
                data = new_data
            else:
                data = pd.concat([new_data, data])
        except FileNotFoundError:
            print(year, slam)
            continue

接下来,我删除了没有对打数据的行(在这种情况下,这些行没有发球速度读数),并收集了相关的特征,如 ace、净得分、非受迫性失误、获胜者等。我会推荐任何感兴趣的人参考 Github 文件,因为把所有内容都发布到文章中会让人不知所措。

终于我们可以开始分析了。在网球场上做出的第一个决定是是否先发球。如下所示,先发球似乎有很大的帮助,因为第一场比赛的破发点比第二场少得多(大约减少了 25%)。善于挽救破发点的最好方法是首先不要面对它们,首先发球可以最大限度地减少球员在整场比赛中面临的破发点。

#imported library's include (Seaborn, Matplotlib.pyplot, pandas)
#sets the x axis to be 12 games and then uses a pandas groupby statementa_plot = sn.lineplot(x = [i for i in range(0,12)], y = data.groupby('GamesPlayed').mean()['BreakPoint'][0:11])a_plot.set(ylim = (0, .19))
plt.title("Break Points Faced per Game")
plt.grid()
plt.xlabel("Games into Set")

第一场比赛显示,与其他比赛相比,面临的破发点减少了 25%

接下来我们要研究的是如何在破发点发球,毕竟这是网球场上你可以完全控制的事情。虽然我们在某种程度上受到限制,因为如果球员错过了第一次发球(即他们试图击球的力度),我们仍然可以检查发球速度如何影响破发点挽救百分比的一些关键因素。

我将发球速度从每小时 80-140 英里,每 5 英里一组。所有指标都与这个循环相关联,每个指标的名称都应该相当直观

for i in range(80, 145, 5): #bucketing by fives and then appending to lists corresponding to different metricsbucket_data = data[(data.ServeSpeed >= i) & (data.ServeSpeed <= i + 5)]
    trimmed_data = bucket_data[bucket_data.BreakPoint]

    x = bucket_data.groupby('BreakPoint').mean()#all data
    y = trimmed_data.groupby('BreakPointWon').mean()#just bp data

    save_percentage.append(1 - x.loc[True, 'BreakPointWon'])#doing the one because has two entries True and False
    rally_length.append(y.loc[True, 'Rally'])

    buckets.append(i)

    winner_percentage_loss.append(y.loc[False, 'Winner'])
    winner_percentage_save.append(y.loc[True, 'Winner'])

    unforced_error_percentage_loss.append(y.loc[True, 'UnforcedError'])
    unforced_error_percentage_save.append(y.loc[False, 'UnforcedError'])

    net_point.append(x.loc[True, 'ServerNetPoint'])
    net_point_won.append(x.loc[True, 'ServerNetPointWon'] / x.loc[True, 'ServerNetPoint'])

    return_net_point.append(x.loc[True, 'NetPoint'] - x.loc[True, 'ServerNetPoint'])
    return_net_point_won.append((x.loc[True, 'NetPointWon'] - x.loc[True, 'ServerNetPointWon']) / (x.loc[True, 'NetPoint'] - x.loc[True, 'ServerNetPoint']))

正如你所料,发球速度的提高与破发点挽救率相关。然而,一旦你达到 130,这种影响似乎变平了。最终发球速度可以公式化为一个决策方程。如果一名球员可以量化每增加一英里他们错过第一次发球的可能性有多大,以及他们在第二次发球时赢得分数的可能性有多大,他们就能够计算出他们应该发球的最佳速度。

import matplotlib.ticker as mtick #imports to enable percentage reading#graphs save percentage by serve speed
ax = sn.lineplot(x = buckets, y = [i * 100 for i in save_percentage])
ax.yaxis.set_major_formatter(mtick.PercentFormatter())#sets y axis as a percentplt.grid()
plt.title("Save Percentage by Serve Speed")plt.ylabel("Save Percentage")
plt.xlabel("Serve Speed")

130 英里/小时后,图表稳定增长,影响有限

接下来,我们考虑赢家和非受迫性失误。正如我们从下面看到的,当你的发球速度提高时,胜率稳步上升,而当你的对手击中胜方的几率保持相对稳定。作为服务器,这可能会导致重要的战术决策。例如,如果你正在打一个打了很多致胜球的大击球手,打一个较慢的发球可能没问题,因为发球速度似乎不会影响他们打致胜球的机会。然而,如果你不得不打致胜球来赢得你的大部分分数,你可以冒险在你的第一次和第二次发球时打得更用力一点,以增加打致胜球的可能性。

#uses two lines on one plot to visualize Winner percentage
ax1 = sn.lineplot(x = buckets, y = [i *100 for i in winner_percentage_loss], label = 'Server')
ax2 = sn.lineplot(x = buckets, y = [i * 100 for i in winner_percentage_save], label = 'Returner')
ax1.yaxis.set_major_formatter(mtick.PercentFormatter())
ax2.yaxis.set_major_formatter(mtick.PercentFormatter())plt.grid()
plt.title("Winner Percentage Server vs Returner by Serve Speed")plt.ylabel("Winner Percentage")
plt.xlabel("Serve Speed MPH")

对于返回者来说,赢家比例保持不变

我们还必须考虑发生非受迫性失误的可能性。正如下图所示,如果你的发球速度是 90 英里/小时,而不是 135 英里/小时,你的对手基本上不会犯非受迫性错误——140 英里/小时的百分比可能是由样本量低造成的。然而,随着你发球速度的提高,你的发球出现非受迫性失误的几率会稳步下降。这同样会导致重要的战术变化。如果你的对手是零星的,犯了很多非受迫性错误,你可能想打一个更软的第一次发球,因为发球速度不会影响他们犯错误的倾向。然而,如果作为一个发球者,你一直不稳定,通过更努力的发球来降低非受迫性失误的概率可能是正确的举动。

#uses two lines on one plot to visualize unforced errors
ax1 = sn.lineplot(x = buckets, y = [i * 100 for i in unforced_error_percentage_save], label = 'Server')
ax2 = sn.lineplot(x = buckets, y = [i * 100 for i in unforced_error_percentage_loss], label = 'Returner')
ax1.yaxis.set_major_formatter(mtick.PercentFormatter())
ax2.yaxis.set_major_formatter(mtick.PercentFormatter())plt.grid()
plt.title("Unforced Error Percentage Server vs Returner by Serve Speed")plt.ylabel("Unforced Error Percentage")
plt.xlabel("Serve Speed MPH")

服务器的非受迫性错误百分比随着速度的增加而降低

最后,我们发现当一个球员来到网前,他们有 68%的机会赢得这一分。上网是一个成功的策略,尤其是在破发点,当你迫使对手在高压情况下进行艰难的射门时。正如我们所看到的,随着你发球速度的增加,网前胜率保持不变,这两种情况都可能是由于样本量小,但你上网的能力显著增加——从 80 英里/小时的 10%增加到 120-130 英里/小时的 20%左右。

#graphs by percentage chance to get to the Net
ax = sn.lineplot(x = buckets, y = [i * 100 for i in net_point])ax.yaxis.set_major_formatter(mtick.PercentFormatter())plt.grid()
plt.title("Percentage Chance to Get to the Net")plt.ylabel("Server Net Point Percentage")
plt.xlabel("Serve Speed MPH") #graphs by win percentage at the net
ax = sn.lineplot(x = buckets, y = [i * 100 for i in net_point_won])
ax.yaxis.set_major_formatter(mtick.PercentFormatter())plt.grid()
plt.title("Win Percentage at the Net by Serve Speed")plt.ylabel("Server Net Point Win Percentage")
plt.xlabel("Serve Speed MPH")

同样,这些信息取决于你的对手和你的实力。如果网络机会是你战略的一个关键部分,你可能会通过增加你的 MPH 得到更好的服务。此外,增加你的 MPH 也会降低你的对手入网的概率,而他们的胜率保持不变,除非是 135 MPH 的异常值。

#Returner percent chance to get to the net
ax = sn.lineplot(x = buckets, y = [i * 100 for i in return_net_point])
ax.yaxis.set_major_formatter(mtick.PercentFormatter())plt.grid()
plt.title("Oppenent Percent Chance to get to Net by Serve Speed")plt.ylabel("Returner Net Point Win Percentage")
plt.xlabel("Serve Speed MPH") #Returner win percentage at the net
ax = sn.lineplot(x = buckets, y = [i * 100 for i in return_net_point_won])
ax.yaxis.set_major_formatter(mtick.PercentFormatter())plt.grid()
plt.title("Returner Win Percentage at the Net by Serve Speed")plt.ylabel("Returner Net Point Win Percentage")
plt.xlabel("Serve Speed MPH")

虽然比赛中做出的每个决定都完全取决于你和对手的比赛风格,但这些统计数据为在破发点上做出明智的选择提供了一些证据。显然,不是每个人都能够发球超过 130 英里/小时,但是发球速度显然是节省破发点的一个重要部分,可能是你下次练习时的一个重要考虑因素。杰夫·萨克曼的数据为网球和网球统计数据提供了宝贵的视角,我们只能希望 ATP 像 MLB 一样开放 IBM 和 InfoSys 的跟踪数据,以增加对这项运动的分析关注。

接下来,我希望做我上一篇文章做的事情(聚类),同时使用大满贯的逐点数据,看看是否可以找到任何额外的见解。

github:https://github . com/dcaustin 33/Medium-hosting/blob/main/Break % 20 point % 20 save % 20% 25 . py

如何在 Docker 中保存状态——数据科学家指南

原文:https://towardsdatascience.com/how-to-save-state-in-docker-a-data-scientists-guide-18bb05589010?source=collection_archive---------20-----------------------

使用数据科学容器时,从持久化数据和状态开始。Docker 中的数据存储和持久性指南。

弗雷迪·雅各布在 Unsplash 上拍摄的照片

介绍

在这篇文章中,我们将讨论 Docker 中的数据持久性,以及如何让您的图像与容器外部的数据进行交互。如果你熟悉 Docker 或者已经浏览过本系列的前几篇文章,请跳到下一个标题!

到目前为止,在这个系列中,我们已经介绍了如何获得一个基本的 Hello World!使用 Flask 和 Python 构建并使用 Docker 部署的 web 应用程序。在第 2 部分中,我们浏览了一个端到端的机器学习示例,为 Iris 数据集构建了一个随机森林分类器,并使用 Flask 将其作为一个预测 web 应用程序,然后将其共享到公共 Docker Hub 存储库。

如果你错过了他们:

现在你可能不想在任何情况下公开分享你的图片。幸运的是,有许多选项可供您构建和维护私有存储库。每个主要的云提供商 Azure、AWS 和 GCP 都有托管存储库选项,这些选项很容易启动和运行。对于那些热衷于使用 Azure 的人,我还写了一个快速指南,介绍如何使用 Docker 和 Azure CLI 运行私有存储库:

如果您已经启动并运行了,并且只是想开始使用数据持久性,那么让我们开始吧。

数据持久性

使用容器时有两个核心假设:

  • 容器应该是一次性的。这意味着他们应该是无国籍的。容器提供了完成工作所需的计算能力、应用程序、配置和代码。然后,在退出时,当他们退出时,一切都被清除。
  • 为了支持微服务方法,容器应该被设计成专家——尽可能专注于几件事情。这允许系统设计者组合多个简单的容器来创建复杂的行为,而不用担心相互依赖。

这种方法有很多好处。无状态支持可伸缩性、可移植性和弹性。如果您正在运行多个容器,并且其中一个出现故障,那么重启它或者启动一个替换容器是很简单的。

为了捕捉状态,它应该在图像之外。这使得微服务可以轻松地共享信息,而无需考虑每个容器的性能或准确性的复杂性,这在传统的应用程序设计中是一个挑战。

将数据管理从应用程序中分离出来可以导致更快的开发和更低的维护开销(阅读:为我们赢得一些时间,这是每个数据科学家都需要的!).

对于在外部何处保持该状态,有几个选项:

  • 磁盘上——这可能是容器可以访问的 Docker 主机本地保存的另一个文件夹
  • Docker 定义的卷—可以在多个容器之间共享的装载存储卷
  • 数据库—有了足够的凭证和配置,每个容器都可以读写本地/网络/云数据库的状态
  • 网络资源——容器可以从另一种类型的网络资源(如服务总线或消息队列)获取状态

在本文中,我们将介绍如何使用 Docker 卷来存储状态。

Docker volumes 允许您将容器的特定文件系统路径连接回主机。当容器中的一个目录被挂载时,该目录中的更改也会在主机上看到。然后,您可以跨容器重启挂载相同的目录,您将看到相同的文件。

我将使用来自 Docker Hub 的标准 Jupyter 笔记本图像来强调在 Docker 环境中移动数据和熟悉的应用程序是多么容易。您可以使用以下命令从 Docker Hub 中提取映像:

docker pull jupyter/datascience-notebook

请注意,这是一个相当大的映像(4.16 GB),如果空间或时间不足,请尝试使用最小的笔记本映像(1.49 GB),并相应地更改以下所有代码。您可以使用以下方法提取最小图像:

docker pull jupyter/minimal-notebook

创建 Docker 卷

首先,让我们从 Docker 卷开始——这是一种由 Docker 管理的资源,容器可以轻松访问它以将其用作存储。要在 Docker 中创建卷,请使用以下语法:

docker volume create <volume_name> 

您可以使用如下所示的docker volume ls来检查这是否成功。

在 Docker 中创建和检查卷(图片由作者提供)。

现在,如果我们想把一些本地文件放到一个容器中,我们可以用几种方法。首先,让我们运行一个容器,并在其中挂载一个目录。然后,我们可以将 Docker 卷装载到同一个容器中,从而允许我们跨容器复制内容。

在这里,我们将刚刚创建的demo-volume挂载到容器内的一个目录中。我们将使用/home/jovyan/demo-dir把它放在默认的 Jupyter 位置。语法如下:

docker run -v <volume_name>:<container_directory> <image_name>

因为我们在这里使用 Jupyter,我们还需要记住映射端口。因此,该命令如下所示:

docker run -p 8888:8888 -v demo-volume:/home/jovyan/demo-dir jupyter/datascience-notebook

运行 Jupyter 笔记本容器的命令,包括端口映射和 Docker 卷安装(图片由作者提供)。

然后,您只需要转到带有令牌的链接,并且(输出中的第二个链接对我来说更加一致):

http://127.0.0.1:8888/?token=a7a30a23821b5764d7f754838af13099b6b134c8687c415f

你应该被认证和重定向,然后你会看到熟悉的 Jupyter 前屏幕和我们的demo-dir安装在我们能看到的地方:

我们的 Docker 卷挂载到容器中的/demo-dir(图片由作者提供)。

这允许我们在卷中存储内容,并像对待任何挂载的文件夹一样对待它。当使用容器和服务时,这实际上是在 Docker 中持久化数据的首选方式。一些更强的卷使用情形包括:

  • 如果您想在多个运行的容器之间共享数据,卷是最好的选择。当已装载的容器停止、崩溃或被删除时,卷仍然存在。这意味着其他容器仍然可以连接到它,并与其中的数据进行交互。
  • 您还可以使用它将包含服务不同部分(例如机器学习服务和数据库)的不同图像连接到相同的数据。
  • 当主机可能没有所需的目录结构时,卷是很好的选择。使用卷允许您通过显式装载主机来放松对主机的这一要求。
  • 卷使跨主机备份和迁移数据变得更加容易。
  • 如果您需要本地文件系统行为,Docker volumes 可以帮助您解决这个问题。

结论

在这篇文章中,我们已经看到了在使用 Docker 时持久化数据的一些选项。我们还介绍了一种最方便的方法,用于在容器之外保存数据,以及在同一主机上运行的容器之间保存数据。

有希望的是,可以看到以这种方式组合 Docker 容器——作为原子的、自包含的单元——允许数据科学家开始构建强大的系统,这些系统保持可伸缩性、灵活性和难以置信的模块化。

进一步阅读

Docker 中的数据持久性还有很多。由 Lorenz Vanthillo 撰写的这篇文章介绍了如何将 Docker 容器连接到 PostgreSQL 数据库:

https://medium.com/better-programming/connect-from-local-machine-to-postgresql-docker-container-f785f00461a7

在这里, Thiago S. Adriano 写了一篇关于连接 SQL Server 的精彩指南:

https://medium.com/dockerbr/accessing-sql-server-on-docker-container-86b84efcaa1c

再次感谢您的阅读,如果您对进一步的内容有任何反馈或要求,请务必告诉我。

如何对几款车型进行规模化训练

原文:https://towardsdatascience.com/how-to-scale-the-training-of-several-models-64180480ca3d?source=collection_archive---------70-----------------------

基于 python 和 celery 的简单解决方案

动机

让我们考虑以下任务:预测几个城市对某种东西的需求。这是一个时间序列预测问题。预测在本地模型和全球模型之间存在差异。对于本地模型,您为每个城市训练一个模型。使用全局模型,您可以为所有城市训练一个模型。总而言之:训练多个相似的模型有时是必要的。

简单的解决方案是依次训练模型:一个接一个的模型。想象你需要 10 分钟训练一个城市的模型,你有 100 个城市。你需要 1 000 分钟来训练所有的模型(16 小时)。这是生产力杀手。由于适应模型是部署的一部分,这将违反持续集成和持续开发的原则。

为了在相同的持续时间内完成训练,与模型的数量无关,解决方案是在 n 台计算机(也称为工人)之间分配训练。本文将描述一个 python 解决方案。解决方案基于著名的图书馆芹菜。github 上有一个原型

解决方案概述

这个问题通常用任务队列管理器来解决。在 python 中,最著名的任务队列管理器是 celery。我们将拥有:

  • 1 个主机,创建任务
  • n 个工人,每个人都符合一个模型

作者图片

对于培训模型,有两个更重要的要求:

  • 指标:我们想知道所有模型的平均指标。
  • 成本:一旦培训结束,工人必须停工。

作者图片

履行

该实现可在 g ithub 上获得。

第一步——第一根芹菜用法&原型骨架

先决条件:安装芹菜包;安装并启动 redis 并了解芹菜的第一步

首先,定义一个名为“fit”的芹菜任务。它将由工人来执行。它是为适应模型而执行的代码,它返回精度。

然后,主人将计算委托给工人。添加此代码,例如在 bin/master.py 中。

最后,执行原型,如下所示:

# start a worker
celery -A tasks worker# start the leader
python bin/master.py

注意:在 github 上,已经创建了一个文件(bin/worker.sh)用于启动一个 worker。

步骤 2——等待任务处理

主设备可能必须等待任务被处理。这很可能发生在部署管道中。这是以下代码的责任:

步骤 3——获得每次训练的平均准确度

为了更好地了解和跟踪精确度,主服务器可以打印每个城市的平均精确度。下面的代码演示了主服务器如何读取其工作线程的结果。

第四步——停止工人

在 src/tasks.py 中定义一个任务“shutdown ”,一个 worker 的单次执行将关闭所有 worker。但是工人将首先完成他们当前任务的执行

主机将任务“关机”委托给工作机(在 bin/master.py 中):

第五步——运行一切!

在一个选项卡中启动 3 个流程(1 个主流程和 2 个工作流程):

作者图片

其他可能性

  • RabbitMQ :以及所有其他实现 AMQP 协议的消息队列。
  • 不是卡夫卡:用卡夫卡解决这个问题很难,也不是最优的。卡夫卡不是解决这个问题的好工具,因为它的设计。它不允许您将几个用户连接到同一个分区。

结论

这篇文章表明,芹菜是一个简单的解决方案,分布培训的几个模型。Celery 是最著名的用于任务处理的 python 库。你用芹菜赢得的知识和技能可以转移到其他问题上。开箱即用,Celery 自带了很棒的特性,比如“关闭所有工作器”或者“从工作器返回一个值给主控器”。尽管如此,其他任务队列管理器可以解决同样的问题。您可以直接使用数据库(例如 Redis)或 AMQP 消息代理(例如 RabbitMQ)来开发解决方案。即使这看起来像是编写自己的任务队列管理器,但它可能是一个更具成本效益的解决方案。

如果你对更多细节感兴趣,请留言告诉我!

如何通过采用 SQL(有时抛弃 Git)来扩展您的分析组织

原文:https://towardsdatascience.com/how-to-scale-your-analytics-org-by-ditching-git-3d8d4ce398d1?source=collection_archive---------17-----------------------

为什么分析工作应该优先考虑可发现性和可再现性,而不是版本控制和代码审查。

[图片来自 Freepik]

流程对于组织的扩展至关重要,而我们对分析流程的理解是错误的。

扩展组织的一个关键方面是过程。过程允许您规范化和合并最佳实践,以确保事情顺利和可伸缩地工作,即使没有人注意控制。但是,分析组织中的流程是经常被忽略的东西,我们经常默认工程遵守的相同流程:即使用 git 和相关模式来共享和存储分析工作。

对于数据科学/分析的某些部分,这样的工程行为转移是合适的:分析基础设施、分析工程、机器学习模型的部署、库-所有这些工作流都是固有的基于代码的,并受益于工程组织中熟悉的严格的测试+ PR 文化。但是对于剩余的分析工作——在 SQL IDEs 和 Jupyter 笔记本中每天都会发生的那种——拟合度很差。作为分析师和数据科学家,我们 90%的工作都是探索性的。不幸的是,在这里,工程实践不仅达不到要求,而且可能对组织有害。为什么?

盲目地将版本控制和代码审查作为共享探索性工作的看门人,会导致非共享的探索性工作。

所以我认为我们需要一个不同的过程。为了理解需要什么样的流程,我们首先需要确立分析组织的目标。在工程中,可维护性、可靠性和可伸缩性是支撑诸如版本控制、代码审查、代码覆盖、验证测试等实践的目标。但是在分析工作中,潜在的目标必然是不同的:可靠性、可维护性和可伸缩性仍然是重要的,但是它们表现得不同。让我们扔掉皇帝的衣服,用我们真正想要的东西来代替这些概念:可发现性再现性。换句话说,我们需要将“科学”放回数据科学(和分析)中。

记住这些概念后,我将在本文中讨论以下内容:

  • 为什么可发现性和再现性在分析和数据科学组织中至关重要。
  • 如何将过程导向这些目标。

第一个支柱:可发现性

为什么我们需要可发现性:代码天生就是可发现的。分析工作不是。

这是一个过于简化的工程代码库,其中箭头表示导入。

图片作者。

任何在现代 IDE 中呆过一段时间的人都知道遍历这个图很容易。每一个现代的 IDE 都有“跳转到”功能,您可以立即跳转到对象引用。从def pet()开始,你可以很容易地跳到class Llama的定义,然后沿着面包屑轨迹一路回到父类Animal

另一方面,您的分析代码库看起来有些不同:

图片作者。

仍然存在互连性(通过数据本身),但是这些连接不能通过您的 IDE 发现(因此线是虚线)。这使得很难像工程师看到函数引用那样看到表引用。那么解决办法是什么呢?

如何获得可发现性:使用一个低摩擦、网络化的系统来做(或至少文档化)查询工作。

不过,在深入探讨之前,让我们先来谈谈采用工程最佳实践的分析组织的首选解决方案: git 。许多组织求助于 git 来跟踪任何一种推动洞察力的查询。这是合理的,并且允许通过比如说表名来搜索数据,但是根据我的经验,git 有一些不便之处:

  • 验证繁琐/盲目。对于 SQL,您必须复制、粘贴并重新执行查询来验证 repo 中的工作。这是一个小小的不便,但是因为 git 中通常不跟踪结果,所以如果自己不重新运行查询,就很难跟踪查询之间的逻辑流。对于基于代码的笔记本电脑来说,这甚至会变得更糟—您需要在获取必要数据的基础上复制虚拟环境。不像在工程中,数据工作的输出几乎和代码本身一样重要,所以如果你只是看代码,你就错过了故事的一半。Git 不适合追踪逻辑的审查过程。
  • 工作往往缺乏足够的背景。特别是,对于原始 SQL,git 提供的上下文很少,查询只能在编写它们的上下文中使用。当然,您可以在查询中添加一个自述文件,但是您编写的所有假设和用来验证这些假设的片段呢?你把那些放进去了吗?如果是这样的话,你是否愿意对它们进行版本控制?
  • Git 中的工作是可搜索的,但不是合格的。筛选过去的工作是粗糙的,因为 git 没有提供查询或分析的健壮性或可重用性的指示——只是说它以前被写过。
  • 在理想的世界中,代码评审是很棒的,但是评审跟不上分析的步伐。代码仍然应该被检查,但是商业决策的速度经常需要在事后和/或逐案的基础上进行检查,而不是强制性的同行评审。一旦发现,见解的有用性通常会呈指数衰减,因此用正式的评审周期来阻碍业务不是一个好主意。当然,你可以在没有代码评审的情况下使用 git,但是总是有潜在的压力要退回到正式的评审过程中——养成在没有评审的情况下合并代码的习惯也可能是个坏主意。😉

我从以上几点得出有争议的结论:

Git 不适合分享大多数分析工作。

最终,这些不便仅仅是不便,但是,也许令人惊讶的是,这些不便经常足以导致人们不分享他们的工作。我在 Airbnb、Wayfair 和其他一些试图实施同样措施的公司亲眼目睹了这种情况。虽然一些非常精美的作品会被分享(例如通过 Airbnb 的知识回购),但这只占完成作品的 1%。剩余的工作存在于 SQL IDEs 的选项卡、本地文件、本地 Jupyter 笔记本中,因此这些工作会被不同的分析师和数据科学家一遍又一遍地重复。

解决办法?不惜一切代价让作品被发现。一个合理的方法是在一个非 git 支持的地方分享你的工作。我们已经为这类事情专门构建了 hyperquery.ai ,但是我已经看到使用更通用的笔记解决方案取得了相当大的成功,比如使用 concept、Confluence 或 Library(h/tBrittany Bennett),如果你不介意将 IDE 和查询共享环境分开的话。对于 Jupyter/R markdown 来说,不幸的是,git 可能仍然是所有罪恶中最小的。但这让我想到了我的第二个目标:再现性。

第二个支柱:再现性

再现性很重要,因为分析是科学。

分析/数据科学就是科学。因此,它需要是可复制的。你产生的任何洞见都是两件事:洞见本身和你为获得洞见所采取的步骤。

可复制性尤其重要,因为我已经告诉过你不要在托管的 git 平台中进行同行评审。虽然避免强制性的同行评审流程阻碍洞察力的使用很重要,但让同事检查关键的、决定决策的工作片段仍然非常重要,优先考虑可重复性可以实现这一点。此外,与代码评审相比,可再现性更好地促进了对结果的仔细验证,正如我所提到的,代码评审在数据输出方面通常是不透明的。

使用 SQL 最容易获得再现性,而不是 Python/R。

为什么?因为 SQL 减少了复制工作的摩擦。与可发现性一样,减少摩擦也很重要,否则没有人会经历如实再现您的努力和验证您的结论的痛苦。正如他们所说,如果你有一个 5 行 git commit,你将得到 50 个请求的修改。如果你有一个 500 行的提交,你会得到一个 LGTM。要求用户建立虚拟环境,并与基于代码的笔记本中充满的隐藏状态进行斗争,这意味着其他人根本不会试图复制你的工作。没有什么比因为你没有仔细检查你的工作而把生意推向错误的方向更糟糕的了。

所以现在我们来看我这篇文章的第二个有争议的陈述:

尽可能使用 SQL,而不是 Python/R。

Python/R 爱好者:在你关闭浏览器并永远屏蔽我之前,请听我说完。我喜欢 Python 和 R,并且是 IPython 和 Jupyter 的最早用户之一(我整个研究生院都在用 Python 研究 rivers)。我甚至发布了几个 Python 开源库。

也就是说,你必须承认:Jupyter 笔记本和 R Markdown 并不是存储可复制作品的最佳地方。隐藏状态、缺乏易执行性、需求文件和缓存数据提供了许多失败点。在一天结束时,运动中的数据打破,并且 SQL 的使用最小化了运动。

当然,假设你不买这个——你是制造完美可复制笔记本的大师。这是完全可能的,如果你有一个基于 odbc 的库,它直接从你的仓库中提取数据,如果你确保在共享你的代码之前总是从头开始重新执行你的所有单元格,如果你确保你有一个好的系统来共享这些笔记本而不意外地存储大量的数据(哎呀,你执行了df并以明文列出了几百兆字节的数据)。但即便如此,如果你把这些事情都做对了,Jupyter 笔记本还是有一定程度的不透明性(尤其是利益相关者无法访问),这将不可避免地降低对你分析的信任度。另一方面,SQL 片段是自包含的,开箱即用。如果利益相关者有疑问,他们可以(并且愿意)执行 SQL,只要您的组织有合理的数据卫生,可复制性是免费的。

要实施的流程:(1)共享知识和(2) SQL(如果可能)

在本文的这一点上,您可能已经很清楚了,但是在我看来,只有两个必要的过程,当实现时,将推动可发现性和可再现性向前飞跃。我会把它们放在一个多余的表格里,帮助你消化它们:

希望这些建议不会像我之前的观点让你期待的那样激烈:

  • 对于可发现性,我甚至不是说要放弃任何基于 git 的版本控制分析,只是建立一些可以共享和更容易发现查询和特别工作的东西。如果你被要求做某件事,并且你的组织足够大,保证有人以前做过。
  • 为了再现性,敦促分析师和 DS 尽可能使用 SQL*,而不是 python、R 或 excel。当你在研究一个模糊的研究问题时,一头扎进熊猫或潮汐中显然是好的,但要把它作为例外而不是常规。当您的 DS 在 pandas 中运行基本的聚合时,他们天生会牺牲可见性和可重复性,以换取他们认为这样做的好处(在我的例子中,通常只是熟悉度)。*****

结束语

我建议的改变很小。在你的 analytics onboarding 文档中明确说明“SQL(尽可能)”,并建立一个支持知识共享的 SQL 编写环境(参见 hyperquery.ai )。但是除此之外,没有什么需要改变的了。

试一试,让我知道这些调整对你有什么效果(或者你是否通过其他方式成功地推动了可发现性和可再现性)。这些微小的变化可能意味着沮丧、超负荷工作的数据团队与通过可重用、自由共享的 SQL 来简化和减轻这种工作负载的团队之间的差异。

推文@ imrobertyi/@hyperquery来问好。👋
关注我们LinkedIn。🙂* 要了解更多关于 Hyperquery 的信息(并注册我们的私人测试版),请访问Hyperquery . ai (如果你对帮助建立感兴趣,我们正在招聘——查看我们的 空缺职位 )。)***

如何在 Google Cloud 上安排 Python 脚本

原文:https://towardsdatascience.com/how-to-schedule-a-python-script-on-google-cloud-721e331a9590?source=collection_archive---------7-----------------------

如何使用 Google Cloud Scheduler 和 Cloud Function 安排一个递归 Python 脚本

照片由尼古拉·塔拉先科Unsplash 拍摄

没有在您的服务器中设置气流?没有任何设置 cron 作业来调度脚本的经验?别担心。今天我们将学习如何用最少的 cron 作业知识在 Google 云平台中调度您的 Python 脚本。

Cloud Scheduler 是一个受管理的 Google 云平台 (GCP)产品,它允许您指定一个频率来计划一个重复的作业。简而言之,它是一个轻量级的托管任务调度程序。

为什么我们需要一个调度程序?调度程序允许您在任何时间运行工作流。它在失败的情况下重试,甚至让你在凌晨 3 点运行一些东西,这样你就不需要在半夜醒来。

入门指南

创建云调度程序

让我们从创建云调度程序开始。去谷歌云平台找云调度器或者直接去这个链接

注意:您必须设置您的计费帐户才能使用云调度程序。你将每月 3 个免费工作,每个计费帐户。更多详情,可以参考云调度器定价

让我们从“安排工作”开始。

在本例中,我将安排一个 Python 脚本来发送电子邮件,因此作业的名称将是schedule-email

计划频率采用 unix-cron 格式。如果不熟悉 unx-cron,可以参考 crontab guru 网站。我总是参考这个网站,以确保我设置了正确的时间表。

例如,30 8 * * *表示该作业将在每天的 08:30 运行。

0 9 6 * *表示该作业将在每月 6 日 09:00 运行。

接下来,我们必须配置作业的目标。在本例中,我们将使用发布/订阅作为目标类型。新主题schedule-email为该作业创建了一个新主题。

这里的高级设置是可选的。但是为了安全起见,让我们设置一个重试尝试。之后,让我们单击“创建”按钮来创建云调度程序。

创建云函数

接下来我们去云函数创建一个云函数。

让我们用名称和地区来配置我们的云函数。触发器类型将是发布/订阅,主题将是我们刚刚创建的主题schedule-email

接下来,我们必须用main.pyrequirement.txt设置脚本。

在本例中,我们将发送一封带有此调度程序的简单电子邮件。因此,这个脚本不需要额外的包/库。我将保持requirement.txt不变。

如果你有兴趣安排一封带附件的邮件,请参考我的另一篇文章。

入口点将是您定义在脚本中运行的函数,在本例中是schedule_email

您还可以选择配置分配的内存、超时和运行时环境变量。如果你运行一个很长的脚本,请记住分配更多的时间和内存。

耶!邮件成功安排在晚上 10 点。

现在你已经学会了如何使用 Google Cloud Scheduler 来调度 Python 脚本。您可以将该调度器用于其他任务,如临时批处理作业、大数据处理作业或基础设施自动化工具。好的一面是云调度程序为您处理所有繁重的工作!

可以在我的 Github 要诀 中查看main.py。干杯!

如果你喜欢读这篇文章,你可能也会喜欢这些:

你可以在 Medium 上找到我其他作品的链接,关注我 这里 。感谢阅读!

如何安排无服务器谷歌云功能定期运行

原文:https://towardsdatascience.com/how-to-schedule-a-serverless-google-cloud-function-to-run-periodically-249acf3a652e?source=collection_archive---------6-----------------------

你有一些需要定期运行的代码吗?请继续阅读,了解如何在谷歌云平台(GCP)上使用无服务器功能来实现这一点。

Unsplash 上由 Boitumelo Phetla 拍摄的照片

作为一名数据科学家/工程师,我经常有需要定期运行的代码。这可能是每天下午 02:00 处理一些日志文件,或者每天凌晨 01:00 运行机器学习模型。

如果它可以在内存限制 8 GiB 内运行,并且不到 9 分钟,那么它可能值得作为一个无服务器功能来实现。

如果您对此感兴趣,那么在本文中,我将向您展示如何使用无服务器架构,利用谷歌云平台(GCP)的云功能无服务器计算产品来调度您的代码。

要了解更多关于谷歌云功能及其好处的信息,请查看我在 Medium 上的另一篇文章。第一节简明扼要地解释了它。😄

⚠️⚠️家政公司

本文假设您已经拥有一个 GCP 账户。如果你没有,在这里注册https://cloud.google.com/可以获得一些免费积分。

如果你想从你的本地机器上与你的 GCP 账户进行交互,使用 这里 列出的步骤安装 Google Cloud SDK。

确保在您的 GCP 项目中使用 API 控制台 *为 Google 云存储、函数、发布/订阅和调度程序启用 API*

本文中的所有代码都是用 Python 3.8 开发的。所有必要的代码都可以通过 GitHub Gist 获得。

任务和解决方案架构示例

那么,我们在建造什么?为了本文的目的,我们将安排一个每 15 分钟打印一次钞票的云函数。当然不是字面上的钱😄,而是钱这个字。

云解决方案架构。(来源:作者)

我们将使用谷歌云平台(GCP)的 4 项服务来完成这项工作。

  1. 云功能 :哦,是的,这个无服务器计算服务将托管并执行我们所有的代码。该服务将每隔 15 分钟触发一次。当它执行时,它将运行我们的代码,将单词“money”写入一个文本文件,并将其保存在 Google 云存储桶中。这是一项简单的任务,可以轻松适应您的使用情形。
  2. Cloud Pub/Sub:这是一个事件驱动的实时消息服务,允许我们创建异步通信的系统。它使得系统设计中存在事件生产者和消费者,也称为发布者和订阅者。在我们的例子中,云调度器将产生一个 Pub/Sub 事件,该事件将触发我们的云功能消费者,该消费者正在从 Pub/Sub 服务中监听特定的主题。
  3. 云调度器 : 这是一款来自 GCP 的全托管企业级 cron 作业调度器。它基本上可以安排任何事情。在这种情况下,我们使用它每隔 15 分钟为一个主题生成一个发布/订阅事件。
  4. 云存储 : 嗯……这里真的不多说了。它基本上是一个保存任何类型数据的位置。它可能没有其他的性感,但在我看来,它是 GCP 上一切的可靠支柱!

现在…我们开始建造!🚀 🚧

步骤 0:创建一个 Google 云存储桶

在 GCP 控制台上搜索存储。(来源:作者)

在 GCP 控制台中,搜索存储以找到云存储,然后单击创建存储桶。给存储桶取一个合适的名称,并确保在计划运行云功能的同一区域创建存储桶。您可以保留其余设置,然后点击创建

创建云存储桶来存储文本文件。(来源:作者)

第一步:创建并配置云功能

现在在 GCP 控制台上搜索云函数,点击创建函数。给云函数取一个合适的名字,并确保它与存储桶在同一个区域。

选择功能触发类型云发布/订阅

创建由发布/订阅触发的云函数。(来源:作者)

点击创建一个主题来创建一个新的发布/订阅主题,这将触发这个云功能。给它起一个合适的名字,点击创建主题,然后点击保存来完成发布/订阅触发器。

创建新的发布/订阅主题。(来源:作者)

现在,在运行时、构建和连接设置部分下,保持运行时选项卡设置不变。我们的功能非常简单。因此,256 MiB 内存的执行环境已经足够了。

但是,在连接选项卡中,选择仅允许内部流量。出于安全原因,这样做是因为它只允许来自项目环境内部的流量,而不会被恶意的外部请求触发。

完成后,点击下一个的对功能进行编码。

步骤 2:编码和部署云功能

现在,您应该会看到内联源代码编辑器窗口。这是我们定义运行时环境和编写要执行的函数的地方。

选择运行时环境为 Python 3.8,因为我们将用 Python 编码。

云函数的内联编辑器。(来源:作者)

如您所见,源代码内联编辑器选项卡下显示了两个文件。让我们了解它们是什么。

文件:main.py

这个文件是所有函数代码驻留的地方,当触发事件发生时被执行。因为我们已经选择了 Pub/Sub 作为触发器,所以在这个文件中应该有一个签名为 hello_pubsub(event,context) 的函数,默认情况下会填充这个函数。

这是由发布/订阅事件触发的主函数的签名。显然,您可以更改主函数名,但请确保在入口点函数名选项卡中相应地更新它。这就是环境如何知道调用哪个函数来处理发布/订阅事件。

出于本文的目的,我们将保持名称不变,只更新内容。

文件:requirements.txt

在这里,我们声明需要安装在云函数环境中的库,以执行我们的函数。默认情况下,环境预装了一堆库。因为这是一个简单的函数,所以我们不需要安装太多额外的库。

编码和部署

你可以从下面的要点中复制并粘贴这两个文件的内容。代码是不言自明的,并被注释。如果您有任何问题,请联系我们。😃

本文所需的云函数代码。(来源:作者)

一旦将代码从 gist 复制到相关文件中,就可以点击 deploy

这将需要一些时间,因为正在设置云功能环境,并且安装了所有要求。您应该会在函数名旁边看到一个加载圆圈。

成功部署函数时,函数名称旁边会出现一个绿色对勾。👊

云功能部署成功。(来源:作者)

好吧,那么…让我们看看它是否有效!😅为此,点击动作下的 3 点按钮,并点击测试功能

步骤 3:测试云功能

测试部署的云功能。(来源:作者)

由于我们的云函数不需要任何输入数据或上下文,我们只需单击蓝色的测试函数按钮,让触发事件输入保持空白。

当函数成功完成时,它应该在下面的日志中显示 OK。如果出现错误,请阅读日志进行诊断。

我们还应该看到云存储桶里有一个新的文本文件,里面有钱!💲 💲 😄

云存储桶,带有由云功能生成的文本文件。(来源:作者)

现在剩下的就是安排函数定期运行。

步骤 4:计划云功能

回到 GCP 控制台,搜索云调度程序,并点击创建作业。这应该会将您带到一个设置页面来配置 cron 作业。

设置云调度程序作业。(来源:作者)

下定义作业部分,给出一个合适的名称,并使用 unix-cron 格式,指定调度频率。

*因为我们想安排我们的函数每 15 分钟运行一次,所以使用下面的: **/15 * * * *** 。您可以从这里了解更多关于格式的信息,并根据您的需求进行调整。

哦,还要确保你在正确的时区。😅

为我们的发布/订阅主题设置 cron 作业的目标。(来源:作者)

配置作业目标部分下,选择发布/订阅主题作为目标。这将显示当前项目中的所有主题。确保您选择了正确的发布/订阅主题,如步骤 1 中所创建的。

必须提供消息正文。我们只是说“你好”,尽管在我们的体系结构中它不会被处理。

创建后的云调度程序作业列表。(来源:作者)

现在点击 create 来安排这个任务。现在应该每 15 分钟运行一次我们的云功能。

但是,我们可以点击调度程序作业页面中的立即运行,立即运行该功能。

您应该能够在云存储桶中看到一个新的货币文本文件,它是在您点击 run now 时创建的。如果出现错误,请检查日志进行诊断。

现在,在你最后一次运行后的每 15 分钟,你应该能够看到新的货币文本文件被添加到云存储桶中。

预定的云功能每 15 分钟产生一次钱。(来源:作者)

恭喜你,你现在已经成功地安排了一个定期执行的无服务器功能。😄 🚀

⚠️注意:确保删除/暂停云调度程序作业和其他资源,以避免产生持续成本。🔥**

最后的想法

通常,人们(包括我)会使用虚拟机和其他工具来运行他们的 cron 作业。但是,重新审视这些任务,看看它们的内存/计算约束是否符合云功能的限制,可能是值得的。

从数据科学系统的角度来看,我可以看到如此多的任务可以采用这种架构。定期处理一些 CSV 数据文件、运行模型预测、每天生成摘要报告表、每天将外部文件加载到大型查询表中,等等。

*此外,拥有像这样的无服务器架构可以实现很大的灵活性并提高可维护性。嗯…这就是微服务架构的全部。 ***条款和条件适用。😄 ******

希望这篇文章能为您的下一个解决方案架构提供一些思路。

感谢您的阅读。

希望这篇文章对你有用。如果你有任何问题或者你认为我能帮忙,请联系我。总是期待与新朋友建立联系。😄

你可能也会喜欢我的这些文章:

*https://python.plainenglish.io/the-only-data-science-machine-learning-book-i-recommend-4fc23b947dfe https://medium.com/codex/3-simple-side-hustles-to-make-extra-income-per-month-as-a-data-scientist-7470030fbf43 *

如何在 Python 中安排航班

原文:https://towardsdatascience.com/how-to-schedule-flights-in-python-3357b200db9e?source=collection_archive---------9-----------------------

使用 CVXPY 分配足够的飞机,同时最小化成本

动机

想象你是一家航空公司的所有者。您的航空公司需要分配其在纽约的飞机来覆盖所有即将到来的定期航班。

共有 10 个航班和 8 个航班序列。每个航班序列由多个航班组成。

例如,一系列航班可以包括从纽约到布法罗、从布法罗到芝加哥以及从芝加哥到纽约的航班。

数据来源于应用整数规划,由陈博士,巴特森,r . g .&党,Y. (2010)

作者图片

每个飞行序列都有一定的成本。我们需要选择一个飞行序列的子集,以便每个航班至少有一架飞机。

有许多可能的方法来选择航班序列的组合,以便每个航班都有可用的飞机。一种可能的组合如下:

作者图片

另一种可能的组合如下:

作者图片

还有很多。

您的航空公司应该选择哪种序列组合才能满足约束条件并使成本最小化?

很多主要航空公司都面临这个问题。美国航空公司估计,他们基于数学编程的系统每年节省约 2000 万美元。

在本文中,您将学习如何使用整数编程和 Python 来解决这个问题。

什么是整数规划?

整数规划涉及带有目标和约束的问题。部分或全部变量被限制为整数。

CVXPY 是一个 Python 工具,为许多整数编程求解器提供了接口。要安装 CXVPY,请键入:

pip install cvxpy

让我们确定这个问题中的输入、目标和约束。

检索数据

从从 Google Drive 下载数据开始:

数据来源于应用整数规划,由陈,陈德生,巴特森,r . g .&党,Y. (2010)

获取每个飞行序列的时间表、成本和小时数。

把所有正数变成 1:

输入参数

定义输入参数:

作者图片

决策变量

使用cp.Variable定义决策变量:

作者图片

限制

每个航班必须至少有一架飞机。例如,为了确保至少有一架飞机从纽约飞往布法罗,必须选择航班顺序 1、4 或 7。

为了确保从纽约→辛辛那提的航班至少有一架飞机,必须选择航班顺序 2 或 5。

因此,对于从纽约→布法罗的航班,我们有约束条件:

作者图片

将这一约束推广到所有 10 次飞行,我们得到:

作者图片

目标

我们想选择使总成本最小化的航班顺序。

作者图片

解决问题

现在我们有了约束和目标,让我们来解决问题吧!

13.0

目标的值是 13。让我们看看 y 的值是多少。

[1\. 1\. 1\. 0\. 0\. 0\. 0\. 0.]

酷!因为 y 数组的前 3 个值是 1,所以我们的飞机通过选择航班 1、2 和 3 的顺序来节省最多的钱。

这意味着飞机应该飞行:

  • 从纽约→布法罗→芝加哥→纽约出发
  • 从纽约→辛辛那提→匹兹堡→纽约
  • 从纽约→芝加哥→辛辛那提→纽约

作者图片

酷!如果我们的飞机希望飞行总小时数不超过 1700 怎么办?

让我们将这个约束添加到我们的问题中,看看会发生什么。

对总时数的约束

首先,我们需要获得代表每个飞行序列的小时数的数组:

作者图片

将第一个约束与新约束合并:

作者图片

解决问题:

20

带有附加约束的目标值为 20,大于 13。为什么目标的值会改变?

这是因为选择了不同的飞行顺序。

作者图片

但是为什么第二个和第三个航班序列没有被选中呢?如果我们仔细观察代表小时的数组,我们可以看到前 3 次飞行的总小时数超过 1700。

作者图片

作者图片

但是,第一、第五和第六个航班序列的总小时数小于 1700,这满足约束条件。

作者图片

这是新选择的飞行序列的可视化表示。

作者图片

结论

恭喜你!您刚刚学习了如何选择航班顺序,同时将成本降至最低。我希望这篇文章能够激励您使用整数编程和 Python 解决类似的问题。

在 Github repo 中,您可以随意使用本文的代码:

https://github.com/khuyentran1401/Data-science/blob/master/mathematical_programming/schedule_flight_crew/flight_crew_schedule.ipynb

我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以通过 LinkedInTwitter 与我联系。

如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:

参考

陈(2010)。应用整数规划:建模与求解。j .威利&的儿子们。

如何使用 Cron 调度 Python 脚本——您需要的唯一指南

原文:https://towardsdatascience.com/how-to-schedule-python-scripts-with-cron-the-only-guide-youll-ever-need-deea2df63b4e?source=collection_archive---------0-----------------------

自动化您的 Python 脚本执行—在 Linux 和 macOS 上运行

照片由乔尔&贾斯敏·福斯特伯德Unsplash 拍摄

当涉及到重复性的任务时,你更擅长自动化它们。这篇文章将教你如何做。

阅读完本文后,您将知道如何自动执行两个 Python 脚本来获取、解析和保存来自 web 的数据。我们开始吧!

这篇文章的结构如下:

  • Cron 是什么?
  • 写剧本
  • 编辑 Crontab 文件
  • 测试
  • MacOS Gotchas
  • 结论

Cron 是什么?

可以把 Cron 看作是在 Linux 和 macOS 环境中调度任务的最简单的方法之一。“Cron”一词来源于希腊语“Chronos”(时间),“Crontab”一词代表“Cron table”或时间表。你很快就会知道这张表指的是什么。

任何时候你都应该使用 Cron 来实现自动化,比如操作系统作业或者 Python 脚本。不用说,自动化的 Python 脚本基本上可以做任何事情。

在 Linux 和 macOS 上,Crontab 由六个字段组成。前五个字段保留用于计划执行的日期和时间(分钟、一月中的某天、一年中的某月、一周中的某天),最后一个字段保留用于要执行的命令。

您可以在日期-时间字段中自由使用星号、值和范围,但稍后会详细介绍。

您现在知道 Cron 和 Crontab 是什么了,但是在进行调度之前,我们仍然需要一些 Python 脚本。接下来我们来介绍一下。

写剧本

今天我们将安排两个简单的脚本。他们的工作是从以下虚假网站获取数据:

这些网站包含各种主题的虚拟数据,但我们将只关注用户和帖子。我们处理两个站点的唯一原因是展示如何在不同的时间间隔调度 cron 作业。

这两个脚本都将通过requests.get() API 调用获取数据,解析 JSON 数据,处理它(只保留某些属性),将其转换成 Pandas 数据帧,并保存到 CSV 文件中。听起来很多,但是只有几行代码。

让我们从get_users.py文件开始:

get_posts.py文件将或多或少地相同——除了处理部分:

最后,确保在你的脚本所在的地方创建output。这就是我们所需要的。如果您要运行脚本,CSV 将以<name>_<timeastamp>.csv名称结构保存在output目录中。时间戳是为了确保文件不会被覆盖。

接下来看看怎么安排任务。

编辑 Crontab 文件

无论您使用的是 Linux 还是 macOS,这一部分都是一样的。macOS 有一些权限问题,但我们稍后会谈到。

如前所述,您必须遵循特定的语法来调度 cron 作业。好消息是,你可以使用 Crontab.guru 网站来制定你的日程安排。

我们希望get_users.py每隔偶数分钟运行一次(例如,0,2,4),而get_posts.py每隔奇数分钟运行一次(例如,1,3,5)。以下是每隔一分钟运行一个作业的正确模式:

图 1 —每隔一分钟执行一次的 Cron 作业模式(图片由作者提供)

以下是奇数分钟:

图 2 —每隔几分钟执行一次的 Cron 作业模式(图片由作者提供)

很好——让我们使用这些模式来安排执行。打开一个终端窗口,执行pwdwhich python3命令,获得脚本文件夹和 Python 的绝对路径:

图 3-获取绝对路径(图片由作者提供)

一旦有了这些,输入crontab -e命令编辑一个 cron 文件,或者创建一个不存在的文件:

图 4 —访问 crontab 文件(作者图片)

它将打开一个 VIM 编辑器——在那里,点击键盘上的I键进入插入模式。您必须指定调度模式、Python 可执行文件的完整路径和脚本的完整路径,以使调度工作正常进行。使用下图作为参考:

图 5 —编辑 crontab 文件(作者图片)

完成后,按下ESC键退出插入模式,紧接着按下:wqENTER键。这将保存 crontab 文件,您将立即返回到终端窗口:

图 6 —成功创建 crontab 文件(作者图片)

要验证文件是否已成功保存,您可以使用crontab -l命令——它将列出所有计划的作业:

图 7-列出所有计划的作业(按作者排序的图像)

这就是你要做的。让我们在下一节检查调度是否有效。

测试

除了坐在那里看着你的脚本每一分钟被执行,你别无选择。这是几分钟后我的output文件夹的样子:

图 8-输出文件夹(作者提供的图片)

如您所见,一切都按预期运行。不要忘记删除这两个作业,否则每天会有 1440 个新的 CSV 文件。

MacOS Gotchas

Linux 用户应该不会有任何问题,但是在 macOS 上情况就不同了。默认情况下,macOS 不会给终端和 Cron 提供完整的磁盘访问权限,所以您必须手动完成。

需要明确的是,您不会得到任何错误,但是output文件夹将保持为空。

如果是这样的话,请跟随这篇文章——它将向您展示如何向终端和 Cron 授予完整的磁盘访问权限。

结论

现在您已经知道了——如何在 Linux 和 macOS 上使用 Cron 轻松调度 Python 脚本。

可能性是无限的——从预定的 web 抓取到 ETL 管道的自动执行。代码可以改变,但原则保持不变。

玩得开心!

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

https://medium.com/@radecicdario/membership

了解更多信息

保持联系

如何通过简单的电源自动化来计划无限制的电源 BI 数据集刷新

原文:https://towardsdatascience.com/how-to-schedule-unlimited-power-bi-dataset-refreshes-with-a-simple-power-automate-a7affe90c2de?source=collection_archive---------4-----------------------

来自 Unsplash.com 的斯蒂芬·菲利普-Hostreviews.co.uk

如何在不到五分钟的时间内设置自动刷新而无需直接查询

为什么您不能总是对您的 PowerBI 使用直接查询

通常,数据工程师会建议您在 Power BI 报告中使用直接查询。这种解决方案(可能)是最用户友好的,因为它使用户能够通过一次点击来刷新数据和视觉效果。然而,有许多技术原因为什么直接查询可能是不可能的。最常见的问题可能是这个:你的数据有不止一个来源

Power BI 的直接查询选项仅在您的 BI 数据集基于单一来源时有效。目前,您的报告需要两个或更多来源,不再支持直接查询。虽然这对于拥有发达的 IT 基础设施和训练有素的数据工程团队的组织来说可能不是问题,但对于其他组织来说却是一个巨大的挑战。许多组织使用 Power BI,因为内置的数据建模工具使得在不应用全面的 ETL 过程的情况下组合不同的数据源变得容易。如果您想不出适用的场景,请考虑以下商业案例:

您的销售团队使用 Salesforce 跟踪他们的销售线索并维护客户信息。然而,财务部使用一种小型会计软件,这种软件是根据您所在地区的要求量身定制的。

财务部门现在希望将客户、渠道和财务数据整合到一份报告中。在大公司中,数据工程团队会将不同的系统连接到一个仓库,并创建一个包含所有需要的信息的表。

但是,您的公司很小,而且您没有数据工程团队。您的会计软件太不知名,不提供 Salesforce 的标准连接器。

因为您希望避免在外部程序员身上花钱,所以您将不同的源连接到您的 Power BI,并通过数据建模器自己进行映射。因此,直接查询选项被禁用,您的用户无法再通过报告的刷新选项更新数据和图像。

以下是你解决这个问题的方法…

如果不能使用直接查询,用户必须手动刷新数据集。虽然这不仅耗时,而且几乎不可能。大多数情况下,最终用户无法访问报表的基础数据集。换句话说,他们必须向报告管理员请求手动刷新…浪费更多的时间。

你们中的一个会跳起来说:为什么不在 Power BI Pro 中简单地安排刷新?这是个好主意,但是你每天只能刷新 8 次。

那还有什么?正确!我们可以升级到高级,这样我们每天最多可以安排 48 次刷新。虽然对于大多数用例来说这可能已经足够了,但这只能让您每 30 分钟刷新一次数据集。如果你想达到接近实时,这是不够的。通过 Power BI cloud 界面设置 48 个日程安排也是一项痛苦的手动工作。相信我,我尽力了。

…您应该这样做!

你需要的东西

在您开始实现您的 Power Automate 流程之前,您需要进行一些采购。给你自己买以下两件东西(不,我不会因此得到任何会员奖金):

如何实现它

首先,将您的报告发布到您的高级工作区或用户。您可以识别用户或工作区是否是高级的,如果它有一点💎名字旁边的。但是,您只能在 web 界面中看到这一点。因此,我建议您在发布报告之前检查一下。

现在,登录到您的 Power Automate web 界面,点击“我的流程”。之后,点击“新建流量”并选择“预定云流量”选项。

新的预定云流量选项。图片作者。

然后会要求您提供名称、开始时间和流程间隔。随意输入,点击创建

预定云流量选项。图片作者。

您已经成功创建了流程,并将看到一个新页面。在这里,单击“+New step”选项,并在搜索栏中键入“刷新数据集”。然后点击 Power BI 动作“刷新数据集”

相应的操作将作为下一步成功添加。现在,您可以在相应的字段中选择您的工作空间或用户以及您的目标数据集。然而,根据您的系统设置,Power Automate 会要求您首先登录 Power Bi。提供您的凭据,然后单击“保存”。

刷新数据集操作。图片作者。

恭喜你!您已经成功设计了一个 Power Automate,它将在指定的循环中刷新目标数据集,而无需任何额外的手动工作。

如果您不确定计划的刷新是否真正起作用,您可以在最后一步检查您的流的运行历史。您可以通过点击流的名称并向下滚动来实现。在这里,您将看到已执行运行的历史记录。如果运行成功,状态将为绿色。

流程运行历史记录。图片作者。

对于所有多疑的人来说:你也可以在 Power BI web 界面上查看。只需单击您的工作区或用户(您发布报告的地方),并查看相应的数据集列。你会看到“刷新”下的条目会显示与你的工作流程大致相同的时间。由于刷新本身可能会出现时差,所以不必担心。这是完全正常的。

Power BI web 界面中刷新的数据集和报告。图片作者。

如何用 Python 熊猫刮 HTML 表格

原文:https://towardsdatascience.com/how-to-scrape-html-tables-with-python-pandas-98d18d2129cb?source=collection_archive---------12-----------------------

数据收集

一个现成的代码,它利用了 Python 熊猫库的 read_html()函数

图片由 GoumbikPixabay 获得

几乎所有在 Python 工作的数据科学家都知道 Pandas 库,几乎所有人都知道read_csv()函数。但是,他们中只有很少人知道read_html()的功能。

read_html()函数允许快速提取 HTML 页面中包含的表格。这个函数的基本版本提取 HTML 页面中包含的所有表格,而使用一些特定的参数可以提取非常特定的表格。

在本教程中,我将重点放在以下 HTML 页面上,其中包含 2020 年欧洲杯的各组比赛:

作者图片

每个表格都具有以下 HTML 结构:

<table class="table"> <thead>
    <tr>
      <th title="Field #1"></th>
      <th title="Field #2">P</th>
      <th title="Field #3">+/-</th>
      <th title="Field #4">Pts</th>
    </tr>
  </thead> <tbody>
    <tr>
      <td><span>1</span> </span>ITA</span>  <span>Italy</span></td
      <td>3</td>
      <td>7</td>
      <td>9</td>
    </tr>
    <tr> 
      ...
    </tr>
    <tr>
       ...
    </tr>
    <tr>
       ...
    </tr>
  </tbody>
</table>

提取所有表格

欧足联网站包含 6 张表格,每组一张(A-F)。我可以简单地通过将路径传递给read_html()函数来提取所有的表

import pandas as pddf_list = pd.read_html("source/euro2020_groups.html")

该函数返回一个包含 6 个数据帧的列表,每组一个。例如,df_list[0]包含第一个数据帧:

作者图片

所有的数据帧都有相同的结构。我注意到第一列Unnamed: 0没有被正确识别。因此,它需要一个清洁过程。

将所有提取的表组合成一个表

现在,我将所有提取的表组合成一个表。为了保持表之间的差异,我需要添加一个新列,存储每条记录所属的组。

我定义了一个包含所有组(A-F)的列表:

import stringN = len(df_list)
groups_names = list(string.ascii_uppercase[0:N])

groups_names变量包含以下值:

['A', 'B', 'C', 'D', 'E', 'F']

现在我通过append()函数将所有数据帧分组。首先我定义了一个空的数据帧,然后我将包含在df_list变量中的所有数据帧添加到它上面。根据上下文,我还添加了Group列,它指定了每条记录所属的组:

df = pd.DataFrame()
for i in range(0,N):
    group_col = [groups_names[i]] * len(df_list[i])
    df_list[i]['Group'] = group_col
    df = df.append(df_list[i])

现在数据帧df如下表所示:

作者图片

清洁数据框

数据帧df看起来有点脏:事实上,列Unnamed: 0是不正确的。首先,我把它改名为Team:

df.rename(columns={"Unnamed: 0": "Team"}, inplace=True)

然后我扩展了Team列,将它分成许多列:

df_new = df['Team'].str.split(' ',expand=True)

df_new数据帧如下所示:

作者图片

唯一有趣的列是 0、1 和 2。因此,我选择 then,并将其分配给原始数据帧中的新列df:

df[['N', 'ID', 'Country']] = df_new[[0,1,2]]

我可以删除原来的Team列:

df.drop(['Team'], axis=1, inplace=True)

df数据帧如下所示:

作者图片

表格是正确的,但是列的顺序是错误的。我需要首先移动组,然后是 N,ID,Country,最后是剩余的列。我可以通过reindex()函数对列进行重新排序,该函数接收精确的列顺序作为输入:

df = df.reindex(columns=['Group','N', 'ID', 'Country', 'P', '+/-', 'Pts'])

df数据帧如下所示:

作者图片

保存数据帧

现在,我可以将数据帧保存为 CSV 文件:

df.to_csv('euro_2020_groups.csv')

摘要

在本教程中,我用 Python Pandas 演示了一个从 HTML 页面中提取表格的简单机制。这可以通过read_html()函数来实现,非常简单快捷。在大多数情况下,报废的桌子需要一些清理过程。

read_html()函数还提供了一个有趣的输入参数,称为match,可以用来提取复杂 HTML 页面中非常具体的表格。想深化这个参数敬请期待:)

本文中解释的所有代码都可以作为 Jupyter 笔记本从 my Github repository 下载。

如果你想了解我的研究和其他活动的最新情况,你可以在 TwitterYoutubeGithub 上关注我。

相关文章

[## 用 Python Selenium 从嵌套的 HTML 页面中抓取数据

towardsdatascience.com](/scraping-data-from-nested-html-pages-with-python-selenium-c5f23065841f) [## 如何用 Python 加载 Google 文档的内容

towardsdatascience.com](/how-to-load-the-content-of-a-google-document-in-python-1d23fd8d8e52)

如何使用 Kaggle API 搜索和下载数据?

原文:https://towardsdatascience.com/how-to-search-and-download-data-using-kaggle-api-f815f7b98080?source=collection_archive---------13-----------------------

使用命令行工具与 Kaggle 交互

图片由穆罕默德·哈桑拍摄,来自 Pixabay ,使用 Pixlr 编辑

aggle 是世界上最大的数据科学社区,拥有强大的工具、数据集和其他资源来帮助您实现数据科学目标。Kaggle 包含大量用于教育目的的免费数据集。它还举办比赛,并免费提供笔记本电脑,以探索和运行数据科学和机器学习模型。

要使用 Kaggle 资源并参加 Kaggle 比赛,您需要登录 Kaggle 网站并进行相应的搜索。要从 Kaggle 下载数据集,需要搜索数据集并手动下载,然后移动到所需的文件夹进行进一步探索。

所有与 Kaggle 的交互都可以通过用 Python 实现的命令行工具(CLI) 使用 Kaggle API 来完成。

安装:

使用 pip 安装 Kaggle 库:

**pip install kaggle**

认证:

要使用 Kaggle 公开可用的 API 与 Kaggle 资源交互,首先您需要使用 API 令牌进行认证。按照以下步骤将新的身份验证令牌下载到您的计算机上,以完成身份验证:

  • 点击您的个人资料图片点击下拉菜单中的账户
  • 向下滚动到 API 章节
  • 点击“创建新的 API 令牌”按钮,以 JSON 文件的形式下载一个新的令牌,该文件包含用户名和 API 密钥。
  • 将 JSON 文件复制到**~/.kaggle/**目录下。在 windows 系统中,进入根目录,然后进入**.kaggle**文件夹,将下载的文件复制到该目录。

如果您直接使用 Kaggle API,那么只要您能够在运行时提供凭证,令牌放在哪里并不重要。

您可以使用 Kaggle API 进行交互,以便在不登录其网站的情况下使用其资源,以下是通过命令行语句使用 API 的可用交互列表:

  • 搜索数据集
  • 下载数据集
  • 创建和维护数据集
  • 搜索已发布的笔记本
  • 下载已发布的笔记本
  • 创建和运行笔记本
  • 与比赛互动
  • 提交参赛作品

1.搜索数据集:

使用 CLI 参数,您可以搜索任何关键字来查找相应的数据集。使用 search 语句获取数据集列表的 CLI 语句:

**kaggle datasets list -s [KEYWORD]**

(图片由作者提供),使用“titanic”关键字搜索数据集的结果

2.下载数据集:

在您使用用于搜索的 CLI 参数搜索了适当的数据集之后,这个 API 提供了一个优势,可以将任何数据集从 Kaggle 下载到您的本地机器。使用 CLI 下载与数据集关联的文件的命令:

**kaggle datasets download -d [DATASET]**

3.创建和维护数据集:

Kaggle API 可用于使用 CLI 参数上传新数据集和数据集版本。这可以简化 Kaggle 上数据集和项目的共享。

创建新的数据集,请遵循以下步骤:

  • 将数据集文件组装到一个文件夹中,然后上传到 Kaggle 上。
  • 要生成元数据,请运行:**kaggle datasets init -p /path/to/dataset**
  • 将元数据添加到生成的文件:**datapackage.json**
  • 为了最终创建数据集,运行:**kaggle datasets create -p /path/to/dataset**

为了上传现有数据集的新版本遵循以下步骤:

  • 要生成元数据,运行:**kaggle datasets init -p /path/to/dataset**
  • 确保元数据文件**datapackage.json**中的**id**字段指向您的数据集。
  • 要最终创建数据集,运行:**kaggle datasets version -p /path/to/dataset -m "MESSAGE"**

4.搜索已发布的笔记本:

使用 Kaggle API,您可以使用关键字进行搜索,找到相应的已发布笔记本。它支持搜索已发布的笔记本及其元数据,以及用于创建和运行笔记本的工作流。

使用搜索关键字获取已发布笔记本列表的 CLI 语句:

**kaggle kernels list -s [KEYWORD]**

(图片由作者提供),使用“titanic”关键字搜索笔记本的结果

5.下载已发布的笔记本:

Kaggle API 提供了从 Kaggle 下载任何发布的笔记本到你的本地机器的优势。使用 CLI 下载与笔记本相关的文件的命令:

**kaggle kernels pull -k [KERNEL] -p /path/to/download -m**

6.创建和运行笔记本:

Kaggle API 可用于上传新笔记本,并使用 CLI 参数维护笔记本版本。这可以方便在 Kaggle 上共享笔记本和项目。

创建新笔记本,请遵循以下步骤:

  • 将代码文件(笔记本)放在一个文件夹中上传到 Kaggle。
  • 要生成元数据,请运行:**kaggle kernels init -p /path/to/kernel**
  • 将元数据添加到生成的文件:**kernel-metadata.json**
  • 为了最终创建数据集,运行:**kaggle kernels push -p /path/to/kernel**

为了上传现有数据集的新版本遵循以下步骤:

  • 将笔记本的最新版本和相应的元数据下载到本地机器:**kaggle kernels pull -k [KERNEL] -p /path/to/download -m**
  • 确保元数据文件**kernel-metadata.json**中的**id**字段指向您的笔记本。
  • 要最后推送新版笔记本运行:**kaggle kernels version -p /path/to/kernel**

7.与竞争对手互动:

Kaggle API 工具提供了一种与 Kaggle 上举办的比赛进行互动的简单方式。要接受任何比赛的规则,您需要登录到比赛网站并接受规则以下载数据集并提交。你需要访问 Kaggle 网站并接受那里的规则,因为通过 API 是不可能的。

与 Kaggle 上举办的竞赛互动的命令:

  • 所有正在进行的比赛列表:**kaggle competitions list**
  • 下载比赛相关文件:**kaggle competitions download -c [COMPETITION]**

8.提交竞赛:

只有在您通过访问 Kaggle 竞赛网站页面接受提交规则后,才能提交任何竞赛。

  • 提交给竞争对手并获得分数的 CLI 参数:
**kaggle competitions submit -c [COMPETITION NAME] -f [FILE PATH]**
  • 要列出所有之前提交的竞赛运行:
**kaggle competitions submissions -c [COMPETITION NAME]**

结论:

在本文中,我们讨论了如何使用 Kaggle API 通过 CLI 参数使用 Kaggle 资源。使用 CLI 命令,我们可以与数据集、笔记本电脑或任何竞赛互动。

为了探索更多的 CLI 参数,您可以在任何调用之后添加***-h***来查看该命令的帮助菜单。

参考资料:

[1] Kaggle API 文档:https://www.kaggle.com/docs/api

[2] Kaggle API GitHub 回购:【https://github.com/Kaggle/kaggle-api

感谢您的阅读

如何分割胰腺 CT

原文:https://towardsdatascience.com/how-to-segment-ct-pancreas-3a390acb3c70?source=collection_archive---------14-----------------------

腹部增强 CT 发现和追踪胰腺指南

特别感谢我的好朋友梅根·恩格斯博士帮助我写这篇文章。

简介—什么是细分?

CT 扫描包含丰富的信息,可以帮助我们了解患者的健康状况。作为数据科学家,我们的角色是提取信息,以便可以测量或量化。

分析 CT 或 MRI 扫描的第一步通常是分割。这里,我指的是追踪——从背景中分割出重要的结构。从分割中,我们提取重要的特征,如器官体积、表面积、亮度和纹理模式,告诉我们疾病的各个方面。

细分可能是一个耗时的过程,也是我们试图使用深度学习实现自动化的首批任务之一。例如,我们实验室开发了一个 U-Net 模型,从腹部 CT ( ) 中分割出三十四个独特的器官。

在本教程中,我将演示如何从腹部 CT 分割胰腺。我将重点使用 ITK 快照,这是一个简单的,免费的工具,你可以使用开始。我将介绍一些解剖学基础,但如果你打算开始自己的研究项目,我强烈建议你联系临床专家,如放射科医生,以了解你的任务的具体需求。

TCIA 数据集

对于这个演示,我使用的是 癌症成像档案 (TCIA)数据集,这是一个由 NIH 提供的公开可用的医学图像数据集。完整的数据集包含来自健康患者的 85 次扫描。数据集还提供分段,尽管我将向您展示如何从头开始追踪。

ITK 快照

有许多工具可以查看和注释 DICOM 图像(有关 DICOM 文件格式的背景,请参见 我的另一篇文章 )。快速入门的方法是使用 ITK 快照 ,它很容易下载和使用。它非常适合较小的数据集。

快速插入——对于更复杂的项目(例如,涉及多个示踪剂或重复扫描的项目),我们在梅奥诊所的团队开发了我们自己的开源软件工具【RIL 轮廓 。RIL 轮廓有先进的功能,使分割更快,更准确,甚至数据版本,这有助于质量控制时,你有多个个人工作在同一个项目。

查看图像

ITK 快照支持 NIFTI 和 DICOM 格式的图像。图 1 显示了导入文件后 ITK 快照界面的样子。

图一。将文件导入 ITK 快照

这是一个 3D 扫描,以 3 个视图显示——轴向(也称为“横向”)(左上)、矢状(右上)和冠状(右下)。你会注意到每个视图都标有前视图(A),后视图(P),上视图(S),下视图(I),右视图(R)和左视图(L)。

对读者来说,右和左可能是向后的——这是从面对我们的病人的角度给出的。

您可以在任何平面上进行分割,但是通常在轴向平面上进行大部分分割。这是因为 CT 中的切片厚度通常在轴向平面上更大(3-5 毫米,而不是 0.5-0.8 毫米),所以您最终必须跟踪更少的切片。

开窗术

开始之前,我们需要调整扫描的对比度。这叫做“开窗”。CT 对比度是以 Hounsfield 单位测量的,它被标准化为空气(HU = -1000)和水(HU = 0)。要在 ITK 快照中调整窗口,请转到工具 > 图像对比度 > 对比度调整。有一个滑动条,但是直接输入数字会更准确。对于腹部软组织,级别为 50,窗口为 400,这意味着图像像素被裁剪在-350 到+450 之间。

图二。 CT 腹部开窗前(左)和开窗后(右)。设置为级别=50,窗口=400。

这些 CT 是对比增强的,这意味着碘造影剂被注射到血流中。这将使血管看起来比周围的组织更亮。此外,患者有钡剂吞咽形式的消化对比,这使得胃和小肠的内容物也显得明亮。

腹部解剖学

在我们找到胰腺之前,了解一点腹部解剖学是有帮助的。我在下面的扫描中标记了一些地标。如果你查阅解剖学教科书,你会看到胰腺藏在肝脏下面,胃的后面,通常靠近脊柱。

图 3。腹部冠状面(左)和轴面(右)解剖

胰腺解剖学

就像其他器官一样,胰腺的位置、大小和形状有相当大的差异,这使得它很难分割。胰腺可能特别难以分割,原因有几个—

  1. 它比其他固体器官附着少,而且容易移动
  2. 它直接连接其他周围器官(尤其是肠壁)
  3. 即使在健康的病人身上,它也有不均匀的外观。

下面,我从维基百科上复制了一幅漫画。胰腺器官分为三个区域,头部、身体和尾部。胰腺具有柔软的叶状外观,并围绕中央胰管组织,中央胰管将胰腺分泌的消化液运送到小肠。

图 4。胰腺图,来自维基百科

在 CT 上,这种分叶状的外观表现为一种柔软的块状结构。胰管可以是可见的,也可以是不可见的(年轻患者胰管不太可见)。要知道胰腺可能含有囊肿— 有人估计 把这个数字高达 50%。肥胖还会影响胰腺的外观,导致脂肪沉积,使胰腺看起来更黑。最后,胰腺萎缩在老年人中也很常见;这可能是疾病的迹象,或者只是老年人的正常变异。

图 5。轴面胰腺特写。关键的标志包括柔软的叶状结构和黑色的胰管。

一步一步地追踪胰腺

我通常认为最容易找到胰腺体,因为它的纹理和位置与众不同。我先追踪这个结构,然后上下追踪。

胰腺往往包裹在几个血管周围,包括主动脉、腔静脉和肾动脉/静脉。这些血管通常在对比增强 CT 上显示为明亮的圆形结构(非对比 CT 这些区别几乎不可见,并且更难分割)。务必避免在分割中意外包含血管,这会给测量带来偏差。

最后,当胰腺的头部和尾部接触附近的器官时,很难将它们分开。我喜欢使用的一个技巧是在冠状面上分割 4-5 个明显的切片,然后以此作为轴向分割的指导。这使得找到胰腺器官的“角落”变得容易。

完成后,一定要再次检查你的工作。我最常犯的错误是不小心跳过了一两片。

图 6。在轴面(左)、矢状面(中)和冠状面(右)完成胰腺分割。使用 ITK 快照,这个分割花了我大约 20 分钟

结论

像其他事情一样,细分是一个学习过程(有点像艺术形式)。在 我们的论文 中,我们发现当多个示踪剂勾画出同一个胰腺时,它们的一致性只有 80%左右,所以可以预料你的工作可能并不完美。

我喜欢告诉学生的一件事是,当你不确定的时候,就做你最好的猜测。你可能比你意识到的更准确!

如何选择数据拆分方法

原文:https://towardsdatascience.com/how-to-select-a-data-splitting-method-4cf6bc6991da?source=collection_archive---------12-----------------------

不同数据拆分方法的优缺点及其背后的原因。

班农·莫里西在 Unsplash 拍摄的照片

S 分离你现有的数据是有效训练和评估你的模型的一项重要任务。在这里,我将讨论 scikit-learn 中不同的数据分离技术,选择特定的方法,以及一些常见的陷阱。

本文包含供您使用的易用代码块和供参考的快速摘要。 **** 请随意将这篇文章加入书签以备后用。****

当你第一次学习数据科学时,拆分你的数据是一项次要的任务。

为什么您应该只使用部分数据?让我的模型学习更多的数据不是会产生更好的结果吗?

虽然人们普遍认为,在构建预测模型时,更多的数据会带来更好的模型,但考虑如何使用您的模型也很重要。

在将模型投入使用之前,测试模型在开发过程中是必不可少的。不过,你必须只处理可用的数据,这意味着留出一些数据作为你的“真实”数据。

但是调查你真实的“现实生活”数据是至关重要的。这个问题的答案决定了您应该如何分离您的数据。

列车试分裂

在最简单的数据分离形式中,您随机抽取一部分数据,将其放在一边供以后测试。

很简单,但是停下来想想这些假设。

  1. 该方法假设数据来自同一分布。例如,假设您有逐年变化的数据。假设您主要从最近一年的数据中取样(甚至可能是由于随机选择而偶然取样)。在这种情况下,您的模型可能无法有效处理今年的预测。
  2. 你有足够的数据使你的数据集具有代表性。如果您有来自相同分布的数据,但只有 100 个实例,选择 10%的数据作为测试集可能会提供不准确的结果。如果这 10 个数据点来自数据中最异常的区域,那么模型的性能会更差。当您有更多的数据实例时,这种情况不太可能发生。
  3. 对于分类问题,是否需要考虑每个类的份额?假设您有一个高度倾斜的分类问题(根据我的经验,通常都是这样)。在这种情况下,您可能需要考虑对数据集进行分层。这一点几乎落入前一点,测试集可能太小,但在这种情况下,它对于您试图预测的一个类来说太小了。

如果您想要执行内部交叉验证,这种拆分方法是完美的。将数据分为训练和测试,并在训练模型时应用交叉验证方法。对于来自同一分布的足够数据,这种方法是可行的

对中大型数据集使用 train_test_split,数据来自同一个分布

import numpy as np
from sklearn.model_selection import train_test_split# Update with your data
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]])
y = np.array([1, 2, 3, 4, 5])X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=10)###########################################
#### Add the code for your model here #####
###########################################

训练测试分割的一个缺点是,当您进行分割时,有一个决定,即您的测试集中的数据将始终是您的测试数据。

这有几个缺点。

  1. 在训练时,你从不在你的模型中包含测试数据。在您的测试数据中可能有一些实例会使您的模型更加健壮。
  2. 测试数据是固定的。最后,还有一个微妙的问题,就是过度适应这个测试集。虽然这不像过度训练神经网络来完美地学习数据那样明确,但这种过度拟合仍然是一个问题。一旦这些数据固定下来,您所执行的实验将根据这个测试集进行重复测试。你要寻找在这个场景中表现最好的模型。但是考虑一下预测建模的原始问题。你不知道未来的数据会怎样。通过对固定的测试集进行重复测试,您正在做一些在真实场景中不可能完成的事情。

KFold

作为训练-测试分割的替代方法,K-fold 提供了一种机制,可以将数据集中的所有数据点同时用作训练数据和测试数据。

Kfolds 将数据集分成多组零重叠的索引,从数据集中随机抽取数据集。

这种方法优于以前的训练测试分割,因为每个数据点都可以是模型的一部分和测试集中的一部分。

然而,这意味着一些事情。

  1. 您将在每个训练数据集上构建多个模型,并在每个测试数据集上进行测试。虽然这对于小数据集来说没问题,但是当模型很大,数据集很大时,事情很快变得昂贵。
  2. 测试之间的性能有所不同。这种性能上的变化是一件好事。您可以计算关于您的表现的统计数据(即,您可以从多次评估中获得标准偏差和平均值)。您还可以更好地了解您的模型在不同场景下的行为。
  3. 通常,当使用这种类型的数据分段时,每个测试的平均值给出了一个模型在真实环境中如何表现的更加可靠的解释。外部交叉验证以这种方式创建多个模型,报告所有折叠的平均性能,然后基于所有数据制作最后一个模型。这个最终模型得益于所有数据的使用。但是,在有额外数据之前,无法对其进行测试。因此,在这种情况下,模型性能的平均值被用作该模型的性能。

当您的数据来自同一个分布 时,将 KFold 用于中小型数据集

import numpy as np
from sklearn.model_selection import KFold# Update with your data
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]])
y = np.array([1, 2, 3, 4, 5])KF = KFold(n_splits=5)
for train_index, test_index in KF.split(X):
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index] ###########################################
    #### Add the code for your model here #####
    ###########################################

时间序列分割

前面的两种方法都认为你所拥有的数据是可以随机抽样的。然而,在时间序列数据中,你不能随机抽样数据。最重要的原因是,没有现实生活中的场景可以用未来的数据训练一个模型来预测过去。

相反,你可以通过时间来分离数据。例如,获取一个数据点之前的所有数据,然后在下一个数据点上测试它,可以确保没有数据泄漏。从这个意义上说,漏损就是用未来的数据来预测以前的数据。

这种分割方法是三种方法中唯一一种考虑分布随时间变化的方法。因此,当您有随时间变化的数据时,可以使用它。

对于时间序列数据或数据分布随时间变化时,使用 TimeSeriesSplit。

import numpy as np
from sklearn.model_selection import TimeSeriesSplit# Update with your data
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]])
y = np.array([1, 2, 3, 4, 5])time_series_cv = TimeSeriesSplit(gap=0, max_train_size=None, n_splits=5, test_size=None)for train_index, test_index in time_series_cv.split(X):
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]###########################################
#### Add the code for your model here #####
###########################################

总结

建立模型很有趣。但是,试图提高模型的性能可能是一项无止境的任务。虽然您可能在一组数据上有出色的表现,但考虑如何在现实世界中使用您的模型是否至关重要。不同的拆分方式服务于不同的目的,所以要相应选择。

记住关注目标问题,而不仅仅是某个测试集的最高性能。

如果你有兴趣阅读关于新颖的数据科学工具和理解机器学习算法的文章,可以考虑在 Medium 上关注我。

如果你对我的写作感兴趣,想直接支持我,请通过以下链接订阅。这个链接确保我会收到你的会员费的一部分。

https://zjwarnes.medium.com/membership

如何为您的数据科学问题选择初始模型

原文:https://towardsdatascience.com/how-to-select-an-initial-model-for-your-data-science-problem-77f7b811bd0?source=collection_archive---------23-----------------------

为自己节省一些时间和麻烦,从简单开始。

塞萨尔·卡利瓦里诺·阿拉贡在 Unsplash 上拍照

这篇文章是为那些试图决定用什么模型来解决问题的新的或者有抱负的数据科学家而写的。

这篇文章不会讨论数据争论。希望这是数据科学家的主要工作。我假设你已经准备好了一些数据,你想看看如何做一些预测。

简单模型

有许多型号可供选择,而且似乎有无穷无尽的变种。

将回归模型转换成分类模型通常只需要很小的改动,反之亦然。幸运的是,标准的 python 监督学习包已经为您完成了这项工作。所以你只需要选择你想要的选项。

有许多型号可供选择:

  • 决策树
  • 支持向量机(SVM)
  • 朴素贝叶斯
  • k-最近邻
  • 神经网络
  • 梯度推进
  • 随机森林

这个清单可以一直列下去,但是可以考虑从两个中的一个开始。

线性回归&逻辑回归

照片由 iMattSmartUnsplash 上拍摄

是的,像 xgboost,BERT 和 GPT-3 这样的花哨模型是存在的,但从这两个开始。

: logistic 回归有一个不太合适的名字。该模型用于分类,但由于历史原因,该名称仍然存在。

我建议将名称改为线性分类这样简单的名称,以消除这种混淆。但是,我在这个行业还没有那样的影响力。

线性回归

**from** **sklearn.linear_model** **import** LinearRegression
**import** **numpy** **as** **np**X = np.array([[2, 3], [5, 6], [8,9], [10, 11]])
y = np.dot(X, np.array([1, 2])) + 1
reg = LinearRegression().fit(X, y)
reg.score(X, y)

逻辑回归

**from** **sklearn.linear_model** **import** LogisticRegression
**from** **sklearn.datasets** **import** load_breast_cancer
X, y = load_breast_cancer(return_X_y=**True**)
clf = LogisticRegression(solver='liblinear', random_state=10).fit(X, y)
clf.score(X,y)

为什么是这些型号?

为什么要从这些简单的模型开始呢?因为有可能,你的问题不需要什么花哨。

打破一些深度学习模型,花费数百美元在 AWS 费用上,只获得轻微的准确性提升,这是不值得的。

这两个模型已经被研究了几十年,是机器学习中最广为人知的模型之一。

它们很容易解释。两个模型都是线性的,所以它们的输入转化为输出的方式可以用手工计算。

给自己省点头疼。

即使你是一个经验丰富的数据科学家,你也应该知道这些模型在你的问题上的表现,主要是因为它们实现和测试是如此的不费力。

我为此感到内疚。我以前曾一头扎进去,建立过复杂的模型。考虑到我正在使用的 xgboost 型号总体上更胜一筹,所以它应该是我的起始型号。却发现线性回归模型的表现只有几个百分点。使用线性回归是因为它更简单,更容易理解。

这里有自我的因素在起作用。

塞巴斯蒂安·赫尔曼Unsplash 上拍摄的照片

你可能想表明你理解这些复杂的模型以及如何使用它们。但有时设置、培训和维护它们并不实际。一个模型可以用,并不意味着就应该用这个模型。

不要浪费你的时间。足够好并被使用的东西总是比复杂但没人使用或理解的东西更好。

所以希望,现在你从简单的开始,从这些模型中的一个开始。

第一个问题

我的问题是分类问题还是回归问题?

你的问题是回归问题吗?

你想预测一个连续的输出吗?

线性回归(作者供图)

像房子、产品或股票的价格?回归。
某样东西会持续多久,比如飞行持续时间、制造时间,或者用户在你博客上停留的时间?回归。

从线性回归开始。画出你的线性回归图并评估这个模型。

在这里保存性能。如果对你的问题来说已经足够好了,那就继续吧。否则,现在你可以开始尝试其他模式。

你的问题是分类问题吗?

您是在尝试预测二进制输出还是多个唯一且离散的输出?

逻辑回归(作者照片)

你是想确定某人是否会从你的商店买东西或者赢得一场游戏吗?分类。

一个是或否回答了你的问题吗?分类。

从逻辑回归开始,绘制你的数据或数据子集的散点图,并给类着色。也许已经有了明确的模式。

同样,评估这个模型,如果你仍然需要改进你的表现,把它作为你的基线。但是从这里开始。

结论

很可能,那些读过这篇文章的人会发现自己处于类似的情况,选择使用什么模型。然后从你读过的一篇论文中决定你的问题对于这个新模型是完美的。结果,花费数小时对这个复杂的模型进行微调,最终只有一个更简单的模型胜出。

不一定是性能,而是因为它们简单易懂

给自己留点时间和精力。就从线性回归和逻辑回归开始吧。

如果你有兴趣阅读关于新颖的数据科学工具和理解机器学习算法的文章,可以考虑在 Medium 上关注我。

如果你对我的写作感兴趣,想直接支持我,请通过以下链接订阅。这个链接确保我会收到你的会员费的一部分。

https://zjwarnes.medium.com/membership

如何在不同的升压算法之间进行选择

原文:https://towardsdatascience.com/how-to-select-between-boosting-algorithm-e8d1b15924f7?source=collection_archive---------13-----------------------

AdaBoost、梯度增强、XGBoost、Light Gbm、CatBoost

绿色变色龙Unsplash 上的照片

几年前我第一次听说 boosting 算法。当时我还在学校读本科,使用线性回归/逻辑回归作为机器学习的主要算法。那时候,boosting 听起来像是一个非常困难和复杂的算法,这让我害怕!

这些年来,我逐渐学会了不同的 boosting 算法。我意识到这其实并不是一个很难学习和应用的概念。当然,如果你想对算法的数学和编码了如指掌,这将是困难和巨大的努力。但是,如果你只是想用算法,知道什么时候用,我们只需要知道特点,了解不同 boosting 算法的区别

本文将重点介绍不同升压算法的概述。我将向您展示主要思想、示例代码、如何使用它们以及每种 boosting 方法的优缺点。然而,我不会深入讨论每一种提升算法的细节。

Boosting 是一种顺序集成学习技术,其中不同的模型被迭代添加,以提高整体模型性能。

作者图片:Boosting 算法的演变

如上图所示,我将按照发布时间的顺序介绍 5 种提升方法。Light Gbm 和 CatBoost 是在相似的时间推出的,所以我们不能说一个是另一个的改进版本。

我们正在使用的数据

这次我将使用来自 UCI 的成人工资预测数据集进行演示。该数据集的主要目标是预测此人的年收入是否超过 5 万英镑。这是一个分类问题,它包含相当多的分类变量,如教育背景、婚姻状况和职业。

我将在 salary 数据集上展示每个 boosting 算法的示例代码。对于前 4 种方法,我已经使用标签编码将文本列转换成整数。标签编码将文本类别转换为 0,1,2,3…我使用这种方法是因为一个热编码(转换为 0/1)会创建太多的列。我将使用最后一个方法 CatBoost 的原始文本列,因为这是算法内置功能的一部分。

此外,为了查看运行时性能,我将所有算法标准化为运行 100 次迭代来比较运行时。

adaboost 算法

AdaBoost 是自适应增强的简称。我们称之为自适应,因为该算法利用了来自先前模型的未分类案例,并创建了一个新的加权数据样本,其中未分类案例具有更大的权重。这样,新添加的模型在解决先前模型的“错误”时应该更具适应性。

AdaBoost 是最早开发的 boosting 算法之一。现在很少使用它,但它是大多数 boosting 算法的基础。

由西拉科恩——自己的作品,CC BY-SA 4.0,https://commons.wikimedia.org/w/index.php?curid=85888769

from sklearn.ensemble import AdaBoostClassifier
clf = AdaBoostClassifier(n_estimators=100,random_state=1)
clf.fit(X_train, Y_train)
predicted=clf.predict(X_test)
print('Accuracy of the result is:')
print(np.mean(predicted==Y_test))#Accuracy: 0.8659023441498618
#Runtime: 0.9506289958953857

梯度推进

与 AdaBoost 相比,梯度提升不惩罚漏分类情况,而是使用损失函数。损失函数可以是回归的平均误差或分类问题的对数损失。此外,梯度提升算法使用梯度下降法来不断最小化损失函数,以找到最优点

梯度提升方法理论上比 AdaBoost 执行得更好。然而,它更容易出现过拟合问题,并且梯度增强的运行时间更长。可以设置早期停止条件,以减轻过拟合并减少运行时间。

通过使用 R 的动手机器学习进行梯度提升

from sklearn.ensemble import GradientBoostingClassifier
clf = GradientBoostingClassifier(n_estimators=100,random_state=0)
clf.fit(X_train, Y_train)
predicted=clf.predict(X_test)
print('Accuracy of the result is:')
print(np.mean(predicted==Y_test))#Accuracy: 0.8646739686764254
#Runtime: 1.6930928230285645

XGBoost

XGBoost 代表极限梯度提升,它指的是工程师们推动梯度提升方法的计算资源极限的目标。

XGBoost 是梯度增强方法的增强版本。首先,它通过使用正则化改进过拟合。其次,通过使用并行运行优化排序,提高了运行速度。最后,使用决策树的最大深度作为参数来修剪该树,这显著减少了运行时间。

from xgboost import XGBClassifier
clf = XGBClassifier(n_estimators=100,random_state=0)
clf.fit(X_train, Y_train)
predicted=clf.predict(X_test)
print('Accuracy of the result is:')
print(np.mean(predicted==Y_test))#Accuracy: 0.8710205752891801
#Runtime: 0.7643740177154541

轻型 GBM

顾名思义, Light Gbm 进一步通过让计算工作量‘轻’来提高程序的运行时间。但是,与其他算法相比,它仍然可以保持相同或更高的模型性能。

Light Gbm 主要通过两种方式优化运行速度和准确性。

  1. 它采用基于直方图的算法,将连续变量拆分到不同的桶中(而不是单独排序)。这大大提高了运行时间。
  2. 它使用逐叶树生长方法,而不是逐层树生长方法(被大多数其他基于决策树的方法使用)。从下面的图片可以看出,它允许损失较高的叶片部分继续生长(最佳拟合切割),从而将整体损失函数降至最低。

来自轻型 gbm 文档的水平方向树生长与叶方向树生长

import lightgbm as lgb
clf = lgb.LGBMClassifier()
clf.fit(X=X_train, y=Y_train,feature_name=list(X_train.columns),categorical_feature=list(df_cat.columns))
predicted=clf.predict(X_test)
print('Accuracy of the result is:')
print(np.mean(predicted==Y_test))#Accuracy: 0.871839492271471
#Runtime: 0.15074729919433594

使用 Light Gbm 的另一个好处是,它有 100 多个参数可以根据数据集和问题进行调优和调整。这里一个非常有用的特性是,您可以在 fit 函数中定义分类特性列表(您需要先将类别转换为整数)。

CatBoost

最后,CatBoost 代表分类推进。它有一个很大的特点就是自动处理分类变量,而不需要将它们转换成数字

CatBoost 是 5 种 boosting 算法中最新开发的,但非常接近轻型 Gbm。分类变量越多,性能越好。

from catboost import CatBoostClassifier
clf=CatBoostClassifier(iterations=100)
clf.fit(X_train, Y_train,cat_features=list(df_cat.columns))
predicted=clf.predict(X_test)
print('Accuracy of the result is:')
print(np.mean(predicted==Y_test))#Accuracy: 0.8731702323676938
#Runtime: 0.5496680736541748

整体性能比较

结果对照表

不同的增强方法在准确性方面的表现相当一致。CatBoost 具有最高的精度,但差异领先是最小的。就运行时性能而言,Light Gbm 具有最快的执行速度和最高的准确率。

梯度增强在运行时间方面表现不佳,并且它具有最低的精度(略低于 AdaBoost)。从这次演习来看,轻型 Gbm 似乎是冠军。

建议

就个人而言,我会推荐使用轻型 GBM 和 CatBoost ,因为它们的性能/速度优势以及大量用于模型调整的参数

当预测器中有许多分类变量时,CatBoost 表现更好。分类变量包括文本、音频和图像。它还为您节省了转换分类变量的工作量。

轻型 GBM 的模型训练速度比 CatBoost 快。同时也不牺牲精度水平。当您有一个大型数据集和相对较少的分类预测器时,您可以选择使用 LightGBM

潜在的未来工作

  1. 比较是在 30k 行数据上进行的。数据集可以有偏差,大小也不是很大。您可以通过使用 make_classification 包来尝试更大的分类数据集
  2. 这个练习只是为了分类,你也可以尝试回归的一面
  3. 在评估模型性能方面,仅使用准确性和运行时间,其他分类评估如 ROC 评分、F1 评分、召回率、精确度也可用于查看全貌
  4. 建模最耗时的部分是超参数调整。当前的练习或比较不包括超参数调整部分。我会有一篇新的文章,请继续关注。

最后

这是对不同类型的升压方法的非常基本的概述。你可以阅读每种方法的更多内容,也许可以在几个数据集上尝试模型以进一步理解它。

另外,boosting 只是集成学习算法中的一种。如果你有兴趣了解更多关于 ensembled learning 的内容,可以参考我下面的文章:

感谢阅读!希望这篇文章能帮到你。

如果你对你想让我介绍的某个特定的助推方法或主题感兴趣,请在评论中提出来!

如何根据列值从 Pandas 数据框架中选择行

原文:https://towardsdatascience.com/how-to-select-rows-from-pandas-dataframe-based-on-column-values-d3f5da421e93?source=collection_archive---------1-----------------------

探索如何根据 pandas 数据框架中的条件选择行

Teslariu MihaiUnsplash 上拍摄的照片

介绍

从数据帧中选择行可能是使用 pandas 最常见的任务之一。在今天的文章中,我们将讨论如何对列值为:

  • 等于标量/字符串
  • 不等于标量/字符串
  • 大于或小于一个标量
  • 包含特定(子)字符串
  • 可迭代的成员(例如列表)

此外,我们将讨论如何将多个条件组合在一起。

在开始讨论从 pandas 数据帧中选择行的不同方法之前,首先让我们创建一个示例数据帧来演示一些概念,该示例数据帧将贯穿本文。

import numpy as npdf = pd.DataFrame(
 [
  (73, 15, 55, 33, 'foo'),
  (63, 64, 11, 11, 'bar'),
  (56, 72, 57, 55, 'foo'),
 ],
 columns=['A', 'B', 'C', 'D', 'E'],
)print(df)#     A   B   C   D    E
# 0  73  15  55  33  foo
# 1  63  64  11  11  bar
# 2  56  72  57  55  foo

在熊猫中选择行

在下面几节中,我们将讨论并展示如何基于各种可能的条件从数据帧中选择特定的行。

选择列值等于标量或字符串的行

假设我们只想选择特定列中有一个特定值的行。我们可以通过简单地使用loc[]属性来做到这一点:

>>> df.loc[df['B'] == 64]
    A   B   C   D    E
1  63  64  11  11  bar

我们甚至可以省略loc并在索引熊猫数据帧时提供布尔条件,如下所示:

>>> df[df['B'] == 64]
    A   B   C   D    E
1  63  64  11  11  bar

注意,除了df['B'],您还可以使用df.B来引用列B。例如,下面的语句与上面的等价。

>>> df[df.B == 64]

在 Python 的上下文中,将这样的布尔条件命名为mask是一种常见的做法,然后我们在索引 DataFrame 时将它传递给 data frame。

>>> mask = df.B == 64
>>> df[mask]
    A   B   C   D    E
1  63  64  11  11  bar

在介绍了几种基于列值等于标量来选择行的可能方法之后,我们应该强调的是loc[]才是正确的选择。这仅仅是因为**df[mask]** 总是会分派到 **df.loc[mask]** ,这意味着直接使用 **loc** 会稍微快一点

选择列值不等于标量的行

接下来,您可能希望只选择特定列中的值不等于标量的行的子集。为此,我们只需遵循与之前相同的约定:

>>> df.loc[df['B'] != 64]
    A   B   C   D    E
0  73  15  55  33  foo
2  56  72  57  55  foo

选择行显示大于或小于标量的列值

这是一个与前一个非常相似的用例。在这种情况下,我们只需要使用所需的操作符来执行比较。举个例子,

>>> df.loc[df['B'] >= 64]
    A   B   C   D    E
1  63  64  11  11  bar
2  56  72  57  55  foo

选择列值包含字符串的行

最常见的一个用例是,当您需要过滤数据帧时,只保留特定列中包含特定(子)字符串的行。

和前面的用例一样,我们可以使用loc来实现:

>>> df.loc[df['E'].str.contains('oo')]
    A   B   C   D    E
0  73  15  55  33  foo
2  56  72  57  55  foo

选择列值在可迭代中的行

现在让我们假设我们只想选择那些特定列中的值包含在列表中的行。为此,我们只需使用如下所示的isin()

>>> df.loc[df['B'].isin([64, 15])]
    A   B   C   D    E
0  73  15  55  33  foo
1  63  64  11  11  bar

选择列值不在 iterable 中的行

现在,如果你想选择值不在可迭代的行(例如,一个列表),那么你可以简单地使用否定字符~:

>>> df.loc[~df['B'].isin([64, 15])]
    A   B   C   D    E
2  56  72  57  55  foo

多重条件

当从 pandas 数据框架中选择行时,您可能希望或必须将多个条件组合在一起。

为此,我们需要使用&操作符

>>> df.loc[(df['A'] >= 59) & (df['E'].isin(['foo', 'boo']))]
    A   B   C   D    E
0  73  15  55  33  foo

最后的想法

在今天的文章中,我们讨论了如何对 pandas 数据帧执行行选择,并展示了具体的用例及示例。

在大部分章节中,我们基本上使用了标签索引,这是通过loc实现的。请注意,pandas 有一个名为iloc的附加属性,通常用于执行位置索引。理解这两者之间的区别是很重要的,我建议你阅读下面的文章,它详细解释了每一个的作用。

[## 熊猫中的 loc 与 iloc

towardsdatascience.com](/loc-vs-iloc-in-pandas-92fc125ed8eb)

如何使用 Python 发送和接收自动电子邮件

原文:https://towardsdatascience.com/how-to-send-and-receive-automated-emails-using-python-a5c711c7a35c?source=collection_archive---------13-----------------------

使用令人眼花缭乱的仪表板创建自动化的电子邮件管道

斯蒂芬·菲利普斯-Hostreviews.co.uk 在 Unsplash 上的照片

介绍

在我们的公司和非公司生活中,我们每天都会收发大量的电子邮件。说实话,这些交易中的很大一部分确实可以自动化。也许我们都经历过人生中具有里程碑意义的时刻,那就是我们一天中的大部分时间都在给许多人发送差不多相同的电子邮件。嗯,不一定非要那样。使用 Python,您实际上可以设置和部署一个自动化的电子邮件管道来接收电子邮件,然后根据前者的内容发送电子邮件。换句话说,当你在工作或家里处理更有影响力的任务时,你可以让自动化发挥作用。

完全没有必要精通技术,我们要做的事情很简单,我们每个人都可以在短时间内完成。在本教程之后,您将学习如何自动接收电子邮件,使用内容和附件生成图表,然后最终向许多收件人发送带有令人眼花缭乱的仪表板的电子邮件。

具体来说,在本教程中,我们将自动执行以下操作:

  • 接收电子邮件
  • 解析电子邮件内容和附件
  • 生成数据可视化
  • 向多个收件人发送电子邮件

接收电子邮件

虽然本教程中使用的技术可以应用于任何使用标准 IMAP 协议的电子邮件服务器,但一些服务器(如 Gmail)的使用可能会有所不同。如果您确实在使用 Gmail,请确保您在 Google 帐户中启用了不太安全的应用程序选项,如下所示:

Gmail 不太安全的应用程序授权-作者图片。

继续启动 Anaconda 或您选择的任何其他 Python IDE,并运行下面的代码片段来连接到您的电子邮件帐户并下载您收件箱中的所有内容。

此外,请注意,存储您的用户凭证的更安全的方法是将它们保存在一个配置文件中,然后在您的代码中将它们作为参数调用。

解析电子邮件内容和附件

现在让我们假设您正在等待一封带有 Microsoft Excel 附件的电子邮件,其中包含许多学生的考试结果。您的目标是使用“考试结果”主题自动搜索该电子邮件。一旦找到它,您将需要提取文件并保存到您的本地目录。

请注意,如果您想要搜索特定的发件人而不是电子邮件主题,请将上面代码片段的第 7 行替换为以下内容:

if 'sender_email@gmail.com' in email_content['From']:

生成数据可视化

现在您已经下载了电子邮件附件,您将希望根据附件的内容生成文本和图表。因为在我们的例子中,文件是一个 Excel 电子表格,我们将使用 Pandas 将其转换成一个数据框。

电子邮件附件数据框-作者图片。

我们现在的目标是找到每次考试的班级平均分,然后创建一个图表,单独显示每个学生的分数。为此,我们将使用如下所示的 Plotly 来生成包含考试结果的自定义折线图、条形图和直方图。在继续下一步之前,请确保您可以通过在 Anaconda 提示符下键入以下命令,使用‘python-kaleido’库将图表保存为图像:

conda install -c plotly python-kaleido

上面的片段将为每个学生创建以下三个图表:

考试成绩图表-作者图片。

向多个收件人发送电子邮件

现在我们已经生成了定制的图表,下一步是将相应的图表和考试结果发送给每个学生。下面的代码片段是前面代码片段中 for 循环的延续。

结果

这就是你自己的电子邮件仪表板,通过自动化管道毫不费力地发送给许多收件人。这只是这种方法的扩展功能的一个小演示,实际上您可以通过发送更丰富的内容来扩展它,包括但不限于文本、图像、音频和其他 HTML 内容。

电子邮件仪表板—按作者分类的图像。

如果您想了解更多关于数据可视化和 Python 的知识,请随时查看以下(附属链接)课程:

使用 Streamlit 开发 Web 应用程序:

https://www.amazon.com/Web-Application-Development-Streamlit-Applications/dp/1484281101?&linkCode=ll1&tag=mkhorasani09-20&linkId=a0cb2bc17df598006fd9029c58792a6b&language=en_US&ref_=as_li_ss_tl

使用 Python 实现数据可视化:

https://www.coursera.org/learn/python-for-data-visualization?irclickid=xgMQ4KWb%3AxyIWO7Uo7Vva0OcUkGQgW2aEwvr1c0&irgwc=1&utm_medium=partners&utm_source=impact&utm_campaign=3308031&utm_content=b2c

面向所有人的 Python 专业化:

https://www.coursera.org/specializations/python?irclickid=xgMQ4KWb%3AxyIWO7Uo7Vva0OcUkGQgW16Ewvr1c0&irgwc=1&utm_medium=partners&utm_source=impact&utm_campaign=3308031&utm_content=b2c

GitHub 资源库:

https://github.com/mkhorasani/python_automated_email

☕喜欢这个教程?这里有空给我捐一杯咖啡

新到中?您可以在此订阅并解锁无限文章

如何使用 Python 发送电子邮件

原文:https://towardsdatascience.com/how-to-send-emails-using-python-3cd7934002f0?source=collection_archive---------17-----------------------

向您展示使用 Python 与人交流的多种方式

来源:https://unsplash.com/photos/3Mhgvrk4tjM

在本教程中,我将向您展示使用 Python 发送电子邮件的多种方式。这在许多项目或情况下非常有用,在这些项目或情况下,您需要以快速、简单和安全的方式与不同的人共享任何类型的信息。

传统方式:SMTPLIB

当使用 Python 发送电子邮件时,这个库是最受欢迎的。它创建了一个简单邮件传输协议(SMTP)会话对象,可用于向任何 internet 机器发送邮件。

在使用此模块发送电子邮件之前,您需要更改电子邮件帐户的设置。事实上,你需要在作为发件人的电子邮件中“启用对不太安全的应用程序的访问”。更多信息请点击这里:https://support . Google . com/accounts/answer/6010255 # zippy = % 2c if-less-secure-app-access-on-for-your-account

一旦这样做了,这里的代码将允许你立刻发送一封非常简单的电子邮件。

这传递了一个非常简单的信息。当然,您可以添加主题、附件等。但是我将要展示的另一种方法也可以用更简单的方式实现。

另一种选择:Yagmail

Yagmail 是一个 gmail 客户端,旨在使发送电子邮件变得更加简单。

我个人喜欢它,因为它非常容易给邮件添加内容(附件、主题、链接等)。)而我发现在使用 SMTPLIB 时并不那么直接。

下面是发送包含主题和附加图像的电子邮件的代码。还是那句话,超级简单!

在第 7 行中,‘test’实际上是邮件的主题,而在内容中,您可以添加消息和附件(图像、word 文档、音频文件等)。)超级轻松。

更具伸缩性的方式:使用 API

电子邮件服务现在已经存在,它可以用很少几行代码帮你发送尽可能多的电子邮件。

使用服务的好处是,它允许您跟踪您发送的内容。你可以很容易地知道是否收到电子邮件,何时何地发送了多少封。这种类型的信息并不总是必要的,但是随着项目的发展,您对这种类型的信息的需求也会增加。

这种服务可以是免费的。例如,如果你使用 Mailgun(https://www.mailgun.com/),你每月可以免费发送多达 5000 封电子邮件。

此类服务的唯一问题是,你需要创建一个账户,如果你打算发送大量电子邮件,你最终可能需要花钱。

一旦你有了一个帐户,这里是你如何使用 Mailgun 和 Python 发送电子邮件。您自己的个人功能(具有正确的凭证)将很容易在您的帐户中使用。

我希望这能对你正在做的任何项目有所帮助,如果你有任何问题,请不要犹豫。

谢谢!

如何测序人类基因组

原文:https://towardsdatascience.com/how-to-sequence-a-human-genome-a-bioinformatics-approach-ae64481cec7b?source=collection_archive---------37-----------------------

实践教程

通过阅读《三只小猪》和穿越一座城市

人类基因组包含超过 30 亿个碱基对。从上下文来看,如果你每秒钟检测一个碱基对,你需要花 94 年来检测它们。因此,毫不奇怪,1990 年,人类基因组计划就是为了完成这一任务而创立的,也就是说,对整个人类基因组进行测序。

像科学中的许多事情一样,这个项目变成了一场竞赛。在这种情况下,在 Celera Genomics 和 IHGSC 之间。

DNA 基因分型和测序。信用:国家癌症研究所(Unsplash)

也许有些令人不满意,两个团队在 2001 年同时发表了完整的基因组。这两个阵营采用的方法各不相同,在本文中,我们将重点介绍 Celera 的三步法:

  1. 将整个基因组切割成大约 150,000 个碱基对长的更易管理的片段。
  2. 将这些片段分别插入克隆的人造细菌染色体中,然后通过“指纹”向科学家展示它们重叠的地方。
  3. 然后,这些重叠被用作向导,向科学家展示顺序,然后从那里,整个基因组被重建。

前两步非常简单,事实上,DNA 的分离和转染是工业上经常做的事情,例如在重组蛋白生产中。第三步要复杂得多,乍一看,可能会让人不知所措。

这种做事方式几乎就像你拿了很多本三只小猪(或者任何一个词汇相当局限于一小组单词的故事),把它们放进一个碎纸机,把纸屑像绳子一样混合在一起,然后试图重建至少一个完美的三只小猪的副本。

信用:马蒂厄·佩蒂亚尔(Unsplash)

除非你对拼图游戏有秘密的嗜好,否则这看起来非常没有希望,事实上也确实如此(特别是当你的《三只小猪》有 30 亿个字符长的时候)。

但是,人类无法有效完成的机械任务,计算机肯定可以。这就是生物信息学的用武之地。生物信息学就像生物学和计算机的私生子。它利用计算机以逻辑方式处理大量数据的能力来解决生物学问题。人类基因组测序可以被视为一个非同寻常的生物学问题,几乎从定义上来说,它包含了大量的数据,这使得使用生物信息学方法来解决它变得非常完美。

回到三只小猪的比喻,因为粉碎的过程是随机的,所以不可能有很多碎片看起来完全一样。例如,在一个副本中,句子“我会一鼓作气,吹倒你的房子”可能会被砍成

"我会吹气,我会吹气,我会吹倒你的房子"。

但是,在另一个副本中,它可能是

"我会发怒,我会砰的一声,我会把你的房子夷为平地"。

如果我们对英语没有任何概念,如果呈现给我们第一批片段,我们就不知道该按什么顺序排列,因为就我们所知,一个顺序看起来和下一个一样好。我们会很容易地把第一组纸条拼凑成正确的措辞“我会吹,我会吹你,我会吹倒我们的房子”。

话虽如此,如果有第二套,我们可能会注意到有一些重叠之间的“我会 huff an”和“我会 huff,我会 pu”和一些更多的重叠之间的“我会 huff,我会 pu”和“d 我会 puff,我会吹你”。因此,我们可能会得出这样的结论:“我会发脾气”和“我会吹气,我会吹你”紧挨着,提供句子“我会发脾气,我会吹气,我会吹你”,这是朝着正确方向迈出的一步。

这个过程似乎有些矫枉过正。为什么你要收集一架子的三只小猪,把每一只都放进碎纸机里,当你可以读其中一只的时候,还要煞费苦心地寻找重叠之处?当谈到基因组时,生物信息学家没有能力像阅读一本书那样从左到右阅读。因此,他们不得不

  1. 将基因组的多个副本分割成更小的“读数”,这不可避免地会变得杂乱无章。
  2. 找到这些读数重叠的地方,并利用这些信息构建整个基因组。

我们先考虑一个理想情况。比方说,我们有一个“天文”这个词,它可以很方便地分成一堆三个字母:“ast”、“str”、“tro”、“ron”、“ono”、“omi”、“mic”、“ica”、“cal”。因为每对连续的三聚体共有 2 个字符(即一个三聚体的“后缀”等于紧随其后的三聚体的“前缀”)。

因此,我们可以从第一个三聚体开始,添加每个后续三聚体的最后一个字符,得到“ast-r-o-n-o-m-i-c-a-l”。如果我们使用四聚体,这将是正确的:

" astr" + "stro" + "tron "," rono "+" onom "+" nomi "+" omic "+" mica "+" ical " = " astr-o-n-o-m-I-c-a-l "。

或五聚体

" astro "+" stron "+" trono "+" ronom "+" onomi "+" nomic "+" omica "+" mical " = " astro-n-o-m-I-c-a-l "。

这其中的两个主要问题是

  1. 它假设所有的读取都是按照正确的顺序进行的。例如,如果我们有“astro”、“trono”、“nomic”、“onomi”、“omica”、“stron”、“mical”、“ronom”,这就不太好了。
  2. 它假设完美覆盖——即每一个可能的 k-mer 都被转换成 k-mer。如果 k-mer 的“ronom”被省略,我们从“trono”到“onomi”,我们就会有一个缺口。

我们将讨论所有这些要点,但首先让我们考虑一个基本操作,即获取一个字符串并尝试将其分解为它的 k-mer 组合——即组成它的 k-mer 集合(例如。《天文》的三聚体构成是" ast "、" str "、" tro "、" ron "、" ono "、" omi "、" mic "、" ica "、" cal "。

def StringComposition(Text, k):
    for i in range(len(Text)-k+1):
        print(Text[i:i+k])

但是,我们也希望能够做相反的事情。也就是说,给定一个 k-mer 组合,恢复它对应的字符串。因为这仍然是一种理想化的情况,我们可以进行上面的观察,并意识到每个 k-mer 都在其之前的 k-mer 中添加一个新字母。

def StringFromGenomePath(Genome):
    k = len(Genome[0])
    string = ""
    string += Genome[0][0:k-1]
    for i in range(0, len(Genome)):
        string += Genome[i][k-1]
    return string

假设 1:所有的阅读顺序都是正确的。

现在,我们陷入疯狂和不确定之中!但在我们全面开始之前,值得注意的是,这很大程度上是基于 Pavel Pevzner 和 Philip Compeau 的 MOOC 生物信息学 II。为了更多地实践这里概述的概念,我强烈建议你去看看!

正如我们之前建立的那样,k-mers 可能不会按照你想要的顺序出现。所以我们转向重叠图的概念。所有的图都是由节点和边组成的。你可以把它想象成一个城市,各个目的地是节点,边是街道

鸣谢:Hanson Lu (Unsplash)

在这种情况下,我们的图将有条有向边,这意味着你只能沿着边所指的方向从一个节点到下一个节点,即单行道。

我们将制作所有的 k-mers 节点,并在共享前缀和后缀的节点之间绘制边。例如,如果我们有三聚体 TAATGGGATGCCATGTT,那么节点 TAA 有一条指向 AAT 的边,它有一条指向 ATG 的边…等等。因为边缘在共享的前缀和后缀之间,所以穿过它们就像穿过两个 k-mers 之间的重叠部分。

基本字符串重建路径。鸣谢:作者

但问题是,我们实际上并不知道事情是以这种特定的顺序联系在一起的,例如,ATG 目前指向 TGC 的气泡,但从技术上来说也可能指向 TGG。

重建 k-mer 就像试图在这个重叠图中找到一条路径/找到一条访问城市中每一个目的地的方法。但不是任何路径:一条哈密尔顿路径,它恰好访问每个节点一次。因为它是沿着有向边(所有的重叠)来做的,所以我们知道所有的 k-mers 都是正确的顺序。

但是,从算法上来说,很难找到哈密顿路径。这就是为什么我们也考虑德布鲁因图的原因。在这个图中,边是 k-mers,节点是构成前缀和后缀的 k-1mers。特别地,对于给定的边,它来自的节点将是前缀,它去往的节点将是后缀。因此,例如在上面的 k-mer TAATGGGATGCCATGTT 中,边 TAA 将从 TA 指向 AA,边 GAT 将从 GA 指向 AT。

为了简化事情,我们可以将具有相同 k-1 mer 的节点“粘合”在一起,合并进入和离开它们的边。

德布鲁金图。鸣谢:作者

def DeBruijn(k, Text):
    mers = {}
    for i in range(len(Text)-k+1):
        if Text[i:i+k-1] in mers:
            mers[Text[i:i+k-1]].append(Text[i+1:i+k])
        else:
            mers[Text[i:i+k-1]] = [Text[i+1:i+k]]  
    for item in mers:
        print("{} -> {}".format(item, ', '.join(mers[item])))

我们想在这个图中找到一条路径,这条路径恰好访问每条边一次(所以每个 k-mer 都被访问一次)。我们知道,如果我们沿着正确的方向沿着边走,那么所有这些 k-mers 的顺序都是正确的,因为它们必须紧挨着与它们重叠的 k-mers(由于共享前缀和后缀的节点)。这样的路径被称为欧拉路径。

欧拉循环非常类似于欧拉路径,只是它在同一个节点开始和结束。对于一个有欧拉圈的图,它必须是

  1. 强连接。即可以从每个其他节点到达每个节点。例如,如果我们的“城市”基本上是一系列没有桥梁连接的岛屿,那么它就不会是强连接的。

2。平衡。进入节点的边数(入度)必须等于离开节点的边数(出度)。换句话说,能让你到达目的地的单行道数量等于能让你离开目的地的节点数量。

在这种情况下,第一个要求几乎是隐含在这种情况下,如果你有一个字符串,你将显然能够从字符串中的一个 k-mer 到另一个。第二个也是,但是如果一个图有两个以上的节点,其中入度不是出度,那么在访问每个点之前,您将不可避免地停留在一个这样的位置。

但是一个人如何找到这样一条路呢?让我们假设你被随机放在一个欧拉图上,任务是计算出一个欧拉圈。如果事先不知道这个图表是什么样子,你的第一反应可能是开始随机地四处游荡,直到有事情发生。

将会发生的“某件事”是你到达一个节点,却无处可去,因为你已经用完了离开那个节点的所有边。但这不会在任何节点发生,因为结果是,你唯一可能被卡住的节点是你从开始的节点。在这种情况下,如果你已经沿着其他每一条边走了,那么很好——你找到了一个欧拉周期。但是,如果仍有一些未使用的边,则必须执行以下操作:

  1. 回溯到一个节点(n ),它有一些未使用的边。
  2. 从那里开始遍历图,直到你再次卡在节点 n。
  3. 沿着原始路径从节点 n 继续前进。

您可以将这种方法视为为您的循环建立一个“主干”,即最初的遍历,然后在图的其他部分不断“循环”到这个主干中。

def EulerCycleSolver(graph):
    path = []

    key = random.choice(list(graph))
    path.append(key)while len(graph[key]) != 0:
        value = random.choice(graph[key])
        graph[key].remove(value)
        key = value
        path.append(key)

    for key in path:
        if len(graph[key]) != 0:
            x = len(path) - path.index(key) - 1
            while len(graph[key]) != 0:
                value = random.choice(graph[key])
                graph[key].remove(value)
                key = value
                path.insert(-x, key)
    #path.pop() #- if want to minus last connection
    return path

然后从这一点,找到一个欧拉路径只是必须忽略最后一个连接。这是可行的,因为所有有欧拉圈的图都必须有一条欧拉路径。但是,如果一个图没有欧拉圈呢?这并不一定意味着图形没有欧拉路径(有点像所有的正方形都是矩形,但不是所有的矩形都是正方形)。

在那些小的子集情况下,图必须是“接近平衡的”。这意味着,有一个节点的进箭头比出箭头多一个,另一个节点的出箭头比进箭头多一个。

具有额外出度的那个将是起点,具有额外入度的那个将是终点。这是因为每次你进入一个节点,你需要能够离开它,但如果你有一个更多的边缘进来,你最终会卡在那个节点,这是好的,如果这是你的最后一个节点。一种相反的直觉适用于起始节点。

通过找到这两个节点,在 then 和 then 之间添加一条边,然后使用之前建立的欧拉循环算法,我们可以很容易地将此图转换为具有欧拉循环的图。

德布鲁金图中的欧拉圈。鸣谢:作者

然后将该序列拟合到字符串重构问题算法中,将返回原始字符串。但是事实证明并不是所有时候。例如,假设您有一个字符串 TAATGGGATGCCat GTT,它的三个成员是 TAA、ATT、ATG、TGG、GGG、GGA、GAT、ATG、TGC、GCC、CCA、CAT、ATG、TGT 和 GTT。虽然欧拉循环算法可以按照这个顺序将它们组合在一起,但它也可以很容易地切换 GG 和 CC,并返回 TAATGCCATGGGat gtt,因为它的三聚体组成是相同的,只是顺序略有不同——TGG、GGG、GGA 将与 TGC、GCC、CCA 进行切换。

因为这些更小的片段可以互换,我们需要考虑它们的顺序,这可以从它周围的三聚体推断出来。而不仅仅是直接围绕着它,因为正如我们所看到的,它们也被转换了。我们需要前面至少有 k 个字符的 k-mers。

这启发了成对的 De Brujin 图采用(k,d)-mers 而不是 k-mers。(k,d) mer 是一对由 d 字符分隔的两个 k-mer。例如,在上面的字符串中,第一个(3,2)将是(TAA|GGA)。条形表示两个 k-mers 之间已删除的所有内容。

就像我们可以有一个 k-mer 组合的字符串,我们也可以有一个(k,d)-mer 组合的字符串。对于上面的字符串,(3,2) mer 组成将是(TAA|GGA),(AAT|GAT),(ATG|ATG),(TGG|TGC),(GGG|GCC),(GGA|CCA),(GAT|CAT),(ATG|ATG),(TGC|TGT),(GCC|GTT)。

成对的德布鲁金图。鸣谢:作者

def PairedDeBruijn(k, Text):
    mers = {}
    for i in range(len(Text)):
        if  Text[i][0:k-1] + "|" + Text[i][k+1:2*k] in mers:
            mers[Text[i][0:k-1] + "|" + Text[i][k+1:2*k]].append(Text[i][1:k] + "|" + Text[i][k+2:2*k+1])
        else:
            mers[Text[i][0:k-1] + "|" + Text[i][k+1:2*k]] = [Text[i][1:k] + "|" + Text[i][k+2:2*k+1]]
    for item in mers:
        return mers

当我们得到一个有序的(k,k-mer 集时,我们可以像上面一样重建字符串,但是将第一个字符添加到第一个 k-mer 的末尾,然后根据 d 的值补充最后几个第二个 k-mer。

假设 2:完美覆盖

尝试处理这种假设比克服之前的事实要容易得多,即并非所有的 k 线图都是按照理想的顺序排列的。正如我们之前看到的,完美覆盖的概念是我们拥有我们想要重建的字符串中出现的每个 k-mer。

这就是为什么生物信息学家经常求助于使用“重叠群”,这是德布鲁金图中最长的可能片段,没有任何不确定性。基本上,如果你要尝试扩展这样一条道路,你需要选择 k-mer 将会带来什么。即使我们的 k-mers 具有完美的覆盖,也使用这种做法,因为有时重复会阻止存在唯一的欧拉路径(即一个图可以翻译成许多字符串)。

生成 MaximalNonBranching 路径/重叠群。鸣谢:作者

def MaximalNonBranchingPaths(graph):
    #print(graph)
    ins = {}
    for i in graph:
        for x in graph[i]:
            if x in ins:
                ins[x] += 1
            else:
                ins[x] = 1
    rejects = {}
    for x in graph:
        if x in ins and len(graph[x]) == 1 and ins[x] == 1:
           rejects[x] = graph[x]

    dones = []
    collections = []
    for x in graph:
        if x not in rejects:
            for y in graph[x]:
                path = [x, y]
                while y in rejects:
                    dones.append(y)
                    path.append(graph[y][0])
                    y = graph[y][0]
                collections.append(path)
    for y in dones:
        del rejects[y]

    while len(rejects) != 0:
        forgotten = []
        key = random.choice(list(rejects))
        forgotten.append(key)
        while key in rejects:
            value = rejects[key][0]
            forgotten.append(value)
            del rejects[key]
            key = value
        collections.append(forgotten)
    return collections

好了,让我们回顾一下我们是如何从残忍地撕毁一堆三只小猪到能够重建整个基因组的。

  1. 在罕见的理想情况下,我们以正确的顺序覆盖所有节点,我们可以只使用字符串重建。
  2. 否则,我们可以用节点作为 k-mers 的前缀/后缀来构造一个 DeBrujin 图。我们想在这个图中找到一个欧拉圈或欧拉路径,然后对其应用字符串重构。
  3. 为了更准确,我们可以使用成对的德布鲁金图,它考虑了 k-mers 之间的空间,并在这周围找到类似的欧拉回路/路径。
  4. 因为我们不能假设完美的覆盖,科学家们经常求助于寻找“重叠群”,这是德布鲁金图中最长的可能片段,没有不确定性。

现在你有了,你应该完全有能力对整个人类基因组进行测序;).

如何使用 Python Web 应用服务于大规模计算?

原文:https://towardsdatascience.com/how-to-serve-massive-computations-using-python-web-apps-590e51624bc6?source=collection_archive---------14-----------------------

克服 Python 的局限性,并通过 web 请求将其用于繁重的数据分析和机器学习。

米格尔·Á拍摄的照片。来自佩克斯的帕德里纳

的上一篇文章中,我写了使用 Python web 应用进行分析项目的局限性。其中一些观点点燃了读者的好奇心,并激励我写另一个故事来补充它。

这篇文章的中心问题是,“如果 Python 因为其同步行为而存在严重缺陷,那么 Instagram 和 Spotify 等平台如何使用它来服务全球数百万人?”

虽然我没有来自这些平台(或类似平台)的官方信息,但根据我的经验,我对处理如此大规模的请求有一些见解。

在本文中,我准备了一个演示来展示基础知识。现实生活中的项目可能有其他几种技术;我没有把它们都包括在内。但是我在这个故事中暗示了一些我最喜欢的,并尽可能提供了参考资料的链接。

让我们再次从讨论同步-异步问题开始。

Python 的同步行为和服务 web 请求的成本。

拥有一个精益技术栈是一个很好的选择。数据科学社区在这方面有 Python 的天赋。因为 python 是一种通用语言,所以可以用它来构建数据管道、机器学习、web 应用等等。

使用 Python web 框架时需要注意的一点是它的同步行为。也就是说,Pyhton 在每个线程中一次处理一个任务。在请求完成之前,其他人必须排队等候。如果您需要服务更多的并发请求,您必须增加内核和实例的数量。

如果你的网络应用只为有限数量的用户服务,这不是一件事。此外,如果您不按需执行繁重的计算,您仍然可以。但是当你增长和计算更多的时候,你的 hello world 类型的网络应用可能会引起严重的问题。

即使是选择节点 app 也是如此。Node 是基于 JavaScript 的,异步运行是这种语言的本性。关键是,在使用 Python 框架时,成本更高(如果未处理的话)。

所以,我们来处理吧。

将计算从请求-响应周期中分离出来。

想象一下,在 Instagram 上;你会看到一只巨大的蓝鲸。被它的美丽所震撼,你双击并喜欢上了这张图片。你希望你能看到更多。但这是你第一次在站台上遇到如此雄伟的照片。

你一直向下滚动;下面几张图片是旧的数据科学迷因之类的东西。

过一会儿,你会再次访问 Instagram。太棒了!你会看到更多巨大的蓝鲸在游泳,和它们的幼崽玩耍。它让你着迷。

这是大多数平台向用户推荐内容的方式。不需要立即学习。它们甚至可能导致假阳性。

处理这个问题的一个聪明方法是将计算从请求-响应周期中分离出来。使用关于用户的先验知识来服务即时请求。积累更多的数据,以便以后更好的学习和表现。这就是我们如何通过继续向下滚动看到旧的数据科学迷因,并在下一次访问中看到更多蓝鲸。

在大规模应用中,我们将用户的每一个动作都收集在一个专用的数据库中。像 Cassandra 这样的数据存储是实现这一目的的绝佳选择。根据应用程序的性质,定期任务用新数据更新模型,或者系统使用触发器来做同样的事情。如果它们发生在你下一次访问平台之前,你很幸运得到了一个最新的模型。

这就足够说明问题了;是时候把手弄脏了。

在 web 请求之外执行繁重的计算。

为了简单起见,我将使用 Flask。但是这种技术同样适用于任何其他 Python 框架。我们使用芹菜来处理请求-响应周期之外的繁重计算。最后,我们将使用一个数据库来收集用户操作。

在这个演示中,我们使用请求本身作为触发器,并立即开始计算。但是它可能会根据您的应用程序的性质而有所不同。通常,您可能还必须使用单独的管道。在这种情况下,你可能需要像阿帕奇气流或者提督这样的技术。

安装消息代理— Redis。

消息代理顾名思义。您可以向代理发送一条消息,代理同时将该消息传递给它的所有订阅者。尽管这个定义看起来很简单,但是对于工程师来说,在消息代理出现之前的生活是很困难的。

这里我们将安装 Redis,一个著名的消息代理软件。相反,你也可以使用 RabbitMQ、亚马逊 SQS 和许多其他芹菜经纪人。

Redis 官方网站有所有操作系统的说明。一种与平台无关的方法是使用他们的官方 docker 映像。

**$** docker run --name redis-server -p 6379:6379 -d redis

安装芹菜和烧瓶

这两个模块的安装非常简单。就像许多其他 Python 包一样,您可以使用 PyPI。

**$** pip install celery Flask

Flask 的目的是通过 HTTP 服务 web 请求。这是一个极简主义的框架,其广受欢迎的替代方案 Django 是满足许多需求的一站式解决方案。我将要分享的技术将在这些方面发挥作用。

芹菜是 Flask(或 Django)和消息代理之间的桥梁。它将您的 Python 对象解析成代理软件可以理解的消息。更广泛的应用还包括任务调度和定期执行。

去耦 hello world 示例。

现在,我们已经安装了芹菜和烧瓶,我们的 Redis 服务正在运行。让我们尝试创建我们的第一个解耦应用程序。

创建一个名为 app.py 的文件,并添加以下内容。

来自作者的代码片段。

上面的代码有四个部分。第一个是将返回芹菜对象的函数(make_celery)。

第二个是 Flask 应用程序创建。如果你有使用 Flask 的经验,你可能对这部分比较熟悉。我们传递额外的配置来通知 Flask 应用程序和 Celery 关于 Redis 服务器的信息。

在第三部分中,我们使用 make_celery 函数创建芹菜应用程序。我们传入 Flask 应用程序实例,它包含 Redis 配置信息。

有了这个设置,我们现在可以创建异步任务。这意味着它们的执行不会中断主线程的常规操作。这里的示例任务 massive _ computation 将返回“你好”,不是立即返回,而是在五秒钟后返回。

为了测试这一点,首先,我们需要启动芹菜服务器。这是一个解耦的过程,将运行您的大规模计算。下面的这个命令会做到这一点。

**$** celery -A app.celery worker -E

在另一个终端中,运行下面录音中显示的命令。

这从 app 模块中导入了我们的 massive _ computation 函数,并调用它。请注意用于调用该函数的独特延迟方法。@celery.task 装饰器添加了这个额外的方法。

一旦调用了函数并将它的值存储在变量中,就可以使用 result 属性来访问它的值。

作者截屏。

正如您在录音中看到的,result 属性在最初的几次调用中没有值。几秒钟后,屏幕上出现了“Hello Thuwarakesh”。

在函数返回值之前,您可以在同一个线程中执行其他活动。这不是使用同步语言(如 Python)开发的应用程序的典型行为。

通过 web 请求服务于大量计算。

我们已经安装了我们需要的技术,并创建了一个与应用程序线程并行运行的基本应用程序。现在,我们已经完成了最后一个部分 web 请求处理。

现在用下面的代码替换 massive _ computation 函数和下面的所有内容。

来自作者的代码片段。

我们创建了 Redis 数据库的一个实例来存储我们分离的计算结果。

我们在这里执行的计算是斐波那契计算。massive _ computation 函数接受一个数字,计算斐波那契数,并将其存储在数据库中。

我们还创建了两个 web API 端点。第一个将设置上次计算的值,另一个将读取当前值。

为了测试这个应用程序,我们需要在已经运行的芹菜服务旁边运行一个 Flask 应用程序。您可以使用以下命令在不同的终端中启动 Flask 应用程序。

**$** flask run

现在,我们已经做好了使用 Python web 应用测试大规模计算的一切准备。让我们试一试。

你可以使用你的浏览器或者 CURL 来完成这项工作。我将在终端窗口中使用 curl。

作者截屏。

上面的录音清楚地解释了用法。当我们查询“/current”端点时,它给出初始值 0。

然后,我们通过“/set”端点指定一个新值,即第 40 个斐波那契数。计算这个数字需要一些时间。然而,系统立即给出了回应,“新的斐波纳契数将很快分配。”这方便地通知用户关于后端任务的信息。

对“/current”终结点的立即查询再次得到 0。这是因为计算尚未完成,数据库中的值仍为 0。

然而,过了一会儿,同一个端点返回第 40 个斐波那契数列的值。后端计算已经完成,芹菜任务更新了数据库中的值。

计算斐波那契数并不是你在现实生活中看到的大量计算。但这只是对它们可能样子的一个合理估计。你可以触发机器学习模型的再训练,而不是斐波那契。

最后的想法

你可能想知道大规模计算在哪里。然而,这篇文章不是关于计算本身。我们专注于如何为大规模计算服务。为了公平起见,我们使用了斐波那契数计算器。

我们已经将计算从 web 服务器的请求-响应周期中分离出来。这允许我们在不中断网络服务器的情况下执行计算。

在本文中,我们使用芹菜来处理这种分离的任务。虽然芹菜能够在生产中运行,但现代替代品提供了更多功能。阿帕奇气流和提督是这方面的一些伟大的技术。

Python 本质上是一种同步语言。试图使它异步会带来很多开销和缺点。使用芹菜进行繁重的计算是处理这个问题的一种优雅的方式。

然而,这并不意味着异步语言可以摆脱它。大规模计算不应该通过请求-响应循环来完成。它们通常服务于不同的目的,而不是即时的、有意义的反应。因此这种方法在任何情况下都是有用的。

感谢阅读,朋友!看来你和我有许多共同的兴趣。我很乐意通过 LinkedIn、T2、Twitter 和 Medium 与你联系

还不是中等会员?请使用此链接 成为 会员。你可以享受成千上万的有见地的文章,并支持我,因为我赚了一点佣金介绍你。

如何设定学习数据科学的套路

原文:https://towardsdatascience.com/how-to-set-a-routine-for-learning-data-science-b20c61f35db?source=collection_archive---------11-----------------------

如何充分利用你拥有的时间

Malvestida 杂志Unsplash 上拍摄的照片

如果你通过正式的全日制教育学习数据科学,你通常可以投入几个小时的时间来学习,并且创建一个学习例程相对容易。然而,如果你像许多人一样,适合围绕全职工作的要求或在照顾家庭的同时学习数据科学护理,可能很难找到时间。

我个人过渡到了数据科学的职业生涯,同时兼顾全职工作和照顾我的两个年幼的孩子。时间对我来说已经很紧张了,我经常因为找不到时间来学习而感到沮丧。然而,随着时间的推移,我学会了一些有用的技巧,来帮助我在我的其他承诺周围划出时间来适应我的学习。

在这篇文章中,我想分享一些我用来创建和坚持学习数据科学的技巧和技术,使我能够成功地过渡到这一新的职业。

你的学习预算是多少?

你需要确定的第一件事是你能花多少时间来学习。能够留出适当的时间进行强化学习是很重要的。理想情况下,这些时间应该至少有两个小时,我建议每周至少留出五个小时。

为了坚持包含一致时间段的学习时间表,它需要是现实的,并且需要适合你的其他承诺。

为了确定你实际上有多少时间可以用于这些紧张的学习时间,我建议首先拿起笔和纸,写下你在典型的一天中已经拥有的时间承诺,包括周末。假设你必须工作 8 小时,你需要睡眠(8 小时),然后你需要时间锻炼、吃饭、做家务和与家人在一起。假设这些还需要 2 -3 个小时。这可能会让你每天的学习预算只有 3-4 个小时。

"关键不在于花费时间,而在于投资时间.",斯蒂芬·R·科维

这 3 到 4 个小时的时间,或者你个人学习预算中剩余的任何时间,都是你专门学习的时间。这段时间应该用于紧张、集中的学习或动手实践应用,如从事副业项目。

优先安排你的学习时间是非常重要的。做到这一点的最好方法是做出承诺并坚持下去。将你每天的学习时间作为一个循环事件添加到你的日历中。

利用空闲时间

死区时间是你日常生活的一部分,在这段时间里你不能进行任何高强度的学习,但对于更轻量级的学习来说是理想的。这可能是坐在火车上作为你早晨通勤的一部分,在工作会议前的 5-10 分钟,没有时间开始新的任务或等待你的孩子完成足球练习。

当我最小的儿子还是个婴儿的时候,没有我安静地坐在他旁边,他无法入睡。所以我每天晚上至少花 30 分钟坐在他床边的地板上。过了一段时间,我开始利用这段时间进行一些安静的学习。这是我看书或听播客的理想时间。通过这样做,我既能给我儿子提供他所需要的舒适,同时也给了我自己学习和成长的时间。

"失去的时间一去不复返。"本杰明·富兰克林

所以我的建议是尽量利用你一天中的任何空闲时间进行某种学习。这不是深度强化学习的时间,但通常是花时间阅读论文、补上博客帖子或视频讲座的绝佳机会。

通过利用这些空闲时间,你可以最大限度地利用学习预算中的可用时间。

也要安排休息时间

大多数运动员在日常锻炼中安排有规律的休息日。这些休息日是必要的,让身体有时间从高强度训练的压力中恢复过来。人们早就认识到,与完全不休息相比,通过休息,运动员的表现实际上有所提高。

“工作中有美德,休息中也有美德。两者并用,不可偏废。”,
艾伦·科恩

我相信对于像学习这样的脑力劳动来说,安排休息日也同样重要。在设计你的学习计划时,确保你每周至少有 1 到 2 天的休息时间。这可能是周末休假或者在一周中的某些晚上不学习。找到适合自己的平衡点很重要。

除了休息日之外,在你的日常生活中安排不太密集的学习也是一个好主意。这类似于运动员的积极休息日,在艰苦训练后的第二天进行温和的锻炼。学习数据科学的积极休息日可能是阅读一本书,在 Youtube 上赶上一些讲座,或者与你的导师喝杯咖啡。

在这段时间里,你仍然会学习,但是你会避免精疲力尽,最终从长远来看,你会学得更快。

我写了很多关于如何使用免费或低价资源学习数据科学,而不必花费数千美元接受更正规的教育。然而,能够负担得起你需要学习的材料是一回事,找到你需要学习的时间是另一回事。尤其是如果你有其他的承诺,比如一份全职工作。

为了找到学习数据科学的现实路线,并且可以长期坚持,我建议采取以下步骤:

  • 设定一个切实可行的时间表,每周至少包括 5 次强化学习。每节课至少要两个小时。
  • 利用空闲时间进行不太紧张的学习,最大化你的整体学习预算。
  • 确保你能及时安排休息日,以避免精疲力竭。

除了时间,你还需要学习资源和足够的动力。关于如何找到免费资源和学习动机的指导,请参见我之前的文章。

感谢阅读!

我每月都会发一份简讯,如果你想加入,请点击此链接注册。期待成为您学习旅程的一部分

如何为企业设置技术指标数据科学项目

原文:https://towardsdatascience.com/how-to-set-technical-metrics-data-science-project-for-business-7e77084448a4?source=collection_archive---------29-----------------------

技术 KPI 是数据科学项目中的必备要素

弗洛里安·伯杰在 Unsplash 上拍摄的照片

数据科学家是受雇使用数据产品解决业务问题的人。然而,数据科学课程的趋势集中在技术方面,而不是业务角度。老实说,如果数据科学家先学习业务而不是技术,他们被聘用的机会会增加

数据科学家工作的重点之一是技术指标,如准确度、精确度、召回率等。许多数据科学家专注于获得尽可能高的指标,但是多高的指标才算是好的呢?。你可能想在竞争中取得最好的成绩,但做生意不同,很多时候你没有时间这样做。那么,如何为企业设定合理的技术指标呢?本文将通过一个示例帮助您理解如何做到这一点。

本文将从我设置满足业务需求的技术指标的经验中探索一个具体的例子。它可能不适用于您的特定业务,但总体思路应该是相似的。带着那个音符,让我们开始吧。

商业和数据科学

数据科学家懂业务是否必不可少?是的,我会为这种说法辩护。优秀的数据科学家和伟大的数据科学家的区别在于解决业务问题。一个优秀的数据科学家可以开发出最好的模型,但是一个伟大的数据科学家可以开发出满足业务需求的好模型。

在下面的文章中,我就为什么一个伟大的数据科学家是懂业务的人这一问题提出了自己的观点。

每个数据科学家都知道的一个知识是将业务问题模拟成技术需求。每个业务项目都将从业务用户希望数据科学家解决的业务问题开始。我们需要讨论我们的项目将触及的每个业务方面的情况。为什么?因为我们的模式会受到每个商业选择的影响。

例如,业务用户需要一个模型来预测客户购买产品的兴趣。许多人最初会通过开发一个分类模型来进行预测。然而,我认为您应该知道的是业务流程如何向客户销售产品。

最佳模型是在业务流程中使用的模型。想象一下,你已经花了几个月的时间来完善这个模型,却发现你的模型无法使用——因为你使用的特性或者不好的标记。这就是为什么你需要知道业务流程。

了解业务会让你成为伟大的数据科学家,因为你会选择适合问题的特性和模型。此外,您可以为您的数据科学项目设定技术要求。为了帮助您理解技术指标的业务概念,让我们使用一个示例数据集。

设定技术要求的业务模拟

对于这种情况,我会利用我在开发机器学习模型方面的经验来预测交叉销售保险客户。数据集来自 Kaggle 。让我们阅读培训和测试数据,以了解数据集和业务问题。

import pandas as pdtrain = pd.read_csv('train.csv')
test = pd.read_csv('test.csv')train.info()

作者图片

训练数据包含具有 381109 行的 12 个特征。因变量(目标)是响应变量。测试数据包括 127037 个具有相似特征的行,但不包括响应。我们来看看目标变量分布。

import seaborn as sns#Target exploration
sns.countplot(train['Response'])

作者图片

我们的数据中有一个不平衡案例;只有 12%的人对培训数据中的交叉销售感兴趣。

我不会在这里展示我所有的数据探索结果,因为要花很长时间来解释它,但我稍后会将我的笔记本附加到我的 GitHub 上。我将描述业务中的特性含义,以及如何从业务角度对待训练/测试(当前数据)。

现在,在现实世界中选择数据之前,我们需要首先考虑业务流程。然而,在这种情况下,让我们反过来;根据我们拥有的数据集,我们需要考虑使用数据集的业务流程和含义。

比如功能 Driving _ License 是客户有没有驾照的一个特征。如果此功能可以帮助您预测交叉销售的客户,您认为您会使用它吗?也许你会说是,但我会说不是。为什么?从商业的角度来看,尤其是保险,向没有驾驶执照的客户提供保险是不合理的(以我的经验来看)。我会说这个特性变成了一个过滤器,而不是训练数据。

我可以说 Policy_Sales_Channel 特性和 Region_Code 特性也可能产生偏见。一些渠道和地区可能比其他地区销售更多;你能把它介绍给模特吗?我之所以说不,是因为它间接导致了一些渠道和地区被排除在外。

让我们进入本文的要点,建立业务的技术需求。我前面解释的所有业务理解都是理解业务流程所需要的。你需要知道这个行业来自哪里,以及你所使用的每个特性的含义。

业务模拟

在继续机器学习开发之前,我们需要在部署这个模型时考虑业务方面。怎么做呢?通过业务模拟,我们可以计划我们的技术需求目标。首先,我们来考虑一下我们为什么要开发这个机器学习模型?我们希望构建模型,帮助企业产生交叉销售可能性更高的销售线索,以避免致电不感兴趣的客户。

遗憾的是,没有关于代理商数量和联系客户费用的信息。为什么这个信息很重要?因为如果联系客户没有相关的成本,而模型做出了错误的预测,那么为什么不直接给他们打电话,而不是依赖机器学习模型呢?。此外,我们需要考虑项目时间表和能够执行销售线索的代理数量,因为这也会影响业务目标。

此外,我们为什么要考虑项目时间表?想象一下,该模型预测 50000 名客户将进行交叉销售。代理会在一天内执行所有 50000 个客户吗?显然,不是(除非每个客户有 50000 个代理),并且代理会优先考虑他们要呼叫的客户。也许你会认为我们可以让代理在任何时候找到销售线索,只要我们预测到他们会交叉销售;问题是客户的生活会随着时间的推移而改变,在这种情况下预测可能不成立(数据漂移)。这就是项目时间表影响业务和技术方面的原因。

让我们试着概述一下我们需要考虑的业务变量:

1.业务目标(从这个项目来看,要跟踪的业务目标是什么;
常为销售数或换算数)2。接洽/拜访成本(与拜访相关的所有成本、运营成本、代理小费等。)
3。代理编号
4。时间线
5。成功转化收入(成功交叉销售对 ANP 的贡献有多大)
6。销售线索数量(在时间表中会有多少销售线索)
7。模型度量

我们仍然可以想到许多变量,但是让我们首先坚持最简单的一个。那么如何处理这些变量呢?我们需要基于业务流程用这个变量构建一个模拟。这个过程可以是任何事情,因为我不知道这个特定公司的过程是怎样的,但是我可以根据我的经验来模拟它。我的目标是模拟我们能否实现目标。

业务目标(BT)是我们需要在时间线(T)内实现或超越的最终目标。在该项目中,在收到预测后,我们会给代理(A) 一定数量的线索(L) 在时间表内处理。假设每个代理只需要调用转换,那么我们需要关心调用(C) 的成本。每个电话都会受到代理数量和项目时间表的影响,代理数量多和时间表短都会增加成本,反之亦然。最后,成功转换收入是每个成功呼叫的系数。总收入将受到模型指标(M)** 和销售线索数(销售线索数中有多少成功呼叫转化为收入)的影响。为什么还要对度量进行建模?因为不是所有的电话都会 100%成功。**

业务流程将只有预测感兴趣的销售线索才是被呼叫的销售线索。

如果我们把它变成一个线性方程,我们就把它写成:

BT <= (S * (L * M)) — (L*(C * (A/T))

这个等式并不完美,但我们需要用一个合理的数字来填充它。

我们已经建立了变量和方程。现在,我们只需要把它装满。成本是一个企业的固定数字,我们可以调整,但成功转换收入在每次成功中都是不同的(除非你想说产品总是产生固定收入/ANP)。在这种情况下,我们可以使用来自客户 ANP 的历史数据,例如平均值或中值。对于我们的情况,让我们以列车数据的年保费平均值为例。

#Rounding the ANP Average per cases
round(train['Annual_Premium'].mean())

结果将是 30564 印度卢比。接下来,让我们为模拟操作定义一个函数。

def business_target_simulation(S, L, M, C, A, T):
    revenue = (S*(L * M)) - (L * (C * (A/T)))
    return revenue

让我们定义一些变量(因为这是模拟,所以您可以更改),我们有:

  • 业务目标(BT);假设今年我们希望通过交叉销售计划获得 10.000.000 印度卢比
  • 时间线(T)将是一年,这意味着 12 个月
  • 每次通话费用(C)假设 5000 印度卢比
  • 代理数量(A),假设为 100
  • 成功收入将是 30564 英镑
  • 销售线索的数量(L)将与现有人口相关,因为它是交叉销售计划。测试数据包含 127037 人。从培训数据中,我们看到大约 12%的人对销售感兴趣。如果我们将其余数据的 12%作为线索(假设预测模型可能遵循相同的概率分布),我们将有 15244 个客户作为线索。
  • 对于模型度量(M ),让我们假设我们使用精度,因为我们需要根据预测的购买兴趣来计算真实的正例。因为业务流程只会调用预测的感兴趣的线索,所以我们需要最大化类 1(感兴趣)的精确度。为什么?因为误报太高(精度低),打了太多电话没有成功收入;sans,成本更高。我们的成本与阳性病例相关(对或错)。

我们要定义我们的技术 KPI,所以让我们模拟各种精度数字。我将创建一个简单的函数来绘制要实现或超越的业务目标的结果。

def simulation_plot(metric_range, S, L, C, A, T, BT):
    result = []
    for score in metric_range:
        result.append(business_target_simulation(S=S, L=L, M = score, C=C, A=A, T=T))
    plt.figure(figsize = (8,8))
    img = plt.plot(metric_range, result, marker = 'o') 
    plt.axhline(BT, color  = 'red')
    return img

让我们输入所有的假设变量,用这个函数来画出函数。

simulation_plot(metric_range = np.arange(0.7, 1.01, 0.01), S = 30564, L = 15244, C = 3000,  A = 100, T =12, BT = 10000000)

作者图片

我们的业务目标是 10.000.000 印度卢比,根据我们的模拟,我们需要至少达到 82% 的精度,我们的模型才能对业务产生影响。这个数字相对较高,但肯定是可能的。考虑到这一点,当我们建立模型和 MLOps 时,我们需要确保精度始终高于 82%。你可以随时改变衡量标准,比如准确性、召回率等。然而;如果我们这样做,我们需要调整等式。

当然,这种模拟是基于线性假设,没有考虑随机因素和误差。我们可以试着改变置信区间,但是让我们留待以后讨论。

您可以修改代码和变量,以更好地模拟业务需求。我建议你调整一下线性函数,因为我知道它并不完美。我愿意为这个功能的建议。

我想展示的是模拟的力量,它能够为业务建立技术要求。有了 82%的准确率,我们就能实现业务目标;少于这个数字是不可取的。

资源

这个模拟的所有代码都存储在我下面的 GitHub 页面上。

https://github.com/cornelliusyudhawijaya/Cross-Sell-Insurance-Business-Simulation

结论

伟大的数据科学家是理解业务流程的人。商业理解来自经验,但它肯定是我们可以学习的东西。

在本文中,我概述了如何为业务建立技术需求,尤其是使用业务模拟的能力。

希望有帮助!

在我的 LinkedInTwitter 上访问我。

如果您喜欢我的内容,并希望获得更多关于数据或数据科学家日常生活的深入知识,请考虑在此订阅我的 简讯。

如果您没有订阅为中等会员,请考虑通过 我的推荐 订阅。

如何设置 AB 测试中的最小可检测效应

原文:https://towardsdatascience.com/how-to-set-the-minimum-detectable-effect-in-ab-tests-fe07f8002d6d?source=collection_archive---------0-----------------------

(图片来自Unsplash.com)

业内笔记

揭秘最难以捉摸的 AB 测试参数

“在这个测试中,我们应该使用多大的最小可检测效应?”无论何时与产品团队建立 AB 测试,确定最小可检测效应(MDE)值都是最棘手的部分之一。关于这个术语的意思存在着许多混乱。以及对于特定的测试应该选择什么值。

在本文中,我想阐明 MDE 的含义,它对实验结果的影响,以及如何找到一个合适的值。

最小可检测效应是什么意思?

MDE 对于计算最小所需样本量是必要的,最小所需样本量是必须收集的观察值的数量。在达到该阈值之前,不得分析 AB 测试的结果。

通常,MDE 被误解为可以检测到的最小影响。这是可以理解的,因为这就是名字的含义。但是如果 AB 测试不能产生显著的结果,如果效应大小小于 MDE,这将意味着测试不能产生任何错误的结果。

MDE 不是 AB 测试中可以检测到的最小可能的影响。

AB 检验中总是存在不确定性因素,这可以通过各种参数来控制,如显著性水平。该参数决定了得出有显著影响的结论的概率,尽管没有影响。尽管没有影响,但总是有可能得到重要的结果,AB 测试总是可以提供重要的结果,尽管影响比 MDE 小。

另一个参数是权力水平,它决定了如果现实中存在积极影响,获得重大成果的可能性。该参数与显著性水平和 MDE 一起决定了实验所需的最小样本量。记住这一点,最小可检测效应的定义可以重新表述如下:

MDE 是应该以一定概率检测到的最小效应大小。

在文献中,术语最小可靠可检测效应被认为是更合适的术语,更符合上述定义。要明确的是,MDE 不是我们期望或想要的效果大小。

为什么 MDE 很重要

想象你站在传送带前,质量检查螺丝从旁边经过。如果你想证明正在生产的 50%的螺丝质量低于标准,在得出结论之前,你会检查多少螺丝?如果你想证明 2%的螺丝是低质量的,这可能会更少。

这个类比可以转移到 AB 测试的世界。我们感兴趣的效应越小,在得出任何结论之前,我们需要收集的样本就越多。所需样本量的增加要求我们进行更长时间的实验。

用 MDE 控制风险和成本

AB 测试是一种控制与特定变更相关的业务风险的机制。每个实验都有与时间相关的成本,比如向一部分用户展示糟糕体验的机会成本。我们进行测试的时间越长,成本就越高。

在某些情况下,拥有非常低的 MDE 会浪费金钱和时间。想象一个产品团队正在一个市场网站上测试一个非常有前途的 MVP。实现这种改变是有风险的,需要花费数月的开发工作,但可能会导致用户转化率的大幅增加。在这种情况下,团队需要至少 5%的转换率来证明成本的合理性。因此,对于根本原因而言,设置明显较低的 MDE 是不必要的,并且会不必要地延长测试时间(测试将超过)。

同时,我们需要确保 AB 测试有正确的统计设置来检测一个效应(如果存在的话)。让我们假设我们进行了一个实验,在这个实验中,我们改变了网站上“立即购买”按钮的内容,以提高转化率。我们的测试只能检测到转化率以一定的概率增加了至少 50%。在这种情况下,即使变化有积极的影响,测试也很可能不会产生任何显著的结果。我们可能会错误地得出结论,认为改变并没有什么不同,并决定继续使用旧的副本(在这种情况下,有人提到了动力不足测试)。

设置适当的 MDE

正如您所看到的,MDE 的正确值在很大程度上取决于用例。它必须了解与潜在实验相关的风险、成本和预期。

你的最小 MDE 应该是能够证明正在测试的变更的实现是正确的最小效果。当然,你总是可以战胜考试,从中学到更多。但是在这样做的时候,必须记住进行实验的风险和机会成本。

那么如何得出一个确切的数字呢?这归结为一个简单的 ROI 计算。考虑以下(非常简化的)情况:

  • 一个团队正在验证一个 MVP,让用户在旅游网站的收银台购买旅游保险。
  • 该网站每天登记 2000 个预订(每年 730.000)。
  • 保险的估计净利润是每个用户 3 美元。
  • 实现完整的功能将花费团队 ca。150 个开发人员小时,比方说每小时 500 美元,总计 75.000 美元(不考虑任何机会成本)。

以年为基础,该网站必须销售 25000 份保险才能达到收支平衡,相当于 3.42%的预订量加上保险。

由于保险转换率是实验的主要指标,3.42%将是一个合理的 MDE。任何低于这个值的值都不会引起团队的兴趣,并且会不必要地延长测试的持续时间。

摘要

对于大多数 AB 测试参数,从业者倾向于使用行业标准值。显著性水平通常选择为 95%,而 80%是测试功效的默认值。尽管不鼓励盲目使用这些默认值,但它们仍然为找到合理的值提供了一些指导。因为 MDE 没有这样的标准,所以每个 AB 测试都会出现一个合适值的问题。这使得所有团队成员了解这个参数的含义以及如何适当地设置它变得更加重要。

通常,测试持续时间首先是固定的,并且选择 MDE 来适应这个运行时间。可能有很好的理由只进行一周或特定时间的实验。但是这种实践通常会导致测试不足或测试过度,从而导致业务的更高风险或机会成本。因此,MDE 必须基于底层业务案例来选择。这个值决定了必要的样本大小,从而决定了测试的运行时间。

喜欢这篇文章吗?

那么你可能也会喜欢我的另一个关于 AB 测试的帖子:

参考资料和进一步阅读

在线 AB 测试中的统计方法 格奥尔吉·格奥尔杰夫

为成功建立有效的数据分析团队和项目生态系统

原文:https://towardsdatascience.com/how-to-set-up-a-data-analytics-team-and-project-ecosystem-for-success-100e14067e77?source=collection_archive---------18-----------------------

应用这些技术创建一个数据分析程序,提供令最终用户满意并满足其需求的解决方案

介绍

在软件开发、信息安全和数据分析的长期职业生涯中,我观察到大型、复杂和压倒性的项目有可能无法满足利益相关者的需求,除非它们管理得非常好。相比之下,我参与的大多数成功的数据分析项目在范围、规模、团队规模和时间上都很小。它们通常需要几天、几周或几个月的时间来完成,而不是几年,并且通常可以满足最终用户的需求。

健全的管理、敏捷的实践、熟练的从业者、强大的工具、标准和指南可以结合起来创建一个数据分析生态系统,从而缩短项目生命周期并提供有用的解决方案。以下部分描述了我的团队为取得成功而开发和利用的一些组织、项目和数据分析属性和技术。虽然我们在大型企业的风险管理和内部审计职能中构建了我们的数据分析计划,但是您也可以将其中的许多技术应用到您的工作环境中。

良好的管理和领导力

在我从事软件开发和数据分析的 34 年中,我观察到了许多管理和领导风格,有好有坏。我最近与一位经理一起工作,他创建了一个框架,并指导我们的团队在一家大型企业中建立了一个成功的部门数据分析程序。根据经验和观察,以下是他和其他模范领导者为帮助个人、团队和项目取得成功而采取的一些品质和行动:

  • 为项目设定目标,并管理项目和团队实现目标。
  • 确定所需的能力,并雇用和培训员工来实现这些能力。
  • 与内部和外部组织合作,分享和学习最佳实践。
  • 提供满足需求的强大软件工具。
  • 作为高层管理人员的沟通渠道。
  • 与团队合作,关心团队及其成员,但不要盛气凌人。
  • 确保实施并遵循基本但充分的商定标准、指南和程序。
  • 建立成长和成就的节奏。
  • 尊重每个团队成员的时间和注意力。

雇佣并发展技能和知识

几年前,我参加了一个数据分析会议,会上一位演讲者描述了她作为数据科学家所需的一些技能。她说有效地完成她的工作需要 200 多种技能。事实上,创建成功的数据分析解决方案需要分析师具备多方面的才能。要聘用和培养具备所需技能和知识的分析师,您和您的管理层可以考虑以下步骤:

  1. 撰写引人注目的职位描述和公告 —撰写描述成功候选人必须具备的技能和知识的职位描述和公告。此外,列出员工在受雇期间必须发展的技能和知识。
  2. 聘用具有专业知识和良好潜力的数据分析师 —应用职位描述和职位发布来聘用具有所需技能和知识、资质和潜力的分析师,以开发额外的所需技能。
  3. 确定学习资源 —创建课程和教程列表,以帮助数据分析师发展在其职位上取得成功所需的技能和知识。
  4. 评估技能 —衡量团队及其成员的优势和劣势,确定发展和成长需求,根据每个数据分析师的工作描述和深入的能力列表评估他们的技能和知识。
  5. 培训分析师 —确保工作单位的预算和时间表允许资金和时间用于数据分析师完成培训,以发展所需的技能和知识。根据技能评估结果,确保分析师参加学习资源列表中定义的培训。

保持项目团队的小规模

除非熟练地管理,否则大型团队的复杂项目可能会陷入困境。尝试保持每个项目的规模和范围较小,并将团队规模限制为一至三个最终用户和一名首席数据分析师,可能有助于项目成功。团队可以将数据分析师添加到复杂的项目中,这将受益于分工或互补的技能。对于大型或复杂的项目,您可能希望指派一名项目经理与团队一起确定和管理任务、时间表、风险和问题。最后,在需要时,寻找项目业务领域的主题专家(SME)。

采用敏捷实践

项目团队,尤其是在软件开发中,经常将敏捷开发方法应用到他们的项目中,比如 Scrum 或看板,来组织任务和快速移动。我的团队有效地使用了在 Microsoft OneNote 中开发的看板,在频繁的站立会议上,在团队及其经理之间跟踪和交流任务。它在一页上由三列组成。每项任务在开始时从“准备工作”变为“工作中”,在完成时从“工作中”变为“完成”。

一个简单的看板可以用来管理项目任务。图片由作者提供。

定义简明的范围、目标和时间表

在整个项目生命周期中,与最终用户、团队成员和经理的对话对于建立和坚持一致同意的简明范围、目标和时间表至关重要。通过保持项目紧凑,我成功地完成了一周至三个月的项目。

如果一个项目很大很复杂,可以考虑把它分成更小的子项目,每个子项目都有一个有限的范围、目标和时间表。

将一组合理的竞争性项目和任务分配给数据分析师

一些研究人员发现,当同时处理多项任务时,人类的表现会受到影响。给个人分配大量的项目或任务可能会适得其反。此外,虽然技能和任务多样性是可以提高个人满意度和绩效的工作组成部分(参见工作特征理论),但分配给工人的项目或任务数量应该合理,以允许工人成功完成所有项目或任务。

平衡团队合作和自主性

在一个运转良好的团队中工作可以带来许多好处,例如:

  • 队友可以互补彼此的技能。
  • 队友之间可以互相鼓励和推动。
  • 团队成员可以分享想法,集思广益,找出解决方案。
  • 团队的生产力可能超过其各个部分的总和。

有效团队合作的好处是毋庸置疑的。另一方面,一些类型的工作,如数据分析、编程和写作,通常最好由半自主工作的个人来完成,通常需要团队成员的输入。他们的工作需要专注和有限的干扰。

采用并掌握强大而通用的工具和语言

数据分析师应该为自己配备功能强大、用途广泛的数据分析工具,以满足他们的需求。通过这种方法,分析师可以利用每种工具的功能,开发能力和最佳实践。以下部分描述了我当前团队在数据分析项目中使用的每个软件包。

Alteryx Designer——根据 Alteryx 的网站,Designer 可以用来“自动化分析的每一步,包括数据准备、混合、报告、预测分析和数据科学。”虽然单用户许可证需要数千美元,但它是一个强大的数据分析和数据科学工具。我的团队使用它来创建和运行输入数据、转换和准备数据以及以多种格式输出数据的工作流。分析师使用它来快速轻松地创建强大且快速运行的工作流。

Tableau — Tableau 软件创建了一个强大的、或许是最受欢迎的商业智能和数据可视化平台。我的团队使用 Tableau Desktop 连接数据源,开发可视化的工作表和仪表板。然后,我们将视觉效果发布到 Tableau 服务器,最终用户可以在那里观看并与之交互。

Python — Python 是一种用户友好且功能强大的编程语言,深受数据分析师和数据科学家的欢迎。与在数据科学家中也很流行的以统计为中心的 R 语言不同,Python 是一种通用语言。它是免费的,也很容易学。分析师可以用免费的库来扩展 Python 的功能,比如 NumPyTensorFlow

Python 编程语言代码示例。图片由作者提供。

SQL —结构化查询语言(SQL)是用于实现、操作和查询存储在关系数据库管理系统(RDBMS)中的结构化数据的标准语言。它包括多种子语言。通过其数据查询语言(DQL),分析师可以从数据库表中查询和检索数据。RDMS 数据库存储了世界各地企业的大量数据集。

SQL(结构化查询语言)代码示例。图片由作者提供。

微软 SQL Server Management Studio(SSMS)—SSMS 是微软的集成开发环境(IDE),用于管理和查询在其 SQL Server RDBMS 中实现的数据库。免费且易于学习,我使用 SSMS 创建并运行 SQL 代码来查询包含所需数据的数据库。

SQL Server Management Studio (SSMS)用于管理 Microsoft SQL Server 数据库和 SQL 代码。图片由作者提供。

Rapid SQL — Rapid SQL 是一个类似于 SSMS 的 IDE,用于开发 SQL 查询以访问存储在 Oracle、SQL Server、DB2 和 SAP Sybase 数据库中的数据。我使用 Rapid SQL 从 DB2 或 Oracle 数据库获取数据。

微软 Visual Studio — Visual Studio 是微软的旗舰集成开发环境(IDE)。我使用 Visual Studio Professional 创建用 Python 和其他编程语言编写的应用程序。它的编辑器具有强大的颜色编码语法。Visual Studio Community 2019是一款免费版的 IDE,可能会满足你的需求。微软的 Visual Studio Code (VS Code)是另一个免费的 IDE,在程序员和数据分析师中很受欢迎。

Microsoft Visual Studio Professional 是用于编写程序和开发应用程序的集成开发环境(IDE)。图片由作者提供。

当然,Excel 是一个无处不在的、有用的、强大的、有时不可或缺的工具。我使用 Excel 工作簿作为项目数据源和输出来创建小型数据集,执行基本的数据清理和计算,等等。像 Excel 这样的电子表格应用程序是任何数据分析或数据科学商店中的重要工具。

电子表格应用程序,如 Microsoft Excel,是通用的数据分析工具。图片由作者提供。

制定基本标准、指南和程序

将简明的标准和指南应用到数据分析项目中,可以提高生产力,维护和共享工作产品。以下是指导我工作的标准和指南。

命名标准——标准化项目,例如文件夹、文件、数据库表、列和字段,使它们易于一致地命名,并在许多产品的集合中找到工作产品。

文件夹结构标准和模板 —对所有项目使用标准文件夹结构,可以轻松创建新项目和查找文件夹和文件。我的团队使用以下文件夹结构模板来组织和存储所有数据分析项目的工作产品:

  • Project_name(将此值更改为项目的名称)
  • alteryx _ 工作流
  • 数据
  • 证明文件
  • python _ 程序
  • sql _ 脚本
  • tableau _ 工作簿

文件夹结构会根据每个项目的需求进行扩展和收缩。

编码标准 —编码标准适用于编程,就像语法适用于英语散文一样。它们帮助我们清晰一致地组织和传达思想。我工作过的数据分析和软件开发团队受益于文档化的编码约定。在项目中应用这些标准可以使每个代码模块更容易被最初的编码者编写,也更容易被任何团队成员阅读、理解、增强和维护。下面是我的团队用来指导工作的一些编码标准的描述。

  • 类、变量和函数命名惯例 —为了可读性,我们决定用小写字母创建所有的类、函数和变量名称,每个单词或缩写用下划线(“_”)隔开。每个类和变量名描述了它存储的值的类型,而每个函数名描述了该函数用什么值或对象做什么。例如,存储人名的变量可能被称为 person_name 或 person_nm。从数据库中检索人名列表的函数可以称为 get_person_names()。
  • 代码模块序言 —我们以文本开始每个模块,描述其用途。为了帮助其他可能维护该模块的编码人员,我们添加了额外的信息,例如作者的姓名、数据库连接字符串、文件位置信息和更改日志。
  • 注释 —虽然有人说代码本身就是文档,但我相信恰当的注释可以帮助编码者组织他们的思想,并帮助其他需要维护或增强代码的人更快地理解它。例如,在它的开始,我描述了一个函数用什么数据做什么。我还在执行任务的每个代码逻辑分组前添加了一个简短的注释。
  • 空白——为了让代码更容易阅读,我在每个函数、每组变量定义和执行特定任务的每个代码块之间插入了一个空行。
  • 简洁的函数范围和可见的大小——和空白一样,我限制了每个函数的内容,以便更容易编码、理解、维护和增强。我努力保持每个函数简单,并试图保持其内容在编辑器中可见(例如 80 个字符宽,40 行长)。

可视化风格指南 —虽然编码标准可以帮助程序员理解、编写和维护代码,但可视化风格指南可以帮助数据分析师开发一致、有用和有意义的视觉效果。它们还可以通过提供一致、设计良好、易于理解和用户友好的视觉效果,使数据分析项目的最终用户受益。以下是我的团队采用的一些视觉风格指南。

  • 品牌标准 —我们公司的品牌管理部门已经确定了一套一致的字体、颜色以及视觉设计风格和组件。我们将这些应用到我们的可视化指南中,以增加专业性和一致性,并帮助为最终用户提供熟悉的用户界面风格。
  • 字体 —我们公司已经设计了一种字体,当它可供我们使用时,我们将使用它。否则,我们的数据分析产品将默认使用 Ariel 字体。
  • 颜色 —我们公司的品牌标准包括一个小调色板。我们尽可能将这些颜色应用于图表、图形和仪表板。我们还试图将图表、图形或仪表板上使用的颜色数量限制在视觉上令人愉悦的范围内。
  • 标题、页眉和标签 —我们的指南描述了应用于文本元素的标准位置、字体、大小和颜色,例如仪表板标题、图形和图表页眉、列、过滤器和图例。
  • 可视组件的放置 —与文本一样,我们的指南描述了图表、图形、过滤器和图例等元素在仪表板上的标准位置。

摘要

建立一个有效的数据分析团队并不容易,该团队定期构建和交付数据分析解决方案,为最终用户提供见解并帮助他们做出决策。但是,应用我在长期的软件开发和数据分析职业生涯中学到、采纳和发展的一些经验和有效实践,可能会帮助你取得成功。

关于作者

Randy Runtsch 是一名数据分析师、软件开发人员、作家、摄影师、自行车手和冒险家。他和妻子住在美国明尼苏达州东南部。

关注 Randy 即将发表的关于公共数据集的文章,以推动数据分析解决方案、编程、数据分析、自行车旅行、啤酒等。

如何在 Pytorch 中建立深度学习项目

原文:https://towardsdatascience.com/how-to-set-up-a-deep-learning-project-in-pytorch-d1b9ac4b70a3?source=collection_archive---------35-----------------------

在 Pytorch 中建立深度学习项目的 3 个步骤

Graham Holtshausen 在 Unsplash 上拍摄的照片

在这篇文章中,我将解释如何在 PyTorch 中建立一个深度学习项目。

任何 PyTorch 深度学习项目通常由 3 个基本步骤组成:

  1. 设置数据集
  2. 创建数据加载器
  3. 创建培训、验证和测试循环

我不会讲述如何建立一个实际的模型,因为它相当简单,因任务而异,而且网上已经有很多资源可以学习如何做这件事。

1.设置数据集

为了创建可以与数据加载器一起工作的数据集,以创建可以发送到实际模型中的数据批,PyTorch 要求您为数据集创建一个特定的类,并覆盖它的两个函数:getitem()函数和 len()函数。

在大多数机器学习项目中,在数据实际发送到模型之前,通常需要对数据进行一些预处理。例如,在自然语言处理任务中,这可能涉及对文本进行标记并将其转换成数字格式。为此,我在同一个类中创建可以完成所有这些过程的函数,如 build_dataset()或 preprocess()函数,并将所有预处理数据存储在一个单独的文件中。

getitem 和 len 函数只是数据加载器用来构建小批量数据的函数。在下一节中,您将看到数据加载器如何使用和需要一个数据集对象/类,该数据集对象/类作为参数正确地覆盖了 getitem 和 len 函数,因此正确地实现这两个函数非常重要。

getitem 函数相当简单。想象您的数据集正在被索引。例如,如果您正在执行一项图像识别任务,并且正在处理图像,则每个图像都将从 0 到数据集大小/数据集中的图像数量进行索引。对于 getitem 函数,您所要做的就是,给定一个索引,返回存在于该特定索引的数据的 x,y 对(或输入输出对)。因此,重要的是要记住,您可能应该将数据存储在索引数据集中,如列表中,这样您就可以轻松地访问特定索引处的元素。len 函数只是一个返回数据集长度的函数。以前面将数据存储为列表的例子为例,您只需返回列表的长度。

class MyDataset:
   def __getitem__(self, index):
       return self.input[index], self.label[index]
   def __len__(self):
       return len(self.input)

需要注意的是,getitem 函数中的数据不一定是元组。您可以用任何类型的数据结构返回数据。如果您的模型有多个输入,您可以将数据作为字典返回。如果只有一个输入,可以将其作为元组返回。这真的没有关系,因为在训练循环中,您只需正确地从数据结构中检索输入。

class MyDataset:
   def __getitem__(self, index):
       return {"Input_1": self.input1[index], 
               "Input_2": self.input2[index], 
               "Input_3": self.input3[index], 
               "Label": self.label[index]}
   def __len__(self):
       return len(self.input1)

2.创建数据加载器

DataLoader 是 Pytorch 提供的一个工具,它使得创建批量数据并将其发送到模型中变得非常容易。它使用我们在上一部分中创建的 dataset 类,以及其他一些东西来创建批处理。下面是你如何编码它们:

from torch.utils.data import DataLoader
data = MyDataset(parameters here)
data.build_dataset()## A helper function to do the preprocessingdataloader = DataLoader(dataset = data, batch_size = batchsize, shuffle=True)

数据加载器提供的一个非常重要的功能是,它们允许我们在将每批数据发送到模型之前,对每批数据应用特定的函数。他们通过 collate 类来实现这一点。collate 是一个一次接收一批数据的类,可以修改该批数据并对数据执行任何特定于批的功能。它是这样工作的:

class MyCollate():
  def __call__(self, batch):
    ## do whatever operations you want here
    ## return the new batch of data

为了正确地创建 collate 类,您必须重写 call()函数。调用函数将接收一批数据,并返回一批新的、修改过的数据。collate 中 call()函数的输入批处理只是一个通过多次调用数据集中的 getitem 函数构建的列表,这是由数据加载器完成的。列表中的每个项目都是数据集中的一个项目或 x,y 对,可以从数据集类中的 getitem()函数中检索到。批处理的输出必须以稍微不同的方式构建。当您将一批数据发送到模型中时,例如,如果您的批量大小为 16,则模型的输入张量将被构造为一个列表/张量中的 16 个单独的输入,而标签/输出张量将是 16 个单独的标签。因为我们覆盖了 collate 函数,所以我们必须手动完成这个过程。如果我们没有覆盖 collate 函数,那么 Dataloader 将通过默认的 collate 函数自动完成这项工作。

collate 函数的输入结构如下:

(input1, label1), 
(input2, label2), 
(input3, label3), 
(input4, label4), 
(input5, label5)

如果批量大小为 5。我们从 collate 函数返回的输出应该是这样的结构:

(input1, input2, input3, input4, input5), 
(label1, label2, label3, label4, label5)

假设我正在做一个 NLP 任务。如果我试图将一批中的标记化句子填充到相同的长度(假设是该批中最长句子的长度),那么我会这样做:

class MyCollate():
  def __call__(self, batch):
    ## find maximum length of a sentence
    max_len = 0
    for item in batch:
       max_len = max(max_len, len(item[0]))
    new_input = []
    new_label = [] 
    for item in batch:
       ## pad all items in batch to max_len
       val = item[0]
       val = pad(val, max_len) 
       ##pad is the function you should create
       new_input.append(val)
       new_label.append(item[1])
    new_input = torch.tensor(new_input)
    new_label = torch.tensor(new_label)
    return new_input, new_label

要将校对功能与您的数据加载器集成,只需执行以下操作:

data = MyDataSet(parameters here)
data.build_dataset()dataloader = DataLoader(dataset = data, batch_size = batchsize, shuffle=True, collate_fn = MyCollate())

shuffle=true 参数只是在创建批处理之前随机打乱数据集中的数据。通常的做法是混洗训练数据加载器的数据,而不是验证和测试数据加载器的数据。关于所有 PyTorch 机器学习项目,需要记住的一点是,模型只能接受张量形式的输入,这就是我在上面的代码片段中返回输入和标签列表之前,将它们都转换为张量的原因。

需要记住的重要一点是,用于在 getitem 函数和 collate 中存储数据的数据结构必须相同,并且它们的大小也必须相同。如果在 getitem 函数中返回一个包含 5 个键值对的字典,则必须在 collate 中返回相同的键。这些值会有所不同,因为您已经对该批数据做了一些预处理。正如我之前提到的,返回的批次的结构会有所不同。如果在 getitem 函数中使用了字典,调用函数的输入将是

{keys:values}, 
{keys:values}, 
{keys:values}, 
{keys:values}, 
{keys:values}

如果批量大小为 5。每批的密钥都是相同的。返回的输出结构将是

{key1: all values for key1}, 
{key2: all values for key2},
{key3: all values for key3},
{key4: all values for key4},
{key5: all values for key5}

在大多数机器学习项目中,您通常需要三个不同的数据加载器:一个用于训练循环、验证循环和测试循环。在 PyTorch 中实现这一点非常简单:

from torch.utils.data.dataset import random_splitdata = MyDataset()
data.build_dataset()train_len = int(0.7 * len(dataset))
test_len = len(dataset) - train_len
train_data, test_data = random_split(dataset, (train_len, test_len))
val_len = int(0.33 * len(test_data))
test_len = len(test_data) - val_len
test_data, val_data = random_split(test_data, (test_len, val_len))train_loader = DataLoader(dataset = train_data, batch_size = batchsize, shuffle = True, collate_fn = MyCollate())test_loader = DataLoader(dataset = test_data, batch_size = batchsize, shuffle = False, collate_fn = MyCollate())val_loader = DataLoader(dataset = val_data, batch_size = batchsize, shuffle = False, collate_fn = MyCollate())

您只需使用 PyTorch 提供的 random_split 函数将原始数据集分割成任意数量的部分。我将上面的数据集分成 70%的训练、20%的测试和 10%的验证。在创建每个数据集之后,您可以简单地将它们传递给自己的数据加载器,并定期使用它们。

3.创建培训、验证和测试循环

PyTorch 中的训练、验证和测试循环相当简单,也很相似。以下是创建训练循环的方法:

model = model.to(device)
model = model.train()
for index, batch in enumerate(train_loader):
    x = batch[0].to(device)
    y = batch[1].to(device)
    optimizer.zero_grad()
    output = model(x).to(device)
    loss = criterion(output, y).to(device)
    loss.backward()
    optimizer.step()

下面是如何创建一个验证/测试循环(它们是同一个东西,但是有不同的数据加载器)。

model = model.to(device)
model = model.eval()with torch.no_grad():
    for index, batch in enumerate(train_loader):
        x = batch[0].to(device)
        y = batch[1].to(device)
        output = model(x).to(device)
        loss = criterion(output, y).to(device) 

优化器是你选择的优化器(我通常选择 Adam),准则是我通常给我的损失函数起的名字。您必须预先对它们进行初始化,以下是您的操作方法:

import torch.optim as optim
import torch.nn as nnlearning_rate = 1e-3optimizer = optim.Adam(model.parameters(), lr = learning_rate)
criterion = nn.BCEwithLogitsLoss()##you can use any loss function

我们必须在验证/测试循环中指定 with torch.no_grad(),以确保 PyTorch 不会计算反向传播的梯度,因为我们在这里不进行反向传播。如果你不包含这段代码,你的程序仍然可以工作,但是它将消耗更多的内存,因为 PyTorch 将计算和存储我们甚至不会使用的模型的梯度。

关于训练和测试循环,需要指出的一件重要的事情是,即使我将 x = batch[0]和 y = batch[1],您也不需要像这样明确地构造模型的输入(作为一个元组),特别是如果您使用了不同的数据结构。您只需要确保从在 collate 中的 getitem 函数和 call 函数中使用的数据结构中正确地检索数据。需要注意的一点是,某些损失函数需要输出的特定形状/尺寸和 y/标签,因此在从模型中获得输出后,请确保对其进行整形,然后将其发送到损失函数或我在上面命名的标准中。

还有一件重要的事情要记住,你需要把。除了优化器和训练循环中的损失。这将把你的张量和数据放到你指定的设备上。如果您不知道如何创建设备,以下是方法:

device = torch.device('cuda' if torch.cuda.is_available() else "cpu")

如果你有一个 GPU,那么设备将自动成为一个 GPU。不然就是 CPU 了。

完成 PyTorch 项目设置的最后一步是将前面的三个步骤结合起来。创建一个初始化所有需要的东西的函数,一个训练模型的函数,一个评估模型的函数。然后你只需要把所有的东西组合在一起,这相对来说比较简单。

您还应该记得将模型权重保存到文件中。除了将模型权重保存到文件中,我还保存了优化器权重。您可以像这样保存模型/优化器权重:

model = Model(parameters here
optimizer = optim.Adam(model.parameters(), lr = learning_rate)
save_dict = {'Optimizer_state_dict': optimizer.state_dict(), 
             'Model_state_dict': model.state_dict()}
torch.save(save_dict, file_path)

加载模型也非常容易。

load_dict = torch.load(file_path)
model.load_state_dict(load_dict['Model_state_dict'])
optimizer.load_state_dict(load_dict['Optimizer_state_dict'])

我希望你觉得这篇文章简单易懂,内容丰富。如果你有任何问题,请在下面的评论中提出。

如何建立法律合同审查的机器学习模型

原文:https://towardsdatascience.com/how-to-set-up-a-machine-learning-model-for-legal-contract-review-fe3b48b05a0e?source=collection_archive---------8-----------------------

行业笔记

深入研究新发布的自然语言处理数据集,以了解合同

合同审查是彻底阅读合同以理解签署合同的个人或公司的权利和义务并评估相关影响的过程。人们普遍认为这是初级律师事务所合伙人必须做的最重复、最乏味的工作之一。这也很昂贵,而且是对法律专业人员技能的低效利用。在这篇博文中,我展示了如何建立一个新发布的数据集和相关的机器学习模型来自动化合同审查。

斯科特·格雷厄姆Unsplash 上拍照

合同评审需要什么?

谈到合同审查,律师的工作就是手动审查数百页的合同,以找到合同中规定的相关条款或义务。这是重复的,因为他们总是需要在任何给定的合同中识别相同的数据点:合同的生效日期是什么?续约条款是什么?谁参与了这个合同?

律师事务所面临着降低成本的巨大压力,尤其是在 COVID 时代期间和之后。随着自然语言处理(NLP)的最新进展,机器学习模型可以学习自动提取和识别合同中的关键条款,从而节省数百小时的人工劳动。

什么是 CUAD 数据集?

2021 年 3 月, Atticus 项目发布了合同理解 Atticus 数据集(CUAD),该数据集由 500 多份合同组成,每份合同都由法律专家仔细标记,以确定 41 种不同类型的重要条款,总共有 13,000 多条注释。除了数据集,他们还发布了几个经过数据集训练的最先进的变压器模型。你可以在他们的 GitHub repo 找到数据集和训练代码,微调后的模型可以从 Zenodo 下载。

在这篇文章中,我将带你一步一步地建立和运行微调后的模型,这样你就可以用它们来做你自己的预测。

数据准备

你应该可以在你自己的机器上运行这个例子,因为它不是很耗费资源,我们也不需要模型的毫秒级响应。我用的所有代码和笔记本都可以在我的 GitHub repo 里找到。

在第一个笔记本中,1 _ preparation . ipynb,我运行一组 shell 命令来下载数据、代码、模型和库。相反,您可以在终端中轻松运行这些命令。

出于这个博客的目的,我使用的是 roberta-base 模型,它是最小的,但也是表现第三好的模型。当然,你可以选择使用性能更好的 roberta-large 型号或 deberta-v2-xlarge 型号。无论选择哪种模型,加载模型和进行预测的指令都是相同的。所有型号均可在此下载

运行这些命令后,您的主项目文件夹中应该有以下三个文件夹: cuad-data/ ,其中包含实际的 cuad 数据集,cuad-models/ ,其中包含模型,和 cuad-training/ ,其中包含用于训练模型的 Python 脚本和 shell 脚本。

CUAD 演示的文件夹结构

加载模型

查看 cuad-training/train.py 中的训练代码,我们可以看到 cuad 模型基于 AutoModelForQuestionAnswering 类,该类是专门为问答任务训练的。这是有意义的,因为我们希望模型通过问它一个问题来识别合同的某些部分(例如,“合同的日期是什么?”).

有了这些知识,我们可以像这样加载模型和它的记号化器(为模型准备输入):

注意,我们将 use_fast 参数设置为 False 。原因是问答(Q & A)模型与具有更智能的溢出处理的快速标记化器不兼容。这完全符合我们的目的,我们只需要记住相应地设置参数。

既然我们已经加载了模型,我们可以用一个样本快速测试它。CUAD 团队提供 JSON 文件中的合同和相关查询数据。41 个查询的完整列表可在此处查看。现在,我们可以使用数据集中的一个契约和查询来测试刚刚加载的模型:

这段代码从 JSON 文件加载第三个查询,询问“合同的日期是什么?”,并显示该合同的前 100 个单词:

查询和签约。我强调了合同中的相关部分。

进行第一次测试预测

问答模型的工作方式是将问题和契约连接在一起(用一个特殊的标记分开),标记化(即准备输入以便模型可以理解),然后输入到模型中。然后,该模型将提供两个输出:开始逻辑和结束逻辑。

开始逻辑描述了字符串中每个单词成为问题答案开始的概率。类似地,结尾逻辑描述了每个单词成为答案结尾的概率。

为了从模型中获得最佳预测,我们现在要做的就是选择具有最高概率的开始和结束标记。

这一切听起来有点抽象,所以我包含了以下两个图表来澄清。第一个图表描述了契约中的每个标记成为答案的开始标记的概率,第二个图表描述了除结束标记之外的相同情况:

每个标记成为开始标记的概率

每个标记成为结束标记的概率

通过分别挑选具有最高概率的两个记号,我们检索总体上具有最高概率的模型预测:

模型预测法

完整代码可以在笔记本2 _ loading _ model . ipynb中找到。

摘要

在这篇博文中,我们介绍了自动化合同审查的挑战以及帮助应对这一挑战的 CUAD 数据集。我们已经下载了数据集并加载了相关的微调模型。然后,我们创建了第一个示例查询,以确保模型正确运行。我们已经查看了模型的输出,并确定了提取模型预测的简单方法。

后续步骤

我们在这里还没有完成:虽然我们现在已经建立并运行了模型,但是我们的方法对于在生产中实际使用来说有点太简单了。首先,您可能已经问过自己:“如果模型预测到一个结束标记在契约中的开始标记之前,该怎么办?”这是一个合理的问题,因为开始和结束标记是由模型独立预测的,所以我们必须实现一些逻辑来解决这个问题。

我们当前方法的另一个限制并不明显,但与问答模型的底层架构有关。这些模型中的大多数,包括这一个,只能接受 512 个令牌(大致相当于 512 个单词),这包括问题和契约的组合。但是这对于我们的用例来说是行不通的:大多数合同都比 512 个单词长得多,例如,特定合同评审查询的答案可能在合同的第 27 页。

在以后的博客文章中,我们将看看如何克服这些限制,以及如何为这个演示设置一个用户友好的 UI。

【2021 年 4 月 13 日编辑: 第二部 现已出版!】

如何为法律合同审查建立机器学习模型—第二部分

原文:https://towardsdatascience.com/how-to-set-up-a-machine-learning-model-for-legal-contract-review-part-2-6ecbbe680ba?source=collection_archive---------17-----------------------

克服臭名昭著的 512 令牌限制

Raphael SchallerUnsplash 拍摄的照片

这是怎么回事?

之前的一篇博文中,我们看了如何开始使用新发布的 CUAD 数据集,它有助于自动化合同审查。我们加载了模型,并对一份合同的简短摘录(前 100 个单词)进行了第一次预测。正如文章中提到的,我们用于这项任务的 NLP 模型通常有 512 个单词的限制。这意味着我们建立的模型不能扫描整个合同的信息。相反,它只限于少于 512 个字的合同摘录。

在这篇博文中,我们将看看如何克服这一限制,以便该模型可以在整个合同中搜索律师感兴趣的关键信息。

边注:技术上来说,限制不是 512 个字,而是 512 个令牌。记号是自然语言的组成部分,因此也是 NLP 模型的组成部分。它们通常通过将单词分成子单词来表示:

单词“Highlight”的标记。第一个和最后一个标记是特殊的标记,用于标识文本的开始和结束。

出于我们的目的,这种技术上的区别在很大程度上是不相关的,我将在本文中互换使用术语令牌单词

我们试图解决的问题是什么?

上次我们在合同的前 100 个字内搜索了一条特定的信息(合同日期)。这很有效,因为我们在 512 字的限制之内。但是,如果我们试图在整个合同中查找这些信息,我们将会超出这个限制。在这种情况下,我们会收到如下所示的错误消息:

合同过长时的错误消息

错误消息通知我们,合同的令牌数(7,548)超过了该模型允许的最大长度 512。

对于许多类似的问答(Q&A)模型来说,这不是问题。这是因为这些问答对中的相关段落要么少于 512 个单词,要么这些段落被截断以符合单词限制,而不会丢失关键信息。这些类型的问答任务的示例可以在斯坦福问答数据集(SQUAD) 中找到。比如这些关于南加州的段落都短于 512 个字。

一份合同有多少字?

对于法律合同,情况就大不相同了。查看 CUAD 数据集中包含的合同,我们发现只有 3.1%的合同短于 512 个单词。

标识有多少合同短于 512 个字的代码。对于 CUAD 数据集,这将是 3.1%。

我们还可以看到,通过绘制合同长度直方图,我们将遇到大多数合同的 512 字限制:

按长度划分的合同

克服 512 字的限制

为了克服这个限制,合同必须被分成 512 个单词的几个部分。然后,该模型可以单独分析每个部分,并汇总结果以得出最终预测。幸运的是,当模型在 CUAD 数据集中的合同上训练时,程序员们必须克服同样的挑战。这意味着,通过识别训练代码中的相关代码段,我们可以对我们的预测任务使用相同的逻辑。我已经用一个 Python 脚本编译了相关的代码片段。在这一节中,我将介绍这个脚本的关键部分。

将问题和契约转换成模型接受的特性的函数是一个名为squad _ convert _ examples _ to _ features()的函数。它的文档和它的实现可以在 Huggingface 网站找到。正如我们从文档中看到的,该函数将一系列问题和合同转换为模型的特性:

将问题和合同转换为模型的特征

然后将生成的要素加载到数据加载器中,并批量输入到模型中。该模型预测开始和结束逻辑,就像我们在第一篇博文中看到的例子一样:

对合同块进行预测

由此产生的开始和结束逻辑适用于合同的各个部分,必须总结为一个最终的模型预测。为此,我们可以利用函数compute _ predictions _ logits():

为了最终的预测,把所有的东西集合在一起

结论

在这篇博文中,我们克服了合同评审 NLP 模型的 512 字限制。这很重要,因为律师在合同中寻找的关键信息可能在文件中的任何地方,正如我们所看到的,大多数合同都比 512 个字长得多。

克服这一限制的代码封装在这个脚本中。在本笔记本中可以找到一个示例,说明如何利用该脚本来回答关于样本合同的 CUAD 数据集的所有 41 个问题。该笔记本的输出包含所有 41 个问题和相应的模型预测。它相当长,所以我将模型预测保存在这个文本文件中,以便于查看。

前 5 个问题和模型预测

有了这些资源,你现在可以自己设计一个法律合同评审模型了。您可以上传一个文本格式的合同,然后运行模型来查找合同中的关键信息,就像我们在这里所做的一样。

在以后的博客文章中,我们将看看如何用 Streamlit 建立一个合同评审的演示网站。这将使得上传合同和使用易于使用的 web 界面运行模型变得更加容易,非常类似于这个例子。

如何使用 Application Factory 模式和 Celery 建立生产级的烧瓶应用程序

原文:https://towardsdatascience.com/how-to-set-up-a-production-grade-flask-application-using-application-factory-pattern-and-celery-90281349fb7a?source=collection_archive---------3-----------------------

使用 flask blueprints、application factory 模式和 Celery 构建和配置生产级 flask 应用程序的高适应性和可伸缩性工作流。

照片由威尔·波拉达Unsplash 拍摄

免责声明

这不是初学者教程。假设读者已经熟悉 flask web 应用程序框架、其常用的库和 celery。

基础

  1. 为您的项目创建一个 github 存储库,并使用 README 和 python 对其进行初始化。gitignore 文件。
  2. 将 git repo 克隆到您的本地机器上
$ git clone <repo link>

3.创建一个虚拟环境,并安装 flask 和您需要的任何其他库

$ python -m venv env
$ env/Scripts/activate
$ pip install flask python-dotenv flask-mail celery redis
$ pip freeze > requirements.txt

项目结构:烧瓶蓝图

什么是蓝图?

Flask 是一个非常灵活的 web 开发框架。作为开发人员,您可以完全自主地决定如何构建您的 web 应用程序。如果您正在构建一个小项目,将所有代码放在一个模块中没有坏处。然而,大型项目普遍接受的模式是使用 Flask Blueprints 将您的项目分成多个包。

一个模块是一个单独的.py python 文件。包是包含一个或多个模块以及一个__init__.py文件的文件夹。__init__.py文件是区分包和标准文件夹的地方:如果它存在于一个文件夹中,那么这个文件夹就是一个包;如果不存在,则该文件夹只是一个普通的存储文件夹。

蓝图是封装了应用程序中某个特定功能的包。您应该将使用蓝图构建的 flask 应用程序视为几个关键的功能块,它们协同工作来交付完整的 web 应用程序。

flask 应用程序由蓝图(作者自己的)组成

在开始编写项目代码之前,最好先考虑一下可以将应用程序分成哪些蓝图。我个人的做法是用两个蓝图,authmainauth蓝图处理所有与用户相关的功能——注册、登录、注销、密码重置和账户确认。main蓝图处理应用程序特有的功能和特性。您还可以添加第三个蓝图api,用于处理对 web 应用程序资源的编程访问。

您应该为具有两个蓝图的项目创建以下项目结构:

|-application.py
|-config.py
|-.env
|-.gitignore
|-readme.md
|-requirements.txt
|-celery_worker.py
|-Dockerfile
|-docker-compose.yml
|-pytest.ini
|-env/
|-tests/
    |-conftest.py
    |-test_main.py
    |-test_auth.py
    |-test_models.py
|-app/
    |-__init__.py
    |-models.py
    |-forms.py
    |-tasks.py
    |-static/
    |-templates/
        |-base.html
        |-400.html
        |-403.html
        |-404.html
        |-405.html
        |-500.html
    |-auth/
        |-__init__.py
        |-views.py
        |-forms.py
        |-templates/auth
            |-register.html
    |-main/
        |-__init__.py
        |-views.py
        |-forms.py
        |-templates/mai
            |-index.html

下表给出了各种组件的概要:

flask 应用程序中的公共文件(作者自己的)

当您使用蓝图时,处理请求的视图函数不会都在一个文件中;它们将被拆分到不同的文件中。每个蓝图都有自己的views.py文件,包含属于它的代码。这些路径没有一个@app装饰器,而是用它们所属的蓝图名称来装饰,例如@auth_blueprint.route('/login')

一旦你将你的项目组织成蓝图,而不是服务器将请求传递给 flask 应用实例来处理,请求被推送到适当的蓝图,蓝图处理它们。为了让 flask 应用程序实例知道项目中的蓝图和属于它的路线,蓝图必须向 flask 应用程序实例“注册”。

结构管理

配置 flask 应用程序是指定关键参数值的过程,这些参数用于控制 flask 应用程序实例及其扩展的行为。关于这个主题的官方 flask 文档提供了一个很好的列表,列出了所有内置的 flask 变量,可以根据需要进行配置。

配置方法

Flask 提供了 4 种配置 flask 应用程序的主要方式:环境变量、flask 应用程序实例的 config 属性、CFG 文件和对象。

*环境变量

当您想要设置一两个配置参数时,使用环境变量是最简单的配置方法。要设置参数,您可以运行set(对于 Windows)或export(对于 Linux)命令。Flask 建议您使用此方法设置FLASK_APPFLASK_ENV环境变量,以便能够使用flask run命令在调试模式下启动 flask development server。

$set FLASK_APP = app.py
$set FLASK_ENV = development

使用环境变量来配置关键参数很简单,但是当您有许多参数或者当您想要使用具有不同配置设置的多个环境时,就不能很好地扩展。

*** flask app 实例的配置属性**

flask 应用程序实例公开了一个类似字典的对象,称为“config ”,通过点符号访问,它允许您将配置变量设置为所需的值,就像您设置字典键的值一样。当使用这个对象时,所有的配置代码都在 flask 对象实例化后立即编写。这是因为配置设置需要在 flask 应用程序实例化时可用,以便它可以在运行之前正确配置。

app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess
app.config**[**'TESTING'**]** = Trueapp.config['MAIL_SERVER'] = 'smtp.googlemail.com'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USE_TLS'] = True
app.config['MAIL_USERNAME'] = os.environ.get('MAIL_USERNAME')
app.config['MAIL_PASSWORD'] = os.environ.get('MAIL_PASSWORD')

尽管在实例化 flask 对象的脚本中包含所有配置代码并不灵活。当 flask 对象被实例化时,它会立即根据这些设置进行配置,并且在实例化之后,无法更改 flask 实例的配置。

当您希望基于您正在做的事情拥有不同的应用程序“版本”时,这就成了一个问题。也就是说,当您处于开发阶段时,您需要一个配置用于开发的 flask 应用程序;当您想要进行测试时,您需要一个配置用于测试的 flask 应用程序;当您准备好进行部署时,您需要一个配置用于生产的 flask 应用程序。

也许您在开发过程中使用了 SQLite,但在生产中想要使用 postgreSQL 数据库。或者,您希望使用不同的 SQLite 数据库文件进行开发、测试和生产,以便将事情分开,使它们不会相互干扰。能够为不同的环境配置不同的 flask 应用程序是实现这一点的唯一方法。

*一个 CFG 文件

不要把所有的配置代码都放在实例化 flask 对象的脚本中,可以把它写在一个单独的配置文件中,然后告诉 config 对象使用它公开的from_pyfile()方法从那个文件中提取配置设置。此方法采用的参数是文件的路径,它可以是相对于项目根目录的路径,也可以是文件的绝对路径。这种方法扩展性很好,但是不允许为不同的环境指定不同的配置设置。

名为 config.cfg 的配置文件的内容示例如下:

DEBUG = **False**
SECRET_KEY = 'a bad secret key'

使用存储在根项目目录中的 config.cfg 文件配置 flask 应用程序:

app = Flask(__name__)
app.config.from_pyfile('config.cfg')

*一个物体

配置 flask 应用程序的方法是在一组 python 类中定义配置设置,该应用程序既具有良好的可伸缩性,又允许您为不同的环境指定不同的配置设置。

在位于项目根目录的名为 settings.pyconfig.py 的 python 脚本文件中,您定义了 4 个类:

  • class Config(object),它是基本配置类,包含适用于所有环境的配置设置。其他 3 个类都继承了这个类。
  • 类 DevelopmentConfig(Config),它包含开发环境的配置设置。
  • 类 TestingConfig(Config),它包含测试环境的配置设置。
  • class ProductionConfig(Config),它包含生产环境的配置设置。

要使用 config.py/ settings . py 文件配置 flask 应用程序实例,您可以使用 config 对象公开的from_object()方法。此方法采用的参数指示配置脚本的名称和应该从中加载配置数据的类。假设您的配置脚本名为 config.py,在开发阶段,您可能希望从 DevelopmentConfig 类加载配置数据。完成此操作的方法如下所示:

app = Flask(__name__)
app.config.from_object('config.DevelopmentConfig')

生产级烧瓶应用程序的配置方式

实际上,有一些参数,比如密钥、邮件服务器用户名和密码,以及许多其他参数的值,出于安全原因,您不希望在 config.py 文件中显式地硬编码。

最终发生的是 flask 应用程序使用环境变量方法和对象方法的组合进行配置。使用环境变量方法在环境中设置敏感参数,然后使用os.environ.get()方法将其导入 config.py 文件。如果环境没有为参数提供值,则会提供默认值。非敏感参数在 config.py 文件中显式定义。

如果您不想像前面解释的那样使用终端设置环境变量,有一个漂亮的小 python 包叫做python-dotenv。一旦安装了这个包,您就可以在项目根目录下创建一个.env文件,并在其中定义所有的环境变量。然后,通过调用load_dotenv()方法,告诉 config.py 文件从.env文件加载环境配置设置。如果你使用这种方法,你需要记住将.env文件添加到.gitignore文件中。

在您的.env文件中:

在您的config.py文件中:

定义你的蓝图

每个蓝图必须有一个__init__.py文件。在这个文件中,通过实例化 blueprint 类的一个实例来定义 Blueprint。传递给类构造函数的参数是蓝图的名称和包含属于蓝图的模板的文件夹的名称。然后,您需要导入与该蓝图相关联的路由,这些路由写在与__init__.py模块位于同一目录的views.py中。

app/auth/__init__.py中:

app/main/__init__.py中:

出于测试目的,您需要编写一些初始代码,以确保一切设置正确。

使用蓝图时:

  • 确保用于定义任何路由的装饰器使用 blueprint 对象。
  • 确保render_template()函数参数采用blueprint_name/template_name.html的形式。这样做是为了反映一个事实,即一个蓝图只能呈现属于它的模板。
  • 确保url_for()功能引用了与视图功能相关的蓝图。这样做是为了反映视图功能属于特定蓝图的事实。url_for(auth.login)
  • 您对app对象的任何引用都需要由current_app对象替换。这是因为当您使用蓝图时,您不再能够直接访问 flask 应用程序实例。你只能通过它的代理人current_app来访问它。
  • 如果您在蓝图注册中为蓝图指定了一个前缀,那么视图函数 decorator 中的 route 不会得到那个前缀(也就是说,decorator 不是您所想的@auth_blueprint.route('/users/login'))。但是,从客户端收到的路由请求必须包含前缀,否则服务器将返回 404 错误。
  • 在蓝图的目录中,您需要创建一个 templates 文件夹,然后在该 templates 文件夹中创建另一个以蓝图命名的文件夹。与蓝图关联的模板存储在以蓝图命名的目录中。这种方法是存储与蓝图视图功能相关的模板的建议方式。
|project  
    |-auth
        |-templates
            |-auth

app/auth/views.py:

app/auth/templates/auth/register.html中:

app/main/views.py中:

app/main/templates/main/index.html中:

应用程序工厂模式

通常,flask 应用程序是用全局范围实例化的。这意味着当您运行 flask 应用程序脚本时,flask 应用程序会立即被实例化和配置。不幸的是,一旦它开始运行,就没有办法改变它的配置设置。

这不是理想的行为。您希望能够创建针对不同环境(开发、测试或生产)配置的同一 flask 应用程序的不同版本。

一种解决方案是将 flask 应用程序的实例化和配置转移到一个函数中。使用应用程序工厂函数,然后在想要创建 flask 应用程序实例时调用它的方法实际上是一种众所周知的设计模式,称为工厂方法模式。使用配置 flask 应用程序的应用程序工厂模式方法使您能够在实例化 flask 应用程序之前定义它的配置。基本上,您需要为 flask 应用程序设置的所有内容都在应用程序工厂函数中定义,这样它会返回一个完全按照您的喜好设置和配置的 flask 应用程序实例。

定义 flask app 实例化的函数称为应用工厂函数(因为它在文学上用于生产许多 flask 应用程序,就像一个工厂用于生产许多产品一样)。它是在项目包的app/__init__.py模块中定义的。然后它在项目的application.py模块中被实例化。

应用程序工厂函数中定义的所有内容的摘要:

  1. Flask 应用实例化
  2. 烧瓶应用配置
  3. 烧瓶扩展实例化和初始化
  4. 蓝图的注册
  5. 请求回调的注册
  6. 应用程序范围错误处理程序的注册
  7. 日志记录配置

登记蓝图

蓝图是通过将蓝图对象传递给 flask 应用程序实例公开的register_blueprint()方法来注册的。该方法接受第二个可选参数,这是一个前缀,所有与蓝图相关联的 URL 都应该以它开头。在下面的例子中,授权蓝图的前缀是/users。这意味着,例如,要访问登录页面,用户必须请求/users/login路线。

app/__init__.py中:

application.py中:

要测试一切以确保蓝图设置正确,请在终端中运行以下命令:

$ flask run

当您导航到 http://127.0.0.1:5000/ 时,您应该会看到“Hello world from the main blue!”

当您导航到http://127 . 0 . 0 . 1:5000/users/register/you-email-address @ Gmail . com时,您应该会看到“您好,您的电子邮件地址 @gmail.com ,来自认证蓝图!”

记录

什么是日志记录,为什么它很重要?

日志记录是记录应用程序信息的过程。它用于在事件发生时记录事件,是调试任何问题和深入了解应用程序如何工作的绝佳工具。

您应该记录的内容包括:

  • 与用户相关的事件,如注册、登录、注销、不正确的密码尝试
  • 特定于应用程序功能的事件(例如,对于一个博客,它可以发布一个新的博客或添加一个评论)
  • 错误,包括特定于应用程序的错误以及数据库操作错误。

您不应该在日志中存储任何敏感数据,因为它们通常存储为文本文件,因此不安全。

日志模块

Flask 使用标准的 python 日志模块。日志模块有 4 个子模块,可以通过点符号访问:记录器、处理程序、过滤器和格式化程序。

记录器是创建日志消息的对象。创建日志消息时,必须使用与重要程度级别相关的函数来指定其重要程度。关键级别(又名日志级别)、其数字表示以及与其相关的功能如下:

  • 调试→ 10 →调试()
  • 信息→ 20 →信息()
  • 警告→ 30 →警告()
  • 错误→ 40 →错误()
  • 临界→ 50 →临界()

有一个默认的 logger 对象,无需任何配置就可以访问和使用它。每个 flask 实例通过app.logger对象公开它。如果您正在使用蓝图,那么您必须通过current_app对象来访问它,这个对象是 flask 应用程序实例的代理。

在你的app/main/views.py:

不幸的是,默认记录器只打印到控制台。因此,如果您想记录到一个文件,您需要配置一个新的记录器实例。默认记录器仍将继续记录,但您可以选择禁用它:

from flask.logging import default_handlerapp.logger.removeHandler(default_handler)

当您配置新的记录器实例时,您可以指定应该记录的消息的最低重要级别。所有重要程度为该值或更高的日志消息都将被记录,任何重要程度值低于该值的日志消息都不会被记录。这在您希望减少日志消息的数量而不从源代码中删除日志调用的情况下非常有用。您可以增加要写入日志的消息的最低日志级别,例如:错误消息及以上。

处理程序是将日志消息指向正确目的地的对象。默认的处理程序称为流处理程序,它向终端发送日志消息。您可以创建不同的处理程序对象来将日志消息路由到不同的目的地。

  • 要记录到一个文件中,你需要使用一个文件处理程序。要将日志消息作为电子邮件发送,您可以使用 SMTPHandler。
  • FileHandler 方法接受要写入的日志文件的路径,包括其名称,并实例化一个 FileHandler 对象,该对象将向该文件发送日志消息。
  • 实例文件夹通常用于存储运行时运行的文件(日志和数据库文件)。此文件夹需要添加到您的。gitignore 文件,这样它就不会被版本控制跟踪。
file_handler = logging.FileHandler('instance/my-app-log.log')app.logger.addHandler(file_handler)
  • FileHandler 对象将日志消息写入单个日志文件。这可能会导致日志文件很快变大。更好的方法是使用 RotatingFileHandler 对象。它还将日志消息写入文件,但是每当当前日志文件超过指定的文件大小(maxBytes)时,它都会创建一个新的日志文件。在开始覆盖现有文件之前,它将创建一个达到指定文件数(backupCount)的新文件。
from logging.handlers import RotatingFileHandlerfile_handler = RotatingFileHandler('instance/scrub-my-list.log', maxBytes=16384, backupCount=20)

过滤器用于向日志消息添加上下文信息。例如,在记录请求时,您可以创建一个过滤器,添加请求来自的远程 IP 地址。

日志格式器用于指定日志消息的格式。每个日志消息都是一个 LogRecord 对象。日志格式化程序用于指定要显示日志记录的哪些属性以及它们应该显示的顺序。

日志记录的常见属性包括:

  • %(asctime)s -创建日志记录的日期时间
  • %(filename)s -路径名的文件名部分
  • %(funcName)s -包含日志调用的函数名
  • %(levelname)s -消息的记录级别
  • %(lineno)d -发出日志记录调用的源代码的行号(如果可用)
  • %(message)s -记录的消息
  • %(module)s -发出记录调用的模块

如何配置日志记录

您应该在创建 flask 应用程序实例之前配置日志记录,否则它将使用默认的处理程序将日志消息写入控制台。这就是在应用程序工厂函数中配置日志记录的原因。

配置日志记录所需的步骤:

  1. 导入日志库。可选:从logging.handlers导入default_handler
  2. 实例化一个处理程序对象。
  3. 使用 handler 对象公开的setLevel()方法设置其日志记录级别。
  4. 实例化一个格式化程序对象。
  5. 使用 handler 对象公开的setFormatter()方法将 Formatter 对象添加到 handler 对象。
  6. 使用 logger 公开的addHandler()方法将 handler 对象添加到 logger。
  7. 停用默认处理程序

app/__init__.py中:

重新启动 flask development 服务器并导航到索引页面。

应该在顶层项目目录中创建一个新文件flaskapp.log。如果打开它,您应该会看到以下日志消息:

2021-05-14 16:14:31,910 INFO: Index page loading [in views.py: 6]

自定义错误处理

HTTP 状态代码

当客户端向 web 服务器发出请求时,响应消息包含 HTTP 状态代码。这是一个 3 位数,表示处理请求的结果。状态代码根据第一个数字分为 5 个类别,每个类别代表一种响应类型:

  1. 1xx —信息响应
  2. 2xx —成功的 eg
  • 200 (OK),用于成功处理请求

3.3xx —重定向

  • 302(找到),成功地将客户端重定向到一个新的 URL

4.4xx —客户端错误

  • 400(坏请求):当客户端提出服务器无法理解或不允许的请求时。
  • 403(禁止):当客户端试图访问受限制的资源,但没有这样做的授权。
  • 404(未找到):当客户端请求服务器无法识别的 URL 时。给出的错误消息应该是这样的:“对不起,您要找的东西不在这里!”。
  • 405(不允许方法):当处理给定路由请求的视图函数不接受请求方法时。给出的错误消息应该类似于“对不起,该资源不支持所请求的方法!”。

5.5xx —服务器错误

  • 500(内部服务器错误):通常由于编程错误或服务器过载而发生。

如何创建自定义错误页面

您通常希望为 403、404、405 和 500 错误定义自己的自定义错误页面,以便:

  • 错误页面可以与 web 应用程序的其余部分具有相同的外观。通过使用一个扩展 base.html 的模板,错误页面将拥有和其他网页一样的导航栏和页脚。
  • 您可以提供导航链接,使用户更容易导航回应用程序。

步骤 1:为错误代码定义一个模板文件,并将其保存在保存 base.html 文件的 templates 文件夹中。

未找到页面的自定义错误模板示例如下所示。您需要为 400、403、404、405 和 500 定义自定义错误处理程序模板。

在您的app/templates/base.html文件中:

在您的app/templates/404.html文件中:

第二步:为每个错误代码定义一个错误处理程序。

错误处理程序是在错误发生时呈现错误模板的函数。你可以给它起任何你想要的名字,它必须用@app.errorhandler()装饰。这个装饰器将它必须处理的错误的状态代码作为参数。

自定义错误处理程序的语法如下所示:

@app.errorhandler(status_code)
def function_name(error):
    # You can log the error or send an email here
    return render_template("status_code.html"), status_code

当您使用应用程序工厂方法时,所有的错误处理函数都在一个帮助函数register_error_pages()中定义。这个函数在应用程序工厂函数中被调用,并一次注册所有的错误处理程序。在create_app()函数之外定义错误处理程序很有用,这样可以保持干净,但仍然能够让 flask 应用程序实例知道错误处理程序。

在你的app/__init__.py文件中:

这个设置向 flask 应用程序实例注册了自定义错误处理程序。蓝图也支持errorhandler()装饰器,这意味着您可以用蓝图注册错误处理程序。然而,不建议使用这种注册自定义错误处理程序的方式,因为它不能被其他蓝图使用。最好向应用程序实例注册错误处理程序,以便它们可以查看所有蓝图中所有视图功能使用的视图。

为了测试定制的错误处理程序,Flask 提供了一个abort()函数,可以用来手动抛出错误。它将您想要抛出的错误的状态代码作为参数。将显示该错误的默认错误页面,但这很简单。

在你的app/main/views.py:

如果已经注册了该错误的错误处理程序,将调用它来显示自定义错误页,而不是默认页。

重新启动 flask 开发服务器。导航到http://127 . 0 . 0 . 1:5000/admin,您应该会看到定制的错误消息。将abort()函数的参数改为 403、404、405,最后改为 500,以确保所有自定义错误页面都被正确呈现。

芹菜

芹菜是什么?

Celery 是一个基于分布式消息传递的开源异步任务队列。尽管它支持调度,但它最常用于异步任务处理。当您的应用程序有长时间运行的任务(如处理数据、生成报告或发送电子邮件等网络相关任务)时,您最好在后台运行这些任务,而不是在与请求相同的流程中运行它们。

分布式消息传递系统有三个组件:

  • 发布后台作业的发布者(芹菜客户端。celery 客户端运行 flask 应用程序)
  • 消息代理/队列(通常是 Redis 或 Rabbit MQ)
  • 订阅者(celery workers 是执行后台任务的独立进程)

分布式消息传递基本上意味着 Celery 依靠一个称为 broker 的中间人来充当它和任务生产者之间的中介。为了启动任务,客户端向消息队列发送消息。然后,消息队列将消息传递给工作线程,并执行所需的任何操作。worker 通过消息代理将作业的状态或结果返回给客户机。在任何时候,客户和员工都不会直接交流。实际上,他们甚至没有意识到对方。它们各自只处理消息队列。

使用分布式消息传递体系结构的主要优点是:

  1. 可伸缩性:每个组件都可以根据需要独立伸缩,而不会影响其他组件
  2. 松散耦合:工作者只关心它接收到的消息,而不关心是谁产生了它
  3. 消息队列向工作人员提供实时消息。工作者不需要不断地轮询队列来查看是否有消息

用芹菜

安装

如果您还没有这样做,安装 celery 和您选择的消息代理的包。我选择了使用 Redis。

$ pip install celery redis

配置

要配置 Celery,您需要定义两个参数,CELERY_BROKER_URLRESULT_BACKEND。这些参数的值是您选择的代理的 URL。它实际上告诉 Celery 代理在哪里运行,这样 Celery 就能够连接到它。我将在本地机器的端口 6379 上运行一个 redis docker 容器。

RESULT_BACKEND参数定义了当您运行一个返回某些东西的任务时,任务结果存储在哪里。如果您正在运行不返回结果或状态的后台任务,那么您不需要取消定义此参数。如果您确实想返回结果,您的消息代理也可以作为您的结果后端。这就是为什么我给了他们相同的网址。

1.在.env文件中定义 redis 客户端的 URL:

CELERY_BROKER_URL = redis://localhost:6379RESULT_BACKEND = redis://localhost:6379

2.在config.py中配置Config类芹菜:

CELERY_BROKER_URL = os.getenv('CELERY_BROKER_URL ')RESULT_BACKEND = os.getenv('RESULT_BACKEND')

芹菜设置

  1. app/__init__.py中实例化一个芹菜对象:

在上面的代码中,我们通过调用 Celery 类对象实例化了一个新的 Celery 对象。它期望的参数是:

  • 正在实例化芹菜对象的模块的名称
  • 代理的 URL,它告诉 celert 代理服务正在哪里运行
  • 结果后端的 URL
from celery import Celery  # NEW!!!!!
from config import Config  # NEW!!!!!celery = Celery(__name__, broker=Config.CELERY_BROKER_URL, result_backend=Config.RESULT_BACKEND)

芹菜的任何其他配置都从应用程序工厂函数内的 flask 应用程序配置传递给芹菜对象:

celery.conf.update(app.config)

2.定义要在后台运行的任务

对于这个例子,我们将设置 Celery 在后台发送电子邮件。

已经配置了flask-mail扩展。

后台任务被定义为函数。每个函数都需要用@celery.task装饰器来装饰。在一个单独的模块中定义所有的任务是一个好主意。

app/tasks.py创建一个发送邮件的任务:

app/auth/views.py中,调用任务:

为了调用任务,我使用了apply_async()方法,并使用args关键字传递任务函数需要的参数。

3.编写启动芹菜工的脚本。

celery_worker.py中:

上面的代码创建了一个 flask 应用程序,然后使用它为 celery 实例的运行建立了一个应用程序上下文。Celery 需要应用程序上下文才能访问任何 flask 扩展对象,以便执行后台任务。它将在 celery worker 进程运行的整个生命周期内保持设置。

有必要导入 celery 实例,因为 Celery 将需要它来执行后台任务。

测试所有东西

  1. 打开 docker 并运行 Redis 容器。

$ docker run -d -p 6379:6379 redis

2.打开一个新的终端窗口,激活虚拟环境并启动一个芹菜客户端:

$ celery -A celery_worker.celery worker --pool=solo --loglevel=info

您应该会看到 clery 客户端启动。它将向您显示它已经连接到 redis 客户机,还向您显示为 Celery 创建的在后台运行的任务。

芹菜客户端输出(作者自己的)

如果您遇到任何问题,请卸载并重新安装 celery,然后重试。还可以尝试不同的执行池,因为我发现这也有所不同。

3.在主终端窗口中,重新启动 flask development 服务器。导航至http://127 . 0 . 0 . 1:5000/users/register/your-email-address @ Gmail . com

如果您检查运行 Celery 客户端的终端,您应该看到以下内容,以了解任务已经成功执行:

芹菜执行电子邮件发送后台任务(作者自己的)

输出的最后一行:

[2021-05-15 19:36:39,651: INFO/MainProcess] Task app.tasks.send_celery_email[59e09990-ed19-4209-8afb-3bdd87ec80c6] succeeded in 3.1569999999919673s: None

您应该会从邮件传递子系统收到一封电子邮件,说明无法找到your-email-address@gmail.com地址。

将 URL 的your-email-address部分替换为有效的电子邮件地址,您应该会收到一封主题和正文都在app/views.py中定义的电子邮件。

请记住,要让 flask 应用程序代表您使用 google SMTP 服务器发送电子邮件,您需要允许不太安全的应用程序访问。

允许不太安全的应用程序(作者自己的)

结论

就是这样!安装完成后,您可以继续开发您的 web 应用程序。

你可以在我的 GitHub 上找到这个回购。非常欢迎您使用 repo,并将其作为完全设置和配置 flask web 应用程序的起点。如果你这样做,记得添加一个.env文件将你所有的环境变量,因为该文件不会上传到 Github。

如何建立最大似然数据标注系统

原文:https://towardsdatascience.com/how-to-set-up-an-ml-data-labeling-system-4eea9b15181f?source=collection_archive---------14-----------------------

ML 模型需要各种任务和模态的标记数据。左图:带有 Supervise.ly 的视频标注。右图:对带有标签的文本进行命名实体识别。

今天大多数生产机器学习应用都是基于监督学习。在这种设置中,机器学习模型在一组标记为的训练数据上进行训练,以便学习如何完成某项任务。例如,ML 模型可以在标记有该图像中的宠物类型的图像上进行训练,以便训练的模型可以告诉你在一组未标记的图像中存在什么宠物。

为了获得带标签的训练数据,ML 团队经常依赖人类注释者,他们为模型的训练标记例子。开始时,标签“团队”可能由一个 ML 工程师一次在图像上画几个小时的方框组成。随着系统变得越来越成熟,团队希望通过利用自动化和依靠大型运营团队来产生更大数量的标记数据。

从概念上讲,标签系统很简单:用户应该能够向标签系统发送数据,并取回该数据的标签。然而,根据您的问题设置和需求,有许多方法可以设置带标签的数据管道。为了帮助你选择适合你的,这里有一些我们学到的关于如何建立一个伟大的 ML 数据标签系统的经验。

你想从标签中得到什么?

在我们讨论不同的贴标设置之前,我们应该先讨论一下在查看贴标系统时应该评估的因素。

  • 准确性:一个标注系统应该准确一致地标注数据,否则你的模型就会学会做错事!例如,如果一个数据点被标记为欺诈,您希望确保它实际上是欺诈,而不是标记者的错误,否则您训练的模型在生产中运行时可能会犯类似的错误。虽然标签系统不可避免地会有一些错误率,但没有什么比由于标签准确性差而不知道是否可以信任您的数据和指标更糟糕的了!
  • 速度:数据要快速大批量标注。一些应用程序使用标签作为实时模型预测的 QA,并要求接近实时的响应时间(一小时内)。然而,标记离线培训工作流可能会牺牲吞吐量的延迟。标签的数量可以从一周数百个样本到数十万个样本不等。
  • 成本:标签要在时间和金钱上低成本生产。贴标签需要时间,因为它通常需要工程时间来建立数据管道,还需要操作时间来做实际的标签。这个时间是要花钱的,无论是直接雇人还是通过与外部提供商签约。

您的标签系统中的许多决策将在这些因素之间进行权衡。例如,如果您有严格的准确性要求,您可以实施 QA 流程来提高标签质量,但会增加额外的时间和成本。

然而,通常有一些技术可以统一改善所有这些因素。更好的贴标工具、自动化和特定领域的优化都可以明显提高贴标效率。

标签选项

ML 团队可以选择建立或购买标签系统的两个关键部分:

  1. 用户检查、编辑和存储数据和标签所需的工具和软件。
  2. 使用工具进行贴标的贴标机操作人员。

一些供应商将这两个组件作为完全托管的服务提供,而一些供应商只提供其中一个。一个 ML 团队也可以决定构建两者。一般来说,你自己建立的越多,你对标签过程的控制就越多,但是在时间和金钱上的成本也更高。

全面管理的标签服务

完全托管服务允许您购买工具和操作人员进行贴标,通常按标签收费。这需要 ML 团队投入最少的时间,尽管他们会因此支付一些额外费用。

完全托管的服务是不需要专业工具或专业知识的标准任务的理想选择。完全托管的服务往往会针对最受欢迎的 ML 任务(例如,图像分类和检测)优化其技术工具链,并在劳动力成本较低的国家/地区部署运营力量,从而显著降低每个标签的成本。此外,一些完全托管的服务公司可能会提供附加功能,如标记自动化功能或基于标记数据的现成模型培训。

然而,全面管理的服务通常在较小的合同上投入较少的精力。一些较大的供应商将要求最低标签量,并且不会接受每年低于 10 万美元的合同!这是因为完全管理的提供者必须训练和维持他们自己的相当大的操作力量。为了获得合理的贴标质量,通常需要付出巨大的努力来培训贴标机完成某项任务,或者在不同客户的任务之间移动贴标机,这需要最小的合同规模来使这项投资物有所值。其他提供商提供现收现付定价,支持小型/尖峰标签工作负载,但代价是价格更高,复杂任务的标签准确性降低。

这些类型的提供商包括 Scale AI、Playment、阿彭、亚马逊 Sagemaker Ground Truth 和 Hive AI。

购买贴标工具

当您的钱比时间多时,完全托管服务通常是最佳选择。当您的组织扩大规模并考虑成本优化时,您可能希望切换到将标注操作与标注工具分离的模式。贴标工具由软件组成,使运营团队能够。它们由标记数据的 ui、跟踪标签的存储系统和以编程方式移动数据的 API 组成。

当独立考虑标记工具时,公司倾向于首先考虑开源工具。开源工具对于小批量的标签工作很有效,但是没有公司开发的软件那么多的支持和功能。开源工具通常不是托管的(因此需要一些初始设置),并且通常不支持更高级的功能,如贴标机监控、任务分配和 QA 流程,这些功能对于将贴标扩展到大规模工作人员至关重要。这就是团队决定购买专用标签软件的原因。

购买贴标工具很像购买任何其他 SaaS 软件。大多数工具都托管在 SaaS,使得离岸操作团队无需大量 it 设置就能轻松访问。一些公司为敏感数据提供内部工具。一些工具提供商还将包括与他们过去合作过的操作人员合作的选项。然而,所有这些都为 ML 团队提供了为他们自己的操作人员创建帐户的能力。

ML 团队通常由工程师组成,他们更熟悉 Jupyter notebooks 和 Tensorflow 等机器学习工具,而不是 React 和 Node 等 web 开发工具。与建立专门的 Python GUIs 相比,购买标记工具允许团队使用更高质量的最终产品,并且比雇佣一组工具工程师来开发一个完美的 web UI 更便宜、更快速。

此外,在购买贴标工具时有很多选择。一些公司专门从事特定类型的标记——自然语言处理对音频对图像对视频——允许 ML 团队为工作选择最好的工具。如果没有足够好的产品,你可以雇佣一些工具工程师来自己开发。

仅工具提供者的例子包括 Labelbox、Dataloop、SuperAnnotate、Supervisely 和 Datasaur。

购买贴标操作劳动力

等式的另一半是贴标工人。如果您想以合理的成本扩大您的贴标产量,您可能不想让您的 ML 工程师每天数小时贴标数据。如果你能以很低的成本让离岸承包商做同样的工作,你甚至可能不想雇佣全职员工。

购买运营人员有很多种选择。如果你在寻找灵活的一次性工作,从 TaskRabbit 雇佣一个承包商相对容易。这有利于贴标签的工作,有灵活的需求,因为这是相对容易的训练一个贴标机一天,并保持他们只要你需要他们。另一方面,这比雇佣海外劳动力成本更高,因此更难扩大规模。

随着贴标需求的增加,您可能希望与能够提供更多贴标劳动力的运营提供商签订合同。这些贴标机更便宜,因为它们位于工资更低的国家,而且它们的劳动力习惯于为许多不同的公司和领域做标准的 ML 任务。

然而,对离岸工人的依赖意味着可能存在语言或文化障碍,需要额外的培训来实现所需的标签准确性。在我之前的一份工作中就有这样一个例子:我们曾要求我们的标签团队在校车图片周围画出边界框,但我们的标签团队所在的国家没有校车。我们必须编写一份培训指南,其中包含许多校车的示例图片,还包含一些看起来像校车的反例,比如同样黄色的皮卡车,以训练贴标机产生准确的标签。

这些供应商通常要求长期的承诺和最小的合同规模,这是基于预先预留一些贴标时间,使得 ML 团队有必要有一些持续的贴标需求,以使贴标机保持忙碌,或者冒着浪费已经付费的时间的风险。一些公司可能会提供会说英语的运营经理,以便更容易地培训和管理离岸团队,而其他公司只是提供招聘服务,并将协调工作留给 ML 团队。

外包运营提供商的例子包括 Cloudfactory、Samasource、TaskUs 和 iMerit。

卷你自己的

你也可以选择自己构建一切!这使您可以最大限度地控制贴标过程,但会花费大量时间和金钱。我不建议在大多数情况下这样做,但是有几个原因让你想把所有事情都放在家里:

  • 您的任务如此独特,以至于外部提供的产品非常差,您可以在内部轻松构建更高质量的标签工具。
  • 您拥有领域专业知识/理解能力,这使您能够以外部产品不会考虑的方式显著加快或自动化标记过程。
  • 您的贴标任务非常困难,因此最好在内部雇佣和培训贴标机,以确保更好的质量控制和保留。这在医学机器学习等领域非常重要,在这些领域,唯一能够生成可接受质量标签的人是昂贵的医生!
  • 你的运营规模足够大(比如谷歌/脸书的规模),从零开始建立一个内部系统比从第三方购买服务更便宜。

构建标注工具可能是一项有些令人望而生畏的任务,并且根据任务的难度和运营团队的规模,其复杂性可能会急剧增加。您需要构建的组件包括:

  • 用于查看数据和修改标签的用户界面。
  • 一个工作流引擎,用于在不同的人、QA 标签之间分配标签工作,并协调冲突的标签。
  • 贴标机质量+吞吐量统计,以监控和管理他们的生产力。
  • 标签存储和版本控制。
  • 自动化/预贴标功能,减少人工贴标机的工作量。

建立和管理内部运营团队很像管理普通员工,尽管规模远高于工程师/项目经理。你需要:

  • 贴标机的人力资源基础设施。这包括招聘,面试和招聘贴标机的过程。一些团队将雇用运营人员作为全职员工,但大多数美国团队将依赖 1099 承包商来降低成本。
  • 运营经理监督贴标工人。他们的工作包括与 ML 团队就贴标指南进行沟通,培训贴标机遵循这些指南,然后在他们工作时监控贴标产量和准确性。

最佳实践

不管你选择哪种标签,总有一些最佳实践可以让 ML 团队获得最好的结果。

编写良好的标签说明

不管你有什么样的标签设置,你都不可避免地需要训练一支标签队伍来根据 ML 团队定义的一组指令对数据进行注释。当贴标机遇到有趣的边缘情况或需求改变时,指令也必须发展以准确反映 ML 团队的期望。即使当您切换贴标工作人员或工具时,您也可以使用相同的贴标说明快速启动并运行新的贴标系统。

如果没有一套可靠的贴标说明,贴标机将会产生不正确(或者更糟,不一致)的结果,浪费时间和金钱。更重要的是,错误不是均匀地分布在整个数据集上,而是在数据集的某些子集上出现标记错误,如模糊的情况或标记者不知道如何处理的某些罕见情况。以下是一些可行的建议,以确保事情做得正确:

  • 对于创建和编辑说明,请使用类似 comment 的工具,该工具允许多个团队成员编辑贴标说明,对有问题的更改进行评论,并与贴标机共享最终版本作为参考。
  • 包括困难或模糊案例的例子(带图片),以及如何处理的说明。书面说明通常很难理解,但图片有助于清楚地传达应该做什么。
  • 对您的标签文档进行版本控制。这有助于跟踪哪些贴标机已被重新培训,何时。这对于跨数据集的不同段跟踪标注说明的变化非常重要,尤其是当您需要更改以前的标注时!

对于伟大的标签说明的例子, Landing AI 为工业缺陷检测提供了一套伟大的标签说明,并为困难/模糊的场景提供了一些说明的例子。 Waymo 开放数据集还包含何时标记对象以及如何标记对象的说明。

信任但核实

一些团队会收到标签,并立即根据这些数据训练一个模型。然而,他们的模型的性能指标会很差,他们也不知道为什么。经过数周的焦虑和超参数优化,他们将检查标签,并意识到其中许多是不正确的,这意味着他们的模型在训练时变得混乱,他们的性能指标首先是不可靠的。

对你收到的新标签做一些基本的质量检查是非常重要的。虽然您的标签提供商可能在他们的流程中有一个 QA 步骤,并在您的合同中写入了标签质量承诺,但最终验证标签质量符合您预期的唯一方法是亲自看一看。事实上,许多标签错误不一定是丢失标签的直接错误,而是 ML 团队和标签团队之间沟通不畅和误解的结果。

检查标签质量的一个简单方法是简单地可视化由贴标系统产生的新标签的子集。这可以由 ML 工程师或产品经理在几个小时内完成,这可以是一个很好的检查,揭示标签说明含糊不清或被误解的地方。

确保标签质量保持高水平是一项持续的工作。错误悄悄溜走,最终被抓住,然后被修复。当标签数量变大时,团队应该将他们的 QA 时间集中在他们的模型和标签不一致的地方,这有效地处理了标签错误的数据点。甚至有更高技能的内部操作人员专门检查来自外部供应商的标签质量也是有用的!

在贴标系统之间进行烘烤

设置标签系统有很多选择!不仅要决定生产多少与购买多少,还有许多供应商提供类似的工具来完成某些标记任务,而且很难缩小购买和生产的选项/组合对您来说是最好的。通常有可能使用一组非常粗略的要求(支持贴标任务、定价、可用吞吐量等。)将一个大的选项列表削减到大约 5 个左右的最终候选项,但是您仍然需要一个过程来选择使用哪个系统。

在这里,重要的是要建立你要优化的评估标准。对于您的用例,贴标精度、速度和成本的正确组合是什么?一旦你有了一套明确的评估标准和一份标签选项的候选名单,你就可以在竞争的标签系统之间进行测试。这个测试的目的是在一个小数据集上对不同的标签系统进行比较,评估哪个选项在您的评估标准上表现最好,然后使用该信息选择哪个选项。

为了构建这个烘焙,我们建议您在内部使用专家贴标机手动标记一个小的“黄金”数据集。这位专家标签员通常最终成为为 ML 系统设定需求的 ML 团队的一员,例如 ML 工程师或产品经理。由于贴标机也是知道他们想从 ML 系统中得到什么的人,你可以相当合理地假设这组数据是你所能得到的最接近完美的标签。这位专家标签员还应该构建一套基本的标签说明,用于在新的数据集上生成更多的标签。

之后,您可以向候选贴标系统发送相同的黄金数据集(无标签)和相同的贴标说明。你可以很容易地衡量速度和成本。为了测量标签的准确性,您可以计算指标,将每个供应商的标签与您的专业贴标机的黄金标签集进行比较。

现在,您可以根据准确性、速度和成本的组合,选择在您的评估中得分最高的选项!这是一个很好的比较选项的定量方法,尽管你需要衡量你想要在这三个因素之间做出什么样的权衡。

每 3-6 个月重复一次这个练习也是有用的,看看其他提供者是否能达到更好的效果。贴标是一个竞争相当激烈的领域,相对来说已经商品化了,所以从一个供应商换到另一个供应商的摩擦相对较小,只要他们在你的烘焙比赛中表现良好。我们的公司 Aquarium ,使得 ML 团队可以很容易地在标签系统之间进行权衡。水族馆允许团队将数据发送给标签供应商进行标记,然后与黄金数据集进行比较,评估结果的准确性。

摘要

有时弄清楚如何扩展 ML 系统是令人畏惧的,拥有一个良好的标记数据流是运送优秀模型的重要部分。在本帖中,我们列出了多种选择来设置 ML 标签系统,在成本、速度和灵活性之间进行权衡。我们还制定了一个流程,允许您公平地评估不同的标签选项,并选择最适合您的用例的选项。

如何正确设置 Anaconda 和 Jupyter 笔记本

原文:https://towardsdatascience.com/how-to-set-up-anaconda-and-jupyter-notebook-the-right-way-de3b7623ea4a?source=collection_archive---------1-----------------------

作者图片

如果 Anaconda (conda)和 Jupyter Notebook (Jupyter Lab)以正确的方式设置,它们的组合可以成为完美的团队,在那里你可以轻松地在深度学习 conda 环境之间切换。

有些程序需要 Tensorflow 1.15,有些需要 Tensorflow 2.0?没问题!只需简单点击即可切换环境和 Tensorflow 版本。

另外,您是否在每个 conda 环境中安装过 Jupyter 笔记本扩展?不要再担心了,我们将安装一次扩展,并让它们在每个环境中都可用!

我们如何实现这一目标?

  1. 安装 Anaconda 或 Miniconda
  2. 在基础环境中安装 Jupyter 笔记本电脑/实验室
  3. 安装新环境
  4. 激活 Jupyter 笔记本的环境

如何安装 Anaconda 或 Miniconda?

Anaconda 是一个很好的包,已经包含了很多 Python 包,可以很容易地进入 Python 世界。此外,它允许在 python 中创建环境,其中包含不同版本的 Python 包。例如,如果一个程序只能在 Python 2.7 或更早版本的 Matplotlib 上运行,您可以为该程序创建一个自己的工作空间,并通过单击一个按钮切换回 Python 3。此外,Tensorflow 2.0 和 Tensorflow 1.15 之间的切换也变得很容易,最终允许您轻松地在版本之间切换(否则这可能会很令人头疼)。

Miniconda 是 Anaconda 的一个基本版本,如果你在一个服务器上工作,磁盘空间有限的话,它会很有用。

要安装 Anaconda 或 Miniconda,请访问他们的网站(【https://www.anaconda.com/products/individual#Downloads】T4),或者如果你使用的是 Linux,只需复制以下命令。

第一个链接在网站上搜索最新版本,并将其写入 LATEST_ANACONDA 变量。

cd ~/Downloads
LATEST_ANACONDA=$(wget -O - https://www.anaconda.com/distribution/ 2>/dev/null | sed -ne 's@.*\(https:\/\/repo\.anaconda\.com\/archive\/Anaconda3-.*-Linux-x86_64\.sh\)\">64-Bit (x86) Installer.*@\1@p')
wget $LATEST_ANACONDA
chmod +x Anaconda3*.sh # make it executable
./Anaconda3*.sh # execute the installer

按照对话,并就默认设置达成一致。

检查和切换 conda 环境

如果 conda 安装正确(可能需要注销并登录,或者重启),您应该能够在终端中输入conda时看到输出。

要列出当前安装的环境,只需键入conda env list

它当前应该只显示安装的“基础”环境。

在环境之间切换就像输入conda activate [NAME]一样简单,如果完成了,用conda deactivate停用它(并返回到基本环境)。

默认情况下,基本环境是激活的。

在基础环境中安装 Jupyter 笔记本电脑/实验室

Jupyter 笔记本可以很容易地安装使用康达。我们的计划是只在基础环境中安装它,然后在子环境之间切换,以避免在每个环境中建立 Jupyter 实验室。

安装 Jupyter 笔记本电脑(默认)

conda install -c conda-forge notebook
conda install -c conda-forge nb_conda_kernels

安装 Jupyter 实验室

conda install -c conda-forge jupyterlab
conda install -c conda-forge nb_conda_kernels

安装 Jupyter 笔记本扩展

我真的很喜欢 Jupyter 笔记本扩展,它支持许多自动完成功能、附加信息,以及让您的生活更加轻松的一般功能。以下安装命令包含了一个好的默认设置:

conda install -c conda-forge jupyter_contrib_nbextensions

很好的概述了其他扩展:https://towards data science . com/jupyter-notebook-extensions-517 fa 69d 2231

(可选)安装 pip 软件包管理器

在我看来,将 pip 包管理器添加到基础(和每个子)环境是一个好主意,因为 conda install 并不支持所有的包。此外,如果 pip 没有安装在每个子环境中,该软件包可能只是安装在“基础”conda 环境中,从而导致在您的子环境中找不到该软件包的错误。

conda install pip

在 conda 和 Jupyter 笔记本中创建环境

假设你想在 Jupyter 笔记本上同时安装 Tensorflow 2.0 和 Tensorflow 1.15。

先举这个例子,同意如果要用 Tensorflow 的 GPU 或者 CPU 版本。要使用 GPU 版本,请在 TensorFlow 中添加“-gpu”,否则,请保持原样。

为了创建一个新的 conda 环境,我们可以运行

conda create --name tf-2.0

如果你已经计划用它安装一些包,只需要把它们添加到末尾,比如:

conda create -n tf-2.0 tensorflow-gpu pip ipykernel

我建议安装pip进行包安装,使用 Jupyter 笔记本切换环境将需要ipykernel

要使用 TensorFlow 1.15 安装环境,请使用以下内容:

conda create -n tf-1.15 tensorflow-gpu==1.15 pip ipykernel

如果成功完成,在执行以下命令时,您应该能够看到三种环境:

conda env list
  1. 基础
  2. tf-2.0
  3. tf-1.15

启动 Jupyter 笔记本并检查环境和扩展

jupyter notebook

在基本环境中运行 Jupyter Notebook,您应该可以看到一个包含“扩展”以及“conda”/“环境”的选项卡。转到扩展,激活你喜欢的扩展,如果你准备好了,使用“新建”按钮创建一个新的笔记本。在这里,您应该能够在您的基础环境、tf-2.0 环境和 tf-1.15 环境之间进行选择。

注意:你总是需要在基础环境中运行 jupyter notebook。运行conda deactivate离开你当前的环境,回到基础环境。

如果你需要安装更多的包,使用conda activate [NAME]激活一个环境,运行像conda install Xpip install X这样的命令,使用conda deactivate离开环境。

如果这对你有用,请告诉我,这对我帮助很大,我希望我能早点知道这件事!

在我的网站上找到这篇文章和其他文章:https://www . data fortress . cloud/blog/how-to-set-up-anaconda-and-jupyter-notebook-the-right-way/

如何在 2021 年建立一个通用的 Lisp IDE

原文:https://towardsdatascience.com/how-to-set-up-common-lisp-ide-in-2021-5be70d88975b?source=collection_archive---------10-----------------------

使用 Roswell 在 Windows 10、MacOS 或 Ubuntu 中快速启动 Common Lisp

克里斯蒂娜·莫里路穿着 Pexels 的照片

如果“以错误的方式”建立一个公共 Lisp (CL)开发环境是乏味且耗时的。

它涉及手动安装和设置:

  1. 一个常见的 Lisp 实现——通常是sbcl
  2. emacs—Common Lisp 中编码的首选非商业编辑器,
  3. quicklisp —通用 Lisp 的黄金标准包管理器,以及
  4. slimeemacs和 CL 实施sbcl之间的功能胶水

这个过程可能会让人不知所措,而且充满陷阱,尤其是对初学者来说。

不过,很幸运,有一个度假村:Roswell

Roswell是一个现代的虚拟环境和 Common Lisp 的包管理器,它不仅允许安装 Common Lisp 的不同实现(如sbcleclallegro等)。)而且将它们中的每一个的不同版本放入单独的虚拟环境中。Roswell允许在不同的实现和版本之间切换,这对于普通的 Lisp 包开发者来说是必不可少的。因此,Roswell 是任何认真的 Common Lisp 开发人员的最好朋友。

此外,Roswell 允许建立一个测试环境并集成 CI(见此处)。

在 Windows 10 中安装 Roswell(PowerShell)

在 Windows 10 (PowerShell)中安装 Roswell 非常简单:

# 0\. install scoop - which is kind of `apt` for windows
iwr -useb get.scoop.sh | iex# 1\. install roswell using scoop
scoop install roswell

仅此而已!接下来的所有命令也可以在 PowerShell 上完成——尽管我在代码行的开头写了$,表示通常是来自 Linux 或 MacOS 的 bash shell(在 PowerShell 中安装 scoop 之后,您也可以在 cmd.exe 中运行 scoop——但是我总是在 Windows 中使用 PowerShell)。

在后面的阶段,可能会出现以下错误

ros install sbcl

可以肯定的是scoop install单独运行,它安装了一个二进制版本的sbcl (sbcl-bin),但是它不支持多线程。

我意识到

ros install msys2

然后运行初始配置

msys2

之后,重新启动 powershell,然后输入

ros install sbcl

应该有效——但事实并非如此。问题出在罗斯威尔的msys2安装脚本中。如果它使用scoop install而不是像它实际做的那样从 sourceforge 拉msys2的源代码,它会工作。所以目前ros相当破。然而,ros install至少安装了不需要msys2sbcl-bin。但是,一个人只有 aked sbcl-bin。一个人甚至不能安装ros install slime也不能安装ros install clisp。因为那些是需要msys2的。很抱歉,罗斯威尔的作者必须修复msys2的安装。在此之前,您只能通过激活 windows 中的wsl2并在其中安装ubuntu来使用 roswell。并使用 Linux 的指令。

在 MacOS 中安装 Roswell

简单如:

$ brew install roswell

在 Ubuntu 20.04 LTS 版(以及更老的 Ubuntu 版本)中安装 Roswell

# Following instructions in github of roswell:# system-wide installation of roswell:sudo apt-get -y install git build-essential automake libcurl4-openssl-dev
git clone -b release https://github.com/roswell/roswell.git
cd roswell
sh bootstrap
./configure
make
sudo make install
ros setup# local installation of roswell:git clone -b release https://github.com/roswell/roswell.git
cd roswell
sh bootstrap
./configure --prefix=$HOME/.local
make
make install
echo 'PATH=$HOME/.local/bin:$PATH' >> ~/.profile
PATH=$HOME/.local/bin:$PATH 
ros setup

或者,您也可以遵循以下步骤:

# install dependencies for ubuntu
$ sudo apt install libcurl4-openssl-dev automake# download Roswell installation script $ curl -L [https://github.com/roswell/roswell/releases/download/v19.08.10.101/roswell_19.08.10.101-1_amd64.deb](https://github.com/roswell/roswell/releases/download/v19.08.10.101/roswell_19.08.10.101-1_amd64.deb) --output roswell.deb# or just for the latest debian package:
$ curl -sOL `curl -s https://api.github.com/repos/roswell/roswell/releases/latest | jq -r '.assets | .[] | select(.name|test("\\\.deb$")) | .browser_download_url'`# run the installation
$ sudo dpkg -i roswell.deb# add roswell to PATH to your ~/.bashrc 
# (important for scripts to run correctly!)
export PATH="$HOME/.roswell/bin:$PATH"# don't forget to source after modifying your ~/.bashrc:
$ source ~/.bashrc

安装罗斯威尔后

一旦 Roswell 安装完毕,我们可以通过以下方式检查可用的公共 Lisp 实现:

$ ros install # this prints currently:Usage:To install a new Lisp implementaion:
   ros install impl [options]
or a system from the GitHub:
   ros install fukamachi/prove/v2.0.0 [repository... ]
or an asdf system from quicklisp:
   ros install quicklisp-system [system... ]
or a local script:
   ros install ./some/path/to/script.ros [path... ]
or a local system:
   ros install ./some/path/to/system.asd [path... ]For more details on impl specific options, type:
   ros help install implCandidates impls for installation are:
abcl-bin
allegro
ccl-bin
clasp-bin
clasp
clisp
cmu-bin
ecl
mkcl
sbcl-bin
sbcl
sbcl-source

安装不同的公共 Lisp 实现和版本

# these are examples how one can install specific implementations and versions of them:
$ ros install sbcl-bin      # default sbcl
$ ros install sbcl          # The newest released version of sbcl
$ ros install ccl-bin       # default prebuilt binary of ccl
$ ros install sbcl/1.2.0    # A specific version of sbcl

我推荐安装最新的sbcl,因为sbcl-bin似乎不支持多线程:

$ ros install sbcl

要列出已经安装的实现和版本,请执行以下操作:

$ ros list installed  # Listing all installed implementations

在不同的实现及其版本之间切换

检查当前活动的实现/版本:

$ ros run -- --version      # check which implementation is used
SBCL 1.2.15

切换到另一个实现/版本:

$ ros use sbcl/2.1.7 # change the version number if newer available!

启动 REPL(使用“rlwrap ”)

$ ros run
# or better:
$ rlwrap ros run # it starts sbcl or whatever implementation 
                 # recently determined by `$ ros use` command.

rlwrap -ing sbcl很有帮助,因为sbcl REPL 的“裸机”不允许行内跳转或者其他有用的编辑命令哪一个是使用 ubuntu shell REPL 时习惯的。

使用 Roswell 安装公共 Lisp 包

对于 quicklisp 的ql:quickload功能可用的任何包,您现在都可以使用当前激活的实现的roswell从命令行安装:

# from the quicklisp package repository for CL
$ ros install rove # rove is a test package for CL# or from github:
$ ros install fukamachi/rove# later update your package by:
$ ros update rove

安装 emacs 和 slime 并与 Roswell 连接

A.简单的方法(但目前已被打破):

通常,emacs 可以在连接并运行 quicklisp】的情况下,通过Roswell中的单个命令进行安装和设置,quicklisp 是日本开发者cxxxrCL开发的一种特殊模式。

$ ros install cxxxr/lem
# and then start `lem` by:
$ lem

不幸的是,目前lem安装存在问题。

因此,必须手动安装emacs,并手动将其与罗斯威尔连接。

B.手动方式(在罗斯威尔的帮助下):

0.全球安装 emacs:

$ sudo apt install emacs
# then start emacs in the background
$ emacs &
  1. 在罗斯威尔内部安装史莱姆和斯旺克:
$ ros install slime
$ ros install swank

看来这还不够。用户还必须通过M-x install-package并选择slime来安装到 emacs slime中。

2.通过配置~/.emacs.d/init.el中 emacs 的标准配置文件,在 emacs 中配置通过 slime 到 Roswell 的连接。

在 emacs 中,通过按下C-x C-f,键入~/.emacs.d/init.el,并按下回车键RET,打开~/.emacs.d/init.el

(Emacs 快捷键符号:

  • CCtrl
  • MAlt
  • SShift
  • SPCSpace
  • RET就是Return
  • 像 Ctrl 键被按下的同时按键x的组合将是C-x,并且

C-x C-f例如:按住 Ctrl 的同时按下x,然后松开两者,然后按住 Ctrl,同时f,然后松开两者)。

打开~/.emacs.d/init.el后,按照维基中针对罗斯威尔的说明,我们编写:

;; initialize/activate emacs package management
(require 'package)
(setq package-enable-at-startup nil)
(setq package-archives '());; connect with melpa emacs lisp package repository
(add-to-list 'package-archives '("melpa"     . "[http://melpa.org/packages/](http://melpa.org/packages/)") t);; initialization of package list
(package-initialize)
(package-refresh-contents);; Ensure `use-package` is installed - install if not                                                                                        
(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;                                                                                       
;; slime for common-lisp                                                                                               
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; to connect emacs with roswell
(load (expand-file-name "~/.roswell/helper.el"));; for connecting slime with current roswell Common Lisp implementation
(setq inferior-lisp-program "ros -Q run");; for slime;; and for fancier look I personally add:
(setq slime-contribs '(slime-fancy));; ensure correct indentation e.g. of `loop` form
(add-to-list 'slime-contribs 'slime-cl-indent);; don't use tabs
(setq-default indent-tabs-mode nil);; set memory of sbcl to your machine's RAM size for sbcl and clisp
;; (but for others - I didn't used them yet)
(defun linux-system-ram-size ()
  (string-to-number (shell-command-to-string 
                     "free --mega | awk 'FNR == 2 {print $2}'")))(setq slime-lisp-implementations 
   `(("sbcl" ("sbcl" "--dynamic-space-size"
                     ,(number-to-string (linux-system-ram-size))))
     ("clisp" ("clisp" "-m"
                       ,(number-to-string (linux-system-ram-size))
                       "MB"))
     ("ecl" ("ecl"))
     ("cmucl" ("cmucl"))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; slime for common-lisp using use-package
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;(use-package slime
    :ensure t
    :config
    (load (expand-file-name "~/.roswell/helper.el"))
    ;; $ ros config
    ;; $ ros use sbcl dynamic-space-size=3905
    ;; query with: (/ (- sb-vm:dynamic-space-end sb-vm:dynamic-space-start) (expt 1024 2));; set memory of sbcl to your machine's RAM size for sbcl and clisp
    ;; (but for others - I didn't used them yet)
    (defun linux-system-ram-size ()
      (string-to-number (shell-command-to-string "free --mega | awk 'FNR == 2 {print $2}'")))
    ;; (linux-system-ram-size) (setq inferior-lisp-program (concat "ros -Q dynamic-space-size="     
                                      (number-to-string (linux-system-ram-size)) 
                                      " run")) ;; and for fancier look I personally add:
    (setq slime-contribs '(slime-fancy)) ;; ensure correct indentation e.g. of `loop` form
    (add-to-list 'slime-contribs 'slime-cl-indent) ;; don't use tabs
    (setq-default indent-tabs-mode nil))

通过以下方式在 emacs 中保存并关闭文件

  • C-x C-s(保存当前缓冲区/文件)和
  • C-x C-c(关闭 emacs)。

3.最后,重新启动 emacs:

$ emacs &

要尝试 emacs 和当前 Roswell 激活的实现之间的连接,创建一个test.lisp文件:

  • (在 emacs 中打开/创建文件)C-x C-f然后输入:test.lisp并按下RET

(打开现有的 lisp 文件:C-x C-f,输入 lisp 文件的路径,按RET)。

在 emacs 中的 lisp 内部,通过按下M-x并键入:slime 来启动slime,然后按下RET来执行命令。

当前test.lisp文件(emacs 缓冲区)下的一个新标签(emacs 缓冲区)应在 emacs 中打开,并且粘液 REPL 应可见:

; SLIME 2.26.1 (or whatever version number you have ...)
CL-USER>

这是 Roswell 中当前激活的 lisp 实现的交互式 REPL(可通过$ ros use命令随时切换,但不适用于已经运行的 emacs 会话;每次$ ros use切换后,可能需要重启 emacs)。

最好的事情是,现在,test.lisp已经(通过slime)与 Roswell 中当前的 CL 实现相连接。您可以将指针指向test.lisp文件中任何 lisp 表达式的末尾,然后按下C-x C-c : emacs 会将该表达式转发给 Common Lisp 的连接实现(在我们的例子中是sbcl)并执行该表达式。

通过vimatom而不是emacs进行连接,查看罗斯威尔 GitHub 网站的wiki

在下文中,我们希望了解如何创建公共 Lisp 包(或项目),如何设置测试,尤其是 Travis CI 的自动化测试,以及如何监控测试的代码覆盖率。

使用 cl-projects 启动公共 Lisp 包/项目

可以使用cl-project自动生成一个包主干。

通过Roswell:安装

$ ros install fukamachi/cl-project

进入Roswelllocal-projects文件夹,因为我们想先把包保存在本地机器上。

$ cd ~/.roswell/local-projects

现在创建你的项目主干——让我们称这个项目为my-project,并假设它依赖于包alexandriacl-xlsx

$ make-project my-project --depends-on alexandria cl-xlsx

tree它列出它的组成部分:

$ tree my-project
my-project
├── my-project.asd
├── README.markdown
├── README.org
├── src
│   └── main.lisp
└── tests
    └── main.lisp2 directories, 5 files

由通用 Lisp 标准包系统 ASDF(另一个系统定义工具)构建的 meta-info 项目文件my-project/my-project.asd的内容是:

(defsystem "my-project"
  :version "0.1.0"
  :author ""
  :license ""
  :depends-on ("alexandria"
               "cl-xlsx")
  :components ((:module "src"
                :components
                ((:file "main"))))
  :description ""
  :in-order-to ((test-op (test-op "my-project/tests"))))(defsystem "my-project/tests"
  :author ""
  :license ""
  :depends-on ("my-project"
               "rove")
  :components ((:module "tests"
                :components
                ((:file "main"))))
  :description "Test system for my-project"
  :perform (test-op (op c) (symbol-call :rove :run c)))

Common Lisp 中的测试被组织成独立的包——因此,.asd文件将项目的测试准备成一个独立的包,并将:rove添加为它的依赖项之一。

填写作者、许可证和描述部分。

在您的项目中,当引入新的包时,它们应该首先包含在两个包系统的:depends-on列表中。

:components部分列出了属于这个打包系统的所有文件和文件夹(列出的文件名没有以.lisp结尾!).所以每当你添加一个新的文件或文件夹时,你应该更新这个文件中的两个defsystem!

my-projcet/src/main.lisp的内容是:

(defpackage my-project
  (:use :cl))
(in-package :my-project);; blah blah blah.

你把你的包码写到;; blah blah blah.里。

每当您需要依赖项时,将它们添加到(:use :cl)列表中。

在这种情况下,用(:use :cl :alexandria :cl-xlsx).来完成它是合理的

或者,如果您从这些包中导入单个函数,您可以通过以下方式仅显式导入这些函数:

(defpackage my-project
  (:use #:cl
        #:cl-xlsx) ;; this package's entire content is imported
  (:import-from #:alexandria ;; package name
                #:alist-hash-table) ;; a function from :alexandria
  (:export #:my-new-function))

:export子句中,您声明了哪些函数应该被导出并公开——从该文件外部可见。

使用 Roswell 和 rove 设置测试

在 Common Lisp 中测试通常用FiveAMprove来完成。

rove是和Roswell玩得好的prove的继任者。

通过以下方式安装:

$ ros install fukamachi/rove

在您的解释器中,首先通过以下方式加载它:

(ql:quickload :rove)

通过以下方式输入其名称空间:

(use-package :rove)

测试的语法非常简单。

阳性和阴性检查

通常,当你进行测试时,你会检查真假。

rove为您提供okng(否定)检查功能。

;; expect true
(ok (= (+ 1 2) 3));; expect false
(ng (eq 'a 'a));; add error message
(ok (= 1 1) "equality should be true")
(ng (< 3 2) "3 and 2 should not be equal")

您可以检查错误、标准输出和宏扩展:

(ok (signals (/ 1 0) 'division-by-zero)) 
;; tests for a specific, expected error(ok (signals (/ 1 0)))                   
;; tests for error occurrence itself without exact specification

控制台的输出:

(ok (outputs (format t "hello") "hello"))

以及一个带有愚蠢宏的宏展开示例。

(defmacro my-sum (&rest args) `(+ ,@args))(ok (expands '(my-sum 1 2 3) '(+ 1 2 3)));; which is:
(ok (expands '<macro-call> '<expected macroexpand-1 result>))

将几个检查分组到一个测试名称中,并对它们进行注释

你应该写下为什么/做什么,因为你正在做检查。有人说“测试是最精确的文档形式。”—所以它们也应该为人类读者而写。

(deftest <test-name>
  (testing "what the test is for"
    (ok <expr>)
    (ok <expr>)
    (ng <expr>))
  (testing "another subpoint"
    (ok <expr>)
    (ng <expr>)
    (ng <expr>)))

下面是一个函数及其测试示例:

(defun my-absolute (x) (if (< x 0) (* -1 x) x))

这就是考验:

(deftest my-absolute
  (testing "negative input should give positive output"
    (ok (eq (my-absolute -3) 3))
    (ng (eq (my-absolute -3) -3)))
  (testing "positive input should give positive output"
    (ok (eq (my-absolute 3.1) +3.1))
    (ng (eq (my-absolute 2.3452) + 2.4352)))
  (testing "zero should always give zero"
    (ok (zerop (my-absolute 0))
        (zerop (my-absolute 0.0000000))))

使用以下命令从控制台运行测试:

(run-test 'my-absolute)

将一个或多个测试分组到测试包(测试套件)中

想象一下,您创建了一个名为my-package的项目或包。

在 package/project 文件夹中应该有一个包含这个包的测试文件(测试套件)的tests文件夹。

cl-projects已经创建了骨架,在我们的例子中是tests/main.lisp

它自动生成的内容是:

(defpackage my-project/tests/main
  (:use :cl
        :my-project
        :rove))
(in-package :my-project/tests/main);; NOTE: To run this test file, execute `(asdf:test-system :my-project)' in your Lisp.(deftest test-target-1
  (testing "should (= 1 1) to be true"
    (ok (= 1 1))))

每当我们需要包作为新的依赖项或它们的单一功能时,我们应该完成这个defpackage定义,类似于我们为my-project/my-project/maindefpackage表达式所做的。

如果我们创建几个测试文件/套件,每个文件都必须在.asd文件的defsystem:components部分注册。这样(asdf:test-system :my-project)就包含了所有的测试服。

增加准备和善后程序

在测试软件包之前,setup函数会对其列出的命令进行一次评估。例如,这对于建立数据库或创建临时目录非常有用。

测试运行后,可以使用teardown命令清理临时目录或其他生成的文件。

;; after the defpackage and in-package declarations:(setup
  (ensure-directories-exist *tmp-directory*));; all the tests of the package(teardown
  (uiop:delete-directory-tree *tmp-directory* validate t 
                              :if-does-not-exist :ignore))

对于应该在每次测试之前或之后运行的命令,请使用:

(defhook :before ...)
(defhook :after ...)

常规设置

为了让测试具有特殊的风格,您可以指定全局变量:

(setf *rove-default-reporter* :dot)  ;; other: :spec :none
(setf *rove-debug-on-error* t)

跑步测试服

(asdf:test-system :my-project)(rove:run :my-project/tests);; you can modify their style when calling to run
(rove:run :my-project/tests :style :spec) ;; other :dot :none

FiveAM,另一套测试服,非常相似。

使用 Travis-CI 自动化测试

由于在[https://raw.githubusercontent.com/roswell/roswell/release/scripts/install-for-ci.sh](https://raw.githubusercontent.com/roswell/roswell/release/scripts/install-for-ci.sh.)中有一个脚本,它负责安装Roswell中所有可用的实现,所以设置 Travis CI 被大大简化了。

首先,你必须在 Travis CI 注册一个账户。

将 Travis CI 与 GitHub 或 Bitbucket 或 GitLab 连接在这里的和这里的中进行了解释。

简而言之:你必须点击你的个人资料图片,然后点击设置,并选择你希望 Travis CI 监控的存储库。(在我们的案例中,这将是 GitHub repo 窝藏 *my-project* )。

接下来要做的就是创建一个名为.travis.yml的文件,并将它放在项目根文件夹中(由 git 运行)。一旦您 git 添加新的.travis.yml文件并 git 提交和推送它,Travis CI 将开始“照顾”您的存储库。

对于只使用最新的 SBCL 二进制文件的测试,一个非常简短的.travis.yml就足够了:

language: common-lisp
sudo: required

install:
  - curl -L https://raw.githubusercontent.com/roswell/roswell/release/scripts/install-for-ci.sh | sh

script:
  - ros -s prove -e '(or (rove:run :my-project/tests) (uiop:quit -1))'

通过将sudo:字段设置为false,用户可以激活 Travis CI 来使用新的container-based infrastructure(比旧系统更快的测试启动时间)。

下面的.travis.yml脚本让Roswell在每次提交和 git 推送代码时运行两个实现的漫游测试。

language: common-lisp
sudo: false

env:
  global:
    - PATH=~/.roswell/bin:$PATH
    - ROSWELL_INSTALL_DIR=$HOME/.roswell
  matrix:
    - LISP=sbcl-bin
    - LISP=ccl-bin

install:
  - curl -L https://raw.githubusercontent.com/roswell/roswell/release/scripts/install-for-ci.sh | sh
  - ros install rove
  - ros install gwangjinkim/cl-xlsx script:
  - ros -s rove -e '(or (rove:run :my-project/tests :style :dots) (uiop:quit -1))'

env:下面的matrix:部分列出了要测试的 Common Lisp 的不同版本和实现。

这是一个成熟的.travis.yml文件,它测试了更多的 Common Lisp 实现。

language: common-lisp
sudo: false

addons:
  apt:
    packages:
      - libc6-i386
      - openjdk-7-jreenv:
  global:
    - PATH=~/.roswell/bin:$PATH
    - ROSWELL_INSTALL_DIR=$HOME/.roswell
  matrix:
    - LISP=sbcl-bin
    - LISP=ccl-bin
    - LISP=abcl
    - LISP=clisp
    - LISP=ecl
    - LISP=cmucl
    - LISP=alisp

matrix:
  allow_failures:
    - env: LISP=clisp
    - env: LISP=abcl
    - env: LISP=ecl
    - env: LISP=cmucl
    - env: LISP=alisp

install:
  - curl -L https://raw.githubusercontent.com/roswell/roswell/release/scripts/install-for-ci.sh | sh
  - ros install fukamachi/rove
  - ros install gwangjinkim/cl-xlsx

cache:
  directories:
    - $HOME/.roswell
    - $HOME/.config/common-lisp

script:
  - ros -s rove -e '(or (rove:run :my-project/tests :style :dots) (uiop:quit -1))'

因为clispabclalisp和/或cmucl需要openjdk-7-jreclisp需要 libc-i386,所以addons:apt:部分必须存在,它们必须使用apt安装。

cache:下面列出的目录被缓存(为了更快的启动)。

install:部分列出了当其中一个组件丢失时需要为您的系统进行的安装,按照给定的顺序。

实现是由https://raw.githubusercontent.com/roswell/roswell/release/scripts/install-for-ci.sh脚本准备的,因此单个实现的安装不必明确列在install:下。如果没有Roswell,测试不同的实现将需要更多的工作。Roswell安装并测试最新版本的实现。

如果您的测试包本身有一些更简单的命令行命令,那么script: 命令看起来会更简单。

查看 Travis CI 文档,了解更多信息(在不同操作系统上进行测试等。)

工作完成后,让 Travis CI 通过电子邮件或电报通知您

添加到.travis.yml一个:

notifications:
  email:
    - my-email@gmail.com

会让它在每次作业运行时通知您。

更好一点的是通过电报发出通知,如下文所述:

您添加到.travis.yml:

after_script:
  - bash ./丨t丨e丨l丨e丨g丨r丨a丨m丨s丨_notification.sh

并将一个名为丨t丨e丨l丨e丨g丨r丨a丨m丨s丨_notification.sh的脚本放到您的项目根文件夹中:

#!/bin/sh

# Get the token from Travis environment vars and build the bot URL:
BOT_URL="https://api.丨t丨e丨l丨e丨g丨r丨a丨m丨s丨.org/bot${丨t丨e丨l丨e丨g丨r丨a丨m丨s丨_TOKEN}/sendMessage"

# Set formatting for the message. Can be either "Markdown" or "HTML"
PARSE_MODE="Markdown"

# Use built-in Travis variables to check if all previous steps passed:
if [ $TRAVIS_TEST_RESULT -ne 0 ]; then
    build_status="failed"
else
    build_status="succeeded"
fi

# Define send message function. parse_mode can be changed to
# HTML, depending on how you want to format your message:
send_msg () {
    curl -s -X POST ${BOT_URL} -d chat_id=$丨t丨e丨l丨e丨g丨r丨a丨m丨s丨_CHAT_ID \
        -d text="$1" -d parse_mode=${PARSE_MODE}
}

# Send message to the bot with some pertinent details about the job
# Note that for Markdown, you need to escape any backtick (inline-code)
# characters, since they're reserved in bash
send_msg "
-------------------------------------
Travis build *${build_status}!*
\`Repository:  ${TRAVIS_REPO_SLUG}\`
\`Branch:      ${TRAVIS_BRANCH}\`
*Commit Msg:*
${TRAVIS_COMMIT_MESSAGE}
[Job Log here](${TRAVIS_JOB_WEB_URL})
--------------------------------------
"

一个电报机器人,你通过从你的电报账户向@Botfather : /newbot写信来初始化它——它要求你给它一个名字,其他任何机器人都不会给它。如果你的名字通过了,你会得到一个机器人。然后向@Botfather写:/token,它会问你向哪个机器人要令牌。这个令牌必须用于脚本中的丨t丨e丨l丨e丨g丨r丨a丨m丨s丨_TOKEN

使用工作服为 Travis 添加代码覆盖率

为此,我们遵循Roswell文档Boretti 的博客,他使用了一个Roswell独立的脚本和一个使用FiveAM作为测试系统的脚本

与 Travis CI 类似,您必须在工作服中创建一个帐户。

然后,您在.travis.yml文件中标记应该评估代码覆盖率的实现:

env:
  matrix:
    - LISP=sbcl COVERALLS=true
    - LISP=ccl

还应规定工作服的安装命令:

install:
  # Coveralls support
  - ros install fukamachi/cl-coveralls

最后,脚本调用必须修改为:

 - ros -s rove 
        -s cl-coveralls
        -e '(or (coveralls:with-coveralls (:exclude (list "t"))
                (rove:run :quri-test))
                (uiop:quit -1))'

结束——也是开始!

现在,我们已经为 2021 年建立了一个完整的公共 Lisp IDE 系统。

祝 Lisp Hacking 快乐!

(欢迎评论区的建议和反应!—关于设置*Roswell**cl-projects*以及用* *rove* 进行测试的部分,我从用日语写了一本书的日本朋友那里了解到: *SURVIVAL COMMON LISP* —作者有: *Masatoshi Sano* *Hiroki Noguchi* *Eitaro Fukamachi* *gos-k**Satoshi Imai* *cxxxr* 然而,许多信息都可以在包和工具的文档中找到。)*

为初学者定制顶点 AI 管道[第 1 部分]

原文:https://towardsdatascience.com/how-to-set-up-custom-vertex-ai-pipelines-step-by-step-467487f81cad?source=collection_archive---------0-----------------------

如何设置自定义顶点人工智能管道的分步教程

unsplash.com 尼康公司

使用顶点人工智能的多点操作

本文的目标是分享我关于如何使用端到端 MLOps Vertex AI 平台从零开始在生产中部署机器学习算法的经验。

尽管主题是讨论过的,但这篇文章的新颖之处在于,我已经解决了从创建管道、提交、触发的整个周期,并且我还展示了如何以实时或批处理模式测试服务部分的例子。此外,我也提到了所有的技术问题,你可以应付沿途节省你的时间。

要阅读更多关于 Vertex AI 的内容,请参考谷歌官方文档[ 1 ]。谷歌推出了一个很好的图表,恢复了 Vertex AI 提供的所有组件。

顶点人工智能功能@谷歌云

既然你对顶点 AI 有了概念,那就开始吧。

使用案例

我将解决在 Kaggle 上讨论的一个众所周知的用例预测葡萄酒质量数据下载自 UCI 机器学习库@ source【Cortez et al .,2009】。
我们将使用一种常见的监督机器学习算法,如随机森林。

这个想法是基于以下标准来预测葡萄酒的质量:

  • 挥发酸度: 挥发酸度是葡萄酒中存在的气态酸。
  • 固定酸度: 主要是 固定酸 葡萄酒中发现的有 酒石酸琥珀酸柠檬酸 苹果酸**
  • 残糖:发酵后剩余的 糖分的量。
  • 柠檬酸: 它是一种弱有机酸,天然存在于柑橘类水果中。
  • 氯化物:葡萄酒中所含的 盐量。
  • 游离二氧化硫: So2 用于防止葡萄酒被氧化和微生物腐败变质。
  • pH: 葡萄酒中的 pH 用于检测酸度
  • 密度
  • 硫酸盐 :添加亚硫酸盐保鲜,保护 葡萄酒 免受氧化和细菌侵害。
  • 酒精: 葡萄酒中所含酒精的百分比。

要预测的目标是基于葡萄酒的质量等级:

  • 好酒= 1 (品质等级≥7 )
  • 劣酒= 0 (质量等级< 7 )

流水线架构

用例使用四个管道组件(数据准备、训练、评估、部署)来实现。每个管道组件都使用工件注册中心提供的容器映像。在本文中,我们将只使用预编译的基本映像。在下一篇文章中,我将给出更多关于如何创建你自己的顶点 AI 自定义 docker 图像的见解。

架构概述。

步骤:

一.建立环境

二。安装一个虚拟 env 并在 JupyterLab 中激活它

三。创建管道组件:加载数据,训练模型,评估模型,部署模型。****

四。创建管道

动词 (verb 的缩写)运行管道

不及物动词触发管道。

****一、设置环境

环境:

  • Vertex AI Workbench(用 Python 3 在虚拟环境中运行的 Jupyter 笔记本)
  • Python 3
  • 虚拟
  • Kubeflow 管道组件
  • 在我的下一篇文章中,我会给你更多关于如何构建自定义图像的见解

如果你想激活笔记本中的,你应该安装jupyter _ contrib _ nb extensions。

安装 kubeflow 组件。

如果 API 未启用,请启用它们。

导入库。

设置全局变量。

二。安装一个虚拟 env 并在 JupyterLab 中使用它

执行以下代码:

重启 Jupyter 并选择新的内核:

三。创建管道组件****

请注意,现在,我将使用 Artifactory 注册表中预编译的 docker 图像。此处见预建容器列表

下图描述了我们将要实现的整体组件。

管道图

加载数据

第一个组件是 get_wine_data。该组件使用了一个预构建的 Python3.9 基础映像,其中我还添加了:pandas、sklean 和 pyarrow。

逻辑很简单,我们读取 葡萄酒质量数据集 ,w e 选择best _ quality**作为标签,我们将数据拆分成训练和测试数据集。
组件的配置存储在一个名为 get_wine_data.yaml 的. yaml 文件中,您可以进一步使用它来运行组件,而无需重写代码。yaml 文件对于生成组件模板非常有用。**

训练模型

组件 train_winequality 使用预构建的 Python 3.9 基础映像,并将存储在 Google Storage 上的训练数据集作为输入。它将框架的名称记录为模型元数据。如果您想要使用顶点 AI 元数据功能,您需要使用model . metadata["name _ of _ the _ metric "]= value 记录指标。**

模型以 pickle 格式存储在 Google Storage 的 PIPELINE_ROOT 路径下。请记住,支持的模型格式是:scikit-learn: model.joblibmodel.pkl,XGBoost: model.bst,
Tensorflow model.pb.

❗注意,模型需要用model这个名字保存

评估模型

评估组件 winequality_evaluation 依赖于预编译的 Python 3 基础映像,其中我们使用“pip”安装了额外的包,如 pandas 和 sklearn。

它输入测试数据集、训练模型和预定义的精度阈值。然后,它计算准确度、ROC 曲线和混淆矩阵,并检查准确度是否高于预定义的阈值。

部署模型

组件 deploy_winequality 使用与之前组件相同的基础映像。它输入项目名称、区域、训练模型和服务容器的 URL。

要部署模型,我们首先创建一个端点,将模型上传到 Vertex AI models,然后将模型部署到端点。

四。创建管道

要定义唯一的管道作业名称,可以使用时间戳。

**from datetime import datetime
TIMESTAMP =datetime.now().strftime("%Y%m%d%H%M%S")
DISPLAY_NAME = 'pipeline-winequality-job{}'.format(TIMESTAMP)**

管道本身帮助您以无服务器的方式编排 ml 工作流。它接受一些参数作为输入,比如包含原始数据的 URL、API 端点和项目。它使用以下操作符作为步骤:data_op、train_model_op、model_evaluation_op 和 deploy_model_op。deploy_model_op 仅在训练模型的精度高于阈值时执行。为此,您需要使用 dsl 的条件管道特性()。条件

动词 (verb 的缩写)运行管道

流水线编译生成ml _ wine quality . JSON作业规范文件。
使用编译器,指定 pipeline_funcpackage_path

**compiler.Compiler().compile(pipeline_func=pipeline,
        package_path='ml_winequality.json')**

使用先前生成的作业规范文件创建一个运行。

**start_pipeline = pipeline_jobs.PipelineJob(
    display_name="winequality-pipeline",
    template_path="ml_winequality.json",
    enable_caching=True,
    location=REGION,
)**

运行管道。

**start_pipeline.run()**

单击运行命令生成的 HTTPS 链接,查看生成的 UI 管道图的状态。

不及物动词触发管道

检查是否启用了以下 API:

  • 云函数
  • 云调度程序

请确保您的服务帐户拥有云功能管理员、服务帐户用户和云调度服务代理的权限。创建重复性作业后,您可以在云调度程序控制台中列出它。

下面你可以找到一个循环工作的例子。使用计划参数(接受 crontab 格式)提及重复间隔。

七。模拟批量预测和实时预测

我们定义了几个变量:

  • 我们将使用的模型名称
  • 我们部署模型的入口点
  • 包含准备进行预测的批处理实例的存储桶
  • 预测模型的 ID(每个上传的模型都有一个唯一的 ID)
  • 我们存储预测输出的 Google 存储目标。

为了创建一个批处理预测作业,我们需要初始化 AI 平台,然后是模型资源名和 batch_predict 调用。

batch_predict 方法请求五个主要参数,例如作业的名称、要预测的实例的路径、存储预测的路径、计算预测所需的机器类型以及输入数据的类型(csv、json)。

批量预测

提交作业后,转到 Vertex AI 中的批处理预测控制台,检查作业的状态:

查找批量预测日志的提示→在操作>记录>日志浏览器中键入:

**resource.labels.service=”aiplatform.googleapis.com”** 

实时预测

每个预测请求必须最大。1.5 MB。我们使用端点。预测** API。在下面的例子中,我们首先初始化 AI 平台,给出项目和位置。然后,我们声明我们计划用于预测的端点的 ID。最后,我们调用“endpoint.predict”方法,传入数据进行预测。**

预测输出是一个. json,包含如下条目:

**Prediction(predictions=[0.0], deployed_model_id='5026685687215161344', explanations=None)**

在下一篇文章中,我将解释如何构建你自己的定制 docker 图像,并在管道中使用它们。

笔记本的源代码可以在我的 github 账户上找到。

强占

[1] 顶点 AI 流水线简介
【2】流水线简介
【3】顶点流水线
【4】无服务器机器学习流水线 带顶点 AI 的 MLOps】

感谢您的阅读!

如果你想在收件箱里收到我未来的故事,别忘了订阅。

如果您喜欢阅读我的故事,并希望支持我成为一名作家,请考虑注册成为 Medium 会员,并获得数千篇数据工程和数据科学文章。

**https://medium.com/@anna.bildea/membership

LinkedIn Twitter 上找我!**

如何为 Data Studio 报告设置 Google Analytics 跟踪

原文:https://towardsdatascience.com/how-to-set-up-google-analytics-tracking-for-google-data-studio-reports-c0c1eec0b777?source=collection_archive---------33-----------------------

监控您的报告的受欢迎程度

乔纳森·弗朗西斯卡在 Unsplash 上拍摄的照片

谷歌数据工作室报告是一个巨大的打击,尤其是在企业领域。

它是免费的,易于使用,并利用数百个潜在的集成,实现了整体和粒度级别报告的巨大潜力。

虽然我最近谈到了谷歌数据工作室的局限性,但现在我想谈谈它有一个很酷的、隐藏的特性——追踪。

没错,Google Data Studio 报告允许嵌入 Google Analytics tracking-id,这将允许对您创建的漂亮报告的受欢迎程度进行更强大的分析数据。

我将向您展示如何通过四个步骤来添加它。

1.创建 Google 分析属性。

假设您已经创建了您的 Google Analytics 帐户,您可以通过导航到您帐户的管理页面并点击属性列中的创建属性来创建 Google Analytics 属性。

然后,您可以命名该属性,在本例中,按照“Data Studio Reports”的方式命名,并调整其他属性设置,例如:

  • 属性时区
  • 无论你是否希望它成为一种普遍属性
  • 网站 URL 和协议
  • 其他信息(如业务信息)

设置调整完毕后,点击“创建”。

Google 在其分析支持文档中提供了关于如何完成这一步骤的详细教程。

一旦创建了您的属性,您就可以继续下一步。

2.从属性设置中复制属性的 tracking-id。

导航至管理部分(点击左侧按钮上的设置图标)。

然后选择属性设置选项卡。

tracking-id 位于设置的第一部分(显示了上下文的其余页面设置)。选择并复制跟踪 id。

以下是谷歌对这个 ID 的说法:

跟踪 ID 是一个类似 UA-000000–2 的字符串。第一组数字(-000000,在上面的例子中)指的是您的账号,第二组数字(-2)指的是与该账户相关的特定房产号

只有当跟踪 ID 也包含在支持此类跟踪技术的其他仪器中时,分析才有效。

因此,让我们前往 Data Studio 并完成集成。

谷歌分析账户截图,显示追踪 id,作者图片

3.打开 Data Studio 报表并导航到报表设置。

在 Data Studio 中,单击文件,然后单击报告设置。

Google Data Studio 报告的屏幕截图,显示了报告设置菜单的位置,图片由作者提供

4.插入 GA 跟踪 id

在 Google Data Studio 报告中插入 GA tracking-id 代码。

这将使您能够获得有关报告使用情况的分析数据,包括用户行为数据、用户位置、使用的系统和设备等。

Google Data Studio 报告的屏幕截图,显示了 GA tracking-id 的粘贴位置,图片由作者提供

瞧啊。现在,您可以监控报告的性能。

在与客户合作时,始终确保他们的需求得到满足,他们的反馈被纳入报告的设计中,以确保整个组织采用的可能性更高。

以下是该过程的概述:

要为您的 Google Data Studio 报告设置跟踪,请在 GA 中创建一个属性,并从属性设置部分复制其跟踪 id。然后,在面板中导航到任何 Google Data Studio 的报告设置,并插入跟踪 id。

感觉好奇?

欲了解更多 Data Studio 教程和技巧,请查看:

</4-limitations-of-google-data-studio-that-advanced-users-should-watch-out-for-fb2a907eaf5c> https://medium.com/bite-sized-marketing/how-to-create-charts-that-display-negative-numbers-in-google-data-studio-4ecbb58c3a79

如何为 Julia 设置数据科学

原文:https://towardsdatascience.com/how-to-setup-julia-for-data-science-6914af62b3a6?source=collection_archive---------17-----------------------

简要概述在您的机器上为数据科学正确设置 Julia 所需的步骤。

https://unsplash.com/photos/VCtI-0qlVgA

介绍

Julia 编程语言是一种相对年轻的语言,近年来在数据科学领域掀起了一阵风暴。这是因为 Julia 语言的特性非常有利于科学计算和机器学习。这是因为数字准确性、计算速度和科学语法的严格结合。考虑到语言的所有这些属性,很容易理解为什么任何数据科学家可能会考虑选择编程语言。然而,当你开始学习这门语言时,你可能会遇到 Julia 编程语言最大的问题,那就是它的普及性。

与大多数其他编程语言相比,Julia 的采用率非常低,用户群和软件包生态系统也比与之竞争的大多数其他统计语言小得多。这使得学习这门语言更加困难,因为可用的资源少得多。此外,如果对于一些用户来说,让这种语言在他们的机器上正常运行都太困难,那么这些用户就不太可能对网站上的语言之外的语言非常熟悉。

安装 Julia

当然,在这方面,设置 Julia 的第一步是实际安装编程语言。当然,根据您可能运行的操作系统,这个过程会有很大的不同。在大多数类似 unix 的操作系统上,比如 MacOS、Linux 和 FreeBSD,这个包可以在你的包管理器中找到。然而,我想指出的是,这可能不是您在这些系统上安装 Julia 语言的方式。这是因为这些包管理器版本经常是非常过时的,在某些情况下,您可能最终得到的是一个古老的、本质上无用的 Julia 版本。即使在版本高于 1.0 突破性版本的情况下,您也可能会发现有许多功能被遗漏,并且文档可能不准确。此外,当涉及到在生态系统中使用包时,兼容性总是一个大问题。

在这些类 Unix 系统上,我当然推荐直接从 Julia 网站下载语言。在这方面,第一步可能是下载文件并将其放在所需的目录中。我通常在 bash 中使用 wget 来实现这一点,但是在 web 浏览器或终端中实现这一点本质上没有任何区别。下载并解压软件包后,下一步是添加到您的系统的路径,以便您的系统知道您的 Julia 安装的实际位置。在 Linux 上,我们可以通过编辑我们的~/来做到这一点。bashrc 或者~/。bash_profile 文件。

wget https://julialang-s3.julialang.org/bin/linux/x64/1.6/julia-1.6.0-linux-x86_64.tar.gz
tar zxvf julia-1.6.0-linux-x86_64.tar.gz

现在我们将这一行添加到我们的~/中。bashrc

export PATH="$PATH:/julia/directory"

我通常把它和我的全网汇编器一起放在/opt 中,但是你也可以把它放在根文件系统下的任何地方。

至于在 MacOS 上的安装,这个过程从网站上提供的 Julia dmg 文件开始。或者,您可以使用 ln 将调用添加到 PATH:

ln -s /Applications/Julia-1.6.app/Contents/Resources/julia/bin/julia /usr/local/bin/juli

对于 Windows,我们当然会运行一个可执行文件。exe 文件,就像您通常对该操作系统上的任何应用程序所做的那样。之后,您可能想像以前一样添加路径。当然,这与你在 Windows 上得到的基于 MSDOS 的 nt 命令终端有些不同。在 Windows 中,将它添加到 PATH 的过程有点像这样:

  1. 打开 Run (Windows 键+ R),键入rundll32 sysdm.cpl,EditEnvironmentVariables并回车。
  2. 在“用户变量”或“系统变量”部分下,找到带有“路径”的行,然后单击编辑。
  3. 将出现“编辑环境变量”界面。在这里,单击“新建”,并粘贴到安装阶段记录的目录中。这应该类似于C:\Users\JohnDoe\AppData\Local\Programs\Julia 1.6.0\bin
  4. 单击确定。你现在可以从命令行运行 Julia,输入julia

开发环境

当谈到 Julia 的开发环境时,有很多不同的选项,我个人认为都很棒。

笔记本电脑

首先,在笔记本电脑领域,我们有三种选择:

  • IJulia.jl
  • Pluto.jl
  • 海王星. jl

所有这些都是我们需要添加的 Julia 包,因此为了启动笔记本服务器,我们可能需要首先确定哪台笔记本服务器最适合我们的工作。就我个人而言,比起冥王星和海王星,我更喜欢 good-ole Jupyter,我相信这可能有点令人头痛,但当它真正稳定和工作良好时,还有一段不错的路要走。我写了一篇关于这个主题的观点鲜明的文章,你可以在这里查看,看看 Pluto.jl 是否适合你:

也就是说,使用像 Pluto 或 Neptune 这样的解决方案的优势在于,这两种笔记本服务器都是用 Julia 编程语言编写的。换句话说,我们可以省去 IPython 内核的中间人,直接通过它自己运行 Julia,这肯定会带来一些性能上的好处。此外,冥王星和海王星文件存储在。jl Julia 文件,而不是 IPython 笔记本文件——这很酷,因为这样你就可以一次编写代码,让它在 REPL 和笔记本上都可以工作。

具体来说,Neptune.jl 是最近发布的对 Pluto.jl 的修改。Neptune.jl 的实现实际上消除了我在使用 Pluto.jl 时遇到的许多问题。这些例子包括交互性,这有时甚至会有点侵入性,会妨碍您编写代码。IJulia 对于 Julia 来说只是一个 Jupyter 内核,对于我来说已经是个人喜好最有效的解决方案了。话虽如此,尝试一下也无妨。

记住这一点,为了使用这些包,我们真正需要做的就是通过 Julia 的包管理器 Pkg 添加它们。当然,IJulia 是个例外,它需要安装 Jupyter 才能正常工作。为了添加这些包,我们首先需要进入朱莉娅·REPL。通过在终端或命令窗口中键入“julia ”,您可以在所有操作系统上通用地做到这一点。一旦你进入朱丽亚·REPL,你就可以按]进入 Pkg REPL。虽然 Pkg 本身是一个你可以随时从 Julia 调用的包,但是我当然更喜欢用这种方式。现在,我们可以使用 add 命令将包作为参数来添加我们的包:

julia > ]
pkg > add IJulia
pkg > add Pluto
pkg > add Neptune

有了 IJulia,Julia 内核现在应该出现在 Jupyter 的内核列表中了,这就是全部了。对于 Neptune 和 Pluto,您需要导入包并使用 run()函数来启动您的服务器。

using Neptune; Neptune.run()
using Pluto; Pluto.run()

文本 IDE

除了拥有笔记本服务器之外,您可能还需要一个用于常规文本的开发环境。为此,我最喜欢的解决方案是 Atom 和 Juno。然而,还有一个我从未使用过的 VSCode 开发环境。Juno 实际上在技术上已被弃用——嗯,没有被弃用,但它收到的唯一更新是安全和错误修复,没有计划向 Juno 软件包添加新功能。与大多数 Atom 包的实例一样,您可以通过首先进入菜单栏并选择 edit>preferences 来安装它。

这将调出一个偏好菜单。在该菜单的左侧,您应该会看到一个小加号,上面写着“install”,您可以在这里安装 Juno。这也会安装 Juno.jl 包,嘣!你现在可以编辑朱莉娅文本!

环境

为了使用 Julia 语言,最不希望的就是能够使用虚拟环境。在 Julia 中,这个过程非常简单,完全通过 Pkg 包管理器来完成。我们可以从 Pkg 调用 activate 命令或方法来创建一个新的虚拟环境。这将创建一个包含 Project.toml 文件的文件夹。该项目文件将包含项目的所有依赖项,其形状类似于典型的配置文件。

julia > ]
pkg > activate env

结论

在过去的一两年里,朱莉娅语言确实越来越受欢迎。这是因为该语言中所有以数据科学为中心的特性,因为数据科学最近已经成为计算世界中一个相当受欢迎的话题。我认为,有了这些新用户,许多人注定会在安装过程中迷失。考虑到这一点,我希望这篇文章成功地解决了这个问题——如果这个问题从来没有出现过,也许它会激起对这门语言的一点兴趣!最棒的是,现在你也知道如何安装它了!

如何在 2 分钟内为您的 Python 笔记本设置日志记录

原文:https://towardsdatascience.com/how-to-setup-logging-for-your-python-notebooks-in-under-2-minutes-2a7ac88d723d?source=collection_archive---------15-----------------------

教程 PYTHON 日志记录

理解、安装、使用和享受 Python 中的标准日志包的分步指南

照片由杰曼特里像素上拍摄

G regor 是一位热爱解决数据谜题的数据科学家。一天,他接到一个新项目,想马上投入到这个新任务中。他对自己最喜欢的编码工具的选择有所准备,并且是一个大师,知道使用哪个包,并且已经形成了如何构建数据项目的想法。他不考虑伐木。也就是说,不是一开始。当大部分代码都写好了,只有一个他试图在代码中指出并找到的错误时,他才恍然大悟。一旦他击碎了他的 bug 并重写了他有缺陷的代码,他意识到他的代码充斥着 *print()* 语句。在传递他的解决方案之前,他需要把它们拿出来。

1.介绍

也许你能理解这个小场景。但是我知道有一个简单的方法可以弥补我的缺点。我花了一些时间研究了标准的 python 日志框架,我将在这里愉快地为我未来的自己解释它,当然,也为你。

我将为我们提供一个复制-粘贴-日志-代码-模板,使日志简单。此外,我将分享关于三个最重要的日志概念的附加信息。文章结尾是我在研究过程中发现的关于日志记录的相关文章。

2.一个复制粘贴模板,立即与您的代码一起工作

这是用于登录到您的控制台的复制粘贴模板。在第 3 节(日志处理程序)中找到一个日志模板来设置日志文件。

基于:https://docs . python . org/3/how to/logging . html # logging-advanced-tutorial

附加提示

  1. 您可以根据您的任务或开发状态更改日志级别,无需在调试会话后删除打印语句
  2. 可以将语句记录到不同的输出中。用于审计目的的日志记录的文件,开发期间带有调试级别的控制台输出,或者生产期间只有警告和错误消息的控制台输出。
  3. 尝试为运行您的代码的其他开发人员和管理员编写有意义的日志语句。
  4. 只要有可能,就提供上下文信息,例如(散列的)用户 id、会话 id,以便能够进行调试或错误处理

3.三个伐木火枪手

图片由作者提供;日志组件概述(记录器(what)、处理程序(where)和格式化程序(how))

如果您已经使用过 Python 或者熟悉编程,那么这个代码块可能已经足够了。为了更容易理解和记忆,我试着把它和 WHAT — WHERE — HOW 联系起来。

  • 指的是记录器本身以及不同的日志级别
  • 这里的是指测井输出或者说处理程序应该去的地方。这可能包括您的控制台和一个文件。
  • 如何指的是日志语句应该如何看起来如何或者应该包括什么?这是由格式器完成的。

什么—日志级别 下面是五个日志级别的概览表。如果你遵循 GitHub 的要点,你还会看到,对于我在应用程序生命周期中添加的每个级别,你都可以使用日志级别。

日志级别概述

如果您将日志级别设置为调试 (logger.setLevel(logging。DEBUG))那么您编写的所有日志语句(DEBUG、INFO、WARNING、ERROR、CRITICAL)都将被记录。如果您将日志级别设置为警告(logger.setLevel(logging。WARNING))则只记录日志语句(警告、错误、严重)。

图片由作者提供;在给定的日志级别配置下,将执行哪个日志语句

这将给你带来好处,让在代码中使用所有日志语句,甚至当你进入生产时。您只需更改日志级别

开发期间,您可能会使用两个日志级别之一 DEBUG 或 INFO。在调试期间,您将使用 DEBUG。当您将代码部署到产品中时,您应该将日志级别设置为警告。下面您会发现两个具有不同日志级别的代码示例,因此会有不同的日志输出。

示例 01 —日志级别设置为调试

日志示例—调试

DEBUG - User User XYZ provided the numbers 100 and 0 for calculation
ERROR - Calculation was unsuccessful for user User XYZ with the inputs 100 and 0
ERROR - division by zero

示例 02 —日志级别设置为警告

日志示例—警告

ERROR - Calculation was unsuccessful for user User XYZ with the inputs 100 and 0
ERROR - division by zero

请注意,在第二个示例中,省略了调试日志语句,因为日志级别设置为警告,因此仅显示警告错误关键语句。

WHERE —日志处理程序 在我自己的经验中,我使用的是文件控制台(流)处理程序。然而,python 日志文档列出了 15 种不同的日志处理程序。请根据您的具体需求进行检查。如何设置 StreamHandler 登录控制台如上图所示。

在这个例子中,我将向您展示如何设置一个 FileHandler 来在控制台输出旁边创建一个日志文件。

使用日志文件记录设置

如何格式化您的日志语句 我发现的大多数示例都是以这种方式格式化的,但是当然,您可以根据自己的需要调整配置:

格式化程序配置

  1. 日期时间信息
  2. 记录器的名称(使用 getLogger-function 提供的名称)
  3. log 语句的日志级别
  4. 日志消息本身。

4.关于日志的更多文章

在这篇文章中,我试图让你在下一个 Python 项目中使用日志包。我提供一个复制-粘贴-记录-代码-设置。然后我解释三个重要的日志概念:日志级别、日志处理程序和日志格式化程序。最后,我提供了一个包含更多信息的列表。

如有任何问题和意见,请随时联系我。谢谢你。在这里找到更多我的文章:

  1. 了解我如何为媒体设计文章
  2. 了解如何使用链接(或管道)在 Python 中编写干净的代码
  3. 学习如何使用 R 分析你的 LinkedIn 数据
  4. 学习如何使用图形语法在 Python 中以描述性的方式创建图表

Gregor Scheithauer 是一名顾问、数据科学家和研究员。他专门研究流程挖掘、业务流程管理和分析。你可以在 LinkedInTwitter 上和他联系,或者在 Medium 上这里。谢谢大家!

如何在 PowerBI 中设置选项卡级安全性

原文:https://towardsdatascience.com/how-to-setup-tab-level-security-in-powerbi-13cbe3daa65a?source=collection_archive---------0-----------------------

创建具有行级安全性的动态导航菜单

@钳工Unsplash 上的照片

我真的很喜欢这个特性,这也是我最近在 PowerBI 中学习做的最喜欢的事情之一。我以前使用过行级安全性,它在为许多用户创建公共报表时非常有用。主要的限制是每个用户组的报告看起来都一样——所以它们需要有相同的设计和相同的可视化,只是结果因访问而异。

我的情况有些不同。有各种各样的业务用户组,每个用户组都定义了他们希望看到的一些额外的特定于业务的度量。因此,根据哪个用户打开页面,页面将包含不同的视觉效果。

实施常规 RLS 并创建一个默认报告将导致一个业务用户组看到为另一个业务创建的空视图。

第一个想法只是用一个数据集为每个企业创建单独的报告,但是:

-报告中的某些页面对所有用户组都是通用的

-一些用户可以访问多个用户组

我讨厌冗余,所以我需要的是标签级的安全性,这样用户就可以轻松地浏览只与他们相关的页面。

我设法通过使用切片器和按钮作为菜单以及连接的行级安全性来调整切片器的内容。

让我们一步一步来看看如何做:

1。设置导航表

示例报告包含 4 个选项卡,在演示中,目标是创建两种类型的用户,他们将能够看到不同的选项卡。

作者图片

用户 1 —可以查看所有选项卡

用户 2 —只能看到其中的 3 个

1。创建新表:

作者图片

在新表中,我们将放入所有选项卡名称和排序列进行排序:

作者图片

我们现在需要向导航表添加 2 个度量:

作者图片

首先将允许 as 导航到选定的页面。第二个只是在按钮上显示自定义文本。

现在让我们创建另一个带有用户访问管理的自定义表。它将包括用户组和将用户组映射到他们可以访问的页面名称:

作者图片

为了让它工作,我们需要在 UAM 和导航表之间创建一个关系:

作者图片

记住勾选在两个方向应用安全过滤器

2 表格准备好后,让我们开始写报告:

首先,创建一个新的切片器视觉对象,将导航表中的页面字段作为值:

作者图片

-使方向水平

-使用单项选择

创建一个空按钮

作者图片

突出显示您创建的按钮转到属性下钻按钮文本,然后单击 fx:

作者图片

现在选择按字段值格式化,并提供在上一步中创建的测量按钮:

作者图片

一旦你把它放在仪表板上,它应该是这样的:

作者图片

由于测量按钮文本将根据切片器选择进行动态调整。

3 设置 PowerBI 服务安全性。

最后一步是在工作区中设置角色。首先,您需要在 PowerBI 服务中发布一个报告,然后转到报告数据集的安全设置。单击数据集旁边的 3 个点,然后选择安全:

作者图片

在左侧,您将在桌面上定义角色,只需点击它,然后添加邮件或用户组来分配角色,您就可以开始了:

作者图片

这个解决方案可以很容易地用来创建真正有用的导航和用户访问管理系统的基础上的报告标签。您可以将 slicer 放在每个报告页面的顶部,并将其用作菜单,这样,不同的用户将只能看到基于他们的角色或分配他们可以访问的页面。虽然我可以很容易地将这一点添加到应该发生的 powerBI 改进列表中。

此外,它还可以与常规的行级安全性相结合,因此您实际上可以同时运行这两个级别,这是一个非常好的特性。

如果你设法用其他方式解决这个问题,我很想听听。

请继续关注最新的 PowerBI 技巧,订阅或关注我的 Twitter

原载于 2021 年 3 月 2 日 https://www.solution-tailor.com**

如何用不到 10 行 Python 代码模拟股票市场

原文:https://towardsdatascience.com/how-to-simulate-a-stock-market-with-less-than-10-lines-of-python-code-5de9336114e5?source=collection_archive---------4-----------------------

让我们用几何布朗运动来模拟一个金融市场

马克西姆·霍普曼在 Unsplash 上的照片

对于那些对量化交易感兴趣的人来说,随机过程理论是美妙的,充满了理论机会。有时,为了测试交易策略,模拟股票市场可能是有用的。让我们看看理论是如何发挥作用的,以及如何使用 Python 将其转化为实践。

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

市场回报

除了价格,当涉及到股票市场建模时,我们可以建模的最重要的对象是回报。如果我们考虑特定的一天 n 和它的前一天 n-1 收益计算如下:

从这个定义出发,我们可以使用以下公式计算价格时间序列:

因此,知道了起始价格 p0 ,我们就可以使用收益序列来计算未来价格。

问题是回报是随机对象,所以每次实现回报都会给我们不同的价格时间序列。价格的随机行为就是这样建模的。

所以,如果我们想模拟价格时间序列,我们需要对收益做一些假设,然后应用上面的公式。几何布朗运动就是这些假设之一。

什么是几何布朗运动?

GBM 是股票市场的一个特殊模型,其收益是不相关的,并且是正态分布的。

我们可以从数学上把这句话翻译成:

也就是说,回报率正态分布,均值为μ,标准差为σ。请记住,这些参数与时间无关,因此该过程称为“稳态”。

μ是回报的平均值。如果它是积极的,我们有一个看涨的趋势。如果是负面的,我们有一个看跌的趋势。该参数的绝对值越高,趋势越强。

σ是收益的波动性。与μ相比,该值越高,价格越不稳定。

回到投资组合理论,无风险收益等于 0 的夏普比率是μ/σ。

对于像我一样热爱统计背后的数学的人来说,如果我们切换到连续时间,我们可以写出这个随机微分方程(SDE):

其中 W 是维纳过程。

这个模型经常在金融数学中使用,因为它是你能建立的最简单的股票市场模型。例如,它是诺贝尔奖获得者布莱克-肖尔斯期权理论的理论基础。然而,这个模型被证明并不完全正确,因为股票市场回报不是正态分布的,也不是平稳的,但这是一个很好的起点。

在伊藤的解释下,SDE 可以解析地解决,但在现实中,我们从来没有连续的时间,因为交易是离散的和有限的。因此,如果我们想模拟 GBM,我们可以简单地离散时间,保持回报的正态性。这在数学上等同于使用欧拉-丸山方法数值求解 SDE。

这个想法非常简单:生成 n 个正态分布的随机变量,并从起始价格开始计算未来价格。

让我们看看如何用不到 10 行代码在 Python 中实现它。

Python 模拟

首先,让我们导入一些有用的库:

import numpy as np
import matplotlib.pyplot as plt

现在,我们必须定义μ,σ和起始价格。例如,我们可以使用这些值:

mu = 0.001
sigma = 0.01
start_price = 5

现在是模拟部分。首先,我们需要设置 numpy 随机数发生器的种子,以便产生可重复的结果。然后,我们为回报生成 100 个值,最后我们从起始价格开始构建价格时间序列。

np.random.seed(0)
returns = np.random.normal(loc=mu, scale=sigma, size=100)
price = start_price*(1+returns).cumprod()

最后,我们可以绘制这些结果:

plt.plot(price)

股票市场的模拟。作者图片

就是这样。总共 9 行。它看起来真的像一个股票价格,不是吗?

例如,我们可以增加μ的值,看看会发生什么。

例如,μ=0.004 时,我们有:

作者图片

正如我们所见,μ值越高,我们的看涨趋势越强。

结论

使用几何布朗运动在 Python 中模拟股票市场非常简单,但是当我们做这个练习时,我们需要记住股票市场并不总是正态分布的,也不是平稳的。例如,我们可以对μ和σ应用时间相关性,或者对回报使用不同的概率分布。

Gianluca Malato 是意大利数据科学家和小说作家。他是数据科学、机器学习和数据分析在线学校YourDataTeacher.com的创始人。

如何使用相扑模拟城市网络上的交通

原文:https://towardsdatascience.com/how-to-simulate-traffic-on-urban-networks-using-sumo-a2ef172e564?source=collection_archive---------5-----------------------

思想和理论

使用 SUMO 和 python 在复杂城市网络中进行高级交通模拟的教程

城市中的汽车|图片来自 PixabayPexels

了解、预测并最终减少城市网络中的交通拥堵是一个复杂的问题。即使在最简单的情况下——单车道,理解交通拥堵的出现也具有挑战性。城市交通模拟(SUMO)平台是一个开源平台,可以模拟复杂环境中的交通流量。但是,除了相扑文档、一些堆栈溢出帖子和一些 YouTube 视频,我没有遇到多少教程教你如何从头到尾创建一个复杂的交通模拟。本文将使用网格网络流量的案例研究来做这件事情。这篇文章的结构如下:

  1. 为什么要研究城市网络中的交通?
  2. 相扑入门
  3. 模拟网格网络中的流量
  4. 关键交通绩效指标分析
  5. 模拟现实交通的未来方向

为什么要研究城市网络中的交通?

在之前的一篇文章中,我讨论了第一篇论文,该论文决定性地展示了交通“幻影”冲击波是如何从无到有产生的,除了驾驶员的互动。

圆圈中的汽车| Tadaki 等人 2013 年新物理学杂志第 15 期 103034 页

最近的研究表明,自动驾驶汽车之间的流线型交互可能会减少人工场景中的交通堵塞,如车辆在环形道路上行驶。但是当你有多条道路时,比如典型的城市道路网,会发生什么呢?有趣的是,在道路网络中,仅仅通过更多车道或更长的道路来增加容量可能不会像你想的那样有效。在另一篇文章中,我展示了“布拉斯悖论”如何导致不寻常的结果,即增加城市网络中的道路数量,可能会使交通更糟糕!

在从事密集的基础设施项目如修建新的道路,增加车道,交通灯等之前。—对交通流量进行现实的模拟很重要,这样提议的项目才有最大的机会成功缓解交通。当整合诸如音乐会、体育赛事等重大事件时,情况变得更加复杂。或者像机场和医院这样的公共建筑。在不久的将来,重要的是模拟拟议的联网车辆和智能交通技术创新的效果,以最好地实现其在简化交通流方面的潜力。

相扑入门

交通模拟似乎属于交通流量研究人员或工程承包公司的小众群体。例如, AnylogicVISSIMAimsun 都是提供交通和移动建模解决方案的公司。然而,相扑是开放的,很容易上手。

安装 SUMO 有多种方式,但我更喜欢 pip 安装方式,它安装 SUMO 和 python 库来与 SUMO 接口。

python -m pip install sumo

就是这样!现在让我们开始创建您的第一个网络交通流量模拟!

模拟网格网络中的流量

在城市规划中,网格状道路网络相当常见。在相扑比赛中,我们设置了一个 5x5 的网格,每条道路长 200 米,有 3 条车道,如下所示:

netgenerate — grid — grid.number=5 -L=3 — grid.length=200 — output-file=grid.net.xml

接下来,我们使用位于 SUMO 主目录下的 tools 文件夹中的 random trips . py(SUMO->tools),为一定数量的车辆(在下面的示例中为 200 辆车)生成随机行程。开始和结束时间表示车辆进入模拟的时间。我选择了 0 & 1,这意味着所有车辆在模拟的前 1 秒进入模拟。周期表示车辆的到达率。

randomTrips.py -n grid.net.xml -o flows.xml — begin 0 — end 1 — period 1 — flows 200

接下来,我们使用 SUMO 的 jtrrouter 生成单个车辆在时间 0 到 10000 之间的路线。

jtrrouter — flow-files=flows.xml — net-file=grid.net.xml — output-file=grid.rou.xml — begin 0 — end 10000 — accept-all-destinations

最后,为了简单起见,我们希望保持一个恒定的密度。最明显的方法是让车辆随机行驶,而不是退出模拟。为此,我们使用曼哈顿交通模型,其中遇到十字路口的车辆根据设定的概率选择直行、左转或右转。默认情况下,在相扑中,车辆一旦到达目的地就退出模拟。然而, SUMO 使用连续重路由 python 脚本实现了Manhattan 模型。

generateContinuousRerouters.py -n grid.net.xml — end 10000 -o rerouter.add.xml

接下来,我们创建一个 sumo 配置文件,以便在 SUMO 中运行模拟,SUMO 基本上是一个具有某些属性的. xml 文件,包含网络文件、路线文件和附加的重新路由文件的名称,以便车辆在模拟完成之前留在模拟中。我们定义了一个输出文件,用于存储交通模拟过程中的详细车辆信息。

<configuration>
  <input>
    <net-file value=”grid.net.xml”/>
    <route-files value=”grid.rou.xml”/>
    <additional-files value=”rerouter.add.xml”/>
  </input>
  <time>
    <begin value=”0"/>
    <end value=”10000"/>
  </time>
   <output>
     <fcd-output value=”grid.output.xml”/>
   </output></configuration>

最后,我们在终端中运行模拟,如下所示。周期表示保存数据的时间间隔——100 表示每 100 个时间步长保存一次车辆信息,即速度和位置。

sumo-gui -c grid.sumocfg — device.fcd.period 100

运行这个程序会弹出 SUMO GUI,在这里您可以看到整个模拟过程!

相扑网格模拟|塞犍陀·维维克

车辆颜色从最慢(红色)到最快(绿色)显示它们的速度。

对于一次模拟来说很容易…但是多次运行呢?

手动更改每个参数和输出文件是相当烦人的。如果您有 100 多次运行来探索交通如何随着不同参数(如车辆数量)而变化,以及多次运行来进行统计平均,那么这一数字就会增加。

为此,我在命令提示符下使用操作系统模块将 SUMO 与 python 连接起来:

分析

SUMO xml 输出包含每个时间步长的单个车辆时间、位置和速度的信息。我想分析速度如何依赖于密度,或模拟中的车辆数量——基本上获得每个时间步长的速度,在模拟中对所有车辆进行平均。

最后,我绘制了速度与密度的关系图,其中每个模拟运行都有一个单独的密度。

网格交通相扑模拟的速度与密度|塞犍陀·维维克

正如你所看到的,随着密度的增加,速度下降。这是因为模拟中的车辆越多,拥堵越多,导致行驶速度越低。这是我们所有人在高速公路上都见过的,尤其是在高峰时间。

交通模拟中另一个常用的参数是流量。正如我在上一篇文章中所讨论的,流量衡量的是单位时间内通过给定点的车辆数量,也是衡量车辆吞吐量的一个指标。通量由下式给出:

交通流量|塞犍陀·维维克

其中总和是长度 L 内的所有车速,车道数=n_l。

在低密度下,每辆车基本上都以极限速度行驶,因此通量随着密度线性增加(下图中的红线)。然而,在更高的密度下,车辆不能以限速行驶,在某一点上,每辆车以更低的速度行驶抵消了大量车辆的影响,导致流量减少。高于一个特征密度(在这个模拟中为~ 0.1–0.2),交通堵塞出现,交通流量随密度衰减。

网格交通相扑模拟的流量与密度|塞犍陀·维韦克

模拟真实交通

我已经展示了如何使用 SUMO+Python 在典型的网格网络中建立基本的流量模拟和集合运行。然而,这绝不是对城市网络的全面模拟。在最近的一项利用 OpenStreetMap 城市街道网络数据和 OSMnx 的研究中,发现一些城市有突出的网格状网络,而其他一些城市没有。SUMO 包括模拟城市街道网络交通的能力,通过将 OpenStreetMap 数据转换成 SUMO。net 文件。

但是除了在现实城市网络上的模拟之外,还有校准这些交通模拟以匹配日常交通模式的问题。为了匹配日常生活中看到的详细交通模式,需要考虑进入道路的人的潮涨潮落——他们从哪里进入,何时进入,何时/从哪里离开。这成为一个极其复杂的问题,因为不可能知道每一个车辆轨迹。如今,许多车辆将 GPS 数据传输给 INRIX 和 HERE technologies 等公司。像谷歌和苹果这样的公司利用手机数据来获取稀疏的位置和速度信息。然而,这只能提供整个人口中一小部分样本的信息。交通流量是一个高度非线性的问题;这意味着微小的变化会产生极端的后果。

同时,您希望您的流量模拟结果对初始条件具有鲁棒性。结果应该清楚地表明一个提议的项目是否对交通流量有显著的改善——在广泛的情况下。这是一个挑战,有详细的大规模交通模拟,运行在一个可行的时间量,并且是现实的。

在相扑网页上,只有少数几个这样真实的场景。这一页的顶部写着:

构建一个场景需要大量的工作。如果你已经建立了一个可以分享的相扑场景(在充分开放的许可下),请联系我们

希望交通流动性数据的民主化、计算资源可用性的增加以及开源交通建模平台将使这些大规模模拟更容易实现。《城市交通》是一个非常复杂的游戏,它提供了对有呼吸、有生命的城市的洞察。

这个项目的代码可以在 GitHub 上找到:

https://github.com/skandavivek/sumo-traffic-grids

参考资料:

  1. R. E. Stern 等人,“通过自动驾驶车辆控制消散停停走走波:现场实验”,arXiv (2017)。
  2. G. Boeing,“城市空间秩序:街道网络定向、配置和熵”,《应用网络科学》(2019)。
  3. P. L. Alvarez 等,“使用相扑进行微观交通模拟”,智能交通系统国际会议。IEEE (2018)。

如果你喜欢这篇文章,请关注我。

如果你对技术和现代社会之间的相互联系有全面的看法,请订阅我的时事通讯。

https://skandavivek.substack.com/

如何用 Excalidraw 勾画您的数据科学想法

原文:https://towardsdatascience.com/how-to-sketch-your-data-science-ideas-with-excalidraw-a993d049f55c?source=collection_archive---------7-----------------------

停止用语言来描述你的想法。用图纸代替。

动机

如果你想让你的经理或同事理解你对一个项目的想法,不要只给他们看文字或一大块代码。使用图形或图表。

假设您想向您的经理解释训练猫分类器的过程,通过向他们展示下图,他们会更容易理解这个过程的流程。

作者图片

在着手一个项目之前,画画也是勾勒出你想做什么的好方法。

有很多绘制图表的工具,但我最喜欢的是 Excalidraw。在本文中,我将向您展示什么是 Excalidraw,以及为什么它是绘制图表的最佳工具之一。

什么是 Excalidraw?

Excalidraw 是一个虚拟白板,用于绘制手绘状的图表。这款虚拟白板有一些不错的功能:

手绘草图

Excalidraw 允许你无缝地创建一个漂亮的手绘图表,如下图所示。

作者 GIF

对于每个形状,您可以调整:

  • 颜色
  • 充满
  • 笔画宽度
  • 笔画样式
  • 马虎
  • 优势
  • 不透明

下面的 GIF 显示了形状是如何随着每个选项的改变而改变的。

作者 GIF

形状移动时,箭头也会移动

如果箭头指向某个形状,而该形状被移动,箭头将自动调整自身,使其仍然指向该形状。这个功能非常有用,因为它节省了你调整形状和箭头的时间。

作者 GIF

弯曲的箭头和线条

您可以通过拖动来创建直线。但是,如果你想创建一条曲线或箭头,选择一条线或一个箭头,然后点击多个位置,如下所示。

作者 GIF

单击该线两次以调整创建该线的点。

从 Excel 创建图表

Excalidraw 还允许您通过复制和粘贴 Excel 中的数据或纯逗号分隔的文本来创建图表!例如,如果您复制下面的表格并将其粘贴到 Excalidraw 上,

…您将自动获得如下两张图!

作者图片

移动和对齐多个对象

按住 Shift 键的同时单击多个对象,可以一起移动多个对象。

你也可以让所有的物体像下面这样整齐的排列成一条直线!若要对齐多个对象,请选择多个对象,然后在左侧边栏中选择要对齐的选项。

作者 GIF

您也可以通过在“层”部分选择相应的选项来调整哪个对象应该位于另一个对象的前面或后面。

作者 GIF

实时协作

想和队友实时协作怎么办?Excalidraw 为您提供了保护。在下面的 GIF 中,无论一个人做了什么改变,另一个人几乎会立即看到。

作者 GIF

要启用实时协作,请单击左上角的两个人图标。

作者图片

形状库

如果你想创建一个更复杂的形状,Excalidraw 的库提供了多种形状供你选择。

作者 GIF

要从库中选择新形状,请单击顶部工具栏上的方形图标,然后选择要添加的图标。点击浏览库,从 Excalidraw 库下载更多形状。

作者图片

保存形状

您也可以将形状保存到您的个人库中以供将来使用。要保存形状,请单击该形状,然后单击方形图标。

滚动到列表底部,单击新形状,将其添加到库中。

作者 GIF

现在,你可以随时从你的个人库中调出你的新图形。

结论

恭喜你!您刚刚学习了如何使用 Excalidraw 勾画您的数据科学想法。通过绘制图表,你的想法更有可能被你的经理和同事理解和接受。

在实际实现代码之前勾画出你的想法也会让你更清楚应该用什么方法来解决你的问题。

我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以通过 LinkedInTwitter 与我联系。

如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:

如何用 Numba 提升你的 Python 速度🚀

原文:https://towardsdatascience.com/how-to-skyrocket-your-python-speed-with-numba-89fd16362e47?source=collection_archive---------9-----------------------

快速介绍

学习如何使用 Numba Decorators 让你的代码更快

Marc-Olivier Jodoin 在 Unsplash 上拍摄的照片

您的旅程概述

  1. 设置舞台
  2. 了解数字和安装
  3. 使用 Jit-Decorator
  4. 三个陷阱
  5. 【Numba 闪耀的地方
  6. 包装

1 —搭建舞台

在数据科学和数据工程中,许多从业者每天都在编写代码。为一个问题制定一个可行的解决方案绝对是最重要的事情。然而,有时代码的执行速度也很重要。

实时分析预测中尤其如此。如果代码太慢,那么这可能会给整个系统造成瓶颈。随着时间的推移,系统通常会变慢。由于要处理的数据越来越多,在数据学科中尤其如此。最坏的情况是,你构建的实时系统可能太慢而没有用😮

很多编译型编程语言,比如 C++,一般都比 Python 快。这是否意味着您应该将整个 Python 管道连根拔起?不。这通常不值得付出巨大的努力。

另一种方法是让您的 Python 代码更快。这就是 Numba 介入的地方:

Numba 是一个 Python 库,旨在提高你的 Python 代码的速度。Numba 的目的是在运行时检查你的代码,看看是否有部分代码可以被翻译成快速机器码。

听起来很复杂,对吧?确实是。然而,对于最终用户(也就是你)来说,使用 Numba 非常简单。通过几行额外的 Python 代码,您可以显著增加代码库的主要部分。你并不真的需要理解 Numba 是如何工作的才能看到结果。

在这篇博文中,我将向你展示 Numba 的基础知识,让你开始学习。如果你需要了解更多,那么我推荐 Numba 文档。如果你更喜欢视觉学习,那么我也制作了一个关于这个主题的视频:

2 —了解 Numba 和安装

让我先给你一个 Numba 的高层次概述👍

Numba 这样描述自己:

Numba 是一个开源的 JIT 编译器,它将 Python 和 NumPy 代码的子集翻译成快速的机器代码。— Numba 文档

我们来解开上面的说法。Numba 是一个开源的轻量级 Python 库,它试图让你的代码更快。其方式是使用行业标准的 LLVM 编译器库。你不需要理解 LLVM 编译器库来使用 Numba。

在实践中,您将添加某些 Python 装饰器来告诉 Numba 应该优化正在讨论的装饰函数。然后,在运行时,Numba 会检查您的函数,并尝试将部分函数编译成快速机器码。

术语 JIT 编译即时编译的缩写。因此,编译步骤发生在代码执行期间,而不是预先编译代码(例如 C++)。实际的区别?您不会生成难以共享的二进制文件,而只会得到 Python 文件!

让我从 Numba 的主页向您展示一个代码示例,以演示 Numba 是多么容易使用。下面的代码是一个蒙特卡罗方法用于近似圆周率的值。

import random

def monte_carlo_pi(nsamples):
    acc = 0
    for i in range(nsamples):
        x = random.random()
        y = random.random()
        if (x ** 2 + y ** 2) < 1.0:
            acc += 1
    return 4.0 * acc / nsamples

Numba 尚未应用于上述代码。如果变量nsamples很大,那么函数monte_carlo_pi相当慢。但是,添加下面两行代码会使它快很多:

from numba import jit # <-- importing jit from numba
import random

@jit(nopython=True) # <-- The only difference
def monte_carlo_pi(nsamples):
    acc = 0
    for i in range(nsamples):
        x = random.random()
        y = random.random()
        if (x ** 2 + y ** 2) < 1.0:
            acc += 1
    return 4.0 * acc / nsamples

没那么糟,对吧?😃

如果您通过 Anaconda 在 Jupyter 笔记本中工作,那么在 Anaconda 提示符下运行以下命令来安装 Numba:

conda install numba

如果你在 IDE 中编写代码,比如 Visual Studio Code或者 py charm或者 PIP,那么你可能想通过 PIP 安装 Numba:

$ pip install numba

更多高级选项,如从源代码编译 Numba,可以在安装页面中找到。

3—使用 Jit 装饰器

现在 Numba 已经安装好了,你可以试用了。我创建了一个 Python 函数,它执行一些 NumPy 操作:

import numpy
from numba import jitdef numpy_features(matrix: np.array) -> None:
    """Illustrates some common features of NumPy."""
    cosine_trace = 0.0
    for i in range(matrix.shape[0]):
        cosine_trace += np.cos(matrix[i, i])
    matrix = matrix + cosine_trace

上面的代码不用想太多。该功能的唯一目的是使用 NumPy 中的几个不同功能,如通用功能广播。让我用 Jupyter 笔记本中的以下神奇命令为上面的代码计时:

x = np.arange(1000000).reshape(1000, 1000)
%time numpy_features(x)**Output:**
Wall time: 32.3 ms

如果您运行上面的代码,根据您的硬件和其他因素,您将获得稍微不同的速度。这可能不是你见过的最慢的 Python 代码。然而,整个代码库中像这样的代码确实会降低整个应用程序的速度。

现在让我们将@jit(nopython = true)装饰器添加到函数中,看看会发生什么。代码现在应该如下所示:

import numpy
from numba import jit@jit(nopython=True)
def numpy_features(matrix: np.array) -> None:
    """Illustrates some common features of NumPy."""
    cosine_trace = 0.0
    for i in range(matrix.shape[0]):
        cosine_trace += np.cos(matrix[i, i])
    matrix = matrix + cosine_trace

编写代码的方式没有太大变化,但是速度不同了。如果您再次对代码计时,您会得到以下结果:

x = np.arange(1000000).reshape(1000, 1000)
%time numpy_features(x)**Output:**
Wall time: 543 ms

什么?代码变得比原始代码慢 10 倍😧

不要气馁。尝试再次运行代码:

x = np.arange(1000000).reshape(1000, 1000)
%time numpy_features(x)**Output:**
Wall time: 3.32 ms

现在的代码比原来的代码快了 10 倍。

这是怎么回事?😵

4—三个陷阱

编译的陷阱

我给你看的这个奇怪的东西不是一个 bug,而是一个特性。当你第一次用@jit(nopython=True)装饰器运行函数时,代码会变慢。为什么?

第一次,Numba 必须检查函数中的代码,并找出要优化的代码。这增加了额外的开销,因此该功能运行缓慢。然而,每次后续的功能会快得多。

这最初看起来像是一种权衡,但实际上并非如此。在数据分析和数据工程中,函数要运行很多次。

例如,考虑一个在预测之前对进入数据管道的新数据进行归一化的函数。在实时系统中,新数据一直在不断到达,函数每分钟被使用数百次甚至数千次。在这种系统中,最初较慢的运行可以在几秒钟内完成。

不将参数 nopython 设置为 True

装饰器@jit(nopython=True)可以不带参数nopython使用。如果你这样做,那么默认情况下 Numba 将设置nopython=False

这不是一个好主意!

如果nopython=False那么 Numba 不会在无法优化代码时提醒你。在实践中,您只需将 Numba 开销添加到代码中,而无需任何优化。这会降低代码的速度😠

如果 Numba 没有成功优化您的代码,那么您希望被告知。最好完全移除 Numba 装饰器。因此你应该总是使用参数@jit(nopython=True)

专业提示:装饰者@njit@jit(nopython=True)的简写,很多人用它来代替。

不要过度优化你的代码

过度优化代码意味着在不需要的时候花费大量时间来获得最佳性能。

不要过度优化你的代码!

在许多情况下,代码速度并不那么重要(例如,批量处理中等数量的数据)。降低代码速度几乎总是会增加开发时间。仔细权衡是否应该将 Numba 整合到代码库中。

Numba 闪耀的地方

照片由穆罕默德·诺哈西Unsplash 上拍摄

假装 Numba 擅长优化任何类型的 Python 代码对任何人都没有帮助。Numba 擅长优化的只是一些 Python 代码。

Numba 非常擅长优化任何涉及循环或 NumPy 代码的东西。由于许多机器学习库(如 Scikit-Learn )大量使用 Numpy,这是使用 Numba 的好地方🔥

然而,Numba 不理解例如熊猫。将@jit(nopython=True)添加到一个纯粹处理熊猫数据帧的函数中可能不会产生很好的性能。参见 Numba 文档中的示例。

我的建议如下:

总是通过测试代码的速度来检查添加的 Numba decorator 是否增加了价值(在第一个编译步骤之后)。不要只是为了好玩而使用 Numba decorators,必要时这样做可以加快代码的速度。

6—总结

如果你需要了解更多关于 Numba 的信息,那么查看 Numba 文档或我在 Numba 上的 YouTube 视频

喜欢我写的?查看我的其他帖子,了解更多 Python 内容:

如果你对数据科学、编程或任何介于两者之间的东西感兴趣,那么请随意在 LinkedIn 上加我,并向✋问好

如何用锋利的笔大幅削减新冠肺炎测试的误差:为什么准确度不仅仅是一个百分比值

原文:https://towardsdatascience.com/how-to-slash-the-error-of-covid-19-tests-with-a-sharpie-d465c08e818c?source=collection_archive---------20-----------------------

为什么准确性不仅仅是一个百分比值

在本文中,我将探索数据科学中的一个基本概念——准确性,并展示对这一基本概念缺乏理解是如何导致一些非常错误的结论的。具体来说,我们将研究横向流动新冠肺炎测试的准确性,并发现它比任何人在家里用记号笔和一块纸板进行的测试的准确性都低。我们将会看到,以百分比值表示的准确度并不是评估这类测试的有用度量。结论不仅限于医学测试,因为从概念的角度来看,测试只是简单的分类器。就像数据科学模型一样,它们基于有限的信息(样本)来预测类别(病毒的存在)。

横向流动测试的准确性

首先,我们需要找到新冠肺炎横向流动测试的准确性。答案可以在一篇科学论文“用于诊断新型冠状病毒感染的快速、护理点抗原和分子检测(综述)”中找到——一篇 400 页的综述,涉及 58 项评估新冠肺炎检测准确性的单独研究。为了简单起见,我们将重点关注没有症状的个体。答案在第 6 页,并不像你想象的那么简单。

科学论文实际上并不直接提供准确性,而是提供灵敏度和特异性——这两个值在图 1 中被拆开,论文中的值在图 2 中被填充。敏感度只是真实阳性率的一个不同术语,即有多少病毒携带者将获得阳性检测结果。同样,特异性只是真实阴性率的一个不同术语,即有多少未携带病毒的人将获得阴性检测结果。使用敏感性和特异性,我们可以构建一个混淆矩阵,描述正确分类为新冠肺炎患者/非患者的可能性:

图 1:混淆矩阵是特定测试结果正确或错误频率的表示。

图 2:横向流动测试混淆矩阵。所提供的数值来源于对 58 例无症状个体抗原检测准确性评估的系统综述[2]。

既然我们知道什么是假阳性和假阴性率,我们可以计算准确性。为了估计准确性,我们需要考虑实际上有多少人感染了病毒。如果不考虑病毒的流行程度,混淆矩阵中的数字并不能真正代表我们在现实世界中进行测试时会发生什么。根据国家统计局[1]的数据,目前这一比例为 1/260。

图 3:使用 ONS 信息的横向流动测试预期混淆矩阵此时每 260 人中有 1 人患有冠状病毒[1]。这代表了来自英国人群的不同检测结果的概率,与图 2 相反,图 2 不知道该病毒在英国人群中的流行情况。

准确性是获得正确结果的概率,不管结果是正还是负。使用图 3 中的预期混淆概率,我们得出 98.7%,这看起来确实令人印象深刻!然而,我决定把这个数字推得更高,并开发了我自己的精确度更高的新冠肺炎测试。我将把我的新测试方法称为纸板测试。

纸板测试的准确性

我开发的新冠肺炎测试,如图 4 所示,由一张用记号笔写着“否定”的纸板组成。这种测试的优势是巨大的——制造成本非常低,可重复使用,结果立即可用。

图 4:我们将使用自制纸板测试来对比横向流动测试的准确性。作者图片

虽然这看起来很荒谬,但请和我一起计算这个测试的准确性。让我们从混淆矩阵开始:

图 5:纸板测试混淆矩阵。不出所料,测试结果总是“阴性”。

以下是混淆预期矩阵,说明目前英国只有 1/260 的人患有新冠肺炎。

图 6:预期混淆矩阵提供了纸板测试在英国人群中不同类型错误的概率。

由于准确性是获得正确结果的概率,无论是肯定的还是否定的,使用图 6 中的预期混淆概率,我们得到 99.6%的准确性。与横向流动测试的 98.7%的准确度相比,这是一个显著的改进。

该值意味着纸板试验产生的误差量,当目前在英国用于无症状个体时,将比目前提供的横向流动试验产生的误差量低 5 倍。这听起来可能很奇怪,但这是对准确性的天真解释的简单结果,公共卫生当局幸运地知道不要只看准确性,因此不会尝试将测试切换到我的纸板测试,无论这可能会节省成本。不使用纸板测试的原因是不同类型的错误对公众健康有不同的影响。

接受假阳性检测结果是一件令人讨厌的事情,会不必要地把某人推向孤立。假阴性意味着新冠肺炎病毒携带者会四处传播,危及生命,增加医疗服务的压力。显然,这两种结果有着完全不同的影响,不应被视为等同。这就是为什么好的决策者会考虑他们决策的预期成本,而不仅仅是测试或预测的准确性。成本是一个技术术语,指决策失误的负面影响。硬币的另一面被称为预期效用,通常用于商业环境中,以评估您的决策预期带来的好处,在这种情况下,您需要考虑真正的正利率和负利率。

一旦你获得了预期混淆矩阵,并能够将成本与不同类型的错误联系起来,就很容易计算出预期成本。量化错误的成本并不总是容易的,这就是其中的一个例子。然而,为了这个练习的目的,我们将简单地给一个假阳性结果分配一个任意单位的成本。我们将假设假阴性的成本是假阳性的 10 倍,而正确的结果(真阳性或真阴性)没有相关成本。将混淆预期矩阵中的适当单元相乘得到以下结果:

图 7:预期成本矩阵显示了两个测试中不同类型错误的预期成本。这些值的总和是使用特定测试产生的错误的总预期成本。

图 7 清楚地显示了使用真实测试和纸板测试的预期影响是完全不同的,纸板测试的误差导致的成本是真实结果的两倍多。这导致了一个合理的结论,真实测试是一个比我自己开发的纸板测试更好的解决疫情的工具,尽管它的准确性更高。

本文展示了对于评估测试、模型或任何其他影响现实世界的分类工具来说,百分比准确性如何不是一个有用的度量。为了正确评估分类工具,有必要考虑敏感性和特异性,构建混淆矩阵、预期混淆和基于分类做出决策的预期成本。这似乎是一个很大的要求,但如果不这样做,我们可能最终会使用一张纸板,而不是真正的新冠肺炎测试来解决疫情。

参考

[1]冠状病毒(新冠肺炎)感染调查,英国:2021 年 7 月 2 日。https://www . ons . gov . UK/peo-plepopulationandcommunity/healthandssocial care/conditions and diseases/bulletins/Coronavirus-covid 19 infections Survey pilot/latest。

[2] Jacqueline Dinnes,Jonathan J Deeks,Sarah Berhane,Melissa Taylor,Ada Adriano,Clare Davenport,Sabine Dittrich,Devy Emperador,Yemisi Takwoingi,Jane Cunningham 等.用于诊断 sars-cov-2 感染的快速、护理点抗原和分子检测。Cochrane 系统综述数据库,(3),2021。

如何摆脱数据科学的低迷

原文:https://towardsdatascience.com/how-to-snap-out-of-a-data-science-slump-82314a9e4644?source=collection_archive---------28-----------------------

我们每周精选的必读编辑精选和原创特写

当事情不像你希望的那样发展时,你会怎么做?无论是需要太多修补的机器学习模型,还是从未实现的工作邀请,或者只是一句“等等,快到6 月了?!"恐怖时刻,我们都偶尔会面临挫折(或者更糟)。我们在最近与数据科学家和 TDS 作者 Carolina Bento 的对话中找到了灵感,Carolina Bento 解决问题的务实方法可能也会引起你的共鸣:“有时,当我陷入困境时,我会思考如何从不同的角度解决问题。”

Bas van den Eijkhof 在 Unsplash 上拍摄的照片

卡罗琳娜的建议更加详细,从将问题分解成最小的原子到与信任的同伴交谈(阅读它——你不会后悔的!),但这一概念适用于我们日常经历中的许多困难情况。重构我们的视角可能很难,但它通常会带来回报——无论是新的解决方案、更深入的理解还是意外的机会。

如果你不相信我们,读一读 Mike Bostock 关于 JavaScript 对数据分析未来的承诺的帖子。在对 Python、R 和 Julia 的优缺点进行了多年无休止的辩论之后, Mike 想知道这是否是一个大的、引人注目的改变的恰当时机,并转向开发人员中最常见的编程语言。

同样,丹尼尔·马科斯也提出了随着公司的成长扩大数据运营的新方法。他在他的全周期数据科学框架的详细描述中综合了它们,并讨论了他如何在自己的工作中实现后者。另一个普遍存在视角转换的领域?对于我们最新的 TDS 播客嘉宾,埃利亚诺马克斯,这是人工智能隐私。埃利亚诺与主持人杰瑞米·哈里斯聊到迫切需要教育终端用户放弃我们的数据的权衡以及关注算法的安全性。

当然,改变不一定要大而引人注目。累积迭代和实验也同样强大;继 Hannah Wnendt 在代码基准测试中的冒险以及她在 R 中提高数据分析的计算速度的最终成功之后,Hannah Wnendt 的最新深入研究就是一个很好的例子。与此同时,Rebecca Vickery 指出,有时候,不是我们的过程,而是我们的工具阻碍了我们——所以也许是时候探索新的选择了。对于 Rebecca 来说,这涉及到用四个额外的工具来补充日益流行的 Jupyter 笔记本电脑,以帮助工作流程保持顺畅和高效。

对我们中的许多人来说,摆脱低迷需要外界的推动——从我们的头脑中清除阴暗的想法。有什么比学习新东西更好的方法来达到这个目的呢?如果这也是你的首选方法,你会喜欢我们最新的实践教程和指南。

如果到目前为止你的一周过得很棒,我们希望它能保持下去!如果没有,我们希望深入研究一些科学数据会有所帮助。不管怎样,我们很感激成为其中的一员,也很感激你为维护这个社区所做的一切——从与你的朋友和同事分享我们的工作,到通过成为灵媒会员来支持我们。

直到下一个变量,
TDS 编辑器

我们策划主题的最新内容:

入门指南

实践教程

深潜

思想和理论

如何解决 R 中的一个约束优化问题

原文:https://towardsdatascience.com/how-to-solve-a-constraint-optimization-problem-in-r-fdf5abee197b?source=collection_archive---------0-----------------------

实践教程

使用nloptr在 R 中进行非线性约束优化

图片由作者使用函数 f = (Z⁴-1)绘制,其中 z 是一个复数

介绍

通常在物理科学研究中,我们最终会遇到一个困难的问题,即优化一个需要满足一系列约束(线性或非线性等式和不等式)的函数(称为目标)。优化器通常也必须遵守上限和下限。我最近在量子信息科学(QIS)中研究了一个类似的问题,我试图根据物理和数学规则规定的一些约束来优化一个非线性函数。感兴趣的读者可能会发现我在星座优化方面的工作,即利用位移接收器实现相移键控相干态的互信息最大化,其中我基于一组约束优化了四相移键控(QPSK)的互信息。

https://ieeexplore.ieee.org/document/9291373

在研究带有一组约束的非线性优化问题时,我发现并不是所有的优化例程都是一样的。有几个不同语言的库可用,如 python (scipy.optimize)Matlab (fmincon)C++ (robotim,nlopt)R (nloptr)。虽然我列出的优化例程并不详尽,但其中一些比其他例程更可靠,一些比其他例程执行更快,一些具有更好的文档。基于几个关键因素,我发现用 R 语言实现的 nloptr,最适合非线性优化。 nloptr 使用 C++实现的 nlopt 作为后端。因此,它提供了 R 语言的优雅和 C++的速度。甚至在 10e-15 数量级的公差下,优化过程也能在几分之一秒内快速执行。

非线性优化问题

一般的非线性优化问题通常具有以下形式

其中 f 是目标函数, g 定义一组不等式约束, h 是一组等式约束。 xL分别为下限和上限。在文献中,已经提出了几种优化算法。比如 MMA(移动渐近线法)支持任意非线性不等式约束,(COBYLA)线性逼近约束优化,(ORIG_DRIECT)直接算法。也支持非线性等式约束的优化算法包括 ISRES(改进的随机排序进化 Strategy)⁴,(AUGLAG)增强的拉格朗日 Algorithm⁵.这些方法的完整列表可以在https://nlopt.readthedocs.io/en/latest/NLopt_Reference/nlopt C++参考页面中找到。nloptr 使用这些方法之一来解决给定的优化问题。

“MMA(移动渐近线法)支持任意非线性不等式约束,(COBYLA)约束优化采用线性逼近,(ORIG_DRIECT)直接算法。同样支持非线性等式约束的优化算法包括 ISRES(改进的随机排序进化策略),(AUGLAG)增广拉格朗日算法。”

在本文的其余部分,我提供了几个使用 R 解决约束优化问题的例子。R Studio 还提供了 knitr 工具,它非常适合用内嵌代码编写文档或文章,还可以生成 latex 源代码和 pdf 文件。这里展示的大多数例子都是从用于验证nloptr R 包中的函数的测试套件修改而来的。

库的安装和加载

在 R 中安装nloptr相当简单。

install.packages(“nloptr”)
library(‘nloptr’)

示例 1:使用显式梯度进行优化

在第一个例子中,我们将最小化 Rosenbrock Banana 函数

其梯度由下式给出

然而,并不是所有的nlopt算法都需要显式梯度,我们将在后面的例子中看到。让我们先定义目标函数及其梯度:

eval_f <- function(x)
{
    return ( 100 * (x[2] - x[1] * x[1])^2 + (1 - x[1])^2 )
}eval_grad_f <- function(x) {
return( c( -400 * x[1] * (x[2] - x[1] * x[1]) - 2 * (1 - x[1]),
200 * (x[2] - x[1] * x[1]) ) )
}

我们还需要优化器的初始值:

x0 <- c( -1.2, 1 )

在运行最小化过程之前,我们需要指定我们将使用的算法。这可以通过以下方式实现:

opts <- list("algorithm"="NLOPT_LD_LBFGS",
"xtol_rel"=1.0e-8)

这里,我们将使用 L-BFGS 算法。现在我们准备运行优化程序。

# solve Rosenbrock Banana function
res <- nloptr( x0=x0,
eval_f=eval_f,
eval_grad_f=eval_grad_f,
opts=opts)

我们可以通过输入看到结果

print(res)

该函数在(1,1)处被优化,这是基本事实。通过在 R Studio 中运行代码来检查自己。

示例 2:无梯度的不等式约束最小化

要最小化的问题是

a1= 2,b1 = 0,a2 = 1,b2 = 1。我们重新排列约束,使其形式为 g(x) ≤ 0:

首先,定义目标函数

# objective function
eval_f0 <- function( x, a, b ){
return( sqrt(x[2]) )
}

和约束是

# constraint function
eval_g0 <- function( x, a, b ) {
return( (a*x[1] + b)^3 - x[2] )
}

定义参数

# define parameters
a <- c(2,-1)
b <- c(0, 1)

现在使用 NLOPT_LN_COBYLA 求解,无需梯度信息

# Solve using NLOPT_LN_COBYLA without gradient information
res1 <- nloptr( x0=c(1.234,5.678),
eval_f=eval_f0,
lb = c(-Inf,0),
ub = c(Inf,Inf),
eval_g_ineq = eval_g0,
opts = list("algorithm"="NLOPT_LN_COBYLA",
"xtol_rel"=1.0e-8),
a = a,
b = b )
print( res1 )

示例 3:没有梯度的等式和不等式约束的最小化

我们想解决下面的约束优化问题

受制于约束

对于本例,最优解在(1.00000000,4.74299963,3.82114998,1.37940829)处获得。

# Objective Function
eval_f <- function(x)
{
return (x[1]*x[4]*(x[1] +x[2] + x[3] ) + x[3] )
}# Inequality constraints
eval_g_ineq <- function(x)
{
return (25 - x[1]*x[2]*x[3]*x[4])
}# Equality constraints
eval_g_eq <- function(x)
{
return ( x[1]^2 + x[2]^2 + x[3]^2 + x[4]^2 - 40 )
}# Lower and upper bounds
lb <- c(1,1,1,1)
ub <- c(5,5,5,5)#initial values
x0 <- c(1,5,5,1) 

我们还需要定义优化选项

# Set optimization options.
local_opts <- list( "algorithm" = "NLOPT_LD_MMA", "xtol_rel" = 1.0e-15 )
opts <- list( "algorithm"= "NLOPT_GN_ISRES",
"xtol_rel"= 1.0e-15,
"maxeval"= 160000,
"local_opts" = local_opts,
"print_level" = 0 )

我们使用 NL_OPT_LD_MMA 进行局部优化,使用 NL_OPT_GN_ISRES 进行整体优化。您可以将容差设置得非常低,以获得最佳结果。使用 maxeval 设置迭代次数。将容差设置得非常低或将迭代次数设置得非常高,可能会以增加计算时间为代价获得最佳近似值。最后,我们优化

res <- nloptr ( x0 = x0,
                eval_f = eval_f,
                lb = lb,
                ub = ub,
                eval_g_ineq = eval_g_ineq,
                eval_g_eq = eval_g_eq,
                opts = opts
)
print(res)

在我的例子中,结果出来是(1 4.768461 3.78758 1.384204),这是相当接近地面的真相。

示例 4:无梯度的多重不等式约束最小化

在这种情况下,我们的目标函数是

使遭受

变量的界限为

对于这个问题,最优解在(1,1)处达到。让我们现在写代码。

# Objective function
eval_f <- function(x)
{
return ( x[1]^2 + x[2]^2 )
}# Inequality constraints
eval_g_ineq <- function (x) {
constr <- c(1 - x[1] - x[2],
1 - x[1]^2 - x[2]^2,
9 - 9*x[1]^2 - x[2]^2,
x[2] - x[1]^2,
x[1] - x[2]^2)
return (constr)
}# Lower and upper bounds
lb <- c(-50, -50)
ub <- c(50, 50)# Initial values
x0 <- c(3, 1) 

最后,为 nloptr 定义如下选项:

opts <- list( "algorithm"
= "NLOPT_GN_ISRES",
"xtol_rel"
= 1.0e-15,
"maxeval"= 160000,
"tol_constraints_ineq" = rep( 1.0e-10, 5 ))

然后执行优化

res <- nloptr(
        x0          = x0,
        eval_f      = eval_f,
        lb          = lb,
        ub          = ub,
        eval_g_ineq = eval_g_ineq,
        opts        = opts )
print(res)

通过指定的公差和迭代次数,我能够获得(1,1)的最优解。

虽然我没有给出带有多个等式约束的例子,但是它们与例子 4 非常相似。但是,一定要选择 NLOPT_GN_ISRES 这样的优化算法。

参考文献

  1. K.Svanberg,移动渐近线法——结构优化的新方法,《国际工程数值方法杂志》, 1987 年,24,359–373。
  2. 鲍威尔·MJD(1994)优化和数值分析进展,Kluwer Academic,Dordrecht,一种通过线性插值模拟目标和约束函数的直接搜索优化方法,第 51–67 页。
  3. https://people.cs.vt.edu/~ltw/lecture_notes/HPCS08tut.pdf
  4. 刘永强,姚欣,“约束进化优化的随机排序”,中国电机工程学会会刊。进化计算,第 4 卷(第 3 号),第 284-294 页(2000 年)。
  5. https://www . HIM . uni-Bonn . de/file admin/HIM/section 6 _ HIM _ v1 . pdf
  6. https://people.kth.se/~krille/mmagcmma.pdf
  7. https://cran . r-project . org/web/packages/nloptr/vignettes/nloptr . pdf
  8. http://faculty . cas . usf . edu/JK Wilde/math camp/Constrained _ optimization . pdf
  9. https://nlopt.readthedocs.io/en/latest/

如果这篇文章对你有益,请使用以下引用来引用我的工作:

Rahul Bhadani. [Nonlinear Optimization in R using nlopt](https://arxiv.org/abs/2101.02912). arXiv preprint arXiv:[2101.02912](https://arxiv.org/abs/2101.02912), 2021.

或者

[@article](http://twitter.com/article){bhadani2021nonlinear,
    title={Nonlinear Optimization in R using nlopt},
    author={Rahul Bhadani},
    year={2021},
    eprint={2101.02912},
    archivePrefix={arXiv},
    primaryClass={math.OC},
  journal={arXiv preprint arXiv:2101.02912},
}

如何用 Python 解决生产计划和库存问题

原文:https://towardsdatascience.com/how-to-solve-a-production-planning-and-inventory-problem-in-python-45c546f4bcf0?source=collection_archive---------8-----------------------

为了使生产和库存成本最小化,你每天应该生产多少件?

动机

假设你是一家服装店的老板。对衣服的需求每天都在变化(更多的人喜欢在周末而不是工作日去购物)。生产成本也是一天一天的变化(雇佣工人周末工作成本更高)。

你的工作是决定每天生产多少件衣服。

作者图片

既然你可以储存你的衣服,你可能会决定在最便宜的一天生产尽可能多的衣服。但是,每天存储 1 个单位的成本是 1 美元,因此您还需要考虑到,随着存储单位数量的增加,存储成本也会增加。

作者图片

你一天应该生产多少产品才能使总成本最小化?

您可以尝试每天生产不同数量的产品,并选择成本最低的产品,但这非常耗时。幸运的是,我们可以使用 Python 和线性编程来解决这个问题。

什么是线性规划?

线性规划是一种数学建模技术,其中线性函数在受到各种约束时被最大化或最小化。

CVXPY 是一个 Python 工具,为许多线性编程解算器提供接口。要安装 CXVPY,请键入:

pip install cxvpy

让我们确定这个问题的输入参数、决策变量、目标和约束。

输入参数

作者图片

决策变量

我们想确定在 t 日结束时要生产多少单位,储存多少单位。

作者图片

请注意,结束库存变量从第 0 天开始,因为约束条件需要知道第 1 天开始时的库存。

目标

我们希望将 4 天的总成本降至最低。这包括生产成本和持有成本。

作者图片

注意,由于存货成本是每天每单位 1 美元,t 日的期末存货成本是:

作者图片

我们可以将总和重写为如下矩阵乘法:

作者图片

限制

期末库存等于期初库存和第 t 天的生产数量之和减去第 t 天的需求:

作者图片

作者图片

一般来说,我们有:

作者图片

第 1 天开始时的库存数量为 0:

作者图片

库存的每日数量不能为负:

作者图片

日生产数量不能为负:

作者图片

等等,但是我们不也需要包括需求的约束吗?那是不必要的。期末库存中的每日数量等于或大于 0,这表明满足了每日需求。

解决

现在我们有了输入参数、约束和目标,我们准备好解决问题了!

1890.0

厉害!问题解决了,目标值是 1890。这意味着最佳解决方案的总成本为 1890 美元。

第 1、2、3 和 4 天的生产量是多少?

[ 75\. 250\.   0\.  60.]

让我们也找到每天的期末存货:

[  0\. 100\.   0\.   0.]

酷!根据调查结果,我们将:

  • 在第 1 天生产足够满足第 1 天需求的产品
  • 在第 2 天生产足够的产品以满足第 2 天和第 3 天的需求
  • 在第 3 天生产足够满足第 3 天需求的量

作者图片

这个解决方案真的是最优的吗?

当使用一个新工具时,我们应该仔细检查以确保它给我们一个最佳的解决方案。让我们仔细检查 CXVPY 给我们的解决方案。

为此,我们将首先创建一个函数,根据每天的生产数量计算总成本。

然后我们将尝试不同的可能组合。我们要确保这些组合满足我们上面写的约束。

在第一天生产一切

由于第一天的生产成本是最便宜的,让我们看看如果我们在第一天生产 4 天所需的每个单位,总成本会是多少。

2070

这个解没有我们之前得到的目标值最优。

在第一天和第二天生产一切

第一天生产所有东西的总成本如此之高可能是因为持有成本的累积。如果我们第一天生产一些,第二天生产一些呢?

2070

这个解决方案也不是更好。

生产足够满足每天需求的量

好吧。如果我们完全避免持有成本,每天只生产足够的量,会怎么样?

1990

没有。这个方案还是不好。

在第一天和最后一天生产一切

如果我们在第一天和最后一天生产所有东西会怎么样?

1890

啊哈!我们找到了一个能产生相同目标值的解决方案。这意味着有两种不同的解决方案产生相同的目标值 1890。这仍然意味着我们找不到比 1890 年更好的客观价值。

我希望你相信我们上面找到的解决方案是最优的解决方案。如果你仍然不相信,请随意尝试其他可能的组合。

结论

恭喜你!您刚刚学习了如何使用 CXVPY 解决生产和库存问题。希望这篇文章能给你用 Python 解决类似问题的动力。

上面的问题可能很容易在你的头脑中解决。但是随着问题变大,你会通过使用线性规划来节省自己的时间。

本文的源代码可以在这里找到:

https://github.com/khuyentran1401/Data-science/blob/master/mathematical_programming/production_and_inventory.ipynb

我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 T2 Twitter 上与我联系。

这个回购如果你想检查我写的所有文章的代码。在 Medium 上关注我,了解我的最新数据科学文章,例如:

如何用 Python 解决人员调度问题

原文:https://towardsdatascience.com/how-to-solve-a-staff-scheduling-problem-with-python-63ae50435ba4?source=collection_archive---------1-----------------------

为每个时间窗口分配足够的工人的同时最小化每个班次的工人数量

动机

假设你是一家咖啡店的经理。你的咖啡店每天 24 小时营业。每日日程分为 8 个时间窗口,如下表所示。每个时间窗口需要不同数量的员工。

数据来源于应用整数规划,由陈,陈德生,巴特森,r . g .&党,Y. (2010)

员工需要被安排到 4 个不同的班次,如下所示:

作者图片

你如何决定每班需要多少员工?

很容易,不是吗?

你可能会说“这很容易!我将在一个班次的三个时间窗口中选择最高数量的需求。例如,由于我的咖啡店从 6:00 到 9:00 需要 55 名工人,9:00 到 12:00 需要 46 名工人,12:00 到 15:00 需要 59 名工人,因此我将从 6:00 到 15:00 分配 59 名工人。”

这个解决方案是可行的,但是它不是最优的。由于不同班次的工人在一些时间窗口内一起工作,每班需要的工人可能比你想象的要少。

作者图片

但是什么是最优解呢?从经理的角度来看,最佳解决方案是最大限度地减少每班工人的数量以节省资金,同时仍然为每个时间窗口分配足够的工人。

让我们利用您的 Python 技能来找到这个问题的最佳解决方案,而不是花费几个小时来试图解决这个问题。

纸浆介绍

线性规划 (LP)是寻找上述约束问题最优解的最佳方法之一。 PuLP 是一个 Python 库,使得使用 Python 来应用线性编程变得很容易。

要安装纸浆,请键入:

pip install pulp

现在让我们使用 gdown 从 Google Drive 下载本文开头提到的数据:

pip install gdown

数据来源于应用整数规划,由陈,陈德生,巴特森,r . g .&党,Y. (2010)

问题陈述

输入参数

首先,让我们创建一个矩阵来显示每个时间窗口与哪个班次相关联。

作者图片

写下其他一些有用的信息:

作者图片

决策变量

决策变量是我们想要求解的未知量。在我们的例子中,决策变量是每班的工人数量。

作者图片

要在 PuLP 中指定决策变量,请使用LpVariable.dicts(name, list_of_variables, lowBound, upBound, cat)

  • name:变量的名称
  • lowBound:此变量范围的下限。默认值为负无穷大
  • upBound:该变量范围的上限。默认值为正无穷大
  • cat:该变量所在的类别,IntegerBinaryContinuous(默认)

例如,由于每个工作班次的工人数量需要是一个大于 0 的整数,因此我们写:

目标

线性规划旨在最小化或最大化某些数值,如成本、利润等。在这个问题中,我们希望最小化支付给所有工人的工资成本。

使用LpProblem(name, LpMinimize),以最小化为目标,制造纸浆问题。

如果目标是最大化,使用LPMaximize

制定

我们想尽量减少一天花在所有员工身上的钱。请注意,不同班次的工人工资不同(即夜班工人的工资通常高于白班工人)。

作者图片

每个时间窗口 t 内的需求也需要得到满足。

作者图片

酷!现在我们已经写好了约束和目标,我们准备好解决问题了!

解决

Status: Optimal

耶!运行prob.solve()时状态为optimal!这意味着求解器找到了最优解!

让我们找出这些最优解是什么:

作者图片

酷!

解释

让我们想象一下我们的结果,看看它们是否有意义。

作者图片

咖啡店 6:00-9:00 需要 55 个工人,12:00-15:00 需要 59 个工人。如果求解器只分配 46 名工人到第一班(从 6:00 到 15:00),咖啡店如何满足这些需求?

因为有一些时间窗口,来自不同班次 的工人一起工作。让我们精确计算每个时间窗口中有多少工人。

作者图片

啊哈!从上面的计算中,我们可以看到在每个时间窗口都有足够的工人来满足需求。多酷啊。

结论

恭喜你!您刚刚学习了如何使用 PuLP 解决优化问题。我希望这篇文章能够激发您利用 Python 技能来解决类似的问题。

这可能看起来很直观,但是当你的问题变得更大时,使用像纸浆这样的工具来解决问题会容易得多。

在 Github repo 中,您可以随意使用本文的代码:

https://github.com/khuyentran1401/Data-science/tree/master/mathematical_programming/schedule_workers

我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 T2 Twitter 上与我联系。

这个回购如果你想检查我写的所有文章的代码。在 Medium 上关注我,了解我的最新数据科学文章,例如:

[## 使用 SimPy 在 Python 中模拟真实事件

towardsdatascience.com](/simulate-real-life-events-in-python-using-simpy-e6d9152a102f)

参考

陈(2010)。应用整数规划:建模与求解。j .威利&的儿子们。

如何解决数据科学中的任何问题

原文:https://towardsdatascience.com/how-to-solve-any-problem-in-data-science-469a67b7ab15?source=collection_archive---------42-----------------------

解决数据科学中复杂问题的简单方法。

解决复杂问题的简单方法。

TLDR:

理解问题

  1. 写下来
  2. 写下你所知道的
  3. 写下你的假设/条件

规划您的解决方案

  1. 把你知道的和你不知道的联系起来
  2. 写下计划

实施您的解决方案

评估您的解决方案

介绍

数据科学家的工作是解决问题。大多数教程强调特定的技能、工具或算法。相反,本教程将概述一个解决问题的方法,你可以适用于几乎任何情况。

乔治·波利亚的《T2 如何解决:数学方法的一个新方面》一书概述了解决数学问题的四步方法论。

这种方法,加上一些小的改动,非常适合数据科学家。

这四个步骤是:

  1. 理解问题
  2. 设计一个计划
  3. 实施解决方案
  4. 评估解决方案

为了实际演示这种方法,我们将进行一个相当简单的编码练习。

理解问题

理解问题是解决问题最容易被忽视的方面。

你能做的最重要的事情就是把问题写下来。

一旦你把它写下来,确定它是真正的问题。我在 IT 部门工作时学到的一件事是,我被要求解决的问题很少是真正需要解决的问题。

一旦你确定了正确的问题,写下你所知道的与问题相关的一切。

执行此操作时要包括的项目:

  • 你以前解决过的类似问题
  • 限制
  • 要求
  • 你知道的任何与寻找解决方案有关的事情

最后,写下与解决方案相关的所有条件。其中一些是组织性的,另一些是技术性的。

例如,如果您将使用您公司的 Amazon EC2 实例来运行您的 python 解决方案,并且该 Python 环境使用 Pandas 版本. 23,那么您就不应该在您的解决方案中使用 Pandas 1.x 的特性。

潘格拉姆问题:

这个问题摘自exercism . io的 Python 赛道

确定一个句子是否是一个字谜。A pangram(希腊语:παν γράμμα,pan gramma,“每个字母”)是一个使用字母表中每个字母至少一次的句子。最著名的英语 pangram 是:
敏捷的棕色狐狸跳过懒惰的狗。
使用的字母表由 ASCII 字母 *a* *z* 组成,不区分大小写。输入将不包含非 ASCII 符号。

exercism . io

问题是

一个给定的字符串输入是英语语言的字谜吗?

我们知道些什么?

  1. Pangram:至少包含字母表中每个字母中的一个的字符串
  2. 字母表中有 26 个字母
  3. 字母是 ABCDEFGHIJKLMNOPQRSTUVWXYZ
  4. 如果一个字母不在字符串中,它就不可能是一个盘符
  5. 字母从少到多的共性是:QJZXVKWYFBGHMPDUCLSNTOIRAE 来源:https://www3 . nd . edu/~ busi forc/讲义/cryptography/letter frequency . html

我们解的条件是什么?

  1. 我们不关心非阿拉伯文字
  2. 我们不在乎一个字母是否大写
  3. 我们不在乎信件是否有重复
  4. 我们不在乎字母的顺序

规划解决方案

一旦我们理解了我们的问题,我们就可以计划我们的解决方案。这就是我们把我们所知道的东西拿出来,并勾画出我们如何用它来解决问题的地方。

在此阶段我们应该问的问题:

  • 怎样才能把我们知道的和我们不知道的联系起来?
  • 为了实现这一目标,我们还需要解决其他问题吗?
  • 我们过去是否解决过类似的问题,并且可以采用我们已经知道的解决方案?
  • 如果我们不能解决现存的问题,我们能不能先解决一个更简单的版本?

潘格拉姆计划:

为了解决 pangrams 问题,我们可以开始使用我们所知道的东西来游戏如何确定一个输入是否是 pangrams

  • 如果输入的长度小于 26,则它不能是一个 pangram
  • 如果一个字母不在输入中,它就不是一个盘符
  • 如果我们从最不常见的字母到最常见的字母来遍历字母表,那么计算效率会更高,因为失败更有可能发生在早期迭代中
  • 如果我们遍历字母表,我们最多有 26 个循环要经历

实施解决方案

这是您实际构建解决方案的地方。

这是我们许多人做得相当好的部分;如此之好,以至于这通常是我们试图解决问题时的第一步(可能就在我们疯狂地查看 google 或 stack overflow 之后)。

成功实施的关键是有条不紊地遵循计划。如果计划不起作用,回到计划阶段看看你是否错过了什么。

pangrams 实现:

这是我为执行我制定的计划而编写的 Python 函数:

# Execute the plan:

letter_list = ['Q', 'J', 'Z', 'X', 'V', 'K', 'W', 'Y', 'F', 'B', 'G', 'H', 'M',
               'P', 'D', 'U', 'C', 'L', 'S', 'N', 'T', 'O', 'I', 'R', 'A', 'E']

def is_pangram(input_string):
    pangram = True
    if len(input_string) < 26:
        pangram = False

    else:
        input_string = input_string.upper()
        for letter in letter_list:
            if letter not in input_string:
                pangram = False
                break
    return pangram# This will evaluate to false, it is missing a 'Z'
is_pangram("The quick brown fox jumps over the lay dog")# This will evaluate to True
is_pangram("The quick brown fox jumps over the lazy dog")

评估解决方案:

这最后一步很容易跳过,但如果我们想持续改进,这一步至关重要。我们需要评估我们答案的质量。

我们可以问的问题有:

  • 这是最好的解决方案吗?
  • 有更好的方法来解决这个问题吗?
  • 就内存和速度而言,我们解决方案中最昂贵的部分是什么?
  • 我的代码可读吗?
  • 评论够不够?
  • 三个月后这个坏了,我会知道它会做什么吗?

Pangrams 评估:

虽然我对这个解决方案相当满意,但我们还可以做一些改进。

我们可以使用 Python set()函数删除重复的字符,而不是评估整个输入,这将使我们的“如果不在”评估更容易。

我们也可以完全不同地处理这个问题,而不是分配一个字典,将一个字母与其 ASCII 码配对,然后使用一个索引函数来查找它。

我特别自豪的是,我的想法是按照共性的逆序迭代字母表。在研究这篇文章的时候,我查看了几个代码实践网站,没有看到其他人实现了这个想法。

结论

直接进入一个问题并试图立即解决它是非常容易的。这对于简单而熟悉的问题非常有效。然而,在复杂的非正统问题上,采用这样一种严格的方法将有助于你从同行中脱颖而出。

当我的团队打算招聘员工时,我们对他们解决问题的过程比对他们给出的具体答案更感兴趣。

最后,我强烈推荐你阅读波利亚的书

关于作者:

Charles Mendelson 是 PitchBook 的营销数据分析师。他还在攻读哈佛扩展学院的心理学硕士学位。如果你正在为你的数据导向播客或 YouTube 频道寻找一位客人,与他联系的最佳方式是在 LinkedIn 上。

原载于 2021 年 2 月 11 日 https://charlesmendelson.comhttps://charlesmendelson.com/tds/how-to-solve-any-problem-in-data-science/

如何高效解决复杂问题

原文:https://towardsdatascience.com/how-to-solve-complex-problems-efficiently-629c71adcd8d?source=collection_archive---------14-----------------------

在任何科学项目中,包括数据科学,如果你想要强大的附加值和创新,你将不得不处理复杂性。

解决复杂的问题需要很多不同的技能,包括注意力、想象力和沟通能力。今天,有经验的科学家提供了许多简单的解决方案来帮助人们完成他们的项目。我们将展示其中的几个,从最具创新性的开始。

杰斯温·托马斯Unsplash 上拍摄的照片

1.巧克力棒技术

一些从事算法研究的大师级数学家过去常常使用“巧克力棒”技术。

照片由 Louis Hansel @shotsoflouisUnsplash 上拍摄

这来自于一个相对复杂的数学问题:如果你有一块 5x12 的巧克力,你需要把它打碎多少次才能只剩下一小片?

最好的解决方法是先考虑一个 1x2 的杠,然后是 1x3,2x3 等等。

这背后的教训是,如果你必须解决一个复杂的问题,你会想尽可能地把它分成最小的部分,直到达到最基本的部分,然后一点一点地扩展它们以理解整体问题。

这也适用于知识块方面:非常复杂的问题需要几个知识块,即结合在一起能够解决复杂问题的基本理解块

例如,在了解一些量子力学之前,你将无法理解弦理论,在了解泛函分析(希尔伯特空间等)之前,你将无法理解量子力学。)等等……

2.寻求帮助可以增进理解和解决问题

通常,当我们在一个复杂的问题上受阻时,我们倾向于寻求支持作为最后的手段,但这是一个错误。

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

如果你必须快速达到好的结果,在问答网站上尽快描述你的问题会有以下好处:

  • 把问题设置清楚,你会理解的好很多。这就是为什么我们经常看到人们问一个问题,几个小时后,他们自己回答了这个问题,因为他们已经清楚地重新表述了这个问题。
  • 你可以很快得到答案。有时候,答案是一个新的有趣的问题,可能有助于取得进展,或者是一个直接的解决方案,这很好。
  • 你将提高你在复杂问题定义中的技能。描述一个复杂的问题不是一件容易的事情,因为你可能需要考虑很多方面。你寻求帮助越多,你就能更好地学会如何清楚地表达你的问题。
  • 它可以帮助其他有类似问题的人。

因此,在早期寻求帮助会节省你很多时间。

请注意,已经有问答网站讨论复杂科学话题,包括数据科学算法:

数学:https://mathoverflow.net/

数据科学:https://datascience.stackexchange.com/

物理:https://physics.stackexchange.com/

3.询问大师

在非常复杂的问题上,大师可以帮助你解决。

如果你正在应用一篇科学论文中的特定算法,而你还没有预期的结果,论文作者通常会回答任何问题

他们通常对如何在不同的项目中使用他们的算法感兴趣,这是一个双赢的局面。

他们的电子邮件或 LinkedIn 个人资料通常很容易找到。

注:当然,像诺贝尔奖得主或菲尔兹奖得主这样的大师,他们的研究活动非常繁忙,可能无法回答问题。

4.教学是学习的最佳途径

解决复杂问题的经典方法是用我们自己的话重新表述,甚至用我们的母语翻译(大脑的神经连接更好)。

理查德·费曼是最好的科学家之一,曾经有很好的教学技能。他能够用简单的语言有趣地解释非常复杂的现象。

重新制定的一个好的解决方案是把我们学到的东西教给别人,总的来说,如果它有一个好的故事。许多有趣的问题可能会出现,并提供新的改进方法。

5.添加尺寸以便更好地理解

在解决复杂问题时,提高可理解性至关重要。

因此,需要使用工具将复杂的问题可视化、简化、着色、动画化甚至模拟

薛定谔方程的例子通过提高 e 在动画中可视化。

这可以通过制作像 2D 或 3D 图表、动画视觉效果,以及在某些情况下 维度缩减 技术等新的表现方式来实现。

对于非常复杂的问题,模拟和测试平台总是受欢迎的,因为它们是实验性的方法,在其中我们可以处理复杂的环境并更好地理解它。

回旋加速器是大型试验台的一个很好的例子。

6.调整您的环境设计以解决问题

大多数科学家需要黑白黑板来解决复杂的问题。

由于有了董事会,我们有可能一次将大量无法在一篇论文中归类的信息进行归类。除此之外,这也是与其他同事讨论复杂话题的最佳方式。这也是把复杂的方程式留给 T21 思考的好方法。

IHES 的数学家们在户外讨论算法。IHES

宽大的桌子或屏幕也可以简化信息管理。

所有那些东西都可以组织成一个改进的设计,比较 本书

注意:交互式数字板也是处理复杂性的一个很好的解决方案,但是非常昂贵。

7.随意犯错,探索新的想法

许多科学突破都是由于意想不到的错误或失败而被发现的。

斯蒂芬·维达在 Unsplash 上拍摄的照片

青霉素、雷达或放射性是意外发现的好例子。

这意味着意想不到的结果可能导致新的解决方案。

错误也是丰富的学习材料,只要它们在一堂有意义的课中被转化。

解决问题并不总是寻找特定的解决方案,而是通过重构原始问题来发现新的解决方案。

8。再读题

应对复杂性需要一次又一次地重温研究

这可能是最难的部分,因为它感觉像是在浪费时间,但拥有扎实的知识是至关重要的。

熟能生巧。

9.掌握互联网搜索有巨大的优势

今天,每个人都使用互联网搜索来解决问题,但并不是所有人都知道高效搜索的方法,即使是科学专家。

这样的网页阅读技巧,这一条 从长远来看会为你节省很多时间。

如果你的英语不是很好,翻译工具也很强大,但是加语境往往很重要,才能达到好的翻译效果。

顺便说一下,我在这里写了一篇关于最近翻译服务背后的数学原理的文章。

10.阅读关于解决问题的书籍

许多有趣的书籍为复杂问题的解决提供了先进的解决方案。以下是其中的一些:

11.锻炼你解决问题的能力

善于解决问题也需要效率。

许多公司要求科学家能够快速解决问题,不仅在团队中,而且在个人中。因此,有可能在解决问题的网站中训练自己,其中一些网站有考试以获得证书或挑战。

欧拉项目:尝试解决许多有趣的数学问题。

出色的:通过创新的课程学习如何解决复杂的问题。

通过实践和挑战建立技能。

Hackerrank :练习包括数学问题的编码技巧。

更不用说 Kaggle 了,这是在拥有大量数据集的数据科学中解决问题的必备。

你呢?

感谢阅读。这篇文章不是关于一个单一的经历,而是来自几个经历,其中可能包括你的经历。

欢迎在评论中分享你的解决方案,我会添加一章来分享给大家。

我希望这篇文章能帮助你更好地理解复杂性,正如理查德·费曼所说的“自然界不可思议的性质”。

如何解决数据科学商业案例面试问题

原文:https://towardsdatascience.com/how-to-solve-data-science-business-case-interview-questions-a4eb3a6f7986?source=collection_archive---------26-----------------------

作为数据科学家准备业务案例面试问题的终极指南

作者在 Canva 上创建的图片

探讨数据科学业务案例面试问题

产品感面试问题类似,数据科学中的业务案例面试问题旨在了解您的解决方案背后的思维过程。即使你的解决方案提供了问题的准确答案,如果你没有给出正确的回答步骤,这在受访者看来也不太好。

业务案例面试问题要求:

  • 诊断和解决实际业务案例问题的能力
  • 了解受访者对围绕公司产品的经济/业务的熟悉程度
  • 受访者解决方案的可行性
  • 以结构化的方式有效传达解决方案

(你答案中的所有这些品质都是数据科学工作的一部分,所以尽量确保你记住了这些)

为了有效地为所提出的业务案例面试问题提供解决方案,了解问题属于哪个类别非常重要。

  1. 应用数据(最常见)
  2. 胶料
  3. 理论测试

问题类型

  • 简要说明
  • 具体例子和一般例子
  • 公司寻找:(在你的答案中)

应用数据

这些问题要求您通过利用公司数据或外部来源来解决特定的业务问题。

这些问题的示例:

  1. DemystData 问“金融机构如何确定申请人的年薪是高于还是低于 5 万美元?”
  2. 脸书问“人们在脸书个人资料上列出的高中有多少是真实的?我们如何找到并大规模部署寻找无效学校的方法?”

公司寻求:

  • 受访者识别和定义相关数据的能力如何
  • 受访者对相关产品的理解程度
  • 受访者对围绕产品的业务/经济的了解程度

定尺寸

这些问题要求预测销售/存在的产品数量。这些都是看似随意,与公司无关的问题。

这些问题的示例:

  1. 谷歌问“去年美国卖出了多少罐蓝色油漆?”
  2. Ebay 问“三藩市所有道路的总长度是多少?”

公司寻求:

  • 受访者对相关产品的理解程度
  • 受访者对目标市场的识别能力如何

理论测试

问这些问题是为了证明/反驳通常涉及公司内产品/功能变化的理论。

这个问题的例子:

  1. 如果一个项目经理说他们想把新闻提要中的广告数量增加一倍,你如何判断这是不是一个好主意?

公司寻求:

  • 受访者对变更后的产品/功能的理解程度如何
  • 受访者对产品和目标受众之间关系的理解程度
  • 选择相关指标来跟踪变革是否成功

结构化解决方案

作者在 Canva 上创建的图像

对提出的业务案例面试问题进行分类后,你应该开始构建你的解决方案。不要立即回答这个问题。要明白,即使你给出了一个好的答案,面试官也想知道你是如何得出答案的。

面试官寻找:

  • 采用系统方法的解决方案
  • 为什么选择了某种解决方案而不是另一种
  • 涵盖问题的关键领域
  • 可行的解决方案

虽然每个数据科学业务案例面试问题都有不同的解决方案,但您的部分解决方案有相同的方法。解决方案的这一部分可以作为背景研究来创建一个特殊的解决方案。

总体框架

受访者首先要做的是理解问题。虽然这看起来很简单,但是你对这个问题的假设可能和面试官想要的不一样。我认为,当你是一名数据科学家,为潜在客户构建背景信息时,你需要了解他们的需求。仅仅通过一个问题很难抓住这一点。花点时间想想公司为什么会问这个问题。

商业案例问题经常被问到:市场份额、用户参与度或收入。了解公司正在努力增加哪一类产品,根据客户的反应,您的解决方案可能会也可能不会改变!即使你认为这不会改变你的解决方案,也要提出来表明你的想法,因为这是开发实际功能/产品时的一个重要方面。

理解问题的一个重要部分是理解问题的关键术语。为了确保你涵盖了所有的关键术语,从头到尾指出并询问你是否对关键术语有一个适当的假设。

例子:“麦当劳在美国每年卖多少个巨无霸?”

  • “巨无霸”→假设巨无霸既包括自己卖的巨无霸,也包括套餐的一部分。巨无霸还有其他的销售方式吗,比如促销/限时销售?
  • “年”→年是指 1 月 1 日至 12 月 31 日(公历)还是 10 月 1 日至 9 月 30 日的财年?
  • “美国”→美国是指美国的 50 个州和特区,还是包括美国的外围小岛和领土?

彻底理解问题后,您需要根据所提问题的类型(应用数据、规模、理论测试)提供解决方案。

特定框架

应用数据

应用数据是一组极其多样化的问题,因此很难有一个特定的框架。这个问题真正测试你对公司产品的了解程度以及如何利用相关数据。

在花时间构建您的解决方案时,请考虑公司可以访问哪些类型的数据?想想公司收集的是什么内部数据。当谈到“应用数据”问题时,内部数据是一个很好的来源,因为公司通常已经收集了相关数据。例如优步问“你如何估计优步对驾驶状况和交通拥堵的影响?”优步已经收集了客户目前使用的优步汽车的相关数据。优步还将拥有其支持的城市在任何给定时间范围内的交通数据。这些是可以用来构建您的解决方案的内部数据。不要忘记从外部来源收集数据。也可以从可信的外部来源收集和利用数据,但是如果您选择不良的数据源,这可能是一个风险更大的答案。

如果需要收集的数据是指标,记得同时提到成功指标和护栏指标。成功指标是您用来量化特定产品的成功的指标。护栏指标是在追求改变成功指标的过程中不会受到负面影响的指标。例如,优步问“你会用什么指标来跟踪优步利用付费广告获取客户的策略是否奏效?”一个可能的成功度量可以是用户的无机增长,护栏度量可以是乘坐的次数。虽然付费广告的目的可能是增加用户数量(这些假设是你作为受访者想要问面试官的问题类型!)优步不希望人们乘坐的交通工具数量减少。

一旦您了解您的解决方案需要哪些数据,请说明所收集的每项数据与您的解决方案有何关联。这表明您了解所选数据的应用领域,以及这些数据如何支持您的解决方案。

请记住,应用数据问题通常涉及用户和用户体验。试着像一个典型用户和边缘用户那样思考来构建你的解决方案。例如脸书问“我们脸书公司想开发一种方法来估计人们的生日,不管人们是否直接给我们这些信息。你会提出什么方法,使用什么数据来帮助完成这项任务?”假设你是一个脸书用户。你可以通过直接信息或者脸书标签收到脸书的生日祝福。一个可能的解决方案是,检查在提到“生日”或“生日”等关键词的帖子中给你贴标签的用户数量。这些帖子往往在你的实际生日期间更多,所以脸书可以据此估计你的生日。

上浆

规模问题可能看起来非常随机和多样,但是分解如何实现解决方案更容易。规模问题也可以称为猜测,因为您试图做出一个估计的猜测。询问规模问题是为了了解您对特定产品的目标受众的识别程度。比如,谷歌问“去年美国卖了多少罐蓝色油漆?”谷歌想知道你能找到多少目标受众,并进一步了解这些消费者大概会购买多少蓝色颜料罐。

要记住的一个关键点是,你不必试图给出某个目标受众将购买多少蓝色油漆罐的超精确数字。面试官可能也不知道确切的答案,他们只是想听听你答案背后的思维过程。

由于规模问题试图确定目标受众,因此潜在用户中有一些常见的分裂因素(不限于):

  1. 年龄
  2. 性别
  3. 人种
  4. 宗教
  5. 农村/城市
  6. 收入
  7. 乐意

另一个要考虑的因素是产品/服务的消费类型。有 3 种消费类型:个人,家庭,结构。

  • 个人是指产品/服务的个人消费,如牙刷、水瓶或 t 恤。
  • 家庭是指整个家庭的消费,如汽车、电视和冰箱。
  • 结构性是指不同家庭的多人消费。例子包括飞机和餐馆。

首先陈述几个目标受众(使用过滤器来帮助),然后提及你将关注的代表大部分市场的目标受众。

一般来说,这是一个好主意,涉及至少 3 个谁会使用产品/服务的过滤器。始终解释过滤器和目标受众之间的相关性。例如,抖音更适合向 13-18 岁的年轻受众做广告,而不是 65 岁以上的老年人。

如前所述,面试官并不寻求精确的数字,所以尽量使用整数。让我们以抖音为例,假设 20%的美国人口年龄在 13-18 岁之间。美国的人口大约是 333,548,370。333,543,000 的 20%很难在面试的时候当场算出来,特别是紧张的时候。如果把人口四舍五入到 3 亿,计算 3 亿的 20%就容易多了。

人们可以使用多种方法来估计规模,但是在分析了各种方法之后,有一种方法脱颖而出,特别是对于数据科学业务案例访谈。该方法是创建将使用该产品的消费者类型的布局,并填写将使用该产品的大致人数。

为了更好地解释这个方法,让我们用一个脸书的面试问题“麦当劳在美国每年卖多少个巨无霸?”。

让我们先取一个美国人口的大概数字,我们假设大约是 3 亿。

巨无霸的主要目标受众通常比儿童餐的目标受众年龄大,比老年人年龄小。主要的目标受众是大学生、家庭和想买便餐的人。

关于大学生,让我们假设 10%的人口是大学生。300 米的 10% = 30 米。让我们假设一个普通大学生每周买一次麦当劳。不是每个人都会买巨无霸,但既然是菜单上的热门项目,我们假设去麦当劳的人有三分之一会买巨无霸。三千万的⅓就是一千万。这意味着在这些假设下,大学生每周会购买 1000 万个巨无霸。这相当于每年 5.2 亿个巨无霸。

关于家庭,让我们假设三分之二的人口生活在同一个家庭中。300 米的三分之二是 200 米。当一个家庭购买食物时,他们倾向于为整个家庭购买。让我们假设普通家庭每周从餐馆购买一次食物,也许每月从麦当劳购买一次。让我们假设一个典型的 4 口之家,一个人选择吃巨无霸。200 米/4 = 50 米。在家庭目标受众下,每月有 5000 万人购买一次巨无霸。这相当于每年 6 亿个巨无霸。

关于那些想买便餐的人,让我们假设有 10%的人想每周买一次快速便餐。300M * 10% = 30M。麦当劳是一家受欢迎的快餐连锁店,在美国几乎到处都有分店。我们假设 3000 万人中,有 50%的人选择麦当劳。30M * 50% = 15M。这导致 1500 万人每周从麦当劳购买一次。让我们假设这些人中有三分之一的人购买巨无霸,这样每周就有 500 万个巨无霸卖给想要快速便宜的目标顾客。这相当于一年售出 2.6 亿个巨无霸。

如果你把这些价值加在一起,美国一年售出的巨无霸数量为 5.2 亿+6.0 亿+2.6 亿= 13.8 亿。

最后,在提到你的最终答案后,你还可以提供更多可能影响价值的相关信息。例如,麦当劳有一个 5 美元或 6 美元的特卖,顾客可以用 5/6 美元购买 2 个巨无霸。这将增加巨无霸的销量。这表明你对产品有所了解。

有时在面试中,你会得到一块在线板,你可以在上面画画并记下你的想法。这可能是一个你可以选择的设计,帮助你更好地理解和解释你的想法!

要记住的事情

  • 记住,你不必提及所有的目标受众。提及占据大部分市场的重要案例,如果你愿意,也可以提及边缘案例。
  • 当你得到最终答案时,做一个理智检查。检查你的最终答案是高估还是低估,并相应地调整数值。
  • 尤其是在使用消费者类型的布局时,要写下来,这样你就有了什么与什么相关的参考
  • 请记住,您可以使用任何听起来合理的过滤器,但一定要记住提及这与实际解决方案的关系。
  • 要记住的一个关键点是不要使用个人偏见。记住你的社交圈并不代表整个人口。不要假设每个人都和你想的一样。站在别人的立场上,看看他们会如何看待这个问题。

理论测试

记住理论测试主要是测试你对产品和目标受众的理解程度。有 3 个步骤可以帮助回答这些问题。

  1. 确定受影响的用户
  2. 变革的利弊
  3. 证明/否定该理论的数据
  4. 将会改变的指标

为了帮助解释这些步骤,我们将使用脸书提出的一个问题:“一位总理想要将新闻订阅中的广告数量增加一倍,你如何判断这是否是一个好主意?”

受影响的用户

影像测试假设,首先你需要做一些背景研究。了解什么类型的用户会受到这种变化的影响。列出受影响的用户组。产品中的一些变化会影响所有用户,而一些变化只会主要影响一部分用户。受影响的用户是目标受众还是其他用户?

以脸书为例,浏览其新闻源的脸书普通用户将受到影响,影响者也将受到影响,因为将会有更多的广告而不是帖子。

利与弊

产品的每一个变化都有积极和消极的一面。这可能会影响用户群或公司的资源。列出两个优点和两个缺点,如果改变被实现,产品将会如何改变。理论测试通常包括测试关于改变产品/服务的理论。利弊列表将有助于更好地理解变更以及收集哪些数据/指标。确定受影响用户的原因是为了在利弊列表中考虑用户组将如何受到影响,因为最终用户是将使用该产品的人。

以脸书为例:

优点

  • 增加脸书的收入
  • 由于广告的增加,企业可能会选择使用脸书作为其营销技术的解决方案

缺点

  • 由于广告的增加,用户可能会减少在应用上的时间
  • 有影响力的人可能不会发布太多的帖子,因为他们的帖子没有像以前那样得到认可

数据支持理论

有时,类似的变革可能已经在同一家公司或另一家公司实施过。如果你知道是否进行了类似的变更,说明变更对产品产生了怎样的影响,以及哪些指标发生了变化。

如果没有之前的数据,请说明如果实施变更,您认为哪些指标会发生变化。记得提及你如何预测指标将会改变,以及你为什么会这样想背后的逻辑。

以脸书为例,我们可以看到当脸书第一次在新闻订阅中植入广告时用户的感受。这将提供关于它如何影响脸书用户的直接信息。可以跟踪的指标包括每日活跃用户和影响者帖子的数量。DAU 将帮助显示用户在改变后是否停止使用该应用程序。如果有影响者的帖子数量减少,他们的追随者对应用程序的使用也会减少。

此时,您已经解释了一般框架和具体问题框架的初始部分。现在,您必须解释边缘案例并总结您的解决方案。

对于任何给定的业务案例面试问题,您给出的每个解决方案都不会涵盖某个边缘案例。出现这种情况的主要原因可能是由于面试期间的时间限制。识别您的解决方案没有覆盖的边缘情况是很好的。即使你不能解释如何解决边缘案例,识别一个可能的边缘案例也比完全不识别要好。许多受访者会指出解决方案的大部分,但指出边缘案例将有助于将您与其他人区分开来。在您的具体问题解决方案之后,有理由提及边缘案例。这有助于构建你的解决方案,让面试官不会感到困惑。

一个边缘案例的例子可以用一个谷歌采访问题来看,“去年美国卖出了多少罐蓝色油漆?”假设确定了 3 个潜在的主要目标受众:住宅建筑、企业建筑和汽车制造商。一个极端的例子是幼儿园和小学会为学生购买油漆。作为受访者,你可以提出一些粗略的估计,说明你如何计算可能购买了多少蓝色油漆。

提供您的详细解决方案后,您应该总结您的解决方案。

记得包括:

  1. 对问题的假设
  2. 收集的数据/指标以及与解决方案的相关性
  3. 使用收集的数据/指标概述解决方案的具体方法

你的解决方案的总结是你面试的一个重要部分。重申你的解决方案中的关键点是很重要的,但它也表明了你将如何与投资者和客户就如何解决这些业务问题进行沟通。

要遵循的步骤概述

  1. 澄清问题的目标——他们为什么问这个问题——了解产品与公司目标的关系——努力增加收入、市场份额或用户参与度
  2. 理解问题—分解关键词
  3. 特定框架
  4. 边缘案例
  5. 总结答案

传达您的解决方案

作者在 Canva 上创建的图片

请记住,你的最终答案并不是面试成功与否的决定性因素。你必须能够详细地交流你的思维过程。面试官想知道你的思维过程是如何运作的,想知道你在解释你的解决方案时是否涵盖了所有的要点。面试的一个重要部分是你能多好地交流你的解决方案。

你和面试官之间应该对问题和思维过程有一个清晰的认识。面试官的意见可能是你的解决方案中最重要的部分。如果面试官给出的指示或提出的问题偏离了框架,那就照着做。千万不要严格按照框架来。你应该根据面试官的评论完善你的解决方案和回答步骤。记住面试官会影响雇佣你的决定,所以你越能吸收面试官的意见,你的机会就越大。

在回应前花点时间

  • 作为受访者,你有一些时间来思考如何解决问题。如果你立即回应,你可能会意识到你的解决方案有一个重大缺陷,从而导致你退回去纠正问题。为了防止这种情况以及你和面试官之间的误解,在回答之前花点时间。受访者通常需要 30 秒钟才能回答。
  • 如果想出解决方案的时间确实超过 30 秒,也不用担心!在这一点上,你可以陈述你的假设,以及你是如何思考如何开始你的解决方案的。这样可以避免尴尬的沉默,也不会显得你花了太多时间来提供解决方案。

就目标/假设达成一致

  • 与面试官交流的一个关键部分是了解如何着手解决问题。商业案例问题背后的措辞故意含糊不清,因此受访者可以识别出需要澄清的短语。类似于与客户的实际讨论,在构思解决方案之前,您需要就目标/假设达成一致。

提及技术术语

  • 既然你申请的是一个技术职位,你就应该使用专业术语来区分你和其他人。这表明你对某些技术概念的应用有所了解。
  • 记住,你永远不要强迫自己使用专业术语。有些时候你应该避免使用技术术语
    ,如果你不完全理解技术概念
    ,如果技术概念是多余的,或者如果问题有更简单的解决方案。仅仅因为机器学习这个术语在任何地方都有销路,并不意味着你应该在任何地方都使用它。
    技术概念和您的解决方案之间没有关联
  • 商业案例面试问题并不总是需要复杂的技术概念,所以不要担心你的解决方案是否简单明了。只要你的解决方案涵盖了问题的重要部分,你就是优秀的。

新指标/数据

  • 每当引入新的指标或收集数据时,都要提到指标/数据是什么。
  • 如何得出/收集指标/数据。
  • 新的指标/数据如何帮助打造您的解决方案?

示例:

赛门铁克问“假设你有一家咖啡店,你如何增加顾客数量?”假设你正试图通过发布一则你最受欢迎的产品的假日促销广告来增加顾客数量。提到你应该收集有多少人购买每种产品的数据集。这可以通过交易和销售的产品来收集。一旦你收集了数据,你就可以发现哪些商品卖得最多。根据畅销产品的利润率,你可以暂时降低价格来增加顾客数量!

被卡住

  • 在提供你的解决方案时,如果你在你的解决方案中卡住了,告诉你的面试官你卡住了!告诉他们你是如何考虑你的解决方案的,以及下一步你想达到的目标。告诉面试官你在解决方案中考虑过的某些步骤,但由于某些原因没有采取(解释这些原因)。试着看看面试官有没有给出什么线索。

你的解决方案中的错误

  • 如果你认为你的解决方案不合理或者肯定会导致错误,说明为什么你的解决方案行不通。多花些时间看看你是否能改变你的解决方案,或者你是否必须回溯你的解决方案到你觉得最有信心的地方。请记住,如果您遇到您的解决方案无法处理的问题,请不要担心。类似于工作环境,最好是确定一个问题,而不是继续在一个破碎的基础上。当提及您的新解决方案时,记得明确说明您的新解决方案将如何避免该问题。

总是大声说出你的解决方案!通过你的解决方案与面试官交流,这样他们也能理解你的思维过程。记住每一步都要和前一步以及总体目标联系起来。经过几个步骤后,做一个理智检查,确保面试官理解你的解决方案。

面试前如何准备商业案例问题

商业案例面试问题是数据科学面试中另一个具有挑战性的部分。由于问题的多样性和看似随机的问题,这些问题很难预测。

关于 3 类业务案例问题:应用数据、规模和理论测试,每一类都有不同的准备方式。

准备应用数据问题时,首先你必须了解公司的业务类型。该公司是否涉足大量 B2B 或 B2C 业务?有时候,对于大公司,比如谷歌,公司会提到你申请的部门。研究这个部门做什么类型的业务。接下来你应该了解公司生产的产品类型,或者更好地了解你申请的部门生产的产品。尝试理解围绕产品的商业模式,以及他们会使用什么类型的数据来帮助改进产品。如果没有这方面的公开资料,试着自己做假设!从目标受众的不同角度来看待产品,以及您将收集哪些数据来了解如何改进产品。

不幸的是,规模问题更具随机性,有时公司会问一个似乎与公司业务模式无关的问题。例子:谷歌问“去年美国卖出了多少罐蓝色油漆?”对于这些类型的问题,需要不断练习其他规模问题。

准备理论测试是应用数据问题的下一步,因为你已经发现如何应用数据来改进产品。如何测试这实际上是否可行?想想如果应用这个解决方案会发生什么。用户将在多大程度上受到影响,某些指标将如何增加、减少或保持不变。想想你的潜在雇主会面临什么样的问题!这些问题可以用数据科学的方法来解决,所以想想你会如何解决这个问题!

尝试研究该产品的竞争对手,了解其他竞争公司是否已经改变了他们的产品,类似于你申请的公司试图提及它如何为竞争公司工作!与规模问题类似,理论测试需要用多个问题进行练习!

最初发表于【https://www.stratascratch.com】

如何用 Python 解决优化问题

原文:https://towardsdatascience.com/how-to-solve-optimization-problems-with-python-9088bf8d48e5?source=collection_archive---------4-----------------------

如何使用纸浆库用几行代码解决线性规划问题

查尔斯·德鲁维奥在 Unsplash 上拍摄的照片

线性规划(或线性优化)是在有约束的数学问题中求解最佳结果的过程。 PuLP 是一个强大的库,它只需要几行代码就可以帮助 Python 用户解决这类问题。

我发现 PuLP 是解决这类线性优化问题的最简单的库。目标函数和约束都可以添加到一个有趣的分层方法中,每个方法只需一行代码。这意味着我们可以花更少的时间编码,花更多的时间解决问题。文档也易于阅读,包括五个易于理解的案例研究

在本文中,我们将使用来自 Fanduel 的 daily fantasy sports (DFS)数据来演示如何解决具有多个约束的最大化问题。目的是这些步骤可以推广到你想解决的其他问题。

我们将使用 DFS 数据,因为它允许我们从理解现实世界的问题到根据目标函数和约束条件定义问题,再到最终用 Python 编写解决方案的整个过程。所有这些步骤都是任何线性规划问题的重要组成部分。DFS 是一个足够简单的上下文来理解这些步骤,同时又足够复杂来讨论它们。

如果您想跟进,请按照以下步骤免费获取数据:

  1. Fanduel 创建一个免费的幻想账户
  2. 前往大厅内的 NBA 选项卡
  3. 单击下面的任何比赛,然后单击“输入新阵容”按钮
  4. 最后,点击页面顶部的“下载球员名单”来获取 csv 格式的数据

照片由 JC GallidonUnsplash 上拍摄

NBA 中 DFS 的背景

在我们进入这篇文章之前,我们将快速看一下 Fanduel 为 NBA 组织比赛的方式。

这一背景将构成我们如何为我们试图解决的问题设置约束的基础。在坐下来实际编写代码之前,理解线性编程中的问题总是必要的。当我们坐下来写代码时,这有助于我们形成约束和目标函数。

目标是建立一个 9 人阵容,尽可能多的得分。玩家通过在当天的比赛中做成功的事情来获得分数,如得分或抢到一个篮板,而消极的行为如把球翻过来会被扣分。每个篮球运动员那天都有一份假想的薪水(来自 Fandeul ),你有 60,000 美元分配给这些运动员。你必须选择 2 名控球后卫,2 名得分后卫,2 名小前锋,2 名大前锋和 1 名中锋。

照片由rupixen.comUnsplash 上拍摄

我们想要解决的问题

既然我们对我们试图解决的问题有了很好的理解,让我们用我们的目标函数正式定义它:

  • 最大化我们 9 名玩家的投射点数。

我们想在问题中加入的约束:

  1. 一个玩家最多只能买 1 次。
  2. 拥有 2 个控卫,2 个得分后卫,2 个小前锋,2 个大前锋,1 个中锋。
  3. 花费不超过 6 万美元。

用纸浆来解决这个问题

我们现在可以开始实际编写代码来解决这个问题。由于这是一篇关于优化的文章(而不是一篇关于预测结果的文章),我们将使用每个玩家的平均分数作为他们今天的预测分数。如果我们正在为 Fanduel 构建一个真正的优化器,我们会希望改进我们的估计,以包括其他变量,如比赛和每个球员的预计上场时间。

初始设置

首先,让我们在命令行中使用 pip 来安装该软件包:

pip install pulp

并在我们的 Jupyter 笔记本或 IDE 中导入必要的包:

from pulp import *
import pandas as pd

然后,我们将使用pd.read_csv()读取数据,给我们一个熊猫数据帧,包括Nickname(Fanduel 上玩家的名字)FPPG(该玩家每场比赛的平均得分)、SalaryPosition变量,我们将称之为data

设置数据结构

我们现在需要使用字典定义变量,因为这些是PuLP使用的数据结构:

# Get a list of players
players = list(data['Nickname'])# Initialize Dictionaries for Salaries and Positions
salaries = dict(zip(players, data['Salary']))
positions = dict(zip(players, data['Position']))# Dictionary for Projected Score for each player
project_points = dict(zip(players, data['FPPG']))# Set Players to Take either 1 or 0 values (owned or not)
player_vars = LpVariable.dicts("Player", players, lowBound=0, upBound=1, cat='Integer')

除了最后一行,所有行都建立了字典,将存储在Nickname中的玩家名字指向我们感兴趣的其他变量。

最后一行使用了LpVariables,它定义了与第二个参数(在本例中是players)数值相关的变量。其他参数定义了player_vars可以采用的值。参数cat可以设置为'Integer''Continuous'。我们只剩下一个将玩家名字指向整数的字典(我们将使用整数分别用 1 或 0 来表示我们是否拥有该玩家)。

定义问题

接下来,我们需要使用LpProblem()设置我们的问题:

total_score = LpProblem("Fantasy_Points_Problem", LpMaximize)

第一个参数是问题的名称,第二个参数是名为sense的参数,可以设置为LpMinimizeLpMaximize。我们使用LpMaximize,因为我们试图最大化我们的投影点。

在我们定义了问题之后,我们使用lpsum()添加我们的目标函数:

total_score += lpSum([project_points[i] * player_vars[i] for i in player_vars])

我们的薪资限制:

total_score += lpSum([salaries[i] * player_vars[i] for i in player_vars]) <= 60000

以及我们的位置限制:

# Get indices of players for each position
pg = [p for p in positions.keys() if positions[p] == 'PG']
sg = [p for p in positions.keys() if positions[p] == 'SG']
sf = [p for p in positions.keys() if positions[p] == 'SF']
pf = [p for p in positions.keys() if positions[p] == 'PF']
c = [p for p in positions.keys() if positions[p] == 'C']
# Set Constraints
total_score += lpSum([player_vars[i] for i in pg]) == 2
total_score += lpSum([player_vars[i] for i in sg]) == 2
total_score += lpSum([player_vars[i] for i in sf]) == 2
total_score += lpSum([player_vars[i] for i in pf]) == 2
total_score += lpSum([player_vars[i] for i in c]) == 1

解决问题

一旦我们定义了问题,我们可以用一行代码解决问题!

total_score.solve()

一旦我们这样做了,我们的优化变量通过调用total_score.variables()被存储在一个列表中,我们每个玩家的值被存储在变量varValue中,我们的值的名字被存储在每个变量的变量name中。因此,我们可以通过查找具有非零值的球员来打印我们的阵容,如下所示:

for v in total_score.variables():
    if v.varValue > 0:
        print(v.name)

Wadi LissaUnsplash 上拍摄的照片

结论

我们现在能够用 Python 中的 PuLP 解决复杂的线性编程问题了!一旦我们理解了我们试图解决的问题,我们就可以使用这个库用几行代码来解决它。

线性优化是许多领域的重要组成部分,如运营、物流、资本配置等。学习这种技能的最好方法是自己解决问题。您可以使用我们在上面走过的相同步骤:

  1. 理解问题
  2. 根据目标函数和约束条件来定义问题
  3. 用纸浆解决问题

我鼓励你把这些步骤应用到你感兴趣的问题上,我很高兴在下面的评论中听到你在做什么项目!

感谢您花时间阅读本文,并祝您在下一个线性编程问题上好运。

如何用数学解决 Python 编码问题

原文:https://towardsdatascience.com/how-to-solve-python-coding-questions-using-math-72d5540b5a24?source=collection_archive---------13-----------------------

破解数据科学面试

2021 年数据科学家和软件工程师必备的编码技能

JESHOOTS.COMUnsplash 上拍照

Python 编码面试有不同的形式,每种类型都有其独特的特点和方法。例如, 字符串操作 题期望考生对元素的检索和访问有扎实的掌握。 数据类型切换 问题测试你对每种类型的权衡和独特特征的理解。

但是,数学题不一样。没有一致的测试方法。相反,您必须找出数据模式并用 Python 对其进行编码,这起初听起来令人望而生畏,但经过实践后是完全可行的。

在这篇文章中,我详细阐述并实时编码了 5 个真实的面试问题,帮助你更好地理解数学在 Python 中是如何工作的。

问题 1:计算区间范围内的奇数,由微软

-给定两个非负整数 low 和 high。
-返回低和高(含)之间的奇数计数。
-https://leet code . com/problems/count-odd-numbers-in-a-interval-range/

走过我的思考

微软问这个问题。作为热身,这个问题似乎太琐碎了,不应该包含在数据科学或软件工程面试中。然而,如果你不知道数学上的捷径,这是非常困难的。

我的第一直觉是迭代上下界的范围,,并使用 for 循环计算奇数的个数。

Python 实现的工作方式如下。

解决方案 1: for 循环

3

正如所料,它在窄范围内运行良好,但在宽范围内运行非常慢。你可以试试这个测试用例:countOdds(3,72222222222222222222222),它需要永远完成。

解决方案 2:数学

作为今天博文的主题,我们学习如何发现数据中的模式,并使用数学方法解决手头的问题。

要计算高低范围内的奇数,它等于上限的奇数减去下限的奇数。

在数学中,结果=奇数到高的计数-奇数到低的计数。

此外,有 50%的奇数,和 50%的偶数。例如,对于 0 和 8 之间的范围,有 4 个奇数和 4 个偶数。

Python 的一般实现如下:

3611111111111110

第二种方法即时返回结果,即使是大范围的结果。对于需要数学计算的问题,优先考虑的是分析模式并找到它的数学等价。我们必须大量练习,才能对潜在的想法感到舒服。

问题 2:排列硬币,作者彭博

-你总共有 n 个硬币,你想形成一个楼梯形状,其中每第 k 行必须正好有 k 个硬币。
——给定 n,求能形成的全楼梯排的总数。

走过我的思考

彭博包括这个问题。总共有 n 个硬币,我们试着把 k 个硬币放在第 k 行。我画了一个简单的图表作为视觉辅助。

我自己的截图

如果 n = 8,我们将 1 放在第一行,2 放在第二行,3 放在第三行,2 放在第四行。因为只有前三排是全楼梯,所以该函数应该返回 3。

有趣的模式是,从第 I 个全楼梯到第(i+1)个全楼梯增加了 1 个单位。在高中,我们学过这种数列叫做等差数列等差数列。所以,对于第 k 个完整的楼梯,硬币总数= k*(k+1)/2。

记不住公式也不用担心。我写这篇文章的时候谷歌了一下。

下一步是找到一种方法来最大化完整楼梯的数量,并最小化硬币计数和 n 之间的距离,这可以通过使用二分搜索法来实现。

解决办法

3

这是二分搜索法的标准实现,唯一的问题是能够得出算术序列的求和公式。

问题 3:频闪信号数字,脸书

-频闪数字是旋转 180 度后看起来相同的数字(上下颠倒)。写一个函数来确定一个数字是否是频闪的。该数字表示为字符串。
——https://leetcode.com/problems/strobogrammatic-number/

走过我的思考

脸书问了这个问题。写下一些数字并将它们旋转 180 度会很有帮助。

**Original      180 degrees rotation**
   0                 0
   1                 1
   2              invalid
   3              invalid
   4              invalid
   5              invalid
   6                 9
   7              invalid
   8                 8
   9                 6 

从 0 到 9,旋转 180 度后只有 5 个有效数字和 5 个无效数字。对于这些有效数字,只有 0、1 和 8 在旋转后保持不变,其他两个数字 6 和 9 会改变值。

一方面,如果一个数包含任何无效的数字,那么它在旋转后就不是一个有效的数。

另一方面,我们返回有效数字(0、1、6、8 和 9)的“镜像”值。我们可以创建一个字典,并利用它的键值对特性来返回值。

Dictionary 有一个独特的键值对特性,这在很多情况下都很方便。请看这里:

解决办法

在 Python 中,我们可以做到以下几点:

True

有两个条件。首先,num 存储为一个字符串,而不是一个整数,我们必须小心访问字符串元素。第二,数字在旋转后会改变它们的位置,因此我们必须使用 reversed()方法从最后一个(最右边的)数字向后读取,例如,169 → 691。

剩下的就不言而喻了。

问题 4:设置不匹配,由亚马逊

-集合 S 最初包含从 1 到 n 的数字。
-但不幸的是,由于数据错误,集合中的一个数字与集合中的另一个数字重复,导致一个数字重复,另一个数字丢失。
-给定一个数组 nums,表示该集合出错后的数据状态。你的任务是首先找到出现两次的数字,然后找到丢失的数字。以数组的形式返回它们。【https://leetcode.com/problems/set-mismatch/】-

走过我的思考

亚马逊问这个问题。简单来说,一个数字重复两次,在一个数字序列中就少了一个数字。我们的任务是找到他们两个。

使用非数学方法解决这个问题是可能的,但是缺点是使用额外的内存利用率,这在技术面试中是被禁止的。所以,我们会用数学方法来解决它。

#1 To find the repeated number
The go-to data type is a set, which does not allow duplicates. By changing the data type to a set, we can get rid of the duplicated case. Then, take the difference between the total sum of the original array and the set. #2 To find the missing number 
Like the first step, we use a set to remove the duplicate and take the difference between the sum of the range up to n and the set.

在 Python 中,我们可以做以下代码。

解决办法

[1, 2]

它工作了。

顺便提一下,在 Python 中将一个集合与另一个函数/方法组合起来,例如 len()和 sum(),是在取出副本后检查更改的一种强大方法。

问题 5:三的力量,高盛和 Hulu

-给定一个整数 n,如果它是 3 的幂,则返回 true。否则,返回 false。
-整数 n 是 3 的幂,如果存在整数 x 使得 n = = https://leetcode.com/problems/power-of-three/
--

走过我的思考

高盛和 Hulu 收录了这个面试问题。有两种方法。首先我们可以用 while 循环把数除以 3,如果是 3 的幂,那么剩余的部分应该是 1。第二,我们可以使用递归。在这里,我将两种解决方案进行比较。

解决方案 1:数学

对于这个问题,数学部分比较容易。我们只需要记住,对于幂数字,提醒应该等于 1。

True

解决方案 2:递归

我们需要指定第二种方法的基本条件。对于幂数,剩余部分等于 0;对其他人来说,剩下的部分不是 0。

False

完整的 Python 代码在我的 Github 上有。

外卖食品

  • 数学对于 Python 编程来说很方便。
  • 最具挑战性的部分是发现模式并编码。
  • 为了找到模式,写出几个例子会有所帮助。
  • 特例呢?重复的怎么办?一套可以有帮助!

Medium 最近进化出了它的 作家伙伴计划 ,支持像我这样的普通作家。如果你还不是订户,通过下面的链接注册,我会收到一部分会员费。

https://leihua-ye.medium.com/membership

我的数据科学面试序列

</5-python-coding-questions-asked-at-faang-59e6cf5ba2a0>

喜欢读这本书吗?

请在 LinkedInYoutube 找到我。

还有,看看我其他关于人工智能和机器学习的帖子。

如何使用堆栈解决 Python 编码问题

原文:https://towardsdatascience.com/how-to-solve-python-coding-questions-using-stack-94571f31af3f?source=collection_archive---------4-----------------------

破解数据科学面试

2021 年数据科学家和软件工程师的基本数据类型

萨姆拉特·卡德卡在 Unsplash 上拍摄的照片

Python 是一种通用的基于脚本的编程语言,在人工智能、机器学习、深度学习和软件工程中有着广泛的应用。它的流行得益于 Python 存储的各种数据类型。

如果我们必须存储键和值对,字典是自然的选择,就像今天的问题 5。字符串列表是一对孪生姐妹,她们走到一起解决字符串操作问题。集合具有独特的位置,因为它不允许重复,这是一个独特的功能,允许我们识别重复和非重复项目。嗯,tuple 是技术面试中最少被问到的数据类型。上周,一位资深数据科学家在 Twitter 上发布了一个编码问题,可以通过 tuple 轻松解决。然而,很多候选人都被绊倒了。我很快会就这个话题再写一篇文章。

数据类型在 Python 编程中起着重要的作用!能够区分彼此对于解决面试问题非常重要。在今天的文章中,让我们转到另一个基本的数据类型,叫做堆栈。

在撰写这篇博文时,我花了无数个小时来选择以下问题,并以一种新程序员容易理解的方式对它们进行排序。每个问题都建立在前一个问题的基础上。如果可能的话,请按顺序解决问题。

叠起来

堆栈是一种线性数据结构,以后进/先出(LIFO)或先入/后出(FILO)的方式(GeeksForGeeks)保存元素。这意味着最后添加的元素将首先从堆栈中弹出。我们可以想象一堆盘子:我们总是使用最上面的那个盘子,这个盘子是最后加到盘子堆里的。Push 和 pop 是栈中最基本的操作,为其他更高级的采用奠定了基础。

瑞安·斯通在 Unsplash 上的照片

在 Python 中,有三种实现堆栈的方法:使用列表、collections.deque 和链表。为了准备数据科学面试,第一种方法已经足够好了。如果你对另外两个感兴趣,请查看这个帖子(链接)。

在 Python 中,我们可以简单地用一个列表来表示一个栈。因此,它具有与列表相同的属性。它有两个基本操作:push()和 pop()。为了将一个元素推入或者添加到堆栈中,我们使用 append()方法。要弹出或删除最后一个元素,我们使用 pop()方法,如下所示。

stack = []          # create an empty stack
stack.append(‘a’)   # push 'a' to the stack
stack.append(‘b’)   # push 'b' to the stack
stack.append(‘c’)   # push 'c' to the stackprint(stack)
['a', 'b', 'c']stack.pop()         #pop the last element
'c'stack.pop()        #pop the last element
'b'stack.pop()        #pop the last element
'a'stack              #check the remaining stack
[]

问题 1:删除所有相邻的重复字符串,由脸书,亚马逊,彭博,甲骨文

-给定小写字母的字符串 S,重复删除包括选择两个相邻且相等的字母,并删除它们。
-我们在 S 上重复删除重复,直到我们不能再这样做。
-在所有此类重复删除完成后,返回最终字符串。保证答案是唯一的。
-https://leet code . com/problems/remove-all-adjacent-duplicates-in-string/

走过我的思考

脸书、亚马逊、彭博和甲骨文都包含了这个问题。在看问题提示的时候,我发现以下几个关键词值得注意:去重,两个相邻相等,去重简单来说,这个问题翻译过来就是去掉相邻的等号字母。翻译过程对于简化问题至关重要,因为很多时候,提示包含太多琐碎的信息,分散了我们解决问题的注意力。此外,确定关键点并大声说出来,让面试官参与进来。

要检查两个字母是否相等,我首先想到的是采用野蛮的力量,在两个连续的位置检查相同的元素。但是,这种方法不起作用,因为移除过程是动态的。

假设测试用例是' 阿巴卡 '如果使用野蛮的力量,我们将只能删除' bb '字符串而不是删除' aa '后创建的' bb . '

我们需要一个动态的解决方案来检查新创建的连续位置是否有相同的元素。

还好宇宙提供了 stack!

我们可以创建一个空栈(列表)来存储新元素。如果元素等于堆栈中的最后一个元素,我们就把它从堆栈中弹出来,不把新元素添加到列表中。换句话说,简单的 pop 操作删除了两个相邻的相同字母。相当整洁!最后,我们将列表重新加入到一个空字符串中,这是一种常见的转换策略。

解决办法

'ca'

作为热身,我故意选择这个简单的问题。下面的问题看起来有点挑战性,但是按照同样的过程完全可以解决。

#问题 2:让字符串变得伟大,谷歌

-给定一串 s 个小写和大写英文字母。
-好的字符串是没有两个相邻字符 s[i]和 s[i + 1]的字符串,其中:0<= I<= s . length-2
-s[I]是小写字母,s[i + 1]是大写字母,反之亦然。
-为了使字符串变好,你可以选择两个使字符串变坏的相邻字符,并删除它们。你可以一直这样做,直到弦变好。
-修复后返回字符串。在给定的约束条件下,答案保证是唯一的。注意空字符串也是好的。【https://leetcode.com/problems/make-the-string-great/】-

走过我的思考

谷歌问了这个问题。让我们再次扫描提示并检索关键信息。下面是吸引眼球的关键词:两个相邻的字符,一个小写,一个大写(反之亦然),去掉两个相邻的不同大小写的字符简单来说,问题是想让我们去掉两个相邻的不同大小写的字符(一个上一个下,不分位置)。

记住说出你的想法,让你的面试官知道你已经抓住了关键信息。如果你没有,你的面试官会问你为什么决定采用 stack 而不是其他数据类型。

按照与问题 1 相同的逻辑,我们创建一个空堆栈来存储元素,并检查要添加的字母是否相同,但大小写不同。在 Python 中,有不同的检查案例的方法。如果你和我一样,不知道任何内置的方法/函数,我们可以按照以下步骤:首先确定这两个字母不相同( stack[-1]!= i )其次,在使用较低的方法(堆栈[-1])后,它们变得相同。lower() ==i.lower() )。

这是一个难题。我们不能从空堆栈中弹出一个元素。它会产生索引错误。像下面这样:

IndexError

为了避免错误消息,我们必须使用第 4 行中的堆栈 if 来确保堆栈不为空。这是 Python 程序员在使用堆栈时最常犯的错误之一。

解决方案 1

'leetcode'

解决方案 2

事实证明,Python 有一个内置的方法 swapcase(),它将字母从大写转换成小写,反之亦然。此外,你可能想和面试官确认一下你是否可以使用任何内置的方法。继续沟通!

'leetcode'

#问题 3:使用堆栈操作构建数组,Google

-给定一个数组目标和一个整数 n .在每次迭代中,你将从 list = {1,2,3…,n}中读取一个数。
-使用以下操作构建目标数组:
-Push:从开始列表中读取一个新元素,并将其推入数组中。
— Pop:删除数组的最后一个元素。
—如果目标数组已经建立,停止读取更多的元素。
-返回构建目标数组的操作。向您保证答案是唯一的。
-https://leet code . com/problems/build-an-array-with-stack-operations/

走过我的思考

谷歌问了这个问题。这个问题好人性化,明确告诉你推送和弹出元素。一叠就好了!

创建一个空堆栈并遍历列表:将元素推送到新堆栈,弹出最后一个元素。最后,检查构造的数组是否与目标数组相同。如果是,停止迭代。

唯一的问题是,如果我们已经获得了目标数组,就要中断 for 循环。为此,保持 stack==target (第 16 行& 17)的缩进块与 if-else 语句一致。面试官可能会问一些后续问题,比如为什么你把缩进放在 for 循环内部而不是外部。

解决办法

['Push', 'Push', 'Pop', 'Push']

#问题 4:棒球比赛,亚马逊出品

-你在用奇怪的规则为一场棒球比赛记分。游戏由几轮组成,过去几轮的分数可能会影响未来几轮的分数。游戏开始时,你从一个空记录开始。您将得到一个字符串列表 ops,其中 ops[i]是您必须应用于记录的第 I 个操作,并且是下列操作之一:
-整数 x-记录 x 的新得分。
-“+”-记录前两个得分之和的新得分。保证总会有两个先前的分数。
—“D”——记录一个新的分数,该分数是之前分数的两倍。保证总会有以前的分数。
——“C”——使之前的分数无效,将其从记录中删除。可以保证总会有一个先前的分数
-返回记录上所有分数的总和。
-https://leetcode.com/problems/baseball-game/

走过我的思考

亚马逊挑了这个问题。这是另一个对受访者友好的问题,因为它告诉你推动和弹出元素。此外,我们需要使用包含多个 if 语句的控制流。构建堆栈和添加/移除元素的过程与上述问题相同。在这里,我重点介绍一下这个问题需要特别注意的独特属性。

通常,在弹出元素之前,我们必须检查堆栈是否为空,如问题 2 所示。但是,我们不必检查这个问题,因为提示告诉我们总会有一个以前的分数。如果没有额外的条件,这个问题会变得有点混乱。最后,我们使用 sum()函数返回所有分数的总和。

问题解决了!

解决办法

30

#问题 5:亚马逊和彭博的《下一个更伟大的元素 I》

-给定两个整数数组 nums1 和 nums2,它们都是唯一的元素,其中 nums1 是 nums2 的子集。
-在 nums2 的相应位置找到 nums1 元素的所有下一个更大的数字。
-nums 1 中数字 x 的下一个更大的数字是 nums2 中其右侧的第一个更大的数字。如果不存在,则返回-1。
-https://leetcode.com/problems/next-greater-element-i/

走过我的思考

亚马逊和 Blooomberg 挑了这个问题。问题 5 需要不止两步的解决方案。但首先,吸引眼球的关键词包括: nums1 是 nums2 的子集,在 nums2 中为 nums1 寻找下一个更大的数字,为 none 返回-1

在我看来,翻译过程是这样的:

#1 subset → elements in nums1 should also be in nums2\. #2 find the next greater numbers → positions matter and value matters! # 3 return -1 if such value does not exist → Use if-else statement as a control flow.

总之,我们必须找到一种方法来识别元素的位置和值,并使用 if-else 语句来比较值。

要找到元素的位置和值,自然的选择是使用 enumerate()函数。此外,我们希望使用字典来保存键值对的记录。

接下来,我们遍历数组 nums2,找到下一个更大的条目。如果有这样一项,我们打破 for 循环;否则,返回-1。完整的代码在解决方案 1 中。

解决方案 1

这种方法很直观,也很容易遵循。

 [-1, 3, -1]

解决方案 2

声明:解决方案 2 不是我的原代码,特别鸣谢去aditya baurai 帖子

事实证明,我们可以采用堆栈和字典。首先,我们创建一个空堆栈/字典,并迭代 nums2:

#1 if the stack is not empty and the last stack element is smaller than num: we pop the stack and create a key-value pair in the dictionary.#2 for other cases, we append the element to the stack.

为了澄清,for 循环迭代 nums2 中的所有元素,而 while 循环是为了找到 nums2 中与堆栈相比下一个更大的元素。为了更好地帮助我们理解,我们可以循环 nums2 的前两个元素。

# pseudo code
# nums2: [1,3,4,2]# step 1: # when the first element num == 1
for num in nums2: 
    stack.append(num) # since the stack is empty# step 2: for the second element num ==3
for num in nums2: # since the stack isn't empty
    while stack and stack[-1] <num:
        anum = stack.pop() # pop out the last element 1 # create a key-value pair: 1 is the key and 3 is the value
        and[anum] = num

简而言之,上面的代码找到了 nums2 中所有较大的元素,最后我们找到了 nums1 中元素的相应值。

[-1, 3, -1]

我的Github上有完整的 Python 代码。

外卖食品

  • 堆栈有两个操作:push()和 pop()。
  • 确定关键词,与面试官交流。
  • Stack 经常使用以下关键字进行组合:两个连续的相同字母/数字/单词,如果某个元素与之前的位置有某种关系,则推送并弹出该元素。
  • 弹出前检查是否为空堆栈。
  • 缩进对于循环来说至关重要。很好的理解问题,决定它的位置(循环内还是循环外)。
  • 复杂的编码问题可以分解成多个更小的部分。

Medium 最近进化出了它的 作家伙伴计划 ,支持像我这样的普通作家。如果你还不是订户,通过下面的链接注册,我会收到一部分会员费。

https://leihua-ye.medium.com/membership

我的数据科学面试序列

</5-python-coding-questions-asked-at-faang-59e6cf5ba2a0>

喜欢读这本书吗?

请在 LinkedInYoutube 上找到我。

还有,看看我其他关于人工智能和机器学习的帖子。

联邦数据来源:高等教育数据

原文:https://towardsdatascience.com/how-to-source-federal-data-higher-education-data-675f5edb9813?source=collection_archive---------56-----------------------

来源:作者根据本文的代码收集和汇编的综合中学后教育数据(IPEDS)的再现。摘录的观点。

从联邦高等教育数据源构建三年数据面板的分步指南

TLDR:本指南利用美国教育部的公开数据,整合了一个为期三年的数据面板(也称为纵向数据)。使用本文中的技术来准备您可以自己分析的数据。请在评论中告诉我,接下来我应该为哪些其他联邦数据源构建类似的指南。

介绍

你是下列任何一种人吗?

  • 为一个需要了解美国高等教育机构的客户工作?
  • 想研究高等教育机构的研究员(研究生,大学教师)?
  • 正在寻找新数据进行探索的现任或有抱负的数据专业人士?

本文提供了 Python 代码,它将从美国教育部下载三年的数据(IPEDS 数据,下面会进一步解释)。本文还解释了这些代码。

首先,本文描述了系统和软件需求。然后,第二,本文概述了代码的五个步骤:

  1. 导入包
  2. 获取数据
  3. 清理数据
  4. 保存数据
  5. 面板组件

本文末尾有一个链接,指向在 Jupyter 笔记本中提供这些代码的存储库。

系统和软件要求

只要您使用的是 Python 3.0,这段代码就可以在 Mac、Windows 和 Linux 上运行。这段代码也适用于 Stata 的 Python API 环境。如果您知道您有一个 Python 环境,请跳过这个需求部分,转到下面的实现部分。

为了自己实现这段代码,您需要访问 Python 编程环境。如果您的计算机上还没有安装 Python,我推荐使用 Anaconda 发行版,它是免费的,并且被许多人认为是数据科学工作的首选。我以前写过如何安装这个软件。如果你喜欢视频,我有一个主题为的视频。

另一个不需要安装软件的选择是使用这个免费的在线 Jupyter 笔记本环境。

履行

第一步导入包并指定数据位置。在这一步中,我们还设置了一些参数。

import requests
import zipfile
import io
import pandas as pd# We use the ipeds prefix because the data comes from the:
# [I]ntegrated [P]ostsecondary [E]ducation [D]ata [S]ystem
ipeds_locs = '[https://nces.ed.gov/ipeds/datacenter/data/'](https://nces.ed.gov/ipeds/datacenter/data/')
ipeds_fils = 'HD{}_Data_Stata.zip'
ipeds_dict = 'HD{}_Dict.zip'
years = [2015,2016,2017]

ipeds_locs中,我们指定数据位置。我们使用ipeds_fils来指定 zip 文件名,使用ipeds_dict来指定数据字典文件名。在years中,我们指定我们想要的结果面板数据的年份。

我们使用ipeds前缀是因为这些数据来自综合系统(IPEDS)。我以前写过这些数据。

第二步是开始一个 for 循环,该循环将遍历years中的值以获得数据。数据源以压缩的 zip 文件格式共享这些数据。并且每年有一个文件。在这一步中,代码下载保存在线数据的 zip 文件。

for yr in years:
    print('GETTING FILES FROM {}'.format(yr))
    rdata = requests.get(ipeds_locs + ipeds_fils.format(yr))
    rdict = requests.get(ipeds_locs + ipeds_dict.format(yr))
    rdata_zip = zipfile.ZipFile(io.BytesIO(rdata.content))
    rdict_zip = zipfile.ZipFile(io.BytesIO(rdict.content))

    print('Extracting {} files from zip archive:'.format(yr))
    rdata_zip.printdir()
    rdict_zip.printdir()
    rdata_zip.extractall()
    rdict_zip.extractall()

    print('Saving zip archive to disk.')
    open(ipeds_fils.format(yr), 'wb').write(rdata.content)
    open(ipeds_dict.format(yr), 'wb').write(rdict.content)

print()语句在遍历各个步骤时提供输出。输出有助于跟踪您的进度。如果你把结果保存在你的笔记中,它将帮助你复制你的工作。

这段代码然后使用requests.get()从在线下载 zip 文件,这是我们在第一步中导入的标准库之一。数据进入名为rdata的变量,而数据字典进入rdict

下一个目标是提取文件,并将它们保存到磁盘上。为了实现这个目标,我们使用了zipfile.ZipFile()io.BytesIO()extractall()

我们还有一个目标是提供更多的输出(用于跟踪和复制目的)。为了提供额外输出,我们使用了printdir()

最终,open()函数和write()方法将文件保存到磁盘。

在第二步中的代码运行后,您将有四个新文件用于每年。这些文件现在将位于您的本地计算机上。这是您将找到的文件的图像。

来源:作者对本文代码收集的文件的翻译。(图 1)

如图 1 所示,在 for 循环中,每年都会有 2 个新的 zip 文件、1 个新的 MS Excel 文件和 1 个新的 CSV 文件。名称为hdyyyy.xlsx的文件是 IPEDS 提供的数据字典文件。带hdyyyy_data_stata.csv的文件是 CSV 格式的数据。扩展名为.zip的文件是代码从网上下载的 zip 文件。上图还显示了 pickle 文件,它是主数据的辅助备份,在代码的后面生成。

第三步清除数据。这个数据已经清理得很好了,但还不完美。这种数据的一个难以处理的方面是它具有代码值而不是代码标签。如下所述,用代码值替换代码标签将使这些数据更易于阅读。

关于“代码值”和“代码标签”的简短讨论:许多人经常用其他术语来指代这两个概念。对于本文,代码值和代码标签指的是分类变量。

正如所提供的,这些数据使用分类变量的代码值。代码值是映射到代码值的简单数字。例如,下图中有两个数据集。左边是原始数据。右边是更新的数据。原始数据有一个数字来代替每个类别。这些数字是代码值。代码值映射到代码标签。

# SIMPLIFIED ILLUSTRATION OF CODE VALUES vs. CODE LABELSORIGINAL DATA:             UPDATED DATA:
+------+-------+------+    +-------+-------+------+
| size | state | type |    | size  | state | type |
+------+-------+------+    +-------+-------+------+
|  1   |  33   |  4   |    | small | Wisc. | 1yr  |
|  1   |  21   |  5   |    | small | Fla.  | 4yr  |
|  2   |  21   |  3   |    | med   | Fla.  | 2yr  |
|  3   |  40   |  3   |    | big   | N.Y.  | 2yr  |
+------+-------+------+    +-------+-------+------+

代码值不利于人的可读性。为了使数据更易于阅读,我们将用代码标签替换那些代码值。

更新的数据更容易读取,因为更新的数据具有人类可读的代码标签,而不是数字代码值。因此,第三步的最后一部分,如下所示,用代码标签替换代码值。

print('Replacing Code Values with Code Labels.')

# Extract frequencies tab the data dictionary (hdYYYY.xlsx)
freqs = pd.read_excel('hd{}.xlsx'.format(yr),
                      sheet_name='Frequencies')# Put institutional data into a data frame (df)
df = pd.read_csv('hd{}_data_stata.csv'.format(yr), 
                 encoding='ISO-8859-1')    

# Get list of categorical variable names
cat_colms = set(freqs['varname'])

# Remove fips code to prevent its modification
cat_colms.remove('FIPS')

在变量freqs中,我们存储来自数据字典(hdYYYY.xlsx)的元数据。上面的第二步下载并解压缩了这个数据字典。图 1 & 2 也显示了这些数据字典文件。变量名freqs是数据来源的电子表格选项卡“频率”的缩写。

在变量df中,我们存储了之前在第二步中下载的机构数据。在 Pandas 中工作时,习惯上使用df作为主数据框的变量名。

cat_colms中,我们存储了分类变量名称的列表。为了获得分类变量的简单列表,这段代码使用了数据字典中的“frequencies”选项卡。

因为该数据既有州 FIPS 代码的列,也有州名的文本列。FIPS 电码的意义和目的超出了本文的范围。简而言之,它们是州、县和其他政治地理的标准代码。我们将保留 FIPS 代码,因为如果我们想通过将它与其他州数据源合并来扩充该数据,它们会很有用。

因为保留州缩写和州 FIPS 代码都很有用,所以我们使用cat_colms.remove('FIPS')从代码将改变的分类列列表中删除该列。

第三步的最后一部分是清理数据,即进一步利用数据字典来创建可以用代码标注替换代码值的地图。映射是一种交叉遍历,Python 可以用一组代码替换另一组代码。这个映射操作是一个循环,因为每一列都需要一个单独的映射。

# Loop through categorical columns
for col in cat_colms:
    # Get map keys (code values)
    code_values = freqs[freqs['varname'] == col]['codevalue']
    # Convert map keys to int where appropriate
    code_values = [int(i) if str(i).isdigit() 
                   else i for i in code_values]
    # Get map value (ValueLabels)
    code_labels = freqs[freqs['varname'] == col]['valuelabel']
    var_map = dict(zip(code_values, code_labels)) 
    # Apply mapping dictionary to categorical column
    df[col] = df[col].map(var_map)

第四步是创建时间索引,然后保存数据以备后用。回头看,这段代码在第三步中创建了变量df。第三步还操作了df中的分类列,用代码标签替换了代码值。

这里,在第四步中,我们进一步操作df。行df['year'] = yr在数据帧中创建一个新列,该列等于yr的当前值,该值在 for 循环的每个周期递增。使用to_csv()to_pickle()方法,这段代码将数据保存在 csv 和 pickle 中(作为本地计算机上的文件)。

# Create time index for panel specification
df['year'] = yr

print('Writing hd{}_data_stata.csv as csv, pkl'.format(yr))
df.columns = [i.lower() for i in df.columns]
df.to_csv('hd{}_data_stata.csv'.format(yr))
df.to_pickle('hd{}_data_stata.pkl'.format(yr))
print('Done!', end='\n\n')

以 CSV 和 pickle 格式将文件保存到磁盘在技术上是不必要的,实际上也是不必要的。我经常以两种格式保存,因为我喜欢防止数据丢失的冗余。当希望确认或复制结果时,拥有数据的冗余副本还可以提供额外的参考点。数据工程师讨厌这样,因为这样效率不高。所以你可以决定你喜欢哪种格式。Pandas 文档还提供了可以编写至少十几种其他格式的函数。

在第四步之后,您将拥有一个工作目录,其中包含一些额外的文件,如图 2 所示。

来源:作者对本文代码收集的文件的翻译。(图 2)

第二步到第四步(导入包、获取数据、清理数据和保存数据)将循环遍历变量years中的每个值,然后继续第五步。

第五步组装面板。下面的代码从第一步到第四步准备的 CSV 文件中收集数据,如图 2 所示。

回想一下,面板数据通常与纵向数据同义。这种数据包括随时间重复的多个单元的观察结果。在这篇文章的代码收集的数据中,每个高等教育机构有三个观察值,从 2015 年到 2017 年每年一个。

all_data = {}
for yr in years:
    all_data[yr] = pd.read_csv('hd{}_data_stata.csv'.format(yr))

df = pd.concat(all_data).sort_values(['unitid',
                                      'year']).set_index(['unitid',
                                                          'year'])

将数据放入单个面板首先要声明一个all_data字典。然后,在通过years变量进行循环时,代码在all_data字典中为每年放置一个数据框。

在第五步中,代码重用了df变量。在这个过程中,我们有效地抛弃了以前的df实例。

pd.concat()函数以及sort_values()set_index()方法(如上所示)的帮助下,结果是一个看起来像图 3 中摘录的数据帧。

图像来源:作者实现文章代码的输出。摘录的综合中学后教育数据系统(IPEDS)数据。(图 3)

改进空间和后续步骤

其他年份

如果您在自己的项目中实现了这段代码,那么明智的做法是从第一步开始修改years = [2015,2016,2017],以包含更多年份的数据。当格式有时发生变化时,添加额外年份的数据会变得很棘手。一定要检查和复查结果。

重构

构建和改进这些代码的另一种方法是定义一个(或多个)函数,使代码更容易维护、阅读、记录和更新。例如,第三步中的 For 循环作为一个函数可能会更好。

这段代码的其他部分作为一个函数会运行得更好。我没有列出所有需要改进的地方,而是邀请其他人在评论中提出建议。

增大

增强包括将该数据与其他数据源合并的选项。例如,文章提到使用 FIPS 代码(它提供唯一的州标识号)将这些数据与其他数据源合并。

改进此代码的另一种方法是用其他数据文件补充数据,这些数据文件也可以从美国教育部国家教育统计中心、其他联邦机构或私人数据源获得。

如果您的分析问题、目的或动机可能需要将这些数据与其他数据源合并,请考虑使用pd.merge()进行合并。

支持 Jupyter 笔记本

为了看到准备运行格式的代码,我准备了这个 Jupyter 笔记本。有时候 Jupyter 笔记本在 GitHub 上渲染不好。如果笔记本没有为你渲染,这里有一个版本在降价

结论

本文通过五个步骤展示了其他人可以用来从网上收集数据的代码。这五个步骤是 1)导入包,2)获取数据,3)清理数据,4)保存数据,以及 5)组装面板。

本文的代码从美国教育部收集美国联邦教育数据。其他数据科学家、研究人员和分析师可以将这些代码用作食谱。

如果你在你的项目中使用这些代码,请告诉我。如果您需要故障排除帮助,请告诉我。我很容易通过下面列出的信息联系。

从某些角度来看,这个项目是关于网络抓取的。从网上抓取数据有多种形式。这个例子包括访问已经是结构化格式的数据。本例中收集的数据也几乎可以用于分析。

如果你想知道在探索过程中你会在这些数据中发现什么,那就去检查一个特定的机构。图 4 中的输出显示了来自威斯康星大学麦迪逊分校的信息。该输出显示了 Rebecca Blank 作为校长、该机构的一般电话号码、邮政编码、州、街道地址和该机构的国会选区。

图片来源:作者对本文代码输出的再现。

图 5 中显示的是我从 IPEDS 数据中准备的一个视觉图,它显示了随着时间的推移在两个不同机构注册的男性和女性的平衡。

图片来源:作者对 IPEDS 数据的可视化。两个机构对比的例子。该图显示,每个校区的男女比例似乎向相反的方向漂移。y 轴上的刻度显示,每个校区性别平衡的总体变化为+/-3%。

https://adamrossnelson.medium.com/membership

感谢阅读

如果你喜欢我要说的话,可以在 adamrossnelson.medium.com找到更多。

感谢阅读。把你的想法和主意发给我。你可以写信只是为了说声嗨。如果你真的需要告诉我是怎么错的,我期待着尽快和你聊天。推特:@ adamrossnelson| LinkedIn:亚当·罗斯·纳尔逊 |脸书:亚当·罗斯·纳尔逊

如何用摩丁加速熊猫

原文:https://towardsdatascience.com/how-to-speed-up-pandas-with-modin-84aa6a87bcdb?source=collection_archive---------2-----------------------

Modin 的一个目标是允许数据科学家对小数据集(千字节)和大数据集(兆兆字节)使用相同的代码。图片由德文·彼得森提供。

pandas 库提供了像 pandas DataFrames 这样易于使用的数据结构以及数据分析工具。熊猫的一个问题是它处理大量数据会很慢。它不是为分析 100 GB 或 1 TB 数据集而设计的。幸运的是,有一个摩丁库,它有一些好处,比如能够通过改变一行代码来扩展你的熊猫工作流,并与 Python 生态系统和 Ray 集群集成。本教程讲述了如何开始使用 Modin,以及它如何加快你的熊猫工作流程。

如何入门摩丁

为了确定首先在 Modin 中实现哪些 Pandas 方法,Modin 的开发人员收集了 1800 个投票最多的 Python Kaggle 内核(代码)。图片由德文·彼得森提供。

Modin 对 pandas API 的覆盖率超过 90%,重点是最常用的 pandas 方法,如 pd.read_csv、pd。DataFrame、df.fillna 和 df.groupby。这意味着如果您有大量数据,您可以更快地执行大多数与 pandas 库相同的操作。本节重点介绍一些常用的操作。

要开始使用,您需要安装 modin。

pip install “modin[all]” # Install Modin dependencies and modin’s execution engines

安装 pip 时,不要忘记""迈克尔·加拉尼克拍摄的图片。

进口摩丁

Modin 的一个主要优点是它不需要你学习一个新的 API。您只需要更改您的导入语句。

import modin.pandas as pd

你只需要修改你的 import 语句来使用 Modin(图片由 Michael Galarnyk 提供)。

加载数据(read_csv)

摩丁确实在大型数据集上大放异彩。图片由德文·彼得森提供。

本教程中使用的数据集来自大约 2GB 的健康保险市场数据集。下面的代码将数据读入一个 Modin 数据帧。

modin_df = pd.read_csv("Rate.csv”)

在这种情况下,Modin 速度更快,因为它将工作从主线程转移到异步线程。文件是并行读取的。改进的很大一部分来自于异步构建 DataFrame 组件(图片由 Michael Galarnyk 提供)。

下面的代码使用了 head 命令。

# Select top N number of records (default = 5)
modin_df.head()

在这种情况下,Modin 较慢,因为它需要一起收集数据。然而,用户应该无法在他们的交互工作流程中察觉到这种差异。

分组依据

和熊猫类似,摩丁也有 groupby 操作。

df.groupby(['StateCode’]).count()

迈克尔·加拉尼克的图片。

请注意,有计划要进一步优化 Modin 中 groupby 操作的性能。

菲尔娜

使用 fillna 方法填充缺失值可以比使用 Modin 快得多。

modin_df.fillna({‘IndividualTobaccoRate’: ‘Unknown’})

迈克尔·加拉尼克拍摄的图片。

默认为 pandas 实现

如前所述,摩丁的 API 覆盖了熊猫 API 的 90%左右。对于尚未涉及的方法,Modin 将默认使用 pandas 实现,如下面的代码所示。

modin_df.corr(method = ‘kendall’)

当摩丁默认为熊猫时,你会看到一个警告。迈克尔·加拉尼克的图片。

尽管默认为 pandas 会有性能损失,但无论该命令当前是否在 Modin 中实现,Modin 都将完成所有操作。

如果一个方法没有实现,它将默认为 pandas(图片由 Devin Petersohn 提供)。

摩丁的文档解释了这个过程是如何运作的。

我们首先转换成熊猫数据帧,然后执行操作。由于 panda 的通信成本和单线程性质,从分区的 Modin 数据帧到 panda 会有性能损失。一旦 pandas 操作完成,我们就将数据帧转换回分区的 Modin 数据帧。这样,在默认为熊猫之后执行的操作将通过 Modin 进行优化。

摩丁如何加快你的熊猫工作流程

modin 使 pandas 工作流程更快的三个主要方法是通过它的多核/多节点支持、系统架构和易用性。

多核/多节点支持

熊猫只能利用单核。摩丁能够有效地利用所有可用的硬件。该图显示了 Modin 可以利用的资源(深蓝色),具有多个核心(B)和多个可用节点(C)。迈克尔·加拉尼克的图片。

熊猫图书馆只能使用一个核心。由于今天几乎所有的计算机都有多个内核,通过让 modin 利用计算机上的所有内核,有很多机会来加速您的 pandas 工作流。

出于这篇博客的目的,你可以把上面的 MacBook 想象成一个 4 核的单节点。图像由迈克尔·加拉尼克拍摄。

如果你想将你的代码扩展到 1 个以上的节点, Modin 有一个 API,可以在本地和云提供商/集群上切换运行代码

系统结构

另一个让摩丁比熊猫更快的原因是熊猫本身是如何实现的。熊猫的创造者韦斯·麦金尼做了一个著名的演讲“我讨厌熊猫的 10 件事”,他谈到了一些熊猫缺乏灵活性和表现问题。

韦斯·麦金尼的一些熊猫问题与表演有关(来自 PyData 2013 的幻灯片)。

摩丁试图解决其中的一些问题。要理解这一点,重要的是要理解它的一些系统架构。下图概述了 Modin 组件的一般分层视图,并对每个主要部分进行了简短描述。

摩丁的系统架构(图片由德文·彼得森提供)。

API 层:这是面向用户的层,主要是 Modin 对 pandas API 的覆盖。SQLite API 是实验性的,而 Modin API 仍在设计中。

摩丁查询编译器:除了它的其他职责之外,查询编译器层严格遵循 pandas API,但是去掉了大部分的重复。

摩丁数据帧层:这是摩丁优化数据帧代数发生的地方。

执行:虽然 Modin 也支持其他执行引擎,如 Dask,但最常用的执行引擎是 Ray ,您可以在下一节中了解到。

雷是什么

Ray 让并行和分布式处理工作更像你所希望的那样( image source )。

Ray 是 Modin 的默认执行引擎。本节简要介绍了什么是 Ray,以及它如何不仅仅被用作执行引擎。

迈克尔·加拉尼克的图片。

上图显示,在高层次上,Ray 生态系统由核心 Ray 系统和用于数据科学的可扩展库组成,如 Modin 。这是一个用于在多个内核或机器上扩展 Python 应用的库。它有几个主要优点,包括:

  • 简单性:无需重写就可以扩展 Python 应用程序,相同的代码可以在一台或多台机器上运行。
  • 健壮性:应用程序优雅地处理机器故障和抢占。
  • 性能:任务以毫秒级延迟运行,扩展到数万个内核,并以最小的序列化开销处理数字数据。

因为 Ray 是一个通用框架,所以社区在它的基础上构建了许多库和框架来完成不同的任务,如用于任何规模的超参数调整的 Ray Tune 、用于易于使用的可扩展模型服务的 Ray Serve 以及用于强化学习的 RLlib 。它还集成了 scikit-learn 等机器学习库以及对 PySpark 和 Dask 等数据处理库的支持。

虽然您不需要学习如何使用 Ray 来使用 Modin,但下图显示,通常只需要添加几行代码,就可以将一个简单的 Python 程序变成一个跨计算集群运行的分布式程序。

如何用 Ray 把一个简单的程序变成分布式的例子(代码解释)。迈克尔·加拉尼克拍摄的图片。

结论

Modin 的一个目标是允许数据科学家对小数据集(千字节)和大数据集(兆兆字节)使用相同的代码。图片来自德文·彼得森

Modin 允许您对笔记本电脑上的 10KB 数据集和集群上的 10TB 数据集使用相同的 Pandas 脚本。由于 Modin 易于使用的 API 和系统架构,这是可能的。这种架构可以利用 Ray 作为执行引擎,使扩展 Modin 变得更加容易。如果您对 Ray 有任何问题或想法,请随时通过 DiscourseSlack 加入我们的社区。你也可以查看射线峰会页面,看看射线是如何在整个行业中使用的!

最初发表于【https://www.anyscale.com】

如何将 Python 数据管道加速到 91X?

原文:https://towardsdatascience.com/how-to-speed-up-python-data-pipelines-up-to-91x-80d7accfe7ec?source=collection_archive---------8-----------------------

一个 5 分钟的教程可以为您的大数据项目节省数月时间。

照片由 Vicky YuUnsplash 上拍摄

作为一名数据科学家,令人沮丧的事情是等待大数据管道完工。

尽管 python 是数据科学家的浪漫语言,但它不是最快的。这种脚本语言在执行时被解释,使得它很慢,并行执行很困难。可悲的是,并不是每个数据科学家都是 C++专家。

如果有一种并行执行,以编译代码的速度运行 python 代码的方法会怎样?这就是 Tuplex 正在解决的问题。

Tuplex 是用 Python 编写的并行大数据处理框架。如果您曾经在 Apache Spark 中工作过,这可能对您来说很熟悉。然而,与 spark 不同,Tuplex 不调用 Python 解释器。它优化管道并将其转换为 LLVM 字节码,以极快的速度运行,与手工优化的 C++代码一样快。

Python 使用多重处理库来并行执行。这个库的缺点是它不能在任何 REPL 环境下工作。然而,我们数据科学家喜欢 Jupyter 笔记本。在幕后,多重处理甚至不是一种并行执行技术。它只启动多个子进程,操作系统负责它的并行执行。事实上,不能保证操作系统会并行运行它们。

在本文中,我们将讨论:

  • 如何安装 Tuplex
  • 如何运行琐碎的数据管道;
  • Tuplex 中便捷的异常处理:
  • 高级配置如何帮助您,以及;
  • 将它与普通的 python 代码进行对比。

我确信这将是一次公园散步。

启动并运行 Tuplex。

尽管它很有用,但 Tuplex 的设置非常简单。PyPI 做到了。

pip install tuplex

虽然在 Linux 上推荐使用这种方法,但是在 Mac 上可能必须使用 docker 容器。

这里有一点需要注意的是,它还没有在 Windows 电脑上测试过。至少 Tuplex 的文档没有提到。请分享你的 Windows 电脑体验。

你的第一条数据管道。

一旦安装了 Tuplex,运行并行任务就很容易了。这是来自 Tuplex 官方文档页面的例子。

来自 Tuplex 文档的片段。

首先,您必须创建一个复合上下文。您可以通过从 Tuplex 模块导入它来做到这一点。

从这里开始,运行并行函数执行只需要三个步骤;并行化、映射和收集。

Tuplex 上下文对象的并行化方法是您的起点。它将输入值列表作为参数传递给函数。该列表中的每个元素都将通过函数与其他元素并行运行。

您可以传递一个用户定义的函数,该函数使用 map 函数转换每个输入。最后,使用 collect 方法收集所有并行执行的输出。

Tuplex 中方便的异常处理。

我最喜欢 Tuplex 的一点是它在管理异常方面的便利性。数据管道中的错误处理是一种令人畏惧的体验。想象一下,花几个小时处理一个数据流,却发现一个被零除的细微错误扼杀了你所做的一切。

来自 Tuplex 文档的片段。

上面的代码会产生一个被零除的错误。如果您使用 spark 或任何标准 python 模块来处理这个问题,至少情况是这样的。

在 Tuplex 中,错误处理是自动的。它会忽略有错误的那个并返回其余的。上面的代码将返回[2,-4],因为列表中的第一个和第三个输入无法执行。

但是,忽略错误有时是有问题的。通常你必须以不同的方式处理它们,而 Tuplex 的 API 足够灵活,可以做到这一点。事实上,Tuplex 方法很方便。

来自 Tuplex 文档的片段。

Tuplex 使错误处理变得毫不费力。您必须在“map”和“collect”方法之间链接一个“resolve”方法。在上面的例子中,我们已经传入了 ZeroDivisionError 类型,并通过替换零来处理它。

resolve 方法的第二个参数是一个函数。有了这个函数,您可以告诉 Tuplex 在出现这种类型的错误时应该做什么。

为高级用例配置 Tuplex。

您可以用两种方式配置 Tuplex。第一种是直截了当的解决方案;只需将字典传递给上下文初始化。下面是一个将执行内存设置为较高值的示例。

来自 Tuplex 文档的片段。

Tuplex 还支持在 YAML 文件中传递配置。在生产环境中,您可能必须将配置存储在文件中。YAML 文件是处理不同配置并在开发和测试团队之间传递的一种很好的方式。

来自 Tuplex 文档的片段。

下面是一个配置文件的例子,它包含了您可以从 Tuplex 文档中进行的所有不同的定制。

来自 Tuplex 文档的片段。

性能基准

Tuplex 的承诺耐人寻味。是时候看看它的性能提升了。

在这次基准测试中,我使用了这个简单的质数计数器函数。我首先使用 for 循环运行这个函数,然后使用 python 内置的多处理模块,最后使用 Tuplex。

作者的片段。

用标准 Python 执行密集型任务。

在 for 循环中运行函数是最简单的。我使用 Jupyter 笔记本中的“%%time”助手来跟踪执行时间。

作者摘录。

多次运行上述代码平均需要 51.2 秒才能完成。

在 for 循环执行中,执行速度会很慢。但是让我们用 python 内置的多处理模块来做同样的尝试。下面的代码不能在 REPL 的 like Jupyter 笔记本上运行。你必须把它放在一个. py 文件中,然后在命令行中执行它。

作者摘录。

运行这个多处理脚本的平均时间为 30.76 秒。与 for-loop 方式相比减少了 20.44 秒。

并行处理密集型任务。

最后,我们执行相同的素数计数器函数,这次是用 Tuplex。下面这段简洁的代码平均花费了 0.000040 秒,并产生了相同的结果。

作者摘录。

与其他标准 python 方式相比,Tuplex 的性能提升非常显著。这个小例子的执行时间比多处理短 769k 倍,比普通 for 循环快 1280k 倍。

我们会…让我们坚持 Tuplex 团队的 5–91X 承诺。然而,Tuplex 敦促我在编写另一个 for 循环之前要三思。

结论

Tuplex 是一个易于安装的 python 包,可以为您节省大量时间。它通过将数据转换成字节码并并行执行来加速数据管道。

性能基准测试表明,它对代码执行的改进是深远的。然而,它的设置非常简单,语法和配置非常灵活。

Tuplex 最酷的部分是它方便的异常处理。数据管道中的错误处理从未如此简单。它与交互式 shells 和 Jupiter 笔记本集成得很好。编译语言通常不是这种情况。甚至 python 本身也不能像 Jupyter notebook 那样在 REPL 内部处理并行处理。

Tuplex 在提升 Python 性能方面取得了显著的成功。但是与 Python 传统的高性能计算方法相比,它的性能如何呢?这里有一篇文章将它与 Cython 进行了对比。

谢谢你的阅读,朋友。看来你和我有许多共同的兴趣。一定要看看我的个人博客。

向我问好LinkedInTwitter。我会为你打破僵局。

还不是中等会员?请使用此链接 成为 会员。你可以享受成千上万的有见地的文章,并支持我,因为我赚了一点佣金介绍你。

如何加快编写大型 SQL 查询

原文:https://towardsdatascience.com/how-to-speed-up-writing-a-large-sql-query-9237c6db56cc?source=collection_archive---------21-----------------------

更聪明地工作,而不是更努力:在大约 3 分钟内学会!

图片由 Prateek Katyal 通过 Unsplash 提供

我们都经历过这种情况:从一个大表中提取数据,这个大表有个需要聚合的数字列。为什么要为 30 多列中的每一列都键入“SUM(col_1) AS col_1,etc ”,而这可以简单得多?注意:第二个超级省时器跟在第一个魔术后面!

Excel 不仅仅可以用于数据透视表

在下图中,我使用了一个假想的 SQL 表中的 10 列。对于每一列,我们将对值求和。我们可以使用 Excel 的内置函数 CONCATENATE()来完成所有繁重的工作,而不是把这些都写出来。

作者照片

在 A 列中,我们有一个要求和的列的列表。在 B 列中,我们输入连接函数。这可以通过别名、不同的聚合等来改变。基本语法是:

  1. 逗号(也可以放在末尾)
  2. 带有左“(”的聚合名称
  3. 列名
  4. 用空格结束“)”
  5. “AS”这个词(AS 不是必需的,但既然如此简单,不妨使用它)
  6. 再次输入列名

一旦我们创建了 B 列,只将复制并粘贴到另一列。然后,您可以复制这些结果并将其粘贴到您的 SQL 查询中。

对 10 列这样做将节省少量时间。真正的好处是当你开始引入 30 或 50+列时。

但是等等,还有更多…

在 A 列或步骤 1 中,我们需要一个列名列表。如果可以加快这个过程,为什么还要把这些都打出来呢?下一部分将根据您使用的 SQL 类型而有所不同。对于 MS SQL Server,您可以使用此查询从表中提取所有列名的列表:

该查询中的一列是您特别命名的表中所有列的名称。您可以复制并粘贴所有列,只删除不需要聚合的列。从 Excel 中删除 20 行比键入 40 个列名要快得多。

最后的想法

正如在以前的文章《V2:什么造就了一个伟大的分析师?》中提到的,你一定是个骗子。一个很好的习惯是确定你经常被要求完成的普通类型的任务,找出节省时间的方法,实施它,然后与你团队中的其他人分享这个想法。一如既往,继续学习!

找出“V2:是什么造就了一个伟大的分析师?”:

和 V1:

如何加快 XGBoost 模型训练

原文:https://towardsdatascience.com/how-to-speed-up-xgboost-model-training-fcf4dc5dbe5f?source=collection_archive---------18-----------------------

虽然增加计算资源可以加快 XGBoost 模型训练的速度,但为了更好地利用可用的计算资源,您也可以选择更高效的算法(图片由 Michael Galarnyk 提供)。

梯度推进算法广泛应用于监督学习。虽然他们很强大,但他们可能需要很长时间来训练。Extreme gradient boosting,或 XGBoost ,是一个开源的梯度增强实现,旨在提高速度和性能。然而,即使是 XGBoost 训练有时也会很慢。

有很多方法可以加速这一过程,例如:

本文将回顾每种方法的优点和缺点,以及如何开始。

改变你的树构造算法

XGBoost 的tree_method参数允许您指定想要使用的树构造算法。为你的问题选择一个合适的树构造算法(exactapproxhistgpu_histauto,可以帮助你更快的产生一个最优的模型。现在让我们回顾一下算法。

确切的

这是一个精确的算法,但是它的可扩展性不是很好,因为在每个 split find 过程中,它会遍历所有的输入数据条目。实际上,这意味着长时间的训练。它也不支持分布式训练。可以在原 XGBoost 论文中了解更多关于这个算法的内容。

虽然确切的算法是准确的,但当数据不能完全适合内存时,它是低效的。原始 XGBoost 论文中的近似树方法使用分位数草图和梯度直方图。

hist

LightGBM 中使用的近似树方法与approx在实现上略有不同(使用了一些性能改进,如 bin 缓存)。这通常比approx更快。

gpu_hist

由于 GPU 对于许多机器学习应用来说至关重要,XGBoost 拥有 hist 算法gpu_hist的 GPU 实现,该算法支持外部存储器。它比 hist 快得多,使用的内存也少得多。注意,XGBoost 在某些操作系统上没有对 GPU 的原生支持

XGBoost 文档

汽车

这是参数的默认值。基于数据集的大小,XGBoost 将选择“最快的方法”。对于小型数据集,将使用 exact。对于较大的数据集,将使用近似值。注意,在这种基于启发式的方法中,不考虑 hist 和 gpu_hist,尽管它们通常更快。

如果你运行下面的代码,你会看到使用 gpu_hist 运行模型是如何节省大量时间的。在我的计算机上的一个相对较小的数据集(100,000 行,1000 个要素)上,从 hist 更改为 gpu_hist 将训练时间减少了大约 1/2。

如果 XGBoost 在您的操作系统上没有对 GPU 的本地支持,请将第 17 行修改为 methods = ['exact ',' approx ',' hist ',' auto']。这将删除“gpu_hist”。

利用云计算

云计算不仅可以让你利用比本地机器更多的内核和内存,还可以让你访问专门的资源,比如 GPU。

最后一节主要是关于选择更有效的算法,以便更好地利用可用的计算资源。然而,有时可用的计算资源是不够的,你只是需要更多。比如下图所示的 MacBook,只有 4 核,16GB 内存。此外,它运行在 MacOS 上,而在撰写本文时,XGBoost 还没有 GPU 支持。

出于本文的目的,你可以将上面的 MacBook 想象成一个 4 核的单节点(图片由 Michael Galarnyk 提供)。

解决这个问题的方法是在云上利用更多的资源。利用云提供商不是免费的,但他们通常允许你利用比本地机器更多的内核和内存。此外,如果 XGBoost 不支持您的本地机器,很容易选择 XGBoost 支持的实例类型。

如果你想尝试加速你在云上的训练,下面是来自杰森·布朗利的文章中关于如何在 AWS EC2 实例上训练 XGBoost 模型的步骤概述:

1.设置 AWS 帐户(如果需要)

2.启动 AWS 实例

3.登录并运行代码

4.训练 XGBoost 模型

5.关闭 AWS 实例(仅在使用实例时付费)

如果您选择一个比本地更强大的实例,您可能会发现云上的训练更快。注意,使用 XGBoost 的多 GPU 训练实际上需要分布式训练,这意味着您需要不止一个节点/实例来完成这个

使用 Ray 进行分布式 XGBoost 训练

到目前为止,本教程已经介绍了通过改变树构造算法和通过云计算增加计算资源来加速训练。另一个解决方案是用利用 Ray 的 XGBoost-Ray 来分发 XGBoost 模型训练。

雷是什么?

Ray 是一个快速、简单的分布式执行框架,可以轻松扩展您的应用程序并利用最先进的机器学习库。使用 Ray,您可以将按顺序运行的 Python 代码,通过最少的代码更改,转换成分布式应用程序。如果你想了解雷和演员模型,你可以在这里了解

虽然本教程探索了 Ray 如何使 XGBoost 代码的并行化和分发变得容易,但需要注意的是,Ray 及其生态系统也使普通 Python 代码以及现有库的分发变得容易,如 scikit-learnLightGBMPyTorch 等等(图片由 Michael Galarnyk 提供)。

如何开始使用 XGBoost-Ray

要开始使用 XGBoost-Ray,首先需要安装它

pip install "xgboost_ray"

因为它与核心 XGBoost API 完全兼容,所以您只需要修改一些代码,就可以将 XGBoost 培训从单台机器扩展到拥有数百个节点的集群。

XGBoost-Ray 支持多节点/多 GPU 训练。在机器上,GPU 通过 NCCL2 传递梯度。在节点之间,他们用 Rabit 代替。你可以在这里了解更多信息。

正如您在下面的代码中看到的,这个 API 非常类似于 XGBoost。粗体部分是代码与普通 XGBoost API 不同的地方。

**from xgboost_ray import RayXGBClassifier, RayParams**
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split

seed = 42

X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, train_size=0.25, random_state=42
)

**clf = RayXGBClassifier(
    n_jobs=4,  # In XGBoost-Ray, n_jobs sets the number of actors
    random_state=seed)**

# scikit-learn API will automatically convert the data
# to RayDMatrix format as needed.
# You can also pass X as a RayDMatrix, in which case
# y will be ignored.

clf.fit(X_train, y_train)

pred_ray = clf.predict(X_test)
print(pred_ray)

pred_proba_ray = clf.predict_proba(X_test)
print(pred_proba_ray)

上面的代码显示了使用 XGBoost-Ray 只需要修改很少的代码。虽然您不需要 XGboost-Ray 来训练乳腺癌数据集,但之前的一篇文章在不同数量的工作人员(1 到 8)中对几个数据集大小(大约 1.5M 到大约 12M 行)进行了基准测试,以显示它在单个节点上对更大的数据集的性能。

单节点基准测试的训练时间(越短越好)。XGBoost-Ray 和 XGBoost-Dask 在单个 AWS m 5.4x 大型实例上实现了类似的性能,该实例具有 16 个内核和 64 GB 内存(图像源),

XGBoost-Ray 在多节点(分布式)设置中也是高性能的,如下图所示。

多个合成数据集的多节点训练时间从大约 400k 到大约 2B 行(越低越好)。XGBoost-Ray 和 XGBoost-Spark 实现了类似的性能(图像来源)。

如果你想了解更多关于 XGBoost Ray 的信息,请查看 XGBoost-Ray 上的这篇帖子。

结论

这篇文章介绍了几种可以用来加速 XGBoost 模型训练的方法,比如改变树的构造方法、利用云计算和在 Ray 上分布式 XGBoost。请记住,有许多不同的方法可以做到这一点,所以请随时用你最喜欢的方式发表评论。如果你想了解雷的最新消息,可以考虑在 twitter 上关注@ Ray distributed

如何将 K-Means 聚类速度提高 10 倍

原文:https://towardsdatascience.com/how-to-speed-up-your-k-means-clustering-by-up-to-10x-over-scikit-learn-5aec980ebb72?source=collection_archive---------12-----------------------

使用 Faiss 库

ChireCC BY-SA 4.0 ,通过维基共享

K-Means 聚类是机器学习中最知名、最常用的聚类算法之一。具体来说,它是一种无监督的机器学习算法,这意味着它在不需要地面事实标签的情况下进行训练。实际上,要使用它,你所要做的就是设置期望的聚类数 K ,初始化 K 形心,然后执行算法得到类。

K-Means 的优点在于它的简单性:它真正做的只是计算点和组中心之间的距离,从而导致线性复杂度 O ( n )。对于大多数不需要处理数百万个数据点的数据集来说,这种方法非常有效。

但这就是我们遇到问题的地方:当涉及到更大的数据集时,K-Means 是缓慢的,因为有太多的数据点需要比较。更糟糕的是,最流行的 K-Means 聚类实现,即 Scikit-Learn ,并没有得到很好的优化。

但不用担心。这就是我们的新朋友费斯的用武之地!

什么是 Faiss?

Faiss 是一个快速相似性搜索和聚类的库。它是由脸书人工智能研究所创建的,非常智能地使用向量,以及跨 CPU 核心的并发性来加快计算速度。更重要的是,它有一个 GPU 组件,用于在更大的数据集上提高速度。

尽管所有这些神奇的事情都发生在幕后,Faiss 仍然提供了一个 Python 接口,这使得编码非常容易。事实上,一旦你进入其中,你会发现代码的布局看起来与 Scikit-Learn 惊人的相似。

安装 Faiss 库

安装 Faiss 最简单的方法是使用 conda。首先,创建您的 conda 环境并激活它:

然后,您可以在环境中安装 Faiss 库。我们还将安装 scikit-learn,因为我们将比较两者之间的速度。最后,我们将安装 Keras 和 TensorFlow —我们将使用其中的数据集。

下面我安装了 Faiss 的 CPU 版本,但他们也有一个 GPU 版本,如果你感兴趣的话。如果你想做一个非常漂亮的安装,你可以随时查看安装文档

太好了!现在我们已经准备好让我们的 K-Means 超级快!

使用 Scikit-Learn 设置数据和基准

我们要做的第一件事是运行 Scikit-Learn 实现。这是为了建立一个通用的比较基准。供您参考,我运行这些测试的机器有以下规格:

  • i7–8700k CPU
  • 32 GB DDR 4 3000 MHz 内存

我们首先要做的是导入和数据加载。

我们将使用经典的 MNIST 数据。MNIST 是由 60,000 幅训练图像和 10,000 幅测试图像组成的数据集。每个图像是 28x28 像素,在黑色背景上包含一个白色像素的数字(0 到 9 中的一个)。它通常被用作机器学习的快速基准——挑战足够有意义,但又足够小,不需要大量的计算能力。

看看下面的代码,看看我们是如何做到的。我们直接从 Keras 获取数据,对其进行整形,并将输入规范化为浮点类型,值介于 0 和 1 之间。

接下来我们要做的是运行我们的 scikit-learn K-Means 基准测试。看看下面的代码,看看我们是如何做到的。

我们将 K-Means 设置为 10 个聚类,因为这是我们的数据集拥有的类标签(数字)的数量。然后,我们运行我们的fit()函数,它实际上创建了集群。我们测量这需要多长时间作为“训练时间”。接下来是我们使用predict()函数在测试集上执行的预测。在这里,我们测量对所有样本进行预测所花费的总时间,作为“预测时间”。

不错!

最终,对这 60,000 幅图像的训练花费了 21.51 秒,而对 10,000 幅图像的总预测时间为 0.0203 秒

使用 Faiss 在 CPU 上运行

现在,我们将看看如何使用 Faiss 实现同样的集群,当然,在 CPU 上要快得多。代码类似于 scikit-learn,只是有几个不同的变量名。

看看下面的代码,看看我们是如何做到的。我们再次将聚类数设置为 10。我们还必须设置两个变量:niter,它相当于来自 scikit-learn 的max_iternredo,它相当于来自 scikit-learn 的n_init。此外,代替fit(),用于训练的函数被称为train(),代替predict(),用于预测的函数被称为search()

我们再次测量训练和预测的时间。在 Faiss 库的情况下,对这 60,000 幅图像的训练花费了 2.33 秒,而总预测时间为 0.0112 秒。这几乎是训练的 10 倍加速和预测的 2 倍加速!

总是超级快吗?

不,不总是。

在我对更小的数据集做的所有测试中,比如波士顿、鸢尾和 T21,几乎没有改善。我认为这是因为 Faiss 需要时间来设置和矢量化所有的数据,所以只有在更大的数据集上才能实现改进。

如果你想在 GPU 上运行,Faiss 团队也有进一步的建议,他们再次指向更大的数据集。这当然是有意义的,因为将数据从 CPU 传输到 GPU 总是需要时间。因此,一般来说,利用 GPU 只能真正为非常大的数据集(即数百万个样本)加速。

了解更多信息

我强烈推荐查看 Faiss Wiki 来了解更多关于如何使用这个库的信息。该库在相似性搜索和检索方面做了令人难以置信的优化(例如 KNN ),并且有大量的例子让你开始。

如何通过 PySpark 加速您的 Python 代码

原文:https://towardsdatascience.com/how-to-speed-up-your-python-code-through-pyspark-e3296e39da6?source=collection_archive---------19-----------------------

环境设置

关于如何安装和运行 Apache Spark 和 PySpark 以提高代码性能的教程。

图片由拍摄来自 Pixabay

当你处理巨大的数据集时,瓶颈不是你的代码(我希望如此…),而是对你的数据集执行某些操作所耗费的时间。出于这个原因,开发一些可以加速代码的库是非常重要的。

阿帕奇 Spark 或许能帮到你。Apache Spark 是一个开源项目,相对于标准技术,它可以将工作负载加速 100 倍。它可以在分布式环境中工作(集群),但也可以在本地使用,例如当您的机器中有多个处理器时。

实际上,在 Apache Spark 中有两种类型的节点:主节点和许多工作节点,主节点是集群的主计算机。主服务器组织工作并在工人之间分配,然后检索结果。

在本教程中,我涉及以下几个方面:

  • 下载并安装 Apache Spark
  • 安装 PySpark 以配置 Python 来与 Apache Spark 一起工作
  • 运行一个简单示例

下载并安装 Apache Spark

Apache Spark 可以从其官方网站下载:

https://spark.apache.org/downloads.html

你可以选择火花释放和包装时间。如果您没有任何特殊需求,可以下载 Apache Hadoop 的最新版本和预编译版本。下载后,您可以将其移动到您的首选目录,并用一个较短的名称重命名。

Apache Spark 可以通过 PySpark 包与 Python 结合使用。

Apache Spark 也需要安装 Java。Java 的兼容版本从 8 到 11 不等。不支持其他版本。

安装 PySpark

现在您可以安装 PySpark,例如通过pip管理器:

pip install pyspark

安装完成后,您需要配置SPARK_HOME并修改您的.bash_profile.profile文件中的PATH变量。该文件是隐藏的,位于您的主目录中。您可以打开它,并在文件末尾添加以下代码行:

export SPARK_HOME="**/path/to/spark**/spark"
export PATH="$SPARK_HOME/python:$PATH"

您可以保存文件并启动终端。您可以输入以下命令:

pyspark

pyspark终端启动。要退出它,只需写下quit()并按回车键。

作为选项,您可以配置 **pyspark** 使用 Jupyter 笔记本。

在这种情况下,您可以使用findspark包,它会为您搜索 Spark 在哪里。实际上,findspark包会从你的概要文件中读取SPARK_HOME目录。

您可以通过以下命令安装findspark:

pip install findspark

安装完成后,您可以启动 Jupyter notebook,并在代码开头添加以下代码行:

import findspark
findspark.init()

简单的例子

现在,您已经准备好运行您的第一个pyspark 示例了。首先,您可以创建一个SparkContext,它对应于您的集群的主节点。您可以指定一些配置参数,例如应用程序名称(myproject)和 url ( local):

from pyspark import SparkContext, SparkConfconf = SparkConf().setMaster("local").setAppName("myproject")
sc = SparkContext.getOrCreate(conf=conf)

getOrCreate()函数创建一个新的SparkContext,如果它还不存在,否则它检索现有的。这是因为只能有一个运行中的SparkContext实例。

现在您可以创建一个 Spark 数据帧,它的行为很像一个 SQL 表。火花数据帧可从SparkContext对象创建,如下所示:

from pyspark.sql import SparkSessionspark = SparkSession.builder.getOrCreate()

现在您可以使用spark对象来读取 CSV 文件:

df = spark.read.csv("/path/to/your/csv/file",inferSchema=True, header=True)

inferSchema=True参数允许自动识别数据类型,但需要更多时间。您可以通过show()函数列出数据帧的第一行:

df.show()

结果看起来像一个 SQL 表。

您可以通过经典的 SQL 查询来查询数据帧。为此,首先必须将新的数据帧注册到可用表列表中:

df_sql = df.createOrReplaceTempView('df_name')

其中df_name是您希望在 SQL 中使用的表的名称。您可以列出所有可用的表格:

print(spark.catalog.listTables())

现在,您可以通过以下代码查询您的表:

query = 'SELECT count(*) FROM df_name'
sc.sql(query)

摘要

在本教程中,我演示了如何在您的计算机上安装和运行 Apache Spark 和 PySpark。此外,我还举例说明了如何将 CSV 文件读入 Spark DataFrame。

如果你想了解我的研究和其他活动的最新情况,你可以在 TwitterYoutubeGithub 上关注我。

相关著作

https://medium.com/geekculture/the-top-25-python-libraries-for-data-science-71c0eb58723d [## 如何在 Android 设备上安装 Python 和 Jupyter Notebook

towardsdatascience.com](/how-to-install-python-and-jupyter-notebook-onto-an-android-device-900009df743f)

参考

https://medium.com/tinghaochen/how-to-install-pyspark-locally-94501eefe421 https://www.sicara.ai/blog/2017-05-02-get-started-pyspark-jupyter-notebook-3-minutes

如何通过缓存加速 Python 代码

原文:https://towardsdatascience.com/how-to-speed-up-your-python-code-with-caching-c1ea979d0276?source=collection_archive---------1-----------------------

使用 cachetools 的快速指南

安东·马卡连柯的图片来自派克斯

几周前,我开始研究优化我的代码。我了解了常见的反模式和最坏的实践,查看了创建 Python 对象时如何分配内存,并最终理解了多线程和多处理等概念以及之间的区别。

今天,我将告诉你关于缓存:一种最小化不必要的计算并加速你的程序的机制。如果做对了,你会惊讶于这是多么有效。

在这篇文章中,我们将了解什么是缓存,什么时候与使用相关,以及我们如何使用 ***cachetools*** python 包将其应用于各种用例。

事不宜迟,我们来看看吧!🔎

什么是缓存?

缓存是一种优化技术,包括将最近(或经常)使用的数据保存在一个内存位置,该位置可以廉价快速地访问重复查询。

由于多种原因,从原始源访问数据可能会很昂贵,缓存似乎是缓解这一问题的解决方案。

👉让我们考虑一个经常使用缓存的应用 : web 服务器。

你正在建立一个小网站来分享你所在地区的本地新闻。

当用户滚动新闻提要并点击一篇文章时,他被重定向到一个网页:浏览器在这一步所做的是查询远程服务器,接收页面源代码并以人类可读的格式呈现它。正如您所料,这个操作非常耗时,因为它涉及到下载远程文件(这是一个网络绑定的操作)和渲染它们。

⚠️每次用户点击这个链接时都重复同样的操作,这似乎是一个不必要的计算。我们已经知道第一次提取后的结果,为什么不重用它呢?

✅:在这种情况下,你应该做的是在获取每篇文章后将内容存储在本地。下次用户打开同一篇文章时,应用程序将从本地副本中读取内容。这会快得多。

您可能已经在不知不觉中实现了缓存

让我们回到前面的例子,尝试提出一个简单的缓存实现。

我们想要的是将每篇文章的内容存储在本地内存中(例如 RAM 中的一个对象),如果用户以后请求相同的链接,就可以重用它。

这看起来像是字典的完美工作。

如果我们试图用同一个 url 连续运行两次fetch_article

作者截图

我们会注意到一个巨大的差异。

  • 第一次:118 毫秒
  • 第二次:5.01 秒

这是一个 2360 的惊人比例!

你会告诉我,118 毫秒还是很快。但是想象一下,如果同一个用户每天多次执行这个操作。有很多时间可以节省。

使用 cachetools 和 TTLCache 实现相同的缓存机制

cachetools是一个提供各种记忆集合和装饰器的模块,包括 Python 标准库的 @lru_cache 函数装饰器的变体。

使用cachetools添加缓存行为非常简单。我们只需添加几行:

如您所见,我们不再需要处理缓存更新的fetch_article函数。

在理解每个 import 语句的作用之前,先让代码替我们说话。

作者截图

运行之后,我们注意到,就像前面的例子一样,相同的时间差。

第一行输入我们需要使用的cachetools包。

**from cachetools import cached, TTLCache**

第二行是我们创建缓存对象的地方:第一个参数指定了我们存储在缓存中的对象的数量。我将它设置为 100,但它可以根据您的使用情况而变化。

第二个参数是生存时间的缩写,基本上是每个结果存储在缓存中的时间。过了这段时间,缓存的结果就过期了。

我随意地将它设置为 86400 秒,这相当于一整天。

**cache = TTLCache(maxsize=100, ttl=86400)**

第三行是我们添加到每个我们想要使用缓存的函数之上的装饰器。

其他缓存策略

我们已经配置了一个 TTL 缓存,但是其他类型的缓存也是可用的。

用哪一个高看你的需求了。有:

  • LFUCache(最少使用):记录检索项目的频率,并丢弃最少使用的项目
  • LRUCache(最近最少使用):丢弃最近最少使用的项目
  • RRCache(随机替换):随机选择物品并丢弃

感谢阅读🙏

缓存是一种重要的优化技术,可以防止重复,提高应用程序的速度。

知道何时以及如何添加缓存是提高代码效率的实用技能。

我希望这篇文章对你有用。今天就这些了。

下次见!👋

资源

您可以查看以下链接,了解更多关于 Python 中缓存的信息

照片由卡斯滕·怀恩吉尔特Unsplash 上拍摄

新到中?您可以每月订阅 5 美元,并解锁无限的文章— 单击此处。

当你在等待数据分析结果的时候,你是如何打发时间的

原文:https://towardsdatascience.com/how-to-spend-your-time-when-you-are-waiting-for-a-data-analysis-output-e71b383f43cb?source=collection_archive---------28-----------------------

数据科学讨论

当你的计算机正在运行你喜欢的算法,而你正在等待结果时,一些建议不要浪费你的时间。

图片由 anncapictures 来自 Pixabay

数据科学家的工作非常具有挑战性:你的知识必须涵盖从数据挖掘到数据分析,直到数据可视化。你从不停止

然而,当你启动一个繁重的计算时,比如一个大数据集上的机器学习算法,会发生什么?你停下来等待结果。你可能会看着屏幕几个小时,希望你的剧本完成。

不管怎么说,这不是消磨时间的最佳方式。你应该做些别的事情。你不能坐下来等待结果。

在这篇文章中,我向你推荐两种可能的替代方法来填补等待时间:

  • 专注于你的项目
  • 敞开心灵

1.专注于你的项目

花时间的一种可能方式是专注于你的项目,也就是说你可以尝试改进你的项目。如何?以下是一些可能的策略。

1.1 再次检查您的代码

第一个策略是再次检查你的代码,确保没有错误。这可能会导致您发现数据中的编程错误或问题。

你可以说我:“是的,你是对的!但是我如何检查我的代码写得好不好?”

一些提示:

  • 你的函数、变量和类都有有意义的名字,从某种意义上说,它们的名字反映了它们是什么。请不要使用my_variable作为变量的名称。如果变量代表某事物的总和,则使用total_sum
  • 你的代码易于阅读:编程语言只是另一种交流语言。因此,你的语言能被解读成旋律是非常重要的。
  • 如果由于代码的复杂性,您不能立即阅读您的代码,您可以向它添加注释。对一个写得好的代码来说,注释代码是最好的实践。

1.2 与你的同事讨论你的解决方案

你可以告诉你的同事你所采用的解决方案,比如解决旅行问题所采用的算法。你的同事可以为你的问题提出其他可能的解决方案。因此,您可以尝试实现它们,并与您的原始解决方案进行比较。

这样的讨论可以帮助你找到解决问题的替代方案,也许比你的方案更好。

1.3 思考接下来的步骤

另一个消磨时间的策略可以是开始思考你的输出的一些可能的可视化。因为你的观想依赖于你分析的输出,根据可能的输出,你可以想象不同的观想。

你可以列出可能的观想工具,并试着理解哪一个最适合你的情况。

1.4 搜索类似项目

你可以谷歌搜索类似的项目,也就是说你可以搜索你的竞争对手是如何解决与你类似的问题的

这个相位会向你揭示新的策略,也许,你会在等待你的算法输出的时候尝试去实现它们。

1.5 搜索其他数据

最后,但同样重要的是,你可以搜索其他的补充数据,这可以揭示你问题的另一个方面。存在许多开放资源,您可以在其中搜索感兴趣的数据。

以下是一些开源数据提供商:

  • 欧盟统计局数据库 —欧洲统计
  • Data.world —云原生数据的目录
  • data.gov—美国公开政府数据

2.敞开心灵

等待数据分析结果的另一种可能方式是知识提升。你可以尝试用不同的方式提高你的技能和知识,比如参加网络研讨会、在线课程等等。

2.1 学习

你可以通过学习来投资你的时间。例如,你可以买一本你不知道的主题的书,然后开始学习。或者,你可以参加一个在线课程,比如那些由 CourseraDatacamp 提议的课程。

就我个人而言,我建议你参加在线课程,这可以很快提高你的技能。我也建议你参加网上研讨会和会议,这可能会打破界限。

2.2 阅读

你可以通过阅读文章、博客和类似的东西来扩展你的知识,让自己跟上时代。例如,您可以在 Twitter 上关注数据科学影响者,阅读他们提出的文章和主题。

以下是一些在数据科学领域非常受欢迎的影响者,你可以在 Twitter 上关注他们:

和许多其他人。

2.3 做练习

你可以通过锻炼来保持健康,或者通过参加网络上发起的挑战。事实上,许多网站建议每月或每周练习,这可能有助于你保持最新的。

以下是一些提出挑战和练习的网站:

  • kaggle —一个提出数据科学竞赛的平台。
  • storytellingwithdata —这个网站提供许多资源和挑战,帮助您提高从数据中构建故事的技能。

2.4 写作

知识不仅包括你自己,也包括其他人。出于这个原因,你可以打开你的思维,开始写。例如,你可以开一个博客,作为作者开始写作。你可以写任何你想写的东西。

另一个选择是开通一个 Youtube 频道,向他人传播你的知识。

写作总是涉及到学习,因为如果你想把一件事解释清楚,你必须非常了解它。

摘要

在本文中,我提出了一些利用等待代码结果的时间的策略:

  • 专注于你的项目
  • 打开你的思维。

我个人建议,首先专注于你的项目,然后打开你的思维。

我提出的只是一个建议,如有意见请回复本文:)你怎么看?

如果你想了解我的研究和其他活动的最新情况,你可以在 TwitterYoutubeGithub 上关注我。

相关文章

https://alod83.medium.com/how-to-design-a-data-journalism-story-b2e421673b6e

如何用 Python 将数据集分割成训练集和测试集

原文:https://towardsdatascience.com/how-to-split-a-dataset-into-training-and-testing-sets-b146b1649830?source=collection_archive---------1-----------------------

探索从建模数据集创建训练和测试样本的三种方法

照片由 Siora 摄影Unsplash 上拍摄

在机器学习的背景下,将我们的建模数据集分成训练和测试样本可能是我们需要进行的最早的预处理步骤之一。为训练和测试创建不同的样本有助于我们评估模型性能。

在本文中,我们将在建模和模型训练的上下文中讨论训练和测试样本的目的。另外。我们将探索使用 Python 和 pandas 创建此类样本的三种简单方法。更具体地说,我们将展示如何创建训练和测试样本:

  • 使用scikit-learn(又名sklearn ) train_test_split()
  • 使用numpyrandn()功能
  • 或者用内置的pandas方法称为sample()

为什么我们需要训练和测试样本

训练模型时一个非常常见的问题是过度拟合。当一个模型在我们用来训练它的数据上表现很好,但它不能很好地推广到新的、看不见的数据点时,就会出现这种现象。发生这种情况的原因有很多,可能是由于数据中的噪声,也可能是模型学会了预测特定的输入,而不是帮助它做出正确预测的预测参数。通常,模型越复杂,过度拟合的可能性就越大。

另一方面,欠拟合发生在模型表现不佳时,即使是在用于训练它的数据上。在大多数情况下,出现拟合不足是因为模型不适合您试图解决的问题。通常,这意味着模型没有学习那些可以被证明是可预测的参数所需的复杂。

为训练和测试模型创建不同的数据样本是可以用来识别这类问题的最常见的方法。通过这种方式,我们可以使用训练集来训练我们的模型,然后将测试集视为数据点的集合,这将帮助我们评估模型是否可以很好地推广到新的、未知的数据。

将建模数据集分为训练集和测试集的最简单方法是将 2/3 的数据点分配给前者,将剩余的三分之一分配给后者。因此,我们使用训练集训练模型,然后将模型应用于测试集。这样,我们可以评估我们的模型的性能。例如,如果训练精度非常高,而测试精度很差,那么这是模型可能过度拟合的良好指示。

请注意,将数据集分成训练集和测试集并不是避免过度拟合等现象所需的唯一操作。例如,如果训练集和测试集都包含现实世界数据中不存在的模式,那么模型的性能仍然会很差,即使我们无法从性能评估中观察到它。

第二点,你应该意识到在某些情况下你应该考虑创建一个额外的集合叫做验证集合。当除了模型性能之外,我们还需要在许多模型中进行选择并评估哪个模型性能更好时,通常需要验证集。

如何将数据集分成训练集和测试集

在这一节中,我们将探索创建训练集和测试集的三种不同方法。在开始这些方法之前,让我们创建一个虚拟数据集,用于演示目的。在下面的例子中,我们将假设我们有一个数据集作为 pandas 数据帧存储在内存中。虹膜数据集包含 150 个数据点,每个数据点有四个特征。

在下面的例子中,我们将假设我们需要 80:20 的训练:测试集比率。

使用熊猫

第一种选择是使用 pandas DataFrames 的方法[sample()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.sample.html):

从一个对象轴中返回一个随机的项目样本。

您可以使用 random_state 来获得再现性

我们最初通过从 pandas 数据帧的所有行中抽取分数为 0.8 的样本来创建训练集。注意,我们还定义了与种子相对应的random_state,这样结果是可重复的。随后,我们通过简单地从现在包含在训练集中的原始数据帧中删除相应的索引来创建测试集。

正如我们所看到的,训练集包含 120 个示例,这与我们在对原始建模数据帧进行采样时所要求的分数一致。剩余的 30 个例子被打包到测试集中。

使用 scikit-learn

第二种选择——也可能是最常用的——是使用sklearn的方法[train_test_split()](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html):

将阵列或矩阵拆分为随机训练和测试子集

我们可以通过将建模数据帧以及应该包括在测试集中的部分示例传递给train_test_split(),在一行中创建训练集和测试集。如前所述,我们还设置了一个random_state,以便结果是可再现的,也就是说,每次我们运行代码时,相同的实例将分别包括在训练集和测试集中。方法会传回包含两个资料框的 tuple,其中包含训练和测试范例。

使用 numpy

最后,一种不太常用的创建测试和训练样本的方法是使用numpy的方法[randn()](https://numpy.org/doc/stable/reference/random/generated/numpy.random.randn.html):

从“标准正态”分布返回一个或多个样本。

我们首先创建mask,这是一个 numpy 数组,其中包含通过比较介于 0 和 1 之间的随机浮点数字与我们希望为训练集保留的分数计算的布尔值。随后,我们通过相应地过滤 DataFrame 来创建训练和测试样本。但是,请注意,这种方法将近似为给出 80:20 的比率,这意味着训练和测试样本中包含的示例数量不一定像本文前面讨论的两种方法那样准确。

下一步是什么?

现在,您已经从原始建模数据集创建了训练和测试集,您可能还需要执行进一步的预处理步骤,如缩放或归一化。这样做时必须小心,因为您需要避免将未来的信息引入到培训集中。这意味着某些动作需要首先应用于训练集,然后使用从该步骤中学习的参数,以便也将它们应用于测试集。有关此主题的更全面解释,请阅读下面的文章。

结论

在本文中,我们探讨了将初始建模数据集分成训练和测试样本的重要性。此外,我们讨论了这些集合如何帮助我们识别我们的模型是过拟合还是欠拟合。最后,我们已经看到了如何用 Python 和 pandas 以三种不同的方式实现这种分离;使用pandas.sample()sklearn.traing_test_split()numpy.randn()

如何将 Tensorflow 数据集拆分为训练集、验证集和测试集

原文:https://towardsdatascience.com/how-to-split-a-tensorflow-dataset-into-train-validation-and-test-sets-526c8dd29438?source=collection_archive---------5-----------------------

为什么以及何时需要训练、验证和测试分割,以及如何使用 Python 从 tf.data.Dataset 构建分割

图片来自 Pixabay

为什么以及什么时候我们需要训练、验证和测试分割?

开发机器学习模型时最大的挑战之一是防止它过度拟合数据集。当模型学习到在用于训练的数据上表现良好的权重组合,但当模型被给予它从未见过的图像时却不能推广时,困难就出现了。这就是所谓的过拟合

当实现一个将在现实世界中部署的模型时,我们可能希望对它投入生产后的行为有一个估计。这就是测试集发挥作用的地方,它是原始数据集的随机分区,旨在表示不用于训练的数据,以便我们可以估计我们的模型在看不见的数据下会如何表现。

此外,当我们计划对模型的不同配置进行实验时,第三个集合是有用的,例如备选架构、优化器或损失函数,也称为超参数调整。为了比较这些实验的性能,可以从原始数据集中提取另一个随机分割,该随机分割既不用于训练也不用于测试,而是用于在不同配置中验证我们的模型。这被称为验证集

现在,你可能想知道,但是验证和测试集的目的是一样的,对吗?的确,这两个数据集都用来评估我们的模型在没有用于训练的数据上的表现。然而,当尝试不同的模型配置以获得最佳验证度量时,我们在某种程度上使我们的模型适合验证集,选择在该集上具有最佳性能的参数组合。

一旦我们运行了我们的超参数调整,并且有了表现最好的模型,测试集允许我们了解这个模型在生产中的表现如何。因此,它应该只在项目结束时使用。

我应该使用哪种分割尺寸?

根据我们数据集的大小,可以使用不同的分割大小,同时考虑更适合当前可用数据但具有不太现实的指标(大训练分割大小)的模型或减少用于训练的数据量但具有更接近真实世界性能的验证和测试指标之间的权衡。

对于训练集、验证集和测试集,一个流行的划分是 80%、10%和 10%。

TensorFlow 实现

Tensorflow 2.0 中使用 Keras 时,我个人推荐使用 tf.data API ,它提供了构建复杂输入管道的抽象。例如,它允许从分布式文件系统中加载数据,使用有效的转换来映射数据,并将结果合并到批处理中进行训练。

但是,tf.data 不提供将 tf.data.Dataset 拆分为上述三个分区的直接调用。为此,我为您带来了一个简单的代码片段,它利用了 API 提供的 take 和 skip 方法。

该方法需要数据集的大小,因为数据集可以动态加载(例如,使用 CSV 数据)并且大小未知。如果数据是从静态源(比如 NumPy)加载的,那么可以使用' TF . data . experimental . cardinality(dataset)'来检索数据集的大小。

另外,请注意,在创建拆分之前,可以为该方法提供一个标志来打乱原始数据集。在大多数情况下,强烈建议这样做,以获得更现实的验证和测试指标。指定了洗牌的种子,以便我们可以运行相同的方法,并且分割保持不变(这对可靠的结果非常重要)。

熊猫实施

作为使用 TensorFlow 数据 API 的替代方法,这里有另一种对存储在 Pandas DataFrame 中的数据集进行分区的方法,在分割之前对整个数据集进行洗牌。这三个部门可以根据需要用于培训。

另一个流行的选择是从 scikit-learn 中调用两次train_test_split 方法(一次用于 train-test split,另一次用于 test-val split),但是我更愿意为您提供一个更本地的解决方案。

最后的话

在本文中,我们不仅探讨了如何将 Tensorflow 数据集划分为训练、验证和测试分区,还探讨了为什么这在任何机器学习项目中都很重要,以及每个分区的用途。

如果你想发现更多像这样的帖子,你可以在下面找到我:

如何将数据分成三组(训练、验证和测试),为什么?

原文:https://towardsdatascience.com/how-to-split-data-into-three-sets-train-validation-and-test-and-why-e50d22d3e54c?source=collection_archive---------0-----------------------

Sklearn 火车测试拆分不够。我们需要更好、更快的东西

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

介绍

为什么需要拆分数据?

您不希望您的模型过度学习训练数据,并在部署到生产中后表现不佳。你需要有一个机制来评估你的模型推广的有多好。因此,您需要将输入数据分成训练、验证和测试子集,以防止模型过度拟合,并有效地评估模型。

在这篇文章中,我们将涉及以下内容。

  1. 培训、验证和测试数据集的简要定义
  2. 准备好使用代码来创建这些数据集(2 种方法)
  3. 了解数据集分割率背后的科学原理

训练有效测试分割的定义

训练有效测试分割是一种评估机器学习模型性能的技术,无论是分类还是回归。你把一个给定的数据集分成三个子集。下面是对每个数据集的作用的简要描述。

训练数据集

  • 用于学习(由模型)的数据集,即,使参数适合机器学习模型

有效数据集

  • 调整模型超参数时,用于对符合训练数据集的模型进行无偏评估的数据集。
  • 也在其他形式的模型准备中发挥作用,如特征选择、阈值截止选择。

测试数据集

  • 一组数据,用于对符合训练数据集的最终模型进行无偏评估。

如果你想了解更多关于机器学习专家如何定义训练、测试和验证数据集的信息,请阅读 Jason Brownlee 的这篇文章。#1 下面参考资料部分的链接

准备使用代码片段

在本帖中,我们将看到将数据分为训练、有效和测试集的两种方法

  1. 随机分裂
  2. 使用时间分量进行分割

1.随机分裂

您无法使用用于训练的相同数据来评估模型的预测性能。如果你用模型之前没有见过的新数据来评估模型,那是最好的。随机分割数据是该无偏评估最常用的方法。

将输入数据随机分为训练集、有效集和测试集。作者图片

一、使用 sk learn→‘train _ test _ split’

在下面的代码片段中,您将学习如何使用两次train_test_split来创建我们期望比例的 train | valid | test 数据集。

二世。使用 Fast _ ml →' train _ valid _ test _ split '

在下面的代码片段中,您将学习如何使用train_valid_test_split在一行代码中创建我们期望比例的 train | valid | test 数据集。

2)使用时间分量进行分割

你可以听听杰瑞米·霍华德关于机器学习的 fast.ai 讲座:程序员机器学习入门。在第 3 课中,他谈到了“什么是好的验证集,我们利用这个讨论来为这个新数据选择一个验证集。”#2

他举了一个例子,“假设您正在构建一个模型来预测下个月的销售额。如果你无法知道你建立的模型是否能够提前一个月预测销量,那么你也无法知道当你将一个模型投入生产时,它是否会变得更好。”#3

每当数据集包含日期变量,并且我们希望预测未来的事情时,使用时态变量是拆分数据集的一种更可靠的方法。因此,我们必须使用最新的样本来创建验证和测试数据集。主要思想是始终选择一个样本子集,忠实地代表我们的模型随后将接收到的数据(无论我们面对的是现实世界的问题还是 Kaggle 竞争)。

对数据进行排序后,训练有效的测试数据集。作者图片

一、自定义代码

在下面的代码片段中,您将学习如何编写自定义代码,以便在对数据进行排序后,创建符合我们期望比例的 train | valid | test 数据集。稍加修改后,您可以直接使用这段代码。

二世。使用 Fast _ ml →' train _ valid _ test _ split '

在下面的代码片段中,您将学习如何在对数据进行排序后,使用train_valid_test_split来创建我们期望比例的 train | valid | test 数据集。所有这些都在一行代码中完成。

数据集分割率背后的科学

经常有人问,将数据集分成训练集、验证集和测试集的比例是多少?

这个决定主要取决于两件事。首先是数据中的样本总数,其次是您正在训练的实际模型。

  • 有些模型需要大量的数据来进行训练,因此在这种情况下,您可以针对更广泛的训练集进行优化。
  • 具有很少超参数的模型将易于验证和调整,因此您可以减少验证集的大小。
  • 但是,如果您的模型有许多超参数,您也会希望有一个重要的验证集。
  • 如果您碰巧有一个没有超参数或者不容易调整的模型,您可能也不需要验证集。

参考文献

1https://machine learning mastery . com/difference-test-validation-datasets/# 2https://www.fast.ai/2018/09/26/ml-launch/

3https://www.youtube.com/watch?v=YSFG_W8JxBo

感谢阅读!!

笔记本可在以下位置获得,并附有完整的功能代码:

https://www.kaggle.com/nextbigwhat/train-valid-test-split-instead-of-train-test-split

2021 年成为伟大数据科学家的 5 种方法

原文:https://towardsdatascience.com/how-to-stand-out-as-a-great-data-scientist-in-2021-3b7a732114a9?source=collection_archive---------34-----------------------

帮助您脱颖而出并从经验丰富的数据科学领导者那里获得聘用的技巧

被录用!(图片由真诚媒体Unsplash 上拍摄)

介绍

由于许多原因,数据科学是一个极具吸引力的职业,因此竞争可能会很激烈。下面一些让优秀候选人脱颖而出的建议可能会让你大吃一惊!

我为各种各样的读者写了这篇文章:

  • 你可能刚刚开始尝试你的第一个角色
  • 你可能在一个无关紧要的技术领域,想要做出改变
  • 或者,你可能已经是一名经验丰富的数据科学家,希望提高自己的技能。

为什么这么难?

这是我在用户组和社区活动中经常遇到的问题,针对的是有抱负的或职业生涯早期的数据专业人士。这是一个竞争激烈的领域,进入门槛正在发生变化——不再像我开始时那样需要博士学位。随着竞争的加剧,全力以赴的技术能力变得更难让你脱颖而出。

为什么要听我的?

我经历过——在桌子的两边!我是一名经验丰富的数据科学家,在科技初创公司中,我经历了高级职位和团队领导职位,一直到总监级别的职位。

在我的职业生涯中,我进步很快,我相信下面概述的几点对此有很大的贡献。

在更高级的职位上,我已经面试并雇佣了几十个候选人——从才华横溢、沉默寡言的专业人士到古怪而出色的人(有时间问问我关于滑板吸血鬼的事情)。我面试过各种各样的角色,包括:

  • 数据科学家
  • 机器学习工程师
  • 数据工程师
  • 分析员
  • BI 开发人员
  • DevOps 工程师、CRM 顾问、项目经理…

在所有这些经历中,有一些关键的主题和技能非常突出(剧透:它们大多是非技术性的技能)。我将在下面分享我对它们的看法,并尝试给出一些如何改进它们的建议。

技术

现在开始,我不打算讨论你应该知道什么算法,你应该阅读什么统计学书籍,或者你应该选择哪个机器学习堆栈。外面有很多课程,其中很多是免费的,这会给你在这个领域打下良好的基础。我在博士期间通过像这种的免费资源学习,但是有很多方法可以获得正确的体验。

宽广还是深邃?

做多面手好还是做专家好?这不是数据科学特有的问题,而是适用于许多技术角色的问题。这个问题也没有明确的答案,这真的取决于你想在什么样的组织中工作。如果你的梦想是在一个专注于一件事的知名技术团队或研究小组中获得一个角色,那么学习机器学习模型的每一种风格都不会像真正深入探索那个利基一样有效。这个领域太大了,不可能成为所有领域的专家(即使是跟上某个领域的研究也已经足够困难了)。

然而,如果你想成为一个组织进入数据科学的第一步,或者你想在一家羽翼未丰的初创公司工作,那么拥有广阔的视野通常是最好的。了解整个行业的工具和技术将使您能够解决更广泛的问题,并更容易知道如何在需求和要求发生变化时从数据中发掘价值。

优秀的候选人通常都有 T 型经验——广泛的知识和对领域的熟悉,以及他们真正闪光的专业(图片由作者提供)。

脱颖而出的候选人往往是 T 型的。他们对更广泛的领域有很好的理解,但只专注于一件事。对你的职业生涯来说,这通常也是一种更有回报的方式!它让你专注于你喜欢的一件事,并真正突出你的优势,同时仍然能够投入到其他类型的项目中。

小贴士# 1——在你的专业技能上呈 T 型可以让你集中精力展示你的专业技能,但仍然有助于一个充满活力的团队处理各种各样的任务。

展示你的弱点

人们通常认为你必须知道一切并表现出来——尤其是在面试的时候。事实并非如此,那些尝试过的人往往面试得很糟糕。当候选人直截了当地告诉我他们不知道一些事情时,我真的感到如释重负——这会建立信任和融洽。

数据科学是一个庞大而复杂的领域。没有人是这方面的专家。如果你不喜欢统计,那就敞开心扉。

像许多人一样,你可能是一个自学成才的程序员,在这种情况下,不要在编码测试中磕磕绊绊地背诵考试答案,而不是真正理解为什么。

如果你得到了这份工作,仅仅是在面试时假装成功就能让你在最初的几个月里感到不舒服。

秘诀 2——诚实面对你的弱点和你不知道的事情。当有人在虚张声势时,通常很容易辨别出来,而你真的不想最终担任一个不允许你表现出色的角色。

软件工程

申请数据科学职位的绝大多数人都花了所有的时间学习机器学习、统计、编码,也许还有一些可视化技能。当你开始催促他们关于设计模式或者软件开发方法的时候,他们会完全不知所措。

在 Jupyter 笔记本上编写粗糙的小模型和构建可以轻松打包、测试和扩展到生产中的强大机器学习工作流之间有很大的区别。

花些时间学习软件工程的基础知识。即使你不需要经常使用它,你也会在整个职业生涯中与软件工程师打交道。他们为早期职业数据科学家遇到的许多问题设计了解决方案,因此要向他们学习。此外,如果你受雇于一家公司的技术部门,你的部门主管或首席技术官很有可能原本是一名软件工程师——会说他们的语言对你有好处。

开始学习可能会很困难,但是开始学习以下两本书的主题是不会错的:

https://amzn.to/39TdfxD https://amzn.to/3jpDE9s

技巧 3——学习软件工程的基础知识。这将使您的工作更容易,您的代码更健壮,并允许您更好地与组织的其他部分联系起来。

运行正常的

对于大多数组织来说,如果最全面、最先进的模型只能由数据科学家来运行,它们就毫无价值。很多数据科学团队和机器学习项目失败是因为他们无法超越探索阶段。

你不需要成为容器和流程编排方面的专家(除非你想成为一名 ML 工程师),但是将你的模型转化为价值是这个角色的关键部分。我几乎总是问这个问题:

你将如何把你的模型交到一个非技术用户的手中?

在我见过的最好的一次面试中,候选人向我展示了他们准备的一些代码和一个非常简单的 web 应用程序,其中包含了这个模型。我马上就能玩它,并围绕他们做了什么提出问题。

如果您想开始使用 MLOps,我在这里写了一个简短的系列文章,带您浏览一个端到端的示例:

技巧 4——了解将您的工作部署到生产环境中的方法和工具。了解基本的 MLOps 将表明你理解模型开发只是工作的一小部分。

证明它

有时候,甚至去面试都很困难。这与上一篇技巧文章中给出的例子非常吻合。在你的申请中,没有比证明你已经做过这类工作更有力的了。

如果我在浏览简历时偶然发现一份带有 GitHub 链接的简历,我会一直查看它,并且通常会投入比我分配给那个人的时间更多的时间。它甚至不需要完全是原创的项目,更重要的是看你如何解决问题。如果你刚刚开始,没有大量的作业,把你的课程作业放上去,写一篇关于你是如何完成的评论。这将有助于你在面试开始前引导面试,因为你的面试官几乎肯定会问这个问题。

还有很多其他途径来展示你的作品。可以考虑边学边写博客(Medium 超级容易上手)。不要害怕通过 YouTube 或者在聚会和活动中出现在人们面前——这也将有助于提高一些重要的软技能。

你不一定要成为专家才能为人们的学习做出贡献。如果你对此不确定或者不知道从哪里开始,我强烈推荐阅读奥斯汀·克莱恩的一些作品,比如这篇文章:

https://medium.com/low-pass-filter/show-your-work-39e6466c4273

或者这本伟大的书更详细地探讨了这个问题:

https://amzn.to/39WKPTp

技巧 5——展示你所知道的。在 GitHub 上做项目,在博客上谈论你学到的一些东西,演讲和活动或者活跃的 YouTube 频道会让你鹤立鸡群。

结论

今天,我试图分享什么样的技能,至少对我来说,能让一名优秀的数据科学候选人脱颖而出。如果所有这些对你来说都是新的或令人生畏的,选择一个,从小处着手。如果你开始写博客,并一边写一边加入 GitHub,你将开始提高你的技能并获得自信。

很难找到适合你的角色。许多人会喜欢一个更全面的候选人,可以在整个组织中交流。仅仅知道最多的算法或最新的工具并不是让你在求职中脱颖而出的最佳方式。

希望这些建议能让你得到工作。如果您有任何反馈,我将非常感谢您的来信。如果你也是这个领域的招聘经理,我很想知道你的想法。

进一步阅读

下面是其他可能有帮助的资源列表。如果上面提到的书有点沉重,那么由 Ahmed Besbes 撰写的这篇关于软件工程的文章是一个很好的开端:

https://medium.com/swlh/software-engineering-tips-and-best-practices-for-data-science-5d85dbcf87fd

这是 Vincent Tatan 对最近 MLOps 思想的一个很好的介绍和概述:

免责声明:这篇文章确实包含附属链接。

如何作为一名有抱负的数据科学家脱颖而出

原文:https://towardsdatascience.com/how-to-stand-out-from-the-crowd-as-an-aspiring-data-scientist-a7fe446421bc?source=collection_archive---------23-----------------------

给有抱负的数据科学家的改变游戏规则的职业建议

图片来源: Skye Studios @ Unsplash

近年来,数据科学一直是应届毕业生和年轻人才最青睐的工作之一。尽管对数据科学家的需求仍在激增,至少在欧洲和北美的就业市场上,但在过去几年里,对于有抱负的数据科学家来说,找到入门级工作变得越来越难。

一个原因可能是,在一个新的就业市场中成为一名合格的候选人自然具有挑战性。随着数据科学在人才中越来越受欢迎,以及雇主推动的所需技术技能的膨胀,在过去几年中,数据科学就业市场对候选人的竞争越来越激烈,尤其是对应届毕业生。然而,有抱负的数据科学家面临越来越多的困难,因为许多雇主正在将注意力转向更高级的候选人或来自数据工程和云计算等其他领域的候选人。

在本文中,我们将讨论有抱负的数据科学家如何脱颖而出,吸引雇主的注意力,并获得聘用:

  1. 获得最低水平的技术技能以赶上市场趋势

在当今不断变化的技术领域,获取新的技术技能不仅对有抱负的数据科学家来说是必要的,对有经验的数据专业人员来说也是必要的。技术来来去去,新工具在几个月内就变得流行起来。这转化为雇主在发布的工作中的动态和不断变化的工作要求。因此,如果简历中没有丰富的技术技能,有抱负的数据科学家就无法进入就业市场。虽然学习如此多的新技术可能是一项非常耗时的任务,但有抱负的数据科学家可以采用敏捷和快速学习的心态来获得最低要求的技术技能,以使他们进入工作岗位,并帮助他们在工作中进一步发展。

2。用突出的方式写你的简历

写一份能脱颖而出的简历,仍然是有抱负的数据科学家无法脱颖而出的最容易被忽视的原因之一。这主要是因为缺乏必要的反馈和对实际工作的理解。简历是初步筛选面试的入口,尤其是由人力资源专业人员或申请人跟踪软件(ATS)审查。写一份能给人力资源专家和招聘人员留下良好第一印象的简历是求职成功的关键。此外,现在的雇主大多使用 ATS 对收到的求职简历进行排名。因此,拥有一份可读的简历,容易被机器解析,并且以比其他候选人排名更高的方式撰写,是获得许多数据科学工作面试的另一个关键因素。

3。制定可靠的网络战略

在数据科学就业市场中,网络的重要性不容忽视。大多数候选人已经感觉到,申请著名工作论坛上发布的工作不再是找到数据科学工作的最终解决方案。然而,大多数候选人没有做任何事情来提升自己的水平,让自己被介绍给那些能让自己更接近被录用的人。候选人必须努力避免迷失在标准的招聘流程中,因为在他们之前有数百名候选人,他们必须在招聘公司内部找到更深层次的关系。这样做的一些方法可以是(a)直接与招聘经理建立关系网,(b)与拥有强大员工推荐计划的公司的员工会面,(c)与内部或外部招聘人员建立关系网,他们可以把你介绍给招聘经理。在这里,人际关系网中使用的目标或方法不如定期会见新专业人士的一致性重要。因此,有抱负的数据科学家必须走出他们的外壳,与人们谈论他们的抱负,并寻求他们对改善职业地位的建议。

4。在目标市场中建立信任和信誉

信任是每个招聘决定中最重要的因素之一。我们需要记住,每次招聘经理做出招聘决定时,他们所经历的思考过程与我们的购买决定非常相似。当我们购买昂贵的产品或服务时,我们希望确保它是高质量的,有效的,可靠的,简而言之,物有所值。有抱负的数据科学家可以通过建立足够的可信度和信任来实现这一目标。做到这一点的一个有效方法是展示以前的雇主,不管是长期的还是临时的,在雇佣你作为数据科学家时所拥有的经验。为了解决这给应届毕业生带来的先有鸡还是先有蛋的问题,我们建议有抱负的数据科学家在职业生涯开始时认真对待实习和临时工作,并专注于获得对这些工作的积极反馈。候选人不应该等太久才得到他们梦想中的工作,而是应该抓住每一个机会为就业市场建立概念证明来完成工作。通过这种方式,有抱负的数据科学家最终可以让雇主非常容易地做出招聘决定,从而雇佣他们从事他们梦想的工作。

5。在你的面试管道中加入大量公司

同样重要的是要注意,尽管采用了前面提到的所有方法,但不是每个雇主都会觉得你适合他们,反之亦然。找工作永远是一场数字游戏,候选人必须总是积极主动地计划如何填补他们的面试渠道,并保持他们的选择余地。通过保持面试渠道畅通,有抱负的数据科学家不仅可以增加尽快获得理想工作的机会,还可以建立关系,在未来的职业生涯中为他们提供帮助。

更多文章来自作者:

</8-career-paths-for-junior-data-scientists-to-pursue-3e6041950e4e> https://medium.com/geekculture/working-as-a-data-engineer-1f53b04aff83 [## 作为数据工程师工作

medium.com](https://medium.com/geekculture/working-as-a-data-engineer-1f53b04aff83)

关于作者:

Pouyan R. Fard 是 Fard 咨询公司的首席执行官兼首席数据科学家。Pouyan 在数据科学、人工智能和营销分析方面拥有多年的公司咨询经验,从初创公司到全球公司。他曾与制药、汽车、航空、运输、金融、保险、人力资源和销售等行业的财富 500 强公司合作。

Pouyan 也在指导活跃在大数据行业的初创公司和人才。他的热情是通过职业培训培养下一代数据科学家,并帮助他们找到数据科学领域的顶级工作机会。

Pouyan 已经完成了关于消费者决策预测建模的博士研究工作,并对开发机器学习和人工智能领域的最先进解决方案保持兴趣。

如何从艺术开始数据分析师的职业生涯,为什么

原文:https://towardsdatascience.com/how-to-start-a-career-as-a-data-analyst-from-a-background-in-the-arts-and-why-913b3ac6710d?source=collection_archive---------11-----------------------

你拥有的 STEM 毕业生可能没有的东西,以及“大数据”必须从艺术中获得的东西

亚当·威尔森在 Unsplash 上拍摄的照片

当工科学生称自己为工程师时,难道不令人讨厌吗?他们太超前了。这不像你听到医学生自称医生或艺术生自称咖啡师!

一个关于艺术学位的笑话是这样说的,这是一条为懒惰或愚笨的人提供的简单的教育途径,充满了乐趣,却不会有任何结果。

对我这个法语毕业生来说,这是一份分析职业,我发现这份职业很有价值,非常适合我在大学期间获得的能力。这与许多人没有明显的联系,但我想鼓励世界上更多的人这样做。

我已经在这个领域工作了十多年,经历了从没有特定培训的起点发展专业技能的过程,以及在伦敦和悉尼的机构、初创企业和大公司中实践分析的过程。

在过去的三年里,我一直在为我的公司雇主招聘分析师,并能够挑战候选人必须拥有 STEM 学科学位的规范,我自己的经验证明,商业分析充分利用了在人文学科研究中获得的能力(我更喜欢“人文学科”而不是“艺术”,但我在这里可以互换使用)。

在这篇文章中,我将试图解释这些能力是什么,它们如何适应分析,以及对于那些考虑从事非 STEM 背景的分析职业的人来说,从哪里开始。我希望激励有正确倾向的毕业生去尝试,说服招聘经理更开放地考虑他们考虑的简历,并在拉近人文科学和科学之间的距离方面发挥作用。

什么是“数据分析师”?

首先,我这里所说的数据分析师是指什么?一个人如何利用他们的时间?

我可以说,现在的分析世界由三个核心学科组成,通常分为“数据分析师”、“数据工程师”和“数据科学家”三个标签。简而言之,数据分析师探索数据以获得可用于业务决策的见解,数据工程师管理收集、存储和访问“大”数据所需的计算工具,数据科学家构建可用于业务预测、个性化建议等的软件。

我不会在这里更详细地描述其他两个学科,我只想说,它们是专业的、技术性很强的角色,可能不适合通才毕业生(尽管在入门级别的时候,界限往往很模糊)。但要了解这三个学科之间的更多区别,这里的是一篇比较每个角色的招聘广告的好文章。

另一方面,数据分析师的角色更容易获得,因为相对简单的技术知识的新手可以通过其他才能为组织带来价值,例如良好的沟通或洞察力。我们可以把这个角色比作一个记者揭露一个故事,建立一个证据体系来证明一个假设,并通过使用有说服力的故事来吸引他们的读者。对于数据分析师来说,证据通常基于数字数据,由数据可视化引导的故事讲述,但潜在的追求和思维模式是相似的。(关于用数据讲故事的经典例子,请看汉斯·罗斯林的 TED 演讲)。

卡斯帕·卡米尔·鲁宾在 Unsplash 上的照片

隐藏在数据中的故事可能是对某种产品的需求激增,这种需求可能与某些情况有关(如雨天的食品配送),或者是某种产品对某些类型的受众的特殊吸引力(如自行车社区的咖啡)。在这些情况下,分析师可以帮助做出的商业决策可能是增加下次我们预期的此类事件的资源,或者向这些社区投放广告。

用于数据分析的工具通常包括电子表格(如 Excel、Google Sheets)、数据可视化工具(如 Tableau、Google Data Studio)和 SQL 代码。在本文的后面,您可以找到更多关于如何开始使用这些工具的信息。Python 和 R 在与职位相关的方面也被大量引用,对于统计分析和从互联网上导入公开可用的数据尤其有用,尽管我认为它们在招聘广告中很流行,但它们一开始并不重要,甚至在高层也是不错的选择。

在典型的一周中,经验丰富的数据分析师可能会:

  • 与组织中的决策者会面,讨论他们的问题(例如是什么让我上一次的营销活动如此成功?人们不与我们重复购买的原因是什么?)并咨询使用可用数据回答这些问题的方法。
  • 使用上述任何工具浏览和清理数据集。“清理”是将杂乱的数据排列起来的过程,这通常是分析数据集所花费的最长时间。(举一个简单的例子,显示客户性别的数据列可能混合了“F”、“female”和“Female ”,它们都表示相同的东西,但就数据而言是不同的。为了清理这个,我们可以把所有这些都转换成 F。)
  • 花时间做研究,了解他们正在处理的数据是如何收集的。例如,在一个营销结果数据集中,收入按推动购买的渠道细分,我们如何准确地将购买归因于社交媒体广告、电子邮件简讯等?如果客户在选择购买之前看到了来自多个渠道的多个广告,该怎么办?
  • 设计实验来测试假设。
  • 使用视觉故事向决策者展示调查结果,并根据洞察提出行动建议。

随着分析师加深他们的技术能力,积累领域知识,他们分析的潜在复杂性将会增加,但是如果他们的观众不能理解他们或者看不到‘那又怎样?’的话,这些都不会有效所有分析的背后。正是在这种情况下,只见树木不见森林的能力和有说服力的沟通变得至关重要。这是一个让许多技术出众的人绊倒的障碍,也是一个人文学科毕业生可能会发现自己拥有优势的关键领域。

他们还能带来什么?

人文学科给数据分析带来了什么?

2020 年,在澳大利亚政府停止资助高等教育中的人文学科后,澳大利亚卫报向人文学科毕业生征集意见,询问他们的学位如何让他们适应工作。

你认为评论中的核心主题是什么?你能猜出哪个包含人文价值的两个词在所有评论中出现得最多吗(准确地说,在 484 条评论中出现了 90 次)?

照片由 GiammarcoUnsplash 上拍摄

在我们找到答案之前,这里有一条评论,举例说明了读者反映的主题:

这个学位给了我独立思考的工具,让我对别人告诉我的一切提出质疑,并得出自己对真实情况的结论[……]交流技能,能够清晰、清晰、有说服力地写作,一直被雇主视为招聘新员工的最重要的品质之一。然而,奇怪的是,他们似乎没有把他们所寻求的技能和艺术毕业生联系起来。[Bizkit]

这里有一条来自一位在数字领域工作的评论者,我们倾向于将它与 STEM 背景联系起来:

我主修英语和古典文学。我职业生涯的大部分时间都在从事基金管理。我为主要的上市公司和私人公司管理过两家公司,并与澳大利亚一家领先的基金经理共事了十多年。我的批判性评估技能弥补了我缺乏会计培训的不足。艺术学位教你如何学习和批判性思考——更多的人应该尝试。【mgan ci23】

这就是:“批判性思考”。在一个面对大量信息和不确定事实的世界里,我们如何知道该相信什么,如何做出决定?

该术语及其变体在 484 条顶级评论中出现了 90 次,其他评论中的许多讨论也借鉴了相同的观点。除了“艺术学位”和“人文学位”这两个词,这是遥遥领先的顶级二元词(两个词的组合),在所有单个词频的统计中(这对挑选关键主题不太有用),关于“思考”的变体排名非常高。如果你想看的话,这里是数据集。

作者图片

那么,为什么“批判性思维”是人文学科的标志,它真的不是 STEM 教育的一部分吗?

我想象会有 STEM 毕业生准备坚定地捍卫他们在学习或其他方面获得的批判性思维能力,但我认为有足够的证据表明,STEM 广泛教授的方式存在一些不足。目前,社会科学领域正在上演一场被广泛讨论的复制危机,这让人们对科学家得出结论的基本方法产生了怀疑,似乎部分科学界已经习惯于使用统计工具,但他们并不完全理解这些工具。大卫·爱泼斯坦,对糟糕的科学研究持批评态度,他认为肤浅的思维是科学中的通病,这是从大学里学到的,他在他的书 Range 中声称:

像许多研究生一样,我有一个大数据库,按下电脑按钮运行一个普通的统计分析,从来没有人教我深入思考(或根本没有)统计分析是如何工作的。stat 程序给出了一个被普遍认为“具有统计学意义”的数字。不幸的是,这几乎肯定是一个假阳性,因为我不理解在我应用它的环境中统计测试的局限性。审查这项工作的科学家也没有[……]我在没有学会科学推理的情况下就一头扎进了极其专业的科学研究。(然后我也因此得到了奖励,硕士学位)。

很容易想象,在工程和计算机科学等学位中,学生们倾向于基于规则的思维,积累事物如何组合的知识,以及解决逻辑问题的灵活性——毫无疑问,这是宝贵的技能。但是,在人类决策的世界里,这些技能能在多大程度上帮助他们呢?在这个世界里,问题往往没有直接的答案,或者存在缺失的事实,或者得出结论的时间有严格的限制。

如何在不确定性中衡量证据,形成立场并解释这是人文学科的领域,随着 STEM 浪潮的兴起,也出现了来自人文学科的反压力,要求平衡。一个很好的焦点可以在 STEAM 运动中找到,该运动提倡在 STEM 教育中增加“艺术”的“A ”,以培养更多以人为中心的思维。

但是这和数据分析有什么关系呢?数据的使用基本上不就是一个数学问题吗?不,这也是在实践中对分析所需要的东西仍然存在巨大误解的地方。最大的误解是,数据告诉我们的是客观事实,这个行业从坚持这一点中受益。在现实中,数据的使用存在不确定性和主观性(参见 Jonathan Choi 的讨论,这是一个很好的起点),有足够的空间来歪曲数据,以人为地支持一个议程,如《T4》《谎言实地指南》* (也以标题武器化的谎言)和 称之为扯淡等书所强调的。大机构中有经验的分析师可能都非常熟悉用支持性数据来支持声明的要求,或许有机会质疑它,但没有足够的时间这么做。*

当谈到人文学科在数据分析中可能扮演的角色时,我们通常会跳到交流方面,但另一个关键的倾向是质疑数据将如何被使用的心态(导致‘那又怎样?’)以及同样重要的数据来源。计算机科学中有一句名言垃圾进垃圾出,但是很少有分析师首先质疑数据的有效性,或者将数据的来源作为他们调查的主题。首先,数据收集的方式往往存在偏见或问题,这可能会改变我们对数据的解释,尽管这听起来可能很明显,但分析师往往无法严格检查他们的信息来源。

批判性思维是一种很难教授的思维习惯。操纵数据的技术,无论是通过代码还是其他工具,都更容易。

为什么数据分析师职位的招聘广告要求 STEM 学位

照片由本工程 RAEngUnsplash 上拍摄

从我的第一份工作开始,我得到的每一份分析工作都要求有数学、计算机科学、统计学、经济学之类的学位,而我没有。但是这从来没有阻碍过。

在澳大利亚,上大学的风气似乎比在英国更注重职业培训,同事们对我的学位背景感到惊讶。当我在 LinkedIn 上建立新的联系时,我很好奇要检查他们的教育背景,我想不出我在澳大利亚遇到的任何一个分析师没有 STEM 或商业相关学位。在英国,雇主对本科生的学习领域没有那么严格的规定,这里的背景更为混杂。(奇怪的是,软件开发人员似乎来自更古怪的背景)。

我不怀疑 STEM 学位为工作提供了一些实用的工具,并为获得第一份工作提供了帮助,但我希望其他人知道,这些学位中的大多数并不直接让毕业生具备工作能力。没有人教数学家如何评估营销活动的表现。没有人教计算机科学家如何在企业中进行 A/B 测试。他们在工作中学会了这些东西,雇主们寻找那些学得快、教得愉快、并且在进入角色后能与每个人相处融洽的毕业生。

对于数据分析至关重要的技术技能可以在工作中相当快地学习到足够有用的标准,职业发展很快就开始专注于构建领域知识(即,你所在的行业如何运作,最新趋势是什么)和提高“软技能”,而大学学位没有涵盖任何相关的深度。这并不是说 STEM 与这一角色无关——科学方法和某些细节(如对统计学的理解)非常有用——但我的观点是,它不会直接让你为这份工作做好准备,人文学科中的一些品质也是有用的,但被低估了。最终,是一个适合有范围的人的角色。

它可能有助于求职者理解,招聘广告中需要 STEM 的主要原因是,它们充当过滤器,有助于减少招聘人员必须审查的申请数量。由于任何人都可以自由申请公开招聘的职位,大公司可能会收到数百份申请,根本不可能审查每一份,因此他们需要一种方法来最大限度地增加在时限内找到优秀候选人的机会。

为此,预先增加 STEM 学位的要求是假设 STEM 申请者比人文学科申请者更适合这个职位。申请人池的假定组成可能如下所示。(这些分布是假设的,其目的是帮助将招聘经理使用的决策启发概念化。它的目的不是洞察人才库的规模和形状。)

作者图片

条形图代表了人文学科和 STEM 毕业生在初级数据分析师职位上取得成功的可能性分布。

我们假设一般的 STEM 毕业生比一般的人文毕业生有更高的成功可能性,但是毕业生的适合性在每个组中都是不同的,一些人文毕业生比许多 STEM 毕业生更适合。

尽管一些优秀的人文学科候选人处于分布的高端,但如果雇主考虑申请人的时间有限,那么只从绿色候选人中挑选将是一种合理的节省时间的措施。

作者图片

但是黄色分布右尾的例外人文毕业生呢?不幸的是,错过它们是使用过滤器的代价。他们被拒绝不是因为他们实际上不适合这个角色,而是因为他们不适合雇主的考虑考虑到他们的时间限制和他们所发挥的启发。(作为一个有趣的旁白,有人建议类似的过程是对电子邮件骗子糟糕的英语语法采取行动——那些不太可能上当的人会对糟糕的写作产生怀疑,并立即离开,从而最大限度地减少骗子在后续工作中浪费的时间,这些工作最终不会有回报。)

作者图片

所以,求职者们,要明白,未能通过申请的筛选阶段可能与你在该职位和职业中的潜力无关,而是与雇主考虑每份申请的实际限制有关。可悲的是,目前使用 STEM 的启发式方法是有效的,所以那些受害者需要另一条途径。

获得第一份分析工作

不管你的背景如何,如果“前门”被证明是困难的,这里有一些进入这个领域的技巧。

1.开始在线学习

我进入分析领域得益于书本上的一些自学。自那以后,行业对数据分析师的需求急剧膨胀,在线学习资源的数量也在不断增加。钻研一些知识不仅会给你在数据分析职业中直接有用的技能,还会测试你是否真的喜欢这个职业。

我向初学者推荐的免费在线资源是 Mode 关于 SQL 的优秀入门书。对于更广泛的付费选项,我建议潜入数据营的交互式 SQL 教程或谷歌在 Coursera 上的数据分析课程,这似乎是现在得到了很多关注

连续三个月每周给自己 10 个小时的学习时间,你将会很好地体会到工作中涉及的内容和一些有用的技能,以及你的动机的证据。

2.网络

在 LinkedIn 和 Twitter 上关注从事分析工作的分析机构和个人。不要犹豫向陌生人寻求建议,如果你大多得不到回应也不要气馁。他们发布的内容会让你对当前社区中的热门话题有一个很好的了解,并且通常会有免费网络研讨会和你可以参加的当地活动的链接。在 meetup.com 上查找您当地城市的分析活动(我推荐“数字分析星期三”或“数据与分析星期三”,这在世界各地的许多主要城市每月举行一次)。请你认识的人把你介绍给他们认识的分析师,并获得他们的建议。

3.通过其他角色输入分析

你很难找到数据没有用的业务功能。不要因为申请其他职位而觉得自己走错了路,一旦进入,就想办法接触数据。自愿清理一份电子表格,或者挑战自己,用数据来改善你的部分功能。或许你可以组织一次内部调查,并为你的团队制作一个可视化结果的包。与贵组织中负责数据分析的人员联系。晚上坚持参加网上课程。

结束语

我打算把这篇文章主要写给来自艺术界的求职者,事实上,你找到了写这篇文章的方法,这可能意味着你已经把这当成了你人生的一个方向。我希望我已经能够激励你去冒险,并说服你这可能是一个可行的选择,尽管所有的迹象都指向相反的方向。

对于其他人,尤其是商界人士,我希望这能让您思考一下在动态、快速发展的环境中进行数据分析所面临的挑战,以及更多批判性思维的必要性。

如何开始分析职业生涯

原文:https://towardsdatascience.com/how-to-start-a-career-in-analytics-808bf7b69c5c?source=collection_archive---------35-----------------------

洛伦佐·菲利波摄

我已经在分析行业工作了将近 6 年,我的职业生涯非常激动人心,并且还在不断发展。令人难以置信的是,越来越多的人对这个领域感兴趣。过去几个月,我们为那些希望在职业生涯中转行做分析的女性开办了一个为期 5 周的聚会班。我发现类似的问题不断出现:

  • 没学过相关的可以吗?
  • 我需要学习哪些技能?
  • 你正在使用的工具是什么?
  • 初级职位应该应聘小型、中型还是大型公司?
  • 我该从何说起呢?

是很多;想把你的职业换成不同的东西会让人不知所措。外面有很多信息,有些与你有关,有些则无关。你怎么知道?

我的个人经历

我将描述的只是我自己的旅程和与该领域其他人分享的经验。我目前在脸书工作,是一名数据工程师,在此之前,我是一名商业智能分析师和商业智能顾问。

我学的是机械工程,一直热爱数学。我小时候想成为一名数学老师,但我的分数很高,所以我决定学工程。老实说,我从来不喜欢它,在我学业结束时,我在寻找一些不同的东西。我毕业于希腊严重的经济危机时期(2012 年),所以当时市场上没有多少工作。我在学习的同时做了一些学生工作,然后开始攻读博士学位。就在那时,我爱上了数据模式。我发现通过数据探索话题和行为很有意思。当时开始自学东西,主要是 Python。我记得这非常令人沮丧,我对编程失去了希望。还有,我记得我从来不能专注于一件事(我的博士学位)。我有十个不同的想法总是在我的脑海中运行,这将导致十个以上的想法。就像一只蝴蝶,我的心会被它看到的每一朵花分心。以至于我完全不知道自己在做什么,想解决什么。

:博士需要大量的纪律和指导。我意识到我是一个喜欢一心多用的人。这可能是我的副业,但不是我的主业。我还意识到,学术生涯可能是一个非常漫长的旅程,这使我对我选择的道路失去了信心。

总之,两年半过去了。我写论文,参加会议,学习大量的研究,但是我仍然没有像我希望的那样进步。然后我得到了一个在柏林进行为期三个月的项目的机会,在那里我将为一个非政府组织做分析研究。听起来很刺激。

我确实去了。我很快就学到了很多东西。

第一课

三个月之内,我的编码技能有了显著的提高。当你周围的人可以给你看东西,你可以问问题,而不是自己一个人研究 aaaaaall 时,情况会有很大的不同。

我发现自己喜欢柏林,享受这条新的道路。有同事,有工作,看到事情进展得更快。我决定试着找一份工作,如果可能的话,延长我的旅程。

我申请了初级分析师/初级 BI 分析师职位,这 3 个月的经验是我唯一的工作经验。

我发了很多申请,并被两家创业公司接受面试。我得到了第一家回复的公司的工作。第二次,我参加了一次面试,但已经得到了前一次的工作邀请。

你可能认为这是运气,但我是一个非常勤奋的人,学得很快。不知何故,我知道我想进入这个领域,我对数学和模式的热爱帮助了我。当我接受采访时,我努力学习 SQL,并做了大量研究来了解分析是如何工作的。此外,即使我当时不知道,我在博士和研究中的经验也帮助我以正确的方式处理问题。

第二课:

我没有专注于我所知道的工具,但是我专注于我的分析技能和热情。当时,我不知道可视化工具,也不知道 SQL 细节;我曾经用过的只是一些 python 库。然而,我太兴奋了,对正在发生的事情以及数据如何帮助决策真正感兴趣。我问了正确的问题,只是因为我喜欢思考如何用数据回答问题的过程。

对产品的理解是我的强项之一。也不一定是你的。但是如果你想开始一个分析职业,你确实需要发展这个技能。这是帮助你前进的技能之一。

你如何看待一个产品?以及数据如何帮助你。

工具/技术

你从哪里开始?你需要学习什么?

SQL

这里我最大的建议就是学习 SQL。需求量非常大。而且很简单。比 Python & R 更容易,你会在很多分析职位上需要它。

一个开始的方法是 w3schools

你可以随时下载一些公共数据集来玩。还有在线编辑器,在那里你可以探索如何处理数据

(英)可视化(= visualization)

有大量的观想工具,对于一个初级角色来说,你不可能知道很多这样的工具。但是有很多免费的试用版,你可以下载这些工具并试用。

我见过的最流行的有:PowerBI,Tableau,Looker。

Tableau 有很棒的教程,你可以玩玩在线版本,也可以在在线社区发帖。观看他们如何创造观想,并从我最喜欢的观想传说中获得灵感。

建立你的分析直觉

我这里没有关于在线链接的任何建议,但是在线研究并理解数据、模式&它们如何在不同的情况下帮助你。如果你已经在一家公司工作,了解数据如何帮助日常决策。将这些想法融入你的思考过程。

没学过相关的可以吗?

是的。我认识一些人,他们从哲学、音乐变成了分析师或软件工程师。这不是一个容易的转变,但是如果你喜欢,如果你喜欢进入数字,你可以做到。一开始需要努力,有很多新的概念。但是这是可行的,并且正在发生。市场上的分析课程越来越多,需求也越来越大。

初级职位应该应聘小型、中型还是大型公司?

中型或大型公司会雇用更多的初级员工,并对他们进行更多的投资。这可能是你最好的机会了。大的创业公司也想要有激情的人。你需要用你的热情说服一家公司,然后你就加入了。一旦有了第一份工作,就只能成长。

你的人际网络也可能充满了能给你推荐或见解的人。伸手向人们询问。

我朋友的建议也是:“首先申请你不想去的公司”。和他们面谈,了解情况,从你的错误中学习。当你在这个过程中有了更多的经验,申请你想工作的公司。

我认为这是一个很好的建议。

另一种方法也可以是看看你现有的公司,换个角色或者获得你想要的技能。

我最大的建议是尝试失败。失败是获得第二次机会的途径。不要认为你失败了,要理解发生了什么,并从中吸取教训。然后多问问题,再试一次。我们好奇的头脑总能给出新的观点和方法。你的背景没有你的激情和想法重要。千万不要低估这一点!

如何在 2021 年开始一个数据科学项目样板?

原文:https://towardsdatascience.com/how-to-start-a-data-science-project-boilerplate-in-2021-33d81393e50?source=collection_archive---------22-----------------------

在本文中,我想展示我如何准备数据科学项目的三个步骤。

艾通过作者创造艺术。更多例子上https://www.instagram.com/art_and_ai/**;受香波特* 的启发,https://unsplash.com/photos/bHlZX1D4I8g*

目录

为什么

我开始的每个数据科学项目都有不同的结果,但开始总是一样的。在本文中,我想展示我如何准备数据科学项目的三个步骤。它涵盖了以下主要领域

  • 应对虚拟环境
  • 管理依赖性和
  • 正确跟踪 jupyter 笔记本的变化

我想涵盖这些方面,因为我没有找到一个合适的样板为我这样做。我知道库克科特项目。然而,我不是在寻找一个文件夹结构,因为这很容易适应。我在寻找自动化步骤,确保我在开发过程中保持适当的标准。

以下网址提供了简单的样板文件设置:

https://github.com/Createdd/data_science_boilerplate▶️

它专注于在 jupyter 笔记本电脑中开发概念验证,而不是生产。如果你也想要一个生产设置,请告诉我。

1.创建项目手续

本地设置步骤。我用的是 Conda 环境和 Git + Github。按照以下步骤来做:

  1. 创建本地文件夹mkdir NAME
  2. NAME在 Github 上创建一个新的存储库
  3. 创造康达环境conda create --name NAME python=3.7
  4. 在 jupyter 中注册新环境ipython kernel install --name NAME--user
  5. 激活康达环境conda activate PATH_TO_ENVIRONMENT
  6. 创建 git repo git init
  7. 连接到 Github repo。添加自述文件,提交并
*git remote add origin URL_TO_GIT_REPO
git branch -M main
git push -u origin main*

2.依赖性管理

我用 Python 开发了很长时间,仍然在改进依赖管理设置。这是我目前的做法。

Pip 没有提供自己的适当的依赖性管理,因为

  • pip 冻结的需求文件不提供任何结构
  • 安装的版本没有固定,这导致每次安装都不一样
  • 没有依赖关系解析

还有一些有用的附加库:

以更好的方式安装依赖项

我使用一个自动化的工作流程来处理依赖列表和编译。

  • 将使用固定的子依赖关系更新需求文件,并创建需求文件。

因此,我们需要用

*python -m pip install pip-tools*

来使用它,而不是编写常规的pip install jupyter jupytext

我们通过以下方式创建一个requirements_dev.in文件

*touch requirements_dev.in*

然后我们打开这个文件,添加我们想要添加的库。我们将在整个存储库中遵循这种风格!

让我们从依赖关系开始

  • jupyter 笔记本
  • jupytext(用于转换。ipynb 文件)
  • pipdeptree(用于显示依赖关系树)
  • when-changed(编译和安装包的监视程序)

那就跑

*pip-compile requirements_dev.in
pip install -r requirements_dev.txt*

这会生成一个格式很好的requirements_dev.txt文件,然后安装所有的东西

良好的排序和显示依赖关系;作者图片

所以每次我们添加一个库时,我们都需要运行编译命令。这也是一个可以自动化的步骤。

我们将使用 when-changed 库。因为我们已经用以前的列表安装了它。我们现在可以做以下事情:

*when-changed requirements_dev.in pip-compile requirements_dev.in;pip install -r requirements_dev.txt*

现在,每次您添加一个包并保存到.in文件时,编译和安装命令都会被触发。

捆绑在单个启动脚本中

为 jupyter notebook 和 change watcher 设置自己的终端窗口可能会很烦人。一种解决方案是将命令捆绑在自己的 bash 脚本中。

*touch startup.sh*

然后插入正在执行的命令,比如

*#!/bin/bashjupyter notebook &
when-changed requirements_dev.in pip-compile requirements_dev.in &
when-changed requirements_dev.in pip install -r requirements_dev.txt*

然后使文件可执行(在 mac 上)并启动脚本。

*chmod +x startup.shtbash startup.sh*

现在两个命令在同一个终端窗口中并行运行。

运行捆绑包脚本;作者图片

3.正确跟踪 jupyter 笔记本的变化

转换为 python 文件

我们将使用 jupytext 将.ipynb文件转换成.py文件。这允许正确跟踪 Git 中的变化。

我们已经在前面的步骤中安装了软件包。现在我们只需要添加一个 githook 来自动完成转换。

为 jupytext 安装 githook

.git/hooks/pre-commit中设置一个钩子,用于正确跟踪 git 中的笔记本变化;

*touch .git/hooks/pre-commit
code  .git/hooks/pre-commit*

把这个复制到文件里

*#!/bin/sh
# For every ipynb file in the git index, add a Python representation
#jupytext --from ipynb --to py:light --pre-commit
jupytext --from ipynb --to jupytext_conversion//py:light --pre-commit*

之后让钩子可执行(在 mac 上)

*chmod +x .git/hooks/pre-commit*

现在,在提交对 jupyter 笔记本的更改之前,该文件被转换为 python 文件,并且这些更改将完美地反映出来:

正确跟踪 ipynb 变化;作者图片

以下网址提供了简单的样板文件设置:

https://github.com/Createdd/data_science_boilerplate▶️

放弃

我与本文中使用的任何服务都没有关联。

我不认为自己是专家。我不是博主什么的。我只是记录工作流程。因此,这些内容并不代表我任何作品的质量,也不完全反映我对事物的看法。

我总是乐于听取建设性的意见以及如何改进。

这写于 21.02.2021 。我无法监控我的所有文章。当你在时间流逝后读到这篇文章时,提示已经过时,流程已经改变,这种可能性很大。

关于

丹尼尔是一名艺术家、企业家、软件开发人员和商业法毕业生。他的知识和兴趣目前围绕着编程机器学习应用程序及其所有相关方面。从本质上说,他认为自己是复杂环境的问题解决者,这在他的各种项目中都有所体现。

连接到:

直接:

如何开始成为一个主动的学习者?

原文:https://towardsdatascience.com/how-to-start-being-an-active-learner-8d311d68fb70?source=collection_archive---------20-----------------------

计算机视觉主动学习简介

照片由莱昂Unsplash 上拍摄

深度学习(DL)模型是计算机视觉中许多任务最常用的方法。DL 通过使用大量的标记数据取得了巨大的成果。然而,随着计算机视觉任务变得更加复杂,DL 网络变得更大,参数数量增加,这需要更多的标记数据来训练网络。

为什么这是个问题?

  • 标注周期 —要标注的数据集越大→价格越高+完成所有标注的时间越长。
  • 训练周期 —更大的训练数据集→更长的训练时间。

主动学习是来救援的!

DL 中主动学习的目标是用更少的数据——更便宜的标注预算和更短的训练周期——训练一个模型,并获得相似的性能。

在这篇文章中,我将描述什么是主动学习,分享一些常见的方法,它们的利弊,并添加一些个人见解。

图 1-绿线 —相同数据量的准确度更高。橙色线— 数据量更少时精度水平相同。(图片由作者创作)

什么是主动学习?主动学习是一个连续的训练管道,它利用不同的方法(如下所述)来选择下一个要注释的样本。选择过程是知情的,而不是通常所做的随机选择过程(图 3 (b))。

图 2 — 主动学习通用管道[8]

我们怎样才能做到呢?主动学习方法旨在从我们的未标记图像集中选择最具信息量和代表性的图像子集。这样,我们可以在使用较小数据集的同时获得更高的模型精度。

主动学习方法:

主动学习方法可以分为三大类[1]:

  1. 不确定性方法 —定义和测量不确定性的数量以选择数据点(图 3 (c))。
  2. 多样性方法 —选择代表未标记池整体分布的多样性数据点(图 3 (d))。
  3. 预期模型变化 —选择会导致当前模型参数或输出最大变化的点,如果它们的标签已知的话。

图 3- 采样策略【4】。蓝点和红点代表不同类别的数据。

预期模型变化方法,a 成功应用于小模型,但对于最近的深度网络在计算上不切实际。因此,我们将着重于前两类。

根据我的经验,主动学习方法也可以分为特定任务型和不特定任务型。如果我有一个包含几个任务的管道,我可能更喜欢找到一个任务不可知的方法,用于所有的模型。相比之下,我可能已经找到了一个很好的方法,针对某个特定的任务,极大地提高了我的结果。在这种情况下,维护几种不同的方法可能是值得的。

不确定性方法:

不确定性方法旨在选择模型最不确定其输出的图像。因此,大多数不确定性方法是依赖于模型的,需要针对每个新模型进行训练或调整。

直接在输出上测量不确定性(特定于任务和模型)

从输出中直接测量不确定性的最简单方法是在推断中使用一个下降图层(也称为蒙特卡洛下降)。在推断中使用丢弃,我们的预测不再是确定性的,而是取决于随机丢弃的节点。因此,可以通过计算 T 个不同预测的方差来估计图像输出的不确定性(更多信息参见[9],例如关于分割任务参见[6])。

结合在网络中的不确定性测量(任务特定和任务不可知)

获得不确定性度量的不同方法是通过添加额外的并行分支将不确定性预测并入网络。

接下来,我将描述使用这种方法的两种方法,一种方法是特定于任务的,另一种是任务不可知的。

特定任务[1】—特定于图像分割任务。关注边界框和遮罩预测中的不确定性。

两个平行分支连接到网络的检测头和掩模头(图 4-蓝色网络分支)。每个分支的输出是预测预测边界框和目标框的交集(IoU)以及预测遮罩和目标遮罩的 IoU 的值。最终预测得分是 IoU 预测和分类得分的组合。分数越低,不确定性越高。

图 4— 架构示意图。蓝色表示 IoU 预测的附加分支和训练的附加损失[1]

任务无关[2】—可以添加到我们使用的任何现有网络中。目标是学会预测网络的损耗。损耗越高,网络输出越不确定。

图 5【2】

不确定性方法的收获

  • 优点:易于实现,可以很容易地插入到现有模型中。
  • 缺点:可能包含多余的数据点。深度学习在相似图像上往往是不确定的。
  • 个人见解:我发现不确定性方法很容易理解,无论是从算法方面还是从实现方面。

多样性方法:

多样性方法旨在从我们的非注释集中选择一个子集,这样它将代表我们的数据分布。与可能导致冗余实例的不确定性方法相比,多样性方法试图将选择的数据分散到整个分布中。

多样性方法测量图像特征之间的相似性,并输出未注释图像的子集,以使其代表整个数据分布,重点是对不同情况进行采样。

那么我们如何创建这些图像特征呢?

一种直接的方法是测量从卷积神经网络提取的特征之间的距离。然后,将选择与许多其他无注释图像相似并覆盖不同情况的图像(更多信息见[5])。

一种不同的方式是使用变分自动编码器并学习到具有期望概率分布的潜在空间的映射函数。然后,对于新的一批未标注数据,创建一个子集,其到潜在空间的映射分布类似于已学习的分布(更多信息见[3])。

多样性方法的收获

  • 优点:独立于模型和任务。可以用来发现罕见的情况,并处理阶级不平衡。
  • 缺点:可能更难理解,需要更深入的理论理解
  • 个人见解:我喜欢主动学习和具体任务之间的耦合消除。

享受两个世界——使用两种方法

可以看出,每一个类别都有自己的优点和缺点。为什么不把它们结合起来,一起享受呢?在下一篇文章中,我将详细阐述如何利用这两种方法的优点来获得更好的结果。现在,你可以看看[3]和[6]并开始成为一个积极的学习者!

参考资料:

[1] 通过得分预测进行实例分割的半监督主动学习

[2] 主动学习的学习损失

[3] 基于贝叶斯样本查询的分词主动学习

[4] 学会抽样:一个主动的学习框架

[5] 提示性标注:生物医学图像分割的深度主动学习框架

[6] 用于黑色素瘤分割的成本有效的主动学习

[7] 作为贝叶斯近似的辍学:表示深度学习中的模型不确定性

[8] 贝叶斯层定位与深度贝叶斯主动学习中模型不确定性的相关性

[9] 作为贝叶斯近似的漏失:表示深度学习中的模型不确定性

如何开始为开源项目做贡献

原文:https://towardsdatascience.com/how-to-start-contributing-to-open-source-projects-41fcfb654b2e?source=collection_archive---------9-----------------------

开始往往是成功的一半

图片由来自 PixabayMarkus Winkler 拍摄

为开源项目做贡献可能是了解您感兴趣的技术、为您最喜欢的工具的发展做贡献以及向未来的员工展示您的能力的最佳方式。

此外,您还可以加入一个活跃的社区,结识有共同兴趣和想法的开发人员,并让您的名字在该领域广为人知。

如何在不污染系统的情况下创建开发环境,并在隔离的便携式工作区中通过第一批测试?

然而,开始并不容易,这是一个关键的步骤,如果做得不好,可能会让任何人气馁。克隆项目、设置环境、构建二进制文件以及通过测试并不总是简单明了的。

这个故事提供了一些想法,关于如何开始一个新的开源项目,创建一个开发环境而不污染我们的系统,并在一个隔离的便携式工作空间中通过第一次测试。

Learning Rate 是一份时事通讯,面向那些对 AI 和 MLOps 世界感到好奇的人。你会在每周五收到我关于最新人工智能新闻和文章的更新和想法。订阅这里

连续的例子

本文使用了一个运行的例子,一个简单的用例,它将使一切变得透明;我们将克隆一个名为 Kale 的开源项目,设置工作环境,并运行我们的第一个测试。

Kale 是一个开源项目,它简化了数据科学家使用 Kubeflow 和 Kubernetes 的体验。

你可以把 Kale 想象成你在 Kubeflow 上的机器学习(ML)项目指挥者;作为数据科学家,我们可以在我们最喜欢的 JupyterLab 环境中工作,无需任何代码更改,就可以在 Kubeflow 和 Kubernetes 上运行 ML 管道,此外,我们可以运行超参数优化实验,将我们的模型作为可扩展的 API,创建 AutoML 项目,并毫不费力地分发我们的深度学习(DL)训练过程。

如果您有兴趣了解更多关于羽衣甘蓝和 Kubeflow 的信息,请阅读以下文章:

既然我们已经看到了羽衣甘蓝是什么,以及它如何将我们的 ML 实验提高到一个新的水平,让我们假设我们愿意积极参与它的开发。怎么才能开始呢?

设置开发环境

当然,第一步是克隆项目:

git clone [https://github.com/kubeflow-kale/kale.git](https://github.com/kubeflow-kale/kale.git)

Kale 是一个 JupyterLab 扩展和一个 Python 库。我更熟悉 Python,所以我将在这篇文章中介绍如何开始为 Kale 的后端 Python 库做贡献。

在克隆项目并在 Visual Studio 代码中打开它之后,您将会看到:

羽衣甘蓝项目——作者图片

然而,我们对此无能为力;最重要的是,我们没有安装必要的库。那我们该怎么办?我们应该把 Kale 需要的所有东西直接安装到我们的系统中吗?我们是否应该创建一个单独的虚拟环境,并将它们安装在那里?不,不!

首先,我们来看看羽衣甘蓝需要什么。一些项目带有我们可以使用的requirements.txt文件,其他项目带有用于 conda 的environment.yaml文件,或者甚至是简化一切的docker-compose.yaml文件。

羽衣甘蓝这些都没有,就从简单的开始吧;让我们创建一个requirements.txt文件。打开backend文件夹中的setup.py文件,复制install_requires列表中的所有库,粘贴到一个新文件中,命名为requirements.txt。它应该是这样的:

kfp
autopep8>=1.4<1.5
astor>=0.8.1
nbformat>=4.4<5.0
networkx>=2.3<3.0
jinja2>=2.10<3.0
graphviz>=0.13<1.0
pyflakes>=2.1.1
dill>=0.3<0.4
IPython>=7.6.0
jupyter-client>=5.3.4
jupyter-core>=4.6.0
nbconvert>=5.6.1<6.0.0
ipykernel>=5.1.4
notebook>=6.0.0
packaging>20
ml_metadata==0.24.0
progress>=1.5
kfserving>=0.4.0<0.5.0
kubernetes<12.0.0

请注意,将来依赖关系的版本可能会改变。

我们现在可以创建一个安装了这些依赖项的 Docker 映像,并将 Kale 项目复制到其中,这样我们就可以使用它了。但是这看起来工作量太大了。让我们自动化吧!

首先,我们需要为 VS 代码安装[remote-containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)扩展。您可以在市场中搜索它,然后单击安装。然后,点击右下方的Open a Remote Window选项,选择Add development container configuration files选项。

按照向导,选择一个最近的 Python 3 环境(所有高于3.5的环境应该都可以),如果您也想在 JupyterLab 扩展上工作,安装 NodeJS。最后,点击 OK,一个名为.devcontainer的新文件夹将会出现在你的项目的根文件夹中。

该文件夹包含两个文件:

  • 一个devcontainer.json文件来保存您的配置选项
  • 建立你的形象

一切都为你准备好了,但是我们需要对Dockerfile做一个小小的修改。打开它,取消安装您的requirements.txt文件的注释行:

COPY requirements.txt /tmp/pip-tmp/
RUN pip3 --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \
&& rm -rf /tmp/pip-tmp

最后,再次点击右下方的Open a Remote Window选项,并选择Reopen in container。VS 代码将构建您的映像,启动一个容器,并挂载您启动 Kale 所需的文件。就这么简单!

如果您想更进一步,您可以更改您的devcontainer.json来安装您想要的 VS 代码扩展,并更改容器内的 VS 代码设置。例如,我倾向于使用Pylance作为我的 Python 语言服务器。如果你想了解更多关于Pylance的信息,请阅读下面的故事:

我的 Kale 的devcontainer.json配置文件如下所示:

如果你想了解更多关于 VS 代码[remote-containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)扩展的信息,请阅读下面的故事:

</5-visual-studio-code-extensions-for-data-scientists-937487b987c0>

运行您的第一个测试

了解一个新项目的最好方法是通过 VS 代码可视化调试器来跟踪它的逻辑。但是你得先知道跑什么。如何触发调试器?为此,您可以阅读文档或直接询问维护人员。在我们的例子中,我们应该从相关文件夹中运行以下命令:

cli.py --nb /kale/backend/kale/tests/assets/notebooks/pipeline.ipynb

但是如何通过可视化调试器来设置断点并遵循逻辑呢?让我们创建一个launch.json配置文件。

转到 visual debugger 窗格,点击create a launch.json file。然后,复制以下几行:

这个文件做三件事:

  1. 在当前活动的.py文件上启动调试器
  2. 传递正确的参数
  3. 设置PYTHONPATH

导航到/backend/kale/cli.py,从这个文件运行调试器。设置您的断点并遵循逻辑!你完了!

结论

为开源项目做贡献可能是了解我们正在使用的技术、为我们最喜欢的工具的发展做贡献以及向未来的员工展示我们的能力的最佳方式。

此外,我们可以参与到一个活跃的社区中,与有共同兴趣和想法的开发人员会面,并让我们的名字在该领域为人所知。

然而,开始并不总是那么容易。这个故事使用了一个运行示例来设置 Kale 的工作开发环境,Kale 是一个开源项目,它简化了数据科学家使用 Kubeflow 和 Kubernetes 的体验。

这是我处理新项目的方式。如果你有任何关于如何丰富这个过程的想法,或者你遵循的任何不同的技术来促进设置工作流,请在评论区留下它们!

关于作者

我叫 Dimitris Poulopoulos ,是一名为 Arrikto 工作的机器学习工程师。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲央行、经合组织和宜家等主要客户设计和实施过人工智能和软件解决方案。

如果你有兴趣阅读更多关于机器学习、深度学习、数据科学和数据操作的帖子,请关注我的 MediumLinkedIn 或 Twitter 上的 @james2pl

所表达的观点仅代表我个人,并不代表我的雇主的观点或意见。

如何开始对音乐实施机器学习

原文:https://towardsdatascience.com/how-to-start-implementing-machine-learning-to-music-4bd2edccce1f?source=collection_archive---------10-----------------------

讨论两个丰富领域的交集。

阿列克谢·鲁班在 Unsplash 上的照片

介绍

对于那些从事数据科学和机器学习的人来说,他们未来职业生涯中最重要的决定之一是追求哪个领域的专业并成为该领域的专家。一些最突出的领域是自然语言处理(NLP)、计算机视觉和量化交易。这些领域正在呈指数级增长,其中的新技术似乎每天都在发展。

然而,虽然不是机器学习最赚钱的应用(就当前的盈利能力而言),但音乐领域已经发展了巨大的洞察力和显著的进步,其中大部分是由于各种机器学习和深度学习应用。

在这篇文章中,我的目标是概述机器学习在音乐应用中的两个主要子领域,进入该领域所需的技能,最佳初学者项目(在我看来)和当前的艺术应用状态。

音乐机器学习需要什么?

音乐机器学习主要有两个子领域。第一个是音乐信息检索(MIR ),第二个是生成音乐。这两个子领域并不排斥,几乎每一个与音乐机器学习相关的应用和技术都需要 MIR。然而,一般来说,这两个子字段对整个字段进行了很好的分类。

关于音乐信息检索:

MIR 是计算机科学、统计学、音乐学和数字信号处理的交叉领域。所有这些任务结合起来形成了 MIR,因为音乐中的信息并不像看起来那样简单。

表面上有简单的信息,可以从你喜欢的歌曲中理解(即速度、音色、响度等。)这些音乐的表示是相对低级的,并且更容易跨不同流派和风格的歌曲进行计算。然而,能够制定更高层次的解释(或人类更经常感知的概念),如情绪和灵感,则更难确定。这就是利用低级统计的多元函数可以发挥作用的地方,以便更好地了解我们想要建模的内容。然而,重要的是要知道,人类从音乐中带走的许多概念至今无法完美建模,因为音乐本身之外有太多的因素在它的感知中发挥作用。

尽管孤立的 MIR 最常见的使用案例是基于音乐的推荐系统,但 MIR 本身是机器学习的每个基于音乐的应用的基础。

关于再生音乐:

至于生成音乐,名字就比较简单了。这个子领域着眼于将深度学习用于广泛的生成任务,无论是产生新的声音还是全新的歌曲。尽管在音乐机器学习中是一个“独立”的领域,它仍然大量使用 MIR,原因很明显。为了生成音乐,围绕这一代的信息应该是最高质量的。

然而,声音的产生并不一定要严格地以新音乐或声音隔离的形式进行。生成音乐还包括将一种声音转换为另一种声音的行为,甚至能够通过去噪或在其上添加新音乐来重建它,以给歌曲添加更多层,这两种应用我们将在后面看到。从本质上讲,音乐的产生并不等于自动化,有许多生产性的途径来利用音乐的产生,这将在后面讨论。

如果你感兴趣,我已经写了关于完全自动化音乐的可能含义,你可以阅读。

音乐机器学习需要哪些技能?

可以说,最重要的技能是数字信号处理(DSP)知识。DSP 是电子工程中的一个领域,它接收物理信号,如我们发出的声音,并将其转换为数字格式,以便对其进行数学处理和转换。

理解 DSP 在音乐机器学习中的作用可能是相当容易的。许多 ML 工程师习惯于通过规范化或标准化对数据进行预处理。然而,对于那些想要从事音乐工作(或者更一般地基于音频)的人来说,机器学习有一个稍微不同的障碍要克服。虽然归一化和标准化在该领域中具有一些效用,但是理解 DSP 的人将知道从波形到频谱图的变换是预处理的确定方法。你决定使用什么样的声谱图取决于问题本身,这就是你对该领域的理解和你的智慧发挥作用的地方。

如果你想开始学习 DSP,我有一系列专门从数据科学角度学习 DSP 的文章,叫做从音频中学习。您可以在这里找到 GitHub 笔记本资源库的链接,也可以在 README 中找到 Medium 文章本身的链接。

*https://github.com/theadamsabra/LearningfromAudio

注: 最明显的技能是机器学习和编程,我不打算过多地钻研这个。然而,我将在下面的 当前最先进的应用 章节中概述一些今天使用的最重要和最有用的模型。*

面向初学者的项目

对于这个领域的新手来说,最好的第一个项目是乐器或流派分类。乐器/流派分类是一种分类形式,它利用音频的结构并确定其中的乐器或流派。

我在这个项目中交替使用乐器和流派,只是因为总体学习体验是相同的,但是在你决定如何处理音频本身时会有细微的差异,只是因为你可能会寻找不同的模式/结构,各种频谱图可以返回给你。你选择哪一个并不重要,所以对你来说最好的选择是选择你最感兴趣的项目。

一旦你建立了这个分类项目,并取得了良好的结果,你就已经完全掌握了基本原理。从那里,你可以开始阅读关于各种先进应用的文献来着手解决。

乐器或流派分类数据集

各种先进的应用

音乐源分离

我把这个放在第一位,不仅因为这是我目前的论文,而且我还发现这个应用程序非常有用。音乐源分离是一项任务,在这项任务中,机器学习模型学习特定声音的结构,提取它,并将其与它混合的其他声音隔离开来。无论是创作一首歌曲的阿卡贝拉版本,还是提取你最喜欢的低音线,都可以通过神经网络以接近/快于实时的速度完成。

此用例的当前艺术应用状态是 Deezer 的 Spleeter。Spleeter 是一个双向 LSTM,它在 MUSDB 数据集上训练,MUSDB 数据集专门用于音乐源分离。

Deezer:

*https://github.com/deezer/spleeter

音乐数据库:

https://sigsep.github.io/datasets/musdb.html

实时伴奏

实时伴奏是处理音乐创作中的创意的更有趣的问题之一。这个问题旨在解决的核心概念是创建一个能够与另一首歌曲一起演奏乐器的生成网络。让我们举个例子来更好地理解这一点。

假设你决定教网络通过钢琴演奏爵士乐( 旁注: 这是非常不可能的,因为它太广泛了。在流派中磨砺将显著提高模型的性能。)当您在没有钢琴的情况下输入音乐时,它会与其他乐器一起实时演奏,创造出自己的演奏效果!

这一领域有许多先进的应用,因此我将在下面列出几个:

MuseGAN:用于符号音乐生成和伴奏的多轨道顺序生成对抗网络:

https://paperswithcode.com/paper/musegan-multi-track-sequential-generative

音乐渐变:通过低级特征建模基于高级特征的可控音乐生成:

https://paperswithcode.com/paper/music-fadernets-controllable-music-generation

自动音乐转录

音乐自动转录的问题,顾名思义,目的是转录任何一段音乐。这对那些演奏乐器的人来说非常有用。人们不仅可以输入他们最喜欢的歌曲,并随时随地播放乐谱,而且同一首歌曲还可以转换成 MIDI 文件,以便在计算机上进行编辑。对于那些不知道的人来说,MIDI 代表乐器数字接口。根据 MIDI 协会的说法,它是一种行业标准的音乐技术协议,连接来自许多不同公司的数字乐器、计算机、平板电脑和智能手机。

因此,这些网络不仅允许为几乎任何歌曲的进一步练习和研究而创作乐谱,而且还允许用于操纵、灵感以及新歌创作的数字等价物。

类似于实时伴奏问题,有许多先进的解决方案。这里有几个例子:

通过回归开始和偏移时间用踏板进行高分辨率钢琴转录:

https://cs.paperswithcode.com/paper/high-resolution-piano-transcription-with-1

走向多乐器鼓转录:

https://paperswithcode.com/paper/towards-multi-instrument-drum-transcription

这样的例子不胜枚举!

如果这三个应用程序听起来对你都不太感兴趣,但你仍然想进一步研究 MIR 和机器学习的可能性,最好的资源是国际音乐信息检索协会(ISMIR。)

https://ismir.net/

自 2000 年以来举行的所有会议以及提交的会议记录和文件都可以在网站上找到。虽然你们中的大多数人可能会阅读该领域最近几年的资料,但如果你决定继续在该领域工作,这个年度会议仍然是一个值得关注的问题。

最后的想法

即使通读了这篇文章,重要的是要知道所有这些信息仍然只是皮毛。还有更多的问题有待发现,不仅仅是迭代当前的 SOTA 解,还有这个领域的未来。

希望这篇文章能为你在这个引人注目的领域开始职业生涯打下基础。参与其中的人越多越好。*

如何免费开始机器学习

原文:https://towardsdatascience.com/how-to-start-with-machine-learning-for-free-483c1974c4b6?source=collection_archive---------7-----------------------

这个领域提供有竞争力的薪水,既有挑战性又有趣。最棒的是你可以免费学习。

Unsplash 上的 Roméo A. 拍摄的照片

人们对机器学习领域越来越感兴趣。对于深度学习和神经网络的大肆宣传,我并不感到惊讶。除此之外,这个领域提供有竞争力的薪水,既有挑战性又有趣。

我假设你是这个领域的新手,不知道从哪里开始。

我最常被问到的问题是:如何从机器学习开始?我的答案总是一样的,因此我写了这篇文章来指导你的旅程。

我的建议是:从免费内容开始,因为网上有很多很好的资源。甚至常春藤盟校也免费提供在线课程。

通过学习这些资源,你将了解机器学习是否适合你

不要马上开始花钱上昂贵的课程。把付费课程当成一门专业。幸运的是,你可以免费学习强大的机器学习基础。

通过阅读本文,你将了解哪些是值得学习的优秀电子书和课程:

  • 用 Python 编程
  • 熊猫的数据分析
  • 从数据科学和机器学习开始

我也分享几个如何高效学习机器学习的小技巧。

介绍

照片由蒂姆·莫斯霍尔德Unsplash 上拍摄

在我们开始之前,我想给你一些建议。

不要太深入任何一本书或课程。当你开始一个新的领域时,了解这个领域的广度是很重要的。

同时从多本书和课程中学习。这样你会听到从不同角度对复杂概念的解释。

练习也很重要。没有任何实践经验不要太深入理论。泰坦尼克号——从灾难中学习机器是一个很好的起点。看看代码和讨论部分。

概念都不背,学习还有什么意义?一个很好的记忆方法是使用 Anki——一个使用间隔重复的应用程序。

编程电子书

面向专业人士的 Python 注释

作者:堆栈溢出的人

专业人士阅读 Python 笔记(图片由作者制作)

这本 Python 书籍是我见过的最完整的 Python 指南之一。它是由栈溢出文档编译的,内容是由栈溢出的人编写的。

这本书广泛涵盖了你(很可能)会用到的 Python 的每个领域。我建议你不要从头到尾读一遍,而是把它作为你想进一步了解的某个主题的参考。

如果你不精通 Python,我推荐你深入阅读这本书。这本书有 816 页,提供的信息足以让你精通 Python。

我为什么推荐这本书?因为你可以随时重温。它可以作为你旅途中的参考。

学习熊猫

作者:埃尔南·罗哈斯

照片由斯坦 YUnsplash 上拍摄

Pandas 成为 Python 中数据科学的事实上的标准。学习熊猫这本书是用 Jupyter 笔记本写的,并附有文字。

它从如何创建数据框架的基本课程开始,以创建 Excel 报表结束。它的目标是那些仍在熟悉熊猫的初级数据科学家。

要了解更多先进的熊猫技巧,我建议你查看我的熊猫系列进行数据分析:

https://medium.com/@romanorac/pandas-data-analysis-series-b8cec5b38b22

机器学习电子书

Python 数据科学手册

作者:杰克·范德普拉斯

Viktor Forgacs 在 Unsplash 上拍摄的照片

Python 数据科学手册面向初级数据科学家。它展示了如何使用最重要的工具,包括 IPython、NumPy、Pandas、Matplotlib、Scikit-Learn 和许多其他工具。这本书非常适合解决日常问题,例如清理、操作和转换数据,或者构建机器学习模型。

可解释的机器学习

副标题:让黑盒模型变得可解释的指南
作者:克里斯托夫·莫尔纳尔

卢卡斯·本杰明在 Unsplash 上的照片

这本书使用了“支付你想要的价格策略”,所以从技术上来说它不是免费的。

可解释机器学习专注于表格数据(也称为关系或结构化数据)的 ML 模型,较少关注计算机视觉和自然语言处理任务。

这本书推荐给机器学习从业者、数据科学家、统计学家和其他任何对让机器学习模型可解释感兴趣的人。它详细说明了如何为机器学习项目选择和应用最佳解释方法。

免费在线课程

机器学习课程

大学:哥伦比亚
导师:约翰·w·佩斯利博士

照片由 h heyerleinUnsplash 上拍摄

https://www.edx.org/course/machine-learning

机器学习是当今数据分析领域最激动人心的职业的基础。您将学习模型和方法,并将它们应用到现实世界中,从识别趋势新闻话题到构建推荐引擎、给运动队排名和绘制电影僵尸的路径。

涵盖的主要观点包括:

  • 概率与非概率建模
  • 监督与非监督学习

主题包括分类和回归、聚类方法、序列模型、矩阵分解、主题建模和模型选择。

方法包括线性和逻辑回归、支持向量机、树分类器、boosting、最大似然和 MAP 推断、EM 算法、隐马尔可夫模型、卡尔曼滤波器、k 均值、高斯混合模型等。

人工智能课程

大学:ColumbiaX
导师:Ansaf Salleb-Aouissi 博士

亚历山大·奈特Unsplash 上拍照

https://www.edx.org/course/artificial-intelligence-ai

自动驾驶汽车、人脸识别、网页搜索、工业机器人、导弹制导、肿瘤检测有什么共同点?

它们都是复杂的现实世界问题,正在通过智能(AI)的应用来解决。

本课程将提供对构建智能计算机系统的基本技术的广泛理解,以及对人工智能如何应用于问题的理解。

你将学习人工智能的历史、智能代理、状态空间问题表示、无信息和启发式搜索、玩游戏、逻辑代理和约束满足问题。

您将通过构建一个基本的搜索代理获得实践经验。对抗性搜索将通过创建一个游戏来探索,机器学习的介绍包括线性回归的工作。

在你走之前

- [Advance your Career in Cybersecurity (60% off) [Course]](https://imp.i115008.net/c/2402645/1024607/11298)- [Become a Cloud Developer using Microsoft Azure [Course]](https://imp.i115008.net/c/2402645/895504/11298)- [Binary logistic regression overview](https://dataanalysis.substack.com/p/supervised-machine-learning-binary-logistic-regression-overview-47282b9c608b)- [Free skill tests for Data Scientists & Machine Learning Engineers](https://aigents.co/skills)

上面的一些链接是附属链接,如果你通过它们购买,我会赚取佣金。请记住,我链接课程是因为它们的质量,而不是因为我从你的购买中获得的佣金。

Twitter 上关注我,在那里我定期发布关于数据科学和机器学习的消息。

照片由Courtney hedgeUnsplash 拍摄

如何开始为数据科学写作

原文:https://towardsdatascience.com/how-to-start-writing-for-data-science-12bcd0bb51f?source=collection_archive---------11-----------------------

通过发布您的作品来创建令人印象深刻的作品集

凯利·西克玛在 Unsplash 上的照片

当我在学校的时候,我的朋友经常在考试前来找我帮忙。他们中的许多人从来没有注意过老师——他们不做笔记,或者经常逃课,考试临近时经常努力跟上。

我会在午休时抽出一些时间来帮助他们学习材料。

久而久之,我意识到这样做其实对我在学校的表现有帮助。

有时,我的朋友会问我一些我从未想过的问题,同样的问题后来会出现在我的试卷上。

教人意味着我必须理解一个主题(真正理解它,而不仅仅是尽可能多的往脑子里塞)。这意味着我能够更长时间地记住信息,不再需要在考试前开夜车。

我开始意识到学习任何东西的最好的方法是教它

我对教学产生了热情。它帮助我提高了我所教授的科目的技能,并且我能够超越课本材料。

放学后,我成了一名兼职教师,并且在我生命中的很大一部分时间里都在教书。

当我开始学习数据科学时,我很快就迷失在在线知识的海洋中。我发现很难记住我学过的概念,很容易失去动力。

我决定回到我最擅长的事情——教书。

听起来可能很有趣,每次我学习一个新概念,我都用白板假装向学生解释这个话题。

这帮助我更深入地了解我正在学习的概念。

不久之后,我创建了一个数据科学博客,并开始写一些主题来分解它们。我还开始展示我构建的项目,并解释创建它们的步骤。

自从我开始为数据科学写作以来,已经有将近两年的时间了。在这篇文章中,我将分解一些我自从开始写数据科学博客以来学到的东西,并提供一些技巧来帮助你做同样的事情。

设身处地为读者着想

每当你想出一篇新文章的想法时,问问自己这个问题:

“读者读完这篇文章会有什么收获?如果我是数据科学行业的新手,我会点击阅读吗?”

在你开始写文章之前,你需要了解你是为谁而写。

技术含量高的人经常会纠结于此。看过很多不理解的数据科学文章。这些文章看似面向行业新手,但夹杂着复杂的术语,对读者来说并不友好。

如果你的读者需要在你文章的每两行后查找一个术语,你会很快失去他们。

人们在不理解事物时会感到沮丧。

每次你解释一个概念的时候,问问你自己,作为一个行业的初学者,你是否能够理解这个概念。问问你自己是否有更简单的方法来分解它。大多数时候,答案是肯定的。

如果你的文章是在一个稍微更高级的水平,你的读者在阅读你的文章之前需要理解某些基本概念,提供学习资源的链接。

告诉读者首先从这些资源中学习,否则,他们将无法理解你所写的内容。这将节省他们大量的时间,并给他们一个扩展知识的机会。

首先成为一名教师,然后成为一名作家

大多数数据科学作者犯的另一个错误是,他们太专注于写作,而不是表达观点。

你不需要成为一个伟大的作家或使用大词。当你写技术文章时,你的主要焦点需要是你的内容是否能被读者理解。

当我第一次想开一个数据科学博客时,我记得我推掉了它,因为我觉得我好像还没有准备好。我阅读了关于成为一名更好的作家的文章和在线课程。我痴迷于语法、拼写和句子结构。

然而,在我写完第一篇文章后,我意识到读者对花哨的术语不太感兴趣,而对内容更感兴趣。

我不需要成为周围最好的作家,我只需要写得足够好来表达我的观点。我开始花更多的时间思考我想传授给读者的知识,并专注于使概念简单易懂。

多读,少写

我通常给任何想成为作家的人的第一条建议是阅读。

在我开始写作之前,我每天都会阅读 3-4 篇关于媒体的文章。这让我了解了人们写的主题、他们的写作风格以及他们表达思想的方式。

我读得越多,我对要写的内容类型或接下来要创建的项目类型就有了更多的想法。

我认为不存在不读书的多产作家。

当你写一篇文章时,你把你学到的技能和知识分享给其他人。写了一段时间后,你的思想和想法库就会枯竭。

你需要创建新的项目,阅读更多的文章,并不断学习,以便通过写作不断传授知识。

随着时间的推移,我认识到输入输出一样重要。为了想出文章、教程或项目(输出,你首先需要自己消费和消化信息。

结论

我等了很久才发表我的第一篇文章,因为我觉得我还不够好。我想等到我成为一个多产的作家后,再开始和别人分享我的作品。

我花了一段时间才意识到,真正擅长某件事的唯一方法是持续不断地做下去。我最初的几篇文章很乱,随着时间的推移,我越写越好。

如果你想开一个博客,但认为你还不够资格,那么你应该现在就开始。

如何成为一名有竞争力的数据科学家

原文:https://towardsdatascience.com/how-to-stay-a-competitive-data-scientist-ba459a0f7a8f?source=collection_archive---------39-----------------------

意见

这里有 3 种方法…

布鲁克·卡吉尔在Unsplash【1】上的照片。

目录

  1. 介绍
  2. 油管(国外视频网站)
  3. 卡格尔
  4. 开源代码库
  5. 摘要
  6. 参考

介绍

虽然关于如何成为数据科学家的文章数不胜数,但关于如何继续成为一名成功的数据科学家的文章却不多,更具体地说,就是成为一名有竞争力的、全面发展的数据科学家。所以——这是我将在本文中深入探讨的内容。需要注意的是,有多种方法可以达到巅峰,但我将讨论我所做的三件事,也就是说,你也可以应用这些工具来提高你作为数据科学家的当前水平。如果您想了解如何使用下面的工具来改善您的数据科学职业生涯,请继续阅读。

油管(国外视频网站)

照片由布鲁克·卡吉尔Unsplash【2】上拍摄。

因为 YouTube 视频在娱乐性方面非常成功,所以他们的教育视频也是如此。也就是说,如果你通常阅读关于复杂数据科学算法的论文或出版物,以了解它们是如何工作的,这可能会变得非常令人困惑和不知所措。这就是 YouTube 的用武之地:它可以作为一个有价值的平台,将复杂的数据科学主题的教程、讨论和总体总结转化为易于理解和有趣的视频。作为一个从例子中学习的人,我发现从其他人那里学习非常成功,他们提供了常见数据科学问题的真实世界的例子,并且由于可视化可以带来的额外价值而使它们更容易理解。如果你是一个视觉学习者,YouTube 可能是学习数据科学的最简单和最好的方法之一。

通过 YouTube 视频提高数据科学的优势:

  • 几乎每个数据科学主题的内容
  • 可以向真实的业内人士学习,以及他们各自的经验
  • 可以直观地看到复杂的主题工作
  • 可以一边学习一边娱乐
  • 免费!
  • 一些 YouTube 帐户有完整的课程
  • 各种教程,包括如何使用 Python 和 R

正如你所看到的,使用 YouTube 作为平台来提高你的数据科学职业有无数的好处。然而,请记住,因为大多数人都可以发布 YouTube 视频,这也意味着任何人都可以传播虚假信息——所以要对学习持保留态度,并从各种账户观看,这样你就可以对你正在学习的材料有更广泛的了解。话虽如此,让我们看看我将在下面讨论的下一个工具,它更适合学习。

卡格尔

伊利亚·巴甫洛夫在 Unsplash 上拍摄的照片。

虽然 YouTube 可能是一个学习的好地方,但它也有信息或内容可能不正确的缺点。因此,另一个值得学习的地方是Kaggle【4】,它作为学习教育内容的来源,更具体地说,是数据科学的来源,更有名气。Kaggle 是一个独特的平台,在这里您不仅可以学习数据科学主题,还可以通过解决实际问题来进行竞争,通常,在特定数据集上具有最高准确性或最低误差的人将会获胜。Kaggle 也有一个部分,Kaggle Learn,你可以免费尝试并完成课程。

我喜欢的一些你可以从中学习的课程有:

  • 机器学习可解释性
  • 自然语言处理
  • 游戏人工智能和强化学习简介
  • 地理空间分析

以上只是你可以参加的一些课程,这些课程也有教程和练习,所以你可以通过例子来学习。他们甚至根据最近的世界大事更新了他们的一些课程,这样你就可以了解相关的话题。

在 Kaggle 上你可以学习的另一个方法是通过他们的公共笔记本搜索例子。一些趋势笔记本是泰坦尼克分析、假新闻检测、客户终身价值和智能水分析等。正如你所看到的,向 Kaggle 学习有几个好处,它作为一个平台,提供了不同的学习途径,如示例、课程、教程、数据、笔记本和交流。

以下是 Kaggle 对改善您的数据科学职业生涯的一些好处:

  • 带教程和练习的免费课程(包括代码)
  • 包含数千个示例的同行和公共笔记本
  • 趋势数据和笔记本的流行使用案例,通常来自当前世界事件
  • 免费!
  • 不同的代码示例,如 Python 和 R 编程
  • 可以搜索不同的主题,如自然语言处理( NLP )或金融等

正如我们所看到的,Kaggle 有很多很棒的地方,但是如果我们想要更多关于存储库的例子,我们可以看看其他地方,就像我将在下一节讨论的那样。

开源代码库

卢克·切瑟在Unsplash【5】上拍摄的照片。

这个网站有一些最好的数据科学的例子,几乎有任何新的数据科学主题,你所要做的就是搜索它。如果有一个新的数据科学库或机器学习算法,GitHub 上大多有一个例子。这里的这些例子通常比 Kaggle 更胜一筹,因为它们通常存放在包含整齐有序的文件夹、数据和文件的存储库中,就像真实的生产或开发存储库一样。有了这种类型的例子,你可以学习一个新的主题,或者通过真实的公司而不仅仅是教育环境中的例子,在当前的主题中变得更好。

GitHub 作为改善您当前数据科学职业的平台的优势:

  • 存储库代码、文件、数据和笔记本
  • 拥有 Jupyter 笔记本格式
  • 可以有各种不同的编程语言
  • 高效组织
  • 代码经常更新
  • 拥有流行的数据科学图书馆

GitHub 确实是数据科学家和其他软件工程师的一个伟大平台。这是 GitHub 的另一个优势或好处,它是一个更加跨功能的平台,包括从非数据科学家和数据科学家的实例学习到真实世界的存储库。

摘要

有很多学习数据科学的途径,也有很多地方可以继续你的数据科学游戏。我已经讨论了我在数据科学领域保持最新的一些方法。重要的是不要停滞不前,因为数据科学和机器学习总是在发展和改进。你两年前在学校学到的东西可能已经过时了,与今天的新技术和图书馆相比没有用了。

总而言之,您可以在以下三个方面提升自己的数据科学职业生涯:

YouTube Kaggle GitHub

所有这些网站基本上都是免费使用的,可以提供最新最好的数据科学的例子。如果你还没有使用这些平台,那么没有比现在更好的开始了。

这些学习平台的其他一些好处是,如果你是一名初级数据科学家,或者如果你正在寻找一份新工作,它们可以作为交换简历的工具和经验。有时,来自 Kaggle 和 GitHub 的项目尤其可以成为更具竞争力的经历,给招聘人员和招聘经理留下更深刻的印象。如果你想证明你的学识或专长,Kaggle 也允许你获得证书。另一方面,GitHub 将让你展示自己在端到端数据科学过程中的代码,这可能非常有价值,因为它将向你自己和其他人表明,你可以将业务修辞、编程技能和机器学习算法应用到用例中——你是一名面向项目的数据科学家,而不仅仅是面向代码的数据科学家。

我希望你觉得我的文章既有趣又有用。如果您已经使用这些平台来学习或改善您的数据科学职业生涯,或者两者兼而有之,请随时在下面发表评论。这对你现在的数据科学事业有帮助吗?你同意还是不同意,为什么?

请随时查看我的个人资料和其他文章,也可以通过 LinkedIn 联系我。

如果你想了解更多关于数据分析以及它如何成为数据科学的重要先决条件,请点击这里查看我的另一篇文章[6]:

参考

[1]由布鲁克·卡吉尔Unsplash 上拍摄的照片,(2017)

[2]Brooke Cagle 在 Unsplash 上拍摄的照片,(2018)

[3]Ilya Pavlov 在 Unsplash 上拍摄的照片,(2016)

[4] Kaggle, Kaggle 主页,(2021)

[5]卢克·切瑟在 Unsplash 上拍摄的照片,(2019)

[6] M.Przybyla,在成为数据科学家之前,你应该首先掌握数据分析,(2021)

如何提高你的 Choropleth 地图技能

原文:https://towardsdatascience.com/how-to-step-up-your-folium-choropleth-map-skills-17cf6de7c6fe?source=collection_archive---------4-----------------------

作者 Gif

本教程的目的是让你的 Foilium 技能更上一层楼。在这篇文章中,我们将创建一个比平常更高级的 Choroplet 地图。我们将添加自定义功能,以添加一个可拖动的图例,悬停功能,和交叉影线(交叉线)。如果您想学习这些技能,我强烈建议您自己用一个样本数据集来检查每个步骤。你会学到一些工具,你可以在自己的项目中运用这些工具,给你的老板或客户留下深刻印象。有些功能花了我几个小时的研究,我认为分享这些技能让人们提高他们的叶子技能是个好主意。分享是关爱,我总是喜欢分享知识,并把它传递给希望进步的人。所以我希望你会喜欢这个教程。

数据清理:

第一步是清理数据来绘制我们的 Choropleth 图。

*# We first import the libraries.* 
**import** pandas **as** pd
**import** folium 
**from** folium.plugins **import** StripePattern
**import** geopandas **as** gpd
**import** numpy **as** np*# Next we import the data.* 
df **=** pd**.**read_csv("sample_data")

*# We grab the state and wills column*
df **=** df[["state","wills"]]
df**.**head()

作者图片

*# We check how many rows we have and the types of our data.*
df**.**info()<class 'pandas.core.frame.DataFrame'>
RangeIndex: 48 entries, 0 to 47
Data columns (total 2 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   state   48 non-null     object 
 1   wills   32 non-null     float64
dtypes: float64(1), object(1)
memory usage: 896.0+ bytes

正如我们在上面看到的,wills 列中有 48 个条目和 16 个缺失值。下一步是导入 geoJson 文件。要创建一个 choropleth,我们需要两样东西:

  • 首先,我们需要一个 geoJSON 文件,为我们提供图层的地理坐标。然后,我们可以使用 geopandas 将坐标读入数据框。
  • 其次,我们需要用不同的颜色在地图上显示这些值。在我们的例子中,我们将使用样本数据中的“wills”列。

对于我们的例子,我们需要美国各州的坐标。

*# We import the geoJSON file.* 
url **=** ("https://raw.githubusercontent.com/python-visualization/folium/master/examples/data")
state_geo **=** f"{url}/us-states.json"

*# We read the file and print it.*
geoJSON_df **=** gpd**.**read_file(state_geo)
geoJSON_df**.**head()

作者图片

在上面的数据框中,您可以看到几何列,它为我们提供了 Choropleth 地图图层的坐标。

*# Next we grab the states and put them in a list and check the length.*
geoJSON_states **=** list(geoJSON_df**.**id**.**values)
len(geoJSON_states)48

我们的实际数据有 48 个州。因此,我们缺少两个状态。让我们找出哪些州缺失,因为我们需要在接下来的步骤中合并这两个数据集来绘制 Choropleth 图。为了找到缺失的状态,我们将使用 NumPy setdiff1d 函数。该函数查找两个数组的集合差。

*# Let's check which states are missing.*
missing_states **=** np**.**setdiff1d(geoJSON_states,df_states_list)
missing_statesarray(['AK', 'HI'], dtype='<U2')

缺失的州是阿拉斯加和夏威夷。下一步是从 geoJSON 数据框中移除这两个状态,这样我们在两个数据框中都有相同数量的状态来合并两个数据框。要合并两个数据框,我们需要确保两个数据框的列名和状态值具有相同的列名。当我们合并数据帧时,我们需要基于一个特定的键来合并它们,如下所示。

*# we rename the column from id to state in the geoJSON_df so we can merge the two data frames.*
geoJSON_df **=** geoJSON_df**.**rename(columns **=** {"id":"state"})*# Next we merge our sample data (df) and the geoJSON data frame on the key id.*
final_df **=** geoJSON_df**.**merge(df, on **=** "state")
final_df**.**head()

作者图片

瞧,正如你在上面看到的,我们有了合并的数据框。到目前为止,我们已经清理了数据,并准备好处理叶子地图,进入有趣的部分。

Choropleth 地图:

要创建一个叶子地图,我们需要设置初始坐标,这样我们就可以知道地图在开始时以哪个坐标为中心。

*# Initialize folium map.*
sample_map **=** folium**.**Map(location**=**[48, **-**102], zoom_start**=**4)
sample_map

作者 Gif

你应该看到上面的美国地图。下一步是创建 Choropleth 并添加层,以根据我们的示例数据中的 wills 列显示不同的颜色。

为了设置 Choropleth 映射,我们将使用 foliumChoropleth()函数。我们需要正确设置的最关键的参数是 geo_data、data、columns、key_on 和 fill_color。为了更好地理解这些参数,我们看一下文档。根据文档,我们了解到以下内容:

  • geo_data(字符串/对象)Geojson 几何的 URL、文件路径或数据(JSON、dict、geopandas 等)
  • 数据(熊猫数据帧或系列,默认无)-要绑定到 GeoJSON 的数据。
  • columns (dict 或 tuple,缺省无)—如果数据是 Pandas 数据帧,则是要绑定的数据列。必须将第 1 列作为键传递,将第 2 列作为值传递。
  • key_on(字符串,默认无)geo _ data GeoJSON 文件中要将数据绑定到的变量。必须以“feature”开头,并且采用 JavaScript 异议表示法。例如:“feature.id”或“feature.properties.statename”。

要了解有关您在上面看到的其他参数的更多信息,请参考以下链接:

下一步是建立 Choropleth 图。

*# Set up Choropleth map*
folium**.**Choropleth(
geo_data**=**final_df,
data**=**final_df,
columns**=**['state',"wills"],
key_on**=**"feature.properties.state",
fill_color**=**'YlGnBu',
fill_opacity**=**1,
line_opacity**=**0.2,
legend_name**=**"wills",
smooth_factor**=**0,
Highlight**=** **True**,
line_color **=** "#0000",
name **=** "Wills",
show**=False**,
overlay**=True**,
nan_fill_color **=** "White"
)**.**add_to(sample_map)

sample_map

作者 Gif

正如您在上面看到的,白色状态表示数据中的空值。在上面的代码中,我将 nan_fill_color 参数设置为白色。

到目前为止,这基本上就是你如何使用叶子创建一个基本的 Choropleth。这可能令人满意,但是我们应该告诉用户白色状态的真正含义。上面的图例没有告诉我们信息,因为它只是给了我们关于 wills 列的信息。为了增加趣味,并将该图提升到另一个层次,我们可能应该向该图添加另一个图例,以便用户只需查看地图就可以知道白色州代表空值。补充一个次要的传说,我在网上看到了一个很好的例子,我强烈推荐你去看看。请参见下面的链接:

https://nbviewer.jupyter.org/gist/talbertc-usgs/18f8901fc98f109f2b71156cf3ac81cd

我们只是不打算添加一个常规的图例,而是添加一个可拖动的图例,让你的剧情更具互动性。要添加可拖动的图例,您可能需要了解一些基本的 HTML 和 JavaScript。请参见下面的示例代码。

*# We import the required library:*
**from** branca.element **import** Template, MacroElement

template **=** """
{% macro html(this, kwargs) %}

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>jQuery UI Draggable - Default functionality</title>
  <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">

  <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

  <script>
  $( function() {
    $( "#maplegend" ).draggable({
                    start: function (event, ui) {
                        $(this).css({
                            right: "auto",
                            top: "auto",
                            bottom: "auto"
                        });
                    }
                });
});

  </script>
</head>
<body>

<div id='maplegend' class='maplegend' 
    style='position: absolute; z-index:9999; border:2px solid grey; background-color:rgba(255, 255, 255, 0.8);
     border-radius:6px; padding: 10px; font-size:14px; right: 20px; bottom: 20px;'>

<div class='legend-title'>Legend (draggable!)</div>
<div class='legend-scale'>
  <ul class='legend-labels'>
    <li><span style='background:white;opacity:0.7;'></span>States that have Null values.</li>

  </ul>
</div>
</div>

</body>
</html>

<style type='text/css'>
  .maplegend .legend-title {
    text-align: left;
    margin-bottom: 5px;
    font-weight: bold;
    font-size: 90%;
    }
  .maplegend .legend-scale ul {
    margin: 0;
    margin-bottom: 5px;
    padding: 0;
    float: left;
    list-style: none;
    }
  .maplegend .legend-scale ul li {
    font-size: 80%;
    list-style: none;
    margin-left: 0;
    line-height: 18px;
    margin-bottom: 2px;
    }
  .maplegend ul.legend-labels li span {
    display: block;
    float: left;
    height: 16px;
    width: 30px;
    margin-right: 5px;
    margin-left: 0;
    border: 1px solid #999;
    }
  .maplegend .legend-source {
    font-size: 80%;
    color: #777;
    clear: both;
    }
  .maplegend a {
    color: #777;
    }
</style>
{% endmacro %}"""

macro **=** MacroElement()
macro**.**_template **=** Template(template)

sample_map**.**get_root()**.**add_child(macro)

sample_map

作者 Gif

正如你在上面看到的,我们已经添加了可拖动的图例。你可以点击它并把它拖到你想要的位置。如果您不熟悉 HTML,我建议您将代码复制并粘贴到您的项目中,并注意下面一行:

  • 有空值的州。

如果您想在图例中添加多个值,只需复制粘贴上面的行并更改背景颜色和名称。

假设你的老板不喜欢你有两个传奇,他让你想出另一个解决方案。另一种选择是添加代表缺失值的交叉影线(交叉线)。为了给层添加模式,我们需要使用名为 StripePattern 的 flour 插件。请看下面的代码:

*# We create another map called sample_map2.*
sample_map2 **=** folium**.**Map(location**=**[48, **-**102], zoom_start**=**4)

*# Set up Choropleth map*
folium**.**Choropleth(
geo_data**=**final_df,
data**=**final_df,
columns**=**['state',"wills"],
key_on**=**"feature.properties.state",
fill_color**=**'YlGnBu',
fill_opacity**=**1,
line_opacity**=**0.2,
legend_name**=**"wills",
smooth_factor**=**0,
Highlight**=** **True**,
line_color **=** "#0000",
name **=** "Wills",
show**=True**,
overlay**=True**,
nan_fill_color **=** "White"
)**.**add_to(sample_map2)

*# Here we add cross-hatching (crossing lines) to display the Null values.*
nans **=** final_df[final_df["wills"]**.**isnull()]['state']**.**values
gdf_nans **=** final_df[final_df['state']**.**isin(nans)]
sp **=** StripePattern(angle**=**45, color**=**'grey', space_color**=**'white')
sp**.**add_to(sample_map2)
folium**.**features**.**GeoJson(name**=**"Click for Wills NaN values",data**=**gdf_nans, style_function**=lambda** x :{'fillPattern': sp},show**=True**)**.**add_to(sample_map2)

*# We add a layer controller.* 
folium**.**LayerControl(collapsed**=False**)**.**add_to(sample_map2)
sample_map2

作者 Gif

为了添加上面的剖面线,我们查看上面代码中的以下行:

  1. nans = final_df[final_df[“遗嘱”]。isnull()]['state']。价值观念
  2. GDF _ nans = final _ df[final _ df[' state ']。isin(nans)]
  3. sp = StripePattern(角度=45,颜色= '灰色',space_color= '白色')
  4. sp.add_to(sample_map2)
  5. folio . features . geo JSON(name = "点击查看收益 NaN 值",data=gdf_nans,style _ function = lambda x:{ ' fill pattern ':sp },show=True)。添加到(样本映射 2)

在第一个例子中,我们获取 wills 列中具有空值的州。在编号 2 中,我从编号 1 中的 nans 变量中提取状态等于状态的行。在数字 3 和 4 中,我设置了我想要为 NaN 值显示的模式。最后,在数字 5 中,我添加了 NaN 层,sp 变量作为 fillPattern。注意,我还在倒数第二行添加了层控制器。

我将讨论的最后一个主题是悬停功能。假设您想将鼠标悬停在各州上方并显示一些数据。为了添加这个功能,我们将再次使用 leav。特色。GeoJson()的功能与我们在上面的代码中所做的一样。

*# Add hover functionality.*
style_function **=** **lambda** x: {'fillColor': '#ffffff', 
                            'color':'#000000', 
                            'fillOpacity': 0.1, 
                            'weight': 0.1}
highlight_function **=** **lambda** x: {'fillColor': '#000000', 
                                'color':'#000000', 
                                'fillOpacity': 0.50, 
                                'weight': 0.1}
NIL **=** folium**.**features**.**GeoJson(
    data **=** final_df,
    style_function**=**style_function, 
    control**=False**,
    highlight_function**=**highlight_function, 
    tooltip**=**folium**.**features**.**GeoJsonTooltip(
        fields**=**['state','wills'],
        aliases**=**['state','wills'],
        style**=**("background-color: white; color: #333333; font-family: arial; font-size: 12px; padding: 10px;") 
    )
)
sample_map2**.**add_child(NIL)
sample_map2**.**keep_in_front(NIL)
sample_map2

作者 Gif

首先,我们创建一个 style_function 和一个 highlight_function 来确定我们希望悬停功能如何出现。接下来,在 NIL 变量中,我们需要注意正确的参数值。

  • 我们将数据设置为 final_df 数据帧。
  • 我们将样式函数设置为我们在第二行创建的 style_function。
  • 我们将第 6 行中的 highlight 函数设置为 highlight_function。
  • 我们使用 GeoJsonTooltip 函数,并将字段和别名参数设置为 final_df 数据框中的列名,以便在将鼠标悬停在各州上方时显示所需的数据点。

参见下面的最终代码。我还在代码底部的图层控制器中添加了明暗模式选项。我使用 cartodbdark_matter 图层作为亮模式,对于暗模式,我使用 cartodbpositron 图层。

*# We create another map called sample_map2.*
sample_map2 **=** folium**.**Map(location**=**[48, **-**102], zoom_start**=**4)

*# Set up Choropleth map*
folium**.**Choropleth(
geo_data**=**final_df,
data**=**final_df,
columns**=**['state',"wills"],
key_on**=**"feature.properties.state",
fill_color**=**'YlGnBu',
fill_opacity**=**1,
line_opacity**=**0.2,
legend_name**=**"wills",
smooth_factor**=**0,
Highlight**=** **True**,
line_color **=** "#0000",
name **=** "Wills",
show**=True**,
overlay**=True**,
nan_fill_color **=** "White"
)**.**add_to(sample_map2)

*# Add hover functionality.*
style_function **=** **lambda** x: {'fillColor': '#ffffff', 
                            'color':'#000000', 
                            'fillOpacity': 0.1, 
                            'weight': 0.1}
highlight_function **=** **lambda** x: {'fillColor': '#000000', 
                                'color':'#000000', 
                                'fillOpacity': 0.50, 
                                'weight': 0.1}
NIL **=** folium**.**features**.**GeoJson(
    data **=** final_df,
    style_function**=**style_function, 
    control**=False**,
    highlight_function**=**highlight_function, 
    tooltip**=**folium**.**features**.**GeoJsonTooltip(
        fields**=**['state','wills'],
        aliases**=**['state','wills'],
        style**=**("background-color: white; color: #333333; font-family: arial; font-size: 12px; padding: 10px;") 
    )
)
sample_map2**.**add_child(NIL)
sample_map2**.**keep_in_front(NIL)

*# Here we add cross-hatching (crossing lines) to display the Null values.*
nans **=** final_df[final_df["wills"]**.**isnull()]['state']**.**values
gdf_nans **=** final_df[final_df['state']**.**isin(nans)]
sp **=** StripePattern(angle**=**45, color**=**'grey', space_color**=**'white')
sp**.**add_to(sample_map2)
folium**.**features**.**GeoJson(name**=**"Click for Wills NaN values",data**=**gdf_nans, style_function**=lambda** x :{'fillPattern': sp},show**=True**)**.**add_to(sample_map2)

*# Add dark and light mode.* 
folium**.**TileLayer('cartodbdark_matter',name**=**"dark mode",control**=True**)**.**add_to(sample_map2)
folium**.**TileLayer('cartodbpositron',name**=**"light mode",control**=True**)**.**add_to(sample_map2)

*# We add a layer controller.* 
folium**.**LayerControl(collapsed**=False**)**.**add_to(sample_map2)
sample_map2

作者 Gif

结论:

最后,让我们回顾一下我们在本教程中学习的步骤,并总结一下我们所学到的内容:

  • 我们使用 NumPy、Pandas 和 GeoPandas 清理数据,并通过合并 geoJSON 数据和我们的样本数据来创建最终数据框,从而使用 folium 创建 Choropleth 地图。
  • 我们学习了如何添加一个可拖动的图例。
  • 我们还学习了如何添加交叉影线(交叉线)来显示空值。
  • 最后但同样重要的是,我们讨论了悬停功能。

我希望你喜欢这个教程,并且你将能够在你未来的项目中运用这些技巧来介绍你的老板或客户。如果你对这个话题有任何问题或者有任何反馈,请随时联系我。如果你能在任何社交媒体平台上分享它,我将不胜感激。谢谢你,下次再见 time️!✌️

https://www.navidma.com/

如何在 Python 脚本中剥离输出并执行交互式代码

原文:https://towardsdatascience.com/how-to-strip-outputs-and-execute-interactive-code-in-a-python-script-6d4c5da3beb0?source=collection_archive---------26-----------------------

使用 strip-interactive 在一行代码中执行交互式 Python 代码

作者图片

动机

你见过这样的交互式 Python 代码教程吗:

…并且希望只获得可以像下面这样执行的代码?

删除所有的>>>符号和移除所有的输出可能很耗时,尤其是当代码很长的时候。有没有一种方法可以让你在一行代码中得到如上的干净输入?

这就是为什么我创建了一个名为 strip-interactive 的包。在本文中,我将向您展示如何使用这个包来做到这一点。

要安装 strip-interactive,请键入:

pip install strip-interactive

提取干净的输入

让我们使用 strip-interactive 从交互式 Python 代码中提取干净的输入:

输出:

import numpy as np
print(np.array([1,2,3]))
print(np.array([4,5,6]))

酷!现在,这些干净的输入可以执行了。

执行干净的输入

为了执行我们刚刚从get_clean_code得到的输入,使用exec方法:

[1 2 3]
[4 5 6]

如果您喜欢一步执行交互式 Python 代码,请使用run_interactive方法:

输出:

[1 2 3]
[4 5 6]

厉害!使用run_interactive方法得到的输出与使用get_clean_codeexec方法得到的输出相同。

如果我的交互代码有注释,这还有效吗?

我相信是的,但是最好测试一下。

产出:

[1 2 3]

太好了,成功了!

这个什么时候失效?

请注意,如果您对如下代码使用run_interactive,将不会有输出:

因此,请确保将print添加到np.array([1,2,3])以查看输出:

输出:

[1 2 3]

结论

恭喜你!您刚刚学习了如何使用 strip-interactive 在一行代码中执行 Python 脚本中的交互式 Python 代码。当您想在文章或文档中快速尝试交互式 Python 代码时,这将非常方便。

这篇文章的代码可以在这里找到。如果你看到如何改进这个包,请在这里随意投稿或提交问题

我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以在 LinkedIn 和 T2 Twitter 上与我联系。

这个回购如果你想检查我写的所有文章的代码。在 Medium 上关注我,了解我的最新数据科学文章,例如:

</2-tools-to-automatically-reload-when-python-files-change-90bb28139087>

如何构建戈朗的 DDD

原文:https://towardsdatascience.com/how-to-structure-ddd-in-golang-28a7c3e7263b?source=collection_archive---------13-----------------------

关于如何在 Go 中用 DDD 方法组织代码和包结构的后续文章

是时候清理代码结构了。上田拓也的 Gopher,勒内·弗伦奇的原始 Go Gopher(CC 3.0)

在 Go 项目中使用 DDD 时,是时候看看更好的架构解决方案了。在本文中,我们将采用一个包含所有 DDD 组件的存储库,并展示如何在维护 DDD 的同时管理一个不太复杂的项目设置。

我们将要改变的库来自我以前写的一篇关于如何在 Go 中实现 DDD 的文章。在那篇文章中,我解释了 Eric Evans 所解释的 DDD 的所有组成部分。这个库可以在 GitHub 上找到。

本文中绘制的所有图像均由珀西·博尔梅勒绘制,地鼠由拓也·上田绘制,灵感来自蕾妮·弗伦奇的作品。图像中的地鼠已被修改

如果你想看这篇文章的视频,可以在 Youtube 上找到

将聚合移动到其域包中

首先要做的是把aggregate包一起去掉。我们学习了什么是聚合以及应用什么规则,我们不一定要命名要聚合的包。我倾向于将聚合放在它们各自的域包中,所以Customer聚合应该放在customer域中。在我看来这更有意义。

从聚合包中删除客户聚合

当然,在将文件移动到customer域后,您还需要更改任何指向aggregate.Customer的引用,如果您在客户包中,就用customer.CustomerCustomer替换它。

customer/repository.go —删除对聚合包的所有提及

必须对Product聚合执行同样的操作,它应该进入product域。我不会涵盖所有的代码更改,找到并重构所有提到的aggregate包应该很容易。

包含产品集合的产品域

在我看来,以这种方式在他们的域包中包含聚合看起来更好,也更有意义。

删除聚合文件夹,我们已经整理了一些代码气味。

该项目的改进结构,但尚未完成

移动值对象和实体

对于entityvalueobject,我们仍然有一个文件夹,我想这没有错。以这种方式将共享结构存储在单独的包中的一个好处是避免了循环导入。

不过,我们可以用另一种不那么臃肿的方式来实现这一点。现在我们根本没有根包。将实体和值对象中的所有文件移动到根目录,并将包重命名为tavern

item.go 在根目录下,包名为 tavern

这给我们留下了一个更好的结构。

将实体和其他共享项目移动到根包中

您还需要将go.mod中的模块重命名为合适的名称。

module github.com/percybolmer/tavern

不仅如此,我们需要更改所有文件中的所有导入来反映这一更改,并且entities包的所有引用都必须更改为tavern,如下所示。

用 tavern 替换实体的所有实例,以及所有导入。

所有以github.com/percybolmer/go-ddd开头的导入都改为github.com/percybolmer/tavern

应用此更改的最简单方法是更改所有文件,删除 go.mod 和 go.sum 文件,并用新名称go mod init github.com/percybolmer/tavern重新初始化 go 模块。

这是相当的重构练习,但它是值得的。请随意重新运行任何测试,这样您就知道它正在按预期工作。

拆分服务包

现在,服务包包含同一个包中的所有服务。我想把这些分成两个包,OrderTavern

原因是随着项目的增长,将服务分成更小的包是很好的。在我看来,把它们都放在同一个包里会显得臃肿。我也喜欢将域作为基础设施的一部分,在这种情况下,我们在services文件夹中创建一个名为order的新文件夹。原因是在未来我们可能会看到更多与订单相关的服务出现,例如,当前的订单服务专注于点饮料的Customer,但是当酒馆需要补给时呢?使用这种结构,开发人员很容易知道在哪里可以找到相关的代码。

另一件重要的事情是配置函数的命名,如果我们继续创建像WithMemoryCustomerRepository这样的函数,就很难保持什么配置去哪里。如果我们看到order.WithMemoryCustomerRepository就很容易知道发生了什么。

如何将服务包组织成子包

做出这个改变需要Tavern包引用order.OrderService而不是唯一的OrderService

更改所有引用以匹配新结构。我们还将在OrderService中添加一个新函数来添加新客户,因为现在我们只能通过使用 struct 中的customer库来做到这一点。这是行不通的,因为服务将暴露给其他包。此外,服务永远不应该假设服务的用户知道如何这样操作,因此在服务自己的域中维护这种逻辑是很自然的。

在 OrderService 中添加 Customer 以帮助创建新客户。

在应用了这些更改之后,订购产品的测试变得更加容易了。

taver_test.go —创建新客户和订购更加容易

现在我们终于有了最终的解决方案。一个非常简单的导航,干净的结构化项目。

要使用的最终架构

如何经营酒馆

我想推荐的最后一件事是使用许多 Go 存储库中的cmd文件夹。在那个文件夹中,应该可以找到所有的命令行工具,而且可以不止一个。为了结束这篇文章,我将在cmd文件夹中创建一个主程序。

mkdir cmd
touch main.go

我们点杯啤酒庆祝一下吧。

main . go——试着运行程序,看看是否一切正常,明白这个双关语了吗?

这个关于 DDD 的很长的两部分系列到此结束。

你可以在 GitHub 上找到完整代码。

关于 DDD 还有很多东西要学,这只触及了基础,以及我如何找到结构化项目。我们还没有触及Domain eventsCQRSEventSourcing等话题。敬请关注更多内容。

如果你渴望了解更多关于 DDD 的知识,我推荐 Eric Evans 的书《领域驱动设计:解决软件核心的复杂性》。你可以在亚马逊上找到它。

一如既往,请随时通过我的任何社交媒体联系我。我确实喜欢反馈、批评,甚至愤怒。

我可以在 medium、T witterInstagramLinkedin 上找到我。

如何构建易于理解的数据科学笔记本

原文:https://towardsdatascience.com/how-to-structure-your-data-science-notebook-to-be-easy-to-follow-2d3c2777e6e0?source=collection_archive---------10-----------------------

创建有序笔记本的清晰步骤,包括示例

凯利·西克玛在 Unsplash 上的照片

笔记本的结构比你想象的更重要。读者在理解细节之前需要对你的作品有一个清晰的概述。

要实现这一点,您的笔记本需要一个有条理的结构,包含直观的连续部分。也许有人只对您的数据解决方案的某一部分感兴趣。所以你工作的主要部分需要容易识别。

但是我们不需要把事情变得不必要的复杂。所以开门见山,一般来说,我们可以简单地使用以下五个部分:

  1. 介绍
  2. 数据争论
  3. 探索性数据分析
  4. 建模(可选)
  5. 结论

下面我们详细说明每一部分必须包含的内容,描述所有的必要子部分

1.介绍

首先,我们必须根据业务目标来描述项目。首先给出你工作的背景,它的起源,你想要达到的目标:主要目标。

例如,假设您正在调查一个包含营销公司销售数据的数据集。引言的第一部分将谈论销售数据的来源,并说明你想从数据中回答哪些问题,例如,你的产品的哪些方面(颜色、尺寸、品牌等)。)与销量的相关性更大。

一个好的经验法则是明确地创建一个要解决的问题列表。

仍然与您的项目目标相关,仅从该笔记本中选择的产品就需要指定。例如,分析的最终目标是创建一个具有洞察力的月度报告?或者只是一个一次性的段落,通过电子邮件发送给首席执行官来证明一个观点?这一点应该在引言中说清楚。

最后,简单说一下任何先验知识也很重要。例如,如果销售数据只来自一个特定的商店,就应该提到这一点。如果在某段时间,公司的某些产品出现问题,如分销问题,直接影响销售,这也应该说明。基本上,我们必须描述任何有助于理解数据源的上下文和重要细节的东西。

2。数据争论

本节首先简要描述我们将要分析的数据集。基本上,这意味着我们必须列出每个表中的列名,以及它们的含义。如果我们要处理多个表,我们还应该描述这些表是如何相互关联的。

之后,我们开始编码,第一步是加载数据。这里检查清洁度也很重要,并且完全清洁你的数据集用于分析。

数据集中的任何修改都应该在这个部分。

接下来的章节将简单地查看用于探索的数据。但是数据争论部分是您为想要探索的维度调整数据的地方。

记录清理数据所采取的步骤也很重要,证明每个决策的合理性。例如,如果您删除了“年龄”列中缺失数据的观察值,您需要清楚地解释原因。

由于数据集通常有许多棘手的任务,一个好的做法是在一个 markdown 单元格中列出本节中执行的所有修改

3.探索性数据分析

这一部分应该以你要回答的问题为导向。换句话说,您将为介绍中提出的每个问题创建一个子部分。

因此,在数据已经清理完毕的情况下,这里你将基本上计算 统计创建可视化,目标是回答每个问题。

请记住,在整个探索过程中始终添加注释。在每个情节或分析决定之后,你需要解释什么是结果,以及你从结果中得到的观察。

引导读者通过你的思维过程!

确保从多个角度调查每个问题,讨论可以使结果更有趣的方面。例如,不只是添加分布图并描述它们,而是考虑创建支持您答案的图

4.建模(可选)

并非所有数据科学工作都包括建模。许多商业问题可以通过探索性的数据分析来回答。例如,设计良好的假设检验可以为您的数据提供许多有趣的见解。

更重要的是建议在笔记本上进行建模。

建模不要用笔记本,要用模块化代码,直接用 python 脚本,用协同工作,测试套件等。尽管如此,笔记本可能用于快速建模实验,例如创建简单的基线模型。

因此,如果您确实包括建模,请确保首先将您的数据集分成“训练”和“测试”样本。然后,处理“训练”部分,直到满足给定的指标,比如使用交叉验证达到 85%的准确率。一旦你完成了比较模型和执行调整,你就可以在“测试”样本上评估你的最终模型。

因此,这里要记录的主要部分是:你如何将数据分成训练和测试,使用了哪些算法和超参数,以及你如何评估你的模型确实有用。例如,有时候“精确”比“回忆”更有意义。这个要在简介里说明,这里调一下。

5.结论

最后,我们总结了我们的发现以及针对引言中提出的问题所获得的结果。

此外,我们应该指出额外的研究可以在哪里进行或者额外的信息可以在哪里有用。例如,分析可以指出折扣优惠的有趣数据是用户与产品页面互动的时间。因此,分析师会建议该公司在每个产品的销售页面上增加这样一个功能。

最后,另一个非常重要的点是确保你清楚你的项目的限制。没有一个项目是完美的,所以至少应该在这里的一个小节中描述一个限制。

强迫自己列出至少一个工作的局限。

例如:数据中是否有任何缺失的观察值,即不在该数据集中的其他信息?我们能完全相信为验证项目中提到的假设而进行的统计测试吗?为什么?

我希望您喜欢这个关于如何构建您的数据科学笔记本的高级视图。按照上面提到的方面,下面是一个具体的子部分示例,您可以将它包含在所描述的五个部分中:

  1. 简介:背景、业务目标、问题列表
  2. 数据争论:清洗步骤列表,步骤 1,步骤 2,…
  3. 探索性数据分析:问题 1,问题 2,…
  4. 建模(可选):拆分数据、训练、测试
  5. 结论:局限性,未来工作

记得在描述作品时充分利用 markdown 单元格和所有可用于 markdown 的样式资源,你会做得很好!

最后,创建内部链接和建立目录也很有用。这里有一个例子:

在笔记本中使用降价单元格和 HTML 的目录。图片由作者提供。

如果你喜欢阅读这样的故事,并想支持我成为一名作家,可以考虑注册成为一名媒体会员。每月 5 美元,你可以无限制地阅读媒体上的故事。如果你用我的链接注册,我会赚一小笔佣金。

如何构建您的数据科学项目

原文:https://towardsdatascience.com/how-to-structure-your-data-science-project-d2484e452e46?source=collection_archive---------43-----------------------

你可以用三种方法来组织你的学习和文件夹项目

威廉·艾文在 Unsplash 上的照片

项目是学习数据科学的好方法。它们提供了一种有意义的、自我指导的方法来提高你的技能,并可能为你和他人解决实际问题。项目也是在作品集中展示你技能的好方法。虽然有一些小项目,你只是在一两天内“做”以熟悉某些技能、库或主题,但也有一些项目可能稍大一些,需要更多的前期规划。

我曾经犯过这样的错误,刚开始一个项目,就忘记了所有我想完成的小任务和我的解决方案。最后,我没有事先制定计划,给自己增加了很多额外的工作。为了省去你的麻烦,我想提供三个框架,你可以用它们来规划你的项目,从头到尾指导你自己。每个框架的步骤当然不是一成不变的,您应该根据自己的具体情况进行调整。一些框架也比其他的更具体,所以只要选择最适合你的就行了!

CRISP-DM —数据挖掘的跨行业标准流程

CRISP-DM 是在欧盟的资助下于 1996 年创建的过程模型。这是最常用的分析模型之一。2015 年,IBM 改进了这种方法并创建了 ASUM-DM,但对于我们的目的来说,CRISP-DM 提供了一个很好的框架。流程模型包含多个步骤,步骤之间有一些可选的迭代循环。这些步骤是:

  • 商业理解
  • 数据理解
  • 数据准备
  • 建模
  • 估价
  • 部署

肯尼斯·延森在维基百科上(CC BY-SA 3.0)

让我们来看一下它们及其组件。

商业理解:
1。收集关于您的问题、领域等的背景信息
。,定义您的“业务”或项目目标以及您的成功标准。请记住,你是在试图解决一个问题,而不是达到一定的准确性分数!
2。 评估情况:你可以利用哪些资源,有什么假设或约束,有什么潜在风险吗?你考虑过伦理问题吗?
3。确定您的数据科学工作的目标,通过您的分析或建模,真正理解您试图实现的目标。 4。制定一个计划(至少是一个大纲)

数据理解:
1。收集(初始)数据:
这可能是从 kaggle,谷歌,一些数据库或你已经有的一些数据现有的数据。它可能是你需要通过网络搜集或其他数据收集方法获得的数据。
2。探索和描述你的数据:了解你的数据的大小、种类和复杂性(这可能有助于避免你的分析或建模中代价高昂的错误)。通过 EDA 浏览数据(了解分布、汇总统计等。).
3。 检查你的数据质量:是否有任何遗漏、错误的标签、不一致,元数据是否正确和有用?

接下来的两个步骤并不总是线性的,可能需要在这两个步骤之间反复进行。

资料准备:
1。选择(右侧)数据:
选择您的特征,可能将数据分为训练集、验证集和测试集。
。清理数据:填充或删除缺失,纠正数据不一致等。
3。 扩展数据:扩展你的特征(通过计算新特征)或者训练例子(例如通过数据扩充)。
4。格式化数据:转换你的数据,使其适合即将到来的分析或机器学习技术(缩放、标准化、编码等)。)

造型:
1。 选择建模技术:这可以是传统的统计模型,也可以是更先进的机器/深度学习技术。根据您的数据、目标和约束条件选择一个或多个模型/算法。定义一个或多个指标。
2。构建/创建模型:
指定模型和超参数,训练它,如果可能的话,在单独的验证集上验证它)
3 .评估模型:根据您选择的指标评估模型的性能。

评价:T421。评估结果:是否有清晰可辨的结果或任何新颖的发现?模型或发现能用来实现你的商业目标吗?
2。回顾过程:有什么地方出错了吗?能快速修好吗?有没有可以探索的替代解决方案?
3。确定接下来的步骤:如果结果没有达到您的业务目标,您可能需要退回一点,用不同的方法重新开始,或者如果您的结果令人满意,您可能会进入部署阶段

部署
1。总结你的过程和发现。试着记录你做了什么,你的过程是什么,你如何解释结果。
2。 创建一个部署计划,确定未来可能出现的任何问题。
3。 计划监控和维护您的解决方案
4。 进行最终评审并记录您的流程

项目管理办法

你不需要一个完整的项目计划,或者这里的甘特图,不要担心。但是项目管理采用的一般方法当然可以应用于您的数据科学项目。
预防性维护方法通常可分为以下几个步骤:

启动—计划—执行—监控&控制—关闭

开始是第一阶段,但也是关键的一步。这是您确定项目目标、可用资源(数据、包、时间)的地方。做完这些后,评估你的项目是否可行,如果可行:太好了!如果没有,你也不必永久抛弃它,也许你现在只是缺少一些资源或时间,但你的想法以后会变得可行。

在计划阶段,你可以决定采取哪些具体步骤来实现你的目标。想想你要用这些数据做什么,你可能会使用哪些模型等等。,如果你能试着想出一个时间表或里程碑,你想在某个时候实现。这肯定会帮助你坚持下去。如果你和一个伙伴或团队一起工作,你可以用你的计划来分配任务

在你计划好一切之后,是时候执行了。完成你给自己设定的任务,努力达到你的里程碑。在这个阶段,重要的是监控&控制你在做什么,你的工作是否仍然符合你最初的目标?一切都像预期的那样吗?如果不是,与预期有什么不同?哪里出了问题?试着理解为了达到你的目标,哪些调整是必要的。

最后,是时候结束你的项目了。但是关闭不仅仅意味着保存你的工作和最后一次推送你的 GitHub repo。记录你的工作,评估每件事的进展,检查你是否真的按计划完成了每件事。为你自己和潜在的记录获取你的经验教训。回收你可以再次使用的东西,比如你写的函数或者你建立的工作流程。最后:庆祝一下!

传动系统方法

这种方法是由(fast.ai 的)杰瑞米·霍华德、玛吉特·兹韦默和迈克·洛基德斯建立的。它是专门为生产数据产品而设计的,可以达到一定的目标。我认为这是一个比前两个更“高级”的方法,因为它的步骤更少细节,定义更广泛。
它包含四个步骤,旨在利用数据产生可操作的结果。

第一步是定义一个清晰的目标或者你想要完成的目标。一旦你有了一个明确的目标,你就可以开始找出你可以利用哪些杠杆来实现你的目标。思考你可以采取哪些行动来改进现有的解决方案。然后考虑你需要收集的数据,以便采取行动实现目标。一旦你完成了这些步骤,你就可以开始考虑你可以构建和使用哪些模型来组合你的数据和杠杆,以产生想要的结果。

我希望这篇概述能给你一些关于如何为你自己或你的投资组合构建数据科学项目的想法。享受规划的乐趣,最重要的是执行你的项目!

-梅林

参考资料:

[1]https://en . Wikipedia . org/wiki/Cross-industry _ standard _ process _ for _ data _ mining

[2]https://www . oreilly . com/radar/drive train-approach-data-products/

数据工程师如何构建 Git 分支策略

原文:https://towardsdatascience.com/how-to-structure-your-git-branching-strategy-by-a-data-engineer-45ff96857bb?source=collection_archive---------0-----------------------

实践教程

数据管道也需要版本控制!

作者图片

如果你曾经合作处理过代码,你会理解版本控制和分支策略的重要性。这些是允许多个开发人员并行处理一个项目的关键工具。没有它们,你的产品很可能会坏掉。

对于那些不理解什么是版本控制和分支的人来说——概括地说,版本控制是管理对你的源代码的变更的实践。它允许开发人员克隆、工作和部署代码,而不会干扰其他开发人员的工作。

分支仅仅是你的源代码的版本。它有助于将当前正在开发的代码与生产环境中实际工作的稳定代码分开。

你可能听说过软件工程师和开发人员的 DEV、UAT 和 MASTER 分支。但是你遇到过数据工程师/数据科学家的分支策略吗?

数据工程师和数据科学家构建和维护的不是产品,而是数据仓库。数据科学家确实在构建数据产品,但在建立稳定的数据仓库来收集数据之前,他们通常无法做到这一点。

我们来谈谈数据工程师和软件工程师在分支设计上的一些差异

内容

Aaron WeissUnsplash 上拍摄的照片

对于数据工程师来说,源代码通常涉及从数据仓库版本到数据管道的所有内容。

有—

  • 将更改应用到数据仓库的 SQL 命令(DMLs/DDLs)
  • 数据管道
  • CI/CD
  • DevOps
  • 数据模型

这些仅仅是我脑海中的想法。通俗地说,数据仓库就是存储数据的地方。但实际上,事情远比这复杂。

数据仓库有多种用途,并且根据您工作的公司而有所不同。在一些地方,数据仓库被用来为数据分析师/数据科学家制作商业智能图,有时甚至为公司的高层管理人员,如首席执行官和首席技术官。

数据仓库可以存储通过实时管道输入到机器学习产品的数据,随着新数据的到来更新机器学习模型。如果存储在仓库中的数据有问题,它将反映在所述机器学习模型中。

这些数据仓库功能中的每一个都有其时间间隔。例如,数据分析师希望他们的图表每天更新,而机器学习产品希望他们的数据实时更新。

因此,对源代码的修改可能会产生比你想象的更大的影响。只需执行一次无效的 SQL 查询,就会接到 CEO 本人的电话,询问为什么仪表板会坏掉。

Unsplash的照片

通常,与数据工程师相比,软件工程师安排的发布时间间隔要长得多。这是因为为一个产品开发一个特性比制作一个在表中添加一列的 SQL 查询需要更长的时间。

既然如此,我注意到数据工程师比典型的软件工程师更频繁地发布版本。我经历了每周 3-4 次的发布。我认为软件工程师的典型功能发布至少需要一周时间。

这不是故意的。

很多时候,数据工程师会收到对重要仪表板或产品进行紧急更改的要求。首席执行官和首席技术官可能出于多种原因要求更改仪表板上的数字,他们希望这些数字几乎立即得到反映。因此热修复的频率。

分支策略

作者图片

让我们来谈谈我为我的组织设计的分支战略。
有 3 个主要分支—

开发 —包含最新的修复和特性

UAT——UAT 环境现状

—生产环境的当前状态

使用这种设计,开发分支将在主分支之前包含提交。生产环境通常不会反映团队在任何测试之前开发的最新特性。

偏差

如果一个开发人员想要开始一个特性/bug 的工作,一个开发分支以吉拉票证命名。吉拉票证是经理分配给工程师的任务。发展发生在这个分支上。

工程师可以将他们的工作部署到开发环境中并执行测试。一旦他们对他们的测试感到满意,他们就可以将开发分支合并到 DEV 分支中,本质上是将他们的变更推进到 DEV 中。

在这一点上,工程师们确信他们的代码正在按预期工作是很重要的。 DEV 可能在任何时间点被合并到 UAT,任何 bug,如果存在的话,都会被提出来。

CI/CD

在这种特殊的设计中,部署到 UAT 和生产环境的唯一方法是将代码推送到它们所连接的分支中。

但是首先,什么是 CI/CD?

持续集成(CI)和持续交付(CD)是软件工程或数据工程中的一种方法,在这种情况下,可以更频繁、更可靠地交付代码变更。它包含了开发团队应该遵循的一系列原则和实践。

在我们的例子中,我们部署 CI/CD 管道来覆盖 Apache Airflow 中的代码,这是我们用于数据管道的工作流管理系统。
这包括 Dag、操作符和其他所有东西的代码。

CI/CD 管道还使用名为 Liquibase 的 SQL 版本控制工具执行 DMLs/DDLs,以将更改应用到数据仓库。

在 UAT 和生产环境中,数据工程师在部署工作时有限制。例如,在 UAT 和生产数据仓库中只允许使用 Select 语句。这是为了防止任何人意外删除表或插入行。

执行 DMLs/DDLs 的唯一方法是通过 CI/CD 管道执行,DMLs/DDLs 是对表的模式/数据进行更改的 SQL 语句。这听起来可能有点矫枉过正,但是这种实践极大地提高了我们数据仓库的稳定性和质量。

UAT

一旦一个团队取得了显著的进展,并希望将特性转移到 UAT,他们就可以安排发布时间。开发部门并入 UAT 部门,运行 CI/CD。通常对环境进行监控,以确认一天内没有任何错误。然后通过使用语义版本化来标记该分支。

掌握

在 UAT 环境中进行彻底的测试后,该团队可以通过将 UAT 分支合并到主分支来将所述特性转移到生产中。运行用于生产的 CI/CD,并再次监控环境。然后对该分支进行相应的标记。

修补程序

虫子。它们是不可避免的。如果在 UAT 和生产环境中的任何一点有错误,数据工程师将需要应用补丁。这是通过从故障分支创建修补分支,应用更改,并将修补分支合并回其原始分支来完成的。

修补程序可以绕过必须通过 DEV 的过程。必要时可以直接合并到 MASTER 中。合并后,分支也相应地被标记。该分支还必须同步到相关分支中。

例如,一个热修复程序被合并到生产中。然后,开发人员必须将 prod 同步到 DEV 和 UAT,以便这些分支也包含修复。

部署工作流程

作者图片

下面是如何使用这种分支策略将工作部署到环境中的分步指南。

  1. 从 DEV 分支创建以吉拉开发票命名的分支。这里我们用 A、B、C 作为特性/bug 的例子。
  2. 一旦测试令人满意,A、B 和 C 可以在任何时候合并到 DEV 分支中。DEV 分支现在包含 A、B 和 c。
  3. 在 UAT 版本中,DEV 分支通过 pull 请求直接合并到 UAT 分支中。 CI/CD 现在将 A、B 和 C 部署到 UAT 环境中,该环境将更改应用到数据管道和实际的数据仓库本身。然后对该分支进行相应的标记。
  4. 经过仔细监控后,计划发布产品。UAT 分支通过拉请求被合并到主分支中。 CI/CD 将 A、B 和 C 部署到生产环境中。分支被相应地标记。
  5. 在发布期间,开发不会停止。工程师可以像往常一样继续他们在开发分支的工作。例如,随着发布的进行,工程师们正在开发特性 D 和 E。
  6. 作为一个假设的场景,在 CI/CD 运行期间,在生产中发现了一个 bug。创建一个包含 bugfix F 的热修复分支,并直接合并到主中,以便进行热修复。bugfix F 通过 CI/CD 部署到生产环境中。该分支被相应地标记。
  7. 主分支和生产环境现在都包含 A、B、C 和 F。一旦团队对修复程序 F 感到满意,主分支就会同步到 UAT 和开发分支上,这样 F 就会出现在所有分支中。戴夫和 UAT 现在包含了 A,B,C 和 f
  8. 一旦 D 和 F 的测试完成,它们就被合并到 DEV 分支中。DEV 分支现在包含了从 A 到 F 的所有特性/错误。它可以再次通过发布周期,将 D 和 F 引入 UAT 和生产。

结论

凯利·西克玛在 Unsplash 上的照片

如果你读到这里,你一定对无聊的东西情有独钟。
当我给我的大多数朋友讲树枝的时候,他们都睡着了,他们不知道我热爱大自然。

Gif by 高质量 Gifs

玩笑归玩笑,适当的分支策略是很重要的,这样数据工程师就不必浪费时间去处理他们不想做的事情。

他们可以只关注数据。

在这篇文章中,我们经历了—

  • 德夫、UAT 和主分行
  • 软件工程师和数据工程师在分支设计上的差异
  • 什么是 CI/CD?
  • 部署工作流程

像往常一样,我引用一句话作为结束。

世界是一个大数据问题。”—作者安德鲁·迈克菲**

订阅我的简讯,保持联系。

也可以通过 我的链接 注册一个中等会员来支持我。你将能够从我和其他不可思议的作家那里读到无限量的故事!

我正在撰写更多关于数据行业的故事、文章和指南。你绝对可以期待更多这样的帖子。与此同时,你可以随时查看我的其他 文章 来暂时填补你对数据的饥渴。

感谢 的阅读!如果你想和我取得联系,请随时通过 nickmydata@gmail.com 联系我或者我的 LinkedIn 个人资料 。也可以在我的Github中查看之前写的代码。**

如何学习谷歌数据分析专业证书

原文:https://towardsdatascience.com/how-to-study-for-the-google-data-analytics-professional-certificate-25e5e13b1f04?source=collection_archive---------0-----------------------

概述如何在这个世界级的数据分析项目中取得成功。

Al ghazaliUnsplash 上拍摄的照片

2021 年 3 月,谷歌做出了一个大胆的声明:不需要相关经验,你将在谷歌的帮助下,通过完成他们的数据分析专业证书,获得一份数据分析工作。

就这样,完成后,你被推入一个、67,900 美元起薪和数十万工作机会的世界。

这一广受期待的课程将于 4 月开始全面开放,这是开始准备该课程的最佳时机。

现在是挑战自我和发展新技能的最佳时机。另外,如果这个疫情教会了我们什么的话,那就是提高技能从来都不是浪费时间,它可以帮助你保证更好的就业选择。仅在美国,数据分析领域就有 337,400 个职位空缺,这一价格合理、自定进度且易于获取的课程是你进入职场的最佳方式,而不必花钱参加训练营或攻读硕士学位。

什么是谷歌数据分析专业证书?

谷歌数据分析专业证书是由谷歌设计的专业培训,为你成为初级数据分析师、数据库管理员和许多其他职位做准备。

该证书旨在填补所有行业中数据分析职位的空白。

谷歌创建了 8 门课程,可以在不到 6 个月的时间内完成,每周投入不到 10 个小时。

这些课程通过在线学习平台 Coursera 完成。

你学到了什么?

谷歌数据分析专业证书的学习过程中,你将学到进入入门级数据分析师职位的基础知识和基本技能。首先要了解这些职位的人在日常工作中使用的实践和流程。接下来,您将学习如何使用数据清理、组织、分析和可视化所需的工具,包括:

  • 电子表格(用于收集和组织数据)
  • SQL(用于组织和提取数据)
  • Tableau(用于可视化数据)
  • r(用于分析和争论数据)
  • 演示(解释和分享你的发现)

谷歌还通过简历制作工具、模拟面试和职业网络支持,在整个工作准备过程中为你提供支持,帮助你在项目完成后找到工作。

课程设置是怎样的?

Google 开发了 8 门课程,帮助你精通数据分析。前五门课程目前已经推出,最后三门预计将于四月份推出。

课程 1:学习数据分析的基础

本入门课程从一开始就温和地介绍了数据分析工作岗位的要求、数据分析师的日常工作、数据分析师取得成功所需的技能,以及完成本课程所需的基本术语和概念。

课程 2:如何提出正确的问题来做出数据驱动的决策

该计划的第二个课程重点是帮助您学习如何提出正确的问题,以做出数据驱动的决策。本课程涵盖了有效提问的基础知识,如何将这些提问技巧应用到现实世界的业务场景中,以及使用结构化思维和与利益相关者进行清晰沟通以实现业务目标的重要性。

课程 3:数据准备

第三个课程涵盖了你需要知道的关于数据准备和提取的一切。本课程包括使用电子表格和 SQL 提取数据,如何组织和保护数据,以及数据伦理和隐私的基础知识。

课程 4:数据清理

本课程涵盖使用电子表格和 SQL 进行数据清理,以及开发数据清理报告。

课程 5:数据分析

第五门课程完全侧重于使用电子表格和 SQL 的数据分析过程。在本课程中,您将学习如何使用公式、函数和 SQL 查询进行分析。

课程 6:数据可视化

本课程中的第六门课程涵盖了数据分析的叙事方面。本课程旨在帮助您了解如何让您的数据发挥作用。您将学习如何使用 Tableau 创建仪表板和可视化效果,然后学习如何向观众展示。

课程 7:使用 R 编程进行数据分析

本课程涵盖了数据分析中常用的一种编程语言。您将学习如何使用 R 和 RStudio 来清理、组织、分析、可视化和报告数据分析。

课程 8:顶点工程

这个项目的最后一门课程从教你案例研究和作品集对你找工作的好处开始,并复习求职和面试技巧。最后,你可以选择完成一个可用于你的专业作品集的顶点项目。

这门课程适合谁,不适合谁。

重要的是,在你一头扎进这个项目之前,要确保你勾选了几个选项。

本课程面向:完全的数据分析初学者,没有必备知识;每周有 10 个小时用于学习;想学习数据分析的基础知识。

本课程不适合:已经精通数据分析的人(本课程处于非常初级的水平,因此不适合已经有经验或参加过其他数据分析 MOOCs 的人);正在寻找 Python 语言的工作(尽管 Python 在事后很容易学会);没有时间专门学习该课程(数据分析最好通过定期安排来学习)。

这个项目要花多少钱?

谷歌数据分析专业证书通过 Coursera 获得,该证书每月收取 39 美元的订阅费。因此,如果你花六个月的时间完成课程,费用大约是 234 美元。

因为这个月订费,所以尽量尽快完成课程以降低成本是有意义的。然而,重要的是要记住,这比你参加训练营(可能在 3000 美元到 15000 美元之间)或获得数据科学硕士学位的成本要低得多。

Coursera 为那些需要的人提供经济援助。

如何学习谷歌数据分析专业证书?

由于 MOOCs 的平均完成率不到 10% ,所以通过弄清楚你打算如何学习该证书来尽早为自己的成功做好准备是非常重要的。

有一个学习计划,尤其是如果自学不是你真正的事,将有助于你完成这门课程,并记住你所学的一切。

作为一个正在自学整个大学学位,目前平均绩点为 3.8 的人,我觉得自己特别有资格写一写如何在自学方面为自己的成功做准备。

谷歌建议,如果你每周花 10 个小时学习和浏览课程材料,你可以在 6 个月内完成课程。对于想要改变职业的普通职业人士来说,这个时间表是合理的。也就是说,如果你没有其他任务,这个课程可以在更短的时间内(2-3 个月)完成。

该计划提供 180 小时的教学和数百次基于实践的评估,你不能只是坐在那里,一边看视频一边吸收信息。为了最大限度地利用课程和每天有限的时间完成课程,你需要在整个过程中积极地学习。

制定一个时间表。

完成本课程的第一步是为你自己制定一个你实际遵循的学习时间表。

很容易告诉自己,你将每天学习十个小时,直到你真的到了那一天,并意识到十个小时的学习真的是多么令人疲惫不堪。不出一周,你就会精疲力尽,成为 90%没有完成 MOOCs 的人之一。

相反,通过创建一个平衡的时间表来调整自己的节奏。

每周 10 小时的学习可以分成 4 天,每天 2.5 小时。当你意识到普通人每天花三个半小时打电话时,你会突然变得更有建设性地利用时间。

在此基础上,你计划在这 2.5 小时内完成课程的哪些部分。

例如:

周一:完成第一周的讲课、阅读和测验。

周三:完成第一周的练习题。

周五:完成第二周的讲座、阅读和测验。

周日:完成第 2 周的练习。

把这个时间表打印出来,放在显眼的地方,你会一直记得你完成这个计划的承诺。

让自己负责任。

制定一个时间表当然很好,但前提是你要坚持并完成一周内你需要做的所有事情。

无论你是通过直播或拍摄你的学习课程、加入学习小组、写关于你学习的博客,还是让一个值得信赖的朋友提醒你需要学习,重要的是要记住保持你的责任保险(保持你学习动力的东西)的一致性。

科技类的课程最好是持续的、有规律的学习,所以你必须尽早建立一个有纪律的学习习惯。

旨在对主题有广泛的理解。

学习技术和学习其他任何东西都是完全不同的。通常情况下,你需要对某个领域的主题有深刻的理解才能取得成功,而在科技领域,你只需要对主题有广泛的理解(并愿意承认自己不知道的事情)。

由于科技教育的开放性,用谷歌搜索任何你不知道的东西是非常容易的。任何知识深度的缺乏都可以通过搜索任何你不理解的东西来进行即时学习的能力来抵消。

因此,你最好把时间花在广泛理解本课程的所有主题上,并学习如何有效地应用它们。

做有效的笔记。

如前所述,学习技术与你以前可能学过的任何东西都完全不同。因此,你记笔记的类型也会不同。

为了支持我们对概念有广泛理解的想法,做笔记帮助这种广泛理解是很重要的。关键是不要做大量的笔记。相反,集中精力掌握一般概念,并写笔记帮助你应用它们。

写笔记已经被证明是帮助学生记住信息的学习工具,这就是为什么它被强烈推荐的原因——尤其是在自学的时候。它不仅能帮助你学习重要的东西,还能帮助你保持参与和积极学习。

不要跳过顶点工程。

谷歌将他们项目的最后一个顶点项目设为可选项目,这意味着你不必完成它就能通过课程。

虽然浏览 180 个小时的学习材料并完成所有的学习练习会让你觉得你知道关于数据分析的所有知识,但记住最好的学习方法是实践,这一点很重要。

随之而来的是完成顶点工程。

虽然单独完成数据分析的所有不同步骤很容易,但将它们放在一起完成完整的分析却是一件全新的事情。

由于对教师的要求和课程提供者必须付出的额外努力,大多数 MOOCs 不提供顶点项目。简而言之,错过一个让谷歌员工回答你遇到的任何问题的机会是愚蠢的。

通过把所有的碎片放在一起,你允许自己在实践中学习。这一行动将会比你仅仅完成分析的每一部分而放弃顶点项目更长久地伴随着你。

最后的想法。

只有这种保证工作成功的说法才会被谷歌这样的公司吹捧,尽管它仍然没有根据。时间会证明这个项目是否能有效地让没有经验的人进入数据分析师的角色。

无论如何,这个全面发展的项目提供了一个世界一流教育的绝佳机会,其成本只是通常可比的训练营或硕士学位的一小部分。

睁大你的眼睛,制定一个坚实的计划,参加这个项目,你没有理由不能完成这个项目,成为进入这个竞争激烈的行业的幸运儿之一。

如何学习 IBM 数据分析师专业证书

原文:https://towardsdatascience.com/how-to-study-for-the-ibm-data-analyst-professional-certificate-427a16da9fd9?source=collection_archive---------4-----------------------

如何成功获得“原创”数据分析师专业证书概述

Unsplash 上由 PolaroMagnet 拍摄的照片

作为谷歌数据分析专业证书的老大哥,IBM 数据分析师专业证书提供了基于 Python 的相同公式的对等物:由技术游戏中的历史名称提供的在线、自定进度的数据分析师课程。

如今,能够从科技行业的重量级人物那里获得行业认可的证书来提升你的简历,足以让任何人都为之倾倒。IBM 承诺,他们将教你在数据分析师就业市场中有竞争力地定位自己所需的技能(不需要以前的经验),对于那些寻求提升技能和改变职业的人来说,这门课程变得显而易见。

所有的你需要开始使用这个 IBM 专业证书是基本的计算机知识,高中数学能力,一些与数字打交道的舒适,和学习的意愿。

如果说过去的一年多教会了我们什么,那就是职业幸福比呆在舒适区更重要。尽管对未来充满不确定性,四分之一的员工正在考虑在疫情之后辞职,这是一个明确的信号,表明人们把自己放在第一位。有什么比现在更好的时间来开始提升技能,以保证你有更好的就业选择呢?

美国有 72,633 个开放数据分析师职位,平均工资为 74,440 美元,预计 10 年增长率为 9%,这一价格合理、自定进度且易于学习的课程是在无需做出重大生活改变的情况下入门的最佳方式。

什么是 IBM 数据分析师专业证书?

IBM 数据分析师专业证书是由 IBM 设计的完全在线和自定进度的专业培训课程,为您成为初级数据分析师做准备。

该计划由 9 门课程组成,可在 11 个月内完成,每周不超过 3 小时。该计划是 100%在线,让您按照自己的节奏学习。

该计划还提供 11 种语言(英语、阿拉伯语、法语、葡萄牙语(欧洲)、意大利语、越南语、德语、俄语、西班牙语、土耳其语和波斯语),使其适用于各大洲的人们。

这些课程通过在线学习平台 Coursera 完成。

你学到了什么?

IBM 数据分析师专业证书的学习过程中,您将学到进入入门级数据分析师职位所需的所有技能。

这从温和地介绍数据分析的概念开始,发现不同数据相关角色之间的主要差异,学习向利益相关者传达数据分析结果所需的软技能,并揭示数据生态系统中的主要供应商。从那里,您将开始学习数据清理、组织、分析和可视化所需的工具,包括:

  • 电子表格(用于基本级别的数据争论、清理、分析、过滤和排序)
  • Excel 和 IBM Cognos Analytics(用于数据可视化和仪表板)
  • Python(用于数据结构和分析)
  • SQL(用于争论、组织和查询数据)
  • Pandas、Numpy 和 Scipy(用于操纵、分析和使用机器学习算法)
  • Matplotlib、Seaborn 和 Folium(用于数据可视化)

通过参加这个项目,你还可以获得 Coursera 职业服务,在那里你可以了解最新的招聘趋势,获得个性化的面试培训,并与招聘专家交谈。此外,IBM 在整个课程中提供了几个项目机会(包括一个最终的顶点项目),可以用来支持您的专业组合。

课程设置是怎样的?

IBM 开设了 9 门课程,将引导你成为一名熟练的初级数据分析师。

课程 1:数据分析简介

本课程首先简要介绍数据分析的概念、数据分析师的角色以及用于执行日常功能的工具。在本课程结束时,您将了解数据生态系统、数据分析的基础知识,以及成为一名使用数据的有效说书人所需的软技能。

课程 2:数据分析的 Excel 基础

本课程结束时,您将掌握使用 Excel 电子表格进行数据分析的基本工作知识。本课程涵盖了使用电子表格的基础知识以及它们在数据分析过程中的用法。从那里,您将学习使用电子表格处理、清理和分析数据的基础知识。

课程 3:使用 Excel 和 Cognos 的数据可视化和仪表板

本课程深入探讨了电子表格的特性和功能,让您能够使用 Excel 和 IBM Cognos Analytics 完成基本的数据分析,而无需编写任何代码。

课程 4:用于数据科学、人工智能和开发的 Python

本课程结束时,你将在几个小时内从零编程经验过渡到编写 Python 代码。

课程 5:数据科学的 Python 项目

本项目课程为您提供了一个机会,通过使用 Python 开发仪表板来展示和实践您新学到的处理数据的 Python 技能。

课程 6:使用 Python 的数据科学的数据库和 SQL

本课程向您介绍关系数据库的概念,并帮助您学习 SQL 语言的基础知识。您将学习如何在云中创建数据库实例,构建和运行 SQL 查询,以及使用 SQL 和 Python 从 Jupyter 笔记本访问数据库。

课程 7:使用 Python 进行数据分析

本课程将带您从之前学习的 Python 基础知识,到准备数据进行分析、执行简单的统计分析、创建可视化以及预测未来趋势。涵盖的主题包括导入数据集、清理数据、数据框操作、汇总数据、构建机器学习回归模型和构建数据管道。您将学习如何使用流行的 Python 库(如 Pandas、Numpy 和 Scipy)来完成这些任务。

课程 8:用 Python 实现数据可视化

本课程将教您使用流行的 Python 库(包括 Matplotlib、Seaborn 和 Folium)创建有效的数据可视化。

课程 9: IBM 数据分析师顶点项目

该计划的高潮为您提供了完成全面数据分析的机会,从开始从多个来源收集数据,一直到提交带有执行摘要的数据分析报告。

证书要多少钱?

IBM 数据分析专家证书通过 Coursera 在线学习平台获得,该平台每月订阅费用为 39 美元。因此,如果你用建议的 11 个月完成课程,费用大约是 429 美元。

由于每月的费用,尽可能快地完成课程以降低成本可能是有意义的。然而,重要的是要记住,这门课程已经比数据科学训练营(在那里你可以支付 3000 美元到 15000 美元的体验)或如果你要获得数据科学硕士学位,要便宜得多。

Coursera 还为有需要的人提供经济援助和奖学金。

Coursera 还提供了一个选项,你可以对一门课程或整个项目进行审核。您将不会获得证书,也不能提交任何作业和获得分数,但您仍然可以访问所有的课程材料。

如何学习 IBM 数据分析师专业证书?

尽管它们很容易进入,MOOCs 的平均完成率不到 10%。这使得你尽早做好尽职调查并找出完成该证书的最佳方式变得更加重要。

制定一个专门的学习时间表,尤其是如果自学不是你的强项,将有助于你完成课程并成功记住你所学的一切。

IBM 建议,如果你每周花 3 个小时浏览课程材料,你可以在 11 个月内完成课程。对于那些在工作之外还有全职工作的普通人来说,这个时间表是合理的。但是,如果您没有其他任务,本课程可以在更短的时间内(1-4 个月)完成。

有 100 多个小时的课程内容要完成,如果你只是被动地看视频,而不是实际地做笔记或完成作业和练习题,那么你不可能从课程中获得任何东西。换句话说,要想从课程中获得最大收益,并真正发展那些能让你在竞争激烈的就业市场中获得资格的技能,你必须工作。

了解学习过程。

如上所述,MOOCs 的平均完成率不到 10% ,这可能是由于学生缺乏有纪律的学习。由于人类的注意力持续时间比金鱼短,我们开始做一些事情时,很自然会被突然出现的更闪亮更新的东西分散注意力。知道了这一点,我们需要更聪明、更勤奋、更自律地学习来完成在线课程。

然而,在制定时间表之前,你需要先搞清楚几件事。

开始时,当你兴致勃勃地说你将每天学习 10 小时,并在不到 3 个月的时间内完成课程,这很容易。直到你真正尝试连续一周每天学习 10 个小时,并意识到这有多难——尤其是当你从大学开始就没有这样做过。如果你遵循这种方法,你将成为 90%没有完成 MOOCs 的人的一部分。

记住你的大脑需要时间来学习东西也很重要。那些遵守 20 小时规则的人明白,虽然只需要 20 小时就能掌握一项技能,但这 20 小时的学习不可能在两天内完成,也不会有任何明显的回报。这种现象与神经可塑性有关——也称为—大脑因经历而改变和适应的能力。简而言之,通过将学习过程延长更长的时间,大脑可以开始改变,发展那些与学习新技能相关的更强的联系。

考虑到所有这些,你应该如何设置你的学习时间表来促进切实可行的学习收益突然变得清晰起来。

建立一个适合你的可行的学习计划。

要想在这个项目中取得成功,你需要先做一点准备工作。这意味着建立一个可行的学习时间表,为你,为你的生活,这将有助于你达到完成本课程的目标。

IBM 已经提出了一个超过 11 个月的学习时间表,每周花 3 个小时学习。想想看,普通人平均每天花大约三个半小时在手机上。突然之间,每周花三个小时学习那些实际上会让你长期受益的东西似乎并不困难。

从一周中挑选三天,你知道你可以花一个小时来学习。虽然我完全支持微学习过程,但学习数据分析是需要更长时间的学习才能让自己进入那种流动状态并真正钻研主题的事情之一。

在你选好三天之后,确定一天中什么时间对你最合适。在你知道自己会疲劳、分心或两者兼而有之的时候学习是没有意义的。

然后,列出你想在每次学习中完成的内容。这不仅让你一小时的学习时间变成了一小时的学习时间(没有时间去想你那天要学什么),而且也让你有责任保持在计划的轨道上。

把你制定的时间表打印出来,放在你学习空间的显著位置,作为激励自己学习的一种方式,同时也提醒自己要完成这个计划。

当你发现困难的话题时,准备好额外的信息资源。

有时候,老师不能以你能理解和吸收的方式教你你需要知道的东西。每个老师都有他们自己的教学风格或解释事情的方式,有时与你的学习风格不一致。

不要灰心丧气,手头上有额外的资源可以用来理解困难的话题。 freeCodeCamp 的 Youtube 频道、 Kaggle可汗学院走向数据科学等等,都是免费资源,可以帮助你理解棘手的东西。

仔细检查你桌子上的每道练习题和作业。

除非你练习,否则你不会变得更好。

当谈到学习数据分析时,这意味着仔细检查并完成你桌子上的每个练习题和作业。通过练习和重复,你的技能和信心会增长。所有最优秀的数据分析师都会告诉你,是专注的实践让他们做得更好。

简而言之,没有练对就不要练。练习到不出错为止。

加入其他人学习数据分析的松散工作空间或不和谐服务器,让你的旅程看起来不那么孤立。

在线学习可能是一个孤立的旅程,尤其是当你没有人可以同情的时候。社区是成为数据分析师的一个重要因素,可以真正帮助你实现目标。

加入 Slack 频道或 Discord 服务器正是可以帮助你接触到其他人,让你的学习之旅更容易,更少孤立的东西。这里有两个很好的资源可以帮助你开始:

让自己负责任。

制定一个时间表当然很好,但前提是你要真正坚持下去。科技类的课程最好是持续的、有规律的学习,这意味着你需要每周都去看书才能取得切实的成果。

让自己承担责任可以采取多种形式,比如告诉你妈妈你将在 4 个月内完成这门课程,写博客,直播自己的学习,或者加入一个学习小组。不管是什么,确保它能帮助你建立一个有纪律的学习习惯。

记录你的学习过程,作为向雇主展示你作为数据分析师的成长的一种额外方式。

学习一项新技能固然很好,但记录你的学习过程更重要。

无论是为了你自己的利益,还是作为一种向雇主展示你作为数据分析师的成长和可培训性的方式,记录你的旅程都是一种很好的方式,不仅可以回顾你取得的成就,还可以巩固你迄今为止学到的东西。

记录你的学习过程可以很简单,比如写日记、发表博客、制作 Youtube 视频,或者告诉别人你那天学到了什么。奖励点,如果你可以货币化!

最后的想法。

关键要点:

  • IBM 提供了基于 Python 的谷歌数据分析专业证书的替代方案:一个在线的、自定进度的数据分析师课程,由科技游戏中的一个历史名称提供
  • IBM 数据分析师专业证书有 9 门课程,可以在 11 个月的学习中完成,并以 11 种语言提供。
  • 本课程结束时,您将学习 Excel、IBM Cognos Analytics、Python、SQL、Pandas、Numpy、Scipy、Matplotlib、Seaborn 和 Folium。

尽管不能保证这门课程将开启你作为数据分析师的职业生涯,但它确实提供了一个保证的好处:以完成训练营或硕士学位所需费用的一小部分,你就有机会通过向业内一些最优秀的人学习,在一个新兴领域发展技能。

如何用 Python 设计你的数据框架

原文:https://towardsdatascience.com/how-to-style-your-dataframe-with-python-eabf376d1efd?source=collection_archive---------36-----------------------

如何使用 Python 高亮显示、格式化或着色您的数据框

Arnel Hasanovic 在 Unsplash 上拍摄的照片

我喜欢 Excel 的条件格式,这是一种简单而优雅的方式来突出你的表格中的关键要点。我们能在熊猫数据框中做同样的事情吗?绝对的!

在本文中,我们将学习如何格式化数据框:

  • 根据条件给数字涂上颜色
  • 突出显示最小值/最大值/空值
  • 数据框中的条形图
  • 热图

入门指南

让我们导入所需的库,并用随机数和 NaNs(不是数字)创建一个数据帧。

具有随机数和 NaNs 的数据帧

我们将使用这个数据帧来应用格式和样式。

根据情况给数字涂上颜色

我们将根据情况给数字涂上颜色。例如,我们希望负值为红色,位置值为绿色,NaN 为蓝色。

对数据帧应用颜色

首先,我们必须定义一个apply_colour函数来返回我们想要的颜色。然后我们使用apply_map将颜色应用到数据框的样式上。

对于Styler.applymap,你的函数应该接受一个标量并返回一个带有 CSS 属性-值对的字符串。

突出显示最小值/最大值/空值

有一个内置函数可以突出显示系列中数据的最小值/最大值/空值。

应用内置函数非常简单,我们只需将颜色参数传递给函数,它将突出显示每个系列中的最小值/最大值/空值。

应用于子集

如果我们只想突出显示某一列或某一行,我们可以使用 subset 参数。

例如,我们可以将subset=['C','D']传递给highlight_max,这样它将只突出显示列 C 和 d

我们也可以定义子集中的行的范围。我们可以使用subset = pd.IndexSlice[2:5, ['C','D']]将 C 列和 d 列的第 2 行切片到第 5 行。

对于行和列切片,任何到.loc的有效索引器都将工作。

一起申请

我们也可以将highlight_maxapplymap(apply_colour)一起应用于数据帧。

带有 highlight_max 和 applycolour 的数据帧

塔当!现在你的数据框架上同时有了highlight_maxapplycolour样式!

数据框中的条形图

我非常喜欢 Excel 中的数据栏条件格式,是的,我们也可以在 dataframe 中这样做!

style.bar用于在数据框中创建条形图。和highligh_max一样,我们可以给它传入subsetcolor参数。

在最新版本中,我们能够进一步定制条形图。现在,我们可以使用align = 'mid’将工具栏居中。此外,我们可以将列表[color_negative, color_positive]传递给颜色参数。

热图

我们也可以在数据帧上创建热图!

我们可以使用seaborn来得到一个漂亮的颜色图!

否则它接受来自 Matplotlib 的任何颜色图,你可以在这个颜色图参考中查看!与前面的函数相同,background_gradient也接受子集作为参数。

现在你已经学会了如何用 Python 设计你的数据框架的样式。希望这篇文章对你有用。可以在我的 Github 中查看完整的 Jupyter 笔记本。干杯!

PS:样式直接在 Github 中无法正常渲染,你可能想在你的本地机器上试试。

如果你喜欢读这篇文章,你可能也会喜欢这些:

你可以在 Medium 上找到我其他作品的链接,在这里关注我https://medium.com/@chingjunetao。感谢阅读!

如何成功运行 A/B 测试

原文:https://towardsdatascience.com/how-to-successfully-run-a-b-tests-f3ca363dec98?source=collection_archive---------24-----------------------

积极尝试各种事物的大型科技公司的最佳实践

Unsplash 上由 Ousa Chea 拍摄的照片

所有最成功的科技公司都在不断试验和改进他们提供给用户的产品。A/B 测试是一种广泛使用的技术,用于确定操作特性的影响。

“随机 A/B 或 A/B/N 测试被认为是许多定量科学领域评估治疗效果的黄金标准。”优步的 Anirban Deb 等人

虽然 A/B 测试在许多数据驱动的决策中发挥着重要作用,但它们很难成功运行,也更难大规模运行。

在这篇文章中,我们将看看一些最成功的科技公司是如何设计系统来正确运行数千次 A/B 测试的。我们不需要重新发明轮子来成功地运行这些测试。我们可以将大型科技公司在他们的实验平台上所做的事情视为运行可扩展的 A/B 测试的最佳实践。

如果您有兴趣了解特定公司运行 A/B 测试的方法,请查看以下链接:

什么是 A/B 测试?

在进入细节之前,我们对什么是 A/B 测试有相同的理解是很重要的。

它们是有一个对照组和一个或多个治疗组(或实验组)的实验。控制组体验的服务和往常一样。治疗组体验具有改变的特征的服务(例如主页上按钮的改变的颜色)。

实验的目的是确定治疗组经历的变化相对于对照组的影响。影响需要是一个可衡量的指标,如在一个页面上花费的时间,查看次数,或与按钮的交互次数。

分配到治疗组和对照组时,应最大限度地提高各组之间的相似性,以降低观察到的治疗效果中混杂因素的风险。这通常通过随机分配来完成。

为什么 A/B 测试很重要

我们可以通过 A/B 测试的受欢迎程度和结果来理解它的重要性。

我们首先来看看我们研究的五家公司对 A/B 测试在其决策过程中的重要性有什么看法:

“事实上,网飞考虑的每一个产品变化在成为默认用户体验之前都要经过严格的 A/B 测试过程。”—网飞科技博客

“在任何给定的时间,我们的平台上都有超过 1000 个实验在运行。”优步的 Anirban Deb 等人

"今天,几乎所有的产品决策都是根据一个或多个 A/B 测试的一些输入做出的."—约翰·里德伯格,Spotify

“作为一家数据驱动的公司,我们非常依赖实验来指导产品和功能。在任何给定的时间,我们都有大约 1000 个实验在运行,并且每天都在增加。”—硕翔,Pinterest

“实验是 Twitter 产品开发周期的核心。这种实验文化是可能的,因为 Twitter 在工具、研究和培训方面投入了大量资金,以确保功能团队能够无缝、严格地测试和验证他们的想法。”推特上的德米特里·里亚博伊

你明白了。成功的公司总是通过实验来改进他们的平台。他们是决定这些公司几乎每一项决策的重要因素。

A/B 测试是一个非常有用的工具。它们允许大规模的公司测试增量变化,而不用将它们暴露给所有的客户。然后,这些结果可以相对概括到客户群体中。

“但是,如果不进行广泛的 A/B 测试,推出[变更]的风险太大,这样我们就能证明新体验优于旧体验。”—网飞科技博客

网飞声称已经对他们与标题相关的图片进行了 A/B 测试,结果该标题的浏览量增加了 20%到 30%。

有了这些类型的影响,就很清楚为什么公司要进行如此多的实验了。它不仅有用,而且有必要为客户提供最佳体验。

构建可扩展的实验平台

我们现在明白,所有成功的企业在做出每一项改变之前都会积极地进行试验。他们是如何在数千个并发测试的规模上成功运行所有这些测试的?

这些平台的基本特性

所有实验平台的设计都类似,至少包含以下三个组件(来自 Spotify 系统的名称):

  1. 远程配置 —允许用户选择要测试的前端或后端服务的特性
  2. Metrics catalog——一个管理、存储实验数据并以最小延迟将数据提供给用户界面或笔记本的系统(Spotify 的目标是不到一秒)。
  3. 实验规划器 —允许员工通过易于使用的用户界面进行实验

这些平台的目标在五家公司中也大致相同(Pinterest 的目标名称):

  1. 实时配置更改:实时关闭和启动实验,无需为每个更改部署代码
  2. 轻量级流程:应该防止可预测的错误,但是要像普通的特性启动一样简单
  3. 客户端无关:用户不需要学习一种新的方法来为每个平台运行实验。
  4. 分析:易于使用的分析仪表板
  5. 可伸缩性:需要能够伸缩在线服务和离线实验数据处理。

我们分析的所有这些企业都有多样化的产品和部门组合。因此,考虑到平台的通用性以满足不同的业务需求是很重要的。优步在其大多数数据平台中都非常重视这一点。

“我们团队的主要目标之一是提供一种适用于整个公司用例的假设检验方法。”优步的 Anirban Deb 等人

如何正确地将用户分配到治疗组和对照组

这些实验最重要的部分之一是将用户正确地分配到治疗组和对照组。如果分组不够相似,结果就没有意义。无法判断观察到的治疗效果是由实验操作还是组间差异(称为混杂因素)引起的。

优步确定了两个关键问题来限制这些问题的风险:

  1. 样本量失衡:如果对照组与治疗组的样本量比例与预期比例显著不同,实验人员应检查其随机化机制是否成功建立。
  2. 闪烁:如果用户在实验期间在控制组和治疗组之间转换(例如,用户购买了一部新的 Android 手机,并曾经拥有一部 iPhone),他们应该从分析中移除。

优步的平台会自动识别这些问题。

Spotify 描述了他们执行的一些测试前有效性检查,以确保结果能够被解释:

  1. 样本不匹配:确保治疗组和对照组的比例与实际观察到的一致。
  2. 预曝光活动:查看用户与应用程序的交互方式是否有任何预实验差异。
  3. 崩溃增加:确保应用程序在实验过程中仍能正常工作
  4. 属性冲突:确保分析师知道类似的实验何时进行,以降低无法获得预期的风险。

如何将用户分配给实验

随着这些公司测试数量的增加,跟踪哪些用户被分配到了哪些实验变得非常重要。不应将用户分配到与其当前参与的实验相冲突的实验(在同一页面上操作多个功能)。

“如果有人最终使用了错误的(分配),一系列实验都会受到影响”——约翰·里德伯格,Spotify

Spotify 采取了一种有趣的方法,他们称之为“盐机”。Spotify 的团队按照最适合他们的节奏自主工作。这导致实验用户分配的复杂性(同时保持分配的关键随机性)。“盐机器”通过使用“盐”树散列到桶中,随机地将桶中的用户重新洗牌(不停止正在进行的实验)这里有详细的解释和可视化这里有

网飞将更多的责任交给运行实验的用户,有两个分配选项:批量分配和实时分配。

批量分配允许分析师使用自定义查询将用户分配给测试。这是他们更灵活的方法,帮助分析师找到他们感兴趣的确切客户。一些缺点包括不能保证所有用户都体验到测试,新用户不能被添加到实验中。

实时分配允许分析师配置关于用户如何实时与应用程序交互的不太灵活的规则,以将他们分配给实验。这保证了用户体验预期的治疗,因为他们正在与应用程序实时交互。也很难知道在这种制度下何时会处理或分配所需数量的成员。最后,潜在增加的应用延迟可能是这种方法的一个问题(在应用等待其他服务时,网飞通过并行计算解决了这个问题)。

要跟踪的指标

随着公司产品数量的增加,跟踪哪些指标的问题会很快变得复杂。这些实验平台中的许多都具有灵活的度量能力,允许分析师测试他们感兴趣的内容。

Twitter 允许分析师使用三种不同类型的指标(增加分析师的灵活性):

  1. 内置指标:由实验团队定义和拥有
  2. 实验者定义的:使用轻量级 DSL 创建的配置度量,指定应该计数什么“事件”。
  3. 导入的指标:实验者创建他们自己的指标,并将它们添加到系统中。

优步定义了三种类型的指标,允许分析师创建:

  1. 连续指标:数值
  2. 比例度量:二进制指示变量,表示用户是否执行某个事件
  3. Ratio metrics :允许分析师计算比率的两列(分子表示已完成行动的数量,分母表示可能完成行动的总人数)。

预处理和有效性检查

在解释结果之前,优步做了三个预处理步骤来提高他们分析的稳健性:

  1. 异常值检测:去除数据中的异常。他们通过基于聚类的算法来检测异常值。
  2. 方差减少:增加假设检验的统计功效(有助于少量用户的实验)。为此,他们使用了 CUPED 方法
  3. 实验前偏差:有时随机化并不能产生很好的组分配。为了纠正这一点,他们使用[差异](https://en.wikipedia.org/wiki/Difference_in_differences#:~:text=Difference in differences (DID or,' versus a 'control group')来纠正这些作业中的偏差。

如何有效地解释结果

获得精确的 p 值计算至关重要。如果结果不容易解释,这个实验就不值得进行。优步描述了他们用来计算统计结果的四种不同的测试:

  1. 【韦尔奇 t 检验】 —用于连续指标
  2. 曼-惠特尼 U 检验 —在有偏差的数据中表现良好
  3. 卡方检验 —用于比例指标
  4. https://alexdeng.github.io/public/files/jsm2011-deng.pdf—用于小样本量(这是一种 bootstrap 方法)

当在一个公司运行数千个测试时,有可能产生被称为类型 1 和类型 2 错误的统计错误。为了降低统计发现不真实的风险,降低错误发现率(FDR)非常重要。优步使用了 Benjamin-Hochberg 程序。

扩展这些平台的挑战

Spotify 确定了它在扩展其实验平台时面临的四个问题,这些问题需要在 2017 年解决:

  1. 缩短用实验调整问题的时间
  2. 产生更少的事件:A/B 测试产生总事件量的 25%,导致处理成本增加
  3. 改进的分析:需要更多的度量标准,需要更多可以分析的东西。
  4. 复杂的协调:不允许同一个用户被分配到多个相互冲突的实验中

所有这些优化对于允许 Spotify 扩展其运行的实验数量非常重要,在构建实验平台时应该加以考虑。

结论

在今天的商业环境中进行实验是必要的。A/B 测试是一种工具,它使我们能够对客户进行因果推断,而无需对所有客户进行测试。

“感谢工程师和数据科学家团队,他们不断对我们的自适应流媒体和内容交付网络算法进行 A/B 测试。更明显的变化呢,比如我们 UI 布局的完全重新设计或者我们新的个性化主页?是的,全部经过彻底的 A/B 测试。”—网飞科技博客

正在尝试的企业正在为他们的客户提供更好的体验,而不是盲目地做出可能对客户体验产生巨大影响的改变。

Twitter 将这一重要过程视为包含 6 个步骤的创新周期:

  • 建立一个假设
  • 定义成功指标
  • 测试假设
  • 学习
  • 建立另一个假设

我们了解了顶尖的科技公司如何大规模地成功解决这些步骤中的问题。

感谢您阅读这篇文章。

如何成功地将你的人工智能项目从试点扩展到生产

原文:https://towardsdatascience.com/how-to-successfully-scale-your-ai-project-from-pilot-to-production-b10e3c359b9c?source=collection_archive---------37-----------------------

照片由 Unsplash 上的艾米利·莫里雄拍摄

关于如何获得成功的试点项目并将其应用于生产的四个实用技巧

没有人需要说服我们今天人工智能的价值,无论是对商业目标还是社会。

但是为了让我们利用所有这些价值,我们需要扩大人工智能项目。事实是,许多公司现在正在尝试这样做。

在这种情况下,当在一个组织内引入人工智能时,人工智能试点项目或人工智能概念验证经常被使用,因为它们可以快速启动一个新的流程、产品或合作伙伴关系,同时又是一个低风险的替代性更严格和成本更高的“标准”项目。

但是如果你的试点项目成功了,你将如何推广它呢?

在你的公司挨家挨户地说,每个人都应该实施你的新人工智能解决方案或工具,这听起来不是一个好策略。

使适应您独特的试点环境成为可能的一个基本部分是建立鼓励整个公司的团队继续适应试点的条件。

在扩展人工智能项目时,有一些方面和因素是至关重要的。总的来说,这些因素决定了哪些计划更有可能成功。

一些成功的因素可能是区分那些成功扩展其人工智能项目的组织和那些不成功的组织的标准。

在这里,我列出了一些决定商业中最常见的人工智能实现成功的关键因素:

  • 项目锚定在业务目标中,并由高级管理层(C 级)发起
  • 能够创建一个具有良好定义的组织结构和治理的人工智能战略和规模模型
  • 多学科团队,不仅仅由 IT 领导者领导或局限于 IT 筒仓。
  • 对人工智能项目的持续时间有清晰和现实的期望,并关注要点。
  • 发展数据技能以从分析中提取价值的能力
  • 实验心态
  • 项目准备合作者的可用性。

成功实施的提示

考虑到前面的大多数关键因素,我在这里准备了一个列表,其中有四个基本技巧,可以帮助你设计和管理一个成功的人工智能实施计划,以将你的概念证明和原型扩展到生产水平。

以正确的速度做正确的事情!

扩展一个人工智能项目不是一个自然的过程,也不是很快。一般来说,要成功完成这一步,大约需要一到两年

除了被商业目的所驱使,成功是因为精心的准备。

这意味着 compWehat 非常实用,并准备建立正确的数据基础,实施正确的流程,分配正确的领导者,拥有正确的技能,并做到这一点。

为了取得成功,您需要将您的人工智能工作投入到获得高层管理人员的具体支持中,确定与业务目标相关联的具体用例,并重新定义数据治理的流程。

要有好的结果,花对了!

人工智能项目只有在投入高的情况下才会有好的结果,这是不正确的。

在扩大人工智能项目方面取得成功的公司在更长期的项目上花费更少,因为他们在决定把钱花在哪里时非常细致和有战略眼光。

他们组织他们的数据,雇佣合适的人才并实施特定的技能。

你肯定不希望成为那些由于预算使用效率低下而无法扩展人工智能计划的组织俱乐部的新成员,对吗?

打破您内部的技术孤岛

谁说 AI 项目一定只能由 IT 领导和专业人士来运行?

很多时候,成功的 AI 倡议是那些单个领导者或部门参与的,他们将处理组织中与人工智能相关的所有点,而是一个跨学科的团队。

业务必须与技术联系起来,因为只向公司技术领域汇报的人工智能项目比在业务领域或首席执行官的指挥下更有可能成功。

成功的公司打破孤岛接触商业、金融,当然还有在人工智能计划中合作的技术领导者。

用正确的数据做正确的事情。

数据是任何 AI 项目的原材料,毫无疑问需要很好的工程化。

根据我的经验,我看到许多人工智能项目在数据质量和完整性方面都出现了一致的问题。

然而,并不总是数据越多越好。在你跑着穿过公司尖叫着要数据之前,有必要确定你是否有正确的流程:如何有效地监控和处理数据。

这样,您将在工程设计过程中帮助确定和构建项目的必要数据,这些数据具有最小的范围,并专注于基本部分,以达到组织想要的结果。

结论

在很大程度上,人工智能试点项目只是一个长期、合作和迭代过程的开始,直到生产并确保良好的投资回报。

如果你允许这一过程展开,你就能揭示你的商业潜力,用人工智能进行创新。

还有一件事…

如果你想了解更多关于人工智能以及如何学习它,以及它将如何影响商业和我们的社会,下面的文章可能会让你感兴趣:

【非常】工业 4.0 中的 AI 简介

人工智能和数字化转型将如何永远改变你的业务

让你学习 AI、机器学习、数据科学印象最深刻的 Youtube 频道。

如果你想继续发现新的资源并了解人工智能,在我的电子书(下方的链接)中,我正在分享关于人工智能、机器学习、深度学习、数据科学、商业智能、分析和其他方面的最佳文章、网站和免费在线培训课程,以帮助你开始学习和发展职业生涯。

学习 AI 在线:200 多种资源在线今天开始学习 AI

此外,我刚刚在亚马逊上发布了其他有趣的电子书,我相信其中一些可能会让你感兴趣……让我们保持联系,关注我,让我们一起做吧。

https://www.amazon.com/dp/B08RSJRNSNT21

参考

  1. 十个人工智能项目有七个失败…https://labs news . com/en/news/technology/seven-out-of-ten-artificial-intelligence-projects-fail-by-study/

如何抑制熊猫设定 SettingWithCopyWarning

原文:https://towardsdatascience.com/how-to-suppress-settingwithcopywarning-in-pandas-c0c759bd0f10?source=collection_archive---------3-----------------------

了解 pandas 中副本和视图之间的区别以及如何处理带有副本警告的设置

Sandy RavaloniainaUnsplash 上拍摄

介绍

这无疑是新来的熊猫遇到的最常见的问题之一。本文解释了为什么首先抛出警告,并讨论了如何抑制它。此外,我们还将讨论一些提示和最佳实践,以避免收到此警告消息。

即使 **SettingWithCopyWarning** 仍然是一个警告,您也必须确保您首先准确理解为什么会出现这个问题,以避免意外行为。

首先,让我们创建一个虚拟数据集,我们将在这篇文章中使用。

import numpy as np
import pandas as pd # Set random seed so that results are reproducible
np.random.seed(0)df = pd.DataFrame(
    np.random.choice(100, (3, 4)), 
    columns=list('ABCD')
)print(df)
#     A   B   C   D
# 0  39  87  46  88
# 1  81  37  25  77
# 2  72   9  20  80

什么是设置 WithCopyWarning

在讨论如何抑制SettingWithCopyWarning之前,先了解这个警告是关于什么的,以及它是由什么触发的,会有所帮助。

SettingWithCopyWarning是一个警告,意味着您的代码可能仍然有效。然而,重要的是不要忽视它,而是首先理解为什么会提出它。这样,您就更容易相应地调整代码,从而不再引发警告。

熊猫中的视图和副本

当您对 pandas 数据帧执行过滤操作时,结果可能是数据帧本身的视图副本,这取决于与 df 结构相关的一些实现细节。

视图与原始数据框架共享底层数据,因此当您修改视图时,您也可以修改原始对象。副本是原始数据帧的独立副本(子集),因此,对副本所做的任何更改都不会影响原始对象。

来源:作者

为了演示副本和视图之间的区别,让我们考虑下面的例子。

>>> df_slice = df.iloc[:3, :3]
>>> df_slice
    A   B   C
0  44  47  64
1  67   9  83
2  36  87  70

这个简单的切片返回一个视图,这意味着原始 df 中的变化将反映到df_slice中,反之亦然。

>>> df_slice.iloc[1, 1] = 1
>>>
>>> df_slice
    A   B   C
0  44  47  64
1  67   1  83
2  36  87  70
>>>
>>> df
    A   B   C   D
0  44  47  64  67
1  67   1  83  21
2  36  87  70  88
>>>
>>> df.iloc[1, 1] = -1
>>>
>>> df_slice
    A   B   C
0  44  47  64
1  67  -1  83
2  36  87  70

另一方面,对副本的操作不会对原始数据帧产生任何影响。例如,下面的操作将返回副本而不是视图

>>> df.loc[df.A > 5, 'B']

现在,如果您对副本应用操作,您很有可能会遇到下面的警告:

__main__:1: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value insteadSee the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

该消息只是警告用户他们正在操作一个副本,而不是原始对象本身。在下一节中,我们将讨论触发该警告的链式赋值或索引问题。

链式分配

如上所述,SettingWithCopyWarning表示潜在的链式分配。首先,让我们定义一些术语,以确保我们说的是同一种语言。

  • 赋值是赋值(或设置)值的操作
  • 访问是返回(或获取)值的操作。例如,当我们索引一个数据帧时,我们几乎是在访问它。
  • 索引是分配或访问值的操作,可能只引用原始数据的子集(例如,列和/或行的子集)
  • 当我们以背靠背的方式执行多个索引操作时,就会出现链接。例如,df[1:][1:5]是一个链接操作。

因此,链式赋值被定义为链式和赋值操作的组合。为了说明这种类型的操作,让我们考虑一个例子,在这个例子中,我们希望为每一个具有A = 8的记录将值-1赋给列B:

>>> df[df.A == 44]['B'] = 100

通常,上述操作会触发警告:

__main__:1: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value insteadSee the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

现在,如果我们打印出原始的df,上面的操作根本没有效果:

>>> df
    A   B   C   D
0  44  71  70  53
1  32  64  44  67
2  38   2  98  50

所以在上面的例子中,发出警告是因为我们将两个操作链接在一起:

  • df[df.A == 44]
  • ['B'] = -1

这两个操作将在独立的上下文中依次执行。第一个操作是访问操作,即基于过滤条件返回数据帧的 get 操作,使得列A的值等于数值 44。第二个操作是赋值操作,它在原始数据帧的副本上设置特定值。

在接下来的部分中,我们将讨论一些方法,您可以使用这些方法来使这种操作更加安全,同时也抑制警告。

如何取消设置 WithCopyWarning

在这一节中,我们将讨论以下解决方法,这些方法可以用来修复您的代码,使SettingWithCopyWarning根本不会被引发。

  • 如何使用**loc[]**以不提高SettingWithCopyWarning的方式对子集进行切片
  • 在执行赋值操作之前,获取原始数据帧的深度副本
  • 禁用链式分配的检查,使SettingWithCopyWarning不再上升

使用 loc 进行切片

现在,如果我们仔细检查提出的警告,我们会注意到它还附带了一个建议:

__main__:1: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
**Try using .loc[row_indexer,col_indexer] = value instead**See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

可用于抑制SettingWithCopyWarning的一种方法是将链式操作执行成单个loc操作。这将确保赋值发生在原始数据帧上,而不是副本上。因此,如果我们试图这样做,就不应该再发出警告。

为了说明如何使用loc来抑制SettingWithCopyWarning,让我们再次考虑上一节的例子。

>>> df[df.A == 44]['B'] = 100

上述语句可以重写为

>>> df.loc[df.A == 44, 'B'] = 100

现在,您会注意到不再发出警告,并且这次的赋值操作对原始数据帧产生了影响:

>>> df
    A    B   C   D
0  44  100  70  53
1  32   64  44  67
2  38    2  98  50

一般情况下,您需要确保使用 **loc** 进行标签索引,使用 **iloc** 进行整数或位置索引,因为这样可以保证它们对原始对象进行操作。关于 **loc** **iloc** 之间的区别以及如何使用它们的更多细节,请务必阅读下面的文章。

[## 熊猫中的 loc 与 iloc

towardsdatascience.com](/loc-vs-iloc-in-pandas-92fc125ed8eb)

使用深层副本

一种不同的方法要求我们在尝试执行改变的赋值之前获取原始数据帧的深层副本。

首先,让我们展示一下,即使将链式操作分成两个语句,问题仍然会出现;

>>> df_2 = df[df.A == 44]
>>> df_2['B'] = 100
__main__:1: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value insteadSee the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

现在,另一个解决方法是使用copy()方法从第一个切片操作创建一个深度副本。

>>> df_2 = df[df.A == 44].copy(deep=True)
>>> df_2['B'] = 100
>>>

瞧啊。不会发出警告。

>>> df_2
    A    B   C   D
0  44  100  64  67

理解 Python 对象的浅层副本和深层副本之间的潜在差异也很重要。如果你想了解更多,请务必阅读下面的文章。

无视警告

SettingWithCopyWarning本质上警告用户操作可能是在副本上执行的,而不是在原始对象上。然而,也有假阳性,这意味着警告可能不准确。在这种情况下,您可以禁用检查,警告将不再出现。如果你不熟悉熊猫,确保这是你最后的选择。

例如,下面的切片将生成一个副本。你可以使用._is_view属性检查生成的数据帧。

>>> df_copy = df.loc[df.A > 32, 'B']
>>> df_copy
0    5
1    4
Name: B, dtype: int64
>>>
>>> df_copy._is_view
False

现在如果我们试图去做

>>> df_2 = df[['A']]
>>> df_2['A'] += 2

你会看到警告

__main__:1: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value insteadSee the caveats in the documentation: [https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy](https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy)

即使结果是正确的:

>>> df_2
    A
0  26
1   3
2  99# the operation before had no effect on the original df
>>> df
    A   B   C   D
0  24  26  33  82
1   1  82  86  64
2  97  32   4  77

在这种情况下,您可以将pd.options.mode.chained_assignment设置为None:

>>> pd.options.mode.chained_assignment = None
>>> df_2[‘A’] += 2
>>>

注意:不要忘记将其设置回默认值warn。选项有None'warn''raise'

最后的想法

在今天的文章中,我们首先讨论了什么SettingWithCopyWarning以及何时被提出。我们已经在实践中看到了 pandas 数据帧或系列的副本和视图之间的差异,以及这如何在特定条件下触发SettingWithCopyWarning

尽管SettingWithCopyWarning仍然是一个警告,可能不会导致您的 Python 代码失败,但是您必须确保理解为什么会出现这个问题,并尝试使用我们前面讨论的技术来调整代码。在极少数情况下,警告可能不会真正影响您的结果。如果您确信它不会给您带来任何麻烦,那么您甚至可以通过设置我们在本文最后一节看到的配置来禁用检查。

后续步骤

在这篇文章中,我们探讨了很多概念,如索引,切片,复制等。下面的文章更深入地讨论了这些概念,所以一定要读一读,以确保你能理解这篇文章中解释的所有概念。

如何将职业转向数据科学(而不至于中途筋疲力尽)

原文:https://towardsdatascience.com/how-to-switch-careers-into-data-science-without-burning-out-along-the-way-89577ddd630?source=collection_archive---------6-----------------------

作者聚焦

“投资教育从来都不是一个坏主意”

在 Author Spotlight 系列中,TDS 编辑与我们社区的成员谈论他们在数据科学领域的职业道路、他们的写作以及他们的灵感来源。今天,我们很高兴与朱莉娅·尼库尔斯基进行对话。

Julia 目前正在攻读可持续发展管理硕士学位的最后一个学期,并在德国一家可持续发展智库担任研究助理。在完成企业管理和经济学学士学位后,她在金融行业担任分析师,重点是可持续金融。2019 年,她完成了 Udacity 的数据科学纳米学位。

朱莉娅,谢谢你和我们聊天!作为一名研究生和研究员,你最近最感兴趣的话题是什么?

我对可持续发展、金融和与数据科学相关的各种主题特别感兴趣。在可持续发展领域,循环经济可持续消费模式以及可持续发展、数字化转型和数据科学的交集是我特别关心的问题。在数据方面,我喜欢研究 NLP 问题、时间序列预测和数据可视化。我最近的一个项目实现了 Longformer 模型来分析传记数据。我目前正在学习的一个领域是机器学习中的单元测试。

退一步说,你是如何找到进入数据科学的路的?

作为一名金融分析师,我几乎没有任何编程技能。我在 R 中完成了一些大学项目,并在 Codecademy 上开设了一门 Python 课程,但从未抽出时间来开发实际的知识和技能。然而,我注意到至少对编程语言有一个大致的了解对于更有效地完成我的工作是多么重要。我的雇主还鼓励他们的员工获得技术技能,越来越多的数据科学家被聘用。

2017 年底,我决心再给编程一次机会。同时,我阅读了数据科学家的实际工作。当我开始学习 HarvardX 的 CS50 课程以获得对计算机科学的基本理解时,我对数据科学家的角色很感兴趣,并希望了解更多。这与我想休息一段时间,考虑换个职业的愿望不谋而合。我辞掉了工作,开始全职学习数据科学。

进入一个新领域最困难的部分是什么?

最具挑战性的时期实际上已经开始了。时间对我来说总是一个限制因素。学习一项新技能是很耗时的,而且用一份全职工作来做这项工作可能非常具有挑战性。我处于一个特殊的位置,可以辞掉工作,全职学习。然而,这不是一个容易的决定。当我告诉人们,我辞去了一份稳定的工作,自己学习技能,而其他人却因此获得了大学学位时,我遭到了相当多的怀疑和批评。我开始怀疑自己,同时感到有压力要快速学习这些技能,以证明我做出了正确的决定。

你是如何度过这段充满挑战的时期的?

许多事情帮助我克服了这些问题。首先,我经常提醒自己,投资教育从来都不是一个坏主意。即使我没有被聘为数据科学家,我也会获得新的知识和技能,这对我未来的任何工作都有好处。第二,我创建了一个学习结构,确保我知道自己的长期目标是什么,同时实现更小、更容易实现的目标。对我个人来说,结构非常重要,我需要看到我正在取得的进步,以便保持动力和有效地工作。

第三,我在 Medium 和 TDS 上读到了人们进入数据科学的学习旅程和职业变化。虽然关于在六个月内从零编码技能到被聘为数据科学家的故事并没有真正安抚我的神经或消除压力,但它帮助我了解了其他人在开始进入该领域时的经历和挣扎。

最后,我有了学习之外的生活。我知道什么适合我,什么不适合。长时间的过度工作或学习会妨碍我放松和做我喜欢的事情,这是适得其反的。虽然我感到有压力要快速进步,但我有意安排休息时间来保持平衡,确保我能坚持我的目标。

对于刚刚开始数据科学之旅的人,您有什么建议?

想想你为什么要学习数据科学。了解你想从这次学习经历中获得什么可以帮助你设定目标,保持动力,并取得你满意的结果。目标应该雄心勃勃,但可以实现。如果你有一个无法实现的雄心勃勃的目标,这会让人失去动力。

调整你的学习以适应你的需要。正如我提到的,我需要有结构,我学习短视频教程和经常在小项目中应用获得的知识效果最好。知道如何学习最有效,会让你更容易获得新技能。最后,我建议要有耐心。虽然有些人能够在六个月内成为一名数据科学家,但给自己施加太大的压力会导致沮丧,甚至放弃你的目标。

是什么激励你为更广泛的读者写作?

在 Udacity 攻读纳米学位期间,我开始接触媒体和 TDS 写作,在那里我必须写两篇关于我的项目的博文。除此之外,我继续写作,因为我喜欢解释概念和创建教程的过程,以帮助他人和扩展我自己的知识。此外,例如,写关于机器学习模型的技术文章可以证明我知道我在说什么。这对我来说尤其重要,因为我正在攻读大学学位之外的数据科学。能够指着某样东西说,“我可以应用它,并理解它是如何工作的,”即使我没有在大学学位中学习它,这也是非常有价值的。

对于那些可能成为 的人,你有什么见解可以分享给更多的读者吗?

如果你想让你的故事引起观众的共鸣,你需要被告知并能够传达潜在的困难概念。我注意到我写的每一篇文章都拓展了我的知识面。特别是当我写机器学习时,我总是阅读学术期刊文章,以了解使用模型背后的实现和推理。我真的很享受这个获取和交流知识的过程。我也很高兴我与那些阅读我的故事、觉得它们有用、或者有意见并联系我的人建立了联系。

最后一个问题:您希望未来几年数据科学领域发生什么变化?

我希望数据科学界有更多的人考虑他们的技能对人类和地球的积极影响。公共部门、非政府组织和社区可以从熟练的数据科学家那里受益。我也希望数据伦理和数据隐私的话题能够成为数据科学领域和教育的一个更完整的部分。我个人希望更多地了解这些领域,以成为一名更负责任的数据科学家。

最后,我希望看到数据科学社区继续发展,因为我相信这个领域受益于多元化的视角和背景。

如果你想了解更多朱莉娅的工作和广泛的兴趣和项目,请访问她的 MediumGitHub 个人资料。以下是我们档案中她的一些出版集锦。

  • 数据科学促进可持续发展 ( TDS ,2021 年 1 月)
    这篇文章向读者展示了数据科学和可持续发展工作如何相互交叉和相互影响,并包括几个令人信服的真实案例。
  • </5-steps-to-develop-unique-data-science-project-ideas-6c2b3a0014b>*【2020 年 9 月TDS
    如果你正在经历灵感滑坡,Julia 关于启动新项目的实用建议可能会有所帮助。它们从基于你的日常事务产生新的话题,到寻找没有被其他人广泛使用的数据集。*****
  • 用 AdaBoost、random forests 和 XGBoost 进行时间序列预测(TDS,2020 年 2 月)
    当你的模型没有产生整齐、完美的结果时,你怎么办?在本帖中,Julia 分享了她在一个极具挑战性的项目中所学到的有用的经验。
    ****
  • 如何建立数据科学作品集网站**(TDS,2020 年 5 月)
    在竞争激烈的市场中导航,求职者和职业转换者需要突出他们所拥有的所有相关技能和经验。在这里,Julia 向我们展示了构建有效的数据科学组合网站的过程,并涵盖了设置
    内容理念。
    ******

请继续关注我们的下一位特色作者,即将推出!(如果您对希望在此空间看到的人有任何建议,请给我们留言。)

如何在 Python 中同步时间序列数据集

原文:https://towardsdatascience.com/how-to-synchronize-time-series-datasets-in-python-f2ae51bee212?source=collection_archive---------6-----------------------

使用动态时间弯曲同步时序数据

图片作者。

介绍

在与数据相关的职业生涯中,人们可能遇到的最痛苦的事情之一就是不得不处理不同步的时间序列数据集。差异可能是由一系列原因造成的——夏令时调整、不准确的 SCADA 信号和损坏的数据等等。在同一个数据集中的不同点上发现几个差异甚至是很常见的,这需要您单独识别和纠正每一个差异。当你这样做的时候,你可能会无意中抵消另一个同步部分。幸运的是,在新颖的“动态时间扭曲”技术的帮助下,我们能够对我们所有的非同步数据集应用一种尺寸适合所有人的解决方案。

动态时间扭曲

简称 DTW 是一种计算两个数据序列之间最佳匹配的技术。换句话说,您正在寻找在任何给定时间从一个数据集到另一个数据集的最短路径。这种方法的美妙之处在于,它允许您根据需要对数据集应用尽可能多的校正,以确保每个点尽可能地同步。您甚至可以将它应用于不同长度的数据集。DTW 的应用是无止境的,你可以将它用于时态和非时态数据,如金融指标、股票市场指数、计算音频等等。唯一的警告是要确保你的数据没有空值或缺失值,因为这可能会影响 DTW 的工作。

DTW 的欧氏距离度量实现。图片作者。

用于查找对应点之间最短路径的距离度量可以是 Scipy 的距离度量模块提供的任何一个。虽然在大多数情况下欧几里得距离可以解决问题,但是您可能希望用其他距离来做好测量。

履行

为了实现我们自己的 DTW 版本,我们将使用 Python 中的 fastdtw 库。这个包的新颖之处在于它简化了 warping 函数的复杂度,从而将复杂度从 O(n)降低到 O(n ),这在运行时带来了明显的不同。

请启动 Anaconda 或您选择的任何 Python IDE 并安装 fastdtw,如下所示:

pip install fastdtw

随后,导入所有必需的包:

import numpy as np
import pandas as pd
import streamlit as st
import plotly.express as px
from sklearn.metrics import r2_score

在运行同步之前,导入数据集并填写任何空值:

df = pd.read_csv('dataset.csv')df['Power'] = pd.to_numeric(df['Power'],errors='coerce')
df['Voltage'] = pd.to_numeric(df['Voltage'],errors='coerce')x = np.array(df['Power'].fillna(0))
y = np.array(df['Voltage'].fillna(0))

然后继续执行同步:

distance, path = fastdtw(x, y, dist=euclidean)

同步路径的结果将类似于以下内容:

path = [(0, 0), (0, 1), (0, 2), (1, 3), (2, 4),...]

参考数据集中的每个点将与目标数据集中的一个或多个点匹配,即参考数据的行 0 可以与目标数据的点 0、1 或 2 匹配。

现在您已经有了扭曲的路径,您可以继续创建具有同步结果的数据框,如下所示:

result = []for i in range(0,len(path)):
    result.append([df['DateTime'].iloc[path[i][0]],
    df['Power'].iloc[path[i][0]],
    df['Voltage'].iloc[path[i][1]]])df_sync = pd.DataFrame(data=result,columns=['DateTime','Power','Voltage']).dropna()
df_sync = df_sync.drop_duplicates(subset=['DateTime'])
df_sync = df_sync.sort_values(by='DateTime')
df_sync = df_sync.reset_index(drop=True)df_sync.to_csv('C:/Users/.../synchronized_dataset.csv',index=False)

最后,您可以使用 Sklearn 的 r2_score 模块计算相关性分数,以比较同步前后的相关性或同步级别:

correlation = r2_score(df['Power'],df['Voltage'])

数据可视化

为了绘制和可视化您的同步数据,我们将使用 Plotly 和 Streamlit——这是我最喜欢的两个库,用于可视化数据并将其渲染为应用程序。

您可以使用下面的函数来创建时间序列图。请确保您的时间戳采用 dd-mm-yyyy hh:mm 的正确格式,或者修改函数以适应您的数据。

要可视化和呈现您的图表,请在 Anaconda 提示符下键入以下命令来运行您的脚本:

cd C:/Users/.../local_directory
streamlit run synchronization.py

在这里,您可以看到同步前后的数据:

作者视觉。

结论

对于时间序列数据的快速和方便的同步,动态时间弯曲可能是唯一最有效的解决方案。虽然它不是完美无缺的,而且确实有一些缺点,比如边界条件匹配不佳,但它是我见过的最全面的解决方案。您也决不会局限于线性数据,实际上您可以同步不同维度的非线性数据。

如果您想了解更多关于数据可视化和 Python 的知识,请随时查看以下(附属链接)课程:

使用 Streamlit 开发 Web 应用程序:

https://www.amazon.com/Web-Application-Development-Streamlit-Applications/dp/1484281101?&linkCode=ll1&tag=mkhorasani09-20&linkId=a0cb2bc17df598006fd9029c58792a6b&language=en_US&ref_=as_li_ss_tl

使用 Python 实现数据可视化:

https://www.coursera.org/learn/python-for-data-visualization?irclickid=xgMQ4KWb%3AxyIWO7Uo7Vva0OcUkGQgW2aEwvr1c0&irgwc=1&utm_medium=partners&utm_source=impact&utm_campaign=3308031&utm_content=b2c

面向所有人的 Python 专业化:

https://www.coursera.org/specializations/python?irclickid=xgMQ4KWb%3AxyIWO7Uo7Vva0OcUkGQgW16Ewvr1c0&irgwc=1&utm_medium=partners&utm_source=impact&utm_campaign=3308031&utm_content=b2c

GitHub 资源库:

https://github.com/mkhorasani/dynamic_time_warping_synchronzation

新到中?您可以在此订阅和解锁无限文章

如何在数据科学工作面试中谈论你的项目

原文:https://towardsdatascience.com/how-to-talk-about-your-projects-in-a-data-science-job-interview-a14ebdda5a1e?source=collection_archive---------9-----------------------

办公时间

以及如何用 4 步法来准备

尼克·莫瑞森Unsplash 上拍摄的照片

准备工作面试是一个乏味的过程。数据科学家职位可能比其他技术职位更难,因为面试可能涵盖广泛的内容,包括但不限于统计、编码、产品问题、行为问题等。但是如果你问我在面试中你最常被问到什么,我的回答是:“谈谈你做过的一个 DS 项目”。

嗯,我认为从事数据科学项目是一回事,知道如何谈论它们是另一回事。在这个博客中,我希望与你分享一些如何在面试中有效地谈论你的 DS 项目的技巧,以及如何准备谈话。

1.是交流,不是聊天!

交流和聊天的区别是什么?在交流中,你是有目的地向你的听众传达你想让他们知道的某些信息。而在聊天中,它更像是没有明确目的的无组织的谈话,你可以让你的话题在这里和那里跳跃。因此,你确实需要为交流做好充分准备,但可能不需要为聊天做好准备。

那么,通过谈论你的 DS 项目,你想传达什么信息呢?

目标简单明了:你想向面试官展示你有能力做好这份工作。为了实现这一目标,你需要展示以下技能:

  1. 技术技能 : Python、R、SQL、Spark、AWS 等。
  2. 数据科学知识:机器学习、统计学、ETL、数据可视化等。
  3. 解决问题的技巧:你是如何处理在项目开始时没有预料到的现实世界数据的困难的。
  4. 沟通技巧:你如何与他人合作,包括团队成员、利益相关者、项目经理等。

在 5-10 分钟内谈论你的项目,包括所有的信息,听起来很有挑战性。但是不要担心,我会在下面举例说明如何在你的谈话中包含所有的内容。

2.了解你的观众!

是的,当你和不同角色的面试官谈论你的项目时,确实会有所不同。通常,你会面试四类人:人力资源、团队经理、数据科学家、商业伙伴/利益相关者。总面试时间窗口根据你的面试官是谁而有所不同。例如,人力资源电话通常需要 15-20 分钟,而与数据科学家的面谈可能需要 30-60 分钟。因此,你需要注意你谈论你的项目所花的时间,这取决于你在和谁交谈。

下表展示了如何与不同的面试官谈论你的项目的一般准则。

作者图片

从表中可以看出,对于“说说你的 DS 项目”这个问题,你需要准备不同版本的答案。你需要很好地控制谈话的流程,强调不同的领域,不要给出太多或太少的技术细节。很有挑战性!

因此,接下来我将介绍一种策略/方法供你在面试中遵循,第 3.1 节将讨论我使用的 4 步法,我将在第 3.2 节向你展示一个例子。我们开始吧!

3.如何谈论你的 DS 项目?

3.1 四步法

你可能知道或听说过在面试中回答行为问题的“明星”方法。我发现谈论你的项目,并对方法进行一些调整,会很有帮助。根据我的经验,我总结了当你谈论你的项目时要遵循的四个步骤:

作者图片

第一步。项目背景和目标
这是你开始谈论你的项目的方式:通过提供一些背景信息,指出项目的目标或目的。这就好比“星”法中的“情境”和“任务”。第一步的目标是给你的面试官关于你的项目的基本知识,但是你不需要在这一部分花太多时间。取决于你在和谁交谈,背景信息可以是一句话,也可以是几个细节。你只需要一句话来描述你的主要目标。

  • 谈论什么作为“背景”:你在这个项目中的角色,你是否与任何团队成员和/或业务伙伴合作,必要的业务需求解释和/或为什么这个项目是有价值的。你也可以提到一些你使用的编码语言或工具。
  • 谈什么“目标”:对于大项目,你可能有多个目标,但我建议你陈述的主要目标不要超过两个。受限于面试时间,所以你要把这部分做的简洁有力,让面试官更容易跟随。你可以用一句话来陈述你的目标,格式如下:“我项目的目标是开发一个 ML 模型/DS 产品/创建一个工具/评估 XX 的影响”。

第二步。挑战和解决方案
我认为这是你故事中最重要的部分,也是面试官会问你最多问题的部分,所以要做好充分的准备和练习!你需要像在“明星”方法中那样谈论“行动”,但你需要在这里讲一个好故事。这就是为什么我发现谈论挑战和解决方案比仅仅列出你做过的工作更好。当你提到“挑战”时,它真的会吸引面试官的注意,因为他们想知道 1)你如何定义挑战,这代表了你的技能和能力,以及 2)你解决问题的技能,比如你如何处理工作中的困难。

  • “挑战”谈什么:我推荐谈一个技术挑战和一个业务驱动的挑战。如果这个项目是你的副业项目或没有商业场景的课程项目,那么你可以只关注技术挑战。

技术挑战的例子包括脏数据、数据不足、预测和响应变量之间的弱相关性、不平衡数据集、建模困难、部署困难等。

  • 谈论“解决方案”的内容:在谈论完你遇到的挑战后,你可以用一句开场白开始谈论解决方案,比如“为了应对这些挑战,我做了以下事情”。然后你可以举例说明你是如何应对你之前提到的挑战的。记住使用“第一,第二,然后,最后”这样的词,让你的观点听起来有条理。

第三步。成就

成绩和“星”法中的“结果”有点不一样。这不仅仅是客观地列出结果,这是你“炫耀”你所取得的成就的部分,因为你经常会被问到“你为什么为这个项目感到自豪”这样的问题。同样,您可以从技术和面向业务的角度来处理这一部分。列出两三项成就就足够了,因为你不想花更多的时间谈论成就而不是工作(在第二步)。确保你的陈述能给面试官留下深刻印象。

  • 谈“成就”谈什么:谈影响,如果有数字支持你的观点会更好。从技术角度来看,您可以将您的模型与以前的模型/方法在提高的准确性、运行时间等方面进行比较。如果模型已经投入生产,你可以提到模型用户的数量,用户的积极反馈,等等。如果这是你 Github 上的一个个人项目,你可以谈论你得到的星星的数量。从商业角度来看,销售提升、收入、防止损失都是值得谈论的好数字。

第四步。吸取的教训
如果你正在和人力资源部谈话或者面试时间很紧,可以跳过这一步。但是我建议你为这一部分做好准备,向面试官展示你能够从自己的经历中反思和学习。同样,这里有一两个强有力的声明就足够了。

  • 谈论“经验教训”:谈论你获得的技能,但需要与第二步中的故事相关。比如开发 ML 模型、制作高级图、创建 ETL 过程等技能。这些技能不一定都是技术性的,你可以加入一些软技能,比如与客户谈判,与非技术性的商务人士沟通等。

3.2 示例

乔安娜·科辛斯卡在 Unsplash 上的照片

在上面提到的四步法的所有理论之后,我很确定你已经对这个过程有了一个大致的概念。现在希望用下面一个例子来说明*。请注意,这个例子只涵盖了重要的点,更多的细节需要在真正的面试中添加。

(第一步项目背景和目标)我想谈谈我的识别欺诈交易的项目。首先,我希望向你们提供一些背景资料。我是这个项目的首席数据科学家,与销售部门的业务合作伙伴一起工作。该项目的目标是使用历史数据开发一个 ML 模型来预测交易是否是欺诈。

(第 2 步挑战和解决方案)我在这个项目中遇到了两个挑战。第一个挑战是历史数据非常不平衡,因为我们在所有交易中只有 1%的欺诈。另一个挑战是我的商业伙伴没有技术背景,所以我需要学习与他们沟通的最佳方式来传达我的发现。为了应对这些挑战,我尝试了一些不同的方法。对于不平衡的数据集,我使用 SMOTE 采样并在 ML 模型中分配权重来处理不平衡。我还参加了 Coursera 课程,学习如何在商业环境中更有效地沟通。

(第三步成就)我真的为这个项目感到骄傲,因为自从投入生产以来,ML 已经节省了 XX 美元。我还从我的商业伙伴那里得到了积极的反馈,该模型易于使用,总体准确率为 XX%。

(步骤 4 经验教训)通过参与这个项目,我练习了开发不平衡数据分类模型的技能,并且积累了向非技术人员展示结果和分析的经验。

4.面试怎么准备?

技巧 1:不要等到你准备好找工作的时候。早点准备!

这是我希望与你分享的最重要的提示。原因很简单:我们会忘记事情,所以最好在事情还历历在目的时候就写下来。我从自己的经历中了解到这一点,在一次面试中,我被问到关于一个实验设计的细节,这个实验来自我 5 年前做的一个项目。虽然我可以告诉面试官时间太长了,所以我记不起细节,但我为什么会让这种事情发生呢?因此,为了避免将来再次发生这种情况,当项目完成时,我会在 OneNote 中记录必要的细节。当然,你可以使用 Word 或 Google Docs 或任何你喜欢的东西,只要你记录下对你未来面试有用的东西。请查看下面的图片,作为记录您的工作的清单,其中包括第 3 节中提到的要点:

作者图片

请注意,不要记录贵公司禁止披露的敏感信息,也不要在采访中谈论这些内容!

提示 2:自己练习和计时。

  • 首先,你可以通过查看你为项目记录的笔记来开始练习说话。我不建议把你想说的每一句话都写下来,但是你可以在笔记中添加关键句子和关键词。这可以确保你有一个有条理的说话方式。
  • 针对不同类型的面试官进行练习和准备,记住本博客第二部分提到的差异,这样你就知道应该强调哪个部分,跳过哪个部分,这取决于面试官。
  • 一旦你为不同的听众确定了要谈论的内容,记录下你练习的时间,并确保你的谈话长度在一个合理的时间范围内(参考本博客的第二部分)
  • 让你的朋友或家人充当你的面试官,询问他们对你的语速、内容、结构和语气的反馈。

提示 3:熟悉你提到的每一个技术细节。

数据科学家是一个技术岗位,你首先要用技术技能打动面试官。因此,你需要确保你对你所谈论的一切都非常清楚,尤其是技术细节。准备好回答关于 ML 模型理论的问题,或者用于评估模型性能的模型度量的定义。通常,面试官会开始问一些关于你项目的理论问题。

4.结论

找到一份理想的工作总是不容易。我相信每一个大的进步都来自于你迈出的小步。我希望这个博客能激发你在面试中更好地交流,并展示你已经完成的伟大工作。

💖喜欢这个故事吗?请随意订阅 DS 和 ML 粉丝的邮件列表成为会员!🤩

这篇博客最初发表在我的个人网站上。

免责声明:我在 3.2 节中创建了这个例子,只是为了在这篇博客中进行说明。和我工作中的任何项目都没有关系,这里陈述的所有数字和情况都是作为例子编造出来的。

如何与您的数据库对话

原文:https://towardsdatascience.com/how-to-talk-to-your-database-1dc5ffafba37?source=collection_archive---------44-----------------------

传统的方式

照片由马太·亨利发自突发

介绍

毫无疑问,最近自然语言处理(NLP)中使用转换器——神经网络的进步确实令人瞩目。这些模型可以很好地执行不同类型的任务,如翻译、文本摘要和自动完成。作为变形金刚的一个不同变体,视觉变形金刚是图像分类和物体检测中许多计算机视觉任务的当前技术水平。

照片由 Alina GrubnyakUnsplash 上拍摄

为了训练这些模型,我们需要大量的数据、专业知识和计算能力。不幸的是,对于中小型企业和个人来说,这可能相当昂贵。

本文的目的是从人工智能的炒作中退一步,并提供一种替代方法来完成这个 NLP 任务。在接下来的章节中,我们将看到如何使用自然语言——简单的英语——与数据库“对话”,而无需训练任何机器学习算法。

程序

第一步是结合若干基于规则的自然语言处理技术对用户输入进行预处理,例如标记化、词条化和词性标注。

Tokenizer API 方法代码(图片由作者提供)

例如,提供输入 “显示 2017 年 1 月拉纳卡的 agros 销售额” 将返回如下所示的响应。也可以玩玩 API ,如果发现什么 bug 或者有什么建议就告诉我。

Tokenizer API 示例响应(图片由作者提供)

接下来,我们创建一个平面表来表示我们的数据库模式。原因是查询单个表比连接多个表更简单。

平面表模式(作者图片)

在上面的例子中,仅仅通过列名,我们就可以识别出至少 7 个不同的表合并成 1 个。

发生在数据库级别的另一部分是映射视图。这个视图帮助我们找出每个标记/单词的含义,还可以在 SQL 中得到它的等价列名。比如给定“Agros”这个词,我们想得出的结论其实是一个品牌。

表格映射视图的一部分(作者图片)

上图显示了该视图的一部分。尽管一开始看起来有些混乱和不直观,但是一旦我们理解了它在生成 SQL 中的作用,它就变得有意义了。对于尽可能多的令牌,我们查询视图并根据令牌(或二元模型)的值进行过滤。

映射视图的使用示例(图片由作者提供)

下图显示了高级别的标记化和映射过程。我们首先提供用户查询,然后生成二元模型和令牌。为了提高效率,我们进行二元模型查找,并从我们的令牌中删除这些单词。

标记化和 SQL 映射过程(图片由作者提供)

一旦我们完成了映射,我们就可以通过编程方式将所有内容组合在一起来构造 SQL。我们用一个“AND”语句连接每个查找,最后我们执行查询来获得结果。

生成的 SQL(图片由作者提供)

结论

即使这个系统不像基于机器学习的系统那样智能和不能一般化,它也提供了为这个特定任务定制的更便宜和更快的解决方案。

下次见,感谢阅读!

这篇文章解释了我本科论文项目的一部分,你可以在这个 GitHub repo 中找到一个演示和源代码。

资源

  1. 变形金刚如何工作
  2. 一幅图像值 16x16 个字:大规模图像识别的变形金刚
  3. 自然语言处理:标记化、词干化、词条化和词性标注

如何驯服你的强盗

原文:https://towardsdatascience.com/how-to-tame-your-bandit-4c6b2723d0db?source=collection_archive---------13-----------------------

揭开纯粹探索的神秘面纱(第一部分)

一个独臂强盗。(照片由马库斯·斯皮斯克Unsplash 上拍摄)

TLDR

多臂强盗很棒,超越了简单的 A/B 测试,走上了之路。对于有强盗的假设检验,有效的算法和非常紧的样本大小界限是可用的。让我们检查一下!😃

在前一集里…

P 我的关于的系列文章第 0 篇解释了为什么使用顺序统计可以显著地提高 A/B 测试的效率,以达到期望的性能水平(第 0 部分点击此处)。在其中,我还解释了一个叫做“多臂 bandit”的统计结构如何概括顺序 A/B 测试,并提供了一个使用 Bandit 方法的优势列表。

在过去的二十年里,班迪特背景下的序贯假设检验受到了研究者的广泛关注。计算机科学家和统计学家一样,已经开发了一个丰富的算法和证明技术的工具包来处理建立在异常严格的数学基础上的各种各样的此类问题。

在本系列的这一部分和随后的部分中,我希望呈现关于这个主题的大量文献中的一小部分,以帮助读者更好地欣赏顺序统计分析的强大功能。让我们首先了解我们正在处理的问题,特别是它不是什么。

纯探索≠后悔最小化!😮

多臂强盗(MAB)的设定包括 K 个动作,一些特别虐待狂的统计学家决定称之为'武器',以唤起拉斯维加斯吃角子老丨虎丨机的可悲形象,又名独臂强盗,偷走你所有的钱。在继续下一步之前,我将快速总结一下 MAB 模型(新手可以参考这个网站上任何数量的关于后悔最小化的基础知识的文章)。

每个臂 K 代表一个分布 P(k),1≤ k≤ K,拉臂代表从分布 P(k)中取样。在时间 t = 1,2,3,mab 算法拉臂 Aₜ.在时间 s 拉动臂 k 产生从分布 P(k)中抽取的样本 X(s,k)。这个样本被称为“奖励”。

分布 Pₖ的均值用θₖ表示,均值最大的臂称为最佳臂。不用说,除了它们所属的概率分布的之外,我们并不先验地知道任何报酬分布。贯穿本文,我们将假设所有的奖励分布都在 亚高斯中。称随机变量 z 是σ-次高斯的,如果对于每个λ ∈ ℝ

亚高斯的定义(作者图片)

上面的参数σ本质上表现为 z 的方差的代理。在本文的其余部分,我们将假设我们的问题有一个唯一的最佳臂,并且该臂是臂 1 。此外,让δₖ= θ₁-θₖ表示臂 1 和 k 之间的平均回报差距。为了便于表示,让我们设置δ₁= δ₂.

后悔最小化:在上面的框架中,给定固定的时间范围 T,MAB 算法的后悔本质上测量了由于它没有拉最佳臂的所有时间而导致的回报损失。

后悔最小化不是这个系列的重点。我感兴趣的是激起普通读者对 A/B 测试的激进概括的兴趣,这种测试被不同地称为“纯探索”和“最佳手臂识别

纯探索

给定置信参数δ∈(0,1),找到概率至少为 1-δ的最佳臂,使用尽可能少的臂拉动。因此,我们的算法需要使用尽可能少的样本来找到 Arm 1。

杰瑞能通过你的测试吗?(照片由 Ricky KharawalaUnsplash 上拍摄)

例子:一个医学研究者有一种药物的 K 种构型,她希望找出其中最有效的一种。

测试这一点的自然方法是通过注射不同配置的实验室小鼠,并观察每种配置的成功率。这样的实验并不关心老鼠本身如何受到药物的影响。事实上,所采用的协议必须相当积极地快速找出次优配置(或武器)(在她耗尽鼠标并不得不四处寻求更多资金之前)。

听起来可能很可怕,但这个例子有助于说明这两个问题之间的区别。后悔最小化算法,根据它们处理的问题的本质,必须“小心行事”,尽可能少地采样次优臂。纯粹的探索算法没有这种强迫性,只关心尽可能快地聚焦于最佳行动,而不关心在此期间他们会产生什么样的遗憾。

💡考虑到我们只有来自分布的样本,臂 k 的平均θₖ的一个很好的代理是从采样臂 k 到时间 t 所获得的平均回报。因此,我们应该研究如何控制θₖ和这个平均值之间的距离。幸运的是,两位著名的数学家发明了一种技术来做到这一点。

切尔诺夫和赫夫丁前来救援

在文章的剩余部分,给定随机变量 X₁,X₂,…由术语' 样本意味着 ' 我们将指随机变量

“样本均值”的定义(图片由作者提供)

当 X₁,X₂,…也是独立同分布(IID)且均值为μ时,我们知道𝔼Xᵐ(t)=𝔼X₁=μ.为了突出μ在某种程度上代表了 IID 序列的基本事实,我们将称其为''(与样本均值相对)。

问题 1

Xᵐ(t 离μ有多远)?假设我们的 IID 序列 X₁,X₂,…由σ-亚高斯随机变量组成,标准切尔诺夫-赫夫丁分析告诉我们

单面装订(图片由作者提供)

Xᵐ(t)-μ的情况也是如此

(Image by author)

💡 This means that O(1/ϵ² log(1/δ)) samples are needed to bring the sample mean to within ϵ of the true mean with high probability. This brings us to the next question.

The sample mean is close to the true mean for large enough t. (Image by author)

O(1/ϵ² log(1/δ)) samples are needed to bring the sample mean to within ϵ of the true mean with high probability.

问题 2(回到单克隆抗体)

给定一个双臂土匪,假设已知δ=θ₁-θ₂,需要多少样本才能高概率找到更好的手臂?(回想一下,我们假设臂 1 是最佳臂。)

💡回答这个问题的一个方法是对两个臂采样足够的次数,以确保它们的样本均值 Xᵐ₁(t 和 Xᵐ₂(t 分别足够接近真实均值θ₁和θ₂,并且简单地选择具有较大样本均值的臂。

事实证明这非常有效!

臂 1 的样本均值比臂 2 的样本均值大得多(图片由作者提供)

根据上面的分析,假设我们现在处理的是 4 个区间,而不是 2 个,我们需要用δ/4 代替δ/2。还有,如图所示,在这种情况下,ϵ=δ/2。由此,我们看到

作者图片

样本确保在概率大于 1 - δ的情况下,臂 1 的样本均值 xᵐ₁(t)>θ₁-δ/2≥θ₂+δ/2 > xᵐ₂(t),臂 2 的样本均值。所以,选择样本均值较大的臂给出正确答案的概率较大。

一个名为动作消除或‘AE’的非常简单的算法正好利用了这一原理,以高概率在多臂强盗中找到最佳臂。然而,AE 还必须应对增加的复杂性

  • 事先不知道δᵢ=θ₁-θᵢ的差距,以及
  • 不得不(潜在地)处理两个以上的臂。

让我们看看算法如何设法解决这个问题。

动作消除算法

AE,顾名思义,是一种“消除”类型的算法,它分阶段进行,丢弃或…消除(啊哈!)在阶段结束时看起来不太理想的武器。

该算法巧妙地回避了需要知道的差距

  • 选择每个阶段结束时样本均值最大的臂作为当前(或经验)最佳臂,
  • 丢弃其样本均值在经验最佳值一定距离之外的所有臂,该距离在阶段开始时选择,以及
  • 通过选择一个新的、更小的距离来开始下一阶段,以使武器在即将到来的阶段中存活。这意味着,随着阶段的进展,样本均值将不得不越来越接近经验最佳值,对应的臂才能存活。

下面的流程图说明了算法的细节。AE 从所有臂开始,并在一个阶段结束时恰好剩下一个臂时结束。请注意,由于ϵₗ随着阶段的进展呈指数下降,样本均值需要非常接近经验最佳值才能生存。换句话说,该算法非常积极地丢弃 arms。

给定置信度δ∈(0,1)的动作消除算法。(图片由作者提供)

分析 AE 在停止前消耗的样本数包括显示(很有可能)

  • 臂 1 永远不会被消除
  • 武器的样本手段永远不会比ϵₗ在每个阶段都远离它们真正的对手 l
  • 臂 k 最多存在 o(log(8/δₖ)阶段。

这些观察意味着动作消除返回概率至少为 1-δ的最佳臂,消耗了最多以下数量的样本

活动消除消耗的样本数。(图片由作者提供)

好消息和坏消息

我们将在后面看到,AE 样本量中的许多项实际上从根本上是不可避免的。然而,这种算法存在许多问题。

  • 首先,不能保证动作消除会停止。样本均值估计可能会波动,Arm 1 可能会在早期被踢出局,一系列问题可能会破坏算法。
  • 即使在 AE 停止的轨迹上,在概率 1-δ的集合之外,其性能也可能是任意差的。
  • 在开始下一阶段之前,该算法实际上丢弃了在给定阶段收集的所有样本。

基于这些原因,我决定称动作消除法为‘无齿’算法(明白吗?😉无牙…被驯服的龙…)。无论如何,回到样本大小,我们现在会看到,尽管它没有什么作用,但 AE 样本复杂性的表达式是一个有价值的信息宝库。

无齿算法的教训

让我们更仔细地看看样本量表达式。可以说,我只强调了“顺序”项,而隐藏了不相关的常量。

红色圆圈中的术语不能删除,但绿色圆圈中的术语可以删除。(图片由作者提供)

用红色圈出的术语是统计分析和随机过程理论中非常基本的问题的结果。在本系列接下来的部分中,我们将看到它们是如何出现的。简而言之,

  • 事实上,第 1 项(σₖ1/δₖ)是任何好的纯探索算法所消耗的样本数的一个著名下限的最重要部分。
  • 第 2 项(log(K))是弱并集的结果。我们将看到这个术语最终是如何被删除的。
  • 第 3 项(log(1/δ))是统计分析中的一个基本极限。事实上,这篇文章暗示了为什么这个术语不可避免。你能找到它吗?提示:如果我给你δₖ的差距值,你能避免吗?
  • 第 4 项(log(log(1/Delta)))来自一个有趣的现象,称为重对数的定律,它控制着独立随机变量之和的增长率。

结束语

  • 在纯探索的背景下,AE 是最早提出的算法之一(并经过严格分析)。
  • AE 不是真的“无牙!”我只是用这个形容词来强调这样一个事实,即更先进的技术显示了接近最优的样本复杂性。事实上,AE 已经被许多研究者成功地用于解决 MABs 和强化学习中的几个问题(包括你的)😅),通常作为更复杂算法中的构建块。
  • 多年来,AE 的许多问题都已经解决了。在接下来的部分中,我将描述一些成功解决 AE 问题的尝试。

因此,在纯探索传奇的这一部分,我们正式定义了这个问题,并看到了如何构造一个算法来解决它。算法的性能分析给了我们一些提示,告诉我们在这种情况下什么可以做,什么不可以做。

在本系列的剩余部分,我将解释是什么使得这些术语不可避免,以及 log(K)术语是如何被消除的。

注:参考资料将在第 2 部分末尾提供。

如何教计算机识别图像中的狗和蛋糕

原文:https://towardsdatascience.com/how-to-teach-computer-to-recognize-dogs-and-cakes-from-images-d35b8cc845dd?source=collection_archive---------64-----------------------

从数据中提取隐藏的知识

做松饼还是不做松饼——这是个问题!图片作者。

人工智能是一个非常有趣的话题,引发了许多情感。这是因为新技术的发展涉及许多机会和威胁。

一些人工智能技术已经存在了很长时间,但计算能力和数值优化例程的进步,海量数据的可用性,导致了该领域的巨大突破。

人工智能被广泛用于在购物或简单地在网上搜索信息时提供个性化推荐。更先进的发明包括自动驾驶汽车——以一种简化的方式,根据从安装在车上的各种传感器收集的数据,对车辆的下一步行动做出决定。

在自动化车辆中使用人工智能。图片由来自 macaubusiness.com的 Nelson Moura 拍摄。

谈到威胁,你可能知道一些科幻电影,其中反叛机器获得了自我意识,并试图接管世界。正是因为这样的形象,围绕人工智能产生了许多神话和恐惧。让我们试着回答一个基本问题——人工智能是发展的威胁还是机遇?

有可能理解 AI 吗?

首先,我们应该说明这个神秘的人工智能(AI)实际上是什么。

正如形容词 artificial 通常不会给我们带来太多的问题,因为我们会将它与人类创造的一些非自然物体联系起来——一台机器,一个纯粹的工程生物——智能这个词会带来很多问题。为什么?因为它是一个抽象的概念,我们可以理解为解决问题或者处理各种情况的能力。为了更好地理解什么是智力,我将在这里提到它的测量方法。

最经典的智力测试(智商测试)是瑞文进步矩阵测试。我相信你们很多人都接触过它们,因为它们是用各种颜色的几何形状的矩阵进行的测试,缺少了最后一个元素。接受检查的人必须抓住(矩阵的)模式元素之间的关系,并从下面给出的例子中指出缺少的元素。这就是测试一般智力——识别模式的能力——的方法。人工智能是任何形式的非自然智能,由机器实现,或者更近一点来说,由人造程序实现——算法。同样重要的是,任务由设备本身执行,而不需要来自用户端的持续监督。

瑞文渐进矩阵测试中的智商测试项目。图片由维基共享资源提供。

几门学科的结合

我们可以将机器学习视为从数据中提取隐藏知识的技术。根据可用的数据类型和手头的研究问题,科学家将选择使用特定的学习模型来训练算法:

  • 监督学习(与老师):当所有呈现给机器的数据都被注释,即被标记,以与我们期望机器给出的答案完全相同的方式出现;
  • 无监督学习(无老师):发生在我们拥有大量无任何标签的数据,主机的任务是确定数据的结构;
  • 强化学习(与评论家一起):通过试错法学习,机器寻求制定任务的解决方案,它的行动会得到奖励(当它做正确的事情时)或惩罚(当它做错时)——机器不会得到任何其他提示或建议。

人工智能领域。图片作者。

除了人工智能,还有几个更密切相关的领域值得了解,至少知道名字。在这里,我们可以详细列出机器学习、数据科学和深度学习等。可以说,机器学习是人工智能的一个子领域,而人工智能又是计算机科学的一个子领域。

简单来说,机器学习使人工智能领域的自适应解决方案得以使用。

我们可以将机器学习视为从数据中提取隐藏知识的技术。根据可用的数据类型和手头的研究问题,科学家将选择使用特定的学习模型来训练算法:

  • 首先,这种机器的眼睛是如何构造的,
  • 其次,数据,比如图像,是如何被机器处理的,以及它们的算法。

计算机视觉过程

现在,我们继续介绍介绍的要点——解释这种基于神经网络的计算机视觉实际上是如何工作的。这里我必须说明两件事:

我们来思考一下机器学习的过程。第一件事是构造算法本身,即定义一定的规则或模型,第二件事是定义参数,参数在过程中迭代改变其值。

在计算机这个现代计算机器中,我们想要重现某个过程,例如检测图像中的某些东西。当我们谈论一台计算机器时,我们实际上要解一个数学方程,这并不奇怪。对于简化的任务,想象我们有一系列数学运算,其中一些参数具有未知的真实值——这些是自适应参数(模型权重),它们将在机器学习过程中改变它们的值。权重乘以输入数据的总和称为输入的线性组合。这有点像收据——我们将商品数量乘以其单价,然后将结果相加,得到最终付款。这里,物品的未知价格是重量,购买物品的数量是输入数据,网络的答案应该是总价。

神经网络模型

这种单一的数学方程以及对其结果的适当反应(激活函数)可以被称为人工神经元。就像大脑中的神经元形成某些结构一样,人工神经元被组合成称为神经网络的复杂结构,我们可以在其中区分层。在下图中,它象征性地显示出来——每个神经元是一个圆形。开始时,在左侧,有一层神经元,称为输入层。在我们的计算机视觉任务中——对带有狗或松饼的图像进行分类——输入数据是组成分析图像的所有像素。在右侧,有一个给出预测的输出层—在我们的例子中是两个类。中间可能还有几个隐藏层。下一层中的神经元连接到前一层中的所有神经元。

简单的神经网络模型。图片由维基共享提供。

开始上课吧

有了这些知识,我们就可以进入实践部分了。在仓库中,你会找到 jupyter 笔记本,你可以用它来进一步学习。实用部分是用波兰语写的,但它是基于来自 SJSU ML 俱乐部英语初学者研讨会的材料。

作为 NAVOICA 项目的一部分,与弗罗茨瓦夫理工大学和 OPI 合作,在 2020/21 年冬季(波兰)为波兰学生进行了深度学习练习。查看我的视频教程(PL)。

原载于 2021 年 1 月 18 日https://majsylw . netlify . app

https://github.com/majsylw/chihuahua-vs-muffin

如何用数据讲述一个令人信服的故事

原文:https://towardsdatascience.com/how-to-tell-a-compelling-story-with-data-d00ea8cd1bb?source=collection_archive---------12-----------------------

数据新闻

将任何数据分析转化为难忘故事的 3 个步骤

T 这里有很多关于讲故事的炒作。就像数据一样。对我来说,讲故事只是“合理组织你的想法”的另一种说法。在任何数据分析的背景下,当涉及到通过数据传达信息时,给你的想法带来一个适当的结构似乎更加合理。

然而,如何最好地呈现您所进行的数据分析的输出并不总是不言而喻的。尤其是当涉及到技术数据操作时,分析可以进行几天、几周甚至几个月。如何最终将您的所有产出整合在一起,讲述一个引人注目的数据故事?

照片由 Rain BennettUnsplash 上拍摄

让我们来设定场景

你发现了有趣的数据来处理。你独自或与同事进行了出色的数据分析。也许你花了几天几夜“让数据说话”,找到了有见地的结果。但是你做到了:你最终发现了有趣的结果,并且希望你能找到你开始分析的问题的答案。等等,这个分析是关于什么的?

在这篇文章中,我想带您踏上我最近在公司进行的一次数据分析之旅。从我的老板最初提出要求,到我展示我的成果,我经历了混合数据分析和讲故事的几个步骤。这就是为什么我想与你分享一些关于如何从任何数据分析中讲述令人信服的数据故事的技巧

简单地说,我的老板让我建立同质的、相同规模的员工团队,这样就可以在具有相似背景的群体中规划 Excel 培训。如果你对这个分析的细节更感兴趣,可以看看本文中的。在找到了一种基于可用数据来回答他的请求的方法之后(这将是“数据挑战”),我必须向他和其他利益相关者展示我的方法的结果:这就是我所说的“讲故事的挑战”。

玛丽·勒费夫尔

第一步:收集你的想法

如果你进行过一定的数据分析,你应该知道你最初为什么开始它。然而,这说起来容易做起来难:当你在数据处理和解释中前进时,有时你可能会忘记分析的主要目标。别担心,我以前去过那里。

因此在进行“你是谁”数据分析之前回到“为什么”是从开始的关键一步。问自己以下问题:

  • 你想回答什么问题?
  • 你想达到什么目标?
  • 在这种情况下,您的数据有什么关系?

在我的例子中,我进行这个数据分析的原因是由上下文本身给出的。我的团队需要组成四个相同级别的员工小组,以便让每个人都能与具有相同技术背景的同事一起接受优秀的培训。我必须回答的问题是:如何最好地为这次培训组成四个小组?我必须达到的目标是形成具有相同数量个体的同质群体。为了做到这一点,我会使用我所掌握的数据:关于员工资历、Excel 熟练程度以及平均每天花在电脑上的时间的数据。

玛丽·勒费夫尔

第二步:确定你的受众

在讲述您的故事时,需要考虑的一个关键因素是您的数据故事面向的个人。《剑桥词典》对观众的定义之一是:“观看或收听演出、电影、公共活动等的人群。,要么一起在一个地方,要么分开”。我想在这里强调一下集团的概念。特别是对于数据故事,你的听众可能没有相同的背景来理解你的数据分析的技术元素。

既然你已经清楚地知道了为什么,让我们把注意力放在世卫组织上。为了确定你的故事的目标受众,你应该问自己以下问题:

  • 什么定义了你的观众群体?
  • 您的受众预先拥有什么类型的知识(如技术或行业相关知识)?
  • 你的故事为他们提供了什么额外的价值?

回到我之前的例子,我面临的挑战是说服我团队的老板,我的方法是将员工分成四个相似组的最佳方式。这是在更大范围内应用这种方法的第一次测试,所以我的故事将首先提交给我的老板,但最终它可能会被提交给其他部门并应用。因此,我的听众由团队领导组成,他们对数据科学有着模糊的认识(而我在分析中使用了 k-means 聚类)和非常以业务为导向的思维。我的故事带来的额外价值是在未来建立个人团体时节省时间。

你的观众是谁?戴维·拉古萨在 Unsplash 上的照片

第三步:建立你的叙述

对于这一最终阶段,请确保您拥有数据故事内容所需的所有元素:

  • 为什么:这个数据故事相关的根本原因及其回答的问题
  • 世卫组织:这个数据故事面向的受众以及他们应该面对的方式
  • 内容:数据分析的有形元素以数据可视化的形式呈现(表格、图表、图片……)

如果你接受的话,你的最终任务是将所有这些元素整合成一个一致且令人信服的数据故事。在这里,你想抓住你的观众的注意力,不仅仅是给他们一个有趣的故事,而是告诉他们一个真正让他们着迷的故事。为此,让我们转向文学或电影中的故事世界。一种常用的戏剧结构叫做弗雷塔格金字塔。在这种结构下,任何故事情节都由五部分组成:

  1. 展览会
  2. 上升动作
  3. 高潮
  4. 下落动作
  5. 灾难还是解决

你应该关注的是这个金字塔的第一、第三和最后几个元素,因为它们构成了你故事的核心结构。不要犹豫让你的听众参与到整个故事中来,比如问他们在故事的这个或那个时刻会做什么。

玛丽·勒费夫尔

尽管我的例子是一个非常短的数据故事(例如,与一个一小时的大规模数据分析项目的演示相比),我也应用了这种类型的结构。我是这样建造的:

  1. 在计划的 Excel 培训开始之前,必须建立参与者小组。挑战在于建立由相似个体组成的同等规模的团队。
  2. 我们第一次尝试将如此多样化的个体分成群体失败了:要么群体是相似的,但不是相同的大小,要么他们是相同的大小,但相对异质。当将这个问题扩展到整个公司时,这种随机分组方法将会失败。
  3. 我发现使用机器学习算法可以帮助我们建立个体集群。因此,我将 k-means 聚类算法应用于我们的问题,并将其参数化以适应我们的数据集。
  4. 我采取了以下步骤——在这里,我将更详细地介绍我的方法和假设。
  5. 这一旅程将我们带到了预期的结果:我们现在能够建立具有相似特征的相同规模的个体群体。Tadaaa,这是与他们对应的训练组的人员列表。

总结思想:获得信任

为了总结您正在尝试构建的这个“数据故事中的故事”,我想提高对您将集成到数据故事中的数据可视化片段的认识。讲述一个故事,尤其是当它依赖于技术分析时,不应该误导读者,让他相信你的故事,而不管你的论点是否正确。从这个意义上来说,特别注意你的故事元素的质量和真实性对于获得你的观众的信任是至关重要的:

  • 与他们分享你的分析中可能包含的潜在偏见
  • 用数字系统地支持你的陈述
  • 问问自己关于数据可视化的三个“黄金问题”

要进一步了解数据可视化方面的内容,您可以查看这篇文章:

💔-questions-you-should-ask-yourself-when-creating-data-visualizations-fa255652508a>

快乐讲故事!

你喜欢读这篇文章吗? 成为 的一员,加入一个不断成长的充满好奇心的社区吧!

如何用情感分析讲故事

原文:https://towardsdatascience.com/how-to-tell-stories-with-sentiment-analysis-f94cf9f8ca71?source=collection_archive---------16-----------------------

一名记者在分析 QAnon 时试图将数学引入新闻编辑室

上周,我发表了“《卡侬时间线:四年,5000 滴和无数失败的预言》。这项调查是与 Bellingcat 合作进行的,belling cat 是一家新闻编辑室,通过创新的开源和数据驱动的报道重塑了调查性新闻报道,最近在《NYT》、《华尔街日报》、《金融时报》、《华盛顿邮报》等上进行了专题报道。

我从开源社区的同事、数据科学家和记者那里收到了数量惊人的反馈。

到目前为止,最受欢迎的问题和兴趣点是方法论——我使用情绪分析来获得对 Qanon 增长故事的定量和定性见解。

今天关于数据科学,我将揭示我的方法。我还将深入解释如何在讲故事中应用这种创新的新方法,这有望成为任何对从数据中提炼有意义的故事感兴趣的人的宝贵财富。

开始使用数据🍕

QAnon 调查的核心是一个包含 4952 个所谓“Q 滴”的数据集,这些神秘的信息是阴谋论的核心。这些帖子是由一个被简称为“Q”的匿名人士发布的,他的追随者认为这个人是美国政治内幕消息的来源。每当一个 Q drop 出现,全世界的信徒都急切地试图解读它隐藏的含义,将他们与现实世界的事件联系起来。

Q 滴数据集是在图片板 8kun 上找到的,被 Q 关注者用作评论 Q 滴的位置。它包含的帖子可以追溯到 2017 年 10 月,当时 QAnon 理论是一种边缘在线爱好,并持续到 2020 年 10 月——到那时它们已经被太认真了。

方法学

本次调查的目标是阐明 QAnon 阴谋论随时间推移的主要发展和讨论。为此,我们将数据分成多个子集,每个子集有一到三个月的时间间隔。

对于每个子集,我们运行了一个 聚类算法 ,将具有相似情感的句子分组在一起。利用聚类的结果,我们总结了每个时间段的主要主题和值得注意的发展。

“情绪”是使用 通用句子编码器 进行评估的,这是一种学术上认可的文本分类模型,根据其含义将每个 Q 下降转换为一组数字——一个向量。

意义相近的 Q 滴,向量相似。两个向量的接近程度可以通过计算它们的点积来计算。因此,我们能够评估句子之间情感的“接近程度”,以便对每个 Q drop 的文本进行分类。

综上所述,这里有三个主要步骤。我们将逐个介绍它们,而上面的部分可以作为这些步骤如何组合在一起的高层次概述。

  1. 将数据分割成多个部分
  2. 情感分析
  3. 算法聚类

1)拆分数据🐼🐍

首先,我们希望在更短的时间间隔内将数据分割成多个子集,并执行任何必要的数据清理。这只是数据分析 101,所以我不打算进入太多的细节,但会推荐一些额外的资源,如果你有兴趣阅读更多!

我最喜欢的数据分析工具是 Python + Pandas dynamic duo。这里欢迎您使用任何编程语言,但是如果您第一次尝试数据分析,我强烈建议您使用这种技术。

🐍对于运行 Python 编程语言来说,py charm是我首选的开发环境,但是很多数据科学家也更喜欢使用 Jupyter 笔记本

🐼 Pandas 是一个广泛流行且超级强大的 Python 数据分析库。

如果你对介绍导入数据集和清理数据的熊猫教程感兴趣,这里有一个很好的资源,来自数据科学。另外,我推荐 Pandas 用于任何数据分析任务的另一个原因是因为它的强大的“分组”功能。

Pandas Groupby 函数允许我们获取一个数据帧(Pandas 中的一个数据集),并基于一个属性轻松地将其分割成子集。

在这个用例中,我们可以按月“分组”,按时间间隔划分数据集。按月分组的具体代码片段可以在这篇 stack overflow 文章中找到,在 Pandas 中遍历“分组”数据的惊人指南可以在这里找到。

2)情感分析

文字很难处理——我们更喜欢数字!(从来没有其他记者这么说过,但对于情感分析来说,这是非常正确的。)

理想的目标是将每个 Q 液滴转换成代表其含义的数字数组,这样我们的液滴数据集看起来更像这样:

那么…我们该怎么做呢?

答案是单词嵌入,这是一种对文本的学习表征,意思相似的单词有相似的表征。由于单词嵌入是自然语言处理中的一种技术,也是机器学习的一个子集,因此基本上有两种方法可以做到这一点:

a)从 Qanon 相关数据中训练我们自己的单词嵌入模型。

b)借用别人的文字嵌入模型,将文字转换成数字。

由于前者需要许多许多个月的工作,我们将采用后者。在这个例子中,我使用了谷歌发布的一个学术上备受好评的单词嵌入模型,该模型用包括政治文本在内的各种数据进行了训练,并针对句子和短段落进行了优化。这个模型的教程“通用句子编码器”可以在这里找到。

🦜 通用句子编码器使用指南

from absl import logging
import tensorflow as tf
import tensorflow_hub as hub
import numpy as nptf.compat.v1.disable_eager_execution()

embed = hub.Module("https://tfhub.dev/google/universal-sentence-encoder/1")

paragraph1 = (
    "I am a sentence for which I would like to get its embedding."
    "Universal Sentence Encoder embeddings also support short paragraphs. "
    "There is no hard limit on how long the paragraph is. Roughly, the longer "
    "the more 'diluted' the embedding will be.")

paragraph2 = "There are Puppets. There are Puppet Masters. Which is MUELLER?"

messages = [paragraph1, paragraph2]

with tf.Session() as session:
  session.run([tf.global_variables_initializer(), tf.tables_initializer()])
  message_embeddings = session.run(embed(messages))

  for i, message_embedding in enumerate(np.array(message_embeddings).tolist()):
    print("Message: {}".format(messages[i]))
    print("Embedding size: {}".format(len(message_embedding)))
    message_embedding_snippet = ", ".join(
        (str(x) for x in message_embedding[:3]))
    print("Embedding: [{},...]\n".format(message_embedding_snippet))

在上面的片段中,我们首先导入 TensorFlow ,这是一个由 Google 开发的流行的 Python 机器学习库。

接下来的代码部分全部来自通用语句编码器指南,在第 8 行,我们从互联网上下载了“嵌入”模块,它获取我们的输入文本,并将文本转换为一个向量,一个 512 个数字的列表。输出数据包含在“message_embeddings”变量中,我们可以用它来分析数据并将数据导出到 excel 表中。

3)将事物聚集在一起

在我们将相似的液滴聚集在一起之前,我们需要知道如何评估两个液滴是相似的。幸运的是,我们已经将 Q 值转换成了向量(基本上是数字数组)。回想一下高中数学,两个向量的“相似性”与其点积成正比,平行向量的点积等于 1。

在 Python 中,求两个向量的点积非常简单:

import numpy as npprint(np.dot(a, b))

升温[地图]

让我们来看一个实际例子吧!下面我们有来自 Q 滴的 10 句话。其中五项与罗伯特·穆勒有关,五项与脸书有关。

10 句话列表:

米勒:“有木偶。有傀儡师。哪个是[穆勒]?”,
米勒 2:"试图取代[JC]成为联邦调查局局长失败[试图重新获得联邦调查局的控制权]。",
米勒 3:“【米勒】【爱泼斯坦埋葬&掩盖真相】”MUELLER 4:"[MUELLER][阴谋推翻正式当选的总统]。"米勒 5:“美国历史上最大的丑闻。叛国。”,
face book 1:“FB 是什么?”,
Facebook2:“间谍工具?”,
Facebook3:“谁创造的?”,
Facebook4:“到底是谁创造的?”,
Facebook5:“没有什么是看起来那样的。”

使用 Python 中的 Seaborn 库制作的热图,我们可以在从 0 到 1 的范围内可视化每对句子的点积。对角线都是暗红色的,因为每一滴都是相同的。请注意左上角大部分是橙色的,因为穆勒的句子彼此更相关,而脸书的句子除了 FB3(“谁创造了它”)和 FB4(“谁真正创造了它”)之外几乎没有关系,这两个句子非常相似,并且都是红色的。

最后一步,我们可以对 Q 个液滴运行聚类算法,将相似的液滴分类在一起。在这个例子中,我们使用了聚集聚类,尽管有许多其他的聚类算法。

这里有一个在 Python 中应用聚集聚类的教程。它能够根据相似性对向量/数字列表进行分组,同时考虑到我们快速查看向量时得到的数学知识。

from sklearn.cluster import AgglomerativeClustering
import pandas as pd
import os

CSV_Path = os.path.join('data.csv')
df = pd.read_csv(CSV_Path)

arr = df.iloc[:,1].to_numpy()
vector = df.iloc[:,3].to_numpy()
dates = df.iloc[:,0].to_numpy()

dates = dates.tolist()[0:200]
sentences = arr.tolist()[0:200]
vector = vector.tolist()[0:200]

for i in range (len(vector)):
    vector[i] = vector[i][1:-1].split()

clustering = AgglomerativeClustering(n_clusters=3).fit(vector)
print(clustering.labels_)

我们简化并指定我们想要的聚类数,并在 Q 个点的子集上运行该算法。我通常喜欢根据子集中的数量下降来修改聚类的数量。这是该算法的一个局限性,另一个聚类算法如 KD 意味着可能能够更好地预测数据集的最佳聚类数。

最后,在数据集上执行算法后,我们可以通读每个聚类中最常见的趋势,然后写下它们,这是计算机永远无法自动化的调查的定性/新闻部分。

这是最终产品的链接,这是调查 Q 滴的方法论的结果:🍕 《卡农时间线》:四年,五千滴,无数次失败的预言

感谢阅读!我目前是 BBC 非洲之眼的开源调查员和自由数据记者。你也可以订阅我的简讯 括号 ,每周一次深入科技、数据和新闻的新兴交叉领域。如果您有任何问题或意见,请直接在 Twitter @上联系我@Edward _ the 6

如何用几行 Python 测试多个机器学习管道

原文:https://towardsdatascience.com/how-to-test-multiple-machine-learning-pipelines-with-just-a-few-lines-of-python-1a16cb4686d?source=collection_archive---------13-----------------------

昆腾·德格拉夫在 Unsplash 上的照片

介绍

在项目的探索阶段,数据科学家试图为他的特定用例找到最佳的管道。因为几乎不可能预先知道哪种转换将对模型的结果最有益,所以这个过程通常包括尝试不同的方法。例如,如果我们正在处理一个不平衡的数据集,我们应该对少数类进行过采样还是对多数类进行欠采样?在这个故事中,我将解释如何使用 ATOM 包来快速帮助您评估在不同管道上训练的模型的性能。ATOM 是一个开源的 Python 包,旨在帮助数据科学家加快机器学习管道的探索。如果你想对图书馆有一个温和的介绍,请阅读这个故事。

管理管道

解释如何管理多个管道的最简单的方法是通过一个例子。在本例中,我们将:

  1. 创建一个不平衡的数据集,并将其提供给 atom

2.使用递归特征消除减少特征数量(RFE)

3.训练三个随机森林(射频)模型:

  • 一个直接在不平衡数据集上训练
  • 在应用过采样后对数据集进行训练
  • 一个在应用欠采样后在数据集上训练

4.比较结果

我们将用不到 20 行代码完成所有这些工作!让我们开始吧。

创建数据集

我们开始创建一个模拟二进制分类数据集,将 0.95–0.05 比例的样本分配给每个类。然后,数据被输入到 atom。

from atom import ATOMClassifier
from sklearn.datasets import make_classification# Create an imbalanced dataset
X, y = make_classification(
    n_samples=5000,
    n_features=30,
    n_informative=20,
    weights=(0.95,),
)# Load the dataset into atom
atom = ATOMClassifier(X, y, test_size=0.2, verbose=2)

数据集被自动分为训练集和测试集。输出如下所示。

<< ================== ATOM ================== >>
Algorithm task: binary classification.

Dataset stats ====================== >>
Shape: (5000, 31)
Scaled: False
Outlier values: 582 (0.5%)
---------------------------------------
Train set size: 4000
Test set size: 1000
---------------------------------------
|    | dataset     | train       | test       |
|---:|:------------|:------------|:-----------|
|  0 | 4731 (17.6) | 3777 (16.9) | 954 (20.7) |
|  1 | 269 (1.0)   | 223 (1.0)   | 46 (1.0)   |

我们可以立即看到数据集是不平衡的,因为它包含的 0 比 1 多 18 倍。我们来看一下数据。注意,由于输入不是 dataframe,atom 为列指定了默认名称。

atom.dataset.head()

执行特征选择

出于解释的目的,我们将从一个数据转换步骤开始,我们希望在我们将要测试的所有管道中共享这个步骤。通常,这类似于特征缩放或缺失值的插补。在这种情况下,我们将数据的维度从 30 个特征减少到 12 个特征。有了 atom,就像这样简单。

atom.feature_selection("RFE", solver="RF", n_features=12)

此命令使用随机森林作为估计器来运行 RFE。剩余的数据集包含最有希望的要素。

Fitting FeatureSelector...
Performing feature selection...
 --> The RFE selected 12 features from the dataset.
   >>> Dropping feature Feature 2 (rank 3).
   >>> Dropping feature Feature 3 (rank 8).
   >>> Dropping feature Feature 5 (rank 10).
   >>> Dropping feature Feature 7 (rank 17).
   >>> Dropping feature Feature 8 (rank 12).
   >>> Dropping feature Feature 11 (rank 19).
   >>> Dropping feature Feature 13 (rank 13).
   >>> Dropping feature Feature 14 (rank 11).
   >>> Dropping feature Feature 15 (rank 15).
   >>> Dropping feature Feature 17 (rank 4).
   >>> Dropping feature Feature 19 (rank 16).
   >>> Dropping feature Feature 20 (rank 2).
   >>> Dropping feature Feature 21 (rank 6).
   >>> Dropping feature Feature 23 (rank 5).
   >>> Dropping feature Feature 24 (rank 9).
   >>> Dropping feature Feature 25 (rank 18).
   >>> Dropping feature Feature 26 (rank 7).
   >>> Dropping feature Feature 27 (rank 14).

现在,我们直接在不平衡数据集上训练我们的第一个模型。使用run方法,我们在训练集上拟合一个随机森林,并在测试集上对其进行评估。

atom.run(models="RF", metric="balanced_accuracy")

Training ===================================== >>
Models: RF
Metric: balanced_accuracy

Results for Random Forest:         
Fit ---------------------------------------------
Train evaluation --> balanced_accuracy: 1.0
Test evaluation --> balanced_accuracy: 0.5326
Time elapsed: 0.733s
-------------------------------------------------
Total time: 0.733s

Final results ========================= >>
Duration: 0.733s
------------------------------------------
Random Forest --> balanced_accuracy: 0.5326

分支系统

在继续之前,是时候解释一下 ATOM 的分支系统了。分支系统允许您在同一个 atom 实例中管理多个管道。每个管道都存储在一个单独的分支中,可以通过branch属性进行访问。分支包含数据集的副本,以及适合该特定数据集的所有转换器和模型。从 atom 调用的方法总是使用当前分支中的数据集,以及atom.dataset等数据属性。默认情况下,atom 从一个名为master的分支开始。致电分支机构,了解其包含的变压器和型号的概况。

atom.branch

Branch: master
 --> Pipeline: 
   >>> FeatureSelector
     --> strategy: RFE
     --> solver: RandomForestClassifier(n_jobs=1, random_state=1)
     --> n_features: 12
     --> max_frac_repeated: 1.0
     --> max_correlation: 1.0
     --> kwargs: {}
 --> Models: RF

当前分支包含我们之前调用的用于特征选择的类,以及我们刚刚训练的模型。

过采样

现在是时候测试模型在对数据集进行过采样后的表现了。在这里,我们创建一个名为oversample的新分支。

atom.branch = "oversample"

New branch oversample successfully created!

注意:创建新分支会自动将当前分支更改为新分支。要在现有分支之间切换,只需输入所需分支的名称,例如atom.branch = "master"即可返回主分支。

过采样分支从当前分支(主分支)中分离出来,采用其数据集和转换器。这意味着特性选择转换器现在也是过采样流水线中的一个步骤。像这样分割分支可以避免重新计算之前的转换。

使用 SMOTE 调用balance方法对数据集进行过采样。

atom.balance(strategy="smote")

Oversampling with SMOTE...
 --> Adding 7102 samples to class: 1.

请记住,该方法仅转换当前分支中的数据集。主分支中的数据集保持不变。快速检查转换是否有效。

atom.classes

请注意,只有训练集是平衡的,因为我们希望在测试集中保留原始的类分布。

现在,我们可以在过采样数据集上训练一个随机森林模型。为了将这个模型与我们训练的第一个模型区分开来,我们在模型的缩写后面添加了一个标记(os 表示过采样)。

atom.run(models="RF_os", metric="balanced_accuracy")

Training ===================================== >>
Models: RF_os
Metric: balanced_accuracy

Results for Random Forest:         
Fit ---------------------------------------------
Train evaluation --> balanced_accuracy: 1.0
Test evaluation --> balanced_accuracy: 0.7737
Time elapsed: 1.325s
-------------------------------------------------
Total time: 1.325s

Final results ========================= >>
Duration: 1.341s
------------------------------------------
Random Forest --> balanced_accuracy: 0.7737

欠采样

需要一个新的分支来对数据进行欠采样。由于当前分支包含过采样数据集,我们必须将新分支从仅包含 RFE 变换器的主分支中分离出来。

atom.branch = "undersample_from_master"

New branch undersample successfully created!

在新分支和现有分支之间添加_from_,将其从现有分支而不是当前分支中分离出来。检查欠采样分支中的数据集是否仍然不平衡。

atom.classes

再次调用balance方法,使用 NearMiss 对数据进行欠采样。

atom.balance(strategy="NearMiss")

Undersampling with NearMiss...
 --> Removing 7102 samples from class: 0.

并使用新标签(us 表示欠采样)拟合随机森林。

atom.run(models="RF_us", metric="balanced_accuracy")

Training ===================================== >>
Models: RF_us
Metric: balanced_accuracy

Results for Random Forest:         
Fit ---------------------------------------------
Train evaluation --> balanced_accuracy: 1.0
Test evaluation --> balanced_accuracy: 0.6888
Time elapsed: 0.189s
-------------------------------------------------
Total time: 0.189s

Final results ========================= >>
Duration: 0.189s
------------------------------------------
Random Forest --> balanced_accuracy: 0.6888

如果我们现在查看我们的分支,我们会看到管道只包含我们想要的两个转换。

atom.branch

Branch: undersample
 --> Pipeline: 
   >>> FeatureSelector
     --> strategy: RFE
     --> solver: RandomForestClassifier(n_jobs=1, random_state=1)
     --> n_features: 12
     --> max_frac_repeated: 1.0
     --> max_correlation: 1.0
     --> kwargs: {}
   >>> Balancer
     --> strategy: NearMiss
     --> kwargs: {}
 --> Models: RF_us

分析结果

我们最终在 atom 实例中获得了我们想要的三个模型。分支系统现在看起来如下。

RFE 变换在三个分支之间共享,但是之后,每个分支遵循不同的路径。主分支没有其他变压器,而其他两个分支各自应用不同的平衡算法。所有三个分支都包含一个随机森林模型,每个都在不同的数据集上进行训练。剩下的就是比较结果了。

atom.evaluate()

atom.plot_prc()

结论

我们已经了解了如何使用 ATOM 包轻松比较多个机器学习管道。将所有管道(以及模型)放在同一个 atom 实例中有几个优点:

  • 代码更短,这使得笔记本不那么杂乱,并且更容易维护概览
  • 跨管道共享的转换不需要重新计算
  • 使用 atom 的绘图方法可以更容易地比较结果

我们所经历的例子非常简单,但是 ATOM 可以做得更多!要了解更多信息,请查看这个相关的故事或者看看软件包的文档。对于 bug 或功能需求,请不要犹豫,在 GitHub 上发帖或给我发邮件。

如何用 Julia 测试你的软件

原文:https://towardsdatascience.com/how-to-test-your-software-with-julia-4050379a9f3?source=collection_archive---------14-----------------------

确保你的 Julia 软件实际上与测试包一起工作!

(src =https://pixabay.com/images/id-731198/

介绍

测试是迭代软件开发最重要的方面之一。这是因为测试可以自动揭示软件的问题,而不需要实际使用软件。不用说,将甚至不工作的软件推送到存储库可能是个坏主意,测试可以避免碰到这个问题。在 Julia 编程语言中实现测试,我认为这是一个非常棒和独特的实现。我认为它很棒,因为它提供了一种使用条件和宏测试软件的非常结构化和简单的方法。今天我想为 Julia 介绍一下 Testing.jl 包的基础知识,这样你就可以在犯下大错之前确保你的软件正常工作。

设置包

为了演示 Julia 的测试包,我们首先需要建立一个新项目。为了建立一个新的项目,我们可以使用 Pkg.generate(),或者 Pkg REPL 中的 generate 命令。一旦进入朱莉娅 press,我将按下]并生成我们命名为“Sample”的新项目

julia> ]
([@v1](http://twitter.com/v1).6) pkg> generate sample

接下来,我将退格退出 REPL,然后按;参加 REPL 的狂欢。然后,我们将 cd 放入新的项目文件夹。

julia> ;
shell> cd sample

现在,我将 cd 放入 source 文件夹,并对 sample.jl 文件进行 nano,添加一个我们可以测试的新函数。

shell> cd src
/home/emmett/dev/julia/sample/srcshell> nano sample.jl

在这个文件中,我放了一些用于模型验证的函数,以及用于支持它们的函数:

mean(x) = sum(x) / length(x)
function mae(actual,pred)
    l = length(actual)
    lp = length(pred)
    if l != lp
        throw(ArgumentError("The array shape does not match!"))
    end
    result = actual-pred
    maeunf = mean(result)
    if maeunf < 0
        maeunf = (maeunf - maeunf) - maeunf
    end
    return(maeunf)
endfunction mse(y,ŷ)
    diff = y .- ŷ
    diff = diff .^ 2
    Σdiff = sum(diff)
    return(Σdiff)
end
function correlationcoeff(x,y)
    n = length(x)
    yl = length(y)
    [@assert](http://twitter.com/assert) n == yl DimensionMismatch("These Arrays are not the same size.")
    xy = x .* y
    sx = sum(x)
    sy = sum(y)
    sxy = sum(xy)
    x2 = x .^ 2
    y2 = y .^ 2
    sx2 = sum(x2)
    sy2 = sum(y2)
    ((n*sxy) - (sx * sy)) / (sqrt((((n*sx2)-(sx^2)) * ((n*sy2)-(sy^2)))))
endfunction r2(actual,pred)
    l = length(actual)
    lp = length(pred)
    if l != lp
        throw(ArgumentError("The array shape does not match!"))
    end
    r = correlationcoeff(actual,pred)
    rsq = r^2
    rsq = rsq * 100
    return(rsq)
end
export r2, mae, mse

然后我使用 ctrl+O 来删除新的缓冲区,现在我们可以开始实际测试这些函数了!

测试

现在我们实际上已经有了一个要测试的包,我们可以着手设置我们的测试环境了。对于 Julia 包,测试和文档都被认为是独立于原始包的包。记住,我们将再次使用 generate 命令来创建这两个项目目录。我们将激活这个新的测试环境,然后将测试依赖项添加到它的虚拟环境中。

shell> cd ..
/home/emmett/dev/julia/sample([@v1](http://twitter.com/v1).6) pkg> activate test
  Activating new environment at `~/dev/julia/sample/test/Project.toml`(test) pkg> add Test
    Updating registry at `~/.julia/registries/General`
   Resolving package versions...
    Updating `~/dev/julia/sample/test/Project.toml`
  [8dfed614] + Test
    Updating `~/dev/julia/sample/test/Manifest.toml`
  [2a0f44e3] + Base64
  [b77e0a4c] + InteractiveUtils
  [56ddb016] + Logging
  [d6f4376e] + Markdown
  [9a3f8284] + Random
  [9e88b42a] + Serialization
  [8dfed614] + Test(test) pkg>

现在我们可以编写测试算法了。包内的第一个函数是 MAE。为了执行测试,我们需要启动一个测试集。这是通过测试集宏完成的。在宏之后,我们提供一个字符串作为第一个参数,然后我们提供一个表达式作为第二个参数。字符串是测试集的标题,表达式是执行测试的代码。我们可以使用 begin 和 end 块创建这样的表达式。所有这些看起来就像这样:

using Testinclude("../src/sample.jl")using Main.sample[@testset](http://twitter.com/testset) "MAE tests" beginend

我们将从两者相等的测试开始这些测试,对于这个场景,MAE 应该是 1。测试宏接受一个参数,这个参数是一个布尔值。让我们在两个相等数组的 MAE 上使用一个 bool 类型的按位运算符,它应该等于零。

x = [5, 10, 15]
y = [5, 10, 15]
[@test](http://twitter.com/test) mae(x, y) == 0

我们的下一个测试将会是,我们是否真的得到了 dims 差异的平均值。

x, y = [4, 10, 15], [5, 10, 15]
    [@test](http://twitter.com/test) mae(x, y) == mean([1, 0, 0])

对于最终的测试集,如下所示:

using Main.sample: r2, mae, mse, mean
[@testset](http://twitter.com/testset) "MAE Tests" begin
    x = [5, 10, 15]
    y = [5, 10, 15]
    [@test](http://twitter.com/test) mae(x, y) == 0
    x, y = [4, 10, 15], [5, 10, 15]
    [@test](http://twitter.com/test) mae(x, y) == mean([1, 0, 0])
end

接下来,我们将为 MSE 函数开始一个新的测试集。我们将做一个断言测试,和一个零测试,就像我们之前做的一样。

[@testset](http://twitter.com/testset) "MSE Tests" begin
x = [5, 10, 15]
y = [5, 10, 15]
[@test](http://twitter.com/test) mse(x, y) == 0
y = [4, 10, 15]
y2 = [6, 10, 15]
[@test](http://twitter.com/test) mse(x, y) == mse(x, y2)
end

接下来,我们将测试我们的 r 函数。因为我们的 r 函数要返回一个百分比,我们将检查返回的类型是否为 Float64,然后检查它是否小于 1。

[@testset](http://twitter.com/testset) "R2 Tests" begin
x = randn(50)
y = randn(50)
[@test](http://twitter.com/test) r2(x, y) <= 1
[@test](http://twitter.com/test) typeof(r2(x, y)) == Float64

现在,我们可以通过返回到 REPL 并包含这些代码来运行我们的测试。

include("test/test.jl")

(图片由作者提供)

结论

无论你创建什么样的软件,测试它总是很重要的。Julia 有一个非常酷的测试软件的方法,它利用宏并使测试非常有条理。与许多其他测试风格相比,我更喜欢这种方法,我认为 Julia 使用这种方法使测试变得轻而易举。非常感谢您阅读我的文章,我希望所提供的信息对使您的软件更好地工作是有价值的!感谢您的阅读!

如何用 Python 测试你的软件

原文:https://towardsdatascience.com/how-to-test-your-software-with-python-f931adb04e89?source=collection_archive---------31-----------------------

Python 中测试模块的概述

(src =https://pixabay.com/images/id-2521144/

介绍

不管你写的是什么样的软件,在开发过程中总会遇到一些问题和错误。不管你的软件写得有多好,或者你碰巧是个多么优秀的程序员,这都很重要。幸运的是,有一些方法可以让我们通过测试来发现软件中的错误和问题。

测试是解决软件缺陷和问题的行业标准技术。测试不仅对于修复错误很重要,对于监控软件中隐含的变化也很重要。有时,依赖的方法或类型可能会被意外地完全改变,测试可以让你在最终将你的软件推向精通之前意识到这一点。今天,我想回顾一下 Python 编程语言的测试基础,这样你就可以放心地编写代码了!另外,对于那些也喜欢用 Julia 编程或者只是好奇的人,我也有另一篇用 Julia 做同样事情的文章!:

[## 如何用 Julia 测试你的软件

towardsdatascience.com](/how-to-test-your-software-with-julia-4050379a9f3)

单元测试与集成测试

在开始实际测试我们的 Python 服务器之前,让我们快速回顾一下 Python 中常见的两种测试技术之间的区别。单元测试用于测试软件内部的小组件。另一方面,集成测试用于测试相互依赖的组件。

为了阐明这个观点,让我们考虑一个类比。我们有一栋房子,灯泡坏了。我们可以通过扳动电灯开关来测试灯是否熄灭。这将被认为是一个单元测试。然而,如果我们要测试这盏灯所依赖的电气系统,它将被视为一个集成测试。集成测试同时测试多个组件。

测试

在 Python 中,相当流行的方法是断言测试。断言测试使用条件来提供我们遇到问题时的抛出。我们可以使用许多方法来断言,考虑下面的例子:

def test_sum():
    assert sum([1, 2, 3]) == 6, "Should be 6"

if __name__ == "__main__":
    test_sum()
    print("Everything passed")

这将抛出一个错误。对于后续测试,当在执行过程中抛出错误时,后续测试将不会运行。记住,我们可以通过使用 Python 中的 unittest 模块来解决这样的问题。这通常是通过构建单元测试的测试子类来完成的。测试用例类。我们可以这样写这个类:

**import** **unittest**

**class** **TestStringMethods**(unittest.TestCase):

现在我们将我们的每个测试方法添加到这个类中:

**def** test_upper(self):
        self.assertEqual('foo'.upper(), 'FOO')

    **def** test_isupper(self):
        self.assertTrue('FOO'.isupper())
        self.assertFalse('Foo'.isupper())

    **def** test_split(self):
        s = 'hello world'
        self.assertEqual(s.split(), ['hello', 'world'])
        *# check that s.split fails when the separator is not a string*
        **with** self.assertRaises(TypeError):
            s.split(2)

最后,我们需要调用 unittest.main()。这个函数在我们的模块内部运行 TestCase 类型的所有子类,并调用它们的所有方法。这将执行测试,并给我们一些可爱的输出,显示我们的测试是如何执行的,同时也运行所有的测试,不管失败与否。

结论

测试是软件工程过程中的一个重要步骤。尽管有时这看起来是额外的工作,但它对于确保您的软件按照预期的方式工作并在未来工作是至关重要的。它还可以用来监控我们软件的隐含变化。我还想说,我真的很喜欢 Python 的测试实现。我认为 unittesting 模块在测试集上加入面向对象的元素是很酷的。这是一个很酷的方法,尽管我仍然会说我更喜欢 Julia 的测试,原因纯粹是主观的——这是一个很好的实现!感谢您的阅读,祝您编码愉快!

如何测试你的 Spark Scala 代码

原文:https://towardsdatascience.com/how-to-test-your-spark-scala-code-268e5de471fd?source=collection_archive---------8-----------------------

让我们使用 Mockito 和 scalatest 为 Spark Scala 数据帧转换编写一些测试

克里斯托夫·高尔在 Unsplash 上拍摄的照片

Spark 转换的单元测试可能很棘手,可能你甚至不能编写 try 单元测试(我喜欢 stackoverflow 的这个回答)。然而,您需要以某种方式测试您的转换。我写了这段代码来分享我最近在这个问题上的经验以及我是如何解决这个问题的。

问题陈述:

假设您的数据管道中有一个如下结构的对象:

它读取数据->转换数据->加载到某个存储。简单的 ETL,很容易。现在让我们使用 Mockito 和 scalatest 为该对象编写一个测试。

写作测试

对于测试,我将使用 mockito-scalascalatest 库来使用它,您需要将它添加到您的 build.sbt:

libraryDependencies ++= Seq("org.scalatest" %% "scalatest" % "3.2.2" % Test,"org.mockito" %% "mockito-scala" % "1.16.23" % Test)

现在实际的测试类:

万岁,我们刚刚为我们的火花代码做了一个测试🎉🎉 🎉

让我们重复一下我们在这里所做的事情:

  1. 我们用 mockito 模拟 IO 方法,所以我们没有加载实际的文件,而是不调用loaddatafrombaute方法,而是替换 DataFrame,它通常会返回我们为测试准备的测试数据
  2. 类似的事情发生在 writeResultsToBucket 方法上,它从未被调用过
  3. 我们用 ArgumentCaptor 捕获 spark 转换的结果。
  4. 我们使用简单的断言比较了转换的实际结果和预期结果

您可能会考虑的一些其他事项:

测试专用火花会议:

你可以从 scalatest(org . scalatest . BeforeAndAfter)中使用 before and after,请看这里的例子:https://www.scalatest.org/getting_started_with_fun_suite

或者只为测试创建一个专用的 spark 会话。

如何比较数据帧:

比较数据帧的更好方法可能是借助 spark-fast-tests 库:https://github.com/MrPowers/spark-fast-tests/

特别是如果出于某种原因你需要比较大的数据帧,那么这个库将会非常方便

测试数据:

上面描述的方法依赖于您需要为您的测试准备的数据样本,因为您可能不希望查询与您的生产代码稍后要做的一样多的数据。所以你可以做以下列表中的事情:

  • 如果您的样本非常小,比如只有 1-2 列,请在存储库中保存一个小的数据样本
  • 作为测试的一部分,随时生成数据,基本上将测试数据硬编码在 scala 代码中
  • 将样本数据保存在某个远程存储桶中,并在测试期间加载它
  • 最后,您可以从数据库中查询示例数据

每种选择都有其利弊,我个人更喜欢将测试数据以某种人类可读的格式存储在存储库中,比如 JSON。但是这完全取决于你项目的具体情况。

感谢阅读!让我知道你的想法,以及你如何为 spark 编写测试?欢迎随时在 LinkedIn GitHub或我的网站piece-data.com

参考资料:

  1. 莫奇托-斯卡拉:https://github.com/mockito/mockito-scala
  2. https://www.scalatest.org/
  3. 火花快速测试:https://github.com/MrPowers/spark-fast-tests/

如何看待数据、数据科学和时间序列

原文:https://towardsdatascience.com/how-to-think-about-data-data-science-and-time-series-7b2fdb74bee3?source=collection_archive---------37-----------------------

什么是数据、数据科学和时间序列?

数据是对世界的测量。我们可以通过多种方式获取数据;我们可以在一个时间点捕捉不同人的特征数据,从人群中收集样本横截面数据,并找到例如身高分布,即所收集样本中个体的平均身高。我们还可以在多个时间点收集这样的样本,也许可以看到平均高度如何随时间变化——这是面板数据。最后,我们可以专注于一个个体而不是一个群体,多年来每天收集他们的身高测量值,并跟踪他们的身高演变。这个最后的数据将是一个时间序列类型的数据样本。为理解时间序列样本而开发的思想可以从一个人的高度转化为海事部门中一艘船的各种测量值的变化的演化。但是我们所说的“理解”时间序列是什么意思呢?它意味着创建一个函数 f(x) 来捕捉数据点如何随时间变化;在存在某种模式的情况下,该函数将捕获该模式,这样我们将能够描述/总结/抽象/概括时间序列过程。例如,如果我们在一个孩子生命的前 10 年里每年测量他的身高,我们发现他的身高从 70 厘米开始,每年增长 7 厘米,到 10 岁时达到 140 厘米,那么这个函数看起来就像:

**f(x) = b*x(t-1) + 7			(1)**

f(x)是下一年的观测值,x 是当年的观测值;因此,从一年到下一年的过渡由上面的函数定义(在前一个值的基础上增加 7 厘米)。换句话说,该函数捕获了数据生成过程,它被正式称为模型。在数据科学领域,我们使用数据来告诉我们模型看起来像什么。这意味着我们事先不知道孩子身高的进化是他们每年长高 7 厘米。我们“训练”一种算法,该算法找到这种模式,并发出通知我们这种模式的模型。因此,这个模型对于信息/研究原因是有用的,但是对于预测原因也是重要的。如果你知道这是孩子身高演变的方式,你可以用今天的身高,加上 7,得到明年身高的预测!如你所见,在时间序列的例子中,这个个体的观察是相关的。如果我们收集横截面数据(在一个时间点上许多不同个体的身高),就没有理由假设他们的身高以任何方式相关——假设从人群中随机抽取样本。如果我们要从人群中挑选一个新的个体,知道最后被选中的个体的身高并不重要。这与时间序列形成对比,在时间序列中,如果我们明年对同一个人进行采样,知道最后一次观察(他们今年的身高)确实会告诉我们他们可能的身高。

自回归模型

转到稍微更技术性的材料,人们可以很快发现并非所有的时间序列都是相同的。个人的身高可以被视为每年大致呈线性增长,但比雷埃夫斯港的室外温度显然不是线性的!我们看不到每年的温度比去年高 7 度!这里我们看到一个每年重复的季节性模式。分析这些温度数据的数据科学算法/函数将与我们的第一个函数有很大不同。有人可能会说,假设我们有每月观测数据,它会是这样的:

**f(x) = b*x(t-12) (2)**

这意味着本月的观察与 12 个月前相同,有道理;通过对比去年 7 月和今年 4 月的气温,可以最好地预测 7 月的气温。从技术上讲,这被称为自回归模型。有见识的读者可能知道什么是回归;我们只是针对横截面数据的情况讨论了这个函数/模型,例如,在横截面数据中,我们发现一个人的身高如何根据父母的身高而变化。但是在这里,因为我们在时间序列空间内,高度在先前的时间点上回归到自身;因此出现了自动回归。在正常回归的情况下,我们可能有一个我们试图预测的因变量和许多自变量/特征,其中一些将能够解释因变量的变化。真正显著的变量被保留在最终的模型/函数中,,因为数据告诉我们它们是有用的预测器。在时间序列自回归模型的情况下,要包括在自回归中的候选变量是人的身高观察的所有以前的滞后,模型告诉我们哪些过去的时期/滞后对于解释当前的观察是重要的。在温度的例子中,模型告诉我们,无论我们现在观察的是什么时间戳,重要的自回归变量都有 12 个滞后;当前值始终取决于之前的 12 个周期。寻找显著自回归变量的方法与横截面案例非常相似,在横截面案例中,我们可以从探索不同变量的相关性开始,保留一些变量,然后对最相关的变量进行回归,以得出最能代表数据的模型的最终特征选择。在时间序列的情况下,通过使用 Box-Jenkins 方法,我们运行自相关和偏自相关图,以查看时间序列的观测值与过去不同滞后时间的观测值之间的相关性。

作者图片

在上面的部分自相关图中,我们看到这个时间序列具有这样的特征,即当前值依赖于 1 到 9 个滞后之前的值(高于蓝色阈值)。因此,如果我们想要自回归该变量(称其为高度只是为了连续性),我们将选择 9 个特征,即 9 个高度滞后,以最好地表示最终模型中的数据。一个更有经验的建模者会知道一个简约/简单的模型总是更好的,所以他们会只选择第一个滞后作为一个特征,因为它是高度相关的,并且比其他滞后携带更多关于下一个值的信息。因此,他们只会在模型中选择一个如下所示的特征:

**f(x) = b*x(t-1)				(3)**

自回归将给出 b 的值,即告诉我们控制所有其他因素的系数,最后一个滞后值对当前值的贡献如此之大。现在,在这一点上,探索这个 b 值是很有趣的,因为它背后隐藏着整个世界的特性。如果这个 b 值小于 1,那么它意味着这个过程是静止的!这意味着它会回复到一个恒定的平均值,不会向一个随机的方向爆炸。在第一个模型(1)中,该模型不是平稳的(它是非平稳的— 单位根),因为 b 是 1;如果这个人的身高等于去年的身高加 7,那么去年的身高应该乘以 b=1。如果我们有一个均值回归过程,b 会更小,例如 0.3,这表明如果在 1 个周期中我们看到一个高值,下一个周期我们应该预期不会看到这样高的值。一般来说,平稳过程更容易预测,因为它们始终有一个恒定的分布,并回复到一个恒定的均值。

作者图片

这是一个均值在 12 左右的平稳过程的例子。如果值为 13,请确保以下值之一将回到或低于 12。

移动平均模型

我们已经说过,建模这一过程的一种方法是使用自回归,其中我们发现在解释当前观察值时哪个滞后是重要的,但也有其他建模方法。第二种方式是移动平均线过程。这里,将每个时间段的预测值与实际值进行比较,定义“误差”值。现在,我们可以不在滞后观测值中(例如在自回归-AR 中)而是在滞后误差中回归当前观测值!这直观地告诉我们,如果一个时期发生“错误”/冲击,其影响将持续到未来多少个时期;这就相当于说当前值是由许多年前的误差解释的。同样,我们遵循相同的回归方法,在所有滞后误差中,我们找出哪些误差是显著的,并将其纳入模型。例如,在对石油价格建模时,如果出现冠状病毒导致的石油价格下跌(就像 2020 年 3 月发生的那样),价格需要多长时间才能恢复正常?这是 MA lags 的数量。现在我们知道了 AR 模型(自回归)和 MA 模型(移动平均),如果我们把它们结合起来,我们就得到 ARIMA 模型!在这种模型中,平稳时间序列的下一个值取决于某些滞后的值以及某些滞后的误差。

ARCH / GARCH

继续讨论时间序列建模的其他方法,还有 ARCH 和 GARCH 模型。这代表自回归条件异方差,是关于时间序列的波动性/方差/垂直分布的建模。因此,现在我们不是像在 AR 中那样将当前值回归到滞后值,而是将当前的方差回归到某个滞后之前的观测值的方差。我们的目标是检测波动性激增持续多长时间,或者它会以何种方式重演。这是有用的,因为如果我们发现当发动机的温度变化增加时,它会在未来更多的时期内增加更多,我们会比我们知道变化中的 1 个峰值通常伴随着收缩和向恒定平均值的强烈返回更担心。

**σ = b*σ(t-1)				(4)**

这些模型看起来是这样的:一个时期的标准偏差或方差基于前一时期的标准偏差或方差回归。

政权

接下来,我们必须理解时间序列的结构或基本模型会随着时间而变化。例如,在儿童身高的例子中,从 0 岁到 18 岁的演变不同于 18-50 岁。换句话说,在高度的时间序列中有两种不同的“状态”,应该用两种不同的模型来描述。第一个是每年增加 7 厘米,第二个是恒定的;每年的值与前一年相同。在其他时间序列中,我们可能会发现更多的制度,以及在未来重复出现的制度:

作者图片

在船速的时间序列中,我们清楚地看到两种不同的状态,一种是当船移动时平均 12 节,另一种是当船停在港口时平均 0 节。显然,有经验的建模者需要为每个状态(旅行/不旅行)准备 2 个不同的模型。更有经验的建模者可以有一个模型来预测每个状态/状态持续多长时间,这样他们对未来的预测就可以及时地在两种状态之间摆动。这类序列的著名模型是马尔可夫切换自回归,其中模型从一个自回归模型切换到另一个模型,遵循马尔可夫过程;即无记忆过程,其中转移概率矩阵定义了这样的概率,即给定当前状态/制度,下一个状态是旅行的概率是 P(旅行),非旅行的概率是 P(非旅行)。因此,这是一个 2x2 转换矩阵,捕捉状态如何根据我们所处的状态进行转换。问题是,有 0.9 的概率停留在同一个州/政权将永远是 0.9,无论你已经在该政权停留了多少时期。因此,在 1 个方案中停留的小时数的模型更有用。

结构模型/向量自回归

到目前为止,我们已经研究了仅使用时间序列本身获得时间序列的下一个值的预测的情况。当然,一个序列的值不仅取决于过去,也取决于不同的序列。例如,发动机的温度不仅可以通过前一时期的温度来预测,还可以通过当前时期的船速、上一时期的船速、上一时期的 RPM、当前时期或上一时期的风速来预测。这在多元自回归或向量自回归(VAR)等更高级的模型下,开辟了一个全新的可能相关性世界。在多元时间序列的情况下,模型看起来像这样:

**f(x,y) = b*x(t-1) + c*y(t-1)			(5)**

这表明一个变量在某一点上的回归是基于它自身的滞后和另一个时间序列的滞后值。在多变量时间序列的世界中,这两个变量都被认为是内生的,即变量 y 不像正常回归情况那样是外生的。这意味着我们需要 2 个方程来模拟它们,1 个方程用来显示 x 如何影响 y,1 个方程用来显示 y 如何影响 x。这些模型通常被称为结构模型或时间联立方程模型。

**X(t) = b*X(t-1) + c*Y(t-1)			(6)
Y(t) = b1*Y(t-1) + c1*X(t-1)			(7)**

这里有两个变量和两个方程。直觉是,如果我们要在一个多变量环境中模拟和预测一艘船上发动机的温度,我们可以用船的速度作为解释变量;我们将根据当前速度确定下一个温度,因为船只速度越快,RPM 越高,导致温度升高。另一方面, 2 变量可能以相反的方式相关,这需要在系统的第二方程中捕捉:温度越高,船长越有可能降低速度,以使发动机不会过热。

为了求解这个方程组,大致有两种方法:一种是基于领域专业知识来"识别系统并找到系数,另一种是理论方法,即向量自回归方法。在第一种方法中,传统的“ Cowles Commission ”方法用于识别联立方程/结构模型,为了识别 2 个变量(2 个方程)之间的 2 种不同关系,我们需要 2 个外生变量的帮助。如果等式(6)中的 X 是容器的温度,Y 是容器的速度,我们可以将系统增强为如下所示:

**X(t) = b*X(t-1) + c*Y(t-1) + d*F(t-1)		(8)
Y(t) = b1*Y(t-1) + c1*X(t-1) + d1*G(t-1)	(9)**

我们在这里添加的是每个方程中的一个外生因子,它将帮助我们求解这些方程,并找到系数 b、b1、c、c1、d 和 d1(我们总共在搜索 6 个未知数)。

为了更好地理解这里发生的事情,让我们引入一个供应和需求概念,在这里我们对船舶发动机的需求和船舶发动机的供应进行建模。供给曲线向上倾斜,2 个轴是温度和速度。因此,运动的提供者(发动机)随着速度的增加要求更多的温度——向上倾斜的供给曲线。另一方面,随着温度的升高,运动的消费者(船长)要求更低的速度——向下倾斜的需求曲线。等式 8 是供给曲线,其中一个周期中速度(Y)的增加导致下一个周期中温度(X)的增加,等式 9 是需求曲线,其中当前周期中温度的增加导致速度下降(由于机长避免过热)。

作者图片

假设我们有很多速度和温度的数据,并且我们从领域专家那里了解到这两个变量之间的两种对立关系,那么我们如何将一种关系产生的数据点与另一种关系产生的数据点分开呢?换句话说,我们如何找到需求和供给曲线的形状,以及如何找到等式 8 和 9 中的系数?利用上述的外生因素:为了找到供给曲线,我们在需求方程(9)上引入因子 G,其向上移动需求曲线,暴露供给曲线的斜率,并在供给方程上引入因子 F,其向外移动供给曲线,暴露需求曲线的斜率(即需求方程的系数)。F 的一个例子可能是突然的零风速条件,这将供应曲线向外移动,这是有意义的,因为现在对于相同的发动机温度/发动机功率,你可以获得比恶劣天气条件下更高的速度。G 的一个例子是,船长采取了不那么保守的态度,即使在高温下也允许更高的速度。

在使用向量自回归求解结构模型的第二种方法中,我们不需要使用任何外生变量或限制来识别系统,我们只需将所有变量接受为内生,对它们的滞后进行回归,并继续使用脉冲响应函数、格兰杰因果关系和预测来获得感兴趣变量的准确预测。如果在基准数据上运行,这种向量自回归可以给我们在正常条件下每个变量及其滞后对其他时间序列贡献多少的系数,然后如果在“异常”时期运行,它可以突出系数已经改变,因此表明变量已经改变,不再影响因变量。这是检测系列是否出现异常的可靠方法。

向量误差修正模型

作为 VAR 模型的扩展,人们可以利用协整的概念,建立误差修正或向量误差修正模型(VECM)。当两个或两个以上的非平稳变量在相互回归时,有一个平稳的剩余时间序列时,就会发生协整。趋势稳定的两个时间序列,这意味着它们有一个趋势,如果它们之间的“差异”是稳定的,即具有恒定的平均值,那么这两个序列是协整的。这意味着从长远来看,这两个系列是相关的;协整关系反映了长期关系。VECM 将短期偏差与协整关系结合在一个模型中。因此,人们可以想象,我们可以在 VECM 的协整部分获得变量的长期(基准)关系,在模型的其余部分获得短期偏差(异常)。这可能是使用 VECM 的一种新方法。

主成分分析

此外,我们可以使用主成分分析或动态因子模型,找出哪些时间序列是同步的,可以只用一个潜在变量来表示。因子加载,即选择包含在每个潜在因子下的变量,将会建议哪些变量在正常条件下是“相关的”。

相关

否则,更简单的方法是找出时间序列之间的相关性(忽略时间作为解释维度)。

如何思考概率

原文:https://towardsdatascience.com/how-to-think-about-probability-b828098e1a6a?source=collection_archive---------23-----------------------

数据科学导论

数据科学的离散概率

克利姆·穆萨利莫夫在 Unsplash 上的照片

如果我必须用一句话来解释机器学习模型是如何工作的,我的答案会是“通过计算(条件)概率。”概率论是最复杂的数据科学任务的基础。这篇文章简单易懂地介绍了概率论。

在这里,我们将涵盖:

  • 离散概率
  • 独立事件和条件事件
  • 概率的简单数学符号

离散概率

抛硬币,你将只有两种可能的结果(正面或反面)。从一副标准牌中抽出一张牌,你会有五十二种可能结果中的一种。当结果是固定数量的可能结果之一时,我们称之为“分类结果。离散概率处理我们的结果是明确的事件。

在本文中,我们将使用从标准的 52 副牌中抽取的例子。但是你可以把我们在这里学到的概念应用到任何离散概率的问题上。

通常,我们使用概率的目的是为了进行预测。我们试图找出哪种可能的结果是最有可能发生的。在计算这些概率时,我们需要考虑我们试图预测的事件是独立的还是有条件的。

独立性ˌ自立性

独立事件

假设我让你从一副标准洗牌牌中抽一张牌。你的牌是红色的概率正好是 50%,因为你是从一副有 26 张红色和 26 张黑色的牌中随机抽取的。

现在,我们把你的牌放回牌堆,重新洗牌。你下一次抽牌也是红牌的概率有多大?50%,因为我们有与第一次抽签相同的初始条件——随机洗牌中的 26 张红牌和 26 张黑牌。

因为第一次抽奖的结果对任何后续抽奖的概率没有影响,所以我们称这些事件为独立事件。

条件事件

现在,假设我们再次开始同样的实验。但这一次,在你抽完第一张牌后,我们不会把它放回牌堆里。如果第一次抽牌是一张红牌,那么第二张牌也是红牌的概率是多少?

第一次抽牌后,牌组不再均衡。如果你抽了一张红卡,那副牌现在还剩下 25 张红卡和 26 张黑卡。这改变了下一次抽签的概率。因为剩下的红色牌比黑色牌少,所以再抽一张红色牌的可能性降低了。抽到红牌的概率是:

  • 第一次抽牌时的 26/52 (0.50)
  • 25/51 (0.49)第二次抽签

这向我们展示了一个事件的结果如何影响下一个事件的概率。如果我们不把牌放回牌堆,每一次抽牌都会影响下一次的概率。我们称这些为条件概率。

计算概率(数学符号)

乘法法则

让我们继续我们的纸牌游戏的例子。我们要计算抽任何花色的红脸牌(国王、王后或杰克)的概率。我们可以认为这是两个事件。抽红牌和抽面牌:

  1. 事件 A =抽红牌
  2. 事件 B =抽一张脸牌

我们知道一副牌中有 26/52 张红色牌和 12/52 张正面牌。因此,我们可以计算这些事件的概率如下:

  1. 事件 A = 26/52 = 0.5
  2. 事件 B = 12/52 = 0.23

我们可以通过考虑每个事件发生的“概率空间”来形象化这个问题——我们用事件发生的概率来表示每个圆的大小:

可视化事件 A 和事件 b 的概率。

要得到红脸牌,我们感兴趣的区域是抽到了红牌和抽到了脸牌的概率的交集(重叠)。

可视化事件 A B 同时发生的概率(两个概率空间的交集)。图片作者。

为了得到这个空间,我们用拿到红卡的概率乘以拿到脸卡的概率:

Pr(A 和 B) = Pr(A) * Pr(B)。图片作者。

所以我们可以把抽到红脸牌的概率计算为:

  • Pr(A 和 B) = Pr(A) * Pr(B)
  • Pr(A 和 B) = 0.5 * 0.23
  • Pr(A 和 B) = 0.115

在这些简单的情况下,我们可以直接验证我们的结果。我们知道一副 52 张牌中只有 6 张红脸牌,这样我们就有 6/52 的机会(或 0.115)。

加法法则

让我们继续我们的纸牌游戏的例子。这一次,我们要计算任意花色抽到红牌 a 面牌(国王、王后或杰克)的概率。我们可以采用同样的方法,把这看作两个事件:

  1. 事件 A =抽红牌
  2. 事件 B =抽一张脸牌

事件和每个事件的概率与我们之前的示例相同:

  1. 事件 A = 26/52 = 0.5
  2. 事件 B = 12/52 = 0.23

这个图像帮助我们想象抽一张红卡、一张脸卡或一张红脸卡的概率。

可视化事件 A B 同时发生的概率(两个概率空间的交集)。图片作者。

然而,当试图计算抽红牌或抽脸牌的概率时,这些事件中的任何三个都会满足我们的标准。我们要寻找的是重叠概率的总面积。

想象事件 A B 发生的概率。作者图片。

因此,总结加法法则,我们可以说

Pr(A 或 B) = Pr(A) + Pr(B) - Pr(A 和 B)。图片作者。

换个角度看概率空间图,让我们知道为什么需要减去 A 和 b 的概率。

为什么我们在计算作者的 B. 图像的概率时要减去 A B 的概率。

如果我们将事件 A 和事件 B 的概率分别相加,我们将两次考虑两个空间之间的重叠,并过度报告 A 或 B 的概率。

  • Pr(A 或 B) = Pr(A) + Pr(B) - Pr(A 和 B)
  • Pr(A 或 B)= 0.5+0.23–0.115
  • Pr(A 或 B) = 0.615

我们可以直接验证我们的结果。我们知道,一副牌中有 32 张牌满足或事件的概率(26 张红牌+ 6 张黑脸牌)。这给了我们 32/52(或 0.615)。

条件事件

你第一次听牌时拿到红脸牌,第二次又拿到 a 的概率有多大?我们可以将此分解为两个独立的事件:

  1. 事件 A =在第一次抽牌时抽一张红脸牌
  2. 事件 B =在第二次抽牌时抽出一张 a

在这个例子中,我们引入了条件性。事件 B 发生在事件 A 之后,事件 A 的结果影响事件 B 的概率。

我们可以认为这是试图计算事件 A 和 B 发生的概率。对于类似的情况,我们再次使用乘法规则,并稍微调整一下条件性因素:

Pr(A 和 B) = Pr(A) * Pr(B|A) —竖线表示“鉴于”。它用来表示条件性。图片作者。

如果我们的第一次听牌是红脸牌,那么我们的牌组中还剩下 51 张牌。其中 4 张会是 a。因此,在第二次抽牌时,抽到 a 的概率是 4/51。我们计算任一事件的概率如下:

  • Pr(A) = 6/52 = 0.115
  • Pr(B | A) = 4/51 = 0.078

所以,抽一张红脸牌后跟一张 a 的概率是:

  • Pr(A 和 B) = Pr(A) * Pr(B|A)
  • Pr(A 和 B) = 0.115 * 0.078
  • Pr(A 和 B) = 0.009

我们可以将此规则扩展到多个条件事件:

多重条件事件的乘法法则。图片作者。

在现实世界中,我们的算法基于概率的平衡做出预测。我们现在可以看到这是如何根据我们的预测任务而变化的。我们是否在考虑:

  • 单个事件还是多个事件?
  • 特定的事件顺序?
  • 从属事件还是独立事件?

虽然离散概率构成了我们在数据科学统计学中所学内容的基础,但它很少直接应用于现实世界的问题。我们的下一篇文章将考虑一种更实用的方法来思考概率。

如何像数据科学家一样思考

原文:https://towardsdatascience.com/how-to-think-like-a-data-scientist-98ba53c260e2?source=collection_archive---------17-----------------------

距离数据科学更近 6 步

Unsplash 上拍摄的 ThisisEngineering RAEng

数据科学家是…

在我们考虑数据科学家的罕见情况下(哈,是的,没错,那很可能永远不会),我们可能会开始考虑某个真正擅长统计、概率、编程和神经网络的人

约翰·莫塞斯·鲍恩在 Unsplash 上的照片

虽然知识库有助于工作,但我认为数据科学家确实是解决问题的专家。我们可以查看数据,我们可以将领域知识与真实数据结合起来,做出战略性的智能决策。

我还认为,虽然我认识的每个数据科学家都有不同的过程,但基本的方法可以系统化为一系列步骤,就像任何其他算法一样。肯定还有其他方法,比如路孚特实验室的数据科学家和数据质量解决方案。然而,这些观点强调将领域知识应用于问题,而不是为初学者解释行动过程。

Jens LelieUnsplash 上拍摄的照片

在这篇文章中,我想与你分享我认为更实用的思维过程。换句话说,我认为成为一名数据科学家的想法不仅仅是一种心态,更是一种日常实践。

通过用这种方法解决问题,我已经帮助几个客户解决了他们的业务问题,并作为一名计算生物学家和数据科学家为癌症代谢做出了一些贡献。而现在,我希望和大家分享一下我的大致过程。希望对你有帮助。

如何像数据科学家一样思考

作为一名数据科学家,我处理问题的方法有 6 个一般的迭代步骤:

  1. 定义问题和假设,我正在做关于这个问题
  2. 概述我将如何解决问题以及我衡量成功的标准是什么
  3. 收集和组织数据
  4. 可视化和分析数据
  5. 建模
  6. 数据和模型解释

1.定义问题和我对问题的假设

乔治·帕甘三世在 Unsplash 上的照片

“你成为世界级的方法是问好问题”——蒂姆·费里斯

数据科学家的主要目标是能够分析数据、衡量结果、设计实验并做出推动个人或组织前进的决策。

然而,在我们做所有这些之前,我认为最重要的一步是定义问题,我认为与问题相关的假设是正确的。

虽然这看起来是如此简单的一步,但我们通常不会太深入地思考我们试图解决的问题。更糟糕的是,我们很少考虑我们强加给模型和数据的假设和偏见。

这两个错误会让你和你的团队付出巨大的代价。如果我们问了错误的问题或做了错误的假设,我们就衡量了错误的变量。这既浪费了时间和金钱,也带来了来自竞争对手的风险,这些竞争对手对问题的想法可能与你不同,甚至比你更好。

我建议在这一阶段花很多时间,概述我们试图解决的问题、我们目前拥有的证据以及我们明确做出的假设。与雷伊·达里奥的彻底透明的原则一样,我们的目标是尽可能理性地看待问题,消除未知的未知和偏见。

一旦我们清楚地看到了问题,那么,也只有到那时,我们才应该进入下一步。

2.概述我将如何解决问题以及我衡量成功的标准是什么

斯蒂芬·道森在 Unsplash 上拍摄的照片

一旦我们知道了问题,我们需要选择解决问题的工具和评估成功的变量。在这一点上,我们可能对如何执行我们的总体规划没有一个高分辨率的视图。这完全没问题。

但是我们需要概述一个总的行动方案。我们应该考虑的一些事情是:

  • 我们认为这是一个有可测量的响应变量的监督学习问题,还是我们需要更多地将它视为一个无监督或半监督学习问题?
  • 我们的模型需要多少数据才能工作?
  • 获取这些数据要花多少钱?
  • 最后,对于我的建模方法来说,成功是什么样的?我们会最大化准确性吗?还是尽量让模型尽可能有可解释性?

虽然概述我们的问题看起来像是从解决问题的步骤中吸取创造力,但它给我们的方法增加了约束,让我们更深入地思考问题。更重要的是,它迫使我们通过一系列可行的步骤来解决问题,并制定策略来解决手头的问题。

3.收集和组织数据

希尔·格雷森在 Unsplash 上拍摄的照片

不幸的是,我们感兴趣的大多数问题在数据库中没有现成的数据。是时候开始收集和生成数据了,或者希望让别人为你收集和生成数据。想想亚马逊的机械土耳其人服务(这个宣传片没有报酬,但叫我亚马逊)。

作为一名数据科学家,最耗时的部分是收集和生成数据。如果你试图解决机器学习问题,将非结构化数据转换成结构化数据集是一个额外的挑战。

4.可视化和分析数据

M. B. M.Unsplash 上拍摄的照片

一旦有了数据集,就该检查数据并真正了解它了。在这里,我们可能会想到探索性数据分析、数据总结和无监督学习。最后,我们开始思考我们在步骤 2 中制定的策略,并开始生成假设进行测试。否则,在极少数情况下,您的数据显示出清晰的模式,并且您有一个简单的问题要解决,您可以直接进入建模。

5.建模

亨特·哈里特在 Unsplash 上拍摄的照片

当然,这是我们都希望能做得更多的数据科学的性感部分。当选择模型子集进行训练时,我们应该考虑我们的目标和我们试图测量的关键性能度量。

在大多数情况下,我们希望我们的模型尽可能准确。但是我们可能也希望模型是可解释的。这就排除了深度学习和其他黑盒算法。

也许我们想知道哪些特性是重要的。那么套索或随机森林是我们最有可能采用的算法。

这一节的要点是没有一种放之四海而皆准的模式可以解决我们所有的问题。我们在选择模型的标准上应该具有战略性和选择性。通过确切地知道我们对从模型中测量什么感兴趣,我们可以更快地排除潜在的方法,并决定更快地测试模型。

6.模型解释和采取行动

弗洛里安·施梅兹Unsplash 上拍摄的照片

你可能已经训练了你的模型几个小时,几天,或者几周,你终于得到了结果。现在是时候决定如何利用这些知识了!

你有没有从你的数据中发现一些很酷很有见地的东西?你从你的模型中发现了什么意想不到的结果?你需要调整你所做的一些假设吗?

这些问题将帮助您向前推进下一步,通过足够的迭代,它将为您和您的团队带来更好的决策。

摘要

成为一名数据科学家不仅仅是要知道很多关于机器学习、Python 和数据库的知识。它是能够更快更好地解决问题,使用数据来指导您的决策框架。希望这 6 个步骤能帮助你的数据科学项目!

我们谈谈吧!

如果您想分享您是如何解决一个具有挑战性的数据科学问题的,或者有改进我的方法的想法,请在下面的评论中留下您的回复。

此外,请随时通过 LinkedIn 联系我——我很乐意与你联系并讨论所有书呆子的事情!

如何看待纠缠量子比特

原文:https://towardsdatascience.com/how-to-think-of-entangled-qubits-506aa1ac268c?source=collection_archive---------23-----------------------

抱歉,会有点疼。

量子机器学习要不要入门?看看 动手量子机器学习用 Python

在之前的帖子中,我们了解了量子计算的两种不同观点。首先,我们将量子比特视为概率系统。第二,我们应用线性代数来可视化布洛赫球中的量子位状态。

不幸的是,当我们在最感兴趣的时候看量子位时,这两种观点都是不充分的。那是他们纠缠在一起的时候。

我们最终得到了不亚于一场大爆炸的结果。

作者图片

那么,我们为什么不再问问欧比旺的意见呢?

作者图片

单个量子位的图形表示是没有用的,因为两个纠缠的量子位共享一个叠加态。它们不再相互独立。他们的价值观相互关联。一旦你测量了一个量子位,另一个量子位的状态就会立即改变。

但是每个球体只覆盖一个量子位。

当我们处理纠缠量子比特时,我们需要看整个量子系统。单个量子位是 0 和 1 的组合。所以当你测量它的时候,你可以在这两种状态中找到它。

如果你有一个由两个量子位组成的量子系统,你可以发现它处于四种状态之一:00、01、10 或 11。如果你有三个量子比特,有八个状态,如果你有𝑛量子比特,有 2^𝑛状态。

是时候看看你在前两篇文章中可能忽略的一件事了。这是数学。

作者图片

向量是量子位状态的数学表示。对于量子位,这些是

量子叠加是这两种基态的组合。

𝛼和𝛽的值是我们已经知道的概率幅度。它们的平方表示测量量子位为 0 (𝛼)或 1 (𝛽)的概率。𝛼越大,量子位被测量为 0 的概率就越大。𝛽越大,量子位被测量为 1 的概率就越大。

由于概率的总和必须是 1,我们可以说它们的总和必须是1

现在,假设我们有两个量子位。让我们称他们为|𝑎⟩和|𝑏⟩.两个量子位中的每一个都有自己的概率振幅:

当我们同时观察这两个量子位时,有四种不同的基态组合。这些组合中的每一种都有其概率幅度。这些是两个相应状态的概率振幅的乘积。

这四种状态各自形成一个量子系统。因此,我们可以用一个方程来表示它们。虽然我们可以自由地为这个态选择一个任意的名字,但是我们使用|𝑎𝑏⟩,因为这个态是|𝑎⟩和|𝑏⟩.的集体量子态

量子位状态的这种表示类似于单量子位状态|𝜓⟩.的表示唯一的区别是双量子位系统有更多的维度。它有四个基本状态向量,而不是两个。

所有管理单一量子位元的规则,都适用于由两个量子位元组成的系统。它的工作原理相似。因此,所有概率的总和(记住状态的概率是振幅的平方)必须是 1:

不出所料,用两个量子位的系统工作与用一个量子位的系统工作是相似的。唯一的区别是,向量的维数更大。

一个向量代表一个量子位状态,一个矩阵代表一个量子位变换。

在我们的例子中,我们从为每个向量添加 CNOT 矩阵和另一个矩阵开始,比如𝐻|𝑎⟩⊗𝑋|𝑏⟩.此外,张量积是结合的。这意味着我们可以将术语重组如下:

手工处理这种大小的矩阵很麻烦。幸运的是,我们有计算机来计算矩阵和张量积。

那么,让我们来计算由𝐶𝑁𝑂𝑇(𝐻⊗𝑋).表示的矩阵

我们可以看到一个两量子位变换门的矩阵有 4 乘 4 维。它对应于两个量子位的状态向量所具有的四维空间。

除了更多的维度,这里没有什么特别的。我们可以将这个矩阵预先放置在两个量子位的系统中。

当我们将这个矩阵乘以初始状态向量时

然后,我们有效地选择矩阵的第一列,并将其作为新的状态向量。

数学揭示了四种状态的振幅。让我们更仔细地看看结果。

我们通过方程引入了两个量子比特的状态

从这个等式中,我们可以推导出外部值的乘积等于内部值的乘积。

每一边都是每个量子位元振幅值的产物:𝑎0a0、𝑎1a1、𝑏0b0 和𝑏1

但是当我们检查 CNOT 门的结果时,我们得到如下结果:

显然,这是一个矛盾。这个矛盾证明了我们不能再用两个独立的量子比特来描述这个量子态了。它已经成为一种共享状态。

结论

数学并不是量子计算的唯一视角。然而,这是最精确的一个。而且,当布洛赫球不确定时,数学提供了一个清晰的解释。

不幸的是,数学是量子计算最不直观的视角。然而,即使数学有时看起来像象形文字,但它不是。

作者图片

数学是许多教科书、博客文章中教授的一门语言,是的,学校也教授数学。

尽管如此,我仍然相信我们不应该仅仅用数学来解释量子计算。我们应该利用我们所有的不同视角。我们应该尽可能让读者容易理解。但是,我们不应该对读者隐藏所有的数学知识。

量子机器学习要不要入门?看看 动手量子机器学习用 Python

在这里免费获得前三章。

如何用 Python 中迭代器的组合追踪危险的小行星

原文:https://towardsdatascience.com/how-to-track-hazardous-asteroids-with-composition-of-iterators-in-python-3945cf8e8f84?source=collection_archive---------31-----------------------

去锈蟒

应用函数组合创建迭代器管道

SpaceXUnsplash 上拍摄的照片

功能性面向对象的编程经常被认为是相反的。将 Python 的迭代器对象组合成一个管道就是它们完美互补的例子。我将使用 NASA 的一个开放 API 来展示这种模式。

显示优点的东西

API 小行星——NeoWs 是一个 RESTful 的近地小行星信息网络服务。它允许搜索离地球最近的小行星。

你可以在 NASA API 门户上找到。

它包含一些奇怪的数据——最大物体直径、最近接近距离、接近日期等等。在这些数据中,每个物体都有一个字段显示该物体对地球有潜在的危险。

让我们考虑这样一种情况,当我们想要获取小行星数据,然后按日期将其写入文件,并找到一个潜在危险的小行星。

通常,我从编写代码开始,我希望如何与不存在的高级类或函数进行交互。

这段代码混合了两种范式功能性面向对象编程。

函数式编程擅长数据处理任务,例如对数据进行顺序操作和改变。对象允许将相关的行为耦合到一个实体中,并存储一个状态。结合两种范例使代码更具声明性。

配置

我们将从隔离每个步骤开始,以分离对象。我们将创建存储每个步骤配置的基本类,稍后将添加所需的实现。

我们需要一个从 URL 加载数据的步骤。

接下来,我们添加一个步骤,它将按日期将加载的小行星数据写入文件。

最后一步将负责寻找危险的小行星。我们将存储一个负责该属性的字段。

功能组成

函数组合是函数式编程的主要模式之一。

直观地说,组合函数是一个链接过程,函数*f*的输出馈入函数*g*的输入。

在 Python 中,我们可以如下实现它。

def compose2(f, g):
    return lambda *args: g(f(*args))

注意,我们希望在从左到右读取函数时执行它们,我们使用了g(f(x))

例如,考虑两个函数。

def square(x):
    return x*xdef format(x):
    return f"x*x = {x}"

我们可以应用compose2()函数制作一个新的。

>>> square_and_format = compose2(square, format)
>>> print(square_and_format(2))
x*x = 4

减少

另一种常用的功能模式是折叠减少功能。reduce()方法将数组累加成一个值。reduce()方法为数组的每个值执行一个提供的函数(从左到右)。

顺便说一句,吉多·范·罗苏姆不喜欢它。

所以现在减少()。这实际上是我最讨厌的一个,因为除了几个涉及+或*的例子之外,几乎每次我看到带有重要函数参数的 reduce()调用时,我都需要拿起笔和纸,在我理解 reduce()应该做什么之前,画出实际输入到该函数中的内容。因此,在我看来,reduce()的适用性仅限于关联操作符,在所有其他情况下,最好显式写出累加循环。
——吉多·范·罗苏姆命运的减少(Python 3000 中的

幸运的是,它被藏在了functools模块里。所以我们可以将我们的compose2函数应用到函数列表中。

from functools import reducedef compose(*functions):
    return reduce(compose2, functions)

现在,我们能够为函数列表应用组合

请求即付的

为了能够对我们的对象应用函数组合和归约,我们需要使我们的类可调用。

在 Python 中,如果我们想让一个对象可调用,我们需要实现神奇的方法__call__

对于Load类,这将是请求数据的简单返回。

class Load:
    ... def __call__(self):
        return requests.get(self.url)

对于Write对象来说,就有点棘手了。我们将迭代器作为参数,保存它,并返回对象本身。稍后我们将实现迭代接口,它将允许我们组合这样的对象。

class Write:
    ... def __call__(self, iterator):
        self.iterator = iterator
        return self

对于Find,它看起来与Write一样。

class Find:
    ... def __call__(self, iterator):
        self.iterator = iterator
        return self

迭代程序

最后,我们必须为对象实现一个迭代器接口。从技术上讲,一个 Python 对象必须实现__iter__方法来提供迭代支持。

在我们的例子中,迭代也将保持数据处理的主要逻辑。

我们不需要为Load类实现迭代。它以列表的形式返回数据,默认情况下可以迭代。

对于类Write,处理和保存数据到文件的逻辑将在这个方法中实现。

对于Find类,在迭代过程中,我们将过滤满足我们条件的对象。

决赛成绩

这就是了。我们实现了几个类,这些类可以通过配置启动,并组成一个管道,如下所示。

pipe = pipeline.compose(
    pipeline.Load(
        url=API_URL, api_key="DEMO_KEY", start_date="2021-05-09"
    ),
    pipeline.Write(to_path="/tmp"),
    pipeline.Find(field="is_potentially_hazardous_asteroid"),
)for each in pipe():
    print(each)

完整的示例源代码请看我的 GitHub repo。

https://github.com/pavel-fokin/iterators-composition

看起来不错!你怎么想呢?

与我分享你对LinkedInTwitter

结论

这种模式有几个优点,我们举几个例子。

优点

  • 关注点分离。每一步都有其独立的作用。
  • 算法的更多声明性符号。
  • 每一步都可以单独测试。

但是和其他模式一样,它不应该被过度使用。如果逻辑变得太复杂或者步骤太多,最好重新考虑这个方法。

更多阅读

如果你喜欢这篇文章,你可以对以下内容感兴趣。

不用 OOP 用 Python 解释依赖倒置原理

https://levelup.gitconnected.com/tenet-of-inversion-with-python-9759ef73dbcf

仔细观察 Python 中多态性的类型。

https://levelup.gitconnected.com/hidden-power-of-polymorphism-in-python-c9e2539c1633

感谢阅读!与我分享你对LinkedInTwitter的想法。如果你喜欢这个故事,请关注me获取更多关于编程的精彩文章。

如何跟踪 Postgres 数据库中所有查询的统计数据,以防止缓慢的查询或瓶颈

原文:https://towardsdatascience.com/how-to-track-statistics-on-all-queries-in-your-postgres-database-to-prevent-slow-queries-or-730d3f94076c?source=collection_archive---------8-----------------------

用这个扩展提供的重要统计数据来优化数据库性能

这种延伸就像一件救生背心;你永远不会希望你需要它,但它在困难的情况下会非常有用(图片由 Unsplash 上的卡斯滕·温内格特提供)

你有没有想过为什么你的应用程序的某些部分突然变得非常慢?可以是你的数据库吗?你会怎么发现?如果有一个扩展来跟踪它执行的所有查询的统计数据,以便您可以分析数据库性能并清除瓶颈,这不是很好吗?

在本文中,我们将看到一个名为 pg_stat_statements 的 Postgres 扩展。它对数据库执行的所有查询进行统计,从而提供关于数据库性能的重要信息。有了它,您可以轻松地跟踪数据库的性能,检测缓慢的查询,消除瓶颈并防止问题发生。

我们将首先进行非常简单的安装。然后我们演示如何使用它。我们来编码吧!

这个扩展是做什么的?

Pg_stat_statements 是 Postgres 的扩展,它跟踪服务器执行的所有查询的执行统计信息。这个扩展跟踪静态数据,比如

  • 该语句被调用的次数
  • 语句的最快和最慢执行
  • 语句执行时间的平均值和标准差
  • 已检索或受影响的总行数
  • 关于块的信息(命中、读取、写入、变脏等。)

这对于分析查询的质量非常有用。使用统计数据,很容易调试数据库中的问题,跟踪缓慢的查询和表,并防止与数据库相关的问题。

这一扩展将帮助我们保持数据在数据库中顺畅流动(图片由丹尼斯·内沃扎伊Unsplash 上拍摄)

装置

安装 pg_stat_statements 非常简单,只需要三个步骤。在这一部分中,我们将介绍每个步骤,然后向您展示如何在本地安装的 Postgres 实例和 Postgres 的 Dockerized 版本中执行这些步骤。如果你对 Docker 不熟悉,可以看看这篇文章,这篇文章由 Docker【和【撰写。

步骤如下:

  1. postgresql.conf添加几行
  2. 在数据库中创建扩展
  3. 重启 Postgres

1.修改 postgresql.conf

这个文件存储了 Postgres 的一些配置。我们需要修改它,以便告诉 Postgres 在我们的语句中存储一些统计数据是可以的。

本地安装 首先我们来处理postgresql.conf文件。找到文件(通常位于 Postgres 安装位置的data文件夹中(windows 示例:C:\Program Files\PostgreSQL\14\data)并打开它。找到写着# — Shared Library Preloading的行,并添加以下三行:

shared_preload_libraries = 'pg_stat_statements'
pg_stat_statements.max = 10000
pg_stat_statements.track = all

我们将在docker-compose.yml文件中定义一些额外的命令,以便将额外的行添加到postgres.conf:

在第 13 行中,我们将 pg _ stat _ 语句包含到 shared_preload_libraries 中。搞定了。

步骤 2:创建扩展

这是一个非常简单的步骤。我们将在 PgAdmin(或另一个数据库 GUI 工具)中执行下面的语句

CREATE EXTENSION pg_stat_statements;

第三步:重启 Postgres

也没那么难;在 windows 中,按下control-r并运行services.msc。找到 Postgres,右键,重启。使用 Docker 时,只需重启容器。

安装完成!让我们为一些问题计时(图片由 Veri IvanovaUnsplash 上提供)

演示

现在所有无聊的事情都已经过去了,让我们看看这个扩展能给我们带来的巨大优势吧!我们将假装是一个图书馆,创建一个出租书籍的数据库。

设置-创建表

我们将创建三个表:

我们简单的数据库结构(图片由作者提供)

在执行了创建这些表的语句之后,当我们调用SELECT [some columns] FROM pg_stat_statements时,我们已经看到了一些统计数据:

我们的首次统计(图片由作者提供)

如您所见,这些统计数据主要涉及创建我们的表的语句。

重置我们的统计数据

下一步是插入一些数据,以便我们可以运行一些查询并检查结果。因为我们对以前操作的统计数据不感兴趣,所以我们调用SELECT pg_stat_statements_reset();来清除所有当前的统计数据。

插入一些数据并运行一些查询

下一步;插入一些数据!

并运行一些查询:

如您所见,我们执行了一些不同的查询。

分析我们的查询

现在我们可以调用SELECT * FROM pg_stat_statements并分析执行统计数据。我选择了一些列,并根据平均执行时间对行进行了排序。这是返回的内容:

来自我们新扩展的一批新的执行统计数据(图片由作者提供)

这些结果不言自明,但让我们快速浏览一遍。第一条记录包含了我们执行两个连接的最后一个最大的查询,难怪它是最慢的!
请注意,我们在lib.books中选择了三个不同的标题。这由记录 5 表示;显示我们对过滤标题的books表进行了三次调用。

使用统计数据,我们可以调整我们的数据库,以优化性能!(图片由妮娜·梅尔卡多Unsplash 上拍摄)

结论

通过这篇短文,我们完成了一个非常有用的扩展。我希望已经展示了简单的安装以及它可以为您提供的监视和改进数据库的价值。如果你有建议/澄清,请评论,以便我可以改进这篇文章。同时,看看我的其他关于各种编程相关主题的文章:

编码快乐!

—迈克

页(page 的缩写)学生:比如我正在做的事情?跟我来!

如何用 TQDM 跟踪 Python 中并行任务的进度

原文:https://towardsdatascience.com/how-to-track-the-progress-of-parallel-tasks-in-python-with-tqdm-6d93339f03fe?source=collection_archive---------4-----------------------

将 TQDM 与多处理相结合

马克-奥利维耶·乔多因在 Unsplash 拍摄的照片

Python 是一种很棒的编程语言。这是一把用于多个领域的瑞士刀:分析和可视化数据,训练机器学习模型,构建 API,抓取网站,DevOps,MLOps,显然还有更多事情。

这种语言的多功能性,除了其他的东西之外,也是有代价的:与其他编程语言相比,Python 是缓慢的

那么,我应该换一种语言吗?

不急。有很多方法可以提高 Python 的速度。

在本帖中,我们将把多重处理视为其中一种方式。我们将看到如何在用例中利用它,以及如何使用稍加修改的 TQDM 版本来跟踪并行任务的进度。

你知道, TQDM ,这个很棒的进度条,你可能以前用过,用来跟踪你的 for 循环的进度。

今天,我们将看到它是如何被用来跟踪并行任务的。

好的,我们来看看。🔍

什么是多重处理?

多重处理允许您创建可以并发运行的程序,并利用工作站的多个内核。

当进程启动时,每个进程都有自己的内存。这使得在使用多重处理时很难共享多个对象。

作者图片

当您有 CPU 密集型操作,如数据处理(标记化、图像增强、过滤等)时,多处理非常有用。).

作为一名数据科学家,您可以使用多处理来加速您的工作负载。

p_tqdm:并行任务的进度条

正如你可能猜到的,“p”代表平行。

**p_tqdm**是对 pathos.multiprocessingtqdm 的包装。

与 Python 的默认多处理库不同,pathos 提供了一个更加灵活的并行映射,可以应用几乎任何类型的函数——包括 lambda 函数、嵌套函数和类方法——并且可以轻松处理带有多个参数的函数。tqdm 应用于 pathos 的平行图之上,并显示一个进度条,包括预计完成时间。— Github

这里没有什么要补充的,让我们看看这个包装器的运行情况。

假设您有一大串数字要处理。

为了简单起见,我们假设这种“繁重的处理”将包括等待 5 毫秒并向一个数字添加一个常数(当然,您可以在这里想象任何更复杂的方式)。

让我们依次运行这个函数,

根据 TQDM,这些任务需要 8 分 42 秒(~ 10000x0.05s 秒)

作者 GIF

现在,如果我们尝试同时运行这些任务,

我们看到完成它们所需的时间是大约 42 秒,大约等于 500 / 12,12 是我的笔记本电脑的内核数。

GIF 格式

👉如果您想将内核数量设置为较低的值,您可以添加num_cpus kwarg。这就像打字一样简单:

👉除了使用 p_map,您还可以使用:

  • p_imap:做同样的事情,但不是返回一个列表,而是返回一个迭代器
  • `p_umap``:返回一个无序列表(处理速度不是特别快)
  • p_uimap:返回无序元素的迭代器

资源

感谢阅读🙏

谢谢你坚持到最后。我希望您发现在您的项目中使用p_tqdm来并行化工作负载并轻松直观地跟踪它们的进度是有用的。

我们演示的例子非常简单,但是您可以想象在许多场景中p_tqdm会派上用场。作为一名数据科学家,每当我抓取数据或处理数据时,我的脚本通常会花时间运行。能够在并行化这些操作的同时跟踪它们是非常有趣的。

下面是我如何使用p_tqdm来加速刮擦:

作者提供的图片——用于抓取的样板代码

如果你想玩这个库,不要犹豫在 Github 上查看它的代码。

我就这些了。下次见!👋

新到中?你可以订阅每月 5 美元,并解锁无限的文章——点击这里。

照片由卡斯滕·怀恩吉尔特Unsplash 上拍摄

如何使用专家知识训练贝叶斯网络?

原文:https://towardsdatascience.com/how-to-train-a-bayesian-network-bn-using-expert-knowledge-583135d872d7?source=collection_archive---------17-----------------------

马修·费尼在 Unsplash 上的照片

实践教程

基于专家知识的机器学习

贝叶斯网络是一个强大的 IA 工具,可以用于一些需要混合数据和专家知识的问题。与机器学习(仅基于数据)不同,BN 带来了向人类询问因果定律(单向)的可能性,因果定律存在于我们想要解决的问题的上下文中。

bn 是表示变量之间概率关系的直接非循环图,其中节点表示变量,弧线表示依赖关系。

创建 BN 有三个主要步骤:

1.首先,确定要解决的问题中的主要变量。每个变量对应于网络的一个节点。为每个变量选择数字状态很重要,例如,通常有两种状态(真或假)。

2.其次,定义网络结构,即所有变量(节点)之间的因果关系。

3.第三,定义控制变量之间关系的概率规则。

(作者创作)

每个步骤都可以使用数据、专家知识或两者的结合来完成。在这个例子中,我将展示如何只用专业知识创建一个 BN。

贝叶斯网络的一个基本(教科书类型)例子如下:我们有四个变量,它们都有两种状态(真/假)。我们想知道在天空多云的情况下,草被弄湿的概率;因此,可能会下雨。此外,如果天空不是多云(是晴天),一个洒水器将被激活(使用太阳能),它将灌溉草地。

前两步如下图所示:

贝叶斯网络(作者使用 Genie 软件创建)

如果是阴天,可能会下雨= >阴天节点和雨天节点之间的正因果关系。

如果不是多云天气(是晴天),那么洒水喷头将被激活= >多云节点和洒水喷头节点之间的负因果关系。

最后,草地可能是湿的,原因有两个:正在下雨,或者洒水器被激活= >所以洒水器和雨节点与 wet_grass 节点有正因果关系。

因果关系通过条件概率表(CPT)来表达。

第三步在于创建那些 CPT。在这种情况下基于先前的专家知识。

多云节点:

多云节点 CPT

这是“输入节点”,我们从另一个来源假设多云(多云=真)的概率是 50%。所以,是晴天(多云=假)的概率也是 50%。在贝叶斯逻辑中,这是先验知识(来自于“是否”方面的专家)。

雨节点:

雨节 CPT

雨节点 CPT 应该代表多云节点和雨节点之间的正因果关系。因此,专家(或注册经验)说,鉴于天空多云,下雨的概率为 80%。也就是说,当天空多云(多云=真)时,下雨(下雨=真)的概率为 80%。同理,当天空不多云(多云=假)时,有 80%的概率不会下雨(下雨=假)。

其他情况是上述概率的补充。当天气多云时,不下雨的可能性是 20%。不多云的时候,下雨的概率是 20%。

需要注意的是,所有这些概率都来自于“专家”,或者如我之前所说的“人类知识”。

洒水节点:

喷头节点 CPT

洒水喷头 CPT 节点应代表多云节点和洒水喷头节点之间的负因果关系

CPT 配置来自 Spinkler 功能逻辑:当天气晴朗时(多云=假),洒水器将以 90%的概率被激活(洒水器=真)。因此,补充说明,当天气晴朗时,喷头有 10%的概率不会启动。

当天空多云(多云=真)时,Spinkler 没有基线配置。因此,概率为 50%(真),50%(假)。

同样,这些数字来自“专家”或人类知识,在这种情况下,来自喷灌机的基线配置。

湿 _ 草节点:

湿 _ 草节点 CPT

最后,Wet_Grass CPT 要表示洒水节点和 Wet_Grass 节点之间的正因果关系,以及雨水节点和 wet_grass 节点之间的正因果关系。

这个 CPT 比较复杂。专家可以完成它,或者贝叶斯定理可以帮助我们计算每个值。我已经在前一篇文章中解释了如何使用这个定理来计算这些值。所以我就不在这里做了,我让下面的链接:

我们可以使用与其他节点相同的逻辑来检查这个 CPT 告诉我们的内容:

如果是阴天,下雨的可能性很大(80%);【mag R1】另外,我们还可以加上 10%的概率,即使是阴天,洒水器也会被激活。求和是通过贝叶斯逻辑完成的,(即“加上“条件概率”)。结果是草地有 99%的可能性是湿的:

作者使用 Genie 软件创作

另一种情况是,当洒水装置关闭并且没有下雨时,我们不会期望看到草是湿的:

作者使用 Genie 软件创作

另外两种可能是洒水器开着的时候,不是下雨的时候。或者,当洒水装置关闭并且下雨时。在这两种情况下,在湿草 CPT 之后,我们发现看到湿草的概率是 90%:

作者使用 Genie 软件创作

我们看到贝叶斯网络如何尊重 CPT 的逻辑,这是可预测的,因为 CPT 是以这种方式“人工构建的”。

然而,这个小例子可以向我们展示贝叶斯网络的范围,也就是说,基于我们用来创建 CPT 的信息,我们可以实验更多在构建它时没有包括的案例(我认为这就是人工智能的意义)。

测试一个 BN 的学习

每个节点的基线概率分布在下一个网络中表示:

作者使用 Genie 软件创作

这个网络将条件概率显示在一起。在我们不知道天气是否多云的一天(真= 50%的概率),我们可以预期有 85%的概率会有湿草。这是可以解释的,因为我们有 70%的机会打开洒水器,有 50%的机会下雨。

然而,我们可以开始玩网络,看看它告诉我们什么:

如果是阴天(100%真实),喷头有 50%的概率开着,下雨有 80%的概率。因此,草地将有 85%的概率是湿的

作者使用 Genie 软件创作

反之,如果不是阴天,90%的概率会开着洒水车,20%的概率会下雨。因此,草地潮湿的概率为 84%。

作者使用 Genie 软件创作

新增病例:

这是我们可以开发 BN 潜力的时候(当它被正确建造的时候)。我们可以探索更接近真实世界的不同案例(巨大的组合):

例如,如果多云的概率是 20%、40%、60%或 80%,会发生什么?

这些网络显示了在这些情况下发生了什么:

作者使用 Genie 软件创作

我们看到在所有情况下,当天空因下雨而多云时,以及当天空因洒水器而不多云时,草将是湿的。所以,如果我们这种配置的目标是让草地尽可能的湿润,那么洒水器就是最好的选择!国阵从数量上解释了原因。

我用了四个例子,但是如果我们测试所有的值(多云=真从 0%到 100%),Wet_grass =真的状态,会一直在 84%到 85%之间。

逆向传播:从 BN 中获得更多价值。

我们还可以为目标节点(Wet_grass)设置“证据”,以便测试网络中的不同场景。这使我们能够作出决定。

例如,假设我们不知道天气是否多云,(50%对,50%错),如果我们希望草地是湿的,我们需要洒水器以 78%的概率打开,雨将以 56%的概率到来:

作者使用 Genie 软件创作

再举一个例子:我希望我的草永远是湿的。

案例 1:天气频道宣布有超过 95%的可能性是阴天。有必要用我的洒水器吗?答案是否定的。

作者使用 Genie 软件创作

案例 2:天气频道宣布阴天的概率小于 12%。为了 100%确定我的草地会是湿的,我必须使用我的洒水器。

作者使用 Genie 软件创作

影响分析

最后可以做一个网络的影响力分析。它向我们展示了哪些是最有影响力的节点,以及最有影响力的链接:

作者使用 Genie 软件创作

这个例子尽可能简单,但它告诉我们,我们需要洒水器或雨水来湿润草地(红色)。它还向我们表明,雨和多云天空之间的关系比多云天空和洒水器之间的关系更强一点(这可以从连接箭头的粗细看出)。

结论

这篇文章用一个非常简单的例子详尽地展示了如何使用专家知识来构建和训练一个 BN。

我展示了 BN 建模现实生活问题的范围和能力,包括概率知识和概率组合。

然而,现实生活中的问题有更高(真的更高)的复杂程度。

为此,有必要使用数据和人类知识。我将在下一篇文章中解释这一点。

如果你想继续阅读这样的故事,你可以在这里订阅!

如何从头开始训练 BERT 模型

原文:https://towardsdatascience.com/how-to-train-a-bert-model-from-scratch-72cfce554fc6?source=collection_archive---------0-----------------------

见见伯特的意大利表弟,菲利波托

伯特,但在意大利——作者图片

我的所有文章都聚焦于 BERT——这个模型主宰了自然语言处理(NLP)的世界,标志着语言模型的新时代。

对于那些以前没有使用过变形金刚模型的人来说,这个过程看起来有点像这样:

  • pip install transformers
  • 初始化预训练的变压器模型— from_pretrained
  • 用一些数据测试一下。
  • 也许对模型进行微调(再多训练一些)。

现在,这是一个伟大的方法,但如果我们只是这样做,我们缺乏对创建我们自己的变形金刚模型背后的理解。

此外,如果我们无法创建自己的变压器模型,我们必须依赖适合我们问题的预训练模型,但情况并非总是如此:

一些关于非英语 BERT 模型的评论

因此,在本文中,我们将探索构建我们自己的 transformer 模型所必须采取的步骤——特别是 BERT 的进一步开发版本,称为 RoBERTa。

概述

这个过程有几个步骤,所以在我们开始之前,让我们先总结一下我们需要做什么。总的来说,有四个关键部分:

  • 获取数据
  • 构建标记器
  • 创建输入管道
  • 训练模型

一旦我们完成了每一个部分,我们将使用我们构建的记号赋予器和模型——并保存它们,这样我们就可以像使用from_pretrained一样使用它们。

获取数据

和任何机器学习项目一样,我们需要数据。在用于训练 transformer 模型的数据方面,我们确实有太多的选择了——我们可以使用几乎任何文本数据。

使用 HuggingFace 的数据集库下载 OSCAR 数据集的视频演练

而且,如果说我们在互联网上有很多东西的话,那就是非结构化文本数据。

从互联网上搜集的文本领域中最大的数据集之一是 OSCAR 数据集。

OSCAR 数据集拥有大量不同的语言,其中一个最明显的从头训练用例是,我们可以将 BERT 应用于一些不太常用的语言,如泰卢固语或纳瓦霍语。

不幸的是,我唯一能说的语言是英语,但我的女朋友是意大利人,所以她——劳拉,将评估我们说意大利语的伯特模型的结果——菲利贝托。

因此,为了下载奥斯卡数据集的意大利部分,我们将使用 HuggingFace 的datasets库——我们可以用pip install datasets安装它。然后我们下载 OSCAR_IT:

我们来看看dataset这个物体。

很好,现在让我们以一种在构建我们的标记器时可以使用的格式存储我们的数据。我们需要从我们的数据集中创建一组仅包含text特性的明文文件,并且我们将使用换行符\n分割每个样本

在我们的data/text/oscar_it目录中,我们会找到:

包含我们的明文 OSCAR 文件的目录

构建标记器

下一个是记号赋予者!当使用转换器时,我们通常加载一个记号赋予器,以及它各自的转换器模型——记号赋予器是这个过程中的一个关键组件。

构建自定义令牌化器的视频演练

在构建我们的标记器时,我们将向它提供我们所有的 OSCAR 数据,指定我们的词汇大小(标记器中的标记数量),以及任何特殊的标记。

现在,罗伯塔特殊令牌看起来像这样:

因此,我们确保将它们包含在我们的标记器的train方法调用的special_tokens参数中。

我们的标记器现在已经准备好了,我们可以将它保存为文件供以后使用:

现在我们有两个文件定义了新的 FiliBERTo 记号赋予器:

  • merges.txt —执行文本到标记的初始映射
  • vocab.json —将令牌映射到令牌 id

有了这些,我们可以继续初始化我们的记号赋予器,这样我们就可以像使用任何其他from_pretrained记号赋予器一样使用它。

初始化标记器

我们首先使用之前构建的两个文件初始化记号赋予器——使用一个简单的from_pretrained:

现在我们的记号赋予器已经准备好了,我们可以试着用它来编码一些文本。当编码时,我们使用通常使用的两种方法,encodeencode_batch

从编码对象tokens中,我们将提取input_idsattention_mask张量用于 FiliBERTo。

创建输入管道

我们培训流程的输入管道是整个流程中更复杂的部分。它包括我们获取原始的 OSCAR 训练数据,对其进行转换,并将其加载到准备好进行训练的DataLoader中。

MLM 输入管道的视频演练

准备数据

我们将从一个样本开始,逐步完成准备逻辑。

首先,我们需要打开我们的文件——与我们保存为的文件相同。txt 文件在先。我们基于换行符\n分割每个样本,因为这表示单个样本。

然后,我们使用tokenizer对我们的数据进行编码——确保包括关键参数,如max_lengthpaddingtruncation

现在我们可以继续创建我们的张量——我们将通过掩蔽语言建模(MLM)来训练我们的模型。所以,我们需要三个张量:

  • input_ids —我们的 token_ids 有大约 15%的令牌使用屏蔽令牌<mask>屏蔽。
  • attention _ mask1s 和 0 s 的张量,标记“真实”记号/填充记号的位置——用于注意力计算。
  • 标签 —我们的 token_ids 带有屏蔽。

如果你不熟悉 MLM,我在这里已经解释过了。

我们的attention_masklabels张量就是从我们的batch中简单提取出来的。然而input_ids张量需要更多的关注,对于这个张量,我们屏蔽了大约 15%的记号——给它们分配记号 ID 3

在最终输出中,我们可以看到一个编码的input_ids张量的一部分。第一个令牌 ID 是1[CLS]令牌。围绕张量我们有几个3记号 id——这些是我们新添加的[MASK]记号。

构建数据加载器

接下来,我们定义我们的Dataset类——我们用它来初始化我们的三个编码张量作为 PyTorch torch.utils.data.Dataset对象。

最后,我们的dataset被加载到 PyTorch DataLoader对象中——在训练期间,我们用它将数据加载到我们的模型中。

训练模型

我们训练需要两样东西,我们的DataLoader和一个模型。我们有——但没有模型。

初始化模型

为了训练,我们需要一个未经训练的BERTLMHeadModel。为此,我们首先需要创建一个 RoBERTa 配置对象来描述我们希望用来初始化 FiliBERTo 的参数。

然后,我们用语言建模(LM)头导入并初始化我们的 RoBERTa 模型。

培训准备

在进入我们的训练循环之前,我们需要设置一些东西。首先,我们设置 GPU/CPU 使用率。然后我们激活模型的训练模式——最后,初始化我们的优化器。

培养

终于——训练时间到了!我们就像平时通过 PyTorch 训练一样训练。

如果我们去 Tensorboard,我们会发现随着时间的推移我们的损失——它看起来很有希望。

损失/时间—在此图表中,多个培训课程串联在一起

真正的考验

现在是真正考验的时候了。我们建立了一个 MLM 管道,并请劳拉评估结果。可以在这里看 22:44 的视频回顾:

我们首先使用'fill-mask'参数初始化一个pipeline对象。然后像这样开始测试我们的模型:

“ciao来了 va?”正确答案!这是我的意大利语达到的最高水平——所以,让我们把它交给劳拉。

我们从开始,“早上好,来弗吉尼亚吗?” —或者“日安,你好吗?”:

第一个回答,“buongiorno,chi va?”意思是“日安,谁在那里?”—如无意义。但是,我们的第二个答案是正确的!

接下来,是一个稍微难一点的短语,“你好,我的鸽子?” —或者“嗨,今天下午我们在哪里见面?”:

我们返回一些更积极的结果:

✅ "hi, where do we see each other this afternoon?"
✅ "hi, where do we meet this afternoon?"
❌ "hi, where here we are this afternoon?"
✅ "hi, where are we meeting this afternoon?"
✅ "hi, where do we meet this afternoon?"

最后,还有一个更难的句子,“你成功了吗?”或者“如果我们选择了另一天,会发生什么?”:

我们在这里也给出了一些更好的答案:

✅ "what would have happened if we had chosen another day?"
✅ "what would have happened if I had chosen another day?"
✅ "what would have happened if they had chosen another day?"
✅ "what would have happened if you had chosen another day?"
❌ "what would have happened if another day was chosen?"

总的来说,看起来我们的模型通过了 Laura 的测试——我们现在有了一个名为 FiliBERTo 的合格的意大利语言模型!

这就是从头开始训练 BERT 模型的演练!

我们已经覆盖了很多领域,从获取和格式化我们的数据,一直到使用语言建模来训练我们的原始 BERT 模型。

我希望你喜欢这篇文章!如果你有任何问题,请通过推特或者在下面的评论中告诉我。如果你想要更多这样的内容,我也会在 YouTube 上发布。

感谢阅读!

🤖《变形金刚》课程 NLP 的 70%折扣

*所有图片均由作者提供,除非另有说明

如何用 TensorFlow 在 10 分钟内训练一个分类模型

原文:https://towardsdatascience.com/how-to-train-a-classification-model-with-tensorflow-in-10-minutes-fd2b7cfba86?source=collection_archive---------3-----------------------

从数据收集和准备到模型训练和评估—包括源代码

照片由爆裂未爆裂

深度学习无处不在。从销售预测到在图像数据上分割皮肤病,只要有高质量的数据,深度学习算法没有做不到的事情。

如果深度学习和 TensorFlow 对你来说很陌生,那你来对地方了。本文将向您展示在表格数据上构建分类模型的整个过程。您将在一次会议中完成从数据收集和准备到训练和评估神经网络模型的过程。我们开始吧。

您将需要安装 TensorFlow 2+、Numpy、Pandas、Matplotlib 和 Scikit-Learn 来跟进。

不想看书?请观看我的视频:

跳到一个部分:

**·** [**DATASET USED**](#efa5)
**·** [**DATA PREPARATION AND EXPLORATION**](#ccbc)
  ∘ [Basic preparation](#3c5e)
  ∘ [Converting to a binary classification problem](#6d40)
  ∘ [Train/test split](#541e)
  ∘ [Data scaling](#0d9d)
**·** [**TRAINING A CLASSIFICATION MODEL WITH TENSORFLOW**](#3a77)
  ∘ [Defining a neural network architecture](#1597)
  ∘ [Visualizing model performance](#c871)
  ∘ [Making predictions](#11c8)
  ∘ [Model evaluation on test data](#1656)

你可以在 GitHub 上下载源代码。

使用的数据集

让我们避免不必要的麻烦,坚持简单的数据集。来自 Kaggle 的葡萄酒质量数据集对今天来说已经足够好了:

图片 1——来自 Kaggle 的葡萄酒质量数据集(图片由作者提供)

数据集基本上是干净的,但默认情况下不是为二元分类(好酒/劣酒)而设计的。取而代之的是,葡萄酒是按等级来评定的。我们稍后会解决这个问题。

下载并解压 CSV 文件到你的机器上,然后打开 JupyterLab。您可以自由使用任何其他 IDE,但下面所有的截图都将来自 Jupyter。

数据准备和探索

第一步是导入 Numpy 和 Pandas,然后导入数据集。下面的代码片段实现了这一点,并打印了一个 5 行的随机样本:

import numpy as np
import pandas as pd 

df = pd.read_csv('data/winequalityN.csv')
df.sample(5)

以下是数据集的外观:

图片 2 —葡萄酒质量数据集(图片由作者提供)

它基本上是干净的,但仍有一些工作要做。

基本准备

数据集有一些缺失值,但数量并不多,因为总共有 6497 行:

图 3-缺失值计数(作者图片)

运行以下代码来消除它们:

df = df.dropna()

唯一的非数字特征是type。可以是白色 (4870 行)或红色 (1593 行)。下面的代码片段将这个特性转换成一个名为is_white_wine的二进制特性,其中如果type是白色的则值为 1,否则为 0:

df['is_white_wine'] = [
    1 if typ == 'white' else 0 for typ in df['type']
]
df.drop('type', axis=1, inplace=True)

现在所有的特性都是数值型的,只剩下一件事要做——将目标变量(quality)二进制化。

转化为二进制分类问题

葡萄酒的等级从 3 到 9,假设越高越好。以下是价值计数:

图 4 —目标变量值计数(作者图片)

为了简单起见,我们将把它转换成一个二进制变量。我们会将任何 6 级及以上的葡萄酒归类为 (1),其他所有葡萄酒归类为 (0)。代码如下:

df['is_good_wine'] = [
    1 if quality >= 6 else 0 for quality in df['quality']
]
df.drop('quality', axis=1, inplace=True)

df.head()

这是数据集现在的样子:

图 5-准备后的数据集(作者提供的图片)

你现在有 4091 种好酒和 2372 种劣酒。班级不平衡,但我们可以解决这个问题。接下来,让我们将数据集分成训练集和测试集。

训练/测试分割

我们会坚持标准的 80:20 分成。代码如下:

from sklearn.model_selection import train_test_split

X = df.drop('is_good_wine', axis=1)
y = df['is_good_wine']

X_train, X_test, y_train, y_test = train_test_split(
    X, y, 
    test_size=0.2, random_state=42
)

现在,定型集中有 5170 行,测试集中有 1293 行。训练一个稍微像样的神经网络模型应该就够了。在开始培训之前,让我们先对数据进行缩放。

数据缩放

sulphatescitric acid这样的特征的值接近于零,而total sulfur dioxide是以百为单位。如果你让它们保持原样,你会混淆神经网络,因为它会认为更高规模的特征更重要。

这就是伸缩性发挥作用的地方。我们将使用来自 Scikit-Learn 的StandardScaler来拟合和转换训练数据,并将转换应用于测试数据:

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

下面是前三个缩放行的样子:

图片 6 —缩放的训练集(图片由作者提供)

现在取值范围更窄了,所以神经网络应该能做得更好。让我们训练模型,看看我们是否能得到一些像样的东西。

用 TensorFlow 训练分类模型

在训练二元分类模型时,您需要记住几件事情:

  • 输出层结构 —您可能想要用 sigmoid 函数激活一个神经元。这将输出一个概率,然后你可以分配给好酒(P > 0.5)或坏酒(P < = 0.5)。
  • 损失函数 —二进制交叉熵是最合适的。不要误认为是分类交叉熵。
  • 类平衡 —目标变量中的类平衡吗?换句话说,你有大致相同数量的好酒和坏酒吗?否则,准确性可能不是最佳评估指标。我们还将使用精度召回

考虑到以上三点,接下来让我们定义一个神经网络架构。

定义神经网络架构

我完全是随机选择这个架构的,所以可以随意调整。该模型从 12 个输入特征到 128 个神经元的第一隐藏层,接着是 256 个神经元的两个附加隐藏层。最后有一个单神经元输出层。隐藏层使用 ReLU 作为激活函数,输出层使用 Sigmoid。

代码如下:

import tensorflow as tf
tf.random.set_seed(42)

model = tf.keras.Sequential([
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(256, activation='relu'),
    tf.keras.layers.Dense(256, activation='relu'),
    tf.keras.layers.Dense(1, activation='sigmoid')
])

model.compile(
    loss=tf.keras.losses.binary_crossentropy,
    optimizer=tf.keras.optimizers.Adam(lr=0.03),
    metrics=[
        tf.keras.metrics.BinaryAccuracy(name='accuracy'),
        tf.keras.metrics.Precision(name='precision'),
        tf.keras.metrics.Recall(name='recall')
    ]
)

history = model.fit(X_train_scaled, y_train, epochs=100)

这将启动培训过程。在我的机器上,一个纪元大约需要 1 秒钟(M1·MBP):

图 7-模型训练(图片由作者提供)

我们在训练过程中跟踪丢失、准确度、精确度和召回,并将其保存到history。我们现在可以可视化这些指标,以了解模型的运行情况。

可视化模型性能

让我们从导入 Matplotlib 并稍微调整一下默认样式开始。以下代码片段将使绘图变大,并删除顶部和右侧的脊线:

import matplotlib.pyplot as plt
from matplotlib import rcParams

rcParams['figure.figsize'] = (18, 8)
rcParams['axes.spines.top'] = False
rcParams['axes.spines.right'] = False

该图将有多条线——损失线、准确度线、精确度线和回忆线。它们都共用 X 轴,代表纪元编号(np.arange(1, 101))。我们应该看到损失在减少,其他指标在增加:

plt.plot(
    np.arange(1, 101), 
    history.history['loss'], label='Loss'
)
plt.plot(
    np.arange(1, 101), 
    history.history['accuracy'], label='Accuracy'
)
plt.plot(
    np.arange(1, 101), 
    history.history['precision'], label='Precision'
)
plt.plot(
    np.arange(1, 101), 
    history.history['recall'], label='Recall'
)
plt.title('Evaluation metrics', size=20)
plt.xlabel('Epoch', size=14)
plt.legend();

让我们来看看:

图 8 —培训期间的模特表现(图片由作者提供)

当我们训练模型时,准确度、精确度和召回率稍微增加,而损失减少。所有都有偶尔的峰值,如果你训练模型更长时间,这些峰值有望消失。

根据图表,你可以为更多的时期训练模型,因为没有稳定期的迹象。

但是我们是否过度适应了呢?接下来我们来回答这个问题。

做预测

您现在可以使用predict()函数来获得缩放测试数据的预测概率:

predictions = model.predict(X_test_scaled)

以下是它们的样子:

图片 9 —预测概率(图片由作者提供)

你必须在评估之前将它们转换成类。逻辑很简单——如果概率大于 0.5,我们指定 1(好酒),否则指定 0(坏酒):

prediction_classes = [
    1 if prob > 0.5 else 0 for prob in np.ravel(predictions)
]

下面是前 20 个的样子:

图片 10-预测类(作者图片)

这就是我们所需要的—接下来让我们评估这个模型。

测试数据的模型评估

让我们从混淆矩阵开始:

from sklearn.metrics import confusion_matrix

print(confusion_matrix(y_test, prediction_classes))

图 11 —混淆矩阵(图片由作者提供)

假阴性(214)比假阳性(99)多,所以测试集上的召回值将低于精度。

下面的代码片段显示了测试集的准确度、精确度和召回率:

from sklearn.metrics import accuracy_score, precision_score, recall_score

print(f'Accuracy: {accuracy_score(y_test, prediction_classes):.2f}')
print(f'Precision: {precision_score(y_test, prediction_classes):.2f}')
print(f'Recall: {recall_score(y_test, prediction_classes):.2f}')

图 12 —测试集的准确度、精确度和召回率(图片由作者提供)

与列车组评估相比,所有值都略低:

  • 精度 : 0.82
  • 精度 : 0.88
  • 回忆 : 0.83

这个模型有点过度拟合了,但在几分钟内仍然是不错的工作。我们将在下一篇文章中讨论优化。

离别赠言

这就做到了——你现在知道如何训练一个简单的神经网络进行二进制分类。我们今天使用的数据集相对干净,几乎不需要任何准备工作。不要习惯那种感觉。

我们还有很多可以改进的地方。例如,您可以向网络添加额外的层,增加神经元的数量,选择不同的激活函数,选择不同的优化器,添加删除层,等等。可能性几乎是无穷无尽的,所以一切都归结于实验。

下一篇文章将涉及优化—您将学习如何自动找到最佳学习速率和神经网络架构,如果您想了解更多,请继续关注。

感谢阅读。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

https://medium.com/@radecicdario/membership

保持联系

深度学习的情感分析

原文:https://towardsdatascience.com/how-to-train-a-deep-learning-sentiment-analysis-model-4716c946c2ea?source=collection_archive---------6-----------------------

如何训练自己的高性能情绪分析模型

照片由 Pietro JengUnsplash 上拍摄

目标

情感分析是自然语言处理中的一种技术,用于识别与文本相关联的情感。情感分析的常见用例包括监控客户在社交媒体上的反馈、品牌和活动监控。

在本文中,我们将探讨如何利用预先训练好的 HuggingFace 模型,在自定义数据集上训练自己的情感分析模型。我们还将研究如何在 CPU 和 GPU 环境中高效地对微调后的模型执行单次和批量预测。如果您正在寻找一个开箱即用的情感分析模型,请查看我以前的文章如何用 python 执行情感分析,其中只有 3 行代码。

装置

pip install transformers
pip install fast_ml==3.68
pip install datasets

导入包

import numpy as np
import pandas as pd
from fast_ml.model_development import train_valid_test_split
from transformers import Trainer, TrainingArguments, AutoConfig, AutoTokenizer, AutoModelForSequenceClassification
import torch
from torch import nn
from torch.nn.functional import softmax
from sklearn.metrics import classification_report
from sklearn.preprocessing import LabelEncoder
import datasets

启用 GPU 加速器(如果可用)。

DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print (f'Device Availble: {DEVICE}')

数据准备

我们将使用一个电子商务数据集,其中包含文本评论和女装评级。

df = pd.read_csv('/kaggle/input/womens-ecommerce-clothing-reviews/Womens Clothing E-Commerce Reviews.csv')
df.drop(columns = ['Unnamed: 0'], inplace = True)
df.head()

我们只对Review TextRating列感兴趣。Review Text列用作模型的输入变量,而Rating列是我们的目标变量,其值从 1(最不利)到 5(最有利)。

为了清楚起见,让我们在每个整数评级后面附加“星”或“星”。

df_reviews = df.loc[:, ['Review Text', 'Rating']].dropna()
df_reviews['Rating'] = df_reviews['Rating'].apply(lambda x: f'{x} Stars' if x != 1 else f'{x} Star')

这是现在数据的样子,1,2,3,4,5 颗星是我们的类标签。

让我们使用 Sklearn 的LabelEncoder对评级进行编码。

le = LabelEncoder()
df_reviews['Rating'] = le.fit_transform(df_reviews['Rating'])
df_reviews.head()

请注意,Rating列已经从文本转换为整数列。

Rating栏中的数字范围从 0 到 4。这些是将用于训练模型的类标签的类 id。每个类 id 对应一个等级。

print (le.classes_)>> ['1 Star' '2 Stars' '3 Stars' **'4 Stars'** '5 Stars']

列表的位置索引是类 id (0 到 4 ),该位置的值是原始评级。例如,在位置号 3,类别 id 是“3 ”,它对应于类别标签“4 星”。

让我们将数据分别按照 80%、10%和 10%的比例拆分为训练、验证和测试。

(train_texts, train_labels,
 val_texts, val_labels,
 test_texts, test_labels) = train_valid_test_split(df_reviews, target = 'Rating', train_size=0.8, valid_size=0.1, test_size=0.1)

将熊猫系列的评论文本转换成句子列表。

train_texts = train_texts['Review Text'].to_list()
train_labels = train_labels.to_list()
val_texts = val_texts['Review Text'].to_list()
val_labels = val_labels.to_list()
test_texts = test_texts['Review Text'].to_list()
test_labels = test_labels.to_list()

创建一个DataLoader类,用于在训练和推理阶段处理和加载数据。

class DataLoader(torch.utils.data.Dataset):
    def __init__(self, sentences=None, labels=None):
        self.sentences = sentences
        self.labels = labels
        self.tokenizer = AutoTokenizer.from_pretrained('distilbert-base-uncased')

        if bool(sentences):
            self.encodings = self.tokenizer(self.sentences,
                                            truncation = True,
                                            padding = True)

    def __getitem__(self, idx):
        item = {key: torch.tensor(val[idx]) for key, val in self.encodings.items()}

        if self.labels == None:
            item['labels'] = None
        else:
            item['labels'] = torch.tensor(self.labels[idx])
        return item def __len__(self):
        return len(self.sentences)

    def encode(self, x):
        return self.tokenizer(x, return_tensors = 'pt').to(DEVICE)

让我们来看看DataLoader的运行情况。

train_dataset = DataLoader(train_texts, train_labels)
val_dataset = DataLoader(val_texts, val_labels)
test_dataset = DataLoader(test_texts, test_labels)

DataLoader初始化一个预训练的标记器,并对输入句子进行编码。我们可以通过使用__getitem__函数从DataLoader中获得一条记录。下面是输入句子进行标记化后的结果。

print (train_dataset.__getitem__(0))

输出数据是一个由 3 个键值对组成的字典

  • input_ids:这包含一个整数张量,其中每个整数代表原始句子中的单词。tokenizer步骤将单个单词转换成由整数表示的符号。第一个记号101是句子的开始记号,而102记号是句子的结束记号。请注意,有许多尾随零,这是由于在tokenizer步骤中应用于句子的填充。
  • attention_mask:这是一个二进制值数组。attention_mask的每个位置对应input_ids中相同位置的一个令牌。1表示应该关注给定位置的令牌,0表示给定位置的令牌是填充值。
  • labels:这是目标标签

定义评估指标

我们希望在培训阶段定期对模型性能进行评估。为此,我们需要一个度量计算函数,它接受一个元组(prediction, label)作为参数,并返回一个度量字典:{'metric1':value1, metric2 :value2}

f1 = datasets.load_metric('f1')
accuracy = datasets.load_metric('accuracy')
precision = datasets.load_metric('precision')
recall = datasets.load_metric('recall')def compute_metrics(eval_pred):
    metrics_dict = {}
    predictions, labels = eval_pred
    predictions = np.argmax(predictions, axis=1)

    metrics_dict.update(f1.compute(predictions = predictions, references = labels, average = 'macro'))
    metrics_dict.update(accuracy.compute(predictions = predictions, references = labels))
    metrics_dict.update(precision.compute(predictions = predictions, references = labels, average = 'macro'))
    metrics_dict.update(recall.compute(predictions = predictions, references = labels, average = 'macro')) return metrics_dict

培养

接下来,我们从预训练的检查点配置实例化一个distilbert-base-uncased模型。

id2label = {idx:label for idx, label in enumerate(le.classes_)}
label2id = {label:idx for idx, label in enumerate(le.classes_)}config = AutoConfig.from_pretrained('distilbert-base-uncased',
                                    num_labels = 5,
                                    id2label = id2label,
                                    label2id = label2id)model = AutoModelForSequenceClassification.from_config(config)
  • num_labels:类别数
  • id2label:将类别 id 映射到类别标签的字典{0: '1 Star', 1: '2 Stars', 2: '3 Stars', 3: '4 Stars', 4: '5 Stars'}
  • label2id:将类别标签映射到类别 id 的映射字典{'1 Star': 0, '2 Stars': 1, '3 Stars': 2, '4 Stars': 3, '5 Stars': 4}

让我们检查一下模型配置。id2labellabel2id字典已经合并到配置中。我们可以在推理过程中从模型的配置中检索这些字典,以便为预测的类 id 找出相应的类标签。

print (config)>> DistilBertConfig {
  "activation": "gelu",
  "architectures": [
    "DistilBertForMaskedLM"
  ],
  "attention_dropout": 0.1,
  "dim": 768,
  "dropout": 0.1,
  "hidden_dim": 3072,
  "id2label": {
    "0": "1 Star",
    "1": "2 Stars",
    "2": "3 Stars",
    "3": "4 Stars",
    "4": "5 Stars"
  },
  "initializer_range": 0.02,
  "label2id": {
    "1 Star": 0,
    "2 Stars": 1,
    "3 Stars": 2,
    "4 Stars": 3,
    "5 Stars": 4
  },
  "max_position_embeddings": 512,
  "model_type": "distilbert",
  "n_heads": 12,
  "n_layers": 6,
  "pad_token_id": 0,
  "qa_dropout": 0.1,
  "seq_classif_dropout": 0.2,
  "sinusoidal_pos_embds": false,
  "tie_weights_": true,
  "transformers_version": "4.6.1",
  "vocab_size": 30522
}

我们还可以使用以下方法来检查模型架构

print (model)

设置训练参数。

training_args = TrainingArguments(
    output_dir='/kaggle/working/results',
    num_train_epochs=10,
    per_device_train_batch_size=64,
    per_device_eval_batch_size=64,
    warmup_steps=500,
    weight_decay=0.05,
    report_to='none',
    evaluation_strategy='steps',
    logging_dir='/kagge/working/logs',
    logging_steps=50)
  • report_to支持将训练工件和结果记录到 mlflow、tensorboard、azure_ml 等平台
  • per_device_train_batch_size是训练期间每个 TPU/GPU/CPU 的批量大小。如果您的设备面临内存不足的问题,请降低此值
  • per_device_eval_batch_size是评估期间每个 TPU/GPU/CPU 的批量大小。如果您的设备面临内存不足的问题,请降低此值
  • logging_step确定培训期间进行指标评估的频率

实例化Trainer。在引擎盖下,Trainer基于给定的训练参数、模型、数据集和指标运行训练和评估循环。

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=train_dataset,
    eval_dataset=val_dataset,
    compute_metrics=compute_metrics)

开始训练吧!

trainer.train()

每 50 步进行一次评估。我们可以通过改变TrainingArguments中的logging_steps参数来改变求值的间隔。除了默认的训练和验证损失指标之外,我们还获得了之前在compute_metric函数中定义的额外指标。

估价

让我们在测试集上评估我们的训练。

eval_results = trainer.predict(test_dataset)

Trainerpredict函数返回 3 项:

  1. 原始预测分数的数组
print (test_results.predictions)

2.地面真实标签 id

print (test_results.label_ids)

>> [1 1 4 ... 4 3 1]

3.韵律学

print (test_results.metrics)

>> {'test_loss': 0.9638910293579102,
		'test_f1': 0.28503729426950286,
		'test_accuracy': 0.5982339955849889,
		'test_precision': 0.2740061405117546,
		'test_recall': 0.30397183356136337,
		'test_runtime': 5.7367,
		'test_samples_per_second': 394.826,
		'test_mem_cpu_alloc_delta': 0,
		'test_mem_gpu_alloc_delta': 0,
		'test_mem_cpu_peaked_delta': 0,
		'test_mem_gpu_peaked_delta': 348141568}

模型预测函数输出未标准化的概率得分。为了找到类别概率,我们对未标准化的分数取一个软最大值。具有最高类别概率的类别被认为是预测类别。我们可以通过取类概率的 argmax 来找到它。我们之前存储在模型配置中的id2label属性可用于将类别 id (0-4)映射到类别标签(1 星,2 星..).

label2id_mapper = model.config.id2label
proba = softmax(torch.from_numpy(test_results.predictions))
pred = [label2id_mapper[i] for i in torch.argmax(proba, dim = -1).numpy()]
actual = [label2id_mapper[i] for i in test_results.label_ids]

我们使用 Sklearn 的classification_report来获得精确度、召回率、f1 和准确度分数。

class_report = classification_report(actual, pred, output_dict = True)
pd.DataFrame(class_report)

保存模型

trainer.save_model('/kaggle/working/sentiment_model')

推理

在本节中,我们将了解如何加载已定型模型并对其执行预测。让我们在另一个笔记本上测试一下这个推论。

设置

import pandas as pd
import numpy as np
from transformers import Trainer, TrainingArguments, AutoConfig, AutoTokenizer, AutoModelForSequenceClassification
import torch
from torch import nn
from torch.nn.functional import softmax

这种推断可以在 GPU 或 CPU 环境中工作。如果可用,在您的环境中启用 GPU。

DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print (f'Device Availble: {DEVICE}')

这与我们在培训阶段使用的DataLoader相同

class DataLoader(torch.utils.data.Dataset):
    def __init__(self, sentences=None, labels=None):
        self.sentences = sentences
        self.labels = labels
        self.tokenizer = AutoTokenizer.from_pretrained('distilbert-base-uncased')

        if bool(sentences):
            self.encodings = self.tokenizer(self.sentences,
                                            truncation = True,
                                            padding = True)

    def __getitem__(self, idx):
        item = {key: torch.tensor(val[idx]) for key, val in self.encodings.items()}

        if self.labels == None:
            item['labels'] = None
        else:
            item['labels'] = torch.tensor(self.labels[idx])
        return item def __len__(self):
        return len(self.sentences)

    def encode(self, x):
        return self.tokenizer(x, return_tensors = 'pt').to(DEVICE)

创建模型类

SentimentModel类帮助初始化模型,包含分别用于单个和批量预测的predict_probabatch_predict_proba方法。batch_predict_proba使用 HuggingFace 的Trainer进行批量评分。

class SentimentModel():

    def __init__(self, model_path):

        self.model = AutoModelForSequenceClassification.from_pretrained(model_path).to(DEVICE)
        args =  TrainingArguments(output_dir='/kaggle/working/results', per_device_eval_batch_size=64)
        self.batch_model = Trainer(model = self.model, args= args)
        self.single_dataloader = DataLoader()

    def batch_predict_proba(self, x):

        predictions = self.batch_model.predict(DataLoader(x))
        logits = torch.from_numpy(predictions.predictions)

        if DEVICE == 'cpu':
            proba = torch.nn.functional.softmax(logits, dim = 1).detach().numpy()
        else:
            proba = torch.nn.functional.softmax(logits, dim = 1).to('cpu').detach().numpy() return proba

    def predict_proba(self, x):

        x = self.single_dataloader.encode(x).to(DEVICE)
        predictions = self.model(**x)
        logits = predictions.logits

        if DEVICE == 'cpu':
            proba = torch.nn.functional.softmax(logits, dim = 1).detach().numpy()
        else:
            proba = torch.nn.functional.softmax(logits, dim = 1).to('cpu').detach().numpy() return proba

数据准备

让我们加载一些样本数据

df = pd.read_csv('/kaggle/input/womens-ecommerce-clothing-reviews/Womens Clothing E-Commerce Reviews.csv')
df.drop(columns = ['Unnamed: 0'], inplace = True)
df_reviews = df.loc[:, ['Review Text', 'Rating']].dropna()
df_reviews['Rating'] = df_reviews['Rating'].apply(lambda x: f'{x} Stars' if x != 1 else f'{x} Star')
df_reviews.head()

我们将创建两组数据。一个用于批量评分,另一个用于单次评分。

batch_sentences = df_reviews.sample(n = 10000, random_state = 1)['Review Text'].to_list()
single_sentence = df_reviews.sample(n = 1, random_state = 1)['Review Text'].to_list()[0]

预测

实例化模型

sentiment_model = SentimentModel('../input/fine-tune-huggingface-sentiment-analysis/sentiment_model')

使用predict_proba方法预测单个句子。

single_sentence_probas = sentiment_model.predict_proba(single_sentence)
id2label = sentiment_model.model.config.id2label
predicted_class_label = id2label[np.argmax(single_sentence_probas)]print (predicted_class_label)
>> 5 Stars

使用batch_predict_proba方法对一批句子进行预测。

batch_sentence_probas = sentiment_model.batch_predict_proba(batch_sentences)
predicted_class_labels = [id2label[i] for i in np.argmax(batch_sentence_probas, axis = -1)]

推理速度

让我们比较一下predict_probabatch_predict_proba方法之间的推理速度

对于 CPU 和 GPU 环境中的 10k 样本数据。我们将对 10k 个样本进行迭代,predict_proba每次进行一次预测,同时使用batch_predict_proa方法对所有 10k 个样本进行评分,无需迭代。

%%time
for sentence in batch_sentences:
    single_sentence_probas = sentiment_model.predict_proba(sentence)%%time
batch_sentence_probas = sentiment_model.batch_predict_proba(batch_sentences)

GPU 环境

遍历predict_proba大约需要 2 分钟,而对于 10k 样本数据batch_predict_proba大约需要 30 秒。批量预测比在 GPU 环境下使用单次预测快了差不多 4 倍。

CPU 环境

在 CPU 环境中,predict_proba花费了大约 14 分钟,而batch_predict_proba花费了大约 40 分钟,几乎是原来的 3 倍。

因此,对于大型数据集,如果您有 GPU,请使用batch_predict_proba。如果您无法访问 GPU,您最好使用predict_proba遍历数据集。

结论

在本文中,我们研究了:

  • 如何利用预训练的 HuggingFace 模型来训练自己的深度学习情感分析模型
  • 如何创建单项和批量评分预测方法
  • CPU 和 GPU 环境中单次和批量评分的推断速度

这篇文章的笔记本可以在这里找到:

加入 Medium 阅读更多这样的故事。

如何在噪声数据上训练细粒度多标签分类模型

原文:https://towardsdatascience.com/how-to-train-a-fine-grained-multilabel-classification-model-on-noisy-data-8d84d4f65781?source=collection_archive---------30-----------------------

时尚 AI

基于 Fastai 和 DeepFashion 数据集的服装属性识别

图片由 TanaCh 根据 Shutterstock.com的许可使用

噪声标签的问题对于每个处理过手动注释数据的人来说都很熟悉。每当多个贡献者参与数据标注任务时,由于不同的参与者将具有不同的标注标准,这将不可避免地导致数据误标注。面临这个问题的组织经常会推迟深度学习产品的开发,并优先考虑数据清理。然而,有一些方法可以帮助建立适当的模型,同时不断提高数据质量。在本文中,我将解决细粒度多标签分类中的噪声数据问题。

在我的上一篇文章“用 DeepFashion 数据集和 Fastai 进行服装分类”中,我遇到了嘈杂标签的问题。毫无疑问,数据中的噪音影响了模型的质量。即使最终我能够在单标签分类任务中获得良好的准确性,如果我找不到这个问题的解决方案,我也会质疑继续这个项目的可能性。概括地说,我的目标是将服装项目建模为一个图表,该图表包含服装类型、属性及其关系(无论两个项目是否可以组合成一个外观)。作为第一步,我正在为服装类型和属性识别构建模型,这些模型将用于在图形建模之前标记我自己的数据。尽管噪声标签对于简单的单标签分类模型来说不是一个大问题,但是多标签属性分类意味着学习语义相近的类别之间的细微差异。这在有噪声的数据上尤其难以解决。

在本文中,我将介绍为多标签属性分类训练模型的过程。文章包含以下几个部分:

  1. 数据
  2. 评估指标的选择
  3. 损失函数的选择
  4. 模特培训
  5. 估价
  6. 摘要

在我的解决方案中,我使用 PyTorch 和 Fastai 库。本文中使用的完整代码可从这里获得。

数据

我使用了 DeepFasion 数据集,这是一个大规模的服装数据库,用于服装类别和属性预测,由香港中文大学多媒体实验室收集。

分类基准于 2016 年发布。它评估了 FashionNet 模型在预测 46 个类别和 1000 个服装属性方面的性能。原论文请参见 DeepFashion:用丰富的注释支持健壮的服装识别和检索,CVPR 2016

DeepFashion 数据库包含几个数据集。对于这个项目,使用了类别和属性预测基准。该数据集包含 289,222 张不同的服装图片,标有 1000 种不同的属性,其中我使用了 98 种属性,分别对应于款式、面料、季节和图案类型。

训练标签以以下格式存储在 multilabel-train.csv 中:

训练数据文件

数据集包含图像的位置、字符串对象形式的标签以及图像是否属于验证集的指示符。

为了加载图像,我们将使用一个数据块,它将图像的完整路径和作为标签的字符串列表作为输入。为此,我们将创建两个助手函数来解析输入格式。我们还将创建一个 splitter 函数,它将基于 is_valid 列创建训练集和验证集。

当调用数据块 API 时,我们需要指定变量的类型。在我们的例子中,自变量是 ImageBlock,因变量是 MultiCategoryBlock。MultiCategoryBlock 希望标签存储为字符串列表。 get_y 方法会搞定的。

让我们看看数据集中的一些图像:

带标签的训练图像

显然,原始数据集在标签中包含了大量噪声。例如,第一张图片上没有掌纹,第二张图片上的“日常”服装看起来比上一张图片上的“时尚”牛仔短裤更花哨。这就是我在本文中要解决的问题,但是首先,我们需要为我们的解决方案选择一个合适的评估指标。

评估指标的选择

现在,当数据被加载时,让我们看一下目标变量:

我们传递给 dblock 变量的标签列表被转换成稀疏的独热编码向量。稀疏性将影响我们对评估指标的选择。fastai 中的默认选择是 accuracy_multi 。但是,它不适用于稀疏标注。我们来看看为什么。方法 accuracy_multi 在 fastai 中定义如下:

如果我们创建一个零张量作为“预测”,并将其与目标值一起发送到 accuracy_multi ,我们将已经达到 98%的准确度。这意味着即使我们的模型不预测任何标签,它仍然有 98%的准确性。

TensorMultiCategory(0.9796)

因此,我们需要找到另一个评估指标,反映我们模型的实际学习进度和性能。一个选择可能是 FBeta 分数。 FBetaF-score 的概括。虽然 F-score 被定义为精度和召回率的调和平均值,并赋予两者相同的权重,但是 FBeta 增加了一个称为 Beta 的权重配置参数。beta 参数决定了回忆在综合得分中的权重。beta < 1 更重视精度,而 beta > 1 更倾向于召回(beta - > 0 只考虑精度,beta - > +inf 只考虑召回)。

让我们看看它是如何处理我们的“0-预测”问题的:

0.0

在没有预测的情况下,它会给我们 FBeta=0。我们还可以测试其他一些极端情况。例如随机预测:

0.001

随机生成的预测的 FBeta 分数接近 0。而在“完美”预测上,其中预测=目标 Fbeta 分数等于 1:

1.0

这看起来像是评估指标的有效选项。现在让我们选择一个损失函数。

损失函数的选择

回到训练标签的例子,它们被编码为独热编码向量。这种编码也被称为硬编码。硬编码标签的问题在于,正确类别的预测概率非常大,而不正确类别的预测概率非常低。该模型将以接近 1 的置信度对每个训练示例进行正确分类,这可能会导致多个问题。第一个问题是过度拟合。另外两个问题与我们数据集中标签的性质有关。

如果我们仔细观察数据集中的标签:

['abstract-print', 'animal', 'baroque', 'basic', 'beach', 'bird-print', 'boho', 'botanical-print', 'camouflage', 'cargo', 'chic', 'chiffon', 'circle', 'civil', 'colorblock', 'cotton', 'cozy', 'crochet', 'cute', 'denim', 'dotted', 'elegant', 'everyday', 'fancy', 'faux-fur', 'faux-leather', 'faux-suede', 'feather', 'floral', 'fur', 'glitter', 'graphic', 'grid-print', 'grunge', 'knotted', 'leaf-print', 'leather', 'leopard-print', 'linen', 'linen-blend', 'logo', 'luxe', 'marble-print', 'medallion-print', 'mesh', 'metallic', 'mixed-print', 'multi-stripe', 'neon', 'neoprene', 'nets', 'netted', 'nylon', 'oil', 'ombre', 'organza', 'ornate-print', 'paisley-print', 'palm-print', 'party', 'patched', 'pattern', 'pleated', 'print', 'relaxed', 'retro', 'safari', 'sateen', 'satin', 'sheer', 'smart', 'soft', 'solid', 'sophisticated', 'sparkling', 'sporty', 'springs', 'square', 'star', 'strap', 'stretch', 'striped', 'suede', 'summer', 'sweet', 'textured', 'thermal', 'tie-dye', 'training', 'triangle', 'tropical', 'tweed', 'utility', 'velvet', 'weekend', 'workout', 'woven', 'zigzag']

我们可以看到衣服属性标签在语义上非常接近。例如:“植物印花”和“花卉”,或者“人造革”和“皮革”,即使对人来说也很难区分。当我们在编码为 One-Hot 的语义相似的标签上训练模型时,正确和不正确的类之间的差异非常大,即使它们在语义上可能非常接近。在这种情况下,模型预测标签的置信度是不受限制的,并且会随着类别而变化,这使得正确类别的分离更具挑战性。

最后,正如我们在数据部分看到的,DeepFashion 数据集受到嘈杂标签的影响。数据由多个参与者手动标注,这些参与者可能具有不同的标注标准,这导致了数据的错误标注。结果,用硬编码标签训练的模型将以高置信度学习不正确的特征。因此,我们需要挑战数据集中的标签,并问自己这样一个问题:真正的标签是否真的是真的。一种方法是通过将损失目标值从 1 降低到 0.9 来给标签分配概率。这种方法被称为标签平滑,并在论文中详细讨论了标签平滑何时有帮助?

标签平滑防止网络变得过于自信,并使其不太可能过度拟合。此外,它通过引入平滑参数 α 来统一正确和错误类别之间的差异。结果,每个不正确的类标签将与正确的类标签等距,这使得更容易分离语义相似的类。我们将在损失函数中实现标签平滑,并使用它来训练我们的模型。

在 fastai 中,多标签分类问题的损失函数的默认选择是一个 BCEWithLogitsLossFlat ,它是一个带有 Logits 的二元交叉熵。*

*实际上是一个 sigmoid 函数,它是 logit 函数的逆函数,将交叉熵的任意实值映射回[0,1]范围,这是我们通常希望在 0 和 1 之间编码的目标。

我们将把 BCEWithLogitsLossFlat 包装在LabelSmoothingBCEWithLogitsLossFlat类中,并在调用 BCEWithLogitsLossFlat 之前应用标签平滑:

让我们比较一下训练网络时使用和不使用标签平滑的损失值。

无标签平滑:

我们可以看到损失值非常小。由于有 0|1 个目标,该模型对其分配的标签过于自信。

现在让我们用平滑标签来训练网络:

当我们通过平滑标签来训练模型时,我们观察到较高的损失值,这起初可能是违反直觉的。原因是标签平滑降低了目标的确定性。在这种情况下,更高的损失实际上是一个理想的结果。

我们还可以观察到,仅在一个时期的训练之后,该模型就具有 98%的准确性。这是我们之前在选择评估指标时讨论的问题。

模特培训

我们继续使用标签平滑来训练模型。现在,我们将检查我们的数据加载器中的数据,并逐渐增加每个小批量的学习率,以观察损失值如何随着学习率的变化而变化。我们的目标是找到最有效的学习速率,使网络更快地收敛。

三个时期后的损失曲线

由于我们的模型已经训练了三个时期,网络的权重不再是随机的,我们没有观察到任何急剧下降的损失。为了进一步的训练,我们将采用一系列权重,从下降点到损失再次开始增长的点,并检查我们是否可以改进模型。

在这个解决方案中,我使用预先训练好的 ResNet34 模型。从预训练模型转移的层已经擅长识别基本视觉概念,并且不需要太多训练。然而,负责识别特定于我们问题的复杂形状的深层仍然会受益于更高的学习率。因此,我们需要对第一层使用较小的学习速率,对最后一层使用较大的学习速率,以允许它们更快地进行微调。

正如我们所看到的,我们的网络在学习方面取得了进步。然而,很难判断我们是需要继续训练还是停下来不要过度适应模型。绘制培训和验证损失图可以帮助我们评估是否需要继续。

培训与验证损失

该图显示验证损失不再改善那么多。如果我们继续训练,我们将增加训练和验证损失之间的差距,这将意味着我们过度拟合我们的模型。所以,我们最好现在就停止训练,进入下一步,测评。

模型评估

如果我们绘制验证 FBeta 分数,我们可以看到它是如何随着每个时期而改进的。

每个时期的验证 FBeta

对训练数据集的评估

首先,我们将查看训练数据集上的预测,以估计我们的模型是否学习了合理的模式。

对训练数据的评估

第一行包含原始标签,第二行包含预测。我们的预测与标签并不完全匹配,但预测的标签是有意义的。总的来说,我们的模型抓住了主要概念。

对测试数据集的评估

现在让我们加载测试数据,并检查模型在其上的表现。

测试批次

[0.22433756291866302,0.44253026656767896,0.9837779402732849]

第一个值是 loss,第二个是非常接近验证值的 FBeta,最后一个是 fastai 库中的 Accuracy Multi。

测试数据的评估

当查看测试数据上的属性预测时,我会说预测的标签实际上比原始标签更好。

对用户指定数据集的评估

最后,我们将检查模型如何处理我的图像。我用智能手机相机拍了 98 张自己衣服的照片。让我们加载图像,并检查模型是否可以正确地对它们进行分类。

用户数据评估

分配的标签看起来非常好。尽管训练数据有噪声,但模型能够学习时尚概念,并对看不见的用户图像进行很好的概括。值得一提的是,我没有标记自己的数据集,因为这将是一项重大的工作。因此,我将使用训练好的模型来获取我自己的数据的标签。

摘要

在本文中,我演示了如何使用 Fastai 库和 DeepFashion 数据集训练一个多标签属性识别模型。

毫无疑问,通过提高训练标签的质量,可以显著提高模型的性能。然而,该模型已经能够提供足够的结果,即使在噪音数据。正如我们所看到的,有一些方法允许在持续改进训练数据质量的同时提供操作就绪的模型。这是一项重要的学习,因为许多组织由于数据质量而推迟了深度学习产品的开发。

感谢您阅读这篇文章!如有任何问题,请在下方留言或通过 LinkedIn 联系我。

如果你喜欢这篇文章,这里有一些你可能喜欢的其他文章:

posted @ 2024-10-18 09:27  绝不原创的飞龙  阅读(294)  评论(0)    收藏  举报