作者|Paul Hiemstra
编译|VK
起源|Towards Datas Science

你也能够在GitHub上浏览这篇文章。这个GitHub存储库蕴含你本人运行剖析所需的所有:https://github.com/PaulHiemst...

介绍

对于许多数据科学家来说,最根本的模型是多元线性回归。在许多剖析中,它是第一个被调用的,并作为更简单模型的基准。它的一个长处是容易解释失去的系数,这是神经网络特地难以解决的问题。

然而,线性回归并非没有挑战。在本文中,咱们关注一个非凡的挑战:解决大量的特色。大数据集的具体问题是如何为模型抉择相干的特色,如何克服过拟合以及如何解决相干特色。

正则化是一种十分无效的技术,有助于解决上述问题。正则化是通过用一个限度系数大小的项来扩大规范最小二乘指标或损失函数来实现的。本文的次要目标是让你相熟正则化及其提供的劣势。

在本文中,你将理解以下主题:

  • 什么样的正则化更具体,为什么值得应用
  • 有哪些不同类型的正则化,以及术语L1和L2正则化意味着什么
  • 如何应用正则化
  • 如何应用tsfresh生成正则化回归的特色
  • 如何解释和可视化正则化回归系数
  • 如何利用穿插验证优化正则化强度
  • 如何可视化穿插验证的后果

咱们将从更实践上介绍正则化开始本文,并以一个理论例子完结。

为什么应用正则化,什么是正则化

下图显示了一个绿色和蓝色的函数,与红色察看值相匹配。这两个函数都完满地合乎观测值,咱们该以何种形式抉择这2个函数。

咱们的问题是不确定的,这导致咱们任意不能抉择这两个函数中的任何一个。在回归剖析中,有两个因素减低了性能:多重共线性(相干特色)和特色的数量。

通常能够手工以失去大量特色。然而,在更多的数据驱动办法中,咱们通常应用许多特色,这导致特色之间有很多相干,而咱们当时并不知道哪些特色会很好地工作。为了克服不确定性,咱们须要在问题中增加信息。在咱们的问题中增加信息的数学术语是正则化。

回归中执行正则化的一种十分常见的办法是用附加项扩大损失函数。Tibshirani(1997)提出用一种称为Lasso的办法将系数的总大小增加到损失函数中。示意系数总大小的数学方法是应用所谓的范数

其中p值决定了咱们应用什么样的正则化。p值为1称为L1范数,值为2称为L2范数等。既然咱们有了范数的数学表达式,咱们就能够扩大咱们通常在回归中应用的最小二乘损失函数:

留神,这里咱们应用L2范数,咱们也用L2范数示意了损失函数的平方差局部。另外,lambda是正则化强度。正则化强度决定了系数大小与损失函数平方差局部的关系。留神,范数项次要长处是缩小了模型中的方差。

蕴含L2范数的回归称为岭回归。岭回归缩小了预测中的方差,使其更稳固,更不容易过拟合。此外,方差的缩小还能够反抗多重共线性带来的方差。

当咱们在损失函数中退出L1范数时,这称为Lasso。Lasso在减小系数大小方面比岭回归更进一步,会降到零。这实际上意味着变量从模型中退出,因而lasso是在执行特征选择。这在解决高度相干的特色(多重共线性)时有很大的影响。Lasso偏向于抉择一个相干变量,而岭回归均衡所有特色。Lasso的特征选择在你有很多输出特色时特地有用,而你当时并不知道哪些特色会对模型无利。

如果要混合Lasso回归和岭回归,能够同时向损失函数增加L1和L2范数。这就是所谓的Elastic正则化。在实践局部完结后,让咱们进入正则化的理论利用。

正则化的示例应用

用例

人类很长于辨认声音。仅凭音频,咱们就可能辨别汽车、声音和枪支等事物。如果有人特地有教训,他们甚至能够通知你什么样声音属于哪种汽车。在这种状况下,咱们将建设一个正则化回归模型。

数据集

咱们的数据是75个鼓样品,每种类型的鼓有25个:底鼓、陷阱鼓和汤姆鼓。每个鼓样本存储在wav文件中,例如:

sample_rate, bass = wavfile.read('./sounds/bass1.wav')bass_pd = pd.DataFrame(bass, columns=['left', 'right']).assign(time_id = range(len(bass)))bass_pd.head()

# 留神,本文中的所有图形都应用了plotnine(    ggplot(bass_pd.melt(id_vars = ['time_id'], value_name='amplitude', var_name='stereo'))       + geom_line(aes(x = 'time_id',                       y = 'amplitude'))      + facet_wrap('stereo')       + theme(figure_size=(4,2)))

wav文件是立体声的,蕴含两个声道:左声道和右声道。该文件蕴含随工夫变动的波形,在x轴上随工夫变动,在y轴上蕴含振幅。振幅基本上列出了扬声器圆锥应该如何振动。

以下代码结构了一个蕴含所有75个鼓样本的数据帧:

