# 大数据人工智能常用特征工程与数据预处理Python实践（2）

## 5.1. 时域特征

n
n

n

i
i

i

i
i

i

### 5.1.1. 均值、方差、标准差特征

（1）均值：

μ
=
1
n

i
=
1
n
x
i
\mu = \frac{1}{n}\sum_{i=1}^{n} x_{i}

i
=
1

n

x

i

（2）方差：

σ
2
=
1
2

i
=
1
n
(
x
i

μ
)
2
\sigma^{2}=\frac{1}{2}\sum_{i=1}^{n}(x_{i}-\mu)^2

i
=
1

n

(

x

i

μ

)

2

（3）标准差：

σ
=
1
n

1

i
=
1
n
(
x
i

μ
)
2
\sigma = \sqrt {\frac{1}{n-1}\sum_{i=1}^{n}(x_{i}-\mu)^{2}}

i
=
1

n

(

x

i

μ

)

2

### 5.1.2. 百分比、偏度、峭度

（1）离散度百分比

σ

=
σ
μ
\sigma’=\frac{\sigma}{\mu}

（2）峭度

k
4
=
1
n

1

i
=
1
n
(
x
i

μ
σ
)
4
k_{4} = \frac{1}{n-1}\sum_{i=1}^{n}(\frac{x_{i}-\mu}{\sigma})^{4}

i
=
1

n

(

σ

x

i

μ

)

4

（3）偏度

k
3
=
1
n

1

i
=
1
n
(
x
i

μ
σ
)
3
k_{3} = \frac{1}{n-1}\sum_{i=1}^{n}(\frac{x_{i}-\mu}{\sigma})^{3}

i
=
1

n

(

σ

x

i

μ

)

3

# 计算特征，标准差、均值、均方差、涨价加油频次
def generateFeature():
client = pymongo.MongoClient('mongodb://study:study@localhost:27017/study')
db = client["study"]
collection = db["sales_feature"]
df = pd.DataFrame(list(collection.find()))
print(df.dtypes)
df = df[(df.id<1100) & (df.fuelle_date > '2019-11-30')]
#计算加油消费金额、加油量、加油间隔的标准差
df_feature = df[['id','price_sensitive','amount','fuelle','fuel_interva']].groupby(['id','price_sensitive']).std()
#计算均值
df_feature1 = df[['id','price_sensitive','amount','fuelle','fuel_interva']].groupby(['id','price_sensitive']).mean()
#修改为均值列名
df_feature1 = df_feature1.rename(columns={
'amount':'amount_mean','fuelle':'fuel_mean','fuel_interva':'fuel_interva_mean'})
df_feature = pd.merge(left=df_feature, right=df_feature1,how="left",on=["id",'price_sensitive'])   #左连接
#df_feature1 = df[['id','amount','fuel_interva']].groupby(['id']).apply(np.std)
#计算涨价提前加油的频次
df2 = df[(df.id<1100) & (df.fuelle_date > '2019-11-30') & (df.changes<0) & (df.time_before==-1)]
df_feature3 = df2.groupby(['id','price_sensitive'], as_index=False)['time_before'].count()  #/4
# df_feature = pd.merge(left=df_feature, right=df_feature3,how="outer",on="id") #外连接
df_feature = pd.merge(left=df_feature, right=df_feature3,how="left",on=["id",'price_sensitive'])   #左连接
df_feature = df_feature.fillna(0)
df_feature['id'] = df_feature['id'].astype('int')
df_feature['price_sensitive'] = df_feature['price_sensitive'].astype('int')
# 百分比（一阶）
df_feature['amount_per'] = df_feature['amount']/df_feature['amount_mean']
df_feature['fuelle_per'] = df_feature['fuelle']/df_feature['fuel_mean']
df_feature['fuel_interva_per'] = df_feature['fuel_interva']/df_feature['fuel_interva_mean']
# 偏度（三阶）
#df_feature['amount_skew','fuelle_skew','fuel_interva_skew']
df_feature4 = df[['id','price_sensitive','amount','fuelle','fuel_interva']].groupby(['id','price_sensitive']).skew()
df_feature4 = df_feature4.rename(columns={
'amount':'amount_skew','fuelle':'fuelle_skew','fuel_interva':'fuel_interva_skew'})
df_feature = pd.merge(left=df_feature, right=df_feature4,how="left",on=["id",'price_sensitive'])   #左连接
#峭度/峰度（4阶）
df_feature = pd.concat([df_feature, pd.DataFrame(columns={
'amount_kurt','fuelle_kurt','fuel_interva_kurt'})])
for index,row in df_feature.iterrows():
id = row['id']
df_tmp = df[df['id']==id][['amount','fuelle','fuel_interva']]
k4 = df_tmp.kurt()
df_feature.loc[index:index,('amount_kurt','fuelle_kurt','fuel_interva_kurt')] = k4.tolist()
# 峰度/峭度kurt不能聚合
print(df_feature)
df_feature.to_hdf("Featue_DataV1.h5", key='df', mode='w', complevel=9)
Featue_Data = db["Featue_Data"]
return df_feature

