回归模型中的特征选择技术
特征选择是一种减少特征数量的方法,从而降低模型的计算复杂度。很多时候,特征选择对于克服过度拟合问题变得非常有用。它帮助我们确定高精度预测响应变量所需的最小特征集。如果我们问模型,添加新特性是否一定会显著提高模型性能?如果不是,那么为什么要添加那些只会增加模型复杂性的新特性。
现在,让我们了解如何从给定数据集中的所有可用特征中选择重要的特征集。
用例子来理解总是比较好的。因此,让我们看看下面 R 中的“mtcars”数据集:
我们将删除 x 列,因为它只包含汽车型号,不会给预测增加太多价值。
在上述数据中,有 12 个特征(x、mpg、cyl、disp、hp、drat、wt、qsec、vs、am、gear、carb ),我们希望预测 mpg(英里/加仑),因此它成为我们的目标/响应变量。
让我们随机选择任何预测变量,并尝试拟合预测 mpg 的模型。让我们从“wt”开始:
三颗星(或星号)代表高度显著的 p 值。因此,截距和斜率的小 p 值表明我们可以拒绝零假设,这使得我们可以得出 mpg 和体重之间有很大关系的结论。通常,p 值为 5% (.05)或更低是一个很好的分界点。在我们的模型示例中,p 值非常接近于零。此外,R 平方值 0.74 告诉我们,模型可以解释目标变量中约 74%的方差,因此模型也很重要。
现在,让我们用两个变量 wt 和 hp(马力)来拟合模型,如下所示:(注意,我们可以使用任意两个随机选取的预测值,因为我们只是试图了解如果使用试凑法会发生什么)
现在,R 平方值从 0.74 增加到 0.81。这意味着这个模型变得更加重要。此外,查看 wt 和 hp 的星级数,我们可以说两者都与目标变量密切相关,因此两者都很重要。
可能会有这样的情况,通过添加新变量,已经添加的变量的影响会降低,在这种情况下,如果任何旧变量的 p 值超过 0.05 的上限,则意味着该变量现在变得不重要,然后我们删除该变量。
现在再添加一个变量“qsec ”,并分析模型摘要,如下所示:
从逻辑上来说,通过添加一个新的变量,它不应该减少已经添加的变量的影响,但是在这种情况下,正如我们在上面的图像中看到的,变量 hp 和“qsec”都变得不重要(p 值> . 05 也没有星号)。
现在,让我们添加所有变量,看看会发生什么:
从上面的总结中,我们看到没有一个变量是重要的,因为所有的 p 值都大于阈值限制 0.05,而且总结也没有产生任何星号作为重要代码。这有点令人惊讶。如果没有显著的变量,那么如何拟合模型?
因此,如果我们对变量的所有组合使用试凑法,那么将会有总 2^k-1 线性模型,我们必须尝试并查看哪些是重要的特征。这不是很费时间的工作吗,当然可以。那么现在该怎么办呢?接下来是特征选择技术,它帮助我们找到产生显著模型拟合的最小特征集。因此,在回归中,非常常用的特征选择技术如下:
- 逐步回归
- 预选
- 反向消除
1.逐步回归
在逐步回归技术中,我们开始用每个单独的预测因子来拟合模型,并查看哪一个具有最低的 p 值。然后选择变量,然后使用两个变量拟合模型,一个是我们在上一步中已经选择的变量,另一个是所有剩余的变量。我们再次选择具有最低 p 值的一个。还要记住,通过添加新变量,上一步中已经选择的变量的影响应该仍然很大。我们保持这个迭代,直到我们得到一个 p 值小于阈值 0.05 的组合。
让我们用一个例子来理解整个过程:
第一步:
我们用一个预测器和目标来拟合模型。我们一个接一个地尝试了每一个预测值,每一行下面分别代表模型拟合的 t 值、p 值和 R 平方值。正如我们所见,mpg ~ wt fit 具有最低的 p 值(也应小于 0.05),因此将选择 wt 并转到步骤 2。
第二步:
现在,我们将使用两个预测值来拟合模型。我们已经在步骤 1 中选择了一个作为 wt,对于第二个预测值,我们将逐一尝试所有剩余的预测值。并且将再次选择具有最低 p 值的那些。在这个例子中,我们得到了 wt 和 cyl。
第三步:
现在,我们将尝试拟合 3 个预测值,其中两个已经在步骤 2 中选择,第三个将尝试剩余的预测值。但是在这里我们看到没有一个 p 值小于 0.05,因此都不显著。
由于所有 p 值都大于 0.05,因此三个组合特征都不显著。因此我们就此打住。
因此,使用逐步回归,我们得到了对最终模型拟合有重大影响的最小特征集{wt,cyl}。这并不意味着其他特征没有影响,但如果我们得到一个只有两个变量的重要模型,它们的影响可以忽略不计。
因此,在这里,我们已经观察到,与我们必须比较 2 个⁰-1 = 1023 个模型的试凑法相比,我们的搜索空间已经急剧减小。
2.预选
向前选择几乎类似于逐步回归,然而唯一的区别是在向前选择中,我们仅不断添加特征。我们不删除已经添加的特征。在每次迭代中,我们只添加那些增加整体模型拟合度的特性。
3.反向消除
在第一步的反向消除中,我们包括所有预测值,在随后的步骤中,继续移除具有最高 p 值(> 0.05 阈值极限)的预测值。经过几次迭代后,它将产生最终的特征集,这些特征集对于以期望的精度预测结果来说是足够重要的。
我们将以 mtcars 数据集为例,按如下步骤进行:
第一步:
在步骤 1 中,我们用数据集中可用的所有特征构建模型。然后观察一些事情:
第二步
第三步
第四步
第五步
第六步
第七步
第八步
第九步
最终,我们得到了{wt,qsec}作为最小的特征集。现在让我们来看看有趣的事情,这里是否反向消除产生了我们用逐步回归得到的相同的特征集。使用逐步回归,我们得到了{wt,cyl}作为最佳可能的最小特征集。
还有一点我们可以得出结论,那就是我们用所有的特征选择技术得到的特征集并不总是相同的。我们必须根据业务问题和我们的理解,明智地选择不同的技术。
以上就是这三种特征选择技术。还有其他同样重要的技巧需要理解,我将在接下来的文章中写下这些技巧。
本文首次出现在“科技隧道”博客上,网址为https://ashutoshtripathi . com/2019/06/07/feature-selection-techniques-in-regression-model/
感谢您的阅读。
非常欢迎你对这篇文章的想法。请在评论区分享。
相关文章:
R 中基于遗传算法的特征选择
这是一篇关于在 R 中使用遗传算法进行特征选择的文章,在这篇文章中,我们将快速回顾一下:
- 什么是遗传算法?
- ML 中的 GA?
- 解决方案是什么样的?
- 遗传过程及其算子
- 健身功能
- R 中的遗传算法!
- 你自己试试
- 相关概念
Animation source: “Flexible Muscle-Based Locomotion for Bipedal Creatures” — Thomas Geijtenbeek
背后的直觉
想象一个黑盒,它可以帮助我们在无限的可能性中做出决定,并有一个标准,这样我们就可以找到一个可接受的解决方案(在时间和质量上)来解决我们提出的问题。
什么是遗传算法?
遗传算法(GA)是一种数学模型,其灵感来自著名的查尔斯·达尔文的自然选择思想。
在不同的世代中,自然选择只保留最适合的个体。
想象一下 1900 年有 100 只兔子,如果我们看看今天的数量,我们会发现其他兔子比它们的祖先更快更熟练地找到食物。
ML 中的 GA
在机器学习中,遗传算法的用途之一是挑选正确数量的变量,以便创建预测模型。
选择正确的变量子集是一个组合优化问题。
这种技术相对于其他技术的优势在于,它允许从先前的最佳解决方案中产生最佳解决方案。随着时间的推移改进选择的进化算法。
遗传算法的思想是将一代又一代的不同解决方案组合起来,从每一个解决方案中提取出最好的基因。这样它创造了新的更适合的个体。
我们可以找到遗传算法的其他用途,如超调参数、寻找函数的最大值(或最小值)或搜索正确的神经网络结构(神经进化)等
特征选择中的遗传算法
GA 的每一个可能的解,都是被选择的变量(一个单个🐇),则被视为一个整体,它不会针对目标对变量进行单独排序。
这很重要,因为我们已经知道变量在组中起作用。
解决方案是什么样的?
简单地说,假设我们总共有 6 个变量,
一个解决方案可以是选取 3 个变量,比如:var2
、var4
和var5
。
另一种解决方法可以是:var1
和var5
。
这些解就是群体中所谓的个体或染色体。它们是我们问题的可能解决方案。
信用图像:Vijini mallawatarachchi
根据图像,解决方案 3 可以表示为一个热点向量:c(1,0,1,0,1,1)
。每个1
表示包含该变量的解决方案。这种情况:var1
、var3
、var5
、var6
。
而方案 4 则是:c(1,1,0,1,1,0)
。
载体中的每个位置都是一个基因。
遗传过程及其算子
GA 的基本思想是生成一些随机的可能的解决方案(称为population
),它们代表不同的变量,然后在迭代过程中组合最佳解决方案。
这种组合遵循基本的遗传算法操作,即:选择,变异和交叉。
- 选择:挑选一代中最适合的个体(即:提供最高 ROC 的解决方案)。
- 交叉:基于两种溶液的基因,创建两个新个体。这些孩子会出现在下一代面前。
- 突变:在个体中随机改变一个基因(即:翻转一个
0
到1
)
这个想法是每一代,我们会找到更好的个体,就像一只跑得快的兔子。
我推荐 Vijini mallawatarachchi 关于遗传算法如何工作的帖子。
这些基本操作允许算法通过以最大化目标的方式组合它们来改变可能的解决方案。
健身功能
例如,这个目标最大化是为了保持使 ROC 曲线下的面积最大化的解决方案。这在适应度函数中定义。
适应度函数采用一个可能的解决方案(或者染色体,如果你想听起来更复杂的话),并且以某种方式评估选择的有效性。
正常情况下,适应度函数采用独热向量c(1,1,0,0,0,0)
,创建例如带有var1
和var2
的随机森林模型,并返回适应度值(ROC)。
此代码中计算的适应度值为:ROC value / number of variables
。通过这样做,该算法对具有大量变量的解进行惩罚。类似于赤池信息准则的想法,或者说 AIC。
R 中的遗传算法!🐛
我的意图是为您提供一个清晰的代码,这样您就可以理解背后的内容,同时尝试新的方法,比如修改适应度函数。这是至关重要的一点。
要在您自己的数据集上使用,请确保data_x
(数据帧)和data_y
(因子)与custom_fitness
功能兼容。
主图书馆是由卢卡·斯库卡开发的GA
。此处见中的小插曲与例子。
📣重要:以下代码不完整。 克隆存储库 来运行这个例子。
# data_x: input data frame
# data_y: target variable (factor)# GA parameters
param_nBits=ncol(data_x)
col_names=colnames(data_x)# Executing the GA
ga_GA_1 = ga(fitness = function(vars) custom_fitness(vars = vars,
data_x = data_x,
data_y = data_y,
p_sampling = 0.7), # custom fitness function
type = "binary", # optimization data type
crossover=gabin_uCrossover, # cross-over method
elitism = 3, # best N indiv. to pass to next iteration
pmutation = 0.03, # mutation rate prob
popSize = 50, # the number of indivduals/solutions
nBits = param_nBits, # total number of variables
names=col_names, # variable name
run=5, # max iter without improvement (stopping criteria)
maxiter = 50, # total runs or generations
monitor=plot, # plot the result at each iteration
keepBest = TRUE, # keep the best solution at the end
parallel = T, # allow parallel procesing
seed=84211 # for reproducibility purposes
)# Checking the results
summary(ga_GA_1)── Genetic Algorithm ─────────────────── GA settings:
Type = binary
Population size = 50
Number of generations = 50
Elitism = 3
Crossover probability = 0.8
Mutation probability = 0.03 GA results:
Iterations = 17
Fitness function value = 0.2477393
Solution =
radius_mean texture_mean perimeter_mean area_mean smoothness_mean compactness_mean
[1,] 0 1 0 0 0 1
concavity_mean concave points_mean symmetry_mean fractal_dimension_mean ...
[1,] 0 0 0 0
symmetry_worst fractal_dimension_worst
[1,] 0 0# Following line will return the variable names of the final and best solution
best_vars_ga=col_names[ga_GA_1@solution[1,]==1]# Checking the variables of the best solution...
best_vars_ga[1] "texture_mean" "compactness_mean" "area_worst" "concavity_worst"
- 蓝点:人口健康平均值
- 绿点:最佳健身值
注意:不要期望结果那么快😅
现在我们根据最佳选择来计算精度!
get_accuracy_metric(data_tr_sample = data_x, target = data_y, best_vars_ga)[1] 0.9508279
准确率在 95,08%左右,而 ROC 值接近 0,95(ROC =适应值*变量个数,查适应函数)。
分析结果
不喜欢分析没有分界点(得分数据)的准确性,但是和这个 Kaggle 帖子的结果对比还是很有用的。
他基于 5 个变量使用递归特征消除或 RFE 得到了类似的精度结果,而我们的解决方案保持 4 个变量。
你自己试试
尝试一个新的适应度函数,有些解还是提供了大量的变量,你可以试试求变量个数的平方。
另一件要尝试的事情是获取 ROC 值的算法,或者甚至是更改指标的算法。
有些配置可以持续很长时间。建模前平衡等级,并使用p_sampling
参数进行游戏。采样技术会对模型产生很大的影响。查看样本大小和模型性能的等级平衡帖子了解更多信息。
改变变异率或者精英主义怎么样?或者尝试其他穿越方式?
增加popSize
以同时测试更多可能的解决方案(以时间为代价)。
请随时分享任何见解或想法,以改善选择。
克隆存储库 运行实例。
相关概念
遗传算法和深度学习之间存在并行性,随着时间的推移迭代和改进的概念是相似的。
我添加了p_sampling
参数来加快速度。而且通常都能达到目的。类似于深度学习中使用的批量概念。另一个相似之处是在神经网络训练中 GA 参数run
和提前停止标准之间。
但是最大的相似之处是这两种技术都来自于对自然的观察。在这两种情况下,人类观察了神经网络和遗传学如何工作,并创建了一个模拟其行为的简化数学模型。大自然有几百万年的进化,为什么不试着模仿一下呢?🌱
—
我尽量简短地介绍 GA,但是如果你对这个庞大的话题有任何具体的问题,请在评论中留下🙋 🙋♂
如果我没有激励你去学习遗传算法,看看这个基于神经进化的项目:
—
感谢阅读🚀
在 Twitter 和 Linkedin 上找到我。
更多博文。
想了解更多?📗数据科学活书
使用 Python 解决分类问题的特征选择
介绍
在模型中包含更多要素会使模型更加复杂,并且模型可能会过度拟合数据。一些特征可能是噪声,并可能损坏模型。通过移除那些不重要的特征,该模型可以更好地概括。
Sklearn 网站列出了不同的功能选择方法。这篇文章主要是基于那个网站的主题。然而,我收集了关于这些方法背后的理论的不同资源,并将它们添加到本文中。此外,我在同一个数据集上应用了不同的特征选择方法来比较它们的性能。
阅读完这篇文章和我在文章中提供的参考资料后,您应该能够理解特性选择背后的理论以及如何使用 python 来完成它。
获取数据
我们使用虹膜数据集。有关此数据的更多信息:
https://sci kit-learn . org/stable/auto _ examples/datasets/plot _ iris _ dataset . html
iris = load_iris()
X = iris.data
y = iris.target
print(X[: 5, :])
print(X.shape)**output:** [[5.1 3.5 1.4 0.2]
[4.9 3\. 1.4 0.2]
[4.7 3.2 1.3 0.2]
[4.6 3.1 1.5 0.2]
[5\. 3.6 1.4 0.2]](150, 4)
这些数据有四个特征。为了测试不同特征选择方法的有效性,我们向数据集添加了一些噪声特征。
np.random.seed(100)
E = np.random.uniform(0, 1, size=(len(X), 10))
X = np.hstack((X, E))
print(X.shape)**output:** (150, 14)
数据现在有 14 个特征。
在应用特征选择方法之前,我们需要首先分割数据。原因是我们只基于来自训练集的信息选择特征,而不是基于整个数据集。我们应该拿出整个数据集的一部分作为测试集来评估特征选择和模型的性能。因此,在我们进行特征选择和训练模型时,无法看到来自测试集的信息。
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=100, test_size=0.3)
print(X_train.shape)**output:** (105, 14)
我们将应用基于 X_train 和 y_train 的特征选择。
I .移除具有低方差的特征
变量阈值是一种简单的特征选择基线方法。它会移除方差未达到某个阈值的所有要素。默认情况下,它会移除所有零方差特征。
https://scikit-learn . org/stable/modules/generated/sk learn . feature _ selection。variance threshold . html # sk learn . feature _ selection。变量阈值
显然,我们的数据没有任何零方差特征。但是为了演示的目的,我仍然在这里应用这个方法。
sel_variance_threshold = VarianceThreshold()
X_train_remove_variance = sel_variance_threshold.fit_transform(X_train)
print(X_train_remove_variance.shape)**output:** (105, 14)
数据仍然有 14 个特征,没有一个特征被删除。
二。单变量特征选择
单变量特征选择通过基于单变量统计测试选择最佳特征来工作。我们将每个特征与目标变量进行比较,以查看它们之间是否有任何统计上的显著关系。它也被称为方差分析(ANOVA)。当我们分析一个特征和目标变量之间的关系时,我们忽略了其他特征。这就是它被称为“单变量”的原因。每个特性都有它的测试分数。
最后,比较所有的测试分数,将选择分数最高的特征。
(1)使用卡方检验。
有关卡方检验的更多信息,请阅读:
- 统计:http://vassarstats.net/textbook/,第八章
- sk learn:https://sci kit-learn . org/stable/modules/generated/sk learn . feature _ selection . chi 2 . html # sk learn . feature _ selection . chi 2
如果你想了解更多关于 Sklearn 如何应用卡方检验的信息,请阅读源代码:https://github . com/scikit-learn/scikit-learn/blob/1495 f 6924/sk learn/feature _ selection/univariate _ selection . py # L172
sel_chi2 = SelectKBest(chi2, k=4) # select 4 features
X_train_chi2 = sel_chi2.fit_transform(X_train, y_train)
print(sel_chi2.get_support())**output:**[ True True True True False False False False False False False False False False]
数组中的前四个元素为真,这意味着前四个特征是通过这种方法选择的。由于这些特征是数据中的原始特征,卡方检验表现良好。
(2)使用 f 检验
- 统计数字
单向方差分析:
http://vassarstats.net/textbook/,第十四章
回归方差分析:
http://fac web . cs . de Paul . edu/shost/CSC 423/documents/f-test-reg . htm
- Sklearn
分类测试:
回归检验:
sel_f = SelectKBest(f_classif, k=4)
X_train_f = sel_f.fit_transform(X_train, y_train)
print(sel_f.get_support())**output:** [ True True True True False False False False False False False False False False]
f 检验也能正确选择原始特征。
(3)使用 mutual_info_classif 测试
- 用于分类:https://sci kit-learn . org/stable/modules/generated/sk learn . feature _ selection . mutual _ info _ class if . html # sk learn . feature _ selection . mutual _ info _ class if
- 对于回归:https://sci kit-learn . org/stable/modules/generated/sk learn . feature _ selection . mutual _ info _ regression . html # sk learn . feature _ selection . mutual _ info _ regression
sel_mutual = SelectKBest(mutual_info_classif, k=4)
X_train_mutual = sel_mutual.fit_transform(X_train, y_train)
print(sel_mutual.get_support())**output:** [ True True True True False False False False False False False False False False]
总之,三种单变量特征选择方法产生相同的结果。
我们使用虹膜数据作为分类问题。对于回归问题,同样,我们可以使用 f_regression,mutual_info_regression 来进行特征选择。
三。递归特征消除
给定将权重分配给特征(例如,线性模型的系数)的外部估计器,递归特征消除(RFE)是通过递归地考虑越来越小的特征集来选择特征。首先,在初始特征集上训练估计器,并且通过 coef_ 属性或通过 feature_importances_ 属性获得每个特征的重要性。然后,从当前特征集中删除最不重要的特征。该过程在删减集上递归重复,直到最终达到要选择的特征的期望数量。
关于 Sklearn 中的 RFE:https://sci kit-learn . org/stable/modules/generated/sk learn . feature _ selection。rfe . html # sk learn . feature _ selection。RFE
(1)使用逻辑回归作为模型
model_logistic = LogisticRegression(solver='lbfgs', multi_class='multinomial', max_iter=1000)
sel_rfe_logistic = RFE(estimator=model_logistic, n_features_to_select=4, step=1)
X_train_rfe_logistic = sel_rfe_logistic.fit_transform(X_train, y_train)print(sel_rfe_logistic.get_support())**output:** [False True True True False False False False False False False False False True]print(sel_rfe_logistic.ranking_)**output:** array([ 3, 1, 1, 1, 9, 8, 7, 6, 5, 4, 2, 11, 10, 1])
所选择的特征是等级 1。结果表明,递归特征消除仅选择了部分原始特征和一个噪声特征。这不是我们想要的理想结果。让我们试试另一个模型:
(2)使用随机森林作为模型
model_tree = RandomForestClassifier(random_state=100, n_estimators=50)
sel_rfe_tree = RFE(estimator=model_tree, n_features_to_select=4, step=1)
X_train_rfe_tree = sel_rfe_tree.fit_transform(X_train, y_train)
print(sel_rfe_tree.get_support())**output:** [ True True True True False False False False False False False False False False]
在递归特征选择中使用随机森林作为模型可以在这种情况下选择正确的特征。
四。使用 SelectFromModel 进行特征选择
SelectFromModel 是一个元转换器,可以与拟合后具有 coef_ 或 feature_importances_ 属性的任何估计器一起使用。如果相应的 coef_ 或 feature_importances_ 值低于提供的阈值参数,则这些特征被视为不重要并被移除。
与单变量特征选择相比,基于模型的特征选择一次考虑所有特征,因此可以捕捉交互。用于特征选择的模型不需要与稍后用于训练的模型相同。
(1)基于 L1 的特征选择
具有 L1 惩罚的线性模型可以消除一些特征,因此可以在使用另一个模型来拟合数据之前充当特征选择方法。
model_logistic = LogisticRegression(solver='saga', multi_class='multinomial', max_iter=10000, penalty='l1')
sel_model_logistic = SelectFromModel(estimator=model_logistic)
X_train_sfm_l1 = sel_model_logistic.fit_transform(X_train, y_train)
print(sel_model_logistic.get_support())**output:** [ True False True True False False False False False True False False False False]
它选择了错误的功能!选择噪声中的一个要素时,原始数据集中的第二个要素被忽略。
(2)基于树的特征选择
model_tree = RandomForestClassifier(random_state=100, n_estimators=50)
model_tree.fit(X_train, y_train)
print(model_tree.feature_importances_)sel_model_tree = SelectFromModel(estimator=model_tree, prefit=True, threshold='mean')
# since we already fit the data, we specify prefit option here
# Features whose importance is greater or equal to the threshold are kept while the others are discarded.X_train_sfm_tree = sel_model_tree.transform(X_train)
print(sel_model_tree.get_support())**output:**[0.11844633 0.09434048 0.21340848 0.33708242 0.02019553 0.03081254
0.02317242 0.01962394 0.02407251 0.02193159 0.03289007 0.01836624
0.01811144 0.027546 ][ True True True True False False False False False False False False False False]
它选择正确的原始特征。
**综上所述的所有特征选择方法:**对于这种特定的数据集,使用 logistic 模型作为递归特征剔除或模型选择会错误地选择特征。另一方面,所有其他特征选择方法都正确地选择了前四个特征。
让我们比较特性选择前后的性能
(1)特征选择前
model_logistic = LogisticRegression(solver='saga', multi_class='multinomial', max_iter=10000)
model_logistic.fit(X_train, y_train)
predict = model_logistic.predict(X_test)
print(confusion_matrix(y_test, predict))
print(classification_report(y_test, predict))**output:** [[16 0 0]
[ 0 11 0]
[ 0 2 16]]
precision recall f1-score support 0 1.00 1.00 1.00 16
1 0.85 1.00 0.92 11
2 1.00 0.89 0.94 18 accuracy 0.96 45
macro avg 0.95 0.96 0.95 45
weighted avg 0.96 0.96 0.96 45
(2)特征选择后
我们使用基于卡方检验的特征选择的结果。
X_train_chi2 是特征选择后馈入模型的数据。
model_logistic = LogisticRegression(solver=’saga’, multi_class=’multinomial’, max_iter=10000)
model_logistic.fit(X_train_chi2, y_train)
我们还需要转换测试数据,因为特性的数量发生了变化。
X_test_chi2 = sel_chi2.transform(X_test)
print(X_test.shape)
print(X_test_chi2.shape)**output:** (45, 14)
(45, 4)
仅使用测试集中与训练集中的剩余特征相对应的特征。这种情况下有四个特征。
predict = model_logistic.predict(X_test_chi2)
print(confusion_matrix(y_test, predict))
print(classification_report(y_test, predict))**output:** [[16 0 0]
[ 0 11 0]
[ 0 1 17]]
precision recall f1-score support 0 1.00 1.00 1.00 16
1 0.92 1.00 0.96 11
2 1.00 0.94 0.97 18 accuracy 0.98 45
macro avg 0.97 0.98 0.98 45
weighted avg 0.98 0.98 0.98 45
**总之,**特征选择去除了噪声,更好地泛化了模型,从而提高了模型性能。
关于噪音
我们可以尝试添加不同的噪声。例如:
E = np.random.uniform(0, 10, size=(len(X), 20))
如果噪声特征的数量增加到 20,并且噪声的幅度更大,则特征选择可能会选择错误的特征。不过性能还是提升了!
**Before feature selection**[[16 0 0]
[ 0 10 1]
[ 0 4 14]]
precision recall f1-score support0 1.00 1.00 1.00 16
1 0.71 0.91 0.80 11
2 0.93 0.78 0.85 18accuracy 0.89 45
macro avg 0.88 0.90 0.88 45
weighted avg 0.90 0.89 0.89 45**After feature selection:**[[16 0 0]
[ 0 10 1]
[ 0 1 17]]
precision recall f1-score support0 1.00 1.00 1.00 16
1 0.91 0.91 0.91 11
2 0.94 0.94 0.94 18accuracy 0.96 45
macro avg 0.95 0.95 0.95 45
weighted avg 0.96 0.96 0.96 45
摘要
在本文中,我对相同的数据使用了不同的特征选择方法。然后我评价他们的表现。我首先向虹膜数据集添加噪声以形成新的数据集。然后,不同的特征选择方法被应用于这个新的数据集。如果噪声与原始数据相比较小,并且噪声特征的数量相对较少,那么大多数方法可以正确地发现原始特征。
比较使用所有特征(原始特征+噪声特征)来训练模型,如果我们仅使用特征选择之后剩余的特征,则模型表现更好。
**注:**完整的木星笔记本可以在这里下载:
参考:
[## [1] 1.13.功能选择-sci kit-了解 0.21.3 文档
sklearn.feature_selection 模块中的类可用于…上的特征选择/维度缩减
scikit-learn.org](https://scikit-learn.org/stable/modules/feature_selection.html)
[2]安德烈亚斯·c·米勒,萨拉·圭多(2016)。Python 机器学习导论:数据科学家指南。奥赖利
使用正则化的特征选择
拉索来救援了
Photo by Markus Spiske on Unsplash
介绍
正则化包括向机器学习模型的不同参数添加惩罚,以减少模型的自由度,换句话说,避免过度拟合。在线性模型正则化中,惩罚应用于乘以每个预测值的系数。从不同类型的正则化,套索或 L1 的属性,能够缩小一些系数为零。因此,可以从模型中删除该特征。
在本帖中,我将演示如何使用套索正则化分类问题来选择要素。对于分类,我将使用来自 Kaggle 的 Paribas 索赔数据集。
- 导入重要库
import pandas as pd
import numpy as npimport matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inlinefrom sklearn.model_selection import train_test_splitfrom sklearn.linear_model import Lasso, LogisticRegression
from sklearn.feature_selection import SelectFromModel
from sklearn.preprocessing import StandardScaler
22。加载数据集
data = pd.read_csv(‘paribas.csv’, nrows=50000)
data.shape
data.head()
3。选择数值列和
在实践中,特征选择应该在数据预处理之后进行,所以理想情况下,所有分类变量都被编码成数字,然后我们可以评估它们对目标的确定性,这里为了简单起见,我将只使用数字变量来选择数字列:
numerics = ['int16','int32','int64','float16','float32','float64']
numerical_vars = list(data.select_dtypes(include=numerics).columns)
data = data[numerical_vars]
data.shape
4。将数据分成训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
data.drop(labels=['target', 'ID'], axis=1),
data['target'],
test_size=0.3,
random_state=0)X_train.shape, X_test.shape
5 。 缩放数据,因为线性模型受益于特征缩放
scaler = StandardScaler()
scaler.fit(X_train.fillna(0))
6。使用 ***SelectFromModel***
使用套索正则化选择特征
在这里,我将在一行代码中完成模型拟合和特征选择。首先,我指定了逻辑回归模型,并确保选择了套索(L1)惩罚。然后我使用来自sklearn
的selectFromModel
对象,它将在理论上选择系数非零的特征。
sel_ = SelectFromModel(LogisticRegression(C=1, penalty='l1'))
sel_.fit(scaler.transform(X_train.fillna(0)), y_train)
7。可视化套索正则化保留的特征
sel_.get_support()
在上面的输出中,输出标签是索引方式的。因此True
是针对 lasso 认为重要的特征(非零特征),而False
是针对权重收缩为零且 Lasso 认为不重要的特征。
8。列出具有所选功能的。
selected_feat = X_train.columns[(sel_.get_support())]print('total features: {}'.format((X_train.shape[1])))
print('selected features: {}'.format(len(selected_feat)))
print('features with coefficients shrank to zero: {}'.format(
np.sum(sel_.estimator_.coef_ == 0)))
系数收缩为零的特征数:
np.sum(sel_.estimator_.coef_ == 0)
9。识别被移除的特征*和*
removed_feats = X_train.columns[(sel_.estimator_.coef_ == 0).ravel().tolist()]removed_feats
10。从训练测试集中移除特征
X_train_selected = sel_.transform(X_train.fillna(0))
X_test_selected = sel_.transform(X_test.fillna(0))X_train_selected.shape, X_test_selected.shape
注意:
L2 正则化不会将系数缩小到零
# Separating the data into train and test set
X_train, X_test, y_train, y_test = train_test_split(
data.drop(labels=['target', 'ID'], axis=1),
data['target'],
test_size=0.3,
random_state=0)X_train.shape, X_test.shape
为了比较,我将使用岭正则化拟合逻辑回归,并评估系数:
l1_logit = LogisticRegression(C=1, penalty='l2')
l1_logit.fit(scaler.transform(X_train.fillna(0)), y_train)
现在,让我们计算零值系数的数量:
np.sum(l1_logit.coef_ == 0)
所以,现在零值系数的数量是零。因此,现在很清楚,脊正则化(L2 正则化)不会将系数缩小到零。
结论:
正如我们所见,我们用于套索正则化的逻辑回归从数据集中移除了不重要的要素。请记住,增加惩罚c
会增加移除的特征数量。因此,我们需要保持警惕,不要将惩罚设置得太高,以至于删除甚至重要的功能,或者设置得太低,以至于不删除不重要的功能。
对于使用随机森林的特征选择:
随机森林是最流行的机器学习算法之一。他们如此成功是因为他们提供了…
towardsdatascience.com](/feature-selection-using-random-forest-26d7b747597f)
Python 中使用包装器方法的要素选择
亲爱的读者:
同一篇文章已被转移到下面的链接。
[## 使用 Python 中的包装器方法选择要素的综合指南
这篇文章作为数据科学博客的一部分发表。简介在当今的大数据和物联网时代,我们…
www.analyticsvidhya.com](https://www.analyticsvidhya.com/blog/2020/10/a-comprehensive-guide-to-feature-selection-using-wrapper-methods-in-python/)
请你点击上面的链接。对造成的不便表示歉意。
快乐阅读!
特征选择为什么和如何解释
了解特征冗余和检测措施的影响
机器学习不仅仅是花哨的模型和复杂的优化算法。如果获胜者采用了更先进的模型或设计了一些出色的功能,包括我在内的许多 Kagglers 都乐于承认失败,但只有少数人在这种情况下忍心接受失败——被一个训练有更少功能的简单模型击败。是的,并不是所有的从业者都认可极简主义在模特训练中的作用。在这第一篇文章中,我将解释冗余特征如何损害模型和一些直观的检测方法。
越多越好,真的吗?
我理解在你的模型中尽可能多的打包功能是多么棒的感觉。我记得我多么喜欢看着我的训练 CSV 文件的大小,想象这个模型会有多好。然而,情况并非总是如此。原因如下:
1.多余的功能减缓了训练过程
这是显而易见的,特征的数量与训练时间正相关。功能越多,计算速度越慢。然而,还有一个隐藏的因素会显著降低训练速度。
在训练集中具有相关的特征使得损失图变得病态(稍后定义)。例如,在一个 2-D 线性回归问题中,如果两个特征都是标准化的,损失的等高线图应该接近圆形(参见我的另一篇关于数据标准化的文章)。
# two features
X1 = np.random.randn(1000,1)
X1 = (X1 -np.mean(X1))/np.std(X1)
X2 = np.random.randn(1000,1)
X2 = (X2 - np.mean(X2))/np.std(X2)
Y = 2.3*X1-0.8*X2 + 0.3*np.random.rand(1000,1)
gradient descent is smooth when features are independent, learning rate = 2e-3
当要素相互关联时,景观会变成椭球形,梯度下降往往会采用之字形路径。
# two features
X1 = np.random.randn(1000,1)
X1 = (X1 -np.mean(X1))/np.std(X1)
X2 = X1 + 0.5* np.random.randn(1000,1)
X2 = (X2 - np.mean(X2))/np.std(X2)
Y = 2.3*X1-0.8*X2 + 0.3*np.random.rand(1000,1)
learning rate = 2e-3
这可能会有问题,因为梯度下降算法可能会振荡,并且需要太长时间才能收敛(您可以通过降低学习速率来减少振荡,但这也会延长训练时间)。请看两个特征高度相关的极端情况:
X1 = np.random.randn(1000,1)
X1 = (X1 -np.mean(X1))/np.std(X1)
X2 = X1 + 0.02*np.random.randn(1000,1)
X2 = (X2 - np.mean(X2))/np.std(X2)
Y = 2.3*X1 - 0.8*X2 + 0.3*np.random.rand(1000,1)
Loss, learning rate = 2e-3(learning rate greater than this may diverge)
正如你所看到的,梯度下降在条件恶劣的损失景观中挣扎,需要更多的迭代(甚至 18,000 次迭代也不够!)实现合理亏损。基于高度相关特征的模型需要更多的迭代,因此需要更长的训练时间。
2.降低的估计能力
我们现在知道,基于高度相关特征的模型需要更多的迭代来训练。因此,如果您在其他项目中使用合理的迭代次数,如 6000 或 10000(在大多数情况下非常足够),算法可能会过早终止,这会损害模型的性能(请参见上面的损失表)。
还有另一个原因:在下面的多元线性回归模型中
X is the training data matrix, Y is the output vector
理论上的最佳估计值是:
如果 X 有冗余(共线性或多重共线性),则 X 的秩未满。因此,我们不能得到最好的估计,因为 X^T*X 的逆不存在。(延伸阅读)
3.你的模型很难解释
机器学习并不总是做预测,在某些应用中,支持基于模型的决策更重要。当涉及到模型分析时,简单的统计方法,如假设检验,就变得又好又方便。例如,人们使用标准误差及其相关的 p 值来判断某个特征是否与结果相关。
当数据集中存在共线性时,这些要素的 t 分值通常较小,因为相关要素的权重具有较大的方差。换句话说,基于不同分区的模型可能具有非常不同的特征参数。例如:
X1 = np.random.randn(1000,1)
X1 = (X1 -np.mean(X1))/np.std(X1)
X2 = X1
Y = 0*X1 + 6*X2 + 0.3*np.random.rand(1000,1)
#essentially 0*X1(X2) + 6*X1(X2) + 0.3*np.random.rand(1000,1)
anywhere on the blue line has the minimum loss
distribution of the estimated coefficient of X1 (w1)
由于蓝线上的任何位置都能成功地使 MSE 最小化,因此只要 w1+w2=6,w1 和 w2 就可能相差很大。如果我们用 X1 不相关的零假设进行显著性检验,很可能我们无法拒绝零假设,因为标准误差很大。例如:
import statsmodels.api as sma
X1 = np.random.randn(1000,1)
X1 = (X1 -np.mean(X1))/np.std(X1)
X2 = X1 + 0.01*np.random.randn(1000,1)
X2 = (X2 - np.mean(X2))/np.std(X2)
X = np.concatenate((X1,X2), axis=1)
Y = 0.5*X1 + X2 + 0.3*np.random.rand(1000,1)**# we know both X1 and X2 contribute to the outcome**
mod = sma.OLS(Y,X)
res= mod.fit()
print(res.summary()
X1 和 X2 的系数都具有较小的 t 值(因此具有较大的 P 值)。因此,我们错误地得出结论,X1 和 X2 都不相关(解释 P 值)。特征冗余会导致较大的系数标准误差,并掩盖特征在回归中的真实作用。
现在我们了解了特征冗余是如何损害建模和数据分析的,识别并移除特征冗余(也称为特征选择)对我们最有利。
如何识别特征冗余?
检测相关特征:条件编号
检测数据中多重共线性的一种流行方法称为特征系统分析,它使用条件数的概念。条件数的定义是:
condition number
给定一个矩阵(输入数据 X),求 X Corr(X)的相关矩阵:
correlation matrix of X
如果 X 的相关矩阵有很大的条件数,说明共线性严重。
下面是一个简短的示例,可以帮助您理解条件编号是如何工作的:
correlation between X1 and X2 determines the condition number
检测不相关的特征
检测无关特征的核心是发现输出是否受到给定特征的影响。基于输出的类型(连续或分类)和特性1,有几种数学方法可以使用。分类特征分类反应—卡方检验
Categorical feature categorical response
卡方检验的本质是假设输入和输出之间没有关系,并检查该假设的有效性。如果该特征确实影响响应,我们期望看到低 P 值。因此,通过选择具有低 p 值的特征来完成特征选择。点击此处查看更多卡方检验信息。
我创建了一些简单的人工数据集,让你更好地理解卡方为什么有用
import pandas as pd
import scipy.stats as sstX = np.random.randint(5,size=1000)
Y = np.ones(X.shape)
index = X<=2
Y[index] =0 # when X <=2, Y = 0\. Therefore X influences Y
crosstab = pd.crosstab(X,Y)
chi2, p,_,_ = sst.chi2_contingency(crosstab)
**###P value = 3.569412779777166e-215-> reject the null hypothesis ->feature is relevant**X = np.random.randint(5,size=1000)
Y = np.random.randint(2, size = 1000) # no relatinoship
crosstab = pd.crosstab(X,Y)
chi2, p,_,_ = sst.chi2_contingency(crosstab)
**###P value = 0.5244308199595783-> large P value, relationship is statistically insignificant**
2。类别特征连续反应—方差分析**
Categorical feature continuous response
方差分析(ANOVA)比较不同组的平均值(每个分类特征数据的响应平均值),并检验组间差异是否具有统计学意义。如果一个特征是相关的,我们期望看到不同组的均值之间的显著差异。点击此处查看更多关于方差分析的信息
示例:
X = np.random.randint(3,size=1000)
Y = np.random.rand(1000) # no relationship
one = Y[X==1]
two = Y[X==2]
zero = Y[X==0]
sst.f_oneway(one,two,zero)
**###statistic=0.07592457518151591, pvalue=0.9268914727618249-> large P value-> relationship is insignificant** X = np.random.randint(3,size=1000)
Y = np.random.rand(1000) + 0.1*X # X is part of Y
one = Y[X==1]
two = Y[X==2]
zero = Y[X==0]
sst.f_oneway(one,two,zero)
**### F_onewayResult(statistic=38.076396290550555, pvalue=1.1607768540773696e-16)-> reject the null hypothesis-> feature is relevant**
3。连续特征连续反应—相关或卡方/方差分析
continuous features and continuous response
最常见的相关系数称为皮尔逊系数,用于测试特征和响应之间的线性关系。当关系为非线性时,Pearson 相关返回低值。一个更好的选择叫做 Spearman 相关性,它测试单调关系是否存在。以下是一些例子:
Pearson’s Correlation Vs. Spearman’s Correlation
如您所见,Spearman 的相关性对于我们的应用程序有更好的性能,因为我们想要检测不相关的特征(Pearson 的给出更多的错误警报)。然而,当关系是非单调的(第四行)时,这两个指标的表现都很差。
另一种方法是将两个变量离散化,并使用卡方检验,正如您所看到的,它成功地确定了非单调关系:
X = 10*np.random.rand(1000)
Y = np.sin(X)
X_ca = pd.qcut(X,10, labels=False) # discretize into 10 classes
Y_ca = pd.qcut(Y,10, labels=False)crosstab = pd.crosstab(X_ca,Y_ca)
chi2, p,_,_ = sst.chi2_contingency(crosstab)
print ('P value = ', p)
**### P value = 0.0-> a strong relationship**
4。连续特征分类反应—卡方检验
continuous feature categorical response
对于这个问题,我们可以简单地通过将数据分成不同的“组”来离散化特征,就像我们在第 3 部分中所做的那样。离散化后,我们可以再次应用卡方检验。
摘要
好的特征可以显著提高模型的准确性和稳定性。因此,添加尽可能多的功能,以便找到好功能的可能性更高,这似乎是合理的。然而,使用大量特征在训练速度、准确性和可解释性方面可能是有害的,这就是为什么特征选择受到许多数据从业者的青睐。在下一篇文章中,你会看到一些系统化的算法,这些算法会自动选择相关特征并消除共线特征。
特征选择为什么和如何解释
Python 中特征选择算法的实现
在的上一篇文章中,我解释了在模型构建中包含不相关或相关特征的问题。在本文中,我将向您展示选择算法的几个简洁的实现,它们可以很容易地集成到您的项目管道中。
在深入详细的实现之前,让我们先来看一下我创建的数据集。数据集有 20 个要素,其中 5 个对输出有贡献,2 个是相关的。
1.包装特征选择
检测能力:★★★☆速度:★☆☆☆
包装算法很简单。通过训练和验证模型来检查特征的有效性。这意味着包装器在处理大型数据集时非常慢。
wrappers are iterative/recursive in nature
尽管添加/删除特性的具体标准可能不同,但核心思想是相同的。因此,我将重点介绍一种叫做反向选择的特殊方法。
— 1.1.包装算法:向后选择
提供具有特征系数(例如回归)或重要性因子(例如树)的模型,算法从所有特征开始,贪婪地消除最不重要的特征。一旦删除了所有特征,该算法就返回给出最佳性能的子集。
— 1.2.Python 中的向后选择:
Scikit-Learn 提供了一个很好的实现,称为 RFECV (递归特征消除和交叉验证选择),一种基于验证分数的算法来消除不相关的特征。
估计器 : 对象
使用
*fit*
方法的监督学习估计器,通过*coef_*
或*feature_importances_*
提供关于特征重要性的信息评分:字符串,可调用或无,可选,(默认=无)
Scikit-Learn 中有许多估值器满足标准。在这个例子中,使用了一个简单的 SVM 分类器。评分函数是评估模型性能(如准确性)的度量。
RFECV 选择了 7 个特征,包括所有相关特征和冗余特征。这表明 RFECV 不擅长移除多重共线性(因为共线性要素的系数往往变化很大)。因此,最好先识别多重共线性(例如使用条件号识别)。
2.过滤特征选择
检测能力:★★☆☆☆速度:★★★
在使用数百万个数据点的真实应用程序中,包装器变得不切实际。过滤算法通过统计测试(例如相关系数)而不是训练实际模型来估计特征的有效性,从而解决问题。
虽然有很多先进的过滤方法,如 mRMR,但我更喜欢这种简单的两步方法。
— 2.1.移除相关要素:条件编号
正如第一篇文章中介绍的,共线性或多重共线性是有害的。下面是我自己开发的一个算法,可以消除两者。
— 2.2.移除不相关的特征:单变量选择
单变量选择对特征和输出执行统计测试,并且仅保留具有高分的特征。常见的测试包括卡方检验、方差分析或互信息。
同样,Scikit-Learn 提供了一个很好的函数,称为 GenericUnivariateSelect。该功能需要 3 个参数
score_func : 可调用
函数采用两个数组 X 和 y,并返回一对数组(分数、pvalues)。对于“百分位数”或“kbest”模式,它可以返回单个数组分数。
模式 : { ‘百分位’,’ k_best ‘,’ fpr ‘,’ fdr ‘,’ fwe’}
param : float 或 int 取决于特征选择模式
选择您想要的统计方法(如卡方检验、F 值)作为评分函数。我将使用卡方,因为 y 是绝对的。
该算法会丢弃 P 值大于 0.5 的要素。使用不太小的阈值是一个很好的实践,这样我们就不会丢失有用的特性(我们在这里丢失了一个有用的特性)。
3。嵌入式特征选择
检测能力:★★★☆☆速度:★★★☆☆
嵌入式特征选择在训练期间智能地丢弃不必要的特征。常见的算法包括 Lasso 回归、决策树和自动编码神经网络。我将在这里解释套索回归。
— 3.1.嵌入式算法:Lasso 回归
Lasso adds a penalty term to the loss function
套索回归因使用大的要素权重/过多的要素而对模型不利。因此,模型倾向于使用尽可能少的参数,从而产生稀疏的结果(例如,一些特征的权重为 0)。
— 3.2.Python 中的套索回归
像往常一样,你可以在 Scikit-Learn 中找到 lasso 回归。在初始化模型时,您必须提供的唯一参数是 Alpha,它决定了惩罚的强度。更大的 alpha 导致更稀疏的结果,alpha=0 实质上意味着没有套索惩罚。
an example of how alpha affects feature selection
如您所见,选择强度由 Alpha 决定。问题是我们不知道应该用什么α。这个问题可以通过选择在交叉验证中表现最好的值来解决。
该模型最终使用 5 个参数,这意味着所有冗余和相关的特征都被排除在模型之外。
摘要
每种类型的选择算法都有其优点和缺点,并且没有使用什么方法的经验法则。在项目环境中考虑权衡是很重要的。
- 包装器提供了最高的选择质量,因为它实际上在不同的特征子集上训练模型。高质量的代价是培训时间。
- 过滤器的选择基于统计数据,速度非常快。但是,它可能无法检测到最佳的特征子集。
- 中间嵌入选择,以公允的价格提供合理的选择力。
使用 sklearn 和 Pandas 进行功能选择
要素选择方法及其在 Python 中的实现简介
在执行任何机器学习任务时,特征选择都是首要且重要的步骤之一。在数据集的情况下,一个特征仅仅意味着一列。当我们获取任何数据集时,不一定每个列(要素)都会对输出变量产生影响。如果我们在模型中添加这些不相关的特性,只会让模型变得更糟(垃圾进垃圾出)。这就产生了进行特征选择的需要。
当在熊猫中实现特征选择时,数字特征和分类特征要区别对待。这里我们将首先讨论关于数字特征的选择。因此,在实现以下方法之前,我们需要确保数据帧只包含数字特征。此外,下面的方法是讨论回归问题,这意味着输入和输出变量都是连续的性质。
特征选择可以通过多种方式完成,但大致有 3 类:1。过滤方法
2。包装方法
3。嵌入式方法
关于数据集:
我们将使用内置的波士顿数据集,它可以通过 sklearn 加载。我们将使用上面列出的方法为预测“MEDV”列的回归问题选择特征。在下面的代码片段中,我们将导入所有需要的库并加载数据集。
#importing libraries
from sklearn.datasets import load_boston
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
import statsmodels.api as sm
%matplotlib inline
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.feature_selection import RFE
from sklearn.linear_model import RidgeCV, LassoCV, Ridge, Lasso#Loading the dataset
x = load_boston()
df = pd.DataFrame(x.data, columns = x.feature_names)
df["MEDV"] = x.target
X = df.drop("MEDV",1) #Feature Matrix
y = df["MEDV"] #Target Variable
df.head()
1.过滤方法:
顾名思义,在这种方法中,您只需要过滤并提取相关特性的子集。模型是在选择特征之后构建的。这里的过滤是使用相关矩阵完成的,最常用的是使用皮尔逊相关。
在这里,我们将首先绘制皮尔逊相关性热图,并查看自变量与输出变量 MEDV 的相关性。我们将只选择与输出变量的相关性高于 0.5(取绝对值)的特征。
相关系数的值在-1 到 1 之间
—越接近 0 的值意味着相关性越弱(恰好 0 意味着不相关)
—越接近 1 的值意味着正相关性越强
—越接近-1 的值意味着负相关性越强
#Using Pearson Correlation
plt.figure(figsize=(12,10))
cor = df.corr()
sns.heatmap(cor, annot=True, cmap=plt.cm.Reds)
plt.show()
#Correlation with output variable
cor_target = abs(cor["MEDV"])#Selecting highly correlated features
relevant_features = cor_target[cor_target>0.5]
relevant_features
如我们所见,只有特征 RM、PTRATIO 和 LSTAT 与输出变量 MEDV 高度相关。因此,我们将放弃除此之外的所有其他功能。然而,这并不是过程的结束。线性回归的假设之一是自变量需要彼此不相关。如果这些变量是相互关联的,那么我们只需要保留其中一个,去掉其余的。因此,让我们检查所选特征彼此之间的相关性。这可以通过从上面的相关矩阵或下面的代码片段中直观地检查来完成。
print(df[["LSTAT","PTRATIO"]].corr())
print(df[["RM","LSTAT"]].corr())
从上面的代码中可以看出,变量 RM 和 LSTAT 是高度相关的(-0.613808)。因此,我们将只保留一个变量,丢弃另一个。我们将保留 LSTAT,因为它与 MEDV 的相关性高于 RM。
删除 RM 后,我们只剩下两个特性,LSTAT 和 PTRATIO。这些是皮尔逊相关给出的最终特征。
2.包装方法:
包装器方法需要一个机器学习算法,并使用其性能作为评估标准。这意味着,您将特征输入到选定的机器学习算法中,并根据模型性能添加/移除特征。这是一个迭代且计算量大的过程,但比滤波方法更精确。
有不同的包装方法,如向后消除、向前选择、双向消除和 RFE。我们将在这里讨论逆向淘汰和 RFE。
一、逆向淘汰
顾名思义,我们首先将所有可能的特征输入到模型中。我们检查模型的性能,然后迭代地逐一移除性能最差的特征,直到模型的整体性能在可接受的范围内。
这里用来评估特性性能的性能指标是 pvalue 。如果 pvalue 大于 0.05,那么我们移除该特征,否则我们保留它。
我们将首先在这里运行一次迭代,只是为了得到一个概念的想法,然后我们将在一个循环中运行相同的代码,这将给出最终的特性集。这里我们使用的是代表“普通最小二乘法”的 OLS 模型。该模型用于执行线性回归。
#Adding constant column of ones, mandatory for sm.OLS model
X_1 = sm.add_constant(X)#Fitting sm.OLS model
model = sm.OLS(y,X_1).fit()
model.pvalues
正如我们所看到的,变量“年龄”的 p 值最高,为 0.9582293,大于 0.05。因此,我们将删除此功能,并再次构建模型。这是一个迭代过程,可以在 loop 的帮助下立即执行。这种方法在下面实施,它将给出最终的一组变量,即 CRIM、ZN、CHAS、NOX、RM、DIS、RAD、TAX、PTRATIO、B 和 LSTAT
#Backward Elimination
cols = list(X.columns)
pmax = 1
while (len(cols)>0):
p= []
X_1 = X[cols]
X_1 = sm.add_constant(X_1)
model = sm.OLS(y,X_1).fit()
p = pd.Series(model.pvalues.values[1:],index = cols)
pmax = max(p)
feature_with_p_max = p.idxmax()
if(pmax>0.05):
cols.remove(feature_with_p_max)
else:
breakselected_features_BE = cols
print(selected_features_BE)**Output:***['CRIM', 'ZN', 'CHAS', 'NOX', 'RM', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT']*
二。RFE(递归特征消除)
递归特征消除 (RFE)方法的工作原理是递归移除属性,并在那些保留的属性上建立模型。它使用准确性度量来根据特征的重要性对其进行排序。RFE 方法将使用的模型和所需特征的数量作为输入。然后给出所有变量的排名,1 是最重要的。它也给出了支持,真的是相关特征,假的是不相关特征。
model = LinearRegression()#Initializing RFE model
rfe = RFE(model, 7)#Transforming data using RFE
X_rfe = rfe.fit_transform(X,y) #Fitting the data to model
model.fit(X_rfe,y)
print(rfe.support_)
print(rfe.ranking_)**Output:***[False False False True True True False True True False True False
True]
[2 4 3 1 1 1 7 1 1 5 1 6 1]*
这里我们采用了 7 个特征的线性回归模型,RFE 给出了如上的特征排名,但是数字“7”的选择是随机的。现在,我们需要找到最佳数量的特征,其精度是最高的。我们通过使用从 1 个特征开始到 13 个特征的循环来实现。然后我们取精确度最高的那个。
#no of features
nof_list=np.arange(1,13)
high_score=0
#Variable to store the optimum features
nof=0
score_list =[]
for n in range(len(nof_list)):
X_train, X_test, y_train, y_test = train_test_split(X,y, test_size = 0.3, random_state = 0)
model = LinearRegression()
rfe = RFE(model,nof_list[n])
X_train_rfe = rfe.fit_transform(X_train,y_train)
X_test_rfe = rfe.transform(X_test)
model.fit(X_train_rfe,y_train)
score = model.score(X_test_rfe,y_test)
score_list.append(score)
if(score>high_score):
high_score = score
nof = nof_list[n]print("Optimum number of features: %d" %nof)
print("Score with %d features: %f" % (nof, high_score))**Output:***Optimum number of features: 10
Score with 10 features: 0.663581*
从上面的代码可以看出,特性的最佳数量是 10。我们现在向 RFE 输入 10 个特征,并得到由 RFE 方法给出的最终特征集,如下所示:
cols = list(X.columns)
model = LinearRegression()#Initializing RFE model
rfe = RFE(model, 10) #Transforming data using RFE
X_rfe = rfe.fit_transform(X,y) #Fitting the data to model
model.fit(X_rfe,y)
temp = pd.Series(rfe.support_,index = cols)
selected_features_rfe = temp[temp==True].index
print(selected_features_rfe)**Output:***Index(['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'DIS', 'RAD', 'PTRATIO',
'LSTAT'],
dtype='object')*
3.嵌入式方法
嵌入式方法在某种意义上是迭代的,它负责模型训练过程的每次迭代,并仔细提取那些对特定迭代的训练贡献最大的特征。正则化方法是最常用的嵌入式方法,其在给定系数阈值的情况下惩罚特征。
这里我们将使用套索正则化进行特征选择。如果特征是不相关的,套索惩罚它的系数,使其为 0。因此,系数= 0 的特征被移除,其余的被采用。
reg = LassoCV()
reg.fit(X, y)
print("Best alpha using built-in LassoCV: %f" % reg.alpha_)
print("Best score using built-in LassoCV: %f" %reg.score(X,y))
coef = pd.Series(reg.coef_, index = X.columns)
print("Lasso picked " + str(sum(coef != 0)) + " variables and eliminated the other " + str(sum(coef == 0)) + " variables")
imp_coef = coef.sort_values()
import matplotlib
matplotlib.rcParams['figure.figsize'] = (8.0, 10.0)
imp_coef.plot(kind = "barh")
plt.title("Feature importance using Lasso Model")
在这里,套索模型已经采取了除氮氧化物,查斯和印度河的所有功能。
结论:
我们看到了如何使用多种方法为数字数据选择特征,并比较了它们的结果。现在出现了在什么情况下选择哪种方法的困惑。以下几点将帮助你做出这个决定。
- 过滤方法不太准确。在做 EDA 的时候很棒,也可以用来检查数据中的多重共线性。
- 包装器和嵌入式方法给出了更精确的结果,但是由于它们的计算量很大,所以这些方法适用于特性较少的情况(~20)。
在下一篇博客中,我们将会看到更多的用于选择数字和分类特征的特征选择方法。
功能存储:数据科学工厂的组件
几年前,优步发现自己面临着任何拥有复杂机器学习业务的公司或组织都熟悉的困境:昂贵而低效的特征工程方法。特征工程需要将原始数据转换为预测模型可理解的格式,但其数据工程师花费了无数时间来为客户人口统计数据、过去的购买历史和数字渠道互动等流行类别重新创建和重用相同的精选建模属性。
识别问题
随着机器学习的某些方面赢得了混乱过程的名声,各个组织的领导者都认识到了反复出现的瓶颈。
1.数据工程师在模型服务期间没有遵循访问要素的最佳实践。
2.数据科学家通常在没有协作的情况下独立完成项目。
3.用于训练的特征和用于服务的特征之间出现不一致。
4.必须运行整个管线,而不是在新数据可用时重新计算选择的特征。
5.为每个项目重新发明轮子所花费的时间导致成本膨胀和速度减慢。
所有这些因素都拖慢了项目的进度;由于团队无法重建预测模型或产生一致的结果,企业冒着失去客户和利益相关者对结果的信任和支持的风险。
特色商店开始获得关注
2017 年,优步推出了米开朗基罗,这是其机器学习平台的一个新的数据管理方面。在其他属性中,米开朗基罗为内部数据科学家和工程师提供了一个功能存储,允许他们与其他团队和机器学习管道中的未来项目一起摄取、编目和共享功能。
这是一个革命性的非常及时的新概念,其他公司纷纷效仿,要么自己建立特色商店,要么提供服务为他人实施和维护该技术。2019 年初,谷歌宣布了 Feast ,这是一个开源的功能商店,为机器学习团队提供解决方案。
随着要素存储的运行,数据团队面临着新的挑战
虽然功能商店的新概念仍处于起步阶段,但专业人士遇到了新的困境。流动运营需要在线和离线分析环境,公司努力缩小两者之间的差距。要运营一个高功能的数据科学工厂,必须弥合这一差距,并确保跨两个平台的高效通信和操作。
由于两个平台之间的不一致,结果的质量、准确性和可靠性出现了问题。
了解强大的离线功能商店
这些操作托管着包含多年历史的大规模、大规模并行环境,并针对同时分析许多记录进行了调整。离线操作可能包括用于揭示大量历史数据中的洞察力和模式的发现环境。处理这些查询可能需要 10 秒到几个小时的时间。
常见的技术包括 Hadoop、数据湖、云存储(S3、Azure Blob、谷歌大查询)、雪花、红移、Netezza、Vertica 和 Teradata。
利用 nimble 在线功能商店
在线运营的运作方式有所不同,在运行任务关键型应用程序、网站和移动应用程序的低延迟环境中提供卓越的可用性。凭借高速响应时间,在线要素商店可在数毫秒内将模型部署到应用程序中,并依靠它们做出近乎实时的决策。
常见的技术有 RESTful 服务、关系数据库(Oracle、MySQL、SQL Server)、NoSQL 数据库(MongoDB、Couchbase、Cassandra 等)。).
弥合线下和线上功能商店之间差距的技巧
1.在离线和在线要素存储之间创建数据奇偶校验,以确保离线训练的模型在用于实时决策时与在线数据相匹配。
2.使用现代数据目录来管理和控制各种功能集,以确保字段、自动评估的质量、数据类型、数据所有者和 SME 都得到很好的记录。专业提示: Alation 和 Colibra 是最佳的数据目录。
3.使用批处理环境创建无法实时进行的长期聚合和推导。创建完成后,将其发布到在线要素存储中,以进行实时模型服务。
4.将实时变量和上下文数据从在线商店推送到线下。
5.从在线环境中创建反馈循环,并记录模型输入、输出和业务成果或响应,以便为自动化模型性能监控和最终自动化模型保留进行自我定位。
随着两家商店的同步,团队可以达到新的效率水平
数据团队正在从成本中心向利润中心转变。随着领导者越来越多地将数据支持的见解融入战略,数据团队承担了更多责任。由于创造过程的高度复杂性,研究人员将机器学习称为“T2 技术债务的高息信用卡”。随着新程序和技术的出现,减少了纠缠和死胡同的数量,效率成为当今的主流。
有了必要的资源,任何团队都可以运营一个高功能的数据科学工厂。特色商店的引入使该行业朝着正确的方向前进了一步,同时也暴露了更多的低效问题。投入时间和精力同步线上和线下商店可以提高可靠性、准确性和效率,并有助于确保客户和团队成员的持续成功。
如需了解更多有关快速通道如何工作的信息,请点击此处访问我们。
这篇文章最初出现在 Quickpath 的博客上。
Python 中多元线性回归的特征变换
用于建模的数据处理和转换
数据处理和转换是一个迭代过程,在某种程度上,它永远不可能是“完美的”。因为随着我们对数据集的了解越来越多,例如目标变量和特征之间的内在关系,或者业务环境,我们会想到处理它们的新方法。最近,我开始利用多元线性回归研究媒体组合模型和一些预测模型。在这篇文章中,我将介绍建模的思维过程和处理变量的不同方法。
我就用金县房价数据集(为了更好玩的修改版)来举例。
我们先导入库,看看数据!
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import scipy.stats as stats% matplotlib inlinedf = pd.read_csv(“kc_house_data.csv”)
df.head()
Image by Author
识别缺失值和明显不正确的数据类型。
df.info()<class 'pandas.core.frame.DataFrame'>
RangeIndex: 21597 entries, 0 to 21596
Data columns (total 21 columns):
id 21597 non-null int64
date 21597 non-null object
price 21597 non-null float64
bedrooms 21597 non-null int64
bathrooms 21597 non-null float64
sqft_living 21597 non-null int64
sqft_lot 21597 non-null int64
floors 21597 non-null float64
waterfront 19221 non-null float64
view 21534 non-null float64
condition 21597 non-null int64
grade 21597 non-null int64
sqft_above 21597 non-null int64
sqft_basement 21597 non-null object
yr_built 21597 non-null int64
yr_renovated 17755 non-null float64
zipcode 21597 non-null int64
lat 21597 non-null float64
long 21597 non-null float64
sqft_living15 21597 non-null int64
sqft_lot15 21597 non-null int64
dtypes: float64(8), int64(11), object(2)
memory usage: 3.5+ MB
在大多数统计模型中,变量可以分为 4 种数据类型:
- 连续:在一个选定的范围内可以有无限个可能值。“float”通常用于 python 中的连续数据。例如生活区的长度
- **标称:**标称变量使用数字表示来解释对象的类型或属性。它们是具有两个或更多可能值的分类值,没有固有的顺序或排列次序。例如,汽车的原产国,美国可以是 1,日本 2,德国 3
- **序数:**序数变量实际上是呈现数值。它们通常在有限的范围内有两个或更多的可能值,并且这些值具有有序的类别。比如房子的档次。当你用 target 绘制序数值时,你经常会看到清晰的垂直线。在数据集中,序号数据可能被读取为整数或浮点数,因此数据可视化总是有助于检测它们
- **二进制:**只有 2 个可能的值,通常是 0 和 1。虚拟变量是二进制的
下图清楚地显示了这种关系。
Common data types in statistics (Image by Author)
连续变量的变换
- Log: 当您有偏斜的数据时,Log 转换有助于减少偏斜。
以房价为例。
df_log[‘price’] = np.log(df[‘price’])
sns.distplot(df_set['price'], fit=norm)
fig = plt.figure()
before log transformation (Image by Author)
after log transformation (Image by Author)
- **幂:**如果我们从本质上知道自变量与目标变量存在指数或递减关系,我们可以使用幂变换。例如,当我们试图建立电视广告支出与销售额的模型时,我们知道在某个时候,电视广告对销售额的影响会降低。这就是所谓的“收益递减”。所以我们通常使用 0.3 到 0.7 的幂来转换电视支出,以便我们可以获得更好的模型拟合。
- **标准化:**减去平均值,除以标准差。标准化并没有使数据更正常,它只是改变了平均值和标准误差。
scaled_price = (logprice -np.mean(logprice))/np.sqrt(np.var(logprice))
- **均值归一化:**分布的值介于-1 和 1 之间,均值为 0。
- **最小-最大缩放:**带来 0 到 1 之间的值
离散变量的变换
- **标签编码:**当实际值是文本,并且您想要为变量创建数值时。例如:
origin = [“USA”, “EU”, “EU”, “ASIA”,”USA”, “EU”, “EU”, “ASIA”, “ASIA”, “USA”]
origin_series = pd.Series(origin)
cat_origin = origin_series.astype('category')
cat_origin.cat.codes0 2
1 1
2 1
3 0
4 2
5 1
6 1
7 0
8 0
9 2
dtype: int8#Or use scikit-learn's LabelEncoder:from sklearn.preprocessing import LabelEncoder
lb_make = LabelEncoder()origin_encoded = lb_make.fit_transform(cat_origin)origin_encodedarray([2, 1, 1, 0, 2, 1, 1, 0, 0, 2])
- 宁滨:宁滨在处理序数值时非常得心应手。在模型中,我们可以通过基于值分布创建箱,然后创建虚拟变量,将变量转换为分类变量,而不是将顺序值作为整数读取。
在金县房价例子中,等级是一个与房价正相关的顺序变量。
Image by Author
df[‘grade’].describe()count 21596.000000
mean 7.657946
std 1.173218
min 3.000000
25% 7.000000
50% 7.000000
75% 8.000000
max 13.000000
Name: grade, dtype: float64
我们可以基于百分点值创建 4 个箱。
bins = [3,7,8,10,13]
bins_grade = pd.cut(df[‘grade’],bins)bins_grade.value_counts().plot(kind='bar')
bins_grade (Image by Author)
bins_grade0 (3, 7]
1 (3, 7]
2 (3, 7]
3 (3, 7]
4 (7, 8]
5 (10, 13]
6 (3, 7]
7 (3, 7]
8 (3, 7]
9 (3, 7]
10 (7, 8]
11 (3, 7]
12 (3, 7]
13 (3, 7]
14 (3, 7]
15 (8, 10]
然后我们为它们创建虚拟变量,因为一些建模技术需要数值。
bins_grade = bins_grade.cat.as_unordered()
grade_dummy = pd.get_dummies(bins_grade, prefix=’grade’)
- 创建虚拟变量
另一种创建虚拟变量的方法是使用 sklearn.preprocessing 包中的 LabelBinarizer
from sklearn.preprocessing import LabelBinarizerlb = LabelBinarizer()
grade_dummies = lb.fit_transform(grade)
# you need to convert this back to a dataframe
grade_dum_df = pd.DataFrame(grade_dummies,columns=lb.classes_)
使用哑元的好处是,无论你使用什么算法,你的数值都不会被误解为连续的。接下来,重要的是要知道对于线性回归(以及 scikit-learn 中的大多数其他算法),在回归模型中添加分类变量时需要一键编码!
同样,特征转换涉及多次迭代。有许多方法可以为模型获取正确的数据。保持好奇和耐心就好!
用闪光灯揭开神经网络“看到”了什么
py torch 中用于神经网络的开源特征可视化工具包
Visualisation of what AlexNet “sees” in these images of birds, using FlashTorch. Source
设置场景
几周前,作为伦敦科技周的一部分,我在由 AnitaB.org[组织的伦敦hopper x1T7]上做了一次演讲。滑梯可在](https://anitab.org/)这里获得。
我在演讲后收到了如此积极的反馈,所以我决定写一个稍微长一点的演讲版本,以便以前向世界介绍【T0:)
该软件包可以通过pip
进行安装。查看源代码的 GitHub repo 。你也可以在 Google Colab 的笔记本上使用它,而不需要安装任何东西!
但是首先,我将简要回顾一下特征可视化的历史,给你一个关于什么&为什么的更好的背景。
特征可视化介绍
特征可视化 是一个活跃的研究领域,旨在通过探索我们可以“通过他们的眼睛”看东西的方式来理解神经网络如何感知图像。它的出现和发展是为了响应让神经网络更容易被人类理解的日益增长的愿望。
最早的工作包括分析神经网络在输入图像中关注什么。例如, 特定于图像的类别显著性图 通过经由反向传播计算类别输出相对于输入图像的梯度,使输入图像内对相应输出贡献最大的区域可视化(稍后将在帖子中详细介绍显著性图)。
Earliest work on image-specific class saliency maps. Source
特征可视化的另一个技巧是。这允许我们迭代地更新输入图像(最初由一些随机噪声产生)以生成最大限度地激活目标神经元的*图像。它提供了一些关于个体神经元如何对输入做出反应的直觉。这是所谓的深度梦背后的技术,由谷歌推广。*
Deep Dream: what does the network sees in the sky? Source
这是一个巨大的进步,但有缺点,因为它没有提供足够的洞察力来了解整个网络是如何运行的,因为神经元不是孤立运行的。这导致了可视化神经元之间相互作用的努力。Olah 等人通过两个神经元之间的相加或插值,演示了激活空间的 算术性质 。
Neuron arithmetic. Source
然后奥拉在阿尔。通过分析给定特定输入时每个中子在隐藏层中发射的数量,进一步定义了更有意义的可视化单位。 将一组被强烈激活在一起的神经元可视化 揭示出似乎有一组神经元负责捕捉诸如耷拉的耳朵、毛茸茸的腿和草等概念。
A group of neurons detecting floppy ears. Source
该领域内的最新发展之一是 激活图谱 (卡特等人,2019)。在这项研究中,作者解决了可视化过滤器激活的一个主要弱点,因为它仅给出了网络如何响应单输入的有限视图。为了更好地了解网络如何感知无数的对象,以及这些对象在网络的世界中如何相互关联,他们设计了一种方法,通过显示神经元的常见组合来创建“通过网络之眼看到的全球地图”。
Different ways to visualise the network. Source
手电筒背后的动机
当我发现特征可视化的世界时,我立即被它在使神经网络更易解释和说明方面的潜力所吸引。然后我很快意识到,没有工具可以轻松地将这些技术应用于我在 PyTorch 中构建的神经网络。
所以我决定建一个— [FlashTorch](https://github.com/MisaOgura/flashtorch)
,现在可以通过 *pip*
安装!我实现的第一个特征可视化技术是显著图**。**
我们将在下面更详细地看看什么是显著图,以及如何使用FlashTorch
在你的神经网络中实现它们。
显著图
显著性,在人类视觉感知中,是一种主观品质使视野中的某些事物突出并抓住我们的注意力。计算机视觉中的显著图可以给出图像中最显著区域的指示。**
Examples of saliency maps. Source
从卷积神经网络(CNN)创建显著图的方法最早于 2013 年在论文 深入卷积网络内部:可视化图像分类模型和显著图 中提出。作者报告称,通过计算目标类别相对于输入图像的梯度,我们可以可视化输入图像内的区域,这些区域对该类别的预测值有影响。
使用闪光灯的显著性图
事不宜迟,让我们使用FlashTorch
并自己可视化显著图!
FlashTorch
还附带了一些utils
功能,让数据处理变得更加简单。我们将用这张great grey owl
的图片作为例子。
然后,我们将对图像应用一些变换,使它的形状、类型和值适合作为 CNN 的输入。
我将使用已经用ImageNet
分类数据集预训练过的AlexNet
进行可视化。事实上,FlashTorch
支持所有自带torchvision
的型号,所以我鼓励你也尝试其他型号!**
Backprop
类是创建显著图的核心。
在实例化时,它接受一个模型Backprop(model)
并且将自定义挂钩注册到网络中感兴趣的层,这样我们就可以从计算图中抓取中间梯度以便可视化。由于PyTorch
的设计方式,这些中间梯度不会立即提供给我们。FlashTorch
帮你整理一下:)
现在,在计算梯度之前,我们需要的最后一件事是目标类索引**。**
概括地说,我们对目标类相对于输入图像的梯度感兴趣。然而,该模型是用ImageNet
数据集预先训练的,因此其预测被提供为1000 个类别的概率分布。我们希望从这 1000 个值中找出目标类的值(在我们的例子中是great grey owl
),以避免不必要的计算,并且只关注输入图像和目标类之间的关系。**
为此,我还实现了一个名为ImageNetIndex
的类。如果你不想下载整个数据集,只想根据类名找出类索引,这是一个方便的工具。如果你给它一个类名,它会找到对应的类索引target_class = imagenet['great grey owl']
。如果您确实想要下载数据集,请使用最新版本torchvision==0.3.0
中提供的[ImageNet](https://pytorch.org/docs/stable/torchvision/datasets.html#imagenet)
类。
现在,我们有了输入图像和目标类索引(24
),所以我们准备好计算渐变**!**
这两行是关键:
gradients = backprop.calculate_gradients(input_, target_class)
max_gradients = backprop.calculate_gradients(input_, target_class, take_max=**True**)
默认情况下,将为每个颜色通道计算渐变,因此它的形状将与输入图像相同——在我们的例子中为(3, 224, 224)
。有时,如果我们采用颜色通道的最大梯度,会更容易看到梯度。我们可以通过将take_max=True
传递给方法调用来实现。渐变的形状将是(1, 224, 224)
。**
最后,让我们想象一下我们得到了什么!
From far left: input image, gradients across colour channels, max gradients, an overlay of input image and max gradients
我们可以理解,动物所在区域的像素对预测值的影响最大。
但这是一种噪音…信号是传播的,它没有告诉我们多少关于神经网络对猫头鹰的感知。
有办法改善这一点吗?
引导返回救援
答案是肯定的!
在论文 力求简单:全卷积网 中,作者介绍了一种降低梯度计算中噪声的巧妙方法。
Guided backpropagation. Source
本质上,在导向反向传播中,对目标类的预测值没有影响或负面影响的神经元被屏蔽掉并被忽略。通过这样做,我们可以阻止梯度流通过这样的神经元,从而减少噪音。
您可以通过将guided=True
传递给calculate_gradients
的方法调用,在FlashTorch
中使用引导式反向传播,如下所示:
让我们想象引导梯度。
差别是惊人的!
现在我们可以清楚的看到网络在关注一只猫头鹰的凹陷的眼睛圆头。这些都是“说服”网络将对象归类为great grey owl
的特征。
但是它并不总是聚焦在眼睛或头部…
****
正如你所看到的,这个网络已经学会关注那些与我们认为这些鸟最有区别的特征相一致的特征。
特征可视化的应用
有了特征可视化,我们不仅可以更好地理解神经网络对物体的了解,而且我们可以更好地进行:
- 诊断网络出了什么问题以及为什么
- 发现并纠正算法中的偏差
- 从只看准确性向前迈一步
- 理解网络行为的原因
- 阐明神经网络如何学习的机制
今天就使用闪光灯吧!
如果你有在 PyTorch 中使用 CNN 的项目,FlashTorch
可以帮助你使你的项目更具可解释性和可解释性。
如果用了请告诉我你的想法!我将非常感谢您的建设性意见、反馈和建议🙏
谢谢,祝编码愉快!
特征相关性:数据泄露、混淆的特征和其他可能使你的深度学习模型失败的事情
在现象学科学中,尤其是在深度学习中,最容易被忽视的概念之一是输入特征之间的相关性。
什么是相关性?查看这幅漫画:
从 boss 正在展示的情节来看,剃光头的员工越多,公司销售额增长越多。如果你是老板,你会考虑对你的员工采取同样的行动吗?大概不会。
事实上,你认识到两组事件之间没有的因果关系,它们的行为相似只是偶然。更清楚的是:剃光头不会导致销售。
所以,我们发现了至少两种可能的相关性:没有因果关系和有因果关系。我们还一致认为,只有第二个是有趣的,而另一个是无用的,当不误导。但是让我们更深入一点。
深度学习中的相关性
让我介绍一个深度学习领域的例子,特别是在计算机视觉领域,特征之间的非因果相关性实际上使模型失败。
一张图有哪些「特色」?
一般来说,要素是模型用来构建预测的任何东西。但是,在这种情况下,指定什么是特性可能更好:
考虑一张脸的照片。功能可以是:
- 大量的绿色像素
- 充满绿色像素的圆圈
- 一组白色像素,包含由绿色像素填充的圆圈
- …以上所有内容构成了一只眼睛
- …所有之前的和更多的来构成脸部。
都是特色。为了保持关注,特征“虹膜”与特征“眼睛”相关联。
给老虎分类
现在,假设您训练一个模型来识别老虎,并假设训练集由成千上万张类似于下图的图片组成。
Tiger examples in the Training set.
当然,训练集包括描述什么不是老虎的其他图片;也许是其他动物,汽车,直升机等。
假设您在这样的数据集上训练的模型在测试集上表现得非常好。你对自己的模型很满意,于是你去了一个动物园,想用一张老虎的照片来试试:
The picture you took in the zoo.
您希望模型举起绿色旗帜,将图片识别为包含一只老虎。但是这个模型实际上完全失败了,说它不是。哪里出了问题?
有罪者:相关的、非因果的特征
也许您已经发现了这个问题:训练集中的图片显示的是森林中的老虎,而动物园中的图片显示的是笼子中的老虎。用技术术语来说,你拍的照片属于与训练集不同的发行版。
正在发生的是:模型认为老虎是你所知道的被“森林”包围的动物,因为在我们的训练集中它总是这样。因为在动物园的照片中没有森林,所以模型不认为照片中有老虎。
现在我们可以更好地区分相关性,引入第三个类别,即由混杂因素引起的相关性。它的效果实际上可以混淆模型,让它相信在动物和森林之间存在实际上并不存在的因果关系。
在我们的例子中,混杂因素,又名隐藏特征* (H)导致特征“老虎”和“森林”出现在同一张图片中。h 是一系列事件,如:生物学,发现老虎的机会,还有摄影师的心情,媒体的兴趣,以及任何能让老虎出现在森林中的事物。*
所以当这一组事件 H 发生时,就生成了一张森林中有老虎的图片。但是 H 是不可概括的:并不是每一次老虎出现的时候,森林也会出现,就像动物园里的照片或者雪地里的老虎。
换句话说,我们的模型 do 相信老虎是隐藏的特征 H* ,而不仅仅是我们所知道的老虎这种动物。*
示意图
我们刚刚介绍了在构建数据模型时应该辨别的三种类型的相关性。让我们在一个模式中看到它们
- 第一种情况最容易识别,就像文章开头的漫画。这种情况在机器学习领域的一种表现形式被称为数据泄露。
作为例子,考虑老虎分类器,并且假设每张包含老虎的图片都被标注了一些标记,比如图片左上角的绿色十字。由于像梯度下降这样的最小化方法是懒惰的,所以模型识别标记比识别老虎更容易。因此,模型将只检查标记的存在来识别老虎图片。显而易见的推论是,这样的模型实际上是没有用的,因为在生产中,你不会找到你在训练集中得到的分数。 - 第二种情况是我们唯一可以放心接受的。老虎身上的条纹就是一个例子:因为没有没有条纹的老虎,所以当且仅当老虎身上有条纹时,模型对老虎进行分类是安全的。
- 第三种情况更加微妙,很难向模型教授。但往往可以简单忍受。
—微妙,因为它在培训阶段很容易被忽略,只有在生产中才能发现,就像 tiger 的例子。
—由于统计数据而难以教授:假设您刚刚发现了我们在上一段中描述的模型中的问题,为了解决它,您将您拍摄的照片添加到训练集中。在这样的基础上,模型仍然很难忽略“森林”这一特征,而当面对笼子里的老虎时,训练过程更有可能接受更大的误差。从技术上来说,你添加的图片并没有改变超空间权重的最小值,因为它只是一个超过 1001 的样本。这意味着当你在除了森林以外的任何环境中面对老虎时,你的模型很可能会在生产中失败。
但是也许你的模型被期望用于森林,所以你可以接受你的模型包括这个混杂因素。
结论和进一步阅读
对特征相关性的控制可能是至关重要的,尤其是当您根据不适合您的应用的数据来训练模型时。
原则上,非因果关联问题可以通过选择一个符合I . I . d .的数据集来训练模型来解决,但正如您所理解的,这对于大多数用例来说是不可能的。
有一些非常聪明的人专门研究这些被低估的问题。作为参考,查看崔鹏教授的作品。
数据科学家实际上(应该)做的是建立一个相当好的训练数据集,也使用数据扩充,以便获得足够的数据方差,并最终缓解这些问题。而且,非常重要的是,在部署到生产环境中之后,要监控模型做出的预测。
最大化互信息的特征,它们看起来怎么样?
我们可以通过最大化交互信息来创建潜在特征,但是它们看起来会是什么样的呢?
Image from pixabay
我要感谢Fran ois Fleuret博士、Devon Hjelm博士、yo shua beng io博士提供了令人惊叹的论文和参考资料。最后,我要感谢我的导师布鲁斯博士的鼓励、耐心和有益的讨论。
简介
由于最近的发展,如 MINE 和 DeepInfoMax ,我们不仅能够估计两个高维随机变量的互信息,而且能够创建潜在特征,使输入数据的互信息最大化。
就我个人而言,我认为创造有意义的潜在变量的想法与本吉奥博士的演讲有些关联。简而言之,更好的数据表示(也称为抽象表示)对机器学习模型有益。这也与我们想要最小化/最大化的目标函数不在像素空间中,而是在信息空间中的想法有关。
在这篇文章中,我将把重点放在可视化潜在变量上,这是通过最大化交互信息而产生的。而不是选择可用于任何下游任务的最佳“最佳”表示。
方法
蓝色球体→ 来自 STL 数据集的输入图像(96*96) 蓝色矩形→ 编码器网络 绿色矩形→ 局部信息最大化器 红色矩形→ 全局信息最大化器 黄色矩形→ 先验分布作为正则化
请注意,输入图像已经转换为灰度,因此没有任何颜色通道。此外,我们可以注意到,我们有三个网络作为目标函数,但是,它们都不是在像素空间,而是在信息空间。(详情请阅读论文 DeepinfoMax )。
此外,请注意,所有的目标函数网络都采用两个变量来最大化它们之间的互信息。在我们所有的例子中,我们给这些网络提供了原始图像(如果需要,可以调整大小)和编码的潜在变量。
实验设置
情况 A)潜在变量具有较小的维数
这种情况下,编码器仅由卷积层组成,没有任何填充。因此,在每次卷积操作之后,图像的空间维度将减小。
维数:(96,96)→(94,94)→(92,92)→(90,90)→(88,88)
情况 B)潜在变量具有更大维度
这是编码器由转置卷积层组成的情况。因此,在每一层之后,图像的空间维度将增加。
维度:(96,96)→(98,98)→(100,100)→(102,102)→(104,104)
情况 C)潜在变量具有相同的维度
在这种情况下,我们使用零填充执行典型的卷积运算,因此空间维度不会改变。
维数:(96,96)→(96,96)→(96,96)→(96,96)→(96,96)
情况 D)潜在变量具有相同的维数(反向自动编码器)
在这种情况下,我们首先通过转置卷积来增加空间维度,但是在没有任何填充的情况下应用卷积来立即减小空间维度。(因此反向自动编码器)。
维数:(96,96)→(98,98)→(100,100)→(98,98)→(96,96)
对于上述所有方法,我们将通过创建两幅图像的直方图来测量原始图像和潜在变量之间的互信息,更多细节在此或在此。此外,所有超参数保持不变,例如学习速率、迭代次数和批量大小。
结果
当我们比较 50 次迭代的损失时,我们可以清楚地看到,当我们保持空间维度与输入数据相同时,互信息最大化。
让我们按照情况 a、b、c 和 d 的顺序,比较每种方法创建的不同特征图。
Left Case a Right Case b
Left Case c Right Case d
当我们考虑原始图像和 32 个特征图之间的平均互信息时,我们可以看到互信息对于情况 c 是最高的。
让我们比较另一幅图像,这次是一匹马的图像。
Left Case a Right Case b
Left Case c Right Case d
对于马的图像也获得了类似的结果。
最后,当我们比较 STL 数据集中所有 5000 个图像的最大互信息时,我们可以看到,相对于输入数据保持维度相同具有最高频率的生成具有高互信息的潜在变量。
结论/交互代码
要访问案例 a 的代码,请点击此处。
要访问案例 b 的代码,请点击这里。
要获取案例 c 的代码,请点击此处。
要访问案例 d 的代码,请点击此处。
要访问用于创建可视化效果的代码,请点击此处。
请注意,我已经修改了来自 DuaneNielsen 的原始实现。
遗言
为什么这和我有关系?我认为这种创造潜在变量的形式可能是克服过度拟合的一个好主意。诚然,我们可以使用生成模型来创建新的数据点,这些数据点可以用作数据扩充,但它们也有自己的一系列问题,如模式崩溃。拥有多样化的数据扩充方法对每个人都有好处。
最后,所有的参考文献都被链接到这里。
二月版:数据可视化
8 篇关于可视化数据的最佳文章
数据可视化是任何数据科学过程中必不可少的一步。这是数据科学家和最终用户之间的最后一座桥梁。它交流、验证、对抗和教育。如果做得正确,它会向更广泛的受众展示来自数据科学项目的见解。
伟大的数据可视化不仅仅是用数字描绘一幅美丽的图画。事实上,这通常只是其中的一小部分。我们还需要考虑其他因素,如观看视觉效果的受众类型、数据素养水平、交互性需求以及多个图表讲述的整体故事。
这 8 篇文章组成了我们的首选帖子,这些帖子提供了数据可视化的有用工具,对实践方向的新见解,以及如何有效使用图表讲述故事的有趣示例。
本杰明·库利,TDS 编辑助理。
用 Datashader 进行大规模可视化和制图
由芬乔 — 6 敏念
如果你曾经试图用 Matplotlib 或 Seaborn 创建一个超过 100,000 点的群体图或关系图,你会对在加载图时摆弄拇指的场景并不陌生。幸运的是,Datashader 是以有意义的方式快速表示大型数据集的绝佳选择。
第三波数据可视化
以利亚·米克斯(Elijah Meeks)——12 分钟阅读
首先是如何可视化数据的清晰性。然后是指导最佳实践的新系统。现在,我们正在进入数据可视化的第三次浪潮:融合。Elijah Meeks 解释了为什么从业者需要将他们的重点从单个图表转移到那些图表出现的产品的构建、评估和交付上。
Airbnb 租房房源数据集挖掘
萨朗·古普塔 — 11 分钟阅读
纽约市一直是 Airbnb 最热门的市场之一,截至 2018 年 11 月,已有超过 52,000 个房源。从 Airbnb 内部对 Airbnb 数据集进行的探索性分析通过静态和交互式可视化调查了纽约市的租赁情况。
Python 中 5 个快速简单的数据可视化代码
由乔治·赛义夫 — 7 分钟阅读
Matplotlib 是一个流行的 Python 库,可以用来非常容易地创建数据可视化。然而,每次做新项目时,设置数据、参数、图形和绘图可能会变得相当混乱和乏味。这篇博文着眼于 5 种数据可视化,以及如何用 Python 的 Matplotlib 为它们编写一些快速简单的可重用函数。
使用交互式地图和动画可视化伦敦的自行车移动性
通过 Eden Au — 9 分钟读取
报告显示,77%的伦敦人同意骑自行车是短途旅行最快的方式。让我们看看如何使用图形、地图和动画来可视化自行车共享系统。
Python 中数据可视化的下一个层次
到时,将 Koehrsen — 8 分钟读取
沉没成本谬误是人类遭受的许多有害认知偏见之一。它指的是我们倾向于继续将时间和资源投入到一个失败的事业中,因为我们已经在追求中花费了太多的时间。
对 NBA 原始投篮日志数据的洞察和对热手现象的探究
由艾蒙汗 — 14 分钟读完
数据科学和篮球比赛每年都变得越来越交织在一起。这篇文章通过可视化 NBA 投篮数据来探索“热手”现象的流行。
117 天我的火绒简介数据
由布雷登杰拉德 — 5 分钟阅读
数据往往是非常私人的,就像这个对 Tinder 四个月活动的可视化探索。布雷登·杰拉德深入探讨了他的喜欢、超级喜欢和信息可能会也可能不会导致真正的约会。
我们也感谢最近加入我们的所有伟大的新作家,安德鲁·克鲁格,凯利·鲁希德,伊夫泰彻·马蒙,伦纳德·梅尔伍德,艾米·沃格尔,史蒂夫·德里斯科尔,普雷斯顿·林,里卡多·奥坎波,萨曼莎·班西尔,勒内·布雷默 姜黎黎,克里斯托弗·道蒂,海伦娜·T·施,乔尔·奎萨达,阿尤什·潘特,保罗·皮纳德,罗曼·莫泽,伊格纳西奥·哈戈皮安,奇拉格·查达等等。 我们邀请你看看他们的简介,看看他们的工作。
根据推特,联邦选举…投票给谁
介绍
澳大利亚 2019 年联邦选举即将到来(5 月 18 日),像往常一样,我不知道该投票给谁。这不是真的,通常,我是俗称的“驴选民”——不投票的人。你知道,在民主的澳大利亚,投票是强制性的。来自澳大利亚选举委员会:
根据 1918 年《联邦选举法》第 245 条,没有有效和充分的理由不参加联邦选举投票是犯罪行为。你需要支付 20 美元的罚款。
因此,我行使我的民主权利驴投票。
我并不是不关心我们伟大而幸运的国家的状况(我是真心实意地这么说),而是我们面临的选择本质上是一样的,只有政策上最微小的差异。我们很幸运,因为我们的投票不是自由或压迫的投票,所以这可能是我无知行为的驱动力?
在今年的投票中,自由党的斯科特·莫里森(代表非澳大利亚人的蓝色右倾政党)将与工党的比尔·肖恩(红色左倾政党)对决。斯科特·莫里森,简称 ScoMo,在 2018 年 8 月 24 日成功政变反对马尔科姆·特恩布尔后成为自由党领袖。
尽管今年有所不同——没有两大政党之间的明显差异——但今年我想进行一次投票。但要做到这一点,我将使用的信息之一是我更喜欢哪位领导人的推文活动。这不会是我投票的唯一依据(我没有完全疯掉),但这将是一个开始。
我从一张完全空白的白纸开始了这项分析。此外,我甚至不知道我会根据 Twitter 上的什么活动来投票。我只是继续收集 ScoMo 和 Shorten 的推文,并从那里获取。
这些方法
该分析使用统计编程语言 R(版本 3.4.3)创建,并在 RStudio 中完成。
Twitter 数据是在 2019 年 5 月 3 日使用 rtweet 包为两位政党领导人收集的。
分析中使用的包如下所示:
rtweet: for tweets
ROAuth: for twitter authorisation
tidyverse: data munging and visualisations
lubridate: working with dates
scales: plotting axis in a formatted way
zoo: working with yyyy-mm dates
分析
该分析着眼于两位领导人自斯科莫上任以来一直在创建的推文。
我会问一些问题,每个问题的获胜者会得到一分。谁在分析结束时得分多,谁就能获得我对这一决策过程中 Twitter 部分的投票。
然而,这种分析有一个真正的局限性——Twitter 只是一个平台,所以考虑所有的社交媒体平台可能会产生不同的结果。此外,任何一方的选民的人口统计可能或可能不完全适合这个平台。既然这样说,为什么要为小事而烦恼呢?!
谁发的微博多?
自 ScoMo 上任以来,他已经发布或转发了 551 次,而同期 Shorten 发布了 977 次。
与此同时,比尔·肖顿(Bill Shorten)整月都在更频繁地发推特,只有今年 1 月两者之间的差距相当接近。
此外,自 2018 年初以来,ScoMo 仅在 5 月和 6 月连续两个月发了两次超过 Shorten 的推文(以他当时的财务主管身份,毫无疑问,这是当年的预算)。
获胜者:
账单缩短(Shorten 1,ScoMo 0)
谁的推文更受欢迎?
这将是一个分为两部分的问题。第一部分将看谁的推文得到更多的喜爱,而第二部分将看谁得到更多的转发。
谁更受欢迎?
当用收到的“收藏夹”数量来衡量推文的受欢迎程度时,Shorten 用巧克力来衡量,平均有 536 个收藏夹,ScoMo 有 325 个。
ScoMo 获得了两个最高的喜爱计数,下面的推文获得了 15,936 个喜爱:
参议员弗雷泽·安宁(Fraser Anning)指责新西兰一名暴力右翼极端恐怖分子在移民问题上实施的谋杀袭击的言论令人作呕。这些观点在澳大利亚没有立足之地,更不用说澳大利亚议会了。
谁会忘记,参议员安宁可笑的麻木不仁的言论…
谁被转发的次数更多?
Shorten 显然获得了更多的转发(平均转发数为 216 到 ScoMo 的 61)。ScoMo 上面关于参议员安宁的推文也是被转发最多的推文。Shorten 转发最多的推文是关于 ScoMo 学校的削减:
斯科特·莫里森已经锁定了对公立学校的大规模削减。没有人投票支持莫里森削减公立学校的经费,但他还是要削减。请分享,这样每个人都知道刚刚发生了什么。
获胜者:
账单缩短(Shorten 2,ScoMo 0)
谁的微博更长?
我为什么关心这个?嗯,我可能不知道,但也许这是一个代理谁提供了更详细的成分水平…或行话?
ScoMo 显然拥有更长的推文,中值字符长度为 204,而 Shorten 的中值推文长度为 153,并且每条推文使用更多的单词,中值单词数为 33,而 Shorten 为 27。
获胜者:
ScoMo(缩短 2,ScoMo 1)
谁是标签之王?
ScoMo 在超过 20%的推文中包含了一个标签。另一方面,Shorten 在他的推文中只有超过 7%的标签。好老臀部 ScoMo 是新铸造的标签王!
获胜者:
ScoMo(缩短 2,ScoMo 2)
谁使用更多的媒体(照片、视频)?
当涉及到政治家时,媒体的使用是很有趣的…谁不喜欢在摄像机周围笨拙地握手或亲吻几个婴儿的好机会呢?!
与 ScoMo 相比,Shorten 倾向于在更多的推文中包含照片,几乎 50%的 Shorten 推文中包含照片。ScoMo 也不甘落后,他 47%的推文包含照片,但他需要解除他的婴儿亲吻游戏。我把这叫做平局。就像网球一样,两位候选人都需要赢两场或更多场比赛(是的,我意识到这不是网球,我是根据他们的推文选择政党的,所以这里没有规则)。
获胜者:
Draw(缩短 2,ScoMo 2)
推文内容分析
Shorten 在推文中最常用的术语是“劳动”,这个词出现在他所有推文中的 30%以上。相比之下,ScoMo 自己的政党并没有出现在他最常用的 30 个术语中。
Shorten 的推文似乎在谈论皇家委员会(我认为目前的委员会是银行贷款,因为银行也出现了),同时也提到了令人揪心的项目——削减、学校、家庭和医疗保险。他似乎也经常提到他的对手。
ScoMo 似乎一直将他的推文内容集中在经济上,诸如经济、就业、企业、预算等术语和一些标签( strongeraus 和 buildingyoureconomy )出现得相当频繁。
测量他们推特行为的情感得分将会很有趣。
获胜者:
ScoMo(缩短 2,ScoMo 3)
每位领导人多久提到一次他们的对手
需要做一些假设来确定每个候选人是否在他们的推文中提到这个职位。如果 ScoMo 的推文中出现了“Bill”、“Shorten”、“Labor”或“Opposition”这些词,那么我们就说他提到了他的竞争对手。另一方面,如果 Shorten 的推文中包含“斯科特”、“莫里斯森”、“自由派”、“自由派”中的任何一个,那么我们说他在推文中提到了他的竞争对手。
Shorten 的推文中提到了很多他的对手,几乎五分之一的推文(19%)提到了他的对手,而 ScoMo 只在超过 7%的推文中提到了 Shorten。我认为这提出了一个有趣的问题;我们希望我们的领导专注于手头的工作,还是其他人正在做的事情?
领导在提到对手的时候都在说什么?
好吧,更让我好奇的是,两位领导人在他们的推文中提到或没有提到他们的对手时最常用的词如下。我这个垃圾真人秀爱好者真的希望这是一场大型的口水战…
嗯,看来我的愿望不会实现了…
Shorten 谈的是公平、时间、交货和家庭而不是 ScoMo。他在的时候,似乎深受银行和皇家委员会、削减到罚款的税率和学校的影响。
另一方面,ScoMo 在谈到他的政府的实力、工作岗位、经济、支持以及有计划时没有提到缩短,而他在提到缩短时最常用的词是关于税收*、边境、拘留和退休人员正如我们之前看到的,缩短或分娩在 ScoMo 的推文中并不突出。*
获胜者:
ScoMo(缩短 2,ScoMo 4)
谁的微博更积极?
使用由芬恩·厄普·尼尔森创建的一个叫做 T42·阿芬恩词典的情感分析常用词典,我们可以测量每个候选人推文中包含的词汇的积极度。
使用这种方法,很明显 ScoMo 一直在使用 Twitter 推送比 Shorten 更积极的信息,与 Shorten 的 346 相比,整体积极指数为 578。
随着时间的推移,当我们看到这一点时,很明显,Shorten 已经开始以越来越消极的态度发布推文。我想知道他的信息策略是不是利用恐惧和消极来让选民投票给工党…
获胜者:
ScoMo(缩短 2,ScoMo 5)
结论
在提出的八个问题中,从我的角度来看,ScoMo 赢了五个,缩短了两个。两位候选人抽出一个问题。虽然缩短推文的频率更高,使用图像的频率也更高,但 ScoMo 推文的内容让他在我 2019 年的联邦推特选举中脱颖而出。
有什么想法可以随意评论。
想查看更多数据分析项目?头过来不怪数据博客https://www.dontblamethedata.com
使用 PySyft 的联邦学习
具有设备上能力的训练机器学习模型的新时代。在本教程中,我将使用 PyTorch 和 PySyft 来训练一个使用联邦方法的深度学习神经网络。
联邦学习简介
什么是联合学习?
联合学习是一种分布式机器学习方法,它能够在大型分散数据语料库上进行模型训练。联合学习使手机能够协作学习共享的预测模型,同时将所有训练数据保留在设备上,将机器学习的能力与将数据存储在云中的需求分离开来。这超越了在移动设备上进行预测的本地模型的使用(如移动视觉 API 和设备上智能回复),还将模型训练带到了设备上。
目标是机器学习设置,其中目标是利用分布在大量客户端上的训练数据来训练高质量的集中式模型,每个客户端都具有不可靠且相对较慢的网络连接。
这个新领域由一系列技术组成,这些技术允许 ML 工程师在不直接访问用于训练的数据的情况下训练模型,并避免他们通过使用密码术获得关于数据的任何信息。
该框架依赖于三种主要技术:
- 联合学习
- 差异隐私
- 安全多方计算
在本文中,我将介绍联合学习及其在预测波士顿房价中的应用。
谷歌如何使用联邦学习?
How google uses Federated Learning to make more accurate keyboard suggestions
应用程序是如何工作的?
随着 PySyft、Tensorflow Federated 等很多著名库的兴起。对于普通开发者、研究人员和机器学习爱好者来说,创建一个去中心化的机器学习训练模型变得更加容易。在这个项目中,我使用 PySyft——一个用于安全、私人深度学习的 Python 库——来训练一个数据集,其目的是预测波士顿市所列房产的房价。PySyft 使用 PyTorch 中的多方计算(MPC)将私有数据从模型训练中分离出来。
在训练深度学习预测模型时,数据会与 Alice 和 Bob 一起安全地保存在本地。对于一个私人训练,我使用了一种联合的方法,其中 ML 模型是用 Alice 和 Bob 两方拥有的移动设备的设备上能力在本地训练的。随着移动设备的计算机性能的提高,以更高的效率训练 ML 模型变得更加容易。
联合学习方法中涉及的步骤
- 移动设备下载全球 ML 模型
- 当用户使用与 ML 模型关联的应用程序时,数据正在生成
- 随着用户开始更多地与应用程序进行交互,用户可以根据其使用情况获得更好的预测
- 一旦模型准备好与服务器进行预定的同步。利用设备上的能力进行训练的个性化模型被发送到服务器
- 收集来自所有设备的模型,并且使用联合平均函数来生成比先前模型改进得多的模型版本
- 一旦被训练,改进的版本被发送到所有设备,在那里用户获得基于全球所有设备的使用的体验
安装 PySyft
PySyft 是一个用于安全、私人深度学习的 Python 库。PySyft 使用 PyTorch 中的联邦学习、差分隐私和多方计算(MPC) ,将私有数据从模型训练中分离出来。
为了安装 PySyft,建议您先设置一个 conda 环境
conda create -n pysyft python=3
conda activate pysyft
conda install jupyter notebook
然后你需要安装软件包
pip install syft
使用联邦学习方法开发神经网络的分步指南
1)导入库
以下 Python 库用于开发项目。
- Numpy — NumPy 是 Python 编程语言的库,增加了对大型多维数组和矩阵的支持,以及对这些数组进行操作的大量高级数学函数。
- PyTorch — PyTorch 是基于 Torch 库的开源机器学习库,用于计算机视觉、自然语言处理等应用。它主要是由脸书人工智能研究小组开发的。它是免费的开源软件。
- PySyft — PySyft 是一个用于安全、私人深度学习的 Python 库。PySyft 使用 PyTorch 中的联邦学习、差分隐私和多方计算(MPC)将私有数据从模型训练中分离出来。
- Pickle—Pickle 模块实现了二进制协议,用于序列化和反序列化 Python 对象结构。
Importing libraries in the Jupyter Notebook
2)初始化训练参数
我们已经对神经网络进行了 100 多次的训练,以获得良好的结果。通过创建总共 8 个批次的记录,我们能够获得良好的结果。的学习率设置为 0.001,以使用随机梯度下降作为网络的优化器。到目前为止,PySyft 只支持 SGD 优化器用于反向传播算法来计算误差和更新网络参数。
梯度下降是一种寻找函数最小值的一阶迭代优化算法。为了使用梯度下降找到函数的局部最小值,人们采取与当前点的函数的梯度(或近似梯度)的负值成比例的步骤。
Initiating the learning parameter in the Jupyter Notebook
3)数据集预处理
下一步包括将数据集读入 Jupyter 笔记本,并在用数据训练神经网络之前对其进行预处理。预处理数据有助于我们更好地了解数据集,并帮助我们选择有助于预测输入结果的最佳特征。
Data Preprocessing for the Boston Housing dataset
在这个项目中,我们使用了最常见的波士顿住房数据集来训练神经网络。我们根据不同的定价特征来预测各种房产的价格。下面列出了其中的一些。你可以在这里找到数据集。
数据库中的每条记录都描述了波士顿的一个郊区或城镇。数据取自 1970 年波士顿标准大都市统计区(SMSA)。
属性定义如下
- CRIM: 城镇人均犯罪率
- ZN: 面积超过 25,000 平方英尺的住宅用地比例
- 印度河:每个城镇的非零售商业用地比例
- CHAS: 查尔斯河虚拟变量(= 1,如果区域边界为河流;0 否则)
- 氮氧化物:氮氧化物浓度(百万分之一)
- RM: 每个住所的平均房间数
- 楼龄:1940 年前建成的自住单位比例
- DIS: 到五个波士顿就业中心的加权距离
- RAD: 放射状公路可达性指标
- 税:每万美元的全价值财产税
- PTRATIO: 按城镇分列的师生比率
- b:1000(Bk 0.63)2 其中 Bk 是按城镇划分的黑人比例
- LSTAT: %
- MEDV: 以千美元为单位的自有住房中值我们可以看到,输入属性混合了多种单位。
4)用 PyTorch 创建神经网络
我们现在必须使用 PyTorch 为模型定义神经网络架构。深度学习网络由 2 个不同的隐藏层组成,并涉及网络中所有层的 Relu 激活函数的使用。输入层由 13 个不同的感知器组成,对应于训练数据集的每个输入特征。
5)将数据与远程移动设备连接
鲍勃和爱丽丝是参与整个循环的两个人。出于模拟目的,我们向所有使用全局 ML 模型与应用程序交互的网络客户端发送批量数据集。
我们可以看到,使用 PySyft 库及其 PyTorch 扩展,我们可以使用张量指针执行操作,就像我们可以使用 PyTorch API 一样(但仍有一些限制需要解决)。
现在,我们联系名为 Alice 和 Bob 的工作人员,他们使用各方提供的数据来训练神经网络。
6)训练神经网络
多亏了 PySyft,我们能够在不访问远程和私有数据的情况下训练一个模型:对于每一批,我们将模型发送给当前的远程工作者,并在将它发送给下一批的工作者之前,将它返回到本地机器。
然而,这种方法有一个限制:通过取回模型,我们仍然可以访问一些私人信息。假设 Bob 的机器上只有一条数据记录。当我们取回模型时,我们可以用更新的权重来检查 Bob trained 用来重新训练模型的数据。
为了解决这个问题,有两种解决方案:差分隐私和安全多方计算(SMPC)。差分隐私将用于确保该模型不会提供对某些隐私信息的访问。SMPC 是一种加密计算,作为回报,它允许您私下发送模型,这样拥有数据的远程工作人员就看不到您使用的重量。
您可以使用下面的 Jupyter 笔记本来检查整个项目。我还留下了联邦学习项目的链接,可以在下面我的 GitHub 知识库中找到。
资源
如果你有兴趣学习更多关于安全和私人人工智能以及如何使用 PySyft 的知识,你也可以在 Udacity 上查看这个免费课程 。这是一门很棒的初学者课程,由 Andrew Trask 教授,他是 OpenMined Initiative 的创始人。
在 GitHub 上查看项目
关于我
我是印度计算机科学与工程专业的大四学生,过去 5 年来一直从事编码工作。在从事了几个机器学习和 iOS 开发项目之后,我正在学习联邦学习的新技术,因为未来十年你如何在移动设备上训练深度学习模型取决于联邦协议。你可以在我的网站上了解我更多。更多项目请查看我的 GitHub 档案。