我们正在用Python做一个机器学习项目。 第一部分



完整机器学习项目Python的翻译:第一部分

当您阅读一本书或听一听有关数据分析的培训课程时,您常常会感觉到您面对的是图片中某些无法放在一起的单独部分。 您可能会害怕采取下一步并借助机器学习完全解决问题的前景,但是借助本系列文章,您将对解决数据科学领域中任何问题的能力充满信心。

为了使您最终了解完整的图像,我们建议从头到尾分析使用真实数据进行机器学习的项目。

依次执行以下步骤:

  1. 清洁和格式化数据。
  2. 探索性数据分析。
  3. 设计和选择功能。
  4. 几种机器学习模型的指标比较。
  5. 最佳模型的超参数调整。
  6. 在测试数据集上评估最佳模型。
  7. 解释模型的结果。
  8. 结论并使用文档。

您将学习阶段如何进入另一个阶段以及如何在Python中实现它们。 整个项目可在GitHub上找到,第一部分位于此处。 在本文中,我们将考虑前三个阶段。

任务说明


在编写代码之前,您需要了解要解决的问题和可用数据。 在此项目中,我们将使用纽约建筑物的公共能效数据

我们的目标是:使用可用数据来构建模型,该模型预测特定建筑物的能源之星评分,并解释结果以查找影响最终评分的因素。

数据已经包含分配的能源之星评分,因此我们的任务是在受控回归下进行机器学习:

  • 监督:我们知道标志和目的,我们的任务是训练可以比较第一个模型和第二个模型的模型。
  • 回归:能源之星得分是一个连续变量。

我们的模型必须准确-以便可以预测接近真实的“能源之星”评分值-并且可以解释-以便我们了解其预测。 了解目标数据后,我们可以在深入数据和创建模型时进行决策时使用它们。

数据清理


并非每个数据集都是观察值的完美匹配,没有异常和缺失值(提示mtcarsiris 数据集 )。 在真实数据中,顺序很少,因此在开始分析之前,需要清除它并将其转换为可接受的格式。 数据清理是解决大多数数据分析任务时不愉快但必不可少的过程。

首先,您可以以Pandas数据框的形式加载数据并检查它们:

import pandas as pd import numpy as np # Read in data into a dataframe data = pd.read_csv('data/Energy_and_Water_Data_Disclosure_for_Local_Law_84_2017__Data_for_Calendar_Year_2016_.csv') # Display top of dataframe data.head() 


这就是真实数据的外观。

这是一个60列的表格的一部分。 即使在这里,仍然存在一些问题:我们需要预测Energy Star Score ,但我们不知道所有这些列的含义。 尽管这不一定是问题,但是因为您经常可以创建准确的模型而根本不了解变量。 但是可解释性对我们很重要,因此我们需要找出至少几列的含义。

收到此数据时,我们没有询问这些值,而是查看了文件名:



并决定搜索“ 84号地方法律”。 我们发现此页面该页面表示我们正在谈论纽约现行法律,根据该法律,一定规模的所有建筑物的所有者都应报告能耗。 进一步的搜索有助于找到所有列值 。 因此,不要忽略文件名,它们可以是一个很好的起点。 另外,这提醒您不要着急,不要错过重要的事情!

我们不会研究所有的列,但是我们肯定会处理能源之星评分,其描述如下:

百分等级是1到100,这是根据建筑物所有者自己的年度能耗报告得出的。 能源之星评分是用于比较建筑物的能源性能的相对度量。

第一个问题已解决,但第二个问题仍然存在-缺少值,标记为“不可用”。 这是Python中的字符串值,这意味着即使是带数字的字符串也将作为object数据类型存储,因为如果列中有任何字符串,Pandas会将其转换为完全由字符串组成的列。 可以使用dataframe.info()方法找到列数据类型:

 # See the column data types and non-missing values data.info() 



当然,某些明确包含数字的列(例如ft²)将作为对象存储。 我们无法对字符串值进行数值分析,因此我们将其转换为数值数据类型(尤其是float )!

此代码首先用一个数字np.nan )替换所有“不可用”(可以解释为数字),然后将某些列的内容转换为float类型:

 # Replace all occurrences of Not Available with numpy not a number data = data.replace({'Not Available': np.nan}) # Iterate through the columns for col in list(data.columns): # Select columns that should be numeric if ('ft²' in col or 'kBtu' in col or 'Metric Tons CO2e' in col or 'kWh' in col or 'therms' in col or 'gal' in col or 'Score' in col): # Convert the data type to float data[col] = data[col].astype(float) 

当与我们相对应的列中的值变成数字时,我们可以开始检查数据。