## 5.2. 时间特征

def Date_Transformation():
data = pd.DataFrame({
'data_time':pd.date_range('2020-10-01 00:00:00',periods = 12,freq = 'D'),'date':pd.date_range('2019-01-01',periods = 12,freq = 'M')
})
# data:提取日期型和时间型的特征变量
data['year']= data['data_time'].dt.year
data['month'] = data['data_time'].dt.month
data['day'] = data['data_time'].dt.day
data['hour'] = data['data_time'].dt.hour
data['minute'] = data['data_time'].dt.minute
data['second'] = data['data_time'].dt.second    # 秒
data['quarter'] = data['data_time'].dt.quarter  # 季度
data['week'] = data['date'].dt.week             # 周
data['weekday'] = data['date'].dt.weekday       # 周几，0为周一
data['yearmonth'] = data['data_time'].dt.strftime('%Y-%m')
data['halfyear'] = data['data_time'].map(lambda d:'H' if d.month <= 6 else 'H2')
# data：转换为相对时间特征
data['deltaMonthToToday'] = datetime.date.today().month - data['date'].dt.month #距离今天的间隔（月数）
data['daysOfyear'] = data['date'].map(lambda d:366 if d.is_leap_year else 365)   #一年过去的进度
data['rateOfyear'] = data['date'].dt.dayofyear/data['daysOfyear']
data.head()

## 5.4. 派生特征

### 5.4.1. 单特征派生特征

（1）将数值转成百分位（标准化）

（2）将数值转成比率

（3）分箱

• 可以减少过拟合的风险，因为分箱相当于对于数据去粗粒度描述
• 增加稀疏数据的概率，减少计算量，因为0的数据变多了
• 减少噪声数据的影响，比如一组数据按照0~100均匀分布，当数据中突然出现一个10000的数据，如果不做分箱的化会对Logistic Regression这种模型的训练造成很大影响
• 方便特征衍生，因为数据离散化后就可以把特征直接相互做内积提升特征维度
• 离散化后可以提升模型的鲁棒性，比如我们仍以行驶里程为例，比如甲车30公里、乙车60公里，到了第二年甲车变成35公里，乙车变成70公里，这样数据大量发生了改变，理论上我们要更新模型。但是如果数据采用分箱算法，按行驶里程分箱逻辑，则第一年和第二年数据没有变化，模型也不用变。

• 等距（等宽）分箱
• 等频（等权重）分箱
• 聚类分箱
• 决策树分箱
• 有监督分箱，有监督分箱主要有best-ks分箱和卡方分箱。

x
x

x

y
y

y

（1）向量余弦

（2）面积

（3）斜率

## 6. 特征选择

。特征选择尝试剔除数据中的噪声。特征选择的方法包括基于统计和基于模型的特征选择。

## 6.1. 特征分析

### 6.1.1. 相关分析

“万物皆有联”，是大数据一个最重要的核心思维。

⑴完全相关：两个变量之间的关系，一个变量的数量变化由另一个变量的数量变化所惟一确定，即函数关系。

⑵不完全相关：两个变量之间的关系介于不相关和完全相关之间。

⑶不相关：如果两个变量彼此的数量变化互相独立，没有关系。

⑴正相关：两个变量的变化趋势相同，从散点图可以看出各点散布的位置是从左下角到右上角的区域，即一个变量的值由小变大时，另一个变量的值也由小变大。

⑵负相关：两个变量的变化趋势相反，从散点图可以看出各点散布的位置是从左上角到右下角的区域，即一个变量的值由小变大时，另一个变量的值由大变小。

