今天要介绍的算法是机器学习中的逻辑回归和决策树算法。
逻辑回归啊
原理
:将线性回归的输出,作为激活函数Sigmoid的输入,通过激活函数将输出值映射到(0, 1)区间内,然后设置阈值完成分类。
Sigmoid函数的数学表达式为:f(x)=11+e−x f(x) = \frac{1}{1 + e^{-x}} f(x)=1+e−x1
基本思想:
- 利用线性模型f(x) = W^T + b根据特征的重要性计算出一个值。
- 在使用Sigmoid函数将值映射为概率值
- 设置阈值为0.6,输出概率值大于0.6,则将未知样本输出为1类。
- 否则输出为0类
- 逻辑回归的假设函数:W(x) = Sigmoid(W^T + b)
逻辑回归的损失函数:Loss(L)=−∑i=1n(yilog(pi)+(1−yi)log(1−pi)) \text{Loss}(L) = -\sum_{i=1}^{n} \left( y_i \log(p_i) + (1 - y_i) \log(1 - p_i) \right) Loss(L)=−i=1∑n(yilog(pi)+(1−yi)log(1−pi))
在损失函数中,Yi表示的是真实标签值,Pi是模型对第i个样本对应类别(通常是正类)的预测概率。通过公式我们不难得出如下结论:
- 当Yi = 1时,预测概率越接近1,损失越小。预测概率越接近0,损失越大。
- 当Yi = 0时,与Yi = 1恰好相反,预测概率越接近0,损失越小。预测概率越接近1,损失越大。
逻辑回归的API:sklearn.linear_model.LogisticRegression
分类算法评估
逻辑回归主要用于二分类模型中,而对于分类算法,都可以统一使用混淆矩阵、精确率、召回率、F1-分数来对模型进行评估。而除混淆矩阵外,其余所有评估标准均可以使用混淆矩阵得出,因此混淆矩阵的重要性不言而喻。
混淆矩阵(Confusion Matrix)是分类模型评估的一种工具,用来衡量模型预测结果与真实值之间的对比关系。通常是一个二维矩阵,其行表示真实类别,列表示模型预测类别。根据实际情况,它会包含以下四个重要的指标:
- 真正例 (True Positives, TP): 被模型正确预测为正类的样本数。即,实际是正类且模型预测为正类的样本。
- 假正例 (False Positives, FP): 被模型错误预测为正类的样本数。即,实际是负类但模型预测为正类的样本。
- 真负例 (True Negatives, TN): 被模型正确预测为负类的样本数。即,实际是负类且模型预测为负类的样本。
- 假负例 (False Negatives, FN): 被模型错误预测为负类的样本数。即,实际是正类但模型预测为负类的样本。
混淆矩阵的结构如下:
预测为正类 | 预测为负类 | |
---|---|---|
实际为正类 | 真正例TP | 伪反例FN |
实际为父类 | 伪正例FP | 真反例TN |
前面提到,除混淆矩阵外,其余所有模型评估指标均是基于混淆矩阵常用指标:
- 准确率:模型预测正确的比例。计算公式为:Accuracy=TP+TNTP+FP+TN+FN Accuracy = \frac{TP + TN}{TP + FP + TN + FN} Accuracy=TP+FP+TN+FNTP+TN
- 精确率:被预测为正类样本中,实际为正类的比例。精确率越高,则意味着误报(将负类预测为正类的错误)较少。计算公式为:Precision=TPTP+FP Precision = \frac{TP}{TP + FP} Precision=TP+FPTP
- 召回率:实际为正类样本中,被预测为正类的比例。找回率越高,则意味着模型漏掉的正类样本较少。计算公式为:Recall=TPTP+FN Recall = \frac{TP}{TP + FN} Recall=TP+FNTP
- F1-Score:精确率和召回率的调和平均数。计算公式为:F1=2×Precision×RecallPrecision+Recall F1 = 2 \times \frac{Precision \times Recall}{Precision + Recall} F1=2×Precision+RecallPrecision×Recall
API接口:from sklearn.metrics import confusion_matrix(混淆矩阵), accuracy_score(准确率), precision_score(精确率), recall_score(召回率), f1_score(F1-分数)
示例代码
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
import pandas as pd
import joblib
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix, accuracy_score, precision_score, recall_score, f1_score
def Cancer_Classification_Prediction():
# 1、读取数据
df = pd.read_csv('../../../../data/breast-cancer-wisconsin - 副本.csv')
# 2、数据预处理
# 2.1、处理异常数据
data = df.replace('?', np.nan)
data = data.dropna()
# 2.2、将数据进行分组
feature = data.iloc[:, 0:10]
label = data.iloc[:, 10]
x_train, x_test, y_train, y_test = train_test_split(feature, label, test_size=0.2, random_state=22)
# 3、特征工程 - 数据标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
# 4、模型的训练
estimator = LogisticRegression()
estimator.fit(x_train, y_train)
# 5、模型的评估
y_predict = estimator.predict(x_test)
# 5.1 准确率
score = accuracy_score(y_test, y_predict)
print(f"score -> {score}")
# 5.2 混淆矩阵
Confusion_Matrix = confusion_matrix(y_test, y_predict, labels=[4, 2])
Confusion_Matrix = pd.DataFrame(Confusion_Matrix, index=['恶性(正例)', '良性(假例)'], columns=['恶性(正例)', '良性(假例)'])
print(f"confusion_matrix -> \n{Confusion_Matrix}")
# 5.3 精确率、召回率和F1-Score
print(f"precision_score -> {precision_score(y_test, y_predict, pos_label=4)}")
print(f"recall_score -> {recall_score(y_test, y_predict, pos_label=4)}")
print(f"F1-Score -> {f1_score(y_test, y_predict, pos_label=4)}")
if __name__ == '__main__':
Cancer_Classification_Prediction()
决策树
决策树(Decision Tree)是一种常用于分类和回归任务的机器学习模型,它通过树形结构来表示决策过程。每一个内部节点代表一个特征,每一个叶子节点代表一个标签。
ID3树
常用指标:
- 熵(信息熵):衡量一个数据集的不确定性和混乱程度的度量。在信息论中,熵用于表示一个随机变量的平均信息量。熵越大,表示数据集不确定或越混乱;熵越小,表示数据集越纯净或确定。计算公式为:Ent(D)=−∑i=1kpilog2pi Ent(D) = -\sum_{i=1}^k p_i \log_2 p_i Ent(D)=−i=1∑kpilog2pi
- 条件熵:是在给定一个特征A后,样本集中,剩余总样本的信息熵。计算公式为:Ent(D∣A)=∑v=1V∣Dv∣∣D∣Ent(Dv) Ent(D|A) = \sum_{v=1}^V \frac{|D_v|}{|D|} Ent(D_v) Ent(D∣A)=v=1∑V∣D∣∣Dv∣Ent(Dv)
- 信息增益:衡量一个特征对分类结果所带来
信息量提升
的指标。它表示在对数据集按照某个特征进行划分后,样本集合的不确定性(熵)减少了多少。信息增益 = 信息熵 - 条件熵
。
ID3树就是根据样本的信息增益指标来进行分类的,信息增益越大的特征,优先作为分类特征作为决策树的内部节点。其具体的构建思路如下:
- 计算数据集的信息熵:先计算整体样本的不确定性。
- 对每个特征列计算其信息增益:计算该特征划分后,样本集熵的减少量。
- 选择信息增益最大的特征:把这个特征作为当前节点的划分属性。
- 划分数据集:按照特征的不同取值,把数据集划分若干个子集。
- 递归生成子树:对每个子集重复上述步骤,继续选择信息增益最大的特征进行划分。
- 停止条件:如果某个子集内的样本已经全部属于同一类,则生成叶子节点。或者没有特征可以继续划分时,用多数类作为叶子节点的类别。
C4.5树
根据ID3树的信息增益计算公式不难看出,ID3树总是倾向于选择特征列数量较多的列作为当前节点的划分属性。这样会增加模型的复杂度,从而容易造成过拟合的情况。因此为了应对ID3树选择特征列数量过多的情况,诞生了C4.5树。其选择特征作为当前节点的规则是选择信息增益率大的特征作为当前节点。计算公式如下:信息增益率 = 信息增益/特征熵
特征熵是衡量整个数据集是整体不确定性,用于描述数据集中类别的分布的混乱程度,不依赖于任何特征的划分。其计算公式为:H(D)=−∑i=1mpilog2pi H(D) = - \sum_{i=1}^{m} p_i \log_2 p_i H(D)=−i=1∑mpilog2pi
CART树
定义
:CART是由Beriman等人在1984年提出的一种决策树算法,能够同时用于分类问题和回归问题。
- 分类树:目标变量是离散型,通过决策树进行分类。
- 回归树:目标变量是连续型,通过树结构预测数值。
CART树的核心思想是通过二叉树不断划分数据集,使每个子节点的纯度尽可能高(分类问题)或方差尽可能小(回归问题)
基本特点
:
- 二叉树结构:每个节点最多只有两个子节点。
- 递归分裂:通过贪心算法选择最哟特征和切分点来划分数据。
- 可用于分类和回归:分别采用不同的分裂标准。
- 剪枝机制:通过兼职减少过拟合,提升泛化能力。
分类和回归树流程:
- 选择最佳分裂特征和分裂点
- 在回归树中,使用的是最小平方误差(MSE):MSE=1N∑i=1N(yi−yˉ)2 MSE = \frac{1}{N} \sum_{i=1}^{N} (y_i - \bar{y})^2 MSE=N1i=1∑N(yi−yˉ)2划分后选择是的子节点总和MSE最小的特征和分裂点。
- 在分类树中,使用的是基尼指数作为节点纯度指标,计算公式为:Gini(D)=1−∑k=1Kpk2 Gini(D) = 1 - \sum_{k=1}^{K} p_k^2 Gini(D)=1−k=1∑Kpk2其中pk为节点中属于类别k的概率。
- 递归划分数据:对每个子节点重复步骤1,直到满足停止条件(节点样本数小于阈值或者纯度达到最大)。
- 剪枝:为避免过拟合,可以使用剪枝操作。
在决策树中,为了防止过拟合,通常会对树进行剪枝。剪枝的目的是减少树的复杂度,提升泛化能力。剪枝方法主要分为两类:预剪枝和后剪枝。
特性 | 预剪枝(Pre-Pruning) | 后剪枝(Post-Pruning) |
---|---|---|
剪枝时间 | 在树生成过程中 | 在生成完整树之后 |
计算量 | 较小 | 较大 |
过拟合风险 | 中等,可能出现欠拟合 | 较低,更好控制过拟合 |
实现难度 | 简单 | 较复杂 |
泛化能力 | 较弱 | 较强 |
优点 | 节省时间,防止树过深 | 保留重要分支,泛化能力强 |
缺点 | 可能错过全局最优,欠拟合风险 | 计算量大,训练时间长 |
三种决策树的对比(分类问题)
特性 | ID3树 | C4.5树 | CART树 |
---|---|---|---|
特征类型 | 离散特征 | 离散和连续特征 | 离散和连续特征 |
划分标准 | 信息增益,信息增益大的优先分类 | 信息增益率,信息增益率大的优先分类 | 基尼指数,基尼指数小的优先分类 |
树的结构 | 多叉树 | 多叉树 | 二叉树 |
处理缺失值能力 | 弱 | 强 | 强 |
剪枝方式 | 不支持 | 后剪枝 | 支持预剪枝和后剪枝 |
优点 | 简单易懂 | 改进了ID3的偏向性,适用性强 | 可用于回归和分类,泛化能力强 |
缺点 | 只能处理离散特征,容易过拟合 | 计算复杂,训练速度较慢 | 生成完全二叉树计算量大,训练时间长 |
决策树的API接口:klearn.tree.DecisionTreeClassifier
实现代码实例
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
import pandas as pd
from sklearn.metrics import classification_report
from sklearn.tree import DecisionTreeClassifier, plot_tree
def Titanic_DecisionTreeClassifier():
# 1、读取数据
data = pd.read_csv('../../../../data/train.csv')
# 2、数据预处理
feature = data[['Age', 'Sex', 'Pclass', 'Parch']]
feature = feature.copy()
feature_name = ['Age', 'Sex', 'Pclass', 'Parch']
label = data['Survived']
# 2.1、用平均年龄填充缺失值
feature['Age'] = feature['Age'].fillna(feature['Age'].mean())
# 2.2、对Sex进行热编码处理
feature = pd.get_dummies(feature)
feature.drop(columns='Sex_male', axis=1, inplace=True)
# 2.3、划分数据集和验证集
x_train, x_test, y_train, y_test = train_test_split(feature, label, test_size=0.2, random_state=22)
# 3、特征工程--数据标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
# 4、训练模型
# todo DecisionTreeClassifier类中criterion参数的默认值是'gini'代表树的类型为CART树
# todo 在机器学习中,没有专门的API实现ID3和C4.5树,因此只能使用CART树的接口,修改criterion参数为'entropy',且树的类型只有二叉树没有多叉树
estimator = DecisionTreeClassifier()
estimator.fit(x_train, y_train)
y_predict = estimator.predict(x_test)
# 5、模型评估
# 获取模型评估的各项指标
print(f"score -> {estimator.score(x_test, y_test)}")
print(classification_report(y_test, y_predict))
# 6、决策树可视化
plt.figure(figsize=(50, 30))
plot_tree(
estimator,
feature_names=feature_name,
max_depth=10,
filled=True,
class_names=['died', 'Survived']
)
plt.show()
if __name__ == '__main__':
Titanic_DecisionTreeClassifier()
# Titanic_LogisticRegression()
# Titanic_KNN()