import globwav_files = glob.glob('sounds/kick/*.wav') + glob.glob('sounds/snare/*.wav') + glob.glob('sounds/tom/*.wav')all_audio = pd.concat([audio_to_dataframe(path) for path in wav_files])all_labels = pd.Series(np.repeat(['kick', 'snare', 'tom'], 25),                       index = wav_files)all_audio.head()

附加函数audio_to_dataframe能够在github仓库的helper_functions.py找到。

应用tsfresh生成特色

为了拟合一个监督模型,sklearn须要两个数据集:一个带有咱们的特色的样本特色x矩阵(或数据帧)和一个带有标签的样本向量。

因为咱们曾经有了标签,所以咱们把精力集中在特色矩阵上。因为咱们心愿咱们的模型对每个声音文件进行预测,所以特色矩阵中的每一行都应该蕴含一个声音文件的所有特色。

接下来的挑战是提出咱们想要应用的特色。例如,高音鼓的声音中可能有更多的高音频率。因而,咱们能够在所有样本上运行FFT并将高音频率拆散成一个特色。

采纳这种手动特色工程办法可能会十分消耗人力,并且很有可能排除重要特色。tsfresh(docs)是一个Python包,它极大地放慢了这个过程。该包基于timeseries数据生成数百个潜在的特色,还包含预选相干特色的办法。有数百个特色强调了在这种状况下应用某种正则化的重要性。

为了相熟tsfresh,咱们首先应用MinimalFCParameters设置生成大量特色:

from tsfresh import extract_relevant_featuresfrom tsfresh.feature_extraction import MinimalFCParameterssettings = MinimalFCParameters()audio_tsfresh_minimal = extract_relevant_features(all_audio, all_labels,                                           column_id='file_id', column_sort='time_id',                                           default_fc_parameters=settings)                                          print(audio_tsfresh_minimal.shape)audio_tsfresh_minimal.head()

这就给咱们留下了11个特色。咱们应用extract_related_features函数来容许tsfresh依据标签和生成的潜在特色预先选择有意义的特色。在这种最小的状况下,tsfresh查看由file_id列标识的每个声音文件,并生成诸如振幅的标准偏差、均匀振幅等特色。

然而tsfresh的弱小之处在于咱们产生了更多的特色。在这里,咱们应用相干默认设置来节俭一些工夫,而不是应用残缺的设置。留神,我间接读取了dataframe的pickle数据,它是应用github仓库中用generate_drum_model.py脚本生成的。我这样做是为了节省时间,因为在我的12线程机器上计算大概须要10分钟。

from tsfresh.feature_extraction import EfficientFCParameterssettings = EfficientFCParameters()audio_tsfresh = pd.read_pickle('pkl/drum_tsfresh.pkl')print(audio_tsfresh.shape)audio_tsfresh.head()

这使得特色的数量从11个扩大到327个。这些特色为咱们的正则化回归模型提供了一个非常广阔的学习空间。

正则回归模型的拟合

当初咱们曾经有了一组输出特色和所需的标签,咱们能够持续并拟合咱们的正则化回归模型。咱们应用来自sklearn的逻辑回归模型:

from sklearn.linear_model import LogisticRegressionbase_log_reg = LogisticRegression(penalty='l1',                                   multi_class='ovr',                                  solver='saga',                                  tol=1e-6,                                  max_iter=int(1e4),                                   C=1)

并应用以下设置:

  • 咱们将惩办设置为l1,即咱们应用l1范数的正则化。
  • 咱们将multi_class设置为1 vs rest(ovr)。这意味着咱们的模型由三个子模型组成,每种可能类型的鼓各有一个。当用整体模型进行预测时,咱们只需抉择体现最好的模型。
  • 咱们应用saga求解器来拟合咱们的损失函数。还有更多可用的,但saga可能实现咱们所须要的性能。
  • 当初将C设为1,其中C等于1/正则化强度。请留神,sklearn Lasso实现应用了????,它等于1/2C。我发现????是一个更直观的度量,咱们将在本文的其余部分应用它。
  • tol和max_iter设置为可承受的默认值。

基于这些设置,咱们进行了一些试验。首先,咱们将比拟基于大量和大量tsfresh特色的模型的性能。之后,咱们将重点探讨如何应用穿插验证来拟合正则化强度,并对拟合模型的性能进行更全面的探讨。

最小tsfresh vs 无效tsfresh

咱们的第一个分析测试了这样一个假如:应用更多生成的tsfresh特色能够失去更好的模型。为了测试这一点,咱们应用最小tsfresh和无效tsfresh特色来拟合一个模型。咱们通过模型在测试集上的准确性来判断模型的性能。咱们反复20次,以理解因为在抉择训练和测试集时的随机性而导致的精确度差别:

from sklearn.model_selection import train_test_splitdef get_score(audio_data, labels):    # 用cross_val_score代替?    audio_train, audio_test, label_train, label_test = train_test_split(audio_data, labels, test_size=0.3)    log_reg = base_log_reg.fit(audio_train, label_train)    return log_reg.score(audio_test, label_test)accuracy_minimal = [get_score(audio_tsfresh_minimal, all_labels) for x in range(20)]accuracy_efficient = [get_score(audio_tsfresh, all_labels) for x in range(20)]plot_data = pd.concat([pd.DataFrame({'accuracy': accuracy_minimal, 'tsfresh_data': 'minimal'}),                       pd.DataFrame({'accuracy': accuracy_efficient, 'tsfresh_data': 'efficient'})])(    ggplot(plot_data) + geom_boxplot(aes(x='tsfresh_data', y='accuracy')) +       coord_flip() +       labs(y = 'Accuracy', x = 'TSfresh setting'))