⑴线性相关（直线相关）：当相关关系的一个变量变动时，另一个变量也相应地发生均等的变动。

⑵非线性相关（曲线相关）：当相关关系的一个变量变动时，另一个变量也相应地发生不均等的变动。

⑴单相关：只反映一个自变量和一个因变量的相关关系。

⑵复相关：反映两个及两个以上的自变量同一个因变量的相关关系。

⑶偏相关：当研究因变量与两个或多个自变量相关时，如果把其余的自变量看成不变（即当作常量），只研究因变量与其中一个自变量之间的相关关系，就称为偏相关。

#### Pearson相关系数 (Pearson Correlation)

[

1

1
]
[ − 1 ， 1 ]

[

1

1
]

，-1表示完全的负相关，+1表示完全的正相关，0表示没有线性相关。

ρ
X
,
Y
=
c
o
v
(
X
,
Y
)
σ
X
σ
Y
\rho_{X,Y}=\frac{cov(X,Y)}{\sigma _{X}\sigma_{Y}}

σ

X

σ

Y

c
o
v
(
X
,
Y
)

ρ
X
,
Y
=

i
=
1
n
(
X
i

X

)
(
Y
i

Y

)

i
=
1
n
(
X

X

)
2

i
=
1
n
(
Y

Y

)
2
\rho_{X,Y}=\frac{\sum_{i=1}^{n}(X_{i}-\overline{X})(Y_{i}-\overline{Y})}{\sqrt{\sum_{i=1}^{n}(X-\overline{X})^{2}}\sqrt{\sum_{i=1}^{n}(Y-\overline{Y})^{2}}}

i
=
1

n

(
X

X

)

2

i
=
1

n

(
Y

Y

)

2

i
=
1

n

(

X

i

X

)
(

Y

i

Y

)

X
X

X

Y
Y

Y

X
X

X

Y
Y

Y

Pearson Correlation速度快、易于计算，经常在我们数据分析员拿到数据（经过清洗和特征提取）之后第一时间所做的分析。

（1）各个特征两两直接相关分析

# Pearson 分析
def analysis_Pearson(df,names):
#names = ['price','fuelle','amount','Payment','vol','changes',
#           'fuel_month','fuel_day','changes_month','changes_day','fuel_interva','time_before']
correlations = df.corr(method='pearson',min_periods=1)  #计算变量之间的相关系数矩阵
correlations.to_excel('dcorr1.xlsx')
print(correlations)
# plot correlation matrix
fig = plt.figure() #调用figure创建一个绘图对象
cax = ax.matshow(correlations,cmap = 'inferno', vmin=-1, vmax=1)  #绘制热力图，从-1到1
fig.colorbar(cax)  #将matshow生成热力图设置为颜色渐变条
ticks = np.arange(0,8,1) #生成0-9，步长为1
ax.set_xticks(ticks)  #生成刻度
ax.set_yticks(ticks)
ax.set_xticklabels(names) #生成x轴标签
ax.set_yticklabels(names)
plt.show()
return correlations

（2）某特征与其他各个特征相关分析

def draw_bar(key_name,key_values):
plt.rcParams['font.sans-serif']=['SimHei'] #显示中文标签
plt.rcParams['axes.unicode_minus']=False
# 标准柱状图的值
def autolable(rects):
for rect in rects:
height = rect.get_height()
if height>=0:
plt.text(rect.get_x()+rect.get_width()/2.0 - 0.3,height+0.02,'%.3f'%height)
else:
plt.text(rect.get_x()+rect.get_width()/2.0 - 0.3,height-0.06,'%.3f'%height)
# 如果存在小于0的数值，则画0刻度横向直线
plt.axhline(y=0,color='black')
#归一化
norm = plt.Normalize(-1,1)
norm_values = norm(key_values)
map_vir = cm.get_cmap(name='inferno')
colors = map_vir(norm_values)
fig = plt.figure() #调用figure创建一个绘图对象
plt.subplot(111)
ax = plt.bar(key_name,key_values,width=0.5,color=colors,edgecolor='black') # edgecolor边框颜色
sm = cm.ScalarMappable(cmap=map_vir,norm=norm)  # norm设置最大最小值
sm.set_array([])
plt.colorbar(sm)
autolable(ax)
plt.show()
def draw_Pearson_bar(correlations,names):
values = correlations.iloc[0].values.tolist()
draw_bar(names,values)
return

