可解释性机器学习--2. Permutation Importance

排列重要性

以一个实例,说明排列重要性。
问题:预测一个人20岁时的身高,使用的是10岁时的数据。数据包括有用的特征(10岁时的身高),几乎没有预测能力的特征(拥有袜子)。

排列重要性是在模型拟合后计算的。所以我们不会改变模型,也不会改变我们对给定的身高、袜子数量等的预测。

相反,我们将问以下问题:如果我随机打乱验证数据的一列,而保留目标和所有其他列,这将如何影响现在打乱的数据中预测的准确性?

随机地重新排序单个列会导致预测不那么准确,因为结果数据不再符合在现实世界中观察到的任何情况。如果我们打乱模型在预测时严重依赖的列,模型的准确性尤其会受到影响。在这种情况下,10岁时改变身高会导致可怕的预测。如果我们反过来洗牌拥有的袜子,由此产生的预测就不会受到如此大的影响。

因此:

  1. Get a trained model.
  2. Shuffle the values in a single column, make predictions using the resulting dataset. Use these predictions and the true target values to calculate how much the loss function suffered from shuffling. That performance deterioration measures the importance of the variable you just shuffled.
  3. Return the data to the original order (undoing the shuffle from step 2). Now repeat step 2 with the next column in the dataset, until you have calculated the importance of each column.

代码实例

问题:使用一个模型,该模型根据球队的统计数据预测足球/足球队是否会有“最佳球员”获胜者。“比赛最佳选手”奖颁给比赛中表现最好的选手。

加载数据,训练模型

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier

data = pd.read_csv('../input/fifa-2018-match-statistics/FIFA 2018 Statistics.csv')
y = (data['Man of the Match'] == "Yes")  # Convert from string "Yes"/"No" to binary
feature_names = [i for i in data.columns if data[i].dtype in [np.int64]]
X = data[feature_names]
train_X, val_X, train_y, val_y = train_test_split(X, y, random_state=1)
my_model = RandomForestClassifier(n_estimators=100,
                                  random_state=0).fit(train_X, train_y)

使用eli5库计算和显示重要性

eli5:可视化工具包,在模型机器学习模型调试和解释其产出的预测结果方面非常有用。
其余可视化工具包还有:yellowbrick, LIME, MLxtend

import eli5
from eli5.sklearn import PermutationImportance

perm = PermutationImportance(my_model, random_state=1).fit(val_X, val_y)
eli5.show_weights(perm, feature_names = val_X.columns.tolist())

关于排列重要性的解释:
顶部的值是最重要的特征,而底部的值则无关紧要。
每行中的第一个数字显示了模型性能随随机洗牌而下降的程度(在本例中,使用“精度”作为性能指标)。

对列进行洗牌对准确性能的影响具有一定的随机性。我们通过多次洗牌重复这个过程来测量排列重要性计算中的随机性。±后的数字衡量了从一次洗牌到下一次洗牌的表现变化。

您偶尔会看到排列重要性为负值。在这些情况下,对洗牌(或嘈杂)数据的预测碰巧比真实数据更准确。这种情况发生在功能并不重要(重要性应该接近于0),但随机的机会导致对洗牌数据的预测更加准确的情况下。这在小型数据集中更为常见,例如本例中的数据集,因为它有更多的运气/机会。

最重要的功能是进球得分。这似乎是合理的。球迷们可能对其他变量的顺序是否令人惊讶有一些直觉。

练习

引言

您将使用出租车票价预测竞赛的数据样本来考虑和计算排列的重要性。

  • 加载数据
  • 划分数据集
  • 构建预测模型
  • 显示部分预测结果
# Loading data, dividing, modeling and EDA below
import pandas as pd
from sklearn.ensemble import RandomForestRegressor
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split

data = pd.read_csv('../input/new-york-city-taxi-fare-prediction/train.csv', nrows=50000)

# Remove data with extreme outlier coordinates or negative fares
data = data.query('pickup_latitude > 40.7 and pickup_latitude < 40.8 and ' +
                  'dropoff_latitude > 40.7 and dropoff_latitude < 40.8 and ' +
                  'pickup_longitude > -74 and pickup_longitude < -73.9 and ' +
                  'dropoff_longitude > -74 and dropoff_longitude < -73.9 and ' +
                  'fare_amount > 0'
                  )