失去的箱线图分明地表明,与基于最小特色的模型相比,无效tsfresh变量显示了更高的均匀精度0.75,而不是0.4。这证实了咱们的假如,咱们将在本文的其余部分应用无效的特色。

通过穿插验证抉择正则化强度

在应用正则化时,咱们必须做出的一个次要抉择是正则化的强度。在这里,咱们应用穿插验证来测试C的一系列潜在值的准确性。

sklearn很不便地蕴含了一个用于逻辑回归剖析的函数:LogisticRegressionCV。它实质上具备与LogisticRegression雷同的接口,然而你能够传递一个潜在的C值列表来进行测试。

无关代码的详细信息,请参阅generate_drum_model.py,咱们将后果从磁盘加载到此处以节省时间:

from sklearn.svm import l1_min_cfrom joblib import dump, loadcs = l1_min_c(audio_tsfresh, all_labels, loss='log') * np.logspace(0, 7, 16)cv_result = load('pkl/drum_logreg_cv.joblib')

注:咱们应用l1_min_c来取得模型蕴含非零系数的最小c值。而后咱们在下面乘上一个0到7之间的16个对数,这样失去16个潜在的C值。我没有一个很好的理由来解释这些数字。转换为,并取log10,咱们失去:

np.log10(1/(2*cs))

这其中蕴含一个很好的正则化强度范畴,咱们将在后果的解释中看到。

穿插验证抉择了以下????值:

np.log10(1/(2*cv_result.C_))

留神咱们有三个值,每个子模型一个(kick-model, tom-model, snare-model)。在这里,咱们看到,6左右的正则化强度被认为是最优的(C=4.5e-07)。

基于CV后果对模型的进一步解释

cv_result对象蕴含更多对于穿插验证的数据,而不是拟合的正则化强度。在这里,咱们首先看看穿插验证模型中的系数,以及它们在一直变动的正则化强度下所遵循的门路。留神,咱们应用helper_functions,py中的plot_coef_paths函数:

plot_coef_paths(cv_result, 'kick', audio_tsfresh) + theme(figure_size=(16,12))

注:咱们在图中看到5条线,因为默认状况下咱们执行5折穿插验证。另外,咱们重点钻研了kick子模型。图中有以下乏味的察看后果:

  • 减少正则化强度会减小系数的大小。这正是正则化应该做的,然而后果反对这一点是很好的。
  • 减少的褶皱线缩小了强度之间的变动。这合乎正则化的指标:缩小模型中的方差。然而,褶皱之间的变动依然十分激烈。
  • 对于前面的系数,总的系数大小会降落。
  • 对于穿插验证的正则化强度(6),相当多的系数从模型中隐没。在tsfresh生成的327个潜在特色中,只有大概10个被选为最终模型。
  • 许多有影响的变量是fft重量。这很直观,因为鼓样本之间的差别集中在特定频率(高音鼓->低频,陷阱鼓->高频)。

这些察看后果描述了这样一幅图景:正则化回归按预期工作,但必定还有改良的余地。在这种状况下,我狐疑每种类型的鼓有25个样本是次要的限度因素。

除了看系数及其变动,咱们还能够看看子模型的总体精度与正则化强度的关系。留神,咱们应用helper_functions.py中的plot_reg_strength_vs_score,你能够在github上找到。

plot_reg_strength_vs_score(cv_result) + theme(figure_size=(10,5))

请留神,准确度笼罩的不是一条线而是一个区域,因为在穿插验证中,咱们对每一次都有一个准确度分数。图中的察看后果:

  • 在拟合的正则化强度(6->0.95)下,kick 模型总体体现最佳。
  • tom模型的性能最差,最小和最大精度都低。
  • 性能峰值介于5–6之间,这与所选值统一。在强度较小的状况下,我狐疑模型中残余的多余变量会产生太多的噪声,而后正则化会去掉太多的相干信息。

论断:正则回归模型的性能

基于穿插验证的准确度得分,我得出结论,咱们在生成鼓声辨认模型方面相当胜利。尤其是底鼓很容易区别于其余两种类型的鼓。正则化回归也为模型减少了很多价值,升高了模型的整体方差。最初,tsfresh展现了从这些基于工夫序列的数据集生成特色的微小后劲。

改良模型的潜在路径有:

  • 应用tsfresh生成更多潜在的输出特色。
  • 应用更多的鼓样本作为模型的输出

原文链接:https://towardsdatascience.co...

欢送关注磐创AI博客站:
http://panchuang.net/

sklearn机器学习中文官网文档:
http://sklearn123.com/

欢送关注磐创博客资源汇总站:
http://docs.panchuang.net/