使用神经网络的自动化特征工程(下)

简介: 使用神经网络的自动化特征工程

下一个功能是用于创建嵌入层。因为“国家/地区”是稀疏的分类特征。此函数将提取要转换为嵌入的特征的字典,以及在此定义的该特征的唯一可能值的列表:

emb_layers= {'Country':list(X_train['Country'].unique())}

我们还稍后将对模型输入进行定义。对于Dimensions参数,我选择遵循默认特征规则。

defadd_emb(emb_layers={},model_inputs={}):
emb_inputs= {}
emb_features= []
forkey,valueinemb_layers.items():
emb_inputs[key] =model_inputs[key]
catg_col=feature_column          .categorical_column_with_vocabulary_list(key, value)
emb_col=feature_column.embedding_column(
catg_col,dimension=int(len(value)**0.25))
emb_features.append(emb_col)
emb_layer=layers.DenseFeatures(emb_features)
emb_outputs=emb_layer(emb_inputs)
returnemb_outputs

在继续使用下一个函数之前,我们需要定义哪些特征需要从不同的特征模型中排除。从根本上讲,我们将要排除要预测的特征(数据泄漏)和用于嵌入的特征。这里还应该小心删除可直接用于计算输出特征的特征。例如,一个预测男女的模型,如果有类似Gender_Female之类的特征那么它基本上可以获得100%的准确率。 为了解决这个问题,我们将从相应的特征模型中排除其他性别,年龄和联系人等特征。

feature_layers= {col:[col,'Country'] forcolinmodel_cols}
feature_layers['Gender_Female'] += ['Gender_Male',
'Gender_Transgender']
feature_layers['Gender_Male'] += ['Gender_Female',
'Gender_Transgender']
feature_layers['Gender_Transgender'] += ['Gender_Female',
'Gender_Male']
feature_layers['Age_0-9'] += ['Age_10-19','Age_20-24',
'Age_25-59','Age_60_']
feature_layers['Age_10-19'] += ['Age_0-9','Age_20-24',
'Age_25-59','Age_60_']
feature_layers['Age_20-24'] += ['Age_0-9','Age_10-19',
'Age_25-59','Age_60_']
feature_layers['Age_25-59'] += ['Age_0-9','Age_10-19',
'Age_20-24','Age_60_']
feature_layers['Age_60_'] += ['Age_0-9','Age_10-19',
'Age_20-24','Age_25-59']
feature_layers['Contact_Dont-Know'] += ['Contact_No','Contact_Yes']
feature_layers['Contact_No'] += ['Contact_Dont-Know','Contact_Yes']
feature_layers['Contact_Yes'] += ['Contact_Dont-Know','Contact_No']

我们还想为我们模型添加一个feature_layer:

feature_layers['Severity_Severe_aux'] = ['Country']

现在,我们拥有构建特征模型所需的所有东西。此函数将使用所有输入特征列表,上面定义的排除特征和嵌入字典,在add_model函数中描述的hidden_layer结构以及是否应使用批处理规范的配置等。

首先,该函数将使用TensorFlow方式的读取输入特征。使用这种方法的原因我们只需要定义一次,就可以在每个特征模型中一再地重复使用它们。接下来我们将确定是否定义了任何嵌入列,并创建一个嵌入层(可选)。对于每个特征模型,我们将创建DenseFeatures输入层(不包括上面定义的特征),并使用add_model函数创建一个单独的模型。在返回之前,我们检查循环是否在跳连接模型上运行。如果是这样,我们将附加输入要素,以便最终模型也可以使用原始要素进行训练。最后,此函数将返回模型输入的字典,每个要特征模型输出层的列表以及每个最终隐藏层(即新设计的特征)的列表。

