# 2.特征工程

## 1. 数据预处理

### 1.1. 数据过滤

    区隔化模型，替每个客群找出适合它的变量和模型，不同群的数据分别用不同类型来做评估。

| 形态     | 说明                                     |
| ------ | -------------------------------------- |
| Type 1 | 训练80% + 测试20%（训练数据做区隔化模型）              |
| Type 2 | 训练80% + 测试20%（在测试数据做区隔化模型，测试不同群效果是否不同） |

> 二种场景有所不同。

### 1.2. 缺失值填补

#### 1.2.1. 直接忽略法

**1. 针对所有数据**

    有缺失值，整笔删除（机器学习中不允许空值）

1. 特点：
   1. 最简单的方法
   2. 搜集数据量很多，缺失数据占一小部分，可删除
   3. 分类建模时，数据\*\*分类标记（Class Label）\*\*为空，无法正确分类，可删除
2. 缺点：
   1. 数据缺失比例大时，造成数据流失。

**2. 针对字段**

1. 字段有缺失值，整个字段删除
   1. 处理数据缺失最简单的方法
   2. 缺失数据占整个字段所有数据比例过大（$$> 50%$$），直接删除
2. 将整个字段转换成**指示变量（Indicator Variable）**
   1. 处理缺失的特殊方法
   2. 缺失数据占整个字段所有数据比例过大（$$> 50%$$），可使用这种方法
   3. 使用此方法理论基础：**空值也是行为的一种呈现**。

#### 1.2.2. 人工填补

**缺点**：当数据缺失过多，耗时且人力负担沉重。

#### 1.2.3. 自动填补

**1. 类别型**

1. 填充一个通用常数，如：`未知/Unknown`，产生新类。
2. 填充该字段的众数（Mode）
   1. **缺点**：不够客观
   2. 可分群求众数（每一群的众数有所不同，分群填补可能更客观）
3. 利用**模型**求出比较可能的值来填入：当做分类问题处理「**精确的做法**」。

**注意点**：算法选择上，要能接受输入字段有空值而依然能建立模型的算法：KNN、随机森林、XGBoosting是常用选择（也可建立数字预测模型）。

**2. 数值型**

1. 填入通用常数，如：`0`。
2. 填入该字段的整体平均值（Mean）、或中位数
   1. **缺点**：不够客观
   2. 对统计结果影响不大
   3. 也可以分群做平均
3. 利用**模型**求出比较可能的值来填入：当做数字预测问题处理。

**注意点**：算法选择上，要能接受输入字段有空值而依然能建立模型的算法（和分类一样）。

### 3. 初级转换

#### 3.1. 类别字段编码

* One-Hot Encoding（机器学习领域说法）
* Dummying（统计和学术研究说法）

> 以上两种等价，叫法不同！

    虚拟变量小心**虚拟变量陷阱**（Dummy Variable Trap）：变量之间会有多重共线性或高度相关的情形发生。通常做One-Hot Encoding后会删除其中一个栏位（少一个），防止虚拟变量陷阱。

例子：

```python
([
    ["A"],
    ["B"],
    ["A"],
    ["C"],
    ["A"]
])
# 编码后生成（有值为1，无值为0）：
([
    [1,0,0],    # A=1,B=0,C=0
    [0,1,0],    # A=0,B=1,C=0
    [1,0,0],    
    [0,0,1],    # A=0,B=0,C=1
    [1,0,0]
])
# A、B、C分别代表位置1，2，3，有值为1，无值为0，生成01矩阵
```

* 多标签编码

    用于描述一个对象的多种不同的特征标签，标签会超过一个。

例子（**多标签问题**）：

```python
([
    ["A","B"], 
    ["C","D"],
    ["A","B"],
    ["E","B"],
    ["A","D"]
])
# 编码后生成（有值为1，无值为0）：
([
    [1,1,0,0,0],    # A=1,B=1,C=0,D=0,E=0
    [0,0,1,1,0],    # A=0,B=0,C=1,D=1,E=0
    [1,1,0,0,0],    
    [0,1,0,0,1],    # A=0,B=1,C=0,D=0,E=1
    [1,0,0,1,0]
])
```

