# 机器学习分类算法体系详解 ## 1\. sklearn转换器和预估器 ### 3.1.1 转换器 - 特征工程的父类 1. **实例化** ```python from sklearn.preprocessing import StandardScaler scaler = StandardScaler() ``` 2. **fit_transform()** - `fit()`:计算每列的均值和标准差 - `transform()`:执行标准化 `(x - mean) / std` ```python x_train_scaled = scaler.fit_transform(x_train) x_test_scaled = scaler.transform(x_test) ``` ### 3.1.2 估计器(sklearn机器学习算法的实现) 1. **实例化** ```python from sklearn.neighbors import KNeighborsClassifier knn = KNeighborsClassifier(n_neighbors=5) ``` 2. **模型训练** ```python knn.fit(x_train, y_train) # 生成模型 ``` 3. **模型评估** - 直接比对预测值与真实值 ```python y_pred = knn.predict(x_test) accuracy = (y_pred == y_test).mean() ``` - 计算准确率 ```python score = knn.score(X_test, y_test) ``` * * * ## 2\. K-近邻算法 ### 3.2.1 核心原理 - **K值选择**: - `k=1`:易受异常点影响 - `k=样本数`:退化为多数表决 - **距离公式**: - 欧氏距离、曼哈顿距离、闵可夫斯基距离 ### 3.2.2 案例:鸢尾花分类 ```python from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsClassifier from sklearn.preprocessing import StandardScaler def knn_iris(): """ 鸢尾花数据集 :return: """ # 1. 加载数据集 iris = load_iris() # 2. 数据集划分 x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=42) # 3. 特征工程 标准化 transfer = StandardScaler() x_train = transfer.fit_transform(x_train) # fit_transform训练集 x_test = transfer.transform(x_test) # transform测试集 # 4. KNN 算法预估 estimator = KNeighborsClassifier(n_neighbors=3) estimator.fit(x_train, y_train) # 5. 模型评估 # 方法一: 直接比对真实值和预测值 y_predict = estimator.predict(x_test) print("y_predict:\n", y_predict) print("直接比对真实值和预测值:\n", y_test == y_predict) # 方法二: 计算准确率 score = estimator.score(x_test, y_test) print("准确率: \n", score) return None if __name__ == '__main__': knn_iris() ``` ### 3.2.3 总结 - **优点**:简单易实现,无需训练 - **缺点**:计算量大,需手动调参 - **适用场景**:小数据集(几千~几万样本) ### 3.2.4 案例:预测facebook签到位置 [facebook_sample.py](../../_resources/facebook_sample.py) * * * ## 3\. 模型选择与调优 ### 3.3.1 交叉验证 **K折交叉验证**:将数据分为K份,轮流作为验证集 ```python from sklearn.model_selection import cross_val_score scores = cross_val_score(knn, X, y, cv=5) ``` ### 3.3.2 网格搜索调参 ```python from sklearn.model_selection import GridSearchCV param_grid = {'n_neighbors': [1,3,5,7,9]} grid = GridSearchCV(knn, param_grid, cv=5) grid.fit(X, y) print(grid.best_params_) # 输出最优参数 ``` ```python from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsClassifier from sklearn.preprocessing import StandardScaler from sklearn.model_selection import GridSearchCV # noinspection DuplicatedCode def knn_iris_grid_search_cv(): """ 鸢尾花数据集 KNN算法 网格搜索 :return: """ # 1. 加载数据集 iris = load_iris() # 2. 数据集划分 x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=22) # 3. 特征工程 标准化 transfer = StandardScaler() x_train = transfer.fit_transform(x_train) # fit_transform训练集 x_test = transfer.transform(x_test) # transform测试集 # 4. KNN 算法预估 estimator = KNeighborsClassifier() # 加入网格搜索与交叉验证 # 参数准备 param_grid = {"n_neighbors": [1, 3, 5, 7, 9, 11]} estimator = GridSearchCV(estimator, param_grid=param_grid, cv=10) estimator.fit(x_train, y_train) # 5. 模型评估 # 方法一: 直接比对真实值和预测值 y_predict = estimator.predict(x_test) print("y_predict:\n", y_predict) print("直接比对真实值和预测值:\n", y_test == y_predict) # 方法二: 计算准确率 score = estimator.score(x_test, y_test) print("准确率: \n", score) # 6. 获取最佳参数 print("最佳参数: \n", estimator.best_params_) print("最佳结果: \n", estimator.best_score_) print("最佳估计器: \n", estimator.best_estimator_) print("交叉验证结果: \n", estimator.cv_results_) return None if __name__ == '__main__': knn_iris_grid_search_cv() ``` * * * ## 4\. 朴素贝叶斯算法详解 #### 3.4.1、核心原理与公式 朴素贝叶斯(Naive Bayes)是基于**贝叶斯定理**和**特征条件独立假设**的分类算法。其核心公式为: $$ P(Y|X) = \frac{P(X|Y) \cdot P(Y)}{P(X)} $$ - **贝叶斯定理**:计算后验概率 $P(Y|X)$(给定特征 $X$ 时类别 $Y$ 的概率)。 - **朴素假设**:特征 $X = (x_1, x_2, ..., x_n)$ 在给定类别 $Y$ 下条件独立,即: $$ P(X|Y) = \prod_{i=1}^n P(x_i|Y) $$ ``` 这一假设简化了计算,但牺牲了部分准确性。 ``` #### 3.4.2、分类决策规则 通过比较后验概率选择最大概率的类别: $$ \hat{y} = \arg\max_Y P(Y) \prod_{i=1}^n P(x_i|Y) $$ 由于分母 (P(X)) 对所有类别相同,实际计算中可忽略。 #### 3.4.3、示例与计算步骤 **案例:天气预测是否打球** 数据集: | 天气 | 温度 | 湿度 | 风速 | 是否打球 | | --- | --- | --- | --- | --- | | 晴朗 | 炎热 | 高 | 弱 | 否 | | 晴朗 | 炎热 | 高 | 强 | 否 | | 多云 | 炎热 | 高 | 弱 | 是 | | ... | ... | ... | ... | ... | **预测新样本:天气=晴朗,温度=凉爽,湿度=正常,风速=强** 1. **计算先验概率**: - $P(是) = 6/10 = 0.6$ - $P(否) = 4/10 = 0.4$ 2. **计算条件概率**(拉普拉斯平滑): - $P(晴朗|是) = (2+1)/(6+3) = 0.333$ - $P(凉爽|是) = (3+1)/(6+3) = 0.444$ 3. **后验概率比较**: - $P(是|特征) \propto 0.6 \times 0.333 \times 0.444 \times ... \approx 0.022$ - $P(否|特征) \propto 0.4 \times 0.75 \times 0.25 \times ... \approx 0.0094$ - **结论**:预测为“是”。 #### 3.4.4、优缺点分析 **优点**: 1. 计算高效,适合高维数据(如文本)。 2. 对小规模数据表现良好,对缺失值不敏感。 **缺点**: 1. 特征独立性假设通常不成立,可能影响准确性。 2. 对输入数据分布偏差敏感(需平滑处理)。 #### 3.4.5、代码实现(Python) ```python from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.naive_bayes import GaussianNB # 加载数据 iris = load_iris() X, y = iris.data, iris.target # 划分数据集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) # 训练模型 model = GaussianNB() model.fit(X_train, y_train) # 预测与评估 print("准确率:", model.score(X_test, y_test)) ``` #### 3.4.6、应用场景 1. **文本分类**:垃圾邮件过滤、情感分析。 2. **医学诊断**:基于症状预测疾病。 3. **推荐系统**:用户行为建模。 #### 3.4.7、扩展:拉普拉斯平滑 为避免零概率问题,对条件概率进行平滑: $$ P(x_i|Y) = \frac{\text{count}(x_i,Y) + α}{\text{count}(Y) + α \cdot N} $$ 其中 $α=1$为平滑参数,$N$ 为特征可能取值数。 通过上述分析可见,朴素贝叶斯虽假设简单,但在实际应用中常因高效性和鲁棒性表现出色。理解其数学基础与适用场景是合理使用的关键。 ### 3.4.8 总结 - **优点**:计算高效,适合文本分类 - **缺点**:依赖特征独立性假设 * * * ## 5\. 决策树算法详解 #### 3.5.1、核心原理与结构 决策树是一种基于树状结构的监督学习算法,通过递归划分特征空间实现分类或回归任务。其核心结构包括: - **根节点**:起始节点,包含全部数据。 - **内部节点**:特征测试节点(如“年龄≥30?”)。 - **叶节点**:最终决策结果(如“批准贷款”)。 **工作原理**: 从根节点开始,根据特征取值选择分支,递归划分数据集,直到满足停止条件(如纯度达标或达到最大深度)。 #### 3.5.2、关键算法与公式 1. **ID3算法(信息增益)** - **熵(Entropy)**:衡量数据不确定性,其中 $p_i$ 为类别 $i$ 的概率。 - **信息增益**:选择使熵减少最多的特征 示例:贷款数据集中,“信贷情况”的信息增益最高,优先作为根节点。 2. **C4.5算法(信息增益率)** 解决 $ID3$ 偏向多值特征的问题:,其中 $H_A(D)$为特征 $A$ 的熵,避免选择取值过多的特征。 3. **CART算法(基尼指数)** - **基尼指数**:衡量数据不纯度,值越小,数据越纯净。$CART$ 支持分类(基尼指数)和回归(均方误差)任务。(sklearn 默认选择) #### 3.5.3、构建步骤与示例 **案例:贷款审批预测** 数据集包含特征:年龄、收入、信用评分、是否有房。 **步骤**: 1. **计算根节点熵**: 总样本15个,批准9个,拒绝6个。 2. **选择最优特征**: - 计算各特征信息增益(如“信贷情况”增益0.179最高)。 - 若特征为连续值(如收入),需找到最佳分割点(如收入≥50k)。 3. **递归构建子树**: - 根节点为“信贷情况”,分支为“一般”“好”“非常好”。 - 子节点继续选择最优特征(如“有房”),直至叶节点纯度达标。 **生成树结构**: ``` 根节点:信贷情况 ≥ 一般? ├─ 是 → 叶节点:批准(准确率90%) └─ 否 → 内部节点:有房? ├─ 是 → 叶节点:批准 └─ 否 → 叶节点:拒绝 ``` #### 3.5.4、优缺点分析 **优点**: 1. **可解释性强**:规则直观,如“收入≥50k且信用好→批准”。 2. **处理混合数据**:支持数值和类别特征,无需标准化。 3. **特征重要性明确**:自动筛选关键特征(如“有房”比“年龄”更重要)。 **缺点**: 1. **易过拟合**:树过深时对噪声敏感,需剪枝(预剪枝/后剪枝)。 2. **不稳定**:数据微小变化可能导致结构剧变。 3. **偏向多值特征**:ID3算法易受高基数特征影响。 #### 3.5.5、剪枝策略 1. **预剪枝**: - 提前停止分裂(如最大深度=3、最小样本分裂数=5)。 - 优点:计算快,避免欠拟合风险。 - 缺点:可能过早停止,损失精度。 2. **后剪枝**: - 先生成完整树,再自底向上剪除冗余分支。 - 使用损失函数 $C_α(T) = C(T) + α|T|$,平衡误差与复杂度。 - 优点:泛化能力更强,适合小数据集。 #### 3.5.6、鸢尾花代码示例(Python) ```python from sklearn.datasets import load_iris from sklearn.tree import DecisionTreeClassifier def decision_tree_iris(): """ 鸢尾花数据集 决策树算法 :return: """ # 1) 加载数据集 iris = load_iris() # 2) 数据集划分 x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=22) # 3) 特征工程 # 4) 决策树算法预估 estimator = DecisionTreeClassifier(criterion="gini", max_depth=None, random_state=None) estimator.fit(x_train, y_train) # 5) 模型评估 # 方法一: 直接比对真实值和预测值 y_predict = estimator.predict(x_test) print("直接比对真实值和预测值:\n", y_test == y_predict) # 方法二: 计算准确率 score = estimator.score(x_test, y_test) print("准确率: \n", score) return None if __name__ == '__main__': decision_tree_iris() ``` #### 3.5.7、应用场景 1. **分类任务**: - 医疗诊断(根据症状预测疾病)。 - 金融风控(评估贷款违约风险)。 2. **回归任务**: - 房价预测(基于面积、地段等特征)。 - 销售额估算(根据广告投入、季节因素)。 通过特征选择、树结构优化和剪枝策略,决策树在可解释性与性能间取得平衡,是理解复杂数据关系的有力工具。 #### 3.5.8、泰坦尼克号--特殊示例 [titanic_sample.py](../../_resources/titanic_sample.py) * * * ## 6\. 随机森林算法详解 #### 3.6.1、核心原理与公式 随机森林(Random Forest)是一种基于**集成学习**和**决策树**的算法,通过组合多棵树的预测结果提升模型性能。其核心包含三个关键点: 1. **Bagging(自助采样)** 从原始数据集中有放回地随机抽取样本(约63.2%的数据用于训练单棵树),生成多个子数据集。 **公式**: $$ \text{Bootstrap采样} = \text{随机选择} \ N \ \text{个样本(允许重复)} $$ 2. **随机特征选择** 每个节点分裂时,仅从全部特征中随机选择 $m$ 个候选特征(通常 $m = \sqrt{\text{总特征数}}$),避免树间高度相似。 3. **集成策略** - **分类任务**:多数投票(Majority Voting) - **回归任务**:预测均值(Mean Averaging) #### 3.6.2、算法步骤与示例 **案例:鸢尾花分类** 数据集包含4个特征(花萼长/宽、花瓣长/宽)和3个类别(Setosa、Versicolour、Virginica)。 **步骤**: 1. **生成多棵决策树** - 每棵树使用不同的Bootstrap样本训练。 - 节点分裂时随机选择2个特征(总特征数=4)。 2. **预测新样本** - 输入样本 - 每棵树独立预测类别,最终通过投票确定结果。 **Python代码实现**: ```python from sklearn.datasets import load_iris from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split # noinspection DuplicatedCode def random_forest_iris(): """ 鸢尾花数据集 随机森林算法 :return: """ # 1) 加载数据集 iris = load_iris() # 2) 数据集划分 x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=22) # 3) 特征工程 # 4) 随机森林算法预估 estimator = RandomForestClassifier(n_estimators=10, random_state=22, max_features="sqrt") # n_estimators: 树的数量 # 加入网格搜索与交叉验证 param_grid = {"n_estimators": [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]} estimator = GridSearchCV(estimator, param_grid=param_grid, cv=10) estimator.fit(x_train, y_train) # 5) 模型评估 # 方法一: 直接比对真实值和预测值 y_predict = estimator.predict(x_test) print("y_predict:\n", y_predict) print("直接比对真实值和预测值:\n", y_test == y_predict) # 方法二: 计算准确率 score = estimator.score(x_test, y_test) print("准确率: \n", score) # 6. 获取最佳参数 print("最佳参数: \n", estimator.best_params_) print("最佳结果: \n", estimator.best_score_) print("最佳估计器: \n", estimator.best_estimator_) print("交叉验证结果: \n", estimator.cv_results_) if __name__ == '__main__': random_forest_iris() ``` #### 3.6.3、关键特性与优势 | **特性** | **说明** | | --- | --- | | **抗过拟合** | 通过随机采样和特征选择降低方差,避免单棵树过拟合。 | | **并行化训练** | 各树独立训练,支持多线程加速(`n_jobs`参数)。 | | **特征重要性评估** | 基于特征在分裂时的贡献度(如基尼指数下降)自动排序。 | | **处理缺失值** | 通过替代分裂机制(Surrogate Splits)自动处理缺失数据。 | #### 3.6.4、超参数调优 | **参数** | **作用** | **推荐范围** | | --- | --- | --- | | `n_estimators` | 树的数量,影响模型稳定性 | 100-500 | | `max_depth` | 单树最大深度,防止过拟合 | 5-30 | | `max_features` | 节点分裂时考虑的特征数 | `sqrt`(分类)、`log2` | | `min_samples_split` | 内部节点分裂所需最小样本数 | 2-20 | | `bootstrap` | 是否使用自助采样 | `True`(默认) | **网格搜索示例**: ```python from sklearn.model_selection import GridSearchCV param_grid = { 'n_estimators': [50, 100, 200], 'max_depth': [5, 10, None], 'max_features': ['sqrt', 'log2'] } grid_search = GridSearchCV(RandomForestClassifier(), param_grid, cv=5) grid_search.fit(X_train, y_train) print("最佳参数:", grid_search.best_params_) ``` #### 3.6.5、优缺点分析 **优点**: 1. **高准确性**:集成多棵树减少噪声影响,优于单棵决策树。 2. **鲁棒性**:对缺失值、异常值不敏感,适合复杂数据。 3. **特征洞察**:直接输出特征重要性,辅助特征工程。 **缺点**: 1. **计算成本高**:树数量多时训练耗时,内存占用大。 2. **可解释性弱**:集成结果难以追溯单棵树决策路径。 3. **偏差问题**:对简单数据可能过拟合(需调整`max_depth`)。 #### 3.6.6、应用场景 1. **分类任务**: - **金融风控**:信用评分、欺诈检测(如信用卡交易异常识别)。 - **医疗诊断**:基于症状预测疾病(如癌症类型分类)。 2. **回归任务**: - **房价预测**:结合房屋面积、地段等特征。 - **销量估算**:根据广告投入、季节因素预测销量。 3. **特征工程**: - 自动筛选关键特征(如电商用户行为分析)。 #### 3.6.7、扩展:随机森林的变种 1. **Extra Trees(极端随机树)** - 节点分裂时随机选择特征和切分点,进一步降低方差。 2. **Isolation Forest(孤立森林)** - 专用于异常检测,通过随机分割快速隔离异常点。 3. **Quantile Regression Forests** - 支持分位数预测,适用于不确定性量化。 #### 3.6.8、与梯度提升树(GBDT)对比 | **特性** | **随机森林** | **梯度提升树(如XGBoost)** | | --- | --- | --- | | **训练方式** | 并行独立训练多棵树 | 串行训练,每棵树修正前序错误 | | **偏差-方差权衡** | 主要降低方差 | 同时降低偏差和方差 | | **参数敏感性** | 相对低(默认参数效果较好) | 高(需精细调参如学习率、树深度) | | **适用场景** | 快速原型开发、高维数据 | 高精度需求、中小规模数据 | ### 总结 随机森林通过**Bagging**和**随机特征选择**实现高效集成,在多数场景下表现出色。其优势在于**抗过拟合**和**特征可解释性**,但需注意计算成本和模型复杂度。对于需要更高精度的任务,可结合梯度提升树进一步优化。 #### 3.6.9、泰坦尼克号--特殊示例 [titanic_sample_random_forest.py](../../_resources/titanic_sample_random_forest.py) ## 附:算法对比 | 算法 | 优点 | 缺点 | 适用场景 | | --- | --- | --- | --- | | KNN | 无需训练,简单直观 | 计算量大,需调参 | 小数据集 | | 朴素贝叶斯 | 高效,适合文本 | 特征独立性假设 | 文本分类 | | 决策树 | 可解释性强 | 易过拟合 | 结构化数据分类 | | 随机森林 | 高准确率,抗过拟合 | 计算成本高 | 大数据集,高维特征 |