Python 中的特征选择技术:预测酒店取消
机器学习项目最重要的特征之一(没有双关语)是特征选择。
特征选择允许识别对响应(或因变量)最重要或最有影响的因素。在这个例子中,特征选择技术被用于预测对客户是否选择取消他们的酒店预订最重要的影响因素。
资料来源:pixabay.com
特征选择工具
三种不同的特征选择工具用于分析该数据集:
- **extractreesclassifier:**extractreesclassifier 的目的是使多个随机决策树适合数据,在这方面,它是集成学习的一种形式。特别是,对所有观察值进行随机分割,以确保模型不会过度拟合数据。
- 前进和后退特征选择:这是一种**“基于包装器”**的特征选择方法,其中特征选择基于特定的机器学习算法(在本例中为 RandomForestClassifier)。对于前向步骤选择,每个单独的特征被一次一个地添加到模型中,并且具有最高 ROC_AUC 分数的特征被选择为最佳特征。当进行后向特征选择时,该过程反向进行,由此每次从模型中丢弃一个特征,即从模型中丢弃具有最低 ROC_AUC 分数的特征。
背景和数据处理
使用这些算法的目的是确定最有助于预测客户是否会取消酒店预订的功能。这是因变量,其中(1 =取消,0 =继续预订)。
用于分析的特征如下。
间隔
leadtime = train_df['LeadTime']
arrivaldateyear = train_df['ArrivalDateYear']
arrivaldateweekno = train_df['ArrivalDateWeekNumber']
arrivaldatedayofmonth = train_df['ArrivalDateDayOfMonth']
staysweekendnights = train_df['StaysInWeekendNights']
staysweeknights = train_df['StaysInWeekNights']
adults = train_df['Adults']
children = train_df['Children']
babies = train_df['Babies']
isrepeatedguest = train_df['IsRepeatedGuest']
previouscancellations = train_df['PreviousCancellations']
previousbookingsnotcanceled = train_df['PreviousBookingsNotCanceled']
bookingchanges = train_df['BookingChanges']
agent = train_df['Agent']
company = train_df['Company']
dayswaitinglist = train_df['DaysInWaitingList']
adr = train_df['ADR']
rcps = train_df['RequiredCarParkingSpaces']
totalsqr = train_df['TotalOfSpecialRequests']
绝对的
arrivaldatemonth = train_df.ArrivalDateMonth.astype("category").cat.codes
arrivaldatemonthcat=pd.Series(arrivaldatemonth)
mealcat=train_df.Meal.astype("category").cat.codes
mealcat=pd.Series(mealcat)
countrycat=train_df.Country.astype("category").cat.codes
countrycat=pd.Series(countrycat)
marketsegmentcat=train_df.MarketSegment.astype("category").cat.codes
marketsegmentcat=pd.Series(marketsegmentcat)
distributionchannelcat=train_df.DistributionChannel.astype("category").cat.codes
distributionchannelcat=pd.Series(distributionchannelcat)
reservedroomtypecat=train_df.ReservedRoomType.astype("category").cat.codes
reservedroomtypecat=pd.Series(reservedroomtypecat)
assignedroomtypecat=train_df.AssignedRoomType.astype("category").cat.codes
assignedroomtypecat=pd.Series(assignedroomtypecat)
deposittypecat=train_df.DepositType.astype("category").cat.codes
deposittypecat=pd.Series(deposittypecat)
customertypecat=train_df.CustomerType.astype("category").cat.codes
customertypecat=pd.Series(customertypecat)
reservationstatuscat=train_df.ReservationStatus.astype("category").cat.codes
reservationstatuscat=pd.Series(reservationstatuscat)
关于这些特征,某些特征如提前期是区间——换句话说,它们可以取很大范围的值,不一定受特定范围的限制。
但是,某些变量,如 customertype 是分类变量。在这方面,类别代码用于将这些变量识别为分类变量,并确保它们在最终分析中不会被错误地排序。例如,考虑以下变量:1 =苹果,2 =香蕉,3 =橙子。这个变量是分类的,数字没有固有的等级,因此如此指定是很重要的。
在这方面,以 customertype 为例,变量首先被转换为 categorical,然后存储为 pandas 系列:
customertypecat=train_df.CustomerType.astype("category").cat.codes
customertypecat=pd.Series(customertypecat)
被取消的变量是响应变量:
IsCanceled = train_df['IsCanceled']
y = IsCanceled
将要素加载到 Python 中后,它们将存储为 numpy 堆栈(或数组序列):
x = np.column_stack((leadtime,arrivaldateyear,arrivaldatemonthcat,arrivaldateweekno,arrivaldatedayofmonth,staysweekendnights,staysweeknights,adults,children,babies,mealcat,countrycat,marketsegmentcat,distributionchannelcat,isrepeatedguest,previouscancellations,previousbookingsnotcanceled,reservedroomtypecat,assignedroomtypecat,bookingchanges,deposittypecat,dayswaitinglist,customertypecat,adr,rcps,totalsqr,reservationstatuscat))
x = sm.add_constant(x, prepend=True)
既然已经定义了 x 和 y 变量,那么使用特征选择方法来识别哪些变量对酒店取消有最大的影响。
具体来说,一旦相关特征被识别,SVM(支持向量机)模型被用于分类。从上述三种技术中识别出的特征被分别输入到模型中,以确定哪种特征选择工具在识别重要特征方面做得最好——这被认为是由较高的 AUC 分数反映的。
树外分级机
将生成 ExtraTreesClassifier:
from sklearn.ensemble import ExtraTreesClassifier
model = ExtraTreesClassifier()
model.fit(x, y)
print(model.feature_importances_)
结果如下:
[0.00000000e+00 2.41288705e-02 6.54290762e-03 3.56552004e-03
4.69576062e-03 3.47427522e-03 4.05667428e-03 4.86925873e-03
2.53797514e-03 2.90658184e-03 3.51521069e-04 2.81228056e-03
3.98090524e-02 1.76395497e-02 5.72618836e-03 4.67231162e-03
1.06281516e-02 1.18152913e-03 4.53164843e-03 7.05720850e-03
4.01953363e-03 4.33681743e-02 5.47423587e-04 1.24294822e-02
7.31621484e-03 2.21889104e-02 7.26745746e-03 7.51675538e-01]
让我们将它归类到一个数据框架中,并看看主要特性:
ext=pd.DataFrame(model.feature_importances_,columns=["extratrees"])
ext
ext.sort_values(['extratrees'], ascending=True)
最常见的特征是特征 1、12、13、21、23、25(交付周期、原产国、市场细分、存款类型、客户类型和所需停车位)。请注意,功能 27 (预订状态)在这种情况下无效,因为这实际上代表了与响应变量相同的东西——即客户是否取消或坚持预订。在这种情况下,在分析中包含该特征是错误的。
向前和向后步进特征选择
如前所述,这种特征选择方法基于 RandomForestClassifier。就逐步向前的特征选择而言,当每个特征被添加到模型中时,对其 ROC_AUC 分数进行评估,即具有最高分数的特征被添加到模型中。对于后退特征选择,过程是相反的-基于具有最低 ROC_AUC 分数的特征从模型中删除。使用此要素选择工具从数据集中选择前六个要素。
正向特征选择实现如下:
from sklearn.ensemble import RandomForestRegressor, RandomForestClassifier
from sklearn.metrics import roc_auc_score
from mlxtend.feature_selection import SequentialFeatureSelectorforward_feature_selector = SequentialFeatureSelector(RandomForestClassifier(n_jobs=-1),
k_features=6,
forward=True,
verbose=2,
scoring='roc_auc',
cv=4)
fselector = forward_feature_selector.fit(x, y)
下面是生成的输出:
[Parallel(n_jobs=1)]: Using backend SequentialBackend with 1 concurrent workers.
[Parallel(n_jobs=1)]: Done 1 out of 1 | elapsed: 2.0s remaining: 0.0s
[Parallel(n_jobs=1)]: Done 28 out of 28 | elapsed: 40.8s finished[2020-03-01 19:01:14] Features: 1/6 -- score: 1.0[Parallel(n_jobs=1)]: Using backend SequentialBackend with 1 concurrent workers.
[Parallel(n_jobs=1)]: Done 1 out of 1 | elapsed: 1.3s remaining: 0.0s
[Parallel(n_jobs=1)]: Done 27 out of 27 | elapsed: 37.4s finished[2020-03-01 19:01:52] Features: 2/6 -- score: 1.0[Parallel(n_jobs=1)]: Using backend SequentialBackend with 1 concurrent workers.
[Parallel(n_jobs=1)]: Done 1 out of 1 | elapsed: 1.5s remaining: 0.0s
[Parallel(n_jobs=1)]: Done 26 out of 26 | elapsed: 37.3s finished...[2020-03-01 19:03:49] Features: 5/6 -- score: 1.0[Parallel(n_jobs=1)]: Using backend SequentialBackend with 1 concurrent workers.
[Parallel(n_jobs=1)]: Done 1 out of 1 | elapsed: 1.9s remaining: 0.0s
[Parallel(n_jobs=1)]: Done 23 out of 23 | elapsed: 40.7s finished[2020-03-01 19:04:30] Features: 6/6 -- score: 1.0
我们可以按如下方式标识功能名称(在本例中是数字,因为它们存储在数组中):
>>> fselector.k_feature_names_
('0', '1', '2', '3', '4', '27')
后向要素选择方法计算量更大,因为会考虑数据集中的所有要素。
我们通过简单地设置 forward=False 来实现。
from sklearn.ensemble import RandomForestRegressor, RandomForestClassifier
from sklearn.metrics import roc_auc_scorebackward_feature_selector = SequentialFeatureSelector(RandomForestClassifier(n_jobs=-1),
k_features=6,
forward=False,
verbose=2,
scoring='roc_auc',
cv=4)
bselector = backward_feature_selector.fit(x, y)
下面是生成的输出:
[Parallel(n_jobs=1)]: Using backend SequentialBackend with 1 concurrent workers.
[Parallel(n_jobs=1)]: Done 1 out of 1 | elapsed: 3.4s remaining: 0.0s
[Parallel(n_jobs=1)]: Done 28 out of 28 | elapsed: 1.1min finished[2020-03-01 19:05:39] Features: 27/6 -- score: 1.0[Parallel(n_jobs=1)]: Using backend SequentialBackend with 1 concurrent workers.
[Parallel(n_jobs=1)]: Done 1 out of 1 | elapsed: 3.2s remaining: 0.0s
[Parallel(n_jobs=1)]: Done 27 out of 27 | elapsed: 1.0min finished...[2020-03-01 19:17:46] Features: 7/6 -- score: 1.0[Parallel(n_jobs=1)]: Using backend SequentialBackend with 1 concurrent workers.
[Parallel(n_jobs=1)]: Done 1 out of 1 | elapsed: 2.7s remaining: 0.0s
[Parallel(n_jobs=1)]: Done 7 out of 7 | elapsed: 13.0s finished[2020-03-01 19:17:59] Features: 6/6 -- score: 1.0
以下是确定的特征:
>>> bselector.k_feature_names_
('0', '1', '3', '4', '5', '27')
如我们所见,所识别的特征与前向特征选择相同。ExtraTreesClassifier 还将要素 1(提前期)识别为重要要素,而此方法识别要素 3、4、5 (arrivaldatemonth、arrivaldateweekno、arrivaldatedayofmonth)。
在这方面,此要素选择方法表明数据集中的时间要素比 ExtraTreesClassifier 方法建议的更重要。
结论
总而言之,我们研究了:
- 如何分析分类和区间特征的特征数据
- 使用树外分类器的特征选择
- 向前和向后特征选择方法
本例的数据集和笔记本可从 MGCodesandStats GitHub 库获得,以及对该主题的进一步研究。
免责声明:本文是在“原样”的基础上编写的,没有担保。本文旨在提供数据科学概念的概述,不应以任何方式解释为专业建议。
有用的参考资料
使用 BorutaPy 进行特征选择
查找携带预测信息的所有要素
图片由 Free-Photos 来自 Pixabay
这篇文章将作为一个教程,介绍在为预测分类模型执行特征选择时如何实现 BorutaPy。当选择使用 BorutaPy 时,我会经历一些优点和一些缺点。我将使用坦桑尼亚油井分类数据集,尝试构建一个分类模型来预测一口井是正常工作、正常工作但需要维修还是不正常工作。
特征选择是机器学习中最重要的步骤之一。将特征输入模型时,目标是为模型提供与预测类相关的特征。包括不相关的特征带来了数据中不必要的噪声的问题,导致较低的模型精度。通常,我们使用基于统计的特征选择方法,如 ANOVA 或卡方检验,评估每个预测变量与目标变量之间的关系。
“Boruta 是一种所有相关特征选择方法,而大多数其它方法是最小最优的;这意味着它试图找到携带可用于预测的信息的所有特征,而不是找到某个分类器误差最小的可能紧凑的特征子集。” - 米隆·库尔萨-
有了 boruta,这些特性就可以被管理到“所有相关”的停止点,而不是“最小最优”的停止点。当用于预测时,所有相关变量都不是多余的。Boruta 基于两个思想,阴影特征和二项分布。当使用 boruta 时,这些特性不是用它们自己来评估,而是用它们的随机版本来评估。对于二项式分布的想法,boruta 采用了一个我们不知道是否有用的特征,并根据选择分布尾部定义的三个区域拒绝或接受该特征,例如 0.5%。
- **拒绝区域:**特征被视为噪声而被丢弃的区域。
- **犹豫不决的区域:**博鲁塔对特性犹豫不决的区域
- **接受区域:**特征被认为具有预测性的区域
例如,我将构建一个三元分类模型,用于坦桑尼亚水井数据。这个分类器将预测水井的状况,数据集可以在这里检索到。我将从我如何处理模型数据开始。
要安装 BorutaPy,请在您的笔记本或终端上运行以下代码。Boruta 的依赖项是 numpy、scipy 和 scikit-learn。
博鲁派文档h😗***
****###Installing BorutaPy**pip install BorutaPy**###Importing the libraries for data processing**import pandas as pd
import numpy as np**###Reading in the data**train_data = pd.read_csv(‘../data/train_data.csv’)train_target = pd.read_csv(‘../data/train_targets.csv’)test = pd.read_csv(‘../data/test_set_values.csv’)**###Adding training label to training dataframe**train = train_data.merge(train_target, on='id', how='inner')**###‘status group' needs to be converted to numerical values for the ###classification model and not ‘functional’, ‘non-functional’, and ###‘functional in need of repair’.**status_group_numeric = {'functional': 2,
'functional needs repair': 1,
'non functional': 0}
train['status'] = train.status_group.replace(status_group_numeric)**
检查数据集中是否有缺失值
**train.isna().sum()**
填充缺失值
许可字段中大约 69%的值为真,31%为假。我也选择用同样的比例来填充缺失的值。我还需要将这些值转换成数字。
**train['permit'].fillna(False, limit=947, inplace=True)
train['permit'].fillna(True, inplace=True)**###Function to take values in permit field and change them to ###numerical values**
def permit(row):
if row['permit'] == True:
return 1
else:
return 0
train['permit'] = train.apply(lambda x: permit(x), axis=1)**
公共会议字段有 91%的正确率和 9%的错误率。我选择用相同的比率来填充缺失的值。我还需要将值改为数字。
**train['public_meeting'].fillna(False, limit=300, inplace=True)
train['public_meeting'].fillna(True, inplace=True)**###Function to take values in public field and convert them to ###numerical values**
def public(row):
if row['public_meeting'] == True:
return 1
else:
return 0
train['public_meeting'] = train.apply(lambda x: public(x), axis=1)**
宁滨特色
出资者一栏显示了谁资助了油井。有 1,897 个不同的结果,但看起来只有前 7 个字段的值出现超过一千次。我将把这一栏分为 7 个不同的类别,其余的字段将归类为“其他”。
**def categorize_funder(train):
'''This function will go through every row in
the dataframe column funder and if the value
is any of the top 7 fields, will return those
values. If the value does not equal any of these
top 7 fields, it will return other.'''
if train['funder'] == 'Government Of Tanzania':
return 'govt'
elif train['funder'] == 'Danida':
return 'danida'
elif train['funder'] == 'Hesawa':
return 'hesawa'
elif train['funder'] == 'Rwssp':
return 'rwssp'
elif train['funder'] == 'World Bank':
return 'world_bank'
elif train['funder'] == 'Kkkt':
return 'kkkt'
elif train['funder'] == 'World Vision':
return 'world_vision'
else:
return 'other'train['funder'] = train.apply(lambda x: categorize_funder(x), axis=1)**
宁滨将安装程序字段分为 7 类
**def categorize_installer(train):
'''This function will go through
every row in the installer column
and if the value is equal to any of
the top 7, will return those values.
If not, will return other.'''
if train['installer'] == 'DWE':
return 'dwe'
elif train['installer'] == 'Government':
return 'govt'
elif train['installer'] == 'RWE':
return 'rwe'
elif train['installer'] == 'Commu':
return 'commu'
elif train['installer'] == 'DANIDA':
return 'danida'
elif train['installer'] == 'KKKT':
return 'kkkt'
elif train['installer'] == 'Hesawa':
return 'hesawa'
else:
return 'other'train['installer'] = train.apply(lambda x: categorize_installer(x), axis=1)**
宁滨把方案管理领域分为 7 类
**def categorize_scheme(row):
'''This function will go through each
row in the scheme management column
and if the value is equal to any of the
top 7, will return those values. If not,
will categorize the value as other.'''
if row['scheme_management'] == 'VWC':
return 'vwc'
elif row['scheme_management'] == 'WUG':
return 'wug'
elif row['scheme_management'] == 'Water authority':
return 'water_authority'
elif row['scheme_management'] == 'WUA':
return 'wua'
elif row['scheme_management'] == 'Water Board':
return 'water_board'
elif row['scheme_management'] == 'Parastatal':
return 'parastatal'
elif row['scheme_management'] == 'Private operator':
return 'private_operator'
else:
return 'other'train['scheme_management'] = train.apply(lambda x: categorize_scheme(x), axis=1)**
由于数据集中有 55 个不同的建造年份,看起来建造年份字段对于我们的模型来说很难分类。我打算把宁滨的这些年变成几十年。
**def categorize_contruction(row):
if row['construction_year'] < 1970:
return '1960s'
elif row['construction_year'] < 1980:
return '1970s'
elif row['construction_year'] < 1990:
return '1980s'
elif row['construction_year'] < 2000:
return '1990s'
elif row['construction_year'] < 2010:
return '2000s'
elif row['construction_year'] < 2020:
return '2010s'train['construction_year'] = train.apply(lambda x: categorize_contruction(x), axis=1)**
移除的功能
我选择删除值与另一个值相似的字段,以及包含我找不到与预测模型相关的足够信息的值的字段。被删除的功能可能包含重要信息,我建议仔细查看这些数据。出于本示例的目的,我将在没有它们的情况下继续。
**- train = train.drop(columns=['subvillage'], axis=1)
- train = train.drop(columns=['scheme_name'], axis=1)
- train = train.drop(columns=['wpt_name'], axis=1)
- train = train.drop(columns=['region'], axis=1)
- train = train.drop(columns=['extraction_type', 'extraction_type_group'],
axis=1)
- train = train.drop(columns=['management_group'], axis=1)
- train = train.drop(columns=['payment_type'], axis=1)
- train = train.drop(columns=['water_quality'], axis=1)
- train = train.drop(columns=['quantity_group'], axis=1)
- train = train.drop(columns=['source_type'], axis=1)
- train = train.drop(columns=['waterpoint_type_group'], axis=1)**
来自数据的状态
**pivot_train = pd.pivot_table(train, index=['status_group'],
values='status',
aggfunc='count')
pivot_train**
对训练数据集进行训练测试拆分
**X = train.drop(columns=['id', 'status_group', 'status', 'date_recorded'], axis=1)
y = train.statusX_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)**
编码和缩放
我用一个 Sklearn 的热编码器对分类特征进行编码,并用 Sklearn 的标准定标器对连续特征进行定标。
****###Instantiating One Hot Encoder** ohe = OneHotEncoder()**###Defining features to encode** ohe_features = ['funder', 'installer', 'basin',
'region_code', 'district_code', 'lga', 'public_meeting',
'scheme_management', 'permit', 'construction_year',
'extraction_type_class', 'management',
'payment', 'quality_group',
'quantity', 'source', 'waterpoint_type']**###Defining continuous numerical features** cont_features = ['amount_tsh', 'gps_height', 'longitude',
'latitude', 'population'**###Creating series for categorical test and train** X_train_cat = X_train[ohe_features]
X_test_cat = X_test[ohe_features]**###Fitting encoder to training categorical features and transforming ###test and train**
X_train_ohe = ohe.fit_transform(X_train_cat)
X_test_ohe = ohe.transform(X_test_cat)**###Converting series to dataframes** columns = ohe.get_feature_names(input_features=X_train_cat.columns)
X_train_processed = pd.DataFrame(X_train_ohe.todense(), columns=columns)
X_test_processed = pd.DataFrame(X_test_ohe.todense(), columns=columns)**###Instantiating Standard Scaler**
ss = StandardScaler()**###Converting continuous feature values to floats**
X_train_cont = X_train[cont_features].astype(float)
X_test_cont = X_test[cont_features].astype(float)**###Fitting scaler to training continuous features and transforming ###train and test**
X_train_scaled = ss.fit_transform(X_train_cont)
X_test_scaled = ss.transform(X_test_cont)**###Concatenating scaled and encoded dataframes** X_train_a2 = pd.concat([pd.DataFrame(X_train_scaled), X_train_processed], axis=1)
X_test_a2 = pd.concat([pd.DataFrame(X_test_scaled), X_test_processed], axis=1)**
导入用于预测分类的库
****###Classification Algorithm** from sklearn.ensemble import RandomForestClassifier**###Model evaluation** from sklearn.model_selection import cross_val_score
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score**###Feature Selection** from boruta import BorutaPy**
对于这个例子,我选择使用随机森林分类器,这是一种基于系综树的学习算法。它是用随机选择的训练数据子集创建的一组决策树。随机森林分类器然后聚集来自不同决策树的投票来选择测试对象的最终类。随机森林分类器的第一次运行将包括所有的特性,然后我将运行 BorutaPy。
****###Instantiating Random Forest Classifier** rf = RandomForestClassifier(n_estimators=500, random_state=42)**###Fitting Random Forest Classifier to training data** rf.fit(X_train_a2, y_train)**###Print accuracy and recall scores for both test and train****###Average is set to micro for recall score since this is a ###multi-class classification model. Micro-average aggregates the ###contributions of all classes to compute the average metric. Micro ###is preferred for data with class imbalance.** print('Test Accuracy:')
print(accuracy_score(y_test, rf.predict(X_test_a2)))
print('Test Recall:')
print(recall_score(y_test, rf.predict(X_test_a2), average='micro'))
print('Train Accuracy:')
print(accuracy_score(y_train, rf.predict(X_train_a2)))
print('Train Recall:')
print(recall_score(y_train, rf.predict(X_train_a2), average='micro'))**####Output:**Test Accuracy:
0.80006734006734
Test Recall:
0.6729820394303477
Train Accuracy:
0.9955555555555555
Train Recall:
0.9902567898799216**
这导致了 80%的测试分数(平均准确度)和 96%的训练分数,现在我将通过 BorutaPy 运行这些特性,看看哪些被选为相关的。
博鲁塔方法论
- 首先,通过创建重复要素并混洗每列中的值来移除它们与响应的相关性,从而为要素提供随机性。(阴影特征)
- 在数据集上训练随机森林分类器,并通过收集 Z 分数来计算相关性/重要性。
- 在阴影属性中查找最大 Z 得分,并为 Z 得分高于阴影要素最大 Z 得分的每个属性指定一个命中。(准确度损失除以准确度损失的标准偏差)
- 获取尚未确定为重要的每个属性,并使用阴影属性中的最大 Z 得分执行双边质量测试。
- 将重要性级别低于 MZSA 的属性标记为“不重要”。
- 将重要性级别高于 MZSA 的属性标记为“重要”。
- 移除所有阴影属性
- 重复此过程,直到计算出所有属性的重要性,或者算法达到设定的迭代次数
****###define X and y for boruta, algorithm takes numpy arrays as inputs ###and not dataframe (why you see .values)**
X_boruta = train_all.drop(columns=['status'], axis=1).values
y_boruta = train_all.status.values**###define random forest classifier, set n_jobs parameter to -1 to ###utilize all processors and set n_estimators parameter to 500, ###number of trees in the forest.**
rf = RandomForestClassifier(n_jobs=-1, n_estimators=500, oob_score=True, max_depth=6)**###Define borutapy with rf as estimator and verbose parameter set to ###2 to output which features have been selected already**
feat_selector = BorutaPy(rf, n_estimators='auto', verbose=2, random_state=42)**###fit boruta selector to X and y boruta**
feat_selector.fit(X_boruta, y_boruta)Output:*Iteration: 1 / 100
Confirmed: 0
Tentative: 277
Rejected: 0
Iteration: 2 / 100
Confirmed: 0
Tentative: 277
Rejected: 0
Iteration: 3 / 100
Confirmed: 0
Tentative: 277
Rejected: 0
Iteration: 4 / 100
Confirmed: 0
Tentative: 277
Rejected: 0
Iteration: 5 / 100
Confirmed: 0
Tentative: 277
Rejected: 0
Iteration: 6 / 100
Confirmed: 0
Tentative: 277
Rejected: 0
Iteration: 7 / 100
Confirmed: 0
Tentative: 277
Rejected: 0
Iteration: 8 / 100
Confirmed: 110
Tentative: 49
Rejected: 118
Iteration: 9 / 100
Confirmed: 110
Tentative: 49
Rejected: 118
Iteration: 10 / 100
Confirmed: 110
Tentative: 49
Rejected: 118* *...* *Iteration: 90 / 100
Confirmed: 122
Tentative: 11
Rejected: 144
Iteration: 91 / 100
Confirmed: 122
Tentative: 11
Rejected: 144
Iteration: 92 / 100
Confirmed: 122
Tentative: 11
Rejected: 144
Iteration: 93 / 100
Confirmed: 122
Tentative: 11
Rejected: 144
Iteration: 94 / 100
Confirmed: 122
Tentative: 11
Rejected: 144
Iteration: 95 / 100
Confirmed: 122
Tentative: 11
Rejected: 144
Iteration: 96 / 100
Confirmed: 122
Tentative: 11
Rejected: 144
Iteration: 97 / 100
Confirmed: 122
Tentative: 11
Rejected: 144
Iteration: 98 / 100
Confirmed: 122
Tentative: 11
Rejected: 144
Iteration: 99 / 100
Confirmed: 122
Tentative: 11
Rejected: 144
BorutaPy finished running.
Iteration: 100 / 100
Confirmed: 122
Tentative: 2
Rejected: 144***
检查接受的特征
****###Print accepted features as well as features that boruta did not ###deem unimportant or important (area of irresolution)**
accept = X.columns[feat_selector.support_].to_list()
irresolution = X.columns[feat_selector.support_weak_].to_list()**###Call transform on boruta to update X_boruta to selected features** X_filtered = feat_selector.transform(X_boruta)print('Accepted features:')
print('----------------------------')
print(list(accept))
print('----------------------------')
print(list(irresolution))**
为所选要素创建新的数据框
通过使用这些选择的特征并将超参数 max_depth 调整为 6,我们获得了改进的分数。
****###Creating new dataframe from original X dataframe with only the ###selected features from BorutaPy**
new_x = train_all[accept]
X2_boruta = new_x.drop(['status'], axis=1)
y2_boruta = new_x.status**###Train test split on updated X**
X_t, X_val, y_t, y_val = train_test_split(new_x, y, random_state=42)**###Instantiating Random Forest Classifier** rf2 = RandomForestClassifier(n_jobs=-1, n_estimators=500, oob_score=True, max_depth=6, random_state=42)**###Fitting Random Forest Classifier to train and test** rf2.fit(X_t, y_t)**###Predicting on test data** y_pred = rf2.predict(X_val)**###Test Score** rf2.score(X_val, y_val)**###Training Score** rf2.score(X_t, y_t)**###Print accuracy and recall scores for both test and train ###Average is set to micro for recall score since this is a ###multi-class classification model. Micro-average aggregates the ###contributions of all classes to compute the average metric. Micro ###is preferred for data with class imbalance.**print('Test Accuracy:')
print(accuracy_score(y_test, rf.predict(X_test_a2)))
print('Test Recall:')
print(recall_score(y_test, rf.predict(X_test_a2), average='micro'))
print('Train Accuracy:')
print(accuracy_score(y_train, rf.predict(X_train_a2)))
print('Train Recall:')
print(recall_score(y_train, rf.predict(X_train_a2), average='micro'))**###Output:** Test Accuracy:
0.797068340067343
Test Recall:
0.769820394303477
Train Accuracy:
0.818649338720538
Train Recall:
0.810256789879921**
仅使用所选功能的第二次运行导致 80%的测试分数和 81%的训练分数。从我们的第一次迭代到 80%的测试分数和 96%的训练分数,这绝对是一个进步。我们正在最小化测试和训练分数之间的差距(模型越来越不适合)。
结论
Boruta 是一个强大的特征选择算法,你可以在大多数数据集上实现。在时间紧迫的情况下,以及在包含大量弱相关预测变量的数据集的情况下,它会非常有用。主要缺点是计算时间,虽然很多算法可以在几秒或几毫秒内执行,但 boruta 的执行时间是以小时计算的。这使得调整参数极其困难,因为每次调整都需要大量的额外时间。对于您正在处理的数据集,Boruta 可能不是最佳选择,我建议您也测试其他算法并比较结果。
参考文献:
- Bhattacharyya,I. (2018 年 9 月 18 日)。特征选择(Boruta/Light GBM/Chi Square)-分类特征选择。检索自https://medium . com/@ indreshbhattacharyya/feature-selection-category-feature-selection-boruta-light-GBM-chi-square-BF 47 e 94 e 2558
- 丹尼尔·霍莫拉。(2016 年 02 月 08 日)。一种全相关特征选择方法。检索自http://danielhomola . com/2015/05/08/boru tapy-an-all-relevant-feature-selection-method/
- 博鲁塔。(未注明)。检索自https://pypi.org/project/Boruta/
特征选择?你可能做错了
…除非您正在使用这个 Python 包
一张关于樱桃采摘的精美照片(版权所有 Shutterstock
我敢打赌,在那里,99%的特征选择是在“SelectFromModel”模式下进行的(这个名字来自 Scikit-learn 的[SelectFromModel](https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.SelectFromModel.html)
),它是这样工作的:
- 你选择一个预测模型(姑且称之为
WhatevBoost
); - 你符合
WhatevBoost
的所有特征; - 你从
WhatevBoost
中提取特征重要性; - 您删除了所有重要性低于某个阈值的特性,保留了所有其他特性。
这似乎是一个合理的方法,对不对?答案可能会让你大吃一惊。
在这篇文章中,我将测试这个过程是否真的如预期的那样工作。最后,我将展示一个出色的——但仍然鲜为人知的——用于特性选择的 Python 包,它恰好优于所有其他测试过的算法。
给我数据
在本帖中,我们将使用模拟数据。
我知道数据科学家对模拟数据嗤之以鼻,但这是测试事物的有效方法。在数据科学中,这是我们能够真正了解真相的唯一情况。
我们的模拟数据集会是什么样子?我们希望生成一些独立的特征:其中一些将与目标变量(称为y
)相关,而其他特征将只是噪声。目的是找到一种能够确定哪些特征属于第一组和哪些特征属于第二组的特征选择方法。
假设我们的特征矩阵由 16 个独立特征组成,我们将其命名如下:
你可能已经从它们的名字猜到了,前 6 个特性与y
有某种关系,而后 10 个只是噪音。
y
的函数形式应该足够复杂,能够包含一些自然界中存在的变量之间的非平凡效应。特别是,我们希望考虑以下类型的关系:
- 线性的
- 非线性的
- 相互作用
而且X
和y
的关系应该是非确定性的,所以增加了一个误差因子,叫做 ε 。为了说明这一切,我想出了下面的函数:
这转化为以下 Python 代码:
最后我们可以生成 X 和 y ,然后在一个训练集和一个测试集中拆分。
尝试“SelectFromModel”模式
现在我们有了数据,是时候挑选一些预测模型,并在“SelectFromModel”模式下进行尝试了。我们来看 8 个模型:
很有可能你听过所有的,但最后一个。你可能会挠头问“这个UnbeatableRegressor
到底是什么?”。好吧,因为我们的数据是用我们确实知道的函数模拟的,所以我们可以得到每个数据科学家的圣杯:完美的模型。它是 y 的功能形式,不用说,它是不可战胜的。
为了获得与 scikit 兼容的回归器,我们只需将我们的函数包装在一个类中:
现在,让我们根据训练数据拟合我们的模型,看看它们在平均绝对误差方面的表现如何。
到目前为止,这并不奇怪:更酷的算法,如XGBoost
或LightGBM
比其他算法表现得更好(即使它们离理论最小值还很远)。
现在,让我们关注特性重要性,这是“SelectFromModel”模式的核心。
特征重要性在机器学习中是一个相当难以捉摸的概念,这意味着没有一种明确的方法来计算它。无论如何,这个想法非常直观:这是一种量化任何单一特征对预测模型准确性的贡献的方式。
值为 0%的特性不会以任何方式影响模型的准确性(因此可以将其删除)。值为 100%的特征是影响预测的唯一特征。在实际应用中,特性从来不是 0%或 100%重要,它们总是介于两者之间。
然而,由于我们只有 16 个特征,并且其中的后 10 个特征(从noise_1
到noise_10
)与y
没有任何关系,我们期望这些特征的重要性为 0%,其余 6 个特征(linear
、nonlinear_square
、nonlinear_sin
、interaction_1
、interaction_2
和interaction_3
)在它们之间共享所有的重要性。
但是让我们更保守一点:让我们取 1%的安全缓冲:我们将丢弃任何重要性低于 1%的特性。这个阈值是相当武断的,但是,考虑到我们只处理 16 个特征,似乎有理由相信低于 1%重要性的特征实际上是无用的。
在下图中,显示了所有 8 个模型的特征重要性。此外,重要性低于 1%的特性在其名称旁边标有“【DROP】”。
令人惊讶的是,最差的模型之一——T0——是唯一一个正确猜测所有相关特征的模型(但是,应该注意的是,nonlinear_sin
由一根头发保持,因为它的重要性是 1.17%:稍微不同的阈值就会改变事情)。
UnbeatableRegressor
提供的更接近特征重要性的“实际”形状的模型是LGBMRegressor
,然而,许多嘈杂的特征被高估了,在这个意义上它们超过了 1%。
您可能会惊讶于这样一个事实,性能更好的模型不一定特性选择更好:拥有一个优秀的模型并不能保证特性选择的成功。此外,这种进行方式受到重要性阈值选择的严重影响:不同的阈值会给出完全不同的结果。
出于这些原因,我开始寻找另一种选择。直到我在波鲁塔绊倒。
使用 Boruta 进行特征选择
Boruta 是一种可以追溯到 2010 年的特征选择算法。它是作为 R 的一个包而诞生的()这个是米隆·库尔萨(Miron Kursa)和维托尔德·鲁德尼克(Witold Rudnickii)的原创文章,丹尼尔·霍莫拉(Daniel)的《蟒蛇》改编本:你可以在这里找到相关的项目。
Boruta 背后的直觉非常聪明,值得在一篇专门的文章中解释。在本文中,我们将限制自己使用 Python 的 Boruta 库,它可以通过pip install Boruta
安装。
波鲁塔是一个包装纸。建议用max_depth = 5
包裹一片随机森林。不用考虑参数调整确实是一个很大的好处。
您可能会问自己:“我们为什么使用RandomForestRegressor
?在之前的实验中,它是表现最差的模型之一”。好吧,这正是 Boruta 的美妙之处:尽管它是随机森林之类的弱模型的包装,但它的设计是为了克服它的缺点。
Boruta 的输出是一个特征排序,它可以将特征细分为 3 个类别:
- 排序 1:确认特征(这些特征对目标变量有一定的信号性,应当保留);
- 排名第 2:暂定特征(博鲁塔对这些特征举棋不定,由你来选择,我是个保守的人,我的建议是保留它们);
- 排名 3 或更高:被拒绝的特性(这些只是噪音,所以应该被丢弃)。
可以绘制排名并可视化 3 个区域:
通过 Boruta 获得的特性排名
Boruta 做了一项惊人的工作:它从剩余的 10 个噪声特征中分离出了 6 个有意义的特征,正如我们所预期的那样。
总结
在本文中,我们使用模拟数据来证明,即使是 Xgboost 或 LightGBM 这样的复杂模型,在选择特性时也可能不是一个好的选择。
作为替代,我们提出了一个名为 Boruta 的相当未知但功能强大的 Python 包,它已经交付了预期的结果。
如果你对 Boruta 的功能感兴趣(我相信理解算法是有效使用它们的唯一方法),你可以阅读我写的关于这个主题的文章:“ Boruta 准确地解释了你希望有人如何向你解释”。
完整的 Python 代码可以在这里找到:https://github . com/smazzanti/TDS _ feature _ selection _ you _ are _ possible _ doing _ it _ error
感谢您的阅读!希望这篇帖子有用。我感谢反馈和建设性的批评。如果你想谈论这篇文章或其他相关话题,你可以在这里给我发短信或在我的 Linkedin 联系人。
特征存储:在组织内部和跨组织实现数据科学和人工智能的更好方式。
功能商店如何帮助企业加速数据和人工智能的采用?
克里斯蒂娜@ wocintechchat.com 在 Unsplash 上的照片
特色商店——人工智能应用的加速器
数据科学和人工智能是改变您的业务和您所做的一切的强大力量,然而,优化和自动化数据科学和人工智能以充分利用它们的潜力和能力有着巨大的可能性。当组织开始他们的人工智能之旅时,他们会面临许多挑战,通常需要但很难加速其采用。
虽然有很多原因,但我们在这篇博客中关注的一个原因是,数据科学家需要重复他们的工作,缺乏集中的存储库等。这给业务和数据科学家带来了成本,例如大量重复工作、增加生产时间,以及产生不一致的人工制品。
在这篇博客中,我们将讨论什么是功能商店,它如何帮助人工智能的采用,以及它能给你的企业带来什么好处。我们将进一步讨论特征库如何成为解决上述问题的解决方案,并作为人工智能采用的推动者和加速器。我们将讨论它如何缩短机器学习模型的上市(生产)时间,以及它如何解决上述问题。
W 什么是特色店?
作为数据科学家,由于没有集中的存储库,我们经常重复工作,这是以增加生产时间为代价的,大量工作重复而不一致,无法共享和重用工件。在这篇博客中,我们将讨论它如何缩短机器学习模型的上市(生产)时间,以及它如何解决上述问题。
企业用户越来越需要并接受在企业中利用数据科学和人工智能来实现以下目标:
- 优化决策
- 优化业务运营
- 创造新的商业机会
一方面是业务利益相关者,另一方面是技术极客、数据(科学)专业人员(我使用这个术语来涵盖所有数据工作者,包括数据科学家、数据工程师、数据可视化专家、数据架构师等。).企业所有者制定决策并经营企业,他们追求的是投资回报(ROI),而数据工作者追求的是他们的技术产品的运行和工作。在这场竞赛中,数据科学家利用他们或其他数据工作者从不同来源获取的不同数据集,构建了不同的机器学习(ML)和深度学习(DL)模型。通常情况下,不同的模型准备数据的过程是相似的,这种努力可以在不同的人工智能工作中简化和重用。
因此,为了使构建人工智能模型的过程更加高效、可重用、可扩展,企业必须构建或利用企业范围的人工智能平台,除了降低在整个企业中开发、部署和共享人工智能模型的成本之外,该平台还可以大幅缩短生产周期。
典型的 ML 流如下所示
典型的 ML 工作流程 2020,Chan Naseeb。保留所有权利。
数据科学家将大部分时间花在准备数据上,在他们到达某个点(如 ML 模型)之前提取特征。这种时间、精力和资源的浪费可以节省下来,并用于获得有价值的见解,通过使这些数据成为可重用和可扩展的东西,可以更快地获得这些信息。
当谈到跨组织和跨部门的人工智能计划时,在数据准备步骤中提取的特征可以在多个项目中共享。存储和共享提取的特征、其他数据和人工智能产品(或资产)可以大大有助于加速人工智能工作和概念验证(POCs)。此外,企业将有更多可扩展的方式来管理数据和人工智能资产。
F 特征存储:
上述关于实现可扩展性、可重用性等预期好处的讨论是促使我们建立这样一个平台(我们称之为功能库)的激励因素,它可以帮助组织在不同的工作和团队中共享数据和人工智能产品。这将有助于加快运行和部署模型的时间,因为花费大部分时间的 ML 管道中的警告现在通过利用/重用现有的工件在某种程度上减少了。
“功能库是一个存储库,允许团队共享、发现和使用一组高度精选的功能来解决他们的机器学习问题”。
我们可以这样定义它
It 是一个集中的软件仓库(库),包含许多功能(工件),其中每个功能都从输入数据中创建一个特征。除了特性之外,你可以将这个定义扩展到存储、创建和共享任何其他数据&人工智能产品(模型、笔记本、代码文件等)。
它可以作为不同团队之间的桥梁,帮助他们减少整个组织中的孤岛。大量的数据和人工智能产品可以存储在特征库中。它们可以根据不同的目的进一步更新、版本化和编目。它可以帮助数据科学家构建新模型或增强现有模型,他们可以使用现成的人工制品并向其添加新的功能(人工制品)。
您可以利用特征库对模型进行在线和离线训练。在前一种情况下,您可以计算所需的特征(实时或批量预计算)并将它们存储到特征库中。而在后一种情况下,您拥有所有类型的数据以及与之相关的其他特征,您可以利用这些数据来训练机器学习模型。
数据科学家因此受益于自动化的数据准备步骤,否则会重复计算。数据处理的标准化和功能的版本化提供了不同模型之间的一致性,同时为数据科学家提供了按需定制的机会。这使得在整个业务中共享知识、模型和其他人工制品变得更加容易。
实施功能商店后,作为一个组织,您会获得什么好处?
向您的数据和人工智能策略中添加一个特征库可以为您带来以下好处:
**可伸缩性:**特性库可以随着 ML 项目交付的速度而增长。你可以使用现有的功能和其他可能的数据和人工智能产品来共享和引导人工智能项目,而不是每次都重新发明轮子。
**规模经济:**组织开发人工智能模型变得更加容易和快速。构建新模型所需的资源更少,因为新模型可以重用特征库中的现有特征。因此,使用共享特征库可以使组织实现规模经济
**更少的生产时间:**每次重新发明轮子时,通过节省数据准备和特征工程的时间、精力和资源,获得有价值的见解所需的时间更少。这并不意味着你不必做任何事情,而是规模和强度会小得多。这将需要您做很少的工作,因为您可以在需要的地方重用和修改这些特性。
**一致性和标准化:**特征库解决了 ML 项目管道中效率低下的问题。它通过自动化重复进行的数据准备工作和标准化数据处理使数据科学家受益,从而使不同模型的特征保持一致。
2020,Chan Naseeb。保留所有权利。
最初发表于T5【https://www.community.ibm.com】。
感谢阅读!
如果你喜欢我的工作,并希望保持联系…
- 最好的方法是跟随我上 中级 。
- 如果你想在介质上写作并提交给出版物。点击此处查看 数据和 AI 以及更多一般性和多样化的话题,您可以将您的文章提交至
- 在Twitter这里关注我。我会在那里发布很多更新和有趣的东西!
- 还有,订阅我的 YouTube 频道 这里!
- 关注我LinkedIn这里。
- 查看我的网站。
数据科学家的特征转换
数据插补,宁滨,编码,等等!熟练掌握所有步骤!
本·怀特在 Unsplash 上的照片
简介
要素变换是修改数据但保留信息的过程。这些修改将使机器学习算法更容易理解,从而提供更好的结果。
我们将涵盖每种方法的所有步骤,从解释到代码;但首先,让我们来看看今天我们将学习的内容:
数据缩放(标准化和规范化)
- 我们将减少重复,提高性能和数据完整性。
数据插补、宁滨和编码
- 如何填充缺失的值,将其转换为数字,并按值进行缩放。
异常值检测
- 最后,我们将根据标准差和四分位间距移除异常值。
数据集
图片由雷南·洛里科拍摄——中号
您可以通过点击此处下载数据集。现在,我们需要定义一些参数和要回答的问题。
这个人工数据集模拟了一些关于心脏病可能性的数据,这就是我们的目标。为了找到答案,我们有一些虚假的医疗信息,如血压、年龄和钠含量。
我们有什么资源?
- **名称:**对象;
- **年龄:**int 64;
- **收缩压(mmHg)😗*int 64;
- **舒张压(mmHg)😗*int 64;
- **钠(mEq/L)😗*int 64;
- **低钠血症:**客体;
- **高钠血症:**客体;
- **心脏病:**对象;(目标)
1)数据插补
当获得新数据时,您要做的第一件事是检查它并寻找丢失的值;让我们看看它看起来怎么样。
图片由雷南·罗利科拍摄——中号
我在这个数据集中随机添加了一些空值,忽略了心脏病一栏。至于我们的方法,对小数据集使用 Pandas 函数是可以的;但是如果你有更大的,考虑使用 scikit-learn 。
如何分配数据?
在 Pandas 中,我们有一个很好的函数叫做 fillna() ,可以想象,它会填充任何空值。让我们来看看。
简单吧?它将产生下面的变化。
图片由雷南·洛里科拍摄——中号
问题是
多么简单啊!一行代码就这样,牛逼!但是冷静下来,有一个问题:我们把同一个值定义为分类的和数值的,这是不对的,那怎么办?
现在,我们有了填充数字资源中空白空间的整列的平均值和分类空间中“缺失”的文本。
图片由雷南·洛里科拍摄——中号
数据插补技巧
- 如果您有数字数据,请考虑用平均值或中值填充空值。
- 当心零;有些功能可以用这个作为布尔表示!
- 使用特定的单词来填充文本列。
- 当心数据重复。
2)异常值检测和消除
在继续之前,我们需要在我们的数字列中寻找差异,**,因为它们会影响我们模型的质量。**基于一个具体的问题,最好保留每个值,但无论如何你都需要知道如何移除它们。
怎么找他们?
通常可以用一些图形工具来显示,比如 Matplotlib。图表的类型?通常是直方图和箱线图。不知道如何绘制数据?我有一篇关于它的文章:数据可视化的终极指南。
下面我们将检查我们的数据表示是否没有异常值。
图片由雷南·洛里科拍摄——中号
为了了解情况,我附上了一个将一个人的年龄改为 134 岁的案例,非常罕见。
图片由雷南·洛里科拍摄——中号
老式的方法
你可能对视觉效果不太适应,或者只是想要一些更切题的东西。如果您符合上面的描述,我将留下代码来创建一个只有离群值的数据帧。
图片由雷南·洛里科拍摄——中号
对于大量的异常值,我们的模型将创建使用这些值的模式,但它们通常只是打字错误、错误数据等等。
如何去除它们?
通常有两种常见的剔除异常值的方法:标准差和四分位距。还有更多像 Z 分数,甚至手动删除,但让我们现在忽略它们。
- 标准偏差
图片来自维基百科——标准差
使用标准差,我们可以只选择那些在平均值的+3 或-3 标准差之间的数据。该值可以调整,但通常在 2 到 4 之间。如果你不确定如何使用标准差,点击此处观看可汗学院的视频。
2.四分位距
为了以这种方式去除异常值,我们需要获得第一个和第三个四分位数。数据必须按升序排列。
https://gist . github . com/ren felo/a1c 773511 e 5171 ace 6735032145 a0a 59
3)宁滨数据
图片由雷南·洛里科拍摄——中号
在这个阶段,我们引入一个间隔来替换所有条目的原始值。换句话说,我们将年龄列更改为:
- 比少 35;
- 在 35 和 50 之间;
- 超过50;
因此,任何符合这些标准的人的年龄值都将被修改。让我们看看代码。
这对于减少过拟合非常有用,但这是有代价的:我们惩罚了我们机器学习模型的准确性。您已经用三个结果的几个可能值更改了整个列。在我们的具体情况下不是问题,而是用好它。
数据宁滨提示
- 永远记住代价;
- 它是来用的,如果没必要,就忽略它;
- 它可以在特征工程期间使用,基于某些条件创建新列;
4)数据编码
用 scikit-learn 库中的任何工具对我们的数据集进行编码要容易得多,但这是一本 Pandas 手册,所以我们将手动进行。
为什么我需要编码?
计算机能阅读数字,甚至是最复杂的数字。理解数字数据比理解分类数据要容易得多,这也是我们这样做的原因。
正常数据集。图片由雷南·洛里科拍摄——中号
编码数据集。图片由雷南·洛里科拍摄——中号
编码后,我们可以验证皮尔逊相关性;它通常忽略分类特征。让我们来看看。
图片由雷南·洛里科拍摄——中号
如您所见,我们开始从数据中获得重要信息:
- name 列现在变得没用了,我们可以看到这一点;
- 年龄、收缩压和舒张压呈高度正相关;
- 低钠血症和高钠血症几乎不相关;
5)数据缩放
机器不像我们一样理解规模。你可以很容易地发现你的工资和你的体重之间的差异,要知道体重不可能和你每月收到的一样多,但计算机不会;这就是我们扩展整个数据集的原因。基本来说,有两种方式可以规模化:标准化和规范化。
标准化
为什么我要保留“姓名”列?图片由雷南·洛里科拍摄——中号
也称为 Z 分数标准化,这种方法调整我们的数据大小,使中值为零,标准差为 1 。最后,无论他们的价值观如何不同,他们都会有相同的代表性。
它非常有用,可以减少过度配置资源的影响,所以请使用它。
技巧
- 标准化减少了过度拟合的影响;
- 在深度学习和神经网络项目中,这是一个常见的过程;
正常化
图片由雷南·洛里科拍摄——中号
也被称为最小-最大规范化,这个方法将我们的数据调整为 0 和 1 之间的固定值。
技巧
- 标准化增加过度拟合的影响;
- 无论什么时候想用,先去掉离群值;
项目
作为本手册的最后一部分,我想展示应用于机器学习模型时的结果。首先,我们从探索性的数据分析开始。
探索性数据分析
我们不必担心数据清理,因为我们的数据集已经准备好了。让我们直接进入预览。
问题 1: 我们的年龄是如何影响收缩压指数的?
图片由雷南·洛里科拍摄——中号
**问题二:**有多少心脏病患者有高钠血症?
图片由雷南·洛里科拍摄——中号
可视化:我们的数据是如何传播的?
图片由雷南·洛里科拍摄——中号
你喜欢这些图像吗?我在 Medium 上还有一篇文章,教你如何创建漂亮的数据可视化效果。如果你想的话,过会儿再看。
没有人喜欢丑陋的东西,对吗?如果他们猜不出我们的期望,那就更糟了。所以让我们来学习如何生成…
towardsdatascience.com](/the-ultimate-guide-for-data-visualization-c98de0d3158d)
模型
由于它不是一个专注于机器学习模型工作流程每一步的项目,所以我会留下三个随机获得的算法的基础分数。这是分类问题,别忘了。我们的评估方法将是一个准确度分数和一个混淆矩阵。
图片由雷南·洛里科拍摄——中号
不幸的是,我们没有足够的数据来改进我们的模型,我们的第一个模型(RandomForest)可能会过度拟合。别忘了这个:你的数据越多,你的算法就越有能力。让我们检查一下混淆矩阵。
图片由雷南·罗利科拍摄——中号
看看这个!RandomForest 太棒了!但是现在注意了:后两个有假阳性和假阴性。我们上两个模型有时预测错误。这样不好,其实。当然可以改进。
不知道如何创建模型?
如果你对机器学习模型的制作有任何困难,不要担心,我有一篇关于它的令人钦佩的文章。充满图像,非常愉快。如果你想的话,可以看看。
使用哪种模型,何时使用,为什么?如何调优你的算法?让我们一起投入进去吧!
towardsdatascience.com](/your-complete-guide-to-machine-learning-models-403b4716172c)
我在哪里可以找到这些材料?
如果您对我如何创建所有这些图形和代码感兴趣,您可以:
就是这样,伙计们!
我希望你喜欢这个内容,并能熟练运用你的新知识!如果你想每天学习有趣的东西,我很乐意与你分享精彩的内容!
另外,你可以在 Github 上查看我的个人资料。我从事一些数据科学项目已经有一段时间了。所有的关键概念都可以学习和重用!
在 GitHub 上注册你自己的个人资料,这是托管代码、管理项目和构建软件的最佳地方…
github.com](https://github.com/renfelo)
卷积神经网络的特征可视化
卷积神经网络中的每个滤波器在做什么?它正在学习检测哪种图像?这里有一个方法可以知道
根据维基百科的说法, apophenia 是*“错误感知不相关事物之间的联系和意义的倾向”*。它也被用作“人类在随机信息中寻找模式的倾向”。无论是科学家在实验室里做研究,还是阴谋论者警告我们“这一切都是联系在一起的”,我想人们需要感觉我们明白发生了什么,即使面对明显随机的信息。
与 XGboost 或可解释的增强机器等更透明的模型相比,深度神经网络通常被视为“黑盒”,因为它们的不可预测性。
然而,有一种方法可以解释卷积神经网络中每个单独的滤波器正在做什么,以及它正在学习检测哪种图像。
至少从 2012 年开始,卷积神经网络开始崭露头角,当时 AlexNet 以 85%的准确率赢得了 ImageNet 计算机视觉竞赛。第二名的比例仅为 74%,一年后大多数竞争者都转向这种“新”算法。
它们广泛用于许多不同的任务,大多与图像处理相关。这些包括图像分类,检测问题,以及许多其他问题。
我不会深入探讨卷积神经网络是如何工作的,但如果你是这方面的初学者,我建议你阅读我的卷积神经网络实用介绍和工作张量流代码。
如果你已经掌握了卷积神经网络是如何工作的,那么这篇文章就是你理解什么特征可视化和它如何工作所需要知道的全部。
特征可视化是如何工作的?
通常,你会训练一个 CNN 给它提供图像和标签,并使用梯度下降或类似的优化方法来拟合神经网络的权重,以便它预测正确的标签。
在整个过程中,人们希望图像保持不变,这同样适用于标签。
然而,如果我们选取任何图像,在我们(已经训练好的)网络中选择一个卷积滤波器,并对输入图像应用梯度下降以最大化该滤波器的输出**,同时保持网络的权重不变,您认为会发生什么?**
突然间,我们的视角发生了转变。我们不再训练一个模型来预测图像的标签。相反,我们现在正在将图像与模型相匹配,让它生成我们想要的任何输出。
在某种程度上,这就像我们在问模型“看到这个过滤器了吗?什么样的图像能打开它?”。
如果我们的网络已经被适当地训练,那么我们期望大多数过滤器携带有趣的、有价值的信息,帮助模型为其分类任务做出准确的预测。我们期望过滤器的激活带有语义含义。
因此,显而易见的是,“激活”过滤器,使其具有大量输出的图像应该具有与数据集中(以及模型标签中)存在的某个对象相似的特征。
然而,鉴于卷积是一种局部变换**,在我们图像的许多不同区域,触发卷积滤波器重复“发芽”的模式是很常见的。**
这一过程产生了谷歌深梦模型流行的那种画面。
在本教程中,我们将使用 TensorFlow 的 Keras 代码来生成最大化给定滤镜输出的图像**。**
由于滤波器的输出在技术上是一个矩阵,我们将最大化的实际函数是该矩阵组件的平均值,是整个图像的平均值。通过这种方式,我们的算法将被激励来生成贯穿整个图像的激活过滤器的任何模式。
实现过滤器可视化
正如我之前提到的,要做到这一点,我们需要首先训练一个神经网络分类器**。幸运的是,我们不需要经历整个混乱而昂贵的过程: Keras 已经配备了一整套预先训练好的神经网络,我们可以下载并使用。**
使用预先训练好的神经网络
对于本文,我们将使用 VGG16,这是一个在相同的 ImageNet 竞争数据集上训练的巨大卷积神经网络。还记得我提过 AlexNet 以 85%的准确率胜出,颠覆了图像分类领域吗?VGG16 在同样的任务上得分 92%。
VGG16 是由英国牛津大学的 K. Simonyan 和 A. Zisserman 在论文《用于大规模图像识别的甚深卷积网络》中提出的卷积神经网络模型。该模型在 ImageNet 中达到了 92.7%的 top-5 测试准确率,ImageNet 是一个包含属于 1000 个类的超过 1400 万个图像的数据集。那是提交给ils vrc-2014的著名模型之一。它通过用多个 3×3 内核大小的滤波器一个接一个地替换大内核大小的滤波器(在第一和第二卷积层中分别是 11 和 5)来对 AlexNet 进行改进。VGG16 训练了几周,用的是 NVIDIA Titan Black GPU 的 。
https://neurohive.io/en/popular-networks/vgg16/—vgg 16—用于分类和检测的卷积网络(重点地雷)
对于这些实验,我将使用 Google colab 的 GPU 机器,并调整 Keras 库的示例过滤器可视化代码。
关于原始脚本是如何工作的,你可以看看 Keras 的博客。我只对它进行了轻微的修改,以方便配置文件名和其他小细节,所以我认为不值得链接到我自己的笔记本上。
这个重要函数的作用是:
- 定义一个损失函数,它等于所选的滤波器在整个图像上的平均输出。在我们的代码中,我们这样做:
loss = K.mean(layer_output[:, filter_index, :, :])
。 - 初始化一个小的起始图片**,典型的是以 RGB(128,128,128)为中心的随机均匀噪声(我实际上用这个玩了一会儿,稍后会详细说明)。**
- 针对该损失计算输入图像的梯度,并执行梯度下降。
注意,我们正在向神经网络输入图像,但是忽略了我们关心的那一层之后的任何一层。**** - 重复 N 次,然后调整图片大小,使其稍微变大(默认值为 20%)。我们从一张小图片开始,随着我们生成过滤器的最大化图像,它会越来越大,因为否则该算法会创建一个重复多次的小图案,而不是创建一个具有更大(主观上更美观)形状的低频图案。
- 重复最后两步,直到达到所需的分辨率。
差不多就是这样。我链接到的代码还发生了一些事情(图像标准化,将许多过滤器生成的图像拼接成可爱的拼贴画),但这是最重要的一点。
这是那个函数的代码,现在你知道发生了什么,就没那么可怕了,对吗?
现在有趣的部分,让我们试试这个,看看哪种过滤器出来。
我尝试特征可视化的结果
在尝试之前,我阅读了许多 不同的 例子的特性可视化文章。以下是我学到的一些东西。
- 第一个卷积层(靠近输入的层)产生更简单的视觉效果。它们通常只是粗糙的纹理,比如平行的波浪线,或者彩色的圆圈。
VGG16 上卷积滤波器的可视化,第二层。
- 更接近输出的卷积层产生更复杂的纹理和图案。有些甚至类似于存在的物体,或者看起来可能存在(以一种非常神秘的方式)。
老实说,这也是我玩得最开心的地方。我尝试了许多不同的“初始图像”,从随机噪声到均匀灰度,再到渐进退化。
任何给定过滤器的结果都非常相似。这让我想到,考虑到我使用的迭代次数,初始图像本身变得非常不相关。至少,它没有对结果产生可预测的影响。
VGG16 的第一个卷积层中的块 4 滤波器的特征可视化。大多数图案看起来规则而有颗粒,但比我们在第一层看到的早期乡村纹理要复杂得多。
块 4 的滤波器可视化,VGG16 的第二卷积层中的滤波器。注意这些图案是如何重复的,但是产生的纹理看起来比第一层要复杂得多。
块 4 的滤波器可视化,VGG16 的第三卷积层中的滤波器。一些更容易渗透的模式似乎出现了。
随着我们越来越深入,并且越来越接近完全连接的层**,我们到达了的最后一个卷积层。它生成的图像是迄今为止最复杂的**,它们制作的图案很多时候都类似于现实生活中的物品。****
块 5 的滤波器可视化,VGG16 的第一卷积层中的滤波器
块 5 的滤波器可视化,VGG16 的第三卷积层中的滤波器
块 5,第二卷积层中的滤波器。所有这些模式都是通过最大化一个“简单的”(尽管是超维的)数学函数出现的,这难道不疯狂吗?
现在,看着这些图像寻找模式,很容易感觉到一个人正在坠入阿波菲斯。然而,我想我们都同意,其中一些图片的特征看起来很像 …你可以放大图片,自己完成句子。特征可视化是新的凝视云。
我自己的猜测是这只是一种新的抽象艺术。
让我向你展示一些我认为视觉上最有趣的滤镜:
********
棉花,橘子皮,眼睛?奇怪的发霉螺旋。
我还有大约 240 张这样的照片,如果有足够的兴趣,我可以把它们做成一个画廊,但我担心过一会儿它可能会变得重复。
结论
老实说,我从这个项目中获得了很多乐趣。直到几周前,我才真正听说过 Google Colab(感谢 r/mediaSynthesis )。能够免费使用一台好的 GPU 机器,感觉太棒了。
几年前,我也读过关于这个主题的大部分论文,但是从来没有真正测试过代码或者写过这样的文章。我很高兴我终于把它从我的清单上划掉了(或者特雷罗,我在骗谁呢?).
最后,在未来,我想尝试不同的网络架构,并想象图像如何在每次迭代中变形,而不是简单地看着成品。
请在评论中让我知道哪些其他实验或参考书目值得查看,以继续扩展这个主题!
如果你喜欢这篇文章,请考虑在推特上发布或在其他地方分享! 关注我的Twitter进一步讨论这些问题,或者关注我的最新文章。
你可以在我的 个人网站 中看到我正在做的事情以及我最近的文章和笔记。
二月版:数据科学的有效编程
丹尼尔·里卡洛斯在 Unsplash 上的照片
像许多其他数据科学爱好者一样,您几乎每天都在编写代码。但是你在有效地编程吗?你为你的项目选择了正确的编程语言吗?你有没有用 IDE 或者笔记本来提升开发效率?你有没有利用任何库或框架来优化代码性能?
有效的编程不仅仅是编写高性能的代码,还包括利用可用的工具更有效地开发项目。学习更有效地编码是一项投资,将在你的职业生涯中获得回报。以下是我们收集的关于有效编程技术和技巧的最佳文章。
辛然·怀贝尔——编辑助理
伟大的开发者永远不会停止学习
通过 Semi Koen — 10 分钟读取
it 专业人员培养持续学习心态的 7 种方法
现在要学习的 7 大现代编程语言
通过 Md Kamaruzzaman — 17 分钟阅读
Rust、Go、Kotlin、TypeScript、Swift、Dart、Julia 如何促进您的职业发展并提高您的软件开发技能
摇滚命令行
由杰夫·黑尔 — 10 分钟读完
节省您时间的 21 个 Bash 命令
Git 和 GitHub 入门:完全初学者指南
由安妮·邦纳 — 18 分钟阅读
Git 和 GitHub 基础知识,供好奇和完全困惑的人使用(以及为您的第一个开源项目做出贡献的最简单的方法!)
为数据科学带来最好的 Jupyter 笔记本电脑
通过 Parul Pandey — 9 分钟读取
使用这些提示和技巧提高 Jupyter 笔记本的工作效率。
针对朱庇特笔记本的案件
由杰瑞米·哈里斯 — 3 分钟阅读🎧
乔尔·格鲁什在 TDS 播客上
最被低估的标准 Python 库
泰勒·福克曼——3 分钟阅读
面向数据科学家的集合
把 Python 脚本变成漂亮的 ML 工具
通过 Adrien Treuille — 7 分钟读取
介绍专为 ML 工程师打造的应用框架 Streamlit
从‘R vs Python’到‘R 和 Python’
通过 Parul Pandey — 7 分钟阅读
在单个项目中充分利用 Python 和 R’的优点。
用 Python 完成机器学习项目演练
通过将 Koehrsen — 15 分钟读取
把机器学习的碎片放在一起
使用 Apache Spark SQL 和数据框架的大规模 SQL——概念、架构和示例
由迪潘然(DJ)萨卡尔 — 21 分钟阅读
使用您友好的 SQL 与扭曲大规模争论,聚集,过滤数据!
我们也感谢最近加入我们的所有伟大的新作家,黄哲伦,伊恩·罗文,伊万·伊林,欧文·弗拉纳根,帕维尔·霍博诺斯(Midvel Corp) , Mykyta Solonko ,阿兰·坦吉,林多·圣天使,陈卿 汤姆·沃特曼,JR·克里奇,杰伊·布齐克,阿什顿·西杜,克谢诺·阿查里亚,拉兹·哈勒瓦等等很多人。 我们邀请你看看他们的简介,看看他们的工作。
联邦政府对人工智能的监管
老大哥来了?还是最终我们的救世主?
安东尼·加兰在 Unsplash 上的照片
2020 年 1 月 13 日,美国政府公布了针对美国人工智能(AI)监管的规则草案。(注:此稿公开征求意见截止到 3 月 13 日,所以还有机会行使你的民主话语权!)
背景
对于那些不熟悉这一过程的人来说,联邦政府经常被要求公布将适用于美国个人和实体的新规则,以供公众审查和评论。这一切都是因为一部名为《行政程序法》(APA)的法律。我之前在这里写过更多关于 APA 及其对数据科学规则的潜在影响的文章。
该草案一旦定稿,将正式发送给所有联邦政府机构,要求它们遵守该草案,直至其被撤销或修改。
让我们稍微倒退一下,了解一下美国人工智能监管的当前背景。2019 年 2 月 11 日,白宫发布了一项行政命令(E.O .)(具有法律效力),题为“加速美国在人工智能领域的领导地位”。
这份行政命令为联邦政府制定了人工智能政策的方向。值得注意的是,这五项要求坚定地确立了美国鼓励人工智能在美国发展和创新的政策,并呼吁为国际参与起草和使用标准。很明显,美国政府认为人工智能创新是经济增长的必要组成部分,这应该得到支持和培育。
“美国政府的政策是维持和加强美国在人工智能领域的科学、技术和经济领导地位。”
根据行政命令,美国人工智能法规的现行规则草案,以及政府增加人工智能劳动力的计划,人工智能标准的国际参与,以及政府对人工智能研究和能力的直接投资。
为什么这很重要?
如果你不习惯通读政府规章制度,可能会有点难以理解。例如,值得注意的是,管理和预算办公室(OMB)正在向所有联邦机构提议和发布这些规则。OMB 对其他联邦机构有监督权,并有权在许多方面规定机构的行动。
因此,这一 OMB 规则将指导联邦政府机构如何考虑、起草和发布(或放弃)所有关于在美国使用或监督人工智能的法规。
让我用一些可能的例子来说明这一点。在交通部能够监管美国的自动驾驶汽车之前,他们必须首先考虑这些 OMB 规则。如果司法部要发布关于法院应该如何在刑事判决中使用机器学习模型的指导或法规,他们也必须首先考虑这些规则。或者说,美国商务部将发布规则,规定亚马逊如何在广告中使用你的数据,他们也必须遵守这些规则。
草案怎么说?
首先,需要注意的是,这适用于政府机构将如何监管私营部门的人工智能,这并不控制政府将如何在内部使用和应用人工智能(这第二部分可能很快就会出现)。
第二,草案非常明确,政府的立场将是对人工智能的发展和创新进行最少的监管和最大的鼓励。因此,联邦政府将寻求消除人工智能发展的潜在障碍,除非绝对必要,否则不会引入对人工智能的监管(我们将在下面详细讨论这意味着什么)。这归结为:当有疑问时,政府不应该监管人工智能。
这可能会走到联邦政府利用其权力取消禁止人工智能发展的州和地方法律的地步——这可能会很有趣,因为几个州正在通过法律监管数据和人工智能在私营部门的使用。
机构指南草案
让我们看看草案对政府管制人工智能说了些什么。他们提议人工智能规则最重要的考虑因素是什么?
- **公众信任艾。**政府对公共部门人工智能的任何监管都必须鼓励“可靠、健壮和值得信赖的人工智能”,这些标准应该是首要的指导主题。
- **公众参与。**各机构应利用现有机制和要求,允许公众监督和参与任何人工智能法规或规则。正如《行政程序法》的大部分内容所强调的那样,这里的希望是,公众将会表达他们的担忧,并分享政府机构内部没有考虑到的信息,这些信息将会重塑法规。
- **科学诚信与信息质量。**规则草案要求各机构在设计人工智能法规时参与并依靠高质量的科学研究和信息。它还要求这项研究的透明度,以允许更新或矛盾的信息出现。这触及了人工智能模型有效性标准要求的核心。
- **风险评估与管理。**规则草案要求各机构采用基于风险的方法来处理人工智能法规。这承认人工智能会有缺陷,但允许在监管中进行基于环境的风险评估。因此,如果允许人工智能按照总体目标前进,一些风险是可以接受的,但造成“不可接受的伤害,或弊大于利的伤害”的人工智能可以受到监管。
- **收益与成本。**监管的一个长期主题是要求机构只有在监管的预期收益大于成本的情况下才追求规则。根据规则草案,这在人工智能规则中必须是真实的。
- 灵活性。规则草案要求机构以灵活的方式管理人工智能,以适应人工智能的快速增长和变化。这应该通过关注基于性能的监管而不是基于设计的监管来实现。这意味着规则不会规定“如何”,而是将重点放在人工智能的“什么”上。
- **公平和不歧视。**重要的是,该领域法规的重点突出了机构法规的必要性,以确保仅根据现有法律和规则的公平性和非歧视性。此外,重点应放在人工智能决策的结果和与现有流程相比的意外歧视上,作为基线。
- **公开和透明。**草案对透明度条例的要求必须“基于具体情况”。背景必须考虑潜在的危害、危害的大小、人工智能的技术状态以及人工智能的潜在好处。这是对法规的一个有趣的评估,因为它允许机构在决定是否要求私营部门人工智能的透明度时考虑一些主观决定。
- **安全保障。**在本节中,机构法规必须关注对人工智能应用中使用的数据的机密性、完整性和可用性的控制。目标是确保私营部门的复原力,保护私营部门免受不良行为者的攻击和剥削。
- **跨部门协调。**OMB 规则草案的最后一个要求是确保各机构规章之间的共享和共性。这将通过在法规草案公布之前对其进行机构间审查来实施。
非监管方法
因为规则草案将禁止管理人工智能,除非有特殊需要。在缺乏对人工智能法规的压倒一切的需要的情况下,机构应该考虑非法规的方法。
这些包括具体部门的指导方针或最佳做法。通常,这将是鼓励和颁布特定行业内的私营部门最佳实践,如运输、广告或银行。
试点项目和实验也将被允许免除监管,以允许在受控环境中进行创新和探索,而不是必须遵守可能阻碍创新的政府规则。
最后,政府应该依靠私营部门组织自愿遵守内部标准和控制,除非另有规定。
人工智能的政府数据
最后,OMB 规则草案规定,各机构必须进一步支持私营部门的人工智能创新,确保它们符合几项要求联邦机构尽可能公开政府数据集和模型的法律和规则。可公开获取的政府数据(大多数可通过 data.gov和机构网站获取)的持续增加旨在将行政数据归还给公众以供所有用途。这些数据是匿名和结构化的,但在许多领域有着巨大的潜力。
结论
这些规则草案只是美国联邦政府在美国和国际社会应对人工智能的最新举措。值得注意的是,几个州似乎正在寻求对人工智能技术和方法进行更进步的监管,这些规则可能会使联邦政府与州和地方政府的规则发生冲突。
联邦监管通常很慢,在美国尤其反动。很明显,当前的目标和策略将集中于减轻特定的威胁和伤害,但对人工智能领域采取不干涉的方法。
尚不清楚这将如何影响任何现行规则,也不清楚这种方法是否会导致美国人工智能创新和研究的上升。随着技术变得越来越普遍,随着普通公民越来越意识到潜在的好处和危害,我们应该密切关注这个领域——以及国际人工智能规则和法律。
联邦学习:用 PyTorch 简单实现 FedAvg(联邦平均)
实践教程
手机、平板电脑和智能手表等移动设备现在是主要的计算设备,已经成为许多人不可或缺的一部分。由于结合了丰富的用户交互和强大的传感器,这些设备承载了大量有价值的私人数据。基于这些数据训练的模型可以显著提高智能应用程序的可用性和功能。然而,这些数据的敏感性意味着也有一些风险和责任[1]。在这一点上,联邦学习(FL)的概念开始发挥作用。
在 FL 中,每个客户分散地训练它的模型。换句话说,模型训练过程是为每个客户单独进行的。只有学习到的模型参数被发送到可信中心,以组合和馈送聚合的主模型。然后可信中心将聚合的主模型发回给这些客户端,这个过程就这样循环下去[2]。
在这种情况下,我使用 IID(独立同分布)数据准备了一个简单的实现,以展示如何将运行在不同节点上的数百个不同模型的参数与 FedAvg 方法结合起来,以及该模型是否会给出合理的结果。该实现是在 MNIST 数据集上进行的。MNIST 数据集包含数字从 0 到 9 的 28 * 28 像素灰度图像[3]。
来自 MNIST 数据集的手写数字(图片由作者提供*)
- MNIST 数据集并不平等地包含每个标签。因此,为了满足 IID 要求,数据集被分组、混洗,然后分布,使得每个节点包含相同数量的每个标签。
- 为分类过程创建了一个简单的两层模型。
- 定义了用于 FedAvg 的函数。
这里,一次迭代完成如下。
- 由于主模型的参数和节点中所有局部模型的参数都是随机初始化的,所以所有这些参数都将互不相同。为此,主模型在节点中的本地模型的训练开始之前将其参数发送到节点。
- 通过使用这些参数,节点开始在它们自己的数据上训练它们的本地模型。
- 每个节点在训练它自己的模型时更新它的参数。训练过程完成后,每个节点将其参数发送到主模型。
- 主模型取这些参数的平均值,并将它们设置为新的权重参数,并将它们传递回节点,用于下一次迭代。
上面的流程是针对一次迭代的。这种迭代可以不断重复,以提高主模型的性能。
**注:**这里的目的不是为了提高分类算法的性能,而是将联邦学习得到的模型与集中式模型的性能进行比较。如果您愿意,可以使用更复杂的模型或调整超参数来提高性能。
如果你准备好了,我们开始吧!
功能解释
数据分发功能
-
【split _ and _ shuffle _ labels(y _ data,seed,amount): 数据集不包含相同数量的每个标签。为了将数据作为 IID 分布到各个节点,必须采集相同数量的数据。该函数根据每个标签给出的数量对它们进行分组,并在自身内部打乱顺序。请注意,这里混洗的是数据的索引,我们将在将来检索数据时使用它们。但是这些索引需要重新设置以避免关键错误。因此,定义了一个新列,并在那里保留了混排索引。
-
get _ iid _ sub samples _ indexes(label _ dict,number_of_samples,amount): 该函数将每个节点中的索引用每个标签的相同数量进行划分。(这里索引仍然是分布式的,而不是数据)
-
create _ iid _ sub samples(sample _ dict,x_data,y_data,x_name,y_name): 该函数将 x 和 y 数据分发给字典中的节点。
FedAvg的功能
-
***create _ model _ optimizer _ criterion _ dict(number _ of _ samples)😗**该函数为每个节点创建一个模型、优化器和损失函数。
-
get _ averaged _ weights(model _ dict,number_of_samples): 该函数取单个节点权重的平均值。
-
set _ averaged _ weights _ as _ main _ model _ weights _ and _ update _ main _ model(main _ model,model_dict,number_of_samples): 该函数将单个节点的平均权重发送到主模型,并将其设置为主模型的新权重。(调用 def get _ averaged _ weights(model _ dict,number_of_samples))
-
***compare _ local _ and _ merged _ model _ performance(number _ of _ samples:***该函数比较主模型和每个节点上运行的局部模型的精度。
-
send _ main _ model _ to _ nodes _ and _ update _ model_dict(main _ model,model _ dict,number_of_samples): 该函数将主模型的参数发送给节点。
-
***start _ train _ end _ node _ process _ without _ print()😗**该函数在节点中训练单个局部模型。
基于所有训练数据的集中式模型的性能如何?
首先,让我们检查一下,如果数据根本不分布到节点上,集中式模型的性能会如何?
— — — Centralized Model — — —
epoch: 1 | train accuracy: 0.8743 | test accuracy: 0.9437
epoch: 2 | train accuracy: 0.9567 | test accuracy: 0.9654
epoch: 3 | train accuracy: 0.9712 | test accuracy: 0.9701
epoch: 4 | train accuracy: 0.9785 | test accuracy: 0.9738
epoch: 5 | train accuracy: 0.9834 | test accuracy: 0.9713
epoch: 6 | train accuracy: 0.9864 | test accuracy: 0.9768
epoch: 7 | train accuracy: 0.9898 | test accuracy: 0.9763
epoch: 8 | train accuracy: 0.9923 | test accuracy: 0.9804
epoch: 9 | train accuracy: 0.9941 | test accuracy: 0.9784
epoch: 10 | train accuracy: 0.9959 | test accuracy: 0.9792
— — — Training finished — — -
此示例中使用的模型非常简单,可以执行不同的改进来提高模型性能,例如使用更复杂的模型、增加历元或超参数调整。然而,这里的目的是比较主模型的性能,该主模型是通过将根据它们自己的数据训练的局部模型的参数与根据所有训练数据训练的集中模型相结合而形成的。通过这种方式,我们可以深入了解联合学习的能力。
然后,开始我们的第一次迭代
数据被分发到节点
主模型被创建
定义节点中的模型、优化器和损失函数
字典的关键字变得可重复
主模型的参数被发送到节点
由于主模型的参数和节点中所有局部模型的参数都是随机初始化的,所以这些参数会互不相同。为此,主模型在节点中的本地模型的训练开始之前将其参数发送到节点。你可以查看下面的重量。
节点中的模型被训练
让我们比较一下联邦主模型和集中式模型的性能
第一次迭代前联合主模型与集中式模型(对所有测试数据)
由于主模型是随机初始化的,且尚未对其采取任何行动,因此在第一次迭代前,其性能非常差。在第一次迭代之后,主模型的精度提高到了%85。
Before 1st iteration main model accuracy on all test data: 0.1180
After 1st iteration main model accuracy on all test data: 0.8529
Centralized model accuracy on all test data: 0.9790
这是一次迭代,我们可以将主模型的参数发送回节点,并重复上述步骤。现在让我们检查当我们重复迭代 10 次以上时,主模型的性能是如何提高的。
Iteration 2 : main_model accuracy on all test data: 0.8928
Iteration 3 : main_model accuracy on all test data: 0.9073
Iteration 4 : main_model accuracy on all test data: 0.9150
Iteration 5 : main_model accuracy on all test data: 0.9209
Iteration 6 : main_model accuracy on all test data: 0.9273
Iteration 7 : main_model accuracy on all test data: 0.9321
Iteration 8 : main_model accuracy on all test data: 0.9358
Iteration 9 : main_model accuracy on all test data: 0.9382
Iteration 10 : main_model accuracy on all test data: 0.9411
Iteration 11 : main_model accuracy on all test data: 0.9431
集中式模型的准确度被计算为大约 98%。用 FedAvg 方法得到的主模型的准确率从 85%开始提高到 94%。在这种情况下,我们可以说,虽然 FedAvg 方法得到的主模型是在没有看到数据的情况下训练出来的,但其性能不可小觑。
可以访问https://github . com/ECE isik/fl _ public/blob/master/fed avg _ mnist _ iid . ipynb查看完整实现。
*您可以访问 github 页面。
[1]j . konen,H. B. McMahan,D. Ramage 和 P. Richtárik,“联邦优化:分布式机器学习用于设备智能”,第 1–38 页,2016 年。
[2] H. B. Mcmahan 和 D. Ramage,“从分散数据中进行深度网络的通信高效学习”,第 54 卷,2017 年。
[3] Y. LeCun、L. Bottou、Y. Bengio 和 P. Haffner。"基于梯度的学习应用于文档识别."IEEE 会议录,86(11):2278–2324,1998 年 11 月。
联合学习:Tensorflow 中的逐步实现
通过代码理解联邦学习
在本教程中,我实现了联邦学习(FL)的构建模块,并在 MNIST 数字数据集上从头开始训练了一个。在此之前,我简要介绍了这个主题,以便将代码中的要点讲清楚。如果这是你第一次学习 FL,我相信你会受益于我最近在 LinkedIn 上发表的关于这项技术的 介绍文章 。
介绍
高质量的数据像孤岛一样存在于全球各地的手机和个人电脑等边缘设备上,并受到严格的隐私保护法的保护。联合学习提供了一种将机器学习模型连接到这些脱节数据的聪明方法,而不管它们在哪里,更重要的是,不违反隐私法律。FL 不是根据经验法则将数据带到模型中进行训练,而是将模型带到数据中。所需要的只是托管数据的设备将其自身提交给联合过程的灵活性。
高质量数据的孤岛。照片由 Andrzej Suwara 在 Unsplash 上拍摄
FL 架构的基本形式是由一个位于其中心并协调培训活动的管理者或服务器组成。客户端主要是边缘设备,数量可能高达数百万。这些设备在每个训练迭代中至少与服务器通信两次。首先,它们每个都从服务器接收当前全局模型的权重,根据它们的每个本地数据对其进行训练,以生成更新的参数,然后将这些参数上传回服务器进行聚合。这种通信循环一直持续到达到预设的纪元编号或精度条件。在联邦平均算法中,聚合仅仅意味着平均操作。这就是 FL 模特训练的全部内容。我希望您抓住了这个过程中最突出的一点——我们现在交流模型权重,而不是移动原始数据。
联合学习布局。图像参考
现在我们清楚了什么是 FL 以及它是如何工作的,让我们继续在 Tensorflow 中从头构建一个,并在 Kaggle 的 MNIST 数据集上训练它。请注意,本教程仅用于说明。我们既不会深入研究 FL 中服务器-客户端通信如何工作的细节,也不会深入研究安全聚合的基础知识。由于这是一个模拟,客户端将仅仅由数据分片来表示,并且所有本地模型将在同一台机器上被训练。这里是我的 GitHub 库中的本教程完整代码的链接。不能再拖延了,让我们开始吧。
导入所有相关包
不要担心,我将在实例化它们各自的对象时提供每个导入模块的细节。
导入所有相关模块
读取和预处理 MNIST 数据集
我在这里使用的是来自的 MNIST 数据集的 jpeg 版本。它由 42000 个数字图像组成,每个类别保存在单独的文件夹中。我将使用这段代码片段将数据加载到内存中,并保留 10%的数据用于稍后测试训练好的全局模型。
读取和处理 MNIST 数字数据
在第 9 行,每个图像将作为灰度级从磁盘中读取,然后变平。扁平化步骤非常重要,因为我们稍后将使用 MLP 网络架构。为了获得图像的类标签,我们在第 11 行拆分它的路径字符串。希望你注意到我们还在第 13 行将图像缩放到[0,1]来减弱不同像素亮度的影响。
创建训练测试分割
创建训练/测试数据分割
这个片段中有几个步骤。我们应用了前面代码块中定义的 load 函数来获取图像列表(现在在 numpy 数组中)和标签列表。之后,我们使用 sklearn 的LabelBinarizer
对象对标签进行热编码。接下来,数字 1 的标签不再是数字 1,而是现在的形式[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
。有了这种标签风格,我们将能够使用 Tensorflow 中的cross-entropy
损失作为我们模型的损失函数。或者,我可以让标签保持原样,而使用sparse-categorical-entropy
损失。最后,我使用 sklearn 的train_test_split
对象将数据拆分成比率为9:1
的训练/测试。
作为数据碎片的联邦成员(客户机)
在 FL 的实际实现中,每个联邦成员都有自己的独立数据。请记住,FL 的目的是将模型传递给数据,而不是相反。这里的碎片创建步骤只发生在实验中。我将把训练集分成 10 份,每个客户一份。我写了一个名为create_clients
的函数来实现这个。
将客户端创建为数据碎片
在第 13 行,我使用前缀(initials
)创建了一个客户端名称列表。在第 16–20 行,我压缩了数据和标签列表,然后随机化了结果元组列表。最后,我在第 21 行根据期望的客户端数量(num_clients
)从元组列表中创建了碎片。在第 26 行,返回了一个字典,其中包含每个客户机的名称作为键,数据份额作为值。现在,让我们将这个函数应用于我们的训练数据集。
客户字典
处理和批量处理客户和测试数据
接下来就是把每一个客户端的数据处理成 tensorflow 数据集,进行批量处理。为了简化这个步骤并避免重复,我将这个过程封装到一个名为batch_data
的小函数中。
为培训准备客户数据的功能
我相信您还记得,每个客户端数据集都是从create_clients
出来的(数据,标签)元组列表。在上面的第 9 行,我将元组分成单独的数据和标签列表。然后,我从这些列表中创建了一个混洗和批处理的 tensorflow 数据集对象。
在应用下面的函数时,我也将处理测试集,并把它放在一边以备后用。
为培训准备每个客户端数据
创建多层感知器(MLP)模型
我在介绍部分没有提到的一点是,FL 最适合参数化学习——所有类型的神经网络。机器学习技术,如 KNN 或 it likes,只是在学习时存储训练数据,可能不会从第一语言中受益。我正在创建一个 3 层 MLP 作为我们分类任务的模型。我希望你还记得我们之前导入的那些 Keras 模块,这是它们适合的地方。
建筑模型:MLP
为了构建一个新的模型,将调用build
方法。它需要输入数据的形状和类的数量作为参数。对于 MNIST,形状参数将是28*28*1 = 784,
,而类的数量将是 10。
现在是时候定义一个optimizer
、loss
函数和metrics
来编译我们的模型了。
清除优化器、损失函数和度量
SGD 是我的默认优化器,除非我有理由不使用它。损失函数是categorical_crossentropy.
,最后,我将使用的度量是accuracy
。但是在衰变的论点中有些东西看起来很奇怪。什么是comms_round
?这只是我在训练期间将运行的全局纪元(聚合)的数量。因此,不是像你可能熟悉的那样,学习率相对于局部时期的数量而衰减,这里我想相对于全局聚集的数量而衰减。这显然是一个超参数选择的选择,但我发现它在实验中工作得很好。我还发现了一份学术报告,其中这种设置也有效[1]。
模型聚合(联合平均)
到目前为止,我所做的一切都非常符合深度学习管道的标准。当然,数据分区或客户机创建位除外。我现在将转移到联邦平均(FL 的标准算法),这是本教程的全部内容。我使用的数据是水平分区的,因此我将简单地进行组件式参数平均,这将根据每个参与客户端贡献的数据点的比例进行加权。这是我使用的联邦平均方程,它是联邦学习的先驱作品之一[2]。
不要让方程中复杂的数学符号欺骗了你,这是一个非常简单的计算。在右边,我们根据他们训练时记录的每个数据点的体重值来估计每个客户的体重参数。在左侧,我们对这些参数中的每一个进行了缩放,并对所有组件进行了求和。
下面我将这个过程封装成三个简单的函数。
实现 FedAvg
(1) weight_scalling_factor
计算一个客户端的本地训练数据占所有客户端持有的整体训练数据的比例。首先,我们获得客户端的批量大小,并使用它来计算数据点的数量。然后,我们在第 6 行获得了总体的全局训练数据大小。最后,我们在第 9 行计算了比例因子的分数。这肯定不是现实世界应用中的方法。训练数据将是不连续的,因此没有一个客户端能够正确地估计组合集的数量。在这种情况下,在每个本地训练步骤之后,当用新参数更新服务器时,每个客户端将被期望指示它们训练的数据点的数量。
(2) scale_model_weights
根据在(1)中计算的缩放因子的值,缩放每个局部模型的权重
(3) sum_scaled_weights
将所有客户的加权求和。
联合模型训练
外语训练逻辑
训练逻辑有两个主要循环,外部循环用于全局迭代,内部循环用于遍历客户端的本地训练。还有一个隐含的第三个问题,它考虑了本地纪元,将由我们的model.fit
方法中的纪元参数来处理。
开始时,我构建了输入形状为(784)的全局模型,类的数量为 10 —第 2-3 行。然后,我进入了外部循环。首先在第 9 行获得全局模型的初始化weights
。第 15 行和第 16 行打乱了客户机的字典顺序,以确保随机性。从那里,我开始迭代客户培训。
对于每个客户端,我创建了一个新的模型对象,编译它,并将其初始化权重设置为全局模型的当前参数——第 20–27 行。然后,本地模型(客户端)被训练一个时期。训练之后,新的权重被缩放并附加到第 35 行的scaled_local_weight_list
上。当地培训到此为止。
回到第 41 行的外循环,我总结了所有缩放的局部训练权重(当然是按组件),并将全局模型更新为这个新的集合。这结束了一个完整的全球训练时代。
按照comms_round
的规定,我运行了 100 个全局训练循环,并在第 48 行测试了经过训练的全局模型,每次通信后都是我们的测试数据。下面是测试逻辑的片段:
测试逻辑
结果
有 10 个客户端,每个客户端在 100 轮全局通信的基础上运行 1 个本地纪元,以下是截断的测试结果:
新加坡元与联邦平均
是的,我们的 FL 模型结果非常好,经过 100 轮沟通后,测试准确率达到 96.5%。但是它与在相同数据集上训练的标准 SGD 模型相比如何呢?为了找出答案,我将根据组合的训练数据训练一个单一的 3 层 MLP 模型(而不是像我们在 FL 中那样训练 10 个)。请记住,组合数据是我们在分区之前的训练数据。
为了确保公平竞争,我将保留除批量之外的所有用于 FL 培训的超级参数。我们 SGD 的批量将是 320,而不是 32。通过这种设置,我们确信 SGD 模型在每个时期看到的训练样本的数量与全局模型在 FL 中每个通信回合看到的完全相同。
SGD 培训
这就是了,SGD 模型在 100 个时期后的测试准确率为 94.5%。在这个数据集上,FL 的表现比 SGD 稍好,这难道不令人惊讶吗?不过,我警告你不要对此过于兴奋。这种结果在现实世界中不太可能出现。耶!客户端持有的真实世界的联邦数据大多是非独立且同分布的(IID)。
例如,我们可以通过构建上面的客户端碎片来复制这个场景,使每个客户端碎片都包含来自单个类的图像—例如,client_1 只包含数字 1 的图像,client_2 只包含数字 2 的图像,依此类推。这种安排会导致 FL 模型的性能显著下降。我将此作为一个练习留给读者去尝试。同时,这里有一段代码,您可以用它来以非 IID 的方式分割任何分类数据。
创造非 IID 碎片
结论
通过本文,我介绍了联邦学习的概念,并带您了解了它的基本形式的 tensorflow 实现。我鼓励你查看我最近在 LinkedIn 上的文章,这里是对这项技术更广泛的介绍,特别是如果你不清楚它的工作原理,或者想了解更多关于如何应用它的信息。对于想要更深入研究这个主题的研究人员来说,有许多关于 arxiv.org/csT2【FL】的期刊,主要是推动其实施并解决其众多挑战。
参考
[1]使用非 IID 数据的联合学习,赵月等人,arXiv: 1806.00582v1,2018 年 6 月 2 日
[2]从分散数据中进行深度网络的通信高效学习,H. Brendan McMahan 等人,arXiv:1602.05629v3 [cs .2017 年 2 月 28 日
FedSpeak——如何构建 NLP 管道来预测央行政策变化
实践教程
用深度神经网络分析决策者谈话指南
(图片由作者创作)
介绍
这篇博客描述了我如何在过去的项目中通过 NLP 技术分析央行政策。源代码可在 github repo 获得。
商业背景
FOMC 有八次例会来决定货币政策。每次会议,它都在网站上发布新闻发布会的记录、声明以及脚本。除了这种定期会议,成员的发言和证词也在网站上。
在会议上,政策制定者讨论、投票和决定货币政策,并公布决定以及他们对当前经济形势和预测的看法,包括 2012 年以来的前瞻性指导。各国央行打算在其出版物中表明其潜在的未来货币政策,以此作为市场沟通的一种手段。
预测输入(由作者创建)
这个项目的目标是在 FOMC 出版的文本中发现潜在的特征。首先,我将机器学习应用于经济指数,以观察这些数字数据的预测性能。然后,在传统的机器学习技术中加入预处理过的文本数据作为附加特征,看它是否包含有意义的信息。最后,应用深度学习技术,如 LSTM/RNN 和伯特,看看这些能否更好地预测每次 FOMC 会议上的加息/降息。
该项目的整个过程(由作者创建)
1.检索市场数据
每日美联储利率和主要经济指数可以从圣路易斯联邦储备银行的经济研究网站获得,该网站名为 FRED :
- 联邦利率
- 国内生产总值
- 消费物价指数/ PCE
- 就业和失业
- 零售和家庭销售
制造业 PMI 和服务业 PMI(原名“非制造业指数或 NMI”)由 ISM(供应管理学会)网站发布。
每日国债收益率可以从美国财政部网站以 xml 格式下载。
探索每个网站上的数据细节很好,但使用 Quandl 更方便,它提供了 Web APIs 和库,以相同的方式检索所有数据。以上所有数据都是公开的,个人使用也是免费的,但是你应该根据你的目标,在原始资料中检查许可条款。
一旦创建了 Quandl 帐户,就会提供 API 密钥。例如,您可以像这样在pip install quandl
之后下载 python 中的数据:
2008 年,美联储将目标联邦利率从单一利率改为一个区间,因此串联两个区间证明了下限或上限观点。
联邦基金利率,目标下限(由作者创建)
2.检索文本数据
所有 FOMC 的出版物都可以在 FOMC 网站上找到。你可能会注意到网站包含每次会议的材料,但内容会随着时间的推移而变化。此外,除了常规会议之外,还有不定期的会议和电话会议。一些文本是 html 格式的,而另一些则是 pdf 格式的。甚至还有一个不同的历史数据网站,页面结构也各不相同。
从 FOMC 会议日历下载以下文本:
- 声明 —在每次 FOMC 会议后立即发布
- 会议纪要 —在每次 FOMC 会议后三周提供,因此可能无法用于最近的会议
- 新闻发布会记录——每次 FOMC 会议都有,但 2011 年才开始提供
- 会议记录 —会议五年后可用,因此不能用作预测的输入,但仍是查看旧会议详细背景的良好来源
- 演讲 —文字记录发表在这一页,我使用了两次会议之间发表的主席演讲
- 证词 —各种证词文本也发表在这一页我用半年度货币政策报告向国会报告
当文本是 HTML 格式时,BeautifulSoup 将完成这项工作。使用 textract 提取 PDF 和 re 模块,通过正则表达式进行搜索。
3.初步分析
为了看看这些文本是否包含一些预测美联储利率的有用见解,我使用了拉夫兰和麦当劳情绪词表来衡量声明的情绪。这本字典包含几千个出现在财务文件中的单词,如 10K,10Q 和收益电话,分为积极,消极等。它包括不同形式的单词,因此不应应用词干分析或词条解释。我运用了一个简单的技巧将情绪转化为否定(例如,不能,不是,不)。请注意,您需要获得必要的商业使用许可证。
首先,画出每句话中正面词和负面词的数量,取其差值作为净情绪。正字数和负字数高度相关,平均值为正。
历年感悟(作者创作)
接下来,将移动平均线应用于净情绪,以查看衰退周期的趋势图。16 项声明的移动平均指数在经济不确定时大多会下降。这表明,净情绪的方向在一定程度上与宏观经济相关,尽管在每次 FOMC 会议上用它来预测会过于嘈杂。
情绪和衰退的移动平均线(由作者创建)
此外,在每次 FOMC 会议上,将净情绪的移动平均值与实际的美联储利率决策进行对比。这与美联储的目标利率有一定的相关性,但在金融危机期间,不容易看到利率处于有效下限,并采取了量化宽松政策。我认为 QE 的声明是一个降低利率的事件。
情绪和货币政策的移动平均线(由作者创建)
以下是在 matplotlib 中生成此图的一些示例代码:
4.预处理经济指数
当 FOMC 决定货币政策时,与之前数据的差异也很重要。对于每个指数,取所有指数与前期和上年同期的差值。
经济指数(由作者创建)
首先使用seaborn.heatmap()
检查美联储利率决策和经济指数之间的相关性。PMI 相关性较高,CPI 与费率决定关系不大。
经济指数和利率决策之间的相关性(由作者创建)
然后,计算这些数字的移动平均值,检查与速率决策的相关性,并选择高度相关的字段作为特征。
移动平均线的相关性(由作者创建)
例如,PMI 值是输入特征候选之一。seaborn.kdeplot()
提供漂亮的分布图。
每个下一个费率决策的 PMI 值分布(由作者创建)
作为特征工程的一部分,计算泰勒规则,看看是否可以使用一阶导数和与美联储利率的差异。美联储在其网站上发布了政策制定者如何使用经济指数数据。这里,从原始数据计算泰勒规则、平衡接近规则和惯性规则。
这一结果看起来与他们的出版物相符,而且这些理论利率和实际美联储利率之间的相关性相当高。
理论费率(由作者创建)
不要忘记检查缺失的值,并用 0 或平均值/中值来估算这些值。还要删除一些没有足够输入数据或缺少输出标签的记录。机器无法从部分丢失的输入中学习,因为它无论如何都需要猜测丢失的数据意味着什么。
每次 FOMC 会议时可用的最新数据被用作决策的基本输入,并添加文本数据作为附加输入,以查看预测是否可以改进。
5.预处理文本数据
在过去的 25 年里,大约有 200 个决定。根据型号,由于缺少数据或可用时间,一些输入无法使用。
每个文档类型的输入文档计数(由作者创建)
最常用的单词(由作者创建)
词云(由作者创建)
在文本处理过程中,您可能面临的一个常见问题是如何在机器学习中处理长文本。大多数基于神经网络的算法都无法分析像 10,000 个单词(最多 500 个)这样的长文本。我们的大多数输入文本太长,无法作为一个完整的文档进行分析。
每句话的字数(由作者创造)
这个问题的典型解决方案是或者对文档向量使用其他算法,例如 JAC card/余弦相似度,或者找到分割长文本的方法,或者使用一些技术来缩短,例如文本摘要。
这里使用的一个简单的解决方案是文本分割技术,按字数(例如 200 个单词,重叠 50 个单词)分割文本,如下所示。这是一种简单的自动化方法,但很容易丢失上下文,因为提取的 200 个单词可能包含也可能不包含相关文本,甚至离题。
另一个问题是数据不平衡—在本例中,比率决策有 60%以上的机会是“保持”,而可用的决策只有大约 200 个,因为会议每年举行八次。如果没有足够的数据,机器学习很容易过度适应训练数据。
按文档类型列出的输入文档数(由作者创建)
文本数据处理已经以如下方式完成,这是 NLP 的常见情况。
NLP 管道(由作者创建)
6.建立和训练 ML 模型
在高层次上,该模型采用文本输入和元输入来预测三个类别:提高、保持或降低,如下所示。关键是如何将文本输入和数字输入结合起来,并且有不同的实现方法。
总体流程(由作者创建)
除了基线模型之外,这里还构建了以下六个模型。所有的模型都是在 pytorch 中构建和训练的,源代码可以在 Github repo 中找到,本文摘录了其中的一些部分。
0.基线模型
基线流程(由作者创建)
这不使用文本输入,而只接受元输入。首先比较具有默认参数的 14 个不同分类器,以快速获得基线性能。
F1 由 14 个不同的分类器评分(由作者创建)
然后,应用 RandomizedSearchCV 和 GridSearchCV 来寻找最优的超参数,并决定使用随机森林作为基础,因为它产生具有合理特征重要性的最佳结果。StratifiedKFold 用于交叉验证。
网格搜索 CV 结果(由作者创建)
困惑矩阵(由作者创建)
学习曲线告诉我们,模型过度适应训练数据,更多的数据可能会提高性能。查看混淆矩阵,它未能预测“降低”和“提高”事件。
功能重要性(由作者创建)
查看混淆矩阵,它未能预测“降低”和“提高”事件。
也进行了系综和叠加,但没有提高性能,因为这里的根本问题是缺乏足够的数据。
A.余弦相似性
余弦相似性流程图(由作者创建)
Tfidf 使用初步分析中使用的 Loughran-McDonald 字典对文本进行矢量化,并计算两个连续会议之间的余弦相似度。该值是文本方向的变化程度(即向量的余弦),其可以指示策略变化。然后将其与基线模型中使用的经济指数相结合。
B.Tfidf
Tfidf 流程图(由作者创建)
使用 Tfidf 向量本身作为输入,而不是余弦相似度。只有当 Tfidf 向量直接保存关于速率变化的有意义的信息时,这才会起作用。使用上一步中标记化的文本,通过 FunctionTransfomer 将 Tfidf 向量与非文本输入连接起来。
C.LSTM
LSTM 流程图(由作者创建)
LSTM ( 长短时记忆)是一种流行的 RNN ( 递归神经网络)架构,可以保存长时记忆和短时记忆,用于序列学习。有许多改进版本,如双向 LSTM,而这里使用的是一个简单的普通模型。深度神经网络的输出与漏失和密集层后的经济指标相结合。
然后,将输入分为文本数据和数字数据。定制数据加载器以产生两种类型的输入。训练过程与 LSTM 处理文本的通常情况相同。
D.LSTM+手套
LSTM +手套工艺流程(由作者创建)
之前的 LSTM 模型创建了自己的单词嵌入,但也有预先训练的嵌入。这里使用全局向量进行单词表示(GloVe) 由维基百科和 gigaword (6B tokens)训练。这个想法是,预先训练的单词表示将提高随机初始化模型的性能。
训练步骤与之前的 LSTM 模型相同。
E.伯特
BERT 流程图(由作者创建)
BERT,或来自 Transformers 的双向编码器表示,是一种基于 transformer 的语言模型,与 Google Research 在 2018 年发布的 RNN 相反。这里使用的模型是预训练的 BERT_BASE,这是一个具有 12 层、768 个隐藏单元、12 个头的深度神经网络,产生 110 万个参数,并在维基百科和图书语料库上进行训练。除了模型和伯特自己的符号化,建筑的其余部分与上面基于 LSTM 的模型保持相同。通常对模型使用transformers.BertForSequenceClassification
就足够了,但是这里需要创建自己的定义来连接文本和非文本输入。
F.BERT +前期情绪分析
BERT +前期情绪分析流程(由作者创建)
最后,我采用了另一种方法——不是直接在 FOMC 文本上训练模型,而是首先在其他金融文本上训练模型以进行情感分析任务。然后使用经过训练的 BERT 模型来分析 FOMC 文本中每个句子的情感,并计算情感得分,然后对每个文档进行汇总,并将其用作另一个 ML 模型的输入,以预测 FOMC 的决定。
结果
下面是测试模型之间的分数对比。深度神经网络模型表现不佳,这基本上是由于缺乏足够的数据来训练这些复杂的模型。带有情绪前分析的最后一个模型优于其他模型,但需要进一步检查这种改进是否具有有意义的显著性和一致性,而不仅仅是由于任何额外的输入。
每个模型的性能分数(由作者创建)
结论
我们研究了 FOMC 文本数据是否包含有用的洞察力,以预测美联储在下一次 FOMC 会议上的目标利率决定(即提高、保持或降低)。我们可以从文本中观察到一些有用的信息,从而更好地预测 FOMC 的决策。然而,我们不能通过神经网络来提高基于文本的预测性能。这部分是因为对于每个非常长的文本,有少量的测试数据要训练。
作为未来的工作,有两个主要方面需要改进:
- 解决缺乏足够训练数据的问题——模型显然过度适应训练样本,未能很好地概括,特别是助推算法容易过度适应。这里考虑了超参数调整和插补。此外,通过合成方法配置模型和分割数据以增加训练数据可能是有益的。
- 提高输入文本质量——输入文本包含大量与美联储目标利率决策无关的段落。例如,有关于法规、组织结构和基础设施的信息。过滤掉不太相关的输入将提高模型预测的准确性以及训练效率。
注意,这篇文章中的代码只是一些摘录。完整源代码请参考 Github repo 。
Fedspeak?或者只是另一袋话?
杰罗姆·鲍威尔——现任美联储主席。鸣谢:维基共享。
本文介绍了“fed tools”Python 包,提供了一个基本单词包算法的实际实现。
最后的数字。现在,我们可以使用按钮和下拉菜单来选择感兴趣的项目和时间段。作者创建的图像。
TL DR : Github Repo 和 FedTools 包。
那么,什么是 Fedspeak 呢?
“Fedspeak”也被称为“Greenspeak”,最初是由艾伦·布林德(Alan Blinder)定义的,用来描述美联储董事会主席在发表模糊、不置可否或模棱两可的声明时使用的“英语方言”。近年来,由于全球金融机构自然语言处理(NLP)能力的提高,美联储政策沟通发生了巨大的变化。
自然语言处理
自然语言处理(NLP)是人工智能的一个领域,它使机器能够与人类语言进行交互,分析,理解和解释人类语言的含义。NLP 有许多子领域,例如自动摘要、自动翻译、命名实体识别、关系提取、语音识别、主题分割和情感分析。
这篇文章关注于通过使用一个“单词包”(BoW)算法来实现一个基本的情感分析。BoW 算法对于从文本文档中提取特征是有用的,这些特征可以随后被合并到建模管道中。
包话(鞠躬)
BoW 方法非常简单,可以在不同的文档类型上实现,以便从文档中提取预定义的特征。在高层次上,单词包是文本的表示,它描述了文档中一组预定单词的出现。这以两个步骤为特征:
1)必须选择预定单词的词汇表或“字典”。
2)测量已知单词的存在。这被称为“包”,因为所有关于词序的信息都被丢弃了。该模型仅考虑文本中预定单词的出现次数。
实际实施
现在我们已经概述了 BoW 算法,我们可以通过 7 个简单的步骤来实现它。
第一步是安装我们将使用的软件包和模块:
其次,我们需要获得联邦公开市场委员会(FOMC)的历史声明,可以在这里找到。然而,新的" FedTools " Python 库使我们能够自动提取这些信息:
现在,我们有一个熊猫数据框架,在一栏中有“FOMC 声明”,按 FOMC 会议日期索引。下一步是遍历每条语句并删除段落分隔符:
现在,我们必须考虑我们希望使用哪一个预定单词的字典。为了方便起见,我们使用蒂姆·拉夫兰和比尔·麦克唐纳的情感词汇列表。由于这个列表很长,所以不包含在本文中,但是可以从合并代码中获得,保存在 Github repo 中。
接下来,我们定义一个函数来确定一个词是否是否定的。该函数检查输入的单词是否包含在预先确定的“求反”列表中。
现在,我们可以实现 BoW 算法,在检测到的单词之前考虑三个单词中的潜在否定者。该函数使我们能够对检测到的正面和负面单词进行计数,同时还将这些单词保存在单独的 DataFrame 列中。
build_dataset
函数使用 Loghran & McDonald 字典lmdict
的输入参数,为每个 FOMC 语句迭代调用bag_of_words_using_negator
函数。
最后,plot_figure
函数调用build_dataset
函数,随后构建输出的交互式可视化。
调用 plot_figure 函数,图形显示如下:
最终输出。作者创建的图像。
完整的代码可以在 Github Repo 中找到,开源的 FedTools 包可以通过 pip install获得。
给机器喂食——我们如何为它们数字化世界。
感谢 COVID19。
海尔林在 Unsplash 上拍摄的照片
最近,在被封锁了几个星期后,我们第一次在城市的一个公园里烧烤。空气中弥漫着春天的气息。太阳正在描绘一幅美丽的画面。我的朋友们在草丛中发现了一朵正在生长的花,这是今年第一次见到这种花。
米歇尔·卡纳摄
我们的第一反应是把花拍下来,分享到社交媒体上。我开始好奇我们行为背后的动机。我们没有碰这朵花,没有观察,也没有闻它。注意到花的存在后几秒钟,我们的第一反应是分享它的图像。
在那个特别的时刻,我意识到我是多么的健忘。我一生中拍过成千上万张照片。
你有多少次通过记录、数字化并最终分享你的生活?
克里斯蒂娜·萨拉戈萨在 Unsplash 上的照片
感觉很奇怪,我们都变得健忘了。我们用视频、照片或音频捕捉一天中的瞬间。我们也将我们的想法转化为文字、表情符号或图画,并通过手机、可穿戴设备、汽车和电脑进行处理。
我们相信数字存储与我们的记忆,我们很少访问以后。我问我的朋友,他们是否有时会回去观看这些照片,并试图回忆与此相关的时刻。我的朋友花了一点时间思考,并认识到他们很少浏览过去的照片。没有时间去看过去,我们常常忙于记录现在。
当危机发生时,它留给我们某些时刻的记忆。人们在情感上是紧密相连的,你可以从特定的事件中嗅到硝烟。瞬间冲破喧嚣。
每个人都会记得在危机期间他们在哪里。
当我们在冠状病毒中导航我们的新常态时,社会距离大规模地加速了我们记忆的数字化。当这个领域结束,目前没有人知道这是什么时候发生的,我们的公共空间将比以前更加空旷。然而,作为社会人,我们需要联系才能生存。
我们大多数人现在可能正坐在家里。在家工作在很大程度上已经成为一种新的工作方式。孩子们在网上接受学校教育。父母正在家里吃午饭。
图片由 GDJ 在 Pixabay 拍摄
我们看到的是互联网上的巨大变化。内容创作飞速发展。与内容的互动率也在飞速上升。人们渴望看新电影,玩新游戏。娱乐和游戏产业正在转型。
业余玩家和职业玩家正在上传他们玩游戏时录制的数百万个视频。像 Zoom 这样的会议工具正在传播,因为它们可以远程连接人们。我每天都在使用这些工具会见遍布世界各地的同事、朋友和家人。
据苹果和百事可乐的前首席执行官、Zeta 的联合创始人约翰·斯卡利称,其结果是,即将发生的最重大的技术变革是数据爆炸。我们已经知道数据量每两年翻一番。数据不仅仅是人类创造的。机器已经学会在没有我们干预的情况下捕捉我们生活中的瞬间。
由于 COVID19,更多的机器将为其他机器数字化世界。这是传感器时代,物联网时代。
我们很快就会在一切事物中发现传感器。索尼刚刚宣布了世界上第一个集成 AI 的图像传感器,使其可以在没有任何额外硬件的情况下执行计算机视觉任务。据估计,世界上很快就会有万亿个传感器。
我们正在进入一个连接性更强、数据更多的十年。
例如,一辆 L2 自动驾驶的无人驾驶汽车可以在一小时内产生大约 25Gb 的数据。如果我们有数百万辆汽车同时行驶,就不可能处理数据流。
我们所有的无线网络都没有为我们已经经历的带宽利用做好准备。我和我的朋友都暂停了。
图片由 Gerald 在 Pixabay 上拍摄
随着旅游业被颠覆,虚拟旅游应运而生。人们正在设计全息传输虚拟现实体验也是为了体育娱乐。
COVID19 疫情改革医疗保健。远程医疗的下一步是包含物联网设备,以远程执行数字诊断。
所有这些都会产生大量的数据。
根据约翰·斯卡利的说法,如果你看看 COVID19 以外的地方,在 90 年代后期,有一项对所谓的暗光纤的重大投资。数千亿美元用于建设手机信号塔和光纤电缆网络。那时候,我还是个学生。我清楚地记得这项投资如何导致了万维网的快速发展,随后是创造了我们第一份工作的网络公司现象。
这项投资还创造了从 2G 到 3G 网络的过渡,支持照片和视频的传输。根据约翰·斯卡利的说法,当史蒂夫·乔布斯在 2007 年推出他的 iPhone 时,如果没有在 90 年代末对暗光纤的投资,就不会有这么大的成功。
互联网海底光缆网络—图片由 Infrapedia 提供
今天,在 COVID19 的帮助下,由于 5G,数据通过互联网边缘以更快的速度传输,世界变得更加数字化。这是蜂窝网络的第五代技术标准,下载速度高达 10 Gbps。
我们的智能手机和我们周围的传感器都将接入互联网高速公路。使用慢速 WiFi 或有线连接的实际最后一英里将会消失。
COVID19 让世界在线。5G 为人类和传感器打开了高速公路,为机器提供食物。
据 Zeta 联合创始人、董事长兼首席执行官大卫·a·斯坦伯格称,每周有数万亿营销信号从数十亿人那里获取数据。我要说,这是一个相当惊人的数字。
我们将会看到大量的数据。我们的记忆、行为、意图和梦想都在为机器学习算法提供信息。今天,机器智能可以整理海量数据,找到隐藏在我们面前的联系。
JDG 在 Pixabay 上的图片
根据 Shoshana Zuboff 的说法,机器智能指的是复杂的高度专业化的计算系统,这些系统在数据森林而不是单棵树上进行训练。她通过将注意力转移到机器的目标而不是技术上来描绘机器智能。机器智能实现了将原材料(我们的数据)转化为高利润算法产品的操作。其中之一就是定向广告。
少数几家最有价值的在线广告公司成功的关键是个性化。
这就是机器智能如何突破噪音,通过每天数百万条信息。这一切都围绕着数据和捕获几乎任何数据的能力。这些广告公司试图做的是让人们尽可能接近交易,并在他们的竞争对手或人们自己之前理解他们的意图。
科学杂志在 Unsplash 上拍摄的高清照片
冠状病毒危机是一个改变世界的事件。未来不是过去的样子。新的力量在于行动。传感器也成为执行器。
我们越依赖机器智能,我们就越把它作为指导。一旦被咬,苹果变得不可抗拒。
虚拟助手可以巧妙地鼓励设计师而不是个人做出选择。可以想象机器智能被用来大规模修改人的行为,并预测行为未来。
感谢 COVID19,我们正在将地球上最古老、最复杂的模拟系统转变为数字形式:我们的大脑。
当我们选择的时候,我们会知道这个选择是不是我们的吗?
Artyom Kim 在 Unsplash 上拍摄的照片
回到我们在公园草地中央发现的那朵被春天的阳光照亮的花。剩下的时间,我和朋友们都在凝视着它的美丽。我在想,我们刚刚收集到的这种关于花的模拟记忆,在一个日益数字化的世界里会有什么意义。
观点是我自己的,不是我雇主的观点。
从抑郁到想自杀
变更数据
用多元线性回归研究抑郁症状的进展
根据美国国家心理健康研究所的数据,2017 年,自杀是美国第十大死亡原因,在 10 至 34 岁的人群中排名第二。然而,自杀也是最耻辱的话题之一。人们避免谈论自杀意念,这使得很难防止抑郁症状的发展。这也使得我们更难了解是什么让人们从感觉没有动力或抑郁到有自杀的想法。
那么是什么导致人们有时情绪低落而想到自杀呢?
这项分析的目的是确定导致抑郁症状进展的一些关键因素。我希望这个项目可以为未来的自杀预防工作增添一些曙光。
数据
国家健康和营养检查调查( NHANES )是疾病控制和预防中心的一部分,它收集并发布了大量来自生活在美国的非制度化平民的采访和医疗检查。
为了准确地代表总体,NHANES 在每个周期对代表不足的总体进行过采样。该数据集特别对西班牙裔、非西班牙裔黑人和亚洲人、处于或低于贫困线 185%的人以及 80 岁及以上的人进行了过采样。
NHANES 网站为每个小节提供单独的 SAS XPT 文件。在这项分析中,我从人口统计、医疗条件和物质使用等主题中串联了其中的 21 个小节。
2017 年至 2018 年间,共有 8704 名参与者完成了面试和体检。由于我对了解轻度抑郁症状如何发展为致命的很感兴趣,我缩小了数据集,只包括那些报告说最近经历过抑郁或绝望困扰的人。这导致了总共 1222 人,占总数据的 14%。
精神健康指数(MHI)
为了量化一个人的心理健康或抑郁症状,我创建了一个名为心理健康指数(MHI) 的变量,它是十份抑郁筛查问卷的累计答案数。每个问题都有一个 4 分制的等级,表明他们在过去两周内被这些抑郁症状困扰的频率。最终的 MHI 范围从 0 到 30。该图显示了至少回答一半问卷(n = 5087)的所有人中每个答案的百分比。(一些缺失值是从其他最相关问题的答案中推断出来的。)
这是我们子集内 MHI 的总体分布。
MHI 的总体分布显示,大多数参与者都在 5 点左右。概括地说,高 MHI 分数表明抑郁症筛查者的报告分数更高。大多数回答这 10 个问题的人报告 MHI 为 0(不包括在分析中)。
我们组有 59%的女性,年龄分布相对均匀,从 18 岁到 70 岁不等,一些老人超过 80 岁。
整体流程
基于探索性分析和我在自杀预防中心的经历,我关注了三个主要话题:人口统计学、现有的医疗条件(其中一些我称之为“绝望”衡量标准)和物质使用。所有过程都是用 Python 完成的。在此过程中检查的个别特征如下。
人口统计 年龄、性别、家庭人数、家庭中成年人人数、家庭中儿童人数、收入、成人人均收入、家庭人均收入、婚姻状况、退伍军人、教育水平
医学状况(限于选择慢性状况) 肥胖、身体残疾、癌症、自癌症诊断以来的年数
物质使用 吸烟(或戒烟)、戒烟年数、开始吸烟年数、大麻使用、可卡因使用、海洛因使用、甲基苯丙胺使用
交互 测试了上述特征之间的交互数量,其中婚姻状况和年龄改进了我们的模型,并在更大程度上进行了调查。
数据转换
应用了右偏连续测量(如收入)的对数转换和非二进制分类数据(如婚姻状况)的虚拟转换。因为我对比较不同变量的系数感兴趣,所以我也标准化了所有的标量特征。
模型评估和选择
心理健康是一个复杂的问题,缩小所有可能影响一个人心理健康发展的因素的范围是一项极具挑战性的任务。为了在选定的主题中找到最适合的模型,我测试了多种不同的特性选择方法。在这里,我概述了最终的评估过程。(要查看整个过程,请参考我的 Github 页面。)
相关消除
首先,我在手动控制相关性高于 0.7 后测试了模型。这导致调整后的 R2 为 0.146。
差异通货膨胀系数(VIF)
我还使用方差膨胀因子(VIF)测试了使用的variance_inflation_factor
stats models控制多重共线性。VIF 衡量一个特定特征中有多少差异可以由所有其他特征来解释。
**import** pandas **as** pd **from** statsmodels.stats.outliers_influence **import** variance_inflation_factordef **vif_**(X):
vif = pd.**DataFrame**()
vif['VIF'] = [**variance_inflation_factor**(X.values, i) **for** i **in** range(len(X.columns))]
vif['Features'] = X.columns
**return** vifVif = **vif_**(X)
使用 VIF 导致模型的调整后 R2 为 0.147。
递归特征消除(RFE)
我测试的另一个特征选择方法是递归特征消除(RFE ),使用 scikit-learn 的RFECV
进行交叉验证。递归特征消除算法重复模型拟合和去除最没有意义的特征的过程。RFECV
sci kit-learn 还使用交叉验证来确定最佳功能数量。
**from** sklearn.linear_model **import** LinearRegression
**from** sklearn.feature_selection **import** RFECVlm = **LinearRegression**()
sel_features = **RFECV**(estimator = lm, step = 1, cv = 10, scoring = 'r2')
sel_features = sel_features.**fit**(X, y)
X = X.**loc**[:,selector.support_]
使用递归特征消除算法选择特征后,模型拟合度略有提高,调整后的 R2 为 0.150。
最终模型
基于性能,我选择了 RFE 模型,但我通过运行单独的迭代来扩展递归,删除具有最高 p 值的要素,并在提高模型拟合度的情况下再次拟合模型。通过添加这个过程,我的最终模型在调整后的 R2 为 0.156 时提高了拟合优度。尽管 0.156 的 R2 分数看起来很低,但在研究人类认知和行为时,R2 分数仍然很低并不罕见。
清洁和测试完成后,最终模型构建的全过程:
最终系数
那么,心理健康指数较高的原因是什么呢?
现在我将分享一些对这些系数的解释,这些解释可能有助于自杀预防研究的未来方向。请再次注意,心理健康是一个复杂的问题,与影响我们生存状态的大量因素相比,这个模型只关注了几个主题。这是为了从整体上预防自杀,并不反映任何个人的状况。
现有医疗条件
癌症等慢性疾病是频繁出现抑郁症状的重要预测因素。在 MHI,癌症导致了大约 3.8 个百分点的增长。在这里给你一个提示,如果你从完全没有症状到一直有一种症状,那将会增加 3 个百分点。有残疾也是经常经历抑郁症状的一个关键预测因素,在 MHI 增加了大约 3.2 个百分点。
这就是我所说的“绝望”衡量标准,在这种情况下,感到无法摆脱身体或精神痛苦会导致抑郁症状恶化。由于诊断的第一年更接近当前时间,MHI 估计值也降低了,这表明自癌症诊断以来的时间越长,您的 MHI 就越高。
当一个人无论如何努力,事情似乎都没有改变时,应对困难的局面就变得更加具有挑战性。鼓励进一步研究复原力和应对绝望的方法。
衰老独奏
未婚个体的年龄增长是较高 MHI 的最高标量特征,在与癌症生活一段时间后。这不是一个明确的衡量标准,因为该模型没有考虑婚姻状况或家庭人数之外的任何其他支持系统。
我相信,研究当前模式如何与护理设施和非婚姻支持团体的可及性相互作用,以及不同类型的支持性护理的效果,将允许更深入地了解心理健康进展。但我也建议继续未婚长者发展支援系统。
物质使用
另一个重要的关键因素是该物质的使用。MHI 的吸烟率上升了近一个百分点。较高的平均每日可卡因使用量也与较高的 MHI 有关。这种关系并不意味着因果关系,进一步的调查是必要的。
结论
我概述了建立多元线性回归模型的迭代过程,并讨论了一些人口统计数据、医疗条件和物质使用如何可能有助于自我报告的精神健康筛查分数的增加。基于这些发现,我建议继续研究如何应对绝望和药物使用,并为未婚老人开发更多的支持系统。
对于未来的方向,我相信增加关于医疗保健设施和支持团体的可及性、就业状况和食品安全的信息将极大地改善该模型。
Apache Spark 中的获取失败异常:解密最常见的原因
SPARK 执行指南
大多数 Spark 开发人员花费了大量的时间来排除在混洗操作中观察到的 Fetch Failed 异常。这个故事将为您提供获取失败异常的最常见原因,并揭示最近对该异常进行的调查结果。
Shuffle 操作是几乎所有 Spark 作业的主干,这些作业的目标是数据聚合、连接或数据重组。在混洗操作期间,数据通过两步过程在群集的各个节点之间混洗:
a)混洗写入:混洗映射任务将待混洗的数据写入磁盘文件,数据根据混洗减少任务排列在文件中。对应于由混洗映射任务写入混洗减少任务的一堆混洗数据被称为混洗块。此外,每个混洗映射任务通知驱动程序关于写入的混洗数据。
b)混洗读取:混洗减少任务向驱动程序查询其混洗块的位置。然后,这些任务与托管其洗牌块的执行器建立连接,并开始获取所需的洗牌块。一旦获取了一个块,它就可用于 reduce 任务中的进一步计算。
想了解更多洗牌过程,可以参考我之前的故事标题:揭秘 Apache Spark 洗牌魔术。
shuffle 的两步过程虽然听起来很简单,但是操作起来很复杂,因为它涉及数据排序、磁盘写/读和网络传输。因此,对于混洗操作的可靠性总是有一个问号,并且这种不可靠性的证据是在混洗操作期间经常遇到的“提取失败异常”。大多数 Spark 开发人员花费大量时间来排除这种常见的异常。首先,他们试图找出异常的根本原因,然后相应地对其进行正确的修复。
在 shuffle reduce 任务中报告的获取失败异常指示从宿主执行器读取一个或多个 shuffle 块失败。调试 FetchFailed 异常非常具有挑战性,因为它可能由于多种原因而发生。找到并了解正确的原因是非常重要的,因为这将有助于您采取正确的措施来克服异常。
最近一段时间对数百个 Spark 作业进行故障排除后,我意识到 Fetch Failed 异常主要是由于以下原因造成的:
- 执行器上的堆内存不足
- 执行器上的低内存开销
- 大于 2 GB 的随机播放块
- 网络超时。
为了了解这些原因出现的频率,我最近还对 Spark、 Apache Spark 上最受关注的 LinkedIn 群组进行了民意调查。令我惊讶的是,相当多的人参与了投票并提交了他们的意见,这进一步证实了人们在 Spark 工作中经常遇到这种例外的事实。以下是投票结果:
LinkedIn Apache Spark 组中对 Fetch Failed Exception 进行的投票结果
根据投票结果,“执行程序堆内存不足”和“洗牌块大于 2 GB”是投票最多的原因。接下来是“网络超时”和“执行器的低内存开销”。
让我们详细了解一下这些原因:
**“执行程序上的堆内存不足”😗*这个原因表明,由于托管相应洗牌块的执行程序因 Java“内存不足”错误而崩溃,导致获取失败异常。当执行器上的堆空间不足或者执行器的垃圾收集器在垃圾收集上浪费了比实际有用的工作更多的时间时,就会出现“内存不足错误”。
为了关联这个原因,您需要检查 Fetch Failed 异常中提到的主机执行器详细信息(主机名/IP 地址/端口)。一旦您获得了执行器的详细信息,您会注意到针对托管执行器的以下任务失败:
- 由于退出代码 143,导致“ExecutorLostFailure”
- 由于执行器心跳超时,导致“ExecutorLostFailure”。
这些针对托管执行器的任务失败表明托管洗牌块的执行器由于 Java“内存不足”错误而被杀死。此外,还可以明确确认 executor 容器日志中的错误。由于托管执行器被终止,托管的 shuffle 块无法获取,因此可能会导致一个或多个 shuffle reduce 任务中的获取失败异常。
根据民意调查结果,这一原因获得了最高的投票率。我在工作中也见证了更大比例的这种原因。
**“执行程序上的低内存开销”😗*该原因表明,由于托管相应洗牌块的执行程序因“低内存开销”而崩溃,因此出现了提取失败异常。当一个执行器的物理内存占用超过指定的物理内存限制时,就会出现“内存开销低”的错误。当执行器堆内存被大量利用,并且对堆外内存也有很好的需求时,就会出现这种情况。
为了关联这个原因,您需要检查 Fetch Failed 异常中提到的主机执行器细节(主机名/IP 地址/端口)。一旦获得了执行者的详细信息,您可能会注意到针对托管执行者的以下任务失败:
- ExecutorLostFailure,使用了# GB 物理内存中的# GB。考虑提高火花。纱线。执行者。开销
针对托管执行器的上述任务失败表明,托管洗牌块的执行器由于过度使用指定的物理内存限制而被杀死。同样,由于托管执行器被终止,托管的混排块不能被获取,因此可能导致一个或多个混排减少任务中的获取失败异常。
根据民意调查结果,这一原因的投票率最低。但是,我也目睹了更大比例的这种原因。事实上,这个比例类似于“执行程序内存不足”的原因。
**“大于 2 GB 的随机播放块”😗*获取失败异常,提及“帧太大”、“帧大小超过”或“大小超过整数”。作为错误原因的“MaxValue”指示相应的混洗减少任务试图获取大于 2 GB 的混洗块。这主要来源于整数的限制。数据结构抽象(ByteBuffer)上的 MaxValue(2GB)用于在内存中存储 shuffle 块。
然而,从 Spark 版开始,这个特殊的原因在很大程度上得到了解决。
根据民意调查结果,这一原因获得了第二高的投票率。但是,在我的工作中,我很少看到 Fetch 因此而失败。
**“网络超时”😗*通常以可配置的时间间隔(spark.shuffle.io.retryWait
)重试可配置的次数(spark.shuffle.io.maxRetries
)来获取混洗块。当从其宿主执行器获取 shuffle 块时耗尽了所有的退休时,在 shuffle reduce 任务中会引发一个获取失败异常。这些获取失败的异常通常被归类为“网络超时”类别。
这种提取失败异常很难关联。此外,这些异常可能由于网络问题而出现,或者当托管相应洗牌块的执行器变得不堪重负时出现。
根据民意调查结果,这一原因获得了第三高的投票率。我也经常目睹这一事业。
我希望,读完这个故事后,您现在一定对 Fetch Failed 异常的各种原因有了一个公平的想法。我计划在一个不同的故事中介绍针对每个原因的可能的修复方法。如果您正在紧急寻找针对 Fetch Failed 异常的修复方法,您可以丢弃一条消息。
最后,我要感谢所有参与投票并提交意见的人。
如果对这个故事有任何反馈或疑问,请写在评论区。我希望,你会发现它有用。 这里是我贴的 Apache Spark 上其他综合故事的链接。
删除丢失的值?你可能不应该。
我们不知道的是,缺失值包含的信息通常与数据集的其他部分一样多。
一个 系列的缺失值通常会像一系列结构化数据上的污点一样突出。
看上图。你可能下意识地注意到的第一件事是有一辆婴儿车不见了。事实上,让我告诉你,这正是人类大脑的工作方式。
任何不寻常的东西都需要检查。
—人类的大脑。
猜猜看?在处理真实世界的数据时,您很少会遇到没有缺失值的数据集!
就像一张纸上的一个污点一样,缺少的值会显得很突出,很碍眼。
缺少列中没有缺少值的矩阵
那些令人满意的干净笔直的柱子之间的白色斑块,该死的,如果我说它们不会触发我的强迫症,就开枪打我吧。
不幸的是,对我们这些数据分析师来说, 处理嘈杂的数据是我们一天工作的一半 &,老实说,为了让我们的生活更轻松,我经常忍不住删除那些缺少值的行!但是这样做是不明智的,因为这可能会导致信息的丢失和/或允许某种程度的偏见进入,这是另一个博客讨论的话题。所以如果感兴趣,继续读到最后& 订阅 即时通知。
回到关于缺失值的讨论
你不应该感到惊讶,但实际上,数据分析师总是主动处理数据集中的缺失值。事实上,通常情况下, 缺失值实际上代表了主要信息位&,尽管它可能与完整数据的其余部分没有什么不同!
因此,确定关于缺失值的假设是绝对必要的,它们是:
- 数据“是否完全随机缺失(【MCAR】)”?
- 还是他们“随意失踪(MAR)”?
- 最后,如果他们“不随意失踪(MNAR)”?
例如,如果男性透露其年龄&体重的可能性比女性高,那么所收集的数据将会有一系列缺失值,它们将被认为是 缺失而不是随机*(MNAR)。因此,可以采取适当的步骤来处理输入缺失变量以供进一步分析。*
不过,从另一方面来说,本着开放的心态,缺失值应该像剩余的完整数据集一样进行分析。事实上,最近的学术研究表明,不一致比传统的统计推断更直观。
我们对不一致的视觉感知
上图中的缺失矩阵展示了可视化缺失值如何帮助我们更好地理解数据集的例子。
快速浏览一下图像,可以看到“*scheme _ name”*列中有大量的值缺失。这种差异的原因可能是什么?
上面那张缺失矩阵图片中的数据集汇集了来自各种渠道的关于 社区水泵 的信息,这些水泵分散在坦桑尼亚的全国各地,看起来其中一些水泵可能是由非政府组织或非营利组织或一些体贴的个人安装的。因此,水泵的维护不属于坦桑尼亚任何政府计划的管辖范围。因此可以有把握地假设数据是 MNAR 。
引用最近一份关于不一致系列数据的视觉感知的研究出版物的声明,应该进一步加强我关于对处理缺失值持开放态度背后的原因的主张。[1]
我们发现,突出显示缺失值的可视化具有更高的感知数据质量,而那些打破
视觉连续性的可视化会降低这些感知,并可能导致解释偏差。—宋海阳和丹妮尔·艾伯斯·萨菲尔
他们的主张是,一般来说,人们对不一致更有的感知能力,尤其是通过向他们描绘一些信息的视觉形式。**
换句话说,就像上面的图片在潜意识里迫使你放大婴儿推车应该出现的地方一样,人类的大脑通过视觉感知做出一系列似乎合理的假设。因此,可以安全地假设一个常识,即我们作为人类,本能地通过视觉感知更多的信息,而不是任何其他形式的推理。**
上述出版物的作者进一步指出,人类在良好的光线下不会接收到不一致的模糊视觉。相反, 如果适用的话,对缺失的数据 进行注释或提供含义是更可取的,甚至是非常可取的。
总而言之,NaN 值并不一定意味着数据质量差,但作为数据分析师,有责任在正确处理数据之前警惕数据中存在此类差异的原因。
参考文献
H.宋和萨菲,我的资料在哪里?用缺失数据评估可视化 (2018),科罗拉多大学视觉实验室。
我是一名自由职业的数据分析师,帮助企业了解如何利用他们的数据需求。如果您有任何相关问题,请随时通过 Twitter 联系我。
此外,你甚至可以 订阅 到我的邮件列表,以便在有新的更新时得到即时通知!
用 fast.ai 进行少拍学习
在少镜头学习中,我们只使用几个带标签的例子来训练一个模型。了解如何使用迁移学习和一个新颖的样本选择框架来训练您的分类器。
介绍
最近,关于新的深度学习架构和训练策略的帖子和教程主导了社区。然而,一个非常有趣的研究领域,即少数镜头学习,并没有得到应有的重视。如果我们想要广泛采用 ML,我们需要找到用很少的数据和代码有效训练它们的方法。在本教程中,我们将通过一个 Google Colab 笔记本来训练一个图像分类模型,每个类仅使用 5 个标记样本。仅使用 5 个示例性样本也被称为 5 次学习。
该图显示了仅在 10 幅样本图像上训练的模型的最高损失
不要忘记查看我们的 Google Colab 笔记本以获得本教程的完整代码!
我们使用的框架和库
Jupyter 笔记本(Google Colab) 本教程的全部代码将作为笔记本提供。Jupyter 笔记本是可通过 web 浏览器访问的 python 编程环境,对于快速原型制作和实验非常有用。Colab 是谷歌的一项服务,在这里你可以免费访问运行在实例上的笔记本。
Fast.ai 训练深度学习模型可能相当复杂,涉及数百行代码。这就是 fast.ai 来救援的地方。由前凯格勒·杰瑞米·霍华德开发的一个库专门旨在快速简单地训练深度学习模型。使用 fast.ai,我们只需几行代码就可以训练和评估我们的分类器。其实,fast.ai 使用的是 PyTorch 框架。
轻轻的 轻轻的旨在解决你应该处理哪些样本的问题。如果你只标注了数据集中的一些样本,那么出现的一个关键问题是你如何挑选样本?Lightly 旨在通过为您提供选择样品的不同方法和指标来解决这一问题
设置您的笔记本
我们从安装必要的依赖项和下载数据集开始。您可以在笔记本中运行任何 shell 命令,只需以**"!"开始代码即可** 例如,要安装我们的依赖项,我们可以在一个笔记本单元中运行以下代码:
在笔记本单元内安装依赖项的代码
在本教程中,我们使用由猫和狗图像组成的数据集。您可以通过运行以下命令,使用 fastai CLI(命令行界面)从 Kaggle 下载它。注意,您需要修改从 Kaggle 获得的令牌:
使用 Kaggle CLI 下载数据集并解压缩文件夹
选择少量学习的样本
为了使用我们的少镜头学习算法获得稳健的结果,我们希望我们的训练集覆盖样本的整个空间。这意味着我们不想要很多相似的例子,而是选择一组非常不同的图片。为了实现这一点,我们可以创建数据集的嵌入,然后使用一种叫做 coreset[1]采样的采样方法。核心集采样确保我们仅通过添加尽可能远离现有数据集的样本来构建数据集。
现在,我们将使用 Lightly app 及其 python 包 lightly 来选择我们想要处理的最多样化的 10 个样本。我们首先需要创建一个嵌入。通过利用最近在自我监督学习中取得的成功,轻松地让我们不用任何标签就能做到这一点。我们可以简单地运行下面的命令来训练几个时期的模型,并创建我们的嵌入:
使用 lightly pip 包训练和嵌入数据集
最后,我们需要上传我们的数据集并嵌入到 Lightly app 来运行我们的选择算法。由于我们不想上传图像,我们可以告诉 CLI 只考虑样本的元数据。
上传元数据并嵌入到 Lightly 的 CLI 命令
一旦上传了数据和嵌入,我们就可以回到网络平台,运行我们的采样算法。这可能需要一分钟才能完成。如果一切顺利,你应该会看到一个滑块图。向左移动滑块,在新的子集中仅保留 10 个样本。提示:您可以使用箭头键一个接一个地移动滑块。一旦我们选择了 10 个样本,我们需要创建一个新的标签(左侧菜单)。对于本教程,我们使用“tiny”作为名称,并按 enter 键创建它。
使用以下 CLI 命令下载新创建的子集:
下载基于标签的子集,并创建我们想要处理的图像的本地副本
您可能会发现您下载的数据集并不完全平衡。例如,你可能有 4 张猫的图片和 6 张狗的图片。这是由于我们选择样本的算法。我们的目标是覆盖整个嵌入/特征空间。很可能在我们的数据集中,猫的相似图像比狗的图像更多。因此,狗的图像会比猫的多。
使用 fast.ai 训练我们的模型
如果你达到这一点,你应该有一个数据集,我们使用轻度和 Coreset 采样获得,准备用于训练我们的分类器。
Fast.ai 只需要几行代码就可以训练一个图像分类器。我们首先需要创建一个数据集,然后是一个学习者对象。最后,我们使用.fit(...)
方法训练模型。
Fast.ai 代码,使用迁移学习来构建和训练分类器
解释结果
为了评估我们的模型,我们使用由 2000 幅图像组成的猫狗数据集的测试集。通过观察混淆矩阵,我们发现我们的模型很难预测狗是猫。
在 10 个样本上训练的模型的混淆矩阵
Fast.ai 还帮助我们用几行代码就可以得到我们模型的可解释的性能图。
Fast.ai 代码来创建我们的模型如何在测试集上执行的图表
该库还允许我们查看来自训练模型损失最高的测试集的图像。你可以看到这个模型与看起来更像猫的小型狗斗争。我们可以通过为训练程序选择更多的样本来提高准确性。然而,本教程的目标是表明,通过利用迁移学习和智能数据选择过程,您可以用少量的训练数据获得很高的准确性(> 80%)。
该图显示了仅在 10 幅样本图像上训练的模型的最高损失
我希望你喜欢这篇关于如何使用 fast.ai 和轻松使用的简单指导。请关注我,了解更多关于 Medium 的教程!
Igor 联合创始人
Lightly.ai
[1]oze an s .(2017),卷积神经网络的主动学习:核心集方法