### 6.1.2. 随机森林分析

G
i
n
i
Gini

G
i
n
i

G
i
n
i
(
p
)
=

k
=
1
K
p
k
(
1

p
k
)
=
1

k
=
1
K
p
k
2
Gini(p)=\sum_{k=1}^{K}p_{k}(1-p_{k})=1-\sum_{k=1}^{K}p_{k}^2

G
i
n
i
(
p
)
=

k
=
1

K

p

k

(
1

p

k

)
=

k
=
1

K

p

k

2

• p
k
p_{k}

p

k

表示选中的样本属于

k
k

k

类别的概率，则这个样本被分错的概率是

(
1

p
k
)
(1-p_{k})

(
1

p

k

)

• 样本集合中有

K
K

K

个类别，一个随机选中的样本可以属于这

k
k

k

个类别中的任意一个，因而对类别就加和。

V
I
M
VIM

V
I
M

G
i
n
i
Gini

G
i
n
i

G
I
GI

G
I

m
m

m

X
1

X
2

X
3

.
.
.
.
.
.
X
c
X_1，X_2，X_3，……X_c

X

1

X

2

X

3

.
.
.
.
.
.

X

c

，现在要计算出每个特征

X
j
X_j

X

j

G
i
n
i
Gini

G
i
n
i

V
I
M
j

G
i
n
i

VIM_j（Gini）

V
I

M

j

G
i
n
i

，亦即第

j
j

j

def FeatureRandomForestClassifier(df):
col_names = ['amount','id','price','fuelle','changes',
'fuel_month','fuel_day','fuel_interva','time_before']
df = df[col_names].fillna(0)
df_train_x,df_train_y,df_test_x,df_test_y = get_train_test_split(df,split_key='id',y='amount',percent=0.2)
x_train, y_train= df_train_x.values ,df_train_y.values.astype('int')
x_text, y_test = df_test_x.values , df_test_y.values
# n_estimators：森林中树的数量,随机森林中树的数量默认10个树，精度递增显著，但并不是越多越好，加上verbose=True，显示进程使用信息
# n_jobs  整数 可选（默认=1） 适合和预测并行运行的作业数，如果为-1，则将作业数设置为核心数
forest_model = RandomForestClassifier(n_estimators=10, random_state=0, n_jobs=-1)
forest_model.fit(x_train, y_train)
feat_labels = col_names[1:]
# 下面对训练好的随机森林，完成重要性评估
# feature_importances_  可以调取关于特征重要程度
importances = forest_model.feature_importances_
print("重要性：", importances)
x_columns = col_names[1:]
indices = np.argsort(importances)[::-1]
x_columns_indices = []
for f in range(x_train.shape[1]):
# 对于最后需要逆序排序，我认为是做了类似决策树回溯的取值，从叶子收敛
# 到根，根部重要程度高于叶子。
print("%2d) %-*s %f" % (f + 1, 30, feat_labels[indices[f]], importances[indices[f]]))
x_columns_indices.append(feat_labels[indices[f]])
print(x_columns_indices)
print(len(x_columns))
# 筛选变量（选择重要性比较高的变量）
threshold = 0.05
x_selected = x_train[:, importances > threshold]
plt.figure(figsize=(6, 6))
plt.rcParams['font.sans-serif'] = ["SimHei"]
plt.rcParams['axes.unicode_minus'] = False
plt.title("油价敏感集中各个特征的重要程度", fontsize=16)
plt.ylabel("import level", fontsize=12, rotation=90)
num = len(x_columns)
for i in range(num):
plt.bar(i, importances[indices[i]], color='blue', align='center')
plt.xticks(np.arange(num), x_columns_indices, rotation=90, fontsize=12)
plt.tight_layout()
plt.show()

### 6.1.3. 数据分布分析

def draw_scatter_matrix_his(df):
plt.rcParams['font.sans-serif']=['SimHei'] #显示中文标签
plt.rcParams['axes.unicode_minus']=False
#直方图矩阵（Scatterplot Matrix）散点图
pd.plotting.scatter_matrix(df,figsize=(8,8),diagonal='hist',alpha=0.2)
plt.show()

（1）高斯/正态分布

（2）泊松分布

