机器学习全生命周期,一步一步,中长篇(一)总共三篇

本文是英文原著翻译,并结合了其他文献的一个有益集成。中文在英文简述的后面。

We’ll follow the general machine learning workflow step-by-step:

  1. Data cleaning and formatting 数据清洗和格式化
  2. Exploratory data analysis 探索性的数据分析
  3. Feature engineering and selection 字段的加工和选择
  4. Hide and filter Sensitive Feature 数据脱敏
  5. Compare several machine learning models on a performance metric 模型的评估和选择
  6. Perform hyperparameter tuning on the best model 用于模型优化的超参数调整
  7. Evaluate the best model on the testing set 评估测试集
  8. Interpret the model results 模型解释
  9. Draw conclusions and document work 记录工作和报告结果

Extrac from

结合人工智能系列文章与深度学习的课程,写一篇总结,将知识要点讲解清楚,并指明文献出处。本篇总结的编程语音采用python.

1. 数据清洗和格式化 (Data cleaning and formatting)

  • Not Available,或者空白处,都转换为 python.nan
data = data.replace({'Not Available': np.nan})
  • 如果要进行数字计算,将 String 类转换为 float 类。
data[col] = data[col].astype(float) 

2. 字段的整理和不合理的数据清除

  • 除去有50%的数据缺省字段, 怎样计算字段的缺省百分比,50%是人为订下来的值,到底这个阀值是多少百分比,是基于业务场景的。这个链接有讨论

  • 也要除去不合理的数据(remove outliers)。在某些业务场景,我们会去除不合理的数据依据这个链接的公式

    • Below the first quartile − 3 ∗ interquartile range
    • Above the third quartile + 3 ∗ interquartile range

3. 探索性的数据分析(Exploratory Data Analysis)

(EDA 的详细概念描述可以从Analytics vidhya: A Comprehensive Guide to Data Exploration获得,博客中有udacity的描述统计学的课程Intro to Descriptive Statistics)

Exploratory Data Analysis (EDA) 探索性的数据分享是没有尽头的过程,在这个步骤中,我们要计算数字,画图看趋势,看不合常理的数据,也看数据的规则和数据之间的联系。

Single Variable Plots (单个变量的绘图)

比较常用的图形之一是 Histogram,横向轴是变量,竖向轴是出现的次数,频率,或百分比。通过图形,可以看数据在该业务场景下的合理性,比如该数据是不是官方数据,还是用户自由填写没有验证的数据。根据数据的可靠性和客观性,我们可以做判断是否要把该数据放入数据模型中,用来对结果做预测。一个histgram范例图是如下显示:

从histgram的变量分布图,我们可以看出这个变量采集的数据是否合理。

  • 数据间的关系 EDA 是用来发现变量(Feature)之间对于目标变量的的耦合性,是非常有利于建模的。密度图(density plot)是用来发现不同变量相对于结果的耦合度的一个方法。一个工具是seaborn库。密度图可以用来对一个变量的不同类别的分布图进行视觉描绘。比如,建筑物有多家庭居民楼,办公楼,酒店,没有冷藏的仓库。一个范例如下图显示:

建筑物也可以按地区分,比如上海有松江区,闵行区。。。

 这两个图可以看出,变量如果按地区分对输出结果或目标值没有关系。

下面的代码是用来绘制建筑物按照类型区分的密度图,密度图假设我们有足够多的数据/点。

  ===============================================
  # 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交互系数Pearson Correlation Coefficient.

这个参数是用来度量两个变量之间的关系:强度和方向的夹角。如果Pearson交互系数是+1,那么两个变量是正向,线性的关系。如果Pearson交互系数是-1, 那么两个变量是负向,线性的关系。

详细可以阅读此wiki链接, 虽然Pearson关系系数不能用来捕捉非线性关系,但仍然是观测连个变量之间关系的好方法。使用Pandas库的dataFrame类里,我们可以非常容易的看两个变量之间的关系。

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

在业务场景中,我们运用Pearson交互系数,可以得到相对于目标值最正向的和最负向的变量。

在本业务场景中,我们可以获得关于结果Score的各变量的关系值。如下图所示,业务场景可以参考本文的出处.

 

本处的翻译略,需理解原文的业务场景。

两个变量的绘图 (two Variables plots)

散点图(scatterplots)可以用来对两个连续变量的关系进行可视化。

散点图也可以将一个变量分类,然后不同类用不同的颜色绘制出来。下面的图片是散点图的一个例子: 

 这个示例图显示的是两个变量之间的相关系数是-0.7时候的样子。这个图显示当 Site EUI变小的时候,变量Energy Star Score值变大,而且不管建筑物是什么类型。

还有一个要介绍的是pairs plot。这让我们看到relationships between multiple pairs of variables 以及单变量的分布图。现在我们用Seaborn可视化库和PairGrid函数来绘制Pairs Plot with scatterplots on the upper triangle, histograms on the diagonal, and 2D kernel density plots and correlation coefficients on the lower triangle.

# 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);

示例图如下所示:

4.数据脱敏

待继续研究。。。

5. 字段的加工和选择 (Feature Engineering and Selection)

