mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
234 lines
14 KiB
Markdown
234 lines
14 KiB
Markdown
# 模型数据准备与评估
|
||
|
||
{{#include ../banners/hacktricks-training.md}}
|
||
|
||
模型数据准备是机器学习流程中的关键步骤,因为它涉及将原始数据转换为适合训练机器学习模型的格式。此过程包括几个关键步骤:
|
||
|
||
1. **数据收集**:从各种来源收集数据,例如数据库、API或文件。数据可以是结构化的(例如,表格)或非结构化的(例如,文本、图像)。
|
||
2. **数据清理**:删除或更正错误、不完整或不相关的数据点。此步骤可能涉及处理缺失值、删除重复项和过滤异常值。
|
||
3. **数据转换**:将数据转换为适合建模的格式。这可能包括归一化、缩放、编码分类变量,以及通过特征工程等技术创建新特征。
|
||
4. **数据拆分**:将数据集划分为训练集、验证集和测试集,以确保模型能够很好地泛化到未见过的数据。
|
||
|
||
## 数据收集
|
||
|
||
数据收集涉及从各种来源收集数据,这些来源可以包括:
|
||
- **数据库**:从关系数据库(例如,SQL数据库)或NoSQL数据库(例如,MongoDB)提取数据。
|
||
- **API**:从网络API获取数据,这些API可以提供实时或历史数据。
|
||
- **文件**:从CSV、JSON或XML等格式的文件中读取数据。
|
||
- **网络爬虫**:使用网络爬虫技术从网站收集数据。
|
||
|
||
根据机器学习项目的目标,数据将从相关来源提取和收集,以确保其代表问题领域。
|
||
|
||
## 数据清理
|
||
|
||
数据清理是识别和更正数据集中错误或不一致的过程。此步骤对于确保用于训练机器学习模型的数据质量至关重要。数据清理中的关键任务包括:
|
||
- **处理缺失值**:识别和处理缺失的数据点。常见策略包括:
|
||
- 删除缺失值的行或列。
|
||
- 使用均值、中位数或众数插补缺失值。
|
||
- 使用K近邻(KNN)插补或回归插补等高级方法。
|
||
- **删除重复项**:识别并删除重复记录,以确保每个数据点都是唯一的。
|
||
- **过滤异常值**:检测并删除可能影响模型性能的异常值。可以使用Z-score、IQR(四分位距)或可视化(例如,箱线图)等技术来识别异常值。
|
||
|
||
### 数据清理示例
|
||
```python
|
||
import pandas as pd
|
||
# Load the dataset
|
||
data = pd.read_csv('data.csv')
|
||
|
||
# Finding invalid values based on a specific function
|
||
def is_valid_possitive_int(num):
|
||
try:
|
||
num = int(num)
|
||
return 1 <= num <= 31
|
||
except ValueError:
|
||
return False
|
||
|
||
invalid_days = data[~data['days'].astype(str).apply(is_valid_positive_int)]
|
||
|
||
## Dropping rows with invalid days
|
||
data = data.drop(invalid_days.index, errors='ignore')
|
||
|
||
|
||
|
||
# Set "NaN" values to a specific value
|
||
## For example, setting NaN values in the 'days' column to 0
|
||
data['days'] = pd.to_numeric(data['days'], errors='coerce')
|
||
|
||
## For example, set "NaN" to not ips
|
||
def is_valid_ip(ip):
|
||
pattern = re.compile(r'^((25[0-5]|2[0-4][0-9]|[01]?\d?\d)\.){3}(25[0-5]|2[0-4]\d|[01]?\d?\d)$')
|
||
if pd.isna(ip) or not pattern.match(str(ip)):
|
||
return np.nan
|
||
return ip
|
||
df['ip'] = df['ip'].apply(is_valid_ip)
|
||
|
||
# Filling missing values based on different strategies
|
||
numeric_cols = ["days", "hours", "minutes"]
|
||
categorical_cols = ["ip", "status"]
|
||
|
||
## Filling missing values in numeric columns with the median
|
||
num_imputer = SimpleImputer(strategy='median')
|
||
df[numeric_cols] = num_imputer.fit_transform(df[numeric_cols])
|
||
|
||
## Filling missing values in categorical columns with the most frequent value
|
||
cat_imputer = SimpleImputer(strategy='most_frequent')
|
||
df[categorical_cols] = cat_imputer.fit_transform(df[categorical_cols])
|
||
|
||
## Filling missing values in numeric columns using KNN imputation
|
||
knn_imputer = KNNImputer(n_neighbors=5)
|
||
df[numeric_cols] = knn_imputer.fit_transform(df[numeric_cols])
|
||
|
||
|
||
|
||
# Filling missing values
|
||
data.fillna(data.mean(), inplace=True)
|
||
|
||
# Removing duplicates
|
||
data.drop_duplicates(inplace=True)
|
||
# Filtering outliers using Z-score
|
||
from scipy import stats
|
||
z_scores = stats.zscore(data.select_dtypes(include=['float64', 'int64']))
|
||
data = data[(z_scores < 3).all(axis=1)]
|
||
```
|
||
## 数据转换
|
||
|
||
数据转换涉及将数据转换为适合建模的格式。此步骤可能包括:
|
||
- **归一化与标准化**:将数值特征缩放到一个共同范围,通常是 [0, 1] 或 [-1, 1]。这有助于提高优化算法的收敛性。
|
||
- **最小-最大缩放**:将特征重新缩放到固定范围,通常是 [0, 1]。使用公式: `X' = (X - X_{min}) / (X_{max} - X_{min})`
|
||
- **Z-分数标准化**:通过减去均值并除以标准差来标准化特征,结果是均值为 0,标准差为 1 的分布。使用公式: `X' = (X - μ) / σ`,其中 μ 是均值,σ 是标准差。
|
||
- **偏度和峰度**:调整特征的分布以减少偏度(不对称性)和峰度(尖峭度)。这可以通过对数、平方根或 Box-Cox 变换等变换来完成。例如,如果一个特征具有偏斜分布,应用对数变换可以帮助将其标准化。
|
||
- **字符串标准化**:将字符串转换为一致的格式,例如:
|
||
- 小写
|
||
- 移除特殊字符(保留相关字符)
|
||
- 移除停用词(不对意义贡献的常见词,如 "the"、"is"、"and")
|
||
- 移除过于频繁和过于稀有的词(例如,出现在超过 90% 文档中的词或在语料库中出现少于 5 次的词)
|
||
- 修剪空格
|
||
- 词干提取/词形还原:将单词减少到其基本或根形式(例如,将 "running" 变为 "run")。
|
||
|
||
- **编码分类变量**:将分类变量转换为数值表示。常见技术包括:
|
||
- **独热编码**:为每个类别创建二进制列。
|
||
- 例如,如果一个特征有类别 "red"、"green" 和 "blue",它将被转换为三个二进制列: `is_red`(100)、`is_green`(010) 和 `is_blue`(001)。
|
||
- **标签编码**:为每个类别分配一个唯一的整数。
|
||
- 例如,"red" = 0,"green" = 1,"blue" = 2。
|
||
- **序数编码**:根据类别的顺序分配整数。
|
||
- 例如,如果类别是 "low"、"medium" 和 "high",它们可以分别编码为 0、1 和 2。
|
||
- **哈希编码**:使用哈希函数将类别转换为固定大小的向量,这对于高基数分类变量非常有用。
|
||
- 例如,如果一个特征有许多独特的类别,哈希可以在保留一些类别信息的同时减少维度。
|
||
- **词袋模型 (BoW)**:将文本数据表示为单词计数或频率的矩阵,其中每行对应一个文档,每列对应语料库中的一个唯一单词。
|
||
- 例如,如果语料库包含单词 "cat"、"dog" 和 "fish",包含 "cat" 和 "dog" 的文档将表示为 [1, 1, 0]。这种特定表示称为 "unigram",并不捕捉单词的顺序,因此会丢失语义信息。
|
||
- **二元组/三元组**:扩展 BoW 以捕捉单词序列(二元组或三元组)以保留一些上下文。例如,"cat and dog" 将表示为二元组 [1, 1] 对于 "cat and" 和 [1, 1] 对于 "and dog"。在这些情况下,收集了更多的语义信息(增加了表示的维度),但一次仅限于 2 或 3 个单词。
|
||
- **TF-IDF(词频-逆文档频率)**:一种统计度量,评估一个词在文档中相对于文档集合(语料库)的重要性。它结合了词频(一个词在文档中出现的频率)和逆文档频率(一个词在所有文档中出现的稀有程度)。
|
||
- 例如,如果单词 "cat" 在文档中频繁出现但在整个语料库中很少出现,它将具有高 TF-IDF 分数,表明其在该文档中的重要性。
|
||
|
||
- **特征工程**:从现有特征中创建新特征,以增强模型的预测能力。这可能涉及组合特征、提取日期/时间组件或应用特定领域的变换。
|
||
|
||
## 数据拆分
|
||
|
||
数据拆分涉及将数据集划分为训练、验证和测试的不同子集。这对于评估模型在未见数据上的表现和防止过拟合至关重要。常见策略包括:
|
||
- **训练-测试拆分**:将数据集划分为训练集(通常占数据的 60-80%)、验证集(占数据的 10-15% 用于调整超参数)和测试集(占数据的 10-15%)。模型在训练集上训练,并在测试集上评估。
|
||
- 例如,如果您有一个包含 1000 个样本的数据集,您可能会使用 700 个样本进行训练,150 个进行验证,150 个进行测试。
|
||
- **分层抽样**:确保训练集和测试集中的类别分布与整体数据集相似。这对于不平衡数据集尤其重要,其中某些类别的样本可能显著少于其他类别。
|
||
- **时间序列拆分**:对于时间序列数据,数据集根据时间进行拆分,确保训练集包含早期时间段的数据,测试集包含后期时间段的数据。这有助于评估模型在未来数据上的表现。
|
||
- **K-折交叉验证**:将数据集拆分为 K 个子集(折),并训练模型 K 次,每次使用不同的折作为测试集,其余折作为训练集。这有助于确保模型在不同的数据子集上进行评估,从而提供更稳健的性能估计。
|
||
|
||
## 模型评估
|
||
|
||
模型评估是评估机器学习模型在未见数据上表现的过程。它涉及使用各种指标来量化模型对新数据的泛化能力。常见的评估指标包括:
|
||
|
||
### 准确率
|
||
|
||
准确率是正确预测实例占总实例的比例。计算公式为:
|
||
```plaintext
|
||
Accuracy = (Number of Correct Predictions) / (Total Number of Predictions)
|
||
```
|
||
> [!TIP]
|
||
> 准确性是一个简单直观的指标,但对于一个类占主导地位的不平衡数据集,它可能不适用,因为它可能会给出模型性能的误导性印象。例如,如果90%的数据属于类A,而模型将所有实例预测为类A,它将达到90%的准确性,但对于预测类B并没有用处。
|
||
|
||
### Precision
|
||
|
||
Precision是模型所有正预测中真实正预测的比例。它的计算公式为:
|
||
```plaintext
|
||
Precision = (True Positives) / (True Positives + False Positives)
|
||
```
|
||
> [!TIP]
|
||
> 精确度在假阳性代价高昂或不受欢迎的场景中尤为重要,例如在医疗诊断或欺诈检测中。例如,如果一个模型预测100个实例为正,但其中只有80个实际上是正的,则精确度为0.8(80%)。
|
||
|
||
### 召回率(敏感性)
|
||
|
||
召回率,也称为敏感性或真正阳性率,是所有实际正实例中真正阳性预测的比例。它的计算公式为:
|
||
```plaintext
|
||
Recall = (True Positives) / (True Positives + False Negatives)
|
||
```
|
||
> [!TIP]
|
||
> 召回率在假阴性代价高昂或不可取的场景中至关重要,例如在疾病检测或垃圾邮件过滤中。例如,如果一个模型识别出100个实际阳性实例中的80个,则召回率为0.8(80%)。
|
||
|
||
### F1 Score
|
||
|
||
F1分数是精确率和召回率的调和平均值,提供了两者之间的平衡。它的计算公式为:
|
||
```plaintext
|
||
F1 Score = 2 * (Precision * Recall) / (Precision + Recall)
|
||
```
|
||
> [!TIP]
|
||
> F1 分数在处理不平衡数据集时特别有用,因为它考虑了假阳性和假阴性。它提供了一个单一的指标,捕捉精确度和召回率之间的权衡。例如,如果一个模型的精确度为 0.8,召回率为 0.6,则 F1 分数大约为 0.69。
|
||
|
||
### ROC-AUC (接收者操作特征 - 曲线下面积)
|
||
|
||
ROC-AUC 指标通过在不同阈值设置下绘制真实阳性率(灵敏度)与假阳性率之间的关系,评估模型区分类别的能力。ROC 曲线下面积(AUC)量化模型的性能,值为 1 表示完美分类,值为 0.5 表示随机猜测。
|
||
|
||
> [!TIP]
|
||
> ROC-AUC 对于二元分类问题特别有用,并提供了模型在不同阈值下性能的全面视图。与准确率相比,它对类别不平衡的敏感性较低。例如,AUC 为 0.9 的模型表明它在区分正负实例方面具有很高的能力。
|
||
|
||
### 特异性
|
||
|
||
特异性,也称为真阴性率,是所有实际负实例中真阴性预测的比例。它的计算公式为:
|
||
```plaintext
|
||
Specificity = (True Negatives) / (True Negatives + False Positives)
|
||
```
|
||
> [!TIP]
|
||
> 特异性在假阳性代价高昂或不受欢迎的场景中很重要,例如在医学测试或欺诈检测中。它有助于评估模型识别负实例的能力。例如,如果一个模型正确识别了100个实际负实例中的90个,则特异性为0.9(90%)。
|
||
|
||
### Matthews Correlation Coefficient (MCC)
|
||
Matthews Correlation Coefficient (MCC) 是二元分类质量的衡量标准。它考虑了真正和假正、真负和假负,提供了模型性能的平衡视图。MCC的计算公式为:
|
||
```plaintext
|
||
MCC = (TP * TN - FP * FN) / sqrt((TP + FP) * (TP + FN) * (TN + FP) * (TN + FN))
|
||
```
|
||
where:
|
||
- **TP**: 真阳性
|
||
- **TN**: 真阴性
|
||
- **FP**: 假阳性
|
||
- **FN**: 假阴性
|
||
|
||
> [!TIP]
|
||
> MCC 的范围从 -1 到 1,其中 1 表示完美分类,0 表示随机猜测,-1 表示预测与观察之间的完全不一致。它对于不平衡数据集特别有用,因为它考虑了所有四个混淆矩阵组件。
|
||
|
||
### 平均绝对误差 (MAE)
|
||
平均绝对误差 (MAE) 是一种回归指标,测量预测值与实际值之间的平均绝对差。其计算公式为:
|
||
```plaintext
|
||
MAE = (1/n) * Σ|y_i - ŷ_i|
|
||
```
|
||
where:
|
||
- **n**: 实例数量
|
||
- **y_i**: 实例 i 的实际值
|
||
- **ŷ_i**: 实例 i 的预测值
|
||
|
||
> [!TIP]
|
||
> MAE 提供了对预测平均误差的直接解释,易于理解。与均方误差 (MSE) 等其他指标相比,它对异常值的敏感性较低。例如,如果一个模型的 MAE 为 5,这意味着模型的预测值与实际值的偏差平均为 5 个单位。
|
||
|
||
### 混淆矩阵
|
||
|
||
混淆矩阵是一个表格,通过显示真实正例、真实负例、假正例和假负例预测的计数来总结分类模型的性能。它提供了模型在每个类别上的表现的详细视图。
|
||
|
||
| | 预测为正 | 预测为负 |
|
||
|---------------|-----------|-----------|
|
||
| 实际为正 | 真正例 (TP) | 假负例 (FN) |
|
||
| 实际为负 | 假正例 (FP) | 真负例 (TN) |
|
||
|
||
- **真正例 (TP)**: 模型正确预测了正类。
|
||
- **真负例 (TN)**: 模型正确预测了负类。
|
||
- **假正例 (FP)**: 模型错误预测了正类(第一类错误)。
|
||
- **假负例 (FN)**: 模型错误预测了负类(第二类错误)。
|
||
|
||
混淆矩阵可用于计算各种评估指标,如准确率、精确率、召回率和 F1 分数。
|
||
|
||
{{#include ../banners/hacktricks-training.md}}
|