SAMPLE_SIZE = 1000
mu = 3
loc = 1
#泊松分布
interva = stats.poisson.rvs(mu,loc,SAMPLE_SIZE)
plt.hist(interva) #画密度图
plt.show()

### 6.1.4. 核密度估计

# 画数据分布散点图，及核密度估计图
def draw_scatter_matrix(df):
plt.rcParams['font.sans-serif']=['SimHei'] #显示中文标签
plt.rcParams['axes.unicode_minus']=False
#核密度图矩阵（Scatterplot Matrix）散点图
pd.plotting.scatter_matrix(df,figsize=(8,8),diagonal='kde')
plt.show()

### 6.1.5. 周期性分析

• 较长：年度周期性趋势、季节性周期性趋势；
• 较短：月度周期性趋势、周度周期性趋势、天度周期性趋势、小时度周期性趋势。

## 6.2. 特征选择

• Filter：过滤法，按照发散性或者相关性对各个特征进行评分，设定阈值或者待选择阈值的个数，选择特征。
• Wrapper：包装法，根据目标函数（通常是预测效果评分），每次选择若干特征，或者排除若干特征。
• Embedded：嵌入法，先使用某些机器学习的算法和模型进行训练，得到各个特征的权值系数，根据系数从大到小选择特征。类似于Filter方法，但是是通过训练来确定特征的优劣。我们使用sklearn中的feature_selection库来进行特征选择。

### 6.2.2. 方差

V
a
r
[
X
]
=
p
(
1

p
)
\mathrm{Var}[X] = p(1 – p)

V
a
r

[
X
]
=

p
(
1

p
)

from sklearn.feature_selection import VarianceThreshold
#方差选择法，返回值为特征选择后的数据
#参数threshold为方差的阈值
VarianceThreshold(threshold=3).fit_transform(df)

### 6.2.3. 基于随机森林算法特征重要性排序

（1）特征选择的步骤

• 计算每个特征的重要性，并按降序排序
• 确定要剔除的比例，依据特征重要性剔除相应比例的特征，得到一个新的特征集
• 用新的特征集重复上述过程，直到剩下m个特征（m为提前设定的值）
• 根据上述代码中得到的各个特征集合特征集对应的袋外误差率，选择袋外误差率最低的特征集

（2）特征重要性的估计方法

### 6.2.4. 相关性

import pandas as pd
# 组合特征
titanic['Sex_pclass_combo'] = titanic['Sex']+'_pclass_'+titanic['Pclass'].astype(str)
titanic.Sex_pclass_combo.value_counts()
# onehot编码
Sex_pclass_combo = pd.get_dummies['Sex_pclass_combo'],drop_first = False,prefix = 'onehot'
Sex_pclass_combo.head()

### 6.2.5. 信息增益

（1）信息熵：

H
(
X
)
=

i

X
p
i
1
l
o
g
p
i
H(X) = \sum_{i \in X} p_i \frac {1} {log p_i }

H
(
X
)
=

i

X

p

i

l
o
g

p

i

1

（2）交叉熵：

H
p
,
q
(
X
)
=

i

X
p
i
1
l
o
g
q
i
H_{p,q}(X)=\sum_{i \in X} p_i \frac {1}{log q_i}

H

p
,
q

(
X
)
=

i

X

p

i

l
o
g

q

i

1

H
(
Y

X
=
x
)
H(Y|X=x)

H
(
Y

X
=

x
)

（3）信息增益：

D
K
L
(
p

q
)
=
H
(
p
,
q
)

H
(
p
)
D_{KL}\left ( p||q \right )=H\left ( p,q \right )-H\left ( p \right )

D

K
L

(
p

q
)

=

H

(
p
,
q
)

H

(
p
)

H
(
Y
)
>
=
H
(
Y

X
)
H(Y)>=H(Y|X)

H
(
Y
)
>

H
(
Y

X
)

#### 信息增益率

G
a
i
n
R
a
t
i
o
(
Y
,
X
)
=
G
a
i
n
(
Y
,
X
)
S
p
l
i
t
I
n
f
o
(
X
)
GainRatio(Y, X) = {Gain(Y, X) \over SplitInfo(X)}

G
a
i
n
R
a
t
i
o
(
Y
,
X
)
=

S
p
l
i
t
I
n
f
o
(
X
)

G
a
i
n
(
Y
,
X
)

