TowardsDataScience 博客中文翻译 2020(七百一十二)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

使用 InterpretML 预测酒店取消预订

原文:https://towardsdatascience.com/predicting-hotel-cancellations-using-interpretml-e4e64fefc7a8?source=collection_archive---------43-----------------------

可解释性是机器学习的一个被忽视但又必要的方面。

为了将模型部署到生产中,并使非技术受众能够理解研究结果,模型结果的可理解性或理解与准确性一样重要。

微软开发的 InterpretML 包的目的是允许增加黑盒机器学习模型的可理解性,同时保持强大的准确性性能。

下面是一个使用可解释助推机(EBM)预测客户是否会取消酒店预订的例子(1 =客户取消,0 =客户不取消)。

数据准备

H1 数据集用于训练目的,而 H2 数据集用于测试模型预测。

Antonio 等人的原始数据集和研究可以在本文末尾的参考资料中找到。以下是数据集的一个示例:

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

来源:使用数据科学预测酒店预订取消(Antonio 等人)

除了包含空值的变量(代理公司)以及 ReservationStatusDate 之外,数据集中的所有特征都包括在内。

最小最大缩放器用于将特征转换为 0 到 1 之间的比例。

假设未消除(0)的发生率比消除(1)多,SMOTE 过采样方法用于创建样本训练数据以模拟消除发生率的特征数据。

>>> counter = Counter(y_train)
>>> print(counter)Counter({0: 21672, 1: 8373})

最初, 0 有 21672 个条目,而 1 有 8373 个条目。

>>> oversample = SMOTE()
>>> x_train, y_train = oversample.fit_resample(x_train, y_train)
>>> counter = Counter(y_train)
>>> print(counter)Counter({1: 21672, 0: 21672})

0 和 1 的发生率现在相等。

可解释的助推分类器

可解释的提升分类器被用作训练模型。

>>> from interpret.glassbox import ExplainableBoostingClassifier
>>> ebm = ExplainableBoostingClassifier()
>>> ebm.fit(x_train, y_train)
>>> print("Accuracy on training set: {:.3f}".format(ebm.score(x_train, y_train)))
>>> print("Accuracy on validation set: {:.3f}".format(ebm.score(x_val, y_val)))Accuracy on training set: 0.907
Accuracy on validation set: 0.623

验证准确率达到 62%。

精确度与召回率和 f1 分数

当比较准确度分数时,我们看到在每个混淆矩阵中都提供了大量的读数。

然而,在精度召回之间存在一个特别重要的区别。

Precision = ((True Positive)/(True Positive + False Positive))Recall = ((True Positive)/(True Positive + False Negative))

这两个读数经常相互矛盾,也就是说,通常不可能在不降低召回率的情况下提高精确度,反之亦然。

对理想指标的评估很大程度上取决于所分析的具体数据。例如,癌症检测筛查出现假阴性(即表明患者没有患癌症,而事实上他们患有癌症)是一大禁忌。在这种情况下,召回是理想的衡量标准。

然而,对于电子邮件,人们可能更喜欢避免误报,例如,将一封重要的电子邮件发送到垃圾邮件文件夹,而实际上它是合法的。

f1 分数在设计一个更通用的分数时考虑了精确度和召回率。

哪个因素对预测酒店取消更重要?

从酒店的角度来看,他们可能希望更准确地识别出最终会取消预订的客户,这使得酒店能够更好地分配房间和资源。确定不打算取消预订的客户不一定会增加酒店分析的价值,因为酒店知道,无论如何,很大一部分客户最终都会坚持预订。

测试集上的性能

当在测试集(H2)上运行该模型时,以下混淆矩阵表明基于 f1 分数的总体准确性为 55% ,而取消类别的召回率为 87% (这意味着在所有取消预订的客户中,该模型正确识别了 87%):

[[14848 31380]
 [ 4437 28665]]
              precision    recall  f1-score   support 0       0.77      0.32      0.45     46228
           1       0.48      0.87      0.62     33102 accuracy                           0.55     79330
   macro avg       0.62      0.59      0.53     79330
weighted avg       0.65      0.55      0.52     79330

下面是生成的 ROC 曲线:

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

来源:InterpretML

确定了前 5 个特征。

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

来源:InterpretML

交付时间(功能 1 )、周末住宿(功能 5 )、所需停车位(功能 15 )、国家(功能 19 )和分配的房间类型(功能 23 )被确定为对客户是否会取消其酒店预订最有影响的五个因素。

让我们将混淆矩阵的准确性指标与使用相同功能运行的标准 XGBoost 模型的准确性指标进行比较:

[[12650 33578]
 [ 1972 31130]]
              precision    recall  f1-score   support 0       0.87      0.27      0.42     46228
           1       0.48      0.94      0.64     33102 accuracy                           0.55     79330
   macro avg       0.67      0.61      0.53     79330
weighted avg       0.70      0.55      0.51     79330

XGBoost 的召回率略高,为 94% ,而总体准确率保持在 55%

随机森林分类器

让我们看看 RandomForestClassifier 作为一个黑盒分类系统如何解决这个问题。

from sklearn.ensemble import RandomForestClassifier
from sklearn.decomposition import PCA
from sklearn.pipeline import Pipelinepca = PCA()
rf = RandomForestClassifier(n_estimators=100, n_jobs=-1)blackbox_model = Pipeline([('pca', pca), ('rf', rf)])
blackbox_model.fit(x_train, y_train)

让我们按照重要性顺序来看一下已确定的特性。

from interpret.blackbox import LimeTabular
lime = LimeTabular(predict_fn=blackbox_model.predict_proba, data=x_train, random_state=1)
lime_local = lime.explain_local(a_scaled[:5], b[:5], name='LIME')
show(lime_local)

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

来源:InterpretML

虽然功能的重要性与可解释的 Boosting 分类器有所不同,但所需的停车位和国家(功能 15 和 19 )仍然被确定为酒店取消的重要影响因素。

这是在测试集上生成的 ROC 曲线:

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

来源:InterpretML

以下是相关的混淆矩阵:

[[43711  2517]
 [17992 15110]]
              precision    recall  f1-score   support 0       0.71      0.95      0.81     46228
           1       0.86      0.46      0.60     33102 accuracy                           0.74     79330
   macro avg       0.78      0.70      0.70     79330
weighted avg       0.77      0.74      0.72     79330

基于 f1 分数的总体准确率要高得多,为 74%,而取消类的召回率要低得多,为 46%。在这方面,该模型在预测总体结果(取消和未取消)方面做得更好。

然而,如果我们希望具体预测哪些客户将取消他们的预订,那么可解释的提升分类器是一个更好的模型。

结论

如前所述,InterpretML 的重点是让模型结果既准确又易懂。从这个角度来看,这个库是一个非常有用的工具,它允许直观和可理解地显示结果。

非常感谢您的阅读,这个项目的 GitHub 库和相关代码可以在这里找到。

免责声明:本文是在“原样”的基础上编写的,没有担保。本文旨在提供数据科学概念的概述,不应以任何方式解释为专业建议。

参考

用线性回归预测房价

原文:https://towardsdatascience.com/predicting-house-prices-with-linear-regression-4fc427cb1002?source=collection_archive---------16-----------------------

以埃姆斯住房数据集为特色的项目

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

史蒂文·昂格曼在 Unsplash 上的照片

在学习数据科学时,许多学生将学习的第一个有监督的机器学习模型之一是线性回归。线性回归试图模拟预测变量 (X)和数字目标变量 (y)之间的线性关系。对于用模型评估的每个观察值,将目标的实际值(y)与目标的预测值(ŷ)进行比较,并且这些值的差被称为 r*esidials。*线性回归模型的目标是最小化残差平方和。多元线性回归的方程式如下所示。

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

图一。多元线性回归方程。在该等式中,β0 是 y 轴截距,x 的每个值都是预测变量。对于每个预测因子,如果所有其他特征保持不变,β系数描述了 x 增加一个单位时 y 的变化。随机误差用ε表示。

对于初学者来说,学习线性回归最常见的方法之一是建立一个模型,根据房子的具体特征来预测房子的价格。对于这个项目,使用了 Ames 住房数据集。该数据集包括 2006 年至 2010 年爱荷华州埃姆斯市出售的房屋信息。数据集中包含 2930 个观测值和 80 多个特征。

下面,我将描述我建立一个线性回归模型来预测房价的步骤。所有代码都托管在 GitHub 上。

步骤 1:导入库;获取和清理数据

埃姆斯住宅数据集是通过大会主办的 Kaggle 竞赛提供给我的。(然而,数据集也可以在这里公开。)在开始研究数据或建模之前,我导入了代码 1 中所示的库。我还清除了丢失的值,确保没有异常值,并且每个特性都是适当的数据类型。

**代码 1。**用于本项目的库

步骤 2:探索性数据分析(EDA)

之前的一篇文章中,我讨论了 EDA 对于在数据集中发现模式的重要性。对于这个项目,EDA 对于探索不同特征和目标(房屋销售价格)之间的关系同样重要。对于数字特性,我创建了一个相关矩阵,专门寻找相关系数的绝对值为 0.5 或更高的特性。这一步帮助我确定了与销售价格密切相关的几个特征,包括房子的整体质量、居住面积和车库的大小(就汽车数量和面积而言)。

代码 2 。数字特征的探索性数据分析

对于分类变量,理解不同类别和销售价格之间的关系要稍微复杂一些。总的来说,这个数据集包含超过 20 个分类特征,一些特征有超过 10 个不同的类别。为了降低模型的维度,我知道简单地对类别进行一次性编码是不可行的。为了解决这个问题,我为每个分类特征创建了条形图,以探索不同类别之间平均销售价格的差异。有趣的是,如下图所示,我开始注意到各种功能的一些类别开始聚集在一起。通过识别这些聚类,我能够设计特征来表示分类变量。

**代码 3。**具有分类特征的探索性数据分析条形图

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

**图一。**按条件 1 的销售价格。在这个用 Matplotlib 和 Seaborn 创建的条形图中,很明显,浅蓝色条形图和深蓝色条形图在销售价格和类别描述方面彼此相似。认识到这些相似性,这个具有九个类别的分类特征可以仅由两个二元特征来表示。

**代码 4。**将图 1 中的聚类转化为二元变量

第三步:模型准备

一旦我完成了对数据和工程特性的探索,就该为建模准备数据了。在这一步中,我使用pd.get_dummies()对任何感兴趣的分类变量进行虚拟化,并使用train_test_split()将我的数据分成训练集和测试集。

第四步:建模

建模是一个迭代的过程,在这个过程中,为了给我的最终模型提供信息,构建了几个模型。总共制造了六个模型。所有模型均采用 R2 评分进行评估。

**代码 5。**功能用于打印 R2 分数

模型 1: 该模型是使用DummyRegressor()创建的基线/空模型。当对每次观察的平均值进行预测时,进行研究以探索 R2 评分。

**代码 6。**虚拟回归模型

模型 2: 该模型是一个线性回归模型,使用在 EDA 过程中被识别为重要的特性。

模型 3: 在看到线性回归模型有改进的空间后,我将所有可能的特征放入一个模型中,以创建一个过拟合模型,然后可以将其正则化。

模型 4: 我尝试的第一种正则化是岭回归,它使用 L2 罚函数。

**代码 9。**缩放数据和岭回归

模型 5: 我尝试的第二种正则化是 LASSO 回归。

**代码 10。**套索回归

模型 6: 最终模型是线性回归,其特征在 EDA 和 LASSO 回归中被识别为重要。因为目标不是正态分布的,所以对于这个模型,它是对数变换的。

**代码 11。**最终线性回归模型。模型中有 47 个特征,包括:地段临街面、地段面积、整体质量、整体状况、建造年份、改造年份、砖石饰面面积、未完工地下室平方英尺、地上总房间数、车库大小(汽车)、车库面积、出售年份、总浴室数、可居住平方英尺、车库汽车 x 面积互动、邻里群 1、邻里群 2、1 层房屋(1946 年及以后)、2 层房屋(1946 年及以后)、1 层规划开发单元、靠近场外特征、靠近繁华街道、石材饰面、新销售、 房地产销售,良好的地下室,优秀的厨房,分区组 1,铺面街道,丘陵地带等高线,低土地等高线,水平土地等高线,复式,两户转换,联排别墅,联排别墅(末端单元),附属车库,地下室车库,内置车库,汽车港口,独立车库,无车库,一般外观质量,良好外观质量,一般外观质量,部分铺面车道,全铺面车道。

第五步:型号选择

在我建立了我的模型之后,我比较了训练和测试的 R2 分数来挑选最好的模型。

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

**图二。**基线、过度拟合、山脊、套索和最终模型的 R2 得分

对我来说,最好的模型与线性回归建立在 EDA 和 LASSO 中确定的特征。该模型解释了测试集销售价格变化的 87.8%。

第六步:模型评估

在选择了我的最佳模型后,我通过计算均方根误差(RMSE)和比较实际值与预测值来进一步评估它的性能。

均方根误差(RMSE)

**代码 12。**计算均方根误差

根据 RMSE 的值,线性回归模型对销售价格的预测可能会相差约 23,625.19 美元。这小于训练数据中销售价格的标准偏差的 1/3。虽然提高这个数字很好,但这是一个很好的起点。

销售价格的预测值与实际值相比如何?

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

**图三。**显示预测销售价格与实际销售价格的图表

通过将预测价格与实际价格进行对比,我发现这个模型在预测所有价格时表现得并不一样好。具体来说,该模型似乎擅长预测 90,000 美元至 225,000 美元范围内的房地产价格,但它在两个极端都做得不好。在最初的测试数据集中,75%的房屋价格在 214,000 美元或以下。由于这些情况下的训练数据不足,该模型在极端值下可能表现不佳。

结论

虽然这篇文章中创建的线性回归模型并不完美,但它能够解释大约 87.8%的房产销售价格变化,并且能够预测 23,625.19 美元以内的销售价格。对该模型残差的进一步研究揭示了该模型在预测极值方面的一个特定弱点。具体来说,预测的理想范围似乎在 90,000 美元到 225,000 美元之间。为了更好地预测这个范围之外的价格,可以对模型进行一些更改。改进的想法包括对数转换特征和将一些分类变量编码为序数。

你参加过艾姆斯住宅挑战赛吗?你有什么建议或窍门?

用 Scikit-Learn 的随机森林模型预测房价

原文:https://towardsdatascience.com/predicting-housing-prices-using-a-scikit-learns-random-forest-model-e736b59d56c5?source=collection_archive---------11-----------------------

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

图片来自 Getty Images

动机

拥有一个房价预测模型对买卖双方来说都是非常重要的工具,因为它可以帮助他们做出明智的决定。对卖家来说,它可以帮助他们确定出售房屋的平均价格,而对买家来说,它可以帮助他们找到购买房屋的正确平均价格。

目标

建立随机森林回归模型,能够预测房屋的中值。我们还将简要介绍一些探索性数据分析、特征工程和超参数调整,以提高我们的随机森林模型的性能。

我们的机器学习管道

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

图片作者:简单的机器学习管道

我们的机器学习管道可以概括为以下任务:

  1. 数据采集
  2. 数据预处理和探索性数据分析
  3. 创建基础模型
  4. 特征工程
  5. 超参数调谐
  6. 最终模型培训和评估

第一步:数据采集

我们将使用波士顿住房数据集*:https://www.kaggle.com/c/boston-housing/data。*

#Importing the necessary libraries we will be using%load_ext autoreload
%autoreload 2
%matplotlib inlinefrom fastai.imports import *
from fastai.structured import *from pandas_summary import DataFrameSummary
from sklearn.ensemble import RandomForestRegressor
from IPython.display import displayfrom sklearn import metrics
from sklearn.model_selection import RandomizedSearchCV#Loading the DatasetPATH = 'data/Boston Housing Dataset/'
df_raw_train = pd.read_csv(f'{PATH}train.csv',low_memory = False)
df_raw_test = pd.read_csv(f'{PATH}test.csv',low_memory = False)

步骤 2:数据预处理和探索性数据分析(EDA)

2.1 数据缺失和异常值的检查和处理。

df_raw_train.info

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

作者图片

了解原始数据:

根据上面的原始训练数据集:

(a)共有 14 个变量(13 个自变量—特征和 1 个因变量—目标变量)
(b)数据类型要么是整数要么是浮点数
© 不存在分类数据
(d)我们的数据集中没有缺失值

2.2 作为 EDA 的一部分,我们将首先尝试确定因变量(MDEV)的分布。

#Plot the distribution of MEDVplt.figure(figsize=(10, 6))
sns.distplot(df_raw_train['MEDV'],bins=30)

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

作者图片:MEDV 分布

MEDV 的值遵循正态分布且平均值约为 22。右边有一些异常值。

2.3 接下来,试着确定:
(i)自变量本身
(ii)自变量与因变量
之间是否有相关性

为此,我们来做一个关联热图。

