【机器学习】阿里云天池竞赛——工业蒸汽量预测(6)

机器学习经典赛题:工业蒸汽量预测(6):特征优化

6.1 特征优化的方法

好的特征对于模型性能有着至关重要的影响。可以通过合成特征、对特征做简单变换、用决策树创造新特征、特征组合等方法对特征进行优化。

6.1.1 合成特征

从一个或者多个输入特征衍生来的特征(标准化和缩放法创建的特征不算),主要包含以下几个类型:
(1)将一个特征与其本身或者其他特征相乘(特征组合)
(2)两个特征相除
(3)对连续特征进行分箱,以分为多个区间分箱。

6.1.2 特征的简单变换

  1. 数值特征的变换和组合
    常用的数值特征的变换和组合如下:
    (1)多项式特征(polynomial feature)
    (2)比例特征(ratio feature): X 1 / X 2 X1/X2 X1/X2
    (3)绝对值(absolute value)
    (4) m a x ( X 1 , X 2 ) max(X1,X2) max(X1,X2), m i n ( X 1 , X 2 ) min(X1,X2) min(X1,X2), X1 or X2
  2. 类别特征与数值特征的组合
    用N1和N2表示数值特征,C1和C2表示类别特征,利用pandas的groupby创建以下几种新特征(其中,C2还可以是离散化了的N1):
    (1)中位数:median(N1)_by(C1)
    (2)算数平均数:mean(N1)_by(C1)
    (3)众数:mode(N1)_by(C1)
    (4)最小值:min(N1)_by(C1)
    (5)最大值:max(N1)_by(C1)
    (6)标准差:std(N1)_by(C1)
    (7)方差:var(N1)_by(C1)
    (8)频数:freq(C2)_by(C1)
    注意:freq(C1)不需要进行groupby操作也有意义。
    如果讲这种方法和线性组合等基础特征工程结合(仅用于决策树),则可以得到更多有意义的特征,如下:
    (1)N1-median(N1)_by(C1)
    (2)N1-mean(N1)_by(C1)

6.1.3 用决策树创造新特征

在决策树系列(单棵决策树、GBDT、随机森林)的算法中,由于每一个样本都会被映射到决策树的一片叶子上,因此可以把样本经过每一棵决策树映射后的index(自然数)或one-hot-vector(哑编码得到的稀疏矢量)作为一项新的特征加入模型中
具体实现采用sklearn和xgboost中的apply()和decision_path()。

6.1.4 特征组合

特征组合是指将单独的特征进行组合(相乘或求笛卡尔积)而形成的合成特征,有助于表示非线性关系。

  1. 对非线性规律进行编码
    由于通过采用随机梯度下降法可以有效地训练线性模型,因此在使用扩展的线性模型时,辅以特征组合一直都是训练大规模数据集的有效方法。可以创建很多不同种类的特征组合,例如:

    • [A x B]:将两个特征的值相乘
    • [A x B x C x …]:几个特征的值相乘
    • [A x A]:对单个特征的值求平方形成的特征
  2. 组合独热向量
    机器学习模型很少会组合连续特征,但是却经常组合独热特征向量,将独特特征矢量的特征组合视为逻辑连接。例如country:usa AND language:spanish

对大规模数据集使用特征组合时学习高度复杂模型的一种有效策略,而神经网络可提供另一种策略。

  1. 使用分桶特征列训练模型
    分桶特征:是以一定方式将连续型数据特征划分到不同的桶(箱)中,可以理解为对连续型特征的一种离散化处理。

如果要为分桶特征定义特征列,可以使用bucketized_column( 而不是numerical_column),该列数字作为输入并使用boundaries参数中指定的分桶边界 将其转化为分桶特征

6.2 特征优化实战

6.2.1 导入数据

import pandas as pd
from sklearn.decomposition import PCA
from sklearn.model_selection import KFold
from sklearn.metrics import mean_squared_error
import lightgbm as lgb
import numpy as np

train_data_file = "../data/zhengqi_train.txt"
test_data_file = "../data/zhengqi_test.txt"
train_data = pd.read_csv(train_data_file, sep='\t', encoding='utf-8')
test_data = pd.read_csv(test_data_file, sep='\t', encoding='utf-8')

6.2.2 特征构造方法

#定义特征构造方法
epsilon = 1e-5