deffeature_models(
output_feature=None,all_features=[],feature_layers={},
emb_layers={},hidden_layers=[],batch_norm=False):
model_inputs= {}
forfeatureinall_features:
iffeaturein [kfork,vinemb_layers.items()]:
model_inputs[feature] =tf.keras.Input(shape=(1,),
name=feature,
dtype='string')
else:
model_inputs[feature] =tf.keras.Input(shape=(1,),
name=feature)
iflen(emb_layers) >0:
emb_outputs=add_emb(emb_layers,model_inputs)
output_layers= []
eng_layers= []
forkey,valueinfeature_layers.items():
feature_columns= [feature_column.numeric_column(f)
forfinall_featuresiffnotinvalue]
feature_layer=layers.DenseFeatures(feature_columns)
feature_outputs=feature_layer({k:vfork,vinmodel_inputs.items()
ifknotinvalue})
iflen(emb_layers) >0:
feature_outputs=layers.concatenate([feature_outputs,
emb_outputs])
last_layer, output_layer=add_model(
feature_outputs=feature_outputs,
hidden_layers=hidden_layers,
batch_norm=batch_norm,
model_name=key)
output_layers.append(output_layer)
eng_layers.append(last_layer)
ifkey==output_feature+'_aux':
eng_layers.append(feature_outputs)
returnmodel_inputs, output_layers, eng_layers

如果使用嵌入层,则它将与这些模型的每个输入连接在一起。这意味着这些嵌入不仅可以训练最大化整体模型的精度,还可以训练每一个特征模型。这导致了非常健壮的嵌入。

在进入最终功能之前,让我们定义将要输入的每个参数。以上大多数参数已在上面进行了描述,或对于所有TensorFlow模型都是典型的。例如,patience 参数,当指定时间段内验证准确性没有提高时,可使用该参数停止训练模型。

params= {'all_features': list(X_train.columns),
'output_feature':y_train.columns[0],
'emb_layers':emb_layers,
'feature_layers':feature_layers,
'hidden_layers':[[256,0],[128,0.1],[64,0.2]],
'batch_norm': True,
'learning_rate':0.001,
'patience':3,
'epochs':20      }

对于最终模型,我们将从运行上一个函数开始以生成输入,输出和特征工程的特征。然后,我们将这些层/特征中的每一个串联起来,并将其输入到最终模型中。最后,我们构建,编译,训练和测试模型。

