TowardsDataScience-博客中文翻译-2020-九十四-
TowardsDataScience 博客中文翻译 2020(九十四)
原文:TowardsDataScience Blog
协议:CC BY-NC-SA 4.0
用 MCMC 方法预测保留曲线
原文:https://towardsdatascience.com/predicting-retention-curve-with-mcmc-method-311b36a3cf5b?source=collection_archive---------19-----------------------
贝叶斯方法预测给定群组的保留曲线,以估计未来的回报率
赫苏斯·罗查在 Unsplash 上拍摄的照片
嘿伙计们,
今天,我将介绍我最*开发的一个解决方案,用于预测给定群组的保留曲线。
定义
总的来说,留存是一个衡量你给应用带来的用户粘性的指标。例如,7 天后的高保留率表明你为应用程序带来的用户会停留很长一段时间,从而给你一个他们是优质用户的指示。
保留曲线看起来像这样:
保留曲线
因此,正如我们所料,它从一个非常高的位置开始,在一个群体的早期,用户倾向于坚持更多。我们看到保留曲线的指数衰减,这也高度表征了应用程序中用户的行为。
我们在这篇文章中的目的是预测给定群组的精确曲线,以估计这些用户对应用程序的忠诚度,我们预测这个给定群组会有多少活跃用户,等等。
预测保留率的 3 种方法
因此,在理解了保持意味着什么之后,我们可以继续思考手头问题的可能解决方案。
- 平均保留曲线 这个解决方案可能是最直观的。我们只是选取许多群组,观察他们的行为,然后对他们的行为进行平均,形成平均保留曲线。有了这条保持曲线,我们将通过假设新的群组接*平均行为来估计它们。
- 仅基于现有数据拟合曲线 通过这种方法,我们将收集给定群组的相关信息,即我们已经拥有的其保留曲线的现有点(例如,对于 5 岁的群组,我们已经可以使用该群组保留曲线的前 4 天来估计其完整的 30 天保留曲线),并尝试基于观察到的数据拟合曲线。
- 同时考虑 1 和 2 的 MCMC 方法 当我们可以从两种方法中获益时,为什么只使用一种方法?在这种贝叶斯方法中,我们使用队列曲线上的先验知识,以及迄今为止我们获得的实际数据。
我们将在整篇文章中介绍这三种方法,并对它们进行比较,以获得估计保留曲线的最佳方法。
制定保留曲线
我们旅程的下一步是以参数的方式制定保留曲线。
正如我们已经讨论过的,保留曲线类似于指数衰减。由于这个原因,我们可以用公式表示这条曲线:
保留曲线公式
这个方程中我们有两个参数: b(截距)和 c(斜率)。 我们可以看到,当使用这种估计来描述我们之前看到的保留曲线的行为时,我们可以很好地描述保留曲线:
实际行为与公式化行为
因此,我们在上面建议的 3 种方法中的目的是估计参数 b 和 c,以便使曲线尽可能接*。
方法评价和比较
方法 1:平均保留曲线 在这一节中,我们将寻求找到我们的保留曲线的平均行为。
正如我们在上一节中看到的,由于曲线可以用参数方式定义,我们可以找到我们群组分布的平均值 b 和 c。这些平均值将作为平均保留曲线。
平均保留曲线性能
正如我们从上面的图中看到的,平均曲线显示了不错的结果,平均误差接* 0,误差条在实际保留曲线的+-2.5%左右徘徊。
方法 2:平均保留曲线
对于这一部分,我们将展示的性能实际上取决于我们实际拥有的数据量。从逻辑上讲,我们拥有的数据越多,我们就越准确。
例如,基于 5 天的数据,我们得到相当糟糕的结果:
我们看到,与方法 1 相比,我们不再处于 0%误差线上,因为我们看到向下移动。然而,标准偏差确实降低了。这是由于我们对每个群体的个人待遇。
另一方面,如果我们等待更多的数据,我们可以获得比方法 1 好得多的结果。例如,以下是基于 18 天而非 5 天数据的结果:
哇!这是一个很大的进步。与方法 1 相比,我们实现了非常低的误差和低得多的可变性。
最后两张图可以作为第三种方法的介绍。
我们已经看到,在不同的情况下,我们从两种方法中获得了优势。
当缺乏数据时,我们可能更喜欢坚持平均曲线,但当我们有足够多的数据时,我们将不再需要平均行为,因为我们已经可以依赖我们从特定群体中看到的。
这种思维方式完全符合方法 3 中的贝叶斯方法。
在贝叶斯方法中,我们将有一个先验(在这种情况下,将由平均保留曲线参数表示)、一个似然函数(将由我们到目前为止看到的实际数据表示),从这两个部分,我们将形成一个后验、,它将包含从两个部分收集的信息并形成一个统一的度量。
由于我们没有归一化常数,我们将使用 MCMC 算法来克服这个障碍。
方法 3:基于 MCMC 的保留曲线 使用所解释的方法,我们将在 5 天的数据后获得这些结果:
我们可以看到,当证据不足时,新的(绿色)方法停留在先前的数据上。实际数据有一定的权重,但它并没有对基于后验的模型产生很大影响。
现在,基于 18 天的数据:
我们现在看到后验是如何向实际数据转移的,而把先验知识留在后面。
摘要
我们通过三种方法来估计保留曲线。
一种是基于平均行为,一种是基于实际数据,表现最好的是 MCMC 方法,它同时考虑了实际数据和先前数据。
我希望这些信息对你有用,也能帮助你形成公司的保留曲线!
用分类预测航空旅客的满意度
原文:https://towardsdatascience.com/predicting-satisfaction-of-airline-passengers-with-classification-76f1516e1d16?source=collection_archive---------6-----------------------
案例研究与 KNN,逻辑回归,高斯 NB,决策树和随机森林。
照片由马塞尔在 Unsplash 上拍摄
这是一个分类监督的机器学*项目,作为 Metis 数据科学训练营(新加坡)项目 3 的一部分完成。在大约 3 周的时间里,我们的讲师带我们经历了一次关于 SQL、AWS、各种分类技术以及如何在 Flask 应用程序上部署我们的机器学*模型的旋风式旅行。在这篇博客中,让我带你浏览我根据飞行调查数据建立的模型,并展示它可能创造的商业价值。
1.背景
由于大多数国际航空旅行已经停飞,世界各地的航空公司业务受到新冠肺炎的重创。受打击最大的可能是新加坡航空公司,该公司在其岛国运营零国内航班。事实上,泰国航空公司等一些航空公司已经申请破产。尽管如此,一旦风暴结束,随着人们纷纷返回海外度假,预计航空旅行的需求将会激增。当人群最终到来时,航空公司可以准备什么来给自己带来竞争优势?为了回答这个业务问题,根据 Kaggle 的航班满意度调查数据创建了一个分类模型,以确定导致客户满意度的关键因素。
2.数据准备
原始数据集包含来自一家美国航空公司的大约 130,000 个调查条目和乘客/航班详细信息。总共有 21 个特征列和 1 个二元目标列。在所有功能中,有 14 个是调查条目,乘客在 1 到 5 的范围内对飞行体验进行评分。但也有一些调查条目的分值为 0,我推断是未填写的调查问题。在移除这些调查条目和一些 NaN 值之后,用于模型构建的结果数据集具有大约 70,000 个条目。此外,为了更加清晰,一些列和其他条目已被重命名。最后,我得到了如下所示的清理后的数据集:
数据清理后用于建模的数据集。
3.EDA 和特征选择
目标等级相当均衡,56.4%的乘客表示中立/不满意(负面等级:0),43.6%的乘客表示满意(正面等级:1)。负面类别中的大量条目并不令人惊讶,因为“中性/不满意”并不一定意味着不满意。还包括对飞行体验漠不关心的乘客。
当我根据客户类型进一步细分满意度类别时,我们看到首次客户的满意度较低。此外,当我按旅游类型划分满意度等级时,观察到个人(度假)旅游的顾客满意度明显较低。在这两种情况下,对体验的更高期望可能是满意度下降的原因之一。
目标类的探索性数据分析。
接下来是特征选择,我的目标是去除那些无助于建立预测模型的特征。这些要素包括对区分目标类没有贡献的要素以及高度相关的要素,这可能会导致多重共线性问题。我希望尽可能保留包含调查条目的功能,这样我就可以确定航班满意度的各个方面。为此,我应用核密度估计(KDE)图,相关热图和套索回归进行特征选择。
按目标类别划分的要素的核密度估计(KDE)图(满意:1,中性/不满意:0)
相关热图。最左边的列显示了特征和目标之间的相关性。
套索回归图。更快降至零的系数表示特征重要性较低。
- KDE 图:特征‘登机口位置’似乎包含缺失的分数‘2’和‘4’,表明异常,因为乘客不可能没有输入这些分数。在特征“性别”上,两者的满意度分布大致相同,表明其与目标相关性差,因此被移除。
- 相关性热图:特征‘年龄’、‘出发/到达时间便利性’、‘登机口位置’和‘总延误’与目标具有 0.15 及以下的低相关性。
- 套索回归图:最不重要的特征具有线性系数,当阿尔法超参数增加时,线性系数最早减少到零。从图中,我发现这些特征是“食物和饮料”、“在线预订的便利性”、“年龄”、“飞行距离”、“总延迟”和“登机口位置”
经过仔细考虑,我决定去掉“性别”、“年龄”、“登机口位置”、“总延误”、“飞行距离”和“出发/到达时间便利性”这些特征。最后,我们只剩下包含大多数调查类别和客户/类别类型的 15 个功能。
4.型号选择
在我确定哪个分类模型对数据集最有预测性之前,我将数据分成 80%用于 5 重交叉验证,20%作为测试集用于所选模型的最终评估。然后,我对各种分类模型进行 5 重交叉验证,以确定它们的最佳超参数。
将数据集分为测试集(20%)和训练-验证集(80%)
因此,在 Scikit-Learn 上运行 GridSearchCV 算法,模型及其最佳超参数为:
- k-最*邻(k=7)
- 逻辑回归(C=0.04)
- 决策树(最大深度=12)
- 随机森林(最大深度=17)
此外,我还在交叉验证过程中使用了高斯朴素贝叶斯和集成方法(通过投票选择所有模型)。在对所有考虑的模型进行 AUC、精度和召回率评分时,随机森林模型被确定为表现最佳,AUC 为 0.99,精度为 0.97,召回率为 0.94。
所有分类模型交叉验证的平均分数。
接下来,让我们了解一些评分标准的含义,这将使我们能够确定哪个评分标准与我们的业务问题最相关。
- 召回:模型正确预测的阳性类别数与实际阳性类别总数的比值。例如,这一指标对于预测患者癌症的模型非常重要,因为捕捉尽可能多的阳性病例至关重要。
- 精度:模型正确预测的阳性类别数与预测的阳性类别总数之比。例如,该指标与垃圾邮件过滤器模型相关,因为只捕获实际的垃圾邮件案例并减少误报数量至关重要。
在这种范式下,拥有高精度对于我们的业务问题将更加重要。为了正确识别导致客户满意的关键因素,正类“满意”的模型预测需要非常可靠。
由于概率阈值的调整带来了查准率和查全率的权衡,我进一步使用随机森林模型做了一个简单的验证来决定最佳的概率阈值。
简单验证:在训练集上重新训练随机森林(60%),并对验证进行评分(20%)
不同阈值随机森林的精度和召回分数
随机森林的默认概率阈值是 0.5。在调优到 0.7 之后,精度从 0.97 提高到 0.99,而在召回率上没有巨大的牺牲。由于这符合我们的模型目标,我选择我们的最终模型为随机森林(最大深度=17 ),概率阈值为 0.7。
5.模型评估
最后,我在 80%的数据集(训练集+验证集)上重新训练选择的模型,然后在剩下的 20%的数据集(测试集)上评估预测。模型性能的最终评估给出的 AUC 为 0.993,召回率为 91.2%,准确率为 99.1%。
测试集上随机森林模型最终评价的 ROC 曲线。
对模型最终评价的混淆矩阵,显示召回率为 91.2%,准确率为 99.1%。
测试集上的模型预测示例。
99.1%的精度意味着当模型预测到乘客满意时,模型确信预测是 99.1%准确和真实的。让我们看看如何将这种高精度应用于商业问题。
6.商业问题
如前面的探索性数据分析所示,首次客户有更高的期望,因此不太可能满意。然而,获得首次客户的满意度是很重要的,因为这可以确保他们更有可能回到航空公司旅行。使用该模型,我们可以探索导致初次顾客满意的重要因素。
- 乘坐经济舱的个人旅行 —首次顾客
经济舱个人旅行首次顾客满意度的样本模拟。
对于个人旅行的经济舱客户,当我开始将所有类别设置为平均评级(评级:3)时,模型不确定客户是否会满意。然而,如果我将机上 Wifi 服务评级提高到优秀(评级:5),其余类别表现一般,该模型确定客户将会满意。有趣的是,如果我降低机上 Wi-Fi 服务等级,同时将其余类别设置为优秀等级,该模型仍然不确定客户是否会满意。
- 乘坐商务舱进行商务旅行 —首次客户
商务舱商务旅行首次客户满意度模拟示例。
对于商务旅行的商务客户,该模型预测他们将更容易满足。由于机上 Wi-Fi 服务评级较低,而其余类别被设置为优秀评级,该模型肯定会让商务客户满意。但是,当我继续降低其余类别的评分时,只有当我至少将在线预订的易用性评分设置为优秀(评分:5)时,模型才能确定客户会满意
为了试验和预测对其他评级排列的满意度,我还在 Heroku 上创建了一个 Flask 应用程序,供潜在的航空公司高管探索这种模式。然而,在应用程序中,为了更简单的理解,我将模型概率阈值降低到了 0.5。
7.结论
我为航空公司创建了一个高度精确的分类模型,以确定提高乘客满意度的关键瓶颈。根据一些模拟,我建议航空公司应该专注于改善飞行中的无线网络服务体验。例如,航空公司可以开发更好的软件,以便更容易地访问机上 wi-fi,或者降低访问机上 wi-fi 的成本,以便更多的经济舱客户可以享受服务。此外,航空公司还应该关注在线预订的便捷性,因为商务旅客优先考虑他们旅行中的便捷性。
最后,希望该模型能为航空公司提供参考,并发挥商业价值。也就是说,我期待 Metis 数据科学训练营的项目 4,在该项目中,我们将致力于聚类、自然语言处理(NLP)和推荐系统。我将很快再次分享,敬请期待!
这里是到我的 GitHub 的链接,它包含了这个项目的所有代码和演示幻灯片。
你觉得我的模型怎么样?通过我的 LinkedIn联系我或者在下面评论来讨论!
附:如果你有兴趣了解 逻辑回归、决策树 或 随机森林 如何运作,我鼓励你看看我下面的一些文章:
[## 从零开始的决策树和随机森林
对决策树和随机森林算法的全面外行介绍
towardsdatascience.com](/decision-tree-and-random-forest-from-scratch-4c12b351fe5e) [## 从零开始的神经网络:逻辑回归—第 1 部分
单层神经网络与裸基础的逻辑回归
medium.com](https://medium.com/mlearning-ai/neural-networks-from-scratch-logistic-regression-part-1-d8cfc4a2fb3b)
支持我! —如果你没有订阅 Medium,并且喜欢我的内容,请考虑通过我的推荐链接加入 Medium 来支持我。
[## 加入我的介绍链接媒体-谭师鹏阿尔文
阅读谭·师鹏·阿尔文(以及媒体上成千上万其他作家)的每一个故事。您的会员费直接…
tanpengshi.medium.com](https://tanpengshi.medium.com/membership)
预测员工评论的情绪
原文:https://towardsdatascience.com/predicting-sentiment-of-employee-reviews-ec0c0c837328?source=collection_archive---------33-----------------------
对来自 Indeed.com 的员工评论的正面和负面情绪进行分类
奥利维尔·科莱在 Unsplash 上拍摄的照片
在我之前的文章中,我们学*了如何从 Indeed.com 的收集、流程、分析员工评价。请随意查看并提供反馈。我很想听听你会如何改进代码。特别是,如何动态地克服网站的 HTML 的变化。
在这篇文章中,我想把我们的数据集进一步解决情感分类问题。具体来说,我们将为每个评论分配情感目标,然后使用二元分类算法来预测这些目标。
我们将导入从 Indeed.com 收集的原始员工评论。我建议你回顾一下我以前的文章来了解我们是如何获得这个数据集的。
首先,让我们导入数据集并进行处理。对于此分析,我们只需要“评级”和“评级 _ 描述”列。关于文本预处理更详细的解释,请阅读我的 nlp 预处理文章。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import contractions
import random
import fasttext
from autocorrect import spell
from nltk.probability import FreqDist
from nltk.tokenize import word_tokenize
import nltk
from nltk.corpus import stopwords, wordnet
from sklearn.feature_extraction.stop_words import ENGLISH_STOP_WORDS
from nltk.stem import WordNetLemmatizer
from imblearn.over_sampling import SMOTE
from sklearn.model_selection import train_test_split
from sklearn.model_selection import StratifiedKFold
from imblearn.pipeline import make_pipelinefrom sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNBfrom sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
from sklearn.metrics import precision_recall_curve
from sklearn.metrics import roc_auc_score
from sklearn.metrics import auc
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import GridSearchCVfrom warnings import simplefilter
simplefilter(action='ignore', category=FutureWarning)
pd.set_option('display.max_colwidth', 200)with open('apple_scrape.csv') as f:
df = pd.read_csv(f)
f.close()print(df.head())df = df[['rating', 'rating_description']]
消除收缩
df['no_contract'] = df['rating_description'].apply(lambda x: [contractions.fix(word) for word in x.split()])
将单词列表转换为字符串
应用“fix”函数的结果是一个单词列表,我们需要将该列表转换回字符串。
df['rating_desc_str'] = [' '.join(map(str, l)) for l in df['no_contract']]
删除非英语评论
首先,我们将使用“快速文本”库来识别每个评论的语言。使用此链接下载预训练模型。一旦每个评论被标记,我们只需过滤数据框,只包括英文评论。
pretrained_model = "lid.176.bin"
model = fasttext.load_model(pretrained_model)langs = []
for sent in df['rating_desc_str']:
lang = model.predict(sent)[0]
langs.append(str(lang)[11:13])df['langs'] = langsdf.head()df = df[df['langs'] == 'en']
符号化
df['tokenized'] = df['rating_desc_str'].apply(word_tokenize)
删除标点符号和特殊字符
df['no_punc'] = df['tokenized'].apply(lambda x: [word for word in x if word.isalnum()])
转换成小写
df['lower'] = df['no_punc'].apply(lambda x: [word.lower() for word in x])
拼写
df['spell'] = df['lower'].apply(lambda x: [spell(word) for word in x])
移除任何数字字符(即整数、浮点数)
df['no_num'] = df['spell'].apply(lambda x: [word for word in x if word.isalpha()])
词汇化
为了将词汇化应用于我们的记号,我们首先需要识别每个单词的词性。接下来,我们需要将从 nltk 获得的标签转换为 wordnet 标签,因为这些是我们的 lemmatizer (WordNetLemmatizer())唯一接受的标签。
df['pos_tags'] = df['no_num'].apply(nltk.tag.pos_tag)def get_wordnet_pos(tag):
if tag.startswith('J'):
return wordnet.ADJ
elif tag.startswith('V'):
return wordnet.VERB
elif tag.startswith('N'):
return wordnet.NOUN
elif tag.startswith('R'):
return wordnet.ADV
else:
return wordnet.NOUNdf['wordnet_pos'] = df['pos_tags'].apply(lambda x: [(word, get_wordnet_pos(pos_tag)) for (word, pos_tag) in x])wnl = WordNetLemmatizer()
df['lemma'] = df['wordnet_pos'].apply(lambda x: [wnl.lemmatize(word, tag) for (word, tag) in x])
删除停用词
stop_words = set(stopwords.words('english'))
df['stop_removed'] = df['lemma'].apply(lambda x: [word for word in x if word not in stop_words])
删除长度少于 3 个字符的单词
def short_words(words):
return [word for word in words if len(word) > 2]df['length'] = df['stop_removed'].apply(short_words)
我们剩下的是一个大的 dataframe,它包含我们执行的每个预处理步骤的一列。我更喜欢以这种方式工作,因为我们可以很容易地看到每一步前后的变化。如果你问我的话,会使数据验证更容易。
决定情绪
我们可以利用像“TextBlob”这样的库。情绪”来计算每个评论的情绪,但由于我们有实际的员工评级,我们可以使用此列来代替。
该员工用 5 分制的李克特量表给公司评分,超过 75%的评分是正面的(即 5 或 4)。此外,5 分制的评分为 3 分(中性),可以是正面的,也可以是负面的。为简单起见,我们将删除中性评级。介于 1 和 2 之间的评分为负,介于 4 和 5 之间的评分为正。
最后,我们将筛选数据帧,使其只包含训练模型所需的列。
def sent(df):
if df['rating'] <= 2:
val = 1.0
elif df['rating'] >= 4:
val = 0.0
else:
val = -1.0
return valdf['sentiment'] = df.apply(sent, axis=1)df = df.loc[(df['sentiment']==1) | (df['sentiment']==0)]df = df[['rating', 'length', 'sentiment']]
df.head()
将数据可视化
让我们花一点时间,根据每个单词的积极或消极程度(即感悟)。为了完成这项任务,我们需要计算每个独特的单词在积极情感评论和消极情感评论中出现的频率。 最终结果将类似于下面的列表,其中“工作”一词在负面评价中出现了 425 次,在正面评价中出现了 4674 次。
下面是代码将产生的结果
为了计算上面的列表,我们首先按照情绪降序排列评论,并重置索引。接下来,我们可以看到,我们有 3570 个正面和 1039 个负面的情感评论。现在,我们将数据集分为正面和负面评论,然后创建一个由 3570 个 1 和 1039 个 0 组成的数组。
df.sort_values(by='sentiment', ascending=False, inplace=True)
df.reset_index(inplace=True, drop=True)df_pos = df[df['sentiment'] == 0.0]
df_neg = df[df['sentiment'] == 1.0]targets = np.append(np.ones(len(df_neg)), np.zeros(len(df_pos)))df['sentiment'].value_counts()
接下来,我们创建一个名为“frequencies”的空字典来存放输出。现在我们迭代 zipped(即。元组)评论和目标数组(3,570 个零和 404 个一)。当我们迭代每个评论中的每个单词时,我们以由单词及其情感组成的元组的形式创建一个对(即。1 或 0)。我们知道有 3,570 个正面评价,因此,只有前 3,570 个评价中的单词将被分配为正面的。剩余的 404 个评论中的所有单词将被指定为负面的。最终结果是单词和情感的元组键的字典,以及作为值的正面和负面词频。
例如,“工作”这个词在所有正面评价中出现了 425 次。
frequencies = {}
for y, words in zip(targets, df['length']):
for word in words:
pair = (word, y)
if pair in frequencies:
frequencies[pair] += 1
else:
frequencies[pair] = 1
print(frequencies)
现在,我们需要做的最后一件事是对“频率”字典中的每个单词的正计数和负计数求和。
首先,我们在频率字典键中索引这个单词,创建一个所有单词的列表(存储在“words”中)。接下来,我们初始化 pos_count 和 neg_count 的计数变量。如果元组关键字“单词 1.0”出现在频率字典中(即 work ',1.0)然后我们索引该关键字的值,“neg_count”变量成为该词在负面评论中出现的次数。出现在正面评论中的单词也是如此。最后,我们将单词、pos_count 和 neg_count 添加到“数据”列表中。
words = [word[0] for word in frequencies]
data = []for word in words:
pos_count = 0
neg_count = 0
if (word, 1) in frequencies:
neg_count = frequencies[(word,1)]
if (word, 0) in frequencies:
pos_count = frequencies[(word, 0)]
data.append([word, neg_count, pos_count])print(data)
正如你所看到的,如果我们把所有的单词都画出来,情节会变得有点乱,因此,让我们随机选择几个单词。因为有更多积极的评论,所以情节偏向积极的一面。
fig, ax = plt.subplots(figsize=(20, 15))x = np.log([x[1] + 1 for x in data])
y = np.log([x[2] + 1 for x in data])ax.scatter(x, y)plt.xlabel('Negative Count')
plt.ylabel('Positive Count')for i in range(0, len(data)):
ax.annotate(data[i][0], (x[i], y[i]), fontsize=15)
ax.plot([0,7], [0,7], color='red')
plt.show()
fig, ax = plt.subplots(figsize=(20, 15))data_rand = random.sample(data, 50)x = np.log([x[1] + 1 for x in data_rand])
y = np.log([x[2] + 1 for x in data_rand])ax.scatter(x, y)plt.xlabel('Negative Count')
plt.ylabel('Positive Count')for i in range(0, len(data_rand)):
ax.annotate(data_rand[i][0], (x[i], y[i]), fontsize=15)
ax.plot([0,7], [0,7], color='red')
plt.show()
特征抽出
我们将创建一个只有两个特征的矢量化特征集,而不是走一步到位的编码或计数矢量化路线,这将创建一个巨大的稀疏矩阵,(想要可视化一个稀疏矩阵看看这个)。 第一个特征将是来自“频率”字典的所有负频率的总和,用于评论中的每个唯一单词。第二个特征将是来自“频率”字典的所有频率的总和,用于评论中的每个独特的正面词。
比如看第一个特征(即。负数总计),让我们假设我们有一个包含以下单词的评论['工作','苹果','承包商']。查看之前计算的“频率”字典,该评论的特征 1 值将是 739 或(425+279+35=739)。
首先,我们创建一个备用的 1x2 numpy 阵列。在评论中循环每个单词,如果(word,1)(即。work ',1)作为一个关键字出现在频率字典中,我们将对其值进行索引。该值被赋给“x”数组中的第一列。如果这个单词不存在,那么“x”数组中的第一列将被赋一个零。然后 for 循环查看是否相同的单词但是具有积极的情绪(即 apple ',0)出现在频率字典中。如果是这样,索引值被分配给“x”数组中的第二列。当 for 循环完成其第一次迭代时,它将 x[0,0]和 x[0,1]值赋给“X”数组中相应列的第一行。
我们可以在下面的结果数据框中看到,第一篇评论中的负面词汇总数为 6790 个,正面词汇总数为 54693 个。
def features(review, frequencies):
x = np.zeros((1,2))
for word in review:
if (word, 1) in frequencies:
x[0,0] += frequencies.get((word, 1.0),0)
if (word, 0) in frequencies:
x[0,1] += frequencies.get((word, 0.0),0)
assert(x.shape == (1, 2))
return xX = np.zeros((len(df), 2))for i in range(len(df['length'])):
X[i, :] = features(df['length'][i], frequencies)X_df = pd.DataFrame(X, columns=['neg_count', 'pos_count'])
reviews_df = pd.concat([X_df, df['sentiment']], axis=1)print(reviews_df.head())
列车测试分离
X_train, X_test, y_train, y_test = train_test_split(
reviews_df.drop('sentiment', axis=1),
reviews_df['sentiment'],
test_size=0.25)
分类器评估
我们将评估六种分类器,逻辑回归、随机森林、KNN、朴素贝叶斯、支持向量分类器和梯度推进分类器。我们肯定希望我们的模型有利于对负面评论(真正的正面评论)的准确预测,因为这些评论给了我们对组织问题的洞察力。也就是说,我们不想要一个过于“挑剔”的模型,它只会预测一个负面评论是负面的,如果它是绝对确定的。我们最终想要一个更平衡的模型,它有利于准确的负面评论预测(真正的正面),但也能很好地正确分类正面评论。因此,从度量的角度来看,我们需要高召回率来正确预测尽可能多的真实负面评论,但也需要良好的精确度来最小化错误的负面评论。此外,高 AUC 分数将指示该模型具有正确分类正面和负面评论的高概率。
为了获得更准确的模型评估并避免过度拟合,我们将使用分层 K-Fold 交叉验证。这样,每个模型将在来自我们原始训练数据的训练和测试数据的不同分割上被评估 k 次。将在每个折叠处计算指标,并对所有折叠进行总体平均。我们将比较每一层的平均训练和测试指标,以确定哪个分类器可能过拟合。此外,由于训练数据中存在少数类的类不平衡,我们将在每个折叠处使用 SMOTE 技术来过采样和平衡目标。让我们看看我们的分类器表现如何。
不幸的是,兰登森林和 KNN 严重过度拟合数据。朴素贝叶斯和 SVC 具有很高的测试召回率,但模型的精度很低,导致了很高的假阴性率。最后,逻辑回归和梯度推进分类器具有非常相似的分数,但是后者具有稍高的精度和 AUC。这似乎是一个稍微平衡的模型。
models = []
models.append(('log_reg', LogisticRegression(max_iter=10000, random_state=42)))
models.append(('rf_classifer', RandomForestClassifier(random_state=42)))
models.append(('knn', KNeighborsClassifier()))
models.append(('bayes', GaussianNB()))
models.append(('svc', SVC()))
models.append(('gbc', GradientBoostingClassifier()))scoring = {'accuracy': 'accuracy',
'precision': 'precision',
'recall': 'recall',
'f1_score' : 'f1',
'auc': 'roc_auc'}sm = SMOTE(sampling_strategy='auto', k_neighbors=5, random_state=42)
skf = StratifiedKFold(n_splits=10)for name, classifier in models:
pipeline = make_pipeline(sm, classifier)
scores = cross_validate(pipeline, X_train, y_train, cv=skf, scoring=scoring, return_train_score=True)
for score in list(scores)[2:]:
print('{} Avg CV Recall {} is {} | std is (+/- {})'.format(name, score[:-6],
np.mean(scores[score]).round(3),
np.std(scores[score]).round(3)))
超参数调谐
梯度推进分类器有很大范围的超参数,我们可以调整。通常,n _ 估计量(即树的数量)、最大深度和学*速率被认为是最重要的参数。我们将检查学*率、n 估计量、最大深度、最小样本分裂和最小样本叶。
请记住,这些超参数范围是多次迭代的结果。我们将从大范围开始(即范围(10,1000,100)并缩小到更具体的范围(即。800,1000,1)基于获得的分数。它似乎是 0.01 的学*率和 n _ 估计量(即 959 的树数)是最好的。
learning_rate = [0.3,0.2,0.15,0.1,0.05,0.01]
n_estimators = range(20,1000,1)param_grid = dict(gradientboostingclassifier__learning_rate=learning_rate,
gradientboostingclassifier__n_estimators=n_estimators)gbc = GradientBoostingClassifier(random_state=42)
skf = StratifiedKFold(n_splits=10)
sm = SMOTE(sampling_strategy='auto', k_neighbors=5, random_state=42)
pipeline = make_pipeline(sm, gbc)grid = GridSearchCV(pipeline,
param_grid=param_grid,
scoring='roc_auc',
verbose=1,
n_jobs=-1,
cv=skf,
return_train_score=True
)
grid_results = grid.fit(X_train, y_train)print('Best Score: ', grid_results.best_score_)
print('Best Params: ', grid_results.best_params_)
scores = grid_results.cv_results_['mean_test_score'].reshape(len(learning_rate),len(n_estimators))plt.figure(figsize=(30, 15))
plt.pcolor(scores, cmap='coolwarm', alpha=0.7)
plt.xlabel('n_estimators')
plt.ylabel('learning_rate')
plt.colorbar()
plt.xticks(np.arange(len(n_estimators)), n_estimators)
plt.yticks(np.arange(len(learning_rate)), learning_rate)
plt.title('GridSearchCV Test AUC Score')
plt.show()
现在我们转向 max_depth,即每个决策树可以构建的深度。增加深度使模型能够捕捉更多的信息(增加复杂性),但是有一个收益递减的水平,因为太多的级别模型将开始过度拟合。
似乎 max_depth 为 2 是最佳的,增加深度我们可以看到模型很快开始过度拟合。
max_depth = [2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20]param_grid = dict(gradientboostingclassifier__max_depth=max_depth)gbc = GradientBoostingClassifier(random_state=42,
learning_rate = 0.01,
n_estimators = 959)
skf = StratifiedKFold(n_splits=10)
sm = SMOTE(sampling_strategy='auto', k_neighbors=5, random_state=42)
pipeline = make_pipeline(sm, gbc)grid = GridSearchCV(pipeline,
param_grid=param_grid,
scoring='roc_auc',
verbose=1,
n_jobs=-1,
cv=skf,
return_train_score=True)
grid_results = grid.fit(X_train, y_train)print('Best Score: ', grid_results.best_score_)
print('Best Params: ', grid_results.best_params_)
cv_results_df = pd.DataFrame(grid_results.cv_results_)
cv_results_df.rename(columns={'param_gradientboostingclassifier__max_depth': 'max_depth'}, inplace=True)
train_scores_mean = cv_results_df["mean_train_score"]
test_scores_mean = cv_results_df["mean_test_score"]
max_depths = cv_results_df['max_depth']plt.figure(figsize=(10,5))
plt.plot(max_depths, train_scores_mean, label='Avg Training AUC Scores')
plt.plot(max_depths, test_scores_mean, label='Avg Test AUC Scores')
plt.xlabel('max_depths')
plt.ylabel('Avg AUC Score')
plt.legend()
plt.show()
Min_samples_split 或拆分内部节点所需的最小样本数。换句话说,如果我们将该参数设置为 2,那么该节点将需要至少两个记录/审查,以便拆分成两个节点。较高的值有助于过度拟合,因为它迫使决策树在拆分之前需要更多的记录。更多的分割=更多的深度=增加的复杂性=过度拟合。
min_samples_split = [2,3,4,5]param_grid = dict(gradientboostingclassifier__min_samples_split = min_samples_split)gbc = GradientBoostingClassifier(random_state=42,
learning_rate=0.01,
n_estimators=959,
max_depth=2)
skf = StratifiedKFold(n_splits=10)
sm = SMOTE(sampling_strategy='auto', k_neighbors=5, random_state=42)
pipeline = make_pipeline(sm, gbc)grid = GridSearchCV(pipeline,
param_grid=param_grid,
scoring='roc_auc',
verbose=1,
n_jobs=-1,
cv=skf,
return_train_score=True)
grid_results = grid.fit(X_train, y_train)print('Best Score: ', grid_results.best_score_)
print('Best Params: ', grid_results.best_params_)
cv_results_df = pd.DataFrame(grid_results.cv_results_)
cv_results_df.rename(columns={'param_gradientboostingclassifier__min_samples_split': 'min_samples_split'}, inplace=True)
train_scores_mean = cv_results_df["mean_train_score"]
test_scores_mean = cv_results_df["mean_test_score"]
min_samples_splits = cv_results_df['min_samples_split']plt.figure(figsize=(10,5))
plt.plot(min_samples_splits, train_scores_mean, label='Avg Training AUC Scores')
plt.plot(min_samples_splits, test_scores_mean, label='Avg Test AUC Scores')
plt.xlabel('min_samples_splits')
plt.ylabel('Avg AUC Score')
plt.legend()
plt.show()
Min_samples_leaf 是形成叶节点所需的最小样本数。换句话说,每个叶子必须至少有 min_samples_leaf 评论,它将其分类为正面或负面。看来 26 条评论是最佳数字。
min_samples_leaf = range(10,30,1)param_grid = dict(gradientboostingclassifier__min_samples_leaf = min_samples_leaf)gbc = GradientBoostingClassifier(random_state=42,
learning_rate=0.01,
n_estimators=959,
max_depth=2,
min_samples_split=2
)
skf = StratifiedKFold(n_splits=10)
sm = SMOTE(sampling_strategy='auto', k_neighbors=5, random_state=42)
pipeline = make_pipeline(sm, gbc)grid = GridSearchCV(pipeline,
param_grid=param_grid,
scoring='roc_auc',
verbose=1,
n_jobs=-1,
cv=skf,
return_train_score=True)
grid_results = grid.fit(X_train, y_train)print('Best Score: ', grid_results.best_score_)
print('Best Params: ', grid_results.best_params_)
cv_results_df = pd.DataFrame(grid_results.cv_results_)
cv_results_df.rename(columns={'param_gradientboostingclassifier__min_samples_leaf': 'min_samples_leaf'}, inplace=True)
train_scores_mean = cv_results_df["mean_train_score"]
test_scores_mean = cv_results_df["mean_test_score"]
min_samples_leafs = cv_results_df['min_samples_leaf']plt.figure(figsize=(10,5))
plt.plot(min_samples_leafs, train_scores_mean, label='Avg Training AUC Scores')
plt.plot(min_samples_leafs, test_scores_mean, label='Avg Test AUC Scores')
plt.xlabel('min_samples_leafs')
plt.ylabel('Avg AUC Score')
plt.legend()
plt.show()
模型评估
将我们的优化模型应用到我们坚持的测试数据中,我们可以看到边际改进。总体而言,AUC 略有上升(0.728 至 0.734),同时积极评价类别的召回率也有所上升(74%至 76%)。我们能够通过 11 个评论增加我们的真实正面计数。我们的模型仍然将大量正面评论错误分类为负面评论(217 个误报)。也就是说,总的来说,它在正确分类真实的正面评价(76%)和真实的负面评价(71%)方面做得相当不错。
model_one = GradientBoostingClassifier(random_state=42,
learning_rate=0.01,
n_estimators=959,
max_depth=2,
min_samples_split=2,
min_samples_leaf=26)sm = SMOTE(sampling_strategy='auto', k_neighbors=5, random_state=42)
X_train_sm, y_train_sm = sm.fit_sample(X_train, y_train)model_one.fit(X_train_sm, y_train_sm)
train_auc = cross_val_score(model_one, X_train_smote, y_train_smote, cv=10, scoring='roc_auc')
y_pred = model_one.predict(X_test)
cnf_matrix = confusion_matrix(y_test, y_pred)
roc_auc = roc_auc_score(y_test, y_pred).round(3)print(classification_report(y_test, y_pred))
print(cnf_matrix)
print('Training CV AUC:', train_auc)
print('Training Avg AUC:', train_auc.mean().round(3))
print('Test Auc:', roc_auc)
优化模型
基础模型
我希望这篇文章对您的数据科学事业有所帮助和启发。一如既往,我欢迎任何和所有的反馈。
用 Python 中的量化金融和机器学*预测短期股票走势
原文:https://towardsdatascience.com/predicting-short-term-stock-movements-with-quantitative-finance-and-machine-learning-in-python-e6e04e3e0337?source=collection_archive---------10-----------------------
QuoteInspector 拍摄的照片
探索机器学*和标准交叉,以 68%的准确率预测未来的短期股票趋势
你有没有听人说过,他们多么希望能回到过去,投资苹果或亚马逊?嗯,他们不能,而且无论他们在 r/WallStreetBets 上花多少时间,他们都不会预测下一个快速致富的投资。事实上,如果你真的听了 r/WallStreetBets,你很可能会在一周内破产,这是我在这篇文章中做出的唯一保证。
然而,让我们看看我们是否可以利用简单的量化金融和机器学*概念,看看我们是否能够以一定的准确度预测股票走势。在本教程中,我们将看看我们是否能够准确预测特定股票的短期走势。
什么是量化金融?
量化金融是利用大型数据集和数学模型来分析金融市场。所以,想象一下,我们有一堆公式,以某种方式让我们更好地理解特定的股票,我们用它来猜测预测的趋势,这就是量化金融。现在,如果我发现了任何突破性的指标、公式或模型,那我就是在撒谎,但是让我们看看我们是否能制造出自己的指标、公式或模型,并且有可能在未来从中赚钱。最终,我们也许能把乔丹·贝尔福特从华尔街之狼变成一种算法。
交易 101
我将使用一些投资和交易领域特有的术语,所以如果你有任何不确定性,请不要犹豫去查找术语。我不是金融专家,所以我会谨慎使用它们。
这里有一些你应该知道的术语:
指标——一种表示股票价格趋势的统计数据
S&P 500——500 家最大上市公司的加权指数
短期运动——股票的 30 天趋势
移动平均线——一段时间内收盘股票价格的平均值
收集数据
所有好的数据科学项目都依赖于输入数据的质量。谢天谢地,由于股票交易的性质,我们可以使用 pandas-datareader (一个内置网页抓取功能的 pandas 扩展)和令人惊讶的不朽工具 Yahoo!金融。
import pandas_datareader as pdr
import datetime
# We can choose any date up to that stock’s IPO
start = datetime.datetime(2014, 1, 1)
# Up to most recent data
end = datetime.date.today()
# We’ll look at F which is Ford
stock = ‘F’
pdr.DataReader(stock, ‘yahoo’, start, end)
# This returns a data frame of scraped stock data from yahoo
完成了!任何数据科学应用程序中最简单也是最重要的部分,只用几行简单的代码就完成了。我们可以进一步扩展到这一点,只使用股票代码从任何股票中收集数据。例如,在我们的应用程序中,我们收集了所有标准普尔股票的数据。
简单分析
在定量金融中,最简单的趋势指标是一个交叉点。交叉是指短均线和长均线交叉。在此分析中,我们将利用简单移动平均线(所有收盘价的权重相等)和指数移动平均线(较新的价格权重较大)。然后,当我们的脚本检测到交叉时,我们将执行交易。
当短均线从长均线上方转到下方时,这是一个交叉,表示卖出(或做空)的机会,反之则表示买入(或做多)的机会。
移动平均线交叉的图形解释
当我们的脚本检测到有利于股票上涨的交叉时,就会触发买入,反之则触发卖出。然后,使用回溯测试分析,我们可以用历史数据测试我们的策略,甚至绘制出我们的算法所做的交易。
我们先算一下所有的均线。对于我们的例子,我们将使用 50 和 200 天窗口的指数移动平均线。
import pandas as pd
# List where we will keep track of long and short average points
indicators = pd.DataFrame(index=data.index)
# 50 day
short_window = 50
# 200 day
long_window = 200
# Exponential moving averages using the closing data
indicators[‘short_avg’] = data[‘Close’].ewm(span=50, adjust=False).mean()
indicators[‘long_avg’] = data[‘Close’].ewm(span=200, adjust=False).mean()
一个所有交叉和指示福特股票方向的图
正如你所看到的,通过这种简单而有效的分析,我们的算法通常可以准确地预测趋势。一种算法可以通过利用期权交易而不是典型的摇摆交易来进一步利用这些摇摆,在典型的摇摆交易中,唯一的机会是买入和卖出。交叉是交易者最简单也是最常用的技术指标之一,现在在算法交易的帮助下,你也可以。
要了解更多信息,请查看 QuantStart ,他们有一些关于 Python 的好的免费文章。
机器学*
如果我们想利用我们的数据做出更好的预测呢?好吧,通过机器学*的魅力,我们可以创建一个模型,给我们一个短期价格预测,希望它有点准确。
我们将像以前一样开始收集数据,但是,这一次我们将需要更多的数据。对于我们的模型,我们使用与之前相同的 API 从所有标准普尔 500 股票中收集了超过 30 年的股票数据,但是我们需要做更多的数据处理。
首先,我们需要一个目标变量,它可以是分类的,也可以是数字的。该项目利用了与总体标准普尔 500 相比的相对百分比变化。这很重要,因为如果标准普尔 500 指数也上涨了 10%,一只股票在 30 天内上涨 10%并不重要。例如,如果苹果股价上涨 8%,S & P 500 下跌 2%,则short_result
(我们的目标变量)将为 10%,稍后归类为强烈买入。
# Getting the S&P 500 relative price difference.
SP = pdr.DataReader(‘SPY’, ‘yahoo’, start_time, end_time)
SP[‘sp_percent_change’] = SP[‘Adj Close’].pct_change(periods=1).astype(float)
data = data.merge(SP[‘sp_percent_change’], left_index=True, right_index=True)
data[‘percent_change’] = data[‘Adj Close’].pct_change(periods=1).astype(float)
# Daily percent change as compared to the S&P 500
data[‘relative_change’] = data[‘percent_change’] — data[‘sp_percent_change’]
现在我们有了一个包含所有训练数据的基本数据框架,我们可能需要添加更多的指标。这是因为我们的 API,以及我们的目标变量,为我们的模型提供了每个实体只有有限数量的特征,因此对于预测趋势是无效的。像这样的机器学*模型需要一段时间的数据。因此,我们将不得不利用这些趋势和一些其他定量财务指标来添加更多的功能。
谢天谢地,像往常一样,有一个库为我们做这些。我们利用了 FinTA(金融技术分析),它能够利用我们已经拥有的所有数据计算出 76 个交易指标。理解每个模型的细节并不是完全必要的,但是可以帮助最大化模型的准确性。在我们的模型中,我们使用了几种不同的移动平均线和力量指数,因为这些指标是专家们最常用来衡量市场的短期波动。
为了实现,我们简单地使用 python 的 eval 函数,因为它最容易快速实现所有选择的指示器方法,并将它们作为特性添加到我们的数据集。
from finta import TA
# Here are all indicators we are using
indicators = [‘SMA’, ‘SMM’, ‘SSMA’, ‘EMA’, ‘DEMA’, ‘TEMA’, ‘TRIMA’, ‘TRIX’, ‘VAMA’, ‘ER’, ‘KAMA’, ‘ZLEMA’, ‘WMA’, ‘HMA’, ‘EVWMA’, ‘VWAP’, ‘SMMA’, ‘MACD’, ‘PPO’, ‘VW_MACD’, ‘EV_MACD’, ‘MOM’, ‘ROC’, ‘RSI’, ‘IFT_RSI’]
df = None
# Using python’s eval function to create a method from a string instead of having every method defined
df = eval(‘TA.’ + indicator + ‘(data)’)
# Some method return series, so we can check to convert here
if not isinstance(df, pd.DataFrame):
df = df.to_frame()
# Appropriate labels on each column
df = df.add_prefix(indicator + ‘_’)
# Mege data frames based on the date
data = data.merge(df, left_index=True, right_index=True)
你可能会问自己“这些特性不会产生不必要的噪音吗”,你可能是对的;然而,我们可以用几种方法来解决这个问题。我们可以收集更多的数据,我们已经这样做了,和/或我们可以利用交叉验证,它利用我们数据的重采样来更好地概括我们模型的预测。
制作模型
现在这里是我们想要如何完成预测的岔路口。我们可以手工制作模型的其余部分;优化我们自己的超参数(这只是控制学*过程的参数)标准化特征,并利用不同的 ML 技术,或者我们可以为我们处理这些。然而,如果你是 ML 的新手,我强烈建议遵循我们的 代码 并学*不同的技术,但是如果你对更大的自动化优化感兴趣,你绝对应该查看一下 亚马逊 Web 服务 SageMaker ,尤其是如果你有一些 AWS 学分的话。
创建 SageMaker 实验、模型和笔记本的过程
SageMaker 为您完成了构建、培训和部署 ML 模型的所有繁重工作,并且非常易于使用。他们有一些很棒的教程,设置自动驾驶实验只需简单的点击几下。一旦完成,您就可以选择最佳模型并部署它。
借助 AWS 部署 SageMaker 模型流程
不管你是使用基于回归的模型还是分类模型,买卖股票的核心问题是分类问题。然而,从回归模型开始并为是否买入或卖出设置上限/下限是有效的。在我们的模型中,我们使用标签强烈买入和强烈卖出与我们的目标变量≥10 和≤-10 的预测评级相关联。买入和卖出分类分别与一个评级[5,10]和[-5,-10]相关联,持有被赋值为(-5,5)。值得注意的是,所有股票的表现要么比标准普尔 500 指数好,要么比标准普尔 500 指数差。预测评级的幅度越大,我们对股票走向的信心就越大。例如,两只股票可能被列为强烈买入,但我们可以对评级更高的那只更有信心。
分析
为了分析我们模型的有效性,我们可以用未经测试的数据来验证我们的模型。我们可以创建的一个指标是预测区间(类似于置信区间),它将告诉我们预测的真实范围,并具有一定的可信度。我们可以使用均方根误差,它对我们来说是 8.91,因此 80%的预测区间将是等于predicted rating ± 11.40
的predicted rating ± 8.91*1.28
。这意味着我们有 80%的信心认为股票的实际相对表现将在我们预测的 11.40 以内。
需要注意的是,我们的区间利用了均方差,该均方差没有考虑超出上限或下限区间的预期。例如,预测值为 10,实际值为 30 的short_result
与-10 的short_result
相同,即使第二个结果没有那么幸运,误差的平方也是相同的。然而,如果我们独立地分析每个标签,我们可以创建更具体的预测区间。
显示由我们的模型预测的每个标签的预测间隔的图表
我们还可以创建混淆矩阵,使我们能够可视化每个结果的预测模型的统计成功。通过分解预测买入或卖出的可能结果(我们忽略了持有预测,因为它的高度不确定性),我们可以明确地可视化我们的正确率。例如,在“预测卖出”和“实际卖出”单元格中具有最高值的混淆矩阵意味着模型预测建议的卖出结果比买入结果更准确。
以下是用每只标准普尔 500 股票代表的未经测试的数据验证我们的模型的结果:
- 使用强烈买入/卖出分类预测正确趋势的准确率为 67.6%
- 使用任何买入/卖出分类预测正确趋势的准确率为 55.8%
强买/强卖混淆矩阵
购买/销售混淆矩阵
最后的想法
机器学*是一种非常强大的技术,可以利用历史数据进行预测,股票市场就是这种技术的一个很好的应用。然而,需要注意的是,股票市场通常是非常不可预测的,技术分析应该总是在基本面分析之后,我有义务说,这些都不应该作为财务建议。
恭喜你。如果你跟着做,你的模型现在可以和其他先前发表的模型相媲美,它们也预测短期股票方向。我们取得了类似的成功,因为我们利用了大量的可用数据和几种类型的指标。这正好说明,在数据科学领域,数量绝对驱动质量。
点击这里查看完整的项目回购和我个人网站上该模型预测的每日反馈:
[## 马修·斯坦宁格
软件工程师-学生
mathewsteininger.com](https://mathewsteininger.com)
使用宏观社会文化变量预测新加坡自杀率
原文:https://towardsdatascience.com/predicting-singapore-suicide-rates-using-macro-sociocultural-variables-13f9e63ece86?source=collection_archive---------54-----------------------
Movember 已经到来,带来了…嗯,只是你典型的潮湿和湿润的新加坡天气(不是人们在北半球所期望的美丽的秋叶)。由于我是一名亚洲男性,因此没有机会留胡子,我决定以自己的方式做出贡献,调查自杀率(包括男性和女性),并试图找出是否有任何方法可以通过观察宏观社会因素来预测自杀率。
如图: 非我 在 Movemeber(图片来自 Unsplash)
关于这一点已经有了很多预先存在的研究(例如,参见此处的和此处的),得出的主要结论之一是宏观经济不稳定与“精神疾病和自杀的加剧”之间的关系。然而,我想超越经济指标,看看随机的、可能不相关的变量,看看是否有任何“盒子外”的因素,我们可以用来预测自杀率(并据此采取行动)。
TL;博士;医生
- 糟糕的模型:我尝试对数据应用随机森林,然后应用线性回归模型。然而,两者都被证明具有极低的 R 值,表明预测能力差(当在验证集上测试时)。
- 经验教训:
答:数据为王:无论您使用哪种模型,您使用的数据都是关键。俗话说,垃圾进,垃圾出。尽管我不愿意承认,但我确实没有足够的数据。我从 SingStat 下载的大部分数据集只能追溯到 1990 年。数据太少,无法对其进行任何有意义的工作。b .因变量的性质:自杀作为心理健康的一个功能,传统上很难管理,更不用说预测了。认为我可以使用宏观变量以某种方式预测自杀率是一个好主意,但可能是天真的想法。 - 提高意识是关键:归根结底,也许我们对付这种致命的社会趋势的最好工具就是意识和同情。消除自杀意念的污名,给人们提供接受帮助的空间,是解决这一问题的关键。作为个人,我们可以用正确的知识和技能来武装自己,为可能遭受精神痛苦的朋友和家人提供帮助。这是一个很好的网站,上面有关于我们如何发挥作用的关键信息。
收集数据
想要做一个新加坡特有的探索,我求助于两个新加坡统计资料库: SingStat 和【Data.gov】T2。这些网站上的数据集真的非常广泛,涵盖了各种各样的统计数据。我从这些网站下载了一大堆随机统计数据,把它们编译成一个主 csv 文件。
虽然自杀率的统计一直追溯到 1968 年,但大多数其他关键统计数据只追溯到 1990 年。我很失望地发现这一点,因为我一直认为新加坡,在所有国家中,将有良好的,可靠的历史统计数据(考虑到我们作为一个国家相对年轻)。尽管如此,我还是利用我所拥有的资料,将我的数据集限制在 1990 年至 2019 年。这后来证明对我不利。
从网上大量可用的数据集中,我选择了一些随机的、不相关的数据集。我想包括更多的变量(随机的东西,比如公共游泳池的游客数量),但是大多数只有 2005 年的数据(有些只有 2010 年的数据!).我还想包括一些重要的消费者消费变量。在其他研究中,酒精使用(通过消费和与酒精相关的犯罪来衡量)是重要因素。然而,犯罪统计从 2011 年才开始,消费统计每 5 年才进行一次。不是特别有用。
然而,我研究了我能找到的数据,最终得到了 14 个不同的变量:失业率、雨天、日照时间、结婚率、视觉艺术展览数量、手机订阅数量、离婚率、图书馆图书借阅数量、理工学生支出、大学生支出、车辆总数、报纸订阅数量、交通事故数量和电力消耗率。
要是我有更多的变量就好了…唉(图片来自 Unsplash)
我认为这是一个相当广泛的列表,并很兴奋地在模型中运行它,看看我们能找到什么。谢天谢地,下载的数据非常干净,在 Excel 中做了一点“预处理”,我们就可以开始了。
数据窥视
清理完数据后,我将它导入 Python,绘制出这些年的自杀率以及相关图,只是为了快速了解数据。
看看自杀率的图表,老实说,看起来并不乐观。这些年似乎没有真正的趋势(上升或下降),虽然在关键时刻(如 2007 年至 2008 年金融危机)似乎有峰值,但也不是特别突出。
看着热图,老实说,它看起来并不乐观。从最后一行来看,没有一个变量与自杀率有特别强的相关性(正或负)。即使对于失业率(在其他论文中显示有显著的正相关性),似乎也没有特别强的相关性。
随机森林回归量
数据的概述并没有吓住我(或者我本应该被吓住),我继续实现了一个随机森林模型,试图理解这些数据。使用sklearn
,我将数据分成训练集和测试集,然后实例化 RFG。
(注:我知道关于为 RFs 分割数据集有不同的思想流派。有些人认为,由于装袋,没有必要为射频验证设置。然而,也有其他人认为,这可以与 OOB 分数进行比较,以获得更好的评估。后来,我还需要为我的多元线性回归模型建立一个测试和训练集,因此需要拆分)
拟合训练数据集,然后我比较了模型的 R 分数。R 的重要性已经在前面讨论过了,但本质上它代表了自变量解释的因变量方差的比例。或者用外行人的话来说,它代表了多少结果可以用自变量来解释。
最终产品是一场灾难。虽然训练 R 是相当可观的 0.80 (80%的自杀率可以通过输入来解释),但公开得分是负,测试集得分 0.36 与 OOB 得分相差甚远。
射频模型通常有很高的 R 值,所以 0.80 的分数不值得一提。虽然我最初打算使用sklearn RandomizedSearchCV
对模型执行超参数调整,但模型的初始评估已经很差,我认为任何调整都没有意义。 N (数据点数)简直太低了。正如 Will Koehrsen 在他关于改进 RF 模型的文章中所写的,第一步是收集更多的数据(在这种情况下,我很遗憾不能)。
出于好奇,我想看看特征的重要性(例如,哪些特征对预测目标最有用)。我使用了 Eryk Lewinson 的代码来创建特性重要性图,并对其进行了调整以适应数据。
为了证明这个模型有多不准确,政府在理工学院的支出是最重要的特征。其次是每年视觉艺术展览的数量。虽然第二个因素排在第二位,但很难看出理工学院的支出是预测自杀率的最重要变量。失业率(通常是一个很强的预测指标)是第七个最重要的因素。这种模式显然是相当破碎的。
多元线性回归
此时,我已经意识到我缺乏数据是一个巨大的问题。然而,由于我已经在使用 Python 了,所以我决定还是结束探索并加入 LR 模型吧。
从结果中可以看出,调整后的 R 平方是负的(也就是说,这个模型不能预测自杀率的任何变化)。因此,这是一个基本上无用的模型。
我感觉像这个气球(图片来自 Unsplash)
结论
- 数据为王:无论你使用什么模型,你使用的数据都是关键。俗话说,垃圾进,垃圾出。尽管我不愿意承认,但我确实没有足够的数据。我从 SingStat 下载的大部分数据集只能追溯到 1990 年。数据集太小,无法对其执行任何有意义的工作。这篇文章是一个关于改进 ML 模型的资源。它建议的第一件事是获取更多的数据来训练你的模型。在这种情况下,由于我在寻找新加坡相关统计数据方面的限制,不可能获得更多的数据。
- 因变量的性质:自杀作为心理健康的一个功能,传统上很难管理,更不用说预测了。认为我可以使用宏观变量以某种方式预测自杀率是一个好主意,但可能是天真的想法。也有其他研究试图使用微观变量(例如观察 twits 来检测自杀意念)。虽然他们确实发现了“算法 SI 分数与全县自杀死亡率的显著关联”,但这是否有助于预测自杀倾向还有待观察。
- 提高意识是关键:归根结底,也许我们对付这种致命的社会趋势的最好工具就是意识和同情。消除自杀意念的污名,给人们提供接受帮助的空间,是解决这一问题的关键。作为个人,我们可以用正确的知识和技能来武装自己,为可能遭受精神痛苦的朋友和家人提供帮助。这个是一个很好的网站,上面有关于我们如何发挥作用的关键信息。
原载于https://Zach lim 98 . github . io/me/2020-11/自杀率预测 。
预测垃圾邮件
原文:https://towardsdatascience.com/predicting-spam-messages-17b3ca6699f0?source=collection_archive---------42-----------------------
使用机器学*算法预测垃圾邮件
Jason Leung 在 Unsplash 上拍摄的照片
在本文中,我尝试预测垃圾邮件。你可以在文末提供的我的 Github 账号上找到所有的 python 代码。
如今,当我们听到“垃圾邮件”这个词时,首先想到的是垃圾邮件。然而,八十年前并非如此。spam 一词是由一个叫 Ken Daigneau 的人在 1937 年创造的,用来命名 Hormel Foods 的新肉制品。肯为新项目命名赢得了 100 美元的奖金。有些人认为 spam 代表五香火腿,还有许多人认为它代表“特别加工的美国肉类”
垃圾品牌。汉尼斯·约翰逊在 Unsplash 上拍摄的照片
“垃圾邮件”这个词在 20 世纪 70 年代开始被认为是“令人讨厌”的东西,在巨蟒剧团的飞行马戏表演之后,当在一个“”场景中,维京人开始唱“垃圾邮件之歌”,并一直重复“垃圾邮件”这个词。后来,在 20 世纪 80 年代和 90 年代,人们使用“垃圾邮件”这个词的重复,有时甚至是《维京人之歌》的整首歌来发送垃圾邮件聊天。因此,人们开始将“垃圾邮件”这个词与令人讨厌的垃圾信息联系起来。
本文的目标是使用不同的机器学*技术来预测邮件是否是垃圾邮件。我使用了加州大学欧文分校提供的 数据集 ,其中包含大约 5500 条短信。下面是文章的结构:
- 探索性数据分析
- 文本预处理和特征工程
- 建模
- 结论
探索性数据分析
首先,我们来做一些探索性的数据分析。通过检查数据集的形状,我们可以看到它有 5572 个观察值和两列。然而,在 5,572 个观察值中,只有 5,169 个唯一值,这意味着大约有 450 个重复行。我还检查了缺失值,但是发现没有一列有任何缺失值。下面是前五行和数据集的形状:
初始数据集
删除重复项后,数据集有 5,169 个观察值,其中 4,516 个是垃圾邮件,653 个是垃圾邮件。相对大量的 ham 消息意味着如果我把所有的消息都当作 ham,我会得到 87%左右的准确率。有些人以朴素贝叶斯(一个非常简单的模型)的精度为基准,但我会以整体精度为基准,并会尝试以更高的精度做出能更好预测的模型。如果你想了解更多关于朴素贝叶斯的知识,可以看看这个 视频 。
文本预处理和特征工程
在开始建模部分之前,我需要处理数据,并使其适合建模。在这一部分,我需要将电子邮件、网址、货币符号、电话号码和数字转换成特定的单词,并删除所有的标点符号。更准确地说,想象一条垃圾消息,它具有下面的消息“使用 www.wearespam.com 的链接获得 100 万美元”,以及另一条包含“使用 www.wearealsosmap.com的链接获得 50 万美元”表述的垃圾消息。在这种情况下,我们不希望算法考虑两个不同的链接或奖金数额,而是用特定的词来定义它们。转换文本后,这两个句子看起来像“使用 webaddr 链接获取货币号码”除了改变文本中的一些单词,我还对词典进行了规范化,并从文本中删除了所有的停用词。为了更加精确,我现在将提供每个部分的更多细节。
删除“不必要的”单词——正如我已经解释过的,我们不需要在文本中有不同的唯一数字。尽管如此,我们需要知道特定的消息是否包含电子邮件地址、电话号码等。您可以使用 Python 的正则表达式包来识别文本中的电子邮件和电话号码。在下面的 网站 找到更多关于正则表达式的信息。
规范词汇——我执行了词汇规范化的词汇化技术。在这个过程中,我们把这个词带到它的“基础”层面。例如,单词“go”、“goes”和“going”有相同的基础,但用法不同。词汇规范化的另一种方法是词干化,但是词汇化比词干化有一些优势。例如,词汇化通过使用词汇将单词转换为其基础,而词干化对单词起作用,而不考虑其内容。因此,词汇化可以导致单词的更好的转换,而不改变意思。要了解更多关于词汇化和词干化的信息,请点击这里的。**
清洗完文字,我需要看到最常见的字。下图显示了文本中最常见的单词是“数字”那是因为我把所有的数字都转换成了一个单词,我们的文本包含了太多不同的数字。
词的出现
最后,在删除了停用词、不必要的词和规范化了词典之后,是时候对文本进行标记了。标记化是将每个单词或一系列单词视为特定单位的过程。例如,在对“我喜欢苹果”句子进行单字标记化之后,我们得到三个单独的标记:[我]、[喜欢]和[苹果]。我使用了 unigram 和 bigram 标记化,因为包含两个单词的表达式也是分析所必需的。例如,在短语“早上好”中,这两个词放在一起,而不是分开,对于捕捉表达的确切含义是必不可少的。我没有用三个或更多的单词来标记,不是为了增加变量的数量和最小化计算能力的使用。在对文本进行标记后,我制作了一个单词包来开始处理数据。通过制作单词包,我们为单词提供了数值。单词包计算每个单词在句子中的出现次数。这是一个简单的技术,易于使用。然而,只用弓也有它的缺点。例如,BoW 衡量文本中每个词的出现次数,出现频率越高的词可以获得更高的重要性。例如,让我们来看下面两个句子:“轰炸、弹幕、幕火、地雷、毒气、坦克、机枪、手榴弹——单词、单词、单词,但它们包含了世界的恐怖”(埃里希·玛利亚·雷马克“西线一切平静”)和“这是一张桌子。”在制作了单词包之后,我们看到单词“words”比“table”更常见,这意味着“words”将变得更加重要。为了解决这个问题,我使用了 TF-IDF(术语频率-逆文档频率)权重。权重提供了每个标记的重要性,但是它也考虑了标记在语料库中的频率。想了解更多关于 BoW 和 TF-IDF 的信息,可以查看 这里 。
在对数据进行标记化并计算 TF-IDF 权重之后,我得到了最终的数据集,它由 5169 行和 37891 列组成。太多了!!!
造型
因为我已经准备好了数据,现在是制作模型的时候了。在我的分析中,我使用了四种不同的模型:SVM、随机森林、逻辑回归和 XGBoost。我将数据集分成两部分,用一部分训练模型,另一部分测试它们的性能。为了提高每个模型的性能,我尝试了不同的参数,并使用贝叶斯优化进行超参数调整。我采用了不同范围的参数,并对训练数据集进行交叉验证,以找到参数的最佳组合。后来,我在测试数据集上测试了这些模型,并使用准确性和 AUC 分数来比较它们的性能。尽管我使用贝叶斯优化进行超参数调优,但我想快速浏览一下广泛使用的替代方法。贝叶斯优化的可能替代品是网格搜索和随机搜索,但我使用贝叶斯优化,因为其他两个有一些缺点。我将简要解释每种方法的工作原理以及它们可能的缺点。
- 网格搜索方法-测量所有可能的参数组合的结果。例如,如果我们想在 0.01 或 0.1 的学*率和 4 或 5 的最大深度之间做出决定,那么网格搜索将建立四个不同的模型(尝试所有可能的组合),并采用模型表现最佳的参数。网格搜索方法的缺点是,在许多参数的情况下,比较所有可能的组合将花费太多的计算能力。
- 随机搜索方法-在提供的参数中,该方法采用参数的随机组合,并用它们来建立模型。对于这种方法,我们需要指定要进行多少种组合。随机搜索方法的主要缺点是它随机选择参数,并且人们永远不能确定该方法将采用参数的最佳组合。
- 贝叶斯优化方法—使用贝叶斯定理指导参数搜索。因此,它走向目标函数增加/减少的方向(取决于目标)。
下面是 XGBoost 的超参数调整代码:
XGBoost 的超参数调整
通过了解所有模型的最佳参数并制作模型,我发现支持向量机(SVM)的预测效果最好。它具有 98%的准确性和 0.92 的 AUC 分数。XGBoost 和 Random Forest 的性能没有显著差异,但这些模型的准确性和 AUC 较低。一个相对简单的模型,逻辑回归,并不能很好地进行预测,并且准确性和 AUC 评分最低。另外,通过查看混淆矩阵,我们可以看到,当算法预测该消息是垃圾邮件时,大多数错误都与误报有关,但实际上,它是 ham。以下是 SVM 的结果汇总:
SVM 绩效总结
最后我对所有模型做了 ROC 曲线,直观的看哪一个表现最好。下面你可以找到 ROC 图:
受试者工作特征曲线
您可以再次看到 SVM(红线)的表现最好,因为它的 ROC 得分最高。
总的来说,在本文中,我试图了解哪种模型有助于更好地预测垃圾邮件。首先,我清理了数据,对文本进行了必要的转换,并将 word 转换为数值,以便能够制作模型。我使用了四个模型,并为 SVM 获得了最高的准确性和 AUC 分数。该模型的使用可以帮助许多企业更好地了解哪些消息是垃圾邮件。然而,我相信可以通过使用更复杂的模型如神经网络来进一步改进预测。
你可以在我的 github 账号上找到本文使用的 Python 代码。
预测 Spotify 曲目跳过
原文:https://towardsdatascience.com/predicting-spotify-track-skips-49cf4a48b2a5?source=collection_archive---------23-----------------------
致力于 Spotify 顺序跳过预测挑战
(截图由 Spotify 提供)
介绍
作为 Metis 数据科学训练营的第三个项目,我做了一个稍微简化的版本的 Spotify 顺序跳过预测挑战【1】。
我相信你知道,Spotify 是一家流媒体服务公司,其商业模式的核心是向用户提供歌曲推荐,以保持他们使用他们的应用程序。
Spotify 拥有超过1.9 亿活跃用户,与超过4000 万首歌曲互动。
挑战的目标是预测用户在收听过程中跳过任何一首歌曲的可能性。
方法学
数据
Spotify 为比赛提供了两套主要信息。一个表有关于用户收听会话的信息。例如:
- 会话 ID
- 在会话中的位置
- 轨道 ID
- 如果轨道被跳过或没有被跳过
- 其他会话元数据
请注意,用户会话的长度都在 10 到 20 首曲目之间,并且不包括任何关于用户的可识别信息。
第二个表包含关于磁道的元数据(对应于会话表中的track_id
功能),例如:
- 轨道持续时间
- 追踪在美国的受欢迎程度
- 发布年份
以及一些额外的功能,由 Spotify 生成,用于描述歌曲,例如:
- 声音度
- 跳动力量力量
- 弹性
- 可跳舞性
该数据集还包括每首曲目的一组 8 个“声音矢量”,它们是 Spotify 为每首曲目生成的潜在编码。
出于许可的原因,Spotify 将曲目信息匿名化,因此没有任何关于曲目名称、艺术家、专辑或流派的数据。
所提供的数据集中的目标(无论是否跳过了音轨)与大约 51.7%被跳过的音轨保持平衡。所以没有必要为了训练而调整班级平衡。
有多余的数据,所以我使用了会话表中大约 100k 行的子集和跟踪表中相应的行,我将它们加载到托管在 AWS EC2 实例上的 Postgres 数据库中。数据库模式如下所示:
Spotify 跳过数据的模式
为了了解单个会话可能是什么样子,下图显示了单个用户会话的曲线图,因为它与其中一个功能相关,即“音轨响度”,Spotify 对歌曲特征的描述,而不是传统意义上的“音量”,其中颜色指示跳过和未跳过的音轨。
单个会话的音轨跳过与音轨响度
虽然它本身没有意义,但它说明了如何根据歌曲属性绘制每个会话。在这个例子中,随着响度值降低,用户只听了前 11 个音轨中的两个,然后听了所有剩余的 9 个音轨。
此外,为了更好地了解整体发行曲目属性,我绘制了一小部分功能的分布,并突出显示了三首不同歌曲在分布中的位置(使用来自 Spotify API 的数据)。这三首来自三个不同流派的歌曲是:
- 威利·尼尔森的拦路强盗(国家)
- 武堂帮的护丫脖子(嘻哈/R & B)
- 约翰·科尔特兰的《蓝色世界》(爵士乐)
以下是属性“能量”、“响度”、“跳舞度”和“声音度”的属性分布图:
标绘 3 首歌曲作为参考的音轨特征子集的分布
特征工程
这些数据本质上是有序的。该模型对任何给定歌曲的跳过预测将基于在用户收听会话中较早跳过的歌曲。因此,为了让我的模型考虑到这一点,我添加了一组特征来表示以前音轨的音频特征以及这些音轨是否被跳过。
旁注:我还尝试了一种替代方法,在这种方法中,我添加了两组特征,分别对应于被跳过的先前轨道和未被跳过的轨道的平均轨道特征信息,但是发现计算时间更长,添加了两倍的特征,并且没有提高模型性能。
型号选择
根据竞赛指南,目标衡量标准是准确性。
我开始用逻辑回归模型作为基线,但是发现它的准确性很差。因此,从那以后,我转向了基于树的模型,这种模型不太容易解释,但能够自动处理复杂的功能交互。
结果
比较逻辑回归和 LightGBM 模型性能的 ROC 曲线
我最好的模型的最终测试精度是 0.73 ,使用的是 LightGBM 的LGBMClassifier
模型,考虑到问题,这已经相当不错了,但还有改进的空间。
在训练模型之后,我分析了误差,寻找改进模型的地方,但是在残差中没有发现任何明确的趋势。
结论
最终 LightGBM 模型的相对特征重要性排序
该图显示了最终模型的前 10 个功能的相对重要性排名。该模型将曲目流行度列为最重要的特征,其次是曲目持续时间,然后是上一首曲目的流行度。这个排名似乎总的来说是有意义的,并没有发现什么太令人惊讶的事情,除了可能的事实是曲目流行度的排名远远高于下一个最重要的功能。然而,有趣的是,这个图(以及在下面的附录中可以看到的完整排名的图)显示,在少数情况下,该模型似乎正在比较当前曲目和先前曲目的特征。一些例子包括流行度、持续时间和响度。
同样,该模型的性能是合理的,与精确度为 0.51 的完全天真的模型(总是预测音轨将被跳过)相比,精确度为 0.73,但仍有很大的改进空间。
未来的工作
展望未来,需要继续努力的几个领域包括:
- 添加无监督学*,根据曲目特征对歌曲进行聚类,并可能生成“伪流派”
- 使用递归神经网络进行预测,这可以更自然地处理序列轨迹信息
- 用来自 Spotify API 的更多数据补充数据集(如流派信息)
- 创建一个 Flask 应用程序,它使用 D3 来可视化模型预测,并允许用户交互式地探索数据集
感谢阅读,我很想听听你的想法!
附录
特征子集描述
- 声音度:音轨有声音的可能性
- 可跳舞性:描述一个曲目适合跳舞的程度
- 能量:轨迹强度的量度
- 价:音轨所传达的“积极”程度
- 语音识别:检测口语单词的存在
全模型特征重要性等级
轨迹"声矢量"相关矩阵
引文
这里有一个挑战网站的链接(这里有更多关于数据集和挑战规则的信息)。
[1] B. Brost,R. Mehrotra 和 T. Jehan,音乐流会话数据集 (2019),2019 年网络会议论文集
使用逻辑回归预测启动性能
原文:https://towardsdatascience.com/predicting-startup-performance-using-logistic-regression-582a1e80b2eb?source=collection_archive---------23-----------------------
通过简单的数据科学分析创业公司的寿命
我第一次接触创业领域是在大学一年级的夏天,直到现在,我也是其中的一员。不幸的是,我遇到的大多数都因为各种原因而关闭了。所以我对创业公司的生存方式产生了兴趣。我能判断一家初创公司是会生存还是会失败吗?尽管创业公司的本质在某种程度上意味着不可预测,但我想看看我能从一些数据中挖掘出什么见解。
摘要
这篇文章的特色是从初创企业数据库angelist.co收集的数据,将 ML 框架化为一个分类问题,即初创企业是否可以提高某个阈值来预测业绩。比较 P 值,卡方,F 值,互信息作为变量选择方法提出和评估。最后,选择的模型找到了最重要的预测因素:规模、成立年份、旧金山、奥斯汀、西雅图和手机游戏。大多数这些都是直观的,因为它们都证实了地理优势和市场竞争力对创业公司的影响。
流程图
以下是我的 jupyter 笔记本从刮痧到建模如果你感兴趣的话:)
1.数据采集
在研究了几个不同的创业数据库后,我选择了 angelist.co 的 T4,因为它的数据相当详细,而且可以免费访问。下面是网站的外观,让你对我们正在处理的数据有一个大致的了解。
天使公司页面
上面的页面显示了大量的初创公司,对于每个初创公司,都会显示以下数据:
- 加入时间(启动加入天使数据库的月份和年份)
- 启动位置
- 创业公司所处的市场(电子商务、医疗保健、B2B、SaaS 等)
- 员工规模(1-10 人、11-50 人、51-200 人等等)
- 当前启动阶段(种子期、首轮融资、…、首次公开募股、已收购)
- 筹集的资金总额
我编写了一个 web scraper 来获取上述数据,从 Angelist 中随机抽取了 4260 个独特的初创公司。下面是我搜集的数据片段。
表 1:抓取的数据
评估指标
我不知道该把这个问题框定为一个回归问题来预测一些美元价值,还是作为“好”和“不好”创业公司之间的分类。如果这是一个分类问题,那么我们需要一些好与不好的衡量标准。TechCrunch 的一项关于一轮融资对下一轮融资影响的研究给了我灵感。
我们在下图中看到,当公司在首轮融资前融资 200 万至 250 万美元时,融资 A 轮的概率最高。因此,融资 2M 美元的种子期公司应该比融资 2M 美元以下的公司有更高的生存机会。因此,我们的种子阶段模型将使用 2M 美元作为阈值来评估哪些公司好。
来源:杰森·罗利,经由 crunchbase
在 0 美元到 200 万到 250 万美元之间,每筹集 50 万美元的首轮融资前融资都会略微增加 A 轮融资的可能性,至少对那些在 2003 年至 2012 年期间筹集了首轮融资前资金的公司来说是如此。在 250 万美元之后,从种子、天使和其他首轮前投资者那里筹集更多资金没有边际效益,至少就公司筹集 B 轮资金的机会而言。
在不同的 A 轮融资中,B 轮融资的概率要低得多。筹资金额对进入下一阶段的影响较小。然而,我们仍然看到接* 1200 万美元的峰值,因此我们将遵循之前相同的逻辑,使用 1200 万美元作为评估初创公司好坏的门槛。
来源:杰森·罗利,via crunchbase
我们发现 B 轮融资的成功率保持相对平稳,与平均水平只有微小的差异。这表明,出于这样或那样的原因,在 B 轮融资之前筹集的资金数量在大多数情况下不会对公司筹集 B 轮融资的能力产生重大影响。
数据后处理
在更正数据类型并清除重复的行/特殊字符后,应用以下处理逻辑来创建一个准备用于训练的表。
- 原始数据列“位置”和“市场”是用于机器学*的一次性编码。
- 创建“年”来表示自时间加入 angelist 以来的年数。
- 创建“size_numeric”是为了将序数数据转换为数字数据(通过选择大小范围的中点)。
- “raised_2mil”和“raised_12mil”是我们试图分别为种子和 A 轮创业公司预测的二元结果变量。
- 通过“种子”和“系列 A”筛选阶段,并为建模准备好两个数据集。
下面是种子期公司数据框架的截图。除了 size_numeric 和 years 之外的所有变量都是二进制 1/0,以表示该创业公司是否符合位置/市场标准。
表 2:生成的数据帧:种子 x
2.初步数据可视化
我们的数据集包含了来自所有不同阶段的总共 4260 家公司。这里有两个有趣的图表,显示了融资最多(最著名)的初创公司以及阶段的分布。
现在,具体来说种子期和首轮融资。让我们看看种子期公司和首轮融资公司在员工规模、地点和市场分布方面有何不同。
公司规模分布
种子期公司的员工往往集中在 1-10 岁和 11-50 岁。A 系列公司的员工往往在 11-50 到 51-200 之间。这是非常直观的,因为当从一个阶段进入另一个阶段时,初创公司的规模通常会变得更大。
创业市场分布
种子和 a 轮之间最热门的市场似乎是一致的。移动商务,b2b 和 Saas 是排行榜的榜首。
启动位置的分布
seed 和 a 系列的地点也有重叠。旧金山、纽约、伦敦、洛杉矶和奥斯汀是这两个阶段的热门地点。
关于影响创业公司生存的因素,这些分布并没有产生太多的洞察力。在下一节中,机器学*被应用于分析上述市场、位置及其对创业公司的影响。
3.建模
如果我们考察输入特征的性质,我们会发现大多数输入特征都是由一键编码生成的二进制特征。我们的输入数据具有很高的维数(大多数是二进制的),因此不太适合基于树的模型。鉴于数据的稀疏分布和低复杂度,我选择使用 logistic 回归 进行建模。
**要建模的两个数据集: seed 和 sseries A,具有不同的“y”(“raised _ 2 mil”和“raised_12mil”)。这将为我们提供比较的洞察力。
特征选择
二进制特征可能非常偏向 0。(例如,一家公司的位置为“伊萨卡”,那么一个名为“伊萨卡”的列中正好有一行的值为 1,而其余的都是 0。)所以某些变量会比其他变量重要得多。在此步骤中,特征选择将用于仅选择重要的特征。
我决定尝试一些不同的特征选择方法,看看它们如何影响结果。也就是说,我将使用 卡方、互信息、ANOVA f 值和 p 值 。
对于 p 值选择,我使用 0.05 的 alpha 执行了一个向后消除,其余的使用来自[sklearn.feature_selection](https://scikit-learn.org/stable/modules/classes.html#module-sklearn.feature_selection)
的内置函数。
简写如下。对训练数据运行逻辑拟合,如果具有最大 p 值的特征超过我期望的显著性水平(意味着 coef 不显著),则我移除该特征并重复该过程,直到剩下的所有特征都具有低于阈值的 p 值。
import statsmodels.api as smdef logiVarSelect(x, y, sig_lvl, columns):
while True:
logi = sm.Logit(y, x).fit(method='bfgs',maxiter=400)
maxP = max(logi.pvalues)
if maxP > sig_lvl:
loc = list(logi.pvalues).index(maxP)
x = np.delete(x, loc, 1)
columns = np.delete(columns, loc)
else:
return columns
p 值向后消除返回不固定数量的变量,在本例中,Seed 为 9,SeriesA 为 6。sci-kit 学*选择使用 SelectKBest 实现,其中 K 设置为 10。通过找到最佳验证集 AUC 性能来挑选该数字。(在下一部分解释)。卡方检验和 F 值检验对种子和系列产生了完全相同的变量,因此它们被合并为一个变量。以下是使用不同流程选择的变量。
一个有趣的观察是,对于 p 值选择方法,种子变量由大小、年份、位置和市场组成。而 A 系列变量不包括市场。对此的一种解释可能是,早期创业公司更依赖市场,随着它们的成长/进入,它们受市场表现/竞争力的影响较小。
模特表演
对于每种特征选择方法,在该组特征上训练逻辑回归,并使用验证组绘制 ROC 曲线。每条 ROC 曲线都有一个指标 AUC(曲线下面积)。该值越倾向于 1,模型对结果的预测就越准确..
在这个步骤中使用交叉验证来产生平滑和圆形的“平均”ROC 曲线。4x 网格中的每条模糊曲线是来自训练/验证集的单个 ROC,粗体曲线代表平均 ROC,灰色阴影区域代表一个标准差。左手边的大图是简单地绘制在一起的平均 ROC。
验证集上种子公司的平均 ROC 曲线
对于种子公司,卡方/F 值选择方法在验证集上表现最佳,AUC 为 0.761。
验证集上系列公司的平均 ROC 曲线
对于 SeriesA 公司,卡方/F 值选择方法在验证集上表现最佳,AUC 为 0.717。
从变量选择的比较来看,卡方/F 值在两个阶段都具有最高的 AUC,现在让我们看看在测试集上的表现。
4.模型评估和讨论
种子阶段模型在测试集上的性能
种子期
对于种子阶段,Chi2/F 选择确实给了我们最好的测试精度 0.764。这意味着我们可以在 76.4%的时间里正确预测提高 2M 的能力。TPR 和 TNR 也是合理的。虽然提高 2M 并不意味着一定成功,但它最有可能提高下一轮。所以它绝对可以帮助我们识别“强大”的创业公司。
让我们再次访问 Chi2/F 选择确定的变量及其相应的系数和 p 值。这将为我们提供关于哪些因素是创业公司生存的强大影响因素的见解。
我们将讨论 p 值小于 0.05 的变量,因为它们在区分好的和坏的创业公司方面具有统计学意义。size_numeric,years,Austin,San Francisco,Seattle,以及 Mobile Games 将在下面详细讨论。
显著预测值及其系数
种子阶段的发现
- “ size_numeric ”有一个 0.0048 的小正系数(正意味着更有可能筹集到 200 万)。简单来说,大公司往往生存得更好。这是有道理的,因为较大的创业公司有更多的脑力,因此具有优势。
- “年”的系数为负,为-0.297,这意味着创业公司成立的时间越长,筹集 200 万美元的可能性就越小。非常直观,如果一个 3 岁的初创公司仍然处于种子阶段,那么这可能意味着它不是一个好公司,很快就会死去。
- “奥斯汀”、“旧金山”、“西雅图”都有 1 左右的正 coeds,西雅图略微领先。这反映了创业公司的“热门”地点,这也是非常直观的。旧金山的硅谷,西雅图的许多科技巨头总部,以及奥斯汀快速发展的科技产业,都使这些地方成为科技创业公司的发源地。
- “手游”是个有意思的,系数-1.298。对于创业公司来说,这似乎是一个糟糕的市场。我和一个风投的朋友讨论过手机游戏市场,我们的解释是 手机游戏市场很难创新,竞争激烈,具体到 。手机游戏本身并不是技术创新。所谓的手机游戏创新是指游戏风格/媒介/角色的知识产权。与解决现实问题的简单粗暴的 Saas 方法相比,这种精品概念对天使投资者来说更难理解。同时,手机游戏是一个竞争非常激烈的市场。很多手机游戏公司被像网易游戏这样的大型国际公司收购。手机游戏的“商业策略”或“卖点”在不同的游戏中是重复的。这种创新的缺乏助长了强大的竞争力。此外,手机游戏是一个非常“特殊”的市场。像“Saas”、“电子商务”或“移动医疗保健”(仅举几个种子阶段的热门市场)这样的市场非常广阔,可以包括非常不同的子市场,但移动游戏真正专注于为 Android 或 IOS 开发游戏。它的特殊性使得它很容易与其他移动游戏创业公司进行隔离和比较,因此使它成为一个具有统计意义的属性。总的来说,这个模型确定的“移动游戏”市场实际上是一个应该避免的投资选择,在 Saas、医疗保健和 b2b 等技术自由的市场中,创新有更多的可能性和理由。
系列 A 阶段
系列舞台模型在测试台上的表演
与种子阶段的模型不同,SeriesA 阶段的模型表现糟糕。TPR 非常低,这意味着它们在预测“好”创业公司方面非常糟糕。造成这种情况的原因可能是样本数据集太小。当种子公司有 1882 个观察值时,我们有 529 个观察值。潜在的下一步是对更多的数据重新运行模型。
最后的话
总的来说,数据的质量肯定是有限的,但我们的种子阶段模型表现良好,精确度为 0.764。成功创业的预测因素不仅仅是市场、位置、规模和成立时间。公司文化和创始人背景等因素在现实生活中可能更具决定性。
然而,我们从种子阶段模型中得到了非常适用于现实生活知识的重要见解。所以,作为一个建议,尽量不要投资手机游戏,把你的钱投在旧金山、西雅图或奥斯汀的创业公司吧!(可能吧!)
退一步说,这个项目基于 Crunchbase 文章的百分比来看一个非常简单的问题。从中得出的见解只是为了我们的单纯解读。在风险投资领域,有太多的神秘、科学和技术是无法通过逻辑回归学*的。
感谢您的阅读!
如果您有任何问题或意见,请随时发起讨论/联系我们!
LinkedIn|xm53@cornell.edu|Github
预测大学教室和足球场的成功
原文:https://towardsdatascience.com/predicting-success-for-college-classrooms-and-football-fields-5f45e20153bf?source=collection_archive---------64-----------------------
每个学生在高等教育机构的旅程都会产生大量数据。使用它来构建支持机构和学生成功的模型。
照片由 MD 杜兰 上 下
帽子、礼服、文凭……还有数据!
每个学生在高等教育机构的旅程都会产生大量数据。招聘、咨询、留人、资助、行政 流程、考核措施,课程工作、体育活动、校友活动均可详细跟踪。
这些数据可以在预测模型中发挥作用,推进机构目标并帮助学生取得成功。除了上面链接的有效用例,这里还有两种更具创新性的方法,研究人员使用机器学*在高等教育的世界中进行预测。当然,尽管存在挑战,但预测分析可以提供对各种高等教育数据的洞察。
KISS:对学生(…和模特)保持简单
随着许多学院和大学现在主要在线教学,学生们正面临着不同寻常的学*挑战。在线学*管理系统(LMS)提供了大量关于学生如何参与课程活动、在线资源和相互交流的数据。但是,哪些数据最能预测哪些学生可能会挣扎,哪些模型提供了最大的效用?
一组研究人员从 Moodle,一个流行的 LMS,收集了四个学期的在线计算机编程入门课程的数据。这些数据包括学生与课程内容的“认知互动”,他们彼此之间的“社会互动”,以及他们与教师的“教学互动”;研究人员认为这些类别可能有不同的预测能力。他们还收集了更多的数据,如学生在 LMS 上的总互动量,并向学生发放了一份关于动机和人口统计的问卷。最后,他们建立了新的功能,包括一个“承诺因子”,一个学生每周总互动量与班上所有学生平均互动量的比率。
照片由 虹膜王 上 下
有了这些有趣的数据,研究人员测试了 13 种不同的数据组合和 6 种不同的预测算法,以了解哪种算法能够最好地识别出有辍学或在第八周失败风险的学生。
令人惊讶的是,他们发现——尽管试图开发新的方法来检查学生的数据——“简单的交互计数可以用来生成预测模型,”尽管其他研究表明这可能还不够复杂。他们预测高风险学生的最佳模型是根据所有学生互动的总计数训练的 AdaBoost 分类器,第二好的模型也使用 AdaBoost,具有相同的计数和“承诺因子”功能。除了这些简单的数据点,即使是学生问卷也不能增强模型。
“我们可以得出这样的结论,一门包含几十种材料的更有条理的课程最适合学生的需求,因为他们可以与课程进行良好的互动,从而取得成功。研究人员写道:“学生互动似乎意味着参与,更多的参与会让学生取得成功。”。
虽然这似乎是显而易见的——建立一个强大的在线课程,学生更有可能成功!—这些结果对那些想自己尝试学*分析和预测的人很有帮助。你不一定要建立一个超级复杂的模型来识别和接触有风险的学生。一种更简单的方法来跟踪学生的在线参与度,并识别那些参与度较低的学生,仍然有助于学生的成功。
照片由 安德鲁·麦克罗伊 上 下
大学体育中的预测分析:成功的推特
机器学*不仅仅是为了大学的学术和行政需要。另一个研究项目“从标签到海斯曼:大学足球招生中的社交媒体和网络”,展示了如何将逻辑回归用于足球学生运动员的推特帖子,以 87%的准确率预测他们是否会在这些推特帖子发布后的一个月内获得奖学金。
在正确预测报价方面,逻辑回归优于其他算法,包括随机森林和 SVM 。研究人员手工标注了 7000 多条推文,但自动自然语言处理,如情感分析,也可能是有用的。
虽然为一个团队选择一名运动员似乎是一个复杂的决定,有许多无形的因素,但有趣的是,Twitter 内容本身被证明是有预测性的。重要的变量包括运动员是否发布了“自我推销”的推文,“迎合”的推文称赞特定的教练和团队,以及他们参加的营地或拜访过他们的教练等信息。Bigsby 还创建了另一个逻辑回归模型,可以预测运动员是否会加入或“退出”某些团队。
除了体育和高等教育,这项研究还为如何将这种预测方法创造性地用于各种工作的招聘提供了思路。
照片由 罗马法师 上 下
潜在问题
虽然这些例子使用的数据很容易从 LMSes 或公共社交媒体获得,但高等教育数据在实践中可能很难收集和分析。机构孤岛、分散的数据以及对学生隐私和偏见的担忧都带来了挑战。
来自 Hechinger 报告的这篇最*的文章特别涵盖了使用预测分析法对学生成绩的一些潜在的意想不到的后果。一个模型(和一个解释它的导师)可以引导一个学生远离一个被预测对那个学生来说过于雄心勃勃的首选专业……但是那个学生也许能够迎接挑战。模型和导师的指导是否符合学生的最大利益?这不是一个容易回答的问题。关于隐私和系统偏见的问题也发挥了作用。
诚然,这里存在复杂的问题。不过,只要小心,预测分析有很多方法可以用来帮助学生和其他人打造高质量的高等教育体验。
有关如何使用预测分析的更多灵感,请观看下面来自 Educause 的视频,其中一些机构领导人解释了预测分析在其机构中的作用。你也可以看看这本免费的电子书,它展示了七所不同的学校在各自机构的不同领域对分析方法的使用。
原载于 Alteryx 社区 并精选于 Alteryx 数据科学门户 。
预测泰坦尼克号的幸存者
原文:https://towardsdatascience.com/predicting-survivors-of-titanic-e7280822b00b?source=collection_archive---------35-----------------------
谁会在海难中幸存?我们可以用机器学*来回答这样的问题。
斯图亚特(1843-1923)/公共领域
1912 年 4 月 15 日凌晨,由白星航运公司运营的英国客轮泰坦尼克号在从南安普敦到纽约的处女航中撞上冰山后沉没在北大西洋。据估计,船上 2224 名乘客和船员中,超过 1500 人死亡,这使得沉船成为现代史上最致命的和平时期商业海上灾难之一。
我们现在想要的是创建一个机器学*模型,能够预测谁将在泰坦尼克号的沉船中幸存。为此,我们将使用这个来自 Kaggle 的数据集——这个任务也有一个 Kaggle 竞赛,这是一个开始 Kaggle 竞赛的好地方。该数据集包含关于乘客的以下信息:
探索性分析
现在,在对这个数据集进行任何机器学*之前,做一些探索性分析并看看我们的数据看起来如何是一个好的做法。我们也想一路准备/打扫。
import numpy as np
import pandas as pddf = pd.read_csv('train.csv')
df
df.describe()
我们在数据中看到了什么?我们看到 PassengerId 列有一个与每个乘客相关联的唯一编号。机器学*算法可以很容易地使用这个字段来记住每个乘客的结果,而没有概括的能力。此外,还有一个名字变量,我个人认为它不能以任何方式决定一个人是否幸存。所以,我们将删除这两个变量。
del df['PassengerId']
del df['Name']
现在,让我们看看我们是否有丢失的值,以及它们有多少。
df.isnull().sum()
在 891 个样本中,687 个样本的座舱变量为空值。此变量缺少太多值,无法使用它。我们会删除它。
del df['Cabin']
我们不想删除其他两列,因为它们很少缺少值,我们将增加它们。
对于装载的变量,由于它是一个分类变量,我们将查看每个类别的计数,并用拥有最多项目的类别替换 2 个空值。
df['Embarked'].value_counts()
oaked 最常见的值是“S ”,因此我们将使用它来替换空值。
df['Embarked'].loc[pd.isnull(df['Embarked'])] = 'S'
对于年龄,我们将用平均年龄替换缺失值。
mean_age_train = np.mean(df['Age'].loc[pd.isnull(df['Age']) == False].values)
df['Age'].loc[pd.isnull(df['Age'])] = mean_age_train
请注意,我们应该存储我们从训练数据中了解到的一切,例如开始上课的频率或年龄的平均值,因为我们将在进行预测时使用这些信息,以防测试数据中也有缺失值。我们还将计算并存储费用平均值,以备测试数据需要。
mean_fare_train = np.mean(df['Fare'].loc[pd.isnull(df['Fare']) == False].values)
我们去掉了空值,现在让我们看看接下来会发生什么。
顺序编码
机器学*算法对文本不起作用(至少不能直接起作用),我们需要用数字转换所有字符串。我们将使用序数编码进行这种转换。序号编码是一种通过给每个类别分配一个数字来将分类变量转换为数字的方法。我们将使用 Scikit-Learn 的OrdinalEncoder
对变量性别、票、上船进行这种转换。
在此之前,我们将备份当前的数据格式以备将来使用。
df_bkp = df.copy()
from sklearn.preprocessing import OrdinalEncoderdf['Sex'] = OrdinalEncoder().fit_transform(df['Sex'].values.reshape((-1, 1)))
df['Ticket'] = OrdinalEncoder().fit_transform(df['Ticket'].values.reshape((-1, 1)))
df['Embarked'] = OrdinalEncoder().fit_transform(df['Embarked'].values.reshape((-1, 1)))
形象化
现在,我们将可视化我们的数据,看看我们的变量在存活和未存活类中的分布如何变化。
下面是我们数据集中每个变量的直方图(以及生成它的代码),左边是幸存人员的子集,右边是未幸存人员的子集。
import matplotlib.pyplot as plt
from IPython.display import display, Markdowndef show(txt):
# this function is for printing markdown in jupyter notebook
display(Markdown(txt))for i in range(1, 9):
show(f'### {df.columns[i]}')
f, (survived, not_survived) = plt.subplots(1, 2, sharey=True, figsize=(18, 8))
survived.hist(df.iloc[np.where(df['Survived'] == 1)[0], i])
survived.set_title('Survived')not_survived.hist(df.iloc[np.where(df['Survived'] == 0)[0], i])
not_survived.set_title('Not Survived')
plt.show()
对这种数据格式运行机器学*
现在,我们将在数据集上尝试几种机器学*方法,看看我们会得到什么结果。我们将使用的机器学*方法有:
- 逻辑回归
- 支持向量机
- 决策图表
- k 个最*邻居
- 多层感知器
我们将使用 Scikit-Learn 的cross_val_score
进行(5 重)交叉验证,而不是选择一个固定的验证集来估计测试集的准确性,sci kit-Learn 的cross_val_score
返回一个数组,其中包含每次交叉验证迭代的分数。
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.neural_network import MLPClassifierX = df.iloc[:, 1:].values
y = df.iloc[:, 0].values# Logistic Regression
lr = LogisticRegression()
lr_score = np.mean(cross_val_score(lr, X, y))
print(f'Logistic Regression: {lr_score}')# Support Vector Machine
svc = SVC()
svc_score = np.mean(cross_val_score(svc, X, y))
print(f'Support Vector Machine: {svc_score}')# Decision Tree
dtc = DecisionTreeClassifier()
dtc_score = np.mean(cross_val_score(dtc, X, y))
print(f'Decision Tree: {dtc_score}')# K Nearest Neighbors
knc = KNeighborsClassifier()
knc_score = np.mean(cross_val_score(knc, X, y))
print(f'K Nearest Neighbors: {knc_score}')# Multi-Layer Perceptron
mlpc = MLPClassifier()
mlpc_score = np.mean(cross_val_score(mlpc, X, y))
print(f'Multi-Layer Perceptron: {mlpc_score}')
运行这段代码,我们得到了以下结果:
特征工程
让我们看看是否可以通过处理数据集的要素来提高精确度。为此,我们将首先恢复到应用序号编码之前所做的备份。
df = df_bkp.copy()
一键编码
现在,我们想对我们的分类变量应用一次性编码,而不是顺序编码。使用一键编码,我们不是给每个类分配一个数字,而是给一个向量分配所有的 0,除了一个特定于该类的位置,在该位置我们放置一个 1。也就是说,我们将每个类转换成一个独立的变量,其值为 0 或 1。我们将使用 Scikit-Learn 的OneHotEncoder
对变量 Pclass 、 Sex 、 Ticket 和embedded应用一键编码。
from sklearn.preprocessing import OneHotEncoder# Pclass
pclass_transf = OneHotEncoder(sparse=False, dtype=np.uint8, handle_unknown='ignore')
pclass_transf.fit(df['Pclass'].values.reshape((-1, 1)))
pclass = pclass_transf.transform(df['Pclass'].values.reshape((-1, 1)))
df['Pclass0'] = pclass[:, 0]
df['Pclass1'] = pclass[:, 1]
df['Pclass2'] = pclass[:, 2]
del df['Pclass']# Sex
gender_transf = OneHotEncoder(sparse=False, dtype=np.uint8, handle_unknown='ignore')
gender_transf.fit(df['Sex'].values.reshape((-1, 1)))
gender = gender_transf.transform(df['Sex'].values.reshape((-1, 1)))
df['Male'] = gender[:, 0]
df['Female'] = gender[:, 1]
del df['Sex']# Ticket
ticket_transf = OneHotEncoder(sparse=False, dtype=np.uint8, handle_unknown='ignore')
ticket_transf.fit(df['Ticket'].values.reshape((-1, 1)))
ticket = ticket_transf.transform(df['Ticket'].values.reshape((-1, 1)))
for i in range(ticket.shape[1]):
df[f'Ticket{i}'] = ticket[:, i]
del df['Ticket']# Embarked
embarked_transf = OneHotEncoder(sparse=False, dtype=np.uint8, handle_unknown='ignore')
embarked_transf.fit(df['Embarked'].values.reshape((-1, 1)))
embarked = embarked_transf.transform(df['Embarked'].values.reshape((-1, 1)))
for i in range(embarked.shape[1]):
df[f'Embarked{i}'] = embarked[:, i]
del df['Embarked']
缩放至[0,1]范围
我们还想将数值变量缩放到[0,1]范围。为此,我们将使用MinMaxScaler
来缩放变量,以便最小值移动到 0,最大值移动到 1,其他中间值相应地在 0,1 之间缩放。我们将把这个转换应用到变量年龄、 SibSp 、 Parch 、费用。
from sklearn.preprocessing import MinMaxScalerage_transf = MinMaxScaler().fit(df['Age'].values.reshape(-1, 1))
df['Age'] = age_transf.transform(df['Age'].values.reshape(-1, 1))sibsp_transf = MinMaxScaler().fit(df['SibSp'].values.reshape(-1, 1))
df['SibSp'] = sibsp_transf.transform(df['SibSp'].values.reshape(-1, 1))parch_transf = MinMaxScaler().fit(df['Parch'].values.reshape(-1, 1))
df['Parch'] = parch_transf.transform(df['Parch'].values.reshape(-1, 1))fare_transf = MinMaxScaler().fit(df['Fare'].values.reshape(-1, 1))
df['Fare'] = fare_transf.transform(df['Fare'].values.reshape(-1, 1))
对这种新的数据格式进行机器学*
现在,我们将对这种新的数据格式运行相同的机器学*算法,看看我们会得到什么结果。
X = df.iloc[:, 1:].values
y = df.iloc[:, 0].values# Logistic Regression
lr = LogisticRegression()
lr_score = np.mean(cross_val_score(lr, X, y))
print(f'Logistic Regression: {lr_score}')# Support Vector Machine
svc = SVC()
svc_score = np.mean(cross_val_score(svc, X, y))
print(f'Support Vector Machine: {svc_score}')# Decision Tree
dtc = DecisionTreeClassifier()
dtc_score = np.mean(cross_val_score(dtc, X, y))
print(f'Decision Tree: {dtc_score}')# K Nearest Neighbors
knc = KNeighborsClassifier()
knc_score = np.mean(cross_val_score(knc, X, y))
print(f'K Nearest Neighbors: {knc_score}')# Multi-Layer Perceptron
mlpc = MLPClassifier()
mlpc_score = np.mean(cross_val_score(mlpc, X, y))
print(f'Multi-Layer Perceptron: {mlpc_score}')
在我们以这种方式设计了我们的特征之后,我们在所有分类器的准确性上得到了显著的提高。其中最好的分类器是决策树分类器。现在我们试图通过使用GridSearchCV
进行超参数调整来改进它。
超参数调谐
from sklearn.model_selection import GridSearchCVdtc = DecisionTreeClassifier()
params = {
'max_depth': list(range(2, 151)),
'min_samples_split': list(range(2, 15))
}
clf = GridSearchCV(dtc, params)
clf.fit(X, y)print(f'Best params: {clf.best_params_}')
print(f'Best score: {clf.best_score_}')
我们得到的参数是:
我们得到的分数是 84.40% ,在超参数调优后提高了 0.9% 。
我希望这些信息对您有用,感谢您的阅读!
这篇文章也贴在我自己的网站这里。随便看看吧!
使用 SAP HANA 预测出租车目的地
原文:https://towardsdatascience.com/predicting-taxi-destinations-with-sap-hana-4125a62e2f5?source=collection_archive---------53-----------------------
基于真实实例展示多模型数据处理的优势
埃里克·诺帕宁在 Unsplash 上拍摄的照片
在我最*的故事中,我使用 SAP HANA 空间引擎和 SAP HANA 自动预测库,根据历史乘坐数据预测了在波尔图市乘坐出租车需要多长时间。在技术上,我利用 Jupyter 笔记本电脑和免费的 SAP HANA Express Edition 将所有操作(地理空间+机器学*)下推到数据库级别,而不是将数据(和计算)移动到客户端。
今天,我想更进一步,甚至根据起点、一天中的时间和轨迹的前几个点来预测出租车的目的地。在现实生活中,这种模型可以支持出租车运营,使后勤运营商能够预测某个区域内的可用出租车数量,甚至在这些出租车到达之前。
完整 Jupyter 笔记本 可在 GitHub 上查看。
让我们从代码开始——我不会详细介绍上传数据和六边形参考网格背后的概念,因为这已经在之前的博客中讨论过了。简单回顾一下:我们不是基于精确的坐标来预测结果,而是基于出租车出发的区域(即六边形单元)来预测出租车的目的地。
当查看出租车目的地区域的六边形单元时,我们最终处理多类分类问题,其中每个六边形单元(即其 ID 值)是一个目标类。HANA 的自动预测库提供了一个GradientBoostingClassifier,它能够进行多类分类。
数据准备和增强
然而,我们必须处理 GradientBoostingClassifier 的一个限制:它最多支持 100 个目标类。我们可以很容易地发现,我们的参考网格包含超过 1300 个潜在的目标区域。
那么,我们该如何处理呢?出租车经常去同一个地区。在前面的分析中,我们已经确定了波尔图的出租车接送热点。我们已经看到,在许多地区,抵达或出发的航班数量非常少。
只预测前 100 个目的地会有什么影响?我们可以使用下面的嵌套语句来检查到达前 100 个单元的总行程的百分比:
因此,我们看到只有不到 10%的行程到达其他地点。这意味着预测前 100 个目的地的模型将适用于超过 90%的旅行。当然,对于剩下的 10%,我们总是预测不正确的目的地。但是由于这些目的地很少,无论如何预测都很难。
好,我们来预测 100 个最常去的目的地。
为了使预测更有趣,我们将进一步包括滑行轨迹的前 10 个坐标。这可以让我们知道出租车朝哪个方向行驶。对于我们现实世界场景中的运营商来说,这对于不是超短的行程来说仍然是足够的提醒。
基于行程的前 10 个坐标,我们希望将以下特征添加到我们的训练数据集中:
-
罗盘 =滑行前进的方向(N,NE,E,SE,S,SW,W,NW)
我们将假设轨迹的第一个点在一个圆的中心,第十个点在其边缘。基于此,我们计算出指南针的方向。请注意,“ACOS(0)”的用法只是一种获取圆周率的黑客手段。 -
罗盘 _DIST =出租车在轨迹的前 10 个点内行驶的直线距离。 想法是检测出租车是否快速进入一条主干道或者沿着一些小巷子行驶。
为了将这些特征添加到我们的数据集中,我们可以发出下面的语句,该语句也根据上面计算的值对指南针方向进行分类。
训练梯度增强模型
好吧,让我们用 75000 个样本轨迹构建一个数据集,分为训练数据集(80%)和测试数据集(20%)。为此,我们将使用 HANA 内置的窗口函数 RANDOM_PARTITION 。在选择前 100 个目的地时,我们已经看到了嵌套 SQL 语句的第二部分。
随机化的双重使用可能首先看起来令人困惑。我们使用“order by rand()”和“top 75000”来随机选取 75000 个样本。然后,我们使用“random_partition()”将这些样本随机分为训练和测试数据集。
结果数据集如下所示,其中 END_HEXID 是我们模型的目标变量,SET_NUM 确定记录是属于定型数据集(SET_NUM = 1)还是测试数据集(SET_NUM = 3)。
最后,我们准备好训练我们的梯度推进模型。在我装有 HANA Express 的笔记本电脑上,培训持续几分钟。所以,慢慢来,喝杯咖啡…..或者浓缩咖啡,最好拿一杯浓缩咖啡。
使用 Python 的 hana_ml 客户端时,将从 Python 内部触发模型训练。但是,所有计算都在后台下推到数据库,数据不会传输到客户端。
喝完加了很多糖的浓缩咖啡后,我们观察分类模型的贡献特征。
决定出租车目的地的三个最重要的影响因素是:
- 出租车前往的方向,
- 提货区和
- 一天中的时刻。
这是有道理的——特别是白天的影响是可以预期的,因为晚上 8 点左右的旅行更有可能在酒吧或餐馆结束,午夜后的旅行更有可能在人们居住的郊区结束。
评估模型性能
当然,我们可以通过发出以下命令从 APL 中检索我们模型的统计度量:
但是,这次我们要评估的模型略有不同。因为我们通过六边形来聚集我们的位置,所以我们可能在六边形的边缘有一些“接*失误”。上述性能测量仅反映了我们是否准确预测了正确的目标六边形,它不包括地理空间邻*性测量。
为了获得一些数据,我们将基于 15000 条记录的测试数据集进行预测。
对于每个预测的记录,我们现在有正确的目标六边形以及预测的目标六边形的 id。为了评估地理空间的接*程度,我们需要将参考格网中的几何数据连接回结果表。
生成的数据帧如下所示,其中 TRUE_CENTROID 和 PREDICTED_CENTROID 是相应六边形单元/区域的质心点。我们可以看到,APL 甚至在输出中添加了一个概率场,通过它我们可以根据模型确定预测位置的可能性。
基于此,我们可以计算出预测质心和真实质心之间的平均距离。
所以平均来说,我们预测的范围是 2.6 公里。为了建立这种关系,我们需要知道我们的六角形细胞的直径。
这意味着由于我们的空间宁滨,我们无论如何只能在 1 公里的范围内进行预测。那么,我们的预测有多少是在正确的目标细胞中,或者是在它的一个相邻细胞中呢?根据直径,我们可以查询 1.1 公里范围内的质心。
我们可以看到,基于这个测量值,我们正确预测了三分之一(在我的例子中是 33.9%)的行程。
这听起来不错,但是我们应该将这个结果与适当的基线进行比较。如果我们简单地总是预测具有最多整体滑行活动的六边形单元,会发生什么?如果我们只有一个猜测,这个可能会很好。
我们可以确定最频繁访问的小区,并如下进行“预测”。
那么,我们的模型与作为基线的“多数票”相比如何呢?
使用我们的模型,我们的仍然比基线好 10%。我们的模型正确预测了 15000 次出行中的 5085 次,而基线多数投票只正确预测了 15000 次出行中的 3568 次。
最后,我们可以将 APL 配置为也输出所有其他六边形簇的概率,这些簇没有被预测为目的地。
我们可以用这些数据来想象一个场景:
- 在左侧,我们可以看到概率分布以及预测的目的地单元,以防我们在早上 8 点从 Campanha 火车站开始向西乘坐出租车。
- 在右图中,我们看到同样的旅程只是在晚上 8 点开始,然后向东北方向行驶。
同一起始位置的预测行程目标。
查看概率分布,我们可以知道,在任何情况下,城市中心都是一个可能的目的地(与时间和方向无关)。然而,对于向西的变量,我们在城市的东部没有看到任何高概率,而前往机场的概率明显更高。对于向东北方向的旅行,我们看到目的地在东北方向的概率较高,而机场和目的地在海边的概率较低。
作为一个附带收获,我们还可以在可视化中很好地看到,我们的前 100 个目的地地区基本上覆盖了波尔图的城市核心。
摘要
老实说,我不确定这是否是向出租车运营商推销解决方案的商业案例。但这仍然是一个有趣的例子,展示了如何将地理空间维度融入到机器学*模型中!
我们已经在这个(和我最*的)博客帖子中看到,如何将地理空间数据无缝地合并到一个简单的机器学*模型中。我们使用 SAP HANA 作为统一平台来处理空间数据和训练我们的模型。此外,我们还使用了 hana_ml Python 客户端来实现 Jupyter 笔记本的所有功能。
【https://blogs.sap.com】最初发表于。关注作者上LinkedIn或Twitter。
用机器学*预测 2020 年 NBA 总冠军
原文:https://towardsdatascience.com/predicting-the-2020-nba-champion-with-machine-learning-32100f6b253d?source=collection_archive---------27-----------------------
使用常规赛统计的历史联盟排名
埃德加·恰帕罗在 Unsplash 上拍摄的照片
当新冠肺炎在三月份暂停 NBA 赛季时,我和其他数百万人一样,彻底崩溃了。作为一个铁杆湖人球迷,我很高兴看到勒布朗和他的团队最终带我们去了乐土。但在经历了过去 6 年完全平庸的表现,没有一场季后赛的表现,以及哀悼已故伟大的科比·比恩·布莱恩特(RIP)的去世后,我想,
当湖人队终于有机会夺冠时,这个赛季真的有必要出现一种不可见的病毒吗?
但是 7 月 31 日,篮球又回来了。
不过,重新开始还有一个月,我已经看完了所有能想到的与篮球相关的内容,从观看 70 年代的 NBA 录像到 6 年级的 AAU 集锦。当我们耐心等待奥兰多的比赛结果时,我想让篮球界对这个赛季的未来有一点了解。我一直喜欢在季后赛开始前深入分析球队并预测每个赛季的冠军。在学*了一个月如何编码和使用数据分析工具后,我觉得已经准备好开始我的第一个机器学*项目来预测 2020 年的 NBA 冠军。(完整的 Github 回购可以在这里找到:https://github.com/trustinyoon/2020-NBA-Chip-Predictor)
数据收集
为什么我使用球队常规赛的联赛排名
我想创建一个模型,只使用常规赛的数据来预测 NBA 冠军。我总是着迷于球队的常规赛排名,并相信它们在决定球队在季后赛中的表现方面有着巨大的影响力。最初,我想过使用每场比赛的团队统计数据,然而,游戏在策略、速度、打法、运动员甚至游戏规则方面都发生了如此巨大的变化,如果我比较不同赛季的每场比赛统计数据,会有太多的噪音。例如,在 2003-2004 赛季,一支球队每场比赛的平均得分是 93.4 分,而上赛季是 111.2 分。仅仅通过比较原始数据来比较不同时代的球员或球队是不准确的。
确定一个团队的优势和劣势的最好方法是将它的表现相对于每个赛季的其他比赛进行比较。因此,我决定使用每个球队统计类别中的常规赛联赛排名作为特征来训练我的模型,以预测季后赛的胜利数。使用球队统计的联盟排名而不是每场比赛的球队统计,可以更清楚地显示出什么样的策略和执行对决定不同赛季的季后赛成功最有影响。
擦
为了收集数据,我从网上刮下了自 2002-2003 赛季以来每支季后赛球队在 basketball-reference.com T2 的常规赛排名。联赛排名从 1 到 30,因为总共有 30 支球队:联赛排名 1 为最好,30 为最差。自从季后赛结构在 2004 年改变后,我没有刮旧赛季,因此 NBA 总冠军必须包括赢得 7 场比赛中的 4 场比赛,而以前的赛季没有。我也没有包括没有进入季后赛的球队,因为这将扭曲我的季后赛胜利数的因变量数据。
我从 basketball-reference.com 刮来的一个球队常规赛表格的例子。联赛排名显示在“Lg 排名”行中。
这个表是为我的 y 变量收集自 2003 年以来每个季后赛球队的季后赛胜利数的数据。
数据清理
在构建了熊猫的数据框架后,我运行了一个相关矩阵来过滤掉与季后赛胜利数(因变量)的皮尔逊相关系数小于 0 . 25 的联盟排名(自变量)。这给我留下了以下与季后赛胜利至少适度相关的联盟排名:投篮命中率%,3%,2%,防守篮板,对手投篮命中率%,对手 2%,对手盖帽,常规赛胜利,胜率,简单评分系统(SRS),整体进攻评分,整体防守评分,有效投篮命中率%,对手有效投篮命中率%,以及上座率。
所选要素的多重共线性
在常规赛胜率(W)、胜率(MOV)和简单评分系统(SRS)中排名前三似乎是能够预测 NBA 冠军的体面指标。然而,SRS 和 MOV 是高度相关的,因为在计算两者时使用了点微分。我决定去掉 MOV,因为 SRS 稍微更准确一些,它考虑到了赛季安排的难度。上座率也有所下降,因为 2020 赛季的剩余比赛将在奥兰多的迪士尼世界进行,没有现场观众。
有效投篮命中率(eFG%和 O_eFG%)与其对应的投篮命中率(2P%、O_2P%、FG%、O_FG%)高度相关,所以我去掉了后四个,因为有效投篮命中率计算出的投篮效率稍微更准确一些。eFG%也与季后赛的胜场数稍有关联。
检查多重共线性后,我的模型具有以下特征:
- 3 个百分点
- 防守篮板
- 对手拦网
- 常规赛获胜
- 简单评级系统
- 总体进攻评分
- 总体防御评级
- 有效现场目标%
- 对手有效投篮命中率%
探索性数据分析
冠军球队常规赛联赛随时间的排名
就冠军常规赛团队进攻数据而言,2000 年代比 2010 年代有更多的可变性。这里最有趣的趋势是 3P%,因为金州勇士队自 2014 年以来以投篮 3 分彻底改变了篮球。三分球已经成为比赛中最重要的投篮,因为它有更高的 EV 和空间能力来创造更多的空位两分球。我们看到,一般来说,*几年的冠军往往在每个进攻团队的统计排名前 5-10,通常在 3P%排名前 5。
常规赛球队防守统计排名的可变性似乎比球队进攻统计排名小得多,在这三个类别中排名前 5-10 可以是季后赛冠军的一个很好的指标。防守篮板(DRB)很重要,但比限制对手投篮效率(O_eFG%)和整体防守评分(DRtg)稍微次要一些。
常规赛的胜数(W)和简单评分系统(SRS)似乎是预测一个冠军最一致的指标。冠军球队很少在常规赛胜利数或 Sr 数上排名前五之外。
限制对手拦网的影响被低估了
我发现对手的盖帽(O_BLK)类别是与季后赛胜利适度相关的最有趣的特征。这一发现让我假设,在 BLK 排名前百分之一的球队会让对手更难防守,这相当于更大的胜算。此外,篮球中的大部分盖帽来自非常短距离的投篮,因此对手盖帽能力较低的球队能够在更高的扣球率下得分,因为有更高的概率进行短距离投篮(例如上篮/扣篮)vs 中距离 2 分或 3 分。
预测模型
线性回归--随机森林--XGBoost
受邀参加奥兰多 2020 赛季重新开始的 22 支球队中每支球队的季后赛胜利预计数
在随机森林和 XGBoost 模型中交叉验证了训练和测试集,这有助于降低 MAEs 和防止过度拟合。
在每个模型中,密尔沃基雄鹿队预计将获得最多的季后赛胜利,湖人队紧随其后😒。尽管在 2019 年总决赛 MVP 科怀·伦纳德离开后,许多体育分析师都认为多伦多猛龙队排名很高,但卫冕冠军多伦多猛龙队的排名也令人惊讶。
但是在我把我所有的刺激资金都押在雄鹿队会赢得这个赛季之前,首先要考虑几件事。
结论
限制
我对数据的主要担忧是冠军球队(16 场季后赛胜利)的样本量非常小。这意味着每种模式中最好的球队的预期胜场数总是少于 16 场,这显然不足以赢得冠军。然而,我将分数解释为一个相对尺度,以查看哪支球队作为冠军具有最高的获胜预测值。
模型的 MAE 也随着每次测试和训练数据的变化而变化。每个型号的值通常在 2 到 3 之间。我用随机试验的预测和 MAE 的结果来总结发现。
摘要
使用常规赛 stat 联盟排名,我发现常规赛期间在胜场数(W)和简单评分系统(SRS)的联盟排名中名列前茅是预测冠军的最佳指标。在最*的趋势中,进攻得分高于防守得分也意味着赢得冠军的机会更大。
最佳预测性能由随机森林回归器实现,MAE 为 2.65,并预测雄鹿队以 13 场预期胜利成为冠军的热门。XGBoost 有一个较小的平均绝对误差 2.44,但是,它预测第一名雄鹿队只会赢得 9.3 场比赛,这与冠军所需的 16 场比赛相去甚远。
密尔沃基雄鹿队被每个模特选为最有希望赢得冠军的球队。湖人、猛龙、快船通常都混在雄鹿之后的积分榜上。
未来的工作
使用预测获胜次数可能不是确定冠军队伍的最有效方法。我会通过提供一支球队赢得 16 场季后赛的概率而不是它的期望值来增强我的模型预测。
我计划每季不断更新数据集,并继续完善现有模型/添加新模型。考虑到这是我的第一个数据科学项目,我使用的算法、参数和统计数据还有很大的改进空间。
用机器学*预测 NBA 季后赛比分
原文:https://towardsdatascience.com/predicting-the-2020-nba-playoffs-bracket-with-machine-learning-2030f80fa62c?source=collection_archive---------32-----------------------
利用历史篮球数据和机器学*预测每个系列赛的结果是可能的吗?
章鱼保罗是一只短命的头足类动物(2008 年 1 月 26 日-2010 年 10 月 26 日),饲养在德国奥伯豪森的海洋生物中心,他因被指能够预测国际足联世界杯足球赛的结果而一夜成名。他所要做的就是吃两个盒子中的一个,除了参赛国家队的旗帜之外,其他方面都一样。许多人认为章鱼是地球上最接*外星智慧的 T4 生物,人们可能会怀疑这种德国无脊椎动物(无意冒犯)是否知道一些关于足球的秘密,而这些秘密可能是更聪明的无毛猿(又名人类)事实上不知道的。
有时候你只有一次机会赢得比赛。[图片由 Ramiro Pianarosa 在Unsplash.com上拍摄]
基于计算机预测体育赛事结果的历史很长。内特·西尔弗的《信号与噪声的 T2》讲述了一个很好的故事,这是对这个主题感兴趣的人的必读之作。这本书还提醒读者,大多数这样的预测都失败了。然而,特别是自从深度学*的出现,先进的统计方法在体育赛事中的应用变得越来越重要,例如导致对棒球中的年轻球员进行球探,或者改进训练,例如到篮球中的投三分球。在这个历史时刻,我们很自然会问自己,在利用历史数据预测体育运动方面,人工智能能比我们强多少。在这篇文章中,我们将探索预测 NBA 季后赛的可能性,谁知道呢,甚至可能赢得 100 万美元。
用人工智能赢得 NBA 支架挑战赛
今年,美国国家篮球协会(NBA)发起了一项挑战,鼓励人们预测所有季后赛系列赛(加上决胜局)的结果,名为 NBA 括号挑战。虽然加入挑战的窗口现在已经关闭,并且在撰写本文时已经有了一些结果,但总体来看,如何安排机器学*系统来做出这样的预测是很有趣的。这当然是一种相当简化的方法,尽管在过去已经提出了更先进的例子,例如基于最大熵的原理。我准备了一个 Google Colab 笔记本,你可以用它来玩。您还需要输入数据,您可以从这个共享文件夹中复制这些数据。
首先,我们从篮球参考网站收集数据。人们可以方便地下载常规赛和季后赛的统计数据。在这里,我们限制到 1990 年至 2019 年,我们将使用 2020 年的常规赛数据来预测 2020 年的支架。
对于每支球队,每年都有以下“经典”功能可用(平均每场比赛):
- 常规赛末排名(Rk)
- 玩游戏的次数(克)
- 播放分钟数(MP)
- 现场目标(FG)
- 投篮尝试(FGA)
- 现场目标百分比(FG%)
- 三分球射门(3P)
- 3 分投篮尝试(3PA)
- 三分球命中率(3P%)
- 两分投篮得分(2P)
- 2 分投篮尝试(2PA)
- 两分投篮命中率(2P%)
- 罚球(英尺)
- 罚球次数
- 罚球百分比(英尺%)
- 进攻篮板
- 防守篮板(DRB)
- 篮板总数(TRB)
- 助攻数(AST)
- 偷窃(短期)
- 街区(BLK)
- 周转率
- 个人犯规
- 点
人们可以以 CSV 格式下载所有这些数据,这些数据可以很容易地作为一个 Pandas dataframe 来处理。
熊猫数据框包含 1990 年至 2020 年的常规季节数据
一些数据探索揭示了输入特征的平均值和百分位数。
毫不奇怪,这些特征之间存在相关性。为了减少输入特征的数量并尽可能消除相关性,*惯上是将标准化 ( 即去除平均值并缩放方差),然后对输入应用主成分分析分解。
输入要素之间相关性的热图
成对输入特征变量的相关图。看起来像斑点的子图对应于不相关的变量。相反,一些子图显示了很强的相关性,如射门次数(FGA)与得分(pts)或得分(PTS)与排名(Rk)。
为了训练机器学*模型,在这个例子中只是一个浅层神经网络,我们假设常规赛数据包含足够的信息来预测季后赛比赛的结果,这有点夸张,但也不太疯狂。
Model: "DNN_regresson" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input_69 (InputLayer) [(None, 32)] 0 _________________________________________________________________ dense_185 (Dense) (None, 32) 1056 _________________________________________________________________ dropout_98 (Dropout) (None, 32) 0 _________________________________________________________________ dense_186 (Dense) (None, 16) 528 _________________________________________________________________ dropout_99 (Dropout) (None, 16) 0 _________________________________________________________________ dense_187 (Dense) (None, 14) 238 ================================================================= Total params: 1,822 Trainable params: 1,822 Non-trainable params: 0 _________________________________________________________________
从技术角度来看,必须创建一组输入示例和相应的标签。有人可能天真地认为,预测比赛结果最明显的方法是让模型输出每个队赢的比赛数,例如4–1,2–4,等等。事实上,这种多维预测是不必要的,通常会产生 3-3、1-3 等不可能的结果。认识到可能结果的数量是有限的,这个问题就可以大大简化。例如,由于每个系列都必须以七局三胜结束(或在 2005 年前的第一轮中以五局三胜结束),因此只允许以下系列,因此可以在地图中进行编码:
valid_results = [(3,0), (3,1), (3,2), (4,0), (4,1), (4,2), (4,3), (3,4), (2,4), (1,4), (0,4), (2,3), (1,3), (0,3)]result_to_idx = {res: i for i, res in enumerate(valid_results)}
idx_to_result = {i: res for i, res in enumerate(valid_results)}
这样,我们可以要求网络输出 14 种可能结果中每一种的 softmax 概率。这样就不会得到不可能的结果作为输出。这种情况下的损失函数是sparse _ categorial _ cross entropy,它基本上是一个 categorial _ cross entropy,它不需要将标签表示为独热向量,而只是表示为整数,在这种情况下对应于有效游戏结果的索引。
该网络可以训练几十个时期和小批量。这种图的关键特征是训练和验证损失之间的必要一致。
作为训练时期的函数的训练(蓝色)和验证(橙色)损失。
决赛成绩
为了得到最终结果,训练好的网络被多次调用,每次比赛调用一次。首先,有必要定义一下互相对抗的队伍的名字。每个名字都被转换成一个表示索引的整数,该整数又被用于获取给定团队和给定年份(在本例中为 2020 年)的输入特征。
first_round = [
["milwaukee bucks", "orlando magic"],
["miami heat", "indiana pacers"],
["boston celtics", "philadelphia 76ers"],
["toronto raptors", "brooklyn nets"],
["los angeles lakers", "portland trail blazers"],
["oklahoma city thunder", "houston rockets"],
["denver nuggets", "utah jazz"],
["los angeles clippers", "dallas mavericks"]]
然后,该程序计算第一轮的结果,并根据结果,为半决赛、决赛和决赛创建类似的列表。
所以…预测如下:
第一轮
- 密尔沃基雄鹿队 4-3 奥兰多魔术队
- 迈阿密热火队 4-3 印第安纳步行者队
- 波士顿凯尔特人队 4 比 1 费城 76 人队
- 多伦多猛龙队 4 比 1 布鲁克林篮网队
- 洛杉矶湖人队 2-4 波特兰开拓者队
- 俄克拉荷马雷霆队 2-4 休斯顿火箭队
- 丹佛掘金队 2-4 犹他爵士队
- 洛杉矶快船队 4-1 达拉斯小牛队
胡人
- 密尔沃基雄鹿队 4 比 3 迈阿密热火队
- 波士顿凯尔特人队 2-4 多伦多猛龙队
- 波特兰开拓者队 2-4 休斯顿火箭队
- 犹他爵士队 2-4 洛杉矶快船队
大会决赛
- 密尔沃基雄鹿队 4-3 多伦多猛龙队
- 休斯顿火箭队 2-4 洛杉矶快船队
总决赛
- 密尔沃基雄鹿队 4 比 1 洛杉矶快船队
那么,今年真的是扬尼斯·阿德托昆博年吗?
用 LSTM 神经网络预测南福克帕耶特河的流量
原文:https://towardsdatascience.com/predicting-the-flow-of-the-south-fork-payette-river-using-an-lstm-neural-network-65292eadf6a6?source=collection_archive---------41-----------------------
如何使用机器学*对时间序列数据进行预测。
爱达荷州有一些世界上最美丽的河流!(📷威尔·斯托弗-诺里斯|东岔口南岔口萨蒙河)
TL;博士:
我制作了一个 LSTM 神经网络模型,它使用 30 多年的天气和河流流量数据来相当准确地预测明天的河流流量。
河流预报的问题是
水遇到爱达荷花岗岩。📷威尔·斯托弗·诺里斯
我从事数据科学的主要原因是将它应用于现实世界的问题。作为一名皮划艇运动员,我花了很多很多时间研究天气预报、水文预报和斯诺特尔站的数据,以预测河流的流量。有很多好地方可以进行这种预测——NOAA 在全国各大河流流域都设有预测中心,包括南福克。
但是,这些预测往往达不到预期。特别是,我注意到预报容易受到重大降雨事件的影响(众所周知,太平洋西北部的河流很难预测),预报通常每天只发布一次或两次,这通常不够频繁,无法对快速变化的山区天气预报做出反应。美国国家海洋和大气管理局也只对一组选定的河流进行预报。如果你想要一个更小或更偏远的流域的预报,即使它被测量了,你也不走运。
因此,我开始着手创建一个模型,这个模型将达到或超过 NOAA 的预测,并为 NOAA 没有覆盖的一些流域建立模型。
首先,我将我的模型与由上游技术创建的行业标准模型进行对比。
南福克帕耶特是一个很好的起点,有几个原因:
- Lowman 上方的南岔口没有筑坝,因此避免了储层的混杂变量。
- 美国地质调查局在南福克操作一个计量器,国家海洋和大气管理局有气象站和河流预报,在盆地里有 SNOTEL 站点。首先有许多容易获取的数据。
- 我曾经在帕耶特教过皮划艇,我几乎划过河流系统的每个部分,所以我很了解这个地区及其水文!
帕耶特的北叉是皮划艇运动员中的传奇。📷威尔·斯托弗·诺里斯
爱达荷州的河流总是不断变化。📷威尔·斯托弗·诺里斯
数据
我比较的上游技术模型使用气象和遥感数据来建立模型。我还没有加入任何卫星图像,尽管这是我的模型的下一个发展。
首先,我从位于南福克源头的班纳萨米特气象站下载了 NOAA 的每日气象数据。最终,我会将更多的站点合并到我的预测中,但是我想在第一次迭代中保持简单。测量的指标有:
- 沉淀
- 温度(最低和最高)
- 积雪深度
- 雪水当量
- 一年中的某一天。
这些是我的预测特征。数据可以追溯到 1987 年。
接下来,我去了位于爱达荷州洛曼的美国地质勘探局测量站,获取了自 1987 年以来每天的流量。在一个更精确的模型中,我可能得到每小时的数据,但是我认为每天的数据对于这个迭代来说已经足够了。
1987-2020 年 Lowman 南福克帕耶特的 CFS 排放
落基山脉的河流除了用于水力发电和灌溉外,还用于娱乐。📷威尔·斯托弗·诺里斯
争论
我用 pandas 合并了两个数据集,创建了一个包含特征和目标变量(流量)的数据框架。
气象数据中有一些缺失值,所以我用一些值来代替 NaNs。我创建了一个关联矩阵来查看是否有任何值是相关的,可以被删除。我决定去掉平均温度读数,因为已经有了最低和最高温度特征。
清理完数据后,是时候开始建模了。
美国西部的水是精确到最后一滴的。📷威尔·斯托弗·诺里斯
模型
我从一个基线开始——如果你只是猜测每次南福克的平均流量——大约 800 CFS——会发生什么?结果发现平均误差约为 600 CFS。这是不可接受的大,因为它几乎是河流本身的流量!
我知道我可以做得更好,好得多。
红线是大约 800 CFS 的基线预测。时间是 2019 年。
线性回归
线性回归非常简单,但也是一个不错的起点。我用了一个,然后两个,然后所有的特征,看看他们能多好地预测南汊的流量。答案是——非常糟糕。
基于“一年中的某一天”特征的单一特征线性回归只是一条每年重置的斜线。不太有用。
双特征线性回归(基于“一年中的某一天”和“温度”)稍有细微差别。
在线性回归中使用所有八个特征并没有好到哪里去。
随机森林
好吧,所以线性回归不被认为是最强大的机器学*模型。是时候展示一些更复杂的东西了。我把所有的特征放在一个随机的森林模型中。我本来可以花更长的时间来调整超参数,但我决定只使用股票 scikit-learn 设置,例外情况是使用 100 个估计器。
结果是一个惊人的改进——随机森林没有完全捕捉到径流的细微差别,但它确实比线性回归更好地跟踪了一般的季节趋势。
一个随机森林模型——越来越接*一个像样的预测!
锯齿山脉,南福克帕耶特的源头。📷威尔·斯托弗·诺里斯
LSTM 神经网络
现在是最新、最大、最糟糕的模型——神经网络的时候了。LSTM 神经网络可用于时间序列预测,尽管它们有一些局限性。我用的是 LSTM 的模型。
这个模型有一些怪癖——你必须以一种非常特定的方式争论数据才能使它适合——我发现了一些非常有价值的教程(Keras 文档和机器学*大师)。
我在 1987 年至 2015 年期间训练了模型,并在 2016 年至 2020 年期间对其进行了评估。在以后的迭代中,我将更多地研究时间序列数据的更好的验证技术,比如嵌套的交叉验证。
最终,我设法得到了一个 R 值为 98%、平均绝对误差仅为~50 cfs 的模型!这比我试过的其他(相当简单的)型号好得多。
我的模型性能随着时间的推移。LSTM 是明显的赢家!
最疯狂的是,我甚至没有将任何其他气象站或遥感数据纳入神经网络。
我怀疑前一天的流量对预测的贡献最大,因为预测的峰值似乎比实际峰值滞后一天左右。
我想对 LSTM 到底是如何得出预测的进行更多的调查,并可视化特征的重要性。
我的 2019 年春季决选 LSTM 模型(提前一天)。
就像爱达荷的穷乡僻壤一样,机器学*总有更多的东西可以探索。📷威尔·斯托弗·诺里斯
后续步骤
尽管我的模型在一天前表现得相当好,但我想在更长的预测范围内(2-10 天)对流量建模。我已经开始用 LSTM 做这个了,但是我需要花更多的时间。
我还想合并更多的气象站。NOAA 在该地区运营着几个站点,观察站点在分水岭的位置如何改变预测将会非常有趣。
我还想把卫星图像作为一个功能。这要复杂得多,因为文件很大,而且首先要获取图像。我已经开始建立一个管道,将谷歌地球引擎数据吸收到我的机器学*模型中。
最后,看看这个模型,它能够很好地预测过程线的下降段——但我也可以,只是凭直觉。该模型不太能够预测由于快速融雪或降雨事件导致的突然上升。在这些事件中,预测对于水电、防洪和公共安全至关重要。
一如既往,有更多的工作要做!
感谢您的阅读,请继续关注第 2 部分,在那里我将介绍一些后续步骤,尤其是合并卫星图像。
关于我的最新预测,请查看 rivers.fyi,我正在将 LSTM 神经网络投入多条河流的生产。
你可以在这里查看我在 Github 上用过的笔记本。
用深度学*预测主流音乐的声音
原文:https://towardsdatascience.com/predicting-the-future-sound-of-music-with-lstm-modeling-85488d8eac18?source=collection_archive---------32-----------------------
夹具在 Unsplash 上拍照
毫无疑问,Spotify 是当今最受欢迎的音乐流媒体平台之一,它高度受数据驱动。数据科学家利用机器学*推荐系统进行个人策划的播放列表,这是该平台最受欢迎和准确得出奇的功能之一。更多深思熟虑的,甚至是新颖的功能被不断地寻找,以保持用户与平台的互动。
所以我在想如何利用 Spotify 的开发者数据来获得创意。
当有人提到一位艺术家时,你听说过“超越时代”这个词吗?如果我们今天就能预测明天谁会领先于他们的时代,那会怎么样?当然,“走在时代前面”的音乐家大多很有名,但更重要的是,他们通常负责发起他们流派的变革。声波历史进程的改变。
进入数据科学 Spotify 对每首歌曲的歌曲特征进行令人印象深刻的算法音频分析。
Spotify 使用算法,根据“声音”、“可跳舞性”和“速度”等特征,给每首歌曲一个数字轮廓。我们可以随着时间的推移汇总这些特征来回答我们的问题。
目标:
该项目的主要目标是分析和预测 Spotify 上超过 160,000 首歌曲的数据集的年平均(主流)趋势。我将尝试使用长短期记忆(LSTM)递归神经网络来预测每个特征在未来可能的值。这基本上是一个数据驱动的数字表示,代表了 5 年后普通音乐的声音。然后,可以创建与这些未来特征值最接*的歌曲播放列表,并将其命名为“领先于他们的时间的曲目”,并可以作为对应用程序用户的流行吸引力。
数据:
从 1920 年到 2020 年发行了超过 160,000 首曲目,每首曲目都有 14 个特征值:
点击“查看文件”可以在 Jovian.ai 上看到完整的 EDA/处理笔记本。
来自 Spotify 开发者页面的一些功能定义:
Acousticness :一个从 0.0 到 1.0 的置信度度量,表示音轨是否是声学的。1.0 表示音轨是声学的高置信度。
可跳性:可跳性描述了一首曲目在音乐元素组合的基础上适合跳舞的程度,包括速度、节奏稳定性、节拍强度和整体规律性。值 0.0 最不适合跳舞,1.0 最适合跳舞。
活跃度:检测录音中是否有观众。较高的活跃度值表示音轨被现场执行的概率增加。高于 0.8 的值表示该轨迹很有可能是实时的。
乐器性:预测一个音轨是否不包含人声。“Ooh”和“aah”在这种情况下被视为乐器。Rap 或口语词轨道明显是“有声的”。乐器度值越接* 1.0,轨道不包含人声内容的可能性就越大。高于 0.5 的值旨在表示乐器轨道,但随着该值接* 1.0,置信度会更高。
效价:从 0.0 到 1.0 的量度,描述一首曲目所传达的音乐积极性。高价曲目听起来更积极(例如,快乐、愉快、欣快),而低价曲目听起来更消极(例如,悲伤、沮丧、愤怒)。
探索数据
这些年来,音乐在数字上是如何发展的?以下是我在 EDA 期间看到的几个例子:
“声音”特征框随时间变化图
声音有明显的区别。20 世纪早期的高音质音乐。乐器、扩音器和制作设备的技术进步可能是大多数最新音乐的声学乐器和整体声音较少的原因。
这些数据的分布告诉我,每年的声学平均值可能并不能很好地代表这些数据,因为它们会受到异常值的影响。我们可能需要创建一个新的具有中间值的年度数据框。中值将更准确地代表大部分数据。
随着时间推移,小提琴演奏出了“关键”
这里我们有一个不同的音乐音阶的用法的概念,一个分类的特征,随着时间的推移。在大多数年份,0 和 7 键音阶是使用最多的,这可以从他们小提琴的粗细看出。
清洁
乍一看,这个数据集对我来说非常干净。它没有丢失的值,没有奇怪的字符,等等。但是经过 EDA 的进一步检查和可视化,一些需要处理的细节开始出现。
例如,“语速”的定义告诉我们:“语速检测音轨中口语单词的存在。越是类似语音的录音(例如脱口秀、有声读物、诗歌),属性值就越接* 1.0。高于 0.66 的值描述了可能完全由口语单词组成的音轨。”
我们现在知道过滤掉任何包含超过 0.66 的语音值的音轨,因为它们是由实际上不是音乐的歌曲组成的。换句话说,这些是录音讲话,也许是单口喜剧录音,它们不会在音乐潮流中扮演角色。
特征工程
我在 EDA 过程中注意到,我需要创建一个新的数据框架,该框架根据中位数而不是平均值对每年的每个值进行分组。这是因为异常值的不平衡分布使得平均值不是集中趋势测量的准确表示。看看一段时间内中值“声音”与平均值“声音”的比较:
我能够创建这个新数据框的最简单的方法是将“分组依据”中位数分配给单独的列,然后合并它们,因为有许多原始列与我们无关,如“显式”或“名称”。在这里看看我的代码:
点击“查看文件”可以在 Jovian.ai 上看到完整的 EDA/处理笔记本。
建模
我进行了 ARIMA 和 LSTM 建模和调整,最初使用“声学”功能,其绘制的时间序列如下所示:
这里真正的目标是练*使用 LSTM 模型,但是我用 ARIMA 做了基线建模。在使用记录值、差分数据、LSTM 层叠加、双向 LSTM 层等众多 ARIMA 和 LSTM 模型后,给我最低均方根误差(RMSE)的模型是利用 1 滞后差分数据的 LSTM 模型。
使用差异数据的 LSTM 验证损失曲线
那么,什么是 LSTM 模式呢? LSTM 代表“长短期记忆”,这是一种循环神经网络(RNN)。通过一系列的 sigmoid 和 tan 激活,LSTM 细胞选择性地遗忘其长期序列的一部分(通过循环遗忘门)。这些剩余值被用于预测下一个值,该值被输出到下一个单元中,作为下一个序列的存储单元输入。
如果你想从技术上更深入地了解如何创建 LSTM 模型,可以看看我写的分解编码过程的帖子(链接即将推出!).
用最佳 LSTM 模型预测未来值
由于价值(在我们的例子中是年)越来越难以预测,我们将预测上限定在 5 年。下面的图表显示了到 2025 年所有标准化要素的预测值(可以放在同一 y 轴上):
过滤“超越时代”的艺术家
我决定从建模中去掉一些在历史上具有相同中值的特征,比如“显式”和“模式”。
不幸的是,我们的数据集不包含任何与所有特征的预测(中值)完全匹配的歌曲。对于最接* 2025 年预测值的歌曲,我采用每个预测模型 RMSE 与其预测值之间的间隔来过滤数据。
最“超前”的艺术家:二十一名飞行员——我心中的泪点
第二大“超前”艺人:新浪潮摇滚乐队——美少女
第三和第四位最“超前”的艺术家:卢·凯尔,里尔·特杰——错了(壮举。Lil Tjay)混音
莎拉·拉尔森清洁盗贼——交响乐(壮举。莎拉·拉尔森)
我们的数据集中没有符合每个预测特征范围的歌曲。我们发现与 2025 年预测(10 个中有 7 个)特征范围最相似的一首歌是《21 个飞行员》——《我心中的泪》。这首歌在我们的“可跳舞性”、“持续时间 _ 毫秒”、“能量”、“速度”、“效价”、“流行度”和“关键”误差范围内,与实际预测值相差不大。有 10 个共有特征中有 6 个的歌曲是新浪潮摇滚乐队的《美丽的女孩》。两首歌分享了 10 分中的 5 分。12 首歌分享了 10 个值中的 4 个。
结论
我们已经成功预测了我们的每个特征。那么他们告诉了我们什么?我们的模型预测,到 2025 年,普通歌曲将具备以下特征:
节奏将增加到 122.2 BPM 左右。响度将继续反弹,并达到接*-6db 的中值。(挺大声的!)歌曲中的工具性可能已经卷土重来,从 0。语速(人声/口语)将趋于平稳。声学度将再次降低,降至 0.08。平均受欢迎程度将继续增长。效价(积极/快乐)将下降并稳定在 0.455。能量会继续反弹,触及 0.649。可跳舞性或多或少也会保持稳定,只会上升一小部分,达到 0.697。换句话说,未来 5 年将保持最高的可跳性。
随后的研究表明,简单的时间序列,如数据点较少的时间序列,通常在 ARIMA 模型中表现更好,而 LSTM 模型在非常复杂的时间序列中表现更好,效率更高。考虑到这一点,我们能够使用稳定数据,通过 LSTM 建模获得较低的 RMSE,用于我们对每个特征的最终预测!
进一步建议
如果可能的话,我们可以直接访问 Spotify API,在整个 Spotify 库中查询那些拥有所有功能的最前沿艺术家。Spotify 总共列出了超过 5000 万首歌曲。找到与每个建模特征的未来平均值完全匹配的歌曲的概率要高得多。
将这种预测进一步扩展到各个流派,看看每个流派是如何随着时间的推移而演变的,以及这些流派中的哪些艺术家更早就演奏了这些价值观的音乐,这将是很有趣的。
最后,更多的时间分配来改进模型分层和/或参数将有助于我们预测的准确性。
欢迎在 GitHub 这里查看整个项目,如果你对我的过程有任何问题或建议,也可以给我发消息!
预测未来。数据科学家什么时候应该把数据留在身后?
原文:https://towardsdatascience.com/predicting-the-future-when-should-data-scientists-leave-the-data-behind-e96c47b18802?source=collection_archive---------27-----------------------
数据科学家经常被要求预测未来事件。不幸的是,我们拥有的科学工具是有限的。
准确地说,预测未来就像写科幻小说一样
在这里,我想说的是,有时数据科学家必须超越数据和科学。通常没有时间等待足够的数据来对潜在的结果做出合理的预测。有时候我们必须开始一些事情。在这些情况下,有一些非科学的工具来帮助我们做出合理的预测,这至少比什么都没有要好。
预测未来很难
大约在公元前 550 年,吕底亚国王克罗伊斯向特尔斐的神谕献祭,这加强了他传说中的财富声望。有金属锭可以作为一座四分之一吨重的金像、两个巨大的瓮、一个金瓮、一个银瓮和各种其他珍贵物品的基座:一座五英尺高的金像,是救他免于中毒的厨师的,还有他妻子的珠宝和腰带。他妻子对此事的想法没有记录。
作为回报,他请求神谕预言如果他进攻波斯会发生什么。有人告诉他,如果他这样做,一个强大的帝国将会崩溃。他把这解释为他将征服的信号——他毕竟花光了所有的钱——他入侵了。神谕被证明是正确的。一个强大的帝国倒了。不幸的是,对克罗伊斯来说,那是他自己的。
事实证明,预测未来是一件棘手的事情。
我想我们可以有把握地说克罗伊斯没有拿回他的钱。 对于我们这些数据科学家来说,风险在于我们表现得像甲骨文 。人们付钱给我们,让我们告诉他们将会发生什么,但是,到了紧要关头,我们通常会用“相信度”和关于概率的深奥讲座来回应。现在不要误解我,我个人喜欢关于概率解释的讨论,但我想知道我们在外人听起来是否像特尔斐的牧师。
“谢谢你的薪水,这里有一些神秘暧昧的呜呜呜,希望它能让你感觉良好。现在跑吧,做你无论如何都要做的事情
这是不可持续的,很容易导致人们完全放弃数据科学。
数据科学家甚至应该从事“未来业务”吗?
前几天,我看到一位亲密的同事告诉一位客户,数据科学家不做预测。因为我见过他叫很多个。predict() 法,我无法真正理解他的意思。
后来,他的论点是,当客户听到“预测”这个词时,他们会认为我们在对世界的未来做出明确的陈述。他更喜欢用“预报”这个词,因为人们知道天气预报不可能 100%准确。
现在,他很可能对客户的看法是正确的(他通常都是这样)。然而,对我来说,这是一种没有区别的区分。我认为,事实上,大多数情况下,数据科学家使用一系列科学工具来进行预测。有时,例如在时间序列问题中,这是显而易见的:明天卖出这些股票,因为我们认为它们的价值会随着时间的推移而下降。其他时候不太明显:例如在分类问题中。你可能不会预测未来,本身,但问题是你要预测人类法官会给你分类的例子贴上什么标签。
也有一些例外,例如,某些类型的 GANs 可能不算在内。但总的来说,我认为我们大多数人都在预测将要发生的事件,或者已经发生但尚未被我们观察到的事件。
这没什么不好。我们应该拥抱它。这是科学家做的事情。
科学方法的卡通解释是,科学家建立一个模型,然后出去寻找推翻它的证据。渐渐地,随着越来越多的证据被收集起来,这个模型也没有被证明是错误的,这个模型被认为是一个科学真理【2】。这大致是数据科学家声称的行为方式:他们查看一些数据,建立一个捕捉正在发生的事情的模型,然后将该模型投入使用。随着更多数据的出现,这个模型得到了验证。
科学在行动。
明摆着的难题
不幸的是,在许多现实世界中,我们的预测并不是很好!例如,即使知道潜在客户之前已经完成了购买过程——这似乎应该是一个巨大的意向指标——也只能在预测谁会点击广告方面提供有限的改进。如果我能预测明天哪些股票会下跌,我会在地中海的游艇上写这篇博客,而不是在伦敦郊区的公寓里。
我们的技术是这样的,我们认为比随机机会做得好一点点就是胜利。如果我们也能比竞争对手做得好一点点,我们就成功了。我们正在尽最大努力使用科学方法,但是在方法和技术上遇到了限制。
现在,有一种数据科学家认为,当科学停止时,我们也应该停止。在这场争论中,科学方法是人类成就的顶峰。当我们不能用它来说任何有意义的事情时,就意味着我们不能真正了解任何事情。一个人不能说的,他必须保持沉默。
作为一个受过科学家训练的人,我对这种想法有些同情。然而,这个世界并不是这样的!如果你的公司以科学的速度前进,也就是说,缓慢而谨慎,只有在积累了足够的证据后才前进,你肯定会被那些行动更快的公司打败。
但是,我们的数据科学家可能会说,这些公司是在凭猜测行事!他们最终肯定会失败。这可能是真的,但是有两个相反的论点。一个是,这是一个非常大的世界,最终可能是一个非常长的时间。有一百个竞争者,他们中的一些人会碰巧猜对。他们的行动比你快得多,以至于在你收集数据证明猜测是否正确之前,你就已经被打败了。
然而,还有另一个更有趣的原因。我认为猜测不一定是随机的。猜测和做得比偶然更好是可能的,而且存在理性的,但本质上非科学的工具,帮助我们做到这一点。
于是,权衡的办法是等到有了数据,然后在一定程度上确定地继续下去,或者使用非科学的工具做出有根据的猜测。在许多情况下,我认为组织应该采取后一种方法。
进入“未来研究”的世界
到目前为止,我认为作为科学家,我们被要求预测未来,但基本上无法做到。对此有两种回应。一种是举起你的双手说,“我是科学家,这就是我停下来的地方”,然后看着你被击败。另一种是抛弃科学,尝试用其他工具来理解复杂的世界。
那么这些工具是什么呢?这里有一些,从未来研究领域借来的。对于数据科学家来说,它们可能看起来很陌生。我们要做的是想象一系列半可信的未来,然后给它们分配概率。这里我指的是赌徒意义上的“相信程度”的概率。令人高兴的是,这也是贝叶斯概率的意义。如果你持怀疑态度,请记住人类的努力不仅仅是科学。哈姆雷特在某种意义上是真实的,尽管它不是“字面上的真实”。
工具 1:科幻想象。在这里,你可以无拘无束地坐下来,编造一些似是而非的东西。这个想法是让你的思想自由。太空电梯?为什么不呢!海底殖民地?当然可以!或许更黑暗的东西?私营公司进行的总人口监测。那是科幻吧?
这个工具的用途不是产生现实的想法。让我们摆脱数据驱动培训带来的限制,尽情发挥想象力。如果你像我一样,通过克拉克和阿西莫夫到达了伊恩·M·班克斯,你可以引导那些未来的幻象,让整个过程不那么…奇怪。
工具二:视界扫描。未来已经到来——只是分布不均匀【5】。创新的历史上充满了想法从利基市场扩散并占领世界的例子。加拿大的那些家伙,直到 2010 年还在研究神经网络?那是无处可去的,直到它无处不在。那么外面还有什么呢?中国的 A.I .大概算主流,但是日本的纳米材料呢?班加罗尔正在进行哪些数据科学创新?或者拉各斯的城市设计创新?这不仅限于技术。想想中非音乐家的文化活力,在用法语【6】说唱。
关键是未来可能已经在某个地方存在了。涉及现有创新传播的预测比从头开始发生的预测更可信。
工具三: 趋势。好吧,瞎编只能让我们到此为止。我们必须查看数据,将想象的未来与我们现有的现状联系起来。你可能有所有这些疯狂的想法,但是我们能辨别它们中的任何一个,以任何方式,是现实的吗?一种方法是从数据中挑选一些相关的趋势,然后进行推断。记得那个太空电梯吗?纳米材料拉伸强度的提高会有多快?
这经常被描述为未来研究的科学部分。对于一个数据科学家来说,这可能不算科学。但至少观察数据趋势的过程应该是熟悉的。只是挑数据是一门艺术,你不能构建一个万物的因子模型,但不代表你什么都不能做。记住我们在这里讨论的是信仰的程度。
工具 4:场景测试。对于任何从事金融工作的人来说,这应该很熟悉。这是管理风险的人一直在做的那种压力测试(或者至少从 2008 年 9 月开始)。在他们的案例中,他们将调查局限于事件对金融投资组合的影响,例如,如果美国退出世贸组织,股价会发生什么变化,或者如果恐怖主义封锁马六甲海峡,大宗商品价格会发生什么变化?同样,我们可以思考重大事件对我们预测的影响,例如,南海战争对日本将建造第一架太空电梯的预测会有什么影响?关键是,没有一个单一的大效应事件是非常可能的,但一些事情最终会发生。通过调查一系列事件,希望你能发现以类似方式影响你预测的共同主题。
合成。您可能会轮流使用这些工具来完善您的预测。最后,你会想象出一堆未来,调查了世界各地的一堆创新,并试图用趋势和假设的场景来反驳它们。然而,当音乐停止时,你必须停止跳舞。记住我们不是在这里做科学研究。你必须下来,用你的判断力去 决定 。如果你愿意,你可以把它想成对将要发生的事情有一个预先的信念,你用微弱的证据更新了它。问题是,你不知道那个证据有多弱,所以数学帮不了你。
良好判断项目
最后,我需要提一下这是如何与 Philip Tetlock 的工作以及他在 Good judgment Project【7】中的工作相吻合的。这是一个测试人们预测未来能力的竞赛。他发现了一群超级预测家,他们比同时代的人更擅长预测未来。他接着指出了让他们变得优秀的性格特征:基本上要聪明、思想开放,与其他聪明、思想开放的人交往,努力工作,对概率意味着什么有一种直觉,并解释你的偏见。
这些都是好东西,但是没有说明如果你不得不做一个预测的话该怎么做。努力工作?当然,但是在哪里?然而,当我读到超级预测者描述他们如何做出预测时,他们给出了上面详述的两种方法,我松了一口气。
所以在结论 中,我认为数据科学家不能忽视预测问题,因为这是人们付钱给我们的目的。然而,我们需要面对这样一个事实,我们用来预测的工具并不是很好。有时候“不太好”就足够好了。然而,在不是这样的情况下,在我们需要考虑更长远的未来的情况下,还有其他非科学的工具可供我们使用。
你怎么想呢?数据科学家应该放过预测吗?请在评论中告诉我!
脚注
【1】《史记》,第一册,逻各斯 1,1.1–1.94,希罗多德
【2】这当然是对卡尔·波普尔的简化,参见这里的讨论。波普尔本人也有一个模型“确证”的概念,这一概念被与似然法相关的统计学家们所接受。当然还有库恩,所以你明白为什么我的是卡通版了。
【3】7、路德维希·维特斯坦根
【4】这些工具摘自我在彼得·马登教授的未来城市弹射器讲座上的笔记。任何错误都是我的!
【5】引自威廉·吉布森,确切地点一如既往有争议。
【6】参见此处的示例。
【7】良好判断项目的参考资料可在这里找到。
【8】识别和培养超级预测者作为提高概率预测的方法。芭芭拉·a·梅勒,菲利普·泰特洛克。心理科学透视,第 10 卷,第 3 期,第 267-81 页
****【9】这里引用的方法我认为包括趋势(朝鲜核试验)和情景测试(南海死亡)。
预测同行撰写的产品评论的“有用性”
原文:https://towardsdatascience.com/predicting-the-helpfulness-of-peer-written-product-reviews-ef7a0dfea2c3?source=collection_archive---------23-----------------------
将自然语言处理和神经网络应用于复杂的文本处理问题
这有帮助吗?菲公主想知道。
一些电子商务网站让顾客写下他们产品的评论,其他顾客在考虑购买产品时可以浏览这些评论。我知道我读过我的顾客朋友写的产品评论,这些评论帮助我判断一个产品是否符合尺寸,是否能持续很长时间,或者是否含有我担心的成分。
如果一家企业能够预测哪些评论对其客户会有帮助,那会怎样?也许它可以把这些评论放在页面的最前面,这样读者就可以更快地获得最好的信息。也许企业可以注意到哪些主题出现在这些有用的评论中,并修改其产品描述以包含更多此类信息。也许企业甚至可以识别“超级评论者”,即特别擅长撰写有用评论的用户,并激励他们评论更多产品。
利用亚马逊的大量产品评论,我训练了一系列机器学*模型,试图识别哪些评论被读者评为“有帮助的”。我尝试了随机森林、逻辑回归、支持向量机、GRU 网络和 LSTM 网络,以及各种自然语言处理(NLP)技术来预处理我的数据。事实证明,预测有用的评论非常困难,但并非不可能!直奔代码,查看我的 GitHub repo 。要了解更多关于我是如何做到的,请继续阅读。
数据集
以下是您需要了解的数据集:
- 它来自亚马逊(via Kaggle) ,尤其是食品部门,不仅包括食品,还包括厨房小工具和宠物食品。
- 它是在 2002 年至 2012 年期间收集的,所以它并不完全是最新的,但我认为在 2020 年我们仍然可以从中学*很多东西。
- 它包含了超过 500,000 条评论,在我删除重复的评论后,还剩下 393,579 条评论。
- 读者有机会将评论标记为“有用”或“无用”。还有一个否决评论的选项,但没怎么用过。大约 52%的评论获得了零个“有帮助”的投票,其余的获得了一个或多个“有帮助”的投票。
- 除了“有用性”和评论本身的文本,数据集还记录了产品 ID、用户 ID、时间戳和评论作者给产品的星级(满分 5 分)。
以下是按类别划分的评论数、总令牌数和唯一令牌数的快速浏览:
虽然有帮助的评论少了,但是比没有帮助的包含了更多的词和更多独特的词。
困惑于预测
鉴于这个数据集的内容,我有两个大问题。问题 1:除了评论本身的文本之外,“有用性”可以通过其他特征来预测吗?例如,如果有用的评论总是包括 5 星评级,或者总是由同一批评论者撰写,那我就省了很多文字争论!
事实证明,答案是否定的:使用数据集中的任何其他特征,或者我自己设计的少数特征,都无法预测有用的评论。有用的评论可以是短的、长的、正面的或负面的;可以是新手写的,也可以是有经验的审稿人写的;它们可以是流行或不知名的产品;而且他们的词汇和无益的评论很像。
这是 t-SNE 的评论样本图,主要关注文本本身。t-SNE 图基本上是对数据集进行主成分分析,将所有要素减少到 2 或 3 个成分,然后绘制它们,这样您就可以看到类是如何重叠(或不重叠)的。这个情节揭示了一个噩梦:至少在这两个维度上,这两个类有很多重叠。
这让我想到了问题 2:如果没有预测有用性的捷径,我该如何从文本中预测有用性呢?我应该如何为建模预处理评论?应该尝试哪些机型?众所周知,使用人工生成的文本作为预测模型的输入非常困难,部分原因是有太多的方法可以将文本转换为数据,然后您需要相当复杂的模型来处理这些数据。选哪个?
当决定如何预处理评论文本时,我想尝试一系列的技术,集中在那些在我的项目的探索阶段看起来最有希望的技术上。至于建模,我想从更简单、训练更快的模型开始,然后逐步进行最复杂的选择。我希望前几轮测试可以帮助我确定最佳的预处理选项,而最后几轮测试可以帮助我完善我的最佳模型。
第一阶段:进入森林
我的第一轮大实验包括针对基线随机森林模型测试不同的预处理技术:
- 将文本作为二元模型处理,然后在其上训练一个随机森林。
- 将文本作为术语-文档矩阵进行处理(基本计数矢量化),然后在此基础上训练一个随机森林。
- 计算 TF-IDF(术语频率-逆文档频率)向量,然后在随机森林中运行这些向量。
所有这些在验证数据上的表现都在 54–55%的准确度范围内,这仅比随机猜测好一点点,但至少不比随机猜测差!TF-IDF 得分最高,所以我决定使用 TF-IDF 向量作为输入,尝试调整一个随机森林,以便做得更好。我尝试了以下方法:
- 使用网格搜索来确定要使用的最佳估计数和最大树深。
- 将 TF-IDF 向量的长度增加一倍(即,创建了更多的输入数据),然后进行一种形式的主成分分析(使用 TruncatedSVD )来选择一些可以解释训练数据中 80%方差的成分。
- 使用我在前面两步中生成的所有东西训练了一个最终的随机森林。
所有这些都产生了一个模型,该模型对训练数据过度拟合(超过 99%的准确率),对验证数据的准确率为 57%,这是我迄今为止的最好成绩。
但是比随机猜测好 7 个百分点并不值得大书特书,所以我转向了迁移学*方法。
第二阶段:脱下手套
迁移学*包括将别人的模型计算出的权重代入你自己的模型。这可能是一种非常方便的方式,可以从其他人的投资中受益,例如,在维基百科的所有内容上训练一个巨大的模型。
这就是嵌入手套的原因。斯坦福大学的一些聪明人训练了一个巨大的模型来量化英语单词在上下文中的关系。通过从 GloVe 中为我的评论语料库中的每个单词收集相关的嵌入向量,我可以从中受益。然后,对于每篇评论,我取所有单个单词向量的平均值,形成一个新的向量,代表评论的整个文本。然后,可以将所有评审向量传递给模型进行训练或预测。
我将我的手套嵌入传递给三个模型:随机森林、逻辑回归和支持向量分类器。这些模型在验证数据上的准确率也在 53–56%之间,其中随机森林的准确率最高。经过一些额外的调优,我仍然只能得到 56%的验证准确率。
在这一切之后,我非常想看看神经网络能做什么。
第三阶段:只有蚊帐
众所周知,序列对序列模型在处理文本数据时表现良好,所以我决定尝试两种不同的这类神经网络架构。我特别感兴趣的是让这些网络动态地计算它们自己的嵌入;由于 GloVe 做得不太好,我希望仅基于我的数据集的嵌入可能是更好的选择。
看看我的基线神经网络的结构:
*# Try again with more epochs, callbacks
import tensorflow as tf
embedding_size = 128
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Embedding(200000, embedding_size, input_shape=(100,)))
model.add(tf.keras.layers.GRU(25, return_sequences=True, input_shape=(100,)))
model.add(tf.keras.layers.GRU(25, return_sequences=True, input_shape=(100,)))
model.add(tf.keras.layers.GlobalMaxPool1D())
model.add(tf.keras.layers.Dropout(0.5))
model.add(tf.keras.layers.Dense(50, activation='relu'))
model.add(tf.keras.layers.Dropout(0.5))
model.add(tf.keras.layers.Dense(50, activation='relu'))
model.add(tf.keras.layers.Dropout(0.5))
model.add(tf.keras.layers.Dense(1, activation='relu'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
history = model.fit(X_train, y_train, epochs=50, batch_size=2048, validation_data=(X_val, y_val))*
这是一个计算嵌入的层,两个各有 25 个门控递归单元(GRU)节点的层,一个汇集其输出的层,两个各有 50 个节点的密集层(有 50%的丢弃以避免过度拟合),然后一个节点对每个样本进行最终预测。我也尝试了同样的架构,但是用长短期记忆(LSTM)节点代替 GRUs。结果没有实质性的差异,GRU 稍微快了一点,所以我决定继续用更大的输入向量和更多的训练时段来调整 GRU 网络。
最佳模型和结果
总的来说,我最好的模型是最后一个:GRU 网络在验证数据上达到了 59%的准确率。在我的 holdout 数据集上,这个模型也达到了 59%的准确率,考虑到它试图解决的问题的复杂性,这还算不错。
像这样的模型可以用来对提交的评论进行排序,并将那些可能有帮助的评论排在队列的最前面。一家企业也可以从自己的网站上搜集评论,筛选出有用的,然后再去评论,以了解潜在客户想知道的、他们的产品描述没有提供的信息。类似地,企业可以确定有用评论的作者,并鼓励他们写更多,或者修改他们的评论提交表格,以包括撰写更多信息性评论的技巧(正如 AirBnB、猫途鹰和其他公司已经做的那样)。
如果你想在有用的评论上看到我的整个项目的精彩细节,请查看 GitHub 上的代码。感谢阅读!
跨贴自【jrkreiger.net】。
用线性回归预测社交媒体广告对销售的影响
原文:https://towardsdatascience.com/predicting-the-impact-of-social-media-advertising-on-sales-with-linear-regression-b31e04f15982?source=collection_archive---------7-----------------------
本文将详细介绍使用 r 软件包进行简单线性回归的步骤,还将涵盖相关的基本介绍性统计数据。
由活动创作者在 Unsplash 上拍摄的照片
什么是简单线性回归?
线性回归测量响应变量 Y 和预测变量 X 之间的关系。X 增加一个单位,Y 增加吗?还是随着 X 增加一个单位而减少?我们想用线性关系从 X 预测 Y 变量。我们可以理解两个变量是如何相互联系或相互影响的。
例如,假设 Y 是伦敦不同街区每 1000 人被刺伤的次数——刺伤次数越多,犯罪率越高。如果 X 是不同社区的中值房价,我们可以使用线性回归来测试中值房价较低的社区是否有较高的犯罪率,反之亦然。
回归方程:
数学上,线性回归可以表示如下:
Y=β1+β2X+ϵ
- 响应(相关)变量 Y 是我们试图预测的。
- 预测(独立)变量 X 用于预测响应。
- β1 是截距,是一个常量值。如果 X = 0,那么 Y 将完全依赖于β1。
- β2 是回归线的斜率。我们将这些术语称为系数。
- ϵ是残差项。这将显示 x 可以解释多少 Y,误差项的平均值为 0。
让我们用一个例子来形象化这一点。
带 R 的示例
我们将使用datarium
包中包含的marketing
数据集,其中包含一家虚构公司的三种媒体(脸书、YouTube 和报纸)的广告预算(以千美元计)以及该公司的销售数据。
1.提出我们的问题:
制定一个研究问题是指导探索性数据分析过程的有用方法。它可以帮助清理数据集,并通过消除不需要的变量、处理缺失值等为严格的分析做准备。我们的一般问题是:
考虑到 YouTube 和报纸广告的效果,脸书广告对公司的销售有什么影响?
我们希望开发一个线性模型来解释预测变量facebook
和数值响应变量sales
之间的关系。在本文中,我们将使用 R 包来执行简单的线性回归。这里有一个简单的线性回归方程:
Sales=β0+β1*Facebook+ϵ
涉及多个预测变量的多元回归将在另一篇文章中进行解释(即将发布!)。例如,如果我们想测试脸书广告对公司销售的影响给定YouTube 和报纸广告的广告预算,我们的多元回归方程将如下所示:
销售额=β0+β1 * Facebook+β2 * YouTube+β3*newspaper+ϵ
我们将首先从一个简单的线性回归开始,找到预测响应sales
的最佳直线,作为预测值facebook
的函数。
2.安装
首先在 R Studio 中安装tidyverse
、ggpubr
和datarium
包。从datarium
包中导入marketing
数据集。
library(tidyverse)
library(ggpubr)
data(“marketing”, package = “datarium”)
3.探索性数据分析
首先,我们将使用str()
函数来获得数据结构的快照视图。我们可以看到有 200 行数据和 4 个变量——YouTube、 facebook 、报纸和销售额。我们还可以看到每个变量的前几个单独的值。此外,我们可以看到每一列变量的类别——我们的每个变量都被归类为“数值型”。
> str(marketing)
'data.frame': 200 obs. of 4 variables:
$ youtube : num 276.1 53.4 20.6 181.8 217 ...
$ facebook : num 45.4 47.2 55.1 49.6 13 ...
$ newspaper: num 83 54.1 83.2 70.2 70.1 ...
$ sales : num 26.5 12.5 11.2 22.2 15.5 ...
我们也可以使用dim()
来了解数据帧的尺寸,即行数和列数。
> dim(marketing)
[1] 200 4
接下来,我们将使用head()
函数来浏览一下我们的原始数据。默认情况下,该函数将返回前六行,但是我们可以根据自己的喜好查看任意数量的行。我们希望看到前 10 行:
> head(marketing, 10)
youtube facebook newspaper sales
1 276.12 45.36 83.04 26.52
2 53.40 47.16 54.12 12.48
3 20.64 55.08 83.16 11.16
4 181.80 49.56 70.20 22.20
5 216.96 12.96 70.08 15.48
6 10.44 58.68 90.00 8.64
7 69.00 39.36 28.20 14.16
8 144.24 23.52 13.92 15.84
9 10.32 2.52 1.20 5.76
10 239.76 3.12 25.44 12.72
让我们也用tail
看看数据集的结尾。这非常有用,因为在一些数据集中,最后几列可能包含数据的总计或汇总,这可能是不相关的。
> tail(marketing)
youtube facebook newspaper sales
195 179.64 42.72 7.20 20.76
196 45.84 4.44 16.56 9.12
197 113.04 5.88 9.72 11.64
198 212.40 11.16 7.68 15.36
199 340.32 50.40 79.44 30.60
200 278.52 10.32 10.44 16.08
现在,我想使用summary
调出一些汇总统计数据。
> summary(marketing)
youtube facebook newspaper
Min. : 0.84 Min. : 0.00 Min. : 0.36
1st Qu.: 89.25 1st Qu.:11.97 1st Qu.: 15.30
Median :179.70 Median :27.48 Median : 30.90
Mean :176.45 Mean :27.92 Mean : 36.66
3rd Qu.:262.59 3rd Qu.:43.83 3rd Qu.: 54.12
Max. :355.68 Max. :59.52 Max. :136.80
sales
Min. : 1.92
1st Qu.:12.45
Median :15.48
Mean :16.83
3rd Qu.:20.88
Max. :32.40
我们必须理解这些重要的术语和数字代表什么。
- 均值:所有数值之和除以数值总数。在我们的示例数据集中,YouTube 广告的平均预算是 176.45 美元或 176,450 美元。另一方面,脸书的平均广告预算要低得多,为 27.92 英镑或 27,920 美元。
- 中位数:奇数排序列表中的中间数。在偶数列表中,中位数是将排序数据分为上下两半的两个数字的平均值。
- 最小值:这是每个变量的最小数值。
- 最大值:这是每个变量的最大数值。
所以我们已经收集了一些关于数据集的有趣信息。我们知道,该公司在 YouTube 上的平均广告支出高于脸书或报纸广告。
我们可以通过quantile
更深入地了解数据的分布。
> quantile(marketing$facebook)
0% 25% 50% 75% 100%
0.00 11.97 27.48 43.83 59.52
4.让我们开始策划吧!
太好了!我们有了一些关于数据集的初步信息,现在我们可以绘制一些图表。我们将使用ggpubr()
包中的ggplot()
函数。首先,为了演示为什么我们使用ggpubr
包来绘制我们的图形,我们将使用plot()
, R 的内置绘图函数来绘制基本图形。
> plot(marketing$sales, marketing$facebook)
现在,我们将使用ggplot()
。
> ggplot(marketing, aes(x = facebook, y=sales)) + geom_point() + stat_smooth()
脸书 vs 销售
允许以更美观的方式绘制图表。这里,情节是带有“aes”或“美学映射”的营销数据集、、从 facebook 和销售变量导出的、一组点和一个平滑器。
上图(准备出版)显示了销售额和 facebook 变量之间的正线性关系。这表明广告预算的增加会导致公司销售额的增加。出于好奇,我们也可以想象一下销售和 YouTube 广告以及销售和报纸广告之间的关系。
YouTube vs 销售
报纸 vs 销售
有趣的是,虽然sales
和youtube
广告之间的关系也是线性的和正的,但是sales
和newspaper
广告之间的关系却不是——它是一条曲线,实际上在报纸广告的非常低和非常高的水平上开始负斜率。
自变量和因变量之间的相关性如何?相关性分析将确定两个连续变量之间的关系强度。我们必须计算相关系数来执行该分析。相关性取+1 和-1 之间的值。接* 0 的值表示两个变量之间的相关性较弱。
在我们的示例数据集中,如果高销售额伴随着高脸书广告价值,变量将是正相关的,反之亦然。正如我们在图表中已经看到的,销售额和脸书广告之间存在正相关关系。然而,销售和 YouTube 广告之间有更强的正相关性。
销售和报纸广告之间的相关性最弱。这表明销售(Y)的大部分变化是报纸广告(X)无法解释的。为了衡量销售额的显著变化,我们需要一个具有强相关性的解释变量,即 YouTube 或脸书。
> cor(marketing$sales, marketing$facebook)
[1] 0.5762226> cor(marketing$sales, marketing$youtube)
[1] 0.7822244> cor(marketing$sales, marketing$youtube)
[1] 0.7822244
5.简单线性回归
为了在 R 中执行简单的线性回归,我们将使用lm()
。
> model1 = lm(sales ~ facebook, data = marketing)
> model1Call:
lm(formula = sales ~ facebook, data = marketing)Coefficients:
(Intercept) facebook
11.1740 0.2025
5.回归线
现在,让我们为我们的回归生成一个图表。回归线将尝试最小化残差平方和(RSS 或残差平方和)。
> ggplot(marketing, aes(facebook, sales)) +
geom_point() +
stat_smooth(method = lm)
回归概念:
- 拟合值和残差:通常,真实世界的数据不会正好落在回归线上,这就是为什么回归方程包含误差项ϵ.的原因拟合/预测值用.表示如果β用表示,则系数为估计值。统计学区分估计值和已知值,因为估计值是不确定的,而已知值是固定的。误差项ϵ将包含估计值和已知值之间的差异。
- 最小二乘法:在简单回归中,我们会使用 OLS 或普通最小二乘法来估计我们的回归模型与数据的拟合程度。用^表示的系数是使 RSS 最小的值。然而,在多元回归中,我们将使用最大似然来估计模型拟合度。
6.解读我们的回归
估计回归线为:
Sales=11.174+0.2025*Facebook+ϵ
- 截距(β0)为 11.174,可以解释为脸书广告预算值为零时的预测美元销售额。因此,对于等于零的脸书广告预算,我们可以预计销售额为 11.174 * 1000 = 11,174 美元。
- 回归系数(β1)表明,对于等于 1000 美元的脸书广告预算,我们可以预期销售额增加 202.5 单位(0.2025*1000),即
sales = 11.174 + 0.2025*1000 = 56.44 units
。这相当于 213,670 美元的销售额。
7.评估我们的模型
现在我们有了回归模型,我们需要理解如何解释它。仅仅创建一个回归模型是不够的。我们必须检查(a)我们的回归是否有统计学上的显著关系,以及(b)我们的模型是否与数据吻合。很好地拟合数据的回归模型是这样的,X 的变化导致 y 的变化。
在继续之前,我们必须了解标准误差和假设检验。
标准误差:
标准误差衡量我们的系数估计值与我们的响应变量的实际平均值相差多少。标准误差可用于计算置信区间。置信区间量化回归系数的不确定性。通过使用confint()
函数,我们了解到区间[0.12,0.24]有 95%的机会包含β1 的真值。
> confint(model1)
2.5 % 97.5 %
(Intercept) 9.8419062 12.5060253
facebook 0.1622443 0.2427472
假设检验:
标准误差可用于对回归系数进行假设检验。最常见的假设检验是检验零假设和替代假设。
- 零假设(H0):系数等于零,即预测变量和响应变量之间没有关系。
- 替代假设(H1):系数不等于零,即预测变量和响应变量之间存在关系。
为了检验零假设,我们必须确定β1 的估计值是否离零足够远,使得β1 不为零。如果β1 估计值的标准误差足够小,那么即使β1 估计值很小,也会提供反对零假设的证据。
我们如何衡量β1 的估计值离零有多远?t 统计量将测量我们对β1 的估计值偏离 0 的标准偏差的数量。我们需要使用回归模型来拒绝零假设,并证明销售和 facebook 变量之间存在关系。
为了解释我们的线性回归,我们将展示我们模型的统计摘要。为此,我们使用summary()
。
> summary(model1)Call:
lm(formula = sales ~ facebook, data = marketing)Residuals:
Min 1Q Median 3Q Max
-18.8766 -2.5589 0.9248 3.3330 9.8173 Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 11.17397 0.67548 16.542 <2e-16 ***
facebook 0.20250 0.02041 9.921 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1Residual standard error: 5.13 on 198 degrees of freedom
Multiple R-squared: 0.332, Adjusted R-squared: 0.3287
F-statistic: 98.42 on 1 and 198 DF, p-value: < 2.2e-16
8.测试我们模型的准确性
让我们来分解这个摘要输出:
- 残差:如前所述,残差是由^.表示的估计系数残差是实际值和估计值之间的差值。理想情况下,残差的分布应该是对称的。
- 系数:我们的系数β0 和β1 分别代表截距和斜率。我们已经在上一节解释了这些系数。
- 系数标准误差,如上所述,衡量我们的系数估计值与我们的响应变量的实际平均值相差多少。换句话说,它衡量系数估计的准确性。我们的标准误差越接*零越好。
- 系数 t 值测量我们的系数估计值离 0 有多远(以标准偏差表示)。相对于标准误差,较大的 t 值将提供反对零假设的证据,并表明预测变量和响应变量之间存在关系。具有低 t 统计量的预测器可以被丢弃。理想情况下,t 值应大于 1.96,p 值应小于 0.05。
- c 系数— Pr( > t) 代表 p 值或观察到大于 t 的值的概率。p 值越小,我们越有可能拒绝零假设。通常,5%或更低的 p 值是一个很好的分界点。注意符号。在我们的例子中,代码' T9 '与每个评估相关联。三个星号代表高度显著的 p 值。由于销售和脸书广告之间的关系非常重要,我们可以拒绝我们的零假设。
- 剩余标准误差:这衡量我们回归拟合的质量。这是销售变量将偏离真实回归线的平均金额。
- 多重 R 平方:除了 t 统计量和 p 值,这是我们测量回归模型拟合度最重要的指标。r 衡量我们的预测变量(销售额)和我们的回应/目标变量(脸书广告)之间的线性关系。它总是介于 0 和 1 之间。接* 0 的数字表示回归,不能很好地解释响应变量的方差,接* 1 的数字可以解释响应变量中观察到的方差。在我们的例子中,调整后的 R(根据自由度进行调整)是 0.3287——只有 32.87%的销售增长可以用脸书广告来解释。如果我们进行多元回归,我们会发现 R 会随着响应变量数量的增加而增加。(注:YouTube 广告预算与公司销售额的关系更强,R 为 0.612。因此,与脸书广告相比,YouTube 广告可以更好地预测公司销售数据)
- F 统计量:这是一个很好的指标,表明 Y 和 x 之间是否存在关系,我们的 F 统计量离 1 越远,我们的回归模型就越好。在我们的例子中,F 统计量是 98.42,在给定数据集大小(200 个观察值)的情况下,它相对大于 1。在多元回归模型中,F 统计量更相关。
因此,我们需要重点关注的模型拟合的四个关键指标是 t 统计量、p 值、R 和 F 统计量。t 统计量越大,p 值越小。p 值越小,X 和 Y 之间关系的几率越大。R 衡量模型与数据的拟合程度-如果 R 接* 1,则表明 Y 中的大部分变化可以用 X 来解释。F 统计显示了模型的总体显著性。较大的 F 统计量将对应于具有统计显著性的 p 值(p < 0.05)。
8.总结我们的结果
总的来说,我们已经进行了简单的线性回归,也涵盖了一些基本的介绍性统计。这绝不是对营销数据集的全面分析,而只是一个如何执行和解释简单的 r 线性回归的示例。这是一个很好的起点,尤其是在试图理解 t 统计量、p 值和标准误差等重要统计概念的相关性时。在下一篇文章中,我们将继续讨论这个数据集的多元回归。多元回归练*将是迈向全面数据分析项目的一步。
使用神经网络(AI)预测西雅图警察拦截期间逮捕和搜身的可能性
原文:https://towardsdatascience.com/predicting-the-likelihood-of-arrests-and-frisks-during-seattle-police-stops-using-neural-networks-9e8de4360cfb?source=collection_archive---------39-----------------------
面对 2008-2009 年大衰退期间全球经济的不确定性,技术世界继续以惊人的速度前进。苹果推出了 iPhone 3G,这是他们的第二款 iPhone 产品,也是第一款包含现在广受欢迎的 App Store 的产品,它将在 2020 年超过每周$1B 的收入,并独自超越世界上大多数国家的国内生产总值。几年前收购安卓之后,谷歌推出了安卓操作系统,后来占据了手机市场* 75%的市场份额。伴随这些重大技术的是“物联网”的形成,这是全球数十亿设备的集合,这些设备现在连接到互联网,并持续收集和共享数据。物联网诞生于 2008 年或 2009 年,当时联网设备的数量超过了联网人数。
自 2008 年以来,物联网(IoT)的存在在当今世界的各个方面都变得更加明显。从这些物联网设备中创建的大量数据是巨大的 IBM 在 2017 年估计,曾经存在的 90%的数据是在 2017 年之前的两年中创建的!我们每天创建 2.5 万亿字节的数据,随着技术的进步和数字鸿沟的缩小,这个数字还在不断增长。许多组织已经学会了利用他们的数据来快速发展他们的策略,以满足他们的客户的经常不明确的需求。这样做为这些公司维持了巨大的增长和盈利水平——例如,脸书、Alphabet、亚马逊、网飞和沃尔玛,为他们自己的市场价值增加了数十亿美元,并使自己成为世界上最有价值的公司之一。
物联网凸显了数据在当今数字化社会中的重要性。没有采用物联网传感器的组织至少正在改变他们的标准操作程序,以从常规业务流程中捕获数据。由于大规模数据管理和仓储的日益复杂性,以及缺乏这样做的短期激励,许多政府组织在采用和促进这一新的数字时代方面行动迟缓。西雅图的亚马逊和雷蒙德的微软总部所在地金县是一个反驳这种观点的地方政府。金县有一个开放的数据政策,定期将最新数据发布到他们位于 https://data.kingcounty.gov/的公民门户网站。数据主题包括执法、环境质量、交通等。
我使用人工智能(AI)预测西雅图警察局在“特里”拦截(临时拘留或涉嫌犯罪活动的主体)期间进行逮捕或搜身的可能性。西雅图市提供了一个非常棒的数据集,我们将用来训练一个机器学*模型:https://data . Seattle . gov/Public-Safety/Terry-Stops/28ny-9ts 8/data。
数据转换
根据对数据集的检查,并不是该属性中提供的每个属性都有助于进行这些预测。例如,我们可以自信地假设主体 ID 和 Terry Stop ID 号是任意值,与逮捕或搜查主体的决定无关。也就是说,我们将用来完成这项任务的数据集的属性包括在下面。
我们将用来完成这项任务的人工智能概念是一个神经网络。神经网络是受构成动物大脑的生物神经元启发并模仿的计算系统。神经网络接受数字阵列作为输入,然后对这些输入中的每一个应用加权来计算输出。通过使用“反向传播”,神经网络将在训练过程中“学*”,并调整其内部权重,使其越来越接*所需的输出。我将特别使用一个神经网络系统,这个系统是我用微软的编程语言 C#从头开始创建的。NET 框架。我的神经网络使用双曲正切(TANH)激活函数,我有一个具有 50 个隐藏神经元的隐藏层,每层拥有一个偏置神经元,我使用 0.018 的学*率进行反向传播。
神经网络本质上是复杂的矩阵计算器。计算器只接受数值,不接受数据集中存在的字符串(文本)值。这意味着我们需要对数据进行一些翻译,以便计算机能够理解输入。除了军官的出生年份之外,该数据集中提供的所有属性都需要从字符串值转换为数字值。
那么我们如何将这些字符串值转换成数字呢?对于每个属性中的每个唯一值,我们将创建另一个属性,如果原始属性与该唯一值匹配,则包含值 1,如果不匹配,则包含值 0。例如,如果我们要对主题感知种族属性进行转换,并且该属性的唯一值只有“白人”、“黑人”和“西班牙裔”,我们将创建新属性“主题 _ 是 _ 白人”、“主题 _ 是 _ 黑人”和“主题 _ 是 _ 西班牙裔”。对于每条记录,如果受试者感知的种族与这些新属性相匹配,我们将为每条新属性填入 1,如果不匹配,则填入 0。
我将这种转换应用于数据集中的许多属性,以创建新的输入列表,我们将输入到我们的神经网络中:
对于只包含两个唯一值(即性别)的属性,我们不必应用这种转换。对于这些属性,我只是将其中一个值替换为 0,将另一个值替换为 1。对于性别,我将所有“男性”值替换为 0,将所有“女性”值替换为 1。
在我们准备好训练我们的神经网络之前,还有一个转换必须应用。军官年龄字段包含范围从 22 到 69 的值。神经网络将一个激活函数应用到它们的每个内部计算中,以模拟生物神经元的阈值“触发”。TANH(以及许多常用的激活函数)的美妙之处在于,输出将始终在–1 和 1 的范围内,防止内部权重在训练时膨胀到无穷大。
双曲正切函数是非线性的,这意味着输出的梯度(导数)不一致。这种非线性赋予每个神经元“激发或不激发”的特性,这在动物的生物神经元中是可以找到的。此外,激活函数的非线性使得我们的神经网络能够发现数据中的非线性趋势。每个神经元由动作电位(输入值)刺激,然后通过双曲正切函数传递。如果动作电位足够高,神经元就会“点火”,将正数传递给下一层的每一个神经元。这个输出然后被连接神经元和下一层神经元的轴突放大或沉默。
由于双曲正切函数的梯度在–1 和 1 之间最为显著(如上图中的紫色框所示),我们将对数据集的连续属性应用最小-最大归一化,以将其向下“归一化”(拉伸)至–1 和 1 之间。我们需要应用的唯一属性是“军官年龄”属性。
在对上面详细描述的数据进行转换之后,我们现在准备好训练我们的神经网络。我们的数据集包含 13,573 条完整且可用的记录。我决定用 75%的数据来训练我们的模型,剩下的 25%用来测试我们神经网络预测的准确性。在初始化了具有 38 个输入节点、50 个隐藏节点和 2 个输出节点的新神经网络之后,我们准备好训练我们的模型。像这样大规模的神经网络训练可能是计算密集型的,需要一些时间,所以我将工作负载外包给了微软 Azure 的计算优化 FSV2 虚拟机的一个实例,该虚拟机由英特尔的至强白金处理器提供支持。
下面是我们正在使用的神经网络图。原谅我的小文本,但它必须小,以适应。
10,180 次训练迭代和 38 小时后,我们有了一个完全训练好的神经网络,可以做预测了。大约有 3393 个预测,所以我不能在这里全部显示出来。但是,以下是对结果的高级分析。
预测精度
神经网络正确预测逮捕了吗?
神经网络计算了每个事件记录中发生逮捕的概率。对于网络预测最有可能逮捕的 100 条记录,在这 100 起事件中有 47 起真的发生了逮捕。相反,网络预测的 100 条记录中最不可能被逮捕,事实上,其中 73 条没有导致逮捕。结合这两个指标,这意味着在前 200 个最极端的案例中,预测正确 120 次,或成功率为 60%。比扔硬币要好,但还不足以非常自信!这是否意味着我们的神经网络失败了?不一定。如果我们后退一步,我们可以认识到输入的数据可能与逮捕的机会没有很大的相关性。我敢肯定,有更多的逮捕发生的决定因素没有在这个数据集中进行测量——对象的举止,药物和酒精的影响,交谈中的尊重,以及以前的犯罪历史都是警察在拦截中可能的决定因素,没有作为输入纳入我们的模型。因此,由于数据的性质,我们可能要求我们的神经网络执行一项不可能的任务。
神经网络是否正确预测了搜身?
与逮捕类似,我们的神经网络也计算了每起事件发生搜身的概率。对于网络预测最有可能被搜身的 100 条记录,实际上有 82 条被搜身了。对于网络预测最不可能被逮捕的 100 条记录来说,事实上有 87 条记录没有被搜身,而不是被 T2 搜身。总的来说,这意味着我们的模型在 200 个案例中有 169 个是正确的,或者说成功率大约为 85%。这相对于停搏预测的准确性是一个很大的改进,并且足够高,让我相信我们的模型在数据中发现了很强的相关性。为什么不是 100%呢?请记住,这是不完善和不完整的信息。这并没有(也可能永远不会)完全捕捉到在每个警察停车时发生的每一件事。因此,期望从我们提供的有限数据中获得*乎完美的预测精度是不合理的。理论上,随着我们提供更多相关数据,这种准确性应该会提高。
现在将我们的范围改为整个测试数据集,神经网络在 66%的情况下正确预测了逮捕,在 75%的情况下正确预测了搜查。虽然这些结果并不完美,但它们确实表明我们的神经网络能够从数据的相关性中提取和学*。那么神经网络是怎么做到的呢?让我们进一步分析结果,尝试阐明相关性。
属性关联
武器出现
武器的存在如何影响逮捕或搜身的预测?在我们的网络最有信心逮捕的前 100 个案例中,有 70 个案例确实有武器。在我们的网络最有信心进行搜身的前 100 个场景中,武器出现了 94 次。另一方面,在最不可能被逮捕或搜身的 100 个案例中,没有一个案例带有武器。这非常表明,这种输入是神经网络预测结果的强有力指标。
最有可能搜身时携带武器的案件有 94 起,最有可能逮捕时携带武器的案件有 70 起,这一事实表明,武器的存在与搜身而不是逮捕更有关联。这可能与常识相反,但实际上可能是有道理的——也许如果有武器,搜身几乎总是会发生,但考虑到武器可能是合法拥有的,并不总是导致逮捕。
官龄
军官的年龄如何影响我们的预测?以下是结果:
最有可能被捕的平均年龄是 29.3 岁,而最不可能被捕的平均年龄是 38.8 岁。这是一个巨大的差异!这意味着我们的神经网络已经发现了警官年龄和被捕几率之间的相关性,并表明年轻警官比年长警官更有可能实施逮捕。也许年纪较大的警官成熟到不需要进行逮捕,或者积极地试图完全避免这种情况。也许年纪较大的官员通常更多地担任管理角色,因此不太可能实施逮捕。
最有可能搜身和最不可能搜身的平均年龄非常相似——29.9 岁和 28.2 岁,所以不足以进行深入研究和推断。
军官性别
军官的性别如何影响我们的预测?
这里没有大的区别,但有些值得注意。如果警察的性别是男性而不是女性,被逮捕和搜身的可能性更大。尤其是考虑到被捕的可能性。
主题性别
受试者的性别如何影响我们的预测?
我们的神经网络已经注意到了这种明显的相关性。无论是最有可能逮捕的案件还是最有可能搜身的案件,研究对象都是 100%的男性。当观察最不可能逮捕和最不可能搜身的案件时,这一比率变化很大。最不可能被逮捕的案件中只有 77%是男性(23%是女性),而最不可能被搜身的案件中,男性比例骤降至 28%(72%是女性)。
最有可能搜身和最不可能搜身的男女比例发生了巨大变化。最有可能的情况下是 100%男性,最不可能的情况下是 72%女性!为什么会这样?我们可以做出许多假设,并用数据来检验每一个假设,但我的最佳猜测是,这是因为由于潜在的性骚扰反弹或诉讼,警察不太可能对女性进行搜身。
这是否意味着官员在工作中有意识或无意识的偏见?也许吧!但是匆忙得出这样的结论是危险的…这可能是许多事情的结果。从理论上讲,这也可能是男性从事的活动的违法程度比女性平均水平更严重的结果。
学科年龄
受试者的年龄如何影响我们的预测?让我们来看看结果:
最有可能被捕:
最有可能搜身的:
最不可能被逮捕:
最不可能搜身的:
请注意,在被标记为最有可能被捕的前 100 个案例中,有 66 个案例的年龄在 26 至 35 岁之间。这意味着我们的神经网络表明这个年龄范围特别容易被逮捕。再问一次,这是否意味着西雅图的警察对这个年龄范围有偏见?也许,但不一定。这可能是该年龄段的人从事的非法活动比其他年龄段的人多得多的结果。
另一方面,最不可能被逮捕的人有更多的年轻和年长的人,这表明这些年龄的人确实不太可能被逮捕。类似的趋势也适用于弗里斯克的预测。
军官竞赛
军官的种族作为一个属性如何影响我们模型的预测?
最有可能被捕:
最有可能被搜身的:
最不可能被逮捕:
最不可能搜身:
这里的比率变化不大,不能提供有用的信息来推断模式或得出结论。
学科竞赛
受试者的种族如何影响我们的预测?
最有可能被捕:
最有可能搜身的:
最不可能被逮捕:
最不可能搜身的:
与警官的种族相似,受试者的种族似乎不是逮捕或搜身结果的有影响的决定因素,但也许在某些地区有一些小的关联。然而,请注意最有可能搜身的案例和最不可能搜身的案例之间的组合变化。最不可能搜身的案件非常严重地偏向黑人。为什么警察比其他种族的警察更少对黑人搜身?没有办法用我们现有的数据来判断,但神经网络现在已经警告我们这一趋势——如果我们有这些资源可供支配,我们可以选择用其他方法和数据来进一步挖掘。
最有可能和最不可能的逮捕组合非常相似。这是不是意味着我们的神经网络坏了?不,这表明这一指标与逮捕或搜身的可能性之间没有很大的关联。
星期几
星期几如何影响预测?
最有可能被逮捕:
最有可能被搜身的是:
最不可能被逮捕:
最不可能搜身的是
除了周二被捕的可能性最小之外,这里似乎没有任何值得注意的趋势。
一天中的时间
我们把一天的时间分成四个不同的组:午夜到早上 6 点,早上 6 点到中午,中午到下午 6 点,下午 6 点到午夜。我们完全可以把它分成 24 小时,甚至更长时间,但是这样效率很低,而且可能不会有什么深刻的发现。训练我们的神经网络需要更多的时间,所以我妥协了,把一天中的时间分成四组。以下是结果:
最有可能被捕:
最有可能搜身的:
最不可能被捕:
最不可能搜身的:
结果表明了你的预期:逮捕和搜身更有可能发生在深夜或凌晨。
辖区
最后,辖区如何影响我们神经网络的预测?数据集的 terry 停靠点出现在五个不同的区域:北部、东部、南部、西部和西南部。
最有可能被捕:
最有可能搜身的:
最不可能被逮捕:
最不可能搜身的:
这里最清楚的指标在于逮捕数据:请注意,我们的网络预测的最有可能逮捕的前 100 起案件中有 64%发生在西区。进一步重申这一点,在我们的神经网络最有信心逮捕不会不会发生的前 100 条记录中,北部似乎是一个相对安全的区域,84%的记录在北部,而西部没有记录发生!
这让我们清楚地看到西雅图的哪些选区可能是安全的,哪些选区可能会变得更加危险。从神经网络做出的预测中,我们可以推断,与西部或者南部相比,北部和西南部是城镇中相对安全的部分。
但是这个假设有保证吗?绝对不行!也许数据是扭曲的——可能西雅图警察局有更多的警察在某些地区巡逻,比如西部,这就是那里有更多逮捕的原因。然而,这一反驳点可能被证明是错误的,因为北部是可能发生搜身的地区之一,这表明那里确实有警察存在。
总结
如前所述,我们的神经网络正确预测逮捕的准确率为 66%,正确预测搜身的准确率为 75%。虽然这些数字并不完美,但它们比扔硬币要好,表明我们的模型能够发现并学*输入数据与逮捕或搜身可能性之间的相关性。
这对我们有什么用?回想起来,这种学*模型可以帮助警察或政府官员发现数据中的异常和趋势。这些见解可用于帮助规划资源分配。例如,如果神经网络模型发现一种趋势,即逮捕很可能发生在城镇的特定地区,在一周的特定日期,在一天的特定时间,官员可以将更多的警力资源分配到该地区,以在犯罪活动发生之前主动预防犯罪活动。在人工分析的监督下,像这样的多层趋势通常很难发现;多亏了神经网络,我们现在可以揭示这些趋势。
我为处理这个数据集而创建的神经网络花了大约 38 个小时来训练 10,180 个例子,或者每次迭代大约 13.5 秒。训练时间长的原因是计算密集型顺序反向传播算法,该算法调整模型的内部权重以更好地逼*每个输出。幸运的是,正向传播(要求模型做出预测)要快得多。即使比我们在这里使用的模型更深的模型也可以在不到十分之一秒的时间内做出预测,即使是在像 5 美元的 Raspberry Pi Zero 这样的低功耗廉价硬件上。
在一个神经网络被创建并在至少性能良好的硬件上训练之后,该模型可以被部署到低性能硬件上,这样它的预测能力就可以在“边缘”(前线)使用——通过物联网设备在警察手中使用。也许在未来,警察将佩戴一系列小型物联网传感器,这些传感器可以实时捕获比该数据集中列出的更多的数据:对话对话、面部表情图像、与对象的接*程度等等。这些传感器可以通过应用情绪分析(可能也由另一个神经网络驱动)来判断对话的情绪,并将其对对话中紧张程度的估计作为输入传递给我们的模型。计算机视觉技术,如微软的 Azure Face 认知服务,可以分析实时图像,并对军官和受试者的压力水平进行预测,并将这些作为输入传递给我们的模型。你甚至可以给警察配备心率监测器或皮质醇监测设备来检测压力或不适,并以此作为输入。
所有这些输入都可以输入到每个官员佩戴的小型离散物联网设备中。这种设备将使用最新版本的经过训练的神经网络,随着情况的发展,不断预测逮捕或搜身的可能性。如果逮捕的可能性超过了预定的阈值,连接的物联网设备可以自动向该地区的另一名官员发出支持信号。军官们将不再需要自己通过无线电寻求帮助,这可能会通过诱导受试者的“战斗或逃跑”反应来使局势进一步升级,并且还会使他们自己处于这样做的潜在反弹的危险中。
随着物联网传感器在各个经济部门的各个业务领域变得越来越普遍,高质量数据的可用性将会增加。幸运的是,希望参与这场数据驱动的人工智能革命的组织可以通过价格合理的现成技术来实现。这样做将极大地改进学*模型,因为引入了高度相关的数据,增强了模型的预测准确性。我鼓励任何对企业数字化转型感兴趣的组织领导者进行投资——与未来的收益或成本节约相比,今天的成本可能微不足道。
预测网址的恶意性
原文:https://towardsdatascience.com/predicting-the-maliciousness-of-urls-24e12067be5?source=collection_archive---------11-----------------------
创建用于分离恶意和良性 URL 的特征向量
在本文中,我们将逐步开发一个用于识别恶意 URL 的简单特性集表示。我们将为 URL 创建特征向量,并使用这些向量来开发用于识别恶意 URL 的分类模型。为了评估这些特征在区分恶意网址和良性网址方面有多好,我们建立了一个基于决策树的机器学*模型来预测给定网址的恶意性。
恶意网站是网络安全中众所周知的威胁。它们是在线传播病毒、蠕虫和其他类型恶意代码的有效工具,并且是大多数网络攻击的 60%以上的罪魁祸首。恶意 URL 可以通过电子邮件链接、文本消息、浏览器弹出窗口、页面广告等方式发送。这些 URL 可能是指向可疑网站的链接,或者很可能嵌入了“可下载内容”。这些嵌入的下载可能是间谍软件、键盘记录器、病毒、蠕虫等。因此,及时检测和缓解恶意代码在其网络中的传播已成为网络防御人员的当务之急。恶意 URL 检测器的各种技术以前主要依赖于 URL 黑名单或签名黑名单。这些技术大多提供“事后”解决方案。为了提高恶意 URL 检测方法的及时性和抽象性,机器学*技术正日益被接受。
为了开发机器学*模型,我们需要一个特征提取框架来表征 URL 或将 URL 转换为特征向量。在本文中,我们将收集已知恶意网址和已知良性网址的样本。然后,我们开发一个指纹识别框架,并为样本中的所有 URL 提取一组给定的【M】特征。我们通过开发一个具有这些特征的简单预测模型来测试这些特征在区分恶意 URL 和良性 URL 方面的有效性。最后,我们测量模型预测恶意网址的能力,作为区分恶意网址和良性网址的特征的有效性。
下图是本文中方法流程的概述。
分析处理
数据
我们从两个来源收集数据:Alexa 1000 强网站和 phishtank.com。从 Alexa 的前 1000 个网站中抓取了 1000 个假定的良性 URL,从phishtank.com中抓取了 1000 个可疑的恶意 URL。由于 virustotal API 的限制率,我们随机抽取了 500 个假定的良性 URL 和 500 个假定的恶意 URL。然后通过病毒扫描这些网址。检测到 0 个恶意内容的 URL 被标记为良性(b_urlX),检测到至少 8 个恶意内容的 URL 被标记为恶意(m_urlX)。我们将每次扫描的 JSON 结果转储到相应的文件‘b _ urlx . JSON’、‘m _ urlx . JSON’中。您可以在这里找到这些文件。
from requests import get
from os import listdir
import pandas **as** pd
import numpy **as** np
from pandas.io.json import json_normalize
import seaborn **as** sns
import matplotlib.pyplot **as** plt
import math
from datetime import datetime
plt**.**rcParams["figure.figsize"] **=** (20,20)
处理应用编程接口速率限制和 IP 阻塞
为了确认示例中的恶意 URL 是恶意的,我们需要向 VirusTotal 发送多个请求。病毒扫描提供多个病毒扫描引擎的汇总结果。此外,我们通过(Shodan)[shodan.io]传递 URL。Shodan 是所有连接到互联网的设备的搜索引擎,提供基于服务的 URL 服务器功能。VirusTotal 和 Shodan 目前的 API 速率限制分别是每分钟 4 个请求和每个 API 密钥每月至少 10,000 个请求。虽然对数据的 URL 请求数量在 Shodan API 请求限制之内,但事实证明,病毒总数有点困难。这是通过创建几个虚拟磁带库应用编程接口密钥(最多 4 个)并在每个请求中随机采样来解决的。除了限制 API 请求的数量之外,在短时间内发送多个请求还会导致来自 VT 和 Shodan 服务器的 IP 阻塞。我们编写了一个小爬虫,从https://free-proxy-list.net/获取最新的精英 IP 地址集,并为每个请求创建一个新的代理列表,因为自由代理的寿命非常短。除了 IP 池之外,我们还使用 Python 的 FakeUserAgent 库在每个请求上切换用户代理。
最后,对于每个请求,使用新的代理和用户代理,我们可以每分钟发送 16 个请求,而不是之前的 4 个。每个请求都有以下请求参数:
- 1 病毒总密钥:来自 VT API 密钥池的样本。
- 1 Shodan 密钥:来自 Shodan API 密钥池的示例。
- 1 IP:向https://free-proxy-list.net/发送请求,获取最新的免费精英代理。
- 1 用户代理:Python 的可用用户代理示例(假冒用户代理)[https://pypi . org/project/假冒用户代理/]
Shodan 和 VT 的扫描产生了以下数据集。从 shodan 中,我们提取了以下特征:
- numServices:主机上运行的服务(开放端口)总数
- robotstxt:网站是否启用了 robots txt
扫描后的最终数据集在这里可用。您可以下载这些数据并运行您的分析。
指纹 URL(用于恶意软件 URL 检测的特征 URL)
目标是提取 URL 特征,这些特征对于区分恶意 URL 和良好 URL 非常重要。首先,让我们看看一个 URL 的结构中的相关部分。
典型的 URL
URL(统一资源定位器的缩写)是一种引用,它指定了 web 资源在计算机网络上的位置以及检索它的机制。如下图所示,URL 由不同的组件组成。该协议或方案规定了如何(或需要什么)传输信息。主机名是计算机网络上计算机 IP 地址的人类可读的唯一引用。域名服务(DNS)命名层次结构将 IP 地址映射到主机名。被攻破的网址被用来实施网络攻击。这些攻击可能是任何或多种形式的网络钓鱼电子邮件、垃圾邮件和驾车下载。
关于域名,所有者购买人们觉得更容易记住的域名。所有者通常希望他们提供的品牌、产品或服务的名称是特定的。URL 的这一部分(域)一旦设置就不能更改。恶意域名所有者可能会选择多个廉价域名,例如“xsertyh.com”。
免费 URL 参数是 URL 的一部分,可以通过更改来创建新的 URL。这些包括目录名、文件路径和 URL 参数。这些免费的 URL 参数通常被攻击者操纵来创建新的 URL、嵌入恶意代码并传播它们。
有许多用于恶意 URL 检测的技术,两种主要技术是 a)黑名单技术,和 b)机器学*技术。黑名单包括维护已知恶意域的数据库,并将新 URL 的主机名与数据库中的主机名进行比较。这是一个“事后”问题。它将无法检测新的和看不见的恶意网址,只有当它被认为是来自受害者的恶意网址时,它才会被加入黑名单。另一方面,机器学*方法提供了一种可跨平台推广且独立于已知签名的先验知识的预测方法。给定恶意和良性恶意软件样本的样本,ML 技术将提取已知好的和坏的 URL 的特征,并概括这些特征以识别新的和看不见的好的或坏的 URL。
URL 指纹识别过程针对 3 种类型的 URL 功能:
- URL 字符串特征:源自 URL 字符串本身的特征。
- URL 域特征:URL 域的域特征。其中包括 whois 信息和 shodan 信息。
- 页面内容特征:从 URL 的页面提取的特征(如果有的话)
下表显示了提取的所有特征的摘要:
URL 的特征向量摘要
运行上面的脚本会产生以下带有 23 个特征的数据。我们将把整数、布尔值和对象列名放在不同的列表中,以便于数据访问。
objects **=** [i **for** i **in** data**.**columns **if** 'object' **in** str(data**.**dtypes[i])]
booleans **=** [i **for** i **in** data**.**columns **if** 'bool' **in** str(data**.**dtypes[i])]
ints **=** [i **for** i **in** data**.**columns **if** 'int' **in** str(data**.**dtypes[i]) **or** 'float' **in** str(data**.**dtypes[i])]
移除高度相关的要素
最线性分析假设预测变量之间不存在多重共线性,即预测要素对不得相关。这种假设背后的直觉是,没有额外的信息添加到具有多个相关特征的模型中,因为相同的信息被其中一个特征捕获。
多重相关特征也表示数据中的冗余特征,删除它们是数据降维的良好开端。通过移除相关特征(仅保留一组观察到的相关特征),我们可以解决预测值之间的特征冗余和共线性问题。
让我们创建一个简单的相关性网格来观察恶意和良性 URL 的派生特征之间的相关性,并删除一个或多个高度相关的特征。
corr **=** data[ints**+**booleans]**.**corr()
*# Generate a mask for the upper triangle* mask **=** np**.**triu(np**.**ones_like(corr, dtype**=**np**.**bool))*# Set up the matplotlib figure* f, ax **=** plt**.**subplots(figsize**=**(20, 15))*# Generate a custom diverging colormap* cmap **=** sns**.**diverging_palette(220, 10, as_cmap**=**True)*# Draw the heatmap with the mask and correct aspect ratio* sns**.**heatmap(corr, mask**=**mask, cmap**=**cmap, vmax**=**.3, center**=**0,
square**=**True, linewidths**=**.5, cbar_kws**=**{"shrink": .5}, annot**=**True)
互相关系数
然而,我们并不希望删除所有相关的变量——只删除那些相关性非常强、不会给模型增加额外信息的变量。为此,我们为观察到的正相关和负相关定义了某个“阈值”(0.7)。
我们看到大部分高度相关的特征都是负相关的。例如,在 URL 中的字符数和 URL 的熵之间存在 0.56 的负相关系数,这表明较短的 URL 具有
这里我们将创建一个函数来识别和删除多个相关特征中的一个。
预测 URL 的恶意性(决策树)
建模根据以前观察到的数据模式构建了解释数据的蓝图。建模通常是预测性的,因为它试图使用这种开发的“蓝图”来预测基于过去观察的未来或新观察的值。
基于提取的特征,我们想要最好的预测模型来告诉我们一个看不见的 URL 是恶意的还是良性的。因此,我们寻求有用功能的独特组合,以准确区分恶意和良性 URL。我们将经历两个阶段,特征选择,其中我们只选择对预测目标变量有用的特征,并用决策树建模以开发恶意和良性 URL 的预测模型。
特征选择
什么样的变量对识别一个网址是“恶意的”还是“良性的”最有用?在计算上,我们可以通过测试哪些变量“改善”或“未能改善”预测模型的整体性能,来自动选择哪些变量最有用。这个过程被称为“特征选择”。特征选择还有助于降低数据的维数,解决计算复杂性和模型性能的问题。特征选择的目标是获得原始数据的有用子集,该子集以不丢失有用信息的方式预测目标特征(一起考虑所有预测)。尽管特征选择超出了简单的相关性消除,但是对于本文,我们将我们的特征选择方法限制为仅仅保留这些特征。让我们创建一个只包含不相关要素的原始数据子集。
predictor_columns **=** data2**.**columns
d **=** data2[predictor_columns]
x, y **=** d[predictor_columns], data['vt_class']
我们只保留对模型有独特贡献的特征。我们现在可以开始用原始样本的 70%和这 14 个特征来开发模型。我们将保留 30%的样本来评估模型在新数据上的性能。
- 数字服务
- 熵
- 数字
- 数字图表
- 体长
- 数字标题
- 数字图像
- 数字链接
- 每日业务报告(Daily Service Report)
- data-storageequipment 数据储藏设备
- sscr
- 小触须(同 small bristles)
- 机器人
- 哈希 Http
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test **=** train_test_split(x, y, test_size **=** 0.3, random_state **=** 100)
决策树
from sklearn import tree
from sklearn.metrics import accuracy_scorefrom sklearn.externals.six import StringIO
from IPython.display import Image
from sklearn.tree import export_graphviz
import pydotplus
有多种机器学*算法(分类)算法可用于识别恶意 URL。在将 URL 转换成代表性的特征向量之后,我们将“恶意 URL 识别问题”建模为二元分类问题。二元分类模型为只有两种结果“恶意”和“良性”的类训练预测模型。批量学*算法是在以下假设下工作的机器学*算法:
- the entire training data is available before model development and
- the target variable is known before the model training task.
批处理算法是理想和有效的,因为它们是可解释的区分学*模型,使用训练数据点之间的简单损失最小化。决策树是机器学*中的一种批量学*算法。
在决策分析中,决策树是模型得出某些结论的决策过程的可视化表示。决策树背后的基本思想是试图理解什么因素影响类成员,或者为什么一个数据点属于一个类标签。决策树清楚地显示了构成类成员的条件。因此,它们是决策过程的可视化表示。
决策树通过将数据集分解成越来越小的部分来构建预测模型。分割子集的决定基于最大化分割的信息增益或最小化分割的信息损失。从根节点(没有不确定性的最纯粹的特征)开始,通过基于子集的纯粹性创建各种叶节点来形成树。
在这种情况下,决策树将解释每个特征的类别边界,以将 URL 分类为恶意或良性。构建决策树时,有两个主要因素需要考虑:
`- a) What criteria to use in splitting or creating leaf nodes and
- b) tree pruning to control how long a tree is allowed to grow to control the risk of over-fitting.`
决策树算法的 criteria 参数指定控制什么标准(Gini 或熵),而 max_depth 参数控制允许树增长多远。基尼系数是指如果我们根据分支中的分布随机选择一个标签,随机样本被错误分类的概率。熵是对信息(或者说缺乏信息)的一种度量。
不幸的是,由于事先不知道标准和树深度的正确组合,我们将不得不反复测试这两个参数的最佳值。我们针对两个标准测试了 50 次迭代的 max_depth,并可视化了模型准确度分数。
参数调谐
似乎最好的模型是最简单的模型,基尼指数和最大深度为 4,样本外准确率为 84%。此外,最大化熵似乎不会产生好的结果,这表明添加到模型中的新参数不一定给出新的信息,但是可以产生改进的节点概率纯度。因此,我们可以用 max_depth = 4 和 Gini 标准来拟合和可视化该树,以识别哪些特征在分离恶意和良性 URL 中最重要。
建立模型…
*###create decision tree classifier object* DT **=** tree**.**DecisionTreeClassifier(criterion**=**"gini", max_depth**=**4)*##fit decision tree model with training data* DT**.**fit(X_train, y_train)*##test data prediction* DT_expost_preds **=** DT**.**predict(X_test)
想象这棵树…
dot_data **=** StringIO()
export_graphviz(DT, out_file**=**dot_data,
filled**=**True, rounded**=**True,
special_characters**=**True,feature_names**=**X_train**.**columns, class_names**=**DT**.**classes_)
graph **=** pydotplus**.**graph_from_dot_data(dot_data**.**getvalue())
Image(graph**.**create_png())
树
预测模型的准确性对 max_depth(树修剪)和分裂质量标准(节点分裂)的参数调整非常敏感。这也有助于实现最简单的简约模型,防止过度拟合,并在看不见的数据上表现得一样好。这些参数特定于不同的数据问题,最好测试不同参数值的组合。
该模型显示,恶意 URL 的脚本与特殊字符比率(sscr)较低,URL 字符相对更“有序”或更单调。此外,恶意网址的域名可能在 5-9 个月前已经过期。我们还知道“恶意广告”的问题,即骗子获得过期合法域名的所有权,以分发可下载的恶意代码。最后,大概良性 URL 最显著的特点就是长寿。他们似乎缓和了 HTML 正文内容中脚本与特殊字符的比例,使域名寿命延长到 4-8 年。
用深度学*预测一首歌的音乐情绪。
原文:https://towardsdatascience.com/predicting-the-music-mood-of-a-song-with-deep-learning-c3ac2b45229e?source=collection_archive---------7-----------------------
使用 Python 上的 Keras 和 Tensorflow 库,通过神经网络模型预测音乐曲目情绪的酷方法。
乌列尔·索伯兰斯在 Unsplash 上拍摄的照片
音乐是一种表达我们情感的强大语言,在很多情况下,它被用来治疗我们生活中的困难时刻。情绪和心情可以很容易地反映在音乐中,当我们做运动时,我们倾向于听充满活力的音乐,同样,当我们焦虑或疲劳时,一首优美放松的歌曲可以帮助我们平静下来。这就是为什么我试图弄清楚分类模型如何帮助确定特定曲目的情绪。
在这篇文章中,我将展示并解释我如何使用一个用于分类的多类神经网络和 Spotify 提供的一个很酷的数据集来实现这个想法。所以不要再说了,让我们开始工作吧!!。
*我的 Github 存储库中的全部代码、脚本、笔记本和数据(点击此处)
所需工具:
- 熊猫和 Numpy 进行数据分析。
- Keras 和 Tensorflow 构建深度学*模型。
- Sklearn 验证模型。
- Seaborn 和 Matplotlib 绘制一个漂亮的图形。
- Spotipy Python 库(点击这里了解更多信息)。
- Spotify 凭证访问其 API 和数据采集(点击此处了解更多信息)。
Spotify 音频功能:
Spotify 使用一系列不同的功能对歌曲进行分类。我从 Spotify 网页复制/粘贴信息。
- 声音:一种置信度,从 0.0 到 1.0,表示音轨是否是声音的。1.0 表示音轨是声学的高置信度。
- 可跳舞性:可跳舞性描述了一个曲目在音乐元素组合的基础上适合跳舞的程度,包括速度、节奏稳定性、节拍强度和整体规律性。值 0.0 最不适合跳舞,1.0 最适合跳舞。
- 能量:能量是一个从 0.0 到 1.0 的度量,代表强度和活动的感知度量。通常,高能轨道感觉起来很快,很响,很嘈杂。例如,死亡金属具有高能量,而巴赫前奏曲在音阶上得分较低。对该属性有贡献的感知特征包括动态范围、感知响度、音色、开始速率和一般熵。
- 乐器性:预测音轨是否不包含人声。“Ooh”和“aah”在这种情况下被视为乐器。Rap 或口语词轨道明显是“有声的”。乐器度值越接* 1.0,轨道不包含人声内容的可能性就越大。高于 0.5 的值旨在表示乐器轨道,但随着该值接* 1.0,置信度会更高。
- 活跃度:检测录音中是否有观众。较高的活跃度值表示音轨被现场执行的概率增加。高于 0.8 的值很有可能表示该音轨是实时的。
- 响度:轨道的整体响度,以分贝(dB)为单位。响度值是整个轨道的平均值,可用于比较轨道的相对响度。响度是声音的质量,是与体力(振幅)相关的主要心理因素。值通常在-60 和 0 db 之间。
- 语速:语速检测音轨中是否存在口语单词。越是类似语音的录音(例如脱口秀、有声读物、诗歌),属性值就越接* 1.0。高于 0.66 的值描述可能完全由口语单词组成的轨道。介于 0.33 和 0.66 之间的值描述可能包含音乐和语音的轨道,可以是分段的,也可以是分层的,包括说唱音乐。低于 0.33 的值很可能代表音乐和其他非语音类轨道。
- 配价:从 0.0 到 1.0 的一种量度,描述音轨所传达的音乐积极性。高价曲目听起来更积极(例如,快乐、愉快、欣快),而低价曲目听起来更消极(例如,悲伤、沮丧、愤怒)。
- 速度:轨道的整体估计速度,单位为每分钟节拍数(BPM)。在音乐术语中,速度是给定作品的速度或步调,直接来源于平均节拍持续时间。
1.解释和分析数据:
为了获得数据,我必须使用 Spotipy 库创建一系列函数。这个库有助于 Spotify 服务自动下载更多关于播放列表、歌曲、艺术家音乐等的技术信息(如上所述)。出于本文的主要目的,我不会提及我是如何获得数据的,但我会解释数据由什么组成。
您可能知道,分类问题使用带标签的数据,所以我必须创建这些标签。我决定创建 4 个类别来标记曲目,这些类别是“充满活力的”、“冷静的”、“快乐的”和“悲伤的”。我根据下面这篇文章选择这些类别,这篇文章解释了按情绪对音乐进行分类的最佳方式。
[## 音乐情绪分类
本文将涵盖使用各种 DSP 和音乐理论技术分析音乐,包括节奏,和声…
sites.tufts.edu](https://sites.tufts.edu/eeseniordesignhandbook/2015/music-mood-classification/)
然后,我在 Spotify 上搜索了一些基于这 4 个标签的不同音乐曲目的播放列表(每个标签 200 首曲目),最后,我将所有这些曲目连接到由每个情绪标记的主数据框中。你可以在我的 GitHub 知识库上查看这个数据集(点击这里)
主要数据有 800 行和 18 列,但是为了信息还原的目的,我决定使用长度、舞蹈性、声音性、能量、I 乐器性、活跃度、化合价、响度
我通过标签对数据框进行分组,计算轨迹特征的平均值。我得到了以下结果:
使用平均统计分组的数据帧。(图片由作者提供)
做这个简单的分析,我很快注意到最流行的歌曲是快乐的,悲伤的歌曲往往有很长的长度,充满活力的歌曲节奏最快,平静的歌曲往往是有声的。
2.构建模型:
2.1-数据预处理:
为了标准化特征,我使用了最小最大缩放器来缩放范围为[0,1]的值,并保持原始分布的形状。我还对 4 个标签进行了编码,因为神经网络使用数值来训练和测试。最后,我将数据分成 80%用于训练和 20%用于测试。
*#Libraries to pre-process the variables*
from sklearn.preprocessing import LabelEncoder,MinMaxScaler
from sklearn.model_selection import train_test_split
我用来处理数据的代码:
*#Define the features and the target*
col_features = df.columns[6:-3]
X = df[col_features]
Y = df['mood']*#Normalize the features*
X= MinMaxScaler().fit_transform(X)*#Encode the labels (targets)*
encoder = LabelEncoder()
encoder.fit(Y)
encoded_y = encoder.transform(Y)*#Split train and test data with a test size of 20%*
X_train,X_test,Y_train,Y_test = train_test_split(X,encoded_y,test_size=0.2,random_state=15)
标签编码如下:
标签及其编码。(图片由作者提供)
2.2 创建模型:
为了建立这个模型,我使用了 Keras 库,这个库被设计成能够快速实验深度神经网络,专注于用户友好。我的主要目标是将轨迹分为 4 类情绪(平静、精力充沛、快乐和悲伤),因此我的模型由一个多类神经网络组成,输入为 10 个特征, 1 层有 8 个节点,4 个输出有输出层。我还需要使用一个分类器作为估计器,在这种情况下,分类器是 KerasClassifier ,它将我之前使用定义的神经网络模型创建的函数作为参数。激活函数对应于一个整流线性单元** ( Relu) ,损失函数是一个 L 逻辑函数和亚当梯度下降算法是优化器。**
*#Libraries to create the Multi-class Neural Network*
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasClassifier
from keras.utils import np_utils*#Import tensorflow and disable the v2 behavior and eager mode*
import tensorflow as tf
tf.compat.v1.disable_eager_execution()
tf.compat.v1.disable_v2_behavior()
- ****重要提示:我禁用了 TensorFlow 的急切执行和 v2 行为,因为我一直试图理解和学*库在那些模式下是如何工作的(抱歉我是 Tensorflow 的新手呵呵)。
我用来建立神经网络的代码:
*#Function that creates the structure of the Neural Network*
def base_model():
*#Create the model*
model = Sequential()*#Add 1 layer with 8 nodes,input of 4 dim with relu function*
model.add(Dense(8,input_dim=10,activation='relu'))*#Add 1 layer with output 3 and softmax function*
model.add(Dense(4,activation='softmax'))*#Compile the model using logistic loss function and adam * optimizer, accuracy correspond to the metric displayed
model.compile(loss='categorical_crossentropy',optimizer='adam',
metrics=['accuracy'])
return model*#Configure the estimator with 300 epochs and 200 batchs. the build_fn takes the function defined above*.
estimator = KerasClassifier(build_fn=base_model,epochs=300,
batch_size=200)
3.3 评估模型:
使用 K 倍交叉验证我评估了使用训练数据的估计器。拆分的次数是 K= 10 洗牌所有的值。
*#Library to evaluate the model*
from sklearn.model_selection import cross_val_score, KFold
我用来评估模型的代码:
*#Evaluate the model using KFold cross validation*kfold = KFold(n_splits=10,shuffle=True)results = cross_val_score(estimator,X,encoded_y,cv=kfold)print("%.2f%% (%.2f%%)" % (results.mean()*100,results.std()*100))
模型的精确度是每个折叠精确度的平均值,在本例中,精确度为 72.75 %。
3.4 训练模型:
是时候训练模型了!所以让我们开始编码:
*#Train the model with the train data*
estimator.fit(X_train,Y_train)*#Predict the model with the test data*
y_preds = estimator.predict(X_test)
需要特别提到的是,模型是用 640 个样本(主数据的 80%)训练的。
模型训练时最后一个时期的一些输出。
历元、时间、损失和训练过程中模型的准确性。(图片由作者提供)
3.多类神经网络的精度;
最后,为了评估模型的准确性,我使用 Seaborn 库和 Matplotlib 绘制了一个混淆矩阵。我还计算了 Sklearn 库提供的准确率分数。
*#Create the confusion matrix using test data and predictions*
cm = confusion_matrix(Y_test,y_preds)*#plot the confusion matrix*
ax = plt.subplot()
sns.heatmap(cm,annot=True,ax=ax)
labels = target['mood'].tolist()
ax.set_xlabel('Predicted labels')
ax.set_ylabel('True labels')
ax.set_title('Confusion Matrix')
ax.xaxis.set_ticklabels(labels)
ax.yaxis.set_ticklabels(labels)
plt.show()*#Show the accuracy score*
print("Accuracy Score",accuracy_score(Y_test,y_preds))
音乐情绪的混乱矩阵
最终的准确度分数为 76% ,看一下混淆矩阵,我注意到我的模型可以很好地分类平静和悲伤的歌曲,但在处理充满活力和快乐的歌曲时有一些问题。我可以修改一些参数,如批次大小、时期,或者聚合或删除一些追踪要素来训练我的模型,从而帮助提高模型的准确性。
4.享受按情绪分类音乐的乐趣:
我想展示如何预测一首歌的情绪,这首歌可能你懒得完全听,但你想知道这首歌会让你跳舞还是哭。
我的 Github 存储库(点击此处)上有一个名为 helpers.py、的脚本,使用它你只需要在 Spotify 上为开发者创建一个应用程序(点击此处了解更多信息)并获得一个 Client_id 、 Client_secret 和重定向 URL** 。使用这个脚本,你可以通过 这个多类分类模型的一点帮助,下载预测任何歌曲 情绪所需的特性。(没错,就像披头士的歌)。**
首先,我们需要获得 Spotify 应用程序提供的任何歌曲的 Spotify URI。比如,我会预测周末的炫目灯光的心情。
眩目灯光下的 Spotify URI:Spotify:track:0 vjijw 4g luzamy D2 vxmi 3 b
Spotify 应用面板(作者截图)。
然后,我会将歌曲的 Spotify URI 传递给一个我定义的名为 predict_mood 的函数。该函数将歌曲的 Id 作为参数,并包含在创建的神经网络模型中
预测情绪函数的代码是:
*#Import the Script helpers.py*
from helpers import *def predict_mood(id_song):
*#Join the model and the MinMaxScaler in a Pipeline*
pip = Pipeline([('minmaxscaler',MinMaxScaler()),('keras',
KerasClassifier(build_fn=base_model,epochs=300,
batch_size=200,verbose=0))])*#Fit the Pipeline*
pip.fit(X2,encoded_y)
*#Obtain the features of the song (Function created on helpers.py)*
preds = get_songs_features(id_song)*#Pre-processing the input features for the Model*
preds_features = np.array(preds[0][6:-2]).reshape(-1,1).T
*#Predict the features of the song*
results = pip.predict(preds_features)
mood = np.array(target['mood'][target['encode']==int(results)])
#Obtain the name of the song and the artist
name_song = preds[0][0]
artist = preds[0][2]*#Store the name,artist and mood of the song to print.* result_pred=print("{0} by {1} is a {2} song".format(name_song,
artist,mood))return result_pred
《致盲之光》的 Spotify URI 是“spotify:track:0 vjijw 4g luzamy D2 vxmi 3 b”但是predict_mood 函数取 Id,所以我只需要取“Spotify:track”之后的代码:在这种情况下,Id 是 0VjIjW4GlUZAMYd2vXMi3b。
结果显示,周末的强光使人精神振奋。很准确,你不这样认为吗?。
5.结论
深度学*算法在实现与你喜欢的事情相关的想法或项目方面有很多乐趣。就我而言,我非常喜欢音乐,所以我可以用这些知识创造一些很酷的方法来帮助我自动完成一项可能需要很长时间才能完成的任务。我还可以更多地了解这个神奇的数据科学世界,以及我对音乐品味的倾向。
我的文章:
- 一个友好的公共汽车和分析人员到达网页上的部门
- 使用 Python 和 R 对音乐进行聚类,在 Spotify 上创建您的播放列表
- 一种在网络上进行公共汽车和分析工作的交互形式。
- 从你电脑的音乐文件夹中自动播放 Spotify 上的播放列表
参考资料:
- https://towards data science . com/cross-validation-explained-evaluating-estimator-performance-e51e 5430 ff 85
- https://towards data science . com/clustering-music-to-create-your-personal-playlists-on-Spotify-using-python-and-k-means-a39c 4158589 a
- https://machine learning mastery . com/multi-class-classification-tutorial-keras-deep-learning-library/
使用人工神经网络预测下一个音高
原文:https://towardsdatascience.com/predicting-the-next-pitch-using-artificial-neural-networks-fc464383f53d?source=collection_archive---------36-----------------------
太空人真的需要使用照相机吗…
来源:来自 Pixabay 的 Vic Cherubuni
欺骗和猜测:在棒球中获得优势
休斯顿太空人队在 2017 年赢得了世界大赛。他们有一个令人难以置信的运行,击败了波士顿红袜队,纽约洋基队,和(谢天谢地)洛杉矶道奇队。然而,美国职业棒球大联盟最*的调查发现,太空人作弊。尽管休斯顿(和旧金山)的球迷不关心太空人队如何击败道奇队赢得世界大赛,但太空人队被发现利用技术窃取标志。他们从一个非法的中外场摄像机转播了对方接球手的手势。在俱乐部会所隧道里的教练会收到摄像头的反馈,并通过敲打垃圾桶来发出超速信号,而不是敲打快速球。这里有一个视频分解,原谅NSFW语言。
在棒球比赛中,知道什么球会到来是一个不可思议的优势。捕鼠人试图不被发现是有原因的。作为一名前球员,我可以证明知道接下来会发生什么是非常有用的。此外,有一个复杂的方法和预测投球通常是区分伟大击球手的特征。这里有一个技安进攻方式的例子:
“我通常打区域联防,大部分时间我会坐快速球。但是如果有一个人会给我一个 2-1 的变速球,我会坐以待毙。或者(与)一个投滑球的左撇子,我会坐滑球。我会坐在这些球场上,然后让一切都过去。”
此外,名人堂外野手和前全垒打王汉克·亚伦曾经说过:
“猜测投手会投出什么是成功击球手的 80%。另外 20%只是执行力。”
在一个复杂的击球方法中考虑了多个变量后,我意识到猜测或坐下来,下一次投球是机器学*的完美应用,特别是香草前馈神经网络。
先决条件:
我是一名数据科学家新手,但这篇博文假设我熟悉基本的深度学*和 python 概念。
数据收集和清理:
Statcast 是棒球领域最*的一项创新,它使整个项目成为可能。Statcast 给出了每一个音高的 CSV 文件,每个音高都有大量的数据,如速度、音高位置、音高结果、位置等。我想把这种算法用在拥有高级混合音高的投手身上,也就是说,以相对高的频率投出至少三种主要音高。米科拉斯在 2019 年投掷了大约 2800 个跟踪球,斯特罗曼投掷了大约 3000 个球。
在推特上关注达伦·威尔曼,替我谢谢他。他在 Statcast 建立了基础设施来实现这一点。推特:@darenw
斯特罗曼的球场阿森纳/来源:Statcast
米科拉斯的球场/来源:Statcast
我在 excel 中做了最初的数据清理,因为无可否认,作为一个以金融为导向的人,我对 excel 比对熊猫更有信心。清理数据后,我根据自己的经验和职业球员的陈述选择了以下相关变量来预测投球:以前的投球类型(string)、以前的投球结果(string)、击球手的惯用手(string)、投球数(ints)、跑垒员(boolean)、出局数(int)、局数(int)和当前跑垒差(int)。
初始模型:
以下是我用过的库。如果有疑问,就扔进去:
输入库后,我读入 CSV 文件,然后去熊猫工作。我们的第一步是一次性编码所有的字符串值。一种热门的编码方式是将分类数据转换为数字数据,以便机器学*模型可以用它来执行逻辑回归。
所有数据都整齐地组织在 NumPy 数组中,我使用 Sklearn 库创建了一个随机训练/测试分割。在试验了不同的优化器之后,我使用 Keras API 构建了一个带有一个隐藏层的前馈模型。
对于斯特罗曼来说,这在预测超过 600 个音高时产生了 46%的准确率。这个结果比随机预测的概率要高得多。
然而,46%让我深感不满。我很反感。我想做得比抛硬币更好,即使硬币真的是六面的,形状也很奇怪。我想到了一个更准确的方法来建立这个模型。
解决问题:
当检查 Astros 中继系统时,我意识到他们没有中继准确的音高。他们转播快速球或慢速球。猜测准确的下一个音高不像猜测音高的特征那样实用,比如移动和速度。我回到 CSV,将相似的球种归类为硬球(两缝线快速球(伸卡球)和四缝线快速球)、破球(切球和滑球)和软球(曲球和变速球)。这更类似于宇航员使用的撞击系统。
通过稍微改变模型和输入,我能够获得接* 60%的准确率。
应用和结论:
在过去的 20 年里,棒球一直是体育界应用定量方法的领导者。从应用上来说,我觉得这个模型可以作为打者或者任何东西的学*工具来真正打败道奇队。击球手可以使用这个模型来策划球探报告,并在第二天面对先发投手的击球上进行模拟。此外,我知道这个模型还可以改进。我使用的变量并不是猜测音高艺术的全部。我很想从一些玩家和捕手(他们称之为游戏)的头脑中了解如何改进这个模型。请在下面找到我的 git 库,里面有模型和数据。
[## danielajk99/pitch_predictor
用于基音预测的人工神经网络。为 danielajk99/pitch_predictor 开发做出贡献,创建一个…
github.com](https://github.com/danielajk99/pitch_predictor)
特别感谢布兰登·威廉姆斯和诺亚·鲁本帮助我完成了这个项目。还要特别感谢 Ulk Aslak 教授和 Lucian Leahu 教授,他们向我介绍了人工神经网络。
数据和球场画面来自棒球专家的 Statcast 搜索工具。按照这个 链接 在 Statcast 中创建自己的数据集。
丹尼尔·丹·金是乔治敦大学的本科生。这个博客是他在丹麦留学项目的最终项目的一部分(由于新冠肺炎的原因,现在实际上是一个在家学*的项目)。在推特上关注我:@danielajk99。
利用经济指标预测名义 GDP:一种数据科学方法
原文:https://towardsdatascience.com/predicting-the-nominal-gdp-using-economic-indicators-a-data-science-approach-7c56cded782?source=collection_archive---------20-----------------------
利用流行的分类模型预测国内生产总值
凯文·Ku 在 Unsplash 上的照片
这篇文章讨论了使用网络上的数据预测名义 GDP(国内生产总值)。问题陈述是从真实来源收集数据,执行探索性数据分析(EDA),训练模型,以及预测名义 GDP(加拿大)。作为一名 IT 人员,我对这些经济学相关术语知之甚少。这就是为什么首先要做的是熟悉这些概念。接下来是用 R 编程语言学*和执行这个项目,并熟悉流行的 R 包,如 tidyverse、ggplot、caret 等。在实践中,很好地利用在线资源可以很容易地*惯 R 及其语法。
步入任务,遇到各种经济统计又名指标,分类为滞后和领先指标。经济指标可能对一个国家的名义 GDP 有直接影响。我们的方法是用这些指标来预测加拿大的名义 GDP。在研究了各种在线博客、文章和论文中的这些指标后,最终确定了以下指标:
人口
难民人口
实际利率
国内公司数量
旅游服务(占进口服务-国际收支的百分比)
税收
房地产市场
劳动生产率
政府债券收益率 10 年期利率
个人汇款(收到&以美元支付)
铁路运送旅客
航空运送旅客
通货膨胀
收入增长
失业率
政府赤字
消费价格指数
商品价格指数
欧元对加元的兑换率
美元对加元的兑换率
多伦多证券交易所交易价值
多伦多证券交易所交易量
入境国际游客
数据来自加拿大统计局、T2、世界银行、T4 统计局和其他来源。这些指标被假定为特征,这些特征的数据是在 2009 年至 2018 年间收集的。数据集分为两部分,训练集和测试集。
T
探索性数据分析
在数据集组装、清理和整齐排列后,开始对数据集进行探索性数据分析。使用标准正态分布的概率密度 dnorm 函数进行数据标准化。为了检查数据是否正常,对每个特征应用夏皮罗-维尔克正态性检验。除 3 个变量外,所有变量的 p 值都大于 0.05,这表明它们是正常的。为了分析数据集特征之间的相关性,使用了 caret 包的find correlation函数,去除了高度相关的属性。由于数据点较少,即 8 个(2009 年至 2016 年),必须降低数据的维度。这是通过使用 prcomp 函数应用主成分分析(PCA) 完成的。至此,EDA 结束了。现在让我们开始建模吧!参考 GitHub 链接… 点击这里!
线性回归建模
在这种类型的建模中,PCA 值用于使用 lm() 函数训练简单的线性回归模型。使用汇总功能对生成的模型进行汇总。关键观察是 p 值小于显著性水平(< 0.05)。这意味着我可以安全地拒绝零假设,因为预测系数的系数β为零。此外,模型的 F 统计值为 428.6(越多越好)。因此,可以得出结论,该模型具有统计学意义。为了验证该模型,我对 2017 年和 2018 年的值进行了测试。模型的总体准确率为 98.31%。文章末尾的表格提供了关于实验的更多细节。
随机森林造型
对于这个建模,R 语言的 randomForest 库使得选择特征和创建随机森林模型变得更加容易。 importance() 函数根据数据叶节点杂质找到并显示每个特征的重要性。这些数据存储在一个新的数据集中,该数据集根据重要性值进行排序。这里的技巧不是选择重要性值仅较高或较低的特征,而是选择中和频谱的值,即较高、较低和中等重要性值的组合,以保持平衡。使用试错法挑选了六个特征。
个人汇款(已收)
实际利率
旅游服务进口
国债收益率 10 年期利率
政府赤字
国内公司数量
使用随机森林函数对模型进行训练。 mtry 参数设置为 6(特征数量),树的数量( ntree )设置为 1000。该模型对 2017 年和 2019 年 NGDP 的预测平均准确率为 95.68%。
支持向量机建模
这是我们实验清单上的最后一个。为了在我们的使用中利用 SVM 建模,我们使用了提供 svn 函数的 R 的 e1071 包来建模。因为我们的用例不是一个分类用例,所以必须应用回归选项。为此, svm() 函数提供了一个类型参数,使我们能够进行选择。相应地,选择EPS-回归类型,并将内核参数设置为径向。关于内核的更多细节,点击这里。这里预测的平均准确率为 98.18%。下面的图表提供了实验的更多细节。
显示实际值与预测值的图表
总之,尽管数据集很小,但所有模型的预测准确率都在 95%以上。当使用 PCA 值训练线性模型时,得到的输出比其他的更好。然而,随机森林可以被认为是最不可靠的,因为它使用数据集的最少特征。如果不是准确性或可靠性,该结果至少倡导了经济指标在预测名义 GDP 中的意义。
PS:这个实验是提交给加拿大统计局商业数据科学家挑战 2019/2020 的一部分。
使用优先机器学*预测奥斯卡
原文:https://towardsdatascience.com/predicting-the-oscars-using-preferential-machine-learning-32f06ffbf427?source=collection_archive---------31-----------------------
奥斯卡和他们的优先投票让我创造了一种新颖的机器学*方法来模仿这种投票系统
去年对电影来说是很棒的一年,如果你像我一样,沐浴在电影票热潮的余晖中,仍然在电影院看很多电影,你知道好莱坞往事、寄生虫、 1917 和更多的电影提供了独特的电影体验。每年的奥斯卡周日,好莱坞都会聚在一起,给自己一个大大的鼓励。当晚最大的奖项是最佳影片奖,它可以将一部电影载入电影史。与奥斯卡之夜颁发的其他 23 个奖项不同,梦寐以求的最佳影片奖是通过一种称为优先投票的方法选出的,这种方法比传统投票更复杂。为今年的奥斯卡做准备,并了解优先投票让我写了一些程序,用机器学*来模拟这个投票系统。
Reddit 用户 u/Tillmann_S 的 2020 奥斯卡艺术
在这篇文章中,我:
- 选择用于预测奥斯卡的数据
- 从数据科学的角度探索优先投票的工作原理
- 演示一个我自己设计的方法,我称之为优先投票随机森林
- 模拟最佳影片投票的幕后发生的事情
- 预测今年的最佳影片得主
我没有在本文中包含我的任何代码,但是这里是存储库,包含我在这个分析中使用的笔记本
如何预测奥斯卡:数据集
为了使用机器学*来预测任何事情,我们需要一个有意义的数据集来训练我们的模型。在最佳影片竞赛的情况下,我们有 9 部 2019 年提名的电影。尽管我对奥斯卡充满敬意(毕竟我有足够的兴趣写这篇文章),但我毫无保留地认为,今年的最佳电影将赢得奥斯卡最佳影片奖。该学院由电影行业各个领域的数千名成员组成,他们每个人都有自己的偏见,这导致了他们的投票。因为投票背后有真实的人,我们不能依赖票房利润或总评论家分数等电影质量的数字指标。但是你知道什么和电影制作人的投票密切相关吗?其他电影人投票。
还有许多其他的颁奖典礼组成了“颁奖季”,像美国演员工会奖和导演工会奖这样的活动的投票者通常也是奥斯卡奖投票者。利用早期奖项如 SAGs、DGAs、PGAs、金球奖和 BAFTAs 的结果,并结合奥斯卡信息如提名数,我可以训练一个模型来预测今年的最佳影片获奖者。为了获得一致的电影数据和命名惯例,我从维基百科上收集了每个颁奖典礼的提名者和获奖者的数据,并使用熊猫和美丽的汤包将它们合并到 Python 中的一个数据集。
优先投票的工作原理
优先投票,也称为即时决胜投票,通常用于有许多候选人争夺一个席位的情况。自 2009 年以来,奥斯卡一直使用这种计票系统来决定最佳影片竞赛,当时该领域从五个提名人扩大到十个。在优先投票中,选民不是为一部电影投票,而是提交一份对所有选项进行排名的投票,排名第一的选项将作为该电影的投票。然后开始一个迭代过程,其中最不受欢迎的电影被淘汰,所有的投票被重新排序,直到一部电影获得超过 50%的#1 选票。在一部电影从所有选票中被淘汰后,之前将被淘汰的电影放在第一位的选票现在将第二位移到第一位,这增加了剩余电影的票数。这一过程一直持续到一部电影获得超过 50%的#1 选票,然后它被宣布为获胜者。这种消除过程的模拟如下所示。
图 1:优先投票淘汰的模拟。由我的偏好随机森林生成
优先投票法的批评者声称,这种方法奖励容易喜欢或无争议的电影,因为无争议的电影将在人们的排名中处于中间位置,而有争议的电影可能在一些人的投票中名列前茅,但在其他人的投票中垫底,因此它们很容易被淘汰。去年,当更具艺术性的电影《T2》《罗马》《T3》输给更具大众吸引力的电影《T4》《绿皮书》时,这种效应就显现出来了。
图片来源:左——阿方索·卡隆/网飞,右——环球影业/参与者/梦工厂
优先抽签随机森林
我们过去已经看到,优先投票可以改变最佳影片竞赛的结果,因此我创建了一个模型来反映这种独特的计票方法。随机森林分类器模型通过使用多个去相关的决策树分类器进行预测。这里有一篇文章更侧重于传统随机森林如何工作的细节。一般来说,一个随机森林会根据树叶的大小将每棵树的“投票”作为一个分数,并根据哪个类别在所有树中拥有最多“投票”来选择最终标签。对于这个优先投票随机森林,我们改为使用测试集中每部电影的 ProbA 值,并使用它们来创建电影的第 1-9 名排名。ProbA 值是该项在“赢家”类别中的可能性,代表比二元“赢家”或“输家”分类更软的预测。这种更软的预测允许我们将预测从布尔分类改为范围。每个决策树产生一张选票,一旦整个森林产生了他们的选票,优先选票淘汰的迭代过程开始确定森林对获胜者的选择。通过使用排名而不是挑选一个类别,我的优先投票随机森林保存了传统随机森林会丢弃的信息,并在优先投票的消除和重新排名阶段再次使用。
图 2:单个决策树对测试集的投票
模拟奥斯卡颁奖典礼
利用我的优先投票随机森林,我模拟了今年的最佳图片竞赛。为了消除每棵决策树的相关性,我改变了每棵树看到的奖励,类似于随机森林的 max_features 超参数。在这个模拟中, max_features 代表投票的学院成员可能属于哪个公会,或者他们对该季其他奖项的关注程度。我还为每个决策树添加了一个随机噪声特征来进行训练,代表每个投票者对某些电影的天生偏见。该学院由大约 7000 名不同的投票者组成,所以我启动了我的森林,很快就产生了 7000 张选票。经过 6 轮淘汰最后一部电影后,第一部电影获得了超过 50%的第一票,我的模型选出了最佳影片奖…
图 3:6 轮优先投票淘汰后的最终排名。当电影《1917》获得超过 50%的票数时,这一过程就停止了。
最终预测
我的优先投票随机森林是一种模拟奥斯卡的新颖方法,我希望它能帮助你了解最佳影片投票和随机森林分类器的一些内容,但除了优先投票,让我们进入正题,真正预测这些坏男孩。利用我搜集的获奖电影数据集,我实现了 H2O 强大的 AutoML 工具来训练 100 个不同的随机森林、XBGT 和深度学*模型,用各种参数来预测今年的奥斯卡奖。AutoML 选择了 XGBoost 模型,该模型在交叉验证中正确预测了 159 部电影中的 147 部电影的奥斯卡奖结果。这个模型的漩涡预测了哪部电影?还有 1917 !看起来这部电影的前景不错,因为优先投票随机森林和我的 AutoML 模型都预测到了。
图片来源:环球影业,弗朗索瓦·杜哈梅尔
链接和推销:
该项目的 Github 回购
抓取代码灵感来自 Github 用户 Buzdygan
旧金山大学 MSDS 分校
预测过去:验证的概念
原文:https://towardsdatascience.com/predicting-the-past-the-idea-of-validation-2f876b2016?source=collection_archive---------65-----------------------
(形象由)
如何确定他/她的模型是否准备好分析看不见的数据?
首先,我们必须明白,虽然传统统计学更侧重于理解给定数据集的复杂性,但数据科学旨在理解所述复杂性,对未来情景做出预测或处方。
因此,评估模型可靠性的主要部分是通过验证。验证的核心思想是:既然我们无法拥有未来事件的数据,我们就必须“预测过去”。
那是什么意思?
因为我们已经知道过去事件(X)的结果(Y),在验证中,我们评估该模型预测事件的结果有多准确。
因此,我们必须从数据集中删除一条信息,我们将把它伪装成未来的数据,模拟生产环境。这个拆下来的零件不是用于模型训练,而是作为一个测试。
这可以通过几种方式来实现。最简单的是将数据分成两组,一组用于建模,另一组用于测试。另一方面,这种方法的演变是交叉验证。
与其把数据只分成两组,为什么不分成五组呢?四个用于模型训练,一个用于精度测试?如果您错过了窍门,这可能会适得其反:如果您将数据集分成五部分,您将进行五种不同的评估,并更改哪一部分是验证集。
通过这种方式,连续的测试可以让你对你的模型的可靠性有一个更广阔的视野。
不过,要记住的重要一点是,如果你没有使用时间序列,那么一定要随机划分样本。
如果你有一个“时间序列”数据集呢?
我们称时间序列为按时间顺序排列的数据集。这个小定义已经表明,传统的随机分裂方法没有用,因为我们可能会制造混乱,甚至使模型不适合。
因此,有两种主要方法和一种非常模糊的方法来验证时间序列数据集:扩展和滑动是主流,交替阻塞是一种非常非传统但非常强大的方法。
这些方法依赖于根据时间非随机地划分数据集。他们每个人都使用不同的分裂组合来验证。例如,2018 年的数据可用于训练模型,以预测 2019 年第三季度的销售额,等等。
我打算稍后再写关于时间序列验证的文章。这篇短文的主要目的是说:验证旨在通过向模型隐藏数据集的一部分,并使其预测隐藏的部分,来模拟生产和新数据的条件。
然后,通过计算误差量来评估可靠性。通过这种方式,可以检查对模型所做的更改在统计上是否显著,以及预测未来数据是否可靠。
预测二手车的价格
原文:https://towardsdatascience.com/predicting-the-price-of-used-cars-891d13faf3fc?source=collection_archive---------44-----------------------
帕克·吉布斯在 Unsplash 上的照片
具有特征选择和特征工程的 XGBoost 实现
本文旨在分析二手车数据集的属性,以便在使用 XGBoost 模型预测这些汽车的价格之前执行特征选择和特征工程。数据处理、清理、特征选择和建模的整个过程在下面的部分中示出。术语“属性”、“变量”和“特征”在本文中可互换使用,具有相同的含义,即它们指的是数据集的列。
我们先来了解一下特征选择和特征工程是什么意思。
特征选择
选择那些与输出变量预测最相关的输入特征的过程称为特征选择。这有助于减少数据的维度,并确保模型不会学*那些可能降低其准确性的不相关特征。
有关功能选择的更多信息,请点击此处。
特征工程
在使用或不使用现有要素的情况下,为给定数据集获取新要素以提高该数据集模型性能的过程称为要素工程。
有关特征工程的更多信息点击此处。
现在让我们深入到实现部分。
履行
导入必要的库
我们导入了预测过程所需的以下库。
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn.preprocessing import StandardScaler, LabelEncoder
from sklearn.model_selection import train_test_split
import math
import matplotlib
import seaborn as sns%matplotlib inline
加载数据集
这里使用的数据集是加载的二手车数据集。它拥有从易贝收集的 37 万行数据和描述每辆二手车细节的 28 个属性。但是使用了具有 50000 行的总数据集的子集。这些数据的内容是德语,然后翻译成英语。这个原始数据集的翻译子集可以在这里找到。数据集属性的描述如下所示:
df = pd.read_csv(‘../input/data.csv’, sep=’,’, header=0, encoding=’cp1252')
df.describe()
从数据描述中我们可以看到,有些数值变量有不能存在的值。例如, yearOfRegistration 变量的最小值为 1000,最大值为 9999,而这两个值是不可能的。这些值将在接下来的代码块中处理。
删除不必要的列和不允许的值
然后,我们删除数据集中对预测汽车成本没有意义的属性。
df.drop([‘name’,’seller’, ‘offerType’, ‘dateCrawled’, ‘lastSeen’], axis=’columns’, inplace=True)
然后删除属性值不可能(不允许)的行。
df=df[(df.price>=100) & (df.price<=200000) & (df.yearOfRegistration>=1950) & (df.yearOfRegistration<=2019) & (df.monthOfRegistration>0) & (df.monthOfRegistration<=12) & (df.powerPS>10) & (df.powerPS<1000)]df.describe()
从上面的数据描述中我们可以看到,属性现在只有可能的值。
NA 值的插补
我们首先需要找出哪些属性具有 NA 值,即空字段。
df.isna().sum()
所以 NA 值只存在于分类变量中。为了填充每个空字段(插补,使用该属性的模式值。
var=[‘vehicleType’,’gearbox’,’model’,’fuelType’,’notRepairedDamage’]
for i in var:
df[i].fillna(df[i].mode()[0],inplace=True)
df.isna().sum()
使用目标变量的特征可视化
根据价格变量绘制特征注册年份、注册月份、和邮政编码。
for i in [‘yearOfRegistration’, ‘monthOfRegistration’,’postalCode’]:
sns.jointplot(x=i, y=’price’,data=df[[i,’price’]],size=7)
注册年份与价格
注册与价格
邮政编码与价格
为每对变量显示的图以及皮尔逊相关性和 p 值可用作特征选择度量。第二个图显示月注册与价格的相关值非常低,而 p 值很高。所以这个变量被删除了。
df.drop([‘monthOfRegistration’],axis=’columns’,inplace=True)
特征工程——创造新的特征“ageOfCar”
这个数据集有一个属性 dateCreated ,这是在易贝上创建汽车广告的日期。通过使用这个属性和 yearOfRegistration 属性,我们可以创建一个告诉我们汽车年龄的新特性( ageOfCar )。
df[‘ageOfCar’]=pd.DatetimeIndex(df[‘dateCreated’]).year-df[‘yearOfRegistration’]
sns.jointplot(x=’ageOfCar’,y=’price’,data=df[[‘ageOfCar’,’price’]],size=7)
车龄与价格
从上面的图中我们可以看到,皮尔逊相关性的大小与注册年份和价格的皮尔逊相关性的大小相同,但是为负。这意味着随着车龄的增加,价格会下降,这在现实生活中也是如此。
现在我们删除变量 yearOfRegistration 和 dateCreated。
df.drop([‘yearOfRegistration’,’dateCreated’],axis=’columns’,inplace=True)
用箱线图识别和去除异常值
在统计学中,异常值是与其他观察值显著不同的数据点。异常值可能是由于测量中的可变性造成的,或者它可能表示实验误差;后者有时被排除在数据集之外。异常值会在统计分析中引起严重的问题。(来源:维基百科)
所以基本上离群点就是不符合一般数据分布的数据点。数据中存在的异常值会扭曲模型并扰乱其学*过程。因此,现在我们将检测数据集中的这些异常值,并使用箱线图(四分位数间距)方法移除它们。要了解不同的异常值检测方法请点击这里。
sns.boxplot(x=df[‘price’])
价格箱线图
因此价格变量的异常值位于值 25000 之后。
sns.boxplot(x=df[‘ageOfCar’])
ageOfCar 箱线图
sns.boxplot(x=df['powerPS'])
powerPS 的箱线图
sns.boxplot(x=df['kilometer'])
公里箱线图
同样,对于特征而言,ageOfCar、powerPS、千米值分别高于 30、高于 280 和低于 25000 都是异常值。这些异常值现在已被移除。
df=df[(df.price<=25000) & (df.ageOfCar>=0) & (df.ageOfCar<=30) & (df.powerPS<=280) & (df.kilometer>=25000)]
编码分类变量
现在,我们需要对数据集的分类变量进行编码,以便模型可以使用它进行训练。分类变量有几种编码技术。在这种情况下,我们将对具有两个类的变量使用标签编码,对具有两个以上类的变量使用目标编码。目标编码优于一键编码,因为后者会导致数据维数非常高。
x=df.drop([‘price’],axis=’columns’,inplace=False)
y=df[‘price’]le1=LabelEncoder().fit(x['gearbox'])
x['gearbox'] =le1.transform(x['gearbox'])
le2=LabelEncoder().fit(x['notRepairedDamage'])
x['notRepairedDamage'] =le2.transform(x['notRepairedDamage'])
le3=LabelEncoder().fit(x['abtest'])
x['abtest']=le3.transform(x['abtest'])from category_encoders import TargetEncoderte=TargetEncoder(cols=['brand','model','vehicleType','fuelType','postalCode']).fit(x,y)
x=te.transform(x)
使用相关热图
通过使用关联热图,我们可以了解变量之间的关系。从热图中可以得出两个主要观察结果(不包括对角线元素):
- 与其他输入变量高度相关的输入变量。
- 与输出变量相关性低的输入变量。
现在让我们生成热图。
f, ax = plt.subplots(figsize=(11, 9))
cmap = sns.diverging_palette(220, 10, as_cmap=True)
x[‘price’]=y
sns.heatmap(x.corr(),cmap=cmap,square=True,annot=True)
从热图中,我们可以看到输入变量之间没有太大的相关性,但是, abtest 与 price 的相关性很差。因此 abtest 被移除。
x.drop([‘abtest’],axis=’columns’,inplace=True)y=x['price']
x.drop(['price'],axis='columns',inplace=True)
标准化,分为训练集和验证集
我们现在将变量标准化,并将其分为训练集(80%)和验证集(20%)。
sc=StandardScaler()
x=sc.fit_transform(x)X_train, X_val, y_train, y_val = train_test_split(x, y, test_size=0.2, random_state = 42)
使用 XGBoost 模型进行训练和测试
我们使用一个 XGBoost 模型来训练数据并预测输出。我们还使用 sklearn 模块的 GridSearchCV 来确定模型的最佳参数。使用 GridSearchCV 调优的参数有:
- n_estimators: 定义 XGBoost 模型使用的估计器(树)的数量。
- max_depth: 定义每棵树允许的最大深度,用于控制过拟合。
- eta: 这是模型的学*率,它缩小了节点的权重,使其更加稳健。
为了获得模型性能的无偏估计,我们使用了带有cv=5
的 K 倍交叉验证方法。通过使用 RMSE 作为误差度量来识别最佳参数。因为我们需要找到产生最小 RMSE 的模型,我们将 RMSE 的负数传递给scoring
参数。
import xgboost as xgb
from sklearn.model_selection import GridSearchCVparam={‘n_estimators’:[10,20,50,100,150,200],
‘max_depth’:range(3,11),
‘eta’:[0.05,0.1,0.15,0.2,0.25,0.3]}xgr=xgb.XGBRegressor()
gs=GridSearchCV(estimator=xgr,param_grid=param,scoring=’neg_root_mean_squared_error’,cv=5,verbose=3)
gs.fit(X_train,y_train)
参数搜索完成后,我们现在可以查看确定的最佳参数及其相应的指标得分。
print(gs.best_params_)
print(gs.best_score_)
eta=0.05
、n_estimators=200
、max_depth=7
被确定为产生最低 RMSE 分数的参数。使用 GridSearchCV 确定的这些参数,我们构建最终模型并将其用于预测。对于回归问题,比如这个问题,误差度量比如 RMSE、MSE、MAE、R 等。被使用。这里,我们使用 RMSE 和 T21(决定系数)作为误差度量。XGBoost 的score()
函数返回回归问题的 R 值。
from sklearn.metrics import mean_squared_errorxgr=xgb.XGBRegressor(eta=0.05,max_depth=7,n_estimators=200)
xgr.fit(X_train,y_train)
pred=xgr.predict(X_val)
print('RMSE: ',mean_squared_error(y_val,pred,squared=False))
print('R2Score: ',xgr.score(X_val,y_val))
RMSE 和 R 值表明模型的结果相当准确。现在,为了评估模型的性能,并了解数据分布的捕捉情况,我们从残差中生成图。
在回归分析中,因变量的观测值(y)与预测值(ŷ)之差称为残差 (e)。每个数据点有一个残差。(来源: Stattrek )
我们使用标准化残差(残差除以其标准差)来创建散点图和直方图。
def residual_plot(y_test, y_pred):
res = y_test — y_pred
fig, axs = plt.subplots(1,2,figsize=(30,10))
std_res = res/np.std(res)
axs[0].title.set_text(‘Scatter Plot of residuals’)
axs[0].set_xlabel(‘True Output’)
axs[0].set_ylabel(‘Residuals’)
axs[0].scatter(y_test,std_res)
axs[1].title.set_text(‘Histogram of residuals’)
sns.distplot(std_res, ax = axs[1]);
plt.show()residual_plot(y_val,pred)
残差的散点图和直方图
散点图显示存在一些异常值,并且残差不具有恒定的方差。因此,它们不遵循正态分布。直方图显示大部分残差集中在零附*。
特征重要性
为了理解输出预测过程中每个特征的重要性并得出未来的推论,我们绘制了直接从 XGBoost 模型中获得的特征重要性值。
feature_important = xgr.feature_importances_
values = list(feature_important)data = pd.DataFrame(data=values, index=feat, columns=[“score”]).sort_values(by = “score”)
ax=data.plot(kind=’barh’,title=’Feature Importance’,legend=None)
ax.set_xlabel(‘Importance value’)
ax.set_ylabel(‘Features’)
plt.show()
特征重要性
未修复损坏、燃油类型、和变速箱对价格的预测作用不大。
结论
总之,我们利用二手车数据集来理解数据清理、插补、特征选择和特征工程的概念。我们还学*了如何使用 XGBoost 模型,并通过绘制残差和特征重要性值对其进行回归分析。
要获得 IPython 笔记本的完整代码请点击这里。
用 R 和 Python 中的多元逻辑回归预测 SARS CoV-2 结果的概率
原文:https://towardsdatascience.com/predicting-the-probability-of-sars-cov-2-result-using-multiple-logistic-regressing-in-r-and-python-874cf9185d62?source=collection_archive---------33-----------------------
对 SARS 冠状病毒 2 型患者进行分类以及哪些变量会影响结果。
来源:维克斯
编者注: 走向数据科学 是一份以研究数据科学和机器学*为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
简介
大约两个月前,巴西的以色列阿尔伯特·爱因斯坦医院发布了关于 Kaggle 的公开数据,以便更好地了解这种新型冠状病毒。因此,我试图使用这个数据集来预测患 SARS CoV-2 的概率,并检查哪些变量影响最具预测性的 SARS CoV-2 结果。
背景
截至 3 月 27 日,圣保罗州记录了 1223 例新冠肺炎确诊病例,68 例相关死亡,而拥有约 1200 万人口的圣保罗州,以及以色列阿尔伯特·爱因斯坦医院所在地,截至 3 月 23 日,有 477 例确诊病例和 30 例相关死亡。该州和圣保罗县都决定建立隔离和社会距离措施,这将至少持续到 4 月初,以减缓病毒的传播。
数据集
该数据集包含在巴西圣保罗的以色列阿尔伯特爱因斯坦医院就诊的患者的匿名数据,这些患者在就诊期间收集了样本以进行新型冠状病毒 RT-PCR 和其他实验室测试。
数据集总共有 5644 行和 111 列。
分析中使用的变量(预测值)
这篇文章不足以解释所有使用的变量。因此,我将即时讨论一些重要的预测因素。
为了准备数据,我使用了 Python 中的 Pandas。对于逻辑回归分析,我使用了 r。现在让我们跳到数据准备。
数据准备
第一眼看数据集,我发现了许多 NaN 值。在前进之前,必须纠正缺少值的问题。
按降序排列的每一列的值计数
从这里开始,我将数据集分成两个子集,命名为条件和疾病。(它们只是名字,不代表任何东西)橙色标记的是疾病子集,绿色标记的是病情子集。
变量中性粒细胞和蛋白质 C reativa 中的缺失值必须进行估算。我已经使用 KNNImputer 来估算丢失的值。
对于这两个数据集,我们的目标变量是 SARS_CoV2_exam_result。数据集疾病具有所有分类预测值,数据集条件具有所有连续数值预测值。
对于分类变量,0 表示未检测到疾病,1 表示检测到疾病。
分析
从这里开始,我将使用 R 进行分析。让我们从疾病数据集开始。
疾病数据集分析
疾病数据集摘要
我不得不跳过副流感 2 号,因为没有病例。现在,让我们绘制克拉姆夫相关图,以检查分类变量之间的相关性。
# CramerV Correlation to check for any correlation between catagorical variables
# Except Patient's age, all other variables are catagorical(binary)
>disease.corr = PairApply(disease[,names(disease) != "Patient_Age_Quantile"],cramerV, symmetric = TRUE)
# Displaying correlation with variable SARS_COV2_Result
>disease.corr[,2]
# Correlation plot
>corrplot(disease.corr, method = "square", type = "lower")
疾病数据集相关图
这里最重要的预测因子似乎是我们目标上的鼻病毒或肠道病毒,相关值为 0.1517。(不太重要)现在让我们将数据集分成 80%的训练和 20%的测试。
# Dividing Train/Test data with 80% training and 20% test
>sample_size <- floor(0.8 * nrow(disease))
>train <- sample(nrow(disease), size = sample_size)
>disease.train <- as.data.frame(disease[train,])
>disease.test <- as.data.frame(disease[-train,])
我们的数据集还没有准备好进行逻辑回归分析。
# Logistic regression considering top predictors
>disease.function = paste("SARS_COV2_Result", "~", "Patient_Age_Quantile + Rhinovirus_OR_Enterovirus")
disease.glm = glm(as.formula(disease.function), data = disease.train , family = binomial)
>summary(disease.glm)
疾病概述
在这里,预测因子患者年龄分位数和鼻病毒或肠道病毒的 P 值显示了巨大的希望。
根据上面的等式,我们可以说,如果一个人患有鼻病毒,他/她患 SARS CoV2 的可能性较小。
我使用了 10 重交叉验证来验证我们的模型。下一步是预测测试数据集上的值并准备混淆矩阵。
# 10 fold cross-validation to verify the model
>cv.glm(disease.train,disease.glm,K=10)$delta[1]# Predicting on test data based on training set
>disease.glm.predict <- predict(disease.glm,disease.test,type = "response")
>summary(disease.glm.predict)
# Mean predict results for SARS Cov2 Results diagnosis
>tapply(disease.glm.predict, disease.test$SARS_COV2_Result, mean)# Confusion matrix for threshold of 1%
>disease.confusion = table(disease.test$SARS_COV2_Result, disease.glm.predict > 0.01)
>disease.confusion# False negative error(Type II error)
>disease.type2error = disease.confusion[1,1]/
(disease.confusion[1,1]+disease.confusion[2,2])
>disease.type2error
我设置了一个严格的阈值(1%)来最小化第二类错误。该模型必须最大限度地减少误检患者的数量。60%的患有新冠肺炎的患者将从模型中被错误地检测为阴性,这是相当高的。
正如预测的那样,ROC 曲线是 okayish 的。
# Plotting ROCR curve
>disease.ROCRpred = prediction(disease.glm.predict, >disease.test$SARS_COV2_Result)
>disease.ROCRperf = performance(disease.ROCRpred, "tpr", "fpr")
>par(mfrow=c(1,2))
>plot(disease.ROCRperf, colorize=TRUE, >print.cutoffs.at=seq(0,1,by=0.1), text.adj=c(-0.2,1.7))# Probability of SARS vs Rhinovirus plot
>disease.predicted.data <- data.frame(
probability.of.having.SARS=disease.glm.predict,
Rhinovirus=disease.test$Rhinovirus_OR_Enterovirus)
>disease.predicted.data <- disease.predicted.data[
order(disease.predicted.data$probability.of.having.SARS, decreasing=FALSE),]
>disease.predicted.data$rank <- 1:nrow(disease.predicted.data)>plot(probability.of.having.SARS ~ Rhinovirus,disease.predicted.data, type = "l", lwd = 2)
ROC 图和 SARS 与鼻病毒的概率图
鼻病毒的症状接* SARS CoV-2 病毒,多见于鼻部(鼻病毒)。因此,随着鼻病毒的检测,患 SARS 的概率降低。
条件数据集分析
条件数据集包含所有数字预测值,即从血液样本中获取的值。从摘要来看,数据看起来正常。
条件数据集摘要
重复相同的步骤,对目标变量的较高相关预测值应用逻辑回归。
# attaching the final dataset
>attach(condition)# Correlation between varables
>condition.corr = cor(condition)
>condition.corr[,2]
# Correlation plot
>corrplot(condition.corr, method = "square", type = "lower")# Dividing Train/Test data with 80% training dataset
>sample_size <- floor(0.8 * nrow(condition))
>train_ind <- sample(nrow(condition), size = sample_size)
>condition.train <- as.data.frame(condition[train_ind,])
>condition.test <- as.data.frame(condition[-train_ind,])# Logistic regression considering all the variables on the targer variable SARS_COV2_Result
>condition.function = paste("SARS_COV2_Result", "~", "Patient_Age_Quantile + Leukocytes + Eosinophils + Red_blood_cell_distribution_width_RDW + Platelets + Proteina_C_reativa_mg_dL")
>condition.glm = glm(as.formula(condition.function), data = >condition.train , family = binomial)
>summary(condition.glm)# 10 fold cross-validation to verify the model
>cv.glm(condition.train,condition.glm,K=10)$delta[1]# Predicting on test data based on training set
>condition.glm.predict <- predict(condition.glm,condition.test,type = "response")
>summary(condition.glm.predict)
>tapply(condition.glm.predict, condition.test$SARS_COV2_Result, mean)# Confusion matrix for threshold of 1%
>condition.confusion = table(condition.test$SARS_COV2_Result, condition.glm.predict > 0.01)
>condition.confusion# False negative error rate (Type II error)
>condition.type2error = condition.confusion[1,1]/ (condition.confusion[1,1]+condition.confusion[2,2])
>condition.type2error
条件数据集相关图
这里我们看到一些高度相关的变量。然而,我们只考虑与目标变量高度相关的预测值。因此,为了进行分析,我将使用患者年龄分位数、白细胞、嗜酸性粒细胞、红细胞分布宽度 RDW、血小板和蛋白质 a_C_reativa_mg_dL 预测值。我们来看看 glm 总结。
条件数据集 glm 摘要
让我们预测一下测试数据集的误差。使用该模型,121 例中的 30 例给出错误的结果,并且 ROC 曲线优于先前的模型。
# Plotting ROCR curve
>condition.ROCRpred = prediction(condition.glm.predict, condition.test$SARS_COV2_Result)
>condition.ROCRperf = performance(condition.ROCRpred, "tpr", "fpr")
>plot(condition.ROCRperf, colorize=TRUE, print.cutoffs.at=seq(0,1,by=0.1), text.adj=c(-0.2,1.7))
条件数据集 ROC 曲线
绘制结果,
# Creating a dataframe with variables and predicted values of SARS results
>condition.predict.dataframe <- data.frame(
probability.of.having.SARS=condition.glm$fitted.values,
Leukocytes=condition.train$Leukocytes,
Patient_Age_Quantile = condition.train$Patient_Age_Quantile,
Eosinophils = condition.train$Eosinophils,
Red_blood_cell_distribution_width_RDW = >condition.train$Red_blood_cell_distribution_width_RDW,
Platelets = condition.train$Platelets,
Proteina_C_reativa_mg_dL = >condition.train$Proteina_C_reativa_mg_dL)>plot1 = ggplot(data=condition.predict.dataframe, aes(x=Patient_Age_Quantile, y=probability.of.having.SARS)) +
geom_point(aes(color=Patient_Age_Quantile), size=4)
>plot2 = ggplot(data=condition.predict.dataframe, aes(x=Leukocytes, y=probability.of.having.SARS)) +
geom_point(aes(color=Leukocytes), size=4)
>plot3 = ggplot(data=condition.predict.dataframe, aes(x=Red_blood_cell_distribution_width_RDW, y=probability.of.having.SARS)) +
geom_point(aes(color=Red_blood_cell_distribution_width_RDW), size=4)
>plot4 = ggplot(data=condition.predict.dataframe, aes(x=Eosinophils, y=probability.of.having.SARS)) +
geom_point(aes(color=Eosinophils), size=4)
>plot5 = ggplot(data=condition.predict.dataframe, aes(x=Platelets, y=probability.of.having.SARS)) +
geom_point(aes(color=Platelets), size=4)
>plot6 = ggplot(data=condition.predict.dataframe, aes(x=Proteina_C_reativa_mg_dL, y=probability.of.having.SARS)) +
geom_point(aes(color=Proteina_C_reativa_mg_dL), size=4)
# Plotting the values
>grid.arrange(plot1, plot2, plot3, plot4, plot5, plot6, ncol=3 , nrow = 2)
患 SARS 的概率与预测值
我们可以看到,患者的年龄分位数和蛋白 a C reativa 呈正相关,其余与目标变量的概率呈负相关。
预测器的单独调查
一些预测因素在单独分析时显示出巨大的潜力。这些预测是,
我现在将创建一个函数来分析这些变量,以查看它们的效果。
# Plotting Seperate probability graphs
>plotting.function <- function(var,variableORrank){
condition.sep.function = paste("SARS_COV2_Result", "~", as.character(var))
condition.sep.glm = glm(as.formula(condition.sep.function), data = condition.train , family = binomial)
print(summary(condition.sep.glm))
cv.glm(condition.train,condition.sep.glm,K=10)$delta[1]
condition.predicted.data <- data.frame(
probability.of.SARS=condition.sep.glm$fitted.values,
variable=condition.train[,as.character(var)])
condition.predicted.data <- condition.predicted.data[
order(condition.predicted.data$variable, decreasing=FALSE),]
condition.predicted.data$rank <- 1:nrow(condition.predicted.data)
ggplot(data=condition.predicted.data, aes(x= variable, y=probability.of.SARS)) +
geom_point(aes(color=variable), size=3) +
xlab(as.character(var)) +
ylab("Probability of having SARS CoV-2") +
scale_colour_gradient(low = "darkgreen", high = "darkred", na.value = NA) +
ggtitle(coef(summary(condition.sep.glm))[,'Pr(>|z|)'])
}>plotfun1 = plotting.function("Platelets")
>plotfun2 = plotting.function("Monocytes")
>plotfun3 = plotting.function("Hemoglobin")
>plotfun4 = plotting.function("Red_blood_cells")
>plotfun5 = plotting.function("Mean_platelet_volume")
>grid.arrange(plotfun1, plotfun2, plotfun3, plotfun4, plotfun5, ncol=3 , nrow = 2)
结果是,
患 SARS 的概率与单一预测因子分析(图表标题为 Pr(>|z|)值,越低越好)(单核细胞是一种白细胞,血红蛋白是一种含铁的氧运输金属蛋白)
除了血小板之外,所有预测因子都与患 SARS CoV-2 的概率呈正相关。
结论
对于医院来说,区分鼻病毒携带者和新冠肺炎病毒携带者是非常重要的。将鼻病毒和新冠肺炎病毒患者分开会让这个过程快很多。
高%vol 的白细胞表明身体正在对抗病毒。
当携带病毒时,身体不能产生足够的血小板来帮助止血。
利用给定的患者血液数据,该模型可以预测患 SARS CoV-2 的概率。
分析中使用的代码
[## 零熊猫/新冠肺炎回归分析
介质物品分析代码。通过创建一个……为零熊猫/新冠肺炎回归分析的发展做出贡献
github.com](https://github.com/ZeroPanda/COVID-19-Regression-Analysis)
参考文献
统计学*介绍及在 R 中的应用;加雷斯·詹姆斯,丹妮拉·威滕,特雷弗·哈斯蒂,罗伯特·蒂布拉尼
[## 新冠肺炎的诊断及其临床表现
支持临床决策的人工智能和数据科学(3 月 28 日至 4 月 3 日)
www.kaggle.com](https://www.kaggle.com/einsteindata4u/covid19) [## 维基百科(一个基于 wiki 技术的多语言的百科全书协作计划ˌ也是一部用不同语言写成的网络百科全书ˌ 其目标及宗旨是为全人类提供自由的百科全书)ˌ开放性的百科全书
维基百科是一个免费的在线百科全书,由世界各地的志愿者创建和编辑,由维基媒体托管…
www.wikipedia.org](https://www.wikipedia.org/)
预测特许学校的弹性
原文:https://towardsdatascience.com/predicting-the-resilience-of-charter-schools-65be8594d75f?source=collection_archive---------31-----------------------
我开发工具帮助家庭在教育选择中感到安全的经历
图片来源:Neonbrand,via Unsplash ( Unsplash 许可)
特许学校对学生来说是一个很好的选择,但是关于特许学校稳定性的问题可能会阻止一些家庭给他们机会。在 Insight Data Science,我开发了一个工具来帮助加州的家庭了解上一所新开的特许学校的风险。
特许学校是公共资助但私人经营的,所以它们不是由传统的公立学区经营的,但它们不像私立学校那样收取学费。特许学校在过去 25 年中经历了大幅增长,2016 年全国约有 300 万学生入学(占公立学校总入学人数的 6%)。特许学校通常专注于特定的课程,如 STEM(科学、技术、工程和数学)或艺术,并且通常比传统的公立学校规模小。这些特点可能会吸引那些寻找更传统教育环境的替代方案的学生,并在一定程度上解释了特许经营行业的增长。
来源:国家教育统计中心
上特许学校的好处和风险
当我在亚利桑那大学攻读经济学博士学位时,我有机会为 BASIS Schools(一个特许学校网络)进行定量研究。在 BASIS 学校,我观察了课堂教学和其他各方面的管理,对网络提供的教育体验印象深刻。
BASIS Schools 从不起眼的地方起步:它的第一所学校于 1998 年在一个租赁的地方开办,那里以前是一个杂货店。BASIS Schools 在《美国新闻与世界报道》2019 年全国最佳公立高中排名中增加了两所高中,包括排名第三的学校 BASIS Scottsdale。
对于一个从以前的杂货店起步的学校系统来说,这已经不错了!来源:美国新闻与世界报道
不幸的是,并不是所有特许学校的故事都以同样的成功告终。由于特许学校通常缺乏传统公立学校管理的学校的运营和财政支持,它们可能面临更大程度的不稳定。
自 2010 年以来,加州开设了 831 所特许学校,其中 73.5%仍在运营(相比之下,同期开设的加州传统公立学校的比例为 90.4%)。意外的学校关闭可能会给家庭带来严重的痛苦,让家长和学生争相寻找合适的教育替代方案。
一位母亲的女儿就读于一所意外关闭的新特许学校,她说她会考虑再次就读一所特许学校,但想知道:
“…我怎样才能更好地评估每个人的数字?…我们需要问的难题是什么?因此,如果我们能够在未来防止这种情况发生,我们绝对会这样做。”
[## 特许学校关闭后会发生什么?
八岁的麦肯齐·惠斯勒的圣诞假期开局不利。她刚刚发现她不会…
www.wunc.org](https://www.wunc.org/post/what-happens-when-charter-school-closes)
介绍… CharterPredictor
了解到进入一所新的特许学校的潜在积极和消极方面,我创建了 CharterPredictor。在 charterpredictor.com 的,加州的家庭可以找到一所 2017 或 2018 学年新开的特许学校,并在学校上运行 CharterPredictor。CharterPredictor 随后为家长提供了一个衡量学校是“风险”还是“安全”选择的标准,以及学校在最初开放后继续运营三年的可能性。
CharterPredictor 还显示学校的初始注册人数,这是一个预测学校是否会继续运营的重要指标(学校资金与注册学生人数挂钩,如果注册学生人数不足,就很难覆盖固定成本)。CharterPredictor 还提供与感兴趣的学校相邻的新特许学校的附加信息,以便有兴趣支持新特许学校的家庭可以快速了解其他相关选项。
背景图片来源:Moren Hsu,via Unsplash ( Unsplash 许可)
虽然最终我们对所有特许学校的稳定性感兴趣,但对于这个项目的迭代,我想重点关注新的特许学校,因为这些学校特别容易关闭,因为它们往往缺乏更成熟的学校的资源。
CharterPredictor 背后的数据
CharterPredictor 背后的数据来自加州教育部,其中包括学校开学和关闭的信息,入学和人口统计信息。我收集了 2004 至 2018 学年的记录,然后将它们与美国社区调查中关于失业和教育水平的邮政编码水平数据结合起来。最后,我获得了与每所特许学校相邻的传统公立学校的家长评级(来自 great schools——great schools 就像 Yelp for schools,家长可以在这里留下对学校的评论和评级),以便衡量传统公立学校的竞争。
为了预测哪些新的特许学校有关闭的风险,我收集了 2004 年至 2016 年期间加州所有新的特许学校(包括 1017 所新学校),并使用 60/40 的拆分将数据分为训练集和测试集。CharterPredictor 然后使用 2017 年和 2018 年开设的学校的信息进行预测。
模拟学校关闭
我使用 XGBoost 来模拟特许学校的关闭,因为 XGBoost 给我的预测比逻辑回归模型更准确。XGBoost 模型导致曲线下面积(“AUC”)测量值为 0.95,而逻辑回归导致 AUC 为 0.94。虽然逻辑回归更容易理解,但我继续使用 XGBoost,因为我希望它能更好地推广到加利福尼亚州以外的新的州和新的功能。
我在几个超参数上使用交叉验证和网格搜索,包括最大树深度、收缩率和提升轮数来调整模型(您可以在 CharterPredictor GitHub 资源库查看构建分析数据集的代码)。预计关闭概率为 20%或更高的特许学校被归类为“有风险的”,因为如果我是一名家长,考虑到学校的稳定性,这似乎是我希望得到通知的水平,尽管这个截止值无疑有些武断。
在评估测试集时,经过训练的模型具有 94.1%的准确性,70.3%的召回率和 70.3%的精确度。在我们测试的 38 所实际关闭的学校中,CharterPredictor 可以正确地将其中的 26 所归类为风险学校。如果 CharterPredictor 的主要目标是保护学生免受不稳定因素的影响,我们可能会选择更低的关闭概率作为阈值来定义一所学校有风险。然而,重要的是避免过度热衷于将学校分类为风险学校,因为其中一些学校可能是我们希望家庭考虑的好机会。
结论和下一步措施
由于教育数据和特许学校政策因州而异,我想先从加州开始。下一步要使它成为更有用的工具,就要把它扩展到加州以外的地方。到目前为止,我相信 CharterPredictor 可以成为一个有用的工具,帮助加州家庭对他们的教育选择更有信心。
总的来说,我喜欢与跨越私人和公共领域的行业合作(如教育、卫生、能源),因为它们往往有大量可用的数据(我可能很难获得完全私人市场的企业细节和开业/倒闭)。此外,这些公共/私人市场往往与我们从社会角度非常关心的结果联系在一起。
关于作者
帕特里克·西泽克在亚利桑那大学获得经济学博士学位,专攻经验微观经济学。Patrick 目前是 Esurance 的数据科学家。
在 Esurance 工作之前,Patrick 是 Insight Data Science 的数据科学研究员。访问 Insight Data Science 的网站。
预测推迟的 2020 年橄榄球六国赛的比分
原文:https://towardsdatascience.com/predicting-the-scores-of-the-postponed-2020-rugby-six-nations-matches-bd9585c8495?source=collection_archive---------49-----------------------
访问和分析六国橄榄球数据,以及预测剩余延期比赛的分数
介绍
六国橄榄球锦标赛是一年一度的橄榄球联盟比赛,由英格兰、法国、爱尔兰、意大利、苏格兰和威尔士的国家队参加。锦标赛定于 2020 年 3 月 14 日结束;然而,由于新冠肺炎疫情,意大利对爱尔兰的倒数第二场比赛和所有的决赛都被推迟,意在改期。这是自 2001 年爆发口蹄疫以来,首次有超过一场比赛被推迟。鉴于此,威尔士橄榄球球迷and 的数据科学家对冠军赛的相关数据以及利用这些数据可能实现的目标感到好奇。这是我写的一篇关于我对六国橄榄球数据的分析,以及预测 2020 年推迟比赛的分数的文章。
六国橄榄球数据
首先要克服的问题是获得一些我可以用来模拟橄榄球比赛的数据。鉴于锦标赛始于 1882 年,我很早就决定要调查每一场可能的比赛,这需要花费相当多的时间和精力。随着锦标赛在 2000 年正式成为六国赛,我转向谷歌,开始寻找 10 年的橄榄球数据。
在网上查看后,我偶然发现了 ESPN Scrum 网站,它包含了从 1882 年以来所有六个国家比赛的基本数据。
ESPN Scrum 网站
最突出的一点是数据是表格形式的。当我看到这张写着“的桌子”时,我不禁暗自高兴。表格是我们的朋友,它让处理数据变得更干净,更轻松。也就是说,只有当数据源结构良好时,这才是正确的。
让我们看看这个网站还能提供什么。当你点击冠军年,在这种情况下,2020 年,你会被重定向到另一个页面,其中包含了迄今为止的结果表。我们可以看到,爱尔兰和意大利、威尔士和苏格兰、意大利和英格兰、法国和爱尔兰之间的最后四场比赛由于延期,因此没有与之相关联的比分。这些是我们想要预测的。
2020 年橄榄球六国记分牌至今
这个阶段需要考虑的重要的是可用的数据;也就是说,这些变量是否对匹配建模有用。我们目前知道的是,对于每支球队来说,比赛是在主场还是客场进行的,比分,以及球队是赢了还是输了比赛。在这个阶段,这些属性可能足以做出合理的预测。然而,关注球队层面的变量,比如每支球队的出场总数,以及球员层面的变量,比如他们的身高、体重、最*的表现等等,会很有趣。如果我们可以找到一个可靠的数据资源,并且数据容易访问,我们可能会在以后添加这些。但是首先,让我们从 ESPN 网站上摘录这些信息。
网页抓取
ESPN 网站不提供任何类型的可下载数据,所以是时候深入网页的来源,提高我的网络抓取技能了!
这个网站的好处在于,2000 年至 2020 年之间的每个记分牌的 HTML 表格都使用相同的 ID。这意味着,给定所有 20 个页面,我可以遍历 URL 并应用相同的预处理步骤来访问每个表。
首先,我复制了 2000 年到 2020 年之间的所有记分牌 URL,并将它们存储在一个数组中。然后,我遍历数组,发出 GET 请求从每个页面获取原始 HTML 内容。使用 BeautifulSoup,HTML 内容被解析为 Python,这样我就可以使用 ID scrumArticleBoxContent
找到特定的记分板表。
现在我有了所有字符串形式的 HTML 表,我可以使用read_html
函数将其解析为 Pandas。因为这个函数输出一系列数据帧,所以我可以使用concat
函数将它们连接成一个主数据帧。然后,我删除了通过 HTML 潜入的不相关的列。
一些行的日期为空,这也反映在 ESPN 网站上显示的表格中。通过使用ffill
函数,我可以用该列中最后一个已知的日期来填充那些缺失的日期。
为了预测每个国家在推迟的比赛中取得的分数,我们将不得不分开每个比赛记录,以便每个队在单独的一行中得到代表。在此之前,我们还必须考虑到国名的顺序代表了哪个国家是主场还是客场比赛。由于球队的名字有一个破折号作为固定的分隔符,我们可以根据破折号分割字符串,将左边的名字解析到home_team
列,将右边的名字解析到away_team
列。
现在队伍被分开了,我们也必须从队伍名称中删除分数。我们可以使用 Regex 从团队名称中提取数字,并将它们解析到home_team_score
和away_team_score
列中。
我们还想知道比赛场地的名称。鉴于这些数据在另一页的另一个表格中,我将打一张懒牌,假设在过去 10 年里,这些比赛在每个国家的同一个体育场进行。我可以通过迭代球场名称并从我的球场字典中分配相应的值,将球场名称与主队联系起来。
基于这最后一个数据帧,我们知道如果home_team_score
不为空,游戏就开始了,如果为空,那么这些就是被推迟的。我们可以根据这个规则将数据分为训练和测试。
让我们先关注一下训练数据。在这个博客的下一部分,我需要知道哪个国家赢了这场比赛。这不会作为一个变量包含在游戏比分预测中。为此,我遍历训练数据帧,并将获胜的团队关联到一个winner
列。
最后,为了分割数据,使每个国家都是数据框中的一行,我可以根据国家是主场还是客场来选择这些国家,然后将它们附加到另一个国家的顶部。
快速分析
这篇博客的主要焦点是看我们是否能做出合理的比赛分数预测。然而,我认为快速查看数据中是否存在任何潜在模式也很有趣。我感兴趣的一件事是,与客场比赛相比,一个球队在主场比赛时是否会赢得更多比赛,这两者之间是否存在某种关联。
围绕主场优势有很多卓有成效的研究。也就是说,有没有据说主队比客场队获得的好处?这些好处可以归因于支持球迷对竞争对手或裁判的心理影响、时区或气候的差异、旅行后的疲劳以及许多其他因素。所以,我想知道 10 年来 6 个国家的数据是否反映了这一点。
熊猫的correlation
函数用于查找数据帧中各列之间的成对相关性。因为这个函数忽略任何非数字数据,所以必须首先将它们映射到某种数字表示。熊猫有另一个内置功能可以为你处理这些。当您将列的数据类型转换为category
时,该列会将非数字数据转换为分类表示。因此,在这种情况下,如果我们要查看一支球队在主场或客场比赛时与他们输赢之间是否存在相关性,例如,这些列将把win
转换为 1,把lose
转换为 0。
如果我们对整个数据集应用correlation
函数,我们会得到 12%的相关分数。相关性旨在最大化其价值;也就是说,较高的分数意味着属性之间有很强的关系。所以在这种情况下,12%的低得分表明没有太大的主场优势。
现在,我不是 100%确信这是真的。当我的祖国威尔士在卡迪夫千年体育场主场比赛时,我确信当威尔士观众放声高唱卡隆·兰时,这点燃了威尔士橄榄球队的某种激情。我自己想想都起鸡皮疙瘩!所以,我们来看看这个。
如果我们关注威尔士在 10 年六国赛中的表现,我们可以绘制出一些结果。首先,我们来看看他们的总体表现。10 年来,威尔士队参加了 100 场锦标赛。在这 100 场比赛中,威尔士赢了 52 场,输了 45 场,平了 3 场。
如果我们看看威尔士主场 49 场比赛的结果,他们赢了 28 场,输了 20 场,平了 1 场。
最后,如果我们看看威尔士 51 场客场比赛的结果,他们赢了 24 场,输了 25 场,平了 2 场。
鉴于这些结果,可以有把握地说correlation
指标反映了相同的输出。与客场作战相比,威尔士主场作战时只多赢了 4 场比赛。但这并没有抵消我们的主场优势。这只告诉我们这个数据集内的相关性。我们可以将其他几场橄榄球比赛纳入分析,这些比赛可能会改变这一结果。
进行分数预测
将主场优势放在一边,我想看的下一件事是预测剩下的延期比赛的比分。有两种监督学*方法。回归用于预测连续值,而分类预测离散输出。例如,预测房子的英镑价格是一个回归问题,而预测肿瘤是恶性还是良性是一个分类问题。由于橄榄球比赛的最终得分在技术上可以是任何正数(甚至是零),我们将研究回归方法。
首先,让我们为训练和测试添加一个标签,这样我们就可以知道哪个数据集是哪个数据集。然后我们将它们组合起来,并对team, stadium
和home_or_away
列进行编码。这是为了确保在我们再次分割它们之后,我们在每个集合中有相同的列和编码。这里需要注意的是,我没有将date
作为建模中的一个变量。现阶段我只是希望能够根据前面几场的比分来预测剩下几场的比分。此外,由于锦标赛通常在每年的同一时间举行,我不认为这对造型有多大影响。如果是季节性的,这可能是一件有趣的事情。
一旦我们对数据进行了编码并再次将其拆分,这样我们就有了训练集和测试集,我们将需要再次拆分我们的训练数据,这样我们就有了验证集。也就是说,我们将从训练集中抽取一个数据样本,这样我们就可以评估我们的模型在预测这些样本的分数方面的性能,因为我们已经知道答案。为此,我们将抽取 30%的训练集样本。所以在 610 个记录中,有 183 个样本。我们还将确定哪些列是属性,哪些是标签。属性是自变量,而标签是我们想要预测其值的因变量。现在我们已经对数据进行了编码,我们有 14 个属性,我们希望根据这些属性来预测分数。因此,我们的属性被设置为 X 变量,而score
列被设置为 y 变量。
现在来训练一个模型。这个问题虽然是回归问题,但不是线性问题。并不指望每支球队在每场比赛后得分都会增加。这就抵消了那些方法。在这种情况下,我决定使用一个 RandomForestRegressor ,因为该算法易于使用,相对准确,而且与标准决策树相比,它可以减少过拟合。随机森林算法创建了几个决策树,在特征权重中注入了一些随机性。这些决策树然后被组合以创建一个用于最终分析的森林(因此是决策树 ) 的随机森林)。该算法既支持分类,也支持回归,使其非常灵活地用于各种应用。
在构建和训练我们的模型之前,我们首先需要设置一些超参数。这些参数通常是最难设置的,因为这些设置通常没有完美的值。一般的经验法则是最初坚持使用默认值,然后一旦模型被训练和测试,就开始使用试错法来调整这些值,直到获得最佳结果。对于这个模型,我发现 50 个 n 估计值和 4 个 max_depth 是提供最佳结果的一组很好的值。有关这些特定设置的更多详细信息,可在官方 scikit-learn 文档中找到。
我将在X_train
(属性)和y_train
(标签)上拟合模型,然后预测我们从训练中移除的验证样本X_val
的得分y_pred
。然后,我会通过测量均方根误差(RMSE)来比较预测值和实际得分(T4)。
RMSE 是残差方差的平方根。它表示模型与数据的绝对拟合。也就是说,观察到的数据点与模型的预测值有多接*。它还有一个有用的特性,就是和你要预测的变量在同一个单位里;所以在这种情况下。
模型的 RSME 结果是 10.1 (10)分…好吗?不好?绝对不完美。由于大多数球队每场比赛得分不到 40 分,10 分的误差并不是特别准确。正如这里所展示的,该模型在预测所有结果的分数方面做了相当多的工作。在预测得分较低的游戏时,该模型似乎表现得更好,但不是明显更好。也许如果我们把那些高分匹配从图片中去掉,我们可能会看到模型中的错误减少。但我们希望捕捉这些可能性,不会把它们视为离群值。这是需要进一步调查的事情。
让我们看看这个模型对延期比赛的预测得分。我们可以在X_test
上应用模型,并将预测作为一列附加到测试数据帧上,这样更容易阅读。
好的。模型还没有给出不切实际的预测!预计英格兰会以 36 比 13 战胜意大利。虽然这么说让我很痛苦,但考虑到英格兰目前领先赢得整场比赛,这似乎是一个令人尊敬的预测。爱尔兰看起来像预测他们会输给法国 19 比 25。同样,这似乎不是一个不切实际的预测。在每场比赛以大约 10 分的优势击败英格兰和意大利之后,法国和英格兰并列榜首。预测威尔士 25 比 16 赢苏格兰(耶!🏴).在只赢了意大利之后,这意味着我们将会避免那个木勺!最后,预计爱尔兰将以 25 比 11 战胜意大利。
结论
那么,我从这个分析中学到了什么?
非线性回归问题并不总是容易的。虽然模型的 RSME 没有我希望的那么低,但我怀疑这是因为数据的可变性。有时威尔士在球场上全力以赴,以超过 40 分的比分获胜,但其他时候,他们真的没有!这是我想进一步调查的事情。我还想在预测中加入其他变量,比如天气状况,裁判是谁,因为他们总是为威尔士的失利负责..还有更多!
当前橄榄球六国 2020 领先委员会
然而,该模型预测的分数并没有那么不切实际。根据 2020 年锦标赛的分数,预测的产出遵循类似的趋势。总体而言,如果没有奖励积分,法国和英格兰可能会成为 2020 年橄榄球六国赛的共同赢家。
完整的笔记本,请查看下面我的 GitHub 回购:https://github.com/LowriWilliams/Rugby_Six_Nations_2020
如果你喜欢这篇文章,别忘了点赞和分享。
利用网络预测 R-1 中的新冠肺炎病例
原文:https://towardsdatascience.com/predicting-the-spread-of-covid-19-using-networks-in-r-2fee0013db91?source=collection_archive---------42-----------------------
激励和创建网络
第二部分可以在这里找到。
像所有传染病一样,新冠肺炎病毒的传播发生在非常局部的水平上。它不只是在世界各地随机跳跃,它必须在人与人之间传播,这些人必须旅行到一个新的地方传播病毒。正是因为这个原因,网络经常被用来帮助模拟疾病的传播,无论是通过使用社交网络来模拟疾病在人与人之间的传播,还是通过地理网络来帮助我们根据邻*地方发生的事情预测疾病的爆发。
在这个博客系列中,我们将关注地理网络,其中节点是地点,如果两个地点相邻,则边连接这两个地点。最终,我们将尝试使用这样一个网络,根据邻*地区的 Covid 病例来预测一个地区的 Covid 病例。
这种方法的准确性将受到限制,因为它没有考虑流行病学因素(如群体免疫和社会距离)或其他地区联系方式(如火车)。然而,这个博客系列仍然为可视化网络和使用它们创建预测分析的特征提供了有益的指导。它还表明网络分析可能是更大的 Covid 模型的有用部分。
(图片由作者创作)
在英国,发布 Covid 案例的最小地理区域被称为中间层超级输出区域(MSOAs ),因此我们将重点关注这些区域。你可以在这里的一个互动地图里看到这个数据,在这里下载。
在这第一部分中,我们将创造一些形象化的东西来激发为什么这种方法可能有效,然后我们将创造出上图中看到的网络。我们将展示代码,同时,所有代码都可以在 github 上找到。
这些都是用来创建本帖中显示的可视化的包。
# Set up ----
# Load packages
library(dplyr)
library(readr) # Loading the data
library(tidyr)
library(sf) # For the maps
library(sp) # Transform coordinates
library(ggplot2)
library(viridis)
library(gganimate) # For the animated map# Network packages
library(igraph) # build network
library(spdep) # builds network
library(tidygraph)
library(ggraph) # for plotting networks
动机
为了了解这种方法可能奏效的原因,我们将看看莱斯特,该市 6 月份的 Covid 病例激增,导致英国首次局部封锁。我们将通过使用{ggplot2}和{sf}包创建地图来可视化 Covid 在该区域的分布,并使用{gganimate}包制作动画。
我们需要下载案例数据(可以直接从 URL 下载),并将其转换成正确的格式。初始表很宽(每个 MSOA 一行,每周一列),有些周没有数据,所以我们利用相对较新的{tidyr}和{dplyr}函数where
、pivot_longer
和across
来清理这些数据。
注意:自从这篇文章发表后,数据和访问数据的位置都发生了变化。这里的新网址是。我们在第 2 部分中使用这些新数据,你可以在 github 上访问新代码。
url <- '[https://c19downloads.azureedge.net/downloads/msoa_data/MSOAs_latest.csv'](https://c19downloads.azureedge.net/downloads/msoa_data/MSOAs_latest.csv')
msoa <- readr::read_csv(url, col_types = cols()) %>%
# Drop columns that are all NA
select(where(~!all(is.na(.)))) %>%
# Pivot longer
pivot_longer(dplyr::starts_with("wk_"),
names_to = "week",
values_to = "cases",
names_prefix = "wk_") %>%
# Turn week to numeric
mutate(week = as.integer(week)) %>%
# Turn NAs into 0s
mutate(across(c(last_7_days, cases),
.fns = ~ifelse(is.na(.), 0, .)))
生成的表如下所示(为了简化,我去掉了前几列)。前两列告诉我们地方当局辖区(LAD ),其面积比 MSOA 还大。接下来的两列告诉我们 MSOA。最后两列告诉我们那一周,以及那一周有多少阳性病例。“last_7_days”列告诉我们从上一整周到今天的阳性病例数。
我们应该做的第一件事是检查莱斯特峰值是否真的出现在数据中,这可以通过绘制简单的线图来完成。
msoa %>%
group_by(lad19_nm, week) %>%
summarise(cases = sum(cases))%>%
filter(lad19_nm == "Leicester") %>%
ggplot(aes(x = week, y = cases)) +
geom_line(size = 1) +
theme_minimal() +
ggtitle("Time series gaph of cases for Leicester")
(图片由作者创作)
我们看到数据中有一个很大的峰值,在第 25 周达到 500 例。
下一步是看看这是如何在 MSOAs 之间分配的。我们可以将它作为另一个线图来做(事实上,我们在 github 代码中也是这样做的),但这不会给我们与在地图上绘制相同的洞察力。
要绘制地图,我们必须下载英国 MSOAs 的形状文件,你可以在这里做。保存并解压缩整个文件夹后,我们可以通过以下方式加载它:
msoa_sf <- sf::st_read("data/maps/Middle_Layer_Super_Output_Areas__December_2011__Boundaries_EW_BFE.shp")
绘制莱斯特的 MSOAs 非常简单,只需将形状文件限制在莱斯特的文件中(我们通过内部连接来实现),然后向 ggplot 添加一个geom_sf()
。为了绘制病例数据,我们限制在特定的一周(让我们选择第 25 周的峰值)并加入病例数据。现在,我们可以根据第 25 周的阳性病例数来填充 MSOA 地区。
msoa_data_wk25 <- msoa %>%
filter(lad19_nm == "Leicester",
week == 25)# We see that covid cases are clustered in several MSOAs
msoa_sf %>%
inner_join(msoa_data_wk25 %>% distinct(msoa11_cd, cases),
by = c("MSOA11CD" = "msoa11_cd")) %>%
ggplot()+
geom_sf(aes(geometry = geometry, fill = cases)) +
# Everything past this point is just formatting:
scale_fill_viridis_c() +
theme_void() +
ggtitle(label = "MSOA map for Leicester",
subtitle = "The colour shows Covid cases during week 25")
(图片由作者创作)
这是我们第一次看到网络有用的迹象。我们看到邻*的澳门特别行政区也有类似的情况。这是有道理的。如果你在一个地方爆发疫情,你预计它会蔓延到邻*地区。
像这样可视化数据的一个缺点是,很难看到案例如何随时间变化。这就是{gganimate}的用武之地。{gganimate}是一个很棒的软件包,可以让您根据特定的变量来制作图形动画。它允许我们为每个星期创建上面的地图,然后为我们把它组合成一个 gif。
# gganimate
# Need to install transformr for this to work
p <- msoa_sf %>%
inner_join(msoa %>% filter(lad19_nm == "Leicester"),
by = c("MSOA11CD" = "msoa11_cd")) %>%
ggplot(aes(group = week)) +
geom_sf(aes(fill = cases)) +
scale_fill_viridis_c() +
transition_time(week) +
labs(title = paste0("New covid cases for MSOAs within Leicester"),
subtitle = "Week = {frame_time}") +
theme_void()# We define this to help us pick the right number of frames
num_weeks <- n_distinct(msoa$week)animate(p, nframes = num_weeks, fps = 1, end_pause = 4)
我们看到,到transition_time()
为止,这段代码看起来与我们上一张图表非常相似。唯一的区别是我们没有将数据过滤到特定的一周,我们在图的aes()
中包含了一个group = week
。transition_time()
是我们如何指示它使用week
作为变量来制作动画。
最后一点代码只是帮助我们指定一个好的帧数,这样每周都会得到相同的帧数。结果如下。
邻*地区的重要性再次凸显出来。高病例数从一个地区蔓延到邻*地区。此外,就在单个 MSOA 病例数达到峰值之前(发生在第 27 周),我们看到邻*地区的病例数也很高。网络分析能让我们预测到这个特殊的区域在第 27 周会有这样的病例高峰吗?只有一个办法可以知道。
网络
现在我们知道为什么网络可以帮助我们,让我们实际上建立一个。要定义一个网络,知道所有的节点是什么,以及它们如何连接在一起(即边)就足够了。
在我们的例子中,节点很简单,这些只是 MSOAs。我们知道,如果两个节点所代表的两个 MSOAs 在我们的地图上是邻居,那么我们希望这两个边是连接在一起的。幸运的是,来自{spdep}包的poly2nb()
函数(读“多边形到邻居”)帮助我们做到了这一点。它可以生成一个形状文件,并告诉我们哪些区域是邻居。
# First we just need to restrict to Leicester MSOAs for one week.
leicester_sf <- msoa_sf %>%
inner_join(msoa %>% filter(lad19_nm == "Leicester", week == 27) ,
by = c("MSOA11CD" = "msoa11_cd"))# Use the poly2nb to get the neighbourhood of each area
leicester_msoa_neighbours <- spdep::poly2nb(leicester_sf)
然后我们可以使用nb2mat()
函数(读作“矩阵的邻居”)把它变成一个邻接矩阵。对于网络,邻接矩阵是这样的:如果存在连接节点 i 到节点 j,的边,则单元 i,j 等于 1,否则等于 0。因此邻接矩阵定义了一个网络,事实上,我们可以使用{igraph}包中的graph_from_adjacency_matrix
函数来创建一个网络对象。
# Use nb2mat to turn this into an adjacency matrix
adj_mat <- spdep::nb2mat(leicester_msoa_neighbours, style = "B")
rownames(adj_mat) <- leicester_sf$msoa11_hclnm
colnames(adj_mat) <- leicester_sf$msoa11_hclnm# Use graph_from_adjacency_matrix to create a graph object from the adjacency matrix
leicester_network <- igraph::graph_from_adjacency_matrix(adj_mat, mode = "undirected")
您可以就此打住,但我发现{tidygraph}包提供了一种使用标准{dplyr}动词(我们将在后面看到)操作网络对象的惊人方法。所以我们用as_tbl_graph()
把这个网络对象变成一个整齐的图形对象。
# Use as_tbl_graph to turn this into a tidygraph
leicester_network <- igraph::graph_from_adjacency_matrix(adj_mat, mode = "undirected") %>%
tidygraph::as_tbl_graph()
现在我们已经创建了这个对象,我们如何与它交互?
打印对象显示我们的网络有 37 个节点和 91 条边。我们还看到它是由两个 tibbles 定义的,一个定义节点数据,另一个定义边缘数据。
> leicester_network
# A tbl_graph: 37 nodes and 91 edges
#
# An undirected simple graph with 1 component
#
# Node Data: 37 x 1 (active)
name
<chr>
1 Beamont Park
2 Rushey Mead North
3 Stocking Farm & Mowmacre
4 Bradgate Heights & Beaumont Leys
5 Rushey Mead South
6 Belgrave North West
# ... with 31 more rows
#
# Edge Data: 91 x 2
from to
<int> <int>
1 1 3
2 1 4
3 2 3
# ... with 88 more rows
注意,节点数据只包含 MSOA 的名称,边数据根据节点在节点数据中的位置告诉我们哪些节点是连接的。例如,边缘数据的第一行告诉我们“Beamont Park”和“Stocking Farm & Mowmacre”是邻居。
如果我们想可视化网络,我们可以使用{ggraph},它是{ggplot2}的网络特定扩展,工作方式大致相同。下面是我们如何创建一个简单的情节。节点位置由算法确定。
ggraph(leicester_network) +
geom_edge_link(colour = 'black', width = 2) +
geom_node_point(size = 5, colour = 'steelblue') +
theme_void() +
ggtitle("Network plot of MSOAs in Leicester",
subtitle = "Each node is an MSOA, and an edge joins two
nodes if they are neighbours")
(图片由作者创作)
如果我们能在之前的地图上覆盖这个网络,那就太好了。这将允许我们感觉检查网络,并使它更容易在网络和现实之间转换。
为了实现这一点,我们首先需要获得每个 MSOA 的中心坐标。幸运的是,我们下载的形状文件为每个 MSOA 提供了一对经纬度坐标。不幸的是,多边形本身处于不同的空间投影下。我们使用以下代码提取坐标并转换投影。
coords <- leicester_sf %>%
as.data.frame() %>%
select(LONG, LAT) %>%
sp::SpatialPoints(proj4string=CRS("+init=epsg:4326")) %>% # LAT LONG code
sp::spTransform(CRS("+init=epsg:27700")) %>% # UK grid code
as.data.frame() %>%
bind_cols(msoa11_hclnm = leicester_sf$msoa11_hclnm) # to allow us to bind on
coords
看起来是这样的:
LONG LAT msoa11_hclnm
<dbl> <dbl> <chr>
1 457176\. 309094\. Beamont Park
2 461975\. 307767\. Rushey Mead North
3 458317\. 307856\. Stocking Farm & Mowmacre
4 456550\. 306747\. Bradgate Heights & Beaumont Leys
5 461046\. 307294\. Rushey Mead South
6 459732\. 307380\. Belgrave North West
7 460299\. 306733\. Belgrave North East
8 458059\. 305765\. Abbey Park
9 462606\. 306391\. Hamilton & Humberstone
10 459885\. 305741\. Belgrave South
# ... with 27 more rows
通过绑定 MSOA 名称,很容易将它加入到我们的网络对象中。我们本质上想要将left_join
放到我们的节点表中。{tidygraph}让这变得非常简单。我们所要做的就是通过使用activate()
告诉它我们想对节点表做些什么,然后我们就可以使用我们都知道并且喜欢的经典动词,比如left_join()
。
# Join on cordinates and sf geometry
leicester_network <- leicester_network %>%
activate("nodes") %>%
left_join(coords, by = c("name" = "msoa11_hclnm"))
任何时候,您都可以使用as_tibble()
提取激活的 tibble(即节点或边)。如果我们现在这样做,我们会看到坐标已经成功连接。
leicester_network %>%
as_tibble() %>%
head name LONG LAT
<chr> <dbl> <dbl>
1 Beamont Park 457176\. 309094.
2 Rushey Mead North 461975\. 307767.
3 Stocking Farm & Mowmacre 458317\. 307856.
4 Bradgate Heights & Beaumont Leys 456550\. 306747.
5 Rushey Mead South 461046\. 307294.
6 Belgrave North West 459732\. 307380.
现在我们创建一个图形,在这里我们使用 MSOA 形状文件作为一个geom_sf
层,然后覆盖我们的网络。
ggraph(leicester_network, layout = "manual", x = LONG, y = LAT) +
geom_sf(data = leicester_sf, fill = "white") +
theme_void() +
geom_edge_link(colour = 'black', width = 2) +
geom_node_point(size = 5, colour = 'steelblue') +
ggtitle("MSOA network overlaying shapefile")
(图片由作者创作)
就这样,我们展示了网络正是我们想要的样子;每个节点都是一个 MSOA,如果两个节点是邻居,那么一条边连接两个节点。
下次
我们已经成功展示了为什么我们可以依靠网络来帮助我们理解 COVID 是如何传播的,以及如何构建和可视化这样一个网络。
在第 2 部分中,我们将看到网络结构如何让我们直观快速地创建强大的功能,然后使用这些新功能创建预测模型。
这篇文章中使用的所有代码都可以在 GitHub 上找到,这里的renv
被用来处理包版本和依赖关系。
使用 R-Part 2 中的网络预测新冠肺炎的传播
原文:https://towardsdatascience.com/predicting-the-spread-of-covid-19-using-networks-in-r-part-2-a85377f5fc39?source=collection_archive---------54-----------------------
生成网络要素并进行预测
在第一部分中,我们展示了为什么网络可以用于预测新冠肺炎的传播,我们创建并可视化了一个名为 MSOAs 的英国小区域地理网络。我们最后展示了莱斯特这些地区的网络,覆盖在莱斯特的地图上(如下所示)。我们关注莱斯特,因为这是英格兰第一个实行局部封锁的地区。
(图片由作者创作)
在第二部分也是最后一部分,我们将使用该网络来生成每个区域的要素。最后,我们将使用这些功能创建一个模型来预测一个地区在未来一周将获得的 Covid 病例数。
除了我们在第一部分中涉及的工作,我们将展示代码,你可以在 github 上找到所有的代码。
我们从两个 R 对象开始。第一个是msoa
,它是一个包含 MSOA 案例数据的 tibble,第二个是msoa_network
,它是英国每个 MSOA 的{tidygraph}网络对象,其中的节点是 msoa,如果它们是邻居,则一条边连接两个 msoa。上面的图像向我们展示了这个网络,但只是针对莱斯特。
这些都是用来创建本帖中显示的数据和可视化的包。
library(dplyr)
library(readr) # Loading the data
library(tidyr)
library(sf) # For the maps
library(ggplot2)
library(viridis)
library(cowplot)
library(glue)# Network packages
library(igraph) # build network
library(spdep) # builds network
library(tidygraph)
library(ggraph) # for plotting networks
使用我们的网络创建要素
有两种方法可以使用我们的网络来创建功能,这有助于将它们分开考虑。
第一类是基于网络结构的特征,例如,一个区域的邻居数量(也称为其度数)。这里的想法是,LAs 的分组和连接方式可能是 Covid 如何在网络中传播的良好指示。
第二个是基于邻*地区正在发生的情况的特征,例如,在邻*的 MSOAs 中有多少病例。这里的想法是,一个被高病例数包围的地区可以预期在接下来的一周内看到自己的上升。
基于网络结构的特征
我们将研究其中一些特性,展示我们是如何为我们的网络推导出这些特性的,然后展示这些特性在莱斯特每个 MSOAs 中的价值。
度数=邻居数量。你可以从下面的图片中看到,我们有两种不同的方式来观想这一点。
首先是使用网络,这样可以更容易地看到连接每个 MSOA 的边。使用这个网络,您可以很容易地计算任何中央 MSOAs 的所有邻居,以查看它是否与它们的度数相匹配。我们不能对接壤的 MSOAs 这样做,因为我们没有标绘他们所有的邻居,因为他们不都在莱斯特。
第二种方法是使用地图来可视化。这可以更容易地看到整个洛杉矶的价值分布。
(图片由作者创作)
介数=一个节点有多少条最短路径。这是一种节点重要性的度量。如果你想从一个 MSOA 旅行到另一个,总有至少一条最短的路线可以减少你必须经过的机场数量。因此,您可能会认为介数高的节点会有更多的人通过它。在现实中,这种方法不太可能代表这一点,而且现实生活中的最短旅行距离与您旅行经过的 MSOAs 最小化没有任何关系。然而,它确实提供了一些额外的背景,模型可能会发现有帮助。
同样,由于我们只是绘制了整个网络的一个子集,我们不能仅仅从莱斯特网络来计算介数。
(图片由作者创作)
三角形=该节点所属的三角形数量。三角形就是有三个节点相互连接的情况。在我们的例子中,当一个 MSOA 与两个也彼此相邻的 msoa 相邻时,就会发生这种情况。我们可能期望 Covid 在有许多三角形的区域中传播得更多,因为 MSOAs 连接得更多。
(图片由作者创作)
传递性=有多少局部聚类。这是对节点的邻居中有多少也是邻居的度量,通过将邻居对的数量除以该节点所在的三角形的数量来计算。社交网络具有很高的传递性,因为朋友的朋友很可能自己也是朋友。我们可能会认为更高的值会影响 Covid 在网络中的传播方式,因为这意味着区域之间的互联程度更高。
(图片由作者创作)
通过将方便的{igraph}函数与{tidygraph} mutate
方法相结合,创建这些功能非常容易。
我们从网络对象开始。我们activate
了节点,所以它知道下面的 mutate 将应用于底层节点数据。然后我们应用 mutate,将我们的新特性定义为应用于我们的网络对象的相应的{igraph}函数,它是使用.G()
获得的。
msoa_features <- msoa_network %>%
activate("nodes") %>%
mutate(degree = igraph::degree(.G()),
betweeness = igraph::betweenness(.G()),
triangles = igraph::count_triangles(.G()),
transitivity = igraph::transitivity(.G(), type = "local")))
唯一的区别是对于传递性你必须指定你想要使用局部传递性(即每个节点的传递性)而不是网络传递性(这是整个网络的单一度量)。
基于邻域的特征
现在,我们希望根据相邻 MSOAs 中正在发生的情况(例如,病例数)来生成要素。与上面只需要生成一次的特性不同,我们需要为每周的案例数据生成这个特性。首先,我们将只看一个特定的星期,即第 25 周,这是莱斯特的第一次高峰。
首先,我们将案例数据连接到我们的网络对象。同样,我们利用了在{tidygraph}对象上使用像left_join()
这样的{dplyr}动词的方式。
msoa_cases_network <- msoa_network %>%
activate("nodes") %>%
left_join(msoa_features %>% filter(week == 25),
by = c("name" = "msoa11_cd"))
现在有了一整套的{tidygraph}函数,可以让你在邻居级别应用自定义函数(例如,参见 map_local )然而,我们在这里想要的非常简单,最有效的计算方法(很远)是使用邻接矩阵。
你可能还记得上次提到的邻接矩阵定义了一个网络。对于网络中的每个节点,它都有一行和一列,如果一条边将节点 i 连接到节点 j ,则单元 (i,j) 的值为 1,否则为 0。
具有相应邻接矩阵的网络示例。Jesus Najera 创作的图片,作为图论博客系列的一部分。
我们首先使用邻接矩阵来创建我们的网络,然而,通过以下方式从现有网络中获得邻接矩阵非常容易:
adj_matrix <- igraph::get.adjacency(msoa_cases_network)
现在,如果我们有网络中每个节点的值的向量,例如 covid 情况,让我们想想如果我们将邻接矩阵乘以这个向量会发生什么。结果将是一个相同长度的向量。位置 i 将只是原始向量的所有值的总和乘以它们在邻接矩阵的行 i 中的位置。但是我们知道第 i 排除了第 i 排的邻居都是 0,而在那些地方,正好是 1 。因此,我们看到结果只是所有节点中所有 Covid 案例的总和,而这正是我们想要的!因为这只是矩阵乘法,所以它发生得非常快。
因此,我们现在知道,为了生成这种“相邻 MSOA 中的 covid 案例”特征,我们只需将邻接矩阵乘以每个 MSOA 中的 Covid 案例的向量。这可以通过以下方式轻松实现:
msoa_cases_network <- msoa_cases_network %>%
mutate(cases_in_neighbourhood =
as.vector(adj_matrix %*% .N()$cases),
cases_in_neighbourhood_average =
cases_in_neighbourhood/degree)
同样,我们可以将mutate
应用于 tidygraph 对象。我们通过使用访问网络底层节点数据的.N()
得到案例向量,然后使用$cases
得到案例向量。我们使用矩阵乘法将我们的邻接矩阵与此相乘,在 R 中用%*%
表示。最后,我们将结果包装在as.vector()
中,这样 R,更确切地说是 mutate,就知道把它当作一个向量。我们通过除以节点的度来计算平均案例数。
为每周创建此内容
现在我们已经这样做了一周,我们只需要每周都这样做。我以下面的方式使用lapply
来做这件事。如果你不熟悉应用系列,它类似于for
循环,但更有效。我们每周应用的代码应该看起来非常类似于我们上面所做的。这里的关键区别是,我们在数据中每周都这样做,然后在最后将所有结果绑定在一起。
data_for_predictions <- lapply(msoa_features %>%
distinct(week) %>%
pull(week),
function(wk){
message(paste0("Creating features for week ", wk))
# Filter to the correct week
weekly_data <- msoa_features %>%
filter(week == wk)
# join onto the network and create network features
weekly_network <- msoa_network %>%
activate("nodes") %>%
left_join(weekly_data, by = c("name" = "msoa11_cd")) %>%
mutate(cases_in_neighbourhood =
as.vector(adj_matrix %*% .N()$cases),
cases_in_neighbourhood_average =
cases_in_neighbourhood/degree)
# Extract as tibble
weekly_network %>%
as_tibble()
}) %>% # Bind all these tibbles together
bind_rows()
这样,我们就创建了一个数据集,对于进行预测建模来说,它应该看起来更熟悉。我们每个 MSOA 每周有一行,有很多功能可以帮助我们预测下周。我们在下面提供了一个摘录,这样你就可以看到我们为某个 MSOA 的几个星期的子集创建的这些新功能。注意,我们已经创建了一个“cases_next_week”变量,因为这将是我们的结果变量。换句话说,我们将使用所有其他变量来尝试和预测下周会有多少病例。
(图片由作者创作)
像其他功能一样,我们可以在地图上看到任何一周的这些功能。下面的可视化显示了第 25 周的情况。换句话说,一个区域越亮,其相邻区域的病例越多。我们称这个变量为“案例 nb”。
(图片由作者创作)
创建预测病例的模型
我们将使用上述数据集,尝试使用其他变量来预测“cases_next_week”。这篇博文不打算深究预测建模或机器学*方法或最佳实践。相反,我们将向您展示如何使用上面创建的数据集创建一个简单的线性模型。如果你正在使用这个博客系列从网络中创建你自己的预测模型,你可以用你最喜欢的模型来代替。
训练和测试数据集
为了了解模型结果的概括程度,我们将数据分为训练数据集和测试数据集。我们这样做是为了让大约 70%的数据用于训练,30%用于测试。
我们使用 week 变量进行划分,因此我们对某个时间点之前的所有数据进行训练,并对其余数据进行测试。这是为了避免我们对过去的数据进行测试,这可能会导致数据泄漏。如果我们试图将这个模型付诸实践并预测下周发生的事情,我们将永远不会有来自未来的训练数据。
processed_df <- data_for_predictions %>%
select(name, week, degree:cases_in_neighbourhood_average) %>%
drop_na() # This is a bit of a cheat to get results quickly
training_threshold <- 0.7
training_weeks <- processed_df %>%
distinct(week) %>%
slice(1:round(nrow(.) * training_threshold)) %>%
pull()train_df <- processed_df %>%
filter(week %in% training_weeks)test_df <- processed_df %>%
filter(!week %in% training_weeks)
模型创建
现在我们使用lm
函数创建一个模型。
linear_model <- lm(cases_next_week ~ .,
data = train_df %>% select(-name, -week))
在这里,我们可以检查模型的摘要,并放心地看到“cases _ in _ neighbourhood _ average”与您认为极其重要的“cases”具有相似的大小系数。这意味着 MSOA 多了一个病例,对下周的病例会产生类似的联想效应,而不是我们在每个邻*地区都多了一个病例。换句话说,模型依赖于我们的邻*特征。
(图片由作者创作)
有趣的是,看起来基于网络结构的特征与下周的案例有更不确定的关系,并且没有我们预期的效果。比如他们的系数大部分都是负的。这可能与以下事实有关:如果区域中没有太多 Covid,那么网络结构容易受到 Covid 传播的影响就没有多大意义。
我们可以用下面的方法为我们的测试数据创建预测。
test_pred <- stats::predict(linear_model,
test_df %>%
select(-name, -week, -cases_next_week))
这让我们能够比较对未知数据的预测和观察。例如,在这里,我们计算测试数据的 RMSE,看到它是 8.36,比训练数据达到的 0.35 高得多,显示模型遭受过拟合。
pred.obs <- tibble(pred = test_pred,
obs = test_df$cases_next_week)rmse <- pred.obs %>%
summarise(sqrt(mean((obs-pred)^2)))
使用模型
显然,像这样的模型有数百种不同的使用方式。一种方法是将输出可视化在地图上。下面显示了我们的模型根据第 40 周(在我们的测试数据中)的数据对第 41 周每个 MSOA 中的病例进行的预测,并将其与第 41 周实际发生的情况进行了比较。
左边的地图显示实际案例,右边的地图显示根据我们的模型预测的案例。(图片由作者创作)
模型性能和改进
现在你可能可以从上面的视觉化图像中看出,这个模型并不是特别好。它在很多领域都是错误的,即使它是正确的,它也严重依赖于该领域已经有多少案例,这不是很有帮助。为了让你了解这一点,如果我们用一个基线模型来代替这个模型,这个基线模型只是假设病例数不变,我们将得到 8.18 的 RMSE,比我们的线性模型好。
如果我们希望在现实世界中使用这个模型,那么需要做大量的工作来理解如何使用它,并围绕它设计一个模型管道。这只是预测建模的本质。如果你自己要做这件事,这里有一些你可能想探索的事情的想法:
- 将结果变量改为“病例数的变化”,以尝试消除对使用当前病例数的过度依赖。
- 使用分类结果变量,如“下周病例会增加 x%吗”或“病例会超过此固定阈值吗”。
- 考虑到每个 MSOA 的人口,所以较小的地区不会有偏见。
- 使用可以减少过度拟合的更复杂的模型(例如,random forest 或 xgboost)。
- 添加更多数据或特征,例如,考虑交通连接区域的方式或额外背景,如该区域的城市化程度。
- 更多的特征工程,例如标准化特征,或者向特征添加噪声(这可以通过减少过拟合来提高模型性能)。
结论
这篇文章有效地展示了你如何从关于事物如何联系的信息(如地理上的邻居)开始,并创建许多可用于预测建模的有用特征。
新冠肺炎继续对我们的生活和社会产生巨大影响。由于疾病传播的指数性质,得到任何关于哪里可能爆发疾病的警告会在应对的选择和影响方面产生巨大的差异。已经有很多令人印象深刻的建模工作在进行,试图给出这个额外的警告(例如帝国理工学院的这个工作)。这篇博客文章表明,网络可以用来提供额外的功能,使模型更加准确,从而帮助我们对抗这种疾病。
这篇文章中使用的所有代码都可以在 GitHub 上找到,这里的renv
被用来处理包版本和依赖关系。
预测股市很难:创建一个机器学*模型(可能)不会有帮助
原文:https://towardsdatascience.com/predicting-the-stock-market-is-hard-creating-a-machine-learning-model-probably-wont-help-e449039c9fe3?source=collection_archive---------9-----------------------
马库斯·温克勒在 Unsplash 上的照片
来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
有许多关于制作机器学*模型来预测股票价格的文章和方法。我不是在这里宣布他们是错误的或被误导的。事实上,我认为这么多人对试图解决一个古老的问题感兴趣是件好事,对 Python 等编程语言的贡献在一定程度上帮助了投资的“民主化”,人们现在可以在几分钟内建立一个相对复杂的机器学*模型。相反,本文想要展示的是支持股票价格可能无法预测这一观点的证据。具体来说,本文将使用 Python 来强调股票价格或多或少遵循随机游走的思想。文章的主旨是,随机漫步并不排除击败市场的可能性,也不主张将投资模型扔到一边,但它应该发出信号,这些模型应该以极度的谨慎和勤奋来构建,并不断进行重新评估。建立交易算法的过程在很多情况下是一个终生的过程。
随机游走理论综述
股票价格的随机游走理论有很长的历史,最早是在 19 世纪中期提出的,然后在 20 世纪中期由尤金·法马和伯顿·马尔基尔等人推广,后者以他的经典之作《华尔街的随机漫步》使随机游走理论在投资界变得常见。该理论最简单的形式是,股票价格无法预测,因为股票价格的变化是随机的。该理论假定金融市场是有效的。也就是说,由于市场参与者是理性的利润最大化者,所有公开信息都包含在股票的当前价格中。如果存在任何异常,它将被迅速利用和消除,从而导致更高效的状态。例如,假设市场认为苹果的股票被低估了。随机游走理论假设市场参与者会立即购买股票,这反过来会导致股票不再被低估。这种“完美”的效率使得股票价格被相应地定价,并反映所有可用的信息。新消息是唯一能改变股票价格的东西,因为消息周期是不可预测的,所以股票价格会随机波动。
你可能已经注意到,随机漫步假说(RWH)做了几个假设,其中最主要的是金融市场是有效的。然而,泡沫存在的事实似乎推翻了这一假设,从而对随机漫步理论提出了质疑。此外,该理论催生了行为金融学领域,理查德·塞勒是其主要支持者之一,该理论旨在表明投资者在许多情况下远非理性行为者,这反过来意味着当行为者经常非理性行为时,市场很难有效。
尽管有这些(合理的)反对意见,随机漫步假说得到了大量经验证据的支持,本文的剩余部分将借助 Python 强调其中的一些。代码可以在这里找到
用 Python 演示随机漫步
根据 RWH 的说法,因为股票价格遵循随机游走,所以股票今天的价格是对其明天价格的最佳预测。为了检验这种说法,我们可以将某一特定股票在不同时间间隔内的滞后价格与该股票的最*价格进行比较,以确定它们是否代表今天的价格。
滞后 1、2、3、4 和 5 天的 DOCU
同样,这里的想法是评估今天的价格是否是明天价格的最佳指标。如果是这样的话,那么股票会相应地定价,因此会随机波动。另一方面,如果滞后价格与今天的价格几乎没有关系,那么今天的价格就不是股票价格的最佳预测者——也许过去的价格是——因此市场是无效的。使用线性回归来评估这一点,我们可以看到滞后价格与今天的价格有着极其密切的关系。在这个特殊的例子中,DocuSign 的滞后价格代表了今天的价格。
将这一分析扩展到纳斯达克 100 指数中的每一只股票,这一现象被证明是普遍的。纳斯达克 100 指数中每只股票的每个线性回归模型的 r 平方得分为 0.99,表明该模型几乎解释了数据中的所有变化。也就是说,滞后价格系列,尤其是 lagged_1,完全解释了最*的价格:
这是否意味着投资者不能选股
RWH 的一个含义是,传统的选股方法,如技术和基本面分析,用处不大。这两种技术都意味着投资者可以利用这些方法来制定有利可图的交易策略,但 RWH 认为这通常会弄巧成拙,因为交易者会利用并因此抵消这些异常,使市场变得有效。然而,该假说允许在某些情况下选股,分析师会比遵循简单的买入并持有政策的投资者做得更好,只要他能比其他分析师和投资者更快地识别实际价格和内在价值之间存在不可忽略的差异的情况,并且如果他能更好地预测重要事件的发生并评估它们对内在价值的影响。
结论
是的,随机漫步理论享有实证支持,并为算法设定了很高的标准,以持续不断地预测股价走势。但这并不自动意味着建立投资模型的雄心被抛弃。甚至 RWH 也允许 T2 的一些交易者表现优于其他交易者。吉姆·西蒙斯是一个克服困难的完美例子。他花了数年时间试图“解决市场问题”,一个方法接一个方法都失败了,最终取得了突破,经过了数年和无数个小时来完善他的方法。即使是现在,他的公司也只有一半的交易是正确的。重点不是阻止你建立下一个机器学*模型,而是现实地设定期望,并鼓励你长期坚持下去。
进一步阅读
股票市场价格的随机波动
漫步华尔街
解决市场的人
用机器学*预测股市。标杆管理。
原文:https://towardsdatascience.com/predicting-the-stock-market-with-machine-learning-benchmarking-44181286389?source=collection_archive---------26-----------------------
亨尼投资
用随机森林分类器绘制基线。
图片作者佩什科夫
本文描述了一个机器学*模型的实现细节和基线性能,该模型用于预测过去 8 年中 S & P500 公司下一年的收入。如果你还没有看到介绍,请阅读用机器学*预测股市。引言。熟悉背景、问题陈述和我选择的解决方法。我们开始吧!
什么是基线?
基线模型是一个简单的模型,用于建立一个参考点,并有效地跟踪一个人的进展。我如何知道我在开发机器学*管道的各个方面时取得了进展?当新型号比以前型号表现得更好时,我知道我取得了进步。在本文中,我将构建这个先前的模型,它将成为下一个更复杂模型的基准。此外,它将帮助我对重要的特性建立一些直觉,并帮助确定进一步开发的优先级。
偏见意识
在机器学*中最危险的两个问题,在我看来就是未来泄漏和过拟合。
未来泄漏是指将表示在预测时不可用的信息的特征包括到训练数据集中。这是一个时间序列问题。因此,防止未来泄漏的第一步是确保在每个时间戳使用的功能不来自该时间戳之后发布的报告——这是一个快速验证,但我们最好确定。
过度拟合指的是以这样一种方式训练模型,它可以很好地预测过去(在训练集上做得很好),但不能预测未来。在这项研究中,这个问题可能来自于财务特征的概念不会随着时间的推移而发生巨大的变化。如果我们在训练和验证集合中的不同时间戳都包括同一家公司,并且这家公司碰巧持续增加其收入,那么模型将最有可能了解什么特征组合代表这家公司(这将产生正确的预测),而不是什么特征组合驱动实际增长。我希望我的模型能够对以前从未见过的公司做出正确的预测。因此,我需要确保它学*功能的趋势,而不是公司的趋势。
培训—验证—保持
有了 8 年的历史和 500 家公司,我将使用每个时间戳每个公司 (2)年的历史数据。由于每个时间戳我需要 2 年的历史数据,所以可预测的最早年份是 2014 (其中 2012 和 2013 构成特征),最晚是 2019 (其中 2017 和 2018 构成特征)。我使用 2018 年和 2019 年作为样本外的维持,它不会用于训练模型。相反,我将使用它来评估和报告模型性能。
该模型在 2014 年至 2017 年使用群组 K 倍验证进行训练。使用这种方法,训练包括使用较晚的年份来预测较早的年份,这在偏差意识一节中被警告过。但是,在这种情况下,这不是一个问题,因为我使用 Group K-Fold 抽样方法,通过公司 ID 而不是随机地在培训和验证之间区分公司。如果某个公司出现在定型集中,它将根本不会出现在验证集中,无论是哪一年。同时,正如偏见意识一节所警告的,培训(A 公司,2016)和验证(B 公司,2014)不会引入过度拟合,因为 B 公司对 A 公司没有任何洞察力,除非这两家公司的目标高度相关。
选择模型
在这个阶段,我想要一个实现简单并且不需要太多调整的模型。逻辑回归可能是一个不错的选择,但它需要仔细考虑处理空值以及相关特征,以获得有意义的系数。 XGBoost 可能是解决这个问题的最佳模型,但是它需要相当大的努力来调整参数。我将改为实现一个随机森林。与 XGBoost 不同,它本身不能处理空值,但是它具有良好的开箱即用性能,并且它的特性重要性在某种程度上代表了它预测高概率的原因。
基准性能
评估分类模型的一个好方法是查看其提升曲线。提升曲线允许我回答以下问题:“如果我从模型中选择了前 N 个预测,我将在 P 个案例中的 K 个案例中是正确的”。
下面是第 5 级的提升曲线,预测公司在下一年的收入是否会翻倍。
该图描绘了三(3)个场景,向我们展示了我们的模型的性能,随机猜测将如何执行,以及完美模型将如何在维持集上执行。在这个类中,只有 ~12%的阳性,所以我们的模型必须相当有选择性。假设我们画出了概率的前 8%(垂直虚线)。最佳模型会将前 8%的概率分配给所有正样本,这将在我们的维持集中提取所有正样本的~ 75%(顶部虚线)。我们的模型提取了所有阳性(中间虚线)的 40% ,大约是完美模型的一半。随机猜测只有 8%的正面结果(底部虚线),比我们的模型差五(5)倍。
通过提高概率等级,我的模型的性能更接*完美模型的性能。如果我画出预测的前 4%,我的模型的性能将几乎是完美的,换来的是给我更少的选择。虽然这听起来很诱人,但应该谨慎,因为数据量不够大,而且前 4%只产生了几十个样本。
也就是说,要成为一个成功的投资者,你可能只需要十几家公司。如果做得正确,这些人会排在前百分之几。
结论
我现在已经用一个开箱即用的随机森林模型对我在第 5 类上的表现进行了基准测试。虽然这个性能看起来不错,但我仍然不知道这个模型依靠什么来做出决策。为了找到答案,我将打开盒子,通过查看特征重要性,看看是什么驱动了这些预测。这将有助于我对推动下一年收入增长的因素建立一些直觉。下一篇见。
财务数据
在这项研究中,我使用了 www.vhinny.com 的历史金融数据。Vhinny 的 Alpha 数据集为 S & P500 公司提供从 2011 年开始的 8 年多的基础数据,如资产负债表、损益表和现金流量表。
我们连线吧!
我很高兴和与我志同道合的人联系,这是对财务独立的追求。如果你也在寻求经济独立,或者你想合作,交流想法,请随时联系我们!以下是我管理的一些资源:
- www.vhinny.com—投资研究平台,为您自己的分析提供金融数据
- https://www.linkedin.com/company/vhinny——加入我们 LinkedIn 上的社区,在那里我和其他贡献者分享与投资相关的内容
干杯!
来自《走向数据科学》编辑的注释: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
用机器学*预测股市。司机。
原文:https://towardsdatascience.com/predicting-the-stock-market-with-machine-learning-drivers-295d85d406e7?source=collection_archive---------44-----------------------
亨尼投资
用随机森林预测下一年的收益。
图片由 whyframeshot 拍摄
这项研究进一步有助于用机器学*探索股市。在本文中,我描述了我在以前的文章中介绍的模型的驱动因素:
- 用机器学*预测股市。引言。
- 用机器学*预测股市。标杆管理。
如果你还没有读过它们,我建议你从“引言”开始。它将引导你按时间顺序阅读这篇文章,并帮助你熟悉问题陈述和我所采用的方法。
我们开始吧!
进展概述
在上一篇文章中,我讨论了我构建的随机森林模型,该模型用于预测明年的收入作为这项研究的基准。我们的目标是获得模型的基线性能,并了解它在不费力的情况下能做得有多好。其基线表现中规中矩,达到了 0.85 的 ROC AUC 。虽然看到良好的性能很好,但更重要的是理解模型如何做出决策,并验证什么驱动模型直观上有意义。****
随机森林特征重要性
我已经用 Python 中的 sklearn 包实现了这个随机森林模型。开箱即用的软件包提供了计算特性重要性的内置功能。在随机森林和其他树 算法中,一般来说,分类特征重要性是基于每个特征在所有树上平均的平均熵减少来计算的。由于它偏向于高基数特性并且忽略了变量交互,所以它不是真正特性重要性的最佳衡量标准。然而,这是一个很好的方法来大致了解正在发生的事情。
我的模型中前 25 个特性的特性重要性如下所示。
Y 轴上显示了建模特征。X 轴显示特征重要性值。建模数据集包含约 100 个特征,涵盖了资产负债表、损益表和现金流量表的所有方面。
我们可以观察到前 13 个特性的特性重要性之间的显著差异。上方地块上cf _ change _ from _ financing _ activities _ n-1下方的特征逐渐变平。这意味着该模型主要依靠前 13 个特征来做出重要决策,而对较低特征做出的决策可能不会对做出正确的预测做出重大贡献。
简化模型
我上面的观察表明,模型可能不需要提供给它的所有信息来完成它的工作。验证此假设的一个好方法是从最不重要的特性开始迭代地删除特性,并评估每一步模型性能的变化,这也是评估特性重要性的另一种方法。
下图显示了 ROC AUC 得分在每次迭代中的演变,其中从最不重要的特征开始移除 5% 的特征。
X 轴显示了的迭代次数,右边的 Y 轴显示了数据集中剩余的个特征,左边的 Y 轴显示了在剩余特征上训练的模型的 ROC AUC 分数。
我们可以看到,在第一次 30 次迭代中删除特性并不会显著影响这个模型的性能。将移除并简化模型是有意义的,给我们留下剩余的 13 特征,我将更详细地研究这些特征。
以下是其余 13 个特性的新特性重要性。
我们可以看到,该图上的大多数功能也出现在全功能模型的顶级功能中。部分变化包括精选车型中的缺席is _ net _ income以及精选车型增加价格的。发生这些变化是因为在每次迭代中重新计算了特性的重要性。由于基于树的算法的贪婪性*,这不能保证与所有特征模型特征重要性的一致性。*
特性有意义吗?
在这一点上,我已经显著地减少了功能的数量,而没有牺牲模型的性能。人们可以观察到其余的特征具有强烈的直觉。其中大部分是描述业务盈利能力的比率。它们包括基本比率,如资本回报率、有形资产回报率、股息收益比、营业利润率等。
同时,有些特征不应该用于预测下一年的收入。这些特征是价格 _n-1 和价格 _ 收益 _n-1。尽管价格和本益比可能与净收入的增长相关,但重要的是要记住:
相关性不等于因果性
当建立机器学*模型时,因果关系是可靠预测的基础。没有因果关系的相关性不会。收入不取决于股价,而股价可能取决于收入(或者没有收入)。净收入的变化可能是导致、、高市盈率的原因,而不是相反。
话虽如此,但值得注意的是,预测时可用的是市盈率。为什么不用呢?
我担心的是,高市盈率意味着市场预期公司未来会赚更多的钱。这意味着市盈率本身是市场对公司业绩预期的一个代表。依靠市场对一家公司收入变化的预期,确实有助于建立稳健的模型。尤其是当市场大部分时间都是错的时候。因此,PE 和价格不应该被用作预测明年收入的模型中的特征。
最后,我还将删除每股收益 n-1 ,因为它与每股收益稀释 n-1 强烈相关,并删除每股收益 n-1 ,因为它与更具体的有形资产收益 n-1 强烈相关。
这给我们留下了一个由 9 个特征驱动的模型,即:
- 资本回报率
- 稀释后每股收益
- 有形资产收益率
- 收益比股息
- 每股收益增长
- 现金
- 营业利润
- 自由现金流对收益
- 非营业费用
新的简化模型的性能
从原始模型中移除 90%的特征后,让我们评估升力曲线的变化。
红色虚线显示了包含所有 100 个特征的模型的升力曲线。红色实线显示了 9 特征模型的升力曲线。接*曲线右侧的性能轻微下降并不明显,而特性数量减少了 90%。这是有利的,因为理解 9 特征之间的关系比理解 100 特征之间的关系简单得多。
结论
在这篇文章中,我调查了预测 2014 年至 2019 年间标准普尔 500 指数公司明年收入的随机森林分类器的驱动因素。我还使用删除特征选择技术将模型中使用的特征数量减少了大约 90%。
在的下一篇文章中,我将更深入地研究剩余的特征,以理解它们究竟如何驱动模型预测,以及寻找成长股的投资者应该追求什么。回头见!
我们连线吧!
我很高兴和与我志同道合的人联系,这是我对财务独立的追求。如果你也在寻求经济独立,或者你想与合作,交换想法或交流思想,请随时联系我们!以下是我管理的一些资源:
- www.vhinny.com—投资研究平台,为您自己的分析提供金融数据
- https://www.linkedin.com/company/vhinny——加入我们 LinkedIn 上的社区,在那里我和其他贡献者分享投资相关的内容
干杯!
用机器学*预测股市。调查结果。
原文:https://towardsdatascience.com/predicting-the-stock-market-with-machine-learning-findings-135f0b3a26cf?source=collection_archive---------32-----------------------
亨尼投资
用机器学*识别高收入成长股
图片由 teerapon 拍摄
在这篇文章中,我展示了我在 2014 年至 2019 年间预测 S & P500 家公司的明年收入的主要发现。虽然这不是必需的,但我鼓励读者看到我在这里分享的观察结果:
- 用机器学*预测股市。引言。
- 用机器学*预测股市。标杆管理。
- 用机器学*预测股市。司机。
我们开始吧!
知道模型在做什么
设计一个优秀的机器学*模型,关键是要准确知道它在做什么。当使用类似于回归的东西时,达成这种理解可能很容易,而当使用深度学*神经网络时,则非常困难。尽管如此,负责人应该始终致力于了解模特是如何思考的。没有它,模型的预测一文不值。
我的模型在做什么
在的前一篇文章中,我已经将原始模型中使用的功能从 100 个减少到 9 个,而没有牺牲模型的性能。其余的特征是:
- 资本回报率
- 稀释后每股收益
- 有形资产收益率
- 收益比股息
- 每股收益增长
- 现金
- 营业利润
- 自由现金流对收益
- 非营业费用
我使用了随机森林特征重要性来决定哪些特征应该保留,哪些特征应该丢弃。虽然特征重要性帮助我理解了每个变量在预测分数时的权重,但它没有告诉我每个特征究竟如何影响分数。运营利润应该是高还是低?我们期待高股息还是低股息?应该有多少现金?
寻找方向
在基于树的算法中,将方向贡献给特征重要性的一种方法利用了 SHAP 值。如果你不熟悉这项技术,请看这里的。
我的模型的 SHAP 值如下所示。请注意,我已经从上述功能中删除了非运营费用,因为它没有为模型性能增加实际价值。
该图上的 X 轴测量每个特征对预测分数的影响。Y 轴显示了用于生成预测分数的所有特征。颜色条显示该特征的值是高还是低。例如,高股息收益鼓励模型作出积极的预测(红色,积极的 SHAP 值)。然而,有形资产的高回报鼓励模型做出负面预测(红色,负 SHAP)。
这个图揭示了对于一个聪明的投资者来说可能不直观的关系。它说,第二年收入翻一番的公司应该有低资本回报率、低有形资产回报率和低营业利润率——所有这些都是糟糕经营业绩的指标。
更进一步
SHAP 值分析允许我在个体 样本水平上查看每个特征如何影响预测。让我们来看看我的模型做出的前 2 位正确预测。
前 2 个积极预测
该模型预测 2013 年星巴克(SBUX)的收入将翻一番。我们来详细看一下。所有 8 个预测值都是红色的,对预测值做出了积极的贡献,将预测值一直推高到 0.96。
正如“寻找方向”部分所预期的那样,我们的资本回报率 (0.001)可疑地低,而自由现金流对收益 (520)和股息对收益比率(76)可疑地高。
这些比率不在正常范围内,需要进一步调查。该公司有足够的现金支付通常的股息,但收入却不多。让我们通过 Vhinny 的历史比率和数据来看看这与全球情况是如何吻合的。
https://www.vhinny.com/display/SBUX
事实上,2013 年报告的净收入为 830 万美元,与 2012 年的 14 亿美元和 2014 年的 21 亿美元相比大幅下降。更进一步,你会发现星巴克那年记下了 28 亿美元的诉讼费用。虽然 28 亿美元是一个沉重的打击,但星巴克的盈利潜力并没有受到影响。高的自由现金流对收益比率表明企业仍然赚钱,并继续正常运营。果然,第二年净收入恢复正常,证明我的模型的预测是正确的。
是什么导致了负面预测
了解了模型如何做出自信的正面预测,让我们看看它如何做出自信的负面预测。以下是前 2 位负面预测的 SHAP 值。
前两大负面预测
对于这两个示例,所有 8 个预测值都在蓝色中,对预测得分产生负面影响。事实上,这两个例子的预测分数是0.00——低得不能再低了。
看看家得宝(Home Depot),我们可以看到良好的有形资产回报率(T44)和资本回报率(T46),自由现金流与收益之比(1.41)在 1.41 左右,这属于正常范围。特洛伊的海伦(乐和)也有类似的情况。
这三项指标将 HD 和乐和定义为产生高回报的盈利公司。投资者通常喜欢这种类型的公司,因为它们的业务表现强劲。为什么我的模型认为一个好的企业不会在第二年收入翻倍?
虽然优秀的公司年收入翻倍并非不可能,但数据表明,一般来说,具有强大业务特征的公司会逐渐自信地成长。实际上,T2 需要两倍的人在世界各地为家得宝建造房屋,T4 需要两倍的收入。800 亿美元的年销售额,在正常情况下不太可能发生。为了让模型预测收入大幅增长的可能性,需要在数据的异常区中有一些东西,这就是我们在自信的正面例子中看到的。
结论
在这篇文章中,我描述了我建立的预测明年收入的模型如何做出决策。研究结果表明,在正常经营条件下,好的企业不太可能在第二年实现收入翻番。与此同时,由于“一次性”事件而失去收入的企业可能会重新站立起来,继续正常运营。该模型能够通过分析公司在给定年度的收入情况下赚了多少现金来识别这些公司。
如果读者和我一样,希望在数据中找到信号并认同股市,我鼓励读者把我的结果当作想法,进行自己的研究。如果读者对这项特别的研究感兴趣,那么推进我的发现的一个好地方就是看看公司规模如何影响企业在遭受打击后恢复正常的概率。
本文总结了这一系列利用基础财务数据预测下一年收益的。我希望读者发现我在这里分享的见解是有价值的,并在他们自己的选股过程中加以利用。
我将继续研究 2020 年的股市崩盘。下期见!
我们连线吧!
我很高兴和与我志同道合的人联系,这是对财务独立的追求。如果你也在寻求经济独立,或者你想合作,交流想法,请随时联系我们!以下是我管理的一些资源:
- www.vhinny.com—投资研究平台,为您自己的分析提供金融数据
- https://www.linkedin.com/company/vhinny——加入我们 LinkedIn 上的社区,在那里我和其他贡献者分享与投资相关的内容
干杯!
用机器学*预测股市。引言。
原文:https://towardsdatascience.com/predicting-the-stock-market-with-machine-learning-introduction-310cd6069ffa?source=collection_archive---------19-----------------------
亨尼投资
问题陈述和方法。
这篇文章标志着我在金融市场寻找信号之旅的开始,在这里我使用各种统计方法和机器学*来分析股票市场,并识别有吸引力的投资。
图片由缩微
千里之行始于足下
如果你不确定我为什么自己去找信号而不去找“专家”,可以看看这篇文章:论精英如何平庸。
财务数据
在这项研究中,我将使用 www.vhinny.com 的历史金融数据。他们的 Alpha 数据集为 S & P500 公司提供从 2011 年开始的 8 年多的基本财务数据,如资产负债表、损益表和现金流量表。
目标
我的目标是找到我能衡量的关于公司的一些特征和股票价格之间的关联。然而,一个聪明的投资者可能已经观察到,股票价格并不完全与商业表现相关。相反,它会受到许多因素的影响,如大大小小的经济事件、公众的看法、对变化的期望、产品的新趋势、消费者行为的新趋势等等。
这让我置身于一个充满噪音和统计偏差的房间,因为存在着我无法测量的因素。忠于我的目标,我将暂时离开这个众所周知的强劲对手,股票价格预测,并专注于预测我更有控制的领域——明年的收入。一旦我对市场驱动因素的理解建立了坚实的基础,我就会回来预测股票价格。
明年的收入是一个更容易解决的问题,因为它与公司的基本面有直接关系。这是一个开始熟悉数据并了解财务信息在预测财务表现时是否有任何预测能力的好地方。
定义目标
我在预测明年的收入。为了有一个一致的目标,我将预测收入的年度增长,而不是收入本身。这样,我的预测将适用于所有公司,无论其规模大小。
下面的直方图显示了 S & P500 公司在过去 8 年的收入增长分布。
X 轴代表年度收入增长,定义为当年和上一年之间的净收入变化除以上一年的收入的比率。Y 轴显示每个 bin 所占的数据百分比。
我们可以看到,该直方图的峰值高于 0,反映出平均值为 0.20 的和 0.05 的中值。这具有直观的意义,因为自 2008 年危机以来,股市一直在持续上涨,表明繁荣的经济有利于业务增长。
回归与分类
我个人更喜欢解决分类问题,而不是回归,因为它们对评估指标有很高的可解释性。对我来说,根据 Lift、PR 和 ROC 曲线做决定比根据 R2 分数做决定更直接。所以,我要把这变成一个分类问题。
更确切的说,我准备把它做成五(5) 分类问题,看我能更好地解决哪一个。我将预测公司是否会
- 将其收入最多减少 100%或增加
- 将其收入最多减少 50%或增加
- 增加其收入至少 0%
- 增加至少 50%的收入
- 增加至少 100%的收入
我还将保持目标的非互斥性,意思是“增加至少 50%”,例如,也将满足前面的 3 个类。
下面的直方图显示了目标按类别的分布。
注意仓如何逐渐减少。这是因为每个下一个箱包含来自前一个箱的数据减去不满足下一个箱的更严格条件的样本。比如“100% >”就是最严格的条件。因此,它的例子最少。同时,此箱中的公司满足所有早期箱的条件。因此,它们也将作为早期箱的例子出现。
待续
这就结束了我对我要解决的问题的介绍。在下一篇文章中,用机器学*预测股市。对标,我在用随机森林模型预测下一年的收入。在那里见。
我们连线吧!
我很高兴与和我有共同道路的人联系,这是对财务独立的追求。如果你也在寻求经济独立,或者你想合作,交流想法,请随时联系我们!以下是我管理的一些资源:
- www.vhinny.com—投资研究平台,为您自己的分析提供金融数据
- https://www.linkedin.com/company/vhinny——加入我们 LinkedIn 上的社区,在那里我和其他贡献者分享与投资相关的内容
干杯!
用递归神经网络预测特朗普的推文
原文:https://towardsdatascience.com/predicting-trump-tweets-with-a-rnn-95e7c398b18e?source=collection_archive---------22-----------------------
用 LSTM RNN 生成作者和特定任务的文本。
唐纳德·特朗普著名的“covfefe”推文。
唐纳德·特朗普独特的方言是每个美国人都能识别的;然而,我们能建立一个神经网络来模仿特朗普的‘cov fefe’一样的词汇吗?
[## mm 909/预测-川普
文本预测只在特朗普的推文、演讲和采访上进行了训练。-mm 909/预测-川普
github.com](https://github.com/mm909/Predicting-Trump)
在 Andrej Karpathy 被高度引用的博文递归神经网络的不合理有效性中,Karpathy 表明递归神经网络(RNNs) 可以作为非常强大的生成模型。他给出了 RNNs 生成莎士比亚戏剧的例子,维基百科关于自然主义的文章,甚至带有真实用户评论的 Linux 源代码。
我们将使用 RNN 来生成新的特朗普推文。
这不是对自然语言处理(NLP)或 RNNs 的深入指导,而是对项目的概述;尽管如此,还是提供了所有的代码,并且有大量的链接可以帮助扩展本文中没有完全解释的主题。
数据
我们首先收集特朗普词汇的例子,越多越好。幸运的是,我们不缺乏数据。特朗普的思想几乎总是保存在推特上,在演讲中,或者在采访中。我们将使用这些推文、演讲和采访的组合来训练角色预测模型。
小鸟叫声
特朗普的推文在几个地方存档。我从 TrumpTwitterArchive 下载了大约 50,000 条他的推文。然后,我通过从推文中删除所有表情符号和网址来清理数据,以帮助提高预测的准确性。以下节选自 cleanTweets.txt :
感谢我们伟大的美国企业为保护我们最脆弱的公民的安全所做的一切!
经双方同意,我们将暂时关闭与加拿大的北部边境,禁止非必要的交通。贸易不会受到影响。详情随后!
同样根据每日来电显示,在佛罗里达州,嗜睡的乔·拜登以 48%对 42%领先。
演讲:GitHub
不幸的是,特朗普的所有演讲都没有一个中心位置,但有几个 GitHub 存储库存有他的演讲子集。下面是一些你可以从哪里得到数据的例子;然而,我只使用了第一个库。
[## unendin/Trump_Campaign_Corpus
特朗普竞选语料库包括唐纳德·特朗普的演讲、采访、辩论、市政厅、新闻发布会…
github.com](https://github.com/unendin/Trump_Campaign_Corpus) [## PedramNavid/trump _ 演讲
特朗普 2015 年 6 月至 2016 年 11 月 9 日的所有演讲——PedramNavid/Trump _ speechs
github.com](https://github.com/PedramNavid/trump_speeches) [## ryanmcdermott/trump-演讲
speechs . txt:1mb 的文本数据摘自唐纳德·特朗普在 2016 年竞选活动中不同时间点的演讲…
github.com](https://github.com/ryanmcdermott/trump-speeches) [## Alex mill/trump _ 抄本
这是唐纳德·特朗普竞选演讲和辩论笔录的半结构化版本,因为…
github.com](https://github.com/alexmill/trump_transcripts)
同样,与 tweet 数据一样,这些数据也需要清理。对于来自 unendin 的存储库的数据,我们需要删除非川普演讲者的所有文本。以下是唐纳德·川普和马克·霍尔珀林在接受采访的节选。
马克·哈尔珀林:人们对你的个性非常感兴趣。很多人,我想你听过这句话,认为你自大或者太自信了。有些人说你极度缺乏安全感,这就是你如此行事的原因。你对任何事情都没有安全感吗?
唐纳德·特朗普:我不知道。也许是两者的结合。
马克·哈尔珀林:你缺乏安全感吗?
唐纳德·特朗普:每个人都没有安全感。
我们可以通过编写一个正则表达式来匹配“SPEAKER: TEXT ”,然后删除除 Donald Trump 之外的所有发言者,从而删除采访中马克·霍尔珀林一方的所有内容。
我还选择删除所有的换行符,因为我觉得它们对文本预测并不重要。由此产生的文字记录只是特朗普在采访中的一面之词。
我不知道。也许是两者的结合。每个人都没有安全感。
然后将所有的演讲连接起来,放入 cleanSpeech.txt
演讲:事实基础
FactBase 是唐纳德·特朗普的演讲和采访档案。可悲的是,FactBase 没有简单的方法一键下载他所有的演讲;然而,这并不重要,因为这些数据很容易被删除。
我们可以使用 Selenium 从 FactBase 中抓取数据。随着时间的推移,这将把特朗普的所有新演讲添加到我们的数据库中。
数据准备
要开始训练我们的模型,我们需要加载和处理文本数据,为网络做好准备。通过这样做,我们将定义两个重要的超参数:序列长度和步长。
加载数据
让我们从把数据载入内存开始。我们将读入数据,并使所有的文本小写。这样,T 和 T 被认为是同一个字母。语料库长度是我们数据库中的字符数。
Corpus length: 23342237
字符词典
模型不会自然地理解文本和标点符号,比如“a”和“?”,但他们确实理解数字。因此,我们需要一种方法将我们所有的文本翻译成数字。
有很多方法可以做到这一点,但我选择使用两本字典。一个把字母变成数字,另一个把数字变成字母。
char_indices['a'] -> 42
indices_char[42] -> 'a'
Unique Chars: 66
序列长度
序列长度是我们的模型得到的上下文窗口的大小。
序列长度定义了有多少个字母,以及有多少上下文,我们要给模型预测下一个字符。序列长度越长,模型在进行预测时就有越多的上下文。序列长度为 20 的示例:
"Today I will be addr"
你可能会猜到这个序列中的下一个字母是 e,句子中的下一个单词是 addressing。这就是我们希望我们的模型预测的。
对于我们的模型,我们将使用长度为 80 的序列。
步长
步长是我们每次迭代滑动上下文窗口的距离。
步长定义了在制作训练样本时,每次迭代要移动多少个字母。下面是一个序列长度为 20,步长为 2,句子为“今天我将向全国发表演讲”的例子:
"Today I will be addr"
"day I will be addres"
"y I will be addressi"
"will be addressing t"
"ll be addressing the"
" be addressing the n"
"e addressing the nat"
"addressing the natio"
"dressing the nation."
对于我们的模型,我们将使用步长 4。
序列长度和步长的权衡
我们希望序列长度尽可能长,以便模型有更多的上下文来预测下一个字符,然而,更长的序列长度意味着更大的模型和更多的处理时间。我选择序列长度为 80,因为我更关心网络拼凑长文本串的能力,而不是网络的处理时间。
步长的权衡更加片面。步长越小越好。较小的步长意味着更多的训练样本和更多的相关句子,然而,只有一定数量的样本可以被存储。我们希望最小化步长,同时仍然将所有的句子放入内存。
***使用数据发生器 ***消除了步长折衷
编码
使用选择的序列长度和步长,我们现在创建一个句子数组来保存所有拆分的句子,创建一个下一个字符数组来保存序列中的下一个字母。
为了更具可读性,我展示的例子是序列长度为 20,步长为 2。句子数组现在看起来像这样:
["Today I will be addr",
"day I will be addres",
"y I will be addressi",
"will be addressing t",
"ll be addressing the",
" be addressing the n",
"e addressing the nat",
"addressing the natio",
"dressing the nation."]
下一个字符数组保存每个句子中的下一个字母:
['e',
's',
'n',
'h',
' ',
'a',
'i',
'n',
'']
这为我们提供了培训示例的总数:
Number of training examples len(sentences): 5835540
最后,我们将热编码这些序列,使它们能够被神经网络处理。
我们现在有( X ,y)对供网络处理。提醒一下,5835540 是训练样本的数量,80 是序列长度,66 是唯一字符的数量。
X.shape: (5835540, 80, 66)
y.shape: (5835540, 66)
模型
我们的模型将是一个长短期记忆(LSTM) RNN 。递归层之后是几个密集层,用比例指数线性单元(SELU) 激活,用批量归一化正则化。
在探索了几种不同的选择之后,我做出了这些决定。
模型图
结果
仅仅过了四个时期,我们就有了一个验证数据准确率为 67.362%的模型。考虑到随机猜测会给我们 1.51%的准确度,该模型表现良好。因此,我们的模型比猜测精确 44 倍。
模型统计
下表显示了对句子“Today I”的预测。
《今日我》预测表
对于第一个字符预测,模型选择“w ”,但它对其决策不是很有信心。这是因为在“今天的我”之后有大量合理的可能性。尽管如此,有 20.53%的把握,这个模型把“今天的我”变成了“今天的我”。
在第一次预测之后,我们继续向模型询问字符。随着可能选项的数量减少,该模型变得更有信心。“今天我要”变成了“今天我要”,然后是“今天我要”。最终,该模型 99%确信最后一个字符是“l ”,从而得到字符串“Today I will”。
预测的句子
以下是不同模型生成的句子示例。所有的模型都在相同的数据集上训练,但是具有不同的架构。这些模型能够理解 twitter 标签、标点、连词、重要日期,甚至反问句。
模型 1
Seed: 'Welcome to America'
Output: 'Welcome to America, right? Well, I would have said that we have to make America great again, but I want to talk about the problem now.'Seed: 'It is really'
Output: 'It is really sad but the fake news media don't want to see the Republican Party continue to prove what we have.'
模型 2
Seed: 'I'
Output: 'I mean, in the middle east, we are going to win. We are going to repeal and replace Obamacare. Hillary is a disaster. We are going to win.'Seed: 'America'
Output: 'America first. Our jobs are going to win on November 8th. Manufacturing jobs have got to do it.'
模型 3
Seed: 'Today I will'
Output: 'Today I will make America great again! @realdonaldtrump is a big thing that is the best in the country and the president is a big deal.'Seed: 'I think that'
Output: 'I think that is a big contract that comes out the world trade center and we have to take care of our country.'
模型 4
Seed: 'I will always'
Output: 'I will always stop the state of the state of Michigan in the state of Michigan'Seed: 'The whitehouse'
Output: 'The whitehouse is not for the state of Michigan'Seed: 'China is a'
Output: 'China is a total crisis and the story in the same thing that I was a great and I will be interviewed by @seanhannity to the @whitehouse!'
披露:我在输出中添加了所有的大写。
结论
我们创造了非常现实的句子,听起来就像真的来自唐纳德·特朗普的推特。我自信地说,这个模型肯定是循环神经网络不合理有效性的另一个例子。在整个过程中,我做了一些重要的观察,并将它们列在下面。
选择性短语
似乎每个模型都选择了一些短语来保持重用。有时这些短语会在一个预测中出现多次。模型 1 不断重复使用短语,“但我现在想谈谈这个问题”和“假新媒体。”对于模型 2,一切都发生在中东。Model 3 总说东西是“全国最好的”。最后,Model 4 讨厌密歇根州。尽管所有这些短语都是唐纳德·特朗普词汇的一部分,但它们在预测中出现得太频繁了,以至于不自然。
一个有趣的观察是,在相同数据集上训练的模型可以专注于不同的短语。这意味着模型更频繁选择的短语与数据集无关。
影响
除了娱乐价值,rnn 还有实际的现实价值。能够生成作者和特定任务的文本,比如 tweets,非常有用。rnn 能够通过给你文本建议来帮助你写更快的电子邮件,比如 Gmail。它们还可以帮助演讲稿撰写人更准确地匹配演讲者词汇。RNNs 和 NLP 之间的交叉非常广泛,应用领域非常广阔。
丰富
训练时间:不幸的是,每个纪元需要大约一个小时才能完成,所以我将训练限制在 4 个纪元。虽然从第 3 代到第 4 代的改进很小,但我认为多训练几个小时会产生更精确的模型。
在写这篇文章的时候,我发现了 CuDNNLSTM 。用 CuDNNLSTM 替换 LSTM,可减少 66%的培训时间。我还没有 CuDNNLSTM 如何影响模型准确性的结果;然而,我怀疑 CuDNNLSTM 和 LSTM 会表现相似。
减少偏差:模型有大量可避免和不可避免的偏差,正如吴恩达在机器学*向往中所定义的。即使对人类来说,文本预测也是一项艰巨的任务,正因为如此,我们可以预期会有相当高的不可避免的偏差。还有大量可以避免的偏见。这可以通过使用更复杂的模型和添加字嵌入来解决。
减少差异:唐纳德·特朗普(Donald Trump)喜欢的“covfefe”词汇的例子越多越好。我希望继续收到更多的推文、演讲和采访。虽然方差目前非常低,但随着模型变得更加复杂,方差将会增加。添加更多的数据将有助于控制差异。
Keras dataGenerator: 我还没有为文本数据实现 Keras 的 dataGenerator 类。实现这个类意味着我们的模型可以总是步长为 1 而不会溢出内存。这意味着我们可以显著增加训练数据库的大小,而不用担心它不适合内存。
所有这些改进将使模型更加精确。
项目存储库
[## mm909 -概述
在 GitHub 上注册你自己的个人资料,这是托管代码、管理项目和构建软件的最佳地方…
github.com](https://github.com/mm909)
Seed: 'Today I will'
Output: 'Today I will be the world -- I think.'
用机器学*预测推特情感
原文:https://towardsdatascience.com/predicting-tweet-sentiment-with-machine-learning-3599c8add259?source=collection_archive---------18-----------------------
推特上的情感分析
🇨🇭·克劳迪奥·施瓦茨| @purzlbaum 在 Unsplash 上拍摄的照片
不可否认的是,社交媒体现在已经成为一个极其重要的平台,帮助企业扩大在线影响力。多年来,营销人员越来越意识到社交媒体平台(如脸书、Twitter、LinkedIn)的重要性,以及它们通过嘴对嘴营销在业务增长中发挥的作用。
许多人也注意到,社交媒体是一个很好的地方,可以在你的客户所在的地方与他们见面,公平地说,一些企业有很好的幽默感…
来源:推特供稿
如果我们回忆一下社交媒体的目的,我将把它概括为将世界任何地方的人们联系在一起,这就可以理解为什么企业纷纷涌向社交媒体,因为他们意识到这是一个交流的好地方,无论这种交流是好消息、坏消息、假新闻还是世界上某个地方发生的紧急情况。
此外,智能手机的普及使人们能够实时宣布这些事件。如果顾客在他们的食物中发现一根头发,你可以打赌它会出现在社交媒体上。因此,越来越多的机构、组织、企业和好奇的个人对有计划地监控各种社交媒体网站以获取对他们重要的信息产生了兴趣。
这方面的一个很好的例子可能是希望检测灾难发生的救灾组织。这显然是一项非常重要的任务,但也非常困难,因为人们并不总是清楚一个人的话是在宣布一场灾难还是对某件有吸引力的事情的夸张描述——在这方面,可以公平地说,话可能非常模糊。
来源:推特供稿
上面的图片显示了一个用户的推文,他说他们想要点燃“天空”。当把“着火”当作动词时,这条推文可以被认为是一场灾难,因为这意味着天空正在猛烈燃烧。然而,根据推文中提供的上下文,我们知道用户指的是形容词版本的“闪亮的”,这意味着他们在说天空非常明亮或明亮。这是显而易见的,但对计算机来说就不一样了。
因此,作为数据科学家(NLP 专家),我们的工作是提出解决方案,尽最大努力克服语言的各种模糊性,这样我们服务的人们就不会不断受到由于语言差异而导致的错误灾难声明的轰炸。
在这一点上,我们将做一些情绪分析结合机器学*来检测来自 Twitter 的灾难推文的情绪。目标是根据推文确定是否有真正的灾难。
注意:对于我的帖子的关注者,你会记得我们一直在一起研究自然语言处理。如果你是新手,这一切都是关于我在 Coursera 上记录的自然语言专业笔记。为了避免我再次解释什么是情绪分析,请回顾一下开始情绪分析的帖子。
数据
我们可以使用 Twitter 的 API 自己检索数据。文档指出" Twitter 的开发者平台使你能够在你自己的应用中利用 Twitter 的开放、全球、实时和历史交流网络的力量。该平台提供工具、资源、数据和 API 产品供您整合,并通过研究、解决方案等扩大 Twitter 的影响。”。这样做意味着我们必须自己处理和标记数据,这更适合现实世界的情况。
对我们来说幸运的是,大部分艰苦的工作已经完成了,因为数据已经被检索并作为逗号分隔值(csv)文件存储在 Kaggle 上。因此,我们的工作只是将数据下载到我们的本地驱动器—要下载数据,访问 真实与否?NLP 与灾难 Tweets 入门竞赛并从数据部分下载数据。
免责声明:本次比赛的数据集包含可能被视为亵渎、粗俗或冒犯的文本。
我们期望在数据中看到的特征如下:
id
—每条推文的唯一标识符。text
—推文的文本keyword
—推文中的一个关键词(虽然这可能是空白的!)location
—发送推文的位置(也可以是空白的)target
—表示一条推文是否是关于真实的灾难(1
)或者不是(0
);只有在train.csv
和sample_submission.csv
评估标准是 F1 分数,详情请见下文。
[## 混淆矩阵“未混淆”
打破混乱矩阵
towardsdatascience.com](/confusion-matrix-un-confused-1ba98dee0d7f)
构建模型
所有代码都可以通过 Github 访问。
[## kurtispykes/twitter 情绪分析
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/kurtispykes/twitter-sentiment-analysis)
第一相
当开始一个项目时,获得快速反馈是非常重要的,因此,我不担心立即获得最佳的准确性。相反,我想找到从数据中获得即时反馈的最佳方式,然后开始更深入地研究,以辨别可以做出哪些改进。
为了通过这个阶段,我首先将我的数据分成训练、开发和测试集——因为这些数据来自 Kaggle,我们已经有了一个测试集,所以我们只需要一个开发集。然而,我将使用分层 Kfold 交叉验证,而不是使用基于维持的开发集——更多关于交叉验证的信息,请参阅我关于交叉验证的文章。
[## 交叉验证
验证机器学*模型的性能
towardsdatascience.com](/cross-validation-c4fae714f1c5)
为了帮助我们编写代码,我制作了一个配置文件,我们将使用它,这样我们就不会在脚本中进行任何硬编码…
现在让我们创建我们的折叠。
该函数读取我们从 Kaggle 接收的原始训练数据,创建一个新列并用-1
填充所有值。之后,我们重组数据,通过标记每个实例所属的文件夹来创建文件夹,最后将其保存为 csv 文件。
创建折叠的过程对我来说很标准。我确实在交叉验证文章中详细描述了我如何选择我的验证策略,但更多的时候,我会对分类问题进行分层——我甚至在我的使用机器学*检测欺诈的故事中使用它。
第二相
快速迭代的下一个阶段是尽可能快地训练一个模型,这意味着我们不会太担心最佳特性工程实践或任何事情。我们只想训练一个简单的模型,做推理。
本质上,我们有 3 个特征(不包括id
),它们是text
、keyword
和location
。我能想到的处理这些问题的最简单的方法就是简单地将关键字和位置附加到文本的末尾。之后,我们对文本进行一些基本的处理,将文本转换成向量,然后建立我们的模型。
为了将我们的文本转换成向量,我们使用了CountVectorizer
,它将一组文本文档转换成一个令牌计数矩阵——参见文档。
我们将使用 2 个不同的模型运行我们的训练脚本,并在我们编写脚本进行推理时,使用每个折叠上具有最佳平均值的模型提交给 Kaggle。我们使用的两个模型是逻辑回归和朴素贝叶斯。
[## 从零开始的算法:逻辑回归
从头开始详述和构建逻辑回归模型
towardsdatascience.com](/algorithms-from-scratch-logistic-regression-7bacdfd9738e) [## 从零开始的算法:朴素贝叶斯分类器
从头开始详述和构建朴素贝叶斯分类器
towardsdatascience.com](/algorithms-from-scratch-naive-bayes-classifier-8006cc691493)
如果您不记得上面的内容,本次比赛的评估标准是 F1 分数:
因此,我们将使用朴素贝叶斯进行推理…
这将输出一个 CSV 文件,我将把它提交给 Kaggle
提交给 Kaggle 的文件(图片由作者提供)
关于这一点需要注意两件事…我们的平均开发集分数和我们的测试分数之间有很大的差异,所以我们必须对我们的交叉验证技术做一些调整。接下来的事情就是我们的分数没有那么大。我的目标是 F1 成绩达到 85 分左右。
在另一篇文章中,我将讨论错误分析,这样我们就可以开始改进我们的模型。
感谢阅读到最后,让我们继续 LinkedIn 上的对话…
[## Kurtis Pykes -数据科学家-自由职业者,自由职业者| LinkedIn
在世界上最大的职业社区 LinkedIn 上查看 Kurtis Pykes 的个人资料。Kurtis 有 3 个工作列在他们的…
www.linkedin.com](https://www.linkedin.com/in/kurtispykes/)
用 DNN 分类器预测终极格斗锦标赛
原文:https://towardsdatascience.com/predicting-ufc-bouts-with-dnn-classifier-f955e9abe6c6?source=collection_archive---------12-----------------------
基于格斗者风格和数据预测综合格斗比赛结果的研究
在 Unsplash 上attendee拍照
免责声明:您不应该使用本文中介绍的模型进行赌博或执行任何与赌博相关的活动。我的 GitHub 帐户中发布的这篇文章或代码不构成下注建议。
起初,我认为试图用统计数据来预测 MMA 比赛结果的想法有点愚蠢。我的推理非常简单:拳手有不同的策略来对付不同的对手。如果你在和麦格雷戈比赛,你知道你需要对你的左手做些什么。如果你在和德米安·玛雅战斗,你知道你不能和他一起战斗。如果你的对手是内特·迪亚兹,你需要尽快搞定他,或者最好在你的有氧运动中处于领先地位。
但是我在 You Tube 上看到了一个很好的视频,改变了我的想法。在这个视频中,他谈到了'击败了 Khabib '。他说,除非一名运动员已经具备了相应的技能,否则不可能指导他调整自己的风格来对抗特定的对手。这些技能需要成为他格斗词汇的一部分,3 个月的准备不会改变多年的训练和肌肉记忆。因此,在兴奋的时刻,计划很可能会通过窗口,那些根植于他们 DNA 的运动将会出现。
Chael Sonnen 谈论击败 Khabib Nurmagomedov
数据
在说服自己这个项目不是完全浪费时间之后,我需要得到一些反映每个战士的数据。所以我做了一个机器人从 ufcstats.com 收集数据。
这些数据很棒,因为它们很好地描绘了每个战士的技术和背景。
例如,看看德米安·马亚和豪尔赫·马斯维达尔的故事:
来源:www.ufcstats.com
来源:www.ufcstats.com
德米安·马亚是一名格斗家,阿九柔道专家,而马斯维达尔是一名跆拳道运动员。这些指标以一种可被 DNN 分类器使用的方式嵌入该信息。
模型
该策略是向 DNN 分类器提供竞争者的统计数据,并训练它根据之前比赛的结果识别谁将获胜。
我没有花很多时间来调整模型,但它基本上是一个 DNN 分类器,有 3 层,每层 30 个单元。数据和我的代码可从以下网址获得:
https://github.com/cunhafh/UFC_bout_prediction
模型精度
该模型使用 30%的可用数据进行训练,评估的准确度约为 80%:
我在最后一场 UFC 夜战上测试了这个模型,它很好地预测了‘布莱德 Vs 多斯桑多斯’和‘多斯安茹斯 Vs 基耶萨’的结果。
该模型预测 Blaydes 和 Chiesa 将获胜。不出所料,布莱德斯、专家分析和赔率都对他有利。然而,基耶萨在另一场比赛中处于劣势,没有多少人预计他会击败拉斐尔·多斯安茹斯——该级别的前冠军。如果我要赌那场比赛,我肯定会因为赌多斯安茹斯而输钱。这句话把我带到了下一个话题。
体育博彩和机器学*
免责声明:本文或代码(发布在上述存储库中)仅为科学利益而开发,不应用于赌博或执行任何与赌博相关的活动。
话虽如此,我相信 ML 模型确实有助于增加自己的胜算。让我们深入了解一下。
使用预测模型相对于“凭直觉”的优势是不可否认的。我们偏向于我们最喜欢的拳手,或者认识的时间更长,或者和我们拥有相同的国籍。机器学*可以为你提供一个严格符合逻辑的选择,这个选择来自于一个经过数千次已知精确度测试的模型。
体育博彩中最大的吹毛求疵是风险/回报比。例如,下一场 UFC 赛事“乔恩·琼斯对多米尼克·雷耶斯”的十进制赔率是 1.25(琼斯)和 4.25(雷耶斯)。在琼斯身上下注的风险/回报比是不合理的(对于 100 美元的赌注,有输掉 100 美元最终赚 25 美元的风险)。
因此,下注策略需要考虑赢的部分来弥补输的部分。
盈亏平衡点
在其他作品中,如果我赌 10 场比赛,每场比赛 10 美元,我应该预计会损失 20 美元,其他赌注的回报应该可以弥补这一点。所以,在这种情况下(模型 acc = 80%),如果所有 10 名战士的平均赔率至少为 1.25,我应该可以保本。如果我只决定在赔率至少为 1.4 的拳手身上下注,我应该预计最低回报率为 12%。当然,所有这些都是在模型有 80%的准确率的情况下进行的。
不过,我还没能测试这个策略,因为在我居住的地方,体育博彩是非法的。我计划在某个时候测试它,但那将是另一篇文章!
我希望你喜欢这篇文章,我很想听听你的想法和建议。也可以随时与我联系。
https://www . LinkedIn . com/in/feli PE-Cunha-MSC-PMP-LSS b-2692131 b/
谢谢
用机器学*预测 UFC 格斗
原文:https://towardsdatascience.com/predicting-ufc-fights-with-machine-learning-5d66b58e2e3a?source=collection_archive---------13-----------------------
我如何使用 Scrapy、深度学*、Flask 和 React 构建多模型战斗预测器。
迪伦·诺尔特在 Unsplash 上的照片
TL;DR: 亲自检查一下预测器,看看它在即将到来的 UFC 战斗卡中表现如何,或者检查一下 github 上的代码
项目概述
作为一个 MMA 爱好者,我经常发现自己试图预测即将到来的战斗卡上的战斗结果。问题是战斗的本质是非常不可预测的。甚至比拳击更重要的是,MMA 比赛的结果可以在一瞬间改变,但当然这也是它如此有趣的原因。
尽管如此,我还是想知道是否有一种方法可以将现代机器学*技术应用于历史格斗数据,并观察一个模型在新的格斗中的表现。
入门指南
当然,像任何 ML 项目一样,我需要数据来处理。幸运的是,我有一个好主意,我可以在哪里找到一些经常在战斗卡后第二天去 www.ufcstats.com 的人,以获得战斗的统计数据。
所以现在我有了我的数据源和一些如何实现这个模型的想法,我想知道是否有其他人已经建立了一个这样的项目,并且看到了这个由田园写的帖子,详细描述了他建立一个战斗预测器的过程。
袁的帖子非常详细和有见地,我抓取统计数据页面的方法很大程度上是受他如何构建自己的抓取工具的启发。谢谢袁!
在袁的预测中,他使用了比赛前可用的比赛数据,我称之为“静态比赛数据”,如年龄,距离,体重,W/L 记录等。然而,UFC 统计页面还详细列出了历史比赛的具体统计数据,如击球、击倒、提交尝试和后卫传球。
由于 UFC 统计页面上没有太多的数据点,我觉得丢弃这些“动态战斗统计”将是一种耻辱。所以我决定建立一个双向预测系统的预测器:
- 第一个模型使用静态统计数据作为战斗机 1 和战斗机 2 的自变量,然后预测因变量,即动态战斗统计数据。(一个** 多目标回归 问题)。**
- 然后,我们将静态和动态的战斗统计数据传递给一个整体赢家模型,该模型预测战斗机 1 或战斗机 2 是赢家。(一个二元分类问题)。
抓取 UFC 统计数据
这个项目的刮刀被分解成两个刺儿头蜘蛛,爬行 UFC 战斗统计的两个部分:
- 关于刮刀
- 战斗机铲运机
****关于刮刀数据对象被分解为以下碎屑项:
class BoutScraperItem(Item):
event_name = Field()
event_date = Field()
event_attendance = Field()
fighter1 = Field()
fighter2 = Field()
str_stat_f1 = Field()
str_stat_f2 = Field()
td_stat_f1 = Field()
td_stat_f2 = Field()
sub_stat_f1 = Field()
sub_stat_f2 = Field()
pass_stat_f1 = Field()
pass_stat_f2 = Field()
weight_class = Field()
win_method_type = Field()
win_method_finish = Field()
round_ = Field()
time = Field()
winner = Field()
回合蜘蛛抓取 UFC 战斗统计的事件部分,并记录每个战士的特定统计,如 str_stat_f1(战士 1 的攻击统计),其中许多将成为我们多目标回归问题的因变量。Fighter1 和 Fighter2 是一场比赛中所涉及的拳手的名字,我们将这些值加入到战斗机数据中。
****战斗机铲运机数据对象分解为:
class FightScraperItem(Item):
fighter_name = Field()
fighter_record = Field()
height = Field()
weight = Field()
reach = Field()
stance = Field()
date_of_birth = Field()
slpm = Field() # strikes landed per min stat td_avg = Field() # takedown average strike_acc = Field() # striking accuracy td_acc = Field() # takedown accuracy
sapm = Field() # strikes absorbed per minute td_def = Field() # takedown defence strike_def = Field() # striking defence sub_avg = Field() # submission average
这里的每一项都是从拳手统计页面中单独抓取的,该页面详细描述了 UFC 回合中每个拳手的职业统计(尽管 UFC 早期的数据填充较少)。
我将这两个数据对象作为表保存到 SQLite 数据库中,并编写了一个小脚本来生成一个组合的 fight-bouts CSV 文件,其中每一行都是 fighter1 和 fighter2 各自的 fighter stats。这个 CSV 以及 fighters 数据对象的 CSV 表示将是我们用来构建这两个模型的两个文件。
如果你有兴趣了解每个蜘蛛的实际抓取逻辑,看看这里的。
预处理
与大多数这类 ML 项目一样,真正的工作是在预处理步骤中完成的,以及如何为建模阶段准备数据。
项目的这一方面经历了无数次迭代。我从 Jupyter 笔记本开始,但随着复杂性的增加,我决定将其作为前端应用程序来实现,我将设计更改为包含 winner predictor 和 stats predictor 的共享预处理方法以及特定于任务的预处理方法的类。
大量的预处理致力于清除丢失的或格式错误的值,例如,高度被表示为字符串,解析字符串斗士记录,以及获得斗士在战斗时的年龄。
预处理中最棘手的一个方面是改变 fighter1 和 fighter2 的统计数据的顺序。我不得不打乱这种顺序的原因是 UFC 的回合数据总是按顺序排列,所以 fighter1 是赢家,所以我必须想出一种方法来随机选择一半的数据集,并将 fighter1 和 fighter2 的统计数据位置相互交换,以便最终的数据集被整齐地分开,这样 fighter1 的 50%是赢家,fighter2 的 50%是赢家。我很乐意整理这种逻辑,如果有人有任何改进的建议,我很乐意听听。
处理器类的另一个重要特性是,它们必须能够在生产中以不同的方式处理数据,因为在生产环境中,数据帧的构造不像训练步骤那样整齐。
在生产中,战斗机的统计数据必须被特别地预测,然后插入到最终的数据帧中,用于胜利者的预测。我的解决方案是为处理器创建额外的子类,以处理特定于生产的情况。
建模
这两个模型都是使用 Keras 构建的,相对简单的架构只包含一个完全连接的隐藏层。我采取了一种启发式的方法来寻找两者的最佳参数,但我渴望使用更新的工具优化工具,如 Keras 调谐器来微调其性能。
统计模型
统计模型采用战斗前双方可用的所有统计的缩放数字表示,其输出层由 8 个特定于战斗的统计组成:
output_cols = [
'pass_stat_f1', 'pass_stat_f2', 'str_stat_f1', 'str_stat_f2', 'sub_stat_f1', 'sub_stat_f2', 'td_stat_f1', 'td_stat_f2' ]
由于这是一个回归问题,统计模型中的最后一层具有线性激活(默认激活)。对于损失,我使用“mse”和 R 作为模型的度量来评估性能。
在验证集上,该模型的 R 通常约为 0.63–64,这还不算太差,但值得注意的是,随着额外的预测值(输出)的增加,R 将始终增加,其中一些可归因于碰巧对齐的随机噪声。为了解决这个问题,我将增加调整后的 R 来惩罚新版本中每一个新输出的模型。
赢家预测模型
像 stats 模型一样,它遵循一个基本的单个全连接隐藏层架构。因变量是 0 (fighter1)或 1 (fighter2),所以我在最后一层添加了一个简单的 sigmoid 激活来预测这些结果之一。
该模型的准确性通常约为 86%,但必须强调的是,这一准确性是通过动态战斗统计的完美信息实现的,这些信息在生产中是预测值,因此不是完美信息,因此统计预测模型的预测能力存在巨大的偶然性。
通过 API 为模特服务
因为我想将模型及其预测作为前端服务,所以我需要构建一些 API 端点来访问模型和可以进行预测的战斗机列表。
使用 Flask,这是相对直接的。有两个主要端点,一个为生成预测的战斗机名称列表服务,另一个为预测管道排队并返回结果。
流水线处理每架战斗机的数据帧,然后将它们连接成正确的形状和顺序,以便进行统计预测。一旦返回了统计预测值,它们就作为具有各自名称和位置的列被添加到数据帧中,并被传递给获胜者预测模型,从而返回与战斗机 1 或 2 相关联的结果。
反应前端
然后,所有 API 的功能都由一个非常简单的 React 前端调用,该前端为用户提供两个可搜索的下拉列表和一个结果显示,显示预测的获胜者和模型对其预测的信心。
在 React 中设置这一点很容易,我发现 React 通常是一种乐趣(我❤胡克)。
我想在前端添加很多东西,比如一个显示用户预测历史的表格,一个显示基本战斗机统计数据的信息图。
包扎
希望这对 ML 爱好者和/或 MMA 爱好者来说都是有益的,正如我已经提到的,我希望在未来的这个项目中增加许多功能,我很想听听你们的想法。谢谢!
另外,也许现在还不要对模型的所有预测结果下赌注。
用机器学*预测二手车价格
原文:https://towardsdatascience.com/predicting-used-car-prices-with-machine-learning-fea53811b1ab?source=collection_archive---------12-----------------------
从数据收集到模型评估的完整数据科学项目
我打算卖掉我的车,那是一辆 4 年前的大众 polo。二手车通常在土耳其一个名为“ sahibinden ”的网站上出售。“Sahibinden”的意思是“来自车主”,尽管有许多经销商使用这个网站来出售或购买二手车。卖二手车最关键的部分是确定最优价格。有许多网站给你二手车的价格,但你仍然想在定价前搜索市场。此外,还有其他影响价格的因素,如位置、你想以多快的速度卖车、车内吸烟等。在你在网站上发布广告之前,最好先看看类似汽车的价格。然而,这个过程可能会很累,因为网上有太多的广告。因此,我决定利用机器学*提供的便利来创建一个模型,根据“ sahibinden ”上的数据预测二手车价格。它不仅有助于解决我的汽车定价问题,还能帮助我学*和实践许多与数据科学相关的主题。
本项目分为以下 5 个子部分:
- 数据收集
- 数据清理
- 探索性数据分析
- 回归模型与评估
- 进一步改进
所有的数据和代码都可以在 github 知识库上获得。请随意使用或分发。
1。数据收集
在“ sahibinden ”网站上有六千多件大众马球出售。我不得不做网络搜集,从网站上收集数据。我不是网络搜集专家,但我已经学到了足够的知识来获取我需要的信息。我认为,如果你想在数据科学领域工作或正在工作,学*一定水平的网络抓取是非常重要的,因为数据通常不会放在盘子里提供给我们。我们必须得到我们需要的。
我使用了 beautiful soup ,这是一个 python 库,用于从 HTML 和 XML 文件中提取数据。语法非常简单,易于学*。有几个重要的细节你需要注意,特别是如果数据被列在几页上。
总是先导入依赖项:
import pandas as pd
import numpy as np
import requests
from bs4 import BeautifulSoup as bs
我使用 python 的请求库的 get() 方法从源中检索数据,并将其存储在一个变量中。然后我用美汤提取整理了这个变量的内容。由于数据在几个页面上,我不得不创建 list 来帮助解析不同的页面,并启动空列表来保存数据。
#initiate empty lists to save data
model_info = []
ad_title = []
year_km_color = []
price = []
ad_date = []
location = []#create lists to parse through pages
page_offset = list(np.arange(0,1000,50))
min_km = [0, 50000, 85000, 119000, 153000, 190000, 230000]
max_km = [50000, 85000, 119000, 153000, 190000, 230000, 500000]
一个页面上最多可以显示 50 个广告。为了搜集大约 6000 辆汽车的数据,我需要迭代 120 多页。首先,我将代码组织在一个 for 循环中,从 120 页中提取数据。然而,在这个过程完成后,我发现数据在前 1000 个条目后重复。然后,我决定将数据分成更小的部分,每组不超过 1000 个条目,所以我使用“km”标准来区分组。我创建了嵌套的 for 循环来提取大约六千辆汽车的数据,如下所示:
for i, j in zip(min_km, max_km):
for page in page_offset:
r = requests.get(f'https://www.sahibinden.com/volkswagen- polo?pagingOffset=**{page}**&pagingSize=50&a4_**max={j}**&sorting=date_asc&a4_**min={i}**', headers=headers)
soup = bs(r.content,'lxml')
model_info += soup.find_all("td",{"class":"searchResultsTagAttributeValue"})
ad_title += soup.find_all("td",{"class":"searchResultsTitleValue"})
year_km_color += soup.find_all("td",{"class":"searchResultsAttributeValue"})
price += soup.find_all("td",{"class":"searchResultsPriceValue"})
ad_date += soup.find_all("td",{"class":"searchResultsDateValue"})
location += soup.find_all("td",{"class":"searchResultsLocationValue"})
在每次迭代中,使用 page_offset、max_km 和 min_km 列表中的值修改基本 url,以转到下一页。然后根据标签和类别将网站内容分解成预定义的列表。html 中的类和标签可以通过在浏览器上检查网站来显示。
“沙希宾登”网站的 HTML
得到 html 的内容后,我提取了文本部分:
model_info_text = []
for i in range(0,6731):
model_info_text.append(model_info[i].text)
对每个列表都进行了这一过程,然后我将这些列表组合起来构建一个熊猫数据框架:
df = pd.DataFrame({"model":model_info_text, "ad_title":ad_title_text,"year":year_text, "km":km_text, "color":color_text,"price":price_text, "ad_date":ad_date_text, "location":location_text})print(df.shape)
print(df['ad_title'].nunique())
(6731, 8)
6293
Dataframe 包括 6731 个条目,但根据广告的标题,其中 6293 个条目似乎是唯一的,我认为这是区分广告的最佳选择。一些用户可能会重新发布相同的广告,或者一些广告的标题可能完全相同。
2.数据清理
我把从网站上抓取的数据保存为 csv 文件。
df = pd.read_csv('polo_data.csv')
df.head()
必须删除新的线条指示器(\n)。我使用 pandas remove() 函数,其中 regex 参数设置为 True。类似地,在价格单元中代表土耳其货币的 TL 必须被移除以进行数值分析。
df = df.replace('\n','',regex=True)
df.price = df.price.replace('TL','',regex=True)
在尝试进行任何分析之前,我们总是需要寻找缺失值并检查数据类型:
df.isna().any()
model False
ad_title False
year False
km False
color False
price False
ad_date False
location False
dtype: booldf.dtypes
model object
ad_title object
year int64
km float64
color object
price object
ad_date object
location object
dtype: object
日期的数据类型是 object。为了能够正确使用日期,我将数据 dype 转换为日期时间。数据是土耳其语的,所以在使用 astpye() 函数之前,我将月份的名称改为了英语。我用字典来改变月份的名称。
months = {"Ocak":"January", "Şubat":"February", "Mart":"March", "Nisan":"April","Mayıs":"May","Haziran":"June","Temmuz":"July","Ağustos":"August","Eylül":"September", "Ekim":"October", "Kasım":"November", "Aralık":"December"}df.ad_date = df.ad_date.replace(months, regex=True)#change the datatype
df.ad_date = pd.to_datetime(df.ad_date)
在读取 csv 文件时,“km”列被截断,该列显示汽车已经行驶了多少公里。这是因为“点”在千中使用。例如,25.000,即 25,000 被检测为 25.0。为了解决这个问题,我将“km”列乘以 1000。为了能够将“km”列的数据类型改为数字(int 或 float),我还删除了“.”和“,”字符。
df.km = df.km * 1000df.iloc[:,5] = df.iloc[:,5].str.replace(r'.','')
df.iloc[:,5] = df.iloc[:,5].str.replace(r',','') #change the datatype
df.price = df.price.astype('float64')
在土耳其,由于人口分布不均,位置可能是决定二手车价格的一个因素。我们的数据框架中的位置数据包括城市和地区。我不认为同一个城市不同区的价格变化。因此,我修改了位置数据,只包含了城市的名称。
位置信息的格式为 CityDistrict(中间没有空格)。地区名称以大写字母开头,用于区分城市和地区。我用的是 python 的 re 模块的 sub() 函数。
import res = df['location']
city_district = []for i in range(0,6731):
city_district.append(re.sub( r"([A-Z, 'Ç', 'İ', 'Ö', 'Ş', 'Ü'])", r" \1", s[i]).split())city_district[:5]
[['Ağrı', 'Merkez'],
['İstanbul', 'Kağıthane'],
['Ankara', 'Altındağ'],
['Ankara', 'Çankaya'],
['Samsun', 'Atakum']]
这个 for 循环以大写字母拆分 location 列的每个单元格中的字符串。土耳其语字母表包含不在英语字母表[A-Z]范围内的字母。我也在 sub 函数中添加了这些字母。输出是两项列表的列表。我使用这个列表的第一项创建了另一个名为“city”的列。
city = []
for i in range(0,6731):
city.append(city_district[i][0])city[:5]
['Ağrı', 'İstanbul', 'Ankara', 'Ankara', 'Samsun']df['city'] = city
nunique() 函数计算对探索性数据分析和结果确认都有用的唯一值。
df.city.nunique()
81
土耳其有 81 个城市,因此数据集包括每个城市至少一辆汽车。
3。探索性数据分析
价格
了解目标变量总是好的。在我们的例子中,目标变量或因变量是价格。
print(df.price.mean())
print(df.price.median())
83153.7379289853
64250.0
平均值远高于中值,这表明存在异常值或极值。让我们同时检查最大值和最小值:
print(df.price.max())
print(df.price.min())
111111111.0
24.0
这种价值观显然是错误的。除非镀金,否则没有超过 1 亿英镑的大众马球。同样,24 土耳其里拉的价值也是不可能的。在使用 sort_values() 函数对 price 列中的值进行排序之后,我检测到了一些异常值,并使用 pandas drop() 函数通过传递要删除的值的索引来删除它们。让我们检查新的平均值和中间值:
print(df.price.mean())
print(df.price.median())
print(df.price.median())66694.66636931311
64275.0
25000.0
平均值仍高于中值,但差异并不极端。我还检查了 mode,这是最常出现的值。平均值高于中值表明数据是正确的或正偏态的,这意味着我们有更多的较低价格和一些具有较高值的异常值。被排序为均值>中值>众数的集中趋势度量是正(右)偏度的指示。我们可以用分布图仔细检查:
x = df.price
plt.figure(figsize=(10,6))
sns.distplot(x).set_title('Frequency Distribution Plot of Prices')
从图中可以看出,数据是右偏的,25000 左右的峰值向我们展示了该模式。检查分布和异常值的另一种方法是箱线图:
plt.figure(figsize=(8,5))
sns.boxplot(y='price', data=df, width=0.5)
蓝框的底部和顶部分别代表第一个四分位数(25%)和第三个四分位数(75%)。第一个四分位数意味着 25%的数据点低于该点。中间的线是中位数(50%)。异常值用最大线上方的点表示。
日期
我不认为日期本身对价格有影响,但网站上广告的等待时间是一个需要考虑的因素。更长的等待时间可能会促使业主降价。如果一个广告在网站上停留了很长时间,这可能是因为价格设置不当。因此,我将添加一个列,表明广告已经在网站上的天数。数据于 2020 年 1 月 18 日报废。
df['ad_duration'] = pd.to_datetime('2020-01-18') - df['ad_date']
Ad_duration 必须是数字数据,因此需要删除数字旁边的“天数”。我用熊猫 replace() 函数去掉了‘天’。
让我们检查广告持续时间数据的分布:
print(df.ad_duration.mean())
print(df.ad_duration.median())
12.641540291406482
10.0
平均值高于中值,有许多异常值。数据是右偏的。为了更好地理解,我还绘制了小于 50 的数据点:
地点
有 81 个不同的城市,但 62%的广告都列在前 10 个城市,伊斯坦布尔占 23%的广告。
a = df.city.value_counts()[:10]
df_location = pd.DataFrame({"city": a , "share": a/6726})df_location.share.sum()
0.6216176033303599
广告数量排名前十的城市
颜色
看起来大众 polo 的最佳颜色选择是白色。一半以上的汽车是白色的,其次是红色和黑色。前三种颜色覆盖了 72%的汽车。
贝亚兹:白色,科勒姆兹:红色,西亚赫:黑色
年
车龄肯定会影响价格。然而,用 is 代替汽车的型号年份更有意义。所以我用当年的“年份”一栏来代替。
df['age'] = 2020 - df['year']
从分布来看,大部分车龄不到 10 年。在 10 处有一个巨大的下降,然后是一个上升的趋势。
公里
公里值显示了车开了多少,所以它绝对是决定价格的一个重要因素。Km 数据*似呈正态分布。
print(df.km.mean())
print(df.km.median())
141011.5676479334
137000.0
广告标题
广告标题是广告的一种说明。卖家试图用数量有限的人物来吸引潜在买家。一旦广告被点击,另一个带有图片和更详细信息的页面就会打开。然而,第一步是让人们点击你的广告,所以广告标题在销售过程中起着至关重要的作用。
我们来看看大家一般都在标题里写些什么。我在这个任务中使用了 wordcloud 。
#import dependencies
from wordcloud import WordCloud, STOPWORDS
WordCloud 唯一需要的参数是一个文本。您可以通过键入“?其他可选参数。我们无法将列表输入到 wordcloud,所以我通过连接 ad_title 列中的所有标题创建了一个文本:
text_list = list(df.ad_title)
text = '-'.join(text_list)
然后用这段文字生成了一个单词云:
#generate wordcloud
wordcloud = WordCloud(background_color='white').generate(text)#plot wordcloud
plt.figure(figsize=(10,6))
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
plt.show()
无停用词的词云
单词云的想法非常简单。越频繁出现的单词显示得越大。这是一个信息量大、易于理解的文本分析工具。然而,上面的 wordcloud 并没有告诉我们太多,因为“大众”、“大众”和“polo”这些词并不是我们要找的。它们展示了我们正在分析的品牌。在这种情况下,我们要使用 wordcloud 的停用词参数,列出需要排除的词。
stopwords = ['VW', 'VOLKSWAGEN', 'POLO', 'MODEL', 'KM']
wordcloud = WordCloud(stopwords=stopwords).generate(text)plt.figure(figsize=(10,6))
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")
plt.show()
带停用词的单词云
这次我没有使用背景颜色参数,只是为了显示不同之处。这些话是土耳其语,所以我会给一个简短的解释:
- “Hatası”:没有任何问题
- “Sahibinden”:从所有者(这很重要,因为人们倾向于从所有者而不是经销商那里购买)。
- “Otomatik”:自动变速器
- “Boyası”:无油漆(由于裂纹、划痕或维修,汽车的任何部分都没有油漆)
其他的话主要是关于干净,没有任何以前的维修。
型号
型号栏包括三种不同的信息:发动机尺寸、燃料类型和变型。检查完这些值后,我发现对于所有单元,只有引擎大小信息是完整的。大多数单元格都缺少燃料类型和变体,因此我为发动机大小创建了一个单独的列。
空格后的前三个字符代表发动机尺寸。我首先删除了空格,并从 model 列中提取了前三个字符:
#remove spaces
df.model = df.model.replace(' ','',regex=True)engine = [x[:3] for x in df.model]
df['engine'] = engine
让我们来看看不同发动机尺寸的价格变化:
df.engine.value_counts()
1.4 3172
1.6 1916
1.2 1205
1.0 409
1.9 20
1.3 4
Name: engine, dtype: int64df[['engine','price']].groupby(['engine']).mean().sort_values(by='price', ascending=False)
似乎平均价格随着发动机尺寸的增加而降低。1.3 可以忽略,因为只有 4 辆车采用 1.3 发动机。与 1.0 和其他发动机尺寸有很大差距,因为 1.0 是较新的型号。正如你在下面的图表中看到的,发动机尺寸为 1.0 的汽车平均车龄和公里数都最低,这表明它们是较新的车型。
不同发动机尺寸的平均车龄和公里数
4。回归模型
线性回归是一种广泛使用的监督学*算法,用于预测连续的因变量(或目标变量)。根据独立变量的数量,它可以是简单或多元线性回归的形式。我创建了一个多元线性回归模型,因为我使用了许多自变量来预测因变量,即二手车的价格。
我们不应该只是使用所有的独立变量,而没有任何预处理或事先判断。特征选择是决定在模型中使用哪些特征(独立变量)的过程。特征选择是一个非常关键的步骤,因为使用不必要的特征会对性能产生负面影响,而删除重要的特征会妨碍我们获得高精度。
我们可以使用回归图来检查因变量和自变量之间的关系。我检查了 km 和价格之间的关系,我认为这是高度相关的。
plt.figure(figsize=(10,6))
sns.regplot(x='km', y='price', data=df).set_title('Km vs Price')
显而易见,随着公里数的增加,价格下降。然而,也有例外。根据上面的回归图,公里数高于 400000 的汽车可以标记为异常值。为了提高模型的准确性,我去除了这些异常值。离群值往往会使模型过度拟合。
df = df[df.km < 400000]
plt.figure(figsize=(10,6))
sns.regplot(x='km', y='price', data=df).set_title('Km vs Price')
Km 与剔除异常值后的价格
现在好多了!
在对年龄和价格应用相同的步骤后,观察到类似的关系:
剔除异常值后的年龄与价格
我还检查了广告时长和引擎大小与价格之间的关系。发动机尺寸越大,平均价格越低。然而,广告持续时间似乎对价格几乎没有影响。
****
检查变量之间关系的另一种方法是相关矩阵。熊猫 corr() 函数计算数值变量之间的相关性。
该值越接* 1,相关性越高。-'号表示负相关。这些值与上面的回归图一致。
我们也可以使用 seaborn 热图来可视化相关矩阵:
corr = df.corr()
plt.figure(figsize=(10,6))
sns.heatmap(corr, vmax=1, square=True)
根据右边的颜色表,两个变量相交处的方框颜色显示相关值。
线性回归模型
在检查了变量的相关性和分布后,我决定用车龄、公里数、引擎大小和广告时长来预测一辆二手车的价格。
我使用了 scikit-learn ,它提供了简单有效的机器学*工具。
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score
我提取了要使用的特性(列):
X = df[['age','km','engine','ad_duration']] #independent variables
y = df['price'] #dependent (target) variable
然后使用 scikit-learn 的 train_test_split 函数,我将数据划分为训练和测试子集。分离训练集和测试集是每个机器学*算法中非常重要的一步。否则,如果我们在同一个数据集上训练和测试,我们将要求模型预测它已经知道的东西。
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)
然后我创建了一个 LinearRegression()对象,用训练数据集对它进行了训练。
linreg = LinearRegression()linreg.fit(X_train, y_train)
是时候衡量模型的准确性了。我在训练和测试数据集上测量了模型的准确性。如果训练数据集上的精度远远高于测试数据集上的精度,我们就有一个严重的问题:过拟合。我不会去详细了解过度拟合。这可能是另一个帖子的主题,但我只想简单解释一下。过度拟合意味着模型过于具体,不能很好地概括。过度拟合模型试图捕获训练数据集中的噪声和极值。
linreg.score(X_train, y_train)
0.8351901442035045linreg.score(X_test, y_test)
0.8394139260643358
比分非常接*,这很好。这里的分数是 R 平方 分数,它是确定实际数据点与拟合回归线有多接*的度量。R 平方值越接* 1,我们的模型就越准确。r 平方度量了我们的模型解释了多少目标变量的变化。
****残差图用于检查实际值和预测值之间的误差。如果一个线性模型是合适的,我们期望看到误差被随机传播并且具有零均值。
plt.figure(figsize=(10,6))
sns.residplot(x=y_pred, y=y_test)
实际值和预测值之间的误差
这些点的平均值可能接*于零,但显然它们不是随机分布的。该分布接* U 形,这表明线性模型可能不是这项任务的最佳选择。
在这种情况下,我想使用 scikit-learn 的 RandomForestRegressor() 来尝试另一个模型。随机森林是建立在决策树上的集成方法。威尔·科尔森的这篇文章对决策树和随机森林做了全面的解释。随机森林通常用于分类任务,但也适用于回归。
from sklearn.ensemble import RandomForestRegressorregr = RandomForestRegressor(max_depth=5, random_state=0, n_estimators=10)
与线性回归不同,随机森林有一些关键的超参数需要优化。max _ depth是一棵树的最大深度(不言自明),它控制着一棵树有多深或者你想要多少个分支。 n_estimator 是一片森林中的树木数量。决策树容易过度拟合,这意味着你很容易使它过于具体。如果 max_depth 太高,可能会导致模型过拟合。我手动更改了 max_depth,以便检查准确性和过度拟合。但是 scikit-learn 提供了非常好的超参数调优工具:RandomizedSearchCV和GridSearchCV。对于更复杂的任务和模型,我强烈推荐使用它。****
**print('R-squared score (training): {:.3f}'
.format(regr.score(X_train, y_train)))
R-squared score (training): 0.902print('R-squared score (training): {:.3f}'
.format(regr.score(X_test, y_test)))
R-squared score (training): 0.899**
测试集上的 r 平方得分是 0.899,这表明与线性回归相比有显著的改进。我还尝试将 max_depth 参数设置为 20,结果是在 overfit 模型上,如下所示。模型在训练集上非常准确,但在测试集上的准确性变得较低。
**regr = RandomForestRegressor(max_depth=20, random_state=0, n_estimators=10)regr.fit(X_train, y_train)print('R-squared score (training): {:.3f}'
.format(regr.score(X_train, y_train)))
R-squared score (training): 0.979print('R-squared score (training): {:.3f}'
.format(regr.score(X_test, y_test)))
R-squared score (training): 0.884**
最后我根据车型查了一下我车的价格:
**regr.predict([[4,75000,1.2,1]])
array([99743.84587199])**
模型建议我以差不多 10 万英镑的价格卖掉我的车,这比我心目中的价格要高。然而,我的车出了事故,经过修理,价格降低了。这些信息没有被作为独立变量考虑,这就把我们带到了本文的最后一部分:进一步改进。
4.进一步改进
有许多方法可以改进机器学*模型。我觉得最根本最有效的一条就是多收集数据。在我们的例子中,我们可以(1)收集更多汽车的数据,或者(2)收集当前数据集中更多汽车的信息,或者两者都收集。对于第一个,有其他网站出售二手车,所以我们可以通过添加新车来增加数据集的大小。对于第二个问题,我们可以从“ sahibinden ”网站收集更多关于汽车的数据。如果我们点击一个广告,另一个有详细信息和图片的页面就会打开。在这一页,人们写下汽车的问题,以前的事故或维修等等。这种信息无疑是有价值的。
另一种改进方法是调整模型超参数。我们可以使用 RandomizedSearchCV 来找到最佳的超参数值。
结论
我试图给你一个机器学*项目如何建立的概述。尽管这不是一项非常复杂的任务,但大多数数据科学项目都遵循类似的模式。
- 定义问题或疑问
- 收集和清理数据
- 进行探索性数据分析,以获得一些关于数据的见解
- 建立一个模型
- 评估模型
- 除非结果令人满意,否则请返回前面的任何步骤。
用机器学*技术预测二手车价格
原文:https://towardsdatascience.com/predicting-used-car-prices-with-machine-learning-techniques-8a9d8313952?source=collection_archive---------1-----------------------
比较五种不同 ML 模型的性能
你可以在我的 github 页面上找到这项研究的所有 Python 脚本。如果您感兴趣,您还可以在同一个存储库中找到用于该研究的数据清理的脚本。
谁应该读这个?
如果您有兴趣了解从零开始构建机器学*系统,包括:
- 数据清理期间的调整
- 探索性数据分析
- 执行机器学*模型:随机森林,线性回归,岭回归,拉索,KNN,XGBoost
- 模型的性能比较
- 以专业的方式报告研究结果
问题
业内新车的价格由制造商确定,政府以税收的形式支付一些额外的费用。因此,购买新车的客户可以放心,他们投资的钱是值得的。但由于新车价格上涨,以及客户因缺乏资金而无法购买新车,二手车销售在全球范围内呈增长趋势(Pal,Arora 和 Palakurthy,2018)。需要一种二手车价格预测系统来使用各种特征有效地确定汽车的价值。即使有网站提供这种服务,他们的预测方法也不一定是最好的。此外,不同的模型和系统可能有助于预测二手车的实际市场价值。在买卖时,了解它们的实际市场价值是很重要的。
客户端
能够预测二手车的市场价值对买卖双方都有帮助。
二手车销售商(经销商):他们是可能对本研究结果感兴趣的最大目标群体之一。如果二手车卖家更好地了解什么使一辆车可取,什么是二手车的重要特征,那么他们可能会考虑这些知识,并提供更好的服务。
在线定价服务:有些网站提供汽车的估价。他们可能有一个很好的预测模型。然而,拥有第二个模型可能有助于他们向用户提供更好的预测。因此,这项研究中开发的模型可能有助于在线网络服务,告诉二手车的市场价值。
个人:有很多人在他们人生的某个阶段对二手车市场感兴趣,因为他们想卖掉自己的车或买辆二手车。在这个过程中,支付过高或低于市场价值出售都是一个大问题。
数据
本项目使用的数据是从 Kaggle 下载的。它是由 Kaggle.com 用户奥斯丁·里斯上传到 Kaggle 上的。奥斯汀·里斯从 craigslist 上搜集了这些数据,目的是为了非盈利。它包含了 Craigslist 提供的关于汽车销售的几乎所有相关信息,包括价格、状况、制造商、纬度/经度等栏目,以及 22 个其他类别。
数据角力
在本节中,我们将讨论如何对 craigslist 二手车数据文件应用数据清理和争论方法。
在进行数据清洗之前,对数据集进行了一些探索和数据可视化。这为如何处理缺失值和极端值提供了一些思路和指导。在数据清理之后,再次应用数据探索,以便理解数据的清理版本。
数据清理:数据清理的第一步是删除不必要的特征。为此, 'url ',' image_url ',' lat ',' long ',' city_url ',' desc ',' city ',' VIN' 等功能全部被删除。下一步,调查该特性的零点数量和零点数据点的百分比(表 1)。
下一步,极值被删除,因为它们抑制了模型的预测能力。首先,标价超过 10 万美元的汽车被取消了。在 550313 个数据点中,只有 580 个数据点的价格超过 100k。它只能满足一小部分买家的需求。此外,有 61726 辆汽车的价格低于 750 美元。这些值也被从数据集中删除,因为这些价格对数据来说是噪音。其次,里程表值超过 300,000 英里但低于 10 英里的汽车被取消。最后,早于 1985 年的汽车被淘汰。对于我们的分析,这些数据点可以被视为异常值。
第二步,用适当的值填充一些缺失的值。对于缺少的'条件'值,注意根据类别进行填充。计算所有'条件'子类别的平均里程表。然后,通过考虑每个条件子类别的平均里程表值来填补缺失值。另外,车型值高于 2019 年的车填为'新',2017-2019 年之间填为'如新'。在此过程结束时,清除了“条件”功能中所有缺失的值。
其他的用' ffill' 的方法填充。此方法将最后一个有效观察向前传播到下一个有效观察。因此,最后一个已知值在每个时间点都可用。到目前为止,里程表,条件,条件和价格功能的所有缺失值都很清楚。经过这一步,所有数据都变得干净了。在此操作之后,将对数据中的 380,962 个观察值进行研究和分析。
探索性数据分析
在探索数据的同时,我们将借助视觉效果来观察不同的功能组合。这将有助于我们更好地理解我们的数据,并给我们一些关于数据模式的线索。
考察物价走势
价格是我们在这项研究中预测的特征。在应用任何模型之前,看看价格数据可能会给我们一些想法。
通过查看图 1,可以观察到大多数二手车的价格低于 20,000 美元。此外,我们看到仍有相当数量的汽车价格超过 2 万美元。我们可以猜测所有类型的汽车可能便宜或昂贵。但是,仍然优秀,喜欢新的,良好的条件的汽车是最受欢迎的汽车在二手车市场(图 2)。打捞车在流行程度上是遵循这三个类别的。因此,仅仅考虑汽车的类型或状况,很难对汽车的价格做出准确的估计。但我们可以告诉它,某些条件的汽车是受欢迎的和更高的机会出售。
二手车的流行特征
在购买二手车时,人们会认真关注车上的里程表值。我们可以看到里程表显著地改变了汽车的价格(图 3)。另一方面,这并不意味着只销售低里程表汽车。根据价格,高里程表汽车也有买家(图 4)。此外,最受欢迎的二手车是里程表在 100k 左右的车。直到 150k 的里程表,市面上的车很多。
汽车制造商是二手车市场上的另一个重要变量。福特和雪佛兰是北美占主导地位的制造商之一(图 5)。丰田和日产作为大厂商遵循订单。可以得出结论,日系车在二手车市场占有相当大的份额。但是,美国车仍然是按需供应,占主导地位。
变速器:变速器是二手车市场中另一个占主导地位的子类别。根据图 6,自动变速器对人们对汽车的偏好有很大的影响。从图 6 中可以看出,2000 年以后,自动变速器汽车在增加。2009 年,这一数字有所下降。全球经济衰退可能会影响二手车市场。另一个有趣的趋势是,2009 年后,其他传播方式在增加。它的市场份额相比自动挡还是那么低,但还是很可观的。其他传输类型增加可能是由几个原因造成的。第一种可能性是无级变速器(CVT)增加。CVT 更环保更省油。这种技术可能会得到推广。另一种可能是 Craigslist 网站上的一些卖家没有填写汽车信息的传输部分。网站可能会直接将他们归入“其他”类别。这也解释了“其他”类别传播的增加。
传动系统类型:在评估一辆车的时候,了解是什么影响了它的状况是很重要的。图 7 告诉我们,四轮驱动汽车更加耐用和可靠。可以看出,从数量上看,4wd 的车是最受欢迎的。从长远来看,与 rwd 和 fwd 传动系统相比,它们可以保持更好的运行能力。4wd 在汽车的“优秀”、“像新的一样”和“状况良好”方面的数字最高。另一方面,我们需要记住,与总数相比,很难说四轮驱动汽车具有更高的“优秀”率和“喜欢新汽车”率(图 7)。此外,通过查看表 4,
我们可以看到,对于所有分位数,所有动力传动系统类型的平均里程表彼此非常接*。这也告诉我们,在二手车市场,驾驶类型可能不会影响汽车的里程表。但是它们的受欢迎程度在驾驶员中是不同的(表 3 和图 8)。
检验&假设
为了理解什么影响二手车价格的变化,将通过使用推断统计方法来检查数据 sat 中可用特征之间的关系。基于图表的主要假设是价格必须受到里程表和条件的影响。一定还有其他显著影响价格的特征。这将在研究的后期阶段进行调查。
第一个假设:
空假设:汽车的价格和里程表没有显著的关系
替代假设:价格与里程表之间存在显著关系。
第二个假设 :
无效假设:汽车的价格和状况之间没有显著的关系
替代假设:价格和条件之间有很大的关系。
里程表 vs 价格
首先,检验第一个假设。在检验两个数值变量之间的关系时,独立 t 检验是一种合适的方法。另一方面,这个测试有一些假设。方差齐性是假设之一。为了检查方差齐性假设是否被违反,应用了 Levene 检验。
检验方差的均匀性:Levene 检验的结果:
Levene 结果(统计值=335641.8310266318,p 值=0.0)
这意味着方差的同质性被破坏了。在这种情况下,我们需要使用韦尔奇检验。Welch t 检验是一种非参数单变量检验,用于检验两个不相关组的均值之间的显著差异。当方差相等的假设存在违规时,它是独立 t 检验的替代方法。因此,它适用于这种情况。以下是韦尔奇测试的结果:
Welch's t-test= 740.70p-value = 0.00Welch-Satterthwaite Degrees of Freedom= 276855.87
在这里,p 值非常重要。这说明里程表和汽车价格之间有很大的关系。作为参考,进行独立的 t 检验没有坏处。它可以提供一些想法,即使它不是里程表和价格功能的健壮方法。
检查正态性:对于检查正态性,q-q 图有助于我们。图 9 告诉我们这违反了常态。这意味着所使用的数据点不是正态分布的。此外,夏皮罗-维尔克检验用于检查正态性。
结果:(0.9586305022239685,0.0)
这里,第一个值是 W 检验统计量,第二个值是 p 值。对于 N > 5000,W 检验统计是准确的,但 p 值可能不准确。通过考虑夏皮罗-维尔克检验的 p 值,可以得出数据不是正态分布的结论。
在这种情况下,我们在初始数据点上有问题。或许,过滤数据可以解决这个问题。为此,远离平均值两个标准差的里程表和价格的值被丢弃,并应用独立 t 检验。
图 9: Q-q 图
如前所述,t 检验在这里是不合适的,因为它违反了方差相等假设和正态假设。另一方面,我们仍然可以解释这个结果,同时记住它是不可靠的。根据表 5,相关性为 0.90。这表明价格和里程表之间有很强的联系。此外,p 值较低,具有统计学意义。效应大小(科恩的 d)是 4.17,这是一个很大的值。d 为 4 表示它们相差 4 个标准差。这意味着两组的平均值相差 4 个标准偏差或更多,因此差异显著。
通过考虑这些韦尔奇检验的结果和表 5,可以得出结论:里程表和价格有显著的关系。因此,第一个假设的零假设被拒绝。拒绝 null 有一些可能的含义:
- 替代假设是真的。
- 可能存在类型 2 错误,这意味着零假设被错误地拒绝
- 是的,有统计学意义。但这并不意味着实际意义。
条件 vs 价格
这项研究的第二个假设关注汽车状况对其价格的影响。为了理解这种关系,表 6 和图 6 可能有用。通过查看图 10,可以说“状况”严重影响了汽车的中值价格。另一方面,在条件值中有许多异常值,这是这样一个 lar 数据集的预期结果。我们在图 10 的底部没有看到异常值。这主要是因为在数据清理期间,价格低于 750 美元的汽车被丢弃。
现在,是时候检查条件和价格之间的关系了。在应用任何线性关系测试之前,必须应用诊断测试。因此,可以检查该关系是否满足四个假设:残差的线性、残差的独立性、残差的正态分布、残差的等方差。为了检验正态性,进行了 Jarque-Bera,为了检验残差的等方差,应用了综合检验。此外,为了检查多重共线性,使用了条件数(condno)检验,为了检测自相关的存在,应用了德班-沃森检验(表 7)。
考虑到表 7,Jarque-Bera p 值和 Omni p 值非常重要。这表明存在违反正态性和方差齐性的情况。此外,Durbin Watson (DW)统计是对统计回归分析中残差的自相关性的测试。德宾-沃森统计值将总是在 0 和 4 之间。值为 2.0 意味着在样本中没有检测到自相关。从 0 到小于 2 的值表示正自相关,从 2 到 4 的值表示负自相关。“条件”和“价格”的德宾沃森得分是 1.49,这表明这是一种微弱但正相关的关系。
对“条件”结果的推断
假设是:
H0 :汽车的价格和状况没有太大的关系
通过考虑测试结果,我们无法拒绝零假设。然而,该假设是基于线性关系。因此,这种情况有几种可能的解释:
“条件”和“价格”之间可以有关系,但不是线性关系。它可以是非线性关系。
可能存在线性关系,但我们的数据可能不具有代表性,使我们看不到这种关系。
零假设是正确的,在“条件”和“价格”之间没有显著的关系。
推断统计学的挑战
在这个数据集中,最大的挑战之一是预测变量的分布违反正态性。这就是为什么,经典的统计方法对分析这些数据帮助不大。此外,数据集中的 14 个变量中只有 3 个数值变量。这限制了我们使用 Pearson-r 相关性的机会。
因此,我们将进入下一部分。在下一节中,将应用机器学*模型,并通过使用平均绝对误差(MAE)、均方误差(MSE)和均方根误差(RMSE)来测试模型的性能。
机器学*模型
本节使用应用机器学*模型作为数据分析的框架。数据集是一种监督数据,指的是将因变量模型拟合到自变量,目的是为未来的观察结果准确预测因变量或了解变量之间的关系(Gareth,Daniela,Trevor,& Tibshirani,2013)。关于数据集,文献表明下列方法可能是合适的。
在本节中,将按顺序应用这些机器学*模型:
随机森林
里脊回归
套索
k-最*邻
XGBoost
此外,在岭回归之前,将应用简单的线性模型并考虑结果。
数据预处理
标签编码。在数据集中,有 13 个预测因子。其中两个是数字变量,其余的是分类变量。为了应用机器学*模型,我们需要特征的数字表示。因此,所有非数字特征都被转换成数字形式。
训练数据。在此过程中,20%的数据被拆分为测试数据,80%的数据作为列车数据。
缩放数据。在研究前几节中的数据时,我们发现数据不是正态分布的。如果不进行缩放,机器学*模型将尝试忽略低值特征的系数,因为与高值特征相比,它们的影响非常小。
在缩放时,使用正确的方法缩放也很重要,因为不适当的缩放会导致不适当的目标量化和不适当的绩效衡量(Hurwitz,e .,& Marwala,2012)。最小-最大缩放器是合适的,特别是当数据不是正态分布,并希望离群值有减少的影响。此外,脊和套索都受到特征大小的影响,以执行正则化。因此,对数据集使用了最小-最大缩放器。
随机森林
随机森林是多个决策树的集合。深度决策树可能会过度拟合,但随机森林通过在随机子集上创建树来防止过度拟合。这就是为什么,这是一个很好的分析模型。
在分析中,创建了 200 棵树。一般来说,树越多,效果越好。结果,获得 4001.8 RMSE 和 2122.92 平均绝对误差(MAE)(表 8)。
图 11:随机森林中的单一决策树
如果我们看一下图 11,我们会看到有七个叶节点。这个树只使用了三个变量:年份、驱动和燃料。叶节点没有问题,因为它们是进行最终预测的地方。要对一个新点进行分类,只需沿着树向下移动,使用该点的特征来回答问题,直到到达一个叶节点,在该叶节点上,类就是预测。
变量重要性:为了量化整个随机森林中所有变量的有用性,我们可以看看变量的相对重要性。图 12 是一个简单的特征重要性条形图,用来说明变量相对重要性的差异。对于本研究,达到 90%的累积重要性被视为成功。
**Model with only important features:** Number of features for 90% cumulative importance is 7 (Fig. 13). The features are: year, odometer, make, drive, fuel, manufacturer, cylinders. The ultimate purpose of the modelling is to get a smaller number of features that can give us a strong prediction. At this point, the model was run with only these seven important features. The new RMSE is 3960.11 (Table 9). This score is slightly better than the full model (4001.80 % vs 3960.11). In addition, this performance was obtained just by using 7 features instead of 13\. Therefore, it can be considered as an improvement in both prediction power and computational cost.
线性回归
在应用脊和套索之前,检查线性回归结果可能是有用的(表 10)。
正如我们在表 10 中看到的,与随机森林相比,线性回归的性能并不太好。实际值和预测值之间的差异值得注意(图 14)。这就是为什么我们需要不同的模型来给出更好的预测结果。
岭回归
普通最小二乘法(OLS)给出无偏回归系数(数据集中观察到的最大似然估计)。岭回归和套索允许正则化(“收缩”)系数。在图 15 中,可以看到系数是如何随着α值的增加而缩小的。
为了在岭回归中找到最佳α值,应用了交叉验证。结果如表 11 所示。
与 OLS 相比,里奇的表现几乎相同。考虑图 16,岭回归表明,这六个变量是最重要的:年份,里程表,燃料,气缸,标题状态和驱动器。
拉索
Ridge 缩小了变量的系数,但不会使它们为零。这在某些情况下可能是好的,但在变量数量相当大的情况下,这可能会给模型解释带来挑战(Gareth、Daniela、Trevor 和 Tibshirani,2013)。对于这个数据集,变量的数量并不大,所以不太需要套索模型。然而,看看 lasso 可以给我们另一个视角。而且,除了投入时间和精力之外,对数据集应用套索没有任何坏处。
为了从图 17 中找到最佳λ值,应用了交叉验证。在这次评估中,获得的 RMSE 是 7578.82(表 12)。
与山脊结果相似,拉索也给出了六个显著特征: 年份、里程表、燃料、汽缸、冠军状态、驱动 。在进行最终解释时,可以考虑这一点。
K-最*邻(KNN)
当你的数据集足够小时,可以使用 KNN 分类器,这样 KNN 分类器可以在更短的时间内完成运行。KNN 算法可以与最精确的模型竞争,因为它做出高度精确的预测。因此,我们可以将 KNN 算法用于需要良好预测但不需要人类可读模型的应用程序。预测的质量取决于距离度量。因此,KNN 算法适用于具有足够领域知识的应用程序(IBM 知识中心,n.d .)。因为我们有 13 个用于预测的特征,KNN 是适用于本研究的合适方法。对于 RMSE 值的评估,我们可以看一下表 12。
从表 13 和图 19 可以看出,当 k 为 7 时,RMSE 值最低。另一方面,k 为 2 和 7 的 RMSE 值之间没有显著差异。这里的基本原理是,如果一组 K 值看起来或多或少一样好,那么我们不妨选择最简单的模型——也就是具有最少数量预测值的模型。对于我们的情况,我们可以选择 2 个预测值,因为它具有最低的 RMSE 值(表 13)。但是,考虑到以前的模型,六七个预测器仍然有很强的理由选择,并与它们更加一致。
XGBoost
XGBoost 是梯度推进方法的一个具体实现,它使用更精确的*似来寻找最佳的树模型。它采用了许多巧妙的技巧,使得它异常成功,尤其是在结构化数据方面。XGBoost 还有额外的优势:训练非常快,可以并行化/跨集群分布。因此,XGBoost 是本研究中使用的另一个模型。XGBoost 的性能如表所示(表 14)。
拟合模型:第一步,目标参数设置为线性。
下一步,进行三重交叉验证。最大深度选择为 3。因此模型保持简单。最后,将执行升压的次数设置为 50。
图 20:单决策树的 XGBoost 图
图 20 提供了该模型的不同视角。给定值(叶)的最终预测是每个分支预测的总和。另一方面,决策树可能不是为我们的数据集进行预测的稳健方式,因为它试图进行回归,但数据集有许多分类变量。除了决策树之外,特征重要性图(图 21)可以给出评估的另一个角度。通过考虑图 21,可以说里程表、制造商、年份和品牌是包含模型的重要特征。
结论
通过执行不同的模型,旨在获得不同的视角,并最终比较它们的性能。这项研究的目的是通过使用包含 13 个预测值和 380962 个观察值的数据集来预测二手车的价格。在数据可视化和探索性数据分析的帮助下,数据集被揭示,特征被深入探索。检查了特征之间的关系。在最后一个阶段,应用预测模型预测汽车价格的顺序为:随机森林、线性回归、岭回归、lasso、KNN、XGBoost。
通过考虑表 15 中的所有四个指标,可以得出结论,随机森林是预测二手车价格的最佳模型。作为回归模型的随机森林给出了最佳的 MAE、MSE 和 RMSE 值(表 14)。据 random forest 称,以下是最重要的特征:年份、里程表、品牌、驱动、燃料、制造商、气缸。这些功能仅通过使用七个列出的功能就提供了 3960.11 RMSE。
研究的局限性和进一步研究的建议
这项研究使用了不同的模型来预测二手车价格。然而,有一个相对较小的数据集来进行强有力的推断,因为观察值只有 380962。收集更多的数据可以产生更可靠的预测。其次,可能有更多的特征可以作为良好的预测指标。例如,这里有一些可能改进模型的变量:门的数量、汽油/英里(每加仑)、颜色、机械和装饰翻新时间、新旧比率、评估与交易比率。
还有一点需要改进的是,在更多技术信息的帮助下,数据清理过程可以更加严格。例如,不使用“ffill”方法,可能会有一些指标帮助更有意义地填充缺失值。
作为进一步研究的建议,在预处理数据时,可以使用一种热编码器方法,而不是使用标签编码器。因此,所有非数字特征都可以转换为名义数据,而不是序数数据(Raschka & Mirjalili,2017)。这可能会导致预测模型的性能发生重大变化。此外,在训练数据之后,代替最小-最大缩放器,可以执行标准缩放器,并且可以比较结果。可以检查不同的标度是否提高了模型的预测能力。
参考文献
IBM 知识中心。(未注明)。使用 KNN。检索自:https://www . IBM . com/support/knowledge center/SSHRBY/com . IBM . swg . im . dash db . analytics . doc/doc/r _ KNN _ usage . html
Gareth,j .,Daniela,w .,Trevor,h .,和 Tibshirani,R. (2013 年)。统计学简介
学*(第八卷)。https://doi.org/10.1016/j.peva.2007.06.006
赫维茨和马瓦拉(2012 年)。将计算智能和机器学*应用于股票市场建模时的常见错误。 arXiv 预印本 arXiv:1208.4429 。
Pal,n .,Arora,p .,Kohli,p .,Sundararaman,d .,& Palakurthy,S. S. (2018 年 4 月)。我的车值多少钱?使用随机森林预测二手车价格的方法。在信息与通信会议的未来(第 413–422 页)。斯普林格,查姆。
Raschka,s .,& Mirjalili,V. (2017 年)。 Python 机器学*。帕克特出版有限公司
基于集成分类器和自动建模的车辆事故严重度预测
原文:https://towardsdatascience.com/predicting-vehicle-accident-severity-using-ensemble-classifiers-and-automl-17ced9495932?source=collection_archive---------26-----------------------
Coursera 上 IBM 数据科学认证的顶点项目摘要
马修·T·雷德在 Unsplash 上的照片
简介/商务问题
这篇文章详细介绍了使用西雅图市交通局登记的车辆事故公开数据集的工作。这项工作通过识别导致各种类型交通事故的因素,预测事故严重程度,并利用这些信息将风险降至最低,从而使美国公众受益。
完整的代码可以在我的 GitHub repo 找到
目标
使用包括汽车和人的数量、交通、天气状况等特征,预测事故的严重程度为“1”或“2”。这是一个分类问题,一旦建模,西雅图市当局就可以获得以前无法获得的事故风险因素的洞察力,也让作者获得必要的完成以获得 Coursera 专业认证。
使用的数据和采取的步骤
所用的原始数据由西雅图交通部提供,采用了以下步骤:
步骤 1: 数据加载和初步观察
第二步:特征可视化详细分析。目标是理解潜在的利用输入变量
步骤 3: 特征工程和选择
第四步:模型拟合和训练
步骤 5 :模型评估,使用自动机器学*(也称为 AutoML)进行灵敏度检查
步骤 6 :为客户总结外卖
第 1 步和第 2 步:此处一并考虑。使用 Seaborn 可视化工具加载和分析交通数据,我们的目标是了解数据分布、属性和预测车辆事故严重程度的意义。
图 1:。describe()命令应用于数据集
Seaborn 可视化是无信息的,可以在 repo 上找到——它们没有在这里发表,因为这篇文章没有附加价值。因此,我分析了数据和一些解释性的西雅图点文献来破译特征。
我学到了什么?
许多特征是交通部使用的唯一标识符,并在预测事故时提供。这些包括事故钥匙、十字路口钥匙、碰撞细节钥匙、分隔车道钥匙和人行横道钥匙。
ObjectID 的独特之处在于,虽然它也是一个由点提供的分类器,但它不会复制在另一个特性中显式可用的信息。
有许多特征是二进制的和非数字的,即可以通过简单的是或否来回答。这些特征包括检查是否:超速是一个因素,行人有通行权,注意力不集中或酒后驾车是促成因素,或一辆停放的汽车被撞。
最后,还有其他非数字特征,它们有两个以上的可能条目。这些因素包括照明和路况、发生事故的路口类型以及事故发生的日期/时间。出于本文的目的,我将时间归类为非数字,因为它是每个 Python 的一个日期时间对象。
第三步:当考虑包括/排除什么以及可能需要什么类型的特征工程时,上面指定的列表要求一种系统的方法。我们希望确保包含有影响的因素,而不增加导致过度拟合的不必要的复杂性
哪种方法保留了最有用的信息,并删除了增加复杂性的不必要的功能?
让我们首先删除作为西雅图点管理工具的特性。这些包括报告号、事件键、交叉键和状态。我们也删除“EXCEPTRSNCODE”和“EXCEPTRSNDESC”列,在这些列中删除有条目的行,这些条目的存在只是为了通知读者某个事件缺少足够的信息。
让我们也去掉坐标 x 和 y,因为它们以一两个特定区域为中心,并被认为没有预测洞察力。
任何非数字特征都需要编码来转换成机器学*算法可以处理的数字。编码可以是顺序的,也可以是一次性的:我选择了后者,因为这些变量都没有我想要保留的固有顺序。受此方法影响的要素包括地址类型、道路和照明条件、停放的汽车是否被撞、碰撞键、天气和交叉口类型。
最后,我使用事件日期和时间提取月份和时间。时间被转换为早上、中午或晚上,随后,这个细节被一次性编码。我认为这是有意义的,因为在深夜/清晨或者季节变化使得道路更难行驶时,驾驶事故会增加
在我们继续进行模型评估之前,让我们看看上面的步骤是如何改变我们数据集中的一些关键特征的。以下是之前的快照:
图 2:显示分类、连续、字母和数字数据的原始数据集快照
这是数据集的快照,在此摘录中,我们看到地址类型被编码为超速和行人是否有通行权。这是训练数据,之前已经完成了训练-测试-分割:
图 3:带编码的原始数据快照
模型拟合和训练
完成必要的特征工程和选择后,我选择了一系列分类器——包括用于基线的虚拟分类器,训练它们,并使用许多指标评估它们在测试集上的性能。代码片段如下。
dum = DummyClassifier()
xgb = XGBClassifier()
dt = DecisionTreeClassifier()
gbc = GradientBoostingClassifier()
rfc = RandomForestClassifier()clfs = [dum,xgb,dt,gbc,rfc]
f1_Scores = []
jaccard_Scores = []
log_loss_Scores = []for clf in clfs:
clf.fit(x_train,y_train)
ypred = clf.predict(x_test)
ypred_proba = clf.predict_proba(x_test)
f1score = f1_score(y_test,ypred)
logloss = log_loss(y_test,ypred_proba)
jaccard = jaccard_score(y_test,ypred)
f1_Scores.append(f1score)
jaccard_Scores.append(jaccard)
log_loss_Scores.append(logloss)
第五步:我在下面的 Excel 表格中总结了模型性能。最佳实践建议使用多个指标来评估性能:
图 4;绩效总结
上表显示了 80 年代中期的 F1 分数和低于 0.5 的对数损失分数,这是对虚拟分类器基线性能的改进。我们将在结论中讨论上述指标对我们客户的影响,但我想先谈谈另外两个话题:
- XGBoost 上的 GridSearchCV 在上述分数上没有提供任何改进
- 我用了 TPOT 的 AutoML 软件包。请参见下面的代码片段,了解由此产生的性能:
%pip install tpot --userimport tpot
from tpot import TPOTClassifier# define model evaluation
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)
# define search
model = TPOTClassifier(generations=5, population_size=50, cv=cv, scoring='f1', verbosity=2, random_state=1, n_jobs=-1)
# perform the search
model.fit(x_train,y_train)
# export the best model
model.export('tpot_capstone_best_model.py')
然后将导出的模型重新引入数据集中进行训练,并在测试集上进行评估。正如在下面的代码片段中观察到的,TPOT 选择对性能最高的 49%的特性使用决策树分类器,结果 F1 值为 0.84,logloss 值为 0.5。 AutoML 更快,但是没有返回比传统方法更有希望的结果。
from sklearn.pipeline import make_pipeline
from tpot.export_utils import set_param_recursive
from sklearn.feature_selection import SelectPercentile, f_classifexported_pipeline = make_pipeline(
SelectPercentile(score_func=f_classif, percentile=49),
DecisionTreeClassifier(criterion="entropy", max_depth=6, min_samples_leaf=19, min_samples_split=7)
)
# Fix random state for all the steps in exported pipeline
set_param_recursive(exported_pipeline.steps, 'random_state', 1)exported_pipeline.fit(x_train, y_train)
tpot_y_pred = exported_pipeline.predict(x_test)
tpot_y_pred_prob = exported_pipeline.predict_proba(x_test)f1score = f1_score(y_test,tpot_y_pred)
logloss = log_loss(y_test,tpot_y_pred_prob)
jaccard = jaccard_score(y_test,tpot_y_pred)
第六步:我们可以给我们的客户——西雅图交通部——一个模型,展示在识别什么会导致特别严重的事故以及什么不会导致特别严重的事故方面的表现。
我们的模型比盲目猜测要好,因为 log_loss 分数 0.47 比基于类分布的“哑分数”0.59 要好。它不仅能够准确地预测严重性,而且能够区分不同的类别——通过超过基准执行者(虚拟分类器)的高 F1 分数来衡量。
西雅图交通部的见解:
- 在预测事故严重程度时,一年中的月份是第二个最有影响力的变量。某些月份天气状况不佳,司机注意力不集中,这是有道理的。西雅图市应该考虑安全计划,在一年中有问题的时候加大交通事故预防力度
- 事故中涉及的人员和车辆数量对严重程度有影响。西雅图市应考虑在一个月或一天的特定时间限制乘客乘车,以最大限度地降低风险。
- 车道钥匙和人行横道钥匙代表事件发生的区域——了解这些特定区域意味着城市可以安装更多的摄像头和更多的标志,以阻止这些特定十字路口的鲁莽行为。
- 注意力不集中的影响明显不如以上这些,但城市仍然可以影响它。西雅图市应该考虑增加对分心驾驶的罚款,并张贴更多的公益广告来阻止这种行为。
- 碰撞的类型对预测严重程度影响最大。这并不奇怪,但这本身并不可行
一如既往,我欢迎想法、建议和反馈。
预测车辆燃油效率
原文:https://towardsdatascience.com/predicting-vehicle-fuel-efficiency-c6065479a72f?source=collection_archive---------20-----------------------
比较 XGBoost(使用 GridSearchCV)和 PyTorch 神经网络来拟合回归模型,并根据汽车特征预测里程
米卡·鲍梅斯特在 Unsplash 上的照片
我的以前的帖子关注的是机器学*和神经网络在石油行业数据集中的应用。这些努力让我有信心成功地实现 XGBoost 和人工神经网络,以预测我工作的炼油厂的重大安全隐患。我非常自豪的重大成功!
为了锻炼一些通用性,我想在这个应用程序中使用 PyTorch 和 GridSearchCV,首先想在一个更简单、更小的数据集上进行实践——即来自 UCI 资源库的 Auto MPG 数据集。
和以前一样,我提出了一个分步的方法来确保系统化的应用:
第一步 =在深入建模之前了解目标和大局。
步骤 2 =加载并获得数据的高级洞察
第三步 =进一步可视化以探索数据。目标:尽早了解最具杠杆作用的特性。
第四步 =建模计划。这里的关键是为训练和测试模型准备好数据。
步骤 5 =执行建模并评估性能。根据需要完成灵敏度分析
第六步 =从工作中得出结论,让最终用户受益
下面是 GitHub repo 中的代码片段和完整代码。
第一步:我们的目标是根据各种特征预测汽车的里程。通过建模工作,我们可以了解是什么使汽车高效,以及如何实现目标里程消耗。
第二步:将输入数据读入 Python 并使用。describe(),。head()函数获取关键的统计数据和初步的数据。我还想命名列,因为这在原始数据中是不可用的。
图 1:首先看看数据,有一些高层次的见解
高级外卖:
- 数据集的变量涵盖了很大范围的数字;如果我们使用像 kNN 这样的算法,这表明需要缩放。
- 似乎我们有连续变量和离散变量的混合,其中一个是非数字的。这表明需要某种编码。
- 有 398 个条目,平均里程为 23 英里,3 个可能的来源,5 个可能的车型年。
单独的检查(此处未显示)显示数据集的“马力”特征有 6 个空值。
步骤 3a) 将相关性绘制为 Seaborn 热图
图 2:皮尔逊相关系数的 Seaborn 热图
从上面可以得出什么结论?
- 车重和排量与里程负相关最强。很好地符合直觉,大型悍马不是最有效的汽油使用者
- 马力和气缸数也与里程数呈强烈的负相关关系——这也符合快速跑车比轿车需要更多汽油的直觉
- 汽车产地和车型年份是分类数字变量,让我们用柱状图来形象化这些变量。
出于建模的目的,我将首先使用所有这些特性。然而,如果我想要一个更紧凑的特征集来防止任何潜在的过度拟合,我可以删除气缸/排量/汽车重量(给定高相关系数)。
步骤 3b) 让我们使用柱状图了解更多关于分类数字特征的信息:
图 3:汽车产地和车型年的直方图
从图 3 直方图得出的结论:原产地 1 的汽车更具代表性,这表明 mpg 结果更适合该原产地——无论原产地可能代表什么,例如制造国。我们注意到车型年份分布在 12 年中,1970、1976、1982 比其他年份更有代表性。
这些数字分类变量应该被编码吗?
图 4:汽车产地和车型年与 mpg 的柱状图
从图 4 柱状图得出的结论:mpg 随着汽车来源数量的增加而略微增加。对于车型年来说,相关性更少,但是现在,我不会对这些变量进行编码。我不介意保留这些特性。
步骤 3c) 上面的分析让我对因变量(即目标,即我们试图预测的东西)产生了好奇。这是向哪个方向倾斜的吗?下面的图 4 显示了特征的右偏度,表明我们可能想要对特征数据进行对数转换,以用于建模。
图 mpg 的直方图
步骤 4: 除了做更多的数据准备和为建模创建测试/训练集,我还将设置 GridSearch CV
4a) 输入缺失数据并创建训练和测试集。还要对汽车品牌进行编码,去掉汽车型号——因为后者是无关的细节。
**# The code below one-hot encodes car make and drops car model.**Data['car make'] = Data['car name']
Data['car make'] = Data['car name'].apply(lambda x: x.split()[0])Data.drop(columns=['car name'],inplace=True)Data = pd.get_dummies(Data,columns=['car make'])**# Next: creating x and y below**x_no_log = Data.drop(columns=['mpg'])
y_no_log = Data['mpg']**# Imputing missing car horsepower values.**imp = SimpleImputer(missing_values=np.nan,strategy='median')
x_no_log['horsepower'] = imp.fit(x_no_log['horsepower'].values.reshape(-1, 1)).transform(x_no_log['horsepower'].values.reshape(-1, 1))
4b) 设置 GridSearchCV——这允许我们循环遍历超参数,根据所选评分指标(在我的例子中为均方差)找到最佳组合。GitHub repo 对 RandomForest 进行了类似的操作。
xgb_params = {'nthread':[4],
'learning_rate': [.03, 0.05, .07],
'max_depth': [5, 6, 7],
'min_child_weight': [4],
'subsample': [0.7],
'colsample_bytree': [0.7],
'n_estimators': [500,1000]}
4c) 设置 PyTorch —下面的代码导入必要的包,用输入维度、隐层节点数和输出节点设置神经网络,然后构建模型。
我还将均方误差声明为优化的损失度量,我将在测试集上评估 XGBoost 和 RandomForest 的性能时使用相同的度量。
最后,设置 Adam 优化算法来操纵梯度下降函数,如下图 6 所示。
图 6:使用 PyTorch 的代码摘录
5) 所有设置完成后,是时候实际运行模型并评估结果了。
5a) 我将首先使用 GridCV 和之前设置的超参数网格,根据训练集中的性能找到性能最佳的 XGBoost 模型(GitHub repo 中对 RandomForest 进行了类似的练*)。
然后,我将训练创建的 PyTorch 神经网络
gsXGB = GridSearchCV(xgbr, xgb_params, cv = 7, scoring='neg_mean_squared_error',
refit=True, n_jobs = 5, verbose=True)
gsXGB.fit(xtrain,ytrain)XGB_best = gsXGB.best_estimator_train_error = []
iters = 600Y_train_t = torch.FloatTensor(ytrain.values).reshape(-1,1) #Converting numpy array to torch tensorfor i in range(iters):
X_train_t = torch.FloatTensor(xtrain.values) ***#Converting numpy array to torch tensor***
y_hat = torch_model(X_train_t)
loss = loss_func(y_hat, Y_train_t)
loss.backward()
optimizer.step()
optimizer.zero_grad()
5c) 模型训练完成后,我现在可以根据测试数据评估性能了。
**# Evaluating best-performing XGBoost model on testing data** ypred = XGB_best.predict(xtest)
explained_variance_score(ytest,ypred)
mean_absolute_error(ytest,ypred)
mean_squared_error(ytest,ypred,squared=True)**# Evaluating PyTorch model on testing data**
X_test_t = torch.FloatTensor(xtest.values) ***#Converting numpy array to Torch Tensor.***
ypredict = torch_model(X_test_t)
mean_squared_error(ytest,ypredict.detach().numpy(),squared=True)
通过超参数调整得到的 XGBoost 模型的均方误差为 0.0117 mpg。给定原始数据集中 23.5 mpg 的平均值,这可以解释为99.9%的准确度
PyTorch 神经网络的均方误差为 0.107 mpg 。使用上述方法,这可以转化为 99.5%的准确度。
我们为客户完成了什么?我们有一个模型可以预测各种汽车的燃料里程;我们的客户可以利用这一点来规划达到理想燃油效率水平的汽车。
此外,我们还可以告知我们的客户——根据下图 7——体重是预测里程数的最有影响力的变量,其次是加速度。马力、排量、加速度在影响上比较接*。
图 7:预测里程的特征重要性
有了这些细节,我们的客户可以计划未来的汽车生产或购买计划。
一如既往,我欢迎任何反馈。
用 XGBRegressor 预测每周酒店取消预订
原文:https://towardsdatascience.com/predicting-weekly-hotel-cancellations-with-xgbregressor-d73eb74a8624?source=collection_archive---------29-----------------------
基于 xgb 回归的时间序列预测
来源:照片由 Yuri_B 从 Pixabay 拍摄
XGBoost 最常用于基于分类或回归的问题,其中将特征合并到模型中以预测感兴趣的结果。
也就是说,XGBoost 也可以用于时间序列预测。这是通过使用感兴趣的时间序列的滞后作为模型中的独立特征来实现的。让我们看看如何使用 XGBRegressor 来帮助我们预测酒店取消预订。
数据处理
以下分析基于来自 Antonio、Almeida 和 Nunes (2019)的数据:酒店预订需求数据集。
使用 XGBoost 构建时间序列预测模型的目的是让酒店能够预测每周酒店取消预订的数量。
来源:Jupyter 笔记本输出
数据首先被分成训练和验证分区:
train_size = int(len(df) * 0.8)
val_size = len(df) - train_size
train, val = df[0:train_size,:], df[train_size:len(df),:]
假设我们正在使用一个基于树的模型,在这个例子中,这些特性没有使用 MinMaxScaler 进行规范化。
形成数据集矩阵:
def create_dataset(df, previous=1):
dataX, dataY = [], []
for i in range(len(df)-previous-1):
a = df[i:(i+previous), 0]
dataX.append(a)
dataY.append(df[i + previous, 0])
return np.array(dataX), np.array(dataY)
然后为模型定义一个回望期,也就是说,当预测向前一步时,我们希望模型“回望”多少时间步?
首先,将使用一个 5 的回看周期。根据 RMSE(均方根误差)测量的精度,可以适当地修改回望周期。
lookback = 5
X_train, Y_train = create_dataset(train, lookback)
X_val, Y_val = create_dataset(val, lookback)
以下是 X_train 输出的示例:
array([[ 41., 48., 87., 74., 101.],
[ 48., 87., 74., 101., 68.],
[ 87., 74., 101., 68., 96.],
[ 74., 101., 68., 96., 69.],
[101., 68., 96., 69., 88.]
...
[111., 70., 39., 59., 74.],
[ 70., 39., 59., 74., 57.],
[ 39., 59., 74., 57., 36.]])
XGBRegressor
XGBRegressor 模型定义如下:
from xgboost import XGBRegressormodel = XGBRegressor(objective='reg:squarederror', n_estimators=1000)
model.fit(X_train, Y_train)
以下是定义的模型参数:
来源:Jupyter 笔记本输出
从上面我们可以看到,在训练 XGBRegressor 时,有许多模型参数可以修改。但是,在这种情况下,n_estimators 被设置为 1000。这定义了 XGBoost 模型中树的数量。目标设置为‘reg:squarederror’,即平方损失回归,对极值误差的惩罚更重。
该模型跨训练集和验证集进行训练:
>>> trainpred = model.predict(X_train)
>>> trainpredarray([ 68.00038 , 95.99979 , 69.00168 , 88.00018 , 147.99892 ,
76.000656, 185.99991 , 122.999306, 91.00025 , 197.99966 ,
...
128.99901 , 111.99981 , 118.00009 , 85.00055 , 181.99738 ,
133.9994 , 111.001526, 70.00158 , 39.0001 , 58.99967 ,
74.00109 , 56.999626, 36.001102, 84.00235 ], dtype=float32)>>> valpred = model.predict(X_val)
>>> valpredarray([ 19.767576, 62.593506, 80.718994, 60.782364, 129.0691 ,
112.3979 , 113.64816 , 91.60748 , 105.40695 , 62.221115,
109.42688 , 126.32669 , 94.05386 , 62.81558 ], dtype=float32)
训练集和验证集(预测集和实际集)会相应地进行调整:
>>> Y_train=Y_train.reshape(-1,1)
>>> trainpred=trainpred.reshape(-1,1)>>> Y_val=Y_val.reshape(-1,1)
>>> valpred=valpred.reshape(-1,1)
结果
现在,在 RMSE(均方根误差)的基础上,将预测值与实际抵消值进行比较。
>>> train_mse = mean_squared_error(Y_train, trainpred)
>>> rmse = sqrt(train_mse)
>>> print('RMSE: %f' % rmse)RMSE: 0.000887>>> val_mse = mean_squared_error(Y_val, valpred)
>>> rmse = sqrt(val_mse)
>>> print('RMSE: %f' % rmse)RMSE: 50.142536
在验证集(Y_val)上平均每周有 109 个取消,RMSE 在验证集上达到 50.14。
我们看到,训练集的 RMSE 几乎为 0,但这并不被视为模型性能的基准。毕竟,预测模型已经训练过的数据是一项毫无意义的工作。
这些发现与 LSTM 相比如何?
还使用 5 的回望周期对上述数据运行了 LSTM 模型。
model = tf.keras.Sequential()
model.add(LSTM(4, input_shape=(1, lookback)))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
history=model.fit(X_train, Y_train, validation_split=0.2, epochs=20, batch_size=1, verbose=2)
得到的 RMSE 如下:
>>> mse = mean_squared_error(Y_val, predictions)
>>> rmse = sqrt(mse)
>>> print('RMSE: %f' % rmse)RMSE: 36.792552
在这方面,当使用 LSTM 模型时,RMSE 低于 XGBoost,这表明 LSTM 在预测每周酒店取消方面做得稍好。然而,XGBoost 在预测每周取消时仍然表现出相当好的性能。
人们应该注意到,RMSE 对更极端值的错误惩罚更重。例如,如果某一周的取消量碰巧比正常情况高得多,而模型预测明显低估了这一点,那么这将导致更高的 RMSE。
作为参考,当使用 XGBRegressor 时,平均绝对误差在 38 处略低,表明该模型在预测不太极端的值时表现更好。
结论
在本例中,我们看到:
- 如何使用 XGBRegressor 预测时间序列
- 准备数据以使用 XGBoost 模型
- 测量模型精度的方法
非常感谢您的宝贵时间,非常感谢您的任何问题或反馈。
你可以在这里找到这个例子的 Jupyter 笔记本。
此外,我强烈推荐下面的机器学*掌握教程,以进一步了解 XGBRegressor 的使用。
免责声明:本文是在“原样”的基础上编写的,没有任何担保。本文旨在提供数据科学概念的概述,不应被解释为任何形式的专业建议。作者与本文提及的任何第三方无任何关系。
利用机器学*预测《权力的游戏》中谁会死
原文:https://towardsdatascience.com/predicting-who-will-die-in-game-of-thrones-using-machine-learning-6c41c0ba897e?source=collection_archive---------52-----------------------
来自 Pixabay 的 SilentPilot 摄影
“我们该对死神说什么?”
HBO 的《权力的游戏》中的死亡显然是不可预测的。角色死于被龙刺穿、斩首、爆炸,甚至烧烤。但是这些死亡有多不可预测呢?
这篇文章将着眼于使用书中的数据预测《权力的游戏》中的死亡,使用从一个冰与火的维基中搜集的数据。也可以在 Kaggle 上找到数据。
导入库
第一件事是导入我们将使用的所有 Python 和 Scikit-learn 库。 Plotly 是一个构建交互式可视化的伟大工具。
探索数据
该数据有 1946 行和 39 列。首先,让我们看看有百分之多少的人物是活着的。
我们看到将* 75%的角色都活着。还有哪些因素会影响死亡率?再来看性别。
看起来雄性比雌性更容易被杀死。
接下来让我们看看最危险的房子,通过除以房子的大小来计算房子的死亡率。
人物死亡最多的房屋(或群体)是:
- 未知(332)
- 豪斯·弗雷(83)
- 守夜人(60)
- 史塔克家族(50)
一个角色不在书里却在剧里怎么办?它们的存在是为了最终被杀死吗?让我们检查一下这个假设。
只显示角色有大约 20%的几率死亡!
既然我们已经知道了哪些因素可能会增加某人的死亡几率,那么让我们开始清理数据吧。
清理数据
让我们检查一下其他的数字变量。年龄和出生日期是相关的,所以绘制它们应该显示相同的趋势。
看起来有两个字符的年龄为负,这也导致了出生日期列中的异常值。我们将不得不手动修复这些异常值。
这些情节现在没有异常值,但是有几个角色缺少年龄和生日。
让我们用它们的中间值来估算两者。
对于分类变量,让我们用字符串“未知”来估算缺失值
检查空值表明我们不再有任何丢失的值:
机器学*模型
首先让我们得到与活着高度相关的列。
您可以随意更改该阈值,但是在这种情况下,使用 0.2 左右的阈值可以获得最佳结果。
让我们定义一个仅由这些列以及目标列组成的新数据帧。
接下来,我们将把数据集分成 80%用于训练,20%用于测试。
逻辑回归
这种分类器通常用于只有两个类值(在我们的例子中是活的或不活的)的二元分类问题。它将输出一组基于概率的类。
Logistic 回归给出了一个:
- 模型得分为 0.9615
- 训练得分 0.9615
- 测试分数为 0.9524
决策图表
决策树在一个标准(如男性或女性)上创建分裂点,因此每个分支导致一个实例的分类。
决策树分类器给出了:
- 训练得分为 1 分(哦,可能过度适应)
- 测试得分为 0.9282
随机搜索
随机化和网格搜索通过尝试固定数量的设置来优化分类器的超参数。用于预测的参数也通过交叉验证进行优化。
得到的一些最佳随机森林参数是:
- n _ 估计数:600(数字估计数)
- min_samples_split: 4(每次分割的最小样本数)
- max_depth: 6=50(树的最大深度)
随机森林
现在我们有了最佳超参数,我们可以比较基尼和熵随机森林模型。首先,我们来试试基尼。
基尼给出:
- 训练得分 0.9647
- 测试得分为 0.9564
- AUC 分数为 0.9373
将标准改为“熵”给出:
- 训练得分 0.9647
- 测试得分为 0.9564
- AUC 分数为 0.9363
测试精度是相同的,所以现在让我们用基尼。
什么特征最重要?
不出所料,来自危房增加了某人死亡的风险。增加风险的其他因素有:
- 一个只表演的角色
- 男性的
- 流行的
- 年长的
- 在第一册和/或第四册中
- 从一个大房子
结论
我们可以通过流行度排序来检查最重要的模型结果。
模型结果,按受欢迎程度百分比排序
我们看到,模型 正确地 预测了(剧透提前)认为:
- 罗柏·史塔克会死的
- 玛格丽·提利尔会死
- 伊里斯·坦格利安(疯狂的国王)会死
- 史坦尼斯·拜拉席恩会死的
- 山姆威尔·塔利会活下来
模型错误地预测到:
- 托曼·拜拉席恩会活下来
- 乔佛里·拜拉席恩会活下来
- 瓦德·佛雷会活下来
为了排序,我们可以根据测试精度对我们使用的模型进行如下排序:
- 优化随机森林(Gini): 95.64%
- 基线随机森林(基尼系数):95.13%
- 基线随机森林(熵):94.36%
- 逻辑回归分析:95.24%
- 决策树分类器:92.82%
使用 Gini 作为我们的最终模型,我们得到的最终测试精度为 0.9564。
这个模型只准确到第六季左右,之后有许多写作的变化,这部剧已经走上了不同于原著的时间线。
你怎么看待人物死亡的风险因素?
用几种分类技术预测葡萄酒质量
原文:https://towardsdatascience.com/predicting-wine-quality-with-several-classification-techniques-179038ea6434?source=collection_archive---------0-----------------------
带代码的数据科学项目演练!
图片由来自 Pixabay 的 Aline Ponce 拍摄
请务必点击 订阅此处 或我的 个人简讯 千万不要错过另一篇关于数据科学指南、技巧和提示、生活经验等的文章!
目录
- 简介
- 设置
- 探索变量
- 转化为分类问题
- 准备建模数据
- 造型
- 功能重要性
介绍
随着隔离的继续,我有了一些爱好和兴趣…包括葡萄酒。最*,我喜欢上了葡萄酒,尽管我并不知道什么是好酒。因此,我决定应用一些机器学*模型来弄清楚是什么造就了优质的葡萄酒!
对于这个项目,我使用了 Kaggle 的红酒质量数据集来建立各种分类模型,以预测某一特定红酒是否“质量好”。该数据集中的每种葡萄酒都被赋予 0 到 10 之间的“质量”分数。出于这个项目的目的,我将输出转换为二进制输出,其中每种葡萄酒要么是“优质”(7 分或更高),要么不是(低于 7 分)。葡萄酒的质量由 11 个输入变量决定:
- 固定酸度
- 挥发性酸度
- 柠檬酸
- 残糖
- 氯化物
- 游离二氧化硫
- 二氧化硫总量
- 密度
- pH 值
- 硫酸盐化
- 酒精
目标
该项目的目标如下
- 尝试不同的分类方法,看看哪种分类方法的准确度最高
- 确定哪些特征最能代表优质葡萄酒
说到这里,我们开始吧!
请务必在此 订阅 或我的 个人简讯 千万不要错过另一篇关于数据科学指南、技巧和提示、生活经验等的文章!
设置
首先,我导入了我将使用的所有相关库以及数据本身。
导入库
import numpy as np
import pandas as pd
import matplotlib as plt
import seaborn as sns
import plotly.express as px
读取数据
df = pd.read_csv("../input/red-wine-quality-cortez-et-al-2009/winequality-red.csv")
理解数据
接下来,我想更好地了解我在做什么。
# See the number of rows and columns
print("Rows, columns: " + str(df.shape))# See the first five rows of the dataset
df.head()
总共有 1599 行和 12 列。通过查看前五行,数据看起来非常干净,但是我仍然想确保没有丢失值。
缺少值
# Missing Values
print(df.isna().sum())
这是一个非常适合初学者的数据集。我不需要处理任何丢失的值,而且在给定这些变量的情况下,也没有太多的灵活性来进行一些特性工程。接下来,我想进一步探索我的数据。
探索变量
“质量”变量直方图
首先,我想看看质量变量的分布。我想确保我的数据集中有足够多的“优质”葡萄酒——稍后你会看到我是如何定义“优质”的。
fig = px.histogram(df,x='quality')
fig.show()
相关矩阵
接下来,我想看看我正在处理的变量之间的相关性。这让我可以很快更好地理解变量之间的关系。
我立即发现了一些与质量密切相关的变量。很可能这些变量也是我们的机器学*模型中最重要的特征,但我们稍后再看。
corr = df.corr()
matplotlib.pyplot.subplots(figsize=(15,10))
sns.heatmap(corr, xticklabels=corr.columns, yticklabels=corr.columns, annot=True, cmap=sns.diverging_palette(220, 20, as_cmap=True))
请务必 订阅此处 或我的 个人简讯 千万不要错过另一篇关于数据科学指南、技巧和提示、生活经验等的文章!
转化为分类问题
回到我的目标,我想比较不同分类技术的有效性,所以我需要将输出变量改为二进制输出。
对于这个问题,我将一瓶葡萄酒定义为质量分数为 7 分或更高的为“质量好”,如果分数低于 7 分,则视为“质量差”。
一旦我将输出变量转换成二进制输出,我就将我的特征变量(X)和目标变量(y)分离成单独的数据帧。
# Create Classification version of target variable
df['goodquality'] = [1 if x >= 7 else 0 for x in df['quality']]# Separate feature variables and target variable
X = df.drop(['quality','goodquality'], axis = 1)
y = df['goodquality']
好酒与劣酒的比例
我想确保有合理数量的优质葡萄酒。根据下面的结果,这似乎是一个公平的数字。在某些应用中,如果数据极度不平衡,可能需要重新采样,但我认为这样做没问题。
# See proportion of good vs bad wines
df['goodquality'].value_counts()
为建模准备数据
标准化特征变量
在这一点上,我觉得我已经准备好了建模的数据。我做的第一件事是标准化数据。标准化数据意味着它将转换数据,使其分布的平均值为 0,标准差为 1。为了均衡数据范围,标准化数据非常重要。
例如,假设数据集有两个输入要素:以毫米为单位的身高和以磅为单位的体重。因为“身高”的值由于其测量而要高得多,所以更强调身高而不是体重,这就产生了偏见。
# Normalize feature variables
from sklearn.preprocessing import StandardScaler
X_features = X
X = StandardScaler().fit_transform(X)
分割数据
接下来,我将数据分成训练集和测试集,这样我就可以交叉验证我的模型,并确定它们的有效性。
# Splitting the data
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.25, random_state=0)
现在,有趣的部分来了!
系统模型化
对于这个项目,我想比较五种不同的机器学*模型:决策树、随机森林、AdaBoost、Gradient Boost 和 XGBoost。为了这个项目的目的,我想比较这些模型的准确性。
模型 1:决策树
作者创建的图像
决策树是一种流行的模型,用于运筹学、战略规划和机器学*。上面的每个方块称为一个节点,节点越多,你的决策树就越精确(一般来说)。决策树的最后节点,也就是做出决策的地方,被称为树的叶子。决策树直观且易于构建,但在准确性方面有所欠缺。
from sklearn.metrics import classification_report
from sklearn.tree import DecisionTreeClassifiermodel1 = DecisionTreeClassifier(random_state=1)
model1.fit(X_train, y_train)
y_pred1 = model1.predict(X_test)print(classification_report(y_test, y_pred1))
模型 2:随机森林
随机森林是一种基于决策树的集成学*技术。随机森林包括使用原始数据的自举数据集创建多个决策树,并在决策树的每一步随机选择一个变量子集。然后,该模型选择每个决策树的所有预测的模式。这有什么意义?依靠“多数获胜”模型,它降低了单个树出错的风险。
作者创建的图像
例如,如果我们创建一个决策树,第三个,它会预测 0。但是如果我们依赖所有 4 个决策树的模式,预测值将是 1。这就是随机森林的力量。
from sklearn.ensemble import RandomForestClassifier
model2 = RandomForestClassifier(random_state=1)
model2.fit(X_train, y_train)
y_pred2 = model2.predict(X_test)print(classification_report(y_test, y_pred2))
模型 3: AdaBoost
接下来的三个模型是提升算法,将弱学*者转化为强学*者。我不想跑题,解释三者之间的区别,因为这是相当复杂和错综复杂的。也就是说,我将留下一些资源,您可以从中了解 AdaBoost、渐变增强和 XGBoosting。
- StatQuest: AdaBoost
- StatQuest:梯度推进
- StatQuest: XGBoost
from sklearn.ensemble import AdaBoostClassifier
model3 = AdaBoostClassifier(random_state=1)
model3.fit(X_train, y_train)
y_pred3 = model3.predict(X_test)print(classification_report(y_test, y_pred3))
模型 4:梯度推进
from sklearn.ensemble import GradientBoostingClassifier
model4 = GradientBoostingClassifier(random_state=1)
model4.fit(X_train, y_train)
y_pred4 = model4.predict(X_test)print(classification_report(y_test, y_pred4))
模型 5: XGBoost
import xgboost as xgb
model5 = xgb.XGBClassifier(random_state=1)
model5.fit(X_train, y_train)
y_pred5 = model5.predict(X_test)print(classification_report(y_test, y_pred5))
通过比较这五个模型,random forest 和 XGBoost 似乎产生了最高级别的准确性。然而,由于 XGBoost 在预测优质葡萄酒方面有更好的 f1 分数(1),我的结论是 XGBoost 是五个模型中的赢家。
特征重要性
下面,我根据随机森林模型和 XGBoost 模型绘制了特性的重要性。虽然它们略有不同,但前三个特征是相同的:酒精、挥发性酸度和硫酸盐。如果你看下面的图表,我把数据集分成质量好的和质量差的两类,以便更详细地比较这些变量。
通过随机森林
feat_importances = pd.Series(model2.feature_importances_, index=X_features.columns)
feat_importances.nlargest(25).plot(kind='barh',figsize=(10,10))
通过 XGBoost
feat_importances = pd.Series(model5.feature_importances_, index=X_features.columns)
feat_importances.nlargest(25).plot(kind='barh',figsize=(10,10))
比较四大特征
# Filtering df for only good quality
df_temp = df[df['goodquality']==1]
df_temp.describe()# Filtering df for only bad quality
df_temp2 = df[df['goodquality']==0]
df_temp2.describe()
好品质
劣等质量
通过观察细节,我们可以看到,优质葡萄酒的平均酒精含量较高,平均挥发性酸度较低,平均硫酸盐含量较高,平均残糖含量较高。
感谢阅读!
如果你喜欢我的工作并想支持我,我会非常感谢你在我的社交媒体频道上关注我:
- 支持我的最好方式是在媒体T10【这里上关注我。
- 在推特关注我这里。
- 点击这里订阅我的新 YouTube 频道 。
- 在 LinkedIn 上关注我这里。
- 在我的邮箱列表 这里报名。
- 查看我的网站terenceshin.com。
预测于达维什投球不砸垃圾桶
原文:https://towardsdatascience.com/predicting-yu-darvishs-pitching-without-hitting-the-trash-can-779903507faa?source=collection_archive---------75-----------------------
使用机器学*来猜测他的下一个投球
作者图片
介绍
据报道,一桩丑闻震惊了棒球界,太空人队在 2017 赛季期间使用电子设备窃取了对方球队的标志,包括世界职业棒球大赛,最终他们赢得了冠军。俞达维是受害者之一。他有一个稳定的常规赛,他在季后赛早期为狗队投得非常好。然而,在世界系列赛对阵太空人的比赛中,事情发生了变化。他在两场比赛的 3.1 局中失了 9 分,包括第七场比赛,当时他在 1.2 局中投了 47 球,失了 5 分,为太空人队赢得了最后的胜利。球迷责怪他,赛季结束后他被交易到小熊队。
两年后,太空人用相机偷了他的投球手势,并在比赛期间敲垃圾桶暗示击球手。所以基本上击球手知道达维什要投什么球,这可能是他在世界大赛中比其他球队表现差的原因。(背景故事:https://www . the ringer . com/MLB/2020/3/9/21170990/astros-sign-stealing-dodgers-world-series-Yu-darvish-Clayton-kershaw)
我很好奇有没有必要用摄像头非法盗签,有没有可能根据他的投球历史推断出他的投球?
在这次调查中,我想回答以下问题:
1 .他最擅长投哪种类型的球?
2。当他需要好球时,他投的是什么类型的球?(二击三球情况)
3。他在不同的情况下有不同的投球策略吗(0 打 0 球,2 打 3 球…,出局,一局等)。
4。有没有可能根据他的投球历史训练一个机器学*模型来预测他的投球?
探索性数据分析
资料组
用于分析的数据集包含 8221 个来自于 Darvish 的音高。数据是从 https://baseballsavant.mlb.com/下载,并为调查争论不休。
另一个数据集包含他的 2017 年季后赛数据,用来测试模型。
音调击穿
图 1 他的音高变化。
他口袋里有很多武器,总共 9 种音高类型。他投出 33.3%的 4 缝线和 15.8%的 2 缝线快速球,21.1%的切球和 20%的滑球。他使用他的曲球,手指分开,变速球,指节曲线和低于 10%的 ephus。
现在让我们来分析他在不同比赛条件下的投球。
罢工
图 2 不同打击条件下他的音高变化。
当没有好球时,他增加他的四缝线快速球百分比,当有两个好球时,他增加他的滑球。他似乎也增加了 2 击时的破发率
球
图 3 他在不同球况下的投球分解。
除了 3 球以外,在不同球况下没有非常明显的差异。他倾向于使用四缝线快速球,避免使用弧线球、指叉球和变速球。
在外
出局怎么样?他投球不同吗?
图 4 他在不同出局数的音高变化。
嗯,不太清楚是否有显著差异。
让我们把好球和出局结合起来。
图 5 他在不同击球、球和界外球时的投球情况。
该图对不同的条件进行了更深入的探究。比如他在面对 2 击 0 球的时候,还是倾向于投 4 缝快球,但是球多了,他就增加了他的滑球百分比。
这个数字可能是有用的参考,但是,它只考虑了三个特点,罢工,球和出局。让我们尝试建立一个机器模型,以包括用于预测的其他特征。
机器学*模型
在特征工程之后,我加入了之前投球的结果,以及每场比赛的投球数。结合数据集中的一些原始特征,我对模型使用了以下特征,并对分类变量进行了一次性编码。
str_list=['stand', 'pre_description','pre_pitch']
num_list=['balls','strikes','outs_when_up','inning',
'home_away', 'score', 'other_score', 'score_diff',
'pre_speed','pre_hd', 'pre_l_s', 'pre_l_a','on_3b', 'on_2b','on_1b','p_count']
2017 年季后赛的结果将用于测试模型,因此我用一个天真的猜测建立了一个基线。我选择他在训练数据集中投得最多的 4 缝线快速球作为测试数据集的预测,并与实际投球进行比较。我得到了 27.16%的准确率。
结果
我建立了一个随机森林模型来预测结果,没有太多的调整,通过交叉验证,我得到了 36.20 +/- 5%的准确率,在测试数据集上的准确率为 37.31%。
随机森林预测的混淆矩阵。
基于混淆矩阵,模型误预测了很多滑球到 4 缝线快速球。尽管这个数字看起来很低,但仍然比一个天真的猜测高出 30%。
结论
随机森林模型提供了比天真猜测(27%)更好的预测(37%),但是仍然不能完美地预测他的音高。我认为仍有改进的空间,例如,更好的特征工程,或包括特定击球手的投球历史。但我认为不可预测的球场是他成为伟大球员的原因之一。而棒球的不可预测性真的是棒球比赛的乐趣所在。
新冠肺炎数据的预测和分析:模型—建议算法 Vuong 模拟器
原文:https://towardsdatascience.com/prediction-and-analysis-of-covid-19-data-model-proposal-algorithm-vuong-simulator-2b05d1bded7e?source=collection_archive---------56-----------------------
数据科学—新冠肺炎—可视化—编程
照片由 Thuy Chung Vuong 拍摄
如何发现未被发现的新冠肺炎感染病例?
编者按: 走向数据科学 是一份以数据科学和机器学*研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
为了加入对抗新冠肺炎·疫情的战斗,我做了我个人的数据预测研究,并根据我在数据处理和电子学方面的经验进行了分析。由于我的资源有限,我当然只能使用我的 Surface 笔记本电脑、我的 Raspberry PI 和开源社区的软件,但我想报告一个新的结果:一种用于估计未发现感染的算法,使用我的“新冠肺炎数据分析的 Vuong 模型”,其实现的软件可以在这里下载。
新冠肺炎数据分析中的一个重要且具有挑战性的研究目标是寻找未发现的感染病例数。字),因为病毒的传播,新型冠状病毒是非常复杂和未知的。在冠状病毒潜伏期(从接触到出现症状的时间)之后,病毒可能会从一个人传播到另一个人。有报道称,一个无症状(无症状)的人可以将新型冠状病毒病毒传播给另一个人(例如“全球范围内感染冠状病毒的巨大无症状库”)。冠状病毒患者在明显康复后可能会再次感染该病毒(最新好消息"新数据表明人们不会再次感染冠状病毒,2020 年 5 月 19 日)
SIR 模型
已经有许多数据模型用于分析和模拟新冠肺炎疫情来计算感染病例数。一个已知的非线性模型是 SIR 模型[ker Mack-McKendrick 理论,1927,1928,1932]: S 为易感人数, I 为传染人数, R 为痊愈或死亡(或免疫)人数。r 也可称为“抗”或“除”。
从真实数据,即当前每天新增的感染病例(新病例)中,使用 SIR 模型的微分方程来优化 SIR 模型的函数 I (t)的参数“β”和“γ”,从而可以找到 I(t)的每个时间点的感染人数(见图 1)。
- β“β”是感染易感人群的比率。
- γ“γ”是感染者变得有抵抗力的比率。
您可以找到许多 SIR 模型可视化的软件包,例如[mattravenhall/BasicSIRModel]和优化β率和γ率以找到 I(t),用于估计感染人数。,如 Brian Collins,新冠肺炎的动态建模。
图一。优化β率和γ率以找到 I(t),用于估计感染人数
SIR 模型的优化有一些批评点:
- 该模型只有两个参数β和γ率,这可能不足以模拟新冠肺炎疫情。
- 医学和病毒学家还没有发现很多其他的参数。
- SIR 模型作为一个封闭系统被采用。假设 N = S + I + R 随时间保持不变。在现实世界中,我们有一个开放的系统,随着时间的推移,N 不是常数,因为人们在移动,病毒可能通过空气传播。
因此也有[ 詹姆士·扬松、新冠肺炎造型不对的评论
图 2 新冠肺炎数据分析对 CODVID-19 数据预测分析的 Vuong 模型。
新冠肺炎数据分析的 VUONG 模型
因此,我想报告我的建议模型:用于新冠肺炎数据分析的 Vuong 模型,以预测和分析 CODVID-19 数据。
新冠肺炎数据函数中的时间值 t 是日期和时间(参见 Python 文档:“日期时间模块”)。因此它们是离散值,所以函数 y (t)是一个“时间序列”。我在这里用 y[x]代替 y (t ),因此 x 是日期时间。这使得以后的编程和绘图更加容易。
我们现在开始描述用于新冠肺炎数据分析的 Vuong 模型(见图 2)。
输入:
- nc[x] 是每日确诊感染病例数,即“新增病例”。
- nd[x] 为每日死亡人数。
产出:
- I[x] 是每日感染病例的估计数。
- G[x] 是每日恢复病例的估计数(germ。Gesund Fä lle)。
参数表将会很长,并且仍然是未知的。这里只列出了重要的已知参数:
- 数据信息的本地标识,例如德国、美国的数据。
- 潜伏期。
- 恢复期。
- 社交和物理距离
- 等等。
在 Vuong 模型中,我实现了两个参数:潜伏期和恢复期
估计感染病例的概念有 3 个步骤:
第一步
从每日新感染病例 nc[x]中,我们将计算预测函数 Ip [x]。Ip[x]是包括未发现感染者在内的感染者人数。与 SIR 模型优化相比,我使用了一个额外的参数——潜伏期τ。
Ip [x] = nc [x,Tau]
Tau:潜伏期。潜伏期过后,病毒会传染给另一个人。潜伏期估计在 2-14 天之间。
第二步:
恢复函数 G [x]已根据步骤 1 中的 Ip[x]、ndx和 RG 参数计算得出:
G [x] = g [Ip [x],nd [x],RG)
RG 是恢复期,不是 R 系数。RG 是一个感染者痊愈的时间。对于轻度病例,RG 可能是 14 天,对于严重病例,大约是 30 天(冠状病毒:需要多长时间才能恢复?、BBC 新闻)
第三步:
根据预测函数 Ip[x]的数量计算最终估计的每日感染病例数,预测函数 Ip[x]已从步骤 1 中导出,并排除了来自步骤 2 的恢复估计病例。
I [x] = Ip [x] — G [x]
现在让我们来看看细节吧!
Vuong 算法在新冠肺炎数据预测中的应用
传染病例数的预测 Ip[x]:
预测函数 Ip [x]取决于 ncx和潜伏期τ。
对于每个 Ip [x],都有一个 r[x-1],即复制因子。这意味着在时间点 x 的感染病例数 Ip [x]是在前一时间点 x-1 的病例数 nc[x-1]的 r[x-1]倍。
例如:在时间 x-1,有 100 个感染病例(Ip[x-1] = 100),生殖因子将是 5 倍(r[x-1] = 5),那么第二天将有 500 个感染病例(Ip [x] = 500)。
Ip [x] = r [x-1] * Ip [x-1] (1)
r[x-1]:Ip[x]的再现因子。
从(1)中,可以计算出:
Ip[x-1]= r[x-2] r[x-3]… r[x-1-n]…。 r [x-N] Ip [x-1-N ]* (2)
n = 0,…,N,N 是用于计算的 Ip 值的数量
假设:所有 r[x-1-n]在时间间隔 N 中是相同的
Ip [x-1] = (R ** N)。Ip [x-1-N] (3)
R**N: R 指数 N
根据新冠肺炎的信息,我们知道在潜伏期τ之后,一个人可以将他的病毒传染给另一个人。
可以说 Ip[x-1-N]患者在潜伏期后会将病毒传染给其他人。这意味着 R 在时间点 x-1-N-τ之前不会激活。接下来是:
R * Ip[x-1]=(R * (N-Tau)) Ip[x-1-N](4)
(N-Tau-1)log R = log(Ip[x])—log(Ip[x-1-N](5)
对于 Ip [x]的估计,我们只需从时间间隔{x / x= x-1,…中取 2 个数 nc[x-1]和 nc[x-1-N]。x-1-N}
然后我们从 log R 计算 R
log R =(log(NC[x])—log(NC[x-1-N])/(N-Tau-1)(6)
R = 10 ** log R
R 是繁殖因子。
然后估计感染病例数 Ip[x]:
Ip [x] = R * nc[x-1] (7)
编程概念:
Vuong 算法已经在 tavuong_simulator.py 中实现
对于实际编程,我们在 x 轴 x = 0 上运行长度为 N 的“窗口”,开始时间为[x-1],结束时间为[x-1-N]。..在等式(5)中,我们只需要 2 个值 nc[x-1]和 nc[x1-N]。但是,这些值可以是 0(零)。因此我们必须添加额外的规则来避免 log (0)的计算:
计算 Ip 和 R 在两个场的两个向量中,Ip [x]和 R [x]
nc[x]的前 N 个值用作被调用 Ip [x]的起始值。
Ip [x] = nc [x],对于 x = 0… N-1
后 x > N:
如果 nc [x] = 0 且 nc [x-1-N]!= 0,即在过去有过感染,我们取 R [x] = R [x-1]
如果 nc [x] = 0 且 nc [x-1-N] = 0,即 nc [x]中有感染,我们取 R [x] = 0
如果 nc [x]!= 0 和 nc [x-1-N]!= 0,即过去有感染,我们取 R [x] =计算值(s .等式(6))
如果 nc [x]!= 0 且 nc [x-1-N] = 0,即在过去有感染,我们取 R [x] = R [x-1]
恢复功能 G[x]
G [x]:恢复函数,取决于 ncx、ndx和恢复期 RG
根据对冠状病毒的了解,在 RP 恢复期后,感染者要么康复,要么死亡。在时间 x-RP 中被感染的人数将是死亡的(nd[x])或康复的。
G [x] = nc[x-GP] — nd[x ] (8)
估计感染病例数
最后,你可以估计仍然存在的感染病例
I [x] = Ip [x] — G [x] (9)
新冠肺炎—vuongsulator . py
我已经使用 Python 开发工具包平台"TAV uong/covid 19-data KIT "开发了用于新冠肺炎数据分析的 vuong 模型,详细描述可以在 Readme.md 或我的上一篇论文中阅读,所以我在这里简单描述一下。
安装和启动
$ github 克隆https://github.com/tavuong/covid19-datakit.git
$ pip 安装费用
$ pip 安装 Matplotlib
$ cd ~ \ covid19-datakit \
$ python。\ covid 19-vuong simulator . py[通过 PC]
$ python3。\ covid 19-vuong simulator . py[由树莓 PI 提供]
此示例向您展示了如何启动 covid 19-vuongsulation 并通过其对话框给出参数。您可以使用项目的[数据文件夹](http://tavuong / covid19-datakit/data)中的测试数据或您的数据,
$ CD ~ \ covid 19-数据套件\
$ python。\ covid 19-vuong simulator . py[通过 PC]
VMODEL >国家?世界
VMODEL > new_case-file?。/data/new_cases.csv
死亡文件?。/data/new_deaths.csv
VMODEL > VuongSimualtion 模式?6
VMODEL >潜伏期?七
VMODEL >恢复期?14
然后它将绘制和打印结果
Vuong_Simulator >确认信息。= 5555708
Vuong_Simulator >Incub。P =7/预计。inf。=5937024
Vuong_Simulator >Reco。P =14/预计。恢复=4233977
Vuong_Simulator >Reco。P =14/预计。Inf。=1703047
Vuong_Simulator >死亡人数= 350212
图 3 https://ourworldindata.org/coronavirus-source-data 新冠肺炎数据【世界】分析,数据来源:
您可以使用这个命令行来启动 Vuong 模拟器,以获得相同的结果
$ python。\ covid 19-vuong simulator . py-c World-o test.png-m ta-n . \ data \ new _ cases . CSV-d . \ data \ new _ deaths . CSV-g 0.98-r 14-t 7-s 6
刚刚通过以下选项实施:
$巨蟒。\ covid 19-vuong simulator . py-h
-n <new_cases_file>-d <new_deaths_file>-o 输出文件</new_deaths_file></new_cases_file>
-c 国
-t 潜伏期τ
-r 恢复期
-s 模拟模式
程序根据模拟模式进行计算和绘图。只有在模式 1 中是时间功能,在其他模式中,显示时间功能的累积
Vuong 模型后的 R 系数(开发中)
2:确诊感染 nc[x] —死亡 nd [x]
3:确认感染 nc[x] /恢复函数 G[x]
/最终估计感染人数 I[x]/死亡人数 nd [x]
4:确认感染 nc[x] —恢复函数 G[x]
死亡人数
5:确认感染 nc[x] /估计感染 Ip[x]
/最终估计感染人数 I[x]/死亡人数 nd [x]
6:确认感染 nc[x] /估计感染 Ip[x]
/恢复函数 G[x]
/最终估计感染人数 I[x]/死亡人数 nd [x]
示例命令
$ python。\ covid 19-vuongssimulator . py-c“美国”-o test.png-m ta-n . \ data \ new _ cases . CSV-d . \ data \ new _ deaths . CSV-g 0.98-r 14-t 7-s 6
图 4 美国新冠肺炎数据分析,数据来源:https://ourworldindata.org/coronavirus-source-data
用新冠肺炎-冯氏模拟程序预测未发现的感染病例
Vuong 算法用于分析新冠肺炎数据,这些 CSV 文件可从这里的开源下载。我想对影响的全球 213 个国家和地区或城市进行分析,例如加州或纽约或杜塞尔多夫,但我能力有限。所以我用 Vuong 模拟器分析了一些国家的新冠肺炎数据:意大利、德国、瑞典、美国和“世界”,你可以在图 5 中看到结果
图 5 新冠肺炎分析-义大利、德国、瑞典、美国的数据。数据来源:【https://ourworldindata.org/coronavirus-source-data
通过使用我提出的算法进行测试分析,我发现了一些关于冠状病毒疫情的有趣预测:
- 在意大利和德国,疫情已经大大降低(图 5)。
- 在美国,疫情已经开始减少(图 4)。
- 在瑞典,疫情仍在扩张(图 5)。
- 对世界来说,第二次危机(第二波)即将到来(图 3)。
摘要
开发了用于新冠肺炎数据分析的 Vuong 模型中的算法,以从确诊病例和死亡数据中搜索未发现的感染病例。Vuong 算法是基于一个开放系统,使用额外的新冠肺炎疫情信息和离散数学。这可能是众所周知的 SIR 模型优化方法的替代解决方案。
你可以下载软件“covid 19-Vuong Simulator”集成到开发套件中,用默认测试开源新冠肺炎数据或你的数据来分析未发现的感染病例。
covid19 数据的可视化和建模一直在不断发展,未来还会更新。如果您开发了一个新的有趣的模型-模块或演示-模块,请不要犹豫联系我进行咨询开发,也许可以将您的模块贡献给开源和麻省理工学院许可的项目TAV uong/covid 19-data kitoverGithub。
玩得开心!
新冠肺炎数据致谢:汉娜·里奇。
综述鸣谢:简范博士教授
感谢支持和咖啡蛋糕的动力:我的妻子 Thi Chung Vuong
超出和结束可用数据的预测
原文:https://towardsdatascience.com/prediction-beyond-and-end-of-the-available-data-653a9a935549?source=collection_archive---------17-----------------------
回归分析和未来价格预测
分析金融时间序列的机器学*算法
作者图片
https://sarit-maitra.medium.com/membership
P 预测超越样本数据进入未来的复杂任务;特别是当我们处理来自高频交易的金融数据的随机时间序列时。机器学*模型的预测性能通常是这样进行的
- 通过将给定数据集分割成样本内周期;用于初始参数估计和模型选择;
- 样本外期间用于评估预测性能
与样本内的表现相比,样本外的预测表现通常被认为更可信,更基于经验证据。样本内性能往往对异常值和数据挖掘更敏感。样本外预测也能更好地反映实时可用的信息。但是,可以注意到,样本内收益的可预测性并不一定意味着样本外收益的可预测性。关键是,从训练集中学*的模型,是否能够推广新的数据。
让我们探索一下,看看我们现实生活中的案例研究是如何在从未见过的数据场景中工作的。我们将使用道琼斯工业指数数据进行调查。
数据加载:
df = web.DataReader('^DJI', data_source = 'yahoo', start = '2000-01-01')
print(df.head()); print('\n'); print(df.shape)
实际价格可视化:
dataset = df.copy()
fig = go.Figure(data=[go.Candlestick(x=dataset.index, open=dataset['Open'], high=dataset['High'], low=dataset['Low'], close=dataset['Close'])])
fig.show()
每日回报的经验分位数:
由于风险价值(VaR)的广泛使用,分位数预测对风险管理决策至关重要。它是两个因素的产物
- 波动预测,以及
- 波动预测的分位数。
使用经验分位数的每日风险值:
假设:日收益率呈正态分布。我们可以看到日收益率的分布图,如下所示。
方法:通过曲线拟合来分析分位数的历史数据,这里,学生的 t 分布
dataset['daily_return'] = dataset['Adj Close'].pct_change()
round(dataset["daily_return"],2).quantile(0.05)
每日回报的 0.05 (p=0.05)经验分位数在-0.02(0.05 分位数是第 5 个百分位数)。
- 有 95%的信心,我们最大的每日损失不会超过投资的 2%
- *如果我们在€投资 100 万英镑,我们一天的 5%风险值是 0.02 €1 万英镑=€2 万英镑
从上面的图中可以看出,高斯白噪声具有恒定的波动性。高波动性和低波动性的时期以及回报的极端波动性。此外,我们还可以看到波动是如何依赖于时间的;高波动期持续存在,低波动期持续存在。
VaR:蒙特卡罗模拟
我们将根据历史波动生成道琼斯价格走势。鉴于这种历史波动性,将会有一点随机性。
用于生成第二天价格的公式:
最后几天的价格,并乘以 1 +随机冲击,这是通过抽取给定历史波动率的分布样本而产生的。
让我们回顾一年前(252 天)的价格。
# resetting index
dataset.reset_index(inplace = True)
dataset = dataset.sort_values(by = 'Date', ascending=True)
print(dataset.loc[[(len(dataset) -252)]]) # closing price 252 days back
我们在这里看到,收盘价是 28745.08 美元。
我们运行一个 10,000 次运行的模拟来获得下面的输出。
days = 252
start_price = 28745.089844 # Taken from above#delta t
dt = 1/252
mu = dataset['daily_return'].mean() # mean return
sigma = dataset['daily_return'].std() # volatilitydef stock_monte_carlo(start_price, days, mu, sigma):
price = np.zeros(days)
price[0] = start_price
shock = np.zeros(days)
drift = np.zeros(days)
for x in range(1,days):
shock[x]=np.random.normal(loc=mu*dt,scale=sigma*np.sqrt(dt)) drift[x] = mu * dt
price[x] = price[x-1] + (price[x-1] * (drift[x]+shock[x]))
return price
plt.plot(stock_monte_carlo(start_price, days, mu, sigma))
plt.xlabel('Days'); plt.ylabel('Price (US$)')
plt.title('Monte-Carlo Analysis for Dow Jones')
plt.show()
runs = 10000
simulations = np.zeros(runs)
for run in range(runs):
simulations[run] = stock_monte_carlo(start_price,days,mu,sigma)[days-1]
q = np.percentile(simulations,1)
plt.hist(simulations, bins = 200)
plt.figtext(0.6,0.8,s="Start price: $%.2f" %start_price)
plt.figtext(0.6,0.7,"Mean final price: $%.2f" % simulations.mean())
plt.figtext(0.6,0.6,"VaR(0.99): $%.2f" % (start_price -q,))
plt.figtext(0.15,0.6, "q(0.99): $%.2f" % q)
plt.axvline(x=q, linewidth=4, color='r')
plt.title(u"Final price distribution for Dow Jones after %s days" %days, weight='bold')
plt.show()
上图表明,道琼斯价格自过去一年以来几乎是稳定的;起始 Adj 收盘价格为 28745 美元,超过 10000 次的平均最终价格几乎相同(28759 美元)。红线表示 99%置信区间的风险值。
我们将执行 ML 来预测未来的 Adj Close 价格。让我们做一些对模型性能至关重要的特征工程。
时间序列组件对于分析感兴趣的变量非常重要,以便了解其行为、模式,并能够选择和拟合适当的时间序列模型。另一方面,时间序列预测器可以帮助一些模型识别额外的模式并提高预测的质量。时间序列的组成部分和特征对于解释时间序列的行为、分析其属性、识别可能的原因等都至关重要…Roman Josue de las Heras Torres
特征工程
dq = df.copy()
dq['ho'] = dq['High'] - dq['Open']
dq['lo'] = dq['Low'] - dq['Open']
dq['oc'] = dq.Open - dq.Close
dq['hl'] = dq.High - dq.Low
dq['volume_gap'] = dq.Volume.pct_change()
dq['day_of_week'] = dq.index.dayofweek
dq['day_of_month'] = dq.index.day
ema_12 = dq['Adj Close'].ewm(span=10).mean()
ema_26 = dq['Adj Close'].ewm(span=26).mean()
dq['ROC'] = ((dq['Adj Close'] - dq['Adj Close'].shift(5)) / (dq['Adj Close'].shift(5)))*100
delta = dq['Adj Close'].diff()
window = 14
up_days = delta.copy()
up_days[delta<=0]=0.0
down_days = abs(delta.copy())
down_days[delta>0]=0.0
RS_up = up_days.rolling(window).mean()
RS_down = down_days.rolling(window).mean()
dq['rsi'] = 100-100/(1+RS_up/RS_down)
dq['macd'] = ema_12 - ema_26#print(dataset)# lag featuerslags = 3
# Create the shifted lag series of prior trading period close values
for i in range(0, lags):
dq["Lag%s" % str(i+1)] = dq["Adj Close"].shift(i+1).pct_change()# target variable
future_pred = int(15)
dq['prediction'] = dq['Adj Close'].shift(-future_pred)
dq.head()
相对强弱指数(RSI)和移动平均线收敛 D 收敛(MACD)
感兴趣的可以访问 这里 获取详细的技术指标。
目标变量
我们已经创建了目标变量来预测当前数据集中不可用的未来 15 天的值。
dq = dq.drop(['High','Low','Open','Close','Volume', 'Adj Close'],1)
dq.dropna(inplace=True)# creating X,y set
X = dq.drop(['prediction'],1)
X_fcast = X[-future_pred:] # future prediction set
X = X[:-future_pred] # removing last 15 rows
y = y[:-future_pred]# splitting train/test
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=42)
不,让我们拟合一个线性(OLS)模型作为基础模型,并观察我们得到的模型:
ols = linear_model.LinearRegression().fit(X_train, y_train)
# Explained variance score: 1 is perfect prediction
print('Training Variance score (R^2)', r2_score(y_train, ols.predict(X_train)))
# Explained variance score: 1 is perfect prediction
print('Test Variance score (R^2): ', r2_score(y_test, ols.predict(X_test)))
极端梯度推进
我们使用 XGBRegressor 拟合模型,随后检查测试集的置信水平,并获得预测值(15 天)。XGBoost 具有处理数据中缺失值的能力。此外,基于树的算法不需要数据缩放。
reg = XGBRegressor(objective ='reg:squarederror', n_jobs=-1).fit(X_train, y_train)
# Explained variance score: 1 is perfect prediction
print('Variance score: %.2f' % r2_score(y_train, reg.predict(X_train)))
# Explained variance score: 1 is perfect prediction
print('Variance score: %.2f' % r2_score(y_test, reg.predict(X_test)))
虽然性能比基本模型有所提高,但是考虑到我们使用了回归算法,我们还没有完全达到。在这一阶段,我们可以回头看看这些功能,并在相关功能上做更多的工作。
一旦我们对准确性感到满意,我们就可以使用单独保存的预测数据进行未来预测。程序如下所示。
prediction = reg.predict(X_fcast)
print('\033[4mExpected Close price for next 15 days\033[0m')
print(prediction);
为了更好地理解,我们需要具有上述值的日期。实际上,我们已经预测了 2 周,如下所示。下面几行代码为获得的预测值生成未来日期。
d = df[['Adj Close']].tail(len(prediction));
d.reset_index(inplace = True)
d = d.append(pd.DataFrame({'Date': pd.date_range(start = d.Date.iloc[-1],
periods = (len(d)+1), freq = 'D', closed = 'right')}))
d = d.tail(future_pred);
d.set_index('Date', inplace = True)
prediction = pd.DataFrame(prediction)
prediction.index = d.index
prediction.rename(columns = {0: 'Forecasted_price'}, inplace=True)
prediction
预期价格
形象化
将观察值(过去 2 个月)和预测值(未来 1 个月)相加的图有助于我们了解模型是否能够从历史数据中捕捉模式。这里的未来预测看起来很现实。
fig = go.Figure()
n = prediction.index[0]
fig.add_trace(go.Scatter(x = df.index[-100:], y = df['Adj Close'][-100:], marker = dict(color ="red"), name = "Actual close price"))fig.add_trace(go.Scatter(x = prediction.index, y = prediction['Forecasted_price'], marker=dict(color = "green"), name = "Future prediction"))
fig.update_xaxes(showline = True, linewidth = 2, linecolor='black', mirror = True, showspikes = True,)
fig.update_yaxes(showline = True, linewidth = 2, linecolor='black', mirror = True, showspikes = True,)
fig.update_layout(title= "15 days days DJIA Forecast",yaxis_title = 'DJIA (US$)',hovermode = "x",hoverdistance = 100, spikedistance = 1000,shapes = [dict(x0 = n, x1 = n, y0 = 0, y1 = 1, xref = 'x', yref = 'paper',line_width = 2)],annotations = [dict(x = n, y = 0.05, xref = 'x', yref = 'paper', showarrow = False,xanchor = 'left', text = 'Prediction')])
fig.update_layout(autosize = False, width = 1000, height = 400,)
fig.show()
从上面的图中我们可以清楚地看到一个糟糕的预测。
除了在特征上的工作,我们需要重新访问和查看我们的目标变量,该变量在本实验中没有改变,我们这样做可能会导致前瞻偏差。我们可以尝试用 df['Adj Close']做实验。shift(-1),给出未来预测。
当我们准备好实时预测未来时,我们当然应该使用所有可用的数据进行估计,以便使用最新的数据。
摘要
我们可以尝试其他算法,如支持向量或随机森林。虽然,XGB 可以学*更复杂的非线性表示,但需要更多的数据集才能更好地执行。我们没有应用任何基本变量,这里使用的所有预测变量都可能与目标变量有线性关系。
在用于预测问题的监督机器学*算法中,基于树的算法是最好的。这些方法能够通过学*许多简单的规则来捕捉数据中的复杂关系,一次一个规则。
需要应用交叉验证和算法优化技术来最终确定稳健的模型性能。通过观察偏差/方差,我们可以调整过拟合或欠拟合问题;我们也可以引入这里没有练*过的早期停止回合。这将是一个好主意,测试几个其他模型,并可能引入一个最好的模型集合,以检查性能和准确性得分。
此外,出于验证目的保留数据是一个重要的诊断测试,因为它给出了预测未来时可以预期的准确性的最佳指示。出于验证目的,保留至少 20%的数据可能是一个好的做法。但是,在大量数据可用的情况下,坚持 50%也可以尝试。
我这里可以到达。
参考文献:
- 伯格梅尔、克里斯托弗和何塞·m·贝尼特斯。“交叉验证在时间序列预测评估中的应用”信息科学 191 (2012)
- 伯格梅尔、克里斯托弗、罗布·j·海曼和古邦秀。“关于评估自回归时间序列预测的交叉验证有效性的说明。”计算统计&数据分析 120 (2018)
- 伯尔曼、普拉比尔、埃德蒙·周和黛博拉·诺兰。"相关数据的交叉验证方法."生物计量学 81.2 (1994)
基于机器学*的养老院综合评分预测
原文:https://towardsdatascience.com/prediction-of-overall-rating-of-a-nursing-home-using-machine-learning-c76871a3a827?source=collection_archive---------54-----------------------
养老院数据集上的端到端机器学*应用
照片来自 Pixabay
摘要:
医疗保险和医疗补助服务中心为全国参加医疗保险或医疗补助计划的每家养老院发布了一套质量评级。这些评级有助于家庭了解不同养老院之间的差异及其质量。他们还帮助做出重要决定,如选择自己喜欢的养老院(医疗保险和医疗补助服务中心,2020 年)。本文旨在回答与数据集相关的某些研究问题。它使用机器学*技术对数据进行建模,并理解不同特征之间的关系。给定一组属性,训练机器学*模型来预测养老院的总体评级。对不同模型的性能进行了评估,并提供了研究问题的答案。
简介:
医疗保险和医疗补助服务中心引入了一个基于“星级”的评级系统,对养老院的质量进行量化。养老院的“总体评级”是根据其在三个领域的表现计算的,而这三个领域又是一个评级。
健康检查:进行年度检查调查,记录疗养院的不足之处。通过考虑在过去三年的这些检查中发现的缺陷的严重性和数量来分配评级。它还包括该部门要求的回访次数,以检查疗养院是否纠正了检查中发现的问题。
人员配备: RN 是注册护士的缩写,LPN 是执业实*护士的缩写。该评级基于每位住院医师每天的总注册护士小时数和每位住院医师每天的总护士小时数。
质量评估:疗养院比较网站上有 15 项质量评估,包括 9 项长期停留评估和 9 项短期停留评估。
由于有多个特征,并且很难理解和分析所有这些特征,因此存在一个称为“总体评级”的单一特征,该特征以 1 到 5(最低到最高)的等级分别对养老院进行评级。关于这三个领域的详细信息见(医疗保险和医疗补助服务中心,2020)。
数据集描述:
该数据集摘自 DATA.GOV 网站(医疗保险和医疗补助服务中心,2019 年)。它由 86 列和 15,437 条记录组成。每个记录都与一个疗养院相关联。描述疗养院的一些重要栏目是,
联邦提供者编号—由联邦政府提供给疗养院的唯一编号。
提供者名称—疗养院的名称。
提供者地址—疗养院的地址。
提供者城市—疗养院所在的城市。
提供者州——疗养院所在的州。
提供者邮政编码—与疗养院相关的邮政编码。
提供者电话号码—疗养院的电话号码。
提供者 SSA 县—疗养院所在的县。
提供者县名称—疗养院所属县的名称。
所有权类型-描述它是一个盈利性或政府或非盈利性实体。
提供者类型—描述疗养院是医疗保险还是医疗补助,或者是医疗保险和医疗补助。
提供者住在医院-一个布尔值,表示真或假,以表示提供者是否住在医院。
合法企业名称——养老院的合法企业。
文件导言部分还介绍了与这些措施相关的其他特点。例如,与‘健康检查’相关的一些特征包括‘评定周期 1 健康缺陷总数’、‘评定周期 1 标准健康缺陷数’、‘评定周期 1 健康缺陷分数’等。与“人员配备”相关的特征包括“每个住院医师每天报告的护士助手人员配备小时数”、“每个住院医师每天报告的 LPN 人员配备小时数”、“每个住院医师每天报告的 RN 人员配备小时数”等。与''相关的特性包括'质量管理评级'、'质量管理评级脚注'、'长期质量管理评级'等。
数据的汇总统计如表 1 所示。因为有许多列,所以表中只显示了其中的几列。
表 1。数据集中要素的汇总统计数据
“罚款总额(美元)”和“认证床位数”这两个特征的数值最高。“罚款总额(美元)”功能的平均值、标准差和 75%置信区间值是最大值。25%和 50%的置信区间值是“认证床位数”和“每日平均住院人数”列的最大值。
探索性数据分析:
图 1 显示了各州的“总加权健康调查分数”。可以观察到,加利福尼亚和得克萨斯具有更高的总加权健康调查分数。佛蒙特州、波多黎各和关岛等地的加权健康调查总得分较低。
图 1。描述各州总加权健康调查分数的条形图
图 2 显示了一个热图,显示了各州养老院的“总体评分”总和。可以看出,加利福尼亚州、得克萨斯州、俄亥俄州和佛罗里达州的养老院总体排名最高。仅考虑 50 个州,阿拉斯加、佛蒙特、特拉华、怀俄明各州对养老院的“总体评分”较低。
图二。热图显示了各州所有疗养院的总体评分总和
图 3 描绘了各州给予养老院的罚款总额的箱线图。有趣的是,尽管德克萨斯州、密歇根州和佛罗里达州都在罚款总额最高的五个州之列,但加利福尼亚州并不在其中。在箱线图中可以观察到很多异常值,因为每个州的养老院所遭受的罚款为零。许多州的中位数也接*于零。密歇根州的四分位数间距最高。德克萨斯州和北卡罗莱纳州的养老院承担了最高的罚款。德克萨斯州的罚金最高,总额超过 120 万美元。
图 3。各州给予养老院的罚款总额(美元)的方框图
皮尔逊相关系数大于 0.7 的特征的相关矩阵如图 4 所示。在“评定周期 2 总健康分数”和“评定周期 2 健康缺陷分数”以及“评定周期 1 健康缺陷分数”、“评定周期 1 健康总健康分数”和“评定周期 1 健康缺陷分数”之间观察到最高相关性。皮尔逊相关系数值大于 0.8 的要素可被视为高度相关。可以从数据集中删除每个集合中的一个高度相关的列,因为它们不提供任何附加值。
图 4。描述最相关特征的皮尔逊相关系数的热图
图 5 显示了“总体评分”和“总加权健康调查分数”栏之间的散点图。回归分析通过拟合线性回归来执行,以识别两个特征之间是否存在任何相关性。
图 5。总体评分和总加权健康调查得分之间的散点图
图 6。总体评分加权健康调查总分回归分析
通过对这两个特征使用线性回归,对数据拟合一条线。图 6 中描绘了相反的关系。随着总体评分的增加,总加权健康调查分数降低。这一观察结果得到了“注意,较低的调查分数对应于较少的缺陷和重访,因此在健康检查领域表现更好”这句话的支持(医疗保险和医疗补助服务中心,2019 年)。
对特征“提供者居住在医院”和“持续护理退休社区”进行独立性卡方检验。零假设假设特征是独立的。另一个假设假设这些特征是相关的。卡方检验显示 p 值为“7.1246454255565634e-12”。由于 p 值小于 0.05(在 95%的置信水平下),我们拒绝零假设,并接受替代假设,认为特征是相关的。“提供商在过去 12 个月内改变了所有权”和“滥用图标”之间的类似测试表明,它们是独立的。因为显著性水平为 0.05(95%置信水平)的 p 值计算为 0.975,大于 0.05。
研究问题:
本文旨在回答有关数据集的三个研究问题。
1.可以开发一个机器学*模型,根据数据中观察到的模式为养老院分配一个类别(总体评级)吗?
2.如果是,它有多可靠,有多准确?
3.影响养老院整体评分的最重要因素是什么?
对上述问题的回答有助于确定养老院影响其整体评级的最重要因素。这可以帮助养老院做出某些决定,以提高其评级,并在高度影响其评级的领域进行改进。
数据预处理:
许多文本数据,如位置、联邦供应商编号、健康调查日期对模型拟合不是很有用,这些列已从数据集中删除。此外,还考虑了调整后的功能,而不是单独报告的功能。例如,不考虑“每个住院医师每天报告的护士助手工作时间”,而是考虑“每个住院医师每天调整的护士助手工作时间”。包含真/假(布尔值)的列已分别替换为 1/0。某些列的 NaN 值,如“质量管理评级”、“长期质量管理评级”、“短期质量管理评级”、“员工评级”都填零。
该列的平均值用于替换“每个住院医师每天调整后的护士助手工作时间”、“每个住院医师每天调整后的 LPN 工作时间”、“每个住院医师每天调整后的总护士工作时间”、“每天住院医师平均人数”等中的 NaN 值。对某些列执行虚拟编码,如“有居民和家庭委员会”和“提供者类型”,因为它包含分类变量。其值都是 NaN 值的列将从数据集中删除。
不是对整个数据集进行规范化,而是将每一列规范化为[0,1]的范围。如果对整个数据集执行规范化,包含大数的列将成为决策的主导。皮尔逊相关系数是在数据集的所有要素之间计算的,每个数据集中的一个高度相关列已从数据集中删除,因为它们不能为模型提供任何附加值。经过预处理后,总列数从 86 列减少到 52 列。
班级分布:
观察属于每个类别(总体评级)的记录数量。类别 5 的记录数量最多,而类别 1 的记录数量最少。但它们之间的差异是 1000 个记录,这是可以容忍的。这种分布是自然的,不需要抽样方法,因为没有一个阶层的代表性严重不足或过多。
图七。按类别分布记录数量(总体评级)
模型拟合:
预测“总体评级”的当前任务是分类任务。诸如随机森林和支持向量机的机器学*算法是可以应用于分类(二进制或多类)的一些健壮算法。
随机森林是一种集成技术,它使用多个决策树,并根据输入特征为给定实例分配一个类。它可以执行回归和分类任务。使用替换对数据进行采样,并在提取的样本上训练几个决策树。在取样过程中,一定百分比的数据被分离出来并标记为 OOB(出袋)数据。在 OOB 数据上测试训练的决策树,并且获得 OOB 误差估计。最终确定具有最小 OOB 误差的最佳“n”棵树,并将其视为单个随机森林分类器。给定一个测试实例,随机森林分类器中的每个决策树预测一个类。执行类似投票的机制,并且由大多数树预测的类被生成作为随机森林分类器的输出。由于集合方法,随机森林可以非常有效地模拟数据(Leo 等人,2020)。
支持向量机是一种监督算法,可用于分类和回归。它确定了可以有效划分数据的最佳超平面。它也被称为最大间隔分类器,因为它试图构建一个超平面,该超平面到两个类的最*元素的距离是最大的(Cortes 等人,1995)。由于它们在许多分类任务中被证明是有效的,这两种模型都被认为是对当前数据的建模。
训练:
数据集按 80:20 的比例划分,其中 80%的数据构成训练集,其余 20%构成测试集。模型将被训练的特征被称为 X_train。对于当前数据集,X_train 构成预处理数据集后获得的所有 51 列(不包括“总体训练”列)。数据集将被训练来预测的目标/列被称为 Y_train,对于当前数据集,它将是“总体评级”列。
在训练过程中,机器学*模型被拟合到数据集。然而,建模的效率取决于给予模型的一组输入,这些输入通常被称为超参数。根据数据,需要调整超参数,这个过程称为超参数调整。用于训练随机森林和 SVM 模型的最佳超参数已经通过被分类为 K-Fold 交叉验证的技术来识别。在这种技术中,训练集被分成 K 个折叠/部分,其中 K-1 个部分被认为是训练集,一个部分被认为是测试集。提供一组超参数作为输入,在 K-1 个零件上训练模型,然后对一个零件进行测试(Refaeilzadeh 等人,2009 年)。这个过程被执行 K 次,并且每次都评估度量。计算分类度量的平均值,例如所选超参数的平均准确度、平均精确度、平均召回率和平均 F1 分数。超参数的最佳集合产生最高的测试分数,并且因此被确定。
对于当前数据集,执行了 5 重交叉验证,机器学*模型的最佳超参数确定如下。
RandomForestClassifier(bootstrap = True,class_weight=None,criterion='entropy ',max_depth=30,max_features='auto ',max_leaf_nodes=None,min _ infinity _ decrease = 0.0,min_samples_leaf=1,min_samples_split=2,min_weight_fraction_leaf=0.0,n_estimators=500,n_jobs=None,oob_score=False,random_state=None,verbose=0,warm _ start =
SVC (C=10,cache_size=200,class_weight=None,coef0=0.0,decision_function_shape='ovr ',degree=3,gamma=1,kernel='rbf ',max_iter=-1,probability=False,random_state=None,shrinking=True,tol=0.001,verbose=False)
随机森林和支持向量机的交叉验证分数如表 2 所示。
表二。随机森林和支持向量机的交叉验证分数
在交叉验证结束时,超参数被确定,并且整个训练集被模型训练为单个实体。模型已经准备好在测试集上进行测试。
测试和评估:
测试集中的每个记录都通过训练集来预测该记录的“总体评级”。每个记录代表一个疗养院。因此,该模型基本上是训练来预测养老院的“总体评级”,给定其一组特征。预测由分类指标评估—精确度、准确度、召回率和 F1 分数。
****表 3。测试集上随机森林的类级分类度量
****表 4。测试集上支持向量机的类级分类度量
表五。机器学*模型性能的整体比较
可以得出结论,随机森林分类器是当前数据集的最佳性能模型。在所有分类指标上,如准确度、平均精确度、平均召回率和 F1 平均得分,它都占据了 SVM 的主导地位。
调研问题答案:
1。可以开发一个机器学*模型,根据数据中观察到的模式为养老院分配一个类别(总体评级)吗?
****回答:是的。可以开发一种机器学*模型,该模型可以将养老院分类为“总体评级”特征中呈现的五星评级之一。还可以得出结论,在关于总体评级栏的数据中存在清晰的模式,并且机器学*模型能够区分这些模式。因此,在当前数据集上建立可靠的模型并成功实现目标是可能的。构建这种模型的过程也在上面陈述了。
2。如果是,它有多可靠,有多准确?
****答:模型的性能可以通过不同的分类指标进行评估。随机森林模型的精确度被计算为 97%。随机森林模型预测类的平均精度被计算为 97%。简单来说,召回率是正确预测的数量与所有应该正确预测的数量之比。平均召回值也是 97%。F1 分数是精确度和召回率之间的调和平均值。F1 分数越高,模型越好。当前的随机森林模型在测试集上实现了 97%的平均 F1 分数。在所述指标的帮助下,可以得出结论,该模型是稳定且非常可靠的。
3。影响养老院整体评分的最重要因素是什么?
****答案:经过训练的随机森林模型提供了对数据集最重要特征的深入洞察。这是因为随机森林通过挑选对目标列最重要的特征来构建对数据建模的决策树。他们通过使用诸如“熵”、“基尼”、“增益率”等技术来计算特征的重要性。对于当前模型,特征重要性的顺序如图 8 所示。
影响“总体评分”的十大特征包括:“健康检查评分”、“QM 评分”、“人员配备评分”、“总加权健康调查评分”、“每个居民每天调整的 RN 人员配备小时数”、“第 1 周期总健康评分”、“长期住院 QM 评分”、“每个居民每天调整的护士人员配备小时数”、“第 1 周期健康缺陷评分”和“短期住院 QM 评分”。
图八。特征重要性的顺序由随机森林分类器决定
结论:
当前的论文提供了回答提出的研究问题所需的方法、工具、技术和程序的详细描述。建立了两个机器学*模型(随机森林和支持向量机),进行了广泛的分析和测试,以从训练的模型中获得洞察力。得出了相关结论,提供了答案。疗养院可以利用从数据中发现的丰富信息,并做出必要的决定来提高它们的总体评级。
限制:
随机森林模型的可解释性很低,因为它是决策树的集合。当树很大时,很难想象或解释它们。与随机森林的训练和测试相关联的存储器和计算成本很高。预测速度不是很快,对于时间敏感型应用来说可能是个问题(Jansen,2018)。
虽然有明确的规定,向养老院提供评级,但数据可能不准确。对于这种不准确的数据记录,模型可能不会给出相同的结果。
推荐未来分析:
当前数据定义了疗养院的不同属性和给予它的不同评级,以及与它的缺陷、处罚和罚款相关的信息。然而,它没有描述养老院所在的地理区域的社会经济因素。这些信息可以添加到数据集中,以丰富结果的质量并找到新的见解。
随着数据的增加,随机森林和 SVM 等模型无法很好地扩展。可以在数据集上训练高级模型(如神经网络)来克服这个问题。
参考文献:
医疗保险和医疗补助服务中心。(2019).提供商信息[数据文件]。于 2020 年 3 月 29 日从https://catalog.data.gov/dataset/provider-info-1de34取回
医疗保险和医疗补助服务中心。2020 年养老院设计对比五星级质量评级体系。
c .科尔特斯和 v .瓦普尼克(1995 年)。支持向量网络。机器学*,20(3),273–297 页。
詹森斯特凡。算法交易的动手机器学*:基于使用 Python 从数据中学*的智能算法,设计和实施投资策略。Packt 出版公司,2018 年。
利奥,布莱曼和阿黛尔·卡特勒。“随机森林。”随机森林-分类描述。于 2020 年 5 月 10 日从 www.stat.berkeley.edu/~breiman/RandomForests/cc_home.htm取回。
Refaeilzadeh P .,Tang L .,Liu H. (2009)交叉验证。载于:刘,主编的《数据库系统百科全书》。马萨诸塞州波士顿斯普林格
基于机器学*的 Volve 油田声波测井预测
原文:https://towardsdatascience.com/prediction-of-p-sonic-log-in-the-volve-oil-field-using-machine-learning-9a4afdb92fe8?source=collection_archive---------21-----------------------
实践教程
使用 Scikit-Learn 逐步解释
rsk Inspirer på Volve 来自 Equinor 照片档案馆
2018 年,挪威石油公司 Equinor 披露了北海 Volve 油田的大规模地下和作业数据集。两年来,对于所有热衷于改善和解决大学、研究机构和公司油气领域研究挑战的人来说,这是一个好消息。以下是来自“马科动物的首席运营官”扬尼克·尼尔森的一段鼓舞人心的话。
“Volve 是我们如何寻找各种可能性来延长油田寿命的一个例子。现在,我们希望分享所有 Volve 数据,以确保未来解决方案的学*和开发。”
Volve 是一个油田,位于北海挪威区块南端斯塔万格以西 200 公里处,于 2008 年至 2016 年生产。
当我查看每个人都可以通过这个网站访问的数据库时,我看到了里面巨大的宝藏!我开始提出一些想法来探索引入机器学*的可能性,直到我想到了进行声波测井预测的想法,原因我在本文的动机部分中阐述。
我将这个项目保存在我的名为volve-machine-learning的 GitHub 资源库中(你可以访问这个资源库)。
数据集概述
在 Volve 油田开放数据库中,有 24 口井。在这项研究中,只使用了 5 口井。油井名称为 15/9-F-11A、15/9-F-11B、15/9-F-1A、15/9-F-1B 和 15/9-F-1C。
测井数据代表地球上的每个岩层( Aliouane 等人,2012 )
每口井都有他们所谓的测井记录。测井记录是代表深度范围内每个岩层属性的某些物理测量值。以下是我们将使用的日志列表。
- NPHI 是地层孔隙度,单位为 v/v
- RHOB 是地层体积密度,单位为克每立方厘米。
- GR 是地层放射性含量,用 API 测量。
- RT 是地层真实电阻率,单位为欧姆米。
- PEF 是地层光电吸收因子,无量纲。
- CALI 是钻孔直径,单位为英寸。
- DT 是纵波传播时间,单位是微秒每英尺。
- DTS 是剪切(横波)传播时间,与 DT 类似。
这些测井数据集的文件格式为 LAS 2.0,这是测井的一种特定格式。你可以在这里找到数据集。
动机
5 口井中有 3 口井(15/9-F-11A 井、15/9-F-1A 井和 15/9-F-1B 井)拥有这套完整的测井资料,除了之外,另外 2 口井(15/9-F-11A 井和 15/F-1C 井)没有 DT 和 DTS 测井资料。这就是为什么我们可以使用监督学*,通过回归模型在这个不完整的数据集中生成 DT 日志。
有 DT 日志的 3 个数据集作为训练数据,没有的作为测试数据。NPHI、RHOB、GR、RT、PEF 和 CALI 测井用作特征;而 DT 是用于预测的目标。目前,不会使用 DTS 日志。
scikit-从 GitHub 学*徽标
通过监督学*,这些训练数据会用Scikit-Learn中的一些回归模型进行训练。然后,该模型将用于根据特征预测产生新的 DT 测井曲线。
我将把工作流程分成七个步骤。您也可以在我的 GitHub repo 中访问我的 IPython 笔记本,它从头到尾运行这个工作流。
访问我的 IPython 笔记本
第一步。显示测井数据集
一个名为 lasio 的 Python 库用于读取这些 LAS 数据集。在任何地层评价中,显示测井记录都是例行公事。以下是使用 Matplotlib 生成的其中一个训练数据 15/9-F-1B 井的显示。每个图代表一条测井曲线;正如我们已经讨论过的,NPHI、RHOB、GR、RT、PEF 和 CALI 是特征,而 DT 是目标。
1B 15/9 井的测井显示
以下是 15/9-F-1C 井的测井曲线显示,该井是没有 DT 测井的两口井之一,因此我们将预测产生一个新的 DT 测井曲线。
15/9-F-1C 井的测井显示
第二步。数据准备
第二步是工作流程中最关键的部分,因为它会影响整个预测的成功。熊猫对数据处理很有用。
首先,我们需要确保我们的整个数据不包含任何非数字值 (NaNs)。过滤数据的一个技巧是设置最小和最大深度限制,这样所有数据都以数值开始和结束。例如,之前显示的 15/9-F-1B 井从 3100 米到 3400 米的深度开始。示例代码:
df = df.loc[(df['DEPTH'] >= 3100) & (df['DEPTH'] <= 3400)]
之后,我们检查数据中是否存在 nan。
df.isnull().sum()
如果一切归零,我们就安全了。在我们现在的情况下,它变为零,我们已经没有 NaNs 了。否则,我们需要处理 NaN 值。这个动作在这里详细讨论。
接下来,我们将各个井数据集合并到两个更大的单个数据框中,每个数据框用于训练和测试数据集。
df = pd.concat([df1, df2, df3])
现在我们有了训练和测试数据框架,最后我们分配井名。这样做的原因是为了便于我们在预测期间检索任何井。你可以在笔记本里看到我是如何分配井名的。
下面是训练数据的最终数据框。
训练数据帧
第三步。探索性数据分析
探索性数据分析(EDA)对于理解我们的数据至关重要。我们想知道的两件重要的事情是每个单独特征的分布和一个特征到另一个特征的相关性。
为了观察多元分布,我们可以在 Seaborn 包中使用一个 pair-plot。以下是特征和目标的多元分布。
训练数据集的配对图
我们从结对图中至少得到了 3 点。首先,我们观察大多数分布是如何偏斜的,并且不是理想的高斯,尤其是 RT。然而,对于机器学*,高斯或不太偏斜的数据是优选的。我们可以对这些数据进行标准化,这将在下面讨论。第二,我们可以看到数据里面的离群值。同样在下一部分,我们将讨论如何去除这些异常值。第三,我们看到一些数据对几乎线性(因此高度)相关,比如 NPHI 和 DT;和反向相关,比如 RHOB 和 DT。配对图说明了很多事情。
我们通过计算 Spearman 相关性 来查看更多特征和目标之间的相关性,并使用热图来可视化结果。以下是我们数据的 Spearman 相关热图。
训练数据的 Spearman 相关热图
只关注 DT 行,我们获得了 DT 和 NPHI 之间的 2 个最大相关(正相关为. 95)以及 DT 和 RHOB 之间的 2 个最大相关(负相关为. 79)。这个相关结果与我们之前在配对图中看到的结果相匹配。还有,除了 CALI,其他数据似乎都和 DT 有很高的相关性。CALI 似乎与其他特征也没有什么关联。
作为惯例,任何相关性非常低的特征都被排除在预测之外,因此 CALI 可以被排除。然而在这里,我将保留 CALI 作为一个特性。
第四步。正常化
我们以前从配对图中知道,大多数分布似乎是偏斜的。为了提高我们的预测性能,稍后,我们最好做一个归一化(其他人可能称之为缩放)。规范化是一种转换数据(不改变数据)以更好地分布数据的技术。
在进行任何标准化之前,我倾向于先对电阻率数据进行测井转换。
df['RT'] = np.log10(df['RT'])
然后,我用 Scikit-Learn 中的函数fit_transform
进行规范化。有几种标准化技术;广泛使用的有标准化(用均值和标准差转换)和 min-max (用最小值和最大值)。在尝试了所有的方法后,我找到了使用Yeo-Johnson方法的力量转换技巧。
归一化后,我们可以看到数据现在是如何使用 pair-plot 再次分布的。
用 Yeo-Johnson 方法进行幂变换后的训练数据对图
看看 NPHI、DT 和 RT 现在如何不那么偏斜,更像高斯分布。虽然 RHOB 和 GR 分布看起来是多峰的,但归一化后它变得更加集中。
第五步。移除异常值
此外,我们刚刚观察到数据中有许多异常值。异常值的存在会降低预测性能。因此,我们做离群点剔除。
Scikit-Learn 提供了几种离群点剔除方法,如隔离森林、使用椭圆包络的最小协方差、局部离群因子、单类支持向量机。除此之外,最广泛使用的异常值去除方法,也是最基本的方法,是使用标准差方法。在这种方法中,我们将阈值指定为偏离标准偏差的最小值和最大值。我们可以自己建造。
threshold = 3
df = df[np.abs(df - df.mean()) <= (threshold * df.std())]
所有 5 种方法都已实现。我用两种方法来比较哪种方法去除异常值的效果最好。一种方法是对每种方法计算剔除异常值之前的数据和剔除异常值之后的数据。
标准化前后的数据计数
从该结果中,我们看到标准差方法移除的异常值最少(最多只有 302 个),其次是单类 SVM 和最小协方差,与其他方法相比异常值相对较少(> 10,000)。您可能已经知道,剔除的异常值越少越好。
然后,为了决定标准差和一类 SVM 之间哪个更好,我使用熊猫为归一化前后的每个特征生成了箱线图。下面是箱线图。
关键的观察结果是,在剔除异常值前后,异常值仍然存在于新计算的汇总统计数据的数据中。这(间接地)是选择哪种方法是最好的直观表示。
现在,通过观察异常值的数量,可以看出一类 SVM 比标准差方法表现得更“干净”。尽管最小的协方差也是干净的,仍然一级 SVM 是赢家。
结论是:我们用一级 SVM 。同样,我们制作一个配对图来观察我们数据的最终结果。
使用一类 SVM 方法去除异常值后的训练数据对图
看看离群值现在是如何减少的。我们都为机器学*做好了准备。
第五步。预测!第一次尝试
现在主菜来了!第五步,我们还没有对我们的真实测试数据(没有 DT 测井的井 15/F-11B 和 15/F-1C)进行实际预测。耐心点!我们需要评估我们使用的每个回归模型的性能,方法是训练训练数据,并用训练数据本身测试模型,然后我们评估预测的 DT 日志与真实 DT 日志的接*程度。
在此步骤中,测试数据=训练数据
我尝试了来自 Scikit-Learn 的 6 个回归模型,分别是经典的线性回归、随机森林、支持向量机、决策树、梯度推进、K-最*邻回归器。
请记住,在完成预测后,我们总是需要对结果进行反规范化,因为我们刚刚进行了规范化。在 Scikit-Learn 中,我们使用一个inverse_transform
函数来完成这项工作。
我使用 R 和均方根误差(RMSE)作为评分标准来衡量每个回归模型的性能。以下是每个回归变量的评分标准的结果。
6 个回归变量的评分标准
从结果来看,我们看到回归器的表现非常出色!可以理解为什么经典的线性回归器不如其他回归器(最低的 R 和 RMSE)表现得好。原因是并非所有的特征都是完美的线性相关的。
然后,我们可以显示真实的 DT 日志和预测的 DT 日志,以比较两者的接*程度。以下是使用梯度推进回归器对每口井预测 DT 测井的真实值。
使用梯度推进回归器的真实与预测 DT 测井
事实上,我使用的所有回归变量仍然使用默认的超参数。例如,梯度增强的几个超参数中的两个是估计器的数量和最大深度。默认值分别为 100 和 3。
根据梯度推进的评分标准,我们已经知道 R 和 RMSE 分别达到了 0.94 和 0.22 左右。我们可以进行超参数调整以确定最佳超参数值,从而提高性能得分。
第六步。超参数调谐
梯度推进回归器上的超参数调谐通过执行训练-测试分割开始,该分割由 0.7 训练和 0.3 测试组成。然后,通过产生的训练和测试分裂,进行具有定义的搜索超参数集的网格搜索和三重交叉验证。以下是搜索到的参数网格。
- 估计数
n_estimators
: 100 和 1000 - 最大深度
max_depth
: 10 和 100
调整超参数花费了大约 5 分钟,直到给出估计器数量为 1,000,最大深度为100 的结果作为最佳超参数。
然后,通过包含超参数重复前面的步骤,并打印新的得分度量,如下所示。
超参数调整后梯度增强的评分标准
R 和 RMSE 都提高了很多,分别是 0.98 和 0.12 左右!有了这个结果,我们有足够的信心使用梯度推进进行预测。以下是超参数调整后的真实与预测 DT 对数图。
超参数调整后使用梯度推进回归器的真实与预测 DT 测井
第七步。为最终预测编译调整后的梯度推进回归器
最后我们做真正的预测!现在,用之前根据我们的实际测试数据调整的超参数(估计数= 1000,最大深度= 10)编译梯度推进回归器。记住,我们真正的测试数据是没有 DT 测井的井;15/9-F-11B 井和 15/9-F-1C 井,或所谓的 2 井和 5 井。
以下是 2 井和 5 井的预测 DT 测井。
15/9-F-11B 井和 15/9-F-1C 井的预测测井曲线令人满意!为了关闭我们的工作流程,我们可以将预测结果导入到原始数据集并写入 CSV 文件。
以下是最终的 CSV 结果:井 15/9-F-11B 和 15/9-F-1C
结论
我们已经证明了监督学*在 Equinor 拥有的 Volve 油田公开数据集上的成功应用。通过这一工作流程,使用梯度推进方法,在两口原本没有压力声波测井记录的油井上预测了新的压力声波测井记录。
我希望这篇文章能为地球科学中的任何 ML 从业者带来新鲜空气,开始探索这个数据集中 ML 的其他可能性。与此同时,我正在考虑其他的可能性,我会在我的 GitHub ( 关注我的工作以获得更新)中积极更新,并且很快会再写一篇!
基于移动应用行为数据的客户流失预测
原文:https://towardsdatascience.com/prediction-on-customer-churn-with-mobile-app-behavior-data-bbce8de2802f?source=collection_archive---------53-----------------------
通过数据处理、模型构建、验证、特征分析和选择深入研究逻辑回归建模
来自 Pixabay 的 Img 通过链接
在之前的文章中,我们使用应用行为数据创建了一个逻辑回归模型来预测用户注册。希望你在那里学得很好。这篇文章旨在基于更大的移动应用程序行为数据,用新的技术和技巧提高你的建模技能。它分为 7 个部分。
1.商业挑战
2.数据处理
3.模型结构
4.模型验证
5.特征分析
6.特征选择
7.结论
现在让我们开始旅程🏃♀️🏃♂️.
- 商业挑战
一家金融科技公司委托我们分析移动应用行为数据,以识别潜在的流失客户。目标是预测哪些用户可能会流失,因此公司可以专注于用更好的产品重新吸引这些用户。
2.数据处理
EDA 应在数据处理前进行。详细步骤在本篇中介绍。下面的视频是 EDA 后的最终数据。
2.1 一键编码
一键编码是一种将分类变量转换成数值变量的技术。它是必需的,因为我们要构建的模型无法读取分类数据。一键编码只是根据唯一类别的数量创建附加功能。在这里,具体来说,
dataset = pd.get_dummies(dataset)
以上自动将所有分类变量转换为数值变量。但是独热编码的一个缺点是虚拟变量陷阱。这是一个变量之间高度相关的场景。为了避免陷阱,必须删除一个虚拟变量。具体来说,
dataset = dataset.drop(columns = [‘housing_na’, ‘zodiac_sign_na’, ‘payment_type_na’])
2.2 数据分割
这是为了将数据分成训练集和测试集。具体来说,
X_train, X_test, y_train, y_test = train_test_split(dataset.drop(columns = ‘churn’), dataset[‘churn’], test_size = 0.2,random_state = 0)
2.3 数据平衡
不平衡类是分类中的常见问题,其中每个类中的观察值比例不成比例。但是如果我们在不平衡的数据集上训练一个模型会发生什么?该模型将巧妙地决定最好的事情是总是预测类 1,因为类 1 占用 90%的数据,所以该模型可以达到 90%的准确性。
这里有许多方法来对抗不平衡的类,例如改变性能指标、收集更多数据、过采样或下采样数据等。这里我们使用下采样方法。
首先,我们来考察一下 y_train 中因变量的不平衡程度。
图 1 因变量的不平衡分布:流失与否
如图 1 所示,因变量略有不平衡。为了对数据进行下采样,我们取每个类的指数,并在 y_train 的多个少数类中随机选择多数类的指数。然后连接两个类的索引,并对 x_train 和 y_train 进行下采样。
pos_index = y_train[y_train.values == 1].index
neg_index = y_train[y_train.values == 0].index
if len(pos_index) > len(neg_index):
higher = pos_index
lower = neg_index
else:
higher = neg_index
lower = pos_index
random.seed(0)
higher = np.random.choice(higher, size=len(lower))
lower = np.asarray(lower)
new_indexes = np.concatenate((lower, higher))
X_train = X_train.loc[new_indexes,]
y_train = y_train[new_indexes]
2.4.特征缩放
从根本上说,特征缩放是对变量范围的标准化。这是为了避免任何变量对模型产生显著影响。对于神经网络,特征缩放有助于梯度下降比没有特征缩放收敛得更快。
这里我们使用标准化来标准化变量。具体来说,
from sklearn.preprocessing import StandardScaler
sc_X = StandardScaler()
X_train2 = pd.DataFrame(sc_X.fit_transform(X_train))
X_test2 = pd.DataFrame(sc_X.transform(X_test))
3.模型构建
在这里,我们建立了一个逻辑回归分类器,用于流失预测。实质上,逻辑回归使用独立变量的线性组合来预测一类概率的对数。如果你想深入了解逻辑回归的更多细节,请访问这个维基百科页面。
具体来说,
from sklearn.linear_model import LogisticRegression
classifier = LogisticRegression(random_state = 0)
classifier.fit(X_train, y_train)
现在,让我们测试和评估模型。具体来说,
y_pred = classifier.predict(X_test)
from sklearn.metrics import confusion_matrix, accuracy_score, f1_score
cm = confusion_matrix(y_test, y_pred)
accuracy_score(y_test, y_pred)
f1_score(y_test, y_pred)
最后我们得到了一个 0.61 的精度和 0 的 F1。61 。表现不算太差。
4.模型验证
模型经过训练和测试后,一个问题是该模型推广到未知数据集的效果如何。我们使用交叉验证来衡量已知数据集和未知数据集之间的性能差异大小。具体来说,
from sklearn.model_selection import cross_val_score
accuracies = cross_val_score(estimator = classifier, X = X_train, y = y_train, cv = 10)
根据上述内容,我们发现 10 重交叉验证产生的平均准确度为 0.64.5 ,标准偏差为 0.023 。这表明该模型可以在未知数据集✨✨.上很好地泛化
5.特征分析
有了 41 个特征,我们建立了一个逻辑回归模型。但是如何知道在预测因变量时哪个特征更重要呢?具体来说,
pd.concat([pd.DataFrame(X_train.columns, columns = [“features”]), pd.DataFrame(np.transpose(classifier.coef_), columns = [“coef”])],axis = 1)
如图 2 所示,我们发现两个特性非常重要: purchase_partners 和 purchase 。这表明用户的购买历史在决定是否流失时起着很大的作用。同时,这表明并非所有变量对预测都很重要。
图 2 变量对预测的重要性
6.功能选择
特征选择是一种为建模训练选择最相关特征子集的技术。
在这个应用中, x_train 包含 41 个特性,但是如图 2 所示,并不是所有的特性都起着重要的作用。使用特征选择有助于减少不重要特征的数量,并以较少的训练数据获得相似的性能。关于功能选择的更详细的解释可以在这里找到。
这里,我们使用递归特征消除 (RFE)。它的工作原理是拟合给定的算法,按重要性排列特性,丢弃最不重要的特性,然后重新调整,直到达到指定的特性数。具体来说,
from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression
classifier = LogisticRegression()
rfe = RFE(classifier, 20)
rfe = rfe.fit(X_train, y_train)
如上所述,我们设置选择 20 个特性。图 3 显示了所有选择的特性。
图 3 RFE 推荐的功能
太好了。使用 RFE 选择的功能,让我们重新训练和测试模型。
classifier.fit(X_train[X_train.columns[rfe.support_]], y_train)
y_pred = classifier.predict(X_test[X_train.columns[rfe.support_]])
最终我们得到了一个 0.61 的精度和 0.61 的 F1。与在 41 个特征上训练的模型相同的性能😇😇!
如果我们再次应用交叉验证,我们得到的平均准确度为 0.647 ,标准偏差为 0.014 。同样,与之前的模型非常相似。
7.结论
最初,我们用 41 个特征训练了一个逻辑回归模型,达到了 0.645 的精确度。但是使用特征选择,我们创建了一个只有 20 个特征的轻型模型,精度为 0.647。一半的特征与决定客户流失无关。干得好!
太好了!这就是全部的旅程!如果您需要源代码,请随时访问我的Github页面🤞🤞(仅供参考,回购正在积极维护中)。
预测强度—一种简单但相对未知的评估聚类的方法
原文:https://towardsdatascience.com/prediction-strength-a-simple-yet-relatively-unknown-way-to-evaluate-clustering-2e5eaf56643?source=collection_archive---------20-----------------------
照片由 nrd 在 Unsplash 拍摄
了解该标准如何工作,以及如何从头开始用 Python 实现它!
有很多内容(书籍、博客帖子、教程等。)的内容,以及在 k-means 聚类等算法中寻找最佳聚类数的各种方法:间隙统计、剪影得分、臭名昭著的肘(scree)图等等。
多亏了新冠肺炎和新发现的大量额外空闲时间,我终于可以回到我积压的书籍中,完成安德烈·布尔科夫的优秀作品百页机器学*书籍。这本书很好地概述了机器学*的各个方面,并鼓励读者深入他们感兴趣的话题。在阅读关于无监督学*和聚类算法的章节时,我遇到了一种评估聚类算法性能的新方法——预测强度。
经过快速搜索,我没有找到类似的文章,我确实认为这种方法很有趣,值得另起炉灶。所以让我们开始吧!
理论介绍
许多用于确定算法(如 k-means)的最佳聚类数的流行方法都是基于类内平方和(WSS)。该度量基于观测值和聚类质心之间的距离。一般来说,WSS 越低,观测值越接*质心,这表明拟合度越高。但是,我们需要在 WSS 和聚类数之间找到一个平衡点,因为无限增加聚类数(直到观察次数)总是会得到更好的拟合。
[1]中建议的预测强度方法从机器学*的角度来看识别最佳聚类数的问题。
我们将算法分解为以下步骤:
- 将数据集分成训练集(X_tr)和测试集(X_te)。
- 使用某个值 k (聚类数)对两个集合运行聚类算法。
- 创建大小为
n_test
xn_test
的共同隶属矩阵 D[C(X_tr,k),X_te],其中n_test
是测试集中的观察值数量,C(X_tr,k)是适合训练集的聚类算法(在我们的例子中是 k-means)。 - 如果测试集的元素 I 和 I '属于同一聚类,则将共同隶属矩阵的第 ii '个元素设置为 1,否则将其设置为 0。
- 以便测量训练集质心预测测试集中的共同成员的程度。对于分配到同一测试聚类的每对测试观察值(在共同隶属矩阵中值为 1),我们基于训练集质心确定它们是否也被分配到同一聚类。
下面来自[1]的图片说明了这个想法:
训练和测试指的是数据集。来源:【1】
6.聚类的预测强度 C(.k)定义为:
其中 n_kj 是第 j 个星团中的观测值数量。
7.对于每个测试聚类,我们使用训练集质心计算该聚类中被分配到同一个聚类的观察对的比例。预测强度是这个量在 k 个测试集群中的最小值。
我们对所有考虑的集群大小运行上述算法的步骤 2-7。然后,我们选择预测强度高于某个阈值的最大聚类大小。作者进行的实验表明 0.8-0.9 是一个很好的阈值。
这可能有点难以理解,所以我建议仔细研究几次这个算法,以便理解这个想法。查看后面部分的代码也会有所帮助。
为了使这个过程更容易,我将尝试提供一些预测强度方法背后的直观解释。假设所选的聚类数等于数据集中的真实聚类数。然后,训练群集将类似于测试群集,并将很好地预测它们。因此,预测强度会很高。
相反,当所选的聚类数高于最佳聚类数时,附加的训练和测试聚类很可能是不同的,这将导致预测强度的较低值。
用 Python 实现
是时候用 Python 实现预测强度算法了。我们将使用该标准来选择玩具数据集上 k-means 聚类中的最佳聚类数。此外,我们还将展示经典的肘图方法进行比较。首先,我们导入所有需要的库:
然后,我们使用make_blobs
生成一个 2 维玩具数据集,其中有 3 个明显分开的簇。为了再现性,我们固定随机状态。
下图显示了生成的数据集。
生成数据后,我们应用 k 均值聚类。首先,我们使用肘图方法来确定最佳聚类数。我们将聚类的最大数量设置为 9。
在 k 均值聚类的scikit-learn
实现中,inertia_
属性存储总的类内平方和(WSS)。我们绘制了结果图:
我们可以清楚地看到“肘”点—它对应于 3 个集群,这与我们人工生成的数据相符。
是时候实现预测强度算法了。我的实现基于[3]中提供的实现,做了一些修改以使代码更简单易读。我们首先将数据分成训练集和测试集。为此,我们使用了scikit-learn
中的train_test_split
函数。我们采用 80-20 的分层比例。
在处理主函数之前,我们需要定义一个辅助函数。它用于确定给定观测值的最*质心(使用欧几里德距离)。
现在,我们定义主函数。在前半部分,我们创建并填充共同成员矩阵。我们使用嵌套循环和一组条件来确定矩阵中每个元素的正确值。在后半部分,我们计算每个聚类的预测强度,并选择最小值作为最终结果。
准备好函数后,我们为每个聚类大小拟合 k 均值聚类,并计算预测强度。请记住,在每次迭代中,我们实际上必须分别为训练集和测试集采用两种 k-means 算法。
下面我们可以看到绘制的结果。按照算法的逻辑,我们应该选择预测强度值高于指定阈值(在这种情况下为 0.8)的最大聚类大小。我们可以看到推荐的集群大小是 3。
结论
在本文中,我介绍了相对未知的聚类算法评估标准——预测强度,并展示了如何在 Python 中将它实现为一个自定义函数。您可以在下一次处理集群问题时尝试一下!
关于算法(R 中)的稍微不同但等价的实现,请参见[2]。这种方法可能更容易理解,因为作者减少了要检查的嵌套循环和条件的数量。
我们还可以应用于玩具示例的另一件事是置信区间,特别是对于非确定性聚类算法。它们基于多次计算预测强度和计算接收结果的平均值和标准偏差。记住,要这样做,我们必须从 k-means 聚类类中删除固定的随机状态。
您可以在我的 GitHub 上找到本文使用的代码。一如既往,我们欢迎任何建设性的反馈。你可以在推特或评论中联系我。
如果您对本文感兴趣,您可能也会喜欢:
[## 在 scikit-learn 中编写自定义输入程序
了解如何创建自定义估算器,包括用于更高级用例的 groupby 聚合
towardsdatascience.com](/coding-a-custom-imputer-in-scikit-learn-31bd68e541de) [## 使用投票分类器的集成学*
了解如何使用集成学*的变体来利用多个模型的优势
levelup.gitconnected.com](https://levelup.gitconnected.com/ensemble-learning-using-the-voting-classifier-a28d450be64d) [## 以 scikit-learn 方式创建基准模型
了解如何为分类和回归问题创建一系列基准模型
towardsdatascience.com](/creating-benchmark-models-the-scikit-learn-way-af227f6ea977)
参考
[1] Tibshirani,r .,& Walther,G. (2005 年)。通过预测强度进行聚类验证。计算与图形统计杂志, 14 (3),511–528。—https://www . stat . Washington . edu/wxs/stat 592-w 2011/Literature/TiB shirani-walther-prediction-strength-2005 . pdf
https://github.com/echen/prediction-strength
[3]https://github . com/aburkov/theMLbook/blob/master/prediction _ strength . py
预测分析:用 TensorFlow 中的 LSTM、GRU 和比尔斯特姆进行回归分析
原文:https://towardsdatascience.com/predictive-analysis-rnn-lstm-and-gru-to-predict-water-consumption-e6bb3c2b4b02?source=collection_archive---------3-----------------------
在 Unsplash 上的this is 工程拍摄
关于开发 LSTM、GRU 和比尔斯特姆模型进行用水量多步预测的分步指南
在这篇文章中,我开发了三个连续模型;LSTM、GRU 和双向 LSTM,预测气候变化影响下的用水量。然后,我用最可靠的一个对未来 10 年的城市用水量进行多步预测。
首先,让我提醒你一下基本面。然后,我将带您完成一个完整的 Python 数据科学项目。
👩💻 上的 Python 代码 GitHub
递归神经网络
递归神经网络(RNN)是一种设计用于使用时序数据的神经网络。在 RNNs 中,输出可以作为输入反馈到网络中,创建一个循环结构。
梯度消失问题
通过反向传播来训练 rnn。在反向传播过程中,RNNs 会遇到梯度消失问题。梯度是用于更新神经网络权重的值。梯度消失问题是当梯度随着时间向后传播而收缩时。因此,梯度较小的层不会学*,它们会导致网络具有短期记忆。
💡❓ 渐变消失问题的解决方案是什么
长短期记忆
长短期记忆(LSTM)是一种专门的 RNN,以减轻梯度消失的问题。LSTMs 可以使用一种称为 gates 的机制来学*长期依赖关系。这些门可以了解序列中哪些信息是重要的,应该保留或丢弃。LSTMs 有三个门;输入,忘记,输出。
LSTM 细胞的结构
双向 LSTMs
双向 lstm(BiSTM)的思想是在 LSTM 模型中聚合特定时间步长的过去和未来的输入信息。在 BiLSTM 中,在任何时间点,您都可以保存过去和未来的信息。
门控循环单元
门控递归单元(GRU)是新一代的神经网络,非常类似于 LSTM。GRU 摆脱了细胞状态,使用隐藏状态来传递信息。GRU 和 LSTM 的另一个区别是 GRU 只有两个大门;复位和更新门。
GRU 细胞的结构
☺时间让我们的手 dirty❗
资料组
加拿大魁北克省的 Brossard 市被选为研究地点。这座城市是蒙特利尔大都市区的一部分。本项目日用水量数据取自 2011 年 9 月 1 日至 2015 年 9 月 30 日。收集同期最低气温、最高气温和总降水量。这些气候变量的测量数据来自加拿大环境部。
导入库
设置随机种子
设置随机种子以在每次运行代码后获得相同的结果。
**# Set random seed for reproducibility**
tf.random.set_seed(1234)
步骤 1:读取和浏览数据
在这个项目中,我正在处理多变量时间序列数据。当我从 CSV 文件导入数据时,我通过 parse_dates = ['Date'] 确保 Date 列具有正确的 DateTime 格式。此外,当我处理日期和时间时,如果我将日期列设置为 dataframe 索引,就会变得容易得多。
**# Read file**
file = 'Data.csv'
raw_data = pd.read_csv(file, parse_dates = ['Date'],
index_col = 'Date')
df = raw_data.copy()
- Max_T:最高温度(℃)
- Min_T:最低温度(℃)
- T_P:总降水量(毫米)
- UWC:城市用水量(立方米/人.天)
**# Define a function to draw time_series plot**
def timeseries (x_axis, y_axis, x_label, y_label):
plt.figure(figsize = (10, 6))
plt.plot(x_axis, y_axis, color ='black')
plt.xlabel(x_label, {'fontsize': 12})
plt.ylabel(y_label, {'fontsize': 12})timeseries(df.index, df['WC (m3/capita.day)'], 'Time (day)','Daily Water consumption ($m^3$/capita.day)')
2011 年 9 月 1 日至 2015 年 9 月 30 日的日用水量时间序列
第二步:数据预处理
数据预处理是最耗时的步骤,包括:
- 处理缺失值
- 替换异常值
- 将数据集拆分为训练和测试数据
- 拆分目标变量和因变量
- 数据转换
- 创建 3D 输入数据集
2.1 处理缺失值
对于时间序列数据,使用线性插值替换缺失值是一个好主意。
**# Check missing values**
df.isnull().sum()
**# Replace missing values by interpolation**
def replace_missing (attribute):
return attribute.interpolate(inplace=True)replace_missing(df['Max_T'])
replace_missing(df['Min_T'])
replace_missing(df['T_P'])
replace_missing(df['UWC'])
2.2 替换异常值
我使用统计方法来检测异常值。统计方法假设数据点呈正态分布。因此,低概率区域中的值被视为异常值。我在统计方法中应用了最大似然的概念,这意味着超出μ 2σ范围的值被标记为异常值。注意,在正态分布的假设下,μ 2σ包含 95%的数据。
**# Outlier detection**
up_b = df['UWC'].mean() + 2*df['UWC'].std()
low_b = df['UWC'].mean() - 2*df['UWC'].std()**# Replace outlier by interpolation for base consumption**
df.loc[df['UWC'] > up_b, 'UWC'] = np.nan
df.loc[df['UWC'] < low_b, 'UWC'] = np.nan
df['UWC'].interpolate(inplace=True)
2.3 将数据集分为训练和测试数据
在这个项目中,我将前 80%的数据设置为训练数据,剩下的 20%为测试数据。我用训练数据训练模型,并用测试数据验证其性能。
**# Split train data and test data**
train_size = int(len(df)*0.8)
train_dataset, test_dataset = df.iloc[:train_size],
df.iloc[train_size:]**# Plot train and test data**
plt.figure(figsize = (10, 6))
plt.plot(train_dataset.UWC)
plt.plot(test_dataset.UWC)
plt.xlabel('Time (day)')
plt.ylabel('Daily water consumption ($m^3$/capita.day)')
plt.legend(['Train set', 'Test set'], loc='upper right')print('Dimension of train data: ',train_dataset.shape)
print('Dimension of test data: ', test_dataset.shape)
训练数据和测试数据的预处理日用水量时间序列
2.4 拆分目标变量和因变量
UWC 是目标变量(输出),是因变量(输入)的函数;Max_T,Min_T 和 T_P。
**# Split train data to X and y**
X_train = train_dataset.drop('UWC', axis = 1)
y_train = train_dataset.loc[:,['UWC']]**# Split test data to X and y**
X_test = test_dataset.drop('UWC', axis = 1)
y_test = test_dataset.loc[:,['UWC']]
2.5 数据转换
一个很好的经验法则是,规范化的数据会在神经网络中产生更好的性能。在这个项目中,我使用来自 scikit-learn 的 MinMaxScaler 。
我为输入和输出定义了不同的标量,因为它们有不同的形状。这对于使用逆变换功能尤其重要。
- X_train.shape: (1192,3)
- y_train.shape: (1192,1)
- X_test.shape: (299,3)
- y_test.shape: (299,1)
务必确保输出的比例在 0–1 范围内,以匹配 LSTM、GRU 和比尔斯特姆输出层的激活函数(tanh)的比例。此外,输入变量最好是小值,可能在 0-1 的范围内。
💡****steps❓有哪些数据转换
- 使用可用的训练数据拟合定标器(MinMaxScaler)(这意味着使用训练数据估计最小和最大可观测值。)
- 将缩放器应用于训练数据
- 将定标器应用于测试数据
值得注意的是,我们应该使用训练数据上安装的缩放器来缩放不可见的数据。
**# Different scaler for input and output**
scaler_x = MinMaxScaler(feature_range = (0,1))
scaler_y = MinMaxScaler(feature_range = (0,1))**# Fit the scaler using available training data**
input_scaler = scaler_x.fit(X_train)
output_scaler = scaler_y.fit(y_train)**# Apply the scaler to training data**
train_y_norm = output_scaler.transform(y_train)
train_x_norm = input_scaler.transform(X_train)**# Apply the scaler to test data**
test_y_norm = output_scaler.transform(y_test)
test_x_norm = input_scaler.transform(X_test)
2.6 创建 3D 输入数据集
LSTM、GRU 和比尔斯特姆采用 3D 输入(样本数、时间步数、特征数)。因此,我创建了一个助手函数, create_dataset ,来重塑输入。
在这个项目中,我定义 time_steps = 30。这意味着模型基于最* 30 天的数据进行预测(在 for 循环的第一次迭代中,输入携带前 30 天,输出是第 30 天的 UWC)。
**# Create a 3D input**
def create_dataset (X, y, time_steps = 1):
Xs, ys = [], []
for i in range(len(X)-time_steps):
v = X[i:i+time_steps, :]
Xs.append(v)
ys.append(y[i+time_steps])
return np.array(Xs), np.array(ys)TIME_STEPS = 30X_test, y_test = create_dataset(test_x_norm, test_y_norm,
TIME_STEPS)
X_train, y_train = create_dataset(train_x_norm, train_y_norm,
TIME_STEPS)
print('X_train.shape: ', X_test.shape)
print('y_train.shape: ', y_train.shape)
print('X_test.shape: ', X_test.shape)
print('y_test.shape: ', y_train.shape)
步骤 3:创建比尔斯特姆、LSTM 和 GRU 模型
3.1 tensor flow 中的比尔斯特姆、LSTM 和 GRU 模型
第一个函数, create_model_bilstm ,创建一个 BDLSM 并获取隐藏层中的单元(神经元)数量。第二个函数 create_model 获得两个输入;隐藏层中的单元数量和模型名称(LSTM 或 GRU)。
为了简单起见,比尔斯特姆、LSTM 和 GRU 在输入层有 64 个神经元,一个隐藏层包括 64 个神经元,在输出层有 1 个神经元。
为了使 LSTM 和 GRU 模型对变化具有鲁棒性,使用了下降函数。掉线(0.2) 随机掉线 20%的单位。
**# Create BiLSTM model**
def create_model_bilstm(units):
model = Sequential()
model.add(Bidirectional(LSTM(units = units,
return_sequences=True),
input_shape=(X_train.shape[1], X_train.shape[2])))
model.add(Bidirectional(LSTM(units = units)))
model.add(Dense(1))
**#Compile model**
model.compile(loss='mse', optimizer='adam')
return model**# Create LSTM or GRU model**
def create_model(units, m):
model = Sequential()
model.add(m (units = units, return_sequences = True,
input_shape = [X_train.shape[1], X_train.shape[2]]))
model.add(Dropout(0.2))
model.add(m (units = units))
model.add(Dropout(0.2))
model.add(Dense(units = 1))
**#Compile model**
model.compile(loss='mse', optimizer='adam')
return model**# BiLSTM**
model_bilstm = create_model_bilstm(64)**# GRU and LSTM**
model_gru = create_model(64, GRU)
model_lstm = create_model(64, LSTM)
3.2 拟合模型
我用 100 个时期和批量 = 32 的训练数据训练模型。我让模型使用 20%的训练数据作为验证数据。我设置 shuffle = False 是因为它提供了更好的性能。
为了避免过度拟合,我设置了一个提前停止,当验证损失在 10 个周期后没有改善时(耐心= 10)停止训练。
**# Fit BiLSTM, LSTM and GRU**
def fit_model(model):
early_stop = keras.callbacks.EarlyStopping(monitor = 'val_loss',
patience = 10)
history = model.fit(X_train, y_train, epochs = 100,
validation_split = 0.2, batch_size = 32,
shuffle = False, callbacks = [early_stop])
return historyhistory_bilstm = fit_model(model_bilstm)
history_lstm = fit_model(model_lstm)
history_gru = fit_model(model_gru)
绘制列车损失和验证损失
在此图中,我将查看每个模型中的时期数,并评估模型在预测中的性能。
**# Plot train loss and validation loss**
def plot_loss (history):
plt.figure(figsize = (10, 6))
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.ylabel('Loss')
plt.xlabel('epoch')
plt.legend(['Train loss', 'Validation loss'], loc='upper right')plot_loss (history_bilstm)
plot_loss (history_lstm)
plot_loss (history_gru)
BiLSTM 的列车损失与验证损失
LSTM 的列车损失与验证损失
GRU 的列车损失与验证损失
3.3 逆变换目标变量
建立模型后,我必须使用scaler _ y . inverse _ transform将目标变量转换回原始数据空间,用于训练和测试数据。
y_test = scaler_y.inverse_transform(y_test)
y_train = scaler_y.inverse_transform(y_train)
3.4 使用比尔斯特姆、LSTM 和 GRU 进行预测
在这里,我用比尔斯特姆、LSTM 和 GRU 模型预测 UWC。然后,我绘制了三个模型的真实未来(测试数据)与预测。
**# Make prediction**
def prediction(model):
prediction = model.predict(X_test)
prediction = scaler_y.inverse_transform(prediction)
return predictionprediction_bilstm = prediction(model_bilstm)
prediction_lstm = prediction(model_lstm)
prediction_gru = prediction(model_gru)**# Plot true future vs prediction**
def plot_future(prediction, y_test):
plt.figure(figsize=(10, 6))
range_future = len(prediction)
plt.plot(np.arange(range_future), np.array(y_test),
label='True Future')
plt.plot(np.arange(range_future),np.array(prediction),
label='Prediction')
plt.legend(loc='upper left')
plt.xlabel('Time (day)')
plt.ylabel('Daily water consumption ($m^3$/capita.day)')plot_future(prediction_bilstm, y_test)
plot_future(prediction_lstm, y_test)
plot_future(prediction_gru, y_test)
BiLSTM 模型的真实未来与日用水量预测
LSTM 模型的真实未来与日用水量预测
GRU 模型的真实未来与日用水量预测
3.5 计算 RMSE 和梅
让我用两个拟合优度来评估模型的性能。
**# Define a function to calculate MAE and RMSE**
def evaluate_prediction(predictions, actual, model_name):
errors = predictions - actual
mse = np.square(errors).mean()
rmse = np.sqrt(mse)
mae = np.abs(errors).mean()print(model_name + ':')
print('Mean Absolute Error: {:.4f}'.format(mae))
print('Root Mean Square Error: {:.4f}'.format(rmse))
print('')evaluate_prediction(prediction_bilstm, y_test, 'Bidirectional LSTM')
evaluate_prediction(prediction_lstm, y_test, 'LSTM')
evaluate_prediction(prediction_gru, y_test, 'GRU')
三个模型的拟合优度表明它们具有非常相似的性能。即便如此,与 LSTM 和 GRU 相比, BiLSTM 模型具有更高的准确性。因此,我使用 BiLSTM 模型对 UWC 未来 10 年进行多步预测。
⚠️ 注意:这个项目的结果并不意味着 BiLSTM 比 LSTM 和 GRU 有更好的结果。这只是说明如何比较这些模型,以得出最可靠的预测。
步骤 4:10 年用水量的多步预测
我在研究地点导入气候数据预测,并对 2015 年 1 月 1 日至 2025 年 1 月 1 日期间的数据进行过滤。
我创建了一个助手函数, plot_history_future ,来绘制历史和未来的 UWC。然后,我创建了一个函数, forecast,来重塑看不见的输入,并使用 LSTM 模型进行预测。
**# Plot histoy and future data**
def plot_history_future(y_train, prediction):
plt.figure(figsize=(10, 6)) range_history = len(y_train)
range_future = list(range(range_history, range_history +
len(prediction))) plt.plot(np.arange(range_history), np.array(y_train),
label='History')
plt.plot(range_future, np.array(prediction),label='Prediction')
plt.legend(loc='upper right')
plt.xlabel('Time (day)')
plt.ylabel('Daily water consumption ($m^3$/capita.day)')**# Multi-step forecasting**
def forecast(X_input, time_steps):
**# Scale the unseen input with the scaler fitted on the train set**
X = input_scaler.transform(X_input)
**# Reshape unseen data to a 3D input**
Xs = []
for i in range(len(X) - time_steps):
v = X[i:i+time_steps, :]
Xs.append(v) X_transformed = np.array(Xs)**# Make prediction for unseen data using LSTM model**
prediction = model_bilstm.predict(X_transformed)
prediction_actual = scaler_y.inverse_transform(prediction)
return prediction_actualprediction = forecast(X_new, TIME_STEPS)
plot_history_future(y_train, prediction)
基于 BiLSTM 模型的日用水量历史与预测
结论
感谢您阅读这篇文章。我知道这是一个相当长的教程😏我希望它能帮助你在 Tensorflow 中为一个数据科学项目开发 LSTM、GRU 和比尔斯特姆模型😊
非常感谢您的反馈。你可以在 LinkedIn 上找到我。
预测分析作为提高营销效率的工具
原文:https://towardsdatascience.com/predictive-analytics-as-a-tool-to-increase-marketing-efficiency-5b4b9d922524?source=collection_archive---------50-----------------------
来源:沉积照片
收集和存储数据的能力越来越强,为企业提供了更强的追溯和实时分析能力。现在,我们可以追踪模式并得出失败的结论,以免重蹈覆辙。或者我们可以确定最成功的解决方案,并重复我们的成功。
从长远来看,预测分析总是比回顾性或实时分析更有效,就像预防比紧急医疗护理更有效一样。回顾性分析本质上是一次解剖——对一个无法挽回的错误的分析。实时分析是此时此地做出反应的救护车,而预测分析是从一开始就将你从疾病中拯救出来的预防医学。
预测分析的概念
正如托马斯·达文波特所说,没有人有能力收集和分析来自未来的数据。但是我们有机会利用过去的数据预测未来。这被称为预测分析,事实上,许多公司已经在使用它。您可以使用过去的数据来:
- 计算客户的终身价值(CLV)。这个指标将帮助你了解客户在一生中会给你的公司带来什么价值,包括未来的收益。
- 根据你网站的用户行为数据开发最佳推荐。
- 预测客户将来可能会购买什么产品或服务。
- 预测客户流失。
- 制定下一季度/六个月/一年的销售计划和预测。
所有这些都是预测分析的简单形式。让我们看看流行的预测分析方法。
预测建模
我们可以确定预测建模的以下阶段:
- 原始数据收集
- 统计模型形成
- 预测
- 随着额外数据的出现,检查/修订模型
预测模型分析用户过去的行为,以评估他们在未来表现出特定行为的可能性。这种类型的分析还涉及发现数据中微妙模式的模型,例如检测欺诈。
通常,当用户在执行转换操作的途中通过转换漏斗时,预测模型会立即进行计算,例如,评估用户实现目标的概率。有了关于从漏斗中的一个步骤过渡到另一个步骤的可能性的准确数据,企业可以更好地管理阻止或帮助用户通过漏斗的因素,并且可以更准确地描述不同类别的客户的行为模式。
您可以在哪里使用预测分析?
普通用户的智能手机上大约有 50 个应用程序。它们中的每一个都接收、传输和生成数据。这些数据以不同的格式存储在不同的服务中。虽然乍一看,这似乎是营销人员的一个积极因素,但有效地处理如此大量的结构化和非结构化数据是一个问题。
让我们看几个成功应用预测分析结果的公司的例子。
亚马逊使用预测营销…
…根据用户过去的行为向他们推荐产品和服务。根据一些报告,这种推荐给亚马逊带来了高达 30%的销售额。此外,亚马逊计划开发一种工具,根据预测,甚至在订单在网站上下单之前,就可以将产品送到预期订单所在的区域,从而缩短向客户交付商品的时间。
梅西百货
梅西的团队利用预测分析进行更准确的直接营销。在三个月的时间里,该公司通过捕捉用户浏览的产品类别数据并相应地发送个性化电子邮件,将其在线销售额从 8%提高到 12%。
哈雷戴维森使用预测分析…
…锁定潜在客户,吸引潜在客户,达成交易。他们识别出准备购买的最有价值的潜在客户。然后,销售代表直接联系这些潜在客户,并引导他们通过销售过程找到最合适的报价。
缝针
StitchFix 是另一家拥有独特的基于预测的销售模式的零售商。注册 StitchFix 时,用户需要完成一项关于他们风格的调查。然后应用预测分析模型为顾客提供他们最可能想要的衣服。如果顾客不喜欢他们收到的衣服,他们可以免费退货。
Sprint 使用人工智能算法来识别有流失风险的客户…
…并预防性地提供关于如何保留它们的必要信息。Sprint 的人工智能预测客户想要什么,并在他们最有可能离开公司的时候为他们提供报价。自从引入这一人工智能系统以来,Sprint 的流失率大幅下降,客户对该公司的个性化服务和有针对性的优惠给予了优异的评价。如您所见,预测客户流失是 SaaS 和电子商务企业预测分析的一项可行任务。
以下是预测分析范围内最受欢迎的指标列表:
- 客户外流比率(流失率)
- 销售计划预测
- 客户终身价值
如何实施预测分析?
如果没有营销和分析部门的合作,没有对研究目标和数据既定顺序的理解,引入预测分析是不可能的。执行预测分析的过程如下:
- 定义你的假设
- 收集内部和外部数据以构建模型
- 定义度量标准来衡量模型的准确性
- 使用现成的服务或开发自己的服务:
- 建立一个 MVP
- 在缺少准确性参数的情况下训练模型,以获得稳定的工作版本
- 创建界面或报告
- 更新或重新训练模型以满足新的要求
在数据收集阶段,确保您已经建立了端到端分析,因为没有它,实施预测分析通常是无效的。
预测分析服务
根据德勤(Deloitte)的《CMO 调查:2019 年春季报告》,基于营销分析的商业决策比例在 2019 年初达到峰值(考虑到过去六年的数据)。根据 MarketsandMarkets 的一项研究,预测分析市场将从 40 亿美元增长到 2022 年的 120 亿美元以上
对营销分析的普遍兴趣,尤其是对预测分析的兴趣,鼓励公司开发易于使用的解决方案和服务,使企业更容易获得预测分析。
以下是其中一些服务:
OWOX 商业智能洞察
- OWOX BI 产品帮助公司实现营销目标,并以高于市场平均水平 22%的速度增长。
- G2 在“营销软件-分析”和“电子商务分析软件”类别中的 2019 年春夏排行榜中名列前茅。
- 将有关营销计划实施的预测直接发送到您的电子邮件中。
图片由作者提供
OWOX BI:
- 结合各种来源的营销数据,使其可用于 Google BigQuery 的分析。
- 使用自己的基于漏斗的归因模型确定每个用户步骤的价值。
- 自动构建报告以分析营销效果。
- 展示您的销售计划将如何实施,您的增长领域和弱点是什么,以及您的市场份额如何变化。
暗示
Infer 提供的预测模型将帮助您结合所有数据源,全面了解您的销售线索在销售漏斗中的位置。推断跟踪来自在线来源和公共数据库的信号,然后根据以前的主要账户和您设定的规则创建预测模型。Infer 获得的数据将有助于营销人员和销售专家寻找未来可能转化为客户的线索,并优化整体销售漏斗。
半径
Radius 提供几种数据分析服务,重点是预测性 B2B 营销。主要特性包括:
- Radius 客户交换(RCX),将您的公司简介与拥有相同受众的其他公司进行比较,让您有机会一起工作并创建自己的营销列表。
- Radius 连接:向 Salesforce 提交预测数据。
Radius 平台还帮助营销人员在部门之间交换数据,并在内部数据库中找到新账户。和 Infer 一样,Radius 也是一个基于云的系统。
板
基于预测建模的规则,BOARD 在一个具有实时仪表板的自适应界面中工作。
这意味着您可以对各种场景建模并分析可能的结果,而不必每次都创建新的模型。
BOARD 带有几个内置连接器,因此您可以从几乎任何来源提取数据——您的 ERP 系统、云数据库、OLAP 魔方,甚至平面文件。你也可以使用 BOARD 的工具将你的预测转化为定制应用。
TIBCO 数据科学
TIBCO 数据科学是一款相对较新的产品,于 2018 年 9 月发布。TIBCO Data Science 作为一个单一平台创建,结合了 TIBCO 前几代服务的功能:TIBCO Statistica、Spotfire Data Science、Spotfire Statistics Services 和 TERR。
数据科学服务帮助组织更快地创新和解决复杂问题,将预测快速转化为最佳解决方案。
SAS 高级分析
SAS 拥有预测分析市场 33%的份额和 40 年的经验;它们为用户提供了基于许多可视化编辑器的高级数据分析功能。SAS 高级分析的主要功能基于图表、自动流程图、嵌入式代码和自动时间规则。
根据用户评论,SAS Advanced Analytics 在预测和分析整体移动方面表现出色,可以相对较快地处理大型数据集。SAS 提供免费的产品演示和知识库来帮助您开始使用它们。
快速采矿机
该软件允许您根据时间间隔自动创建报告。由于 60 多个内置集成,您可以导入自己的数据集,并将其导出到其他程序。
扩展提供了更大的灵活性(异常检测、文字处理、web 挖掘),但可能不包括在基本订阅价格中
虽然 RapidMiner 是为数据科学家设计的,但它很容易安装和开始使用。
IBM SPSS
IBM SPSS 使用基于统计的数据建模和分析。该软件适用于结构化和非结构化数据。它可以在云中、本地或通过混合部署来满足任何安全性和移动性要求。
您可以使用现有数据在 SPSS 可视化编辑器和建模仪表板中构建预测模型。对非结构化数据的高级支持包括语言技术和自然语言处理,因此您可以在模型中包括来自社交网络和其他基于文本的来源的数据。
SAP HANA
SAP HANA 在本地或云中提供数据库和应用程序。该软件通过为大型外部数据集和直观可视化添加连接器,减少了创建模型所需的时间。
您还可以将预测分析库(PALs)连接到 SAP HANA,以从大型数据集获得额外的洞察力。对于以客户为中心的行业,该软件提供文本和社交媒体数据分析,以预测未来的客户行为,并根据过去的行为推荐产品。
SAP HANA 与 R 编程语言兼容,因此您不需要学*新的语言来配置您的查询。当您的系统集成了足够多的内部数据时,预测模型会自动提供新的见解。
总结
营销中的预测分析是一个强大的数据科学工具,其功能无法在一篇文章中涵盖。
提醒一下,以下是预测分析的三条戒律:
- 从基础开始:检查数据的质量,并自动收集数据以消除人为错误。训练模型的质量取决于训练数据的质量。
- 永远不要远离你研究的目标,因为重要的不是过程,而是结果。
- 遵守精度要求。请记住,您的预测结果只能通过测量经过验证的模型在应用于您的数据时的准确性来验证。
支持向量机(SVM)和 Plotly 的客户预测分析
原文:https://towardsdatascience.com/predictive-analytics-on-customer-behavior-with-support-vector-machines-svm-7e68fd2be610?source=collection_archive---------12-----------------------
现实世界中的数据科学
围绕客户行为和人口统计的大数据的兴起,为利用预测分析的数字营销战略打开了一个可能性的世界。
营销和客户分析是当今世界最热门的数据科学应用领域之一。为了利用可用数据,现代企业需要分析工具来提供他们所需的洞察力,以提供个性化的消费者体验。在本文中,我们将探索一种被称为支持向量机(SVM)的监督机器学*算法。像这样的分类算法可以增加我们对客户的了解,并改进我们的营销和参与策略。
美国宇航局在 Unsplash 拍摄的照片
背景
现代客户的特点是他们对控制、连通性和便利性的需求。竞争日益激烈的全球市场将控制权交到了客户手中。当他们想要的时候,他们知道自己想要什么。惊喜!就是现在。
社交媒体和其他资源赋予了客户权力,使他们能够研究、探索、分享和比较。现代消费者关注其他人的评论和意见,一个感性的评论可以成就一个品牌,也可以毁掉一个品牌。
最后,现代消费者已经完全颠覆了对便利的传统理解。现代技术创造了对媒体和服务的期望,只需按一下按钮就可以获得。很快,Alexa 就会在我们用完纸巾的前一天,根据世界各地流感爆发的数据,结合我们认为她没在听时记录的喷嚏频率,自动给我们送来一盒新纸巾。(这是我在 Covid 打之前写的…)
目标
换句话说,真正的便利意味着客户需要的产品会来到他们身边。为了在顾客所在的地方见到他们,你必须了解他们。个人主义时代创造了独特的消费者,他们只会对迎合他们的营销体验做出反应。
通过这个项目,我们将探索汽车保险销售的客户数据。我们的目标是发现什么样的营销方法对特定的客户群最有效。到这个项目结束时,我们将能够根据客户的人口统计数据和过去的行为数据来预测客户是否会对销售电话做出回应。
在我的 GitHub 上找到数据和 Jupyter 笔记本
首先,我们将首先探索我们的客户群…
使用 Plotly 进行探索性数据分析(EDA)
导入包。Plotly 是 Python 中现代数据可视化的标准。
我们对这个项目感兴趣的主要变量是“响应”。它是一个二元变量,表示客户是否对营销电话作出了回应。
接下来,我们将探讨销售人员采取的行动如何影响回复率。这些因素是销售渠道和更新报价类型。为了快速执行描述性分析,我们将利用 Plotly Express ,一个 Plotly 图形对象的高级包装器。
从第一张图中,我们发现代理人的成功率似乎最高。第二个图表显示,要约类型 3 和 4 相对无效。
现在,让我们探索一些人口统计信息,看看什么类型的客户最有可能对我们的营销优惠做出回应。
受教育程度较高的人似乎不太可能对工作做出回应。与第一张图表类似,拥有豪华汽车的客户似乎不太可能对报价做出反应。
如何才能进一步探究财富与回复率之间看似负相关的关系?
该图进一步支持了当前的营销努力对低收入客户更有效的观点。但是,它也显示了这个样本中的大多数客户都属于低收入阶层。
在我们进入分类模型之前,让我们看看哪些特征与我们的响应变量具有最强的相关性。
连续变量回归分析
当因变量为二元时,逻辑回归是适当的回归分析。逻辑回归用于描述数据,并解释一个因变量和一个或多个自变量之间的关系。
在这种情况下,我们将使用逻辑回归来确定哪些变量(如果有的话)对客户响应销售电话的概率有影响。
我们可以从收入的 p 值、每月保费汽车、自上次索赔以来的月数、自保单生效以来的月数、公开投诉数量、保单数量中看到,这些输入变量似乎与目标变量响应具有显著关系。“coef”栏告诉我们,这些变量都与响应负相关。
我们如何解释 P 值?
p 值评估样本数据支持零假设的程度。在这种情况下,我们的零假设是变量对于预测因变量 Response 是不重要的。
p 值只有在与 alpha 值比较时才有用。小于标准α值 0.05 的 p 值可被认为对因变量有显著影响。
换句话说,p 值是在零假设为真的情况下,观察到该样本中变量之间这种关系的概率。
如果在随机抽取样本的人群中,零假设是正确的,那么在我们现有的样本量中,得到至少和我们得到的一样极端的检验统计量的可能性有多大?彼得·弗洛姆
分类变量回归分析
标签编码
大多数机器学*算法需要将分类变量转换为数值,并且许多算法的性能根据分类变量的编码方式而变化。在这种情况下,我们所有的分类数据都是名义数据,而不是序数数据。
如您所见,每个类别都被赋予一个从 1 到 N 的值(其中 N 是特性的类别数。)
婚姻状况、续保类型、销售渠道、车辆大小、政策变量的 p 值在 0.05 显著性水平上显著。同样,这些变量与响应有负关系。
连续变量和分类变量的回归分析
我将让您自己检查这个输出。你能告诉我们在分类模型中包含哪些重要的变量吗?一个有趣的观察是,具有更高客户终身价值的客户似乎不太可能响应营销电话。
那么,为什么我们花了这么多时间去寻找“重要的关系”呢?这是被称为特征工程的过程的一部分。如果我们想要使用分类算法来预测未来的客户是否会对营销电话作出响应,我们想要查看那些与因变量有显著关系的特征(变量的别称)。去掉对结果没有影响的变量有很多好处。它不仅降低了模型中的噪声,还降低了模型训练所需的处理能力。
支持向量机分类算法
支持向量机是一种监督 ML 算法,可用于分类和回归。在此算法中,每个数据项都被绘制为 n 维空间中的一个点(其中 n 是您拥有的要素数量。)然后,找到在 N 维空间中最好地分离类别的超平面。
让我们用这幅插图来探索一下超平面的概念,这是我花了太长时间拼凑的:
支持向量是来自最接*超平面的每个类的数据点。SVM 的目标是最大化两个阶级之间的差距。如果我们移动上面例子中的一个支持向量,超平面也会随之移动。
在我们没有像上面例子那样的线性可分数据的情况下(这在现实中是经常发生的),内核的技巧就派上用场了。内核技巧背后的思想是将非线性可分离的数据映射到一个更高维的空间,在那里我们可以创建一个超平面来实际分离这些类。请看这张令人惊叹的 GIF 图片:
我们将把内核技巧留给另一个项目。现在,让我们继续把我们的数据分成训练集和测试集。这是数据科学过程中的一个关键步骤,它允许您诚实地评估模型的性能。这一过程有助于保护您的模型不过度拟合。但是,如果您的样本不能代表您希望将模型应用到的人群,那么您如何对数据进行分割并不重要。
我们将使用的另一种方法是交叉验证。如下图所示,它将数据分割成您选择的 K 个(在本例中,K=5)集合。K-1 个子集用于训练我们的数据,最后一个子集用于测试。我们将 K 个“折叠”的平均准确度作为我们的最终度量。
有关训练/测试分割和交叉验证的更多信息,请查看本文
Scikit-Learn 屡试不爽。让我们看看这个模型能做什么。
正如我们所看到的,训练/测试分割和交叉验证技术都产生了非常可靠的指标。基于这一结果,我们对利用这一模型预测客户回复率的能力充满信心。
结论
如果给我们一份客户名单和他们的人口统计数据,我们可以利用从这个项目中收集到的洞察力来制定关于如何与该客户互动的战略决策。
感谢阅读!我希望这篇文章既有趣又有见地。我很开心地完成了我的第一篇文章,也很难放下我的完美主义,点击发表,哈哈。我欢迎任何建设性的反馈。随时在 LinkedIn 上联系我!
预测分析:用 TensorFlow 中的 GRU 和比尔斯特姆进行时间序列预测
原文:https://towardsdatascience.com/predictive-analytics-time-series-forecasting-with-gru-and-bilstm-in-tensorflow-87588c852915?source=collection_archive---------0-----------------------
Enrique Alarcon 在 Unsplash 上拍摄的照片
为时序预测构建 GRU 和双向 LSTM 的分步教程
R 当前的神经网络被设计用来处理时序分析中序列相关性的复杂性。在本教程中,我为一个单变量时间序列预测模型建立 GRU 和比尔斯特姆。门控循环单元(GRU)是新一代的神经网络,非常类似于长短期记忆(LSTM)。而双向 lstm(bil STM)的思想是在 LSTM 模型中聚合特定时间步长的过去和未来的输入信息。
下面这篇文章很好地介绍了 LSTM、GRU 和比尔斯特姆。
[## 预测分析:TensorFlow 中的 LSTM、GRU 和双向 LSTM
关于开发 LSTM、GRU 和双向 LSTM 模型来预测用水量的分步指南
towardsdatascience.com](/predictive-analysis-rnn-lstm-and-gru-to-predict-water-consumption-e6bb3c2b4b02)
什么是时间序列分析?
与回归分析不同,在时间序列分析中,我们没有强有力的证据表明什么影响了我们的目标。时间序列分析使用时间作为变量之一,以观察是否随时间发生变化。
什么是时间序列预测?
时间序列预测的目的是根据历史数据拟合一个模型,并使用它来预测未来的观测值。这篇文章致力于使用深度学*方法进行时间序列预测。如果你愿意学*时间序列预测的经典方法,我建议你阅读这个网页。
☺让我们去 code❗
👩💻 上的 Python 代码 GitHub
资料组
对于本项目,数据为加拿大魁北克省 Brossard 市 2011 年 9 月 1 日至 2015 年 9 月 30 日的日用水量。
导入库
import pandas as pd
import numpy as np
import matplotlib.pyplot as pltfrom sklearn.preprocessing import MinMaxScaler, StandardScalerimport warnings
warnings.filterwarnings(‘ignore’)from scipy import stats
%matplotlib inlineimport tensorflow as tf
from tensorflow import keras
from tensorflow.keras import Sequential, layers, callbacks
from tensorflow.keras.layers import Dense, LSTM, Dropout, GRU, Bidirectional
设置随机种子
tf.random.set_seed(1234)
1.读取和浏览数据
在这个项目中,我处理的是单变量时间序列数据。当我从 CSV 文件导入数据时,我通过 parse_dates = ['Date'] 确保 Date 列具有正确的 DateTime 格式。此外,当我处理日期和时间时,如果我将日期列设置为 dataframe 索引,就会变得容易得多。
df = pd.read_csv(‘Data.csv’, parse_dates = [‘Date’])
1.1 时间序列图
为了更好地理解数据,我绘制了每日、每月和每年的用水量。
**# Define a function to draw time_series plot**def timeseries (x_axis, y_axis, x_label):
plt.figure(figsize = (10, 6))
plt.plot(x_axis, y_axis, color =’black’)
plt.xlabel(x_label, {‘fontsize’: 12})
plt.ylabel(‘Water consumption ($m³$/capita.day)’,
{‘fontsize’: 12})
dataset = df.copy()
timeseries(df.index, dataset[‘WC’], ‘Time (day)’)dataset[‘month’] = dataset.index.month
dataset_by_month = dataset.resample(‘M’).sum()
timeseries(dataset_by_month.index, dataset_by_month[‘WC’],
‘Time(month)’)dataset[‘year’] = dataset.index.year
dataset_by_year = dataset.resample(‘Y’).sum()
timeseries(dataset_by_year.index, dataset_by_year[‘WC’],
‘Time (month)’)
日用水量时间序列
你可以看到数据有一个季节性的模式。
月用水量时间序列
年用水量时间序列
1.2 处理缺失值
首先,我想检查缺失值的数量,并确定没有数据值存储的日期。然后我使用线性插值来替换丢失的值。
**# Check for missing values**
print(‘Total num of missing values:’)
print(df.WC.isna().sum())
print(‘’)
**# Locate the missing value**
df_missing_date = df.loc[df.WC.isna() == True]
print(‘The date of missing value:’)
print(df_missing_date.loc[:,[‘Date’]])**# Replcase missing value with interpolation**
df.WC.interpolate(inplace = True)**# Keep WC and drop Date**
df = df.drop('Date', axis = 1)
1.3 将数据集分为训练和测试数据
像我通常做的那样,我将前 80%的数据设置为训练数据,剩下的 20%为测试数据。我用训练数据训练模型,并用测试数据验证其性能。
💡提醒一下,您必须使用 iloc 根据索引位置找到数据帧的子集
**# Split train data and test data**
train_size = int(len(df)*0.8)
train_data = df.iloc[:train_size]
test_data = df.iloc[train_size:]
1.4 数据转换
一个很好的经验法则是,规范化的数据会在神经网络中产生更好的性能。在这个项目中,我使用来自 scikit-learn 的 MinMaxScaler 。
您需要遵循三个步骤来执行数据转换:
- 使用可用的训练数据拟合定标器(MinMaxScaler)(这意味着使用训练数据估计最小和最大可观测值。)
- 将缩放器应用于训练数据
- 将定标器应用于测试数据
💡需要注意的是, MinMaxScaler()的输入。fit() 可以是数组状或数据帧状(n_samples,n_features)。在这个项目中:
train_data.shap = (1192,1)
scaler = MinMaxScaler().fit(train_data)
train_scaled = scaler.transform(train_data)
test_scaled = scaler.transform(test_data)
1.5 创建输入
GRU 和比尔斯特姆采用一个三维输入(数量 _ 样本,数量 _ 时间步长,数量 _ 特征)。因此,我创建了一个助手函数 create_dataset ,来重塑输入。
在这个项目中,我定义 look_back = 30。这意味着模型基于最* 30 天的数据进行预测(在 for-loop 的第一次迭代中,输入携带前 30 天,输出是第 30 天的用水量)。
**# Create input dataset**
def create_dataset (X, look_back = 1):
Xs, ys = [], []
for i in range(len(X)-look_back):
v = X[i:i+look_back]
Xs.append(v)
ys.append(X[i+look_back])
return np.array(Xs), np.array(ys)LOOK_BACK = 30X_train, y_train = create_dataset(train_scaled,LOOK_BACK)
X_test, y_test = create_dataset(test_scaled,LOOK_BACK)**# Print data shape**
print(‘X_train.shape: ‘, X_train.shape)
print(‘y_train.shape: ‘, y_train.shape)
print(‘X_test.shape: ‘, X_test.shape)
print(‘y_test.shape: ‘, y_test.shape)
2.创建模型
第一个函数, create_bilstm ,创建一个 BiDLSM 并获取隐藏层中的单元(神经元)数量。第二个函数, create_gru ,构建一个 gru 并获得隐藏层中的单元数。
两者在输入层都有 64 个神经元,一个隐层包括 64 个神经元,在输出层有 1 个神经元。两个模型中的优化器都是 亚当 。为了使 GRU 模型对变化具有鲁棒性,使用了下降函数。掉线(0.2) 随机掉线 20%的单位。
**# Create BiLSTM model**
def create_bilstm(units):
model = Sequential()
**# Input layer**
model.add(Bidirectional(
LSTM(units = units, return_sequences=True),
input_shape=(X_train.shape[1], X_train.shape[2])))
**# Hidden layer**
model.add(Bidirectional(LSTM(units = units)))
model.add(Dense(1))
**#Compile model**
model.compile(optimizer=’adam’,loss=’mse’)
return modelmodel_bilstm = create_bilstm(64)**# Create GRU model**
def create_gru(units):
model = Sequential()
**# Input layer**
model.add(GRU (units = units, return_sequences = True,
input_shape = [X_train.shape[1], X_train.shape[2]]))
model.add(Dropout(0.2))
**# Hidden layer**
model.add(GRU(units = units))
model.add(Dropout(0.2))
model.add(Dense(units = 1))
**#Compile model**
model.compile(optimizer=’adam’,loss=’mse’)
return modelmodel_gru = create_gru(64)
2.1 拟合模型
我创建一个函数, fit_model ,获取模型并用 100 个时期和 batch_size = 16 的训练数据训练模型。我让模型使用 20%的训练数据作为验证数据。我设置 shuffle = False 是因为它提供了更好的性能。
为了避免过度拟合,我设置了一个提前停止,当验证损失在 10 个周期后没有改善时(耐心= 10)停止训练。
def fit_model(model):
early_stop = keras.callbacks.EarlyStopping(monitor = ‘val_loss’,
patience = 10)
history = model.fit(X_train, y_train, epochs = 100,
validation_split = 0.2,
batch_size = 16, shuffle = False,
callbacks = [early_stop])
return historyhistory_gru = fit_model(model_gru)
history_bilstm = fit_model(model_bilstm)
2.2 目标变量的逆变换
建立模型后,我必须使用scaler . inverse _ transform将目标变量转换回训练和测试数据的原始数据空间。
y_test = scaler.inverse_transform(y_test)
y_train = scaler.inverse_transform(y_train)
3.评估模型的性能
我们将如何评价 GRU 和比尔斯特姆的表现?
1-绘制训练损失和验证损失
为了评估模型性能,我绘制了训练损失与验证损失的关系图,我预计验证损失低于训练损失😉
2-比较预测和测试数据
首先,我用比尔斯特姆和 GRU 模型预测 WC。然后,我绘制了两个模型的测试数据与预测。
3-计算 RMSE 和梅
我使用两种拟合优度来评估模型的准确性。
3.1 绘制列车损失和验证损失
def plot_loss (history, model_name):
plt.figure(figsize = (10, 6))
plt.plot(history.history[‘loss’])
plt.plot(history.history[‘val_loss’])
plt.title(‘Model Train vs Validation Loss for ‘ + model_name)
plt.ylabel(‘Loss’)
plt.xlabel(‘epoch’)
plt.legend([‘Train loss’, ‘Validation loss’], loc=’upper right’)
plot_loss (history_gru, ‘GRU’)
plot_loss (history_bilstm, ‘Bidirectional LSTM’)
3.2 比较预测和测试数据
**# Make prediction**
def prediction(model):
prediction = model.predict(X_test)
prediction = scaler.inverse_transform(prediction)
return predictionprediction_gru = prediction(model_gru)
prediction_bilstm = prediction(model_bilstm)**# Plot test data vs prediction**
def plot_future(prediction, model_name, y_test):
plt.figure(figsize=(10, 6))
range_future = len(prediction)
plt.plot(np.arange(range_future), np.array(y_test),
label=’Test data’)
plt.plot(np.arange(range_future),
np.array(prediction),label=’Prediction’) plt.title(‘Test data vs prediction for ‘ + model_name)
plt.legend(loc=’upper left’)
plt.xlabel(‘Time (day)’)
plt.ylabel(‘Daily water consumption ($m³$/capita.day)’)
plot_future(prediction_gru, ‘GRU’, y_test)
plot_future(prediction_bilstm, ‘Bidirectional LSTM’, y_test)
3.3 计算 RMSE 和梅
def evaluate_prediction(predictions, actual, model_name):
errors = predictions — actual
mse = np.square(errors).mean()
rmse = np.sqrt(mse)
mae = np.abs(errors).mean()
print(model_name + ‘:’)
print(‘Mean Absolute Error: {:.4f}’.format(mae))
print(‘Root Mean Square Error: {:.4f}’.format(rmse))
print(‘’)evaluate_prediction(prediction_gru, y_test, ‘GRU’)
evaluate_prediction(prediction_bilstm, y_test, ‘Bidirectiona LSTM’)
4.30 天用水量的多步预测
为了使用经过训练的 GRU 和比尔斯特姆模型进行预测,我需要至少 60 天的观察数据来预测未来 30 天的情况。为了便于说明,我从观测数据中选择了 60 天的用水量,并用 GRU 和比尔斯特姆预测了未来 30 天的用水量。
**# Make prediction for new data**
def prediction(model):
prediction = model.predict(X_30)
prediction = scaler.inverse_transform(prediction)
return predictionprediction_gru = prediction(model_gru)
prediction_bilstm = prediction(model_bilstm)**# Plot history and future**
def plot_multi_step(history, prediction1, prediction2):
plt.figure(figsize=(15, 6))
range_history = len(history)
range_future = list(range(range_history, range_history +
len(prediction1))) plt.plot(np.arange(range_history), np.array(history),
label='History')
plt.plot(range_future, np.array(prediction1),
label='Forecasted for GRU')
plt.plot(range_future, np.array(prediction2),
label='Forecasted for BiLSTM')
plt.legend(loc='upper right')
plt.xlabel('Time step (day)')
plt.ylabel('Water demand (lit/day)')
plot_multi_step(new_data, prediction_gru, prediction_bilstm)
结论
感谢您阅读这篇文章。我希望它能帮助你在 Tensorflow 中开发用于时间序列预测的 GRU 和比尔斯特姆模型😊
非常感谢您的反馈。你可以在 LinkedIn 上找到我。
预测性早期停止——一种元学*方法
原文:https://towardsdatascience.com/predictive-early-stopping-a-meta-learning-approach-90561f0e9454?source=collection_archive---------44-----------------------
作者:Dhruv Nair,数据科学家,Comet.ml
介绍
预测性提前停止是一种用于加速模型训练和超参数优化的最新方法。我们的基准研究表明,预测性早期停止可以加快模型训练多达 30%的底层基础设施独立。
我们基于从学*曲线外推、超带和中位数停止等项目中收集的见解,以创建一个预测模型,可以估计亏损曲线的收敛值。
Comet 能够利用其平台的公共部分的超过200 万个模型的模型数据,如超参数和损耗曲线,来创建一个模型,该模型的预测可以跨超参数和模型架构进行推广。
在某些情况下,我们能够在收敛实际发生之前的数百个时期提供收敛的估计。除了预测收敛值之外,我们的预测提前停止产品还提供了当前模型优于当前训练扫描中看到的最佳模型结果的概率估计。
在某些情况下,我们能够在收敛实际发生之前的数百个时期提供收敛的估计。
这些预测允许我们终止表现不佳的模型的训练,以便搜索过程只评估最有希望的候选人。
基准测试:
我们在三种不同的设置中测试了我们的预测性早期停止方法:
- 一种超参数搜索,用于优化充当神经网络代理的函数的参数
- 使用 SMAC 优化器在 CIFAR10 上优化 6 层 CNN 的超参数搜索,具有和不具有预测性早期停止。
- 使用具有超波段的随机搜索与具有预测性提前停止的随机搜索来优化相同的 6 层 CNN 的超参数搜索。
代理函数的结果:
在我们的第一个测试中,我们设置了一个指数衰减函数作为神经网络的代理。我们将这个代理模型运行了 20 步,并使用 Comet 的贝叶斯优化器和预测性提前停止来确定这个函数的参数的最佳值。在超参数搜索过程中,我们观察到不允许次优模型训练完整的 20 个步骤。图 1 ,说明了我们的停止机制。
SMAC 的 CNN 模型的结果:
我们对 CNN 模型的基准测试是以如下方式建立的:
我们使用 SMAC 优化器来估计 6 层 CNN 模型中的以下超参数。模型超参数和结构基于 AlexNet。
{
"learning_rate":{
"type":"loguniform",
"value":[0.0000001, 0.01]
},
"learning_rate_decay":{
"type": "uniform",
"value":[0.000001, 0.001]
},
"weight_decay": {
"type": "loguniform",
"value": [0.0000005, 0.005]
}
}
我们对优化器进行了 8 次测试,包括有无预测性提前停止。每个优化器试验都有 6 个小时的预算来评估尽可能多的配置。允许每个超参数配置最多训练 100 个时期,并且在每个时期结束时评估验证集。我们的预测性提前停止模型使用验证损失来确定是否终止超参数配置。
在所有试验结束时,我们确定了所有试验中试验损失的平均值,作为达到该损失值所需的超参数扫描中总次数的函数。
我们可以在图 2 中看到,使用预测性早期停止允许 SMAC 获得可比的损失值,几乎快了 300 个时代。这减少了 25%的超参数优化时间。
我们还根据最终验证损失,将超参数配置划分为分位数。然后,我们计算了优化器在所有试验的每个分位数上花费的平均时期数。
在图 3 中,我们看到 SMAC 和预测性提前停止 SMAC 花费大致相同的时间来评估前 25%和前 50%的配置。然而,预测性早期停止在结果的后 50%中花费少 30 个时期训练模型,在后 25%中花费少 20 个时期。
在图 4 中,我们看到了预测性提前停止的超参数扫描的样本损失曲线。次优配置会在允许的训练步骤总数之前停止。
具有超波段的 CNN 模型的结果:
我们以类似于 SMAC 的方式为 Hyperband 设置了测试。我们特别使用了在 Optuna 中实现的异步连续二等分普鲁纳。我们可以认为这是一个带有单个括号的超带。我们随机选择了 120 个超参数配置。每个配置被分配了最少 10 个时期的资源,并且被允许训练最多 100 个时期。这导致最大培训预算为 12000 个纪元。
在每个评估点,基于最差的验证损失,配置的数量减少 N 倍。在我们的实验中,我们评估了 N 值为 2、4 和 8 的超带。
对于预测性提前停止,我们使用不同的间隔参数值测试了每个配置。每 10、15 和 20 个时期评估一次配置。在每一次评估中,我们都会估计当前配置优于目前最佳配置的可能性。如果这个概率小于一个阈值,在我们的例子中是 90%,我们终止当前的配置。阈值和间隔都是用于预测性早期停止的可配置超参数。
然后,我们确定超参数扫描中实现的最佳验证损失,以及扫描后预算中剩余的历元数。
在图 5a 中,我们看到所有方法都找到了验证损失的最佳值,然而,预测性提前停止仅使用总预算的 15%就能评估配置,相比之下,Hyperband 使用了 25%。这在速度上提高了 10%。
结论
预测性提前停止具有非常明显的时间、能量和成本节约优势。浪费计算周期对环境或研究人员的预算都没有好处。
艾伦人工智能研究所最*发表了一份报告,报告内容是关于训练机器学*模型的计算成本不断上升,以及这些日益增长的能源需求如何对环境产生不利影响。该论文指出,当前最先进的人工智能研究进展主要集中在准确性或误差等指标上,代价是对环境不友好。他们称这种模式为红色人工智能。为了对抗红色人工智能研究的盛行,他们提出了向强调计算效率的人工智能研究的转变:绿色人工智能。
该论文建议根据生成结果所需的浮点运算(FPO)总数来跟踪人工智能算法的效率。FPO 的总数与调整期间评估的超参数配置的数量以及每个配置上花费的训练迭代次数直接相关。
我们希望我们在预测性早期停止方面的努力有助于提高超参数搜索过程的计算效率。我们认为这个工具是降低人工智能研究相关货币壁垒的一种方式,也是朝着采用绿色人工智能实践迈出的一步。
在我们的下一篇文章中,我们将描述在不属于较大参数搜索的单独运行中应用预测性早期停止。
*购买 Comet Teams 或 Comet Enterprise 后,预测性提前停止功能可作为附加功能提供。正在通过一项或多项未决专利申请寻求对预测性提前停车的专利保护。
了解更多信息并在此注册。
预测销售线索评分
原文:https://towardsdatascience.com/predictive-lead-scoring-cefd8240778c?source=collection_archive---------4-----------------------
在 Unsplash 上由 Carlos Muza 拍摄的照片
如今,成功的现代公司通过利用数据驱动的模型和见解,在了解其客户、产品和服务方面进行了大量投资。什么是预测性销售线索评分?为什么它对公司收购和销售策略的成功很重要?在客户旅程的每个阶段,您如何开发一个线索评分模型来优化具有预期质量的客户和潜在客户的数量?营销和销售团队如何有效地监控预测的销售线索得分,以及跟踪销售线索的质量和绩效?
我将回顾预测性销售线索评分的基本概念以及添加到营销和销售运营中的商业价值。然后,我将解释如何得出销售线索得分阈值,并系统地监控客户和潜在客户的表现,以推动最佳的销售线索质量和数量。
什么是预测性销售线索评分?
销售线索评分是关键的营销自动化任务之一,用于锁定正确的客户和潜在客户,并提高营销和销售团队的生产力和效率。预测性销售线索评分将传统的销售线索评分方法提升到了一个新的水平,方法是应用大数据和机器学*算法来评估现有客户和潜在客户的关键行为,并根据一个可以区分更有可能转化、保留或购买公司产品和服务的客户和潜在客户的量表对其进行排名。首先,预测性销售线索评分根据反映客户和潜在客户感知价值的标准生成一个可跟踪的指标。其次,它允许营销团队开展更有针对性的活动和投资,以最大限度地提高营销支出的投资回报率。第三,它通过优化销售团队与高质量客户和潜在客户打交道的时间和精力,提高了销售团队的效率和生产力。最后但同样重要的是,它通过协调收购和销售目标,提高了整体转化率和购买率。
如何开发预测性销售线索评分模型?
预测性销售线索评分流程从识别现有和潜在客户生成的数据和评分属性开始。确定优化的目标指标很重要——无论是转化率、保留率、产出还是服务质量等。此外,您需要根据一组关键属性训练销售线索评分模型,该模型可以捕捉客户生命周期的不同方面。该模型评估与客户和潜在客户相关联的各种属性和所识别的行为(即,客户购买)之间的关系,并基于实现所识别的行为的倾向对它们进行评分。
照片由胡玮炜在媒体上拍摄
预测性销售线索评分模型包括哪些关键属性?
- 客户档案数据衡量您的客户和潜在客户的核心档案属性。这些属性可能包括客户的人口统计信息,如年龄、位置、职称、行业、任期以及角色细分。
- 帐户档案数据反映了重要的公司地理属性,如公司规模、行业和帐户类型等。
- 客户意向数据衡量现有和潜在客户对特定产品和服务的兴趣,以及他们与您的营销团队或销售代表接触的意愿。
- 客户参与数据捕捉重要的客户活动,包括电子邮件活动,如 CTO、CTR,网站活动,如访问、表单填写、产品页面浏览或下载、来宾帐户创建、免费或付费试用激活、网上研讨会或活动出席等。
- 客户购买数据捕获现有客户的购买活动,包括购买您的产品和服务的质量和金额,以及他们购买的时间和频率。
- 营销和销售绩效还提供了关于营销和销售计划和活动有效性的重要信息。表现出色的项目和活动通常可以揭示公司营销和销售活动的范围和影响的关键见解。此外,当营销和销售团队执行计划和活动时,他们从各种渠道获取客户和潜在客户,如直接、付费、有机搜索、推荐、社交媒体等。确定表现最佳的渠道将使团队能够更有效地与客户和潜在客户互动,并帮助发现各种渠道的优化策略。
一旦您收集了这些关键数据点,这些与客户或潜在客户相关的信息将被整合到系统中,同时触发预测性销售线索评分模型。整合的数据将流经预测性销售线索评分模型,该模型将科学地评估这些确定的属性与目标行为之间的关系。
好模式与坏模式
在开发您的销售线索评分模型时,训练几个模型并执行适当的模型验证是非常有用的,以便选择预测部署最准确的最佳模型。例如,AUC 是比较模型的好指标。一个好的模型将产生更高的 AUC,其中具有更高预测销售线索得分的客户最有可能对应于实际购买,而质量差的客户几乎没有购买该公司产品或服务的动机。另一方面,一个糟糕的线索评分模型可能会产生更多的“错误”,这意味着该模型要么会错过预测已经购买的高质量客户,要么会高估未成熟客户的质量。这意味着一个糟糕的模型往往会产生相对较少的真阳性(TP),但是会产生比你预期的更多的假阳性(FP)。
照片由胡玮炜在媒体上拍摄
如何评价预测线索评分模型的性能?
在您训练评分模型后,预测的销售线索得分是如何工作的?市场营销和销售团队能否信任模型得出的分数,并根据预测的销售线索分数确定目标客户和潜在客户?要评估评分模型的性能,您可以将预测的销售线索得分应用于已完成销售周期的真实客户。
照片由胡玮炜在媒体上拍摄
如左图所示,预测销售线索得分≥91 的前 10%客户几乎达到了累计购买百分比的 23%。专注于前 10%的客户可以覆盖给定时间段内总客户购买量的* 23%。同样,将预测销售线索得分≥75 分的前 30%客户作为目标客户,将允许团队覆盖客户购买总量的 2/3 以上。随着您的团队有能力覆盖更多的客户,在达到前 40%-50%的客户后,累积收益的提升开始下降。建议的销售线索评分阈值是立即与质量更高的前 40% -50%的客户合作。对于预测销售线索得分较低的客户和潜在客户,他们需要首先通过有针对性的信息培育计划进行热身。因此,很明显,营销和销售团队可以通过关注高质量的线索来实现生产力和效率的显著提升。
如何监控客户和潜在客户的质量?
营销和销售团队将需要建立收购和销售目标,并制定实现这些目标的策略。营销和销售团队如何有效地监控客户和潜在客户的质量,并优先考虑最有可能购买的人群?团队可以考虑以下用例,并决定他们希望如何在日常业务运营中利用预测的销售线索得分。
- 根据预测的销售线索得分有效地细分客户和潜在客户,并将其放入不同的类别。如下表所示,仅关注预测销售线索得分≥75 分的热情销售线索将使团队覆盖客户总购买量的 84%。但是,如果他们花时间瞄准这些冷线索,他们预计只能覆盖客户购买量的 4%。
照片由胡玮炜在中拍摄
- 系统监控预测销售线索得分和客户购买率之间的关系。在下面的图表中,当您从图表的左侧移动到右侧时,几乎可以立即看出预测销售线索得分和客户购买率之间有很强的正相关关系。因此,它向您的营销和销售团队发出了一个强烈的信号,要求他们优先关注高质量而不是低质量的客户。
由胡玮炜在媒体上拍摄的照片
- 准确提供关于关键优化指标的宝贵见解。在这种情况下,您可以利用预测销售线索评分模型,深入了解哪些客户特征和行为属性对购买率的贡献最大,并揭示表现最佳的渠道、计划和活动等。
总之,预测性销售线索评分为现代公司取得成功提供了必要的信息。它不仅揭示了基于从现有和潜在客户以及产品和服务中收集的实时数据,哪些客户和潜在客户最有可能转变、保留甚至购买的关键见解,而且还帮助公司基准化和揭示关键优化指标,并一致地跟踪关键客户概况和细分,以便描绘出现有和潜在客户群中哪些销售良好而哪些销售不佳的完整画面。
如果你觉得这篇文章有帮助,请告诉我。如果您有任何问题或想法要分享,请随时发表评论。
阅读更多:
- 了解和预测客户终身价值(CLTV)
- 衡量客户生命周期成功指标
- 从客户生命周期分析中获得的六大经验
预测性维护:利用 CRNN 和光谱图检测传感器故障
原文:https://towardsdatascience.com/predictive-maintenance-detect-faults-from-sensors-with-crnn-and-spectrograms-e1e4f8c2385d?source=collection_archive---------34-----------------------
应用深度学*和频谱图转换来防止故障
詹姆斯·托马斯在 Unsplash 上拍照
预测性维护是各个领域的一个活跃的研究领域。特别是在最*几年,机器学*解决方案出现了巨大的发展。一些企业投入大量资金来开发能够提前预测在商业活动中可能发生的故障的解决方案。
这些研究的一个有趣领域是物联网行业,我们有传感器来监控机器或特定引擎部件的工作状态。解决这类问题的经典方法通常包括采用时间序列模型和信号处理技术,使我们能够从高频数据中提取价值。
在这篇文章中,我们采用深度学*架构来执行预测性维护任务,以处理我们用光谱图预处理的高频数据序列。这一步使我们能够采用一种特定的神经网络结构,称为卷积递归神经网络(CRNN) ,它同时从我们数据的空间和递归结构中学*。
数据
我们的任务需要研究压力条件下的液压管道,以便跟踪系统特定部分的活动状态。
该数据集是用液压试验台通过实验获得的。该试验台由通过油箱连接的一次工作回路和二次冷却过滤回路组成。当四个液压部件(冷却器、阀门、泵和蓄能器)的状态定量变化时,系统周期性地重复恒定负载循环(持续时间 60 秒)并测量过程值,如压力、体积流量和温度。
这些数据是由 UCI 储存库(液压系统状态监控)收集的,我们都很熟悉,因为我在以前的帖子中使用过这些数据来开发预测性维护解决方案。现在,我们的范围始终是开发一种能够检测故障的机器学*解决方案,但我们对处理高频数据感兴趣。因此,我们利用以 100 Hz 采样的压力数据(每个传感器 6000 个属性:总共 6 个)来建立一个模型,该模型将蓄能器的状态分为四类(最佳压力、稍微降低的压力、严重降低的压力、接*完全失效)。
光谱图变换
处理这种原始数据的第一步包括充分的预处理阶段。数据只是被分成固定的、相同的标记序列,我们的职责是从这些信息来源中提取价值。如前所述,我们采用光谱图对这些信号片段进行预处理,并输入 CRNN。频谱图是信号的时频画像。它们是信号频率成分强度随时间变化的曲线图。它们在音频处理/分类中被广泛采用,并且由于它们在高频域中映射数据行为的能力而对我们有用。为了应用声谱图变换,我们必须首先降低级数的幅度;一个简单的区分,加上一个适当的剪辑来限制极端的变化,听起来不错。以下是由 6 个不同压力信号组成的原始和标准化序列的示例:
用 python 计算光谱图相当容易;Librosa 是一个提供这种功能的好库。我们对每一个压力系列都进行了转换,所以我们对每一个样品都进行了 6 个光谱图的转换,而不是原始信号的转换。
单个压力信号的频谱图示例
模型
卷积和递归神经网络是构建深度学*模型最常见和最强大的结构。CNN 和 rnn 并不相互排斥,因为两者都可以对图像和文本输入进行分类,从而为结合两种网络类型以提高效率创造了机会。如果要分类的输入在视觉上是复杂的,并且增加了 CNN 单独无法处理的时间特性,则尤其如此。
CRNN 架构示例
典型地,当这两种类型的网络结合时,有时称为 CRNN,输入首先由 CNN 层处理,其输出然后被馈送到 RNN 层。这些混合架构正被开发用于视频场景标记、光学字符识别或音频分类等应用。对于我们的分析,我们将先前生成的光谱图输入 CRNN,以检测液压管道中蓄能器的工作状态。每个观察值现在由叠加的光谱图组成(总共 6 个,每个压力信号一个)。在 Keras 语言中,我们可以这样复制 CRNN:
def get_model(data):
inp = Input(shape=(data.shape[1], data.shape[2], data.shape[3]))
x = Conv2D(filters=64, kernel_size=(2, 2), padding='same')(inp)
x = BatchNormalization(axis=1)(x)
x = Activation('relu')(x)
x = MaxPooling2D(pool_size=(2, 1))(x)
x = Dropout(0.2)(x)
x = Permute((2, 3, 1))(x)
x = Reshape((data.shape[2], -1))(x) x = Bidirectional(GRU(64, activation='relu',
return_sequences=False))(x)
x = Dense(32, activation='relu')(x)
x = Dropout(0.2)(x)
out = Dense(y_train.shape[1], activation='softmax')(x)
model = Model(inputs=inp, outputs=out)
model.compile(loss='categorical_crossentropy',
optimizer='adam', metrics=['accuracy'])
return model
在第一阶段,网络从频谱图中提取卷积特征,保留结构频率 x 时间 x n _ 特征。当我们传递到递归部分时,我们需要以格式time x n _ features:time对我们在卷积级别和频谱图中观察到的维度进行整形;新的 n_features 是在卷积 n_features 和频率上计算的谄媚操作的结果。
最后,我们的模型在我们的测试集上可以达到大约 86%的准确率。
摘要
在这篇文章中,我执行了一项预测性维护任务,对液压管道中特定类型的组件的工作状态进行了分类。在预处理阶段,我们可以应用原始高频压力信号的频谱图变换和强大的 CRNN 作为模型结构,从我们的数据中提取空间和时间特征,从而实现很好的性能。
如果你对题目感兴趣,我建议:
- 预测性维护:用 CNN 检测传感器故障
- 预测性维护与 LSTM 暹罗网络
- 预测性维护与 ResNet
查看我的 GITHUB 回购
保持联系: Linkedin
涡扇发动机的预测维修
原文:https://towardsdatascience.com/predictive-maintenance-of-turbofan-engine-64911e39c367?source=collection_archive---------42-----------------------
使用时间序列数据并询问 RNN“下一次故障何时发生?”
比尔·杰伦在 Unsplash 上的照片
预测性维护对于制造商和维护人员都非常重要,它通过在问题导致设备故障之前解决问题来降低维护成本、延长设备寿命、减少停机时间和提高生产质量。
“预测性维护技术旨在帮助确定在用设备的状况,以便估计何时应该进行维护”——来源维基百科
在这篇文章中,我想展示一下使用 RNN(递归神经网络)/LSTM(长短期记忆)架构不仅更准确,而且与之前由 Marco Cerliani 编写的 CNN(卷积神经网络)方法相比,它在准确分类结果方面表现得更好。
资料组
本帖使用 C-MAPSS 数据集 进行涡扇发动机的预测性维护。这里的挑战是确定剩余使用寿命(RUL) 直到下一次发动机发生故障。
数据集可以在 这里 找到,下面简单介绍一下数据集,
“在每个时间序列开始时,发动机正常运行,但在序列中的某个时间点出现故障。
在训练集中,故障在数量上增长,直到系统故障。
在测试组中,时间序列在系统故障之前的某个时间结束。
以下是模型训练中使用的发动机状况
列车轨迹:100 个
测试轨迹:100 个
条件:一个(海平面)
故障模式:一个(HPC 退化)
了解数据集
加载数据集后,我们将获得 100 台发动机的时间序列数据,其中包含每 100 台发动机的运行设置和传感器读数,以及故障发生的不同场景和总共 20631 个训练示例。举例来说,下面是我们的训练数据集的前 5 个训练示例。
train_df.head()
图 1:训练数据
为了进一步理解给定的数据,(见图 2)描述了对于给定的发动机,在下一个故障发生之前还有多少循环。
例 1:69 号发动机(最左边)在故障前大约还有 360 个循环。
例 2:发动机识别号 39(最右边)在故障前大约还有 110 个循环。
train_df.id.value_counts().plot.bar()
图 2:发动机及其各自的剩余有用循环直到故障
以下(图 3 和图 4)是 id 为 69 的发动机的时间序列数据。
engine_id = train_df[train_df['id'] == 69]ax1 = engine_id[train_df.columns[2:]].plot(subplots=True, sharex=True, figsize=(20,30))
图 3:运行设置 1、2 和 3 的时间序列读数以及 s2 到 s7 的传感器读数
图 4:传感器 s8 直到 s20 的时间序列读数
*图片(图 2、图 3、图 4)使用 Marco Cerliani 的 GitHub Notebook ( 此处 )的源代码获得。
数据预处理
数据预处理是训练任何神经网络的最重要的步骤。对于像 RNN(递归神经网络)这样的神经网络,网络对输入数据非常敏感,数据需要在-1 比 1 或 0 比 1 的范围内。这个范围即-1 比 1 或 0 比 1,通常是因为 tanh ( 见图 5) 是伴随在网络隐层中的激活函数。因此,在训练模型之前,必须对数据进行标准化。
图 5:MathWorks 文档中的 tanh 函数
使用 sklearn 的预处理库提供的最小最大缩放器函数,我们在 0 到 1、的范围内归一化我们的训练数据,尽管理论上我们可以将我们的数据归一化并实验到-1 到 1。然而,这篇文章仅仅展示了数据在 0 到 1 范围内的缩放。
from sklearn.preprocessing import MinMaxScalersc = MinMaxScaler(feature_range=(0,1))
train_df[train_df.columns[2:26]] = sc.fit_transform(train_df[ train_df.columns[2:26]])
train_df = train_df.dropna(axis=1)
使用列号 2 到 26(见图 1)的原因是,我们采用操作设置 1(列号 2)、设置 2、设置 3、传感器 1 直到传感器 21(列 25),python 范围不考虑上限,因此上限为 26。为便于说明,这里是训练数据标准化后的前 5 个训练示例(图 6)。
图 6:训练集的标准化数据
一旦我们将数据标准化,我们就采用一种分类方法来预测 RUL。我们通过以下方式为我们的分类方法在数据集上添加新的标签来做到这一点。
"使用以下源代码:fromGithub"
w1 = 45
w0 = 15train_df['class1'] = np.where(train_df['RUL'] <= w1, 1, 0 )
train_df['class2'] = train_df['class1']
train_df.loc[train_df['RUL'] <= w0, 'class2'] = 2
这段代码现在为我们的分类问题创建标签(见图 7 ),分类方法如下:
标签 0:当剩余 45+个循环后出现故障。
标签 1:当在 16 和 45 之间的周期直到故障时。
标签 2:当在 0 和 15 之间的周期直到故障时。
图 7:添加标签
太好了!现在,我们需要进一步准备数据,以便神经网络有效地处理时间序列数据,我们通过指定时间步长(或窗口大小)来做到这一点。诸如 RNN 或 CNN 之类的神经网络要求输入数据为三维形式。因此,我们现在需要将二维数据转换成三维数据。
为了演示这一转换过程(见图 8),我们简单地通过指定时间步长(窗口大小)来运行时间序列数据。这个过程也被称为滑动窗口技术 。
图 8:来自弹簧连杆的滑动窗口技术
对于我们的时间序列数据,我们将滑动窗口技术用于所有传感器和操作设置,通过指定时间步长(或窗口大小)为 50,尽管时间步长大小可以任意设置。下面的代码片段将我们的二维数据转换为大小为 15631x50x17 的三维数据(numpy pandas 数组),这对于神经网络的输入是最佳的。
“以下源代码修改:来自Github
*time_steps = 50def gen_sequence(id_df):data_matrix = id_df.iloc[2:26]
num_elements = data_matrix.shape[0]for start, stop in zip(range(0, num_elements-time_steps), range(time_steps, num_elements)):
yield data_matrix[start:stop, :]def gen_labels(id_df, label):data_matrix = id_df[label].values
num_elements = data_matrix.shape[0]return data_matrix[time_steps:num_elements, :]x_train, y_train = [], []
for engine_id in train_df.id.unique():
for sequence in gen_sequence(train_df[train_df.id==engine_id]):
x_train.append(sequence)
for label in gen_labels(train_df[train_df.id==engine_id['label2']):
y_train.append(label)x_train = np.asarray(x_train)
y_train = np.asarray(y_train).reshape(-1,1)*
*更多时间序列数据的进一步阅读,请阅读文章( 此处 )。
深度学*模型
RNN/LSTM 在处理时间序列数据方面得到了最好的证明,网上有大量的文章证明了其在广泛应用中的有效性。因此,我们采用 RNN/LSTM 架构。
现在,由于我们的数据已经准备好,并且是三维形式,我们现在可以定义 RNN/LSTM 神经网络架构,该架构包括 2 个隐藏层,每个隐藏层具有激活函数 tanh (见图 5),后面是一层 softmax 分类器。
*model = Sequential()#inputmodel.add(LSTM(units=50, return_sequences='true', activation='tanh',
input_shape = (x_train.shape[1], x_train.shape[2])) )
model.add(Dropout(0.2))#hidden layer 1
model.add(LSTM(units=60, return_sequences='true',activation='tanh'))
model.add(Dropout(0.2))#hidden layer 2
model.add(LSTM(units=60, activation='tanh'))
model.add(Dropout(0.2))#output
model.add(Dense(units=3,activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])print(model.summary())*
这是模型摘要的输出(见图 9)。
图 9:模型架构
培训 RNN/LSTM 模型
RNN/LSTM 模型总共被训练了 30 个时期,尽管我试图训练该模型 40 个时期,该模型被视为过度拟合。
*history = model.fit(x_train, y_train,batch_size=32, epochs=30)*
注:‘历史’变量用于记录模型在训练过程中的损耗、准确度等必要参数。
通过使用 keras.evaluate()函数获得准确度,并且获得接* 94%的总准确度(参见图 10)。
*model.evaluate(x_test, y_test, verbose=2)*
以下代码展示了如何绘制精度和损耗。
*plt.subplot(211)
plt.plot(history.history['accuracy'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['accuracy'], loc='upper left')*
这是模型精度的输出,与 79%的精度相比,获得了大约 94%的精度。我们已经看到了对以前方法的改进。
图 10:模型的准确性
我们获得的模型损耗为 0.12,比 CNN 方法好。
图 11:模型的总损失
这是混淆矩阵(见图 12 ),它更深入地展示了模型在分类中的实际表现。
***cnf_matrix = confusion_matrix(np.where(y_test != 0)[1], model.predict_classes(x_test))plt.figure(figsize=(7,7))plot_confusion_matrix(cnf_matrix, classes=np.unique(np.where(y_test != 0)[1]), title="Confusion matrix")plt.show()***
**** 注:函数-混淆 _ 矩阵()位于 sklearn 文档***
图 12 : 来自 sklearn 文档
结论
在这篇文章中,我们看到了一种替代方法,如何使用 RNN/LSTM 神经网络架构通过解决预测性维护问题,并证明比之前的 CNN 方法更好。**
参考
- https://towards data science . com/playing-with-time-series-data-in-python-959 e 2485 BF F8
- https://towards data science . com/extreme-rare-event-class ification-using-auto encoders-in-keras-a565b 386 f 098
- https://towards data science . com/remaining-life-estimation-with-keras-2334514 f9c 61
涡轮风扇发动机的预测性维护
原文:https://towardsdatascience.com/predictive-maintenance-of-turbofan-engines-ec54a083127?source=collection_archive---------2-----------------------
埃米尔·莫勒纳尔在 Unsplash 上拍摄的照片
探索美国宇航局的涡轮风扇数据集
探索性数据分析和基线线性回归模型
尽管 NASA 的涡扇发动机退化模拟数据集(CMAPSS)发布于十多年前,但至今仍很受欢迎且具有相关性。到目前为止,2020 年已经发表了 90 多篇新的研究论文[1]。这些论文提出并测试了预测涡扇发动机数据集剩余使用寿命(RUL)的新算法。
当我第一次开始学*预测性维护时,我偶然发现了一些使用涡扇发动机退化数据集的博客文章。每篇文章都包括探索性数据分析和预测 RUL 的简单模型,但我觉得缺少两样东西:
- 我从来没有完整地了解如何将不同的合适技术应用于同一问题
- 博客帖子只关注第一个数据集,让我猜测如何解决更复杂的挑战。
几年后,对我来说,这似乎是一个有趣的项目。在一系列的文章中,我计划展示和解释多种分析技术,同时为更复杂的数据集提供一个解决方案。
我已经创建了一个索引,在下面我会更新新帖子的链接:
1.FD001 —探索性数据分析和基线模型(本文)
2。FD001 — 更新了 RUL 的假设&支持向量回归
3。FD001 — 时间序列分析:分布滞后模型
4。FD001 — 预测性维护的生存分析
5。FD003 — 随机森林(我把顺序改了,看文章找原因)
6。Jupyter 笔记本
7 中 NNs 的可重现结果引物。FD002 — 滞后 MLP &基于条件的归一化
8。FD004 — LSTM &总结
涡扇发动机数据集有四个复杂性递增的数据集(见表 1)[2,3]。发动机开始时运转正常,但随着时间的推移出现了故障。对于训练集,引擎运行到故障,而在测试集中,时间序列在故障前“某个时间”结束。目标是预测每台涡扇发动机的剩余使用寿命(RUL)。
表一:涡轮风扇数据集概述
数据集包括多个涡扇发动机随时间的模拟,每行包含以下信息:
1。发动机单元号
2。时间,以周期为单位
3。三种操作设置
4。21 传感器读数
我发现这个数据集真正酷的地方是,你不能使用任何领域知识,因为你不知道传感器一直在测量什么。因此,结果纯粹是基于应用正确的技术。
在今天的帖子中,我们将重点探索第一个数据集(FD001 ),其中所有发动机都出现相同的故障,并且只有一种运行条件。此外,我们将创建一个基线线性回归模型,以便我们可以比较未来帖子的建模工作。
探索性数据分析
让我们从导入所需的库开始,读取数据并检查前几行。请注意,一些列的值似乎没有偏差或偏差很小。我们将在下面进一步探讨这些。
train.head()的结果
接下来,FD001 应该包含 100 台发动机的数据,让我们检查单元号以验证情况是否如此。我选择使用熊猫描述功能,这样我们也可以了解分布情况。当我们这样做的时候,让我们也检查一下时间周期,看看我们能了解到引擎在崩溃之前平均运行的周期数。
unit_nr 和 time_cycles 数据集描述统计
当我们检查 unit_nr 的描述性统计数据时,我们可以看到数据集总共有 20631 行,单元号从 1 开始,到 100 结束。有趣的是,平均值和分位数与 1-100 向量的描述性统计数据并不完全一致,这可以解释为每个单元具有不同的最大 time_cycles,因此行数也不同。当检查最大时间周期时,可以看到最早出现故障的发动机在 128 个周期后出现故障,而运行时间最长的发动机在 362 个周期后出现故障。发动机平均在 199 到 206 个周期之间发生故障,但是 46 个周期的标准偏差相当大。为了更好地理解,我们将在下面进一步想象。
数据集描述还表明涡轮风扇在单一工况下运行。让我们检查设置以进行验证。
发动机设置的描述性统计
观察设置 1 和 2 的标准差,它们并不完全稳定。然而,波动是如此之小,以至于无法识别其他操作条件。
最后,我们将检查传感器数据的描述性统计数据,寻找信号波动的指标(或不存在的指标)。
传感器信号的描述性统计。
通过查看标准偏差,很明显传感器 1、10、18 和 19 根本没有波动,这些传感器可以安全地丢弃,因为它们不包含有用的信息。检查分位数表明传感器 5、6 和 16 波动很小,需要进一步检查。传感器 9 和 14 的波动最大,但这并不意味着其他传感器不能保存有价值的信息。
计算 RUL
在我们开始绘制数据以继续 EDA 之前,我们将计算剩余使用寿命的目标变量(RUL)。目标变量有两个用途:
- 在绘制传感器信号时,它将作为我们的 X 轴,使我们能够轻松地解释发动机接*故障时传感器信号的变化。
- 它将作为我们的监督机器学*模型的目标变量。
没有关于训练集中引擎的 RUL 的进一步信息,我们将不得不提出我们自己的估计。我们将假设 RUL 随时间线性减小,并且在发动机的最后一个时间周期具有 0 值。这种假设意味着击穿前 10 个周期的 RUL 为 10,击穿前 50 个周期的为 50,等等。
数学上我们可以使用max_time_cycle — time_cycle
来计算我们想要的 RUL。因为我们想考虑每个引擎的max_time_cycle
,所以在计算max_time_cycle
之前,我们将按照unit_nr
对数据帧进行分组。然后将 max_time_cycle 合并回数据帧中,以便通过减去列max_time_cycle — time_cycle
来轻松计算 RUL。之后,我们删除max_time_cycle
,因为不再需要它,并检查前几行来验证我们的 RUL 计算。
测绘
为了更好地理解数据集,绘制总是一个好主意。让我们从绘制麦克斯·RUL 的直方图开始,来理解它的分布。
直方图再次证实,大多数发动机在 200 个周期左右就会发生故障。此外,分布是右偏的,很少有发动机能持续超过 300 次循环。
下面我将展示用于绘制每个传感器信号的代码。由于发动机数量众多,为每个传感器绘制每个发动机的图是不可行的。一幅图中有这么多线条,这些图表将不再能被理解。因此,我选择绘制每个 unit_nr 可被 10 整除且余数为 0 的引擎。我们恢复 X 轴,因此 RUL 沿轴减小,RUL 为零表示发动机故障。由于传感器数量众多,我将讨论几个代表整个系列的图表。请记住,根据我们的描述性统计,我们应该明确检查传感器 5、6 和 16 的图形。
S1 与衰落的 RUL 图
传感器 1、10、18 和 19 的图形看起来相似,平坦的线表示传感器没有有用的信息,这再次证实了我们从描述性统计得出的结论。传感器 5 和 16 也显示一条扁平线,这些可以添加到要排除的传感器列表中。
S2 与下降的 RUL 的曲线图
传感器 2 显示出上升趋势,对于传感器 3、4、8、11、13、15 和 17 可以看到类似的模式。
S6 对衰落的 RUL 的图表
传感器 6 的传感器读数有时会下降,但似乎与 RUL 下降没有明显关系。
七国集团对 RUL 的图表
传感器 7 显示下降趋势,这也可以在传感器 12、20 和 21 中看到。
S9 对 RUL 的图表
传感器 9 与传感器 14 具有相似的模式。
基于我们的探索性数据分析,我们可以确定传感器 1、5、6、10、16、18 和 19 不保存与 RUL 相关的信息,因为传感器值始终保持恒定。让我们从基线线性回归模型开始我们的模型开发。该模型将使用剩余的传感器作为预测器。
基线线性回归
首先,我们将定义一个小函数来评估我们的模型。我选择包括均方根误差(RMSE ),因为它将给出预测平均偏离多少时间周期的指示,并解释方差(或 R 得分)以指示我们使用的自变量可以解释我们的因变量的比例。
我们将删除不包含任何信息的unit_nr, time_cycle, settings and sensors
。定型集的 RUL 列存储在自己的变量中。对于我们的测试集,我们删除了相同的列。此外,我们只对测试集中每台发动机的最后一个时间周期感兴趣,因为我们只有这些记录的真实 RUL 值。
线性回归的设置非常简单。我们通过简单地调用方法并将其赋给“lm”变量来实例化模型。接下来,我们通过传递我们的“X_train”和“y_train”来拟合模型。最后,我们对训练集和测试集进行预测,以全面了解我们的模型如何根据提供给它的数据进行操作。
# returns
# train set RMSE:44.66819159545453, R2:0.5794486527796716
# test set RMSE:31.952633027741815, R2:0.40877368076574083
请注意,RMSE 在测试集上较低,这与直觉相反,因为通常模型在训练期间看到的数据上表现更好。
一种可能的解释是,训练集的计算 RUL 范围一直到 300 多。观察下图的趋势,线性计算的 RUL 的较高值似乎与传感器信号没有很好的关联。由于测试集的 RUL 预测更接*失败,并且较低的目标 RUL 和传感器信号之间的相关性更清楚,所以模型更容易对测试集做出准确的预测。训练和测试 RMSE 的巨大差异可以被看作是我们对 RUL 假设的一个缺陷,这也是我们将来要努力改进的地方。现在,我们已经完成了 EDA 和基线模型。
描述线性下降的 RUL 和 S12 的图表。该图旨在展示传感器信号和线性下降的 RUL 强相关的地方。
在今天的帖子中,我们探索了美国宇航局涡扇发动机退化模拟数据集的第一个数据集,并创建了一个测试 RMSE 为 31.95 的基线模型。我要感谢 Maikel Grobbe 和 Wisse Smit 对我的文章的评论。在下一篇文章中,我们将看看如何改进计算出的 RUL,使预测更加准确。此外,我们将开发一个支持向量回归来进一步提高性能。
如果你有任何问题或评论,请在下面的评论中留下。完整的笔记本你可以查看我的 github 页面这里。
参考文献:
[1]2020 年迄今发表在 NASA CMAPSS 数据上的论文: Google scholar search ,2020–08–08
访问[2] A. Saxena,K. Goebel,D. Simon 和 N. Eklund,“飞机发动机运行至故障模拟的损伤传播建模”,载于 2008 年 10 月丹佛市 Ist 国际预测与健康管理会议(PHM08)会议录。
【3】美国宇航局官方数据仓库
Oracle DBMS 20c 的预测性维护
原文:https://towardsdatascience.com/predictive-maintenance-with-oracle-dbms-20c-3e9c5f5abefb?source=collection_archive---------52-----------------------
物联网传感器可以提供关于系统健康状况的信息,但隐藏了与即将发生的故障相关的有价值的早期警告,而这些故障可以通过预测性维护来避免。一种在核电站和关键基础设施中使用了几十年的机器学*算法MSET-SPRT,能够检测到这些被信号噪音隐藏的关键警告会用Oracle DBMS 20c发布。在本文中我将展示如何将应用到一个真实的测试用例中。
根据麦肯锡的研究:“ 可视化 AI 和其他分析 的使用和潜在影响”,2018 年,人工智能和其他分析对所有行业关于异常检测问题的估计影响估计在 1.0 到 1.4 T 美元之间。
异常检测是关键的成功因素,例如,在预测性维护中,它试图预测何时需要维护,而不是传统的预防性方法,在传统的预防性方法中,活动是在定期安排的基础上计划的,或者在基于条件的维护活动中,甚至通过物联网传感器来监控资产。
预测性维护的问题可以用下图来解释:
赡养的金发女孩问题
应用基于机器学*的异常检测算法,可以执行预测,以估计系统或组件的状况及其剩余使用寿命 (RUL),尝试预测即将发生的故障。
最著名的算法之一是 MSET-SPRT ,在这篇博文中用一个用例进行了很好的描述:“ 机器学*用例:对工程系统的实时支持 ”。它最初于 20 世纪 90 年代在美国 DOE 的 Argonne 国家实验室开发,几十年来一直用于监控核电厂或空军,在这种情况下“故障不是一个选项”,它将被包含在 Oracle DB 的下一个版本 20c 中,作为由Kenny Gross@Oracle Labs改进的实现。
Oracle DB 20c 现在可以作为 Oracle 云基础设施上的预览版使用,并可用于测试其性能。
多变量状态估计技术 e — 序贯概率比检验(MSET-SPRT) 算法监控关键过程并检测细微异常。MSET 是一种非线性、非参数异常检测机器学*技术,它基于来自监控信号的正常操作序列的历史数据来校准系统的预期行为。它的工作方式如下图所示:
MSET-SPRT 算法
MSET 模型在来自 N 个传感器的一系列 M 个基于时间的观察值上被训练,并用于根据输入中的新值估计信号值。为了形成关于系统总体健康状况的假设,这些函数计算估计信号值和实际信号值之间的差(残差),并使用 SPRT 计算来确定是否有任何信号变得退化。对于输入中的正常信号,提供值为 1 的输出,对于检测到的异常,提供值为 0 的输出——为了描述评分,还提供了其他一些信息。假设被监控数据的特征不会随着时间而改变。
我们希望达到的目标是尽快检测到即将到来的故障,从信号中提取信息,以便在早期发出警报。
使用案例
为了试验这种异常检测算法,我选择了一个数据集,该数据集来自美国宇航局艾姆斯预测数据库 ,命名为“轴承数据集,由辛辛那提大学智能维护系统(IMS)中心提供。
它收集了一个机械测试工厂的数据,该工厂有 4 个轴承——我们称之为:B1、B2、B3、B4——安装在一个以 2000 RPM 旋转的轴上,电机连接到轴上,连续几天不间断地运行。每个轴承上安装了 2 个加速度计,因此我们有 8 个信号,每次以 20 KHz 采样 1 秒钟。每次采样有 20480 个点,每 10 分钟重复一次。有几组测试可用,但我使用了从 2003 年 10 月 22 日 12:06:24 到 2003 年 11 月 25 日 23:39:56 收集的数据(Set №1)。我们总共有超过 44 毫升的记录。
在该测试结束时,轴承 B3 和轴承 B4 都被损坏。
方法
为了创建一个能够尽快检测到即将到来的缺陷的模型,以便在正确的时间进行维护活动,我使用了一个 Oracle DB 20c 实例和一个配置为使用 PL/SQL 作为解释器的 Zeppelin 笔记本:关于如何重现该测试的所有信息都在本文的末尾。
关于 Oracle DB 上 PL/SQL 中的 Oracle 机器学*的大致了解,请参考我的帖子“ 自治数据库上的机器学*:一个实用的例子 ”。在这篇文章中,我谈到了自治数据库,但是从编程的角度来看,使用 Zeppelin 是同样的方法。
首先,我已经从 44 Ml 记录数据集中提取了第一个时间框架,我们可以使用它作为系统正常行为的示例,必须在其上训练 MSET(从 10 月 22 日到 11 月 1 日)。数据集的剩余部分已被用来评估算法训练的准确性。数据集准备的重要注意事项。传感器值记录的时间戳字段必须为日期或时间戳类型。在我们的例子中,我选择了允许存储几分之一秒的时间戳,如以下代码所示:
**CREATE** **TABLE** MSET_TRAINING_SH_DATA
( "TIME_ID" **TIMESTAMP** (6) **NOT** NULL **ENABLE**,
"B11" NUMBER,
"B12" NUMBER,
"B21" NUMBER,
"B22" NUMBER,
"B31" NUMBER,
"B32" NUMBER,
"B41" NUMBER,
"B42" NUMBER
);
为了直观显示 B3.1 传感器的正常状态与接*故障状态,我绘制了以下图表:
B3.1 与故障信号相比,传感器处于正常状态
为了获得更有价值的数据可视化,我计算了连接到轴承 B3 的传感器的均方根和 B4,即 20 KHz 下每个样本一秒钟的观察值。正如你所看到的,直到 11 月 24 日,当情况恶化时,没有证据表明 B3 会遭受损失。对于 B4,11 月 21 日有一些微小的波动
来自附在轴承上的 4 个加速器的 RMS 信号将被损坏
仅监控这些参数,您没有时间计划维护活动来替换轴承 3 和 4,并避免每次整个系统的故障。
作为训练样本,与训练集大小(10 Ml)相比,MSET-SPRT 需要更有限的记录数,因此我查询了第一个第二个采样:22–10–2003 12:06:25.005000,对应于 2010 年 10 月 22 日系统测试运行早期的 20480 条记录。
MSET-SPRT 实现需要几个参数,但我只设置了这些参数:
- MSET_MEMORY_VECTORS: 125
- MSET_ALPHA_PROB: 0.1
- 毫秒警报计数:5
- MSET _ ALERT _ windows:5
- 准备 _ 自动:开
必须理解的是,与在评分期间没有记忆的分类算法不同,在 MSET-SPRT 中,评分是在考虑一组按时间顺序的连续样本(MSET_ALERT_WINDOW)以及有多少样本(MSET_ALERT_COUNT)已经超过触发警报的阈值的情况下进行的。
对于调用 create_model() 函数,我们不需要设置目标,因为该算法是在正常条件观测值上训练的,但是我们需要指定时间戳字段。
BEGIN DBMS_DATA_MINING.DROP_MODEL('MSET_MODEL1'); **DBMS_DATA_MINING**.**create_model**(
model_name => 'MSET_MODEL1',
mining_function => 'CLASSIFICATION',
data_table_name => 'sample',
case_id_column_name => 'time_id',
target_column_name => '',
settings_table_name => 'MSET_SH_SETTINGS');END;
之后,我对由超过 33 Ml 记录组成的完整测试数据集运行了预测,以评估该模型在多少天后有助于预测即将到来的故障。
为此,我编写了一个存储过程 test_model(startDay,stopDay) :
%osql
CREATE OR REPLACE PROCEDURE test_model (startDay NUMBER,stopDay NUMBER) AS str1 varchar2(4000);
str2 varchar2(4000);
i varchar2(2);
ii varchar2(2);
BEGINstr1 := q'[
insert into pred_stat_temp
select dt,count(pred) as fail_num from (
SELECT to_char(time_id,'DD') as dt,b11,b31,
PREDICTION(mset_model1 using *) OVER (ORDER BY time_id) pred
FROM mset_test_sh_data where to_char(time_id,'DD')=']';
str2 := q'[') where pred=0 group by dt order by dt]';for i in startDay..stopDay loop
if i<10 then
ii:= '0'||to_char(i);
else
ii:= to_char(i);
end if;
execute immediate str1|| ii ||str2;
end loop;
END;
为了执行这样一个长时间运行的过程,我使用了 Oracle DB 作业,如下所示:
%osql
DECLARE
X NUMBER;
begin**dbms_job.submit**(
X,
'BEGIN test_model(1,25); END;',
SYSDATE
);
end;
并通过以下方式监控状态:
select job_name,job_action,start_date,end_date from USER_SCHEDULER_JOBS
这种方法允许我测试超参数的几种组合,以便在算法设置上找到最合适的组合。
下图是从 11 月 10 日开始每天发射的异常数量图。
故障前最后一段时间每天检测到的异常数量
在第 18 个上已经检测到 47 个异常(在 2.375.680 记录上),与第 19 个上的 282 (在 1.474.560 记录上)相比,归一化代表增长的 866 %,足以在故障前 5 天触发报警。
但是与同一天的正常信号范围相比,这个指标有用吗?为了有个概念,我计算了 11 月 18 日和 11 月 19 日 B3.1 信号的 RMS、Min、Max 和方差,后者是模型开始显著增加警报数量的时候。
如果我们比较这两天,没有任何指标比模型检测到的 866%的异常增长更好。
因此,您可以使用根据 19 日触发的异常数量调整的阈值来发出警报,以请求维护活动。
自己试试
如果您想自己测试算法和这个用例,您必须按如下方式设置环境:
- 在 OCI 上提供数据库云服务,获得一个试用账户。请注意,当您在数据库版本列表中提供 DBCS 的一个实例以具有选项 20c(预览)时,您必须选择存储管理软件作为:逻辑卷管理器:
要选择的存储类型,以选择版本 20c
- 按照这些指令安装 Zeppelin 环境并配置 Oracle DBMS 解释器;
- 从这里下载轴承数据集,使用脚本 pythonprepare . py创建训练和测试 CSV,通过 SQLDeveloper 等工具上传到 DB 上;
- 运行 Zeppelin 笔记本提供的。
引文
[1] J. Lee、H. Qiu、G. Yu、J. Lin 和 Rexnord Technical Services (2007 年)。辛辛那提大学。“轴承数据集”,美国宇航局艾姆斯预测数据库(http://ti.arc.nasa.gov/project/prognostic-data-repository),美国宇航局艾姆斯研究中心,加利福尼亚州莫菲特菲尔德
放弃
本文表达的观点是我个人的观点,不一定代表甲骨文的观点。
使用 ResNet 进行预测性维护
原文:https://towardsdatascience.com/predictive-maintenance-with-resnet-ebb4f4a0be3d?source=collection_archive---------43-----------------------
利用深度学*检测高频传感器的故障
在 Unsplash 上由 Lasse Nystedt 拍摄的照片
迟早,所有的机器都会出故障。确定设备状况或计划何时进行维护,是影响成本和生产率的极具战略性的决策。
机器学*方法已经作为一种有前途的工具出现在预测性维护应用中,以防止生产线中的故障。然而,这些解决方案的性能取决于适当的数据分析和正确分析方法的选择。
在这篇文章中,我们面临着一个类似于以前其他相关文章中的预测性维护任务: 使用 CNN 的预测性维护和 使用 CRNN 的预测性维护。这里的特殊性在于,我们只使用一个单高频信号源到产生我们最终的预测。基于 Mel 频率倒谱系数(MFCCs)的特定变换的应用是从信号中提取特征的基础。这一步使我们能够采用一个残差卷积神经网络结构,它学*我们数据的正确隐藏结构。
数据
我们的任务是研究压力条件下的液压管道。数据由 UCI 资料库收集。在液压系统状态监控中跟踪各种系统部件的活动状态。
该数据集是用液压试验台通过实验获得的。该试验台由通过油箱连接的一次工作回路和二次冷却过滤回路组成。当四个液压部件(冷却器、阀门、泵和蓄能器)的状态定量变化时,系统周期性地重复恒定负载循环(持续时间 60 秒)并测量过程值,如压力、体积流量和温度。
更准确地说,我们重点监控整个系统的状态(用稳定标志标识为稳定或不稳定)分析电机功率。该 KPI 由单个传感器监控,该传感器以 100 Hz 的采样率记录信号。
我们尝试分类的时间序列切片的形状与下图相似。
使用一阶差分对原始信号进行标准化,并对其进行限幅以限制疯狂值。标准化信号以这种方式用于产生 MFCCs。
MFCCs 通常按如下方式得出:
- 从原始信号的窗口摘录中进行傅立叶变换;
- 将上面获得的光谱功率映射到 mel 标度上;
- 对梅尔对数幂进行离散余弦变换;
- MFCCs 是最终频谱的幅度。
它们在音频分析中的应用很常见,但我们在这里利用它们处理高频数据的能力。
模型
如前所述,我们使用基于卷积的网络来预测液压管道的系统状态。我们使用剩余跳跃连接在卷积块中添加一些 bost。
更深的网络更难优化。向网络中添加额外的层会增加训练过程的难度。我们的优化算法变得更难最小化损失。剩余结构试图通过增加跳跃连接来解决这个问题。跳跃连接增加了从网络中的一个初始点到前向点的映射。如果网络没有更多可以学*的东西,则网络的权重保持不变,否则,如果记录了改进(在损失或度量优化中),则网络权重随之改变。
下面是一个残余块的例子,我们可以很容易地在我们的网络架构中使用。此外,根据问题需要,层的数量、激活函数或内核大小的不同变化是可能的。使用这种块时,唯一必须保持不变的是它内部的维度。在我们的例子中,我们注意在卷积运算中操作填充,并使初始维度等于最后的卷积层,以操作最终的连接。
def residual_block(init, hidden_dim):
init = Conv1D(hidden_dim, 3,
activation=’relu’, padding=”same”)(init)
x = Conv1D(hidden_dim, 3,
activation=’relu’, padding=”same”)(init)
x = Conv1D(hidden_dim, 3,
activation=’relu’, padding=”same”)(x)
x = Conv1D(hidden_dim, 3,
activation=’relu’, padding=”same”)(x)
skip = Add()([x, init])
return skip
我们将我们的方法与虚拟基线进行比较,虚拟基线包括将我们的测试样本分类为测试数据中的大多数类别(稳定条件)。我们的网络在看不见的测试数据上达到了 87%的准确率。这是一个很好的结果,相对于我们的基线(66%的准确率)是一个很大的进步。
摘要
在本文中,我们执行了一项预测性维护任务。更详细地说,我们预测了仅考虑电机功率的液压试验台的一般情况。所考虑的信号具有高频率的特征,这使得不可避免地对我们的数据进行一些初步处理。我们通过基于 MFCC 的特征提取过程创造了有价值的信息。生成的新信号被用于输入基于剩余连接的深度学*模型,以产生最终预测。
如果你对题目感兴趣,我建议:
- 预测性维护:用 CNNT5 检测传感器故障
- 预测性维护与 LSTM 暹罗网络
- 预测维护:用 CRNN 和频谱图检测传感器故障
查看我的 GITHUB 回购
保持联系: Linkedin
预测建模者为初学者选择最佳回归模型指南
原文:https://towardsdatascience.com/predictive-modellers-guide-to-choosing-the-best-fit-regression-model-707120e502b4?source=collection_archive---------7-----------------------
如何选择最适合的回归模型
在寻找预测的最佳拟合模型时,找到正确的算法一直被证明是整个项目成败的关键。对于像我和其他机器学*专家一样的机器学*新手来说,找到最适合的模型可能非常令人困惑,这通常不仅是因为低水平的编码能力,而且主要是因为对概念的理解和应用较差,并且容易陷入错误的度量标准。
在这篇文章中,我将通过的 3 个主要步骤来一步步介绍构建最佳拟合模型的概念和指南,以解决任何回归问题。假设您至少知道这些模型的概念,所以我将更多地关注它们的应用。我们将比较以下机器学*算法的性能:
线性回归
K-最*邻(KNN)回归变量
决策树回归器
随机森林回归器
Adaboost 回归器
XGBoost 回归器,和
支持向量机(SVM)回归器
指标:首先,让我们从指标开始,因为选择用来评估模型的指标非常重要。R 平方(R)、调整后的 R 平方(Adj R)、均方误差(MSE)和均方根误差(RMSE)是回归变量非常流行的度量标准。
r 回归得分或决定因素系数是一种直观的统计尺度,用于测量回归模型中由自变量解释的因变量的变化比例。无论输入要素如何,总是预测 y 的期望值的常数模型将获得 0 的 R 值,而完美拟合模型的 R 值为 1.0。对于表现任意差的模型,r 值可以是负的。通常,R 是模型的相对拟合的度量。然而,这一指标有一个值得注意的缺陷,因为 R 分数往往总是随着附加功能的增加而增加,而不一定会提高模型的拟合度。为了克服这个缺点,另一个度量标准,调整后的 R,被解释为由所有独立变量组成的模型所解释的总方差的比例,是优选的。调整后的 R 考虑了自由度。当向模型中添加更多的特征提高了模型的拟合度时,它会增加,否则会减少。
均方误差(MSE) 是回归线与一组点的接*程度的度量。它测量从点到回归线的距离,称为误差或残差方差,并对其求平方,以消除任何负号。均方根误差(RMSE) 取 MSE 的平方根,表示模型与数据的绝对拟合度——观察数据点与模型预测值的接*程度。RMSE 相对更容易解释,因为它与响应变量是同一个单位。较低的 RMSE 值意味着回归线接*数据点,表明拟合较好。RMSE 可以很好地衡量模型预测响应的准确程度,如果模型的主要目的是预测,则它是最重要的拟合标准。
建立了基本的概念之后,让我们开始动手实践吧。我选择了隐藏警告,以避免它们出现在输出中,使输出变得混乱。隐藏所有警告时要注意的是,您必须确保代码没有错误。
为了让代码看起来更专业,我发现在一个地方导入所有需要的库是一个不错的开始。
1.设置目录并导入相关库
导入数据,探索,预处理,为建模做准备。
2。探索和准备数据
浏览数据以了解其维度、数据类型、基本统计数据等。根据数据集的不同,可能需要处理分类变量和缺失值。在本例中,如上所示,没有空值,但是我必须对 cd、multi 和 ads 中的分类值进行编码。
另一件需要检查的重要事情是异常值。准备带有异常值的数据集进行建模的方式与准备不带异常值的数据集的方式不同,您将在后面的缩放中看到这一点。在这里,你可以看到上图中价格和高清的异常值。虽然价格异常值不是问题,因为它是目标特征,但在这种情况下,像 hd 、这样的预测值中异常值的存在会影响模型的性能。检测异常值并选择适当的缩放方法来最小化它们的影响最终会提高性能。你可以在我的 Github 库这里找到完整的代码和数据集。
因为我们在处理回归问题,所以了解预测值和目标变量之间的相关性是很重要的。这可以通过使用如下所示的关联热图和矩阵来实现。
从相关矩阵中,我们可以看到自变量与目标的相关程度不同。较低的相关性意味着弱的线性关系,但是可能存在强的非线性关系,因此,我们不能在这个水平上通过任何判断,让算法为我们工作。
谈到缩放,sklearn 中有各种各样的缩放器,包括 MinMaxScaler、StandardScaler、RobustScaler、minmax_scale、MaxAbsScaler、Normalizer、QuantileTransformer 和 PowerTransformer。我对比了一下本文常用的,找到最合适的。可以随意添加,也可以根据自己的要求选择。下面的程序在缩放和三个选择的类型之前可视化。
正如你从上面的第二张图中看到的,它重新缩放了范围[0,1]中的所有特征值。然而,它对异常值的存在非常敏感。
StandardScaler:此缩放器忽略平均值,并将数据缩放到单位方差。然而,异常值会影响均值和标准差。因此,像 MinMax scaler 这样的 StandardScaler 在存在异常值的情况下不能保证平衡的特征比例。
RobustScaler:与前两个不同,RobustScaler 基于百分位数,因此不容易受到离群值的影响。
PowerTransformer:对每个要素应用幂变换,使数据更像高斯分布。
MaxAbScaler:类似于 MinMaxScaler,但用于只有正值的数据,也存在大的异常值。
QuantileTransformer:匹配高斯分布而不是均匀分布,并为极值引入饱和伪影。
最终的选择取决于数据集的领域知识或试错法。从上图可以看出,只有 RobustScaler 返回了一个很好的分布,其异常值超出了分布的大部分,因此,它是实现最佳性能所需的显而易见的选择。
3.训练模型并进行预测
现在让我们分割数据集并导入适当的建模库。
在构建模型之前,我希望每个模型都发挥出最佳性能,因此为线性回归选择特征并调整 XGBoost、AdaBoost、决策树、随机森林、KNN 和 SVM 的超参数以找到模型中使用的最佳参数非常重要。
线性回归:当建立一个线性回归模型时,没有必要包含那些对目标变量的变化没有合理贡献的不必要的特征。使用向后排除法,您可以取消选择 p_values >为 0.05 的要素,这被解释为无法解释目标的变化,而非偶然变化。以下代码仅返回 p_values <为 0.05 的选定要素。
查看所选要素的 p 值:
调整超参数是优化超参数模型性能的一个关键方法,如下所示。
XGBoost: 这里要调优的常用超参数包括:学*率、最大深度和 n 估计量。
AdaBoost: 学*率和 n 估计量
决策树: max_depth
随机森林:最大深度和 n 估计量
KNN: 当我们的要素具有不同尺度的值时,将它们标准化到相同的范围非常重要,这样无论值的单位是什么,算法都不会对较大值、较高值进行加权,并将较小值视为较低值。这对于 KNN 等基于距离的算法至关重要。我们之前发现 RobustScaler 是最适合该数据集的缩放器,因此我们将在这里使用它进行缩放。
这里要调优的常见超参数是 n_neighbors 和 p。
SVM: 同样,规模化对 SVM 来说也很重要。这里要调整的超参数是 gamma、C 和 kernel。
选择了最佳特性并调整了超参数后,就该使用这些参数构建优化模型了。这可确保每个模型在数据集上发挥最佳性能。下面是我们发现的值的使用演示。
现在我们来预测一下
肮脏的工作做完了,现在让我们看看结果。
R 分数:
调整后的 R
RMSE 值:
正如预期的那样,调整后的 R 分数略低于每个模型的 R 分数,如果我们基于此指标进行评估,最佳拟合模型将是调整后 R 分数最高的 XGBoost,最差模型将是 R 分数最低的 AdaBoost。但是,请记住,这一指标只是对健康的相对测量,因此我们必须查看 RMSE 值。在这种情况下,XGBoost 和 AdaBoost 分别具有最低和最高的 RMSE 值,其余模型的顺序与其调整后的 R 值完全相同。这进一步证实了该数据集的最佳拟合模型是 XGBoost,最差拟合模型是 AdaBoost。注意,这并不总是发生,所以要小心。一般来说,当你有一个模型与最高调整的 R 和高 RMSE,你会更好地与一个有适度调整的 R 和低 RMSE,因为后者是绝对适合的措施。
查看预测价格与实际价格的曲线图,还可以看到 XGBoost 中的数据点彼此更接*,而 AdaBoost 中的数据点则相距更远。
感谢您的来访,我希望您喜欢这篇文章,并发现它很有帮助。你可以在 GitHub 这里找到完整的代码和数据集。
Linkedin 简介:https://www.linkedin.com/in/freemangoja
预测查询与监督 ML 模型
原文:https://towardsdatascience.com/predictive-queries-vs-supervised-ml-models-ee7f17e4840e?source=collection_archive---------35-----------------------
未来预测查询会取代有监督的机器学*模型吗?
超过 4 个数据集的精度基准。本文比较了预测查询和监督 ML 模型的工作流程、架构和缩放/准确性。图像源 Aito
当今科技领域最大的趋势之一是机器学*的民主化。因为商品最先进的模型,更好的工具和更好的硬件:机器学*正在成为公司工具箱中的日常工具。
ML 民主化仍然是一个持续的趋势,鉴于这一领域的混乱,值得问一问:这一转变将把我们带向何方?未来的日常管理会是什么样子?
预测查询是机器学*的一种有趣的方式,尤其是在 ML 民主化的背景下。像麻省理工学院的 BayesLite 和 Aito 这样的解决方案提供了一种使用类似 SQL 的查询立即获得任意预测的方法。例如,Aito 中有一个预测查询:
{
"from": "invoice_data",
"where": {
"Item_Description": "Packaging design",
"Vendor_Code": "VENDOR-1676"
},
"predict": "Product_Category"
}
因此:预测查询似乎是一种更容易、更快、完全不同的机器学*方式。它们让我们看到了未来,任何人都可以像查询数据库一样轻松地进行机器学*。
本文简要介绍了预测查询,并从三个不同方面对预测查询和监督学*进行了比较:
- 工作流,比较预测查询和监督机器学*之间的容易程度和成本
- 该架构比较了使用预测查询和使用监督模型之间的高级差异
- 质量是一项新兴的、有前途的技术的一个明显的关注点。
预测查询简介
预测查询类似于普通的数据库查询,除了它们提供关于未知的的预测,而传统的数据库查询提供关于已知的的事实。下面是一个针对 BayesLite 数据库的 BQL (贝叶斯查询语言)查询示例:
BayesLite 中的预测性 BayesQL 查询。BayesQL 基于 sQL,它提供了一种非常优雅的方式来查询任意估计值。该查询可以在创建群体、创建分析、初始化分析和分析操作之后执行。图片来源:Aito
本质上,预测查询可以为监督 ML 模型提供非常类似 SQL 的替代方案,主要区别在于:
- 虽然受监督的机器学*模型需要在使用前进行配置、训练和部署,但预测查询可以在数据库准备好数据后提供即时答案。因此:预测查询具有不同的工作流程。
- 虽然监督机器学*总是专门用于从 A 到 B 的单个预测,但是预测查询可以用于 A)基于任何已知的 Y 即时预测任何未知的 X,以及 B)还提供推荐、智能搜索和模式挖掘。因此,监督模型是狭窄的,而预测查询是多用途的,这对架构有影响。
- 当有监督的机器学*时,窄模型被显式地形成训练时间,预测查询在查询时间期间做多用途建模或窄建模。因此:预测查询在技术上更具挑战性。
只有很少的解决方案提供这种预测查询。一个是提到的 BayesLite,它在一个特殊的准备阶段创建了一个内存中的多用途模型。另一个解决方案是 Aito.ai,它在没有显式准备的情况下进行查询时窄建模。这是 Aito 工作流程的一个例子。
Aito 中 3 步预测查询。数据上传到数据库后,可以立即运行预测查询。对于像 Titanic 这样的小数据集,预测通常需要几毫秒(图中可见的 187 毫秒延迟是由网络 ping 爱尔兰引起的)。图片来源:Aito
我们将以下比较集中在 Aito 上。我们认为这种关注是合理的,因为在 Aito,我们更熟悉该解决方案,并且它足够成熟,可以在实际生产环境中为最终客户服务。虽然 BayesLite 非常令人印象深刻,他们的 BQL 界面和 DB/ML 集成值得羡慕:BayesLite 似乎有一些属性,如简单数据的 16 分钟准备阶段,这与提出的论点不一致。
因此,接下来让我们更深入地挖掘预测查询和监督 ML 模型之间在工作流、架构和质量方面的差异。
1.工作流程
预测查询和传统监督模型之间的第一个区别与工作流程和成本有关。
受监督的 ML 模型通常部署在数据科学项目中,这些项目有几个步骤,如移交给数据科学家、数据准备、特征工程、模型拟合、部署、集成、再培训以及监控和维护。作为这种线性进展的补充,您通常还会有一个迭代阶段,在此阶段,通过细化数据、准备、特性、模型、部署或集成来改进结果。
数据科学项目的简化版本。关于这些项目的更多信息可以在网上广泛获得。图片来源:Aito
一个人或两个人可能需要几个星期或几个月的时间将一个监督模型投入生产。这可以将每个型号的价格提高到 10 万欧元。如果你需要几个模型,你需要几个数据科学项目,导致成倍的费用和延迟。
现在,如果您使用预测查询来实现机器学*功能,这个过程会发生相当大的变化。对于预测查询,工作流本质上如下:
- 准备一次辅助预测数据库(如果它不用作主数据库)
- 用评估请求验证足够好预测质量
- 像集成 SQL 查询一样集成预测查询
- 编写测试/评估案例,将它们推给 Git,让 CI 处理回归测试
- 如果认为有必要:通过分析跟踪生产预测质量,并在产品仪表板中显示指标。
预测查询的工作流程类似于数据库查询的工作流程。然而,由于预测功能是统计性的,其行为可能会随着数据的变化而变化:建议在实施之前验证预测质量(步骤 2),并在生产中监控预测质量(步骤 5)。图片来源:Aito
虽然将辅助数据库(如 ElasticSearch)投入生产可能需要数周时间,但将每个查询投入生产的相关费用更接*于使用搜索/数据库查询的费用。这种查询通常只占相关功能费用的一小部分,而基于查询的功能通常可以在几小时内实现,几天内投入生产。
工作流程和费用之间的这种巨大差异可以解释为:a)预测数据库的 AutoML 功能被专用数据库加速;b)由于数据和 ML 已经集成到单个系统中,部署和集成的需求减少。数据科学项目的复杂阶段被系统地消除或简化:
- 不需要将数据科学项目移交给数据科学家,因为预测查询工作流对于软件开发人员来说已经足够简单。
- 数据准备和特征工程步骤可以通过 ML-数据库集成大大减少。如果数据已经在数据库中,您不需要重新准备和重新上传数据。如果您可以通过数据库引用进行推理,那么您不需要手动将数据聚合到平面数据框架中。您也不需要手动特征化文本,因为预测数据库会像 ElasticSearch 一样自动分析文本。最后:如果数据库有内置的特征学*能力,你就不需要管理特征冗余。
- 建模阶段可以通过一个复杂的模型实现自动化,这个模型可以为大多数应用程序提供足够好的结果。
- 对于每个模型云部署,模型的实时集成和重新训练完全消失了,因为您不需要“部署”或重新训练预测查询。相反,你可以像集成 ElasticSearch 一样集成一个辅助预测数据库。如果您使用预测数据库作为您的主数据库,您甚至可以省略那个集成。
- 维护更容易,因为您不用为每个预测目标维护已部署的基础设施,而是像使用 Git & CI 维护代码一样维护类似 SQL 的查询。
因此,通过预测查询实现 ML 的工作流程和成本与通过 SQL 实现普通业务逻辑的过程相似。
2.建筑
预测查询和监督模型之间的第二个区别是狭窄性及其对软件架构的影响。
众所周知:受监督的 ML 模型在两个不同方面狭窄:
- 预测设置的狭窄性。监督学*模型本质上是从 A(例如文本)到 B(类别)的狭窄函数,这意味着如果你有 10 个不同的问题,你最终会有 10 个不同的监督 ML 模型。
- 预测功能类型的狭窄性。一种监督方法通常只能用于一种预测。因此,你经常需要完全独立的系统或产品来实现预测、推荐、智能搜索和模式挖掘。
这种组合的狭窄对架构有负面影响。如果你有 10 种不同的预测功能,混合了预测、推荐和智能搜索用例:你最终会陷入一个非常复杂的系统。该系统可以包括具有半打部署模型的单独的监督模型平台、单独的推荐系统、单独的智能搜索产品和单独的模式挖掘工具。这种复杂性很难学*、掌握和维护。智能搜索和基于内容的推荐引擎经常复制数据库的大部分,这导致了冗余。系统也可能不能很好地相互集成,并且它们可能以不一致的状态结束,其中智能搜索可能返回旧的信息,并且推荐和预测可能忽略新产品和数据。
监督模型的狭窄性推动了额外的部署和集成,因为每个预测模型通常需要单独的服务器用于模型特定的 API 和数据集成。每个外部服务通常通过单独的集成服务器集成。这扩大了维护的基础设施和复杂性。图片来源:Aito
另一方面,可以认为预测查询本质上是多用途的,并且在两个方面都不狭窄。首先:预测查询没有固定的预测设置,它们不需要针对 10 个不同的问题进行 10 个单独的模型部署。10 个问题可能需要 10 个预测查询,这是一个明显的优势:虽然创建和维护 10 个不同的监督 ML 模型可能很难,但大多数软件工程项目在创建、理解和维护数十甚至数百个 SQL 查询方面并不费力。
第二,关于预测类型的狭窄性:对于预测数据库,多用途的性质自然地从这种系统中不可避免的设计选择中显现出来。在某种程度上,它的出现与传统数据库中出现多用途的原因是一样的:数据库无法预先知道查询,因此从设计上来说,它必须准备好服务于任何通用需求。这使得设计选择通常是通用的,而不是特定的。
作为一个不太明显但不可避免的设计选择:教科书中的贝叶斯/概率方法最适合快速统计计算,这使得预测数据库成为可能。这在 BayesLite 和 Bayesian Aito 中都很明显。与此同时,如此坚实的数学基础很容易进一步推广,以创建一个多用途的预测系统,这在这两个系统中都很明显。BayesLite 和 Aito 都提供广泛的智能功能组合。
预测数据库本质上是多用途的。Aito 查询 API 提供预测、推荐、匹配(例如从职位到候选人)和统计关系发现作为对基本查询和全文搜索(FTS) 功能的补充。推荐可以与全文搜索相结合,以提供个性化的搜索。预测、匹配和推荐查询也可以作为普通查询执行,其中结果按概率排序。图片来源:Aito
在 Aito 的例子中,贝叶斯数学被推广,不仅服务于预测,还服务于建议。因为搜索数学是基于贝叶斯二元独立模型和预测数据库需要索引所有文本以发挥作用:扩展贝叶斯 Aito 以服务于传统搜索,匹配和个性化搜索用例是很自然的。同样,使用教科书数学来使可解释的人工智能变得极其简单。向一个需要快速模式挖掘才能正常运行的系统添加模式挖掘支持几乎是不可避免的。另一方面:BayesLite 通过广泛的分析能力、SQLite 广泛的数据库功能和令人印象深刻的生成数据的能力补充了 Aito 的功能组合。
因此,类似地,对于已知数据,数据库是非常多用途和通用的,对于未知数据,预测数据库也是非常多用途和通用的。现在,如果您将传统数据库和预测数据库功能结合起来,您将创建更多用途的系统,可以灵活地服务于所有知识相关的需求,包括已知和未知的需求。
在预测方法中,1)客户端 API 集成、2)预测服务器和 3)每模型数据集成被 a)单个预测查询请求和 b)预测数据库的一次性集成所取代。该方法更符合行业最佳实践,如 DRY 、可重用性,避免了 NIH 和用代码替换基础设施。图片来源:Aito
对于单个应用程序的结果是:也许您只需要一个预测数据库来满足您的所有需求。你得到查询,自然语言搜索,预测,推荐,智能搜索等。从单一来源。不需要额外的服务器部署、定制模型或数据集成,因为一切都由单个数据库提供。冗余、一致性和互操作性问题也消失了,因为所有功能都基于相同的事务数据。
面向预测查询的架构也更符合行业最佳实践。用查询替换预测服务器有助于用查询/代码替换基础设施,如在无服务器计算和中将围绕数据(在数据库中)的关注点与查询/代码(在 Git 中)分开。用单个集成替换多个冗余数据集成符合 DRY 原则,并且该方法允许重用旧的数据集成。使用现成的解决方案通常比创建定制的解决方案更可取,以避免重新发明轮子和不是在这里发明的 反模式。总的来说,这种方法减少了需要维护的代码、基础设施和复杂性的数量,并且与良好的旧软件架构目标和原则相一致。
监督 ML 模型和预测查询之间的简化架构比较。图片来源:Aito
因此,面向预测查询/数据库的方法是对传统方法的彻底背离,对行业具有广泛的影响。就像一个思考游戏:如果您有一个可以回答已知和未知查询的数据库:为什么您要另外维护一个单独的普通数据库或者部署大量冗余的 ML 模型/系统?
3.质量
在人工智能的早期,你可以看到人们设想一个类似预测数据库的系统。一个愿景是 McCarthy 对的认识论部分的想法,它将以无缝的方式将机器学*、知识表示和推理结合起来。这个认识论部分本质上是一个世界模型,它可以用来查询已知和未知,就像预测数据库一样。尽管如此,这个愿景从未完全实现,原因很明显:创建一个基于查询的统计推理系统在算法和性能方面都极具挑战性。
最基本的问题是预测总是需要一个模型,但是如果你事先不知道预测的细节,你就有三个相当具有挑战性的选择:
- “世界模型”,您可以在其中创建一个通用模型,为任意查询提供服务。这里的问题是很难创建一个通用的 ML 模型来服务任意的预测,如果你不想降低写/准备的性能就更难了。
- “特别模型”,您可以当场为每个查询训练一个单独的监督模型。这里的挑战是,在不降低查询延迟和吞吐量的情况下,创建高质量的模型查询时间是非常困难的。
- 第三个也是直觉上最合理的选择是将这两种方法结合起来,因为这不仅可以提供最佳的结果,还可以提供最佳的写入和查询速度。从负面来看,它还结合了前两种方法的挑战。
BayesLite 是“世界模式”方法的一个很好的例子。它在额外的“创建群体”、“创建分析”和“分析”步骤中创建了一个内存通用模型。虽然这种方法很优雅,但是即使数据集有限,建模步骤也可能需要 10 分钟以上,这很好地说明了写入/准备时间方面的牺牲。不过,通过使用更专业的数据库(BayesLite 基于 SQLite)和不同的算法(查询时间表示学*可以像在 Aito 中一样加速到毫秒级,这意味着快速的写时准备也应该是可能的),准备速度可能会大大提高。
另一方面,Aito 使用“特定模型”方法,在这种方法中,性能损失发生在查询时。接下来,我将重点介绍我们如何利用这种方法解决一些固有的性能挑战。
Aito 的统计推理管道。Aito 为每个预测查询执行特征选择、特征学*和贝叶斯推理步骤。一种基于 MDL 的表示学*技术创造了“概念学*”用于特征学*,它为贝叶斯推理提供了独立的高级特征。图片来源:Aito。
实质上,为特定查询创建“特定模型”通常需要:1)针对数百个查询特定特征的温暖且快速的数据结构;2)几千个相关统计测量;以及 3)每个感兴趣特征/检查的几千个相关样本。为了满足毫秒级的这些需求,Aito 1)为每个可能的特性快速准备了数据结构,2)使用专门的索引来计算微秒级的完整数据库统计数据,3)使用专门的数据结构来实现亚毫秒级的数据采样。
因此:预测性查询通常可以在毫秒级提供服务,如图 1 所示。您可以在本笔记本中找到关于基准的更多信息。
图一。根据 7 个平均词或 31 个平均词(在高端笔记本电脑上测量)预测二进制值或预测 128 个备选项的分类值时的 Aito 性能。根据查询的规模,可用于推理的文本特征的数量在 10k 和 1.5M 之间。注意对数刻度。 Benchmark 的 Jupyter 笔记本和更多信息可从 这里获得。图片来源:Aito
虽然大多数预测可以以较低的延迟提供服务:因为 Aito 当前使用完整的数据库统计信息,所以 Aito 的伸缩有一个 O(N)组件。这意味着一旦你开始接*百万个数据点:性能就会下降。此外,查询中已知功能的数量和预测类别中备选功能的数量会影响性能,如图所示。
目前,这些性能特征对 Aito 的可能用途造成了一定的限制,因为大数据集和复杂推理可能会影响延迟和吞吐量。然而,值得注意的是,受监督的机器学*性能和资源需求也经常在百万样本规模或例如基准 SVM 实现的 10k 样本规模中开始下降。Aito 查询性能对于数据集有限、延迟和吞吐量要求不严格的应用程序来说也是绰绰有余,例如公司内部工具、PoCs/MVP、后台流程、智能流程自动化和 RPA 。
虽然性能质量对于许多用途来说已经足够好了,但我们确实希望它在未来会更好。对更加专门化的数据库结构的早期实验表明,写速度和采样速度仍然可以提高 10-50 倍。这可以让预测数据库具有 a)与搜索数据库相当(或更好)的写性能,b)更好的缩放,因为基于采样的推理缩放更像 O(1)而不是 O(N ),以及 c)大大提高的预测速度。在未来,通过进行写入时间特征/表示学*来集成“世界模型”方法可以使预测速度更接*我们在传统监督学*中看到的速度,但写入性能会有所下降。
最后,但同样重要的是:让我们考虑预测质量。在基准测试中,我们将 Aito 与 7 ML 模型进行了比较,包括 4 个不同分类数据集上的随机森林和离散数据(Aito 不做回归)。
图二。 Aito 基准测试超过 4 个数据集和 8 种算法( RF 、 CART 、 AITO 、 LDA 、 LR 、 KNN 、 NB 、 SVM )。你可以在这里找到基准代码。图片来源:Aito
正如我们在基准测试中看到的那样,尽管训练预测模型的预算是毫秒级的,但临时模型方法产生了非常好的预测质量。
创建一个毫秒级的好的即席模型是可行的,因为创建一个特定的模型来为特定的预测服务比创建一个通用的模型来为通用的预测服务要快得多。如前所述,训练阶段不需要考虑每百万个特征和每百万个可用样本,而只需要考虑与查询相关的几百个特征和几千个样本。降低的复杂性和专用的数据库使得能够立即服务于适度复杂的特定于查询的模型。
临时模型也可能出奇地好,因为该模型针对单个预测进行了微调。当预测必须基于稀有特征时,传统的监督模型可能丢弃稀有特征并忽略数据中的稀有模式以限制模型的复杂性,这成为一个问题。有了预测查询,问题就简单地消失了,因为查询时间训练允许选择最适合每个单独查询的特征和模型细节。
同样值得注意的是,数据库包含大量的元数据。公司 ID 可以指整个公司表,其元数据可以通过贝叶斯先验用于预测。还有一些数据库友好的机制,如类推(已经在 Aito 中实现了),它可以假设像('消息有 Bob ','接收者是 Bob ')和('消息有 John ','接收者是 John ')这样的关系具有共享的结构('消息有 X ','接收者是 X ')和共享的统计行为。这种技术可以通过利用传统方法无法获得的数据和模式来改进预测。
这都提出了一个问题:通过各种技术,预测查询不仅可以达到奇偶性,而且在许多实际应用中可以达到比最佳监督 ML 模型更好的性能吗?
结论
因此,预测查询可以通过以下方式颠覆机器学*领域…
- …用类似于数据库查询相关工作流的更快的工作流取代昂贵的监督式 ML 工作流…
- …用一个多用途系统和类似 SQL 的查询取代狭窄的监督模型和产品的复杂性…
- …同时保持与监督学*相比具有竞争力的性能和预测质量。
作为这 3 个因素的结果:可以想象,在未来的现实世界应用中,预测查询将取代大多数监督 ML 模型。这是一个简单的思维体验所暗示的:如果你可以从数据库中即时获得预测:你为什么要花数周时间生产和集成冗余的监督模型?
此外,可以想象,预测查询/数据库将成为机器学*民主化的主要驱动力。就像思想实验一样:如果做 ML 就像数据库查询,那么为什么没有开发人员能做 ML 呢?还有:如果基于 ML 的功能成本变得类似于基于数据库的功能成本,为什么 ML 不能像数据库一样用于每个公司、每个项目和每个功能中?
预测性与适应性 SDLC:区别是什么?
原文:https://towardsdatascience.com/predictive-vs-adaptive-sdlc-what-is-the-difference-463596add74b?source=collection_archive---------3-----------------------
想知道您的下一个项目是使用预测软件开发生命周期(SDLC)还是自适应 SDLC?
在 Unsplash 上由 Austin Distel 拍摄的照片
各个组织各不相同。项目和商业策略互不相同。确保您的开发方法与您的组织和项目相匹配。许多项目经理正在从传统的预测性软件开发生命周期 (SDLC)方法转向适应性 SDLC 方法。
你应该吗?
要确定这一点,您应该对预测性和适应性 SDLC 方法有一个清晰的理解,并确定最适合您的组织和项目的方法。
预测软件开发生命周期:概述
顾名思义,预测性 SDLC 假设您可以预测完整的工作流。它包括充分理解最终产品并确定交付过程。在这种形式的项目生命周期中,您在项目的早期阶段确定成本、范围和时间表。
瀑布模型是最常见的预测模型之一。它假设 SDLC 中的各个阶段可以顺序发生,这意味着一个阶段会进入下一个阶段。简而言之,在瀑布模型中,所有的阶段一次发生一个,并且彼此不重叠。
虽然瀑布模型非常简单,易于使用和理解,但它也有一些缺点,可能会对您的项目产生重大影响。
由于瀑布模型遵循顺序方法,一旦应用程序处于测试阶段,就很难在开发阶段返回并调试它。
预测性 SDLC 的优势
- 这很容易理解和遵循,因为每个阶段都是在另一个阶段完成后开始的。
- 详细的说明和简洁的工作流程使开发人员更容易在指定的预算和时间范围内工作。
- 它使组织能够承担预期的项目预算和时间表(如果一切按计划进行)。
- 预测性 SDLC 中的每个阶段都有具体的时间表和可交付成果,这使得团队更容易操作和监控整个项目。
预测性 SDLC 的缺点
- 在预测性 SDLC 中,工作软件是在较晚的阶段生成的,这导致了对应用程序中的错误和漏洞的延迟识别。
- 如果在项目的测试阶段发现了 bug,组织通常不得不承担延迟应用程序的额外成本。
- 对于复杂的项目,它不是理想的 SDLC 模型。
- 预测性 SDLC 不适合需要灵活需求或最终产品不确定性的动态项目。
预测性 SDLC 方法的主要关注点是开发和维护最终产品的规格。这使得它成为项目的理想选择,在这些项目中,所有的需求都被定义,并且对最终产品有一个清晰的愿景。
在预测性 SDLC 中,由于工作已经是预测性的和众所周知的,因此预期的变化很小。团队对项目的发展方向以及如何遵循顺序有一个清晰的想法。
另一方面,预测方法可能非常严格,要求开发人员在整个生命周期中保持严格的标准。由于工作的顺序已经预先确定,任何随后的改变都可能非常昂贵和耗时。
适应性软件开发生命周期:综述
适应性 SDLC 方法混合了增量开发和迭代开发。它包括逐步增加功能,并根据反馈进行修改和完善。换句话说,工作可以很容易地根据从客户那里收到的新反馈来适应变化的需求。
敏捷和其他迭代方法属于自适应 SDLC 的范畴。自适应 SDLC 方法的一个关键要素是,虽然它定义了 SDLC 中的某些里程碑,但它也允许实现它们的灵活性。
适应性 SDLC,例如敏捷,关注于通过快速适应动态业务需求来实现期望的最终目标。它更加关注当前的需求,并为项目的未来范围留有余地。
自适应 SDLC 的优势
- 自适应 SDLC 需要迭代的、进化的和增量的方法,这些方法提供了灵活的指导方针和简单的工作流程。
- 像敏捷这样的方法在本质上是高效的,并且增强了团队协作。
- 短的反馈循环导致快速适应变化的需求。
- 在部署阶段减少潜在的漏洞和错误,因为应用程序在开发阶段经常被测试。
- 它专注于交付高质量的应用程序,同时保持技术优势。
- 鼓励不同的团队在一个项目上合作,增加面对面的互动,营造更好的工作环境。
自适应 SDLC 的缺点
- 它要求客户/用户在整个 SDLC 中广泛参与。
- 在使用自适应 SDLCs 时,不同的团队必须不断地一起工作,这涉及到大量的交互。团队之间的持续沟通可能非常耗时,并且需要更多的承诺。
- 由于自适应 SDLC 需要组织和他们的客户之间的紧密合作,任何一方缺乏承诺都会影响软件质量。
- 经常性的变更正好在开发的时候被采用,这可能导致不太详细的文档。
自适应 SDLC 方法最适合于范围有可能发生重大变化的项目,或者不确定什么是期望的项目。您可能需要适应客户对这些项目不断变化的需求。
自适应 SDLC 方法通常比预测 SDLC 方法更快。这主要是因为很少有项目被充分理解并真正使用预测性 SDLC 方法。当需求没有被充分理解时,问题会在生命周期的后期被发现,这会导致昂贵的返工。
哪个更好?
由于每种方法对于特定类型的项目都有其用途,因此没有明确的决定哪种方法更好。选择很大程度上取决于项目类型、您的策略和组织需求。
如果您仔细分析预测性 SDLC 和适应性 SDLC,并权衡每个项目的利弊,而不是依赖所有项目的统一方法,这是最好的。
在以下情况下,预测性 SDLC 方法可能是更好的选择:
- 你正在做一个团队已经熟悉的项目。团队将会更有生产力,因为他们已经确切地知道项目的期望和他们应该做什么。
- 项目参数发生变化的可能性很小。这是至关重要的,因为在项目结束时,任何后续的变更都将是非常复杂的,并且在预测方法中实现起来非常昂贵。
- 对于最终的可交付产品应该是什么,有非常好的定义和理解的需求。
- 你有一个完整的项目开发过程文档。
- 你喜欢可预测性,喜欢事先对可能/预期的变化有一个清晰的想法。
- 项目经理对其他方法不太有经验。在这种情况下,如果他们在一个他们有大量经验的熟悉的方法中工作,事情会进行得更顺利。
在以下情况下,自适应 SDLC 方法可能是更好的选择:
- 您正在进行一个参数不断变化或尚未确定的项目。自适应方法为您提供了根据新的或更新的参数进行调整的空间。
- 对最终产品的结果没有严格的预期。换句话说,只有当项目具有创新性和/或探索性时,您才应该使用适应性方法。
- 你的工作时间表很灵活。
- 你在一个快速发展的行业工作。
- 项目经理对适应性 SDLC 方法很有经验。
结果
正如您所看到的,预测性和适应性 SDLC 方法都有独特的优势,因此在您的所有项目中只使用其中之一将是一个巨大的错误。仔细评估每个项目的需求和规格,看看你应该采取哪种方法。
关于预测型与自适应型 SDLC,您有任何疑问吗?请在评论中告诉我们。
本文原载于【Cypressdatadefense.com】
预测分析与解释分析
原文:https://towardsdatascience.com/predictive-vs-interpretative-analytics-9f2d85ac1106?source=collection_archive---------32-----------------------
蝴蝶效应和如何成为百万富翁
您是否注意到如今“分析”一词经常与“预测”一词联系在一起?“预测分析”已经成为 IT 界的热门词汇。
事实上,“预测”这个词似乎比“解释”更有吸引力,因为对我们这些懒惰的人来说,我们认为工作会更少。“解释性的”或“解释性的”(不是“不言自明的”)意味着你仍然需要理解,而“预测性的”意味着你只是知道会发生什么。人类总是着迷于预测未来的概念,就像童话中的水晶球一样。
诚然,预测可能会告诉你将会发生什么,但不知道为什么会发生。在某些情况下,你可能还是要理解这一点。
由 Ayanna Johnson 在 Unsplash 上拍摄的照片
只有当一个人不能轻易做出预测,或者当结果不能轻易改变时,预测才有用。
一个很好的例子就是天气,你自己无法预测,也无法改变。对于预测性人工智能(AI)来说也是一样,它通常会被设计成告诉你将会-可能-发生什么,但不会告诉你为什么会发生。这就是“黑箱”效应或“可解释性问题”。
那么,你什么时候还需要这种预测人工智能呢?其实只有两种情况:
- 当人工智能在预测方面比你更好——或更快——时,这并不容易,因为人类一直在做这种事,而且是惊人的预测机器。请记住,你可以在一眨眼的时间内,通过闻到附*的空气,以惊人的准确度预测出某种食物会让你生病(但你也缺乏内置的大气压力传感器,无法准确预测天气)。
- 当你无法改变结果时,因而你无论如何也不需要理解。你可能需要知道是否会下雨,但你不需要了解天气是如何工作的,除非你非常好奇,或者你想成为一名气象学家。
如果你能理解和改变结果,你应该关联和理解,而不是预测。
我们来问这个问题:你会成为百万富翁吗?你是希望得到一个预测,一个简单的“是”、“否”,甚至是基于历史数据的“何时”,还是希望得到一个详细的解释,说明你所做的事情有什么帮助,什么没有帮助?
这就是蝴蝶效应的切入点。作为一个人,你无时无刻不在做决定,其中很多决定将会对你的未来产生影响。有些决定可能看起来无关紧要,但仍然会产生巨大的影响,例如,你是否会遇到你一生的挚爱。
因此,假设你是一个聪明的人,一个努力工作的人,你有一个关于你应该做什么才能成功的好主意,然后你得到一个预测(例如,从一个水晶球),你肯定会在大约三年内成为一个百万富翁。然后,你开始变懒,并决定你更喜欢诗歌而不是大数据,因为你将成为百万富翁,你认为这没问题。
嗯,那个关于你会成为百万富翁的预言现在已经应验了。因为这是现实世界,不是童话,你的诗也没那么好。
如果你稍微想一想,你会发现你最好了解如何成为百万富翁,而不是仅仅得到一个你是否会成功的预测。因为你所做的所有决定都会对结果产生影响,因此你在得到预测后所做的任何事情都会使预测出错,比如,决定成为一个懒惰的诗人。你需要理解“如何”和“为什么”。
让我们再举一个例子,这次你是公元 136 年左右的一个暴躁的 60 岁的罗马皇帝。你已经病得很重了,经常流鼻血和水肿,预言(古罗马没有水晶球)说你会在 62 岁时死于心脏病发作。在这种情况下,在这些时候,清楚地了解人们为什么会心脏病发作,从而有助于防止他们,可能会比预言家的预测容易得多。顺便说一下,这是一个有趣的故事(除了占卜者,那是我),尝试谷歌一下。
现在,当你从一家公司的角度看问题时:首席执行官更喜欢对下一年财务收入的预测,还是清楚地了解过去几年导致收入增加或减少的原因?
公司可以获得大量数据(内生的或外生的),这些数据可以与收入的增加或减少相关联。一旦你明白了这些相关性,你就可以开始寻找因果联系和根本原因,然后进行改进。那么在预测收益之前,我们是不是应该先试着了解如何增加收益呢?
数据是我们信息系统内部真实世界的“反映”,但是它可能有很多,而且不是不言自明的。
财务收入或任何其他与其直接相关的指标通常是一个结果(抱歉),会受到公司每个人(从一线员工到首席执行官)做出的运营或战略决策的影响。
因此,在我们将所有资金和精力投入预测分析之前,我们应该利用先进的分析技术和技能来帮助我们发现模式、相关性和因果联系,以便更快、更好地理解为什么我们会得到这种特定的结果,以及我们如何采取行动来改变它,使之对我们有利。如果数据可用,人工智能、现代分析和数据科学可以通过帮助解释事物的“为什么”、为什么有些事情可行以及为什么其他事情不可行来提供巨大的商业价值。我说的是 人工智能,旨在解释或帮助解释事物,而不是“可解释的预测性人工智能”,它会做出预测,并解释如何或为什么。
我们举个实际的例子:销售。销售转化为作为“对象”的数据,这个“数据对象”(可能是数据库中的一行或一组行)具有属性(可能是数据库中的列),例如:
- 国家
- 城市
- 积范畴
- 产品
- 量
- 客户类别
- 日期
- 等等。
销售的所有这些业务“属性”通常都可以在信息系统的数据中获得,可能有数百万行销售数据。
你可以开始手动分析,使用传统的商业智能工具(或 Excel…),你可能会发现在美国的销售情况很好,而在日本却很差。但这并不能告诉你太多。所以,你继续分析,你可能会发现在日本某个产品类别的销售非常糟糕。您继续分析,您可能会发现特定产品类别中的一些产品表现不如其他产品,其中一些产品总体表现不佳,而在一些客户类别中表现良好,在其他一些客户类别中表现不佳。这个过程会一直持续下去,直到你有一个完整的“场景”来调查,然后你会开始寻找要解决的根本原因。
现在想象一下,你给我原始数据,我给你最有影响的属性列表+最糟糕的场景列表(属性的组合),以及它们相对于结果的“权重”(糟糕的销售)。
其中一个场景可能是这样的:
【国家 02】;[产品类别 A];【产品 A08】;[客户类别 X];【2019 年】;[Q1 时期];【等。] = 5%的不良销售
现在,您可以开始分析不是一次一个属性,而是完整的场景,并清楚地知道从哪里开始。你马上就会知道,在某个特定时期,该产品在某个特定城市的客户类别中销售不佳,这占了“不良销售”的 5%。因此,您可以从现在开始,调查根本原因,进行补救和改进。
您有一个可以研究的场景的完整列表,它们都是相关的,值得研究,因为它们是由算法基于特定标准(通过属性影响和场景相对于结果的权重)选择的。它可以是一个列表,或者看起来像这样,不好的场景用橙色表示,好的用蓝色表示:
有了这种可视化,您可以立即看到日本销售存在问题,并且可以深入每个分支机构,通过分析详细的场景来了解原因。
现在,您可以要求数据和分析团队设计一个算法来预测明年的销售额。这种算法可能会告诉你,日本的销售仍然会很糟糕,这不会帮助你理解为什么以及如何补救。
我们现在需要对每个关键绩效指标进行解释性分析。
我并不是说预测分析毫无用处,但对于许多公司来说,这种“解释性”或“解释性”分析比预测分析要多得多。这里没有深度学*或超级复杂的东西,只有统计数据,没有那么简单,但也不是科幻小说。
我们监控许多指标,对于这些指标,清楚地了解什么导致好的或坏的结果将比简单地预测结果带来更多的商业价值。因为当你清楚地了解不同的变量及其对结果的影响时,你就可以对这些变量采取行动,以优化和改善结果。
总之,在投资新的预测算法之前,先问这两个问题:
- 如果你有时间,你能自己做这个预测吗?
- 你能采取纠正措施使预测出错吗?
如果两个答案都是“是”,那么重新考虑,把注意力放在理解而不是预测上。这样你不仅能适应,还能提高。
通常,如果你曾经因为一种预测算法而感到沮丧,这种算法无助于解释为什么一个特定的结果被预测,那可能是因为你需要理解,而不是预测。
感谢您的阅读,请让我知道您的想法,并毫不犹豫地分享。
数据科学面试准备指南
原文:https://towardsdatascience.com/preparation-guide-for-data-science-interviews-69932d30c7c4?source=collection_archive---------4-----------------------
为合适的工作从合适的资源中获得合适的技能
这是前所未有的时代,我们中的许多人都在寻找转换或找到工作。面试准备成了焦点。面试对每个人来说都很重要。
不确定性、随机性和人为错误让面试变得非常可怕。肾上腺素在你的血管里涌动,你正处于把一切都搞砸的边缘。
做好准备是在面试中减少损失的唯一办法。正如本杰明·富兰克林所说:
没有做好准备,你就是在为失败做准备。
我上周的一篇帖子是关于建立有效的数据科学投资组合的,在那里我分享了一个全面可行的建立投资组合的指南。
一个好的投资组合在大多数时候会帮助你接到第一个电话,如果你真的了解自己的事情,你差不多有 90%的把握。剩下的 10%是由本文第一行提到的三种特质所占。
因此,这篇文章旨在为您提供可行的技巧和资源,为您的下一次数据科学面试做好准备。
为自己确定合适的角色!
数据科学也是一个非常多样化的领域。在你开始建立投资组合之前,你需要做的第一件事就是确定哪一部分技能与你的专长/兴趣相匹配。
为了帮助您,这里列出了当今数据科学中四种常见的角色类型,
- 数据分析师— 在这四种角色中,大多数人都是数据分析师。常见任务包括从 SQL/NoSQL 数据库和其他存储库中提取数据,执行探索性数据分析,分析 A/B 测试结果,处理谷歌分析,或掌握工具 Excel、Tableau。
研究一份好的分析师职位描述会告诉你需要掌握和准备什么,这里有一个例子:
2。数据工程师— 这些人专门为经历大量流量的数据驱动型公司设计和开发数据基础设施。常见任务本质上是核心技术,如设计数据模型、管理 SQL 和 NoSQL 数据库、使用 Hadoop、Spark、Airflow 等构建数据处理系统。
3。ML/AI 工程师— 像这样的职位更加注重研究,需要你了解机器/深度学*算法的来龙去脉。常见的任务包括设计、开发、部署 ML 模型/基础设施,构建支持大型应用程序的库和框架。
4。数据科学家(全栈)——没有“全栈数据科学家”的头衔,但每家数据支持公司(尤其是初创公司和中型公司)都梦想拥有他们。他们几乎涵盖了上述角色中提到的所有技能,并在解决复杂的技术和算法问题方面拥有丰富的经验。一个不断学*和使用机器/深度学*的数据分析师会在 3-4 年内称自己为数据科学家。
注:了解公司的需求因为有时候光有技能是不够的,还有几个因素,比如某个特定部门的特定需求、领域专长、解决某类特定问题的经验等等。
面试准备课程
一旦你发现哪个角色适合你的兴趣,接下来的工作就是做一个作品集,如果你已经准备好了,你就应该开始准备面试了。
我将课程分为两类:
- 一般话题(技能)——每个有志之士都应该努力掌握和练*这些技能的资源。
- 特定角色主题 —针对上述特定角色的强制性主题以及掌握这些主题的资源。
一般主题
你必须具备的四项主要技能如下:
1.编程;编排
每个职位描述都在他们的资格标准中提到良好的编程技能,因为没有一个数据科学工作是完整的,除非你能够操作数据。几乎每个技术面试都是从一个需要解决的编程问题开始的。
你可以选择任何你觉得舒服的编程语言。在数据科学中两种广泛使用的语言是 Python 和 R 。我推荐你学* Python,因为它的多功能性。
练*编程的资源:
- leet code—****掌握编程技巧的最佳去处。庞大的社区,每个话题都有好的问题,大公司面试时常见的问题。
- Hackerrank、code forces、** 编码忍者 也是你可以一头扎进去的顶级平台之一。**
- 如果你是一个完全的初学者并且想学* Python,从这里开始https://www.learnpython.org/。
- 你也可以使用我的 YouTube 播放列表上的编程基础或者我的博客上的数据科学 Python 基础开始学* Python(针对初学者)。
** [## 数据科学的 Python 基础
数据科学入门基础 python 编程精要。
towardsdatascience.com](/python-fundamentals-for-data-science-6c7f9901e1c8)
2.概率与统计
统计学在数据科学家的职业生涯中起着至关重要的作用。没有多少数据科学家和分析师接受过正式的统计培训,你应该从数据科学的角度切入主题。为探索性分析、抽样、实验设计等奠定基础。即使你正在使用 Excel 或 Tableau,理解基础统计学也是非常重要的。
资源刷量统计:
- 实用统计学书籍——这将从数据科学的角度教你统计学。你应该至少读这本书的前三章。
- 统计与概率|可汗学院——本课程将为你在面试中所有统计与概率相关的问题做好充分的准备。一个免费的课程,有很好的视频讲座和练*题的汇编。
- 赤裸裸的统计— 对于惧怕数学、更喜欢理解实际例子的人来说,这是一本令人惊叹的书,解释了统计学如何在现实生活场景中应用。
3。使用 SQL/NoSQL/熊猫的数据争论
从关系或非关系数据库中提取数据是每个分析师都需要知道的事情。一些分析师的工作描述明确要求编写复杂的 SQL 查询来收集数据的专业知识。
然后,一个人应该精通 Python 包,如 pandas、NumPy、scipy、statsmodel,以便能够处理数据集。
使用 Python 提高数据分析技能的资源:
- Kaggle Learn — 你应该看看 Kaggle 的系列课程,这里涵盖了 SQL、熊猫、数据可视化等等。
- Data camp Data Analyst Python Track—该课程还将帮助您快速掌握作为分析师所需的技能,尤其是在数据操作和可视化方面。他们针对上述每一种工具提供交互式动手练*。
- 使用 Python 进行数据分析 — 本课程涵盖了数据分析师的所有重要技能。
- 练*题— 一旦你有了很好的理解,通读几个博客和职业网站上的例题比如跳板。(如果你想让我准备一份问题清单,请回复这个帖子)
4。机器学*算法
一些初级角色可能不需要这样做,但如果你能展示你对开发 ML 模型的理解,这将是一个很好的例子。我建议每个人都熟悉基础知识,包括 ML 问题的类型,线性回归,决策树,逻辑回归,以及如何使用数据训练和测试它们。
学*和实践机器学*的资源
- 用 Scikit-Learn、Keras 和 Tensorflow 进行机器实践学*,第二版
对于初学者来说,这将是理解机器学*的圣经。这是任何想尝试 ML 的人的必读之作。这本书涵盖了所有的基本算法以及数学解释和实践问题。
这本书的第二部分深入研究了深度学*,这是 ML/AI 工程师应该彻底了解的东西。
- 百页机器学*书
这本书会让你跟上机器学*的速度。安德烈写得很好的一本书,他试图将基本算法、构建模块和问题浓缩到这本书里。
- 机器学*教程由安德鲁 NT3G
谈到机器学*,没有 Andrew NG 关于 ML 的课程,推荐是不完整的。理解 ML 和统计模式识别的必看。它涵盖了监督/非监督学*以及最佳实践。它还涵盖了许多应用 ML 解决现实世界问题的案例研究和应用。**
角色特定主题
除了预演你的项目陈述,你应该复*将在技术面试和课后作业中测试的主题。这些都是特定角色的话题,取决于工作要求,所以研究工作描述是非常重要的。
1.数据分析师:
作为一名合格的数据分析师,您应该重点准备以下主题:
- 数据清理/争论—转换数据并从中获得洞察力。
- 统计学基础——概率、统计和线性代数的基础。
- Python/SQL 复*工具
- 谷歌分析(基于职位描述)
- Excel 和 Tableau 为那些对商业智能分析师和市场分析师感兴趣的人提供复*资料
2.数据工程师
你们更注重技术,不需要太多的数学和统计数据。牢固掌握编程并理解数据管理工具是至关重要的。这些工程师是数据科学的开发人员。
- 胜任的编程/开发技能,web 框架、REST APIs 等知识。
- 大数据工具— spark、Hadoop、airflow(DevOps)。学*开发分布式系统。
- 开发 ETL 管道。
- 云服务提供商(Google Cloud 或基于 JD 的 AWS)
3.ML/AI 工程师
人工智能工程师应该对最大似然算法有深刻的理解,他们应该知道驱动那些算法到优化状态的数学。以下是你应该掌握的基本概念:
- 出于显而易见的原因,良好的编程技能。
- 研究不同的损失函数、成本函数、训练算法、正则化方法、神经网络优化器等。动手操作的书将非常方便准备这些。
- 很好地掌握算法的数学和统计基础——至少是线性代数、多元微积分、随机分析。
- 利用庞大的数据集和最佳实践来实现批量学*和在线学*。
- 熟悉数据工程工具—您可能需要自己部署模型,或者帮助工程团队集成您的深度模型,以便在生产服务器上按预期工作。
4.数据科学家
大多数公司都希望多面手加入他们的数据科学家团队。该职位要求你设计和执行 A/B 测试实验,对数据样本进行统计分析,有时重构生产代码并可视化数据。
因此,您应该准备的主题是:
- 良好的编程技能(Python,R,Matlab)。
- 对数学和统计概念有深刻的理解,能够设计和进行研究实验,并评估它们对观察结果的重要性。
- 应该学过分类和回归问题,学会处理有监督和无监督学*。
- 证明有能力解决复杂的问题,如图像分类,语音识别,自然语言处理。学会使用预先训练好的模型;使用 TensorFlow、PyTorch 等库的经验。
- 领域专长——这完全取决于你的研究领域和公司所属的行业。例如,对冲基金的研究科学家需要对金融和经济有深刻的理解。
- 熟悉数据工程工具——他们还应该对如何建立数据基础设施以及他们的代码如何进入生产服务器有一个简单的了解。
摘要
如果我必须给你一个简单的步骤来总结整个过程,你可以用这个工作流程来制定你自己的策略:
- 确定你擅长的角色。
- 研究所有大中型公司的职位描述,寻找他们想要的特质、领域专长和技术能力。
- 准备一份投资组合,展示广泛的研究和解决公司同一领域内复杂问题的能力。根据公司的不同,域名可能无关紧要,但对几乎所有的大人物来说都很重要。
- 重温这些主题。
- 排练你对所有关键主题和项目的陈述和解释。
- 请一位朋友或导师对你进行模拟面试。越多越好。如果你在找导师,你应该去看看 Codementor.io 。使用这个链接可以让你获得 10 美元的积分,帮助你安排第一次会议,因为我是他们的会员合作伙伴。
- 保持冷静,扼杀面试!
数据科学与哈什特
通过这个渠道,我计划推出几个覆盖整个数据科学领域的系列。以下是你应该订阅频道的原因:
- 这些系列将涵盖每个主题和子主题的所有必需/要求的高质量教程,如数据科学的 Python 基础。
- 解释了为什么我们在 ML 和深度学*中这样做的数学和推导。
- 与谷歌、微软、亚马逊等公司的数据科学家和工程师以及大数据驱动型公司的首席执行官的播客。
- 项目和说明实施到目前为止所学的主题。
通过计算非参数统计测试的置信区间来做晚餐和挽回局面
原文:https://towardsdatascience.com/prepare-dinner-save-the-day-by-calculating-confidence-interval-of-non-parametric-statistical-29d031d079d0?source=collection_archive---------29-----------------------
完整的 python 代码,带有用于曼恩-惠特尼 U 检验和威尔科森符号秩检验的工作示例。
照片由戴加·埃拉比在 Unsplash 上拍摄
“我想我需要去看医生”,睡眼惺忪的 Janhvi 说。
“为什么?”,我问道,仍然半睡半醒,享受着慵懒的早晨氛围。
“这几天感觉很累,没胃口。我最好去确诊一下”,她一边回答,一边拉开我的毯子,半踢着我下床。这是我做好准备开车送她去看医生的暗示——我美好的早晨就这样过去了!
“啊!但是你穿那条白裙子看起来很迷人。我相信你几个小时后就会好的”——我想,涂黄油总是有帮助的。她看着我时的眼神足以让这个表情符号为它的钱而战,所以我减少了损失,站了起来。是时候去拜访我们信任的医生了。
你该选择什么——爱情还是金钱?
我们的血浆数量下降了一点。工作压力大,饮食不合理,你是 Janhvi 吗?”“医生叔叔”骂道。
“我可以给你开你常用药物的处方,过两三个星期就应该好了。然而,在过去的 6 个月里,这个新品牌似乎在我试用过的病人身上取得了更好的效果。我觉得你应该试试。一周之内效果就很明显了。”
“一样的价格?”我问道,尽管有点太急切了,但我必须承认。
“我以为询问任何新的副作用会是第一个问题。但是,是的,它花费更多一点。那是哪一个?”博士叔叔干巴巴地打趣说,没有从 Janhvi 转移他的眼睛。
那是当时最贵的一家。在接下来的 10 分钟里,我绞尽脑汁想出一个冗长的借口来挽回面子。在开车回家的路上,我心中的数据科学家开始发挥作用。“你知道,统计学家有一大堆测试来比较两类或两种治疗方法。他们只是不会凭直觉说一个比另一个好。由于患者如此之少,很难概括不同方法之间的差异。”
哈维:“嗯……嗯”
我:“我想在这种情况下,我们可以很好地记录在我们的医生手下接受治疗的每个患者的血浆计数,根据他们接受的治疗将其分为两组,然后使用统计测试来检查是否真的有任何差异。”
哈维:“嗯……嗯”
我:“我们测量的是你的血浆数,不是吗?我认为这不符合正态分布。曼-惠特尼测试应该会给我们答案。”
Janhvi:“说什么?!我的血浆不正常?你是这个意思吗?”
我:“没有,没有!我说它不遵循正态分布。看到那座远山了吗?想象一下,就在 2D。中间的一个峰值,向左右逐渐变小。我们在宇宙中测量的大多数事物都倾向于遵循正态分布——比如身高、血压、考试成绩或智商。在不涉及数学的情况下,如果我数一数这个星球上所有的人,或者至少是很多人,身高在 6 英寸到 20 英尺之间,并以如下方式记在一个表格中——数最左边的最矮的人→数右边高 1 英寸的人→数右边高 1 英寸的人→以此类推,直到数最高的人是最右边的人,那么我会看到一个有趣的模式,在我们周围经历的许多事情中都观察到了。”
高度和数量
Janhvi:“哪个是?”她的兴趣增加了。
我:“一座山,一条钟形曲线。如果我去我们的花园,开始堆砌砖块,为我在表格中输入的每个条目创建一个新列(每个新列刚好竖立在前一列的右侧),砖块列的高度等于我在表格中输入的计数,那么您将拥有一个山形结构。”
正态分布
Janhvi:“有意思。不要在我们的花园里这样做。”
我:“好吧。”
“我认为这是我们能够与这个世界上的其他人产生共鸣的原因之一。我们大多数人在某个时候都会经历同样的事情。
我们分享很多。"
她看着远处的地平线,轻声说道。
我笑了。我从来没有那样想过。我想她是对的。
"血浆数量不符合正态分布吗?"。她回到这个世界就像她离开这个世界一样快。
我:“不。不是所有的事情都是这样,我认为人与人之间的血浆计数不是这样。但我们可以稍后向医生确认。”
Janhvi:“那么这有什么关系呢?”
我:“简单来说,要用的统计检验类型取决于你处理的数据类型。在我们的病例中,我们根据输出数据比较了两类治疗,血浆计数是连续的数据,但不正常。曼-惠特尼 U 检验用于这种情况。”
Janhvi:“你会向医生解释这一点,请他做这个对比测试,然后就能确定新的治疗方法是否比旧的好?”
我:“嗯……我可以自信地说出来。我将能够做出一个听起来像这样的声明——我们可以 95%地确信,治疗之间的平均血浆计数的差异在 x 和 y 之间的范围内。由于这个范围看起来不太大,这两种治疗方法对患者的效果很有可能是一样的。或者说,它们可能是不同的。”
“这么多工作为了T5 那 的声明!”,她大声说道。
“为你做任何事,亲爱的!我绝不会让你服用一种新药,除非你对它有足够的信心”,我说,希望在我的声音中传达出一丝自豪和关心。“你可能现在还没有意识到,但这种测试对制药或金融领域的研究至关重要。”
Janhvi:“是的,没错。我想你很幸运在过去的一周里有机会研究了这些测试,并发现它们很有趣?”
我:“是啊!找出其中一些测试(称为非参数测试)的置信区间并不容易,也没有标准的编程包,至少在 python 中没有。所以我做了一些调查,并为它们创建了自定义函数。我计划很快就此写一篇文章。你怎么知道的?”
珍妮薇:“我太了解你了,我最亲爱的。我们快到家了。告诉你,我觉得我需要睡到很晚,当我起床的时候我会很饿。你在接下来的几个小时里安静地完成你的文章,然后给我做一顿丰盛的晚餐,这样我就完全忘记你问医生叔叔的那个问题了,怎么样?”
“听起来很公平”,我说,不好意思地笑着。
用代码弄脏我们的手
所以在这里,分步代码。
代码背后的方法已引用自英国医学杂志,第 296 卷,1988 年 5 月 21 日:M . J .坎贝尔&M . J .加德纳的“计算某些非参数分析的置信区间”。
你可以从 Colab 或者 GitHub 下载我的完整代码。
对于不成对的样本
non_param_unpaired_CI python 函数
让我们看一下论文中列出的例子,这样我们可以比较结果:
不成对数据集
n =第 1 组或样本 1 数量= 10
m =第 2 组或样本 2 大小= 10
对两个样本的值进行排序,并将它们分别作为列标题和行索引输出。我们需要计算样本 1 中的每个观察值与样本 2 中的每个观察值的差异,给出我们nxm的差异。它看起来是这样的:**
n x m 差异
在我们的 python 函数non _ param _ unpaired _ CI()中,这是通过下面一行代码实现的:
python 中的 n x m 差异
人口中位数或平均数的差的估计现在由这些差的中位数给出。从表中的 100 个差异中,第 50 个最小差异为-6 g/l,第 51 个第最小差异为-5 g/l,因此中值差异估计为(-6+(-5))/2= -5.5 g/l。这可以通过 python 计算得出:
差异的中位数
我们需要第 K 个最小的和第 K 个最大的中值差值来找到区间范围。k 由下式给出:
k 代表不成对样本
在这里,这个术语就是给定置信度下的百分位数。如果我们的置信水平是 0.95,那么 alpha 就是(1–0.95)= 0.05。我们可以用 python 中的这个来计算 N 为:
n 已计算
因此 K 为:
k 计算值
这出来就是 24 。第 24 个和第 24 个的最小差值为-10 g/l,第 24 个和第 24 个的最大差值为+ 1 g/l。因此,群体中位数差值的 95%置信区间为从 -10 g/l 到+1 g/l 。
对于成对样本
这可用于 Wilcoxon 带符号等级测试的情况。
non_param_paired_CI python 函数
工作示例—成对样本
请注意,这里的第一步是计算每个样本的观察值差异(之后-之前)。
n =每个样本的大小= 11
现在让我们计算我们的 N 和 K ,置信水平为 0.95,alpha =(1–0.95)= 0.05:
n 已计算
k 公式
k 计算值
k 出来就是 11 。
我们现在将创建一个包含所有差异平均值的nxn表格。因为列标题和行索引是相同的,所以我们只需要 n(n+1)/2 个值:
差异的平均值
在 python 中:
python 中的平均差异
第 11 个最小的和第 11 个最大的平均值是 11.9 和 25.1 ,因此是我们的区间。
照片由拉娜·阿比在 Unsplash 上拍摄
劈!时间刚刚好!希望这能帮助到外面的人。如果是的话,一定要让我知道。现在我要走了,去做一顿丰盛的晚餐:)
对分享想法、提问或简单讨论想法感兴趣?在 LinkedIn 、 YouTube 、 GitHub 上与我联系或者通过我的网站:我只是一个学生。
回头见&学*愉快!
** [## Himanshu Chandra -业务主管-ML
www.linkedin.com](https://www.linkedin.com/in/himanshu-chandra-33512811/)**
代码下载链接 : Colab , GitHub 。
演职员表&参考资料:
M J .坎贝尔的《起点的统计数据》
杰森·布朗利的博客——机器学*大师
“计算某些非参数分析的置信区间”,作者 M . J .坎贝尔&M . J .加德纳
为企业采用人工智能做准备
原文:https://towardsdatascience.com/preparing-corporations-for-artificial-intelligence-adoption-e67603a22037?source=collection_archive---------51-----------------------
创建促进人工智能转型的文化的执行指南
肖恩·波洛克在 Unsplash 上的照片
行动纲要
大多数公司未能扩大其人工智能试点项目的规模。大多数人工智能项目的预算都被削减了,因为它们没有足够快地交付结果。
问题不在技术,也不在人才。罪魁祸首往往是为前人工智能时代设计的企业文化和组织结构。为了大规模部署人工智能,高管们必须建立一种文化,让业务和技术团队能够无缝协作。
以下是一个由 10 部分组成的框架,帮助高管们为公司大规模实施人工智能做好准备。这不是一个让公司前进的顺序列表。大多数公司都会精通这个框架的一个或多个部分。
相反,本执行指南描述了成功人工智能实施文化的必要条件。企业领导人可以使用这个框架来诊断他们公司在这些领域的熟练程度。
然后,他们可以建造。
人工智能转型框架
面向高管的人工智能转型框架。作者制图,照片由 Laurenz Heymann 在 Unsplash 上提供
几乎每个 CEO 都说他们在‘做 AI’,就像你的朋友告诉你他在‘打健身房’一样。
这两个人很可能都得不到自己希望的结果。许多公司不会超越人工智能试点项目,你的朋友会告诉你,他太忙了,没有时间锻炼。
2019 年 Gartner CIO 调查声称3000 家被调查公司中有 37%已经部署了人工智能。可以肯定的是,剩下的 63%中的许多人在他们的人工智能之旅中遇到了一两个障碍。
光有技术和人才是不够的。企业必须打破文化障碍,重新思考组织结构,以便跨部门和地域部署人工智能。
企业 AI 部署没有单一的蓝图。企业如何实现人工智能取决于它们的规模、人才库和人工智能成熟度。
然而,高管可以使用这个由 10 部分组成的框架来指导他们的人工智能转型之旅:
- 旨在大规模部署人工智能
- 在整个公司建立人工智能意识
- 在高管层致力于“人工智能转型愿景”
- 规划人工智能项目的投资组合
- 建立内部人工智能团队,并与人工智能供应商合作
- 在公司内分配人工智能人才并分配职责
- 在整个公司中采用数据驱动的决策
- 打破数据孤岛
- 弥合业务和技术团队之间的差距
- 整合和变革管理预算
一、以大规模部署人工智能为目标
人工智能使企业能够对数据进行分类,找到模式,预测结果,并大规模地重复决策。
规模很重要。对于银行来说,部署用于客户细分的机器学*工具来帮助交叉销售和向上销售相对容易。部署一套人工智能解决方案来优化从入职到持续关系管理的整个客户旅程,更具挑战性,也更有回报。
企业如何构建和部署可扩展的人工智能解决方案组合?归结为组织结构和文化。公司必须促进业务和技术团队之间的合作,以便人工智能解决方案能够适应不断发展的业务需求。组织结构也必须足够灵活,以允许人工智能人才被部署到最需要的地方。
二。在整个公司建立人工智能意识
企业必须提高整个组织的人工智能意识。从 C-Suite 到个人贡献者的每个人都必须知道人工智能如何解决业务问题,以及他们如何使用人工智能工具。
AI 教育可以是内部的也可以是外部的。AI 成熟度高的公司会设立内部 AI 学院和在职培训项目。其他公司可以在课堂和研讨会上使用外部培训师和顾问。
高级管理人员
高管和高级经理将已经对他们公司的业务需求、目标和挑战有了深刻的理解。因此,他们必须建立人工智能意识,以便能够:
- 获得对人工智能技术如何工作的高级理解(例如,机器学*、机器视觉、自然语言处理)
- 确定其行业和公司内的高价值人工智能用例
- 认识他们公司可以用来实现业务需求的特定人工智能工具和技术
- 学会优先考虑人工智能计划
- 了解采用的障碍、对人员角色的影响以及所需的文化变革
技术职工
企业必须投资于数据科学家、人工智能工程师和人工智能工具开发者的技术培训。根据他们的角色,他们的培训可以包括:
- 数据最佳实践(例如,收集、清理、治理、修正偏差)
- 对机器学*和深度学*的技术理解
- 了解用于构建和培训人工智能和数据模型的开源和第三方工具(例如 Python、PyTorch、TensorFlow)
- 了解行业标准和新兴人工智能技术
商务翻译
也被称为分析翻译,这一新兴角色将在业务和技术团队之间架起桥梁,以确保人工智能产品满足业务需求。业务翻译也可以管理构建人工智能工具的技术人员,并负责人工智能项目的实施和采用。
业务翻译通常来自业务部门(如项目经理、业务分析师、主题专家、业务部门经理)。他们已经对业务有了很好的理解,也可能擅长项目管理、人员管理或战略规划。
商务翻译需要基本的技术培训和人工智能意识,以便:
- 用技术术语向构建人工智能工具的数据科学家和工程师传达业务需求和要求
- 将分析方法和人工智能工具应用于商业问题
- 详细开发人工智能用例
- 了解部署人工智能工具将如何改变工作流程
商业用户
这些是人工智能工具在营销、财务、销售或其他功能方面的最终用户。这些员工需要接受如何在日常工作中使用人工智能工具的培训。他们还需要克服对人工智能的恐惧。
大多数人害怕 AI 和自动化会抢走他们的工作。如果高管们把机器看得比自己人的技能和经验更重要,经理们可能会感到被冒犯。高管必须让员工相信,人工智能将帮助他们实现更多的目标。他们必须讲述一个令人信服的故事,说明为什么人工智能至关重要,以及它将如何惠及公司及其员工。
至关重要的是,高管必须让员工相信,人类永远是等式中最重要的部分。虽然人工智能可以产生数据驱动的见解并自动化流程,但只有人类拥有常识和功能知识来应用这些见解。把 AI 想象成增强的智能,而不是人工的智能。
实际上,自动化会导致一些失业。涉及常规和重复性任务的工作风险最大。然而,关于自动化将如何导致三分之一的工作岗位流失的头条新闻并没有讲述事情的全部。人工智能自动化了任务,而不是整个工作。真实的故事是关于员工的人工智能增强,而不是大规模的人工智能替代。
员工应该欢迎人工智能增强。一旦日常任务实现自动化,员工就可以将更多的时间投入到有影响力和令人满意的工作中。雇主也希望如此。德勤(Deloitte)对 1900 名人工智能采用者的企业调查显示,人工智能的一个主要好处是它解放了员工,使他们更具创造力。
如果员工认为人工智能对增长(或生存)至关重要,他们更有可能接受人工智能。零售业高管只需要指出亚马逊和电子商务带来的生存威胁。解释人工智能如何让零售商变得更高效、反应更灵敏,这很有说服力。强调员工发挥的关键作用并描绘未来成功的蓝图将会让员工完全参与进来。
三。致力于首席执行官级别的人工智能转型愿景
当一家公司的高管能够解释他们的人工智能转型愿景时,该公司人工智能成功的几率就会增加。转型愿景不是关于单个用例。这是为了在市场上大获全胜。
具体来说,最高管理层应该对四个问题有详细的回答:
- 人工智能可以帮助我们应对哪些商业挑战?
- 人工智能将如何在 3-5 年内使我们从竞争中脱颖而出?
- 我们将如何使用人工智能来增长和占领市场份额?
- 在数据可用性、人才和创新文化方面,我们今天必须采取哪些措施?
假设一家暖通空调公司在办公楼中安装供暖、通风和空调设备。他们看到了一个将传感器与机器学*结合起来的机会,以根据人类活动管理整个建筑的温度。这使得暖通空调公司的客户能够最大限度地减少能源使用。在这种情况下,采用人工智能节省的能源将使公司与众不同,并帮助它获得市场份额。
这是暖通空调公司 AI 转型愿景的开始。接下来,他们应该问自己如何通过利用他们的数据、人才和文化取得胜利。
人工智能转型愿景应该为公司的人工智能战略和项目组合提供信息。这也应该有助于公司优先考虑人工智能项目。
考虑长远,寻求试点项目的短期知识
一个长期的人工智能转型愿景将帮助高管们致力于一个多阶段的人工智能之旅。高管们会意识到真正的收益需要时间。如果没有长远的眼光,高管们可能会在看不到结果的时候撒手不管。
即使是成功的人工智能项目也可能需要时间来产生投资回报。试点项目可能根本不会产生财务投资回报。尽管如此,如果试点项目告诉公司应该如何改革数据基础设施,以实现大规模人工智能的采用,这是一个有价值的快速胜利。
试点项目花费不多,但可以给公司提供宝贵的见解,以构建可扩展的人工智能解决方案。它们可以揭示应该以更高的数量或更详细的方式收集什么类型的数据,并确定当前的数据缺口在哪里。例如,这些知识将帮助公司开发与数据收集和治理相关的核心能力。
致力于长期转型愿景的高管更有可能激励和鼓励创新文化,在这种文化中,财务 ROI 不是衡量成功的唯一标准。这种心态为更大的长期财务投资回报率打开了大门。
四。规划人工智能项目的投资组合
成功的人工智能转型是由不同时间跨度的项目组合驱动的。
更大、更雄心勃勃的人工智能计划带来的可衡量的好处可能需要数年时间,同时在短期内产生巨大的成本。单独投资大型多年项目会造成预算压力和管理层的不耐烦。
公司应该计划不同时间范围的人工智能项目组合。这使得公司能够从短期项目中获得稳定的收益,从而说服高管继续支持他们。一个结构良好的人工智能项目组合包括:
- 小型试点项目教授如何扩展人工智能的宝贵经验
- 在 6-12 个月内有可观回报的短期项目
- 处理越来越有价值的用例并在 12-24 个月内产生投资回报的中期项目
- 在整个企业中应用可扩展人工智能的长期项目
假设一家银行的人工智能转型愿景是“通过用人工智能简化整个客户旅程来获得更大的市场份额。”然后,项目应该使客户更容易注册,帮助银行提供方便和定制的客户服务,这反过来又说服更多的人注册。
试点项目主要是学*和概念验证。他们的价值来自于向公司展示他们现在所处的位置,以及他们在数据、人才和基础设施方面的需求,以便成功部署人工智能。
短期项目专注于从单一用例中产生“速赢”。银行可能会启动一个项目,在客户入职期间自动执行“了解您的客户”( KYC)流程。人工智能支持的自动化工具随时可用,KYC 流程也实现了标准化,这使得该项目成为帮助银行削减成本和提高效率的短期项目。
中期项目可以关注更高价值的用例,这些用例需要更多的时间来产生回报。在自动化 KYC 之后,我们的银行可能会开展一个项目,使用无监督的机器学*来构建一个客户细分工具。该工具将根据行为和特征将客户分类,使银行能够更有效地进行交叉销售并增加收入。
长期项目为公司及其客户提供真正的价值。这些可以是独立的项目,也可以是将较小的项目实现组合成一个连贯的解决方案的计划。我们的银行希望简化整个客户旅程,可以创建一个应用程序或网络平台来处理客户入职事宜,提供量身定制的产品推荐,并提供客户服务。
一个结构良好的投资组合可以分阶段提供投资回报。除了来自早期阶段的知识和见解,在阶段中产生 ROI 的项目可以资助(并验证)未来的阶段。
动词 (verb 的缩写)建立一个内部人工智能团队,并与人工智能供应商合作
从长远来看,公司应该致力于在内部构建人工智能。从短期来看(对于特定的用例来说),从供应商那里购买人工智能工具可以产生立竿见影的回报。
收购人工智能的理由。与人工智能供应商合作可能会加快一次性人工智能项目的速度,特别是如果该公司处于人工智能之旅的早期。一个人工智能供应商可能有一个用例的完美工具,这节省了公司的时间。供应商的专业知识也可以缩短新的内部人工智能团队的人工智能学*曲线。
人工智能建筑案例。内部构建的人工智能工具更有可能满足业务需求,并与数据和工作流相结合。从长远来看,依赖供应商产品来实现多个人工智能计划是不可行的。供应商不熟悉公司的业务需求、流程和数据。现成的供应商工具可能无法与公司的数据和业务流程集成。公司也不能让供应商接触敏感数据。至关重要的是,在内部构建人工智能工具使公司能够发展其人工智能能力并扩大规模。
混合方法。在迫切需要定制解决方案的情况下,与人工智能供应商合作构建定制的人工智能工具是一种选择。当内部员工可以准确地告诉供应商该工具应该做什么时,该工具更有可能与公司的流程和数据集成。例如,汇丰银行与人工智能供应商 ayas di合作开发了一款人工智能反洗钱工具。尽管汇丰无疑有内部人工智能团队,但他们利用供应商的专业知识来更快地获得结果。
除了供应商合作伙伴关系,一个良好的人工智能转型愿景需要一个帮助整个公司的集中式人工智能团队。这个团队将包括数据科学家、数据工程师、机器学*工程师和 AI 产品经理。根据公司的组织结构,团队可能向 CTO、CIO、首席数据官甚至首席 AI 官报告。
内部人工智能团队的职责包括:
- 人工智能策略和问题识别
- 人工智能标准和流程
- 规划和执行人工智能项目组合
- 数据和治理标准
不及物动词在公司内分配人工智能人才并分配职责
为人工智能的可扩展性而组织。图片作者。
哪种组织模式最适合大规模部署人工智能?人工智能人才应该居住在公司的什么地方?《哈佛商业评论》关于人工智能驱动的组织的专题讨论了扩展人工智能的三种组织模式:
- 集中化:将人工智能人才集中到一个中央核心(“枢纽”),比如总部或地区办公室
- 去中心化:将人工智能人才嵌入各个业务部门(“辐条”)
- 混合:将人工智能人才&的职责分配给核心和业务部门
与人工智能战略、项目和采用相关的任务可以由三个组织层中的任何一个拥有:核心、各种业务单元,或者跨核心和业务单元工作的“灰色区域”。
核心
核心负责人工智能&数据战略、招募、治理以及与人工智能&数据供应商合作。
核心创建人工智能标准、流程和最佳实践,帮助在整个组织中扩展人工智能。这确保了业务部门不会重复工作,并且人工智能部署是无缝的,符合公司标准。
核心应该负责数据计划,如数据清理、标记和集成。这些计划应该与人工智能项目一起逐步实施。在确定业务需求和人工智能用例之前,没有必要花费数百万美元进行公司范围的数据收集和清理——如果管理层意识到它们不适合人工智能项目需求,这些数据计划可能会被放弃。
业务部门
业务单位负责与采用相关的活动,因为他们是人工智能系统的最终用户。这些任务包括业务分析、鼓励采用、培训用户、重新设计工作流程和衡量效益。
业务部门必须最终对人工智能产品的成功负责。由于人工智能工具是为解决业务需求而设计的,业务部门的领导,如区域经理,应该对人工智能产品的成功负责。
灰色地带
落入灰色区域的任务可以由核心或单个业务单元拥有。这些任务包括 项目管理、算法开发、产品设计&测试、IT 基础设施和变更管理。
选择由核心部门还是业务部门负责这些任务取决于三个因素:
- 人工智能成熟度:公司以前部署人工智能的经验
- 人工智能的紧迫性:人工智能计划的速度和复杂性
- 商业模式:参与人工智能采用的部门、职能或地理位置的数量
如果企业的人工智能成熟度低、紧迫性高、商业模式简单,它们应该将人工智能人才和运营集中在核心。相反的情况要求将人工智能人才分散到各个业务部门。
AI 成熟。一家开始人工智能之旅的公司可能会将其数据&分析高管、数据科学家、人工智能工程师和支持人员集中在核心。这使得标准化工具、数据流程、存储库和基础设施的开发更快。当然,这些人员可以根据需要部署到业务部门。
艾尿急。需要快速部署 AI 项目的公司,可能会选择将其 AI 人才集中在核心。这允许更好地监控行业技术趋势,并在构建人工智能产品时更容易协调。
商业模式。人工智能工具有时必须支持大量的业务单位、地理位置或功能。在这种情况下,该公司复杂的商业模式可能会说服高管将人工智能人才整合到核心部门,并根据需要将他们分配到组织的其他部门。
归根结底,这与其说是一门科学,不如说是一门艺术。一家必须紧急部署人工智能解决方案并拥有复杂商业模式(建议人工智能人才集中化)的公司可能具有较高的人工智能成熟度(建议分散人工智能人才)。在这种情况下,高管应该考虑这三个因素的相对重要性,并确定人工智能人才在核心部门还是在业务部门最有用。
假设银行投资组合中的一个人工智能项目涉及为某个国家构建一个 KYC 自动化工具。如果该国的客户关系团队之前已经为客户入职部署了人工智能工具,该团队可以接管通常由核心处理的活动,如业务案例分析和项目实施。
七。在所有级别接受数据驱动的决策
人工智能应该通过赋予人们数据洞察力来改善日常运营。因为运营是由人来执行的,所以公司必须采用一种从最高管理层到基层的数据驱动的决策文化。
当人工智能被正确采用时,员工可以通过算法建议来增强他们的技能和判断力,以实现比人类或机器单独更好的结果。
这只有在员工能够信任人工智能工具并感到被授权做出决策的情况下才会发生。信任是通过 AI 感知建立的(如上所述)。当企业放弃传统的自上而下的方法时,决策权就产生了。
以一家全国连锁超市为例。关于优化占地面积和产品布局的决策通常由区域经理根据历史数据做出。对于拥有数百家商店的连锁超市来说,这种自上而下的决策可能不会给单个商店带来最好的结果。在数据驱动的决策文化中,使用人工智能工具跟踪实时店内客户行为的当地经理能够更好地决定商店如何展示产品。
八。打破数据孤岛
人工智能需要来自组织许多部门的大量数据。许多公司部门将数据存储在孤岛中——这些系统相互之间没有接口,只能由特定的团队访问。这是人工智能采用的一个障碍,但却是可以克服的。
大型保险公司因其数据孤岛而臭名昭著。保险公司往往有几十个独立的遗留(即旧的)系统,这些系统相互之间没有连接,也没有连接到新的数字和云平台。这种不利于人工智能和该行业正在着手的数字化举措。
像大多数数据密集型行业一样,保险公司也在投资对遗留系统进行现代化改造,或将数据迁移到数字系统、数据湖和数据仓库。数据湖和数据仓库都存储大数据。数据湖是一个巨大的原始数据池,没有结构或标签。数据仓库存储用于特定目的的结构化、带标签的数据。
打破数据孤岛不是一蹴而就的。在实施 AI 之前投资昂贵的大规模数据转换通常是一个坏主意。最好是两者一起做,以便根据您的人工智能计划的需要来完成数据转换。
人工智能试点项目在这里很有帮助——它们揭示了当前的数据差距在哪里。有了这些知识,公司可以开始智能地打破数据孤岛。
九。弥合业务和技术团队之间的差距
业务翻译者,前面介绍过,确保 AI 和数据科学解决方案的设计考虑到了业务需求。
业务和技术团队并不总是说同一种语言。区域销售经理可能确切知道他们想要从人工智能驱动的客户细分工具中获得什么——它应该将客户分成代表他们对哪些产品感兴趣的桶。然而,销售经理可能无法用技术术语将这些需求传达给实际构建工具的数据科学家或机器学*工程师。
这不是企业界的新问题。部署内部 IT 系统或面向客户的移动应用的公司将这些项目的所有权交给专注于 IT 的项目经理和业务分析师。例如,IT 项目经理理解新 IT 系统的业务目标。他们还将对技术有一个基本的了解,并能监督构建系统的技术人员。
当涉及到人工智能计划时,这些业务翻译可以是项目经理、业务分析师,甚至是内部顾问。他们需要对人工智能方法和能力有广泛的认识,这样他们才能理解技术团队在做什么,并给他们指明方向。
商业翻译可以利用他们对商业和人工智能的认识来识别人工智能采用的障碍。在项目早期,他们可以调查最终用户,研究工作流,与业务和技术领域的关键利益相关者交谈。这使他们能够诊断和解决问题,如缺乏员工认同或最终用户的不合理期望。
确定具有商务翻译能力的员工至关重要。这个角色很快就会大受欢迎——而且没有太多的人同时拥有人工智能意识和商业知识。德勤人工智能在 2019 年的企业调查中发现,商业人才几乎与人工智能人才一样受重视,在公司实施了 20 多个人工智能系统后,甚至更受重视。
X.整合和变革管理预算
整个公司的人工智能意识加上员工对人工智能计划的认同为人工智能的采用奠定了基础。然而,仅仅这些还不足以确保 AI 与业务流程的顺利集成。公司必须至少为采用活动和开发活动做同样多的预算。
集成人工智能工具涉及工作流重新设计、培训和变更管理。这些支持活动应该在部署 AI 解决方案之前就开始。它帮助员工准备好使用人工智能工具,并避免不愉快的意外。它还确保员工了解、参与和支持人工智能之旅。
尽早开始可以让业务翻译人员和最终用户在实施之前发现潜在的采用问题。也许人工智能工具需要重新设计一些工作流程,这样会带来更多的麻烦而不是好处。在部署之前认识到这一点允许技术团队修改 AI 工具。
外卖食品
AI 不容易。投资回报需要时间。一家公司的人工智能之旅是由其独特的需求和情况决定的——将会有未知的领域需要跨越。
高管们可以通过推广一种为人工智能转型量身定制的文化,让他们的公司为这一旅程做好准备。上面描述的 10 部分人工智能转型框架可以帮助高管诊断组织需要如何改变,以便大规模部署人工智能。
扩大人工智能需要时间,知道该做什么只是第一步。强大的文化、人工智能意识和各级员工的认同将是关键。
为时间序列分析准备数据
原文:https://towardsdatascience.com/preparing-data-for-time-series-analysis-cd6f080e6836?source=collection_archive---------22-----------------------
一些简单的技巧和窍门来获得分析就绪的数据
在 Unsplash 上 NeONBRAND 拍摄的照片
每个单独的时间序列(TS)数据都装载有信息;时间序列分析(TSA)就是解开所有这些的过程。然而,为了释放这种潜力,数据需要在通过分析管道之前进行适当的准备和格式化。
TS 可能看起来像一个简单的数据对象,很容易处理,但事实是,对于一个新人来说,在真正有趣的事情开始之前准备数据集可能是一项艰巨的任务。
因此,在本文中,我们将讨论一些简单的技巧和诀窍,以获得可供分析的数据,从而潜在地节省大量的生产时间。
查找数据
如果你用你自己的数据集做分析,你就有了。但是,刚刚学* TSA 的人,找到正确的数据集可能会很麻烦。
数据来源其实不少。机器学*库附带的一些数据集——众所周知的玩具数据——已经存在很长时间了。这些“玩具”数据很好玩,尤其是对初学者来说。但这是一种瘾,每个人都需要尽快戒掉,投入到现实世界中去。
下面是一些在不同领域的一系列主题上查找数据的来源——一些是经过策划的,一些需要清理。你一定能从这个列表中找到你最喜欢的。
我建议你从整理过的数据集开始,这样你就不必揪着头发去解决数据问题,对真正有趣的东西失去兴趣。但是一旦你学会了基本原理,发现数据越乱越好,这将迫使你经历整个分析过程。
好了,这里有一些玩具数据集——干净、有条理、可供分析——经常在机器学*教程中使用:
- 1949 年至 1960 年间每月报道的航空旅客人数
- 美国某些州的客户每小时消耗的电能
- 股票市场数据不同公司的开盘价、最高价、最低价和收盘价以及交易量
- 一个关于洗发水销售的超小型数据集
- 1981-1990 年间的日最低气温数据(不知道代表哪个国家/城市,不过那不重要)
- 每日记录的空气质量数据(一氧化碳、二氧化硫、臭氧等。)针对印度的不同城市
对于真实世界的数据集,有一些非常棒的存储库。老实说,我认为您不需要超越这些存储库来学*高级 TS 分析和建模。
1)美国人口普查局拥有大量美国商业活动的时间序列数据
2 ) 美联储经济数据(FRED) 是关于美国经济指标的一个很好的数据源
3 ) 世界发展指标(WDI) 是一个由世界银行维护的关于世界各国社会、经济和环境问题的巨大资料库。
数据准备
首先,人们总是倾向于像对待任何其他数据集一样对待时间序列。然后操之过急。但是 TS 观测和我们熟悉的横截面观测是不一样的。
时间序列数据已经存在很长时间了,许多人致力于让其他人的生活更轻松(想到了 R 编程语言中的 Rob Hyndman 和 Python 世界中的 Jason Brownlee )。
有很多非常好的库是专门用来处理 TS 数据的。通过转换数据,您让库认识到它是一个特殊的 TS 对象。
假设您已经完成了所需的预处理,例如重命名列、处理缺失值等。—以下是如何通过几个步骤准备数据。
在这个练*中,我使用了一个在机器学*中被过度使用的玩具数据——航空乘客数据集——并用 Python 执行代码。
# import a couple of libraries
import pandas as pd
import numpy as np# import data
df = pd.read_csv("../DataFolder/file.csv")# look at the head
df.head()
数据集的前几行
从前面几行我们可以看到,数据集有两列,第一列表示“yyyy — mm”格式的日期列,另一列表示实际观测值。
记住,我们还不知道它是否是一个时间序列对象,我们只知道它是一个有两列的数据帧。
df.info()
数据帧信息
因此,在其他信息中,这个摘要确认了它是一个有两列的pandas
数据帧。第一列是对象,第二列是整数。
它不显示任何时间维度,这是因为月列存储为字符串。所以我们需要将其转换成日期时间格式。
df_air["Month"] = pd.to_datetime(df_air["Month"])
接下来,让它成为索引。这样做的好处是,您可以以任何方式过滤/切片数据:按年、月、日、工作日、周末、特定的日/月/年范围等等。
df_air = df_air.set_index("Month")
df_air.head()
将月份更改为日期时间并设置为索引后的数据帧
最后一个好的实践是从日期时间索引中提取年、月和工作日,并将它们存储在单独的列中。如果需要的话,这为根据年/月等对数据进行“分组”提供了一些额外的灵活性。
df_air['year'] = df_air.index.year
df_air['month'] = df_air.index.month
df_air['weekday'] = df_air.index.weekday_name
这就是我们的最终数据集。只需对比与原始数据的差异。此外,正如下面用黄色墨水突出显示的,它现在确认它不只是任何数据帧,而是一个时间序列对象。
df.head()
总之,我们做了一些事情来将我们的数据转换成时间序列对象:
1)将月份列从字符串转换为日期时间;
2)将转换后的日期时间列设置为索引;
3)从索引中提取年、月和工作日,并存储在新列中
现在怎么办?
现在您已经有了可供分析的数据,下一步是什么?你现在可以用它进行所有你想要的有趣的分析了,我会在以后的文章中介绍。与此同时,如果你想阅读一些先进的运输安全管理局分析,我写了几篇,看看下面。
- 时间序列数据挖掘技术及应用
- 时间序列数据分析中的六个关键点
- 多元时间序列预测
祝你 TSA 之旅好运!
联系提问或者只是关注: 推特 。
用网络分析准备研究生院面试
原文:https://towardsdatascience.com/preparing-for-graduate-school-interviews-with-network-analysis-84df6354659b?source=collection_archive---------39-----------------------
利用数据科学发现跨机构教师之间的联系。
图一。不同机构的教职员工的图表(彩色),由他们的出版历史联系起来。
本文是正在进行的关于在研究生院面试过程中利用数据科学的系列文章的第一部分。查看下一期 专题造型 ,敬请期待更多。
美国的研究生院面试季正在火热进行中,这意味着你会遇到很多在某个特定领域可能相互认识的重要人物。当你准备的时候,你会开始意识到世界是多么的小,全国和全世界的教师是如何通过合作和相互尊重来建立他们的职业生涯的。为了帮助理解这些关系,我花了几周时间思考如何最好地收集、处理和呈现这些数据,以便在采访中有效地使用。我刚从我的第一轮面试中回来,并与我的同事分享了我的一些结果,他们的兴趣促使我写了这篇简短的走查,所以任何有兴趣为自己做同样事情的人都可以。
我们将主要使用 Python,包括以下模块:
- 学术,通过谷歌学术收集数据。
- 熊猫和 Numpy,进行基础数据角力和操作。
- Networkx 和 Matplotlib,用于绘图和数据表示。
- Python-docx,用于自动化文档构造。
其中一些可能包含在 Python 的典型安装中,也可能不包含在其中,因此我建议您参考它们各自的网站/文档以获得专门的帮助。
第 0 部分:数据收集准备
根据我的理解和知识,并没有一个确切的谷歌学术 API 可以被接口来直接获取数据,因此实现了学术。这带来了一些优点和缺点,其中一些有时会由于高容量使用而被阻塞。出于这个原因,我们想在安装后对它的脚本做一些小的修改。请在 Python 下的 lib/site-packages/文件夹中,或者在您决定维护该模块的任何地方找到 scholastic . py 文件。这里我们将添加一个简单的随机用户代理生成器:这里是这里是。在 scholastic . py 中,您可以找到 web-scrapers 标题的定义,如下所示:
_HEADERS = {
‘accept-language’: ‘en-US,en’,
‘User-Agent’: ‘Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36’,
‘accept’: ‘text/html,application/xhtml+xml,application/xml’
}
这对于简单的运行来说已经足够好了,然而,根据你感兴趣的教师数量,这可能是不够的。因此,在脚本的开始,我们将从前面的超链接文章中添加随机用户代理生成器,我们的 scholarly.py 脚本的开始应该是这样的:
def get_random_ua():
random_ua = ''
ua_file = 'C:/Users/Masters-PC/Documents/ua_file.txt'
try:
with open(ua_file) as f:
lines = f.readlines()
if len(lines) > 0:
prng = np.random.RandomState()
index = prng.permutation(len(lines) - 1)
idx = np.asarray(index, dtype=np.integer)[0]
random_proxy = lines[int(idx)]
except Exception as ex:
print('Exception in random_ua')
print(str(ex))
finally:
return random_ua_GOOGLEID = hashlib.md5(str(random.random()).encode('utf-8')).hexdigest()[:16]
_COOKIES = {'GSP': 'ID={0}:CF=4'.format(_GOOGLEID)}
_HEADERS = {
'accept-language': 'en-US,en',
'User-Agent': get_random_ua(),
'accept': 'text/html,application/xhtml+xml,application/xml'
}
这应该让我们为我们的应用程序做好了准备,尽管您可以随意浏览带超链接的文章的其余部分,并实现他们的其余建议。
第一部分:数据收集
取决于你离面试日期有多*,你可能会也可能不会有你将会见的教员名单。这是我们将使用谷歌学术获得他们数据的广度的地方。首先,导入相应的模块并定义这个作者列表。
authorlist = """Wilhelm Ostwald
Linus Pauling
Max Perutz
Frederick Sanger
Michael Smith
Harold Urey
Milton Friedman
Friedrich Hayek"""
我只包括了 7 个随机的诺贝尔奖获得者,但是这个想法是你应该能够同时包括你感兴趣的所有教师。我的名单上有超过 40 人,分布在 10 多个机构,我还包括了我以前的导师,以防那里有任何以前未被发现的联系。有了这个,我们就可以利用学术并把输出写到一个. csv 文件中,我们可以继续检查错误。
import scholarly
import csv
authors = authorlist.split('\n')
table = [['Name','ID','Affiliation','Domain','First Year Cited','Citations','Citations (5 Years)','cites_per_year','coauthors','hindex','hindex5y','i10index','i10index5y','interests','publications']]for i in range(len(authors)):
print(i)
query = authors[i]
try:
search_query = scholarly.search_author(query)
author = next(search_query).fill()
data = [author.name,
author.id,
author.affiliation,
author.email,
'first cited year',
author.citedby,
author.citedby5y,
author.cites_per_year,
['coauthors'],
author.hindex,
author.hindex5y,
author.i10index,
author.i10index5y,
author.interests,
['publications']]
coauthors = []
for j in author.coauthors:
coauthors += [[j.name,j.affiliation]]
data[8] = coauthors
publications = []
for j in author.publications:
publications += [j.bib['title']]
data[-1] = publications
except:
print(query + ' is not available')
data = ['']*15
data[0] = query
table += [data]with open('FoIScholardata.csv', 'w', newline='', encoding='utf-16') as myfile:
wr = csv.writer(myfile, quoting=csv.QUOTE_ALL)
for i in table:
wr.writerow(i)
运行后,您现在应该在当前工作目录中有一个 FoIScholardata.csv 文件,可以在 Microsoft Excel、Google Sheets 或任何其他电子表格编辑器中打开该文件来检查数据。
第 1a 条。证明、清理和扩充数据。
你应该做的第一件事是仔细检查你是否获得了正确的教授数据,因为那些有相同或相似名字的人可能会混淆。如果是这种情况,您可能希望在搜索查询中包括他们的机构名称/缩写以消除歧义,例如:
authorlist = "...
Linus Pauling CalTech
..."
你可能注意到的下一个问题是一些教授的数据不可用。如果这不是你的情况,你可以继续第 1b 部分。最可能的原因是他们没有创建自己的谷歌学术个人资料。为了解决这个问题,我们可以用其他网站来增加我们的数据,包括他们的机构网页或其他网站,如 ResearchGate。如果您感兴趣,可以随意创建新的数据列。一旦你这样做了,如果你还需要获得他们的出版物列表,你可以使用学术以及下面的代码片段。将“用户”列表替换为谷歌学术网站上作者出版物中的缩写名称列表。
import scholarly
import pandas as pd
import time
import random
table = pd.read_csv("FoIScholardata.csv", encoding='utf-16')
users = ['W Ostwald', 'MF Perutz']
names = list(table.Name)
surnames = []
for i in names:
surnames += [i.split(' ')[-1]]
for user in users:
print(user)
try:
srch=scholarly.search_pubs_query(user)
except:
print('Holding for an hour.')
time.sleep(3600)
pubs = []
noerror = True
while noerror:
time.sleep(0.5+random.random())
try:
pub = next(srch)
if user in pub.bib['author']:
pubs += [pub.bib['title']]
print(len(pubs))
except:
noerror = False
titles = []
for i in pubs:
titles += [i.bib['title']] n = surnames.index(user.split(' ')[-1])
table.publications[n] = titles
export_csv = table.to_csv (r'fillins.csv', index = None, header=True) #Don't forget to add '.csv' at the end of the path
print('Holding for about a minute')
time.sleep(45+random.random()*30)
根据您的兴趣修改导出的文件名,并将您的结果添加回原始 FOIScholardata.csv 文件。睡眠时间包括在内是为了方便逃避被封锁,但你可以随时删除/修改它们。
第 1b 节:确定作者之间的合作关系。
谷歌学术确实包括了一个共同作者的列表,这得到了概要持有者的认可,但这似乎是一个相对较新的特性。因此,它可能是在用户更新了他们的简档,或者他们的合作者创建了他们的简档等之后引入的。,可能不包括所有实际的合著者。因此,我们将基于共享同名出版物来手动添加这些协作。
import pandas as pd
import numpy as np
table = pd.read_csv("FoIScholardata.csv")
matrix = [[0]*len(table)]*len(table)
matrix = np.array(matrix)
newcol = []
for i in range(len(table)):
print(i)
author = table.Name[i]
pubs = []
collaborators = []
if type(table.coauthors[i])==str:
pubs = eval(table.publications[i])
for j in range(len(table)):
if i == j:
continue
if type(table.coauthors[j])==str:
coms = list(set(eval(table.publications[j])) & set(pubs))
matrix[i][j] = len(coms)
if matrix[i][j]>0:
collaborators += [table.Name[j]]
newcol += [collaborators]
table['collaborators'] = newcol
export_csv = table.to_csv (r'FoIScholardata.csv', index = None, header=True) #Don't forget to add '.csv' at the end of the path
第 2 部分:生成主要合作者图表。
现在,我们的主要活动,虽然我们肯定有很多事情要做,我希望你留下来。有了适当组织的数据,我们将不会利用 Networkx 来构建和显示我们的图表。
import math
import pandas as pd
import numpy as np
import networkx as nx
from matplotlib import cm
import matplotlib.pyplot as plt
table = pd.read_csv("FoIScholardata.csv")
G=nx.Graph()
for i in range(len(table)):
G.add_node(table.Name[i])
for i in range(len(table)):
for j in eval(table.collaborators[i]):
G.add_edge(table.Name[i],j)
domains = np.unique(table.Domain);
#see [https://matplotlib.org/tutorials/colors/colormaps.html](https://matplotlib.org/tutorials/colors/colormaps.html)
viridis = cm.get_cmap('hsv', len(domains))
from matplotlib.pyplot import figure
figure(num=None, figsize=(16, 12), dpi=100, facecolor='w', edgecolor='k')
pos = nx.spring_layout(G, k = 0.25) # positions for all nodes
labels = { i : table.Name[i] for i in range(0, len(table.Name) ) }
options = {"alpha": 0.8}
for i in range(len(G.nodes())):
nx.draw_networkx_nodes(G, pos, nodelist=[table.Name[i]],node_size=table.hindex[i]*19,node_color=viridis(list(domains).index(table.Domain[i])), **options)
for i in pos:
angle = 0
plt.text(pos[i][0],pos[i][1],s=i,fontsize=12,rotation=angle, rotation_mode='anchor')
plt.axis('off')
plt.savefig("CollaboratorSpringGraphColor.png") # save as png
plt.close()
幸运的话,您的结果应该看起来有点像这样:
图二。共同发表科学家的 Spring (Force-directed)图。注:这些科学家之间的联系事实上是不正确的。
如果您遇到颜色格式的问题,您可能需要手动修改数据中的“域”变量。在这种格式中,您可以很容易地识别该图中可能出现的子网和其他模式。其他格式也是可用的,即我们名义上的图像,圆形图。为此,我们应该分三部分稍微修改我们的代码:
- 修改位置声明:
pos = nx.circular_layout(G)
2.旋转名称标签,使它们不重叠:
for j in range(len(pos)):
i = list(pos.keys())[j]
angle = 0
if ((math.atan2(pos[i][1],pos[i][0])*180/math.pi) > (70)) & ((math.atan2(pos[i][1],pos[i][0])*180/math.pi) < (110)):
angle = 45
elif ((math.atan2(pos[i][1],pos[i][0])*180/math.pi) > (-110)) & ((math.atan2(pos[i][1],pos[i][0])*180/math.pi) < (-70)):
angle = -45
3.更改输出文件名:
plt.savefig("CollaboratorCircleGraphColor.png")
生成的图像应该如下所示:
图三。标注的圆形图展示了所选院系之间的相互联系。注:这些科学家之间的联系事实上并不正确。
第 3 节:得出每位研究人员的额外个性化数据。
现在,这个图表对于一幅大图来说是很好的。然而,当你接*被邀请的日期时,为了考虑到每一位教授,你可能会想把它大大地分解一下。首先,我们将建立在谷歌学者的“兴趣”概念上。正如我们已经*惯的那样,该特征可以由轮廓支架来完成,也可以不由轮廓支架来完成。然而,我们可以通过再次查看出版物标题来构建一个替代品。我们要做的是提取所有出版物的词频,并查看哪些出现在顶部。如果没有安装,您可能还需要安装 get_stop_words 模块。
import pandas as pd
import matplotlib.pyplot as plt
from stop_words import get_stop_wordsexcs = get_stop_words('en')
table = pd.read_csv("FoIScholarData.csv")
def valuef(x):
return worddict[x]
newcol = []
for i in range(len(table)):
pubs = eval(table.publications[i])
worddict = {}
for j in pubs:
words = j.lower().split(' ')
for k in words:
if k in worddict.keys():
worddict[k] += 1
else:
worddict[k] = 1
values = []
topics = []
for j in worddict:
if worddict[j] > 5:
if not (j in excs):
values += [worddict[j]]
topics += [j]
width = 0.3
topics.sort(key=valuef)
values.sort()
newcol += [topics]
plt.bar(topics[-15:], values[-15:], width, color='b')
plt.xticks(rotation = -45)
plt.gcf().subplots_adjust(bottom=0.22)
plt.title('Title Word Frequency for ' + str(table.Name[i]))
plt.savefig(str(table.Name[i]) + "_WF.png") # save as png
plt.close() # displaytable['topics'] = newcol
export_csv = table.to_csv (r'C:\Users\Masters-PC\Desktop\ProfNetworks\FoIScholardata.csv', index = None, header=True) #Don't forget to add '.csv' at the end of the path
除了在我们的数据电子表格中为我们提供一个新列之外,这还将为每位教授生成一个可视化效果,如下所示:
图 3。宾夕法尼亚州立大学 Charles Geier 博士的出版物标题词频直方图。
这张图表立即提供了信息,因为我们可以确定研究人员对抑制控制和一般认知发展的兴趣。也许,更深入的分析,包括主题建模,以获得研究人员之间更深层次的联系是可能的,尽管这超出了本文的范围。
更新:我决定贯彻这个承诺,并且有效地执行了一个 主题建模方法 来连接这些部分。请随意查看!
第 4 部分:对每位研究人员的图表进行*距离观察。
我们创建的大图表可能不适合每个研究人员的个性化报告。因此,我们可能只对提取子网络感兴趣,类似于力定向图中的可视化。为此,我们将考察他们的一阶合作者(直接),和二阶合作者(合作者的合作者)。
import math
import pandas as pd
import numpy as np
import networkx as nx
from matplotlib import cm
import matplotlib.pyplot as plt
table = pd.read_csv("FoIScholardata.csv")def f(n, c2, c1):
m = (c2-c1)/4
b = c2 - m*5
return m*n+bfor qt in range(len(table.Name)):
G=nx.Graph()
# adding just one node:
G.add_node(table.Name[qt])
for j in eval(table.collaborators[qt]):
G.add_node(j)
G.add_edge(table.Name[qt],j)
if len(eval(table.collaborators[list(table.Name).index(j)]))>0:
for k in eval(table.collaborators[list(table.Name).index(j)]):
G.add_node(k)
G.add_edge(j,k)
N = len(eval(table.collaborators[qt]))
domains = np.unique(table.Domain);
#see [https://matplotlib.org/tutorials/colors/colormaps.html](https://matplotlib.org/tutorials/colors/colormaps.html)
viridis = cm.get_cmap('hsv', len(domains))
from matplotlib.pyplot import figure
figure(num=None, figsize=(16, f(N, 12, 4)), dpi=100, facecolor='w', edgecolor='k')
#pos = nx.spring_layout(G, 1/(len(G.nodes))) # positions for all nodes
#pos = nx.circular_layout(G) # positions for all nodes
pos = nx.kamada_kawai_layout(G) # positions for all nodes
labels = { i : list(G.nodes())[i] for i in range(0, len(G.nodes())) }
#nx.draw(G)
#options = {'node_size': 500, "alpha": 0.8}
options = {"alpha": 0.8}
for i in range(len(G.nodes())):
nx.draw_networkx_nodes(G, pos, nodelist=[list(G.nodes())[i]],node_size=table.hindex[list(table.Name).index(list(G.nodes())[i])]*19,node_color=viridis(list(domains).index(table.Domain[list(table.Name).index(list(G.nodes())[i])])), **options)
nx.draw_networkx_edges(G, pos, width=1.0, alpha=0.5)
for i in pos:
surname = i.split(' ')[-1]
plt.text(pos[i][0],pos[i][1],s=i,fontsize=f(N, 36, 48))
plt.axis('off')
xlims1 = plt.xlim()
plt.xlim(xlims1[0],f(N, 2, 2.5))
#plt.ylim(-3, 3)
plt.savefig(table.Name[qt]+ "CollaboratorSpringGraphColor.png") # save as png
plt.close() # display
我想这个自定义的 f 函数值得讨论一下。并非所有的研究人员都有相同数量的合作者,因此,我对每个条目的 f 函数进行了线性校准,我认为应该根据创建的图像进行适当的缩放,这样当我们进入下一部分,即生成我们的报告时,它将是美观的。这些数字可能有点武断,所以请随意调整它们以满足您的要求。
第 5 部分:执行每位研究者的个性化报告。
所有这些数据都已可视化并准备就绪,我们现在可以开始最终完成我们的总结报告。为此,我们将使用 Python-docx。
from docx import Document
from docx.shared import Inches
from docx.enum.table import WD_ALIGN_VERTICAL
import pandas as pd
import numpy as np
import networkx as nx
from matplotlib import cm
import matplotlib.pyplot as plt
def f(n, c2, c1):
m = (c2-c1)/4
b = c2 - m*5
return m*n+btable = pd.read_csv("FoIScholardata.csv", encoding='utf-16')for qt in range(len(table.Name)):
print(qt)
document = Document()
try:
if type(table.Affiliation[qt])==float:
continue
document.add_heading(table.Name[qt], 0)
p = document.add_paragraph('')
p.add_run(table.Affiliation[qt]).italic = True
p.add_run('\n'+'Interests '+str(table.interests[qt])[1:-1])
document.add_picture(table.Name[qt]+"_WF.png", width=Inches(5))
if len(eval(table.collaborators[qt]))>0:
document.add_heading('Collaborators', level=1)
coltable = document.add_table(rows=1, cols=2)
coltable.cell(0, 0).vertical_alignment = WD_ALIGN_VERTICAL.CENTER
for j in eval(table.collaborators[qt]):
pol = coltable.rows[0].cells[0].add_paragraph(
j, style='List Bullet')
co = coltable.rows[0].cells[1].add_paragraph()
bo = co.add_run()
bo.add_picture(table.Name[qt]+"CollaboratorSpringGraphColor.png", width=Inches(f(N, 4.9, 4)))
cols = []
ncols = []
bestcol = []
for j in eval(table.collaborators[qt]):
k = list(table.Name).index(j)
collabs = list(set(eval(table.publications[qt])) & set(eval(table.publications[k])))
cols += [table.Name[k]]
ncols += [len(collabs)]
bestcol += [collabs[0]]
ntable = document.add_table(rows=1, cols=3)
hdr_cells = ntable.rows[0].cells
hdr_cells[0].text = 'Collaborator'
hdr_cells[1].text = 'Title'
hdr_cells[2].text = 'N'
for k in range(len(cols)):
row_cells = ntable.add_row().cells
row_cells[0].text = cols[k]
row_cells[0].width = Inches(1)
row_cells[1].text = bestcol[k]
row_cells[1].width = Inches(5)
row_cells[2].text = str(ncols[k])
row_cells[2].width = Inches(0.5)
margin = Inches(0.5)
sections = document.sections
for section in sections:
section.top_margin = margin
section.bottom_margin = margin
section.left_margin = margin
section.right_margin = margin
document.add_page_break()
document.save('ScholarSheets/'+table.Name[qt]+'.docx')
except:
print(str(qt) + 'not')
这将为我们留下一个最终的 Word 文档,看起来有点像这样:
图 4。Charles Geier 博士的示例输出文档。
有了这份文件,我们现在有了关于我们教授的数据的简明摘要,并可以开始编辑笔记和执行更有针对性的文献搜索,以选择作为面试过程中您的审查的一部分。我们可以通过阅读教授之间的共享论文,制定潜在的问题,并记下笔记来一举两得。如果你能走到这一步,谢谢你的支持,我希望你这个赛季表现最好!如果您想更深入地了解,请不要忘记查看第 2 部分的主题建模。
准备 AWS 数据库专业认证— 7 个步骤
原文:https://towardsdatascience.com/preparing-for-the-aws-database-specialty-certification-7-steps-2b43aeda2e4e?source=collection_archive---------29-----------------------
带有视觉主题风景地图的指南
当我通过认证考试时,LinkedIn 认证组的一些社区成员问我的准备情况,并指出 Safari Books Online、Packt Publishing 或 Udemy 没有课程。
在这里,我详细介绍了建议的准备步骤,并分享了我创建的帮助我准备考试的技术主题景观图。
了解知识领域
了解认证的 5 个方面。这是第 0 步。
- 特定于工作负载的数据库设计
- 部署和迁移
- 管理和运营
- 监控和故障排除(包括性能)
- 数据库安全
最初不要太在意权重,对所有的都同等重要。
RDS 和 Aurora 总是最常见的话题,但这仅仅是因为它们有大量的风格和版本。
AWS 上的数据库是一个非常庞大的主题,涉及 AWS 架构知识和数据库知识的交叉。虽然解决方案体系结构助理或解决方案架构师专业认证不是强制性的,但了解这些主题非常重要。
参加考试准备培训—第一关
在 AWS 培训和认证站点进行的考试准备:AWS 认证数据库-专业培训应该是您的第一步。但是,我建议您在第一次通过时,以快节奏的方式进行培训,并浏览主题。
这个想法是将你自己的经验与认证考试的要求对应起来。可能有些领域你有很深的知识,很好地符合考试要求,而有些领域你可能不会在日常工作中遇到,需要一些关注。
阅读架构良好的白皮书
这是准备工作的第 2 步,理解数据库作为整个 AWS 架构的一部分的重要性。
数据库部分是最重要的。
AWS 数据库专业主题前景
完成这些步骤后,转到步骤 3。重点是我创建的主题风景图。用这个来发展你自己的覆盖范围和准备地图。
我在这里用神奇的绘图工具 draw.io 重新创建了我的学*地图。
下面是你阅读和使用它的方法:对于每一个内圈的项目,从外圈里挑选一个项目,阅读或思考它。通过实践经验或从视频和最佳实践文档中使用的知识,了解组合(内圈+外圈),如何最好地使用它,它如何影响您的架构/设计,以及如何最好地处理它。
以下是预期的范围和深度(根据我的经验):
- 希望对 Neptune、QLDB、DocumentDB、CloudFormation 和 elastic cache(memcached)有基本的了解。
- 对红移、弹性缓存(Redis)、网络、安全、成本和 Lambda 有中等水平的了解
- 关于 Dynamo、RDS(各种风格)、Aurora (MySQL 和 PostgreSQL)、迁移和 HA 的详细知识水平。
阅读 AWS 文档中的最佳实践部分
这是第 4 步,您将逐步导航到 AWS 文档中的每个产品,并专门查看每个产品的“最佳实践”部分。
吸收知识,反思建议。
AWS 回复:发明视频
准备的第五步应该是在 YouTube 上看 AWS re:Invent 2017 视频(DAT3xx 和 DAT4xx)。2017 年的所有视频(以及 2016 年的一些视频)都有适当的深度,有助于准备工作。
re:Invent 2018/2019 中的一些新功能有助于实现新功能。
给出了一些链接
AWS re:Invent 2017:新发布!亚马逊 Neptune 概述和客户用例(DAT319)
AWS re:Invent 2017:新发布!亚马逊海王星上的深潜(DAT318)
AWS re:invent 2017:迁移到 Amazon Au (DAT315)并在其上运行的实践者指南
AWS re:invent 2017:从 Oracle 和 SQL Server 迁移到亚魔卓的最佳实践(DAT309)
AWS re:invent 2017:在 AWS 上运行 PostgreSQL 的最佳实践(DAT314)
AWS re:invent 2017:深入探索亚马逊关系数据库服务(RDS) (DAT302)
AWS re:invent 2017:深入了解亚马逊 Aurora MySQL 兼容版(DAT301)
AWS re:invent 2017:深入了解亚马逊 Aurora PostgreSQL 兼容版(DAT402)
AWS re:invent 2017:elastic cache 深度挖掘:最佳实践和使用模式(DAT305)
AWS re:invent 2017:将数据库和数据仓库迁移到云:获取 St (DAT317)
AWS re:invent 2017:将您的 SQL Server 数据库迁移到 Amazon RDS (DAT312)
AWS re:invent 2017:在亚马逊 RDS 上运行 Oracle 数据库(DAT313)
AWS re:invent 2017:重复什么时候用哪个数据库?
AWS re:invent 2017:~ REPEAT ~ Amazon dynamo db(dat 403-R)的高级设计模式
参加考试准备培训—第二遍
我建议再参加一次考试准备培训,这是第二次,现在重点更加突出。
此外,这也是浏览培训中列出的所有链接的时间。
参加模拟考试
此时,您应该已经准备好参加认证考试了。
参加模拟考试可能会有帮助,如果只是为了评估难度水平,以及最后一分钟的检查,以确保你对主题有体面的覆盖面。
不要因为模拟考试只有 20 道题,权重和覆盖面计算无法和真题匹配,就去关注分数。
结论
这份 AWS 数据库专业认证考试准备指南和可视化主题景观图应该对数据库从业者和数据架构师有用。
为 TensorFlow 对象检测准备开放图像数据集
原文:https://towardsdatascience.com/preparing-open-images-dataset-for-tensorflow-object-detection-c3da6e688eb5?source=collection_archive---------23-----------------------
使用开放图像创建张量流对象检测数据集的指南
图片由安德鲁·尼尔在 Unsplash 上拍摄
数据是建立深度学*模型时要考虑的最强支柱之一。数据越精确,模型越有经验。为了训练深度学*模型,你需要大量的数据,你可能想要创建自己的数据,或者你可以使用互联网上的公共数据集,如可可女士、 ImageNet 、开放图像等。
有时,这些数据集遵循不同的格式,而您想要定型的模型遵循另一种格式。当数据非常大时,使数据可供模型使用变得很麻烦。这是我在创建自己的物体探测器时偶然打开的。
目标检测是计算机视觉的一个分支,它可以定位图像中的特定目标。我使用了 Tensorflow 对象检测 API 来创建我的自定义对象检测器。为了创建我的探测器,我从开放图像 V4 数据集创建了我的数据。数据集包含 600 个类和总共约 170 万幅图像,分为训练集、验证集和测试集。它已经更新到 V6,但我决定用 V4,因为有两个工具我们很快就会看到。
为了训练一个 Tensorflow 物体检测模型,你需要创建TF records,它使用了以下:
1。图像
2。图像注释
“打开图像”既有图像,也有它们的注释。但是,所有的注释都放在一个文件中,当您需要特定类的数据时,这个文件会变得很笨拙。为了处理这个问题,我决定将数据转换成 PASCAL VOC 格式。现在,你可能会问什么是 PASCAL VOC?简而言之,PASCAL VOC 格式为每个图像创建一个 XML 文件,该文件包含图像中每个对象的边界框的坐标。很有条理,对吧?如果你想了解更多关于 PASCAL VOC 的知识,这里的是一个很棒的参考。
现在说得够多了,让我们看看实际情况吧!
但是但是但是!在我们开始之前,你可能想和我一起走,所以这是我的 github 回购的笔记本。我们开始吧!
我建议使用 google colab,因为这些工具可能需要的一些文件很大,可能对未来的用例没有用处。
- 这个工具让我们可以下载特定类别和特定数量的图像。通过克隆 repo 下载该工具。
- 下载完成后,您会发现一个 classes.txt 文件。这里您需要提到您想要收集其数据的类名。你可以在这里找到课程列表。例如,我将采取类'手机'和 98 个图像相同。
- 粘贴以下代码:
当您第一次运行脚本时,该工具可能会要求您下载一些文件,允许它。下面是提示符的样子
开放图像数据集工具包的屏幕截图
该工具为每个分割创建目录,并为这些目录中的每个类创建子目录。
4.现在,让我们使用以下脚本来看看每个类的文件数量:
输出以查看手机目录中的文件
嗯(表示踌躇等)..但是我提到了 98 张图片,对吧?它会创建一个名为“Label”的文件夹,其中包含每个图像的注释。
让我们看看文件夹“标签”包含什么:
标签目录中的内容
我们为每个图像获取一个注释文件。但是,我们说完了吗?没有。注释不符合 PASCAL VOC 格式。因此,我们需要另一种工具,可以将这些注释转换成所需的格式。
这个工具为我们做最后的工作。克隆它。我稍微修改了这个工具,让名字中有一个以上单词的类可以在我的报告中找到这里。
完成后,运行以下命令来转换注释文件:
这里, sourcepath 是每个类的“标签”文件夹的位置, dest_path 是存储 XML 注释的位置。
一旦创建了 XML 注释,我们就不再需要 txt 注释了。让我们删除它们:
这将删除所有类别目录中名为“Label”的所有文件夹。
现在您已经有了过滤后的数据集!😀
提示:一旦数据集准备好,使用 labelImg 验证注释。对象有时可能被错误地注释。
就是这样,伙计们!感谢您的阅读😊
为变压器预培训准备数据—书面报告
原文:https://towardsdatascience.com/preparing-the-data-for-transformer-pre-training-a-write-up-67a9dc0cae5a?source=collection_archive---------32-----------------------
为 Transformer (BERT、RoBERTa、XLM、XLNet 等)收集、连接、重排和标记所需的数据。)预培训
Devlin 等人的 BERT 论文的截图(2018)
仅在一年多前,瓦斯瓦尼等人(2017)推出的 Transformer 模型的最知名化身,Devlin 等人(2018)推出的BI 方向En 编码器 R 表示来自Ttransformers(更好地称为 BERT )模型,此后在自然语言处理(NLP) 社区中变得非常受欢迎。这不仅是因为它在一系列 NLP 任务上的最先进的结果,也是因为它可以通过他们自己的库公开获得,还因为越来越受欢迎的 T21 变形金刚库。
伯特和其他变形金刚像罗伯塔、和 XLNet 都是在多伦多图书语料库数据集(朱等人,2015)和英语维基百科的串联上(以及其他)被预训练的。由于前者不再公开提供,而后者需要大量的预处理,这篇文章展示了收集、连接、重排和标记自己试验这些变压器模型所需的数据所涉及的一切(和代码)。
收集(和预处理)数据
多伦多图书语料库数据集
如前所述,朱等人(2015)的多伦多图书语料库(TBC) 数据集已不再公开。然而,数据集的来源仍然可用。因此,您可以按照我之前的这篇文章自己复制 TBC 数据集:
[## 复制多伦多图书语料库数据集——一篇综述
复制不再公开的多伦多图书语料库数据集,从其…
towardsdatascience.com](/replicating-the-toronto-bookcorpus-dataset-a-write-up-44ea7b87d091)
英语维基百科
虽然 维基百科转储 是免费提供的,但在准备用于变压器预训练之前,它们仍然需要被提取、清理和预处理。因此,类似于 TBC 数据集,您可以在我之前的另一篇文章之后这样做:
[## 为 NLP 模型训练预处理 Wikipedia 转储—书面报告
下载、提取、清理和预处理 NLP 模型的维基百科转储(例如像 BERT 这样的变压器…
towardsdatascience.com](/pre-processing-a-wikipedia-dump-for-nlp-model-training-a-write-up-3b9176fdf67)
➕🔀串联和混排数据
现在,您已经收集了多伦多图书语料库数据集和英语维基百科,我们可以继续连接和重组这两者。这可以在 Bash 或类似的软件中使用下面的代码很简单地完成:
cat tbc_replica.txt en_wiki.txt | shuf >> concat_shuffled.txt
💥将数据符号化
收集、连接和重组数据后,现在剩下的就是对数据进行标记。在理想情况下,我们会动态地对数据进行标记,但是出于性能原因,我们会对数据进行预标记。为此,我们使用最*发布的速度惊人的 标记器库 ,也是通过下面的代码由 HuggingFace 实现的:
要对数据进行令牌化,首先在这里下载 vocab 文件,然后在您的终端中运行下面的命令:python3 tokenize_data.pyconcat_shuffled.txt bert-base-uncased-vocab.txt
就这样,大功告成!现在,您可以使用您刚刚准备好的数据,自己开始试验这些 Transformer 模型。🤗
参考
[1] J. Devlin 等人, Bert:用于语言理解的深度双向变换器的预训练 (2018), arXiv 预印本 arXiv:1810.04805 。
[2]瓦斯瓦尼等人,注意力是你所需要的全部 (2017),神经信息处理系统进展(第 5998–6008 页)。
[3]朱等,【书与电影的对齐:通过看电影和看书走向故事化的视觉解释】 (2015),IEEE 计算机视觉国际会议论文集(第 19–27 页)。
预处理和准备面部数据集,为 CNN 模型做好准备
原文:https://towardsdatascience.com/preprocess-and-prepare-a-face-dataset-ready-for-cnn-models-885867907eb0?source=collection_archive---------20-----------------------
让我们使用 Google Colab、TensorFlow 和 Dlib 从 IMDB-WIKI 数据集中提取人脸,并以 CNN 友好的格式存储在 Google Drive 中。
来源:IMDB-WIKI 数据集
你好朋友们。在本文中,我将对 IMDB-WIKI 数据集进行预处理,从这些图像中提取人脸,并将它们与其他有用的信息(如姓名、年龄和性别)一起保存到 Google Drive。数据将作为对象本身存储在。泡菜格式。最棒的是,你不必在你的机器上运行一行代码,而是在 Google Colab 上运行。
在深入研究我们的代码之前,我将简要介绍一下 Google Colabs。你是否曾经担心过你的电脑处理能力不够或者你缺少一个 GPU,现在你不必再担心了,因为谷歌已经通过谷歌实验室提供了一个解决方案。通过你的浏览器在谷歌的服务器上使用 GPU 进行令人眼花缭乱的快速执行。
Google Colabs 为用户提供了一个 Jupyter 笔记本,用于交互式编码体验。它与 GitHub 无缝连接。您创建的所有笔记本都存储在您的 google drive 中。
由于我们将使用 Google Colabs,我建议您学* Jupyter 笔记本的工作原理,因为它会让您对环境感到更加舒适。如果你想了解更多关于 Google Colab 的信息,你可以阅读这篇由 fuat 撰写的 Google Colab 免费 GPU 教程。
在我们开始编码之前,让我简单介绍一下我们将如何从这里开始。
- 我将在 Google Colab 上创建一个笔记本
- 我们将把 Google drive 安装到笔记本上。
- 我们将使用这个笔记本来提取和处理数据集,并将其保存在我们的 Google Drive 中。
在本文结束时,您将准备好使用 CNN 模型的数据集。
我们开始吧。
在本文中,我详细解释了预处理过程中需要的每个步骤。我还解释了每一行代码,这样你就不会感到困惑。
1)创建您的第一个笔记本
访问 Google Colabs 主页。您将看到一个欢迎笔记本。如果您还没有登录您的 Google 帐户,请登录。已经签到的可以跳过这一步。
图 1:显示 Colab 笔记本上的登录按钮
登录后,您将看到一个弹出框。点击右下角的“新建笔记本”按钮。
图 2:创建新笔记本
将创建一个新笔记本,您将被重定向到该笔记本。它也将被保存在你的硬盘中一个名为 Colab Notebooks 的文件夹中。
现在将你的笔记本重命名为“extract _ data _ and _ preprocess . ipynb”。
2)开始编码
打开您创建的“extract data _ and _ preprocess . ipynb”笔记本。
将运行时类型改为 GPU:
- 点击运行时选项,然后转到“更改运行时类型”。
- 选择硬件加速器选项,将其从无更改为 GPU 并保存。
图 4:将运行时改为 GPU
将你的谷歌硬盘安装到你的笔记本上。
**Note:** You will be able to mount your drive only after you have connected to a runtime. To connect to a runtime if not connected already click on the connect button on the top right corner.
图 5:安装 Google Drive
现在,我们必须导入我们将在整个数据预处理过程中使用的所有包。
代码块 1:导入所需的包。
在 Colab 中,可以在不同的单元格中编写代码,并以您喜欢的任何顺序逐一执行它们。现在,执行导入所有包的单元格。
我们将使用 dlib 的基于 CNN 的人脸识别模型来从我们的数据集中的图像中检测和提取人脸。基于 CNN 的模型比 dlib 中的 Hog 模型慢,但更精确。要了解更多关于他们的区别,请阅读由阿伦·彭努萨米撰写的文章基于 CNN 的 dlib 人脸检测器。
我们必须下载 CNN 模型运行所需的权重。因此,在一个新的单元格中,让我们编写代码来下载权重。
代码块 2:下载 Dlib 的 CNN 人脸识别模型的权重。
我来解释一下代码:
第 2 行:我已经使用 Keras 库中的 get_file 函数下载了权重。下载的文件将存储为“mmod _ human _ face _ detector . dat . bz2”
第 3 行:‘cache _ subdir’—此处必须给出下载文件的存储路径。
第 4 行:‘origin’—待下载文件的下载网址
第 6–10 行:在这些行中,使用 bz2 包打开下载的压缩文件,以二进制格式读取内容并存储在“mmod_human_face_detector.dat”文件中。该文件稍后将被 CNN 模型使用。
接下来让我们下载数据集。IMDB-WIKI 数据集拥有超过 45 万张图片。处理这么多的图像并从中提取数据将花费很多时间,所以我将只使用维基数据集中的那些图像。那些希望使用 IMDB-WIKI 的人可以在下面的代码中替换“dataset_url”,将“data_key”值更改为“IMDB ”,将“mat_file”值更改为“imdb.mat”。
代码块 3:下载和提取数据集。
第 1–2 行:数据集的下载 URL 和将从文件中提取的文件夹名称。文件夹名称与提取无关,稍后我们的代码中将会用到它。
第 4–7 行:使用与之前相同的功能,并给它一个不同的下载 URL。我们将“extract”参数设置为 True,这样函数将自己提取数据集。之前我们没有使用相同的函数提取,因为 bz2 文件格式不支持提取。
第 9 行:‘wiki’是所有图像元数据存在的密钥。当您加载。mat 文件并查看它。
第十行:的名字。包含图像元数据的 mat 文件。
现在已经下载并提取了数据集。让我们加载。解压缩的文件夹中存在 mat 文件。由于文件是 MatLab 格式,我们必须将其转换为 Python 数据类型。
代码块 4:加载。mat 文件和初始化所需变量
第 1 行:我们正在加载。使用 scipy 包处理数据格式转换的 mat 文件。
第 2 行:加载的文件为字典格式。它有一个关键的“维基”,其中有其余的数据。为了更好地理解加载文件中的所有数据,您可以打印字典或访问 IMDB_WIKI 网站。
第 3 行:我们将所有图像的路径加载到 route 变量中。文件中的数据不是一种非常容易访问的格式,所以不要与我使用的多维数组访问相混淆。
第 4–9 行:初始化所有基本变量。
准备数据集的所有要求现在都已完成。在我们开始处理它之前,让我们编写代码来看看我们从数据集得到了什么,我们是如何处理它的,以及我们将要存储什么。
代码块 5:查看我们将要存储哪种图像的代码
第 1 行:创建 dlib 的基于 CNN 的人脸检测模型的对象。的。作为参数传递的 dat 文件是我们首先下载并提取的文件。
第 6 行:选择一个随机索引,从该路径加载图像并显示。
第 7 行:让这一行保持原样,我将在下一步简要解释。
第 8 行:从给定路径加载图像
第 9 行:由于 OpenCV 使用 BRG 格式,我们正在将图像转换为标准的 RGB 格式。
第 10 行:查找给定图像的面部坐标。它将返回图像中人脸的坐标列表。
第 11–22 行:使用 dlib 模型提供的人脸坐标,我们在人脸周围画一个方框。然后,我们使用 TensorFlow 提供的 crop_to_bounding_box 函数裁剪出该区域。然后我们显示两幅图像。裁剪后的人脸图像是每幅图像将要拍摄和存储的内容。
当您执行上面的单元时,您将看到来自您的数据集中的两个随机图像,这将向您显示图像将如何被处理。
图 6:显示提取的人脸样本。(来源:IMDB-WIKI 数据集)
终于到了处理整个数据集并从中提取我们需要的数据的时候了。
代码块 6:处理图像并提取人脸和其他所需数据。
第 4 行:对数据集中的所有图像运行一个循环,“I”是我们用来从 route 变量中的列表获取第 I 个路径的索引。然后,我们在该路径获取图像。这样,我们可以读取数据集中的所有图像。
第 7 行:使用 try-except 块,不要让一些错误的图像阻止我们的进程。
第 8–9 行:我正在访问的数据是创建该数据集的人对图像集的面部评分。所以我们忽略了所有没有人脸的图片。这将加快提取速度。我们还检查我们试图访问的图像的性别数据是否也可用。这将有助于我们忽略数据集中存在的所有破损图像。
第 10–14 行:如前所述,读取图像并检测其中的人脸。
第 15 行:我们只考虑一个只有一张脸的图像。
第 18 行:取 CNN 模型返回的人脸坐标。有时,当人脸出现在图像的角落时,模型往往会给出图像外部的坐标,使用 max 函数,我们可以确保坐标在图像内部。
第 19–22 行:获取脸部的高度和宽度。该模型返回“左上”和“右下”坐标。在下一行中,我们确保坐标在图像中。
第 24 行:使用 TensorFlow 的 image 类提供的函数从图像中裁剪人脸。
第 28 行:将图像大小调整为 32x32,因为图像大小对于任何 CNN 模型的训练都无关紧要,所以,我们可以减少图像所消耗的空间。
第 31 行:将提取的、调整大小的面部图像附加到图像列表。
第 32 行:出生日期以序数日期格式给出。因此,使用 datetime 类,我们将序数日期转换为 datetime 类对象,从中我们可以单独提取年份。
第 33–35 行:将各个数据添加到各自的数组中。
第 37–51 行:处理上述过程中发生的异常。所有阵列中数据的一致性非常重要。因此,当错误发生时,我们从列表中弹出图像数据和其他元数据。
现在我们已经完成了数据集的处理,是时候将数据存储到我们的驱动器中了。
代码块 7:保存包含所有已处理数据的字典。
第 1–7 行:用我们提取的数据创建字典。
第 8–9 行:检查我们将要存储数据的目录是否存在,如果不存在,我们就创建它。
第 10–12 行:我们在追加二进制模式下创建一个文件,并将我们的字典转储到其中。
**Note:** While dumping a huge object to Google Drive, it is advisable to break the data into parts and store it. The session may crash and the runtime will restart if a large file is being stored in the drive.
我附上了我的“extract _ data _ and _ preprocess . ipynb”笔记本的链接供你参考https://colab . research . Google . com/drive/1 u5 or-riuleztsmo 7 en _ h85 _ HqgIPEVlN。
希望这篇文章值得你阅读。
如有任何疑问,请随时联系我。
Instagram: nachijr4
电子邮件:nachi2muthu13@gmail.com
中等:纳赤木图
领英:纳奇穆图
预处理数据:特征缩放
原文:https://towardsdatascience.com/preprocessing-data-feature-scaling-cc28c508e8af?source=collection_archive---------37-----------------------
sklearn 的一些重要特征缩放技术
照片由来自佩克斯的阿多尼·加博尔拍摄
一般来说,在更新每个机器学*模型的特征时,特征缩放是一个必要甚至是必不可少的步骤。为什么这很重要?很简单,因为我们用于预测或聚类的每个算法背后都隐藏着一些数学公式。这些数学公式几乎没有意识到每个要素之间的数值范围的变化,当涉及到梯度下降时,这一点是显而易见的!
事实上,未经缩放的数据会导致可视化困难,更重要的是,它们会降低许多机器学*算法的预测性能。这种类型的数据也可以减缓许多基于梯度的估计量的收敛,或者完全阻止它。
事实上,许多估计量是在假设所有特征在可比尺度上变化的情况下设计的。特别是,基于梯度的估计器通常假设训练数据已经标准化(具有单位方差的中心特征)。一个显著的例外是基于决策树的估计器,它对数据的任意缩放都是鲁棒的。
让我们举一个例子:假设你正在进行房价预测,你将拥有以下类型的特征:价格、表面、房间数量等。当然,这个数据框架的价值尺度根据特征是完全不同的。但是,您必须使用相同的算法来处理它们。这就是特性缩放的必要性所在!您的算法确实需要混合[0… 100,000]美元的价格、[10… 500]平方米的面积、从[1..10]房间。因此,缩放包括将这些数据放在同一级别。
如果您没有明智地应用特征缩放,您将会观察到缓慢的学*和降低的性能。
幸运的是, Scikit-Learn 将帮助我们再次完成这项工作,但是在使用任何技术之前,我们必须了解每种技术是如何工作的。
基本上,Scikit-Learn(sk Learn .预处理)提供了几种缩放技术,我们将回顾 4:
- 标准缩放器
- 最小最大缩放器
- MaxAbsScaler
- 鲁棒定标器
首先,我们将创建随机数据集以及一些图形函数,这将有助于我们更好地理解上述不同技术的效果。
以下是 Python 代码:
在这段代码中,除了 trace 函数之外,我们还在一个 DataFrame (Pandas)中创建了 6 个数据集。
让我们看看我们的数据集是什么样的:
标准缩放器
我们将从风险可能最小的:StandardScaler()开始我们的缩放技术之旅。
这种技术假设数据是正态分布的。该函数将重新计算每个特征,以便数据以 0 和 1 为中心。
标准化公式统计
因此,标准化去除了平均值,并将数据缩放到单位方差。然而,当计算经验平均值和标准偏差时,异常值仍然有影响。
最小最大缩放器
这种技术通过在给定的范围(默认为[0,1])上调整来变换每个特征(x)。可以通过参数 feature_range = tuple (min,max)更改该范围。为了简单起见,下面是每个特征的变换公式:
如果这种技术可能是最广为人知的,那么它特别适用于分布不是高斯分布或者标准差很小的情况。但是,MinMaxScaler()对异常值非常敏感。在这种情况下,我们快速切换到最后一种技术:RobustScaler()。
MaxAbsScaler
当值的分布很稀疏并且有很多整数时,这种缩放技术很有用。绝对值映射在范围[0,1]内。事实上,对于只有正值的数据,此缩放器的行为与 MinMaxScaler()类似,因此也存在较大的异常值。
鲁棒定标器
RobustScaler()技术使用与 MinMaxScaler()相同的缩放原理。但是,它使用四分位数范围而不是最小-最大值,这使得它在异常值方面更加可靠。以下是重新加工特征的公式:
- Q1 (x):第一个分位数/ 25%
- Q3 (x):第三个分位数/ 75%
与以前的缩放器不同,这个缩放器使用一些基于百分位数的居中和缩放统计数据。因此,它们不受非常大的边际异常值的影响。因此,变换后的特征值的结果范围比先前的定标器更大,更重要的是,大致相似。
结论
让我们总结一下我们刚刚遇到的特征缩放技术:
- 使用
[**MinMaxScaler**](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.MinMaxScaler.html#sklearn.preprocessing.MinMaxScaler)
或[**MaxAbsScaler**](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.MaxAbsScaler.html#sklearn.preprocessing.MaxAbsScaler)
可以将特征缩放到一个范围,通常在零和一之间。 [**MaxAbsScaler**](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.MaxAbsScaler.html#sklearn.preprocessing.MaxAbsScaler)
是专门为缩放稀疏数据而设计的,[**RobustScaler**](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.RobustScaler.html#sklearn.preprocessing.RobustScaler)
不能适用于稀疏输入,但您可以对稀疏输入使用transform
方法。- 如果您的数据包含许多异常值,使用数据的平均值和方差进行缩放可能不会很好。在这种情况下,你需要用
[**RobustScaler**](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.RobustScaler.html#sklearn.preprocessing.RobustScaler)
来代替。
这篇文章所基于的 Jupyter 笔记本可以在这里找到。
参考
- 比较不同标量对有异常值的数据的影响。https://sci kit-learn . org/stable/auto _ examples/preprocessing/plot _ all _ scaling . html
- 预处理数据。https://scikit-learn.org/stable/modules/preprocessing.html
- 我应该标准化数据吗?http://www . FAQs . org/FAQs/ai-FAQ/neural-nets/part 2/section-16 . html
张量流 CNN 模型中的预处理层 2
原文:https://towardsdatascience.com/preprocessing-layer-in-cnn-models-for-tf2-d471e61ddc2e?source=collection_archive---------22-----------------------
一种使 CNN 模型更不容易出错、更易于开发人员使用的技术
来源:pexels.com
机器学*新手最常犯的一个错误是忘记标准化输入图像。难怪!当你进行迁移学*时,每个模型需要不同的输入标准化。比如 VGG需要从 RGB 图像中减去这个矢量【123.68,116.779,103.939】。 MobileNetV2 需要区间< -1,1 >的输入。PyTorch 模型通常使用不同的归一化方法。这个技巧可以在将来为您节省大量时间和 bug。在将图像输入到模型之前,不需要进行标准化,您可以简单地将该层添加到您的模型中(计算图)。
使用旧的 TensorFlow 1(安息吧),您可以简单地向图形添加预处理操作,并冻结该模型。然而,在 TensorFlow 2+中,您需要创建自己的预处理层。
因此,首先定义我们的预处理方法(这是针对 MobileNetV2 的):
然后创建从 tf.keras.layers.Layer 继承的自定义层,并在输入上使用 call 方法中的函数:
创建模型时,在调用预训练模型的基础模型之前插入层(tf.keras 的功能 API):
就这样!
从现在开始,您的模型总是只接受 RGB [0,255]图像,并且输入的规范化在模型内部完成。如果您以 Keras .h5 格式保存了这样一个模型,那么不要忘记在模型加载期间指定定制对象。我总是建议将模型保存为 SavedModel 或 TFLITE 格式,因为模型中的一切都被冻结了,可以随时部署了!
用预处理层你:
- 节省了其他人调试你的模型的大量时间。
- 在使用您的模型时,您不需要告诉您的客户以任何方式标准化图像。将不同版本/架构的模型部署到移动设备上的计算机视觉应用程序时,这通常很痛苦。
下次见!
米哈尔
在 Python 中预处理文本数据:Kaggle 简介
原文:https://towardsdatascience.com/preprocessing-text-data-in-python-an-introduction-via-kaggle-7d28ad9c9eb?source=collection_archive---------14-----------------------
作为一名数据科学家,您将不可避免地与文本数据打交道。处理文本数据(如推文、摘要或报纸文章)与处理传统的数字数据(如温度或金融数据)截然不同。
这种差异不比预处理期间大。虽然数字数据的预处理很大程度上依赖于数据(哪些列缺少大量数据?是否有任何列没有准备好进入模型?是否需要对任何列进行一次性编码?),文本数据的预处理实际上是一个相当简单的过程,尽管理解每个步骤及其目的并不那么简单。
预处理文本数据的目的是将数据从原始的可读形式转换成计算机更容易处理的格式。大多数文本数据以及我们将在本文中使用的数据都是以文本字符串的形式出现的。预处理是获取原始输入数据并准备将其插入到模型中的所有工作。
这篇文章介绍了完成 Kaggle 的灾难推文挑战的整个过程。尽管本文包含了整个过程,但我们主要关注预处理步骤。本文描述了典型的文本数据预处理所涉及的各个阶段,并解释了每个阶段的基本原理和效果。有关其他步骤的更多信息,请参见每个部分中包含的链接。
这个 Kaggle 数据集由使用灾难相关语言的推文组成。目标是创建一个分类器,可以确定包含灾难相关语言的推文是否实际上是关于灾难的,或者是出于不同的非紧急目的使用相同的语言。
例如,推文“@bbcmtd 批发市场着火了【http://t.co/lHYXEOHY6C ”和“哭着要更多!“让我燃烧吧”都包含关键词“燃烧”,但其中只有一个是指灾难。对我们来说,很明显,前一条推文描述的是杂货店的火灾,而第二条推文指的不是真正的火灾或灾难——更有可能是一场音乐会。然而,如果一名数据科学家想从 Twitter 上搜集关于真实灾难的推文,以提醒医疗服务,他们将面临一个挑战:他们必须建立一个分类器,可以分辨出尽管两条推文都包含一个表示“着火”的单词,但其中只有一条描述的是真正的危险火灾。
事实证明,构建这样的分类器并不困难——我们将使用逻辑回归模型来完成。从我们阅读的 tweet 到我们的模型可以学*的数据的关键是预处理。
方法
对于本文,我们将基本上完成 Kaggle 挑战;即,为灾难推特数据集建立分类器。我们的大部分解释将集中在预处理部分,尽管我们将链接到每个其他步骤的有用文章。我们的方法包括数据导入、数据探索、预处理、模型训练和呈现结果。总的来说,这种方法相当简单,因为本文主要关注的是预处理。
首先当然要导入相关的包:
数据导入
接下来,我们导入数据。最简单的方法是首先从 Kaggle 下载数据,可以在这里找到。然后,阅读 CSV 的使用熊猫。显然,路径取决于计算机上各自的文件位置。
数据探索
首先,让我们看一下我们的数据:
灾难推文数据由四列组成:“关键词”、“位置”、“文本”和“目标”。“关键词”指的是推文中表示潜在灾难的特定单词。只有当 Twitter 用户在发送推文时标记了位置,才会存在“位置”数据。“文本”包含推文的文本。最后,“目标”是我们的因变量——如果推文指的是合法的灾难,则为 1;如果推文是误报,则为 0。
显然,在“关键字”和“位置”栏中有许多“不”字。但是有多少?这些列中的数据密度可能是一个问题。
“关键词”实际上有 99%的密度,但“位置”只有 67%的密度。我们会放弃它,因为它丢失了太多的数据。我们也将删除“关键字”,但原因不同。“关键字”是重复的,因为它只包含“文本”中的一个词。“keyword”将提供零洞察力来发现灾难性推文和非灾难性推文之间的区别,这两种推文都具有关键字“finding”。我们将删除这两列,只将“文本”作为独立变量。“文本”具有 100%的密度。
关于文本数据的探索性数据分析,我推荐这篇文章。
预处理
我们的预处理方法包括两个阶段:准备和矢量化。准备阶段包括清理数据和剔除多余内容的步骤。步骤是 1。删除 URL 和 Twitter 句柄,2。将所有文本变为小写,请按 3。删除号码,请按 4。删除标点,请按 5。标记化,6。删除停用字词,和 7。词汇化。停用词是通常不添加任何意义的词。例如,查看 NLTK 停用词的列表。
标记化步骤获取一个文本字符串,并将其转换成一个标记列表(单词)。它通过解析字符串和用空格分隔来实现这一点。这意味着' hello world '变成了['hello ',' world']。在准备步骤之后执行此步骤非常重要,因为标记化会将标点符号作为单独的标记。
引理化步骤获取记号,并将每个记号分解成它的引理。一个引理本质上是一个词的基本形式,切断了变位和变位的途径。例如,“不同”会变成“不同”,“奔跑”会变成“奔跑”,“卡车”会变成“卡车”。词汇化甚至可以将“was”变成“be ”,因为 nltk 词汇化器利用了词汇表,而不是仅仅依赖于算法。
下面是准备步骤的代码。remove_urls()使用了我在 StackOverflow 上发现的一个棘手的正则表达式操作。其他函数都是不言自明的。
现在让我们将“text”列通过这个预处理管道。我们不必担心 NaNs,因为我们之前看到“text”列具有 100%的密度。
您可能已经注意到,预处理()函数有一个额外的行,它重新加入了标记列表。我们实际上更喜欢符号列表,但是我们的矢量器不接受符号列表作为输入,只接受字符串。
我们的数据现在看起来像这样:
在我们将训练数据放入矢量器之前,我们还需要准备测试数据。为了分别转换训练和测试数据,矢量器必须适合整个文本语料库(包括训练和测试数据集)。
对测试数据做同样的预处理。
现在,我们将训练和测试“pp_text”列合并到我们的文本语料库中。
现在我们已经为矢量化做好了准备。我们使用方便的 scikit-learn 工具 TfidfVectorizer。
该向量机已被应用于语料库。现在我们转换训练和测试数据。在本文中,我们将只使用 train_transform 数据。当我们在看不见的数据上测试我们的模型时,将使用 test_transform 数据。
我们现在有两个变量准备回归。y 列仍然是之前的“目标”列,通知我们这条推文是否是真正的灾难推文。x 列现在看起来像这样:
刚刚发生了什么?到目前为止,我们的所有步骤都有助于准备数据,但没有彻底改变它。现在我们的数据甚至无法识别。
根据 scikit-learn 的网站介绍, TfidfVectorizer 实际上是 CountVectorizer 后跟 TfidfTransformer 。CountVectorizer 首先获取我们的文本文档,并对它们进行标记,就像我们之前所做的那样(但是后来没有这样做,因为这个函数不接受标记化的数据作为输入)。一旦数据被标记化,CountVectorizer 就会收集一个由每个唯一标记组成的单词包,并为每个单词分配一个数字。最后,CountVectorizer 将标记化的文本数据表示为标记计数矩阵,如下所示:
此图像显示了 CountVectorizer 矩阵的前六行。这些行告诉我们,在文档 0 中,单词 368、3403、4146、5201、8491 和 11223 都出现了一次。我们对这些计数感兴趣,因为如果一个单词在一个文档中出现多次,这个单词可能非常重要。
TfidfTransformer 只是将这个令牌计数矩阵转换成一个词频-逆文档频率(tf-idf)表示。使用 tf-idf 很重要,因为简单地使用令牌计数可能会产生误导。以前,我们假设如果一个单词在一个文档中出现多次,那么它就是重要的。如果这个词在整个语料库中非常常见呢?那么它在我们当前文档中的高频率就不那么重要了,因为这个词在其他地方出现得如此频繁。
Tf-idf 通过将频率(基本上是计数)乘以逆文档频率(1/文档频率)来达到平衡。这意味着,如果单词 1 在文档 A 中出现一次,但在整个语料库中也出现一次,而单词 2 在文档 A 中出现四次,但在整个语料库中出现 16 次,则单词 1 将具有 1.0 的 tf-idf 分数,而单词 2 将仅获得 0.25 的分数。单词 2 在文档 A 中的重要性被其在语料库中的高频率所冲淡。(这是对实际 tf-idf 方程的简化解释,比较复杂。)
因此,我们得到了文档 0 的这种表示:
注意,在 CountVectorizer 表示中,文档 1 中的所有标记只出现了一次。现在,在 tf-idf 表示中,一些令牌比其他令牌具有更高的分数。Tf-idf 为我们的数据增加了一层细微差别。
我们的数据没有经过预处理,我们已经准备好进入建模阶段。
型号
现在是将我们的数据分成训练集和验证集的好时机。
现在,我们可以使用 scikit-learn 训练我们的模型,即逻辑回归。
结果
我们的模型已经被训练好了。现在让我们得到它对验证集的预测。
在我们的验证集上测试模型的结果呢?
这个结果明显好于抛硬币,这是一个好迹象。为了真正了解我们的模型是否表现良好,我们必须将其与 Kaggle 排行榜上其他人的表现进行比较。
我们在现实中表现如何?我使用本文中描述的模型对 Kaggle 给出的测试数据进行预测,然后将这些预测提交给 Kaggle。结果呢?准确度分数为 0.80572,略好于我们的验证集结果。这使我们在 3341 个提交的作品中排名第 1266 位(尽管前 428 个提交的作品都有超过 0.99 的分数——高得可疑)。干得好。
结论
预处理文本数据是一个漫长的过程,但实际上非常简单。尽管不同文本数据科学任务的预处理可能有所不同,但当您下次必须进行文本预处理时,了解一个文本预处理示例会非常有帮助。我希望这篇使用 Python 进行文本预处理的指南对您有所帮助。
如果您想要最终完成 Kaggle 提交,剩下的唯一步骤是使用我们训练的模型来预测 test_transform 数据,格式化和导出这些结果,并将它们提交给 Kaggle。这些步骤显示在我这篇文章的要点这里。
资源
预处理的有用资源:
[## 词干化和词汇化
下一步:更快发布列表交叉向上:确定以前的词汇:其他语言。的目录索引
nlp.stanford.edu](https://nlp.stanford.edu/IR-book/html/htmledition/stemming-and-lemmatization-1.html) [## sk learn . feature _ extraction . text . tfidf vectorizer-sci kit-learn 0 . 22 . 2 文档
class sk learn . feature _ extraction . text . tfidf vectorizer(input = ' content ',encoding='utf-8 ',decode _ error = ' strict '……
scikit-learn.org](https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfVectorizer.html) [## sk learn . feature _ extraction . text . count vectorizer-sci kit-learn 0 . 22 . 2 文档
class sk learn . feature _ extraction . text . count vectorizer(input = ' content ',encoding='utf-8 ',decode_error='strict'…
scikit-learn.org](https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.CountVectorizer.html#sklearn.feature_extraction.text.CountVectorizer) [## sk learn . feature _ extraction . text . tfidftransformer-sci kit-learn 0 . 22 . 2 文档
将计数矩阵转换为归一化的 tf 或 tf-idf 表示,tf 表示词频,而 tf-idf 表示…
scikit-learn.org](https://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfTransformer.html#sklearn.feature_extraction.text.TfidfTransformer)
延伸阅读:
[## NLP 第 3 部分|文本数据的探索性数据分析
让我们更好地理解我们新清理的数据集
medium.com](https://medium.com/@kamilmysiak/nlp-part-3-exploratory-data-analysis-of-text-data-1caa8ab3f79d) [## sklearn.linear_model。逻辑回归-sci kit-学* 0.22.2 文档
逻辑回归(又名 logit,MaxEnt)分类器。在多类的情况下,训练算法使用一对其余…
scikit-learn.org](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html)
在 Python 中预处理文本
原文:https://towardsdatascience.com/preprocessing-text-in-python-923828c4114f?source=collection_archive---------20-----------------------
建立情感分类器的一步
这篇文章是关于建立情感分类器的三篇连续文章中的第二篇。在第一篇文章的中我们进行了探索性的文本分析之后,是时候对我们的文本数据进行预处理了。简单地说,预处理文本数据就是做一系列的操作,将文本转换成表格形式的数值数据。在本帖中,我们将探讨三种不同复杂度的方法来预处理文本到 tf-idf 矩阵,为模型做准备。如果你不确定什么是 tf-idf,这篇文章用一个简单的例子来解释。
照片由 Domenico Loia 在 Unsplash 上拍摄
在我们开始之前,让我们后退一步,快速地看一下更大的画面。 CRISP-DM 方法概述了成功的数据科学项目的流程。数据预处理是数据准备阶段的关键任务之一。
CRISP-DM 工艺流程摘录
0.Python 设置
这篇文章假设读者(👀是的,你!)可以访问并熟悉 Python,包括安装包、定义函数和其他基本任务。如果你是 Python 的新手,这个是一个很好的起点。
我在 Jupyter 笔记本里测试过 Python 3.7.1 的脚本。
让我们在开始之前确保您已经安装了以下库:
◼️ 数据操作/分析: numpy,pandas ◼️ 数据分区:sk learn ◼️文本预处理/分析: nltk ◼️ 拼写检查器: 拼写检查器(pyspellchecker 安装时
一旦你安装了 nltk ,请确保你已经从 nltk 下载了【停用词】和【wordnet】语料库,脚本如下:
import nltk
nltk.download('stopwords')
nltk.download('wordnet')
如果你已经下载了,运行这个会通知你。
现在,我们准备导入所有的包:
# Setting random seed
seed = 123# Measuring run time
from time import time# Data manipulation/analysis
import numpy as np
import pandas as pd# Data partitioning
from sklearn.model_selection import train_test_split# Text preprocessing/analysis
import re, random
from nltk import word_tokenize, sent_tokenize, pos_tag
from nltk.util import ngrams
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizer
from nltk.tokenize import RegexpTokenizer
from sklearn.feature_extraction.text import TfidfVectorizer
from spellchecker import SpellChecker
1.数据📦
我们将使用 IMDB 电影评论数据集。您可以在这里下载数据集,并将其保存在您的工作目录中。保存后,让我们将其导入 Python:
sample = pd.read_csv('IMDB Dataset.csv')
print(f"{sample.shape[0]} rows and {sample.shape[1]} columns")
sample.head()
让我们来看看情绪之间的分歧:
sample['sentiment'].value_counts()
在样本数据中,情感是平均分配的。我们先把数据分成两组:训练和测试。我们将留出 5000 箱进行测试:
# Split data into train & test
X_train, X_test, y_train, y_test = train_test_split(sample['review'], sample['sentiment'], test_size=5000, random_state=seed,
stratify=sample['sentiment'])# Append sentiment back using indices
train = pd.concat([X_train, y_train], axis=1)
test = pd.concat([X_test, y_test], axis=1)# Check dimensions
print(f"Train: {train.shape[0]} rows and {train.shape[1]} columns")
print(f"{train['sentiment'].value_counts()}\n")print(f"Test: {test.shape[0]} rows and {test.shape[1]} columns")
print(test['sentiment'].value_counts())
在这篇文章中,我们将使用序列进行预处理实验。只有当我们需要评估最终模型时,我们才会预处理测试。让我们检查一下训练数据集的头部:
train.head()
好了,我们开始预处理吧!✨
2.预处理文本
根据我们的处理方式,我们可以得到不同的 tf-idf 矩阵。在构建模型时,尝试不同的预处理方法是很好的。我们将研究以下 3 种方法:
- 更简单的方法
- 简单方法
- 不太简单的方法
虽然在这篇文章中我们只讨论了将文本预处理成 tf-idf 矩阵,但是您可能还想探索其他的方法。
对于每一种方法,我们一定会衡量运行时性能,因为这是一个重要的考虑因素,特别是如果模型将被生产。我们将在下一篇文章中测试哪种方法更适合这个模型。在我们开始之前,为了使事情变得简单,让我们定义一个函数来帮助我们检查不同的方法:
def inspect(vectoriser, X):
# Fit and transform
start = time()
print(f"There are {vectoriser.fit_transform(X).shape[1]} columns.\n")
end = time()
print(f"Took {round((end-start),2)} seconds.\n")
# Inspect tokens
tokens = list(vectoriser.vocabulary_.keys())
tokens.sort()
print(f"Example tokens: {tokens[:50]}\n")
# Inspect ignored tokens
ignored = vectoriser.stop_words_
if len(ignored)==0:
print("No token is ignored.")
elif len(ignored)>50:
print(f"Example ignored tokens: {random.sample(ignored, 50)}")
else:
print(f"Example ignored tokens: {ignored}")
2.1.更简单的方法 1️⃣
让我们从三个中最简单的开始。在这种方法中,我们将让 sklearn 的 TfidfVectorizer 做所有的预处理,而不使用任何额外的定制函数。让我们使用默认参数来感受一下我们将获得多少列:
vectoriser = TfidfVectorizer()
inspect(vectoriser, X_train)
相当快。输出超过 97,000 列,前 50 个标记大部分是数字。现在,让我们调整一些参数来进一步清理标记,并更好地控制预处理:
# Simpler approach
vectoriser = TfidfVectorizer(token_pattern=r'[a-z]+', stop_words='english', min_df=30, max_df=.7)
inspect(vectoriser, X_train)
虽然上述两个版本花费的时间差不多,但后者的列数要少 7-8 倍。在这里,我们要求 TfidfVectorizer 做一些事情:
◼ token_pattern=r'[a-z]+'
:标记成字母标记——这意味着我们丢弃数字和标点符号。如果您不熟悉正则表达式 , [a-z]+
意味着令牌必须只由字母组成。
◼ stop_words='english’
:去掉停止字。
◼ min_df=30
:移除稀有令牌。当一个令牌出现在少于 30 条评论中时,我们认为它是稀有的。这将大大减少令牌的数量。尝试在没有该参数的情况下运行脚本,并查看令牌的数量。
◼ max_df=.7
:删除超过 70%文档中的令牌。这意味着如果一个令牌包含在超过 31.5K 个评论中,那么我们将忽略它们。实际上并没有很多单词因为这个而被排除在外。因此,我们甚至可以保留这个特性的默认值。
max_df
和min_df
有助于令牌选择。换句话说,在这两者的帮助下,我们可以丢弃那些或者太频繁可能对情感分类没有用处或者太罕见可能导致过度拟合的令牌。
📍这里有一个提示:如果我们这样定义参数:
TfidfVectorizer(token_pattern=r'[a-z]+', max_df=.5)
在匹配矢量器之后,您可以通过运行vectoriser.stop_words_
来找出哪些令牌由于max_df=.5
条件而被排除。当我们调用inspect
函数时,输出的'示例被忽略的标记'部分显示了那些被排除的单词的片段。现在,我鼓励你运行上面的脚本并检查vectoriser.stop_words_
。你看到了什么?你看到的大多是停用词吗?尝试将这些值更改为. 5、. 6、. 8 或. 9,然后重新运行以观察被排除的单词如何变化。这有助于理解调整某些参数如何影响预处理。现在,如果你热衷于添加stop_words='english’
或min_df=30
(不要同时添加两个,一次添加一个以了解单个参数),并检查这次排除了哪些令牌。我们将在下一篇文章中构建模型时进一步调整这些参数。
🔗如果您热衷于了解更多关于参数的信息,这里有 文档 。
这种方法是一种🍰,是不是?我喜欢这种方法,尤其是因为它做一些基本的事情真的又好又快。在我看来,从简单开始总是好的,只有在提高性能的情况下才增加复杂性。
2.2.简单方法 2️⃣
总有改进的余地。例如,在以前的方法中,单词“播放”、“播放”、“正在播放”和“已播放”被认为是 4 种不同的标记。如果我们去掉这些屈折变化的词尾,使这些符号正常化为一个唯一的符号“play”,这不是很好吗?这就是我们在这部分要做的事情!
为了使屈折词尾正常化,我们将使用一种叫做引理满足的技术。另一种选择是词干。如果你想了解这两者的区别,我在这里简单解释了一下区别。
词条释义有助于将单词转换成词典形式。以我们之前的例子为例,让我们将它们进行比较,看看输出是什么样的:
lemmatiser = WordNetLemmatizer()
for word in ['play', 'plays', 'playing', 'played']:
print(lemmatiser.lemmatize(word, 'v'))
酷,所有的单词现在都转换成‘玩’了。注意我们如何在lemmatize
方法中传递 v 作为第二个参数?‘v’是一个词性标签。事实上,准确的词汇匹配依赖于我们随单词一起提供给词汇匹配器的词性(POS)标签。为了演示这一点,让我们重新运行前面的脚本,做一点小小的改动,将“v”变成“n”:
lemmatiser = WordNetLemmatizer()
for word in ['plays', 'playing', 'played']:
print(lemmatiser.lemmatize(word, 'n'))
这一次,并不是所有的词都转换成了玩。这个简单的例子展示了词性标签如何影响引理满足的有效性。那么到底什么是词性标签呢?简单地说,它指的是这个词的语法范畴。单词“movie”是一个名词,而“watch”根据上下文可以是动词也可以是名词。名词和动词都是词类的例子。在第一次运行中,我们告诉 lemmatiser 提供的单词是动词(因此是‘v’),在第二次运行中是名词(因此是‘n’)。使用 nltk 的 词性标注器: pos_tag()
,我们可以用词性来标注每个单词。
我们将很快创建一个自定义函数,根据标签进行词性标注和词汇匹配。我们将这个函数传递给TdidfVectoriser()
的analyzer
参数。当我们这样做时,以前使用的一些参数如token_pattern, stop_words
将不再受支持。因此,我们还必须在自定义函数中包含一个标记化步骤:
def preprocess_text(text):
# 1\. Tokenise to alphabetic tokens
tokeniser = RegexpTokenizer(r'[A-Za-z]+')
tokens = tokeniser.tokenize(text)
# 2\. POS tagging
pos_map = {'J': 'a', 'N': 'n', 'R': 'r', 'V': 'v'}
pos_tags = pos_tag(tokens)
# 3\. Lowercase and lemmatise
lemmatiser = WordNetLemmatizer()
tokens = [lemmatiser.lemmatize(t.lower(), pos=pos_map.get(p[0], 'v')) for t, p in pos_tags]return tokens
这里需要注意的一点是,pos_tag()
和lemmatiser.lemmatize()
对词性标签使用不同的命名约定,所以我们必须将由 nltk 标签器生成的词性映射到 lemmatiser 能够理解的名称。这就是我们有pos_map
的原因。现在,让我们预处理数据并评估:
vectoriser = TfidfVectorizer(analyzer=preprocess_text, min_df=30, max_df=.7)
inspect(vectoriser, X_train)
它将列数减少到 10,754。与更简单的方法中的 12,805 列相比,列数减少了约 16%。在我的电脑上花了大约 11 分钟,比这慢了 85 倍。如果我们仔细想想,词条满足不会改变评论中的每一个词。就拿“这部电影太棒了”来说吧。句子为例。唯一受益于引理满足的词是“was”。所以记住这一点,如果你需要更快地完成词条满足,有时对所有单词使用默认的词性是很好的。在这种情况下,我们的自定义函数简化为:
# Simple approach
def preprocess_text(text):
# 1\. Tokenise to alphabetic tokens
tokeniser = RegexpTokenizer(r'[A-Za-z]+')
tokens = tokeniser.tokenize(text)
# 2\. Lowercase and lemmatise
lemmatiser = WordNetLemmatizer()
tokens = [lemmatiser.lemmatize(t.lower(), pos='v') for t in tokens]return tokensvectoriser = TfidfVectorizer(analyzer=preprocess_text, min_df=30, max_df=.7)
inspect(vectoriser, X_train)
列数与我们使用的词性标注器非常接*,但只花了大约一分钟。因此,在这两个版本之间,我更喜欢对这个文本数据集使用默认的词性标签。值得注意的是,如果我们不给pos
参数提供值,lemmatiser 默认为‘n’。一般来说,我通常喜欢使用' v '作为默认,因为我发现它在一般情况下规范化更多的单词。但是,更合适的默认pos
将取决于数据。
2.3.不那么简单的方法 3️⃣
在这种方法中,我们将进一步清理数据。基于从探索性数据分析中获得的知识和一般预处理思想,我们将做以下工作:
◼纠正错别字:【chr acter】到【character】
◼将英式拼法转换为美式拼法:【realize】到【realize】
◼去掉停用词
def convert_to_american(token):
# Copied from [here](https://scikit-learn.org/stable/modules/feature_extraction.html)
token = re.sub(r"(...)our$", r"\1or", token)
token = re.sub(r"([bt])re$", r"\1er", token)
token = re.sub(r"([iy])s(e$|ing|ation)", r"\1z\2", token)
token = re.sub(r"ogue$", "og", token)
return tokendef correct_typo(tokens):
spell = SpellChecker()
return [spell.correction(t) if len(spell.unknown([t]))>0 else t for t in tokens]
def preprocess_text(text):
# 1\. Tokenise to alphabetic tokens
tokeniser = RegexpTokenizer(r'[A-Za-z]+')
tokens = tokeniser.tokenize(text)
# 2\. Lowercase and lemmatise
lemmatiser = WordNetLemmatizer()
tokens = [lemmatiser.lemmatize(t.lower(), pos='v') for t in tokens]# 3\. Correct spelling (this won't convert 100% )
tokens = correct_typo(tokens)
# 4\. Convert British spelling to American spelling (this won't convert 100%)
tokens = [convert_to_american(t) for t in tokens]# 5\. Remove stopwords
stop_words = stopwords.words('english')
stop_words.extend(['cannot', 'could', 'done', 'let', 'may' 'mayn', 'might', 'must', 'need', 'ought', 'oughtn',
'shall', 'would', 'br'])
tokens = [t for t in tokens if t not in stop_words]
return tokens
除了这些,我们可以继续添加其他层来纠正和清理。但是,每个额外的步骤都会增加复杂性和运行时间,而不能保证模型性能的提高。在预处理文本时,通常可以尝试以下一些方法,这些方法在我们的例子中不是特别有用,但在其他例子中可能有用:
◼清理垃圾,如 html 标签、电子邮件地址、网址
◼将数字转换成文字,而不是丢弃它们
◼将表情符号或表情符号转换成文字
好了,让我们预处理并检查输出:
vectoriser = TfidfVectorizer(analyzer=preprocess_text, min_df=30, max_df=.7)
inspect(vectoriser, X_train)
在我开始运行这段代码的几个小时后,它仍然在运行。因为我认为它花费的时间太长,所以我不得不中断内核来停止查询。为了了解这种方法比前两种方法慢多少,我使用下面的脚本将数据集的大小减少到其大小的 1/9:
train = train.sample(5000, random_state=seed)
我在这个更小的数据子集上运行了所有三种方法。下面是三种方法的比较:
不太简单的方法比其他两种方法更标准化代币,但成本非常高。与其他方法相比,预处理至少要花费 1000 倍的时间。当数据集增长时,这个比率可能会变得更糟。因此,进一步追求不那么简单的方法是不实际的,除非它被优化为运行更快。
👂如果你有一台比我更好的计算机,这个运行时间问题可能不一定会成为你的一个限制,在这种情况下,你可以自由地继续追求。
和在 Unsplash 上的合影
您想访问更多这样的内容吗?媒体会员可以无限制地访问媒体上的任何文章。如果您使用 我的推荐链接成为会员,您的一部分会费将直接用于支持我。
谢谢你看我的帖子。希望您已经学会了一些不同的预处理文本的实用方法,可以应用到您的下一个 NLP 项目中。在下一篇文章中,我们将构建一个情感分类器。以下是该系列另外两篇文章的链接:◼️python 中的探索性文本分析
◼️python 中的情感分类
以下是我的其他 NLP 相关帖子的链接:
◼️Python 中的简单 word cloud
(下面列出了一系列关于 NLP 介绍的帖子)
◼️ 第一部分:Python 中的预处理文本
◼️ 第二部分:词条满足和词干的区别
◼️ 第三部分:TF-IDF 解释
◼️ 第四部分:python 中的监督文本分类模型
再见🏃💨
为机器学*(图像识别)预处理图像
原文:https://towardsdatascience.com/preprocessing-your-images-for-machine-learning-image-recognition-277fb7aad5b2?source=collection_archive---------61-----------------------
照片由 Jye B 在 Unsplash 上拍摄—【https://unsplash.com/photos/RuTMP0iI_ek
我在 JKU 学*期间,有一个为机器学*项目预处理图像的任务。在学*算法中使用原始图像之前,有必要对其进行清理,因此我们创建了一个预处理函数。我认为这对其他人也很有用,所以我想分享一点我的方法。该文件是以一种易于理解的方式构建的,并且应该具有类似教程的效果。
目录
- 预处理错误
- 加工文件
- Python 代码
- 关于
预处理错误
在为机器学*任务处理图像时,经常会遇到一些错误。这些是:
- 正确的文件扩展名,代表图像文件(如 jpg)
- 特定的文件大小
- 该文件可以作为图像读取(取决于用于进一步处理的库)
- 图像数据具有可用信息(不止一个值)
- 图像有一定的宽度和高度
- 没有重复的图像
加工文件
该函数有 3 个参数:
- 包含图像文件的输入目录
- 输出目录,有效图像将被复制到该目录
- 包含错误的日志文件
我的解决方案递归搜索允许的图像文件。这是通过get_files
功能完成的。
check_files
函数获取文件并返回带有相应错误代码的图像列表。
validate_file
函数检查图像中的各种常见错误,并返回错误编号。如果没有发生错误,错误代码将为 0。
separate_files
功能将区分有效图像和无效图像。
copy_valid_files
功能会将有效文件复制到定义的“输出目录”文件夹中。
函数在指定的日志文件路径中创建一个日志文件,包含所有有错误的文件。
整个pre_processing
函数最终返回有效文件的数量。
Python 代码
python 文件可以在我的数据科学收藏库中找到:https://github.com/Createdd/DataScienceCollection
在这里,您可以通过 Github Gist 检查代码:
关于
丹尼尔是一名企业家、软件开发人员和律师。他的知识和兴趣围绕商业法和编程机器学*应用发展。从本质上说,他认为自己是复杂环境的问题解决者,这在他的各种项目中都有所体现。如果你有想法、项目或问题,不要犹豫,立即联系我们。
连接到:
- 领英
- Github
- 中等
- 推特
呈现随机森林分类器的特征重要性
原文:https://towardsdatascience.com/present-the-feature-importance-of-the-random-forest-classifier-99bb042be4cc?source=collection_archive---------17-----------------------
机器学*
如何建立一个随机森林分类器,提取特征重要性,并漂亮地呈现出来。
Sebastian Unrau 在 Unsplash 上的照片
W 当报告我的机器学*模型的结果时,我总是试图呈现出比更多的东西“我达到了高达 91%的准确率。”因为这一句话无法体现我在建模过程中所做的这么多工作。
尽管有监督的机器学*模型旨在获得尽可能高的准确性,但您总是可以展示一些副产品,以使您的结果对应用领域有所启发。展示特性的重要性是一个好主意。
在这篇文章中,我将以 随机森林分类器 为例,展示如何生成,提取,呈现特征重要性。
数据的收集、清理、和拆分同样重要,但与这里的主题没有那么大的关联,所以有兴趣的可以在这里参考我以前的一篇文章:
[## 使用三种机器学*模型基于勒布朗数据的端到端游戏预测方案
综合指导一个二元分类问题使用三个不同的分类器,包括逻辑…
towardsdatascience.com](/end-to-end-project-of-game-prediction-based-on-lebrons-stats-using-three-machine-learning-models-38c20f49af5f)
建一条管道。
塞缪尔·西亚尼帕尔在 Unsplash 上拍摄的照片
首先,导入我们需要的所有模块如下:
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.model_selection import StratifiedKFold
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV
import plotly.express as px
第二,建立超参数训练功能。
def train_hyper_tune(X,y):
# create the pre-processing component
my_scaler = StandardScaler()
my_imputer = SimpleImputer(strategy="median")
# define classifiers
## Classifier : Random Forest Classifier
clf_RF = RandomForestClassifier(random_state=0)
# define pipeline
## clf_RF
pipe = Pipeline([('imputer', my_imputer), ('scaler', my_scaler), ('rf_model',clf_RF)])
# create hyperparameter space
## clf_RF
param_grid = {
'rf_model__n_estimators' : [50,100],
'rf_model__max_features' : [0.8,"auto"],
'rf_model__max_depth' : [4,5]
}
# set GridSearch via 5-fold cross-validation
## clf_RF
grid = GridSearchCV(pipe2, cv=5, param_grid=param_grid)
# run the hyperparameter tunning
grid.fit(X,y)
# return results of the tunning process
return grid,pipe
在上面的函数中,我使用 sklearn 中强大的 管道模块对数据进行预处理,并在管道中建模。函数GridSearchCV用于在定义为 param_grid 的超参数空间中寻找最佳超参数。
训练模型。
布鲁斯·马斯在 Unsplash 上的照片
通过执行如下超参数训练过程:
my_grid,my_pipe= train_hyper_tune(X_train, y_train)
网格搜索的每次迭代的结果都存储在 my_grid 中。
然后,我将最佳超参数传递给我的训练函数,如下所示:
def train_on_entire(X,y,pipe,grid_res):
# fit pipeline
pipe.set_params(**grid_res.best_params_).fit(X, y)
# return the newly trained pipeline
return pipemy_entire_pipe = train_on_entire(X_train,y_train,my_pipe,my_grid)
完成了。 my_entire_pipe 是我最终训练好的模型。
我可以在 从未接触过的 测试数据集上检查我的最终模型的性能。
my_entire_pipe.score(X_test, y_test)
这给了我高达 0.901 的精度!
提取特征重要性。
威尔·斯图尔特在 Unsplash 上拍摄的照片
我之所以说 sklearn 中的 管道模块强大,是因为它可以让你追溯到你管道中每一个经过训练的组件。
提取被训练管道的部件(裕丰)
随机森林分类器的特征重要性保存在模型本身中,所以我需要做的就是提取它并将其与原始特征名称相结合。
d = {'Stats':X.columns,'FI':my_entire_pipe[2].feature_importances_}
df = pd.DataFrame(d)
要素重要性数据框如下所示:
特征重要性(裕丰)
到目前为止,我已经有了做以下可视化所需的一切。
在统计图中展示特征的重要性。
实际上,有很多方法可以呈现特性的重要性,比如柱状图,或者箱线图,如果你已经为一个健壮的度量做了 N 次建模的话。
我本人对 花花公子排行榜 情有独钟,原因可以在我之前的一篇帖子中找到,如下:
[## 一行命令值 200 美元吗?
我的真实故事。生成统计图的命令行花费了一个博客作者 200 美元。
medium.com](https://medium.com/@jianan.jay.lin/is-one-line-of-command-worth-200-dollars-6f43884aa21f)
在制作图之前,我只是将特征重要性按升序排序。
df = df.sort_values(by='FI', ascending=0)
然后,生成如下的统计图:
fig = px.bar_polar(df, r="FI", theta="Stats",
color="Stats", template="plotly_dark",
color_discrete_sequence= px.colors.sequential.Plasma_r)
fig.show()
鸡冠图 1 由俞峰
哎呦!为什么看起来这么丑?
在再次检查特征重要性数据框后,我发现名为“ +/- ”(代表篮球中的加/减,估计一个篮球运动员对球队的贡献)的特征已经主导了特征空间。
这个结果表明这个特征对我们的预测模型是最重要的。既然我建立的模型是基于 勒布朗詹姆斯的 统计来预测比赛结果,那么用 +/- 来评估他的表现比其他基础统计更有预测力也是合理的。
然而,我们总是可以通过放大图形来检查所有其他特征的重要性。
df_drop = df[df.Stats != '+/-']
fig = px.bar_polar(df_drop, r="FI", theta="Stats",
color="Stats", template="plotly_dark",
color_discrete_sequence= px.colors.sequential.Plasma_r)
fig.show()
鸡冠图二由俞峰
现在我们看到几个其他的特性出现在前面,比如比赛分数( GmSC ) ,以及投篮命中率(【FG %】)。
我也很惊讶,这个名为【G】的特性,排名竟然比很多我认为应该重要的其他特性都要靠前,比如辅助( AST )。
【G】实际上是一个赛季的比赛指数, 1 表示一个赛季的第一场比赛, 82 表示一个赛季的最后一场比赛。这个特征表现出重要性的事实表明 勒布朗詹姆斯 可以沿着整个赛季的进程调整自己对比赛的影响。
就是这样。随机森林分类器中特征重要性的表示。
如果你喜欢读这篇文章,请关注我的 中型 以下是我的一些其他帖子:
[## 线性回归中的一个实用建议
从弹性网开始,记得调好定义 l1 范数之比的超参数。
towardsdatascience.com](/a-practical-suggestion-in-linear-regression-cb639fd5ccdb) [## NBA 球员统计数据 R 包“ggplot2”中数据可视化的实践指导
应用于 NBA 数据的 R 数据可视化工具“ggplot2”的 6 分钟之旅。
towardsdatascience.com](/hands-on-guidance-of-data-visualization-in-r-package-ggplot2-of-nba-players-stats-d812ed272d66)
照片由阿里·帕扎尼在 Unsplash 上拍摄
在《星球大战》宇宙中呈现 Neo4j 图形数据科学的多节点标签支持和图形可变性特征
原文:https://towardsdatascience.com/presenting-multiple-node-label-support-and-graph-mutability-features-of-the-neo4j-graph-data-a0b0ea744884?source=collection_archive---------22-----------------------
浏览 Neo4j 图形数据科学库中的算法执行和图形可变性功能的节点过滤器,并使用星球大战网络
文章于 2022 年 4 月 30 日更新,以遵循新的 GDS 2.0 语法
我决定暂时停止观看我强烈推荐的鲍勃·罗斯的绘画之乐,并检查 Neo4j 图形数据科学 2.0 版中的一些新语法。
对我来说,一个非常酷的 GDS 功能是在执行图形算法时能够通过标签过滤节点。类似于关系,我们可以用 relationshipTypes 参数选择哪些应该被图算法考虑,我们可以用新的 nodeLabels 参数过滤哪些节点应该被使用。我们还将看看投影图的可变性特性。
我喜欢寻找新的社交网络,以免我的博客文章变得无聊和重复。在这里,我们将深入研究星球大战世界。由于 Evelina Gabasova 的帮助,人物之间的互动在 GitHub 上可用。我们将把它与 Florent Georges 提供的数据集结合起来,Florent Georges 抓取了星球大战 API 并添加了来自维基百科的描述。
图表模式和导入
星球大战图表模式
我们的图表由与其他角色有交互关系的角色组成。 X 的值指示交互发生在哪一集,例如交互 1 指示第一集的交互。每个角色也属于一个物种,该物种被表示为与物种节点的关系。
我们将从导入交互社交网络开始。数据集有点棘手,因为角色在每集中都没有唯一的 id。相反,在每一集中,一个新的 id 被确定为 JSON 文件的“nodes”元素中的字符的从零开始的索引。为了缓解这个问题,我们使用apoc.cypher.runMany
过程为每一集运行两个事务。首先,我们存储节点,并根据从零开始的索引为它们赋值。在第二个事务中,我们使用该值存储字符之间的链接。每集都重复这一过程。
UNWIND range(1,7) as episode
CALL apoc.load.json('https://raw.githubusercontent.com/evelinag/StarWars-social-network/master/networks/starwars-episode-' + toString(episode) + '-interactions.json')
YIELD value as data
CALL apoc.cypher.runMany("
WITH $data.nodes as nodes
UNWIND range(0,size(nodes)-1) as value
MERGE (c:Character{id:nodes[value].name})
SET c.value = value RETURN distinct 'done'
;
WITH $data as data, $episode as episode
UNWIND data.links as link
MERGE (source:Character{value:link.source})
MERGE (target:Character{value:link.target})
WITH source, target, link.value as weight, episode
CALL apoc.create.relationship(source,'INTERACTS' + episode, {weight:weight}, target) YIELD rel
RETURN distinct 'done'", {data:data, episode:episode},{statistics:true,timeout:10})
YIELD result RETURN result
我们将继续用该物种的信息丰富我们的图表。不幸的是,两个数据集之间的字符名称并不完全匹配。我们可以使用几种方法来找到与角色名字最接*的匹配。APOC 图书馆有一整块区域致力于文本相似程序。我决定使用全文搜索索引来匹配角色的名字。我们首先在字符的 id 属性上定义全文搜索索引。
CALL db.index.fulltext.createNodeIndex(
"names",["Character"],["id"])
每个全文搜索查询可能会返回多个结果,但是我们将只查看顶部的结果。如果顶部结果的分数高于任意阈值,在我们的例子中是 0.85,我们将假设它是相同的字符。我们可以看一些例子:
CALL apoc.load.json('https://raw.githubusercontent.com/fgeorges/star-wars-dataset/master/data/enriched.json') YIELD value UNWIND value.people as person
CALL db.index.fulltext.queryNodes("names",
replace(person.name,'é','e'))
YIELD node,score
RETURN person.name as species_dataset_name,
collect(node)[0].id as interactions_dataset_name
LIMIT 5
结果
或多或少,物种数据集包含全名,而交互数据集只包含角色的名。因为全文搜索匹配看起来很好,所以让我们继续将附加信息存储到图中。
CALL apoc.load.json('https://raw.githubusercontent.com/fgeorges/star-wars-dataset/master/data/enriched.json')
YIELD value
UNWIND value.people as person
// search for characters
CALL db.index.fulltext.queryNodes("names",
replace(person.name,'é','e'))
YIELD node,score
// collect the top hit
WITH person, collect([node,score])[0] as top_hit
WITH person, top_hit[0] as node, top_hit[1] as score
// threshold
WHERE score > 0.85
// enrich characters
SET node += apoc.map.clean(person,
['films','vehicles','starships','species'],['n/a'])
WITH node, person.species as person_species
UNWIND person_species as species
MERGE (s:Species{id:species})
MERGE (node)-[:BELONG_TO]->(s)
我们还将导入关于该物种的额外元数据。
CALL apoc.load.json('https://raw.githubusercontent.com/fgeorges/star-wars-dataset/master/data/enriched.json')
YIELD value
UNWIND value.species as species
MATCH (s:Species{id:species.url})
SET s += apoc.map.clean(species,
['films','homeworld','people','url'],['n/a','unknown'])
不幸的是,我们还没有给我们所有的角色分配物种。一些字符出现在第一个数据集中,而没有出现在第二个数据集中。由于这篇博文的重点不是展示如何有效地搜索互联网,所以我准备了一个 CSV 文件,我们可以用它来指定缺失物种的值。
LOAD CSV WITH HEADERS FROM
"https://raw.githubusercontent.com/tomasonjo/blogs/master/Star_Wars/star_wars_species.csv" as row
MATCH (c:Character{id:row.name})
MERGE (s:Species{name:row.species})
MERGE (c)-[:BELONG_TO]->(s)
有些物种只有一两个成员,所以我决定把它们归为“其他”物种。这样,我们将使我们进一步的图形分析更加相关。
MATCH (s:Species)
WHERE size((s)<-[:BELONG_TO]-()) <= 2
MERGE (unknown:Species{name:'Other'})
WITH s, unknown
MATCH (s)<-[:BELONG_TO]-(character)
MERGE (unknown)<-[:BELONG_TO]-(character)
DETACH DELETE s
多节点标签支持
我们现在可以看看多节点标签投影,以及它如何允许我们在执行图形算法时过滤节点。因为我们将使用原生投影,我们必须根据他们的种族给角色分配二级标签。我们将使用apoc.create.addLabels
程序来分配二级标签。
MATCH (c:Character)-[:BELONG_TO]->(species)
CALL apoc.create.addLabels([id(c)], [species.name]) YIELD node
RETURN distinct 'done'
如果你对 GDS 图表目录的概念不熟悉,你可能想看看我以前的博客帖子。我们将使用 array 选项来描述我们想要投影的节点标签。属于所有五个物种的节点将被投影。交互网络中的所有关系也将被投影并被视为无向和加权的。由于给定的一对节点之间可能有不止一个关系,我们投影一个多重图。
CALL gds.graph.project('starwars',
['Other','Human','Droid','Neimodian','Gungan'],
{INTERACTS1:{type:'INTERACTS1', orientation:'UNDIRECTED', properties:['weight']},
INTERACTS2:{type:'INTERACTS2', orientation:'UNDIRECTED', properties:['weight']},
INTERACTS3:{type:'INTERACTS3', orientation:'UNDIRECTED', properties:['weight']},
INTERACTS4:{type:'INTERACTS4', orientation:'UNDIRECTED', properties:['weight']},
INTERACTS5:{type:'INTERACTS5', orientation:'UNDIRECTED', properties:['weight']},
INTERACTS6:{type:'INTERACTS6', orientation:'UNDIRECTED', properties:['weight']}})
首先,让我们计算整个投影图上的加权 PageRank 。
CALL gds.pageRank.stream('starwars',
{relationshipWeightProperty:'weight'})
YIELD nodeId, score
RETURN gds.util.asNode(nodeId).name as name, score
ORDER BY score DESC LIMIT 5
结果
结果并不令人惊讶,也许除了汉索罗似乎是银河系中最重要的人物。这是因为阿纳金·天行者和达斯·维德在我们的网络中被视为两个独立的实体,否则阿纳金可能会在上面。尽管如此,从 PageRank 评分来看,所有前五个角色的重要性都非常相似,没有人真正脱颖而出。
假设我们想找到冈根人社交网络中最重要的人物。在带有节点标签参数的算法中,我们可以只考虑冈根人。
CALL gds.pageRank.stream('starwars',{nodeLabels:['Gungan'],
relationshipWeightProperty:'weight'})
YIELD nodeId, score
RETURN gds.util.asNode(nodeId).id as name, score
ORDER BY score DESC LIMIT 5
正如你所料,传奇人物加·加最终胜出。
我们还可以结合节点和关系过滤器。我们将在第五集和第六集中根据人类和其他物种的互动网络来计算 PageRank。
CALL gds.pageRank.stream('starwars',{nodeLabels:['Other','Human'],
relationshipTypes:['INTERACTS5','INTERACTS6'],
relationshipWeightProperty:'weight'})
YIELD nodeId, score
RETURN gds.util.asNode(nodeId).name as name, score
ORDER BY score DESC LIMIT 5
结果
看起来卢克和莱娅已经长大了。节点过滤特性的增加允许我们在描述我们想要考虑作为图算法的输入的投影图的子集时非常精确。完成分析后,我们可以从目录中删除投影图。
CALL gds.graph.drop('starwars')
图形可变性
有了图形可变性特性,图形算法在先前支持的流和写之上有了第三种模式变异。我们可以看看官方文档来更好地了解它提供了什么:
*mutate*
模式与**write*
模式非常相似,但不是将结果写入 Neo4j 数据库,而是在内存图形中提供。注意,*mutateProperty*
必须事先不存在于内存图形中。这使得可以在同一个内存图形上运行多个算法,而无需在算法执行期间将结果写入 Neo4j。*
基本上, mutate 模式与 write 模式几乎相同,只是它不直接将结果写入 Neo4j 存储的图形,而是将结果存储到同一个内存中的投影图形,该图形用作图形算法的输入。稍后,如果我们愿意,我们仍然可以使用gds.graph.writeNodeProperties
过程将内存中图形的变异属性存储到 Neo4j 中。
我们将从投影一个新的内存图形开始。这次我们将使用 cypher projection 。在节点查询中,我们将只过滤第一集出现的字符。我们还提供了标签列,这将允许我们在执行算法时过滤节点。如果仔细观察, labels 列是数组的形式,这意味着单个节点可以有多个标签。同样,通过 cypher projection,我们可以提供一个虚拟标签,如查询所示。
*CALL gds.graph.project.cypher('starwars_cypher',
'MATCH (species)<-[:BELONG_TO]-(c:Character)
// filter characters from first episode
WHERE (c)-[:INTERACTS1]-()
RETURN id(c) as id, [species.name] as labels',
'MATCH (c1:Character)-[r]-(c2:Character)
RETURN id(c1) as source, id(c2) as target,
type(r) as type, r.weight as weight',
{validateRelationships:false})*
Cypher Projection 的一个特性是 validateRelationships 参数。如果我们试图投影节点查询中没有描述的节点之间的关系,默认设置会抛出一个错误。因为我们在节点查询中只投射第一集的角色,但是试图在关系查询中投射所有角色之间的交互,所以我们会得到一个错误。我们可以在关系查询中添加一个过滤器,或者只是将 validateRelationship 参数设置为 false。这样,在图形投影期间,节点查询中未描述的节点之间的所有关系都将被忽略。
最后,我们可以尝试一下用于社区检测的鲁文算法的变异模式。我们将在物种内部而不是在整个网络上调查第一集的社区结构。为了实现这一点,我们必须为每个物种分别运行算法,并且只考虑来自具有节点标签参数的给定物种的角色,并且只考虑来自具有关系类型参数的第一集的交互。为了定义用于将结果存储到内存图的指定属性,我们使用了 mutateProperty 参数。
*MATCH (s:Species)
CALL gds.louvain.mutate('starwars_cypher',
{nodeLabels:[s.name], mutateProperty: s.name + '_1',
relationshipTypes:['INTERACTS1']})
YIELD communityCount
RETURN s.name as species, communityCount*
结果
我们现在可以使用第一集中角色社区的变异属性作为种子属性来计算第二集中的社区。通过给每个节点分配一个唯一的 id 来初始化 Louvain 算法。使用seed property参数,我们可以定义每个节点的初始唯一 id。如果你想了解更多关于种子属性和它的用例,我写了一篇关于它的博客文章。
*MATCH (s:Species)
CALL gds.louvain.mutate('starwars_cypher',
{nodeLabels:[s.name], mutateProperty: s.name + '_2',
relationshipTypes:['INTERACTS2'], seedProperty: s.name + '_1'})
YIELD communityCount
RETURN s.name as species, communityCount
ORDER BY communityCount DESC*
结果
我们可以观察到第二集中的社区数量略有减少。要将变异的属性写回 Neo4j 存储图,我们可以使用gds.graph.writeNodeProperties
过程。
*CALL gds.graph.writeNodeProperties('starwars_cypher',
['Human_1','Human_2'])*
我们现在可以检查第一集里人类的社区结构。
*MATCH (c:Human)
WHERE exists (c.Human_1)
RETURN c.Human_1 as community,
count(*) as size,
collect(c.id) as members*
结果
并在第二集中考察这些社区是如何进化的。
*MATCH (c:Human)
WHERE exists (c.Human_2)
RETURN c.Human_2 as community,
count(*) as size,
collect(c.id) as members*
结果
结论
有了多节点标签支持,我们能够在内存中投影整个图,并非常具体地描述我们希望用作图算法输入的子图,因为我们现在可以过滤节点和关系。图形可变性允许我们链接各种图形算法,而不需要删除和重新创建具有新计算属性的投影图。在我看来,这是 Neo4j 图形数据科学库的一大特色。
如果你心中有任何很酷的数据集,你想让我分析,或者有任何关于你接下来想看到什么的反馈,请告诉我。与往常一样,代码可以在 GitHub 上获得。
在深度学*中保护数据隐私|第 1 部分
原文:https://towardsdatascience.com/preserving-data-privacy-in-deep-learning-part-1-a04894f78029?source=collection_archive---------11-----------------------
理解联邦学*的基础及其使用 PyTorch 的实现
链接到第二部分(将 CIFAR10 分发到真实世界/非 IID 数据集):
https://towardsdatascience . com/preserving-data-privacy-in-deep-learning-part-2-6c2e 9494398 b
链接第三部分(非 IID 数据集联合学*的实现):https://towardsdatascience . com/preserving-data-privacy-in-deep-Learning-part-3-AE 2103 c 40 c 22
照片由 Harsh Yadav 拍摄
非常感谢著名数据科学家阿克谢·库尔卡尼先生对本教程的启发和指导。
在数据和数字化革命的世界中,越来越多的个人信息被共享和存储,这开辟了保护数据隐私的新领域。但是,什么是数据隐私,为什么需要保护它?
照片由谷歌人工智能
数据隐私定义了特定信息/数据应如何处理,或者谁有权根据其相对重要性进行访问。随着 AI(机器学*和深度学*)的引入,可以从这些模型中提取大量的个人信息,这对个人数据被暴露的人会造成不可挽回的损失。因此,在实现各种机器学*模型的同时,需要保留这些数据。
在这一系列教程中,主要关注的是保护深度学*模型中的数据隐私。您将探索不同的方法,如联合学*、差分隐私和同态加密。
在本教程中,您将发现如何在机器学*模型上使用联邦学*来保护数据隐私。完成本教程后,您将了解:
- 联邦学*的基础
- 在客户端之间划分数据(用于联合学*)
- 模型架构
- 全局权重中分散权重的聚合
介绍
F 深度学*,也称为协作学*,是一种深度学*技术,其中在多个分散的边缘设备(客户端)或服务器上对其个人数据进行训练,而不与其他客户端共享数据,从而保持数据的私密性。它旨在训练机器学*算法,例如,在具有本地数据集的多个设备(客户端)上的深度神经网络,而无需显式交换数据样本。
照片由谷歌人工智能拍摄
这种训练同时发生在其他设备上,成百上千的设备。在用不同的数据在不同的设备上训练相同的模型之后,它们的权重(训练的概要)被发送到全局服务器,在那里进行这些权重的聚合。使用不同的聚合技术来充分利用在客户端设备上学*的权重。在聚合之后,全局权重再次被发送到客户端,并且训练在客户端的设备上继续。在联合学*中,这整个过程被称为一轮通信,这是为了进一步提高模型的准确性而进行的通信次数。
Google AI 拍摄的照片
联邦学*使人工智能算法能够从位于不同地点的大量数据中获得经验。这种方法使几个组织能够协作开发模型,而不必彼此共享敏感数据。经过几轮沟通后,共享模型(全局模型)接触到的数据范围比任何单个客户端拥有的数据范围都要大得多,同时,它也了解了客户端特有的特性。
有两种类型的联合学*:
- 集中式联邦学*:在这种设置中,中央服务器用于编排算法的不同步骤,并在学*过程中协调所有参与节点。服务器负责在训练过程开始时选择节点,并负责聚合接收到的模型更新(权重)。是系统的瓶颈。
- 分散联邦学*:在这种类型中,节点能够协调自己以获得全局模型。此设置可防止单点故障,因为模型更新仅在互连节点之间交换。
现在我们已经清楚了什么是联合学*,让我们继续在 PyTorch 中从头构建一个,并在 CIFAR10 数据集上训练它。借助本教程,我们将了解联邦学*的基本流程。我们既不会详细讨论服务器-客户端通信在现实世界中是如何工作的,也不会讨论聚合技术,这将在接下来的教程中讨论。在本研究中,数据集被随机分为客户端,所有本地模型将在同一台机器上接受训练。我们走吧。
1.导入所有相关的包
导入相关模块
照片由谷歌人工智能
2.超参数
- num_clients :客户端总数,进一步用于将数据集划分为 num_clients,每个客户端具有相同数量的图像。
- num_selected :通信回合中从 num_clients 中随机选择的客户端数量。用于培训部分。通常,num_selected 大约是 num_clients 的 30%。
- num_rounds :通信轮次总数。在每轮通信中,随机选择 num_clients,在客户端设备上进行训练,然后将各个模型权重聚合到一个全局模型中。
- 时期:每个选定客户端设备上的本地训练回合总数。
- batch_size :将数据分批加载到数据加载器中。
3.将 CIFAR 10 加载并划分到客户端
本教程中使用了 CIFAR10 数据集。它由 10 类 32×32 像素的 60,000 幅彩色图像组成。有 50,000 个训练图像和 10,000 个测试图像。在训练批次中,每个类有 5000 个图像,总共有 50000 个图像。在 PyTorch 中,CIFAR 10 可以在 torchvision 模块的帮助下使用。
在本教程中,图像被平均划分到客户端,从而代表了平衡(IID)的情况。
第 6–11 行定义了加载图像时要使用的训练数据的图像增强和归一化方法。第 14–15 行用给定的增量加载训练数据。进行 traindata_split,第 18 行,它将训练数据拆分成 num_clients,即在我们的例子中是 20 个。最后,使用 train_loader(第 21 行)将图像输入神经网络以训练模型。
第 24–27 行定义了测试图像的标准化方法。第 30–32 行定义了一个 test_loader,用于生成给定模型的测试结果。
4.构建神经网络(模型架构)
本教程中使用了 VGG19 (16 个卷积层,3 个全连接层,5 个 MaxPool 层和 1 个 SoftMax 层)。VGG 还有其他变体,如 VGG11、VGG13 和 VGG16。
5.用于联合训练的辅助函数
client_update 函数在私有客户端数据上训练客户端模型。这是在 num_selected 客户处进行的一轮本地培训,在我们的例子中是 6 个。
server_aggregate 函数聚集从每个客户端接收的模型权重,并用更新后的权重更新全局模型。在本教程中,取权重的平均值并聚合到全局权重中。
测试函数是标准函数,将全局模型和测试加载器作为输入,返回测试损失和准确度。
6.训练模型
一个全局模型和单独的 client_models 在 GPU 上用 VGG19 初始化。在本教程中,SGD 用作所有客户机模型的优化器。
也可以用 VGG11、VGG13 和 VGG16 代替 VGG19。其他优化器也是可用的,人们可以检查链接了解更多细节。
第 2–5 行创建了一个列表,用于跟踪训练和测试数据集的损失和准确性。个人客户培训从第 8 行开始,即沟通环节。最初,从 num_clients 中选择 num_selected 个客户端(第 10 行),即从 20 个可用客户端中随机选择 6 个客户端。使用 client_update 函数为每个选定的客户端(第 12–14 行)进行培训。现在,权重的聚合使用上面定义的 server_aggregate(第 18 行)函数进行。这将更新全局模型,全局模型是用于预测的最终模型。在更新全局模型之后,在上面定义的测试函数的帮助下,这个全局模型被用于测试训练(第 20 行)。
这个过程持续 num_rounds,在我们的例子中是 150 次通信。这是联邦学*的最基本层次的例子,它可以进一步应用于一个真正的基于客户机的系统。
7.结果
对于 6 个选定的客户端,每个客户端在 150 轮通信的顶部运行 5 个本地时期,下面是截断的测试结果。
因此,在 150 轮沟通后,该模型使用联合学*达到了大约 89.8 %的准确率。但是它与在相同数据集上训练的标准 SGD 模型相比如何呢?为了进行比较研究,在没有联邦学*的情况下,使用标准 SGD 优化器对训练数据训练 VGG19 模型。为了确保一个平等的比赛场地,所有的超参数都是相同的,它被训练了 200 个纪元。
标准 SGD 模型在 200 个周期后给出大约 94%的测试准确度。因此,与原始模型相比,我们的联合学*表现良好,准确率约为 90%。
摘要
在本教程中,您发现了如何使用 PyTorch 的联邦学*来保护深度学*模型中的数据隐私。
具体来说,您学到了:
- 什么是数据隐私,为什么需要保护数据隐私?
- 联邦学*的基础及其在平衡的 CIFAR-10 数据集上的实现。可以为任何图像分类问题建立类似的模型。
下面是快速修改整个过程的流程图。
结论
联合学*是机器学*模型中保护数据隐私的最佳方法之一。通过仅发送模型的更新权重而不是数据,确保了客户端数据的安全性。同时,全球模型可以从客户特定的特征中学*。但是不要对这个模型过于兴奋,因为上述结果在现实世界中不太可能出现。客户端持有的真实联邦数据大多是非独立的,并且是同分布的(非 IID)。因此,为了解决真实世界/非 IID 数据集的问题,请继续关注本系列的下一部分。
在接下来的教程中,您不仅将了解如何在联邦学*中处理非 IID 数据集,还将了解联邦学*中的不同聚合技术、模型权重的同态加密、差分隐私及其与联邦学*的混合,以及更多有助于保护数据隐私的主题。
链接到第二部分(将 CIFAR10 分发到真实世界/非 IID 数据集):
https://towards data science . com/preserving-data-privacy-in-deep-learning-part-2-6c2e 9494398 b
链接第三部分(非 IID 数据集联合学*的实现):https://towardsdatascience . com/preserving-data-privacy-in-deep-Learning-part-3-AE 2103 c 40c 22
参考
[1] Felix Sattler,来自非 IID 数据的健壮且通信高效的联邦学*, arXiv:1903.02891
[2] H.Brendan McMahan, 从分散数据中进行深度网络的通信高效学* ,第 20 届人工智能与统计国际会议论文集(AISTATS) 2017。JMLR: W & CP 第 54 卷
在深度学*中保护数据隐私|第 2 部分
原文:https://towardsdatascience.com/preserving-data-privacy-in-deep-learning-part-2-6c2e9494398b?source=collection_archive---------16-----------------------
将一个平衡的数据集分布到一个非 IID/真实世界的数据集中,并进一步划分到用于联合学*的客户端中。
链接到第一部分(联邦学*基础):https://towards data science . com/preserving-data-privacy-in-deep-Learning-part-1-a 04894 f 78029
链接第三部分(非 IID 数据集联合学*的实现):https://towardsdatascience . com/preserving-data-privacy-in-deep-Learning-part-3-AE 2103 c 40c 22
照片由 Harsh Yadav 拍摄
非常感谢著名数据科学家阿克谢·库尔卡尼先生对本教程的启发和指导。
上图类似于非 IID(独立同分布)数据集。如果每个随机变量(图像)具有与其他随机变量相似的概率分布,并且都是相互独立的,则随机变量(图像)的集合是独立且同分布的。在本系列的第 1 部分中,我们使用了 CIFAR10 数据集,这是一个 IID 类型的示例,但是对于真实世界的用例,需要有一个非 IID 数据集来表示真实世界的场景。那么,什么是非 IID 数据呢?要为联合学*积累非 IID 数据,需要对当前数据集(CIFAR10)进行哪些更改?
这些是本教程将回答的一些问题。本博客是在深度学*中保护数据隐私系列的第 2 部分,重点关注将 CIFAR10 分发到非 IID 数据集,并在客户端之间进一步划分。完成本教程后,您将了解:
- 非 IID 数据集
- 将平衡数据集转换为非 IID 数据集和真实数据集
- 形成封装了该非 IID/真实世界数据集的一部分的客户端
- 使用联合学*的图像分类用例
与非 IID 数据集相似。照片由 Harsh Yadav 拍摄
现实生活中的数据(指对象、值、属性和其他方面)本质上是非独立且同分布的(非 IID)。相比之下,大多数现有的分析或机器学*方法都是基于 IID 数据的。因此,需要一种合适的方法来处理这种类型的真实数据集。本教程将介绍非 IID 数据集的基础,从而为实现各种联邦学*技术来处理从非 IID 数据中获得洞察力的问题打开舞台。非线性是一个常见的问题,导致深度学*模型的性能不稳定。在文献中,非 IID 图像分类问题在很大程度上研究不足。
NICO (带有上下文的非 IID 图像数据集)就是这样一个基准数据集,可以进一步用于开发最先进的机器学*模型来处理非 IID 数据。
在这个系列中,CIFAR 10 被用作基准数据集,并且进一步被转换成非 IID 数据集。要了解更多关于联邦学*的基础知识,请阅读本系列的第 1 部分。在本教程中,我们将创建两种不同类型的数据集,一种是复制现实生活中的数据,即现实世界数据集,另一种是非 iid 数据集的极端示例。
真实世界数据集: CIFAR 10 被随机分成给定数量的客户端。因此,一个客户端可以有任意数量的类的图像,比如说,一个客户端只有 1 个类的图像,而另一个客户端有 5 个类的图像。这种类型的数据集复制了真实世界的场景,其中客户端可以有不同类型的图像。
图 1:真实数据集,其中 CIFAR10 被划分为 20 个客户端
非 IID 数据集:现实世界的数据集也属于这一类别。但是,在这种情况下,会进行不同类型的分发,其中 CIFAR10 数据集根据每个客户端的类参数进行划分。例如,如果每个客户端的类别=2,则所有客户端将具有从所有类别中随机选择的任意两个类别的图像。
图 2:非 IID 数据集,每个客户端的类=2
从上面的图像中,我们可以知道所有的客户端都有来自任意两个类的图像,但是存在一些异常值,其中一些客户端有来自两个以上类的图像,而一些客户端与其他客户端相比有非常少数量的图像(client_20)。这种异常值确保所有客户端都有一组唯一的图像。这是非 IID 数据集的一个极端例子。我们还可以将 CIFAR10 数据集划分为每个客户端的类= 1,其中所有客户端都将拥有来自一个类的图像,只有一些异常值。
让我们深入到编码部分,更详细地理解它。
1.导入库
2.超参数
- classes_pc: 每个客户端的类,用于通过在客户端之间创建类的不平衡表示,将平衡数据集划分为非 IID 数据集。例如,如果 classes_pc=1,则所有客户端将仅具有来自一个类别的图像,从而在客户端之间产生广泛的不平衡。(参考:图 2)
- num_clients :要分发图像的客户端总数。
- batch_size: 将数据分批加载到数据加载器中。
- real_wd: 我们正在创建两种类型的数据集,一种是真实世界数据集(图 1),另一种是极端的非 IID 数据集(图 2)。如果 real_wd 为 TRUE ,则创建复制真实生活的数据集,即真实世界数据集(图 1)。如果 real_wd 为 FALSE (默认),则创建极端非 IID 数据集。
3.创建发行版
get_cifar10 函数下载 cifar10 数据集并返回 x_train,y_train 用于训练,x_test,y_test 用于测试。第 5–6 行从 torchvision 下载数据集,第 8–9 行将其转换为 NumPy 数组。
clients_rand 函数为客户端创建一个随机分布,这样每个客户端都有任意数量的图像。它是将在接下来的代码片段中使用的助手函数之一。
split _ image _ data _ realwd函数将给定的图像分割成 n 个客户端。它返回一个分割,该分割进一步用于创建真实世界的数据集。这整个片段都有注释来解释按顺序发生的事情。要了解更多关于这个发行版的内容,请阅读本系列的第 2 部分。
现在,我们将为非 IID 数据集创建一个类似的分割,如上所述(使用图表)。要了解更多关于这个发行版的内容,请阅读本系列的第 2 部分。
shuffle_list 函数接受上述函数(split_image_data_realwd 或 split_image_data)的输入,分别对每个客户端的图像进行混洗。
下面的代码片段将拆分转换为数据加载器(在这一部分中完成了图像增强),以将其作为训练模型的输入。
get_data_loader 函数使用上述辅助函数,并将 CIFAR10 数据集转换为真实世界或非 IID 类型,视需要而定。
现在,我们已经准备好了创建真实世界或非 IID 数据集的所有函数,联邦学*可以进一步使用这些函数来开发最先进的模型。
现在,我们已经成功创建了这些数据集,让我们来探索对象分类的一些潜在用例,这些用例可以进一步用于联合学*,并确保个人数据安全。
插图由 Harsh Yadav 绘制
摘要
在本教程中,您了解了如何使用 PyTorch 为影像分类准备非 IID/真实世界数据集。
具体来说,您学到了:
- 什么是非 IID(独立同分布)数据集。
- 如何将平衡分布转换成非 IID/真实世界。
- 对象分类的潜在用例。
下面是将 CIFAR10 数据集转换为客户端的整个过程的快速修订流程图,可进一步用于联合学*。
结论
非 IID 数据很难训练,联邦学*也是如此。真实世界/非 IID 数据集被划分成客户端(num_clients ),这些客户端可以被联邦学*进一步使用并保持数据隐私。
在本系列的下一部分中,我们将在联邦学*中使用这个数据集。请继续关注下一部分,它将探索在非 IID 数据集上的联邦学*中使用的新的聚合和通信技术。在接下来的教程中,您将了解联邦学*的不同聚合技术、模型权重的同态加密、差分隐私以及它与联邦学*的混合。
链接第三部分(非 IID 数据集联合学*的实现):https://towardsdatascience . com/preserving-data-privacy-in-deep-Learning-part-3-AE 2103 c 40c 22
参考
[1] Felix Sattler,来自非 IID 数据的健壮且通信高效的联合学*, arXiv:1903.02891
[2]岳鹤,走向非独立影像分类:数据集与基线, Elsevier
在深度学*中保护数据隐私|第 3 部分
原文:https://towardsdatascience.com/preserving-data-privacy-in-deep-learning-part-3-ae2103c40c22?source=collection_archive---------25-----------------------
非独立同分布(非 IID)数据集上联邦学*的实现。
链接到第 1 部分(联合学*的基础):https://towards data science . com/preserving-data-privacy-in-deep-Learning-part-1-a 04894 f 78029
链接到第二部分(将 CIFAR10 分发到真实世界/非 IID 数据集):
https://towardsdatascience . com/preserving-data-privacy-in-deep-learning-part-2-6c2e 9494398 b
隐私是本世纪最重要的方面之一,无论是私人数据的物理隐私还是虚拟隐私。照片由 Harsh Yadav 拍摄
非常感谢著名数据科学家阿克谢·库尔卡尼先生对本教程的启发和指导。
什么是联合学*?什么是非 IID 数据集?要在联邦学*中积累非 IID 数据,需要做哪些改变?这类深度学*方法有哪些用例?
这些就是你在这里的一些问题。本博客是在深度学*中保护数据隐私系列的第 3 部分,重点关注使用非 IID 数据集实现联合学*。在本系列的第 1 部分中,我们探索了联邦学*的底层架构及其使用 PyTorch 的基本实现。但是第 1 部分无法处理真实世界的数据集,在真实世界中,任何客户端都可以拥有任意数量的来自给定类的图像。为了解决这个问题,在第 2 部分中,我们将 CIFAR 10(平衡数据集)分发到非 IID/真实世界分发中,并进一步将其划分为客户端。现在,为了构建真实世界/非 IID 数据集的联合学*模型,我正在编写本教程。在本系列的这一部分中,我们将对非 IID 客户机(在第二部分中)使用联合学*的架构(在第一部分中)。因此,它可以被认为是联合学*的一个真实世界的用例。
完成本教程后,您将了解:
- 联合学*
- 非 IID 数据的联合学*架构
- 联邦学*中的再培训和交流方法
- 加权平均作为聚集技术
什么是联合学*?(快速回顾)
深度学*是一种隐私保护方法,旨在在拥有个人数据的多个设备(客户端)上训练人工智能模型,而无需显式交换或存储数据样本。全局模型(权重)被传送到这些设备,在这些设备中,实际的训练同时发生,合并了客户特定的特征,然后用在各个设备的训练期间学*的所有新特征来更新(聚集)全局模型。
Google keyboard 的下一个单词预测是联合学*的一个杰出例子。联邦学*处理设备历史(打字历史)来建议对 Gboard 的查询建议模型的下一次迭代的改进。
由 Kiki Siepel 在 Unsplash 上拍摄的照片
联邦学*与花的学*非常相似。就像所有的花瓣(客户端)都由花梗(全局服务器)持有,每个花瓣都有不同的尺寸和模式,但与组成花的其他花瓣相似(非 IID 数据集),以及所有的营养物质(模型的权重)如何由花梗同时转移到花瓣,花是联合学*的真实类比。
要深入了解使用 Pytorch 的联邦学*的基本实现,请阅读本系列的第 1 部分。
现在,我们可以开始本博客的下一个也是最激动人心的部分了,开始玩代码吧。本教程使用 PyTorch,通过将平衡的 CIFAR10 数据集转换为非 IID/真实世界的数据集,从头开始构建一个联合学*模型。有许多联合学*的聚合技术,但是这项研究实现了所有权重的加权平均值。
1.导入库
2.超参数
- classes_pc: 每个客户端的类,此外,这用于通过在客户端之间创建类的不平衡表示来将平衡数据集划分为非 IID 数据集。例如,如果 classes_pc=1,则所有客户端将仅具有来自一个类别的图像,从而在客户端之间产生广泛的不平衡。
- num_clients :要分发图像的客户端数量。
- num_selected: 在每轮通信开始时从 num_clients 中随机选择的客户端的数量。用于全球模型的培训阶段。通常,num_selected 约为 num_clients 的 30–40%。
- num_rounds: 全局模型训练的总通信轮数。在每一轮沟通中,对单个客户的培训同时进行。
- 时期:每个客户端设备上的本地训练回合数。
- batch_size: 将数据批量加载到数据加载器中。
- baseline_num: 要保存在全局服务器上的基线图像的总数,用于在聚合之前重新训练客户端的模型。这种在全局服务器上重新训练所有模型的技术处理非 IID/真实世界的数据集。
- retrain_epochs: 从参与通信回合的所有客户端接收模型权重后,全局服务器上的再训练回合总数。
3.将平衡的 CIFAR10 转换并划分为非 IID 数据集。
CIFAR10 数据集被转换为极端非 IID 数据集(参见第二部分)。CIFAR10 由 60,000 张 32x32 像素的彩色图像组成 10 类。训练集由 50,000 幅图像组成,剩余的 10,000 幅图像用于测试目的。
下面是代码,将在本系列的第 2 部分中详细解释。请前往第 2 部分以更详细地理解以下片段。
要更深入地了解上述函数,请阅读本系列的第 2 部分,其中详细解释了每一个函数。
4.构建神经网络(模型架构)
本教程中使用了 VGG19 (16 个卷积层,3 个全连接层,5 个 MaxPool 层和 1 个 SoftMax 层)。
5.联邦学*的辅助函数
baseline_data 函数为基线数据创建一个加载器,在全局服务器上聚集权重之前,客户端的模型在该加载器上被重新训练。“num”是在全局服务器上对客户端模型进行再训练的图像数量。第 9–10 行获取 CIFAR10 数据,并打乱训练集。第 12 行从这个混洗的数据集中选择 num 个图像,随后它被用于在第 14 行创建数据加载器。
client_update 函数根据给定的私有客户端数据训练客户端模型。这是为每个选定的客户端,即 num_sleected(在我们的例子中是 6)进行的本地培训回合。
client_sync 函数将客户端模型(训练前)与全局权重同步。在特定客户端没有参与先前的通信回合的情况下,它是有帮助的,因此它确保所有选择的客户端具有来自全局模型的先前训练的权重。
server_aggregate 函数聚集从每个客户端接收的模型权重,并用更新后的权重更新全局模型。在本教程中,将计算权重的加权平均值。在本系列的第 1 部分中,平均值被用作聚合方法,而不是加权平均值。
测试函数是使用测试数据集评估全局模型的标准函数。它返回测试损失和测试准确性,用于不同方法的比较研究。
现在,我们已经完成了数据的所有预处理和联邦学*的一些辅助函数。因此,让我们深入研究模型的训练,即使用非 IID 数据集的联合学*。
6.训练模型
照片由谷歌人工智能
全局模型,客户端的模型用 VGG19 初始化,训练在 GPU 上完成。第 6–11 行,在 GPU (Cuda)上用 VGG19 初始化模型。在第 14 行,优化器(SGD)和学*率一起被定义。我们还可以在优化器中添加动量项。在第 17 行,基线数据被添加到具有‘baseline _ num’图像的加载器,即,如上定义的 100 个图像。
使用上述函数将非 IID 数据装载到 train_loader 中,这确保了数据是非 IID 数据。class _ PC = 2,num_clients=20,batch_size=32。
第 1–4 行创建了一个列表,用于跟踪模型在训练和测试数据集上的损失和准确性。第 7 行开始在通信回合(num_rounds)中训练单个客户端。在每一轮通信中,首先,用全局权重更新选定的客户端。然后,在客户端设备上训练本地模型,之后在全局服务器上进行再训练。在重新训练客户端的模型之后,将进行权重的聚合。
第 9 行从 num_clients 中选择 num_selected 个客户端,即从总共 20 个客户端中随机选择 6 个客户端。使用 client_sync(第 15 行)完成客户端设备上的训练(第 13–17 行),其中在训练之前使用全局权重更新本地模型,然后使用 client_update 函数(第 16 行)开始训练。一旦本地模型在设备本身上被训练,确保私有数据的隐私,它们就被发送到全局服务器。首先,使用基线数据对这些模型进行再训练(第 12-17 行)。接下来是将这些局部模型(权重)聚合(第 27 行)成一个全局模型。在更新全局模型之后,在上面定义的测试函数的帮助下,这个全局模型被用于测试训练(第 28 行)。
这个过程持续 num_rounds,在我们的例子中是 150 次通信。这是使用非 IID 数据集的联邦学*的例子,对于真实世界的数据集(在第 2 部分中定义)也可以做类似的事情,这可以进一步应用于一个真实的基于客户机的系统。
7.结果
对于 6 个选定的客户端,每个客户端运行 5 个本地时期,并在全局服务器上保留 20 个时期,在 150 轮通信的顶部,下面是截断的测试结果。
在全局服务器上重新训练的联合学*的准确性
相比之下,本教程中使用的方法给出了大约 72% 的准确度,而本系列第 1 部分中使用的方法在非 IID 数据集上应用时给出了大约 35% 的准确度。此外,当前的方法(在全球服务器上重新训练)与其他可用的方法相比要稳定得多。
在对这种方法(保留在具有加权平均值的全局服务器上)与第部分第 1 中使用的方法(即具有平均值的基本联合学*)的比较研究中,方法 2(在全局服务器上重新训练)远远优于第 1 部分中使用的方法。整个教程展示了在全局服务器上保留来处理数据集的非 IID 问题的重要性。因此,这项研究是处理非 IID 数据集问题的一个很好的方法,可以用于现实世界的用例中。
摘要
在本教程中,您发现了如何使用 PyTorch 的联邦学*来保护深度学*模型中的数据隐私,并且可以应用于现实世界的问题。
具体来说,您学到了:
- 非 IID 数据集上联邦学*的实现
- 加权平均值作为聚合技术(我们在第 1 部分中使用了权重的平均值)
- 在用全局服务器上的基线数据训练和重新训练客户端的模型之前,用全局权重同步客户端。
下面是快速修改整个过程的流程图。
非 IID 数据集的联邦学*流程图,作者插图
结论
联合学*是机器学*模型中保护数据隐私的主要方法之一。通过仅发送模型的更新权重,而不是数据,确保了客户端数据的安全性。这种用基线数据重新训练每个客户模型的方法处理了非 IID 数据的问题。此外,每个客户端模型的同步与全局权重以及加权平均值作为技术的集合,有助于获得该模型的良好准确性。本教程处理非 IID 数据集的极端情况,但是当用于现实生活中的数据时,它比我们的结果表现得更好,这是因为当前数据实际上比我们在现实生活场景中处理的数据更加截断。
在接下来的教程中,您不仅将了解联合学*中的不同聚合技术,还将了解模型权重的同态加密、差分隐私及其与联合学*的混合,以及一些有助于保护数据隐私的更多主题。
参考
[1] Felix Sattler,来自非 IID 数据的健壮且通信高效的联合学*, arXiv:1903.02891
[2] H.Brendan McMahan, 从分散数据中进行深度网络的通信高效学* ,第 20 届人工智能与统计国际会议论文集(AISTATS) 2017。JMLR: W & CP 第 54 卷
根据 262,144 次模拟,杜达总统将坚定地再次当选
原文:https://towardsdatascience.com/president-duda-heading-for-a-firm-re-election-according-to-262-144-simulations-3f5f6ceddb04?source=collection_archive---------24-----------------------
在总统决选前对趋势的详细分析给了 Trzaskowski 追赶现任的空间。
来源:安杰伊·杜达·脸书简介
免责声明:本文无意支持任何一位竞选波兰共和国总统的候选人。它只专注于提供以往总统选举的数据见解,并为本周日举行的决胜选举的可能结果建模。
由于波兰目前的政治平衡,今年的总统选举尤为激烈。
现任总统杜达正在努力争取连任,以维护执政党法律与正义党(PiS)目前的政治话语。
另一方面,反对派支持者试图通过选举公民纲领党副主席 rafatrzaskowski 来打破现政府的立法权。
这一选择很有分量,因为下一次议会选举将于 2023 年举行,Trzaskowski 的成功可能会引发提前大选。
来源:tvn24.pl
在第一轮投票中,杜达总统获得了 43.50%的选票,这是自 1989 年以来的第二好成绩。
然而,他能否战胜 Trzaskowski 仍不确定。过去一周的民意调查显示,没有明显的热门人选。
虽然几乎四分之三的选民决定支持两个最大政党的候选人,但 Szymon hoownia 和 Krzysztof Bosak 的选民本周将有至关重要的发言权。
资料来源:ewybory.eu,截至 2020 年 7 月 6 日
在过去几个月里,hoownia 和 Bosak 的选民结构都发生了变化。此外,民意调查通常包括一部分坚定的未决选民,这可能会扭曲结果。
为此,我决定分析波兰 2005 年、2010 年和 2015 年的前三次总统选举。基于投票之间的趋势和相关性,我试图提取合理的参数,并模拟本周日可能的结果。
为什么我只分析最后三个?这是因为 2005 年是波兰政治平衡的转折点。自那以后,只有两个政党交替当选执政——法律与正义党(PiS)和公民纲领党(PO)。
我将在接下来的部分深入探讨这个问题,但是如果你觉得对波兰的政治环境感到舒服,可以随意跳过它!
政治背景
2005 年之前,总统府以及议会多数席位都掌握在民主左翼联盟(SLD)手中。
由于 2002 年末的腐败丑闻,也就是所谓的莱文事件,他们开始失去公众的支持。此后,三大政治力量开始出现,并形成新的力量平衡。
保守派的法律与正义党(PiS)、自由派的公民纲领党(PO)和波兰共和国的社会民主自卫党(SO),重点关注农村事务。由于 SO 领导人 Andrzej Lepper 的古怪性格,它在与 PiS 和 PO 的竞选中失败了。
这两人本打算在 2005 年议会选举后创建一个联合政府。然而,在 PiS 在总统和大选中获胜后,联盟从未取得成果,PiS 和 PO 最终站在了政治光谱的对立两极。
自那以后,波兰政坛找到了平衡,两党的支持者在投票模式上基本保持一致。随着议会多数党的更迭——(2005-2007 年)PiS,(2007-2015 年)PO,(2015 年至今)PiS,没有一个外部政党能够获得足够的选票份额来破坏这一分裂。
在总统办公室也观察到类似的模式,分别由卡钦斯基(PiS)——2005 年,科莫洛夫斯基(PO)——2010 年,杜达(PiS)——2015 年获得。
由于投票*惯相对稳定,我决定将过去三次总统选举纳入我的分析。
在这篇文章中,我试图从历史数据中提取投票模式,并用它们来模拟本周日在……惊喜,惊喜——PiS 和 PO 候选人——安杰伊·杜达和 rafatrzaskowski 之间进行的决胜选举的潜在结果。
我们能从以前的选举中学到什么?
在接下来的两个部分中,我将展示过去总统选举的深刻见解以及它们对决胜选举最终结果的影响。
如果你对数学废话不感兴趣,跳转直接进入 谁领先 位!;)
我决定打破逐个县的投票模式,这使我能够调查当地的模式。
以下图中的每个点代表一个县。我还关注候选人相对于合格选民总数的投票份额,而不是总投票份额。这样,我们可以在我们的模型中考虑县投票率的变化。
总统选举中投票率的变化本身似乎并没有太大的不同。回归道岔的均方根误差(RMSE)保持在 2 个百分点的界限内。
前一次选举中的第一次投票率与第一次投票率
类似地,投票偏好基本保持不变,因为人们支持他们在以前的选举中投票支持的同一政党的候选人。
这是意料之中的,因为历史上 PiS 在农村地区和小城市更受欢迎。另一方面,PO 一直在城市地区取得强劲的成绩。
今年,当前的支持度与 2015 年的支持度之间有着特别强的相关性。回归系数大于 1 表明 2015 年有强烈偏好的县更支持同一政党的候选人。
杜达总统也注意到了这种回归的一个相对较大的截距——0.079。这意味着他设法在全国范围内将他的选民基础统一提高了大约 8 个百分点。
第一轮投票结果与上次选举的第一轮投票结果
这些结果表明,在过去的 5 年里,波兰政治舞台上的两极分化越来越严重,因为任何一方的选民都更加积极。
事实上,自 1990 年第一次民主选举以来,第三方候选人获得的选票份额(26.04%)位居第二。在 2010 年因斯摩棱斯克空难而举行的选举期间,这一数字只有所下降,斯摩棱斯克空难是波兰现代史上最具分裂性的事件之一。
为了确保在本周日获胜,这场比赛本质上归结为两个决定性因素——动员候选人自己的选民和说服大多数第三方选民。第三方选民在过去的总统选举中被证明是至关重要的。
让我们来看看 2005 年的总统选举,PiS 候选人莱赫·卡钦斯基在第一轮投票中以 33.10%的得票率位居第二,输给了他的 PO 对手唐纳德·图斯克,得票率为 36.33%。
虽然图斯克明显领先,但第三名的安杰伊·莱珀(15.11%)的选民显示出对卡钦斯基的强烈支持。最好的说明是回归莱珀在每个县关于卡钦斯基和图斯克在两次投票之间选民基础增加的结果。
每个县的候选人相对于 Andrzej Lepper 结果有所增加。
可以观察到民主左翼联盟候选人第四马雷克·博罗夫斯基的相反趋势,但与莱珀相比,他的选民基础相对较小且分布更均匀,这并没有弥补卡钦斯基支持率的上升。
卡钦斯基凭借与莱珀相似的选民基础,以 54.04%的总票数赢得了选举。
每个县的候选人相对于马雷克·博罗夫斯基结果的增加。
这是故事的一部分——第三方候选人对第二轮投票的结果有着重大(甚至是决定性)的影响。
然而,在第二轮投票之前动员自己的选民一直是两次投票之间为期两周的马拉松的重要组成部分。事实证明,并非偶然。
让我们来看看在第一轮决胜选举之前,每个候选人的选民基础的增长情况。
每个县的候选人相对于他们自己的结果有所增加。
特别是在 2010 年和 2015 年,两党候选人在每个县都取得了与其最初支持度成比例的收益。
这突出了一个事实,即许多主要政党的选民决定只在第二轮投票中投票,而最终决定必须在第二轮投票中做出。
科莫洛夫斯基的增长与他的初步结果特别相关,突出了 PO 的选民努力阻止杜达上任。
建模和假设
模拟选民基础的增加归结为候选人自己的结果,以及他们说服第三方选民的能力。
因此,我们可以拟合线性模型,根据候选人的投票结果和第三方选票的份额来预测候选人在每个县的增长。我故意不把对手的选票份额作为独立变量,因为它与候选人自己的结果负相关。最终模型是:
%增加= b0 + b1 x 候选人结果+ b2 x 第三方投票+ 误差
对最*三次选举中的两党候选人运行该模型,得到以下模型:
# standard deviation of each coefficient is given in bracketsTusk, 2005 increase = -0.041(0.005) + OWN x 0.329(0.021) + OTHER x 0.238(0.019)Komorowski, 2010 increase = 0.02(0.007) + OWN x 0.092(0.013) + OTHER x 0.206(0.046)Komorowski, 2015 increase = 0.001(0.004) + OWN x 0.536(0.013) + OTHER x 0.084(0.032)Kaczynski, 2005 increase = -0.106(0.01) + OWN x 0.423(0.049) + OTHER x 0.994(0.026)Kaczynski, 2010 increase = -0.045(0.006) + OWN x 0.257(0.011) + OTHER x 0.481(0.044)Duda, 2015 increase = -0.006(0.008) + OWN x 0.474(0.009) + OTHER x 0.267(0.06)
一些有趣的细节立刻引起了我的注意。
首先,PiS 一贯更擅长在第三方势力强大的县增加选民基础。2010 年的情况也是如此,当时 napieraski 的结果与科莫洛夫斯基的结果高度相关,减少了 napieraski 对 b2 的影响。
第二,两党都严重依赖于在决胜选举期间前往投票站的不太活跃的选民的推动。
然而,每个缔约方的增长能力似乎有限。将 b1 系数与第一轮投票中获得的结果进行比较,表明在更高支持水平上动员的能力下降。
PO 候选结果与 b1:
30.46% — (0.500–0.700)?
33.77% — 0.536
36.33% — 0.329
41.54% — 0.092
PiS 候选结果与 b1:
33.10% — 0.423
34.76% — 0.474
36.46% — 0.257
43.50% — (0.150–0.300)?
第一轮投票结果较低表明动员能力较高,选民基础有机增长。因此,更高的级别限制了这种能力,因为许多选民已经在第一轮投票中参加了投票。
考虑到这一点,我选择了一个相对较宽的系数范围,我们可以根据历史趋势预期看到这些系数。这是:
Trzaskowski B1:0.500–0.700
杜达 B1:0.150–0.300
对 b2 进行类似的假设。随着每次连续的选举,PiS 拦截第三方选民的能力减弱。今年,这可能是一项特别困难的任务,因为 Szymon Hoł ownia 的选民往往与更自由的价值观联系在一起。
尽管如此,说服第三方选民对两位候选人来说都是一项具有挑战性的任务,因此我们可以预计 b2 系数的低值与 2015 年选举相似。
Trzaskowski B2:0.150–0.300
杜达 B2:0.200–0.350
最后,b0 截距表明所有县的支持度均有增加。在投票人数大幅增加的情况下,这些数字往往会特别高,比如在 2015 年。
平均而言,他们倾向于将分数正常化,因为在任何一个县,任何一位候选人都很少获得少于 7-8%的合格选票。从历史上看,这个截距稍微有利于 PO 候选人。
Trzaskowski B0:(-0.040)—(-0.020)
杜达 B0:(-0.070)——(-0.040)
为了建模,我假设这些参数是均匀分布的。将每个区间截断成 8 个均匀分布的值,并模拟这些值的每个组合,得到了 262,144 个选举模拟。
谁领先?
选票的中间份额使杜达总统以总票数的 50.97% 处于领先地位,紧随其后的是 Trzaskowski49.03%。
百分比分数的标准偏差为 1.91%,这使得 Trzaskowski 的获胜边界与平均值的标准偏差不到一个。
该模型显示杜达总统有 68.8%的机会赢得本周日的选举。
两名候选人的投票份额分配
这仍然是一个相对较小的差额,极大地依赖于参数假设的有效性。
仅仅依靠过去的三次选举,这些参数很难建模。它们只能从总体投票模式和当前的政治平衡中间接推断出来。
预计投票率将达到 65.49%,标准差为 2.51%。鉴于这些结果,杜达预计将获得 1008 万张选票,而 Trzaskowski 目前约有 970 万张选票。
道岔分布
Trzaskowski 怎么做才能缩小差距?
由于高度的两极分化,动员他自己的选民似乎是一个特别有效的策略。
b1 达到 0.65 以上水平的模拟,使他与他的对手处于平等地位。Trzaskowski 目前的选民基础具有巨大的有机增长潜力,他的竞选团队应该努力利用这一事实。
你怎么想呢?
你认为这个分析遗漏了什么吗?
你认为我的假设是否正确?
也许你想更详细地谈谈这个模型?
随时联系!
[## Cezary Klimczuk -数据科学家|伦敦大学学院毕业生
www.linkedin.com](https://www.linkedin.com/in/cezary-klimczuk-423522129/)
我在 Jupyter Notebook 中使用 Python 进行了所有分析。
我下载并清理了 pkw.gov.pl 的选举数据。请随时访问我的 GitHub 页面 ,更深入地探索我的项目!
总统选举预测
原文:https://towardsdatascience.com/presidential-elections-forecast-19d366ea7945?source=collection_archive---------3-----------------------
我的预测依赖于每个州的流行数据的历史数据
承认
感谢阿斯玛·巴拉卡特帮助我收集这项研究所需的数据!
介绍
许多因素会影响选举结果,如新冠肺炎、弹劾、经济、失业率、自然灾害应对、气候变化、外交政策、人们对自己政党的忠诚度、辩论、总统身高以及许多其他因素。在本文中,我将只关注每个州普选的历史数据。
模型
建模和分析中使用的编程语言是 SAS 9.4。使用的模型是 PROC 单变量。
结果
为了测试我的模型,我预测了 2016 年的选举,并将结果与实际值进行了比较。总体而言,算法显示特朗普将在 2016 年获胜,这确实发生了。此外,它预测他将赢得 2020 年的选举。然而,通过检查状态的结果,我发现代码预测了 11 个错误的状态,进一步的细节如下。
我们应该收集历史上多长时间的数据?
这种模式完全依赖于人们对其政党的忠诚。它不包括任何其他因素。我们收集了自 1960 年以来每个政党的普选百分比。
选择 1960 年是暂定的。我认为大多数人不会改变他们的政党。因此,我搜索了美国的平均预期寿命,发现它大约是 78 岁,这意味着我应该回到 1940 年选举以来的数据。然而,通过一些反复试验,我发现 1960 年给出了最准确的结果。尽管如此,还需要进一步的实验来进行更准确的验证。
模型精度
我通过使用我的算法来预测 2016 年的选举,验证了这些实验。如图 1 所示,该算法正确预测了 39 个州和哥伦比亚特区,错过了 11 个州。然而,它预测共和党将以 311 张选举人票赢得 2016 年选举。民主党仅获得 224 票,接*共和党和民主党分别获得 304 票和 227 票的实际结果。
图 1:2016 年结果测得的模型精度
根据图 1,模型准确率为 78.43%。这个模型还有很大的改进空间,可以提高它的准确性。(请阅读文章末尾的更正)
二话没说,给你表:
表 1:结果
您可以从这里下载表 1 中列出的文件:
http://engyfoda.com/MYPREDICTIONSISA_2.xlsx
还可以下载以下文件:
民主党的 2020 年文件:http://engyfoda.com/DEMOCRATSISA.xlsx民主党的 2016 年文件:【http://engyfoda.com/DEMOCRATS2016.xlsx】T4共和党的 2020 年文件:http://engyfoda.com/REPUBLICANISA.xlsx共和党的 2016 年文件:http://engyfoda.com/REPUBLICAN2016.xlsx
注意:在上述文件中,最后一个变量(L)是每个州的选举人票。
形象化
通过比较我对 2016 年选举的预测和 2016 年实际结果的两张地图,图 2 和图 3,这是模型错过的 11 个州:
1.科罗拉多州(实际胜出的候选人是:希拉里)
2。伊利诺伊州(实际胜出的候选人是:希拉里克林顿)
3。密歇根州(实际胜出的候选人是:唐纳德·特朗普)
4。内华达州(实际获胜的候选人是:希拉里克林顿)
5。新罕布什尔州(实际获胜的候选人是:希拉里克林顿)
6。新墨西哥州(实际胜出的候选人是:希拉里)
7。北卡罗来纳州(实际获胜的候选人是:希拉里克林顿)(这是错误的。请阅读文末更正)
8。宾夕法尼亚州(实际胜出的候选人是:唐纳德·特朗普)
9。弗吉尼亚州(实际获胜的候选人是:希拉里克林顿)
10。西弗吉尼亚州(实际获胜的候选人是:唐纳德·川普)
11。威斯康星州(实际获胜的候选人是:唐纳德·特朗普)
图 2:我对 2016 年选举的预测
图 3:2016 年选举的实际结果
下面是我对 2020 年预测的可视化,如图 4 所示。通过比较我对 2016 年和 2020 年的预测,图 2 和图 4,只有西弗吉尼亚州从民主党转向共和党,导致共和党的选举人票从我 2016 年预测的 307 张增加到 2020 年预测的 311 张。由于该算法在 2016 年的结果中已经错过了 11 个州,这种错过在 2020 年的预测中仍然存在。所以我可以断定,算法对 2020 年的预测是川普以 78.43%的概率获胜。
图 4:2020 年预测
模型缺陷
该模型源于人们对其政党的忠诚度,而在 2020 年选举中,人们的偏好可能会因其他因素而改变。例如,许多共和党人反对特朗普,许多民主党人不赞成在 LGBT 和堕胎的性自由中占据自由概念,这违反了他们的宗教信仰。
而且这种分析只依赖两方的结果,不考虑对方的结果。如果我们收集第三方的结果并将其注入到模型中,一些州的结果会有所提高。
此外,仅使用两位小数。向模型输入更精确的数据将会提高它的准确性。
原始数据
每个州的原始数据可以从这里下载:
阿拉巴马,阿拉斯加,亚利桑那,阿肯色州,加利福尼亚州,科罗拉多州,康涅狄格州,特拉华州,佛罗里达州,佐治亚州,夏威夷,爱达荷州,伊利诺伊州, 马萨诸塞州,密歇根州,明尼苏达州,密西西比州,密苏里州,蒙大拿州,内布拉斯加州,内华达州,新罕布什尔州,新泽西州,新墨西哥州,纽约州 罗德岛,南卡罗来纳州,南达科他州,田纳西州,得克萨斯州,犹他州,佛蒙特州,弗吉尼亚,华盛顿,西弗吉尼亚,威斯康辛州
结论
这种模式完全依赖于人们对其政党的忠诚。可以为以后的工作做几个步骤。首先,做进一步的实验来验证时间回到哪一年会让我们得到更准确的结果。其次,增加输入数据文件中的小数位数可能会影响模型的性能。第三,在模型中加入更多的因素,如各州对新冠肺炎的反应、失业率以及对自然灾害的反应。自然灾害的应对可以是一篇全新的文章来研究和比较他们与每一位总统的数据。自 2016 年以来,野火、飓风和洪水的数量有所增加。总之,本文仅仅是一个开始,还有提高模型准确性的空间。
无论你的政党是什么,请投票。
Engy Fouda,
作者,使用 SAS Studio 学*数据科学
修正
我写道,该模型在 2016 年预测北卡罗来纳州是错误的,但它是正确的预测。唐纳德·特朗普在 2016 年赢得了北卡罗来纳州。我在输入两个实际投票时犯了一个错误;我把它们调换了。这一修正将模型准确率提高到 80.39%,因为它在 2016 年的选举中错过了 10 个州,而不是 11 个州。
压力脉动带来更好的浓缩咖啡
原文:https://towardsdatascience.com/pressure-pulsing-for-better-espresso-62f09362211d?source=collection_archive---------12-----------------------
压力曲线的时髦方式
五年前,我爱上了杠杆咖啡机。他们能够像半自动机器一样进行压力分析,但是没有成本。主要警告:杠杆机器需要艺术性。随着时间的推移,我学会了如何制作美味的浓缩咖啡。我还买了一些杠杆机器,并失去了购买更昂贵的压力剖面机的欲望,因为压力剖面是杠杆机器的标准功能。我仍然在阅读这些新机器,我发现了一个有趣的想法:压力脉动。
压力剖面
大多数咖啡店里的普通浓缩咖啡机对热水(理想温度为 90℃)施加恒定的压力(理想压力为 9 巴)来制作浓缩咖啡。更先进的机器给出一些调整压力的时间间隔。更好的是,你可以用类似于杠杆机器的非常低的压力进行预输注,这样,你就可以用压力进行注射。
压力剖面包括在整个发射过程中修改压力。你可以从低压开始,高压结束;你可以在高压下开始,在低压下结束。两者给了镜头不同的味道。
最*十年的进步已经使 PID 控制的温度和压力至少在咖啡店里为大众所接受。这些机器把所有的艺术性都简化成了一门科学,因为每次拍摄都可以根据水温、压力和体积进行复制。
压力脉动
最*看到浓缩咖啡三期,看到一个有趣的段子:“这成为了 Simonelli 集团脉冲喷射技术的基础,用在 Aurelia Wave 浓缩咖啡机上。对于浓缩咖啡萃取的三个阶段,咖啡师可以选择不同的流速通过圆盘。
所以我研究了奥雷利亚波,但是关于脉冲是如何工作的信息很少。保密可能是故意的,但我有一个聪明的想法:我可以尝试在手动机器上脉冲。
我用帕沃尼琴的次数更多了,所以我尝试了一次断奏。拉的时间比较长,但是结果很惊人。到目前为止,这是我一生中最好的一次拍摄。
https://www . LinkedIn . com/pulse/impact-pulse-jet-technology-my-espresso-extraction-andr % C3 % A9-eiermann
André Eiermann 用 Aurelia Wave 做了一些测试,他没有发现 TDS 差异,但他确实注意到了味道差异。我想知道在多点测量 TDS提取的体积是否会显示机器设置之间的更大差异。我认为他的实验没有达到应有的彻底程度,但这绝对是一个好的开始。他尝试测试了很多变量,对实验进行优先排序需要大量的试验、错误和直觉。
理论上,压力脉冲类似于在注射中间进行多次预输注。因此,基于对预灌输的了解,人们会期望在给定的输出体积中有相同或更高的提取。一般来说,使用预浸泡,浓缩咖啡比没有更高的提取率。Aurelia Wave 在预输注过程中确实会产生喷射脉冲,但我没有在手动杠杆机器上尝试过。
脉动过程
对于杠杆机器,我们有一系列的选择。这些说明假定类似于 la Pavoni 或 Kim Express 或 Flair:
- 预输注 15 秒
- 绽放 15 秒
- 脉冲 15 到 45 秒,直到达到所需的重量输出。
脉冲频率和持续时间是主要变量。目前,让脉冲提供*乎稳定的咖啡流似乎很重要。我的很多脉动都是基于拍摄过程中的视觉,并使用脉动来获得暗咖啡。副作用更少。
实验
我的意图是尝试不同持续时间的不同脉冲方法。问题是,用杠杆机器,我拉了更多的工匠镜头,我是根据我用相机在底部看到的进行调整的。像 DE1Pro 这样的像样的浓缩咖啡机本来可以帮助控制更多的变量,但我认为杠杆机器上的脉冲固有的一点是视觉上看到无底的 portafilter 和咖啡师进行实时调整之间的反馈。
为了收集数据,我试着交替使用压力脉冲拍摄和常规压力拍摄。常规压力注射仍然具有预注入和起霜,因为仅在注入期间施加脉冲。我也把我的大部分镜头作为断续浓缩咖啡镜头,因为它们味道更好,提取率更高。随着时间的推移,我积累了大量数据,然后我从这些数据中提取了一组数据点,其中机器、咖啡豆和重量对于常规压力射击和压力脉冲射击是相同的。
原始数据!
我最后得到了 17 个数据对,还不够统计意义。然而,它们很适合定性检查。建立一个足够大的统计数据集的困难意味着我必须拍摄 30 多对照片,这在我进行其他实验以及拨入新的咖啡烘焙时是很困难的。最重要的是,我发现压力脉冲改善了我的投篮,所以不这样做,我知道我没有尽我所能投出最好的球。话虽如此,我还是把我的数据归纳到下面这个。
数据:整合和清理
我用来比较的两个主要指标是提取率和最终得分。提取率由从圆盘中提取到杯中的咖啡量决定,而提取率由使用数字折射计(Atago) 测量总溶解固体(TDS)来确定。所有 17 对都有最终得分指标,但只有 9 对数据有 TDS 指标,因为我在开始收集这些配对数据点后开始收集 TDS 测量值。
最终得分是 7 项指标(强烈、浓郁、糖浆、甜味、酸味、苦味和余味)的记分卡的平均值。当然,这些分数是主观的,但它们符合我的口味,帮助我提高了我的拍摄水平。分数有一些变化。我的目标是保持每个指标的一致性,但有时粒度很难确定。
首先,从提取率来看,在大多数情况下,压力脉冲与常规注射相同或更好。该图在 x 轴上显示了常规压力提取,在 y 轴上显示了相应的压力脉冲提取。
当看最终得分时,趋势是相似的,但是有更多的情况下脉冲没有帮助。然而,这又回到了一个论点,即脉冲将提供相同或更好的提取,而不是更差的提取,因为它与预灌输相似。
红色圈出的数据点是非断奏镜头。剩下的都是断断续续的镜头。
以下是一些平均值的总体总结。我不能说这些分布在统计学上是显著的,但是它们已经足够有趣了,以至于我在所有的照片中都使用了压力脉冲。我还应该注意到,因为我不经常拉非断奏的镜头,所以我不太确定它的影响。从我在有压力脉动和没有压力脉动的情况下拍摄的非断奏照片来看,我没有注意到味道上的巨大差异。我怀疑的是在拍摄开始时提取率更高,但我没有数据支持这一说法。最*我还使用了更长时间的预输注,这是一个额外的变量。
我还有一些其他想探索的东西。我目前已经在数据表中添加了脉冲数以及预输注、开花和输注的时间。希望这能让我对压力脉动有更深入的了解。显然,如果我有一个压力计或 DE1Pro,我可以更好地控制和测量脉冲以及每个脉冲的压力峰值。同时,下面是我在研究压力脉动时想到的一系列实验:
- 每脉冲峰值压力
- 啁啾信号 vs 开/关
- 射击时间内的脉冲长度
- 预输注和压力脉动
总之,目前的证据表明压力脉冲(包括喷射脉冲)比恒压更好。关于手动机器的压力脉动的最好的部分是,它是一种容易应用和适应自己使用的方法;它不需要额外的硬件。
对于 Aurelia 波,我希望有人检查 1:1 输入/输出比下喷射脉冲的性能差异,因为我的实验表明提取受脉冲影响很大。
如果你愿意,可以在 Twitter 和 YouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡照片和浓缩咖啡相关的视频。你也可以在 LinkedIn 上找到我。
我的进一步阅读:
断续浓缩咖啡:提升浓缩咖啡
浓缩咖啡中咖啡的溶解度:初步研究
浓缩咖啡模拟:计算机模型的第一步
压力脉动带来更好的浓缩咖啡
咖啡数据表
工匠咖啡价格过高
被盗浓缩咖啡机的故事
平价咖啡研磨机:比较
浓缩咖啡:机头温度分析
浓缩咖啡过滤器分析
便携式浓缩咖啡:指南
克鲁夫筛:一项分析
Presto 联邦查询
原文:https://towardsdatascience.com/presto-federated-queries-e8f06db95c29?source=collection_archive---------15-----------------------
在 AWS 上使用 Ahana 的 PrestoDB 沙箱开始使用 Presto 联邦查询
帖子的音频介绍
介绍
根据 Presto 基金会的消息,Presto ( 又名 PrestoDB ),不要和 PrestoSQL 混淆,是一个开源、分布式、ANSI SQL 兼容的查询引擎。Presto 旨在针对从千兆字节到千兆字节的各种大小的数据源运行交互式专门分析查询。Presto 被许多知名组织大规模用于生产,包括脸书、推特、优步、阿里巴巴、 Airbnb 、网飞、 Pinterest 、 Atlassian 、纳斯达克和 more 。
在接下来的文章中,我们将更好地理解 Presto 执行联邦查询的能力,联邦查询在不移动数据的情况下连接多个不同的数据源。此外,我们将探索 Apache Hive、Hive Metastore、Hive 分区表和 Apache Parquet 文件格式。
AWS 上的 Presto
AWS 上的 Presto 有几个选项。AWS 推荐亚马逊 EMR 和亚马逊雅典娜。Presto 预装在 EMR 5.0.0 及更高版本上。Athena 查询引擎是从 Presto 0.172 衍生而来的,并不支持Presto 所有的原生特性。然而,Athena 有许多类似的特性以及与其他 AWS 服务的深度集成。如果您需要全面、精细的控制,您可以自己在亚马逊 EC2、亚马逊 ECS 或亚马逊 EKS 上快速部署和管理。最后,你可以决定从 AWS 合作伙伴那里购买一个有商业支持的 Presto 发行版,比如 Ahana 或 Starburst。如果您的组织需要来自经验丰富的 Presto 工程师的 24x7x365 生产级支持,这是一个绝佳的选择。
联邦查询
在现代企业中,很少会发现所有数据都存储在一个单一的数据存储中。考虑到组织内部和外部的大量可用数据源,以及越来越多的专用数据库,分析引擎必须能够高效地连接和聚合多个来源的数据。 AWS 将联合查询定义为一种功能,它使数据分析师、工程师和数据科学家能够对存储在关系、非关系、对象和定制数据源中的数据执行 SQL 查询。'
Presto 允许查询其所在位置的数据,包括 Apache Hive 、 Thrift 、 Kafka 、 Kudu 和 Cassandra 、 Elasticsearch 和 MongoDB 。事实上,目前有 24 种不同的 Presto 数据源连接器可用。使用 Presto,我们可以编写连接多个不同数据源的查询,而无需移动数据。下面是一个 Presto 联邦查询语句的简单示例,它将客户的信用评级与他们的年龄和性别相关联。该查询联合了两个不同的数据源,一个是 PostgreSQL 数据库表postgresql.public.customer
,另一个是 Apache Hive Metastore 表hive.default.customer_demographics
,其底层数据位于亚马逊 S3。
阿哈纳
Linux Foundation 的 Presto Foundation 成员, Ahana 是第一家专注于将基于 PrestoDB 的即席分析产品推向市场并致力于促进 Presto 社区发展和传播的公司。Ahana 的使命是为各种形状和规模的组织简化即席分析。阿哈纳在 GV ( 前身为谷歌风险投资)的领导下,已经成功筹集到种子资金。Ahana 的创始人拥有丰富的科技公司工作经验,包括 Alluxio、Kinetica、Couchbase、IBM、苹果、Splunk 和 Teradata。
PrestoDB 沙盒
这篇文章将使用 Ahana 的 PrestoDB 沙箱(在 AWS Marketplace 上可用的基于 AMI 的 Amazon Linux 2 解决方案)来执行 Presto 联邦查询。
Ahana 的 PrestoDB 沙盒 AMI 允许您快速开始使用 Presto 查询数据,无论您的数据驻留在哪里。这个 AMI 将单个 EC2 实例沙箱配置为既是 Presto 协调器又是 Presto 工作器。它附带了一个由捆绑的 PostgreSQL 支持的 Apache Hive Metastore。此外,还捆绑了以下目录,以便使用 Presto 进行尝试、测试和原型制作:
- JMX:对监控和调试很有用
- 内存:在 RAM 中存储数据和元数据,当 Presto 重新启动时,这些数据和元数据将被丢弃
- TPC-DS:提供一组模式来支持 TPC 基准 DS
- TPC-H:提供了一组模式来支持 TPC 基准 H
阿帕奇蜂房
在这个演示中,我们将使用由 PostgreSQL 支持的 Apache Hive 和 Apache Hive Metastore 。Apache Hive 是一个数据仓库软件,它使用 SQL 来帮助读取、写入和管理驻留在分布式存储中的大型数据集。该结构可以被投影到已经存储的数据上。提供了命令行工具和 JDBC 驱动程序来将用户连接到 Hive。Metastore 提供了数据仓库的两个基本特性:数据抽象和数据发现。Hive 通过提供与 Hive 查询处理系统紧密集成的元数据存储库来实现这两个功能,以便数据和元数据保持同步。
入门指南
要开始用 Presto 创建联邦查询,我们首先需要创建和配置我们的 AWS 环境,如下所示。
演示的 AWS 环境和资源的架构
订阅 Ahana 的 PrestoDB 沙盒
首先,在 AWS Marketplace 上订阅 Ahana 的 PrestoDB 沙盒。确保你知道所涉及的费用。美国东部(N. Virginia)基于 Linux 的 r5.xlarge 按需 EC2 实例的 AWS 当前价格为每小时 0.252 美元。为了进行演示,因为性能不是问题,所以您可以尝试一个较小的 EC2 实例,比如 r5。
配置过程将引导您创建一个基于 Ahana 的 PrestoDB 沙盒 AMI 的 EC2 实例。
我选择在默认的 VPC 中创建 EC2 实例。演示的一部分包括使用 JDBC 本地连接到 Presto。因此,还需要为 EC2 实例包含一个公共 IP 地址。如果您选择这样做,我强烈建议将实例的安全组中所需的端口22
和8080
限制为您的 IP 地址(一个/32
CIDR 块)。
限制仅从我当前的 IP 地址访问端口 22 和 8080
最后,我们需要为 EC2 实例分配一个 IAM 角色,该实例可以访问亚马逊 S3。我将 AWS 托管策略[AmazonS3FullAccess](https://console.aws.amazon.com/iam/home?region=us-east-1#/policies/arn:aws:iam::aws:policy/AmazonS3FullAccess$jsonEditor)
分配给 EC2 的 IAM 角色。
连接亚马逊 3FullAccess AWS managed policy to the Role
部分配置还要求一个密钥对。您可以使用现有密钥或为演示创建新密钥。为了在将来的命令中引用,我使用一个名为ahana-presto
的键和我的键路径~/.ssh/ahana-presto.pem
。确保更新命令以匹配您自己的密钥的名称和位置。
完成后,将提供使用 PrestoDB 沙箱 EC2 的说明。
您可以从基于 web 的 AWS EC2 管理控制台查看包含 Presto 的正在运行的 EC2 实例。请务必记下公共 IPv4 地址或公共 IPv4 DNS 地址,因为在演示过程中将需要此值。
自动气象站云形成
我们将使用亚马逊 RDS for PostgreSQL 和亚马逊 S3 作为 Presto 的附加数据源。GitHub 上的项目文件中包含一个 AWS CloudFormation 模板cloudformation/presto_ahana_demo.yaml
。该模板在默认 VPC 中为 PostgreSQL 实例创建一个 RDS,并创建一个加密的 Amazon S3 存储桶。
这篇文章的所有源代码都在 GitHub 上。使用下面的命令来git clone
项目的本地副本。
git clone --branch master --single-branch --depth 1 --no-tags \
[https://github.com/garystafford/presto-aws-federated-queries.git](https://github.com/garystafford/presto-aws-federated-queries.git)
要从模板cloudformation/rds_s3.yaml
创建 AWS CloudFormation 堆栈,请执行下面的aws cloudformation
命令。确保您更改了DBAvailabilityZone
参数值(粗体显示的)以匹配创建 Ahana PrestoDB 沙箱 EC2 实例的 AWS 可用性区域。以我为例,us-east-1f
。
*aws cloudformation create-stack \
--stack-name ahana-prestodb-demo \
--template-body file://cloudformation/presto_ahana_demo.yaml \
--parameters ParameterKey=DBAvailabilityZone,ParameterValue=**us-east-1f***
要确保运行在 Ahana PrestoDB 沙箱 EC2 上的 Presto 可以访问 RDS for PostgreSQL 数据库实例,请手动将 PrestoDB 沙箱 EC2 的安全组添加到数据库实例的 VPC 安全组入站规则内的端口5432
。我还将自己的 IP 添加到端口5432
,使我能够使用 JDBC 从我的 IDE 直接连接到 RDS 实例。
AWS CloudFormation 堆栈的 Outputs 选项卡包括一组值,包括 PostgreSQL 实例的新 RDS 的 JDBC 连接字符串JdbcConnString
,以及亚马逊 S3 bucket 的名称Bucket
。在演示过程中,所有这些值都是必需的。
准备 PrestoDB 沙箱
我们需要采取几个步骤来为我们的演示正确准备 PrestoDB 沙箱 EC2。首先,使用 PrestoDB 沙盒 EC2 SSH 密钥将scp
和properties
目录指向 Presto EC2 实例。首先,您需要将EC2_ENDPOINT
值(粗体显示的)设置为 EC2 的公共 IPv4 地址或公共 IPv4 DNS 值。您可以硬编码该值,或者使用下面显示的aws ec2
API 命令以编程方式检索该值。**
**# on local workstation
EC2_ENDPOINT=$(aws ec2 describe-instances \
--filters "Name=product-code,Values=ejee5zzmv4tc5o3tr1uul6kg2" \
"Name=product-code.type,Values=marketplace" \
--query "Reservations[*].Instances[*].{Instance:PublicDnsName}" \
--output text)scp -i "~/.ssh/ahana-presto.pem" \
-r properties/ sql/ \
ec2-user@${EC2_ENDPOINT}:~/ssh -i "~/.ssh/ahana-presto.pem" ec2-user@${EC2_ENDPOINT}**
设置环境变量
接下来,我们需要设置几个环境变量。首先,替换下面的DATA_BUCKET
和POSTGRES_HOST
值(粗体显示的)以匹配您的环境。PGPASSWORD
值应该是正确的,除非你在 CloudFormation 模板中修改了它。然后,执行命令将变量添加到您的.bash_profile
文件中。
***echo """
export DATA_BUCKET=**prestodb-demo-databucket-CHANGE_ME**
export POSTGRES_HOST=**presto-demo.CHANGE_ME.us-east-1.rds.amazonaws.com**export PGPASSWORD=5up3r53cr3tPa55w0rd
export JAVA_HOME=/usr
export HADOOP_HOME=/home/ec2-user/hadoop
export HADOOP_CLASSPATH=$HADOOP_HOME/share/hadoop/tools/lib/*
export HIVE_HOME=/home/ec2-user/hive
export PATH=$HIVE_HOME/bin:$HADOOP_HOME/bin:$PATH
""" >>~/.bash_profile***
或者,我建议用可用的更新来更新 EC2 实例,并安装您喜欢的工具,如htop
,来监控 EC2 的性能。
***yes | sudo yum update
yes | sudo yum install htop***
运行在 r5.xlarge EC2 实例上的htop
视图
在进一步配置演示之前,让我们回顾一下 Ahana PrestoDB EC2 实例的几个方面。Ahana 实例上预装了几个应用程序,包括 Java、Presto、Hadoop、PostgreSQL 和 Hive。显示的版本是截至 2020 年 9 月初的最新版本。
***java -version
# openjdk version "1.8.0_252"
# OpenJDK Runtime Environment (build 1.8.0_252-b09)
# OpenJDK 64-Bit Server VM (build 25.252-b09, mixed mode)hadoop version
# Hadoop 2.9.2postgres --version
# postgres (PostgreSQL) 9.2.24psql --version
# psql (PostgreSQL) 9.2.24hive --version
# Hive 2.3.7presto-cli --version
# Presto CLI 0.235-cb21100***
Presto 配置文件在/etc/presto/
目录中。配置单元配置文件在~/hive/conf/
目录中。这里有几个命令,您可以使用它们来更好地了解它们的配置。
***ls /etc/presto/cat /etc/presto/jvm.config
cat /etc/presto/config.properties
cat /etc/presto/node.properties# installed and configured catalogs
ls /etc/presto/catalog/cat ~/hive/conf/hive-site.xml***
快速配置
要配置 Presto,我们需要为新创建的 RDS for PostgreSQL 实例创建并复制一个新的 Presto postgresql
目录属性文件。修改properties/rds_postgresql.properties
文件,将值connection-url
(粗体显示的)替换为您自己的 JDBC 连接字符串,显示在 CloudFormation Outputs 选项卡中。**
**connector.name=postgresql
connection-url=**jdbc:postgresql://presto-demo.abcdefg12345.us-east-1.rds.amazonaws.com:5432/shipping**
connection-user=presto
connection-password=5up3r53cr3tPa55w0rd**
使用sudo
将rds_postgresql.properties
文件移动到正确的位置。
**sudo mv properties/rds_postgresql.properties /etc/presto/catalog/**
我们还需要修改现有的配置单元目录属性文件,这将允许我们从 Presto 写入非托管配置单元表。
**connector.name=hive-hadoop2
hive.metastore.uri=thrift://localhost:9083
**hive.non-managed-table-writes-enabled=true****
以下命令将用包含新属性的修改版本覆盖现有的hive.properties
文件。
**sudo mv properties/hive.properties |
/etc/presto/catalog/hive.properties**
为了完成目录属性文件的配置,我们需要重新启动 Presto。最简单的方法是重启 EC2 实例,然后 SSH 回到实例中。由于我们的环境变量在.bash_profile file
中,它们将在重启和登录回 EC2 实例后继续存在。
**sudo reboot**
将表添加到 Apache Hive Metastore
我们将使用 RDS for PostgreSQL 和 Apache Hive Metastore/Amazon S3 作为联邦查询的附加数据源。Ahana PrestoDB 沙盒实例预配置有 Apache Hive 和 Apache Hive Metastore,由 PostgreSQL 支持(EC2 上预安装的独立 PostgreSQL 9.x 实例)。
沙箱的 Presto 实例预配置了用于 TPC 基准 DS (TPC-DS)的模式。我们将在 Apache Hive Metastore 中创建相同的表,它们对应于 TPC-DS 数据源的sf1
模式中的三个外部表:tpcds.sf1.customer
、tpcds.sf1.customer_address
和tpcds.sf1.customer_demographics
。Hive 外部表描述了外部文件的元数据/模式。外部表文件可以由 Hive 外部的进程访问和管理。例如,下面是在配置单元 Metastore 中创建外部customer
表的 SQL 语句,该表的数据将存储在 S3 存储桶中。
**CREATE EXTERNAL TABLE IF NOT EXISTS `customer`(
`c_customer_sk` bigint,
`c_customer_id` char(16),
`c_current_cdemo_sk` bigint,
`c_current_hdemo_sk` bigint,
`c_current_addr_sk` bigint,
`c_first_shipto_date_sk` bigint,
`c_first_sales_date_sk` bigint,
`c_salutation` char(10),
`c_first_name` char(20),
`c_last_name` char(30),
`c_preferred_cust_flag` char(1),
`c_birth_day` integer,
`c_birth_month` integer,
`c_birth_year` integer,
`c_birth_country` char(20),
`c_login` char(13),
`c_email_address` char(50),
`c_last_review_date_sk` bigint)
STORED AS PARQUET
LOCATION
's3a://**prestodb-demo-databucket-CHANGE_ME**/customer'
TBLPROPERTIES ('parquet.compression'='SNAPPY');**
三条CREATE EXTERNAL TABLE
SQL 语句包含在sql/
目录中:sql/hive_customer.sql
、sql/hive_customer_address.sql
和sql/hive_customer_demographics.sql
。在继续之前,需要在所有三个文件中手动更新桶名(上方粗体显示的)为您自己的桶名。
接下来,运行下面的hive
命令,在现有的default
模式/数据库中的 Hive Metastore 中创建外部表。
**hive --database default -f sql/hive_customer.sql
hive --database default -f sql/hive_customer_address.sql
hive --database default -f sql/hive_customer_demographics.sql**
为了确认成功创建了表,我们可以使用各种hive
命令。
**hive --database default -e "SHOW TABLES;"
hive --database default -e "DESCRIBE FORMATTED customer;"
hive --database default -e "SELECT * FROM customer LIMIT 5;"**
使用“描述格式化的客户地址”Hive 命令
或者,您也可以使用hive
命令访问 CLI,从 Hive 内部交互地创建外部表。将 SQL 文件的内容复制并粘贴到hive
CLI。使用quit;
退出配置单元。
Apache Hive 中的交互式查询
亚马逊 S3 数据源设置
创建外部表后,我们现在将从 TPC-DS 数据源的三个表中选择所有数据,并将这些数据插入到相应的 Hive 表中。物理数据将以高效的列存储格式写入亚马逊 S3, SNAPPY 压缩的 Apache Parquet 文件。执行以下命令。接下来,我将解释为什么customer_address
表语句有点不同。
**# inserts 100,000 rows
presto-cli --execute """
INSERT INTO hive.default.customer
SELECT * FROM tpcds.sf1.customer;
"""# inserts 50,000 rows across 52 partitions
presto-cli --execute """
INSERT INTO hive.default.customer_address
SELECT ca_address_sk, ca_address_id, ca_street_number,
ca_street_name, ca_street_type, ca_suite_number,
ca_city, ca_county, ca_zip, ca_country, ca_gmt_offset,
ca_location_type, ca_state
FROM tpcds.sf1.customer_address
ORDER BY ca_address_sk;
"""# add new partitions in metastore
hive -e "MSCK REPAIR TABLE default.customer_address;"# inserts 1,920,800 rows
presto-cli --execute """
INSERT INTO hive.default.customer_demographics
SELECT * FROM tpcds.sf1.customer_demographics;
"""**
使用 AWS 管理控制台或 AWS CLI 确认数据已加载到正确的 S3 存储桶位置,并且是拼花格式。请放心,即使 S3 控制台错误地将Compression
显示为None
,拼花格式的数据也会被快速压缩。您可以使用像 parquet-tools 这样的实用程序轻松地确认压缩编解码器。
亚马逊 S3 中按关键字前缀组织的数据
使用 S3 的“选择”功能预览快速压缩的拼花地板格式数据
分区表
customer_address
表是唯一的,因为它是由ca_state
列进行分区的。分区表使用PARTITIONED BY
子句创建。
**CREATE EXTERNAL TABLE `customer_address`(
`ca_address_sk` bigint,
`ca_address_id` char(16),
`ca_street_number` char(10),
`ca_street_name` char(60),
`ca_street_type` char(15),
`ca_suite_number` char(10),
`ca_city` varchar(60),
`ca_county` varchar(30),
`ca_zip` char(10),
`ca_country` char(20),
`ca_gmt_offset` double precision,
`ca_location_type` char(20)
)
**PARTITIONED BY (`ca_state` char(2))** STORED AS PARQUET
LOCATION
's3a://**prestodb-demo-databucket-CHANGE_ME**/customer'
TBLPROPERTIES ('parquet.compression'='SNAPPY');**
根据 Apache Hive ,一个表可以有一个或多个分区列,并且为分区列中的每个不同的值组合创建一个单独的数据目录。由于 Hive 表的数据存储在亚马逊 S3 中,这意味着当数据被写入到customer_address
表中时,它会根据状态被自动分成不同的 S3 键前缀。数据被物理地“分区”。
亚马逊 S3 按州划分的客户地址数据
每当在 S3 中添加新分区时,我们需要运行MSCK REPAIR TABLE
命令来将该表的新分区添加到 Hive Metastore 中。
**hive -e "MSCK REPAIR TABLE default.customer_address;"**
在 SQL 中,谓词是一个条件表达式,其计算结果为布尔值,可以是真或假。定义与查询的条件/过滤器(谓词)中经常使用的属性一致的分区可以显著提高查询效率。当我们执行一个使用相等比较条件的查询时,比如ca_state = 'TN'
,分区意味着查询将只处理对应的ca_state=TN
前缀键中的一部分数据。在customer_address
表中有 50000 行数据,但是在ca_state=TN
分区中只有 1418 行(占总数据的 2.8%)。由于 Parquet 格式具有快速压缩的额外优势,分区可以显著减少查询执行时间。
将数据添加到 PostgreSQL 实例的 RDS
为了进行演示,我们还将把tpcds.sf1.customer_address
表的模式和数据复制到新的 PostgreSQL 实例的shipping
数据库中。
**CREATE TABLE customer_address (
ca_address_sk bigint,
ca_address_id char(16),
ca_street_number char(10),
ca_street_name char(60),
ca_street_type char(15),
ca_suite_number char(10),
ca_city varchar(60),
ca_county varchar(30),
ca_state char(2),
ca_zip char(10),
ca_country char(20),
ca_gmt_offset double precision,
ca_location_type char(20)
);**
像 Hive 和 Presto 一样,我们可以从命令行以编程方式或交互方式创建表;我更喜欢程序化的方法。使用下面的psql
命令,我们可以在shipping
数据库的public
模式中创建customer_address
表。
**psql -h ${POSTGRES_HOST} -p 5432 -d shipping -U presto \
-f sql/postgres_customer_address.sql**
现在,要将数据插入到新的 PostgreSQL 表中,运行下面的presto-cli
命令。
**# inserts 50,000 rows
presto-cli --execute """
INSERT INTO rds_postgresql.public.customer_address
SELECT * FROM tpcds.sf1.customer_address;
"""**
为了确认数据被正确导入,我们可以使用各种命令。
**-- Should be 50000 rows in table
psql -h ${POSTGRES_HOST} -p 5432 -d shipping -U presto \
-c "SELECT COUNT(*) FROM customer_address;"psql -h ${POSTGRES_HOST} -p 5432 -d shipping -U presto \
-c "SELECT * FROM customer_address LIMIT 5;"**
或者,您可以通过将sql/postgres_customer_address.sql
文件的内容复制并粘贴到psql
命令提示符来交互式地使用 PostgreSQL 客户端。要从psql
命令提示符与 PostgreSQL 交互,请使用以下命令。
**psql -h ${POSTGRES_HOST} -p 5432 -d shipping -U presto**
使用\dt
命令列出 PostgreSQL 表,使用\q
命令退出 PostgreSQL 客户端。现在,我们已经创建并配置了所有新的数据源!
与 Presto 交互
Presto 提供了一个监视和管理查询的 web 界面。该界面提供了对 Presto 集群和集群上运行的查询的仪表板式洞察。Presto UI 在使用公共 IPv4 地址或公共 IPv4 DNS 的端口8080
上可用。
有几种方法可以通过 PrestoDB 沙箱与 Presto 交互。这篇文章将展示如何使用 JDBC 连接和 Presto CLI 在 IDE 中对 Presto 执行特定查询。其他选项包括从 Java 和 Python 应用程序、 Tableau 或 Apache Spark/PySpark 中运行对 Presto 的查询。
下面,我们看到一个来自 JetBrains PyCharm 的针对 Presto 的查询,使用 Java 数据库连接(JDBC)连接。使用像 JetBrains 这样的 IDE 的优点是有一个单一的可视化界面,包括所有的项目文件、多个 JDBC 配置、输出结果,以及运行多个特定查询的能力。
下面,我们将看到一个使用 JDBC 连接字符串配置 Presto 数据源的示例,该字符串在 CloudFormation stack Outputs 选项卡中提供。
确保下载并使用最新的 Presto JDBC 驱动 JAR。
使用 JetBrains 的 ide,我们甚至可以限制数据源显示的数据库/模式。当我们配置了多个 Presto 目录,但是我们只对某些数据源感兴趣时,这是很有帮助的。
我们还可以使用 Presto CLI 运行查询,有三种不同的方式。我们可以将 SQL 语句传递给 Presto CLI,将包含 SQL 语句的文件传递给 Presto CLI,或者从 Presto CLI 进行交互工作。下面,我们看到一个从 Presto CLI 交互运行的查询。
当查询运行时,我们可以观察到实时的 Presto 查询统计信息(在我的终端中对用户不太友好)。
最后,查看查询结果。
联邦查询
演示中使用并包含在项目中的示例查询主要摘自学术文章Why You Should Run TPC-DS:A Workload Analysis,该文章在tpc.org网站上以 PDF 格式提供。我已经修改了 SQL 查询来处理 Presto。
在第一个示例中,我们将运行同一基本查询语句的三个版本。查询的版本 1 不是联合查询;它只查询一个数据源。第 2 版查询查询两个不同的数据源。最后,第 3 版查询查询三个不同的数据源。SQL 语句的三个版本都应该返回相同的结果— 93 行数据。
版本 1:单一数据源
查询语句的第一个版本sql/presto_query2.sql
不是联邦查询。查询的四个表(catalog_returns
、date_dim
、customer
和customer_address
)中的每一个都引用 TPC-DS 数据源,这是预装在 PrestoDB 沙箱中的。注意第 11–13 行和第 41–42 行的表引用都与tpcds.sf1
模式相关联。
我们将使用presto-cli
以非交互方式运行每个查询。我们将选择sf1
(比例因子为 1) tpcds
模式。根据 Presto ,比例因子(sf1
、sf10
、sf100
)中的每个单位对应一个千兆字节的数据。
**presto-cli \
--catalog tpcds \
--schema sf1 \
--file sql/presto_query2.sql \
--output-format ALIGNED \
--client-tags "presto_query2"**
下面,我们看到了presto-cli
中的查询结果。
下面,我们看到第一个查询在 Presto 的 web 界面中运行。
下面,我们在 Presto 的 web 界面中看到了第一个查询的详细结果。
版本 2:两个数据源
在查询语句的第二个版本sql/presto_query2_federated_v1.sql
中,两个表(catalog_returns
和date_dim
)引用了 TPC-DS 数据源。另外两个表(customer
和customer_address
)现在引用 Apache Hive Metastore 来获取它们在亚马逊 S3 的模式和底层数据。注意第 11 行和第 12 行上的表引用,而不是第 13 行、第 41 行和第 42 行。
再次使用presto-cli
运行查询。
**presto-cli \
--catalog tpcds \
--schema sf1 \
--file sql/presto_query2_federated_v1.sql \
--output-format ALIGNED \
--client-tags "presto_query2_federated_v1"**
下面,我们在 Presto 的 web 界面中看到了第二个查询的详细结果。
即使数据在两个独立的、物理上不同的数据源中,我们也可以很容易地对其进行查询,就好像它们都在同一个地方一样。
版本 3:三个数据源
在查询语句的第三个版本sql/presto_query2_federated_v2.sql
中,两个表(catalog_returns
和date_dim
)引用了 TPC-DS 数据源。其中一个表(hive.default.customer
)引用了 Apache Hive Metastore。底层数据在亚马逊 S3。第四个表(rds_postgresql.public.customer_address
)引用 PostgreSQL 数据库实例的新 RDS。注意第 11 行和第 12 行以及第 13 行和第 41 行的表格引用,与第 42 行相对。
同样,我们使用presto-cli
运行了查询。
**presto-cli \
--catalog tpcds \
--schema sf1 \
--file sql/presto_query2_federated_v2.sql \
--output-format ALIGNED \
--client-tags "presto_query2_federated_v2"**
下面,我们在 Presto 的 web 界面中看到第三个查询的详细结果。
同样,即使数据在三个独立的、物理上不同的数据源中,我们也可以很容易地对其进行查询,就好像它们都在同一个地方一样。
其他查询示例
该项目包含几个额外的查询语句,这些语句是我从Why You Should Run TPC-DS:A Workload Analysis中提取的,并修改了 Presto 和跨多个数据源的联邦工作。
**# non-federated
presto-cli \
--catalog tpcds \
--schema sf1 \
--file sql/presto_query1.sql \
--output-format ALIGNED \
--client-tags "presto_query1"# federated - two sources
presto-cli \
--catalog tpcds \
--schema sf1 \
--file sql/presto_query1_federated.sql \
--output-format ALIGNED \
--client-tags "presto_query1_federated" # non-federated
presto-cli \
--catalog tpcds \
--schema sf1 \
--file sql/presto_query4.sql \
--output-format ALIGNED \
--client-tags "presto_query4"# federated - three sources
presto-cli \
--catalog tpcds \
--schema sf1 \
--file sql/presto_query4_federated.sql \
--output-format ALIGNED \
--client-tags "presto_query4_federated" # non-federated
presto-cli \
--catalog tpcds \
--schema sf1 \
--file sql/presto_query5.sql \
--output-format ALIGNED \
--client-tags "presto_query5"**
结论
在这篇文章中,我们通过使用来自 AWS Marketplace 的 Ahana 的 PrestoDB 沙盒产品,对 Presto 有了更好的理解。我们学*了 Presto 如何查询数据所在的位置,包括 Apache Hive、Thrift、Kafka、Kudu 和 Cassandra、Elasticsearch、MongoDB 等。我们还了解了 Apache Hive 和 Apache Hive Metastore、Apache Parquet 文件格式,以及如何和为什么在亚马逊 S3 对 Hive 数据进行分区。最重要的是,我们学*了如何编写联合查询,将多个不同的数据源连接起来,而不将数据移动到一个单一的数据存储中。
本博客代表我自己的观点,而非我的雇主亚马逊网络服务公司的观点。
窥视黑匣子
原文:https://towardsdatascience.com/prettifying-partial-density-plots-in-python-1f7216937ff?source=collection_archive---------20-----------------------
内部 AI
更吸引人的部分依赖图如何在黑盒模型中与非技术涉众建立信任。
人们不相信他们不了解的东西。人工智能和机器学*算法是我们拥有的一些最强大的技术,但它们也是最容易被误解的。因此,数据科学家最重要的职责之一就是以易于理解的方式传达复杂的信息。
黑盒模型
也许对神经网络最大的误解之一是,我们不能直接看到产生结果的模型。我们可以看到我们的投入和产出,我们可以衡量结果,但我们并没有真正理解它们之间的关系。从实用性的角度来看,这是有问题的,因为像人类一样,关系的本质会随着时间而改变。人工智能今天对卡车的感知可能会反映出卡车明天的样子。
特斯拉赛博卡车。来源:迈克·马琳/Shutterstock.com
然而,大多数变化都不像特斯拉的网络卡车那样刺耳。如果我们看不到算法的内部,我们怎么知道算法正在跟上普通假设的逐渐变化呢?我们打开盒子。我们拥有的最好的工具之一是部分依赖图(PDP)。
部分相关图
Scikit-Learn 的创作者这样描述部分依赖情节:
部分相关性图(PDP)显示了目标响应和一组“目标”特征之间的相关性,忽略了所有其他特征(“补充”特征)的值。
换句话说,PDP 允许我们看到预测变量的变化如何影响目标变量的变化。下面是一个 PDP 的例子,显示了不同的房子特征对预测价格的影响。
来源: Scikit-Learn
从这些图中,我们可以看到,随着中值收入和房屋年龄的增加,预测价格往往会增加。然而,随着一个地区平均入住率的上升,预测价格会下降。底部的线条代表观察值的分布。
这些情节非常容易理解和创作。使用拟合的模型、数据集(仅限 X 要素)和输入要素列表,您可以在导入相关库后使用单行代码生成上述图:
import matplotlib.pyplot as plt
from sklearn.inspection import partial_dependence, plot_partial_dependenceplot_partial_dependence(model, X, features)
这些图对于几乎任何类型的回归模型都很好。然而,我发现在将 PDP 应用于分类任务时,非技术利益相关者有时很难解释结果。更重要的是,它们看起来并不特别吸引人。让我们打扮一下,并添加一些功能。
美化的 PDP
为了便于说明,我们将使用泰坦尼克号数据集。我们将使用 XGBoost 分类模型构建一个简单的模型,该模型尝试基于几个输入特征来识别幸存者。我们最感兴趣的是弄清楚我们的模型如何使用年龄作为存活率的预测指标(没有双关语)。
from xgboost import XGBClassifierdf = pd.read_csv('titanic.csv')
X = df[['Age', 'SibSp', 'Parch', 'Fare']]
y = df['Survived']model = XGBClassifier()
model.fit(X, y)fig = plt.figure(figsize(10, 9))
plot_partial_dependence(model, X, ['Age'], fig=fig)
plt.show()
正如我们所看到的,我们的模型已经确定,在所有其他因素相同的情况下,老年人更不可能存活。我们还可以看到大多数乘客年龄在 20 到 40 岁之间。
如果我们可以通过在同一个图表上绘制直方图来更清楚地了解年龄分布,这不是很好吗?将部分相关值显示为百分比怎么样?如果我们也能可视化决策边界,那不是很好吗?我们可以通过使用 partial _ dependence 方法获取部分依赖值并自己绘制结果来完成所有这些工作。幸运的是,我已经创建了一个函数来完成这项工作。
from sklearn.inspection import partial_dependence
上述函数将为单个输入变量生成一个 PDP,并允许输入轴标签和图表标题的目标名称。此外,它还提供了将 y 轴刻度显示为百分比、更改决策边界以及返回部分相关值以供进一步分析的选项。通过坚持使用标准设置并为目标传递一个名称,我们得到如下结果:
plot_pdp(model, X, 'Age', target='Survival')
有了这个,我们对年龄分布有了更丰富的了解。我们可以清楚地看到年龄跨越了决策界限。我们以一种让非技术利益相关者更容易阅读和理解的方式来标记轴。从这里开始,您可以试验这些选项,看看它们如何改变图表的显示,或者根据您的喜好修改代码。
如果没有别的,我会鼓励你想出新的方法来分享你的工作,以创造更多的非技术观众的参与。
更新:如果将上述代码与GradientBoostingRegressor或GradientBoostingClassifier一起使用,则需要将方法设置为“brute”
partial_dependence(model, X, ['Age'], method='brute')
身体和精神疾病的流行
原文:https://towardsdatascience.com/prevalence-of-physical-and-mental-diseases-450c0f4f5851?source=collection_archive---------59-----------------------
在完全观想繁荣。
女性与男性以及年轻人与老年人——在 MIMIC-III 的约 3 万名重症监护患者的数据集上分析身体和精神疾病患病率的差异。
电子健康记录(EHRs)是医疗信息的宝库(点击阅读更多关于 EHRs 的信息)。在本帖中,我们将使用来自 MIMIC-III 的 EHRs 来分析疾病流行率在年龄和性别上的差异。
EHRs 中的数据通常以自由文本的形式提供,因此很难用于任何类型的统计分析。这意味着我们首先需要构建它。为此,我们将使用医学概念注释工具(MedCAT) 。MedCAT 用于从自由文本中提取和组织提及的医学概念(疾病、症状等)。一旦我们有了结构化格式的信息,我们就可以进行分析,并创建几个图表来展示疾病频率的差异。
这篇文章附有一个Google Colab其中包含了完整的源代码。Colab 使用虚拟数据,模拟 MIMIC-III 中的表格(不公开提供)。****
准备数据
MIMIC-III 数据库的组织方式使得每个文档(EHR)都有一个ID
并且每个ID
都与一个患者相关联。对于每个病人,我们也有年龄和性别的信息。一名患者可以有 0 个或多个文档(临床记录)。如果你对如何组织和准备该项目和类似项目的 MIMIC-III 数据库感兴趣,请查看数据集分析和准备。
这里,我将假设您知道如何使用 MedCAT,并且所有相关的概念都已经提取出来,并且在 python 字典中可用,如下所示。如果你想学*如何使用 MedCAT,请查阅 MedCAT 教程。
**concept_location = {'concept_id': [<documents_with_concept>], ...}**
concept_location
—告诉我们每个概念 ID(疾病)在哪个文档(EHR)中找到。这本字典提供了足够的信息来联系疾病和病人,并分析年龄和性别的差异。
concept_id
—身体或精神疾病的唯一标识(在中为 CUI)。
documents_with_concept
—找到某个概念的所有文档 id(EHR)的列表。
在我们继续之前,我们需要生成几个映射(下面的代码块),考虑到数据集的格式,这样做的方式可以不同。如果你想用一些虚拟数据测试一切,看看附带的 Google Colab 。虚拟日期遵循 MIMIC-III 中数据的精确组织。我们需要的所有映射都可以使用 Colab 中所示的concept_location
来创建。
**# CUI (the disease identifier) to patientId
#that have that disease.
cui_pts = {}# PatientID to gender
pt2gender = {}# PatientID to Age group (find the definitions for age groups [here](https://www.researchgate.net/publication/232746130_Automated_Medical_Literature_Retrieval))
pt2agegroup = {}# PatientId to age (years)
pt2age = {}# PatientId to list of disease identifiers
pt2cuis = {}**
我已经为 MIMIC-III 数据集创建了映射,其方式与 Colab 中显示的方式完全相同。更进一步,我将假设上面的映射已经被计算过了。
现在,我们希望创建一个 CSV 文件,其中包含我们制作图表所需的所有数据,这些图表将显示每个疾病和组(年龄、性别)的患者分布情况。我们将组织 CSV,以便每行包含一种疾病及其所有必要信息:
- 患有该疾病的患者总数
- 患有该疾病的女性/男性患者人数
- 每个年龄组的患病人数
首先,让我们获得每个患者组的计数,如果我们想要计算患有给定疾病的患者的比例,这是必要的:
**pt_total = len(pt2age)pt_male = len([x for x in pt2gender if pt2gender[x] == "M"])pt_female = len([x for x in pt2gender if pt2gender[x] == "F"])pt_adl = len([x for x in pt2agegroup if pt2agegroup[x] == "Adolescent"])pt_yadult = len([x for x in pt2agegroup if pt2agegroup[x] == "Young Adult"])pt_adult = len([x for x in pt2agegroup if pt2agegroup[x] == "Adult"])pt_maged = len([x for x in pt2agegroup if pt2agegroup[x] == "Middle Aged"])pt_aged = len([x for x in pt2agegroup if pt2agegroup[x] == "Aged"])**
现在,我们可以创建 CSV 的头部。唯一未知的一栏是TUI
,它决定了是身体疾病还是精神疾病(摘自 UMLS )。
**csv = [['disease', 'cui', 'tui', 'total', 'male', 'female', 'Adolescent', 'Young Adult', 'Adult', 'Middle Aged', 'Aged']]**
对于每种疾病,我们知道所有患有这种疾病的患者(从cui_pts
图中),我们可以用它来计算每一组患有某种疾病的百分比:
**for cui in cui_pts:
d = cdb.cui2pretty_name[cui]
t = (len(cui_subjects[cui]) / pt_total) * 100
m = (len([x for x in cui_subjects[cui] if
subject2gender[x] == 'M']) / pt_male) * 100
f = (len([x for x in cui_subjects[cui] if
subject2gender[x] == 'F']) / pt_female) * 100
adl = (len([x for x in cui_subjects[cui] if
subject2agegroup[x] == 'Adolescent']) / pt_adl) * 100
yadult = (len([x for x in cui_subjects[cui] if
subject2agegroup[x] == 'Young Adult'])/pt_yadult)*100
adult = (len([x for x in cui_subjects[cui] if
subject2agegroup[x] == 'Adult']) / pt_adult) * 100
maged = (len([x for x in cui_subjects[cui] if
subject2agegroup[x] == 'Middle Aged']) / pt_maged)*100
aged = (len([x for x in cui_subjects[cui] if
subject2agegroup[x] == 'Aged']) / pt_aged) * 100# We get the TUI from medcat
tui = cdb.cui2tui[cui]
# Add to the array that will become the CSV
dt.append([d, cui, tui, t, m, f, adl, yadult, adult, maged, aged]**
现在,我们从数据中创建了一个熊猫数据框架,并根据每种疾病的患者总数对其进行排序:
**df = pd.DataFrame(dt[1:], columns=dt[0])# Sort by total
df = df.sort_values(by=['total'], ascending=True)**
身体和精神疾病
为了绘制前 30 种身体和精神疾病,我们现在可以简单地使用熊猫的内置绘图功能:
**# Physical: T047
# Mental: T048# Subset the data, to a certain type and number
_data = df[df.tui=='T048'].iloc[-30:]ax = _data.plot(y=['total'], x="disease", kind="barh")# Hide the legend and add labels
_ = ax.legend().set_visible(False)
_ = ax.set(xlim=(0, 17), ylabel="Disease Name", xlabel="Percentage of patients with disease")plt.show()**
********
图一。左边是身体疾病的分布,右边是精神疾病的分布。
请注意:图 1 中的情节和本帖中的所有其他情节都是实验性的,主要用于展示 MedCAT。
女性 vs 男性
我们创建的数据框架包含了制作大量绘图所需的所有数据。如果我们现在需要精神和身体疾病的女性和男性患者:
**# Subset the data
_data = df[df.tui=='T048'].iloc[-30:]
ax = _data.plot(y=['male', 'female'], x="disease", kind="barh")# Set the legend and labels
ax.legend(loc='lower right')
_ = ax.set(xlim=(0, 17), ylabel="Disease Name", xlabel="Percentage of patients with disease", )plt.show()**
********
图二。女性和男性患者的身体疾病分布在左侧,精神疾病分布在右侧。
在这种情况下,我们也可以证明我们的结果得到了医学领域已发表的工作的支持。图表显示抑郁症在女性患者中比在男性患者中更常见(由论文支持)。或者说物质滥用(主要是酒精)在男性患者中要常见得多(由论文支持)。****
这表明我们的结果不是随机的,我们使用的整个管道工作得相当好。
年轻人对老年人
最后,我们将分析基于年龄的差异。由于无法按年份显示疾病,我们将患者分组(取自此处的):
- 青少年 : 13 至 18 岁
- 青壮年 : 19 至 24 岁
- 成年人 : 25 至 44 岁
- 中年 : 45 至 64 岁
- 年龄 : 64 岁以上
图 3。身体疾病的年龄分布。
正如预期的那样,对于大多数疾病来说,随着年龄的增长,患病人数的百分比会增加。
图 4。精神疾病的年龄分布。
精神疾病在老年人中也更普遍,这也是意料之中的。唯一的例外是亢奋行为和冲动性格。一个有趣的概念是酒精滥用,成年人达到高峰,青少年比年轻人高。****
结束了
我们探索疾病频率和年龄/性别之间关系的项目到此结束。相同的实验(以及更多在分析 EHRs 中介绍的)可以很容易地在真实世界的医院数据上进行和重复,并有可能用于改善医疗保健。
感谢您的阅读。
预防和应对疾病爆发
原文:https://towardsdatascience.com/preventing-and-tackling-outbreaks-f790f2fca5d2?source=collection_archive---------30-----------------------
群落发现及其在系统发育网络中的应用
为了便于结果的分析和可视化,实现了一个 web 应用程序— Phyl。
随着高通量测序方法的出现,需要新的方法来可视化和分析越来越多的数据。虽然一些软件已经存在,但是它们不能很好地扩展或者需要高级技能才能在系统发育学中有用。
该项目的目的是实现三种社区发现算法——Louvain、Infomap 和分层标签传播(LLP);使用两个合成网络——格文-纽曼(GN)和兰奇希尼蒂-福图纳托-拉迪奇(LFR)对它们进行基准测试;在真实的网络中测试它们,特别是来自金黄色葡萄球菌 MLST 数据集的一个;比较可视化框架——cyto scape . js 和 D3.js,最后,把它们都放到网上(【mscthesis.herokuapp.com】T4)。
鲁汶、信息地图和 LLP 都是用 JavaScript 实现的。除非另有说明,以下结论适用于 GN 和 LFR。就速度而言,卢万胜过所有其他人。考虑到准确性,在有明确社区的网络中,卢万是最准确的。对于更高的混合,LLP 是最好的。与弱混合相反,在高度混合的 GN 中,提高分辨率参数是有利的。在 LFR,较高的分辨率会降低检测的准确性,与混合参数无关。平均节点度的增加提高了划分的准确性,并且最小化了偶然检测的可能性。使用项目中开发的算法或 LFR 实现来生成具有更高混合度或平均度的 GN 在计算上更密集。在金黄色葡萄球菌网络中,鲁汶在检测直接由共同祖先进化而来的 7 组菌株的聚类中是最快最准确的。
介绍
根据经济学家的说法,数据已经成为世界上最重要的资源[1]。越来越多的信息迫切需要新的存储、分析和可视化方法。
真实系统中不同元素之间的相互作用可以看作是网络[2]。从它们的拓扑或连接模式中,可以提取功能知识。虽然经验分析在小型网络中很有用,但对于大数据来说,使用算法来揭示其属性是不可或缺的。因此,被称为图形的数学模型被用来简化它们的表示。图论提供了分析它们的所有工具。这种表示意味着必须获得网络的所有元素及其关系。一般来说,分析越接*人群,收集数据就越困难。两个主要原因是缺乏非侵入性的获取方法或隐私问题[3]。事实上,在医疗领域,关于患者数据保护的立法变得越来越严格[4]。一方面,确保医学数据的伦理使用是基本的,另一方面,它可能构成调查许多病理原因的障碍。接下来,讨论将集中在传染病这个特定的话题上。
正如世界卫生组织所述,耐药性(AMR)是 2019 年需要关注的十大主要威胁之一[5]。在过去的几年里,由于使用了旨在治疗由病原微生物引起的疾病的药物,AMR 得到了加强。根据生物体的不同,它被细分为抗病毒(病毒)、抗生素(细菌)、抗真菌(真菌)或抗寄生虫(寄生虫)抗性。尽管耐药性是一个自然进化过程,随着时间的推移,最有能力的菌株会被选择出来,但抗菌药物的使用频率,甚至误用,正在加速几种微生物物种的耐药率的增长[6]。这不仅在人群中特别相关,而且在农场中也特别相关,在农场中,牛被给予预防性剂量的抗生素作为生长助剂。此外,人们在世界各地旅行的频率也促进了耐药微生物的传播。由于所有这些以及传染病的高死亡率(图 1),授权中央卫生当局使用可扩展且易于使用的工具以允许他们在短时间内进行干预是至关重要的[7]。
图 1 感染仍然是死亡的主要原因之一(*)。世卫组织在 2000 年至 2015 年间从世卫组织成员国的 90,000 多人中收集的数据。改编自[8]。
*年来开发的下一代测序方法为我们提供了大量的微生物数据[9]。事实上,由于全基因组测序方法的高分辨能力,已经有可能推断菌株之间更精确的进化关系。因此,具有更高数量基因的等位基因谱不断增加,并且由此可以评估描述菌株间进化距离的更完整的系统发育树或网络。所有这些在疾病预防的多个阶段都是有用的:疫苗设计、评估已测序菌株的致病性、检测疾病爆发和控制感染。以及诊断,增强混合感染的检测(由多种遗传上不同的生物体引起)[10]。
一般来说,这个项目的目标是从系统发育网络的拓扑结构中提取功能知识。例如,能够根据网络中其他生物的相似性和特征,推断出对抗生素的抗性等特性。与随机网络相反,真实网络呈现不对称的边分布。根据这种不对称性,可以识别出节点群。根据定义,社区是网络中边密度较高的区域。尽管如此,这个定义还不够严格,不足以在图中确定它们。这就提出了下面的问题:如果不清楚我们在找什么,我们怎么能发现社区呢?为了回答这个问题,社区发现理论在过去几年中得到了发展。尽管在检测的准确性和速度方面已经有了相当大的进步,但是在不同的网络中,一些算法比其他算法表现得更好。
目标
该项目的目标是用 JavaScript 实现三种社区发现算法——Louvain、Infomap 和分层标签传播(LLP);在准确性和速度方面,与两个合成网络——格文-纽曼(GN)和兰奇希尼蒂-福图纳托-拉迪奇(LFR)网络进行比较;使用亚马逊、扎卡里空手道俱乐部和葡萄球菌 金黄色葡萄球菌多位点序列分型(MLST)单位点变异(SLV)网络进行额外测试;比较不同可视化框架的工具和对大数据的稳健性——D3 . js(使用 SVG 和 Canvas 元素)和 Cytoscape.js,并创建一个 web 应用程序来实现网络可视化(在运行社区发现算法之前和之后),并绘制从基准测试中获得的所有数据。
文章大纲
在方法上,介绍了已实现的社区发现算法、已实现的基准工具、真实测试数据和数据可视化库。结果表明,社区发现算法在准确性和速度方面进行了分析。基准网络的生成速度是基于网络的不同属性来确定的。比较了不同的 web 可视化框架。并且使用不同的算法和输入参数来划分金黄色葡萄球菌 MLST SLV 网络。最后,对目标是否实现进行了回顾性分析,详细说明了 INSaFLU web 应用中的主要困难和未来需要完成的工作,并对已经完成的工作提出了一系列前瞻性改进建议。
方法学
社区发现
鲁汶算法
该算法在项目中实施,分为两个阶段:模块化优化和社区聚集[11]。合在一起,它们被认为是 1 次通过。第一步完成后,接着是第二步。两者都被执行,直到网络中不再有变化并且实现最大模块化。
模块化优化——该算法将随机排序网络中的所有节点,以便一个接一个地将它们移除并插入不同的社区 C 。这将持续到模块性(输入参数)没有显著增加被证实:
设中的∑为 C 、 ∑tot 中所有链接到 C 、 ki 中节点的权重之和 i 、 ki、中所有链接到 i 的权重之和
社区聚合——完成第一步后,属于同一个社区的所有节点合并成一个巨型节点。连接巨型节点的链接是先前连接来自相同不同社区的节点的链接的总和。该步骤还生成自循环,该自循环是在折叠成一个节点之前给定团体内所有链接的总和。
信息地图算法
与 Louvain 类似,也实现了 Infomap 算法。它使用不同的质量函数(最小描述长度[12])来划分网络:
设 qm 是模块 m 的退出概率,而 pα 是相对权重 wα ,其计算方法是将连接到α的边的总权重除以图中所有链接的总权重的两倍。
分层标签传播算法
LLP 算法的发展是基于标签传播(LP) [13]。后者首先为网络中的每个节点分配一个不同的社区,然后,它根据*邻节点中的主导社区迭代地修改相应的社区。在每次迭代中,对所有节点执行这个步骤,按照之前的随机顺序。
LLP 不仅考虑了邻居中的节点,还考虑了剩余网络中的节点[14]。迭代过程是一样的,区别在于它优化的值。在这种情况下,分配的社区是最大化:
被 ki 在给定节点的邻域中带有标签 λi 的节点的数量和 νi 在整个图中以相同方式标记的总数。
这种方法也已实现,通过其在整个网络中的常见存在,缓冲属于某个社区(在节点的邻域中)的节点的数量。
表 1 社区发现算法的时间复杂度。
基准
不同的社区发现算法以不同的方式划分同一个图。因此,了解哪些算法是最重要的。
获得这种洞察力的准确方法是对社区结构已知的网络进行划分。下一小节将介绍 GN 和 LFR 基准网络,以及 NMI,后者用于估计原始分区和检测到的分区之间的相似性。
社区发现算法不仅在准确性方面进行了测试,而且在速度方面也进行了测试。所有基准测试都重复了 10 次。平均值和相应的 95%置信区间包含在结果中。
格文-纽曼网络
在 GN 网络中,128 个节点被分成 4 组,每组正好有 32 个节点[16]。然后,由用户选择的混合参数定义来自不同社区的节点被连接的概率。该概率由下式给出:
每个节点都与另外 16 个节点相连(图 2)。由此实现的算法不仅允许混合参数变化,而且允许平均程度变化。这导致使用这些网络的基准测试数量增加。
图 2 GN 合成网络。恒定的节点数(N),可变的混合参数(μ)和平均节点度(k)。用 D3.js 和 SVG 表示。
兰奇内蒂-福图纳托-拉迪奇网络
LFR 基准网络(图 3) [17,16]试图更好地接*真实网络。这意味着他们不仅考虑具有系数ζ (5)的社区大小的幂律分布,而且考虑具有系数γ (6)的节点度的幂律分布:
图 3 LFR 合成网络。改变混合参数(μ)、节点数(N)和平均节点度(k),同时保持其余 2 个变量不变。用 D3.js 和 SVG 表示。
归一化互信息
使用归一化互信息(NMI) [18]测试社区发现算法的聚类质量。在项目中用 JavaScript 开发了一种算法,并在几个网络中进行了测试。它接收长度相同的 2 个数组的输入,并返回相应的 NMI:
NMI 依赖于互信息 I ,条件熵 H(Y|C) 以及带标签的 H(Y) 和聚类集 H(C) 的熵。
真实测试数据
使用实现的算法执行的测试数量越多,它们对于最大数量的网络正常工作的确定性就越高。这样,断开的网络(从亚马逊网络取样)、小型网络(扎卡里的空手道俱乐部)和系统网络(金黄色葡萄球菌MLST·SLV)也被额外考虑。然而,没有使用这些进行基准测试。
亚马逊网络
这个网络是抓取亚马逊网站后获得的[19]。每个节点代表商店中的一个给定产品,连接的节点对意味着它们经常一起被购买。原始网络包含 334 863 个节点和 925 872 条链路。测试中只使用了各个节点的前 5 000 条链路(图 4)。
图 4 从 5 000 个链接图中抽取的亚马逊产品联合购买网络样本。用 D3.js 和 SVG 表示。
扎卡里的空手道俱乐部网络
这是一个代表来自大学空手道俱乐部的 34 个人之间的 77 种关系的社交网络[20]。
节点 1 是讲师,34 是总裁(图 5)。深蓝色和浅蓝色的节点代表俱乐部内部的分裂,这是由于他们之间的冲突造成的。每个链接连接两个成员,在他们分开之前,他们经常在俱乐部外面见面。
图 5 扎卡里的空手道俱乐部网络。用 D3.js 和 SVG 表示。
葡萄球菌 金黄色葡萄球菌
为了测试群落发现算法在系统发育网络中的应用,使用了 MLST 的金黄色葡萄球菌等位基因谱数据库(图 6)【21】。MLST 概况包含关于七个基因座 ( arcC 、 aroE 、 glpF 、 gmk 、 pta 、 tpi 和 yqiL )的信息,并且在下载时,它有 5199 个 MLST 概况(ST)。通过将每个 ST 链接到其所有 slv 来创建图,并且最大的部分用于社区发现算法的基准。选择这个测试网络是基于这样一个事实,即它可以模拟与使用 cgMLST 或 wgMLST 配置文件创建的模式相似的模式,这些模式具有比 MLST 多得多的基因座。
图 6金黄色葡萄球菌 MLST SLV 网。用 D3.js 和 Canvas 表示。
可视化框架
在可视化应用程序中,用户可以选择使用 D3 或 Cytoscape JavaScript 库来可视化每个网络。对于第一个框架,有可能通过画布或 SVG 元素来可视化数据。所有的网络都是使用力引导的实现来绘制的。这种模式要求开发人员设置重力、排斥力或弹簧常数等功能,这些功能将影响网络的显示方式。根据这些参数,应该减少节点和链接重叠,以便获得图形的增强视图(图 7)。
图 7 扎卡里的空手道俱乐部网络用 D3.js Canvas(左上)、D3.js SVG(右上)和 Cytoscape.js(下图)表示。
关于基准绘图,使用了 D3.js。它在视觉表现、性能和网上可用实例数量方面的灵活性决定了这一选择。
结果
网络应用
为了便于分析和可视化之前算法执行后的结果,实现了一个 web 应用程序(mscthesis.herokuapp.com)。
它的后端是使用 Node.js 设计的,运行在一个 Heroku 服务器上,该服务器链接到一个 GitHub 存储库(github.com/warcraft12321/Thesis),其中包含所有与项目相关的实现和文档。使用芝诺多(【zenodo.org/badge/latestdoi/162063699】)将数字对象标识符(DOI)归属于这个存储库。在 Docker Hub(cloud . Docker . com/u/war craft 12321/repository/Docker/war craft 12321/thesis)可以获得该应用的图片。以下操作在云中严格执行:
- 生成 GN 和 LFR 基准网络。后者是使用 C++实现中的二进制文件生成的[22]。这是在从 NPM 导入一个模拟服务器命令行的包之后才有可能实现的;
- 真实的测试网络在云中对数据进行了适当的处理,这样数据就可以在前端发送和显示;
- 一旦鲁汶、信息图和 LLP 算法的执行不在用户的浏览器中进行,这可能会引起一些隐私问题。虽然,在用户端运行 Infomap 而仍然保持 web 应用程序在所有设备上的功能是不可行的;
- 应用程序和 NPM 之间的通信是在服务器中建立的,因此可以在应用程序中导入和绘制上传到 NPM 的每个包的统计数据;
- 最后,在云中运行算法后获得所有基准数据。
前端是静态和动态的。静态版本使用 HTML、CSS 和 JavaScript。动态执行由 Node.js 管理,它运行在服务器端(图 8)。
图 8 Web 应用。
社区发现算法
就准确性而言,对于弱混合网络(μ < 0.4),Louvain 优于所有其他网络。其次是对于μ < 0.3 的 Infomap,LP 和 LLP (γ = 0.5)或对于 0.3 ≤ μ ≤ 0.4 的 Infomap,LLP 和 LP (γ = 0.5)。通过增加μ,能够基于整个网络的全景来检测社区的 LLP 对于μ ≥ 0.5 始终是最有效的。比较 Louvain 和 Infomap 在μ ≥ 0.5 时的表现是差不多的。基于 95%置信区间,不可能说一个比另一个表现得更好。要强调的另一点是,Louvain 和 Infomap 非常敏感,因此,在μ ≈ 0.5 的网络中检测社区是不可靠的。LLP 和 LP 没有呈现出任何社区检测受到急剧影响的特定值。这些结论对 GN 和 LFR 网络都有效(图 9 和图 10)。
图 9 根据 GN 网络中的混合参数,每个算法的聚类质量:Louvain、Infomap、LP 和 LLP,其余特性如图 2 所示。
图 10 根据 LFR 网络中的混合参数,每个算法的聚类质量:Louvain、Infomap、LP 和 LLP,其余特性如图 3 所示。
由于只考虑了 LLP 的两个伽马值,因此需要进行更精确的分析,以检查是否有其他值可以获得更好的结果。
在 GN 网络(图 11)的情况下,可以在混合较少的网络中以更高的准确度检测社区。每当μ < 0.5. When μ ≥ 0.5, the NMI between the detected partition and the one in the original network is higher as long as we keep increasing γ. Another point to highlight is the possibility of detecting communities with higher precision in networks with higher μ using appropriate γ than in others with lower μ but with a non-optimal γ. This is valid for networks with μ >为 0.5 时,我们增加γ,性能就会下降(图 12)。
图 11 运行 LLP 后的 GN 网络(图 2)。当γ更接* 0 时,社区少、大、稀的网络粗结构凸显。随着γ的增长,细晶粒结构被揭开。社区变得越来越小,越来越密集。用 D3.js 和 SVG 表示。
图 12 LLP 算法在分辨率参数方面的精确度。对 GN 网络中的混合参数 0–1(蓝色-棕色)进行分析,其余属性如图 2 所示。
在 LFR 网络中,增加 gamma 总是会导致 NMI 下降(图 13)。
图 13 LLP 算法在分辨率参数方面的精确度。对 LFR 网络中的混合参数 0–1(蓝色-棕色)进行分析,其余属性如图 3 所示。
测试平均节点度的影响,以检查它是否影响每个算法识别社区的能力。
在 GN 网络的情况下,对于μ ≤ 0.5,平均度数的增加增强了卢万、Infomap、LP 和 LLP 区分社区的能力。对于μ > 0.5,NMI 聚类质量较低,因为平均节点度较高。假设不期望算法识别μ ≈ 1 的原始社区,这表明较高的平均度倾向于减少偶然的检测。这种观察可以应用于 GN 和 LFR 网络(图 14)。
图 14 LLP 算法在混合参数方面的精度。平均节点度为 15,20 和 25 的 GN 网络。其余的属性类似于图 2 中的属性。
在速度方面,Louvain 算法的表现明显优于其他任何算法。有助于其效率的一个重要属性是,它仅在模块化优化阶段(1)的每次迭代中计算模块化变化。在 Infomap 中,最小描述长度在优化步骤(2)的每次迭代结束时重新计算。由于这一计算密集型步骤,Infomap 在基准测试中表现最差。根据表 1,预计 Infomap 和所有其他文件之间的执行时间差异是对数的。由于实施步骤效率低下,这一目标未能实现。比较 LLP 和 LP,最快的是需要优化最简单方程的那个——LP(图 15)。尽管时间复杂度看起来是相同的,如表 1 中所预测的。同样,使用相同的表,预计 LLP 和 LP 的执行速度与鲁汶一样快。图 15 中观察到的微小差异可以用 LLP/线性规划实施中的一些非优化步骤来解释。
图 15 卢万、Infomap、LLP 和 LP 根据 LFR 网络的规模完成分析所用的时间。其余的属性类似于图 3 中的属性。
基准网络算法
之前生成了 GN 和 LFR 网络,因此可以执行之前的测试。在项目中实现了创建前者的算法。生成这种网络所需的时间随着平均节点度和混合参数呈指数增长(图 17)。在普通计算机中,对于高于 20 度的平均度数,执行它变得不可行。它的性能与 Fortunato 的实现进行了比较,Fortunato 的实现高度可扩展,允许在更短的时间内生成具有更多链路的网络(图 16)。已经证实,随着混合参数逐渐增加,网络生成时间*似线性增加,与项目中实施的网络相反。就像以前一样,生成具有更多边的网络需要额外的计算能力。
图 16 根据混合参数生成 GN 网络(使用 LFR 实现)所需的时间。在平均节点度为 15、20 和 25 的网络中进行的分析。其余的属性类似于图 2 中的属性。
图 17 根据混合参数生成 GN 网络(使用项目实施)所需的时间。在平均节点度为 15 和 20 的网络中进行的分析。其余的属性类似于图 2 中的属性。
其他测试在 LFR 网络中进行。针对网络的节点数量和混合参数测试了执行时间。在这两种情况下,验证了*似线性关系(图 18 和图 19)。在 GN 网络中,一旦每个社区和社区的元素数量固定,就不考虑节点的数量。尽管只分析了混合参数和节点数量,用户仍然可以选择调整节点最大程度、节点程度分布和社区大小分布的指数、每个社区的最大/最小节点数量、每个社区的重叠节点数量(在项目中不考虑覆盖)以及重叠节点的成员数量[22]。
图 18 根据节点数量生成 LFR 网络所需的时间。在平均节点度为 15、20 和 25 的网络中进行的分析。其余的属性类似于图 3 中的属性。
图 19 根据混合参数生成 LFR 网络所需的时间。在平均节点度为 15、20 和 25 的网络中进行的分析。其余的属性类似于图 3 中的属性。
每一个社区的发现,基准网络生成器,准确性措施和相关算法都在 NPM(表 2)。这样,它们可以用于任何特定于用户的应用程序。
表 2 项目中实现的算法在 NPM 可用。
可视化框架
D3.js (SVG)允许用户可视化 web 应用程序中使用的所有网络,并以可能的最高分辨率表示基准图(受用户设备中像素密度的限制)。从性能上来说,是第二快的。
D3.js (Canvas)是分析过的框架中最快的。然而,与之前的相比,网络中的节点和链路失去了分辨率。
当网络分析及其表示一起执行时,Cytoscape.js 是可取的。有相当多的算法,包括社区发现算法,可以促进图的研究。工作实例的缺乏和网络数据处理的缓慢使得 Cytoscape.js 的效率较低。金黄色葡萄球菌 SLV 网络和其他具有相似或更多节点/边的网络的表示溢出了 web 应用程序。
金黄色葡萄球菌
在从金黄色葡萄球菌的 MLST 数据集获得的 SLV 图的最大组成部分中执行了卢万、信息图和 LLP 算法。
使用三个模块性变化阈值:0.1、0.02 和 0.01 来执行 Louvain 算法。如简介中所预测的,可以验证快速实现高模块化分区(需要 2 次通过才能获得最终结果)。这个特性使得基于模块的算法速度更快。
使用信息图算法,考虑了几个最小描述长度阈值:0.1、0.02 和 0.01。对于所有值,从同一祖先传下来的每一个小的密集节点组都被分离到不同的社区中。因此,没有进一步审议。
LLP 算法考虑分辨率参数的三个值:0、0.5 和 1。与 Infomap 类似,它将网络划分为几个小而密集的社区。
根据 Louvain、Infomap 和 LLP 对 GN network 的基准分析(图 9 和图 10 ),可以预测,一旦 Louvain 在具有明确定义的社区的网络中运行,它将比其他网络表现得更好。在调整了 Louvain 的停止参数之后,使得所识别的社区是最相关的——来自属于同一社区的同一祖先的密集连接区域的节点,获得了最终的分区(图 20)。值得注意的是,一些类似于用正方形突出显示的聚类被算法细分。一种解释是不同亚群的菌株之间存在高重组率。
通过将生成的元数据文件上传到 PHYLOViZ Online,其中的节点被相应地标记为推断的群落,可以观察到具有相同群落的原始系统发生树。
图 20 在金黄色葡萄球菌 MLST SLV 网络的克隆复合体 0(如 PHYLOViZ 2 中所标识的)上运行卢万算法(考虑模块性变化的不同阈值)后获得的分区。用 D3.js 和 Canvas 表示。
结论
鲁汶、信息地图和 LLP 算法都是用 JavaScript 实现的。除非另有说明,以下结论适用于 GN 和 LFR 网络。就速度而言,卢万胜过所有其他人。就准确性而言,在有明确社区的网络中,卢万是最准确的。对于更高的混合,LLP 是最好的。与弱混合相反,在高度混合的 GN 网络中,增加分辨率参数是有利的。在 LFR 网络中,较高的分辨率降低了检测的准确性,而与混合参数无关。平均节点度的增加提高了分割精度,表明偶然检测被最小化。使用项目中开发的算法或 LFR 实现来生成具有更高混合度或平均度的 GN 网络在计算上更加密集。在金黄色葡萄球菌 MLST SLV 网络中,鲁汶在检测由同一个祖先进化而来的 7 组菌株的聚类中是最快最准确的。模块化变化阈值越低,检测越好。
除了三种社区发现算法之外,GN 基准网络生成器、NMI 和汉明距离算法也在 NPM 推出。web 应用程序托管在 Heroku 云平台中。可以从 Docker Hub 下载包含在本地机器上运行应用程序所需的所有模块的映像。GitHub 提供了该项目的所有实现和完整路线图。使用 Zenodo 将数字对象标识符(DOI)归属于这个存储库。
遇到的主要困难之一是在用户端运行社区发现算法。这个功能不会引起太多的隐私问题。必须在服务器上运行算法,这样应用程序才不会崩溃。在 Infomap 实现中,不可能达到其时间复杂度所预测的计算效率。拥有超过 10 000 个节点的网络的在线可视化是不可行的,即使使用表现出最佳性能的框架— D3.js(使用 Canvas 元素)。
在接下来的几个月里,这个项目中开发的一些工具将在 INSaFLU 中实施。用于显示系统进化树的新可视化框架,以及上传的元数据,将增强流感毒株进化路径的可追溯性。随时间动态变化的地理地图将允许用户精确获取每个样本的时间和位置,并在关键季节加强流感监测。交互式直方图显示了从流感病毒样品中获得的属于共有序列的每个核苷酸,突出显示了 SNPs,以及它们在指定毒株表型中的作用。新的流感监测动态报告将允许以最小化的方式可视化增加的数据量。
作为未来的改进,实现的算法可以在内存和速度方面进行优化。在更高效的实现中,网络和图表可视化可以运行得更快。之前的更新将使 web 应用程序加载更快,运行更流畅。用一组更具代表性的网络(涵盖更广泛的拓扑属性)对社区发现算法进行基准测试,将有可能以更高的确定性来推断任何社区发现算法是否在系统发育网络中始终表现更好。将项目中开发的社区发现功能整合到系统发育/面向监测的分析网络应用程序中,如 PHYLOViZ Online 或 INSaFLU,将是有益的。
论文 | 扩展摘要 | GitHub 知识库
参考
[1]“世界上最有价值的资源不再是石油,而是数据”《经济学人》,2017 年 5 月 6 日。【在线】。可用:https://www . economist . com/leaders/2017/05/06/the-worlds-most-valued-resource-is-again-oil-but-data。【2019 年 5 月 28 日获取】。
[2] A.-L. Barabási,《网络科学书》,[在线]。可用:http://networksciencebook.com。【2019 年 5 月 15 日获取】。
[3] H. G. S. Patil、A. N. Babu 和 P. S. Ramkumar,“生物医疗技术中的非侵入式数据采集和测量:概述”,载于通过技术集成最大化医疗服务提供和管理,IGI 全球,2016 年。
[4]“健康”,欧洲数据保护主管,[在线]。可用:https://edps . Europa . eu/data-protection/our-work/subjects/health _ en。【2019 年 6 月 9 日获取】。
[5]《2019 年全球健康十大威胁》,世界卫生组织,[在线]。可用:https://www . who . int/emergencies/ten-threats-to-global-health-in-2019。【2019 年 6 月 4 日获取】。
[6]“抗生素耐药性”,世界卫生组织,2018 年 2 月 15 日。【在线】。可用:https://www . who . int/en/news-room/fact-sheets/detail/antimicrobial-resistance。【2019 年 5 月 29 日访问】。
[7] Z. A. Memish、S. Venkatesh 和 A. M. Shibl,“旅行对抗生素耐药性国际传播的影响”,《国际抗微生物剂杂志》,,第 21 卷,第 2 期,第 135-142 页,2003 年。
[8]“全球十大死亡原因”,[在线]。可用:【https://www.theatlas.com/charts/HkLaDreuW. 【2019 年 5 月 12 日访问】。
[9]b . Ribeiro-gon alves,A. P. Francisco,C. Vaz,M. Ramirez 和 j . a . carri co,“PHYLOViZ Online:基于网络的可视化、系统发育推断、分析和共享最小生成树的工具”,核酸研究,第 44 卷,第 1 期,第 246–251 页,2016 年。
[10] Y. Motro 和 J. Moran-Gilad,“下一代测序在临床细菌学中的应用”,生物分子检测和定量,第 14 卷,第 1–6 页,2017。
[11] V. D. Blondel,J.-L. Guillaume,R. Lambiotte 和 E. Lefebvre,“大型网络中社区的快速展开”, J. Stat .机甲战士。(2008) P10008,2008 年第 12 页。
[12] M. Rosvall、D. Axelsson 和 C. T .博格斯特伦,“地图方程”,《欧洲物理杂志专题》,第 178 卷,第 1 期,第 13-23 页,2009 年。
[13] N. Raghavan,R. Albert 和 s .鸠摩罗王,“检测大规模网络中社区结构的*线性时间算法”,物理评论 E 25th 周年里程碑,第 76 卷第 3 期,2007 年。
[14] P. Boldi,M. Rosa,M. Santini 和 S. Vigna,“分层标签传播:用于压缩社交网络的多分辨率无坐标排序”,载于 WWW '11 第 20 届国际万维网会议论文集,2011 年。
[15]l . subelj,“聚类的标签传播”,载于网络聚类和块建模的进展,纽约,威利,2018 年。
[16] M .格文和 M. E. J .纽曼,“社会和生物网络中的社区结构”,《美国国家科学院院刊》,第 99 卷,第 12 期,第 7821-7826 页,2002 年。
[17] A. Lancichinetti,S. Fortunato 和 F. Radicchi,“测试社区检测算法的基准图”, Physical review。统计、非线性和软物质物理学。,第 78 卷,2008 年第 4 期。
[18] A. Lancichinetti,S. Fortunato 和 J. Kertesz,“检测复杂网络的重叠和分层社区结构”,新物理学杂志,第 11 卷,2009 年。
[19] J. Yang 和 J. Leskovec,“基于地面事实的网络社区定义和评估”,载于 2012 年 IEEE 数据挖掘国际会议(ICDM) 的会议录,2012 年。
[20] W. Zachary,“小群体中冲突和裂变的信息流模型”,《人类学研究杂志》,第 33 卷,1976 年。
[21]“金黄色葡萄球菌 MLST 数据库”,公共公报,2019 年 6 月 5 日。【在线】。可用:【https://pubmlst.org/saureus/. 【2019 年 6 月 5 日接入】。
[22]a . lanchi netti 和 S. Fortunato,“在具有重叠社区的有向和加权图上测试社区检测算法的基准”, Physical review。统计、非线性和软物质物理学。,2009 年第 80 卷。
防止数据帧的死亡
原文:https://towardsdatascience.com/preventing-the-death-of-the-dataframe-8bca1c0f83c8?source=collection_archive---------11-----------------------
数据帧系列
数据框架正在失去统计计算和机器学*的根基
数据框架产生于特定的需求,但是因为如此多不同的系统现在都自称为数据框架,这个术语几乎没有任何意义。为了保存数据框架,我们在最*的预印本[2]中基于原始数据模型对定义进行了形式化。
在我们进入细节之前,我想先概述一些我将在下面回答的问题:
- 什么是数据帧,它来自哪里?
- 数据帧和表格有什么不同?矩阵?
- 数据框架系统的爆炸是如何杀死数据框架的?
- 用户为什么要关心?
既不是表格也不是矩阵
最早的“dataframe”,最初是“data frame”,出现在贝尔实验室的 S 编程语言中。“数据框架”于 1990 年首次发布,并在约翰·m·钱伯斯和特雷弗·j·哈斯蒂于 1992 年撰写的《S 中的统计模型》一书的第三章中进行了详细描述[1]。在那一章中,Chambers 和 Hastie 多次提到数据帧有一个矩阵原点。
数据帧明显有矩阵的味道;特别是,在思考和计算时,变量可以被视为矩阵结构的列,而观察值可以被视为矩阵结构的行…
整本书要记住的基本概念是数据框架支持类似矩阵的计算 …
Chambers 和 Hastie 继续描述了一种类似于关系表的结构,但保留了它的矩阵属性。S 的开源版本 R 于 2000 年发布了第一个稳定版本,并继承了 dataframe。2009 年, pandas 发布,为 Python 带来了 R dataframe 语义。所有这些 dataframe 实现都来自单一来源,继承了相同的语义和数据模型。
在我们最*的 arxiv 预印本[2]中,我们描述了 dataframe 数据模型的第一个形式定义和第一组 dataframe 代数。这个 dataframe 数据模型保留了最初在 S 中定义的数据模型,并且代数支持在 S、R 或 pandas 中所做的一切。
数据框架数据模型
数据框架产生于将数据视为矩阵和表格的需要。单一类型矩阵限制性太强,而关系表要求数据首先定义为模式。在数据帧中,可以在运行时推断列的类型,不需要事先知道,也不需要列中的所有行都是相同的类型。数据框架实际上是关系系统、矩阵以及电子表格的组合。
数据帧支持来自线性代数(矩阵)、关系代数(表格)和一些电子表格公式的运算符。
与关系系统相比,数据帧有许多有趣和独特的属性:
- 一个直观的数据模型,包含了行和列的隐式排序,并像在矩阵中一样对称地对待它们;
- 支持跨越关系(例如,过滤、连接)、线性代数(例如,转置)和类似电子表格(例如,透视)运算符的运算符的 API
- 一种直观的查询语法,鼓励快速验证简单表达式、重用查询结果以及组合成复杂查询
- 一种类型系统,允许在一列中异构类型化的行,例如在一列的 int 中的字符串作为脏数据。
data frame 数据模型如下所示:
数据框架数据模型。
数据帧由数据的二维混合型数组(矩阵)、一组行标签、一组列标签和每列的类型(域)组成。每列的类型都是可选的,如果需要,系统可以在运行时在列上引入一个类型。这种惰性模式允许将数据帧视为关系表,而不会牺牲其他类似矩阵的数据帧属性,这对于重用关系数据库的优化非常有用。
与矩阵比较。所有矩阵都可以表示为数据帧(带空标签)。然而,并不是所有的数据帧都是矩阵,即使我们去掉它们的标签。矩阵在模式中是同构的,但是数据帧允许多种类型的模式。在特殊情况下,没有标签的数据帧是一个矩阵,但是所有的数据必须是同类类型,并且属于 int 或 float 或其他满足字段代数定义的类型。我们将这些矩阵 称为数据帧,它们对于数据帧和机器学*管道之间的关系尤为重要。
与关系表的比较。一个关系由一个声明的模式定义,一个关系有许多可能的实例——满足该模式的元组集。一个实例可以被认为是一个固定的关系表。数据帧有点像关系实例:它们代表一组固定的数据。然而,它们的模式可以是未指定的,因此由模式归纳函数基于它们的内容来归纳。这种灵活性对数据帧至关重要,并有助于解释为什么数据帧出现在 R 和 Python 等具有动态类型和运行时类型错误的语言中。
数据帧可以有效地以两种等效的方式来查看。从关系的角度来看,数据帧是有序的关系,具有指定的行、列和行的等价性,以及一个延迟诱导的模式。从线性代数的角度来看,数据帧是添加了行和列标签的异构矩阵。在预印本中,我们继续通过利用这两种观点来描述数据框架代数,但是我将把代数的细节留给感兴趣的人。
系统正在定义不存在的数据框架
许多系统对缩放数据帧采取的方法是移除难以缩放的属性,或者将数据帧等同于关系表。这种行为可能会带来重新定义数据帧的副作用。这与系统本身无关,系统通常都构建得很好,用户也很满意。然而,随着越来越多的系统继续被贴上“数据框架系统”的标签,我们面临着失去数据科学家工作流程中一个重要部分的风险。术语“数据框架”几乎没有任何意义。对于用户来说,仅仅根据术语来衡量自称为数据框架的系统的效用已经很困难了。
数据框架本质上是交互式的,它们是数据科学家工具箱的重要组成部分,因为我们仍然需要系统来进行人在回路中的数据清理和对结构不良的数据进行争论。也许更重要的是,数据框架在与机器学*工具链交互时也有明显的优势,因为数据框架的线性代数和统计计算根。在非数据框架系统中,您可能会发现自己在清理/争论之后存储数据,只是为了将数据加载回您最喜欢的机器学*库中。相反,如上定义的矩阵数据帧通常可以直接用于机器学*库。
为什么这很重要。保留来自 S、R 和 pandas 的数据帧属性和语义的正式定义很重要,因为这些系统所具有的属性使得数据帧有用且独特。隐式排序很重要,因为 dataframe 用户希望在检查查询结果时看到一致的顺序,并希望系统保持首选顺序。行/列对称性和其他类似矩阵的属性使得重塑数据和与机器学*工具的交互操作更加容易。惰性类型很有用,因为数据经常处于不同的清理阶段。在预印本中,我们基于原始实现的独特属性形式化了一个狭义的定义。
正如我们在预印本中所描述的,我们使用这个正式定义来指导一个更具可伸缩性的数据帧系统的实现。我们不改变数据帧的定义,而是试图理解它,在不改变语义的情况下扩展语义。这是我们所知的传统数据框架得以生存的唯一方式。
参考
[1]约翰·钱伯斯和特雷弗·哈斯蒂合编。年代的统计模型。第 251 卷。太平洋格罗夫,加利福尼亚州:沃兹沃斯&布鲁克斯/科尔高级图书&软件,1992 年。
[2] Petersohn,Devin 等人,“可伸缩数据框架系统”arXiv 预印本 arXiv:2001.00888 (2020)。
使用 Panoply 预览地球系统模型模拟
原文:https://towardsdatascience.com/previewing-a-model-simulation-with-panoply-f1559624132e?source=collection_archive---------78-----------------------
当处理整个地球系统的模拟时,模型输出通常由数十到数百千兆字节的数据和数百个独立变量组成。使用 python 脚本等传统方法处理这个问题可能是一个漫长的过程,尤其是如果您想要快速浏览或比较数据的话。这就是 Panoply 发挥作用的地方。本文描述了这是什么,以及如何在其中加载您自己的数据集。
照片由 NASA 在 Unsplash 拍摄
什么是 Panoply?
Panoply 是 NASA 的一个轻量级(~40 MB) netCDF 查看器,可用于快速了解地球模型模拟中的变量。Panoply 设计用于来自 Goddard 地球观测系统(GEOS) 的输出,但在使用 AerVis 代码转换为 netCDFs 后,也可用于 Met Office Unified Model .pp
输出。
装置
安装很简单,所需的文件很紧凑,可以在大多数操作系统上运行,不应该涉及任何管理权限。可以从以下页面找到下载链接:
[## 美国宇航局 GISS:全景 4 netCDF,HDF 和 GRIB 数据浏览器
panoply \PAN-uh-plee\,名词:1。壮观或令人印象深刻的阵列。...全景图地理参考和其他阵列来自…
www.giss.nasa.gov](https://www.giss.nasa.gov/tools/panoply/)
加载地块
要加载一个图,我们首先打开 Panoply(双击),我们得到一个文件浏览器窗口。使用它导航到您的数据目录并选择相关文件:
选择您的变量
接下来,我们将看到所选文件的内容。从这里,我们可以点击我们希望进一步探索的变量。
选择您的绘图风格
接下来,选择绘图样式。对于 AerVis 代码,这应该是地理参考经度数据。
查看情节
最后,我们创建绘图——从中我们可以使用下面的选项来更改时间步长和绘图属性。
比较不同的图/变量
最后,如果我们愿意,可以返回 netCDF 变量(上方的选择您的变量 部分)选择一个不同的值,并点击合并图按钮而不是进行创建。这在我们的可视化中创建了两个绘图数组,并允许一系列的组合选项。
结论
当前的方法涉及大量的数据混合和脚本来提供模型比较。现有的工具很冗长,要么需要花时间编写,要么非程序员无法使用。Panoply 提供了一种在任何计算机架构上探索 ESM 模型输出的交互式方法。因此,如果您有 netCDF 格式的全球数据,请尝试一下!
抽样资料
为了生成数据,可以从 github 库下载 GEOS Chem,尽管建议至少在 16 个内核上运行。然而,英国气象局模型需要安全检查和许可才能获得。
定价和营销分析——组织增长引擎的关键
原文:https://towardsdatascience.com/pricing-and-marketing-analytics-key-to-organization-growth-engine-d5032df4b54a?source=collection_archive---------24-----------------------
定价是推动组织收入并帮助确定盈利能力的关键因素之一。一些顶级组织,尤其是亚马逊,利用了基于客户需求和行为的动态定价。你可能已经注意到,像优步,Careem 这样的公司在高峰时间收取更高的价格,这些价格是根据管理供求的算法建模的。像沃尔玛这样的零售公司之所以取得成功,是因为他们每天都采取低价策略,向顾客提供低价;这帮助他们提高了销售额和客户忠诚度。如今,随着大数据技术的出现,许多企业正在利用数据的力量来优化定价决策。即使价格上涨 1%,也能使组织的运营利润提高 10%。
因此,定价在一个组织的发展中起着关键作用,并帮助他们实现四个主要目标:
图 1:定价的四个主要目标(图片由作者提供)
这篇文章将讨论不同的定价策略,尤其将详细讨论三种重要的定价技术。所有这些技术对营销人员、业务分析师和数据科学家都很重要。
1.奶油/撇奶油
图 2:价格撇除策略从溢价开始(图片由作者提供)
这种定价策略包括设定初始溢价,预期随着竞争对手的进入价格会降低。这里的目标是在需求很高,并且没有竞争对手介入的情况下,获得尽可能多的收入。
示例:
最新的 iPhone/iPad/Mac
苹果在开始时通常会保持很高的价格。
图 3:由于这三个因素,苹果在开始时通常保持很高的价格。(图片由作者提供)
首先,苹果拥有庞大的客户群;鉴于其品牌,许多人认为苹果的产品极具吸引力。
高初始价格意味着其产品的质量。
苹果预计其销量将非常高,因此未来降低价格对其整体销量影响很小或没有影响。
请注意,当产品是创新的或豪华的时,这通常很有效。
2.渗透定价
图 4:渗透定价策略从低价开始(图片由作者提供)
这种定价通常被市场中的后来者使用,以便他们可以通过在开始时设定较低的价格来从竞争对手那里吸引客户。
智能手机市场
正如我们已经看到的例子,苹果收取非常高的价格/撇除价格。另一方面,三星以低价为工具,利用渗透定价来吸引顾客。
苹果仍然向小市场销售昂贵的手机,并能够在消费者中建立品牌忠诚度,而三星则向更广泛的客户群销售大量手机。
图 5:渗透定价策略与价格撇除策略(图片由作者提供)
3.日常低价
图 6:https://en . Wikipedia . org/wiki/daily _ low _ price #/media/File:EDLP _ 1。JPG
沃尔马特广告
这种策略包括对产品设定持续的低价,而不必等待销售活动。沃尔玛获得了巨大的成功,因为每天的低价帮助它建立了提供低价的声誉。如今,该公司拥有 8500 多家门店,为超过 2 亿名客户提供服务。虽然这种策略导致低利润,但沃尔玛能够从其巨大的销售额中获得可观的利润。
5.成本加成定价
对于大多数零售商来说,这是一种非常常见的定价技巧,在这种情况下,销售价格是由成本和成本之外的百分比决定的。
第一步:确定固定成本和可变成本
固定成本:无论你做不做生意,这个成本都保持不变。例如月租金。
可变成本:这是原材料、劳动力或任何其他与每单位产品或服务相关的价格。这随输出水平而变化。
第二步:确定单位成本
单位成本包括公司生产一单位产品或服务的总成本。这包括固定成本和可变成本。
(图片由作者提供)
第三步:确定加价
(图片由作者提供)
因此,我们将收取 8.75 美元/台。
6.目标回报定价
这种定价模式根据投资者希望从投资于公司的资本中获得的收益来定价。从上面的表格中,我们可以看到投资者期望 20%的投资回报。
(图片由作者提供)
7.需求定价
既然我们已经看到了包括传统定价策略在内的不同定价策略,现在让我们将注意力转向动态或基于需求的定价方法。你可能每次访问都看到不同的电商网站收取不同的价格。另一个例子包括航空业;7 月份买的票和 1 月份买的票价格不一样。为什么?这是因为需求;更高的需求推高了价格。7 月份的假期可能是提振 7 月份需求的因素之一。
另一个例子包括酒店业,周末预订的房间将比工作日期间租赁的相同房间更贵。此外,你可能已经注意到,booking.com 价格每天都在根据需求而变化。
为了更好地理解这个概念,让我们来说明需求曲线的概念。
图 7:需求曲线说明了需求量和价格之间的反比关系(图片由作者提供)
这条典型的需求曲线说明了需求量和价格之间的反比关系。随着价格上涨,需求量下降。现在的问题是价格的变化会对需求量产生多大的影响?为此,经济学家计算了所谓的需求价格弹性。
需求数量的变化对价格变化的反应就是所谓的需求价格弹性。在这里,我们将探讨需求的价格弹性以及现实世界的应用。
图 8:https://sites . Google . com/site/frameworks mkt 622/home/5-创造价值-主张/定价/价格-需求弹性
PED=%需求数量变化/ %价格变化
解释弹性
当价格的微小变化导致需求量的较大变化时,需求被认为是有弹性的。这是强替代产品的情况,价格的微小变化可能导致客户购买替代产品。
当价格的变化引起需求的巨大变化时,需求被认为是无弹性的。
图 9:【https://hbr.org/2015/08/a-refresher-on-price-elasticity
说明最优定价的简单示例
图 10a:最优定价(作者图片)
请注意,在 40 美元,我们赚取最大利润。在 50 美元时,需求量减少,导致总利润减少。这里的重点是解释弹性和数量需求根据价格变化的方式如何影响我们的整体收入和利润。
图 10b:最优定价(作者图片)
非常欢迎你计算需求的价格弹性
企业如何利用价格弹性?
这是营销经理/分析师最重要的指标之一。根据《哈佛商业评论》中提到的一次采访,营销人员的目标是将他或她的产品从相对弹性转变为非弹性,这是通过创造差异化产品、品牌形象和忠诚度来实现的。目标是提高支付意愿,不管价格如何。
根据麦肯锡的见解,动态定价应该包括五个模块。
- 长尾模块:这有助于通过识别相似的产品来设定初始价格或介绍价格。根据其中一篇文章,拥有 100 万种产品的美国零售商通过收集 10 万种最畅销产品的丰富数据集建立了长尾模块,包括竞争对手的价格、客户行为和产品属性。这些产品然后被智能地匹配以确定价格。这个试点帮助零售商增加了 3%的收入。
- 弹性模块:这已经在上面说明了。这可以通过使用时间序列方法和回归模型来实现,这些方法和模型考虑了季节性、同类相食和竞争因素。
- 键值商品模块:这些商品的价格比其他商品更容易被消费者记住。这对于不销售产品的经销商尤为重要。例如食品杂货公司。在这种情况下,公司可以建立一个模型来评估每个项目对消费者价格感知的重要性。
- 竞争响应模块:利用数据科学和机器学*模型的力量,公司可以实时利用竞争对手的定价数据以及这些价格对客户的影响。
- 全渠道模块:该模块确保一个项目或产品的价格在所有渠道都得到反映。这里的公司可以利用价格歧视策略。
定价评估
既然我们已经看到了不同的定价策略,对一个组织来说,评估其产品价格也是非常重要的,因为投资者/股东对 ROI、盈利能力、IRR 和现金流感兴趣。我们可以用不同的方法来评估价格
- 收支平衡法
在这种方法中,我们计算要达到收支平衡需要销售的单位数量。这考虑了固定成本、单位成本和价格。换句话说,盈亏平衡点是一种产品的总收入等于总支出的点。
2。NPV 资本预算
资本预算有许多不同的方法,包括净现值、内部收益率、回收期、盈利能力指数。
净现值(NPV)考虑了资金的账户时间价值,并将未来现金流转化为今天的美元或货币。
参考
[1]https://small business . chron . com/penetration-pricing-examples-18365 . html
[2]https://www.marketing91.com/penetration-pricing/
[3]https://doc player . net/36830320-Chapter-8-price-analytics . html
https://research.aimultiple.com/dynamic-pricing/
https://hbr.org/2015/08/a-refresher-on-price-elasticity
http://investopedia.com/
[7]https://www . McKinsey . com/industries/retail/our-insights/how-retailers-can-drive-profitable-growth-through-dynamic-pricing
Mercari 中的定价对象—机器学*和深度学*视角
原文:https://towardsdatascience.com/pricing-objects-in-mercari-machine-learning-deep-learning-perspectives-6aa80514b2c8?source=collection_archive---------46-----------------------
作为开创性自我案例研究的一部分,解决 Kaggle 的 Mercari 数据集的基于 NLP 的回归的补充工作——应用人工智能课程
这是我的第一篇博客,我很高兴分享我在解密 Kaggle 比赛的解决方案时的机器学*和深度学*经验。尽管这是提交给 Kaggle 的一篇迟到的文章,但我在分析过程中的学*之旅也非常直观、有趣且富有挑战性。希望这个博客最终能给读者一些有用的学*资料。
目录
- 商业问题
- 误差度量
- 机器学*和深度学*在我们问题上的应用
- 数据来源
- 探索性数据分析— EDA
- 现有方法
- 数据准备
- 模型解释
- 结果
- 我改进 RMSLE 的尝试
- 未来的工作
- LinkedIn 和 GitHub 知识库
- 参考
图片来源:https://unsplash.com/photos/1M4wYTqVD4o
1.商业问题
Mercari,Inc .是一家在日本和美国运营的电子商务公司,其主要产品是 Mercari marketplace 应用程序。人们可以使用智能手机轻松销售或购买商品。该应用程序的用户可以在列出商品时自由选择价格。然而,这里存在更高的风险,因为如果价目表与市场价格相比过高或过低,消费者和顾客都会不知所措。上述问题的解决方案是自动推荐商品价格,因此,最大的社区购物应用程序希望向其卖家提供价格建议。
眼前的问题是预测任何给定产品的价格,这说明这是一个回归问题。我们在训练数据中的特征是物品的训练标识、名称、物品条件标识、类别名称、品牌名称、价格、运输、物品描述。除了作为我们目标变量的价格之外,我们在测试数据中拥有所有其他特征。这些特征不仅是分类的和数字的,而且也是卖方提供的商品的文本描述。例如,女性配饰产品的文字描述如下:
作者图片
我们可以看到两者售价不同;第一个 16 美元,第二个 9 美元。
因此,这里的挑战是,我们需要建立一个模型,该模型应该根据上图所示的描述,以及产品名称、类别名称、品牌名称、物品状况等来预测产品的正确价格。
2.误差度量
这个问题的误差度量是均方根对数误差(RMSLE)。请参考这篇博客了解更多关于该指标的信息。下图显示了度量计算的公式:
图片来源:https://cs 230 . Stanford . edu/files _ winter _ 2018/projects/6940447 . pdf
计算 RMSLE 的代码如下所示:
计算 RMSLE 的函数
3.机器学*和深度学*在我们问题上的应用
在这个人工智能(AI)的时代,我们想到 AI 的那一刻,接下来的两个流行语就是机器学*和深度学*。我们发现人工智能无处不在,事实上它们是人类生活的一部分。无论是通勤(如出租车预订),医疗诊断,个人助理(如 Siri,Alexa),欺诈检测,犯罪检测,在线客户支持,产品推荐,无人驾驶汽车,等等。有了尖端的机器学*和深度学*算法,任何类型的预测问题都可以解决。
我们的问题是独特的,因为它是基于 NLP(自然语言处理)的回归任务。NLP 中的第一步是将文本表示为数字,即将文本转换为数字向量表示,以构建回归变量。
作者图片
解决价格预测问题的一种方法是利用 TF-IDF、BoW 等矢量化技术,并构建将由经典机器学*算法(例如简单线性回归器、基于树的回归器等)使用的固定大小的稀疏向量表示。).另一种方式是使用深度 NLP 架构(例如 CNN、LSTM、GRU 或它们的组合),这些架构可以自己学*特征,并且需要来自嵌入的密集向量。在当前的分析中,我们正在研究这两种方法。
4.数据来源
本次分析的数据集来自 Kaggle,这是一个面向数据科学家的流行在线社区或数据平台。
图片来源:【https://www.kaggle.com/c/mercari-price-suggestion-challenge
理解数据
训练集包含超过 140 万个产品,而阶段 2 测试集包含超过 340 万个产品。
列出训练/测试数据中的字段名:
- train_id 或 test_id —列表的唯一 id
- 名称 —卖方提供的产品名称。请注意,为了避免数据泄露,该字段中的价格被删除并表示为[rm]
- item _ condition _ id—此处卖方提供物品条件
- 【类别名称】 —每件商品的类别列表
- brand_name —每件商品所属的对应品牌
- 价格 —这是我们的目标变量,以美元表示(test.tsv 中不存在该列)
- 运费 — 1,如果运费由卖家支付,0,否则
- item _ description—此处给出了每个项目的描述,价格被移除并表示为[rm]
下面显示的数据一瞥:
列车样本数据的屏幕截图
5.探索性数据分析— EDA
EDA 是数据科学过程中的一个重要步骤,是一种统计方法,通常使用可视化方法从数据集获得更多见解。在我们深入研究 EDA 之前,让我们快速浏览一下数据以了解更多信息。下面是检查空值的代码片段:
print(train.isnull().sum())
代码输出的屏幕截图
从上面的输出中,我们认识到有三列,即类别名称、品牌名称和项目描述包含空值。其中,品牌名称包含了大量缺失值(~632k)。列类别名称包含大约 6.3k 个空值,而项目描述只有 4 个空值。让我们稍后在创建模型时处理它们,现在我们逐个特性地深入研究 EDA。
5.1 类别名称的单变量分析
训练数据集中总共有 1287 个类别。下面显示的是计数的代码片段:
计数类别的代码
类别计数的输出
category_count 的曲线图如下所示:
上面的条形图显示了出现频率最高的 10 个类别。人们会注意到,女装是所有服装中最引人注目的。
每个类别名称由 3 个以'/'分隔的子类组成,并具有主类别/子类 1 /子类 2 名称。重要的是将它们分开,并作为新的特征包括进来,这将使我们的模型做出更好的预测。
拆分类别
在我们的分析中,我们使用下面的函数将每个 category_name 拆分为 main_category 、 sub_cat_1 、 sub_cat_2 。
用于拆分的效用函数
此外,这三列中每一列的类别数是使用下面的代码行计算的:
main_category_count_te = test['main_category'].value_counts()
sub_1_count_te = test['sub_cat_1'].value_counts()
sub_2_count_te = test['sub_cat_2'].value_counts()
上述分析表明,有 11 个主要类别,这些类别又分为 114 个子类别(子类别 1),这些子类别又被分配到列车数据中的 865 个特定类别(子类别 2)。绘制类别的代码如下所示:
绘图代码
绘图类别
拆分后该类别每列中前 10 项的条形图如下:
5.2 品牌名称的单变量分析
共有 4807 个独特品牌,其中出现频率最高的 10 个品牌如下图所示:
绘图代码在这里:
#https://www.datacamp.com/community/tutorials/categorical-data
sns.barplot(x=brand_count[:10].values, y=brand_count[:10].index)
plt.title('Frequency Distribution of top 10 brand names')
plt.xlabel('Counts', fontsize=12)
plt.show()
值得注意的是,粉红色和耐克品牌,其次是维多利亚的秘密,是占据领先地位的品牌。
5.3 价格的单变量分析
由于价格是数字,我们使用 describe()函数来感知统计汇总。下面是代码片段:
train.price.describe()
汇总统计数据
describe()函数解释了任何产品的最高价格是$2009,最低价格是 0。还注意到,75%的产品价格范围出现在 29 美元以下,50%的产品价格低于 17 美元,而 25%的产品价格低于 10 美元。平均价格范围是 26.7 美元。
价格变量的分布
绘制目标的分布图
plt.title("Distribution of Price variable")
plt.xlabel("Price(USD)")
plt.ylabel("No. of products")
plt.hist(train['price'],bins=30)
从上图可以明显看出,价格特征遵循右偏分布。正如这里讨论的,由于分布另一侧的点,偏斜分布会导致高均方差(MSE)值,如果数据是正态分布,MSE 是有限的。因此,价格特性的对数转换是不可避免的,如果数据是正态分布的,模型也可以表现得更好。这是通过以下代码片段完成的:
日志转换代码
下面显示的是对数变换后的价格变量的曲线图。
5.4 项目 _ 描述的单变量分析
我们绘制单词 cloud 是为了了解描述中的流行单词。对应的代码片段与下面显示的图对应:
单词 cloud 的代码
从上面的词云中,人们可以注意到在我们的 item_description 中频繁出现的词。
描述字数
单独的文本描述可能是该问题的重要特征(参考),即对于机器学*模型,并且将有助于深度学*模型的嵌入过程。
用于计算描述中字数的代码
为了进一步研究该特性,我们绘制了如下所示的箱线图和分布图以及代码:
箱形图
sns.boxplot(train['description_wc'],orient='v')
plt.title("Box plot of description word count")
plt.xlabel("item_description")
plt.ylabel("No. of words")
plt.show()
人们可以注意到大多数描述包含大约不到 40 个单词。
密度图
plt.figure(figsize=(10,3))
sns.distplot(train['description_wc'], hist=False)
plt.title('Plot of the word count for each item description')
plt.xlabel('Number of words in each description')
plt.show()
描述字数的密度图是右偏的。
汇总统计数据
汇总统计表明 item_description 的最小长度为 1,而最大长度为 245。平均长度约为 25 个单词。越少的描述越长,而它们中的大多数包含不到 40 个单词,正如我们在方框图中看到的。
5.5 项目 _ 条件 _ 标识的单变量分析
有序分类特征 item_condition_id 的范围是 1 到 5。普通性是条件 1 的项目是“最好的”,条件 5 的项目是“最差的”(基于这个参考)。 item_condition_id 的条形图如下所示:
正如上面的柱状图所示,大多数待售商品状况良好。因此,条件 1 的项目较高,其次是条件 3 和条件 2,而条件 4 和条件 5 的项目较低。
5.6 双变量分析
了解目标变量与其他特征的关联类型将有助于特征工程。因此,价格变量与其他两个变量进行比较。
价格与运输
和往常一样,绘图会帮助我们更好地理解事物。代码和图形如下所示:
箱线图的代码
人们可以观察到,当物品的价格较高时,卖家支付运费,反之亦然。
价格与描述长度
这两个变量的绘图和我们上面做的一样。
plt.scatter(train['description_wc'],train['price'],alpha=0.4)
plt.title("Price Vs Description length")
plt.xlabel("Description length")
plt.ylabel("Price(USD)")
plt.show()
值得注意的是,描述长度较短的商品往往比描述长度较长的商品价格更高。
6.现有方法
有几个内核、博客和论文使用简单的机器学*或深度学*方法做出了解决方案。我们将向他们中的一些人简要介绍:
MLP
Pawel 和 Konstantin 凭借他们惊人的解决方案赢得了这场竞赛。他们使用了一种基于前馈神经网络的方法,即一种对稀疏特征有效的简单 MLP。执行的一些预处理技巧包括对分类列进行一次性编码,使用标准 PorterStemmer、BoW-1,2-grams(有/没有 TF-IDF)对文本进行词干分析,将不同的字段(如 name、brand name 和 item_description )连接成一个字段。他们获得了 0.37 的优异成绩。
美国有线新闻网;卷积神经网络
在这项研究中,作者使用 CNN 架构和最大池分别对名称和项目描述进行矢量化。他使用预先训练的手套向量进行单词嵌入,嵌入是对姓名和项目 _ 描述的共享搜索。使用的一些有用的技巧是在最后一个完全连接的层和单词嵌入的平均池层之前跳过数字和低基数分类特征的连接。作者从单一深度学*模型(链接)取得了 0.41 的惊人成绩。
LGBM +山脊
在这里,作者应用了一个名为 LightGBM 的基于树的梯度推进框架,以实现更快的训练和更高的效率。该研究还使用了一个简单、快速的岭模型进行训练。一些特征技术包括:使用 CountVectorizer 对 name 和 category_name 列进行矢量化,使用 TfidfVectorizer 对 item_description 进行矢量化,使用虚拟变量对 item_condition_id 和 shipping_id 进行创建,使用 LabelBinarizer 对 brand_name 进行矢量化。两个模型合二为一后,作者取得了 0.44 的成绩。(链接)
GRU + 2 山脊
在这项研究中,作者使用 RNN、里奇和里奇 CV 构建了一个关联模型,其均方根误差约为 0.427。这里应用的一些有用的技巧包括对文本特征使用 GRU 层,对 RNN 训练使用预定的学*衰减,使用具有 2 个时期的小批量大小,以及对脊模型使用超过 300k 的特征(链接)。
7.数据准备
数据清理
根据这份参考资料,Mercari 网站上的最低价格为 3 美元。因此,在我们的训练数据中,我们保留价格高于$3 的项目。下面显示的是相同的代码片段:
#https://www.kaggle.com/valkling/mercari-rnn-2ridge-models-with-notes-0-42755
train = train.drop(train[(train.price < 3.0)].index)
处理空值/缺失值
从 EDA 中,我们了解到 3 列即。、类别名称、品牌名称、和项目描述为空值。因此,我们用适当的值替换它们。我们用下面的函数来做这件事:
处理缺失值的代码
列车测试分离
在我们的分析中,价格字段是目标变量“y”。根据误差函数评估我们的回归模型的适合度是很重要的,我们需要观察“y”并预测“y”。不幸的是,我们没有观察到的目标值来评估我们的模型。因此,训练数据被分成训练集和测试集。
对于基本的线性回归模型,测试集由 10%的数据组成,对于深度学*模型,测试集包括总数据的 20%。
缩放目标
使用 sklearn.preprocessing 中的 StandardScaler 函数对目标变量进行标准化,如下所示:
缩放目标变量
因为我们的目标变量是使用上述函数标准化的,所以在我们计算误差度量之前,将预测值按比例缩小(逆变换)是很重要的。这是通过使用以下函数来完成的:
8.模型解释
让我们详细了解一下机器学*和深度学*管道。
8.1 机器学*管道
作者图片
在此分析中,自然语言处理概念如 BoW、TFIDF 等。用于对机器学*回归模型的文本进行矢量化。
特征构造
在执行 EDA 时,我们添加了四个新特性,即通过拆分列类别生成三个新列,并添加来自 item_description 的文本描述的字数。此外,我们根据姓名文本的长度再创建一列。所以,我们有了五个新特性。
我们的数据集由分类特征、数字特征和文本特征组成。必须对分类特征进行编码,并对文本特征进行矢量化,以创建模型使用的特征矩阵。
分类特征编码
我们使用 sci-kit 中的 CountVectorizer 函数对分类特征进行一次性编码,如 category_name 、 main_category 、 sub_cat_1 、 sub_cat_2 、 brand_name ,并使用 get_dummies()函数对 shipping_id 和 item_condition_id 进行编码。下面是相同的代码:
一键编码的代码
文本特征矢量化
我们分别使用 BoW(一元和二元)和 TFIDF(一元、二元和三元)编码文本特征 name 和 item_description 。其功能如下所示:
矢量化代码
下面给出了使用上述函数的代码:
特征矩阵
通过将所有编码特征(分类特征和文本特征)与两个数字特征(即文本描述和姓名的字数)连接起来,生成最终的矩阵。以下代码供参考:
产生的最终矩阵由超过 206k 个特征组成。的确,这是一个很大的特点。
最终矩阵形状的屏幕截图
首次切割模型
为这个问题选择一个合适的算法可能是一项艰巨的任务,尤其是对初学者来说。
图片来源:https://unsplash.com/photos/bmrGgKXz_xU
我们学*根据数据维度、线性、训练时间、问题类型等选择算法。正如这里讨论的。
在我们的分析中,我们首先使用简单的线性模型进行实验,如线性回归、支持向量回归机,对于这两个模型,我们都选择 sci-kit learn 中的 SGDRegressor。在此之后,我们训练岭回归。
我们使用 GridSearchCV 通过以下函数对所有模型的参数进行超参数调整:
线性回归
线性回归旨在减少预测和实际数据之间的误差。我们使用具有“平方损失”的 SGDregressor 和针对不同 alphas 的超参数调整来训练简单的线性回归。下面显示的代码是相同的:
根据我们的测试数据,这个简单的模型得出的最佳 alpha = 0.001 的 RMSLE 为 0.513。
支持向量回归机:
支持向量回归机(SVR)旨在预测偏离实际数据不超过ε的函数(参见)。我们使用具有“epsilon_insensitive”的 SGDRegressor 作为 alphas 的损失和超参数调谐来训练 SVR。在我们的测试数据中,当 alpha = 0.0001 时,该模型产生的 RMSLE 为 0.632。在我们的例子中,简单的线性回归比支持向量机表现得好得多。SVR 的代码如下:
里脊回归
岭回归是线性回归的*亲,具有由 L2 范数给出的一些正则化以防止过度拟合。我们在线性模型下使用 sci-kit learn Ridge 库获得了良好的拟合,对于 alpha = 6.0,RMSLE 为 0.490。下面是具有超参数调整的岭模型的代码:
里奇夫
它是一种交叉验证估计器,可以自动选择最佳超参数(这里指的是:)。换句话说,带有内置交叉验证的岭回归。正如在这个内核中所述,对于我们的问题,它比 Ridge 表现得更好,我们构建了 RidgeCV 模型,在我们的测试数据上,它为 alpha 6.0 产生了 0.442 的 RMSLE。相同的代码如下所示:
我们还可以观察到 RidgeCV 在我们的第一次切割模型中表现更好。为了进一步提高分数,我们正在探索使用 RNN 解决这个问题的神经网络。
8.2 深度学*管道
递归神经网络(RNN)擅长处理序列数据信息(更多信息请参见参考)。我们使用门控递归单元(GRUs)来构建使用神经网络的回归器,这是一种训练速度更快的新型 RNN。从 GRU,我们获得嵌入后的名称、item_description 列的文本特征向量,对于其他分类字段,我们使用嵌入,然后进行展平。所有这些共同构成了我们深度学*模型的 80 维特征向量。
作者图片
嵌入
深度学*(DL)管道的数据准备遵循与 ML 管道相同的程序,除了训练-测试分离。这里我们认为 20%的训练数据是测试数据。如前所述,DL 管道需要密集的向量,而神经网络嵌入是将我们的离散变量表示为连续向量的有效手段(参见)。
标记化和填充
嵌入层要求输入为整数编码(参考)。因此,我们使用 Tokenizer API 对文本数据进行编码,下面是相同的代码片段:
标记化后的示例描述数据截图如下所示:
标记化后描述文本的屏幕截图
在标记化之后,我们填充序列。名称和描述文本长度不同,Keras 倾向于输入序列长度相同。我们计算超出特定单词范围的数据点的百分比,以确定填充长度。
下面显示的代码用于选择描述文本的填充长度:
print("% of sequence containing len > 160 is")
len(X_train[X_train.wc_desc > 160])/X_train.shape[0]*100
上面代码的输出
从上图中我们看到长度超过 160 的点的百分比是 0.7,这是< 1%. Hence we pad description text with 160. Similarly, we calculate for the 名称列,我们选择 10。相应的代码片段如下所示:
print("% of name containing len > 10 is")
len(X_train[X_train.wc_name > 10])/X_train.shape[0]*100
以上代码的输出
此外,我们根据排名对分类变量进行编码,代码片段如下所示:
注意:所有的嵌入都是和模型一起学*的。
整个数据准备管道以及编码、标记化和填充由以下函数执行:
网络体系结构
当前分析的网络设计受这个内核的启发。此外,我们在这个框架中试验了额外的丢弃层和批量规范化层。下面是构建我们的网络的代码片段:
看看我们下面的网络:
GRU 神经网络
深度学*模型
总共训练了四个模型,它们的退出率和学*率不同。每个网络由四个退出层组成,对于这些层中的每一层,我们对所有模型尝试不同的退出率(详见结果)。
培养
对于训练模型 1 和模型 2,我们使用具有默认学*速率的 Adam 优化器。此外,这些模型用两倍的批量大小训练 3 个时期。模型 1 和模型 2 的测试数据的均方根误差分别为 0.436 和 0.441。模型训练如下图所示:
具有默认学*率的模型 2 训练
模型 3 和 4 使用 Adam optimizer 以预定的学*速率进行训练。共 3 个时期,批量为 1024。对于时段 1 和 2,学*率是 0.005,对于最后一个时段,我们将其降低到 0.001。模型 4 的培训如下所示:
模式 4 以预定的学*率进行培训
模型平均集合
模型平均是一种集成学*技术,用于减少神经网络中的高方差。在目前的分析中,我们集成了在不同退出正则化条件下训练的模型(参考)。每个模型大约需要 30 到 35 分钟来训练。考虑到训练时间,我们只包括两个模型进行组合。因此,在四个模型中,创建了两个系综,即,一个来自实现 RMSLE 0.433 的模型 1 & 2,另一个来自 RMSLE 0.429 的模型 3 & 4
组装模型 1 和 2 的代码如下所示:
我们观察到来自模型 3 & 4 的集合在我们的训练测试分割数据中表现优于。
最终模型
为了获得 Kaggle 的最终分数,我们现在在 Kaggle 内核中训练。我们建立了两个与模型 3 和 4 相同的模型用于组装。下面展示的是在 Kaggle 接受训练的模特的截图:
这两个模型的模型平均组合在包含约 340 万个产品的最终测试数据上的 Kaggle 公开评分中得到 0.428 分。因此,我们获得了排名榜前 10%的分数。
排行榜截图
9.结果
下面显示的是模型输出的摘要屏幕截图:
机器学*流水线的输出:
深度学*管道输出快照:
4 个模型的输出
组装输出截图:
2 个系综的输出
Kaggle 投稿评分:
10.我改进 RMSLE 的尝试
一般来说,Kaggle 的竞争对手的核心是说教的来源。本分析的灵感来自于这个、这个以及一些来自于赢家的解决方案。提高我们分数的策略如下:
- 包含停用词进行分析:这个问题的一个关键是,删除文本描述/名称中的停用词会影响 RMSLE 分数。停用词的保留提高了分数。
- 考虑更多的文本特征用于建模:总共得到 206k 个特征,其中包括仅来自文本数据的 200k 个特征。在这个问题中,更加重视文本信息可以提高分数。
- 二元语法和三元语法:在自然语言处理中,*惯上包括二元语法、三元语法等 n 元语法。如果我们打算在矢量化过程中添加一些语义。在我们的研究中,我们使用单词包对名称应用一元和二元语法,使用 TFIDF 对项目描述应用一元、二元和三元语法。
- 根据价格 过滤数据:Mercari 不允许发布低于 3 美元的商品。因此,那些产品价格低于$3 的行将是错误点。移除它们将有助于模型更好地运行。
- 小批量模型训练&少时段:使用 1024 的批量和预定的学*提高了分数
- 集成两个神经网络模型:这种策略是当前研究独有的,它将分数推高到了排行榜上。我们通过训练两个神经网络模型并构建它们的集成来执行我们的预测分析。
11.未来的工作
可以通过探索以下选项来提高分数:
- 使用多层感知器,因为它是解决这个问题的流行方法
- 使用 CNN 结合 RNN 处理文本数据
- 添加更多的 GRU 层或进一步微调
这些是我们随后想要探索的一些可能性。
12.LinkedIn 和 GitHub 知识库
这是我在 LinkedIn 上的简介。请参考我的 GitHub 库查看完整代码。
13.参考
https://github . com/pjankiewicz/mercari solution/blob/master/presentation/build/yandex . pdf
[## 带注释的 RNN+2 桥模型(~0.42755)
使用 Kaggle 笔记本探索和运行机器学*代码|使用来自 Mercari 价格建议挑战赛的数据
www.kaggle.com](https://www.kaggle.com/valkling/mercari-rnn-2ridge-models-with-notes-0-42755) [## Mercari 价格建议挑战
这是我在 Kaggle 环境中的第一次数据科学体验。虽然挑战本身很有趣,经历也…
medium.com](https://medium.com/analytics-vidhya/mercari-price-suggestion-challenge-66500ac1f88a) [## Mercari 价格建议挑战——机器学*回归案例研究
这是我的第一个媒介故事。希望你读它的时候开心,就像我喜欢为观众写它一样
medium.com](https://medium.com/analytics-vidhya/mercari-price-suggestion-challenge-a-machine-learning-regression-case-study-9d776d5293a0) [## 深度学*神经网络的集成学*方法——机器学*掌握
如何通过组合多个模型的预测来提高性能?深度学*神经网络是非线性的…
machinelearningmastery.com](https://machinelearningmastery.com/ensemble-methods-for-deep-learning-neural-networks/) [## 如何在 Keras 中开发一套深度学*模型——机器学*掌握
深度学*神经网络模型是高度灵活的非线性算法,能够学**乎无限数量的…
machinelearningmastery.com](https://machinelearningmastery.com/model-averaging-ensemble-for-deep-learning-neural-networks/) [## 我如何在使用 CNN 和 Tensorflow 的 Kaggle 的 Mercari 价格建议挑战中失去银牌
2018 年 1 月,我参加了一个名为 Mercari 价格建议的 Kaggle 比赛。比赛持续了三…
medium.com](https://medium.com/unstructured/how-i-lost-a-silver-medal-in-kaggles-mercari-price-suggestion-challenge-using-cnns-and-tensorflow-4013660fcded) [## 应用课程
应用机器学*课程 GATE CS 混合课程面试准备课程 AI Workshop AI 案例研究
www.appliedaicourse.com](https://www.appliedaicourse.com/course/11/Applied-Machine-learning-course)
危机期间的定价优化:数据是关键
原文:https://towardsdatascience.com/pricing-optimization-during-the-crisis-data-is-key-a4d4f6c678b?source=collection_archive---------47-----------------------
疫情引发的危机给客户需求带来了前所未有的压力。如果没有受到这些环境的巨大影响,组织必须相应地快速适应市场变化,以维持甚至发展业务并超越竞争对手。因此,优化他们的定价策略对于驾驭这种新常态至关重要。
然而,即使在平时,也很少有公司在第一次尝试时就能正确定价,第二次、第三次或第四次尝试时也是如此。根据贝恩公司的一项研究,高达 85%的 B2B 公司“在定价上有很大的提升空间”但是,即使一家公司碰巧接*目标,继续向最优定价前进也会产生巨大的差异。
我最*一直在与来自顶级实验室的同事一起研究这个特定的主题,特别是他的创始人 Manu Carricano ,我们一起编写了 这份白皮书 ,并举办了一场 网络研讨会 ,分享了我们的一些发现,以及如何构建一个可靠而灵活的框架来监控和调整定价策略。
数据是关键
定价优化的一个基本要素是数据。传统上,公司通过选择少量相关数据流来确定固定价格,从而锚定其定价策略。然而,如今的组织越来越多地将越来越多的元素纳入动态而非固定的定价模型。随着定价成为差异化的核心杠杆,在这个不可能的时代,组织需要能够比以往任何时候都更快地响应市场变化,这意味着根据环境(如本地化或特殊场合)优化一系列决策(如定价或促销),以服务于多个业务目标的功能(如净收入增长或交叉销售)。
公共数据模型:走向可信定价模型的第一步
动态定价模型有可能极大地改变组织的底线。但是它也可以测试特定数据架构和数据管理实践的限制。在整合越来越多的数据流时,由于缺乏数据质量、跨多个地理位置或业务部门的数据治理不力,以及部署时间过长且效率低下,许多组织都面临着重复的“信任”问题。
解决这些问题的第一步是开发一个公共数据模型(CDM)。为所有需要的数据建立一个集中的模型对于确保用户拥有单一的真实来源是至关重要的。CDM 为影响定价优化的关键部分定义了标准,包括交易、产品、价格和客户。从那里,标准通过混合数据流应用,并服务于下游系统以利用定价数据(业务应用、仪表板、微服务等)。)与一个同构数据模型。CDM 还为参与该计划的各个团队提供了一种一致的方式,以便使用一种共同的语言更好地协作。
为定价优化准备适当的数据
拥有一个通用的数据模型是一个重要的基础组件。但定价优化效率的真正考验将取决于定价和收入专家对这些数据采取行动的速度。换句话说,用户准备数据有多容易,这是数据分析的第一步,也是最关键的一步。从历史上看,答案一直是“不太”。准备数据可能包括从处理空值到标准化不匹配的数据到拆分或连接列的所有内容,这是一个非常耗时的过程,需要非常注意细节,并且通常需要大量的技术技能。它可能会占用整个分析过程的 80%。但总的来说,花费额外的时间是值得的——适当准备的数据可以在错误和准确的最终分析之间产生差异。
为了解决定价优化的数据方面,我非常喜欢谷歌云用 Cloud Dataprep 解决数据准备问题,这是一种完全托管的服务,利用 Trifacta 技术,允许用户访问、标准化和统一所需的数据源。其机器学*驱动的引擎和可视化界面将整体数据准备过程的速度加快了 90%。利用云数据准备进行定价优化的一些关键步骤包括:
- 评估数据源:在获取定价优化所需的数据后,必须对其内容进行评估。每个源系统都有自己描述和存储数据的方式。每个源系统也将具有不同的精确度。在这第一步,建立一个清单是必要的,以便清楚地了解每个来源的质量,这将在以后通知他们应该如何清洗和标准化。
- 标准化数据:在确定源系统并评估其数据质量之后,下一步实际上是解决那些数据质量问题,以实现数据的准确性、完整性、一致性和完整性。最终,这些数据将被标准化并映射到其相应的 CDM 数据类别。
- 在一个结构中统一:将这些数据统一到一个单一的结构中包括将所有单独的 CDM 数据类与每个单独的类在最细的粒度级别上的属性连接起来。这是一个关键步骤,因为它为所有定价优化工作创建了一个可靠的数据源。
- 交付分析& ML/AI :一旦数据干净并准备好进行分析,分析师就可以开始运行用例及场景,探索价格变化的影响。正是在这个阶段,组织将开始看到其底线的巨大变化,但不是没有准备这些数据的所有艰苦的前期工作。
了解更多信息
想要了解在云中成功实施定价分析框架的关键因素吗?你可以阅读我们与致力于价格优化实践的团队共同撰写的白皮书。您还可以观看我们就该特定主题举办的网络研讨会,这样您就可以找出贵组织的弱点,更好地了解您的定价优化之旅所需的数据源,并查看 Google Cloud 智能分析套件如何实现基本公共数据模型(CDM)的分步演示。
定价,包装和产品:如何使用联合和 maxdiff 得到它的权利
原文:https://towardsdatascience.com/pricing-packaging-and-product-how-to-use-conjoint-and-maxdiff-to-get-it-right-8340b93e341c?source=collection_archive---------33-----------------------
摄影:rinke dohmen 资料来源:联合国人类住区规划署
我打赌你们公司的定价都是错的。
好吧,也许不是错了,让我们只说明显是次优。我不认识你或你的公司,但我知道在这方面我胜算很大——我也知道很少有产品经理或公司高管相信他们的定价是正确的。
你的产品和营销策略中最重要的一个方面(也许是最重要的)很少被关注,很可能是自动运行的。事实上,我最*对产品经理进行了一项调查,平均而言,他们最*一次对材料定价进行审查/更改是在 26 个月前。我明白为什么会这样——定价和包装决策是困难的、有风险的,而且是跨职能的。但这并不意味着什么都不做是明智的做法。
很多公司都做对了。一些行业有效地强迫它(想想消费品/零售)。但这是一个 B2B、技术和服务型公司特别努力的领域。好消息是,通过一些工作,它可以被修复,您可以立即对您公司的运营经济产生重大影响。
框架
我组织定价/包装分析的方式分为四个相关主题:
1.打包:在这种情况下,这意味着将各种功能或属性组合成不同的产品(SKU)。
2.价格模型和价格指标:这是您组织 SKU 和向客户收取产品费用的方式。例如,您可能有一组好-更好-最好的分层产品(模型),您对其收取一次性安装费,并按用户每月订阅费(指标)。
3.价格点:这些是您收取的实际价格(例如 3.99 美元),不同的 SKU 会有所不同。价格点可以基于期限承诺和数量以及细分市场和地理位置。在大多数地方,价目表实际上是一个价格矩阵。
4.商业条款:在 B2B 环境中,你将有一个协议来管理双方之间的业务关系。这是升级、降级、取消、产品寿命终止和未来价格上涨的定义。
在分析和改变这四个定价/包装领域时,需要一点艺术和科学。科学方面是关于使用正确的方法获得做出明智决策所需的数据。艺术维度是你如何将这些洞察力应用到市场中。例如,您可能故意优化包装/定价,因为从营销信息或定位的角度来看,“正确”的答案不起作用。
接下来的部分主要集中在寻找合适的定价和包装的科学方面。
该方法
步骤 1-创建基线
假设你有一个现有的企业,首先你应该把你的客户的交易规模和他们支付的平均单价放在一起绘图。在 x 轴上,您按照 ACV 从最小到最大对客户订单进行排序,在 y 轴上是支付的单价。如果您没有单一的可变价格指标(例如,每用户),而是只有一个固定费用类型模型或使用各种不同的指标,那么您应该使用适用于您产品的最接*的使用指标。这使你的顾客群支付的实际价格标准化了。
来源:pricekit.io
这告诉你什么?首先,这给了你一个要超越的底线。其次,如果您看到大量分散的数据点,这表明不一致的销售折扣做法(如果得到解决,这本身可能是一个快速的胜利)。
另一个值得获取的数据点来自你失去的交易(你应该密切跟踪)。如果你有细节,把它们画在上面的同一张图上。毫无疑问,由于价格和其他因素而被归类为失败的交易将被夸大。如果你看到这些拟议中的交易与成功的交易没有什么不同,这强烈表明价格以外的因素也在起作用。
第二项活动是审查你现有的商业条款。如果您对某些客户有最惠价格、价格上涨的数量和频率限制或其他此类承诺,您需要将它们记录下来并跟踪到受影响的客户。当您计划推出任何新模型时,您将需要它。
此外,这项工作的一部分应该是让你评估将现有客户群货币化的机会。
你的账户级别变动是多少?这衡量的是不续订和完全离开你的客户。如果价格很低,并且存在退出障碍(比如,向新供应商迁移的成本很高),那么你就拥有定价权。你的商业条款会告诉你,你可以在这些现有客户身上提高价格的程度和过程。其次,看看 NRR(我在这里谈论这个话题),如果它不是强大(比如说< 110%),这表明你应该寻找包装机会,以推动更强的向上销售和交叉销售运动进入现有基础。
最后,记录竞争对手的报价。这既包括直接竞争对手,也包括客户可能采用的替代产品,而不是购买您的产品。获得全面的报价菜单、标价和有效折扣需要努力,但这是值得的。询问客户、失去的交易、行业专家、渠道合作伙伴的见解。详细的机密数据不是目标,但了解他们的主要产品、他们使用的指标和粗略的价格点才是。
第二步—编译离散选择选项
找到合适的定价和包装的最佳方法是 AB 测试你的方式。没有什么比实际购买数据更真实、更确凿的了。但是除非你有很大的耐心,很大的预算,并且只通过数字和直接的方式销售——那么你需要找到另一种方式。
另一种方法是获取数据,以便对客户购买行为进行建模。做到这一点的方法是离散选择分析。
离散选择分析是一种统计建模,涉及在给定一组选项的情况下,个人选择特定选项的概率。它还与逻辑回归相关,逻辑回归是预测二元(例如是/否)结果的常用方法。
您可能在过去见过或使用过联合分析或最大差异分析——这两种分析都可以被视为离散选择模型的形式,至少它们通常是如何应用于产品定价/包装问题的。
离散选择的本质是给顾客提供一套现实的备选方案,然后看他们选择什么。轻松点。
来源:pricekit.io
嗯,概念上很容易,但要做好它需要相当多的工作。特别是,您需要解决两个挑战:
许多可能的选项。假设你销售的产品有 5 个特点或功能。在这 5 个包中,你可以创建 31 个不同的包。(如果你对这个怎么算感兴趣,查一下组合公式。它是:组合 5 选 5,加 5 选 4,以此类推)的和。
让我们进一步说,你想测试不同的价格点,一个高,一个基线和一个低端,以确定其对所选套餐的影响。您可能想知道每用户销售额、每笔交易销售额或其他指标之间是否存在差异。您需要将它们与市场上已有的竞争对手和替代产品进行比较。你可以看到这些选项是如何叠加的。
没有办法在一次调查中显示所有的问题。下一节将讨论如何缩小这些选项的范围。
第二个问题是恰当地传达以可消费的方式构成备选方案的特性。商品可以通过简单的描述(屏幕尺寸 48 英寸、50 英寸、55 英寸)来理解。然而,大多数产品需要更多的细节和背景——尤其是那些具有新/新奇功能的产品。有时候详细描述一下就够了。有时候你需要一个截屏,或者视频或者 gif。有时,在你询问受访者之前,你需要用中间内容来解释概念(即一元方法)。如果你不能给顾客提供一个现实的和可理解的选择,你就不会得到好的数据。
为了做好这项工作,你需要努力确保你的措辞是正确的,你的功能命名是清晰的,并且你有很好的资产来实现你的概念。这不是那种你可以忽略深思熟虑的内容和谨慎措辞的项目。
第三步:缩小选项并形成假设
实际上,你需要将所有可能的特性缩小到一个更小、更集中的列表中,只列出重要的和不同的特性。大多数产品特性,即使它们是必需的,也属于我称之为“预期填充物”的范畴。查看您的产品使用情况,询问销售工程师他们总是演示什么,与行业分析师交谈,询问一些客户为什么选择您而不是竞争对手——这些功能往往会真正影响选择。
您还应该尽早建立您的基准定价模型和指标。这样做的原因是,如果可以的话,减少一整类变量在你的选择练*中进行测试。如果有一个分类标准,可能很难偏离它,除非你是一个提供独特产品的新进入者。此外,您的价格指标需要与您的业务模式、销售方式以及企业的运营经济直接保持一致。例如,如果你有直销团队或高 CAC,免费增值或基于使用量的现收现付模式就不适合你,除非你准备采用批发业务模式和 GTM 改革,以适应新的目标市场和定价/包装。这对大多数公司来说都太难了。
一个好的经验法则是,尽可能直接根据产品的使用方式和客户从中获得的价值来确定价格。(但从客户的角度来看,它需要简单、事先可知并且可预测)。而且,理想情况下,它也是线性可扩展的——因此更大的客户、更大的使用量和更大的价值相应地支付更多。
如果您没有足够的背景数据来缩小功能并自己建立度量假设,并且没有保留,一个好的方法是对功能和价格模型运行 maxdiff 分析。
Maxdiff 是一种直接获得排序偏好的方法。您向回答者展示一个选项列表,并要求给出最佳/最差的评分,通常会对选项子集重复这一过程,以生成足够的回答来计算整个集合的排序偏好。这种方法避免了让人们在一个尺度上单独评价项目时“一切都是高优先级”的问题。因此,maxdiff 是区分重要事物和不重要事物的特别有用的方法。像这样做一个快速的预先调查会增加你的整体定价/包装工作的时间和成本,但是洞察力和信心可能会抵消它。
你的准备工作的结果应该是一组,比如说 5 个不同的包装选项,每个选项由 3-6 个你的关键功能的组合组成,围绕一个价格指标构建。该填充符可以被卷成一个“基本能力”描述,描述所有产品做什么或者从分析中一起删除。假设有另外 3 个竞争对手的报价要测试,并且您想在 3 个不同的价位测试每一个,这就给了您 25 个要担心的包(24 + a“不要选择这些”)。这个数字是可以控制的。
第四步:构建并运行分析
要进行基于选择的联合或最大差异调查,您需要一个能够胜任这项任务的调查工具。如果你有一个复杂的产品,你需要一些能给你提供格式和媒体选项的东西来以一种真实的方式展示项目。您还需要一个工具,能够在您的调查受访者中智能地分配选择范围,并且能够显示相同套餐的不同价位。有一些专门从事离散选择类型调查的工具,也允许产品经理、数据科学家、金融分析师和营销人员直接做这项工作。如果你了解你的业务,并想了解和解释结果,这是适合你的路线。如果没有,你当然可以外包给咨询或市场研究公司,他们有自己的工具,可以为你做这项工作。
这个分析的核心应该是基于选择的联合。这是一种离散选择练*,您向调查受访者提供一组选项,通常每次 4 或 5 个,并让他们选择最有可能购买的一个。这个练*重复几次,显示不同价位的不同选项。
一旦掌握了调查数据,建模和分析就有 4 个关键领域:
Preferences and share :最重要的数据是包选择频率(选择的时间百分比)。这将告诉你哪些包装在市场上有最强和最弱的需求——假设你的调查对象是市场的代表。所有软件包(您的和竞争对手的)的选择频率分布提供了一种市场份额视图,如果所有软件包都在市场上,将会发生什么。由于你测试的可能是你自己的替代品,而不是最终提供给客户的,所以这不是一个精确的衡量标准(但是像商业中的大多数事情一样,指示性/方向性数据通常就足够了)。
来源:pricekit.io
价格敏感度。数据还应该告诉你一个包的价格变化如何影响该包的选择频率。我通常使用 3 个价格点——基线和基线的+/- 50%。这造成了足够大的差异,因此它将显示在偏好数据中,但仍然是市场现实的价格。
由此,您可以计算每个包的平均选择价格,并由此计算价格调整频率(即频率 x 平均选择价格)。将各种套餐的原始频率视为客户市场份额的衡量标准,将价格调整后的频率视为收入市场份额的衡量标准。
此外,我还关注我所谓的价格敏感度指数。我的计算方法是,查看展示给回答者的每组选项,然后用所选价格点除以所展示的套餐的平均价格点。当在每个集合中绘制这些价格敏感度指标时:如果它们聚集在 1 附*,这就是如果价格完全不影响决策时你所期望的。大于 1 的选项群是那些选择更贵的套餐的人,小于 1 意味着他们倾向于选择更便宜的选项。这将告诉你顾客在多大程度上被便宜的选择所吸引(或者不是)。请注意,这是假设所有的包都在相同的大致价格范围内。如果有一家公司的价格是其他公司的 10 倍,结果就会有偏差。
效用(又名部分价值):一些联合调查软件包首先被设计用来计算特征效用。这种分析量化了每个单独特性对整个产品包的价值水平。例如,这种分析可以告诉您,“单点登录功能”的感知价值比“双因素身份认证功能”高 30%。
我发现效用值更有助于解释为什么一些包比其他的好,而不是首先作为构建包的指南。在解释为什么客户可能会从入门级产品选择或升级到高级/更贵的产品时,尤其如此。但是——小心调查软件,它迫使你仅仅为了获得统计上有效和全面的功能效用而构建简单化或人为限制的选择。依我看,这不是这项工作的主要目的。
细分:查看每个回答者选择的最优方案,你可以将他们分成相似的行为细分(例如,使用 K-means )。找到不同但相当大的群体,他们喜欢不同的套餐和不同的价位,这是你整个 SKU 系列的基础。
您不是在寻找一个合适的套餐和价格,而是寻找一个小的套餐和价位集合—每个都针对有价值的细分市场进行了优化。
您的调查中的人口统计问题应设计为允许您估计集群的真实市场规模,并使您能够将这些偏好反馈到现有客户群中(例如,用于追加销售和续订评分)。在调查中添加态度和认知问题,可用于告知围绕每个集群及其独特包装的营销信息。
到目前为止所做的分析旨在获得试图模拟现实世界行为的数据。你应该了解(a)什么功能重要,什么型号更受欢迎,( b)什么套餐需求最大,( c)这些套餐的价格敏感度如何,( d)你的套餐相对于竞争对手的表现如何,( e)这些项目在不同客户群中有何不同。
但是没有算法可以返回唯一确定的最佳答案。这就是你的判断和实际情况发挥作用的地方。最重要的指导应该是:你的报价需要适销对路。
这可能意味着您将特性聚合到更高的类别中,并将它们作为一个组附加到一个或另一个包中。我会避免你说这样的话:“这个 SKU 有很好的(安全、分析、报告、集成等),但另一个 SKU 有更好的(这些)”。如果你在你的价值主张中引入了很多细微差别,你已经给你的营销和销售团队造成了很大的伤害。一般来说,我认为最好保持价值主张的强势,即使牺牲一些(潜在的)功能驱动的追加销售活动。
一旦模型和定价到位,实现工作就开始了。根据变化的程度,这可能是一个简单的更新,也可能是一个公司范围内的重大举措。
你将不得不修改你的价目表,你的账单应用程序,并把这个模型应用到你的标准商业条款中。通常,由于过去的条款协议,您可能必须在维护旧 SKU 的同时维护旧 SKU,直到客户可以迁移。对于你在第一步中发现的条款与新模式或价格点有冲突的客户,你必须制定一个沟通和行动计划。
如果有大的结构变化,你需要更新营销材料、支持内容、销售宣传材料、演示、价目表、培训合作伙伴等等。这最好与主要新功能或新产品功能的引入或新的消息传递/定位/营销活动一起进行,以便所有这些变化可以同时进行,并相互加强。
从开始到结束,这项工作可能需要几个星期到几个月。一旦你有了数据,你就知道了方法,为新产品发布或年度战略计划节奏更新数据的工作就少多了。这是在你的公司内部建立一种能力,而不仅仅是做一个一次性的项目。你投入在正确定价和包装上的精力可能比你能做的几乎任何事情都有更大的回报。
定价研究——Van westen dorp 的 Python 价格敏感度表
原文:https://towardsdatascience.com/pricing-research-van-westendorps-price-sensitivity-meter-in-python-ec07fabbeacd?source=collection_archive---------19-----------------------
Python 中的测量设计和分析
调查
范·韦斯滕多尔普的价格敏感度测量仪是用来调查顾客价格偏好的。价格敏感度量表调查包括四个问题,要求每个调查参与者提供产品的四个价格点,当产品是:
- 太便宜(即太便宜)
- 便宜(即便宜货)
- 昂贵的
- 太贵了
这四个问题的示例如下所示:
资料来源:Qualtrics
数据
假设有 20 名参与者填写了调查问卷。让我们首先导入所需的库,并从这 20 个参与者那里读入数据。
数据框的前五行如下所示:
分析
这里我写了一个函数,计算四个问题(太便宜,便宜,贵,太贵)的累计百分比,绘制四条线,并报告最优价格和可接受的价格范围。
这是我们运行price_sensitivity_meter(df)
时的输出。x 轴显示价格点,y 轴显示价格累计频率的百分比。如果你想让剧情更流畅,可以设置interpolate=True
。在我们的函数中,interpolate
的默认值是 False。
主要结果是:
- 最优价格点(OPP)
“太便宜”和“太贵”的交集。在我们的例子中,最优价格是 300 美元。
- 可接受的价格范围
下界(又名。边际便宜点或 PMC)是“太便宜”和“太贵”的交集。上限(又名。边际成本点或 PME。)是“便宜”和“太贵”的交集。在我们的例子中,可接受的价格范围是 280 美元到 350 美元。
用质量验证结果
为了确保我们的结果是正确的,我用 Qualtrics 验证了我的结果。使用相同的数据,Qualtrics 生成以下报告:
资料来源:Qualtrics
最优价格与我们的结果相同。两者都显示 300 美元是最佳价格。可接受的价格范围不同,但非常接*。我们得到了 280 到 350 美元,而 Qualtrics 报告了 280.1 到 350.0 美元。(我不确定为什么 Qualtrics 在剧情中每一步都有一个斜率。台阶之间的垂直线不直。我怀疑数据量大了,竖线会变直。)
现在,您可以用 Python 设计自己的价格敏感度测量仪调查并分析结果。尽情享受吧!
参考
[## Van Westendorp 价格敏感度量表研究| Qualtrics
许可证包含的产品体验 Van Westendorp 定价模型 Van Westendorp 方法使用一系列…
www.qualtrics.com](https://www.qualtrics.com/marketplace/vanwesterndorp-pricing-sensitivity-study/)
在 Jupyter 笔记本中开发可再生神经网络的初级读本
原文:https://towardsdatascience.com/primer-on-developing-reproducible-neural-networks-in-jupyter-notebook-2f88d23b7c8d?source=collection_archive---------30-----------------------
照片由耶鲁安穴獭在 Unsplash
探索美国宇航局的涡轮风扇数据集
这不仅仅是为迭代开发播下种子
在准备我的下一篇文章时,在训练神经网络(NN)之前,我在一个 Jupyter 笔记本上尝试了不同的预处理设置。在尝试了一些设置后,我决定恢复到以前的设置,因为它的性能更好。然而,在执行细胞时,神经网络的结果并不相同,即使我已经设置了种子…
因此,在 Jupyter Notebook 中开发 NNs 时,我开始寻求可重复的结果。专门针对您在处理单元和训练单元之间来回切换的场景。
可重复和可比较的结果引物
开发神经网络模型时,比较模型性能并验证改进模型的尝试的有效性非常重要。编译 NN 为网络中的每个连接生成/初始化随机权重。这些权重在训练期间更新。然而,随机初始化的影响大到足以影响模型性能到小数点后第十位,妨碍了模型的比较。因此,我们需要“控制”这种随机初始化,以便在迭代、预处理或特征工程之间来回切换时,结果仍然具有可比性。
为了实现这一点,我发现我需要在两个层面上控制这种随机性:
- 会话间再现性(始终适用)—您需要设置各种随机样本生成器的种子,以确保您在笔记本中训练的神经网络在每次启动笔记本时返回相同的结果(无论是在不同的一天还是在重新启动内核后)。甚至必须在导入其他包之前【1,2】设置原生 Python 种子。这将确保每次执行代码时生成的权重是相同的,例如,第一组随机生成的值将总是相同的,第二组随机生成的值将总是相同的,等等。
- 在会话比较中(特别适用于笔记本电脑)—在编译 NN(首次抽取随机权重)后,您可能想要尝试不同的预处理方法。你必须在神经网络编译后保存权重,并在(重新)训练前重新加载这些权重。否则,重新编译你的神经网络会根据你设置的种子生成新的权重(随机权重的第二次抽取)。将其与没有替换的操纵概率进行比较[3]。你的第一次抽签将总是产生相同的结果,你的第二次抽签也将总是产生相同的结果,但它不等于第一次抽签。因此,您必须保存并恢复首次初始化的权重。此外,您还必须重置优化器,以避免从它的最后状态继续学*。
这两个步骤对于获得可比较和可重现的结果至关重要。
最后一点:当设置你的随机种子时,它可能会产生可怕的初始权重。因此,建议尝试一些随机的种子,以确保你不会吃亏。
让我们看看这是什么样子的
示例实现
对于这个示例实现,我将使用 NASAs CMAPSS 关于涡扇发动机退化的数据集。目标是预测剩余使用寿命。
首先,导入库,并为 python 环境、其内置随机库 numpy 和 tensorflow 设置随机种子。
接下来,您读入数据。
train.head()的结果
我就走个捷径,跳过解释几个数据准备步骤。你可以通过底部的链接查看完整的代码。让我们定义一个简单的 MLP。
定义模型后,我们编译它。通过编译模型,权重根据我们在开始时设置的种子进行初始化。这是我们第一次在时段再现性之间随机抽取重量和支持。此外,初始化的权重被保存以供以后(重新)使用。保存权重是在会话比较中支持的重要步骤。
对于下面的代码块,最重要的一行是第 1 行。Alpha 值决定了平滑滤波器的强度。
因为我是在笔记本上工作,所以在数据准备单元格和模型拟合单元格之间来来回回。出于这个原因,我在拟合之前重新编译模型以重置优化器,否则它会继续从它的最后状态学*。但是,重新编译模型会生成一组新的权重(随机权重的第二次抽取)。因此,我重新加载初始权重,以获得可比较和可重复的结果。
我现在可以试验不同的过滤强度来了解它的效果。一旦超过了α的值,我就可以回到之前的值,确保得到相同的结果。
alpha = 1.0, train_rmse = 18.00
alpha = 0.4, train_rmse = 17.43
alpha = 0.2, train_rmse = 17.82
alpha = 0.4, train_rmse = 17.43!
不幸的是,平滑 FD001 的数据会使测试集上的预测变得更糟,但这与这个玩具示例无关。要点是:通过实现这两个步骤,您可以在会话内和会话间获得可重复的结果。您可以在预处理和训练单元格之间来回切换,尝试不同的设置。当您想要使用以前的设置时,您可以确信结果是相同的。此外,当您第二天返回(或重启内核)时,您可以确信结果仍然是一样的。
希望这能让你的生活更轻松!完整的代码,请查看我的 github 页面这里。我要感谢迈克尔·格罗贝和杰弗里·卢普斯对我的文章的评论。
对于关注我的系列“探索 NASA 的涡扇数据集”的读者来说,这里开发的初始 NN(没有平滑或特征选择)已经在 FD001 数据集上具有 18.50 的测试 RMSE。比基线模型提高了 42%,比之前最好的模型有了很大的提高,后者是一个 RMSE 为 20.54 的支持向量回归模型(在基线上总体提高了 35.7%)。在我的下一篇文章中,我们将深入研究 FD002,其中涡扇发动机在不同的运行条件下运行,指数平滑确实具有有益的效果。
参考资料:
【1】https://keras . io/getting _ started/FAQ/# how-can-I-obtain-reproducible-results-using-keras-during-development
【2】https://stack overflow . com/questions/32419510/how-to-get-reproducible-results-in-keras/59076062 # 59076062
【3
主成分分析
原文:https://towardsdatascience.com/principal-component-analysis-3c39fbf5cb9d?source=collection_archive---------23-----------------------
(2021 年 9 月更新)无监督学*中最重要的算法之一背后的逐步直觉、数学原理和 python 代码片段
这个动画展示了当旋转方向到达两个特殊方向时,投影点(A…E)的协方差矩阵如何对角化(是下面的特征分解方程的解)。为了验证这一点,当方向与橙色虚线(第一主成分)或第二粉红色虚线(第二主成分)重叠时,请减慢视频速度或尝试暂停视频。您还会注意到矩阵的对角线元素达到了它们的最大值(最大方差)。(视频由作者使用 Geogebra6 sw 制作)
这个公式叫做特征分解方程。最初的工作始于 1800 年底,但由于(个人)计算能力的进步,直到最*才在大数据分析中得到实际应用。
大家好,我是意大利米兰的 Andrea Grianti。在阅读了许多关于这个主题的书籍和论文后,我写了这篇文章来分享我的想法。这不是一本教科书,而是进一步理解该主题的起点。因为后面的数学/代数很难,我把它分成了四部分:
- PCA 直觉
- 数学/代数(简单)
- 数学/代数(难)
- Python 片段
1。PCA 直觉
如果您有一个包含数千/数百万个观察值(行)和数百个不同变量(列)的大型数据集,首要目标之一是验证是否有可能简化和缩减数据集,以便于对原始数据的一个小得多的子集进行分析。
直接消除变量是显而易见的方法,但它显然会影响数据集的信息内容。过多或错误的剔除会使你的数据集变得无用,过少的剔除会使数据集变得庞大和难以分析。
术语'信息'是一个非常通用的主题,很难定义它。这取决于数据集。对我来说,一个数据集可能包含信息,而对其他人来说,可能什么也不包含,反之亦然。
我们可以尝试使用“信息内容”这样的概念来定义数据集中的信息量,这是一个与特定值发生的概率相关的概念,在数据集变量的所有可能值中。
根据这一概念,变量 x 的可能结果越多,预测其值的概率越低,因此信息含量越高。
这是我们要牢记的第一个假设:更高的方差= >更高的信息含量。只有上下文和我们的数据能告诉我们这个假设是否成立。
在关注高方差数据概念之前我们必须处理一个第二个假设: 变量之间的相关性是数据冗余的一种形式 。如果两个变量之间有明确定义的关系,例如以度为单位的角度和以弧度为单位的角度,或者以厘格或法拉为单位的温度,那么这两个变量中的一个是无用的,可以直接从数据集中消除。相反,当相关性不太明确时,不推荐直接排除,可以通过第三个假设尝试管理相关性证据的缺乏。
第三个假设是: 我们假设无论变量之间的相关性是什么,这都是线性的 。
概括一下,我们假设:
- 方差与信息内容有关,应该最大化
- 冗余变量和变量之间的高度相关性是一种应该最小化的噪声形式
- 变量之间的相关性是线性的
这两个假设为什么重要?因为要降低数据集的维度,我们应该评估每个变量对数据集总体方差(=信息)的贡献,以便选择贡献最大的变量,丢弃贡献最小的变量。
这种运算的战场是协方差矩阵或它的兄弟相关矩阵。因为相关矩阵通过绑定两个变量之间的简单协方差和相关性的相同关系严格绑定到协方差矩阵,所以我将使用协方差矩阵,因为选择与后面的数学原理的理解无关。
在任何情况下,对于那些喜欢简单刷新协方差和相关性概念以便理解这里的关系的人来说,它是:
我们知道,对于两个变量,协方差公式为(如果我们的数据集是从总体中抽取的数据样本):
不集中在平均样本数据的协方差(来源:作者)
协方差代表一种离差度量,它包括两个变量之间的线性“同步性的概念,这两个变量与它们各自的均值相关。
也就是说,对于每个点,测量一个点的 x 坐标>与所有 x 点的平均值>、之间的差值如何与同步的、、<与同一点的 y 坐标>和<之间的差值,然后对所有 y 点的平均值>求平均值。****
画在笛卡尔坐标系上的点。注意红色的平均点。还要注意,当重新定义轴时,将(0,0)点设置在平均值上,离散度不受影响。这实际上简化了理解协方差和相关性之间关系的推理。(来源:作者)
有趣的是,在上面的示例图片中,平均值的左右两边有相同数量的点(对于维度 x),平均值的上下两边也有相同数量的点(对于维度 y)。
这个简单的例子让你明白了协方差对于 符号的重要性。当结果给你一个正号或负号时,它给你一个关于象限的概念,其中同步的方向在哪里。还要注意,具有相同的符号并不能告诉你任何关于方向的斜率的信息,只能告诉你方向所在的象限。
如果点不是从左下到右上,而是从左上到右下(沿平均值的水平线反映),协方差将是相同的值,但前面有一个负号。
协方差如何绑定到相关性
如果你暂时不考虑上述协方差公式中的常数,等式的其余部分就是乘积与差值的和,这应该让你想起(至少对于乘积的和)代数中的点积概念。
为了使它看起来像两个向量之间的点积,我们可以将数据点居中(从每个变量值中减去该变量的平均值),并且我们两个的平均值都= 0,而方差保持不变(因为移动所有点不会改变点之间的距离,并且离差保持不变)。
在这种情况下,中心数据的协方差公式简化为:
以平均数据为中心的的协方差公式(来源:作者)
其中包含点积的定义我们知道是:
点积(来源:作者)
但是我们从几何学中知道,点积也可以写成:
点积:几何版(来源:作者)
考虑到当数据居中时,方差公式也简化为:
居中变量 X 和 y 的方差公式。
中心数据相对于向量 X 和 Y 长度的标准偏差
对于中心数据,协方差公式用标准差和向量 X 和 Y 之间的夹角余弦表示,即相关系数。(来源:作者)
两个中心变量情况下协方差和相关性(rho)之间的关系。当变量为 n 时,相同概念可以根据矩阵进行转置(来源:作者)
两个中心变量的简单协方差和相关性之间的关系:σ是它们的标准偏差,ρ是相关系数。在相关性为零的极端情况下,协方差为零。另一方面,当相关性最大时,ρ= 1 或ρ=-1,协方差是每个变量的标准偏差的乘积。
从协方差到协方差矩阵
考虑到上面的协方差公式仅适用于 2 个变量,我们可以将协方差矩阵视为数据集中所有变量之间所有协方差的“大图”。
协方差矩阵(在文献中也称为方差/协方差矩阵)(来源:作者)
当我们计算原始数据集(我们称原始数据集 X 为许多列向量 X1,X2…Xn 的集合)的方差/协方差矩阵时,我们会看到沿对角线的方差,但我们也会看到非对角线元素中的联合协方差,这是一个变量与其他变量之间的‘同步性’大小的(难以解释)度量。
因为我们当然不能为了消除变量之间的相关性而修改我们的原始数据 X(除非我们完全删除一个变量,这总是可能的,但有风险,因为我们可能不情愿地删除重要信息), 我们可以尝试找到一种方法,将 X“转换”成不同的数据集 Y,该数据集 Y 具有与 X 相关联的 special (德语中 special =eigen……)但是以这样的方式构建,Y(Y1,Y2…Yn)的新变量将具有不同的协方差矩阵 Cy,其中这些变量的方差将与其他变量的区间(相关性)隔离开来(= >协方差= 0)。
这是我们想降落的地方。具有对角化的新协方差矩阵 Cy。意味着我们要解决一个问题,找到一个新的数据集 Y,绑定到原始数据集 X(我们将看到绑定是如何工作的),其中 Y 的所有新变量在它们之间是不相关的。这样,Cy 矩阵中的协方差将为零,方差被隔离在对角线中。这将清楚地允许我们将数据集的总方差定义为对角线元素的总和(Trace)(来源:作者)。
这个操作就是特征分解方程的魔力。通过求解该方程,我们将找到一种方法来转换原始 X 数据集,从而将协方差矩阵 Cx 转换为新的数据集 Y,并使用一种称为 B 的特殊转换矩阵将对角化协方差矩阵 Cy 转换为新的数据集 Y。B 将是我们用来从 X 到 Y 来回转换的方式,反之亦然。
假设我们能够解出那个特征分解方程 …那又怎样?如果使用原始数据 X,我不得不使用 Cx 来解决无法根据相关性隔离单个变量对总体方差的贡献的问题,现在,通过求解该方程,我可以使用一个新的 Y 数据集,其协方差矩阵为 Cy,并且是对角的,因此 Y 的每个变量的方差贡献都有明确的定义,并且不受联合交互/相关性的影响。这样,我们就可以根据它们的方差值来决定在哪里切割 Y 数据集,以根据它们相对于 Cy 中的方差值总和的贡献权重来保留最重要的 Y 变量的子集。
当我们用 Y 而不是 X 工作时,要付出什么样的代价?因为新的 Y 数据集的变量(我们将会看到)是原始 X 数据的线性组合,它们的含义是不确定的。因此,要给 y 变量赋予上下文意义,就需要一定的敏锐度,让它们从实用的角度“说话”。当然,事情有点复杂,关于如何命名新发现的变量,我们在这里跳过了许多细节,但要框定问题和解决方案,就这样。
在任何情况下,要从 X 到 Y(以及从 Cx 到 Cy),我们需要理解我们可以对原始数据进行的转换的逻辑(通过一个仍待定义的 B 矩阵)。所以我们需要讨论(研究)一下投影和线性变换,因为它们是严格联系的。
2。PCA 后面的数学/代数(更容易)
投影概念:简而言之,我们在图表中绘制的内容取决于我们用来表示数据的坐标系统。艺术中的透视思考:它是现实生活中的投影按照特定的规则变换。
例如,在三维中,我们使用笛卡尔系统,其由正交向量(长度=1 的正交/垂直向量)的矩阵(E)表示。
卡茨安基地(来源:作者)
例如,当我们有一个数据集 X(测量值是三维的:列向量 x1、x2、x3)时,为了计算变量 x1 的方差,我们应用通常的方差公式。但是我们实际做的是通过点积将 X 的每个数据点的坐标投影到 E 的 3 个方向上。
因此,一般来说,我们有X \u E = X。这个投影操作在笛卡尔坐标系中是“透明的”,我们甚至没有意识到要进行投影,因为它在我们的头脑中是“自动的”。
但是,如果我们决定离开笛卡尔系统,我们可以建立一组类似的正交 向量,它们定义了由 b1、b2、b3(而不是由 e1、e2、e3 组成的 E)组成的新基 B,如下所示:
(来源:作者)
如果我们点乘(例如)数据集 X 的一个通用行向量,该向量包含单个数据点的坐标(如果您喜欢,可以是单个观察值):
通用数据行,(1,3)表示 1 行 3 列
对于 B (=3 行,3 列),我们获得新的行向量(=1 行,3 列):
Y 中相应的新行,使用 X 的一般行,用 B 转换
其中该向量的每个元素具有新的“度量”/“坐标”,由下式给出:
这里的三个方程是上图易方程的展开。因此,在维度上,形状仍然是(1 行,3 列),但行中的每个元素都是 xi 和 B 的线性组合。
在代数术语中,一般来说,在我们的例子中,我们简单地用以下公式改变基:
首先是矩阵形式。在我们的例子中,Y 由 3 列向量(y1,y2,y3,m 行)组成,B 由 3 列向量(b1,b2,b3,3 行)组成。所以 Y 是(m,n) = X (m,n)。B (n,n)。当找到 B 的解时,这 3 个方程将代表所谓的“主分量”。
其中 X 是基 E 中的原始数据矩阵(m 行乘 n 列),B 是新的标准正交基(n 乘 n),Y (m 乘 n)是在新基 B 中测量值被转置的结果新数据矩阵。
注意,y1、y2、y3 是新变量,其含义与 x1、x2、x3 无关,但是它们是新的,并且新含义必须在语义上定义,因为它们是分别由 B 的 b1、b2、b3 向量的相应分量加权的所有X 变量的线性组合。那就是:
- y1 由向量 b1=[b11,b12,b13]加权的 X 的每个变量组成
- y2 由向量 b2=[b21,b22,b23]加权的 X 的每个变量组成
- y3 由向量 b3=[b31,b32,b33]加权的 X 的每个变量组成。
所以如果我们找到 B 的解,我们可以用 y 的新变量。但是,我们应该使用什么 B 来达到我们的目标,找到 Y 与 Cy 对角矩阵?
b 可以逐步建立如果我们知道它存在一个唯一的方向,使沿该方向投影的 X 的方差最大化。我们可以沿着笛卡尔坐标系的 X 轴投影数据集 X,但在这种情况下,方差可能没有最大化。因此,我们需要找到那个特定的方向。一旦我们找到了最大方差的方向和值,我们就知道找到了第一个本征向量和第一个本征值。一般来说,我们可以说已经找到了第一主分量 PC1: y1=X.b1,其强度是特征值 1(λ1)。
为了根据方差解释了多少来评估 y1,在这个阶段,可以将λ1 除以协方差矩阵 Cx 的对角元素之和,因为总方差之和不会从 Cx 变为 Cy。
然后,利用相同的原理,我们可以找到第二方向B2(第二特征向量)作为最大化 X 沿着单位长度且正交于 b1 的第二方向的所有可能投影之间的方差(第二特征向量)的方向。当发现这是第二个主成分时:PC2: y2=X.b2
然后第三方向 b3 使 X 沿第三方向的方差最大化,该第三方向再次由单位向量定义,该单位向量也必须与 b2 和 b1 都正交。当发现这是第三个主成分:PC3: y3=X.b3
在这些迭代结束时,我们将建立一个特殊的 B=b1,b2,b3*,一个新的数据集 Y =[y1=X.b1,y2=X.b2,y3=X.b3]由 3 个“主分量”组成,按方差强度排序,一个特殊的特征值向量λs =(λ1,λ2,λ3),其中每个λ是每个 y1,y2,y3 的方差。
当然,迭代可以进行到 n 维。最后,根据总方差和(λ1,λ2,λ3)上的每个方差的相应权重,我们有所有元素来减少 Y。希望用 Y 的几个变量,我们可以“解释”总方差的大部分,我们可以减少变量的数量,但不能减少它包含的信息量..
3.PCA 后面的数学/代数(难)
以上是解释手动迭代程序以求解特征分解方程的冗长部分。现在我们来看看从开始到本征分解方程的解的整个数学过程。
我们称 X 为原始数据集(m 行 x n 列),其中列中的每个变量已经围绕它们各自的平均值“居中”, Cx 是 X 的协方差矩阵,b1 是 n 个元素的未知向量和未来 B 变换矩阵的第一列,y1 是 X 沿未知向量 b1 的投影:y1=X.b1
- Y 的第一个新变量的方差我们称之为 y1:
- 为了最大化 Var(y1)并找到相应的第一方向,我们使用带有拉格朗日乘数的拉普拉斯方程。符号是梯度,f 是最大化的函数,在我们的情况下是 y1 的方差 X.b1,g 是我们设置约束的函数,b 向量的长度必须是 1:
图一
- f 对 B1(n 分量的未知向量)的偏导数为:
图 2 如果你想知道为什么你可以用一个简单的未知向量 B1(b11,b12),一个给定的 simmetric Cx like ([4,2][2,1]),以及未知项 B1(b11,b12)。你将有一个二次多项式和两个偏导数(b11 和 b12)组成一个矩阵,它是 Cx 乘以 b1 的 2 倍
- g 对 b1 的偏导数是:
图 3
- 本征分解方程变为:
图 4
- 为了找到某个 b1 向量<> 0,我们必须找到括号中的项的行列式,并将其设置为 0。只有在这种情况下,b1 的 n 个未知分量中的 n 个方程组才有非平凡解:
图 5
- 这个含有 n 个未知数的 n 方程系统的解可能会给出(我保持简单,因为可能有例外)n 个不同的λ。这些λ代表 X 的投影点沿待定方向的 n 个不同方差。
- 现在我们应该指定找到的 lambdas(姑且称之为 lambda1)的最大值,并通过求解由下式给出的系统来找到 b1:
图 6
- 在我们找到 b1 之后,我们取λ2,并且我们在上面的等式中再次求解该系统以找到 b2,等等,直到对于所有的λ,我们有了所有的 b 向量。
- 正如你所想象的,计算对于 3 个变量来说是非常长的,这就是为什么我们需要 Python 和数字算法来完成这些脏活。
- 最后我们将(例外情况除外)得到:作为 b1,b2,b3 … bn 列向量序列的特征向量 B 矩阵;特征值向量 L(ambda)表示 Y(作为主分量)的每个 Y 的方差或特征向量的幅度。
4.Python 片段:
这里有很多例子和库,但在这里我想用 Python 来展示,只需用 numpy 代码片段,你就可以快速尝试你的样本小数据集,并通过查看结果来理解发生了什么。我跳过了 print 语句,因为您可以在控制台上工作并自己检查变量的内容。甚至图表都被省略了,但是你可以用 matplotlib 或者类似的工具做你想做的事情。这里的重点不是构建一个应用程序,而是展示对逻辑的理解。
import numpy as np
import pandas as pdpd.options.display.max_columns = 200
pd.options.display.width=200
pd.options.display.max_rows=200def fcenter(X): #function to center data
data_mean=np.mean(X,axis=0) #calc mean by column
X=X-data_mean #centered data
return Xdef fcov(X): #function to find the covariance matrix
covx=(X.T.dot(X))/X.shape[0] #calc cov matrix of X
#alternative to: covx=np.cov(X,rowvar=False,ddof=0)
return covxdef feigen_decomp(Cx): #this is the core to solve the eigen decomposition equation
eigval,eigvec=np.linalg.eig(Cx) #solve eigen equation
return eigval,eigvecX=np.array([[1,1,6],[4,2,9],[2,-2,3],[-3,3,1],[-5,1,7]]) #some data
Xc=fcenter(X) #centered data
#----------------------
#this shows that variance does not change when centering data
vX=np.var(X,axis=0) #variance of columns of X
vXc=np.var(Xc,axis=0) #variance of columns of Xc
#----------------------
Cx=fcov(Xc) #Cx=covariance of Xc
L,B=feigen_decomp(Cx) #L=eigenvalues vector, B=eigenvectors matrix
Lw=L/L.sum() #weight in % of every PC (not cumulative)
Y=Xc.dot(B) #Y=Principal Components matrix (in columns = y
scores)
Cy=fcov(Y) #shows that diagonal of covariance matrix of Y
coincides con L
#----------------------
#Loadings analysis
Loadings=np.sqrt(L)*B #see comments
Loadings_sq=Loadings**2 #see comments
Loadings_sq.sum(axis=0) #see comments
Loadings_sq.sum(axis=1) #see comments
关于加载的一个注意事项:当您想要了解结果时,加载是有用的。回想一下,Y 的每个新变量都是所有 X 变量的线性组合。负载矩阵垂直表示每个 PC 的方差有多少是由 X 的每个变量 X 解释的:事实上,每列的总和等于 L,水平表示每个 PC 解释了每个 X 的方差有多少:事实上,行的总和等于 X 的方差。如果你想的话,可以去看看。最后比这个还好玩:-)。
对于试图定义与对主成分的值(分数)有贡献的最相关的 x 的名称相关的 PCs 的名称,加载是重要的。
…跟我来
大家好,我叫 Andrea Grianti,我的职业生涯是在 IT 和数据仓库方面度过的,但后来我对数据科学和分析主题越来越有热情。
请考虑跟随我,以使我达到追随者数量的阈值,以便 Medium platform 将我纳入他们的合作伙伴计划。
现实生活中的主成分分析算法:发现房地产数据集中的模式
原文:https://towardsdatascience.com/principal-component-analysis-algorithm-in-real-life-discovering-patterns-in-a-real-estate-dataset-18134c57ffe7?source=collection_archive---------4-----------------------
在 Python 中使用 PCA 进行降维和模式可视化
主成分分析,简称 PCA,是一种无监督的学*技术,用于显示数据中的核心模式。
在本文中,我们将介绍 PCA 如何处理真实生活中的一个房地产经纪人的例子,他想了解为什么他们的一些房源需要很长时间才能关闭,以及我们如何使用 PCA 来编码一个更小的数据集。
你的朋友 Maggie 是一名房地产经纪人,她很困惑为什么她公司管理的一些房产六个多月都没有卖出去。她知道你是一名数据科学家,并问你是否能帮助她了解正在发生的事情。
你从做一些探索性的分析开始。您对数据进行全面检查,看看是否有缺失或不一致的值,然后就该在数据中寻找模式了。
Maggie 想知道为什么这些房产这么长时间都卖不出去。她想知道数据中的特征和模式是什么,使得这些房产需要这么长时间才能售出。
但是,在一个庞大且具有大量属性(通常称为特征)的数据集中寻找模式是不可能手工完成的。
除此之外,您的数据集可能有几个冗余要素。您可能会怀疑有些功能是其他功能的细微变化。在某些情况下,一些特征可能是纯粹的噪声,不能揭示数据中的核心模式。
例如,您注意到在 Maggie 的数据集中有以下特征:
- 一所房子的门的总数,
- 卧室总数,
- 浴室总数。
拥有一个关于门总数的特征似乎并不能揭示关于数据的一些关键信息,因为我们拥有另外两个特征。从统计学的角度来看,一所房子的门的总数很可能是一个多余的特征,并不能解释数据中的差异。
好吧,没什么大不了的!如果一所房子的门的总数是一个多余的特征,我们可以从数据集中删除它。这在我们的情况下是有意义的,但是在具有数百甚至数千个特征的数据集中,我们需要更加谨慎。
在包含大量要素的数据集中,我们需要在移除某个要素之前确保它是冗余的或有噪声的。我们可能会在不知情的情况下删除关于数据的重要信息。
我们应该只移除我们确信不会影响数据模式或预测结果的特征。
要在这个数据集中找到模式,您会立即想到主成分分析。
主成分分析(PCA)是一种无监督的学*方法,这意味着当我们在数据集中没有每个观察值的标签或目标时,可以使用它。
监督与非监督学*的目标。
在有监督的学*方法中,我们必须为每个观察值设置一个标签,因为目标是预测一个类别或一个数字,而在无监督的学*中,目标是在数据中寻找模式。
所以,你可以帮助我们的朋友 Maggie,使用主成分分析来找出需要更长时间才能出售的资产的核心特征。
PCA 是如何工作的
主成分分析的目标是对数据进行线性变换,从而最大限度地减少噪音和冗余。结果是数据集揭示了数据的最重要的特征。
应用 PCA 后,您将拥有一组主成分,按照它们对描述数据模式的贡献大小降序排列。用统计学的术语来说,它们是根据它们解释了多少差异来排名的。
第一个主成分在描述数据的变化方面是最重要的。其余的主成分在表达数据模式的可变性方面不太重要。
在幕后,主成分分析使用统计工具来识别数据集中的噪声和冗余。它使用协方差矩阵来分析:
- 每个特征的方差。它会显示某个特征是相关的还是纯粹的噪声,我们可以在对角线单元格中读取。
- 特征对之间线性关系的强度。这有助于发现冗余特征,并且它被读入所有非对角线值。
解释协方差矩阵。
协方差矩阵突出显示了妨碍观察数据模式的东西。那么,在一天结束时,什么样的主成分分析将产生一组主成分:
- 通过最大化特征方差来减少噪声。
- 通过最小化要素对之间的协方差来减少冗余。
PCA 的基础是协方差矩阵,并且在实践中,有两种方法来识别主分量:
- 计算协方差矩阵的特征向量。
- 计算协方差矩阵的奇异值分解。
在研究 Maggie 的数据之前,PCA 要求我们准备好数据集。原始数据集如下所示:
我们虚拟数据集的一部分😀
在探索性分析阶段,我们还想创建一个 pairplot ,并找出特征之间任何明显的相关性。但是,即使在这个只有 17 个要素的小虚拟数据集上,生成的 pairplot 也是巨大的,并且计算起来很慢。这是有道理的,因为我们必须选择 2 = 136 个单独的地块。
特征标准化和缩放
PCA 的第一步是归一化数据,并确保所有特征呈正态分布。然后,数据将遵循标准正态分布,平均值等于零,标准偏差等于一。
对数据进行规范化会将每个要素转换为一个通用的表示形式,并使要素之间的所有值具有可比性。当要素具有不同的比例时,对其进行归一化尤为重要。例如,当一个要素以英里为单位,而另一个以分钟为单位时。
标准化还保证主要成分是:
- 线性无关。每个主成分都是一个线性组合,不是由其他主成分组成的。
- 正交。这意味着所有的主分量彼此成 90 度角。
有几种方法可以标准化您的特征,通常称为特征缩放。其中之一是 Z 分数标准化,也称为标准化。
要对数据集应用 Z 值归一化,您需要更新每个数据点的值,以便:
我们走了这条弯路来讨论规范化,但是大多数统计库会为您做这件事。有了像 ScikitLearn 或 statsmodels 这样的 Python 库,你只需要设置一些参数。
在这个过程的最后,PCA 会将你的特征编码成主成分。但是需要注意的是,主成分不一定与特征一一对应。它们是数据集的新表示形式,可以一次对多个要素进行编码。
查看协方差矩阵
我们探索性分析的另一步是看一下协方差矩阵。PCA 对数据进行归一化并创建协方差矩阵,但它对于可视化要素之间的线性关系非常有用。
数据集的协方差矩阵。
要阅读这个矩阵,我们应该首先关注较暗的区域:
- 在非对角线上,成对的冗余特征。证实我们最初的预感卧室和号 _ 门有 97%的协方差。这意味着这两个特征之间有很强的线性关系。随着号门增加一个单位,间卧室增加一个单位,反之亦然。这对特征编码了相似的模式,所以我们可以认为它们是多余的。
- 在对角线上,我们看到所有的特征都有很高的方差。看起来所有的特征都是相关的,没有一个是纯粹的噪音。
下面是如何绘制协方差矩阵。
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt# Load dataset
dataset = pd.read_csv('src/dataset.csv')pca = PCA(dataset, standardize=True, method='eig')
normalized_dataset = pca.transformed_data# Covariance Matrix
# bias =True, so dataset is normalized
# rowvar = False, each column represents a variable, i.e., a feature. This way we compute the covariance of features as whole instead of the covariance of each rowcovariance_df = pd.DataFrame(data=np.cov(normalized_dataset, bias=True, rowvar=False), columns=dataset.columns)# Plot Covariance Matrix
plt.subplots(figsize=(20, 20))sns.heatmap(covariance_df, cmap='Blues', linewidths=.7, annot=True, fmt='.2f', yticklabels=dataset.columns)plt.show()
Python 中的 PCA
我们将使用 Python 库 statsmodels 来执行 PCA。你也可以使用 ScikitLearn ,但是 statsmodels 提供了更多的灵活性。例如,你可以选择是使用特征向量还是奇异值分解。
因此,在本例中,我们将在 statsmodel PCA 方法中设置以下标志:
- 标准化设置为 True,所以我们用均值 0 和方差 1 来标准化数据。
- 方法设置为 eig ,那么协方差矩阵的特征向量就成为我们的主成分。
我们将让参数 ncomp 不设置,因此 PCA 返回所有主成分,即与特征的数量一样多。
import pandas as pd
from sklearn import preprocessing# Load dataset
dataset = pd.read_csv('dataset.csv')# Run PCA
pca = PCA(dataset, standardize=True, method='eig')components_df = pca.factors
解释 PCA 的结果
所以, components_df 是一个包含所有主分量的数组,即协方差矩阵的特征向量。
但是这本身并不能告诉我们太多的数据。我们需要找到一种方法来解释这些结果,并将其与我们的原始数据集联系起来。
我们将首先计算原始数据集中每个主成分和每个要素之间的相关性。这里的关键是将主成分和特征作为一个整体进行成对关联,而不是在单个值之间进行关联。
如果我们把相关矩阵可视化就更容易了。在颜色渐变的顶部,我们将稍微调整一下图形:
- 在单元格之间创建一些空间,为了更好的可读性和美观,线宽= 0.7。
- 用 annot=True 将相关值添加到每个单元格。这样更容易发现单元格数值之间的差异。
- 用 fmt='.2f' 截断每个单元格中的值,使其具有两位有效数字,以提高可读性。
我们有一个相关矩阵😀
主成分和原始数据集特征的相关矩阵。
我们可以立即看到与第一主成分 comp_00 相关的最高相关值。
主成分是根据它们编码的数据集中的可变性大小来排序的。因此,第一主成分与数据集特征具有更高的相关性是有意义的。
与第一主成分相关联的这些特征与确定数据中的模式最相关。
我们还看到特征和主成分之间没有一对一的关系。第一主成分与几个特征有很强的正相关性。
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt# Load dataset
dataset = pd.read_csv('dataset.csv')# Run PCA
pca = PCA(dataset, standardize=True, method='eig')
components_df = pca.factorscombined_df = pd.concat([dataset, components_df], axis=1)
correlation = combined_df.corr() # This matrix will have the correlation between:
# 1\. feature vs features
# 2\. feature vs principal component
# 3\. principal component vs principal component
# We're removing part of the output to keep only the correlation between features and principal componentscorrelation_plot_data = correlation[:-len(components_df.columns)].loc[:, 'comp_00':] # plot correlation matrix
fig, ax = plt.subplots(figsize=(20, 7))
sns.heatmap(correlation, cmap='YlGnBu', linewidths=.7, annot=True, fmt='.2f')
plt.show()
PCA 如何帮助 Maggie
相关矩阵显示了哪些特征与第一主成分相关,因此哪些特征将一起改变。一个很好的例子是,由于第一主成分和卧室和平方英尺之间存在正相关,我们可以说,当你增加卧室或浴室的数量时,平方英尺往往会增加。
但是也有一些与第一主成分负相关,例如与交通可达性、靠*市中心和超市靠*度负相关。这表明,更大的房子,有更大的面积和更多的卧室、、将倾向于远离市中心、超市和更低的交通可达性。
由于 Maggie 正在分析超过 6 个月仍未售出的房屋的特征,她可以研究这些负相关性,以找到这些房屋为何长期未售出的线索。
权衡:失去可解释性
第一主成分与数据集中 17 个特征中的 11 个具有强正相关。这意味着它编码或代表了这些特征的模式。
这很棒,因为我们现在可以用更少的数据表达更多的信息。这里的权衡是,我们失去了可解释性。
当我们绘制彼此相对的特征时,更容易理解这些模式。但是由于主成分编码了几个特征,当我们绘制它们时,就不清楚了:
- 每个主成分编码什么特征,
- 每个特征的比例对我们看到的模式有更大的影响。
为了理解每个特征对主成分的贡献,我们需要查看每个主成分的负载。
负载是应用于线性组合中的每个特征的权重,其导致主成分的得分。
前两个主要成分的载荷。
只看前两个主成分,我们可以看到:
- 卧室和数量 _ 门在第一主成分中捕获更多信息。
- 硬木地板和城市中心在第二主成分中捕获了更多的信息。
以下是检查装载的方法。
import pandas as pd
from statsmodels.multivariate.pca import PCA# Load dataset
dataset = pd.read_csv('dataset.csv')pca = PCA(dataset, standardize=True, method='eig')
loadings = pca.loadings
print(loadings)
降维
PCA 最受欢迎的应用之一是降维。这是一种创建数据集新表示的方式,即:
- 小于原始数据集,
- 仅保留其核心模式和特征。
选择主成分来表示较小版本的数据集本身就是一个复杂的主题。之所以叫因子分析,是因为我们也可以把组件称为因子。
挑选因素的传统方法包括:
- 凯泽准则
- 解释方差
- 碎石图
凯泽准则
根据 Kaiser 准则,我们只选择特征值大于 1 的主成分。每个特征值与一个特征向量相关联,该特征向量实际上是一个主分量。
凯泽标准适用于我们的结果。
如果我们使用这种方法,我们将排除最后三个主要成分。
import pandas as pd
from statsmodels.multivariate.pca import PCA # Load dataset
dataset = pd.read_csv('src/dataset.csv')pca = PCA(dataset, standardize=True, method='eig')
eigen_values = pd.DataFrame(data=pca.eigenvals.values, columns=['eigenvalue'])print(eigen_values)
解释方差
使用这种方法,您可以选择想要主成分编码的数据集中的总方差。通常这些临界值是 80%或 90%。
主成分解释的累积方差。
如果我们使用这种方法,我们有:
- 前六个主成分解释了 80%多一点的方差,
- 前九个主成分可以大致解释我们数据集中 90%的差异。
我们会使用前六个或前九个主成分,这取决于我们建立的临界值。
import pandas as pd
from statsmodels.multivariate.pca import PCA# Load dataset
dataset = pd.read_csv('src/dataset.csv')pca = PCA(dataset, standardize=True, method='eig')# Cumulative Variance Explainedcumulative_variance_explained = pd.DataFrame(data=pca.rsquare.values, columns=['cumulative_var'])print(cumulative_variance_explained)
在统计学中, R 平方是用于确定一个变量的方差有多少是由另一个变量解释的度量。因此,PCA 模型的这个属性的名称。
碎石图
有了 scree plot ,我们可以更直观的方式挑选组件。我们绘制每个组件的特征值,并使用肘方法来确定我们的分界点。
在碎石块中寻找弯头。
这个想法是沿着减少的特征值,看看这些值在哪里形成一个弯头。我们只包括导致拐点的主分量。
这是一个不太精确的方法,因为它取决于每个人看手肘的角度。
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.multivariate.pca import PCA# Load dataset
dataset = pd.read_csv('src/dataset.csv')pca = PCA(dataset, standardize=True, method='eig')plt.subplots(figsize=(10, 10))
pca.plot_scree()
plt.show()
结论
希望你喜欢这个例子。借助这个随机生成的数据集,我们经历了 PCA 的每个步骤,涵盖了:
- PCA 的工作原理。
- 什么是主成分以及它们与原始数据集的关系。
- 如何决定保留哪些主成分,以防我们想要缩减我们的数据集。
感谢阅读!
主成分分析—已解释
原文:https://towardsdatascience.com/principal-component-analysis-explained-d404c34d76e7?source=collection_archive---------14-----------------------
详细的理论解释和 scikit-learn 示例
图源
主成分分析为什么重要?
随着数据科学的巨大进步,数据变得比以往任何时候都更有价值。现实生活中的数据集通常有许多要素(列)。一些特征可能是无信息的或者与其他特征相关。然而,我们可能事先不知道这一点,所以我们倾向于收集尽可能多的数据。在某些情况下,不使用所有功能也可以完成任务。由于计算和性能的原因,如果可能的话,希望用较少数量的特征来完成任务。无信息特征不提供任何预测能力,并且还导致计算负担。假设我们正在尝试预测篮球运动员的投篮命中率。数据集包括到篮筐的距离,方向的角度,防守者的位置,以前投篮的准确性和球的颜色。显而易见,球的颜色与投篮的准确性没有关系,所以我们可以把它去掉。现实生活中的情况不是那么明显,我们需要做一些预处理来确定无信息特征。使用软件包可以很容易地计算出特征之间或特征与目标变量之间的相关性。
也有一些案例具有大量的自然特征。例如,具有 8×8 像素图像的图像分类任务具有 64 个特征。我们可以找到一种方法,在不丢失大量信息的情况下,用较少的特征来表示这些图像。根据您工作的领域,您甚至可能会遇到包含一千多个要素的数据集。在这种情况下,减少功能的数量是一项具有挑战性但非常有益的任务。
随着特征数量的增加,分类器的性能在某个点之后开始下降。更多的特征导致模型需要学*更多的组合,以便准确地预测目标。因此,对于相同数量的观测值(行),模型往往在要素数量较少的数据集上表现更好。此外,大量的特征增加了过度拟合的风险。
有两种主要的方法来减少特征的数量。第一个是特征选择,旨在找到最有信息的特征或消除无信息的特征。可以手动或使用软件工具选择功能。第二种方法是在保留尽可能多的信息的情况下,从现有的特性中派生出新的特性。这个过程叫做特征提取或者降维。
我说的“保存尽可能多的信息”是什么意思?我们如何衡量信息量?答案是方差,这是一个变量被分散多少的度量。如果一个变量(特征)的方差很低,那么在建立模型时,它并不能告诉我们太多。下图显示了两个变量 x 和 y 的分布。正如您所看到的,x 的范围是从 1 到 6,而 y 的值介于 1 和 2 之间。在这种情况下,x 具有高方差。如果只有这两个特征来预测一个目标变量,那么 x 在预测中的作用远远高于 y。
在进行降维时,必须尽可能地保留当前数据集中的差异。降维的方法有很多。在这篇文章中,我将介绍一种最广泛使用的降维算法:【主成分分析】。
PCA 是一种无监督学*算法,它在数据集中寻找特征之间的关系。它也被广泛用作监督学*算法的预处理步骤。
PCA 是如何工作的?
注意:PCA 是一种线性降维算法。也有非线性方法可用。
我们首先需要移动数据点,使数据中心位于原点。虽然单个数据点的位置会改变,但相对位置不会改变。例如,具有最高要素 1 值的点仍具有最高要素 1 值。然后,PCA 将直线拟合到数据,使数据点到直线的距离最小化。
这条红线是新的轴或第一个主分量(PC1)。数据集的大部分方差可以用 PC1 来解释。第二个主成分能够解释相对于 PC1 的垂直变化。
排序红线是第二个主成分(PC2)。主成分的顺序根据它们所解释的原始数据集的方差分数来确定。很明显,PC1 比 PC2 能解释更多的差异。
然后旋转主分量和数据点,使得 PC1 成为新的 x 轴,PC2 成为新的 y 轴。数据点的相对位置不会改变。主分量彼此正交,因此线性无关。
主成分是原始数据集特征的线性组合。
PCA 的优点是使用比原始数据集少得多的特征保留了原始数据集的大量差异。主成分是根据它们所代表的方差来排序的。
让我们来看一个使用 scikit-learn 的例子。 Scikit-learn 是一个机器学*库,为预测数据分析提供简单高效的工具。
Scikit 学*实现
为了保持一致,我将使用我从一开始就展示的数据点。这是一个非常简单的例子,但足以理解这个概念。
我们使用这些数据点创建一个数据帧,并为每个数据点分配一个类。
import numpy as np
import pandas as pddf = pd.DataFrame({
'feature_a':[2,1.5,2,2.5,3,2.5,3.7,2.8,1.8,3.3],
'feature_b':[1,1.2,2,1.5,3,2.4,3.5,2.8,1.5,2.5],
'target':['a','a','a','a','b','b','b','b','a','b']})
所以这是一个有两个独立变量的二元分类任务。
在应用 PCA 之前,我们需要将数据标准化,使数据点的平均值为 0,方差为 1。Scikit-learn 提供了来自 sklearn 的 StandardScaler() .预处理导入 StandardScaler
from sklearn.preprocessing import StandardScalerdf_features = df[['feature_a','feature_b']]
df_features = StandardScaler().fit_transform(df_features)
然后,我们使用创建一个 PCA()对象,并拟合数据点。
from sklearn.decomposition import PCApca = PCA(n_components=2)
PCs = pca.fit_transform(df_features)
然后,我们使用主成分创建一个新的数据帧:
#Data visualization libraries
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline#Create DataFrame
df_new = pd.DataFrame(data=PCs, columns={'PC1','PC2'})
df_new['target'] = df['target'] #targets do not change
我们可以绘制一个散点图来查看新的数据点:
fig = plt.figure(figsize = (8,4))
ax = fig.add_subplot()
ax.set_xlabel('PC1')
ax.set_ylabel('PC2')targets = ['a', 'b']
colors = ['r', 'b']for target, color in zip(targets,colors):
rows = df_new['target'] == target
ax.scatter(df_new.loc[rows, 'PC1'],
df_new.loc[rows, 'PC2'],
ax.legend(targets)
根据主成分的数据点
我们还可以绘制原始数据点的散点图,以便您可以清楚地看到数据点是如何转换的:
正如您在主成分图中看到的,仅使用 PC1 就可以将两个类分开,而不用同时使用 feature_a 和 feature_b。因此,我们可以说 PC1 解释了大部分差异。确切地说,我们可以计算每个主成分对方差的解释程度。Scikit-learn 提供了解释 _ 方差 _ 比率 _ 方法来计算这些金额:
pca.explained_variance_ratio_array([0.93606831, 0.06393169])
PC1 解释了 93.6%的方差,PC2 解释了 6.4%。
每个主成分解释的差异
注:主成分是原始特征的线性组合。
这个例子是一个非常简单的例子,但它解释了这个概念。当在具有更多特征的数据集上进行 PCA 时,我们只需遵循相同的步骤。
感谢您的阅读。如果您有任何反馈,请告诉我。
我的其他帖子
机器学*
- 朴素贝叶斯分类器—解释
- 逻辑回归—已解释
- 支持向量机—解释
- 决策树和随机森林—解释
- 梯度增强决策树—解释
- 用机器学*预测二手车价格
数据分析
- 数据科学中最被低估的工具:NumPy
- 使用熊猫组合数据帧
- 用熊猫处理缺失值
- 熊猫的三大功能
主成分分析-现在用你自己的术语解释
原文:https://towardsdatascience.com/principal-component-analysis-now-explained-in-your-own-terms-6f7a4af1da8?source=collection_archive---------34-----------------------
学*一种重要的机器学*技术,根据你的理解水平量身定制五种不同的解释。
主成分分析——现在用你自己的方式解释(图片:unsplash.com
几个月前的一个晚上,在线杂志《连线》的标题引起了我的注意。当我把目光聚焦在它上面时,上面写着:“能不能用每个人都能理解的语言向他们解释所有的事情?在 5 个层次中,一位专家科学家在 5 个不同的复杂层次中解释一个高层次的主题 - 首先是对一个孩子,然后是青少年,然后是同一主题的本科生,研究生,最后是同事。
出于好奇,我点击了链接,开始学*令人兴奋的新概念,我终于可以用自己的理解水平掌握这些新概念了。音乐、生物、物理、医学——那天晚上一切似乎都很清楚。不用说,我不能停止看连续剧,很晚很晚才睡觉。
连线网站截图,展示“5 级”概念集合(图片:截图)
实际上,我是在撰写一篇更具技术性的文章时开始写这篇文章的。从文本中的几个段落开始,它变得越来越大,直到我觉得我原来的文章再也支撑不住它的重量。我能向同龄人、同事、孩子和没有数学倾向的人解释这些关键概念吗?读者能在多大程度上理解这些解释?
让我们来了解一下:)
1)子代
有时,当我们学*新的东西时,我们被告知许多事实,可能会看到一幅画或一个有数字的表格。看到大量的数字和表格可能会令人困惑,所以如果我们能够得出相同的结论,只是使用更少的这些事实、表格和数字,这将非常有帮助。
主成分分析(或简称 PCA)就是我们所说的算法:一组要遵循的指令。如果我们用数字来表示我们所有的事实和表格,遵循这些指示将允许我们用更少的数字来表示它们。
如果我们把这些数字转换回事实,我们仍然可以得出同样的结论。但是因为我们用比以前更少的事实来画它们,执行 PCA 只是帮助我们不那么困惑。
2)高中年龄的青少年
我们的数学研究集中在几个关键领域,这些领域为我们的数学理解和定位提供了基础。高中数学通常意味着学*微积分,它涉及函数分析和解析几何等科目。让我们用它们来更好地解释主成分分析。
你可能在高中的某个时候遇到过类似的函数(图片由作者提供)
函数是数学中的特殊对象,当我们给它输入值时,它会给我们一个输出值。这使得它们在学*数据中的某些关系时非常有用。高中教授的一个关键技术是如何通过对函数的性质进行简短的分析来绘制函数的图形。我们使用微积分中的一个东西叫做导数:导数就是函数在给定点的斜率的*似值。我们在图形区域内选择几个关键点,找出函数在这些点上的值,并计算函数在这些点上的导数,从而得到函数斜率的提示。然后我们用刚刚得到的点和斜率画出函数形状的*似值。
但有时函数会变得邪恶……(图片由作者提供)
在现实世界中,有时我们有很多函数,甚至是奇怪的东西,比如同时输出多个值的函数,或者需要多个输入才能给我们值的函数。如果你是那种觉得高中函数很可怕的人,想象一下这些多数字函数有多可怕——即使对熟练的成年人来说也是如此!主成分分析是一种技术,它获取所有这些函数的输出,并使用更少的这些数字给出我们接*的*似值。更少的数字通常意味着记忆更少的数据,更小更便宜的存储方式,以及更少的当我们看到如此多的数字而不知道从哪里开始时的“困惑”感。
大学一年级学生
在学*期间,你已经学*了线性代数、统计学和概率。您已经处理了一些输入和输出多个值的“真实世界”函数,并了解到它们处理的是称为向量和矩阵的东西。您还学*了所有关于随机变量、样本值、均值、方差、分布、协方差、相关性以及所有其他统计学技术术语。
数学术语(图片:【youtoart.com】T2)
主成分分析依赖于一种叫做“奇异值分解”(简称 SVD)的技术。现在让我们把它当作计算机科学中所谓的“黑匣子”:一个未知的函数,一旦我们给它输入所需的输入,它就会给出我们想要的输出。如果我们收集大量数据(来自观察、实验、监控等)并以矩阵形式存储,我们可以将这个矩阵输入到我们的 SVD 函数中,得到一个更小维度的矩阵,使我们可以用更少的值来表示我们的数据。
虽然现在,将 SVD 作为一个黑盒可能是有意义的,但是进一步研究输入和输出矩阵可能是有趣的。事实证明,SVD 为一种称为“协方差矩阵”的特殊矩阵提供了额外的有意义的输出。作为一名本科生,你已经处理过协方差矩阵,但你可能会想:“我的数据与它们有什么关系?”
左——尤金尼奥·贝尔特拉米;右——卡米尔·乔丹;两位 19 世纪晚期的数学家独立发现了奇异值分解(图像:公共领域)
我们的数据实际上与协方差矩阵有很大关系。如果我们将数据分为不同的类别,我们可以将相关的值分组到一个表示该类别的向量中。这些向量中的每一个也可以被视为一个随机变量,包含 n 个样本(这使得 n 是向量的长度)。如果我们将这些向量连接在一起,我们可以形成一个 m 个随机变量的矩阵 X,或者一个具有 m 个标量的随机向量,保存该向量的 n 个测量值。
代表我们的数据的连接向量矩阵可以用来计算我们的随机向量的协方差矩阵。然后,这个矩阵作为输入提供给我们的 SVD,SVD 为我们提供了一个酉矩阵作为输出。
在不深入研究酉矩阵的情况下,输出矩阵有一个简单的特性:我们可以从矩阵中挑选前 k 个列向量来生成一个新的矩阵 U,并将原始矩阵 X 乘以矩阵 U 来获得一个更低维的矩阵。事实证明,当映射到一个较低的维度时,这个矩阵是存储在 X 中的数据的“最佳”表示。
理科学士
毕业于一个学术学位,你现在有了正确解释主成分分析所需的数学背景。但是,如果我们不理解数学背后的直觉或我们试图解决的问题,仅仅写下数学是没有帮助的。
PCA 试图解决的问题是我们称为“维数灾难”的问题:当我们试图训练机器学*算法时,经验法则是我们收集的数据越多,我们的预测就越好。但是对于每一个新的数据特征(意味着我们现在有一个额外的随机向量),特征向量所跨越的向量空间的维度增加一。我们的向量空间越大,训练我们的学*算法所需的时间就越长,一些数据冗余的可能性就越高。
机器学*算法经常需要非常大量的数据(图片:【towardsdatascience.com】T2)
为了解决这个问题,研究人员和数学家一直在努力寻找执行“降维”的技术:将我们的向量空间嵌入另一个更低维度的空间。维数减少的固有问题是,对于向量空间维数的每一次减少,我们实质上丢弃了跨越原始向量空间的随机向量中的一个。这是因为新空间的基础少了一个向量,使得我们的随机向量之一是其他向量的线性组合,因此在训练我们的算法时是多余的。
当然,我们确实有简单的降维技术(比如丢弃随机向量,检查哪个丢失的向量对算法的准确性影响最小)。但是问的问题是“在进行降维时,如何才能损失最少的信息?”结果答案是“通过使用主成分分析”。
从数学上来说,如果我们像以前一样用矩阵形式表示我们的数据,n 个随机变量每个都有 m 个测量值,我们将每个样本表示为行 xi。因此,我们正在寻找一个线性映射 T: ℝ n → ℝ k,它使 xi 和 T(xi)之间的欧几里德距离最小化
我们要做什么?为了最小化降维过程中的信息损失
这个公式背后的直觉是,如果我们将我们的图像向量表示为原始向量空间中的 n 维向量,它们从原始位置移动的越少,意味着信息损失越小。为什么距离意味着信息的丢失?因为向量的表示越接*其原始位置,表示就越准确。
我们可以说 T1 是比 T2 更精确的投影,因为它更接*原始向量 Xi(图片由作者提供)
我们如何找到线性地图?原来地图是奇异值分解提供的!回想一下,如果我们调用 SVD,我们得到一个酉矩阵 U,它满足
由于线性映射空间和矩阵空间之间的同构,我们可以看到矩阵 u 表示从 ℝ n 到 ℝ n 的线性映射:
从 Rn 到 Rk 的线性映射的向量空间同构于矩阵空间 R(n×k)
SVD 到底是怎么给我们提供函数 U 的?奇异值分解本质上是线性代数中一个重要定理的推广,这个定理叫做谱定理。虽然谱定理只能应用于正常矩阵(满足 MM* = MM,其中 M是 M 的复共轭),但 SVD 通过将矩阵分解为三个矩阵,将结果推广到任意矩阵 M:SVD(M)= U σ v。
根据谱定理,U 是酉矩阵,其行向量是 Rn 的正交基,每个行向量跨越一个与其他特征空间正交的特征空间。如果我们把那个基表示为 B = {u1,u2 … un},并且因为 U 对角化了矩阵 M,所以它也可以看作是标准基和基 B 之间的变换矩阵。
将任意线性地图分解成 3 个正交投影的图示。其中每一个都将 Xi 投影到匹配的特征空间,嵌套在 R3 内(图片由作者提供)
当然,任何子集 Bk = {u1,u2 … uk}都是 ℝ (k)的正交基。这意味着执行乘法 M * U-1(类似于乘以 U * M)同构于线性映射 t:ℝn→ℝk . SVD 背后的定理将这个结果推广到任何给定的矩阵。虽然这些矩阵不一定是可对角化的(甚至是正方形的),但关于酉矩阵的结果仍然适用于 U 和 v,我们剩下的就是执行乘法 X' = Cov(X) * U,执行我们正在搜索的维数约简。我们现在可以把简化的矩阵 X '用于任何我们曾经使用原始矩阵 X 的目的。
专家数据科学家
作为一名在学*算法的研究和开发方面拥有丰富经验的专家数据科学家,您可能已经知道 PCA,并且不需要对其内部工作方式和在实践中的应用进行简要描述。然而,我确实发现,很多时候,即使我们已经应用了一段时间的算法,我们并不总是知道使它工作的数学。
如果你遵循了前面的解释,我们仍然有两个问题:为什么矩阵 U 表示线性映射 T,它最小化了信息的损失?而 SVD 是如何给我们提供这样一个矩阵 U 的呢?
第一个问题的答案在于线性代数中一个重要的结果,叫做主轴定理。它陈述了解析几何中的每个椭球体(或超椭球体等价体)形状可以表示为形状 Q(x)=x'Ax 的二次型 q:ℝn xℝn→ℝ(这里 x '表示 x 的转置)使得 a 可对角化并且具有到相互正交的特征空间的谱分解。所获得的特征向量形成了 ℝ n 的标准正交基,并且具有匹配超椭球轴的性质。太棒了!
主轴定理向我们展示了 A 的特征向量与 Q 定义的椭球的轴重合(图片修改自researchgate.net
主轴定理显示了线性代数和解析几何之间的基本联系。当绘制我们的矩阵 X 并可视化各个值时,我们可以绘制一个包含我们的数据点的(粗略的)超椭球形状。然后,我们可以为数据的每个维度绘制一条回归线,尝试最小化数据点到回归线的正交投影的距离。由于超椭球体的特性,这些线就是它们的轴。因此,回归线对应于从二次型 q 的谱分解获得的跨越特征向量。
向量、可能的正交投影和投影的正交补码之间的关系和权衡(图片由作者提供)
回顾类似于公式化问题时使用的图表,注意正交投影的长度与其正交补的长度之间的权衡:正交补越小,正交投影越大。即使 X 是以矩阵形式写的,我们也不能忘记它是一个随机向量,因此它的分量在它们的测量值之间表现出方差。由于 P(x)是一个投影,它不可避免地丢失了一些关于 x 的信息,这些信息累积起来就是方差的损失。
为了最小化正交投影上的方差损失(即保留最大可能方差),我们必须最小化正交补的长度。由于与数据主轴重合的回归线使代表测量值的向量的正交互补最小化,因此它们也使原始向量的方差最大化。这正是 SVD“最小化信息损失”的原因:因为它最大化了保留的方差。
既然我们已经讨论了 SVD 背后的理论,那么它是如何施展魔力的呢?SVD 以一个矩阵 X 为输入,将其分解为满足 X = U σ V 的三个矩阵:U,σ,V,由于 SVD 是一个分解而不是一个定理,所以让我们在给定的矩阵 X 上一步一步地执行。
首先,我们要引入一个新术语:矩阵的奇异向量是任何满足等式的向量 v
由于 X ∈ ℝ (m x n),我们无法保证它的维度或内容。X 可能没有特征值(因为特征值只为方阵定义),但它总是至少有ρ个不同的奇异向量(ρ(X)是 X 的秩),每个向量都有匹配的奇异值。
然后我们可以用 X 来构造一个对称矩阵
因为每个转置矩阵也是伴随矩阵,所以 XT 的奇异值是 X 的奇异值的复共轭。这使得 XT*X 的每个特征值是 X 的匹配奇异值的平方:
XT*X 的特征值是 X 的奇异值的平方
因为 XTX 是对称的,所以也很正常。因此,XTX 是正交可对角化的:存在对角矩阵σ2,它可以写成三个矩阵的乘积:
XT*X 的正交对角化
其中 V 是由 XTX 的特征向量构成的标准正交矩阵。我们将这些向量标记为
Bv 是使用 XT*X 的正交对角化获得的 ℝ n 的标准正交基
我们现在构造一组新的向量
我们将每个成员定义为
注意,因为 Bv 是一个正交群,对于每一个 1≤i≤j≤n
因此,我们可以证明:
关键方程#1:因为 Bv 是正交群,所以 Bu 也是正交群
另外,ui 也是 X*XT 的一个特征向量:这是因为
关键等式#2: Bu 由 X*XT 的特征向量组成
我们现在可以通过以矩阵形式表示 Bu 和 Bv 之间的关系来完成证明:
ui 和 vi 之间的关系,以矩阵形式表示
然后通过标准矩阵乘法:U *σ= X * V,紧接着就是
我们刚刚取得的结果令人印象深刻,但请记住,我们使用 Bv 的向量将 Bu 构造为一组 n 个向量,即 U∈R(m×n)而σ∈R(n×n)。虽然这是有效的乘法,但 U 不是方阵,因此不能是酉矩阵。为了解决这个问题,我们用零“填充”矩阵σ以实现 m×n 形状,并使用 Gram-Schmidt 过程将 U 扩展为 m×m 形状。
既然我们已经完成了数学部分(唷…),我们可以开始画一些简洁的连接了。首先,虽然 SVD 在技术上可以分解任何矩阵,我们可以只输入原始数据矩阵 X,但是主轴定理只适用于可对角化的矩阵。
第二,主轴定理通过在矩阵的特征向量上执行正交投影来最大化矩阵中保留的方差。但是谁说我们的矩阵首先捕获了大量的变化?
为了回答这些问题,并结束本文,我们将首先重申,捕获随机变量之间的方差是通过使用协方差矩阵来完成的。并且因为协方差矩阵是对称的和半正定的,所以它是正交可对角化的,并且具有谱分解。然后,我们可以使用这个简洁的公式重写协方差矩阵的公式,该公式是通过将 SVD 应用于相乘形成协方差矩阵的矩阵而获得的:
关键等式 3:注意这非常类似于 XT*X 的正交对角化
这就是为什么我们说 SVD 在应用于 X 的协方差矩阵时会给出额外的有意义的输出:
a)Cov(X)的奇异值分解不仅与其谱分解相同,而且将其对角化!
b)对角化矩阵 V 是由 Cov(X)的酉特征向量构成的标准正交矩阵,用于进行 X 的主成分分析!
c)使用 Cov(X)捕获我们的数据中的最大方差,并且通过将其投影到与 Cov(X)的 k 个最大特征值相关联的基本特征向量上,我们丢失了将我们的数据减少(n-k)维的最小可能方差
d)主轴定理确保我们在使用 Cov(X)和 v 执行 PCA 时,最小化来自 ℝ n→ ℝ k 的投影误差
Python 中从头开始的主成分分析(PCA)
原文:https://towardsdatascience.com/principal-component-analysis-pca-from-scratch-in-python-7f3e2a540c51?source=collection_archive---------1-----------------------
以及一些低维空间的可视化。
主成分分析是一种用于降维的数学技术。它的目标是在保留大部分原始信息的同时减少特征的数量。今天我们将使用 pure Numpy 从头开始实现它。
卢卡斯·本杰明在 Unsplash 上的照片
如果你想知道为什么 PCA 对你的普通机器学*任务有用,这里列出了 3 大好处:
- 减少训练时间——由于数据集更小
- 去除噪音——只保留相关的内容
- 使可视化成为可能——在最多有 3 个主要成分的情况下
最后一个是个大问题——我们今天将看到它的实际应用。
但是这有什么大不了的呢?好问题。假设您有一个包含 10 个要素的数据集,并希望对其进行可视化。但是如何? 10 个特征= 10 个物理尺寸。当涉及到可视化 3 维以上的任何东西时,我们人类有点糟糕——因此需要降维技术。
我想在这里做一个重要的说明——主成分分析不是一个特征选择算法。我的意思是,主成分分析不会像正向选择那样给出前 N 个特征。相反,它会给出 N 个主成分,其中 N 等于原始特征的数量。
如果这听起来令人困惑,我强烈建议你观看这个视频:
该视频深入理论推理,并解释了一切比我更好的能力。
我们今天的议程如下:
- 加载数据集
- 执行 PCA
- 制作令人惊叹的可视化效果
所以,事不宜迟,让我们开始吧。
数据集和导入
我希望这里的一切都超级简单,所以我决定使用众所周知的虹膜数据集。它最初只有 4 个特征——仍然无法可视化。我们将在应用 PCA 后解决这个可视化问题。
以下是导入和数据集加载:
import numpy as np
import pandas as pddf = pd.read_csv(‘[https://raw.githubusercontent.com/uiuc-cse/data-fa14/gh-pages/data/iris.csv'](https://raw.githubusercontent.com/uiuc-cse/data-fa14/gh-pages/data/iris.csv'))
df.head()
执行上面的代码应该会产生以下数据框:
让我们继续 PCA 本身。
逐步 PCA
以下是所需步骤的简短总结:
- 缩放数据 —我们不希望由于缩放差异,某些功能被投票认为“更重要”。10m = 10000mm,但是这个算法不知道米和毫米(对不起我们读者)
- 计算协方差矩阵 —给出随机向量的每对元素之间的协方差的方阵
- 特征分解——我们会讲到的
所以让我们从第一个(也是最简单的)开始。
数据缩放
我已经简要地谈到了我们为什么需要扩展数据的想法,所以我不会在这里重复我自己。把它当作一个必要的先决条件——不仅在这里,对任何机器学*任务都是如此。
为了执行缩放,我们将使用来自 Scikit-Learn 的标准缩放器:
from sklearn.preprocessing import StandardScalerX_scaled = StandardScaler().fit_transform(X)
X_scaled[:5]
这部分就这样了。我们继续吧。
协方差矩阵
让我们回到这里,理解方差和协方差的区别。方差报告单个随机变量的变化,比如说一个人的体重,协方差报告两个随机变量的变化,比如一个人的体重和身高。
协方差矩阵的对角线上有方差,其他元素是协方差。
我们不要在这里深究数学,因为你有那部分的视频。下面是如何获得 Numpy 中的协方差矩阵:
features = X_scaled.T
cov_matrix = np.cov(features)
cov_matrix[:5]
酷毙了。如你所见,对角线元素是相同的,矩阵是对称的。接下来,特征分解。
特征分解
特征分解是将方阵分解为特征向量和特征值的过程。特征向量是简单的单位向量,特征值是给特征向量大小的系数。
到目前为止,我们知道我们的协方差矩阵是对称的。原来,对称矩阵的特征向量是正交的。对于主成分分析,这意味着我们有第一个主成分,它解释了大部分的差异。与之正交的是第二个主成分,它解释了大部分剩余的方差。对 N 个主分量重复这一过程,其中 N 等于原始特征的数量。
这对我们来说很简单——主成分按照解释的方差百分比排序,因为我们可以决定保留多少。例如,如果我们最初有 100 个特征,但是前 3 个主成分解释了 95%的方差,那么只保留这 3 个用于可视化和模型训练是有意义的。
由于这不是关于特征分解的数学讲座,我想接下来是时候做一些实际工作了。请自行探索理论部分。
我们可以通过 Numpy 进行特征分解,它返回一个元组,其中第一个元素代表特征值,第二个元素代表特征向量:
values, vectors = np.linalg.eig(cov_matrix)
values[:5]
vectors[:5]
由此,我们可以计算每个主成分的解释方差的百分比:
explained_variances = []
for i in range(len(values)):
explained_variances.append(values[i] / np.sum(values))
print(np.sum(explained_variances), ‘\n’, explained_variances)
第一个值只是解释的方差之和,并且必须等于 1。第二个值是一个数组,表示每个主成分的解释方差百分比。
前两个主成分解释了数据中大约 96%的方差。酷毙了。
现在让我们深入到一些可视化中,从中我们可以清楚地看到应用 PCA 的目的。
形象化
以前我们已经得出结论,我们人类看不到任何高于 3 维的东西。Iris 数据集最初有 4 个维度(4 个特征),但在应用 PCA 后,我们成功地只用 2 个主成分解释了大部分差异。
现在我们将创建一个由这两个组件组成的熊猫 DataFrame 对象,以及目标类。代码如下:
projected_1 = X_scaled.dot(vectors.T[0])
projected_2 = X_scaled.dot(vectors.T[1])res = pd.DataFrame(projected_1, columns=[‘PC1’])
res[‘PC2’] = projected_2
res[‘Y’] = y
res.head()
好了,现在借助 Python 可视化库的强大功能,让我们首先以一维方式可视化这个数据集——作为一条线。为此,我们需要舍弃第二个主成分。最简单的方法是将 Y 值硬编码为零,因为散点图需要 X 轴和 Y 轴的值:
import matplotlib.pyplot as plt
import seaborn as snsplt.figure(figsize=(20, 10))
sns.scatterplot(res[‘PC1’], [0] * len(res), hue=res[‘Y’], s=200)
只要看看 Setosa 类的可分性就知道了。Virginica 和 Versicolor 更难分类,但我们仍然应该只用一个主成分就能得到大多数正确的分类。
现在让我们看看这在 2D 空间中是什么样子:
plt.figure(figsize=(20, 10))
sns.scatterplot(res[‘PC1’], [0] * len(res), hue=res[‘Y’], s=100)
太棒了。为了好玩,试着包含第三个主成分并绘制一个 3D 散点图。
对于本文来说就是这样。让我们在下一部分总结一下。
在你离开之前
到目前为止,我已经看到了关于 PCA 的纯数学或纯基于库的文章。使用 Scikit-Learn 很容易做到这一点,但是我想在这里采用一种更加手动的方法,因为缺少这样做的在线文章。
我希望你已经理解了,并且降维的“抽象概念”不再那么抽象了。
感谢阅读。
喜欢这篇文章吗?成为 中等会员 继续无限制学*。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
[## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)
主成分分析-可视化
原文:https://towardsdatascience.com/principal-component-analysis-visualized-17701e18f2fa?source=collection_archive---------54-----------------------
使用主成分分析(PCA)的数据压缩
约书亚·索蒂诺在 Unsplash 上拍摄的照片
如果你曾经上过机器学*的在线课程,你一定遇到过用于降维的主成分分析,或者简单地说,用于数据压缩的主成分分析。你猜怎么着,我也上过这样的课程,但我从来没有真正理解 PCA 的图形意义,因为我看到的都是矩阵和方程。我花了相当多的时间从各种来源理解这个概念。所以,我决定在一个地方编译它。
在本文中,我们将采用一种可视化(图形化)的方法来理解 PCA 以及如何使用它来压缩数据。假设有线性代数和矩阵的基础知识。如果你对这个概念不熟悉,就跟着做吧,我已经尽了最大努力让它尽可能简单。
介绍
如今,包含大量维度的数据集越来越常见,并且通常很难解释。一个例子可以是一个面部照片数据库,比如说, 1,000,000 人。如果每张面部照片的尺寸为 100x100,,则每张面部的数据为 10000 维(每张面部存储 100x100 = 10,000 个唯一值)。现在,如果需要 1 个字节来存储每个像素的信息,那么需要 10000 个字节来存储 1 张脸。由于数据库中有 1000 张人脸,因此需要 10,000 x 1,000,000 = 10 GB 来存储数据集。
主成分分析(PCA)是一种用于降低这种数据集的维度的技术,利用了这些数据集中的图像具有共同点的事实。例如,在由脸部照片组成的数据集中,每张照片都有像眼睛、鼻子、嘴巴这样的面部特征。我们可以为每种类型的特征制作一个模板,然后将这些模板组合起来,生成数据集中的任何人脸,而不是逐个像素地对这些信息进行编码。在这种方法中,每个模板仍然是 100×100 = 1000 维,但是由于我们将重用这些模板(基函数)来生成数据集中的每个面,因此所需的模板数量将非常少。PCA 正是这样做的。
PCA 是如何工作的?
这部分会有点技术性,所以请耐心听我说!我将用一个简单的例子来解释 PCA 的工作原理。让我们考虑下面显示的包含 100 个二维点的数据(需要 x & y 坐标来表示每个点)。
作者图片
目前,我们使用 2 个值来表示每个点。让我们用更专业的方式来解释这种情况。我们目前使用 2 个基函数,
x 为(1,0),y 为(0,1)。数据集中的每个点都表示为这些基函数的加权和。例如,点(2,3)可以表示为 2(1,0) + 3(0,1) = (2,3)。如果我们忽略这些基函数中的任何一个,我们将无法准确地表示数据集中的点。因此,两个维度都是必要的,我们不能只去掉其中一个来降低存储需求。这组基函数实际上是二维的笛卡尔坐标。
如果我们仔细观察,我们可以很好地看到数据*似于一条线,如下面的红线所示。
作者图片
现在,让我们旋转坐标系,使 x 轴沿着红线。然后,y 轴(绿线)将垂直于这条红线。让我们把这些新的 x 轴和 y 轴分别称为 a 轴和 b 轴。如下所示。
作者图片
现在,如果我们使用 a 和 b 作为这个数据集的新的集合基函数(而不是使用 x 和 y ),那么说数据集中的大部分方差沿着 a 轴不会错。现在,如果我们去掉 b 轴,我们仍然可以使用 a 轴非常精确地表示数据集中的点。因此,我们现在只需要一半的存储空间来存储数据集并准确地重建它。这正是 PCA 的工作原理。
五氯苯甲醚是一个 4 步流程。从包含 n 维的数据集开始(需要表示 n 轴):
- 找到一组新的基函数(n-轴),其中一些轴对数据集中的方差贡献最大,而其他轴贡献很小。
- 按照方差贡献的降序排列这些轴。
- 现在,选择要使用的顶部 k 轴,放下剩余的 n-k 轴。
- 现在,将数据集投影到这些 k 轴上。
在这 4 个步骤之后,数据集将从 n 维压缩到仅 k 维( k < n )。
步伐
为了简单起见,让我们取上面的数据集,并在其上应用主成分分析。所涉及的步骤将是技术和线性代数的基本知识是假设。您可以在此处查看 Colab 笔记本:
[## 主成分分析
colab.research.google.com](https://colab.research.google.com/drive/1QQcoE501NS9nPBAmlg12zQWHCT1IlI96)
第一步
由于这是一个二维数据集, n =2。第一步是找到新的一组基函数( a & b )。在上面的解释中,我们看到数据集沿着一条线具有最大方差,我们手动选择这条线作为 a 轴,垂直于它的线作为 b 轴。实际上,我们希望这个步骤是自动化的。
为此,我们可以找到数据集协方差矩阵的特征值和特征向量。由于数据集是二维的,我们将得到 2 个特征值和它们相应的特征向量。然后,2 个特征向量是两个基函数(新轴),两个特征值告诉我们相应特征向量的方差贡献。特征值的大值意味着相应的特征向量(轴)对数据集的总方差的贡献更大。
作者图片
第二步
现在,按照特征值递减对特征向量(轴)进行排序。这里,我们可以看到 a 轴的特征值比
b 轴的特征值大得多,这意味着 a 轴对数据集方差的贡献更大。
作者图片
每个轴对总数据集方差的百分比贡献可计算如下:
作者图片
上面的数字证明了 a 轴对数据集方差的贡献为 99.7%,我们可以去掉 b 轴,仅损失 0.28%的方差。
第三步
现在,我们将去掉 b 轴,只保留 a 轴。
作者图片
第四步
现在,将第一个特征向量(a 轴)整形为一个 2x1 的矩阵,称为投影矩阵。它将用于将形状为
(100,2)的原始数据集投影到新的基函数(a 轴)上,从而将其压缩到(100,1)。
重建数据
现在,我们可以使用投影矩阵将数据扩展回其原始大小,当然会有很小的方差损失(0.28%)。
重建的数据如下所示:
作者图片
请注意,沿 b 轴的方差(0.28%)丢失,如上图所示。
那都是乡亲们!
如果你成功了,向你致敬!在本文中,我们采用了一种图形化的方法来理解主成分分析是如何工作的,以及如何将其用于数据压缩。在我的下一篇文章中,我将展示如何使用 PCA 来压缩在野外(LFW)标记的人脸,由 13233 个人脸图像组成的大规模数据集。
有什么建议请留言评论。我定期写文章,所以你应该考虑关注我,在你的订阅中获得更多这样的文章。
如果你喜欢这篇文章,你可能也会喜欢这些:
[## 机器学*-可视化
理解机器学*的视觉方法
towardsdatascience.com](/machine-learning-visualized-11965ecc645c) [## 用 Pytorch 检测人脸标志点
想知道 Snapchat 或 Instagram 如何将惊人的滤镜应用到你的脸上吗?该软件检测你的关键点…
towardsdatascience.com](/face-landmarks-detection-with-pytorch-4b4852f5e9c4)
访问我的网站了解更多关于我和我的工作。