# Plot the correlation heatmapplt.figure(figsize=(14, 8))
corr_matrix = df_raw_train.corr().round(2)
sns.heatmap(data=corr_matrix,cmap='coolwarm',annot=True)

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

作者图片:相关热图

(i)独立变量之间的相关性 :
我们需要寻找多重共线性的特征(即彼此相关的特征),因为这将影响我们与独立变量的关系。

注意到 RADTAX 彼此高度相关(相关分数:0.92),而有几个特征彼此稍微相关,相关分数约为 0.70 (INDUS 和 TAX、NOX 和 INDUS、AGE 和 DIS、AGE 和 INDUS)。

(二)自变量与因变量之间的相关性 :
为了让我们的回归模型表现良好,理想情况下我们需要选择那些与我们的因变量(MEDV)高度相关的特征。

我们观察到 RMLSTAT 都与和 MEDV 相关,相关系数分别为 0.66 和 0.74。这也可以通过散点图来说明。

#Scatter plot to observe the correlations between the features that are highly correlated with MEDVtarget_var = df_raw_train['MEDV']plot1 = plt.figure(1)
plt.scatter(df_raw_train['RM'],target_var)
plt.xlabel('RM')
plt.ylabel('MEDV')plot2 = plt.figure(2)
plt.scatter(df_raw_train['LSTAT'],target_var)
plt.xlabel('LSTAT')
plt.ylabel('MEDV')

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

作者图片:RM 与 MEDV 散点图

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

作者提供的图片:RM 与 LSTAT 的散点图

从上面的散点图来看:
i) MEDV 随 RM 线性增加。这是有道理的,因为我们预计随着房间数量的增加,房子的中值价格会更贵。MEDV 随 LSTAT 线性下降。这也是有道理的,因为我们可以预期,在社会地位较低的地方,房子的中值价格通常会更便宜。

步骤 3:创建基础模型

停下来。在我们创建我们的基本随机森林模型之前,选择一个合适的评估标准是非常重要的。

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

图片来自 imgflip.com

3.1 选择正确的评估指标
选择正确的评估指标将有助于我们评估我们的模型性能是否良好。对于回归问题,最常用的评估指标是均方根误差(RMSE)均方根逻辑误差(RMLSE)

RMSE :这是我们的模型预测值和实际值之间的平方差。

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

均方根误差公式

其中 y:预测值,y:实际值

RMSLE :它是我们的模型预测的对数和实际值的对数之间的平方差的度量。

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

均方根逻辑误差

其中 y:预测值,y:实际值

RMSLE 可能是一个更好的评估指标,因为(1)它足够稳健,可以处理我们在数据集中看到的异常值(2) RMSLE 会因低估实际值而招致更大的损失。如果我们站在卖家的角度,我们不想低估价格,因为这会导致损失。然而,对于这个项目,我们不会站在任何一方,我们将选择 RMSE 作为评估指标,因为我们将使用不受异常值影响的随机森林模型。

3.2 创建我们的基础随机森林模型

下一步是首先创建一个基本模型,不进行任何特征工程和超参数调整。在我们完成特征工程和超参数调整之后,我们将使用这个模型的性能作为比较的基准。

我们选择的机器学习模型是随机森林回归模型,原因如下:

  1. 随机森林模型需要最少的数据准备。它能够轻松处理分类、数字和二进制特征,无需缩放或标准化。
  2. 随机森林模型可以帮助我们执行隐含的特征选择,因为它们提供了重要特征的良好指标。
  3. 随机森林模型不受离群值的影响,离群值存在于我们的数据中,它们完全忽略了统计问题,因为不像其他机器学习模型在标准化后表现得更好。

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

照片摄于 frontiersin.org

我们想创建一些有用的函数:

# A function to split our training data into a training set to train our  model and a validations set, which will be used to validate our model.def split_vals(a,n):
    return a[:n],a[n:]# Functions that will help us calculate the RMSE and print the score.def rmse(x,y):
    return math.sqrt(((x-y)**2).mean())def print_score(m):
    res =[rmse(m.predict(X_train),y_train),rmse(m.predict(X_valid),y_valid),m.score(X_train,y_train),m.score(X_valid,y_valid)]
    if hasattr(m,'oob_score_'):res.append(m.oob_score_)
    print(res)

进一步拆分我们的训练数据—用于训练随机森林模型的训练数据和用于验证模型性能的验证数据。

n_valid = 100
n_train = len(df_raw_train)-n_valid
X_train,X_valid = split_vals(df_raw_train.drop('MEDV',axis=1),n_train)
y_train,y_valid = split_vals(df_raw_train['MEDV'],n_train)
X_test = df_raw_test

在没有特征选择和超参数调整的情况下创建和拟合我们的随机森林模型**。**

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

从我们的基本随机森林模型中,我们已经得到了一个非常不错的结果,其中训练 RMSE1.394 ,而验证 RMSE3.021 。但是,请注意,我们的模型似乎更适合,因为验证 RMSE 比训练 RMSE 大约高 3 倍。

因此,击败的基线分数是验证 RMSE 3.021** !**

步骤 4:特征工程

特征工程和超参数调整是机器学习管道中的基本步骤

4.1 确定重要特征
我们数据中的特征直接影响着我们的随机森林模型及其实现的结果(即,我们准备和选择的特征越好,我们实现的最终结果就越好!).因此,我们将通过确定哪些特性在之前的基础模型中被认为是重要的,来探索和微调我们的随机森林模型。

def feat_importance(m,df_train):
    importance = m.feature_importances_
    importance = pd.DataFrame(importance,index=df_train.columns,columns=["Importance"])
    return importance.sort_values(by=['Importance'],ascending=False)importance = feat_importance(m,X_train)
importance[:]

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

分级特征重要性系数

importance.plot(kind='barh')

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

分级特征重要性条形图

我们观察到在预测 MDEV 时最重要的特征是 LSTATRM 。回想一下,之前发现这两个参数与 MDEV 高度相关。

4.2 丢弃不重要的特征
下一步将尝试丢弃重要性系数小于 0.01 的特征,并使用它再次为我们的随机森林建模,以查看我们的预测结果是否有改进。

#Discarding features with feature coefficients less than 0.01to_keep = importance[importance['Importance'] > 0.01].index
df_raw_train_keep = df_raw_train[to_keep].copy()
df_raw_test_keep = df_raw_test[to_keep].copy()#Splitting data into training and validation setX_train,X_valid = split_vals(df_raw_train_keep,n_train)# Fitting our Random Forest Model after discarding the less important features.

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

我们的随机森林模型在移除了一些冗余功能(即 6 个功能)后,表现稍好!).我们已经获得了确定因变量 MEDV 的前 9 个最重要的特征(LSTAT、RM、DIS、CRIM、TAX、NOX、PTRATIO、NOX 和 AGE)。

接下来,让我们看看对于我们的随机森林模型来说重要的特性的等级是否有任何变化。

def feat_importance(m,df_raw_train_keep):
    importance = m.feature_importances_
    importance =
pd.DataFrame(importance,index=df_train.columns,columns=["Importance"])
    return importance.sort_values(by=['Importance'],ascending=False)importance

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

去除冗余特征后的分级特征重要性系数

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

移除冗余特征后的分级特征重要性条形图

我们观察到,在先前移除冗余特征之后,最重要的特征仍然是 LSTAT 和 RM。我们想探究逐一删除剩余的每个功能会如何影响我们的总体得分。

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

请注意,删除 RM、LSTAT、DIS 和 CRIM 会导致更差的验证 RMSE,而删除 AGE 和 PTRATIO 会给我们一个稍好的分数。因此,在运行最终模型之前,我们将进一步从数据集中删除 AGEPTRATIO

4.3 去除独立要素间的多重共线性

在 2.3(i)中,有一些相互关联的特征。为了提高模型的性能,我们最好是移除特征之间的多重共线性

为了了解这些特征是如何相互关联的,我们可以绘制一个树状图。

#Dendogram plotfrom scipy.cluster import hierarchy as hc
corr = np.round(scipy.stats.spearmanr(df_raw_train_keep).correlation,4)
corr_condensed = hc.distance.squareform(1-corr)
z = hc.linkage(corr_condensed,method='average')
fig = plt.figure(figsize=(16,10))
dendogram = hc.dendrogram(z,labels=df_raw_train_keep.columns,orientation='left',leaf_font_size=16)
plt.show()

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

重要特征之间的树状图

从树状图中,在排名方面我们可以看到,没有一个特征是衡量同样的东西。排名最接近的是 NOX 和 CRIM。

如果在排名方面存在非常接近的特征,下一步将是移除这些特征,一次移除一个,看看我们的模型是否可以进一步简化,而不影响我们的验证 RMSE 分数。然而在这种情况下,我们不需要。

步骤 5:超参数调整

我们已经到了最后一步(万岁!)才能建立最终的随机森林模型。

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

图片来自 tech-quantum.com

超参数调整是一个迭代过程 s,由此我们选择超参数的最佳配置,这为我们提供了最佳模型性能输出。对于随机森林模型,我们将重点调整 3 个超参数:

(1) n_estimators :在我们的随机森林中创建和推广的树的数量。很可能,我们创建的树越多越好,因为这将使我们能够对更多的数据集进行采样,并帮助我们更好地进行归纳。然而,会有这样一种情况,即以计算能力为代价,增加树的数量只会对我们的验证 RMSE 产生非常小的改变。

(2) min_samples_leaf :表示叶子节点中的样本数。每当我们将 min_sample_leaf 加倍时,我们就从树中删除了一层,并将叶节点的数量减半。因此,增加 min_samples_leaf 的结果是,我们的每个叶节点内将有多个样本,因此当我们计算该叶节点的平均值时,它将更加稳定,尽管我们将获得稍小的深度和较少的节点数。因此,尽管每棵树的预测性和相关性都不会降低,但我们的模型应该能够更好地概括并防止过度拟合。

(3) max_features :表示每次分割要考虑多少个特征。

为了优化和搜索最佳超参数,我们将使用随机网格搜索方法

n_estimators = [int(x) for x in np.arange(start = 10, stop = 2000, step = 10)]
max_features = [0.5,'auto', 'sqrt','log2']
min_samples_leaf = [1, 2, 4]
bootstrap = [True, False]
random_grid = {'n_estimators': n_estimators,
               'max_features': max_features,
               'min_samples_leaf': min_samples_leaf,
               'bootstrap': bootstrap}# First create the base model to tune
m = RandomForestRegressor()
# Fit the random search model
m_random = RandomizedSearchCV(estimator = m, param_distributions = random_grid, n_iter = 100, cv = 3, verbose=2, random_state=42, n_jobs = -1)
m_random.fit(X_train, y_train)
m_random.best_params_

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

从我们的随机网格搜索中,我们发现我们的随机森林模型的最佳超参数是上面那些。

第六步:最终模型

最后一步——构建我们的最终模型。为此,我们将放弃前面讨论过的年龄和比率特性。

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

图片来自 gurutzeunzalu.blogspot.com

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

我们已经获得了 2.847 的验证 RMSE 分数,这比我们原来的基础模型验证 RMSE 分数 3.021** 要好!**

另外,****最终验证 R 分0.87 ,这比基础款验证 R 分0.85 要好。R 分数告诉我们我们的模型能够在多大程度上解释数据集中的变化。得分为 0.87 表明我们的模型可以解释数据集中 87%的变化。

因此,我们看到简单的最终模型即使具有较少的输入特性也表现得更好!

额外的一步:部分独立

虽然我们已经创建了一个更好的模型,让我们后退一步,进一步探索我们的结果。

之前,我们观察到房价上涨中值(MDEV)和房间数量(RM) 之间存在线性关系。****

让我们试着做一个 ggplot。

from pdpbox import pdp
from plotnine import *
ggplot(df_raw_train, aes('RM', 'MEDV'))+stat_smooth(se=True, method='loess')

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

ggplot

基于上面的 gg 图,我们观察到 RM 和 MEDV 之间的关系是而不是我们所期望的。例如,人们通常会认为房价会随着房间数量的增加而上涨。然而,我们看到 4 房和 5 房之间的价格下降,同样 8 房和 9 房之间的价格下降。

这里的问题是我们正在查看单变量关系并且在单变量图中丢失的特征之间有许多相互作用**。例如,为什么 5 间房的价格比 4 间房的价格低,而 6 间房的价格和 4 间房的价格差不多?**

因此,要找到 RM 和 MEDV 之间的真实关系,我们需要做一个部分独立图**(即假设所有其他特征相同,房子的价格如何随房间数量而变化)来查看真实关系。**

def plot_pdp(feat,clusters=None,feat_name=None):
    feat_name = feat_name or feat
    p = pdp.pdp_isolate(m,X_train,feat)
    return pdp.pdp_plot(p,feat_name,plot_lines=True,cluster=clusters is not None,n_cluster_centers = clusters)
plot_pdp('RM')

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

PDP 图

从上面的部分依赖图(PDP)中注意到,在去除所有其他外部因素后,我们观察到 RM 和 MEDV 之间的关系几乎是一条直线(即大致线性),这正是我们所预期的。黄线代表所有交易的平均 MEDV。

现在我们来探讨 LSTAT 和 RM 是如何影响房价中位数的。

feats = ['LSTAT','RM']
p = pdp.pdp_interact(m,X_train,feats)
pdp.pdp_interact_plot(p,feats)

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

因此,查看 PDP 图,我们可以有把握地得出结论:房间数量(RM)线性影响中值房价(MEDV)。人口的状况反过来影响着 MEDV。

最后的想法和下一步

我们建立了一个随机森林模型,其验证 RMSE 分数为 3.021** 和验证 R 分数为 0.87 。**

我们还从我们的随机森林模型中确定了影响关键特征**。波士顿的中值房价(MEDV)(1) LSAT :低人口状况的百分比 (2) RM :每所住宅的平均房间数 (3) NOX :氮氧化物浓度 (4) CRIM :城镇人均犯罪率。**

我们建造的最终模型远非完美。例如,观察我们最终模型中的培训 R 分数0.87验证 R 分数高出0.98**。这表明最终模型能够解释训练数据中 98%的变化,而仅解释验证数据中 87%的变化(即最终模型仍然过度拟合训练数据,并且没有将 以及推广到验证数据)。**

解决过度拟合的一个简单方法是尝试增加数据集的大小来训练我们的模型。目前,我们的数据集中只有 406 个条目,根本不够用

祝贺并感谢你坚持到最后。我真诚地希望你学到了新的东西!快乐学习!😬

用 R 预测房价

原文:https://towardsdatascience.com/predicting-housing-prices-with-r-c9ec0821328d?source=collection_archive---------17-----------------------

实践教程

使用 ARIMA 模型和 Case-Shiller 指数以及一些创造性的 R 程序,我们可以预测下一年的全国房价。这怎么可能呢?!让我们来了解一下!

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

照片由亚历克斯·瓦西Unsplash 上拍摄

目标

  1. 预测下一年美国房价
  2. 获得使用真实经济数据的经验
  3. 将数据可视化
  4. 理解数据的基本假设
  5. 了解使用 ARIMA 方法的预测建模

介绍

这个项目是为两种人设计的——对代码感兴趣的人和对房地产市场感兴趣的人。虽然这些概念将通过技术定义和代码示例来介绍,但要了解房价、预测模型或经济数据的周期性本质,并不需要理解代码。

对于那些只是阅读的人来说,尽量不要被代码所困扰。沿途寻找图像和情节,因为我会尽可能简单地用简单的英语解释正在发生的事情以及为什么这对我们很重要。

对于那些跟随代码的人来说,我假设您可以设法设置一个 R 环境。我的示例将使用 RStudio 在 Mac 上的 R Markdown 文件中本地运行,但任何其他本地或基于云的方法也应该工作得很好。

你可以从我的 GitHub 这里获得所有文件。

让我们投入进去吧!

获取数据

获取数据最简单的方法是从我的 GitHub 这里下载文件,或者去 FRED(美联储经济数据)为自己下载 S & P/Case-Shiller 20 个城市房价销售对计数(SPCS20RPSNSA) 数据[1]。如果你是从 FRED 那里下载的,就把它作为一个 CSV 文件来使用。

出于各种原因,我们在这个项目中使用了 20 个城市的变量,但主要是因为它没有经过季节性调整,并能很好地反映房地产市场每月的变化。

数据的原始来源来自标准普尔基于一个指数,该指数最初由耶鲁大学教授、2013 年诺贝尔经济学奖得主罗伯特·希勒[2][3]和卡尔·凯斯(Karl Case)共同开发,后者获得了哈佛大学经济学博士学位,并在韦尔斯利大学任教数十年[4]。看看最后参考文献中的链接,了解更多关于席勒博士和凯斯博士的信息。

代码

加载库

第一项任务是加载一些我们需要完成项目的库。为此,我们所需要的就是预测序列潮汐库。单击上一句中的名称可获得每个文档的链接!

代码如下:

# If these libraries are not installed on your machine, you can use the install.packages("name_of_package") command and library(name_of_package) to do the same thing as the require() function I am using below. I just like require because it is a single line of code :)# Import Libraries
require(forecast)
require(tseries)
require(tidyverse)

导入数据

接下来,我们需要导入数据。我使用的是直接从 FRED [1]下载的 CSV(逗号分隔值)文件。您还可以通过不同的方式阅读 Excel 格式,或者通过获得加分并从 FRED API 中提取来使用 Excel 格式。对于这个,它只有几千字节,所以本地 CSV 就可以了。确保数据与您的 R 或 R Markdown 文件在同一个目录下,以便使用 my code,或者如果数据在不同的位置,则从其确切的文件路径导入数据

MAC 用户注意:不要打开带数字的 CSV 文件。如果你这么做,r 将很难解码数据。下载的时候忍住双击的冲动。如果您这样做,您将需要删除该文件并下载一份新的副本,而不要在 Numbers 中打开它。

代码如下:

# Import Data
CaseShiller <- read.csv("SPCS20RPSNSA.csv")# Check data import
head(CaseShiller)

以下是输出结果:

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

凯斯席勒索引的前 6 行。数据由标准普尔和圣路易斯美联储银行提供(美联储经济数据)。参考文献中的引文[1]。

将数据转换为时序对象

为了做 ARIMA 模型(我们马上就要到了!),我们需要用 ts() 函数将原始数据转换成时间序列对象。通过一点数据争论,我们可以使列名更好一些,简化数据结构,并使我们的日期更容易配合。做这件事的方法不止一种,但这是我知道的最简单的方法。

代码如下:

# Change name of data column to Units
names(CaseShiller)[2] <- "Units"# Creates a Units Object as intermediate to transform into time series
CSUnits <- CaseShiller$Units# Creates Time Series Object that starts in January 2000 with a monthly frequency
tCaseShiller <- ts(CSUnits, start = c(2000, 1), frequency = 12)# Check Data Transformation
tCaseShiller

以下是输出结果:

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

为 Case-Shiller 索引创建的时序对象的表。数据由标准普尔和圣路易斯美联储银行提供(美联储经济数据)。参考文献中的引文[1]。

那么,为什么我们需要将数据转换成时间序列对象呢?这不是和我们开始的时候一样的数据吗?

嗯,是和不是。当创建 ARIMA(自回归综合移动平均),只有一个变量被使用[5]。ARIMA 模型使用真实值,然后将数据滞后一段时间以创建残差,残差是衡量现实和预期之间差异的值[5]。当处理这样的数据时,创建一个时间序列对象是让单变量数据与 R [5]合作的最佳方式。

ARIMA 模型是复杂的统计工作。他们有 pdq 值与之相关联[5]。通常会写成这样:ARIMA(p,d,q) [5]。

p 值处理模型的自回归部分,通常处理模型的线性部分如何与前面的点结合的顺序[5]。

d 值处理模型中出现差异的次数,这有助于使数据随着时间的推移更加稳定,不同的值以不同的方式影响输出[5]。

q 值处理模型的移动平均部分,通常处理误差如何以线性方式与模型交互[5]。

为 ARIMA 模型确定正确的 pdq 值是一门艺术和科学,我们需要检查一些自相关数并做一些实验,但我们在这里学习并将使用自动选择功能,如下一段代码所示[5]。

要记住的最后一个想法是,ARIMA 模型不喜欢方差很大的数据,所以需要做一些工作,这通常涉及到对数变换[5]。我们以后再担心那个,所以你会明白我的意思的。

ARIMA 模型创建

现在是有趣的部分!我们可以使用 R 中的 auto.arima() 函数来替我们完成这项艰巨的工作。

代码如下:

# Automatically create ARIMA model
fit <- auto.arima(tCaseShiller)
fit

以下是输出结果:

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

R 中 auto.arima()函数对时间序列 Case-Shiller 数据的结果

根据我的理解,当自动函数给出两组 pdq 值时,这意味着它们给出了相同的结果,这种情况确实会不时发生,取决于数据如何通过建模过程计算出来[5]。

我们可以再花一个小时来详细说明这里的每一点统计数据,但故事的重点是我们希望我们的模型少出错。为此,我们将重点关注 AIC(赤池的信息标准)值,并使其尽可能小。

模型精度

通过测量模型准确性,我们可以得到各种统计方法来衡量模型错误程度。

代码如下:

# Check Accuracy
accuracy(fit)

以下是输出结果:

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

时间序列 Case-Shiller 数据的第一个 auto.arima 拟合精度

如果你擅长统计学,你会认识这些术语。就我们的目的而言,大数值是不好的,小数值是好的。我们稍后将回到这些值。如果你不知道这些是什么意思,试着在谷歌上搜索“统计在这里插入缩写”来获得更完整的定义。

制作并绘制我们的第一个预测

通过创造性地使用 plot()forecast() 函数,我们可以用预测值绘制原始数据,预测值周围有 80%和 95%的误差阴影。我选择预测 12 个周期,因为我们有月度数据,我们可以真正看到该模型在一年的时间内是否有意义。

代码如下:

# Create a Simple Plot with a forecast for the next year
plot(forecast(fit, 12), xlab = "Date", ylab = "Units", main = "ARIMA Forecast for Case-Shiller Index")

以下是输出结果:

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

基于凯斯席勒指数 ARIMA 模型的历史值和预测值图。数据由标准普尔和圣路易斯美联储银行提供(美联储经济数据)。参考文献中的引文[1]。

如果您想查看带有置信区间的预测值表,请使用以下代码:

# Get table of forecasted values. Check back next year to see whether this was close!
pred_values <- forecast(fit, 12)
pred_values

这是表格的前 10 行:

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

凯斯席勒指数 R 中 ARIMA 模型的预测值和置信带数。

很神奇,对吧?!蓝线是下一年的预测值。较暗的阴影区域是 80%置信区间,较亮的阴影区域是 95%置信区间。

看起来很棒,但是这是什么话?如果我们打算用它来计算如何投资,我们真正能看到的是它上下波动,我们不知道价格会比往年更高、更低还是完全一样。这是一个好的开始。我们继续吧。

检查我们的假设

我们有一个模型,但我们如何知道我们甚至可以开始信任它?首先,我们需要检查数据是否正常(或者至少足够正常!)分布式[5]。其次,我们需要看看我们是否有任何有意义的自相关[5]。

为此,我们将使用 Q-Q 图来观察常态。简而言之,如果我们几乎所有的点都在这条线上或相对接近这条线,我们就有正常的数据[5]。对于 ARIMA 模型和一般的数据科学来说,正常的数据意味着我们的生活要容易得多。

对于自相关,我们将使用 Box-Ljung 检验。自相关对我们的目的是不利的。这意味着我们的数据本质上是一个逻辑同义反复,下一条数据有它的价值,因为前一条数据说那是它应该被估价的[5]。自相关有点像从 1 到 10 的整数序列,表示 2 跟随 1,3 跟随 2,4 跟随 3,等等。因为这就是模式。A 是 A,因为 A 是 A,我们不想用它来预测未来。这里没有帮助。

让我们来看看一个简单的方法来验证我们的假设是有根据的。

代码如下:

# Check assumptions of normality & Autocorrelation
qqnorm(fit$residuals)
qqline(fit$residuals)
Box.test(fit$residuals, type = "Ljung-Box")# Has high p-value, so autocorrelations not significantly different than 0
# There are a few possible outliers, but most of the data is pretty normally distributed

以下是输出结果:

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

我们第一个 ARIMA 模型的 Q-Q 图

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

我们的第一个 ARIMA 模型的 Box-Ljung 测试输出

这里的生活真好!我们的数据在 Q-Q 图上看起来很好,所以我们得出结论这是正常的[5]。对于 Box-Ljung 检验,我们有一个大的 p 值,表明我们的自相关与 0 没有显著差异[5]。如果这里的 p 值为 0.05 或更小,我们将至少 95%确定我们的数据不同于 0,这意味着自相关可能存在[5]。谢天谢地,这里一切正常!

时间序列数据的对数变换

目测数据,看起来我们的数据是季节性的。我们需要做一个季节分解来证实这是真的。然而,强烈建议使用对数转换数据[5]。所以让我们开始吧!

代码如下:

# Transform time series to log scale
ltCaseShiller <- log(tCaseShiller)# check it worked
head(ltCaseShiller)

以下是输出结果:

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

对数变换我们的时间序列数据的对数的 ARIMA 模型

季节性分解

做一个季节性分解可以去除每年的变化,从而发现数据是真的季节性的还是看起来像是季节性的[5]。我们可以看到去除所有噪声后的数据的季节变化和总体趋势[5]。让我们看看那个。

代码如下:

# Create new fit on log scale series for seasonal decomposition
fit2 <- stl(ltCaseShiller, s.window = "period")# Plot Seasonal Decomposition
plot(fit2, main = "Seasonal Decomposition of log(Case-Shiller Units)")

以下是输出结果:

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

凯斯席勒指数的季节性分解。数据由标准普尔和圣路易斯美联储银行提供(美联储经济数据)。参考文献中的引文[1]。

我们可以清楚地看到,这些数据始终具有很强的季节性,并且具有长期的涨跌趋势。

按年份的季节性绘图

让我们更仔细地看看这个问题,并在我们的数据集中绘制每年的指数。作为 tidyverse 的一部分,ggplot2 库可以通过使用 ggseasonplot() 函数来帮助使用。

代码如下:

# Create a Season Plot
ggseasonplot(tCaseShiller, year.labels = TRUE, col = rainbow(20))

以下是输出结果:

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

凯斯席勒指数的季节曲线图。数据由标准普尔和圣路易斯美联储银行提供(美联储经济数据)。参考文献中的引文[1]。

我们可以很清楚地看到,记录在案的每一年都遵循同样的模式。冬天价格低,夏天价格高。听起来差不多。

循环返回以比较模型

还记得我说过 ARIMA 模型喜欢波动性较小的数据吗?让我们看看当我们使用我们的日志转换数据时会发生什么。我们已经讨论了这些步骤,所以让我们用新数据快速地重复一遍这个过程,以比较结果。

创建新的 ARIMA 模式

自动创建我们的新 ARIMA 模型的代码与之前完全相同,除了我们将数据对象的名称改为 log 转换的名称。

代码如下:

# Automatically create ARIMA model
fit3 <- auto.arima(ltCaseShiller)
fit3

以下是输出结果:

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

使用对数转换数据的新 ARIMA 值

那么这里有什么不同呢?嗯,这次我们有不同的 pdq 值,以及非常不同的 AIC 值。未经对数变换的原始数据的 AIC 约为 4500。现在我们在-966。正负并不重要,所以我们唯一关心的是得到绝对值最小的 AIC 值[5]。这意味着我们基于对数转换数据的模型更适合[5]。

再次检查准确性

让我们再来看看准确度分数。原始精度在顶部,新精度在底部。请记住,较低的数字意味着模型错误较少。你注意到了什么?

代码如下:

# Check Accuracy
fitAccuracy <- data.frame(accuracy(fit))
fitAccuracy2 <- data.frame(accuracy(fit3))fitAccuracyFinal <- rbind(fitAccuracy, fitAccuracy2)
fitAccuracyFinal

以下是输出结果:

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

两种 ARIMA 模型的误差度量精度表

我注意到,当使用对数转换数据时,几乎每个误差的统计测量都至少比原始数据小一个数量级。这是一个好迹象!

绘制测井转换数据

就像之前一样,让我们看看一个基本的情节来形象化的预测。当然,y 轴是以对数为单位的,但是你也会有同样的想法。

代码如下:

# Create a Simple Plot with a logged forecast for the next year
plot(forecast(fit3, 12), xlab = "Date", ylab = "Units", main = "ARIMA Forecast for Case-Shiller Index")

以下是输出结果:

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

基于凯斯席勒指数 ARIMA 模型的历史和对数转换预测值图。数据由标准普尔和圣路易斯美联储银行提供(美联储经济数据)。参考文献中的引文[1]。

需要明确的是,这个模型中仍然存在大量的不确定性,但这里的要点是,它给了我们一组不同的值,可能更接近真实的中心趋势。

最终预测结果

为了轻松获得最终表格,我们可以将预测放入数据框中,使用 exp() 函数,通过将输出缩放回对数转换数据的正常值,然后将预测数字合并到带有适当标签的数据框中,从而消除对数值。

代码如下:

# Get table of forecasted values. Check back next year to see whether this was close!
# Original Data
pred_values <- data.frame(forecast(fit, 12))# Log transformed data
pred_values2 <- data.frame(forecast(fit3, 12))
pred_values2[,1:5] <- exp(pred_values2[,1:5])# Merge forecast predictions!
mergedDF <- data.frame(Date = rownames(pred_values), Original_Data_Forecast = pred_values$Point.Forecast, Log_Transformed_Data_Forecast = pred_values2$Point.Forecast, Difference = round(pred_values$Point.Forecast - pred_values2$Point.Forecast, 2))
mergedDF

以下是输出结果:

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

原始数据和对数转换数据预测的最终结果

对于最终的解释,模型通常是接近的。在接下来的几个月里,他们的预测更加接近 4-10 个月的时间范围。这是有道理的,因为不确定性源于多种原因。

结论

希望这篇文章有趣,有娱乐性,有教育意义。我认为使用真实数据用代码探索想法是学习和变得更好的好方法。这个项目和代码源自我的正规教育背景,是经济理念和编程的良好结合。我认为它也很好地强调了经济的某些部分既可以是周期性的,也可以是稳定的。

如果您有任何改进建议或未来要探索的主题,请联系我们。

参考

[1] S&P 道琼斯指数有限责任公司,S&P/凯斯席勒 20 个城市房价销售对计数[SPCS20RPSNSA],从圣路易斯美联储银行的弗雷德检索;https://fred.stlouisfed.org/series/SPCS20RPSNSA, 2020 年 10 月 15 日。

[2] R .席勒,在线数据罗伯特·席勒 (2018),【http://www.econ.yale.edu/~shiller/data.htm】T2

[3]罗伯特·J·希勒——传记。NobelPrize.org。诺贝尔媒体 AB 2020。周四。2020 年 10 月 15 日。https://www . nobel prize . org/prices/economic-sciences/2013/shiller/biographical/

[4]p·鲍尔、卡尔·凯斯|美国经济学家 (2020)、https://www.britannica.com/biography/Karl-Case

[5] R. Kabacoff, R 在行动(第二版。) (2015),纽约州谢尔特岛:曼宁出版公司

基于支持向量机的人力资源流失预测

原文:https://towardsdatascience.com/predicting-hr-attrition-using-support-vector-machines-d8b4e82d5351?source=collection_archive---------38-----------------------

学习按照最佳实践训练 SVM 模型

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

凯文·Ku 在 Unsplash 上的照片

继我之前的帖子之后,我将介绍我们如何在真实世界数据集上使用 python 和 Scikit-Learn 来应用支持向量机。这些数据取自最近由 IIT、古瓦哈蒂在 Kaggle 上举办的 InClass hackathon,作为他们夏季分析 2020 顶点项目的一部分,你可以从这里下载。

在这篇文章中,你会看到训练和调音 SVM 并让他们为你的问题陈述工作是多么容易。用这个我在黑客马拉松中排名第 29 位(前 4%),只做了很少的预处理和特征工程。

在我们继续之前,您必须对 SVM 的工作方式有一个直观的了解。我建议你仔细阅读我之前的文章,深入了解这个算法。

[## 解码支持向量机

直观理解支持向量机的工作原理

towardsdatascience.com](/decoding-support-vector-machines-5b81d2f7b76f)

现在假设你理解支持向量机背后的理论…

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

来源: imgflip

问题陈述

随着新冠肺炎不断释放它的浩劫,世界继续被推入大经济衰退的危机,越来越多的公司开始削减他们表现不佳的员工。公司解雇成百上千的员工是当今典型的头条新闻。裁员或降薪是一个艰难的决定。这一点需要非常小心,因为对表现不佳的员工的识别不准确可能会破坏员工的职业生涯和公司在市场上的声誉。

**目的:**根据给定的员工历史数据,预测员工流失情况。

导入所有必需的包

**import** **pandas** **as** **pd**
**import** **numpy** **as** **np**
**import** **matplotlib.pyplot** **as** **plt**
**from** **sklearn.model_selection** **import** StratifiedKFold
**from** **sklearn.compose** importmake_column_transformer
**from** **sklearn.ensemble** **import** RandomForestClassifier
**from** **sklearn.model_selection** **import** GridSearchCV,RandomizedSearchCV
**from** **sklearn.svm** **import**  SVC
**from** **sklearn.decomposition** **import** PCA
**from** **xgboost** **import** XGBClassifier
**from** **sklearn.model_selection** **import** cross_val_score
**from** **sklearn.preprocessing** **import** StandardScaler,RobustScaler
**from** **sklearn.preprocessing** **import** OneHotEncoder,LabelEncoder
**from** **sklearn.pipeline** **import** make_pipeline
pd.set_option('display.max_columns', 500)
pd.set_option('display.max_rows', 1000)