#### 3.2. 顺序字段编码

    顺序字段编码时要**特别注意数值的大小**，数值大小也许会对计算产生影响，所以编码过程中需要思考数值本身具有的业务意义，再进行编码。

### 4. 高级转换

#### 4.1. 一般化 Data Generalization

    **方法一**：类别型字段的一般化操作，利用概念阶层对类别进行提升（提升一层或其他），如下图：

![](https://3776797973-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MkW0vdxiACBavm67CgB%2Fuploads%2Fgit-blob-0fd05180146dac1b077cc8b6bd8a46fce22fccfd%2F2021-10-12-10-03-35.png?alt=media)

    **方法二**：先把教育程度排序，分别计算每种值导致目标字段的概率，根据目标字段的概率进行替换（根据和目标字段关系运算）。

#### 4.2. 离散化 Data Discretization

    一般是数值型字段转换成类别型，优点：

1. 使数据精简，降低数据复杂度，让数据容易理解。
2. 可支持许多无法处理数值型字段的算法。
3. 提高分类器稳定性，提升分类模型准确度。
4. 可找出输入字段在目标字段的趋势（Trend），有助于未来解读。

    离散化结果需要和目标值有一定的趋势，切割出数个区间来取代值域上众多的数据数值。

1. 人工分离法
2. 基本装箱法Binning Method
   1. 等宽（Equal-Width-Interval）装箱
   2. 等频（Equal-Frenquency-Interval）装箱法

    离散化的结果需要**易于解释**——这一点也十分重要。

## 2. 特征工程概要

    **数据和特征**决定了机器学习的上限，**模型和算法**只是在逼近这个上限，**特征工程**是机器学习成功的关键因素；特征工程目的是将字段转换为能更好**表示潜在问题**的特征，提高学习效能。

### 2.1. 重要性

* 特征越好，灵活性越强
* 特征越好，构建的模型越简单
* 特征越好，模型的性能越出色

### 2.2. 步骤

1. 建立机器学习模型的Baseline Model（基模型）
2. 使用一种或多种特征工程技术处理原始数据
3. 重新建立机器学习模型，并比较Baseline Model
4. 效能大于某个临界值，代表它有益

    特征工程之前，**特征理解**和**特征改进**。

### 2.3. 特征理解

* 数据是结构还是非结构
* 字段类型：数值、类别、顺序、二元
* 探索式数据分析 Exploratory Data Analysis
  * 描述性统计 Descriptive Statistics（生成数据质量报告）
  * 数据可视化 Data Vistualization

### 2.4. 特征改进

1. 数据清洗
2. 数据编码
   1. 标准化：Data Standardization
      1. Z-Score, Min-Max
   2. 一般化和离散化
   3. 数据归一化：Data Normalization
      1. L1归一化（两个值相加总和为1）
      2. L2归一化
3. 非结构数据结构化

## 3. 涵盖范围

### 3.1. 特征建构：Feature Construction

**运用外部数据**

    使用外部特征数据（公司的、OpenSource）的领域知识来补充特征数据。

**运用数据探索**

    使用统计分析的图示查看每种特征引起的最终结果，并进行类似描述性分析的操作，最主要的是查看该特征的相关信息对目标值的影响，根据原始变量产生新的衍生性变量。

**运用专家经验**

    根据领域专家的知识经验选择相关特征。

**运用数据分析**

    （略）案例中使用了**决策树**做基本分析。**决策树**的一个核心问题，一次只能考虑一个字段，无法同时考虑两个字段。

    另外一种方法：**多项式特征/交互特征**：`degree`决定了多项式最大项，如有两个特征$$x\_1, x\_2$$

| degree参数   | 说明                                             |
| ---------- | ---------------------------------------------- |
| degree = 2 | $$x\_1, x\_2, x\_1^2, x\_2^2$$                 |
| degree = 3 | $$x\_1, x\_2, x\_1^2, x\_2^2, x\_1^3, x\_2^3$$ |

    `PolynomialFeatures`默认交互特征：$$x\_1x\_2$$。

### 3.2. 特征选择：Feature Selection

> 无效变量：不相关变量、多余变量

#### 3.2.1. 无效变量

    **维度的诅咒**问题。

    两种方法删除无效变量：`Redundancy`和`Irrelevancy`

* `Redundancy`：两个变量效果一致，多余了一个，这两个变量一起考虑或删除其中一个。
* `Irrelevancy`：这两个变量和目标之间关系不密切，不相关，无法带来信息，直接移除。

#### 3.2.2. 统计方式选择

    方差阈值化（Variance Thresholding，VT），计算每一个数值型字段的方差，如果方差低于某个阈值，那么该字段包含信息量不够，这样的字段可以拿掉。

$$\frac{1}{n\_i}\sum\limits\_{i=1}^n(x\_i - \mu)^2$$

    其中$$x$$是特征向量，$$x\_i$$是特征值，$$\mu$$是特征均值。注意：

1. 方差**不能**事先标准化，尤其是Z-Score标准化，因此，如果特征集包含了不同单位（`different units`）时VT将会不起作用。
2. 方差门槛值必须手工设定（设置阈值）。

> 如果每个特征方差都是0或1，那么VT将无法工作。

    如果是二元变量（男、女），那么VT的方法使用**概率计算**如：

$$Var(x)=p(1-p)$$

    男女编码成`10`，$$p$$是1的概率，$$1-p$$是0的概率，最终计算的$$Var(x)$$值越大越重要。

    也可以使用**统计检验的方式**解决输入字段和目标字段不相关（`Irrelevancy`）的问题（VT不考虑和目标字段的关联关系）

| 目标类型   | 检验类型 | 检验方式        |
| ------ | ---- | ----------- |
| 类别（离散） | 类别   | 卡方检验/VT     |
| 类别（离散） | 数值   | ANOVA检验、T检验 |
| 数值（连续） | 类别   | ANOVA检验、T检验 |
| 数值（连续） | 数值   | 相关系数        |

**1. 卡方统计量**$$\chi^2$$**：**

$$\chi^2 = \sum\limits\_{i=1}^n\frac{(O\_i - E\_i)^2}{E\_i}$$

    真实值$$O\_i$$和期望值$$E\_i$$越接近表示二者无关，越不一致则表示二者有关，所以卡方值越大则表示二者关联性越高（越不一致）。

1. 必须先计算卡方值
2. 然后根据卡方计算`p-value`
3. 在`95%`置信水平之下，$$p-value < 0.05$$则为显著（重要）的关键字段

**2. T检验/ANOVA检验**

    T检验之前

1. 必须用**F检验**去检验每个字段样本变异数是否和母体相同：`p-value`越小代表变异数越有差异。
2. 然后计算**T检验**的`T-value`，然后根据它计算`p-value`。

    ANOVA检验

1. 先计算`F-value`
2. 根据`F-value`查表算出`p-value`
3. 在`95%`置信水平之下，$$p-value < 0.05$$则为显著（重要）的关键字段

#### 3.2.3. 高度相关

    两个特征高度相关（`Redundant`），计算两两之间过后移除掉其中一个，皮尔森$$>0.95$$的就可以直接移除。

#### 3.2.4. 模型方式

    主要是解决共线性（`Collinearity`）问题，可使用：

* 决策树：Decision Tree
* 随机森林
* XGBoost
* 逻辑回归中的逐步回归：Logistic Regression - Stepwise

    主要协助选择并过滤出重要且不具有共线性的变量，KO多余变量`Redundant`。

#### 3.2.5. 递归方式

    `RFECV`，`RFE`递归特征评估，`CV`交叉验证，反复训练一个模型，每次训练过后移除掉一个特征直到变差（`Accuracy`），递归式属于`Wrapper Methods`。

> Wrapper Method包含：
>
> * 向前法（Forward）
> * 向后法（递归，Backward）
> * 双向法（Bi-Direcation）

### 3.3. 特征转换：Feature Transformation

1. 线性的特征转换
   1. 和目标无关：PCA、NMF、SVD、TSVD
   2. 和目标有关：LDA
2. 非线性特征转换：
   1. 和目标无关：Kernel PCA、t-SNE
   2. 和目标有关：神经网络

    特征数量$$P\_{new} < P\_{original}$$，转换过后降低特征数量，这样做的缺点如：

1. 尽量减小损失
2. 依旧可以执行高质量的预测

    这种特征转换的一个问题是：可解释性不足，如果您想要解释性特别强，就必须做**特征选择**。

#### 3.3.1. 线性：PCA

    PCA——主成分分析，利用线性方式做维度消减，它会把特征投影到一个维度更小的空间，会保留大多数**方差比较大**的特征（非指导性技巧）——使用主成分取代原来的特征，如图：

![](https://3776797973-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MkW0vdxiACBavm67CgB%2Fuploads%2Fgit-blob-0922103d6c24ebfeb6323598f109901f7de5b185%2F2021-10-13-11-19-26.png?alt=media)

    将左侧`x,y`两个特征直接转换成主成分，主成分分析步骤如：

1. （隐藏步骤）处理之前做标准化
2. 计算协方差矩阵（Variance-Covariance Matrix）
3. 解出协方差特征值（Eigen Value）和特征向量（Eigen Vector）
4. 特征值从大到小排序，排序后分第一主成分、第二主成分

    在协方差矩阵$$A$$中，求出满足$$Ax=\lambda x$$的$$\lambda$$以及$$x$$，其中$$\lambda$$是特征值，$$x$$是特征向量。

#### 3.3.2. 线性：SVD/TSVD

    潜在语意分析（Latent Semantic Analysis,LSA）就是衍生出来的模型，它从庞大文字数据中找出词汇所拥有的潜在语意关联性，是广泛用在自然语言上的降维方式。

    LSA可计算词汇语意相似度、词汇与文件相似度，它可以将**词汇-文件**的矩阵降维，转换为潜在语意空间，这个过程就会使用SVD矩阵分解技术（奇异值分解）。

$$X = UDV^T \to \hat{X}=\hat{U}\hat{D}\hat{V}^T$$

![](https://3776797973-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MkW0vdxiACBavm67CgB%2Fuploads%2Fgit-blob-731b5b4cfa6af402e1a30e4301a14bd4676ae937%2F2021-10-13-11-32-59.png?alt=media)

    中间去掉了部分特征经过了特征转换，如图只转换前两个维度，忽略其他维度。左边相乘结果：左边**词和文件的关系**、右边是**词和语义的关系**。

    LSA的缺陷：

1. LSA通过奇异值分解降维后，语义维度形成正交，矩阵中有可能有负值，造成解读困难：使用NMF/LDA解决。
2. 奇异值分解费时，尤其是关键词量大时
3. 新词加入时，需重新进行矩阵分解。

    取而代之将SVD替换成TSVD（Truncated SVD），它可以产生一个指定维度分解矩阵，运算速度更快。

#### 3.3.3. 线性：NMF

    NMF（Non-negative Matrix Factorization）是一个**非监督**的线性维度降维技术，将原始空间对应到语义空间，它不会产生负值。

1. 给定需要转换的特征维度`r`
2. NMF的分解写成$$V \approx WH$$，其中$$V$$是原始的$$d \times n$$特征矩阵（$$d$$是关键词，$$n$$是文件），$$W$$就是$$d \times r$$，$$H$$就是$$r \times n$$。
3. NMF的一个主要改动就是，生成的矩阵不会包含负值（非负矩阵）。

    NMF特征

1. 原始矩阵中所有元素都是非负数
2. 分解后矩阵中所有元素都是非负数
3. 潜在语意控件维度不一定正交

    NMF步骤

1. 将矩阵$$W, H$$初始化，值为正
2. 将$$H$$视为常数，更新$$W$$
3. 将$$W$$视为常数，更新$$H$$
4. 当$$W, H$$都收敛，停止计算

#### 3.3.4. 线性：LDA

    LDA（Linear Discriminant Analysis）是和目标有关的线性转换，它是一个分类的降维算法，利用线性区别。它的工作原理类似于PCA，但是二者新维度方向不同：

1. PCA是最大化数据中的变异，并且保留数据中的变异，非监督
2. LDA是把不同的两个类别之间的距离拉远（分开），监督

    LDA步骤

1. 计算每个类别的平均值向量
2. 计算每个类别内$$S\_w$$和类别间$$S\_B$$的散布矩阵（Scatter Matrix）
3. 解出$$S\_w^{-1}S\_B$$矩阵的特征值（Eigen Value）和特征向量（Eigen Vector）
4. 将特征值从大到小排序，保留$$K$$个特征向量
5. 使用得到的$$K$$个特征向量将数据投影到新的空间

> LDA是希望把各类数据分得越开越好，PCA则是保留数据中的变异，注意二者区别。

![](https://3776797973-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MkW0vdxiACBavm67CgB%2Fuploads%2Fgit-blob-cc4a81ad146d4620424efbdc45fa813697df7ad6%2F2021-10-13-11-58-33.png?alt=media)

    左侧LDA分类效果很好，每一类直接可以用垂直直线分开，而PCA的分类效果不好，LDA参考了目标字段（监督），PCA则不参考（非监督）。

#### 3.3.5. 非线性：Kernel PCA

    PCA的一个扩展，使用核kernal函数，允许对非线性数据进行降维，比PCA多了一个核函数步骤。将原始坐标投影到一个线性可分的空间，核函数（此处核函数和SVM的核函数一模一样）如：

1. RBF：高斯核函数
2. Poly：多项式核函数
3. Sigmoid：Sigmoid核函数
4. Linear：线性核函数（使用Linear则是标准PCA）

> Kernal(Linear) PCA = PCA，比PCA多一个核函数的过程，转换到另外的特征空间。

#### 3.3.6. 非线性：t-SNE

    t-SNE（t-Distributed Stochastic Neighbor Embedding）是将复杂的高维数据降维到**二维**或**三维**（固定目标维度），有助于低维空间可视化，降维后相似数据会聚在一起，方便理解。

    步骤

1. 利用高斯分布来计算在高维数据中任意两点$$x\_i, x\_j$$的相似度$$H$$
2. 在低维空间中，随机产生与高维空间中相同数量的数据点，并利用$$t$$分布计算低维空间两点$$y\_i,y\_j$$的相似度$$L$$。
3. 更新数据点$$y\_i$$，拉近$$H$$和$$L$$的相似度分布
4. 重复上述步骤，使得$$H$$和$$L$$的相似度分布趋近相同

> t分布可以将原本高维空间彼此邻近的结构，在低维空间更近，原本更远的结构，低维空间更远。

#### 3.3.7. 非线性：神经网络

    神经网络会参考目标字段（监督式），字段和字段相关性可通过神经网络学习来处理，后续做特征部分做详细说明。

#### 3.3.8. 总结

| 算法               | 监督/非监督 | 线性/非线性 |
| ---------------- | ------ | ------ |
| PCA              | x      | 线性     |
| NMF              | x      | 线性     |
| SVD,TSVD         | x      | 线性     |
| Kernel PCA       | x      | 非线性    |
| T-SNE            | x      | 非线性    |
| AutoEncoder      | x      | 非线性    |
| LDA              | o      | 线性     |
| NN/Deep Learning | o      | 非线性    |

### 3.4. 特征学习：Feature Learning

> 在示例中，最终都是运行决策树算法`C 5.0`，运行属性对目标的影响结果。

#### 3.4.1. 类别：关联规则为基础

    决策树算法是通过不断迭代对数进行切割来划分数据集，表现很好，但是：

1. 这类算法只能同时考虑一个属性
2. 并且这类算法不去参考属性和属性之间的相关性

    字段相关性分两类：**类别型**、**数值型**，最终有三类：

* Categorical-Type：类别型
* Numerical-Type：数值型
* Categorical-Numerical-Mix：混合型

**1. CAM模型**

    CAM（Classification based on Association Mining）模型用来解决相关性的组合型爆炸问题。

1. 先把训练数据执行关联规则挖掘
2. 此处的**关联规则**使用了多维度关联规则挖掘
3. 关联规则挖掘分析之后再将数据执行传统决策树算法

> 数值型离散化，可以根据目标字段直接运行决策树得到数值分布结果。

#### 3.4.2. 数值：神经网络为基础

    神经网络决策树（NDT，Neural Decision Tree）：

$$S(t+1) > S(t) = BUY$$

> NDT结合了神经网络和传统决策树来分析案例

    数据准备：先做Max-Min Normalization，将特征极值正规化到\[0,1]范围，然后运行神经网络，将$$S(t)$$转换成$$S(t+1)$$新的坐标空间（隐藏层的组合函数坐标空间）。

#### 3.4.3. 深度学习为基础

    Autoencoder架构：学习一个**压缩表示法**，它包含了一个encoder层和decoder层。

![](https://3776797973-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MkW0vdxiACBavm67CgB%2Fuploads%2Fgit-blob-348b39b045825945a5a5d9d94884a5b31213eab1%2F2021-10-14-09-32-30.png?alt=media)

    中间的隐藏层会很多，越多隐藏层产生出来的特征有可能会越好（**左右隐藏层是对称的**），训练完成后保留Encoder的**模型**。

```python
X = model.predict(X)
```

    没有使用目标字段，是**非监督的**，但又使用了监督方式在执行，所以又称为自监督（Self-Supervised）的方式学习。AE变种：

* Auto Encoder：AE，标准的
* Variational AE：VAE
* Denoising AE：DAE
* Sparse AE：SAE

    它是一个多层神经网络，称为自编码器，隐藏层的向量可以降维。

**1. VAE：Variational AE**

    VAE在编码器阶段添加了一个约束，产生的code服从单位高斯分布：Gaussian Distribution。

![](https://3776797973-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MkW0vdxiACBavm67CgB%2Fuploads%2Fgit-blob-e85d5ca3b09cfbe22e359eaa3f12596c61f3f688%2F2021-10-14-09-44-30.png?alt=media)

图中$$\mu\_1,\mu\_2$$是平均值向量节点，而$$ho\_1^2,\rho\_2^2$$是标准差向量节点，中间得到的结果做随机抽样，得到中间表示法，服从单位高斯分布。

**2. DAE：Denoising AE**

    给定一个带有噪音的图像，让该Encoder具有抗噪的能力，它是一种学习对图片去噪（Denoise）的神经网络，实际过程中在输入内随机加入噪声数据，让机器执行后回复到无噪声的数据状态。

**3. SAE：Sparse AE**

    AE基础上限制每次得到的中间表示尽量**稀疏**，使自动编码器将每个输入表示为少量节点组合，中间的非零值节点称为**活动节点**。

**4. RBM：受限波尔兹曼机**

    也可用于深度学习网络，深度信念网络使用多个RBM堆栈而成，并可使用梯度相加法和反向传播算法进行调优。

![](https://3776797973-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MkW0vdxiACBavm67CgB%2Fuploads%2Fgit-blob-b6b89790c6a9b3cf1bd0842e43b6c9fdfd2ba3da%2F2021-10-14-09-51-42.png?alt=media)

* Encoder和Decoder的权重实际是一样的

#### 3.4.4. 词嵌入为基础

    词嵌入（Word Embedding）是一种将文本中词转换成数字向量的方法，把一个维数为所有词数量的高维空间嵌入到一个维数低得多的**连续向量空间**，每个单词或词组被映射为实数域上的向量，词嵌入结果就生成了词向量。

    词向量的数量远小于词本身的数量，词嵌入具有语义层的效果。

![](https://3776797973-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MkW0vdxiACBavm67CgB%2Fuploads%2Fgit-blob-9782c317cf8116f48ef516a8a8f33e2ef61ca277%2F2021-10-14-09-57-59.png?alt=media)

    词嵌入模型**不考虑权重**，词袋模型才**考虑权重**。