S
p
l
i
t
I
n
f
o
(
X
)
=

i

X
p
i
1
l
o
g
p
i
=
H
(
X
)
SplitInfo(X)= \sum_{i \in X} p_i \frac{1}{log p_i} = H(X)

S
p
l
i
t
I
n
f
o
(
X
)
=

i

X

p

i

l
o
g

p

i

1

=

H
(
X
)

#### Python实现代码

# 计算信息增益，data为pandas dataframe，yname为条件列，求xname列的概率
def FeatureEntropy(data, xname, yname):
# 信息熵
def entropy(data, att_name):
'''
data: 数据集
att_name: 属性名
'''
levels = data[att_name].unique()
# 信息熵
ent = 0
for lv in levels:
pi = sum(data[att_name]==lv) / data.shape[0]
ent += pi*np.log(pi)
return -ent
# 条件熵
def conditional_entropy(data, xname, yname):
xs = data[xname].unique()
ys = data[yname].unique()
p_x = data[xname].value_counts() / data.shape[0]
ce = 0
for x in xs:
ce += p_x[x]*entropy(data[data[xname]==x], yname)
return ce
# 信息增益
def gain(data, xname, yname):
en = entropy(data, yname)
ce = conditional_entropy(data, xname, yname)
print('yy条件下, xx的信息熵:{}'.format(ce))
return en - ce
def gain_ratio(data, xname, yname):
g = gain(data, xname, yname)
si = entropy(data, xname)
print('信息增益:{}'.format(g))
print('信息熵:{}'.format(si))
return g / si
g_rat = gain_ratio(data,  xname, yname)
print('信息增益率:{}'.format(g_rat))
return g_rat
yy条件下, xx的信息熵:1.8741493088501542

### 6.2.6. 互信息

p
(
X
,
Y
)
p(X,Y)

p
(
X
,
Y
)

p
(
X
)
p
(
Y
)
p(X)p(Y)

p
(
X
)
p
(
Y
)

X
X

X

Y
Y

Y

，如果其联合分布为

p
(
x
,
y
)
p(x,y)

p
(
x
,
y
)

，边缘分布为

p
(
x
)
p(x)

p
(
x
)

p
(
y
)
p(y)

p
(
y
)

，则互信息可以定义为：

I
(
X
;
Y
)
=

x

X

y

Y
p
(
x
,
y
)
l
o
g
p
(
x
,
y
)
p
(
x
)
p
(
y
)
I(X;Y)=\sum_{x \in X} \sum_{y \in Y} p(x,y) log \frac{p(x,y)}{p(x)p(y)}

I
(
X
;
Y
)
=

x

X

y

Y

p
(
x
,
y
)
l
o
g

p
(
x
)
p
(
y
)

p
(
x
,
y
)

I
(
X
;
Y
)
=
H
(
X
)

H
(
X

Y
)
I(X;Y)=H(X) – H(X|Y)

I
(
X
;
Y
)
=

H
(
X
)

H
(
X

Y
)

H
(
X
)
H(X)

H
(
X
)

X
X

X

H
(
X

Y
)
H(X|Y)

H
(
X

Y
)

Y
Y

Y

X
X

X

I
(
X
;
Y
)
I(X;Y)

I
(
X
;
Y
)

Y
Y

Y

（1）pearson相关系数

（2）互信息

['id' 'amount' 'fuelle' 'fuel_interva' 'amount_mean' 'fuel_mean'
'fuel_interva_mean' 'time_before' 'amount_per' 'fuelle_per'
'fuel_interva_per' 'amount_skew' 'fuelle_skew' 'fuel_interva_skew'
'amount_kurt' 'fuel_interva_kurt' 'fuelle_kurt']
[7, 8, 9, 11, 12, 13, 14, 16]
[0.01018806 0.19962888 0.34711295 0.28081759 0.09184614 0.10353152
0.14419254 0.5478874  0.54111304 0.61332275 0.25363344 0.53352316
0.55300996 0.42932777 0.494555   0.17967126 0.60378084]
def FeatureMutual_info(df):
df = df.fillna(0)
df_train_x,df_train_y,df_test_x,df_test_y = get_train_test_split(df,split_key='id',y='price_sensitive',percent=0.2)
X_train, y_train= df_train_x, df_train_y
X_test, y_test= df_test_x, df_test_y
sns.heatmap(df.corr(), annot= True, fmt= '.2f')
selector = SelectKBest(mutual_info_classif, k=8).fit(X_train, y_train)  # 保留8个特征
select_feature = selector.get_support(indices=True)
print(select_feature)
select_feature = select_feature.tolist()
Scores= selector.scores_
print(select_feature)
print(Scores)
X_new_train = selector.transform(X_train)
X_new_test = selector.transform(X_test)
clf = RandomForestClassifier(n_estimators=10, random_state=0, n_jobs=-1)
clf.fit(X_new_train, y_train)
get_socre(y_test, clf.predict(X_new_test))
#采用OVO的方式进行逻辑回归函数参数的定义，结果明显好于OVR方式
clf = LogisticRegression(multi_class="multinomial",solver="newton-cg")
clf.fit(X_new_train, y_train)
get_socre(y_test, clf.predict(X_new_test))
plt.show()
return