丢失和异常数据


除了不正确的数据类型外,最常见的问题之一就是缺少值。 由于各种原因可能会不存在这些值,在训练模型之前,必须填写或删除这些值。 首先,让我们找出每一列中有多少个值( 代码在此处 )。


要创建表,使用了StackOverflow分支上的函数。

信息应始终谨慎删除,并且如果该列中有很多值,则可能对我们的模型没有好处。 删除列的最佳阈值取决于您的任务( 这里是一个讨论 ),在我们的项目中,我们将删除多于一半的空列。

同样在此阶段,最好删除异常值。 它们可能是由于输入数据时出现错别字或由于测量单位中的错误而发生,也可能是正确的但极高的值。 在这种情况下,我们将根据极端异常定义删除“额外”值:

  • 在第一个四分位数下方是一个3 *四分位数范围。
  • 高于第三四分位数+ 3 *四分位数范围。

Github上的记事本上列出了删除列和异常的代码。 完成数据清理过程并清除异常后,我们拥有11,000多座建筑物和49个标志。

探索性数据分析


无聊但必要的数据清理阶段已经完成,您可以继续学习! 探索性数据分析 (RAD)是一个无限时间的过程,在此过程中,我们将计算统计数据并查找数据中的趋势,异常,模式或关系。

简而言之,RAD试图弄清楚哪些数据可以告诉我们。 通常,分析是从表面综述开始的,然后我们找到有趣的片段并进行更详细的分析。 这些发现本身可能会很有趣,或者它们可能有助于模型的选择,从而有助于决定我们将使用哪些功能。

单变量图


我们的目标是预测“能源之星”得分的值(在数据中更名为我们的score ),因此从检查此变量的分布开始是有意义的。 直方图是一种可视化单个变量分布的简单但有效的方法,可以使用matplotlib轻松构建直方图。

 import matplotlib.pyplot as plt # Histogram of the Energy Star Score plt.style.use('fivethirtyeight') plt.hist(data['score'].dropna(), bins = 100, edgecolor = 'k'); plt.xlabel('Score'); plt.ylabel('Number of Buildings'); plt.title('Energy Star Score Distribution'); 



看起来可疑! 能源之星评分是一个百分位数,因此当每个点分配给相同数量的建筑物时,您应该期望分配均匀。 但是,不成比例的大量建筑物获得了最高和最低的结果(对于能源之星评分,越大越好)。

如果再次查看该得分的定义,我们将看到它是根据“由建筑物所有者独立填写的报告”计算得出的,这可以解释非常大的值的过高之处。 要求建筑业主报告其能源消耗就像要求学生在考试中报告其成绩。 因此,这可能不是评估房地产能源效率的最客观标准。

如果我们有无限的时间供应,那么我们可以找出为什么这么多建筑物达到很高和很低的点。 为此,我们必须选择适当的建筑物并仔细分析它们。 但是,我们只需要学习如何预测分数,而无需开发更准确的评估方法。 您可以标记自己为可疑点,但我们将重点放在预测上。

关系搜索


AHFR的主要部分是寻找标志与目标之间的关系。 与之相关的变量可用于模型,因为它们可用于预测。 研究分类变量(仅需要有限的一组值)对目标的影响的一种方法是使用Seaborn库绘制密度。

密度图可以视为平滑的直方图,因为它显示了单个变量的分布。 您可以为图表上的各个类着色,以查看分类变量如何更改分布。 该代码绘制了能源之星得分密度图表,根据建筑物的类型(对于尺寸超过100的建筑物列表)进行了着色:

 # Create a list of buildings with more than 100 measurements types = data.dropna(subset=['score']) types = types['Largest Property Use Type'].value_counts() types = list(types[types.values > 100].index) # Plot of distribution of scores for building categories figsize(12, 10) # Plot each building for b_type in types: # Select the building type subset = data[data['Largest Property Use Type'] == b_type] # Density plot of Energy Star Scores sns.kdeplot(subset['score'].dropna(), label = b_type, shade = False, alpha = 0.8); # label the plot plt.xlabel('Energy Star Score', size = 20); plt.ylabel('Density', size = 20); plt.title('Density Plot of Energy Star Scores by Building Type', size = 28); 



如您所见,建筑物的类型极大地影响了点数。 办公大楼通常得分较高,而酒店则较低。 因此,您需要在模型中包括建筑物的类型,因为该符号会影响我们的目标。 作为分类变量,我们必须对建筑物类型执行一次热编码。

可以使用类似的图形来按城市区域估算能源之星得分:



面积对得分的影响不如建筑物类型大。 尽管如此,我们仍将其包括在模型中,因为区域之间存在细微差异。

要计算变量之间的关系,可以使用Pearson相关系数 。 这是两个变量之间线性关系的强度和方向的量度。 值+1表示完全线性正关系,而值-1表示完全线性负关系。 以下是Pearson相关系数值的一些示例:



尽管该系数不能反映非线性依赖性,但是可以从它开始评估变量之间的关系。 在Pandas中,您可以轻松计算数据框中任何列之间的相关性:

 # Find all correlations with the score and sort correlations_data = data.corr()['score'].sort_values() 

与目标最负相关:



最积极的是:



属性和目标之间存在很强的负相关性,其中最大的属于不同的EUI类别(计算这些指标的方法略有不同)。 EUI(能源使用强度 )是建筑物消耗的能量除以平方英尺的面积。 该特定值用于评估能效,数值越小越好。 逻辑表明这些相关性是合理的:如果EUI增加,则能源之星得分应下降。

二元图


我们使用散点图可视化两个连续变量之间的关系。 您可以将其他信息添加到点的颜色,例如,分类变量。 能源之星评分和EUI之间的关系如下所示,颜色表示不同类型的建筑物:



该图使您可以直观地看到-0.7的相关系数。 随着EUI的降低,能源之星评分增加,这种关系在不同类型的建筑物中都可以观察到。

我们最新的研究图表称为对图 。 这是查看不同变量对和单个变量分布之间关系的好工具。 我们将使用Seaborn库和PairGrid函数创建一个配对图,在上三角图中具有散点图,在对角直方图,二维核心密度图和下三角中具有相关系数。

 # Extract the columns to plot plot_data = features[['score', 'Site EUI (kBtu/ft²)', 'Weather Normalized Source EUI (kBtu/ft²)', 'log_Total GHG Emissions (Metric Tons CO2e)']] # Replace the inf with nan plot_data = plot_data.replace({np.inf: np.nan, -np.inf: np.nan}) # Rename columns plot_data = plot_data.rename(columns = {'Site EUI (kBtu/ft²)': 'Site EUI', 'Weather Normalized Source EUI (kBtu/ft²)': 'Weather Norm EUI', 'log_Total GHG Emissions (Metric Tons CO2e)': 'log GHG Emissions'}) # Drop na values plot_data = plot_data.dropna() # Function to calculate correlation coefficient between two columns def corr_func(x, y, **kwargs): r = np.corrcoef(x, y)[0][1] ax = plt.gca() ax.annotate("r = {:.2f}".format(r), xy=(.2, .8), xycoords=ax.transAxes, size = 20) # Create the pairgrid object grid = sns.PairGrid(data = plot_data, size = 3) # Upper is a scatter plot grid.map_upper(plt.scatter, color = 'red', alpha = 0.6) # Diagonal is a histogram grid.map_diag(plt.hist, color = 'red', edgecolor = 'black') # Bottom is correlation and density plot grid.map_lower(corr_func); grid.map_lower(sns.kdeplot, cmap = plt.cm.Reds) # Title for entire plot plt.suptitle('Pairs Plot of Energy Data', size = 36, y = 1.02); 



要查看变量之间的关系,请查找行和列的交集。 假设您要查看Weather Norm EUIscore之间的相关性,然后寻找Weather Norm EUI系列和score列,它们的相交系数为-0.67。 这些图不仅看起来很酷,而且还有助于选择模型的变量。

设计和特征选择


设计和选择功能通常会在机器学习上花费的时间带来最大的回报。 首先我们给出定义:

  • 特征构建:从原始数据中提取或创建新特征过程。 要在模型中使用变量,您可能需要对其进行转换,例如,采用自然对数,或提取平方根,或对分类变量应用一键编码。 可以将特征设计视为从原始数据创建其他功能。
  • 特征选择:从数据中选择最相关的特征过程,在此过程中,我们删除了一些特征以帮助模型更好地概括新数据,以获得更易解释的模型。 标志的选择可以被认为是去除了“多余的”,因此只有最重要的部分仍然存在。

机器学习模型只能从我们提供的数据中学习,因此确保我们包含与任务相关的所有信息非常重要。 如果您没有为模型提供正确的数据,它将无法学习,也无法产生准确的预测!

我们将执行以下操作:

  • 适用于分类变量(所有权的季度和类型)一键编码。
  • 加上所有数值变量的自然对数。

为了将分类变量包括在模型中,必须进行一次热编码 。 机器学习算法将无法理解“办公室”的类型,因此,如果建筑物是办公室,我们将为其分配属性1;如果不是办公室,则将属性分配为0。