deffinal_model(params,test=True):
print(params['batch_norm'],params['hidden_layers'])
model_inputs, output_layers, eng_layers=feature_models(
all_features=params['all_features'],
feature_layers=params['feature_layers'],
emb_layers=params['emb_layers'],
hidden_layers=params['hidden_layers'],
batch_norm=params['batch_norm'],
output_feature=params['output_feature'])
concat_layer=layers.concatenate(eng_layers)
last_layer, output_layer=add_model(
feature_outputs=concat_layer,
hidden_layers=params['hidden_layers'],
batch_norm=params['batch_norm'],
model_name=params['output_feature'])
output_layers.append(output_layer)
model=tf.keras.Model(
inputs=[model_inputs],
outputs=output_layers)
aux_loss_wgt=0.5/len(params['feature_layers'])
loss_wgts= [aux_loss_wgtforiinrange(len(params['feature_layers']))
loss_wgts.append(0.5)
model.compile(loss='binary_crossentropy',
optimizer=tf.keras.optimizers.Adam(
lr=params["learning_rate"]),
loss_weights=loss_wgts,
metrics=['accuracy'])
es=tf.keras.callbacks.EarlyStopping(
monitor='val_loss',mode='min',verbose=1,
patience=params['patience'],restore_best_weights=True)
history=model.fit(
trainset,validation_data=valset,
epochs=params['epochs'], verbose=0, callbacks=[es])
yhat=model.predict(testset)
loss=log_loss(
np.array(y_test[params['output_feature']]),
yhat[-1])**.5print('Binary Crossentropy:',loss)
iftest==True:
sys.stdout.flush()
return {'loss': loss, 'status': STATUS_OK}
else:
returnhistory, model

需要注意的是,函数的输入之一称为test。这个 输入可以在使用hyperopt求解最佳参数(test = True)或训练并返回最终模型(test = False)之间进行切换。编译模型时,也可能不调整loss_weights参数。因为我们有多个辅助输出,所以我们需要告诉TensorFlow在确定如何调整模型以提高准确性时给每个加权多少。我个人喜欢对辅助预测(总计)给予50%的权重,对目标预测给予50%的权重。有些人可能会觉得给辅助预测赋予任何权重是很奇怪的,因为它们在损失计算步骤中被丢弃了。问题是,如果我们不给它们赋予任何权重,模型多半会忽略它们,从而妨碍它学习有用的特征。

现在,我们只需要使用上面定义的参数来运行final_model:

history, model = final_model(params,test=False)

现在我们有了一个经过训练的模型,我们可以使用keras get_layer()函数选择性地提取要在其他模型中使用的新特性。如果这能引起足够的兴趣,我将把这一步留到以后的文章中讨论。

结果

“它最后战胜了XGBoost,这与传统观点不同,因为传统观点认为梯度增强模型更适合结构化数据集。”

你可以想象,这是一个计算上昂贵的模型训练。但是好消息是它通常会在比典型MLP少得多的试验中收敛到一个更准确的答案。如果你把不花几周时间在繁琐的工程特性上节省下来的时间也算进去,那就快得多了。此外,预测延迟足够小,可以使其成为一个生产模型(与典型的Kaggle 50+元模型相反)。如果你提取特征并用它们重新训练一个神经网络,那么它会变得更快。

问题仍然存在,它是准确的吗?在我应用这个模型的每一个案例中,它都是最准确的。它始终战胜了XGBoost,让我们看看它在这个问题上做得如何!

我测试了三种不同的模型:

  1. XGBoost
  2. 带有嵌入的标准MLP
  3. 上面训练的自动特征模型

对于自动特征模型,我使用hyperopt进行了20个试验,以试验不同的网络规模。对于这两个对比的模型,由于它们的训练时间较快,因此我进行了40次试验。结果如下:

640.jpg

正如预期的那样,我们的自动特征模型表现最好。需要记住的一件事是,这个简单的数据集没有足够的有用信息来允许任何模型比边际收益更好。当我处理数百个特征的海量数据集时,自动功能模型将领先XGBoost击败5–10%也是有可能的。

目录
相关文章
|
4天前
|
数据采集 存储 API
网络爬虫与数据采集:使用Python自动化获取网页数据
【4月更文挑战第12天】本文介绍了Python网络爬虫的基础知识,包括网络爬虫概念(请求网页、解析、存储数据和处理异常)和Python常用的爬虫库requests(发送HTTP请求)与BeautifulSoup(解析HTML)。通过基本流程示例展示了如何导入库、发送请求、解析网页、提取数据、存储数据及处理异常。还提到了Python爬虫的实际应用,如获取新闻数据和商品信息。
|
8月前
|
安全 数据中心 虚拟化
自动化的NSX网络交付
临近年关,忙忙碌碌;今天下定决心更新,说一说NSX数据中心网络的自动交付。
自动化的NSX网络交付
|
4天前
|
弹性计算 运维 Shell
自动化网络扫描工具发现活跃主机
【4月更文挑战第30天】
9 0
|
4天前
|
网络协议 安全
【专栏】`curl`是广泛用于网络编程和自动化脚本的命令行工具,支持HTTP、HTTPS等协议
【4月更文挑战第28天】`curl`是广泛用于网络编程和自动化脚本的命令行工具,支持HTTP、HTTPS等协议。在处理大文件或慢速服务器时,设置超时参数至关重要。本文介绍了`curl`的超时参数,如`-m`(最大操作时间)、`-c`(连接超时)、`--dns-timeout`(DNS解析超时)和`-t`(时间条件)。通过示例展示了如何设置这些超时,并提到了一些高级技巧和注意事项,如错误处理和带宽限制。合理设置超时能提高效率和可靠性,对编写健壮的自动化脚本非常有用。
|
4天前
|
网络协议 Linux iOS开发
|
4天前
|
Ubuntu Linux
自动化解决Linux网络预测网络接口命名问题
自动化解决Linux网络预测网络接口命名问题
20 0
|
4天前
|
机器学习/深度学习 运维 算法
|
4天前
|
监控 Java 持续交付
内部网络监控软件的Groovy应用:持续集成与部署的自动化监控
在当今高度数字化的环境中,对于内部网络的监控变得至关重要。为了保证系统的稳定性和安全性,监控软件的自动化变得越来越必要。本文将介绍如何利用Groovy编程语言实现持续集成与部署的自动化内部网络监控软件,并通过代码示例展示其实现方式。
270 3
|
4天前
|
Web App开发 存储 前端开发
Python 自动化指南(繁琐工作自动化)第二版:十二、网络爬取
Python 自动化指南(繁琐工作自动化)第二版:十二、网络爬取
82 1
|
机器学习/深度学习 算法 数据库
特征工程系列之自动化特征提取器
特征工程系列之自动化特征提取器
特征工程系列之自动化特征提取器

热门文章

最新文章