通常基于id 值(用户id、商品id等)
或类别特征的某个类别
计算数值特征的一些统计量,一般在多个表好操作一些。
用N1
和 N2
表示数值特征,用C1
和C2
表示类别特征(C2还可以是连续值特征离散化后的取值),利用 pandas 的 groupby 操作,可以创造出以下几种有意义的新特征:
display(df.head(10))
输出
C1 C2 N1 N2
0 A a 1 1.1
1 A a 1 2.2
2 A a 2 3.3
3 B a 2 4.4
4 B a 3 5.5
5 C b 3 6.6
6 C b 4 7.7
7 C b 4 8.8
8 D b 5 9.9
9 D b 5 10.0
1)分组统计中位数
median(N1)_by(C1)
例子: 不同公司职员工资的中位数。
df.groupby(['C1']).agg({'N1': 'median'})
# 输出
N1
C1
A 1.0
B 2.5
C 4.0
D 5.0
2)分组统计算术平均数
mean(N1)_by(C1)
例子: 顾客平均每次的购买金额。
df.groupby(['C1']).agg({'N1': 'mean'})
# 输出
N1
C1
A 1.333333
B 2.500000
C 3.666667
D 5.000000
3)分组统计众数
mode(N1)_by(C1)
例子: 购买商品类型的众数。
df.groupby(['C1'])['N1'].agg(lambda x: stats.mode(x)[0][0])
# 输出
C1
A 1
B 2
C 4
D 5
4)分组统计最小值
min(N1)_by(C1)
例子: 购买行为至今天数最小值(最近一次购买至今天数)。
df.groupby(['C1']).agg({'N1': 'min'})
# 输出
N1
C1
A 1
B 2
C 3
D 5
5)分组统计最大值
max(N1)_by(C1)
例子: 理财用户的历史最大在投金额。
df.groupby(['C1']).agg({'N1': 'max'})
# 输出
N1
C1
A 2
B 3
C 4
D 5
6)分组统计标准差
std(N1)_by(C1)
df.groupby(['C1']).agg({'N1': 'std'})
# 输出
N1
C1
A 0.577350
B 0.707107
C 0.577350
D 0.000000
7)分组统计方差
var(N1)_by(C1)
df.groupby(['C1']).agg({'N1': 'var'})
# 输出
N1
C1
A 0.333333
B 0.500000
C 0.333333
D 0.000000
8)分组统计频数
freq(C2)_by(C1)
例子: 每个月购买商品次数。
df.groupby(['C1']).agg({'C2': 'count'})
# 输出
C2
C1
A 3
B 2
C 3
D 2
仅仅将已有的类别和数值特征进行以上的有效组合,就能够大量增加优秀的可用特征。
freq(C1)
,直接统计类别特征的频数,这个不需要 groupby 也有意义。
df['C1'].count()
# 输出:10
将这种方法和线性组合等基础特征工程方法结合(仅用于决策树),可以得到更多有意义的特征,例如:
中位数分组和线性组合结合
N1 + median(N1)_by(C1)
N1 - median(N1)_by(C1)
N1 * median(N1)_by(C1)
N1 / median(N1)_by(C1)
df = pd.merge(df, df.groupby(['C1'])['N1'].median().reset_index().rename(columns={'N1': 'N1_Median'}),on='C1', how='left')
df['N1+Median(C1)'] = df['N1'] + df['N1_Median']
df['N1-Median(C1)'] = df['N1'] - df['N1_Median']
df['N1*Median(C1)'] = df['N1'] * df['N1_Median']
df['N1/Median(C1)'] = df['N1'] / df['N1_Median']
display(df.head(20))
# 输出:
C1 C2 N1 N2 N1_Median N1+Median(C1) N1-Median(C1) N1*Median(C1) N1/Median(C1)
0 A a 1 1.1 1.0 2.0 0.0 1.0 1.00
1 A a 1 2.2 1.0 2.0 0.0 1.0 1.00
2 A a 2 3.3 1.0 3.0 1.0 2.0 2.00
3 B a 2 4.4 2.5 4.5 -0.5 5.0 0.80
4 B a 3 5.5 2.5 5.5 0.5 7.5 1.20
5 C b 3 6.6 4.0 7.0 -1.0 12.0 0.75
6 C b 4 7.7 4.0 8.0 0.0 16.0 1.00
7 C b 4 8.8 4.0 8.0 0.0 16.0 1.00
8 D b 5 9.9 5.0 10.0 0.0 25.0 1.00
9 D b 5 10.0 5.0 10.0 0.0 25.0 1.00
均值分组和线性组合结合
N1 + mean(N1)_by(C1)
N1 - mean(N1)_by(C1)
N1 * mean(N1)_by(C1)
N1 / mean(N1)_by(C1)
df = pd.merge(df, df.groupby(['C1'])['N1'].mean().reset_index().rename(columns={'N1': 'N1_Mean'}),on='C1', how='left')
df['N1+Mean(C1)'] = df['N1'] + df['N1_Mean']
df['N1-Mean(C1)'] = df['N1'] - df['N1_Mean']
df['N1*Mean(C1)'] = df['N1'] * df['N1_Mean']
df['N1/Mean(C1)'] = df['N1'] / df['N1_Mean']
display(df.head(20))
# 输出:
C1 C2 N1 N2 N1_Mean N1+Mean(C1) N1-Mean(C1) N1*Mean(C1) N1/Mean(C1)
0 A a 1 1.1 1.333333 2.333333 -0.333333 1.333333 0.750000
1 A a 1 2.2 1.333333 2.333333 -0.333333 1.333333 0.750000
2 A a 2 3.3 1.333333 3.333333 0.666667 2.666667 1.500000
3 B a 2 4.4 2.500000 4.500000 -0.500000 5.000000 0.800000
4 B a 3 5.5 2.500000 5.500000 0.500000 7.500000 1.200000
5 C b 3 6.6 3.666667 6.666667 -0.666667 11.000000 0.818182
6 C b 4 7.7 3.666667 7.666667 0.333333 14.666667 1.090909
7 C b 4 8.8 3.666667 7.666667 0.333333 14.666667 1.090909
8 D b 5 9.9 5.000000 10.000000 0.000000 25.000000 1.000000
9 D b 5 10.0 5.000000 10.000000 0.000000 25.000000 1.000000
对于创造新的有用特征毫无用处;只能作为对已有特征的处理。
# 程序实现
df['Feature'] = df['Feature'] + n
df['Feature'] = df['Feature'] - n
df['Feature'] = df['Feature'] * n
df['Feature'] = df['Feature'] / n
如果u(x1, y1) > u(x2, y2)
,则v(x1, y1) = f(u(x1, y1)) > v(x2, y2)=f(u(x2, y2))
,那么f()
就是(正)单调变化,V是U的单调变换。设u
为效用函数,f(u)
是其单调变换。
例子:幂变换
适用范围:不适用于决策树类算法。
# 程序实现
import numpy as np
# 计算n次方
df['Feature'] = df['Feature']**2
# 计算log变换
df['Feature'] = np.log(df['Feature'])
[A X B]:将两个特征的值相乘形成的特征组合;
[A x B x C x D x E]:将五个特征的值相乘形成的特征组合;
[A x A]:对单个特征的值求平方形成的特征组合。
借助特征组合,线性学习器可以很好扩展到大量数据,并有助于构建复杂模型解决非线性问题。
适用场景:仅适用于决策树以及基于决策树的ensemble
算法,因为常见的axis-aligned split function
不擅长捕获不同特征之间的相关性;不适用于 SVM 、线性回归、神经网络等。
# 程序实现
df['Feature'] = df['A'] * df['B']
df['Feature'] = df['A'] * df['B'] * df['C'] * df['D'] * df['E']
df['Feature'] = df['A'] * df['A']
当两个变量各自与 y 的关系并不强时候,把它们结合成为一个新的变量可能更会容易体现出它们与 y 的关系。
特征a和特征b的多项式输出是:[1, a, b, a^2, ab, b^2]
或者[1, a, b, ab]
。
import numpy as np
from sklearn.preprocessing import PolynomialFeatures
X = np.arange(6).reshape(3, 2)
print(X)
# 输出:array([[0, 1],
[2, 3],
[4, 5]])
# 设置多项式阶数为2
poly = PolynomialFeatures(2)
print(poly.fit_transform(X))
# 输出:array([[ 1., 0., 1., 0., 0., 1.],
[ 1., 2., 3., 4., 6., 9.],
[ 1., 4., 5., 16., 20., 25.]])
#默认的阶数是2,同时设置交互关系为true
poly = PolynomialFeatures(interaction_only=True)
print(poly.fit_transform(X))
# 输出:array([[ 1., 0., 1., 0.],
[ 1., 2., 3., 6.],
[ 1., 4., 5., 20.]])
计算两个特征的数值比例:X1/X2
。
例子: 购物车转化比特征。
# 程序实现
df['Feature'] = df['X1']/df['X2']
计算特征值的绝对值:|X|
。
例子: 某数据的相关系数特征。
# 程序实现
import numpy as np
df['Feature'] = np.abs(df['Feature'])
max(X1, X2)
例子: 最近两个月的最大购买金额。
程序实现
# 最大值
df['Feature'] = df.apply(lambda x: max(x['X1'], x['X2']), axis=1)
min(X1, X2)
例子: 公司地址和宿舍地址距离商业中心的最小距离。
# 程序实现
# 最小值
df['Feature'] = df.apply(lambda x: min(x['X1'], x['X2']), axis=1)
按特征值对全体样本进行排序,以排序序号作为特征。这种特征对异常点不敏感,不会导致特征值冲突。
例子: 广告历史曝光量排名。
# 程序实现
X = [10, 9, 9, 8, 7]
df = pd.DataFrame({'X': X,})
df['num'] = df['X'].rank(ascending=0, method='dense')
display(df.head())
# 输出
X num
0 10 1.0
1 9 2.0
2 9 2.0
3 8 3.0
4 7 4.0
计算两特征的异或值:X1 xor X2
。
实际应用中也可以先进行二值化,然后再进行异或运算。
# 程序实现
# 按位进行异或运算
df['Feature'] = df.apply(lambda x: x['X1'] ^ x['X2'], axis=1)
[1] https://machinelearning-notes.readthedocs.io/zh_CN/latest/feature/%E7%89%B9%E5%BE%81%E5%B7%A5%E7%A8%8B%E2%80%94%E2%80%94%E6%97%B6%E9%97%B4.html
[2] https://www.cnblogs.com/nxf-rabbit75/p/11141944.html#_nav_12
[3] https://gplearn.readthedocs.io/en/stable/examples.html#symbolic-classifier
[4] 利用 gplearn 进行特征工程. https://bigquant.com/community/t/topic/120709
[5] Practical Lessons from Predicting Clicks on Ads at Facebook. https://pdfs.semanticscholar.org/daf9/ed5dc6c6bad5367d7fd8561527da30e9b8dd.pdf
[6] Feature Tools:可自动构造机器学习特征的Python库. https://www.jiqizhixin.com/articles/2018-06-21-2
[7] 各种聚类算法的系统介绍和比较. https://blog.csdn.net/abc200941410128/article/details/78541273