#组交叉特征,可以自己定义,如增加x*x/y,log(x)/y等
func_dict = {
    'add': lambda x, y: x + y,
    'mins': lambda x, y: x - y,
    'div': lambda x, y: x / (y + epsilon),
    'multi': lambda x, y: x * y
}

6.2.3 特征构造函数

#特征构造函数
def auto_features_make(train_data, test_data, func_dict, col_list):
    train_data, test_data = train_data.copy(), test_data.copy()
    for col_i in col_list:
        for col_j in col_list:
            for func_name, func in func_dict.items():
                for data in [train_data, test_data]:
                    func_features = func(data[col_i], data[col_j])
                    col_func_features = '-'.join([col_i, func_name, col_j])
                    data[col_func_features] = func_features
    return train_data, test_data

6.2.4 特征降维处理

#基于PCA进行特征降维
train_data2, test_data2 = auto_features_make(train_data, test_data, func_dict, col_list=test_data.columns)
pca = PCA(n_components=500)
train_data2_pca = pca.fit_transform(train_data2.iloc[:, 0:-1])
test_data2_pca = pca.transform(test_data2)
train_data2_pca = pd.DataFrame(train_data2_pca)
test_data2_pca = pd.DataFrame(test_data2_pca)
train_data2_pca['target'] = train_data2['target']
x_train2 = train_data2[test_data2.columns].values
y_train2 = train_data2['target']

6.2.5 模型训练和评估

使用LightGBM模型对新构造的特征进行模型训练和评估。

#模型训练与评估
#5折交叉检验
folds = 5
kf = KFold(n_splits=folds, shuffle=True, random_state=2019)

#记录训练和预测MSE
MSE_DICT = {'train_mse': [], "test_mse": []}

#线下训练预测
for i, (train_index, test_index) in enumerate(kf.split(x_train2)):
    #LGB模型
    lgb_reg = lgb.LGBMRegressor(
        learning_rate=0.01,
        max_depth=-1,
        n_estimators=5000,
        boosting_type='gbdt',
        random_state=2022,
        objective='regression',
    )
    #切分训练集和预测集
    x_train_kfold = x_train2[train_index]
    x_test_kfold = x_train2[test_index]
    y_train_kfold = y_train2[train_index]
    y_test_kfold = y_train2[test_index]
    #模型训练
    lgb_reg.fit(X=x_train_kfold,
                y=y_train_kfold,
                eval_set=[(x_train_kfold, y_train_kfold),
                          (x_test_kfold, y_test_kfold)],
                eval_names=['train', 'test'],
                early_stopping_rounds=100,
                eval_metric='MSE',
                verbose=50)
    #训练集和预测集预测
    y_train_kfold_predict = lgb_reg.predict(x_train_kfold, num_iteration=lgb_reg.best_iteration_)
    y_test_kfold_predict = lgb_reg.predict(x_test_kfold, num_iteration=lgb_reg.best_iteration_)
    print('第{}折 训练和预测 训练MSE 预测MSE'.format(i))
    train_mse = mean_squared_error(y_train_kfold_predict, y_train_kfold)
    print('-----\n', '训练MSE\n', train_mse, '\n-----')
    test_mse = mean_squared_error(y_test_kfold_predict, y_test_kfold)
    print('-----\n', '预测MSE\n', test_mse, '\n-----')
    MSE_DICT["train_mse"].append(train_mse)
    MSE_DICT['test_mse'].append(test_mse)
print('-----\n', '训练MSE\n', MSE_DICT['train_mse'], '\n', np.mean(MSE_DICT['train_mse']), '\n-----')
print('-----\n', '预测MSE\n', MSE_DICT['test_mse'], '\n', np.mean(MSE_DICT['test_mse']), '\n-----')

运行结果:

...
-----
 训练MSE
 [0.00017012122282987903, 0.003986113221006774, 0.004653503140174019, 1.6944261550293392e-05, 0.0019608822664788713] 
 0.002157512822407967 
-----
-----
 预测MSE
 [0.09929753449545065, 0.1250100344303853, 0.09311309275116833, 0.10307589284589647, 0.09883896847504547] 
 0.10386710459958923 
-----

将代码运行得到的5折交叉验证的各折叠训练MSE、预测MSE及平均MSE,与上一节未作特征优化的结果(训练MSE平均值为0.006117279317883938,预测MSE平均值为0.10952066075608168)对比,可以发现MSE得到进一步降低。

参考资料

[1] 《阿里云天池大赛赛题解析——机器学习篇》

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

镰刀韭菜

看在我不断努力的份上,支持我吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值