字段加工和选择往往带来意想不到的收获。

  • 字段加工 字段加工是指从原始数据抽取一些字段进行转换成为新的字段。

  • 字段选择 字段选择就是从字段中,选择最重要的字段,或最可能影响结果的字段。

只要我们提供数据,机器学习的模型就不断会学习,所以要确保我们的数据要包含必要的相关信息。我们要确保训练模型的数据要正确。

字段加工

对于这个项目,我们在字段加工中,会采取以下步骤:

  • 对类型变量的单热敏编码(One-hot encode categorical variables (borough and property use type))
  • 添加数值变量的自然对数变换(Add in the natural log transformation of the numerical variables)

单热敏编码 是必须的,如果我们想在模型中表达分类变量。比如模型不懂建筑物的一种是办公室,但我们可以将一位数字表达为1,其余类型的为零。

字段的转型可以帮助模型学习非线性的关系。转换/编码的方法有 开平方根,自然对数,对字段开方 ,那种方式根据业务场景和最好的实践方法。

下面的代码选择数值字段,用对数对字段进行转换。选择两个分类的字段,用单热敏编码方法转换字段,然后聚合这两集合。这听起来有大量的工作,但如果用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)

字段加工后,我们有11000个建筑物,并有110个字段。其实不是所有字段是必要的,所以我们将用字段选择来删除一些字段。

字段选择

110 个字段中,很多变量之间的相关系数接近1,也就是近乎线性的关系。那么如果是这样,一个变量就重复了或多余的了。比如下面的两个变量。 Site EUI vs Weather Normalized Site EUI 这两个变量的Pearson 相关系数是0.997,接近1.

彼此强相关的特征被称为共线,并且移除这些特征对中的一个变量通常可以帮助机器学习模型概括并且更易于解释。 (我应该指出,我们正在讨论字段与其他字段的相关性,而不是与目标或输出的相关性,这有助于我们的模型!)

有许多方法可以计算字段之间的共线性,其中最常见的是方差膨胀因子。 在这个项目中,我们将使用相关系数来识别和删除共线特征。 如果它们之间的相关系数大于0.6,我们将丢弃一对字段中的一个。 对于实现,请看一下(以及此Stack Overflow答案)

虽然这个值看似随意,但我尝试了几个不同的阈值,这个选择产生了最好的模型。 机器学习是一个经验领域,通常是试验和发现最好的东西! 选择特征后,我们剩下64个总功能和1个目标。

有许多方法可以计算字段之间的共线性,其中最常见的是方差膨胀因子。 在这个项目中,我们将使用相关系数来识别和删除共线特征。 如果它们之间的相关系数大于0.6,我们将丢弃一对字段中的一个。 对于实现,请看一下 notebook (和 这个 Stack Overflow 解答)

虽然这个值看似随意,但我尝试了几个不同的阈值,这个选择产生了最好的模型。 机器学习是一个经验领域,通常是试验和发现最好的东西! 选择字段后,我们剩下64个字段和1个目标。

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

建立基线 (Establishing a Baseline)

我们现在已经完成了数据清理,探索性数据分析和字段工程。 在开始建模之前采取的最后一步是建立一个较低的基线。 这基本上是我们可以比较我们的结果的猜测。 如果机器学习模型没有超过这个猜测,那么我们可能必须得出结论,机器学习的这个模型对于这个任务是不可接受的,或者我们可能需要尝试不同的方法。

对于回归问题,合理的较低基线是猜测测试集中所有示例的训练集上目标的中值。 这为任何模型设定了相对较低的标准。

我们将使用的基线是平均绝对误差(mae),它测量预测的平均绝对误差。 回归有很多指标,但我喜欢Andrew Ng建议选择一个指标,然后在评估模型时坚持使用它。 平均绝对误差易于计算并且可以解释。

在计算基线之前,我们需要将数据分成训练和测试集:

训练集的字段是我们在训练期间为我们的模型提供的答案。 目标是让模型学习字段和目标之间的关系。

测试字段集用于评估训练的模型。 该模型不允许查看测试集的答案,必须仅使用这些字段值进行预测。 我们知道测试集的答案,因此我们可以将测试预测与答案进行比较。 我们将使用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))

猜测的Score基线值是 66.00 测试集的基线值是: MAE = 24.5164

较低的基线值的估计在测试集上减少了约25个点。 得分范围从1-100,所以这代表25%的错误,超过相当低的标准!

结论 在本文中,我们介绍了机器学习问题的前三个步骤。 定义问题后,我们:

  • 清理并格式化原始数据
  • 执行探索性数据分析以了解数据集
  • 脱敏敏感性数据 (还没有方案)
  • 选择了一组我们将用于模型的字段
  • 最后,我们还完成了建立基线的关键步骤,我们可以据此判断机器学习算法。

第二篇文章(此处提供)将展示如何使用Scikit-Learn评估机器学习模型,选择最佳模型,以及执行超参数调整以优化模型(select the best model, and perform hyperparameter tuning to optimize the model)。 处理模型解释和报告结果的第三篇文章就在这里

一如既往,我欢迎反馈和建设性的批评,可以通过我的Twitter账号联系我@koehrsen_will

参考文献

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值