y = data.fare_amount

base_features = ['pickup_longitude',
                 'pickup_latitude',
                 'dropoff_longitude',
                 'dropoff_latitude',
                 'passenger_count']

X = data[base_features]


train_X, val_X, train_y, val_y = train_test_split(X, y, random_state=1)
first_model = RandomForestRegressor(n_estimators=50, random_state=1).fit(train_X, train_y)

# Environment Set-Up for feedback system.
from learntools.core import binder
binder.bind(globals())
from learntools.ml_explainability.ex2 import *
print("Setup Complete")

# show data
print("Data sample:")
data.head()

接下来,理解训练数据中的值

train_X.describe()
train_y.describe()

显示计数、均数、四分位间距、标准差、最小/大值

问题一:第一个模型使用以下特性:

  • pickup_longitude
  • pickup_latitude
  • dropoff_longitude
  • dropoff_latitude
  • passenger_count

在运行任何代码之前,哪些变量似乎对预测出租车票价有潜在的帮助?你认为排列的重要性一定会确定这些特征的重要性吗?

答:了解纽约市出租车是否会根据乘客数量改变价格将会很有帮助。大多数地方不会根据乘客数量来调整票价。如果你认为纽约也是一样,那么只有列出的前4个特征才是重要的。乍一看,所有这些似乎都同等重要。

问题二:创建一个名为perm的PermutationImportance对象来显示first_model的重要性。将其与适当的数据匹配并显示权重。

答:

import eli5
from eli5.sklearn import PermutationImportance

perm = PermutationImportance(first_model, random_state=1).fit(val_X, val_y)
eli5.show_weights(perm, feature_names = base_features)

问题三:在看到这些结果之前,我们可能期望这四个方向特征中的每一个都是同等重要的。但是,纬度特征比经度特征更重要。你能对此提出任何假设吗?

答:

  1. 旅行可能倾向于有更大的纬度距离比经度距离。如果经度值通常更接近,那么对它们进行洗牌就不那么重要了。
  2. 城市的不同部分可能有不同的定价规则(例如,每英里价格),而定价规则可能因纬度而异,而不是经度。
  3. 向北<->向南(变化的纬度)的通行费可能比向东<->向西(变化的经度)的通行费高。因此,纬度会对预测产生更大的影响,因为它会记录通行费的数量。

问题四:没有对纽约市的详细了解,很难排除大多数关于为什么纬度特征比经度更重要的假设。

下一步很好的做法是,将居住在城市某些地区的影响与总旅行距离的影响分开。

下面的代码创建了纵向和纬度距离的新特征。然后,它构建一个模型,将这些新功能添加到您已经拥有的功能中。

填写两行代码来计算并显示这组新特征的重要性权重。

# create new features
data['abs_lon_change'] = abs(data.dropoff_longitude - data.pickup_longitude)
data['abs_lat_change'] = abs(data.dropoff_latitude - data.pickup_latitude)

features_2  = ['pickup_longitude',
               'pickup_latitude',
               'dropoff_longitude',
               'dropoff_latitude',
               'abs_lat_change',
               'abs_lon_change']

X = data[features_2]
new_train_X, new_val_X, new_train_y, new_val_y = train_test_split(X, y, random_state=1)
second_model = RandomForestRegressor(n_estimators=30, random_state=1).fit(new_train_X, new_train_y)

# Create a PermutationImportance object on second_model and fit it to new_val_X and new_val_y
# Use a random_state of 1 for reproducible results that match the expected solution.
perm2 = PermutationImportance(second_model, random_state=1).fit(new_val_X, new_val_y)

# show the weights for the permutation importance you just calculated
eli5.show_weights(perm2, feature_names = features_2)

Kaggle系列课程提供文字描述、实例训练以及可编译的运行环境,非常适合初学者,上面还有很多公开数据集和竞赛开源代码,干货满满!

自从发现这个宝库之后,最近都在学习上面的课程,有可解释机器学习、特征工程等,希望一边学习一边整理相关资料,并在自己的博客中同步上传学习记录!

另外,附上kaggle官网,有兴趣的小伙伴可以浏览学习,有问题一起交流呀!

猜你喜欢

转载自blog.csdn.net/weixin_41698730/article/details/113876179
今日推荐