加载数据集

为了保存原始的培训数据,我制作了一份副本。

training = pd.read_csv('train.csv')
train_data = training.copy()
test_data = pd.read_csv('test.csv')

基础 EDA

train_data.info()

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

图 1

我们有 1628 个观察值和 29 个特征,其中 22 个是整数,7 个是对象。一些整数数据类型特征也可能是分类的。我们必须预测自然减员,它可以是 0 或 1(如果员工离开公司,则为 1)。

train_data.head()

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

图 2

让我们打印出一些变量的统计数据

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

图 3

这里要注意的奇怪的事情是行为的标准差为 0,均值=min=max = 1。这意味着对于所有的观察,该列的值都是 1,所以我们将删除它。我们还将删除 Id ,因为它对所有员工都有唯一的值。

train_id = train_data.Id
train_data = train_data.drop(['Behaviour','Id'],axis = 1)

test_id = test_data.Id
test_data = test_data.drop(['Behaviour','Id'],axis = 1)

进一步研究后,我发现特性 Pperformance rating只有两个值,3 或 4,所以我将它们分别映射到 0 和 1。

train_data['PerformanceRating'] = train_data['PerformanceRating'].apply(**lambda** x: 0 **if** x == 3 **else** 1)
test_data['PerformanceRating'] = test_data['PerformanceRating'].apply(**lambda** x: 0 **if** x == 3 **else** 1)

让我们检查我们的目标变量消耗的分布。

train_data[‘Attrition’].value_counts().plot(kind = ‘bar’)

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

图 4

我们的分布大致平衡。

检查重复项

print('Number of duplicates: ',train_data.duplicated().sum())

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

train_data[train_data.duplicated()]['Attrition'].value_counts().plot(kind = 'bar')

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

图 5

好了,数据有 628 个副本,所有副本都对应于损耗 1。这意味着数据被过采样以保持平衡。我们现在将删除重复的内容,并再次检查分布情况。

train_unq = train_data.drop_duplicates()
print('New train set: ',train_unq.shape)
X = train_unq.drop('Attrition',axis = 1)
y = train_unq['Attrition']
y.value_counts().plot(kind = 'bar')
plt.show()

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

图 6

现在我们的训练数据有 1000 个数据点,而目标变量是不平衡的。有许多方法可以处理不平衡的数据集,如使用 SMOTE 进行上采样或下采样。

我们还可以使用交叉验证策略,例如分层 k 折叠,它可以保持目标变量(此处为损耗)在折叠中的分布相似。使用分层抽样而不是随机抽样来分割训练和验证数据。这里的 stratas 是我们的目标变量的两个值。如果你不明白这意味着什么,那么不要担心,只要记住这是一个有效的方法来处理不平衡的数据集,而我们训练我们的模型。你可以在 scikit-learn 交叉验证用户指南中了解更多信息点击

预处理、培训和验证

我们现在将遵循以下步骤:

  • 降低性能等级(在探索中,我发现 85%的值属于一个类,这可能会导致过度拟合)
  • 一个热编码所有的“对象”数据类型特征
  • 对所有整数数据类型要素使用标准缩放。
  • 使用预处理的数据,并使用分层 K-Fold 对其进行分割。
  • 用 3 个候选模型进行拟合和验证:随机森林、XGBoost 和支持向量分类器

这是很多步骤。scikit-learn 允许我们使用管道列变压器用几行简单的代码完成所有这些工作。

所以,首先,我们为预处理做一个管道