[+]F1 score : 0.825

[+]acc score: 0.825

[+]F1 score : 0.835

[+]acc score: 0.835

### 6.2.7. 特征组合

（1）目的：

（2）方法：

• 多个连续变量： 加减乘除运算
• 多个类别型变量： 所有值交叉组合

### 6.2.8 PCA降维

PCA(Principal Component Analysis)，即主成分分析方法，是一种使用最广泛的数据降维算法。PCA的主要思想是将n维特征映射到k维上，这k维是全新的正交特征也被称为主成分，是在原有n维特征的基础上重新构造出来的k维特征。PCA的工作就是从原始的空间中顺序地找一组相互正交的坐标轴，新的坐标轴的选择与数据本身是密切相关的。其中：

import numpy as np
from sklearn.decomposition import PCA
X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2],[2,3]])
pca = PCA(n_components=2)
NewX = pca.fit_transform(X)
print(X)
print(NewX)
print('各维度的方差:{}'.format(pca.explained_variance_))
print('各维度的方差值占总方差值的比例:{}'.format(pca.explained_variance_ratio_))
pca = PCA(n_components=1)
NewX = pca.fit_transform(X)
print(NewX)
print('各维度的方差值占总方差值的比例:{}'.format(pca.explained_variance_ratio_))

## 6.3. 特征选择与机器学习、深度学习

### 6.3.2. 如何选择或衡量机器学习、深度学习这两种方法

[1].《基于Pandas实现皮尔逊相关与余弦相似度在工业大数据分析中的应用实践》
CSDN博客 ， 肖永威 ， 2020.08

[2].《一篇带你学会相关分析》

[3].《《大数据时代》读书笔记》
CSDN博客 ， 肖永威 ， 2016.06

[4].《Python机器学习笔记：随机森林算法》

[5].《数据分析 第三篇：数据特征分析（分布+帕累托+周期）》

[6]. 《深度学习如何处理信息实现智慧之信息熵、相对熵、交叉熵等》
CSDN博客， 肖永威 ，2020年01月

[7].《Python Matplotlib绘制渐变色柱状图（bar）并加边框和配置渐变颜色条（colorbar）》
CSDN博客 ，肖永威 ，2020.09

[8].《机器学习中，有哪些特征选择的工程方法？》

[9].《信息熵信息增益率基尼系数原理和pandas实战》
DataScience ，2018.09

[10].《机器学习+特征工程vs深度学习—如何选择》
CSDN博客 ， 海晨威 ，2018年10月

[11].《信息论（1）——熵、互信息、相对熵》

[12].《浅谈常见的特征选择方法》

[13].《信号下的基本时域频域特征(上)》

[14].《如何生成派生特征》

[15].《Python科学计算初探——余弦相似度》
CSDN博客 ， 肖永威 ，2018.04

[16].《已知多边形各点平面坐标，Python实现求面积》
CSDN博客 ，肖永威 ，2018年4月

[17].《特征组合&特征交叉 (Feature Crosses)》
segmentfault 思否, kugua233 ，2018.05

[18].《python随机模块random的22种函数》
CSDN博客， Elenstone ，2020年5月

[19].《特征工程之分箱–卡方分箱》

[ 20.《特征工程之特征分箱（决策树分箱、卡方分箱、bestks以及评价标准WOE和IV)》
CSDN博客 ， Donreen ，2020年9月

[21].《数据降维-PCA主成分分析》