添加变换后的特征将有助于模型了解数据中的非线性关系。 在数据分析中,通常的做法是提取平方根,取自然对数或以某种方式转换符号 ,这取决于特定的任务或您对最佳技术的了解。 在这种情况下,我们将添加所有数字符号的自然对数。

该代码选择数字符号,计算其对数,选择两个分类符号,对其进行一次热编码,然后将这两个集合组合为一个。 从描述来看,还有很多工作要做,但是在Pandas中,一切都很简单!

 # Copy the original data features = data.copy() # Select the numeric columns numeric_subset = data.select_dtypes('number') # Create columns with log of numeric columns for col in numeric_subset.columns: # Skip the Energy Star Score column if col == 'score': next else: numeric_subset['log_' + col] = np.log(numeric_subset[col]) # Select the categorical columns categorical_subset = data[['Borough', 'Largest Property Use Type']] # One hot encode categorical_subset = pd.get_dummies(categorical_subset) # Join the two dataframes using concat # Make sure to use axis = 1 to perform a column bind features = pd.concat([numeric_subset, categorical_subset], axis = 1) 

现在,我们拥有110列(标记)的11,000多个观测值(建筑物)。 并非所有的符号都对预测能源之星得分有用,因此我们将选择符号并删除一些变量。

功能选择


可用的110个标志中有许多是多余的,因为它们相互之间有很强的相关性。 例如,这是EUI和天气标准化站点EUI的图形,相关系数为0.997。



彼此强烈相关的符号称为共线 。 在这样的属性对中删除一个变量通常有助于模型泛化并且更易于解释 。 请注意,我们在谈论的是某些符号与其他符号的相关性,而不是与目标的相关性,这只会对我们的模型有所帮助!

有多种计算特征共线性的方法,其中最流行的一种是方差膨胀因子 。 我们将使用bcorrelation系数搜索和删除共线特征。 如果一对符号之间的相关系数大于0.6,则我们将其丢弃。 该代码位于记事本中(并用于响应Stack Overflow )。

该值看起来是任意的,但实际上我尝试了不同的阈值,以上所述使我可以创建最佳模型。 机器学习是经验性的 ,通常必须进行实验以找到最佳解决方案。 选择后,我们有64个属性和一个目标。

 # Remove any columns with all na values features = features.dropna(axis=1, how = 'all') print(features.shape) (11319, 65) 

选择基本等级


我们清除了数据,进行了探索性分析,并构造了标志。 在继续创建模型之前,您需要选择初始基准级别(未使用的基准),这是一种假设,我们将以此与模型结果进行比较。 如果它们低于基本水平,我们将假定机器学习不适用于此任务,或者应尝试其他方法。

对于回归任务,作为基本级别,对于测试集中的所有示例,合理地猜测训练集上目标的中间值是合理的。 这些套件为任何型号设置的障碍都相对较低。

作为指标,我们将预测中的平均绝对误差(mae)作为标准。 还有许多其他回归指标,但是我喜欢选择一个指标并使用它评估模型的建议。 而且平均绝对误差易于计算和解释。

在计算基础水平之前,您需要将数据分为训练和测试集:

  1. 我们在训练期间提供模型的属性以及答案。 模型必须学会匹配目标的特征。
  2. 测试功能集用于评估训练后的模型。 当她处理测试套件时,她看不到正确答案,只能根据可用功能进行预测。 我们知道测试数据的答案,可以将预测结果与它们进行比较。

对于培训,我们使用70%的数据,而对于测试-30%:

 # Split into 70% training and 30% testing set X, X_test, y, y_test = train_test_split(features, targets, test_size = 0.3, random_state = 42) 

现在我们计算初始基础水平的指标:

 # Function to calculate mean absolute error def mae(y_true, y_pred): return np.mean(abs(y_true - y_pred)) baseline_guess = np.median(y) print('The baseline guess is a score of %0.2f' % baseline_guess) print("Baseline Performance on the test set: MAE = %0.4f" % mae(y_test, baseline_guess)) 

基线猜测为66.00
测试集的基准性能:MAE = 24.5164

测试仪上的平均绝对误差约为25分。 由于我们的评估范围是1到100,因此误差为25%-该模型的障碍很小!

结论


您在本文中,我们经历了使用机器学习解决问题的前三个阶段。 设置任务后,我们:

  1. 清除并格式化原始数据。
  2. 进行探索性分析以研究可用数据。
  3. 我们开发了将用于模型的一组功能。

, , .

Scikit-Learn , .

Source: https://habr.com/ru/post/zh-CN425253/


All Articles