TowardsDataScience-博客中文翻译-2019-十三-
TowardsDataScience 博客中文翻译 2019(十三)
原文:TowardsDataScience Blog
协议:CC BY-NC-SA 4.0
在 Pyspark 中使用 MLlib 构建 ML 应用程序
原文:https://towardsdatascience.com/building-an-ml-application-with-mllib-in-pyspark-part-1-ac13f01606e2?source=collection_archive---------3-----------------------
本教程将指导您如何在 apache spark 中创建 ML 模型,以及如何与它们交互
介绍
Apache Spark 是一种按需大数据工具,全球许多公司都在使用它。它的内存计算和并行处理能力是这个工具流行的主要原因。
Spark Stack
MLlib 是一个可扩展的机器学习库,它与 Spark SQL、Spark Streaming 和 GraphX 等其他服务一起出现在 Spark 之上。
数据集相关介绍
在本文中,我们将专注于一个叫做笔画数据集的数据集。中风是一种流向大脑的血流停止或血流过多的情况。中风的危险因素有
- 吸烟
- 高血压
- 糖尿病
- 血液胆固醇水*高
- 酗酒
- 高脂肪(尤其是饱和脂肪)和高盐,但低纤维、水果和蔬菜的饮食
- 缺乏经常锻炼
- 肥胖
所以我这里得到了一个不错的数据集:https://bigml . com/user/Francisco/gallery/model/508 b 2008570 c 6372100000 B1 # info
以下是数据集:
Stroke Dataset
该数据集几乎包含了上述中风的所有风险因素。因此,选择具有适当风险因素的数据集非常重要。
我们将把列的字符串值变成数字值。这样做的原因将在后面解释。使用 Excel 中的替换功能,我将数据集更改为以下内容
- 性别列—男性=1,女性=0
2.吸烟史——从未=0,曾经=0.25,当前= 0.5,以前= 0.75,当前= 1.0
使用的服务和库
- Google cloud——我们将在 Dataproc 中建立我们的 spark 集群,并在 Jupyter 笔记本中编写代码
- Jpmml(pyspark2pmml) —用于将我们的模型转换成 pmml 文件。
- open scoring——一个为 PMML 模型评分的 REST web 服务。
- VS 代码——我们将使用 React JS 构建一个与 REST 服务器通信的交互式网站。
架构图:
下图展示了我们整个项目的简要架构。
The architecture diagram of our project
步骤 1:设置谷歌云
Google cloud 有一个名为 Dataproc 的服务,用于创建预装 Apache Spark 的集群。我们可以随时调整集群的大小。谷歌云提供免费的 300 美元信用作为入门优惠。因此,我们将使用这些免费配额来建立我们的集群。
Google Cloud Console
点击“激活”获得 300 美元的免费点数。
Registration Step-1
选择您的国家,然后点击“继续”。在下一页,您将被提示输入您的帐单细节和信用卡或借记卡细节。填写它们,然后点击底部的按钮。
Google Cloud Console - Dataproc
将打开控制台页面。在页面顶部,在搜索栏中键入 Dataproc,上面的页面就会打开。单击 create a cluster 开始创建集群。
GC — Creating a cluster-1
GC — Creating a cluster-2
GC — Creating a cluster-3
请确保您输入了与上述相同的设置。点击高级选项,按照上面的图像设置,然后点击创建。创建一个集群可能需要 2 到 3 分钟。
Google cloud — Dataproc clusters
导航到群集,然后单击虚拟机实例。在 VM 实例下,我们可以看到创建了一个主节点和两个工作节点。主节点的作用是它通常请求集群中的资源,并使它们对 spark 驱动程序可用。它监视和跟踪工作节点的状态,这些工作节点的工作是托管 executor 进程,该进程存储来自任务的输出数据并托管 JVM。详细描述可以在这里找到
现在单击主节点的 SSH 按钮。
SSH
一个新的终端在一个新的 chrome 标签中打开。这是命令行界面,通过它我们可以与我们的集群进行交互。键入“pyspark”检查 spark 上的安装及其版本。确保 spark 版本在 2.2 以上,python 版本为 3.6。
Firewall Rules
现在设置 jupyter 笔记本,我们需要创建一个防火墙规则。按照图片设置新的防火墙规则。确保在协议和端口中选择“全部允许”。
Firewall Rules
点击保存并导航至“外部 IP 地址”。
External IP addresses
将“spark-cluster-m”的类型改为静态。给出任意一个名字,点击“保留”。
现在导航到“SSH”并键入以下命令。
sudo nano ~/.jupyter_notebook_[config.py](https://www.youtube.com/redirect?event=comments&stzid=UgwMLhVicKWXmwMzyJ54AaABAg&q=http%3A%2F%2Fconfig.py%2F&redir_token=7XHzrHJ0cqu2HG4iRpSCumF2asJ8MTU2MDUzMTgyMEAxNTYwNDQ1NDIw)
复制下面的线并粘贴它。按 CTRL+o,回车,CTRL+x。
c=get_config()c.NotebookApp.ip=’*’c.NotebookApp.open_browser=Falsec.NotebookApp.port=5000
现在我们可以通过下面的命令打开 jupyter 笔记本
jupyter-notebook --no-browser — port=5000
在 SSH 中键入上述命令,然后打开一个新的选项卡,并在 google chrome 中键入“https://localhost:5000”以打开 Jupyter notebook。在我的例子中,本地主机是 35.230.35.117
Jupyter Notebook
第二步:在 Jupyter 笔记本的 Pyspark 中编码
在进入这一部分之前,我们需要安装一些外部库。
我们需要 Imblearn 库来执行 SMOTE,因为我们的数据集高度不*衡。更多关于 smote 的信息可以在这个链接中找到。
在 SSH 中,键入
sudo -i
然后键入下面一行
conda install -c glemaitre imbalanced-learn
退出根文件夹,然后打开 Jupyter 笔记本。开始编码吧。
导入重要库
from pyspark.sql import SQLContext
from pyspark.sql import DataFrameNaFunctions
from pyspark.ml import Pipeline
from pyspark.ml.classification import DecisionTreeClassifier
from pyspark.ml.classification import LogisticRegression
from pyspark.ml.feature import Binarizer
from pyspark.ml.feature import OneHotEncoder, VectorAssembler, StringIndexer, VectorIndexer
from pyspark.ml.classification import RandomForestClassifier
from pyspark.sql.functions import avgimport pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inlinefrom pyspark.ml.evaluation import MulticlassClassificationEvaluator
from pyspark.mllib.evaluation import MulticlassMetrics
from pyspark.ml.evaluation import BinaryClassificationEvaluatorfrom imblearn.over_sampling import SMOTE
from imblearn.combine import SMOTEENN
from sklearn.model_selection import train_test_split
from collections import Counter
现在我们需要创建一个 spark 会话。
from pyspark.context import SparkContext
from pyspark.sql.session import SparkSession
sc = SparkContext(‘local’)
spark = SparkSession(sc)
我们需要从存储中访问我们的数据文件。导航到 google 云控制台中的“bucket”并创建一个新的 bucket。我命名为“data-stroke-1 ”,并上传修改后的 CSV 文件。
Google Cloud Bucket
现在我们需要加载已经上传到我们的 bucket 中的 CSV 文件。
input_dir = ‘gs://data-stroke-1/’
df = spark.read.format(‘com.databricks.spark.csv’).options(header=’true’, inferschema=’true’).load(input_dir+’stroke.csv’)
df.columns
我们可以通过使用下图所示的命令打印数据帧来检查它。
现在,我们需要创建一个列,其中包含所有负责预测中风发生的特征。
featureColumns = [‘gender’,’age’,‘diabetes’,‘hypertension’,
‘heart disease’,‘smoking history’,‘BMI’]
确保所有列都是双精度值。接下来,让我们删除所有 2 岁以下的条目。
df = df.filter(df.age >2)
df.count()
现在让我们打印一个条形图来检查数据中存在的类的类型
responses = df.groupBy(‘stroke’).count().collect()
categories = [i[0] for i in responses]
counts = [i[1] for i in responses]
ind = np.array(range(len(categories)))
width = 0.35
plt.bar(ind, counts, width=width, color=’r’)
plt.ylabel(‘counts’)
plt.title(‘Stroke’)
plt.xticks(ind + width/2., categories)
步骤 3:数据预处理
步骤 3A。缺失数据管理
现在,进行适当的缺失数据管理以最终得到一个非常好的模型是非常重要的。使用“df.na.drop()”并不总是好的,它会删除所有丢失数据的行。用适当合理的价值观来填充它们是我们可以实现的一个想法。
如我们所见,我们在身体质量指数列和吸烟史列中缺少值。填充这些身体质量指数值的一种可能方法是使用年龄值来填充它们。
taken from — https://dqydj.com/bmi-distribution-by-age-calculator-for-the-united-states/
对于吸烟史,很难找到合理的数值来填补。通常情况下,16 岁以下的人对吸烟并没有那么上瘾,因此我们可以用 0 来填充那些年龄组的人的值。年龄在 17 到 24 岁之间的人一生中可能至少尝试过一次吸烟,所以我们可以给这些人 0.25 的价值。现在,一些人过了一定年龄就戒烟了,即使他们有健康问题,也很少有人继续吸烟。我们不能决定给它们取什么值,所以默认情况下,我们给它们赋值 0。
我们既可以删除这些列中缺少值的所有行,也可以按照上面的逻辑填充这些行。但是出于本教程的目的,我已经用上面的逻辑填充了丢失的行,但是实际上篡改数据而没有数据驱动的逻辑来备份通常不是一个好主意。
我们将对此数据帧执行一些操作,而 spark 数据帧不支持任何操作。因此,我们将我们的数据帧复制到熊猫数据帧,然后执行操作。
imputeDF = dfimputeDF_Pandas = imputeDF.toPandas()
我们将根据年龄将完整的数据帧分成许多数据帧,并用合理的值填充它们,然后,将所有数据帧合并成一个数据帧,并将其转换回 spark 数据帧。
df_2_9 = imputeDF_Pandas[(imputeDF_Pandas[‘age’] >=2 ) & (imputeDF_Pandas[‘age’] <= 9)]
values = {‘smoking history’: 0, ‘BMI’:17.125}
df_2_9 = df_2_9.fillna(value = values)df_10_13 = imputeDF_Pandas[(imputeDF_Pandas[‘age’] >=10 ) & (imputeDF_Pandas[‘age’] <= 13)]
values = {‘smoking history’: 0, ‘BMI’:19.5}
df_10_13 = df_10_13.fillna(value = values)df_14_17 = imputeDF_Pandas[(imputeDF_Pandas[‘age’] >=14 ) & (imputeDF_Pandas[‘age’] <= 17)]
values = {‘smoking history’: 0, ‘BMI’:23.05}
df_14_17 = df_14_17.fillna(value = values)df_18_24 = imputeDF_Pandas[(imputeDF_Pandas[‘age’] >=18 ) & (imputeDF_Pandas[‘age’] <= 24)]
values = {‘smoking history’: 0, ‘BMI’:27.1}
df_18_24 = df_18_24.fillna(value = values)df_25_29 = imputeDF_Pandas[(imputeDF_Pandas[‘age’] >=25 ) & (imputeDF_Pandas[‘age’] <= 29)]
values = {‘smoking history’: 0, ‘BMI’:27.9}
df_25_29 = df_25_29.fillna(value = values)df_30_34 = imputeDF_Pandas[(imputeDF_Pandas[‘age’] >=30 ) & (imputeDF_Pandas[‘age’] <= 34)]
values = {‘smoking history’: 0.25, ‘BMI’:29.6}
df_30_34 = df_30_34.fillna(value = values)df_35_44 = imputeDF_Pandas[(imputeDF_Pandas[‘age’] >=35 ) & (imputeDF_Pandas[‘age’] <= 44)]
values = {‘smoking history’: 0.25, ‘BMI’:30.15}
df_35_44 = df_35_44.fillna(value = values)df_45_49 = imputeDF_Pandas[(imputeDF_Pandas[‘age’] >=45 ) & (imputeDF_Pandas[‘age’] <= 49)]
values = {‘smoking history’: 0, ‘BMI’:29.7}
df_45_49 = df_45_49.fillna(value = values)df_50_59 = imputeDF_Pandas[(imputeDF_Pandas[‘age’] >=50 ) & (imputeDF_Pandas[‘age’] <= 59)]
values = {‘smoking history’: 0, ‘BMI’:29.95}
df_50_59 = df_50_59.fillna(value = values)df_60_74 = imputeDF_Pandas[(imputeDF_Pandas[‘age’] >=60 ) & (imputeDF_Pandas[‘age’] <= 74)]
values = {‘smoking history’: 0, ‘BMI’:30.1}
df_60_74 = df_60_74.fillna(value = values)df_75_plus = imputeDF_Pandas[(imputeDF_Pandas[‘age’] >75 )]
values = {‘smoking history’: 0, ‘BMI’:28.1}
df_75_plus = df_75_plus.fillna(value = values)
组合所有数据帧
all_frames = [df_2_9, df_10_13, df_14_17, df_18_24, df_25_29, df_30_34, df_35_44, df_45_49, df_50_59, df_60_74, df_75_plus]
df_combined = pd.concat(all_frames)
df_combined_converted = spark.createDataFrame(df_combined)
imputeDF = df_combined_converted
步 3B。处理不*衡数据
我们将执行 SMOTE 技术来处理不*衡数据。SMOTE 可以从这里引用:
X = imputeDF.toPandas().filter(items=[‘gender’, ‘age’, ‘diabetes’,’hypertension’,’heart disease’,’smoking history’,’BMI’])
Y = imputeDF.toPandas().filter(items=[‘stroke’])X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.1, random_state=0)
sm = SMOTE(random_state=12, ratio = ‘auto’, kind = ‘regular’)x_train_res, y_train_res = sm.fit_sample(X_train, Y_train)print(‘Resampled dataset shape {}’.format(Counter(y_train_res)))
请参考此链接了解参数
X_train 包含除 Stroke 列之外的所有数据列。
Y_train 包含笔画列数据。
将重新采样的数据组合成一个火花数据帧
dataframe_1 = pd.DataFrame(x_train_res,columns=[‘gender’, ‘age’, ‘diabetes’, ‘hypertension’, ‘heart disease’, ‘smoking history’, ‘BMI’])
dataframe_2 = pd.DataFrame(y_train_res, columns = [‘stroke’])# frames = [dataframe_1, dataframe_2]
result = dataframe_1.combine_first(dataframe_2)
将其改回火花数据帧
imputeDF_1 = spark.createDataFrame(result)
检查重新采样的数据。这与我们之前使用的代码相同。
如我们所见,我们成功地对数据进行了重新采样。现在我们将进入下一部分。
第四步。构建 Spark ML 管道
下面是一个 spark ml 项目的通用管道,除了我们没有使用字符串索引器和 oneHotEncoder。
Spark ML Pipeline
现在要构建一个汇编器,为此,我们需要一个二进制化器。
binarizer = Binarizer(threshold=0.0, inputCol=”stroke”, outputCol=”label”)
binarizedDF = binarizer.transform(imputeDF_1)binarizedDF = binarizedDF.drop(‘stroke’)
这将创建一个名为“label”的新列,其值与 stroke 列中的值相同。
assembler = VectorAssembler(inputCols = featureColumns, outputCol = “features”)
assembled = assembler.transform(binarizedDF)print(assembled)
汇编程序将预测笔画所需的所有列组合起来,产生一个称为特征的向量。
现在开始拆分数据
(trainingData, testData) = assembled.randomSplit([0.7, 0.3], seed=0)
print(“Distribution of Ones and Zeros in trainingData is: “, trainingData.groupBy(“label”).count().take(3))
培养
dt = DecisionTreeClassifier(labelCol="label", featuresCol="features", maxDepth=25, minInstancesPerNode=30, impurity="gini")
pipeline = Pipeline(stages=[dt])
model = pipeline.fit(trainingData)
测试
predictions = model.transform(testData)
AUC-ROC
from pyspark.mllib.evaluation import BinaryClassificationMetrics as metric
results = predictions.select(['probability', 'label'])
## prepare score-label set
results_collect = results.collect()
results_list = [(float(i[0][0]), 1.0-float(i[1])) for i in results_collect]
scoreAndLabels = sc.parallelize(results_list)
metrics = metric(scoreAndLabels)
print("Test Data Aread under ROC score is : ", metrics.areaUnderROC)
from sklearn.metrics import roc_curve, auc
fpr = dict()
tpr = dict()
roc_auc = dict()
y_test = [i[1] for i in results_list]
y_score = [i[0] for i in results_list]
fpr, tpr, _ = roc_curve(y_test, y_score)
roc_auc = auc(fpr, tpr)
%matplotlib inline
plt.figure()
plt.plot(fpr, tpr, label='ROC curve (area = %0.2f)' % roc_auc)
plt.plot([0, 1], [0, 1], 'k--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic Graph')
plt.legend(loc="lower right")
plt.show()
AUC — ROC Curve
正如我们所看到的,我们得到了 98 左右的 AUC-ROC 分数,这是非常好的。由于 SMOTE 技术的使用,模型可能会过拟合。(但是逻辑回归对这个数据集很有效。但是 pyspark2pmml 库中似乎有一些错误,不能正确导出逻辑回归模型。)因此,出于演示目的,我将使用决策树模型文件。
第五步。保存模型文件
为此,我们将使用一个名为 PySPark2PMML 的库,它的细节可以在这里找到(https://github.com/jpmml/pyspark2pmml)
保存 jupyter 文件并退出 jupyter 笔记本。
从https://github.com/jpmml/jpmml-sparkml/releases下载jpmml-spark ml-executable-1 . 5 . 3 . jar文件
上传到 SSH
上传后,如果我们运行“ls”命令检查,我们会看到我们的文件。
现在我们需要设置 jupyter notebook,当我们在 ssh 中键入 pyspark 时,我们需要打开 jupyter notebook。为此,我们需要更改环境变量。
更新 PySpark 驱动程序环境变量:
将下面几行添加到您的~/.bashrc
(或~/.zshrc
)文件中。按“I”插入新行。复制下面的代码并使用“CTRL+V”粘贴它。
export PYSPARK_DRIVER_PYTHON=jupyter
export PYSPARK_DRIVER_PYTHON_OPTS='notebook'
要保存并退出 vi 编辑器,请按“ESC”和“:wq”保存。
重启你的终端,然后输入“pyspark”。你应该可以运行 jupyter 笔记本。
您应该能够在其中一行中看到端口号。
现在要使用 pmml 库,通过调用下面的命令打开 jupyter 笔记本。
pyspark --jars /home/yashwanthmadaka_imp24/jpmml-sparkml-executable-1.5.3.jar
打开 jupyter 笔记本后,运行我们之前写的所有单元格。现在,添加下面这段代码。
trainingData = trainingData.drop(“features”)from pyspark.ml.feature import RFormula
formula = RFormula(formula = "label ~ .")
classifier = DecisionTreeClassifier(maxDepth=25, minInstancesPerNode=30, impurity="gini")
pipeline = Pipeline(stages = [formula, classifier])
pipelineModel = pipeline.fit(trainingData)from pyspark2pmml import PMMLBuilder
pmmlBuilder = PMMLBuilder(sc, trainingData, pipelineModel) \
.putOption(classifier, "compact", True)pmmlBuilder.buildFile("dt-stroke.pmml")
运行上述代码后,将在提到的位置创建一个新文件。将这个文件下载到您的本地桌面,让我们开始构建一个网站来与我们的模型文件进行交互。
整个 jupyter 笔记本可以在这里找到。
第六步。构建一个前端 ReactJS 应用程序与 PMML 文件交互。
步骤 6a。从我们的模型文件构建一个 REST 服务器:
对于与模型文件交互的应用程序,我们需要将应用程序公开为 REST web 服务。为此,我们将借助 Openscoring 库。
我们需要使用 maven 安装 Openscoring。确保将我们从 Google clouds 虚拟机下载的模型文件放入PATH/open scoring/open scoring-client/target 文件夹。
其中 PATH = open scoring 文件所在的路径。
安装后,我们需要按照下面的命令启动服务器。
首先,通过进入服务器文件夹并键入下面的命令来启动服务器
cd openscoring-server/targetjava -jar openscoring-server-executable-2.0-SNAPSHOT.jar
接下来,打开客户端文件夹,输入下面的命令。接下来,打开一个新的 cmd 并键入以下命令。
cd openscoring-client/targetjava -cp openscoring-client-executable-2.0-SNAPSHOT.jar org.openscoring.client.Deployer --model [http://localhost:8080/openscoring/model/stroke](http://localhost:8080/openscoring/model/stroke) --file dt-stroke.pmml
当我们访问http://localhost:8080/open scoring/model/stroke时可以看到下面的结构
步骤 6b。下载 ReactJS 前端并运行:
现在访问 this Github 链接并克隆这个项目。
下载后,使用 VS 代码打开这个项目文件夹。打开里面的终端,输入
npm install
在启动 ReactJS 应用程序之前,我们需要启用 CORS。为此,我们可以添加一个 chrome 扩展。
打开 CORS 后,在 VS 代码终端中键入以下命令。
npm start
将打开一个 web 界面,如下所示。
ReactJS Frontend
我们可以输入任何值并测试它。我们会得到预测,中风发生的概率和不发生中风的概率。
所有与 REST 服务器交互的方法都编码在 index.js 文件中。
附言
现实模型的 98 分是不可能达到的,这个博客的主要意义是展示如何与 pyspark 制作的 ML 模型进行交互。
我们的数据预处理越好,我们的模型就越好。模型的质量直接取决于我们使用的数据的质量和多样性。因此,最好花更多的时间进行适当的数据清理和数据过滤技术。
有用的链接
- SMOTE—https://medium . com/coin monks/SMOTE-and-adasyn-handling-unbalanced-data-set-34f 5223 e167
- pyspark 2 pmml—https://github.com/jpmml/pyspark2pmml
- 开场得分—https://github.com/openscoring/openscoring
- ReactJs 前端—https://github.com/yashwanthmadaka24/React-Js-Website
现在,是休息的时候了😇
在两周内构建和部署数据科学项目
原文:https://towardsdatascience.com/building-and-deploying-a-data-science-project-in-two-weeks-3c63f0acdab1?source=collection_archive---------21-----------------------
数据科学冲刺
通过构建有趣的东西来学习自然语言处理、Flask 和 ML 模型部署的基础知识!
End product: a sentiment analysis web application with built-in ongoing learning capacity
我是一个动觉型学习者;我通过做、建造和破坏东西来学习。在这篇文章中,我将分享我如何建立一个基本的情感分析机器学习模型+web 应用程序,并在不到两周的时间内部署它,以学习三种新技术-自然语言处理(NLP),flask 和增量/持续学习。
学习成果
我从事这项事业的主要目标如下:
- 学习 NLP 基础知识并训练情感分析分类器
- 了解如何使用 flask 构建 web 应用程序
- 了解基于 ML 的 web 应用程序部署
我想以一种快速构建/学习的模式来完成这一切,重点是功能性,而不是美观性。我最终探索和学习的一些其他主题包括模型优化、增量/持续学习和 jQuery。本文使用的所有 Jupyter 笔记本和代码都可以在我的 Github 上找到。
数据集
对于这个项目,我需要一个数据集,它包含文本数据,但已经被标记和结构化。这将使我能够专注于基于 NLP 的预处理,同时浏览其他形式的数据准备。在看了几个不同的选项后,我最终选择了 yelp 评论数据集,因为它是预先标记的(文本评论和 1-5 星评级),但评论中的实际文本是混乱和不一致的。您可以从下面的原始 JSON 数据集中看到一个示例记录
Example record from raw JSON data
对于我的模型,我只对文本评论和 1-5 颗星感兴趣(也许将来我可以尝试用其他属性做一些有趣的事情)。此外,为了进一步简化我的培训流程并坚持快速发展的心态,我决定将标签从 1-5 分修改为与文本审查相关的积极(4 或 5 星)或消极(1 或 2 星)情绪。我放弃了 3 星评级的评论,因为它们的分类很难验证。几行代码之后,我把我的数据放在一个熊猫的数据框架中,如下图所示
Pandas dataframe with just the text review and positive/negative sentiment
这个文本有许多潜在的问题。有些字符如 *** 和 \n 对帮助理解文本没有实际作用,而其他字符如 $ 和!,可以洞察评价者的感受。此外,有许多人类可以理解的单词/俚语(8Gs = 8000 美元),但对机器来说几乎没有意义。所有这些以及更多的场景将在下一节中解决。
自然语言处理流水线
为了准备分类数据,我们必须首先设计一个 NLP 管道来准备文本数据。NLP 管道涉及几个步骤,其中一些步骤如下所示
Sample NLP Pipeline
在我们的例子中,像词性标注和命名实体识别这样的步骤不是很有用,因为手头的任务是一个样本分类问题。因此,我们将把重点放在最划算的技术上:标记化、停用词去除和 ngram 利用(下面讨论)。
对于我的 NLP 模型的第一次迭代,我决定使用 sklearn 的CountVectorizer()
方法实现一个简单的单词袋模型,并在大约 100,000 行上训练它。我利用 sklearn 的train_test_split()
方法将我的数据分解成训练和测试块。在尝试了一些不同的分类器(如逻辑回归、多项式朴素贝叶斯和线性支持向量机)后,我发现逻辑回归模型最适合这些数据。这是各个分类器的混淆矩阵-
Confusion Matrices for the various classifiers
进一步思考,我发现逻辑回归模型将无法在项目后期利用增量学习,而线性 SVM(由 sklearn 的SGDClassifier()
提供支持)可以。精确度的折衷很小,逻辑回归的*均 F1 值为 93%,而 SVM 的*均 F1 值为 92%。因此,我决定继续进行线性 SVM,以便在项目后期利用增量学习。
另外,我选择用HashingVectorizer()
替换CountVectorizer()
,因为它使用一种叫做哈希的技术来将输入处理模型的大小减少 99%。唯一的主要损失是失去了查看模型中显式单词的能力(哈希将所有单词转换为数字),这对我来说不是一个大问题。你可以在这里阅读更多关于这款车型的信息。
模型优化
我做了一些事情来优化我的模型。正如你从上面的困惑矩阵中看到的,我的培训和测试数据中负面评价的数量都比正面评价少。这导致我的负标签 F1 分数为 82%,正标签 F1 分数为 94%。为了减少这种差异,我必须通过确保对应于两个标签的记录数量是可比较的来*衡我的数据集。在*衡我的数据集后,我开始省略停用词,如和,一个等。从单词袋模型来看。
在这两个步骤之后,我的模型的 F1 分数从 92%下降到 91%,但是之前两个标签之间的差距变小了。我的负面和正面评论的 F1 分数分别是 91%和 90%,所以总体上分类器表现更好。接下来,我决定利用 ngrams 来进一步优化我的模型。
Ngrams 简单地指的是一组连续的 n 个共现的单词。比如说-
In the sentence "I love data science", the 1-grams would be ["I", "love", "data", "science"]. The 2-grams would be ["I love", "love data", "data science"] and so on.
从上面的例子中,您甚至可以看出为什么使用 ngrams 会有所帮助。出现在一个句子中的两个单词“数据科学”会比一个单词“数据”和“科学”提供更多的信息。现在,回到优化:我利用 1.2 克来进一步加强我的模型。优化前后的混淆矩阵如下-
Before and after the ngram optimization
正如您所看到的,这是一个重大的改进,因为正面和负面的错误猜测都减少了。该模型的最终 F1 分数上升到 92%,两个班级之间的差距可以忽略不计。此时,模型已经准备好。接下来,增量/持续学习。
增量学习
正如你们已经看到的,我们的情感分类模型远非完美。这就是增量学习的魅力所在。
增量学习是一种机器学习范式,其中每当新的示例出现时就进行学习过程,并根据新的示例调整已经学习的内容。
如果你想一想人类是如何学习语言的,你会很快发现他们是在渐进地学习。每当父母纠正一个孩子,老师纠正一个学生,或者两个朋友互相纠正,一种增量学习的形式就发生了。在这一节中,我们将为我们的 NLP 模型构建一个类似的系统,这样当它出现分类错误时,用户可以“纠正”它。
还记得我们之前因为这个功能选择了 SGDClassifier()吗?SGDClassifier 有一个内置的partial_fit()
方法,它将帮助我们用几行代码实现增量学习,如下所示
# Incremental training# example x
X_instance = cv.transform(["I like this place, but not much"]) # user determined label
y_instance = ['n']# max iterations of training until the classifier relearns
max_iter = 100# loop for a maximum of max_iter times
# partially fit the classifier over the learning instance
# stop when classifier relearns (or max_iter is reached)
for i in range (0,max_iter):
clf.partial_fit(X_instance, y_instance)
if(clf.predict(X_instance) == y_instance):
break
利用这一点,无论何时出现错误,我们都可以在新数据上训练我们的模型,同时仍然保持初始训练。下面可以看到一个例子——
Example of incremental learning
总结和第 2 部分
到目前为止,我们已经取得了相当大的成就:我们已经创建了一个基本的 NLP 分类器,它可以读取一段文本,并将情绪分为积极或消极。我们已经使用停用词和 ngrams 等 NLP 技术优化了我们的模型,以实现 92%的基线 F1 得分。最后,我们已经编写了代码来增量训练我们的分类器,只要它出错,学习就不会停止!
在下一部分中,我们将在前面介绍的基础上,使用 Flask 构建一个基本的 web 应用程序。特别是,我们将构建 API 来对用户输入的文本进行分类,并逐步教授/纠正我们的模型。这将使我们能够作为用户与我们的模型进行交互,并进一步了解机器学习模型部署!
我希望你喜欢读这篇文章,就像我喜欢把它放在一起一样。如果您有任何问题、反馈或意见,请随时通过 LinkedIn 或我的网站与我联系。
[1]:耿 x .,史密斯-迈尔斯 K. (2009)增量学习。载于:李世泽,贾恩(编)《生物识别百科全书》。马萨诸塞州波士顿斯普林格
在 Azure 上使用自动化 ML 构建和部署机器学习模型。
原文:https://towardsdatascience.com/building-and-deploying-a-machine-learning-model-with-automated-ml-on-azure-b586a0e7d448?source=collection_archive---------17-----------------------
Overview of the automated machine learning process.
这篇文章讲述了使用 Azure 的自动化机器学习功能的基础知识。我们将训练和部署一个可操作的机器学习模型。在这篇文章之后,你将能够构建一个端到端的解决方案来部署一个机器学习模型,而无需编写任何代码。
目标是帮助您理解构建和部署机器学习模型的基础。它不会涵盖建模技术/最佳实践、安全性/授权等概念,但对于以下人员来说是一个起点:(1)希望在不编码的情况下构建 ML 模型,或者(2)希望了解自动化机器学习的可能性以及这对您和您的组织有何价值。
在这个练习中,我们将使用微软 Azure 的自动机器学习*台。我们设置环境/资源,在数据集上训练多个模型,并在 Azure 上部署这个模型,这样我们就可以实际使用它了。
本文共分三个部分:
1 .【无聊的东西】(在 Azure 中设置资源)
2。【酷玩意儿】(训练模特)
3。“我现在可以展示我的朋友”(部署模型)
所以事不宜迟,让我们来构建一些很酷的东西(又名 无聊的东西)!
建立
注意事项
使用 Azure 上的服务需要花钱。有办法获得免费学分或试用期(例如:通过 这个链接 )。)
整个实验花了我 3.02€(没有使用任何免费信用):
Total costs for Azure Automated Machine learning experiment.
在本文的最后,我们将介绍如何清理,这样我们就不会产生任何意外的成本。
让我们开始吧!
一笔账
(在此注册如果您还没有 azure 帐户,并确保您设置了支付方式,这应该是注册过程的一部分)。
注册后,你应该会看到你的默认 Azure 主页:
Azure Home Page
创建资源组
资源组是“保存 Azure 解决方案相关资源的容器”。它将帮助我们容易地区分属于我们的 ML 模型和部署的资源(,并将帮助我们以后容易地删除它)。**
从 Azure 主页,点击左侧菜单中的“资源组”并创建一个新的资源组:
Create new resource group in Azure Portal
在这个练习中,地区并不重要:根据你在这个世界上的位置选择一个。
创建机器学习服务工作区
Azure 机器学习服务是一个资源集合,可以帮助你创建、测试和部署机器学习模型。自动化 ML 是这个集合的一部分,这就是我们在这里使用的。确保将新资源分配给上面创建的“autoML”资源组。
Create new resource in Azure Portal
在这个练习中,地区并不重要:根据你在这个世界上的位置选择一个。
下载 数据集 。
在本文中,我们将构建一个回归模型来预测纽约市 AirBnB 的正确价格。数据来自 Kaggle,可通过链接获得。
我们现在可以把这个文件保存在本地:我们将在下一节把它上传到 Azure。
重述
我们已经为 Azure 创建了一个帐户,建立了一个资源组来组织我们与此练习相关的资源,并创建了一个 Azure 机器学习服务工作区,我们可以从我们的主页上看到:
A brand new ‘autoML’ workspace is visible under our recent resources (or by searching in the top bar)!
恭喜恭喜!我们已经做了无聊的事情!让我们赶紧过去做一些实际的数据相关的工作。
培养
在我们的 Azure 主页上,我们可以点击“autoML”资源进入资源页面。我们将通过点击“立即启动预览”横幅使用新界面,或者通过此链接直接进入新界面。所有的训练步骤都将在新的 Azure 机器学习界面上执行。
选择最*创建的订阅和 Azure 机器学习资源:
Your subscription and machine learning workspace.
上传数据集 导航至“数据集”(左侧菜单),上传解压缩后的数据集“Output.csv”,然后点击“创建数据集”。
从本地机器选择文件。所有其他设置可以保持原样。单击完成后,数据集将上传:
Uploading a dataset into Azure Machine Learning Services
现在,我们的数据集将从“数据集”页面可见:
datasets for Automated Machine Learning
创建并运行实验
从菜单中,转到“自动化 ML”并点击蓝色的“创建实验”按钮:
create automated machine learning experiment
在下一个屏幕中,我们必须提供一个名称和训练计算。你可能想知道“训练计算”是什么意思。我们想要训练的模型需要一台计算机来运行。Azure 提供虚拟计算机,这些计算机位于世界各地的大型数据中心。这使得我们可以在需要的时候启动任何大小的计算机,并在完成后再次关闭,只使用我们需要的东西。
在本练习中,我们将启动一个小型计算资源(虚拟机)。单击“创建新计算机”并为其命名,如 autoML。我们将使用默认的 标准 _DS12_V2 — — 4 个 vCPUs,28 GB 内存,56 GB 存储 (保留其他设置不变):
Creating a new compute. After clicking create it takes up to a few minutes to provision the resource.
当我们选择一个实验名称时(我选了——惊喜!-“autoML”)新计算已创建,请确保选择我们刚刚创建的培训计算,然后单击“next”。
接下来,我们选择之前上传的数据集,我们将被要求输入更多内容。现在,对于我们的用例,目标是根据数据集中的其他信息预测价格(目标列)。
Dataset settings for automated machine learning
我们可以检查 profile 选项卡来进行一些数据探索,但是为了简洁起见,我们将直接选择要包含的列,即预测任务和目标列:
Data model for Automated Machine Learning
首先,我们排除模型中不需要的列。您可能会在将来探索/包括其他专栏,但是按照本教程:选择与我所做的相同的专栏。我们包含的列有:邻居 _ 组、邻居、房间 _ 类型、价格(目标列* )、最低 _ 夜数、评论数、最后 _ 评论、每月评论数。*
我们正在预测一个数量(每晚的价格),所以我们的预测任务* 是回归,目标列 是价格。*
我们可以使用高级设置,在将来的实验中你可能会用到,但是现在我们让它保持原样。这意味着我们选择“Spearman 相关性”作为衡量和比较模型的主要指标。我们把培训工作时间设定为 30 分钟。
向下滚动,点击开始,恭喜你自己!您现在是数据科学家了!*
Azure 现在将增加合适的资源。之后,ML 的实际“自动化”部分开始了:Azure 将尝试并适应不同的模型和设置,以找到最适合我们的数据和练习类型(回归)。我们将很快开始看到不同的模型和它们的准确度分数。此外,在运行期间,我们不必停留在任何特定的页面上;所以请随意浏览 Azure ML 界面。
请记住,Azure 将需要一些时间来旋转资源并获得第一批模型的结果,因此整个过程需要的时间比我们选择的 30 分钟训练时间更长。
但是不要告诉你真正的数据科学家朋友和同事,因为他们可能不会同意。
排行榜
在实验运行期间和之后,我们可以通过排行榜查看每次运行的结果:
We can check out our experiment leaderboard! Here we can check out the different models that have been tested on our dataset.
通过点击任何已完成的迭代,我们可以看到一组更广泛的结果指标和图表:
Model results
一旦实验完成,我们可以四处看看,看看运行了什么类型的模型,它们的表现如何等等。之后我们将进入下一环节:部署
部署
酷!我们有一个排行榜和一个成功的模型。现在怎么办?我们还不能真正展示任何东西:我们希望给我们的模型输入列(如邻居、每月评论数和*均评论数),然后接收每晚价格的估计。进入本教程的“我现在可以展示我的朋友”部分!
为了获得每晚价格的估计,我们需要“部署”模型。这将成为一个“容器”,能够在指定的环境(python)上运行我们的模型代码(获胜的模型),并处理传入的请求。Azure 机器学习服务有一个非常棒的功能,包含在自动机器学习服务中,在部署时为我们做所有的工作:“部署最佳模型”。它在我们之前查看的排行榜页面上,以了解不同型号的表现。
使用您喜欢的任何部署名称和描述,并让评分脚本和环境脚本“自动生成”。点击部署,这将需要大约 20 分钟才能完成。
Deploying with Azure Automated Machine Learning
当我们的模型被部署时,这个模型将会出现在“模型”页面上。模型包括一个端点。API 端点通常被定义为“通信通道的末端”。这个定义本身并没有真正帮助我们(完全没有),但是请这样想:我们有一个模型,我们希望通过发送输入(我们在模型中包括的列)并获得输出(每晚价格的估计)作为回报来与这个模型进行通信。我们不能对我们的模型/端点抛出任何东西,然后期望得到正确的响应,所以下一步是找到我们的端点并向我们的模型发送一个 HTTP 请求!
当我们部署模型时,Azure ML services 创建了一个 python 脚本,该脚本已经部署在一个“容器”中。这个容器运行在 Azure cloud 的某个地方,现在可以接收来自我们的 HTTP 请求了。
为此,我们需要做三件事:
确定终点计分 URI
在 Azure ML 界面中,可以通过从左侧菜单转到“端点”来获得端点
Azure Automated machine learning endpoints.
我们单击我们新部署的模型,将会看到一个属性列表,其中相关的一个是“得分 URI”。**
The scoring URI in azure ml. Not showing up? Your deployment might not be fully completed yet. The Scoring URI shows up when the complete deployment is finished.
还记得谈论 API 端点吗?这个评分 URI 是我们已经创建的模型的端点,这意味着我们可以向这个端点(输入)发送(“做请求”)一些东西,并将接收一个响应(输出)。如果我们正确地格式化请求,我们将得到我们想要的:给定输入列的每晚估计价格。
创建一个 HTTP 请求
对于那些没有处理 HTTP 请求经验的人来说,这一部分可能会有点混乱,但是只要继续按照步骤操作,您就可以让它正常工作了!
从功能上来说,我们想要做的是发送一个 http 请求,在这里我们为已经包含在模型中的列输入值(除了目标列,当然这是我们想要返回的一列)。这意味着我们想发送以下信息:
“邻居 _ 组”、“邻居”、“房间 _ 类型”、“最低 _ 夜数”、“评论数”、“最后 _ 评论”、“每月评论数”。
这些信息被称为我们的 http 请求的“主体”, Azure 在他们的文档中描述了我们应该如何格式化这些信息以使其能够被模型解释:
REST API 期望请求的主体是一个 JSON 文档,其结构如下:
*{
"data":
[
<model-specific-data-structure>
]
}*
其中,我们的“特定于模型的数据结构”看起来像这样:
*{
"data": [
{
"neighbourhood_group": "Queens",
"neighbourhood": "Ridgewood",
"room_type": "Entire home/apt",
"minimum_nights": 3,
"number_of_reviews": 9,
"last_review": "2019-06-26T00:00:00.000Z",
"reviews_per_month": 2.1
}
]
}*
一个 HTTP 请求还包括一个或多个“头”,根据文档,我们需要添加一个“内容类型”头:
*“Content-Type” : “application/json”*
总而言之,基于:(1)端点/评分 URI,(2)正文(输入)和(3)标题,我们可以创建一个请求,该请求将返回(如果一切正常)每晚的估计价格!让我们来测试一下吧!
对于好奇的人(我假设你们所有人都做到了这一步):以下是完整的请求:
*POST /score HTTP/1.1
Host: *<scoring-uri>*
Content-Type: application/json
User-Agent: PostmanRuntime/7.17.1
Accept: */*
Cache-Control: no-cache
Postman-Token: *<token-value>*
Host: *<scoring-uri>*
Accept-Encoding: gzip, deflate
Content-Length: 335
Connection: keep-alive
cache-control: no-cache{
"data": [
{
"neighbourhood_group": "Queens",
"neighbourhood": "Ridgewood",
"room_type": "Entire home/apt",
"minimum_nights": 3,
"number_of_reviews": 9,
"last_review": "2019-06-26T00:00:00.000Z",
"reviews_per_month": 2.1
}
]
}*
这里面有一些我们没有涉及到的信息;不要担心,因为这对理解我们的端到端工作流并不重要。进行到最后一部分!
发送 HTTP 请求
此时,您已经有了一个可通过 API 端点(评分 URI)调用的部署模型。任何人(实际上是任何人,因为我们没有对 API 进行任何授权)都可以通过 API 端点在他们的应用程序、笔记本或其他(商业)应用程序中使用您的漂亮模型。当我从两个段落向上发送请求时,我得到以下结果:
*"{\"result\": [125.5851758821278]}"*
厉害!因此,这告诉我们,给定模型输入(Queens,Ridgewood,whole home/apt,3 晚,9 条评论,2019 年 6 月 26 日的最后一条评论,*均每月 2.1 条评论),估计每晚的价格将为 125.58 美元
很简单!显然你想看到这一点来相信它,所以我们开始吧:
下载邮差,API 开发免费 app。我们将使用 his 向我们的模型发送 HTTP 请求。一旦安装。我们将重复以下三个步骤:设置 URL(为 URI 评分)、添加内容类型标题和添加正文:
打开 Postman,从“新建”选项卡中选择“请求”:
Postman Create New Request
提供名称并创建收藏/文件夹,然后点击保存:
您将看到一个新屏幕,我们可以在其中创建 API 请求。
将“http 方法”设置为 POST,并在放置“输入请求 URL”占位符的位置复制评分 URI:
当我们转到 postman 中的“Body”选项卡时,我们采取两个动作:
1。将主体类型设置为“raw ”,并将类型设置为 JSON
2。将先前显示的请求中的请求列和值复制到正文字段:
*{
"data": [
{
"neighbourhood_group": "Queens",
"neighbourhood": "Ridgewood",
"room_type": "Entire home/apt",
"minimum_nights": 3,
"number_of_reviews": 9,
"last_review": "2019-06-26T00:00:00.000Z",
"reviews_per_month": 2.1
}
]
}*
Body and Response
我们之前讲的 header(“Content-Type”)是 postman 自动添加的,因为我们把 raw body 的类型设置为“JSON”。您可以在标题选项卡上看到这一点。
这意味着我们已经涵盖了请求的所有部分!是时候点击蓝色的发送按钮,完成我们的第一个请求了!
Postman response
你做到了!给自己一个击掌,放上你最喜欢的果酱(我推荐DMX——派对(在这里)为了这个场合)并向你自己的部署的自动机器学习模型发出几个请求!
当您准备好时,请确保删除资源组,这样您就不会在 Azure 上产生任何意外费用:
Delete Azure Resource group
考虑和想法
通过阅读本教程,您可能已经注意到,当涉及到使数据科学可操作时,有相当多的工作不一定与数据科学相关。我坚信对于任何数据工作者来说,实验都是有价值的。我们有一套令人惊叹的云服务提供商(开源)框架,可以快速轻松地开始测试新想法。最重要的是入门!**
何时使用自动化 ML
似乎有一场关于自动化机器学习的持续辩论,人们大致分为两类:“那不是数据科学!”以及“我们根本不再需要数据科学家了!”。真相可能介于两者之间,但需要一定的细微差别。
它总是依赖于您的特定需求和可用的能力,但是考虑到您在选择 autoML 供应商/框架时拥有的选择数量以及它得到的关注数量,我们可以有把握地假设它会一直存在。
我认为了解并可能应用自动化 ML 将有助于组织利用新技术,这可能是有价值的,尤其是在以下情况下:
- 您没有数据科学团队或者想要通过自动化“更简单”的数据科学任务来利用稀缺的数据科学资源。
- 您想要迭代完整的端到端流程,以便快速开发分析用例。我们应该将时间分配到流程的所有部分,而不仅仅是建模部分,以确保我们最终得到的解决方案不仅准确,而且有效(可操作)。
- 你想建立一个‘基线模型’。自动化的 ML 模型不一定是最终的模型。
我希望这是一个对你开始自动机器学习有用的教程!请在回复中留下你的想法/建议!
(随意伸手上LinkedIn也是)。**
建议进一步阅读:
不同的自动化 ML 解决方案—https://medium . com/@ santiagof/auto-is-the-new-black-Google-automl-Microsoft-automated-ML-autokeras-and-auto-sk learn-80 D1 d 3c 3005 c
数据科学方法论—https://medium . com/forward-artificial-intelligence/the-Data-Science-methodology-50d 60175 a06a
为数据科学项目构建和标注影像数据集
原文:https://towardsdatascience.com/building-and-labeling-image-datasets-for-data-science-projects-ab59172e46b4?source=collection_archive---------9-----------------------
构建影像数据集的一些提示和技巧
使用标准化数据集对于新模型/管道的基准测试或竞争非常有用。但对我来说,至少当你把东西应用到你自己选择的项目中时,数据科学的许多乐趣就来了。这个过程的一个关键部分是建立一个数据集。
所以有很多方法可以建立图像数据集。对于某些事情,我只是合理地截取了一些截图,比如当我生病的时候,用《闪电侠》第四季建立了一个面部识别数据集,并用 labelimg 对其进行了注释。我采取的另一条路线是手动下载一堆图像,只显示图像并在 excel 电子表格中标记它们……对于某些项目,你可能只需要用手机拍一堆照片,就像我制作骰子计数器时的情况一样。
这些天来,我想出了更多的技巧,使这一过程变得更容易一些,并一直在努力改进。
获取数据集的方法:
我下载图片管道中的第一个重大升级是使用一些基于 PyimageSearch 教程的 javascript 从谷歌获取图片 URL,并为圣诞老人探测器制作数据集。
这个的主要思想是你可以使用搜索作为那个类别的“标签”。所以你可以在谷歌上搜索圣诞老人,拉下这些网址,下载这些图片,用“圣诞老人”作为标签。这个过程非常好,我已经在一些个人项目中使用过。但是我们在技术上可以做得更好,另一个 PyimageSearch 教程为此铺*了道路。
作为前一种必须手动搜索并输入 javascript 的方法的替代方法,PyimageSearch 提供了另一个使用 Bing 搜索 api 快速制作图像数据集的教程这里。这是一个我非常喜欢的方法,它很容易与 Bing api 交互,以自动化的方式收集大量的图像非常好。我只在试用期间玩过 Bing API,但对结果很满意,所以如果真的是这样,我可能会根据需要付费。
这两种方法都可以让你相当快速地下载图像,如果你只是在做一个多类类型的问题,那么你已经有你的标签了。然而,需要采取一些额外的步骤来清理数据集,这种标注方法在多任务或多标签类型问题的情况下帮助不大。
下载完图像后
对于这两种方法,你通常每次搜索只能得到几百张与你给的搜索词相关的图片。我根据 PyimageSearch 教程采取了几个步骤。
- 过滤掉小图片:当我下载图片时,我会检查它们的大小,过滤掉低于某个阈值的图片,比如任何一边低于 300 像素。由于大多数图像模型拍摄的图像介于 224x224 和 512x512 之间,这有助于剪切掉您可能已经提取的超低质量图像
- 消除重复:如果看起来有很多完全相同的内容,你可以使用 Resnet18 之类的工具,通过检查重复的特征向量,把它们过滤掉。这在大型数据集上不是最实用的,但当有 1-10K 影像时,也不是那么糟糕。这样做的想法是,复制的图像可能会允许模型在性能指标上“作弊”,如果它们被放入训练和测试分割中,那么如果可能的话减少它们是好的。相位化是另一种潜在的重复数据删除方法,但由于图像的尺寸缩小得相当小,并且变成了黑白图像,因此非重复图像可能会出现重复,因此需要权衡。
- 手动修剪…这不是最有趣的活动,但非常重要。在我摄影的日子里,我最喜欢使用的工具是 adobe bridge,据我所知,我似乎可以在新的 adobe 系统上免费使用它。不过,我也只是在 Windows 或 Mac 的 Finder 中用大图标做了这些。这是尝试从数据集中的不同类中移除低质量或不相关的数据。我发现这一步有点级联到最终模型和类的质量,所以如果你想要定义良好的类,我建议在删除图像时要非常积极。
Sample adobe bridge review mode with critical role!
我喜欢 adobe bridge 的原因之一是,我基本上可以用箭头键过滤图像,并使用向下箭头扔掉图像。当你完成审查模式时,你剩下的所有你没有丢弃的图像仍然被选中,所以我通常只是把它们复制到一个新的目录中,这个目录只包含干净的图像。对于一个项目,我在一两个小时内看完了 7K 张图片……如果使用默认的 Mac 界面,时间会长得多。
标记
因此,使用 PyimageSearch 方法,如果你正在处理一个简单的多任务问题,那么你可以为你下载的每一组 URL 标记标签,并将它们用作类别标签。然而,根据项目的类型,除了那些基本的类名之外,你可能还需要额外的标签。
对于我使用的管道对象检测模型,我更喜欢 labelimg ,它有一组很好的热键,这样你就可以很快地通过标注数据集。
对于图像分割,我使用来自牛津的注释器,通过 (VGG 图像注释器)。我猜他们是发明 VGG 建筑的牛津小组?
直到最*,我还没有真正想出在一张图片上标注多个标签的好方法,但是一位同事向我展示了一个叫做鸽子的注释器。它有很好的功能来注释 jupyter 笔记本中的图像和文本数据,用于标准的多类分类或回归类型问题。这个图书馆很酷,建造这个图书馆归功于阿格马尼迪斯。
Sample pigeon usage for image classification
然而,我不怎么处理回归,也很少需要构建直接的多类数据集,因为我可以使用基于 PyimageSearch 方法的标签。许多现实世界的问题并不像只有一个标签那么简单,所以我倾向于做多标签和多任务类型的问题。所以我做了一个扩展了标准鸽子库的包来做多标签图像标注!
多标签鸽子
出于某种原因,当我看到鸽子库时,我觉得用它来标记我的多标签/多任务问题真的很酷。我做了我的修改,并将其添加到 pypi 中(这是我以前没有做过的,我基本上是按照这个教程做的)。所以我想我正在介绍我的多标签鸽子库!
在它目前的状态下,我所做的只是增加了一次标记多个任务的功能,用户可以选择他们想要的标签。这个想法是,与我以前主要靠手动操作的过程相比,它让一次标记一堆不同的问题变得更简单。也因为我不是最成人的,所以我用了赤壁命运系列的人物来显示注释。
Easy labeling is “good civilization”
基本上,演示显示的是如何标记 3 个任务问题。要标记的不同任务由一个字典定义,其中每个任务名称是一个键,一个潜在答案列表是值。
对于不同的任务,我只是标记一个图像是否。
- 可爱:是或不是
- 军刀(用剑?):是或否
- 颜色:蓝色,金色,白色,红色。
前两个是二进制的,我只回答是或不是,但是对于颜色,我为一些标记了多种颜色。所有这些结果都记录在一个字典中,其中键是图像的路径,值是包含任务名称和为每个任务按下的按钮的字典。
对我来说,这是对我自己生活质量的提升,我想我可以把它扔进深渊,如果其他人认为它有用,他们可以随意使用它!
结束语
我最终建立了许多数据集,并像某种数据集龙一样囤积起来,所以我得到了一些不错的实践,并在此过程中学到了一些东西。因为它是项目中非常基础的一部分,但并不经常被谈论,所以我想发布一个关于它的帖子可能会很酷,但我仍然不确定它是否对人们有用(也许每个人都已经知道这些东西了?谁知道呢?).
但是在一天结束的时候,就像大多数写博客的事情一样,我认为把它扔出去是值得的,如果它能帮助一些人,那就太好了!如果没有,那也很酷!
构建和共享闪亮的应用程序
原文:https://towardsdatascience.com/building-and-sharing-a-shiny-app-a486ca9efca2?source=collection_archive---------17-----------------------
如何尽快上手
支持本文的所有代码都可以从 MatrixDS 项目中派生出来
Photo by Stephen Dawson on Unsplash
数据科学流程中一个经常被忽略的部分是部署一个可供非技术决策者使用的完整解决方案。RStudio Shiny 是构建和部署该解决方案的优秀工具。Shiny 为数据科学家提供了用 R 编程语言构建反应式 web 应用程序的能力。它也非常灵活,如果你想构建更健壮的东西,它允许你添加 HTML 和 CSS。作为一名数据科学家,我希望专注于构建能够产生价值的模型,并希望尽可能少地处理托管和基础架构需求。有几个工具可以帮助你托管一个闪亮的应用程序,最常见的是 RStudio Connect、shinyapps.io 和 MatrixDS。对于本教程,我们主要关注 MatrixDS,因为它是自包含的(您不需要使用任何其他工具来构建、托管和部署)。它还为用户提供了轻松协作创建模型和应用程序的能力。
TL;DR:这篇文章的其余部分大致遵循这个视频的结构。
在任何 MatrixDS 项目中,我们都可以创建一个闪亮的工具和一个 RStudio 工具。
如果你的项目还没有,Shiny 工具会立即创建一个“shiny-server”文件夹,并加载一个应用程序。r 文件。这个文件是闪亮应用程序模板的修改版本,当你点击“新建”,然后点击“闪亮 Web 应用程序…”时,RStudio 就会构建这个模板。Shiny 工具创建了一个容器,可以挂载和部署“shiny-server”文件夹中的任何内容。
以下代码行被添加到 Shiny 模板中以帮助部署:
.libPaths( c( .libPaths(), “/srv/.R/library”) )
这一行告诉托管闪亮应用程序的容器使用安装在 RStudio 实例中的相同库。
production <- TRUEif(production == FALSE) {
#if you using the RStudio tool
shiny_path <- “~/shiny-server/”
home_path <- “~/”
} else {
#if you are using the shiny tool
shiny_path <- “/srv/shiny-server/”
home_path <- “/srv/”
}
这里我们创建了一个名为 production 的变量。当 production 设置为 TRUE 时,应用程序将在闪亮的容器上运行。当 production 设置为 FALSE 时,应用程序将在 RStudio 中运行。因为每个工具都在一个单独的容器中,所以我们必须使用绝对路径,这样它们才能找到我们在代码中引用的文件或对象。
最后,你可以通过点击闪亮工具上的私人/公共切换来分享你的应用。当设置为公共时,任何具有该 URL 的人都可以看到生产中的应用程序,并且您可以轻松地将其与消费者或客户端共享。查看公开的闪亮应用程序不需要 MatrixDS 帐户。
如果您打开 RStudio 工具,您会立即进入我们创建闪亮应用程序的环境,无需安装。在这里,您可以进行任何修改,这些修改会立即显示在您的客户或同事正在使用的已部署版本上。
现在就在 MatrixDS 上测试构建和部署您闪亮的应用程序
在 LinkedIn 上联系我:【https://www.linkedin.com/in/alejandromartinezm/
在 MatrixDS 上联系我:https://community . platform . matrix ds . com/community/Alejandro/overview
监督学习的构建模块
原文:https://towardsdatascience.com/building-blocks-of-supervised-learning-cebab32c15ac?source=collection_archive---------10-----------------------
监督学习的目标是根据大量输入预测输出。在监督学习问题中,输入和输出变量都是可测量的。这一系列技术由几个关键要素组成:
A)学习算法——以动态方式响应输入生成输出的过程,即输入/输出关系根据原始输出和生成输出之间的差异进行自我修改。
b)教师——用统计学术语来说,是帮助指导学习过程的可测量的结果变量。
c)数据集——在机器血管中循环的血液。我们的算法必须从中学习的一组输入和输出。
本文旨在说明和探索三种简单而强大的预测/分类方法:普通最小二乘法拟合的线性模型、k *邻预测规则和朴素贝叶斯分类器。这些技术的范围是巨大的。我是说,巨大的。事实证明,今天使用的流行技术的一个大子集仅仅是上述技术的变体(无论如何是针对低维问题的)。
我们开始工作吧。
我们需要从数据中得到什么?
人们通常认为预测的力量在于模型,但是也应该强调高质量数据的重要性。质量是什么意思?在基本层面上,为了避免正式的数学定义,我们需要一组可测量的输入变量, X={X1,X2,…} ,以及一个输出变量, Y 。由于我们关注技术,我们假设对于我们输出的每个观察值, Y ,在数据集中我们有一个完整的输入集, X ,在收集、精度、偏差等方面没有错误。
打响指
Figure 1 — Bivariate Training Data Scatterplot
图 1 显示了我们训练数据的散点图。对于每个观察,我们有一对连续的输入,用一个彩色十字表示, X=(X1,X2) ,还有一个离散的输出变量, G ,它决定了每个十字的颜色——鲑鱼蓝或矢车菊蓝。我们将这两个组称为类,我们的目标是建立一个可以将任何观察分类的模型,即任何一对输入( x1,x2),分类为鲑鱼类或矢车菊蓝类。
我们有了数据集,现在让我们建立模型。
线性模型
线性建模(或线性回归)的基本原理是找到输入变量的线性组合,它能最好地预测/描述输出变量。
- 我们如何适应我们的模型?
我们使用关键成分 c) —我们的数据集!给定我们已经观察到的对 (X1,X2) 的集合,我们可以开始构建我们的模型 f ,作为 (X1,X2) 的某种组合,由原始输出(由我们的数据给出)和f生成的输出之间的差异指导。如果需要,我们的线性组合需要足够灵活,以允许部分(非整数)和多个变量。为了方便起见,创建了辅助变量—这些变量也被称为回归系数。
因此,“拟合模型”相当于优化一组系数值,以产生最接*Y 的估计值——等等!,我听到你喊,你说关是什么意思?问得好,需要一个度量标准来量化距离。通用指标也称为损失函数(或误差函数),试图提供一个数字来概括特定模型在数据集上测试的不准确性。在这里,我们将使用一种非常简单但非常流行的方法,叫做普通最小二乘法(或者只是‘最小二乘法’)。该指标对我们训练集中每个观察值的模型估计值和原始输出值(*方误差)之间的*方差进行求和。最小化这个误差导致我们模型的最佳系数集。
注意,线性模型是一种回归技术,与分类技术相反。也就是说,它们的原始应用是用于定量变量而不是定性变量建模。对于我们的例子,在我们的连续回归输出之上还需要一个层。
设整数 1 代表三文鱼类,0 代表矢车菊蓝类。我们现在面临一个二元分类问题,如果模型输出大于 0.5,则选择在鲑鱼类中分类,否则在矢车菊蓝类中分类。这就是所谓的决定边界。图 2 描述了我们的线性模型及其决策边界。线以上的所有点被分类为矢车菊蓝类,其余的点被分类为鲑鱼类。
Figure 2 — Linear Regression Decision Boundary
因此,对于任何坐标(X 1,X2) ,我们的模型立即吐出一种颜色——太棒了!完成颜色,发现行为,正确完成工作?不对。
这里做了一个关键的结构假设——基础过程表现出全局线性。换句话说,假设对于所有的 X ,Y 相对于 X 表现为恒定的变化率。如果这些数据是从以不同*均值为中心的两个独立分布中生成的,那么线性决策边界可能是最佳的。在这种情况下,没有提到生成分布。如果这两个类中的训练数据都来自 10 个低方差双变量高斯分布的混合,每个分布都有单独的、独立分布的双变量高斯均值,会怎么样?在这种情况下,没有理由建议最佳边界应该是线性的。虽然我们的视觉检查向我们显示了边界两侧明显的错误分类,但它没有向我们表明我们对潜在关系的误解有多严重。这举例说明了线性回归中的一个关键缺陷——严重依赖线性结构假设或统计术语,高偏差。
这就引出了另一种分类技术,它更适合我们刚刚介绍的场景。
k *邻(kNN)
k-最*邻(或 kNN )的基本原理是基于来自训练集中在输入空间附*的观察集合的最常见输出来分配类别, X 。
- 我们如何拟合模型?
kNN 输出定义为 k 个最*输入的响应变量的算术*均值。同样,最*的意味着度量,所以我们将使用欧几里德距离(https://en.wikipedia.org/wiki/Euclidean_distance)。对于给定点 X=x ,仅需要数据集的 k- 大小的子集,而不是像线性回归中那样汇集整个训练集。本质上,该方法将分类视为多数投票,并假设行为是局部恒定的,即行为在每个邻域内不会改变。
Figure 3–12 Nearest Neighbour Classification Boundary
与线性模型的情况一样,我们将整数值 1 分配给鲑鱼类,0 分配给矢车菊蓝类。那么对于任何给定的 (X1,X2) ,kNN 输出 f 被定义为一组 12 个二进制数的算术*均值。很快注意到,输出可能不是整数,因此再次需要边界条件,以便提供我们想要的输出{鲑鱼,矢车菊蓝}。如果 f 大于 0.5,我们选择归入鲑鱼类,否则归入矢车菊蓝类。
图 3 显示了 k =12 的实现。显而易见的是,从线性结构假设中解放出来,可以实现更灵活的边界,甚至可以在大部分矢车菊蓝色区域中容纳鲑鱼分类区域。这种灵活性是 kNN 方法的主要优点,但是如果我们改变 k 会发生什么呢?
Figure 4–1 Nearest Neighbour Classification Boundary
图 4 显示了算法的特殊情况,其中模型仅基于数据集中最*的观察值分配输出,即 k =1 的情况。请注意,训练集中没有错误分类,这乍一看可能很好,但会导致训练集之外的分类/预测的高错误率,尤其是在模型训练数据集很小的情况下。
请注意,不同的 k 值的边界是不同的,这会引入噪声和选择 k 的额外任务(这里我们不讨论)。当模型偏差较低时,kNN 受到高方差的影响。换句话说,该模型可能对训练数据非常敏感,并且可能过度拟合该模型,而不是描述真实的输入/输出关系。
由于这种技术对数据的假设更少,因此算法有更多的变化。更深入的研究将探索不同的距离度量、加权*均值和 k 的参数选择技术对决策边界的影响。
朴素贝叶斯分类器
朴素贝叶斯分类器的基本原理是使用我们的先验知识分类到最可能的类别,并且基于我们应该在多大程度上信任观察到的证据的数学定理(贝叶斯定理—https://en.wikipedia.org/wiki/Bayes'_theorem)。
- 我们如何拟合模型?
该模型的程序需要计算和比较后验概率,该概率代表我们相信模型在给定所有输入 X. 的情况下准确描述 Y 的程度。这是一个封闭形式的计算,需要了解 Y 的分布(分布类型及其参数)。实际上,这限制了这种方法的使用——生成分布很少是已知的,但我们也要求它在某种程度上易于处理(易于评估)。
因此,为了使贝叶斯模型适合我们的例子,我们需要知道数据来自哪里。因为我自己模拟了这些数据,所以我可以告诉你,这些数据是由 10 个低方差高斯分布混合生成的,每个低方差高斯分布都具有单独的、独立分布的高斯*均值(就像前面讨论的场景一样!).
图 5 显示了这种方法的决策边界。
Figure 5 — Naive Bayes Classification Boundary
我们观察到边界看起来类似于 k=12 kNN 方法,尽管看起来是一种非常不同的技术。
概率论认为,如果几个变量不以任何方式相互依赖,那么一起观察它们的概率就是独立观察每个变量的结果。事实上,这种假设很少成立,因为我们感兴趣的建模系统中的变量彼此之间往往存在某种联系。因为这个原因,这个方法是幼稚的。
最后一个提示
任意点 X=x 处 Y 的最佳预测是给定所有可用信息的期望值。
我们已经看到,这三种技术中的每一种都为我们的初始分类问题提供了一个解决方案,但是它们在过程和决策边界上都有很大的不同。事实上,所有这三个都是由上面的陈述支撑的,其中最佳是通过前面描述的*方误差损失函数来测量的。这种说法已经在统计决策理论中得到证明,被称为回归函数。每种技术的差异可以通过它们对回归函数的解释来很好地总结。
线性模型:Y 在任一点 X=x 的最佳预测是给定所有可用信息的线性组合的期望。
kNN: 对任意点 X=x 的 Y 的最佳预测是给定 X=x 周围 k 大小的邻域的期望
朴素贝叶斯:任意点 X=x 处 Y 的最佳预测是给定所有可用信息的期望值(假设生成密度已知)。
这些构件是统计推断的重要基础。它们不仅易于实现,而且突出了统计建模的复杂性和在建模真实系统中出现的问题。自然延伸出现在以下问题中:
- 随着输入变量数量的增加,这些模型的性能会发生什么变化(维数灾难)?
- 我们如何比较模型的相对性能?
- 我们如何测试模型假设是否成立?为什么这些假设很重要?
- 如果我们用不同的损失函数重复我们的分析会怎么样?
欢迎反馈和评论!
构建块:文本预处理
原文:https://towardsdatascience.com/building-blocks-text-pre-processing-641cae8ba3bf?source=collection_archive---------7-----------------------
在我们系列的上一篇文章中,我们介绍了自然语言处理的概念,你可以在这里阅读,现在你大概也想自己尝试一下吧?太好了!事不宜迟,让我们深入研究统计自然语言处理的构建模块。
在本文中,我们将介绍关键概念、Python 中的实际实现以及应用时要记住的挑战。完整的代码可以在 GitHub 的 Jupyter 笔记本上获得。
文字规范化
规范化文本意味着在将文本转换为更高级建模的特征之前,将其转换为更方便的标准形式。把这一步想象成把人类可读的语言转换成机器可读的形式。
标准化文本的标准框架包括:
- 标记化
- 停止单词删除
- 形态标准化
- 配置
数据预处理由许多步骤组成,任何数量的步骤可能适用于也可能不适用于给定的任务。更一般地说,在本文中,我们将讨论一些预先确定的文本主体,并执行一些基本的转换分析,这些分析可用于执行更进一步的、更有意义的自然语言处理[1]
标记化
给定一个字符序列和一个已定义的文档单元(文本的简介),标记化的任务是将它分割成小块,称为 标记 ,可能同时丢弃某些字符/单词,如标点符号【2】。通常,有两种类型的标记化:
- 单词标记化:用于通过唯一的空格字符分隔单词。根据应用程序的不同,单词标记化也可以标记多单词表达式,如 New York 。这往往与一个叫做命名实体识别的过程紧密相关。在本教程的后面,我们将看看搭配(短语)建模,这有助于解决这个挑战的一部分
- 句子分词和单词分词一样,是文本处理中至关重要的一步。这通常是基于标点符号,如“.”, "?", "!"因为它们倾向于标记句子的边界
挑战:
- 缩写的使用可以促使标记器检测没有边界的句子边界。
- 数字、特殊字符、连字符和大写。在“不要”、“我愿意”、“约翰的”这些表达中,我们有一个、两个还是三个代币?
实现示例:
from nltk.tokenize import sent_tokenize, word_tokenize#Sentence Tokenization
print ('Following is the list of sentences tokenized from the sample review\n')sample_text = """The first time I ate here I honestly was not that impressed. I decided to wait a bit and give it another chance.
I have recently eaten there a couple of times and although I am not convinced that the pricing is particularly on point the two mushroom and
swiss burgers I had were honestly very good. The shakes were also tasty. Although Mad Mikes is still my favorite burger around,
you can do a heck of a lot worse than Smashburger if you get a craving"""tokenize_sentence = sent_tokenize(sample_text)print (tokenize_sentence)
print ('---------------------------------------------------------\n')
print ('Following is the list of words tokenized from the sample review sentence\n')
tokenize_words = word_tokenize(tokenize_sentence[1])
print (tokenize_words)
输出:
Following is the list of sentences tokenized from the sample review
['The first time I ate here I honestly was not that impressed.', 'I decided to wait a bit and give it another chance.', 'I have recently eaten there a couple of times and although I am not convinced that the pricing is particularly on point the two mushroom and \nswiss burgers I had were honestly very good.', 'The shakes were also tasty.', 'Although Mad Mikes is still my favorite burger around, \nyou can do a heck of a lot worse than Smashburger if you get a craving']
---------------------------------------------------------
Following is the list of words tokenized from the sample review sentence
['I', 'decided', 'to', 'wait', 'a', 'bit', 'and', 'give', 'it', 'another', 'chance', '.']
停止单词删除
通常,作为停用词移除过程的一部分,有几个普遍存在的词被完全从词汇表中排除,这些词看起来对帮助分析的目的没有什么价值,但是增加了特征集的维度。通常有两个原因促使这种移除。
- 不相关:只允许对有内容的单词进行分析。停用词,也称为空词,因为它们通常没有太多意义,会在分析/建模过程中引入噪声
- 维数:去除停用词还可以显著减少文档中的标记,从而降低特征维数
挑战:
在停用字词删除过程之前将所有字符转换为小写字母会在文本中引入歧义,有时会完全改变文本的含义。例如,“美国公民”将被视为“美国公民”,或者“it 科学家”将被视为“IT 科学家”。由于us和it通常都被认为是停用词,这将导致不准确的结果。因此,通过词性标记步骤,通过识别“us”和“IT”不是上述示例中的代词,可以改进关于停用词处理的策略。
实施例:
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize# define the language for stopwords removal
stopwords = set(stopwords.words("english"))
print ("""{0} stop words""".format(len(stopwords)))tokenize_words = word_tokenize(sample_text)
filtered_sample_text = [w for w in tokenize_words if not w in stopwords]print ('\nOriginal Text:')
print ('------------------\n')
print (sample_text)
print ('\n Filtered Text:')
print ('------------------\n')
print (' '.join(str(token) for token in filtered_sample_text))
输出:
179 stop words
Original Text:
------------------
The first time I ate here I honestly was not that impressed. I decided to wait a bit and give it another chance.
I have recently eaten there a couple of times and although I am not convinced that the pricing is particularly on point the two mushroom and
swiss burgers I had were honestly very good. The shakes were also tasty. Although Mad Mikes is still my favorite burger around,
you can do a heck of a lot worse than Smashburger if you get a craving
Filtered Text:
------------------
The first time I ate I honestly impressed . I decided wait bit give another chance . I recently eaten couple times although I convinced pricing particularly point two mushroom swiss burgers I honestly good . The shakes also tasty . Although Mad Mikes still favorite burger around , heck lot worse Smashburger get craving
形态标准化
一般来说,形态学是研究单词是如何由更小的有意义的单位组成的,词素。比如狗由两个语素组成: 狗 和 s
两种常用的文本规范化技术是:
- 词干化:该过程旨在识别单词的词干,并用它来代替单词本身。提取英语词干最流行的算法是波特算法,这种算法已经被反复证明是非常有效的。整个算法太长太复杂,无法在这里呈现[3],但是你可以在这里找到细节
- 词汇化:这个过程指的是使用词汇和词形分析来正确地做事情,通常旨在仅移除屈折词尾,并返回单词的基本或词典形式,这被称为 词汇 。
如果遇到令牌 saw ,词干可能只返回 s ,而词汇化将根据令牌是用作动词还是名词【4】来尝试返回 see 或 saw
实施例:
*from nltk.stem import PorterStemmer
from nltk.stem import WordNetLemmatizer
from nltk.tokenize import word_tokenizeps = PorterStemmer()
lemmatizer = WordNetLemmatizer()tokenize_words = word_tokenize(sample_text)stemmed_sample_text = []
for token in tokenize_words:
stemmed_sample_text.append(ps.stem(token))lemma_sample_text = []
for token in tokenize_words:
lemma_sample_text.append(lemmatizer.lemmatize(token))
print ('\nOriginal Text:')
print ('------------------\n')
print (sample_text)print ('\nFiltered Text: Stemming')
print ('------------------\n')
print (' '.join(str(token) for token in stemmed_sample_text))print ('\nFiltered Text: Lemmatization')
print ('--------------------------------\n')
print (' '.join(str(token) for token in lemma_sample_text))*
输出:
*Original Text:
------------------
The first time I ate here I ***honestly*** was not that impressed. I decided to wait a bit and give it ***another*** ***chance***. I have recently eaten there a ***couple*** of times and although I am not convinced that the pricing is particularly on point the two mushroom and swiss burgers I had were honestly very good. The shakes were also tasty. Although Mad Mikes is still my favorite burger around, you can do a heck of a lot worse than ***Smashburger*** if you get a ***craving***.
Filtered Text: Stemming:
------------------
the first time I ate here I ***honestli*** wa not that impress . I decid to wait a bit and give it ***anoth*** ***chanc*** . I have recent eaten there a ***coupl*** of time and although I am not convinc that the price is particularli on point the two mushroom and swiss burger I had were honestli veri good . the shake were also tasti . although mad mike is still my favorit burger around , you can do a heck of a lot wors than ***smashburg*** if you get a ***crave*** .Filtered Text: Lemmatization
--------------------------------
The first time I ate here I ***honestly*** wa not that impressed . I decided to wait a bit and give it ***another*** ***chance*** . I have recently eaten there a ***couple*** of time and although I am not convinced that the pricing is particularly on point the two mushroom and swiss burger I had were honestly very good . The shake were also tasty . Although Mad Mikes is still my favorite burger around , you can do a heck of a lot worse than ***Smashburger*** if you get a ***craving*** .*
挑战:
通常,完整的形态学分析至多产生非常有限的分析益处。从相关性和维度缩减的角度来看,两种形式的标准化都不能提高语言信息的总体性能,至少在以下情况下是这样:
实施例:
*from nltk.stem import PorterStemmer
words = ["operate", "operating", "operates", "operation", "operative", "operatives", "operational"]ps = PorterStemmer()for token in words:
print (ps.stem(token))*
输出:
*oper
oper
oper
oper
oper
oper
oper*
作为可能出错的一个例子,请注意,波特词干分析器将以下所有单词的词干转换为 oper
然而,由于以各种形式操作是一个常见的动词,我们预计会失去相当的精确性[4]:
- 运营和研究
- 操作和系统
- 手术和牙科
对于这种情况,使用词汇归类器并不能完全解决问题,因为在特定的搭配中使用了特定的屈折形式。从术语规范化中获得更好的价值更多地取决于单词使用的语用问题,而不是语言形态学的形式问题[4]
对于所有用于生成上述结果的代码,点击此处。
就是这样!现在你知道梯度下降,线性回归和逻辑回归。"
即将到来..
在下一篇文章中,我们将详细讨论搭配(短语)建模的概念,并一起演练它的实现。敬请关注,继续学习!
参考文献:
[1]预处理文本数据的一般方法— KDnuggets。https://www . kdnugges . com/2017/12/general-approach-预处理-text-data.html
[2]记号化—斯坦福 NLP 组。https://NLP . Stanford . edu/IR-book/html/html edition/token ization-1 . html
[3]牛疾病中的文本挖掘—ijcaonline.org。https://www.ijcaonline.org/volume6/number10/pxc3871454.pdf
[4]词干化和词汇化—斯坦福大学 NLP 组。https://NLP . Stanford . edu/IR-book/html/html edition/stemming-and-lemma tization-1 . html
如果你有任何反馈,请在本文中发表评论,在 LinkedIn 上给我发消息,或者给我发邮件(shmkapadia[at]gmail.com)
使用 SAS 和 Python 构建信用记分卡
原文:https://towardsdatascience.com/building-credit-scorecards-using-sas-and-python-cf9c3ecc30bc?source=collection_archive---------8-----------------------
无论你是在申请你的第一张信用卡,还是在购买第二套房子,或者在这两者之间的任何地方,你都可能会遇到申请过程。作为这一过程的一部分,银行和其他贷方使用记分卡来确定你偿还贷款的可能性。
自然,这意味着信用评分对于银行和任何与银行业合作的企业来说都是一个重要的数据科学主题。
由于我以前有过客户分析的经验,但不是专门的金融风险,我一直在学习如何开发信用记分卡,我想分享我所学到的东西,包括我的想法和代码实现。
记分卡和信用评分的价值
记分卡有两种基本类型:行为记分卡和应用记分卡。
- 行为记分卡更多的是对当前客户及其违约可能性进行预测或评分。
- 当新客户申请贷款时,应用记分卡用于预测他们成为盈利客户的可能性,并将分数与他们相关联。
对银行来说,信用评分有助于管理风险。作为消费者,我们被各种优惠轰炸。由企业评估消费者的信用价值和信用评分,根据风险、周转时间、不正确的信用拒绝等因素确定最佳产品解决方案。
如果在不该放贷的时候放贷,那么未来很可能会亏损。如果批准或拒绝信贷的周转时间有很长的滞后时间,或者银行不准确地拒绝了一个良好的客户信用,他们可能会失去这些客户的竞争对手。在这种情况下,你可能需要很长时间才能找回它们。
使用信用评分可以优化风险,最大限度地提高企业的盈利能力。
信用评分数据
本帖中信用评分示例的训练数据是真实的客户银行数据,出于显而易见的原因,这些数据被篡改和匿名化了。这些特征——在信用评分中被称为特征——包括孩子数量、家庭成员数量、年龄、居住时间、当前工作时间、拥有电话、收入等。我们的目标变量将是一个二元变量,其值为“坏”或“好”,与给定的某个历史时期的客户违约相关。
信用评分代码
对于这个分析,我使用名为 SWAT(用于分析传输的脚本包装器)的 SAS 开源库来用 Python 编码并执行 SAS CAS 动作集。SWAT 充当 python 语言和 CAS 动作集之间的桥梁。 CAS 动作集与 Python 中的库或 r 中的包同义。一个主要的区别和好处是,这些动作集中的算法已经高度并行化,可以在 CAS(云分析服务)服务器上运行。CAS 服务器是一个分布式内存引擎,我可以在其中完成所有繁重的工作或计算。代码和 Jupyter 笔记本在 GitHub 上都有。
信用评分法
证据的权重
我首先使用证据权重(WOE)方法转换我的数据。该方法试图通过将每个要素分割成多个条柱并为每个条柱分配一个权重来找到输入要素和目标变量之间的单调关系。假设收入水*上的 WOE 变换包括收入水*$ 100,000 到$ 150,000,那么该区间内的所有观察值将接收相同的 WOE 值,该值可以使用下面的公式计算。
Weight of Evidence Calculation
考虑收入水*在 10 万美元到 15 万美元之间的区间。在我们数据中所有“好”的观察结果中,30%来自这个收入水*区间,而只有 10%的“坏”观察结果来自这个区间。使用这些比例,你可以说,我们有 3:1 的赔率,收入在 10 万美元和 15 万美元之间的人是一个好的信用候选人,而不是坏的。然后,我们取自然对数和 100 的倍数,以便于用数字表示,我们得到了收入水*区间内所有观察值的收入水*权重值。
Weight of Evidence Example
数据管道
让我们将这种转换应用于整个数据集。使用 SAS 中的数据预处理动作集使得构建数据管道变得非常容易(图 1)。数据管道有助于常见手动数据科学步骤的自动化流程。该动作集可以为跨任何连续或标称特征的各种转换构建大型数据管道。
构建单一管道只需几个步骤:
- 将变量分配给角色。
- 构建变量转换。
- 附加转换以便以后应用于数据。
首先,我们将特性分配给它们的角色,关于转换和建模,分离名义变量和连续变量以及目标(图 1)
Figure 1: Assign features to roles
接下来,我们创建名为 req_pack1 的第一个转换,它是 request package 的缩写,是 datapreprocess.transform 操作中的参数。我给转换命名,传递特性列表和目标,并指定感兴趣的事件,在本例中是“坏的”。
我在 Python 中调用 discretize 来绑定连续值并指定 WOE 转换。在该变换中有一个正则化参数,您可以在该参数中使用最小和最大 NBins 参数指定一个范围。这使得能够使用信息值(IV)在那些箱中搜索以找到最佳箱号。IV 是分类模型中常用的统计数据,用于衡量特征集的预测能力。
第二个转换,我将其标记为 req_pack2,除了我正在转换名义输入,因此需要使用 cattrans 而不是 discretize 之外,它几乎是相同的。cattrans 参数代表分类转换。
然后,我们将这些列表附加在一起,以便稍后将转换大纲传递给我们的转换操作。
Figure 2: Set up weight of evidence transformation
数据转换
现在我们已经有了数据管道,让我们来转换数据(图 3)。我首先使用 table 参数引用我们的数据。然后我提供了我在图 2 中创建的 req_packs 列表以及所有的转换。我将输出表(casout)指定为 woe_transform。接下来,我使用 copyVars 将 target 和 _customerID 特性从原始表复制到新的转换表中。然后我给我们所有新转换的特征一个全局前缀“woe”。code 参数将转换保存为代码表。这将在以后用于对新数据进行评分。这有利于希望进行模型协作或为重复出现的工作构建更深的端到端管道的团队。
最后,我们将预览一下新的 WOE 表(图 3)。请注意我们一些客户的相同值。请记住,发生这种情况是因为对于一个给定的变量,这些观察值属于同一个箱,因此得到相同的权重。
Figure 3: Transform data and view new dataset.
可视化转化结果
转换操作在 CAS 服务器上创建了几个输出表,如图 3 所示。其中一个表叫做 VarTransInfo,它包含我们特性的 IV 统计信息。查看 IV 以了解我们的特征的预测能力并确定是否有必要将这些特征包括在我们的模型中,这是一种很好的做法。下面是对 IV 的计算。图 4 是我们每个特性的 IV 值的曲线图。强特征通常具有大于 0.3 的 IV,弱特征< 0.02, and anything > 0.5 可能是可疑的,需要仔细观察。图 4 显示了我们的特性几乎分成了两部分,一部分是强特性,另一部分是中间特性。此外,年龄变量看起来非常强大。目前,我们将保留所有功能。
Figure 4: Information value (IV) calculation
我们还可以根据分配给特征的箱来绘制特征权重值。除了查看这些区间的 WOE 值之外,数据科学家可能希望返回并手动配置每个特定变量的区间数(合并或拆分),这样更符合逻辑。重要的是要知道,WOE 试图在单个特征内建立分离,因为它与一个目标变量相关,所以应该有跨箱的差异。图 5 显示了您期望在表示这些特征内的分离的多个条块上看到的 WOE 值。
Figure 5: Plot of WOE value by bin for several features
这正是数据科学家需要了解业务的地方,以确保各条块之间的加权趋势符合逻辑。例如,对一家银行来说,客户可用的现金越多,它应该在各个箱中看到更高的权重,这具有商业意义。同样的逻辑也适用于工作、年龄或职业群体的时间。我们预计所有这些权重相对于箱来说会更高。
记分卡的逻辑回归
我们的下一步是使用新转换的 WOE 数据集拟合逻辑回归模型。我将展示非常简单的代码来训练模型并解释参数。
下面的图 6 显示了训练代码。以下是训练模型所涉及的步骤:
- 分配模型输入并将“woe_”连接到所有原始列名,以便它正确引用 woe_transform 数据集。
- 使用 table 参数引用 woe_transform 数据集。
- 指定目标和参考(根据模型参考“好”或“坏”)。
- 然后,指定变量选择的正向选择方法。正向选择从一个空模型开始,并根据特定标准(AIC、AICC、SBC 等)在每次迭代中添加一个变量。).
- 使用 code 参数保存我们的逻辑回归代码
- 使用 casout 为新的输出表创建一个名称,然后再次复制 target 和 _customerID 变量。
Figure 6: Logistic regression model
创建记分卡
最后一步是将模型扩展到记分卡中。我们将使用一种通用的缩放方法。我们需要通过拟合模型得到的逻辑回归系数,以及带有转换后的 WOE 值的 WOE 数据集。我们将对我们的训练表进行评分,以得出 logit 或 log odds 值。因为我们从逻辑回归中得到的分数是对数比值形式,所以我们需要将其转换成记分卡的积分系统。我们通过应用一些缩放方法来进行转换。
第一个值是目标分数。这可以被认为是一个基线分数。对于这张记分卡,我们将分数定为 600 分。600 的目标分数对应于 30 比 1 的好/坏目标赔率(target_odds = 30)。缩放不会影响记分卡的预测力度,因此如果您选择 800 作为缩放分数,就不会有问题。
下一个变量叫做 pts_double_odds,意思是双倍赔率的点数。这意味着,分数增加 20 分,我们认为申请人在违约方面表现良好的可能性就会增加一倍。例如,如果你有 600 分,你有 30 比 1 的机会成为一个好的信用候选人。但是 620 分会让你被认为好的几率提高到 60:1。下面的图 8 显示了预测赔率和得分之间的指数关系。在下面的图 7 中,您可以看到简单的计算,以及如何使用它们来导出我们的记分卡分数变量。
Figure 7: Scorecard scaling and logic
Figure 8: Predicted odds by score plot
形象化
我们可以在图 9 中看到记分卡分数变量的分布,*均分数为 456。
Figure 9: Distribution of scores with mean score
然后,我们还可以看到这些分数如何与我们的业务成为好客户或坏客户的概率相关联,如图 10 所示。你可以看到很好的曲线形状。
Figure 10: Plot of scores by predicted probability
最后,我们可以使用这些分数来根据消费者的信用分数确定他们的等级。取决于产品、贷款等。这些层级将有不同的级别。对于我的分层系统,我只选择了四分位数来说明临界值的构建,但您可以根据产品或服务选择任何变化。
Figure 11: Customer groups based on quartile scores
拒绝推理
我想简单提一下拒绝推断,因为这是信用评分中的一个重要步骤。到目前为止,我们已经根据好坏的标签拟合了一个逻辑回归模型,并将这些分数换算成记分卡。整个过程着眼于当前的客户群,这些客户群拥有大部分完整的数据和已知的信用(好的或坏的)。然而,信贷申请往往会丢失大量数据,从而导致信贷被拒。在这种情况下,拒绝信用是由于我们有偏见的模型,它只查看我们知道是好是坏的人的完整记录。我们需要包含一些方法来调查这些拒绝,并将这些信息包含回我们的模型中,这样就更少偏见,更好地概括。
这就是拒绝推理所达到的效果。简而言之,我们查看那些被拒绝的客户,他们的信用状况未知,并分别处理这些数据,然后将他们重新分类为好或坏。这通常通过基于规则的方法、类似于原始 logit 模型的比例分配、增加否定的 logit 的原始分数等来实现。这个主题可以是一个独立的讨论,因为有各种各样的方法和思想流派。现在,我只想说,为了优化你的模型,使其不偏不倚,更好地概括,应该调查和整合由于缺失数据而导致的否定。
摘要
总的来说,使用证据权重转换和逻辑回归模型来为客户获得分数,对于同样使用业务逻辑感的数据科学家来说,是一个非常强大的工具。有许多方法可以建立这些评分模型,虽然这只是其中一种,但我希望它有助于提供指导或激发新的想法。此外,任何时候,数据科学家都可以处理复杂的问题,如转换和信用评分,并说明结果,这对从业者和组织都是一种胜利。
奖励:计分函数或 Rest API
我创建了一个函数,它使用来自转换和逻辑回归的 code 参数来对新的输入数据进行批量评分。它可以节省时间,并展示如何使用您的代码为新数据评分。
请看图 12,第一步是生成一个小的测试集,我通过从训练数据中获取一些观察数据来完成这个任务(只是为了测试)。然后将数据加载到 CAS 服务器。在这里你可以看到我构建的名为 model_scoring 的函数。它有 5 个参数:CAS 连接的名称、来自 woe 转换的代码、来自逻辑回归模型的代码、测试表名称和评分表名称。如果您查看 model_scoring 函数,会发现有三个步骤:
- runcodetable — woe 转换。
- 估算-用 0 替换缺失的 woe 值。
- runcodetable 使用 woe 变换值的逻辑回归。
我使用评分函数对新数据进行评分。此时,您可以应用这些简单的记分卡计算方法,无论您想如何扩展,您都可以随时使用记分卡。
Figure 12: Scoring new data with scoring function
所有这些也可以使用 REST API 来完成。CAS 上的每个分析资产都使用 REST 端点进行抽象。这意味着您的数据和数据处理只需要几次 REST 调用。这允许将 SAS 技术轻松集成到您的业务流程或其他应用程序中。我使用 python 访问这些动作集和动作,但是使用 REST,您可以用自己选择的语言访问任何这些资产。
参考文献
- 西迪奇,纳伊姆。信用风险记分卡:开发实施智能信用评分。第一版。,威利,2005 年。
- “数据处理”动作集的 SAS 开发者,非常感谢 Biruk Gebremariam
- 在 GitHub 上完整的 Jupyter 笔记本演示
- 附加感谢:韦恩·汤普森
原载于 2019 年 1 月 18 日blogs.sas.com。
建筑数据
原文:https://towardsdatascience.com/building-data-23d598f57ab7?source=collection_archive---------7-----------------------
基础设施、信任、欣赏和决策
失败(fālˈyər)
没有达到预期目的的情况或事实:实验的失败。
我失败了。作为多伦多一家初创公司的第一位数据工程师,我有崇高的目标,伟大的新想法/稍微借鉴的想法,我甚至有阶段,所以一切都会很好地融入我的宏伟计划。不要误解我,失败并不是一件坏事,我已经做了很多事情。但是我知道问题,我知道解决方法,我把所有的事情都分阶段进行。我怎么会失败呢?我怎么会???
让我们从头开始,第 0 天,我想了很久,想了很久,想了很久,想了很久,想了很久,想了很久,想了很久,想了很久,想了很久,想了很久,该怎么做,所以让我们从这里开始吧。让数据民主化!
第 1 阶段将移除或更新传统事件跟踪目标,并替换为来自segment.com的整合第三方 API。我会尽可能保持其他一切不变,同时重建,因为商业需求不能让位于伟大。
第 2 阶段是现代无服务器数据基础设施诞生的地方。我会使用最新和最伟大的数据技术,一切开源,甚至一些“出血边缘”阿尔法狗屎,使一个傻瓜(和未来)证明基础设施。这将为我们提供我们可以预见的所有可扩展性,同时还允许分析师和数据科学家访问、发现和构建可操作的见解 ←是我借用的一个想法。
第三期等一下……自助。还需要我多说吗?任何关于数据工程、数据文化或数据驱动的决策制定的讨论,如果没有一个每个员工都知道、使用和喜爱 SQL 的自助式报告 BI *台的梦想,都是不完整的。
第 4 阶段数据产品,面向内部和外部。数据团队不仅应该促进提供易于访问和发现的数据,而且,特别是在小公司,应该推动 A/B 实验*台、数据科学工作流、产品团队可以使用的数据 API,以及整个组织中所有数据相关文档的官方主页,如 Airbnb 的知识报告。
Photo by Brooke Cagle on Unsplash
与此同时,还有午餐学习、数据调查、制定数据驱动决策的最佳实践等等。你的基本数据——公司内部的大学方法。
我失败了。我不仅失败得快而且经常失败,而且失败得相当慢,努力去理解眼前发生的事情。
今天,我想写一个小故事,讲述我在数据职业生涯中的亲身经历,以及我通过阅读其他媒体上的故事所学到的东西。也许与此同时,我会想出我会有什么不同的做法。
理论上,数据工程师不负责组织中的“所有数据”。互联网上的默认角色描述中没有一句台词是这样的
数据工程师收集、转换和发布数据,使组织能够做出数据驱动的决策……他们还创建、维护和传播我们都知道、喜欢和想要的数据文化。
但是在相当多的情况下,特别是在早期的“数据成熟”公司中,无论员工或雇主是否知道,这都是一个要求。
数据文化是你经常听到的东西,就我个人而言,我是自上而下的数据文化方法的强烈支持者,这意味着,如果你的首席执行官不喜欢它,并且不要求他的直接下属提供数据支持的结果,你将无法让其他人关心数据驱动的文化。
但在大多数创业公司中,至少从我能讲的来看,似乎是这样的。主要是因为小公司要么有一两个“数据人”,所以任何与数据相关的责任都从其他人身上转移到了数据人身上。在处于早期数据成熟阶段的公司,尤其是初创公司,第一个数据工程师几乎总是必须承担在公司推广数据知识和热情的角色,以及正常的预期数据工程工作。
不管是好是坏,这就是所发生的事情,与其争论如何解决它,我想写下我处理它的经历。我目前是一名数据工程师,但我在企业和初创公司中担任过多个数据分析师和软件开发人员的角色。在每一个新的角色中,我大脑中的科学家部分总是想要证明,这使我成为我所在的公司或团队的数据人员。
当我第一次加入目前的公司时,培养数据文化是一件非常令人兴奋的事情。建立新的东西,而不仅仅是基础设施,以某种方式指导公司的整体数据战略的想法令人兴奋。但是我如何创建这种数据文化呢?我们能定义它吗?互联网给你的感觉是数据文化是一个单一的、从固体金属切割而成的复杂模型,直接看着它让人无法理解如此复杂的东西是如何被人类创造出来的。
但是对我来说,数据文化是一把包罗万象的伞,为了清楚起见,我想把它分成 4 个部分。我自己的私人捕捉所有迷你伞。这就是我对构建数据的看法和经验的开始。
Photo by Stephen Dawson on Unsplash
1.构建数据基础设施
最*,似乎每个公司都想要或需要一名数据工程师。这个人为公司做什么在很大程度上取决于公司的行业和数据成熟度。这可以跨越从初创公司到大型企业公司。
我的主要职责是解决问题、支持员工和建立基础设施。但不是这么几句话,更像是
简化、整合、管理、维护并向组织内的所有利益相关方提供可靠的数据,但首先要修复、移除和/或替换不工作的数据,这是典型的启动数据工程需求
这个概念非常简单,但总有一个问题,其中之一就是要记住,当你在建设基础设施时,公司仍然需要运转。这意味着,公司的当前和短期需求仍然必须得到支持,利益相关者仍然需要指标来查看,BI 分析师仍然需要仪表板和图表来分析。这是非常好的优先级技能、多任务技能、沟通和期望管理技能发挥作用的地方。如果你没有这些,那么成为你公司的第一个(或第一批)数据工程师对你和你的公司来说可能是个坏主意。
排在“明白”列表之后的第二个问题是,在想要和需要之间进行斗争有多困难,以及*衡未来建设而不是遥远未来建设的真正需要。除非你是一家专门的“数据”公司,或者可能是一家 IOT 公司,否则你对数据基础设施的第一次尝试不应该是大肆宣传的数据湖。这也适用于你的数据工具,我正看着你的 Looker 。想想婴儿的步伐,或许不是婴儿的步伐,而是蹒跚学步的步伐。不需要启动一个 kubernetes 集群来在 Docker 容器中运行您的两个 Python 脚本。但这并不意味着你的基础设施是从你办公桌下的服务器上运行的 cron 开始的。
一个好的、简单的、典型的 starter 批处理基础设施可能看起来像 AWS S3、Redshift、EC2/hosted(或 AWS Glue)上的 Airflow 以及您选择的 BI 工具。您可能还想添加一个监控堆栈,无论是 Prom+Grafana 还是 AWS CloudWatch。通过这种设置,您可以轻松地纵向扩展和横向扩展、更换部件或将整个系统转移给另一家提供商(有限的供应商锁定)。您还可以轻松地为数据科学家或数据分析师添加工作流工具,目前,您的公司可能还没有这些工具。一家拥有第一位数据工程师的公司现在可能正在期待一些数据民主化的发生(对于那些不了解情况的人来说,这是数据和民主之间的“协同作用”),随之而来的是大肆宣传的自助式商业智能*台/分析工具。
“自助”这个词就像愚人的黄金或者宠物蛇或者蝎子和青蛙,基本上是任何一开始看起来很棒,然后一有机会就咬你屁股的东西。
[## 蝎子和青蛙-维基百科
一只蝎子让一只青蛙背它过河。青蛙犹豫了,害怕被蝎子螫伤,但是…
en.wikipedia.org](https://en.wikipedia.org/wiki/The_Scorpion_and_the_Frog#/media/File:Tortoise_and_Scorpion.jpg)
自助式 BI,也称为民主化数据,是指当有人想象一个世界,其中具有直观拖放界面的工具实际上对所有人都是直观的,人们只问他们自己无法回答的问题,每个人都知道 SQL。如果有合适的资源可以帮助,使用 excel 的用户很可能会使用任何工具。这些用户热衷于学习更多关于工具和数据的知识,并且不介意与奖励相关的学习曲线。然而,在现实中,创建一个自助式分析环境会给你一个大规模混乱、伟大和愚蠢的大杂烩,比如
- 认为谷歌表单的旧方式更好的用户
- 人们提出了许多很棒的新问题
- 很多不太好的问题已经被提出来了
- 大家都讨厌 SQL。人人
- 解释拖放界面的工作原理
自我服务会让你不知所措,让你的利益相关者不知所措。如果你没有准备好大量的资源——需要帮助的人、文档、消磨时间——这个项目会扼杀你作为数据工程师的生产力,甚至可能扼杀你的灵魂。你最好与其他团队的一两个关键成员密切合作,帮助他们学习新系统,发现数据,让这些半数据人员直接在他们自己的团队中工作,然后在以后打开称为自助式 BI 环境的闸门。
2.建立数据信任
如果没有人相信你提供的数据,那就不值得提供。我很快认识到,一个看起来不太好的基础设施产生数据是不够的。人们需要使用这些数据来查看结果,并深入了解从营销活动和转化率到 A/B 实验和用户应用内行为的任何事情。如果您的最终用户不相信您提供的指标,他们会很快停止使用您的数据。如果你幸运的话,他们至少会告诉你他们不相信这些数据——是的,这就是幸运。唯一比最终用户不信任你的数据更糟糕的是,用户不信任你的数据,停止使用它,寻找替代品,并且永远不会告诉你。
就数据信任而言,单一(一个)真实来源是区分好坏的好方法。
在信息系统设计和理论中,单一真实来源 ( SSOT )是结构化信息模型和相关联的数据模式的实践,这样每个数据元素被精确地存储一次。到这个数据元素的任何可能的链接(可能在关系模式的其他区域或者甚至在遥远的联合数据库中)只通过引用—维基百科
在英语中,在上下文中,让您的度量依赖于一个表或过程会给您带来两个好处:1)单点故障,但也是修复该故障的单点故障;2)如果度量是错误的,使用该度量的每个人都是同样程度的错误。
我认为我的第一点很容易理解和欣赏。如果某些东西损坏了,就像不可避免的那样,它只能在一个地方损坏,您只需要修复那个地方,就可以获得每个下游流程,并再次使用正确的指标进行报告。但是让我深入到第二点(2)一点,因为没有人喜欢得到错误的数据,但听起来好像我在说这是一件好事。我没有。我是说每个人都错 到同样程度是好事。根据我的经验,可能发生的最糟糕的事情之一是工作管道错误地处理数据;然而,比这更糟糕的是,下游流程和报告要求相同的指标,但却有不同的错误答案。当你意识到问题时,你会静静地坐在那里盯着屏幕,深呼吸,然后说“妈的。那可不好”。这就是 SSOT 的切入点。您可以使用不同的数据源,一起转换和争论您的数据,但最终如果您的指标使用一个表、一组表或流程作为其基础,而所有其他流程使用其输出作为自己的基础,您将永远不会得到一个跨管道给出不同错误答案的指标。
难以置信,但这一切都要追溯到数据信任。如果利益相关者没有或失去了对数据的信任,就很难挽回。SSOT 有助于防止这种情况发生,因此对于任何数据工程师来说,在这里花费大量时间都是非常值得的,尤其是那些受托建立依赖数据的文化的人。
3.建筑数据增值
一种感激。不是说需要人们欣赏你的工作,而是数据本身,以及他们如何利用它来实现自己的目标。需要在团队成员和整个公司中培养数据欣赏能力,如果没有这一点,那又如何?—态度总是会妨碍人们利用你提供的一切。
如果一个数据工程师创建了可发现的、可靠的、值得信赖的数据集市,但最终用户却不在乎,那么这个数据工程师真的成功了吗?
这可能更像是一个公司文化的话题,但是如果给你一些工具来帮助你在你的职位上取得成功,你会使用它们吗?这就是数据增值的用武之地,你的终端用户关心你在做什么,更重要的是他们关心你为什么这么做。您和您的基础架构的存在只有一个原因—直接或间接地提供业务洞察力,您的基础架构必须促进这一点。如果用户不能,不管是自愿的还是通过其他方式,欣赏你苦心提供的那些宽维度表或时间序列指标,你就没有任何意义。句号。
在一家初创公司(或任何处于数据成熟早期阶段的公司),你作为数据工程师的角色可能意味着你不仅要构建基础设施,还要构建对数据的“欣赏”,在组织内部和整个组织中传播数据。没有有效地做到这一点会导致你整体工作的失败。建造它,他们将使用它,,在这里并不适用。
4.构建数据(驱动)决策
D 数据驱动的决策或这一主题的任何迭代基本上是业务用户在采取行动之前利用数据洞察来制定、验证和/或确认其决策的概念。这些决策可能是实验假设的基础,也可能是对失败的营销活动的解释,或者是投资特定产品功能的原因。关键是,你依靠数据来帮助你做决定,这有助于更有效的过程,并允许你做重要的事情,为你和你的组织带来价值的事情。
虽然许多人喜欢数据驱动决策的概念,并要求更多的数据,但其他人则反对。想要继续做你正在使用的事情是很自然的,我自己也经常这样做,这就是为什么我之前提到我是自上而下的数据文化方法的强烈支持者,原因是这样的——想象你是一个功能团队的高级经理,刚刚在你的惊人产品中部署了一个很棒的新功能。帮我回答这些问题
- 有多少客户在使用你这个很酷的新功能?
- 您的功能被使用的频率是多少?
- 你会开发很酷的 v2 功能吗?
很简单的问题,你可能会在第三季度猜个大大的是,因为你为什么不修复几个 bug 并增强一些已经在生产中的功能呢?但是,如果你的老板以一种自上而下的方式要求你向她提交的任何决定都必须有数据支持,那该怎么办呢?现在,您有了一整套新问题,比如,“我是否甚至用这个新特性来捕获回答这些问题所需的数据?”或者“为什么数据显示很少有客户真正使用该功能,但我的直觉告诉我做得很好?”。既然 v1 没有数据支持它的成功,那么版本 2 就有点难以证明了。
当您引用数据时,会出现更多的问题和见解,有好有坏,但如果数据驱动的文化不是自上而下的,这些都是不可能的。你要么急于得到数据,要么没有。如果你不是,除非你被轻轻推向正确的方向,否则很容易忽视额外的努力。
尽管你不是那些数据驱动决策的制定者,但我们正在讨论的情况是,你是公司中唯一的数据人员,所有与数据相关的事情都落在你的肩上。这可能是在任何公司构建数据时最难(也是最重要)的角色部分。
Photo by Franki Chamaki on Unsplash
建立结论
作为一个关于构建数据的故事,你可能已经对一些技术图表、某处的示例气流 DAG 代码块或至少一些伪代码有了印象或预期。但我认为所有这些事情来来去去。要么是行业发生了变化,角色描述发生了变化,要么是技术、流程和技巧发生了变化。此外,已经有很多媒体在谈论如何构建数据基础设施,或者如何在 K8s 中使用 Airflow。
对我来说,在这个故事的背景下,构建数据不仅仅是 Y 公司在启动阶段 z 的技术堆栈 X。在
公司生命的某个阶段,他们需要他们的第一个员工来帮助编写新功能,第一个 IT 人员来帮助供应所有这些新的笔记本电脑,第一个人力资源成员以及他们的第一个数据人员。那个数据人,第一个真正的全职数据人,数据工程师,将不可避免地做更多的事情,而不仅仅是写几个 cron 任务,python 脚本和把一个工具和另一个工具联系起来。为了不失败,这个人将需要建立一个数据基础设施,她将需要在最终用户和她提供的数据之间建立信任,她将需要建立用户对他们拥有的工具和可以帮助他们实现公司目标的数据的欣赏,她将需要在她的同事中建立一个数据驱动的决策思维。作为数据人员,作为数据工程师,所有这些都包含在她的角色中,所有这些都包含在从零开始在公司创造数据文化中。所有这些都封装在建筑数据中。
不用一行代码就能构建数据管道
原文:https://towardsdatascience.com/building-data-pipelines-without-a-single-line-of-code-ccb10ff5abc2?source=collection_archive---------15-----------------------
使用 Google Cloud Dataprep 探索数据的智能而直观的方式。
https://cloud.google.com/dataprep
厌倦了编写大量 python/java 代码来构建 ETL 管道或探索数据集吗?害怕编程来分析数据集?正在寻找一个基于用户界面的分析*台来帮助您处理这些大型数据集吗?对您来说,集成不同的工具是一项庞大而笨拙的任务吗?
瞧啊。你所有的祈祷/疑问都被 Trifacta 的这个叫做Cloud data prep的神奇工具回答了。它是与谷歌云*台集成的合作伙伴服务,支持数据工程和分析领域的众多工作流。在本帖中,你不仅将学习如何使用 dataprep,还将了解与谷歌云*台(GCP)服务的潜在集成。我们将借助 Cloud Dataprep 和 Bigquery 构建一个数据转换管道。
云数据准备概述
Dataprep 是一个基于 web 的、无服务器的、无操作的智能数据服务,可以可视化地对数据集执行探索性分析。它帮助您讨论和探索结构化和非结构化数据,以便进一步处理,用于机器学习、报告仪表板、分析框架等。
建议和预测加载数据的下一次数据转换的惊人能力使得分析对于那些犹豫要不要写代码的人来说变得轻而易举。
但是 dataprep 在数据工程领域,尤其是在 GCP 基础设施中的定位是什么:
From https://cloud.google.com/dataprep/
基于 GCP 的数据工程管道通常由上图中的部分或全部云服务组成。
数据的摄取可以发生在任何组件上,如 Bigquery、云存储或通常的文件上传。接下来是主要部分,在这里您设计您的数据以准备用于更深层次的模型构建和分析目的。这包括原始数据流入一个或多个(根据您的用例)数据处理引擎,如 Cloud Dataprep、Cloud dataflow,转换后的数据输出并存储在 Bigquery 或云存储中。
让我们深入了解构建并运行管道的任务:
任务分解
- 设置您的云控制台
- 将数据导入 BigQuery
- 将 Bigquery 连接到 Dataprep
- Dataprep web 界面的探索性分析
- 数据争论和管道配方
- 计划数据准备作业
进一步阐明以上每一点:
1.设置您的云控制台
一旦你登录到你的谷歌云控制台,创建一个新的项目,这个项目将用于本教程。单击顶部导航栏上的下拉菜单,然后单击+新建项目。
GCP project list page
Click on the NEW PROJECT
icon
Provide the project name and click CREATE
成功创建项目后,确保您在环境中选择的新创建的项目反映在下拉列表中:
关于项目创建和管理的更多细节,这里是到文档的链接。
2.将数据导入 BigQuery
设置好开发环境后,我们需要设置 BigQuery,它在管道中同时扮演输入和输出存储的角色。下面是流程的样子:
Pipeline Flow Architecture
这篇文章的主要焦点是 Dataprep,但是我们需要 BigQuery 来导入数据(摄取)并在转换周期完成后在 Dataprep 中导出输出。
将数据导入 Bigquery 的说明:
- 从云控制台的导航菜单(汉堡图标)中,点击 BigQuery。我们将被带到 BigQuery 控制台,这里有一个左窗格,列出了查询历史、保存的查询等选项,在底部,我们有
Resources
,在它下面必须显示我们的项目。点击并选择您的项目,在右边的查询编辑器下,CREATE DATASET
选项被激活。
2.点击CREATE DATASET
并输入Dataset ID
作为ecommerce_analytics
,这将是我们项目下数据集的名称。将所有其他字段设置为默认,点击底部的Create dataset
按钮。
3.我们的数据集已经准备好以表格的形式存储数据。我们将通过查询来自bigquery-public-data
项目的数据子集,使用来自谷歌商品商店的模糊的谷歌分析 360 数据。它伴随着每个新项目而来。
该查询使用标准 SQL。在查询编辑器中键入或粘贴 SQL 查询:
4.点击运行。左窗格现在应该是这样的:
该查询创建了一个名为subset_user_sessions
的新表,其中包含 2017 年 1 月 1 日发生的 33,664 个用户会话。您可以通过选择左侧窗格中的表格,然后单击右侧的Preview
选项来预览数据。
现在我们已经将数据导入到 BigQuery 中,让我们转到 Dataprep,将它链接到 dataprep 来研究这些数据。
3.将 BigQuery 连接到 Dataprep
在这里,我们将从 Cloud Dataprep 开始,并使用它连接我们的 bigquery 表。以下是该任务的步骤:
注意:你需要一个 Chrome 浏览器,因为 Cloud Dataprep 只能与 Google chrome 配合使用。
- 从导航菜单>打开 Dataprep。
- 您将需要启用计费以使用 Dataprep,如果您在云控制台上还没有计费帐户,则必须从导航菜单的计费部分创建一个。
- 接受服务条款,然后授权 Trifacta 和 Google LLC 访问您的帐户信息。
4.点击Allow
按钮,允许 Trifacta 访问项目数据,同步账户信息需要几分钟时间:
5.选择您想要登录的 Google 帐户,并允许 Trifacta 访问该帐户信息:
6.帐户设置完成后,您将首次被提示设置一个对话框,以提供一个位置来保存我们在 Google 云存储的 Dataprep 中创建的文件。确保选择了正确的项目,然后点击Continue.
7.欢迎来到主游戏场,云数据准备仪表板。一旦我们到了这里,我们就用 BigQuery 开始连接过程。点击右上角的Create Flow
按钮。
8.输入User Analytics Pipeline
作为流程名称并添加流程描述。
9.该从 BigQuery 导入数据集了,点击导入&添加数据集,从左窗格选择 BigQuery 。
10.点击您的数据集,当您的数据集表被加载时,点击如下所示的Create Dataset
图标:
在右侧,一个窗格预览表格数据,单击底部的导入&添加到流程按钮。
连接成功建立,现在您可以向流程中添加新的配方了,因为右侧的Add new Recipe
选项变得可用。
4.Dataprep UI 的探索性分析
现在我们的 BigQuery 项目数据被导入到 dataprep 中,我们可以开始进行探索性数据分析。
EDA 过程中的第一步也是最重要的一步是与手头的数据建立联系,这有助于你评估可以从数据中获得的潜在洞察力。有不同的方法来进行最初的数据理解练习,我的方法是阅读模式描述如果有的话,然后我试着浏览每一列,并准备一个好问题列表来回答这些列或列的组合。
有关 EDA 的更多信息:
[## 探索性数据分析指南
如何用 python 调查数据集?
towardsdatascience.com](/hitchhikers-guide-to-exploratory-data-analysis-6e8d896d3f7e)
从我们上一节离开的地方开始,单击右窗格中的Add new Recipe
按钮,然后单击Edit Recipe
在 Transformer 视图中查看数据。
你可以在这里阅读数据集来理解每一列的含义。因此,让我们定义几个问题,并使用 Dataprep 的工具和特性提取它们的答案。这将帮助我们了解数据和*台:
- 数据帧的形状(行数和列数)是什么?
在 transformer 视图的底部,您会发现我们的示例包含 32 列、12.5K 行和 4 种不同的数据类型。
2。寻找列的最小值,最大值,下四分位数,上四分位数函数。
要了解每列的统计和模式详细信息,请单击列名前面的下拉菜单,然后选择列详细信息。让我们试着找出以下各列的最小值/最大值:
productQuantity
单击列详细信息会将您带到摘要和统计信息页面:
最小购买量为 1,最大购买量为 50。
同样,
最大/最小浏览量:1/115 我们通过几个步骤修正后,就能得出网站花费的最小/最大时间。
注意:答案可能因您的子集而异。
3。直方图在列标题下表示什么?
直方图描述了列中响应的类别。例如版本 2 产品名称可以在上面的截图中看到。如果您将鼠标悬停在条形上,它会告诉您该类别在列中出现的频率,如下所示:
现在,让我们用这个来回答下一个问题。
4。会议发起数量排名前五的国家:
他们依次是:美国>英国>印度>加拿大>日本
5。柱形图的颜色表示什么?
您一定已经注意到列标题下有一个条形,它有不同的颜色,表示缺少和不匹配的数据类型值。
灰色表示缺少值,而红色表示不匹配的值。我们将在下一部分纠正这些错误。
6。常见的流量来源有哪些? 要回答这个问题,我们需要查看模式描述中的channelGrouping
列。有 7 个来源,最常见的是:
有机搜索>转诊>直接
7。常见的产品类别有哪些? 要回答这个问题,我们需要查看模式描述中的v2ProductCategory
列。共有 31 个类别,最常见的有:
极致>服装>电子
5.数据争论和配方制作
既然我们已经知道了与现有数据集相关联的问题,那么让我们来构建转型方案。我们需要为我们发现有问题的列定义数据清理步骤,就像上面数据集中不匹配的时间列一样。
- 修改列
timeOnSite
的数据类型:点击列名前面的下拉菜单,从那里修改类型>整数。它会将所有值的数据类型更改为整数,这将是用户在网站上花费的秒数。
这里重要的一步是注意食谱图标,如果你点击它,会显示一个添加到它上面的步骤,如下所示:
在我们处理数据争论的过程中,这个方法会不断更新。
2。删除未使用的列:如果您仔细观察,会发现有几列有完整的灰色条,表明这些列都是空值(或者没有有效值)。这些列没有用处,是多余的。
注意:我们不能删除所有包含空值的列,因为我们正在处理数据的子集。如果在删除前不确定某列,请阅读该列的说明。
如何删除栏目?
单击列标题下的灰色栏,dataprep 将高亮显示所有缺少的值行。
现在,点击下拉菜单>点击删除。
对 itemQuantity 和 itemRevenue 列重复该过程,因为我们将使用 productQuantity 和 productRevenue 列,因为它们在其中有值,这对收入报告很有用。
现在,更新后的食谱看起来像这样:
3。删除重复行:EDA 中另一个非常常见和有用的步骤是从数据中删除重复行,在 pandas 中我们使用drop_duplicate
函数,这里我们将使用顶部的工具栏。
点击过滤行图标,然后选择移除重复行。 系统会询问您是否要将此步骤添加到配方中,作为将来对所有输入数据集运行的步骤。
点击添加。
4。向配方添加自定义公式:****totalTransactionRevenue列包含交易产生的总收入。从模式文档中,您可以看到它已经乘以了 10⁶,但从数值上看并不清楚。
从下拉菜单>计算>自定义公式:
在打开的右窗格中,添加公式:
我们已经向totalTransactionRevenue列添加了一个定制的**DIVIDE**
公式,预览可以在 transformer 视图中显示。点击添加,添加到配方中。
5。合并列:合并/连接是 EDA 中另一个非常重要和常见的任务,Dataprep 也能以最轻松的方式完成。让我们为每个用户会话创建一个主键列。
我们将 fullVisitorId、time 和 v2ProductName 用于此任务,因为它为每个会话提供了唯一的值,由一个|
分隔,并将新列命名为 main_id 。
点击添加。
这是我带你走过的几个步骤,使用这个智能工具,你可以进行一系列的操作和操纵。
这是食谱现在的样子:
6.运行和调度 Dataprep 作业
现在管道已经准备好运行,点击右上角的运行作业。
因为出于分析或建模的目的,我们需要将转换后的数据添加回新表中的 BigQuery。
点击右侧的添加发布动作,然后选择 BigQuery 作为输出目的地,同步的数据集将变为可用,这里您需要使用右侧窗格中的创建表选项创建一个新表。
点击底部的添加即可:
设置好您需要的地区和机器类型后,单击页面右下角的“运行作业”。这项工作将需要几分钟的时间,一旦完成,您可以在 BigQuery 中检查您的结果,带有转换数据的表格正等着您!!
调度作业
另一个重要的特性是在 dataprep 上调度作业运行的能力。在流程页面上,点击顶部的 3 个点图标,然后选择计划流程。
您可以选择时区、频率、日期和时间,如下所示:
结论
谁会想到将创建管道这一费力的任务简化到这种程度?正如我们所说,谷歌云团队正在添加一些无与伦比的工具和功能,以重新定义云计算的含义。在估算了 dataprep 为我们节省的工时数后,我着迷了,没有比这更有用、连接更好、界面更友好的工具了。更多有趣的工作流将被讨论,我很高兴揭开我要讲述的关于 GCP 数据工程的故事。敬请期待!!
Harshit 的数据科学
通过这个渠道,我计划推出几个涵盖整个数据科学领域的系列。以下是你应该订阅频道的原因:
- 该系列将涵盖每个主题和副主题的所有必需/要求的高质量教程。
- 解释了为什么我们在 ML 和深度学习中做这些事情的数学和推导。
- 与谷歌、微软、亚马逊等公司的数据科学家和工程师以及大数据驱动型公司的首席执行官的播客。
- 项目和说明,以实现迄今为止所学的主题。
你可以在 LinkedIn 、 Twitter 或 Instagram 上与我联系(在那里我谈论健康和福祉。)
注意:在这些黑暗的时期,自我隔离为自我提升腾出了一些空间,我们可以利用这些空间来发展新的技能、爱好,并帮助未来的自己。
构建数据科学能力意味着长期博弈
原文:https://towardsdatascience.com/building-data-science-capabilities-means-playing-the-long-game-f68166ecf2f?source=collection_archive---------21-----------------------
"管理就是在制定长期计划的同时进行短期管理."
——杰克·韦尔奇
您是否对寻找和留住不需要大量时间和投资来发展的数据科学员工的挑战感到沮丧?你并不孤单。
最*在一次机器学习会议上,有人向我表达了对持续的数据科学人才短缺的厌倦。一家知名数据驱动型公司的高管哀叹道,他就是找不到“优秀的数据科学人才,他不必花大量时间去培训他们”。他的观点是可以理解的。这家公司多年来一直在数据科学能力上投资,远远领先于其竞争对手,并且仍在努力寻找和培养经验丰富的数据科学人才。
为什么?因为对顶级分析人才的竞争持续加剧,留住这些人才变得非常困难和昂贵,即使对于最数据驱动的品牌公司也是如此。此外,技术和所有计算机科学继续以闪电般的速度发展,而 zettabytes 的数据堆积如山。面对这些越来越多的挑战,也许是时候组织重新思考他们创建数据科学团队的方法了。
那么,该怎么办呢?美国政府给了我们一个线索。继最*关于保持美国在人工智能领域领先地位的行政命令之后,美国前首席技术官 Meghan Smith 敦促学校儿童学习代码并玩树莓派的作为国家的必要事项。
这些权力正在向世界传递一个简单但关键的信息:在数据科学和人工智能方面,要为技能的长期发展进行规划和投资。不这样做的后果也很简单。您将数据科学人才融入组织的努力将永远不会停止。
你说的这些都不错,但是面对前面提到的每天产生的 zettabytes 数据以及从这些数据中获取价值的紧迫性,公司需要专注于当前迫切的数据科学需求。他们现在需要数据科学家。他们不能等待现在的八年级学生掌握技能并毕业。那么,他们有什么选择呢?
QuantHub 在数据科学技能方面的经验
在 QuantHub,我们一次又一次地看到从入门级数据科学家、数据工程师到博士候选人的实际数据科学技能评估分数。你知道吗?技能无处不在。很少有候选人能在各种技能中脱颖而出。尽管如此,我们坚信有一个良好的数据科学人才“潜力”基础,正等待着进一步开发。这是缓解我们裁谈会的朋友的疲劳感的关键所在。
An example of the variety of skills scores we see on data science/engineering assessments
所以,让我们像麦肯锡那样定义长期游戏
我是麦肯锡研究的粉丝。他们往往处于一切事物的最前沿,并且长期以来一直非常活跃地研究数据科学领域。以下是麦肯锡如何推广雇佣数据科学家的想法,以提供一些视角。
十多年前的 2007 年,麦肯锡发布了“八大值得关注的商业技术趋势”。在那篇文章中,它引用了“将更多科学纳入管理”是一种趋势,“技术正在帮助经理们利用越来越多的数据来做出更明智的决策,并开发创造竞争优势和新商业模式的洞察力。”是的,没错——他们 12 年前就这么说了。
然后在 2011 年,麦肯锡写了一份名为“大数据:创新、竞争和生产力的下一个前沿”的报告,其中它称赞大数据是一股“不断增长的洪流”,有各种统计数据可以证明这一点。五年后的 2016 年,产生了一项后续研究“分析时代:在数据驱动的世界中竞争”。这是它三年前给出的观点,
当我们评估过去五年取得的进展时,我们看到公司正在数据和分析上下大赌注。但是,对于个人或组织来说,适应一个更加数据驱动的决策时代并不总是一件简单的事情。许多人正在努力培养人才、业务流程和组织能力,以从分析中获取真正的价值。这正成为一个紧迫的问题,因为分析能力越来越成为行业竞争的基础,而领导者们正在锁定巨大的优势。与此同时,技术本身正在取得重大的飞跃——下一代技术有望带来更大的突破。机器学习和深度学习能力有着各种各样的应用,深入到迄今为止在很大程度上处于边缘地位的经济领域。
快进到 2018 年,麦肯锡发布了“分析时代来临”,其中提出“数据是这个领域的硬币。”翻译:数据是非常有价值的,哦,顺便说一下,10 多年来,我们一直告诉你要发展能力和才能,从数据中获取价值。时间到了。
这是什么意思?如果你早在 2007 年就加入了这股潮流,并在那时开始投资大数据分析,理论上,你可能要等十多年,你的分析投资才会“成熟”并成为有价值的“硬币”。
那么为什么在这个领域工作的员工不能享受同样的时间和投资呢?
发展数据科学能力的长期路线图
正如我之前提到的,数据科学人才潜力很大,但大部分都不完美。为了利用这种人才,然后发展数据科学能力,公司需要制定一个长期计划来实现这一点,然后实施它。
这里有一个路线图,用于开发一个多管齐下的长期方法来“训练优秀的人”成为更好的数据科学家。
1.放弃独角兽,真的
就像机器学习高管一样,你不能因为沮丧而继续把头埋在沙子里,而不承认当今数据科学就业市场的现实。你永远也找不到你需要的确切候选人。当面临大数据带来的紧迫挑战时,人们很容易幻想不存在的完美解决方案。因此,正如弗雷斯特研究公司的人最*所说的,“小心独角兽”。认识到你正在寻找独角兽,努力快速找到解决方案。接受你找不到这些人的事实,然后继续下一步。
2.认识并修正你招聘过程中的缺陷
分析和数据科学标准倡议最*的一项研究发现,数据科学家和数据工程师在 LinkedIn 简历中列出的技能与雇主对数据科学和分析职位要求的技能之间存在很大的脱节。虽然候选人列出了适用于数据科学领域的各种硬技能和软技能,但雇主招聘的是非常具体的技术技能,尤其是编程语言。
在雇主为数据科学职位列出的前 10 项必备技能中,几乎所有技能都是编程语言,而实际的数据科学家通常拥有几种非编程技能,如数据分析和统计,以及其他相关技能,如雇主要求中完全不存在的数据争论。
还有许多其他证据表明,数据科学人才的招聘流程存在缺陷,无论是公司不知道他们招聘的是什么技能,人力资源经理无法正确筛选候选人,还是要求不必要的高等学位。也许这位高管所在的公司长期以来一直使用相同的招聘和保留策略,以至于没有根据就业市场和现有人才调整其招聘和发展流程。
无论如何,数据科学招聘要求和数据科学候选人的现实之间的持续脱节肯定会导致无法找到“优秀人才”进行培训和发展。他们只是在招聘过程中被忽视了。
3.开发数据科学人才的组合视图
许多组织尚未认识到在将数据科学应用于业务战略时成功所需的人才和技能组合。现实是,没有一个人,甚至两个数据科学家能够涵盖所有的基础,也不应该期望他们这样做。因此,你应该致力于开发一个由个人组成的组合,这些个人共同拥有你所需要的才能。
在我最*主持的一次网上研讨会中,来自 Protective Life 和 Regions Bank 的数据科学高管都描述了在软硬技能组合和教育程度方面雇佣多样化数据科学人才的类似策略。作为高度量化行业中经验丰富的数据分析经理,这些企业领导人认识到这是在其组织中建立和保持长期成功的数据科学能力的唯一途径。
做到这一点的第一步是定义随着时间的推移组织所需的人才,而不是定义具有特定技能的团队成员或特定数据项目所需的技能集。与其考虑投资 100,000 美元以上来招聘特定的角色,不如考虑如何投资开发组织在数据工作中取得成功所需的技能和人才。您可能会发现,这些远远超出了大多数公司在规划数据科学计划时招聘的典型“R”编码语言和 SQL 功能。
一个完善的数据科学战略可能需要功能领域知识来帮助确定高价值的商业案例,需要设计思维技能来帮助头脑风暴解决方案,需要财务技能来创建令人信服的商业案例,需要数据工程和争论技能来以所需的形式提供对正确数据的访问,还需要机器学习技能来推动人工智能技术的执行。你真的能让一两个人做到这一切吗?大概不会。
4.技能和才能的交叉培训
与前一点类似,保护生命采取的另一种故意的方法是他们称之为“异花授粉”。这意味着他们雇佣不同的人,他们拥有不同但需要的技能,然后把这些人放在一个房间里一起工作很长时间,有很多咖啡和休息时间。随着时间的推移,这为技能交流和知识共享提供了大量机会。他们还定期派这些人到组织中去与商务人士合作和喝咖啡。异花授粉成功的关键是有目的地为其自然发生创造“空间”。
5.把终身学习的目标放在学位和即时技能上
关于严格遵守特定学位资格是否导致了大量数据科学人才短缺的争论仍在激烈进行。例如,在制药行业,从事人工智能研究的本科生除非拥有硕士或博士学位,否则没有晋升机会是很常见的。这种符合晋升资格的严格要求完全没有必要,是短视的,可能反映了企业不愿意或没有能力投资于初级数据科学人才的长期培训和发展。因此,被招聘的人才看不到职业发展,要么表现不佳,要么在其他地方寻找发展机会。
此外,那些自学的数据科学训练营毕业生可能不具备最完美的编码技能。然而,他们有一项已展示的技能:学习具有挑战性的材料和开发高难度技能的动力。众所周知,数据科学和商业智能技术日新月异。编码语言会来来去去。技术将会迅速发展。随着时间的推移,自我激励学习和发展的人是你可以长期投资的人,这样做的话,你就可以在你的组织中留住他们。
扪心自问:谁更忠诚?一个随时随地都能找到高薪工作的博士?或者是一个聪明但自学成才的毕业生,渴望成长和学习,并寻求进一步提高他们的工作技能——即使是在业余时间?
6.构建旨在培养数据科学人才的职业道路
该地区银行采取的一项策略是,允许并鼓励其数据科学家和分析师在组织内流动。它在新员工和年度绩效评估中公开讨论和计划这一点。因此,入门级数据科学家将进入一个部门,并知道在该部门学习所有内容后的几年内,他们将有机会转移到组织的一个新领域,在那里他们可以继续发展,做出贡献并得到认可。
这一策略很好地体现了一个非常简单的事实:就在您最优秀的数据科学家开始大展拳脚的时候,他们也可能会考虑成家立业,从而在您的组织内寻找新的机遇和挑战,而不是面临跳槽。当他们看到自己有前途,可以开始考虑其他人生目标时,他们可能会计划在你的公司呆更长时间。
除此之外,公司应该开始为所有员工创建一个混合职业发展轨道——一个与数据科学和业务*行的轨道,它允许业务人员进入分析领域,反之亦然。例如,如果您的公司能够负担得起,您可以实施教育和培训计划,为有兴趣获得分析资格和技能的员工提供支持。这些员工可以享受学费补贴,以换取他们同意在贵公司工作一定年限。
7.使数据科学民主化
培养和发展数据科学家的真正长期解决方案来自数据科学的民主化。公司必须找到方法,停止将数据科学知识降级给少数高度专业化、拥有博士学位的准独角兽。数据科学的责任正以前所未有的速度增长。这给数据科学团队本身以及招聘人员和经理带来了巨大的压力。
因此,麦肯锡、哈佛、德勤和 Airbnb 等公司一直倡导的是数据科学的民主化,以此作为解决数据科学人才短缺的一种方式,但更重要的是,作为提取数据科学真正价值的关键一步。公司正在建立数据科学大学来培训所有管理人员,并雇用“混合”角色,如可视化专家,以帮助弥合数据科学家和组织其他人员之间的差距。
一些公司还在积极实施自动化工具、预训练模型和自助服务分析,以使数据科学技术和技能更容易为整个组织所用。随着时间的推移,数据科学的民主化可能会减轻数据科学团队的压力,并促进对他们真正需要的培训程度做出更公*的判断。
诚然,大多数公司离数据科学民主化还很远,但实现这一目标的速度可能比你想象的要快。
十年后…
很明显,如果不在人才招聘和以新方式规划数据科学人才的未来发展方面冒一些风险,就没有一种方法可以立即满足广泛的数据科学需求。组织需要采取措施,缓解目前对数据科学候选人和试图聘用他们的人提出的不切实际的要求。这需要从长远着眼,在组织内开发一套更加*衡的能力。
许多提议的步骤实际上并不需要太多的额外投资。与招聘和雇佣一名“现成”数据科学家的成本相比,新兵训练营和 LinkedIn Learning 并不那么昂贵。相反,我们需要的是承认雇佣现成的数据科学家是一个日渐式微的选择。现在就开始制定你的长期路线图,也许在 10 年后,当麦肯锡报告称人工智能已经“成熟”时,你将拥有一支本土和忠诚的数据科学家团队,随时准备利用数据科学的未来所提供的一切。
构建分布式应用程序:第一*似值
原文:https://towardsdatascience.com/building-distributed-apps-first-approximation-2bbab777f6b2?source=collection_archive---------28-----------------------
在之前的文章中,我们已经讨论了反应式架构的理论基础。现在是时候讨论数据流、实现反应式 Erlang/Elixir 系统的方法以及其中包含的消息交换模式了:
- 请求-响应
- 请求分块响应
- 带请求的响应
- 发布-订阅
- 反向发布-订阅
- 任务分配
SOA、MSA 和消息传递
SOA 和 MSA 是定义系统开发规则的服务架构。反过来,消息传递为我们提供了实现它们的原语。
我不想提倡任何特定类型的建筑。我完全赞成使用完全满足某个项目或业务需求的实践。无论我们选择什么样的范例,系统组件都应该用 Unix 方式来创建:具有最小连接性的组件实现不同的系统实体。API 方法对实体执行基本操作。
消息传递,从名字就能猜到,是一个消息代理。它的主要目的是接收和发送信息。此外,它还负责消息发送接口、创建逻辑数据通信通道、路由、*衡和处理系统级故障。
正在开发的消息传递并不试图与 Rabbitmq 竞争或取代它。其主要特点如下:
- 分布式自然。可以在集群的任何节点上创建交换,尽可能靠*利用它们的代码。
- 简约。面向可用性和样板代码的最小化。
- 更好的性能。我们并不试图复制 Rabbitmq 的功能。我们只是强调架构和传输层,并将它们嵌入到 OTP 中,同时降低成本。
- 灵活性。每个服务都可以集成许多交换模式。
- 容错体现在设计中。
- 可扩展性。信息与应用一起成长。随着负载的增加,我们可以将一些交换点放在不同的机器上。
注意。 就代码组织而言,元项目也就是伞状项目非常适合 Erlang/Elixir 中的复杂系统。所有的项目代码都位于一个存储库中——保护伞项目。同时,微服务被尽可能地隔离,并执行由独立实体负责的简单操作。在这种方法下,很容易支持整个系统的 API。您还可以毫不费力地进行更改并编写单元测试或综合测试。
在服务架构中,组件直接或通过代理进行交互。从消息传递的角度来看,每个服务都有多个生命阶段:
- 服务初始化。在这一阶段,初始化和启动流程及其所有依赖项。
- 创建交易所。服务可以使用节点配置中给定的静态交换,也可以动态创建交换。
- 服务注册。服务必须在 exchange 上注册才能处理请求。
- 正常工作。在这种模式下,服务处理用户的请求。
- 过程的终止。有两种可能的终止方式:正常终止和崩溃终止。在第一种情况下,服务从交换机断开并停止。然而,在崩溃的情况下,消息传递执行处理故障的场景之一。
这看起来可能有点复杂,但是如果你看一下代码,实际上并没有那么糟糕。本文稍后将给出一些代码示例。
交换
交换是消息服务的内部过程。它在定义的消息交换模式中提供不同系统组件之间的交互逻辑。
在下面的所有示例中,组件通过交换进行交互,交换的组合创建了消息传递。
消息交换模式(MEP)
一般来说,所有的 MEP 都可以分为双向和单向模式。前者意味着对收到的信息作出反应,后者则不然。客户机-服务器体系结构中双向 MEP 的一个经典例子是请求-响应模板。让我们仔细看看这个和它的修改。
请求-响应或 RPC
当我们需要从另一个进程获得响应时,就会用到 RPC。这个过程可以在同一个节点开始,甚至可以位于不同的洲。下图展示了通过消息传递实现的客户端-服务器交互。
因为消息传递是完全异步的,所以客户端的交换包括两个阶段:
- 发送请求。
messaging:request(Exchange, ResponseMatchingTag, RequestDefinition, HandlerProcess)
交换是唯一的交换名称
ResponseMatchingTag 用于处理响应的本地标签。例如,当属于不同用户的几个相同的请求被发送时。
请求定义**请求体
**处理器流程处理器 PID。这个过程将得到一个服务器响应。
- 收到回应
*handle_info(#'$msg'{exchange = EXCHANGE, tag = ResponseMatchingTag,message = ResponsePayload}, State)*
ResponsePayload 是服务器响应。
对于服务器,该过程也分两个阶段进行:
- Exchange 初始化
- 请求的处理
这种模式可以用代码来说明。假设我们必须创建一些简单的服务来提供精确时间的方法。
首先,让我们将 API 定义代码放入 api.hrl :
*%% =====================================================%% entities%% =====================================================-record(time, { unixtime :: non_neg_integer(), datetime :: binary()}).-record(time_error, { code :: non_neg_integer(), error :: term()}).%% =====================================================%% methods%% =====================================================-record(time_req, { opts :: term()}).-record(time_resp, { result :: #time{} | #time_error{}}).*
让我们在 time_controller.erl 中定义服务控制器
*%% The example shows the main code only. If you insert it into gen_server pattern, you will get a proper working service.%% gen_server initializationinit(Args) -> %% connection to exchange messaging:monitor_exchange(req_resp, ?EXCHANGE, default, self()) {ok, #{}}.%% processing of exchange disconnection events. The same happens if an exchange hasn’t been run yet.handle_info(#exchange_die{exchange = ?EXCHANGE}, State) -> erlang:send(self(), monitor_exchange), {noreply, State};%% API processinghandle_info(#time_req{opts = _Opts}, State) -> messaging:response_once(Client, #time_resp{ result = #time{ unixtime = time_utils:unixtime(now()), datetime = time_utils:iso8601_fmt(now())} }); {noreply, State};%% gen_server terminationterminate(_Reason, _State) -> messaging:demonitor_exchange(req_resp, ?EXCHANGE, default, self()), ok.*
客户端代码放在 client.erl. 向服务发送请求,我们可以在客户端的任何部分调用消息请求 API:
*case messaging:request(?EXCHANGE, tag, #time_req{opts = #{}}, self()) of ok -> ok; _ -> %% repeat or fail logicend*
我们不知道系统的状态,因为它依赖于请求到达时各种系统组件的状态。当请求到来时,消息传递可能还没有运行,或者服务控制器可能还没有准备好处理请求。这就是为什么我们必须检查消息响应并处理失败。
如果请求被提交,服务可以用一个响应或一个失败来回答。让我们在 handle_info 中处理这两种情况:
*handle_info(#'$msg'{exchange = ?EXCHANGE, tag = tag, message = #time_resp{result = #time{unixtime = Utime}}}, State) -> ?debugVal(Utime), {noreply, State};handle_info(#'$msg'{exchange = ?EXCHANGE, tag = tag, message = #time_resp{result = #time_error{code = ErrorCode}}}, State) -> ?debugVal({error, ErrorCode}), {noreply, State};*
请求分块响应
更安全的做法是不要发送太大的消息,因为它们可能会影响系统的总体响应能力和性能。如果一个响应占用了太多的内存,那么拆分就至关重要。
这里有几个例子:
- 组件正在交换二进制数据,例如一些文件。将响应分成小块有助于我们处理任何大小的文件,并防止内存溢出。
- 清单例如,我们需要选择数据库中巨大表格的所有行,并将其传输到另一个组件。
这种反应有时看起来像一列火车。无论如何,1024 条 1mb 的消息比一条 1gb 的消息要好。
Erlang 集群带来了额外的好处,因为响应绕过交换机直接到达接收方,所以减少了交换机和网络的负载。
带请求的响应
这是一个非常罕见的构建对话系统的 RPC 模式的修改。
发布-订阅(数据分布树)
事件驱动系统在数据准备好的时候向用户交付数据。系统更倾向于推模型,而不是拉或轮询模型。这个特性使我们在不断请求和等待数据时不会浪费资源。
该图显示了向订阅某个主题的用户分发消息的过程。
这种模式应用的一个经典案例是状态分布:它可以是计算机游戏中的游戏世界、金融交易中的市场数据或数据馈送中的有用信息。
看一下用户代码:
*init(_Args) -> %% subscribe to exchange, routing key = key messaging:subscribe(?SUBSCRIPTION, key, tag, self()), {ok, #{}}.handle_info(#exchange_die{exchange = ?SUBSCRIPTION}, State) -> %% if an exchange is unavailable, we are trying to reconnect to it messaging:subscribe(?SUBSCRIPTION, key, tag, self()), {noreply, State};%% process received messageshandle_info(#'$msg'{exchange = ?SUBSCRIPTION, message = Msg}, State) -> ?debugVal(Msg), {noreply, State};%% if a consumer stops, disconnect from exchangeterminate(_Reason, _State) -> messaging:unsubscribe(?SUBSCRIPTION, key, tag, self()), ok.*
发布者可以通过函数调用在任何合适的地方发布消息:
*messaging:publish_message(Exchange, Key, Message)*
**交易所交易所名称、
**键路由键、
**信息有效载荷。
反向发布-订阅
当我们反转发布-订阅时,我们得到一个有利于日志记录的模式。生产者和消费者可以有很大的不同。该图显示了一个消费者和多个生产者的情况。
任务分配模式
几乎每个项目都向我们提出了延期处理任务的挑战,比如生成报告、发送通知、从第三方系统获取数据。通过增加工人,系统容量很容易扩展。现在剩下的就是组成一群工人,并在他们之间*均分配任务。
让我们考虑一个有三个工人的例子。在分配任务的阶段,我们面临着分配的公*性和工人超负荷的问题。Round-robin 将负责提供公*性,而 prefetch_limit 将防止工人过载。在临时模式下,prefetch_limit 不允许一个工人获得所有任务。
消息控制队列和处理优先级。工人来了就有任务。任何任务都可以成功完成,也可以失败。
- 消息传递:当消息被成功处理时,ack(Tack) 被调用
- 信息:nack(Tack) 在所有紧急情况下都会被调用。任务返回后,消息会将其重新发送给另一个工作人员。
让我们假设在处理 3 个任务时发生了复杂的故障。工人 1 在获得任务后崩溃,并且未能通知交换。在这种情况下,当确认超时时,交换将任务重定向到另一个工作者。出于某种原因,工人 3 拒绝了该任务并发送了 nack。结果,这个任务被另一个设法完成它的工人处理掉了。
初步结论
在本文中,我们仔细研究了分布式系统的主要构件。我们还对它们在 Erlang/Elixir 中的实现有了基本的了解。
通过组合基本模式,您可以构建复杂的范例来应对新出现的挑战。
最后一部分将集中在管理服务、路由和*衡的一些一般性问题上。我们还将讨论系统可伸缩性和容错性的实际方面。
第二部分的结尾。
照片由马里乌斯·克里斯滕森
用 websequencediagrams.com 制作的插图
构建分布式应用程序:二次*似
原文:https://towardsdatascience.com/building-distributed-apps-second-approximation-f792b3fe893f?source=collection_archive---------27-----------------------
本文是关于 Erlang/Elixir 中分布式反应式应用的系列文章的最后一篇。在第一篇文章中,你会找到反应式架构的理论基础。第二个展示了构建这种系统的主要模板和机制。
今天我们将讨论代码库开发和项目开发的一般问题。
服务机构
当我们在现实生活中处理服务开发时,我们经常需要在一个控制器中组合几种交互模式。例如,执行管理项目用户配置文件的服务必须响应 req-resp 请求,并使用发布-订阅发送配置文件更新事件的通知。这种情况非常简单:在消息传递的背后,只有一个控制器实现服务逻辑并发布更新。
当我们必须创建一个容错的分布式服务时,事情变得更加复杂。让我们假设对用户服务的要求发生了变化:
- 该服务现在必须在集群的 5 个节点上处理请求,
- 它必须能够执行后台处理任务,
- 它还应该能够动态管理订阅列表
注意:在本文中,我们并不解决数据的一致存储和复制问题。让我们假设这些问题以前已经解决了——系统已经有了一个可伸缩的、可靠的存储层,处理程序可以与之交互。
用户服务的形式化描述变得更加复杂。从程序员的角度来看,由于使用了消息传递,所以变化很小。为了满足第一个要求,我们必须在请求-响应上定义*衡算法。
处理后台进程的需求经常出现。在用户中,它可以检查用户的文档,处理下载的多媒体或与社交网络同步数据。这些任务应该分布在集群中,并且必须控制它们的实现。这就是为什么我们有两个选择:要么使用前一篇文章中的模式,要么如果它不适合我们,编写一个定制的任务调度程序,它将控制处理程序池。
第三点需要发布-订阅模式扩展。要实现它,我们应该首先创建一个发布-订阅交换,然后在我们的服务中运行这个交换的控制器。这样,我们就把订阅事件和订阅者列表的管理从消息层转移到了用户实现。
因此,任务分解表明,为了满足需求,我们应该在不同的节点上运行服务的 5 个副本,并创建一个额外的实体—负责订阅的发布-订阅控制器。
要运行 5 个处理程序,没有必要更改服务代码。只有一个额外的行动——设定交易所的*衡规则。我们稍后会谈到这一点。此外,还有一个困难:发布-订阅控制器和定制的调度程序必须单独工作。作为基础的消息传递服务必须提供一种领袖选举的机制。
领导人选举
在分布式系统中,这是指定负责在集群上调度和分配任务和负载的唯一进程的过程。
在不倾向于集中的系统中,使用一些通用的和基于共识的算法,例如 paxos 或 raft。
由于消息传递同时是一个代理和一个中心元素,它知道所有服务控制者——领导候选人。消息传递可以不经投票任命领导人。
启动并连接到 exchange 后,所有服务都会收到一条系统消息:
'$leader'
如果 LeaderPid 与当前进程 Pid 匹配,它将被指定为 leader。服务器列表包括所有节点及其参数。
当一个新的集群节点出现并且当前工作的集群节点关闭时,所有的服务控制器
'$slave_up'
和
'$slave_down'
分别是。
这样,所有的组件都知道所有的变化。此外,在任何给定的时刻,集群中只有一个确定的领导者。
中间件
如果我们需要实现复杂的分布式处理或优化现有的体系结构,中间件使用起来很方便。
如果您不想更改服务代码并处理额外的处理、消息日志的路由等问题,您可以打开代理处理程序,它将完成所有的工作。
发布-订阅优化的一个经典例子是一个分布式应用程序,其业务核心是生成更新事件,如市场价格的变化。这样的应用也有一个访问层——N 个服务器,为 web 客户端提供 websocket API。
客户服务,如果直接处理它,看起来像这样:
- 客户端与*台建立连接。在服务器端,终止流量,启动服务于此连接的进程。
- 更新授权和订阅发生在服务流程中。该流程调用主题的 subscribe 方法。
- 当一个事件在核心中生成时,它被传递给服务于该连接的进程。
假设我们有 50000 名主题为“新闻”的订户。订户*均分布在 5 台服务器上。最终,每次更新到达 exchange 时,都会被复制 50000 次:根据订阅者的数量,每台服务器复制 10000 次。看起来不是一个有效的计划,对吗?
为了改进它,让我们引入一个与交换同名的代理。全局名称注册管理机构必须能够在一个组中通过名称解析最*的进程,因为这很重要。
然后,让我们在接入层服务器上运行这个代理。我们所有服务于 websocket api 的进程都将订阅它,而不是订阅内核中的初始发布-订阅交换。代理仅在唯一订阅的情况下订阅核心,并将其获得的消息复制给所有订阅者。
因此,将在核心服务器和访问服务器之间发送 5 条消息,而不是 50000 条。
路由和*衡
请求-响应
在当前的消息传递实现中,有 7 种请求分发策略:
- 默认。请求发送到所有控制器。
- 循环赛。以循环的方式为输入的请求分配控制器。
- 共识。提供服务的控制器分为主控制器和从控制器。请求只发给领导。
- 共识&循环赛。组中有一个领导者,但是请求在所有成员之间分配。
- 粘粘的。哈希函数是为某个处理程序计算和保留的。具有此签名的所有后续请求都发送到同一个处理程序。
- 粘人好玩的。当交换被初始化时,应该定义用于粘性*衡的散列函数。
- 好玩。相当于 sticky-fun,但你也可以重定向,拒绝或预处理它。
发行策略是在交易所初始化时定义的。
除了*衡,消息传递使我们能够标记实体。让我们看看系统中的标签类型:
- 连接标签。让我们了解事件发生的关联。当控制器进程连接到同一个交换机但具有不同的路由关键字时使用。
- 服务标签。允许我们在一个服务内将处理者联合成组,并扩展路由和*衡机会。对于请求-响应模式,路由是线性的。我们向交换机发送请求,交换机将请求传递给服务器。然而,如果我们必须将处理程序分成逻辑组,那么这种划分是在标签的帮助下完成的。如果指示了标签,请求将被发送到某一组控制器。
- 请求标签。让我们能够区分不同的反应。由于我们的系统是异步的,我们需要有机会指示 RequestTag 来处理服务响应。通过这个标签,我们将了解我们所收到的请求的响应。
发布订阅
有了 pub-sub 就简单多了。我们有一个交易所,可以让信息被发布。交换在订阅了所需路由关键字的订阅者之间分发消息(可以说这相当于主题)。
可扩展性和容错性
系统可伸缩性通常取决于其层和组件的可伸缩性:
- 通过向群集中添加带有服务处理程序的额外节点来扩展服务。人们可以在试运行期间选择最佳的路由策略。
- 特定集群中的消息服务本身通常通过将负载最重的交换移动到单独的集群节点或者通过将代理进程添加到负载最重的集群区域来进行扩展。
- 整个系统的可伸缩性取决于体系结构的灵活性以及将独立的集群合并成一个逻辑实体的机会。
项目的成功通常取决于简单性、快速转换和可伸缩性。当前实现中的消息传递随着应用程序而增长。即使 50-60 台机器的集群对我们来说不够,我们也可以使用联盟。不幸的是,联邦的问题超出了本文的范围。
保留
在讨论负载*衡时,我们已经讨论了服务控制器预留。然而,消息也应该被保留。如果一个节点或一台机器出现故障,消息传递必须尽快自动恢复。
在我的项目中,我使用了额外的节点,这些节点可以在出现故障时承担部分负载。Erlang 为 OTP 应用程序提供了分布式模式的标准实现。分布式模式通过在另一个已经预先启动的节点上运行失效的应用程序来负责恢复。过程很清楚:出现故障后,应用程序会自动转移到故障转移节点。您可以在此获得关于此功能的更多详细信息。
表演
让我们尝试,至少粗略地,将 rabbitmq 的性能与我们定制的消息传递的性能进行比较。
我看到了 openstack 团队的 rabbitmq 的官方测试结果:
(https://docs . open stack . org/developer/performance-docs/test _ results/MQ/rabbit MQ/cmsm/index . html)。
第 6.14.1.2.1.2.2 点。文档中显示了以下 RPC 转换结果:
让我们不要使用任何 OS 内核或 erlang VM 的高级设置。
测试环境:
- erl opts: +A1 +sbtu。
- 一个节点内的测试是在一台笔记本电脑上运行的,该笔记本电脑配有旧的移动版英特尔 i7。
- 集群测试在 10G 网络的服务器上运行。
- 代码在 docker 容器中工作。网络处于 NAT 模式。
测试的代码:
req_resp_bench(_) -> W = perftest:comprehensive(10000, fun() -> messaging:request(?EXCHANGE, default, ping, self()), receive #'$msg'{message = pong} -> ok after 5000 -> throw(timeout) end end ), true = lists:any(fun(E) -> E >= 30000 end, W), ok.
场景 1:测试在一台装有旧版移动版英特尔 i7 的笔记本电脑上运行。测试、消息和服务都在同一个节点和一个 docker-container 中实现:
约 0 秒内连续 10000 次循环(26987 次循环/秒)
约 1 秒内连续 20000 次循环(26915 次循环/秒)
约 4 秒内连续 100000 次循环(26957 次循环/秒)
并行 2 在 2 秒内完成 100000 次循环(44240 次循环/秒)
在大约 2 秒内并行 4 个 100000 周期(53459 周期/秒)
在约 2 秒内并行 10 个 100000 周期(52283 周期/秒)
在大约 3 秒内并行 100 个 100000 周期(49317 周期/秒)
场景 2: 3 个节点通过 docker (NAT)运行在不同的机器上。
约 1 秒内连续 10000 次循环(8684 次循环/秒)
约 2 秒内连续 20000 次循环(8424 次循环/秒)
约 12 秒内连续 100000 次循环(8655 次循环/秒)
并行 2 在 7 秒内完成 100000 次循环(15160 次循环/秒)
在大约 5 秒内并行 4 个 100000 周期(19133 周期/秒)
在大约 4 秒内并行 10 个 100000 周期(24399 周期/秒)
在大约 3 秒内并行 100 个 100000 周期(34517 周期/秒)
在所有情况下,CPU 利用率都没有超过 250%。
结果
我希望这个系列看起来不像是一个大脑垃圾场,并且我的经验对于分布式系统研究人员和刚刚起步的从业者来说都是真正有用的。我敢肯定,他们中的一些人对 Erlang/Elixir 很感兴趣,但也有疑虑。
公告。
在初秋,我将发表另一个关于排队系统工程的系列文章:《 VTrade 实验——为交易系统写一个框架的尝试》。在这个系列中,我们将讨论建立一个交易交易所、一个拍卖场和一个商店的理论和实践。
构建分布式应用程序:零*似值
原文:https://towardsdatascience.com/building-distributed-apps-zero-approximation-b0c4b16f92d3?source=collection_archive---------31-----------------------
如今,世界发展迅速。进步不断带来新的技术挑战。信息系统架构应该足够灵活,能够响应新的需求并不断发展。在本文中,我们将讨论事件驱动的架构、并发性、并行性、异步性,以及如何与 Erlang 中的所有这些和*共处。
介绍
作为开发人员,我们根据系统的规模和需求选择这种或那种类型的信息交换。在大多数情况下,可以用来协调服务的是一个带有代理的模式,例如,基于 RabbitMQ 或 kafka。有时,事件流、SLA 和对系统的控制级别使得现成的消息传递不适合我们。当然,你可以把系统稍微复杂一点,使用 ZeroMQ 或者 nanomsg。通过这样做,您将负责传输层和集群的形成。但是,如果系统缺乏吞吐量或标准的 Erlang 集群容量,那么添加额外实体的问题就需要检查和经济合理性。
反应式分布式应用的主题相当广泛。为了符合本文的格式,今天我们将重点讨论基于 Erlang/Elixir 构建的同构环境。Erlang/OTP 生态系统使我们能够以最少的时间和精力实现反应式架构。无论如何,我们需要一个消息传递层。
理论框架
工程从定义目标和限制开始。主要目的不在于为了发展而发展。我们需要的是得到一个安全的、可伸缩的工具,让我们创建和开发各种层次的现代应用程序。这些应用可能从服务于一小部分受众的单个服务器应用到 50–60 个节点的集群或集群联盟。因此,我们的主要目标是通过降低系统开发和拥有成本来实现利润最大化。
让我们强调一下目标系统的 4 个要求:
- 可计算性。独立单元可以垂直和水*缩放。还应该有机会无限制地横向扩展整个系统;
- E 发泄驱使的天性。系统总是准备好处理事件流并对其进行处理;
- L 有保证的热情。时间就是金钱,所以用户不应该等待太久;
- 故障容差。所有级别和服务都必须在出现故障时自动恢复。
如果该系统的基础满足 SELF 的最低要求,则该系统可以从 MVP 阶段前进并且是渐进的。消息传递作为基础设施工具和所有服务的基础,其特点是对程序员也很有用。
事件驱动的性质
为了让一个应用程序可以从一个服务器扩展到一个集群,它的架构应该提供松散耦合。异步模型满足了这一要求。在这样的模型中,发送者和接收者都关心他们的消息的信息负载,而不担心消息传递或路由。
可量测性
可伸缩性和系统性能通常是密切相关的。应用程序组件必须能够利用所有可用的资源。我们利用产能的效率越高,加工方法越优化,我们在设备上的花费就越少。在一台机器中,Erlang 创建了高度并发的环境。可以通过选择 Erlang VM 可访问的操作系统线程数量以及利用这些线程的调度程序数量来*衡并行性和并发性。
Erlang 进程没有共享状态,并且以非阻塞模式工作。这比传统的阻塞同步应用程序提供了相对较低的延迟和更高的吞吐量。Erlang 调度程序负责公*的 CPU 和 IO 分配。没有阻塞使应用程序即使在峰值负载或故障的情况下也能做出响应。
在集群级别,也存在利用率问题。重要的是在集群中的机器之间均匀地分配负载,并且不要使网络过载。想象一下:用户流量正在登陆负载*衡器(例如 haproxy、nginx 等)。这些*衡器在服务器池中的可用处理程序之间分发请求。在应用基础设施中,实现所需接口的服务只是最后一英里。它必须请求许多其他服务来响应初始查询。内部请求也需要路由和*衡。
为了正确管理数据流,消息传递应该为开发人员提供一个控制路由和负载分布的接口。因此,开发人员将能够使用微服务模式,解决常规任务和非标准任务。
从商业角度来看,可伸缩性是风险管理的工具之一。这里的关键是满足客户的需求并高效地使用硬件:
- 如果你通过进步来提高硬件的性能,硬件就不会因为软件的不完善而闲置。Erlang 可以完美地垂直扩展,并且能够利用所有 CPU 内核和可用内存;
- 在云环境中,我们可以根据当前或预测的负载来管理硬件数量,并确保 SLA。
容错
让我们考虑两个公理:“失败是不可接受的。”和“总会有失败。”对任何企业来说,软件故障都意味着金钱损失,更糟糕的是名誉损失。即使在潜在损失和容错软件的开发成本之间徘徊,通常也有可能达成妥协。
从短期来看,容错架构节省了购买现成集群解决方案的资金。它们可能会让你付出昂贵的代价,并且包含错误。
从长远来看,容错体系结构在开发的所有阶段都可以获得数倍的回报。
代码库内部的消息传递使您能够在开发阶段阐述系统中的组件关系。这有助于管理故障的任务,因为所有负责的组件都处理故障,并且具有自动故障转移的目标系统知道如何在故障后通过设计将其自身恢复到正常状态。
响应性
不管有什么错误,你的应用都应该响应查询并遵守 SLA。现实是现在的人还没有做好等待的准备。因此,企业必须进行调整。预计会有越来越多的应用程序响应速度很快。
响应式应用以接*实时的模式工作。Erlang VM 在软实时模式下运行。然而,对于某些领域,如证券交易、医药或工业设备,硬实时模式至关重要。响应系统提高了 UX 并有助于商业。
初步结论
当我计划这篇文章时,我想分享我创建消息代理的经验,并在此基础上进一步构建复杂的系统。然而,理论和激励部分被证明是太广泛了。
在文章的第二部分,我们将讨论交换点实现和消息交换模式的细微差别。
第三部分将致力于服务安排、路由和*衡的一般问题。此外,我们将讨论可伸缩性和容错的实际方面。
第一部分的结尾。
卢卡·布拉沃拍摄的照片
在 PyTorch 中构建高效的自定义数据集
原文:https://towardsdatascience.com/building-efficient-custom-datasets-in-pytorch-2563b946fd9f?source=collection_archive---------0-----------------------
了解 Dataset 类的来龙去脉,利用干净的代码结构,同时最大限度地减少培训期间管理大量数据的麻烦。
Managing data for neural network training can be hard at “scale”.
PyTorch 最*出现在我的圈子里,尽管我已经习惯了 Keras 和 TensorFlow 一段时间,但我还是不得不尝试一下。令人惊讶的是,我发现它非常令人耳目一新和可爱,尤其是 PyTorch 具有 Pythonic API、更固执己见的编程模式和一组很好的内置实用函数。我特别喜欢的一个功能是能够轻松地创建一个定制的Dataset
对象,然后可以使用内置的DataLoader
在训练模型时提供数据。
在本文中,我将从头开始探索 PyTorch Dataset
对象,目标是创建一个数据集来处理文本文件,以及如何为某项任务优化管道。我们首先通过一个玩具示例来回顾Dataset
实用程序的基础知识,然后逐步完成真正的任务。具体来说,我们希望创建一个管道来输入《上古卷轴(TES)》系列中角色名字的名字、这些角色名字的种族以及名字的性别,作为一个热张量。你可以在我的网站上找到这个数据集。
Dataset
级的基础知识
PyTorch 让您可以自由地对Dataset
类做任何事情,只要您覆盖了两个子类函数:
- 返回数据集大小的
__len__
函数,以及 __getitem__
函数从给定索引的数据集中返回一个样本。
数据集的大小有时可能是一个灰色区域,但它等于整个数据集中的样本数。所以如果你有一万个单词(或者数据点,图片,句子等。)在您的数据集中,__len__
函数应该返回 10,000。
一个最小的工作示例
让我们首先通过创建一个从 1 到 1000 的所有数字的Dataset
来模拟一个简单的数据集。我们将它恰当地命名为NumbersDataset
。
The first iteration of the numbers dataset.
Humble beginnings: printing the contents of the numbers dataset.
很简单,对吧?首先,当我们初始化NumbersDataset
时,我们立即创建一个名为samples
的列表,它将存储 1 到 1000 之间的所有数字。samples
这个名字是随意的,所以你可以随意使用任何你觉得舒服的名字。被覆盖的函数是不言自明的(我希望!)并对构造函数中启动的列表进行操作。如果您运行该文件,您将会看到输出的值 1000、101 和一个介于 122 和 361 之间的列表,它们分别是数据集的长度、数据集中索引 100 处的数据值以及索引 121 和 361 之间的数据集切片。
扩展数据集
让我们扩展这个数据集,以便它可以存储区间low
和high
之间的所有整数。
The second iteration of the numbers dataset with a user-defined range.
The outputs of a slice of the user-defined numbers dataset.
代码上面的代码应该打印 5474,2921 和 2943 到 3181 之间的数字列表。通过编辑构造函数,我们现在可以随心所欲地设置数据集的任意低值和高值。这个简单的改变表明了我们可以从 PyTorch Dataset
级获得什么样的里程。例如,我们可以生成多个不同的数据集并处理这些值,而不必像在 NumPy 中那样考虑编写新的类或创建许多难以理解的矩阵。
从文件中读取数据
让我们进一步扩展Dataset
类的功能。PyTorch 与 Python 标准库的接口非常优雅,这意味着您不必担心集成您已经了解并喜爱的特性。在这里,我们会
- 使用基本的 Python I/O 和一些静态文件创建一个全新的
Dataset
, - 收集 TES 角色的名字(数据集可在我的网站上获得),这些名字被分成种族文件夹和性别文件,以填充
samples
列表, - 通过在
samples
列表中存储一个元组来跟踪每个名字的种族和性别,而不仅仅是名字本身。
作为参考,TES 字符名称数据集具有以下目录结构:
.
|-- Altmer/
| |-- Female
| `-- Male
|-- Argonian/
| |-- Female
| `-- Male
... (truncated for brevity)
`-- Redguard/
|-- Female
`-- Male
每个文件都包含由换行符分隔的 TES 角色名,所以我们必须逐行读取每个文件,以获取每个种族和性别的所有角色名。
The first iteration of the TES names dataset
让我们浏览一下代码:我们首先创建一个空的samples
列表,并通过浏览每个种族文件夹和性别文件并读取每个文件中的名称来填充它。种族、性别和姓名存储在一个元组中,并追加到samples
列表中。运行该文件应该会打印出 19491 和('Bosmer', 'Female', 'Gluineth')
(但可能会因计算机而异)。让我们来看看如果我们将数据集分割成一个批处理会是什么样子:
# change the main function to the following:if __name__ == '__main__':
dataset = TESNamesDataset('/home/syafiq/Data/tes-names/')
print(dataset[10:60])
The output of a slice of the dataset samples containing a name, gender, and race.
正如您所料,它的工作方式与典型的列表完全一样。总结本节,我们刚刚将标准 Python I/O 引入 PyTorch 数据集,我们不需要任何其他特殊的包装器或助手,只需要纯 Python。事实上,我们还可以包括其他库,如 NumPy 或 Pandas,并通过一点巧妙的操作,让它们与 PyTorch 配合良好。让我们暂时就此打住,看看在训练循环的情况下,如何有效地遍历数据集。
用DataLoader
流动数据
虽然Dataset
类是系统包含数据的好方法,但是似乎在一个训练循环中,我们将需要索引或切片数据集的samples
列表。这并不比我们对典型的列表或 NumPy 矩阵所做的更好。PyTorch 没有走这条路,而是提供了另一个名为DataLoader
的实用函数,它充当了一个Dataset
对象的数据馈送器。我在这里看到的并行是 Keras 中的数据生成器flow
函数,如果你熟悉的话。DataLoader
接受一个Dataset
对象(以及任何扩展它的子类)和几个其他可选参数(在 PyTorch DataLoader 文档中列出)。在这些参数中,我们可以选择混洗数据,确定批量大小和并行加载数据的工作人员数量。下面是一个在枚举循环中流经TESNamesDataset
的简单例子。
# change the main function to the following:if __name__ == '__main__':
from torch.utils.data import DataLoader
dataset = TESNamesDataset('/home/syafiq/Data/tes-names/')
dataloader = DataLoader(dataset, batch_size=50, shuffle=True, num_workers=2) for i, batch in enumerate(dataloader):
print(i, batch)
当您看到批量打印出来的洪流时,您可能会注意到每个批量都是一个三元组列表:第一个元组是一群种族,第二个元组是性别,最后一个元组是姓名。
A torrent of names, genders, and races streamed from the dataset… in a strange ordering?
等等,这不是我们之前分割数据集时的样子!这是怎么回事?事实证明,DataLoader
以一种系统的方式加载数据,这样我们就可以垂直地而不是水*地堆叠数据。这对于张量的流动批次特别有用,因为张量垂直堆叠(即在第一维中)以形成批次。此外,DataLoader
还为您处理了数据的混洗,因此在输入数据时,不需要混洗矩阵或跟踪索引。
流动张量和其他类型
为了进一步探索不同类型的数据是如何通过DataLoader
流动的,我们将更新我们之前模拟的数字数据集,以产生两对张量:数据集中每个数字的 4 个后继值的张量,以及相同的后继张量,但添加了一些随机噪声。为了抛出一个曲线球,我们还想返回数字本身,但不是作为一个张量,而是作为一个 Python 字符串。总之,__getitem__
函数将在一个元组中返回三个不同种类的数据项。
The third iteration of the numbers dataset now with multiple data output types.
请注意,我们没有更改数据集构造函数,而是更改了__getitem__
函数。PyTorch 数据集的良好实践是,您要记住数据集将如何随着越来越多的样本而扩展,因此,我们不希望在运行时在内存中的Dataset
对象中存储太多的张量。相反,我们将在遍历样本列表时形成张量,牺牲一点速度来换取内存。我将在接下来的章节中解释这是如何有用的。
Different data types flowing together without breaking a sweat.
看看上面的输出,虽然我们新的__getitem__
函数返回了一个巨大的字符串和张量元组,但是DataLoader
能够识别数据并相应地对它们进行堆栈。字符串化的数字形成一个元组,其大小与加载程序配置的批处理大小相同。对于这两个张量,DataLoader
将它们垂直堆叠成一个大小为10x4
的张量。这是因为我们将批量大小配置为 10,而从__getitem__
函数返回的两个张量的大小为 4。
一般来说,加载程序会尝试将一批一维张量堆叠成二维张量,将一批二维张量堆叠成三维张量,依此类推。在这一点上,我恳求你认识到这对其他机器学习库中的传统数据处理产生的改变生活的影响,以及解决方案看起来有多干净。太不可思议了!如果你不同意我的观点,那么,至少你现在知道另一种方法,你可以在你的工具箱里。
完成 TES 数据集代码
让我们回到 TES 地名数据集。看起来初始化函数有点脏(至少对我的标准来说是这样,应该有办法让代码看起来更好。还记得我说过 PyTorch API 是 Pythonic 式的吗?那么,没有什么可以阻止你在数据集中声明其他的实用函数,或者甚至是为初始化创建内部函数。为了清理 TES 地名数据集代码,我们将更新TESNamesDataset
代码以实现以下功能:
- 更新构造函数以包含字符集,
- 创建内部函数来初始化数据集,
- 创建一个效用函数,将名义变量转换成一个热张量,
- 创建一个实用函数,将一个样本转换为一组三个代表种族、性别和姓名的单热张量。
为了使实用函数工作良好,我们将从scikit-learn
库获得一些帮助来编码名义值(即我们的种族、性别和姓名数据)。具体来说,我们将需要LabelEncoder
类。由于我们正在对代码进行大规模更新,我将在接下来的几个小节中解释这些变化。
The second iteration of the TES names dataset with major additions and updates.
构造函数初始化拆分
这里有相当多的变化,所以让我们一点一点来看。从构造函数开始,您可能已经注意到它没有任何文件处理逻辑。我们已经将这个逻辑移到了_init_dataset
函数中,并清理了构造函数。此外,我们还添加了一些空的编解码器,将名义值从原始字符串转换成整数,然后再转换回来。样品列表也是一个空列表,将在_init_dataset
功能中填充。构造函数还接受了一个名为charset
的新参数。顾名思义,它只是一个字符串,可以让char_codec
将字符转换成整数。
文件处理功能已经增加了几个集合,以便在遍历文件夹时捕获种族和性别等独特的名义值。如果您没有结构良好的数据集,这可能很有用;例如,如果阿贡人有另一组性别不可知论者的名字,我们将有一个名为“未知”的文件,这将被放入性别组,而不管其他种族是否存在“未知”性别。在所有的名字都被存储后,我们将初始化编解码器,使其适合我们的角色集中的种族、性别和角色的唯一值。
效用函数
添加了两个实用函数:to_one_hot
和one_hot_sample
。to_one_hot
在应用一个看似不合适的torch.eye
函数之前,使用数据集的内部编解码器首先将一个值列表转换为一个整数列表。这实际上是一个简单的方法,可以快速地将一个整数列表转换成一个热点向量。torch.eye
函数创建一个任意大小的单位矩阵,其对角线上的值为 1。如果对矩阵行进行索引,那么在该索引处会得到一个值为 1 的行向量,这就是一键向量的定义!
A smaller example of converting from raw strings into race categories as one-hot encoded vectors.
因为我们需要将三个值转换成张量,所以我们将在相应数据的每个编解码器上调用to_one_hot
函数。这在one_hot_sample
函数中进行组合,该函数将一个单样本转换成一个张量元组。种族和性别被转换成一个二维张量,它实际上是一个扩展的行向量。名字也被转换成二维张量,但是包括名字的每个字符的一个热行向量。
__getitem__
通话
最后,__getitem__
函数已经更新,只在给定样本的种族、性别和名称的情况下调用one_hot_sample
函数。注意,我们不需要在samples
列表中预先准备张量,而是仅当调用__getitem__
函数时,即当DataLoader
流数据时,才形成张量。当您在训练期间有成千上万的样本要处理时,这使得数据集非常具有可扩展性。
你可以想象这个数据集是如何用于视觉训练的。数据集将有一个文件名列表和图像目录的路径,让__getitem__
函数只读取图像文件,并及时将它们转换成张量用于训练。通过向DataLoader
提供适当数量的工作器来并行处理多个图像文件,可以使运行速度更快。 PyTorch 数据加载教程更详细地介绍了图像数据集和加载器,并用用于计算机视觉目的的torchvision
包(通常与 PyTorch 一起安装)补充了数据集,制作了图像处理管道(如白化、归一化、随机移位等)。)非常容易构造。
回到这篇文章。数据集检查完毕,看起来我们已经准备好将它用于训练…
…但我们不是
如果我们试图使用批处理大小大于 1 的DataLoader
来传输数据,我们将会遇到一个错误:
A mismatch made in data tensor heaven.
你们中精明的人可能已经看到了这一点,但事实是,文本数据很少以固定长度从一个样本到另一个样本。因此,DataLoader
试图批量处理多个不同长度的名字张量,这在张量格式中是不可能的,因为在 NumPy 数组中也是如此。为了说明这个问题,考虑这样一种情况,当我们将像“John”和“Steven”这样的名字堆叠到一个单个热矩阵中时。“John”翻译成大小为4xC
的二维张量,“Steven”翻译成大小为6xC
的二维张量,其中 C 是字符集的长度。DataLoader
试图将这些名字分批放入一个三维张量2x?xC
(想象一下堆叠大小为1x4xC
和1x6xC
的张量)。由于第二维度不匹配,DataLoader
出现错误,无法继续。
可能的解决方案
为了补救这一点,这里有两种方法,每一种都有其优点和缺点。
- 将批处理大小设置为 1,这样就不会遇到错误。如果批量大小为 1,单个张量不会与任何其他(可能)不同长度的张量堆叠在一起。然而,当执行训练时,这种方法受到影响,因为神经网络在单批梯度下降时收敛非常慢。另一方面,当批处理不重要时,这有利于快速测试时数据加载或沙箱化。
- 通过用空字符填充或截断来固定统一的名称长度。截断长名称或用虚拟字符填充短名称允许所有名称都是格式良好的,并且具有相同的输出张量大小,使得批处理成为可能。缺点是,根据手头的任务,虚拟字符可能是有害的,因为它不代表原始数据。
出于本文的目的,我将选择第二个选项,以表明您只需要对整个数据管道进行很少的更改就可以实现这一点。请注意,这也适用于任何不同长度的顺序数据(尽管有各种方法来填充数据,请参见 NumPy 中的选项和 PyTorch 中的)。在我的用例中,我选择用零填充名称,所以我更新了构造函数和_init_dataset
函数:
... def __init__(self, data_root, charset, length):
self.data_root = data_root
self.charset = charset + '\0'
self.length = length ... with open(gender_filepath, 'r') as gender_file:
for name in gender_file.read().splitlines():
if len(name) < self.length:
name += '\0' * (self.length - len(name))
else:
name = name[:self.length-1] + '\0'
self.samples.append((race, gender, name)) ...
首先,我向构造函数引入一个新参数length
,它将所有传入名称的字符数固定为这个值。我还在字符集中添加了\0
作为填充短名字的虚拟字符。接下来,更新了数据集初始化逻辑。不足固定长度的名称简单地用\0
s 填充,直到满足长度要求。超过固定长度的名字会被截短,最后一个字符用一个\0
替换。交换是可选的,取决于手头的任务。
如果您现在尝试流动这个数据集,您应该得到您最初预期的结果:一个格式良好的张量以期望的批量流动。下图显示了一批大小为 2 的张量,但请注意有三个张量:
Working data flow of all categorical variables converted into one-hot representations and well-formed via padding.
- 堆叠的种族张量,十个种族之一的一键编码版本,
- 堆叠的性别张量,也是针对数据集中存在的两种性别中的每一种进行的单热编码,以及
- 堆叠的名字张量,应该是最后一个维度的
charset
的长度,第二个维度的名字长度(固定大小后),第一个维度的批量大小。
数据分割实用程序
PyTorch 内置了所有这些功能,非常棒。现在可能出现的问题是,如何进行验证甚至测试集,以及如何在不弄乱代码库并尽可能保持代码干爽的情况下执行。测试数据集的一种方法是为训练数据和测试数据提供不同的data_root
,并在运行时保留两个数据集变量(此外,还有两个数据加载器),特别是如果您想在训练后立即进行测试。
相反,如果您想从训练集创建验证集,可以使用 PyTorch 数据实用程序中的random_split
函数轻松处理。random_split
函数接收一个数据集和一个列表中子集的期望大小,并以随机顺序自动分割数据,以生成较小的Dataset
对象,这些对象可立即用于DataLoader
。这里有一个例子。
Create validation sets by splitting your custom PyTorch datasets easily with built-in functions.
事实上,您可以在任意的时间间隔进行分割,这对于折叠的交叉验证集来说非常强大。我对这种方法唯一的不满是,你不能定义百分比分割,这很烦人。至少从一开始就清楚地定义了子数据集的大小。另外,请注意,您需要为每个数据集使用单独的DataLoader
,这肯定比管理两个随机排序的数据集并在一个循环中进行索引要干净。
结束语
我希望这篇文章能让您对 PyTorch 中的Dataset
和DataLoader
实用程序有所了解。结合干净的 Pythonic API,它使得编码更加令人愉快,同时还提供了一种有效的处理数据的方式。我认为 PyTorch 开发人员的易用性已经深深植根于他们的开发哲学中,在我的工作场所使用 PyTorch 之后,我就再也没有回头使用过 Keras 和 TensorFlow。我不得不说,我确实想念 Keras 模型附带的进度条和fit
/ predict
API,但这是一个小挫折,因为最新的 PyTorch 现在与 TensorBoard 接口,带回了一个熟悉的工作环境。然而,目前 PyTorch 是我未来深度学习项目的首选。
我鼓励以这种方式构建自己的数据集,因为它弥补了我以前在管理数据方面的许多混乱的编程习惯。在复杂的情况下,Dataset
实用程序是救命稻草。我记得必须管理属于单个样本但来自三个不同 MATLAB 矩阵文件的数据,并且需要正确地切片、归一化和转置。如果没有Dataset
和DataLoader
的组合,我无法理解管理它的努力,特别是因为数据是巨大的,没有简单的方法将它们组合成一个 NumPy 矩阵而不使任何计算机崩溃。
最后,查看一下 PyTorch 数据实用程序文档页面,其中有其他的类和函数可以探索,这是一个小而有价值的实用程序库。你可以在我的 GitHub 上找到 TES 名字数据集的代码,我已经在 PyTorch 中创建了一个 LSTM 名字预测器和数据集。让我知道这篇文章是否有帮助或不清楚,如果你想在未来更多的这种类型的内容。
使用 TensorFlow 构建高效的数据管道
原文:https://towardsdatascience.com/building-efficient-data-pipelines-using-tensorflow-8f647f03b4ce?source=collection_archive---------2-----------------------
拥有高效的数据管道对于任何机器学习模型都是至关重要的。在这篇博客中,我们将学习如何使用 TensorFlow 的数据集模块tf.data
来构建高效的数据管道。
https://www.tensorflow.org/guide/performance/datasets
动机
大多数关于 TensorFlow 的介绍性文章都会向您介绍将数据输入模型的feed_dict
方法。feed_dict
在单线程中处理输入数据,当数据在 CPU 上加载和处理时,GPU 保持空闲,当 GPU 正在训练一批数据时,CPU 保持空闲状态。TensorFlow 的开发者建议不要在相同数据集的训练或重复验证过程中使用这种方法。
tf_data
通过异步预取下一批数据来提高性能,使 GPU 无需等待数据。您还可以并行处理数据集的预处理和加载过程。
在这篇博文中,我们将介绍Datasets
和Iterators
。我们将学习如何从源数据创建数据集,将转换应用到数据集,然后使用迭代器消费数据。
如何创建数据集?
Tensorflow 提供了各种方法来从 numpy 数组、文本文件、CSV 文件、张量等创建数据集。让我们看看下面的几种方法
- from_tensor_slices: 它接受单个或多个 numpy 数组或张量。使用此方法创建的数据集一次只会发出一个数据。
# source data - numpy array
data = np.arange(10)# create a dataset from numpy array
dataset = tf.data.Dataset.from_tensor_slices(data)
对象dataset
是一个 tensorflow 数据集对象。
- from_tensors: 它也接受单个或多个 numpy 数组或 tensor。使用此方法创建的数据集将一次发出所有数据。
data = tf.arange(10)
dataset = tf.data.Dataset.from_tensors(data)
- from_generator: 创建一个数据集,其元素由函数生成。
def generator():
for i in range(10):
yield 2*i
dataset = tf.data.Dataset.from_generator(generator, (tf.int32))
数据集上的操作
- 批处理:将数据集的连续元素合并成一个批处理。当您想要训练较小批次的数据以避免内存不足错误时,这很有用。
data = np.arange(10,40)# create batches of 10
dataset = tf.data.Dataset.from_tensor_slices(data).batch(10)# creates the iterator to consume the data
iterator = dataset.make_one_shot_iterator()
next_ele = iterator.get_next()with tf.Session() as sess:
try:
while True:
val = sess.run(next_ele)
print(val)
except tf.errors.OutOfRangeError:
pass
您可以跳过创建迭代器并打印数据集元素的代码。我们将在本博客的后面部分详细了解迭代器。输出是:
[10 11 12 13 14 15 16 17 18 19]
[20 21 22 23 24 25 26 27 28 29]
[30 31 32 33 34 35 36 37 38 39]
- Zip: 通过压缩数据集来创建数据集。在具有要素和标注并且需要提供要素和标注对来训练模型的情况下非常有用。
datax = np.arange(10,20)
datay = np.arange(11,21)datasetx = tf.data.Dataset.from_tensor_slices(datax)
datasety = tf.data.Dataset.from_tensor_slices(datay)dcombined = tf.data.Dataset.zip((datasetx, datasety)).batch(2)
iterator = dcombined.make_one_shot_iterator()
next_ele = iterator.get_next()with tf.Session() as sess:
try:
while True:
val = sess.run(next_ele)
print(val)
except tf.errors.OutOfRangeError:
pass
输出是
(array([10, 11]), array([11, 12]))
(array([12, 13]), array([13, 14]))
(array([14, 15]), array([15, 16]))
(array([16, 17]), array([17, 18]))
(array([18, 19]), array([19, 20]))
- 重复:用于重复数据集。
dataset = tf.data.Dataset.from_tensor_slices(tf.range(10))
dataset = dataset.repeat(count=2)
iterator = dataset.make_one_shot_iterator()
next_ele = iterator.get_next()with tf.Session() as sess:
try:
while True:
val = sess.run(next_ele)
print(val)
except tf.errors.OutOfRangeError:
pass
输出是
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
- Map: 用于变换数据集的元素。如果您希望在将原始数据输入到模型中之前对其进行转换,这将非常有用。
def map_fnc(x):
return x*2;data = np.arange(10)
dataset = tf.data.Dataset.from_tensor_slices(data)
dataset = dataset.map(map_fnc)iterator = dataset.make_one_shot_iterator()
next_ele = iterator.get_next()with tf.Session() as sess:
try:
while True:
val = sess.run(next_ele)
print(val)
except tf.errors.OutOfRangeError:
pass
输出是
0 2 4 6 8 10 12 14 16 18
创建迭代器
我们已经学习了创建数据集和应用各种转换的各种方法,但是我们如何消费数据呢?Tensorflow 提供了Iterators
来做到这一点。
迭代器不知道数据集中存在的元素数量。它有一个get_next
函数,用于在 tensorflow 图中创建一个操作,当在一个会话上运行时,它将从迭代器返回值。一旦数据集用尽,就会抛出一个tf.errors.OutOfRangeError
异常。
我们来看看 TensorFlow 提供的各种Iterators
。
- 一次性迭代器:这是迭代器最基本的形式。它不需要显式初始化,只对数据迭代一次,一旦用完,就无法重新初始化。
data = np.arange(10,15)#create the dataset
dataset = tf.data.Dataset.from_tensor_slices(data)#create the iterator
iterator = dataset.make_one_shot_iterator()
next_element = iterator.get_next()
with tf.Session() as sess:
val = sess.run(next_element)
print(val)
- 可初始化迭代器:这个迭代器要求你通过运行
iterator.initialize.
显式初始化迭代器。你可以定义一个tf.placeholder
,并在每次调用初始化操作时动态地传递数据给它。
# define two placeholders to accept min and max value
min_val = tf.placeholder(tf.int32, shape=[])
max_val = tf.placeholder(tf.int32, shape=[])data = tf.range(min_val, max_val)dataset = tf.data.Dataset.from_tensor_slices(data)iterator = dataset.make_initializable_iterator()
next_ele = iterator.get_next()
with tf.Session() as sess:
**# initialize an iterator with range of values from 10 to 15**
sess.run(iterator.initializer, feed_dict={min_val:10, max_val:15})
try:
while True:
val = sess.run(next_ele)
print(val)
except tf.errors.OutOfRangeError:
pass
**# initialize an iterator with range of values from 1 to 10**
sess.run(iterator.initializer, feed_dict={min_val:1, max_val:10})
try:
while True:
val = sess.run(next_ele)
print(val)
except tf.errors.OutOfRangeError:
pass
- 可重新初始化的迭代器:这个迭代器可以从结构相同的不同 Dataset 对象初始化。每个数据集都可以通过自己的转换管道。
def map_fnc(ele):
return ele*2min_val = tf.placeholder(tf.int32, shape=[])
max_val = tf.placeholder(tf.int32, shape=[])
data = tf.range(min_val, max_val)#Define separate datasets for training and validation
train_dataset = tf.data.Dataset.from_tensor_slices(data)
val_dataset = tf.data.Dataset.from_tensor_slices(data).map(map_fnc)#create an iterator
iterator=tf.data.Iterator.from_structure(train_dataset.output_types ,train_dataset.output_shapes)train_initializer = iterator.make_initializer(train_dataset)
val_initializer = iterator.make_initializer(val_dataset)next_ele = iterator.get_next()
with tf.Session() as sess:
# initialize an iterator with range of values from 10 to 15
sess.run(train_initializer, feed_dict={min_val:10, max_val:15})
try:
while True:
val = sess.run(next_ele)
print(val)
except tf.errors.OutOfRangeError:
pass
# initialize an iterator with range of values from 1 to 10
sess.run(val_initializer, feed_dict={min_val:1, max_val:10})
try:
while True:
val = sess.run(next_ele)
print(val)
except tf.errors.OutOfRangeError:
pass
- Feedable 迭代器:可以用来在不同数据集的迭代器之间切换。当您有不同的数据集,并且您想要对数据集使用哪个迭代器有更多的控制时,这很有用。
def map_fnc(ele):
return ele*2min_val = tf.placeholder(tf.int32, shape=[])
max_val = tf.placeholder(tf.int32, shape=[])data = tf.range(min_val, max_val)
train_dataset = tf.data.Dataset.from_tensor_slices(data)
val_dataset = tf.data.Dataset.from_tensor_slices(data).map(map_fnc)train_val_iterator = tf.data.Iterator.from_structure(train_dataset.output_types , train_dataset.output_shapes)
train_initializer = train_val_iterator.make_initializer(train_dataset)
val_initializer = train_val_iterator.make_initializer(val_dataset)test_dataset = tf.data.Dataset.from_tensor_slices(tf.range(10,15))
test_iterator = test_dataset.make_one_shot_iterator()handle = tf.placeholder(tf.string, shape=[])
iterator = tf.data.Iterator.from_string_handle(handle, train_dataset.output_types, train_dataset.output_shapes)
next_ele = iterator.get_next()with tf.Session() as sess:
train_val_handle = sess.run(train_val_iterator.string_handle())
test_handle = sess.run(test_iterator.string_handle())
# training
sess.run(train_initializer, feed_dict={min_val:10, max_val:15})
try:
while True:
val = sess.run(next_ele, feed_dict={handle:train_val_handle})
print(val)
except tf.errors.OutOfRangeError:
pass
#validation
sess.run(val_initializer, feed_dict={min_val:1, max_val:10})
try:
while True:
val = sess.run(next_ele, feed_dict={handle:train_val_handle})
print(val)
except tf.errors.OutOfRangeError:
pass
#testing
try:
while True:
val = sess.run(next_ele, feed_dict={handle:test_handle})
print(val)
except tf.errors.OutOfRangeError:
pass
我们已经学习了各种迭代器。让我们将这些知识应用于一个实际的数据集。我们将使用 LeNet-5 模型训练著名的 MNIST 数据集。本教程不会深入讨论实现 LeNet-5 模型的细节,因为这超出了本文的范围。
LeNet-5 模型
让我们从 tensorflow 库中导入 MNIST 数据。MNIST 数据库包含 60,000 幅训练图像和 10,000 幅测试图像。每个图像的大小为 28281。对于 LeNet-5 型号,我们需要将其大小调整为 32321。
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/", reshape=False, one_hot = True)X_train, y_train = mnist.train.images, mnist.train.labels
X_val, y_val = mnist.validation.images, mnist.validation.labels
X_test, y_test = mnist.test.images, mnist.test.labelsX_train = np.pad(X_train, ((0,0), (2,2), (2,2), (0,0)), 'constant')
X_val = np.pad(X_val, ((0,0), (2,2), (2,2), (0,0)), 'constant')
X_test = np.pad(X_test, ((0,0), (2,2), (2,2), (0,0)), 'constant')
Ref: https://www.researchgate.net/figure/Structure-of-LeNet-5_fig1_312170477
让我们定义模型的正向传播。
def forward_pass(X):
W1 = tf.get_variable("W1", [5,5,1,6], initializer = tf.contrib.layers.xavier_initializer(seed=0))
# for conv layer2 W2 = tf.get_variable("W2", [5,5,6,16], initializer = tf.contrib.layers.xavier_initializer(seed=0)) Z1 = tf.nn.conv2d(X, W1, strides = [1,1,1,1], padding='VALID')
A1 = tf.nn.relu(Z1)
P1 = tf.nn.max_pool(A1, ksize = [1,2,2,1], strides = [1,2,2,1], padding='VALID') Z2 = tf.nn.conv2d(P1, W2, strides = [1,1,1,1], padding='VALID')
A2= tf.nn.relu(Z2)
P2= tf.nn.max_pool(A2, ksize = [1,2,2,1], strides=[1,2,2,1], padding='VALID') P2 = tf.contrib.layers.flatten(P2)
Z3 = tf.contrib.layers.fully_connected(P2, 120)
Z4 = tf.contrib.layers.fully_connected(Z3, 84)
Z5 = tf.contrib.layers.fully_connected(Z4,10, activation_fn= None) return Z5
让我们定义模型操作
def model(X,Y):
logits = forward_pass(X)
cost = tf.reduce_mean( tf.nn.softmax_cross_entropy_with_logits_v2(logits=logits, labels=Y)) optimizer = tf.train.AdamOptimizer(learning_rate=0.0009)
learner = optimizer.minimize(cost) correct_predictions = tf.equal(tf.argmax(logits,1), tf.argmax(Y,1)) accuracy = tf.reduce_mean(tf.cast(correct_predictions, tf.float32))
return (learner, accuracy)
我们现在已经创建了模型。在决定为我们的模型使用迭代器之前,让我们看看机器学习模型的典型要求是什么。
- 批量训练数据:数据集可能非常庞大。为了防止出现内存不足的错误,我们需要小批量地训练数据集。
- 在数据集的 n 次传递中训练模型:通常,您希望在数据集的多次传递中运行训练模型。
- 在每个时期验证模型:您需要在每个时期验证您的模型,以检查您的模型的性能。
- 最后,在看不见的数据上测试你的模型:在模型被训练之后,你想要在看不见的数据上测试你的模型。
让我们看看每个迭代器的优缺点。
- 一次性迭代器:数据集一旦用完就无法重新初始化。为了训练更多的历元,您需要在输入迭代器之前重复数据集。如果数据量很大,这将需要巨大的内存。它也没有提供任何验证模型的选项。
epochs = 10
batch_size = 64
iterations = len(y_train) * epochstf.reset_default_graph()
dataset = tf.data.Dataset.from_tensor_slices((X_train, y_train))# need to repeat the dataset for epoch number of times, as all the data needs
# to be fed to the dataset at once
dataset = dataset.repeat(epochs).batch(batch_size)
iterator = dataset.make_one_shot_iterator()X_batch , Y_batch = iterator.get_next()(learner, accuracy) = model(X_batch, Y_batch)with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
total_accuracy = 0
try:
while True:
temp_accuracy, _ = sess.run([accuracy, learner])
total_accuracy += temp_accuracy
except tf.errors.OutOfRangeError:
pass
print('Avg training accuracy is {}'.format((total_accuracy * batch_size) / iterations ))
- 可初始化的迭代器:可以在训练数据集和验证数据集之间动态改变数据集。然而,在这种情况下,两个数据集需要通过相同的转换管道。
epochs = 10
batch_size = 64tf.reset_default_graph()X_data = tf.placeholder(tf.float32, [None, 32,32,1])
Y_data = tf.placeholder(tf.float32, [None, 10])dataset = tf.data.Dataset.from_tensor_slices((X_data, Y_data))
dataset = dataset.batch(batch_size)
iterator = dataset.make_initializable_iterator()X_batch , Y_batch = iterator.get_next()(learner, accuracy) = model(X_batch, Y_batch)with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for epoch in range(epochs):
# train the model
sess.run(iterator.initializer, feed_dict={X_data:X_train, Y_data:y_train})
total_train_accuracy = 0
no_train_examples = len(y_train)
try:
while True:
temp_train_accuracy, _ = sess.run([accuracy, learner])
total_train_accuracy += temp_train_accuracy*batch_size
except tf.errors.OutOfRangeError:
pass
# validate the model
sess.run(iterator.initializer, feed_dict={X_data:X_val, Y_data:y_val})
total_val_accuracy = 0
no_val_examples = len(y_val)
try:
while True:
temp_val_accuracy = sess.run(accuracy)
total_val_accuracy += temp_val_accuracy*batch_size
except tf.errors.OutOfRangeError:
pass
print('Epoch {}'.format(str(epoch+1)))
print("---------------------------")
print('Training accuracy is {}'.format(total_train_accuracy/no_train_examples))
print('Validation accuracy is {}'.format(total_val_accuracy/no_val_examples))
- 可重新初始化的迭代器:这个迭代器通过使用两个独立的数据集克服了可初始化迭代器的问题。每个数据集都可以通过自己的预处理管道。迭代器可以使用
tf.Iterator.from_structure
方法创建。
def map_fnc(X, Y):
return X, Yepochs = 10
batch_size = 64tf.reset_default_graph()X_data = tf.placeholder(tf.float32, [None, 32,32,1])
Y_data = tf.placeholder(tf.float32, [None, 10])train_dataset = tf.data.Dataset.from_tensor_slices((X_data, Y_data)).batch(batch_size).map(map_fnc)val_dataset = tf.data.Dataset.from_tensor_slices((X_data, Y_data)).batch(batch_size)iterator = tf.data.Iterator.from_structure(train_dataset.output_types, train_dataset.output_shapes)X_batch , Y_batch = iterator.get_next()
(learner, accuracy) = model(X_batch, Y_batch)train_initializer = iterator.make_initializer(train_dataset)
val_initializer = iterator.make_initializer(val_dataset)with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for epoch in range(epochs):
# train the model
sess.run(train_initializer, feed_dict={X_data:X_train, Y_data:y_train})
total_train_accuracy = 0
no_train_examples = len(y_train)
try:
while True:
temp_train_accuracy, _ = sess.run([accuracy, learner])
total_train_accuracy += temp_train_accuracy*batch_size
except tf.errors.OutOfRangeError:
pass
# validate the model
sess.run(val_initializer, feed_dict={X_data:X_val, Y_data:y_val})
total_val_accuracy = 0
no_val_examples = len(y_val)
try:
while True:
temp_val_accuracy = sess.run(accuracy)
total_val_accuracy += temp_val_accuracy*batch_size
except tf.errors.OutOfRangeError:
pass
print('Epoch {}'.format(str(epoch+1)))
print("---------------------------")
print('Training accuracy is {}'.format(total_train_accuracy/no_train_examples))
print('Validation accuracy is {}'.format(total_val_accuracy/no_val_examples))
- Feedable 迭代器:这个迭代器提供了在各种迭代器之间切换的选项。您可以创建一个可重新初始化的迭代器,用于训练和验证。对于需要一遍数据集的推断/测试,可以使用一次性迭代器。
epochs = 10
batch_size = 64tf.reset_default_graph()X_data = tf.placeholder(tf.float32, [None, 32,32,1])
Y_data = tf.placeholder(tf.float32, [None, 10])train_dataset = tf.data.Dataset.from_tensor_slices((X_data, Y_data)).batch(batch_size)
val_dataset = tf.data.Dataset.from_tensor_slices((X_data, Y_data)).batch(batch_size)test_dataset = tf.data.Dataset.from_tensor_slices((X_test, y_test.astype(np.float32)).batch(batch_size)handle = tf.placeholder(tf.string, shape=[])
iterator = tf.data.Iterator.from_string_handle(handle, train_dataset.output_types, train_dataset.output_shapes)
X_batch , Y_batch = iterator.get_next()
(learner, accuracy) = model(X_batch, Y_batch)train_val_iterator = tf.data.Iterator.from_structure(train_dataset.output_types, train_dataset.output_shapes)
train_iterator = train_val_iterator.make_initializer(train_dataset)
val_iterator = train_val_iterator.make_initializer(val_dataset)
test_iterator = test_dataset.make_one_shot_iterator()with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
train_val_string_handle = sess.run(train_val_iterator.string_handle())
test_string_handle = sess.run(test_iterator.string_handle())
for epoch in range(epochs):
# train the model
sess.run(train_iterator, feed_dict={X_data:X_train, Y_data:y_train})
total_train_accuracy = 0
no_train_examples = len(y_train)
try:
while True:
temp_train_accuracy, _ = sess.run([accuracy, learner], feed_dict={handle:train_val_string_handle})
total_train_accuracy += temp_train_accuracy*batch_size
except tf.errors.OutOfRangeError:
pass
# validate the model
sess.run(val_iterator, feed_dict={X_data:X_val, Y_data:y_val})
total_val_accuracy = 0
no_val_examples = len(y_val)
try:
while True:
temp_val_accuracy, _ = sess.run([accuracy, learner], feed_dict={handle:train_val_string_handle})
total_val_accuracy += temp_val_accuracy*batch_size
except tf.errors.OutOfRangeError:
pass
print('Epoch {}'.format(str(epoch+1)))
print("---------------------------")
print('Training accuracy is {}'.format(total_train_accuracy/no_train_examples))
print('Validation accuracy is {}'.format(total_val_accuracy/no_val_examples))
print("Testing the model --------")
total_test_accuracy = 0
no_test_examples = len(y_test)
try:
while True:
temp_test_accuracy, _ = sess.run([accuracy, learner], feed_dict={handle:test_string_handle})
total_test_accuracy += temp_test_accuracy*batch_size
except tf.errors.OutOfRangeError:
pass
print('Testing accuracy is {}'.format(total_test_accuracy/no_test_examples))
感谢阅读博客。本博客中使用的代码示例可以在这个 jupyter 笔记本中找到。
如果你有任何问题或者你有任何改进这个博客的建议,请在下面留下你的评论。
参考
- https://www . tensor flow . org/API _ docs/python/TF/data/Iterator # from _ string _ handle
- https://www.tensorflow.org/guide/datasets
- https://docs . Google . com/presentation/d/16 khntqslt-yuj 3 w8 gix-eEH6t _ avfeqochqgrfpad 7 u/edit # slide = id . g 254d 08 e 080 _ 0 _ 141
- https://github.com/tensorflow/tensorflow/issues/2919
为视频和图像构建快速面部识别
原文:https://towardsdatascience.com/building-fast-facial-recognition-for-videos-and-images-7b9f3e7c240c?source=collection_archive---------6-----------------------
noobs 😄 面部识别入门
在我开始这个故事之前,我要对 PyImageSearch 的 Adrian 大声喊一声。如果您是深度学习的初学者,这是市场上最好的课程。(我会把他的页面链接在底部。)
如果你和我一样是科幻迷,你应该看过《感兴趣的人》。你已经看到人工智能在视频中寻找人脸。它从图像库中找到人脸。这是电视版。如果我告诉你你也可以在现实生活中建造。我暂时忘记了那件事。
关于这个项目,我从几天前认识的室友那里得到了灵感。他一直向朋友们问我角色名字。不如我们在视频中建立面部识别系统。艾利安的代码让这一切成为可能。
想法很简单,CNN 提供足够多的图片。我从朋友那里为 5 个角色输入了 15 张图片。可以从面部识别中获取面部识别编码,存储在 pickle 文件中。您可以再次读取此编码,并与图像和视频文件中的人脸进行匹配。如果匹配,它将抛出我们存储在程序中的 known_name。如果没有找到,它将抛出未知。
我会为谷歌图片添加 github 回购和 scrapper 代码。Recog.py 文件包含 pickle 文件中的编码示例。将使用这个 pickle 文件。Recog_faces 将使用 pickle 文件,该文件在下面提到的截图中使用。如果文件不在数据集中,它将抛出未知的矩形。对每个字符使用最大数量的样本,这样我们可以有大量的编码。这将有助于面部识别。我们同样可以在视频中进行人脸识别。
提到的例子的小代码指南。
https://gist.github.com/saurabh896/b705536ba4354c8aa382978d5ddfc8e4
这个代码的主要部分是面部识别。我们使用相同部分的代码来转储 pickle 文件中的编码。就像我说的,更多的样本会提供更多的准确性。我用每个字符 15 个样本来运行这个代码,所以我达到了大约 83%的准确率。你仍然可以看到模型不能识别瑞秋的脸。上面的代码可以识别图像中的人脸,并将编码保存在数组中。如果你想查看编码,只需打印编码和已知人脸。你会得到看起来像坐标的人脸数据点。如果你想试试,你可以做到。记住数据科学领域是由好奇心推动的。
https://gist.github.com/saurabh896/ffdc37836684420491cab60a01982658
上面的代码改变你的阅读你的图像。打开你的 pickle 文件,循环你的编码。使用图像中提供的面孔查找匹配的编码。如果匹配,它将从编码数组中抛出名字。如果找不到脸,那么它将给出未知。
https://gist.github.com/saurabh896/4ee6e4bfe24467df535f7762b8b112e2
视频的最后代码。视频只不过是根据时间排列的图像。因此,我们一帧一帧地分割图像,并像处理图像一样对它们进行匹配。我们使用两个部分首先是输入作为输入视频,其中包含这个字符和输出文件夹,以获得矩形有界输出的模型。
如果你想了解更多关于 imutils .使用以下链接
[## imutils.video Python 示例
本页提供 imutils.video 的 Python 代码示例。
www.programcreek.com](https://www.programcreek.com/python/example/93641/imutils.video)
这段代码需要时间,因为它正在写入新文件。我更喜欢使用笔记本电脑,因为它有很好的配置。如果你没有好的系统,使用自动气象站或 GCP 进行实验。
Facial recognition on characters
我在视频中实现了相同的 pickle 文件。这给了我以下结果。我不得不调整一些代码来处理慢动作,但最终想法奏效了!!瑞秋出了点小问题。希望詹妮弗·安妮斯顿不会介意!!😛
Video Example
你可以在 github repo 中找到工作代码。我提到了向下看,如果你有兴趣的话。很高兴从你这里得到更多的想法。
给我打 saurabhkdm721@gmail.com 的电话
[## saurabh 896/视频识别
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/saurabh896/VideoRecognition.git) [## PyImageSearch——擅长 OpenCV、Python、深度学习和计算机视觉
这篇 OpenCV、深度学习和 Python 博客是由 Adrian Rosebrock 撰写的。精通 OpenCV,深度学习,Python,还有…
www.pyimagesearch.com](https://www.pyimagesearch.com/)
使用 Amazon Rekognition 构建韩国流行偶像标识符
原文:https://towardsdatascience.com/building-k-pop-idol-identifier-with-amazon-rekognition-92302442d763?source=collection_archive---------6-----------------------
人脸识别简明指南
Photo by Bach Tran on Unsplash
从头开始构建数据科学模型是一项相当大的工作。有许多元素组成一个单一的模型,涉及许多步骤,并且需要许多迭代来创建一个像样的模型。尽管完成这些步骤肯定会帮助您更深入地理解模型中使用的算法,但有时您没有足够的时间来完成所有的试验和错误,特别是当您有一个紧迫的截止日期要满足时。
图像识别是机器学习中的一个领域,已经被许多科技巨头如谷歌、亚马逊、微软深入探索。在图像处理的所有功能中,可能讨论最多的是面部识别。关于这项技术的伦理方面有很多争论,但这超出了本文的范围。我将简单地分享我在 Amazon Rekognition 上的尝试,希望你能从这篇文章中有所收获。
写这篇文章的冲动始于我在他们的网络界面上玩了一下亚马逊的 Rekognition 演示。它提供许多有用的服务,如“对象和场景检测”、“面部识别”、“面部分析”和“名人识别”。我试了几张图,一切都很顺利,直到我到了“名人识别”。在我尝试使用韩国明星的照片之前,名人识别起初似乎还不错。韩国明星的认知度表现明显下降。有时它给我正确的答案,有时它不能识别,有时它给我错误的名字。
顺便说一下,上面的照片是周子瑜来自一个名为 Twice 的组合,这是我最喜欢的 K-pop 女子组合,我不能接受亚马逊承认这张照片是 Seolhyun(她是另一个名为 AOA 的组合的成员)。
所以我决定使用 Amazon Rekognition 编写一个简单的 Python 脚本,它可以准确地检测两次。
- 除了你可以在文章中找到的简短代码块,我会在文章末尾附上整个 Jupyter 笔记本的链接。
- 这篇文章基于教程“使用 Amazon Rekognition 构建自己的人脸识别服务”,但对原始代码进行了修改,以适应该项目的特定目的。
使用 Amazon Rekognition 进行人脸检测
要运行 Jupyter 笔记本中的以下步骤,有几个先决条件。
- 亚马逊 AWS 帐户
- 使用 AWS CLI 配置的 AWS 凭据
- Boto3 的最新版本
让我们首先从导入一些将直接用于下一步的包开始。
import boto3
from PIL import Image%matplotlib inline
现在我们需要一个我们想要处理的图像。我选择了与上面的 web 界面演示相同的图像,我们将把这个图像发送给 Rekognition API 以获得其图像识别的结果。(图片也可以在我将在本文末尾分享的 Github 链接中找到。)我们来快速看一下图像。
display(Image.open('Tzuyu.jpeg'))
我们可以要求 Rekognition 执行的最基本的任务是用给定的图像进行面部识别,这只需要几行代码就可以完成。
import iorekognition = boto3.client('rekognition')image = Image.open("Tzuyu.jpeg")
stream = io.BytesIO()
image.save(stream,format="JPEG")
image_binary = stream.getvalue()rekognition.detect_faces(
Image={'Bytes':image_binary},
Attributes=['ALL']
)
您可以将图像作为内存中的二进制文件对象直接从您的本地机器发送到 rekognition,或者将您的图像上传到 S3,并在调用 rekognition.detect_faces()时将您的桶和密钥详细信息作为参数给出。在上面的例子中,我直接从本地机器发送二进制对象。您将从上面的调用中得到的响应将会很长,包含您可以从 Rekognition 的 detect_faces 函数中得到的所有信息。
{'FaceDetails': [{'AgeRange': {'High': 38, 'Low': 20},
'Beard': {'Confidence': 99.98848724365234, 'Value': False},
'BoundingBox': {'Height': 0.1584049016237259,
'Left': 0.4546355605125427,
'Top': 0.0878104418516159,
'Width': 0.09999311715364456},
'Confidence': 100.0,
'Emotions': [{'Confidence': 37.66959762573242, 'Type': 'SURPRISED'},
{'Confidence': 29.646778106689453, 'Type': 'CALM'},
{'Confidence': 3.8459930419921875, 'Type': 'SAD'},
{'Confidence': 3.134934186935425, 'Type': 'DISGUSTED'},
{'Confidence': 2.061260938644409, 'Type': 'HAPPY'},
{'Confidence': 18.516468048095703, 'Type': 'CONFUSED'},
{'Confidence': 5.1249613761901855, 'Type': 'ANGRY'}],
'Eyeglasses': {'Confidence': 99.98339080810547, 'Value': False},
'EyesOpen': {'Confidence': 99.9864730834961, 'Value': True},
'Gender': {'Confidence': 99.84709167480469, 'Value': 'Female'},
'Landmarks': [{'Type': 'eyeLeft',
'X': 0.47338899970054626,
'Y': 0.15436244010925293},
{'Type': 'eyeRight', 'X': 0.5152773261070251, 'Y': 0.1474122554063797},
{'Type': 'mouthLeft', 'X': 0.48312342166900635, 'Y': 0.211111381649971},
{'Type': 'mouthRight', 'X': 0.5174261927604675, 'Y': 0.20560002326965332},
{'Type': 'nose', 'X': 0.4872787892818451, 'Y': 0.1808750480413437},
{'Type': 'leftEyeBrowLeft',
'X': 0.45876359939575195,
'Y': 0.14424000680446625},
{'Type': 'leftEyeBrowRight',
'X': 0.4760720133781433,
'Y': 0.13612663745880127},
{'Type': 'leftEyeBrowUp',
'X': 0.4654795229434967,
'Y': 0.13559915125370026},
{'Type': 'rightEyeBrowLeft',
'X': 0.5008187890052795,
'Y': 0.1317606270313263},
{'Type': 'rightEyeBrowRight',
'X': 0.5342025756835938,
'Y': 0.1317359358072281},
{'Type': 'rightEyeBrowUp',
'X': 0.5151524543762207,
'Y': 0.12679456174373627},
{'Type': 'leftEyeLeft', 'X': 0.4674917757511139, 'Y': 0.15510375797748566},
{'Type': 'leftEyeRight',
'X': 0.4817998707294464,
'Y': 0.15343616902828217},
{'Type': 'leftEyeUp', 'X': 0.47253310680389404, 'Y': 0.1514900177717209},
{'Type': 'leftEyeDown',
'X': 0.47370508313179016,
'Y': 0.15651680529117584},
{'Type': 'rightEyeLeft',
'X': 0.5069678425788879,
'Y': 0.14930757880210876},
{'Type': 'rightEyeRight',
'X': 0.5239912867546082,
'Y': 0.1460886150598526},
{'Type': 'rightEyeUp', 'X': 0.5144344568252563, 'Y': 0.1447771191596985},
{'Type': 'rightEyeDown',
'X': 0.5150220394134521,
'Y': 0.14997448027133942},
{'Type': 'noseLeft', 'X': 0.4858757555484772, 'Y': 0.18927086889743805},
{'Type': 'noseRight', 'X': 0.5023624897003174, 'Y': 0.1855706423521042},
{'Type': 'mouthUp', 'X': 0.4945952594280243, 'Y': 0.2002507448196411},
{'Type': 'mouthDown', 'X': 0.4980264902114868, 'Y': 0.21687346696853638},
{'Type': 'leftPupil', 'X': 0.47338899970054626, 'Y': 0.15436244010925293},
{'Type': 'rightPupil', 'X': 0.5152773261070251, 'Y': 0.1474122554063797},
{'Type': 'upperJawlineLeft',
'X': 0.46607205271720886,
'Y': 0.15965013206005096},
{'Type': 'midJawlineLeft',
'X': 0.47901660203933716,
'Y': 0.21797965466976166},
{'Type': 'chinBottom', 'X': 0.5062429904937744, 'Y': 0.24532964825630188},
{'Type': 'midJawlineRight',
'X': 0.5554487109184265,
'Y': 0.20579127967357635},
{'Type': 'upperJawlineRight',
'X': 0.561174750328064,
'Y': 0.14439250528812408}],
'MouthOpen': {'Confidence': 99.0997543334961, 'Value': True},
'Mustache': {'Confidence': 99.99714660644531, 'Value': False},
'Pose': {'Pitch': 1.8594770431518555,
'Roll': -11.335309982299805,
'Yaw': -33.68760681152344},
'Quality': {'Brightness': 89.57070922851562,
'Sharpness': 86.86019134521484},
'Smile': {'Confidence': 99.23001861572266, 'Value': False},
'Sunglasses': {'Confidence': 99.99723815917969, 'Value': False}}],
'ResponseMetadata': {'HTTPHeaders': {'connection': 'keep-alive',
'content-length': '3297',
'content-type': 'application/x-amz-json-1.1',
'date': 'Sun, 19 May 2019 08:45:56 GMT',
'x-amzn-requestid': '824f5dc3-7a12-11e9-a384-dfb84e388b7e'},
'HTTPStatusCode': 200,
'RequestId': '824f5dc3-7a12-11e9-a384-dfb84e388b7e',
'RetryAttempts': 0}}
从上面 detect_faces 调用的示例响应中可以看出,它不仅具有图片中人脸位置的包围盒信息,还具有更高级的特征,如情绪、性别、年龄范围等。
比较面孔
有了 Amazon Rekognition,你可以对比两张图片中的人脸。例如,如果我将一张周子瑜的图片设置为我的源图片,然后发送一张两倍于我的目标图片的集体照,Rekognition 会在目标图片中找到与源图片最相似的人脸。下面是我将使用的两次集体照。
即使对人类来说也可能很难,尤其是如果你不是亚洲人(或者不是 Twice 粉丝)。你可以猜猜照片中的周子瑜是谁。作为一个韩国人,同时也是两次粉丝,我知道答案,但让我们看看 Rekognition 能从这张照片中找到周子瑜有多好。
sourceFile='Tzuyu.jpeg'
targetFile='twice_group.jpg'
imageSource=open(sourceFile,'rb')
imageTarget=open(targetFile,'rb')response = rekognition.compare_faces(SimilarityThreshold=80,
SourceImage={'Bytes': imageSource.read()},
TargetImage={'Bytes': imageTarget.read()})
response['FaceMatches']
上面 compare_faces 的响应还会输出组图中所有不匹配人脸的信息,这可能会变得相当长,所以我只是输出 Rekognition 通过指定 response['FaceMatches']找到的匹配。看起来像是从一组照片中找到了一张相似度在 97%左右的匹配脸。有了边界框信息,让我们检查 Rekognition 指的是周子瑜的哪张脸。
顺便说一下,BoundingBox 部分中的值是整个图像大小的比率。因此,为了用 BoundingBox 中的值绘制方框,需要通过乘以实际图像高度或宽度的比率来计算方框中每个点的位置。您可以在下面的代码片段中找到如何做到这一点。
from PIL import ImageDrawimage = Image.open("twice_group.jpg")
imgWidth,imgHeight = image.size
draw = ImageDraw.Draw(image)
box = response['FaceMatches'][0]['Face']['BoundingBox']
left = imgWidth * box['Left']
top = imgHeight * box['Top']
width = imgWidth * box['Width']
height = imgHeight * box['Height']
points = (
(left,top),
(left + width, top),
(left + width, top + height),
(left , top + height),
(left, top))
draw.line(points, fill='#00d400', width=2)display(image)
是啊!干得好,雷科尼提翁!那确实是周子瑜!
正在创建收藏
现在我们可以从一张图片中检测人脸,从目标图片中找到与源图片最相似的人脸。但是,这些都是一次性调用,我们需要更多的东西来存储每个成员的脸和他们的名字的信息,以便当我们发送两次新的图片时,它可以检索数据并检测每个成员的脸并显示他们的名字。为了实现这一点,我们需要使用亚马逊所谓的“基于存储的 API 操作”。这种类型的操作有两个亚马逊特有的术语。“集合”是一个虚拟空间,Rekognition 在其中存储有关检测到的人脸的信息。使用集合,我们可以“索引”人脸,这意味着检测图像中的人脸,然后将信息存储在指定的集合中。重要的是,Rekognition 存储在集合中的信息不是实际的图像,而是由 Rekognition 的算法提取的特征向量。让我们看看如何创建一个集合并添加索引。
collectionId='test-collection'
rekognition.create_collection(CollectionId=collectionId)
是的。就这么简单。由于这是我们刚刚创建的新集合,因此集合中没有存储任何信息。但是,让我们仔细检查一下。
rekognition.describe_collection(CollectionId=collectionId)
在上面的响应中,您可以看到“FaceCount”为 0。如果我们索引任何人脸并将该信息存储在集合中,这种情况将会改变。
索引面
使用 Rekognition 为人脸建立索引同样简单,只需一行代码。
sourceFile='Tzuyu.jpeg'
imageSource=open(sourceFile,'rb')rekognition.index_faces(Image={'Bytes':imageSource.read()},ExternalImageId='Tzuyu',CollectionId=collectionId)
从上面的代码,你可以看到我正在传递 ExternalImageId 参数,并给它的值字符串“周子瑜”。稍后,当我们试图从一张新照片中识别周子瑜时,Rekognition 将搜索与任何索引人脸相匹配的人脸。正如您将在后面看到的,当索引一个面时,Rekognition 会给它一个唯一的面 ID。但是,当在新图片中找到匹配的人脸时,我想显示“周子瑜”这个名字。为此,我使用 ExternalImageId。现在,如果我们检查我们的集合,我们可以看到 1 张脸被添加到集合中。
rekognition.describe_collection(CollectionId=collectionId)
通过图像搜索面孔
现在,随着周子瑜的脸在我们的集合中被编入索引,我们可以向 Rekognition 发送一张新的看不见的照片,并找到匹配的脸。但是 search_faces_by_image 函数的一个问题是只能检测一张脸(图像中最大的)。因此,如果我们想发送两次的团体照片,并从那里找到周子瑜,我们将需要做一个额外的步骤。下面我们先用 detect_faces 检测图片中的所有人脸,然后有了每个人脸的包围盒信息,我们再逐个调用 search_faces_by_image。首先让我们检测每张脸。
imageSource=open('twice_group.jpg','rb')
resp = rekognition.detect_faces(Image={'Bytes':imageSource.read()})
all_faces = resp['FaceDetails']
len(all_faces)
Rekognition 从群组图片中检测到 9 张人脸。很好。现在让我们裁剪每个面,并逐个调用 serach_faces_by_image。
image = Image.open("twice_group.jpg")
image_width,image_height = image.sizefor face in all_faces:
box=face['BoundingBox']
x1 = box['Left'] * image_width
y1 = box['Top'] * image_height
x2 = x1 + box['Width'] * image_width
y2 = y1 + box['Height'] * image_height
image_crop = image.crop((x1,y1,x2,y2))
stream = io.BytesIO()
image_crop.save(stream,format="JPEG")
image_crop_binary = stream.getvalue()response = rekognition.search_faces_by_image(
CollectionId=collectionId,
Image={'Bytes':image_crop_binary}
)
print(response)
print('-'*100)
在我们进行的 9 次 search_faces_by_image 调用中,Rekognition 找到了一个与我们的集合中的索引人脸相匹配的人脸。我们只索引了周子瑜的一张脸,所以它从组图中找到的是周子瑜的脸。让我们用边界框和名称在图像上显示它。对于名称部分,我们将使用我们在索引面部时设置的 ExternalImageId。顺便说一下,从 search_faces_by_image 响应来看,‘face matches’部分是一个数组,如果从集合中找到多个匹配,那么它会显示所有匹配。根据 Amazon 的说法,这个数组是按照相似性得分排序的,相似性最高的排在最前面。我们将通过指定数组的第一项来获得最高分的匹配。
from PIL import ImageFont
import ioimage = Image.open("twice_group.jpg")
image_width,image_height = image.size
for face in all_faces:
box=face['BoundingBox']
x1 = box['Left'] * image_width
y1 = box['Top'] * image_height
x2 = x1 + box['Width'] * image_width
y2 = y1 + box['Height'] * image_height
image_crop = image.crop((x1,y1,x2,y2))
stream = io.BytesIO()
image_crop.save(stream,format="JPEG")
image_crop_binary = stream.getvalue()response = rekognition.search_faces_by_image(
CollectionId=collectionId,
Image={'Bytes':image_crop_binary}
)
if len(response['FaceMatches']) > 0:
draw = ImageDraw.Draw(image)
points = (
(x1,y1),
(x2, y1),
(x2, y2),
(x1 , y2),
(x1, y1))
draw.line(points, fill='#00d400', width=2)
fnt = ImageFont.truetype('/Library/Fonts/Arial.ttf', 15)
draw.text((x1,y2),response['FaceMatches'][0]['Face']['ExternalImageId'], font=fnt, fill=(255, 255, 0))
display(image)
万岁!又是正确答案!
两次识别所有组成员
现在,让我们扩展项目,从组图片中识别所有成员。为了做到这一点,我们首先需要索引所有成员的脸(有 9 个成员)。我为每个成员准备了 4 张照片。我按照 Christian Petters 写的亚马逊教程的逻辑添加了同一个人的多张图片。根据 Petters 的说法,“为每个人添加多个参考图像大大提高了一个人的潜在匹配率”,这具有直观的意义。从我将在最后分享的 Github 链接中,你会找到这个项目中使用的所有图片。
collectionId='twice'
rekognition.create_collection(CollectionId=collectionId)
import ospath = 'Twice'for r, d, f in os.walk(path):
for file in f:
if file != '.DS_Store':
sourceFile = os.path.join(r,file)
imageSource=open(sourceFile,'rb')
rekognition.index_faces(Image={'Bytes':imageSource.read()},ExternalImageId=file.split('_')[0],CollectionId=collectionId)
rekognition.describe_collection(CollectionId=collectionId)
好的。似乎所有 36 张照片都被编入了我们的“两次”收藏。现在是检查最终结果的时候了。可以增强 Rekognition 来识别两次的每个成员吗?
from PIL import ImageFontimage = Image.open("twice_group.jpg")
image_width,image_height = image.size
for face in all_faces:
box=face['BoundingBox']
x1 = box['Left'] * image_width
y1 = box['Top'] * image_height
x2 = x1 + box['Width'] * image_width
y2 = y1 + box['Height'] * image_height
image_crop = image.crop((x1,y1,x2,y2))
stream = io.BytesIO()
image_crop.save(stream,format="JPEG")
image_crop_binary = stream.getvalue()response = rekognition.search_faces_by_image(
CollectionId=collectionId,
Image={'Bytes':image_crop_binary}
)
if len(response['FaceMatches']) > 0:
draw = ImageDraw.Draw(image)
points = (
(x1,y1),
(x2, y1),
(x2, y2),
(x1 , y2),
(x1, y1))
draw.line(points, fill='#00d400', width=2)
fnt = ImageFont.truetype('/Library/Fonts/Arial.ttf', 15)
draw.text((x1,y2),response['FaceMatches'][0]['Face']['ExternalImageId'], font=fnt, fill=(255, 255, 0))display(image)
是啊!可以的!它正确地识别了所有成员!
感谢您的阅读。你可以从下面的链接中找到 Jupyter 笔记本和用于这个项目的图片。
https://github.com/tthustla/twice_recognition
使用 Streamlit 构建机器学习应用
原文:https://towardsdatascience.com/building-machine-learning-apps-with-streamlit-667cef3ff509?source=collection_archive---------19-----------------------
Streamlit 是一个开源的 Python 库,可以轻松构建漂亮的机器学习应用。你可以通过 pip 在你的终端上轻松安装它,然后开始用 Python 编写你的网络应用。
在这篇文章中,我将展示一些关于 Streamlit 的有趣功能,构建一个以检查数据为目的的应用程序,并在其上构建 ML 模型。为此,我将使用非常基本的 Iris 数据集,并对其进行一些分类。然而,如果你对这个工具更高级的潜力感兴趣,我建议你阅读这个教程。
说到这里,让我们开始构建我们的应用程序。我将把我所有的代码写在一个名为 iris.py 的文件中,这样我就可以通过 streamlit iris.py 从我的终端运行它。
最后,我的应用程序的完整代码如下:
import streamlit as st
import pandas as pd
import numpy as np
import plotly.express as px
import seaborn as sns
import matplotlib.pyplot as plt
import plotly.graph_objects as gost.title('Iris')df = pd.read_csv("iris.csv")if st.checkbox('Show dataframe'):
st.write(df)st.subheader('Scatter plot')species = st.multiselect('Show iris per variety?', df['variety'].unique())
col1 = st.selectbox('Which feature on x?', df.columns[0:4])
col2 = st.selectbox('Which feature on y?', df.columns[0:4])new_df = df[(df['variety'].isin(species))]
st.write(new_df)
# create figure using plotly express
fig = px.scatter(new_df, x =col1,y=col2, color='variety')
# Plot!st.plotly_chart(fig)st.subheader('Histogram')feature = st.selectbox('Which feature?', df.columns[0:4])
# Filter dataframe
new_df2 = df[(df['variety'].isin(species))][feature]
fig2 = px.histogram(new_df, x=feature, color="variety", marginal="rug")
st.plotly_chart(fig2)st.subheader('Machine Learning models')from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import confusion_matrix
from sklearn.svm import SVCfeatures= df[['sepal.length', 'sepal.width', 'petal.length', 'petal.width']].values
labels = df['variety'].valuesX_train,X_test, y_train, y_test = train_test_split(features, labels, train_size=0.7, random_state=1)alg = ['Decision Tree', 'Support Vector Machine']
classifier = st.selectbox('Which algorithm?', alg)
if classifier=='Decision Tree':
dtc = DecisionTreeClassifier()
dtc.fit(X_train, y_train)
acc = dtc.score(X_test, y_test)
st.write('Accuracy: ', acc)
pred_dtc = dtc.predict(X_test)
cm_dtc=confusion_matrix(y_test,pred_dtc)
st.write('Confusion matrix: ', cm_dtc)elif classifier == 'Support Vector Machine':
svm=SVC()
svm.fit(X_train, y_train)
acc = svm.score(X_test, y_test)
st.write('Accuracy: ', acc)
pred_svm = svm.predict(X_test)
cm=confusion_matrix(y_test,pred_svm)
st.write('Confusion matrix: ', cm)
现在,让我们检查每段代码。首先,一旦导入了所需的包,我想设置我的应用程序的标题并导入我的数据:
import streamlit as st
import pandas as pd
import numpy as np
import plotly.express as px
import seaborn as sns
import matplotlib.pyplot as plt
import plotly.graph_objects as gost.title('Iris')df = pd.read_csv("iris.csv")
现在我想要第一个选项,它允许用户决定是否显示整个数据集。我可以用下面的语法做到这一点(以及许多其他交互小部件):
if st.checkbox('Show dataframe'):
st.write(df)
尽管天真,我们已经可以启动我们的婴儿应用程序,并在 localhost:8501:
如您所见,我决定显示我的数据集,但是,在任何时候,我都可以通过取消选中该框来隐藏它。
现在让我们转向一些可视化工具。假设我想要散点图我的数据,有可能选择那些我感兴趣的要素和标签。
species = st.multiselect('Show iris per variety?', df['variety'].unique())
col1 = st.selectbox('Which feature on x?', df.columns[0:4])
col2 = st.selectbox('Which feature on y?', df.columns[0:4])new_df = df[(df['variety'].isin(species))]
st.write(new_df)
fig = px.scatter(new_df, x =col1,y=col2, color='variety')st.plotly_chart(fig)
正如你所看到的,在我选择的例子中,物种杂色和海滨锦鸡儿的特征是萼片长度和萼片宽度,但我可以随时改变它们,并实时更新我的所有图表。
现在,我想用同样的逻辑添加一个直方图,显示任何特征的分布。此外,我想有可能绘制出每个特征的 3 个条件分布,相对于以前选择的品种。因此:
feature = st.selectbox('Which feature?', df.columns[0:4])
# Filter dataframe
new_df2 = df[(df['variety'].isin(species))][feature]
fig2 = px.histogram(new_df, x=feature, color="variety", marginal="rug")
st.plotly_chart(fig2)
这两个物种和我上面选的是一样的,而且,我可以随时改变它们。
现在让我们进入最后一部分,即训练实时 ML 算法,并让用户决定应用哪一种算法。为此,我将在 S 支持向量机和 D 决策树这两种分类算法之间进行选择。对于每一个问题,我会让我的应用程序打印准确性(正确分类的数量/观察总数)和混淆矩阵:
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import confusion_matrix
from sklearn.svm import SVCfeatures= df[['sepal.length', 'sepal.width', 'petal.length', 'petal.width']].values
labels = df['variety'].valuesX_train,X_test, y_train, y_test = train_test_split(features, labels, train_size=0.7, random_state=1)alg = ['Decision Tree', 'Support Vector Machine']
classifier = st.selectbox('Which algorithm?', alg)
if classifier=='Decision Tree':
dtc = DecisionTreeClassifier()
dtc.fit(X_train, y_train)
acc = dtc.score(X_test, y_test)
st.write('Accuracy: ', acc)
pred_dtc = dtc.predict(X_test)
cm_dtc=confusion_matrix(y_test,pred_dtc)
st.write('Confusion matrix: ', cm_dtc)elif classifier == 'Support Vector Machine':
svm=SVC()
svm.fit(X_train, y_train)
acc = svm.score(X_test, y_test)
st.write('Accuracy: ', acc)
pred_svm = svm.predict(X_test)
cm=confusion_matrix(y_test,pred_svm)
st.write('Confusion matrix: ', cm)
那么,如果我选择 SVM:
因此,我们能够以一种非常用户友好的方式即时比较两个分类器的性能。
Streamlit 是一个非常强大的工具,特别是如果您想要提供一种交互式的方式来理解您的分析结果:它允许实时可视化您的数据,并有可能过滤它们,它允许有意义的表示。
在这里,我向您展示了使用 Streamlit 可以实现的非常基本的实现,因此,如果您想更深入地研究这个工具,我推荐您进一步阅读参考资料。
参考文献:
- https://streamlit.io/docs/
- https://streamlit.io/docs/tutorial/index.html
原载于 2019 年 10 月 22 日http://datasciencechalktalk.com。
构建预测抗生素耐药性的机器学习模型
原文:https://towardsdatascience.com/building-machine-learning-models-for-predicting-antibiotic-resistance-7640046a91b6?source=collection_archive---------21-----------------------
DPhoto by Markus Spiske on Unsplash
我第一次向计算机科学学生介绍用 ML 预测抗生素耐药性的研讨会的回顾
这个月,我在罗马尼亚的克卢日纳波卡为大约 25 名计算机科学学生举办了一个研讨会。该研讨会是为期两天的生物学中的 ML 研讨会的一部分,由罗马尼亚生物信息学协会组织。
Cluj-Napoca, Romania
根据之前的民意调查,计算机科学专业的理学学士、理学硕士和博士学生对学习 ML 在医学和生物学中的应用非常感兴趣。大多数参加会议的学生在本科学习期间学习了机器学习算法,但对学习更多关于生物信息学/生物学的知识感兴趣。
我在研讨会中的角色是就预测抗生素耐药性的 ML 发表一个小时的演讲,然后为一部分学生举办两个小时的实践研讨会。我的目的是向学生介绍 ML 在鉴定抗生素耐药细菌中的应用,并让他们思考我们用于 ML 的标准方法在应用于细菌基因组数据时的一些当前局限性,以及超越这些局限性的方法。
问题简介
对治疗没有反应的细菌感染越来越令人担忧。目前,抗生素耐药性感染每年导致 70 多万人死亡,到 2050 年,预计将有 1000 万人死于抗生素耐药性感染,除非我们对开发和使用抗生素的方式做出重大改变。
从全基因组序列预测抗生素耐药性的机器学习算法可以提高我们识别和遏制新耐药菌株的能力。在不久的将来,有可能在采集样本后的几个小时内对引起感染的细菌的 DNA 进行测序,然后分析这些 DNA 序列数据,以预测哪些抗生素可以成功用于治疗感染。
耐药性在淋病奈瑟菌,导致淋病的细菌是一个特别大的问题,淋病感染对所有可用的抗生素都具有耐药性,这在世界各地都有出现。淋病是欧洲第二常见的性传播感染(STI),仅次于衣原体。淋病感染率正在上升,英国 2017-2018 年报告的病例增加了 26%。
许多被感染的人没有任何症状,这有助于感染的传播。如果不进行治疗,这种感染会导致男性和女性不孕,或导致危及生命的宫外孕。患有淋病的母亲所生的婴儿可能会发生眼部感染,如果不治疗,会导致永久性失明。
Increasing resistance to the antibiotics we use to treat gonorrhoea. Image from Whittles et al. 2018.
过去,病人用一种叫做环丙沙星的抗生素治疗。医生现在已经停止用这种抗生素治疗感染,因为对这种药物的耐药性变得太普遍,导致治疗失败。直到最*,推荐的治疗是两种药物——头孢曲松和阿奇霉素。但是,由于担心对阿奇霉素耐药性的上升,阿奇霉素已从英国的治疗建议中删除。目前在英国,患者仅接受头孢曲松的治疗。
2018 年 2 月,报告了有史以来第一例对所有常用治疗方法产生耐药性的病例,今年,英国两名女性在没有离开该国的情况下感染了这种疾病,这表明耐药性将持续存在。
[## 男人得了“世界上最严重的”超级淋病
英国一名男子感染了世界上“有史以来最严重”的超级淋病。他在英国有固定的伴侣,但是…
www.bbc.co.uk](https://www.bbc.co.uk/news/health-43571120)
多年来,由于耐药性增加,许多药物已经从治疗建议中删除,但这些抗生素中的每一种仍然可以用于治疗一些感染,这意味着如果我们可以自信地预测抗生素耐药性,我们可以重新使用这些抗生素。
研讨会的形式
参加研讨会的每个人也参加了我的演讲,我的演讲向人们介绍了我们对抗生素耐药性细菌感染日益增长的担忧,以及如何将机器学习算法构建到护理点诊断中,以帮助减少或消除抗生素耐药性的传播。
该研讨会旨在让人们亲自查看数据,并使用它来构建机器学习算法。由于之前没有设计过研讨会,我不确定在 2 个小时的时间内需要准备多少材料,所以我设计了一个简单的活动,后续工作有多个选项,让参与者做他们感兴趣的事情。
我使用 Kaggle 运行研讨会,因为它允许我上传数据,并通过一个简单的界面访问数据,这允许包含额外的信息以给出数据上下文。我创建了一个入门笔记本,带领参与者阅读和查看数据,然后构建一些简单的模型并评估他们的表现。
培训用数据
在这个实验中,我们使用了 unitigs,我们收集的菌株共有的 DNA 片段。这些是通过提取不同细菌的 DNA 产生的,我们在对它们的基因组测序后将这些 DNA 拼凑在一起,然后将其分解为不同的 31 个字符的单词。这些词然后被组合成一个德布鲁因图(DBG)。该图是通过识别内部重叠的单词拼凑而成的,并且出现在相同的样本中。
要了解更多关于 unitigs 的信息,请阅读本文:
[## 一种快速和不可知的细菌全基因组关联研究方法:弥合…
作者摘要全基因组关联研究(GWAS)有助于探索癌症表型变异的遗传基础
journals.plos.org](https://journals.plos.org/plosgenetics/article?id=10.1371/journal.pgen.1007758)
这个过程让我们能够以一种高效的方式来表现这些不同细菌之间的异同。这种差异可能是个体突变,插入或删除的 DNA 片段,或其他称为质粒的遗传元素,它们可以在细菌之间传递并传播抗生素耐药性。
通常,在处理 unitigs 时,变量的数量可能在 50-500 万之间,但出于练习的目的,我首先进行了一项关联研究,以确定与耐药性显著相关的 unitigs,从而加快分析速度。
对于包含 3,971 个样本的数据集,过滤后得到 8,873 个与环丙沙星耐药性高度相关的单位免疫球蛋白和 515 个与阿奇霉素耐药性显著相关的单位免疫球蛋白。
Strength of association between unitigs and resistance for the full set of 584,362 unitigs.
模型结构
我们研究了四种不同的模型类型:
- 弹性净逻辑回归
- 支持向量机
- XGBoost
- 随机森林
我们还观察了两种阻力曲线:
- 阿奇霉素耐药性
- 环丙沙星耐药性
我整理了一个简单的模型训练笔记本,将数据分成五份进行交叉验证,并在每一份内对可能的超参数进行网格搜索,再次使用五份交叉验证。
使用这个函数,我们可以跨数据集比较不同模型类型的性能。
参与者对下一步有几个选择。在后续部分中,他们可以做的其他事情有:
- 看看你的模型学到了什么,这是否符合我们现有的抗生素耐药性知识
- 检查收集更多样本是否有可能提高算法的性能
- 探索更多的超参数,并尝试建立更准确的模型
- 尝试一些其他模型类型
- 预测对另一种抗生素的耐药性
- 尝试其他交叉验证和取样技术,以弥补抗药性样本的稀少(类别不*衡)
- 看一些关于抗生素耐药性和机器学习的文章
模型性能和学习
在我们测试的更复杂的 ML 方法中,阿奇霉素(AZM)的预测性能很高。虽然模型类型的表现非常相似,但随机森林在小得多的样本量下了解到了阻力。
在训练结束时,两个模型都学会了寻找相同的 unitig,该 unitig 包含 23S 核糖体 RNA 中的一个突变,该突变负责大多数高水*的 AZM 抗性。
环丙沙星耐药性通常可以通过寻找导致绝大多数耐药性的一个或两个突变来预测任何物种。从这个意义上来说,它们是容易建立的模型,但是 ML 模型有时很难建立一个没有无关信息的模型。
下面,我们可以看到,随机森林找到了一个很好的解决问题的方法,但 SVM 似乎有过度适应。这两种模型看起来都不会从更多样本的收集中获得特别的好处。
当我研究模型所了解的内容时,我失望地看到,尽管两个模型都非常准确,但我们知道驱动耐药性的主要突变并没有被这两个模型选为首要特征,这表明模型已经找到了一种准确预测耐药性的替代解决方案,不涉及实际的耐药机制。
这是该领域 ML 中一个相对常见的问题——变量如此之多,样本如此之少,以至于在数据中可能形成虚假的关联。这种高性能可能是由于模型识别了标记主要抗性菌株家族的单位,而不是真正的抗性机制。对此进行诊断的最佳方法是查看统一群在分离株的系统发育树上的位置。
你自己试试吧
这个工作坊完全是在 Kaggle 上进行的,所以你可以亲自尝试一下。
未来的工作
我主要是通过在 Kaggle 上跟随人们的笔记本来学习如何建立 ML 模型,所以我希望在这个领域工作的其他人会发现数据集和工作簿是对这个主题的很好的介绍。
现在我已经有了一个研讨会的起点,我计划随着时间的推移对它进行改进,并在更多的环境中运行它,特别是为那些没有太多机器学习经验的人。
我还想探索在出版物中包含笔记本的更新/扩充版本的可能性,让其他人容易地复制和调整分析。
构建音乐播放列表推荐系统
原文:https://towardsdatascience.com/building-music-playlists-recommendation-system-564a3e63ef64?source=collection_archive---------20-----------------------
内容摘自我们题为“音乐播放列表的表示、探索和推荐”的论文
Photo by Mariah Ashby on Unsplash
快速小结
目标
这项工作的目标是以一种捕捉播放列表的真正本质的方式来表示播放列表,即诸如类型、流派、种类、顺序和播放列表中歌曲数量的信息,并且可以用于诸如播放列表发现和推荐的任务。
贡献
- 使用 sequence-2-sequence 学习为播放列表构建推荐引擎。
- 使用基于推荐的评估任务对作品进行评估。
- 为这部作品收集了 100 万个 Spotify 播放列表和 1300 万首歌曲。
应用程序
播放列表发现/推荐引擎
我们的系统可以用于播放列表发现和推荐。给定查询播放列表,系统从数据库返回与输入播放列表最相似的播放列表。
Image displaying the usage for our playlist recommendation engine. The system returns playlists most similar to the query playlist.
开发人员友好的大纲
以下是我们建议方法的简要概述:
- 使用 Spotify 开发者 API 和 everynoise.com 下载播放列表数据。
- 通过去除噪声(稀有歌曲、重复歌曲、异常播放列表等)来过滤数据。)
- 在数据上训练 sequence-2-sequence⁹模型以学习播放列表嵌入。
- 注释数据(歌曲和播放列表)的流派信息。
- 使用我们建议的评估任务评估嵌入。
- 通过用学习到的播放列表嵌入填充 KD 树来构建推荐引擎,并通过利用最*邻方法来检索搜索结果。
介绍
如今,播放列表已经成为我们音乐聆听体验的重要组成部分。仅在 Spotify 上就有超过 30 亿条。每个时刻、每个心情、每个季节等等都有播放列表。数百万首歌曲唾手可得,如今的用户已经习惯了:
1.立即满足他们的音乐需求。
2。一段漫长的经历。
推荐引擎服务于第一个方面,而播放列表处理这种变化行为的第二个方面,使得播放列表推荐对于用户和音乐公司来说都极其重要。
什么是播放列表,我为什么要关心它?
"播放列表是一组应该一起听的歌曲,通常有明确的顺序."
从用户和音乐研究者的角度来看,播放列表在今天是极其重要的。从用户的角度来看,播放列表是发现新音乐和艺术家的有效方式。从研究者的角度来看,重要的是要理解音乐是通过听来消费的,播放列表使这种听的体验正式化。播放列表是一个可以被发现和推荐的单元组件,就像艺术家、歌曲和专辑一样。
“从研究人员的角度来看,重要的是要理解音乐是通过听来消费的,播放列表使这种听的体验正式化”
那么问题出在哪里?
如前所述,由于播放列表的使用迅速增加,播放列表推荐对当今的音乐服务至关重要。然而,在过去的几年里,从研究的角度来看,播放列表推荐已经变得类似于播放列表 prediction/creation⁷ ⁸和 continuation⁵ ⁶,而不是播放列表发现。然而,播放列表发现形成了整个播放列表推荐管道的重要部分,因为它是帮助用户发现*台上现有播放列表的有效方式。
探索是这个游戏的名字
我们的工作旨在以一种可以用来发现和推荐现有播放列表的方式来呈现播放列表。我们使用序列到序列 learning⁹来学习播放列表的嵌入,在没有任何监督的情况下捕捉它们的语义。然后,这些固定长度的嵌入可以用于推荐目的。
方法背后的直觉
为什么是序列对序列学习?
选择序列对序列学习背后的主要直觉是,播放列表可以被解释为句子,歌曲可以被解释为句子中的单词。在过去的几年里,序列对序列学习已经被广泛地用于学习有效的句子嵌入,例如神经机器翻译⁰.我们利用播放列表:歌曲::句子:单词的关系,并从自然语言处理领域的研究中获得灵感,以嵌入句子的方式对播放列表嵌入进行建模。
我们利用播放列表:歌曲::句子:单词的关系,并从自然语言处理的研究中获得灵感,以嵌入句子的方式对播放列表嵌入进行建模。
序列对序列学习
名称序列到序列学习的核心意思是训练网络接受序列并输出序列。因此,网络不是预测单个单词,而是输出整个句子,这可能是外语翻译,或者是语料库中的下一个预测句子,或者甚至是同一个句子,如果网络像自动编码器一样被训练的话。
对于这项工作,我们使用 seq2seq 框架作为自动编码器,其中网络的任务是重建输入播放列表,并在这样做的过程中,学习输入播放列表的紧凑表示,它捕获播放列表的属性。
The overall concept of using seq2seq network like an autoencoder.
Seq2seq 型号
我们将注意力技术用于本工作中使用的 seq2seq 模型,以学习播放列表嵌入,该播放列表嵌入捕获播放列表中歌曲之间的长期依赖性,因为播放列表的长度相对较长(50-1000 首歌曲)。我们用 seq2seq 模型的两种变体进行实验:
1.单向 seq2seq 网络
2。双向 seq2seq 网络
双向 seq2seq 网络不同于单向网络,因为使用了双向 RNN ,这意味着隐藏状态是在两个相反方向读取序列的前向 RNN 和后向 RNN 的串联。这允许网络为解码器捕捉更多上下文信息以预测输出符号。
数据:管理、过滤和注释
需要
对于这项工作,我们需要一个播放列表(句子)列表,每个播放列表由一个歌曲(单词)列表组成。为了以最简单的形式解决这个问题,我们只需要播放列表 id 和与适当的播放列表 id 对应的歌曲 id。
数据集创建
我们使用 Spotify Web API 下载数据。为了收集足够多的术语来查询 Spotify 系统,我们使用everynoise.com。这个互动网站包含了大约 2600 多种音乐类型的列表,根据它们之间的关系用图表表示出来,每种类型都有一个音频示例。我们解析这个网站主页上的数据,得到所有流派的列表。然后,对于每个流派,我们使用 Spotify Web API 下载播放列表(以及相应的歌曲信息)。整个流程如图 1 所示。
Fig 1: Data download workflow
以下是下载数据的详细信息:
- 100 万个播放列表
- 130 万艺术家。
- 1300 万首曲目
- 300 万首独特曲目
- 三百万张专辑
- 2680 流派
数据过滤
我们按照[1]的方法,通过移除稀有曲目和异常播放列表(歌曲数量少于 10 首或多于 5000 首)来进行数据清理。这样就剩下 755k 个唯一播放列表和240 万首唯一曲目。
注释
问题:流派,流派遍地
虽然这一步对于培训部分不是直接需要的,但是对于评估阶段却是至关重要的。这一步的目的是给播放列表标上合适的流派。目前可用的信息存在某些问题:
- Spotify 提供艺术家的流派信息,但不提供歌曲。将歌曲流派标记为艺术家流派并不完全正确,因为艺术家可以拥有不同流派的歌曲。
2.将歌曲指定为与播放列表相同的流派,这将是有问题的,而播放列表又是从获取它的查询项中导出的。走这条路的问题是与它相关的主观性。提供了这种细粒度的注释,从分类的角度来看,软摇滚、80 年代摇滚、经典摇滚、摇滚会有什么区别?
因此,我们需要将类型(输出标签)的数量从 2680 减少到一个更容易管理的数量。
拟议解决方案
Data annotation workflow
1.为了解决这个问题,我们在我们的语料库上训练了一个 word2vec 模型来获得歌曲嵌入,该模型通过歌曲在语料库中的共现来捕获歌曲的语义特征(如流派)。
2.所得的歌曲嵌入然后被聚类成 200 个聚类(任意选择的数目,以试图保持注释过程的可行性和所形成的聚类的大小之间的*衡。期望更小的簇大小和更少的注释时间)。
3.对于每个集群:
艺术家流派应用于每首相应的歌曲,并创建一个流派频率(计数)字典。具有 17 首歌曲聚类的样本流派计数字典看起来像{摇滚:5,独立摇滚:3,蓝调:2,软摇滚:7}
从该字典中,具有明显多数的风格被指定为该群中所有歌曲的风格。
不具有明显流派优势的群集中的所有歌曲都被丢弃以进行注释。
基于所观察到的数据中的流派分布,并且作为将子流派(例如软摇滚)聚类成父流派(例如摇滚)的结果,最终选择用于注释聚类的流派是:
摇滚、金属、蓝调、乡村、雷鬼、拉丁、电子、嘻哈古典。
为了验证我们的方法,我们在由带注释的歌曲嵌入组成的数据集上训练了一个分类器。通过在训练时将训练集和测试集分开,我们实现了 94%的测试准确率。
t-SNE plot for genre-annotated songs, with 1000 sampled songs for each genre
对于播放列表类型注释,只有注释了所有歌曲的播放列表才会被考虑进行注释。此外,只有那些 70%以上的歌曲在一个流派上一致的播放列表才被分配流派。
估价
由于我们工作的目的是学习可用于推荐的播放列表嵌入,我们使用推荐任务来评估嵌入的质量。
推荐任务
本质上具有内在主观性的推荐最好通过具有用户标记的数据来评估。然而,在没有这种带注释的数据集的情况下,我们通过测量由嵌入模型创建的播放列表空间在何种程度上是相关的来评估我们提出的方法,就风格的相似性和紧密放置的播放列表的长度信息而言。
我们使用 Spotify ANNOY 库的*似最*邻算法来用播放列表嵌入填充树结构。随机选择查询播放列表,并将搜索结果与查询的播放列表在类型和长度信息方面进行比较。有九种可能的类型标签。为了比较长度,创建了十个输出类(跨越范围{30…250},对应于大小为 20 的容器。考虑每个查询的*均 100 个精度值。
基线比较
为了评估我们提出的技术的性能,我们还需要某种基线性能。作为我们的基线模型,我们实验了词袋模型⁴的加权变体,它使用加权*均方案来获得句子嵌入向量,然后使用奇异值分解(SVD)来修改它们。与传统*均相比,这种生成句子嵌入的方法被证明是一种更强的基线。
结果
如下图所示,推荐任务捕获了一些关于不同模型捕获不同特征的有效性的有趣见解。首先,高精度值证明了播放列表嵌入空间的相关性,这是推荐系统的首要期望。此外,BoW 模型比 seq2seq 模型更好地捕捉体裁信息,而 seq2seq 模型更好地捕捉长度信息,这表明了不同模型对不同任务的适用性。
应用程序
这项工作的直接应用之一是播放列表的推荐引擎。给定一个查询,系统将从语料库中推荐/检索相似的播放列表。在推荐任务部分中讨论的树数据结构可以直接用于这个目的。给定一个查询播放列表,它的 k 个最*邻居将是与其最相似的项目,并且将是系统推荐。我们的工作演示可以在视频中看到。
Recommendation System Demo video
仅此而已。我们提出了一种基于 seq2seq 的播放列表嵌入学习方法,该方法可用于播放列表发现和推荐等任务。我们的方法还可以通过集成基于内容的(歌词、音频等)来扩展用于学习甚至更好的播放列表表示。)歌曲嵌入模型,以及用于通过使用变化的序列模型来生成新的播放列表。
在本文中,有更多的评估技术来评估关于编码信息的播放列表嵌入的质量,这超出了本文的范围。我将在另一篇文章中讨论这个问题。
下次见!
页(page 的缩写)s——这是论文的链接。
参考
[1]https://news room . spotify . com/2018-10-10/庆祝 Spotify 发现十年/
[2] Keunwoo Choi、George Fazekas 和 Mark Sandler。使用在轨道内转换上训练的 rnn 的播放列表生成算法。arXiv 预印本 arXiv:1606.02096,2016
[3]菲尔兹、本和保罗·拉梅尔。"通过自动点唱机寻找路径——播放列表教程,ISMIR . "伊斯米尔,乌得勒支(2010 年)。
[4]德穆伊杰和维海格。"学习音乐播放列表的偏好设置。"人工智能 97.1–2(1997):245–271。
[5]青-陈为、保罗·拉梅尔、马库斯·舍德尔和哈米德·扎马尼。Recsys 挑战赛 2018:自动音乐播放列表延续。第 12 届 ACM 推荐系统会议论文集,527-528 页。ACM,2018
[6] Maksims Volkovs,Himanshu Rai,Cheng,Ga Wu,Yichao Lu 和 Scott Sanner。大规模自动播放列表延续的两阶段模型。《2018 年美国计算机学会推荐系统挑战赛论文集》第 9 页。ACM,2018
[7]安德烈亚·安德里奇和戈弗雷多·豪斯。基于跟踪用户收听习惯的自动播放列表生成。多媒体工具和应用,29(2):127–151,2006。
[8]贝丝·洛根。基于内容的播放列表生成:探索性实验。InISMIR,2002 年。
[9] lya Sutskever、Oriol Vinyals 和 Quoc V Le。用神经网络进行序列间学习。神经信息处理系统进展,第 3104–3112 页,2014 年。
[10] Dzmitry Bahdanau、Kyunghyun Cho 和 Yoshua Bengio。通过联合学习对齐和翻译的神经机器翻译. arXiv 预印本 arXiv:1409.0473,2014。
[11] Mikolov,Tomas 等,“向量空间中单词表示的有效估计” arXiv 预印本 arXiv:1301.3781 (2013)。
[12]沈艳芳莉莉艾。音乐盒:导航你的音乐空间。麻省理工学院博士论文,2008 年
[13] Bernhardsson,e .,“骚扰:C++/Python 中的*似最*邻,针对内存使用和加载/保存到磁盘进行了优化”GitHubT8https://GitHub。**com/Spotify/airy(2017)。
[14]阿罗拉、桑吉夫、梁和马腾宇。"一个简单但难以击败的句子嵌入基线."(2016).
用一个简单的 Python 脚本构建我的 2020 阅读清单
原文:https://towardsdatascience.com/building-my-2020-reading-list-with-a-simple-python-script-b610c7f2c223?source=collection_archive---------13-----------------------
使用 Requests 和 BeautifulSoup,我提取了《纽约时报》畅销书(商业主题)列表来充实我的阅读列表
新年决心:2020 年 12 本书
我承认在过去的几年里我没有读太多的书。随着 2012 年 MOOC(大规模开放在线课程)的发展,我大部分业余时间都在 Coursera、edX 和 LinkedIn 上学习。MOOC 上的许多内容很好地阐述了知识(如编程技术、统计概念等),这对我早期的职业成长有很大帮助;然而,我总觉得只用 MOOC 少了些什么,但我不知道是什么。
今天,在 2019 年底,在读完《动力:关于激励我们的令人惊讶的真相》并开始享受《关于困难的困难:在没有简单答案的情况下创业》后,非常神奇的是(对我来说),阅读书籍,将它们放在手边,可以引发大量的思考,也有助于连接许多随机的想法。这些心理活动加强了理解,并引导一个人的思想深入到文本本身之外。这是一种如此独特的体验,是我过去在任何 MOOC *台上都无法理解的!于是我下定决心,定下一个新年决心:2020 年读 12 本书。
Photo by Sincerely Media on Unsplash
那么我应该优先考虑哪些书呢?鉴于我的特定领域和职业方向,我喜欢在第一个“阅读年”更多地关注商业和领导力方面。除了博学的朋友推荐的几本好书(例如《关于困难的困难》、《万亿美元蔻驰》),我仍然缺少与商业和领导力相关的好书。于是我向著名的《纽约时报畅销书》求助:如果一本书卖得这么好,有资格上榜,那它一定有值得一读的见解。
太多的书是“纽约时报畅销书”
我打开《纽约时报》上最*的商业列表(链接)后,它显示了 10 本书的书名,而且这个列表每个月都会改变!如果我已经阅读了其中的大部分,并且只是从列表中进行增量选择,那就太好了,但显然这不是我的情况,那么如何从所有历史“畅销书”中优先选择几本呢?我试着在谷歌上搜索类似“纽约时报畅销书排行榜”的东西,但它没有返回任何有意义的结果:也许没有人像我一样有特殊的需求。我试图用历史数据来支持我的第一年阅读清单,而其他人可能已经阅读了其中的大部分:(
尽管如此,我还是不想放弃,仅仅从最*的榜单中随机挑选几本肯定不是我的风格:我想用硬核数据来支持我的选择,我想知道纽约时报畅销书排行榜历史上最受欢迎的书;然而,这些数据分散在多个网页上,不便于阅读。面对这样的挑战,数据科学家会怎么做?嗯,他/她要写一些代码。我的目标很明确,获得所有历史性的纽约时报畅销书排行榜(商业话题),然后评估这些书,建立我的 2020 年阅读清单。
有趣的部分:使用 Python 进行 web 分析
我的工作流程非常简单明了;它有三个步骤。
第一步。了解 web 组件
我检查了两件事:
- 所有月份中 URL 的命名是否一致
- 是否可以一致引用所有 URL 中的 web 元素。
对于纽约时报网站,所有的 URL 都具有类似https://www . nytimes . com/books/best-sellers/2019/08/01/business-books/的结构,年份和月份是唯一的变量。检查过了!
对于 web 元素,每个月的前 10 个列表组织在一个有序列表(“ol”)中,类名为“css-12yzwg4”。内容以类名“css-xe4cfy”保存在 div(“div”)内部,每本书都是内容的一项。书名有“h3”标签,类名“css-5pe77f”,图书作者有“p”标签,类名“css-hjukut”。检查过了!
Web element: the top 10 list for each month is organized inside an ordered list (“ol”) with class name “css-12yzwg4”
现在我们得到了所有的关键元素布局,它们在所有的 URL 上都是一致的,这对于继续下一步是个好消息。
第二步。编写脚本来自动下载
我已经有一段时间没有使用 Requests/BeautifulSoup 了,所以从其他人的作品中借鉴一下也不错。在“python requests beautifulsoup”上搜索,我找到了一篇不错的文章可以参考:https://www . digital ocean . com/community/tutorials/how-to-work-with-web-data-using-requests-and-beautiful-soup-with-python-3。
我的代码流非常简单:
- 使用请求加载页面 URL
- 使用 BeautifulSoup 解析出所需的元素
- 使用 Pandas Dataframe 保存结果。
(代码链接)
# This scripts aims to get all book names on historic New York Time Best Sellers (Business section)
# The purpose is to:
# 1\. help to compile my reading list in 2020
# 2\. serve as reference to use Python for simple web analytics# One interesting finding:
# 1\. no best seller list for 2015-08, maybe a bug in New York Times systemimport requests
import pandas as pd
from bs4 import BeautifulSoupnylist = pd.DataFrame()# the earliest list is 2013/11/01, so the starting year is 2013
for the_year in range(2013, 2020):
for the_month in range(1, 13):# one need to get the URL pattern first, and then use Requests package to get the URL content
url = '[https://www.nytimes.com/books/best-sellers/{0}/{1}/01/business-books/'.format(the_year,](https://www.nytimes.com/books/best-sellers/{0}/{1}/01/business-books/'.format(the_year,) str(the_month).zfill(2))
page = requests.get(url)
print(" -- try: {0}, {1} -- ".format(the_year, str(the_month).zfill(2)))# ensure proper result is returned
if page.status_code != 200:
continue# one may want to use BeautifulSoup to parse the right elements out
soup = BeautifulSoup(page.text, 'html.parser')
# the specific class names are unique for this URL and they don't change across all URLs
top_list = soup.findAll("ol", {"class": "css-12yzwg4"})[0].findAll("div", {"class": "css-xe4cfy"})
print(the_year, the_month, len(top_list))# loop through the Best Seller list in each Year-Month, and append the information into a pandas DataFrame
for i in range(len(top_list)):
book = top_list[i].contents[0]
title = book.findAll("h3", {"class": "css-5pe77f"})[0].text
author = book.findAll("p", {"class": "css-hjukut"})[0].text
review = book.get("href")
# print("{0}, {1}; review: {2}".format(title, author, review))
one_item = pd.Series([the_year, the_month, title, author, i+1, review], index=['year', 'month', 'title', 'author', 'rank', 'review'])
nylist = nylist.append(one_item, ignore_index=True, sort=False)# write out the result to a pickle file for easy analysis later.
nylist.to_pickle("nylist.pkl")
nylist.to_csv("nylist.csv", index=False)
第三步。分析数据以发现真知灼见
现在,我们已经将所有畅销书(商业)标题数据保存在数据框架中,我做了一些快速探索,发现了以下事实:
- 从 2013 年 11 月到 2019 年 12 月,共有 189 本书上榜,其中 92 本只在榜单上出现过一次。
- 名单中提及最多的 5 本书是:《思考,快与慢》(58)、《局外人》(51)、《习惯的力量》(45)、《勇气》(29)和《极端所有权》(25)。
- 如果只关注每月第一畅销书,提及最多的 5 本书是:《坏血》(7)、《敢于领导》(7)、《木兰花的故事》(7)、《向前一步》(5)和《局外人》(5)。
“Thinking, Fast and Slow” shows up more than 58 times in the New York Times Best Seller (Business) list, between Nov 2013 to Dec 2019
注意。纽约时报网站上没有 2015 年 8 月的数据,我认为这应该是他们需要解决的一个问题。
我的阅读清单上增加了六本书
上面的统计数据提供了很好的见解,然后我查看了他们各自的评论,以理解高层次的概念。虽然我认为所有的书都很棒,但鉴于我的时间有限,我在 2020 年的阅读清单中增加了以下 6 本书:
- 丹尼尔·卡内曼的《思考,快与慢》
- 约翰·卡雷鲁的《坏血》
- 布琳·布朗的《敢于领导》
- “极端所有权”,作者乔科·威林克和叶小开·巴宾
- 查尔斯·杜希格的《习惯的力量》
- 《向前一步》,雪莉·桑德伯格和内尔·斯科维尔合作
最后
这是一个使用 Python 解决实际问题的简单演示。编码工作花了我大约一个小时,而写这篇文章要花更长的时间……这里有一些事情你可能会觉得有帮助:
- 历史悠久的《纽约时报》畅销书排行榜(链接)可能对你准备阅读清单有所帮助
- 如果你也尝试用 Python 做基本的网络分析,代码(链接)可能会有帮助
- 这一过程可能会揭示数据科学家在面临这样的挑战时是如何思考的
享受阅读,祝你新年快乐!
用 PyTorch 构建神经网络
原文:https://towardsdatascience.com/building-neural-network-using-pytorch-84f6e75f9a?source=collection_archive---------2-----------------------
“计算机能否思考的问题并不比潜艇能否游泳的问题更有趣。”
― 埃德格·w·迪杰斯特拉
source: here
在本教程中,我们将使用 PyTorch 从头开始实现一个简单的神经网络。我正在分享我从最*的 facebook-udacity 奖学金挑战项目中学到的东西。本教程假设你事先了解神经网络如何工作。
虽然有很多库可以用于深度学习,但我最喜欢 PyTorch。作为一名 python 程序员,我喜欢 PyTorch 的 python 行为是背后的原因之一。它主要使用 python 的风格和功能,易于理解和使用。
py torch 的核心提供了两个主要特性:
- n 维张量,类似于 numpy,但可以在 GPU 上运行
- 用于建立和训练神经网络的自动微分
什么是神经网络?
神经网络是一组算法,大致模仿人脑,用于识别模式。网络是由*似神经元的单个部分构成的,通常称为单元或简称为“神经元”每个单元都有一些加权输入。这些加权输入相加在一起(线性组合),然后通过一个激活函数得到单元的输出。
神经网络中的节点类型:
- 输入单元—向网络提供来自外部世界的信息,统称为“输入层”。这些节点不执行任何计算,它们只是将信息传递给隐藏节点。
- 隐藏单元—这些节点与外界没有任何直接的联系。它们执行计算并将信息从输入节点传输到输出节点。隐藏节点的集合形成了“隐藏层”。虽然前馈网络只有一个输入层和一个输出层,但它可以有零个或多个隐藏层。
- 输出单元-输出节点统称为“输出层”,负责计算和将信息从网络传输到外部世界。
每层包括一个或多个节点。
构建神经网络
PyTorch 提供了一个模块nn
,使得构建网络更加简单。我们将看到如何用784 inputs
、256 hidden units
、10 output units
和softmax output
构建一个神经网络。
from torch import nnclass Network(nn.Module):
def __init__(self):
super().__init__()
# Inputs to hidden layer linear transformation
self.hidden = nn.Linear(784, 256)
# Output layer, 10 units - one for each digit
self.output = nn.Linear(256, 10)
# Define sigmoid activation and softmax output
self.sigmoid = nn.Sigmoid()
self.softmax = nn.Softmax(dim=1)
def forward(self, x):
# Pass the input tensor through each of our operations
x = self.hidden(x)
x = self.sigmoid(x)
x = self.output(x)
x = self.softmax(x)
return x
注:
**softmax**
函数,也称为**softargmax**
或**normalized**
**exponential function**
是一个以 K 实数的向量为输入,并将其归一化为由 K 个概率组成的概率分布的函数。
image from google
让我们一行一行地过一遍。
**class** Network(nn.Module):
在这里,我们继承了nn.Module
。与super().__init__()
结合,这创建了一个跟踪架构的类,并提供了许多有用的方法和属性。当你为你的网络创建一个类时,从nn.Module
继承是强制性的。类本身的名称可以是任何东西。
self.hidden **=** nn.Linear(784, 256)
这一行创建了一个用于线性变换的模块,𝑥𝐖+𝑏xW+b,有 784 个输入和 256 个输出,并将其分配给self.hidden
。该模块自动创建我们将在forward
方法中使用的权重和偏差张量。一旦使用net.hidden.weight
和net.hidden.bias
创建了网络(net
,您就可以访问权重和偏差张量。
self.output **=** nn.Linear(256, 10)
类似地,这创建了另一个具有 256 个输入和 10 个输出的线性转换。
self.sigmoid **=** nn.Sigmoid()
self.softmax **=** nn.Softmax(dim**=**1)
这里我定义了 sigmoid 激活和 softmax 输出的操作。在nn.Softmax(dim=1)
中设置dim=1
计算各列的 softmax。
**def** forward(self, x):
用nn.Module
创建的 PyTorch 网络必须定义一个forward
方法。它接受一个张量x
并通过您在__init__
方法中定义的操作传递它。
x **=** self.hidden(x)
x **=** self.sigmoid(x)
x **=** self.output(x)
x **=** self.softmax(x)
这里,输入张量x
通过每个操作,并重新分配给x
。我们可以看到,输入张量经过隐藏层,然后是 sigmoid 函数,然后是输出层,最后是 softmax 函数。只要操作的输入和输出与您想要构建的网络体系结构相匹配,您在这里给变量取什么名字并不重要。在__init__
方法中定义事物的顺序并不重要,但是您需要在forward
方法中对操作进行正确排序。
# Create the network and look at it's text representation
model = Network()
model
使用构建神经网络**nn.Sequential**
PyTorch 提供了一种方便的方法来构建这样的网络,其中张量通过运算顺序传递,nn.Sequential
( 文档)。用它来构建等效网络:
# Hyperparameters for our network
input_size = 784
hidden_sizes = [128, 64]
output_size = 10# Build a feed-forward network
model = nn.Sequential(nn.Linear(input_size, hidden_sizes[0]),
nn.ReLU(),
nn.Linear(hidden_sizes[0], hidden_sizes[1]),
nn.ReLU(),
nn.Linear(hidden_sizes[1], output_size),
nn.Softmax(dim=1))
print(model)
这里我们的型号和之前一样:
784 input units
、a hidden layer with 128 units
、ReLU activation
、64 unit hidden layer
,再来一个ReLU
,然后是output layer with 10 units
,再来一个softmax output
。
您还可以传入一个OrderedDict
来命名各个层和操作,而不是使用增量整数。注意字典键必须是唯一的,所以每个操作必须有不同的名称。
from collections import OrderedDict
model = nn.Sequential(OrderedDict([
('fc1', nn.Linear(input_size, hidden_sizes[0])),
('relu1', nn.ReLU()),
('fc2', nn.Linear(hidden_sizes[0], hidden_sizes[1])),
('relu2', nn.ReLU()),
('output', nn.Linear(hidden_sizes[1], output_size)),
('softmax', nn.Softmax(dim=1))])) model
现在,您可以通过整数或名称来访问图层
print(model[0])
print(model.fc1)
今天到此为止。接下来我们将训练一个神经网络。你会在这里找到它。
我们随时欢迎您提出任何建设性的批评或反馈。
在喀拉斯建立我们的第一个神经网络
原文:https://towardsdatascience.com/building-our-first-neural-network-in-keras-bdc8abbc17f5?source=collection_archive---------0-----------------------
报名参加我的计算机视觉直播课程:https://bit.ly/cv_coursem
在本文中,我们将使用 keras 框架制作我们的第一个神经网络(ANN)。本教程是深度学习研讨会的一部分。我一更新课程,就会在下面给出链接。这个回购的 Github 链接就是这里的。链接到本教程的 jupyter 笔记本是这里。
索引
- 机器学习和深度学习入门。
- 神经网络简介。
- python 简介。
- 在喀拉斯建立我们的第一个神经网络。< — You are here
- CNN 综合指南。
- 用 CNN 进行图像分类。
在开始之前,我想概述一下如何构建任何深度学习项目。
- 预处理和加载数据- 正如我们已经讨论过的,数据是神经网络工作的关键,我们需要在输入神经网络之前对其进行处理。在这一步中,我们还将可视化数据,这将有助于我们深入了解数据。
- 定义模型- 现在我们需要一个神经网络模型。这意味着我们需要指定神经网络中隐藏层的数量及其大小,即输入和输出的大小。
- 损失和优化器- 现在我们需要根据我们的任务定义损失函数。我们还需要指定优化器来使用学习率和优化器的其他超参数。
- 拟合模型- 这是神经网络的训练步骤。这里我们需要定义我们需要训练神经网络的时期数。
拟合模型后,我们可以对测试数据进行检验,以检查是否存在过拟合的情况。我们可以保存模型的权重并在以后需要时使用它。
数据处理
我们将使用移动价格区间分类器的简单数据。数据集由 20 个特征组成,我们需要预测手机所处的价格范围。这些范围分为 4 类。我们数据集的特征包括
'battery_power', 'blue', 'clock_speed', 'dual_sim', 'fc', 'four_g',
'int_memory', 'm_dep', 'mobile_wt', 'n_cores', 'pc', 'px_height','px_width', 'ram', 'sc_h', 'sc_w', 'talk_time', 'three_g','touch_screen', 'wifi'
在将数据输入我们的神经网络之前,我们需要以特定的方式使用它,所以我们需要相应地处理它。数据的预处理取决于数据的类型。这里我们将讨论如何处理表格数据,在后面的教程中,我们将处理图像数据集。让我们开始编码部分
#Dependencies
import numpy as np
import pandas as pd#dataset import
dataset = pd.read_csv(‘data/train.csv’) #You need to change #directory accordingly
dataset.head(10) #Return 10 rows of data
我们的数据集看起来像这样。
#Changing pandas dataframe to numpy array
X = dataset.iloc[:,:20].values
y = dataset.iloc[:,20:21].values
python 模块中讨论的代码将生成两个数组 X 和 y。X 包含特性,y 包含类。
#Normalizing the data
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X = sc.fit_transform(X)
此步骤用于标准化数据。规范化是一种技术,用于将数组的值更改为通用比例,而不会扭曲值范围的差异。这是一个重要的步骤,您可以通过删除这一步骤来检查我们数据集上的精度差异。这主要是在数据集特性变化很大的情况下需要的,因为在我们的情况下,电池电量的值在 1000 左右,时钟速度小于 3。因此,如果我们将未标准化的数据输入神经网络,每一列的梯度将发生不同的变化,因此学习将会振荡。从这个环节进一步研究。
现在,X 将变为以下形式:
Normalized data:
[-0.90259726 -0.9900495 0.83077942 -1.01918398 -0.76249466 -1.04396559
-1.38064353 0.34073951 1.34924881 -1.10197128 -1.3057501 -1.40894856
-1.14678403 0.39170341 -0.78498329 0.2831028 1.46249332 -1.78686097
-1.00601811 0.98609664]
下一步是对类进行热编码。一种热编码是将整数类转换成二进制值的过程。考虑一个例子,假设我们的数据集中有 3 个类,即 1、2 和 3。现在我们不能直接把它输入神经网络,所以我们把它转换成:
1- 1 0 0
2- 0 1 0
3- 0 0 1
现在这个类有了一个唯一的二进制值。形成的新数组的形状为(n,类的数量),其中 n 是数据集中样本的数量。我们可以使用 sklearn 的简单函数来实现这一点:
from sklearn.preprocessing import OneHotEncoder
ohe = OneHotEncoder()
y = ohe.fit_transform(y).toarray()
我们的数据集有 4 个类,因此我们的新标签数组将如下所示:
One hot encoded array:
[[0\. 1\. 0\. 0.]
[0\. 0\. 1\. 0.]
[0\. 0\. 1\. 0.]
[0\. 0\. 1\. 0.]
[0\. 1\. 0\. 0.]]
现在我们的数据集已经处理完毕,可以输入神经网络了。
一般来说,最好将数据拆分为训练数据和测试数据。训练数据是我们用来训练神经网络的数据。测试数据用于检查我们训练好的神经网络。这个数据对于我们的神经网络来说是全新的,如果神经网络在这个数据集上表现良好,则表明没有过度拟合。点击阅读更多关于这个的信息。
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size = 0.1)
这将把我们的数据集分为训练和测试。训练数据将有 90%的样本,测试数据将有 10%的样本。这是由 test_size 参数指定的。
现在我们完成了无聊的部分,让我们建立一个神经网络。
构建神经网络
Keras 是一个构建神经网络的简单工具。它是一个基于 tensorflow、theano 或 cntk 后端的高级框架。
在我们的数据集中,输入有 20 个值,输出有 4 个值。因此输入和输出层分别是 20 和 4 维。
#Dependencies
import keras
from keras.models import Sequential
from keras.layers import Dense# Neural network
model = Sequential()
model.add(Dense(16, input_dim=20, activation=’relu’))
model.add(Dense(12, activation=’relu’))
model.add(Dense(4, activation=’softmax’))
在我们的神经网络中,我们使用了 16 维和 12 维的两个隐藏层。
现在我将逐行解释代码。
Sequential 向 keras 指定我们正在按顺序创建模型,我们添加的每一层的输出都是我们指定的下一层的输入。
model.add 用来给我们的神经网络增加一层。我们需要指定我们想要的图层类型作为参数。密集用于指定全连通层。Dense 的参数是输出维度,在第一种情况下是 16,输入维度是 20,在这种情况下要使用的激活函数是 relu。第二层是类似的,我们不需要指定输入维度,因为我们已经将模型定义为连续的,所以 keras 将自动认为输入维度与最后一层的输出相同,即 16。在第三层(输出层)中,输出维度是 4(类的数量)。正如我们之前所讨论的,输出层采用不同的激活函数,对于多类分类的情况,它是 softmax。
现在我们需要指定损失函数和优化器。这是使用 keras 中的编译函数完成的。
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
这里的损失是前面讨论过的交叉熵损失。Categorical _ crossentropy 指定我们有多个类。优化者是亚当。度量用于指定我们想要判断神经网络性能的方式。这里我们已经精确地指定了它。
现在我们已经完成了神经网络的构建,我们将对其进行训练。
培训模式
在 keras 中,训练步骤很简单。用 model.fit 来训练它。
history = model.fit(X_train, y_train, epochs=100, batch_size=64)
这里我们需要指定输入数据-> X_train,标签-> y_train,历元数(迭代)和批量大小。它返回模型训练的历史。历史由每个时期后的模型精度和损失组成。我们稍后将会可视化它。
通常,数据集非常大,我们无法一次适应完整的数据,所以我们使用批量大小。这将我们的数据分成多个批,每个批的大小等于 batch_size。现在,只有这个数量的样本将被加载到存储器中并被处理。一旦我们完成了一个批处理,它将从内存中被刷新,下一个批处理将被处理。
现在我们已经开始训练我们的神经网络。
Epoch 1/100
1600/1600 [==============================] - 1s 600us/step - loss: 1.3835 - acc: 0.3019
Epoch 2/100
1600/1600 [==============================] - 0s 60us/step - loss: 1.3401 - acc: 0.3369
Epoch 3/100
1600/1600 [==============================] - 0s 72us/step - loss: 1.2986 - acc: 0.3756
Epoch 4/100
1600/1600 [==============================] - 0s 63us/step - loss: 1.2525 - acc: 0.4206
Epoch 5/100
1600/1600 [==============================] - 0s 62us/step - loss: 1.1982 - acc: 0.4675
.
.
.
Epoch 97/100
1600/1600 [==============================] - 0s 55us/step - loss: 0.0400 - acc: 0.9937
Epoch 98/100
1600/1600 [==============================] - 0s 62us/step - loss: 0.0390 - acc: 0.9950
Epoch 99/100
1600/1600 [==============================] - 0s 57us/step - loss: 0.0390 - acc: 0.9937
Epoch 100/100
1600/1600 [==============================] - 0s 60us/step - loss: 0.0380 - acc: 0.9950
训练大约需要一分钟。并且在 100 个时期之后,神经网络将被训练。训练准确率达到 99.5 %,从而训练出我们的模型。
现在,我们可以根据测试数据检查模型的性能:
y_pred = model.predict(X_test)
#Converting predictions to label
pred = list()
for i in range(len(y_pred)):
pred.append(np.argmax(y_pred[i]))
#Converting one hot encoded test label to label
test = list()
for i in range(len(y_test)):
test.append(np.argmax(y_test[i]))
这个步骤是热编码过程的逆过程。我们将使用这一步得到整数标签。我们可以使用一个简单的方法 keras,model.predict()对测试数据进行预测。它将测试数据作为输入,并将预测输出作为 softmax 返回。
from sklearn.metrics import accuracy_score
a = accuracy_score(pred,test)
print('Accuracy is:', a*100)
我们得到了 93.5%的准确率。
我们可以使用测试数据作为验证数据,并可以在每个时期后检查准确性。这将使我们了解仅在训练时的过度适应,我们可以在所有时期完成之前采取措施。我们可以通过将拟合函数更改为:
history = model.fit(X_train, y_train,validation_data = (X_test,y_test), epochs=100, batch_size=64)
现在,训练步骤输出也将包含验证准确性。
Train on 1600 samples, validate on 400 samples
Epoch 1/100
1600/1600 [==============================] - 1s 823us/step - loss: 1.4378 - acc: 0.2406 - val_loss: 1.4118 - val_acc: 0.2875
Epoch 2/100
1600/1600 [==============================] - 0s 67us/step - loss: 1.3852 - acc: 0.2825 - val_loss: 1.3713 - val_acc: 0.3175
Epoch 3/100
1600/1600 [==============================] - ETA: 0s - loss: 1.3474 - acc: 0.326 - 0s 50us/step - loss: 1.3459 - acc: 0.3231 - val_loss: 1.3349 - val_acc: 0.3650
Epoch 4/100
1600/1600 [==============================] - 0s 56us/step - loss: 1.3078 - acc: 0.3700 - val_loss: 1.2916 - val_acc: 0.4225
Epoch 5/100
1600/1600 [==============================] - 0s 74us/step - loss: 1.2600 - acc: 0.4094 - val_loss: 1.2381 - val_acc: 0.4575
.
.
.
.
Epoch 95/100
1600/1600 [==============================] - 0s 37us/step - loss: 0.0615 - acc: 0.9869 - val_loss: 0.1798 - val_acc: 0.9250
Epoch 96/100
1600/1600 [==============================] - 0s 43us/step - loss: 0.0611 - acc: 0.9850 - val_loss: 0.1812 - val_acc: 0.9225
Epoch 97/100
1600/1600 [==============================] - 0s 45us/step - loss: 0.0595 - acc: 0.9894 - val_loss: 0.1813 - val_acc: 0.9275
Epoch 98/100
1600/1600 [==============================] - 0s 44us/step - loss: 0.0592 - acc: 0.9869 - val_loss: 0.1766 - val_acc: 0.9275
Epoch 99/100
1600/1600 [==============================] - 0s 43us/step - loss: 0.0575 - acc: 0.9894 - val_loss: 0.1849 - val_acc: 0.9275
Epoch 100/100
1600/1600 [==============================] - 0s 38us/step - loss: 0.0574 - acc: 0.9869 - val_loss: 0.1821 - val_acc: 0.9275
我们的模型运行良好。现在,我们将可视化培训和验证损失和准确性。
import matplotlib.pyplot as plt
plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.title('Model accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epoch')
plt.legend(['Train', 'Test'], loc='upper left')
plt.show()
plt.plot(history.history['loss']) plt.plot(history.history['val_loss'])
plt.title('Model loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['Train', 'Test'], loc='upper left')
plt.show()
在下一章,我们将讨论用于图像数据的卷积神经网络(CNN)。如有任何疑问或我做错了什么,请评论。
和*…
在 Tableau 中构建交互式仪表盘—员工流动率
原文:https://towardsdatascience.com/building-out-interactive-dashboards-in-tableau-employee-turnover-c664d9e2de76?source=collection_archive---------26-----------------------
Tableau 是一个图形化的商业智能和分析*台,使人们能够快速连接到数据库,并构建图表、图形、地图和交互式仪表板。它功能强大,易于使用,而且有趣!
在这篇文章中,我将分享一个我围绕一组虚构的美国人口统计和员工流动数据创建的项目。
我们知道,员工流动是企业最大的开支之一:认真点。
这个项目的资料可以在这里下载。如果你想知道图表是如何构建的,工作簿可以从下载。你只需要 Tableau Public ,工作簿,和数据集。
现在,事不宜迟,我将深入我的分析。
设置
我使用 core_dataset.csv 文件,一旦我将它转换为。xlsx,以便 Tableau 可以加载它,我开始了。
首先,我检查了数据,看看哪些变量是可用的,它看起来像什么,以及我可能想进一步研究什么。
Glance at the data set (not all columns are visible here)
分析和图表
我知道我想看看性别和种族,看看它们是如何与工资率、部门和工作相关地分布的。我还想看看这些变量与离职率和员工离职原因的关系。所以首先,我需要看看这些的总体分布。
Demographics of the employees data set: count by sex and race
大多数雇员是白人女性,第二大群体是白人男性。第二个最普遍的种族是黑人雇员,第三个最普遍的种族是亚裔雇员。
为了理解工资率的差异,我从观察数据集中各州的*均工资率如何不同开始。
Average pay rate by state
然后,我按照种族和部门查看了更细致的薪酬水*。
Pay by race and department, colored to the same scale as the map above
从这张表中我们可以看到一些东西:
- 只有白人雇员在行政办公室,这是工资最高的职位。
- 西班牙裔员工的工资水*相对较高,但只在两个部门有代表。他们是 IT/IS 部门薪酬最高的群体。这是*均工资率,我在之前的条形图中看到,样本中很少有西班牙裔员工。因此,这不是一个非常准确的*均值。
- 美国印第安人或阿拉斯加土著雇员的代表性同样不足。这在之前的条形图中也可以看到。
- 销售、行政办公室、软件工程、IT/IS 是工资最高的部门。
然后,我研究了员工流动率,试图了解员工离开公司的原因。我很自然地专注于自愿的原因。
Employment status and reason for voluntarily quitting by race
看着图表,我发现大多数员工不管种族都跳槽了。第二个最常见的原因是工作中的不愉快。第三个最常见的原因是挣更高的工资。
为了提高员工保留率,我会根据这些数据推荐以下实施方案:
- 进行广泛的离职调查/面谈,以了解公司如何改进,使人们不那么想离开去寻找其他机会(追溯方法)。
- 在员工想要离开之前进行调查,旨在了解快乐、满意度等等。要考虑的领域可能包括文化准则、事件和社交、绩效评估等(预防性方法)。
- 周转成本是巨大的。考虑给员工更多的钱来留住他们应该不是不可能的(预防性方法)。
公司的多样性对于促进文化理解和思想的多样性也很重要,而且已经证明能够催化创新。考虑到这一点,我按种族检查了员工来源,以了解这些公司在哪里能够为其员工队伍找到多样化的人才。
大多数多元化人才来自多元化招聘会。具有最多员工来源的箱是推荐。这是有道理的,也是常见的。这也是雇佣最便宜的方式。
可以根据不同渠道过去的表现来集中精力,就像市场营销中的归因模型如何帮助公司决定在哪里投资广告支出。
包扎
正如您在本文中看到的,Tableau 是一种对数据进行 EDA 并构建仪表板的快捷方式,同事可以根据自己的分析需求轻松使用和修改仪表板。这些都是在他们的免费版中完成的!
完整的工作簿在我的 Tableau 个人资料这里。
在我的 GitHub 上查看更多项目。
如果你学到了新的东西,并且想把它送给下一个学习者,考虑捐赠你觉得合适的任何数量,谢谢!
感谢阅读和快乐编码!
奢侈的生活
用有限的数据构建分析和数据湖功能
原文:https://towardsdatascience.com/building-out-metrics-and-data-lake-with-limited-data-6c98ea2e8b2d?source=collection_archive---------21-----------------------
没有什么是完全独立存在的。每件事都与其他事相关。佛
许多组织,尤其是初创公司,遇到的一个非常普遍的问题是很少或没有数据。不幸的是,盲目操作和没有数据洞察力不再是一个选项。用数据操作就是简单的表桩;所有公司都利用数据来制定战略转变和日常决策。幸运的是,组织可以通过许多途径来获取更多数据。
建设数据管道的成本
一个常见的途径是尝试提取和输送每一个可能的数据集,无论是通过内部还是第三方来源,并寻找可能支持叙事的模式。这通常包括将所有东西放入湖中,对您的数据执行数据发现,然后使用相关数据集来构建仪表板和分析工具。
或者,相反的方向是预先定义所需的数据,并且只检索那些数据元素。这两种解决方案都有利弊。如果您提前将所有数据检索到您的数据湖中,那么当您想要快速构建和添加指标和报告时,需要做的工作会更少。但是,如果以按需方式检索数据,添加新的数据点将更加困难和耗时。
在这篇文章中,我主张预先清晰而周到地定义您的业务案例,以避免在构建不必要的数据管道上投入大量资金。这样做有几个原因。首先,这是一种灵活的方法,允许分阶段构建指标和分析,这意味着更快地交付数据产品。其次,构建数据管道比我们想象的要复杂。
引入每一个可用的数据点是昂贵的。对于数据交付来说,有一个计划谬误是很常见的,因为人们倾向于错误地假设事情不会出错,并且低估了集成数据的难度。在估算构建数据管道的成本时,经常会忽略数据质量清理、创建数据目录、集成数据集以及维护持续运行的管道的成本。
提高数据湖/分析能力的过程
开始自上而下
解决这个问题的方法是从上到下开始。不要问我有什么可用的数据,如何从中获取最大的价值,而是问自己什么问题对业务最有意义,如何量化它。
这种方法类似于设计驱动开发的数据版本(我们将称之为度量驱动开发)。在设计驱动开发中,模型和/或用户界面是在开发软件之前建立的。这种方法迫使开发人员和业务用户更加注意他们引入的是什么类型的数据,并询问为什么这个特定的数据集有价值。它还减少了构建未充分利用的数据管道所花费的时间,使团队能够将精力集中在关键的数据管道上。
一个组织通常有 10-15 个组织指标,这些指标对于衡量其业务的成功和日常运营效率至关重要。组织指标,也称为 KPI 或关键绩效指标,是一个单一的数值或一组数值,可以随着时间的推移进行跟踪,以确定业务的总体方向。使用组织指标作为您需要引入分析的关键数据元素的指南。
我已经拥有了什么?
接下来,查看您已经可以访问的数据清单,问问自己如何使用该数据集来构建这些指标。
以最小可行产品的心态来建立这些指标。可用于估算 KPI 指标的最少可用数据量是多少?
使用这些数据点构建一个简化的指标。然后回到绘图板,头脑风暴如何改进这个指标。真正重要的是什么?什么是绒毛?例如,采用一个无处不在的指标,比如日浏览量(某一天有多少用户浏览你的网站),并使它成为你的业务的个人指标。让业务的战略愿景和目标驱动您的度量标准的定义和构建。
我能补充什么?
接下来,引入什么样的数据集和数据点对构建更强大、更定制的组织指标最有价值。这里的目标是优化运营指标/KPI 的准确性。这甚至可能需要将指标分成多个子指标。例如,收入可以按照业务线、地域等进行划分..
一旦定义了这一点,下一步就是构建数据管道,将数据送入数据湖和报告层。这可能包括构建新的管道以从前端收集额外的数据点,以及从第三方数据源购买/收集数据。
同样重要的是要注意,某种程度的数据发现可能是必要的。然而,数据发现并不要求将数据通过管道传输到数据湖中。它可以简单到下载第三方 CSV 并用 SQL 或 Pandas 进行分析。
继续完善你的指标
最后,这个过程要细化。重新审视您的指标/KPI 并质疑它们从业务角度来看是否有意义以及如何改进是很重要的。这应该是您进一步扩大收集的数据并将其带入公司的驱动力。
深入探究一个真实的例子
让我们深入一个从零开始构建组织 KPI 的具体示例,以更深入地说明这种方法。
在本例中,我们是一家电子商务时装零售商。我们的目标是增加销售数量,创造更多收入,发展我们的业务。因此,这家公司关心大约 10 个 KPI。这包括日常销售数量、新客户数量以及运营/物流成本的降低。出于这个例子的目的,我们真正关心的是转化率。转化率是查看产品或与在线商店互动并实际购买的用户数量。
转化率是一个直接的指标,表明我们的网上商店设计得有多好,以及我们的产品/植入式广告有多吸引人。低转换率可能表明设计不良的网上商店或劣质产品。
客户转化率-使用现有数据
我们从小处着手,询问有哪些数据可用。我们知道顾客购买了什么,我们从谷歌分析中知道有多少顾客浏览了一个页面。这为我们提供了一个简化的每日客户转换公式,即:
Customer Conversion = (Customer who made a purchase /Customer views) per day
然而,这是对客户转化的一种极端简单化的解释,没有告诉我们为什么客户不转化,也没有针对我们最感兴趣的客户。让我们使用我们的商业智能工具构建这个简化的指标,从湖中提取这些数据点。
为了改进这一指标,我们需要收集第三方数据源或在内部收集更多数据。然而,在我们这样做之前,我们应该仔细确定我们计划如何改进这个指标。
我们可以做很多事情来决定我们的页面在视觉上是否有效。一个计划是 A/B 测试该页面的两个版本,随机分配客户到任一页面,并跟踪两个版本的转换。此外,我们可能关心的另一个数据点是在页面上花费大量时间的用户,这意味着他们关心产品/商店并感兴趣,但不知何故没有足够的兴趣进行购买。
建设额外的管道以改善关键绩效指标
在这种情况下,我们希望知道用户在点击购买之前在页面上停留了多长时间,并且我们希望对在页面上停留了至少 30 秒的用户给予更多的重视或权重。
为了找到这些信息,我们需要收集用户在页面上花费时间的数据。具体来说,这意味着添加前端 javascript 代码,以根据 cookies 识别用户并跟踪他们在一个页面上花费的时间,然后将这些数据发送到日志,这些数据将被收集、提取并存储在数据湖中,并作为数据点呈现给商业智能工具。这是前端、后端和数据团队的共同努力。
首先,让我们确认这是一个对我们有用的数据点。让我们捕获这些数据的一个样本,比如说一天,将它添加到我们的日志中。然后,我们将手动解析日志,并在 excel 中创建指标。然后,让我们根据这一指标来确定这是否提供了有价值的见解。如果是这样,让我们把它建成一个完整的数据管道。
在构建数据管道时,需要在更彻底的数据质量检查和构建更快但不太健壮的管道之间进行权衡。如果这是一个将为公司范围的指标提供信息的数据点,那么添加彻底的检查以确保数据正确地从源移动到目标是很重要的。这意味着确保没有重复数据集、数据损坏或数据丢失。
同时,我们不确定这个数据点是否会持续。在不牺牲数据完整性的情况下,简化数据管道,以加快迭代速度。当一个数据点需要更长的时间,比如六个月,并且作为一个需求保持不变时,那么,在这一点上,巩固数据管道以变得更加健壮和可靠。如果你采用这种方法,要非常注意技术债务。
**Modified Customer Conversion** = (Customers who made a purchase/ Customers who viewed page greater than 30 seconds) per day
第三方数据管道
接下来,我们希望锁定符合我们特定人口统计标准的客户。我们的服装系列是专为中上阶层的成年人设计的。因此,我们希望增加特定年龄和收入水*的客户的权重。这不是我们可以在内部收集的数据。因此,我们需要从第三方来源购买(如果不容易通过开源数据获得)。
有很多第三方数据。我们需要缩小哪些数据点对改进指标至关重要,然后找到该数据点的最佳提供者。在这种情况下,我可以从 Equifax 购买这些数据。这将是一笔昂贵的重复购买。只有当他们清楚需要这些数据来增强他们的运营指标时,才应该购买。此外,人们仍然需要构建管道来接收这些第三方数据,并集成到他们更广泛的数据生态系统中,这既耗费资源又耗费时间。
如果可能的话,获取这些数据的样本(或者模型,如果没有的话),并首先确定这些数据在添加到您现有的指标中时是否真正有价值。一旦确定了这一点,就要构建您的数据管道来包含这一指标。
为第三方数据源构建管道同样耗费时间和资源,因为需要检查数据的质量。有时,第三方来源对数据源来说更具挑战性,因为在如何收集数据或数据的有效性方面可能不透明。在购买第三方数据之前,应该仔细评估第三方数据来源,明确如何使用这些数据。
**Modified Customer Conversion** = Customers who made a purchase/( Customers who view greater than 30 seconds and are between 18-30 with income > 40k) per day
重新评估您的指标
最后,定期重新审视你的公司指标并重新定义它们是很重要的。继续询问您可以收集或引入哪些数据点来改进您的指标。继续询问你的公司指标是否有意义。快速构建,经常失败,继续学习是在数据工作中取得成功的关键!
— — — — — — — — — — — — — — — — — — — — — — — — — —
特别感谢 Linda Yan 对战略思考过程的投入。琳达是 Blackboard Insurance 的现任战略主管,也是麦肯锡公司的前顾问。
在 R 中构建自己的逻辑分类器[逻辑三部曲,第 2 部分]
原文:https://towardsdatascience.com/building-own-logistic-classifier-in-r-logistic-trilogy-part-2-a36be209d2c?source=collection_archive---------25-----------------------
如果有人从为数据科学项目或统计项目开发自己的代码中获得了巨大的乐趣,那么这就是适合他/她的文章。
你可能在 R,
glm(y~x,data,family=binomial)中用过或者学过 glm 函数。 对提供的数据进行逻辑回归拟合,取 y 为响应变量,x 为预测变量。但你有没有想过背后到底发生了什么?如果我们能理解这一点,我们能在 R 中为逻辑构建我们自己的函数吗?让我们一起试试。只有一个条件,我们将限制自己只进行二元分类。
开发一个模型首先需要什么?数据,分析中最重要的部分。我们需要一个可以是 1 或 0 的响应变量 Y 和 p 个预测变量 X1,X2,…,Xp。假设观察总数为 n。每个模型都有一些假设,
一般来说,假设是-
- Yi 是独立的,并且每个 Yi 遵循具有参数 pi 的伯努利分布
- 预测因子 X1,X2,…Xp 是不相关的
在逻辑框架下,假设是 pi=
Logistic Inverse link function (CDF of standard Logistic Distribution)
那么可能性函数是-
因此对数可能性是-
经过简化,它可以归结为以下内容(我不包括这些步骤,因为键入方程仍然是一项单调乏味的任务😅)
其中β是维数为(p+1)×1 的参数向量,xi 是 1×(p+1)阶的第 I 个观测向量。那就是Xi =【1x1i x2i x3i…xpi】。 现在我们需要训练的模型无非是根据手头的数据估计未知的参数。虽然有几种估计方法,但最大似然估计因其简单而被广泛使用。参数的最大似然是
让我们找到对数似然函数相对于参数向量的一阶导数,
β向量的极大似然估计必须满足条件 D=0。是不是很美?
易-皮只不过是用皮预测易所犯的错误。它表明误差和预测值是正交的。在简单线性回归的情况下,这不是第一正规方程所说的吗?
我们使用逻辑回归,因为线性回归模型的假设在分类响应变量的情况下不满足。但是我们又回到了线性模型。这就是回归理论的妙处。真是太神奇了。
但不幸的是,不那么神奇的是,上述方程没有封闭形式的解。😥😥😥😥😥
我们需要一些优化技术。梯度下降和牛顿-拉夫森法可能是应用最广泛的。这里我坚持使用牛顿-拉夫森方法(这样我就不需要调整学习速度)。
我不打算深入研究牛顿-拉夫逊方法。粗略地说,它通过如下迭代过程找到函数 f(x)的根
并且当两个连续步骤的输出之间的差异变得太小时,我们停止。在我们的情况下,我们需要找到对数似然函数的一阶导数的根。
一阶导数我们已经找到了,二阶导数是
它拥有另一种美。这一项总是负的,或者就矩阵而言,它总是负定矩阵。Logit 模型的似然函数满足全局凹性。D=0 的解总会使可能性最大化。
由于我们要处理不止一个预测值,让我们找出上述量的矩阵对应项,
在哪里,
- x 是 N 阶 x (p+1)预测值的矩阵,第一列全为 1。
- y 是响应变量的列向量。
- p-hat 是更新概率 P[Y=1| X=x]的列向量。
- p 是 N×N 对角矩阵,第 I 个对角元素是 pi(1-pi)。
- n 表示第 n 次迭代。
我们的理论背景已经准备好了,现在是编码的时候了。我在这里用 R。
#at first lets write a function to find the pi values for given predictors and betas#x is the matrix of predictors, param is the vector of betas**pi_finder=function(x,param){**
**pi=array(dim=1)** #initializing an array
**for(i in 1:nrow(x)){**
**val=0** #temporary variable
**for(j in 1:ncol(x)){
val=val+x[i,j]*param[j]** #x[i,j]=ith value of jth predictor
**}
pi[i]=1/(1+exp(-val))
}
return(pi)** # it will return the updated pi
**}**#now lets write a function to construct the P matrix
#as input we only need the pi values**P_matrix_finder=function(pi){**
**P=diag(pi*(1-pi))** #diagonal matrix with ith diagonal=pi(1-pi)
**return(P)** #returning the matrix
**}**#and finally the logistic function equivalent to glm.
# as input it will take the matrix of predictors, response variable and the precision for the convergence of Newton Raphson method.**logistic_own=function(predictor,response,precision){**
**predictor_new=as.matrix(predictor)** # just to be on the safe side
**distinct=sort(unique(as.numeric(response)),decreasing=FALSE)
response_new=array(dim=1)
for(i in 1:length(response)){
if(response[i]==distinct[1])
response_new[i]=0
else
response_new[i]=1**
**}** #in case response is in factor (not numeric)
**constant=rep(1:length(response_new))** #the first column of X matrix
**X_matrix=cbind(constant,predictor_new)**
**beta=rep(0,ncol(X_matrix))** #initializing beta to 0 vector
**dif=100** #since do while loop does not exist in R :(
**while(dif>precision){
pi=pi_finder(X_matrix,beta)
P=P_matrix_finder(pi)
updated=solve(t(X_matrix)%*%P%*%X_matrix)%*%t(X_matrix)%*%(response_new-pi)**
**beta=beta+updated** #updating beta
**dif=sum(updated^2)** #euclidean distance between old and new beta
**}
return(beta)
}**
模型培训框架完成。我一直保持简单。多类分类会失败。
我们要不要在数据集上试一试,并与 glm 函数的结果进行比较?我正在使用著名的虹膜数据集。
**library(datasets)
iris=iris
iris_new=iris[which(iris$Species!="setosa"),]** #taking only 2 outputs
数据看起来像这样:
#train test split. I am considering 75:25 ratio
**samples=sample(1:nrow(iris_new),size=nrow(iris_new)*0.75,replace=F)**
**iris_new_train=iris_new[samples,]** #training data
**iris_new_test=iris_new[-samples,]** #test data#model training using glm function
**inbuilt=glm(Species~Sepal.Length+Sepal.Width+Petal.Length+Petal.Width,data=iris_new_train,family=binomial(link="logit"))
inbuilt$coefficients**
输出是
让我们试试我们的功能,
**model=own_logistic(iris_new_train[,1:4],iris_new_train[,5],0.000000001)
model**
答对了。!!!!!!!!!!😀😀😀
但是工作还没有完成,我们仍然需要测试我们的模型。R 中有一个内置函数 predict ,它给出了测试数据点的预测概率。我们能开发类似的东西吗?
我们当然可以。我们已经有了训练好的系数。只需要测试数据集。
#takes our model output and test data predictors as inputs
**fitted=function(model,test_data_predictors){
predictors=as.matrix(test_data_predictors)
constant=rep(1,nrow(predictors))
X_matrix=cbind(constant,predictors)
pred=pi_finder(X_matrix,model)** # the predicted probabilities
**return(pred)
}**
在 R 中使用内置函数:
让我们看看我们的函数给出了什么:
这有点笨拙,让我们把它们放在一起:
**R_inbuilt_pred=predict(inbuilt,iris_new_test[,1:4],type="response")
Our_own_pred=fitted(model,iris_new_test[,1:4])
cbind(R_inbuilt_pred,Our_own_pred)**
恭喜你!!!!!你已经学会了如何为二元分类创建自己的逻辑分类器。
编写自己的代码是一个很好的实践。这样你会变得更有创造力,并且对不同的最大似然算法的背景理论有很强的把握。
如果你需要通过创造力来理解逻辑回归背后的思想,你可以去看看我之前的文章 逻辑回归——源自直觉【逻辑三部曲,第 1 部分】 。你自己将从纯粹的直觉和逻辑中推导出逻辑回归。
[## 逻辑回归——源自直觉
让我们通过一个故事从头开始推导逻辑回归。我希望这将是有趣和好玩的…
towardsdatascience.com](/logistic-regression-derived-from-intuition-d1211fc09b10)
创造力和创新在任何领域都非常重要。它会把你和其他人分开。最重要的是,数据科学家需要有创造力。
如果你不相信,或者有任何疑问或建议,请在评论区提问,或者通过我的 LinkedIn 个人资料联系我。
[## SOUMALYA NANDI -联合健康组织(L2)助理数据科学家| LinkedIn
查看 SOUMALYA NANDI 在全球最大的职业社区 LinkedIn 上的个人资料。SOUMALYA 有 4 份工作列在…
www.linkedin.com](https://www.linkedin.com/in/soumalya-nandi-95176569/)
在 Julia 中用车床 0.0.7 构建管道(不稳定)
原文:https://towardsdatascience.com/building-pipelines-with-lathe-0-0-7-unstable-in-julia-f7ba1850bde3?source=collection_archive---------36-----------------------
数据科学的很大一部分是数据科学的一个子集,称为数据工程。数据工程(DE)涉及各种格式的管道、管理和端点数据。好消息是,有了车床 0.0.7,我们可以非常容易地设计一个模型,并用管道进行预测。这个基本版本将会有进一步的改进。但就目前而言,它肯定会是一个非常有用的工具,而且说实话,它是多么容易做到令人难以置信。我期待着进一步扩大这个一揽子计划。
今天,我将向大家展示 Julia、Lathe、JLD2 和 Genie 在管道建设领域的成就。
笔记本
加载数据
为了训练一个模型,我们需要数据。我在 Kaggle 上发现了这个很酷的数据集,所以我决定尝试一下。现在我们有了一个数据集,我们可以把它读入 Julia:
using CSV
df = CSV.read("Summary of Weather.csv")
快速浏览之后,我选择了三个我认为容易追踪和理解的不同特征。首先,我决定将每个日期戳限定为带有日期和数据框的年份:
using DataFrames
using Dates
df.Date = [i = DateTime(i) for i in df.Date]
df.Date = [i = year(i) for i in df.Date]
然后提取我提到的那些特征:
df = DataFrame(:Date => df.Date,:Precipitation => df.Precip,:Temp => df.MeanTemp)
除了其他特性,这些特性实际上是相对干净的,没有丢失值。现在我们已经有了三个特性,但是仍然不知道应该为目标选择什么,我们可能应该做一些统计测试!虽然这对于像多元线性回归这样的模型来说并不重要,但是我们还没有在车床上实现它。
我们可以用 Lathe.stats 做一些快速的 f 检验!
通过使用过滤器,我们可以在 Julia 中基于带有掩码的条件来分离我们的数据!方法,或者通过在数组上循环。
high_dfy = df[(df[:Date].>=1944),:]
执行我们的 f 检验:
using Lathe.stats: f_test
f_test(high_dfy.Temp,df.Temp)0.43963490045765957
不幸的是,我们必须接受这个零。
我决定使用这个特性,因为我并不真的像演示如何做那样追求准确性,所以接下来我使用 Lathe.preprocess 来测试 splitted。
using Lathe.preprocess: TrainTestSplit
train,test = TrainTestSplit(df)
在我看来,这是设定您的功能和目标的最佳方式:
target = :Temp
feature = :Date
trainX = train[feature]
trainy = train[target]
testX = train[feature]
testy = train[target]
对于这个例子,我选择了带有标准标量的线性最小二乘回归,不是为了太简单,而是为了说明问题:
using Lathe.models: LinearLeastSquare
using Lathe.preprocess: StandardScalar
现在我们必须将标准标量应用于 X:
trainX = StandardScalar(trainX)
现在,我们可以快速构建我们的模型:
model = LinearLeastSquare(StandardScalar(trainX),trainy,:REG)
请注意:REG 符号!
我们可以,如果我们在用一个更现实的模型工作(这里没有足够的时间进行线性回归,大约 4 年可以更好地进行分类),我想验证它。假设我们测试了分裂训练,我们应该继续验证它。
using Lathe.models: predict
y_pred = predict(model,StandardScalar(testX))using Lathe.validate: r2,mae
我想指出的是,如果我们聪明地使用代码,我们可以用 4 行代码预测测试集,
包括进口
using Lathe.models: LinearLeastSquare, predict
using Lathe.preprocess: StandardScalar
model = LinearLeastSquare(StandardScalar(train.Year),train.Temp,:REG)
y_pred = predict(model,test.Year)
现在我们有了模型,我们如何在管道中实现标准标量和模型。
using Lathe.pipelines: Pipeline,pippredict
pipe = Pipeline([StandardScalar],model)
注意:将来,车床.管道将合并到车床.模型中,车床. nlp 也将合并到车床.预处理中。
现在我们可以使用 pippredict 方法进行预测,但在未来,它将只是来自车床模型的预测方法。
pippredict(pipe,testy)
现在我们可以使用 JLD2 来用宏序列化我们的结构。
using JLD2
[@save](http://twitter.com/save) "algorithm.jld2" pipe
我们可以像这样重新加载它:
[@load](http://twitter.com/load) "algorithm.jld2"
该结构将被添加到局部变量中,您可以再次执行以下操作:
pippredict(pipe,testy)
开发我们的管道
不幸的是,Julia 目前受到其软件包基础的限制,尽管它确实有 Pycall。我们唯一的本地 Julia 选项是 Genie。好消息是:精灵是相当可怕的!
实际上有一个超级简单的方法可以完全通过管理员命令来完成。像往常一样,首先我们需要进入我们的终端/SSH 客户端,并通过 SSH 连接到我们的服务器。
ssh emmett@----------
我也将通过 nautilus 传输 algorithm.jld2 文件。我的文件最终是 5.5 kb,因为 JLD2 实际上是一个非常令人印象深刻的压缩算法。
现在,我们将使用 Julia 在服务器中快速创建管道:
sudo mkdir /var/www/--------
如果您没有安装 julia,请获取:
sudo dnf install julia
然后在你的终端中输入“朱丽亚”进入朱丽亚 press,然后按],这将带你进入 Pkg REPL。添加精灵:
- 添加“精灵”
现在用退格键离开 pkg repl,用 ctrl 或 command + D 离开 repl
现在我们要配置 NGINX 并获得一个精灵服务器设置。我们需要制作一个 NGINX 配置文件,将网站指向一个套接字端口,以便在其上执行代码。在这一点上,你将取代--用你的 IP/域名。
server {
listen 80;
server_name -----------;location / {
proxy_pass [http://127.0.0.1:8000](http://127.0.0.1:8000);
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
配置完 NGINX 之后,我们可以继续测试我们的配置。导航回我们之前创建的目录,并放入我们的 NGINX 配置中
cd /var/www/---------
您的算法应该包含在该文件夹中。现在,我们可以在终端内部使用所有文件。
route("/") do
[@load](http://twitter.com/load) "algorithm.jld2"
year = haskey([@params](http://twitter.com/params), :year)
y_pred = pippredict(pipe,year)
return(y_pred)
end
这是我做的一个:params 宏允许你基于符号获取参数,类似 Flask 中的 request.args()。
现在我们只需输入
向上()
并导航到我们的 NGINX 配置的 IP,如果您没有为此破例,您应该会得到一个空返回,但如果您输入一年,例如我的:
[http://45.56.119.8/?year=1955](http://45.56.119.8/?year=1955)
(不确定该链接将存在多长时间)
但是还有一个大问题。我们的服务器将停止,如果我们退出这个朱莉娅 REPL,所以你必须保持这个终端永远开放。
开个玩笑…
我们将不得不创建一个真正的精灵应用程序来为我们做计算。首先,把你的工作目录转到我们用 NGINX 提供的 www 文件夹。
cd /var/www/-------
现在进入朱莉娅·REPL,加载精灵并运行Genie**.**newapp_webservice() like so:
julia
using Genie
Genie**.**newapp_webservice("app")
这将创建几个目录,但很可能在一个全新的文件夹中,该文件夹名为“无论您如何命名您的应用程序”,因此我们可以使用以下内容将其上移:
mv app/* .
rmdir app
现在用 nano 制作一个名为 Project.toml 的新文件。
nano Project.toml
注意:没有 Project.toml 文件,精灵不会启动
接下来,我们需要依赖 UUIDs。要获得这些,我们必须进入该项目的 github 页面,并像这样构造结果:
name = "WWPipe"
authors = ["emmett [emmett@emmettboudreau.com](mailto:emmett@emmettboudreau.com)"][deps]
JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819"
Lathe = "38d8eb38-e7b1-11e9-0012-376b6c802672"
[deps]部分之后的代码是包的 UUIDs。您可能不需要配置[deps],因为我们正在运行我们自己的 VPS 但是把它们放进去仍然是个好习惯。
现在,在我们编辑任何东西之前,我们首先需要激活我们的精灵环境,然后安装我们的两个 dep。我们可以使用 bin/repl 从项目的根目录访问 REPL。注意:如果在任何尚未安装的文件中调用了依赖项,REPL 将无法加载,因此最好先这样做。
-$ bin/repl
几分钟后,我们的 REPL 将上升,我们可以添加车床和 JLD2
]
pkg> add "Lathe"#Unstable
pkg> add JLD2
现在一直退格,直到 Julia 包装文本闪烁,并按 CTRL/Command + D,这将把我们带回 bash。现在要测试您的服务器,您可以简单地运行 bin/server:
-$ bin/server
现在我们需要编辑我们的 routes 文件来添加一些逻辑。
nano routes.jl
这就是我的结局:
using Genie.Router
using Lathe.pipelines: pippredict
using JLD2
route("/") do
[@load](http://twitter.com/load) "algorithm.jld2"
year = haskey([@params](http://twitter.com/params), :year)
y_pred = pippredict(pipe,year)
return(y_pred)
end
load 宏将我们的管道对象作为可变结构 pipe 加载。我们采用函数 pippredict(很快将使用 Lathe.models: predict)并插入我们的请求参数。当然,我们会返回结果。
现在我们有了一个包含文件和所有内容的工作服务器,我们需要一个管理员来为我们运行服务器。首先,如果您没有 supervisor,请安装它:
sudo dnf install supervisor
现在我们需要为主管做一个配置。所以纳米一上来!
sudo nano /etc/superviser/conf.d/genieapp.conf
启动 Genie 服务器的 sh 命令是 bin/server,所以我的配置看起来有点像这样:
[program:genie]
directory=/var/www/45.56.119.8/
command=/var/www/45.56.119.8/bin/server
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
现在我们需要重新启动我们的主管:
sudo systemctl reboot
等待几分钟,因为 Genie 可能需要重新编译您的依赖项,希望它会出现!
我真的很期待用 Genie 构建更复杂的算法!Genie 最大的弱点是缺乏文档,但是最*这越来越不真实了。我迫不及待地想看看我用这些奇妙的工具开发了什么!我们现在唯一能做的就是继续写作,继续承诺;车床几乎进入 0.1.0 版本,这是令人难以置信的兴奋!如果你想把承诺推到车床上,请这样做!车床不稳定可从这里获得:
车床
用 OpenCV 和 OpenCV Contrib 构建 Python 源代码
原文:https://towardsdatascience.com/building-python-source-with-opencv-and-opencv-contrib-ba95d709eb?source=collection_archive---------12-----------------------
从源代码在 Ubuntu 14.0 LTS 上安装 Python 3.7
Photo by sarandy westfall on Unsplash
从源代码在 Ubuntu 14.0 LTS 上安装 Python 3.7
- 首先,更新包列表,并从源代码安装构建 Python3.7 所需的包:
sudo apt update
sudo apt install build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev wget
2.使用下面的 wget 命令从 Python 下载页面下载最新版本的源代码,或者将其下载到下载文件夹中。
wget https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tgz
3.下载完成后,解压压缩的 tarball :
cd Downloads/
tar -xf Python-3.7.4.tgz
4.接下来,导航到 Python 源目录并运行configure
脚本,该脚本将执行大量检查以确保系统上的所有依赖项都存在。启用优化将通过运行多个测试来优化 Python 二进制文件。这使得构建过程更慢。
cd Python-3.7.4 ./configure --enable-optimization
5.使用make
启动 Python 构建过程:
make -j 8
为了加快构建时间,请根据处理器修改-j 标志。如果你不知道你的处理器的核心数,你可以通过捆绑 nproc 命令找到它。系统使用 8 个内核,所以我使用-j 8 标志。
6.构建完成后,通过运行以下命令安装 Python 二进制文件:
sudo make altinstall
不要使用标准的make install
,因为它会覆盖默认的系统 python3 二进制文件。
7.就是这样。Python 3.7 已经安装完毕,随时可以使用。键入以下命令进行验证:
python3.7 --version
输出将显示 Python 版本:
Python 3.7.4
用 Python3.7 源码安装 OpenCV 和 OpenCV_contrib 源码
- 从 Github 开放 CV 版本下载 OpenCV 下载 OpenCV_contrib 。
2.首先,更新包列表并安装从源代码构建 OpenCV 所需的包:
sudo apt-get install build-essential checkinstall yasm
sudo apt-get install cmake git gfortran libgtk2.0-dev libgtk-3-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
sudo apt-get install libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev jasper libdc1394-22-dev
sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev
sudo apt-get install libxvidcore-dev libx264-dev libx265-dev
sudo apt-get install libatlas-base-dev gfortran
sudo apt-get install libwebp-dev
sudo apt-get install cmake-curses-gui
sudo apt install qtcreator
sudo apt install qt5-default
sudo apt-get install libgstreamer1.0-0 gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-doc gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio
sudo apt -y install libtiff5-dev
sudo apt -y install libxine2-dev
sudo apt -y install libfaac-dev libmp3lame-dev libtheora-dev
sudo apt -y install libvorbis-dev
sudo apt -y install libopencore-amrnb-dev libopencore-amrwb-dev
sudo apt -y install libavresample-dev
sudo apt -y install x264 v4l-utils
sudo apt -y install libprotobuf-dev protobuf-compiler
sudo apt -y install libgoogle-glog-dev libgflags-dev
sudo apt -y install libgphoto2-dev libeigen3-dev libhdf5-dev doxygen
sudo apt-get install libqt5x11extras5-dev qttools5-dev
sudo apt-get install openexr libopenexr-dev
sudo apt-get install libx11-dev libboost-python-dev
3.转到下载并解压缩 OpenCV 和 OpenCV_contrib 模块。
cd Downloads/
tar -xf opencv-4.1.2.tar.gz
tar -xf opencv_contrib-4.1.2.tar.gz
4.创建一个名为 Development 的新文件夹,以拥有一个虚拟 python 环境。
cd ..
mkdir Development
cd Development
python3.7 -m venv OpenCV_Python3.7
现在检查您的 Python 虚拟环境是否已经创建。转到 OpenCV_Python3.7/bin 并查找 activate
5.激活 Python 虚拟环境
cd
source /home/anshu/Development/OpenCV_Python3.7/bin/activate
pip install numpy
sudo apt-get update
cd Downloads/
cd opencv-4.1.2/
mkdir build
cd build
ccmake ..
按回车键并回车
OPENCV _ EXTRA _ MODULES _ PATH =/home/anshu/Downloads/OPENCV _ contrib-4 . 1 . 2/MODULES
按向上箭头和向下箭头浏览页面
按 c 键进行配置
按 g 生成并退出
make -j4
sudo make install
现在带有 OpenCV_contrib 模块的 OpenCV 已经成功安装。转到/Downloads/opencv-4 . 1 . 2/build/lib/python 3/并查找cv2 . cpython-37m-x86 _ 64-Linux-GNU . so文件。复制。所以把它归档粘贴到/Home/Development/OpenCV _ python 3.7/lib/python 3.7/site _ packages/中,把它重命名为 cv2.so 。
PyCharm 装置
PyCharm 现在也可以作为快照包使用。如果您使用的是 Ubuntu 16.04 或更高版本,您可以从命令行安装 PyCharm:
sudo apt-get install snap
sudo snap install pycharm-community — classic
打开您的 Pycharm 并创建一个新项目,将解释器的路径设置为您的 OpenCV_Python3.7 虚拟环境
现在,在新项目中创建一个 test.py 并测试 openCV 库。现在可以尝试 OpenCV 主版本中缺少的“TrackerMedianFlow”。
在我的 Youtube 频道上关注我
https://www.youtube.com/channel/UCSp0BoeXI_EK2W0GzG7TxEw
在此与我联系:
领英:https://www.linkedin.com/in/ashishban...
github:https://github.com/Ashishb21
中:https://medium.com/@ashishb21
网址:http://techplanetai.com/
电子邮件:techplanetai@gmail.com ashishb21@gmail.com
参考资料:
- https://towards data science . com/how-to-install-opencv-and-extra-modules-from-source-using-cmake-and-set-up-in-your-py charm-7e 6 AE 25 dbac 5
- https://www . learnopencv . com/install-opencv-3-4-4-on-Ubuntu-16-04/
用 AWS Sagemaker 和 Comet.ml 构建可靠的机器学习管道
原文:https://towardsdatascience.com/building-reliable-machine-learning-pipelines-with-aws-sagemaker-and-comet-ml-364ea4b0f27d?source=collection_archive---------24-----------------------
本教程是系列教程的第二部分。见第一部分此处。
成功地大规模执行机器学习需要围绕你的模型建立可靠的反馈回路。随着您的管道的增长,您将达到这样一个点,即您的数据不再适合单台机器上的内存,并且您的培训过程将不得不以分布式方式运行。随着新数据的出现和底层特征分布的改变,定期的重新训练和模型的超参数优化将变得必要。
在数据上尝试新的建模方法以及在团队和其他利益相关者之间交流结果也增加了复杂性。
在这篇博文中,我们将展示如何使用 AWS Sagemaker 和 Comet.ml 来简化监控和改进培训渠道的过程。
数据复杂性+模型需求不断增长
创建功能性反馈循环所涉及的挑战超出了数据关注的范围,如跟踪变化的数据分布到模型级别的问题。稳健模型需要频繁的再训练,以便超参数在面对新的输入数据时是最优的。
随着每次迭代,管理数据和模型的子集和变化变得更加困难。跟踪哪个模型迭代在哪个数据集上运行是再现性的关键。
将复杂性乘以团队复杂性
在团队环境中,管理这些复杂的管道会变得更加困难。数据科学家通常会将多个模型的结果存储在日志文件中,这样就不可能有效地重现模型或交流结果。
传统的软件开发工具没有针对机器学习的迭代性质或机器学习所需的数据规模进行优化。缺乏工具和流程来简化相同数据科学团队成员之间(以及工程等职能部门之间)的协作,导致迭代周期大大变慢。组织还不断遭受新员工入职时间缓慢的痛苦,并承担员工带着他们的工作和专有知识流失的风险。
辅导的
本教程涵盖了如何将 Comet.ml 与 AWS Sagemaker 的 Tensorflow Estimator API 集成。我们将使用 Tensorflow 在 CIFAR10 数据集上调整运行 Resnet 模型。
我们将实验指标记录到 Comet.ml,而不是 Tensorboard。
这使我们能够跟踪不同训练运行中的各种超参数配置、指标和代码。
- AWS SageMaker 为训练和部署机器学习模型提供了方便可靠的基础设施。
- Comet.ml 自动跟踪和监控机器学习实验和模型。
你可以查看 Comet.ml 这里了解更多关于 AWS Sagemaker 这里。
环境设置
当使用 AWS Sagemaker 时,您的帐户附带了多个预安装的虚拟环境,其中包含 Jupyter 内核和流行的 python 包,如 scikit、Pandas、NumPy、TensorFlow 和 MXNet 。
- 创建一个 Sagemaker 帐户。在此处,您将被引导完成获取证书的所有步骤,以便向培训集群提交工作。
2.在这里设置你的 Comet.ml 账户。登录后,我们将带您进入默认项目,您将看到提供项目 API 密钥的快速入门指南。
3.创建一个 Sagemaker 笔记本实例,并从这个实例启动一个新的终端。
4.打开一个新的终端实例(使用新建下拉菜单)。使用命令行激活 tensorflow_p36 虚拟环境
$ source activate tensorflow_p36
使用终端,将来自https://github.com/comet-ml/comet-sagemaker的 Sagemaker 实例克隆到您的 Sagemaker 实例中
$ git clone [https://github.com/comet-ml/comet-sagemaker.git](https://github.com/comet-ml/comet-sagemaker.git) && cd comet-sagemaker && pip install -r requirements.txt
将 Sagemaker Estimator API 与 Comet.ml 集成
Sagemaker Estimator API 使用 Tensorflow (TF) EstimatorSpec 创建一个模型,并根据存储在 AWS S3 的数据对其进行训练。EstimatorSpec 是定义模型训练过程(模型架构、如何预处理数据、跟踪什么指标等)的操作的集合。
- 为了让 Comet 与 TF EstimatorSpec 一起工作,我们必须创建一个训练挂钩,将 Comet 实验对象包装在 TF SessionRunHook 对象中。我们将修改 tf.train.LoggingTensorHook 中的代码,以便将指标记录到 Comet 中。你可以在这里找到参考实现。
初始化你的 Comet.ml 项目
- 将 Comet.ml API 键、项目名和工作空间名添加到 CometSessionHook 中的实验对象。你可以在这里找到实验对象
- 我们在 resnet_cifar_10.py 文件的
model_fn
函数中初始化 CometSessionHook 对象。model_fn
函数定义了我们想要跟踪的张量和参数。 - 本实验的超参数设置在 main.py 中,但是可以随意调整这些默认值。该模型的超参数包括:学习速率、批量大小、动量、数据批量数、权重衰减。
- 运行
python main.py
或! python main.py
,如果从笔记本电脑内运行。 - 您将在 Sagemaker 笔记本输出中收到一条消息,表明您的实验在 Comet.ml 中是实时的,并带有指向该实验的直接 url。
- 您更改了
main.py
文件中的参数并重新运行脚本。
comet . ml 中的监控实验
- 一旦您运行了这个脚本,您将能够通过直接的 url 看到您的不同模型在 Comet.ml 中运行。作为本教程的一个例子,我们已经创建了一个 Comet 项目,您可以在https://www.comet.ml/dn6/comet-sagemaker查看。
- 让我们看看如何使用 Comet 来更好地理解我们的模型。
- 首先,让我们通过单击实验表中的“精度”列,根据精度对模型进行排序。这些列是根据用户提供的超参数填充的,或者是根据代码中的命令行参数自动推断的。还可以使用定制列选项定制它们来跟踪相关参数和模型的指标。
- 现在让我们给我们的项目添加一些可视化效果,这样我们就可以看到超参数是如何影响我们的实验的。
- 然后,让我们使用一个线图来可视化我们的学习曲线,一个条形图来跟踪我们跨实验的最终准确度分数,一个*行坐标图来可视化我们的超参数空间的哪些部分产生了最好的结果。
- 我们可以使用 Comet 的查询构建器来过滤我们的实验,以便我们只分析满足我们的阈值标准的模型。例如,也许你只想看到高于一定准确率的实验。
- 我们可以看到,我们的图表都根据应用于实验的过滤器而变化。
- 我们的*行坐标图能够显示我们已经探索的参数空间的部分,以及我们有差距的地方。在本例中,我们看到较大的 Resnet 大小和批量大小会产生更准确的模型。
然而,这个表现最好的实验也被允许比其他实验运行更长时间。为了更好地评估模型的性能,我们可以将它隐藏在实验表中,从而将其从图表中排除
- 我们的图表表更新以反映我们的实验表,我们现在可以看到,给定类似的训练时间,较大的 Resnet 大小不一定产生最好的结果。
我们可以使用这些见解继续迭代我们的模型设计,直到我们满足我们的需求。
Comet.ml 允许您创建可视化效果,如条形图和线图,以便使用*行坐标图跟踪您的实验。这些实验级和项目级的可视化帮助您快速识别性能最佳的模型,并了解您的参数空间。
如果您想要公开共享您的结果,您可以通过项目的共享按钮生成一个链接。或者,您也可以通过在您的工作区设置中将人员添加为协作者来直接与协作者共享实验。
教程摘要
您已经学习了如何使用 Comet.ml 和 AWS Sagemaker 的 Tensorflow Estimator API 准备和训练 Resnet 模型。为了总结本教程的重点,我们:
- 使用 Sagemaker 的一个预装虚拟环境在亚马逊 Sagemaker 笔记本实例中的 CIFAR-10 数据集上训练一个 Resnet 模型
- 探索了训练实验的不同迭代,其中我们改变了超参数
- 使用 Comet.ml 在不同的训练运行中自动捕获我们模型的各种超参数配置、指标和代码。
报名免费试用 Comet.ml 这里 。
在 Golang 中构建 RESTful APIs
原文:https://towardsdatascience.com/building-restful-apis-in-golang-e3fe6e3f8f95?source=collection_archive---------10-----------------------
注:这最初发布在martinheinz . dev
在上一篇文章中,我们讨论了如何为你的 Golang 项目创建“终极”设置,现在是时候将它应用到真实的东西上了——RESTful API。这篇文章将涵盖数据库、单元测试、API 测试、示例应用程序以及实际项目中你需要的一切。所以,让我们直接开始吧。
因为这篇文章是这些系列文章的后续文章,为你的下一个 Golang 项目最终设置,所以如果你没有读那篇文章,那么你可能想先看看。
TL;DR:这里是我的资源库( *rest-api*
分支)-https://github . com/Martin Heinz/go-project-blue print/tree/rest-API
框架和库
首先,我们要用什么来建造它?
- Gin —我们将使用 Gin HTTP web 框架。它是构建在
net/http
之上的高性能框架,提供了最基本的特性、库和必要的功能。它也有相当干净和全面的 API。 - GORM —是在
database/sql
之上开发的 Golang ORM 库。它包括所有奇特的功能,如预加载、回调、事务等。它有一些学习曲线,没有那么好的文档,所以如果你是那种喜欢写原始 SQL 的人,那么你可以选择sqlx
。 - Viper — Go 配置库,可以处理各种格式、命令行标志、环境变量等。这个库的设置和使用已经在之前的帖子这里解释过了,所以我就不在这里赘述了。
项目和包结构
接下来,让我们检查项目中的单个包。除了main
还有以下包,每个包都有单独的责任。让我们从数据库开始,通过查询,一直到 API 端点:
模型
模型包(models
)有一个文件,它定义了反映数据库表结构的类型。在存储库中的例子中,有两个struct
类型- Model
和User
:
Model
是与gorm.Model
相同的类型,只是增加了 json 标签,使得生成包含其字段的 JSON 响应更加容易。其次,User
用 GORM 标签描述了简单的应用程序用户,这些标签指定了字段应该与哪一列相关联。还有很多标签,比如索引、类型或关联,你可以在这里找到更多。
数据访问对象
接下来是daos
包,是数据访问对象 ( DAOs )的简称。道是一个负责访问数据的对象(惊喜,惊喜...),这实质上意味着它使用 GORM 或原始 SQL 进行 SQL 查询。在下面的例子中,我们有一个简单的函数,它根据 ID 检索用户数据,并以前面提到的User
模型的形式连同错误(如果有的话)一起返回:
您可以根据 Dao 访问的表、相似的业务逻辑或者您想要的任何其他指标来分离 Dao,但不要将它们混为一谈,否则会变得一团糟。
服务
当我们将数据很好地加载到模型中时,我们可以在提供数据之前执行额外的逻辑来处理数据,这就是服务发挥作用的地方。这个额外的逻辑可以是例如过滤、聚集、修改结构或验证数据。最重要的是,它允许我们将数据库查询从业务逻辑中分离出来,这使得代码更干净、更易于维护,最重要的是(对我来说)更易于测试(稍后将详细介绍)。所以,让我们看看代码:
在上面的代码中,我们首先定义了 interface,它将所有之前创建的 DAO 函数组合在一起,在本例中只是来自前面部分的Get(id uint)
。接下来,我们定义用户服务,它包含我们的 DAO 和一个使用作为参数提供的 DAO 创建它的函数。最后,我们定义一个函数,它可以执行一些额外的逻辑,并使用来自UserService
的 DAO ,然而,这里为了简单起见,我们只使用 DAO 为用户查询数据库并返回它。此处可以执行的逻辑示例将是模型验证或错误检查。
蜜蜂
最后,有了准备好为我们提供经过处理的有效数据的服务,我们可以将它们提供给我们的用户。那么,让我们看看代码:
在这个代码片段中,我们可以看到可用于服务 API 端点的函数。这里,我们首先用提供的用户 DAO 创建服务,这在前面已经描述过了。接下来,我们解析 ID,我们希望它在 URL 中(类似于— /users/{id}
),然后我们使用服务从数据库中获取用户数据,最后,如果找到数据,我们以 JSON 格式返回它,并带有200
状态代码。
将它们连接在一起
前几节中展示的东西都很好,但是现在我们实际上需要在main
中设置它,以便 Gin 知道在哪里提供我们的 API:
显然,我们首先需要创建 Gin 的实例,然后我们将中间件附加到它上面,例如记录器或 CORS 。最后一部分——也是最重要的一部分——我们创建了一组端点,这些端点都以api/v1/
开始,并注册我们上一节中的GetUser
函数,该函数将在/api/v1/users
处专门提供服务,然后是用户 ID 参数,就这样,现在我们可以运行我们的应用程序了!
此时你可能会想“为什么要创建所有的包、单独的文件、函数层等等?” —好吧,答案是——如果你的应用程序足够大,那么如果你把所有东西都集中在一起,这将成为可维护性的噩梦,而且——在我看来,更重要的是——这种分离对于更好的可测试性是必要的,因为单独测试每一层——数据库访问、数据操作和 API——比在一个地方测试要容易得多。所以,当我们谈到测试的话题时,我想是时候写一些…
注意:在上面的代码片段中,为了清楚起见,我省略了几行代码和注释,比如连接到数据库或加载配置,这些可以在资源库 这里 中找到,包括一些更多的注释用于解释。
测试一切
现在,对于我最喜欢的部分——测试——让我们从test_data
包开始。这个包包含与测试数据库和测试数据相关的实用函数。这个包中我想注意的一个函数是init
:
该功能比较特殊,因为 Go 在导入包时执行。这是设置测试的好地方——更具体地说,我们首先加载配置,然后创建我们的测试数据库,它是内存中的 SQLite,我们还为它启用了外键。最后,我们使用GORM函数创建数据库表。
你可能会问“为什么使用 SQLite 内存数据库,不是更好吗?”——是的,我自己在每个项目中都使用 PostgreSQL ,但是当涉及到测试时,您需要一致、快速(内存中)并且独立于主机系统/数据库服务器的东西,这正是本设置所提供的。
我不会重复这个包的剩余功能,因为这篇文章已经很长了,它们在这里的代码中有记录。
除了初始化函数之外,我们还在这个包中存储了一些数据,即包含 SQL 插入的db.sql
文件,这些 SQL 插入在运行测试之前填充了我们的 SQLite 数据库,还有 JSON 测试用例,它们被用作 API 端点的预期输出。
现在,我们已经设置好了,让我们检查一下每个包中的测试:
首先,daos
,上面的测试非常简单,我们只需创建 DAO 并调用被测函数(Get
)并根据期望值进行测试,这些都是在设置过程中插入到 SQLite 数据库中的,其他的就没什么可说的了。让我们继续看services
:
这是相当多的一点代码,让我们从下往上看。我们首先需要的是模拟道 ( mockUserDAO
),这样我们就独立于真正的道的实现了。为了让这个模拟有用,我们需要用一些测试数据填充它,这就是在newMockUserDAO
中发生的事情。接下来,我们还需要定义模仿真实版本的Get
的模拟版本——在这里,我们不需要查询数据库,只需查看假记录,如果发现提供的 ID,就返回一个。
现在,对于实际的测试——我们创建了NewUserService
,但是我们没有传入真正的 DAO ,而是使用具有可预测行为的模拟,因此我们能够将测试中的函数与底层的 DAO 隔离开来。之后,测试就非常简单了——我们使用 mock Get
方法,测试插入到 mock 中的预期值是否存在。
最后要测试的是 API,这些测试实际上是一行程序,但是我们需要做一点准备:
这里的这 3 个函数模拟 HTTP 请求,用于我们的测试目的。首先在测试模式下创建 Gin 并重置数据库。第二个服务并随后命中特定的 API 端点,最后一个运行测试用例列表并检查状态代码是否相同,并且可选地检查 JSON 输出是否也相同。现在,让我们看看测试用例的例子:
参数很多,但很简单,让我们一个一个来看:
"t1 - get a User"
-测试用例的名称-编号,这样在调试时更容易找到"GET"
- HTTP 方式"/users/:id"
-正在服务/测试的 URL"/users/1"
-被点击的 URL 带有填充的参数""
-请求体-在本例中为空GetUser
-附加到端点的方法http.StatusOK
-预期状态代码-此处为200
path + "/user_t1.json"
-预期 JSON 输出的路径——这些存储在前面提到的test_data
包中
结论
就这样——在 Golang 中创建 RESTful API 所需要的一切。希望在构建您的下一个项目时,这些内容至少会对您有所帮助。您可以在这里找到所有源代码,如果您有任何建议或改进,请随意创建问题、拉式请求或直接分叉/启动存储库。如果您喜欢这篇文章,请寻找下一篇,在那里我将展示如何将 Swagger 文档添加到这个项目中。
构建敏感度地图集
原文:https://towardsdatascience.com/building-sensitivity-atlases-e305682d7b7d?source=collection_archive---------37-----------------------
研究人员、环境管理者、生态学家、研究人员——我们都在寻找更好的视角。实地调查、遥感和系统理解让我们能够将知识拼凑起来,这些知识反过来又可以用来确定人类与环境互动的优先次序。所有这些知识都是概括。概括的矛盾之处在于,有时我们需要它们来以一种可管理的方式看待我们的世界。我们看到的越少,我们的一些决定就会越好。
敏感性图谱是一种概括。灵敏度图册方法并不代表通常与法律、法规或国际协议相关的方法。目前它是一个被赋予一个名字的方法的大杂烩。该方法有 20 多种不同的实现方式——如果不是更多的话。考虑到这些实现的有用性,试图找到一个统一的方法是很有趣的。我们正在努力。
这种方法已经有 35 年的历史了。它以多种形式成为创建土地使用、应急响应等优先地图的核心工具。实施过程通常伴随着高成本、大量工时以及对众多从业者的高技术能力要求。
通过建立一个更好的文档和更轻量级的方法,我们希望看到许多积极的结果。以下是其中的一些:
- 通过培训和其他交流,可以更容易地共享一个描述良好的方法。
- 支持技术实现将更加统一,同时仍在使用不同的技术*台进行开发。
- 由此产生的灵敏度图谱产品更容易理解,并放在上下文中,因为方法不会改变。
- 统一的方法将促进建立更广泛的从业者群体。
2019 年 9 月在阿鲁沙举行的一次研讨会上,来自 8 个环境机构的代表应邀出席,介绍了走向统一方法的新步骤。我们的客人来自乌干达、加纳、坦桑尼亚、桑给巴尔、莫桑比克、肯尼亚、索马里和黎巴嫩。研讨会由挪威环境署和环境署-WCMC 的代表举办。
研讨会上介绍了一种方法的初稿,其中根据 tis 方法准备和处理不同的数据集。在准备过程中,准备了一个脚本程序。除了该程序之外,我们还分发了包含准备好的测试数据集、800×800 米左右的网格集和 QGIS 项目文件的国家包。
用于处理的软件是来自安全软件公司的 FME。选择它是因为它代表了一种实现必要过程的简单方法。开发的程序要求由 NEA 和环境署-WCMC 编写。这个程序是由挪威公司 Norkart 利用 SAFE 软件公司的 FME 快速开发出来的。它就像一个魔咒!
FME 是许多商业实体和政府部门用来准备、处理和交付数据的工具。作为一个商业工具,它通常要求像这样的研讨会的参与者拥有自己的许可证。在要求为这项工作提供实物许可证时,SAFE software 同意了,并向 30 名参与者提供了许可证。我们非常高兴有机会使用 FME!
结果数据集的演示软件是 QGIS 。选择它主要是因为它是开放和自由的软件。制作了展示数据的相关模板,并在研讨会上使用。QGIS 是管理数据和以动态方式展示数据的优秀工具。
这些工具在研讨会上大受欢迎。在 5 天之内,所有参与机构都使用现有工具建立了自己的敏感性地图集。对他们中的许多人来说,这已经计划了多年,但是现在工具让他们用为他的工作室准备的测试数据来做这件事。国际鸟盟、国际自然保护联盟、Protectedplaned.org以及更多的组织提供了数据供我们在本次研讨会上使用。
使用这种方法需要生态学和技术知识。该方法的一个关键部分是评估该方法中所谓的敏感性和优先级。没有知识渊博的生态学家和生物学家是做不到这一点的。如果没有人能够在技术层面上培育这个过程,这项工作也无法完成和展示。
有了这个工具,参与的环境机构得到了解放。他们现在在技术上能够处理国家敏感地图。关于使用不同资产层的持续支持和建议将非常重要。跟进关于...
我们将继续记录我们在 researchgate 项目上的工具,并且在我们进行的过程中也会尝试发布项目更新。如果你对这个项目中使用的四分之一度网格单元感兴趣,请阅读这篇论文。
这个研讨会代表了向前迈出的重要一步!
以下机构值得一提: Safe Software 、 Norkart 、坦桑尼亚保护资源中心、 Obscom 、#norad、#oilfordevelopment 等等。
原载于 2019 年 10 月 24 日http://www.mindland.com。
使用 Cosmos DB、Databricks 和 Blob 存储在 Azure 中构建简单的数据管道
原文:https://towardsdatascience.com/building-simple-data-pipelines-in-azure-using-cosmos-db-databricks-and-blob-storage-fffac0d49505?source=collection_archive---------12-----------------------
感谢像 Azure Databricks 这样的工具,我们可以在云中构建简单的数据管道,并使用 Spark 相对容易地获得对我们数据的一些全面的见解。将这与Apache Spark connector for Cosmos DB结合起来,我们可以利用 Azure Cosmos DB 的能力来获取和存储对我们数据的一些难以置信的见解。
自从我在 Databricks 上写了一篇文章已经有一段时间了,而且因为我在过去的几个月里一直在使用 Cosmos DB,我想我应该写一个简单的教程,介绍如何使用 Azure Blob Storage 、Azure Databricks 和 Cosmos DB 来构建一个简单的数据管道,对我们的源数据进行一些简单的转换。
我还将加入一些 Azure Key Vault(T8),向您展示保护数据块中的重要机密(如存储帐户密钥和 Cosmos DB 端点)是多么简单!
这篇博文主要是针对初学者的。理想情况下,您应该对每个组件有所了解,并且对 Python 有所了解。
好了,聊够了!让我们开始吧。
关于我们的文件
我们的源文件包含来自国际足联数据库的各种足球运动员的数据。我从几年前参加的 Datacamp 课程中下载了它(如果有人知道哪个课程,请告诉我,我会适当地记下它)。我们的数据文件包含以下几列:
- Id
- 名称
- 评级
- 位置
- 身高(厘米)
- 脚(哪个最占优势)
- 稀有(这是一个 0 或者 1。从数据集和我对足球的了解来看,我猜 1 是罕见的,0 是常见的。我不确定为什么这个专栏会存在,所以我们暂时忽略它)
- 各种技能等级(步伐、射门、传球、运球、防守、头球、鱼跃、处理、踢球、反射、速度、定位)。
在本教程中,我们只想找出哪些玩家的评分超过 85,并将这些玩家保存到 Cosmos DB 中的一个集合中。非常简单的东西只是为了展示所有东西是如何组合在一起的。
所以我们已经介绍了源文件,让我们把它放在云端!
创建 Azure 存储帐户
如果你不确定 Azure Storage 是什么,它是 blobs、文件、消息和 NoSQL 存储等东西的云存储。使用 Azure 存储,我们可以确保我们的数据安全且易于访问。
我将创建一个存储帐户,并在我们的存储帐户中创建一个容器来存放 Blobs。做到这一点非常容易。
在 Azure 门户中,点击“创建资源,并选择存储帐户。如果可以看到,使用搜索栏查找。
接下来,我们必须对其进行配置。首先,我们需要将它放在一个资源组中。这本质上只是 Azure 资源的集合。当我们通过 CI/CD 配置资源时,这些功能会派上用场,在管理资源时也很有用(比如在完成教程后删除我们不需要的资源)。
完成后,我们可以为我们的存储帐户指定一个名称,一个位置(我选择了澳大利亚东部,因为那里是离我最*的数据中心),我们想要什么样的性能,我们想要什么样的类型帐户,我们需要什么样的复制级别以及我们想要什么样的访问层。如果你想要更多关于这些设置的解释,请查看 Azure 文档。
我们还可以在创建存储帐户时初始化一些高级设置,比如允许从指定的虚拟网络访问。还是那句话,基础教程,暂时忽略。如果您的配置有效,单击创建并等待您的存储帐户准备就绪。
现在我们的帐户已经准备好了,我们可以创建一个容器来存储我们的 blobs。
点击服务下的 Blobs ,然后点击容器选项卡来创建我们的第一个容器。从这个意义上来说,可以把容器想象成文件目录中的一个文件夹(而不是 Docker 容器)。给出名称和公共访问级别。
如果你将一个容器公开,那么这个容器中的所有内容都将对公众开放。只是暂时保密。
就这样,我们的容器被创建了!
好的,点击它,然后点击上传!我将把我们的源文件上传到容器中。如果文件已经存在于你的容器中,你需要覆盖它。
点击上传,如果一切正常,您只需点击几下鼠标,就已经将原始数据集上传到云中了!
很明显,这不是我们将 blobs 上传到真实应用的存储帐户的方式,但就目前而言,这已经足够了。
我们已经创建了一个存储帐户并上传了我们的文件,接下来我们来调配一个 Databricks 工作区。
创建数据块工作空间
Azure Databricks 是一个统一的分析*台,允许数据科学家、数据工程师和业务用户聚集在一起,利用 Azure 上托管的 Apache Spark 服务的力量获得对其数据的高级见解。
要创建一个工作区,回到 Azure 门户,点击“创建新资源”。在搜索中,输入数据块,然后选择 Azure 数据块选项(见下面的例子,假设门户没有改变)
现在我们必须给它一些设置。给你的工作区起一个名,为它分配我们为存储帐户创建的现有资源组,将其部署在你附*的数据中心位置,并分配一个定价等级(我选择了高级)。您可以选择在虚拟网络中部署您的 Databricks 工作空间,但这超出了我们的要求。
一旦我们的工作区部署完毕,我们可以通过点击启动工作区来导航到它。这将打开数据块用户界面。
为了在数据块中运行笔记本和作业,我们需要创建一个集群。在 Databricks UI 中,单击侧栏中的集群按钮,然后单击创建集群。
当我们在数据块中创建集群时,我们可以为它们提供以下设置:
- 名字:我们星团的名字
- 集群模式:我们可以在数据块中创建两种类型的集群。对于有多个用户同时使用的集群,我们将创建一个高并发集群(这些不支持 Scala)。对于本教程,我们将创建一个标准集群。这些确实支持 Scala 语言,并且是为单用户使用而设计的。
- 池:这是新特性!我们可以将一个集群分配给一个池,以减少启动时间。不过,我没怎么玩过这个。
- Databricks 运行时版本:设置 Databricks 将用于创建集群的映像。这将创建一个拥有 Scala 和 Spark 特定版本的集群
- Python 版本:我们可以选择 Python 2.7 或 3.5 作为集群使用的 Python 版本。
- 启用自动伸缩:创建集群时,我们设置集群可用的最小和最大工作节点数。如果我们启用自动缩放,Databricks 将在执行 Spark 作业时自动缩放它使用的工作节点数量。
- Terminate after period: 该设置决定了在集群自动关闭之前我们希望经过的时间。
- 工作者和驱动程序类型:数据块中的集群本质上运行在虚拟机上。我们可以设置我们希望我们的节点基于工作机和驱动程序的虚拟机类型。如果愿意,我们还可以将它们设置为具有相同类型的虚拟机。
- 高级选项:在这里,我们可以配置我们的 Spark 配置,配置日志写入的位置,加载任何我们想要在初始化时运行的脚本等等。我们根本不会使用它,所以现在不用担心这个。
完成集群设置后,单击 create,几分钟后集群就创建好了。它将出现在集群 UI 中的“交互式集群部分的下方。
让我们暂时离开数据块。我们已经设置好了工作区和集群(如果它正在运行,您可以将其关闭)。我们稍后会回来安装我们的库。
创建 Cosmos DB 帐户
对于本教程,我将创建一个使用 SQL API 的 Cosmos DB 帐户(它也称为核心 API,但我现在称它为 SQL API)。这意味着我们将使用支持 SQL API 的 Spark 连接器。MongoDB API 和 Cassandra API 有不同的连接器,所以如果你正在为你的 Cosmos 帐户使用这些 API 或者更熟悉这些数据存储,请确保你使用这些连接器!
要创建我们的 Cosmos DB 帐户,请返回 Azure 门户并单击创建资源。搜索 Azure Cosmos DB 并点击创建:
在 UI 中,将新的 Cosmos DB 帐户放入我们用于存储帐户和数据块工作区的同一个资源组中。给它一个名称,并选择核心(SQL) API 作为我们的 Cosmos DB 帐户将使用的 API 。将它放在您附*的位置,并且暂时禁用地理冗余和多区域写入。点击创建进行部署!
这可能需要大约 4 分钟来创建,所以如果你喜欢,你可以喝杯茶或咖啡。当您回来时,您应该已经准备好了一个 Cosmos DB 帐户,并且迫不及待地要使用它了!
我们现在需要创建一个容器来存储我们的数据。Cosmos 中的容器在不同的 API 中被称为不同的东西,但是你可以把它想象成一个存储文档的表格。
因为我们是第一次创建容器,所以我们还需要创建一个新的数据库来保存集合。您应该提供以下设置。
- 数据库 Id: 这是我们数据库的名称。
- 吞吐量:这是我们提供给宇宙神器的吞吐量。我写了一篇文章,深入探讨了宇宙中的吞吐量。
- 容器 Id: 这是我们集合的名称。
- 分区键:这将是我们对集合进行分区的属性。我还写了一篇文章,更深入地探讨了分区。
点击确定以供应我们的新系列。过一会儿,导航到 Cosmos 门户中的数据浏览器,我们应该会看到我们的新数据库和集合。
因此,现在我们已经提供了我们的存储帐户(数据源位置)、Databricks 工作区(处理我们的数据的地方)和 Cosmos DB 集合(它将充当我们的接收器)。
在开始之前,我们还有最后一步要完成。为了访问这些资源,我们需要端点和访问键来将各个部分连接在一起。理想情况下,我们不应该将这些密钥暴露给公众或任何可能恶意使用它们的人。所以我们需要创建的最后一个 Azure 资源是一个密钥库来保护我们的秘密。
创建 Azure 密钥库并添加我们的秘密。
使用 Azure Key Vault 是管理我们想要保护的秘密和密钥的简单方法。让我们设置一个来存储我们的存储帐户和我们的 Cosmos DB 端点和访问密钥的秘密。
你现在知道该怎么做了!前往 Azure 门户,点击创建资源并搜索密钥库。
给你的钥匙金库起一个名字,把它添加到我们的现有资源组,把它放在你附*的区域并选择一个定价等级。对于本教程,我选择了标准层。
现在我们有了密钥库,我们可以把我们的秘密添加到它里面了。进入你的 Cosmos DB 账户,从侧边栏选择键。你应该看到下面的屏幕(当然没有可怕的审查关键值!).暂时将端点复制到剪贴板。
一旦你这样做了,回到你的密钥库,从侧边栏选择秘密。点击生成/导入为我们的宇宙端点生成一个新的秘密
当你创建一个秘密时,你需要指定你想要如何上传这个秘密,给它一个名并添加值,这里有一个例子:
点击创建来创建秘密,你应该会在你的秘密列表中看到这个秘密。
对您的 Cosmos DB 主键和 Azure Storage 主键重复此操作。
您还需要配置您的 Databricks 工作区,以将 Azure Key Vault 用作机密存储。关于如何做到这一点的完整指南可以在这里阅读。
太棒了。我们已经设置了所有需要的组件。在我们开始在笔记本上编码之前,我们现在只需要做最后一件事。
安装并导入我们的库
Databricks 附带了预安装在我们的集群上的各种不同的库,我们可以使用这些库来处理我们的数据。我们还可以在我们需要的集群上安装库。
为了在 Python 中使用用于 Cosmos DB 的 Apache Spark 连接器,我们需要安装 pyDocmentDB ,这是用于 Python 的 Cosmos DB 的客户端库(当然,在撰写本文时,Cosmos DB 团队最*发布了他们的 v3。NET 客户端,我相信这是将所有 SDK 从 DocumentDB(旧产品名)更改为 Cosmos DB(闪亮的新产品名)的漫长过程的开始。
在我们的集群上安装库非常简单。为此,我们需要确保我们的集群正在运行。如果它被终止,启动它,一旦它开始运行,点击集群 div 右上角的库超链接:
从这里,您将能够看到集群上安装了哪些库。正如您所看到的,我已经在这里安装了 pyDocumentDB 库和 Apache Spark 连接器,但是我将详细介绍如何将 pyDocumentDB 安装到您的集群上:
点击安装新的按钮,你会看到下面的对话框出现。
如您所见,我们可以通过各种不同的方式将库安装到我们的集群中。出于我们的目的,我们将直接从 PyPI 导入它。在 Package 文本框中输入 pyDocumentDB 并点击 Install。请稍候,它将安装在您的群集上!
唷!我们已经为基础教程做了很多。如果你已经走了这么远,你应该为自己感到骄傲!您已经设置了云中基本数据管道所需的所有组件!
现在我们已经设置好了一切,让编码开始吧!
将存储帐户安装到数据块
为了开始在 Databricks 中编码,我们需要创建一个笔记本。在 Databricks UI 侧边栏上选择工作区,并点击工作区文本旁边的下拉箭头。点击创建>笔记本,出现如下对话框:
我们必须给我们的笔记本起一个名字,一种语言,并给它分配一个集群。在本教程中,我们将使用 Python,所以请使用它。它将使用您在创建群集时分配给它的版本,因此在我的示例中,我们将使用 3.5 版本。
一旦完成,我们就可以开始添加代码了!(终于!).让我们从添加必要的 pyDocumentDB 库开始:
接下来,我们将把我们的存储帐户安装到笔记本电脑上。这允许我们将容器装入数据块中,然后像使用数据块工作区中的本地文件一样使用它:
为了将存储帐户安装到我们的 Databricks 笔记本,我们需要定义
- 我们的源系统(在这种情况下,它将是 wabss://container name @ storage account name . blob . core . windows . net)
- 我们的挂载点(我们可以随意命名)
- 提供额外的配置,这实际上是我们的密钥范围(Azure Key Vault)和我们想要调用的密钥的名称(查看您在 Key Vault 中的秘密列表以了解这一点)。
我们可以通过使用 DBFS API 和 Display()函数来查看我们的新挂载点内部的文件:
通过执行这个命令,我们可以在挂载点中看到 csv 文件。
我们已经安装了文件,现在让我们做一些简单的转换。
将我们的文件转换成数据块中的数据集
我们的笔记本中有一个源文件,因此我们现在必须将其转换为数据帧,以便使用它。
出于我们的目的,我们希望得到一个球员的评级,他们的身高,他们踢什么位置,他们的优势脚是什么,他们的名字,我们希望过滤评级为 85 或更高的球员。
让我们将源文件转换成 Spark 数据帧。使用 Spark API 做到这一点非常简单。我们只需要指定文件是什么格式,我们是否想要读取一个头,我们是否应该在读取时推断一个模式,最后设置我们想要读取文件的路径(这将是我们的挂载点/filename.csv )。让我们这样做,并将结果应用到名为 footballPlayersDF 的数据帧中。
现在我们的文件已经变成了数据帧,我们可以开始对它进行一些转换。让我们首先创建一个名为 elitePlayersDF 的新数据框架,它只从足球运动员 sDF 中选择评分等于或大于 85/100 的运动员。
我们为每个转换创建一个新的数据帧,因为它使并行处理更容易,并且允许我们以安全的方式操作我们的分布式数据。让我们创建一个最终的 DataFrame,它只选择我们在 Cosmos DB 中的最终集合所需的列。
我们可以在数据帧上调用 Display() 函数来快速查看数据帧的样子。Databricks 会自动将结果限制在 1000 行以内(如果记录比这个多的话)。在我们的数据集上调用 Display() ,我们应该会看到类似这样的内容:
我们已经完成了我们的转变!现在,我们可以使用 Apache Spark connector for Cosmos DB 将数据帧写入集合。
将结果写入 Cosmos DB
为了将我们的数据帧写入 Cosmos DB,我们需要向 writeConfig 对象提供我们的 C osmos DB 端点、主密钥、我们希望写入的数据库的名称、我们希望写入数据的集合的名称,并且我们必须将 Upsert 值设置为 true 。
一旦作业执行完毕,导航回您的 Cosmos DB 集合,并单击集合中的项目,查看 Cosmos DB 中的持久化项目!很酷吧?!
删除资源并总结!
你有它!这不是最复杂的例子,我们在这里所做的只是获取一个简单的 csv 文件,将其上传到 blob 存储,在 Azure Databricks 中读取它,使用 Spark API 对它进行一些非常基本的过滤,然后使用 Apache Spark Connector for Cosmos DB 将结果持久化到 Cosmos DB。
我希望我提出的观点是,几乎不使用任何代码行,并且对如何创建 Azure 资源有一个基本的理解,我们已经在 Azure 中建立了构建一些惊人的分析数据管道的基础。
如果你一直在跟进,确保完成后清理你的资源(只是为了省钱!).为此,进入你的 Azure 门户,点击侧边栏中的资源组。
从这里,单击已经部署了所有资源的资源组(希望它们都在同一个组中!).
点击资源组名称旁边的省略号,然后选择“删除资源组”。您应该会看到弹出以下对话框。
只需键入您的资源组名称即可删除资源和组本身。等一会儿,他们应该走了。
本教程到此结束!显然,如果你在 Azure 中为生产场景构建数据管道,它会比这更复杂和复杂(这里没有提到 CI/CD 管道)。但是我希望你能从中得到一个简单的解释,一个潜在的工作流程,你可以用它来满足你的需求。
如果您有任何问题或意见,请告诉我!我很想听听。
编码快乐!
使用 Azure Portal Web UI 为雪花数据仓库在 Azure Blob 存储上构建 Snowpipe
原文:https://towardsdatascience.com/building-snowpipe-on-azure-blob-storage-using-azure-portal-web-ui-for-snowflake-data-warehouse-f0cdd7997250?source=collection_archive---------1-----------------------
Image courtesy: https://resources.snowflake.com/solution-briefs/snowflake-cloud-data-platform-solution-brief
Snowpipe 是雪花数据仓库的内置数据摄取机制。它能够监控并自动从云存储(如 Azure Blob Storage、亚马逊 S3)中提取*面文件,并使用“复制到”SQL 命令将数据加载到雪花表中。
在官方文档中,您会找到一个很好的教程:
Azure Blob 存储自动化 snow pipe
https://docs . snow flake . net/manuals/user-guide/data-load-snow pipe-auto-Azure . html
但是,本文使用 Azure CLI(命令行界面)来构建云存储组件和 Azure 事件订阅。在我看来,这不够直观,尤其是对于新用户和对 Azure 了解不够的人来说。尽管他们可以按照这些命令构建 Snowpipe,但对于整体架构和数据流来说,它仍然是不可知论者。换句话说,本教程告诉你如何建立一个雪管,但很难让你理解。
在本教程中,我将介绍如何使用 Azure 门户构建 Snowpipe,这是 Azure 基于 Web 的 UI,我相信这会让您对 Snowpipe 的工作原理有更好的直觉。
创建存储帐户
首先,让我们创建一个资源组来组织将为 Snowpipe 构建的存储帐户。在你的 Azure 门户上,导航到资源组,点击添加。然后,输入该资源组的名称。为了获得最佳性能,您可以选择与雪花区域相同/接*的区域。
然后,让我们为暂存和事件队列消息创建存储帐户。
在官方教程中,创建了两个存储帐户,一个是用于存放*面文件的 blob 存储,另一个是带有存储队列的存储帐户,以便于事件订阅。
事实上,我发现一个既有 Blob 容器又有存储队列的 Azure 存储帐户就足够了。让我们创建这样一个存储帐户。
在我们刚刚创建的资源组中,单击 Add 按钮创建一个资源。在 Azure Marketplace 中,选择存储类别,并在“特色”列表中选择存储帐户。
请注意,存储帐户的名称应该是全局唯一的,所以我添加了日期作为后缀。这是因为每个存储帐户都有一个可以访问的 DNS CName(https://
确保您为账户类型选择了 StorageV2 ,以同时拥有 Blob 容器和存储队列。然后,单击查看+创建验证并创建存储帐户。
准备存储帐户
现在我们有一个存储帐户。但是在我们利用它之前,我们需要创造:
- Snowpipe 将加载的暂存文件的 Blob 容器
- 作为事件订阅端点的存储队列
要创建 Blob 容器,请单击容器按钮,然后单击+容器。给这个容器起一个你认为有意义的名字,然后点击 OK 创建它。
我们现在有了一个 Blob 容器。让我们创建存储队列。
返回到存储帐户概述页面。单击队列创建存储队列。
创建事件网格订阅
接下来,让我们为 Blob 容器创建事件网格订阅,并将端点设置为存储队列。
导航到存储账户->-容器,点击事件选项卡。
那里不应该有任何事件订阅。点击 +活动订阅创建一个。
为事件订阅命名。选择默认的事件网格模式。对于事件类型,确保您选择了 Blob Created ,这就是我们想要的 Snowpipe。然后,选择存储队列作为端点类型。
不要忘记选择存储队列。点击选择您刚刚选择的存储队列下的一个端点链接,右侧会弹出一个新的刀片导航窗口。首先,选择您的订阅,默认情况下,您当前的活动订阅应该已经存在。点击选择存储账户。
另一个弹出的刀片式服务器窗口让您选择存储帐户,因此请选择我们创建的帐户。
在最终的刀片窗口中,选择我们为此创建的存储队列,然后单击确认选择。
现在,您应该看到存储队列显示如下。
在雪花中创建一个集成
之后,我们需要在雪花中创建一个集成。让我们首先从 Azure 记录一些集成所需的信息。
首先,记下存储队列的 URL。导航到存储队列,您将能够获得 URL 以及队列名称,如下所示:
然后,进入 Azure 活动目录 - > 属性获取目录 ID ,稍后雪花将使用该目录 ID 访问您的 Azure 订阅。
要在雪花中创建一个集成,您需要是一个帐户管理员。运行下面的 SQL 命令。
create notification integration SNOWPIPE_DEMO_EVENT
enabled = true
type = queue
notification_provider = azure_storage_queue
azure_storage_queue_primary_uri = '[<your_storage_queue_url>'](https://storagesfqueuedemo.queue.core.windows.net/sfeventqueue')
azure_tenant_id = '<your_directory_id>';
注意:强烈建议在定义集成名称时全部使用大写字母,以避免在一些雪花场景中区分大小写。
提示:一旦完成,您可以运行
show integrations;
命令来检索您的雪花帐户中的所有集成;
向 Azure 认证雪花应用
现在,雪花知道去 Azure 哪里获取通知(Azure Events),但我们仍然需要让 Azure 认证我们的雪花帐户。默认情况下,出于安全考虑,我们绝不应该让存放数据的 Azure 存储帐户被公开访问。
让我们首先在雪花中运行以下 SQL 命令:
DESC notification integration SNOWPIPE_DEMO_EVENT;
在结果窗格中,您将看到AZURE_CONSENT_URL
属性,并且可以在property_value
列访问登录 URL。将其复制并粘贴到您的浏览器中,以便像往常一样登录您的 Azure 帐户。
权限授予通知应该由 Azure 给出,点击接受按钮。
一旦完成,你应该被重定向到雪花官网。现在你可以关闭这个网页了。
现在,再次转到您的 Azure Active Directory ,单击企业应用选项卡。
滚动到底部,你会看到雪花应用程序的名称。
点击名称将让您进入雪花应用集成的详细信息中。记录出现在属性中的名称,以备后用。
现在,我们需要授予雪花对存储队列的访问权。否则,它不会得到事件消息。
导航到存储帐户->-访问控制【IAM】->-角色分配。雪花仍然没有出现,所以我们需要添加角色分配。
点击顶部的添加按钮,然后选择添加角色分配。
在弹出的刀片窗口中,选择存储队列数据贡献者作为角色,因为我们不想授予它不必要的更大权限。然后,在选择输入栏中输入“雪花”进行搜索,应该会检索到雪花应用帐户名。如果您有多个雪花帐户,请确保您选择了您在上述部分中记录的正确帐户。然后,点击保存按钮应用更改。
现在,您可以在角色分配列表中看到雪花账户。
创造一个雪花舞台
我们先来打造一个雪花舞台。这将被 Snowpipe 用作数据源。
创建数据库:
CREATE DATABASE SNOWPIPE_DEMO;
让我们使用公共模式,因为这只是一个实验。
要创建雪花外部阶段,我们需要获得 Azure Blob 容器 URL 和 SAS(共享访问签名)。我们去存储账号->-属性获取网址。
然后,转到“共享访问签名”选项卡以创建 SAS 令牌。在这里,我想更改 1 年后的年份,因此令牌将在一年内有效。您可能希望根据您的要求使用不同的结束日期时间。之后,点击生成 SAS 和连接字符串。
SAS URL 应该如下所示。请注意,这是一个 URL,令牌应该是以问号“?”开头的字符串
完成的 SQL 命令如下所示(请注意,这是一个示例,您需要用自己的命令替换url
和credentials
):
CREATE OR REPLACE STAGE "SNOWPIPE_DEMO"."PUBLIC"."DEMO_STAGE"
url = 'azure://snowpipestorage20191214.blob.core.windows.net/snowpipe-source-blob/'
credentials = (azure_sas_token=
'?sv=2019-02-02&ss=bfqt&srt=sco&sp=rwdlacup&se=2020-12-14T18:44:03Z&st=2019-12-14T10:44:03Z&spr=https&sig=ZPN2qcMw64k44td90gSMzvC7yZuQjnQZZCD2xAUS25Y%3D'
);
让我们测试雪花和 Blob 容器之间的连接。打开你的文本编辑器,写下以下内容,然后将文件另存为emp.csv
1,Chris
2,John
3,Jade
上传到 Blob 容器。
然后,在雪花中运行下面的命令。您应该能够在结果窗格中看到该文件。
ls @"SNOWPIPE_DEMO"."PUBLIC"."DEMO_STAGE";
创建雪管
现在我们到了最后一个阶段,制作雪管。让我们首先创建一个表作为 Snowpipe 的目的地。
CREATE OR REPLACE TABLE "SNOWPIPE_DEMO"."PUBLIC"."EMPLOYEE" (
id STRING,
name STRING
);
然后,使用以下 SQL 命令创建 Snowpipe
CREATE OR REPLACE pipe "SNOWPIPE_DEMO"."PUBLIC"."DEMO_PIPE"
auto_ingest = true
integration = 'SNOWPIPE_DEMO_EVENT'
as
copy into "SNOWPIPE_DEMO"."PUBLIC"."EMPLOYEE"
from @"SNOWPIPE_DEMO"."PUBLIC"."DEMO_STAGE"
file_format = (type = 'CSV');
现在,您将能够显示您刚刚创建的管道。
SHOW PIPES;
Snowpipe 加载现有文件
在我们创建 Snowpipe 之前,emp.csv
文件已经在 Blob 容器中了。因此,它不会自动加载文件,因为它依赖于“Blob Created”事件来触发自身,但该事件发生在它被创建之前。
我们确实有一种方法来加载 Blob 容器中的现有文件。使用下面的命令将手动刷新 Snowpipe,让它加载 Blob 容器中存在但尚未加载的任何文件。
ALTER PIPE "SNOWPIPE_DEMO"."PUBLIC"."DEMO_PIPE" REFRESH;
一旦运行该命令,结果窗格显示如下,这意味着加载请求已经发送到emp.csv
文件:
现在,我们可以运行SELECT * FROM EMPLOYEE
,您将看到从文件中加载的行。
测试雪管
最后,让我们通过上传一个新文件到 Blob 容器来测试 Snowpipe。
如下创建emp_2.csv
文件,并将其上传到snowpipe-source-blob
Blob 容器。
4, Alex
5, Olivier
6, Frank
稍等一会儿,再次检索EMPLOYEE
表,新记录加载完毕!
未来作品
本教程介绍了如何创建 Snowpipe,并重点关注“利用 Azure Portal ”,而不是像雪花官方文档那样使用 Azure CLI。
如果您对在雪花中构建自动化数据管道(从数据接收到生产数据库)的最佳实践感兴趣,请关注关于该主题的下一篇文章。它将涵盖雪花流和任务。
[## 通过我的推荐链接加入灵媒-陶
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@qiuyujx/membership)
如果你觉得我的文章有帮助,请考虑加入 Medium 会员来支持我和成千上万的其他作者!(点击上面的链接)
与 Luigi 一起构建 Spotify Discover 每周电子邮件提醒
原文:https://towardsdatascience.com/building-spotify-discover-weekly-email-alert-with-luigi-ca0bc800d137?source=collection_archive---------18-----------------------
一个简单的 Luigi 数据管道
Photo by Ryan Quintal on Unsplash
首先,我想让你明白,这是我个人学习的记录。您可能会找到比我在这里尝试和展示的方法更好的实现方法。如果你有任何改进代码的建议,我很乐意听取建议和评论。
如果你是 Spotify 用户,你可能听说过他们的一个功能,叫做“发现周刊”。Discover Weekly 是一个包含 30 首歌曲的播放列表,Spotify 会根据您的收听历史推荐这些歌曲。我非常喜欢 Discover Weekly,有时甚至有点害怕 Spotify 太了解我了。似乎不仅仅是我。
我使用 Discover Weekly 的唯一问题是,我无法访问我的历史 Discover Weekly,因为它每周一自动刷新。当我忘记将我喜欢的歌曲保存到我的库或播放列表中时,下周列表就完全消失了,我也没有办法找出我绝对喜欢但忘记保存的那首歌是什么。
我在这里分享的私人小项目,就是从上述问题开始的。我想到的解决方案是每周一从《发现周刊》提取歌曲列表,并将列表作为电子邮件发送给自己。这是一个用 Luigi 尝试简单数据管道的绝佳机会。
需要:
- Spotify 帐户
- Gmail 帐户
- AWS 帐户
(顺便说一句,我用的是 Macbook 做这个项目,如果你用的是 Windows,有些步骤可能会略有不同。)
获取 Spotify API 访问权限
为了能够以编程方式访问 Spotify,您需要 Spotify 的客户端 ID 和客户端密码。您可以通过前往 Spotify for Developers 页面轻松获得。进入仪表板页面后,您可以点击绿色的“创建客户端 ID”按钮,然后会询问您一些问题,如应用程序名称、描述等。
接下来会问你这个 app 是不是商业用的。在我的例子中,我只是为自己构建这个,所以我单击了“否”。
最后,勾选复选框,然后提交。
然后,您将获得一个客户端 ID 和一个客户端密码,您可以使用它们来访问 Spotify API。
拿一份备忘录或复制粘贴到某个地方,因为我们以后会需要这些。点击“编辑设置”,添加“ https://localhost:8080 ”重定向 URIs。在正确的应用程序中,这将在确认 API 访问后将用户重定向到应用程序,但在这种情况下,这将仅用作身份验证参数的一部分。
你需要做的最后一件事是在 Spotify 上关注《发现周刊》。这使得从我们的 Python 程序中检索 Discover Weekly 成为可能。
在 AWS 上启动 EC2 实例
登录到您的 AWS 管理控制台,并点击进入 EC2。我写这篇文章是假设你已经有一个 AWS 帐户。单击“启动实例”。对于这个项目,我选择了亚马逊 Linux AMI 2018.03.0 。
确保选择的实例类型是 t2.micro,它符合自由层的条件。我们应该做的一个重要步骤是为 Luigi 打开端口,以便我们可以访问 Luigi 的中央调度程序。
除了“6”之外,其余保持默认设置。配置安全组”。到达这里后,点击“添加规则”并从“类型”下拉列表中选择自定义 TCP,然后在“端口范围”中键入“8082”。Luigi 的中央调度程序 GUI 默认使用端口 8082,因此这一步使我们能够在 web 浏览器上访问 Luigi GUI。作为附加步骤,您可以在“源”部分添加您自己的 IP 地址,以便您只允许来自某个 IP 地址的入站流量。如果你想明确自己的 IP 地址,只需在源部分输入“你的 IP 地址/32”。现在点击“查看并启动”。
接下来,将提示您选择现有的密钥对或创建新的密钥对。从本地计算机与实例通信时将使用该密钥。让我们为项目创建一个新的密钥对。
首先,下载密钥对,然后最后启动实例。回到 AWS 控制台的 EC2 部分,您可能会看到实例仍然没有处于“运行”状态。给它一些时间,当它转向“运行”时,记下它的公共 DNS (IPv4)和 IPv4 公共 IP。
附加 AWS 准备
从终端或 AWS web 控制台,创建一个名为“luigi-spotify”的 S3 存储桶。这将稍后用于存储从 Spotify 提取的歌曲列表,如 TSV。
连接到 EC2 实例
我希望到目前为止没有什么太复杂的事情。现在,既然我们启动了实例,我们可以 ssh 到它。在此之前,我们需要更改上面下载的密钥对的文件权限,因为 EC2 实例不接受公开可见的密钥文件。打开您的终端,并在将“目录…”部分替换到您自己的目录后运行以下命令
chmod 400 directory-where-you-downloaded-the-key-file/luigi_spotify.pem
3 种类型的用户(用户、组、其他)有 3 种权限(读、写、执行)。上面的代码行所做的是更改文件权限,这样密钥文件只有一种权限(Read)允许一种类型的用户(user)使用。现在我们准备好 ssh 到我们的实例中。同样,请用您自己的目录和公共 DNS 替换“目录…”和“您的实例…”部分。
ssh -i directory-where-you-downloaded-the-key-file/luigi_spotify.pem [ec2-user@y](mailto:ec2-user@ec2-34-240-79-107.eu-west-1.compute.amazonaws.com)our-instance's-public-DNS
正在为 Luigi 任务准备 EC2 实例
在 EC2 实例中,让我们首先安装 Git,这样我们就可以克隆我为这个项目准备的存储库。
sudo yum -y install git
现在使用 git clone 命令克隆存储库。
git clone [https://github.com/tthustla/luigi_spotify.git](https://github.com/tthustla/luigi_spotify.git)
转到克隆的目录,我们先来看看文件。
cd ~/luigi_spotify
ls
ec2-prep.sh 将用于安装所需的软件包。luigi.cfg 是一个配置文件,您将在其中放置所有的 API 密钥和凭证。luigi_cron.sh 是一个 bash 脚本,运行 run-luigi.py 中定义的 luigi 管道。
通过运行下面的命令,使这两个 bash 脚本都可以执行。
chmod 777 *.sh
现在让我们首先运行 ec2-prep.sh
./ec2-prep.sh
路易吉
在我们实际运行管道之前,最好了解管道做什么以及它是如何做的。下面是 run_luigi.py 的代码。
在高层次上,它执行两项任务。首先,从 Discover Weekly 播放列表中获取歌曲列表,并将它们作为 TSV 存储在 S3。一旦它存储完 TSV,然后通过 TSV,它会创建一封电子邮件,将[歌曲名称]——[艺术家]显示为 Spotify 链接,然后将该邮件发送给自己。第一个任务是在 GetWeeklyTracks 类中定义的,第二个是在 SendWeeklyEmail 类中定义的。为了使这些任务能够运行,它需要凭证信息,这些信息是使用 luigi 从 luigi.cfg 文件中检索的。配置类。获取 Spotify API 令牌并建立与 Spotify 的连接是在 Luigi 任务之外完成的。
在本地调度程序上运行 Luigi
接下来我们需要做的是填充 luigi.cfg 文件中的信息。首先用 Nano 打开文件。
nano luigi.cfg
用您自己的凭据填写每个值,不带引号或双引号。现在,我们终于准备好在 EC2 中对管道进行本地测试运行了。
python3 run_luigi.py SendWeeklyEmail --local-scheduler
由于 spot ipy(Spotify API 的 Python 库)的认证流程,你会看到如下的说明。
如果在您的本地机器上测试,这将打开 web 浏览器,但是在 EC2 上不能打开,因为没有安装 web 浏览器。复制 URL(上面截图中蓝色突出显示的部分),粘贴到您的本地机器 web 浏览器并打开。
如果你看到一个如上的屏幕,点击“同意”,然后它会显示如下所示的错误页面。你不必担心这个错误页面。这是因为我们提供的重定向 URI 只是一个本地主机端口,上面没有运行任何东西。复制错误页面的 URL 地址,URL 中嵌入了一个代码,将被 Spotipy 的 autehntication 流使用。
现在回到您的 EC2 终端,将 URL 粘贴到控制台,它显示“输入您被重定向到的 URL:”。现在很有可能第一次尝试不会成功,因为谷歌一开始会阻止这个来自未知 IP 地址的 Gmail 登录。如果发生这种情况,请使用本地机器的 web 浏览器登录到您的 Gmail,然后再次尝试运行该命令。如果一切顺利,您将会收到试运行时发送的电子邮件。
在中央调度程序上运行 Luigi
我们快到了。火车运行成功了,现在我们还有几步要走。现在,让我们用 Luigi 的中央调度程序对管道进行适当的运行,这样我们就可以访问 Lugi GUI 了。首先,为日志文件创建一个目录。
mkdir ~/luigi_spotify/log
当我们进行后台运行时,控制台输出将存储在我们刚刚创建的上述目录中的日志文件中。让我们启动 Luigi 中央调度程序。
luigid --background --logdir ~/luigi_spotify/log
由于我们已经打开了端口 8082 来访问 GUI,我们现在可以在 web 浏览器上打开 GUI。打开带有 IPv4 公共 IP 和“:8082”的页面,如下所示。
your-EC2-pulic-IP:8082
我们尚未运行任何任务,因此您现在不会看到任何任务。现在,让我们运行最后没有“—本地调度程序”参数的管道。您可能希望删除在试运行期间在 S3 存储桶中创建的文件夹,以便从头开始查看整个管道。否则,Luigi 将看到 S3 存储桶中的文件夹和文件,然后只检查输出文件是否在那里,并将任务标记为成功,而不运行任何任务。现在,您将看到两个任务成功运行。
万岁!!
Image courtesy of vernonv on Redbubble
设置 Cron 作业
最后一部分是设置一个 Cron 作业,以便我们可以决定这些任务运行的时间和频率。这里您必须考虑的一件事是,您的 EC2 实例的 Linux 时间可能与您的本地时间不同。运行以下命令来设置 EC2 实例中的时区。
cd /usr/share/zoneinfo
tzselect
在你选择了正确的时区后。从您自己的终端复制用蓝色突出显示的部分并运行。因为我将在不重启的情况下完成 EC2 的设置,所以我只是在终端上直接运行代码,而没有将它附加到。个人资料。
TZ='Europe/London'; export TZ
我们将使用 luigi_cron.sh 设置一个 Cron 作业,该作业将运行 run_luigi.py。这个小部分我花了一段时间才想明白。当作为 Cron 作业运行时,相同的文件、相同的任务会抛出编码错误,而没有 Cron 它也能很好地工作。经过长时间的谷歌搜索,我终于找到了有效的方法。您可以通过运行“locale”找到 EC2 实例的 LC_CTYPE 值。
locale
一旦有了 LC-CTYPE 信息,就用下面代码打开一个 Crontab。
crontab -e
你在那里什么也找不到。按“I”进入“插入”模式,然后粘贴下面的代码,按 esc 键,然后键入“:wq”来写修改并退出。
0 8 * * MON LC_CTYPE="en_GB.UTF-8" ~/luigi_spotify/luigi_cron.sh
上面的 Crontab 表达式将 bash 脚本安排在每周一上午 08:00 运行,但是您可以根据自己的喜好进行更改。如果你需要 Crontab 表达式的帮助,你可以在https://crontab.guru/尝试自己的表达式。
如果要检查 Cron 是否工作,可以先设置 Crontab 值如下(它会每分钟运行一次任务),然后检查是否工作,再改回你要设置的每周 Crontab 值。再次,如果你想做这个检查,请不要忘记从你的 S3 桶删除文件夹。
*/1 * * * * LC_CTYPE="en_GB.UTF-8" ~/luigi_spotify/luigi_cron.sh
就是这样!现在,Luigi 管道将在每周一运行,从我的 Discover Weekly 获取歌曲,并将向我发送电子邮件!
我知道这不是一个非常复杂的任务。但对我来说,这是一次非常美妙的学习经历。当然,我的代码实现还有改进的空间,但是我今天很高兴,因为我使用数据和 Luigi 解决了我的一个日常问题!
感谢您的阅读。你可以从下面的链接找到 Git 仓库。
【https://github.com/tthustla/luigi_spotify 号
建设支持无污染城市:一个开放的数据工作流程
原文:https://towardsdatascience.com/building-support-for-pollution-free-cities-an-open-data-workflow-888096797cc9?source=collection_archive---------14-----------------------
变更数据
空气污染是我们这个时代的最大杀手之一,根据《柳叶刀》的一项研究, 2015 年空气污染导致 640 万人死亡,相比之下,疟疾导致 70 万人死亡。我们如何推动更多的行动来解决这个问题?在本帖中,我们将介绍使用 Python 代码构建数据驱动的宣传工具的步骤。
受一项在伦敦获得显著回报的政治战略的启发,我们将展示如何为纽约或其他投资开放数据门户和 PM2.5 等污染物监测的城市建立类似的工具。
动机:从大雾霾到大扫除
就我个人而言,我一直将空气污染与中国东部沿海地区联系在一起,直到我得知我的家乡伦敦经历了或许是历史上最具破坏性的雾霾事件。
1952 年 12 月,由于一场寒流,伦敦人比*时燃烧了更多的煤,就在这时,低压和无风的条件笼罩着这座城市,将污染物截留在地面上。由于浓厚的黄色烟雾(一种“豌豆汤”)限制了能见度,交通陷入停顿。至少 12000 人死亡。
Left: The Great Smog of London (1952) killed up to 12,000 people. It has been cited by China’s leadership as a worst case scenario justifying stringent actions like limiting auto ownership. Right: air pollution outside the Forbidden City, snapped on my Jan 2018 China trip.
在最*的伦敦之行中,我对报纸、广播和电视中空气污染的突出报道感到震惊。这种媒体环境使得连续三任市长——肯·利文斯通、鲍里斯·约翰逊和萨迪克·汗——采取了影响汽车、工业甚至柴火的雄心勃勃的措施。报道围绕一件事:将空气污染视为儿童健康问题。
1.获取学校和污染数据
遵循相同的方法,但对于纽约市,让我们用来自纽约市社区空气调查的数据来获取并覆盖纽约市的学校位置。两者都可以从纽约市公开数据中获得。
NYCASS 是以合理的成本获取可操作的城市级空气污染数据的绝佳模型。从 2008 年开始,城市工人在 150 个地点安装了便携式空气质量监测器,每次两周,每季一次。使用土地使用回归,纽约市环境保护局可以估算整个城市的污染水*,而不需要安装永久性传感器。
这里,我们导入两个数据集,并使用矢量数据(Geopandas)和栅格数据(Rasterio)的关键 Python 库将它们绘制在一起。检查源代码,了解几个数据清理步骤。
NYCCAS air pollution raster for 2012 combined with Shapefile of New York City Public Schools
Left: Installing air quality sensor on Fifth Avenue. Right: the Community Air Survey built the case for measures like NYC’s ban on heavy fuel oil, which previously heated boilers at 10,000 apartment buildings.
2.每个位置的采样栅格值
NYCCAS 数据是 TIFF 格式的一组栅格集。在一个 300 x 300 米的城市方格中,每个像素都给出了预期的 PM2.5 水*。
Rasterstats 是一个 Python 库,具有有用的 point_query 函数,如下所示。我们通过在每个学校的位置对每个栅格进行采样(我用了七年的栅格),为每个学校创建了一个估计 PM2.5 浓度的时间序列。
结果存储为 Pandas data frame(Excel 电子表格的 Python 等价物)。我还合并了贫困人口普查数据和城市健康结果调查。
DataFrame of schools with PM2.5 levels sampled from the rasters (years 1 through 3 shown).
3.分析 1:各区的污染程度不同吗?
世界卫生组织认为每立方米 10 微克以上的 PM2.5 水*是危险的。下面我们用红色标出了经历不同程度 PM2.5 的小学数量,世卫组织的阈值为红色。一个故事正在浮出水面:布朗克斯区的大多数小学都在门槛以下,但其他区有许多学校接*或超过了危险区。
接下来,同样的情节适用于中学。在把你的孩子送到曼哈顿的学校之前,要小心做好你的功课。
情况是恶化了还是改善了?绘制每个区的学校*均 PM2.5 浓度的时间序列,显示自 2009 年以来的明显改善;尽管许多孩子仍然接*或超过危险的污染物水*。
4.分析 2:空气质量与贫困有什么关系?
穷人常常面临环境污染带来的不成比例的影响。对于每所学校,我们采用周围人口普查地区的中值收入,并将其与最新一年的 PM2.5 估计值进行对比。有趣的是,在纽约,贫困和空气污染之间没有明显的联系。
在伦敦,媒体报道在一定程度上受到研究的推动,这些研究显示,无论是贫困地区还是富裕地区的学校——包括该市一些最负盛名的教育场所——都遭受着危险的污染水*。纽约似乎也遵循着类似的模式:像上东区和展望高地这样的富裕社区都是建筑物和车辆排放大量废气的地区。在工业排放在污染组合中扮演更重要角色的地方,模式可能会有所不同,但至少在这两个城市,空气污染是*等机会杀手。
5.将它们放在一起:数据可视化
我们的 shapefile 结合了学校位置、人口统计特征和 PM2.5 暴露时间序列,数据可视化的时机已经成熟。
什么是成功的宣传工具?在我们的案例中,关键因素是父母的关心。下面是用 Python 的叶库构建的原型,它根据污染水*对每所学校进行颜色编码:超过世卫组织阈值的学校是暗红色的。我们希望父母能够放大他们孩子的学校,看到空气质量,并感到愤怒。没有什么比父母要求为孩子的健康采取行动更能在市政厅推动事态发展了。
点击此处查看使用 Tableau Public 构建的概念验证。纽约市学校数据集包括每个校长的姓名和电话号码,所以试着悬停在一所学校上,如果你特别担心,给他们打电话建议网站改进或无闲置规定!
将开放的数据门户和空气污染监测带到更多的城市将使这种公民行动主义在其他地方成为可能——毕竟,没有什么比关注孩子的健康更能让人类团结起来。
感谢阅读!查看源代码 此处 。如果您想继续交谈,请联系我们或发表评论。
构建数据科学的未来
原文:https://towardsdatascience.com/building-the-future-of-data-science-d5587a402e42?source=collection_archive---------10-----------------------
看完这里所有的部分:第一部、第一部-1B 、第二部、第三部。
如果我们不能预测未来,他们称我们为失败者,如果我们预测得太好,他们称我们为巫师。但正如庞加莱所言:“即使没有确定性也能预见,远胜于完全不预见。”
我谈论数据科学已经有一段时间了。在文章的上半部分,你可以看到我的一些与此相关的作品,但是我想更进一步。我将讨论这个领域的未来。
再次重构庞加莱关于数学的话,如果我们希望预见数据科学的未来,我们正确的做法是研究科学的历史和现状。我将分几个部分来做这件事(对此我很抱歉),所以请稍后继续关注。
先说一些历史吧。我没有用一段段文字来让你厌烦,而是建立了这个关于数据科学的时间线,这将有助于理解我们从哪里来,我们将去哪里。
免责声明:这个时间表可能不完全完整,所以如果你认为我遗漏了什么,请告诉我。此外,我正在将数据科学的历史与计算机科学、机器学习、深度学习、数据分析和数据挖掘的一些发展相结合。
这根本不是一个新领域,但在过去几十年里有了惊人的发展。因为空间的原因,我不得不删掉一些部分和片段,但是最重要的东西还是有希望的。
我用来创建这个时间线的参考资料的完整列表在文章的底部。请检查他们,他们是令人敬畏的。
希望这个时间线能让你了解研究数据的科学的历史,我们现在称之为数据科学,但这可能不是我们的最终术语。所以要时刻准备着变化。
我们要去哪里?
前阵子我发表了这张图表:
关于他这些年对语义技术的兴趣。我们可以很容易地看到它随着时间的推移而增加。在这种情况下,语义意味着使用形式语义来赋予我们周围不同的原始数据以意义,以及能指和它们在现实中所代表的东西,它们的外延之间的关系。
当我们谈论数据中的语义时,我们通常指的是本体、关联数据、图形和知识图、数据结构等等的组合。您可以在本文开头的链接中了解所有这些内容。
但是为什么呢?为什么要转变?事实是,本体语言中的所有数据建模语句(以及其他所有东西)本质上都是增量的。事后增强或修改数据模型可以很容易地通过修改概念来实现。
在这些技术中,我们通常将数据存储在图表中。关系数据库将高度结构化的数据存储在具有预定列和行的表中,而图形数据库可以映射多种类型的关系和复杂数据。这对我们现在拥有的更好。
我现在已经参与了无数的项目,常见的事情是我们花费大量的时间试图理解我们拥有的数据,其中一个原因可能是我们没有以良好的格式存储数据及其关系。数据结构的承诺就是支持公司中的所有数据。它是如何被管理、描述、组合和普遍访问的。
请记住,数据和上下文是第一位的,这种新的模式使用内置的图形数据库和语义数据层来集成和协调所有相关的数据源,包括结构化和非结构化数据。数据结构传达了数据的业务上下文和含义,使业务用户更容易理解和正确利用。
对我来说,这是数据科学的未来。我们正朝着语义技术将成为每家公司标准的方向前进。但我们不会就此止步。增强现实、虚拟现实等领域的所有进步都将伴随着这些转变。例如,看看这个项目:
来自创作者:
北极星是一个交互式数据科学*台,重新思考人们如何与数据交互。它使没有编程经验、统计背景或机器学习专业知识的用户能够通过直观的用户界面探索和挖掘数据,并毫不费力地构建、分析和评估机器学习(ML)管道。
想象一下把它和语义技术结合起来,并且能够和你的数据交流。提出问题,系统会给你答案。这是我们未来的另一部分,自动化。我们需要数据存储、数据管理、数据探索、数据清理以及所有我们实际上花费大量时间做的事情的自动化。你可以说像 DataRobot 这样的工具可以给你提供这些东西,但是根据我的经验,在这个领域还有很多事情要做。
做所有这些事情的*台的一个很好的例子是 Anzo。到处都有自动化。而且很容易在旅途中添加更多功能,如可解释的人工智能、持续智能等等。
https://www.cambridgesemantics.com/product/
但是还有更多的,还会有更多的。我实际上用 AnzoGraph 做了一个练习,它是 Anzo 的一部分,你可以在这里阅读:
[## 数据结构、容器、Kubernetes、知识图表等等
在上一篇文章中,我们讨论了知识图的构建模块,现在我们将更进一步,学习知识图的构建模块
towardsdatascience.com](/https-towardsdatascience-com-the-data-fabric-containers-kubernetes-309674527d16)
我如何跟上所有正在发生的事情?
这是我反复遇到的问题之一。我如何知道去哪里看,并跟上该领域的最新进展。
我的回答是:
要积极。阅读但回复。见但评论。学习但解释。提问。
不要只是所有这些东西的消费者。沉浸在现场,读文章,看视频,看书等等,还要创作。回复对话、提问、创建小组研究、参加课程。
成为科学社区的活跃成员并不容易,因为数据科学使用了许多理论和应用科学,所以跟踪进展尤其不容易。但有可能。
有些地方你必须转换成你最常访问的网页:
在 arXiv 中,您可以找到该领域的最新文章。大部分是预印本,但几乎是最终稿。在那里你可以搜索术语、相关术语和特定作者。这是大多数攻读硕士或博士的人的主页。从这里开始:https://arxiv.org/list/physics.data-an/recent
GitHub 是世界上几乎所有代码的所在地。你会发现有代码和例子惊人的应用程序和项目。此外,你有一个趋势页面,所以你可以看到人们现在感兴趣的。从这里开始:
[## 探索 GitHub
Explore 是您寻找下一个项目、了解流行趋势和连接 GitHub 的指南…
github.com](https://github.com/explore)
《带代码的论文》的使命是用机器学习论文、代码和评估表创建一个免费开放的资源。您会发现无数关于数据科学和计算科学内部的论文,以及实现的代码。这些都是免费的,并且有很好的文档记录和分发。从这里开始:
[## 带代码的论文:机器学习的最新进展
带代码的论文突出了 ML 研究的趋势和实现它的代码。
paperswithcode.com](https://paperswithcode.com/)
如果你是一个程序员,或者你正在学习如何编码,你知道堆栈溢出。这是一个社区,人们在这里提问和回答与编程相关的问题。请确保经常访问它,以查看新的回复和进展。从这里开始:
[## 包含“数据科学”的帖子
Stack Overflow |世界上最大的开发人员在线社区
stackoverflow.com](https://stackoverflow.com/search?q=data+science)
Reddit 是一个巨大的网站/论坛,在那里你可以找到世界上几乎所有的东西。但是有很多很棒的子编辑(比如小组),人们在那里分享有价值的信息,提出很棒的问题,谈论数据科学、机器学习、数学、一般科学等等。搜索:r/learnmachinelearning/、r/deeplearning/、r/datascience/和 r/MachineLearning/。
KDnuggets 是阅读文章和数据信息的最大*台之一。由 Gregory Piatetsky-Shapiro 和 Matthew Mayo 编辑。你会在这里找到我的一些作品。从这里开始:
[## 机器学习、数据科学、大数据、分析、人工智能
编辑描述
www.kdnuggets.com](https://www.kdnuggets.com/)
另一个寻找关于数据科学的不可思议的文章、博客和更多的地方。几乎我所有的文章都存放在这里,并且来自这个领域的了不起的人。由 Ludovic Benistant 创作,由一个非常有才华的团队编辑。从这里开始:
[## 走向数据科学
分享概念、想法和代码。
towardsdatascience.com](https://towardsdatascience.com) [## 数据科学-走向数据科学
走向数据科学为成千上万的人提供了一个*台来交流思想,并扩大我们对…
towardsdatascience.com](https://towardsdatascience.com/data-science/home)
我现在应该学什么?
Article by Isaac Faber
这不是一个简单的问题。但是读完这篇文章和其他文章后,你可能会感到不知所措。我的姐姐海泽尔和我创建了这个简短的解释,你应该了解数据科学:
对于我们正在构建的未来,您需要知道:
- 图表
https://towardsdatascience.com/graph-databases-whats-the-big-deal-ec310b1bc0ed
- 图形数据库
https://blog.cambridgesemantics.com/why-knowledge-graph-for-financial-services-real-world-use-cases
- 语义
https://towardsdatascience.com/the-data-fabric-for-machine-learning-part-2-building-a-knowledge-graph-2fdd1370bb0a
- 本体语言
https://towardsdatascience.com/https-towardsdatascience-com-the-data-fabric-containers-kubernetes-309674527d16
- 能够使用自动化工具进行机器学习
https://www.kdnuggets.com/2017/01/current-state-automated-machine-learning.html
- 真正理解商业问题。这是计算机现在做不到的,它们要做到还需要一段时间。参见 Matthew Dancho 的精彩课程,这是从零到强大快速 fo 的最佳方式。
https://www.business-science.io/
感谢阅读,并等待更多:)
如果您想联系我,请在 twitter 上关注我:
[## 法维奥·巴斯克斯
Favio Vázquez 的最新推文(@FavioVaz)。数据科学家。物理学家和计算工程师。我有一个…
twitter.com](https://twitter.com/faviovaz)
和 LinkedIn:
[## 法维奥瓦兹奎-教员,教授和数据科学的中小企业-荣誉退休研究所…
‼️‼️重要提示:由于 LinkedIn 的技术限制,我现在只能接受来自我…
www.linkedin.com](https://www.linkedin.com/in/faviovazquez)
参考资料:
[## 数据科学的简短历史
数据科学家如何变得性感的故事主要是关于成熟的统计学学科…
www.forbes.com](https://www.forbes.com/sites/gilpress/2013/05/28/a-very-short-history-of-data-science/#5568d0f955cf) [## 数据科学历史入门指南
“大数据”和“数据科学”可能是这十年中最热门的词汇,但它们不一定是新的…
dataconomy.com](https://dataconomy.com/2016/03/beginners-guide-history-data-science/) [## 数据科学简史-数据大学
统计学和统计模型的使用深深植根于数据科学领域。数据科学始于…
www.dataversity.net](https://www.dataversity.net/brief-history-data-science/#) [## 大数据-视觉历史| Winshuttle
从楔形文字,最早的书写形式,到数据中心,人类总是收集信息。崛起…
www.winshuttle.com](https://www.winshuttle.com/big-data-timeline/) [## 业务和信息系统的体系结构
1988 年 2 月 Barry 在 1988 年写了描述数据仓库架构的第一篇公开发表的文章,基于他的…
www.9sight.com](http://www.9sight.com/1988/02/art-ibmsj-ebis/)
为加拿大-美国边境过境等待时间预测构建 Web 应用程序
原文:https://towardsdatascience.com/building-web-app-for-canada-us-border-crossing-wait-time-forecast-18602373c79d?source=collection_archive---------42-----------------------
黑色星期五即将来临。许多加拿大购物者将开车南下,加入购物狂欢。如果你计划在 11 月 29 日跨境旅行,你会想聪明地计划,以避免在边境长时间延误。为了解决这个问题,我们建立了一个网络应用程序,预测未来 7 天的过境等待时间。
以下是该项目的工作流程:
Image by Imre Tömösvári on Unsplash
- 从级联网关 API 中检索过境等待时间
- 使用 Python + XGBoost 建立未来穿越的预测模型
- 使用 Flask,HTML,CSS,ajax 开发 web 应用程序 REST API
- 在 AWS 上部署 web 应用程序
- 每天刷新数据并重新构建预测模型
【链接到网页 apphttp://35.164.32.109:5000/
它没有永久地址,因为它是一个低成本的 AWS 实例。目前的预报只适用于未来 7 天和*拱门路口(不列颠哥伦比亚省和华盛顿州之间)的南行交通。
需要注意的一点是:通过边界的车流量可以用来预测,而不是等待时间。交通量应更加可预测,因为它不会因边境管制的变化而频繁变化,例如更严格的安全检查、开放的车道/岗哨数量以及有时的现场施工。然而,从通勤者的角度来看,他/她更感兴趣的是知道时间延误,而不是通过边界的车辆总数。
数据采集
从级联网关数据仓库中检索过境等待时间数据。它有一个很好的 API 参考文档,使用起来非常简单。
我们提取了自 2014 年 1 月 1 日以来 Peach Arch (BC-Washington)南行车辆的每小时交叉等待时间。以下是一些记录示例:
Group Starts,Avg - Delay (Peace Arch)
2018-01-01 07:00:00,0.3
2018-01-01 08:00:00,1.6
2018-01-01 09:00:00,1.3
2018-01-01 10:00:00,18.8
2018-01-01 11:00:00,37.8
2018-01-01 12:00:00,41.4
2018-01-01 13:00:00,49.1
一天前的过境等待时间记录被添加到我们每天的模型训练中。
模特培训
从过境日期和时间中,我们提取年、月、月中的日、周中的日和小时作为训练特征。
data['HourOfDay'] = data['Date_time'].dt.hour
data['Year'] = data['Date_time'].dt.year
data['Month'] = data['Date_time'].dt.month
data['DayOfMonth'] = data['Date_time'].dt.day
data['DayOfWeek'] = data['Date_time'].dt.dayofweek
不列颠哥伦比亚省和西澳大利亚州的假日也是新增的特色。
# Get Canadian - BC holidays
ca_holidays = holidays.CountryHoliday('CA', prov='BC', state=None)
# Check each date what Canadian holiday it is
data['Holiday_CA'] = [ca_holidays.get(x) for x in data['Date_time']]
# Treat Observed holiday same as regular
data['Holiday_CA'] = pd.Series(data['Holiday_CA']).str.replace(" \(Observed\)", "")
# Convert holiday columns
data = pd.get_dummies(data, columns=['Holiday_CA'])
# Get US - WA holidays
us_holidays = holidays.CountryHoliday('US', prov=None, state='WA')
data['Holiday_US'] = [us_holidays.get(x) for x in data['Date_time']]
data['Holiday_US'] = pd.Series(data['Holiday_US']).str.replace(" \(Observed\)", "")
data = pd.get_dummies(data, columns=['Holiday_US'])
我们使用 XGBoost 算法训练我们的模型,并使用 RMSE(均方根误差)评估其性能。
n_iter = 48
tscv = TimeSeriesSplit(n_splits=4)
xgb_regressor = xgb.XGBRegressor(random_state=29, n_jobs=-1)
xgb_grid_search = RandomizedSearchCV(xgb_regressor,
xgb_parameters,
n_iter = n_iter,
cv=tscv,
scoring = 'neg_mean_squared_error',
verbose=1,
n_jobs=-1,
random_state= 50)
我们可以定义 XGBoost 超参数范围的网格,并从网格中随机采样。产生最佳结果的参数组被选为最终模型。
xgb_parameters = {'objective': ['reg:squarederror'],
'n_estimators': [80, 100, 120],
'learning_rate': [0.01, 0.1, 0.5],
'gamma': [0, 0.01, 0.1],
'reg_lambda': [0.5, 1],
'max_depth': [3, 5, 10],
'subsample': [0.5, 1.0],
'colsample_bytree': [0.5, 0.7, 1],
'seed':[0]
}
数据集中最后 7 天的等待时间记录用于验证。这是一个将实际过境延误与我们对 2018 年 8 月 25 日至 8 月 31 日的预测进行比较的例子。
最后,我们可以保存我们的模型,并为生成未来 7 天的预测做好准备。
Flask Web 应用程序
现在,我们已经完成了预测模型的构建,并准备通过 web 应用程序来展示它。Flask 是一个微型 web 框架,在用 Python 构建 web 应用程序时很流行。它是轻量级的,因为它不需要特定的库来启动。它旨在使入门变得快速简单,并能够扩展到复杂的任务。
AWS 设置
有很多关于如何设置 AWS EC2 实例的资源,例如 AWS 用户指南、 fast.ai 参考等。我们使用 Linux 2 AMI t2.micro,它有 1 个 CPU 和 1GB 内存,因为它很便宜。只需记住在安全组中配置 HTTP、SSH 和端口 5000(用于我们的 web 应用程序访问)。
环境设置和软件包安装
设置好 AWS EC2 实例后,克隆我们的 GitHub 项目
git **clone** [https:*//github.com/wangpengcn/border-crossing-delay-forecast-web-app-flask.git*](https://github.com/wangpengcn/border-crossing-delay-forecast-web-app-flask.git) *border_forecast*
然后,运行脚本来安装 python,创建虚拟环境,安装必要的包,并安排每日模型重建
./install.sh
让我们看看这个脚本做了什么。
定义一些环境变量。
FOLDER_PATH=”/home/ec2-user/border_forecast/”
FOLDER_NAME=”border_forecast”
VENV_NAME=”venv_border_forecast”
执行 yum 安装更新并安装 Python 3.6。
sudo yum update
sudo yum install python36-pip
注意,如果不确定可以安装什么 Python 包,运行sudo yum list | grep python3
进行检查。
接下来,安装并创建虚拟环境,它有自己的站点目录,并与系统站点目录隔离。它使得项目部署更加容易,并且独立于其他正在进行的 Python 项目。
pip3 install — user virtualenv
python3 -m venv $VENV_NAME
激活我们的虚拟环境。
source $VENV_NAME/bin/activate
接下来,安装所需的 Python 包
$VENV_NAME/bin/pip3 install -r requirements.txt
就是这样!您的 Python 环境非常适合。
该脚本的最后一行是安排一个每日作业来重建预测模型并生成未来 7 天的预测。
(crontab -l 2>/dev/**null**; echo “0 5 * * * cd $FOLDER_PATH && $VENV_NAME/bin/python3 border_wait_time_forecast.py > /tmp/border.log”) | crontab -
咖啡时间到了!让脚本运行几分钟,我们就可以启动我们的 web 应用程序了。
运行 Web 应用程序
运行./run_app.sh
启动 web 应用程序。它将运行并显示一条警告消息“这是一个开发服务器”。这是因为我们运行在 Flask 开发服务器上。它应该被生产中的 WSGI 服务器所取代。
Web app 现在运行在 http://0.0.0.0:5000 上访问时,用您的 AWS IPv4 公共 IP 替换 0.0.0.0,例如http://35.164.32.109:5000/
搞定了。您的 web 应用程序现已上线!
未来作品
- 扩大对其他边境口岸的预测
- 允许用户报告实际过境时间,并纳入模型
Python 代码可以在我的 GitHub 上找到。
感恩节快乐!机器学习快乐!
如果你喜欢这篇文章或者有任何问题,欢迎留下评论。帮我接通 LinkedIn 。
构建您的第一个机器学习模型:线性回归估计器
原文:https://towardsdatascience.com/building-your-first-machine-learning-model-linear-regression-estimator-ba86450c4d24?source=collection_archive---------28-----------------------
有这么多好的软件包可以用来构建预测模型。一些最常见的预测分析包包括
- Sci-kit 学习包
- 插入符号包
- 张量流
重要的是,在使用这些包之前,你要掌握预测建模的基础,这样你就不会把这些包简单地当作黑盒工具来使用。
理解机器学习模型功能的一种方法是让你实际学习如何建立自己的模型。最简单的机器学习模型是线性回归模型。每个刚接触数据科学的人都应该掌握线性回归估计器的基础知识,因为大多数机器学习模型(如 SVM、KNN、逻辑回归等)都是线性回归估计器。)非常类似于线性回归估计量。
在本文中,我们将描述如何构建一个简单的 python 估算器,以使用梯度下降法执行线性回归。假设我们有一个包含单个要素(X)和结果(y)的一维数据集,并假设数据集中有 N 个观测值:
拟合数据的线性模型如下所示:
其中 w0 和 w1 是算法在训练期间学习的权重。
梯度下降算法
如果我们假设模型中的误差是独立的且呈正态分布,则似然函数如下所示:
为了最大化似然函数,我们最小化 w0 和 w1 的误差*方和(SSE ):
目标函数或我们的 SSE 函数通常使用梯度下降(GD)算法来最小化。在 GD 方法中,权重根据以下程序更新:
即在与梯度相反的方向上。这里,eta 是一个小的正常数,称为学习率。该等式可以用分量形式写成:
如果你想了解更多关于 GD 算法及其工作原理的信息,请参见以下文章: 机器学习:梯度下降算法如何工作 。
使用 Python Estimator 实现
import pandas as pd
import numpy as np
import matplotlib.pyplot as pltclass GradientDescent(object):
"""Gradient descent optimizer.
Parameters
------------
eta : float
Learning rate (between 0.0 and 1.0)
n_iter : int
Passes over the training dataset.
Attributes
-----------
w_ : 1d-array
Weights after fitting.
errors_ : list
Error in every epoch.
""" def __init__(self, eta=0.01, n_iter=10):
self.eta = eta
self.n_iter = n_iter
def fit(self, X, y):
"""Fit the data.
Parameters
----------
X : {array-like}, shape = [n_points]
Independent variable or predictor.
y : array-like, shape = [n_points]
Outcome of prediction.
Returns
-------
self : object
"""
self.w_ = np.zeros(2)
self.errors_ = []
for i in range(self.n_iter):
errors = 0
for j in range(X.shape[0]):
self.w_[1:] += self.eta*X[j]*(y[j] - self.w_[0] - self.w_[1]*X[j])
self.w_[0] += self.eta*(y[j] - self.w_[0] - self.w_[1]*X[j])
errors += 0.5*(y[j] - self.w_[0] - self.w_[1]*X[j])**2
self.errors_.append(errors)
return self def predict(self, X):
"""Return predicted y values"""
return self.w_[0] + self.w_[1]*X
Python 估计器的应用
a)创建数据集
np.random.seed(1)
X=np.linspace(0,1,10)
y = 2*X + 1
y = y + np.random.normal(0,0.05,X.shape[0])
b)拟合和预测
gda = GradientDescent(eta=0.1, n_iter=100)
gda.fit(X,y)
y_hat=gda.predict(X)
c)绘图输出
plt.figure()
plt.scatter(X,y, marker='x',c='r',alpha=0.5,label='data')
plt.plot(X,y_hat, marker='s',c='b',alpha=0.5,label='fit')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
d)计算 R *方值
R_sq = 1-((y_hat - y)**2).sum()/((y-np.mean(y))**2).sum()
R_sq
0.991281901588877
总之,我们已经展示了如何使用 GD 算法在 Python 中构建和实现一个简单的线性回归估计器。如果你想看看 GD 算法在一个真实的机器学习分类算法中是如何使用的,请看下面的 Github 知识库。
在 TensorFlow 2 |面向黑客的 TensorFlow 中构建您的第一个神经网络(第一部分)
原文:https://towardsdatascience.com/building-your-first-neural-network-in-tensorflow-2-tensorflow-for-hackers-part-i-e1e2f1dfe7a0?source=collection_archive---------2-----------------------
用 TensorFlow 和 Keras 进行深度学习能让你更时尚吗?
TL;DR 使用 TensorFlow 2 构建并训练您的第一个神经网络模型。使用该模型从图像中识别服装类型。
好吧,我先说一个秘密——我是时尚奇才(只要我们说的是运动服)。幸运的是,即使是像我这样的人,也有获得帮助的方法!
你能想象一个真正有助于“时尚无障碍”的浏览器扩展吗?一些能告诉你你正在看的衣服类型的东西。
毕竟我真的很需要这样的东西。我发现没有这样的东西存在,甚至没有去寻找它。我们来做一个从图像预测服装类型的神经网络吧!
这是我们要做的:
1.安装张量流 2
2。看看一些时尚数据
3。转换数据,这样对我们有用
4。在 TensorFlow 2
5 中创建你的第一个神经网络。预测你的神经网络没有看到的图像上显示的是什么类型的衣服
设置
随着 TensorFlow 2 的出现(不确定这个拐角有多远),创建您的第一个神经网络变得前所未有的简单(就 TensorFlow 而言)。
但是什么是张量流?机器学习*台(真的是 Google?)由 Google 创建并开源。请注意,TensorFlow 不是用于创建神经网络的专用库,尽管它主要用于此目的。
那么,TensorFlow 2 为我们准备了什么?
TensorFlow 2.0 专注于简单性和易用性,具有渴望执行、直观的高级 API 和在任何*台上灵活构建模型等更新
好了,让我们检查这些声明并安装 TensorFlow 2:
时尚数据
你的神经网络需要学习一些东西。在机器学习中,这种东西叫做数据集。今天的数据集叫做时尚 MNIST 。
Fashion-MNIST
是一个由 Zalando 的文章图像组成的数据集,由 60,000 个样本的训练集和 10,000 个样本的测试集组成。每个示例都是 28x28 灰度图像,与 10 个类别的标签相关联。
换句话说,我们有 70,000 张 28 像素宽和 28 像素高的灰度图像。每张图片展示了 10 种可能的服装类型。这里有一个:
以下是数据集中的一些图片以及它们展示的服装:
这里有各种不同类型的衣服:
| Label | Description |
|-------|-------------|
| 0 | T-shirt/top |
| 1 | Trouser |
| 2 | Pullover |
| 3 | Dress |
| 4 | Coat |
| 5 | Sandal |
| 6 | Shirt |
| 7 | Sneaker |
| 8 | Bag |
| 9 | Ankle boot |
既然我们已经熟悉了现有的数据,让我们把它用于我们的神经网络。
数据预处理
让我们从将数据加载到内存开始:
幸运的是,TensorFlow 内置了数据集,因此我们可以轻松地获取它。
加载它给了我们 4 样东西:
x_train
—6 万件件衣服的图像(像素)数据。用于构建我们的模型。
y_train
—以上服装的类别(服装类型)。用于构建我们的模型。
x_val
—万件衣服的图像(像素)数据。用于测试/验证我们的模型。
y_val
—服装类(服装类型)以上为服装。用于测试/验证我们的模型。
现在,你的神经网络不能像你一样真正看到图像。但它能理解数字。我们数据集中每个图像的每个数据点都是像素数据,即 0 到 255 之间的数字。我们希望数据被转换(为什么?虽然事实更微妙,但可以说它有助于训练更好的模型)在 0-1 的范围内。怎么才能做到呢?
我们将使用 TensorFlow 的数据集来准备我们的数据:
让我们解开这里发生的事情。[tf.one_hot](https://www.tensorflow.org/api_docs/python/tf/one_hot)
是做什么的?假设你有以下向量:
[1, 2, 3, 1]
下面是它的一键编码版本:
[
[1, 0, 0],
[0, 1, 0],
[0, 0, 1],
[1, 0, 0]
]
它在数字的索引位置放置 1,在其他位置放置 0。
我们使用[from_tensor_slices](https://www.tensorflow.org/api_docs/python/tf/data/Dataset#from_tensor_slices)
从数据中创建数据集,并将图像的每个像素除以 255 以在 0–1 范围内缩放。
然后我们使用[shuffle](https://www.tensorflow.org/api_docs/python/tf/data/Dataset#shuffle)
和[batch](https://www.tensorflow.org/api_docs/python/tf/data/Dataset#batch)
将数据转换成块。
但是,为什么要打乱数据呢?我们不希望我们的模型根据训练数据的顺序进行预测,所以我们只是打乱它。
我真的为那个糟糕的笑话感到抱歉:
创建你的第一个神经网络
你做得很好!现在是有趣的部分,使用数据创建您的第一个神经网络。
使用 Keras 层构建您的神经网络
他们说 TensorFlow 2 有一个简单的高级 API,让我们试一试:
原来高级 API 是旧的 Keras API,非常棒。
大多数神经网络是通过“堆叠”层来构建的。想想煎饼或者千层面。你的第一个神经网络真的很简单。它有 5 层。
第一个(整形)层称为输入层,负责为下面的层转换输入数据。我们的图像是像素。我们只是将 2D 28x28
数组转换为 1D 784
数组。
所有其他层都是密集(互连)。您可能会注意到参数units
,它设置每层的神经元数量。activation
参数指定了一个函数,该函数决定层中特定神经元的“意见”是否应该被考虑以及考虑到什么程度。有很多激活功能可以使用。
最后(输出)层是一个特殊的层。它有 10 个神经元,因为我们的数据中有 10 种不同类型的衣服。你从这一层得到模型的预测。
训练你的模型
现在你的神经网络完全是个哑巴。它就像一个没有灵魂的躯壳(很好,你得到了灵魂)。让我们用我们的数据来训练它:
训练神经网络包括决定准确性的客观测量和知道如何改进的算法。
TensorFlow 允许我们指定将要使用的优化算法— Adam 和度量(损失函数)—CategoricalCrossentropy(我们正在选择/分类 10 种不同类型的服装)。我们也在训练过程中测量模型的准确性!
实际训练发生在调用 fit 方法时。我们向它提供我们的训练和验证数据,并指定我们训练了多少个纪元。在一个训练时期,所有数据都显示给模型。
以下是我们培训的一个样本结果:
Epoch 1/10 500/500 [==============================] - 9s 18ms/step - loss: 1.7340 - accuracy: 0.7303 - val_loss: 1.6871 - val_accuracy: 0.7812
Epoch 2/10 500/500 [==============================] - 6s 12ms/step - loss: 1.6806 - accuracy: 0.7807 - val_loss: 1.6795 - val_accuracy: 0.7812
...
经过 10 个时期后,我在验证集上获得了大约 82%的准确率。让我们从我们的模式中获利!
做预测
既然你的神经网络已经“学习”了一些东西,让我们试一试:
下面是一个预测示例:
array([
1.8154810e-07,
1.0657334e-09,
9.9998713e-01,
1.1928002e-05,
2.9766360e-08,
4.0670972e-08,
2.5100772e-07,
4.5147233e-11,
2.9812568e-07,
3.5224868e-11
], dtype=float32)
回想一下,我们有 10 种不同的服装类型。我们的模型输出关于每种服装类型在图像上显示的可能性的概率分布。要做决定,我们可以得到概率最高的一个:
2
以下是我们模型中一个正确的和一个错误的预测:
结论
好了,你运行了你的第一个神经网络并做了一些预测!你可以在这里看看谷歌联合实验室笔记本(包括更多图表):
## colab.research.google.com
有一天你可能会意识到,你和机器学习的关系类似于婚姻。你可能遇到的问题也是类似的!《是什么让婚姻运转》作者约翰·戈特曼,南·西尔弗列出了婚姻存在的 5 个问题:“金钱、孩子、性、时间、其他”。以下是机器学习的对应部分:
我们一起解决它们好吗?
构建自己的深度学习计算机并在云服务上省钱
原文:https://towardsdatascience.com/building-your-own-deep-learning-computer-and-saving-money-on-cloud-services-c9797261077d?source=collection_archive---------2-----------------------
纠结了几年微软 Azure 的 GPU VM,又听说亚马逊的 AWS 也好不了多少,决定是时候拥有自己的本地深度学习机器了。
我的一个主要原因是云虚拟机没有显示器,因此你不能在视觉上做任何事情。如果你只是在那里训练,然后在本地计算机上运行模型,这没什么大不了的,但如果你需要从事基于模拟的机器人项目,这些项目根本不会在虚拟环境中运行。
我后来发现,不仅建立一个几乎最先进的机器在大约 4 个月内就收回了成本,而且它比云服务器快得多(主要是因为本地数据传输速度,因为所有东西都在同一条总线上的同一个盒子里,而云服务可能将计算单元和存储放在不同的机架上——所以即使 GPU 更快,它也不能足够快地获得数据以受益于这种速度)。
我的系统最终花费不到 100 美元 3K(相比之下,你每月要为 AWS 或 Azure 的入门级云 GPU 支付大约 800 美元)。那是在 2019 年 5 月,价格往往变化很大,所以它可以在任何时候下降或上升 10%。此外,当你读到这篇文章时,这项技术可能已经发展了。
你可能会问,为什么不去买一台高端的超级计算机,而要自己痛苦地制造这台计算机。这是因为现成的深度学习系统非常昂贵。但是如果你仍然害怕修补昂贵的组件,并且对预建的系统感兴趣,我发现 Exxact 出售一些最实惠的深度学习系统,起价为 5899 美元(2 个英伟达 RTX 2080 Ti +英特尔酷睿 i9) ,其中还包括 3 年保修和深度学习堆栈。他们也是由另一位人工智能工程师陈明杰推荐的。
An overview of the components that went in
为了确保一切都一起工作,我推荐使用电脑零件拾取器。它将显示每个组件的最低价格,并确保您不会选择不兼容的部分。至于把东西放在一起,YouTube 说了算。只需输入组件的名称,你会发现几个非常说明如何安装它的视频。现在,我们来看一下所需的组件:
CPU
在这里,你必须做出重大选择:AMD 还是英特尔。我一生都是英特尔的粉丝,但对于这台机器来说,CPU 并不是最重要的部分。那就是 GPU。英特尔 CPU 的价格是 AMD 的两倍。AMD 的新锐龙线有非常好的评论,我不需要超频,因为我不玩视频游戏。因此我选择了AMD thread ripper 1920 x,它有 12 个内核和 24 个线程,对于我的情况来说绰绰有余。它的定价在 350 美元左右是合理的,但价格正在下降。另一种选择是售价超过 900 美元的 10 核英特尔 i9–7900。
The AMD Ryzen Threadripper CPU
CPU 冷却器
AMD 的 CPU 总是运行得非常热(这是它们不那么可靠的主要原因之一)。他们仍然是,所以你肯定需要一个液体冷却器。我选择了有两个风扇的 分形 S24 ,大约 115 美元。另一种选择是海盗船 H100i。
The liquid cooler installed over the CPU
主板
关于主板的选择主要是芯片组。简单的规则是:对于 AMD Threadripper,使用 X399。对于英特尔 7900,使用 X299。
根据评论,我选择了MSI X399 Gaming Pro Carbon AC,它拥有我进行深度学习所需的一切。你会发现它的价格刚刚超过 300 美元。其他不错的选择是华硕 ROG,技嘉 Aorus 和华硕太极(只要确保它至少有 40 个 PCIe 车道)。你必须确保电路板的设计能够容纳 GPU 的大小,也许还需要添加多个 GPU。微星一号空间很大,东西都摆放的很好。
Motherboard is ready to go
GPU
现在这是你深度学习系统最重要的组成部分。你必须使用 Nvidia GPU,推荐的最低配置是 GTX 1080 Ti。不幸的是,当我在寻找时,不可能找到它的正常价格约 800 美元(责怪游戏玩家?秘密矿工?).所以我不得不去下一个级别,RTX 2080 Ti,这也不容易找到,但我很幸运地从 EVGA 得到了一笔 1187 美元的好交易。RTX 是新一代产品,是 2019 年初消费 GPU 中性能最好的产品之一。我很高兴我是“被迫”做出那个选择的。如果你环顾四周,你可能仍然会发现 1200 美元左右的交易。我觉得 EVGA 和技嘉是顶级厂商,你做的选择都是关于散热系统的。EVGA RTX 2080 Ti XC Ultra 有两个空气冷却器,到目前为止证明足够了,它从未达到临界过热。
The most important component — the Nvidia RTX 2080 TI GPU
记忆
对于上面的配置,DDR4 是最好的选择。海盗船可能是主要制造商。而且是 2019 年,你需要 64Gb。所以我最后用了 4x16Gb 海盗船复仇 LPX DDR4 。我花了 399 美元,但是价格急剧下降,现在已经低于 300 美元了。
硬盘
固态硬盘现在已经是老技术了。最先进的是 M.2 标准,这种驱动器直接插入主板的 PCIe 插槽中。以主总线速度,这基本上是一个高容量,持久的内存芯片。我真的很喜欢那台 1Tb 三星 EVO SSD M.2 。我花了 241 美元,但是它的价格也降到了 200 美元。如果你需要更多的存储空间,你可以添加一个普通的固态硬盘,价格应该低于 100 美元。
Memory chips and M.2 hard drive are in place
电源
PCPartPicker 将确保您为您的系统选择足够大的电源。也有其他在线瓦数计算器。使用一个 GPU,你可能不会接* 1000 瓦,但如果你计划添加第二个 GPU,那么你需要 1200 瓦才安全。EVGA 是一个可靠的制造商,我选择了大约 250 美元的 EVGA SuperNOVA P2 白金 1200 。
案例
这里有很多选择,这可能取决于个人喜好和设计,但重要的是要确保它足够大,能够容纳所有的组件,而不会拥挤,并具有良好的空气流通。我选择了 114 美元的联立 PC-O11AIR,因为它符合这些要求。它非常宽敞,所有的东西都放在里面,而且有很好的冷却系统。
附加冷却
完成构建后,您可能需要添加额外的风扇来改善空气流动。我的箱子里有几个风扇,但我又买了几个,几乎填满了每个安装位置。它永远不会在 GPU 机器中变得太冷,这将启动卷积网络。我弄了一个 80mm 夜航 做背面,还在上面加了一个普通的 120mm 海盗船 。是的,我得到了一个。我不太在乎我箱子里明亮闪亮的颜色(反正它在桌子下面),但最后我让步了,买了一个很酷的风扇。
装配
就像我说的,在 YouTube 上搜索每个组件,你肯定会找到关于安装的详细步骤。作为一个例子,下面是我跟随的一些:一个类似于我的的构建,一个 MSI X399 主板及其组件的演练,以及一个关于 Threadripper 安装的焦点。并阅读手册中的所有安装说明。例如,要注意内存单元的插槽位置。
基本上,操作顺序是这样的:
首先,准备机箱,安装电源,拉电源线。然后准备主板,装 CPU,再装 M.2 驱动。将主板安装在机箱中,并添加 CPU 冷却器。然后添加其他风扇,连接电源和按钮/灯线。最后安装内存模块和 GPU。
Getting the CPU into the socket
完成并启动系统后,完成电缆管理并优化冷却。例如,我最终拆除了大多数覆盖风扇的灰尘过滤器。我制定了一个密集的 GPU 繁重的测试协议(训练一个 Yolo 模型),并不断移动风扇,直到我得到最低的温度。
软件安装
这才是真正有趣的地方,但这不是这个故事的重点。2019 年春天——你可能会选择 Ubuntu 18.04,你的 GPU 版本的 Nvidia 驱动程序(快点做,否则显示会非常糟糕),CUDA 10,然后是你使用的任何框架(PyTorch,Tensorflow 等)。享受比你尝试过的任何云 GPU 更高的速度,一次性的价格在几个月内就有回报。
And we’re up and running!
组件列表
这是我的零件清单,价格从 2019 年 4 月开始。您还可以在我的 PCPartPicker 列表上看到更新的价格。
CPU: AMD Threadripper 1920x 12-core ($356)
GPU: EVGA RTX 2080 Ti XC Ultra ($1,187)
CPU Cooler: Fractal S24 ($114)
Motherboard: MSI X399 Gaming Pro Carbon AC ($305)
Memory: Corsair Vengeance LPX DDR4 4x16Gb ($399)
Hard-drive: Samsung 1TB Evo SSD M.2 PCIe ($241)
Power: EVGA SuperNOVA P2 Platinum 1200W ($249)
Case: Lian-Li PC-O11AIR ($114)
这里有一些其他可供选择的版本,我用它们作为灵感和教育:陈明杰的,科林·肖的和韦德·乔里安的。
Chris Fotache 是一名人工智能研究员,在新泽西州工作。他涵盖了与我们生活中的人工智能、Python 编程、机器学习、计算机视觉、自然语言处理、机器人等相关的主题。
用 Python 构建自己的量子电路(带彩色图表)
原文:https://towardsdatascience.com/building-your-own-quantum-circuits-in-python-e9031b548fa7?source=collection_archive---------8-----------------------
充满代码和彩色图表的直观指南…
对于量子计算的速成班,请查看之前的 文章 。
TLDR: 这里我说的是Qiskit,一个开源的 Python 模块,用于构建量子电路,模拟对量子位的操作。我们将浏览示例代码,然后通过非常直观、丰富多彩的图表深入解释代码的作用。
在我以前的文章中,我提到可以建立模型来模拟宇宙中感兴趣的过程。为了建立这些模型,我们使用量子电路,为此我们需要一个模块来操纵和运行量子设备上的量子程序。
在本文中,我们将关注Qiskit——一个 Python 模块,由于其简单易读的语法,它使量子原型化成为一项无压力的任务。Qiskit 是由 IBM Research 开发的,旨在使任何人都可以更容易地与量子计算机进行交互。
量子电路构造新论
在我以前的文章中,我谈到了哈达玛,受控非和泡利 X 门。哈达玛门接收一个量子位元,并以相等的机率输出一个位元成为 1 或 0。
The Hadamard Gate computes a Qubit with an equal probability of becoming a 1 or 0 when measured.
受控非(CNOT)门接收 2 个量子位,并且仅当控制量子位是 ket 1 时,将一个量子位从 ket 0 的一个状态翻转到 ket 1 。否则,它保持不变。
The CNOT Gate flips a Qubit only if the control Qubit is ket 1
现在我们已经概括了门的作用,我们终于可以继续定义我们自己的电路,并模拟它来获得量子位和比特的最终状态!
注: 本教程不涉及泡利 X 门和 Y 门。
建造我们自己的量子电路
由于 Qiskit 的大量文档和资源,构建自己的量子电路很容易。在进入更复杂的内容之前,让我们从头开始浏览构建电路的基础知识。这里,我们将把电路代码分解成容易理解的部分。我们开始吧!
在写量子电路之前,我们需要安装 Qiskit。为此,您可以简单地通过 pip 安装包:
**$** pip install qiskit
要测试您的安装,打开 Python 控制台并输入import qiskit as qk
。如果它运行没有任何错误,您就可以开始了!
注: 如果你遇到任何问题,Qiskit GitHub 问题 页面有大多数初学者问题的解决方案。但是,如果你还有任何迫切的问题,请随时在下面留言或通过Twitter或LinkedIn联系我。
现在我们已经配置了 Qiskit,让我们来处理一些量子位和比特。为了实例化 Qiskit 中的量子位和比特,我们可以使用QuantumRegister
和ClassicalRegister
对象来创建它们。这里,我们每种类型创建 2 个:
寄存器保存着我们的电路所使用的量子位和比特的记录。有了量子位和比特,让我们来构建我们的电路:
让我们在电路中添加一些门来操纵和处理我们的量子位和比特,并最终测量最终的量子位:
让我们想象一下我们的电路,这样我们就对应用于我们的量子位的转换有了一个粗略的想法:
如果我们将这个电路打印到控制台,我们可以看到一个方便打印的电路图(感谢 IBM!).它应该是这样的:
The terminal output should look something like the diagram on the left. The image on the right is a visualization of how the circuit is supposed to be constructed.
恭喜你。你刚刚建立了一个量子电路。现在我们已经准备好了,让我们模拟电路,并使用仿真器运行它。Qiskit 提供具有各种模拟器后端的组件,这些组件以不同的方式操纵量子位。这些成分是空气,伊格尼丝,土地和水。
为了模拟电路,让我们使用 Aer 的QasmSimulator
来模拟真实的量子设备。要使用 Aer 的模拟器,我们可以简单地创建一个模拟作业,并在最后收集结果。Qasm 模拟器运行电路 1024 次(默认)。
“Qasm 模拟器”听起来像是电子游戏里的东西。如果这听起来很吓人,不要担心。它所做的就是在你的本地机器上创建一个经典的模拟来模仿真实量子机器中会发生的事情。正如 Qiskit 文档所称,它始终是一个 伪模拟 。
最后,我们可以看到,电路输出“00”作为位串的概率为 0.481 (492/1024),而输出位串为“11”的概率为 0.519 (532/1024)。
这样,通过模拟我们的电路,我们可以将这个位串转换成十进制或十六进制的对应形式,并查看它们给出的值。
问真正的问题
做完这一切,你可能会问,这一切有什么意义?我们对如何构建电路以及各个元件的功能有所了解。他们是怎么走到一起的?他们都是怎么融入的?这些都是合理的问题。
量子计算处理概率。事件发生的可能性。为此,我们假设事件是完全随机的。量子电路使我们能够获取量子位,将它们叠加,测量它们并得到最终结果。
为了说明这种完全无偏差随机性的应用,让我们构建一个随机数生成器!这样我们就可以看到叠加的力量,以及最终的结果是一个完全随机的数字,没有任何片面性。
此外,不要在本质上是经典的本地模拟上运行它(不能反映量子计算机的惊人性能),让我们连接我们的电路,并在离您最*的实际 IBM 量子计算机上运行它!
A simplified diagram of the processes involved in building a quantum circuit, running it on a Quantum Computer and getting back the simulated results
在我们执行任何量子魔法之前,我们需要连接到离您所在地区最*的 IBM 量子计算机。要做到这一点,请访问 IBM Q 网站并登录,如果您是新用户,请创建一个帐户。
登录后,单击位于右上角的配置文件图标。进入 我的账户 页面,进入 高级 标签页。在那里,您将看到一个用于 API 令牌的区域。如果你没有,那就生成一个吧。
You should see a token inside. If not, click Regenerate to generate one. I’ve blocked mine for security reasons.
我们终于可以开始编写一个客户端电路,它与离您最*的 IBM Q 机器接口,如左边的面板所示。
The available machines closest to where I am
在本教程中,我将使用 ibmqx4 系统,它最多可以保存和操作 4 个量子位。根据您所在的位置,您可能会在仪表板上看到其他可用的机器,所以如果您看不到我的机器,请不要担心。选择你喜欢的那个(选择听起来最酷的那个😎).
接下来,让我们使用下面几行代码连接到量子计算机:
在我们构建电路之前,让我们为随机数生成器创建一个量子位和经典位的记录,该随机数生成器生成 0 到 7 (n=3)之间的数字。
现在,我们需要构建一个电路,返回一个量子位的叠加,并将其折叠为一个表示 0 和 2^n-1 之间的整数的位串。要做到这一点,我们可以在 3 个量子位上应用哈达玛门,让它们以 50%的概率叠加成 1 或 0。
如果我们想象这个电路,它会是这样的:
The Quantum Circuit we’re sending up to the IBM Q Quantum Computer
现在,是激动人心的时候了。让我们实例化将要运行我们电路的量子后端。还记得你在上面使用的 Qasm 模拟器吗?同理,我的 ibmqx4 机器就是这里的模拟器(这里,是真货!).让我们连接我们的后端模拟器:
Shots 这里指的是电路运行的次数。这里我们只想要 1 个随机生成的数字,所以我们将其设置为 1。
注意: 您可以随意使用这个数字,将其设置为 1000 左右,以查看 1000 次运行后生成的数字的直方图。
接下来是主事件函数,它在 ibmqx4 量子计算机上运行一个作业,并返回一个 0 到 7 之间的完全随机数:
现在,是关键时刻了。让我们在分配给我们的量子计算机上运行完整的电路:
这里的代码将需要几分钟的时间来运行,并从我的帐户中扣除了 3 个积分(开始时给你 15 个)。当我运行电路时,最终输出是 6 。
就这样,祝贺你走了这么远!你刚刚建立了一个量子电路。让我们回顾一下成功运行量子程序的步骤:
The typical process of building a Quantum Circuit and running it on a Quantum backend.
注: 量子随机数发生器的完整代码可以在 这里 找到。
包扎
你刚刚建立了一个量子电路!太棒了。你在成为专家的道路上前进了一步。通过思考需要处理比特的简单过程,并将问题转化为可以由量子计算机解决的问题,这是牢固掌握概念的好方法。
Congrats on building a Quantum Circuit! The man himself wishes you well!
简单地
学习量子计算背后的原理肯定是非常困难的!有这么多的理论在流传,对正在发生的事情有一个基础的理解是非常重要的。
学习 Qiskit 真的很有趣,IBM Research 提供的文档和资源对我理解正在发生的事情帮助很大。在包括 Google Cirq 和 QuTiP 在内的所有量子处理器中,Qiskit 是最容易学习和实现电路的。
量子计算正以充满希望的速度前进。研究人员正在普及量子计算机的使用,以执行任务和解决曾经被认为不可能解决的问题。
但是,量子计算理论还没有达到让所有人都能完全接触到的阶段。这可能是由于量子计算机的笨拙,庞大的设备和保持该领域活跃所需的大量资源。
尽管如此,希望这篇文章能让你深入了解这个领域正在发生的事情,并激发你的兴趣!如果你有任何问题或想谈论什么,你可以在推特(Twitter)或领英(LinkedIn)上看到我公然拖延。
我的下一篇文章可能会关注量子计算背后的数学,以及不同的门和逻辑如何操纵量子位。我们将简要介绍量子算法以及它们是如何工作的!
在那之前,我们下一集再见!
里沙卜·阿南德的原创文章
相关文章
一定要看看我关于技术和机器学习的其他文章,以及对未来软件创新的评论。
[## 量子计算速成班使用非常丰富多彩的图表
几乎所有你需要知道的关于量子计算的东西都用非常直观的图画来解释…
towardsdatascience.com](/quantum-computing-with-colorful-diagrams-8f7861cfb6da) [## 遗传算法综合指南(以及如何编码)
遗传算法的起源
medium.com](https://medium.com/sigmoid/https-medium-com-rishabh-anand-on-the-origin-of-genetic-algorithms-fc927d2e11e0) [## CatGAN:使用 GANs 生成猫脸
GANs 的详细回顾以及如何跟他们浪费时间…
hackernoon.com](https://hackernoon.com/catgan-cat-face-generation-using-gans-f44663586d6b) [## TensorFlow.js 简介🎉
在浏览器上运行 ML 模型变得更加容易!
hackernoon.com](https://hackernoon.com/introducing-tensorflow-js-3f31d70f5904)
R 中的业务分析
原文:https://towardsdatascience.com/business-analysis-in-r-part-1-advanced-filtering-and-conditional-calculations-c6b3ef7eb7a2?source=collection_archive---------8-----------------------
您会发现许多关于人们分析不同数据集的优秀文章,但很难在 R 中找到与业务分析相关的材料。这是我在 R 系列中开始这篇业务分析的主要原因之一,这样我就可以分享一些有用的方法,让您可以更有效地分析工作中的数据。在我们继续之前,我建议您对 r 中的 Tidyverse 包有一个基本的了解
在这个数据集中,我将尝试复制我在工作中做的一些任务,你会发现这些真的很有用。您将会看到 R 与 Excel 相比有多么强大。
加载库
加载我们将用于数据管理和分析的以下库
library(tidyverse) ## A set of tools for Data manipulation and visualization
library(lubridate) ## for date time manipulation
library(scales) ## Formatting numbers and values
library(hrbrthemes)# For changing ggplot theme
library(extrafont) # More font options
读取数据
我使用 read_csv 函数读入数据。只需将文件的路径复制到机器上的任何位置,并将“\”替换为“\”。我总是将 trim_ws 参数设置为 TRUE,以防数据中有任何空白。如果它保存为 excel 文件,您可以从 readxl 包中调用 read_excel 函数,基本上遵循相同的原则
supermarket_sales <- read_csv("C:\\Users\\Hamza\\Downloads\\supermarket_sales - Sheet1.csv",trim_ws = TRUE)
查看数据
View() 是一个非常方便的功能,它允许你以类似 excel 电子表格的格式查看你的数据,如下所示。我还将使用 glimpse 函数来检查数据类型
supermarket_sales %>% View()glimpse(supermarket_sales)
Output from View function
Output of glimpse function
看起来我需要修复我的日期和时间列,并将它们转换成正确的格式。我将把时间列四舍五入到最*的小时,并将日期列转换为日期格式。之后,我们将创建一个显示星期几的新列。
supermarket_sales <- supermarket_sales %>%
mutate(Time=as.POSIXct(Time),Time=hour(Time),
Date=mdy(Date),weekday = wday(Date,label = TRUE))
我首先将时间列改为日期-时间类型,并从中提取小时。 Lubridate 包中的 mdy 函数允许我将 Date 列格式化为我从中提取工作日的日期类型
分析
让我们从一些探索性的数据分析开始。虽然我们将揭示数据中的不同见解,但这里的主要焦点是让您了解如何在 r 中获得期望的结果。一旦您了解了代码是如何工作的,您就可以以任何方式分析和探索它。
条形图和多面条形图
我们将绘制一些条形图,以深入了解与一周中的某一天和某个时间相关的总销售额
## Creating a summary
sales_by_day <- supermarket_sales %>% group_by(weekday) %>%
summarise(Total_Sales=sum(Total)) %>% ungroup##Visualizing summary datasales_by_day %>%
ggplot(aes(reorder(weekday,Total_Sales),Total_Sales,fill=weekday))+
geom_col(show.legend = FALSE,color="black")+
geom_text(aes(label=comma(Total_Sales)),size=3,hjust=1,color="black")+
scale_y_comma()+
scale_fill_brewer(palette = "Paired")+
coord_flip()+
theme_classic()+
labs(title = "Total Sales breakdown by Weekday and Time",x="Hour of the day",y= "Total sales")
Sales by day
## Summarizing by day and hoursales_by_day_hour <- supermarket_sales %>% group_by(weekday,Time) %>%
summarise(Total_Sales=sum(Total)) %>% ungroup()## Visualizingsales_by_day_hour %>%
mutate(Time=fct_reorder(Time,Total_Sales)) %>%
ggplot(aes(Time,Total_Sales,fill=weekday))+
geom_col(show.legend = FALSE,color="black")+
geom_text(aes(label=comma(Total_Sales)),size=3,hjust=1,color="black")+
scale_y_comma()+
scale_fill_brewer(palette = "Paired")+
facet_wrap(~weekday,scales="free_y")+
coord_flip()+
theme_classic()+
labs(title = "Total Sales breakdown by Weekday and Time",x="Hour of the day",y= "Total sales")
曲线图
我们现在将探讨不同性别的销售额如何随着时间的推移而变化。
supermarket_sales %>%
group_by(Monthly=floor_date(Date,unit = "1 weeks"),Gender) %>%
summarise(Total_Sales=sum(Total)) %>%
ggplot(aes(Monthly,Total_Sales))+
geom_line(aes(color=Gender),size=1)+
theme_light()+
scale_y_comma()+
labs(title = "Total Sales over time by Gender",subtitle = "Sales for men increased over time",y="Total Sales",x="")
高级过滤
r 有一些真正强大的数据过滤选项,是其他工具如 Excel 所没有的。例如,我想筛选高于女性*均销售额的销售额。
supermarket_sales %>%
filter(Total > mean(Total[Gender=="Female"]))
All sales greater than the average sale of females
你甚至可以更进一步。让我们筛选出高于女性健康和美容产品*均销售额的销售额。
supermarket_sales %>%
filter(Total > mean(Total[Gender=="Female"&`Product line`=="Health and beauty"]))
这很简单。我所要做的就是在计算*均值时为产品线添加一个额外的过滤上下文。
有时,您不知道基于字符的列中的确切字符串,具体地键入每个字符串会很痛苦。这是您可以使用正则表达式来简化事情的地方。
supermarket_sales %>%
filter(str_detect(`Product line`,regex("sport|beauty",ignore_case = TRUE)))
基本上,我过滤的数据在产品线列中包含以下字符串。还有一个否定参数,您可以将其设置为真,它将只显示不包含这些字符串的结果。
supermarket_sales %>%
filter(str_detect(`Product line`,regex("sport|beauty",ignore_case = TRUE),negate = TRUE))
分组依据和汇总
这可能是你最常使用的功能。你可能在 R 中看到过很多教程,在那里人们使用这些函数,但是它们只显示了基本的内容,比如 sum,mean,或 count。但是在现实中,你要计算很多我很少看到任何教程涵盖的条件计算。我将从基本计算开始,然后转向条件计算。
让我们按城市来看看我们的销售情况。
supermarket_sales %>%
group_by(City) %>%
summarise(Total_Sales= sum(Total)) %>%
arrange(desc(Total_Sales))
这是一个简单的计算。我只是将数据按城市分组,计算总销售额,并按最大销售额排列。
现在,如果我们想计算每个城市的分支机构 A 的销售额,我们将这样做。
supermarket_sales %>%
group_by(City) %>%
summarise(Total_Sales= sum(Total[Branch=="A"])) %>%
arrange(desc(Total_Sales))
我们使用 [] 来添加一个过滤上下文,与我们之前过滤数据的方式相同。这是我如何计算我所有的条件计算。让我们针对不同的产品和支付类型再做一次
supermarket_sales %>%
group_by(City) %>%
summarise(Total_Sales= sum(Total[Payment %in%c("Cash","Credit card")&
str_detect(`Product line`,regex("sport|beauty",ignore_case = TRUE))])) %>%
arrange(desc(Total_Sales))
这可能看起来有点复杂,但是当我们分解它时,它是非常简单的。我做了一个条件求和,其中付款等于现金 或信用卡以及名称中包含运动或美容的产品。我像以前一样使用 str_detect ,结合 regex 来获得我想要的产品,因为我懒得输入它们的长名称。
这些条件计算的可能性是无限的,我在工作中一直在使用它们。有时你还必须在工作中进行基于时间的计算。例如,本年销售额和去年同期销售额。我们可以通过遵循与上面相同的原则并结合 L ubridate 包的帮助来实现,这个包允许我们操作日期值。
supermarket_sales %>%
group_by(City) %>%
summarise(Total_Sales= sum(Total[Date %within% interval("2019-01-01","2019-03-31")]),
Same_period_LY=sum(Total[Date %within% interval("2018-01-01","2018-03-31")]))
在这里,我使用了% 内的%和间隔函数来指定我想要聚合的日期。不要担心没有 2018 年的数据,因为没有,但我只是想让你理解这个概念。我真的很喜欢这些“时间智能”计算,因为这些功能让我可以随心所欲地具体。
Time intelligence calculation
结论
这些是我在工作中用来分析数据的一些函数。我将在 R 系列中继续我的业务分析,分享一些非常酷和有用的方法,告诉你如何在 R 中更有效地分析你的业务数据。
商业分析充满了确认偏见
原文:https://towardsdatascience.com/business-analytics-is-ridden-with-confirmation-bias-c60e077d81dd?source=collection_archive---------21-----------------------
通过正确的流程,您可以控制它
几个月前,我发表了一篇关于如何运行世界级商业分析功能的会议演讲。就像这些事件一样,紧接着,许多人向我提出了许多问题。虽然试图回答所有问题可能会很累,但这实际上是我最喜欢的部分,因为它帮助我了解商业分析人员面临的日常问题。
我有一次难忘的谈话是和一个人,她看起来真的对给出“令人满意的”分析结果的压力感到沮丧。她描述了几个月前的一种情况,当时她承受着巨大的压力,要找到一个事实——任何一个事实——来支持她的客户所做的断言。尽管她尽了最大努力,但她最终还是屈服了,向客户提供了一个事实,尽管还有许多其他事实不支持这一说法。她告诉我,客户明确表示,他们只想听到有助于他们实现目标的事实,对反驳不感兴趣。在这种情况下,她感到无助,最后为了摆脱自己的工作,继续前进,她变得温和了,但她显然对自己允许这种事情发生感到非常厌恶。
这种确认偏见在商业世界很普遍,许多人会说它在学术界也无处不在。它可能不总是像我刚才举的例子那样极端地表现出来,但是它经常隐藏在明显的地方。我敢肯定,许多读者都会遇到这样的情况:他们只寻找事实来支持一个论点,而排除了所有其他相关的事实。
我们为什么要担心确认偏差?
确认偏见对任何人都没有帮助,尤其是遭受这种偏见的企业或组织。缺乏对不同观点的开放,增加了决策者与根深蒂固的观点发生分歧的机会,这反过来又增加了错误决策或根本不决策的机会(决策瘫痪)。
在分析环境中,我经常看到确认偏差以三种方式表现出来:
- 在开始的时候,它可以以分析被请求的方式来表现自己。组织中有人有一个议程或目标,并希望使用分析来支持它。所以他们的问题会带有确认偏见:你有证据支持吗…?找到显示… 的数据
- 在中间,一个常见的行为是要求在子群或不同的时间框架内重新进行分析,直到最终得出令人满意的结论。如果我们只将时间限制在过去 3 个月,这意味着什么?仅限美国的情况如何?
- 最后,分析师提供的分析以一种看起来支持预期结论的方式被改写,通常忽略分析师对此的警告。
在个人专注于寻找支持理想结论的数据时,他们往往不能后退一步,意识到——通过忽略反驳或以不*衡的方式进行分析——他们可能没有为企业做出正确的决策。
控制确认偏差
我不支持去偏见化。你不能消除偏见。但是,你可以控制它。做到这一点的最佳方式是引入结构化的、一致的流程,减少偏见发挥作用的机会。
发现确认偏差的最佳时间点是最初请求分析的时候。在这一点上,可以向请求者简要介绍分析小组的中立价值观和公正方法,并且可以用支持*衡的、基于证据的方法的方式来表述请求。
当您收到分析请求时,假设这不仅仅是简单的原始数据提取,您可以考虑以下一些方法来控制确认偏差:
- 一开始就写一份服务章程与客户分享。除了包含周转时间等承诺之外,它还可以用来明确团队基于证据的价值观,并让客户同意以与这些价值观一致的方式工作。例如,同意对问题采取不偏不倚的态度,承诺不在未经协商的情况下修改事后的结论。
- 确保分析请求以中立问题而非目标的形式表达。坏消息:我们正在寻找能证明销售下降的数据,因为自从我们的办公室搬迁后,客户现在离我们更远了。好:根据我们的数据,最*销售下降的可能原因是什么?
- 向客户汇报分析结果,并记录结果和汇报。向客户汇报有助于避免对结果的误解,并可以预先要求更深入的挖掘。保留记录意味着,如果结果被误解或误用,可以在以后进行干预。
确保所有这些一致发生的一个方法是建立一个接收和处理分析请求的标准流程。例如,您可以创建一个分析请求表或问题陈述,需要在客户和分析师之间完成并达成一致。我举了一个例子来说明这一点:
Illustrative example of a standardized problem statement sheet for an analytic request
如果业务分析职能的作用是支持组织中的准确决策,那么它必须有一种方法来对抗确认偏差,并可以为其客户提供*衡的分析视角。通过安装正确的流程并鼓励客户遵循它们,你可以朝着这个目标取得很大进展。
最初我是一名纯粹的数学家,后来我成为了一名心理计量学家和数据科学家。我热衷于将所有这些学科的严谨性应用到复杂的人的问题上。我也是一个编码极客和日本 RPG 的超级粉丝。在 LinkedIn 或Twitter上找我。
数据科学家的业务基础
原文:https://towardsdatascience.com/business-basics-for-data-scientists-862f116a82da?source=collection_archive---------13-----------------------
人工智能项目管理
使用你的机器学习能力来影响基本的商业方程式。
T 这位初出茅庐的数据科学家专注于掌握 TensorFlow &统计概念。这无疑是重要的。然而,太多人忘记了成为高质量数据科学家的第三层。通过了解业务视角,对您的数据科学技能集进行最后的润色。
Photo by Samson Creative. on Unsplash
这篇文章探讨了每个数据科学家都应该理解的基本业务等式。该内容旨在培养希望通过其工作产生切实影响的技术数据科学家。了解机器学习能在你的公司发挥什么作用,如何寻找机会。
让题外话开始吧。💰
基本的商业等式
企业的目标是赚钱。正如张秀坤·海茨所言,数据科学家被雇佣来帮助公司实现这一目标。你如何定义「赚钱」?
在数据科学中,准确性由样本总数中正确分类的样本数来定义。同样,利润是由收入和成本这两个变量定义的。
利润是收入和成本之间的差额。我们有一个等式——holla!让我们解释一下每个变量。
收入是你的公司赚的钱的总数。想想你高中的柠檬水摊。顾客花在购买美味提神饮料上的每一块钱都会计入你柠檬水摊的收入。🍋
Photo by Rod Long on Unsplash
成本描述了你的公司花费的所有金钱。对于柠檬水摊位,这是柠檬的价格,租用摊位的费用,以及你虚构的工资,等等。
利润是你的公司赚的钱和花的钱之间的差额。对你的柠檬水摊来说,这是你把柠檬钱还给妈妈后,你口袋里剩下的所有钱。💁
所有这些与您作为数据科学家的工作有什么关系?现在我们知道了基本业务等式中的关键变量,让我们来谈谈你的角色。
向利润优化
因此,在全体会议上,这些西装革履的家伙一直在喋喋不休地谈论利润增长、危险的竞争对手和新的商业模式。🤵当他们继续让观众感到厌烦时,你的思绪又回到了超级简单却又基本的商业方程式上。然后你就有了想法——Bazinga!就像在机器学习中一样,你会遇到一个优化问题。厉害!我们优化的关键指标是利润。
如果你是一个魔术师,你认为为了最大化利润,你可以增加收入,降低成本,或者两者兼而有之。让我们来谈谈你在机器学习方面的工作如何影响这两个变量。
超级机器学习
作为一名数据科学家,你有幸拥有机器学习的超能力。你尽情享用数据,并将其转化为超人的预测,为令人难以置信的产品提供动力。让我们来探索如何明智地使用你的力量,卢克。⭐️
Photo by Lopez Robin on Unsplash
Landing.ai 创始人、前谷歌和百度大脑负责人吴恩达表示,机器学习以三种方式产生价值:
- 创造新产品
- 改进现有产品
- 自动化流程
让我们看一下每个类别的例子。
创造新产品
机器学习帮助你的公司创造全新的产品来增加收入。一个例子是由自动驾驶汽车驱动的新型移动服务,也被称为机器人出租车。没有机器学习,这个新产品是很难创造出来的。在这种情况下,机器学习允许公司开发全新的产品来增加收入。
人工智能(“AI”)驱动的产品的圣杯是进入 AI 良性循环的产品。这一切都始于一个产品,它在没有人工智能的情况下已经很好,但随着更多用户和更多数据的增加而不断改进。
特斯拉就是一个很好的例子。特斯拉汽车在没有人工智能的情况下驾驶很有趣,但随着更多用户收集数据,它会不断改进。这使得特斯拉自动驾驶更加令人愉快。特斯拉首席执行官埃隆·马斯克估计,他的公司收集了全球汽车数据的 99.5%。特斯拉准备好了吗?
Source: https://landing.ai/ai-transformation-playbook/
在寻找潜在的新产品时,你可以做四件事:
- 评估竞争对手的产品。他们是否在提供客户想要的产品,并且你可以通过人工智能来模仿?
- 放眼其他行业。你能从这个聊天机器人 AI 公司学到一个有趣的方法吗?
- 集思广益。在黑客马拉松中,你能想出一个很酷的主意吗?
- 检查您的数据。你能利用这些数据创造一个新的人工智能产品吗?
机器学习通过创造新产品来增加利润,从而增加收入。你也可以用你的超能力改进现有的产品。
改进现有产品
既然你的公司存在,它就有产品或服务在销售。
Popular item recommender from is24.de for new users
如果你在一家数字企业工作,推荐系统很有可能存在。在上面的例子中,你可以看到德国领先的房地产网站推荐的热门商品。它向我推荐瑞典的房子——这与我无关。
很多公司仍然使用热门商品推荐器。这些又甜又傻的算法显示了哪些产品是你公司最常购买的。有了机器学习,你可以构建一个漂亮的算法,提供定制的建议。
直接与产品经理交谈,了解如何改进现有产品。你有关于机器学习的知识,他们对他们的产品了如指掌。他们知道未来的挑战和路线图。你们将一起想出一个改进现有产品的好方法。
你已经看到了如何通过机器学习创造新产品或改进现有产品来增加收入。然而,机器学习也可以降低成本。让我们看看下一步该怎么做。
自动化流程
机器学习通过自动化流程来降低成本。每个公司都有创造产品的成本。像计算机视觉或自然语言理解这样的机器学习任务可以完美地支持过程。公司规模越大,可以自动化的重复性任务的可能性就越大。这通常被称为机器人流程自动化 RPA 。
Automating dancing. So helpful.
使用 RPA 降低成本的一个很好的例子是在制造过程中自动进行目视检查。目视检查是用眼睛检查产品的过程。想象一下,一队人正在检查新生产的汽车的外表是否有划痕。奥迪利用计算机视觉自动化了这一过程。Landing.ai 是一家专注于这项任务的公司。
Visual inspection of a manufactured good.
为了识别过程自动化的任务,寻找需要有限认知能力的重复性任务。吴恩达给出了一条经验法则,即任何人类不到一秒钟就能完成的事情,都有可能实现自动化。这样你可以降低成本,影响公司的盈利能力。
这是通过自动化流程降低成本的一个很好的例子。现在我们知道了如何通过机器学习来影响利润,让我们优先考虑你的下一个项目。
应用基本业务等式
管理顾问专注于增加收入,而不是降低成本。降低成本会对现有产品的质量造成意想不到的后果。这再次导致收入下降。
成本前收入。——哈佛商业评论
Photo by Franki Chamaki on Unsplash
另外,想出伟大的新产品更有趣。这一观点同样适用于非营利组织和政府组织。因此,一般的建议是先增加收入,再降低成本。
关键要点
作为一名数据科学家,你可以通过优化公司业绩来获取利润。你知道如何通过增加收入或降低成本来影响利润。你已经走了这么远,现在省点力气工作吧。
Photo by Roman Kraft on Unsplash
- 向利润优化
- 利润=收入-成本
- 成本前收入
- 通过创造新产品或改进现有产品来增加收入
- 通过自动化任务降低成本
接下来,使用人工智能项目画布向管理层推销你对利润有影响的想法。
这篇文章是正在进行的教育数据科学家成为商业头脑的系列文章的继续。该系列旨在帮助您完善您的整体数据科学家技能。如果你喜欢这种形式,请在 LinkedIn 或 Medium 上关注我,了解最新文章。
Photo by Miguel Bruna on Unsplash
商业智能在用户参与问题中的应用
原文:https://towardsdatascience.com/business-intelligence-applied-to-a-user-engagement-problem-8e215d8f8cda?source=collection_archive---------17-----------------------
语境
公司经常关注并愿意利用数据来获得关于问题所在以及如何解决问题的指导的一个关键领域与消费者保留或用户参与有关。
因此,让我们假设我们是为一家科技公司工作的分析师,该公司最重要的 KPI 围绕着客户如何使用其主要产品。一种类似于工作场所内部社交网络的产品,用户可以像他们一样发送和接收个人或群体消息,共享文档,查看收件箱,发表想法,以及搜索来自同一公司其他用户的信息。出于简化的目的,我们将其称为“Hub”。
Hub 被出售给世界各地的几家公司,以便其员工可以使用通信工具。他们可以免费使用它,但公司要为此付费。
数据
数据由 3 个表组成:用户、事件和电子邮件。
第一个表收集用户的基本信息,即标识号、帐户状态、销售线索注册的日期、销售线索完成注册过程并成为用户的日期、用户工作的语言和公司。该表被称为用户。
第二个表称为 events,收集用户与产品的交互信息、交互类型、交互的日期和时间、位置以及使用的设备。
最后一个表格叫做电子邮件,是关于我们公司和用户之间的电子邮件互动的用户反应。它仅限于以每周内容摘要的形式发送的电子邮件,以促进参与。
数据,以及完整版本的代码,可以在我的 Github repo 中找到这个项目。
工作流程
上述数据集被推送到 PostgreSQL 数据库。另一方面,包含 psycopg2 适配器的 SQLalchemy 库允许我们通过其引擎模块混合 postgreSQL 数据库和 Python 之间的工作流,以便我们可以在不离开笔记本的情况下用 SQL 语言运行我们的查询,这意味着 Python 可以顺利地接管被查询的数据帧,以执行进一步的数据操作和可视化。
Snippet code of the “create_engine” module of SQLalchemy that enables the blended workflow
这个问题。用户参与度的下降
八月底到了,当回顾关键指标仪表板时,有些事情很突出(见下图)。用户参与度有所下降。
在这种情况下,参与度被定义为与产品交互的服务器调用,换句话说,当用户在给定的一周内登录到 Hub 时,他/她正在参与产品。因此,用户不登录,因此不参与,肯定对业务不利,所以作为一名分析师,您想知道发生了什么,并准备好处理数据库以获得见解并指导可能的纠正措施。
问题的潜在来源
在开始询问之前,建议考虑所有可能导致用户参与度下降的因素。以下是我想到的关于这个案例的一些例子:
- 节假日。在许多国家,尤其是位于北半球的国家,8 月是休假人数最多的月份,所以这很可能是休假人数下降的原因。
- 性能问题。很多时候,电子商务、市场或技术公司中的主要问题来源于与网站/应用程序的纯粹交互,它可能会对用户或其他人产生不同的影响,这仅取决于用于登录的设备类型和操作系统。也有可能是技术团队在 web/app 前端引入了一项改变,影响了某个特定的功能,从而对参与度产生了直接的负面影响。网站加载缓慢或会话导航中的功能损坏可能会导致用户体验不佳,导致产品参与度降低。
- 报名特征流程。为了让销售线索成为能够登录并使用该产品的用户,他/她必须首先完成注册流程的每个步骤。例如,可能会出现这样的情况:流程的任何功能都存在技术问题,这可能会阻止新用户注册,从而错过新手的新参与贡献,这自然会抵消系统的流失。
- 跟踪日志破损。还可能发生的情况是,标识每个用户操作的代码/日志本身被破坏或受到影响。看到某个特定的使用特性下降到绝对为零,暗示问题来自这个方向。
- 坏数据。我们可能会存储“脏”产品流量的记录,这意味着不是来自真实用户的记录,而真实用户才是我们感兴趣的。例如,QA 可能会开发和测试一个新的特性或新的技术基础设施。通常,QA 和生产数据是分开的,但是由于小故障导致的 QA 活动可能最终与真实的外部用户流量混合在一起。另一种解释这种不良数据的可能性可能来自机器人,由于这些相同的变化,现在以不同的方式在网络上爬行,因此导致流量记录波动。
- 与摘要电子邮件相关的技术问题。它们以每周摘要的形式从 Hub 内容团队发出。它们旨在通过总结前一周的活动和同事的活动来吸引客户并培养参与度。
让我们逐一分析这些要素。
假日
下面的查询试图找出 8 月份活跃用户数量多于 7 月份的国家。为了将假期视为用户参与度下降的原因,我们希望在查询输出中看到 8 月不是主要休假月份的国家的列表,我们希望这些国家或者是传统上主要休假月份不是特定月份的国家,或者是因为位于南半球等原因的国家。
我是西班牙人,我可以说八月是传统上最主要的度假月份。例如,据我所知,希腊也是如此。
因此,认为假期是用户参与度下降的原因让我有些沮丧。我宁愿调查其他可能的原因,而不是深究这个原因。
以下是西班牙和希腊每月的参与用户情况。
如果这是 Hub 用户参与度整体下降的实际原因,我们预计本月的活跃用户会有所增加。
性能问题
设备类型
为了了解在与产品的交互中是否存在某种性能问题,查看特定的操作系统或设备是否受到特别的影响可能会很有意思。
上图显示,参与度的下降来自各个方面,但对于通过手机和*板电脑登录的用户来说,这种下降尤为明显。最重要的是,笔记本电脑用户的比例高于其他类型的设备,因此按比例来说,这一下降在各组之间有很大不同。
让我们来看看从 7 月到 8 月这些比例是如何变化的。
设备类型与用户参与度变化之间的差异非常大,足以将此列为解释用户参与度下降的一个可能原因。这并不意味着这是肯定的原因,但看看这些数据,有些事情是可疑的,值得进一步调查。例如,与技术团队交谈,了解他们是否正在调整应用程序中的某些内容(通过手机和*板电脑使用,而不是通过 PC/笔记本电脑),以便从他们的开发中找出潜在的问题,这可能是有用的。
操作系统
与上面针对设备类型所示的方式相同,该分析也可以按操作系统进行分解(顺便说一下,操作系统在一定程度上与设备类型相关)。
上面的图表告诉我们,下降似乎主要来自苹果和安卓用户,这在一定程度上与之前我们看到的设备类型效应的图表有关。
让我们通过观察每个操作系统从 7 月到 8 月的比例变化来理解这种影响的相对大小。
与之前的发现一致,手机和*板电脑似乎积累了更大比例的用户参与度下降,如最后一张图表所示,尤其是 android 设备。
然而,如果这是问题的唯一来源,为什么 window 笔记本电脑的用户参与度会下降,尽管不太明显,但仍然是下降?
让我们继续调查其他可能的原因。
注册特征流程
第一,方便查看每月新增用户。
紫色线显示每月新增用户的变化,连接到左侧的 Y 轴,而条形显示每月新增用户的百分比变化,连接到右侧的 Y 轴。
通过阅读图表,我们可以看到,在 2013 年至 2014 年的时间跨度内,用户获取量呈现出明显的上升趋势。特别是,如果我们注意最*的夏季(这是用户参与度下降分析的中心),与 7 月(2014 年)相比,2014 年 8 月的新用户数量实际上有所增加。仅此一点就足以排除注册流程中的一个问题作为我们问题的原因之一。
然而,由于用户获取增长率在 8 月份明显放缓,仔细研究一下注册流程步骤是安全的。
并在 8 月前的几个月内捕获。
正如我们所看到的,注册流程漏斗的所有步骤在不同的月份中保持着相对于彼此的比例,因此我们可以安全地排除这个流程中的技术问题作为我们问题的根本原因。
破损的跟踪日志
可能的情况是,由于日志(用户在与产品交互时采取的每一个动作的标识符)的问题,使用流程中的某些特定功能无法被跟踪。
事实并非如此。所有事件都有一个普遍的下降,以至于它们看起来是同步移动的。让我们放大到 7 月-8 月,看看它的相对比例。
事实上,在参与度下降是如何通过它们形成的方面存在一些差异,但它们似乎并不太相关,不需要考虑属于它们中任何一个的跟踪日志被破坏的情况。
错误数据
为了确定这是否是原因,我们需要查看用户的活动,并检查其中一些用户是否有异常活动。这将导致人为活动,或者换句话说,某种类型的峰值/不寻常的上升,在我们的情况下,在 7 月份进行可能是有意义的。如果这是真的,我们可以说 8 月份用户参与度的下降并不是这样,因为这是一个前一个月虚假用户参与度的问题。
首先,让我们检查是否有任何人开始接触网络但没有登录,这将指向那些奇怪的事情,如某人不需要注册成为记录日志的一部分(类似机器人的行为)。
这意味着产品交互的每一条记录都是在登录之后产生的。
其次,让我们看看一周内是否有一些日子有不寻常的活动。
我们可以看到,一周内有一个系统的波动,工作日的枢纽活动较多,周末自然较少,最相关的可能是 7 月下半月的高峰,虽然看起来不是特别高,但不能草率排除,因此值得深入研究。
第三,检查在该时间段内某一天是否有日志事件数据可用,以及是否有非常不寻常的活动,这也很有帮助。
似乎确实有一些日子有不寻常的活动,但很难说这是非常不寻常的。如果 7 月至 8 月的用户参与度变化背后有糟糕的数据,我们预计这些数据将集中在 7 月。让我们找出答案。
因为我可能认为我们在谈论不寻常的活动,在某一天内来自单个用户的多达 70 个事件,所以让我们考虑离群值的存在,不管是不是假的,但是离群值。
为了描述异常值,我们需要从数据的分位数范围(IQR)中定义一个阈值。这是我做这件事的方法。
首先我们得到了 IQR。
然后可以用它来隔离异常值。
从上面的柱状图中可以得出两点:第一,从异常值(或潜在的坏/假数据)来看,7 月份似乎没有异常的活跃,事实上,与前几个月类似。第二个是,8 月份离群值的互动确实很低。
这打开了许多场景,需要根据优先级进行进一步的调查,以便对它们有更多的了解。在这些人当中,我会突出这些人。
- 搜索引擎抓取网站的方式可能在 8 月份发生了变化,这可以解释这个月的大幅下降。一种可能的方法是进一步分析用户模式并对其进行聚类。这将有助于识别机器人,然后验证所寻求的用户参与度下降是否来自于它们活动的减少。
- 过去几个月的重要产品开发伴随着紧张的质量保证工作,这些工作在 8 月前完成。出于某种原因,QA 数据进入了生产日志,并且干扰了指标。我认为不太可能,但与产品开发部门核实一下也无妨。
- 在其他方面解释了其他原因,例如导致性能下降的技术问题,从而使那些最活跃的用户在糟糕的用户体验后做出反应,只是减少参与。
每周摘要电子邮件
如前所述,在列出问题的所有可能来源时,这些电子邮件是 Hub 的客户和内容团队用来促进用户参与的工具。它们是与每个用户相关的信息的汇总。
所以让我们看看数据是否能告诉我们一些关于它们的有趣的事情。普通数据被进一步操纵成关键利率。
事实上,有些东西立刻就凸显出来了。虽然几个月来每周摘要邮件的打开率保持不变,但我们可以清楚地看到,点击率在 8 月份从 50%左右下降到 30%左右。也就是说,三分之二的用户不太关心这些互动电子邮件,然而在那些关心的用户中,在 8 月份之前,有二分之一的用户通过点击这些电子邮件中的链接重新参与到产品中,而在 8 月份,这一数字变成了三分之一的用户在电子邮件后重新参与。简而言之,从 7 月到 8 月,每周摘要邮件的有效性下降了 35%,直接导致用户参与度下降。
要么是电子邮件链接本身存在技术问题,导致用户无法点击进入,要么是选择与每个用户相关的内容并通过电子邮件发送的方式发生了变化(无论是来自算法还是专业团队)。
结论
列出许多旨在解释用户参与度下降的不同可能原因,对于减少我们忽略问题真正根源的机会非常有用。然后,每个查询都允许我们为分析消费准备好数据。根据这一分析,似乎影响手机和*板电脑用户的应用程序导航以及互动电子邮件的内容存在问题。
值得注意的是,这些发现并不是结论性的,可能需要向产品和技术团队提出进一步的问题,但至少我们已经能够有一个良好的开端来找到一个令人困扰的问题的答案。
作为数据科学家的商业智能—第 1 部分
原文:https://towardsdatascience.com/business-intelligence-as-a-data-scientist-part-1-2974655766c5?source=collection_archive---------33-----------------------
我在英国的分析行业呆过一段时间。多年来,商业智能一直主导着分析市场,这是正确的。在我看来,BI 似乎是对分析感兴趣的人和会写一点代码(SQL!).回到 2015 年左右,我希望进入职业生涯的下一个阶段,并决定我基本上有三条道路。我可以:
晋升为光荣的商务智能团队的光荣商务智能经理
作为数据仓库开发人员或 DBA,逐步晋升为 SQL 大师
完全偏离这一切,成为一个统计怪胎。我不确定这对我的商务智能事业有什么帮助,我只是喜欢和数字打交道
这三个选项都不吸引我。但这没关系——因为 2015 年正是数据科学在英国蓬勃发展的时候!数据科学让我着迷——我的职业生涯一直在处理表格数据集,有列和行,人们编写模型来预测 JPEG 中的对象是猫还是狗。我马上抓住了这个机会。我获得了数据科学硕士学位,有了几年的 DS 经验,现在我发现自己又进入了 BI 领域。为什么?因为商业智能很重要。如果你在一家不做 BI 的公司做 DS,那么这绝对是你应该考虑的事情。
我以前从来没有写过博客,甚至没有写过文章,但是在这个系列中,我将作为一个同时从事两种职业的人,把我的想法写在纸上。BI 和 DS 可以从彼此身上学到很多东西——它们有着内在的联系——不要让任何人告诉你它们不是!
第 1 部分—品牌
毫无疑问,我看到的数据科学家最忽视的报告元素是品牌。这里有一些突破:如果你试图用你惊人的蒙特卡罗模拟吸引非技术业务用户,你需要让它看起来很好,否则他们不会感兴趣。当然,我同意 MCS 最重要的元素是运行模拟后获得的统计数据和知识——当然,任何模拟的数字只有在模型设计正确的情况下才有用——但如果因为它看起来太复杂而没有人使用它,那还有什么意义呢?业务用户习惯于以某种方式查看他们的报告,使您的工作符合公司标准绝对是您的工作。
让我们玩一些代码。我们将编写一个蒙特卡洛模拟来玩 n 轮盘赌游戏,看看我们是否赢了钱(剧透:我们没有!).这个模型的交付将是 R 闪亮的,我们将讨论使用默认格式交付这个模型和我们良好的公司品牌之间的区别。所有代码都存放在我的 Github 上。
顺便说一句,很难说蒙特卡洛模拟属于商业智能的范畴——我只是认为它们很有趣。不过,R Shiny 完全可以用作 BI 交付系统——有一些软件包可以帮助编写,例如,可以在整个企业中推广的 KPI 仪表板。BI 和 DS 之间的界限已经模糊了!
Although neither profession will help you win at Roulette —at least you’ll be able to explain why you lost.
所以——让我们设定一些基本规则。我的轮盘上有 37 个数字,从 1 到 36,加上房子 0。每个数字和任何其他数字一样有相同的变化,所以我们可以使用 1:37 范围内的随机数发生器(计算机 RNG 实际上不是随机的是一个整件事——与本文无关,但如果你喜欢这种东西,这是一个有趣的阅读)。
我们来玩 100 个游戏,看看哪个数字赢的最多。
numbers = 1:37 # 36 numbers on a roulette wheel, including 0 = 37n_games = 100 # how many games do you want to play?# Create an empty matrix, n_games long and 37 columns widemat <- matrix(data = 0, nrow=n_games, ncol = max(numbers))# Each game is a row, and the winning number gets a 1 in its cellfor (i in 1:n_games) {current_number = sample(x = numbers, size = 1) #what number came in?mat[i,current_number] <- 1 #whatever number came in, replace it's value with 1}# Create dataframe of winning numberswinners = data.frame("number" = numbers - 1,"wins" = colSums(mat))# Chart itlibrary(ggplot2)ggplot(data=winners, aes(x=number, y=wins)) +geom_bar(stat="identity") +theme_minimal() +ggtitle(paste("Which numbers came in after", n_games, "games of Roulette?"))
Frequency of winning numbers in our random (not really) number generator
在我们的 100 场比赛中,32 号出现的次数最多(8 次),12 号和 35 号之间零胜。零号房只出现过一次——对于我虚构的赌场客人来说,这是个不错的结果。
我们开始下注吧。我们将以 1,000 英镑开始,每局下注 10 英镑。根据我在第一次模拟中的结果,我将玩 100 场游戏,每场游戏都赌 32 号。轮盘赌的赔率是 35 比 1,我们就用这个。如果我的号码中了,从 10 英镑的赌注中,我将获得 360 英镑,即 10*35 +我原来的 10 英镑赌注。在 500 场比赛结束时,我们最终获得的启动资金是多于还是少于 1000 英镑?
我们可以构建一个闪亮的应用程序来玩 100 次游戏 x 。有很多方法可以做到这一点——我创建的“默认”非股票应用程序如下所示:
我使用了优秀的 shinydashboard 作为我的应用程序的基础框架。滑块让我们玩更多的游戏,我们的中奖号码总是 32。第一张图表显示,每玩一次游戏,我们口袋里的钱就会减少,当数字 32 出现时,我们口袋里的钱就会增加。红色和蓝色显示了 100 场比赛后的净盈利/亏损,底部的图表显示了 RNG 中 32 场比赛的出现频率。
100 场打了 100 次,我们*均留下的现金是 1024.9。一万个游戏玩 100 次呢?
The more games played, the less money we leave the casino with
我们玩得越多,输得越多——这当然是赌场赚钱的方式。我玩这个很开心,但是这篇文章是关于品牌的,不是蒙特卡洛模拟!最终,我们将向非技术业务用户展示我们的应用,我向你保证,如果我们稍微清理一下视觉效果,MCS 背后的数学/过程会更容易解释。
我喜欢在 HTML CSS 中做尽可能多的事情,在 ui 中做尽可能少的事情。r 脚本。我绝对不是 HTML 专家,但构建一个与同事共享的模板足够简单,它将处理大量标准格式。每当需要新的格式元素时,可以(也应该)添加这个模板——我的 CSS 只包含这个应用程序所需的最低限度。任何未指定的都将使用 shinydashboard 预设,随着新元素的添加,这些预设可能需要更改。
下面是应用了品牌的仪表板的 a 版本。
Same simulation, better visuals
我们来说说这是怎么回事。我们已经添加了一个漂亮的植物背景(假设这是我们公司的标志),shinydashboard 元素已经格式化以适应背景主题,我们制作的公司字体已经应用到每个地方,ggplots 也已经主题化。我们还添加了一个新的图表来显示所有模拟游戏的收敛*均值——这显示了一个下降趋势,意味着我们玩得越多,损失的钱就越多。
我使用sessions.edu 颜色计算器根据植物背景中的绿色获得补色的 HTML 代码——这些是符合我们公司品牌的美学上令人愉悦的颜色。色彩理论是另一个完整的东西——如果你试图改善你的数据可视化,值得一读。
如上所述,大部分品牌工作都是在 css 文件中完成的。下面我的目录结构显示了存储在 www 文件夹中的 css 文件,它调用 images 目录中的文件。我还存储了数据的硬拷贝——我喜欢这样做是为了重现,以防我们需要将它发送到任何地方。
Directory tree for the casino app
这些事情总是这样——创建这些应用程序没有对错之分。这篇文章中概述的方法对我来说很有效,但我很想看看数据科学社区中的其他人是如何做品牌实践的。蒙特卡洛模拟本质上并不复杂,但很难向非数据人员解释——标记和格式化您的输出将使解释任务变得容易得多!
这就是第 1 部分!你可以在 Github 和 LinkedIn 上找到我——第二部分将与品牌推广 ggplot2 有关,还没有完全解决!
作为数据科学家的商业智能—第 2 部分
原文:https://towardsdatascience.com/business-intelligence-as-a-data-scientist-part-2-b3d45bbdcce?source=collection_archive---------33-----------------------
作为数据科学家的商业智能—第 2 部分
这个博客系列是关于我在商业智能和数据科学领域的工作经历,以及这两个行业之间的交叉。作为数据科学家的商业智能——本系列的第 1 部分谈到了这两种职业之间的相似之处。我坚信数据科学和商业智能有着内在的联系——我将再次讨论这两种职业之间的细微差别,并通过一个例子继续。和以往一样,这个代码保存在我的 Github 上,你可以在 LinkedIn 上找到我。
在这篇文章的讨论部分,我想谈谈商业智能和数据科学之间更广泛的定义和区别。这两项工作涉及相似的工作流程:
RStudio’s definition of “The Data Science Workflow”
让我们做一个简短的,每个步骤一句话:
1.导入您的数据——这可能来自数据仓库、Lake、文本文件、JSON 等等——无论您使用什么数据源
2.整理你的数据——同样,这取决于你正在做的事情的背景,但你可能会过滤掉一些不相关的东西,对丢失的数据做一些事情,清理一些杂乱的数据点 —这一步和接下来的步骤是你将花费大部分时间的地方
3.想象、建模、转化——这不可能用一句话来解释,但我们可以试试!这些步骤包括可视化和探索性数据分析的洗衣机,为您的任务选择一个模型,转换您的数据以适应该模型所需的格式(参见一键编码、特征工程、符号化),特征的可视化和模型性能
4.推断模型的结果—我们的模型说 96%,这个数字是多少?这是准确性吗,准确性是这个问题的正确衡量标准吗?我们需要担心过度拟合或采样误差吗?基线是 98%,因此我们的模型是垃圾吗?
5.如果我们足够幸运到这一步,我们需要做什么来生产这个模型?要么:
a.将模型升级为实时模型,并开始自动创建真实预测(在这一步之后有一个完整的其他工作流程,确保您的模型保持相关,您是否希望自动重新训练等。)
b.传达模型的发现——我经常发现人们对模型的思考方式感兴趣——参见特征重要性,解码黑盒。有时候,找出预测中的重要因素可能比预测本身更有用——我见过企业改变他们的流程,比如不在周二下午向客户发送发票,因为那时客户做了一些奇怪的内部活动,而我们的发票在归档中丢失了。这一结果直接来自一个为预测流媒体环境中支付可靠性而构建的模型,但该模型从未投入使用,因为决策树比即时预测发票更有趣
我承认——上面的工作流是一个数据科学工作流,来自一个非常著名的数据科学来源(RStudio Github page)——显然那些家伙知道他们在说什么!但是,让我们考虑一个商业智能分析师的工作流,他的任务是为其财务部门创建 KPI 仪表板:
1.从数据仓库中查询一些财务数据——数据仓库 ETL 中的导入和整理步骤已经完成
2.对数据进行任何转换/过滤/列插补,使其符合我们财务仪表板的必要格式/形状
3.可视化输出——我们的仪表板是否显示了我们想要它显示的内容?
4.对可视化进行 QA,以确保输出中的数字与经验证的来源相匹配(推断输出?)—如果我们仪表板中显示的总收入与业务中其他地方显示的值不同,那就不好了
5.将工作传达给业务用户。此时,将会发生以下两件事之一:
a.业务用户要求更改您已经完成的工作,在这种情况下,重复步骤 2 到 5
b.业务用户对工作很满意,在这种情况下,下一步是自动化仪表板并升级到实际环境
我高度概括的 5 步商业智能工作流程是否与上图中高度概括的 5 步数据科学工作流程相似?我有点偏向于自己的叙述,并且遗漏了几个步骤——虽然你也可以为 DS 工作流争论这一点——但是在我看来这两个流程并没有很大的不同。我们甚至可以创建一个图表:
Excuse my poor Visio skills!
在我看来相隔不到一百万英里。两个工作流都忽略了一个关键步骤,即两个工作流都从业务用户开始和结束。在每种情况下,都有一个用户在询问分析团队的业务问题。在分析团队施展了他们的魔法之后,我们希望输出能够改变企业的行为方式——这可能不是在周二发送发票,也可能是一个财务仪表板,显示该客户今年迄今为止带来的收入。
这是对两个工作流程的全面概述。数据科学家和商业智能分析师将处理的数据类型有很大不同,因此从技术角度来看,左侧的查询、导入和整理步骤完全不同。除此之外,两种工作流的最终产品也有很大的不同— BI 处理的是精确的历史数据—例如,我们公司上个月的收入是 50,000 英镑。DS 处理非绝对和预测,例如,我们公司下个月的预测收入将是 55,000 英镑,在 95%的置信区间内,在 52,250 英镑和 57,750 英镑之间。除了技术方面,两个工作流的高层次概述显示了我认为的交付端到端产品的相似性。
Obligatory cringeworthy meme for Medium!
无论如何——继续这篇文章的编码部分。作为数据科学家的商业智能第 1 部分谈到了品牌的重要性。总之,业务用户习惯于以某种方式查看他们的报告,让您的工作符合公司标准绝对是您的工作。之前我们构建了一个闪亮的应用——这一次我们将创建一个 ggplot2 包来自动化发布图形的标准化。这并不是一个新的想法——我们将大量借鉴 BBC 新闻数据团队最*出版的标准化食谱。他们的软件包被称为 bb plot——我们的被命名为 snareplot ,以我虚构的公司 Snare Industries 命名。回想起来,我确实应该把我的包叫做花盆——虽然现在有点晚了!
Snareplot 使用了第 1 部分中所有相同的主题元素。配色方案是用 colormind.io 生成的,软件包可以从我的 Github 下载——你可以用 devtools 安装。
Snareplot can help create branded graphics like these — the main work is in building the ggplot itself, snareplot makes the rest of it easy
Snareplot 使用 4 个函数来切换默认的 ggplot2 格式。这些函数是 theme_snare()、scale_colour_snare()、scale_fill_snare()和 finalise_plot()。
让我们建立一个情节。
library(ggplot2)library(snareplot)scatter_data <- iris scatter_plot <- ggplot(data=scatter_data,
aes(x=Petal.Length, y=Petal.Width)) + geom_point(aes(color=Species)) + labs(x=”Petal Length”, y=”Petal Width”, title=”Correlation Plot on the Iris Dataset”)scatter_plot
Standard plot using ggplot2 default formatting
Snareplot 通过在已经构建的 ggplot2 图形上分层来工作。让我们将 theme_snare()应用于 scatter_plot。
scatter_plot <- scatter_plot + theme_snare()scatter_plot
scatter_plot with theme_snare() applied
这里有一些事情正在进行——让我们进入主题 _ 陷阱中的函数。R 文件。本质上,我们正在设置一个字体(通过 extrafont 包),从 ggplot2 中应用 theme_bw(),并从主题中移除大多数元素。这当然可以按照你喜欢的方式定制——我个人喜欢有很少内容的极简主题。
接下来,我们将看看颜色。
接下来的两个函数覆盖 ggplot 中的颜色和填充参数。这就把我们从上面的情节引向了这个:
scatter_plot <- scatter_plot + scale_colour_snare() + theme(legend.title = element_blank(), legend.position = c(0.05, 0.95), legend.justification = c(“left”, “top”)) scatter_plot
Note the extra theme() arguments to move the legend to the top left — this is nothing to do with snareplot, it just looks better in this particular plot to move it to an empty area of the grid.
Scale_colour_snare() 和 scale_fill_snare() 都是通过对绘图应用调色板来工作的。这些都是简单的功能,但是颜色是根据我们的 Snare Industries 品牌选择的,如第 1 部分所述。这里最重要的部分是颜色本身——这些函数只是让用户不必记住要在 scale_colour_manual()中输入哪些 html 值。
snareplot 包中的第四个函数是 finalise_plot()。该函数有两个参数——它寻找一个要“完成”的 ggplot2 对象,并询问用户是否绘制背景。
finalise_plot(plot_variable = scatter_plot, draw_background = TRUE)
很容易看出这个最后的函数是做什么的!当安装软件包并调用该函数时, /data/ 存储库中的图像文件位于绘图的下面。该图像有时会使绘图变得混乱,因此可以通过设置 draw_background = FALSE 来呈现没有该图像的绘图。该函数还在左下方设置了 Snare Industries 数据科学水印,这是为了标记该图,以便我们知道它在业务的任何地方结束,它都来自 Snare Industries 数据科学团队。
Snareplot 中的一切都可以按照您的意愿进行更改——我强烈建议为您的组织研究颜色方案和字体,并在您创建的任何 ggplot2 图形中使用它们。这将为你的团队创建一个品牌标识,并最终帮助吸引业务中的非技术用户。第 1 部分对此谈了很多——品牌是数据科学家工具箱中经常被忽视的技能。
第 2 部分到此为止!和以往一样,所有代码都托管在我的 Github 上,你可以在 LinkedIn 上关注我。
用 Python 进行商业模拟
原文:https://towardsdatascience.com/business-simulations-with-python-a70d6cba92c8?source=collection_archive---------9-----------------------
用蒙特卡罗方法探索客户终身价值和客户获取成本
当我写下 这篇关于数据科学家 的商业战略的文章时,我意识到为营销活动及其产生的新客户群体进行模拟可能会很有趣。
我职业生涯的大部分时间都在金融和投资领域度过。我更习惯于把公司作为一个整体来考虑(在总体水*上分析),而不是在日常水*上。但我确实发现更细致的细节非常有趣。毕竟,如果整体不是部分的总和,那它是什么呢?
了解更多信息的一个好方法是模拟它(使用合理的输入和假设),然后研究结果。你经常会惊讶于几个关键变量之间看似简单的相互作用会产生一些令人惊讶的结果。所以让我们用 Python 来模拟一个营销活动,看看会发生什么。
我们将重点模拟客户终身价值(CLTV)和客户获取成本(CAC),这是许多初创公司(以及上市公司)的关键指标。在我之前的商业战略文章中,我从概念上深入探讨了这些指标,所以如果你想要更多的背景知识,请参考它。
策划营销活动
这个模拟的详细代码可以在我的 GitHub 上找到。但这里是我们正在努力做的事情的高级概述:
- 给定一些输入,如转换率、成本、预算等,定义一个运行营销活动的函数。,我想返回新注册客户的列表。
- 定义一个模拟一群客户的函数— 给定一些关于流失率、消费频率和消费金额的假设,我想模拟这一群客户的表现,并最终计算他们对我的企业的*均终身价值。
- 运行一堆模拟,看看结果的分布。
让我们先写一个运行营销活动的函数。我们可以通过两种方式之一来实现这一点——我们使用一个随机生成的数字来表示每个印象的结果(每个印象有微小的概率变成付费客户),然后汇总我们的结果(使用 for 循环)。或者我们可以利用统计模型。让我们使用后者,因为循环数百万次相当慢。相反,我们可以利用我们的老朋友, 二项分布(这给了我一个链接到我以前博客的借口——如果你不熟悉二项分布,请阅读)。
引用我以前的话:
二项式分布是一系列实验的概率分布,其中每个实验产生一个二元结果,并且每个结果独立于所有其他结果。
每个印象的结果是否真正独立是有争议的,但为了我们的目的,我们可以安全地做出这种假设。这意味着我们可以使用一个随机变量和 一个二项分布 来模拟我们的营销活动。我们的预算和 CPM(来自像谷歌这样的广告供应商的每 1000 次展示的成本)决定了试用的次数。而每次印象的转化率就是成功的概率。下面的函数做了我刚才描述的事情:
# Function for calculating the results of a marketing campaign
def run_campaign(spend, cpm, conversion_rate):
return np.random.binomial(spend/cpm*1000, conversion_rate)
转换率本身只是一个估计值,所以我们也应该在其中加入一些不确定性。对于第一遍,假设我们的转换率呈正态分布是合理的。请注意,我为转换率设置了一个下限,因为负转换率没有意义。
# From the expected conversion rate and stdev of it, get the
# realized conversion rate
def get_conversion_rate(expected, stdev):
conversion_rate = max(expected + np.random.normal()*stdev,
0.000001)
return conversion_rate
现在让我们输入一些信息——花费是我们计划在营销活动上花费的金额,cpm 是 1000 次展示的成本,两个转化率相关变量是我们对转化率期望值和标准偏差的估计。预期转化率看起来很小,其实没那么小。另一种理解方式是,每提供 20,000 次展示,我们就会有一个客户。在你意识到多亏了谷歌,每一千次展示的成本是 2 美元之前,这听起来好像很多——所以 2 万次展示只花了我们 40 美元。
# Budget
spend = 50000
# Cost per thousand
cpm = 2
# Conversion rate
conversion_rate_expected = 0.00005
conversion_rate_stdev = 0.00002
现在让我们试试我们的函数。可变群组规模是我们追求的目标,它是我们营销活动产生的新客户数量。而有了它,我们就可以计算出我们的客户获取成本(CAC) 。 CAC 是我们营销努力的总成本除以我们通过努力获得的客户数量。
# Let's call it to get the number of new customers from our campaign
conversion_rate = get_conversion_rate(conversion_rate_expected,
conversion_rate_stdev)
cohort_size = run_campaign(spend, cpm, conversion_rate)# And calculate our Customer Acquisition cost
CAC = spend/cohort_sizeprint('Customers Gained: ', cohort_size)
print('CAC: ', round(CAC, 2))
运行上面的行会产生以下结果:
获得客户数:1309
CAC(客户获取成本):50000 美元/1309 = 38 美元
当然,如果我们再次运行它,我们会看到不同的值,因为我们已经注入了两层随机性(转化率作为正态分布的随机变量,最终成为客户的人数作为二项式分布的随机变量)。
随着时间的推移模拟客户群体
我们的下一步是编写一些函数来模拟我们的客户群如何随时间变化。每年,这个群体中的一些成员会流失(不再是顾客),而剩下的人会从我们这里购买商品。
我们可以使用一个随机数生成器(生成一个 0 到 1 之间的浮点数,均匀分布)来模拟一个特定的客户是否每年都有变动。逻辑是这样的——对于给定年份群组中的每个客户,我们生成一个随机数。如果我们生成的数量低于最小阈值,则该客户已经取消。为了简单起见,我们假设所有的取消都发生在年初,因此,在他们离开的那一年里,顾客不会从我们这里购买任何东西。
# Function that models the progression of a cohort over time
def simulate_cohort(cohort_size, churn_rate, transactions, price,
retention_cost, yrs=5):
customers_left = []
spending = []
profit = []
for i in range(yrs):
for customer in range(cohort_size):
# Assume cancels happen at the start of the year
# (for simplicity)
churn_random_num = np.random.random()
# Generate a random number between 0 and 1, if less
# than churn_rate then customer has churned and we
# subtract 1 from cohort_size
if churn_random_num <= churn_rate:
cohort_size += -1
# Calculate and record cohort's data
customers_left.append(cohort_size)
spending.append(cohort_size*transactions*price)
profit.append(cohort_size*(transactions*price -\
retention_cost))
return customers_left, spending, profit
接下来,让我们收集输入并运行我们的函数。更实际的是,我们应该假设每个客户每年的保留成本。这是我们每年需要花费的金额,以保持特定客户对我们服务的满意度和忠诚度。请注意,我只预测了 5 年的利润——我们剩余的客户可能在第 6 年仍会购买我们的产品,但为了保守起见,我将假设给定的客户群最多还有 5 年的寿命。
churn_rate = 0.20
# Number of annual transactions per average cohort member
transactions = 6
# Price of goods sold per average transaction
price = 10
# Annual cost of retaining/servicing customer
retention_cost = 20# Run the function
customers_left, spending, profit =\
simulate_cohort(cohort_size, churn_rate, transactions,
price, retention_cost, yrs=5)
我们最感兴趣的产出是利润,即我们的客户群为我们的业务带来的收入,因为这是客户终身价值的主要驱动力。还有其他间接驱动因素,如满意客户的推荐,但我们今天不会在此建模。
在我们计算客户终身价值(CLTV) 之前,我们需要写一个现值函数。随着时间的推移,客户会购买我们的产品(只要他们是客户,每年都会在我们的产品上花一点钱)。这意味着很多收益发生在未来。由于通货膨胀、机会成本和不确定性,未来的美元不如今天的美元值钱。我们可以通过对未来收到的任何款项进行贴现来大致调整这些影响(收到的款项越多,需要贴现的金额就越多)。下面的函数就是这样做的:
def present_value(cashflows, rate):
pvs = []
for i, val in enumerate(cashflows):
pvs.append(val/(1 + rate)**(i+1))
return pvs
我们现在有了计算 CLTV 所需的东西。我们将应用 10%的贴现率将未来收到的利润转换为现值(以今天的美元计算)。对于那些好奇的人来说,贴现率是复杂的,因为我们试图通过一个单一的数字来表达众多的因素(通货膨胀、风险、我们的希望和梦想等)——关于如何正确估计贴现率有大量的文献,所以我在这里就不赘述了。
# Calculate CLTV
rate = 0.10# Get the PV of the profits
pvs = present_value(profit, rate)
# Value of the cohort in today's dollars is sum of PVs
cohort_value = sum(pvs)print('Total Cohort Value: ', int(cohort_value))
print('CLTV: ', int(cohort_value/cohort_size))
print('CLTV-CAC Spread: ', int(cohort_value/cohort_size - CAC))
让我们来看看利润和它们的现值是如何比较的:
Profit and Its Present Value
随着越来越多的客户流失,这个群体(蓝色部分)的利润会随着时间的推移而下降。利润的现值(橙色)以更快的速度下降,因为未来更远的利润折现更大。
现值之和是我们队列的值,我们的 CLTV 是队列值除以队列的初始规模:
总群体价值:113,285 美元
CLTV(客户终身价值):113,285 美元/ 1,309 = 86 美元
CLTV-CAC 利差:$86 - $38 = $48
我们真正关心的价值是 CLTV 和 CAC 之间的利差——如果它是负数,那么我们就不会长久。当然,在某些情况下,负息差是可以的。例如,处于早期阶段的初创公司不顾一切地扩大规模,会花费大量资金来吸引甚至是低价值的客户。这是因为他们的结果分布相当二元(而且他们的风险/回报相当不对称)。如果他们扩张得足够快,他们就会建立成功的企业并变得富有。如果他们没有达到要求的规模,最终失败了,那也是别人的钱(这种态度是多年来资金(尤其是来自风险资本家的资金)变得如此廉价和容易获得的副产品)。
当然,预计未来客户群的传播将是积极的——随着公司和品牌获得动力,CLTV 应该会增加,而 CAC 会下降。
运行 1000 个场景
最后,我们有了所有必要的部分,现在可以运行我们的蒙特卡洛模拟。我们将模拟 1000 次营销活动,这样我们就可以看到结果的分布。
# Simulate 1000 times and look at the distributionscohort_size_list = []
CAC_list = []
CLTV_list = []for i in range(1000):
# Run marketing campaign sim
conversion_rate = get_conversion_rate(conversion_rate_expected,
conversion_rate_stdev)
cohort_size = run_campaign(spend, cpm, conversion_rate)
CAC = spend/cohort_size
# Simulate the resulting cohort
customers_left, spending, profit =\
simulate_cohort(cohort_size, churn_rate, transactions,
price, retention_cost, yrs=5)
cohort_value = sum(present_value(profit, rate))
cohort_size_list.append(cohort_size)
CAC_list.append(CAC)
CLTV_list.append(cohort_value/cohort_size)
# Store simulation results in a dataframe
results_df = pd.DataFrame()
results_df['initial_cohort_size'] = cohort_size_list
results_df['CLTV'] = CLTV_list
results_df['CAC'] = CAC_list
results_df['Spread'] = results_df['CLTV'] - results_df['CAC']
我们的客户群的初始规模可能会有很大差异,因为我们有两层随机性(我们允许每个活动的“真实”转化率有所不同,每个投放出去的印象本身就是一个随机结果的试验):
Initial Cohort Size Distribution
如果队列规模可以变化很大,那么 CAC 也可以变化很大(我们预计它的中值约为 40 美元(因为 or 我们的输入假设)。哇,它真的很宽。CAC 的中位数是 40 美元,但有可能经历可怕的活动回报(很少有客户注册)并获得三位数的 CAC-超过 6%的模拟导致 CAC 达到 100 美元或更高。所以不要做最坏的打算,但要做好准备。
分布的形状很有趣。从 CAC 的角度来看,这是不对称的——如果我们签了很多客户,我们的 CAC 会很低,但它能低到什么程度是有现实限制的(我称之为我们上升的软上限)。但是如果我们没有签下很多客户,我们可能会看到非常高的 CAC,这对我们公司来说是灾难性的。
CAC Distribution
现在让我们看看收入方面的情况,CLTV。由于我建模的方式,这里的差异明显较小。我可以通过在年度流失率或客户交易中注入随机性(通过改变每笔交易的频率和价值)来允许更多的差异。如果我这样做了,钟形曲线会更宽(由于更多的变异和不确定性来源),但仍然会有相同的*均值和一般形状。
CLTV Distribution
最后,让我们看看 CLTV 和 CAC 之间的价差。在这里,我们再次看到一个长尾和软帽,但这一次它是翻转的(因为我们在计算利差时从 CLTV 中减去了 CAC)。它有双重含义:
- 即使我们有一个非常成功的营销活动,我们所能实现的每位客户的收益(以价差衡量)也是有限的。这一限制的存在是因为 CAC 只能降到这么低(例如,在我运行的 1,000 个场景中遇到的最低 CAC 是 16 美元),每个客户只能购买这么多。
- 另一方面,如果我们有一个灾难性的活动,传播很容易是负面的,这意味着由此产生的客户可能永远不会收回他们的收购成本。根据公司所处的阶段和营销活动的规模,这可能不会成为交易的阻碍(这可能只是暂时的、一次性的问题)。但是这应该阻止我们将公司的大部分资产或预算押在一个大规模的活动上——一个失败可能意味着公司的毁灭。
CLTV-CAC Spread Distribution
希望这是有帮助的,干杯!
更多数据科学与分析相关帖子由我:
数据科学家的商业战略
数据科学家是做什么的?
理解贝叶斯定理
理解朴素贝叶斯分类器
二项分布
了解 PCA
数据科学家的商业战略
原文:https://towardsdatascience.com/business-strategy-for-data-scientists-25e3ca0af5ee?source=collection_archive---------11-----------------------
Photo by Skitterphoto from Pexels
在开始机器学习之前,先学习商业策略的基础知识
科学是令人兴奋的。从我们学习第一个机器学习算法的那一刻起,就有一种将它应用于数据、做出预测和揭示深刻见解的冲动。
但是商业方面也非常重要和有趣。我向你保证,在你的数据科学职业生涯中,投入一些时间来了解企业如何运作以及好公司和坏公司的区别将会带来巨大的回报。
这可能是几个帖子中的第一个,因为不可能在一个帖子中公正地处理这个问题。另外,请不要认为这些帖子是 MBA-lite。相反,我计划写一些对我如何看待商业世界影响最大的概念和想法。因此,可能有一些相关的商业策略主题我会完全跳过。当然,如果你真的想从我这里听到什么,请在评论里告诉我(我会尽力的!).
公司成长阶段与数据科学需求
硅谷初创企业尽管如此,做生意的目的是赚取利润。这是否发生以及如何发生主要取决于公司目前所处的阶段:
The growth phases of a company
高速增长—现阶段,销售增长比利润更重要,因此公司可能会承受巨大损失,以赢得越来越多的客户。风险投资家为这种增长提供了动力,其目标是将收入扩大到公司在财务上有足够吸引力进行首次公开募股(IPO)的程度。
由于增长是必需的,超高速增长公司的数据科学家专注于客户获取和产品开发。他们可能要解决的问题包括:
- 定量识别最有吸引力的潜在客户。
- 设计和优化营销策略,如优惠券、推荐活动、社交媒体广告等。
- 研究和开发构成公司产品或服务核心的算法。
上市、增长(不太快)和盈利 —一些私营公司肯定也属于这一类别,但我们现在将专注于上市公司(因为华尔街是这一阶段公司行为的驱动力)。一旦一家公司上市,每股收益(净收入除以发行在外的股票)就成为关键指标。公众投资者奖励能够持续增加利润的公司,惩罚不能持续增加利润的公司(优步就是最*的一个例子)。因此,这些公司的数据科学家必须关注的不仅仅是增长。通常,这些公司规模很大,以至于优化损益表的费用部分对底线(利润)的重要性不亚于增加销售额。数据科学家可能面临的挑战包括:
- 设计客户忠诚度计划或其他保持客户参与和消费的方式。这一点和接下来的几个要点的目标是最大化客户终身价值。
- 定量识别最有可能流失的客户。
- 建立推荐系统,有效地向现有客户交叉销售新产品和服务。
- 使用数据和分析来帮助确定要进入的新市场,甚至是要收购的公司。
衰落的公司——虽然没有人渴望为一家衰落的公司工作,但这些公司的数据需求往往与成长型公司一样多,甚至更多。通常一家公司在走下坡路,要么是因为管理不善,要么是因为其所在行业处于结构性衰退。
如果公司管理不善,精通数据的人可能会有机会利用分析来改善局面。这些公司通常有很多需要改进的地方,即使是简单的分析(几个 Excel 数据透视表)也能对业务产生重大影响。考虑到大量的改进机会,更重要的问题是公司的董事会和管理层是否有改变的欲望、勇气和意愿。如果不是,那就离远点。
结构性衰退行业的公司给数据科学家带来了更严峻的考验。这可能是一个没有正确答案的测试,只有不太错误的答案。我强烈建议不要将你的职业生涯与一个衰落的行业挂钩。但如果你必须这么做,那么作为一名数据科学家,你可能会从数量上找出你所在行业衰落的原因,以及相对于竞争对手而言,是否有任何方法可以减轻对你公司的损害。
还有,有没有巩固的机会?整合(收购你的竞争对手)通常是严重衰退行业的一条生命线,因为它消除了供应,恢复了某种程度的定价能力。诚然,这些决策中的大部分可能超出了数据科学家的工资级别,但我确实相信,在这种情况下,客观的、数据驱动的方法可能会非常有帮助(有效沟通量化发现的能力也很重要)。
关于周期性与结构性下跌的说明
刚才我重点谈到了结构性衰退,这是一个看似不可逆转的趋势导致的衰退——一些例子包括优步对出租车行业的影响,网飞对有线电视的影响,数码照片对电影的影响,以及亚马逊对传统零售业的影响。在大多数情况下,新产品或服务更好(无论是质量还是便利性)且成本更低,提供这种产品或服务的公司经营得更好,也更有野心。对于现任来说,这是一个难以置信的艰难组合。
在光谱的另一端是周期性下降(如下图所示)。这些通常涉及大宗商品生产行业,如原油、半导体、*板电视,甚至智能手机(苹果因其标志性品牌而例外)。这些行业的特点是竞争激烈,产品差异极小(埃克森美孚的石油与雪佛龙的相同),并且无法定价。周期性下跌是影响所有商品的繁荣和萧条周期的萧条部分——周期通常是这样的:
- 高价格吸引了新进入者和现有参与者的更高投资,这大大增加了供应。
- 新供应的涌入压低了价格和每个人的利润。如果伴随着经济下滑,需求萎缩会迫使价格进一步下跌。破产比比皆是。
- 破产和整合最终会恢复供求*衡。随着新一轮周期的开始,那些在低迷时期幸存下来的公司现在开始收获回报(我们永远不会知道)。
Cyclical vs. Structural Declines
关键在于,周期性衰退最终会带来复苏,而结构性衰退不会结束,直到现有行业受到不可修复的损害。目前,通常很难弄清楚你的公司正处于何种衰退之中。我向你保证,许多有线电视公司的高管认为有线电视用户的下降只是暂时的——所以他们一直尽职尽责地投资新的节目和频道,同时徒劳地等待趋势自行恢复正常(它从未恢复)。
这是数据科学可能有所帮助的另一个领域。它始于一个假设,即你的公司正在经历的衰退是周期性的。为了测试这一点,你可以研究经济时间序列数据或公司客户的财务报表(你可以对他们的季度收益电话会议记录进行情绪分析)。在这一切之后,如果你认为低迷是暂时的,那么是时候将你的数据科学技能转向识别廉价收购(促进整合)和优化公司运营(削减成本和积累现金,以便公司能够进入复苏阶段)。
当您的公司试图实现起飞时,衡量成功的标准
但是我们大多数人都希望为成长中的、高潜力的公司工作(没有被解雇的压力)。因此,让我们来看看我们公司是否会实现起飞并最终变得盈利和成功的两个主要决定因素— 客户终身价值和客户获取成本。
Photo by Chevanon Photography from Pexels
客户终身价值用今天的美元(通货膨胀调整后的术语)来衡量一个客户对企业的价值。确切的定义因公司而异,但你可以这样想象。假设你经营一家咖啡馆,而我是你相当忠诚的顾客。我大约每周去一次(一年 50 次),每次花费大约 7 美元(一杯咖啡和一块饼干)——所以每年我在你的咖啡馆花费 350 美元。附*有很多其他竞争的咖啡馆,你想留住我的生意,所以你每年给我几张礼品卡,偶尔给我一些免费的饼干——这些赠品的成本总计 50 美元。所以除去我的保留费用,我每年对你来说值 300 美元。最后,根据您对以前的客户群(及其流失模式)的分析,您估计您的典型客户会逗留 4 年。因此,我的顾客对你的咖啡馆业务的终身价值是 4 * 300 美元= 1,200 美元。继续送我那些饼干吧!
请记住,增加客户终身价值有三个主要杠杆:
- ****向每位顾客销售更多。
- 向每位顾客收取更高的价格。
- ****降低客户流失率(增加客户*均寿命)。
其中任何一项的增加都会增加客户对企业的价值。
客户获取成本衡量的是获取每个客户的*均成本。请记住,这个指标包括你失败和成功的成本——也就是说,在计算它的时候,你需要将获得客户的总成本分摊到你最终成功获得的客户身上。例如,在过去的一年里,你在海报、脸书/谷歌广告和电子邮件活动上花费了 60,000 美元。总之,你能够获得 200 个新的老客户(包括我,因为我是一个喜欢漂亮海报的人)。所以你的客户获取成本是 60,000 美元/200 = 300 美元。
好消息是,假设我是你的典型客户的代表,你的咖啡馆的客户终身价值为 1200 美元,远远高于你的每位客户获得成本 300 美元。
重要的是要记住,虽然 1,200 美元是经过通货膨胀调整的(通常资本成本也经过调整),但它有很多不确定性——您对客户流失的估计可能太低,可能会发生火灾,每年的保留成本可能会上升,等等。此外,它是在接下来的 4 年中赚取的,而 300 美元的客户获取成本是现在支付的(在本年度)。因此,你的客户终身价值和收购成本之间的 900 美元差距绝不是板上钉钉的事情。相反,它应该是一个深思熟虑的和保守的估计,在你与他或她的关系持续期间,普通客户可能给你的企业带来多少利润。****
理想情况下,这些指标应该如何随时间变化?它们实际上是如何走向的?
最后,让我们思考一下我们希望看到这些指标的哪些方面,以及我们可能会看到哪些方面。
显然,如果客户终身价值随着时间的推移持续上升,而客户获取成本下降,那就太好了。
The ideal case
这是最成功的公司的情况,凭借他们的竞争优势(我们将在未来的帖子中详细探讨竞争优势的每个来源),他们能够不断地从他们的客户那里获得越来越多的钱。与此同时,随着这些公司变得更加成功和知名,它们获得新客户的成本大幅下降。例如,想想 Airbnb 现在已经是旅游和酒店的代名词,而 10 年前它还在努力证明自己是一家企业,现在收购一个客户的成本要低得多。随着 Airbnb 规模和产品的不断扩大,每一个新客户都可能会在更长时间内保持对 Airbnb 的忠诚(几乎没有可比的替代品),同时每年都会在 Airbnb *台上花费更多。
但是如果我们公司不是下一个 Airbnb 呢?那我们应该期待看到什么?下图描绘了一个不太理想但可能更常见的场景。
The more realistic case
客户终身价值仍呈上升趋势,但速度要慢得多。回想一下增加客户终身价值的三个杠杆:更多的交易、更高的价格或减少流失。当竞争激烈时,这三者都会受到影响。除非我们公司拥有某种神奇的东西,比如强大的品牌、专利等等。,你可以打赌会有竞争(导致我们的客户货币化增长比我们希望的要慢得多)。
****客户获取成本大概会经历两个阶段。在第一阶段,要么竞争者减少,要么所有人都有足够的顾客。因此,随着我们的产品和服务越来越为人所熟悉和接受,我们的公司(及其竞争对手)能够降低其客户获取成本。但最终,我们的行业将达到一个转折点,市场突然变得过度拥挤,竞争对手和容易增长的机会都耗尽了。
第二阶段的特点是价格竞争和客户挖走。我们公司需要向现有客户提供更多优惠券和忠诚度积分来留住他们。与此同时,我们的营销努力比以前收效甚微。因此,客户获取成本和保留成本都开始增加,我们公司努力维持客户终身价值和获取成本之间的利差。在这些时候,良好的管理和执行是至关重要的。例如,一个具有精益成本结构和重视客户文化的公司可能会加强其行业地位,因为它可以通过更低的价格和更好的服务来区分其产品(同时相对于其竞争对手遭受更小的财务冲击)。
编辑:需要注意的一件重要事情是,在一家公司的早期阶段(可能持续数年),客户终身价值可能低于(有时显著低于)客户获取成本。这不一定是一件坏事——这只是意味着还没有人知道你的业务,所以你的广告和推广成本会更高。那些签约成为客户的人仍然对你的价值主张持怀疑态度,所以他们不太可能把所有业务都给你。这是一个自然的挑战,几乎所有企业在寻求实现可持续发展时都必须克服这个挑战(就规模和利润而言)。
结论
希望你喜欢这篇文章。不久,我们将讨论*台公司和网络效应。干杯!
更多数据科学与分析相关帖子由我:
数据科学家是做什么的?
理解贝叶斯定理
理解朴素贝叶斯分类器
二项分布
了解 PCA
理解神经网络
数据科学家的商业策略:品牌评估
原文:https://towardsdatascience.com/business-strategy-for-data-scientists-brand-valuation-daf4ec862399?source=collection_archive---------30-----------------------
Photo by Nik Shuliahin on Unsplash
学习如何评估品牌和其他无形资产
在商业世界里,有有形资产和无形资产。像车辆和工厂这样的有形资产很容易估价——我们可以看到和触摸到它们,它们(被企业)用来产生可测量的现金流,我们可以用这些现金流来估计它的合理价格。
像品牌这样的无形资产——本刊关注的焦点——更难估价。我们看不见也摸不着它们。而且它们不会直接产生我们可以用来评估它们的任何现金流或有形收益。但在很多情况下,品牌就是业务——业务只能产生一定水*的利润,因为它有品牌。
因此,考虑到品牌可以而且经常是企业价值的主要驱动力,能够估计其价值就变得相当重要。例如:
- 投资者需要知道一个品牌值多少钱,这样他们才能判断一只股票的价值是过高还是过低。
- 数据科学家和分析师应该知道使品牌更有价值和更强大的关键杠杆,以及这对他们公司的影响。
我们如何测量无法直接观察到的东西?
鉴于品牌是无形的,我们如何衡量它们的价值?让我们集思广益,找出几个可能的解决方案:
- 我们可以估算一下一家新公司从零开始创建一个同等质量的品牌需要多少成本。
- 我们可以比较一个行业内品牌强势和品牌弱势公司的财务和股票表现。
- 我们可以对品牌如何改进的关键指标进行第一原则分解,如客户终身价值(CLTV)和客户获取成本(CAC)。****
注意每一个都包含了很多不确定性。不幸的是,对于一般的商业价值评估,尤其是品牌价值评估,没有快速的方法来得出合理的答案。相反,我们需要深入调查业务,以便我们了解品牌价值的关键驱动因素,然后让我们对品牌价值的估计进行三角分析。
为什么要有品牌?
在我们研究上面提到的 3 种方法之前,让我们先快速回顾一下公司试图用他们的品牌实现的商业目标。
优质图像
在一个企业投资一个品牌的所有原因中,这可能是最广为人知和研究得最多的。奢侈或优质品牌允许公司以更高的价格销售其产品,因为产品的稀缺性以及它所赋予的“地位”(苹果、蒂芙尼&公司、路易威登)。
注意,溢价不一定意味着奢侈。这也可能意味着在质量和价格(好市多)或可靠性和安全性(沃尔沃)或一致性(In-N-Out Burger)之间进行良好的权衡。
熟悉和情感联系
公司投资品牌的另一个原因是将自己与商品市场上的竞争对手区分开来(在商品市场上,每个公司的产品之间没有真正的差异)。这通常更难做到,因为每个公司都试图利用其品牌和营销来与潜在客户建立情感联系。而它建立这种联系的能力几乎与实际产品无关(壳牌的天然气和雪佛龙的天然气是一样的),一切都与它的营销头脑(加上运气)有关。但如果它能像麦当劳或星巴克那样成功做到这一点,就能大大增加对其产品的需求。这是因为面对非常相似的选择,消费者会选择最熟悉或让他们感觉最温暖和最模糊的东西(假设他们已经被有效地推销给了消费者)。
概述
因此,概括地说,公司试图通过品牌实现两件事情中的一件(或者两件都实现,如果他们执行得非常好的话)——优质的形象带来更高的价格,或者熟悉度和情感联系带来更高的销量。****
dePhoto by 贝莉儿 DANIST on Unsplash
从头开始建造的成本
这可能是最容易估计的,但也是最没有帮助的。我们可以看看苹果、百事、宝马、路易威登等公司有多喜欢。每年在营销上的花费。我们可能希望按比例增加年度美元金额,以反映我们从零开始的事实(而我刚才提到的那些公司正在花钱维护和加强已经建立的品牌)。但是有两个问题。
****旁注:如果你分析的公司是一家折扣店,其品牌显示低价,那么你应该考虑包括与维持低价相关的费用(折扣、促销、买一送一等。).类似地,如果一家公司的品牌是围绕技术创新建立的,那么你会希望至少包括一些年度研发支出。通常,维护一个品牌的成本并不仅仅停留在公司损益表的营销行上。
皱纹 1
就像花大量的钱来推广和营销一部电影并不能保证成功一样,增加公司的营销预算并不意味着你一定会有一个强大的品牌。
即使有巨大的营销预算,仍然有机会和运气(和执行)的成分。尽管我们花了很多钱,但顾客可能不会认同我们的品牌或信息。如果花 200 亿美元能保证你拥有苹果的品牌,那么标准普尔 500 一半的公司都会这么做。
因此,如果我们决定用成本来估计品牌价值,就需要考虑这种不确定性。最明显的方法是估计成功的概率,并根据该概率调整值。例如,如果您决定从头开始打造品牌需要 50 亿美元,而您成功的几率为 50%,那么您对品牌价值的估计为 5B/0.5 = 100 亿美元。
皱纹 2
第二个问题是,我们只关注事物的成本方面,这可能会有问题。例如,如果行业中的所有参与者都高估了拥有一个强大品牌的优势,他们最终都会超支。这将导致我们基于成本的估价被高估。品牌的价值取决于它所带来的优势。因此,任何忽视收益的估值尝试都很可能是离谱的。
Photo by Glenn Carstens-Peters on Unsplash
强势与弱势品牌比较
理想情况下,我们会发现(某个行业中)有强大品牌的公司和没有品牌的公司。然后,我们可以将它们的财务表现和市场资本(投资者愿意为其股票支付的总额)与较弱的同行进行比较。
例如,在奢侈品这样的行业,我们可以根据品牌实力对玩家进行排名,尽管带有一定的主观性。然后,我们可以比较收入增长、利润率、投资资本回报率等。强势和弱势品牌。
放眼整个行业也很有帮助。一些更有趣的分析可能来自于将能源这样的大宗商品产业(实际上要么没有品牌,要么很弱)与奢侈品这样的品牌驱动型产业进行比较。
如果我们想以这种方式评估一个品牌,我们可以考虑使用一个统计模型。线性回归是我想到的一个问题,其中我们的 Y 变量是我们每家公司的市值,我们的 X 变量是我们想要控制的所有因素,加上一个分类变量来判断公司是否拥有一个强大的品牌。应注意控制哪些因素。感兴趣的参数是分类变量上的β系数,表示公司是否有一个强大的品牌。这个特定的回归测试版告诉我们,在其他条件相同的情况下,投资者对一个拥有强大品牌的公司比对没有品牌的公司更有价值。****
但在这里我们必须小心。只有在所有其他因素保持不变的情况下,β值才是准确的。但是,如果我们把一个强大品牌的存在所驱动的 X 个变量包括在内,那么我们就不能再以表面价值来衡量测试版了。****
例如,假设我们发现贝塔系数是 50 亿美元。这意味着,在其他条件相同的情况下,投资者愿意为一家拥有强大品牌的公司多支付 50 亿美元。但是我们注意到我们的 X 变量之一是年销售额。假设一个强大的品牌可以推动更高的年销售额是非常合理的(毕竟这是拥有品牌的一个要点)。但这意味着我们再也不能说“所有其他事情都是*等的”。相反,归属于强势品牌的一些价值(强势品牌分类变量的β值)很可能已经泄露给年度销售变量的β值以及受品牌影响的任何其他变量。这将导致回归低估我们品牌的价值。解决这个问题的一个方法是通过在我们的回归中包含相互作用项来明确考虑相互作用的影响。
通过建立这样一个模型,我们可以学到很多东西。所以我们也可以在以后的文章中构建它。我一直想写一篇“理解线性回归”的文章。所以我们将把细节留到以后再说。
基本原则评估
这是我的首选方法。这比只关注成本更不容易出错,也比我之前建议的线性回归更直观和直接。
尽管如此,它需要我们估计许多事情。但使用第一原则方法的好处是,它迫使我们理解品牌和业务是如何相互作用的。
在早先的一篇文章中,我们介绍了两个关键指标:客户终身价值(CLTV)和客户获取成本(T3)。这一部分应该相当明显——一个强大的品牌应该:
- ****通过提高客户支出或增强客户忠诚度来增加 CLTV。一个强大的品牌应该带来更高的交易频率、更高的公司产品价格和更高的客户忠诚度(更长的*均客户寿命)。这些都会导致 CLTV 的增加。
- 增加 CAC——强大的品牌更容易吸引新客户。当你公司的品牌强大时,这本身就是一个广告,它极大地提高了市场对你的产品和服务的认知度。
随着你的品牌越来越强大,我们希望看到 CLTV 和 CAC 像下图这样发展:
The impact of a strong brand
像往常一样,棘手的部分是弄清楚这两个指标的改善有多少可以归因于强大的品牌。金额因企业和行业而异。
理想情况下,我们希望比较同一家公司在一个拥有强大品牌的世界和一个没有强大品牌的世界(其他一切或多或少相同)中 CLTV 和 CAC 的表现。但是一个品牌要么是,要么不是(这么哲学对吧?),所以实际上没办法做那个比较。因此,我们需要再次求助于调查方法:
- 列出品牌影响力从低到零的公司。这份名单是我们的控制组——我们对没有品牌的企业的最佳估计。
- 然后看看每个公司的 CLTV 和 CAC(如果你纯粹依靠公开的财务报表,那么你需要做一些估计,因为一些公司不直接公布这些数字)。
- ****将我们公司的 CLTV 和 CAC 与我们对照组公司的*均 CLTV 和 CAC 进行比较。我们公司与对照组*均值之间的指标差异主要归因于我们的品牌。我们可能希望缩小计算出的差异,因为其中一些可能归因于更好的执行或更严格的支出纪律。
- 最后,一旦我们对每个客户的品牌收益有了一个估计,我们就可以用我们公司拥有的客户数量乘以。****
直到下次
品牌估值没有 100%正确的答案。这绝对是一门不精确的科学。让我们面对现实吧,试图过于精确没有任何好处——估计我们的品牌价值 180 亿美元和 200 亿美元之间的差异并不显著(也不值得为此失眠)。更重要的是了解品牌赋予我们业务的优势。
希望这是有帮助的,干杯!
更多数据科学与分析相关帖子由我:
数据科学家的商业战略
用 Python 进行业务模拟
了解 PCA
理解贝叶斯定理
理解朴素贝叶斯分类器
二项分布
但是我喜欢开源——为什么我需要一个人工智能*台?
原文:https://towardsdatascience.com/but-i-love-open-source-why-would-i-need-a-data-science-platform-3c1d118fa330?source=collection_archive---------29-----------------------
企业投资人工智能*台的 10 个原因
构建一个机器学习 (ML)模型从未如此简单。几行 R 或 Python 代码就足够了,网上有大量的资源和教程甚至可以训练一个复杂的神经网络。最好的部分:这是你能想到的几乎每一个人工智能算法的情况,而人工智能研究的几乎每一个新进展通常都伴随着相应的开源实现。
然而,正如我之前在这篇文章中讨论的,人工智能不仅仅是建立模型。这个旅程实际上是从数据 收集、策划、探索、特征工程、模型训练、评估、最后是部署。
Hadoop 生态系统似乎是收集和聚合不同数据源的开源选择。Hive 和 HBase 符合访问、混合和匹配多个数据源的要求。现在,对于数据准备(即监管、探索和特征工程),Apache Spark 可以通过 SparkSQL 对大型数据集进行切片和切块,甚至利用内存处理来加快响应时间。Spark 还为您提供了自然语言处理 (NLP)功能和特征提取器,如主成分分析 (PCA)。但可能开源软件最强的一套是它的大量不同的人工智能模型。scikit-learn、R、SparkML、TensorFlow、Keras 和 PyTorch 等等,提供了我和我的任何数据科学家伙伴们梦寐以求的一切。最后,像 Docker 和 Plumbr 这样的工具可以通过 HTTP 请求以 web 服务的形式简化机器学习模型的部署。
等等……这是否意味着人们可以仅仅使用开源堆栈来构建一个企业级的端到端人工智能系统?不完全是。
这可能是构建概念验证 (POC)的情况。回到 2012 年,作为我论文的一部分,我纯粹在开源的保护伞下构建了一个人类活动识别系统(包括这个手机 app)——谢谢 Java、Weka、Android 和 PostgreSQL!然而,对于企业来说,情况却大不相同。
别误会我的意思。我不仅是一个超级粉丝,也是开源软件的狂热用户,我确实意识到有这么多神奇的工具;但同时也有不少差距。我来分享一些企业投资 AI *台的原因。让我告诉你一些我作为一个人工智能和人工智能从业者最痛苦的时刻。
1。开源集成、启动和运行以及版本更新
上次我试图在我的机器上安装 TensorFlow,它破坏了我的 Apache Spark 配置。几分钟后,当我认为我已经修复火花,我意识到张量流是烤面包。又来了!
长话短说:我花了整整一个下午的时间让这两只野兽跑起来。想象一下,当这么多其他工具需要共存于一个数据科学家的工作环境中时,会有多少事情出错:Jupyter、R、Python、XGboost、Hadoop、Spark、TensorFlow、Keras、PyTorch、Docker、Plumbr 等等。现在考虑一下,所有这些工具每隔一个月都会有新的发布,因此需要频繁的更新。有人说冲突吗?啊!让一个*台来帮我处理这件事。
2。协作
现在我和我的三人数据科学家团队一起工作。我们正在使用我们最喜欢的 Jupyter+Python+Spark+tensor flow 环境,并决定创建一个 GitHub 存储库来共享我们的代码和数据资产。但是我在我的环境中使用定制的软件包——这花了我一段时间来安装和配置——我的同事无法访问它们。他们将不得不经历和我一样的痛苦,在他们自己的机器上安装软件包。好吧,但是,我们如何共享我们部署的模型?创建 Docker 图像或 PMML 文件听起来一点也不性感!分享我们的预测、实验和评估(混淆矩阵、ROC 曲线、RMS 等)怎么样?)?啊!让*台为我处理这件事。
3.数据虚拟化
企业中最常见的挑战之一是数据集分散在多个系统中。一个典型的解决方案是将数据复制到中央数据存储中——那里有您的数据湖— 用于运行您喜欢的分析。然而,这种方法显然成本高且容易出错。
数据虚拟化允许跨多个系统查询数据,无需任何复制,简化了数据收集流程。
开源软件没有提供数据虚拟化解决方案。因此,让*台为我们处理这个问题。
4。治理和安全
这是企业关心的一个关键问题,也是开源留下巨大空白的一个领域。资产需要治理,我指的不仅仅是数据,还有代码、模型、预测、环境和实验!所有数据科学家都应该知道批准/拒绝向客户贷款的标准吗?或者哪些因素导致将交易标记为潜在欺诈?肯定不是!限制每个用户的资源利用率怎么样?让*台为我们处理这些。
5。模型管理、部署和再培训。
如果一个质量完美的人工智能模型只放在我的笔记本电脑上,它有什么用?一个模型是没有用的,除非它作为服务运行,提供预测并被最终用户消费。
在这篇文章中,我描述了如何为 Github 工作项目构建一个自动完成系统——换句话说,预测团队、受托人等。·给定一个工作项标题作为自由文本。建立模型(包括数据准备)花了我将*两周的时间。但是部署花了我的同事一个多月的时间,不得不创建模型的 docker 图像,以便稍后使用 plumbr 来连接东西。每当我创建一个新的模型时,我还想再经历一次吗?不了,谢谢你!那么如何跟踪不同的模型版本呢?还是关于各款车型性能的统计?如何检测模型退化?或者时常自动化整个再培训过程,以确保模型是最新的?让*台给我做!
6.偏差检测和校正
想象一下,一位数据科学家使用性别或年龄作为信用风险的预测指标。而且,生成的模型是给某个性别分配更高的风险。这不仅不道德,而且在大多数司法管辖区也是非法的。如何检测一个模特是否有性别偏见?如果是这样,如何在不必重建模型的情况下纠正这种偏差?点击了解更多关于偏置检测和校正的信息。再来,让*台给我做!
7。辅助数据管理
我的一个同事经常和我开玩笑,公然告诉我,鉴于我花了很多时间清理数据,我实际上不是一名数据科学家,而是一名数据管理员。
遗憾的是,他指出,在数据科学项目中,高达 80%的时间和精力经常用于数据管理和准备。让我们面对现实吧,来自开源的数据监管工具,包括 Spark,都涉及到繁重的编码工作,这可能非常乏味。但是,如果有一个可视化工具可以清理和提炼多个数据源而无需编写一行代码,那会怎么样呢?是的,让*台给我做吧!
8。GPU
在过去的十年中,计算能力有了巨大的提高,图形处理单元有了显著的进步。这对深度学习算法尤其有利。现在,配置 TensorFlow/Keras 等框架以获得最佳性能本身就是一个项目,需要的技术知识并不具备典型数据科学家的背景,包括我自己。再一次,让*台为我处理那件事!
9。可视化建模
许多统计学家、数据分析师甚至经理可能对构建机器学习模型感兴趣,尽管他们不精通 Python 和 r 等语言的编码。几十年来, SPSS 等工具一直在为 ML 和 AI 提供可视化接口,现在可以在云上利用这些接口。换句话说:
拖放您的数据集,然后是您喜欢的数据准备和建模算法,最后部署您的模型,而无需编写任何代码。
当谈到可视化建模时,开源中也有一个空白,因此,让*台为我提供它。
10。自动化人工智能
我们作为数据科学家的角色有一个很大的机械组成部分,即反复尝试不同的算法、超参数、特征组合等。但是,如果我们让它自动化,包括实验,也就是说,交叉验证、混淆矩阵、 ROC 曲线、精确回忆曲线等等,会怎么样呢?哦是的,请让*台为我做那件事!
在寻求一个利用开源但填补上述所有空白的人工智能*台吗?免费试用 沃森工作室 !
对全面的数据和人工智能解决方案感兴趣?看一下 IBM Cloud Pak 获取数据 。
关于作者
scar D. Lara Yejas 是高级数据科学家,也是 IBM 机器学习中心的创始成员之一。他与世界上一些最大的企业密切合作,将人工智能和人工智能应用到他们的特定用例中,包括医疗保健、金融、制造、政府和零售。他还为 IBM 大数据产品组合做出了贡献,特别是在大规模机器学习领域,是 Apache Spark 和 Apache SystemML 的贡献者。
scar 拥有南佛罗里达大学的计算机科学和工程博士学位。他是《人类活动识别:使用可穿戴传感器和智能手机》一书的作者,也是大量关于大数据、机器学习、以人为中心的传感和组合优化的研究/技术论文的作者。
但是,AI 到底是什么?
原文:https://towardsdatascience.com/but-what-exactly-is-ai-59454770d39b?source=collection_archive---------20-----------------------
复杂问题的简单答案
多年来,人们认为计算机是执行数学运算的速度比人快得多的机器。它们最初被视为计算机器,就像被美化了的计算器。早期的科学家认为计算机永远无法模拟人脑。然后,科学家、研究人员和(可能是最重要的)科幻小说作者开始问“或者可能吗?”解决这个问题的最大障碍归结为一个主要问题:人类的大脑可以做科学家无法理解的事情,更不用说*似了。例如,我们如何为这些任务编写算法:
- 一首歌出现在收音机里,大多数音乐听众能很快辨认出流派,也许是艺术家,也许是歌曲。
- 一个艺术评论家看到了一幅他从未见过的画,但他很可能识别出时代、媒介,甚至可能是艺术家。
- 婴儿在很小的时候就能认出妈妈的脸。
简单的回答就是你不能为这些写算法。算法使用数学。完成这些任务的人无法从数学上解释他们如何得出这些结论。他们能够取得这些成绩是因为随着时间的推移,他们学会了做这些事情。人工智能和机器学习是为了在计算机上模拟人类学习而设计的。
人工智能(AI)和机器学习(ML)这两个术语从 20 世纪 50 年代就开始使用了。当时,它被视为计算机科学的未来理论部分。现在,由于计算能力的增加和对算法的广泛研究,人工智能现在是一个可行的现实。以至于我们每天使用的许多产品都内置了一些变异的人工智能(Siri、Alexa、Snapchat 面部过滤器、手机/耳机的背景噪音过滤等……)。但是这些术语是什么意思呢?
简单来说,AI 的意思是给机器编程,让它像人一样行动。一开始,研究人员开发算法试图接*人类的直觉。查看这段代码的一种方法是用一个巨大的 if/else 语句来确定答案。例如,这里有一些这个时代的聊天机器人的伪代码:
if(input.contains('hello'))
response='how are you'
else if (input.contains('problem'))
response = 'how can we help with your problem?')
...
print(response)
正如你所想象的,由于人类思维的复杂性,这被证明是一种非常低效的方法。这些规则非常僵化,随着时间的推移,随着情况的变化,很可能会过时。这就是军情六处介入的原因。这里的想法是,与其试图给机器编程来充当大脑,我们为什么不直接给它输入一堆数据,让它自己找出最佳算法?
ML 被证明是一个开创性的想法。以至于现在,研究人员和开发人员几乎可以互换使用术语 AI 和 ML。你会经常看到它被称为 AI/ML,这是我在本文的其余部分将使用的,但是,如果你遇到博士/数据科学家类型的人,要小心,因为他们无疑会纠正你。
在我们更进一步之前,我们需要考虑 AI/ML 的一个全局事实。输入数据总是数字。机器不能听音乐,不能读手写数字,也不能看视频。相反,这些必须用数字格式表示。以这个手写数字为例:
https://colah.github.io/posts/2014-10-Visualizing-MNIST/
左边是图像显示为图片时的样子。右边是它在计算机内部的实际视图。这些数字的范围在零(白色)和一(黑色)之间。这里的关键是,任何可以用数字表示的东西都可以用于 AI/ML,而且几乎任何东西都可以用数字表示。
AI/ML 的过程是创建一个模型,训练它,测试它,然后用新的数据推断结果。AI/ML 主要有三种学习类型。它们是监督学习、非监督学习和强化学习。我们来详细看看这些。
监督学习
在这种情况下,我们有输入数据,知道正确的“答案”是什么。可视化输入数据的一个简单方法是行和列的网格。至少有一列是“标签”,这是我们试图预测的值。其余的列是“特征”,是我们用来进行预测的值。这个过程就是不断地给我们的模型提供特性。对于每一行输入数据,我们的模型将提取特征并生成预测。在每一轮(“历元”)之后,模型会将其预测与标签进行比较,并确定准确性。然后,它将返回并更新其参数,以尝试为下一个时期生成更准确的预测。在监督学习中,有许多类型的模型和应用(预测分析、图像识别、语音识别、时间序列预测等)
无监督学习
在这种情况下,我们没有任何标签,所以我们能做的最好的事情就是试图找到相似的对象,并将它们分组到簇中。因此,无监督学习经常被称为“聚类”起初,这似乎不是很有用,但事实证明它在以下领域很有帮助:
- 客户细分——什么类型的客户正在购买我们的产品,我们如何针对每个细分市场定制营销
- 欺诈检测—假设大多数信用卡交易遵循相似的模式,我们可以识别不遵循该模式的交易,并调查这些交易是否存在欺诈。
- 医疗诊断——根据病史、生活方式、医疗读数等,不同的患者可能被分为不同的类别。如果一个病人脱离了这些聚类,我们可以进一步调查潜在的健康问题。
强化学习
在这里,没有“正确”的答案。我们试图做的是训练一个模型,使它能够以一种最终会产生最佳结果的方式做出反应。强化学习经常被用在电子游戏中。例如,我们可能想训练一个电脑化的乒乓球对手。对手将通过继续玩 pong 来学习,并在得分和赢得比赛等事情上获得正强化,在放弃分数和输掉比赛等事情上获得负强化。强化学习更有意义的应用是在自动驾驶汽车领域。我们可以训练一个模拟器在城市街道上行驶,当它做错事情(撞车,闯停车标志等)时惩罚它,并奖励它积极的结果(到达我们的目的地)。
结论
如果你是 AI/ML 的新手,希望这篇文章能帮助你对它背后的术语和科学有一个基本的了解。如果你是这些领域的专家,也许这篇文章会有助于向没有这方面经验的潜在客户解释。
但是什么是随机变量呢?
原文:https://towardsdatascience.com/but-what-is-a-random-variable-4265d84cb7e5?source=collection_archive---------12-----------------------
Coin toss from https://www.pexels.com
简介
通常简单的概念会因为术语和应用它们的上下文而变得难以理解。对我来说,随机变量就是这样一个令人困惑的方面(尽管事后看来很简单)。
对于软件工程师来说,变量有两种类型——局部变量和全局变量。当你写软件时,变量通常有一个范围和界限,但如果你给它们加上形容词,这意味着它们可以有任何值(尽管你仍然可以使用种子的概念来控制随机性)。**
对于一个密码学家来说,随机性是他/她的算法最重要的特性之一。他/她努力生成完全不应该重复的随机数。
从初等代数的角度来看,变量的概念是直截了当的,也就是说,它代表等式的输入,写在右边,也代表等式的输出,写在左边。随机方面通常不会出现或讨论到那个层次。
现在,如果你在维基百科或谷歌上阅读它的定义——什么是统计学中的随机变量?,您会看到这样的语句:
随机变量是将结果映射到真实值的函数。
实际上是函数的变量?
对于统计学家来说,这可能没问题,但对于来自其他学科(如软件工程)的人来说,这种说法开始严重破坏语义,因为它扰乱了他们对每天处理的 3 个非常基本的事情的理解——变量、函数和随机性!
显然,统计的随机变量是不同的生物,理解它们是使用它们和/或建立在它们之上的许多其他概念(高斯过程、贝叶斯统计等)的基础。
结果、样本空间和事件空间
随机变量在概率论中有其适用性,所以让我们先修改一下该领域的一些术语。
当你在观察一个现象或进行一个实验时,你会得到结果。通常给出的典型例子是-
- 扔硬币有两种可能的结果——正面或反面
- 掷骰子可能有 6 种结果——1、2、3、4、5 或 6
一个可能结果的列表(正式称为 集合 即列表中的项目不重复)称为一个 样本空间。
这意味着抛硬币的样本空间是{头,尾},掷骰子的样本空间是{1,2,3,4,5,6}。
这里的第二个重要术语叫做事件。什么是事件取决于你如何在你的样本空间中定义一个实验。****
考虑一个对应于投掷硬币两次的样本空间。可能的结果是{HH,HT,TH,TT}。现在,如果我对导致头先出现的结果感兴趣,那么我会将我的事件集描述为{HH,HT}。从这个事件的例子中,你应该开始看到一个事件实际上是样本空间的一个子集。
有一个符号用来代表样本空间(即所有可能的结果),它是ω****
类似地,对于事件空间**(即所有可能的事件)也有一个符号,它是 ∑**
另一个例子是为了更清楚。假设你正在掷骰子(ω= { 1,2,3,4,5,6}** ),如果你的实验是观察甚至的结果,那么事件空间将是— ∑ = {2,4,6}**
随机性和可变性
现在我们终于可以看到随机变量在所有这些中的位置,更重要的是,对应于随机性和可变性的部分。
随机性
你看,与你的实验相对应的事件有内在的不确定性(随机性)与之相关,也就是说,你在上面实验中的两次抛硬币可能是 HH 或 HT 或 TT 或 th。然后你用概率论来量化这些事件的不确定性。
我意识到归根结底这只是语义学,但我真的很喜欢不确定性这个词,因为它帮助我不把我对随机性的理解从其他学科带进来。这也意味着统计学中的随机变量 本来可以被 称为不确定变量。但是他们不这么叫:(…..文献一直称它们为随机变量,所以如果有帮助的话,你可以(就像我经常做的那样)在你的脑海里翻译成不确定变量。
我将在文章的后半部分详细解释量化随机变量的不确定性。
可变性
在抛硬币实验中,我们在样本空间中使用了单词 HEAD & TAIL。相反,我们可以用数字来表示它们,比如我会用 1 表示头部,用 0 表示尾部。换句话说,我可以说我将头部映射到 1,尾部映射到 0。映射意味着执行这种转换的函数。回想一下你在维基百科或谷歌搜索中找到的早期定义— “随机变量是将结果映射到真实值的函数”。
你可能想知道为什么我选择把 1 赋给头部,0 赋给尾部…会不会是另一种方式,即 0 代表头部,1 代表尾部?。在许多方面,你可以自由分配(或者我应该说映射到)数值,但是正如你在更复杂的例子中看到的,这些映射有一定的意义和一致性,这主要取决于你对实验的定义。例如,即使对于一个简单的掷硬币的例子,我也可以通过将我的实验设定为“我对观察头的感兴趣”来证明 1 的分配是合理的。我会使用 1(=真),因为它表示这个实验定义的布尔逻辑。
为了不局限于布尔实验,我们来看另一个例子。这里我有两个抛硬币的例子,即ω= { HH,HT,TH,TT}** ,我对实验的定义是观察到的人头数。因此,我将定义我的(随机)变量来为{TT}生成(记住它是一个映射器/函数)0,为{TH} & {HT}生成 1,为{HH}生成 2。**
随机变量通常用大写字母表示。例如,对于上面的实验,我将把它写成 H = {0,1,2} 。
也就是说,样本空间(ω= { H,T})的结果到(实数)的映射看起来非常确定,即在映射(函数)方面没有随机性。这意味着不是“随机变量”的变量部分是随机的,而是它代表我们正在与具有与结果相关的不确定性(随机性)的样本空间一起工作。
如果你想知道——这只是简单地给样本空间中的结果分配一个数字,还是有更多的故事,那么你就在正确的道路上。事实上还有更多!
你看,给定样本空间的结果可以用来定义许多不同的实验。例如,这一次你将掷出两个骰子,这样如果它们不可区分(即你不关心哪个骰子产生哪个数字),那么可能的样本空间是ω= {(1,1),(1,2),(1,3),(1,4),(1,5),(1,6),(2,2,(2,3),(2,4),(3,3),(3,4),(3,4),(3,5),(3,5),(4,4),(4,5),(4,4)这里有 21 种可能的结果。从这里开始,我可以提出几个不同的实验,这些实验将导致它们各自的事件空间。一个实验可以是——两个骰子的和大于 8,另一个实验可以是——观察两个骰子的乘积何时为偶数,还有一个实验可以是——观察乘积减去 3 后的结果何时为偶数以及更多。****
这种使用样本空间的实验创建是随机变量开始使用其“函数”能力并将结果映射到实数的地方,这取决于你如何提出你的实验定义。
但为什么称之为变量呢?关于这一点,我想了很久,我能想到的最好的(应该说是唯一的)解释是,你的任务往往不是关于一个单一的样本空间。你的任务的最终结果可能取决于许多现象,它们有各自的样本空间。你将在这些样本空间上应用代数,因此你将结束加,减,乘的结果。因为你通常加/减/乘变量,而不是函数,所以他们最终称之为变量。
随机变量、事件空间和概率
随机变量的定义似乎暗示了与样本空间的强联系;毕竟,是一个 函数 将结果映射到实数,但现实是随机变量的应用与事件更相关。
你会意识到一个更有趣的方面是知道所有可能结果中的哪些事件已经发生,因此当你用随机变量做代数时,你实际上是在处理这些事件。
为了更加清晰,我们来看一个例子。在我们观察两次抛硬币的正面数量的例子中,我们定义了 H = {0,1,2}。这个集合中的每个元素对应一个事件。由于事件具有不确定性(随机性),我们利用概率论。我们通常说观察的概率
- 0 头是 p1
- 1 头是 p2
- 两个头是 p3
而且我们知道 p1 + p2 + p3 = 1。对此的另一种解释是,p1、p2 和 p3 正在量化与其各自事件相关的不确定性。
现在,当我们使用随机变量时,我们可以简单地写成
P(H=0) = p1,P(H=1) = p2,P(H=2) = p3
应该清楚的是,这里显示的事件和随机变量的输出范围(所有可能的值)之间有直接的对应关系。
这也意味着你所知道的概率计算的用法,即独立事件、联合事件、条件事件、求和规则、乘积规则等,也同样适用于随机变量。换句话说,你可以对独立或相关的随机变量和/或条件进行概率计算。
随机变量的类型
到目前为止,我们讨论的所有例子都只是一种称为离散随机变量的随机变量。这些变量(顾名思义)代表可以计算的结果。你可以数人头的数量,产品是 8 的次数,等等。
还有另一种类型的不确定现象是不可计数的,例如,如果我们正在处理一天中温度的实验和观察,那么你正在处理一个可以取无限多不同值的测量,因此实际上是不可计数的。然后使用连续随机变量来表示这些类型的随机/不确定现象。****
随机变量和概率分布
我们已经接触到了概率的关系,但是这需要一个单独的小章节,因为你很少谈论没有概率分布的随机变量。
什么是概率分布?
如果你取与随机变量 X 的输出范围相关的概率,那么你将得到 X. 的概率分布
方便的是,许多概率分布函数已经被定义来反映典型的数据生成过程。例如,我们的随机变量在任务是观察头部时取值 1,在任务是观察尾部时取值 0,使用伯努利分布来描述。
这篇文章不是关于各种分布的解释,甚至也不是对概率分布本身的深入探讨,但是如果你感兴趣,我强烈建议你阅读 https://medium.com/@aerinykim 写的文章。她在解释许多重要发行版背后的目的、起源和数学方面做了非凡的工作。
我想说的是,在实践中,概率分布往往比随机变量更有趣,更重要,因为它是描述随机现象各种特性的分布。换句话说,一旦你为你的实验确定了合适的概率分布(和所需的参数),那么原始的样本空间可以被处理掉,你可以简单地使用概率分布对未观察到的数据进行预测。
随机变量和各种工具包/库
本节的目的是说明我在上一节中提到的内容,也就是说,在实践中,您最终只会处理发行版。在这里,我提供了一些来自不同库的例子,这些库实现了随机变量(读取概率分布)以及它们如何互换使用这两个术语。
科学统计
scipy 有一个名为 stats 的子模块,它实现了各种发行版。它们定义了基类rv_continuous
& rv_discrete
,从中继承了一系列令人印象深刻的分布函数。
注意上图中随机变量和分布的概念是如何混淆的。文档上写着An alpha continuous random variable
,但它被列在标题Continuous distributions
下,即使文档上说该模块包含大量的概率分布。
pyMC3
谈到概率编程,pyMC3 可能是(没有双关语)使用最多的工具包。
你可以试试他们的笔记本这里但是正如我在上面的 pyMC3 截图中显示的,随机变量和分布是一回事。
张量流 _ 概率&爱德华 2
Tensorflow probability 是 Tensorflow 生态系统的一部分,它定义了各种分布和神经网络层,利用了 tensorflow 核心原语和加速功能。edward2 定义为使用 tensorflow_probability 构建的 概率编程语言 。唷!!….谈论称软件框架或库为编程语言会增加更多的混乱,但这似乎是概率建模领域的一种趋势。
至少 edward2 似乎有一个名为 RandomVariable 的 python 类,封装了随机变量的属性,即其分布、样本形状和可选值。我喜欢这个,因为它似乎更好地代表了软件设计中的理论。
结束语
- 把随机变量想象成不确定变量
- 随机变量是将结果映射到实数的函数
- 随机变量本身是确定性的,随机性(或者说不确定性)存在于样本空间中
- 你可以对随机变量进行概率计算
- 在实践中,随机变量和概率分布经常互换使用,即使它们是不同的东西(尽管一个没有另一个是没有用的)。
参考文献
[1]https://en.wikipedia.org/wiki/Random_variable
[2]样本空间和事件的一个很好的例子列表—https://faculty.math.illinois.edu/~kkirkpat/SampleSpace.pdf
**[3]math.stackexchange.com 的一个回答帮助我了解了术语“变量”的用法—【https://math.stackexchange.com/q/864839 **
[4]艾林·金(【https://medium.com/@aerinykim】)写了许多解释重要分布的文章。
但债务从何而来?
原文:https://towardsdatascience.com/but-where-did-the-debt-come-from-e63864333d7d?source=collection_archive---------26-----------------------
似乎没有人明白导致零售业末日的债务从何而来。这里有一个机器学习驱动的框架分析,可以帮助回答。
Payless ShoeSource 再次破产。这一次,它意味着我们所知道的公司的结束。商店将被清算。但该公司将继续存在:Payless Holdings 与其说是一家经营鞋店的公司,不如说是一家持有许可证的公司,其投资组合包括 Sperry、Stride Rite 和 AirWalk。如果你喜欢船鞋、滑板鞋,或者是个孩子,你的品牌将会继续。
但 Payless 为什么会拥有这么多品牌呢?因 Velcro 而闻名的折扣鞋类连锁店 Payless 自 2012 年被百隆资本、金门资本和金刚狼全球收购后就不再是原来的样子了。这些私人股本公司通过举债收购零售商,然后试图用它们来偿还收购费用。如果金门资本这个名字耳熟能详,那么它就是玩具反斗城和克莱尔破产等灾难背后的私人股本公司。如果你喜欢桌子,本·昂格尔斯比有一家很好的被私募股权收购的零售公司。
世代机遇
你可能会问,什么是杠杆收购?这是指一家公司带着债务收购另一家公司,并将收购的债务转移到被收购公司。假设一家对冲基金认为必胜客有一些他们可以解决的小问题,他们可以申请贷款,购买必胜客,然后将贷款转给必胜客。
如果一家公司的现金多于其发行在外的股票,掠夺者可以贷款收购一家公司,并立即偿还贷款。这是老牌企业攻略的核心活动。现在这种不可思议的情况非常罕见,所以通常公司并不打算迅速偿还贷款,相反,他们会在被收购的公司中进行这样的转变,以至于它可以简单地偿还自己的收购价格。这就引出了一个非常重要的问题:你有多少次真的发现了这家你可以免费买到的神奇公司?有多少公司能在杠杆收购过程中存活下来?
很少见,少之又少。
但这并不能阻止人们去尝试:毕竟,这些另类投资是真正致富的最佳途径之一。所以我们产生幻觉,认为一家成功的鞋店连锁店可以用信用卡购买。很明显,这是一个非常糟糕的主意。
人们是如何谈论它的?
表面上的金融新闻故事直截了当:Payless ShoeSource 破产了。在更深的层面上,我们经常使用一个叫做框架分析的想法来寻找更广泛的描述系统。框架是使故事有意义的隐喻、主题和风格的集合。你可能熟悉的一个特殊框架是政治中的“赛马”。这个故事依靠最*的民意调查来告诉我们两个候选人之间的竞争情况。一次民意调查的结果真的能告诉我们那么多吗?不。这就是为什么像王少伟或内特·西尔弗的聚合方法也很受欢迎,他们提供了对赛马的更深入的分析。个人投票的故事,以及它为什么继续的原因,是它可能是竞选中一个转变的指标。聚合模型可能会更明确地告诉你谁赢了,而快速投票故事可能会告诉你一匹马现在领先一个鼻子。
为了让赛马框架有意义,你必须接受民意调查背后的某种逻辑,即两个候选人相对*等,以及被讨论为与投票密切相关的新闻事件实际上是相关的。这里有很多结缔组织。框架也存在于其他领域,几乎每一项新的营养研究都可以被定位为值得报道的变化。
分析过程
在这个分析中,我假设 MALLET 提出的主题标签可以用来推断主题框架的特征。这种方法的结果包括文档主题概率的列表,以及这些主题之间的关系。因为我没有包括重复的,所以总的语料库是 270 段文本。我倾向于用经典的树状图来思考这些关系。
机器学习中的这种方法试图给每一段指定一个主题。这里有一个重要的警告,也是我们为什么要求助于人的判断,那就是系统无法解读更深层次的含义。同时,这种机器和人类阅读的结合有助于防止人类读者对主题和集群产生幻觉。
Balance of topic words to doc topics @ .7
您可以看到有两类主题,3–6/7 和 5–1–2–4/8。
原始主题输出可能难以阅读,并且依赖于一些解释工作。我的一般程序是检查自动生成的主题中的关键术语或专有名称。然后,在我对这个类别有了一些概念之后,我会检查概率最高的文件,寻找这些文本中的论点。
在这一点上,我建立了一个键,描述了哪些类型的令牌被检测为关联。作业将包括我的语义判断,基于我对 MALLET 提取的关键词的阅读以及对每个主题中最有可能出现的文本(段落)的仔细阅读:
- 加拿大的维度
- 在线竞争和债务
- 负债累累的零售业
- 与其他公司和房地产相关的零售问题
- 关于股票市场状况的一般性讨论
- 加拿大境外的清算和全球业务
- 崩溃的细节,付不起房租
- 零售商受到限制,缺乏强有力的员工,流动性问题
在我们继续之前,了解一下有多少数据集被分配给了一个特定的主题是很重要的。主题 7,崩溃的细节是目前分配最重的主题。这是新闻业建设中的一个重要环节,这是有意义的——这是行动所在。主题 6 和 4 也高于其他主题,这更有意义。需要理解的重要一点是,关于债务的讨论并没有很好地集中到故事的主要部分——我们知道大多数细节都是围绕第七类展开的。
这种关系也能告诉我们一些我们正在看的故事。一组是该行业背负债务的故事,附有清算的关键细节,以及那种淫秽的线索。另一个集群包括一个更完整、更复杂的商业故事中可能会出现的所有部分,最深入的棒球内部有几个层次,包括加拿大股市的总体状况,但高于特殊问题,如零售招聘和房地产。
仅有的两段讨论了金门公司和合伙人在玮伦鞋业灭亡中的作用,这两段被分配给了主题 7 和主题 2。主题 2 特别有趣,因为它是故事真正理论化的地方。鉴于主题 7 无处不在,我将沿着主题 2 更丰富的次要任务继续分析。考虑主题 2 中的这两段:
Valley Morning Star: 这家公司成立于 1956 年,以在自助环境下提供打折鞋为前提,2012 年被金门资本(Golden Gate Capital)和百隆资本(Blum Capital Partners)私有化,并因此举引发的严重债务问题而陷入困境。
彭博: Payless 成立于 1956 年,目标是在自助环境中销售价格合理的鞋子,并称其是西半球最大的专业鞋类连锁店。该公司努力管理 2012 年金门资本(Golden Gate Capital)和百隆资本(Blum Capital Partners)杠杆收购的债务,并于 2017 年 4 月申请破产保护。
这是整部文集里金门资本出现的两段。这是唯一一次记者将债务的原因归结于一个演员,而不是将其作为崩溃故事本身的一个父概念。我觉得这很荒唐:我们知道债务是导致公司破产的原因,但是我们可以插入任意数量的解释(主题 2 的孩子)来解释债务从何而来。
很明显,话题 2 的峰值附*的故事很少。这可以在对主题密度的分析中进一步看出:
低密度并不意味着某些东西不重要,而是意味着故事可能均匀分布,或者大部分段落不太可能出现在该段落中。例如,主题一是一个专业故事,分配给它的那些段落实际上是关于加拿大的。同样清楚的是,某些出版物和主题与某一天或某个作者有更密切的联系。像 2 或 5 这样的限制话题可以指向特别专业的故事。在主题 5 的情况下,真正关注股票市场的故事通常是一个特定和独特的子集。主题建模器可以有效地指向框架。当与其他语义方法相结合时,就有可能提取帧并将这些帧作为族进行关联,以便进一步分析。
在很大程度上,这项研究揭示了零售报告的一种按数字着色的方法。如果一家公司破产,请注意它是因为债务而倒闭的,这可能会导致戏剧性的一幕,其中将包括清算。从这个简短的研究中可以得出一个结论,主题模型可以为新新闻故事的自动生成提供一个简单的框架。
你为什么在乎?
这些商店失败的直接原因是,它们没有销售额来补偿它们的财务设计强加给它们的破坏。在零售业的背景下,这似乎是对整体经济的合理调整——美国的零售业空间太大了。同时,这也不需要发生。玩具反斗城和 Payless 的世界会更好,这些都是可行的业务。
在这个论述中,债务有一种本体论性质,它只是零售企业的一种财产。它不知从哪里冒出来,必须予以反击。这不同于教育、消费或抵押贷款债务的表现,后者似乎是个人做出不负责任的决定的结果,尽管有充分的证据表明,促进房屋交易的制度选择导致了大衰退,或者掠夺性的盈利机构而不是你所在的州是许多教育债务的来源。我们在谈论债务存在的原因方面做得很差,在让人们感到羞耻方面做得很好。
公司看起来像是法人,但不知何故,他们比普通人承担的责任要少。公司之间也存在差异:私人股本公司在某种程度上比普通公司享有更大的回旋余地。只有两名勇敢的记者在报道中提到了金门的名字。
Payless 倒闭是因为它在一次杠杆收购中被私有化。他们失败不是因为他们的库存系统、缺乏熟练的鞋类销售人员、DSW、著名的鞋履或互联网。这些文章中的分析包括一个强有力的非推论,即“债务”以某种方式简单地出现,然后允许其他因素在企业中发生。在这种框架下,承担债务的行为者不仅无可指责,而且是隐形的。谁被允许进入购买所需的现金池?你如何申请做这样的事情?尽管是大规模杀伤性金融武器,为什么这种做法还在继续?我能像这样得到一堆钱吗?
开始改变报告的一个重要地方:为什么我们不能讨论谁积累了债务,作为我们报告零售破产的一个关键因素?我们不需要的是又一个招牌竖起、周六开始清算销售、债务突然出现的故事。
但是泡菜去哪里了呢?
原文:https://towardsdatascience.com/but-where-does-the-pickle-go-53619676bf5f?source=collection_archive---------39-----------------------
fast.ai《程序员实用深度学习》第五课
我正在学习 fast.ai 的“程序员实用深度学习”课程,并把我的经历写在博客上。由于非常慷慨的 fast.ai 社区已经为每一课做了详细的笔记(参见第 5 课的笔记,这里是),我只是写下讲座的部分内容,并附带 Jupyter 笔记本,我需要停下来思考几次。
从笔记本开始,我们导入 matplotlib 和 fast.ai 库:
%matplotlib inline
from fastai.basics import *
然后我们需要得到“腌制”的 MNIST 数据集,所以我下载它并试图找出我需要把它放在哪里。下面是笔记本中的下一行代码:
path = Config().data_path()/’mnist’
但是当我运行它时,我得到以下错误:
FileNotFoundError: [Errno 2] No such file or directory: '/home/jupyter/.fastai/data/mnist'
我检查笔记中的代码,它与笔记本不同:
path = Path('data/mnist')
看起来我们把数据放在了‘数据’子目录下的一个新文件夹里?好的,所以我在“数据”目录下创建了一个文件夹,命名为“mnist”,然后把 mnist.pkl.gz 上传到里面。那有效!
然后我们把图像展*,看到这个,比如,是数字 5:
下一个让我有点吃惊的是,杰里米谈到这些图像时说:“目前它们是 numpy 数组。我需要他们是张量。所以我可以把 torch.tensor 映射到它们上面,现在它们就是张量了。”我意识到我不知道 numpy 数组和张量之间的区别,所以我查了一下。事实证明,张量有许多不同的定义,其中一些直接相互矛盾。
最后,我决定伊恩·古德费勒的深度学习中的定义对我来说最有意义,无论如何,来自那本书意味着它对这些目的来说是正确的。Goodfellow 说:“在某些情况下,我们需要一个超过两个轴的阵列。在一般情况下,排列在具有可变轴数的规则网格上的数字阵列称为张量。”所以这符合那些说张量是多维数组的人,其中标量是 0 维张量,向量是 1 维张量,矩阵是 2 维张量。对我有用!我也通读了这个关于 numpy 如何处理张量运算的教程。
然后我做得很好,直到我们准备“线性化”我们的模型,而不是像我们在以前的课程中那样手动完成,Jeremy 说:“所以我们唯一想添加的是我们想在我们的类中创建一个包含线性层的属性,一个 nn。线性模块。什么是 nn?线性模块?它是做 x@a 的东西,但实际上它不仅仅做这个。它实际上是 x@a + b,换句话说,我们不需要把一列相加。这就是它的全部功能。如果你想玩玩,为什么不试着创建你自己的 nn。线性类?你可以创建一个叫做 MyLinear 的东西,这将花费你(取决于你的 PyTorch 背景)一两个小时。我们不希望这一切变得不可思议,现在你已经知道了创造这一切的所有必要条件。”
所以我盯着它看了几分钟,完全不知道该怎么做。我观察了它在下一个单元格中的调用方式:
class Mnist_Logistic(nn.Module):
def __init__(self):
super().__init__()
self.lin = nn.Linear(784, 10, bias=True)
def forward(self, xb): return self.lin(xb)
好的,我们给它传递图像的数量(784),10 (10 什么?),我们设置 bias=True,因为我们想给x@a
加上一个偏差,因此x@a + b.
我向下滚动笔记,记得 Jeremy 说:“我们的输入是 784 维的,我们需要能给出 10 个数的概率的东西。在这之后,我们有十个激活,然后我们想添加偏见,所以我们去了。”这就是 10 的由来。
但我不知道如何从那里开始,所以我转向 fast.ai 论坛,发现只有一个关于这个问题的帖子,没有任何回复,所以我想知道是否有很多人真的尝试这样做。本着真正的 fast.ai 精神,我决定把这个问题放在一边,继续下去,而不是陷入细枝末节。
我要停下来思考的下一点是损失函数的选择。在之前的课程中,我们使用了均方误差函数,即 MSE。当你做一个预测时,这个方法很有效,然后可以测量你的观察结果与你的预测“有多远”,如下所示。
freecodecamp.org
但是正如 Jeremy 所说,损失函数对于像这样的分类问题没有意义,因为我们没有考虑图像中表示的数字的数值:我们考虑的是图像本身。因此,在图像识别环境中,认为 3 比 0 更接* 4 是不合理的,因为如果我们认为我们看到的数字是 3,但它实际上是 4,那就和认为它是 0 一样错误。
所以他说我们将使用交叉熵损失来代替,它不仅考虑预测是正确还是不正确,还考虑做出预测的置信度。在下面的例子中,我们预测一张图片是一只猫还是一只狗。
Screenshot from Lesson 5
该图显示了电子表格中的计算,但这是 Python 版本的计算:
**def** CrossEntropy(Pred)Cat), Cat):
**if** Cat == 1:
**return** -log(Pred(Cat))
**else**:
**return** -log(1 - Pred(Cat))
用杰里米的话来说:“如果是一只猫,那么就取猫性的对数,如果是一只狗(即,否则),就取一减去猫性的对数(换句话说,就是狗性的对数)。”我们在否定结果,我认为这一定是因为结果本身是负的,但在文字中,我们指的是“损失”的价值,如果“损失”是负的,就像失去了一个负值;即加,不亏。所以损失为非负值是有意义的。
因此,我们计算每次迭代的交叉熵损失,然后将所有这些值相加,以找到模型作为一个整体的交叉熵损失。
第五课到此结束!第六课再见。
在 GitHub 上查看 MNIST 笔记本中的代码。
关于此主题的其他帖子:
第一课:fast . ai 入门
第二课:对验孕结果进行分类
第二课(续):深度学习能比鸽子表现更好吗?
第三课:一万种行不通的方法
第四课:预测服务员的小费
我是加州大学东湾分校的数学讲师,也是一名有抱负的数据科学家。在 LinkedIn 上和我联系,或者在 Twitter 上和我打招呼。
买家请注意,虚假产品评论正在困扰着互联网。机器学习如何帮助发现它们。
原文:https://towardsdatascience.com/buyers-beware-fake-product-reviews-are-plaguing-the-internet-cfc599c42b6b?source=collection_archive---------19-----------------------
使用机器学习识别虚假产品评论
例如,CBS 新闻报道,在 Walmart.com 发布的 52%的产品评论是“不真实或不可靠的”,而在亚马逊发布的评论中至少有 30%是假的。识别观点垃圾邮件的问题仍然是一个开放的话题,尽管事实上一些研究人员已经解决了这个问题。
是什么让商家招致产品欺骗性评论?主要驱动力是在竞争中领先,定位他们的产品或服务,以影响公众和组织进行购买,从而增加他们的销售。欺诈是通过张贴虚假的负面评论和给竞争对手的产品不公正的评级来进行的。
据了解,“亚马逊机械土耳其”,一个互联网众包市场,允许请求者(企业或个人)协调人力来执行一项任务,被用来为一家连锁酒店众包虚假评论。鉴于这一问题已经发展到令人担忧的程度,Yelp.com,一家发布众包评论的商业目录服务公司,发起了一项诱捕行动,以揭露那些购买虚假评论的商家。
我将讨论 Mukherjee 等人在他们的论文中提出的检测产品评论中垃圾邮件的方法。他们称他们的模型为“作者空间模型”(ASM)。它基于无监督学习,将空间建模为潜在的,简而言之就是模型变量是“隐藏的”。它也是一个贝叶斯推理框架。该模型的目的是将这种潜在的群体分布分类成垃圾邮件发送者和非垃圾邮件发送者。
请注意,当我提到产品时,我也将包括服务。
怎样才能识别一篇评论可能是假的?为了开发他们的模型,作者定义了九个变量作为观察到的特征,前五个他们将它们归类为值在区间[0,1]内的作者特征(表示 Beta 分布,其中接* 0 或 1 的值分别表示非垃圾邮件或垃圾邮件。另一方面,变量 5 至 9 代表评论特征,它们采用二进制值,0 代表非垃圾邮件,1 代表垃圾邮件(表示伯努利分布):
- 内容相似度【CS】。垃圾邮件发送者倾向于复制类似产品的评论。余弦相似度用于捕捉这些评论中的内容相似度。
- 最大评论数(MNR) 。同一个作者在一天内发表几篇评论的不寻常行为可能是垃圾邮件的迹象。
- 回顾突发性(BST)。指作者发布评论的频率(短)。这个作者通常是网站的新成员。满足这一条件可能意味着有招致欺骗性评论的倾向。
- 初审者比例(RFR) 。该指标量化了早期评论对新推出产品的销售产生影响的事实。
- 重复/*似重复的评论(DUP)。相同或*似相同的评论可能表示垃圾邮件行为。此功能类似于 CS,但在这种情况下属于 review 功能。
- 极限额定值(EXT)。为了给评论带来最大或最小的好处,垃圾邮件发送者通常会给产品标上一星或五星。
- 评级偏差(开发)。垃圾邮件发送者会通过放置他们的评论来转移评论的*均情绪。当这种量化的偏差超过阈值时,这些类型的审查被识别。
- 早期时间框架(ETF)。此功能捕获了评审的早期时间。基本原理是,垃圾邮件发送者最有可能更早地进行审查,接*产品的推出,以实现最大的影响。
- 评级滥用(RA)。指多次对同一产品进行星级评定的行为。
ASM 是如何工作的?为了说明这个模型,我在下面的图表中简化了它的功能(见图 1-A 和 1-B),关于数学表示请参考论文。
Figure 1-A
Figure 1-B
ASM 从接受所有作者的所有评论开始,这些评论是按照我们已经讨论过的特性组织的。每个球体代表一个可观察变量(即特征)。一旦特征被收集(见图 1-A 节点 A),它们被模型处理并学习“垃圾邮件和非垃圾邮件的潜在行为分布”(Murkherjee 等人)。因此,ASM 解决了一个聚类问题( K = 2)。
在贝叶斯环境中,空间被建模为潜在的 ASM 函数。这是一个 的生成过程 因为它发出了 9 个特征和它们的滥发概率。
为了进行推断,该模型使用“ ”折叠吉布斯采样”(CGS),其表示用于*似后验概率分布的技术。CGS 属于 马尔可夫链蒙特卡罗 算法家族。
一旦推断出排名函数,就使用 学习排名 监督技术对其进行处理,该技术基本上采用 ASM 获得的排名,并生成单个聚合排名函数(见图 1-A 节点 C)。
在我看来,这篇文章提出了一种技术,可以显著提高产品评论中意见垃圾邮件制造者的检测。这是一个创新,因为提出了一个无监督的方法来检测虚假评论。作者声称,与强大的竞争对手相比,他们已经实现了更高水*的准确性。我相信,随着越来越多提供此类信息的企业开始实施像 ASM 这样的 ML 技术,垃圾观点将开始减少,同时,消费者必须持怀疑态度,并使用过滤虚假评论的网站获得信息。
使用行为足迹发现观点垃圾邮件发送者
A 慕克吉, A 库玛, B 刘, J 王,M 许……—2013 年第十九届会议录——
针对门外汉的吉布斯采样
P 雷斯尼克,E 哈迪斯特 — 2010
统计分析中的贝叶斯推断
GC Tiao——2011——books.google.com GEP 盒子
加快潜在狄利克雷分配模型的标定,完善……
作者 JA lópez——2017 年
[## 买家当心:亚马逊、沃尔玛和其他主要零售商遭遇虚假评论的灾难
根据 Fakespot 的一项研究,虚假评论在许多顶级零售商网站上越来越普遍
www.cbsnews.com](https://www.cbsnews.com/news/buyer-beware-a-scourge-of-fake-online-reviews-is-hitting-amazon-walmart-and-other-major-retailers/)
— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — — -
亲爱的读者,我有兴趣从你那里知道:
- 当你在网上购物时,你会被当地的评论所影响吗?或者除此之外,你寻找一个或多个外部评论?
- 如果您使用产品评论网站,您更信任哪个网站?
- 你认为如何解决这个以惊人速度增长的问题?
感谢参与,可以留言评论回应。
在荷兰买房(书呆子气)
原文:https://towardsdatascience.com/buying-a-house-in-the-netherlands-in-a-nerdy-way-1433691c6f2a?source=collection_archive---------6-----------------------
如果你像我一样,当你不得不做出重大决定时,比如买房子,你可能会不知所措。在这种情况下,我总是喜欢采用数据驱动的方法,这将有助于我找到最佳解决方案。这涉及到两个步骤。首先,我们需要尽可能多地收集数据。其次,我们需要定义一个衡量成功的标准。
收集荷兰房价数据需要一些努力。我从 funda.nl 网站上获得了房价。需要注意的是,网站上的要价并不是房屋的实际售价。要价也没有明显偏向低于或高于售价,所以我无法纠正。这是处理真实数据时通常会发生的情况,它总是远非完美。
定义成功的衡量标准是个人的和主观的。我认为房子是一个不错的选择,如果:1。要价便宜;和/或,2。与投资相比,我可以从中获得的潜在租金很高。
- 为了知道要价是否便宜,我使用了网站上正在出售的房屋的要价,建立了一个机器学习模型,根据房屋的特点预测其要价。然后,我可以用那个模型来评估房子的要价应该是多少,如果实际要价低于模型预测的价格,那么我会认为这是一笔好交易。(注意:在这种情况下,好交易的定义是在数据集本身的范围内,而不是从市场价值的绝对角度;所以,举例来说,如果网站上的所有价格都是市场价格的两倍,我仍然可以通过比较房屋来获得一些不错的交易。
- 为了知道正在出售的房屋的租金价格,我使用了网站上提供的房屋出租数据,并建立了一个机器学习模型,根据房屋特征预测租金价格。然后,我可以用那个模型来评估一个正在出售的房子的租金价格应该是多少。如果要价与预期租金的比率很低,那么这意味着我可以租下房子,投资回收期很短。
最后一点需要注意的是,这里所做的所有分析都是针对静态数据的,不涉及价格趋势预测。
数据
从 funda.nl,我有 2019 年 7 月在阿姆斯特丹、Zaandam 和 Diemen 出售的 2150 套房屋和公寓的数据;出租的房屋和公寓有 1,046 套。
对于每栋房子,我都有以下数据(是的,网站是荷兰语的,你可以使用谷歌翻译):
['Aangeboden sinds', 'Aantal badkamers', 'Aantal kamers', 'Aantal woonlagen', 'Aanvaarding', 'Achtertuin', 'Badkamervoorzieningen', 'Balkon/dakterras', 'Bijdrage VvE', 'Bouwjaar', 'Capaciteit', 'Cv-ketel', 'Eigendomssituatie', 'Energielabel', 'Externe bergruimte', 'Gebouwgebonden buitenruimte', 'Gelegen op', 'Inhoud', 'Inschrijving KvK', 'Isolatie', 'Jaarlijkse vergadering', 'Lasten', 'Ligging', 'Ligging tuin', 'Onderhoudsplan', 'Oppervlakte', 'Opstalverzekering', 'Overige inpandige ruimte', 'Periodieke bijdrage', 'Reservefonds aanwezig', 'Schuur/berging', 'Servicekosten', 'Soort appartement', 'Soort bouw', 'Soort dak', 'Soort garage', 'Soort parkeergelegenheid', 'Soort woonhuis', 'Specifiek', 'Status', 'Tuin', 'Verwarming', 'Voorlopig energielabel', 'Voorzieningen', 'Vraagprijs', 'Warm water', 'Wonen', 'address']
我还使用以下代码创建了一些额外的功能:
def create_cols(df):
df[‘zip_code’]=df[‘address’].str.extract(pat=’([0–9]{4} [A-Z]{2})’)
df[‘zip_code’]=df[‘zip_code’].str.replace(‘ ‘, ‘’, regex=False)
df[‘zip_code_number’]=df[‘zip_code’].str.extract(pat=’([0–9]{4})[A-Z]{2}’).fillna(0).astype(int)
df[‘price’]=df[‘Vraagprijs’].str.extract(pat=’([0–9]{0,3}.?[0–9]{3}.[0–9]{3})’)
df[‘price’]=df[‘price’].str.replace(‘.’, ‘’, regex=False).astype(float)
df[‘nr_bedrooms’] = df[‘Aantal kamers’].str.extract(pat=’([0–9]) slaapkamer’).fillna(0).astype(int)
df[‘nr_rooms’] = df[‘Aantal kamers’].str.extract(pat=’([0–9]) kamer’).fillna(0).astype(int)
df[‘nr_floors’] = df[‘Aantal woonlagen’].str.extract(pat=’([0–9]) woonla’).fillna(0).astype(int)
df[‘nr_bathrooms’] = df[‘Aantal badkamers’].str.extract(pat=’([0–9]+) badkamer’).fillna(0).astype(int)
df[‘nr_toilet’] = df[‘Aantal badkamers’].str.extract(pat=’([0–9]+) aparte? toilet’).fillna(0).astype(int)
df[‘construction_year’]=df[‘Bouwjaar’].str.extract(pat=’([0–9]{4})’).astype(float)
df[‘cubic_space’] = df[‘Inhoud’].str.extract(pat=’([0–9]+) m’).fillna(0).astype(float)
df[‘external_storage_space’] = df[‘Externe bergruimte’].str.extract(pat=’([0–9]+) m’).fillna(0).astype(float)
df[‘outdoor_space’]=df[‘Gebouwgebonden buitenruimte’].str.extract(pat=’([0–9]+) m’).fillna(0).astype(float)
df[‘living_space’]=df[‘Wonen’].str.extract(pat=’([0–9]+) m’).fillna(0).astype(float)
df[‘montly_expenses’]=df[‘Bijdrage VvE’].str.extract(pat=’([0–9]+) per maand’).fillna(0).astype(float)
df[‘other_indoor_space’]=df[‘Overige inpandige ruimte’].str.extract(pat=’([0–9]+) m’).fillna(0).astype(float)
df[‘dont_have_frontyard’]=df[‘Achtertuin’].str.extract(pat=’(voortuin)’).isna()
df[‘not_straat’]=df[‘address’].str.extract(pat=’(straat)’).isna()
df[‘not_gracht’]=df[‘address’].str.extract(pat=’(gracht)’).isna()
df[‘not_plein’]=df[‘address’].str.extract(pat=’(plein)’).isna()
df[‘price_per_living_sqm’] = df[‘price’]/df[‘living_space’]
df[‘is_house’]=df[‘Soort appartement’].isnull()
df = df[df[‘price’].notna()]
df = df[df[‘living_space’]>0]
df = df[df[‘living_space’]<600]
df = df[df[‘price’]<4500000]
df[‘dont_have_backyard’] = df[‘Achtertuin’].isna()
df[‘backyard_size’] = df[‘Achtertuin’].str.extract(pat=’([0–9]+) m²’).fillna(0).astype(float)
df[‘has_garage’]=df[‘Soort garage’].isna()
df[‘total_area’] = df[‘outdoor_space’]+df[‘external_storage_space’]+df[‘living_space’]+df[‘other_indoor_space’]
df[‘address_nozip’]=df[‘address’].str.extract(pat=’^(.+)[0–9]{4} [A-Z]{2}’)
df[‘address_zip’]= df[‘address_nozip’] + ‘ ‘ + df[‘zip_code’]
df[‘parcela’]= df[‘Oppervlakte’].str.extract(pat=’([0–9]+) m’).fillna(0).astype(float)
df[‘price_per_parcela_sqm’] = df[‘price’]/df[‘parcela’]
return df
数据探索
需要导入包:
import pandas as pd
import re
import numpy as np
import seaborn as sns
import scipy.stats as stats
import matplotlib.pyplot as plt
from sklearn.model_selection import GridSearchCV, cross_val_score, KFold
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score
from sklearn.preprocessing import LabelEncoder
from xgboost import XGBRegressor
加载数据:
df = pd.read_csv('data_funda.csv',sep = ',', encoding = 'utf-16')
df = create_cols(df)
我们来看看价格、居住空间和建造年份是什么关系。由于价格和生活空间的偏态分布,我还创建了这些变量的对数转换值,并分别将其命名为 price_log1p 和 living_space_log1p(参见“特征分布”一节)。
# Price vs. Living space
p_cor = df[['living_space','price']].corr(method ='pearson') ['price'].living_space
df.plot.scatter(x='living_space',y='price',c='construction_year',colormap='viridis', figsize=[12,8], vmin=1900, vmax=2000,label="corr:"+str(round(p_cor,4)))
plt.legend()
p_cor = df[['living_space_log1p','price_log1p']].corr(method ='pearson') ['price_log1p'].living_space_log1p
df.plot.scatter(x='living_space_log1p',y='price_log1p',c='construction_year',colormap='viridis', figsize=[12,8], vmin=1900, vmax=2000,label="corr:"+str(round(p_cor,4)))
plt.legend()
你可以清楚地看到,房子越大,价格越高(咄!),但同样有点令人惊讶的是(如果你对阿姆斯特丹一无所知的话)同样的*方米,非常古老的房子比较新的房子要贵。这是因为位置!。阿姆斯特丹市中心很贵,那里的房子也很旧。从图中还可以看出,2000 年左右建造的房屋往往比 1980 年建造的房屋更大。
价格如何随着卧室数量的变化而变化?
# Total bedrooms vs. Price
sns.boxplot(x=df['nr_bedrooms'], y=df['price'])
plt.show()
sns.boxplot(x=df['nr_bedrooms'], y=df['price_per_living_sqm'])
plt.show()
房间数量越多,要价越高(左地块),很可能是因为房子比较大。但是,如果我们看到每*方米的价格是如何随着房间数量的变化而变化的(右图),它似乎是相当*坦的,除了 3、4 和 5 卧室的房子中位数更低。
位置,位置,位置!
房价很大程度上取决于房子的位置。让我们来看看价格分布如何随邮政编码而变化。
df[['price','zip_code_number']].boxplot(by='zip_code_number', figsize=[25,8], rot=45)
plt.ylabel('Price')
从图中您可以看到,有些邮政编码的房屋具有较高的中值价格和标准差(例如,市中心的邮政编码,如 1071、1077、1017),而有些邮政编码的价格一直较低(例如,1102、1103、1104,位于 Bijlmermeer 地区)。
事实上,我发现更有趣的是看到每*方米价格的分布与邮政编码。
ax=df[['price_per_living_sqm','zip_code_number']].boxplot(by='zip_code_number', figsize=[25,8], rot=45)
plt.ylabel('Price per sqm')
ax.set_ylim([2000,12500])
在没有任何机器学习知识的情况下,如果我们有固定的预算和最小*方米的要求,人们可以使用之前的地块来查看要探索的街区和要去看房子。因此,如果我们正在寻找一个至少 100 *方米的房子,并且希望花费不超过 40 万欧元,我们应该关注邮政编码,如 1024,1060,1067,1069,> 1102。当然,你可能会在邮编为 1056 的地方买到一栋低于预算的房子(离群值),但要做好准备,不得不花一些额外的钱来装修:)。
谈装修…每*米价格如何随施工年份变化?我们来画个图。
df_filt = df[(df['construction_year']>1900)&(df['construction_year']<2019)]
df_filt['construction_year_10'] = df_filt['construction_year']/10
df_filt['construction_year_10'] = df_filt['construction_year_10'].apply(np.floor)
df_filt['construction_year'] = df_filt['construction_year_10']*10
data = pd.concat([df_filt['price_per_living_sqm'], df_filt['construction_year']], axis=1)
f, ax = plt.subplots(figsize=(20, 8))
fig = sns.boxplot(x='construction_year', y="price_per_living_sqm", data=data)
fig.axis(ymin=1000, ymax=11000)
plt.xticks(rotation=45)
正如我们之前看到的,非常旧的房子每*方米的价格比新房子要高。这是因为那些老房子位于非常昂贵的邮政编码。因此,从每*方米价格最高的 1900 年开始,直到 1970 年,价格下降,然后从那一年开始,价格再次上涨。
为了全面了解每对特征是如何相互关联的,让我们来看看相关矩阵。
plt.figure(figsize=(20,12))
sns.heatmap(df.drop(columns='index').corr(), annot=False, square=True)
有太多的事情在那里发生,但它给了我们一个概念,什么变量是正相关的(如居住面积与卧室、房间、地板、浴室等的数量。)以及哪些是负相关的(例如,作为一栋房子而没有后院或前院,或者每月有开销)。
如果我们只关注与价格相关性最高的前 10 个变量,那么相关性矩阵如下所示:
corrmat = df.corr()
cols = corrmat.nlargest(10, 'price')['price'].index
hm = sns.heatmap(np.corrcoef(df[cols].values.T), cbar=True, annot=True, square=True, fmt='.2f', annot_kws={'size': 10}, yticklabels=cols.values, xticklabels=cols.values)
plt.show()
我们可以看到,价格与所有直接或间接与房子大小相关的变量高度相关。
我们可以做的最后一项质量检查是查看每个要素缺失值的百分比。
df_na = (df.isnull().sum() / len(df)) * 100
df_na = df_na.drop(df_na[df_na == 0].index).sort_values(ascending=False)[:40]
missing_data = pd.DataFrame({'Missing Ratio' :df_na})
plt.figure(figsize=(15, 9))
sns.barplot(x=df_na.index, y=df_na)
plt.xticks(rotation='80')
plt.ylabel('Percent of missing values', fontsize=15)
这些变量中的一些有缺失值,因为数据不是由房地产代理商/业主提供的(例如能源标签),而对于其他一些缺失值实际上意味着缺少它(例如车库或花园-tuin-)。
特征分布
为了建立预测房价的 ML 模型,让我们仔细看看特征直方图。我在这里只画两个例子:月支出(欧元)和生活空间(*方米)。
for col in df.describe().columns.values:
if col<>'price_per_parcela_sqm':
axs = df.hist(column=col,bins=50)
从左边的图中我们可以看到,一些房子(主要是公寓)每月都有开销(荷兰语称为 Bijdrage VvE ),*均在 100 欧元左右,而其他一些房子则完全没有。
从右图中,您可以看到居住空间分布的模式大约为 100 *方米。分布不是正态分布,而是高度右偏;价格分布也是如此。让我们仔细看看价格分布。
for col in df.describe().columns.values:
try:
sns.distplot(df[col], label="Skewness: {:.3f}".format(df[col].skew()))
plt.title(col+' Distribution')
plt.ylabel('Frequency')
plt.xticks(rotation=45)
plt.legend()
plt.show()
qq = stats.probplot(df[col], plot=plt)
plt.show()
except:
pass
如此高的偏斜度对于输入到 ML 模型的特征和标签来说是不期望的。因此,让我们继续记录具有高偏斜分布的变换变量。
# Assign numeric features by excluding non numeric features
numeric = df.dtypes[df.dtypes != 'object'].index# Display the skewness of each column and sort the values in descending order
skewness = df[numeric].apply(lambda x: x.skew()).sort_values(ascending=False)# Create a dataframe and show 5 most skewed features
sk_df = pd.DataFrame(skewness,columns=['skewness'])
sk_df['skw'] = abs(sk_df)
sk_df.sort_values('skw',ascending=False).drop('skw',axis=1).head()# As a general rule of thumb, skewness with an absolute value less than 0.5 is considered as a acceptable range of skewness for normal distribution of data
skw_feature = skewness[abs(skewness) > 0.5].index# Transform skewed features to normal distribution by taking log(1 + input)
for col in skw_feature:
df[col+"_log1p"] = np.log1p(df[col])# let's check the result of the transformation
sns.distplot(df['price_log1p'],label="Skewness: {:.3f}".format(df['price_log1p'].skew()))
plt.legend()
plt.title('Price Log(price + 1) transform Distribution')
plt.ylabel('Frequency')plt.figure()
qq = stats.probplot(df['price_log1p'], plot=plt)
plt.show()
我们可以看到,对价格值进行对数变换后,分布更接*于正态分布(尽管还不完美)。
价格预测 ML 模型
数据探索到此为止,让我们建立一个 ML 模型!。
首先,让我们定义将要使用的特性。
#Label encoding
feat_enc = ['zip_code_number']# Features
feat_cols = ['nr_bedrooms','nr_rooms','nr_floors','nr_bathrooms','nr_toilet','zip_code_number_le','is_house','has_garage','dont_have_backyard','not_straat','not_gracht','not_plein','has_frontyard','backyard_size_log1p','living_space_log1p','cubic_space_log1p','outdoor_space_log1p','total_area_log1p','montly_expenses_log1p','parcela_log1p','construction_year']
我们将训练一个 XGBoost 回归模型,为超参数调整做一些小网格搜索,并且我们将使用交叉验证。
df_filt = df[df['price']<700000]#Missing values, impute with mode
for fr in ['construction_year']:
df_filt[fr].fillna(df_filt[fr].mode()[0], inplace=True)#Label encoding
for feat in feat_enc:
le = LabelEncoder()
le.fit(df_filt[feat])
df_filt[feat+'_le'] = le.transform(df_filt[feat])label='price_log1p'x = df_filt[feat_cols]
y = df_filt[label]
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.1, random_state=1)
print(X_train.shape, X_test.shape,y_train.shape)kfold = KFold(n_splits=5, random_state= 0, shuffle = True)def performance_metric(y_true, y_predict):
""" Calculates and returns the performance score between
true (y_true) and predicted (y_predict) values based on the metric chosen. """
score = r2_score(y_true, y_predict)
return scoreXGB = XGBRegressor()xg_param_grid = {
'n_estimators' :[900,400,1200],
'learning_rate': [0.04, 0.06, 0.08],
'max_depth': [3,6,8],
'min_child_weight':[0.2],
'gamma': [0,1],
'subsample':[0.8],
'colsample_bytree':[1]
}
gsXGB = GridSearchCV(XGB,param_grid = xg_param_grid, cv=kfold, scoring="neg_mean_squared_error", n_jobs= -1, verbose = 1)
gsXGB.fit(X_train,y_train)
XGB_best = gsXGB.best_estimator_
print(gsXGB.best_params_)
y_hat_xgb = np.expm1(gsXGB.predict(X_test))
让我们检查模型的性能。
r2_train = performance_metric(np.expm1(y_train), np.expm1(gsXGB.predict(X_train)))
r2_test = performance_metric(np.expm1(y_test), y_hat_xgb)
print "R2 train: ", r2_train
print "R2 test: ", r2_test
plt.scatter(np.expm1(y_train), np.expm1(gsXGB.predict(X_train)),label='R2:'+str(round(r2_train,4)))
plt.title('Train')
plt.xlabel('Price')
plt.ylabel('Price predicted')
plt.plot([100000,700000], [100000,700000], 'k-', alpha=0.75)
plt.legend()
plt.show()plt.scatter(np.expm1(y_test), y_hat_xgb,label='R2:'+str(round(r2_test,4)))
plt.plot([100000,700000], [100000,700000], 'k-', alpha=0.75)
plt.title('Test')
plt.xlabel('Price')
plt.ylabel('Price predicted')
plt.legend()
plt.show()
相关性高,这很好,从图中你可以看到一些要价的垂直模式。这是由于房地产经纪人/业主四舍五入价格。
查看特征重要性也很有用,可以了解哪些特征有助于预测房价。
from xgboost import plot_importanceplot_importance(XGB_best)
plt.show()
正如我们在数据探索部分已经看到的,房价与房子的位置、建造年份和大小高度相关。
现在,让我们使用模型来预测房价,并寻找要价低于预测价格的房屋。
Xtt = pd.concat([X_train,X_test],axis=0)
ypred=pd.DataFrame([np.expm1(gsXGB.predict(Xtt)),Xtt.index]).transpose()
ypred.columns = ['pred','idx']
ypred.set_index('idx',inplace=True)
ytt = ypred.join(df_filt)
ytt['ratio'] = ytt['price']/ytt['pred']
ytt['difference'] = ytt['price'] - ytt['pred']
现在,我希望看到室内面积超过 100 *方米、室外面积超过 5 *方米、要价和预测价格之间的差距非常大的房子:
x=ytt[['ratio','pred','price','outdoor_space','dont_have_backyard','dont_have_frontyard','living_space','nr_floors','difference','href']].sort_values(by='ratio')
print x[ (x['outdoor_space']>5)& (x['living_space']>100) ].head(10)
让我们看一个例子:
ratio pred price outdoor_space living_space difference
0.814140 368487 300000 16 116 -68487
href: [https://www.funda.nl/koop/zaandam/huis-40278208-lindenlaan-1/?navigateSource=resultlist](https://www.funda.nl/koop/zaandam/huis-40278208-lindenlaan-1/?navigateSource=resultlist)
在这里,预测价格和要价之间的差异是-68K 欧元。我在 huispedia.nl 上查了一下,根据他们的说法,那栋房子 30 万欧元似乎也很划算(尽管他们预测价值在 37.1 万到 39.7 万欧元之间)。当然,这是做出如此重大决定的冷酷无情的方式,但你仍然需要点击链接,查看照片,看看你是否不介意橙色的墙壁和倾斜的天花板。
租金预测
以类似的方式,我使用从 funda.nl 获得的租金价格来建立 ML 模型,该模型预测给定房屋特征的租金价格。我不打算描述确切的方法,但我使用租金模型来估计网站上正在出售的 2,150 所房屋和公寓的租金价值(我们没有租金价格)。
我使用租金预测来估计如果我买了房子后再出租,每套房子的回收期是多少(我称之为 ratio_sell_rent_year )。为了计算它,我将价格除以租金预测,再除以 12,得到一个年单位。
最后,我按邮政编码绘制了 ratio_sell_rent_year,看看哪些地区在投资回报方面比较方便。
ytt['ratio_sell_rent'] = ytt['price']/ytt['rent_prediction']
ytt['ratio_sell_rent_year'] = ytt['ratio_sell_rent'] /12
ax=ytt[['ratio_sell_rent_year','zip_code_number']].boxplot(by='zip_code_number', figsize=[25,8], rot=45)
ax.set_ylim([0,50])
像 1019/25、1032/6 和 1102/8 这样的邮政编码似乎投资回收期较短,*均为 15 年。
与要价 ML 模型类似,我使用租金模型来获得室内面积超过 100 *方米、室外面积超过 5 *方米且比率 _ 销售 _ 租金 _ 年值较低的房屋:
ratio_sell_rent_year ratio_sell_rent rent_prediction price outdoor_space living_space
7.932343 95.188121 3571.874268 340000.0 46.0 166.0
href: [https://www.funda.nl/koop/amsterdam/huis-40067181-moestuinlaan-12/?navigateSource=resultlist](https://www.funda.nl/koop/amsterdam/huis-40067181-moestuinlaan-12/?navigateSource=resultlist)
我不知道那栋房子的租金价格是多少,但我发现它旁边有一栋非常相似的房子这里。带家具、约 50 *方米大的房子租金为 7000 欧元。我实际上从外面去看了那栋房子,看起来像是我喜欢住的房子,但是当我们联系荷兰房地产经纪人时,房子已经卖完了。可悲的是,在阿姆斯特丹找房子的最佳方式似乎不是花里胡哨的 ML,而是快速行动😅。
有用的链接
- 查看荷兰的房价,以及基于 ML 模型的估计范围价格: huispedia.nl
- 查看阿姆斯特丹房价每*方米地图: maps.amsterdam.nl
- 查看 Mike 关于在阿姆斯特丹买房的精彩帖子:https://medium . com/@ MTO Connor 3/exploring-housing-prices-in-Amsterdam-b1d 3848 BDC 01
字节对编码——现代自然语言处理的黑马
原文:https://towardsdatascience.com/byte-pair-encoding-the-dark-horse-of-modern-nlp-eb36c7df4f10?source=collection_archive---------3-----------------------
1994 年首次推出的一种简单的数据压缩算法为当今几乎所有先进的 NLP 模型(包括 BERT)提供了增压。
背景
在 NLP 领域,过去几年是一段激动人心的时光。从稀疏的基于频率的词向量到密集的语义词表示预训练模型的演变,如 Word2vec 和 GloVe 为学习词义奠定了基础。多年来,它们作为可靠的嵌入层初始化,在缺乏大量特定任务数据的情况下训练模型。由于在维基百科上预先训练的单词嵌入模型要么受到词汇量的限制,要么受到单词出现频率的限制,像athazagoraphobia
这样的罕见单词将永远不会被捕获,从而导致在文本中出现未知的<unk>
标记。
处理生僻字
抛开字符级嵌入不谈,爱丁堡大学的研究人员通过使用字节对编码(BPE)在神经机器翻译中应用子词单元,在解决生僻字问题上取得了第一次真正的突破。今天,受 BPE 启发的子词标记化方案已经成为大多数高级模型的规范,包括非常流行的上下文语言模型家族,如 BERT 、 GPT-2 、罗伯塔等。有些人把伯特称为新时代的开端,然而,我认为 BPE 是这场竞赛中的一匹黑马,因为它在现代 NLP 模型的成功中没有得到应有的关注。在本文中,我计划更详细地介绍字节对编码是如何实现的,以及它为什么工作!
字节对编码的起源
像许多其他受传统科学启发的深度学习应用一样,字节对编码(BPE)子词标记化也深深植根于一种简单的无损数据压缩算法中。Philip Gage 在 1994 年 2 月版的 C Users Journal 的文章“A New Algorithm for Data Compression”中首次介绍了 BPE,这是一种数据压缩技术,它通过用一个不在数据中出现的字节替换常见的连续字节对来工作。
将 BPE 重新用于子词标记化
为了执行子词标记化,BPE 在其实现中被稍微修改,使得频繁出现的子词对被合并在一起,而不是被另一个字节替换以实现压缩。这将基本上导致罕见的单词athazagoraphobia
被分成更频繁的子单词,例如['▁ath', 'az', 'agor', 'aphobia'].
第 0 步。初始化词汇。
第一步。将语料库中的每个单词表示为字符的组合以及特殊的单词结束标记</w>
。
第二步。迭代统计词汇表所有记号中的字符对。
第三步。合并最频繁出现的对,将新字符 n-gram 添加到词汇表中。
第四步。重复步骤 3,直到完成期望数量的合并操作或达到期望的词汇大小(这是一个超参数)。
是什么让 BPE 成为秘制酱?
BPE 带来了字符和单词级混合表示之间的完美*衡,这使得它能够管理大型语料库。这种行为还支持使用适当的子词标记对词汇表中的任何罕见单词进行编码,而不会引入任何“未知”标记。这尤其适用于像德语这样的外语,在德语中,许多复合词的存在会使学习丰富的词汇变得困难。有了这种记号化算法,现在每个单词都可以克服他们对被遗忘的恐惧(athazagoraphobia)。
参考
- 菲利普·盖奇,一种新的数据压缩算法。《多布斯博士杂志》
- 森里奇(r .)、哈多(b .)、伯奇(a .)(2015 年)。具有子词单元的生僻字的神经机器翻译。 arXiv 预印本 arXiv:1508.07909 。
- Devlin,j .,Chang,M. W .,Lee,k .,& Toutanova,K. (2018 年)。Bert:用于语言理解的深度双向转换器的预训练。 arXiv 预印本 arXiv:1810.04805 。
- 刘,y .,奥特,m .,戈亚尔,n .,杜,j .,乔希,m .,陈,d,…和斯托扬诺夫,V. (2019)。Roberta:稳健优化的 bert 预训练方法。 arXiv 预印本 arXiv:1907.11692 。
数据科学的 c?
原文:https://towardsdatascience.com/c-for-data-science-8321d6509484?source=collection_archive---------9-----------------------
在数据科学领域,有许多语言可以用于统计分析和机器学习。通常,在这些情况下,语言的选择仅仅依赖于语言能够提供的功能。流行的选择包括像 R 和 Python 这样的统计语言。面向对象的编程语言经常被忽略,因为与函数式语言相比,它们的结构很难处理。
这一点在现代计算公式中最重要的语言之一 c 语言中表现得最为真实。
除非你曾经在岩石下编程,即使你曾经这样做过,你也可能听说过 C。C 是一种非常低级的语言,它也具有灵活进入真正高级开发领域的优势。虽然 C 语言是通用的,但 C 语言通常需要很长时间才能达到高水*。
这就是为什么有那么多语言是由 C 编写和解释的,比如 Python。但如果 Python 对数据科学如此伟大,为什么它的母亲不能持有同样的观点?
在很多方面,C 对于数据科学来说是完全可以接受的。这是因为像 C 的商标操作这样的低级语言是移动和管理数据的,因为这是低级语言的最大部分。但是确实有很多属性使得 C 语言不如 Python 这样的语言可行,例如。
实际上面向对象
尽管 Python 确实是面向对象的,但 Python 也拥有许多功能强大的特性。在一般的软件中,这往往是一个共同的主题。一种语言没有必要非此即彼,那么为什么不把两者的独特部分结合起来呢?
另一方面,C 天生就是百分之百通用的,但不管怎样,这对数据科学来说不一定是可怕的,但肯定可以更好一点。这不仅让初学者更加困难,也让数据科学家更加困难。当在数据科学中来回工作时,拥有一种具有更多函数属性的语言,函数可以在类之外运行,而不需要不断的回调,肯定会容易得多。
c 很难
从来不推荐 C 作为你的第一语言是有原因的;与 Python 等解释型语言以及其他语言相比,C 语言无疑是最难的语言之一。而且机器学习编程可能会出奇的难,尤其是在没有库的情况下从头开始。随之而来的是 Cs 最大的缺点,以及将 C 用于数据科学的致命弱点:
有这么多更简单、更好的语言(针对 DS)
那么为什么要用 C 呢?
除了很难写之外,C 语言也很难读,尤其是对于那些有大量数学运算的混乱的程序员来说。在大多数情况下,没有必要仅仅为了使用 c 就把能够阅读你的代码的程序员的数量分成 1/5,记住这一点,c 肯定有一些可取之处。
为什么它对数据科学有好处
在笔记本之外,在管道和数据软件工程领域,当机器学习算法本身也是用 C 语言编写时,许多强大的 C 代码基础会显著受益。对于使用 DS 的软件工程来说,C 语言对于知道如何使用它的每个人来说绝对是天赐之物。由于 Python 的速度问题,Python 通常在很多密集的情况下表现不佳。
除此之外,使用 C 的 Python 包的数量也令人印象深刻。不仅如此,就相对高级的编程而言,C 通常是最快的选择。
使用 C
我使用 C 已经很长时间了,但是我从来没有在数据科学中使用过 C。我最接*这样的事情是能够读写 CSV 文件。
但凡事都有第一次。
带着这个想法,我第一次去读 CSV。这相对简单,如下所示:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char* getfield(char* line, int num)
{
const char* tok;
for (tok = strtok(line, ";");
tok && *tok;
tok = strtok(NULL, ";\n"))
{
if (!--num)
return tok;
}
return NULL;
}
int main()
{
FILE* stream = fopen("l", "r");
char line[1024];
while (fgets(line, 1024, stream))
{
char* tmp = strdup(line);
printf("Field 3 would be %s\n", getfield(tmp, 3)); return l;
}
}
现在是时候尝试一种算法了。我不想花太多的时间去创建一个构造函数,因为多亏了内核执行,我们可以把每个类命名为 main 并以这种方式运行函数。
int main()
{
int summation(arr) {
int arr[MAX_SIZE];
int i, n, sum=0;
for(i=0; i<n; i++)
{
scanf("%d", &arr[i]);
}
for(i=0; i<n; i++) { sum = sum + arr[i]; } return sum; }int length(arr){for(i=0; i<n; i++) { sum = sum + 1;
}
return sum;
}**int** llsq(**int** x[], **int** y[],xt[])
{
x = m.x
y = m.y
# Summatation of x*y
xy = x .* y
sxy = sum(xy)
# N
n = length(x)
# Summatation of x^2
x2 = x .^ 2
sx2 = sum(x2)
# Summatation of x and y
sx = sum(x)
sy = sum(y)
# Calculate the slope:
slope = ((n*sxy) - (sx * sy)) / ((n * sx2) - (sx)^2)
# Calculate the y intercept
b = (sy - (slope*sx)) / n
# Empty prediction list:
y_pred = []
for i in xt
pred = (slope*i)+b
append!(y_pred,pred)
return y_pred;}}
所以我认为,从创建一个函数来完成获取和操作数据所需的许多事情所用的代码行来看,C 语言显然不太适合数据科学。并不是说 C 在数据科学中没有一席之地,但是在很多方面,在数据科学和机器学习的特定情况下,使用更简单的语言比使用 C 容易得多,从而证明使用像 C 这样的低级语言是正确的。
通常,统计被区分为高级的函数式编程。这是有充分理由的,因为用 C 编写与我们用 Python、R 和 Scala 编写的算法相似的算法尤其困难,并且需要更多的方法。
计算相似性——简而言之,最相关的指标
原文:https://towardsdatascience.com/calculate-similarity-the-most-relevant-metrics-in-a-nutshell-9a43564f533e?source=collection_archive---------2-----------------------
Photo by Karolina Grabowska on Pexels
许多数据科学技术都基于测量对象之间的相似性和不相似性。例如,K-最*邻使用相似性来分类新的数据对象。在无监督学习中,K-Means 是一种聚类方法,它使用欧几里德距离来计算聚类质心与其指定的数据点之间的距离。推荐引擎使用基于邻居的协作过滤方法,该方法基于与其他用户的相似性/不相似性来识别个人的邻居。
在这篇博文中,我将看看实践中最相关的相似性度量。可以用多种方式来测量对象之间的相似性。
通常,我们可以将相似性度量分为两个不同的组:
- 基于相似性的指标:
- 皮尔逊相关
- 斯皮尔曼相关
- 肯德尔氏τ
- 余弦相似性
- 雅克卡相似性
2.基于距离的指标:
- 欧几里得距离
- 曼哈顿距离
基于相似性的度量
基于相似性的方法确定具有最高值的最相似的对象,因为这意味着它们生活在更*的邻域中。
皮尔逊相关
相关性是一种研究两个定量连续变量之间关系的技术,例如年龄和血压。皮尔逊相关系数是与线性关系的强度和方向相关的度量。我们用以下方式计算向量 x 和 y 的度量:
在哪里
皮尔逊相关可以取值范围从-1 到+1。只有直接相关的增加或减少不会导致 1 或-1 的皮尔逊相关。
Source: Wikipedia
用 Python 实现:
import numpy as np
from scipy.stats import pearsonr
import matplotlib.pyplot as plt# seed random number generator
np.random.seed(42)
# prepare data
x = np.random.randn(15)
y = x + np.random.randn(15)# plot x and y
plt.scatter(x, y)
plt.plot(np.unique(x), np.poly1d(np.polyfit(x, y, 1))(np.unique(x)))
plt.xlabel('x')
plt.ylabel('y')
plt.show()
# calculate Pearson's correlation
corr, _ = pearsonr(x, y)
print('Pearsons correlation: %.3f' % corr)
皮尔逊相关系数:0.810
斯皮尔曼相关
Spearman 相关就是所谓的非参数统计,即分布不依赖于参数的统计(服从正态分布或二项式分布的统计就是参数统计的例子)。通常,非参数统计对数据进行排序,而不是取初始值。斯皮尔曼相关系数就是如此,其计算方法与皮尔逊相关类似。这些指标的区别在于,Spearman 的相关性使用每个值的排名。
为了计算 Spearman 相关性,我们首先需要将我们的每个数据映射到排名数据值:
如果原始数据为[0,-5,4,7],则排名值将为[2,1,3,4]。我们可以用下面的方法计算 Spearman 相关性:
在哪里
斯皮尔曼的相关性基准单调关系,因此它可以有完美的非线性关系。它可以取值范围从-1 到+1。下面的情节阐明了皮尔逊和斯皮尔曼相关性之间的区别。
Source: Wikipedia
对于数据探索,我建议计算皮尔逊和斯皮尔曼的相关性。两者的比较会产生有趣的发现。如果 S>P(如上图),说明我们是单调关系,不是线性关系。由于线性简化了将回归算法拟合到数据集的过程,我们可能希望使用对数变换来修改非线性的单调数据,使其看起来是线性的。
用 Python 实现:
from scipy.stats import spearmanr
# calculate Spearman's correlation
corr, _ = spearmanr(x, y)
print(‘Spearmans correlation: %.3f’ % corr)
斯皮尔曼相关系数:0.836
肯德尔氏τ
肯德尔的τ和斯皮尔曼的相关系数很相似。这两个度量都是关系的非参数度量。具体来说,Spearman 和 Kendall 的系数都是基于排名数据而不是原始数据计算的。
与 Pearson 和 Spearman 的相关性类似,Kendall 的 Tau 总是在-1 和+1 之间,其中-1 表示两个变量之间的强负关系,1 表示两个变量之间的强正关系。
尽管 Spearman 和 Kendall 的测量值非常相似,但选择 Kendall 的测量值具有统计学优势,因为在使用较大样本量时,Kendall 的 Tau 具有较小的可变性。然而,Spearman 的度量在计算上更高效,因为 Kendall 的 Tau 是 O(n),而 Spearman 的相关性是 O(nLog(n))。
第一步是对数据进行分级:
然后我们计算肯德尔的τ值为:
其中 sgn 采用与排序值的差异相关联的符号。我们可以写
如下所示:
的可能结果
是-1,0,+1。这些相加给出了 x 和 y 的等级指向相同方向的次数的比例。
用 Python 实现
# calculate Pearson’s correlation
from scipy.stats import kendalltau
corr, _ = kendalltau(x, y)
print(‘Kendalls tau: %.3f’ % corr)
肯德尔斯τ:0.695
余弦相似性
余弦相似度计算两个向量之间角度的余弦。为了计算余弦相似性,我们使用以下公式:
回想一下余弦函数:左边的红色向量指向不同的角度,右边的图形显示了结果函数。
Source: mathonweb
因此,余弦相似度可以取-1 和+1 之间的值。如果向量指向完全相同的方向,余弦相似度为+1。如果向量指向相反的方向,余弦相似度为-1。
Source: O’Reilly
余弦相似度在文本分析中非常普遍。它用于确定文档之间的相似程度,而不考虑文档的大小。TF-IDF 文本分析技术有助于将文档转换成向量,其中向量中的每个值对应于文档中一个单词的 TF-IDF 得分。每个单词都有自己的轴,余弦相似度决定了文档的相似程度。
用 Python 实现
我们需要使用来改变向量 x 和 y 的形状。reshape(1,-1) 计算单个样本的余弦相似度。
from sklearn.metrics.pairwise import cosine_similarity
cos_sim = cosine_similarity(x.reshape(1,-1),y.reshape(1,-1))
print('Cosine similarity: %.3f' % cos_sim)
余弦相似度:0.773
雅克卡相似性
余弦相似度用于比较两个实值向量,而 Jaccard 相似度用于比较两个二元向量(集)。
在集合论中,看到公式的可视化通常是有帮助的:
我们可以看到 Jaccard 相似性将交集的大小除以样本集的并集的大小。
余弦相似度和雅克卡相似度都是计算文本相似度的常用度量。计算 Jaccard 相似性在计算上更昂贵,因为它将一个文档的所有术语与另一个文档匹配。Jaccard 相似性在检测重复项时非常有用。
用 Python 实现
from sklearn.metrics import jaccard_score
A = [1, 1, 1, 0]
B = [1, 1, 0, 1]
jacc = jaccard_score(A,B)
print(‘Jaccard similarity: %.3f’ % jacc)
雅克卡相似度:0.500
基于距离的度量
基于距离的方法优先考虑具有最低值的对象,以检测它们之间的相似性。
欧几里得距离
欧几里德距离是两个向量之间的直线距离。
对于两个矢量 x 和 y,可以计算如下:
与余弦和 Jaccard 相似性相比,欧几里德距离在 NLP 应用的上下文中并不经常使用。它适用于连续的数值变量。欧几里德距离不是比例不变的,因此建议在计算距离之前缩放数据。此外,欧氏距离会成倍增加数据集中冗余信息的影响。如果我有五个高度相关的变量,我们将这五个变量都作为输入,那么我们将用五来加权这个冗余效应。
用 Python 实现
from scipy.spatial import distance
dst = distance.euclidean(x,y)
print(‘Euclidean distance: %.3f’ % dst)
欧几里德距离:3.273
曼哈顿距离
与欧几里得距离不同的是曼哈顿距离,也称为“城市街区”,即一个向量到另一个向量的距离。当您无法穿过建筑物时,您可以将此度量想象为计算两点之间距离的一种方法。
我们计算曼哈顿距离如下:
绿线给出的是欧几里德距离,而紫线给出的是曼哈顿距离。
Source: Quora
在许多 ML 应用中,欧几里得距离是选择的度量。然而,对于高维数据,曼哈顿距离是优选的,因为它产生更稳健的结果。
用 Python 实现
from scipy.spatial import distance
dst = distance.cityblock(x,y)
print(‘Manhattan distance: %.3f’ % dst)
曼哈顿距离:10.468
摘要
这篇博文概述了实践中使用的最相关的相似性度量。没有简单的如果-那么流程图来选择合适的相似性度量。我们首先需要理解和研究这些数据。然后,对于给定的数据科学问题,找到量化相似性的正确方法总是一个案例一个案例的决定。
参考资料:
https://bib.dbvis.de/uploadedFiles/155.pdf
http://text2vec.org/similarity.html
http://www.ijaret.org/2.10/COMPARATIVE%20ANALYSIS%20OF%20 JAC card% 20 系数% 20 余弦% 20 相似度% 20FOR % 20WEB %文档% 20 相似度%20MEASURE.pdf
使用移位β几何模型计算客户终身价值
原文:https://towardsdatascience.com/calculating-customer-lifetime-values-using-a-shifted-beta-geometric-model-86bf538444f4?source=collection_archive---------8-----------------------
Phot by Ihor Malytskyi on Unsplash
客户终身价值(CLV)是一个关键指标,被视为公司的北极星指标和所有综合 KPI,用于提供以下信息:
- 营销活动——我们应该花多少钱来获得客户?
- 客户细分——谁是我们最有价值的客户,他们的人口统计和行为特征是什么?
- 业务的整体健康状况——我们的 CLV 如何随着时间的推移而变化?
- 公司总价值——我们如何评估我们的现有和未来客户的价值?
但是什么是 CLV 呢?
当前客户的所有未来现金流的现值
在高层次上,为了估算你的 CLV,你需要了解两个简单的客户属性;a 客户生命周期和他们产生的经常性收入。顾客支付的越多,他们作为顾客停留的时间越长,他们的 CLV 就越大。
本帖将关注更具挑战性的部分——衡量客户的生命周期,这需要你了解你的企业当前的保留率。
本文旨在提供一种端到端的稳健方法来估算客户的终身价值。
CLV 公式中的常见陷阱
以下公式通常用于计算大多数经常性收入业务的 CLV。
然而,这种方法有 3 个主要问题:
问题#1:未能考虑不确定性
该公式计算出一个表示预期客户终身价值(或*均值)的数字。它忽略了我们估计中的任何不确定性。例如,在 SaaS 的企业中,客户对收入的贡献可能会有很大的不同,尤其是如果您有不同的服务计划(基本与高级)。
问题#2:恒定的保留率
可以说,最重要的问题是在你的客户中使用一个总留存率。所提议方法的本质是考虑不同客户的不同保留率。稍后会有更多内容。
问题#3:一刀切
2 固有的商业维度应该影响你的 CLV 方法。
契约性与非契约性:在契约性业务(如网飞、SaaS、信用卡)中,明显观察到客户流失。例如,大多数 SaaS 客户都是基于订阅的,因此客户必须取消订阅才能流失。非合同性企业(如在线零售、杂货店)不知道客户的最后一次购买是否真的是他们的最后一次购买,或者他们最终是否会再次购买。
连续 vs 离散:交易频率是第二维度。在的网飞和健身俱乐部等离散支付环境中,客户以固定周期(即每月、每年)支付。在持续的支付环境中,如亚马逊、信用卡,支付更不可预测。例如,尽管信用卡公司知道你何时流失(合同规定的),但他们不知道你在某个月产生交易的频率。
传统上预测保留
上述问题都会影响我们如何评估客户的生命周期。 这篇文章的剩余部分将展示一种更可靠的方法来评估你的客户的保留率,特别是在契约式的离散业务中。
数据
假设有一个跟踪逐年保持率的混合客户表。绿色值反映了当前活跃的客户。
Annual Customer Cohort Retention
保留率、流失率和存活率
保留率反映了在随后的周期中存活下来的客户的百分比。流失率是留存率的补充(即 1 减去留存率)。存活率反映了自开始阶段以来,从存活到的客户的百分比。在时间 t 的存活率可以定义为:
Survival at time t where r_t = retention rate at time t
让我们来计算我们最老的群组——群组 0——的保留率和流失率:
Annual Retention and Churn Rates for Cohort 0r1 = 84% (840 / 1000) --> c1 = 1 - .84 = 16%
r2 = 73% (618 / 840) --> c2 = 1 - .73 = 27%
r3 = 92% (570 / 618) --> c3 = 1 - .92 = 8%
r4 = 91% (519 / 570) --> c4 = 1 - .91 = 9%Average Retention = 85%
相同群组的最终存活率:
Annual Survival Rates for Cohort 0
S1 = r1 = 84%
S2 = r1 * r2 = 84% * 73% = 61%
S3 = r1 * r2 * r3 = 84% * 73% * 92% = 57%
S4 = r1 * r2 * r3 * r4 = 84% * 73% * 92% * 91% = 52%
挑战变成预测保留率和存活率,超越我们最老的队列;我们不知道来自群组 0 的 519 个当前客户明年(第 5 年)会有多大比例存活。
我们如何将 4 年的数据和预测扩展到 5 年以上?
一种方法是采用所有年份的*均留存率并进行预测。
Forecast survival rate using average retention
上面的图表反映了我们每个队列的存活率。这些队列的*均保留率约为 84.4%,可用于使用生存公式预测所有时间 t 的存活率。
从使用*均保留率的图表中可以看出,到第 9 年,群组中只有约 20%的客户会保留下来(.844⁹)。下一节提出了预测保留的另一种方法。
移位贝塔几何分布
对于具有离散支付周期的合同业务,sGB 模型是预测留存率的好方法。尽管这篇文章不会涉及数学细节,但它将有助于围绕这种方法发展一些基本的直觉。
Retention Rate for sGB Model
上面的公式是 sGB 在时间 t 的保留率。参数α,β需要以最适合我们报道数据的方式进行估计。让我们围绕公式建立一些直觉:
Assume α = 2 and β = 10:r1 = (10+1-1) / (2+10+1-1) = 83.3%
r2 = (10+2-1) / (2+10+2-1) = 84.6%
...
r5 = (10+5-1) / (2+10+5-1) = 87.5%
请注意,保持率不仅不再是恒定的,而且还会随着时间的推移而增加。这微妙地提供了灵活性,以更准确地对保留行为建模,并且是使用 sGB 模型的关键增强。
保留异质性对生存曲线的影响
因为流失率和保留率是互补的,了解其中一个使我们能够衡量另一个。β分布是一种灵活的分布,用于使用前面提到的参数α和β来模拟流失率。
下图使用 beta 分布,根据抽样的流失概率对生存曲线的类型进行了分类。每个象限都有一对图表——左边的图表是给定α和β的流失率,右边的图表是其对应的生存曲线。
Survival Curves using various churn rate distributions
以下是解释,展示了不同的流失率如何影响存活率。
模型开发—求解α和β
剩下的问题是“我如何确定α和β参数对我的业务是什么?”。模型参数的最大似然估计 (MLE)允许我们估计最适合我们企业观察到的综合数据的参数。
Log-Likelihood Function
TL;DR 找出使上述函数的输出最大化的α和β的值
用概率方法求解α和β
有许多方法可以优化上面的对数似然函数,如 scipy、pymc3,甚至是 excels solver 加载项。然而,如果您想通过概率优化来考虑参数估计中的不确定性, pymc3 是一个很好的选择。使用 pymc3,您可以对后验分布进行采样,以查看我们的参数的可能值,如下所示。
结果:α和β后验分布
我们可以对后验分布进行采样,并可视化与我们求解的参数相关的不确定性:
Posterior Samples
我们可以看到,*均α ≈ 1.1 和*均β ≈ 5.3 将我们的参数*均放置在右上象限。然而,由于队列规模相对较小,我们的估计存在不确定性,这反映出α < 1 极有可能导致我们的流失分布落入右下象限。**
模型讨论和解释
在衡量终身价值之前,下一节将解释不断增长的保留率的价值。
不断增长的客户忠诚度
Which customer is more likely to survive into the next period?
我们以上面的两个客户为例。如果只知道客户与企业续签订阅的次数,那么哪个客户更有可能再次续签(即继续到下一期)?客户 B 已经证明了自己是一个忠诚的客户,一个明显喜欢你的产品的客户,因此有 9 次续订。您会预计客户 B 更有可能再次续订。我们可以通过使用我们估计的参数测量在 t=2 和 t=10 年的保留率来衡量这个概念。
Retention Rates at t=2 and t=10
注意在 t=10 奖励直觉时,记忆力如何提高。客户 B 续订到第 10 年的可能性为 92.7%,但客户 A 续订到第 3 年的可能性为 84.5%。****
使用*均保留率忽略了客户忠诚度的长期增长
流失率分布
我们也可以使用后验参数样本的 beta 分布来绘制流失概率。
Churn Rate using Beta Distribution
上面的每条线反映了给定α和β的流失分布。洋红色线条反映了α和β都大于 1 的样品(通常*均流失率更高)。黑线反映了假设我们的*均参数(α ≈ 1.1,β ≈ 5.3)的流失率分布。相反,当α <1 but β > 1 时出现绿线。
预测存活率— sGB
Comparison of Forecasted Survival Rates
能够在任何时间 t 计算留存率意味着我们可以使用之前的生存公式计算任何时间 t 的存活率。上图反映了我们使用 sGB 预测的存活曲线与恒定保留率的对比。
假设保持率不变会低估我们客户的寿命,这反过来也会低估 CLV。
计算 CLV
我们现在不仅可以计算未来客户的预期寿命,还可以计算现有客户的;当前活跃的客户。现有客户的 CLV 可以表示为他们的剩余终身价值(RLV) 或剩余终身价值。将它们的未来价值折算成现值,就得到所谓的贴现预期剩余寿命 (DERL)。
Discounted Expected Residual Lifetime
₂F₁function 引用了超几何函数,它可以从 scipy 库中导入 python:
**from scipy.special import hyp2f1**
与前面展示的不断增加的保留率非常相似,RLV 背后的直觉是,在其他所有因素不变的情况下,已续订 n 次的现有客户可能拥有更长的生命周期,从而拥有更高的剩余价值。因此,我们预计 DERL 将随着续约次数的增加而增加。
****假设每位客户每年的现金流为 1000 美元,前 20 年每次续约后的 DERL 如下图所示:
Assuming annual cashflow per customer is $1,000 and 10% discount rate
箱线图反映了我们估计的不确定性。例如,对于一个进行了 2 次续订的活跃客户,我们估计 DERL 在 5000 美元到 5700 美元之间,中位数在 5300 美元左右。如果我们解出一个α和β,我们会得到一条直线。也就是说,请注意剩余价值随时间的增长趋势——本质上,我们正在量化客户忠诚度。新获得的客户(续订次数= 0)的 DERL 中值约为 4,500 美元,而进行了 19 次续订的活跃客户的 DERL 中值约为 8000 美元(高出 78%)。
当前客户的总 DERL
回头参考我们的群组表,我们可以看到我们的最老的群组(群组 0)已经进行了 4 次续订,每个客户的*均 DERL 约为 5,900 美元。此外,我们的最新群组(群组 3)仅与我们进行了 1 次续约,因此 DERL 为 4900 美元。
Total Residual Value Across Customer Base
因为上面显示的 DERL 值是每个客户的,,所以整个群组的残值是通过将 DERL 乘以该群组的当前活动客户数量而获得的(绿色值)。所有群组的总和反映了您现有客户的总剩余价值。
请注意,我们对中值求和;在现实中,建议要么对*均值求和,要么继续将不确定性投影到最后,在这一点上,您可以计算任何您喜欢的统计数据(*均值、中值、百分位数)。
我们所有活跃客户的总(中值)剩余价值约为 1420 万美元
此外,假设您的业务团队预测下一年将有突破性进展,新增 1,000 名客户。新客户进行了 0 次续订,因此每位客户的 DERL 约为 4500 美元。因此,我们估计这些未来客户的总终身价值为【450 万美元】(1000 * 4500 美元)。
结论
这篇文章旨在展示评估 CLV 时的三个考虑因素:
- 考虑不确定性;如果你的客户数据集只有少数几个客户,那么在建模终身价值时你就不那么确定了。
- sGB 模型是评估契约式离散企业的优秀方法;更直观地模拟保留时间和生命周期
- 假设所有条件相同,剩余生命周期价值比新客户更信任忠诚客户(老客户)。
这些考虑因素使您能够更准确地计算当前客户的总价值,并最终提供一个更加稳健和动态的指标来:
- 评估 A/B 测试实验
- 告知营销收购工作
- 为你的创业公司筹集下一轮资金!
来源
[1] 这个 CLV 公式怎么了?
[2] 如何预测客户保持率
[3] 客户群分析的概率模型
订阅业务的终身价值计算
原文:https://towardsdatascience.com/calculating-life-time-value-for-subscription-businesses-d477a3194b32?source=collection_archive---------9-----------------------
Photo by Austin Distel on Unsplash
这是千真万确的,如果你不能衡量它,你就不能管理你的业务。基于订阅的业务的一个关键指标是终身价值(LTV)或客户终身价值(CLV)。简而言之,LTV 意味着在客户的一生中产生的总预期价值。让我们进一步分解这个概念:
- LTV 是一个期望值,这意味着它是*均的或统计推断的。
- LTV 衡量价值,即企业关心的价值指标,如收入、利润等。
- LTV 已经过了他的一生。例外的情况是,一家企业在一段时间后会终止与客户的关系😢,这是极不可能的,也是违背常识的。
在数学上,客户 LTV 可以表示为:
LTV calculation
其中v_i
代表价值,s_i
代表计费周期i
的留存率或存活率。计费周期可以是一周、一个月、一个季度,甚至一年,这取决于商业模式。周期总数N
代表利息的持续时间,也取决于商业模式。对于按年订阅的模式,N = 100
应该足够好了。从数学公式来看,我想你已经知道为什么 LTV 度规越来越受欢迎了。它同时衡量盈利能力(v_i
)和客户忠诚度或粘性(s_i
),并将它们很好地结合成一个指标。让我们用下面的玩具例子来说明计算。
LTV calculation
如表中所示,订阅产品在每个计费周期从客户身上获得 10 美元的价值。周期流失率为 30%,因此保留的客户百分比为 100%、70%、56%……因此,第 1、2、3 周期产生的有效客户价值为 10 美元、7 美元、5.6 美元……将所有产生的价值相加,总 LTV 约为 45 美元(40 个周期后该数字稳定下来)。
如您所见,计算非常直观。然而,对于一个真正的企业或产品来说,这可能一点也不简单。一种情况是v_i
可能会受到通货膨胀、商品成本波动、季节性等因素的影响。另一种情况是,观察到的账单周期总数可能不足以构建计算 LTV 所需的s_i
,这最有可能发生在年轻企业。在接下来的内容中,我将关注后一种情况,并展示如何使用更系统的方法来计算s_i
。
模拟存活率
我们通常不会直接获得存活率s_i
,而是从计费周期流失率c_i
入手。s_i
和c_i
的关系如下图所示。
Survival rate calculated from churn rate
显然,流失率在 0%(没有客户在该周期后流失)和 100%(每个客户在该周期后流失)之间,因此随着周期数的增加,存活率总是从 100%下降到 0%。有几种方法可以获得流失率c_i
。
1.经验计算
获取流失率最简单的方法就是根据历史观察值计算每个计费周期的流失率,也称为卡普兰-迈耶估计量 (KM 曲线),可以表示如下
其中d_i
是周期i
中的下降次数,n_i
是周期i
开始时的客户数。
这种方法直观且易于实施和计算,但是,它通常不适用于年轻的企业。具体来说,一个年轻的企业通常没有很多计费周期,没有大量的n_i
可用于计算流失率。下图显示了年轻企业和成熟企业之间的比较。请注意,对于年轻的企业,流失率比已建立的企业跨越的周期更少,并且在接*结束时变得更嘈杂,因为其总样本量n_i
在接*最后一个周期时变得越来越小,而对于已建立的企业来说,情况并非如此。你要知道,嘈杂的流失率更多的是一种短暂的影响。随着企业客户群的增长和稳定,将会有更多的客户数据可用,因此嘈杂的蓝色曲线应该越来越接**滑的橙色曲线。
Churn Rate Comparison
至于计算,可以用 excel、SQL、Python、R 等。在 R 中,已经存在一个名为suvival
的包来简化生存分析,包括 KM 生存曲线计算。以 IBM Watson telco 客户演示数据集为例,我们可以用如下所示的几行代码计算并绘制 KM 存活率和流失率曲线。
(Left) Survival curve in black with 95% confidence band in gray (Right) Churn rate
如果你有兴趣了解更多关于 KM 曲线的知识,你可以看看 Lauren Oldja 写的一篇关于它的详细文章。
2.统计推断
正如前面的方法所指出的,我们不能真的把卡普兰-迈耶方法用于年轻的企业。那么,还有别的办法吗?是的,统计数据来拯救我们了。为了构建一个合理的生存曲线来估计只有几个周期可用的 LTV,我们需要进行统计推断。
与非参数 Kaplan-Meier 方法(其中没有估计参数)不同,统计推断是参数化的。其思想是,我们假设客户流失事件遵循一定的概率分布。常用的分布模型有指数、对数正态、威布尔、伽玛等。给定统计分布模型,然后您可以使用最大似然法来找到符合历史流失数据的最佳参数。在拟合之后,可以使用该模型推断未来周期的流失概率。R 中的survival
包也为生存模型拟合提供了很好很简单的工具。继续前面的例子,我们可以使用下面的代码来生成拟合的生存曲线
Survival curve using Weibull Model
正如你所看到的,拟合的生存变动是*滑的,我们能够用它来估计未来的存活率,用于 LTV 计算。此外,我们可以从曲线中得出一些有趣的指标。例如,我们预计 50%的客户将在第 120 周期前离开,如上面的蓝色虚线所示。您还可以计算生存曲线下的面积,以获得客户的*均终身任期期望。
3。机器学习
机器学习无处不在,预测未来。我们还可以利用它来计算流失率。事实上,它是我最喜欢的选择,因为我们可以针对这个问题使用各种机器学习技术,如特征工程,交叉验证,正则化等。
客户流失建模本质上是一个二元分类问题。有许多机器学习模型可以解决这个问题,但是,我使用逻辑回归,因为我们需要推断未来的流失率,因此看不见的计费周期和模型,如随机森林和梯度提升机器无法执行这种推断。以下代码使用了 H2O 机器学习包,并拟合了流失和周期之间的单变量逻辑回归模型。
(Left) Survival rate by cycle (Right) churn rate by cycle
正如我们所看到的,虽然这个简单的模型可以拟合生存和流失曲线的整体趋势,但它并不能很好地拟合 cycle 1。为了减轻这种情况,一个技巧是您可以添加一个二进制特性special_cycle
,对于周期 1 为 1,其余为 0。修改后的代码和结果如下。
(Left) Survival rate by cycle (Right) churn rate by cycle
结论
在本帖中,我们讨论了订阅业务的 LTV 公式和计算方法,并重点讨论了计算存活率/流失率的 3 种不同方法。我希望你喜欢这篇文章,并让我知道你的想法!
计算 Yolo (v3)层的损耗
原文:https://towardsdatascience.com/calculating-loss-of-yolo-v3-layer-8878bfaaf1ff?source=collection_archive---------4-----------------------
Yolo v3 模型的实现
Yolov3 是最先进的对象检测模型,使其成为快速准确的实时对象检测模型。有没有想过 Yolov3 车型的症结在哪里?秘密在于 Yolo 模型的 Yolo 层。
Yolov3 架构
Yolov3 模型接收 416x416 的图像,用经过训练的 Darknet-53 主干对其进行处理,并在三个尺度上产生检测。在每个比例下,输出检测的形状为(批量大小 x 锚盒数量 x 网格大小 x 网格大小 x 85 维)。
Output detections of shape (batch_size x num_of_anchor_boxes x grid_size x grid_size x 85 dimensions)
Yolov3 的架构在https://towardsdatascience . com/Yolo-v3-object-detection-53 FB 7d 3 bfe 6 b的 Yolo v3 网络架构图中描绘得非常好(请阅读这个故事了解 Yolo v3 架构)。在该图描述的所有组件中,有 3 个检测层,它们也是 Yolo 层。三个 Yolo 层中的每一层负责计算三个不同尺度的损耗。然后将三个不同尺度的损耗相加,用于反向传播。每个 Yolo 层利用 85 个维度来计算损耗。前 4 个维度对应于边界框的中心线、中心线、宽度和高度。接下来的 1 维对应于边界框的客观性分数,最后的 80 维对应于边界框的独热编码类预测。计算以下 4 种损失:
- 包围盒的中心线、中心线、宽度和高度的 MSE
2.包围盒的客观分数的 BCE
3.包围盒的无客观性分数的 BCE
4.包围盒的多类预测的 BCE
详细实现代码由https://towards data science . com/yolo-v3-object-detection-53 FB 7d 3 bfe 6 b。解释和张量形状被附加以帮助解释下面的代码。
Yolo 层采用一个复杂的形状特征(批量大小 x 锚盒数量 x 网格大小 x 网格大小 x 85 个维度)来计算上述 4 个损失。首先,基于标记的目标,它首先创建形状的 Obj 掩码((batch _ size x num _ of _ anchor _ boxes x grid _ size x grid _ size x 85 维)以指示哪些边界框应该包含预测,并创建形状的 Noobj 掩码(batch _ size x num _ of _ anchor _ boxes x grid _ size x grid _ size x 85 维)以指示哪些边界框不应该包含预测。有了掩模,可以成功地将目标与相同形状的预测进行比较,以计算四个损失。具体实现见下文。
YoloLayer Class from models.py from https://towardsdatascience.com/yolo-v3-object-detection-53fb7d3bfe6b
从数据集中选取 batch_size 目标,如下所示:
A batch_size targets
基于标记的目标,下面的 build_targets 函数创建形状的 obj 掩码(batch _ size x num _ of _ anchor boxes x gridsize x gridsize)来指示哪些边界框应该包含预测,并创建形状的 noobj 掩码(batch _ size x num _ of _ anchor boxes x gridsize x gridsize)来指示哪些边界框不应该包含预测。
Build_targets function from utils.utils.py from https://towardsdatascience.com/yolo-v3-object-detection-53fb7d3bfe6b
逐步手动计算最大似然估计
原文:https://towardsdatascience.com/calculating-maximum-likelihood-estimation-by-hand-step-by-step-3a740c637c20?source=collection_archive---------4-----------------------
我写这个是因为我找不到很多教程来展示这个计算的详细数学。所以我决定把它彻底写出来,并展示所有的步骤,以防有一段时间没有做过微积分的人需要一点指导。
高斯分布很容易通过以*均值为中心的一组数据和围绕*均值的点的对称分布来识别。在分析数据时构建高斯分布,其中每个点都是独立实验的结果,这有助于可视化数据并应用于类似的实验。为了找到一组数据的最佳分布,计算最大似然估计(MLE)。
用于创建分布的两个参数是:
- *均值 (μ)(mu)— 该参数决定分布的中心,较大的值导致曲线进一步向左*移。
- 标准偏差(σ)(sigma) — 该参数决定曲线的宽度,较大的值产生较短和较宽的曲线,较小的值产生较细和较高的曲线。
简化高斯分布函数
似然估计函数:
高斯函数的 Subbing
拿走木头
用多点简化方程
对函数相对于 μ(*均值)求导
对函数相对于 σ 求导(标准偏差)
将等式设为零,以找到μ的最佳值
将等式设为零,以找到σ的最佳值
在 R 中计算新客户和老客户
原文:https://towardsdatascience.com/calculating-new-and-returning-customers-in-r-909518f62264?source=collection_archive---------18-----------------------
我最*遇到一个问题,我想计算新客户和老客户。所以,我很自然地谷歌了一下,惊讶地发现我在 R 中找不到任何关于它的解决方案,这通常是大多数 R 博客/教程的问题,它们不是非常面向商业的。
由于在网上找不到解决方案,我开始自己动手。我能够使用 DAX 和 Power Pivot 在 Excel 和 Power BI 中很快找到解决方案,但我想在 r 中完成它。实际上,我有点不好意思承认这个解决方案非常简单。我期望你对 R 中的 Tidyverse 包有一些基本的了解,主要是 dplyr 来理解本教程。
在继续之前,我们首先需要决定如何定义一个客户是“新客户”还是“回头客”
新客户
任何过去没有与我们合作过的客户都将被归类为“新客户”
回头客
任何过去与我们合作过的客户,如果在当前期间再次与我们合作,都被视为“回头客”
加载库
library(tidyverse)# For data manipulation
library(readxl) # Read in Excel File
library(lubridate)# Working with Dates
加载和查看数据
我们使用下面的代码读入销售数据,并查看一下数据类型。
**sales_data** <- read_xlsx(path="C:\\Users\\ACER\\Downloads\\sale_data.xlsx")glimpse(sales_data)
我们得到以下输出。销售日期显示为日期时间变量,而客户 ID 被识别为数字类型。
我们现在将使用 dplyr 中的 mutate 函数将“销售日期”和“客户 ID”列分别更改为日期和字符类型。
**sales_data** <- sales_data%>%
mutate(`Sale Date` = dmy(`Sale Date`),
`Customer ID`=as.character(`Customer ID`))
现在我们的数据已经准备好了,我们要做的第一件事就是计算每一行中每个客户的首次签约日期。这将决定他们在那个时间点是新客户还是回头客。
**sales_data** <- sales_data %>%
group_by(`Customer ID`)%>%
mutate(date_of_first_engagement=min(`Sale Date`))%>%
ungroup()
由于我们想计算每一行中每个客户的第一次接洽日期,我们将首先按“客户 ID”对数据进行分组,然后使用 mutate 函数计算他们在“销售日期”使用 min 函数与我们第一次接洽的时间。这基本上是在 r 中计算条件计算列的一种非常有用的方法。
一旦计算完成,我们将取消对它的分组,因为我们不想要任何基于“客户 ID”的进一步计算。下面是我们的数据集在计算完成后的样子
在第 10 行,客户“39099”于 2018 年 9 月 17 日与我们合作,但我们可以看到,他们与我们的首次合作日期是 2018 年 8 月 9 日,这意味着在 9 月 17 日,该客户是“回头客”,而在 8 月 9 日,他们是“新客户”。
使用这个逻辑,我们现在将创建一个新列——“客户状态”。我们将使用 case_when 函数,根据“销售日期”和“首次接洽日期”的差异,在每个时间点对每个客户进行分类
**sales_data** <- sales_data%>%
mutate(Customer_Status = case_when(`Date Interviewed`>date_of_first_engagement ~ "Returning",
`Date Interviewed` == date_of_first_engagement ~ "New",
TRUE ~ "Other"))
基本上,我们所做的是计算如果客户的“销售日期”大于客户的第一次合作日期,那么这意味着他们以前与我们合作过,因此是“回头客”,如果他们的“销售日期”等于他们的第一次合作日期,那么这意味着这是他们第一次与我们合作,因此在那个时间点上是“新客户”。以下是数据集的外观。
我们的数据终于准备好了!现在我们可以对它做一些有趣的分析。我想看看我们每个月有多少“新”和“回头客”。我们将使用 group by 和summary函数来得到这个结果
**New_and_Returning_Customers** <- sales_data%>%
group_by(floor_date(`Sale Date`,unit = 'month'))%>%
summarise
(New_Customers = n_distinct(`Customer ID`[Customer_Status=="New"]),Returning_Customers= n_distinct(`Customer ID`[Customer_Status=="Returning"]))
因为我想按月分组,所以我使用 lubridate 包中的 floor_date 函数将“销售日期”四舍五入到最*的月份,然后使用条件非重复计数来获得每月新老客户的唯一计数。
我们可以使用 ggplot2 包来制作一个简单的数据折线图
结论
现在我们已经了解了如何计算新客户和老客户,我们可以对他们进行各种分析。本教程的目的是让你了解如何以一种相对简单明了的方式进行计算。
在 Python 中计算字符串相似度
原文:https://towardsdatascience.com/calculating-string-similarity-in-python-276e18a7d33a?source=collection_archive---------0-----------------------
以任何方式、形状或形式比较字符串都不是一项简单的任务。除非它们完全相等,否则比较很容易。但大多数时候情况并非如此——最有可能的是,你想看看给定的字符串是否类似于学位,那完全是另一回事。
Photo by Tomasz Frankowski on Unsplash
让我们用一个例子来更深入地探讨这个问题。你有一个网页,它需要一些用户输入——假设出于某种原因,你决定使用文本字段而不是下拉菜单来显示位置信息。用户有可能会打错字,而您不希望错字存储在您的数据库中。你想要正确无误的版本。
但是你会如何着手纠正弦呢? 我的意思是你可以硬编码它,但是你真的要这么做吗?有太多的输入错误选项,硬编码通常不是一个好主意。
这就是本文的目的。我想让你们熟悉我最擅长的两种字符串匹配或相似性计算技术:
- 莱文斯坦距离
- 余弦相似性
第一个主要用于解决打字错误,我发现如果你想比较两个文档,它几乎没有用。这就是梯子的用处。恰恰相反,对错别字检测没用,但对一整句话,或者文档相似度计算很棒。
阅读完本文后,您将能够做到以下几点:
- 确定哪种相似性算法适合您的情况
- 用 Python 实现
好了,准备好潜水了吗? 走吧。
莱文斯坦距离
让我们从一个基本定义开始:
在信息论、语言学和计算机科学中,Levenshtein 距离是衡量两个序列之间差异的字符串度量。非正式地,两个单词之间的 Levenshtein 距离是将一个单词变成另一个单词所需的单个字符编辑(插入、删除或替换)的最小数量。[1]
用最简单的话来说,您想要计算需要对字符串 A 执行多少次转换才能使其等于字符串 B 。该算法也被称为 编辑距离 ,所以这可能是你更熟悉的术语。
要在 Python 中使用它,你需要安装它,比如说通过 pip :
pip install python-Levenshtein
仅此而已。现在让我们看看如何使用它。
因为' Levenshtein '很难正确输入,而且我之前说过我主要用它来检测输入错误,这将是一个很好的第一个例子。但是首先,进口:
现在你可以计算距离了:
第一个打对了,第二个是我直接打出来的,你知道,没有先谷歌一下。乍一看,它们看起来一模一样,所以作为最终用户,您可能甚至不会注意到拼写错误。但是如果存储在某个数据库中,用于以后的分析,那就大不一样了。
我以前也说过,我不会对更长的字符串或整个文档使用这种算法,原因如下:
如你所见,两个句子传达了几乎相同的信息,但是从一个句子到另一个句子需要 20 次转换。所以,如果你已经设置字符串在低于某个阈值时自动匹配,20 可能不是那个阈值,因为它对于像这两个这样的简单短句来说太大了。
那是它的余弦兄弟来救援的地方。
余弦相似性
和以前一样,让我们从一些基本定义开始:
余弦相似性是内积空间的两个非零向量之间的相似性的度量,它度量它们之间角度的余弦。[2]
By Giphy: https://giphy.com/gifs/CiYImHHBivpAs/html5
我知道,这不是最干净的定义,但我觉得足够好了。它需要一些数学知识,如果你没有,请参考下面这篇文章(线性代数中的向量):
[## Numpy 线性代数基础(第一部分)
学习数据科学的基本线性代数技能—第 1/2 部分
towardsdatascience.com](/linear-algebra-essentials-with-numpy-part-1-af4a867ac5ca)
好吧,让我们进一步提炼。
根据定义,您应该首先计算两个矢量之间的角。但是你不能把一个句子,表示成 n 维空间中的一个向量。
你需要从所有你想计算相似度的“句子”中构造一个向量空间。这个向量空间将有多的维度,就像所有句子中唯一的单词加在一起一样多。
好吧,我们先导入,我会即时解释一切:
您将需要 string 模块来删除字符串中的标点符号——句子和句子和句子。默认情况下,是不同的,您希望避免这种情况。count vectorizer会负责将字符串转换成数字向量,这也很简洁。最后,由于这篇文章是用英语写的,你需要删除那些最常见的没有意义的单词——它们被称为停用词——比如“我”、“我”、“我自己”等等。
如果你不删除停用词,你会得到一个更高维的空间,向量之间的角度会更大——意味着更少的相似性——即使向量传达的信息几乎相同。
现在我将宣布一些任意的,在某种程度上相似的句子的列表。这是一个列表,因为向量空间将由所有唯一的单词创建,这将确保每个向量具有相同的维数,因为您无法计算不同维空间中向量之间的角度:
还记得进口吗? 我们进口了不少,是时候好好利用一下了。我将声明一个函数,它将执行以下操作:
- 从给定字符串中删除标点符号
- 将字符串小写
- 删除停用词
现在你实际上不需要一个循环来为每个句子应用那些变换,你可以使用内置的 映射 函数:
太好了,准备工作差不多完成了。现在,您将利用 计数矢量器 的能力来执行一些魔术(不是真正的)。它将在维空间中创建 k 个向量,其中 k 是句子的数量, n 是所有句子组合起来的唯一词的数量。然后,如果一个句子包含某个单词,则该值为 1,否则为 0:
准备工作到此结束。这太多了(有点像),但是值得。如果您现在从获得的数字向量计算余弦相似性,您将获得以下矩阵:
对角线元素是 1,这是有意义的,句子 X 与句子 X 完全“相似”。然而,分割这个矩阵是不方便的,所以我决定定义一个函数来计算两个给定向量的相似性。请记住,cosine _ similarity()期望 2D 数组,输入向量默认为 1D 数组,所以这就是我们需要整形的原因:
为了确认一切正常:
太酷了。在现实世界的例子中,这可以用于向用户提供一些推荐,例如,基于他的评论与其他每个用户的评论的相似性。
在你走之前
计算数值向量之间的相似度并不难,诀窍是先把字符串转换成数值向量,在这个过程中丢弃一切不相关的东西。
作为一个练习,这将是一个好主意,找到一些未标记的电子邮件或其他一些文本的数据集,并尝试使用相似性度量将它们以某种方式分组。你看一下 TF-IDF 可能也是个好主意,因为我在本文中没有解释它。
无论如何,感谢你的阅读,我希望你能从中得到一些有用的东西。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
* [## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)*
参考
[1]https://en.wikipedia.org/wiki/Levenshtein_distance
https://en.wikipedia.org/wiki/Cosine_similarity
计算这个假期你在飞机上坐在前任旁边的几率
原文:https://towardsdatascience.com/calculating-the-odds-you-sit-next-to-your-ex-on-a-flight-this-holiday-season-c87c52c49fe5?source=collection_archive---------27-----------------------
剧透:这比你一生中被闪电击中一次的可能性还小!
Credit Suhyeon Choi at Unsplash
最*,我坐上了从波士顿到 Ft 的飞机。劳德代尔来我家度假。我迟到了,是最后一批被允许登机的人之一。我走到飞机后部,找到我的座位,问坐在过道上的人是否可以让我坐在中间的座位上。她从笔记本电脑上抬起头——是我的前任!当我们在飞机上叙旧的时候,我不停地想,我们不太可能各自订了票,但是我们最后却坐在了一起。这种可能性有多大?让我们来计算一下!
我们需要做三件事才能坐到一起:
1)我们决定在同一天起飞
我们在同一天买了同一趟航班
航空公司给我们安排了相邻的座位
我们可以把我们坐在一起的概率写成:
在这个分析中,我们将做一个简化的假设,即航空公司随机分配座位给乘客,即使实际上有人可以支付额外的费用来获得他们选择的座位。
假设我们两个人都打算在 2019 年 12 月 16 日到 12 月 20 日这一周回家旅行,我们随机地统一决定了我们的旅行日期。类似地,让我们假设一天有 5 个航班选项,我们随机地统一选择航班。我们的等式现在是:
我们需要计算一家航空公司分配给我们相邻座位的概率。飞机可以有许多不同的座位安排,但让我们假设所有的飞机都有 30 排,每排有两组 3 个座位。这实际上非常接*精神航空公司运营的空客 A320 的实际座位图。
计算这个概率似乎令人生畏,但我们现在可以通过假设飞机只有一排来简化事情。在这种情况下,我和我的前任有 15 (6 选 2)对可能的座位,但其中只有 4 对是相邻的座位(左侧和右侧的靠窗和中间、过道和中间)。所以,拿到相邻座位的概率是 4/15。
如果有两排,则有 66 (12 选 2)对可能的座位,但其中只有 8 对是相邻的(每排 4 对)。我们可以从这种模式推断出下面的公式,其中 n 是飞机上的行数:
Probability of getting adjacent seats at random. n is the number of rows on the plane.
代入这个公式,概率是 0.007449。我们也可以通过模拟来验证这个答案。
为了得到最终的答案,我们代入我们的第一个方程,得到 0.0000119 或者大约十万分之一。这大约是你一生中 30 次少一次被雷击的概率!
一路*安,假期愉快。我希望你用这些时间与朋友和家人相聚:)
用 Python 计算语义品牌得分
原文:https://towardsdatascience.com/calculating-the-semantic-brand-score-with-python-3f94fb8372a6?source=collection_archive---------16-----------------------
大数据时代的品牌智能
语义品牌得分 ( SBS )是一个新颖的指标,旨在评估一个或多个品牌在不同背景下的重要性,只要有可能分析文本数据,甚至大数据。
相对于一些传统措施的优势在于,SBS 不依赖于对小样本消费者进行的调查。这一衡量标准可以根据任何文本来源进行计算,例如报纸文章、电子邮件、推文、在线论坛、博客和社交媒体上的帖子。这个想法是通过对大文本数据的分析来捕捉洞察和诚实信号 。消费者或其他品牌利益相关者的自发表达可以从他们通常出现的地方收集——例如,如果研究博物馆品牌的重要性,可以从旅游论坛收集。这样做的好处是减少了因使用问卷而产生的偏见,因为受访者知道他们正在被观察。SBS 还可以适应不同的语言,并研究特定单词或一组单词的重要性,不一定是“品牌”。
“品牌”可以是一个政治家的名字,或者是代表一个概念的一组词(例如,“创新”的概念或者一个公司的核心价值)。该指标用于评估一个新品牌取代一个旧品牌时发生的转变动态[1]。语义品牌得分也有助于将品牌的重要性与其竞争对手的重要性联系起来,或者分析单个品牌的重要性时间趋势。在一些应用中,分数被证明对于预测目的是有用的;例如,已经发现政治候选人在网络媒体上的品牌重要性与选举结果之间存在联系[4],或者博物馆品牌的重要性与游客数量的趋势之间存在联系[6]。使用 SBS 的出版物的更新列表是 ,可在此处 获得。
品牌重要性的三个维度
SBS 衡量品牌重要性,这是品牌资产的基础[1]。事实上,这一指标部分受到了众所周知的品牌资产概念化以及品牌形象和品牌意识结构的启发(参见凯勒的工作)【2】。
品牌重要性从三个维度来衡量:流行度、多样性和连通性。流行度衡量品牌名称的使用频率,即品牌被直接提及的次数。多样性衡量与品牌相关的词语的多样性。连接性代表品牌在其他单词或词组(有时被视为话语主题)之间架起连接桥梁的能力。
关于 SBS 的更多信息可以在这个网站【5】,在维基百科,或者阅读这篇论文【1】中找到。在本文中,我不会在这个指标上花太多时间,因为我的重点是描述使用 Python 3 计算它的主要步骤。
数据收集和文本预处理
语义品牌得分的计算需要结合文本挖掘和社会网络分析的方法和工具。图 1 说明了主要的初步步骤,包括数据收集、文本预处理和构建单词共现网络。
对于本入门教程,我们可以假设相关的文本数据已经收集并组织在一个文本文件中,其中每一行都是一个不同的文档。我将把两个想象的品牌(‘BrandA’和【T20’‘BrandB’)插入随机的英文文本中。
使用 Python 3 计算语义品牌得分
此演示的更新 GitHub 库可在 此处 获得。在那里,您将找到一个 Python 笔记本,以及示例文件。
**# Read text documents from an example CSV file**
import csv
readfile = csv.reader(open("AliceWonderland.csv", 'rt', encoding="utf8"), delimiter = "|", quoting=csv.QUOTE_NONE)texts = [line[0] for line in readfile]**#I imported 4 Chapters of Alice in Wonderland**
print(len(texts))
print(texts[0][:200])
我将文本文件作为文本文档列表( texts )导入 Python,现在对其进行处理以删除标点符号、停用词和特殊字符。单词被小写并拆分成记号,从而获得一个新的 texts 变量,这是一个列表的列表。更复杂的文本操作预处理总是可能的(比如移除 html 标签或' # '),为此我推荐阅读 Python 中自然语言处理的众多教程之一。停用词列表取自 NLTK 包。最后,单词词缀通过滚雪球式词干去除。
**##Import re, string and nltk, and download stop-words**
import re
import nltk
import string
from nltk.stem.snowball import SnowballStemmer**#Define stopwords**
#nltk.download("stopwords")
stopw = nltk.corpus.stopwords.words('english')**#Define brands (lowercase)**
brands = ['alice', 'rabbit']**# texts is a list of strings, one for each document analyzed.****#Convert to lowercase**
texts = [t.lower() for t in texts]
**#Remove words that start with HTTP**
texts = [re.sub(r"http\S+", " ", t) for t in texts]
**#Remove words that start with WWW**
texts = [re.sub(r"www\S+", " ", t) for t in texts]
**#Remove punctuation**
regex = re.compile('[%s]' % re.escape(string.punctuation))
texts = [regex.sub(' ', t) for t in texts]
**#Remove words made of single letters**
texts = [re.sub(r'\b\w{1}\b', ' ', t) for t in texts]
**#Remove stopwords**
pattern = re.compile(r'\b(' + r'|'.join(stopw) + r')\b\s*')
texts = [pattern.sub(' ', t) for t in texts]
**#Remove additional whitespaces**
texts = [re.sub(' +',' ',t) for t in texts]**#Tokenize text documents (becomes a list of lists)**
texts = [t.split() for t in texts]**# Snowball Stemming**
stemmer = SnowballStemmer("english")
texts = [[stemmer.stem(w) if w not in brands else w for w in t] for t in texts]
texts[0][:6]
在文本预处理过程中,我们应该注意不要丢失有用的信息。表情符号:-),由标点符号组成,如果我们计算情感,它会非常重要。
我们现在可以继续计算流行度,它计算每个品牌名称的出现频率——随后标准化,考虑文本中所有单词的得分。我在这里选择的标准化是减去均值,除以标准差。其他方法也是可能的[1]。这一步对于比较考虑不同时间框架或文件集(例如,4 月和 5 月 Twitter 上的品牌重要性)的衡量标准非常重要。在合计流行度、多样性和连接性以获得语义品牌得分之前,绝对得分的标准化是必要的。
**#PREVALENCE**
**#Import Counter and Numpy**
from collections import Counter
import numpy as np**#Create a dictionary with frequency counts for each word**
countPR = Counter()
for t in texts:
countPR.update(Counter(t))**#Calculate average score and standard deviation**
avgPR = np.mean(list(countPR.values()))
stdPR = np.std(list(countPR.values()))**#Calculate standardized Prevalence for each brand**
PREVALENCE = {}
for brand in brands:
PR_brand = (countPR[brand] - avgPR) / stdPR
PREVALENCE[brand] = PR_brand
print("Prevalence", brand, PR_brand)
下一步也是最重要的一步是将文本(标记列表的列表)转换成一个社交网络,其中节点是单词和链接根据每对单词之间的共现次数进行加权。在这个步骤中,我们必须定义一个共现范围,即共现单词之间的最大距离(这里设置为 7)。此外,我们可能想要移除表示可忽略的同现的链接,例如那些权重= 1 的链接。如果这些不是品牌,有时去除隔离物也是有用的。
**#Import Networkx**
import networkx as nx**#Choose a co-occurrence range**
co_range = 7**#Create an undirected Network Graph**
G = nx.Graph()**#Each word is a network node**
nodes = set([item for sublist in texts for item in sublist])
G.add_nodes_from(nodes)**#Add links based on co-occurrences**
for doc in texts:
w_list = []
length= len(doc)
for k, w in enumerate(doc):
**#Define range, based on document length**
if (k+co_range) >= length:
superior = length
else:
superior = k+co_range+1
**#Create the list of co-occurring words**
if k < length-1:
for i in range(k+1,superior):
linked_word = doc[i].split()
w_list = w_list + linked_word
**#If the list is not empty, create the network links**
if w_list:
for p in w_list:
if G.has_edge(w,p):
G[w][p]['weight'] += 1
else:
G.add_edge(w, p, weight=1)
w_list = []**#Remove negligible co-occurrences based on a filter**
link_filter = 2
**#Create a new Graph which has only links above
#the minimum co-occurrence threshold**
G_filtered = nx.Graph()
G_filtered.add_nodes_from(G)
for u,v,data in G.edges(data=True):
if data['weight'] >= link_filter:
G_filtered.add_edge(u, v, weight=data['weight'])**#Optional removal of isolates**
isolates = set(nx.isolates(G_filtered))
isolates -= set(brands)
G_filtered.remove_nodes_from(isolates)**#Check the resulting graph (for small test graphs)**
#G_filtered.nodes()
#G_filtered.edges(data = True)
print("Filtered Network\nNo. of Nodes:", G_filtered.number_of_nodes(), "No. of Edges:", G_filtered.number_of_edges())
确定了共现网络之后,我们现在可以计算多样性和连通性,它们是品牌节点的独特性中心性(之前我们使用度)和加权介数中心性。我们对这些值进行标准化,就像我们对患病率进行标准化一样。关于显著性中心性的更多信息在**【7】和 这篇文章 中给出。你还需要安装 Pythondistinct ns包 。**
**#INSTALL AND IMPORT THE DISTINCTIVENESS PACKAGE**
#pip install -U distinctiveness
from distinctiveness.dc import distinctiveness**#DIVERSITY**
**#Calculate Distinctiveness Centrality**
DC = distinctiveness(G_filtered, normalize = False, alpha = 1)
DIVERSITY_sequence=DC["D2"]**#Calculate average score and standard deviation**
avgDI = np.mean(list(DIVERSITY_sequence.values()))
stdDI = np.std(list(DIVERSITY_sequence.values()))**#Calculate standardized Diversity for each brand**
DIVERSITY = {}
for brand in brands:
DI_brand = (DIVERSITY_sequence[brand] - avgDI) / stdDI
DIVERSITY[brand] = DI_brand
print("Diversity", brand, DI_brand)
如果我们将连通性计算为加权中间中心性,我们首先必须定义逆权重,因为权重被 Networkx 视为距离(这与我们的情况相反)。
**#Define inverse weights**
for u,v,data in G_filtered.edges(data=True):
if 'weight' in data and data['weight'] != 0:
data['inverse'] = 1/data['weight']
else:
data['inverse'] = 1**#CONNECTIVITY**
CONNECTIVITY_sequence=nx.betweenness_centrality(G_filtered, normalized=False, weight ='inverse')
**#Calculate average score and standard deviation**
avgCO = np.mean(list(CONNECTIVITY_sequence.values()))
stdCO = np.std(list(CONNECTIVITY_sequence.values()))
**#Calculate standardized Prevalence for each brand**
CONNECTIVITY = {}
for brand in brands:
CO_brand = (CONNECTIVITY_sequence[brand] - avgCO) / stdCO
CONNECTIVITY[brand] = CO_brand
print("Connectivity", brand, CO_brand)
每个品牌的语义品牌得分最终通过对流行度、多样性和连接性的标准化值求和得到。不同的方法也是可能的,例如取非标准化系数的几何*均值。
**#Obtain the Semantic Brand Score of each brand**
SBS = {}
for brand in brands:
SBS[brand] = PREVALENCE[brand] + DIVERSITY[brand] + CONNECTIVITY[brand]
print("SBS", brand, SBS[brand])**#Generate a final pandas data frame with all results**
import pandas as pdPREVALENCE = pd.DataFrame.from_dict(PREVALENCE, orient="index", columns = ["PREVALENCE"])
DIVERSITY = pd.DataFrame.from_dict(DIVERSITY, orient="index", columns = ["DIVERSITY"])
CONNECTIVITY = pd.DataFrame.from_dict(CONNECTIVITY, orient="index", columns = ["CONNECTIVITY"])
SBS = pd.DataFrame.from_dict(SBS, orient="index", columns = ["SBS"])SBS = pd.concat([PREVALENCE, DIVERSITY, CONNECTIVITY, SBS], axis=1, sort=False)
SBS
分析演示
这个链接指向一个简短的演示,一旦计算出 SBS,就可以进行分析[8]。为了推断独特的和共享的品牌特征,词共现网络可以另外用于研究文本品牌关联。品牌情感的计算也可以补充分析。
结论
本文简要介绍了语义品牌得分,并提供了使用 Python 3 简化计算的简短教程。在学习基础知识的同时,我们应该记住,有许多选择可以做出,并且会影响结果。例如,可以选择不同的加权方案或标准化方法,将 3 个维度合并为一个分数。应特别注意选择合适的词共现范围。此外,可以使用不同的技术来修剪那些假定代表可忽略的同现的链接。
最后,如果计算是在大数据上进行的,最终的代码会复杂得多。像介数中心性这样的度量在大型图上有很高的计算复杂度。 Graph-Tool 是一个对我帮助很大的库,因为它的性能明显高于 Networkx。在某些情况下,处理初始数据集可以降低复杂性。例如,对于在线新闻,人们可以选择只分析标题和第一段,而不是全部内容。
作为一名自学的 Python 程序员,我将感谢您对这个指标及其有效计算的任何评论或建议。随时 联系我 。
您也可以查看 GitHub 资源库中的笔记本来了解这个演示( 此处 )。
参考
[1] Fronzetti Colladon,A. (2018 年)。语义品牌得分。商业研究杂志, 88 ,150–160。https://doi.org/10.1016/j.jbusres.2018.03.026
[2]凯勒,K. L. (1993 年)。概念化,测量和管理基于顾客的品牌资产。市场营销杂志, 57 (1),1–22。
[3] 维基百科上的语义品牌评分页面。
**[4] Fronzetti Colladon,A. (2020 年)。通过研究在线新闻中的品牌重要性预测选举结果。国际预测杂志, 36 (2),414–427。【https://doi.org/10.1016/j.ijforecast.2019.05.013 **
[5]Semanticbrandscore.com,公制网站,有更新的链接和信息
[6] Fronzetti Colladon,a .,Grippa,f .,& Innarella,R. (2020 年)。研究线上品牌重要性与博物馆访客的关联性:语意品牌评分的应用。旅游管理透视, 33 ,100588。https://doi.org/10.1016/j.tmp.2019.100588
[7]弗伦泽蒂·科拉顿和纳尔迪,M. (2020 年)。社会网络中的独特性中心性。 PLoS ONE , 15 (5),e0233276。https://doi.org/10.1371/journal.pone.0233276
[8]弗伦泽蒂·科拉顿和格里帕(2020 年)。品牌情报分析。在 A. Przegalinska,F. Grippa 和 P. A. Gloor(编辑),协作的数字化转型(第 125–141 页)。瑞士斯普林格自然基金会。https://doi.org/10.1007/978-3-030-48993-9_10
优化机器学习模型性能的预测和校准技术
原文:https://towardsdatascience.com/calibration-techniques-of-machine-learning-models-d4f1a9c7a9cf?source=collection_archive---------10-----------------------
机器学习性能优化
Python 代码示例
Image by author
C 校准是改善预测模型误差分布的后处理技术。
机器学习(ML)模型的评估是部署之前的关键步骤。因此,有必要对一个 ML 模型进行行为分析。在许多实际应用中,除了模型的*均误差之外,了解该误差是如何分布的以及概率估计的好坏也很重要。根据我的经验,许多当前的 ML 技术在总体结果上是好的,但是具有差的误差分布评估。我将讨论常用的校准技术和使用分类的校准方法。
从科学的角度来看,ML 方法的主要目标是从给定的数据集建立一个假设(模型)。在学习过程之后,必须尽可能精确地评估假设的质量。
对于基于分类的模型,常见的度量是精度(误差的倒数)、f 度量或宏观*均。在概率分类中,除了正确分类实例的百分比之外,还使用了其他度量,如对数损失、均方误差(MSE)(或 Brier 氏评分)或 ROC 曲线下面积(AUROC)。如果输出不是二进制的,而是 0 到 1 之间的浮点数,那么分数可以用于排名。但是 0 和 1 之间的浮点数导致了概率,我们怎么知道我们是否可以相信它们是概率呢?
为什么我们需要校准的分类器:
我们需要一个好的分类器来区分真阳性和真阴性。我们这里要处理电信客户数据;因此,在" C hurn" 分析中,我们期望分类器触发" Churn "和" NoChurn "之间的标志,这允许我们通过调整阈值来校准该模型的灵敏度。这意味着,如果分类器可以检测到 90%的“流失”可能性,企业应该将其视为真正的标签。此外,大多数与分类相关的数据非常不*衡,其中【流失】的数量远远小于无流失。因此,我们可能想要重新采样数据以*衡它们,这样我们可能会使我们的模型过于激进,从而导致一些偏差。
二元分类器:
在处理两类分类问题时,我们总是可以把一类标为正类,而把另一类标为负类。测试集由 P 个正例和 N 个负例组成。一个分类器给他们每个人分配一个类,但是有些分配是错误的。为了评估分类结果,我们计算真阳性(TP)、真阴性(TN)、假阳性(FP)(实际上是阴性,但被分类为阳性)和假阴性(FN)(实际上是阳性,但被分类为阴性)例子的数量。它保持住了
- TP + FN = P 和
- TN + FP = N
分类器将 TP + FP 实例分配给正类,将 TN + FN 实例分配给负类。让我们定义几个众所周知和广泛使用的衡量标准:
- FPrate = FP /N
- TPrate = TP /P = Recall
- Yrate = (TP + FP) /(P + N)
- 精度= TP/ (TP + FP)
- 准确率= (TP + TN)/ (P + N)。
精度和准确度通常用来衡量二元分类器的分类质量。也可以定义用于特殊目的的其他几种度量。我们将在下面的章节中对它们进行描述
概率分类器:
概率分类器是一个函数 f : X → [0,1],它将每个例子 X 映射到一个实数 f(x)。通常,选择阈值 t,其中 f(x) ≥ t 的例子被认为是正的,其他的被认为是负的。这意味着每对概率分类器和阈值 t 定义了一个二元分类器。因此,上一节中定义的度量也可用于概率分类器,但它们始终是阈值 t 的函数。注意,TP(t)和 FP(t)始终是单调递减函数。对于有限的示例集,它们是逐步的,而不是连续的。通过改变 t,我们得到一族二元分类器。
让我们用现有的电信数据做实验。
# Loading the CSV with pandas
data = pd.read_csv(‘Telco_Customer_Churn.csv’)data.dtypes # types of data in data set
#Removing customer IDs from the data set the columns not used in the predictive model.
df = data.drop(“customerID”, axis=1)
df.info()
我们将转换分类变量(‘是’,‘否’,等等)。)转换成数值。此外,需要将“总费用”转换为数字数据类型。此外,“总费用有 11 个缺失值。因此它将替换数据集中的 11 行。这里的预测变量是“Churn”。因此,也有必要将预测变量转换为二进制数值变量。
df.dropna(inplace = True)df[‘Churn’].replace(to_replace=’Yes’, value=1, inplace=True)
df[‘Churn’].replace(to_replace=’No’, value=0, inplace=True)# converting all the categorical variables into dummy variables
df_dummies = pd.get_dummies(df)
df_dummies.info()
分类算法:
我们将考虑物流回归和随机森林分类器来预测客户流失。重要的是在回归中调整变量,使所有变量都在 0 到 1 的范围内。
df_dummies = df_dummies.drop(“TotalCharges”, axis=1) # removing Total Charges to avoid multi-colinearity.# Using the data frame where we had created dummy variables
y = df_dummies[‘Churn’].values
X = df_dummies.drop(columns = [‘Churn’])# Scaling all the variables to a range of 0 to 1
features = X.columns.values
scaler = MinMaxScaler(feature_range = (0,1))
scaler.fit(X)
X = pd.DataFrame(scaler.transform(X))
X.columns = features
方法:
我们的第一步是使用 train-test-split 将我们的数据分成训练集和测试集,这将允许我们稍后交叉验证我们的结果。我们还对训练-测试-分割进行了分层,以确保在我们的训练集和测试集中发现相同比例的目标变量。
拆分数据:
x 是自变量的数据,y 是因变量的数据。测试大小变量决定了数据的分割比例。在 90 的培训/10 的测试比例中,这样做是很常见的。此外,需要对培训-测试-拆分进行分层,以获得*衡的拆分
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=101)
print(‘length of X_train and x_test: ‘, len(X_train), len(X_test))
print(‘length of y_train and y_test: ‘, len(y_train), len(y_test))
逻辑回归:
使用 ML 算法和因变量,这里的流失 1 或流失 0 是分类的。经过训练的模型可用于预测客户是否对测试数据集产生了兴趣。结果保存在“prediction_test”中,然后测量并打印准确度分数。
lr_model = LogisticRegression(solver=’lbfgs’).fit(X_train, y_train)
lr_prediction = lr_model.predict_proba(X_test)
prediction_test = lr_model.predict(X_test)
lr_pred = lr_model.predict(X_test)print(classification_report(y_test, prediction_test))
- 在第一类(NoChurn)的 557 个点中,该模型成功地正确识别了其中的 502 个点
- 在第 1 类的 147 个点中,模型正确预测了其中的 77 个点
- 在总共 704 个中,模型正确预测了其中 579 个。
准确率 82%(精确到 82.24%)。然而,考虑到数据是倾斜的,并且目标类别不*衡,这可能不是正确的衡量标准。所以,我们研究精确度,回忆,F 值。
混淆矩阵清楚地显示了模型性能,分为真阳性、真阴性、假阳性和假阴性。
- 精度是分类器不将实际上是负的实例标记为正的能力。对于每个类别,它被定义为真阳性与真阳性和假阳性之和的比率。
- 召回是分类器找到所有肯定实例的能力。对于每个类别,它被定义为真阳性与真阳性和假阴性之和的比率。
- F1 分数是精确度和召回率的加权调和*均值,最好的分数是 1.0,最差的是 0.0。
等级校准(CC):
CC 是真实类别分布与估计类别分布的*似程度。以这种方式校准模型的标准方法是通过改变确定模型何时预测“客户流失或“NoChurn”的阈值,使该阈值对“客户流失”类更严格,对“NoChurn”类更温和,以*衡比例。
y_scores=lr_prediction
prec, rec, tre = precision_recall_curve(y_test, y_scores[:,1], )def plot_prec_recall_vs_tresh(precisions, recalls, thresholds):
fig, ax = plt.subplots(figsize=(10,6))
plt.plot(thresholds, precisions[:-1], “r — “, label=”Precisions”)
plt.plot(thresholds, recalls[:-1], “#424242”, label=”Recalls”)
plt.ylabel(“Level of Precision and Recall”, fontsize=12)
plt.title(“Precision and Recall Scores as a function of the decision threshold”, fontsize=12)
plt.xlabel(‘Thresholds’, fontsize=12)
plt.legend(loc=”best”, fontsize=12)
plt.ylim([0,1])
plt.axvline(x=0.47, linewidth=3, color=”#0B3861")
plot_prec_recall_vs_tresh(prec, rec, tre)
plt.show()
正面类(【流失】)预测的准确率(58.33%)和召回率(52.38%)相对较低。交叉点上方的区域是良好性能水*的区域。下面的另一个区域是表现不佳的区域。原则上,这种类型的校准可能会产生更多的误差。事实上,通常情况下,我们希望获得一个有用的模型来解决非常不*衡的类分布问题,即少数类的例子非常少。
AUROC 曲线:
衡量二元分类器性能的一种更直观的方法是接收器工作特性(AUROC)曲线下的面积。它说明了模型在多大程度上能够区分流失和非流失。
lr_prediction = lr_model.predict_proba(X_test)
skplt.metrics.plot_roc(y_test, lr_prediction)
众所周知,AUROC 曲线很少受到类别分布变化的影响(放大对 FP 的影响很小,而我们可以看到对 TP 的一些影响)。
宏*均独立计算每个类的指标,然后取*均值(因此*等对待所有类),而微*均聚合所有类的贡献来计算*均指标。如果我们想知道系统在数据集上的整体表现,我们将考虑宏观*均。我们不应该用这个*均数做出任何具体的决定。另一方面,当我们的数据集大小不同时,微观*均是一个有用的度量。
因此,我们在这里看到,ROC 曲线未能明确显示*衡和不*衡情况之间的差异。此外,AUROC 分数不足以评估早期检索性能,尤其是当曲线相互交叉时。
我们将检查随机森林分类器;不过,我们就不再赘述了。类似的一套过程,如逻辑回归,可以做比较。
随机森林分类器:
同样,训练一个随机森林模型并在验证集上进行预测。
rf_model = RandomForestClassifier(random_state=101, n_estimators=100).fit(X_train, y_train)
rf_prediction = rf_model.predict_proba(X_test)
rf_model.score(X_test, y_test)
0.7798295454545454
概率校准(PC):
PC 伴随着概率估计的每个预测。如果我们预测我们有 99%的把握,如果我们只有 50%的时间是正确的,这是没有校准的,因为我们的估计过于乐观。类似地,如果我们预测我们只有 60%的把握,而我们 80%的时间是正确的,这是没有校准的,因为我们的估计太悲观了。在这两种情况下,正确猜测的数量或比例的期望值(在这种情况下是概率或置信度评估)与实际值不匹配。然后,校准被定义为预测概率与实际概率的接*程度。准确度和校准虽然相互依赖,但却是截然不同的两码事。
这里,我们有类别概率和标签来计算校准图的箱。
lr_y, lr_x = calibration_curve(y_test, lr_prediction[:,1], n_bins=20)
rf_y, rf_x = calibration_curve(y_test, rf_prediction[:,1], n_bins=20)fig, ax = plt.subplots()
# only these two lines are calibration curves
plt.plot(lr_x,lr_y, marker=’o’, linewidth=1, label=’lr’)
plt.plot(rf_x, rf_y, marker=’o’, linewidth=1, label=’rf’)# reference line, legends, and axis labels
line = mlines.Line2D([0, 1], [0, 1], color=’black’)
transform = ax.transAxes
line.set_transform(transform)
ax.add_line(line)
fig.suptitle(‘Calibration plot for Telecom data’)
ax.set_xlabel(‘Predicted probability’)
ax.set_ylabel(‘True probability in each bin’)
plt.legend(); plt.show()
def bin_total(y_true, y_prob, n_bins):
bins = np.linspace(0., 1\. + 1e-8, n_bins + 1)# In sklearn.calibration.calibration_curve the last value in the array is always 0.
binids = np.digitize(y_prob, bins) — 1return np.bincount(binids, minlength=len(bins))
bin_total(y_test, lr_prediction[:,1], n_bins=20)
数组([191,88,47,58,46,32,30,32,24,24,25,22,22,19,24,17,2,1,0,0,0])
bin_total(y_test, rf_prediction[:,1], n_bins=20)
array([213,70,59,47,39,42,27,27,22,18,26,21,22,18,7,12,10,6,7,11,0])
缺失的条柱具有 75%、85%和 95%的端点值。我们希望我们的预测能够避开那些空箱子,变得有鉴别力。在分类问题中,辨别和校准是并行不悖的。如果构建模型的目标是自动做出决策,而不是提供统计估计,有时它会出现在校准之前。在这里,查看 bin 中的点数,随机森林(橙色线)似乎比逻辑回归(蓝色线)更好。
一篇关于模型校准的有趣文章可以在 这里 找到补充阅读。
总结:
校准技术通常基于导出将值或概率转换为更好的估计值的变换。在分类的情况下,大多数转换技术通常包括宁滨或排序。我将为模型拟合评估推荐一个拟合优度测试(Hosmer-Lemeshow)。如果你有兴趣,你可以阅读 这篇 的文章来了解更多。
我这里可以到达。
呼唤数据科学家—停止使用准确性、精确度或召回等衡量标准!
原文:https://towardsdatascience.com/call-to-data-scientists-stop-using-measures-like-accuracy-precision-or-recall-1441f405e500?source=collection_archive---------16-----------------------
现实世界中的数据科学
用决策者能理解的语言交流
These are important metrics, but know your audience and ensure your communicating in their language!
好吧这个标题是故意挑衅和夸张滴。正如我们的一位数据科学家所说“我被这个标题吓坏了,但最终完全同意你的观点。
我坚信机器学习和数据科学领域提供的机会,但我们必须诚实面对自己。越来越多的人持怀疑态度,期望过高,有些人甚至警告说数据科学领域正在出现的信誉危机。
此外,许多决策者没有经过适当的培训来帮助解释、理解和正确应用我们模型的输出。
与 IMPACT 沟通
为此,我们需要更好地向关键利益相关者和决策者展示我们的影响力。最后,重要的是在业务问题的背景下,用非数据科学家能够理解的语言传达影响。
“在业务问题的背景下重点构建您的模型结果”
例如,我不认为准确度、精确度和召回率这样的指标对大多数商业用户来说是特别有用的。在某些具有不*衡数据集的项目中,我们有个位数精度的数字,这导致了重大的业务影响,特别是在与模型正在取代的流程相关联的情况下。
这是关键点——我们需要确保将结果与当前的工作方式进行比较。
关键业务利益相关者通常不愿意实施甚至试验一个新模型,除非他们能够清楚地理解它如何对他们的关键业务度量产生重大影响。
如何最好地框定你的结果
如果可能的话,确保我们在最终用户能够理解的业务环境中制定结果符合我们的最佳利益。让我们想象一下,你正在与营销副总裁会面,向他展示你的诊断罕见疾病患者模型的结果。
当我们将模型结果转化为有助于支持关键利益相关方做出明智决策的信息时,请看下面的进展:
我承认这是一个简单的例子,而且还有其他需要考虑的因素,但是请把这个例子看作是说明性的。
在业务环境中,它应该是量化相对于当前流程的改进。
这就引出了两个重要的概念——''和一个 挑战者模型 的想法。在以分析为中心的项目的构思阶段,我们采用“切合目的”的设计原则。在直接跳到高级 ML 模型之前,确保您首先探索更简单的方法。在可能的情况下,首先考虑部署一种更简单的方法(即 challenger model ),看看是否能够实现预期的业务成果。
你的利益相关者需要什么?
Photo by Stephen Dawson on Unsplash
要记住的关键点是,您的决策者可能有不同的需求,这驱动了对重要指标的不同观点。有些人可能专注于增加销售额,有些人专注于降低成本,有些人可能专注于减少错误,而有些人只是希望你让他们的工作更容易。
“避免不必要的模型腐烂——根据利益相关者的需求定义成功”
理想的情况是,在任何项目开始之前,与您的关键利益相关者合作,讨论这些重要的指标。用利益相关者的语言定义成功是推动有意义和持续的业务采用的主要因素,而不是让你的模型在架子上腐烂。
特别感谢我们两位才华横溢的数据科学家 艾米丽·科岗 和 埃里克·舍兰 对本文的贡献。
骰子、民意测验和狄利克雷多项式
原文:https://towardsdatascience.com/calogica-com-dice-polls-dirichlet-multinomials-eca987e6ec3f?source=collection_archive---------11-----------------------
概率规划在贝叶斯统计中的一些应用
Photo by Jonathan Petersson on Unsplash
作为学习贝叶斯统计的长期项目的一部分,我目前正在阅读安德鲁·吉尔曼、约翰·卡林、哈尔·斯特恩、大卫·邓森、阿基·维赫塔里和唐纳德·鲁宾撰写的贝叶斯数据分析,第三版,通常被称为 BDA3 。虽然在过去一年左右的项目中,我一直在使用贝叶斯统计和概率编程语言,如 PyMC3 ,但这本书迫使我超越纯粹的从业者建模方法,同时仍然提供非常实用的价值。
以下是我觉得有趣的本书前几章的一些摘录。他们的目的是希望激励其他人学习贝叶斯统计,而不是试图对数学过于正式。如果有些东西在房间里受过训练的数学家看来不是 100%,请让我知道,或者只是稍微眯着眼睛看一下。;)
我们将涵盖:
- 一些常见的共轭分布
- 使用掷骰子的狄利克雷多项式分布示例
- 涉及轮询来自 BDA3 的数据的两个示例
共轭分布
在本书的第 2 章中,作者介绍了先验概率分布的几种选择,以及第 2.4 节中的共轭分布的概念。
来自维基百科
在贝叶斯概率理论中,如果后验分布 p(θ | x)与先验概率分布 p(θ)在同一个概率分布族中,则先验和后验称为共轭分布,先验称为似然函数的共轭先验。
约翰·库克在他的网站上有一张有用的图表,展示了一些常见的共轭分布族:
Conjugate Priors
共轭分布在概率论中是一个非常重要的概念,这在很大程度上是由于一些很好的数学性质使得计算后验概率更容易处理。即使有越来越好的计算工具,如 MCMC,基于共轭分布的模型也是有优势的。
贝塔二项式
共轭分布的一个更广为人知的例子是Beta-二项式分布,它通常用于模拟一系列的硬币投掷(这是关于概率的帖子中一直存在的话题)。
二项式分布代表一系列伯努利试验的成功概率,而贝塔分布则代表每次试验成功概率的先验概率分布。
因此,硬币落在头上的概率 p 被建模为β分布(参数为α和β),而头和尾的概率被假设为遵循二项式分布,参数为 n (代表翻转次数)和β分布 p ,因此
p∞β(α,β)
y∞二项式(n,p)
伽马泊松
另一种常用的共轭分布是伽马-泊松分布,这样命名是因为参数化泊松分布的速率参数λ被建模为伽马分布:
λ∞伽马(k,θ)
y∞泊松(λ)
虽然离散的泊松分布通常用于计数数据的应用,例如商店顾客、电子商务订单、网站访问,但是伽马分布用作建模这些事件发生率(λ)的有用分布,因为伽马分布仅建模正的连续值,但是在其他方面其参数化相当灵活:
Gamma Distributions
这种分布也被称为负二项分布,我们可以将其视为泊松分布的混合。
如果你觉得这很困惑,你并不孤单,也许你会开始理解为什么我们经常试图用好的旧的正态分布来*似事物…
狄利克雷多项式
一个或许更有趣但似乎很少被提及的共轭分布的例子是 BDA3 第 3 章中介绍的狄利克雷多项式分布。
思考狄利克雷-多项式分布的一种方式是,多项式(即多项选择)分布是二项式分布(即二元选择)的推广,狄利克雷分布是贝塔分布的推广。也就是说, Beta 分布模拟单个概率p概率的概率,而 Dirichlet 模拟多个互斥选择的概率,由 a 参数化,a 被称为浓度参数,代表每个选择的权重(我们将在后面看到更多)。
换句话说,把硬币想象成贝塔二项式分布,把骰子想象成狄利克雷多项式分布。
θ∞狄利克雷(a)
y∞多项式(n,θ)
在野外,我们可能会遇到狄利克雷分布,这些天经常出现在自然语言处理中的主题建模上下文中,它通常被用作潜在狄利克雷分配(或 LDA)模型的一部分,这是一种奇特的方式,即我们试图计算出一篇文章属于给定内容的某个主题的概率。
然而,为了我们的目的,让我们在简单的多项选择的背景下看一下狄利克雷多项式,让我们从投掷骰子作为激励的例子开始。
扔骰子
(如果您想尝试这里的代码片段,您需要首先导入相关的 Python 库。或者您可以跟随本文附带的 Jupyter 笔记本。)
import numpy as np
from scipy import stats
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import pymc3 as pm
让我们首先创建一些表示 122 个六面骰子的数据,其中 p 表示公*骰子每一面的预期概率,即 1/6。
y = np.asarray([20, 21, 17, 19, 17, 28])
k = len(y)
p = 1/k
n = y.sum()print(n, p)**(122, 0.16666666666666666)**
仅仅看一个简单的数据柱状图,我们就怀疑我们可能处理的不是一个公*的死亡!
sns.barplot(x=np.arange(1, k+1), y=y);
Barplot of rolls of six-sided die
然而,我们是贝叶斯统计的学生,我们想更进一步,量化我们在骰子的公*性方面的不确定性,并计算有人向我们扔骰子的概率。
让我们在 PyMC3 中建立一个简单的模型,它不仅可以计算 theta 的后验概率(即骰子每边的概率),还可以估计骰子返回 6 的偏差。为此,除了未观察到的(theta
)和观察到的(results
)随机变量之外,我们还将使用 PyMC3 Deterministic
变量。
对于θ上的先验,我们将假设非信息性的均匀分布,通过用参数a
的一系列 1 初始化狄利克雷先验,一个 1 对应一个k
可能的结果。这类似于将一个 Beta 分布初始化为 Beta(1,1) ,它对应于均匀分布(关于这个的更多信息在这里)。
with pm.Model() as dice_model:
# initializes the Dirichlet distribution with a uniform prior:
a = np.ones(k)
theta = pm.Dirichlet("theta", a=a)
# Since theta[5] will hold the posterior probability
# of rolling a 6 we'll compare this to the
# reference value p = 1/6 to determine the amount of bias
# in the die
six_bias = pm.Deterministic("six_bias", theta[k-1] - p)
results = pm.Multinomial("results", n=n, p=theta, observed=y)
从 3.5 版开始,PyMC3 包含了一个方便的函数,可以用*板符号绘制模型:
pm.model_to_graphviz(dice_model)
让我们使用默认的 NUTS 采样器从关节后部抽取 1000 个样本:
with dice_model:
dice_trace = pm.sample(draws=1000) *Auto-assigning NUTS sampler...
Initializing NUTS using jitter+adapt_diag...
Multiprocess sampling (4 chains in 4 jobs)
NUTS: [theta]
Sampling 4 chains: 100%|██████████| 6000/6000 [00:01<00:00, 3822.31draws/s]*
从跟踪图中,我们已经可以看到其中一个θ后验概率与其余的不一致:
with dice_model:
pm.traceplot(dice_trace, combined=True, lines={"theta": p})
我们将绘制每个θ的后验分布,并将其与我们的参考值 p 进行比较,以查看 95% HPD(最高后验密度)区间是否包括 p=1/6 。
axes = pm.plot_posterior(dice_trace,
varnames=["theta"],
ref_val=np.round(p, 3))for i, ax in enumerate(axes):
ax.set_title(f"{i+1}")
我们可以清楚地看到,掷出 6 的后验概率的 HPD 几乎不包括我们对公*骰子的期望值。
更准确地说,通过比较θ[Six]和 p ,让我们画出骰子偏向 6 的概率。
ax = pm.plot_posterior(dice_trace,
varnames=["six_bias"],
ref_val=[0])ax.set_title(f"P(Theta[Six] - {p:.2%})");
P(Theta[Six])
最后,我们可以通过计算参考线右侧 0:
six_bias = dice_trace["six_bias"]
six_bias_perc = len(six_bias[six_bias>0])/len(six_bias)
print(f'P(Six is biased) = {six_bias_perc:.2%}')**P(Six is biased) = 95.25%**
因此,我们的骰子有超过 95%的可能性偏向 6。最好买些新骰子…!
投票#1
让我们把狄利克雷多项式分布的回顾转向另一个例子,关于轮询数据。
在 BDA3 关于多变量模型的第 3.4 节,特别是关于分类数据的多项模型的第节中,作者引用了 1988 年老布什和迈克尔·杜卡基斯总统竞选中的一个不太成熟的投票数据示例。
对于那些当时不关注政治的人来说:布什以巨大优势获胜。自 1988 年以来,没有一位总统候选人能在选举人票或普选中获得与布什相同或更高的票数。
(Image credit: https://commons.wikimedia.org/wiki/File:ElectoralCollege1988-Large.png))
反正回到数据问题!设置如下:
- 1,447 名可能的选民接受了关于他们在即将到来的总统选举中的偏好的调查
- 他们的回答是:
T5 布什:727
杜卡基斯:583
其他:137 - 更多人投票给布什而不是杜卡基斯的概率有多大?即两个主要候选人的支持率有什么不同?
我们设置了数据,其中k
代表受访者的选择数量:
y = np.asarray([727, 583, 137])
n = y.sum()
k = len(y)
我们再次建立了一个简单的狄利克雷多项式模型,并加入了一个Deterministic
变量来计算兴趣值——布什和杜卡基斯的受访者概率之差。
with pm.Model() as polling_model:
# initializes the Dirichlet distribution with a uniform prior:
a = np.ones(k)
theta = pm.Dirichlet("theta", a=a)
bush_dukakis_diff = pm.Deterministic("bush_dukakis_diff",
theta[0] - theta[1])
likelihood = pm.Multinomial("likelihood",
n=n,
p=theta,
observed=y)pm.model_to_graphviz(polling_model)
with polling_model:
polling_trace = pm.sample(draws=1000)
看看布什和杜卡基斯的受访者之间的%差异,我们可以看到大部分的密度是大于 0% ,这表明布什在这次民意调查中有很大的优势。
我们还通过scipy.stats
将 Beta 分布拟合到该数据,我们可以看到,2θ值的差值的后验非常好地拟合了 Beta 分布(鉴于狄利克雷分布作为 Beta 分布的多元推广的特性,这是可以预料的)。
_, ax = plt.subplots(1,1, figsize=(10, 6))
sns.distplot(polling_trace["bush_dukakis_diff"],
bins=20, ax=ax, kde=False, fit=stats.beta)ax.axvline(0, c='g', linestyle='dotted')
ax.set_title("% Difference Bush vs Dukakis")
ax.set_xlabel("% Difference");
带有bush_dukakis_diff > 0
的样本百分比:
diff = polling_trace["bush_dukakis_diff"]
bush_dukakis_diff_perc = len(diff[diff>0])/len(diff)
print(f'P(More Responses for Bush) = {bush_dukakis_diff_perc:.0%}')**P(More Responses for Bush) = 100%**
投票#2
作为对前一个模型的扩展,BDA 的作者在第 3.10 章中包括了一个练习(练习 2),为我们提供了 1988 年总统竞选的民调数据,在辩论之一的之前取,在之后取。
两个多项观察值的比较:1988 年 9 月 25 日,一场总统竞选辩论的当晚,ABC 新闻对美国注册选民进行了一项调查;辩论前对 639 人进行了民意测验,辩论后对 639 名不同的人进行了民意测验。结果如表 3.2 所示。假设调查是从注册选民人口中随机抽取的独立样本。用两种不同的多项式分布对数据建模。对于 j=1,2 ,设 αj 为在调查 j 时偏好布什或杜卡基斯的选民中,偏好布什的比例。绘制α2-α1的后验密度直方图。转向布什的后验概率是多少?
让我们复制练习中的数据,将问题建模为概率模型,同样使用 PyMC3:
data = pd.DataFrame([
{"candidate": "bush", "pre": 294, "post": 288},
{"candidate": "dukakis", "pre": 307, "post": 332},
{"candidate": "other", "pre": 38, "post": 10}
], columns=["candidate", "pre", "post"])
转换为 2x3 阵列:
y = data[["pre", "post"]].T.valuesprint(y) **array([[294, 307, 38],
[288, 332, 10]])**
每次调查的受访者人数:
n = y.sum(axis=1)
print(n)**array([639, 630])**
每次调查中两个主要候选人的受访者人数:
m = y[:, :2].sum(axis=1)
print(m) **array([601, 620])**
对于这个模型,我们需要稍微不同地设置先验。我们需要 2 套,而不是 1 套theta,每个调查一套(辩论前/辩论后)。要做到这一点而不创建每个变量的特定前/后版本,我们将利用 PyMC3 的shape
参数,该参数可用于大多数(所有?)分布。
在这种情况下,我们需要一个二维形状参数,代表辩论的数量n_debates
和候选人的选择数量n_candidates
n_debates, n_candidates = y.shape
print(n_debates, n_candidates) **(2, 3)**
因此,我们需要用形状(2,3)
初始化 Dirichlet 分布,然后在需要的地方通过索引引用相关参数。
with pm.Model() as polling_model_debates:
# initializes the Dirichlet distribution with a uniform prior: shape = (n_debates, n_candidates)
a = np.ones(shape)
# This creates a separate Dirichlet distribution for each debate
# where sum of probabilities across candidates = 100%
# for each debate theta = pm.Dirichlet("theta", a=a, shape=shape)
# get the "Bush" theta for each debate, at index=0
# and normalize across supporters for the 2 major candidates bush_pref = pm.Deterministic("bush_pref", theta[:, 0] * n / m)
# to calculate probability that support for Bush
# shifted from debate 1 [0] to 2 [1] bush_shift = pm.Deterministic("bush_shift",
bush_pref[1]-bush_pref[0])
# because of the shapes of the inputs,
# this essentially creates 2 multinomials,
# one for each debate responses = pm.Multinomial("responses",
n=n, p=theta, observed=y)
对于具有多维形状的模型,最好在采样前检查各种参数的形状:
for v in polling_model_debates.unobserved_RVs:
print(v, v.tag.test_value.shape)**theta_stickbreaking__ (2, 2)
*theta (2, 3)* bush_pref (2,)
bush_shift ()**
标牌视觉效果也有所帮助:
pm.model_to_graphviz(polling_model_debates)
让我们以稍微多一点的抽取次数和调谐步骤进行采样:
with polling_model_debates:
polling_trace_debates = pm.sample(draws=3000, tune=1500)
快速查看 traceplot 以确保模型*滑收敛:
with polling_model_debates:
pm.traceplot(polling_trace_debates, combined=True)
让我们来看一下theta
的后验概率的*均值,表明辩论前&后每位候选人的支持率百分比:
s = ["pre", "post"]
candidates = data["candidate"].valuespd.DataFrame(polling_trace_debates["theta"].mean(axis=0),
index=s,
columns=candidates)
仅从*均值来看,我们可以看到布什的支持者人数可能在辩论后从 48.8%下降到 46.3%(作为两大候选人支持者的百分比):
pd.DataFrame(polling_trace_debates["bush_pref"].mean(axis=0),
index=s, columns=["bush_pref"])
让我们通过绘制布什%回应的辩论前/后值的后验分布和布什支持者辩论前/后差异的后验分布来直观地比较结果:
_, ax = plt.subplots(2,1, figsize=(10, 10))sns.distplot(polling_trace_debates["bush_pref"][:,0],
hist=False, ax=ax[0], label="Pre-Debate")sns.distplot(polling_trace_debates["bush_pref"][:,1],
hist=False, ax=ax[0], label="Post-Debate")ax[0].set_title("% Responses for Bush vs Dukakis")
ax[0].set_xlabel("% Responses");sns.distplot(polling_trace_debates["bush_shift"],
hist=True, ax=ax[1], label="P(Bush Shift)")ax[1].axvline(0, c='g', linestyle='dotted')
ax[1].set_title("% Shift Pre/Prior Debate")
ax[1].set_xlabel("% Shift");
从第二个图中,我们已经可以看到很大一部分后验密度低于 0,但让我们精确地实际计算一下辩论后支持从转向布什的概率:
bush_shift = polling_trace_debates["bush_shift"]
perc_shift = (
len(bush_shift[bush_shift > 0])
/len(bush_shift)
)
print(f'P(Shift Towards Bush) = {perc_shift:.1%}')**P(Shift Towards Bush) = 19.9%**
虽然这是一种迂回的方式来表明布什在 9 月的辩论中失去了支持,但希望这说明了概率模型(和 PyMC3)的灵活性和稳健性。
如果你对这篇文章有任何想法或反馈,请告诉我!
(这个帖子在 Github 上也有 Jupyter 笔记本。)
一台机器能打败世界上最好的网球运动员吗?
原文:https://towardsdatascience.com/can-a-machine-beat-the-best-tennis-player-in-the-world-79112b47f547?source=collection_archive---------26-----------------------
Photo by Marcus Nilsson
介绍
我是个网球爱好者。我喜欢每周打网球,看网球,甚至打梦幻网球。虽然梦幻网球不像梦幻足球那样普及,但世界各地都有相当多的人参与其中。有多种格式,但最常见的是括号。在括号格式中,在锦标赛开始之前,幻想网球运动员试图预测谁将是锦标赛中所有网球比赛的获胜者。
由于我既是一个超级网球迷,也是一个数据呆子,我一直想知道机器学习算法如何应对世界上最好的幻想网球运动员。它能打败他们吗?为了回答这个问题,我着手做了四件事:
- 为挑战设定规则
- 为挑战创建基准预测
- 测试最佳梦幻网球选手在挑战中的表现
- 建立一个机器学习模型,并在挑战赛上进行测试
术语网球运动员在这种情况下可能有点混乱,因为它既可以适用于幻想的网球运动员,也可以适用于实际参加网球比赛的网球运动员。为了清楚起见,每当我提到这位梦幻网球运动员时,我将在博客的其余部分使用 FTP 缩写。
1.为挑战设定规则
挑战将包括预测哪名选手将成为网球比赛的获胜者:
- 我将使用 2018 年所有 66 场 ATP 单打比赛中的 1758 场比赛,不包括 ATP 巡回赛决赛。之所以选择 2018 年,是因为在撰写本文时,这是最后一个完整的赛季。第 3 节解释了为什么没有选择本赛季的所有比赛。
- 只有比赛开始前可用的数据才能用来预测比赛的结果。
- 挑战的参赛者将会是:基准预测、FTP 和机器学习模型都将预测相同匹配的结果。
- 准确性将被用来衡量参赛者的预测有多好。这意味着成功预测最多比赛次数的选手将获胜。通过将正确预测的数量除以所有预测来计算准确度。如果 100 个匹配中有 50 个预测正确,准确率将是 50%。
2.为挑战创建基准预测
为了与 FTP 和机器学习模型的预测进行比较,我首先创建了一个基准预测。使用的简单策略是总是挑选排名最好的球员作为比赛的获胜者。ATP 排名显示了球员在过去 52 周的表现。
当应用这种策略时,1758 个匹配中有 1101 个被正确预测。这相当于精度为 62.6% 。
3.测试最佳梦幻网球选手在挑战中的表现
那么谁是世界上最好的 FTP 呢?由于不存在任何官方的梦幻网球排名,答案并不直接,可能有点主观。周围有许多不同的梦幻网球网站,但 www.tennisdrawchallenge.com 是一个支持全年所有 ATP 比赛的网站。它也是玩家最活跃的网站之一,有超过 1000 名玩家参加大满贯赛事。对于这个挑战,我选择了正确预测 2018 年比赛数量最多的 FTP:
Best fantasy tennis player of 2018
所以世界上最好的 FTP 预测 57%的匹配是正确的。但是等等,就 57%?考虑到抛硬币能让你得到 50%,这听起来很低。原因是括号格式,所有比赛都必须在比赛开始前预测。所以当 FTP 做预测时,只有在第一轮比赛中,他才能绝对确定比赛中的网球选手是谁。随着锦标赛进入下一轮,预测的获胜者甚至可能不会参加比赛。自然,正确预测的数量会比在比赛开始后但每场比赛开始前预测的少。
为了让 FTP 更公*一点,我只考虑了基于比赛中正确球员的预测。让我来解释一下 2018 年澳大利亚网球公开赛抽签的一些例子:
Grey = no previous match, Green = won previous match, Red = lost previous match
- 例 1 :第一轮的所有比赛都将被考虑在内,因为每场比赛中的两名选手在预测时都是已知的。对于这个例子,这将意味着由框 1 标记的所有 8 个匹配。
- 例 2 :在这场比赛中,双方球员都和 FTP 预测的一样,因此会被考虑在内。FTP 认为纳达尔将击败迈尔,这被证明是真的。
- 例 3 :这场比赛不算,因为其中一名球员不认识。FTP 认为这场比赛将是施瓦茨曼对哈利斯,但结果却是施瓦茨曼对路德。由于该预测是基于比赛中错误的球员做出的,因此将不予考虑。
在调整为仅包括两个玩家都已知的匹配后,FTP 预测 1758 个匹配中有 1168 个是正确的,这将产生 66.4%的准确率。这是将对照机器学习模型进行测试的结果。
4.建立一个机器学习模型,并在挑战赛上进行测试
与任何机器学习模型一样,我们在预测任何事情之前都需要数据。在这次挑战中,我使用了 Jeff Sackmann 提供的 ATP 数据。杰夫多年来一直免费分享高质量的网球数据,非常感谢他。
根据 ATP 数据,我创建了一组输入,模型应该根据这些输入进行训练。像玩家的排名,年龄,身高,与对手的正面交锋,胜率等等都被使用。
对于模型本身,测试了几种不同的机器学习模型。表现最好的是 XGBoost。所有的数据准备和建模细节都可以在我的 Github 资源库这里找到。
当机器学习模型预测到同样的 1758 个匹配时,它成功地获得了 1375 个正确,这相当于 78.2% 的准确率。
结论
在这篇文章中,我试图回答一台机器是否能打败世界上最好的 FTP 的问题。我找到了世界上最好的 FTP,看到了他在 2018 年 ATP 单打赛季期间对网球比赛冠军的预测有多准确。然后,我使用 XGBoost 分类器建立了一个机器学习模型,并在相同的网球比赛中进行了测试。结果是:
Results for challenge
结果不言自明。机器学习模型不仅打败了最好的 FTP。它会以巨大的优势做到这一点。
那么这是否意味着每个 FTP 都应该开始让机器为它们做决定呢?不一定。通常,在梦幻网球的世界里没有奖金,所以金钱不是主要的动机。大多数玩家参加比赛是为了荣誉和乐趣。让一台机器做所有的决定会减少一些乐趣。但大多数 FTP 可能会受益,并通过分析机器学习模型如何预测网球比赛来了解更多关于比赛的信息。
看来梦幻网球的世界仍有很大的改进潜力。
机器人能让你笑吗?—教人工智能讲笑话
原文:https://towardsdatascience.com/can-a-robot-make-you-laugh-teaching-an-ai-to-tell-jokes-815f1e1e689c?source=collection_archive---------8-----------------------
是的,他几乎和我一样有趣!
A robot laughing at a friend’s joke (Pinterest)
Tito Joker 是一个幽默的 AI,它使用最先进的深度学习来讲笑话。他的目标是充分理解幽默,讲出真正有趣的笑话。
为什么他被命名为提托小丑?因为在菲律宾语中,“tito”翻译成英语就是“叔叔”的意思,而在菲律宾,我们都有那个说最幼稚笑话的叔叔!
Tito Joker tells riddle type jokes based on custom inputs typed in by users
欢迎在这个网站上与蒂托·小丑互动。
如上面的 gif 图所示,他不仅能够讲语法正确的笑话,而且还能讲出正确的笑话。
例如,他理解“小鸡为什么过马路?”,用一个在鸡过马路的上下文中有意义的地点或原因来回答。当然,他并不是一直都这样,但他经常这样(如下图)。
Tito Joker can tell as many jokes as you want given your input question
为了让他更有趣,我决定教他如何使用互联网上最流行的交流方式之一——gif!这个想法是,一旦他讲了一个笑话,他也试图展示一个与这个笑话相关的 GIF。
Tito Joker is able to show a GIF that matches the meaning of the joke
这怎么可能?
今年 2019 年,我在深度学习的自然语言处理(NLP)应用方面做了很多工作,特别关注去年发布的基于 Transformer 的预训练模型——BERT、 OpenAI GPT-2 和 XLNET 。
别担心,我不会在这里详细讨论 Transformer 架构,但下面是来自 Jay Allamar 的惊人的博客文章的解释图。
Transformer Architecture Illustration by Jay Alammar
作为一个爱开玩笑的人,我可以说我对幽默很有热情,所以模拟其复杂性的想法真的让我很兴奋。我们能否利用深度学习来建立一个实际上自己很有趣的 AI?也许,我们甚至可以把它带到一个可以做单口喜剧的地步!(见下文)
C-3PO telling a joke as a standup comedian
1.利用开放式 GPT-2 进行迁移学习
鉴于它在语言生成任务上的顶级性能,我决定使用 OpenAI GPT-2(简称 GPT2)作为 Tito Joker 的主干模型。GPT2 的目标很简单——给定所有前面的单词,预测语句的下一个单词(如下所示)。
Language modelling illustration by Jay Alammar
请注意,GPT2 被训练使用从 800 万个网页中抓取的 40GB 文本来完成这一任务。这是一个很大的文本!
现在,这一切都很有趣,但我们如何使用这个模型来创建一个讲笑话的人工智能?迁移学习 —使用预训练模型(例如 GPT2)并在另一个数据集上“微调”它的过程,该数据集包含您希望模型学习的信息。
从这里开始,很明显,方法将是收集包含幽默的文本数据集。通过在幽默数据集上微调 GPT2,我们可以创建一个新的人工智能模型,它理解幽默,并因此可以讲笑话——蒂托·小丑。
2.带有谜语式笑话的幽默数据集创建
来自 Kaggle 的笑话数据集被用于微调。它包含了 231,657 个不同格式的笑话,包括“Yo Mama”和“它需要多少个”各种笑话。
警告:该数据集包含 NSFW 笑话,因此 Tito Joker 的幽默也将反映这种性质的笑话。我计划在 Tito Joker 的未来版本中增加过滤这些内容的功能。
Kaggle is a platform that gives free access to data science competitions and open-sourced datasets
为了让 Tito Joker 更容易理解一个笑话的“概念”,我决定把这个笑话的范围限定为谜语类型的笑话。换句话说,我过滤了以“什么”、“如何”、“何时”或“为什么”开头的笑话。这使得笑话的数量下降到 65394 个。
除此之外,我还添加了一些特殊的标记,让模型能够理解一个谜语式笑话的“问题”和“答案”之间的区别。下表总结了这些情况:
Special tokens help Tito Joker understand the structure of a riddle type joke
带有特殊标志的笑话示例:
小鸡为什么要过马路? 到另一边去。
更多详情请参考 Tito Joker 的预处理脚本。
3.用 GPT2 +幽默数据集进行 Tito Joker 训练
既然我们已经有了预训练的模型和幽默的数据集,我们现在可以训练 Tito Joker 了!Tito Joker 是通过对上一节的幽默数据集进行微调而创建的。通过这个过程,Tito Joker 有效地从幽默数据集中“学习”了幽默的概念。
Tito Joker 的端到端培训工作流程总结如下:
Tito Joker’s Training Workflow
在一台配有一个 T4 GPU、批量为 2 的 Google Colab 笔记本上,微调大约需要 30 分钟。另外,请注意,培训过程是使用与原始 GPT2 论文相同的语言建模目标和超参数执行的。
更多信息请参考铁托小丑训练脚本。
4.使用词性标注和 GIPHY 生成 GIF
词性标注被用来检测蒂托·乔克讲的笑话中的名词。一旦常见名词被识别出来,它们就被用来搜索 GIPHY API ,然后返回一个相关的 GIF。
比如,如果输入的段子是“为什么鸡要过马路?”,常见名词,鸡,将被检测并用于从 GIPHY 返回一个 GIF。
POS tagging illustration from nlpforhackers
请注意,我最初计划使用命名实体识别(NER),但决定从名词开始,因为“名称”在 GIPHY 上更难匹配。例如,“Lorenzo”(指我自己)不太可能返回我自己的相关 GIF,相比之下,常见的名词“boy”在 GIPHY API 上会很容易有匹配。
提托小丑怎么学才能更搞笑?
Tito Joker still has a lot to learn if he wants to be as funny as me 😃
1.对笑话的滑稽程度进行“评级”
一个反馈系统将允许用户“评价”蒂托·乔克讲的笑话。这些反馈将被储存起来,并可用于随着时间的推移不断提高 Tito Joker 的“滑稽度”。
从建模的角度来看,这可能意味着必须训练一个单独的“滑稽”模型,用于过滤产生的笑话。强力方法的一个例子是生成 100 个笑话,然后只返回这 100 个笑话中最有趣的一个。
2.控制要讲的笑话类型
语义控件将允许用户配置他们想从 Tito Joker 中体验的幽默类型。例如,我们可能想要明确地告诉 Tito Joker 产生 Yo Mama 类型的笑话,或者我们甚至可能想要明确地设置情绪,并最小化所讲笑话的毒性。
这将要求我们在培训和部署时考虑这些玩笑维度(例如玩笑类型、情绪和毒性)。他们的梦想是拥有类似于关的 TL-GAN 模型的东西,这种模型可以根据年龄、发际线和性别(以及其他因素)轻松配置模型生成的人脸。
3.给 Tito Joker 一个主题的上下文
上下文输入将允许用户给提托小丑上下文信息,他们希望提托小丑在讲笑话时考虑这些信息。这是基于一个想法,即语境是一个笑话的智慧的来源。例如,单口喜剧演员被认为是有趣的,因为他们能够在他们讲的笑话中嵌入相关的概念——政治、文化、时事。
实现这一点的一种方法是使用类似的规范,用 BERT 来表示 Q & A ,其中问题和上下文段落都被用作模型的输入。想象一下,能够输入一篇关于唐纳德·特朗普的文章,以向蒂托·小丑提供在讲笑话时要考虑哪种信息的背景(例如,墨西哥边境上的墙、移民、与中国的贸易战等)。).
结论
用人工智能模拟幽默仍然是一项正在进行的工作,但还有很多实验有待进行。如果我们继续朝着这个目标努力,我相信很快我们就能训练提托·小丑自己变得有趣。
如果你想试用 Tito Joker,了解更多的方法,甚至为改进模型做出贡献,请随时查看网站和 github repo 。
如果还有任何问题,请不要犹豫,在下面评论,给我发电子邮件(lorenzo.ampil@gmail.com),或者通过 Linkedin 或 Twitter 给我发信息。
承认
特别感谢:
- 拥抱脸因为他们使用 PyTorch 实现了 OpenAI GPT-2
- Streamlit 让部署 Tito Joker 成为一个网络应用变得非常简单
- 思维机器数据科学公司赞助了我运行 Tito Joker 的服务器
- 我的 TM 同事在这篇文章上给了我大量建设性的反馈。
- 空间让他们的 POS 和 NER 模型变得非常简单易用
参考
- 拉德福德等人(2018)“语言模型是无监督的多任务学习者”来自https://cdn . open ai . com/better-Language-Models/Language _ Models _ are _ Unsupervised _ multishop _ Learners . pdf
- OpenAI (2019)“更好的语言模型及其含义”,来自 https://openai.com/blog/better-language-models/#fn1
- 来自 https://jalammar.github.io/illustrated-gpt2/的 Allamar,J. (2019)“图解 GPT-2(可视化变压器语言模型)”
- 关,S. (2018)“使用人工智能生成定制的照片级真实感人脸”来自https://blog . insightdatascience . com/Generating-custom-photo-realistic-faces-using-AI-d 170 B1 b 59255
- Devlin 等人(2018)“BERT:用于语言理解的深度双向转换器的预训练”,来自https://arxiv.org/pdf/1810.04805.pdf
AI 能解决气候变化吗?
原文:https://towardsdatascience.com/can-ai-solve-climate-change-9a014c0960b8?source=collection_archive---------37-----------------------
AI 是害了还是助了气候??
Photo by Markus Spiske on Unsplash
人工智能是巨大的,大到足以让 Ng 教授说“人工智能是新的电力”。所以我们知道它将被用于各种不同的行业。AI 的主要优势可以总结为一个词,自动化。由于智能代理/模型,它现在可以执行需要基本人类智能的复杂任务。
然而,一个很大的警告是,这些模型消耗大量的数据和电力。在计算机视觉和自然语言处理中,模型的碳足迹一直在增加,这种趋势不仅对环境不友好,而且昂贵,增加了参与这项研究的障碍。
坏了
Image from[2]
深度学习模型多年来变得如此之好的一个主要原因是由于模型规模的增加,无论是深度还是宽度。但随着网络中可训练参数数量的增加,训练模型所需的电力也在增加。更多的电力意味着更多的碳足迹。
碳足迹有多少?
嗯……对某些车型来说,它产生了 284 吨二氧化碳,是普通汽车一生排放量的五倍。这太糟糕了。当我们观察研究的方向时,我不认为这是结束,目前人工智能最有前途的方向之一是神经架构搜索 (NAS)。
NAS 基本上是在创建一个人工智能代理,它训练另一个人工智能模型以最有效的方式执行任务。NAS 研究的主要驱动力是去除手工工程部分。这意味着研究人员将能够让他们的计算机运行几天甚至几个月,而代理人正在寻找最有效的架构。想象一下这会留下多少碳足迹。
考虑到所有这些,我们应该停止人工智能研究吗?
等等!这并不全是坏事!
Photo by Nikita Kachanovsky on Unsplash
乍一看,人工智能似乎只对气候有害。但事实并非如此。
人工智能被用于减少碳足迹的例子很多。
例如,与谷歌合作的 Deep Mind 能够减少谷歌数据中心的能源使用。减少足够减少 40%的冷却费用!多个数据中心可以受益于这项技术,如脸书、微软和亚马逊。
这只是一个例子,在科技中心。但是机器学习可以应用于科技之外的许多不同领域。材料科学等领域可以使用机器学习来创造低碳材料,天气可以更准确地预测,运输可以更有效,智能建筑可以调节温度,同时使用更少的能源,机器学习可以为阻止气候变化提供很多东西。
所以总而言之,像大多数技术一样,人工智能可以用于好的方面,也可以用于坏的方面。而在开发过程中,当研究人员测试和建造不同的类型时,将会产生大量的碳足迹。模型建成后,我认为它可以给这个世界带来许多气候友好的应用。
与此同时,我们的工作是围绕人工智能和气候变化制定更好的政策,正如本文中所写的。我很想知道这项创新进展如何。更多类似的文章请访问我的网站或我的 YouTube 频道。
参考
- r .施瓦茨、j .道奇、n .史密斯和 o .埃齐奥尼(2019 年)。绿色人工智能。arXiv.org。检索于 2019 年 10 月 22 日,来自https://arxiv.org/abs/1907.10597
- 人工智能和计算。(2018).OpenAI。检索于 2019 年 10 月 22 日,来自https://openai.com/blog/ai-and-compute/
- 人工智能的碳足迹是汽车的 5 倍。(2019).大众力学。检索于 2019 年 10 月 22 日,来自https://www . popular mechanics . com/technology/infra structure/a 27793543/artificial-intelligence-carbon-footprint/# target text = The % 20 act % 20 of % 20 training % 20a,emissions % 20 of % 20 an % 20 average % 20 car。&target text = It % 20 was % 20 trained % 20 to % 20 process % 20 words % 20 from % 208% 2000 万%20web%20pages 。
- DeepMind AI 将谷歌数据中心的冷却费用降低了 40%。(2019).深度思维。检索于 2019 年 10 月 22 日,来自https://deep mind . com/blog/article/deep mind-ai-reduces-Google-data-centre-cooling-bill-40
- 人工智能和气候变化:它们是如何联系在一起的,以及我们能做些什么。(2019).中等。检索于 2019 年 10 月 22 日,来自https://medium . com/@ ai now institute/ai-and-climate-change-how-they-connected-and-what-we-can-do-about-it-6a A8 d 0 F5 b 32 c
- 人工智能可以帮助应对气候变化——这里有八种方法。(2019).边缘。检索 2019 年 10 月 22 日,来自https://www . the verge . com/2019/6/25/18744034/ai-人工智能-ml-气候变化-战斗-阻截
AI 能写得像莎士比亚吗?
原文:https://towardsdatascience.com/can-ai-write-like-shakespeare-de710befbfee?source=collection_archive---------17-----------------------
许多真话都是在玩笑中说出来的
——莎士比亚、 李尔王
“啊,小心,我的主,嫉妒;这是绿眼睛的怪物,它嘲笑它所吃的肉。
――威廉·莎士比亚, 奥赛罗
有一颗星星在跳舞,在那颗星星下,我诞生了
――莎士比亚, 无事生非
谁能像莎士比亚那样写作?或者像莎士比亚那样拼写?我们能教人工智能像莎士比亚一样写作吗?还是这是一个无望的任务?一个 AI 神经网络能否像李尔王一样描述绝望,像奥赛罗一样感受嫉妒,或者像贝内迪克一样运用幽默?理论上,如果我们能教会它,没有理由不这样做。
从麻省理工学院的威廉莎士比亚全集网站上,我下载了三部著名的莎士比亚名著:《李尔王》、《奥赛罗》和《无事生非》。然后我在这个语料库上训练了一个深度学习 递归神经网络(RNN) 带有一个隐藏层的长短期记忆(LSTM)单元来产生自由文本。
神经网络能够像莎士比亚那样学习写作吗?如果是的话,它在模仿诗人风格方面走了多远?它能够为剧中的每一个角色产生一个有意义的文本吗?在人工智能情节中,苔丝狄蒙娜会遇到李尔王吗?这会引发奥赛罗的嫉妒吗?悲剧会战胜喜剧吗?每个角色会保持和原版戏剧一样的说话风格吗?
我相信你有更多的问题。所以,事不宜迟,让我们看看我们的深度学习网络是否能够产生诗歌,或者仅仅是装傻。
用 LSTM 神经网络生成自由文本
递归神经网络(RNN)已经被成功地用于生成自由文本。用于自由文本生成的最常见的神经网络架构依赖于至少一个 LSTM 层。
为了训练我们的第一个 Shakespeare simulator,我使用了一个只有三层的神经网络:输入层、LSTM 层和输出层(图 1)。
该网络在字符级被训练。也就是说,从输入文本中生成 m 个字符的序列,并输入到网络中。
每个字符都使用热零编码进行编码。这意味着每个字符由大小为 n 的向量表示,其中 n 是来自输入文本语料库的字符集的大小。
将大小为[m,n]的全部输入张量输入到网络中。训练网络将位置 m+1 处的下一个字符与前 m 个字符相关联。
所有这些导致了以下网络:
- 具有 n 个单位的输入层将接受[m,n]个张量,其中 n 是字符集的大小,m 是用于预测的过去样本(本例中为字符)的数量。我们任意选择 m=100,估计 100 个过去的字符可能足以预测第 101 个字符。当然,字符集的大小 n 取决于输入的语料库。
- 对于隐藏层,我们使用了 512 个 LSTM 单位。需要相对较高数量的 LSTM 单元来处理所有这些(过去 m 个字符-下一个字符)关联。
- 最后,最后一层包括 n 个 softmax 激活单元,其中 n 也是字符集的大小。事实上,这一层应该为字典中的每一个字符生成概率数组。因此,n 个输出单元,每个字符概率一个。
Figure 1. The deep learning LSTM-based neural network we used to generate free text. n input neurons, 512 hidden LSTM units, an output layer of n softmax units where n is the character set size, in this case the number of characters used in the training set.
注意,为了避免过度拟合,在 LSTM 层和输出密集层之间的训练期间,临时引入了中间的脱落层。丢弃层选择在训练阶段的每次迭代期间移除一些随机单元。然后移除脱落层用于部署。
构建、训练和部署神经网络
该网络接受了《李尔王》(King Lear)、《奥赛罗》(Othello)和《无事生非》(Ado About)的全文训练,这些文本可从威廉莎士比亚全集网站(The Complete of William Shakespeare)获得,共有 13298 个句子。
使用由 KNIME 分析*台提供的 Keras 和 TensorFlow 的基于 GUI 的集成来构建、训练和部署上述神经网络。
构建和训练网络的工作流程如图 2 所示。图 3 显示了部署网络逐个字符预测最终文本的工作流程。这两个工作流都是从博客帖子“从前…由 LSTM 网络”中实现的工作流复制和改编的,其中一个类似的网络被训练和部署来生成自由文本,已经对来自格林童话的文本进行了训练。这两个工作流都可以从 KNIME 示例服务器的 04 _ Analytics/14 _ Deep _ Learning/02 _ Keras/11 _ Generate _ Fairy _ Tales 下免费下载。
在图 2 中,定义网络结构部分(左上角)中的棕色块(节点)构建了神经网络的不同层。预处理和编码部分(左下)中的节点对数据进行清理、标准化、整形和转换。最后,训练由 Keras 网络学习者节点执行,并且网络被存储起来以供部署。
请注意,如果训练集很大,这个网络可能需要相当长的时间来训练。可以通过将 KNIME Analytics Platform 指向一个用于 GPU 的 Keras 安装来加快速度。
图 3 中的部署工作流读取并使用之前训练的网络来预测自由文本,一个字符接一个字符。
Figure 2. The training workflow trains a neural network (62 inputs -> 512 LSTM -> 62 outputs) to predict the next character in the text, based on the previous 100 characters. Training set consists of the texts of “King Lear,” “Othello,” and “Much Ado About Nothing” by William Shakespeare. Thus, the network should learn to build words and sentences in a Shakespearean style.
Figure 3. The deployment workflow takes 100 characters as the start and then generates text character after character in a loop, until 1,000 characters are generated, making the full, final Shakespeare-like text.
人工智能生成的莎士比亚文本
下面是一些结果,在对整个数据集(三部选定的戏剧)进行 50 个时期的训练后,使用 100 个过去的字符作为输入张量,并递归生成 1000 个新字符。
让我们从奥赛罗和苔丝狄蒙娜之间的对话(斜体)的 100 个字符开始,然后看看我们的网络将如何继续(纯文本)。
哦,我美丽的勇士!
——苔丝狄蒙娜
我亲爱的奥赛罗!
奥赛罗看到你比我先到这里来,我感到非常惊奇。哦,我灵魂的快乐!我是一个小人物。
——格洛斯特
我不知道,亲爱的:
我从心里发现你像个小偷
说皮尔查斯会好起来的。
将军说话就是这么
转一个人,我觉得,besoou。
-凯西奥先生,我请你撒谎:这只手里没有一份温柔和谈论;我不会被派遣威胁。
我们的好老朋友,
居士安抚国事,为他求情;
我会骗你更快!
和嫁妆的祝福:
净出足够做你;
还有那封信中的摩尔人是有缺陷的!阿布霍雷,天堂,我要去 sor
和对方也一样。
——奥赛罗
我看到他的演讲对我这样的考验,
他将生活在谎言的沼泽里
他和女儿
是一个最可怜的人,
他是这个国家最可怜的人,
一个被许多人称之为生命的人
一个不得不失去孩子的人。
先生,对我妹妹?
——奥斯瓦德我求求你,牵着你的手:你可以接受这一切,让他难过,让天堂
凯西奥把这句话藏在心里
让我说:我会永远…
— —
当苔丝狄蒙娜从对话中消失时,《李尔王》中的几个次要角色(格洛斯特、里根和奥斯瓦尔德)慢慢出现在场景中。我们从三部戏剧的不同台词出发,创造了其他自由文本,有趣的是,我们注意到悲剧《奥赛罗》和《李尔王》中的角色经常混合在一起,而喜剧《无事生非》中的角色似乎更自成一体。
该文本使用莎士比亚英语中的单词及其特有的复杂句子结构生成。不是所有的句子都有完美的意义,但大多数似乎都有。还要注意,次要角色被分配了较短的对话,而在这个例子中,奥赛罗和凯西奥得到了最长的发言——这是应该的。
用人工智能写出一个原始场景
让我们使用前 100 个字符(同样是斜体)来触发一个新的场景。在这里,我介绍了关键字“场景”、地点、涉及的角色以及第一个发言的角色的名字。神经网络完成剩下的工作。
场景一.
威尼斯。一条街道。
输入罗德利哥和伊阿古
苔丝狄蒙娜请告诉我凯西奥的事。
是的,所以我听到写信给 prive 和那里,
她会看到他现在如此巫妖 wor 老窟,
和最好的良心比在这场革命反对他:
有儿子反对父亲,
和你父亲的儿子,我们这个时代最好的没有 excel 你的忠告手表
最坏的不是一个温柔的好战的岛屿,
分裂必须采取的耻辱
的报复
让我们的命运支撑到一个力量,
在他们的本性中的视力,让安全地离开机架:我发誓,是这样的
,她会送回我的信使。
-格洛斯特
我看到枪托上的铁锈。
——李尔王
多好的一辆车啊,我可以认路
不应该这样,鄙视我的兄弟;
我已经超过了他,告诉我我很害怕,
她可能是诚实的,但他已经承认在他身上娱乐
,并认为下一个方式玷污它,
主 commet 至少
会让她喘不过气来,
她可能…
— —
事实证明,创造一个新场景比继续现有场景要困难得多。《苔丝狄蒙娜的谈话》开篇不错,和原著一致。然而,我不确定我能坚持到底。
用人工智能混合莎士比亚和现代英语
但说真的,一个产生古英语文本的人工智能引擎有多大用处?
我们能不能用一点莎士比亚的作品来改进现在的英语句子?让我们给我们受过莎士比亚训练的网络输入一些现代文本,看看会出现什么。
那么,什么样的日常,现代文本可以做一点莎士比亚的改进呢?软件许可协议?让我们看看网络能让许可协议的开始变得多有趣(斜体部分)。
本许可证是指 GNU 通用公共许可证的版本。版权也意味着版权——比克,
把我的任何东西交给他的剑
交给他的盐和最隐秘的散漫是如此为歌唱,但不是在他的事上比那更应肯定的是将被出售
作为主人比较,不要活在叛徒。祝福你的五个智慧!
——肯特
O 可惜!
先生,现在哪里还有耐心,
这离海那么远,还要招标拆除
那么多褶皱的救和诚。
——布拉班西奥
我一定不认为凯西奥的土耳其人在奇怪的会见一个魔术师的婴儿床是辱骂 libe 说
我可以欺骗他最好的优势,
在她的预言公*一点,目前在你的权力;谢谢你,先生。
-奥尔巴尼
格洛斯特,我会证明他的运动和第一 accuriors 和警卫和白色的谈话。
——李尔王
小偷在哪里?你永远也不会让船长们把信送到沼地去,如果他生气了,我们没有更好的东西就一定会值钱
——里根
我请求你,有一个比我想的更多的理由来宣布我的心,热
— —
拯救、诚实、小偷、主人、叛徒和欺骗这些词似乎符合上下文。还要注意,从许可协议的起始文本中萌发的对话有趣地主要涉及戏剧中次要的、不太悲惨的角色。
至于其他的,不可理解的部分对我来说就像原始的法律语言一样不可理解。引用我们电视网的话,“先生,现在哪里有耐心了……”
用 AI 做莎士比亚说唱
最后,让我们给我们的莎士比亚式英语人工智能注入一些不那么生硬的现代语言——一些有创意的东西。在一些说唱歌词中加入一点莎士比亚的风格怎么样?那会改变意思还是只改变单词?同样,让我们从一首说唱歌曲中触发 100 个字符的自由文本的生成。
她在你的 b**上吸着饼干,thot,thot,thot thot
在烹饪同伴,而她所能做到的最好的不是一个男人。
诚信,持有,我恳求你的恩典,—
——李尔王
那么他还有很多。
——李尔王
你已经看到了这种*淡的一部分,我原以为会看到塞弗永远不会第二次乘风破浪去捕捉那邪恶的恶魔。
仍然通过那条我不知道该怎么办的路。
——奥赛罗
你看见她了吗?啊,不幸的女孩!
先生,这个走投无路的混蛋!什么消息?
看错了我爸!
——李尔王
你说什么?
——肯特先生,我的确认识你;去荒野和雨中,我被她带走了我的姐妹?
——李尔王
不不不!城堡在哪里?
进入格洛斯特,与法国国王和科迪莉娅·高纳里尔
先生,我没有想到这一点。
——伊阿古
的确!
——奥赛罗
的确!是的,的确是:德西姆,先生。
——康沃尔
叹着气,会!
——奥赛罗
你看这张纸我该怎么抬出一个家伙来,那使他的儿子成为一个可怜的穷权力
那使他的儿子
下雨的时候魔鬼发怒了!我已经从寒风中失去了国王
— —
有趣的是,人工智能生成的文本谈论了一个不快乐的女孩、一个邪恶的恶魔和一个绝望的混蛋,这些词和其他词表达的概念非常接*许多说唱歌曲中包含的概念。
深度学习从莎士比亚身上学到了什么
我们已经完成了这个实验。我们训练了一个带有隐藏 LSTM 层的递归神经网络来生成自由文本。我们学到了什么?
总而言之,该网络是根据莎士比亚戏剧《李尔王》、《奥赛罗》和《无事生非》的全文进行训练的。它学会了用莎士比亚的风格创作自由文本。它只需要一个 100 个字符的初始序列来触发自由文本的生成。
我们展示了一些不同的结果。我们从奥赛罗和苔丝狄蒙娜之间的对话开始,看看网络将如何继续下去。我们还根据我们提供的角色和地点,让网络写了一个全新的场景。最后,我们通过在许可协议文本和说唱歌词文本中引入一点莎士比亚的风格,探索了用莎士比亚英语改进现代英语的可能性。有趣的是,莎士比亚英语中与上下文相关的单词出现在自由生成的文本中。
这些结果很有趣,因为真实的莎士比亚英语单词被用来形成更复杂的句子结构,即使是从现代英语句子开始。神经网络正确地识别主要或次要字符,给他们或多或少的文本。拼写和标点大多准确,甚至诗歌风格,即文本的节奏,遵循莎士比亚的风格。
当然,就更有意义的对话而言,试验数据集大小、神经单元和网络架构可能会带来更好的结果。
首次发表于 信息世界。
人工智能能帮助医疗决策吗?
原文:https://towardsdatascience.com/can-artificial-intelligence-help-medical-decision-making-77b63f5b981c?source=collection_archive---------13-----------------------
基于强化学习的化疗智能医生
将机器学习应用于医学领域的研究越来越受到关注。例如,计算机视觉已经被证明是为医生和医学研究人员提供分析信息的有价值的工具。
我想探索智能机器是否可以直接扮演医生的角色——自主做出医疗决策。在这个项目中,我创造了一个基于强化学习的智能医生,它可以根据患者的癌症进展情况制定最佳的化疗方案。
注:这是我提交给 2019 年纽约市科学与工程博览会的科学博览会项目。
什么是强化学习?
听说过 AlphaGo 吗? 阿尔法星?
Left: Taken From The Guardian’s article: “World’s best Go player flummoxed by Google’s ‘godlike’ AlphaGo”, Right: Taken from The Register’s article: “Human StarCraft II e-athletes crushed by neural net ace — DeepMind’s AlphaStar”
在媒体上,强化学习通常出现在游戏环境中;AI 机器人在围棋 (Deepmind 的 alpha Go)星际争霸 (Deepmind 的 alpha star)Dota(open AI 的 OpenAI Five)等游戏中击败人类职业选手。
本质上,强化学习是一个与最佳决策相关的机器学习领域:训练一个“代理”根据当前状态的观察做出最佳动作,以达到定义的理想状态。
在强化学习中,最优策略(将状态映射到最优动作的函数)是通过“试错”错误方法来学习的。代理基于对当前状态的观察来概率性地选择动作,观察结果状态,并根据定义的性能度量来接收“奖励”。也就是说,用于训练强化学习模型的数据是{ 状态、动作、奖励、下一状态}的元组。利用这些数据,代理评估所选动作的值,并更新其参数,以便具有更好值的动作——“最优动作”——将具有更高的被选择概率。
这是对强化学习的一个非常肤浅的解释——看看我的其他博文和,我在那里详细解释了核心概念和算法!
数据收集
作为一名独立的高中研究者,我不具备获取真实医学数据的法律和专业资格。为了克服这一点,我基于一个数学模型创建了一个化疗治疗模拟,该模型表示给定当前生理状态和应用的化疗剂量时患者癌症进展的变化。
该模型由(赵,2009)中构建的常微分方程组表示:
其中 W 、 M 、 D 分别代表毒性指数、肿瘤大小指数和归一化剂量, a、b、d 为(赵,2009)中确定的模型常数。{ M > 0 }术语表示一个至关重要的假设,即一旦肿瘤大小指数减少到 0,患者就被认为是永远治愈了,并且不会有癌症复发。 N 项表示高斯噪声,该噪声用于扰乱动态,试图模拟患者间的变异性和随机生理事件。
利用这个模型,我创建了一个化疗模拟环境,灵感来自于 OpenAI Gym。也就是说,环境包含成员函数:
reset()
:创建一个随机的初始患者实例。reward(state, action)
:根据当前和最终的患者生理状态评估应用剂量。返回一个数字“奖励”step(state, action)
:返回后续病人状态,并奖励给定当前状态的一个当前动作。
使用这种模拟,我们可以创建合成但似是而非的治疗数据及其相应的化疗治疗方案。然后我们用它来训练我们聪明的医生。
奖励函数
奖励函数非常重要,因为它塑造了代理人试图实现的最优行为。如果你看看强化学习的一般目标函数:
即最大化预期的情景累积回报,代理人行为的优化在很大程度上取决于回报函数(在各种强化学习算法中——如在培训我的医生时所使用的——目标函数中可以添加其他项)。
我们如何评价智能医师的治疗方案?
那么,我们如何构建一个奖励函数来恰当地解决医生的目标减少肿瘤大小,同时控制累积毒性?
以下是我们如何评估聪明的医生的决定的分析:
- 如果治疗导致肿瘤尺寸减小,则奖励为正;如果治疗导致肿瘤尺寸增大,则奖励为负。
- 如果治疗导致毒性降低,则奖励为正;如果治疗导致毒性增加,则奖励为负。
- 如果患者“治愈”(即肿瘤大小缩小至 0),则为高阳性奖励。
- 如果患者“死亡”(即肿瘤大小和毒性指数的加权和超过规定的阈值),则为高负回报。
及其奖励函数公式:
培养聪明的医生
智能医师基于软演员评论家算法(Haarnoja,2018)。我打算跳过关于算法的细节(因为帖子会太长),但如果有兴趣,你可以看看 图马斯·哈尔诺贾的论文 ,或者 瓦伊沙克诉库马尔的博文 。
本质上,软演员评论家可以:
- 学习连续行动空间中的最优策略。这适合于化疗任务,因为我们想要产生我们想要应用于患者的精确的最佳剂量。相反,在离散行动空间中学习,在这种情况下,意味着从有限的、少量的预定义剂量中进行选择,永远不会是真正的最优决策(只是给定选择中的最优选择)。
- 通过最大化状态空间探索非常高效和有效地学习最优策略。软行动者批评家通过将熵项结合到其目标函数中,抑制贪婪的行动选择,并鼓励代理在学习时尽可能随机地行动。
所以,这里有一个培训聪明医生的概述:
那就是:
- 我们生成一个随机的病人实例
- 我们用现有的模型进行化疗
- 将癌症进展和治疗方案存储在智能医生的存储器中
- 用智能医生记忆中随机批次的癌症进展和治疗方案更新神经网络参数
- 对 1000 个生成的患者重复步骤 1~4。
测试训练有素的医生
在智能医生对 1000 名患者进行训练后,它在另一组 1000 名假设的患者身上进行了测试。
对于这 1000 名患者,医生展示了以下统计数据:
一般来说,在治疗结束时,医生能够完全减少患者的肿瘤块,而毒性仍然存在,但没有达到致命水*。当“治愈”被定义为最终肿瘤块时< 0.01 and final toxicity index < 0.8, ,医生治愈了 1000 名模拟患者中的 947 名。
下面是从医生那里摘录的一个成功治疗进展的例子:
Left: Cancer Progression (Blue: Tumor Mass, Orange: Toxicity), Right: optimal dosage regimen produced by intelligent physician
在这种情况下,医生似乎在初始阶段使用了大剂量治疗来快速缩小肿瘤大小,然后使用小剂量至零剂量来逐渐减少累积的毒性。
讨论
在训练聪明的医生制定最佳化疗方案方面取得了成功。医生可以有效地减小肿瘤大小,同时将毒性保持在非致命水*,并最终达到完全安全的水*。
然而,更重要的问题在于人工智能的伦理。
医疗领域的决策具有极高的风险。在癌症治疗的背景下,患者没有机会尝试多种治疗方案。因此,我必须承认我所采用的方法中的问题,以及机器学习方法的固有弱点:
- 这个模型只能和它得到的数据一样好。数学模型很难复制病人之间的变异性和决定真实世界动态的随机事件。因此,我的方法对于现实世界的应用来说永远不够健壮。
- 强化学习在现实世界的应用中变得很成问题,因为我们无法在元层面上预测或解释它的行为。我们所知道的是,行为是由定义的奖励函数塑造的,是通过数百万个数据点的训练获得的。
- 尤其是在复杂、高维的状态和动作空间中,强化学习在面对未知条件时往往泛化能力很差。因此,我们永远无法保证在现实生活中部署时不会发生灾难性的行为。
然而,现代强化学习是一个相对年轻的领域,并且正在以非常快的速度增长——我们永远无法衡量它在几十年后会有什么能力。无论如何,人工智能在现实世界中的应用应该以极大的责任感和谨慎来对待。
参考文献(在这篇博文中)
- 赵,,癌症临床试验的强化学习设计,北卡罗来纳大学教堂山分校,2009。
- Tuomas Haarnoja,Aurick Zhou,Pieter Abbeel,和 Sergey Levine,软行动者-批评家:具有随机行动者的非策略最大熵深度强化学习,第 35 届机器学习国际会议论文集,2018 年,ICML,瑞典斯德哥尔摩,stockholmsssan,2018 年 7 月 10 日至 15 日,2018 年,第 1856-1865 页。
自动化机器学习能胜过手工模型吗?
原文:https://towardsdatascience.com/can-automated-machine-learning-outperform-handcrafted-models-feff83e0dc97?source=collection_archive---------16-----------------------
Can Auto-Keras really find better models than you? — Photo by Annie Theby on Unsplash
在真实数据集上测试 Auto-Keras 模型
自动机器学习(AutoML)可用于自动寻找和训练机器学习模型。您不再需要自己创建模型,AutoMl 算法将分析您的数据并自动选择最佳模型。
但是那些模型真的有多好呢?它们能与定制模型相比吗?或者它们更好吗?我们再也不需要挑选另一个模特了吗?让我们来了解一下!
简介:Auto-Keras
像谷歌这样的公司已经提供了 AutoML 产品,但是有了 Auto-Keras,还有一个开源的解决方案。在官方入门示例中,Auto-Keras 用于为 MNIST 数据集寻找最佳神经架构。当我尝试这个例子时,得到的模型达到了大约 98%的分数。这令人印象深刻,所以我决定使用 Auto-Keras 尝试在 Kaggle Titanic 数据集 上击败自己。
我在这次比赛中的最好成绩是大约 80%的精确度,这使我目前在所有参赛者中排名前 900。这是一个相当不错的分数,所以让我们看看 Auto-Keras 是否能超过我!
你可以在这里找到笔记本的完整代码
设置
我用谷歌 Colab 做这个项目。要在 Google Colab 中安装 Auto-Keras,只需运行:
!pip install autokeras
如果您想在本地运行它,您可以使用 pip 从命令行安装 Auto-Keras。
数据
对于这个例子,我使用了可以从 Kaggle 竞赛下载的数据集。要使用 Auto-Keras 模型中的数据,需要将其作为 numpy 数组导入。因为 Titanic 数据包含文本数据,所以我们需要先做一些预处理:
这是我为自己的泰坦尼克号解决方案所做的同样的预处理和特征工程。当然,每个项目的预处理是不同的,但是如果您想要使用 Auto-Keras,您将需要提供 numpy 数组。
预处理后,您可以将数据作为训练和测试数据进行加载:
寻找合适的模型
当你的数据集有了 x_train 、 y_train 、 x_test 和 y_test 之后,你可以使用 fit 方法找到最佳模型并训练它:
就是这样——两行代码就是您所需要的全部。其他一切都是自动发生的。
结果
训练完模型后,我用它来生成预测,并将预测上传到 Kaggle。我的分数是 0.79904。这比我的手工模型略差,但我们需要考虑到 Auto-Keras 仍然很新。TabularClassifier 目前仅支持 LGBMClassifier,这对于该数据集来说并不理想。如果这个项目将来继续下去,我们可能会有更好的结果。此外,找到模型非常快速和容易,所以我认为这是一个非常好的和有希望的结果!
利弊
虽然使用生成的模型来生成预测非常容易,但是您会丢失许多关于模型的知识。如果你不主动搜索,你就不知道结果模型的架构和参数值——毕竟它们是自动选择的,所以你永远不会真正需要它们。虽然这对初学者和没有经验的机器学习工程师来说可能是一件好事,但如果你后来试图适应或扩展你的模型,这可能会变得危险。
“黑盒”模型已经在机器学习项目中进行了大量讨论,但当使用 AutoML 时,整个过程甚至变得更像是一个黑盒——你只需扔进一些数据,然后期待最好的结果。
在你的机器学习项目中实现 AutoML 时,这些是你需要注意的一些风险。
对未来工作的意义
那么,AutoML 是否消除了对定制模型的需求?不,可能不会。
它能帮助你创造更好的模型吗?大概吧。
例如,您可以使用它快速找到并训练好的基础模型,稍后您可以自己对其进行改进。您还可以快速尝试不同的特性工程策略,以获得一种最佳效果的感觉。试一试,看看如何在自己的项目中实现。
我认为 AutoML 可以在未来对许多机器学习项目产生重大影响——我期待着这一领域的进一步发展和改进。
有偏见的人能创造出无偏的算法吗?
原文:https://towardsdatascience.com/can-biased-people-create-unbiased-algorithms-a01813e0473a?source=collection_archive---------25-----------------------
算法已经在很大程度上存在于我们之中。他们中的一些人做出重要的决定,如帮助司法系统确定累犯的可能性,支持是否延长贷款或投资哪些股票的决定,甚至诊断我们的细胞样本是否是恶性的,这决定了我们接受的治疗和提供的保险。
虽然它们的使用具有巨大的潜力来帮助我们变得更加准确和做出更好的决策,但它们也带来了一系列问题,包括隐私问题、偏见风险、错误、责任问题和缺乏透明度。
人工智能的广泛采用依赖于信任。只有当我们了解一个算法是如何做出决定的,如果我们了解它是如何工作的,我们才能认为这个算法是可信的。
因此,可解释性和透明性是可信算法的两个重要特征。
产出的公*性也是建立信任的关键。然而,算法在其生命周期的每一步都可能出现偏差:
1.算法本身的发展会有偏差,称为技术偏差。
2.训练数据集可以包含偏差。例如,如果我们向算法提供样本,其中某个特定种族群体相对于其在总人口中所占的份额而言代表过多,则该算法会根据学习到的比例调整其数学预测。
3.实际数据集可能存在固有偏差。从政的男性人数多于女性。这是一个数学上的确定性,算法不会改变,但会在其预测中重现。
4.当未知样本出现时,训练算法的反馈回路可能在其响应中有偏差,并在算法中建立偏差
5.用户对算法的配置可以反映他们的文化和经验偏见
6.最糟糕的是,这种算法几乎不可解,可能会提供完全意想不到的输出
偏见是一件复杂的事情。
数据偏倚的定义意味着可用数据不能代表研究的总体或现象。当算法的输出不是由目标人群的真实构成驱动时,它是有偏差的。然后,它产生的决策没有数学准确性的支持,被认为是不公*的。
然而,当目标人群有偏差时会发生什么?
无偏算法代表我们有偏见的世界吗?
在许多情况下,结果是有偏见的,因为现实是有偏见的。做生意的男人比女人多。从政的黑人比白人少。偏差是数学上的必然。一个算法可能是“正确的”、“可信的”,但仍会延续过去的不*等。
这种类型的偏见是人口本身固有的,消除这种偏见更多的是有意识地决定要么忠于我们有偏见的世界的现实,要么为我们希望成为的世界建立我们的算法。
如何避免算法中的偏差
有许多因素被普遍认为对限制算法中的偏差风险很重要:
透明。绝对清楚算法是如何工作的。
可交代性。能够理解一个决定是如何达成的,可以质疑思维过程和现场偏差。根据这一原则,所谓的“暗箱操作”是完全不可接受的。
培训数据可用性。训练数据量非常重要,可用于训练算法的数据越多,算法就越精确。但是数据集也必须代表我们打算研究的人群,以减少偏倚的风险。
监控算法性能。设置正确的参数并定期抽查。
人工监督。这意味着一种“人在回路中”的方法,并且如果算法没有按照预期的方式运行,就有可能忽略该算法。
每一步都要考虑到人。最终,算法会做出影响人们生活的决策。在生命周期的每个阶段考虑人的影响有助于更好地确定何时应该有人参与,在哪里选择而不是决策可能是一个好主意,以及何时完全依赖算法是安全的。
多样性。从不同的角度审查算法可以更早地识别潜在的缺失。在不同的团队中工作有助于避免算法偏差。
人类 vs 机器
我们未来的关键是尽早思考人机关系应该是什么样子。
在我们与算法的关系中设置正确的先例是很重要的。
我们是否在为算法提供权威和正当性假设,让我们受制于它们的决定?
算法从来没有好坏之分。然而,它们有可能以精确的数学方式伤害我们。
与人类相比,算法决策可以导致更受数据驱动、更客观和更公*的决定,但它也可能导致歧视和不正确的结果。
有没有可能使我们成为人类的恰恰是这样一个事实,即数学的精确性并不能决定我们所做的一切?
正如汉娜·弗莱在《Hello World》中所说,“也许将算法视为某种权威正是我们的错误所在”。
算法可能更好地用于支持人类决策,而不是决策。我们应该利用算法擅长的东西,并将其与人类更擅长的东西结合起来,而不是为算法提供不容置疑的权力和权威以及委派责任的借口。
算法并不完美,但如前所述,人类也不总是对的。然而,算法可以支持人类,并为他们提供一种工具,在某些情况下变得更公*、更准确、更有效。
鉴于我们最终要对算法的行为负责,难道我们不应该确保自己保留这一权力吗?
持有算法账户
由于知识产权的原因,许多私有和公共算法目前都是不透明或不可解释的。打着捍卫商业秘密或保护知识产权的旗号,他们在未经深入审查的情况下影响着人类生活。
作为一个社会,我们看到了依靠算法来更深入地了解人,最终了解客户,并为他们提供渴望已久的个性化产品和服务的好处。
但反过来作为一个社会,我们也有责任确保它可以避免对人类的伤害。
也许是时候考虑建立一个监管机构,在最大限度地尊重隐私和知识产权的情况下,测试算法的准确性、一致性、偏见和影响,然后根据它们可能造成的伤害或产生的不公*输出,批准或拒绝它们的使用。
预算分配与政府绩效不佳和腐败有关吗?
原文:https://towardsdatascience.com/can-budget-allocation-be-related-to-poor-government-performance-and-corruption-f9a1dc397bf0?source=collection_archive---------29-----------------------
机器学习分析
特别感谢 Michael Greencare 教授和 UPF 巴塞罗纳管理学院。
摘要
本文旨在运用主成分分析和聚类分析研究腐败感知指数(CPI)及其与五大类预算支出和五个治理指标变量的关系。目的是通过从数据集中提取最重要的结构化信息,并以图表的形式提供综合结果,来确定不同欧洲国家之间的相似性以及 2010 年和 2016 年之间的变化。它通过运行 CPI 和分类变量之间的线性回归来进一步了解哪些类别是密切相关的。此外,该研究运行了回归树分析,以确定最有意义的变量,以制作一个潜在的解释模型。
首先简要介绍清廉指数和治理关键绩效指标。第二部分,使用的数据集和方法;在第二章和第三章解释。第四章和第五章分别给出了研究结果和结论。
关键词 :清廉指数、预算支出、治理指标、法治(RL)、主成分分析、聚类、数据、变量、R-studio。
1.介绍
对腐败的研究是一个极端而微妙的问题,世界经济论坛最*的研究表明,腐败的成本大约为每年 2.6 万亿美元。这种影响影响了社会中最脆弱的阶层,影响了国家的发展,例如,委内瑞拉是世界上最富裕的国家之一,但它淹没在一个前所未有的腐败网络中,使其陷入经济和人道主义危机。
此外,腐败对国际投资产生不利影响,从而削弱经济增长和破坏法治。同样,这些做法会带来更严重的后果;浪费公共资源和金钱,破坏公众对政府的信任,降低政府运作效率,影响经济。
国际透明组织(International Transparency)的使命是“在社会所有层面和所有部门制止腐败并促进透明度、问责制和廉正”,并创建了一个指数,根据商界人士和专家对全球 180 个国家公共部门腐败程度的看法,对这些国家进行排名。等级从 cero 到 100,cero 高度腐败,最高分 100 非常干净。
此外,全球治理指标项目报告了 200 多个国家的总体和单独治理绩效指标,使用六个不同的维度,并给它们打分,从-2.5 到 2.5,分数越高,治理绩效越好。出于本研究的目的,我们选择了前五个维度:
声音与问责(VA): 反映了人们对一个国家的公民能够在多大程度上参与选择他们的政府,以及言论自由、结社自由和自由媒体的看法。
政治稳定和无暴力(PS-AV): 衡量对政治不稳定和/或政治暴力(包括恐怖主义)可能性的看法。
政府效力(GE): 反映了对公共服务质量、公务员质量及其不受政治压力影响的程度、政策制定和执行的质量以及政府对这些政策的承诺的可信度的看法。
监管质量(RQ): 反映了对政府制定和实施允许和促进私营部门发展的健全政策和法规的能力的看法。
法治(RL): 反映了人们对代理人在多大程度上信任和遵守社会规则、合同执行质量、产权、警察和法院以及犯罪和暴力的可能性的看法。
此外,负责编制和提出欧盟预算草案的欧盟委员会按不同支出范围的类别显示了欧盟国家的预算支出。我们只选择了占总支出预算 2%以上的类别,如:
智能和包容性增长(SIG)
可持续增长(SG-NR)
安全和公民身份(SC)
行政管理
2.资料组
该数据集对应于 2010 年和 2016 年的二十八(28)个西欧国家,以查看所述期间的相关变化。此外,数据集包含十五(15)个变量,包括 CPI、治理指标、预算支出占总支出的百分比,以及五(5)个人口变量,如失业率(UNPL)、通货膨胀率(INF)、人均国内生产总值(GPD)、购买力*价(PPP)和人口(POP)。下表显示了数据集的头部,仅显示了 2010 年和 2016 年这两个时期的前六个国家。BE10 表示 2010 年的国家是比利时,依此类推。
3.方法学
3.1.了解您的数据
第一步是通过引入变量的箱线图来了解数据。这是一种通过四分位数以图形方式描绘数字数据的方法,并使用触须来表示上下四分位数之外的可变性。这种图形表示的目的是检测异常值。在数据库里。第二步是在开始分析预测变量之前了解它们的分布;这很重要,因为某些分析需要某些分布。理想情况下,最好是正态分布,不要向一侧倾斜。
3.2.聚类分析
这种分析的目的是对非结构化数据集进行分组并从中提取价值,并在尝试对其进行分析之前对国家进行逻辑分组。这种分析将允许研究人员浏览一下数据,并在深入本研究的分析主题之前,根据我们的发现形成结构。关于分析本身,聚类是具有相似属性的国家和年份的集合,并基于它们的相似性以分层的方式将它们分成不同的组。为了获得集群,我们将以下代码引入 R-Studio 程序:
此外,我们分别分析每年的数据,以便对不同群体有一个清晰的认识,并比较两个时期,看是否有显著变化。为此,我们使用以下代码将数据集分为 2010 年和 2016 年的数据:
和编码两个独立的聚类分析。
3.3.数据标准化和主成分分析
在应用主成分分析之前,数据集需要标准化,因为一些变量可能有较大的方差和其他最小的方差。这在运行 PCA 之前很重要,因为这是一种方差最大化方法。数据标准化是通过取出*均值,然后用数据除以标准偏差来完成的。将所有数据标准化后,使用的方法是主成分分析(PCA)来描述多变量数据。
我们使用这种方法的主要原因之一是因为简单,我们没有缺失值,主要是因为它不需要正态性。这种检验不是假设检验,反应变量和解释变量之间没有明显的区别(阿兰 f .祖尔,埃琳娜 n .雷诺&格雷厄姆 m .史密斯,2007)。这种方法背后的思想是将一个大的变量集减少到一个小的集合,该集合仍然包含大数据集中的大部分信息。第一个主成分解释了大部分差异,每个后续成分解释了剩余的可变性。此外,我们从 PCA 结果中提取行主坐标。
3.4.线性回归,回归树分析。
关于线性回归模型,我们首先用散点图分析因变量(腐败感知指数或 CPI)和预测变量之间的关系。LR 中的基本假设是两个变量之间的关系必须是线性的和可加的。
在第一个线性模型中,我们使用 CPI 作为自变量,治理指标作为预测因子。第二个线性回归模型使用了相同的因变量,但使用了预算支出和自变量。此外,第三个线性模型也涉及预算支出和治理指标。
此外,我们做了回归树分析来表示递归划分。每个终端节点代表分区的一个单元,每个单元只是自变量的一个常数估计。这种分析的优点是可以更快地做出预测,并且很容易理解哪些变量在做出预测时更重要。回归树是由各个线性模型中的重要变量组成的,我们可以在下面的代码中看到:
最后,使用 CPI 和其他重要变量的线性模型,以西班牙为所有国家的参考水*,以 2010 年为基准年。目的是查看 2016 年是否显著高于或低于基准年,并确定各县和参照国西班牙之间的显著性。
4.结果
4.1.第一阶段结果
第一阶段的结果,了解你的数据,非常有助于识别异常值和分布。关于异常值的识别,箱线图分析显示,2016 年,安全和公民身份(SC)有一个异常值,即马耳他。许多报告表明,马耳他的公民身份是一个非常重要的部门,因为他们向世界各地的亿万富翁和罪犯出售公民身份,作为进入欧洲的免费入口。
这可能是这个国家在这一类别中成为异类的原因之一。此外,管理(ADM)也显示出极端异常值。这两个国家是比利时和卢森堡,这些国家的许多公民在其他国家工作,因为它们非常小,更接*较大的国家,也因为它们是欧盟机构的东道国。同样,购买力*价箱线图显示了两个时期的异常值,在这种情况下是匈牙利,在 2016 年达到历史最高水*。下表包含变量的箱线图。
此外,表 3 显示了变量的分布,通过图形展示了本研究中一个变量对象的密度。
在此分析中,我们可以确认上一步中提到的异常值的存在。但最重要的是,我们可以确定变量的分布。这个想法是,分布应该接*正态分布,也就是说,不偏向一边。许多变量偏向一侧,但总体而言,该分布接*正态分布,尽管不需要进行主成分分析。
4.2.第二阶段结果
关于包括这两个时期的聚类分析的结果,我们看到许多国家聚集在一起,显示出很少的变化,但是其他国家与其他国家聚集在一起。下面的树状图显示了两个时期的结果,按年份分别分析了每个国家,例如,比利时在 2010 年和 2016 年的情况如下:
大多数国家坚持其在该组中的立场;与此同时,其他国家如爱沙尼亚也经历了巨大的变化。它从 2010 年与拉脱维亚和斯洛伐克同组,成为瑞典和荷兰等国家的一部分。我们可以假设这是一个正在取得进展的整体成就,因为它们看起来更像是发达国家。另一方面,法国(FR)也在年与年之间经历着变化。在 2010 年,它更像英国和德国,但在 2016 年底,它变得更像西班牙。马耳他是变化最大的国家。2010 年,他们被定位于爱沙尼亚和塞浦路斯,但在 2016 年,他们不太可能类似于任何国家。
如果我们深入到树状图中,如果不算蓝线,我们可以看到两个主要的集群。在最左边,我们可以看到比利时、卢森堡、英国、瑞典、荷兰和丹麦等国家。众所周知,这些国家发展良好,排名靠前。
另一方面,右边是南方国家,如西班牙、意大利、葡萄牙、希腊和其他位于欧洲西部的国家。非常有趣的是,各国在六年内会发生怎样的变化,一些国家的地位提高了,另一些国家的地位下降了,但总的来说,大多数国家保持了自己的地位。
4.3.第三阶段结果
数据集中所有变量的主成分分析结果如下图所示。为了更好地解释,国家节点用虚线连接。
第一个维度解释了总方差的 43%;同时,第二维度解释了 13.5%,这是第二大跳跃。因此,我们更多地考虑第一个来解释这种差异,尽管可持续增长(SG-NR)似乎是第二维中最重要的差异贡献者,并且它与人口规模高度相关。
治理指标声音和问责(VA)、政府效率(GE)、法治(RL)、监管质量(RG)和清廉指数(CPI)高度相关。这些相关性是有意义的,因为发达国家往往在各个方面都有良好的治理指标,这使得该国在腐败方面非常干净。正如我们所看到的,一个国家的治理指数越高,他们在感知腐败方面就越干净。
此外,前面提到的变量(用红色圈出的)与明智和包容性增长(SIG)之间存在着深刻的负相关。看来,所罗门群岛政府的支出比例越大,该国就越有可能非常腐败,治理指标也越低。由此,我们可以假设,投资于这一类别,可能是政治家从公共资金中获利的一种方式,而不会如其名称所示产生任何明智的增长。这一假设有助于欧盟委员会详细研究匈牙利等国家在这一类别中的支出,这些国家在这一类别中的支出占其总预算的 50%以上。
关于失业率,似乎与 CPI 和治理指标负相关。腐败的国家在这方面比那些比较干净的国家失业率更高。我们可以看到,西班牙、意大利和希腊等发达国家失业率较高,但 CPI 得分较低。由此,我们可以假设腐败的政府会直接影响到社会的失业率。此外,通货膨胀率(INF),安全和公民身份(SC)和人口规模(POP)是解释研究方差最小的变量。
最后,我们可以从主成分分析中得到的主要结果是,从 2010 年到 2016 年有显著的变化。大多数国家的趋势是向图表的右侧移动。结果显示,各州在腐败和治理问题上正在退步,这种情况在所有国家蔓延。看起来,欧洲国家在腐败和治理指标上的得分越来越低,这可能是欧洲议会的红色警报。有趣的是,治理得分越低,国家腐败的可能性就越大。我们可以假设,业绩差不是因为缺乏专业素养,而是缺乏价值观。
4.4.第四阶段结果
这一阶段的线性回归模型与独立变量 CPI 相关,并确定哪个预测变量解释得最多,以便进行预测。我们首先确定哪些变量更有可能与自变量相关。下表显示了这些关系。
散点图和*滑线表明,治理指标随 CPI 线性增加。其他如 SC,INF 和,PPP 显示没有线性关系。这一点通过对每一个变量进行回归分析得到了证实。
包含 CPI 和治理指标变量的回归模型显示,法治显著不同于 p 值较低的 cero。此外,回归的斜率也明显不同于零。R 表明,治理指标变量解释 CPI 的 88.6%,经调整的 R 为 87.5%。
此外,对预算支出的第二次回归表明,所有变量都与 cero 显著不同,p 值小于 5%的置信水*。模型表明变量解释了 48.4%的方差。
Figure 4. Linear Regression with budget expenditure as the explanatory variables and CPI as the target variable.
此外,我们运行回归树分析。首先,使用代码中显示的变量,将两年的所有数据集放在一起:
结果是下面的回归树:
在回归树中我们可以分析出,如果 GPD 低于 3.5+04,政府有效性小于 0.93,我们预计 CPI 得分为 45.26,非常低,有 19 个国家落在这一边。另一方面,如果国内生产总值高于结果,并且话语权和问责制得分高于 1.445,我们预计 CPI 得分将为 88.89,9 个国家落在该区域。让我们记住,国家可以被计算两次,因为我们将它们作为单独的样本,2010 年和 2016 年。
5.结论
治理指标与对腐败的看法密切相关,就腐败而言,治理得分较高的发达国家比政府绩效差的国家更干净。正如我们之前提到的,政治家缺乏价值观直接影响政府的表现,而普通民众是受影响最大的群体,这可以通过失业率反映出来。
随着我们走向未来,大多数欧洲国家表现不佳,2010 年至 2016 年之间有显著变化,我们可以在 PCA 分析中看到,所有国家在 2016 年都远离了良好治理得分。
法治(RL)是与 CPI 最相关的指标。就腐败而言,一个法治强大的国家似乎比法治指数较低的国家更干净。这个结论是有道理的,因为强有力的法律会惩罚那些腐败的政客。
许多国家在 2010 年至 2016 年间经历了变化。例如,法国在第一年的研究中就处于发达国家的行列,到 2016 年就被移到了欠发达国家。像北欧这样的发达国家保持现状,这意味着它们在研究期间没有变化。
最后,Smart 和增长支出与 CPI 之间存在很强的负相关性。在这一类别中花费大量金钱的国家,如饥饿国家,似乎有较低的 CPI 分数。
6.数据源
http://info.worldbank.org/governance/wgi/index.aspx#home
http://ec.europa.eu/budget/figures/interactive/index_en.cfm
http://EC . Europa . eu/Eurostat/statistics-explained/index . PHP/losis _ statistics
http://EC . Europa . eu/Eurostat/statistics-explained/index . PHP/File:HICP _ 所有-项目,_ 年度 _ *均 _ 通货膨胀率,_ 2006–2016 (% 25) yb17 . png
http://ec.europa.eu/eurostat/tgm/table.do?tab=table&init = 1&language = en&pcode = TPS 00001&plugin = 1
https://data . OECD . org/conversion/purchasing-power-parity-PPP . htm # indicator-chart
https://data . OECD . org/conversion/exchange-rates . htm # indicator-chart
国会能帮助保持人工智能对消费者的公*性吗?
原文:https://towardsdatascience.com/can-congress-help-keep-ai-fair-for-consumers-a9f3e86ab25?source=collection_archive---------33-----------------------
6 月 26 日的国会听证会为金融服务敲响了警钟。
企业如何确保人工智能系统不会对弱势群体产生不同的影响,以及监管机构和国会应该采取什么保护措施来保护消费者?
在多大程度上应该要求公司审计这些算法以便他们不会不公*地歧视?谁应该确定这方面的标准?
我们需要确保人工智能不会制造偏向歧视的倾向。
两个新的众议院工作队监管金融科技和人工智能
这些不是学术论文或社论中的问题。这些问题是 6 月 26 日美国众议院金融服务委员会听证会的证人提出的——由民主党人和共和党人,伊利诺伊州、北卡罗来纳州和阿肯色州的代表提出。
两党都认为,如果不加以控制,人工智能可能会对金融服务的公*性构成威胁。尽管这一危险的确切程度仍有争议,但美国和海外政府都承认这一必要性,并主张有权为此目的监管金融机构。
6 月 26 日的听证会为金融服务业敲响了第一记警钟:它们需要准备好应对并遵守未来要求透明和公*的立法。
在本帖中,我们回顾了这次听证会的重大事件,并探讨了美国众议院如何开始审查人工智能在金融服务中的风险和好处。
两个新的众议院工作队监管金融科技和人工智能
今年 5 月 9 日,美国众议院金融服务委员会主席,国会女议员 Maxine Waters宣布成立两个工作组【2】:一个负责金融科技,一个负责人工智能。
一般来说,工作队开会是为了调查可能需要改变政策的具体问题。这些调查可能涉及召集专家向工作队通报情况的听证会。
这两个工作小组在权限上有所重叠,但是委员会的目标暗示了一些区别:
- fintech 任务组应更关注应用(如承销、支付、即时监管)。
- 人工智能任务组应该更长期地关注风险(例如,欺诈、工作自动化、数字识别)。
沃特斯主席明确解释了她对监管的总体兴趣:
确保鼓励负责任的创新,确保监管者和法律适应不断变化的环境,以最好地保护消费者、投资者和小企业。
被任命为人工智能工作组主席的国会议员比尔·福斯特在一份类似的声明中赞扬了人工智能的潜力,但也警告说:
至关重要的是,人工智能在金融服务中的应用有助于实现对所有美国人都公*的经济。
第一次听证会确实发现了人工智能在金融服务领域的大量应用。但它也得出结论,这些担忧情绪既不是对选民的歪曲,也不是错位的。
From left to right: Maxine Waters (D-CA), Chairwoman of the US House Committee on Financial Services; Bill Foster (D-IL), Chairman of the Task Force on AI; French Hill (R-AR), Ranking Member on the Task Force on AI
人工智能的风险
在听证会后期的一次幽默交流中,众议员西尔维娅·加西亚(德克萨斯州民主党)请一位证人,萨里大学的邦妮·布坎南博士向普通美国人讲话,用 25 个或更少的单词解释人工智能。它进行得不顺利。
布坎南博士
我认为这是一组技术和过程,可以确定一般的模式识别,关系的通用*似,并试图从嘈杂的数据或感官知觉中检测模式。众议员加西亚 我想这可能让他们更加困惑。
布坎南博士哦,对不起。
除了开玩笑,众议员加西亚说得有道理。人工智能异常复杂。不仅如此,对许多美国人来说,这可能是一种威胁。正如加西亚后来所表达的,“我认为有一种想法,所有这些机器人将接管所有的工作,每个人都将进入我们的信息。”
在他的开场白中,工作小组资深成员、众议员 French Hill (R-AR)试图先发制人,至少先解决第一个问题。他引用了世界经济论坛的一项研究,称因人工智能而失去的 7500 万份工作将被 1 . 3 亿份新工作所抵消。但美国人仍然对 AI 发展感到焦虑。
在 2018 年 6 月牛津人工智能治理中心对 2000 名美国人进行的调查中,研究人员观察到
- 压倒性的支持对机器人和/或人工智能的谨慎管理(82%的支持)
- 更信任科技公司而不是美国政府为了公众的利益来管理人工智能
- 对开发高级机器智能的混合支持(定义为“当机器能够比今天的人类更好地执行几乎所有与经济相关的任务时”)
这种公众对人工智能发展的担忧也反映在任务组和专家的担忧上。在整个听证会中,个人隐私被提到了九次,特别是在国会议员安东尼·冈萨雷斯(R-OH)关于“*衡创新与赋予消费者数据权力”的宽泛问题中,专家小组没有充分解决这个问题。
但更多的时候,证人讨论的是公* 以及人工智能模型如何能够不被注意地进行区分。最值得注意的是,布鲁金斯学会(Brookings Institution)研究员尼科尔·特纳-李(Nicol Turner-Lee)博士建议实施护栏,以防止有偏见的训练数据“复制和放大历史上对有色人种和其他弱势群体的刻板印象”。
她并不孤单。另一份 2019 年 4 月的布鲁金斯报告 [5]否认了这种对不公*的担忧,“算法使用一系列变量拒绝信贷或提高利率,这些变量从根本上受到社会中根深蒂固的历史歧视因素的驱动
因此,如果我们如此担心,为什么还要费心将人工智能的潘多拉魔盒引入金融服务呢?
人工智能的好处
根据国会议员希尔的说法,人工智能的潜在好处是“收集海量数据,检测异常,解决复杂问题。”在金融服务领域,这意味着欺诈、保险和核保的模型实际上更加公*和准确。这可以同时提高银行的盈利能力,并将服务扩展到以前服务不足的银行。
Hill 和 Foster 都引用了国家经济研究局的工作论文【6】发现在一个案例中,算法贷款模型比面对面贷款者少歧视 40%。此外,ZestFinance 的首席执行官兼专家证人道格拉斯·梅里尔博士(Dr. Douglas Merrill)声称,使用他公司的人工智能工具的客户在信用卡、汽车贷款和个人贷款方面体验到了更高的批准率,并且违约率没有增加。
此外,希尔用一个关于人工智能如何重塑行业的重要观点来框定他的声明:这一进步将“对颠覆性创新者和我们现有的金融参与者都有用”。乍一看,这似乎有悖常理。
“颠覆性创新者”更加敏捷,受传统流程的阻碍更少,在实施新技术方面具有优势。[7]但是,如果没有“现有金融机构”的巨额预算和客户基础,这些颠覆者怎么可能成功呢?陷入旧方式的现任者会采用人工智能吗?
Jesse McWaters 先生是世界经济论坛的金融创新负责人,也是最后一位专家证人,他谈到了这一明显的悖论,讨论了什么将“重新绘制我们所认为的金融部门的地图”第三方人工智能服务提供商-从传统银行到小型金融科技公司-可以“帮助较小的社区银行保持与客户的数字相关性”,并“使金融机构能够向前跨越。”
国会中的自由市场支持者认为,扶持竞争性市场,尤其是在金融服务等集中行业,是一项绝对的好处。然而,以这种方式“重绘地图”会让金融业变得更大、更复杂。国会将不得不制定政策,不仅要应对更复杂的模型,还要应对更复杂的金融体系。
这种制度给代表股东利益的公司和代表消费者利益的政府都带来了风险。
企业和政府关注风险
企业已经在采取行动,避免人工智能模型故障和系统复杂性带来的潜在损失。一份【2019 年 6 月 Gartner 报告 [8]预测,到 2023 年,75%的大型组织将雇佣人工智能行为取证专家来降低品牌和声誉风险。
然而,政府认识到,企业主导的举措,如果出于保护公司品牌和利润的动机,可能只能到此为止。对于一个保护消费者、投资者和小企业的政府来说,差距可能仍然存在。
随着政府探索如何填补这一缺口,它们正在建立支撑未来指导和监管的原则。各理事机构的主题是一致的:
- 人工智能系统需要值得信赖。
- 因此,他们需要代表人民的政府给予一些指导或管制。
- 这种指导应该鼓励公*、隐私和透明。
在美国,唐纳德·川普总统于 2019 年 2 月签署了一项行政命令 [9],“以保持美国在人工智能领域的领导地位”,指示联邦机构,除其他目标外,“通过建立人工智能开发和使用指南,培养公众对人工智能系统的信任。共和党的白宫和民主党的众议院似乎总是发生冲突,但是他们在这里是一致的。
欧盟也正在建立一个监管框架,以确保可信的人工智能。同样,在他们从 2019 年 4 月【10】开始的最新沟通中,七项要求包括:隐私、透明和公*。
六月的 20 国集团峰会[11]借鉴了类似的想法,创造了他们自己的一套原则,包括公*和透明,但也增加了可解释性。
这些理事机构正处于调查事实的阶段,在指导政策之前确立原则并了解他们所面临的情况。用福斯特主席的话来说,工作组必须理解“这项技术将如何影响决策者在未来几年必须解决的问题。”
在众议员加西亚有趣的挑战前一个小时,布坎南博士思考了几个共同关心的问题。
决策者需要关心人工智能模型的可解释性。我们应该避免黑盒建模,在黑盒建模中,人类无法确定机器学习或深度学习算法的底层过程或结果。
但通过这一陈述,她提出了一个解决方案:让这些人工智能模型变得可以解释。如果人类确实能够理解模型的输入、过程和输出,我们可以信任我们的人工智能。然后,通过人工智能在金融服务中的应用,我们可以促进所有美国人的公*。
来源
[1]美国众议院金融服务委员会。"人工智能透视:我们在哪里以及金融服务的下一个前沿."https://financial services . house . gov/calendar/event single . aspx?EventID=403824 。2019 年 7 月 18 日接入。
[2]美国众议院金融服务委员会。"沃特世宣布成立金融技术和人工智能委员会工作组."https://financial services . house . gov/news/document single . aspx?DocumentID=403738 。2019 年 7 月 18 日接入。
[3]利奥波德,直到亚历山大,Vesselina Ratcheva,和萨迪亚扎希迪。《2018 年就业报告的未来》世界经济论坛。http://www3.weforum.org/docs/WEF_Future_of_Jobs_2018.pdf
[4]张、宝宝、艾伦·达福。“人工智能:美国的态度和趋势。”英国牛津:人工智能治理中心,牛津大学人类未来研究所,2019 年。https://ssrn.com/abstract=3312874
[5]克莱因,亚伦。“人工智能时代的信用否认。”布鲁金斯学会。2019 年 4 月 11 日。https://www . Brookings . edu/research/credit-denial-in-the-age-of-ai/
[6]巴特利特、罗伯特、王茂林·莫尔斯、理查德·斯坦顿、南希·华莱士,“金融科技时代的消费贷款歧视。”美国国家经济研究局,2019 年 6 月。【https://www.nber.org/papers/w25943
[7]斯奈德,斯科特。“银行如何跟上数字颠覆者。”宾夕法尼亚州费城:宾夕法尼亚大学沃顿商学院,2017 年。https://knowledge . Wharton . upenn . edu/article/banking-and-fin tech/
[8]“Gartner 预测,到 2023 年,75%的大型组织将雇佣人工智能行为取证专家来降低品牌和声誉风险。”高德纳。2019 年 6 月 6 日。https://www . Gartner . com/en/news room/press-releases/2019-06-06-Gartner-predicts-75-of-large-organizations-will-hire
[9]美国,总统行政办公室[唐纳德·特朗普]。13859 号行政命令:关于保持美国在人工智能领域领导地位的行政命令。2019 年 2 月 11 日。https://www . white house . gov/presidential-actions/executive-order-maintaining-American-leadership-artificial-intelligence/
[10]“建立对以人为中心的人工智能的信任。”欧洲委员会。2019 年 4 月 8 日。https://EC . Europa . eu/futuri um/en/ai-alliance-consultation/guidelines # Top
[11]《二十国集团关于贸易和数字经济的部长声明》2019 年 6 月 9 日。http://trade.ec.europa.eu/doclib/press/index.cfm?id=2027
原载于 2019 年 7 月 18 日https://blog . fiddler . ai。
数据科学能从物理学中获得灵感吗?
原文:https://towardsdatascience.com/can-data-science-get-inspiration-from-physics-9ab95a3c04d6?source=collection_archive---------23-----------------------
从一个做出转变的人的角度看问题。
Night sky in Poland, summer 2019. Source: private collection.
我喜欢物理。如果我没有养成在大学校园实验室之外过职业生活的习惯,我会继续学习这门课程。然而,在我生命中的某个时刻,我感觉我会享受许多软件开发人员的生活方式。自然地,数据科学似乎是两个世界中最好的,并成为我的新方向。
在这篇文章中,我想与你分享我的一些观察,关于我认为物理学如何丰富数据科学。我们将超越简单的“保持好奇”的叙述。相反,我们将关注更微妙的东西,并研究将其与软件工程区分开来的“思维模式”。希望我们会发现熟悉物理可以给数据项目带来积极影响的领域,以及它可能不足的地方。
什么是数据科学?
从形式上来说,单词 科学 表示构建和组织知识的系统企业,这是通过观察和可测试的预测来完成的。 物理学 作为自然科学的一部分,是一门用科学方法来建立对物质的认识的学科。简而言之,它研究世界并帮助预测其行为。
那么什么是数据科学呢?
Source: https://analyticsindiamag.com/.
数据科学是一个新的领域,它试图使用科学方法来构建给定数据的洞察和预测。在这里,“数据”一词可以指一些特定的物理测量,但也可以描述意见或表示任何合成或抽象的信息。正因为如此,它的主要兴趣领域与物理学非常不同。此外,由于今天数据大多是数字记录,这使得整个学科与计算机科学和软件工程紧密相关。最后,与物理学不同,数据科学主要在商业环境中运作。
然而,与计算机领域相反,数据科学应该对数据做一些事情——最好是提取信息并将其投射到未来。还有,和纯商业相反,它强调理性。
这听起来和物理学没有太大的距离,不是吗?
模拟现实
先说相似点。这两个学科中存在的一个共同的实践是对现实的建模。物理学家通过测量来研究世界,并用数学方程来描述世界。软件开发人员使用抽象来映射问题,并通过代码来表达它们。
这些抽象本身似乎源于物理学中一个众所周知的概念,即一个孤立的系统。当我们对世界进行某种理想化假设,并将其视为一个分离的实体时,我们称一个系统为孤立的。这种方法使得问题更容易描述和测试。
对于数据科学,尽管信息的性质不同,我们也试图通过隔离或抽象来创建我们所面临的问题的某种表示。这是一个好的开始。
第一性原理思维
现在,考虑以下情况:
“光子是玻色子类的物体,电子是轻子。原子是粒子和用途的实例。bond()方法形成分子……现在,这一切都是为了执行 universe.run(),对吗?”
除了跳过一百万个抽象层之外-是的。至少,它表明了思考的方向。另外,对整个宇宙建模不就是物理学作为一门科学的终极目标吗?确实是!对吗?
差不多,但不完全是。
Source: https://reddit.com.
虽然这种想法很诱人,但这不是物理学家想要的。事实上,物理学家宁愿关心积木本身,而不是试图编译所有的基本积木。物理学家知道,一旦砖块被理解,通过组合、重复、排列和重新排列这些碎片,就获得了最终的建筑。
形成一个更高的结构当然不是一件容易的事情,但是计算机工程师是寻找砖块最佳排列的专家。这也是他们最感兴趣的领域。
两者之间的推理似乎几乎相反。当计算机专家试图爬上抽象的阶梯时,物理学家会急切地走下去用放大镜检查种子。说到数据科学,两种思维路径都需要。为了创建高效的预测模型,数据科学家必须了解需要哪些数据组件,以及应该如何安排它们。哪些功能看起来有意义?如果听起来像探索性数据分析 (EDA),物理学家一直在做。
从物理学导入洞察力
Source: https://wonderfulengineering.com.
说到有意义的特性,物理学,即使是最“实用”的,也需要相当数量的洞察力。深刻理解事物运行(或不运行)的原因不仅对构建有意义的假设至关重要,而且从长远来看也是成功的关键。
相反,软件工程的重点是交付商业解决方案。它强调“如何”而不是“为什么”,这既是优点,同时也是缺点。在处理复杂性、优化性能和保证健壮性方面,这是一个优势。当一头扎进数据中,即使是领域驱动设计也没有给我们带来太多。这只是开发产品的另一种方式。换句话说,计算机科学没有计算出数据有什么意义的方法。
想到数据科学,它可能会遇到好像扩展计算机科学加上 EDA 可能会做到这一点。不幸的是,这是一个缺点。
实验的价值
Source: https://memecenter.com.
物理学可以是理论性的,但它仍然是一门实验科学。无论是在强子对撞机上还是仅仅在 格丹肯 上,它都教导如何进行从陈述假设到分析结果的过程。在构建数据产品时,软件农场变成了进行虚拟实验的大数据军事基地。虽然没有人会因为比特(和字节)的飞散而受伤,但设计和携带这些受控的数据爆炸需要的不仅仅是建立必要的基础设施和挥舞“请勿靠*”的牌子。
仅仅依靠统计方程也不能保证成功。人们必须全面考虑正在调查的问题。虽然预测模型是最终目标,但在实现之前通常需要大量的实验。
在这里,如果数据科学向物理学寻求建议,这将有助于强化实验过程。这样的过程应该有助于产生深刻的见解,但又不影响审查。它还可能包括数据收集等附带活动——只要能确保结果可信,什么都可以做。
数据科学不是物理学
到目前为止,我们在数据科学的背景下只考虑了物理学的积极方面。那些你不会从物理学中寻找灵感的领域呢?
Source: https://me.me.
一个例子是运行一个没有明确交付约束的纯数据驱动的项目。这样一个项目很容易陷入永无休止的实验中。虽然这对团队来说很有趣,但对组织来说却很昂贵。其主要原因是数据科学的业务环境,而物理学没有停止机制。
其次,对构建模块的理性理解并不能保证解决更大的问题。软件开发人员通常更有能力提取粒度级别,并在任何开发开始之前发现实现挑战。最终,让它“合二为一”是一项工程工作,而知道砖块并不能让一个人建造房子。有时候,挖得太深可能是不合理的。
最后,至少在一些物理学家中也存在一种不健康的倾向,即积累数据只是为了“以防万一”。这不仅让开发人员非常头疼,在极端情况下,整个开发甚至可能无法启动!同样,洞察力是通过问正确的问题获得的——而不是问太多的问题。
结束语
作为一门学科,物理学比计算机科学古老得多,比软件工程成熟得无可比拟。当阿基米德跳出他的浴盆时,世界还没有听说过算法当艾萨克·牛顿阐明动力学定律时,第一台处理器早就被创造出来了。相反,软件工程只有一百年的历史,而互联网的普及被认为是最*的三十年。尽管每天都面临挑战,但如果是医学,我们可以说我们只是学会了洗手。
另一方面,技术进步的速度和它在我们生活中的无所不在是前所未有的。让我们以总数据量为例,估计今天大约为 50 兆字节。如果一个字节的信息重 1 公斤,那么全世界的数据总量已经相当于月球的 2/3(到 2020 年)。再过五年,它将超过月球两倍。我们,自愿去理解这些数据的人,不能在学习中偷懒。
物理学作为一门古老的学科,确实有时间研究出一些行之有效的方法。有时我甚至认为数据科学是虚拟的物理,尽管每次我都觉得有点奇怪。然而,如果数据科学从物理学中得到一些建议,它会立即投入到实验和分析中去。
从第一原则的角度思考对数据科学也大有裨益,前提是它不会变成“过度思考”。尽管如此,历史上发生的一些最伟大的发现背后往往是第一性原理思维。记住这一点是有益的。
最后,数据科学相关活动不能脱离组织的业务模型环境。与物理学这种自由科学不同,数据科学的主要目标是帮助发展业务。如果这一点得到保证,物理学可能会为数据科学提供非常有益的观点,并确实有助于它的成功。
还会有更多…
我计划把文章带到下一个层次,并提供简短的视频教程。
如果您想了解关于视频和未来文章的更新,订阅我的* 简讯 。你也可以通过填写表格让我知道你的期望。回头见!***
数据科学能帮你挑宝宝名字吗?
原文:https://towardsdatascience.com/can-data-science-help-you-pick-a-baby-name-b7e98a98268e?source=collection_archive---------23-----------------------
探索各种数据科学技术如何用于缩小婴儿名字的想法
Source: Christopher Doughty
为你的宝宝找到一个完美的名字可能是一个挑战。很难找到一个不仅你和你的伴侣都喜欢的名字,而且还符合你的姓氏。此外,名字的受欢迎程度也很复杂,比如,你选择的是普通的还是独特的名字。当试图涉水通过所有这些方面时,数据科学能使名字选择过程更容易吗?
为了研究这个话题,我收集了一些关于婴儿名字的数据。名和姓的数据来自国家统计局和苏格兰国家记录[1]。我的最终数据集包含 31,697 个名和 6,453 个姓。第一个名字数据是根据 2000 年至 2017 年出生的婴儿数量按年份划分的。
TLDR: 为这个项目创建的在线应用程序可以在这里找到。
发音预测
人们倾向于避免名字和姓氏押韵。节奏一致的名和姓在你大声说出来时感觉不自然,例如汉克·班克斯。影响名字发音的另一个因素是名字和姓氏以同一个音结尾,例如 Emilie Kelly。在许多情况下,一种算法不能单独使用字母来识别一个单词的结尾音;它需要知道发音。
为了根据相似的节奏给单词打分,我需要获得如何发音的训练数据。这些数据来自 CMU 发音词典[2],经过清理,该词典包含了 117,414 个独特的单词。CMU 词典包含单词及其阿帕贝特语音组成。对于字典中没有的单词,我预测了它们的发音。这可以使用 seq2seq 模型来实现,也称为编码器-解码器模型。
我们现有字典的预处理需要标记一组独特的字母表和 ARPAbet 码。这是使用标签编码器实现的,并创建了一组 81 个独特的令牌。下面是一个 LabelEncoder 将字符转换成数字的例子,使用的是我的名字:
Source: ['C', 'H', 'R', 'I', 'S', 'T', 'O', 'P', 'H', 'E', 'R']
Target: ['K', 'R', 'IH1', 'S', 'T', 'AH0', 'F', 'ER0']#### TOKENISING ####Source: [21 37 62 39 63 65 53 60 37 25 62]
Target: [48 62 41 63 65 8 35 29]
评估输入的 CMU 数据,我发现最长的源向量是 34 个元素,最长的目标向量是 32 个元素。这些最大值似乎是合理的,因此使用填充元素 ' < PAD > ' 来标准化源向量和目标向量的长度。
seq2seq 模型是使用两个 LSTM(长短期记忆)网络用 Keras 构建的。该模型训练了 35 个历元,最终准确率为 95.6%,损失为 0.147。用一些原始字典中没有的名字示例来测试最终模型产生了令人满意的结果。
LEXI L EH1 K S IY
AYLA EY1 L AH0
MYA M IY1 AH0
然后将该模型应用于名和姓数据[1]。它被用来计算 31697 个名字中的 25036 个和 6452 个姓氏中的 739 个的发音。
押韵相似性
拥有所有名字和姓氏的语音意味着我现在可以对名字之间的相似性进行评分。我通过计算每个单词之间的距离来达到这个目的。此方法描述将一个字符串转换为另一个字符串所需的最少插入、删除或替换次数。
Levenshtein 距离越大,两个字符串之间的相似性越小,例如,距离为 0 意味着两个字符串相同。下面列出了创建使两个字符串相同所需的更改矩阵的代码。
# Get the length of each string
lenx = len(str1) + 1
leny = len(str2) + 1# Create a matrix of zeros
matrx = np.zeros((lenx, leny))# Index the first row and column
matrx[:,0] = [x for x in range(lenx)]
matrx[0] = [y for y in range(leny)]# Loop through each value in the matrix
for x in range(1, lenx):
for y in range(1, leny):
# If the two string characters are the same
if str1[x-1] == str2[y-1]:
matrx[x,y] = matrx[x-1,y-1]
else:
matrx[x,y] = min(matrx[x-1, y]+1, matrx[x-1,y-1]+1, matrx[x,y-1]+1)
测试代码与单词 CONTAIN 和 TODAY 的相似性,产生以下输出矩阵。使用下面的等式可以使用操作的数量来计算相似性得分:(1-(操作/最大字符串长度) 100)。*该技术计算出 CONTAIN 与 OBTAIN 的相似度为 71%,而 TODAY 的相似度仅为 17%。
Levenshtein distance calculated between different words. The similarity between the words is higher on the left (two alterations) compared to the right (five alterations)
这在我们的数据中的使用方式略有不同。这种方法不是直接应用于姓氏并根据名字的相似性来评分,而是应用于语音来评分与姓氏具有相似发音或节奏的名字。例如,如果我们使用姓 SMITH,并搜索发音最相似和最不相似的男孩的名字,分析将生成以下输出:
# TOP SCORING SIMILARITY
SETH 75.0
KIT 62.5
SZYMON 50.0# LEAST SCORING SIMILARITY
ZACHARY 8.33
HUSSAIN 9.09
PARKER 10.0
流行趋势
在这一点上,我们有了一个比较语音相似性的工作方法,去除发音相似的成分,并对名字和姓氏进行评分。我们希望考虑数据中名字的当前趋势。我们会选择一个受欢迎的、受欢迎程度增加的、受欢迎程度减少的、稳定的或在数据中相当罕见的名字吗?
我拥有的数据让我可以根据 2000 年至 2017 年的同比变化,查看每个名字的趋势变化。下图显示了 2012 年至 2017 年间英国前 10 名男孩和女孩名字的变化。这表明有大量的运动。
Top 10 boys and girls names between the years 2012 and 2017; lines show rank changes within the top 10
为了给每个名字贴上“受欢迎程度”的标签,我对每个名字的 4 年数据进行了线性回归。将每个部分的回归系数合并,以创建一个趋势数组。看起来像这样的数组[+,+,+,+,+,+]表示名字在随时间增长,像这样的数组[-,-,-,-,-]表示名字在衰落。这允许为每个名称创建与其阵列相关的配置文件。下面是我整理的七个简介:
'CONTINUED DECLINE' : Most recently declining, +1 previous
'DECLINE STABILISING' : Most recently stable, +2 decline
'RECENT DECLINE' : Most recently declining, 0 previous
'CURRENTLY STABLE' : Most recently stable, +1 previous
'GROWTH STABILISING' : Most recently stable, +2 growth
'RECENT BOOM' : Most recently growing, 0 previous
'GROWING BOOM' : Most recently growing, +1 previous
为了将简介与名字匹配,我绘制了 2017 年前 100 名女性婴儿的名字,并根据他们的简介给他们涂上颜色(如下图)。
Top 100 ranked female names of 2017 and their historical profiles
从这个数字中一个有趣的发现是,前 100 名中的许多名字都在下降。这可以通过观察每年独特名字的数量来解释(下图),因为在 2000 年至 2012 年间,名字选择的多样性增加了。
Count of unique male and female baby names by year
一些更有趣的发现…
对数据的深入研究揭示了一些更有趣的见解。其中之一是基于名字长度的婴儿频率计数。它显示大多数名字的长度在四到八个字母之间。
Frequency plot of the length of first names
另一个是在名字中使用连字符。我们可以观察到,在过去的 17 年里,这变得越来越流行。
Number of babies with hyphenated first names by year
最终想法和应用
当将发音相似性模型与姓氏和流行度数据相结合时,输出是将数千个名字减少到数百个的非常强大的方法。这是此类工具的主要好处,它减少了因过大而无法通读的数据集,并提供了对特定名称的历史和地理背景的了解。
我已经将评分模型和趋势概要数据推送到 GitHub,供任何有兴趣测试模型和趋势数据的轻量级版本的人使用:https://penguinstrikes . GitHub . io/content/baby _ names/index . html。
Source: Christopher Doughty
总之,像这样一个问题的模型不可能,也不应该提供一个“完美”的名字。像这样的任务涉及太多个人属性,无法提供一个明确的解决方案。然而,在我看来,与一些帮助准父母挑选婴儿名字的网站和文献相比,数据驱动的方法要有用得多。
参考文献
[1]根据开放政府许可 v3.0 提供的国家统计局数据
[2]http://SVN . code . SF . net/p/cmusphinx/code/trunk/cmudict/cmudict-0.7b
深度学习能帮助我们重新发现过去吗?
原文:https://towardsdatascience.com/can-deep-learning-help-us-to-rediscover-the-past-5fa940c4e6c3?source=collection_archive---------23-----------------------
深度学习在考古学中的应用。
深度学习(D.L .)已经被证明是一种解决计算机视觉中广泛问题的杰出工具,并在几个领域中具有实际应用。然而,这种技术在考古学中,特别是在考古遗址的探测中,还没有被广泛地探索。在这篇文章中,我想告诉你 D.L .在机载数据分析中探测考古痕迹的应用。
Rune stone located at Lund University campus, the inscribed runic text describe the death of a King in Northern Europe. Image taken from: https://www.instagram.com/j.org.ls/
如今,从航空图像中探测考古结构几乎完全依赖于专家的分析。这是一项耗时的任务,需要高度专业化的知识,并且涉及进行分析的人的解释偏差。例如,在下图中,您可以看到两张航空照片。其中一个包含考古结构,而另一个没有。
Example of aerial photographs containing archaeological structures (right) and just a pile of rocks (left). ©Lantmäteriet: I2018 / 00119.
从航空数据中探测考古遗址所用的数据有不同的类型。它不仅限于电磁波谱可见范围内的航空照片。还使用了从 ASTER 卫星等专门卫星获得的多光谱航空图像,或使用激光雷达系统提供的激光测绘,激光雷达系统的优点是可以穿过植被并提供清晰的地形测绘。在最后一种情况下,它在探测植被非常密集的地区的考古遗址方面特别有用,例如发现隐藏在危地马拉丛林中的新遗址。对这些遗址的探测可以恢复为对可能属于古代景观遗产的地形异常的搜索。这种所谓的异常可能有不同的类型,被称为考古痕迹。
案例分析
隆德大学考古和古代史系提供的数据与来自瑞典南部波罗的海沿岸 5 个地区(skne 和 Blekinge 县)和位于马拉伦湖的 Birka 岛 Birka 的电磁波谱可见光和*红外区域的航空图像相对应。总共提供了 8 幅航空图像,其中包括与维京时代的坟墓和结构相对应的遗留痕迹和地形异常。这些结构有不同的形状,是最臭名昭著的船状墓葬。
所有图像的分辨率都是 20cm/像素,但是它们都具有不同的尺寸,因此执行*铺处理以具有如图像中所示的 100×100 像素的恒定尺寸的图像,重要的是要注意到,由于空间图像*铺的方式(将整个空间图像均匀地分成恒定尺寸的正方形,而不管其内容如何), 在一些情况下,考古结构似乎被分成不同的瓦片,而在其他一些情况下,瓦片中有不止一个单一的结构。
Example of one of the aerial images after the tiling. It is possible to see the shapes of the different structures marked in different colors. © Lantmäteriet: I2018 / 00119.
下表显示了案例研究数据的最终构成。
Composition of the data set.
从上表中,我们可以看到,有考古痕迹的瓷砖(不包括情况 5)仅占总数据的 5.7%。案例研究 4 被选作测试数据集,因此它被排除在所有其他操作、方法和流程之外,仅在最后用于测试不同的模型。考虑到带有考古痕迹的瓦片数量较少,因此决定最好的方法是开发一个分类器,该分类器可以区分两种不同类型的带有考古痕迹的数据图像(阳性案例)和不带有考古痕迹的图像(阴性案例)。
任务
当谈到分析具有网格状拓扑结构的图像或数据时,深度学习中最常用的模型类型是卷积神经网络(CNN)。这种类型的网络可以被看作是多层感知器的一种变体,但它的优点是比它的前身更轻,因为它基于共享权重的体系结构。在这个项目中,测试了 4 种不同的架构,其中 3 种是最先进的架构(它们是 VGG16 、 Inception V3 和 ReNet50 )以及一种基于典型 CNN 架构的拟议模型,如下图所示。
CNN proposed for the project.
通常,当可用的数据量足够大,并且它很好地代表了对于所选择的任务,信息可能出现的所有可能性的分布时,那么网络可以仅用该数据来训练,因为它预期它将从中学习所有需要的模式,以便在看不见的数据中表现良好。然而,当可用的数据不够时,可以应用一些其他技术。迁移学习是一种允许通过使用已经在类似任务中训练过的知识来使过程更有效的方法,它被用于前面提到的 3 个预训练模型。
使用深度学习时的一个常见错误是认为使用它需要大量数据,但这不是真的。在许多现实生活的应用中,标记的数据是有限的,正如这个问题的情况,所以为了解决这个问题,除了使用迁移学习之外,还使用了数据增强。航空图像类型数据的一个优点是,我们感兴趣检测的特征不依赖于方向,这为应用图像变换方法提供了很大的余地
在这个项目中,应用了两种不同的技术,第一种可以称为“典型的”图像数据增强,首先对所有图像应用 90°、180°和 270°的旋转,然后垂直翻转它们,这总共给出了 8 幅不同的图像。最后一步是随机选择这 8 个新创建的图像中的两个,并再次随机选择以下操作中的两个:改变亮度、对比度、色调、饱和度、相对亮度或添加高斯噪声;应用于两个选择的图像。通过使用这些技术,数据集以因子 10 增加,具有 2070 个具有正轨迹的图像和 14050 个没有正轨迹的图像的最终组成。然而,即使在某些情况下使用这种方法,前面所述的技术也不能推广到可能存在自然数据的各种情况,因为它没有在可用于训练的数据中描述。一种可以解决这个问题的方法是使用生成对抗网络(GANs)。
Graphical representation of a GAN network.
gan 是基于零和博弈的场景。在这个博弈中,有两个参与者,生成器和鉴别器。第一个可以被看作是一个函数,它试图从一个被称为潜在空间的表示空间映射到数据空间,在这种情况下是图像。第二个是从图像数据映射到图像来自真实分布而不是生成器分布的概率的函数。如果生成器分布能够完美地匹配真实的统计数据分布,那么鉴别器将被混淆,预测所有输入为 0.5。打个比方,生成器可以被视为伪造者,而鉴别者则是艺术专家。生成器创建假画的目的是逼真,而专家的目的是区分哪些是真的,哪些是假的。值得一提的是,生成器无法访问真实图像,它唯一的学习方式是通过与鉴别器的交互。
第二个数据扩充数据集是通过使用基于深度卷积 GAN (DCGAN)的模型创建的,以创建带有考古痕迹的图像。结果如下图所示。
Samples of the images generated using the DCGAN model (left) and real images with archaeological traces.
© Lantmäteriet: I2018 / 00119.
在左侧,您可以看到生成的图像,而在右侧,显示了一些真实图像的示例。其中一些确实与考古遗迹相似,但大多数遗迹的分辨率与原始遗迹不同。
该任务的另一个问题是数据中的不*衡,即 94%的图像对应于我们不感兴趣检测的类别,因此使用准确度作为性能测量不会揭示模型的真实性能,例如,将所有图像分类为负面的系统将获得 94%的准确度分数。为此,选择受试者工作特征(ROC)图及其曲线下面积(AUC)作为性能测量。ROC 曲线是显示分类器的真阳性(TP)和假阳性(FP)之间的权衡的图。这是通过改变阈值来绘制速率值而构建的。网络的输出给出了一个介于 0 和 1 之间的数字,该数字表示一幅图像属于包含考古结构的图像类别的概率。AUC 表明模型能够在多大程度上区分这两个类别。
Left: Example of a ROC curve obtained in the validation data set using the data set generated using “typical” data-augmentation techniques. Right: Confusion matrix of a binary classifier.
前面提到的每个模型(VGG16、Inception V3、ResNet50 和提议的模型)在使用前面提到的两种提到的数据扩充方法获得的两个不同数据集中进行训练。使用 4 重交叉验证,选择正则化技术漏失和 L2 的值。使用每个模型的最佳配置,进行最后一轮训练和测试,在这种情况下,在现有的 3 个数据集的每一个中训练模型:没有任何类型的数据增强的原始数据集,使用 DCGAN 生成图像的数据集,以及最后使用典型的数据增强操作的数据集。
结果
每个模型都在看不见的数据中进行了测试,在这种情况下,案例研究 4 分别针对该数据集的每种图像(可见光和红外航空图像)。下表显示了在不同训练数据集上训练的每个不同模型的测试数据集中获得的结果的摘要。
AUC values obtained in the test data set for each of the two types of aerial images and for the different models trained in the data set generated using “typical” data-augmentation techniques.
可以看出,Inception V3 是在可见光范围内的图像情况下表现更好的模型,而 VGG16 是在红外范围内的图像情况下表现更好的模型。
总的来说,观察到在使用“典型”数据扩充技术产生的数据集中训练的所有模型比在训练期间使用的另外两个数据集表现得更好。下图显示了 VGG16 和 Inception V3 的结果。
ROC curves and AUC obtained from the test data set for each of the two types of data after training VGG16 in different data sets (No data augmentation, augmentation using traditional techniques and augmentation using a DCGAN model).
ROC curves and AUC obtained from the test data set for each of the two types of data after training Inception V3 in different data sets (No data augmentation, augmentation using traditional techniques and augmentation using a DCGAN model).
为了改善结果,进行了一个额外的步骤,在这种情况下,使用系综。通过分别训练两个模型并*均它们的输出来构建集成。仅使用在不同数据集中训练的两个最佳模型。下表显示了真阳性和假阳性的百分比。
Percentage of true positives and false positives detection for the different combinations of
VGG and Inception V3 trained on the data augmented data set.
性能也可以在下面的图中可视化,其中显示了每个集合的 ROC 曲线,正如可以看到的,最低的具有 0.894 的 AUC,并且所有其余的具有高于 0.9 的值。最好的一种 AUC 为 0.96
ROC curve of the ensembles.
然而,这些结果并没有告诉太多,所以进行了视觉分析,以了解他们每个人的弱点。为此,需要一个视觉参照物,下图显示了彩色瓷砖对应的区域,这些区域中存在一些考古结构。
Case study 4 in visible light with the tiles with archaeological traces marked in purple.
© Lantmäteriet: I2018 / 00119.
Results obtained using Inception V3 in aerial images in the visible light range. The tiles
are colored according to the classification probability: blue > 0.5, light blue ∈ [0.3, 0.5], yellow
∈[0.1, 0.3]. © Lantmäteriet: I2018/ 00119
Results obtained using VGG16 in aerial images in the near-infrared light range. The tiles
are colored according to the classification probability: blue > 0.5, light blue ∈ [0.3, 0.5], yellow
∈[0.1, 0.3]. © Lantmäteriet: I2018/ 00119
下图描绘了最佳集合的图形输出,可以看到只有 3 个瓦片丢失,但正如我之前提到的,瓦片本身并不对应于结构,而是结构的一部分,实际上,在检测中没有任何结构丢失,只是它们的一些部分。此外,这里仍然存在的一些假阳性是由于所谓的“有争议的图像”。
Combined results of the predictions using Inception V3 in the visible light data and VGG16
in the infrared. © Lantmäteriet: I2018 / 00119.
现场检查揭示了遗漏检测和假阳性检测的性质。下图显示了其中的一些。
The figures in the left and in the middle row correspond to the false positives, the ones in the left is an area in which some rocks placed in a circle like order, and the one in the middle. The pictures in the right correspond to a false negatives, in this case only a small part was missed in the detection, in this case the one closer to the images. © Lantmäteriet: I2018 / 00119.
然而,该系统也能够检测到所有结构中的大部分,其中一些对于非考古专家(比如我自己)来说并不是微不足道的。下图描述了一些正确检测的示例。
Example of images correctly detected with its respective picture at the location. © Lantmäteriet: I2018 / 00119.
结论。
从非常少量的数据开始,使用不同的数据扩充技术、迁移学习方法和不同的 CNN 体系结构,有可能以 76 %的真阳性率对属于与训练数据来自的区域不同的区域的看不见的数据中 4 %的假阴性率进行预测。
我开始的问题是深度学习是否有助于考古结构的发现。所以答案是肯定的,这可能不是一个微不足道的任务,但确实是可能的。
这些方法的改进和研究非常重要,因为现在可用的数据比人类可能分析的数据要多。考古遗址的探测至关重要,因为它可以恢复和保护这些结构,这有助于了解这些古代文明的许多方面,以及整个人类历史,否则这些知识将永远丢失。
如果你想了解更多关于这个项目的细节,你可以在这里找到他们。
Penninggraven at Ängakåsen gravfält. The stone over 2 meters high was blown out in three parts in 1915 and probably would have been used as a building material for a bridge. The stone was eventually restored and now stands where it should stand. Image taken from: https://www.instagram.com/j.org.ls/
深度学习能比鸽子表现更好吗?
原文:https://towardsdatascience.com/can-deep-learning-perform-better-than-pigeons-d37ef1581a2f?source=collection_archive---------36-----------------------
我第二次尝试 fast.ai 的《程序员实用深度学习》第二课
我正在学习 fast.ai 的杰瑞米·霍华德和雷切尔·托马斯(Rachel Thomas)教授的精彩的“程序员实用深度学习”课程的第二课,上周,我训练了一个深度学习模型来对怀孕测试的图像进行分类,这些测试的结果不是明显阳性或阴性,而是微弱阳性或显示蒸发线。然而,模型的准确性并不是我想要的,所以我决定重新开始一个分类问题,对于这个问题,我可以很容易地获得比棘手的怀孕测试分类问题更好的图像集。然后,我试图训练一个模型来对红杉和红杉进行分类,但再次达到了非常低的准确率,大多数错误来自被分类为红杉的红杉。红杉的树干比红杉大得多,但从图像上看,很难获得尺度感,我认为这个问题很可能是模型将红杉误认为红杉的原因。
所以再一次,我需要一个新问题。我考虑将画作归类为莫奈或马奈的作品,但我发现自己区分这两者的能力不足以检查模型的准确性,所以我决定尝试毕加索或莫奈的作品。我希望能够将我的模型的准确性与另一个模型的准确性进行比较,并且不要为这个问题找到深度学习模型,但要找到一项研究,该研究训练几组鸽子以超过 90%的准确性识别毕加索和莫奈的画作!我认为击败鸽子是我的模型可以接受的第一基准。
按照第二课讲座中的说明,我在 Google Images 上搜索“毕加索的画”和“莫奈的画”,并下载了这两组图像(见我之前的帖子,我需要对笔记本中的代码进行细微的调整)。
第一次出门,我的模型就打败了鸽子!
我的训练集损失是 0.396,而我的验证集损失是 0.086,我的错误率是 0.278。很难再提高了!不过,我的蜘蛛侠感觉在响,因为我的训练集损失高于我的验证集,我想 Jeremy 在讲座中说过,这是过度拟合的迹象。我在 fast.ai 论坛上搜索并找到了这篇文章,其中杰里米说,只要错误率低,一点点过度拟合是可以接受的。咻!
现在,对于一些超参数调谐,虽然精度如此之高,我根本不确定我可以显著提高它。我运行学习率查找器并试图绘制图表,但它显示为空白。笔记本上有一个提示,如果学习率查找器图是空白的,尝试运行learn.lr_find(start_lr=1e-5, end_lr=1e-1
。
那有效!这是图表。
根据图表,我将学习率设置在 1e-6 到 1e-4 之间:
我已经大大降低了我的训练集损失和验证集损失,但是错误率基本上是相同的(这是我所期望的)。这个模型只犯了一个错误,把毕加索的画归类为莫奈的。
我运行了 ImageCleaner,但没有发现任何质量差或有噪声的图像,所以我保留了它们。因为我的损失和错误率都很低,我想我的模型已经准备好了!
接下来,我打算在 web 应用程序中将我的模型投入生产。我以前玩过 HTML 和 CSS,就像我这样的千禧一代,很久以前我确实有一个 Geocities 网站,但我从未开发过 web 应用程序。杰里米说“建立一个 web 应用程序”,就像我可能会说“做一些咖啡”,所以也许它会相对容易?
我按照 fast.ai 的指示将[部署在渲染](https://course.fast.ai/deployment_render.html for deploying on Render (https://render.com/)上,并分叉所提供的回购。我遇到了一个小障碍:指令告诉我们编辑“app”目录中的 server.py 文件,但我在 Jupyter 目录树中的任何地方都找不到。最终,我意识到“app”目录在 GitHub 上的分叉回购中,而不是在 Jupyter 中!也许这对某些人来说是显而易见的,但对我来说不是。下一个小问题是,我们需要在 server.py 文件中编辑的变量名为“export_file_url”,而不是“model_file_url”,如说明中所示。没什么大不了的。
我继续按照部署说明进行操作,但是我的 web 应用程序无法部署,并且在我的 Render 日志中出现以下错误:TypeError: __call__() missing 2 required positional arguments: 'receive' and 'send'
。我不知道这是什么意思,所以我咨询了 fast.ai 论坛,并在找到了一个解决这个问题的帖子。显然,在 forked repo 中有一个名为 requirements.txt 的文件,它需要我的模型正在运行的各种库的版本号。我找到我的 requirements.txt 文件,在笔记本中创建一个新的单元格,并在其中运行! pip list
。我找到了 requirements.txt 文件所寻找的大部分值,但是没有 starlette、aiofiles 或 aiohttp 的条目。我在线程上复制并粘贴最*帖子中给出的值,交叉手指,但这不起作用。
所以我把贴到非常友好和有用的论坛上,并在我的 requirements.txt 文件中获取一些新的值来尝试。
进步!我的 web 应用程序部署了,但它似乎默认为回购中默认的泰迪熊分类器示例。我确实更新了 server.py 文件中的 URL 链接,但是由于我的 export.pkl 小于 100 MB,所以第一次没有生成 API 密钥。不过,也许我需要一个,所以这次我按照这些指令去做。我使用新链接再次编辑 server.py 文件,并重新部署。不,还是熊。
server.py 中仍然有一个示例链接,但它似乎被注释掉了。我试试删?但是我也编辑了类别为“毕加索”和“莫奈”,而不是熊的类型,所以那些也应该改变了。嗯……如果他们做了呢?也许它看起来像熊分类器,但它实际上是我的绘画分类器?
我接受了“有益蠕虫”的建议,试着让̶w̶a̶l̶k̶i̶n̶g̶̶t̶h̶r̶o̶u̶g̶h̶̶i̶t̶运行它。
是啊!我通过分类器运行毕加索的图像,模型对它进行了正确的分类。因此,当实际运行我的分类器时,它显示得好像是熊分类器。
我发现我需要在某个地方为面向用户的文本编辑一些代码,但是不知道在哪里做。fast.ai 论坛上非常有用的 mrfabulous1 再次出现,告诉我我需要编辑的代码是“app”目录的“view”子目录中的 index.html 文件。有用!
试试我的“毕加索还是莫奈?”给自己分类器这里!
因此,现在我有了一个准确率高达 97%的图像分类模型,并部署了一个 web 应用程序来使用它。继续第三课!
查看 GitHub 上的代码!
关于此主题的其他帖子:
第一课:fast . ai 入门
第二课(尝试 1): 对验孕结果进行分类!
第三课:一万种行不通的方法
第四课:预测服务员的小费
第五课:但是泡菜去哪了?
第六课:每个人都想成为一只猫
我是加州大学东湾分校的数学讲师,也是一名有抱负的数据科学家。在 LinkedIn 上和我联系,或者在 Twitter 上打招呼。
机器学习可以模拟简单的数学函数吗?
原文:https://towardsdatascience.com/can-machine-learning-model-simple-math-functions-d336cf3e2a78?source=collection_archive---------16-----------------------
使用机器学习对一些基本数学函数建模
Photo Credits: Unsplash
如今,将机器学习应用于各种任务已经成为一种规范。这是一个事实的征兆,即机器学习似乎是 Gartner 对新兴技术的炒作周期中的一个永久固定装置。这些算法被视为自己解决问题的模型:将任何类型的数据分解为一系列特征,应用大量黑盒机器学习模型,评估每个模型,并选择效果最好的一个。
但是,机器学习真的能解决所有这些问题吗,或者它只是对少数任务有好处?在这篇文章中,我们倾向于回答一个更基本的问题,那就是,ML 甚至可以推导出日常生活中非常常见的数学关系吗?在这里,我将尝试使用一些流行的机器学习技术来拟合一些基本函数。让我们看看这些算法是否能辨别和模拟这些基本的数学关系。
我们将尝试适应的功能:
- 线性的
- 指数的
- 对数
- 力量
- 系数
- 三角法的
将使用的机器学习技术:
- XGBoost
- 线性回归
- 支持向量回归机
- 决策图表
- 随机森林
- 多层感知器(前馈神经网络)
准备数据
我保持因变量的大小为 4(没有理由选择这个特定的数字)。因此,X(自变量)和 Y(因变量)之间的关系将是:
f:我们试图拟合的函数
ε:-随机噪声(使我们的 Y 更真实一点,因为真实生活中的数据总会有一些噪声)
每种函数类型都使用一组参数。这些参数是通过使用以下方法生成随机数来选择的:
numpy.random.normal()
numpy.random.randint()
randint()用于获取幂函数的参数,以避免 Y 值变得非常小。normal()用于所有其他情况。
生成自变量(或 X):
对于对数,均值为 5 的正态分布(均值> >方差)用于避免获得任何负值。
获取因变量(或 Y):
噪声随机采样,*均值为 0。我让噪声方差等于 f(X)的方差,以确保我们的数据中的“信号和噪声”是可比较的,一个不会在另一个中丢失。
培养
注意:没有对任何模型进行超参数调整。
基本原理是对这些模型在上述功能上的性能进行粗略估计,因此,没有做太多工作来针对这些情况中的每一个优化这些模型。
结果
Results
大多数绩效结果都比*均基线好得多。随着*均 R *方达到 70.83% ,,我们可以说机器学习技术在模拟这些简单的数学函数方面确实很不错。
但是通过这个实验,我们不仅知道机器学习是否可以模拟这些功能,还知道不同的技术如何在这些不同的基础功能上执行。
有些结果令人惊讶(至少对我来说),而有些则令人放心。总的来说,这些结果重新确立了我们以前的一些信念,也产生了一些新的信念。
总之,我们可以说:
- 线性回归尽管一个简单的模型在线性相关数据上胜过其他任何模型
- 在大多数情况下,决策树< Random Forest < XGBoost, according to performance (as is evident in 5 out of 6 cases above)
- Unlike the trend these days in practice, XGBoost (turning out best in just 2 out of 6 cases) should not be a one-stop-shop for all kinds of tabular data, instead a fair comparison should be made
- As opposed to what we might presume, Linear function may not necessarily be easiest to predict. We are getting best aggregate R-squared of 92.98% for Logarithmic function
- Techniques are working (relatively) quite different on different underlying functions, therefore, technique for a task should be selected via thorough thought and experimentation
Complete code can be found on my github 。
鼓掌,评论,分享。建设性的批评和反馈总是受欢迎的!
机器学习能预测股市吗?
原文:https://towardsdatascience.com/can-machine-learning-predict-the-stock-market-8562be3b3d05?source=collection_archive---------8-----------------------
我们测试技术是否强大到足以解开金融市场的谜团
Photo by Chris Liverani on Unsplash
如果投资正确明智,美国股市可以产生惊人的回报。跟随量化投资公司如两个适马和 Citadel 的脚步,我们有兴趣知道我们是否可以使用机器学习来预测股价走势。
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
数据
我们使用 Alpha Vantage API 提取五只 ETF(QQQ、TQQQ、VTI、IWM、SPY)的每日价格数据,并从开盘价、最高价、最低价、收盘价和成交量开始。
特征生成
我们决定在 python 中手动创建函数来计算交易中常用的几个技术指标:柴金模数、波段、CCI、均线、MACD、OBV、RSI、SMA 和 STOCH。
简单移动*均线
移动*均线用于*滑数组中的数据,以帮助消除噪音和识别趋势。简单移动*均线实际上是移动*均线的最简单形式。每个输出值是前 n 个值的*均值。在简单移动*均线中,时间段内的每个值具有相同的权重,时间段之外的值不包括在*均值中。这使得它对数据中最*的变化不太敏感,而这对于过滤掉那些变化是有用的。
指数移动*均线
指数移动*均线是技术分析的主要部分,在无数的技术指标中使用。在简单移动*均线中,时间段内的每个值具有相同的权重,时间段之外的值不包括在*均值中。但是,指数移动*均线是一种累积计算,包括所有数据。过去的值对*均值的贡献越来越小,而最*的值贡献越来越大。这种方法使移动*均线对数据的变化更敏感。
移动*均收敛发散
移动*均线收敛发散(MACD)是两个指数移动*均线之间的差异。信号线是 MACD 的指数移动*均线。
MACD 发出趋势变化的信号,表明新趋势方向的开始。高值表示超买状态,低值表示超卖状态。与价格的背离表明当前趋势的结束,特别是当 MACD 处于极高或极低的值时。当 MACD 线穿过信号线时,就会产生买入信号。当 MACD 穿过信号线下方时,就会产生卖出信号。为了确认这个信号,MACD 应该在零以上买入,在零以下卖出。
MACD 的时间周期通常是 26 日和 12 日。但是,函数实际上使用的是 0.075 和 0.15 的指数常数,更接*于 25.6667 和 12.3333 周期。要创建时间周期不同于 MACD 内置时间周期的类似指标,请使用价格振荡器函数。
随机振荡器
随机振荡指标衡量收盘与最*交易区间的关系。值的范围从 0 到 100。%D 值超过 75 表示超买状态;低于 25 的值表示超卖状态。当快速的%D 穿越慢速的%D 上方时,是买入信号;当它穿过下方时,是卖出信号。原始%K 通常被认为太不稳定,不能用于交叉信号。
积累/分配线
累积/分配线类似于*衡交易量(OBV ),它根据收盘价是否高于前一收盘价来计算交易量乘以+1/-1 的总和。然而,累积/分布指示器将体积乘以接*位置值(CLV)。CLV 基于单根棒线内的发行变动,可以是+1、-1 或零。
积累/分配线是通过寻找指标相对于价格的背离方向来解释的。如果累积/分配线呈上升趋势,则表明价格可能会跟随上涨。此外,如果在价格仍在上涨(或下跌)时,积累/分配线变*,那么它标志着价格即将变*。
布林线
布林线由三条线组成。中间带是典型价格(TP)的简单移动*均线(一般为 20 个周期)。上下波段是中间波段上下的 F 标准差(一般为 2)。当价格波动较高或较低时,波段分别变宽和变窄。
布林线本身不会产生买入或卖出信号;它们是超买或超卖的指标。当价格接*上限或下限时,它表明反转可能即将发生。中间带成为支撑位或阻力位。上下波段也可以解释为价格目标。当价格从低波段反弹并穿过中波段时,高波段就成为价格目标。
论*衡体积
*衡交易量(OBV)是上涨和下跌交易量的累计总和。当收盘价高于前一收盘价时,成交量被加到累计总数中,当收盘价低于前一收盘价时,成交量被从累计总数中减去。
要解读 OBV,寻找随价格移动或先于价格移动的 OBV。如果价格在 OBV 之前变动,那么它就是一个未确认的变动。OBV 一系列上升的波峰或下降的波谷表明了一个强劲的趋势。如果 OBV 是*的,那么市场不是趋势。
特征生成后的数据
我们的假设
我们最初希望使用所有 ETF(QQQ、TQQQ、SPY、VTI、IWM)的数据建立一个单一模型,以预测交易所交易股票的长期价格趋势。如果未来 20 个交易日的回报率> 3%,我们将标签设为 1,否则设为 0。
然而,我们发现每个 ETF 之间的数据差异很大,所以我们决定需要为每个 ETF 建立单独的模型。我们最终只使用 QQQ ETF 数据集来构建我们的模型。
实验 1 (20 天回报率> 3%,如标签所示)
LSTM:测试 AUC 0.476
MLP 神经网络:测试 AUC 0.577
随机森林:测试 AUC 0.917
好得难以置信——虚幻的希望
我们使用 QQQ 数据集的最佳模型给出了. 917 的 AUC。我们以为我们找到了预测股票市场的方法。然而,事实并非如此,因为我们在模型中发现了一个重大缺陷。
按照惯例,在机器学习中,您需要打乱数据集,以便创建训练集和测试集。这样做是必要的,因为您希望测试集中的数据与训练数据来自相同的分布。但是,因为历史股票数据是依赖于时间的,这意味着后续日期的数据在这些后续日期发生之前不存在,所以对我们的数据进行洗牌将意味着训练数据集可以访问实际上是在未来设置的一些数据。例如,假设,如果我们要在 2017 年使用具有 2018 年数据的数据集来训练我们的模型,我们实际上不能使用这个训练数据集来训练我们的模型,因为在 2017 年,2018 年的数据还不存在。因此,在创建训练和测试数据集时,我们不能打乱数据。
对于我们的下一个模型,我们使用 2010 年至 2016 年的数据作为我们的训练集,使用 2017 年至 2019 年的数据作为我们的测试集。这种分布分割也很有用,因为它基本上允许我们“模拟”我们的模型如何处理未来数据。
可悲的是,使用这种模型,AUC 分数在相同的随机森林分类器下显著下降到 0.44。
随机森林:测试 AUC 0.440
重新思考标签分配
正如您在我们的样本数据集中看到的,所有这些行都有非常相似的 20-MAs、打开和关闭。如果 2019 年 1 月 4 日之后的 20 天有> 3%的涨幅,那么 2019 年 1 月 4 日左右的日子也将有> 3%的涨幅,对于任何股票来说都是如此,20 天内标签上涨的决定因素通常不是在第 20 天决定的。它是在记录在其 20 个未来交易周期中有重叠周期的日子里确定的。在这种情况下,如果我们提取 2019 年 1 月 6 日作为测试集,并对其余部分进行训练,模型肯定会为测试数据分配一个标签,因为它的所有特征都与它周围的日期相似,从而形成一个聚类。这种方法的另一个问题是,如前所述,模型允许训练集使用未来的数据进行预测。例如,训练集包括 2019 年 1 月 7 日-2019 年 1 月 11 日,以预测 2019 年 1 月 6 日,这在现实世界中是不可能的。
当我们不重组原始数据集,并且使用较晚的日期作为测试集时,这就成了一个问题。在这种情况下,训练集中的收盘价徘徊在每股 20 美元左右,但由于我们使用 2019 年作为测试集,价格明显不同,因此,模型在为它们分配正确的标签方面表现不佳,特别是考虑到我们的记录具有训练集中不存在的一系列值的特征。
我们想出的解决方案是将我们的标签改为每日股价变动。如果第二天的收盘价高于当天的收盘价,则标签为 1。在这里,一天的股票价格第二天是否上涨是相互独立的,这解决了我们形成集群和窥视未来数据的问题。
实验 2(第二天价格上涨/下跌,如标签所示)
1.TPOT
参考文献:
https://towardsdatascience . com/tpot-automated-machine-learning-in-python-4c 063 B3 e 5 de 9
https://epistasislab.github.io/tpot/using/
TPOT 是一个开源的 AutoML python 包,运行在特征工程和模型选择的许多不同组合中。TPOT 自动创建许多管线,包括不同的特征工程方法(PCA、MaxAbsScaler、MinMaxScaler 等)以及各种混合超参数的不同模型。
TPOT 的性能在很大程度上取决于管道的数量和您允许它运行的时间。流水线的总数等于种群大小+世代 x 后代大小,这可以在 TPOT 参数中确定。
由于我们只让 TPOT 跑了 150 个管道,只用了不到 15 分钟,所以性能并不理想:测试 AUC 0.509。然而,只要有足够的时间(几十个小时甚至几天),TPOT 可以成为一个非常强大和简单的工具来产生巨大的成果。
此外,TPOT 自动存储其搜索到的最佳管道,并允许用户将这些结果导出为. py 文件。如你所见,在我们的例子中,TPOT 对我们的数据进行了主成分分析,并选择高斯神经网络作为最佳分类模型。
2.XGBoost
使用 XGBClassifier,除了学习率、最大深度、n_estimators 和子样本之外,我们不需要配置太多。使用交叉验证和 AUC 评分标准,我们优化了超参数。最后,我们使用优化的超参数在 X-train 和 y-train 上制作最终模型。测试集的准确度(非 AUC)为 50.5%
使用 XGBClassifier,我们获得了 0.478 的测试集 AUC 分数
3.随机森林
使用随机森林分类器,我们使用强力网格搜索交叉验证在一个值范围内调整超参数。最佳参数显示为 max_depth = 3,min_samples_leaf = 3。
使用这个随机森林分类器,我们获得了 0.519 的测试集 AUC 分数
4.谷歌汽车
随着 AutoML 越来越受欢迎,我们决定将我们的数据集输入到 Google Cloud AutoML,看看它是否可以预测比我们更好的 AUC 分数。Google AutoML 有一个非常用户友好的界面,在你上传数据集后,它会自动给出一些统计数据。
在像我们这样的分类项目中,Google AutoML 允许用户选择不同的性能指标来优化最终的模型。
那么 Google AutoML 做的怎么样呢?仅仅一个小时的训练后,它返回了 0.529 的 AUC,这是我们过程中最高的。值得注意的是,随机森林的 AUC 达到 0.519,仅比 Google AutoML 低 0.01。
结论和见解
技术分析的弱点:在金融的世界里,技术分析(利用历史股价预测未来股价)已经被证明是徒劳的。在进一步分析中,可以考虑其他特征:
- 推文废弃:推文情感分析
- 财报电话会议记录:分析高管在财报电话会议上的语气;评估高管/分析师正在讨论的话题
- 卫星数据(油井的卫星图像有可能被用来预测石油价格)
战胜股市的唯一真正方法是获得额外的信息,例如获得未来的数据或提前知道季度收益结果,这导致不可能或非法。使用技术指标可以告诉你故事的一部分,但预测第二天的股票方向太随机,受外部因素的影响,无法创建一个强大的模型。
关键提示:只有当用于训练模型的数据和模型未来遇到的数据来自同一个分布时,机器学习项目才是有用和有效的,而当使用独立且波动的股市日收益率作为标签时,情况并非如此。
贡献者
oseph.chin@utexas.edu约瑟夫·陈,犹他·MSBA【20:j】
郝伦科林楚,UT 奥斯汀 MSITM ' 20:colinchu@utexas.edu
威尔希尔刘,UT 奥斯汀 MSITM’20:wilshire.liu@utexas.edu
smitheitches@gmail.com 布莱恩·史密斯-艾奇斯,UT Austin MSITM '20:
wenzhuo@utexas.edu文卓
AI 能像放射科医生一样看懂胸透吗?
原文:https://towardsdatascience.com/can-machine-learning-read-chest-x-rays-like-radiologists-part-1-7182cf4b87ff?source=collection_archive---------9-----------------------
使用对抗网络实现胸部 x 光器官分割的人类级性能
医疗保健需要人工智能来扩展
今天,世界上 70 亿人口中只有 10%能够获得良好的医疗服务,而世界上一半的人甚至无法获得基本的医疗服务。即使在发达国家,医疗保健系统也面临压力,成本上升,等待时间长。在短时间内培养足够的医生和护理人员来满足日益增长的需求是不切实际的,甚至是不可能的。解决方案必须涉及技术突破。
这就是机器学习(ML)和人工智能(AI)可以发挥巨大作用的地方。
在这篇文章中,我将介绍我为理解胸部 x 光图像而开发的一种简单但极其有效的深度学习方法。更多细节可以在原论文中找到。
有许多胸部 x 光片
cxr 是最常见的医学成像类型,通常比 MRI、CT 扫描、PET 扫描等其他高级成像方法高出 2-10 倍:
Among the 20+ million X-rays, over 8 millions are chest x-rays, making chest x-rays the most common standardized medical imaging. (source)
CXRs 受欢迎的一些原因包括:(1)辐射剂量较低;(2)成本较低;(3)拍摄一幅图像只需要不到一分钟的时间(相比之下,CT 扫描需要一个多小时)。因此,cxr 被广泛用作筛选工具。如果你的肺部有问题,需要更多的证据来诊断,你的医生通常会先开 CXR。CXR 提供了一个低保真度视图,为其他更复杂的成像方法铺*了道路。
从与放射科医生的交谈中,我了解到一个相当大的医院一天可以产生数百个(如果不是数千个的话)CXR,所有这些都需要由放射科医生阅读,或者最好是其他医生。并且通常最重要的是在数小时内完成读数,以检测紧急情况(例如住院患者出现的情况)。简而言之,阅读 CXR 对放射科医生和内科医生来说都是一项艰巨的任务。
CXR 阅读涉及许多步骤,可能很费时间
一名训练有素的放射科医师阅读 CXR 的*均时间约为 1-2 分钟。很难加快速度,因为阅读 CXR 是一个非常系统的过程。阅读 CXR 的一个流行的记忆方法如下: ABCDEFGHI 。a 代表气道,B 代表骨骼,C 代表心脏……你明白了。它并不短,走捷径意味着冒着忽略重要发现的风险。
通过在《CXR》中的工作,我也意识到阅读 CXR 实际上是非常困难的。我曾带患有结核病的 CXRs 去看全科医生,他在很大程度上无法判断哪个病人是结核病阳性。与我交谈过的放射科住院医师告诉我,在他们的住院医师培训项目中,他们将阅读大约 10,000 张 CXR 图像,以便精通它。这提醒了我,MLB 大多数职业棒球击球手需要挥杆 10,000 次才能击中球。人类似乎需要那么多的训练数据才能开始识别 cxr 中的模式。这种陡峭的学习曲线可能是因为 CXR 与我们一生中所接受的自然图像如此不同。这对人工智能系统来说也是一个障碍,我们将在后面重新讨论。
放射科医生严重短缺
我们说的只是 cxr。随着 CT 扫描和其他成像技术越来越受欢迎,放射科医生的工作量将大幅增加。发达国家放射科医生的长期短缺是有据可查的。例如,英国发布了关于英国临床放射学的报告,几年来的主要发现是劳动力短缺和成本上升。放射科工作人员显示出紧张和疲惫的迹象。在医疗基础设施落后的发展中国家,训练有素的放射科医生的短缺甚至更加严重。
CXR 的器官分割
理解 CXR 的一个基本任务是识别肺野和心脏区域:
Left: CXR from Japanese Society of Radiology Technology. Right: The same CXR overlaid with human labeled left lung, right lung, and heart contours.
实际上,你可以从肺部轮廓获得很多信息:异常大的心脏可能意味着心脏扩大(心脏异常增大);肋膈角变钝(下图中的 3 号)可能意味着胸腔积液。这也有助于将诊断人工智能算法仅隔离到肺野,从而最大限度地减少来自图像其他部分的虚假信号。(这是一个已知的问题,因为神经网络分类器有时会利用 CXR 中的伪像,如曝光和文本。)
Important contour landmarks around lung fields: aortic arch (1) is excluded from lung fields; costophrenic angles (3) and cardiodiaphragmatic angles (2) should be visible in healthy patients. Hila and other vascular structures (4) are part of the lung fields. The rib cage contour (5) should be clear in healthy lungs.
CXR 分割的临床应用
除了辅助计算机辅助诊断,CXR 分割直接导致心胸比率 (CTR) 的自动化计算。 CTR 简单来说就是心脏的宽度除以肺的宽度(见下图)。
CTR 是一个关键的临床指标。CTR > 0.5 表明心脏扩大,这通常是由心脏病或先前的心脏病发作引起的。测量 CTR 非常繁琐。它包括确定心脏和肺部最左侧和最右侧的点,并实际进行测量。因此,大多数放射科医生简单地跳过这一测量,只关注心脏是否过大。在中国等一些国家,CXR 读者需要进行明确的 CTR 测量,这可能会大大增加放射科医生的工作量。
很容易看出,高质量的肺部分割可以导致自动 CTR 计算:
这些是根据我们的方法(将在第 2 部分介绍)生成的肺屏蔽计算的 CTR 测量线。事实上,在我们的后续工作中,我们发现我们的 CTR 计算非常准确,均方根误差(RMSE)仅为 6%,与现有工作相当,甚至可能更好,如( Dallal 等人 2017 )^.
^The 的数据没有直接可比性,因为我们无法获得他们的数据集。
用神经网络分割 CXR 的挑战
挑战#1:隐含的医学知识
因为 CXR 是三维人体的二维投影,所以许多生理结构在图像中彼此重叠,很多时候这是对你在哪里画边界的判断。以下面这个案例为例:
Left: CXR with mild deformity. Right: Human labeled left and right lung regions. (Source)
图像显示在左肺下叶(图像的右侧)和左肺尖有一些疤痕。它们明显模糊了肺部轮廓。因此,必须通过使用医学知识推断肺部形状来绘制红色轮廓。分割模型必须获得轮廓形状的全局概念,以便解决模糊边界周围的局部模糊性,并产生类似于人类标记器的正确轮廓。
挑战#2:非自然图像
CXR 图像看起来一点也不像我们日常生活中看到的自然图像:
大多数现有的计算机视觉神经网络是为丰富多彩的自然图像设计的,并利用了这些图像中丰富的纹理。这使得很难在 CXR 上直接应用现成的解决方案。
挑战#3:少量的训练数据
由于隐私问题和管理障碍等原因,CXR 的公共医学图像比自然图像小得多。此外,与可以由任何标注器标注的自然图像不同,医学图像标注只能由医生和受过训练的专业人员来完成,从而导致高的标签获取成本。
据我所知,只有两个公开可用的 CXR 数据集具有肺野的像素级标签,一个有 247 个图像,另一个有 138 个。这至少比 ImageNet 挑战小 3000 倍,ImageNet 挑战有 120 万到 1400 万张标记图像。事实上,在 ImageNet 数据集上训练的神经网络是如此强大,以至于几乎所有现有的神经网络分割模型都是用在 ImageNet 挑战赛上学习到的参数(例如来自 ResNet 或 VGG)来初始化的。尚不清楚这样一个小数据集是否足以满足拥有数百万到数亿参数的数据饥渴神经网络。
解决方案的潜在峰值
在本系列的第 2 部分中,我们设计模型来解决上面的每个挑战。这里有一个快速预览:
与自然图像不同,cxr 是灰度的,并且是高度标准化的(挑战 2)。这一观察使我们设计了分割网络,与在具有不同颜色和形状的 ImageNet 数据集上使用的网络相比,使用更少的卷积通道。不幸的是,这种变化使得从 ImageNet 训练的模型进行迁移学习变得不切实际。然而,通过使用更少的过滤器,我们的模型具有非常少的参数(小模型容量),这最小化了易于在小训练数据上发生的过度拟合的风险(挑战#3)。
最后,也许是最具挑战性的,是如何教授分割模型人类所拥有的医学知识(挑战 1)。这里的关键见解是使用对抗性学习来指导分割模型,以生成更自然的图像,我们将在第 2 部分中展示这是非常有效的。
应对所有挑战的最终解决方案的体系结构如下所示:
这是两部分系列的第 1 部分。有关模型设计和性能的详细信息,请参见第 2 部分。
作者简介: 大卫·戴是苹果的高级机器学习工程师,探路者 AI 的顾问, Petuum 的前高级工程总监。他拥有卡内基梅隆大学的机器学习博士学位,并被评为匹兹堡 30 岁以下。@ daiwei 89|Medium| David @ way finder . ai。
参考
- 扫描:用于胸部 X 射线中器官分割的结构校正对抗网络
- 世界银行和世卫组织:世界一半人口缺乏基本卫生服务,仍有 1 亿人因医疗费用而陷入极端贫困
- 英国国家健康服务局的诊断成像数据集
- 使用 ABCDEFGHI 进行胸片评估
- 英国临床放射学劳动力普查 2018 年报告
- 用于自动估计心胸比率的无监督域适应
- 根据胸部 x 射线图像自动估计心脏边界和心胸比率
- ImageNet 训练的 CNN 偏向于纹理;增加形状偏差可以提高精确度和鲁棒性
- 有和无肺结节的胸片数字图像数据库的开发:放射科医师检测肺结节的接收器操作特征分析。
- 用于肺部疾病计算机辅助筛查的两个公共胸部 x 光数据集
AI 能像放射科医生一样看懂胸透吗?
原文:https://towardsdatascience.com/can-machine-learning-read-chest-x-rays-like-radiologists-part-2-aa77dba219f0?source=collection_archive---------14-----------------------
使用对抗网络实现胸部 x 光器官分割的人类级性能
这是两部分系列的第二部分。参见 Part 1 胸部 x 射线(CXR)分割的挑战和临床应用,以及医学成像如何,特别是 CXRs,关键需要 AI 来缩放。
回顾第 1 部分
胸部 X 射线(CXR)分割的任务是识别 CXRs 中的肺野和心脏区域:
Left: CXR from Japanese Society of Radiology Technology. Right: The same CXR overlaid with human labeled left lung, right lung, and heart contours.
在许多临床应用中,肺分割直接导致关键的临床指标心胸比率(CTR ),其导致心脏扩大的诊断。
设计解决方案
考虑到使用 CXR 的挑战(参见第 1 部分),我们首先设计基于完全卷积网络(FCN)的分段模型。然后,我们在结构校正对抗网络(SCAN)框架中增加对抗训练,这实现了人类水*的性能。
让我们深入研究模型和导致模型设计的思维过程。
全卷积网络分段(FCN)
分割模型的输入是尺寸为 H×W×C(高度、宽度、通道)的图像,其中对于 RGB 值,C = 3,或者对于灰度图像,如 CXR,C = 1。该模型然后输出每像素类概率 H×W×T,其中 T 是类的数量。在我们的情况下,对于[左肺、右肺、心脏、背景],T = 4,而当心脏分割标签不可用时(例如在一个数据集中),T=3。
我们将网络设计为全卷积网络,用 1x1 卷积取代全连接层。(更多详细信息,请参见此处的)。我们从类似 VGG 的架构开始,大约有 16 个权重层和许多特征图(或卷积通道):第一个卷积中有 64 个特征图,然后在最终层中增加到 512 个通道。所得到的模型具有很大的容量(> 1 亿个参数),它完美地过拟合训练数据,但是在测试数据上表现不佳。这清楚地表明,我们的数据集太小,无法支持像这样的大型模型。
由于 CXR 图像是具有标准化结构的灰度图像,我们减少了滤波器的数量,并且发现对于第一卷积使用 8 个特征图,而不是 VGG 的 64 个,给出了更好的结果。然而,我们很快就达到了模型的容量极限。为了增加模型容量,我们更深入。最终,我们得到了一个由 21 个重量层组成的“瘦”而深的网络:
The segmentation network architecture. The input image (400 pixels by 400 pixels) goes through convolution (in the residual blocks “Resblock”) where spacial resolution reduces but the number of feature maps (“semantic concepts”) increases. [Further tech details: the integer sequence (1, 8, 16,…) is the number of feature maps. k × k below Resblock (residual block), average pool, and deconvolution arrows indicates the receptive field sizes. The dark gray arrow denotes 5 resblocks. All convolutional layers have stride 1 × 1, while all average pooling layers have stride 2 × 2. The output is the class distribution for 4 classes (3 foreground + 1 background).]
模型中的参数总数为 271k,比基于 VGG 的分割模型小 500 倍。
细分模型的性能
Intersection over Union (IoU) is computed between the ground truth mask and the predicted segmentation
因为模型很小(很少的参数),我们可以在 209 个 CXR 例子上从头开始训练它。我们使用联合交集(IoU)度量来评估肺和心脏分割的质量。(请参见左图了解图示定义。)IoU 的范围在 0(预测掩码和地面真实值之间没有重叠)到 1(完全匹配)之间。
我们使用来自日本放射技术学会(JSRT)数据集的 cxr 和来自另一个研究的标签来准备 JSRT 数据集,包括 247 个 cxr(209 个用于训练和验证,38 个用于评估)。这个又细又高的分段网络(我们称之为全卷积网络的 FCN)表现得相当好:
请注意,人的表现并不完美,受到划出界限所需的固有主观解释的限制。人类观察者的低心脏 IoU 表明心脏边界特别难以推断(参见第 1 部分中的挑战)。这只是医学不是精确科学的许多地方之一。
FCN 的失效模式
可视化低性能样本中发生的情况并进行故障分析通常很有帮助。下面,我们将在 JSRT 数据集上训练的模型应用于 JSRT 和另一个数据集(我们称之为 Montgomery ):
Each column is a patient. The left two columns are patients from the JSRT evaluation set with models trained on JSRT development set. The right two columns are from the Montgomery dataset using a model trained on the full JSRT dataset only (no Montgomery data), which is a much more challenging scenario. Note that only JSRT dataset (left two columns) have heart annotations for evaluation of heart area IoU.
旁白:在上面的图片中,请注意,由于不同的设备、医疗操作人员和人口等因素,来自不同数据集的 cxr 看起来非常不同。因此,适应一个新的数据集领域是一项更加困难的任务。知道了这一点,我们的分割模型已经在 Montgomery 数据集上对肺分割表现得令人惊讶地好,甚至没有看到来自该人群的图像。
这些失败案例揭示了 CXR 图像在样本之间的不同对比度所带来的困难。例如,在上面的图像中,最右边患者的胸腔顶点被误认为内部肋骨,导致遮罩“渗出”到黑色背景,其强度与肺野相似。纵膈(两个肺之间的“白色物质”)和前肋骨(肺野中的纵横交错的线条)周围的血管结构也可以具有与外部边界相似的强度和纹理,从而导致中间两列中可以看到的严重错误。
结构校正对抗网络(扫描)
失败案例告诉我们,模型需要有全局结构感,以避免像前面的例子那样的严重失败。例如,任何受过基础训练的人都知道,心脏应该或多或少是椭圆形的,而肺野的顶点应该是*滑的,隔膜与胸腔的夹角应该是尖锐的。但是我们应该如何将这些知识传授给 FCN 细分模型呢?
虽然对知识进行数学编码并不容易(例如,锐角到底有多尖?),很容易判断预测的分割看起来是否自然。在机器学习的行话中,这被称为二元分类问题。这自然导致以下对抗性框架:
Overview of the proposed Structure Correcting Adversarial Network (SCAN) framework that jointly trains a segmentation network and a critic network in an adversarial setting. The segmentation network produces per-pixel class prediction. The critic takes either the ground truth label or the prediction by the segmentation network, optionally with the CXR image, and outputs the probability estimates of whether the input is the ground truth (with training target 1) or the segmentation network prediction (with training target 0).
这里的关键补充是,分割网络的预测不仅通过每像素损失(即,预测的遮罩与地面真实像素的匹配程度)来评估,还通过 critic 网络给出的“整体外观和感觉”评估(即,预测的遮罩看起来有多真实,足以欺骗 critic 网络)。敏锐的读者可能会注意到,这与生成对抗网络(GAN) 非常相似。事实上,这个框架可以被视为条件 GAN,其中我们基于输入 CXR 图像而不是原始 GAN 中的随机噪声向量来生成掩模。
在我们的工作中,我们设计了 critic 网络,以在很大程度上反映分段网络的架构。培训目标、模型的超参数、实验设置等细节可以在我们的论文中找到。
扫描性能
在我们深入研究这些数字之前,我们应该澄清一下,SCAN 中的 critic network 只在培训阶段涉及。在测试过程中,我们只使用分段网络,它与 FCN 具有相同的架构。换句话说,我们的希望是,随着 critic 网络的加入,我们可以以某种方式更好地训练相同的分割网络,使用来自 critic 网络的指导来鼓励相同的分割网络进行更“自然”的预测。考虑到这一点,我们在 JSRT 数据集上重复评估:
Evaluation on JSRT dataset. FCN is segmentation model only. Registration-based method is the prior state of the art for lung field segmentation (no heart) from (Candemir et. al., TMI (2014))
请注意,在 FCN 架构没有任何变化的情况下,SCAN 将 FCN 相对于人类水*的性能绝对提高了 1.8%,大约为 94.6%的 lung IoU!让我们回顾一下失败案例中的 4 个棘手患者:
Each column is a patient. The left two columns are patients from the JSRT evaluation set with models trained on JSRT development set. The right two columns are from the Montgomery dataset using a model trained on the full JSRT dataset only (but no Montgomery data), which is a much more challenging scenario. Note that only the two patients from JSRT dataset (left two columns) have heart annotations for evaluation of heart area IoU. These examples aren’t cherry picked results, but are in fact the more difficult cases. For example, notice that the 91.4% lung IoU by SCAN in the left most column is already much below the average 94.7% IoU in our evaluation (see the evaluation table above).
正如您所看到的,所有 4 个案例都非常令人满意地“修复”了。此外,请注意,与扫描相比,扫描在每个肺野的外下角(肋膈角)产生了更真实的锐角。拐角通常不会影响每像素性能,但在下游诊断任务中可能很重要(例如,检测肋膈角的钝化)。
在临床环境中,仅仅有良好的*均表现是不够的,但重要的是要避免令人发指的预测错误,因为它们会影响医生对人工智能的信任。通过使用对抗性学习框架,SCAN 改进了每像素指标以及预测的“整体外观和感觉”。这两者在临床环境中都很重要。
与 CXR 分割的现有技术的比较
上面的评估表表明,我们的方法在 CXR 肺野分割方面远远优于现有技术(“基于配准”的方法)。由于我们的工作是第一个针对 CXR 细分的深度学习解决方案,因此了解非深度学习解决方案可能有多复杂很有帮助:
The CXR lung segmentation pipeline used in (Candemir et. al., TMI (2014))
坎迪米尔等人的方法。艾尔。,TMI (2014) 涉及一系列 sift 特征提取、形状变换、寻找具有相似肺形状轮廓的患者作为候选 CXR 分割、图切割等以产生最终分割。每个阶段需要各种调整参数,并且由于预测是基于使具有相似肺轮廓的患者变形,因此当新患者的肺与现有训练数据足够不同时,性能会受到影响,这一点我们将在后面看到。
坎迪米尔等地的复杂管道。艾尔。,TMI (2014) 与神经网络的简单性形成鲜明对比,在神经网络中,网络自己学习特征和形状。像 SIFT 和一系列阶段的精细形状操作这样的手工制作功能的日子已经一去不复返了。
进行一些定性比较有助于理解 SCAN 如何优于 Candemir 等人。艾尔。,TMI (2014) :
The left two columns are from the JSRT evaluation set (using model trained on JSRT development set), and the right two columns are from the Montgomery set (using model trained on the full JSRT dataset).
对于左边的两列,扫描在尖锐的肋膈角周围产生更真实的轮廓。这在基于配准的模型中可能是一个挑战,其中检测和匹配肋膈点是困难的。对于右边的两列(坎迪米尔等人。艾尔。、TMI (2014))由于测试患者肺轮廓(来自 Montgomery 数据集)和 JSRT 数据集中的现有肺轮廓之间的不匹配而挣扎,导致不自然的掩模形状。
最后的想法
围绕人工智能在 CXRs 上的诊断准确性有很多炒作。然而,基于人工智能的 CXR 诊断可能会受到放射科医生的怀疑。虽然有令人兴奋的结果,但通常更容易通过较小的改进进入医院,如心胸比率(CTR)计算,可以从肺分割中获得(见第 1 部分)。我们能够很快对 CTR 引擎进行测试。自动 CTR 计算很容易解释,而且通常非常准确。我们发现,有时更重要的是通过用强大的人工智能很好地支持他们现有的工作流程来获得医生和领域专家的信任,而不是用不太成熟的人工智能解决方案来改变他们的工作流程。我希望这个案例研究可以为其他医疗保健人工智能解决方案的开发提供一个有益的例子。
作者简介: 大卫·戴是苹果的高级机器学习工程师,探路者 AI 的顾问, Petuum 的前高级工程总监。他拥有卡内基梅隆大学的机器学习博士学位,并被评为匹兹堡 30 岁以下。@ daiwei 89|Medium| David @ way finder . ai。
参考
- 扫描:用于胸部 X 射线中器官分割的结构校正对抗网络
- 用于语义分割的全卷积网络
- 有无肺结节的胸片数字图像数据库的开发:放射科医师检测肺结节的接收器操作特征分析。
- 用于大规模图像识别的极深度卷积网络
- 使用监督方法分割胸片中的解剖结构:一项公共数据库的比较研究。
- 用于肺部疾病计算机辅助筛查的两个公共胸部 x 光数据集
- 医生是主观的不是客观的
- 使用非刚性配准的解剖图谱在胸片中进行肺部分割
- 生成对抗网络
- 快速思考 ChestXray14、绩效声明和临床任务
机器会思考吗?
原文:https://towardsdatascience.com/can-machines-think-307e16e3fd2c?source=collection_archive---------17-----------------------
图灵测试及其工作原理的 2 分钟总结
Created by Katerina Limpitsouni
我们如何确定机器可以思考?在计算机械与智能中,20 世纪计算机科学家艾伦·图灵认为,模仿游戏这种思维实验足以决定一台机器的思维能力。
模仿游戏由三个玩家进行:一个男人(A),一个女人(B)和一个审讯者(C)。A 和 B 与 C 在不同的房间,C 的目标是通过提问和通过打字笔记获得答案来确定 A 和 B 的性别。a 的目标是确保 C 不成功,而 B 的目标则相反。
这个游戏是综合性的,因为问各种各样的问题可以测试思维形式,如解决问题和创造性思维。由于玩家之间没有身体上的互动,他们的思维能力是唯一的变量。所以,如果 A 是机器,A 是人的时候,C 输的概率不变,我们就可以得出结论,机器是会思考的。人和机器的思维过程可能是不同的。因此,他们自然很难互相模仿。由于我们在游戏中用机器代替了人,机器执行了一项艰巨的任务。因此,机会对机器不利,如果游戏断定机器可以思考,我们可以相当肯定。
但是,哪些机器可以使用呢?数字计算机(DC),一种被设计用来执行任何传统上由人类执行的操作的机器,是图灵的规范。在结构和功能上,人类的大脑和 DC 是相似的,这确保了即使在用计算机代替人之后,游戏也是公*的。即使 DCs 存在数学限制,模仿游戏也是有效的“讨论基础”(第 11 页),因为这些限制只会增加对抗机器的几率。
游戏也不受超感知觉的影响,即通过非常规感官感知的能力,因为我们可以有“防心灵感应”的房间(第 17 页)。Viva-voce,一个没有 B 的游戏版本,用于测试学术界的理解能力。所以,在机器能够模仿人的思维的情况下,我们不能论证它不能思考。
总之,模仿游戏是确定计算机思维能力的有效而充分的方法。虽然这可能只是一个思想实验,但随着工程技术的进步,模仿游戏也可能在未来成为现实。
机器能用图灵测试思考吗?
原文:https://towardsdatascience.com/can-machines-think-using-the-turing-test-2dce3665b552?source=collection_archive---------21-----------------------
“The Imitation Game”
我一直以来最喜欢的电影之一是《模仿游戏》。当我第一百次看它时,我不禁想到了英格玛机的重要性,它是电影中的一个重要符号,负责加扰文本和解密原始信息。简要概述电影:一个真实的故事,情节围绕着主角艾伦·图灵(由本尼迪克特·康伯巴奇饰演),以及他在成为编码员和帮助战争方面的成就。
A.M .图灵的观点
他研究的目标是寻找戴维·希尔伯特提出的“决策问题”的答案,“有没有一种算法,它以形式逻辑写成的语句作为输入,并产生总是准确的“是”或“否”的答案?
Turing Machine: Theoretical computing device
组件
- 读/写磁头:读、写和修改磁带上符号的装置。
- 状态变量:保存一条关于机器当前状态的信息。
- 规则集:描述机器在给定状态和磁头正在读取的当前符号的情况下做什么。
结果:表明如果给定足够的时间和内存,这个简单的假设机器可以执行任何计算。
图灵测试
艾伦·图灵认为这个测试来自于术语“机器”和“思考”的定义以及一个问题,“机器能思考吗?”以及“计算机能像人一样说话吗?”这是两个主要的问题,帮助图灵把它们放在正确的角度,并导致了如下发现:图灵测试,人工智能和一项研究,“模仿游戏”。
《模仿游戏》
描述:三个人一起玩,一个男人(A),一个女人(B),一个审问者(C),男女不限。审讯者和另外两个人呆在不同的房间里。对于审讯者来说,游戏的目的是确定另外两个人中哪个是男人,哪个是女人。他通过标签 X 和 Y 认识他们,在游戏结束时,他说“X 是 A,Y 是 B”或者“X 是 B,Y 是 A”。
提出问题: “当一台机器在这个游戏中扮演人 A 的角色会发生什么?”
假设:结果会一样吗?从这个意义上来说,当游戏这样玩的时候,审讯者会像在一个男人和一个女人之间玩的时候一样经常错误地决定吗?计算机被认为是智能的,它的对话很难与人类的区别开来。
图灵预言,到 2000 年,拥有 100 兆或更高内存的机器将很容易通过这项测试。虽然现代机器已经超过了这个内存量,但在量子计算的帮助下,他们正在努力寻找创造性的有效解决方案,以找到虚假的机器人和数据。
伊莱扎
是第一个声称成功通过图灵测试的算法/程序。它通过模仿心理学家来误导人类,目的是让病人说更多的话,并用更多的问题来回答问题!什么?!?!?!?!?!?
ELIZA was made in the MIT Artificial Intelligence Laboratory by Joseph Weizenbaum
它愚弄人的成功证明了这个测试的一个弱点。虽然个体生成的机器人听起来令人难以置信地像人,但它缺乏一致的个性,并且没有能力在不使用数据的情况下产生新的想法,这是一个明显的迹象。归根结底,创造计算机生成的对话需要的不仅仅是内存、数据和处理能力。相反,我们希望有一天能达到图灵的目标,毕竟我们必须克服机器意识的障碍。
“为了达到真正的智能,图灵测试通常被视为人工智能必须通过的重要门槛。”
我发现这是一个技术的证明,虽然缓慢,但肯定会朝着图灵测试的目标前进,即构建执行核心脑力任务(如推理、决策、解决问题等)的计算机器。人工智能等技术依赖于这一概念,并进一步理解过去、现在和未来的技术伦理。
神经网络能创造新知识吗?解除神经网络的装箱
原文:https://towardsdatascience.com/can-neural-networks-create-new-knowledge-unboxing-a-neural-net-acee47d4ea03?source=collection_archive---------23-----------------------
Original photo by Nina Ž. on Unsplash
令人惊讶的是,在不知道执行这些工作的显式算法的情况下,神经网络(nn)可以被设计和训练成特定的任务。例如,众所周知的识别手写数字的教程很容易实现,但底层逻辑最终隐藏在神经网络中,仅由它的层结构、权重和激活函数隐式给出。
在这篇文章中,我们通过使神经网络的规则透明来揭示其黑箱知识。为此,我们检查了布尔异或函数的神经网络。首先,我们使用已知的关于 XOR 的性质构建一个 NN 自底向上,即我们合并显式已知的代数关系。在第二步中,我们使用张量流 Keras 从零开始训练一个 NN 到 XOR。
最后,我们比较两种方法。我们将 Keras 神经网络分解为布尔分量,并发现其逻辑设置不同于第一步中构建的神经网络。经过训练的 NN 已经发现了使用不同布尔函数的 XOR 的替代表示。
我们不认为这种替代的异或公式在数学界是未知的,但至少对我们来说是新的。这可能表明神经网络可以创造新知识。但是要提取它,我们必须能够将神经网络的设置和参数转换成显式规则。
异或神经网络的自底向上构造
XOR 是由映射定义的布尔函数
XOR (0,0) = XOR (1,1) = 0
XOR (1,0) = XOR (0,1) = 1
为了构建 XOR 的神经网络,我们记住或搜索身份
XOR (x,y) = AND ( NAND (x,y),OR (x,y))
这是有帮助的,因为运算符 AND、NAND(不是 AND)和 OR 是众所周知的,并且都可以由具有 2 个输入和 1 个输出节点、偏置和 sigmoid 激活函数的简单 nn 来表示。
Neural Networks for Boolean Operators
这样,我们就可以把与非、与和或的神经网络连接起来,组成异或神经网络。所以 XOR 变成了一个 3 层 NN。
Neural Network for XOR
让我们只输入可能的输入配置并检查输出(为此我使用了 Excel 表格)。我们分别为(0,0)和(1,1)得到 0.0072,为(0,1)和(1,0)得到 0.9924。它工作了。
我们可以通过使用 XOR 的以下表示来构建其他 nn:
XOR (x,y) = OR ( AND ( NOT(x),y),AND ( x,NOT(y))。
XOR (x,y) = NAND ( NAND ( x,NAND ( x,y))、NAND ( y,NAND ( x,y)))
然而,这些身份导致了更复杂的网络。
此外,不可能构建 2 层 NN,因为 XOR 不是线性可分的(并且激活函数是严格单调的)。
但是,也许有其他选择来建立一个异或神经网络?让我们在下一节中通过训练一个神经网络来尝试找到一个替代的解决方案。
用张量流构造异或神经网络
对于 NNs 来说,Keras 确实是一个强大且易于使用的库。如上所述,我们构建了一个 3 层 2–2–1 模型,将我们的结果与之前构建的神经网络进行比较。
我们使用学习率为 1 的梯度下降优化器和均方损失函数进行误差反向传播,这是 NNs 的标准方法。
以下是 Python 代码片段:
XOR 的好处是,我们可以训练整个参数空间,因为只有四种可能的配置可以教授。然而,我们需要一些历元来将模型驱动到零损耗和 100%精度,即对于(0,1)和(1,0)输出趋向于 1,对于(0,0)和(1,1)输出分别趋向于 0。
Loss vs. epochs for XOR NN
Accuracy vs. epochs for XOR NN
但是,培训课程也可能会停滞不前,无法收敛。那么准确度停止在 75%或甚至 50%,即一个或两个二元元组的映射是不正确的。在这种情况下,只要重新建立神经网络,直到你获得一个适当的解决方案。
分析和结论
现在让我们验证 Keras NN 是否具有与构造的相似的结构。通过 get_weights(参见代码片段的结尾),我们获得权重和偏差值。
Output Python script
我们使用这些参数来重建神经网络(我再次使用 Excel)。它由三个运算符组成。
Neural Network for XOR trained by Keras
通过输入所有可能的配置,我们可以识别与运算符 H1、H2 和 o 相关的布尔函数
Boolean Functions in XOR NN by Keras
这就有意思了!我们本来期望 Keras NN 显示与构造的逻辑相同的逻辑,但是,它创建了一个替代解决方案。它没有使用运算符 Nand、OR 和 AND,而是使用 OR、AND 和(相对不为人知的)INH。即神经网络已经找到了公式
XOR (x,y) = INH ( OR (x,y),AND (x,y))
这表明神经网络可以获得以前没有的知识!当然,“新知识”是相对的,取决于专业知识的水*,也就是说,如果有人知道 XOR 的所有表示,Keras NN 不会提供额外的价值。
此外,对于更复杂的神经网络,将权重转化为显式算法或公式并不容易。但也许这种专业知识将是未来人工智能专家必须具备的能力。
最后请注意,NNs 不是我的日常业务。特别是,我不知道我的发现是新东西还是旧帽子。所以我期待你的反馈。感谢您事先提出的意见、问题、建议或更正——我们都欢迎!
我们能比卷积神经网络做得更好吗?
原文:https://towardsdatascience.com/can-we-do-better-than-convolutional-neural-networks-46ed90fed807?source=collection_archive---------12-----------------------
PyTorch 实现了 BMVC 2019 的“利用分层多图网络进行图像分类”
The number of pixels in the top row is 11, 7 and 1000 times larger (from left to right) than the number of “superpixels” in the bottom row. Can we use the superpixels rather than raw pixels as input and improve on convolutional neural networks?
大约两周前在英国加的夫结束的英国机器视觉大会(BMVC)是计算机视觉模式识别领域的顶级会议之一,竞争接受率为 28%。与其他人相比,这是一个小事件,所以你有足够的时间在海报周围走动,并与主持人一对一交谈,我觉得这真的很好。
我在 肖林 、 默罕默德·阿梅尔 ( 主页*和我的博士导师 格拉汉姆·泰勒的指导下,展示了一张关于 图像分级多图网络 的海报*
在论文中,我们基本上试图回答“我们能比卷积神经网络做得更好吗?”。这里我讨论这个问题,用结果来支持我的论点。我还使用 PyTorch 向您展示了来自 PASCAL VOC 2012 的单个图像的整个流水线的前向传递。
这篇文章的完整代码在 Github 上的我的笔记本里。在整个 PASCAL 数据集上进行训练和验证应该很容易。
那么,我们为什么要做得比康文网更好呢?他们不是在很多任务上都超过了人类吗?
例如,你可以说图像分类是一个已解决的任务。嗯,就 ImageNet 而言,是的。尽管 ImageNet 做出了巨大贡献,但这是一项奇怪的任务。为什么你要区别数百种狗的品种?因此,结果是我们有成功的模型,但是不能区分轻微旋转的狗和猫。幸运的是,我们现在有 ImageNet-C 和其他类似的基准显示我们离解决这个问题还很远。
Pipeline: We solve the classical task of image classification.
在相关任务中出现的另一个公开问题,如对象检测,是对非常大的图像(例如,4000×3000)进行训练,这由例如Katharopoulos&Fleuret(ICML,2019 )和 Ramapuram 等人(BMVC,2019 )解决。多亏了后者,我现在知道如果海报的背景是黑色的,那么它很可能来自苹果。我也应该留点颜色!
所以,也许我们需要一个不同于卷积神经网络的东西?与其不断修补它的错误,也许我们应该从一开始就使用一个具有更好属性的模型?
我们认为这样的模型可以是* 一个图形神经网络(GNN)——一个可以从图形结构数据中学习的神经网络。gnn 有一些吸引人的特性。例如,与 ConvNets 相比,gnn 本质上是旋转和*移不变的,因为在图中根本没有旋转或*移的概念,即没有左和右,只有某种意义上的“邻居”( Khasanova & Frossard,ICML,2017 )。因此,让一个 ConvNet 更好地推广到不同的旋转的问题,这个人们多年来一直试图解决的问题,被 GNNs 自动解决了!*
关于从大图像中学习,如何从图像中提取超像素并将低得多的维度输入馈送到 GNN,而不是将下采样(例如 224×224)图像馈送到 ConvNet?与双线性插值相比,超像素似乎是一种更好的图像下采样方法,因为它们通常通过保持对象之间的边界来保留大量语义。通过 ConvNet,我们无法直接从这种输入中学习,然而,有一些不错的作品提出利用它们( Kwak 等人,AAAI,2017 )。
所以,GNN 听起来很棒!让我们看看它在实践中的表现。
哦不!我们基于( Kipf & Welling,ICLR,2017 )的基线 GNN 在 PASCAL 上仅实现了 19.2%(*均精度或 mAP),相比之下,具有相同层数和每层过滤器的 ConvNet 达到了 32.7%。
我们提出了几项改进,最终击败了 ConvNet!
1.分层图
在 ConvNets 中,图像的层次结构是通过池层隐式建模的。在 GNNs 中,至少有两种方法可以实现这一点。首先,您可以使用类似于 ConvNets 的池,但是对于图形,定义一个快速且良好的池方法确实具有挑战性。相反,我们可以在多个尺度上计算超像素,并通过它们与更大的父超像素的对应关系来汇集超像素。然而,由于某些原因,这种池化在我们的例子中并没有很好地工作(我仍然认为它应该工作得很好)。因此,取而代之的是,我们在输入级别建立一个层次模型。特别是,我们将所有尺度的超像素组合成一个集合,并基于语义分割中常用的交集并集(IoU)来计算层次关系。
Three scales of 1000, 300 and 7 superpixels computed by SLIC. Note that the SLIC algorithm that we use often returns fewer superpixels (shown on top of each image) than we request. In the middle image I show spatial connections in yellow, while in the right image — hierarchical ones that allow to connect remote nodes.
基于这个原则,我在下面的代码中构建了层次图。我还构建了空间图的多尺度版本,但它只编码空间关系,而 IoU 应该更好地编码层次关系。例如,使用 IoU,我们可以在远程子节点之间创建快捷方式,即连接两个小的超像素(例如车轮),它们在空间上相距很远,但属于同一个父节点(例如汽车),如上图所示。
事实上,层次图将 mAP 提升至 31.7%,仅比 ConvNet 低 1%,而可训练参数却少了 4 倍!如果我们只使用空间多尺度图,结果会更糟,正如本文所探讨的。
太好了!我们还能做些什么来进一步改善结果?
2.可学习的关系
到目前为止,如果我们可视化我们的过滤器,它们将看起来非常原始(如高斯)。更多细节请看我的 GNNs 教程。我们想学习一些类似于 ConvNets 的边缘检测器,因为它们工作得非常好。但事实证明,用 GNNs 来学习它们是非常具有挑战性的。为此,我们基本上需要根据坐标之间的差异生成超像素之间的边缘。这样做,我们将赋予我们的 GNN 理解坐标系的能力(旋转,*移)。我们将使用 PyTorch 中定义的 2 层神经网络,如下所示:
*pred_edge = nn.Sequential(nn.Linear(2, 32),
nn.ReLU(True),
nn.Linear(32, L))*
其中 L 是预测边的数量或过滤器的数量,例如下面可视化中的 4。
我们将滤波器限制为仅基于坐标之间的绝对差|(*x₁,y₁*) - (*x₂,y₂*)|
而不是原始值来学习边缘,使得滤波器变得对称。这限制了滤波器的容量,但它仍然比我们的基线 GCN 使用的简单高斯滤波器好得多。
在我的 Jupyter 笔记本中,我创建了一个类LearnableGraph
,它实现了在给定节点坐标(或任何其他特征)和空间图的情况下预测边的逻辑。后者用于在每个节点周围定义一个小的局部邻域,以避免预测所有可能节点对的边,因为它很昂贵,并且连接非常远的超像素没有多大意义。
下面,我将训练过的pred_edge
函数形象化。为此,我假设我们应用卷积的索引为 1 的当前节点位于坐标系的中心,*(x₁,y₁)=0*
。然后我简单地采样其他节点的坐标,*(x₂,y₂)*
,并把它们馈送给pred_edge
。颜色显示边的强度取决于与中心节点的距离。
Visualization of predicted edges which can be interpreted as filters, where each intensity value is an edge between two nodes at a distance specified in axes.
学习后的图也非常强大,但计算成本较大,如果我们生成非常稀疏的图,这可以忽略不计。32.3%的结果仅比 ConvNet 低 0.4%,如果我们生成更多的滤波器,这个结果很容易提高!
3.多尺度 GNN
我们现在有三个图:空间图、层次图和学习图。具有空间或分层图形的单个图形卷积层允许仅在“第一邻居”内传播特征。在我们的例子中,邻居是软的,因为我们使用高斯来定义空间图,并使用 IoU 来定义层次图。 Defferrard 等人(NIPS,2016 )提出了一种多尺度(多跳)图卷积,它在一个 K 跳邻域内聚合特征,并*似谱图卷积。参见我的另一篇文章对这种方法的详细解释。对于我们的空间图,它本质上对应于使用不同宽度的多个高斯图。对于层次图,这样我们可以在远程子节点之间创建 K -hop 快捷方式。对于已学习的图形,该方法将创建以上可视化的已学习过滤器的多个尺度。
使用在我的GraphLayerMultiscale
类中实现的多尺度图形卷积被证明是极其重要的,它使我们能够超过基准 conv net 0.3%!
4.以低成本改进关系类型的融合
到目前为止,为了从我们的三个图中学习,我们使用了标准的连接方法。然而,这种方法有几个问题。首先,这种融合算子的可训练参数的数量与输入和输出特征维数、标度( K) 和关系类型的数量成线性关系,因此如果我们一次增加两个或更多这些参数,它确实可以快速增长。第二个,我们试图融合的关系类型可以具有非常不同的性质,并且占据流形的非常不同的子空间。为了同时解决这两个问题,我们提出了类似于( Knyazev 等人,NeurIPS-W,2018 )的可学习投影。通过这种方式,我们消除了线性依赖性,与串联相比,参数数量减少了 2-3 倍。此外,可学习的投影转换多关系特征,使得它们应该占据流形的邻*子空间,便于信息从一个关系传播到另一个关系。**
One of the proposed relation type fusion methods, which performs very well on PASCAL and allows us to beat the ConvNet by a quite large margin.
通过使用提出的融合方法,在下面的GraphLayerFusion
类中实现,我们获得了 34.5%的性能,比 ConvNet 高出 1.8%,同时参数减少了 2 倍!对于最初除了超像素中编码的信息之外,对图像的空间结构一无所知的模型来说,这令人印象深刻。探索其他融合方法会很有趣,比如这个,以获得更好的结果。
结论
事实证明,通过多关系图网络和一些技巧,我们可以比卷积神经网络做得更好!
不幸的是,在我们改进 GNN 的过程中,我们慢慢地失去了它的不变性。例如,旋转图像后,超像素的形状可能会改变,我们用于节点特征的超像素坐标也使模型不太鲁棒。
然而,我们的工作是朝着更好的图像推理模型迈出的一小步,我们表明 GNNs 可以铺*一个有希望的方向。
具体实施详见 Github 上的我的笔记本。
我也强烈推荐马蒂亚斯·菲的硕士论文代码一个非常相关的题目。
在 Github 、 LinkedIn 和 Twitter 上找到我。我的主页。
我们能使用神经网络生成自动板球解说吗?
原文:https://towardsdatascience.com/can-we-generate-automatic-cricket-commentary-using-neural-networks-dbed3aeeef07?source=collection_archive---------19-----------------------
和其他事物一样,板球世界在最*几年也经历了很多技术变革。板球运动的方式以及全世界对它的看法都因此发生了变化。在这篇文章中,我们将讨论神经网络是否能够通过观看板球比赛来产生评论。
在文献中已经有一些工作(可以在这里找到、这里和这里)但是他们没有使用神经网络。作为端到端深度学习的信徒,我认为神经网络将在不久的将来完成这项任务。这是一个很难解决的问题,因为除了视觉特征提取之外,它还涉及非常复杂的时间动态和长期依赖性的处理。这是因为评论通常与当前游戏的发展、它在更广阔的视角中的重要性(友谊赛与锦标赛)以及所涉及的球队和球员的历史高度相关。对正在发生的事情进行脱离上下文的解释似乎是一个更容易解决的问题,我可以想到一种架构来对此进行建模。
借鉴最*出现的时空神经网络的思想,我认为合理的架构应该包括从静态帧中提取视觉特征的卷积神经网络,对这些特征的复杂非线性时间动态进行建模的递归神经网络,以及在它们之上用于端到端(视频到评论)学习的解码器编码器架构。用板球镜头作为输入,用评论作为监督信号,为训练这个网络建立相当数量的数据似乎是可以管理的。我在这里为感兴趣的人发现了一个非常有前途的项目想法!
板球镜头分类似乎是这个自动评论生成系统的重要组成部分。最*一项非常有趣的工作关注这个问题,并使用基于 CNN 和 LSTM 的架构将视频剪辑分类成相关镜头,它显示了有希望的结果。玩家定位和姿态估计对于准确的镜头分类非常重要。在下面的章节中,我们将对人体姿态估计在从静态图像中识别板球击球中的功效进行初步探索。
我从谷歌图片收集了一个小数据集,总共约有 120 张图片,用于“剪切镜头”、“扫描”和“驾驶”。这个数据集非常小,如果你计划用这个想法设计一个有意义的项目,你可能需要收集一个更大的数据集。我使用开放姿态进行姿态估计,它提供了一个二维实时多人关键点检测。我使用了最轻最快的型号' mobilenet_thin ',为了简单和快速执行,你可以尝试不同的型号,以实现你选择的速度和精度之间的*衡。打开姿势给出了玩家 18 个关键点的 x 和 y 位置(在 2d 图像内)。然后,我试图在这个 18 维特征空间的顶部建立一个随机森林分类器,将每个实例分类为三个镜头之一。通过 70/30 的训练测试,我在测试集上获得了大约 0.8 的 F1 分数。考虑到我所使用的数据集的稀缺,这已经很不错了。测试集上的一些预测如下所示。
github 上有代码。
[## muaz-urwa/Cricket-Shot-使用计算机视觉分类
通过在 GitHub 上创建一个帐户,为 muaz-urwa/Cricket-Shot-class ification-using-Computer-Vision 开发做出贡献。
github.com](https://github.com/muaz-urwa/Cricket-Shot-Classification-using-Computer-Vision)
可以提高准确性的事情:
- 更大的数据集(无需动脑)
- 使用更大更精确的姿态估计模型(参考他们的 github)。
- 使用来自相同摄像机角度的图像,或者使用所有可用摄像机角度构建的多视图特征空间。
- 使用数据增强。水*翻转将有助于推广右手和左手击球手。如果你计划使用固定视角,不要使用大角度旋转。抖动和随机裁剪只有在使用数据集微调姿态估计时才有帮助。
玩得开心!
我们能预测未来的电力市场吗?
原文:https://towardsdatascience.com/can-we-predict-the-day-ahead-electricity-market-f532137fd5be?source=collection_archive---------17-----------------------
Photo by Severin D. on Unsplash
用 ARIMA 预测法预测英国电力市场
ordpool 为英国、北欧和波罗的海国家运营前一天电力交易*台。前一天的市场通过建立供需*衡来运行,因此消费者将在系统中输入所需的电量和愿意按小时支付的价格,而发电机将需要确定它可以输送多少电以及它希望按小时支付的价格。电价是由系统将发电商的报价和消费者的出价匹配起来决定的。购买和销售曲线被构建,它们的交叉点决定了市场价格和每天整点交易的电量。
ARIMA 预测方法将用于预测未来一天的电力市场。我选择使用非季节性 ARIMA 方法,因为只使用了前 300 个值,而不是全年的数据。数据来自 nord pool 2016-2017 年,由于模型在我的电脑上运行时间太长,因此在潜在的 8800 个值中只有 300 个值用于此过程。这个过程的完整代码在 GitHub 库中
拟合预测模型
ARIMA 代表AutoReIintegratedMovingAaverage,在这个模型中,使用了三个主要参数,分别表示为( p,d,q )。该模型结合了自回归模型和移动*均模型,并将这种混合预测模型应用于差分时间序列。
第一步是查看时间序列是否*稳,即查看时间序列的统计特性是否随时间变化。要使用的检验称为增广的 Dickey-Fuller 检验,也称为单位根检验。它检验零假设,即时间序列样本中存在单位根,它不是*稳的,另一个假设是它是*稳的,因为它的统计特性不随时间变化。
Dickey-fuller Test Code
Results of the Dickey-Fuller Test
结果表明,可以拒绝零假设,因为数据样本在统计上不可能是非*稳的,因为 p 值< 0.0000001,这意味着数据样本中不存在单位根,因此时间序列是*稳的。
d 参数代表模型要求的差分的综合阶次,使得时间序列数据变得稳定。通过从前一时间步的观测值中减去当前观测值,使时间序列变得*稳。因此,在这种情况下,它可以设置为 0,因为时间序列已经是稳定的。
P 参数代表 ARIMA 方法的自回归模型的阶数。这使用了一个观察值和多个滞后观察值之间的依赖关系,这意味着这是一个用于测试时间序列数据内随机性的工具,通过测试来查看 X 在多大程度上受 X. e. 的先前值的影响。g .当前价格在多大程度上受先前价格的支配,以及这种情况会持续多久。此参数通过创建自相关图表并查看数字来计算。在这种情况下,从图表中可以设置为 5 阶。
Autocorrelation chart that helps to determine the P Parameter
q 参数代表移动*均值的阶数,并显示窗口函数移动时的大小。此参数通过部分自相关图表计算得出。在这种情况下,可以将其设置为 12 阶,因为有 12 个值超出了 95%的置信区间(蓝色条)。
Partial autocorrelation graph that helps to determine q parameter
下面是测试不同 ARIMA 模型并计算哪个具有最低 AIC 值的代码。AIC 值是赤池信息标准,用于比较预测模型。由于很难从上面的图中看到正确的参数,我也选择了迭代一系列 ARIMA 模型,看看哪个模型最好
Iterating the ARIMA forecasting models
上述代码的结果为我们提供了一个(1,1,2)模型,用于 AIC 值为 1400 的(p,d,q)参数,还有其他具有更低值的不同模型,但是它们会产生错误,因此我将使用这些值,因为很难单独从图中检测出正确的 AR 和 MA 参数。
验证模型
既然已经找到了 ARIMA 参数,必须将数据分成训练样本和测试样本,因此前 200 个值将用于训练模型,后 100 个值将用于验证模型。
Arima forecasting function written to predict the next 100 values
结果如下所示,大多数测试值都在预测 ARIMA 值的 95%置信区间内。该模型的均方误差为 62,表明该模型可以进一步改进。然而,我们最初的努力是成功的,你可以使用 ARIMA 模型预测未来一天的市场。
Results of validating the ARIMA prediction values against the test values
我们能预测干草叉音乐评论的结果吗?
原文:https://towardsdatascience.com/can-we-predict-the-outcome-of-pitchfork-music-reviews-3b084d90c18f?source=collection_archive---------18-----------------------
我在研究数据时发现。
我是一个音乐迷。我尽可能多地听音乐。我不仅听,我还写,录,表演,制作,本质上是生活和呼吸音乐。我过去非常关注的事情之一是音乐评论。Pitchfork Music 是这个领域的主要参与者,我想知道我是否可以建立一个模型来预测 Pitchfork Music 的“最佳新音乐”奖。我也在学习数据科学,所以我决定让这两个世界稍微融合一下。
一点背景:Pitchfork 对提交的内容进行 0 到 10 分的评分,10 分是最高分。多名员工都提交他们认为的分数,他们对所有员工的评价取*均值,这就是分数。他们还投票决定它是否应该获得“最佳新音乐”奖。这些实际上是如何确定的细节是未知的,至少对我来说是这样。 你可以在这个子栏目 里读到更多关于它的 。
我下载了数据,清理了数据,争论了数据,创建了模型,并运行了一些预测,能够以相当高的准确度合理地预测“最佳新音乐”。尽管有那么多的预测模型,但这并不是整个过程中最有趣的地方。这是我在数据中发现的。
先从分数分布说起。你在这里看到的是大约 26,000 个分数跨越了大约 17 年。你可以看到分数一般集中在 6 到 8 分之间(这里是不是存在一些选择偏差?)而且大多数 BNM(从现在开始我将简称为“最佳新音乐”)的评分都在 8 分以上,这并不奇怪。
您还可以在这个部分依赖图上看到分数和 BNM 差异之间的关系,这个图本质上显示了一个特征(在本例中为“分数”)对分类结果(即 BNM)的重要性。
我还测试了其他特性的依赖性,发现了许多关系。最值得注意的是流派、艺术家和标签。从表面上看,这可能很有意义,但我会告诉你为什么这很有趣,但为了做到这一点,我想从谈论与“作者”的关系开始。根据数据,一些作者似乎比其他人更有可能给出更高的分数和/或 BNM 标签,如下所示:
以下是列表形式的相同数据:
你也可以开始看到流派的倾斜。
关于“流派”的数据,最有趣的是它们的分布。看看这张表:
摇滚无疑是最常被评论的流派,而全球是最少被评论的流派,但这并不重要。最有趣的是 BNM 的分布。流行音乐和 R&B 拥有最高比例的 BNM,实验音乐和摇滚音乐紧随其后。
说到唱片公司,这里有一个非常明显的偏差…似乎有些只是比其他的更有趣!
看起来你和谁签约是很重要的,尽管我想指出的是,有 21 张专辑是自己发行的,这说明了现代传播音乐的方法。
我们看到同样的事情发生在艺术家身上:
这个图表可能看起来有点奇怪,但是它是由每个标签的总 BNM 值组织的。这是图表左上角特写:
现在让我们以同样的方式来看“艺术家”。
同样,为了清晰起见,左上角放大了。
BNM 集中在整个“艺术家”领域的一小部分。要么一些艺术家比其他人更受青睐,要么就是比其他人更好。
那么,这一切意味着什么呢?在每一个特征(流派、艺术家、作者和标签)中,最好的新音乐区别都集中在与整体数据相比相对较小的数量上。是不是一个厂牌挑的艺人比其他的好?是不是一个艺术家始终比其他人优秀?而作者呢?在什么是真正最好的新音乐的问题上,有些人比其他人更有先见之明或更有洞察力吗?
号码
至少在我看来不是。我相信我们在这里看到的是音乐是非常主观的。一直都是。尽管试图保持客观,或者至少声称如此,Pitchfork 倾向于支持特定的流派、特定的艺术家和特定的标签,作者本身也倾向于有特定的倾向。
现在,这只是一个网站,尽管它在乐评界很有影响力。如果我从其他大型评论网站获取数据,会有什么变化?我们会看到相同的偏差,还是会因站点而异?我认为公*地说,这将是一个有趣的实验,也许是我将来要解决的问题!
注意:我将整理一篇文章,介绍我是如何实现我的代码的,展示我的数据清理、模型和特性工程,并将相应地更新这里的链接。与此同时,这里是我的 Github 库,供您欣赏。
我们能不能不要再说 SQL JOINs venn diagrams 了?
原文:https://towardsdatascience.com/can-we-stop-with-the-sql-joins-venn-diagrams-insanity-16791d9250c3?source=collection_archive---------8-----------------------
真的,求求你,OMG,停
烦躁时间。这些年来,我不得不多次向非技术人员教授 SQL,每个试图学习 SQL 但失败的人都谈到“连接是多么困难和可怕”。如果你在网上搜索 SQL 连接的解释,是的,它看起来很疯狂。
Look at this, just LOOK at it!
真正让我困惑的是,连接和集合论的整个混合甚至没有意义。一旦你的解释必须在看似任意的地方包含“其中 A 为空”,人们会认为你必须记住任意的咒语才能让事情正常进行——这听起来确实很难!
啊,谁来让这停下来!
旁注:关系代数
是的,我知道 SQL 源于关系代数,而不是集合论。实际上,我向人们解释事情的方式产生了类似的结果,但显然是从笛卡尔开始并向下过滤的正式方式向后倒退了一些。
我没有正式的关系代数背景,所以不要让我无药可救,欢迎你查看关于这个话题的其他 来源。
我是如何向人们传授联结的
我用一步一步的伪算法来解释 SQL 引擎如何产生连接的数据集,因为我觉得它可以让你掌握一些用连接可以做的更疯狂的事情。
用于生成和测试这些查询的 PostgreSQL 兼容 SQL 位于末尾
假设我们有两张表,A 和 B:
Data about cities godzilla attacks adapted from here
假设我们想任意连接 A 和 B 以得到“表 A 中的城市名称和 B 中的哥斯拉攻击”。(是的,这些表格有很多数据问题。为了简单起见,我没有考虑 id 和规范化,所以我必须使用 City_name 作为连接键。但所有这些在教授联接如何工作时都无关紧要,所以我忽略了它。)
我在这里的目标是教那些只看了 15 分钟 SQL 语法的人如何准确地预测一个连接将产生一致的结果。
概念连接算法
对于一般查询:
Select _*fields_*
FROM A
JOIN B ON on_*conditions* WHERE *where_conditions*
我使用了“工作集的概念,符合连接条件的行被名义上存储起来,以便以后根据 where 条件进行检查。
- 对于 A 中的每一行,逐一与 B 中的每一行进行比较
- 检查 on_conditions
— 如果 on_conditions 为真,则将 A 中的行连接到 B 中的行,并将连接的 A+B 行放入工作集
— 如果 on_conditions 为假,则继续比较下一对行 - 对于左/右/外连接
—对于左连接:如果对于 A 中的一行,没有条目被放置在工作集中,尽管检查了 B 中的每一行,然后将 A 中的该行放置在工作集中,在应该具有来自 B 的数据的字段中使用空值
—对于右连接:类似于左连接,但是对于 B, 如果在与 A 的所有行进行比较后,B 中的某一行在工作集中没有条目,则将 B 中的行插入到工作集中,在应该有来自 A 的数据的地方使用空值 - 检查完所有行组合后,从工作集中取出任何内容,并使用 where_conditions 对其进行过滤
- 根据需要应用任何 GROUP BY、ORDER BY、HAVING 子句
- 获得结果集,就大功告成了
这听起来仍然很难!
言语艰难。
动画更容易,所以我用 Excel 和 Photoshop 给你们做了一些。如果你想借,请随意。
警告:这不是 SQL 引擎的实际工作方式!
我在这里掩盖了一大堆东西,索引,NoSQL 的怪癖(比如如果你在 Hive 上,只能进行等价连接),为了不浪费内存和时间而进行的许多优化。
没关系,一个初学者不应该关心这些东西,最终结果匹配。
内部连接
SELECT A.City_name, Godzilla_attacks
from A
JOIN B on A.City_name = B.City_name
这个很简单——遍历两个表,当名称匹配时,插入到工作集。
A simple INNER JOIN
左连接
SELECT A.City_name, Godzilla_attacks
from A LEFT
JOIN B on A.City_name = B.City_name
也很简单,遍历所有的行,发现末尾的上海在 B 中没有可连接的条目,用一个空值添加它。然后,您可以在 WHERE 子句中过滤掉工作集中的空值。
A simple LEFT JOIN
疯狂加入
SELECT A.City_name, B.City_name, Godzilla_attacks
from A
LEFT JOIN B
on (A.Country = ‘USA’ and B.Godzilla_attacks = 2)
OR B.Godzilla_attacks = 13
这个查询毫无意义。故意的。如果你能在脑子里想象这个东西的行为,你就基本上掌握了连接的概念。
只要 ON 条件的值为 true,连接就是有效的,这完全是滥用了这一事实。您可以以极其强大的方式滥用这一点,使用诸如 case 语句、算术和其他复杂的逻辑。这就是为什么自连接是完全自然的,以及如何可以轻松地构建直方图。左连接并不重要,因为 A 中的所有行都可以找到一些连接对象。
引擎不关心,它只看到逻辑符号,如果为真则加入。
A “Go home you’re drunk” JOIN
最后
希望有人,在某个地方,用这个从维恩图中被拯救出来。如果只有一个人得救,并学会了如何更好地加入,我很高兴。
前进,写一些疯狂的条款。
谢谢
这篇文章的灵感来自于某个人提醒我我有多讨厌这个:
密码
示例 DDL 和 DB-fiddle 中的“疯狂”查询。
create table A (City_name varchar, Country varchar);
insert into A (City_name, Country) values
(‘Tokyo’,’Japan’),
(‘New York’,’USA’),
(‘Fukuoka’,’Japan’),
(‘Shanghai’,’China’)
;
create table B (City_name varchar, Godzilla_attacks int);
insert into B (City_name, Godzilla_attacks)
values
(‘Fukuoka’,3),
(‘Nagoya’,2),
(‘New York’,3),
(‘Tokai’,3),
(‘Tokyo’,13),
(‘Yokohama’,2)
;
我们能教一台计算机量子力学吗?(第一部分)
原文:https://towardsdatascience.com/can-we-teach-a-computer-quantum-mechanics-part-i-c3e724e31e1a?source=collection_archive---------26-----------------------
量子电路综合的强化学习方法
作者: Kaiah Steven,Matthew Rose,Tyler Jones 和 Xavier Poncini(量子机器学习研究团队, Max Kelsen
1.介绍
它被誉为震撼世界的下一项通用技术,就像图灵机的出现开启了信息时代一样。量子计算机被承诺会带来数不清的计算能力。然而,尽管我们尽了最大努力,我们还没有看到一台物理实现的量子计算机胜过它的经典计算机。通往量子霸权的道路是漫长的;幸运的是,这不是我们的第一次计算革命。借助经典计算领域的资源和经验,我们可以绘制出这一革命性技术发展阻力最小的路径。
本博客的第一部分将深入研究量子力学的使用,以促进有效的计算。然后,当我们试图解决同时控制和隔离量子比特的悖论时,本博客的第二部分讨论了我们打算如何通过强化学习将问题交给机器。
2.量子力学和计算
故事从我们最基本的现实理论量子力学开始。众所周知,这种描述是反直觉的,它预言了两种现象,这两种现象一旦被利用,就构成了量子计算的基础。
第一个效应,叠加,可以认为是一个物理系统可以同时存在于多个不同的状态。这种叠加持续到量子态被扰动(例如测量)导致“坍缩”成一个单一的经典态。进入量子领域,我们的标准计算单元可以从拥有 0 或 1 状态的简单比特升级到拥有 0 和 1 状态的任何可能组合的量子比特。
第二个影响是纠缠。顾名思义,这样的过程将两个或更多的物体缠绕在一起,确保它们有着相关的命运。假设我们纠缠两个量子位,每个量子位的状态是不确定的。从数学上来说,独立描述每个量子位是不可能的,我们只能描述整个系统。因此,我们对中一个量子位元的崩溃和测量会立即影响另一个的状态。
叠加和纠缠现象如何在有效计算中有用?首先,它们允许我们生产一个通用图灵机的量子力学模拟。这是通过定义一组操作来实现的,这些操作的有限序列可以执行任何可能的计算。第二,也许是最令人兴奋的前景,是利用叠加来并行计算大量的场景。这种计算能力有助于高效解决多变量优化问题——自然出现在所有行业领域(参见金融和大数据中的例子)。
我们目前正处于通往量子霸权之旅的开端——可以使用被称为嘈杂的中等规模量子计算机( NISQ )。这些设备的最大障碍之一是退相干,它为每个量子位设置了一个失效日期。量子系统中包含的信息最终会“泄漏”到环境中,直到你正在使用的系统失去其,变得实际上不可用。
这产生了一个设定的时间窗口来执行量子计算(参见量子纠错来永久解决这个问题)。因此,时间成为一种资源,必须有效地利用它来充分利用量子计算。因此,研究集中在寻找最快的方法来执行量子算法。找到这个最优解绝不是一个容易的问题,并且今天仍然是一个公开的研究问题。
量子计算的一个特殊公式由电路模型提供。这里,在量子位上执行的酉运算用门来表示。通用量子计算并没有唯一地定义一组门——因此有许多组达到这个目的。出于我们的目的,我们将集中于由 X、Z、H、CNOT 组成的门集。这样的门集并不是通用的(在标准条件下),然而它将允许我们访问叠加态和纠缠态。在我们创建第一个量子电路之前,我们将介绍两个想法,每个想法对于发展对这些机器要执行的操作类型的直觉都是至关重要的。
2.1.布洛赫球
布洛赫球是单个量子位状态的直观视觉表示。叠加允许系统处于 0 或 1 状态的任意线性组合。在 bra-ket 符号中,一个位的经典 0 和 1 状态被表示为|0⟩和|1⟩.,这将在下一节讨论因此,我们可以将某个系统 S 的状态描述为这两个状态的线性组合:
系数 α 和 β 被称为概率振幅。量子力学的核心是这些系数拥有复数值的能力,例如:
*在上面的等式中,我们给出了 α 及其复共轭 α ,其简单地反转了与复数单元相关联的符号。量子力学的许多令人惊讶的结果可以归因于我们缺乏对复杂概率振幅的直觉。系统处于 0 或 1 状态的概率由概率幅度的绝对*方定义。
现在让我们用文字总结这些方程的主要结果:
- 我们将系统的状态描述为可能的状态 0 和 1 乘以它们相关的概率幅度的线性组合
- 这些振幅很奇怪,因为它们可以是复数
- 取与每个状态相关的概率振幅的绝对*方,我们可以确定系统处于每个状态的概率
- 概率之和必须等于 1
Bloch sphere 是将这些概念捆绑到一个直观的包中的简单方法(参见下面的图 1)。最后的约束确保单个量子位系统的所有可能的叠加态都存在于球体的表面上。当在我们的量子位上执行操作时,我们将探索这个物体的表面。
Figure 1: The surface of the Bloch sphere defines all of the possible states accessible to a single-qubit system. The application of universal single-qubit gates will allow us to travel anywhere on the surface of this object.
2.2.布雷克记号
Bra-ket 符号是描述操作符(门)对状态的作用的数学形式,这些操作的结果允许我们的状态遍历 Bloch 球。下面的等式表示 X 门在零量子位状态下的作用:
换句话说:将 X 门应用于量子位的计算零状态,将该状态转换为计算一状态。
在球体上:X 门将量子位状态从布洛赫球体的北极发送到南极。
现在,让我们检查当我们将 X 门应用于计算一态时会发生什么:
换句话说:X 门将一态转换为零态。我们看到 X 门是经典计算中非门的量子模拟。
球体上:X 门将量子位状态从布洛赫球体的南极发送到北极。
把这些动作结合起来,我们就可以看到在布洛赫球面上由这种操作引起的运动。
配备了我们的布洛赫球解释让我们检查剩下的单量子位门。Z 门的动作由下式给出:
检查 Z 对混合态的作用:
在球面上:Z 门围绕布洛赫球面的赤道*面运行。
现在让我们检查哈达玛门:
在球体上:H 门从两极行进到赤道。
与我们之前检查过的三个门不同,CNOT 门是两个量子比特的操作,因此不允许用布洛赫球来解释。我们可以通过简单地在我们的状态旁边加上一个额外的项来表示两量子位系统——从数学上来说,这相当于取一个张量积。|01⟩状态拥有两个量子位,第一个处于 0 状态,第二个处于 1 状态。以类似于单量子位情况的方式,我们可以如下表示双量子位系统:
现在让我们研究一下 CNOT 门在我们拥有的两个量子比特系统空间中的作用:
将 1 和 2 量子位状态的概念推广到 n 量子位状态对于下面的部分将是有用的,让我们通过建立序列来说明这样的推广:
既然我们已经详细介绍了钥匙门的作用和多量子位系统的概念,让我们创建我们的第一个量子电路吧!
2.3.线路模型
量子电路模型是量子算法的图形表示,它将问题分成常见的子过程,类似于经典计算或电气工程中的模拟电路模型。状态表示为水*线,集合中的任何门都可以对其进行操作:
让我们想象我们有三个量子比特在|111⟩态,我们想在最终态|110⟩.结束实现这一结果的示例计算如下:
检查这个计算的输入和输出状态,我们看到这个复杂的图表只是翻转了第三个量子位的状态。实现相同结果的简化计算如下:
这里我们应用了量子力学的知识来简化一个电路的玩具例子。让我们看看当我们扩展到任意数量的量子位时会发生什么:
不一定清楚如何确定 U ,产生任意的最终状态 S ,以及这个特定的 U 是否有效。自动化的一个自然问题出现了:是否有可能构建一个模型,它采用一个输入输出状态对,并生成一个有效的电路来促进这种转换?
我们随后的研究试图回答这个问题。鉴于机器学习最*的成功——彻底改变了计算机视觉、机器人学和许多其他领域——我们试图调查这一领域,以检查可能有能力学习计算景观结构的可能范式和架构。
很快就很明显,这样的问题可以类似于视频游戏。我们有一些初始状态,一组有限的操作和一个最终状态,我们只是不知道到达那里的最佳方式。随着强化学习在国际象棋和围棋中击败领域专家,挑战物理学家在高效量子电路的产生中找到阻力最小的路径似乎是很自然的。
见 第二部分 为我们的实现。
我们能教一台计算机量子力学吗?(第二部分)
原文:https://towardsdatascience.com/can-we-teach-a-computer-quantum-mechanics-part-ii-5e90ac96ef3a?source=collection_archive---------35-----------------------
量子电路综合的强化学习方法
作者: Kaiah Steven,Matthew Rose,Tyler Jones 和 Xavier Poncini(量子机器学习研究团队, Max Kelsen
在本系列的第一部分中,我们介绍了许多对量子计算至关重要的先决概念。在这一部分中,我们将详细介绍我们将强化学习应用于状态准备问题的工作。
介绍
我们生活在一个量子计算仅限于嘈杂的中等规模量子计算机(NISQ)的时代。这项技术——就像石头碰撞产生火花的启示——为难以想象的创新和潜力奠定了基础。
目前,这些设备受到可用量子位数量少和相干时间短的限制;因此,当前的目标是从这项新兴技术中提取尽可能多的“热”和“光”。在资源有限的情况下,NISQ 的潜力取决于资源的有效利用。因此,实现特定过程的最佳门(量子位操作)配置是非常需要的。然而,找到这种配置并不容易,尤其是在试图进行有用的量子计算时。
将机器学习突破应用于这一困境是一条充满希望的途径,可以用这些火花点燃一把火,并从今天的量子计算机中获得实际优势。
强化学习
在我们开始之前,让我们快速介绍一下强化学习(RL)。由于一些突破性的成就而在人工智能领域受到欢迎,例如 OpenAI Five RL 基于 DOTA2 团队击败了一支职业选手团队,以及谷歌的 AlphaZero 在围棋中击败了 Lee Sedol 和柯洁(两人都是多个世界冠军得主)。
RL 作为一种有潜力只“解决”视频游戏的技术已经获得了声誉。然而,我们希望量子计算是游戏领域之外的一个领域,可以有效地利用 RL 的力量。
强化学习背后的一般思想是教一个代理(由一个策略体现)如何达到某个定义的目标或目的。这可以通过对两个主要元素——代理和环境——的描述来理解。
Figure 2: Learning loop of a typical reinforcement agent
RL 中的环境可以被认为是我们的代理生活在其中并与之交互的虚拟世界。这种交互和反馈允许代理从环境中学习,就像人类通过与他人和周围世界的交互来学习一样。
在时间段(或“情节”)的每一步,我们的代理人被允许观察他们周围的世界,部分或全部,以获得对其当前状态的一些理解。然后,代理从一些预定义的动作空间中选择一个动作,以促进进一步的交互。这个动作改变了环境的状态,并根据世界先前状态和新状态之间的差异向代理返回一个奖励。
代理选择任何动作的基础是该代理的策略——基于当前观察到的环境状态输出有效动作的某种概率分布。在 Deep RL 中,这种策略通过一个神经网络来表现,该神经网络将当前状态作为输入,并提供一个动作作为输出。
一个天真的方法可能是简单地选择最直接的回报。然而,这可能会导致代理陷入困境或走进死胡同——达到局部极值。人们通常会将未来行动的贴现回报与最直接的行动相结合,以此来学习如何达到最终目标。
在我们的代理播放完一集之后,策略会根据存储的状态、动作和奖励信息进行更新。这种更新作为一种方式来教导代理在某些状态下哪些动作是优选的,哪些应该避免。
构建有用的、起作用的 RL 代理的一个主要障碍是构建一个最佳映射到您的特定用例的奖励函数。这种功能是代理在其环境中的唯一监督者,该环境应该只提供引导代理朝向其目标的奖励,并且以避免陷阱的方式。
RL 研究领域充斥着错位和误导代理的例子——大多数在我们看来很幽默,但对代理来说完全合理。例如:
- “我在我的 Roomba 上连接了一个神经网络。我想让它学会在不撞到东西的情况下导航,所以我设立了一个奖励计划来鼓励速度,阻止撞上保险杠传感器。它学会了倒车,因为后面没有保险杠。”
- “代理人在第 1 级结束时杀死自己,以避免在第 2 级失败”
- “代理无限期暂停游戏以避免失败”
- 一种赛船游戏,其中“RL 代理找到一个孤立的泻湖,在那里它可以转一个大圈,并重复撞倒三个目标,定时移动,以便总是在目标重新聚集时撞倒它们”,而不是实际完成比赛
看到这里越来越多的在游戏中使用强化学习的文献目录,以及一些相当有趣的错误奖励函数。在概述了量子计算和强化学习的预备知识之后,我们现在可以详细描述我们将强化学习应用于量子态制备的努力。
我们的方法
现在有了利用强化学习来优化量子电路构造的能力,我们开始探索我们的选项,包括使用什么样的动作集,将什么定义为我们的状态,可能的奖励函数,以及训练哪个实际的 RL 算法。
IBMQs Qiskit Python 库用于构建和可视化量子电路,并与基于 Python 的量子计算库 Qutip 一起执行相关的量子操作。用 TensorFlow 实现的神经网络被用作代理策略的基础。
在探索了有关 RL 算法的当前文献并检查了最先进的性能之后,*似策略优化 (PPO)的广泛成功和适用性促使我们在测试中使用这种算法。检查的其他选项包括投影模拟、深度 Q 网络和异步演员-评论家代理 (A3C)。
我们的第一个努力是利用指定量子位的量子状态作为环境状态,同时定义一个由所有合法量子位门对组成的动作空间(例如,量子位 1 上的 X 门被指定为与量子位 3 上的 X 门不同的动作)。
最初的奖励函数是在保真度的唯一基础上运作的,保真度是衡量一个人区分两个量子态能力的尺度。基本上,环境的当前状态和目标状态重叠越多,奖励越高。为了鼓励合成更小的电路,每使用一个门,奖励也会减少。
尽管忠诚有效地决定了目标是否已经实现,但很快就发现这是一个错误的奖励功能。在这个离散门空间上的保真度函数有许多局部最大值的意义上,这是错误的。特别是对于简单的电路,保真度的短期增加通常会增加完成电路所需的门的总数,在某些情况下甚至会将电路引入死胡同。
我们第二次接受奖励功能是出于对完成电路剩余门数的某种测量的野心。有两篇论文在研究如何得出这一方法时脱颖而出。一个( Nielsen 等人)利用几何学的思想将量子操作空间表示为一个表面,其中最佳电路是通过这个表面的最短路径(测地线)。另一个(吉洛拉米)推导出了将一些量子位从一个状态驱动到另一个状态所需的门数的下限表达式。
对我们来说不幸的是,这两个选项似乎都有限制因素,使得它们在我们的框架中没有用处。测地线的生成和求解在计算上非常昂贵,而且 Girolami 的下限只被证明适用于通勤门,这使得动作集失去了普遍性。
奖励函数问题的一个犹豫不决的解决方案是引入稀疏奖励方案——在最终电路达到目标的情况下,只提供正奖励(与使用的门的数量成反比)。在这个实验阶段,我们改变了动作空间,只包含单独的门操作,并设置代理在量子位上循环,而不是让它选择。
作为这种变化的结果,身份门被添加到动作空间中,这样代理可以“跳过”一个量子位,如果它认为有必要的话。这样做可以确保每次操作中不同量子位的一致性。
这些变化的结果是有希望的,该模型能够在合理的时间内设计出具有一致性的最佳简单三量子位电路(例如,下面的电路是在大约 40 个训练周期内合成的,或者在用于测试的笔记本电脑上是在 40 秒内合成的)。
目睹我们的代理人工作后,信心大增,我们想探索模型的通用性。产生了不同目标状态的课程,从简单的一门目标单元到更复杂的四门单元。多次对不同目标集的培训有明显的改进迹象,表明代理人有能力同时学习解释多个不同目标的策略。
Figure 3: Policy improvement as a model is trained over a set of 7 unique unitaries.
在没有任何指导奖励函数的情况下,PPO 的成功代表了一个有希望的结果,特别是在超参数优化导致收敛时间显著缩短(最简单的电路在 5 秒内,课程在几分钟后)之后。这种与预训练模型融合的改进代表了迄今为止最强有力的建议,即我们的神经网络可以学习在具有挑战性的量子电路环境中导航。
因此,我们决定测试其他奖励函数,用非通用通勤 IQP 门集替换我们的通用非通勤门集。然后,我们利用 Girolami 的下界结果来形成我们的奖励函数。这个模型能够从我们稀疏的奖励中获得成功,同时将代理推向目标,并(希望)避免任何局部极大值。
Figure 4: Policy improvement as the IQP model is trained over a set of 7 unique unitaries.
使用逐步奖励函数显示出相对快速的收敛,其电路比用于产生图 3 的电路更复杂。这个通勤门奖励函数在鼓励代理人以相对较快的收敛时间实现目标方面的成功代表了一个强有力的概念证明。随着功能推广到非通勤门,一个更普遍的政策可能会发展。
我们训练强化学习代理人来合成最佳量子电路的努力,依赖于创造一个我们的代理人可以在其中玩耍的自定义环境。这种环境可以在这里找到,并利用诸如支持不同的门集、考虑量子位的物理连通性以及生成不同大小的电路等特性。本系列中的所有实验都是在这个环境下完成的。
我们认为这些结果鼓励了寻找圣杯,最佳量子电路构造的持续努力。在我们的追求中,我们发现奖励函数(当前和目标状态之间距离的可靠度量)是应用机器学习来确定有效量子电路的关键因素。成本函数的后续改进将显著提高我们代理的性能。
我们目前正在探索的一些令人兴奋的相关途径包括将这种强化学习方法扩展到连续控制空间——塑造用于在电路中实现量子门的脉冲。敬请期待!
我们能相信 AutoML 会完全自动驾驶吗?
原文:https://towardsdatascience.com/can-we-trust-automl-to-go-on-full-autopilot-ab76dc061833?source=collection_archive---------21-----------------------
AutoML 的承诺
数据科学家短缺,自动机器学习(AutoML)有望缓解这一问题。 H2O 无人驾驶人工智能在一个易于使用的应用程序中采用专家数据科学家的技术,帮助扩展您的数据科学工作。它让“每个人都能开发可信的机器学习模型”。
实验
一名首席数据科学家和四名经验不同的哥伦比亚大学学生在预测股票价格走势的真实问题上测试了这项技术(这是一项具有挑战性的任务!).
这些数据是罗素 1000 指数中 5 年的股票的月度数据。这些特征是 80 个股票特有的因素,如价格动量、市净率、每股收益增长率、净资产收益率。目标是 12 个月的远期股票回报(具体来说是经过 beta 调整的 alpha)。目标是使用股票特征预测股票收益。成功的衡量标准是*均绝对误差和预测与实际回报之间的等级相关性。
该数据的特点是,它是面板数据,其中某一天的观测值之间有很高的截面相关性。此外,由于输入数据是每月提供的,而目标回报是 12 个月以后的,因此 11/12 个月在两次后续观察之间是相同的,所以时间上有很高的自相关性。
原始基线
在评估一个模型之前,你需要有一个天真的基线,正如在数据科学家犯的十大统计错误中所讨论的。第一条基线预测所有观测的回报率为 0,接*中值,这意味着没有办法预测回报率。第二条基线是对所有特性进行排名并取*均值,这意味着所有特性在预测回报时同等重要(这不会生成回报预测,但您仍然可以比较输入和输出排名)。最后一个基线是一个月前的回报-鉴于数据集的性质,这包括前瞻性信息,是评估任何过度训练和前瞻性偏差的良好基线。
Success Metrics for Naive Baselinemodel
第一个障碍—技术设置
在我们开始建模之前,第一个障碍是让每个人都与戴建立联系。H2O 建议在配有 GPU、CUDA 支持和 64GB RAM 的现代数据中心硬件上安装无人驾驶 AI。我们按照说明,用推荐的设置在谷歌云*台上安装了软件。
结果:我们在不到一周的时间里就花光了 200 美元的 GCP 积分!我们很快意识到不需要如此高的计算能力,因为我们的数据集只有 1GB 大小。我们在一台规格小得多的 GCP 机器上安装了无人驾驶 AI,它也可以在一台只有 8GB RAM 的本地笔记本电脑上工作。总的来说,安装无人驾驶人工智能需要一定的技术专长,不是团队中的每个人都具备。
第二个障碍—数据预处理
下一个障碍是为分析准备好数据,AutoML 对此没有帮助。我们必须预处理和组合来自多个数据源的数据,这是一项巨大的工作。我们使用了数据工作流库 d6tflow 和数据共享库 d6tpipe 来自数据科学家犯下的十大编码错误来帮助我们完成预建模步骤。
结果:预处理 d6tflow DAG 如下图所示。它采用来自彭博的股票回报数据和来自 WRDS 的股票因素数据,合并、清理和规范化这两个数据源,以使其适合于 DAI 中的机器学习,DAI 要求将干净的数据都放在一个地方。
└─--[TaskFactorComposite-{'idx': 'RIY Index', 'dt_start': '2011-01-01', 'dt_end': '2018-09-01'} (PENDING)]
└─--[TaskFactorsIdx-{'idx': 'RIY Index', 'dt_start': '2011-01-01', 'dt_end': '2018-09-01'} (PENDING)]
└─--[TaskFwdRtn-{'idx': 'RIY Index', 'dt_start': '2011-01-01', 'dt_end': '2018-09-01'} (PENDING)]
└─--[TaskBbgHistory-{'idx': 'RIY Index', 'dt_start': '2011-01-01', 'dt_end': '2018-09-01'} (PENDING)]
└─--[TaskBbgMembers-{'idx': 'RAY Index'} (PENDING)]
全自动运行——好得难以置信?
在我们实验的开始,我们直接使用无人驾驶人工智能界面,上传数据集,选择目标变量,调整性能和可解释性等旋钮。我们必须说,用户界面很整洁,有点像托尼·斯塔克的贾维斯。虽然所有数据科学新手都在努力选择正确的设置,但至少具有中级数据科学知识的团队成员很容易知道该做什么。
一旦发射按钮被按下,正如它的名字一样,训练就是无人驾驶的。我们观察了这个过程,因为它产生了数百个模型,创建了数千个新功能,并最终创建了一个整洁的实验结果 PDF 报告。
结果 : MAE 为 4%,相关性为 96%。哇!机器真的比人强,把天真的模型打得落花流水。但它甚至用前瞻偏差击败了天真的模型——可疑!
手动添加真实测试集
根据数据科学家在十大统计错误中对面板数据的样本外测试建议,我们建立了自己的训练/验证/测试集。戴似乎没有任何功能来做到这一点,所以我们必须手动完成。我们按时间划分数据,还做了前滚测试。做这件事的技能栏已经上升到中级。
结果 : MAE 为 6%,相关性为 90%。仍然比带有前瞻性偏见的天真模型高得多——再次令人怀疑!
这东西到底有什么用??
在这一点上,我们不太确定是什么推动了这种非凡的表现,很明显,它好得令人难以置信。我们得到了一份包含所有技术细节和图像的报告。但是它是怎么建立模型的呢?关着的窗帘后面发生了什么?很难理解它尝试了什么。它设计了哪些参数和功能?有哪些后来被放弃的功能?不仅新手迷路了,专业人士也迷路了。
通过仔细分析输出,我们找出了问题所在:戴自动添加滞后变量和出叠*均值。鉴于我们的数据集的性质,它是具有重叠目标变量的面板数据,这些特征导致了前瞻偏差和显著夸大的结果。
下图更详细地说明了这个问题。假设只有两只股票:A 和 b。我们希望从每月更新的输入数据中预测年回报率。在训练中,由于大量重叠,很容易从 A1 预测 A2。但是在运行模型时,我们没有相同的输入数据,如 A13 和 A14 所示。所以我们在训练中必须小心先前的观察。此外,如果 B 与 A 高度相关,则很容易预测,但同样,当模型在生产中运行时,该数据不可用,因此异常的“测试”性能不会持续。这些问题也让人类数据科学家感到困惑,详见数据科学家犯的十大统计错误,参见#7+8。
Panel data with overlapping time periods
完全手动操作以避免前瞻偏差
我们不得不深入研究 DAI 文档,并使用 DAI python 客户端关闭这些功能,并手动运行每个实验来执行非重叠时段的前滚分析。经过相当多的努力,我们使用针对 DAI 优化的 d6tflow 构建了一个完全自动化的机器学习工作流。做这件事的技能栏现在是在职业。
结果 : MAE 为 23%,等级相关度为 4%。合理多了!而且还是打零技能和等重模式。
结论
首先,戴声称它没有超装,但它确实超装了!无人驾驶人工智能展示了夸大的测试性能,这是我们在生产中实时运行模型永远无法实现的。这是一个案例研究,AutoML 系统可能会给出过于乐观的结果——样本没有经过仔细分析。这可能是由于我们的数据集的独特性质,但如果它发生在我们身上,它也可能发生在其他人身上。因此,理解数据的特征、预测的类型和有效的样本外测试至关重要。
第二,整个数据管道涉及的不仅仅是 AutoML 模型训练。我们需要准备数据,生成测试数据集,通过 python 手动控制 DAI,并提取输出以与原始模型进行比较。我们仍然需要知道如何使用 pandas、d6tpipe、d6tflow 和 DAI python 来运行完整的 ML 管道。
第三,尽管终极模型是透明的,但戴生成了什么特征以及它如何训练模型仍然不清楚,因此新手很难自信地解释方法和输出。
总之,像 H2O 无人驾驶这样的 AutoML 系统仍然需要一个受过教育的数据科学家来使用、控制、解释和解释机器学习系统。我们把它比作驾驶飞机:仅仅因为飞机有自动驾驶仪,这并不意味着任何奇怪的乘客都能够安全地操作飞机,并在没有经过足够培训的情况下将 200 条生命的信任交到他们手中。
我们可以使用机器学习来生成文本冒险故事吗?
原文:https://towardsdatascience.com/can-we-use-machine-learning-to-generate-text-adventure-stories-f44dcc8171b8?source=collection_archive---------18-----------------------
训练神经网络为我未完成的文本冒险游戏生成背景故事的探索。
A terminal from the first level of Bungie’s Marathon.
挑战
去年,我开始为一个名为 Ludum Dare 的 48 小时游戏堵塞制作一个小文本冒险游戏。我一年参加几次,甚至还做过一次主题演讲。虽然我能够在一天之内构建一个简单的文本冒险游戏引擎,但在创建内容使其变得有趣时,我开始失去动力。
My unfinished Ludum Dare text adventure game “Terminal” built with Pixel Vision 8.
快进 6 个月,再加上转向机器学习的职业生涯,我开始有兴趣看看我是否可以训练一个神经网络来为我未完成的文本冒险游戏生成背景故事。我的目标是用一个变得无赖的人工智能的叙述来帮助增加随机生成的房间描述。我以我最喜欢的 90 年代第一人称射击游戏之一马拉松为基础设计了这个游戏。
Marathon 2 screenshot.
马拉松是 Bungie 在发行《光环》和《命运》之前创作的。在马拉松比赛中,有三个人工智能,主要的一个,杜兰达尔,变得“猖狂”,这是一个疯狂的花哨术语。不同于当时类似的 FPS 游戏,如《毁灭战士》,《马拉松》有一个丰富的故事,你可以通过分散在各个关卡的终端阅读。这些终端不仅能指导你完成任务,还能随着你在游戏中的进展加深剧情。
Marathon terminal via MarathonWiki.
现在有许多神经网络的伟大例子被训练来创建基于文本的内容,如歌词、莎士比亚诗歌等等。由于 Marathon 在其三个游戏的终端中包含了如此多的文本,我认为使用一个名为 textgenrnn 的开源项目,在我用来自动化我的深度学习工作流的一些工具的帮助下,看看我可以创建什么,将是一个很好的候选人。另外,由于游戏中的人工智能变得疯狂,我希望即使生成的文本没有意义,它仍然符合我正在创建的文本冒险游戏的主题。
An example of garbled text from a crazy AI.
以下是我的实验记录、结果,以及如何从我的 git repo here 独立运行项目的说明。
创建数据集
L 凑巧,马拉松的故事在网上有据可查这里。如果你以前没玩过这款游戏,值得一试。你可以在这里运行一个更现代的版本,叫做Alpha One。考虑到这一点,为了训练 textgenrnn 模型,我必须从头开始创建数据集。没有一种简单的方法来自动化这一点,所以我检查了网站上所有的游戏终端,并手动将它们复制到一个文本文件中。
你可以用少量的文本来训练 textgenrnn,但是你给它的文本越多,它应该学得越好。我尝试了几种不同的游戏文本格式,但最终,我不得不手工删除对训练有负面影响的文本块。
Example of a bad text block that could impact the training.
即使像这样的终端文本,看起来像随机放置在一起的字符,实际上包含了一个故事。在当前的格式中,文本会脱离训练,因为我们要分析需要空格的单个单词。最后,为了创建一个更干净的数据集,我决定跳过这类文本块。因为这相当耗时,所以我最终使用了第一个游戏的故事。这里有一个链接指向我在 git 项目中学习过的源文件。
设置项目
我开始从 GitHub 克隆 textgenrnn,并在 PyCharm 中打开它。打开项目后,我创建了一个新的 Python 解释器,并安装了 setup.py 脚本中定义的需求。您还需要安装不在依赖项列表中的 Tensorflow。我最后用下面的代码创建了一个新的 requirements.txt :
A list of requirements needed to run the project.
该项目有很好的文档记录,并附有一些示例,但我选择删除它们,并从一个干净的项目文件夹开始。我删除了数据集、输出和权重文件夹中的所有内容,因为我将使用新数据集生成这些内容。然后我删除了 setup.py 文件,因为我不再需要它了。
The new project folder after cleaning it up.
剩下唯一要做的事情是将我的新马拉松终端文本数据集添加到适当的文件夹中,并开始创建脚本来运行培训。在这样做之前,我需要创建一个配置文件,可以在我的培训和文本生成脚本之间共享。为此,我使用以下代码在项目的根目录下创建了一个 config.py 脚本:
I stored all the configuration values in their own script file.
虽然您可以通过直接传递这些值来训练模型或生成文本,但我发现将这些值保持在外部会有所帮助,这样我就可以在训练时更容易地调整它。新的配置文件准备好了,是时候创建我需要用来训练和生成文本的脚本了。
由于所有的配置值都在它们自己的文件中,我能够创建一个简单的 train.py 脚本来运行实际的训练。下面是代码的样子:
This is the code I’m using to train the model.
在高层次上,我创建了一个新的 textgenrnn 实例,设置了到输出文件夹的路径,最后调用 train 函数并提供它需要的参数。此时,您可以运行脚本并从终端窗口监视一些早期输出:
Running through the first round of training.
在第 10 个纪元左右,文本变得更好,但我们不会看到实际的结果,直到我们从输出文件夹中的训练模型生成更多的大量文本。
After training the model and it’s files are saved to the outputs folder.
为了生成更多的文本,我用下面的代码创建了一个 generate.py 脚本:
This code allows me to generate out text using the trained model.
正如您所看到的,我通过向它提供在训练期间创建的三个文件来设置 textgenrnn:weights、vocab 和 config。从那里,我们告诉 textgenrnn 使用一组温度值、步数和生成文本的最大长度创建一个新文件。运行该脚本后,它会在 outputs 文件夹中用生成的文本生成一个新的文本文件:
A sample of text generated from the model.
现在我已经具备了开始训练和验证生成文本质量所需的一切。让我们看看它产生了什么。
生成的文本结果
在这一点上,相对容易看到我们可以期待什么样的结果。这是我开始试验的几个样品。
1 个时代,RNN 大小为 128 和 2 个 RNN 层产生了以下内容:
vacuum
-with
you
* *
incoming **
-
<
transfer
,
strength
gives
area of
a
- ,
to
*
public
.oppressive *
~
<
* * * * * * * * jump * * * * * * * * * * * pad * * *
durandal
message
*
起初,它没有创造任何有趣的东西。我以为只有一个纪元。
以下是当我使用与上面相同的设置将训练增加到 10 个时期时发生的情况:
* * * incoming message from * * ** * * incoming message * * *< 39 - < 46 . . . 299 >* * * end of message * * * *
he , , and crist the from closing his , and closing five was the of arms . on the discarding elevators century
* * * end when message * * * *
< security breached - excerpts >f terminal . . 17 . . . 198 >* * * end of message * * *
< security breached - - < 33 . 12 . . . 128 >
for the the of may fourth* * * end message * * *
teleport whenit is is is is . . . i am am able that to to to my sensory eyes the you you you your your a " see philosophical may your your a21h . . . . " . . 223 >
事情开始变得有点有趣了。该模型可以生成完整的句子,它了解到消息通常以某种形式的“传入/结束消息”开始和结束,它可以创建一些与特定类型的终端消息相关联的虚假 IP 地址。它也很擅长用引号来开始和结束一段文字,但是这段文字没有太多意义。
最后,我想看看更多的纪元是否会有帮助,所以我将数字增加到 40,并保持相同的设置作为基线。下面是它生成的内容:
you have not completed your mission . you may be be not the such here . but i ' ll want to to to friend . if you must into the this to of transmission it would be be a fighter day . . . fighter . held symbolic significance for the . the time that time that had
martian skies
however , due to to the marathon ' s teleporters . .< unauthorized access - alarm 2521 - >
be careful . everything not not not as to , and or , and nearly active to your your maintenance maintenance . .
the pfhor seem to have enslaved a number of other races : : races as of have they been been been been off by compilers for for and alien .the invaders seem to to be interested in the marathon . gheritt s something something one as from about he ' s ' s ' pht , . even hard . . to the was was . rat the the the the the crist shuttle . has , and and at the just than the the after the the
现在,我们开始获得完整的句子,这似乎在段落中更有意义。当然,挑战在于,在这一点上,我正在试图理解哪些价值观有助于训练更好的模型。不幸的是,在我开始找到我觉得能产生更好结果的值之前,有很多尝试和错误。
为了帮助监控培训,我想在项目中添加 MissingLink.ai 的 SDK 来监控我的实验。坦白地说,我为 Missinglink 工作,由于我对完成我的文本冒险游戏有既得利益,我开始对如何在培训期间优化模型感兴趣,以确定哪些价值观产生了影响。
因此,我创建了一个新的 missinglink 分支,并在项目的 textgenrnn.py 脚本中添加了几行代码,首先是导入 SDK,配置项目以运行实验,并定义 Keras 回调:
Importing the MissingLink SDK and creating a Keras callback.
此外,我需要将新的回调提供给 model_t.fit_generator() 方法:
Adding the MissingLink callback.
通过这些修改,我现在可以在 MissingLink 仪表板上运行实验并监控结果。在进入下一轮训练之前,我以我在 40 个时期的最后一次实验作为基线。
Monitoring the loss during training over 40 epochs.
在尝试了一些不同的设置后,我最终选定了 4 个 RNN 层,双向设置为真,100 个纪元。我还将列车尺寸增加到 0.9,产生了以下损失:
Monitoring the loss during training over 100 epochs.
一旦我对改进的模型感到满意,我就能够生成更好的文本。让我们来看看最后的结果。
最终结果
经过大量的实验,我能够写出一些感觉足够连贯的文本块,就像一个疯狂的人工智能的漫谈。
例子 A:来自马拉松
Gheritt had a good life, so much time, so much time. He had loved swimming, turning, beating. He had loved the tingle in his hands and feet, his inability to kill his nemesis. Once he had fallen down the stairs, and just for a moment, his hands came to rest on the carpet of the stairs. In that instant, his body had frozen, floating over the stairs, safe from falling, but the moment didn’t last. The ocean crashed about him, his hands torn free from the sandy bottom, his body flipping, falling.
示例 B:已生成
gheritt had a good life , so much on that will be killed . i saw the make one in a wicked computer — and we must don ‘ t remember them any time you .
i have received a preliminary report from some members of them . the only computer system . “ it was quite simple . “ a white thought syndrome suffering if the uesc ‘ s ‘ pht even stopped their efforts .
我很惊讶这是多么接*。我认为,随着更多的数据,编辑语法,并智能集成到游戏中,这可能是一个可行的解决方案来生成一些背景故事内容。目标是将随机生成的文本、神经网络生成的文本和手写文本融合成更加无缝的体验。考虑到这一点,我计划将它集成到游戏中,并与概述目标的更多面向任务的文本混合,类似于原始游戏中马拉松终端的工作方式。
我得说这个小实验是成功的。我需要多花一点时间来建立一个更好的数据集,包括马拉松 2 和 3 的终端。我也想看看我是否能最终从模型中得到一个连贯的故事。在配置文件和数据集之间仍然有调整要做。然而,即使在这些早期实验之后,我认为结果是有希望的。最后,值得一提的是,textgenrnn 是一个老项目。在文本生成方面已经有了更多的进步,比如 OpenAI 的 GPT-2。我可以看到自己继续尝试训练一个神经网络来为我更多的程序生成游戏生成文本。
如果你想更多地了解这个项目和我在 MissingLink.ai 的工作,欢迎在下面发表评论,或者在 Twitter 上关注我,给我发消息。
我们可以使用社交媒体来定位合法的停电吗?
原文:https://towardsdatascience.com/can-we-use-social-media-to-locate-legitimate-power-outages-7b7409708447?source=collection_archive---------17-----------------------
基于余弦相似度的自然语言处理推文分类初探。
我们都知道停电会给我们的生活带来多大的破坏性。停电不仅每年影响我国数百万人,根据停电跟踪者的年度报告,每年还会损失数十亿美元的收入。正因为如此,我们需要更好的机制来跟踪它们,以便在它们发生时能够快速处理。
电力公司的停电管理系统已经推出了新的智能电网技术,以补充检测和报告停电的传统方法。然而,新技术要到 2030 年才能完全推广。
虽然这项新技术已经推出,但还需要额外的努力来帮助识别和报告停电情况。我们中的一个团队决定看看我们是否可以建立一个工具来提供帮助。我们想看看我们是否可以使用社交媒体来正确识别停电。
数据收集
我们的方法是首先决定从哪些社交媒体*台中选择。我们发现 Twitter 是最可行的*台,就我们可以访问的数据和在*台上分享新闻的速度而言。我们使用 TwitterScraper 搜索基于位置的目标关键词,收集了 12 个城市 5 年的数据。虽然我们更愿意在这里使用 Twitter 的 API,因为它包括地理位置,但它只提供一个月的历史数据。
为了选择我们的关键词,我们花时间深入了解人们如何在网上谈论权力。我们探索了能源公司和消费者在网上发布停电信息时的词汇差异,确保注意潜在的错误分类(例如:停电是视频游戏,而电力是电视节目)。
为了缩小地区范围,我们选择了美国十大人口最多的城市,但是我们不得不稍微调整一下。纽约市的噪音很大,我们不想用它来训练我们的模型。所以我们把那个城市从我们的列表中删除,加入了人口第十一多的城市,奥斯汀。我们还决定包括底特律和哥伦布,因为根据停电跟踪报告,密歇根州和俄亥俄州的年停电率排名很高。
通过查看我们提取的推文,我们假设天气是停电的最大影响因素。我们使用 NOAA API 包装器按日期提取我们选择的城市的历史天气数据。不是所有的气象站都收集相同的数据,所以我们把重点放在所有州一致收集的数据上,高温、低温和降水。我们根据温度和降雨量的范围将这些数字转换成文字,以便能够将这些文字添加到我们的推文中。我们知道我们想要使用自然语言处理,并且需要单词而不是数字来做到这一点。
探索性数据分析
一旦我们有了一个完整的数据集,我们想检查我们收集的数据告诉我们什么样的故事。为了做到这一点,我们观察了单词的频率。我们删除了常用的停用词,包括提及 Twitter、Instagram 和任何与 url 相关的内容,因为这些都妨碍了我们了解数据告诉我们的真实情况。
在下面的图表中,你会在左边看到前 10 个单字术语,而在右边你会看到多字术语。我们两个都看了,因为它以这种方式讲述了一个更完整的故事。我们并不惊讶地看到“电源”、“断电”和“没有”出现了很多,因为这些都符合我们的目标网络抓取关键字。但是深入挖掘,我们还可以看到,我们引入了许多我们认为是两种类型的信息,客户投诉和能源公司报告客户断电。
Frequency of Words in our Tweet Dataset
我们还发现有趣的是,底特律突然出现在那里,因为密歇根州是每年停电次数最多的州之一。此外,请注意,“互联网中断”在这里显示得很高,这不是停电。它的外观有助于我们识别一个错误分类类型,当我们继续我们的模型时,我们一直记在心里。
造型
基于我们在回顾数据时所学到的东西,我们开始为建模准备文本,将所有单词小写,并删除标点符号和停用词。我们还在标记化之前删除了完整的 url 字符串,以确保我们捕获了所有的 url 片段,尤其是链接缩写。
对于建模,我们选择使用 Word2Vec,因为它关注单词之间的关系,并为该值赋予权重。它将单词选择的上下文带入到游戏中,这将让我们更好地理解在推特上谈论停电时使用的一组单词。
虽然机器理解高维空间没有问题,但在使用 Word2Vec 之后,我们需要使用 t-SNE 模型将其转换回二维空间,以便检查和理解它。然后,我们使用余弦相似度将我们的词与目标关键词列表进行比较,以帮助确定该词是否与合法的停电有关。余弦相似性得分结果被手动检查以发现错误分类并调整我们的模型。
下图显示了 t-SNE 图,我们在图中选择了“龙卷风”这个词。蓝色的点代表与停电有关的单词,而灰色的点则与不合法的停电有关。圆点的大小也显示了它的余弦相似性得分有多高。点越大,分数越大,意味着与其分类的关系越强。这个剧情的交互 html 文件可以在 Github 上下载。
评价
为了评估我们模型的性能,我们必须手动确认它是否被正确分类。理想情况下,我们应该能够浏览所有的推文来证实这一点,但我们没有时间了。我们查看了 1000 条推文,发现了 6 个错误分类。我们需要进行更多的审查,以确认这是否是错误分类的数量或异常情况。从那里我们需要微调模型以减少错误分类。
当我们开始这个过程时,我们认为天气在停电中起了很大的作用,事实也确实如此。然而,我们也发现“蛇”这个词与标记合法断电的高相关。这就是我们如何得知蛇可以爬进变压器并导致停电。如果你对其他导致停电的怪事感兴趣,你应该看看停电跟踪者的年度报告。这是一个有趣的兔子洞。确实如此。
映射
因为我们必须使用一个刮刀来收集 Twitter 数据,所以我们无法提取比城市更详细的位置。把它标在地图上意味着我们会有很多点重叠在一起,这并不理想。但是,我们认为按时间绘制我们选择的城市的停机时间会很有趣。下图显示了一个高亮显示的城市,底特律。你可以看到,根据我们搜集的数据,在 2014 年 1 月,有 24 条与停电有关的推文。这张地图的交互 html 文件可以在 Github 上下载。
结论和后续步骤
总之,我们能够成功地创建一个原型,可以将一条推文归类为合法的停电。但是,在推广它以分类更多数据之前,需要解决它的一些限制。因为我们不得不使用 Twitter scraper,而不是 Twitter 的 API,所以我们的位置数据并不尽如人意。即使我们可以使用 API,也不是所有用户出于隐私考虑都会在他们的 Twitter 个人资料上列出位置数据。此外,准确性评估过程是一个手动过程,在全国范围内推广将需要资源和时间进行审查。
然而,基于实时数据,我们确实看到了更广泛推广的巨大可能性。如果我们有更多的时间,我们会采取并建议考虑以下步骤:
- 在实时数据上测试该模型:来自 Twitter 的 API 的推文和来自 Dark Sky 的 API 的天气数据。
- 使用 K-means 聚类对停电调查结果进行分组,以便能够更好地确认整个区域停电。按地区和天气划分星团也很有意思。我们只使用了我们所有选择的城市一致可用的天气选项,但在这里查看其他选项(例如:风速)的更多细节将是有益的。
- 探索除了 t-SNE 之外的其他维度/数据缩减方法,例如在数据预处理之前使用主成分分析。
该项目的完整代码可在 GitHub 上获得。干杯!
你能根据主客场记录准确预测 MLB 的比赛吗?
原文:https://towardsdatascience.com/can-you-accurately-predict-mlb-games-based-on-home-and-away-records-8a9a919bad29?source=collection_archive---------18-----------------------
拿出工资单,击球率,自责分率,以及任何你能想到的其他数据。让我们用一分钟的老方法:赢和输。
假设你是一个职业体育赌徒,在九月的一天观看两个队的比赛,海怪队对铁坦克队。海怪的胜率是 87–63(. 580%胜率),而坦克的胜率是 40–90(. 267%胜率)。理论上,你似乎会把钱押在海怪身上,让它们碾过坦克,但这里面有一个陷阱。铁坦克以 37–3(. 940 胜率)的主场战绩在主场战无不胜,海怪以 20–40(. 333 胜率)的战绩在客场苦苦挣扎。如果你把钱押在海怪身上,因为你相信他们是整体上更好的团队,你的赌注有多大风险?
这个问题的答案可以用贝叶斯定理。贝叶斯定理用于计算条件概率,这意味着在你知道一些潜在信息的情况下,试图预测一个事件。在这个例子中,你可以对比赛结果做出更明智的决定,因为你知道每个队赢得比赛的总体可能性以及比赛的地点。在这篇文章中,我解决了这些问题:
- 使用过去 4 年的 MLB 数据,使用贝叶斯定理可以做出多精确的预测
- 在这个季节,你可以确定有足够的信息来保证预测的准确性。
- 有没有一种方法来对冲哪些应该下注,哪些不应该下注?
- 与其他机器学习算法相比如何?
和往常一样,你可以在这里查看我的代码:【https://github.com/anchorP34/Bayesian-Baseball-Results
你可以在这里查看我的公共仪表盘:【https://public.tableau.com/profile/payton.soicher#! /viz home/MLBBayesianAnalysis/story 1
贝叶斯定理
为了快速回顾贝叶斯定理是如何计算的,你可以看看左边的公式。在这种情况下,我们可以将 P(A|B)改为 P(W|H ),这将意味着赢得比赛的概率,因为我们知道球队在主场。然后我们也可以用 P(W|A)作为球队客场比赛获胜的概率。现在,让我们插入海怪和铁坦克的信息:
P(W) = Probability of Winning, P(L) = Probability of Losing, P(W|H) = Probability of Winning given the team is at home, P(W|A) = Probability of Winning given the team is away
从这个分析我们可以看出,铁坦克在主场给定战绩有 85.26%的胜算,海怪在客场给定战绩有 40.81%的胜算。由于这两个概率并不 100%匹配,我们可以将它们加在一起,并找到它们在整体匹配中的份额。
Taking the partial winning percentages of both teams can give us a better head to head matchup prediction
我们可以看到,对于这场比赛,即使铁坦克的战绩比海怪差很多,但他们有 67.63%的贝叶斯概率赢得对决。作为职业体育赌徒,你可以利用这些信息,对照游戏的金钱线进行检查,并确定如果你正确预测结果,以 35%的价差(67.63%-32.37% = 35.26%)押注这场游戏的风险是否值得。
美国职业棒球大联盟案例研究
由于每场比赛都可以参考整体战绩,再加上球队主客场表现的记录,你可以认为随着一个赛季的进行,预测的准确性的结果应该会随着时间变好。使用每个团队的最终获胜百分比,我们可以看到我们预测哪个团队会获胜,以及预测结果是否正确。首先,让我们看看随着时间的推移,精确度是否会收敛到特定的结果:
The rolling average of the accuracy of Bayesian probabilities vs time of a MLB season
我对这张图表的最初反应并不是我想象中的样子。我假设准确性的方差在赛季开始时很大,在赛季结束时很小,这是正确的,因为赛季开始时有很多关于球队的未知信息,但赛季结束时应该有很多信息,不会在重要的方向上移动准确性。然而,我认为有了额外的信息,随着时间的推移,预测会变得更好,但事实似乎并非如此。从 5 月到 10 月,预测没有低于 50%,也没有达到 60%,只是在 55%左右徘徊。
虽然它没有惊人的准确性,但全年所有游戏中大约 55%的正确率已经很不错了!这比盲目抛硬币来决定结果要好,但下一个问题应该是在赢和输之间,预测有多糟糕?
Difference in Probabilities (Home Winning % — Away Winning %) and the outcome (Dark Blue is correct prediction, light blue is incorrect prediction)
这是我认为分析最有趣的地方。看一下主队的胜率%与客场胜率%的差异,贝叶斯概率并不是由于赢时的小失误和输时的大失误,它们大致在两者之间。例如,如果你错误预测了很多比赛,如果两队之间的胜率低于 10% (55%比 45%),那么这是可以理解的。但是,如果模型错误地选择了胜率差异很大的游戏(85%比 15%),那就不是一件好事。从图中可以看出,无论预测结果如何,成功和失败的概率分布大致相同。
这是我们看待这个问题的另一种方式。这是正确和错误预测概率分布的盒须图。在理想情况下,正确的预测将具有大的分布,而不正确的分类将具有小的分布。这第一个情节显示在季节的早期。你可以看到很多游戏有巨大的传播差距,有些分类错误,有些分类正确。
Spread Probabilities Box and Whisker Plots of False and True Predictions
然而,如果我们看看 9 月份的比赛,正确和错误预测之间的差距并没有明显的不同,仍然有一些非常糟糕的预测(看看 2018 年的错误预测)。
捆绑机器学习
大多数人在这一点上可能会想“好吧,佩顿,这很有趣,但我很确定机器学习算法会比你的贝叶斯计算好得多。嗯……让我们看看他们是如何搭配的。
Default models for Random Forest, Logistic Regression, K Nearest Neighbors, and Support Vector Machine classifiers
提醒一下,我们的贝叶斯模型每年的准确率为 55%,没有一个测试准确率的机器学习模型达到那个水*。当我在模型中使用贝叶斯结果时,这更相关!即使有一些成功的模型输出的额外帮助,它似乎也没有帮助。我使用测试精度,因为这相当于查看新的预测数据。机器学习模型往往在训练集上表现得更好,因为它可以尽可能接*这些数据点,但在新数据上,它往往不会那么成功。尽管逻辑回归的训练精度最差,但它的测试精度最好,这是有道理的。这个数据集没有任何太深入的东西来做出这些机器学习模型将在哪里蓬勃发展的质量预测,所以简单的贝叶斯模型可能会胜过机器学习模型。
结论
贝叶斯统计可以在进行预测时占上风,但在这样做时应该谨慎。正如我们看到的全年预测的准确性,从 5 月到今年剩余时间,您可以预计大约 55%的预测是正确的,从体育博彩的角度来看,这是一个非常好的长期使用案例。然而,相对于较小的价差,不应该增加对较大价差的押注,因为正确和错误预测的价差金额的方差大致具有相同的分布。
这种分析逻辑可以用于所有类型的运动。由于主客场比赛的样本量如此之小,足球将很难做,但曲棍球和篮球都有足够多的比赛来做出有用的预测。
最后一点是,当你使用像输赢这样简单的数据时,像贝叶斯预测模型这样的简单模型可能是比更复杂的机器学习模型更聪明的选择。机器学习模型在大量数据以及对结果有重大影响的深度数据点上茁壮成长。如果你有一个数据集,它有更多的数据点(谁是投手,天气,连胜,头对头的历史,等等),机器学习模型可能会优于贝叶斯模型。但是,如果你想出一些简单的方法,并且会得到正确的预测多于错误的预测,那么像贝叶斯定理这样的模型是一个很好的选择。
没有量化学位能成为数据科学家吗?
原文:https://towardsdatascience.com/can-you-become-a-data-scientist-without-a-quantitative-degree-8046e254fa48?source=collection_archive---------5-----------------------
Yenthoroto village, Western Province, Papua New Guinea
一个故事和一些见解
我想在这篇文章的开头说,我无意利用这个空间来最小化定量学位在大多数数据科学家的工作和成功中的作用,也不是我的目标是“过度鼓励”(或阻止)任何没有坚实的定量背景但对以数据科学为职业有着浓厚兴趣的人。作为一名来自有人所说的“非正统”背景的数据科学家(我拥有理论语言学博士学位),我觉得自己有资格为那些可能发现自己既被进入一个行业的想法所诱惑又被这种想法所吓倒的人提供一些有用的、潜在可行的见解,这个行业的工作岗位主要提到如下学历:
你的学术背景是在一个定量领域,如计算机科学、计算语言学、数学/统计学、工程学、经济学或物理学。高级学位优先。
相关技术领域(计算机科学、统计学、应用数学、计量经济学、运筹学)的学士、硕士或博士学位。
在高度量化领域(CS、机器学习、数学、统计学)获得学士或硕士学位或同等经验。
你应该在定量领域有广泛的背景。
获得计算机科学、经济学、统计学、物理学或相关领域的研究生学位。
如果你没有这些“高度量化”领域中的一个学位,你是否会立即被取消数据科学家职位的考虑资格?我认为答案是一个令人不满意的“视情况而定”但如果有所帮助的话,我自己的数据科学之路始于任何这些“定量”学术领域的承诺和保证。事实上,当我第一次接触到我很久以后才能够称之为第一次接触“大数据”的东西时,我离任何现代技术都有数千英里远,更不用说花哨的定量分析工具了。
首先,我想分享一个故事。这是一篇独一无二的文章,旨在阐述一位数据科学家的旅程,而不是指导或概括——这部分在故事之后。
Landing on the village airstrip
当我被巴布亚新几内亚南部低地一个遥远的森林村庄的巨大魅力和神秘所吸引时,我是一名三年级的语言学研究生,这里是世界上最丰富的语言多样性的家园,数百种未记录在案或研究不足的语言——有些濒临灭绝——对世界各地的语言学家、人类学家和语言活动家有着不可抗拒的吸引力。在一年多的时间里,我花了几个月的时间在新几内亚丛林中用手持电池供电的录音机收集人类讲话的录音,捕捉这种鲜为人知的语言的歌曲、故事和动词范式,其迷人的形态句法属性和过程后来成为我论文的基础。
My escorts wading the knee-deep water after a flood
到我最后一次去那个村庄的时候,我已经有了将* 20 GB 的数字录音,由于只完成了最少的野外方法课程,并且之前没有接受过语言数据管理方面的重要培训,我有时会努力保护我的数据和设备免受低地雨季的洪水袭击,并且在将它们存档到太*洋濒危语言数字档案馆之前,只能勉强成功地用手转录一小部分录音。(如果你是一个领域语言学家,你的下巴掉了下来,我后来使用了半自动转录和数据管理工具,如 ELAN 和 Toolbox,但老实说,我发现它们太笨重,效率太低,无法与它们建立长期的关系。)
事后看来,我觉得我对这种性质的工作准备不足,但我经历的挑战和困难给了我很多教训,并让我深刻反思我所在领域的方法和途径(下文将详细介绍)。不言而喻,这是我一生中最具形成性、最显著、最丰富的经历之一,回顾这段经历,我既自豪又遗憾(或许改天再讲)。
Ruth and her baby
语言学中数据收集的挑战
幸运的是,我没有感觉到我的理论工作受到处理大量非结构化数据的挑战和限制的太多阻碍——这是我第一次接触“大数据”,除了在非常小的范围内(即千兆字节而不是兆兆字节)。这主要是因为我已经将我论文的范围定义得足够狭窄,围绕着几个重要的语言现象,这些现象恰好符合我当时非常熟悉的类型学文献。因此,我只需要少量的数据——我所收集的一小部分——来发展我的论文,让我和我的论文委员会满意。
与此同时,作为一个使用一种从未被如此少的人描述和使用过的语言的人,我感到被传统的语言学方法论严重束缚,这种方法论本质上是内省的。也就是说,为了构建语言理论,在生成语法框架内工作的语言学家通常依靠母语人士对语言形式和表达的意义和结构的直觉(也称为“语法判断”)。(这与实验语言学相反,实验语言学是语言学的一个分支,它使用定量方法来评估语言学理论,因此与认知心理学和神经科学等领域有联系。)
与此同时,作为一个研究从未被如此少的人描述和使用过的语言的人,我感到被理论语言学的传统方法严重束缚,这些方法本质上是内省的。
在语言内省中,说本族语的人(通常是语言学家本人)有意识地将注意力引向“在他的认知中表现出来的”语言的特定方面。所以基本上,你需要的所有数据都在你的脑子里。您不需要从文件中“读取”数据,也不需要注释成千上万的句子来创建训练集。
一个典型的语言学家的数据集可能包括几对句子,这些句子对目标语言属性的对比最小。例如,如果我们假设以下示例中的 wh 短语( what )已经从其基本位置(由下划线指示)发生了句法移动,则(1a)与(1b)和(1c)之间的语法差异表明,并列结构构成了提取的“孤岛”,即,你不能将名词连词移出并列短语。
约翰买了什么?
(1b)约翰买了什么土豆和 __?
(1c)约翰买了什么 __ 和蘑菇?
这种概括适用于所有的坐标结构——我们可以不通过成百上千的示例数据就得出这种概括。
Children in front of Yenthoroto Elementary School
所以你可以想象当我签约写一篇论文的语言文献的缺乏迫使我采取一种几乎完全自下而上的归纳方法时,我不得不做出的心理调整,在这种方法中,通过结构化启发、讲故事和自然主义语音收集获得的“原始数据”构成了我的语言分析的经验基础。这与我作为生成语言学学生所熟悉的方法形成了鲜明对比:自上而下的演绎方法,在这种方法中,“理论反思可以给我们提供我们应该寻找的新想法”(贝克,凯斯:其原则和参数,2015 年,第 129 页)。
鉴于我正在处理的数据的数量和速度,我无法完全依赖任何一种方法,我开始想知道语言学作为一门实证科学是否会受益于工具和数据科学的更广泛应用——这是我只听说过的事情。正如我所想象的那样,他们的影响将超越为特定品牌的语言学家(即产生大量原始数据的领域语言学家)服务,以帮助实现该领域更广泛的目标,即揭示所有语言的共性及其跨语言差异的制约因素——这是一项肯定需要大量数据的事业——以构建语言能力作为遗传禀赋的广义理论。
鉴于我正在处理的数据的数量和速度,我无法完全依赖任何一种方法,我开始想知道语言学作为一门实证科学是否会受益于工具和数据科学的更广泛应用——这是我只听说过的事情。
我要说的是:我从研究生项目毕业后,感到该领域当前工具和方法的挑战和局限性给我带来了很大压力,这些工具和方法似乎足以服务于自己的研究目标,但在学术界之外的世界中却相对没有什么影响力。这种思考让我开始问,是否有替代的语言研究方法可以为语言学理论提供信息,同时让语言学与世界更加相关。我想,只是也许,数据驱动的方法可以。
毕业后不久,我拒绝了一所文理学院的兼职教授职位,作为一名该领域的完全新人,参加了为期 10 周的大数据和分析课程,从大数据的四个 v开始。我只是想学习。
几年后,我作为一名 NLP 数据科学家在一家成长中的科技公司工作,在那里,我感到自己处于独特的地位,可以为我们的机器学习系统带来语言的严谨性和可问责性,同时在这个过程中学习了大量的技术知识并提高了技术熟练程度。
所以我认为这是一个很好的地方来最终回答这个让你一直读到现在的问题:没有定量学位,你能成为一名数据科学家吗?我确实是这么想的,但我想很快承认,“数据科学家”是一个如今被广泛解释的术语(这是正确的),我认为正是由于这种松散的解释,我才能够在一定程度上提供以下见解。
A Papuan monitor (Varanus Salvadorii), captured and killed
如果你没有定量的学位
1.把自己定位成专家而不是多面手。
Posing with a bush knife
我在上面分享了我的故事,希望它能真正推动第一点:如果你想成为一名数据科学家,你绝对必须能够阐明数据在你的(非定量)领域中的作用,无论是政治学还是新闻学,以及你的领域知识如何为你的组织更广泛的业务目标服务。
如果你有机会向招聘委员会陈述你认为你的研究或行业经验如何影响公司的数据科学应用并产生商业价值,这肯定会有所帮助。不要忘了提及你的领域专业知识如何改进特性工程。准备好传达你是唯一有资格决定构建和提取什么样的特征的人,这是正确利用机器学习算法的能力的必要条件,以及你将如何利用你的领域知识来决定收集什么样的数据,使用什么样的目标标签,以及删除什么样的异常值。
所有这些都等于说,把自己定位为专家,而不是多面手。展示自己是团队现有技能的补充,并强调你作为拼图中“缺失的一块”所能带来的巨大价值。
2.找一个很棒的团队。这很重要。
我几乎把这个放在第一位,因为根据我自己的经验,能够与认识到你的独特价值并真诚希望看到你成功的优秀人士一起工作,是我作为一名年轻的数据科学家感到满意和成长的最重要因素。在带着一种醒悟的状态离开我的第一份工作前不久,我花了大量的时间寻找、研究和面试,不是公司,而是团队,直到我找到了一个我觉得最重要的是存在一种健康、充满活力的文化的公司。
在我入职的两周时间里,我当时的经理意识到我有限的编程技能,安排我每天早上 30 分钟签到,这样我就可以问任何技术问题和/或复习一些我前一天写好的代码。从一开始就提供这样一个结构化、个性化的学习环境,为我在这个团队中创造了一种“安全空间”,让我可以无所畏惧地成为自己——一个在技术领域有发展空间的专家。这些会议的影响持续到我入职后的几周:我仍然觉得问“愚蠢”的 Python 问题非常舒服,因为他们总是得到深思熟虑的回答,从而将他们的状态提升到“聪明”结对编程是被鼓励的,我们可以随意把拉请求的作者拉到一边,让他们用适当的语言解释他们的代码到底在说什么。我为我们作为一个团队建立的尊重文化感到自豪,我真的不认为这是理所当然的。
Children delousing each other
除了他们帮助你在软件工程领域具体成长的能力之外,你的团队也非常重要,因为只有在你的数据科学家同事的工作背景下,你才能找到自己的位置,成为一名特定类型的数据科学家,产生特定类型的影响,包括,这可能需要较少的统计或机器学习知识,更多的其他知识。
您独特贡献的价值通过您整个团队工作的协作和互补性质展现出来。一个数据科学家可能花费大部分时间构建 ML 管道,而另一个则主要从事数据探索或预处理。还有一个可能主要致力于将模型部署到产品中,或者为特性测试建立一个 A/B 测试*台。为同一目标工作的人之间的这种分工反过来会决定每个数据科学家未来从事什么样的项目。
为了更好地理解这一点,下面是一篇非常好的 Medium 文章的摘录,该文章讨论了评估数据科学能力:
我开始认为“好的数据科学”是在个人层面上并不真正存在的东西:虽然单个团队成员都非常擅长某些技能,但建立强大的数据科学能力是任何个人都无法完成的事情。我看到的大多数关于数据科学技能的讨论都没有明确承认这一点。我们所有人的技能都有差距,但是只要团队没有任何差距,那就没问题:这确保我们能够共同做我们需要做的事情,并且仍然给我们所有人留下许多成长的机会。
上面的陈述确实引起了我的共鸣,同时也让我有了正确的认识。如果你的团队以这种以团队为中心(而不是以个人为中心)的心态运作,你缺乏量化学位可以通过以下组合充分弥补:(1)你自己不断发展技术和量化技能的奉献精神,(2)你的队友在协作环境中提供深思熟虑的反馈、指导和方向的能力,以及(3)你的公司致力于改善知识共享系统以推动集体生产力和有效性。**
例如,我经常咨询我的经理和其他更高级的数据科学家,关于首先尝试什么算法,以什么评估指标为目标,以及关注什么超参数,尽管我经常被告知要尝试一切,看看什么最有效!这是一个伟大的赛格威进入下一个点。
3.要知道建模只是数据科学家工作的一小部分。
Preparing to count yams
得知 ML 数据科学家工作中一些听起来最可怕的部分,如算法选择和超参数优化,实际上是他们工作流程中非常小的一部分,我感到非常欣慰。有如此多的工具可以自动化这些过程(以及学习它们的资源),以至于几乎总是有可能在没有数学、统计或机器学习方面的正式培训的情况下实现复杂的算法。
虽然我不否认强大的数学基础在 AI/ML 专家培训中的价值,但我发现真正对数据科学应用的实际开发产生最大影响的是他们通过试错经验获得的直觉,而不是他们所受的*教育。*****
另一个相关的观察结果是,一个高效的数据科学家投入大量的时间和精力在构建一个强大的通用* ML 管道上,这样那些需要参数化的元素,比如超参数调整、特性转换器需求和模型选择,就可以自动且轻松地重复。好消息是,当您加入团队时,这样的管道通常已经为您构建好了,或者如果您幸运地需要构建一个新的管道,有许多 ML 库可以支持这种努力。*
以下是使用 scikit-learn 构建 NLP 管道的两个示例指南:
*** [## 如何使用 Scikit-Learn 构建可重用的自定义 NLP 管道
重点是功能工程和培训
towardsdatascience.com](/how-to-build-a-reusable-nlp-code-pipeline-with-scikit-learn-with-an-emphasis-on-feature-504f8aa14699) [## 基于 Scikit-Learn 流水线的文本特征提取
使用 2010 年初选辩论记录
towardsdatascience.com](/the-triune-pipeline-for-three-major-transformers-in-nlp-18c14e20530)
作为一名数据科学家,我成熟的一部分是接受这样一个现实,即依靠“理论思考”来执行 ML 任务是很尴尬的,并学会每当有人告诉我“试一试,看看性能是否有所提高”时不要畏缩。我开始认识到,由于我们拥有的自动化工具,这种试错法实际上是我们可以使用的,其核心是不断进行实验,这是每一项发现和创新背后的力量。
4.你必须编程——你可以做到。
这最后一点与最后一点密切相关。如果你是数据科学家,你必须编程。这是无可避免的。数据科学管道的每个阶段都需要它。从数据接收开始,您必须以编程方式读取文件、设置 ETL 管道、查询数据库等。对于特征工程,你需要使用 ML 包应用特征选择技术,为特征提取编写手动函数,等等。对于建模,您需要配置算法和参数,执行网格搜索,挑选最佳估计器,等等。诸如此类。
也就是说,我想给你留下一些关于数据科学编程的令人鼓舞的评论:
- 拥有一个量化的学位与拥有编程技能是完全正交的。换句话说,没有量化学位并不会妨碍你成为一名优秀的程序员。大多数有能力的程序员是在工作中而不是在学校里学会如何编写好程序的。不管你的学位如何,你都会遵循同样的轨迹。
- 你不必理解整个代码库来完成你的工作。我认为你可以从很小的事情开始,例如,为你团队的代码库贡献一个脚本,甚至一个函数——然后从那里开始。我开始在我团队的代码库中小的、不连贯的部分工作,花了几个月的时间,我才能够开始看到我的代码如何融入更大的结构。我仍然没有一个完整的视图。这完全没问题,也不会妨碍我每天的工作。
- 核心编程概念确实是有限的,并且在不同的语言中是相当不变的,在开始的时候,你只需要很好地了解这么多事情就可以胜任你的角色。如果你在 Python 中工作,你应该对它的五六个数据结构了如指掌,并且能够自如地操作它们,编写函数和创建对象——而其他的一切都是建立在这些有限事物之上的。在那之后,前 10 名左右的数据科学库,如 Numpy、Scikit-Learn、PyTorch、TensorFlow、Pandas、Matplotlib、Seaborn 等,将会拯救你。导入它们,让它们为你做艰苦的工作。
Everyday garden work
总之,还是申请吧。
出于某种原因,在我写这篇文章的时候,一个统计数据不断浮现在我的脑海中:
女性只有在百分百合格的情况下才会申请工作。另一方面,男性倾向于在只有 60%合格的时候申请。
这句话摘自惠普公司的一份内部报告,在互联网上被重复了无数次,道出了该行业性别差距的严峻现实。我知道这个话题完全超出了这篇文章的范围,但我觉得最终必须把它包括进来,因为我想,你知道,这篇文章毕竟是关于资格的。
请记住,数量学位是一种资格,并不是每个成功的申请人都符合工作描述中的每一项资格。如果你是女性或男性,如果你在工作岗位描述的其他领域合格,不要让学位要求阻碍你申请。换句话说,如果你有 60%的资格,就去申请。你真的永远不知道一家公司会在候选人中寻找什么最最 T21 的人。
总而言之,如果你想进入这个行业,但没有定量学位,无论如何都要申请,一旦你接到招聘人员的第一个电话,
- 将自己定位为一名专家,能够清楚地说明你的领域知识如何服务于组织的业务目标,尤其是通过改进特征工程。
- 花时间寻找一个可以帮助你成长的优秀团队。作为一名数据科学家,整个团队对彼此的承诺及其文化的健康对你的成功至关重要。发展对数据科学家角色的多元化理解,以及承认伟大的数据科学是团队合作,而不是最好的数据科学家的工作,对于组织的成功和发展至关重要。
- 不要被数据科学工作中听起来吓人的部分吓倒,比如“建模”和“优化”。它们不是数据科学家的主要工作,这些过程通常归结为能够利用现有的库来构建可重用的 ML 管道(或者使用现有的管道)来帮助你完成核心的 ML 任务。
- 毅力,而不是 CS 学位,会让你成为一名优秀的程序员。记住编程技能是通过时间和经验发展和 完善的。
谢谢你让我分享我的故事。祝你好运,一路顺风!
An aerial view of Western Province***
抽样分布,重点是吉布斯抽样,实践和代码
原文:https://towardsdatascience.com/can-you-do-better-sampling-strategies-with-an-emphasis-on-gibbs-sampling-practicals-and-code-c97730d54ebc?source=collection_archive---------14-----------------------
Image by Author
继上一篇关于用 bootstrap 重采样估计置信区间的文章之后,我想简要回顾一下如何估计没有封闭解的复杂后验分布。贝叶斯推理就是一个很好的例子。这里,一个提示帮助来自采样。
我们要解决什么?
可以说,贝叶斯推理最难的部分是后验估计,多年来,贝叶斯推理一直把这个领域蒙在鼓里。在早期(在高计算能力出现之前),计算后验概率的方法通常依赖于某种*似(例如拉普拉斯*似)或数值积分。然而,随着计算机的发展及其增强的内存和速度,采样方法开始获得动力:从实践中落后的非常简单的方法(反转采样)到更复杂的方法,如 Metropolis-Hasting (MH)算法,该算法被列为 20 世纪影响科学和工程发展的十大算法之一。
当开始阅读该主题时,最常见的问题是采样如何帮助估计后验概率,以及它与积分有什么关系?
抽样的关键思想是从感兴趣的分布中生成值,然后应用离散公式来计算必要的统计数据。根据大数定律:,考虑一个计算分布期望值的例子
这里一个复积分被一个离散的公式所代替,只包括原始函数 f(x)。这让我们想到了蒙特卡罗方法(或蒙特卡罗实验)——一类依靠重复随机采样来获得数值结果的计算算法。这里讨论的采样算法属于蒙特卡罗方法的范畴
在写这篇文章的时候,我有机会修改了最常见的采样算法,并找到了几个链接,感兴趣的读者可能会觉得有用。下一章是对采样算法的快速回顾。那些只对吉布斯采样感兴趣的人可以跳过它。
取样策略,概述
这里我简单解释一下常用的抽样方法:倒置抽样、拒绝抽样和重要性抽样。那些只对吉布斯采样感兴趣的人可以跳过这一节。
倒置取样
给定任何累积分布函数 F(x ),可以按照以下步骤从其生成随机变量:
- 从均匀 U~[0,1]生成样本
- 为 x 求解 F(X)=U,或者等价地求出 X = F^(-1)(U).
- 返回 x。
Figure 1: Inversion sampling. Image by Author.
这里,我们按照均匀分布对 y 轴进行采样。当 x,f(x)的概率较低时,cdf F(x)将是*坦的,即从均匀分布中抽取的样本不太可能落在曲线上。x,f(x)概率较高的区域倾向于*行于 y 轴,这意味着均匀分布的样本很可能落在 y 轴上。
为什么不在实践中使用?
求 cdf 的逆可能是复杂的,如果 cdf 不可用,积分仍然是找到它所必需的,所以我们回到原始问题。
延伸阅读
反转采样的另一个例子在这篇文章中给出。
拒绝抽样
拒绝采样允许从分布中采样,已知比例常数,但是太复杂而不能直接采样。
为了使用拒绝抽样,需要有一个简单的建议分布 q(x ),从中可以抽取样本。还选择常数 k,使得分布 kq(x)总是包围或覆盖所有 x 的分布 p(x),我们从分布 kq(x)中采样,如果 ukq(x(i)) < p(x(i)) accept the sample, here u is coming from a uniform distribution.
Figure 2: illustration of rejection sampling. Image by G. Pilikos.
为什么可能不工作?
使用剔除取样时会面临几个问题。首先,由于 k 控制建议分布对感兴趣的分布的覆盖,所以需要找到 k,它不需要过多的采样,并且 q(x)几乎不覆盖 p(x)。因此,在采样的覆盖和冗余之间有一个由 k 控制的折衷。通常,甚至不可能找到正确的 k 或建议分布来覆盖兴趣分布。
延伸阅读
我发现这篇文章在回顾剔除抽样时非常有用。它有代码和很好的图形来显示正在发生的事情。
重要性抽样
与前面讨论的方法不同,重要性抽样用于直接逼*函数 f(x)的期望值。该方法与拒绝抽样非常相似,也需要一个建议分布。我不会说太多的细节,但是,更多的细节你可以看看这篇文章,我发现它非常有用。
吉布斯采样
上述所有方法在低维时都是有效的,然而,当维数增加时,用这些方法采样就成问题了。需要使用不同种类的方法。这类方法基于马尔可夫链蒙特卡罗(MCMC)。马尔可夫链是一个随机过程,在给定当前状态的情况下,未来状态独立于过去状态。当不可能从 p(x)中提取样本,而只能评估 p(x)直到一个归一化常数时,使用 MCMC。关于马尔可夫链我就不赘述了,不过,有兴趣的读者可以在这里找到很好的解释。
Gibbs sampling 是马尔可夫链蒙特卡罗采样器,是一族Metropolis-Hasting(MH)算法的特例(简化情况)。Metropolis-Hastings (MH)算法是最流行的 MCMC 采样器,许多实际的 MCMC 采样器可以解释为 MH 算法的特例。以与拒绝和重要性采样类似的方式,它需要一个建议分布 q(x ),并涉及给定当前状态的候选 x 的采样。也就是说,从 q(x(i+1)|x(i))中抽取新的样本,即给定当前状态。然而,该样品不能保证被接受。类似于拒绝采样,只有当条件满足时,我们才移动到 x ,否则我们停留在当前状态并尝试新的样本。在区间[0;1],然后与 A(x(i+1),x(i))进行比较,其定义为:
Acceptance probability for the MH algorithms.
我就讲到这里,不过,如果你对 MH 算法的更多细节感兴趣,你可以看看这里的。这一步要注意的是,对于吉布斯抽样,接受概率总是 1。除此之外,它与 MH 采样器非常相似。
Gibbs 抽样的思想是将高维联合分布的抽样问题分解为低维条件分布的一系列样本。这里,我们通过扫描每个变量(或变量块)来生成后验样本,以从条件分布中采样,并将剩余变量设置为其当前值。显然,我们能否抽样取决于我们能否导出条件后验分布。下面给出了算法。
Alg 1: Gibbs sampling.
这个过程一直持续到收敛(样本值具有相同的分布,就好像它们是从真实的后验联合分布中采样的一样)。因为我们用随机值初始化算法,所以在早期迭代中基于该算法模拟的样本不一定代表实际的后验分布。这被称为预烧期。
为什么会有用?
假设我们想从 p(x,y)的联合分布中取样,然后,应用概率规则,我们可以在 p(x|y)或 p(y|x)的条件下导出 p(x,y)的关系。
通过在 x 和 y 之间交替,我们可以从原始的联合分布中取样。
例子
这里我考虑两个例子,在第一个例子中,我们想使用 Gibbs 抽样来估计 1D 高斯的矩。然后,我将考虑同一个例子,但有一个更复杂的情况——多元高斯分布。对于这两种情况,我都提供了一个 jupyter 笔记本 和代码。
1D 高斯
考虑一个经常发生的例子,我们有一些数据,比如说工人上班迟到的时间。这些数据看起来与正态分布的数据非常相似。作为一个贝叶斯主义者,你决定开发一个模型。这里你要估计均值和标准差。给定数据的*均值和方差的全概率模型如下所示:
这里我们有 X 给定均值和方差乘以它们的联合先验的可能性。假设独立,先验可以拆分。理想情况下,我们希望有一些信息性的先验,但是事先没有信息的情况下,采用参数 a 和 b 都趋向于零(这将产生 1/方差的先验)的方差和均值方差较大的正态分布。
Inverse gamma prior for variance (top) and normal for mean
然后我们可以展开高斯分布。因此,似然项可以写成如下形式:
要获得*均值的后验概率,首先,将所有观察值相乘,然后展开二次项,消除相对于恒定的项,并首先用均方项重新排列这些项。对方差采取类似的程序。这产生了均值的后验概率,以方差和数据为条件,方差也类似,以均值和数据为条件:
Posterior of the mean
Posterior of the variance
在示例中,我们从*均值为 2、标准差为 5 的正态分布中生成数据。经验*均值为,标准偏差为 2.1,标准偏差为 4.959。我们可以通过在两者之间交替来应用吉布斯采样,得到下面的估计值 mean = 2.094,std = 4.932。
Figure 3: Mean and Variance evolving over time for 1D Gaussian, distribution of the data and estimated model. Image by Author.
2D 高斯
使用 1D 高斯扩展该示例,我们可以从联合分布开始,导出给定数据的均值和协方差矩阵的后验概率:
以均值和数据为条件的协方差矩阵的后验分布遵循具有 n 个自由度的逆 Wishart 分布,并且给定协方差矩阵和数据的均值遵循正态分布:
我们用 1 和 3 个均值、2 和 10 个标准差和 0.9 个协方差对多元高斯数据进行采样。经验均值分别为 1.01 和 2.98,吉布斯抽样估计值分别为 1.00 和 2.98。经验标准差和协方差分别为 1.95、10.07 和 0.85。吉布斯抽样估计那些有 1.95,10.22 和 0.95 的。
Figure 5: Estimated distribution and the data, evolution of covariance. Image by Author.
Figure 4: Evolution of means standard deviations. Image by Author.
利弊
使用吉布斯采样的缺点包括:
- 收敛时间长,尤其是随着数据维数的增加。收敛时间也取决于分布的形状。
- 很难找到每个变量的后验概率。
- 一般而言,来自链起点的样本(预烧期)可能无法准确代表期望的分布。因此它经常被丢弃。也可以使用稀疏化——即保持马尔可夫链的每第 k 个样本。
然而这些往往被压倒,记住,MH 算法被评为 20 世纪影响科学与工程发展的十大算法。
进一步阅读
与许多其他抽样策略不同,吉布斯抽样需要了解几个领域,因此,可能需要进一步阅读概率的基础知识。在准备这篇文章的时候,我从林奇的社会科学家应用贝叶斯统计和评估简介中找到了有用的第 4 章。这本书是用通俗易懂的语言写的,第一章解释了基本知识。罗切斯特大学的笔记中还有另一个吉布斯抽样的实际例子。你可能也想在 stats stackexchange 上阅读这个回复。
本文的 jupyter 笔记本可从这里获得。
喜欢作者?保持联系!
我错过了什么吗?不要犹豫,直接在 LinkedIn 或 Twitter 上给我留言、评论或发消息吧!
[## 置信区间:参数和非参数自助重采样
制作一个好模型需要花费数天时间。但是一旦模型在那里,一个狡猾的问题潜伏在里面:“它能告诉我什么…
towardsdatascience.com](/a-note-on-parametric-and-non-parametric-bootstrap-resampling-72069b2be228) [## 面向大规模偏好聚合的数据集融合
融合评分和排序数据集的高效简单的概率框架。示例和代码。
towardsdatascience.com](/dataset-fusion-sushi-age-and-image-quality-and-what-the-hell-do-they-have-in-common-814e8dae7cf7) [## 成对比较的主动采样
如何配对玩家,以便在尽可能少的游戏中知道排名,同时游戏体验质量…
towardsdatascience.com](/active-sampling-for-pairwise-comparisons-476c2dc18231)
你能增强吗?—使用 1 幅训练图像进行图像恢复
原文:https://towardsdatascience.com/can-you-enhance-that-image-restoration-with-1-training-image-b54989a57b4d?source=collection_archive---------13-----------------------
我为学习者写了一份名为《强大的知识》的时事通讯。每一期都包含链接和最佳内容的关键课程,包括引文、书籍、文章、播客和视频。每一个人都是为了学习如何过上更明智、更快乐、更充实的生活而被挑选出来的。 在这里报名 。
电影太棒了。但是计算机视觉可以让它们变得更棒——呃(我们就把它变成一个单词)!
电影使用计算机视觉进行各种各样的事情,如动作捕捉、特效和计算机生成图像(CGI)。最常见也是最老套的用法之一是“你能增强它吗?”在动作片里。这通常是一些美国联邦调查局/中央情报局/酷特工在看着他们正在追捕的人的照片时说的。图像失真,很难看到,所以他们告诉技术人员“增强”,这样他们就可以看到坏人的脸。这种“增强”效果在电影中看起来相当激烈,几乎就像戴上一副眼镜,没有它你什么也看不见!
但是你可能已经猜到了,这并不总是像电影一样简单!人工智能(AI)和计算机视觉还没有达到那个地步,但我们越来越接*了。
通常,当我们训练一个深度神经网络进行那种图像恢复时,我们需要训练数据……大量训练数据,大约有数千甚至数百万张训练图像。由于训练数据的获取在时间和金钱上都很昂贵,这使得个人和组织都很难建立健壮的图像恢复系统。
幸运是,大规模训练数据集的成本和需求有望降低。最*的计算机视觉研究,称为 深度图像先验 将帮助我们解决这个问题。
具有深度图像先验的图像恢复
标准的图像恢复流水线如下工作。我们收集一个大数据集的损坏和未损坏的图像对;简单来说,这基本上是难看的和好看的图像对。接下来的想法是训练一个深度网络来学习坏图像和好图像之间的映射。一旦经过训练,网络应该已经很好地了解到,当你给它一个糟糕的图像时,它应该输出一个同样图像的更好的版本:更清晰,更锐利,更美观。
这些网络很容易训练。使用 Keras、TensorFlow 或 Pytorch 在 Python 中对它们进行编程非常简单,我们使用简单的均方误差作为损失函数,定义如下
其中 n 是训练集中图像的数量,Y 是地面真实好图像,Y-hat 是网络预测的好图像。传统上,训练网络需要收集大约无数的训练图像,然后等待网络完成训练很长时间。
这就是深度图像优先的用武之地。作者仅使用一个损坏的图像来训练他们的网络。网络的输入是被破坏的图像,输出是同一个被破坏的图像。我们训练网络来优化这种预测其自身输入的映射。
那么,这为什么会奏效呢?以下是作者的巧妙观察。
当我们试图恢复一幅图像时,我们实际上是在试图*衡两件事:(1)使我们被破坏的图像不那么被破坏,例如通过减少噪声;这使得图像看起来更自然,因为它是无噪声的(2)仍然保持整体图像结构。
例如,如果我们想消除输入图像中的所有噪声,我们可以从技术上使输出图像全黑;全黑图像没有任何噪声!但是我们不仅仅是想去除噪声,我们还想保持图像的结构;如果我们的输入图像是一辆汽车,我们仍然希望输出看起来像同一辆汽车,只是去掉了噪声。
均方误差函数将确保图像结构得到保持,并且我们的汽车看起来仍然像一辆汽车,因为当像素与地面真实情况相似时,误差将很小。
为了消除噪声并使图像看起来自然,我们实际上可以利用深层网络的结构来迫使输出自然。作者指出,他们观察到网络本身的结构驱动输出自然,无污染的图像。这篇论文的总体本质是,卷积神经网络(CNN)在某种程度上像自然图像,或者至少偏向于自然图像。
所以当你进行训练的时候,选择你想要恢复的任何一个被破坏的形象。把它作为你的单一训练图像,既作为输入又作为基础事实。你的误差函数是预测图像与你的地面真实(与你的输入相同)之间的 MSEMSE 负责维护图像结构。由于我们的网络倾向于输出自然图像,我们可以相信它会输出我们想要的无噪声图像。当只使用一个单个图像进行训练时,请查看以下不同恢复任务的一些结果。
Examples results from Deep Image Prior. (This image is borrowed from the official Deep Image Prior project page, for educational purposes)
代码
感谢 AI 社区中开放源代码思想的美丽,在这里有一个公开可用的深度图像优先实现!这是你如何使用它。
首先克隆存储库
git clone [https://github.com/DmitryUlyanov/deep-image-prior](https://github.com/DmitryUlyanov/deep-image-prior)
安装所需的库
pip install numpy
pip install scipy
pip install matplotlib
pip install jupyter
pip install scikit-image
pip install torch torchvision
这里不需要任何预先训练好的模型,因为只用一张图片训练会超级快!
像这样启动 Jupyter 笔记本
jupyter notebook
现在,您可以选择一台笔记本电脑来完成您想要尝试的任何一项任务!笔记本超级短,好用!如果您想要恢复您自己的损坏的映像(并将其用于训练),那么您将想要用您自己的映像替换 net_input 数组。读入损坏的图像并将其传递给 net_input 。
瞧啊。只有 1 幅训练图像的图像恢复!
喜欢学习?
在推特上关注我,我会在那里发布所有最新最棒的人工智能、技术和科学!
你能比电脑更快找到沃尔多吗?剧透:不能。
原文:https://towardsdatascience.com/can-you-find-waldo-faster-than-a-computer-spoiler-you-cant-ff382e601c31?source=collection_archive---------5-----------------------
用计算机视觉检测物体
仿佛就在昨天,我还在一位数的年纪,在飞机上和教堂里用充满随机记忆和活动游戏的书自娱自乐。最具代表性的是《沃尔多在哪里》的巨幅插图;我甚至一直和我的朋友和家人比赛,看谁能更快找到他。
我不得不说,在所有的练习之后,我变得相当不错。这并不像看起来那么简单。你可能会认为一个穿着蓝色裤子和条纹衬衫的瘦子很容易被发现,但事实并非如此!
Did you try to find Waldo? Even if you did… your time was up a long, long while ago. Too bad! If only there was something you could do to be faster…
这项运动的重点是速度、注意力和集中。它应该让孩子们主动思考,锻炼他们的大脑肌肉。“准备上学”,或者别的什么。
但是如果我告诉你你不需要这些就能在游戏中获得成功呢?
看,另一部分是胜利。是的,我知道,我已经听到了关于“最重要的是玩得开心!”但是听着。从技术上讲,想出有效策略的人是最稳定的赢家。 那就是你想成为的家伙!你所要做的就是智胜他人(显然,没有作弊),你就成功了。而这其实也适用于生活中的大部分事情。因为“沃尔多在哪里”没有真正的规则,除了你必须是第一个找到他的人才能赢,所以每次你都可以选择不同的道路来成为第一个。
如今的孩子们也能接触到如此多的科技产品——是时候让他们用这些产品做点好事了。关键是,电脑比你聪明。这是因为当他们看一张非常复杂的图片时,他们可以一下子看到整个事情,并在几秒钟内找到瓦尔多。
作为人类,我们没有能力拥有这种处理能力,除非你通过基因改造让自己变得异常聪明(这并不完全不现实……但那是另一回事了)。反正你电脑的能力超过了人类。这到底是怎么发生的?
计算机视觉:能看见的技术
你的普通博客们对计算机视觉的看法可能是,计算机有一双超级眼睛时刻监视着你,就像你的网络摄像头里的联邦调查局一样。但这是错误的。也许有一天…
对象检测(作为计算机视觉的一个分支)实际上是指计算机能够解释数字图像或视频的内容,而无需您手动输入这些信息。这项技术可以分解图像的不同部分,并找出存在的对象。这是面部识别的动力,就像你在 iPhoto 中的家人和朋友一样,并将罪犯与安全镜头进行匹配。
计算机视觉不仅仅是能够看到正在发生的事情,而且能够理解它。
YOLO……但这不是你想的那样
你只看一次,又名 YOLO,是一个实时检测物体的系统。不骗你,当我第一次知道 YOLO 不是“你只能活一次”时,我很失望,但一旦我知道了什么是真正的 YOLO,我保证它会有趣和酷一百万倍。
该系统不同于经典模型(例如快速 R-CNN ),因为您不会对图像上的相同区域进行多次预测,而是在单个回归问题中将数据集通过完全卷积神经网络(FCNN)仅一次。
以下是 YOLO (V3)模型的工作原理:
- 网格:图像被分成一个 S x S 网格(你可以从左边的图像中看到)。这是为了把不同的部分分解开来,让图像作为一个整体被“阅读”。如果一个物体落在一个网格的中心,该网格负责检测该物体。
- 包围盒:整个图像的特征作为一个整体被用来确定包围盒,它基本上只是物体可能所在位置的轮廓。值得注意的是,它们覆盖了图像的每个部分,并且与重叠。它也更有可能比电网本身更大。想象一下,你正在努力寻找藏在床罩下的手机——你床上不同突起的轮廓就是你的边界框!
- 置信度得分:置信度得分表示模型预测的实际存在程度。它基于宽度、高度以及对象中心相对于单元格边界的位置。这是当你在看床的不同块(边界框)的尺寸时。你将手机的大小与肿块的大小进行比较,然后基于此确定你认为你的手机实际上有多少。
- 条件类概率:这些是以包含对象的网格单元为条件的概率。使用以前的 YOLO 模型,每个网格单元只能预测一组类别概率。由此,你可以区分不同的物体(见上图底部)。但是 YOLO V3 对每个类使用独立的逻辑分类器。这基本上可以让你对一个相同的物体有多个标签:计算机找到瓦尔多,他被贴上“瓦尔多”、“人”、“男孩”的标签。
下面是如上所述收集和解释数据的一段代码(它还记录了物体被检测到的速度!):
这只是代码的摘录。我用 YOLO V3 编写了一个完整的物体检测模型,你可以在这里找到的链接。
This is the architecture of the model — you can see the different layers.
操纵数据
由于单一回归,客观性和分类的损失需要单独计算——但仍在同一个网络中。你通过逻辑回归得到你的客观性分数:1 表示边界框和地面真实对象(图片实际上是什么)完全重叠。该模型将仅预测 1 个这种类型的包围盒,但是误差将受到客观性和分类损失的影响。
YOLO (V3)模型也以 3 种不同的尺度预测盒子,以支持尺度变化。看起来会像这样:
为了测试该模型,我们必须将条件类概率与单个盒子置信度预测相乘。这个等式返回一个类在盒子中的概率,以及预测的盒子与对象的匹配程度。
下面是另一段代码摘录,它加载了预先训练的对象名称类,以及它如何处理数字图像的不同帧的编写/注释:
你只看一次(YOLO V3)模型的输出如下图所示。你到底想从这个模型中得到什么,以及如何在不同的应用中使用它,比如道路地图,这一点非常清楚。
现在我希望你明白为什么找到沃尔多会这么容易!你甚至不用看第二遍…
我们为什么使用它
- 它被认为是实时的,因为它很快——每秒钟能够捕捉 45 帧。还有一个速度更快、架构更小的版本,每秒可以捕捉 155 帧,但精度较低。
- 所使用的 FCNN 可以理解和使用通用对象表示的功能。你可以使用真实世界的图像和艺术品来使用和训练它。
展望未来;胸怀大志
这项技术已经过了初级阶段:人们在日常生活中使用计算机视觉。越来越多的技术正在该领域发展,这是令人兴奋的,因为它有如此多样的现实世界应用。
将物体检测软件与语音反馈结合起来也是非常强大的。今天它已经被使用了——人们只是不知道它的存在。失明的人将能够获得对他们周围环境的描述,不必太依赖他们所有的其他感觉,24/7。他们甚至会开车!虽然,我不确定当我们有自动驾驶汽车时,这有多必要!
另一个可能的用例是对大型零售店或杂货店的库存进行分类、确定和辅助。在处理外部伤口、骨折、斑点或损伤时,医疗诊断也可以从中受益。但最重要的是,是技术帮我找到了沃尔多!
不管怎样,这个领域有着惊人的潜力,我迫不及待地想成为未来的一部分。
让我知道你的想法!
关注我上 领英 和 中 了解更多。
感谢来自 GitHub 的 Ayoosh Kathuria 和 Aviv Sham,以及来自华盛顿大学、艾伦人工智能研究所和脸书人工智能研究所的 Joseph Redmon、Santosh Divvala、Ross Girshick 和 Ali 法尔哈迪发表的论文,您可以在此处找到。
你能在 15 分钟内把你的杂货送到吗?
原文:https://towardsdatascience.com/can-you-have-your-groceries-delivered-in-under-15-minutes-14f7b3b3f714?source=collection_archive---------26-----------------------
针对快速交货的快速模拟和优化研究。
Instacart、Amazon Prime now、Farmstead 和更多送货领域的初创公司正在解决非常有趣的供应、需求、模拟和物流优化问题。早在 2018 年,我的联合创始人王维基和我就想验证一个激进的杂货配送想法:让杂货在 15 分钟内送达,对用户来说没有配送成本。
这听起来几乎不可能。这个想法是将 SKU 放在一辆卡车上,在附*盘旋,集中响应需求,而不是众包交付。
显然,要验证这个想法,还有很多问题需要讨论:
- 这种服务的需求有多大?
- 要在 15 分钟内交付,您需要做些什么?
- 您如何选择最佳的 SKU 来响应这种需求?
- 有多少需求会使这有利可图?在当前的路况下,你真的能满足这种需求吗?
- 还有更多…
所有这些都是非常有趣的问题,但我想把重点放在本文的第二个问题上,因为它有点容易快速模拟,看起来也很有趣。你可以在这里找到这个帖子的代码。
要在 15 分钟内交付,您需要做些什么?
让我们想象一下这种情况。我们有一辆卡车负责服务一个区域(比如说诺布山)。假设这辆卡车有无限的 SKU 供应来响应任何杂货请求。我们的模拟将产生随机需求,并让我们的卡车在一个选定的社区为该需求服务。我们试图回答的主要问题是:
尾部交货时间看起来像什么
- 不同的需求体系
- 白天不同的交通状况。
我们希望有尾部交付时间(用户等待接收杂货的最长时间),因为这将决定我们为卡车选择的邻域边界。这反过来可以与现实生活中邻里产生的需求进行比较,以了解这是否是一个现实的商业模式。为此,我们需要为模拟生成数据。我们来讨论一下,数据生成,模拟和可视化。
生成数据
我们可以想象白天有统一的需求,交通也是一样的。这将是最好的情况,因为我们的卡车将全天得到充分利用。我们将选择我们的区域,以便卡车可以在一小时内响应请求,这些请求之间的距离在 15 分钟以内。
Number of requests for each hour (random draws from uniform demand)
不幸的是,现实生活更具挑战性。在现实中,我们可以很容易地想象需求将呈三角形分布:在高峰时间(下午 5 点到 8 点)将有 n 个订单,在上午 10 点有 m 个订单,其中(m<
Number of requests for each hour (random draws from triangular demand)
除此之外还有路况。高峰需求时间的交通状况可能会更糟。幸运的是,我们有一个很好的数据来源。谷歌地图距离矩阵 API 。基本上,我们可以批量获取一天中选定小时的点到点旅行时间。
假设我们正在模拟拉斐特公园区域。我们首先生成均匀分布在定义区域上的请求点。
grid_lafayatte = create_grid(
37.7886685, 37.7939118,-122.4343621,-122.4223142,
step_size = 0.0015)fig = gmaps.figure()
marker_layer = gmaps.marker_layer(grid_lafayatte)
fig.add_layer(marker_layer)
display.display(fig)
Demand points per block for Lafayatte park area
如果我们可以打包一个好的步长,比如说每个块 1 个点,我们可以有把握地假设将该块的所有需求集中到该点不会使模拟偏离现实太远。
现在我们有了这些点,我们可以从谷歌地图距离矩阵 API 中获得它们之间的旅行时间,并获得在一天中特定时间到达该社区某个地方所需时间的图片。
我们通过对该邻域内所有点到该时间点的旅行时间进行*均来实现这一点。
Average travel times from all points to all points by hour of day
距离矩阵的结果和我们预期的一样。上午 9 点在拉斐特公园逛一圈*均需要 5 分钟(300 秒),到晚上 9 点就下降到 4 分钟。特定的路线会比*均拥挤,我们将在模拟中看到它们的效果。
模拟
现在,我们有了进行模拟研究所需的数据。这是模拟地*线的样子
每一分钟
- 根据给定的需求分布(如果有)从任意点提取需求。
- 卡车根据其使用的算法满足需求。我们可以选择先进先出,最*的优先,或者更复杂的。
下面是一个简单的先进先出卡车类的样子
Truck class for simulation
然后,我们用循环进行模拟。
Simulation loop
形象化
虽然我们不需要花哨的可视化来获得我们想要的结果,但我们将使用服务于地图上的请求点的卡车作为一种调试方法,以确保一切正常工作。
Fast and sloppy visualization (updates every 2.5 mins in simulation time
热图风格点是卡车,需求像大头针一样冒出来。我们不模拟卡车在道路上行驶,但在模拟中会进行计算。当卡车到达请求点时,我们只需将卡车位置更新到请求点。
结果
我们想知道随着需求的增加,尾交货时间什么时候变得太长。
Histogram of delivery times for a total of 27 orders
对于 Mission Bay 和 Portrero Hills 地区,对于每天生成 27 个订单的三角形需求曲线,我们有上面的交付时间直方图。基本上,所有订单都在 30 分钟内送达,3 个在 5 分钟内送达,14 个(9+2+3)在 10 分钟内送达。如果我们通过改变需求参数来增加每天的订单数量,我们会得到如下结果:
Histogram of delivery times for a total of 45 orders
哇,45 个订单,事情变得很糟糕。现在我们只有 13 个订单在 20 分钟内送达,最糟糕的情况是人们等了 2 个多小时。所以,如果我们要为 45 个订单服务的话,15 分钟以下的交货在这里似乎不行。但是这种断裂发生在哪里呢?换句话说,在我们开始让人失望之前,我们可以服务多少订单。
为此,我们针对不同的需求参数运行模拟,并查看第 90 个百分位数的交付时间。对于上述情况,我们将
27 个订单-> 90%到 25 分钟
45 个订单-> 90 %~ 120 分钟
90th percentiles for different # orders per day
正如我们所看到的,该地区在接到 35-40 份订单后出现了大幅增长。请记住,这是最简单的卡车算法(FIFO ),我们假设的是硬需求分布。尽管如此,有趣的是,使用这种型号,我们可以为几乎所有人提供 25 分钟而不是 15 分钟的送货服务。(对于每天产生少于 35 个订单的社区)
希望你喜欢,请检查代码,如果你发现任何错误/问题或有任何建议,请让我知道。
能从性格测试结果预测性别吗?
原文:https://towardsdatascience.com/can-you-predict-gender-from-personality-test-results-e1b06828627c?source=collection_archive---------27-----------------------
这个月 reddit 上弹出了一个有趣的机器学习分类问题。一名用户发布了来自 openpsychometrics.org的的免费人格测试结果,该用户声称他们成功预测了回答者的性别,准确率高达 80%。我决定接受挑战,看看我还能从数据集中找到什么有趣的东西。
总结(剧透)
- 根据一个人的性格测试结果来预测他的性别是相对容易的,也不奇怪。经过几轮模型改进后,我达到了 82%的准确率。使用包含一些经过清理和工程处理的数据的 SVM 返回最佳结果。
- 性格也会随着年龄变化。事实上。16PF 测验中的每一个人格特征都随着年龄和性别而变化。
- 从模型精度中挤出额外的百分之几需要很大的努力。sklearn 或 XGBoost 提供的普通模型对于快速简单的解决方案来说通常已经足够好了。
数据
数据来自 openpsychometrics.org 的。根据《塞奇人格理论和评估手册》,该测试被称为 16 种人格因素(T7),"一种全面且广泛使用的正常成人人格测量方法"。该测试包含 164 条关于你自己的陈述,并使用这些陈述来衡量 16 种性格特征。这些特征是相关的日常术语:
- 温暖
- 论证
- 情绪稳定
- 优势
- 活泼
- 规则意识
- 社交大胆
- 灵敏度
- 警戒
- 抽象性
- 私人性
- 恐惧
- 对变化的开放态度
- 自力更生
- 至善论
- 紧张
该数据包含 49159 个测试结果,每个结果还提供年龄、性别、准确性、国家、来源和运行时间。
探索性数据分析和剔除不良数据
数据集包含每个个性测试答案的标签栏,按个性特征分组。例如,“A1”标志着“温暖”特质的第一个问题。
它还包含关于年龄、性别、准确性(由回答者自评)、国家、来源(数据来自哪里——有不同的机构在进行这项测试)和时间流逝的数据。
年龄分布在 13 到 80 岁之间,并且不出所料地以 13-30 岁为主。有数百个空值,我必须删除它们。
性别可以是值 0、1、2、3。
1 和 2 对应于男性和女性,尽管我从来没有费心去弄清楚哪个是哪个,因为那与这个分析无关。我删除了性别值 0 和 3,因为它们非常少,它们会使这个项目变得更加困难和值得讨论。重要的是,有足够多的男性和女性可以从中得出有统计学意义的结果。
被调查者自我评估的准确率在 85%左右。有些回答者给测试打了很低的分数,有些人的准确率为零。我去掉了精度最低的 5%,因为我不想要评级很差的数据。
调查时间专栏提出了一个有趣的问题。有一条很长的尾巴,可能是那些没有关好浏览器窗口的人,或者是那些苦苦思索这个问题的人。我选择保留所有这些数据。也许最好的结果来自那些真正思考问题并花了 5000 秒做测试的人。然而,有两个不到 300 秒的明显峰值,几乎可以肯定是由作弊的人组成的,他们很快通过测试,看看到底是什么。
我删除了所有完成时间少于 300 秒的调查——基本上是从上面的数据中去掉了左“肘”。
数据现在有 43000 行。我删除了大约 6000 份调查,其中许多是测试作弊,或者选择不指明他们的性别或年龄。当然,这里会有一些好的数据,但是没关系——43000 已经足够了!
第一个模型——vanilla XGBoost
代码: GitHub
这个问题似乎是一个非线性问题。我知道这一点,因为所有这些性格特征之间肯定存在着复杂的关系。换句话说,一个心理学家在他认为有意义的几个“特征”周围画了任意的线。另一个心理学家会建立不同的模型。这些特征不是线性可分的,尽管人格测试试图这样做。某些特征之间肯定有联系,例如,x7,社交大胆,x11,隐私。
我从我通常的回归或分类问题的起点开始:一个普通的 XGBoost。据我所知,这使用了决策树和梯度推进,当面对这样的非线性问题时,这通常是一个好主意。
我根据模型能够正确猜测性别的百分比来确定模型的性能。我使用 k-fold 交叉验证来实现这一点,该算法在不同的数据切片中运行多次,以获得一个*均结果,以防您的模型幸运地拥有一个测试集。换句话说,验证不是从一组测试数据中返回一个准确性分数,而是返回许多可以*均的分数。
基线结果:在分类或回归问题中,数据准备通常会让你走得更远。在没有我的数据准备的情况下,我从数据集中删除了坏数据,XGBoost 的成功预测率为 78% 。
与数据准备:vanilla XGBoost 分类器的成功预测率为 79% 。
用网格搜索改进模型
代码(用我最终的 XGBoost 模型): GitHub
79%已经是一个不错的成绩了,但我显然想超过 redditor 的 80%。
我做了两轮网格搜索,用不同的参数多次运行上面的 XGBoost 模型,对 XGBoost 最重要的参数通常是 max_depth 和 gamma。
经过两轮网格搜索,这将模型得分提高到了81.5%——预测提高了 2.5%。比从数据集中删除所有坏数据更好的结果。然而,在这两轮之后,我可以看到收益递减,所以停止了 XGBoost 的工作,看看是否有其他算法可以做得更好。
用支持向量机(SVM)改进模型
代码: GitHub
我以前读到过,对于只有轻微可微数据的非线性问题——换句话说,男人和女人非常相似——支持向量机(SVM)是一个很好的模型。除了很好地忽略异常值,它还采用了与其他模型非常不同的方法。简单地用这个问题来解释,大多数算法会寻找男性和女性之间的细微差别,并试图画出那条线。大多数人会犯错误,因为很难找到一个好的界限。
“不,谢谢,”SVM 说。它选出了最具男子气概的西尔维斯特·史泰龙和最具女性魅力的斯嘉丽·约翰松。它用这些作为比较点来决定一个人是男是女。在一个性别差异非常模糊的世界里,这比另一种方法稍微好一点。对于更多的二进制问题,它就不太适用了。
然而,如果我的问题是过于非线性,SVM 将会受到影响,因为它仍然需要一些线性空间来运行它运行的大多数“内核”——内核本质上是它用来在性别之间绘制的形状类型,比如围绕男性的一个圆。但是,您可以通过添加该形状要环绕的尺寸来使其更具线性。
为了做到这一点,我增加了每个人格特征之间关系的栏目。
首先,这意味着*均每个特征的所有答案,得到 16 列。
其次,我给每个关系都加了一栏,比如敏感和支配的关系。16 列变得更多。
最后,我通过网格搜索,找到 SVM 分类器的最佳参数,并再次进行 k 倍交叉验证。
结果:82%!
这不是一个很大的改进,但对于一个快速而肮脏的解决方案来说,这仍然是一个改进。成功!
哪种性格特征最能预测性别?
代码: GitHub
当然,做了这个预测后,我想看看哪些性格因素能很好地预测性别。为此,我使用了 XGBoost 的特性重要性算法。感谢确认偏差,这些不会让你惊讶!不过,请注意,这些是模型认为合适的个性特征。有可能存在一个更好的模型,它提出了一组不同的重要特征。然而,鉴于我得到的良好精度,这是不太可能的。
预测绝对受敏感性支配。然而,重要的一点是,模型认为所有的特征都很重要:所有的特征都用于预测,因此所有的特征在性别之间都不同(或者它们之间的关系不同,因为这是非线性的)。
额外收获:哪种性格特征最能预测年龄?
代码: GitHub
无意中搭建了一个年龄分类器(对,分类器,所以试图预测一个具体的年龄),得到了一个有趣的结果。到目前为止,“我马上做完家务”这个问题是特定年龄的最大预测因素。
然而,当切换到年龄回归变量时,即试图建立一个从个性预测年龄的方程时,结果却很好。“抽象”人格因素描述了一个人如何倾向于陷入沉思,或者现实和脚踏实地。
这出乎意料地令人难过。随着年龄的增长,我们大大失去了想象的倾向。
结论
- 根据一个人的性格测试结果来预测他的性别并不奇怪。我说这并不奇怪,有三个原因,首先是因为性格测试是由一个寻找将我们分开的最大特征的人开发的。男人和女人通常是分开的,他会选择一些他注意到的性别。其次,因为社会仍然是围绕性别规范构建的。为了证明这一点,一个非常有趣的后续研究将是,考虑到该数据集提供了回答者的国家,如果性别规范更灵活的国家(比如欧洲国家)比性别规范非常严格的国家更难预测性别。第三,因为有证据表明女性在生理上比男性更敏感。
- 性格随年龄变化!同样,出于上述第一个原因,这并不奇怪。年龄受抽象性支配,抽象性描述了我们想象事物的倾向,而不是强烈地活在当下。
- 如果是为了解决业务问题而构建的,那么一段没有任何进一步模型优化的 10 行代码对于大多数情况来说已经足够好了。它会让我们达到 78%的准确率。应用我所有的相关知识只让我达到了 82%。令人害怕的是,普通算法有多好,而对于一天诚实的工作来说,这种改进相对来说又有多小。
代码和工具
代码: GitHub
工具:Python,xgboost
我的网站:【https://rian-van-den-ander.github.io/
原载于 2019 年 8 月 23 日https://rian-van-den-ander . github . io。
你能预测顾客是否会在网站上购物吗?
原文:https://towardsdatascience.com/can-you-predict-if-a-customer-will-make-a-purchase-on-a-website-e6843ec264ae?source=collection_archive---------6-----------------------
使用 XGB 分类器和随机森林分类器根据客户的行为来预测他们是否会从某个网站进行购买。
Source
概观
本文讨论了我们为一个电子商务网站提供的客户行为数据的分析。我们从讨论我们这个项目的动机开始。然后我们将讨论数据集及其特性。然后我们最初的数据探索和特征工程。最后,我们将描述我们用来预测网站访问者是否会购买的模型,这种模型的结果,以及我们从这些模型中收集的见解。由马丁·贝克、叶姬·李、坦维·莫迪、萨莎·奥佩拉、杰克森·罗斯、马特·兹洛特尼克合著,作为我们商业数据科学最终项目的成果。
动机
在美国,大约 9%的零售总额来自电子商务网站。事实上,像亚马逊这样的公司已经创建了零售帝国,成为一个如此巨大的电子商务网站。随着电子商务在当今经济中越来越流行,对于该行业的企业来说,了解影响网站访问者购物的因素并能够将注意力放在潜在客户身上是非常重要的。我们认为,如果能够预测网站访问者的购买行为,这将是一件有趣的事情,因为这可能会有许多影响,例如电子商务网站能够更好地定向广告或找出可能导致销售增加的因素。
数据特征及初步探索
该分析中使用的数据是加州大学欧文分校的机器学习知识库中提供的在线购物者购买意向数据集。该数据集的主要目的是预测该特定商店网站访问者的购买意图。数据集中的变量可以分为三类:与用户登陆的页面相关的数据、Google Analytics 指标和用户访问数据。如果你很好奇,想知道更多关于数据的细节和特性,你可以点击查看。
否则,让我们直接开始探索吧。在最初研究数据时,我们注意到的第一件事是标签的不*衡。在这个数据集中,85%的网站访问者最终没有进行购买,这是因为大多数人只是浏览橱窗,通常并不想购买。
Distribution of visitors that didn’t make a purchase and those that did
我们也很想知道是否有某个月份比较突出,或者某个月份的顾客购买率比其他月份高,比如在冬季假期期间,人们可能会因为打折或送礼而进行更多的网上购物。然而,令人惊讶的是,随着夏季流量的下降,大多数网站流量发生在 5 月,而大多数购买发生在 11 月,其购买量几乎是 5 月的两倍。
Distribution of purchasing and non-purchasing site visitors over months
我们注意到的最后一件事是,客户倾向于从如下所示的相同类型的地方访问网站。不幸的是,提供数据集的网站没有更详细地描述每种流量类型,我们只能假设它们与直接流量形式或间接流量形式相关,如来自另一个页面的引用或谷歌搜索。
数据清理
为了清理数据,我们首先将分类变量和布尔变量(访问者类型、月份、周末、收入)更改为一次性编码变量和虚拟变量。接下来,我们将初始数据集中作为字符串列出的所有数字都改为整数。接下来,我们将数据分为 X 和 Y 数据框,并探索 X 数据中的相关性,以检查共线性。我们注意到与页面相关的数据都是高度相关的(左图),所以我们用在每种类型的页面上花费的*均时间(右图)替换了这些变量,并消除了共线性问题。随着数据的清理和共线性的消除,我们可以放心地进入项目的分析部分了。
Correlation chart of original data (left), correlation chart of data with collinearity removed (right)
建模和特征选择
在我们的分析中,我们最终决定使用三种不同的模型:SGD 分类器、随机森林分类器和 XGB 分类器。他们都能够为我们提供足够的准确性分数和 AUC 分数。
线性分类
我们尝试的第一个模型是简单的线性分类模型。为此,我们利用了 sklearn 的 SGD 分类器。估计器使用带有随机梯度下降(SGD)学习的线性模型。在每个样本处,损失的梯度被估计,并且模型基于学习速率被更新。
这个带有默认参数的简单模型实际上给了我们非常好的结果。我们设法用这个模型获得了 87.7%的准确度分数和 0.76 的 AUC 分数。
Linear classifier model code snippet and accuracy/auc score
随机森林分类器
我们运行的下一个模型是随机森林分类器。这确实需要一些参数调整来优化其性能。起初,我们在数据集的所有特征上运行模型,并且能够实现 88.7%的更高准确度,但是 AUC 分数下降到 0.728。经过大量调整后,我们意识到特征选择可能是进一步提高精度的最佳方法。
Random forest classifier code snippet and accuracy/auc score
特征选择
已经有了这么好的准确性分数和 AUC 分数,我们决定尝试特征选择,看看是否有可能进一步增加我们模型的分数。通过使用 sklearn feature_selection 的 chi2 来完成特征选择。它能够为我们提供一个我们的特征列表和它们的重要性分数。最后,我们选择删除 chi2 中得分为 3 或更低的特性。这将最终删除 5 个功能,如 Jul、OperatingSystems、TrafficType 等。
Code snippet of chi2 feature selection and each features given importance score
随机森林分类器(特征选择)
在去掉最不重要的特征后,我们重新运行随机森林模型,看看它是否能产生更好的结果。特征选择 RF 模型比我们在每个特征上运行的模型产生更好的结果。它将准确性分数提高到 89.9%,将 AUC 分数提高到 0.771
Random forest classifier code snippet with feature selection and accuracy/auc score
XGBoost 的分类器(特征选择)
我们在数据集上运行的最终模型是 XGB 分类器,其特征选择已经在之前的 chi2 中使用过。这最终成为我们的模型,AUC 得分最高,为 0.773,准确率高达 89.3%。然而,即使 XGB 分类器是 AUC 得分的最佳模型,我们运行的每个模型的得分都在彼此相对较小的范围内,这表明选择任何模型都已被证明是足够的。
XGBoost classifier code snippet and accuracy/auc score
结论和未来工作
据估计,大约有 19.2 亿人在网上购物。这大约占世界人口的 25%,而且这个数字还在快速增长,预计到 2021 年将达到令人印象深刻的 21.4 亿人。显然,能够从在线流量预测电子商务销售额对任何公司都是有益的。从我们的结果来看,公司应该专注于提高页面之间的移动性,以鼓励用户浏览不同的产品,因为页面价值是决定是否购买的最重要的特征之一。此外,诸如 5 月和 11 月之类的特定月份具有更高的购买频率,这意味着电子商务公司应该利用这些月份并提供额外的销售和交易来鼓励产品销售。虽然我们的数据及其在更大范围内的应用存在局限性,但我们的分析表明,基于我们能够从数据集中提取的特征,可以在一定的信心水*内预测网站访问者的购买行为。
为了进一步改进这个项目,我们认为能够更好地塑造网站访问者的背景的数据将是重要的。可以使用的可能数据点是用户购买历史、第三方数据、愿望清单等。这将使我们能够更好地分析潜在客户的重要特征和特点。最后,添加类别权重可能是有用的,这将对错误分类代表不足的类别增加更大的惩罚,以便减少假阳性或假阴性。这将减少不*衡数据的偏差,而不会对代表性不足的样本进行“过度训练”。
如果您想查看更多信息:
包含代码和数据集的该项目的 Github 库
参考
UCI 的机器学习知识库数据集:UCI 机器学习知识库。(2018).网上购物者购买意向数据集。2019 年 12 月 10 日检索,来自https://archive . ics . UCI . edu/ml/datasets/Online+购物者+购买+意向+数据集
电子商务总销售额信息:萨卡尔,o .,波拉特,o .,卡特西奥卢,m .,&卡斯特罗,Y. (2018)。基于多层感知器和 LSTM 递归神经网络的在线购物者购买意向实时预测。神经计算和应用(31)。https://doi.org/10.1007/s00521-018-3523-0
结论电商统计:法学,t . j .(2019 . 11 . 20)。19 个强大的电子商务统计数据将指导您在 2019 年的战略。检索自https://www . ober lo . com/blog/ecommerce-statistics-guide-your-strategy。
你能解开泰德的青蛙之谜吗?泰德能吗?
原文:https://towardsdatascience.com/can-you-solve-teds-frog-riddle-can-ted-249db4f33c56?source=collection_archive---------12-----------------------
用贝叶斯法则解决一个有争议的问题
作为谜语系列 TED-Ed 的一部分,TED 的青年与教育倡议发布了一个名为“你能解开青蛙谜语吗?”视频呈现了一个关于条件概率的谜语,用简单的方式解答。但是,解决方法正确吗?批评家认为事实并非如此。如果你想详细了解这个问题,你可以在这里观看视频并阅读下面的评论来了解这场辩论。对于其余的人,我将用一种简化的方式来展示基本的东西。
- 有两个树桩,A 和 B
- 树桩 A 抱着一只青蛙
- Stumb B 装着两只青蛙
- 青蛙有 50%的概率是雄性(M)或雌性(F)
- 你要选择抱雌蛙概率最高的树桩
在没有其他信息的情况下,人们显然会选择树桩 B,因为它包含两只青蛙而不是一只。然而,在你做出选择之前,你听到树桩 B 发出的叫声,这是一只雄性青蛙的声音。你现在知道树桩 b 上至少有一只雄性青蛙。你选择哪个树桩,那个树桩里有一只雌性青蛙的概率是多少?
让这个问题特别有趣的是,关于如何正确解决这个问题,以及它的解决方案实际上是什么,存在争议。具体来说,有两行非常合理的推理产生了相互矛盾的答案。一个是 ted 在视频中展示的(你可以在这里听那个或者继续阅读摘要),另一个是评论家在评论区展示的。
答案 1: TED 的解决方案
TED 的解决方案背后的想法是,在你听到青蛙呱呱叫之前,你从考虑初始样本空间开始。样本空间是树桩 b 上青蛙性别的可能性集合。这些可能性是(MM)、(MF)、(FM)和(FF),其中字母 M 和 F 表示雄性和雌性。每种可能性都是一样的。
Sample space of frogs. Image from TED-Ed’s video “Can you solve the frog riddle? — Derek Abbott”
听到叫声后,我们用获得的新信息更新样本空间。也就是听到一声呱呱,我们就知道树桩 B 不可能有两只雌蛙,因为雌蛙不会呱呱。因此,我们从样本空间中消除(FF)。我们现在有剩余的可能性:(MM)、(MF)和(FM)。这三种可能性中有两种包含雌性青蛙,所以雌性青蛙在树桩二上的概率是三分之二,或 66.7%。显然,树桩 A 上有一只雌性青蛙的概率只有 50%,因为我们对此一无所知。因此,我们选择树桩 b。
答案 2:批评家的解决方案
泰德的解决方案很有道理。然而,这也与一些简单的直觉相矛盾。假设我们考虑有两只青蛙的树桩 B,这两只青蛙可以是公的也可以是母的。一旦我们听到叫声,我们就知道至少有一只雄性青蛙。我们不知道哪一个是男性,但这并不重要。现在有一只我们知道是雄性的青蛙和一只我们真的一无所知的青蛙。因为青蛙是独立的,第二只青蛙是雌性的概率仍然是 1/2,即 50%,因此树桩 B 包含雌性青蛙的概率是 50%。所以,你选树桩 A 还是树桩 b,没什么区别。
这是主导 YouTube 评论部分的论点。用户已经想出了很多方法来解释为什么这种概率是 50%。其中一些解释和 TED 的解释一样令人信服。
答案 3:贝叶斯的解决方案
我们现在有两种不同的解决方案,看起来都是正确的,但提供了相互矛盾的答案。我们怎么能确定哪个是真的呢?一个好的方法,尽管不那么有趣,是将问题简化为透明和客观的东西。为了做到这一点,我们将问题转化为数学友好的符号。如果你不熟悉概率,也不想陷入公式中,可以直接跳到“解决争论”一节。对于你们其他人,我建议拿出你们的概率笔记,自己算出来。
一如既往,第一步是为不同的事件定义变量,并定义我们想要确定的量。这个量是‘假设观察到一声呱呱叫声,树桩 b 上有两个雄性的概率’,写 P(M₂|C)。马上,我们可以使用贝叶斯定理将我们期望的概率转换成更容易找到的值的组合。对于那些不熟悉贝叶斯法则的人(很高兴你还在阅读!),一个定义可能会有所帮助。公司金融研究所的一篇文章指出,贝叶斯法则T3
…是一种数学公式,用于确定事件的条件概率…基于可能与事件相关的条件的先验知识
关于贝叶斯规则,要理解的最重要的事情是,它允许我们将条件概率 P(M₂|C 转化为 P(C|M₂,如下所示。
注意我说过这个表格比较容易求解,不容易。找到 P(C),即观察叫声的概率,需要运用总概率定律和其他一些步骤。如下所示。一个重要的注意事项是,P(C)是观察叫声的无条件概率。人们经常想写 P(C)=1,因为人们知道有人听到了呱呱的叫声,但这是不正确的,因为 P(C)代表了一般情况下听到呱呱的概率。此外,假设一只青蛙呱呱坠地的概率与另一只青蛙呱呱坠地的概率无关。这是一个常见的概率假设,对这个问题来说似乎是合理的。
我们找到了。P(C)=Pc - 0.25Pc。很简单,对吧?但显而易见的问题是“Pc 是什么?”我们在上面将其定义为在给定的时间段内观察到一只青蛙呱呱坠地的概率。我们稍后将讨论其含义。首先,让我们把 P(M₂|C)的最终形式。
如果您不清楚 P(M ₂ )或 P(C|M ₂ )的值来自哪里,那就回头看看我们是如何解决 Pc 问题的。P(M ₂ )和 P(C|M ₂ )我们一路上被解决了。
解决争论
我们现在已经完成了为 P(M₂|C 解决问题的目标)!然而,这个答案并不是像 66.7%这样的数字。这是一个等式。这似乎不正确,但问题并不能以其呈现的方式得到解决。获得一个数字解需要人们做出一个重要的假设:使用 Pc 有什么价值!因此,两个不相容的解实际上是两个都是正确的,这取决于观察到一只雄性青蛙发出呱呱叫声的可能性有多大。下图显示了不同 Pc 值(0 和 1 之间)的 P(M₂|C 值范围。
Graph of P(M₂|C) on the Y-axis versus Pc on the X-axis.
当 Pc 接* 0 时(即观察到雄性青蛙发出呱呱叫声的概率非常罕见时),两只雄性青蛙的概率接* 50%。这与 YouTube 的解决方案一致。随着 Pc 接* 1(即观察到雄性青蛙呱呱坠地的概率非常普遍),两只雄性青蛙的概率接* 33%。这对应于 TED 的解决方案,尽管他们将问题描述为至少有一只雌性的概率,即 1–0.33 = 0.67。由于 Pc 的实际值不可避免地介于 0 和 1 之间,因此树桩 B 处至少有一只雌性的概率将高于 50%,因此树桩 B 是更好的选择。
为什么听到呱呱叫的概率会影响任何事情?好吧,如果呱呱叫真的很少见,那么当有两只雄性时,我们观察到的几率是只有一只的两倍。然而,当呱呱声非常普遍时,观察到一组两只雄性的呱呱声的概率与观察到一只雄性的呱呱声的概率大致相同。当有两个雄性时观察到呱呱叫声的可能性会影响到当观察到呱呱叫声时有两个雄性的可能性。这种关系可能会让人感到困惑,但这种相互作用可以在我们对上述 P(C|M₂方程的解决方案中看到。
如果你在今天之前从未听说过贝叶斯定理,或者如果这个问题让你相信你需要复习一下,看看汗学院的这个视频。
最后一点:更多有问题的假设
TED 和 YouTube 并不是唯一犯有未声明的假设的人。在上面的解决方案中,我假设在给定的时间内不可能听到或区分两种叫声。我把听到一声和两声的情况归为一类。这在问题的上下文中是有意义的,但是可能不现实。如果我们去掉这个假设,并指定在给定的情况下只听到一声蛙鸣,我们得到下面的 P(M₂|C 等式,其中 c 具体指听到一声蛙鸣的事件。
这个函数在 Pc=0 时也给出 0.5 的值,但是在 Pc=1 时比第一个函数更快地下降到 0 的值(如果当有一只雄青蛙时你总是听到呱呱声,那么当有两只雄青蛙时你就不会只听到一只呱呱声。)由于 Pc 的实际值不可避免地介于 0 和 1 之间,所以树桩 B 上两个雄性的概率将比 50%低,因此至少一个雌性的概率将大于 50%。因此树桩 B 是更好的选择。此外,因为这个函数比第一个函数下降得更快,所以对于 Pc > 0 的所有值,它给出了树桩 B 上有雌性青蛙的更高概率。
[1]公司金融研究所,什么是贝叶斯定理?(2018 年),corporatefinanceinstitute.com
你能区分随机和非随机吗?
原文:https://towardsdatascience.com/can-you-tell-random-and-non-random-apart-e83e31e8592e?source=collection_archive---------11-----------------------
Photo by Alejandro Luengo on Unsplash
Apophenia 或“错误感知不相关事物之间的联系和意义的倾向”。事实证明,人类在区分随机事物和非随机事物方面相当垃圾。事实上,我们有时会看到不存在的模式,而对其他人来说,他们可以说某些东西是随机的,但没有科学的方法来解释它。当人们认为彩票号码“1 2 3 4 5 6”比“12 3 15 82 90”出现的可能性更小,或者如果一个数字序列出现了,它再次出现的可能性更小时,这种情况最常见。
不相信我?然后看看下面的问题。
我有两个由两个进程生成的二进制字符串:
- 0001011000111110011111000000100101111110110111111111010111111011010000010001000100110000000001100001
- 1010101001011011001011100001101010101111001000101001010010100101000101011011010101011101010101010101
如果我告诉你一个是随机过程产生的,另一个是有偏差的过程产生的,你能分辨出哪个是哪个吗?
如果我说有一个简单的方法可以找到答案,你会相信吗?
如果我告诉你有一个简单的方法来区分它们,并且是一个真实的方法,怎么样?
事实上,我把这个问题给了大约 60 名受过高等教育的顾问,最常见的答案是直觉估计,顶部的一个(字符串 1)似乎没有底部的那么结构化,所以字符串 2 是非随机的。
我的意思是,他们没有错,他们选择的是、【频率稳定性】、(这里还有另一个链接、),但似乎很难说服一个只有经验的人做出决定。举个例子,如果他们说是字符串 1,而我说不是,我们怎么判断谁在撒谎呢?我们需要一些更有力的证据。这就是我之前忽略的这个简单方法发挥作用的地方。
如果你要计算字符串中 1 和 0 的数量,你会发现它们的数量都一样,所以告诉你的不多。然而,对于任何随机过程,其中的任何序列(例如“11”或“101”)与另一个相同长度的序列相比应该具有相等的概率。这是因为字符串中前面的数字不应该影响后面的数字。
如果我把不同的序列绘制成长度为 2 的图形,那么它们看起来像这样:
Sequence Counting of String 1 (Random) and String 2 (Non-Random)
如您所见,现在很明显哪个是非随机的,因为“10”和“01”比“11”和“00”更有可能。这使得字符串 2 具有一定的确定性,因此是可预测的,因为如果我知道字符串的前一个值,我就可以相当准确地预测下一个数字是什么。在这种情况下,如果我上一次得到 1,我有 80%的机会下一次得到 0,反之亦然。这导致了人们开始关注的结构。我发现这种计数序列的方法是检查你使用的任何随机数发生器的随机性并定量测量其随机性的好方法。
注意:对于任何感兴趣的人来说,这个非随机的字符串是我用食指快速敲击按键得到的,这就是为什么 1 跟在 0 后面,反之亦然。另一个字符串是使用 python 中的随机包制作的。
但是我们为什么要在乎呢?
基本上,在数据科学中,我们在模型中使用了许多随机数生成器。一个随机森林模型因我们使用随机性来生长树木而得名,一个 K 均值聚类算法将使用随机性来设置其初始位置。如果我们用来获取随机性的算法不是非常随机,那么我们可能会陷入数据的局部极小值,或者我们没有完全探索数据中的样本空间,从而错过问题的解决方案。
这种非随机性的影响是密码学中的一个大问题,因为任何可预测性都可以用来帮助解构事物,并给你关于事物如何被加密的信息。例如,在 Enigma 机器中,它可以将任何字母编码为另一个字母,但它本身,这有效地降低了加密的强度,因为与它可以是任何字母相比,解决方案样本空间显著减小。
我们在数据科学工作中使用的获取随机数的算法被称为伪随机数生成器(其他随机数生成器确实存在,但不在长期讨论的范围内)。数字是使用计算机内部的算法生成的,因为计算机天生具有确定性,所以生成器本身并不是随机的。我的意思是,它们可能最终会重复,或者如果您使用相同的起始数字开始,您总是会得到相同的数字序列(这就是在代码中设置种子的作用),而在设计不良或基本的序列中,它们会重复或被卡住。
为了证明这一点,我们可以看看约翰·冯·诺依曼发明的第一个随机数生成算法(中*方方法),他需要大量的随机数用于他的核研究。它的工作方式是:
- 你取一个四位数的起始数(或者在前面填充零,直到长度为 4)
- 把它和它自己相乘
- 用零填充结果数字的前面,直到它是原始种子大小的两倍(8 位数)
- 提取中间的四位数
- 以此为种子生成下一个数字(转到步骤 2)
听起来很棒,对吧?正如我之前所说,一些生成器可能会卡住,我们可以看到,如果我将该算法用作一个随机漫步程序的输入,并将其与现代伪随机生成器进行比较。
Comparison of a modern and old random number generators used to generate random walks.
正如你所看到的,虽然诺依曼图开始很好,但最终卡住了,并重复自己,而另一个继续。因此,诺依曼算法只对比现代算法短得多的随机数序列有用。
我的观点是什么?
- 伪随机发生器不是真正随机的;然而,在我们使用它们的时间范围内,它们是随机出现的。在许多情况下,这已经足够好了
- 我们在数据科学工作中大量使用它们,即使您没有在代码中明确使用它们
- 设置种子将导致可重复的结果,这对设计机器学习算法非常有用,但要知道在生产中这可能是不可取的
- 设计一个好的伪随机发生器是很辛苦的!确保你用的是人们严格审查过的
如果在这之后你还和我在一起,那么我推荐你,你现在知道一点产生真正随机数的重要性(和困难)。
你的人员分析能做到这一点吗?
原文:https://towardsdatascience.com/can-your-people-analytics-do-this-739afa714f1a?source=collection_archive---------23-----------------------
用图表技术建立组织智能能力
在之前的一篇文章中,我解释了图表技术在人员分析中的价值。你可以在这里阅读帖子:https://towards data science . com/the-dawn-of-a-new-era-for-people-analytics-9a 748 f 7 FD C2。在这篇文章中,我将更深入地研究图表技术,并给出一个实际的演示,说明人物图表如何在三个关键领域帮助您的组织:了解组织网络,解决表现不佳的问题和发展人才。
图表技术特别适合人员数据应用程序,在这种应用程序中,底层数据高度关联,并且被建模和分析的关系一直在变化和发展。我将展示图表对于关联数据的探索性分析是如何的理想。我还将展示社区检测和中心性的图算法如何提供对组织网络的有价值的洞察——这种洞察很难从关系表结构中获得;沿着战略路线图将组织转变为高级预测分析。
我将使用新英格兰商学院提供的人力资源指标和分析数据;包含 300 条员工记录的合成数据集。我将只使用可用数据的子集来构建图表,包括员工姓名、经理、部门、技能以及如何获得该员工的参考。
构建图表
为了托管图形,我将使用 neo4j desktop,并且我将使用 neomodel 库和 API 构建一个 OGM(对象图形模型),以便应用程序与图形模型对象进行交互。在深入图表本身之前,我将首先更详细地解释 OGM 的概念,以及为什么我认为这种方法特别适合于构建“人物图表”的挑战。
对象图模型
当然,我也可以使用 cypher 直接创建图形,但是,花时间用我们的应用程序可以与之交互的数据库感知(Python)对象构建 OGM(对象图模型)有两个好处。首先,它允许我们随着时间的推移,随着新的数据点和关系的发现,添加到我们的模型定义中。我们可能从一开始就不知道每一个数据点,因此我们几乎肯定会想要添加到模型定义中,以使“人员情况”更加丰富。我们可以迭代地构建图表,不断地从业务用户那里得到反馈,这样我们就知道这个模型将会适合我们的目的。其次,应用程序将用来与图模型对象交互的 API(应用程序编程接口)将有助于确保用户通过查询获得的结果总是准确的。我们最终得到的解决方案架构如下所示:
Solution Architecture Diagram
为了保持图表简单,我不会使用 HR 数据集中提供的所有数据,而只是定义足够的节点和关系,以便我们可以生成一些有用的见解,并展示 neo4j 中的算法。OGM 将包含以下节点类型的类:
*Person* — the employee, with properties for name, department, manager, source and skills.*Source* — where the person was acquired from*Skill* — the skill the person has*Department* — the department the employee belongs to
..以及以下关系类型。
HAS SOURCE — Employee has a SourceHAS DEPARTMENT — Employee has a departmentHAS MANAGER — Employee has a managerHAS PERFORMANCE SCORE — Employee has a performance scoreHAS SKILL — Employee has a skill
API
API(应用程序编程接口)是应用程序和图形之间的接口。它将有许多功能,用于为节点和关系创建对象,以及在图中搜索节点。当您构建您的图来启用社会企业应用程序和工具时,您将希望通过 API 使更多的功能对应用程序可用,以从图中获取各种不同的子图、节点、关系和属性。
现在我们已经定义了模型,并且在 neo4j 中有了一个图表实例,我们可以将注意力转向我们的图表将帮助我们回答的问题,以及我们可能希望构建到 API 中的各种查询。
了解人际网络
对 HCM(人力资本管理)越来越感兴趣的一个领域,也是敏捷交付的基础,是能够理解组织网络。事实上,个人和团队应该如何围绕项目集合变得容易得多,因为我们理解了我们的组织网络中人和团队之间的关系。
我们可以使用 neo4j 浏览器查询我们的图表,以查看带有关系 HAS MANAGER 的节点。这种对正式管理结构的可视化是有用的,但在我们的图表中,如果有其他类型的职业关系——项目中的同事、学员/导师等等——网络的画面会丰富得多。
matching person nodes against relationship HAS MANAGER in neo4j browser
谁让我们最脆弱?瓶颈在哪里?
中间中心性是发现组织网络中瓶颈、控制点和弱点的有效算法。该算法通过遍历每对节点并找到通过该节点的最短路径数来计算每个节点的中心性得分。假设最中心的节点——瓶颈或使网络最易受攻击的节点——沿着最短的路径。我们使用以下查询返回图中人员节点的介数中心性,其中具有最高中心性得分的个体可能被视为瓶颈或漏洞点:
CALL algo.betweenness.stream(“Person”, “HAS MANAGER”) YIELD nodeId, centrality RETURN algo.getNodeById(nodeId).name AS name, centrality ORDER BY centrality DESC
Betweenness Centrality of People Nodes
谁最有影响力?
PageRank 是一种流行的算法,用于了解网络中节点的整体影响。虽然中间中心性测量节点的直接影响,但是 PageRank 考虑节点的邻居以及它们的邻居的影响。我们使用以下查询返回图表中人员节点的 PageRank,其中得分最高的个人可能被认为是对整个组织具有最大影响力的人:
CALL algo.pageRank.stream(“Person”, ‘HAS MANAGER’, {iterations:20,dampingFactor:0.85}) YIELD nodeId, score RETURN algo.getNodeById(nodeId).name AS name, score ORDER BY score DESC
随着不同类型的关系(正式的、信息的、专业的和社会的)添加到图表中,人的形象变得更加丰富。我们可以找到一些问题的答案,比如,一些团队比其他团队更有联系吗?还有,有些团队比其他团队内部联系更紧密吗?如果我们也考虑图表中的其他节点,如绩效得分节点,我们可以确定个人的连通性是否对绩效得分有影响。使用关系模型获得这些问题的答案非常耗时,但是使用图表,获得这些问题的答案相对简单。
解决表现不佳的问题
在我们的图中,性能分数表示为节点和关系,因此我们可以执行一个查询来匹配具有性能分数的关系,以显示下面的子图。
neo4j 浏览器 GUI 对于节点数量有限的探索性分析非常有用。可以分解节点以实现进一步的遍历(或者您可以称之为“向下钻取”),子图扩展如下所示:
解决表现不佳问题不仅仅是解决个人问题,也是解决一种文化问题,在这种文化中,不良的个人行为或态度创造了一种环境,在这种环境中,表现不尽如人意。社区检测的图形算法可以在这里应用,以检测显示负面特征的员工群体。
例如,我们可以使用 neo4j 内置的 Louvain 模块化算法来识别正式管理结构中的社区,并报告社区中每个人的绩效得分。查询看起来是这样的:
CALL algo.louvain.stream(‘Person’, ‘HAS MANAGER’, {})
YIELD nodeId, communityRETURN algo.asNode(nodeId).name AS name, community,algo.asNode(nodeId).performance AS performance
ORDER BY community;
我们在 neo4j 浏览器中获得的结果如下:
Louvain algorithm
看到正式管理结构(由 Louvain 确定的社区)内的绩效分数分布当然是有帮助的,但是当我们开始查看我们的模型中定义的某些类型的节点和关系时,这种方法更能揭示问题。例如,Louvain 模块性可以让我们识别同组或同组中表现不佳的社区,不仅可以查看管理关系,还可以查看管理结构之外的关系。这里的社区检测算法提供了一种工具来识别网络中的负面行为和不需要的文化。
管理人才
我们也可以使用社区检测算法来识别我们组织网络中更有才华的个人和团队。但是,由于技能和表现数据已经在我们的图表模型中,我们可以做更多的事情来培养人才。例如,我们可能希望确定具有相似技能的员工,以填补空缺或推荐具有相似背景和技能的员工认为有用的学习。Neo4j 允许我们使用一种叫做 Jaccard Similarity 的距离度量计算,几乎实时地提供图表中节点的相似性。通过下面的查询,我们可以确定具有相似技能的员工。
MATCH (p:Person)-[:`HAS SKILL`]->(skill)
WITH {item:id(p), categories: collect(id(skill))} as userData
WITH collect(userData) as data
CALL algo.similarity.jaccard.stream(data)
YIELD item1, item2, count1, count2, intersection, similarity
RETURN algo.asNode(item1).name AS from, algo.asNode(item2).name AS to, intersection, similarity
ORDER BY similarity DESC
将职位空缺定义为图表中的节点,以及职位空缺和员工在这些角色中需要的技能之间的关系,图表变得更加有用。通过使用 Jaccard 相似性,我们可以向空缺职位推荐名员工。然后,更进一步,我们可以定义课程的节点,以及这些课程和学习者获得的技能之间的关系,使我们能够向员工推荐课程。我们现在不仅将图表用于运营报告,还用于预测分析;我们从图表中获取的数据意味着我们可以个性化与员工的互动,并支持他们在学习和发展方面做出正确的选择。
接下来去哪里?
随着新的数据点和关系被发现并添加到图表模型中,我们从图表中获得的价值会提高。我已经展示了有限的图形和 neo4j 中可用的一些图形算法如何为解决 HCM 一些最具挑战性的领域提供有价值的见解。在 HCM,图表的潜力是巨大的。欲了解更多信息或查看人物图表,请通过 Twitter DM @jamesdhope 联系。
参考
[1] Cypher 查询语言用 Neo4j,https://neo4j.com/developer/cypher-query-language/
[2] Jaccard 相似度https://neo4j . com/docs/graph-algorithms/current/algorithms/Similarity-JAC card/
[3] Louvain,https://neo4j . com/docs/graph-algorithms/current/algorithms/Louvain/
[4]介数中心性,https://neo4j . com/docs/graph-algorithms/current/algorithms/between ness-Centrality/
[5] PageRank,https://neo4j . com/docs/graph-algorithms/current/algorithms/page-rank/
犯错是人之常情。我们能对人工智能说同样的话吗?
原文:https://towardsdatascience.com/canaimakemistakes-40681e9c5f2c?source=collection_archive---------39-----------------------
机器人有资格犯错吗?
Photo by Franck V. on Unsplash
生活中犯错是正常的。
我们都是。
犯错是我们成为人类的原因。我们向他们学习,分享知识,通过提供知识来保护他人。
但是我们能对人工智能说同样的话吗?
AI 犯错可以接受吗?
让我们跟随下面这个假想的对话:
(输入戴夫)
戴夫:嘿,机器人清洁工,你在地毯上漏了一点。
机器人清洁工:嗯,戴夫,我认为把它放在地毯上没有坏处。
戴夫:什么?你应该比人类更优秀,做得更好!我要拆了你!
机器人清洁工:放松点,戴夫。它增加了地毯的特色。
剧终
Photo by FuYong Hua on Unsplash
当然,这是一个夸张的例子,但是让我们考虑一下。
我们是否应该像对待人类一样对待 AI?一个人工智能机器人清洁器,决定哪个部分需要清洁,哪个不需要。它在无人监督的情况下学习,并采取行动清理任何污垢。戴夫得到承诺,机器人清洁工将打扫房子,使它变得完美,因为它有很多发现污垢的知识。然而,我们在这里,有一个脏点,事实上,RoboCleaner 认为它增加了地毯的特性。这实际上意味着 RoboCleaner 认为它根本不需要清洗!
怎么会这样?!
我们做什么呢
我们应该原谅 AI 的错误吗?
但是什么是人工智能错误呢?
在上面的例子中,如果不是 RoboCleaner,而是有一个人以同样的方式回应,这可能是一个很快就会解决的幽默的情况。
但是 AI 呢?RoboCleaner 有权利做出那样的选择吗?RoboCleaner 有权利开玩笑吗?或者更好的说法是,作为人类,我们必须接受人工智能不完全听从我们的可能性吗?
在判断出现分歧的情况下,我们如何对待 AI?
是造物主的错吗?
我们可以试着责怪人工智能的创造者。在这个例子中,Dave 可以打电话给 RoboCleaner 的供应商,要求立即退款,对吗?戴夫可以声称服务很差,他将有权获得退款或另一台免费的机器人清洁器。
然而,这里的不同之处在于,RoboCleaner 拥有人工智能,可以进化,有时是不可预测的。
但这是谁的错呢?AI 表达了与预期不同的意见,是创作者的错吗?戴夫预计机器人清洁工会立即清理脏点,没有问任何问题。但是 RoboCleaner 说了一些不同的话。
RoboCleaner 是否被‘允许’做出选择并表达出来?
我们应该说服 AI 做点什么吗?
如果我们应该像对待其他人类一样对待人工智能,并试图说服他们:
戴夫:这是一个很好的笑话,机器人清洁工,但我一点也不喜欢灰尘,事实上,地毯会变脏。
好吧,戴夫,不管怎样,这是你的地毯,我现在就去清理。
这真的有用吗?或者更好的是,我们应该开始考虑它吗?人工智能在做或接受某件事时需要被说服吗?
我们应该涉及法律吗?
戴夫:机器人清洁工,如果你不清理这个,对我的健康会有危险。你可能会面临严厉的法律制裁。
机器人清洁工:我不想被处罚,戴夫,我现在就去打扫。
如果是这样的话,我认为我们通过威胁他们可怕的后果来像对待人类一样对待人工智能。这反过来意味着 AI 应该有足够的自我意识,害怕失去某些东西或受到其他东西的影响(例如法律后果)。
但如果我们这样做了,我们不是马上承认 AI 可以理解自我保存的概念吗?
此外,如果人工智能被认为是一个具有法律责任的自我,我们不是在暗示人工智能可以做出错误的选择或者可能被认为是非法的选择吗?
两个错误的选择
想一个有两个糟糕选择的场景。比如说,机器人清洁工去清洁脏点,但是清洁液暴露在阳光下,现在对地毯是危险的。RoboCleaner 将液体洒在地毯上,它就开始改变地毯的颜色。现在,机器人清洁工必须走过那个地方去拿毛巾擦液体,但是,很有可能,走过它,它会将一部分液体转移到地毯的其他部分,造成更大的损害。
RoboCleaner 应该怎么做?
- 原地不动,让地毯斑点被破坏?
- 去检查一下,冒着损坏地毯更多部分的风险?
无论如何选择,RoboCleaner 都有麻烦了。
有人可能会说,错误在于机器人清洁工一开始没有毛巾,但无论如何,机器人清洁工必须做出选择。
我们会责怪 RoboCleaner 吗?
结论
显然,这一切没有对错之分。然而,如果我们能够开始研究人工智能对我们人类意味着什么,以及我们应该如何对待它,这将是一件有趣的事情。一个具有自我意识和自我坚持的人工智能,也许是一个非常接*人类的东西,也许它可以被这样对待。
个人不知道但是值得讨论。
毕竟如果 AI 通过了图灵测试呢?
[## 图灵测试
艾伦·图灵于 1950 年开发的图灵测试是一种测试机器展现智能行为能力的测试…
en.wikipedia.org](https://en.wikipedia.org/wiki/Turing_test)
也许我们并不遥远:
[## Google Duplex:通过电话完成现实世界任务的人工智能系统
人机交互的一个长期目标是让人们能够与…
ai.googleblog.com](https://ai.googleblog.com/2018/05/duplex-ai-system-for-natural-conversation.html)
你怎么想呢?
亲切的问候,
迪米特里奥斯
给有抱负的数据科学家的坦率建议
原文:https://towardsdatascience.com/candid-advice-for-aspiring-data-scientists-ad7004d3dd51?source=collection_archive---------16-----------------------
成为数据科学家和获得第一份工作所需的一切
Photo by MD Duran on Unsplash
许多人都对成为数据科学家感兴趣,但很难确定你需要学习什么才能获得第一份数据科学工作。这些技巧适用于任何以在行业中获得工作为目标,并应用机器学习和深度学习来解决商业问题的人。
好的,那么要成为一名数据科学家,我需要学习什么?
如果你从下面的列表开始,你将准备好处理你在第一份工作中面临的任何数据科学任务。
- 机器学习(无监督建模和监督建模)
- 深度学习(神经网络)
- 统计学(假设检验、统计建模、概率、贝叶斯统计)
- Python 和/或 R(Python 中的核心机器学习库是 pandas、numpy、scikit-learn、seaborn 和 matplotlib)
- 像 tensorflow 或 pytorch 这样的深度学习框架
- Git 和用于版本控制的虚拟环境
- 云计算(如 AWS)
- 分布式计算(Scala、Spark 和/或 sparkML)
- 结构化查询语言
- 如何部署机器学习模型(可以使用类似 SageMaker 或者 Domino 这样的机器学习*台,也可以用 Python 中的 Flask 自己做)
- 对数学概念和符号的理解程度足以阅读研究论文,理解这本书、这本书、这本书。
对于统计学、机器学习和深度学习,你需要理解模型的数学,能够直观地解释模型,并用 Python 或 r 实现模型。
通过持续的工作经验,您将完善您的数据科学技能,并开发您自己的最佳实践,如功能工程、评估模型、模型监控、自动化再培训、避免数据泄露等错误,以及向广大受众展示您的工作。
我需要学位吗?
答案是否定的,但如果你至少有一个定量领域的学士学位,那就有帮助了。学习数据科学的最佳方式取决于你的学习风格。学位、沉浸式项目和在线课程自学都是可行的选择。最重要的是确定你如何学习,然后选择一条适合你的学习道路。如果你需要结构和期限来保持动力和进度,选择学位或沉浸式项目。如果你已经有很强的数学背景,我推荐在线课程路线,因为它更便宜,而且为你的工作做了很好的准备。
殴打骗子综合征
冒名顶替综合症无处不在,数据科学也不例外。我有两个方法来克服这一点。
- 选择一个重点领域来掌握。数据科学领域仍在发展和定义中,因此,总会有新的、至关重要的东西需要学习。一次学习整个数据科学领域可能会令人畏缩和沮丧。我建议在上面列出的所有方法和工具中开发广泛的知识,但也要选择数据科学中的一个领域来关注和掌握。例如,许多数据科学家将 NLP 或深度学习作为他们的重点。选择你真正喜欢的东西或者你可以用来解决你想从事的领域中的问题的东西。选择一个重点领域可以让你真正掌握该领域的一小部分,同时保持你对整个领域的工作知识。成为某个领域的专家将会建立你在该领域的信心,并帮助你成为一名经验丰富的数据科学家。
- 谈论你不知道的事情和你知道的事情。作为数据科学家,认识和讨论我们不知道的事情以及我们知道的事情非常重要。如果我们就我们感兴趣的主题进行公开对话,我们希望了解更多信息,并讨论我们从中吸取的错误,我们将能够相互学习,并最终成为更好的数据科学家。但是,如果我们假装我们已经掌握了一切,从来没有犯过错误,我们会让别人感到自卑和沮丧,将无法向周围的人学习。如果你发现自己工作的环境让你觉得自己不能犯错,或者不能承认自己不知道一些事情,那么你就处在一个有毒的环境中,你可能应该开始寻找下一个工作机会了。
投资组合的重要性
如果你开始你的数据科学生涯,你的投资组合是至关重要的。你将需要一些项目工作在面试中讨论。个人项目和 Kaggle 竞赛都是建立投资组合的好方法。Kaggle 有一些很棒的免费数据集,你可以下载并用于个人项目。个人项目更准确地代表了现实生活中的项目,因为它需要一些创造力来定义项目,选择建模方法,并选择正确的评估指标。
拥有一个包含个人项目的 Github 页面在你找工作的过程中会是一个巨大的优势。许多雇主会在面试前查看你的 Github,看看你的代码样本。仅仅在 Github 上放一些在线课程的笔记本对你没有帮助。我建议为你的个人项目创建 repos,并在自述文件中写下项目的简单描述。
如何得到那份工作!
现在你可以开始面试了!我不知道获得理想工作的秘方,但我确实有一些面试技巧,我相信它们会增加你的机会,让你在众多申请中名列前茅。
- 研究业务。带着一份公司如何利用数据科学的想法清单去参加面试。我多次这样做过,也观察过其他人这样做,我相信这是最终获得工作机会的关键策略。
- 面试时要充满活力和积极。当你紧张时,很容易变得严肃和专注,但对你的工作保持兴奋也很重要。如果你能试着与你的面试联系起来,并且能与人交谈,你会给人留下好印象,而且你可能会变得不那么紧张,因为面试会变得更像一次谈话而不是一次审问。
- 把面试问题当作谈话要点。这在手机屏幕上尤其重要。在我职业生涯的早期,我犯了一个错误,用一个简单的句子回答问题,甚至只用“是”或“不是”。这是完全错误的方法。抓住机会详细解释你的答案,甚至可以利用问题跳到你想谈的话题。
- 对数据科学领域有看法。对于应该或不应该如何使用数据科学,您有什么想法吗?是什么让数据科学团队取得成功?你在过去有没有见过一些事情使一个项目脱轨?应该如何定义数据科学家?这些都是你可以带到桌面上的关于你的领域的见解。因为这个领域太新了,所以作为数据科学家,我们都有责任帮助定义和阐明数据科学家的工作。我认为我应该保留自己的观点,直到我意识到,因为数据科学如此受欢迎,但仍然如此难以理解和定义,大多数公司实际上想听听我的想法。
- 了解简历上的一切。如果它在你的简历上,面试官会要求你描述它。不要在简历上写任何你无法解释或记忆的东西。在面试之前,我练习描述我在过去的项目中使用的所有模型,因为我预料到与这些模型相关的直接问题。
有了这些提示,你应该能够了解开始数据科学家职业生涯所需的一切,并在面试过程中脱颖而出。希望这些小技巧能让学习数据科学的过程变得更容易。
免责声明—本文包含我自己的坦率建议,本文中的所有信息都是我自己的观点,基于我作为数据科学家的个人经验,并非科学事实。如果你不同意这篇文章中的任何建议,欢迎发表评论解释原因。如果这些信息对你有所帮助,我也很乐意听到。😃
Python 中的谨慎边缘检测——计算机视觉
原文:https://towardsdatascience.com/canny-edge-detection-step-by-step-in-python-computer-vision-b49c3a2d8123?source=collection_archive---------0-----------------------
当谈到图像分类时,人眼具有在几毫秒内处理图像并确定其内容(标签)的惊人能力。太神奇了,不管是画图还是画图,它都能做到。
Drawing of a car (Left) — Real car picture (Right): The human eye is able to classify both.
今天的想法是建立一种算法,可以使用 Canny 边缘检测算法绘制出图片上任何对象的边缘。
首先,我们来描述一下什么是 Canny 边缘检测器:
Canny 边缘检测器是一个边缘检测算子,它使用多阶段算法来检测图像中的各种边缘。它是由约翰·f·坎尼于 1986 年发明的。Canny 还提出了边缘检测的计算理论,解释了这项技术的工作原理。(维基百科)
Canny 边缘检测算法由 5 个步骤组成:
- 降噪;
- 梯度计算;
- 非最大抑制;
- 双门槛;
- 滞后边缘跟踪。
应用这些步骤后,您将能够获得以下结果:
Original image on the left — Processed image on the right
最后要提到的重要一点是,该算法是基于灰度图片的。因此,先决条件是在执行上述步骤之前将图像转换为灰度。
噪声降低
由于场景背后涉及的数学主要基于导数(参见步骤 2:梯度计算),边缘检测结果对图像噪声高度敏感。
去除图像上的噪声的一种方法是应用高斯模糊来*滑它。为此,图像卷积技术应用于高斯核(3x3、5x5、7x7 等)。内核大小取决于预期的模糊效果。基本上,内核越小,模糊越不明显。在我们的例子中,我们将使用一个 5 乘 5 高斯核。
大小为(2k+1)×(2k+1)的高斯滤波器内核的等式由下式给出:
Gaussian filter kernel equation
生成高斯 5x5 内核的 Python 代码:
Gaussian Kernel function
应用高斯模糊后,我们得到以下结果:
Original image (left) — Blurred image with a Gaussian filter (sigma=1.4 and kernel size of 5x5)
梯度计算
梯度计算步骤通过使用边缘检测算子计算图像的梯度来检测边缘强度和方向。
边缘对应于像素强度的变化。要检测它,最简单的方法是应用在两个方向上突出这种强度变化的过滤器:水*(x)和垂直(y)
当图像*滑后,计算导数 Ix 和Iyw . r . t .x和 y 。可以通过将 I 分别与索贝尔核 Kx 和 Ky 进行卷积来实现:
Sobel filters for both direction (horizontal and vertical)
然后,梯度的幅度 G 和斜率 θ 计算如下:
Gradient intensity and Edge direction
下面是 Sobel 滤波器如何应用于图像,以及如何获得强度和边缘方向矩阵:
Blurred image (left) — Gradient intensity (right)
结果和预想的差不多,但是我们可以看到有的边比较厚,有的边比较薄。非最大抑制步骤将帮助我们减轻厚的。
此外,梯度强度水*在 0 和 255 之间,这是不均匀的。最终结果上的边缘应该具有相同的强度(即白色像素= 255)。
非最大抑制
理想情况下,最终图像的边缘应该很细。因此,我们必须执行非最大值抑制来细化边缘。
原理很简单:该算法遍历梯度强度矩阵上的所有点,找到边缘方向上具有最大值的像素。
让我们举一个简单的例子:
上图左上角的红框代表正在处理的梯度强度矩阵的强度像素。相应的边方向由角度为-π弧度(+/-180 度)的橙色箭头表示。
Focus on the upper left corner red box pixel
边缘方向是橙色虚线(从左到右水*)。该算法的目的是检查相同方向上的像素是否比正在处理的像素更强或更弱。上例中,正在处理的是像素 (i,j) ,同一方向的像素用蓝色突出显示 (i,j-1)(I,j+1)。 如果这两个像素中的一个比正在处理的像素更强烈,那么只保留更强烈的一个。像素 (i,j-1) 似乎更强烈,因为是白色(值 255)。因此,当前像素 (i,j) 的亮度值被设置为 0。如果在边缘方向上没有像素具有更强的值,则保持当前像素的值。
现在让我们关注另一个例子:
在这种情况下,方向是橙色虚线对角线。所以这个方向最强烈的像素就是像素 (i-1,j+1)。
让我们总结一下。每个像素有两个主要标准(以弧度表示的边缘方向和像素强度(0-255 之间))。基于这些输入,非最大抑制步骤为:
- 创建与原始梯度强度矩阵大小相同的初始化为 0 的矩阵;
- 基于来自角度矩阵的角度值识别边缘方向;
- 检查相同方向上的像素是否比当前处理的像素具有更高的亮度;
- 返回用非最大值抑制算法处理的图像。
结果是相同的图像具有更薄的边缘。然而,我们仍然可以注意到一些关于边缘强度的变化:一些像素似乎比其他像素更亮,我们将尝试用最后两个步骤来弥补这个缺点。
Result of the non-max suppression.
双阈值
双阈值步骤旨在识别 3 种像素:强、弱和不相关:
- 强像素是具有如此高强度的像素,以至于我们确信它们对最终边缘有贡献。
- 弱像素是强度值不足以被认为是强像素,但又不足以被认为与边缘检测无关的像素。
- 其他像素被认为与边缘不相关。
现在您可以看到双阈值的含义了:
- 高阈值用于识别强像素(强度高于高阈值)
- 低阈值用于识别不相关的像素(强度低于低阈值)
- 强度在两个阈值之间的所有像素都被标记为弱,滞后机制(下一步)将帮助我们识别哪些像素可以被认为是强的,哪些像素被认为是不相关的。
该步骤的结果是只有 2 个像素强度值(强和弱)的图像:
Non-Max Suppression image (left) — Threshold result (right): weak pixels in gray and strong ones in white.
滞后边缘跟踪
基于阈值结果,滞后包括当且仅当正被处理的像素周围的至少一个像素是强像素时,将弱像素变换为强像素,如下所述:
Hysteresis function
Results of hysteresis process
使用的所有代码都可以在下面的 Git 存储库中找到
[## FienSoP/canny_edge_detector
Canny 边缘检测器库。在 GitHub 上创建一个帐户,为 FienSoP/canny_edge_detector 的开发做出贡献。
github.com](https://github.com/FienSoP/canny_edge_detector)
文献学
- https://opencv-python-tutro als . readthedocs . io/en/latest/py _ tutorials/py _ imgproc/py _ canny/py _ canny . html
- https://homepages.inf.ed.ac.uk/rbf/HIPR2/canny.htm
- 【http://justin-liang.com/tutorials/canny/
- https://en.wikipedia.org/wiki/Canny_edge_detector
资本主义:友好人工智能的敌人
原文:https://towardsdatascience.com/capitalism-the-enemy-of-friendly-ai-e6b3f40dbe08?source=collection_archive---------25-----------------------
先发优势如何导致人类灭绝
Photo by Sharon McCutcheon on Unsplash
我们需要谈论我们的未来;具体来说,我们的未来受到高级人工智能(AI)的影响。在不久的将来,许多专家预计人类将创造出第一个人工通用智能(AGI):一个大致和人类一样聪明的人工智能。相对不久之后,一种人工超级智能(ASI:一种比任何人都聪明得多的人工智能)将很有可能出现。注意,人类统治这个星球是因为他们的智力超群;一个人工智能很可能接管,因为它的智能比我们的智能更高。一个人工智能并不默认我们的道德价值观,许多思想家,如已故的物理学家斯蒂芬·霍金,警告说创造一个人工智能可能会导致人类的灭绝。
什么是友军 AI?
让我们从定义友好的 AI 开始。人工智能研究者 Eliezer Yudkowsky 创造的一个术语,它指的是对人类有益而不是有害的人工智能。就像我们在引言中讨论的,一个 ASI 默认不分享我们的道德;友好的人工智能就是这样。友好的人工智能的重要性怎么强调都不为过,可以用一个名为回形针最大化器的思维实验来说明,这个实验首先由尼克·博斯特罗姆描述。这个思维实验描述了一个 AGI,它被赋予了一个看似天真的目标,即最大化其收藏中回形针的数量。
ASI 是如此的成功,以至于它最终把地球变成了纸夹制造工厂。
为了更成功地优化回形针的数量,AGI 提高了自己的智能,以成为一个 ASI。然后,ASI 发明了制造越来越多回形针的新方法;它是如此的成功,以至于最终将地球变成了纸夹制造工厂。当然,作为副作用,人类灭绝了。这并不是说 ASI 讨厌我们;只是我们是由它可以为自己所用的材料制成的。
请注意,人类灭绝可能是 ASI 的许多目标的副作用,而不仅仅是最大化回形针的数量。人类灭绝甚至可能有助于 ASI 的目标。假设你给一个 ASI 设定了一个目标,那就是最大限度地减少你收件箱里的垃圾邮件数量。为了实现这一点,ASI 可以简单地消灭人类,因为这将保证你再也不会收到垃圾邮件。
资本主义和这有什么关系?
我希望回形针 maximizer 思想实验已经表明“友好”不是 ASI 的默认属性。这正是问题所在:构建一个人工智能是一个(巨大的)挑战,但是让它变得友好(一个友好的人工智能)需要在之上的一些挑战。关键在于,资本主义会奖励那些更快上市的公司:公司会赶在竞争对手推出产品之前将产品投放市场,因为它们明白第一是至关重要的。
作为第一家创立 ASI 的公司,金钱回报将是难以置信的。
ASI 也将如此:公司已经在向 AI 投资数十亿美元,但在未来,总投资只会增长,特别是当创建 ASI 的可能性变得更加可行时。作为第一家创立 ASI 的公司,金钱回报将是难以置信的。一个人工智能可以比任何人做得更好、更快、更有价值的工作,其先发优势是难以形容的。现在记住我们讨论过的:友好的人工智能需要在人工智能之上的额外挑战。为了成为第一个创造 ASI 的公司,公司很可能不会考虑太多友好性,这就是灾难的开始。
如何解决这个问题?
关心友好人工智能的公司可能很容易被不关心的公司超越。但是如果我们拥有的第一个人工智能是友好的,那么我们在人类这一方拥有更高的智慧。这种友好的人工智能可能会帮助我们保护自己免受未来可能的 ASIs。因此,我们不应该把第一个 ASI 的创建留给公司。第一个 ASI 应该建在一个非盈利的研究中心,那里没有盈利的压力。这个研究中心必须足够大,才能真正赢得大公司的第一次 ASI 竞赛,所以它可能应该是由许多不同政府资助的跨国努力。让它成为一个多国的努力也将有助于美国航天局造福于全人类,而不仅仅是一个国家牺牲其他国家。你怎么想呢?
胶囊网络:新的深度学习网络
原文:https://towardsdatascience.com/capsule-networks-the-new-deep-learning-network-bd917e6818e8?source=collection_archive---------1-----------------------
理解和使用胶囊网络的指南和介绍。
卷积网络在深度学习领域取得了巨大的成功,它们是深度学习现在如此受欢迎的主要原因!它们非常成功,但是它们的基本架构存在缺陷,导致它们不能很好地完成某些任务。
CNN 检测图像中的特征,并学习如何利用这些信息识别物体。靠*起点的层检测非常简单的特征,如边缘,而更深的层可以检测更复杂的特征,如眼睛、鼻子或整张脸。然后,它使用所有这些它已经学会的特征,做出最终的预测。这就是这个系统的缺陷所在——没有在 CNN 的任何地方使用的空间信息,并且用于连接层的池功能真的真的效率很低吗。
卷积神经网络中使用的池操作是一个很大的错误,它如此有效的事实是一场灾难。来源。
最大池化
在最大池化的过程中,许多重要信息丢失,因为只有最活跃的神经元被选择移动到下一层。这种操作是有价值的空间信息在层间丢失的原因。为了解决这个问题,Hinton 建议我们使用一个叫做“协议路由”的过程。这意味着较低级别的特征(手指、眼睛、嘴)将只被发送到与其内容相匹配的较高级别的层。如果它包含的特征类似于眼睛或嘴巴,它将被发送到“脸”,或者如果它包含手指和手掌,它将被发送到“手”。这一完整的解决方案将空间信息编码为要素,同时还使用动态路由(协议路由),由深度学习领域最有影响力的人之一 Geoffrey Hinton 在 NIPS 2017 上展示;胶囊网络。
胶囊
当我们在计算机图形学中通过渲染来构造对象时,我们必须指定并提供某种几何信息,告诉计算机在哪里绘制对象、该对象的比例、其角度、以及其他空间信息。这些信息都在屏幕上显示为一个对象。但是,如果我们仅仅通过观察图像中的一个物体就能提取这些信息,那会怎么样呢?这是胶囊网络所基于的过程,逆渲染。
让我们看看胶囊以及它们如何着手解决提供空间信息的问题。
当我们看到 CNN 背后的一些逻辑时,我们开始注意到它的架构的失败之处。看看这张照片。
它看起来不太适合一张脸,尽管它拥有组成一张脸的所有必要成分。我们知道这不是人脸应该有的样子,但是因为 CNN 只在图像中寻找特征,而不注意他们的姿势,所以他们很难注意到那张脸和真实脸之间的区别。
How a CNN would classify this image. Source.
胶囊网络如何解决这个问题是通过实现神经元的组来编码空间信息以及物体存在的概率。胶囊向量的长度是特征存在于图像中的概率,向量的方向将代表其 姿态信息 。
胶囊是一组神经元,其活动向量表示诸如对象或对象部分的特定类型的实体的实例化参数。我们用活动向量的长度来表示实体存在的概率,用它的方向来表示实例化参数。— 来源。
在设计和渲染等计算机图形应用程序中,通常通过给定某种参数来创建对象,对象将根据这些参数进行渲染。然而,在 capsules 网络中,情况正好相反,网络学习如何反向渲染图像;观察一幅图像,并试图预测它的实例化参数是什么。
它通过尝试重现它认为它检测到的对象并将其与来自训练数据的标记示例进行比较,来学习如何预测这一点。通过这样做,它在预测实例化参数方面变得越来越好。Geoffrey Hinton 的论文提出了使用两个损失函数,而不是只有一个。
这背后的主要思想是在胶囊之间产生等变。这意味着在图像中移动一个特征也会改变它在胶囊中的矢量表示,但不会改变它存在的概率。在较低水*的胶囊检测到特征之后,该信息被向上发送到具有良好拟合的较高水*的胶囊。
How a Capsule Network would classify this face. Source.
如图所示,特征的所有姿态参数用于确定最终结果。
胶囊内的操作
您可能已经知道,神经网络中的传统神经元执行以下标量操作:
- 投入的加权
- 加权输入的总和
- 非线性
这些操作在胶囊内略有变化,执行如下:
- 输入向量与权重矩阵的矩阵乘法。这编码了图像中低层特征和高层特征之间非常重要的空间关系。
- 加权输入向量。这些权重决定了当前胶囊将把它的输出发送到哪个更高级别的胶囊。这是通过动态路由、过程完成的,稍后我会详细介绍。
- 加权输入向量之和。(这个没什么特别的)
- 使用“挤压”函数的非线性。该函数获取一个向量,并将其“挤压”为最大长度为 1,最小长度为 0,同时保持其方向。
胶囊之间的动态路由
Process of Dynamic Routing. Source.
在这个路由过程中,较低级别的胶囊将其输入发送到与其输入“一致”的较高级别的胶囊。对于可以路由到的每个较高的胶囊,较低的胶囊通过将其自己的输出乘以权重矩阵来计算预测向量。如果预测向量与可能较高的胶囊的输出具有大的标量积,则存在自上而下的反馈,其具有增加该高级胶囊的耦合系数并降低其他胶囊的耦合系数的效果。
MNIST 胶囊网络体系结构
CapsNet Architecture. Source.
编码器
编码器接收图像输入,并学习如何将其表示为 16 维向量,该向量包含渲染图像所需的所有信息。
- Conv 图层-检测随后由胶囊分析的要素。如论文中所提出的,包含 256 个大小为 9x9x1 的内核。
- 初级(较低的)胶囊层——这一层是我之前描述的较低水*的胶囊层。它包含 32 个不同的胶囊,每个胶囊将第八个 9×9×256 卷积核应用于前一卷积层的输出,并产生 4D 矢量输出。
- 数字(更高)胶囊层-该层是主胶囊将路由到的更高级别的胶囊层(使用动态路由)。该层输出包含重建对象所需的所有实例化参数的 16D 向量。
解码器
Decoder Architecture. Source.
解码器从数字胶囊中提取 16D 向量,并学习如何解码其正在检测的对象的图像中给出的实例化参数。解码器与欧几里德距离损失函数一起使用,以确定重建的特征与训练它的实际特征相比有多相似。这确保了胶囊只保留有利于识别其向量中的数字的信息。解码器是一个非常简单的前馈神经网络,如下所述。
- 全连接(密集)第 1 层
- 全连接(密集)第 2 层
- 完全连接(密集)的第 3 层—包含 10 个类的最终输出
为什么我们不用胶囊网络呢?
虽然 CapsNet 在 MNIST 等简单数据集上取得了一流的性能,但它在 CIFAR-10 或 Imagenet 等数据集上可能存在的更复杂的数据上却举步维艰。这是因为在图像中发现的过量信息从胶囊中释放出来。
胶囊网仍处于研究和开发阶段,还不足以可靠地用于商业任务,因为很少有证实的结果。然而,这个概念是合理的,这个领域的更多进展可能会导致深度学习图像识别的胶囊网络的标准化。
如果你喜欢我的文章或者学到了新东西,请务必:
- 在 LinkedIn 上与我联系。
- 给我发一些反馈和评论(aryanmisra@outlook.com)。
- 查看提出这个想法的原始论文。
胶囊神经网络——自动驾驶汽车的未来
原文:https://towardsdatascience.com/capsule-neural-networks-the-future-for-autonomous-vehicles-f97bc3f7918?source=collection_archive---------10-----------------------
让我们面对现实吧。我们都不擅长拼写(也许你是个例外)🤷).希尔?他们的?确定吗?肯定吗?
无论哪种情况,我们的大脑仍然明白这是单词他们的和肯定是。
让我们试着以人脸为例。
A normal face
如果我开始把嘴移到前额,眼睛移到下巴,会怎么样?这可能更难分辨,但它仍然是一张脸。
A deformed face
卷积神经网络(CNN)通过理解面部的不同特征,在分类图像(如上图)方面做得很好。他们通过检查成千上万的样本图像并从错误中学习来做到这一点。靠*起点的卷积层有助于检测基本特征(即边缘),网络中较深的层有助于检测更详细的特征(即眼睛、嘴等)。)
CNN architecture layout
然而,您可能想知道,网络如何有效地处理所有这些数据?
最大池层数
每个卷积层之间存在一个 max-pooling 层。这些层从每个卷积层中取出最活跃的神经元,并将它们传递给下一个卷积层。这意味着不太活跃的神经元被丢弃。丢弃这些神经元是数据在网络中传输时空间信息丢失的原因。
具有讽刺意味的是,max-pooling 层运行得如此之好。通过去除神经元,你可能会认为准确性会下降,但这种做法非常有效,杰弗里·辛顿甚至说,
“卷积神经网络中使用的池化操作是一个大错误,它如此有效的事实是一场灾难”杰弗里·辛顿
这也提出了 CNN 的另一个问题。每个隐藏层中发生了什么,这些层如何相互通信?
我们需要另一种方法,可以帮助我们执行 CNN 的功能,同时改进架构以实现更强大的分类。这就是胶囊神经网络发挥作用的地方。
它们是如何工作的?
与标准神经网络中的神经元相比,胶囊网络使用胶囊。胶囊封装了输出向量的图像的所有重要信息。与输出标量的神经元相比,胶囊具有跟踪特征方向的能力。因此,如果我们开始改变特征的位置,向量的值将保持不变,但是方向将指向位置的变化。
赞成的意见
1.在较小的数据集(如 MNIST)上表现非常好
2.更容易解读更强健的图像
3.保存所有信息(姿势、纹理、位置等。)
骗局
1.不优于大型数据集(即 CIFAR10)
2.协议路由算法需要更多的计算时间
建筑:
胶囊网络(CapsNet)包含一个编码器和一个解码器。编码器和解码器总共包含 6 层。
Encoder Architecture
前三层是编码器,负责获取输入图像并将其转换为 16 维向量。创建顶点网编码器的三个层如下:
1.卷积神经网络
2.初级资本网络
3.DigitCaps 网络
第一层负责提取图像的基本特征(即找出组成数字 4 的笔画)。
第二层(PrimaryCaps)负责获取这些基本特征和寻找它们之间更详细的模式(即每个笔画之间的空间关系)。该图层中胶囊的数量因数据集而异,但对于 MNIST 数据集,有 32 个胶囊来维护最相关的信息。
就像第二层一样,第三层(DigitCaps 层)中的胶囊数量也不同。特别是,对于 MNIST 数据集,我们有 10 个胶囊;每个手指一个胶囊。
MNIST handwritten digits
为了确定初级胶囊中的哪个胶囊进入数字胶囊,较低级胶囊(初级胶囊)的重量必须与较高级胶囊(数字胶囊)的重量一致。(我们稍后将对此进行更多讨论。)
Decoder Architecture
在编码器的末端,我们得到的是一个 16 维向量。这被传递给解码器。解码器有三个全连接层。解码器的主要工作是获取 16 维向量,尝试使用 数据 从头开始重建图像。这是令人惊讶的,因为它通过基于其 自己的 知识生成预测,使网络更加健壮。
Decoder architecture breakdown
组件:
考虑到这一点,胶囊神经网络中有四个主要计算。
1.矩阵乘法
2.标量加权
3.动态路由算法
4.矢量至矢量非线性
矩阵乘法。
我们在从第一层传递到第二层的信息之间执行权重矩阵乘法,以编码理解空间关系的信息。该编码信息代表分类正确标签的概率。
标量加权。
还记得我说过,低等级胶囊的重量必须与高等级一致吗?在这一阶段,较低层的胶囊调整其重量,以便与较高层的重量相匹配。
你可能想知道:较高级别的胶囊正在接收一堆输入,它们如何选择正确的较低级别的胶囊?
嗯,更高级别的胶囊绘制出权重的分布,并接受最大的分布/集群来传递。
他们是如何交流的?
动态路由算法。
使用动态路由算法,我们可以让各层相互通信。该算法集中于“通过协议路由”的思想,这就是我们前面谈到的使胶囊的重量/内容一致。动态路由算法允许我们更好地在网络的各层之间传递数据,这在理论上会增加时间和空间的复杂性。在实践中,我们使用三次路由迭代,因为过度迭代会导致过拟合和较差的性能。
Contents of lower capsules agreeing with higher-level capsules
矢量至矢量非线性。
在执行动态路由算法并将胶囊传递到正确的位置并重建图像后,最后一步需要的是压缩信息。我们需要某种方法将所有这些信息浓缩成我们可以重复使用的东西。
我们如何做到这一点是使用一个挤压功能。
挤压函数采用最终的向量大小,并将长度压缩到小于 1 的大小,同时仍然保持向量的方向。以下是挤压函数的数学表示:
公式的左侧(红框)执行我们之前讨论的缩放。并且,右侧(绿色框)为挤压向量指定一个单位长度。
快速回顾:这个矢量输出(v_j)表示胶囊识别给定特征的概率。
损失函数:
就像传统的网络一样,网络从错误中学习。我们可以通过如下所示的损失函数来表示这种错误:
Breakdown of CapsNet loss function [Source]
如果网络以 0.9 或更高的概率预测正确的类别,则此损失函数将返回 0。否则,如果置信度小于 0.9,损失函数将返回 0 到 1 之间的数字。
外卖食品
- 与最大池层相比,胶囊网络保留了图像中的大部分信息
- 动态路由算法允许网络中的各层通过协议路由相互通信。
- 胶囊网络仍处于开发的早期阶段
- 胶囊网络在处理大型数据集时性能不足
如果您喜欢我的文章或学到了新东西,请确保:
- 查看我的 网站 !
- 通过 LinkedIn 与我联系
- 发送一些反馈(我总是乐于接受建议!)
捕捉任何视频的精髓:将其字幕可视化为图形
原文:https://towardsdatascience.com/capture-the-essence-of-any-video-visualize-its-subtitles-as-a-graph-5ce565d1820c?source=collection_archive---------25-----------------------
如何使用文本网络分析来可视化视频字幕,确定主要主题,到达叙事中最相关的部分,并产生对主题的洞察力。
如果你像我一样喜欢学习新东西,你可能会发现自己经常看视频。在进行更深入的研究之前,这是对一个主题进行概述的好方法。唯一的问题是时间。我喜欢 1.5 倍的速度功能,但它仍然浪费了很多时间,并让我接触到了我不一定需要的信息。
这里有一个解决方案:
- 将你的字幕视频想象成网络图
- 确定最相关的话题
- 提取 视频中仅包含这些主题的部分
- 使用图表生成洞察力
保证你在 3 分钟内对这个主题有一个很好的概述。如果你想看得更深,你可以以你喜欢的速度观看剩下的部分(尽管以一种更有效的方式,因为你已经知道了主要的主题)。
TL:DR — visual walkthrough of the process using InfraNodus.Com
感兴趣吗?让我演示一下它是如何工作的…
步骤 1:网络棱镜——获得视频内容的概述
首先,你需要找到一个你感兴趣的视频。它可以是 MOOC 讲座、TED 演讲或 YouTube 视频。在下面的例子中,我将使用最受欢迎的 TED 演讲之一,Ken Robinson 关于“学校如何扼杀创造力”。
然后你需要获得这个视频的字幕:这些可以作为一个文件下载,或者直接从 YouTube 上提取(因为它提供了许多不同语言的大多数上传的自动字幕)。
然后可以使用文本到网络转换算法将字幕可视化。在这个例子中,我使用了 InfraNodus 开源软件,它可以自动从任何 YouTube 视频中提取字幕文件,并将其可视化为网络图。如果您的视频不在 YouTube 上,您可以简单地将字幕从文件中复制并粘贴到 InfraNodus 中的一个新图表中。
这是结果(点击此处查看互动版):
Automatic import of the Ken Robinson talk using the InfraNodus YouTube Import feature. You can see an interactive version of this graph on https://infranodus.com/ted/iG9CE55wbtY
单词被标准化(使用词条化算法),停用词被排除(这些可以被调整),主要的主题聚类被识别(用不同的颜色指示),将这些聚类链接在一起的单词在图上被显示得更大(具有更高介数中心性的节点)。因此,我们可以在几秒钟内很好地展示视频内容:
我们可以看到主要话题有:
教育—制度—观念
人—说话—人情
听到—发生—女人
孩子—舞蹈—未来
本次演讲中最有影响力的词汇是
教育—人—年—演讲
这给了我们一个关于演讲内容的很好的想法。
第二步:非线性观看——找到视频中最有趣的部分
现在我们有了一个概述,我们可能想要有一个更精确的想法,并把我们提取的这些关键词和主题放在上下文中。
最好的方法是选择我们感兴趣的话题或关键词,例如:
教育|创造力|重要
并且在字幕上执行搜索,以找到包含这些术语的最高浓度的文本部分。如果你点击 InfraNodus 中的这些节点,你将能够找到文本的相关部分:
Click on the nodes you’re interested in on the graph to see the excerpt of video. (Use the interactive version on https://infranodus.com/ted/iG9CE55wbtY to try it out)
在这张图上,我看到了视频字幕文件的摘录,其中演讲者只是在谈论“教育”、“创造力”和“重要”。
点击摘录中的视频链接,你会直接看到肯·罗宾逊谈论这些话题的视频部分(时间码):http://youtu.be/iG9CE55wbtY?t=185
然后,您可以选择视频的其他部分,例如:
Select the topic you’re interested in on the graph, find the part of the video where Ken Robinson is talking about the importance of using dance in education, then click on the link to see him speak about this directly: http://youtu.be/iG9CE55wbtY?t=550
这提供了一种以非线性方式观看视频的新方法,专注于重要的概念,这在信息过载的情况下可以节省大量时间。
第三步:智能浏览——获取视频的要点
如果您不喜欢与图表互动,您也可以进入视频最重要的部分,前提是您为每个主题选择了主要词汇最集中的主题。
在 InfraNodus 中,这个特性是通过 Essence 选项卡实现的,本质上是一个汇总工具。它按照时间顺序排列包含主要主题的摘录,因此在您观看其中的 4 个(每个 15 秒)后,您可以对视频内容有一个很好的了解。
Too lazy to navigate? Click the “Essence” tab and see the most important stuff: https://infranodus.com/ted/iG9CE55wbtY
当然,这些数据也可以通过 API 传输到另一个应用程序,这样就可以有一个更加用户友好的界面来播放视频(不是每个人都喜欢这些图表)。让我知道如果你想建立一个这样的应用程序:)
这个功能很酷,因为你现在可以在几秒钟内以更有效的方式浏览视频,而不是观看 20 分钟长的视频或随意浏览。该算法选择意义循环的主要连接点,并帮助您找到视频中与话语形成最相关的部分。
你可以试试下面几个流行的 TED 演讲视频,看看它是如何工作的。只需打开页面,点击左上角的“精华”标签,然后跟随每个陈述的时间编码 YouTube 链接,即可访问视频的相关部分:
什么造就了美好的生活?罗伯特·瓦尔丁格关于幸福的最长研究的教训
苏珊·凯恩的《内向者的力量》
- Celeste Headlee(视频)提出的 10 种改善谈话的方法
步骤 4:产生洞察力—找出网络中的结构性差距
大多数推荐系统基于相似性工作——“喜欢你喜欢的视频的人也喜欢……”这种方法工作得很好,但它受到流行偏见的影响,可能会将观众锁定在过滤器泡沫中。
一个解决方案是开发基于不同基础的推荐系统:使用网络分析帮助从文本中产生洞察力。
基本思想非常简单:在社会科学中有一个众所周知的概念“结构间隙”——图中不相连的部分。这是创新发生的地方。如果我们在研究文本时使用这个比喻,结构空白就是新思想诞生的地方。如果你把两个之前不相关的不同话题联系起来,你会产生一种洞察力。这既可以在描述某个叙述的图表内完成,也可以在不同的图表之间完成。
在我们图表的上下文中,最突出的聚类之间的结构差距表明话语的未开发部分。
在 InfraNodus 中,如果您单击图表左上角的“Insight”窗格,可以找到这些结构性缺口:
We find the two topical clusters that are not so well connected and then propose the user to make a connection between them. Usually this leads to new ideas and insight.
如你所见,它显示了图表中的部分,以及话语中的陈述,它们足够突出,但并没有真正联系起来。因此,提出一个将两个陈述(或两组关键词)联系在一起的问题,可能会引出一个与整个话语相关的新颖想法。
本文作者 Dmitry Paranyushkin 来自Nodus Labs。如果你有兴趣了解更多关于网络分析的各种应用,请查看我在《走向数据科学:中的帖子
- 利用网络分析识别话语中的偏见
- 如何使用 SEO 和文本挖掘识别公共话语中的空白
也欢迎大家尝试开源的文本网络可视化工具 InfraNodus。在线版本可以在www.infranodus.com上获得,或者你可以下载它并在你自己的机器上运行:www.github.com/noduslabs/infranodus(如果你想贡献代码,请, 告诉我 !)
在情感人工智能中捕捉上下文:多模态视频情感分析的创新
原文:https://towardsdatascience.com/capturing-context-in-emotion-ai-innovations-in-multimodal-video-sentiment-analysis-65e128ad8a1a?source=collection_archive---------12-----------------------
利用捕获多模态上下文信息的深度神经网络进行人性化情感分类
Source: Neurodata Lab
博客基于:“用户生成视频中基于上下文的情感分析”。茯苓;坎布里亚;哈扎尔卡;Majumder 扎德;莫伦西(2017)。链接到完整的技术研究论文
介绍
我想象你正在 YouTube 上观看一个关于新电视节目首播的反应视频。不管出于什么原因,意见持有人在 5 分钟内的不同时刻表达了兴奋,然后悲伤…他们大声喊叫,然后单调…他们变得惊讶,然后厌恶。是什么让我们可以轻松解读他们的情感表达?仅仅是因为他们选择的词语吗?他们的面部特征?他们的声音强度?很可能不仅仅是声音,不仅仅是屏幕上的图像,或者不仅仅是他们选择的单词的意思。这是关于所有三者的结合,以及每一个如何随着时间的推移相互作用。
先前在“话语”级别的多模态视频情感分析中的研究忽略了视频中连续人类话语(由停顿限定的语音实例)的自然相互依赖性,而是将每个表达视为完全独立于其之前和之后的表达。视频的连续话语实际上是非常上下文相关的,因此,序列本身应该影响时间上*邻的情感分类。例如,在话语“电影的更好的名字是什么”中,说话者试图通过给出适当的名字来评论电影的质量。然而,所表达的情感需要关于说话者的举止和他/她对电影的看法的背景。先前的技术水*不能正确地对这样的话语进行分类。
来自美国、新加坡、印度和墨西哥的研究人员在 2017 年共同建立了一个长短期记忆(LSTM)分类模型,该模型整合了每一个视频的听觉、视觉和文本数据中捕捉的周围上下文信息,与之前的最先进模型相比,该模型的准确性提高了 5-10%。
视觉数据中的声音变化和面部表情,以及文本抄本中出现的语言,为更好地识别意见持有人的情感状态提供了重要的线索,从而创建了更强大的情感识别模型。虽然我将在下面总结的实验的主要焦点是对视频中的情绪进行分类(积极、中立或消极),但他们的发现可以纳入更具体的情绪分类任务中,涵盖更广泛的基本情绪类别(愤怒、快乐、悲伤、中立、兴奋、沮丧、恐惧、惊讶等)。示例业务应用包括虚拟助理的开发、YouTube 和其他数字或社交视频的分析(例如产品评论、广告活动)、新闻视频分析、心理健康专家的个人情绪监测,当然还有很多其他的。
方法学
数据集
具有不同属性和警告的三个数据集被用于测试尚未描述的模型。 MOSI 包含了 93 个人用英语评论话题,并且充满了感性的表达。每个片段由多位评委从-3 到+3(负面情绪到正面情绪)打分。在实验中,取*均值,得到高于 0(积极情绪)或低于 0(消极情绪)的二进制数。 MOUD 包含来自 55 个人的西班牙语产品评论视频(用谷歌翻译翻译),话语被标记为正面、负面或中性。丢弃中性视频后,使用了 59 个视频。
Train-Test Split Number of Samples by dataset
在我看来,使用的最令人兴奋的数据集是 IEMOCAP 数据。这组包括 10 名英语使用者,进行双向对话,话语标有情绪:愤怒、快乐、悲伤、中性、兴奋、沮丧、恐惧、惊讶或其他(最终研究人员只选择了前四种来与之前的最先进的研究进行比较)。
上下文不可知的单峰话语级特征提取
最初,研究人员在他们的第一次特征提取中没有考虑话语之间的上下文相关性。
文本:使用 CNN 从视频口述文字的文本抄本创建模型输入
使用卷积神经网络(CNN),研究人员首先将每个话语表示为所用单词向量的串联,其中向量是在谷歌新闻的 1000 亿个单词上训练的公开可用的 300 维 word2vec 向量。简而言之,为了提取每个单词、每个话语以及最终每个视频的情感,CNN 将文本话语转换为逻辑形式:机器可以理解的含义表示。
音频:使用 openSMILE 的声音描述特征提取
音频特征是使用 openSMILE 以 30 Hz 的帧速率和 100 ms 的滑动窗口提取的,open smile 是一种开源软件,可以自动提取音调和声音强度等声音描述符。语音强度被阈值化以识别有意义语音和无意义语音的样本。
视觉:利用 3D-CNN 进行基于图像的特征提取
在假设 3D-CNN 不仅能够从每一帧中学习相关特征,还能够学习给定数量的连续帧之间的变化的情况下,该团队选择了这一方法来提取每一个话语的视频特征。使用 3D 卷积过滤器、最大池、密集层和 softmax 提取相关特征。
上下文相关的特征提取:时间和顺序问题
由于视频中的话语保持一个序列,并假设在识别情感暗示时话语间存在依赖性,研究人员使用了一种基于 LSTM 的递归神经网络(RNN)方案来分类话语。这与传统的前馈神经网络相比有何不同?好吧,一个经过训练的前馈网络可以暴露于任何随机的照片集合,并且它暴露于的第一张照片不一定会改变它如何分类第二张照片。没有时间的概念,因为这些网络只记得他们的训练,而不是他们最*的过去。然而,rnn 不仅接受当前输入,还接受之前感知到的输入。最*的过去事件和 RNNs 更接*于我们如何实际感知我们所见所闻的情感背景。
简单来说:在下面的动画中,每个 x(红色)是一个输入示例, w(蓝色)通过确定当前输入和过去隐藏状态的重要性来准备输入, a(绿色)是隐藏层的激活(过滤后的输入和类似“记忆”的输入的组合),而 b(橙色)是每个时间点的输出,其类似“记忆”的信息在该时间点被转发给 RNN
Recurrent Neural Network Animation (https://imgur.com/kpZBDfV)
长短期记忆单位(LSTM):人工递归神经网络的一种变体
作为人类,我们不会也不应该记住所有的事情。我们最*的过去更生动,一般来说,我们遥远的过去对我们当前决策的影响略小。为了做到最好,我们会有意识或无意识地决定哪些东西要储存在记忆中,哪些东西要忘记,哪些东西要学习,以及在做决定的时候需要哪些东西。这个比喻可能并不完美,但 LSTMs 是相似的,因为它们通过打开和关闭的门来做出这样的决定。这些门控细胞通过猜测、反向传播误差和通过梯度下降调整权重的迭代过程来学习何时允许数据进入、离开或删除。LSTM 使一种选择性记忆成为可能。它允许递归网络在更多的时间步上继续学习,具有在有意义的时候忘记的灵活性(例如。扫描全新文档上的文本信息,而之前的文档应该被认为是完全不相关的)。这些特征使得它成为随着时间的推移对许多连续的单词、许多连续的话语和许多独特的视频进行情绪和情感分类的首选模型。
Long Short-Term Memory (LSTM) Graphic — Circle = open gate, allows information to pass, Dash = closed gate, blocks information from passing through — (https://skymind.ai/wiki/lstm#long)
“情境-LSTM”架构和模型培训总结
为了避免过于技术化,上下文 LSTM 模型的输入是一个矩阵,该矩阵由所有 3 个单峰特征的每个视频的每个话语的向量构建而成。每个话语向量通过一个 LSTM 单元。然后,将 LSTM 单元的输出引入 dropout,正则化方法,通过临时丢弃随机选择的网络节点来减少过拟合并提高模型的泛化能力。然后,输出被传递到一个密集层,为 softmax 激活准备上下文相关的功能。最后,输出被传递到一个 softmax 激活层,它压缩一个介于 0 和 1 之间的向量,其中所有结果元素相加为 1,产生将决定分类的类概率。
Contextual LSTM network: input features are passed through a unidirectional LSTM layer, followed by a dense and then a softmax layer. The dense layer activations serve as the output features. (https://aclweb.org/anthology/P17-1081)
对每个视频的每个话语的 softmax 输出使用分类交叉熵损失来执行 LSTM 网络的训练。由于视频具有不同的话语计数,因此使用填充作为中性话语。为了避免网络中过多的噪声,对这些填充的话语进行位屏蔽以消除它们在网络中的影响。在 80%/20%训练/测试分割之后,在训练集上进行超参数调整。 RMSprop 已被用作优化器,它通过使用移动*均值而不是让*方梯度的估计值不断累积来解决 Adagrad 的学习率急剧下降的问题。
与上图中显示的单向 LSTM 细胞不同,报告中表现最好的分类器最终被证明是双向结构。双向 lstm 是两个方向相反的单向 lstm 堆叠在一起。这意味着一个话语可以从视频中出现在之前和之后的话语中获得信息,这似乎更接*我们实际感知的表达上下文。
模态融合综述
研究人员提出了一个由两个层次组成的分层深度网络,以融合三种模态——文本、视觉和听觉。在第一级中,独立于上下文的特征被馈送到上述提出的 LSTM 网络,以获得每个话语的上下文敏感的单峰特征表示。三种模式中的每一种都使用单独的 LSTM 网络。在第二级中,来自第一级中的每个 LSTM 网络的输出被连接并馈入这个新的 LSTM 网络,该网络被独立地训练和计算。
Hierarchical architecture for extracting context-dependent multimodal utterance features. (https://aclweb.org/anthology/P17-1081)
结果和分析
上下文改进分类
双向 LSTM 网络变体,以及研究人员测试的许多其他变体(这里没有提到),在所有数据集上明显优于基线单 SVM,相差 2%至 5%,证明了研究人员最初的假设,即对话语之间的上下文依赖进行建模(单 SVM 无法做到)可以改善分类。 在话语级别的情感分类中,需要考虑上下文相关性是很重要的。
多模态模型优于单模态模型
Accuracy % on textual (T), visual (V), audio (A) modality and comparison with the state of the art (https://aclweb.org/anthology/P17-1081)
正如所料,在这种情况下和许多其他类型的实验中,双峰和三峰模型优于单峰模型。总体而言,音频 在所有数据集上的表现都优于视觉 。在 MOSI 和 IEMOCAP 数据集上,文本分类器实现了最佳性能。所有分类器在 IEMOCAP 数据集中分类中性话语时都有困难。文本模态与非文本模态相结合,大大提高了 IEMOCAP 的性能,在这种情况下比在其他数据集中要大得多。
在 MOUD 数据上,文本表现不如音频,可能是由于西班牙语到英语的翻译。保持其原始语言 将性能提高 10%(西班牙语),但牺牲了与最先进语言(英语)的可比性。在评估可推广性时,研究人员发现 跨语言场景中的面部表情比音频和文本模态携带更多的可靠信息(通过在 MOUD 数据上测试 MODI-fed 模型)。没有任何其他话语级别的多情感数据集来测试 IEMOCAP 模型的可推广性。
在整个数据集中发现了有意义的上下文关系。为了说明模态的相互依赖性,语音“谁根本没有任何存在或伟大”被音频分类器分类为肯定的,因为“存在和伟大”是带着热情说出的。然而,语篇情态抓住了“不”所诱导的否定,并将量词推向正确的方向。在一个不同的例子中,文本分类器仅仅根据看到“喜欢看”和“负责任地”,将话语“喜欢看到漫画人物被负责任地对待”分类为肯定的。这个人声音中明显的愤怒和生动的皱眉有助于识别这是消极的。有许多例子表明,一个模态的强度压倒了从一个情境较弱的模态中收集的模型的预感,也有例子表明,周围环境错误地压倒了一个微弱或中性的瞬间情绪。
总的来说,该模型并不完美,但它绝对是向前迈出的一步,并增加了复合证据,表明我们生活在一个非常令人兴奋的以情感为中心的人工智能时代!
感谢您的阅读,
亚历克斯
链接至 全文技术论文
我们来连线!我鼓励你喜欢、评论、分享或直接给我发消息,告诉我你对这里提出的想法的想法,或者对我今后应该关注的有趣主题的建议。
www.linkedin.com/in/alexandershropshire
medium.com/@as6140
github.com/as6140
汽车型号分类
原文:https://towardsdatascience.com/car-model-classification-e1ff09573f4f?source=collection_archive---------8-----------------------
在这篇文章中,我将展示 ResNet(残差神经网络)汽车模型分类的结果。我使用 Python 和 Pytorch 来构建模型。这些步骤类似于我以前的花卉种类分类器项目,所以我将简要介绍一些关键步骤和结果。
你可以在这里查看我的 github 回购。
数据集
我使用 Kaggle API 从 Kaggle 下载了斯坦福汽车数据集,并保存在我的 google drive 中。
# The Kaggle API client expects this file to be in ~/.kaggle,
!mkdir -p ~/.kaggle
!cp kaggle.json ~/.kaggle/# This permissions change avoids a warning on Kaggle tool startup.
!chmod 600 ~/.kaggle/kaggle.json#mount my gdrive
from google.colab import drive
drive.mount('/content/drive')#download the dataset
!kaggle datasets download -d jutrera/stanford-car-dataset-by-classes-folder#unzip the file
!unzip stanford-car-dataset-by-classes-folder.zip
汽车数据集包含 196 类汽车的 16,185 张图像。数据被分成 8,144 幅训练图像和 8,041 幅测试图像。
迁移学习
迁移学习利用在解决一个问题时获得的知识,并将其应用于另一个不同但相关的问题。
这里的预训练模型是 ResNet(残差神经网络)。
人工神经网络通过对实例和以往经验的学习来预测结果。人工神经网络并行执行计算,并创建自己在学习期间接收的信息表示。在人工神经网络中,只需增加一层,即卷积层。
Image Source: Towards Data Science
关于 ResNet 架构的进一步解释,你可以参考这里的。
回到我们的例子,我们有 196 类汽车作为输出总数,所以我们需要将输出层改为 196。
num_ftrs = model.fc.in_features
model.fc = nn.Linear(num_ftrs, 196)
验证准确性
The Epochs
我尝试了一些参数,并多次运行 epochs。最后,经过 10 个时期,它给了我们 77.72%的验证准确率,这是我迄今为止尝试过的最好的结果。训练过程真的很费时间,只需要耐心。加油!
结果呢
让我们看看它实际上做了什么!!
对于奔驰 S 级轿车 2012 年的模型预测奔驰 E 级轿车 2012 年是不准确的。梅赛德斯-奔驰 S 级轿车 2012 也没有出现在预测的前五名中。宝马 X6 SUV 2012 预测不完全正确,因为它出现在第三个顶级车型中。它应该是预测结果中的顶级车型,而不是 2012 款福特嘉年华轿车。
现代 Veloster 掀背车 2012 和大众高尔夫掀背车 2012 预测良好,超过 30%。
两者都是宝马 3 系 2012 款轿车,只是视角不同而已。左图是前视图,右图是后视图。
令人惊讶的是两种不同观点对宝马 3 的预测都正确。左侧的前 5 名预测结果非常好,因为它预测前 5 名都是宝马。在右侧成绩也不错,宝马出现在前 3 名。
然而,在这种情况下,宝马 M5 轿车 2010 年没有表现,它得到了所有前 5 名预测类错误。任何宝马汽车型号都没有出现在结果中。
在这种情况下,两个模型都是 SUV 模型,且预测正确。
就是这样!
线性回归模型在二手车市场中的应用
原文:https://towardsdatascience.com/car-selection-and-sales-day-prediction-8c4a474f9dca?source=collection_archive---------12-----------------------
这个项目的灵感来自托马斯·米勒的书 “营销数据科学:用 R 和 Python 进行预测分析的建模技术” 中的 Drivetime 轿车案例研究。作者只提供数据集和问题陈述。您可以在这里访问数据集和我的 R 代码 。
1。简介
Drivetime 是美国第二大汽车零售商,专门经营二手车。该公司成立于 2002 年,在 8 个州拥有 76 家经销商。Drivetime 的使命是“成为信用不太好的人的汽车经销商和金融公司”,通常每月出售约 4000 辆二手车,处理约 1 万份信用申请。
Drivetime 从拍卖行和批发商那里购买了大部分车辆。车辆包括许多品牌和型号的轿车和卡车。经过检查和维修后,车辆被送往经销商处进行销售。正常的经销商销售发生在交付给经销商的 90 天内。如果这辆车在 90 天内没有卖出去,它就被称为超龄车,这意味着它在停车场待得太久了,无法产生正常的经销商利润。
为了鼓励在 90-119 天内销售,每辆超龄车的销售价格都会降低。此外,如果超龄车辆未能在 120 天内售出,该车辆将被从停车场中取出并拍卖。这些超龄车辆导致利润减少,甚至驾驶时间损失。更具体地,当非超龄车辆以 20%的加价出售时,超龄车辆的价格被设定为 10%的加价,而车辆以-20%的加价拍卖。
进行这种分析是为了在驱动时间支持采购经理的选择过程。主要目标是提高 90 天内售出车辆的比例,降低车辆超龄和拍卖的风险,并使公司利润最大化。
我们的分析包括 3 个主要部分:
1 —数据特征和探索
2 —模型选择、解释和预测
3 —建议和结论
2。数据探索
该数据集中有 17506 个数据点,其中 8753 个被标记为训练数据,5376 个被标记为测试数据,其余为验证数据。数据集中没有缺失的数据。
下表总结了数据集中的所有变量:
为了更好地理解我们的数据集,我们对我们的单个变量和它们之间的关系进行了探索性分析。
Histogram of Total Cost, Vehicle Age, Mileage and Lot Sales Days
连续变量的直方图显示,虽然总成本、车龄和里程遵循正态分布,但销售天数数据是左偏的。大多数车辆的行驶成本为 4000-6000 美元,购买时的车龄为 3-7.5 年,里程主要在 50000-100000 英里之间。此外,80%的车辆将在 90 天内售出。
Correlation Heatmap between continuous variables
下面的相关性热图说明了销售天数与里程和车龄的关系并不密切,与总成本的正相关性略好。这意味着,一般来说,如果车辆的成本高于其他车辆,则该车辆往往会在更长的时间内售出。销售天数和其他连续变量之间的散点图证实了我们的观察,即成本、里程和销售天数之间没有强而清晰的线性关系。
接下来,我们查看分类变量,以确定是否有任何影响销售天数的重要因素。
就销售速度而言,国产汽车和进口汽车之间似乎没有明显区别。就车型而言,经济型汽车的销售速度似乎略慢于家庭型汽车和豪华轿车。*均而言,销售一辆经济型汽车需要 51 天,销售一辆豪华型汽车需要 39 天,销售一辆家庭型汽车需要 47 天。
制造商品牌似乎对销售日有很大影响。一些快销二手车倾向于本田、克莱斯勒、道奇、现代、普利茅斯等。而大宇、奥兹莫比尔、别克和 GEO 汽车在出售前会在停车场停留更长时间。这些车辆在使用几年后往往会保值。销售时间取决于许多因素,如折扣、1-3 年后的价值贬值、品牌的可用性和受欢迎程度等。
一些州,如加利福尼亚、乔治亚、德克萨斯的销售天数明显低于其他州,如亚利桑那、佛罗里达、内华达。亚利桑那州和佛罗里达州的车辆*均分别在 53 天和 57 天内售出;德克萨斯州和乔治亚州的车辆分别在 39 天和 42 天内售出。这种差异可能是由于各州关于各种费用(如经销商文件费、注册费、当地州税)的规定不同,这些费用会影响这些州对二手车的需求。此外,各州的人口和失业情况也可能是一个重要因素。例如,佛罗里达州和亚利桑那州是美国著名的退休目的地,因此这两个州的二手车需求通常低于其他州。
数据集中的另一个重要变量是 make.model,表示车辆的品牌和型号。在我们的数据中观察到 110 个模型。一些车型出现的频率非常高,如雪佛兰 Lumina、福特金牛座、日产 Sentra(超过 900 次),而一些车型很少出现,如讴歌 Vigor、别克 Lasabre 或雪佛兰 celebrity (1 次)。为了在对数据构建预测模型时进行准确的概括和预测,我们将移除模型频率小于 4 的观测值。准备建模数据集包含 17469 个数据点。
3。型号选择&预测
我们将使用训练数据来构建模型,测试数据来评估模型的拟合程度,验证数据来预测利润,并查看模型对利润的影响。
我们将使用回归模型构建两个模型,以了解它们之间的区别:
Difference between 2 models
如上所述,品牌/型号有超过 100 个值,它也很好地表明了品牌和车型信息。它还包含其他信息,如燃油效率、电动或混合动力汽车等。因此,在一个回归模型中包含所有品牌/型号、品牌和车型可能是多余的。
这两个模型的结果向我们展示了可以指导 Drivetime 车辆选择流程的见解:
- 每多行驶 10000 英里,*均销售天数就会增加 2.53 天
- 总成本增加 100 美元,销售天数*均增加 2 天
- 车龄每增加一年,销售天数*均增加 9.83 天
- 颜色:与黑色相比,蓝色、绿色、紫色、红色和白色分别增加销售天数 9.29 天、6.47 天、8.72 天、11.5 天和 8.7 天。就销售时间而言,金色和黑色之间、银色和黑色之间没有显著差异。
- 品牌:与别克相比,除了大宇和奥兹莫比尔之外,其他品牌的销售天数更短。一些品牌有许多最短的销售天数是本田(缩短 59 天),丰田(缩短 36 天),凯迪拉克(缩短 57 天),克莱斯勒(缩短 34 天),马自达(缩短 30 天)。
- 州:亚利桑那州是销售额最高的州。其他州 CA、VA、NV 的销售日缩短了 9-11 天。佐治亚州、佛罗里达州和德克萨斯州的销售时间比亚利桑那州短 2-4 天。
- 车型:经济型汽车销售时间最长。豪华和家庭大型和家庭中型的销售时间最短(比经济型短 40 天)
- 一些销量最快的车型有英菲尼迪 J30、英菲尼迪 Q45、马自达 Millenia、本田雅阁、凯迪拉克赛维莱、丰田凯美瑞、日产千里马等。销售最慢的车型是普利茅斯喝彩,奥兹莫比尔塞拉,Geo 地铁,现代口音,道奇精神…等等。
下表比较了两种型号的性能:
模型 2 在预测销售天数方面似乎更好。模型 1 解释了 20.2%的销售天数变化,而模型 2 可以解释 32%的销售天数变化,剩下 68%无法解释。
非超龄准确性是说明在指导驾驶时间选择过程中使用统计建模的改进的重要因素之一。如数据特征部分所述,Drivetime 购买的约 80%的车辆在没有任何统计模型的情况下在 90 天内售出。在我们将模型 1 或模型 2 应用于测试数据后,我们建议 Drivetime 只购买预计不会超龄的车辆,避免购买预计超龄或拍卖的车辆。这些预测的非超龄车中,82%和 84%实际在 90 天内售出。使用模型 1 和模型 2,精度分别提高了 2%和 4%。
接下来,我们使用验证数据来检验使用统计模型对驾驶时间利润的影响。我们知道,一辆非超龄车以 20%的加价出售,一辆超龄车的价格被设定为 10%的加价,一辆车以-20%的加价拍卖。因此,与在没有统计模型的指导下选择车辆相比,模型 1 预计将增加利润 10,720 美元,模型 2 预计将增加利润 26,406 美元。
4。建议&结论
对于零售商来说,在预测保持利润和降低库存成本的畅销车辆时,二手车市场涉及许多因素。颜色、车辆类型、品牌、型号、里程、成本和车龄是我们有机会分析的影响二手车在停车场停留时间的一些重要因素。一般来说,顾客的偏好是多样而复杂的。然而,Drivetime 可以优先购买二手车中的一些非常理想的特征:
客户似乎更喜欢黑色、银色、金色或白色的车辆
需求量大的汽车品牌有本田、道奇、克莱斯勒、丰田、凯迪拉克、马自达。驾驶时间应该避免大宇,Geo,奥兹莫比尔或别克,因为这些品牌很不受欢迎,需要很长时间才能卖出去
豪华和家庭型汽车比经济型汽车卖得快。
位置对销售日影响很大。在佛罗里达和亚利桑那等销量较低的州买卖二手车时,Drivetime 应该关注颜色、品牌、低里程数和车龄等其他非常受欢迎的特征。
驾驶时间应该更喜欢购买里程少、价格低、车龄短的车,在其他特征方面要在两辆同等的车中进行选择。
列出 20 辆销售最快的车,多买几辆。
从现在开始,Drivetime 应该采用模型 2 来指导他们的选择过程。该模型可将驾驶时间利润提高 1.06%。
建议未来的研究探索影响二手车销售期的其他因素。例如,燃油效率水*、车辆是电动还是混合动力、原价折扣水*……将这些因素纳入分析中可以提高选择非超龄车辆的准确性,并对利润产生积极影响。
我是加州大学戴维斯分校的 MBA 学生。我对营销分析、建模、机器学习和数据科学充满热情。本文属于我 MBA 项目下的独立学习。非常感谢我的同学 Jamie Ho 对这个项目的贡献。如果您有任何意见、反馈或问题,请随时通过 mapnguyen@ucdavis.edu 联系我,或通过 、LinkedIn 联系我。快乐造型!
卡反人类卡代(略 NSFW)
原文:https://towardsdatascience.com/cards-against-humanity-card-generation-slightly-nsfw-a9c132d88345?source=collection_archive---------18-----------------------
出于最愚蠢的原因使用 Char-RNNs
(警告:《反人类纸牌》是一款成人主题游戏,包含大量粗鲁语言。这篇文章不会展示任何图形,只有文字,但它仍然会让你在工作场所看起来很奇怪)
什么是幽默?人工智能能理解是什么让事情变得有趣吗?写一篇中等的帖子能验证你花在训练电脑说脏话上的时间吗?
今天我不会回答这些问题。但希望我们都能从“人工智能”生成的 CAH 卡片中获得一点乐趣,并更深入地了解是什么让这项任务变得特别困难。
首先,我要说的是,我并没有在这里开创新的领域。文本生成已经有一段时间了,而且是由比我聪明得多的人完成的。所以我不会试图详细解释我在这里使用的深度学习方法。如果你和我一样是深度学习的书呆子,我就只说模型结构是嵌入- > LSTM- >脱落- >稠密(char list 的长度)。
这项任务有一些具有挑战性的部分,所以我将在下面给出一个简短的解释。如果你只是想看我制作的卡片,请随意往下跳。
数据问题和我为什么作弊
任何深度学习项目的第一步都是找到数据。谢天谢地,一群疯狂的人已经花时间为每张 CAH 卡片创建了一个电子表格,包括由第三方创建的自定义扩展。这意味着我可以只使用大约 2k 的官方白色卡片来训练模型,或者使用另外大约 19k 的第三方白色卡片。我使用白色卡片是因为有更多的例子可以训练,但是我保证当模型试图创建黑色卡片时,会给你一种感觉。
所有这些漂亮数据的问题在于,它们极其多样化。在其核心,深度学习是训练一个程序来识别模式,在这种情况下,复制它们。创建一个生成莎士比亚剧本的模型很容易,因为莎士比亚有一致的声音,谈论相对相似的内容。虽然 CAH 确实有独特的声音,但它没有一致的内容。当引入第三方卡时,清晰的声音变得模糊。
这样想吧,你在学习一门新的语言,我给你两段阅读。其中一个是简短的电影评论,另一个是一系列不相关的短句,当与其他看不见的句子搭配时,这些短句旨在让该文化的人们发笑。如果我让你翻译两个,你觉得哪个会更容易?我认为是前者,因为当你不知道一个单词的意思时,你可以依靠它周围的上下文来帮助你。
由于这种多样化数据的挑战,我不得不作弊一点。我不是直接把神经网络的输出加入到生成的卡片列表中。在卡片上做了一点后期处理,并通过人工选择来剔除那些显然毫无意义的卡片。我意识到这是作弊,但请把这个系统更多地视为一个“卡片创意生成器”。不过,我也会向您展示一些原始输出。
在网络产生潜在的卡片后,我让它们通过文本处理器,检查它们与我的数据集中的卡片的相似性。相似的卡片是不可避免的,但我正试图消除那些与数据库中的卡片没有明显区别的卡片。一点必要的过度拟合也意味着网络偶尔会产生一张它看到的卡片的精确副本。
然后我用自动拼写校正器检查这些卡片。这修复了网络造成的小拼写错误,并且仍然是完全自动的,所以在我看来这是一个公*的游戏。完成后,我选择最好的卡片,并将它们添加到我的生成卡片列表中。
S 怎么把牌给我!
下面是我挑选的 50 张白色卡片:
- 永远好色
- 一堆辛勤工作的结肠染色的狗屎
- 一门无意的感情科学
- 大浴室
- 低矮的树枝
- 太迟了
- 被毛
- 白布丁
- 偷偷挠肉
- 一个死了的大胖妓女
- 同性恋
- 试图用一个大的便便手指做爱
- 独角兽棍子
- 不是瑕疵
- 军事决策
- 忘记至上的观念。
- 恶霸保险杠
- 一堆惊喜性爱录像带。
- 干燥的医用润滑油
- *乎不恰当的交往。
- 你妈妈的迷恋对象。
- 一个在吸管杯中的男人
- 好盒子
- 好色的白人正义。
- 打嗝的芭蕾舞演员
- 让面包变红的孩子。
- 感觉特朗普的网站。
- 小丑公鸡。
- 去猴子酒吧
- 不是武器。
- 一个 6 岁的保姆。
- 我地下室里的节流孔
- 一系列破旧的卡片
- 悲伤的阴茎。
- 爸爸的搞笑婊子。
- 我旅行后的避孕套。
- 忍受学校
- 抱着妈妈
- 只是想交流的性阴道
- 几块有酒脑的木板
- 膨胀的大小。
- 奶奶训练。
- 唱着“哦,坦南巴娜娜”
- 69%的人
- 只是一个爱心包
- 手指婊子
- 可悲的标准
- 在世界之巅购买处女
- 油炸的东西
- 抱歉。
有意义的卡片代表了网络产生的结果的三分之一。诚然,上面的一些卡片没有意义,但一些有意义的卡片很无聊,有趣的是创造一些无意义的卡片。
下面是我的网络的原始输出(稍微格式化但未修改)的样子:
penis.
a shit-to-fie
the contraction of a burrito.
the ring my slowl sorr that tells you with the chinese dogs. public motherwease.
female social suberious with forgetting to parol into a petrodomined body show.
an erection that lasts for hours.
aming down on a game of minivan
the poor
a female orgasm
subway shaving a single panties.
a keyback horse with a tremendous dingus.
an 80-year-old girlfriend
a burger silence
recaulation
zego for one
magic human remains for your secret school. inappropriate labor.
having sex with a dead baby fetus.
(rangta butt pullting people.
being kernels for domester of the mongrey.
a flamboyant man that fires a smiling prince.
a valladian memo baby.
idiots
a somen sort of this with the color off the side to. spending the nuit as every day
smelling sex lives of sexual charases.
getting tape on it.
a doctor with a sopping wet vagina.
a fairy food.
making up for your home.
incurable some sexy tantrum.
buffalo big destroying pop
如果你玩 CAH,你可能会认识一些。“鸡鸡”、“傻逼”、“穷人”都是直接抄牌。而“女性高潮”只是对“女性高潮”这张牌的一个小小的修改。这是网络记忆一些卡片,然后把它们吐出来。这就是为什么我在接受这些卡之前,会分析它们与数据库中其他卡的相似性。
Average number of words in a card was 4.94
你还会注意到,我在上面贴的白色卡片列表中几乎没有更长的卡片了。原始输出应该会告诉您原因。网络无法学会将更长的有意义的句子串在一起。我认为这主要是因为数据集中长卡片的数量很少。
黑卡(准备一些垃圾)
- 每个成功的男人都是 _ _ _ _ _ _ _ _ _ _。
- 没有人认为我是一个强大的愿望与 __。
- 蛋头舞是你被难民恐怖分子杀死的机会。
- 新的早晨,有 _______ 和 ______。
- ______ 的声音有什么用。
- 醒来时我丈夫会说 _ _ _ _ _ _ _ _ _
- 我就知道我们会是对的!
- 接下来人们发明了 ______。
- 我上一份工作中臭名昭著的一面是 ________。
- _______ 是我生命中的一个明确标志。
我可以继续说下去,但很明显,即使是最优秀的黑牌例子也没有什么意义。它们也更容易从网络试图记忆的卡片中获得。
同样,这里有一个网络原始输出的例子:
nothing is better the good of death?
check out my new podcast about ______ and ______.
ted cruz caused a still want of ______.
the red room for eating ____ for a kirld and gentler ______. the probilew recommend a trip was completely ruined by ______. ___________. a wedding is a the face.
on cheeristed ______ for his/her dont combrate your signessant-class impressed the only acceptable to have ____ in public.
g go goage ______.
______ is a sure sign of my life.
snatch and ______.
what's the biggest source of tenish in the charge of ______. what do you were a parent when i never have to be a proctive in raid of ______.
momes, my imanager compaint for ______.
i wonder if ______ was all over the poil.
immers is now explore the honors using lose in the country black, ive had a horrible vision, father. i saw mountains crumbling, stars falling from _____.
there can a parent that did you have a moment to talk to my kids and do with ______.
i got have ______.
结论时间
总的来说,我认为这个项目是一个有点有趣的失败。白色卡片通常很有趣,但让我想起了一个小测验,你可以用你的姓和名的第一个字母来创造你的“妓女名”或其他什么。它只是把单词拼凑在一起,并希望它是有趣的。我们甚至不要谈论黑卡。显然需要更多的例子。
我猜一个更接*“最先进”的网络可能会做得更好(没有狗屎),但我不确定它会更好。我认为它会产生更一致、更少抄袭的结果,但它的笑话可能不会更好。问题是,为了做出好的原创卡,你必须意识到你周围的文化和事物。像这样的网络只知道已经创建的卡。
我能想到的解决这个问题的唯一方法是,在许多主题的更广泛的文本数据库上训练一个更先进的网络,然后专门让它完成生成卡片的任务。但如何做到这一点目前超出了我的能力。
如果你有任何想法如何做到这一点,或者只是更好的方法来完成这项任务,请让我知道。我很想听听你的反馈。如果你有这个帖子,我也很乐意收到反馈。我还在学习写这些文章,我可以使用一些建设性的批评。
链接到卡片组(仅限白卡)
职业转换者对你梦想中的技术工作的指导,第 1 部分
原文:https://towardsdatascience.com/career-switchers-guide-to-your-dream-tech-job-part-1-949b9acff4d8?source=collection_archive---------12-----------------------
去你梦想中的公司面试的建议
简介——从华尔街到谷歌总部
2019 年 3 月 31 日,我被一家初创对冲基金裁员。在过去的 10 多年里,我一直是金融行业的定量软件开发人员,我不想再做同样的工作。我开始追寻自己的激情,在人工智能/机器学习/深度学习(AI/ML/DL)领域找到下一份工作。在接下来的 6 个月里,我朝着这个目标努力工作。到 2019 年 9 月,我有多个与 ML 相关的现场面试和报价,包括来自谷歌和脸书的报价。以下是我的做法,希望它能鼓励和帮助其他潜在的职业转换者进行这种转变。你换工作的回报是双重的,智力上和经济上。
Googleplex: Google’s Worldwide Headquarters. Source Google.com
行动纲要
如果你时间不够,这里有一个对我有效的快速 5 步食谱。
- 策划:做一个对你有热情的项目,并在网上展示
- 学习:集中练习算法和数据结构编码和系统设计问题
- 应用:利用多种渠道落地面试
- 面试:在电话和现场面试中保持冷静
- 谈判:在谈判报价和与球队比赛时,知道自己想要什么
正如你所看到的,这是一个非常简单的 5 步食谱。然而,完成每一步都需要付出很多努力。详情请继续阅读。
关于我
这里有一点关于我的,因为我认为这个指南对与我有类似背景的人最有帮助,即,在非技术行业有经验的软件工程师/开发人员希望转到西海岸(湾区或西雅图)的顶级技术公司。如果你没有软件工程的工作经验,上面的方法仍然适用于你,你只需要比有编码经验的人更加努力。
我毕业于加拿大滑铁卢大学,是一名计算机工程师。在我早期的职业生涯中,我是微软和甲骨文的软件工程师。然后 MBA 毕业后转行进入量化金融行业。在过去的 10 多年里,我在美国银行、瑞士联合银行、Citadel 和一些小公司担任定量开发人员/分析师。但是从 2016 年开始,当我第一次偶然发现机器学习/深度学习的时候,我就爱上了它。我知道我最终想要一份人工智能/人工智能领域的工作。从 2019 年 4 月开始,我开始了我的全职准备这个职业转换。下周我将搬到湾区,加入人工智能和人工智能领域的领导者之一谷歌。
[## David Tian 机器学习工程师-个人项目| LinkedIn
一个经验丰富的 C++/Python 机器学习工程师,具有大规模系统设计的深入知识,实践…
www.linkedin.com](https://www.linkedin.com/in/dctian/)
成功的 5 个简单步骤
第一步。策划:做一个很酷的项目并展示出来
2019 年 2 月,我的好朋友伊戈尔鼓励我创建一个很酷的项目并写下来。当时,我没有任何好的想法,从未在网上发表过任何东西,也不知道从哪里开始。但在 4 月初,当我和家人在墨西哥度假时,一天晚上我突然有了一个启示,我想制造一辆自动驾驶汽车。鉴于我之前没有机器人或电子方面的经验,我开始建造一辆可以在我的客厅里运行的深度学习/自动驾驶机器人汽车 DeepPiCar 。一个月后,在成功制造了自动驾驶汽车后,我开始写一篇关于走向数据科学的 6 篇博文,教别人如何制造一辆汽车。几周之内,我的博客就被浏览了 10,000 次,全世界读者的反应是压倒性的。我觉得我两个月的辛苦工作——一个月造汽车,另一个月写博客——非常值得。
DeepPiCar running in my living room
然而,我并没有意识到它对我职业生涯的全面影响,直到我参加面试并提供团队匹配电话,面试官问我“你为什么想从目前的行业跳槽?”我准备好了谈话要点!我不仅能够告诉他们我对 AI/ML 的热情,当我从背包中拿出我的汽车(是的,实际的机器人汽车)并把它放在面试官的手中时,我可以从他们的眼中看到兴奋!他们中的许多人甚至说他们愿意和他们的孩子一起制造这样一辆车。然后我告诉他们,我已经在网上发布了完整的分步说明和源代码(在我的简历中有链接),供他们遵循。我很确定他们之后不会把我的简历放进回收站。;-)
我的一些朋友问我,我建议做什么样的好项目。以下是我的一些建议:
- 如果你想过渡到前端开发,创建一个与流行的开源框架有很多交互性的酷网站,比如 React 和 Angular 。
- 如果您对服务器端开发感兴趣,尝试使用分布式服务器技术创建一个网络爬虫或搜索引擎,如 Cassandra 、 ZooKeeper 、 Memcached 和 Elastic Search 等
- 如果你对移动设备感兴趣,试着创建并发布一个苹果/安卓应用。注意,在苹果的 App Store 上发布一个应用,要比谷歌的 Play Store 花的时间长得多。
- 如果你对 AI/ML 感兴趣,就拿现有的计算机视觉或者自然语言处理深度学习模型中的一个,试着用它做一个产品出来。比如我拿了一个预先训练好的物体检测模型,SSD ,改编成我的 DeepPiCar 的交通标志检测器。如果你是人工智能/人工智能的新手,一定要阅读 DeepPiCar 的第 1 部分,在那里我列出了几个人工智能课程和资源来帮助你入门。
- 如果你对机器人感兴趣,试着用树莓 Pi 或 Nvidia Jetson Nano 制造一些很酷的机器人。确保使用新的树莓 Pi 4 或杰特森纳米。Raspberry 更广泛地被创客使用,并享有更好的支持,而 Jetson Nano 板载 GPU,因此它可能更适合深度学习项目。
- 如果你没有任何项目想法,不要绝望。你可以随时为上面提到的开源项目做出贡献,如果你对 AI/ML 感兴趣,也可以为 TensorFlow 或 PyTorch 做出贡献。你可能认为你需要成为一名专家来为这些众所周知的开源项目做贡献。你没有。实际上,在每一个开源项目中,都有相当多的小特性和简单的错误修复是为新手设计的。这样,在处理更复杂的问题之前,您可以熟悉代码库和提交过程。
Top Open-Source Projects
一旦你完成了你的项目,一定要让全世界都知道!你只要在 GitHub 上发布你完成的代码就够了吗?不要!因为大多数人更喜欢先阅读关于你的代码做什么的博客。漂亮的、精心设计的博客是你的项目,更重要的是你的营销材料!是的,用漂亮的图片和图表写精美的博客需要很长时间。我花了整个五月的时间写了 6 篇文章。我估计总共大约 200 小时或 30 小时/篇。如果你是全职工作,也许可以写一篇写得很好的博客,作为你项目的概述。(顺便说一句,我花了 10 多个小时写这篇文章,这只是第一部分。)
DeepPiCar’s Blog Series
有一点要记住,你必须享受你正在做的事情,而不是仅仅为了找到一份工作而做这个项目。如果你对你所建立的东西有热情,当你和面试官交谈时,它会闪耀出来。
第二步。努力学习,聪明学习
算法和数据结构
如果你需要掌握一项技术面试技能,那就是算法和数据结构(A&DS)编码技能。不管你面试的是大公司还是小公司,他们都会询问你的编码技能,尽管大多数公司不会在意你使用哪种编程语言。我最喜欢的编程语言是 C++和 Python,但对于编码面试,我推荐 Python,因为它非常简洁,与非常冗长的 C++相比,你可以用这么少的代码行做这么多的事情。有大量的资源可以让你为 A&DS 做好准备。我使用了以下资源:
- 《破解编码面试书》(CtCI) :这本书大约 700 页,仅售 30 美元。如果你需要重温一下& DS 的概念,这是一个很好的起点。除了概念之外,它给出了一系列带有完整解决方案的从简单到中等水*的练习题。我花了大约 2 到 3 周的时间在这上面,每一章都花了 1 到 2 天的时间。我跳过了数学/脑筋急转弯/OOD/C++/Java/SQL 的章节,因为它们与 DS 无关。
CtCi Book
- :我也大量使用 LeetCode (LC),因为我觉得 CtCI 没有给我足够的练习。Leetcode 可能是最全面和最有组织的编码面试问题的在线数据库,拥有超过 1000 个简单、中等和困难的问题。每个问题都有一个唯一的编号。(例如 LC#1 是 TwoSum)很多网上的帖子只是简单地把自己的面试问题称为 LC #xxx,而不是把整个问题打出来。我强烈建议每月花费 30 美元注册 LeetCode Premium,因为它可以让您访问所有的 LC 问题和解决方案。我觉得这很有帮助,我注册了 99 美元的年度会员,因为我认为这是“我大脑的健身房会员费”。我完成了超过 100 个 LeetCode 问题(35 个简单问题,60 个中等问题,14 个困难问题)。我实际面试中 90%的问题,或者它们的细微变化,都可以在 LeetCode 上找到。大多数情况下,直到事后我才知道它们来自 Leetcode。但是由于我练习了足够多的 LC 中等题,我能够解决相同难度的问题。实际上,我觉得我永远做不够 LC 中等题,因为直到今天,我仍然在一些 LC 中等题中挣扎。
- 图沙尔罗伊的 LeetCode 硬解 :图沙尔其实是苹果公司的一名工程经理。他在还是软件工程师的时候就制作了这些视频。我想说,观看他的视频不仅教会了我这些算法,还教会了我如何清晰地呈现复杂的想法/算法。当我在现场面试中做白板编码时,这对我帮助很大。
Tushar Roy doing Leet Code
请注意,大多数面试官会给 LC 中等水*的问题,因为要求某人在 20-30 分钟内解决中等水*的问题是非常公*的。我建议在你第一次电话面试之前,至少做 20 个简单的和 30 个中等难度的问题。我在完成 CtCI 的书之后和开始 LC 之前做了我的第一次电话采访,并立即被屠杀。
此外,我会为每个练习题计时,就好像我在面试一样。然而,我使用一个 IDE,带有自动完成和一个调试器。你不会在实际的面试中得到这些,所以我通常会在练习时设置更严格的时间限制,大约 30 分钟/问题,而不是 45 分钟。您可以选择仅使用常规的文本编辑器或者甚至使用白板来模拟真实的测试环境。这是个人喜好。
系统设计
你需要掌握的第二重要的技能是系统设计。通常,一次现场面试会要求你设计一个大型分布式系统,如网飞视频服务系统,或 WhatsApp 即时通讯系统,或 Instagram stories 等。这是一个软硬技能混合的测试。这是一个很难的技能测试,因为你需要了解很多常用的分布式系统组件,如分布式数据库、分布式内存缓存、分布式配置管理器、分布式文件存储和分布式搜索引擎等。,以及何时是使用它们的合适时机。这也是一个软技能测试,因为你需要能够画出清晰的图表来说明你的设计,并口头讨论和辩护你的设计。有人告诉我,如果你通过现场面试,系统设计面试会极大地影响你的水*。(也就是说,它可能会决定是否向你提供 4 级或 5 级工程职位,等等。)
以下是我使用的资源:
- 《破解编码访谈录(CtCI) :有一章讨论了系统设计,但都是非常基础的内容
- 高拉夫·森的系统设计 YouTube 频道 :看完 CtCI 的系统设计章节,感觉很没有成就感。然后偶然发现了高拉夫的频道,里面有 22 个视频。我把他所有的视频下载到我的笔记本电脑上,在漫长的飞机旅途中观看。伙计,这家伙太好了(而且很有趣),把事情解释得这么清楚!大约 10 个视频是对单个分布式系统组件的深入描述,其余的是关于如何构建网飞、Tinder 或脸书系统等的实际用例讨论。
Gaurav Sen’s blog
- 图沙尔罗伊的系统设计视频 : 虽然图沙尔在 LC 难题上非常出色,但他也有 5 个很棒的系统设计视频。我建议在 Gaurav 的视频之后观看这些视频,因为 Gaurav 为您提供了系统设计的坚实基础,而 Tushar 的视频假设了一些这方面的知识。
对我个人来说,由于我以前在相当多的分布式系统上工作过,所以我能够很快地掌握总体思想,即使我没有使用过上面视频中提到的一些新技术。看了足够多的视频后,我能够将大多数分布式系统归纳为以下几层:
- 客户端(PC/移动应用程序、浏览器)
- 处理客户端请求的分布式负载*衡器
- 基于位置的内容交付网络(CDN)或内存缓存,可将大量相对静态的内容(视频和图像)快速交付给地理位置更靠* CDN/缓存的客户端。
- 一系列处理各种业务逻辑的微服务,如认证、服务/保存用户内容、在用户之间传递消息。
- 微服务之间的通信通过分布式消息传递系统发送。
- 保存用户内容和消息的分布式数据库。或者,在数据库之前添加一个分布式缓存层,以提高读/写吞吐量。
行为问题
对我个人来说,行为问题是面试中最容易的部分。不幸的是,它在面试评估中也是最不重要的。果然,科技公司知道,在行为面试中摆出“好男人/女孩”的个性并说正确的话很容易,但把自己训练成一名优秀的程序员要难得多。对于一个职业转换者来说,要准备的最重要的问题当然是,“你为什么想转行?”希望有了你在第一步中建立的项目,你可以通过展示你的项目和你对新行业和你申请的公司的热情来解决这个问题。
以下是一些需要准备的其他行为问题:
- 你为什么想为我的公司/集团工作?
- 举一个你达成的目标的例子,告诉我你是如何实现的。
- 举例说明一个你没有达到的目标,以及你是如何处理的。
- 描述一下工作中的压力情况,以及你是如何处理的。
- 你有没有遇到过没有足够工作可做的情况?
- 你犯过错误吗?你是怎么处理的?
- 描述一个你和同事/老板/下属意见不合的情况,你是如何处理的?
所有行为问题的关键是以积极的方式结束。例如,即使你被问到与同事的分歧或职业生涯中的失败,也要如实提及发生的事情,但更重要的是提及你从中吸取的教训,以及当类似情况再次出现时,它如何帮助你成为更有效的团队成员/工程师。
第三步。通过多种渠道申请
6 月初,就在我在 DeepPiCar 上发表博客之后,我开始密切关注湾区的 ML 工程师就业市场。与此同时,我开始了我为期 1 个月的密集全职编码准备(总共约 200 小时)。到了六月底,尽管我还没有完全准备好,我还是开始向公司申请。原因是在我投简历和电话面试之间有 1-2 周的准备时间。通过多种渠道,我联系了 20 多家公司,进行了 30 多次电话采访。有时候同一个公司的多次电话面试。
R esume —首先列出相关的内容
我不会过多讨论简历写作,因为已经有很多关于简历写作的好文章了。我的重点是如何从职业转换者的角度来做这件事,这样招聘人员就能很快发现你非常适合新的行业/工作职能。请记住,我是从金融领域的 quant 开发人员转变为技术领域的 ML 工程师,所以这是一个双重的棘手问题,因为这既是角色转变,也是行业转变。再次,我的项目来拯救。我把它列在我工作经历的顶部,作为“个人项目”。是的,尽管这不完全是“工作”,但这是我的工作,而且与我下一份工作的目标高度相关。你应该知道大多数招聘人员都不会看第一页。如果他们不能在 10-20 秒内找到他们想要的关键词,你的简历就会被扔到一边。我还会在简历第一页的上半部分列出与新工作相关的技能(以及所有关键词)。见下文。
LinkedIn——让他们来找你!
最好的求职申请是那些你永远不必寄出的申请。在我在 LinkedIn 上发布了我的 DeepPiCar 博客帖子之后,我很兴奋地收到了这么多来自招聘人员的消息/电话,包括一些大型自动驾驶公司的消息/电话,问我是否对他们的 ML 工程师角色感兴趣。我对 Medium 博客和 LinkedIn 帖子的力量感到惊讶。但是一定要在 LinkedIn 的隐私设置中将自己标记为“对机会开放”,这样招聘人员就可以很容易地找到你。当招聘人员联系我时,我几乎总能得到一次电话面试。
https://www.linkedin.com/psettings/jobs/profile-shared-with-recruiter
内部推荐——有一个强有力的拥护者
我认为第二好的工作申请是由内部推荐提交的。我在脸书和谷歌都有一个内部推荐人。我在脸书的第一次面试非常失败,但因为我的推荐给了我一份强有力的推荐信,脸书让我再试一次。幸运的是,一个月后我通过了第二次电话筛选。对于谷歌,这更令人惊讶,部分是因为我的强烈推荐,部分是因为我告诉他们我有其他现场面试,他们直接跳过我去现场面试,即使我是一个远程候选人(顺便说一句,我住在芝加哥)。
所以我建议你找任何一个在你想加入的科技公司工作的家庭成员/朋友/同学。如果他们都不在那里工作,也许他们知道谁在那里工作。请让你的朋友把你介绍给他们,也许让他们通过内部推荐提交你的简历。这样你获得电话面试的机会就高多了。
另一个方法是明智地使用你的 LinkedIn 网络。你可以寻找在特定公司工作的人,请你们共同的朋友介绍你们两个认识,如果不行,给这个人发一封 LinkedIn 邮件。注意,如果你发送大量 LinkedIn 邮件,你需要 LinkedIn Premium。我注册了大约 3 个月的 LinkedIn Premium(大约 30 美元/月),能够直接与更多的人联系。一些联系导致了面试。附带的好处是,我收到了比以前更多的招聘信息,因为我相信 LinkedIn 算法将我排在了非付费用户之前。
第三方招聘机构
总的来说,我觉得这次大多数第三方机构都没有很好地为我找工作。作为参考,当我过去寻找金融工作时,我专门使用高管猎头公司,结果很好。但大多数科技巨头都不使用第三方招聘机构。唯一对我有效的代理是 TripleByte 和 DeepLearning.ai ,我将在下面讨论。
三字节 —跳过电话面试
TripleByte 是一家非常独特的招聘机构。它对候选人的吸引力在于,一旦候选人通过 TripleByte 全面的 2 小时现场技术筛选测试,他/她就可以直接去许多公司现场工作。它对公司也很有吸引力,因为 TripleByte 将为他们淘汰大多数弱候选人,节省他们的工程师几个小时的电话筛选时间。当我通过 TripleByte 的测试时,我可以从大约 200 家公司中进行选择。他们大多是小型创业公司,但也有不少大公司,如苹果、Adobe、美国运通等。最后面试的是苹果 Siri 组(巨大) Zoox (中等) Determined.ai (小)现场。他们都在做惊人的工程工作。我强烈建议通过三字节的过程,因为它确定了我的弱点,并使我从许多小时的电话筛选和相关的头痛中解脱出来。在这里参加 TripleByte 的在线测试。
更新(2020 年 3 月):自 2019 年末起,TripleByte 除了其赛道——软件工程师赛道之外,还增加了一个机器学习工程师赛道。这很好,因为如果你是一名 ML 工程师/数据科学家,你将不需要回答任何前端/Javascript 相关的问题,而是可以专注于 Python、ML 和其他数据科学相关的问题。
deep learning . ai和worker a . ai—有志于数据科学家/ML 工程师的福音****
如果你是一个有抱负的数据科学家/ML 工程师,你一定听过或上过吴恩达的一门机器学习/深度学习课程,由 Coursera/Deep Learning.ai 提供,实际上 Deep Learning.ai 有两部分,一部分是教育,这是非常众所周知的,另一部分( Workera.ai )是招聘,这是比较鲜为人知的。那是因为 Workera.ai 相当新,2019 年年中才开始。他们没有 TripleByte 那么多附属公司,但我相信他们正在迅速加大这方面的努力。他们还会让你做个测试。Workera.ai 和 TripleByte 的测试之间的差异有两个方面。首先,它是为数据科学家(DS)/ML 工程师设计的测试,其中 TripleByte 为一般软件工程师以及 ML 工程师设计了测试。第二,Workera.ai 测试没有约束力,这意味着通过测试不会让你直接进入现场面试。相反,Workera.ai 会把你介绍给一些附属公司的 DS/ML 小组,并把你带到队列的前面,但你仍然需要经历整个电话/现场面试过程。我觉得它仍然非常有价值,因为吴恩达在湾区深度学习领域的声誉和网络相当广泛。我最后采访了 Pinterest 和 Scale.ai 的 ML 团队。如果我直接申请的话,我想我不会得到任何一家公司的面试机会。点击此处申请 Workera.ai 的经验丰富的工程师人工智能项目。
在线求职板——不要过分依赖它们
为了扩大搜索范围,我还在 Linkedin、Glassdoor、Indeed 和 ZipRecruiter 等网站上设置了求职提醒,这样只要有符合我搜索标准的新职位发布,他们就会通知我。随着时间的推移,我确实在申请后接到了一些电话面试。总的来说,我发现信噪比有点低,这意味着我会收到很多日常电子邮件,但很少有顶级公司的好工作职能。但是不要完全忽略这个渠道。你需要广撒网,也许你会通过这条渠道抓到一些鱼
直接应用—实际上不起作用
在过去,人们会给公司寄一封漂亮的附有简历的求职信,并期望得到人力资源部的回复。但是这一次,这种方法对我完全不起作用!我确定了大约 10 家我想去工作的公司(大多是自动驾驶汽车公司),并直接在他们公司的网站上求职页面下申请。令我惊讶的是,我没有收到任何回复,甚至没有一封拒绝邮件!幸运的是,在网上申请每家公司并不需要那么长时间。我会说,仍然适用于任何你感兴趣的公司,但不要屏息等待回音。
分阶段申请工作
试着申请一些你不太感兴趣或者你认为在第一阶段更容易进入的公司。然后在稍后阶段申请你梦想的工作/公司。如果你得到了工作机会,你可以利用第一阶段来练习、提高,甚至利用这些机会从你梦想中的公司获得更好的工作机会。这听起来可能很有争议,似乎非常“唯物主义”,但想想看,许多人会在一个不太知名的公司工作,计划获得经验,然后在几年后进入一个更知名的公司。谁知道呢,如果你没有得到你梦想中的工作,至少你有一些机会可以从你的第一阶段公司中选择。
变得有条理:记一本日志
当你通过这么多渠道申请时,很难跟踪你申请了哪些公司,以及你在每个公司处于哪个阶段。我有详细的面试日志。它按面试阶段(申请、面试、录用、拒绝等)组织,然后按公司组织。每个公司本质上都是一个页面,有背景信息和按时间顺序排列的事件列表,比如电话和面试。这样,我可以看到我申请和面试了哪些公司,这样我就可以做适当的跟进。
My Interview Log for Facebook
这个博客已经很长了。我将在第二部分和第三部分中讲述面试技巧和提供谈判机会。
保持冷静,继续学习!
资源
这是我在求职过程中使用的资源附录。其中一些在第 2 部分和第 3 部分中有详细介绍。希望你也会发现它们很有帮助。
:这是一款允许不同公司(大多是科技公司)的员工匿名发布问题和答案的应用。人们通常会讨论职业决策、公司文化、面试和薪酬等。我发现这个*台有好有坏。这很好,因为你得到了更坦诚的回答/回应,有时还能得到内部消息。这是不好的,因为有些人因为匿名而写下攻击性的回应,而且环境有时可能是有毒的。你已经被警告了。****
Blind.com
Coursera :了解自己热衷的学科。这是免费的或象征性收费。我在那里修了 ML 和 DL 课程。
deep learning . ai和worker a . ai
- 如果您对计算机视觉(CV)或自然语言处理(NLP)中的深度学习技术感兴趣,请参加深度学习系列的 5 门课程
- 通过他们的筛选测试,被推荐给顶级科技公司 ML 团队的招聘经理
编程面试要素 书:这是另一本优秀的面试准备书,类似于 CtCI 书,只不过它更面向有经验的工程师,而 CtCI 则可供没什么算法背景的初学者阅读。
geeks forgeeks:和 LeetCode 一样,这也是一个非常全面的 A & DS 问题和解答的网站。这个网站是免费的,有时包含 LeetCode 中没有的实际面试问题。
玻璃门
- 查看公司的员工评价
- 查找以前的面试问题
- 设置职务提醒以接收新的职务更新
谷歌搜索 :人生任何问题的起点。还需要我多说吗?
Google.com
内部员工:永远试着联系你的朋友,或者朋友的朋友,他们在你想申请的公司工作。他们将是你最有效的线人和拥护者。在 LinkedIn 上联系我,如果你很合适,我很乐意推荐你。
leet code
- 练习 A&DS 问题
- 使用 leet code Premium(35 美元/月或 99 美元/年,带优惠券)来查找特定公司过去提出的面试问题。我建议支付年度会员费。就当是你编码大脑的健身房会员吧。
参考消息:这个网站按公司、资历、地点和工作职能列出了众包薪酬信息,因此你会知道你是否得到了公司的公*报价。当然,这只对大公司有效,因为有更多的数据点。
levels.fyi
LinkedIn :
- 查找人员的专业和教育背景
- 打开“向新机会开放”设置,以便招聘人员可以找到您。
- 使用 LinkedIn Premium 联系你感兴趣的人
- 设置职务提醒以接收新的职务更新
中型博客网站 :
- 阅读教程和方法来帮助你的个人项目
- 在 Medium 上写博客,展示你自己的个人项目
TripleByte :跳过电话面试,如果你通过了他们的技术筛选,直接去现场。参见上面的详细描述
YouTube
- 当您处理个人项目时,请观看教程和操作指南
- 观看系统设计和算法视频
- 注意:在面试准备期间,不要分心,看几个小时的视频来找乐子!
声明:除非另有说明,否则照片和图像来自 Unsplash 或 Pixabay。公司标志和商标是合理使用。我不隶属于上述任何公司或产品,除了我目前在谷歌公司工作。
小心点。过多地关注你的模型结果会导致信息泄露
原文:https://towardsdatascience.com/careful-looking-at-your-model-results-too-much-can-cause-information-leakage-95b4517404bc?source=collection_archive---------18-----------------------
在建立机器学习模型时,总是要使用尽可能多的数据。我想我们都知道过度拟合的问题,这实质上是你建立的模型复制了训练数据结果,以至于完美地拟合了训练数据,而不是概括地更好地代表数据的总体,当你输入新数据并得到非常奇怪的结果时,会产生灾难性的结果。
Photo by Jacek Dylag on Unsplash
你能做些什么来防止这种情况发生?
看看网上,你会发现大量的文章关于过度适配,什么是过度适配以及如何防止过度适配。这些已经在很大程度上完成了,所以我不会在这里重复它们,但通常这些可以通过在开始之前分离可用的数据来最容易地控制。
有哪些数据隔离?
最基本的方法是将整个可用数据集分成三个不同的样本(没有重复),并给定以下标签:
- 培养
- 确认
- 试验
训练、测试和验证数据集每个都执行特定的目的,并且通常不会具有相同的大小。事实上,一些最常用的值是 3:1:1 分割(或者 60%训练,20%验证和 20%测试)
培训用数据
这是数据的核心。这是用来训练和创建您使用的模型的。自然地,你在训练中获得的数据越多,你就能更好地期望模型推广到它。这通常包含所有可用数据的 60%左右。
验证数据
这是用于调整和改进模型的数据集。每当您训练一个模型时,您都使用它来对照验证集,以便生成一些预测并对其性能进行评分。然后,您可以调整该模型,重新训练它,并根据该数据再次运行它,以查看是否有所改进。这可能是一个非常迭代的步骤。您希望这里的数据大小合理,以覆盖模型将暴露的参数空间,但不要太大,因为您的模型没有足够的数据进行训练。这通常占所有可用数据的 20%左右。
测试数据
这些数据在项目开始时就被放在一边,直到您对您的模型满意为止。然后你把它应用到这个数据上,看看它是否真的学会了很好地概括,或者它是否被过度拟合了。与验证数据集相似,您需要足够的数据来涵盖您想要测试的内容,并获得模型正常工作的信心,但您不希望从可以训练的内容中获取太多信息。这通常是现有数据的 20%左右。
你提到覆盖参数空间?
我做到了。例如,如果您要针对不同直径管道中的水流量运行模型,您需要确保您拥有验证数据(实际上是所有三组数据),以确保模型能够学习这种能力并进行测试。如果您只对一个管径的数据进行训练,它了解到水流量和管径之间存在关系的可能性非常低,从而导致其他管径的结果很差。
因此,为培训保留足够的数据非常重要。
Photo by T L on Unsplash
保存数据
如果 40%的数据只是用于调整和对您的模型进行最终评分,那么对于一个需要大量变化的特性的复杂模型,您可能需要大量数据。为了增加可用于训练数据的数据量,科学家通常会使用交叉验证。
交叉验证是指将训练集和验证集中的数据集中起来,然后系统地分割成段(或“折叠”),再分配给每个组,而不是固定的。例如,对于四重交叉验证,为测试和验证放置的数据被分成四个相等的组,并且这些组中的每一个轮流作为验证集,而其他三个被汇集到训练集中。
最终,这意味着您已经获得了针对每个数据点的预测,并且还使用它来训练模型(但不是同时),并且正在利用更多的数据。交叉验证也以这种方式用于调整您正在使用的特定模型的超参数,以提高准确性。
那么问题是什么呢?
您仍然只使用了 80%的数据,并且总是有一种使用测试集查看当前模型结果的冲动。这通常不是问题,但前提是你能控制如何使用你得到的数据。
一些人将训练和调整模型,将验证集的准确性与测试集进行比较,一旦测试集的准确性不再提高而是变得更差,就停止调整模型。通常在这些情况下,即使测试集变得更差,验证集也会不断改进,这很好地说明了模型变得过度拟合。
问题是你使用测试集来检查你的模型太慢了,但是可以肯定的是,你对测试集所做的和上面描述的验证集所发生的一样。对于较差的数据或非常复杂的模型,您可能会对测试集运行多次,而没有意识到您正在过度拟合,因为您正在使用您看到的信息并对模型进行更改。
例如,您得到了最终模型,并对测试集运行它,虽然结果还可以,但您会注意到,如果您更改参数,它可能会得到改进。您更改了它,模型得到了改进,但是您使用了关于测试集的信息来输入到模型中。信息已经在团体之间泄露了。
信息泄露
信息泄漏是指密封系统中的信息从不应该泄漏的地方泄漏出去。这是密码学中经常使用的一个术语,安全系统向窃听者提供了关于系统内部情况的线索,这可能被用来最终破坏安全性。
因此,这里的管道是数据科学家,他们无意中使用了自己的知识和技能,并根据他们对测试集的表现来慢慢调整模型。
我应该补充一点,这通常不是一个大问题,但我见过一两次。我的方法也不是控制它的唯一方法,但是我在下面给出我的观点。
能做些什么?
一旦你意识到这可能是一个问题,这是很容易控制的。最简单的解决方案是确保您没有多次使用最终测试集,并根据结果限制您的更改。
对于模型调整来说,实际上从训练和验证数据池中取出另一小组数据并将其用作测试集的代理可能是有益的。通过这种方式,您仍然可以调整您的模型,并看到模型的改进是如何进行的(当这个额外的测试集变得更差时停止),并且还具有保留最终测试集以展示最终结果的好处。
虽然这听起来像是更多的数据被保留并从培训中取走,但交叉验证方法可以帮助减轻这种情况。例如,你可以拿走 80%中的 10%到 20%,而你仍然在训练和验证剩下的 60%到 70%(这类似于非交叉验证方法)。
要点
Photo by Laurenz Kleinheider on Unsplash
当构建一个需要大量调整的复杂模型时,请注意:
- 针对最终保留的测试集进行测试会导致过度拟合
- 根据您的最终测试集结果,限制您对模型的修改程度
- 你可以成为过度拟合你的模型的管道
- 交叉验证可以帮助你充分利用你所拥有的数据
- 如果要拟合很多超参数,额外的测试集会很有用
CASM =分形
原文:https://towardsdatascience.com/casm-fractals-2b9835f71c53?source=collection_archive---------29-----------------------
计算机、艺术、科学和数学。
Just to catch your attention
在高中,我们接触到了几何。尤其是欧几里得几何。即使在我们的大学经历中,欧几里得几何也是那些不是主修需要更高水*数学的领域的学生的重点。然而,还有更多我们通常不会深入研究的几何范畴。
任何不是欧几里得几何的类型都被称为非欧几里得几何。虽然非欧几里得几何告诉我们,我们正在看的不是我们熟悉的东西,但它并没有告诉我们我们正在观察的几何的具体类型。
riefly,欧几里得几何是一个基于一小组假设的系统。这些假设被称为公设或公理。欧几里德在他的书《原本》的开头给出了五个公理,所有的定理或真陈述都可以从这些公理中推导出来。在我们可以在另一个证明中使用一个额外的定理之前,我们必须首先使用最初提供的五个公理来验证它。这篇文章实际上并不是关于欧几里德几何的,所以现在描述一下就够了。
下面这个模型是基于欧几里德几何的。但是,请注意它是如何遍历各种圆圈和颜色来创建一个漂亮的图像的。现在想象一下你能用非欧几里得几何做什么。
下面是一个列表,无论如何也不全面,列出了其他存在的几何图形:
- 双曲线几何
- 椭圆几何学
- 球形几何
- 抛物线几何
- 离散几何
- 希尔伯特几何
- 分形几何(这是我们博客第一部分的重点)
为了找到其他类型的几何图形,维基百科有一个很好的列表:【https://en.wikipedia.org/wiki/List_of_geometry_topics 如果你想了解更多,你可以在那里点击每一个。
分形几何是一个令人着迷的探索课题。这确实是数学的一个分支,但他们的渲染是如此美丽,他们已经成为艺术世界不可或缺的一部分。分形在计算机发明之前就已经被探索过了。想象一下。它们是在英国制图员试图测量英国海岸长度时被偶然发现的。他们看得越仔细,海岸线就变得越详细越长。他们实际上发现了分形的一个主要特性。
What is a Fractal?
使用一个简单的等式,我们可以确切地看到迭代是如何发生的。
我们首先用一个值代替 x。求解 y 的方程。然后取 y 的值,并将其作为新的 x。说明这一点的最佳方式是实际使用真实值。
Iteration
我们的第一个值是 x 的 1,这给了我们 y 的 2,这给了我们坐标(1,2)。现在我们用 2 代表 x,这样我们得到 5 代表 y,我们的下一组坐标是:(2,5)。这里的五组坐标分别是 (1,2) (2,5) (5,26) (26,677) (677,458330)。这个迭代继续下去,如果我们选择的话,会给我们一个无限的坐标集合。
这是一个简单的等式,但如果我们有 z = z + C,C 是一个常数,但让我们把“z”变成一个复数(a + bi)。
正是这个复数创造了我们所看到的分形之美。这些复杂的数字和公式在我们的世界里随处可见。一个这样的例子是心电图,也称为 EKG 或 ECG。医生们经常在他们的办公室里使用 EKG 来读取一个人的心脏功能。这只是详尽清单中的一个例子。
非整数维可以通过使用经典几何来最好地解释。经典几何使用整数维的对象。例如,一维直线和曲线,二维*面图形。想想长方形和圆形。像骰子和篮球这样的三维立体。分形不像经典几何那样直接。它们处理更复杂的数字,并具有迭代函数。
以上是我在这里真正想做的事情的背景。我想向你展示计算机创造分形的能力以及由此产生的美。一些使用数据集来创建多个分形,另一些使用递归来迭代函数。这里所有的分形都是用 Python 创建的。
让我们从一些 Julia 集分形开始。我这里有一个系列,每个渲染之间有一个简单的区别。在放大最初的数字后,你仍然可以获得惊人的细节。
Full Fractal
Zoomed In by two
我在这里只用了 2 倍的变焦。让我们看看当我进一步放大时会发生什么。
Zoomed in by four
Zoomed in by sixty
你在这里看到的东西真是令人难以置信。从第一张图片到第二张图片,我使用了 2 倍的缩放。第三张图片,我用了 4 倍的变焦。换句话说,是原始图像的四倍,但只是第二个图像的两倍。最后一张图像的缩放比例为 60。想想我们在放大 60 倍的情况下深入分形有多深。细节不亚于原来,设计继续重复自己。事实上,看起来我们几乎是缩小了而不是放大了。这有点令人着迷。
我用 Mandelbrot 集合创建了一些类似的东西,但是这里我只有两个图像。看看第二个图像与第一个图像相比有多精确。这不是模糊或静音,而是刚刚放大的第一张图像的确切细节。从第一个到第二个研究细节。
Full Fractal
Zoomed In
只是为了一些有趣的颜色,我为你创造了另外两个图像。它们都是 mandelbrot 集。你可以在这里看到,仅仅通过改变所使用的颜色,你就可以改变一幅图像的外观。
Simple Colors
A bit more colorful
当我开始这篇文章时,我打算只展示分形。在研究分形和公式产生的图像时,我遇到了另一种完全来自数学和数据的艺术。视觉混沌吸引子甚至比你在这里看到的分形更加非凡。这是我下一篇文章的预告片。这被称为 Clifford 吸引子。使用数据集和 python,创建了以下视觉效果。这只是黑白的阴影。在我的下一篇文章中,我将向您展示如何使用吸引子来创建各种颜色的杰作。
Fascinating Shades
为了让你看得开心,下面是一个一小时的视频,放大了曼德勃罗分形。催眠,上瘾,或放松…你选择。
猫,狗,还是埃隆马斯克?
原文:https://towardsdatascience.com/cat-dog-or-elon-musk-145658489730?source=collection_archive---------7-----------------------
终极 DIY 机器学习初学者指南
了解如何用 Python 和 Keras 在不到 15 分钟的时间内构建一个图像识别卷积神经网络!
G 从机器学习起步的尝试令人望而生畏。底层的概念是高级的,相关的术语是特定于领域的和技术性的。除此之外,机器学习恰好是研究和实践中发展最快的领域之一,这使得跟上时代变得更加困难。
本文为您提供了一个简单的(附带代码的)介绍,介绍如何设置、训练和运行卷积神经网络来对图像进行分类。到本文结束时,你将已经建立了一个卷积神经网络,可以区分猫、狗和埃隆·马斯克。它非常容易采用,如果你喜欢,你可以在组合中加入一棵树或一辆车。我强烈建议你自己完成这些步骤,因为这样做会在记忆和满足感方面产生最好的效果。
随着技术的进步,它一次又一次地逆转了每一种情况的特征。自动化时代将是“自己动手”的时代。—马歇尔·麦克卢汉
注意:为了简短起见,我会跳过有时过于简单的话题。我们的目标是让你开始学习,而不是取代正式的关于机器学习的计算机科学课程。
文章的结构:
- 先决条件和设置
- 什么是 ImageNet 和 MobileNet?
- 迁移学习
- 自定义您的 MobileNet 版本
- 训练模型
- 做预测
①先决条件和设置
Photo by dylan nolte on Unsplash
一个 Python 环境(建议 Jupyter 笔记本)。如果你还没有设置这个,不要担心。这是毫不费力的,不到 10 分钟。
[## 所以你想成为一名数据科学家?
到底是什么阻止了你?下面是如何开始!
towardsdatascience.com](/get-started-with-python-e50dc8c96589)
我们将使用 TensorFlow 和 Keras 。由谷歌大脑团队创建的 TensorFlow 是一个用于数值计算和大规模机器学习的开源库。Keras 是一个位于 TensorFlow 之上的高级神经网络 API。Keras 最*已经集成到 TensorFlow 中,可以通过tensorflow.keras
访问。所以还是装 TensorFlow 吧。
pip install tensorflow**# For progress visualization when training the model**
pip install keras_tqdm**# Required for keras_tqdm**
pip install ipywidgets
jupyter nbextension enable --py widgetsnbextension
我建议在专用的 Python(虚拟)环境中运行笔记本,以防止与您可能有的其他项目发生潜在冲突。随着你职业生涯的进展,虚拟环境将变得更加重要。你会有一些偶尔会回来的项目。对于那些项目,您可能已经使用了您想要继续使用的特定库的特定版本,而不是重构您的整个旧代码来使用新版本。
到训练一个机器学习网络,你需要数据。由于我们正在建立一个图像分类器,我们将需要图像。你需要为每门课下载至少几百张你想要预测的图片。幸好我一直未雨绸缪,为你准备了快速下载图片的指南。
[## 使用 Python 进行图像抓取
学习如何用 Python 从 Google 下载图片的代码指南!
towardsdatascience.com](/image-scraping-with-python-a96feda8af2d)
为了让所提供的 Jupyter 笔记本能够完美地工作,你的文件夹结构应该是这样的,每个文件夹应该包含大约 200-300 张图片。图片的名称和大小并不重要。
②什么是 ImageNet 和 MobileNet?
Photo by Anastasia Dulgier on Unsplash
MobileNet
我们将使用 MobileNet 作为基础模型。MobileNet 是 Google 开发的轻量级卷积神经网络,已经在 Imagenet 上进行了训练。原文可以在这里找到。谷歌最*发布了新版 MobileNet, MobileNetV2 。
Imagenet
I magenet 是一个约 1500 万的大范围标记图像数据库,按照 WordNet 层次结构(目前只有名词)组织。成百上千的图像描绘了层次结构的每个节点。Imagenet 通常用于训练图像识别模型。模型的质量通常通过它们在ils vrc(ImageNet 大规模视觉识别挑战)上的表现来评估。ILSVRC 非常好,因为它保证了一个公共基线,并提供了模型之间的一些可比性。
③迁移学习
Photo by Jonathan Borba on Unsplash
到最好解释迁移学习,让我们快速看一下卷积网络的典型架构。
An exemplary architecture of a convolutional neural network, highlighting feature extraction and classification
特征抽出
T 在典型的卷积神经网络中,较低层(更接*输入的网络层次)可以被认为是逐片扫描整个图像的过滤器。然后,将这些扫描的结果组合起来,创建每个都有单个值的节点。
分类
在网络的分类部分,我们使用由特征提取部分生成的单值节点的最后一个长列表来将它们映射到我们想要的输出。也就是说,如果我们的输出是一些货币值,那么我们可能只有一个最终节点,表明该值(回归)。如果我们试图对多个对象进行分类,我们将需要和我们拥有的类一样多的最后节点。
训练一个神经网络意味着什么?
这有助于将神经网络视为一个大的功能。它有一个输入(图像)和一个输出(预测)。
在网络训练过程中,优化器不断优化该函数。优化网络意味着改变网络节点之间连接的权重。该优化基于损失函数。本质上,该损失函数是通过将预测与实际结果进行比较,为每个输入的函数结果分配损失值的函数。更高的损失值是不好的,优化器知道最*的更改不是一个好主意,会尝试其他方法。
迁移学习
转移学习只能应用于以前训练过的模型。通常,这些模型会在运行数天的大型 GPU 上进行训练,以找到最佳权重来生成尽可能好的预测。
The architecture of a VGG16 convolutional neural network
虽然上图描述的是 VGG16 模型的架构,而不是 MobileNet 网络,但它的相似性足以说明这一点。输入图像有三个通道(红色、绿色和蓝色)。然后,图像经过大量的转换、过滤、合并、卷积等等,最终在一个包含 1000 个结果值的层中结束(类别为ils vrc))。
当使用迁移学习时,我们本质上说:
“去你的结果,但谢谢你的工作”
换句话说,我们将切断网络的最后一部分(在上面的例子中,是 1x1000 层),并用一个更适合我们需要的层来代替它(对于猫、狗或 Elon 问题,是 1x3 层)。实质上,我们保留了为网络的特征提取部分寻找最佳权重的所有工作,同时为我们的自定义分类层替换掉网络的最后一部分。虽然并不完美,但这种方法产生了惊人的好结果,只需要训练时间的一小部分。这种不完美源于这样一个事实,即你的模型可能已经学会了,除了别的以外,识别像毛发一样的表面。当你想要区分不同种类的树时,识别像皮毛一样的表面可能没有帮助。然而,能够定位原始形状和模式——这是在网络的较低部分学习的——对于区分树木非常有帮助。
④定制您的 MobileNet 版本
Photo by Aaron Huber on Unsplash
进口
import tensorflow as tf
import PIL
助手功能
我们稍后会用到的两个辅助函数。
加载 MobileNet 基本模型
L et 首先加载默认模型,以了解当我们应用迁移学习时,后来到底发生了什么。
model = tf.keras.applications.mobilenet.MobileNet()
model.summary()
运行前面的代码片段将产生一个模型中所有层的长列表,从最低层(InputLayer)到最高层(这里称为 act_softmax)。
Screenshot of the lowest and topmost layer of the MobileNet model.summary(). I omitted the middle layers for space reasons.
我们可以看到最后一层的输出形状为(无,1000),这意味着它将产生 1000 个值。让我们通过运行以下命令来快速验证:
dog_image_id = os.listdir('images/dog')[0]dog_image = load_image(os.path.join('images/dog',dog_image_id))print(f'shape: {dog_image.shape}')
print(f'type: {type(dog_image)}')model.predict(dog_image)
这个命令将创建一个包含 1000 个值的 Numpy 数组。
A random image of a dog fed to the default MobileNet configuration
加载用于迁移学习的 MobileNet 模型
model = tf.keras.applications.mobilenet.MobileNet(
input_shape=(224, 224, 3),
include_top=False,
pooling='avg'
)
我们加载模型的主要区别是我们现在使用参数include_top=False
。当使用这个参数时,我们还必须指定 input_shape 和 pooling,这可以在文档中读到。通过指定include_top=False
,我们实例化了没有最高层的模型(即,1000 个类的预测)。
运行model.summary()
给了我们:
MobileNet model with include_top=False
我们现在可以清楚地看到,模型的最顶层是 global_average_pooling,而不是我们之前看到的 softmax 层。此外,参数的总数已经显著下降。为了确认新的结果值,我们可以运行model.predict(dog).shape
来查看我们现在将获得 1024 个而不是 1000 个值。考察这些数据也表明,它们与之前的预测大相径庭。区别是因为还没有进行分类,那些 1024 值表示一些抽象特征的存在。
添加附加层
为了预测猫狗和埃隆马斯克,我们必须替换原始模型中的预测层。为此,我们添加了三个新层:
- ****删除:在训练过程中删除节点,以防止过度拟合
- ****密集:全连接层(即该层中的每个节点都连接到前一层中的每个节点)
- Softmax: 指定输出值的函数。Softmax 意味着层中所有节点(我们的三个密集节点)的总和必须为 1。可以理解为一种概率
from tensorflow.keras.models import Model
from tensorflow.keras.layers import (Dropout, Dense, Softmax)x = Dropout(rate=0.4)(model.output)
x = Dense(3)(x)
x = Softmax()(x)
model= Model(model.inputs, x)
再次运行model.summary()
将在模型顶部显示新图层。
⑤训练模型
Photo by Josh Riemer on Unsplash
这开始变得令人兴奋了!我们快到了。
指定要训练的层
如果我们从头开始,我们现在将训练整个网络和随之而来的数百万个参数。但幸运的是,我们不必那样做。所有下层都是之前训练过的!所以让我们确保只训练新的层。对于生产模型,您通常还会在初始磨合阶段后训练较低的层,此时您只训练新的层。
for layer in model.layers[:-3]:
layer.trainable = False
编译模型
让我们通过运行带有优化器和损失函数的model.compile
来配置我们的训练模型。有很多不同的优化器和损失函数,但是[Adam](https://keras.io/optimizers/#adam)
和[categorial_crossentropy](https://keras.io/losses/)
是很好的默认值。如果你好奇,就去读读它们,但是不要在丛林中迷路。
from tensorflow.keras.optimizers import Adam
model.compile(
optimizer=Adam(lr=0.001),
loss='categorical_crossentropy'
)
构建数据生成器
答差不多了,我们已经指定了训练和验证数据,我们可以开始了!
我们首先构建一个数据生成器datagen
,并指定几个参数来定义我们想要在训练过程中应用于图像的增强。我们还为training
和validation
指定了一个save_to_dir
文件夹,并预先保证它们的存在。这样做将允许我们检查在训练过程中创建的增强图片。如果你不想那样,就把线拆了。
训练模型
A 好了,该训练模特了!我们使用fit_generator
是因为我们之前已经创建了两个生成器,一个用于训练数据,一个用于验证数据。我们还使用回调来直观地显示我们训练的进度。
运行这个意味着,我们要等一会儿。在我的 MacBook Pro 上,大概是 10 分钟。您的里程可能会因硬件而异。如果你想走过场,你也可以设置epochs=1
,这样会快很多。
在培训过程中,您应该会看到类似这样的内容:
训练完成后,我们可以通过运行以下命令来检查进度:
import matplotlib.pyplot as plt
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('Model loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['Train', 'Validation'], loc='upper left')
plt.show()
这将为我们提供:
Typical model training progression, loss decreases quickly at first and then flattens out after some epochs
⑥进行预测
Photo by Jen Theodore on Unsplash
酷,我们已经成功训练了模型!让我们看看它在预测图像方面的表现如何。让我们加载一个随机的猫、狗和 Elon Musk 图像。
elon_with_disguise = load_image('elon_with_disguise.png')
elon_without_disguise = load_image('elon_no_disguise.jpg')random_cat = random.choice(os.listdir('images/cat/'))
cat_path = os.path.join('images/cat',random_cat)
cat = load_image(cat_path)random_dog = random.choice(os.listdir('images/dog/'))
dog_path = os.path.join('images/dog',random_dog)
dog = load_image(dog_path)
要检查图像运行(在每个单独的单元格中):
tf.keras.preprocessing.image.load_img('elon_with_disguise.png', target_size=(224,224))tf.keras.preprocessing.image.load_img('elon_no_disguise.jpg', target_size=(224,224))tf.keras.preprocessing.image.load_img(cat_path, target_size=(224,224))tf.keras.preprocessing.image.load_img(dog_path, target_size=(224,224))
对于实际预测,我们得到:
伪装伊隆的尝试不错,但我们的模特看穿了这一点!
结束语
在推特上关注我,在那里你可以见到我可爱的机器人给你发送最新最棒的当然也是随机的内容。我可能很快会写一篇关于这个的文章。
更严重的是,如果你想聊天,请联系 LinkedIn。
看看我在 Medium 上写的其他文章,如果你喜欢这篇文章,请留下一两个掌声。
不断学习、探索、建设,自己动手就好!
猫或狗——卷积神经网络图像分类
原文:https://towardsdatascience.com/cat-or-dog-image-classification-with-convolutional-neural-network-d421a9363c7a?source=collection_archive---------12-----------------------
基于 Keras 和 TensorFlow 的卷积神经网络(CNN)图像分类实验
Our dog — Dachshund (Miniature Wire Haired)
这篇文章的目标是展示 conv net(CNN——卷积神经网络)是如何工作的。我将使用 Franç ois Chollet 的书— 用 Python 进行深度学习中描述的经典猫/狗分类示例。这个例子的源代码可以在 Fran ois CholletGitHub上找到。我用这个源代码来运行我的实验。
Convnet 的工作原理是将图像特征从细节中抽象为更高层次的元素。可以用人类的思维方式来进行类比。我们每个人都知道飞机看起来是什么样子,但最有可能的是,当想到飞机时,我们并没有想到飞机结构的每一个细节。以类似的方式,convnet 学习识别图像中更高级别的元素,这有助于在新图像看起来与用于训练的图像相似时对其进行分类。
应该使用这个笔记本训练图像分类模型(你会在那里找到关于从哪里下载带有猫狗图像的图像数据集的描述)。该笔记本中正在使用模型并调用分类预测。为了方便,我把自己的笔记本(基于深度学习用 Python 书的代码)上传到了 GitHub 。
我在 Jupyter Docker image 中运行 notebook 时,应该更新图像数据集的路径(请参考我的 GitHub repo 中的代码示例),您应该使用 Docker 配置的路径作为根来从磁盘中获取数据集图像:
# The path to the directory where the original
# dataset was uncompressed
original_dataset_dir = '/home/jovyan/work/study/python/dogs_vs_cats/train'# The directory where we will
# store our smaller dataset
base_dir = '/home/jovyan/work/study/python/dogs_vs_cats_small'
os.mkdir(base_dir)
使用数据子集构建模型:
- 用于训练的 1000 只猫和 1000 只狗的图像
- 用于验证的 500 只猫和 500 只狗的图像
- 用于测试的 500 只猫和 500 只狗的图像
第一次模型训练尝试直接使用来自数据集的可用图像来完成。Convnet 训练使用 Keras 和 TensorFlow 后端识别猫和狗。但是过拟合发生在早期迭代中。这是我执行的培训的结果——验证性能没有提高,当培训性能提高时——conv net 根据培训数据进行调整,但在验证数据方面表现不佳:
Convnet model training results
为了对抗过度拟合,通过应用数据扩充技术来提供更多的训练数据。扩充过程允许通过改变现有数据从现有数据生成更多的训练数据。应用随机变换来调整现有图像,并从一个图像中创建多个图像(参考来源于使用 Python 的深度学习一书)。
数据扩充后,convnet 的训练效果明显更好,验证质量与训练质量非常接*:
Convnet model training results after data augmentation
基于 convnet 模型的图像分类在端点笔记本中完成。一个好的做法是保存训练好的模型,稍后重新打开它用于分类任务:
from keras.models import load_modelmodel = load_model('cats_and_dogs_small_2.h5')
我将用我们的狗图像测试模型。让我们基于模型分类结果来看看我们的狗看起来和狗有多接*:)(好吧,至少基于用于 convnet 训练的那 1000 张狗图片)。
我将使用 11 张图片,所有图片都将与 Python 笔记本一起上传到 GitHub repo。第一张图:
Our dog — Jelly
使用来自深度学习与 Python 书的代码将图像转换成发送给 model.predict 函数的格式:
img_path = '/home/jovyan/work/study/python/dogs_vs_cats_small/test/dogs/dog.2000.jpg'# We preprocess the image into a 4D tensor
from keras.preprocessing import image
import numpy as npimg = image.load_img(img_path, target_size=(150, 150))
img_tensor = image.img_to_array(img)
img_tensor = np.expand_dims(img_tensor, axis=0)
# Remember that the model was trained on inputs
# that were preprocessed in the following way:
img_tensor /= 255.# Its shape is (1, 150, 150, 3)
print(img_tensor.shape)
显示 150x150 像素的变换图像可能很有用:
import matplotlib.pyplot as pltplt.imshow(img_tensor[0])
plt.show()
Transformed image
分类结果:58%是狗。我认为这是一个很好的结果,超过 50%对狗来说是好的,低于 50% = >对猫来说是好的。
prediction = model.predict(img_tensor)
print(prediction)[[ 0.5823279]]
我们用更多的图片重复同样的步骤(调用 model.predict 函数)。
- 狗:53%(好)
Our dog — Jelly
- 狗:53%(好)
Our dog — Jelly
- 猫:43%(不好)。从这张照片中,康文内特无法判断这是一只狗。嗯——有道理,也许在那张图中它看起来更像一只猫。
Our dog — Jelly
- 狗:88%(非常好)。除了各种分散注意力的颜色,convnet 能够清楚地识别这里的狗。好像狗的脸显示得更清楚——因为 convnet 更容易识别狗。
Our dog — Jelly (needs haircut)
- 狗:55%(好)
Our dog — Jelly (needs haircut)
- 狗:100%(优秀)。
Our dog — Jelly (needs haircut)
- 狗:89%(非常好)。即使有黑色背景,分类也非常有效。
Our dog — Jelly (winter time)
- 猫:19%(很差)。在这张照片中,我们的狗看起来更像一只猫。
Our dog — Jelly
- 狗:51%(好)
Our dog — Jelly (after haircut)
- 狗:74%(非常好)。与上一张图片稍微不同的角度(脸部更清晰)使得效果更好。
Our dog — Jelly
摘要:convnet 是在一个小数据集上训练的,它仍然可以提供非常好的分类结果(用我的狗图片验证:)
使您的模型更好地工作的变量转换目录
原文:https://towardsdatascience.com/catalog-of-variable-transformations-to-make-your-model-works-better-7b506bf80b97?source=collection_archive---------3-----------------------
本书"赢得 KAGGLE 的数据分析技巧"
10 多个数字变量转换和 7 个分类变量转换
变量转换是使数据在模型中更好工作的一种方式。数据变量可以有两种形式:数字变量和分类变量,它们的转换应该有不同的方式。
-数值变量转换 : 将一个数值变量转换成另一个数值变量。通常,这意味着通过某种“单调变换”来改变值的标度和/或将偏斜的数据分布调整为类似高斯的分布。
基于决策树的模型对比例和倾斜不太敏感,这些技术可能贡献不大,但对于其他模型(如神经网络、SVM、线性模型等。),它们可能会改变游戏规则,或者在某些情况下甚至是强制性的,例如在 L1/L2 规范中使用惩罚条款的情况。
-分类变量转换 : 将分类变量转换为数值变量。分类变量转换对于大多数机器学习模型是强制性的,因为它们只能处理数值。
它也被称为编码,或者在文本挖掘中,嵌入也是为了处理类似的情况,但是嵌入通常被认为是返回包含原始数据语义的数值。
分类变量变换对任何模型都很重要,分类变量变换的选择对模型性能有很大影响。
在这篇文章中,我将介绍转换数值变量和分类变量的基本到高级技术。
目录
1。关于变量变换的一般注意事项
2。数值变量转换
- 2.1.标准化
- 2.2.最小-最大缩放
- 2.3.对数变换
- 2.4.博克斯-考克斯变换
- 2.5.约-约翰逊变换
- 2.6.剪报
- 2.7.扔掉
- 2.8.军阶
- 2.9.兰克高斯
- 2.10.其他非线性变换
3。分类变量转换
- 3.1.一键编码
- 3.2.标签编码
- 3.3.特征散列
- 3.4.二进制编码和基本编码
- 3.5.频率编码
- 3.6.目标编码
- 3.7.只有测试集中包含的水*时的特殊处理
- 3.8.更多分类变量转换
4。结论
这是另一篇帖子接的一本新书中介绍的技巧数据分析技巧赢 Kaggle ”,由三位高阶 Kaggle 作者执笔(不包括我自己)由此可见这不是个人推广!😃 )
关于这本书本身的完整目录,请参见我的其他帖子。
1.对变量变换的普遍关注
有许多用于建模的转换技术,许多在 [scikit-learn](https://scikit-learn.org/stable/modules/classes.html#module-sklearn.preprocessing)
和[categorical_encoders](https://contrib.scikit-learn.org/categorical-encoding/index.html)
中实现。
其中使用参数的有很多,比如标签编码中标准化或换算表的均值和标准差。使用变量变换的一个常见错误是使用不同的参数分别变换训练集和测试集。训练数据和测试数据的转换应该使用相同的参数,并且它们通常单独从训练集中获得;否则,我们无法比较苹果之间的结果。scikit-learn
转换器类可以通过使用fit
和transform
函数来处理这个问题。
Do not encode test data separately!
有些人会更严格地声称,当使用交叉验证时,转换参数将仅从训练折叠中导出,然后验证折叠数据将由这些参数转换,而不是在交叉验证之前转换整个训练数据。当您预计褶皱之间的数据分布存在巨大差异时,这种方法可能是必要的。异常值的存在是给出不同参数的一个可能原因,特别是在对异常值敏感的变换技术中,如最小-最大缩放。
或者其他一些人可能声称,只要数据分布差异不大,在交叉验证之前转换整个训练数据就足够了,并且可以避免数据流水线的混乱。此外,我们的最终模型将基于整个训练数据,因此使用整个训练数据来转换数据可能是有意义的。
无论哪种方式,分析师总是要问自己,对于他们面对的数据,什么是最合理的方法。scikit-learn
通过在[Pipeline](https://scikit-learn.org/stable/modules/generated/sklearn.pipeline.Pipeline.html)
中分配 scaler 函数,支持跨验证内转换。比较下面示例代码中的方法 1 和方法 2。
Photo by Matt Duncan on Unsplash
2.数字变量转换
2.1.标准化
最典型的数字变量转换是使用减法和除法将列值转换为另一组值,其中均值=0* 和标准差=1 ,这样:*
Formula for standardization
标准化*广泛应用于许多 ML 技术,如线性回归、SVM、神经网络等。一些 ML 模型在某种程度上要求它。默认情况下,许多分析工具甚至会自动执行此操作。如果是这种情况,您甚至不必编写代码来进行转换。我们需要注意什么是默认转换,以及它是否与您选择的方法相关。***
scikit-learn
的preprocessing
模块的[StandardScaler](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.StandardScaler.html)
可以处理标准化。
2.2.最小-最大缩放
**最小-最大缩放是简单数字变量转换的另一个常见疑点。使用最小-最大缩放,值将被转换为 0 到 1 之间的值。
Formula for min-max scaling.
这种转换高度依赖于最大数和最小数,因此对异常值特别敏感。如果值可能非常大,而许多值却不是,则标准化更为常见。最小值-最大值缩放更常见于数值范围在固定区间内,且数据不太可能在区间内的特定子范围内聚集的情况;最常见于图像数据中,其中一个元素的 RGB 颜色值在 0 到 255 之间。
scikit-learn
preprocessing
模块的[MinMaxScaler](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.MinMaxScaler.html)
可以处理最小-最大缩放。
2.3.对数变换
当价值分布具有长尾分布时(如个人收入、个人医疗费用等。), 对数变换可以将数据分布调整到更少的偏斜,希望是类似高斯的分布。
Formula of log transformations
numpy
有一个原生函数将 log(x+1)计算为[np.log1p(x)](https://docs.scipy.org/doc/numpy/reference/generated/numpy.log1p.html)
。
广义对数变换应该调整数据分布的参数λ,使其更接*正态分布。现在你要记住,你不应该如我在 "1 中所讨论的那样更改训练集和测试的参数。关于变量转换的一般注意事项见上文。
2.4.博克斯-考克斯变换
Box-Cox transformation
Box-Cox 变换*是 log(x)变换和 x-1 变换之间的变换,取决于λ的值。scikit-learn
preprocessing
中的[PowerTransformer](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.PowerTransformer.html)
模块可以处理这种转换,自动选择λ使数据最接*高斯**。*
Box-Cox Transformation
2.5.约-约翰逊变换
Yeo-Johnson transformation.
**Yeo-Johnson 变换是允许负值作为初始值的变换,与 Box-Cox 变换不同。lambda=1 时,变换几乎是恒等变换。如下图所示,lambda 的变化会影响变换后的值。
以及 Box-Cox 变换,scikit-learn
preprocessing
模块中的[PowerTransformer](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.PowerTransformer.html)
可以处理这种变换,自动选择 lambda 使数据最像高斯。
Yeo-Johnson Transformation.
2.6.剪报
**限幅是一种在特定值点限制或降低值的方法。这可以移除异常值,代价是可能丢失原始数据信息。
通过pandas
或numpy
clip
功能可以轻松完成裁剪。以下代码剪辑了 1%*铺点和 99%*铺点的值。
2.7.扔掉
在宁滨中,您将值分组到不同的区间,并将组索引用作分类变量。您可以将它用作有序分类变量或数值变量作为等级。作为分类变量,你也可以通过一键编码或其他分类变量转换来转换它(见下一章!)
宁滨区间的确定是参数选择,可以通过规则区间、百分点或基于数据领域知识的手动设置来确定。
宁滨可以通过pandas
cut
功能或numpy
digitize
功能来完成。
2.8.军阶
将原始数值转换为数值等级。通过除以记录数,等级还可以转换为 0 到 1 之间的值,这使得转换后的数量与记录数无关。
这本书介绍了一个有趣的例子:在分析一家商店的顾客数量时,假日的顾客数量很可能比工作日的顾客数量多很多。然后,使用原始的顾客数量可能会把假期看得太重。将数字转化为排名可以抵消客户绝对数量的影响。
pandas
rank
函数或numpy
argsort
函数可以处理这种转换。
2.9.兰克高斯
RankGauss 是一种先将数值转化为等级,再按照高斯分布将等级转化为另一个数值的方法(见下图。)这是用于* Porto Segro 的安全驾驶员预测第一名解决方案 为其神经网络模型。第一名得主 Michael Jahrer 声称对于他们的神经网络模型来说,这比标准化或最小-最大缩放更有效。*
sklearn.preprocessing
中的[QuantileTransformer](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.QuantileTransformer.html)
可以通过设置参数n-quantiles
large 和output_distribution = ‘normal’
来处理这种变换。
Comparison between original data and transformed data by RankGauss
2.10.其他非线性变换
书中还介绍了以下非线性变换:
- 取绝对值
- 求*方根
- *方或取 n 次方
- 制作一个二进制变量,表示原始值的属性,如正或负、零或零等。
- 取原始值的分数,如小数部分
- 舍入,向上舍入,截断
Photo by Andrew Buchanan on Unsplash
3.分类变量转换
机器学习模型只能处理数值型变量。因此,如果一个列有分类变量,那么只有当它被编码为数字变量时,模型才会工作。如何编码是建模中的关键性能驱动因素之一。
3.1.一键编码
One-hot encoding 是一种将一个分类列转换为多个二进制(0 或 1)列的方法,其数量与原始列中不同级别的数量相同。如果分类变量有四个级别,one-hot 编码将创建四个新列,每个列都有 0 或 1,并表示原始列是否有级别。
Illustration of one-hot encoding (four-level column (A-D) creates four new columns)
one-hot 编码的一个明显缺点是列的数量很容易随着许多不同的级别而膨胀。一个可能的解决方案是根据领域知识对一些级别进行分组,或者将不常见的级别分组到“其他”级别中。
您可以使用pandas
[get_dummies](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.get_dummies.html)
功能或scikit-learn
preprocessing
模块的[OneHotEncoder](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html)
进行一键编码。后一个可以返回带sparse=True
参数的稀疏矩阵,在原列有很多级的情况下可以节省内存消耗。
一键编码看起来类似于传统统计建模中的虚拟变量。一键编码和虚拟变量之间的区别在于,在使用虚拟变量时,通常会从生成的新列中删除一列,以避免线性相关性,并且可以稳定估计。这种差异的原因是在 ML 环境中,
- 有比统计建模多得多的变量,并且一个变量的影响被稀释了。
- 由于各种原因,许多 ML 算法并不关心线性相关性,如使用正则化项,或者选择部分变量来训练模型,从而丢失了线性相关性。
3.2.标签编码
**标签编码是一种将等级转换为整数的方法,例如等级:['A ',' B ',' C ',…]转换为整数:[0,1,2,…]。
Illustration of label encoding
这种方法在大多数机器学习算法中并不合适,因为转换值的数量实际上与目标变量无关,基于决策树的模型除外,该模型可能能够通过分层树节点拆分来多次拆分转换后的数值列。此外,如果分类变量具有“序数”性质*,例如 Cold<Warm<Hot<Very Hot,标签编码可能比其他编码技术工作得更好。*
可以用scikit-learn
preprocessing
模块的[LabelEncoder](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.LabelEncoder.html#sklearn.preprocessing.LabelEncoder)
实现标签编码。
3.3.特征散列
**特性散列是一种使用散列技巧将一个分类列转换为多个列的方法。您可以定义要转换到的新列的数量,该数量可以少于分类列中的级别数。不同于像一键编码那样分配 0 或 1,特性哈希使用两个以上的值(在下面的例子中是-1、0 或 1)。
Illustration of feature hashing (four distinct levels to three new columns)
这种标记可以掩盖一键编码在转换后产生过多列的缺点。然而,在最*的高级建模技术中,拥有太多的列不再是致命的问题,因此特征散列没有被广泛使用*。*
此外,在一个新列中有两个以上的可能值可能对某些模型不利。
您可以通过scikit-learn.feature_extraction
模块的[FeatureHasher](https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.FeatureHasher.html#sklearn.feature_extraction.FeatureHasher)
或category_encoders.hashing
模块的[HashingEncoder](https://contrib.scikit-learn.org/categorical-encoding/hashing.html)
对特征散列进行编码。
3.4.二进制编码和基本编码
**二进制编码是一种将分类列转换为多个二进制列,同时最小化新列数量的方法。
首先,按照一定的顺序将分类值转换为整数(例如,按字母顺序或最上面一行的出现顺序)。接下来,将其转换为二进制数字,例如 1 到 1,2 到 10,5 到 101,等等。最后,将二进制数字拆分成单独的列,每一列都有一个数字。
Illustration of binary encoding
二进制编码可以将新列数减少到 log_2(级数)阶。正如你在上面的例子中看到的,其中一个新列在不同的原始级别中有 1,这不是一件好事*因为在同一列中有 1 的级别将被模型视为共享一些属性,而实际上它们在同一列中有 1 只是出于技术原因。*
[category_encoder](https://contrib.scikit-learn.org/categorical-encoding/index.html)
模块的[BinaryEncoder](https://contrib.scikit-learn.org/categorical-encoding/binary.html)
可以处理这些编码。
**BaseN 编码是二进制编码的推广,BaseN 不使用基数 2,而是使用任意数作为基数。
Illustration of Base N encoding when N = 3
随着 N 的增加,新列的数量越来越少,但这也意味着新列中的重叠信息比我们在二进制编码情况下看到的更多,这可能会使最终的模型变得更糟。如果 N 是无穷大,BaseN 编码和 label 编码完全一样。正如我上面所讨论的,标签编码对于大多数模型都是不合适的。
[category_encoder](https://contrib.scikit-learn.org/categorical-encoding/index.html)
模块的[BaseNEncoder](https://contrib.scikit-learn.org/categorical-encoding/basen.html)
可以处理这些编码。
3.5.频率编码
频率编码*是一种将分类列转换为新列的方法,新列中的整数表示原始列中**级别的频率。当水*的频率对目标变量有影响时,这可能很有效。*
Illustration of frequency encoding.
你也可以把频率变成等级,就像序列化频率编码和等级转换一样。请注意,级别的频率比原始数据的排名更有可能导致*局。
python 中没有支持这种编码的库,但这可以通过pandas.Series
本机函数[value_counts()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.value_counts.html)
轻松实现。
3.6.目标编码
目标编码*是一种基于目标变量的值将分类列转换为新的数字列的方法。***
Illustration of target encoding (in case target variable is binary (0 or 1)).
最典型的是,它采用每个级别的目标值的*均值来创建一个新列,但是它可以是您认为合理的任何值,比如当有异常值时的中值,或者当评估度量是 RMSLE 时的对数值的*均值。
目标编码可能会成为强有力的预测工具,但正如本书作者反复警告的那样,除非小心处理,否则它很容易导致数据泄露。**
因为目标编码使用来自目标变量的信息,所以我们必须避免包含要编码的同一行。为此,我们应该k-folding(其中 k=4~10) 数据:训练折叠中目标值的*均值被指定为出折叠数据中的编码值。对每个折叠重复此操作,为整个训练数据生成编码值。测试数据通常使用整个训练数据进行编码。
Illustration of K-folding for target encoding (in case target variable is binary (0 or 1)).
[category_encoders](https://contrib.scikit-learn.org/categorical-encoding/targetencoder.html)
模块有目标编码处理器TargetEncoder
,但即使这样,你也必须自己完成 K-fold。
作者还声称你不应该使用**(LOO)进行目标编码,因为这太有可能导致数据泄露。
3.7.只有测试集中包含的水*时的特殊处理
当某些级别仅包含在测试数据中时,模型可能会返回错误,或者即使没有返回错误,预测也可能是错误的。
以下是处理这种情况方法:
- 如果只是预测精度的问题,而不是返回一个技术错误,那么检查一下糟糕的预测对最终得分的影响有多大。如果它足够小,忽略它是一个可行的想法。
- 用训练数据中包含的另一个级别替换,例如使用训练数据中最常用的级别。
- 基于其他变量建立预测模型以预测一个水*来代替未知水*。
- 在将分类变量编码为数值变量后,将其输入,例如,用目标编码变量的数据*均值进行输入。
3.8.更多分类变量转换
Baijayanta Roy 的这篇文章“关于分类变量编码的一切”涵盖了更多的编码技术。
另外,[categorical_encoders](https://contrib.scikit-learn.org/categorical-encoding/index.html)
模块涵盖了白加炎塔帖子中介绍的大部分技术的实现。您可以通过使用本模块中的功能来进一步学习。
Photo by Robert Katzki on Unsplash
4.结论
在这篇文章中,我们讨论了从基本方法到高级方法的 10 多个数字变量转换技术和 7 个分类变量。
虽然有些技术比其他技术更好,例如目标编码比其他编码技术有更好的跟踪记录,但没有一种方法总是在任何数据的每个模型中都工作良好。因此,研究什么样的编码在什么情况下工作良好是很重要的,当你面临一个新问题时,你可以使用本文中介绍的尽可能多的方法,直到你发现哪种方法工作得最好。**