categorical = [f **for** f **in** training.columns **if** training[f].dtype == object]
numeric = [f **for** f **in** X.columns **if** f **not** **in** categorical+['Id',','Behaviour','PerformanceRating']]

pre_pipe = make_column_transformer((OneHotEncoder(),categorical),(StandardScaler(),numeric))

变量分类存储对象数据类型特征的所有列名,而数字存储所有整数数据类型列。

现在,我们为模型定义管道,并打印出不同模型的交叉验证分数。使用 cross_val_score,我们可以将“skf”传递给“cv”参数,它将负责为我们进行拆分迭代和计算分数。由于数据不平衡,我使用“roc_auc”作为评分标准。为了更好地理解 cross_val_score 的参数,请查看其文档

# random forest pipeline
pipe_rf = make_pipeline(pre_pipe,RandomForestClassifier())
#xgboost pipeline
pipe_xgb = make_pipeline(pre_pipe,XGBClassifier()) 
# SVM pipeline
pipe_svc = make_pipeline(pre_pipe,SVC(probability=**True**))print(‘RF:‘,np.mean(cross_val_score(X=X,y=y,cv=skf,estimator=pipe_rf,scoring=’roc_auc’))) print(‘XGB:‘,np.mean(cross_val_score(X=X,y=y,cv=skf,estimator=pipe_xgb,scoring=’roc_auc’))) print(‘SVC:’,np.mean(cross_val_score(X=X,y=y,cv=skf,estimator=pipe_svc,scoring=’roc_auc’)))

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

图 7

显然,支持向量分类器比基于树的模型表现更好。移除更多功能和调整后,随机森林和 XGBoost 的性能可能会更好,但在本文中,我们将使用 SVM。

在一次热编码后,我们在数据集中总共有 46 个特征,随着维度的增加,有更多的机会过度拟合,也可能有不相关的特征。所以我决定用主成分分析来降低维数。

所以,首先我拿了 46 个组件,并在我们的管道中加入了 PCA。我已经看到了累积的解释差异。

n = 46
pipe_svc = make_pipeline(pre_pipe,PCA(n_components=n),SVC(probability=**True**,C = 1,kernel='rbf'))

plt.figure(figsize=(10,8))
pipe_svc.fit(X,y)
plt.plot(range(1,n+1),pipe_svc.named_steps['pca'].explained_variance_ratio_.cumsum())
plt.xticks(range(1,n+1,2))
plt.title('Explained Variance')

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

图 8

我们可以看到大约 34 个成分解释了 100%的方差。所以我们用了 34 个组件来适应我们的模型。

n = 34
pre_pipe = make_column_transformer((OneHotEncoder(),categorical),(StandardScaler(),numeric),remainder = 'passthrough')
pipe_svc = make_pipeline(pre_pipe,PCA(n_components=n),SVC(probability=True,C = 1,kernel='rbf'))
print('SVC: ',np.mean(cross_val_score(X=X,y=y,cv=skf,estimator=pipe_svc,scoring='roc_auc')))

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

我们的分数降低了 0.01,但我们已经大大降低了维度,现在这个模型在看不见的数据上表现更好的机会更大了。

超参数调谐

为了从模型中挤出所有的性能,现在是时候调整我们的 SVM 模型了。我们将为此使用 GridSearchCV,如果你不熟悉它,请看一下文档

我们可以调整的参数有:

  • c:这是正则化参数
  • 核:线性、多项式或 RBF(高斯)
  • Gamma:相当于高斯核中的方差项
  • 类别权重:平衡目标变量中类别的权重(权重与类别频率成反比)

还有更多参数,但这些是影响性能的重要参数,在进一步讨论之前,请查看 scikit-learn 文档

对于管道,调整也是一个非常简单的过程,我们只需定义参数网格,然后将整个管道传递到网格搜索中。我没有在这里调优内核。因为“rbf”是最常用的内核,并且适用于大多数任务,所以我只使用它来节省一些计算时间。您也可以继续尝试调优内核。

param_grid = {

    'svc__C':[0.001,0.01,0.1,1,10,100,1000],
    'svc__gamma': ['auto','scale'],
    'svc__class_weight': ['balanced',**None**]
}

grid_search = GridSearchCV(pipe_svc,param_grid=param_grid,cv = skf, verbose=2, n_jobs = -1,scoring='roc_auc')
grid_search.fit(X,y)
print('Best score ',grid_search.best_score_)
print('Best parameters ',grid_search.best_params_)
best_svc = grid_search.best_estimator_

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

图 9

您可能已经注意到,我在参数网格中的所有参数前面添加了“svc__ ”,这样做只是为了指定我们在网格搜索中调整管道的哪个步骤,因为我们不只是将一个估计器传递给 GridSearchCV,而是传递给整个管道。我相信可能有更好的方法来做到这一点,如果你知道更好的技术,请在评论中告诉我。

我们可以尝试进一步调整我们的模型,通过调整 C 的范围和固定其他超参数的值来找到最佳的 C,就像这样

pipe_svc = make_pipeline(pre_pipe,PCA(n_components=n),SVC(probability=**True**,C = 1,kernel='rbf',class_weight=**None**,gamma='auto'))
param_grid={
    'svc__C':[0.01,0.03,0.05,0.07,0.1,0.3,0.5,0.7,1]  
}
grid_search = GridSearchCV(pipe_svc,param_grid=param_grid,cv = skf, verbose=2, n_jobs = -1,scoring = 'roc_auc')
grid_search.fit(X,y)
print('Best score ',grid_search.best_score_)
print('Best parameters ',grid_search.best_params_)
best_svc = grid_search.best_estimator_

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

图 10

最终的平均验证分数现在是 0.8319。是时候向 Kaggle 提交了。

best_svc.predict_proba(test_data)[:,1]
submission = pd.DataFrame(prediction,columns=['Attrition'])submission['Id'] = test['Id']
submission = submission[['Id','Attrition']]
submission.to_csv('submissionfile_SVC.csv',index = None)

瞧啊。

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

图 11

正如你所看到的,我的排名下降了 4 位。发生这种情况是因为我的模型过度适应训练数据,我可能不应该太疯狂地调整“C”。更好的特征选择也可能有助于提高分数。你怎么想呢?请随意查看我的 Kaggle 笔记本并执行代码。

如果你坚持到最后,谢谢你。我希望你觉得这篇文章有用,并从中学习到新的东西。请在评论中提供宝贵的反馈,我很想知道你对提高性能的想法。

使用监督机器学习预测 IMDb 电影评级

原文:https://towardsdatascience.com/predicting-imdb-movie-ratings-using-supervised-machine-learning-f3b126ab2ddb?source=collection_archive---------13-----------------------

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

照片由佩克斯的达莉亚·谢夫索娃拍摄

我叫 Joe Cowell,我最近参加了 Metis 数据科学训练营。为期 12 周的沉浸式项目将把我从“数据新手”变成一名成熟的数据科学家。我的意思是,这个帖子的标题包括“有监督的机器学习”,而我只参加了这个项目三周,所以看起来 Metis 正在履行他们的承诺。无论如何,我会试着为感兴趣的人写一篇关于我是谁的帖子,但现在,让我们看看我是如何使用监督机器学习来预测 IMDb 电影评级的。

背景:

在我的音乐生涯中,问题总是“这首歌有多好?”也从来没有“这首歌会赚多少钱?”也许这就是为什么我们是典型的饥饿艺术家…不管怎样,我把这个概念应用到电影中。这个想法是,电影行业的艺术家可以利用这个模型来预测观众对电影的接受程度,因此,专注于 IMDb 评级作为目标,而不是 Metacritic 的评级系统或烂番茄的 Tomatometer。

总体而言,该项目探索了数据科学家所需的几项关键技能:

  • 网络抓取(请求、HTML、美汤)
  • EDA(熊猫,numpy)
  • 线性回归(scikit-learn)
  • 数据可视化(seaborn,matplotlib)

第一步:数据采集&清洗🔍

简单地说,IMDb 有一个 API 可以下载大量数据,但是这个项目的主要需求是通过 web 抓取获得数据;因此,我继续使用请求和漂亮的汤从 IMDb 获得信息。Requests 是获取网页并将其转换为 python 中的对象所需的模块。Beautiful Soup 采用了该对象,即网页背后的 HTML 信息,并使搜索和访问 HTML 文本中的特定信息变得容易。你真的需要这两者来完全完成网页抓取的过程。

在 IMDb 的页面上,我使用了高级搜索功能来搜索 2000 年到 2020 年间的书籍。结果跨越了数千页,每一页都有 100 部电影的标题和链接。经过进一步检查,我注意到该 URL 包含短语:’ start=1 '。将起始数字增加 100 将会翻页。通过一个助手函数,我使用请求和漂亮的 Soup 来获取每个页面的链接,并返回这些链接的列表。

为了利用电影超链接列表,我创建了另一个函数来从每个页面提取尽可能多的数据。该函数接收一个链接并返回一个包含以下信息的字典:标题、IMDb 评分、IMDb 评分者的数量、美国电影协会评分、类型、导演、作者、前三名明星、发行的初始国家、发行的原始语言、发行日期、预算、美国首映周末、美国总票房、全球累计总票房、制作公司和运行时间。

作为 EDA 的一部分,必须清理一些数据。这包括将字符串中的任何数值转换成整数。运行时间必须转换成分钟,所有的货币值都需要去掉逗号和美元符号,发布日期必须转换成日期时间。此外,包含列表的类别需要从字符串转换成实际的 python 列表(流派、导演、明星、制作公司)。检索函数完成了大部分清理工作,但是在将数据放入数据帧之后,还需要做一些其他的清理工作。

一个数据帧中有 2000 多部电影,我需要做更多的处理来获得一个用于建模的功能性数据帧。这意味着放弃没有预算信息的电影,预算低于 1000 美元的电影,以及评分低于 1500 美元的电影。关于最后一个要求,评级者数量少的电影被证明报告了更极端的电影评级(电影倾向于完美的 10 或一个大鹅蛋)。总而言之,我最终得到了一个包含 1100 多部电影的数据框架。现在是时候开始建模了。

在进入下一部分之前,我想提一下 Pairplots。Pairplots 是一个很好的可视化工具,用于探索数据中的关系,并告知 MVP 从哪里开始。看起来信息量很大,但是当您以第一列或最后一列为目标来格式化数据帧时,解释所有这些信息会容易得多。对于此配对图,第一列中的图显示了自变量和目标之间的关系。虽然我没有使用大部分数值数据,但很明显存在线性和指数关系,这可以很容易地告知从哪里开始建模。

sns.pairplot(movies_df_drop, height=1.2, aspect=1.25)

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

(图片由作者提供)

第二步:模型和特征📈

值得注意的是,这个项目的另一个要求是使用线性回归,所以我试验的模型是线性回归和岭回归。有了这么多可用的特性,而且这是我第一次使用 python 进行回归,我花了一些时间来整理每个特性。

首先,我决定走一条简单的路线,以运行时间为唯一特征,以 IMDb 评级为目标,进行简单的线性回归。这导致 R 值为 0.2687。老实说,我对任何大于零的数字都相当兴奋,所以我已经准备好钻研其余的数据了。

对于美国电影协会评分和流派,我创建了虚拟变量添加到数据框架中,得到的 R 为 0.3997。至于导演、编剧、明星和制作公司,我在每个类别中创建了一个最常出现的玩家列表,并为顶级竞争者创建了虚拟变量。如果一个导演只在我的数据中出现过一次,那么这个导演的权重(或系数)将是该特定电影评级的直接结果,因此让玩家拥有多行数据将为模型提供更多信息,以创建更好的知情系数。

为了更有创意,我选择了发布日期,制作了一个“发布月”专题。同样,我采用了上映日期,并创建了另一个功能来确定电影上映以来的年份。这可能不是最相关的特性,但是我很高兴能够试验日期时间信息。

将特征加载到模型中后,得到的 R 值为 0.4751,这看起来很有希望,但下一步是通过交叉验证对模型进行严格测试。

第三步:测试和培训/结果🎥

虽然线性回归完成了工作,但我知道我想比较模型的系数,使用岭回归是一种迫使自己缩放输入并尝试不同方法来创建模型的好方法。

对于这一部分,我建议查看一下项目库,以了解训练和测试模型背后的过程,但是我将直接跳到最终的模型和结果。

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

(图片由作者提供)

最终模型的 R 为 0.432,平均绝对误差为 0.64。这是一个相当低的 R,但是这篇文章描述了为什么预测人类行为的 R 低于 0.5 是可以预期的。此外,预测评级与实际评级左侧的图表为模型提供了更多的信心,因为两者之间存在某种线性关系。此外,残差最高的电影要么收视率低,要么是像猫、五十度灰、表情电影这样的电影。这些特定的电影背后有很好的统计数据,但公众并没有很好地接受它们,这是一个很难纳入这个模型的指标。

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

(图片由作者提供)

查看与每个特征相关的系数也很重要。如左图所示,运行时间、发行后的年数和预算都是模型中的重要角色,一些类型和作者也在上面。这就是岭回归的美妙之处:能够使用系数来确定特定特征的权重。

最终,我有了一个预测 IMDb 评级的模型,其 R 为 0.432,明显优于仅用平均值进行预测,MSE 为 0.64,这意味着预测可能在两个方向上都有 0.64 个点的误差。

总结:📘

这不仅是我第一次在网上搜集数据,也是我第一次创建模型,更不用说线性回归模型了。总的来说,我对这种模式相当自豪。此外,单独遍历数据科学工作流的体验非常有益;我:

  • 通过在网上搜集信息,我创建了自己的数据集
  • 浏览数据集并清理掉所有不相关的内容
  • 开发了一个 MVP,在任何给定的时刻都有一个工作模型
  • 迭代地改进模型,以获得具有每个特性的更好的产品
  • 可视化我的模型的有效性以及对电影评级的贡献

在训练营的三周内,我就熟悉了网页抓取、EDA、线性回归建模和数据可视化。再一次,对于我的过程的更多代码的解释,检查我的 GitHub 库,如果你有任何问题或意见,请随时联系我。

我真的很期待在 Metis 学习更多的技术和技能,所以如果你对我的数据科学之旅感兴趣,请回来查看更新。

随意伸手:
LinkedIn|Twitter

用图卷积神经网络预测首次公开发行股票

原文:https://towardsdatascience.com/predicting-initial-public-offerings-using-graph-convolutional-neural-networks-42df5ce16006?source=collection_archive---------48-----------------------

从数据库到预测

大约一年前,我了解了图形数据库的概念,以及它们与表格、关系数据库相比,如何不同地表示数据。我很感兴趣的是,有一种存储和查找数据关系的方法,我发现这种方法比在表格数据上计算连接更直观。如果两条数据是相关的,在图形数据库中,您只需在它们之间创建一条边。由于数据在图中,您可以在数据库上执行所有标准的图算法,例如广度和深度优先搜索、最短路径算法和相似性算法。所有这些算法都处理不同数据点之间的边缘(关系)。事实证明,有机器学习算法也可以处理数据之间的关系。本文将详细介绍建立和运行您自己的图形机器学习管道的步骤——从数据库到预测。

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

照片由里克在 Unsplash 上敲击

首先,我们将使用来自 Crunchbase 的示例数据集建立一个 TigerGraph 云实例。该数据包含大约 200,000 家处于不同融资阶段的公司,并包含诸如它们是否实现了首次公开募股(IPO)、公司的主要投资者、创始人及其总部所在地等信息。然后,我们将使用 Jupyter 笔记本中的 pyTigerGraph 和 Giraffle 连接到数据库。最后,我们将建立一个图形卷积神经网络(GCN)来预测我们数据集中的某个公司是否会 IPO。要了解代码,请点击这里的库。

设置 TigerGraph 云

我不打算深入介绍如何设置 TigerGraph 云实例,因为这篇文章很好地指导了您配置实例的步骤。在步骤 1 中,只需选择“企业知识图(Crunchbase)”初学者工具包。一旦你启动并运行了你的初学者工具包,我们将不得不通过 Gradle 获得一个 SSL 证书来访问服务器。在您的项目目录中,在您的终端中键入以下内容:

openssl s_client -connect <YOUR_HOSTNAME_HERE>.i.tgcloud.io:14240 < /dev/null 2> /dev/null | \
openssl x509 -text > cert.txt

我们还需要创建另外两个文件。首先,让我们在基础项目目录中创建一个grad le-local . properties文件。这应包括:

gsqlHost=YOUR_HOSTNAME_HERE.i.tgcloud.iogsqlUserName=tigergraphgsqlPassword=YOUR_PASSWORD_HEREgsqlAdminUserName=tigergraphgsqlAdminPassword=YOUR_PASSWORD_HEREgsqlCaCert=./cert.txt

另一个应该放在 py_scripts/目录中,命名为 cfg.py 。这应包括:

secret = "YOUR_SECRET_HERE"token = “”password = “YOUR_PASSWORD_HERE”

秘钥可以在 Graph Studio 的管理页面下获得。

安装查询和提取数据

我们将使用两种不同的工具与 TigerGraph 云实例进行交互:Giraffle 和 pyTigerGraph。Giraffle 将允许我们安装需要在数据库上运行的查询,而 pyTigerGraph 将为我们提供一个接口,将这些查询的结果拉入 Python。

长颈鹿

Giraffle 是 Gradle 的一个插件,一个构建系统。这允许您轻松地将代码打包以部署在各种不同的平台上,并使用版本控制软件(如 Git)来跟踪您为数据库编写的查询。更多信息,请查看其项目页面这里

这些疑问

我们通过几个终端命令将查询安装在 Jupyter 笔记本的前几个单元格中。每个查询的功能概述如下:

  • companyLinks 在 TigerGraph 中计算公司之间的关系,并将其返回到一个 JSON 有效负载中,我们可以用 Python 解析该负载。这过度简化了这里的图表。该查询返回有共同点的公司对。这损害了准确性,因为一些常见的元素(创始人、投资者等。)可能比位置或行业更重要。创建具有多种类型顶点的 GCN 是可能的,(称为关系图卷积笔记本),但它更复杂。开始的一个好方法是简化图表,直到你只有相同类型事物之间的关系。
  • getAllCompanies 顾名思义,它返回数据集中所有公司的列表。我们需要它的原因将在下一节中变得明显。
  • getAllIpo 获取数据集中所有已经上市的公司。这在下一节很有用,也可以用来检查我们预测的准确性。

pyTigerGraph

为了从我们安装的查询中获得结果,我们将使用 pyTigerGraph。要了解更多信息,请点击这里查看我的 GitHub 上的包。

欠采样数据

好了,现在我们已经安装了所有的查询,并将数据放入笔记本,请注意一些事情。首先,与公司总数(约 200,000 家)相比,IPO 公司的数量微不足道(约 1,200 家)。这意味着数据集非常不平衡,这将导致 GCN 预测每家公司不会 IPO(这样它的准确率将达到 99.4%)。另一件需要考虑的事情是,大多数计算机没有足够的内存来运行全图上的 GCN。便利的是,不平衡的数据意味着我们应该对未上市公司进行欠采样,以便得到一个更加平衡的数据集。这就产生了一个大约有 2000 个顶点的图,平均分布在已经上市和没有上市的公司之间。然而,这种方法有一个缺点。由于这些公司是从非 ipod 和 ipod 名单中随机抽样的,我们不能保证每个公司之间有很多边缘,这对我们的准确性有很大影响。

图形卷积神经网络

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

使用图卷积神经网络进行分类(来源:https://docs.dgl.ai/en/latest/tutorials/basics/1_first.html

图形卷积神经网络(GCN)是一种半监督分类算法,它处理图形中的连接以及每个顶点的特征。这个概念类似于传统的基于图像的卷积神经网络,但 GCN 不是查看相邻的像素,而是查看通过边连接的顶点。顶点特征可以是任何向量,比如顶点的各种属性的 doc2vec 表示,或者仅仅是一个一键编码的向量,这就是我在这里选择做的。然后我们标记两个不同的顶点,一个已知有 IPOed,另一个没有。

我们的神经网络架构非常简单。它由两层组成,输入维数等于特征向量中的条目数(它也恰好是图中的顶点数,因为我们对它们进行了一次性编码)。然后,我们将输入通过一个有 32 个神经元的层,然后通过 2 个神经元输出。我们使用 Adam 作为训练过程的优化器。然后我们开始训练循环。不幸的是,由于我们之前对图表的采样不足,GCN 在图表中并不总是有足够的边来准确可靠地做出预测。我通常得到大约 60%的准确率,但由于公司的随机抽样,它确实变化很大。

结论

GCN 并不是一个预测一家公司是否 IPO 的好方法,因为内存限制和对图表的欠采样。其他图形机器学习方法,如 node2vec 可能会更好。另一种可能提高精确度的方法是使用关系图卷积神经网络(R-GCN ),它可以处理具有多种不同类型顶点的图。

信用

Parker Erickson 写的文章和笔记本,他是明尼苏达大学攻读计算机科学学士学位的学生。他的兴趣包括图形数据库、机器学习、旅行、演奏萨克斯管和观看明尼苏达双城棒球赛。随意伸手!在以下地址找到他:

GCN 资源:

笔记本改编自:https://docs.dgl.ai/en/latest/tutorials/basics/1_first.html

使用 Python +大数据预测住院患者的住院时间

原文:https://towardsdatascience.com/predicting-inpatient-length-of-stay-at-hospitals-using-python-big-data-304e79d8c008?source=collection_archive---------18-----------------------

医疗保健中的机器学习

从原始数据集检索到机器学习建模的端到端项目

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

来自纽约邮报文章的纽约医院病人的照片(图片来自 Shutterstock)

背景:

病人住院时间是医院管理效率的一个关键指标。医院资源有限,需要有效利用床位和临床医生的时间。随着最近新冠肺炎疫情的出现,这一概念得到了体现。现在,我们比以往任何时候都更能看到,将住院时间限制在不必要的时间内,并了解特定住院患者可能需要住院多长时间,符合患者、医院和公共卫生的最佳利益。

因此,只有在患者一进入医院并被诊断出就可以获得信息的情况下,预测患者将停留多长时间的能力可以对医院及其效率产生许多积极的影响。可以预测患者住院时间的模型可以让医院更好地分析对住院时间影响最大的因素。这种分析可以为缩短住院时间铺平道路,从而降低感染风险和药物副作用,提高治疗质量,并通过更有效的床位管理增加医院利润。此外,预测患者的住院时间也极大地有利于患者和患者家属,因为他们可以知道他们在入院时预计会住院多长时间。**该项目的目标是创建一个模型,用于预测患者入院后的住院时间,**此处详细介绍了完成此任务的步骤。

在整个分析中使用的全部代码可以在这里找到。

数据集介绍:

为了进行这一分析,我使用了公开的“2015 年纽约医院住院病人出院”数据集,该数据集可在纽约州政府健康数据网站上找到。该数据集包含 230 多万行患者数据,包括患者人口统计、诊断、治疗、服务、成本和收费等信息。根据 HIPAA 法规,患者数据已被取消身份。为了分析这种规模的数据集,我利用了 Python 接口中的各种大数据分析工具,如 Spark、AWS clusters、SQL 查询优化和降维技术。然而,本文中显示的大部分代码使用了 Pandas 和 scikit learn。让我们先来看看数据集中的所有要素和相关数据类型。

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

接下来,让我们看看我们的数字特征是如何相互关联的。我们可以通过使用关联热图来实现这一点。

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

从我们数据的关联图中可以看出,有几个特征相互之间有很强的相关性,也许更重要的是,与住院时间有很强的相关性。尽管查看我们所有的列(如许可证号)的相关性矩阵没有意义,但我们可以从中看出,APR 疾病严重程度代码与住院时间、总费用和总成本有很强的正相关性。CCS 诊断代码似乎也与住院时间略有正相关。我们可以在数据集中看到特征之间的其他正相关,例如 CCS 诊断代码和 APR DRG 代码。除了让我们知道数据中是否存在多重共线性之外,该图还让我们了解了哪些功能对于预测住院时间可能特别重要。

探索性数据分析与可视化:

接下来,让我们探索并可视化数据中的潜在关系。在下面的分析中,住院时间作为我创建的图的 y 轴上的主要变量,因为它是这个项目的预测变量。首先,住院时间的单变量分布是可视化的。

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

正如我们所看到的,停留时间值的范围从 1 天到 120 天以上(120 天已经被合计为包括所有停留 120 天或更长时间的时间)。此外,分布非常不均匀,数据中大多数患者的住院时间在 1 到 5 天之间。这是需要记住的数据的一个重要方面。我们暂时先把它放在这里,以后再来看。接下来,我们来看看不同年龄组的住院时间分布是如何变化的。

住院时间长短会随着患者年龄的变化而变化吗?

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

由于存在许多异常值,y 轴被限制在 0 到 30 之间。

从该图中,随着年龄组的增加,平均住院时间分布变长的趋势显而易见。

哪些诊断的平均住院时间最长?

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

平均而言,被诊断患有分娩并发症的患者平均住院时间最长,其次是患有呼吸系统疾病的患者。让我们来看看一些我们可能不认为会有太大影响的特性是如何随着停留时间的变化而变化的。

停留时间长短会因种族而异吗?

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

我们可以看到,正如人们可能会怀疑的那样,病人的种族不会导致住院时间分布的很大差异。然而,有趣的是,黑人/非洲裔美国人与分布第二大的群体(白人)在住院时间值上的差距最大,相差约 2 天。

住院时间长短如何因患者付费类型而异?

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

从该图中可以明显看出,不同的医疗保险支付方式往往具有不同的住院时间分布。具体来说,我们可以看到,例如,医疗保险患者往往平均住院时间最长。然而,健康保险计划与其他因素密切相关,如收入和年龄。因此,这可能是因为医疗保险患者往往有更长的住院时间,因为他们也在一个较大的年龄段。让我们更深入地探讨这个想法:

以医疗保险为主要支付方式的患者年龄分布如何?

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

这一想法得到了上述图表的支持,并让我们了解了不同变量是如何相互作用来影响停留时间的。

让我们继续讨论数据集中存在的一些最重要的特征:疾病的严重程度和入院病人的类型。

住院时间长短因病情严重程度而异?

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

我们可以看到 APR 疾病严重程度特征中的大量差异,这表明它很可能是包含在机器学习(ML)模型中的一个重要特征。

住院时间长短如何因入院类型而异?

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

每种疾病严重程度类型的诊断描述有何不同?

在这里,我对数据集的诊断描述列执行文本解析分析,然后创建 wordclouds 来可视化这些结果。使用根据疾病严重程度分类的每个患者的诊断描述创建了词云。

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

使用了 NLTK tokenizer 包,随后移除了停用词(a、and、the 等。)来自 wordcloud 创建之前的描述。

从该分析中,我们可以看到每种疾病严重程度类型的诊断描述中的一些相似之处,但也有一些巨大差异。

网页抓取附加功能

在上面关于健康保险项目的简短讨论中,我也提到了患者收入可能会起到一定作用,并且最终可能与住院时间长短相关。这种情况的一个例子是,对于一些低收入病人来说,医院提供的生活条件比他们在医院外的情况要好。因此,这些患者被激励尽一切努力延长他们的住院时间。不幸的是,我们的数据集不包括任何关于患者收入的信息。但是,它包括患者的 3 位数邮政编码。当我们准备开始这个项目的建模部分时,重要的是要考虑这样一个事实,即对于大多数 ML 模型来说,zipcode 并不是一个好的特性。虽然它的信息是用数字编码的,但它不是一个数字特征,因为它的数字在数学上没有任何意义。反过来,这使得邮政编码很难理解,也很难通过 ML 模型创建预测模式。因此,在我的分析中,下一步将是用患者收入的粗略衡量标准来取代这种原始的 3 位数邮政编码数据,这将证明是一个更有用的功能。

为了做到这一点,我通过邮政编码从这个网站收集了平均收入数据,包含了 2006-2010 年的数据。下面是数据集中每个 3 位数邮政编码的中值收入图,是通过内部连接(通过 python 中的 SQL)将网络抓取的数据连接到我们的数据框架上实现的。

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

y 轴上的收入以美元为单位。请注意,邮政编码 999 是那些不在本州的患者的聚合邮政编码(详见博客开头的完整编码链接)。

我们可以使用这个新的收入特征来可视化其他特征如何随着新构造的特征而变化。

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

我们现在准备开始准备这个分析的建模部分。

建模准备:

为了开始这一部分,我首先将删除所有对预测建模没有用的列。这包括邮政编码、诊断描述、操作证书编号等。,此外还有患者入院时不会出现的特征,如总费用和总收费,从而防止数据泄露

接下来,我对包含字符串的所有分类列执行特征编码。使用具有相应数字代码的类别,如 APR 疾病严重程度代码与 APR 疾病严重程度描述,而不是它们的字符串对应物,以防止类别二进制化的需要,从而防止维度的潜在大幅增加。

此外,我将对特性的特定子集使用字符串索引。对于年龄组和 APR 死亡风险,由于这些特征中的类别存在固有的顺序性,所以进行了串索引。例如,“0 至 17 岁”年龄组比“70 岁或以上”年龄组更小。因此,用 1 对最小的年龄组“0 到 17”进行编码,用越来越大的整数对较大的年龄组进行编码是有意义的。类似地,APR 死亡风险的“轻微”类别为 1,而“极端”为 4。对这类特定要素进行字符串索引非常有益,因为它可以防止增加数据集的维度,并允许模型了解要素类别中存在的普通性。手动完成此操作的代码如下所示。但是,对不具有固有顺序性的要素(如“医疗服务区”)使用字符串索引时,一定要小心。因此,执行剩余分类特征的一键编码。

mort_string_index = {'Minor': 1, 'Moderate': 2, 'Major': 3, 'Extreme': 4}
age_string_index = {'0 to 17': 1, '18 to 29': 2, '30 to 49': 3, '50 to 69': 4, '70 or Older': 5}df['Age Group'] = df['Age Group'].apply(lambda x: age_string_index[x])
df['APR Risk of Mortality'] = df['APR Risk of Mortality'].apply(lambda x: mort_string_index[x])

现在,让我们来看看我们的预测功能,住院时间。停留时间的范围从 1 到 120,并且只接受整数值。我决定将预测停留时间视为一个多类分类问题(而不是回归)。与我使用的回归相比,多类分类产生了一个很大的优势:手动定义类仓来手动控制预测特异性的能力。我们可以将这些值分组到对预测更有意义的箱中,而不是将停留时间视为 120 个不同的类别,而不会显著降低预测的特异性。在探索了这些条柱的多种选择后,其中包括权衡模型的有用性(如果条柱太大,预测将不再有用)和模型准确性,我最终确定了以下条柱格式:

1–5 天、6–10 天、11–20 天、21–30 天、31–50 天和 50–120 天以上

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

从这个图像来看,一个巨大的阶级不平衡是显而易见的。在回顾在本分析开始时绘制的原始住院时间数据的单变量分布时,同样的趋势是明显的。数据中的这种不平衡必须小心处理,因为它会导致误导性的准确性分数。类别不平衡会导致模型过度预测最常出现的类别,因为简单地预测大多数数据实例的类别,而不考虑它们的特征,将会导致最高的整体准确度分数。因此,旨在优化准确度分数的模型可能落入这个陷阱。例如,即使该模型总是预测住院患者的住院时间为 1 至 5 天(在该数据集中最常见的住院时间),它也会达到约 1.6e6/2.3e6 = 69%的准确度。与模型的基线精度(如果随机猜测,模型将达到的精度)相比,它是 1/6 或大约 17%,乍一看,这是明显更好的模型性能。

处理阶层失衡

对最频繁出现的类进行欠采样和对过度预测的类进行惩罚是处理类不平衡的两种最常见的方法,这两种方法都在该数据集上进行了探索。最终,我发现分配惩罚是最有效的方法,它比欠采样方法具有更高的模型精度,同时还能像欠采样一样防止与类别不平衡相关的风险。为了将这些惩罚分配给类,我使用了 scikit learn 的 ML 函数中的“类权重”参数,并将该参数设置为“平衡”。这有效地给每个类分配了一个与它出现的频率成反比的权重。

ML 造型

主成分分析:

在训练任何模型之前,我在使用 StandardScaler()函数标准化训练和测试数据集之后对数据执行 PCA。主成分分析是一种强大的工具,它允许人们降低数据集的维数,这对大型数据集非常有益,例如我们在这里处理的数据集。此外,它还消除了数据中的任何多重共线性。尽管 PCA 不适合用于混合了数字和分类特征的数据集(已经进行了一键编码/字符串索引),但使用 PCA 并不会对性能造成显著影响(更多信息请参见此处关于何时使用 PCA 与 MFA)。在应用 PCA 之前,务必对数据进行归一化处理,因为 PCA 会将原始数据投影到通过计算要素内点之间的相对距离来最大化方差的方向上。因此,当特征在不同的尺度上时,可以抛弃 PCA。

import numpy as np
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScalerx_train = StandardScaler().fit_transform(X_train)
x_test = StandardScaler().fit_transform(X_test)
pca1 = PCA()
pca1.fit(x_train)
explained_variance_ratio = pca1.explained_variance_ratio_
pc_vs_variance = np.cumsum(pca1.explained_variance_ratio_)

下面,我绘制了相对于使用的 PCA 成分数量的%解释方差。从这个图中,我们可以决定在剩下的分析中使用多少个成分,以便在数据中保留一定百分比的解释方差。这里,我选择保留 29 个组件,因为这是解释数据中 95%的方差所需的最少组件数。

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

逻辑回归:

接下来,让我们训练一个一对多逻辑回归分类器。逻辑回归分类器是分类问题的强模型。让我们在将 PCA 应用于标准化数据后训练一个模型,如下所示。

pca = PCA(n_components=29) #29 components, as found above
x_train = pca.fit_transform(x_train)
x_test = pca.transform(x_test)from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
import numpy as nplog_reg = LogisticRegression(multi_class='ovr').fit(x_train, y_train)
y_train_pred = log_reg.predict(x_train)
y_pred = log_reg.predict(x_test)test_acc = accuracy_score(y_test, y_pred)
train_acc = accuracy_score(y_train, y_train_pred)print('Test accuracy:', test_acc)
print('Train accuracy:', train_acc)

列车精度:0.7315117403879348
测试精度:0.20000001

鉴于该数据集的基线准确性和性质,我们得到了非常好的结果。然而,这个模型是在没有平衡任何类别权重的情况下对数据进行训练的。在进行预测后创建混淆矩阵是一个很好的做法,这样可以更仔细地检查模型性能,因为仅准确性分数就可能会产生误导。

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

标签是根据每个箱子中较长的停留时间值创建的。例如,标签 5 对应于 bin (0,5),或者停留时间范围从 1 天到 5 天。

混淆矩阵展示了忽视数据集中的类别不平衡的危险。虽然我们获得了非常高的准确度分数,但是该模型明显过度预测了预测标签 5,因为它是具有最高频率的标签。另一方面,该模型从不预测标签 30 和 50。这两种趋势在热图中第一列的较暗颜色中都很明显,与 30 和 50 列中的最亮颜色形成对比(也用 0 表示)。现在,让我们看看我们是否能处理这个问题。

平衡类权重参数的 Logistic 回归:

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
import numpy as nplog_reg = LogisticRegression(class_weight='balanced', multi_class='ovr').fit(x_train, y_train)
y_train_pred = log_reg.predict(x_train)
y_pred = log_reg.predict(x_test)test_acc = accuracy_score(y_test, y_pred)
train_acc = accuracy_score(y_train, y_train_pred)print('Test accuracy:', test_acc)
print('Train accuracy:', train_acc)

训练精度:0.5892498813701775
测试精度:0.200000001

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

正如我们所看到的,定义类权重参数对我们的模型的性能有巨大的改善,防止分类器简单地过度预测最高频率的类。尽管整体准确性下降,但在未来的“真实世界”测试中,我们的模型现在将是任何给定实例的更好的预测器。此外,由热点图对角线上的深色表示,即使模型预测了错误的标签,它通常也会向右或向左偏离一个标签。

让我们打印出更多的分类指标,以便更好地了解我们的模型的表现:

from sklearn.metrics import classification_report
print(classification_report(y_test, y_pred))

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

让我们使用 f1 分数将逻辑回归分类器与我们将创建的其他模型进行比较。F1-score 是对模型准确性的度量,它是通过取精度和召回率的调和平均值来计算的,从而将精度和召回率组合成一个度量。如果您不熟悉精确度和召回率的概念,请参考本文了解更多信息。本质上,f1-score 提供了一种定量的方法来评估过度预测某些类别标签的趋势以及模型区分类别的能力。

决策树:

对于我们的下一个模型,让我们尝试在我们的数据上训练一个决策树分类器。决策树往往在多类分类问题中表现得非常好,并且直观易懂。然而,在我们创建模型之前,让我们首先优化决策树分类器的超参数。为此,我们可以在字典定义的超参数值组合范围内运行随机搜索。通过这种搜索,我们可以返回找到的最佳值。这种超参数搜索通过 scikit RandomizedSearchCV 函数实现。这里,我选择优化 max_depth 和 max_leaf_nodes 参数,因为它们是防止过度拟合的关键参数,这是决策树特别容易出现的一个属性。利用三重交叉验证。

from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import RandomizedSearchCVdtree = DecisionTreeClassifier(class_weight='balanced')
search_vals = dict(max_depth=[35,50,75,100], max_leaf_nodes=[800,1000,1500,2000])
dtree_search = RandomizedSearchCV(dtree, search_vals, cv=3)
search = dtree_search.fit(X_train,y_train)
search.best_params_

输出:{ ‘最大深度’:50,‘最大叶节点’:1000}

我还绘制了一条验证曲线,同时利用三重交叉验证,以可视化超参数优化和模型复杂性对模型准确性的影响。max_depth 参数的验证曲线如下所示。

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

随着 max_depth 参数变得不太严格(允许更深的树),验证曲线突出了决策树过度拟合的趋势。然而,有趣的是注意到,尽管在训练和验证精度之间有很大的差距,但是验证精度在这个最大深度范围之间并没有下降。

使用上面找到的超参数,让我们训练一个决策树分类器,并使用它来创建预测。下面是我用来训练模型的代码。让我们像以前一样将“class_weight”参数设置为“balanced”。注意,我在原始训练数据上训练模型,而不是 PCA 缩放+变换的数据,因为决策树是尺度不变的。因此,它们不需要对训练数据进行缩放。此外,当决策树在 PCA 变换的数据上训练时,实现了较低的准确性。

from sklearn.tree import DecisionTreeClassifier
dtree=DecisionTreeClassifier(max_depth= 50, max_leaf_nodes=1000, class_weight='balanced')
dtree.fit(X_train,y_train)from sklearn import metrics
train_predictions = dtree.predict(X_train)
test_predictions = dtree.predict(X_test)print("Train Accuracy:",metrics.accuracy_score(y_train, train_predictions))
print("Test Accuracy:",metrics.accuracy_score(y_test, test_predictions))

训练精度:0.6170775710955541
测试精度:0.200000001

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

最终,我们可以看到决策树分类器的准确性有所提高!每个类别标签的 F1 分数也有所增加,表明模型性能有所提高。让我们看看我们是否可以用决策树集成做得更好,或者被称为随机森林模型。

随机森林:

我们可以改进决策树分类器,将树打包成一个集合,并在所有构建的树之间利用多数投票的能力。这被称为随机森林模型。下面是这个模型的代码和模型性能。请注意,模型参数是通过反复试验(同时观察 f1 和准确度分数)选择的,因为网格搜索/随机搜索在计算上非常昂贵。然而,使用所述技术可以进一步优化参数。

from sklearn.ensemble import RandomForestClassifierrf = RandomForestClassifier(n_estimators=150, max_depth=15, class_weight='balanced')
rf.fit(X_train,y_train)train_predictions = rf.predict(X_train)
test_predictions = rf.predict(X_test)print("Train Accuracy:",metrics.accuracy_score(y_train, train_predictions))
print("Test Accuracy:",metrics.accuracy_score(y_test, test_predictions))

训练精度:0.6729519125323106
测试精度:0.100000001

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

我们提高了决策树的准确性,以及每个职业的 f1 分数。接下来,让我们利用 scikit 中的一个函数在随机森林模型中生成一个特性重要性图。这里,特征重要性是通过计算得到的,即节点杂质的减少量,该减少量是通过到达树中该节点的概率来加权的。

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

从该图中,我们可以看到 APR DRG 代码(根据入院原因、疾病严重程度和死亡风险对患者进行分类的分类系统)和 APR 疾病严重程度代码是预测患者住院时间的两个最重要的特征。有趣的是,与其他支付类型组相比,医疗保险支付类型组在预测住院时间方面具有相对较高的重要性。病人的平均收入也起了重要作用。

提升决策树:

最后,让我们看看另一种类型的集成方法:boosting 可以实现什么样的性能。使用 scikit learn 中的 AdaBoostClassifier,我们可以创建一个增强的决策树分类器。该模型通过创建 n 个短的决策树树桩来工作,其中每个连续的树桩都旨在改善前一个树桩的分类错误。这些树的多数投票然后被组合以产生最终的预测。用于实现这一点的代码如下所示,其中使用与随机森林模型等效的方法优化了超参数。

from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_scoredtree = DecisionTreeClassifier(random_state = 1, class_weight = "balanced", max_depth = 15)
boost = AdaBoostClassifier(dtree, n_estimators=75, random_state=0)
boost.fit(X_train, y_train)train_predictions = boost.predict(X_train)
test_predictions = boost.predict(X_test)print("Train Accuracy:", accuracy_score(y_train, train_predictions))
print("Test Accuracy:", accuracy_score(y_test, test_predictions))

训练精度:0.9397049441494455
测试精度:0.20000001

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

在这里,我们可以看到增强决策树实现了最高的模型准确性,击败了逻辑回归分类器和随机森林集成。然而,少数民族班级(不经常出现)的大多数 f1 分数略低。因此,根据患者不同,假阳性或假阴性的严重程度的变化可以保证在使用随机森林模型或增强决策树分类器作为最佳模型之间进行切换。

星火团环境:

由于此数据的规模,一些建模方面(如超参数优化)需要很长时间来运行。因此,我想加入一个关于 Apache Spark 好处的注释。如果我们通过并行化许多计算密集型任务来利用 Apache Spark 和 AWS 集群,我们可以实现显著的代码加速。查看我在这篇博客文章开头链接的完整代码,了解可以用来完成这一任务的脚本。该代码包括如何在 Python 环境中设置 Spark,将 AWS 集群连接到笔记本,从 S3 桶中检索数据集,以及创建模型。我发现在这个项目中使用 Spark 的一个缺点是 Spark ML 模型函数中缺少类权重参数。在完整的代码中,我还展示了手动分配类权重的方法。这段代码改编自一篇博客文章,点击这里可以看到。

结论

最终,通过这篇博文中强调的步骤,我能够使用从患者进入医院并被诊断出的那一刻起就有的数据来预测患者的住院时间,准确率约为 70%。这种模式能够极大地改善医院管理和患者福祉。未来的方向可能是开发第二个模型,允许进行一系列模型预测,最终预测给定患者在住院期间的治疗费用。这可以通过首先通过模型预测住院时间来实现,例如这里创建的模型。接下来,可以创建第二个模型来根据住院时间预测“总成本”。

在将此处创建的模型投入使用之前,还需要考虑重要的伦理因素,因为患者收入和种族等特征被用来预测住院时间。关于这个话题的更多内容可以在这里阅读

外卖:

  • 多类分类设置中分类与回归的优势
  • 字符串索引与一次性编码分类变量的重要性
  • 处理阶层失衡的重要性
  • class_weights 参数的有效性,它消除了对最高频率类进行欠采样的需要(欠采样的缺点是减少了可用于训练的训练数据量)
  • 获取原始数据集并使用它来收集见解和生成预测所需的一般步骤
  • APR DRG 代码和 APR 疾病严重程度代码是预测患者住院时间的两个最重要的特征。此外,与其他支付类型组相比,医疗保险支付类型组在预测住院时间方面具有相对较高的重要性。平均收入对住院时间也有显著影响。

参考文献:

[1].Baek,h .,Cho,m .,Kim,s .,Hwang,h .,Song,m .,和 Yoo,S. (2018 年)。使用电子健康记录分析住院时间长度:一种统计和数据挖掘方法。 PloS one13 (4),e0195901。https://doi.org/10.1371/journal.pone.0195901

[2].sci kit-学习。(未注明)。从 https://scikit-learn.org/stable/取回

本文中的工作扩展了我的最终项目,并利用了我在宾夕法尼亚大学的 CIS 545:大数据分析中学到的概念

IPL 比赛的预测分析

原文:https://towardsdatascience.com/predicting-ipl-match-winner-fc9e89f583ce?source=collection_archive---------6-----------------------

使用 SVM 二元分类器的预测

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

Alessandro Bogliari 在 Unsplash 上的照片

自 2008 年 IPL 诞生以来,它吸引了全球各地的观众。高度的不确定性和最后时刻的紧张刺激了球迷观看比赛。在很短的时间内,IPL 已经成为收入最高的板球联赛。长期以来,数据分析一直是体育娱乐的一部分。在一场板球比赛中,我们可能会看到根据当前比赛情况显示球队获胜概率的比分线。我的朋友,这是在行动中的 D ata A 分析!

想起什么了吗?我们可以把它看作是数据分析的人类版本!来源

作为一个板球迷,可视化的板球统计数据是迷人的。当我在 Kaggle 上浏览 Medium 和 kernels(比如说代码剧本)的博客时,我被所做的分析迷住了。因此,我决定通过构建一个分类器来预测获胜的团队,从而获得第一次实践经验。

在机器学习中,问题主要分为两类:回归问题和分类问题。回归问题处理具有连续值作为输出的问题,而在分类问题中,输出是分类值。由于赢家预测的输出是一个分类值,我们试图解决的问题是一个分类问题。

那么从哪里开始,做什么呢?

  1. 了解数据集。
  2. 清理数据。
  3. 分析要成为特征的候选列。
  4. 按照模型/算法的要求处理特征。
  5. 根据训练数据训练模型/算法。
  6. 在测试数据上测试模型/算法。
  7. 调整模型/算法以获得更高的准确性。

我们开始吧!

英国广播公司的

为了顺利学习,我建议浏览一下我用过的 Python 库,比如 PandasNumpyScikit-learn

步骤 1 —了解数据集!

在处理数据的同时, Kaggle:你的数据科学之家是 to-go 平台。我使用了 https://www.kaggle.com/nowke9/ipldata 的数据集。该数据集有 2 个文件:matches.csv,包含 2008 年至 2019 年的每场比赛的详细信息 deliveries.csv,包含每场比赛的逐球详细信息。

第 2 步—将数据放入操场并进行清理!

我用的是*。read_csv()* 读取 csv 文件。中的路径。read_csv() 函数可以是相对的,也可以是绝对的。在这里,我使用谷歌合作实验室作为我的游乐场,因此文件存储在那里。

没有什么是完美的。生活很乱。关系很复杂。结果不确定。人是不理智的。—休·麦凯

正如 Hugh Mackay 在上面的引用中正确指出的“没有什么是完美的”,在这种情况下,它与我们的数据有关。我们拥有的数据在几列中包含空值。

column null_values
city      7 
winner    4 
player_of_match 4 
umpire1   2 
umpire2   2 
umpire3  637 
dtype: int64

有几种方法可以处理空值,其中,我将对列城市使用插补。插补是一种统计上填补缺失值的方法。更多参考,你可能会发现https://www.kaggle.com/alexisbcook/missing-values很有帮助。由于在列 winner 中填充值是不合理的,我们可以删除这些记录。

的组合。选择()。如果城市中的值为空,则 where()* from numpy 根据地点列替换城市列中的值。*

步骤 3 —进一步预处理数据

在摆弄数据时,我发现了一个有趣的冗余。队伍上升浦那超级巨星队伍 _1队伍 _2胜利者投掷 _ 胜利者中被复制。

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

用一个值替换这些值显然是下一步要做的事情。Python 库使得数据操作变得容易执行。Pandas 允许我们将数据加载到数据帧中,并轻松有效地对其进行操作。

!!数据现在是干净的。我们终于可以开始分析特性(列)了。

第 4 步—特征工程

注:考虑的栏目有: team_1 team_2 toss_winner toss_decision venue city and winner。

为了使这些列能够帮助模型进行预测,这些值应该对计算机有一定的意义。由于他们(仍然)没有能力理解文本并从中得出结论,我们需要将字符串编码为数字分类值。虽然我们可以选择手动完成这个过程,但是 Scikit-learn 库为我们提供了一个使用label encoder的选项。

在我们开始构建模型之前,必须承认一个重要的观察结果。像 toss_winnertoss_decisionwinner 这样的栏目对我们来说可能有意义,但是机器呢?

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

他刚刚过了什么日子?照片由:Guylaine BrunetFlickr上的

我来详细说明一下。 toss_winnerwinner 中的值包含团队名称,但这些变量与 team_1team_2 有什么关系呢?他们之间唯一的共同点是他们会分享相同的价值,但这不足以成为逻辑。另外, toss_decision 可能是球棒或者场地,但是他们指的是哪支球队呢?为了解决这个问题,我们将为列 winnertoss_winnertoss_decision 添加新列 team1_winteam1_toss_winteam1_bat ,以便它们反映与列 team_1 的关系。

如果 team1 赢了,则列 team1_win 中的值将为 1,否则为 0,对于列 team1_toss_decision 来说,如果 team1 赢了,则该值将为 1,并且如果 team1 首先击球,则最后 team1_bat 将为 1。

步骤 5 —特征选择

我们基于我们所拥有的领域知识手动选择了一些特性。但是我们没有统计数据证明所选择的特征对我们的数据集是重要的。 Scikit-learn 提供了一个名为feature _ selection的优秀模块,它为我们提供了几种进行特征选择的方法。首先,我们将检查这些列中是否有任何一列表示与其他列相同的值。为此,我们需要创建一个相关矩阵来找出列之间的关系。如果列之间相关性的绝对值足够高,我们可以说它们表示相似的值。

我们数据的相关矩阵看起来像这样:

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

在这里,我们看到 team1_bat 表示与 team1_toss_win 相同的信息。很奇怪,对吧?这就是数据集是如何建立的,如果第一队赢了掷硬币,那么他们将一直击球,如果第二队赢了掷硬币,那么他们将一直投球。所以我们从我们的特性列表中删除了列 team1_bat

步骤 6 —构建、训练和测试模型

对于一个分类问题,多种算法可以根据我们拥有的数据和使用的模式训练分类器,预测某些输入条件的结果。我们将尝试决策树分类器随机森林分类器逻辑回归SVM ,并选择最适合我们数据分布的算法。

一旦我们构建了模型,我们需要使用从未向模型公开的值来验证该模型。因此,我们使用train _ test _ split(Scikit-learn 提供的一个类)将我们的数据分成两部分,每部分 80–20。该模型针对 80%的数据进行训练,并针对另外 20%的数据进行验证。

我们现在可以训练各种模型并比较性能。

这导致了:

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

从结果可以明显看出,对于该数据分布,**【SVM】**给出了比其他算法更高的准确率 66.23%

尽管精确度不够高,没有用,但它给出了一个关于设计机器学习问题的解决方案时所使用的策略和方法的基本概念。

下一步是什么?

影响比赛结果的还有很多其他因素,比如天气*,球员的状态主场优势等等,这里不包括。尝试添加这些功能,并尝试使用它。通过使用作为 train_test_split 替代方案的 K 倍交叉验证的概念,可以对代码进行进一步修改。在 K-Fold 的链接中查看一篇令人惊叹的文章。*

最后!

既然你已经做到了,我们在预测 IPL 团队获胜的概率方面做了很好的工作,通过将其转换为二进制分类问题,并在学习 Python 库的同时使用 Python 库。如果您有任何问题、建议或反馈,请随时通过[电子邮件](mailto: gpithadia@gmail.com)或 LinkedIn 联系我。你可以在我的 GitHub 上找到这段代码,非常欢迎你来贡献。

预测快乐!

感谢 德鲁米尔·帕特尔赛义德·祖拜尔萨希尔·桑加尼 ,以及 亚什·沙阿 的帮助!**

使用分类模型预测 Kickstarter 活动的成功

原文:https://towardsdatascience.com/predicting-kickstarter-campaign-success-with-classification-models-91b07c63e6ec?source=collection_archive---------36-----------------------

旨在帮助活动家提高他们成功发起运动的机会!

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

Unsplash 上的byrk拍摄的照片

Kickstarter 是一个神奇的平台,帮助企业家发起运动,并“帮助将创意项目带入生活”。虽然任何人都可以在这个网站上传播他们的创意,但不是每个人都能在竞选截止日期前获得足够的承诺。我的项目旨在帮助活动家缩小关注标准,以发起一场成功的运动。

方法学

1。数据来源

从网站 Web Robots 获取 Kickstarter 数据集,该网站抓取所有 Kickstarter 项目并收集 CSV 和 JSON 格式的数据。

2。数据清理

在进一步研究数据之前,对我的特征和虚拟类别变量进行预处理。

**项目类别:**该功能是一个字典,包含有关活动类别的各种信息。我从这个变量中提取了类别名称、类别位置和类别父 ID 信息,做了三个新变量。

**类别名称:**从项目类别变量中提取这些信息后,我将它转换成一个哑变量。

**状态:**最初有 5 种不同的活动状态,包括暂停、取消、成功、失败和活动,为了简化预测,我将分组减少为成功/失败。

3。特征选择&工程

通过计算每个变量的信息值(IV)并仅保留值大于 0.1 的变量来执行特征选择。有关信息价值计算的更多信息,请访问本网站

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

我的功能 IV 表的快照

至于特性工程,我采用了时间戳特性,如创建时间、启动时间、状态更改时间和截止时间,计算它们的差异,得到每个阶段的持续时间。

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

不同时间戳特性的特性工程快照

4。建模

我选择逻辑回归作为我的基线模型,并将数据分成 20%测试、20%验证和 60%训练样本。在将不同的训练、验证和测试样本拟合到我的基线模型中之后,我得到了下表中的结果:

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

逻辑回归模型的结果

训练精度和测试精度非常相似,因此没有过度拟合的迹象。然而,测试召回率高于测试精确度,因此我在其他模型上的精确度得分还有一定的提升空间。

我们还可以查看混淆矩阵,以获得关于模型在哪里出错的更多信息。

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

逻辑回归模型的混淆矩阵

该模型做出的假阳性预测比假阴性预测更多,这意味着对实际上不成功的成功活动的预测比实际上成功的成功活动的预测更多。为了降低我的假阳性预测率,我运行了其他模型来寻求改进。

我首先将我的数据分成 20%的测试和 80%的交叉验证,并将样本拟合到 KNN、随机森林和 AdaBoost 等模型中。在 RandomizedSearchCV 的帮助下,我能够微调每个模型中的参数,并确保我从它们中获得最佳性能。下面是我得到的每个型号的结果表:

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

KNN、随机森林和 AdaBoost 的结果表

虽然随机森林给了我们三个模型中最高的 F-1 分数,但我认为 AdaBoost 是我最好的模型,因为它给了我们最高的精度分数。我把精确的表现放在回忆的表现之上,因为我不想预测不成功的活动会成功。AdaBoost 给我们的精确分数是 0.72,这意味着在 10 次活动中,我的模型正确预测了 7 次活动成功。

结果

为了更好地理解上面的模型是如何工作的,让我们来看看我的特性是如何执行的。下图显示了功能的重要性:

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

特征重要性图

我们可以看到,目标和时间相关特征是预测活动成功的最重要特征。这一发现是有意义的,因为你的竞选活动的成功取决于认捐的数额是否符合你的目标,以及你是否在竞选活动的最后期限内得到认捐的数额。

我们还可以查看下图,了解这些功能以何种方式影响营销活动的结果。

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

特征值与模型输出图

SHAP 值表示特征对模型输出变化的责任。SHAP 值越高,特征对模型的积极影响越大。如果我们只看图表的右半部分,即模型受到积极影响的那一半,我们可以看到哪些特征值有助于发起成功的营销活动。

以“准备持续时间”特性为例,其特性值在图表的整个右半部分都很低(蓝色)。这意味着较短的准备时间有更好的机会发起一场成功的运动。以“目标”特征为例,其特征值在图表的整个右半部分也很低(蓝色)。这意味着一个小目标有更好的机会发起一场成功的运动。至于其他与项目类别相关的特性,不同的类别会对模型产生不同的影响。

图表中的见解与我们的直觉相关,因为如果你的准备时间很短,你更有可能在项目截止日期内完成活动。同样,如果你有一个较小的目标,你就有更大的机会达到符合目标的认捐额。

我还用 Flask 和 Javascript 构建了一个 web 应用程序来演示我的模型性能。该应用程序允许用户输入前 4 个重要特性的值,并检索活动成功的预测。

Web 应用程序演示

结论

根据我的结果部分,我建议活动家:

  • 设定一个适合项目范围的小目标
  • 保持活动持续时间短
  • 仔细考虑类别

为了增加他们成功发起运动的机会!

对于未来的步骤,我想做一个多类分类,考虑到不同的活动状态,而不是成功/失败。此外,我还想收集更长时间内的数据。根据我的直觉,有一些功能会影响模型的性能,但是,对当前模型没有太大影响。也许一旦我延长了数据收集的时间,这些特性就会显示出它们的影响。

如需更多信息,请随时联系我!你也可以在 Github 上查看这个项目的源代码和文档。

预测 Airbnb 房源的市场排名

原文:https://towardsdatascience.com/predicting-market-rank-for-airbnb-listings-59009a886d6?source=collection_archive---------39-----------------------

使用机器学习模型量化房地产竞争力

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

图片来源:Airbnb

动机

有几个原因使得 Airbnb 数据更具挑战性,也更有价值:

  • 与定义目标和指标的 Kaggle 不同,开放式问题定义是一项关键的数据科学技能-如何确定有价值的业务目标并围绕它创建分析框架和建模解决方案?
  • 包括结构化数据、文本和图像在内的丰富信息需要评估和叙述——如何处理数据过多,同时又遗漏了某些数据?
  • 来自 insideairbnb.com 等来源的定期数据更新,提供关键反馈并实现迭代优化
  • 在数据的背后,是有待解释和发掘的地方、人和他们的多元文化。增强 Airbnb 体验可以为人类带来丰富,并使其成为数据科学家的一个有意义和迷人的目标

为什么预测市场排名而不是价格?

在设计机器学习模型之前,首先要问的问题是,我们的目标是什么?目标还应考虑数据的可用性和质量。许多已发表的工作集中在价格预测上。然而,价格可能在不同日期之间大幅波动,这限制了模型的实用性。相反,我会把重点放在一家上市公司相对于其市场竞争对手的排名上。这是一个重要的设计考虑因素,因为相对排名得分捕捉了列表的相对吸引力,并使模型更通用,以适应更多的数据并用于更多的应用。

在这里,我们将市场排名定义为一个列表在特定城市或社区的相对竞争力得分。这个预测模型怎么用?想象一下,如果你是一个主持人,你不仅可以看到你目前的排名与竞争对手相比如何,你还可以评估改变功能(降低价格,增加设施……)以提高你的排名的效果。对于 Airbnb 来说,预测房源受欢迎程度的能力可以为潜在的客人提供有效的推荐(“以下是好莱坞为你推荐的日期和价格范围的前 10 个房源”),或者为主人提供优化推荐(“如果你将清洁费降低 20 美元,你的排名将从前 25%提高到前 10%)。最终,目标是增加销售额和提高客户满意度。

模型设计和培养目标

上市做得越好,它的市场排名就应该越高。我们如何定义和获取监督培训的“市场排名”信息?我们正在寻找能告诉我们一个列表有多受欢迎的数据。虽然我们没有实际的预订信息,但我们有每月更新的可用性和审查数据。让我们来看看这两个关键指标的优缺点:

可用性——可用性本身可能会产生误导,因为列表可能因为被预订或主机退出市场而不可用。通过观察从时间 A 到时间 B 的可用性变化,并查看主机上次更新日历的时间,我们可以更智能地解释变化并导出大多数列表的预订活动

评论——目标观察窗口中评论数量的增加很好地代表了列表的表现。仍然有一个陷阱,那些最小日期越长的列表评论越少(相对于预订的天数)

如图所示,预订率和点评增长率可通过以下方式估算:

  • 对于目标时间范围,查看主机何时更新日历以及可用性如何随时间变化,计算预订率
  • 对于相同的目标时间范围,查看添加了多少评论,并计算评论率

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

预订率和评论率相辅相成,为单个房源提供市场排名指标。它们被缩放和标准化以用作回归模型的训练目标。为了进一步多样化,我基于列表特征的子集训练了预订率模型和评论率模型,同时防止数据泄露。所得到的预订率得分和评论率得分然后被合计为一个组合得分,该组合得分然后被用来以百分位数的形式生成市场排名,量化列表在任何城市、区域或邻近地区的相对实力。

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

开发基线模型

对于原型,我使用了洛杉矶 airbnb 房源的数据,2019 年 3 月 6 日为时间 A,2019 年 12 月 5 日为时间 B,2019 年 12 月 5 日+ 30 日为目标预订时间窗口。为了简单起见,我使用 XGBoost 进行最少量的数据处理和调优。

下图显示了审核率模型的样本验证曲线,其 R2 分数约为 0.6。这将作为一个基线,通过添加功能、数据、调整等,有可能进行改进

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

下图显示了预订率模型的学习曲线示例。随着数据量的增加,训练和验证之间的差距(表示方差)显示出缩小的趋势。正如所料,从误差水平来看,偏差明显存在,可以通过特性和算法来改善。

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

下图显示了两个回归模型的 SHAP 汇总图。这些特征按照它们对模型结果的影响从上到下排列。对于每个特征,其影响通过其在水平轴上的范围来可视化。红色表示较高的特征值,蓝色表示较低的特征值。向右扩展量化了积极影响(特征值越高,预订和评论率越高,因此列表越热门)。向左延伸量化了负面影响。一些快速观察:

  • 不出所料,更高的价格、更少的点评、更长的最低住宿时间会对预订率产生负面影响
  • 客人最喜欢整个家/公寓
  • 咖啡机、自助入住等简单功能有助于提升房源
  • 这两种型号的功能影响不同,因此它们是互补的

SHAP(SHapley Additive exPlanations)是一种新兴的算法不可知的可解释 AI (XAI)方法,它利用博弈论来衡量特征对预测的影响。详细的 SHAP 分析超出了这里的范围。

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

图解市场排名

在这里,我们使用洛杉矶地区保留的列表测试集来评估模型。在结合预订模型和评论模型的得分后,我们以百分位数的形式获得一个城市范围的排名得分(“market_rank_city”)。例如,就其市场竞争力而言,列表 ID 8570847 位于顶部 98.6%,而列表 ID 14014479 位于底部 6.9%。

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

按照标准 url 格式【https://www.airbnb.com/rooms/查看实际列表,看看分数是否有意义。

市场排名也可以计算出一个明确的目标群体,导致更多的应用。例如,我们可以对某个价格范围内某个特定区域的列表进行排名。我们可以应用任何特征值作为过滤器来比较子集中列表的竞争力。

下面是计算好莱坞附近价格为 150 美元到 250 美元的列表的百分位数排名(“market_rank_neighborhood”)的示例。

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

从上面的列表中,我们来看看最上面的列表,这是一个新的带完整厨房的 2 卧室公寓,售价 174 美元/晚:【https://www.airbnb.com/rooms/32792761】T4

下面是一个 13 平方英尺的房间,配有一张双人床,价格为 199 美元/晚:https://www.airbnb.com/rooms/28012404

对新上市公司的业绩进行建模

请注意,我们包括历史信息,如评论和预订活动的增长率,以预测未来的结果。这不是数据泄露的一种形式。相反,它真实地反映了潜在客户对房源的评价。因此,model 对新上市的产品更加中立,因为它缺少许多特性的信息。这也是现实的真实反映。

为了更准确地区分新上市公司的质量,需要开发侧重于便利设施、照片、文本和位置等特征的模型。想想 KNN 建立在随时间恒定的特征子集上。

下一步是什么

我分享了一个利用真实世界数据的数据科学项目的旅程,从一个有意义的目标开始,通过研究可用数据和试验模型组合,到有希望的结果。开发的基线模型仅仅触及了可能的表面。由于 airbnb 数据的巨大数量和动态性质,进一步的改进可能来自更多的数据清理、功能工程和算法调整。添加图像和文本信息也有助于深度学习的激动人心的探索。

更多 Airbnb 功能分析及可解释 AI (XAI)的图解使用请参考:https://medium . com/@ Wang . Sean . x/boosting-machine-learning-models-with-explable-AI-xai-601683119 c84

回归预测国际足联足球运动员的市场价值

原文:https://towardsdatascience.com/predicting-market-value-of-fifa-soccer-players-with-regression-5d79aed207d9?source=collection_archive---------18-----------------------

线性、套索、岭、弹性网和多项式回归的案例研究。

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

福赞·萨里Unsplash 上拍摄的照片

自 Metis 数据科学训练营开始以来,三周已经过去了,这段旅程可谓紧张而激动人心。在这篇文章中,我详细介绍了我利用过去两周仔细学习的关于 web 抓取和回归的技能和知识构建的项目。在浏览了各种网站后,我最终选定了一个有趣的话题——国际足联足球运动员的市场价值预测!

一个足球运动员的市场价值是多少?

当我们谈论一名足球运动员的市场价值时,我们指的是他的足球俱乐部可以出售或将其合同转让给另一家俱乐部的估计金额。足球俱乐部可以支付天文数字来获得顶级球员。正如我们将在后面看到的,足球运动员的市场价值遵循指数趋势,这表明一小部分运动员具有很高的价值。因此,预测市场价值的能力可能会给一些富有的足球俱乐部带来商业优势。

推动市场价值的最重要因素是什么?经过研究,我列出了以下因素:

  • 足球技能:因为没有一个足球运动员是 100%全能的,所以足球技能分为防守、射门和守门几个领域。在这些领域中的任何一个领域拥有高评级都可以提升你的市场价值。
  • 场上位置:平均来说,前锋比中场更被看重,其次是后卫。
  • 年龄:或者青春的系数。自然,年轻球员将拥有更高的市场价值,因为他们有更大的增长潜力和更长的服务期限。
  • **媒体覆盖率:**或媒体系数。一般来说,拥有受欢迎的球员,他们会产生更大的媒体影响,可以为俱乐部带来更多的收入。

尽管如此,由于这些因素的一些数据很难获得,我将尝试创建一个可行的回归模型,仅基于足球技能和年龄来预测市场价值。下面我详细介绍这个项目的过程和结果。

美汤刮网

I web 用经典的 Python 模块美汤刮出了 FIFA 指数网站。我总共收集了 19,401 名球员的数据,包括他们的身高、体重、年龄、偏好的脚和技能评分。每个技能等级都被细分到不同的领域,这些领域的得分从 0 到 100。因此,技能等级是通过取其领域的平均值来进行网络搜集的。足球运动员及其各自领域的技能评级如下:

  • 球技 : 控球,运球
  • 传球 : 传中,短传,长传
  • 防守 : 盯人,滑铲,立铲
  • 心理 : 攻击性、反应、攻击位置、拦截、视野、沉着
  • 体能 : 加速度、耐力、力量、平衡、冲刺速度、敏捷性、跳跃
  • 射门 : 头球、射门力度、射门、远射、弧线球、任意球准确性、点球、凌空抽射
  • 守门员 : 定位、假摔、处理、踢球、反应

以下是我用来收集所有数据的脚本:

在做了一些轻微的处理和剔除一些没有市场价值数据的球员后,这里是数据框架的总结:

探索性数据分析

绘制特征和目标(市场价值)的热图揭示了一些有趣的趋势:身高、体重、年龄、偏好的脚和守门员似乎与目标变量无关:

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

作者图片

因此,问题是我们应该删除这些功能吗?我们已经从领域知识中了解到,年龄是市场价值的一个重要预测指标。守门员技术怎么样?请注意,守门与其他技能指标呈负相关。这并不奇怪,因为守门员大多是专业的,很少上场比赛。然而,如配对图所示,其中一些守门员的价值很高:

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

作者图片

因此,删除守门员特征可能会导致对守门员市场价值的预测下降,也使模型不稳定。配对图还显示了市场价值的指数分布,揭示了赢家通吃的情况。

特征选择和工程

因此,我们继续对市场价值取对数,试图使数据线性化。此外,身高、体重和偏好的脚的特征被删除。如使用 Statsmodels 软件包绘制的 OLS 回归总结所示,该模型得到了显著改进:

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

作者图片

更不用说调整后的 R 值从 0.32 提高到 0.67,对数似然性也增加了,表明拟合优度更好。此外,残差遵循更加正态的分布,偏斜度几乎降至 0,峰度几乎降至 3,满足正态假设。此外,与目标变量的相关性在所有特性中得到了极大的提高。

我们可以从 OLS 总结中观察到的其他见解是年龄和流逝特征的负系数。虽然我们已经知道年龄与市场价值呈负相关,但及格的负系数还是令人吃惊。这意味着,如果一个球员提高了他的传球技术,平均来说,他的市场价值会随之下降!一个可能的解释是,市场会奖励更有统治力的球员,而更擅长传球的球员可能在其他领域更弱。

型号选择

现在,为了拟合数据,我们希望比较的回归模型是简单线性回归、套索回归、岭回归、弹性网回归和多项式回归。请注意,LASSO、Ridge 和 Elastic Net 只是线性回归的正则化版本,它将额外的正则化项添加到我们希望最小化的成本函数中。这些正则化项中的每一项都包含超参数α,其值在模型选择期间选择。在继续之前,我们将整个数据框架随机分为 80%的训练集和 20%的测试集,其中我们保留测试集用于最终的模型评估。对于模型选择,我们进一步随机将训练集分成 5 个部分进行交叉验证。

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

作者图片

通过对 5 重 CV 中的验证集取平均分数(平均绝对误差),为套索、脊和弹性网选择最佳阿尔法。多项式回归也选择最佳次数。因此,最佳 Alphas 和度数为:

  • 套索回归:大约。0
  • 岭回归:0.93
  • 弹性净回归:大约。0
  • 多项式回归:4 次

因为套索和弹性网的 Alpha 值可以忽略不计,所以它们可以近似为线性回归模型。比较其余模型的性能,显然多项式回归(4 次)胜出:

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

模型评估

是时候在测试集上给我们的多项式回归模型打分了!在对日志市场价值的测试集进行评分时,结果仍然非常具有可比性,r 为 0.930,平均绝对误差为 0.279,尽管峰度约为 1。

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

作者图片

Q-Q 图也是非常线性的,代表了对数据的良好模型拟合。然而,在我们对结果感到高兴之前,我们应该记住,我们已经在前面对目标变量取了对数。当我们“取消记录”预测的目标变量,并与测试集中的原始市场价值进行比较时,会发生什么?

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

作者图片

在不取对数的情况下,对市场价值的测试集进行评分,我们得到 r 为 0.836,€平均绝对误差为 668,684,峰度为 234!结果是令人惊讶的,但是我应该强调,这是我们用回归和我们选择的有限特性可能实现的最佳模型。

下面是比较市场价值和预测市场价值的测试集的最终数据框架的快照。虽然预测通常遵循实际市场价值的趋势,但我们能够观察到一些异常值。此外,该模型似乎也有利于捍卫者,如将维吉尔·范·迪克和吉奥吉奥·基耶利尼排在前 5 行所证明的。一个更准确的模型会更有利于罢工者。

结论和未来工作

尽管如此,考虑到我使用的有限特性,最终模型的结果还是相当不错的。今后,如果有其他数据来源,应考虑球员在场上的位置和媒体系数等重要特征。

话虽如此,我期待在未来几周从 Metis 数据科学训练营学习更多的机器学习技术!谁知道呢?随着更多的机器学习工具,如神经网络,我们可能会重新访问该项目,并设计一个更好的模型。

这里是到我的 GitHub 的链接,它包含了这个项目的所有代码和演示幻灯片。

你觉得我的模型怎么样?通过我的 LinkedIn联系我或者在下面评论来讨论!

附:感谢阅读我关于 回归 的作品。如果你也有兴趣了解 分类 ,那就来看看我的下一个项目:

[## 用分类预测航空旅客的满意度

案例研究与 KNN,逻辑回归,高斯 NB,决策树和随机森林。

towardsdatascience.com](/predicting-satisfaction-of-airline-passengers-with-classification-76f1516e1d16)

支持我! —如果你没有订阅 Medium,并且喜欢我的内容,请考虑通过我的推荐链接加入 Medium 来支持我。

[## 加入我的介绍链接媒体-谭师鹏阿尔文

阅读谭·师鹏·阿尔文(以及媒体上成千上万其他作家)的每一个故事。您的会员费直接…

tanpengshi.medium.com](https://tanpengshi.medium.com/membership)

使用 Python 预测缺失值

原文:https://towardsdatascience.com/predicting-missing-values-with-python-41e581511117?source=collection_archive---------14-----------------------

建立数据插补模型

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

来源

对于数据科学家来说,处理缺失数据是数据清理和模型开发过程的重要部分。通常,真实数据包含多个稀疏字段或充满错误值的字段。在本帖中,我们将讨论如何构建模型来估算数据中缺失或错误的值。

我们开始吧!

出于我们的目的,我们将使用葡萄酒数据集,这个数据集可以在这里找到。

首先,让我们将数据读入熊猫数据框:

import pandas as pd
df = pd.read_csv("winemag-data-130k-v2.csv")

接下来,让我们打印前五行数据:

print(df.head())

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

让我们从这些数据中随机抽取 500 条记录。这将有助于加速模型训练和测试,尽管读者可以很容易地修改它:

import pandas as pd
df = pd.read_csv("winemag-data-130k-v2.csv").sample(n=500, random_state = 42)

现在,让我们打印与我们的数据相对应的信息,这将使我们了解哪些列有缺失值:

print(df.info())

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

有几列的非空值少于 500 个,这相当于缺少值。首先,让我们考虑建立一个模型,使用“点”估算缺失的“价格”值。首先,让我们打印“价格”和“积分”之间的相关性:

print("Correlation: ", df['points'].corr(df['price']))

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

我们看到有一个微弱的正相关。让我们建立一个线性回归模型,用“点”来预测“价格”。首先,让我们从“scikit-learn”导入“LinearRegresssion”模块:

from sklearn.linear_model import LinearRegression

现在,让我们将我们的数据分开用于训练和测试。我们希望能够预测缺失的值,但是我们应该使用基本事实“价格”值来验证我们的预测。让我们通过只选择正价格值来过滤掉缺少的值:

import numpy as np 
df_filter = df[df['price'] > 0].copy()

让我们也初始化我们将用来存储我们的预测和实际值的列表:

y_pred = []
y_true = []

我们将使用 K 折交叉验证来验证我们的模型。让我们从“scikit-learn”导入“KFolds”模块。我们将使用 10 个折叠来验证我们的模型:

from sklearn.model_selection import KFold
kf = KFold(n_splits=10, random_state = 42)
for train_index, test_index in kf.split(df_filter):
    df_test = df_filter.iloc[test_index]
    df_train = df_filter.iloc[train_index]

我们现在可以定义我们的输入和输出:

for train_index, test_index in kf.split(df_filter):
    ...
    X_train = np.array(df_train['points']).reshape(-1, 1)     
    y_train = np.array(df_train['price']).reshape(-1, 1)
    X_test = np.array(df_test['points']).reshape(-1, 1)  
    y_test = np.array(df_test['price']).reshape(-1, 1)

并符合我们的线性回归模型:

for train_index, test_index in kf.split(df_filter):
    ...
    model = LinearRegression()
    model.fit(X_train, y_train)

现在让我们生成并存储我们的预测:

for train_index, test_index in kf.split(df_filter):
    ...
    y_pred.append(model.predict(X_test)[0])
    y_true.append(y_test[0])

现在让我们来评估我们模型的性能。让我们使用均方误差来评估我们模型的性能:

print("Mean Square Error: ", mean_squared_error(y_true, y_pred))

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

我们看到表演不是太好。我们可以通过对平均价格加上一个标准差的价格进行训练来改善这一点:

df_filter = df[df['price'] <= df['price'].mean() + df['price'].std() ].copy()
...
print("Mean Square Error: ", mean_squared_error(y_true, y_pred))

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

虽然这显著提高了性能,但代价是无法准确估算高价葡萄酒的价值。我们可以不使用单一特征的回归模型来预测价格,而是使用基于树的模型,如随机森林,它可以处理分类和数字变量。让我们建立一个随机森林回归模型,使用“国家”、“省份”、“品种”、“酒厂”和“点数”来预测葡萄酒的“价格”。首先,让我们将分类变量转换成可由随机森林模型处理的分类代码:

df['country_cat'] = df['country'].astype('category')
df['country_cat'] = df['country_cat'].cat.codesdf['province_cat'] = df['province'].astype('category')
df['province_cat'] = df['province_cat'].cat.codesdf['winery_cat'] = df['winery'].astype('category')
df['winery_cat'] = df['winery_cat'].cat.codesdf['variety_cat'] = df['variety'].astype('category')
df['variety_cat'] = df['variety_cat'].cat.codes

让我们将随机样本量增加到 5000:

df = pd.read_csv("winemag-data-130k-v2.csv").sample(n=5000, random_state = 42)

接下来,让我们从 scikit-learn 导入随机森林回归器模块。让我们还定义我们将用来训练我们的模型的特征列表:

from sklearn.ensemble import RandomForestRegressor
features = ['points', 'country_cat', 'province_cat', 'winery_cat', 'variety_cat']

让我们使用具有 1000 个估计器和最大深度 1000 的随机森林来训练我们的模型。然后,让我们生成预测并将它们追加到一个新列表中:

for train_index, test_index in kf.split(df_filter):
    df_test = df_filter.iloc[test_index]
    df_train = df_filter.iloc[train_index]

    X_train = np.array(df_train[features])
    y_train = np.array(df_train['price'])
    X_test = np.array(df_test[features])
    y_test = np.array(df_test['price'])
    model = RandomForestRegressor(n_estimators = 1000, max_depth = 1000, random_state = 42)
    model.fit(X_train, y_train) y_pred_rf.append(model.predict(X_test)[0])
    y_true_rf.append(y_test[0])

最后,让我们评估随机森林和线性回归模型的均方误差:

print("Mean Square Error (Linear Regression): ", mean_squared_error(y_true, y_pred))
print("Mean Square Error (Random Forest): ", mean_squared_error(y_pred_rf, y_true_rf))

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

我们看到随机森林模型具有优越的性能。现在,让我们使用我们的模型预测缺失的价格值,并显示预测示例:

df_missing = df[df['price'].isnull()].copy()X_test_lr = np.array(df_missing['points']).reshape(-1, 1)
X_test_rf = np.array(df_missing[features])X_train_lr = np.array(df_filter['points']).reshape(-1, 1)    
y_train_lr = np.array(df_filter['price']).reshape(-1, 1)X_train_rf = np.array(df_filter[features])
y_train_rf = np.array(df_filter['price'])model_lr = LinearRegression()
model_lr.fit(X_train_lr, y_train_lr)
print("Linear regression predictions: ", model_lr.predict(X_test_lr)[0][0])model_rf = RandomForestRegressor(n_estimators = 1000, max_depth = 1000, random_state = 42)
model_rf.fit(X_train_rf, y_train_rf)
print("Random forests regression predictions: ", model_rf.predict(X_test_rf)[0])

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

我就讲到这里,但我鼓励您尝试特性选择和超参数调整,看看是否可以提高性能。此外,我鼓励您扩展此数据估算模型,以估算分类字段中的缺失值,如“区域 _1”和“指定”。在这里,您可以构建一个基于树的分类模型,该模型根据分类和数字特征进行训练,以预测所列类别的缺失值。

结论

总之,在这篇文章中,我们讨论了如何建立机器学习模型,我们可以用它来估算数据中的缺失值。首先,我们建立了一个线性回归模型,对评论的葡萄酒进行“点数”训练,以预测葡萄酒的价格。然后,我们建立了一个随机森林模型,根据“点数”和其他分类变量来预测葡萄酒价格。我们看到随机森林模型明显优于基于线性回归的数据插补模型。我希望你觉得这篇文章有用/有趣。这篇文章的代码可以在 GitHub 上找到。感谢您的阅读!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值