一、机器学习概述
(一)机器学习基本概念
- 机器学习专门研究如何模拟或实现人类的学习行为,使其不断地改善自身的性能
- 机器学习模型=数据+机器学习算法
graph LR id0("新的数据")--输入-->id1("模型")--预测-->id2("未知属性") id3("历史数据")--训练-->id1
(二)机器学习的方式
1.基于规则的学习
- 基于规则的学习是通过人工对数据提取规律,将规律转换为代码
- 但部分问题无法通过基于规则的学习解决:
- 图像和语音识别
- 自然语言处理
2.基于模型的学习
- 基于模型的学习是通过编写机器学习程序,让机器自己从数据中提取规律
(三)机器学习数据集
- 样本:数据集中的一条数据
- 特征:样本中的一个属性
- 目标值:最终要预测的属性
二、机器学习的分类
(一)监督学习
- 监督学习是指人工为机器提供一大堆标记好的数据
- 机器通过学习归纳算法或模型
- 通过算法或模型预测数据
- 常见模型:Linear regression、Logistic regression、SVM、Neural netword
1.分类问题
分类问题是监督学习中一个核心问题:
- 当输出变量Y取有限个离散值时,预测问题便形成了分类问题
- 监督学习从数据中学习一个分类模型或分类决策函数,形成了分类器
- 分类器对于输入的数据,按照分类模型或分类决策函数进行分类
2.回归问题
- 回归问题是指对一系列连续性输出变量进行预测
- 数据会提供大量的自变量和连续因变量,通过寻找自变量和因变量之间的关系,从而形成预测模型
(二)无监督学习
- 无监督学习是指人工为机器提供的数据中没有分类标记,无目标值
1.聚类问题
- 聚类问题是一种探索性数据分析技术,在没有任何相关先验信息的情况下,将数据划分为有意义的小的组别(也称为簇)
- 簇内的成员具有一定的相似度,簇之间存在较大差异
2.数据降维
- 无监督降维是数据特征预处理时使用的技术,用于清除数据中的噪声
(三)半监督学习
- 半监督学习是指数据中既有携带标记,又有不携带标记的
- 在处理未标记数据时,可以采用“主动学习”方式:
- 利用已标记数据训练模型
- 利用训练出的模型套用未标记的模型
- 通过询问领域专家分类结果与模型分类结果进行对比,提高和改善模型
- 也可以采用“聚类学习”方式
- 通过聚类将未标记的数据聚集在一个簇中,从而为未标记的数据添加标记
- 本质上利用了一个假设:相似的样本拥有相似的输出
- 半监督学习可以分为两类:
- 纯半监督学习:未标记数据作为训练数据
- 直推学习:未标价数据作为预测数据
(四)强化学习
1.概念
- 强化学习是机器学习的分支,用于解决连续决策问题
- 强化学习的目标一般是变化的、不明确的,甚至可能不存在绝对正确的标签
2.目标
- 强化学习的目标是构建一个系统,在与环境的交互中提高系统的性能,环境一般包括反馈和状态
- 系统在与环境交互的过程中,通过强化学习得到一系列的行为,通过探索性的试错或者借助精心设计的激励系统使得正向反馈最大化
graph LR id0(系统) id1(环境) id1--反馈-->id0 id0--交互-->id1 id1--状态-->id0
三、拟合问题
(一)欠拟合
1.现象
- 模型在训练集上的表现效果差,没有充分利用数据
- 预测的准确率很低,拟合结果严重不符合预期
2.原因
- 产生原因:模型过于简单
- 出现场景:一般出现在机器学习模型早期训练阶段
3.解决方案
- 添加其他特征项
- 添加多项式特征:在线性模型中添加高次项
- 减少正则化参数
(二)过拟合
1.现象
- 模型在训练集上表现很好,但在测试集上效果很差
2.原因
- 产生原因:模型过于复杂、数据不纯、训练数据太少等
- 出现场景:模型优化到一定程度
3.解决方案
- 重新清洗数据:减少数据不纯
- 增大训练的数据量
- 采用正则化对参数施加权重
- 采用dropout方法进行随机采样训练模型
4.奥卡姆剃刀原则
- 奥卡姆剃刀原则或称为节俭原则:给定两个具有相同泛化误差的模型,较简单的模型比复杂的模型更可取
- 模型越复杂,出现过拟合的概率越高
(三)泛化能力
- 训练出的模型适用于新样本的能力,称之为泛化能力
- 模型的泛化能力强,意味着对于新数据有很好的适应能力
四、KNN算法
(一)KNN算法简介
1.概念
- KNN算法是监督学习分类算法,主要解决现实生活中的分类问题
- KNN算法的思想极度简单,应用数学知识少,但效果不错
2.过程
- 取一个k值:表示与邻近的k个点进行比较
- 在所有点中找到离新样本最近的k个点
- 被选中的k个点根据自身所属类别进行投票
3.原理
- 输入:训练数据集,x为实例的特征向量,y为实例所属的类别
$$
T={(x_1,y_1),(x_2,y_2)...(x_n,y_n)}
$$ - 输出:实例x所属的类别y
- 步骤:
- 选择合适的参数k
- 计算未知实例与所有已知实例的距离
- 选择最近的k个已知实例
- 根据少数服从多数的原则,让未知实例归属为k个实例中数量最多的类型
(二)距离度量算法
在机器学习算法中,经常需要判断两个样本是否相似,常用的方式是将相似的判断转换为距离的计算
1.欧式距离
欧式距离:指两点之间通过直接连线的方式,所得到的线段的长度
$$
二维:距离L=sqrt{(x_1-x_2)^2+(y_1-y2)^2}
推广:距离d=sqrt{sum{k=1}^{n}(x{1k}-x{2k})^2}
$$
2.曼哈顿距离
曼哈顿距离:指两点之间沿着坐标轴运动的距离(例如二维中,沿着x轴移动的距离+沿着y轴移动的距离)
$$
距离d=sum{k=1}^n |x{1k}-x_{2k}|
$$
3.切比雪夫距离
切比雪夫距离:类似国际象棋,一个棋子可以向八个方向移动,那么它从一个棋格到另一个棋格的最小距离
$$
距离d=max(|x_1-x_2|,|y_1-y_2|)
$$
4.闵式距离
闵式距离:是对上述距离的概括性表示
$$
距离d=sqrt[p]{sum{k=1}^n |x{1k}-x_{2k}|^p}
$$
- 当p=1时,该距离为曼哈顿距离
- 当p=2时,该距离为欧式距离
- 当p趋于无穷时,该距离为切比雪夫距离
(三)归一化和标准化
1.需求背景
- 样本中会具有多个特征,每一个特征有自己的定义域和取值范围,因此它们对于距离计算的影响也是不同的
- 因此需要对特征进行归一化处理,使得特征都缩放到相同区间或者分布内
2.归一化
- 归一化:通过对原始数据的变换,将数据映射到[0,1]区间内
$$
x^{'}=frac{x-min}{max-min}
x^{''}=x^{'}*(max-min)+min
$$ - scikit-learn中实现归一化的API:
from sklearn.preprocessing import MinMaxScaler #1.准备数据 data = [数据] #2.初始化归一化对象 transformer = MinMaxScaler() #3.进行归一化处理 data = transformer.fit_transform(data)
- 注意:归一化受到最大值和最小值的影响,容易被异常数据影响,适合传统精确小数据场景
3.标准化
- 标准化
$$
x^{'}=frac{x-mean}{sigma}
$$- $ mean $:特征的平均值
- $ sigma $:特征的标准差
- scikit-learn中实现标准化的API:
from sklearn.preprocessing import StandardScaler #1.准备数据 data = [数据] #2.初始化标准化对象 transformer = StandardScaler() #3.进行标准化处理 data = transformer.fit_transform(data)
- 注意:对于标准化来说,如果出现异常点,由于具有一定的数据量,少量异常点对于平均值的影响不大
(四)KNN算法API
1.导包
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
2.加载数据集
#1.加载内置的鸢尾花数据集
iris = load_iris()
iris.data
3.数据标准化
#2.数据标准化
transformer = StandardScaler()
x = transformer.fit_transform(iris.data)
4.模型训练
#3.模型训练
estimator = KNeighborsClassifier(n_neighbors=3) #n_neighbors:K的值
estimator.fit(x,iris.target)
5.进行预测
#4.利用模型进行预测
result = estimator.predict(x)
print(result)
(五)分类模型评估方法
1.数据划分
- 需求:如果使用所有数据来训练模型,将缺少用于测试的数据,难以评估模型的泛化能力
- 测试集:使用测试集来测试模型对于新样本的判别能力,以测试误差作为泛化误差的近似
- 测试集的要求:
- 能够代表整个数据集
- 测试集与训练集互斥
- 测试集与训练集比例建议:2比8、3比7等
2.数据划分的方法
- 留出法:简单地将数据集划分为训练集和测试集
- 交叉验证法:将数据集划分为训练集和测试集之后,再将训练集划分为训练集和验证集(验证集用于调试参数)
- 留一法:每次从训练集中抽取一条数据作为测试集
- 自助法:以可放回采样为基础随机抽取m个样本,没被抽到的其余数据作为测试集
3.留出法
- 导包
from sklearn.model_selection import train_test_split from sklearn.model_selection import StratifiedShuffleSplit from sklearn.model_selection import ShuffleSplit from collections import Counter from sklearn.datasets import load_iris
- 加载数据集
#1.加载数据集 x,y = load_iris(return_X_y=True) #若不加参数,默认通过data获得特征值x,通过target获得目标值y
- 方式一:留出法-随机分割
#2.留出法(随机分割) x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.2) #test_size表示测试集比例
- 方式二:留出法-分层分割
#2.留出法(分层分割) x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.2,stratify=y) #test_size表示测试集比例 #stratify=y表示保证测试集和训练集之间的y标签下的比例相同
- 方式三:多次划分-随机分割
#2.多次划分(随机分割) spliter = ShuffleSplit(n_splits=5,test_size=0.2,random_state=0) #n_splits:表示分成几个数据集 #random_state:随机数种子
- 方式四:多次划分-分层分割
#2.多次划分(分层分割) spliter = StratifiedShuffleSplit(n_splits=5,test_size=0.2,random_state=0)
4.交叉验证法
K-Ford交叉验证:将训练集均匀分成k份,假设每份数据的标号为0~k-1:
- 从0开始,每次抽出标号为i(i从0到k-1)的数据
- 使用剩下的数据进行训练形成k个模型
- 再使用抽出的数据进行检验
from sklearn.model_selection import KFold
from sklearn.model_selection import StratifiedKFold
from collections import Counter
from sklearn.datasets import load_iris
#1.加载数据集
x,y = load_iris(return_X_y=True)
print("原始比例:",Counter(y))
#2.随机交叉验证
spliter = KFold(n_splits=5,shuffle=True,random_state=0)
for train,test in spliter.split(x,y):
print("随机交叉验证:",Counter(y[test]))
#3.分层交叉验证
spliter = StratifiedKFold(n_splits=5,shuffle=True,random_state=0)
for train,test in spliter.split(x,y):
print("分层交叉验证",Counter(y[test]))
5.留一法
from sklearn.model_selection import LeaveOneOut
from sklearn.model_selection import LeavePOut
from sklearn.datasets import load_iris
from collections import Counter
#1.加载数据集
x,y = load_iris(return_X_y=True)
print("原始比例:",Counter(y))
#2.留一法
spliter = LeaveOneOut()
for train,test in spliter.split(x,y):
print("训练集:",len(train),"测试集:",len(test))
#3.留P法
spliter = LeavePOut(p=3) #表示每次抽取p个数据
for train,test in spliter.split(x,y):
print("训练集:",len(train),"测试集:",len(test))
6.自助法
import pandas as pd
#1.构造数据集
data = [数据]
data = pd.DataFrame(data)
#2.产生训练集
train = data.sample(frac=1,replace=True)
print("训练集:",train)
#3.产生测试集
test = data.loc[data.index.difference(train.index)]
print("测试集:",test)
(六)分类算法的评估
1.评估方法
- 利用训练好的模型使用测试集的特征值进行预测
- 将预测结果和测试集的目标值进行比较,计算预测的准确率
from sklearn import datasets from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsClassifier #1.加载数据集 x,y = datasets.load_iris(return_X_y=True) #2.划分训练集和测试集 x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.2) #3.创建KNN对象 estimator = KNeighborsClassifier(n_neighbors=6) #4.使用KNN训练模型 estimator.fit(x,y) #5.进行预测 predict = estimator.predict(x_test) #6.进行评估 print(sum(predict==y_test)/y_test.shape[0])
2.评估API
from sklearn.metrics import accuracy_score
#方式1:直接调用函数
accuracy_score(预测值,测试值)
#方式2:通过对象调用函数
estimator.score(测试集特征值,测试集目标值)
(七)K值选择
KNN算法的核心在于找到合适的K值
1.如何确定K值
- K值过小:容易受到异常点的影响
- K值过大:容易受到样本均衡的影响
- k=样本数:导致结果永远是样本中多的那一个
因此,k一般取一个较小的数值,通过交叉验证法来选择最优的k值
2.GridSearchCV
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import GridSearchCV
#1.加载数据集
x,y = load_iris(return_X_y=True)
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.2,stratify=y,random_state=0)
#2.寻找最优参数
estimator = KNeighborsClassifier()
param_grid = {"n_neighbors":[1,2,3,4,5,6,7,8,9,10]} #使用字典确定要传的参数以及可能的取值
estimator = GridSearchCV(estimator,param_grid=param_grid,cv=5,verbose=0)
#cv:表示将数据集划分为5份
#verbose:是否显示打印信息
estimator.fit(x_train,y_train)
#3.输出结果
print("最优参数:",estimator.best_params_,"最优得分:",estimator.best_score_) # 注意:最优得分是验证集的结果
print("准确率:",estimator.score(x_test,y_test)) #准确率是测试集的结果
五、线性回归算法
(一)线性回归算法简介
1.概念
线性回归:是指利用回归方程对一个或多个自变量和因变量之间的关系进行建模的一种分析方式
2.公式
$$
h(w)=w_1x_1+w_2x_2+w_3x_3+...+b=w^Tx+b
$$
3.线性回归API
- 模块:linear_model
- 对象:sklearn.linear_model.LinearRegression()
- 参数
- fit_intercept:是否计算偏置
- 属性
- LinearRegression.coef_:回归系数
- LinearRegression.intercept_:偏置
4.基本流程
from sklearn.linear_model import LinearRegression
train = 训练集
test = 测试集
#实例化线性回归对象
estimator = LinearRegression()
#训练模型
estimator.fit(train,test)
#查看回归系数
print(estimator.coef_)
#进行预测
estimator.predict(预测)
(二)损失函数
1.损失函数的概念
损失函数:用于计算预测值和真实值之间的误差,误差越小说明模型性能越好
2.平方损失
$$
J(w)=(h(x_1)-y_1)^2+(h(x_2)-y_2)^2+...+(h(x_n)-yn)^2=sum{i=1}^n (h(x_i)-y_i)^2
$$
3.正规方程
对损失函数求导等零,计算最值
$$
w=(X^TX)^{-1}X^Ty
$$
(三)梯度下降
1.简介
对于一个可微分的函数,寻找其最值:
- 找到当前位置的最大梯度
- 沿着梯度的正方向(求最大值)或者反方向(求最小值)
- 重复上述步骤,就能不断逼近局部最小值
2.公式
$$
theta{i+1}=theta{i}-alphafrac{partial}{partial theta_{i}}J(theta)
$$
- $ alpha $:表示学习率,也称为步长,控制每一步走的距离
- 注意:如果过大,则可能错过最值点;如果过小,则可能需要多次迭代
- $ - $:负号表示沿着梯度下降最快的方向移动,因为梯度本身表示的是上升最快的
3.梯度下降流程
- 前提:确定优化模型的假设函数和损失函数
- 算法相关参数初始化
- 通过公式进行迭代
(四)其他梯度下降算法
1.全梯度下降算法(FGD)
- 全梯度下降算法:在每次迭代时,使用全部样本的梯度值
- 具体实现:
- 在更新参数时,使用所有的样本来进行更新
- 计算训练集的所有样本误差,对其求和平均后作为目标函数
- 公式:
$$
theta{i+1}=theta{i}-alphasum{j=0}^{m}(h{theta}(x_0^{(j)},x_2^{(j)},...,x_n^{(j)})-y_i)x_i^{(j)}
$$ - 注意:
- 全梯度下降算法执行速度慢,无法处理超出内存容量限制的数据集
- 全梯度下降算法不支持在线更新模型,在运行过程中,不能增加新的样本
2.随机梯度下降算法(SGD)
- 随机梯度下降算法:在每次迭代时,随机选取一个样本梯度值
- 公式:
$$
theta{i+1}=theta{i}-alpha(h_{theta}(x_0^{(j)},x_2^{(j)},...,x_n^{(j)})-y_i)x_i^{(j)}
$$ - 注意:
- 随机梯度下降算法在遭遇噪声时容易陷入局部最优解
- API:
from sklearn.linear_model import SGDRegresser
- 参数
- loss:损失函数类型
- fit_intercept:是否计算偏置
- learning_rate:学习率
- 属性
- SGDRegression.coef_:回归系数
- SGDRegression.intercept_:偏置
3.小批量梯度下降算法
- 小批量梯度下降算法:在每次迭代时,随机抽取一个小的样本集(通常为2的次幂,便于GPU运算)使用全梯度下降算法
- 公式:
$$
theta{i+1}=theta{i}-alphasum{j=t}^{t+x-1}(h{theta}(x_0^{(j)},x_2^{(j)},...,x_n^{(j)})-y_i)x_i^{(j)}
$$
4.随机平均梯度下降算法
- 随机平均梯度下降算法:在内存中为所有样本维护一个旧梯度值,在每次迭代时,随机选择一个新的样本来更新此样本的梯度,其他样本的梯度保持不变,然后求平均梯度更新参数
- 公式:
$$
theta{i+1}=theta{i}-frac{alpha}{n}(h_{theta}(x_0^{(j)},x_2^{(j)},...,x_n^{(j)})-y_i)x_i^{(j)}
$$
(五)回归问题评估
1.平均绝对误差(MAE)
- 公式:
$$
MAE=frac{1}{n}sum{i=1}^{n} |y{i}-hat y_{i}|
$$ - API
from sklearn.metrics import mean_absolute_error mean_absolute_error(预测值,真实值)
2.均方误差(MSE)
- 公式:
$$
MSE=frac{1}{n}sum{i=1}^{n} (y{i}-hat y_{i})^2
$$ - API:
from sklearn.metrics import mean_squared_error mean_squared_error(预测值,真实值)
3.均方根误差(RMSE)
- 公式:
$$
MSE=sqrt{frac{1}{n}sum{i=1}^{n} (y{i}-hat y_{i})^2}
$$
4.R-Squared
- 公式:
$$
R^2=1-frac{sum(y_i-hat y_i)^2}{sum(y_i-overline y_i)^2}
$$ - API:
from sklearn.metrics import r2_score r2_score(预测值,真实值)
- 注意:
- 一般来说,我们认为0.5以下为弱拟合,0.5~0.8为中拟合,0.8以上为强拟合(理论上,小于0的情况是存在的,表示模型非常差)
- R-Squared只是表示拟合的强弱,并不能认为R-Squared越大模型越好
- R-Squared对非线性模型没有意义
5.Adjusted R-Squared
- 公式:
$$
R_{adj}^2=1-frac{(1-R^2)(n-1)}{n-k-1}
$$- n:样本数量
- k:模型中自变量的数量
- 注意:
- 如果Adjust R-Squared和R-Squared差距较大,则说明模型存在过拟合
(六)正则化
1.概念
正则化:在算法学习过程中,数据提供的某些特征中可能影响模型复杂度,或者这个特征的异常较多,我们需要减少这个特征的影响,就是正则化
2.类别
- L1正则化
- 公式:假设L(w)是未添加正则化项的损失函数,$ lambda $控制正则化项的大小
$$
最终损失函数:L=L(w)+lambda*sum_{i=1}^n |w_i|
$$ - 作用:进行特征选择,L1正则化会产生较多的参数为0,从而产生稀疏解,将参数为0的特征舍弃,即可达到特征选择的目的
- API:
form sklearn.linear_model import Lasso
- alpha
- normalize:True/False,是否标准化
- 公式:假设L(w)是未添加正则化项的损失函数,$ lambda $控制正则化项的大小
- L2正则化
- 公式:假设L(w)是未添加正则化项的损失函数,$ lambda $控制正则化项的大小
$$
最终损失函数:L=L(w)+lambda*sum_{i=1}^n w_i^2
$$ - 作用:防止模型过拟合,减小特征的权重
- API:
form sklearn.linear_model import Ridge
- 公式:假设L(w)是未添加正则化项的损失函数,$ lambda $控制正则化项的大小
六、逻辑回归算法
(一)逻辑回归应用场景
逻辑回归:是机器学习中一种分类模型,用于解决二分类问题
(二)逻辑回归的原理
1.输入
逻辑回归的输入是一个线性方程
$$
h(w)=w_1x_1+w_2x_2+w_3x_3+...+b
$$
2.激活函数
sigmoid函数:
$$
g(w^T,x)=frac{1}{1+e^{-h(w)}}=frac{1}{1+e^{-w^Tx}}
$$
回归结果输入到sigmoid函数中,输出[0,1]的一个概率值,默认阈值为0.5
(三)损失以及优化
1.损失
逻辑回归的损失,称之为对数似然损失
- 分类形式的公式为:
$$
cost(htheta(x),y)=begin{cases}-log(htheta(x)),当y=1时-log(1-h_theta(x)),当y=0时end{cases}
$$
- 综合完整损失函数:
$$
cost(htheta(x),y)=sum{i=1}^m -yi log(htheta(x))-(1-yi)log(1-htheta(x))
$$
2.优化
使用梯度下降算法减少损失函数的值,从而更新逻辑回归对应算法的权重参数
(四)逻辑回归的API
sklearn.linear_model.LogisticRegression(solver=,penalty=,C=)
solver
:默认'liblinear'
,可选'sag'
、'saga'
、'newton-cg'
、'lbfgs'
'liblinear'
:适用于小型数据集'sag'
、'saga'
:适用于大型数据集- 多分类问题:
'sag'
、'saga'
、'newton-cg'
、'lbfgs'
penalty
:正则化的种类C
:正则化力度
(五)分类回归指标
1.混淆矩阵
正例 | 假例 | |
---|---|---|
正例 | 真正例TP | 伪反例FN |
假例 | 伪正例FP | 真反例TN |
注:左侧:真实结果--上方:预测结果
2.准确率
准确率:又称查准率,指的是对正例样本的预测准确率
$$
P=frac{TP}{TP+FP}
$$
3.召回率
召回率:又称查全率,指的是预测为真正例样本占所有真正例样本的比重
$$
R=frac{TP}{TP+FN}
$$
4.ROC曲线与AUC值
- ROC曲线:我们分别考虑正负样本的情况
- 正样本中被预测为正样本的概率(TPR)
- 负样本中被预测为正样本的概率(FPR)
- AUC值:由于ROC曲线图像越靠近(0,1)点模型对于正负样本的辨别能力越强,而图像越靠近(0,1)点,ROC曲线下面积越大,故我们将ROC曲线下面积称为AUC值
- API:
- 分类评估报告:
sklearn.metrics.classification_report(y_true,y_pred,labels=[],target_names=None) """ y_true:真实的目标值 y_pred:预测的目标值 labels:指定类别对应的数字 target_names:目标类别的名称 return:每个类别的精确率与召回率 """
- AUC计算:
from sklearn.metrics import roc_auc_score sklearn.metrics.roc_auc_score(y_true,t_score) """ y_true:每个样本的真实类别,以0(反例)、1(正例)标注 y_score:预测得分 """
七、决策树
(一)决策树简介
1.决策树的定义
决策树:从根结点开始,非叶子结点中存储判断的条件,根据是否满足条件进入不同的分支,如此反复,直到叶子结点。决策树是非参数学习算法,可以解决分类问题和回归问题
2.决策树的构建
- 特征选择:挑选强分类的特征
- 决策树生成
- 决策树剪枝
3.决策树API
from sklearn.tree import DecisionTreeClassifier
:分类器from skleran.tree import plot_tree
:绘图
(二)ID3决策树
1.信息熵
- 定义:熵代表随机变量的不确定度。熵越大,不确定性越高;熵越小,不确定性越低
- 公式:
$$
H=-sum_{i=1}^k p_i log(p_i)
当只有两个类别时,等价于:H=-xlog(x)-(1-x)log(1-x)
$$- $ p_i $:表示第i个类别的在总数中的占比
2.信息增益
- 定义:特征A对于训练集D的信息增益$ g(D,A) $,定义为集合D的经验熵$ H(D) $与特征A指定条件下D的经验熵$ H(D|A) $的差
$$
g(D,A)=H(D)-H(D|A)
$$ - 算法:
- 前提假设:
$$
begin{aligned}
&(1)设训练数据集为D,|D|表示其样本的个数.
&(2)设有K个类C_k,k=1,2,...,|C_k|表示属于类Ck的样本个数,sum{k=1}^K =|D|.
&(3)设特征A有n个不同取值{a_1,a_2,...,a_n},根据特征A的取值将D划分为n个子集D_1,D_2,...,D_n,|D_i|表示Di的样本个数,sum{i_1}^n|D_i|=|D|.
&(4)子集中属于类Ck的样本集合为D{ik},则有D_{ik}=D_icap Ck,|D{ik}|为D_{ik}的样本个数.
end{aligned}
$$ - 输入输出:
- 输入:训练数据集D,特征A
- 输出:特征A对于训练数据集D的信息增益g(D,A)
- 步骤:
- 计算数据集D的经验熵H(D):
$$
H(D)=-sum_{k=1}^K frac{|C_k|}{|D|}logfrac{|C_k|}{|D|}
$$ - 计算特征A对数据集D的经验条件熵H(D|A):
$$
H(D|A)=sum_{i=1}^n frac{|D_i|}{|D|}H(Di)=-sum{i=1}^n frac{|Di|}{|D|}sum{i=1}^n frac{|D_{ik}|}{|Di|}logfrac{|D{ik}|}{|D_i|}
$$ - 计算信息增益:
$$
g(D|A)=H(D)-H(D|A)
$$
- 前提假设:
- 选择:选择信息增益最大的作为结点的判断条件,将数据集按判断条件划分,对每一个子集再次计算信息增益,如此往复
3.ID3算法步骤
- 计算每个特征的信息增益
- 使用信息增益最大的作为判断条件拆分数据集
- 使用剩余的特征对子集继续计算信息增益
(三)C4.5决策树
1.信息增益率
公式:
$$
Gain_Ratio(D,a)=frac{Gain(D,a)}{IV(a)}
IV(a)=-sum_{v=1}^V frac{D^v}{D}logfrac{D^v}{D}
$$
- $ Gain_Ratio(D,a) $:表示信息增益率
- $ Gain(D,a) $:表示信息增益
- $ IV(a) $:表示内在信息
2.使用信息增益率的原因
仅使用信息增益会优先选择具有较多属性值的特征,因为属性值多的特征会产生较大的信息增益,但这个特征不一定是最优的
(四)CART分类决策树
1.CART决策树简介
- CART决策树是一种决策树模型,可以用于分类
DecisionTreeClassifier
,也可以用于回归DecisionTreeRegressor
- CART决策树的学习算法通常包括决策树生成和决策树剪枝,用途不同的决策树会采用不同的优化算法
- CART分类树:使用基尼指数最小化策略
- CART回归树:使用平方误差最小化策略
2.基尼指数
公式:
$$
Gini(D)=1-sum{k=1}^K p^2
Gini_index(D,a)=sum{v=1}^Vfrac{D^v}{D}Gini(D^v)
$$
- $ Gini(D) $:基尼系数
- $ Gini_index(D,a) $:基尼指数
选择:选择基尼指数最小的作为分割点
3.生成CART决策树
DecisionTreeClassifier(max_depth=,criterion=)
#max_depth:表示决策树最大深度
#criterion:表示决策树类型,默认为"gini"生成CART决策树
(五)CART回归决策树
1.区别
CART分类决策树 | CART回归决策树 |
---|---|
预测输出一个离散值 | 预测输出一个连续值 |
使用基尼指数构建 | 使用平方损失构建 |
使用叶子节点出现更多次数的类别作为预测类别 | 使用叶子节点里的均值作为预测输出 |
2.平方损失
公式:
$$
begin{align}
&设存在n个特征,其中第i个特征的目标值为y_i.对特征进行排序.
&计算每相邻2个特征的均值作为划分点,一共可以形成n-1个划分点.
&对于每一个划分点,左侧的特征记为集合L,右侧的特征记为集合R.L_i表示L中第i个特征对应的目标值,Ri同理.
&对L和R中的目标值求均值,得到overline L和overline R.
&该划分点的平方损失:Loss=sum{i=1}^L (Li-overline L)^2+sum{j=1}^{R}(R_j-overline R)^2
end{align}
$$
选择:平方损失最小的作为最终的划分点
(六)剪枝
1.预剪枝
- 预剪枝:是在决策树生成完成之前进行的剪枝操作,限制决策树的生成规模
- 方式:判断一个节点在分裂之后能否提升模型的准确率,若不能则剪掉
- 优点:使决策树很多分支不展开,降低了过拟合风险和训练开销
- 缺点:
- 有些分支虽然不能提升模型准确率,但可能其后续分支能提升准确率
- 带来了欠拟合风险
2.后剪枝
- 后剪枝:是在决策树生成完成之后进行的剪枝操作,削减决策树的规模
- 方式:判断一个节点在被剪除之后能否提升模型的准确率,若能则剪掉
- 优点:保留了更多分支,一般情况下后剪枝导致欠拟合的风险较小一些
- 缺点:训练开销大
八、朴素贝叶斯
(一)常用概率
条件概率:表示事件A在事件B已经发生的条件下发生的概率,$ P(A|B) $
联合概率:表示多个条件同时成立的概率,$ P(AB)=P(A)P(B|A) $
(二)贝叶斯公式
$$
P(A|B)=frac{P(B|A)P(A)}{P(B)}
等价于:P(A|B)P(B)=P(B|A)P(A)
$$
(三)拉普拉斯平滑系数
由于训练样本可能不足,导致概率计算中出现0的情况,为了解决这一问题,我们引入拉普拉斯平滑系数:
$$
P(A|B)=frac{N{AB}+alpha}{N{B}+alpha m}
$$
- $ N_{AB} $:表示A中符合条件B的样本的个数
- $ N_B $:表示条件B下所有样本的个数
- $ m $:表示所有独立样本的总数
- $ alpha $:表示拉普拉斯平滑系数,一般指定为1
九、支持向量机
(一)支持向量
1.概念
- 支持向量机的基本模型是定义在特征空间上的间隔最大的线性分类器,是一种二分类的模型,当使用了核技巧之后,支持向量机可以用于非线性分类
- SVM:指的是N维空间的分类超平面,其将空间分为两部分
- 支持向量:指的是落在边际两边的超平面上的点,用于支持构建最大边缘超平面
from sklearn.svm import SVC
2.分类
- 线性可分支持向量机(硬间隔支持向量机)
- 当训练数据线性可分时,通过硬间隔最大化,学习得到一个线性可分支持向量机
- 线性支持向量机(软间隔支持向量机)
- 当训练数据近似线性可分时,通过软间隔最大化,学习得到一个线性支持向量机
- 非线性支持向量机
- 当训练数据不可分时,通过使用核技巧以及软间隔最大化,学习得到一个非线性支持向量机
(二)软间隔和硬间隔
- 硬间隔:指的是让所有样本都不在最大间隔之间,并处于正确的一侧。但如果出现异常值或样本不能线性可分,则硬间隔无法实现
- 软间隔:指的是可以容忍一部分样本在最大间隔之内,甚至在错误的一侧
(三)惩罚参数C
在软间隔情况下,我们需要考虑最大化间隔和那些限制间隔违例的样本所带来的损失
- C越大:表示违反限制间隔的样本点带来的损失越大,要减少此类样本的数量,也就是减小间隔
- C越小:表示违反限制间隔的样本点带来的损失越小,可以适当增大间隔来提高模型的泛化能力
(四)SVM核方法和损失函数
1.核方法
当存在线性不可分的情况时,我们需要使用核函数提高训练样本的维度或将训练样本投向高维
$$
begin{align}
&线性核:k(x_i,x_j)=x_i^Tx_j
&多项式核:k(x_i,x_j)=(x_i^Tx_j)^d,[d>=1为多项式的次数]
&高斯核:k(x_i,x_j)=exp(-frac{||x_i-x_j||^2}{2sigma^2}),[sigma>0为高斯核的带宽]
&拉普拉斯核:k(x_i,x_j)=exp(-frac{||x_i-x_j||}{sigma}),[sigma>0]
&Sigmoid核:k(x_i,x_j)=tanh(beta x_i^Tx_j+theta),[tanh为双曲正切函数,beta>0,theta<0]
end{align}
$$
- 线性核:一般不增加数据的维度,而是预先计算内积
- 多项式核:一般是通过增加多项式特征,提升数据维度并计算内积
- 高斯核:一般是将样本投射到无限维空间,使得原本不可分的数据变得可分
2.损失函数
- 0-1损失:
- 当正例样本落在y=0下方时损失为0,否则为1
- 当负例样本落在y=0上方时损失为0,否则为1
- Hinge损失:
- 当正例样本落在y>=1一侧时损失为0,否则距离越远损失越大
- 当负例样本落在y<=-1一侧时损失为0,否则距离越远损失越大
- Logistic损失:
- 当正例样本落在y>0一侧时,距离y=0越远则损失越小
- 当负例样本落在y<0一侧时,距离y=0越远则损失越小
十、聚类算法
(一)概念
聚类算法:是一种典型的无监督学习算法,主要用于将相似的样本划分到同一类别中
(二)聚类算法的API
1.导包
sklearn.cluster.KMeans
2.参数
n_clusters=
:指定聚类的数量
init=
:可以填入'k-means++',表示选择下一个中心点时,离现有的中心点远的点的选择概率较高
(三)k-means聚类步骤
- 随机设置k个特征空间内的点作为初始的聚类中心
- 对于其他的点计算到k个中心的距离,未知的点选择最近的中心点作为标记类别
- 对于每一个聚类,计算平均值作为新的中心点
- 如果新中心点与原中心点一致,则结束;否则重复第二步
(四)模型评估
1.误差平方和(SSE)
$$
SSE=sum{i=1}^k sum{pin C_i} |p-m_i|^2
$$
- 简单来说,就是对于每一个聚类,将所有样本与中心点求距离,分别平方后求和
- 最后将所有聚类的结果加到一起
2.“肘”方法
- 对于n个点的数据集,迭代计算k,k从1到n.每次聚类完成后计算每一个点到其所属中心的距离平方和
- 当k逐渐增大时,距离平方和会逐渐缩小,直到k=n时,距离平方和为0
- 在平方和变化过程中,会出现一个“拐点”,此点前后平方和的下降速度变化较大,也就是突然下降速度变缓慢,我们认为该点是最佳k值
3.轮廓系数法
$$
S=frac{(b-a)}{max(a,b)}
$$
- $ a $:表示样本i到同一簇内其他点不相似程度的平均值,说白了就是与自己同一簇的其他点求距离的平均值
- $ b $:表示样本i到其他簇内平均不相似程度的最小值,说白了就是与其他簇的点按照簇求距离的平均值,然后取最小值
- $ S $:取值为[-1,1],越接近1,表示聚合程度越好;越接近0,表示越靠近分簇的边界;为负值时,表示该点可能被误分了
(五)特征降维
1.概念
- 用于训练的数据集的质量对模型的性能及其重要。如果训练集中包括一些不重要的特征,可能导致模型的泛化性能不佳
- 降维是指在某些限定条件下,降低特征的个数
2.低方差过滤
- 若一个特征的方差很小,说明这个特征包含的信息较少,我们设定一个阈值,过滤掉方差低于阈值的特征
过滤对象 = sklearn.feature_selection.VarianceThreshold(threshold=0.0) 数据 = 过滤对象.fit_transform(数据) #threshold:阈值,默认为0
3.相关系数法
- 皮尔逊相关系数:
$$
r=frac{nsum xy-sum x sum y}{sqrt{nsum x^2-(sum x)^2}sqrt{nsum y^2-(sum y)^2}}
$$ - 斯皮尔曼相关系数:
$$
RankIC=1-frac{6sum d_i^2}{n(n^2-1)}
$$ - $ n $:表示维度数
- $ d_i $:表示样本中不同特征在数据中排序的序号差值
#皮尔逊相关系数 from scipy.stats import pearsonr pearsonr(data[],data[]) #斯皮尔曼相关系数 from scipy.stats import spearmanr spearmanr(data[],data[]) #相关系数 data.corr(method="spearmanr") #每一个特征两两计算相关系数,默认使用spearmanr
4.主成分分析(PCA)
PCA通过对数据维数进行压缩,尽可能降低原数据的维数,损失少量信息,在此过程中可能会舍弃原有数据、创造新的变量
from sklearn.decomposition import PCA
对象 = PCA(n_components=)
数据 = 对象.fit_transform(数据)
#n_components:
#1.表示保留百分之多少的原始信息,如0.95表示保留95%
#2.若传入的数据大于1,表示保留多少列的信息,如3表示保留3列
十一、集成学习
(一)集成学习
1.概念
集成学习算法是将多个分类器组合,从而实现一个预测效果更好的集成分类器
2.分类
- 并行算法:利用相同的数据集同时搭建多个模型,然后通过投票的方式,少数服从多数得到最终的预测结果
- 串行算法:按一定次序搭建多个模型,后加入的模型需要对现有的模型有一定的贡献,从而不断提升性能
3.性能评估
要获得好的集成效果,那么我们需要个体的学习器拥有一定的准确性,并且各自之前要存在一定的差异
- 准确性:当学习器准确性过低时,出现错误预测的概率比较大,集成后因为少数服从多数,较多的错误会覆盖较少的正确,最终导致整体的错误,也就是说,会导致整体的准确性降低
- 差异性:当学习器之间差异性过低时,学习器对于数据的预测结果相似,错误的一起出错,正确的一起正确,无法达到用正确纠正错误的效果,也就是说,不会导致整体的缺勤率提高
(二)Bagging
1.Bagging框架
Bagging是通过有放回的抽样产生不同的训练集,从而得到有差异的学习器,然后通过少数服从多数的方式得到预测结果
2.booststrap抽样
在样本集中有放回地进行抽样,每次抽取的概率相等,抽中的数据作为训练集,未抽中的数据作为测试集,其中训练集大约占63.2%,测试集大约占36.8%
3.性能
- Bagging不仅能适用于二分类,而且能不经修改地用于多分类、回归任务
- Bagging主要关注降低方差,因此其在不剪枝决策树、神经网络等易受样本扰动影响的学习器上效果明显
4.算法
- 从样本集进行booststrap抽样,得到若干训练集和测试集
- 对每个训练集和测试集分别训练模型
- 最终每个模型按一定方式进行组合得到最终的预测结果
- 分类任务:简单投票,每个学习器一票,少数服从多数
- 回归任务:简单平均,每个学习器的值加和求平均
5.随机森林
- 随机森林是基于Bagging框架实现的一种集成学习算法,它采用决策树模型作为基学习器
- API:
sklearn.ensemble.RandomForestClassifier()
n_estimators
:决策树的数量Criterion
:决策树划分依据(entropy或者gini[默认])max_depth
:树的最大深度max_features="auto"
:决策树构建时使用的最大特征数量"auto"
或"sqrt"
:auto默认采用的就是sqrt,结果为sqrt(n_features)
"log2"
:结果为log2(n_features)
"None"
:结果为n_features
booststrap
:是否采用有放回抽样,默认为Truemin_samples_split
:结点分裂所需的最小样本数,默认为2min_samples_leaf
:叶子节点的最小样本数,默认为1min_impurity_split
:节点划分的最小不纯度(基尼系数、均方差等)
(三)Boosting
1.Boosting框架
每一个学习器重点关注前一个学习器不足的地方进行训练,通过加权投票得到最终结果
2.算法
- 先从初始训练集训练一个基学习器
- 根据基学习器的表现对训练样本分布进行调整,使得先前基学习器做错的训练样本在后续得到最大的关注
- 基于调整过后的样本分布训练下一个基学习器
- 如此反复,最终将所有基学习器进行加权组合
(四)AdaBoost
1.简介
- AdaBoost是Boosting算法的一种实现,用于分类问题
- AdaBoost通过弱分类器的线性组合构造强分类器
- 训练时,赋予样本权重,并在训练过程中动态调整,分错的样本会增加权重
2.步骤
- 假设存在N个样本,每个样本赋予权重为1/N
- 在训练中,若样本分类错误,则提升其权重;分类正确,则降低其权重
- 权重更新过后的样本作为下一个训练器的训练集
- 最终加权组合弱分类器,分类误差小的权重大,分类误差大的权重小
3.公式
- 最终预测公式:
$$
H(x)=sign(sum_{i=1}^m alpha_ih_i(x))
$$- $ alpha $:为模型的权重
- $ m $:为弱学习器的数量
- $ h_i(x) $:为弱学习器
- $ H(x) $:为分类结果,大于0为正类,小于0为负类
- 模型权重更新公式:
$$
alpha_t=frac12ln(frac{1-epsilon_t}{epsilon_t})
$$- $ epsilon_t $:表示第t个弱学习器的错误率
- 样本权重更新公式:
$$
D_{t+1}=frac{D_t(x)}{Z_t}*begin{cases}e^{-alpha_t},预测值=真实值e^alpha_t,预测值ne真实值end{cases}
$$- $ Z_t $:归一化值,即所有样本权重的总和
- $ D_t(x) $:为样本权重
- $ alpha_t $:模型权重
(五)GBDT
1.提升树
- 步骤
- 初始化$ f_0(x)=0 $
- 对于$ m=1,2,...,M $
- 计算残差:$ r_{mi}=yi-f{m-1}(x),i=1,2,...,N $
- 拟合残差$ r_{mi} $得到回归树$ h_m(x) $
- 更新$ fm(x)=f{m-1}(x)+h_m(x) $
- 得到回归问题提升树:$ fM(x)=sum{m=1}^M h_m(x) $
2.梯度提升树
- 梯度提升树利用损失函数的负梯度作为提升树算法中残差的近似值,实际上一般负梯度等于残差
3.GBDT算法
- 初始化弱学习器:对损失函数求最小值
$$
f_0(x)=argspace mincsum{i=1}^N L(y_i,c)
$$ - 对于$ m=1,2,...,M $:
- 对每一个样本i,$ i=1,2,...,N $求负梯度:
$$
r_{im}=-[frac{partial L(y_i,f(x_i))}{partial f(xi)}]f(x)=f{m-1}(x)
$$ - 根据划分点,将样本分为两部分,每一部分使用其负梯度的平均值作为预测值
- 将每一个样本的负梯度作为该样本的目标值,该样本所属部分的负梯度平均值作为预测值
- 继续计算这一轮样本的负梯度,如此往复
- 对每一个样本i,$ i=1,2,...,N $求负梯度:
- 最终使用强学习器的预测结果与所有弱学习器的预测结果相加得到最终的预测结果
(六)集成算法多样性
1.数据样本扰动
对于给定的数据集通过采样法从中得到具有差异的数据子集
2.输入属性扰动
训练样本通常由一组属性进行描述,可以基于这些属性的不同组合产生不同的数据子集
3.算法参数扰动
通过随机设置不同的参数,对模型参数加入小范围的随机扰动,从而产生差别较大的学习器
(七)XGBoost
1.XGBoost原理
XGBoost是对梯度提升算法的改进:
- 求解损失函数时使用泰勒二阶展开
- 在损失函数中加入了正则化项
- 从损失函数中推导出一个树节点分裂指标
对于构建最优模型,一般采用的方法是最小化训练数据的损失函数:
- 经验风险最小化:
$$
minfrac1Nsum_{i=1}^NL(y_i,f(x_i))
$$ - 结构风险最小化:
$$
minfrac1Nsum_{i=1}^NL(y_i,f(x_i))+Omega(f)
$$
2.XGBoost公式
$$
obj(theta)=sum_i^n L(y_i,hat yi)+sum{k=1}^KOmega(f_k)
$$
- 第一项:表示强学习器的损失
- 第二项:表示K个弱学习器的复杂度
3.弱学习器复杂度
$$
Omega(f)=gamma T+frac12lambda||omega||^2
$$
- 第一项:$T$表示一棵树的叶子结点的数量,$gamma$表示该项的调节系数
- 第二项:$omega$表示叶子结点输出值组成的向量,$lambda$表示该项的调节系数
4.打分函数
$$
obj=-frac12sum_{i=1}^T(frac{G_i^2}{H_i+lambda})+gamma T
$$
- 使用方法:
- 我们对于一个节点,分裂前求打分函数,分裂后求两个节点的打分函数之和
- 计算分裂前减去分裂后的分数
- 若大于0,说明分裂后树的结构损失更小,考虑分裂
- 若小于0,说明分裂后树的结构损失更大,避免分裂
5.常用API
- 通用参数
booster
:默认使用gbtree
gbtree
:使用树模型gblinear
:使用线性模型silent
:默认使用0
0
:打印运行信息1
:不打印运行信息
- TreeBooster
eta
:学习率,默认为0.3
gamma
:节点分裂所需的最小损失函数下降值,默认为0
max_depth
:树的最大深度,默认为6
min_child_weight
:默认为1
- 当值过大时,可以避免模型学习到局部的特殊样本,但值过高易导致欠拟合,
subsample
:控制随机采样的比例,取值范围(0,1],默认为1
- 值过大:易导致过拟合
- 值过小:易导致欠拟合
- 常用值:0.5-1,0.5表示平均采样
colsample_bytree
:控制每棵树特征采样的比例,默认为1
,常用0.5-1colsample_bylevel
:控制树每一次分裂对特征采样的比例,默认为1
alpha
:权重的L1正则化项,默认为0
scale_pos_weight
:默认为1
- 当样本十分不平衡时,可以将词此参数设定为一个正值,使算法更快收敛
- 通常设置为负样本的数目与正样本的数目的比值
- LinearBooster
lambda
:默认为0
- L2正则化惩罚系数,增加该值会导致模型更加保守
alpha
:默认为0
- L1正则化惩罚系数,增加该值会导致模型更加保守
lambda_bias
:默认为0
- 偏置上的L2正则化
- 学习目标参数
objective
:默认为reg:linear
reg:linear
:线性回归reg:logistic
:逻辑回归binary:logistic
:二分类逻辑回归eval_metric
:指定验证集的指标,默认是通过目标函数选择rmse
:均方根误差mae
:平均绝对值误差logloss
:负对数似然函数值error
:错误分类数目与全部分类数目比值auc
:曲线下面积seed
:随机数种子,默认为0
附录:
1.保存和加载模型
#保存
joblib.dump(模型,保存的文件名)
#加载
joblib.load(文件名)