一、机器学习概述
1、人工智能
像人一样智能的综合与分析,机器模拟人类。
是一个系统,像人那样思考,像人那样理性思考。
是一个系统,像人那样活动,像人那样合理的系统
2、机器学习
让机器自动学习,而不是基于规则编程。(不依赖特定规则编程)
让机器在没有明确编程的情况下学习的研究领域
通过历史数据训练的一个模型,在新的数据输入后,该模型可以预测新数据的未知属性。
3、深度学习
深度神经网络,大脑方式,设计一层一层的神经元去模拟万事万物。
4、总结
机器学习是实现人工智能的一种途径
深度学习是机器学习的一种方法
二、机器学习三要素
1、数据
(一)、作用
决定了模型效果的上限。
(二)、常见术语
- 样本:一条数据就是一个样本,多个样本组成数据集
- 特征:一列数据一个特征,有时也被称为属性,特征是从数据中抽取出来的,对结果预测有用的信息
- 标签:需要预测的信息
- 数据集划分:可划分两部分:训练集、测试集 比例:8 : 2,7 : 3
- 用来训练模型的数据集
- 用来测试模型的数据集
2、算法
(一)、有监督学习–更加常见的一种算法学习
(1)定义
输入数据是由输入特征值和目标值所构成,即输入的训练数据有标签的。
输入实例X和输出正确答案Y来训练模型,在经过一定的训练后,模型可以将一个全新的输入相对应的预测出输出。
(2)数据集
需要人工标注数据
(3)两种有监督学习
- 分类:目标值是不连续的
分类种类:二分类、多分类任务
- 回归:目标值是连续的
(二)、无监督学习–不太常见
(1)定义
输输入数据没有被标记,即样本数据类别未知,没有标签,根据样本间的相似性,对样本集聚类,以发现事物内部 结构及相互关系。
(2)数据集
不需要标注数据
(3)特点
- 训练数据无标签
- 根据样本间的相似性对样本集进行聚类,发现事物内部结构及相互关系
(4)常见类型
- 聚类算法,将有相同或者类似属性的数据聚合到一起,虽然我们没有标签知道该类数据的具体类别,但是我们知道某块数据是同一类。
- 异常检测,因为有聚类的效果,所以当一些异常数据出现时,可以很明显的看出来不在群组内。
- 降维,可以将一个大的数据集压缩成尽量小的数据集,同时丢失尽量少的信息。
(三)、半监督学习
(1)工作原理
-
让专家标注少量数据,利用已经标记的数据(也就是带有类标签)训练出一个模型
-
再利用该模型去套用未标记的数据
-
通过询问领域专家分类结果与模型分类结果做对比,从而对模型做进一步改善和提高
(2)特点
可大幅降低标记成本
(四)、强化学习
(1)定义
机器学习的一个重要分支
(2)应用场景
AlphaGo围棋、各类游戏、对抗比赛、无人驾驶等场景
(3)基本原理
通过构建四个要素:agent,环境状态,行动,奖励,agent根据环境状态进行行动获得最多的累计奖励。
例如小孩子学走路:
-
小孩就是 agent,他试图通过采取行(即行走)来操纵环境(地面),
-
并且从一个状态转变到另一个状态(即他走的每一步),
-
当他完成任务的子任务(即走了几步)时,孩子得到奖励(给巧克力吃),
-
并且当他不能走路时,就不会给巧克力。
(五)、总结
In | out | 目的 | 案例 | |
---|---|---|---|---|
监督学习 | 有标签 | 有反馈 | 预测结果 | 猫狗分类 房价预测 |
无监督学习 | 无标签 | 无反馈 | 发现潜在结构 | 物以类聚 人与群分 |
半监督学习 | 部分有标签,部分无标签 | 有反馈 | 降低数据标记的难度 | |
强化学习 | 决策流程及激励系统 | 一系列行动 | 长期利益最大化 | 围棋 |
3、算力
-
CPU:IO操作
-
GPU:并行计算
三、建模流程
1、获取数据
根据任务获取数据
2、数据基本处理
缺失值处理
异常值处理
3、特征工程
利用专业背景知识和技巧处理数据,让机器学习算法效果最好。这个过程就是特征工程
释义:特征工程是困难、耗时、需要专业知识。应用机器学习基础就是特征工程
【理解】数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已
(一)、特征提取
从原始数据中提取与任务相关的特征,构成特征向量
对于文本、图片这种非行列形式的数据行列形式转换,
一旦转换成行列形式一列就是特征
(二)、特征预处理
特征对模型产生影响;因量纲问题,有些特征对模型影响大、有些影响小
将不同的单位的特征数据转换成同一个范围内
使训练数据中不同特征对模型产生较为一致的影响
(三)、特征降维
将原始数据的维度降低,叫做特征降维
会丢失部分信息。降维就需要保证数据的主要信息要保留下来
原始数据会发生变化,不需要了解数据本身是什么含义,它保留了最主要的信息
(四)、特征选择
原始数据特征很多,但是对任务相关是其中一个特征集合子集
从特征中选择出一些重要特征(选择就需要根据一些指标来选择)
特征选择不会改变原来的数据
(五)、特征组合
把多个的特征合并成一个特征
通过加法、乘法等方法将特征值合并
4、模型训练
KNN(K近邻算法)
线性回归
逻辑回归
5、模型预测
6、模型评估
(一)、分类
准确率
(二)、回归
MAE、MSE
(三)、聚类
CH、SC
(四)、模型拟合
(1)三种情况
- 正好拟合:用来表示模型对样本点的拟合情况
- 过拟合
- 模型在训练集上表现很好, 在测试集表现很差
- 模型太过于复杂, 数据不纯, 训练数据太少
- 欠拟合
- 模型在训练集上表现很差, 在测试集表现也很差
- 模型过于简单
(2)泛化
模型在新数据集(非训练数据)上的表现 好坏 的能力
(3)奥卡姆剃刀原则
给定两个具有相同泛化误差的模型, 较简单的模型比较复杂的模型更可取
四、KNN算法–近邻算法
1、KNN简介
一个样本最相似的 k 个样本中的大多数属于某一个类别,则该样本也属于这个类别
一般用来解决分类和回归问题。
样本的数量决定最终训练出来的模型好坏,当K值过小:用较小邻域中的训练实例进行预测,容易受到异常点的影响,K值的减小就意味着整体模型变得复杂,容易发生过拟合;K值过大:用较大邻域中的训练实例进行预测,受到样本均衡的问题,且K值的增大就意味着整体的模型变得简单,欠拟合。
而我们该如何区选择k值呢?
通常需要一些方法来寻找这个最合适的K值:交叉验证、网格搜索。
2、KNN的API介绍
(一)分类API
# sklearn.neighbors.KNeighborsClassifier(n_neighbors=5)
# n_neighbors:int,可选(默认= 5),k_neighbors查询默认使用的邻居数
from sklearn.neighbors import KNeighborsClassifier
def dm01_knnapi_分类():
estimator = KNeighborsClassifier(n_neighbors=1)
X = [[0], [1], [2], [3]]
y = [0, 0, 1, 1]
estimator.fit(X, y)
myret = estimator.predict([[4]])
print('myret-->', myret)
(二)回归API
# sklearn.neighbors.KNeighborsRegressor(n_neighbors=5)
from sklearn.neighbors import KNeighborsRegressor
def dm02_knnapi_回归():
estimator = KNeighborsRegressor(n_neighbors=2)
X = [[0, 0, 1],
[1, 1, 0],
[3, 10, 10],
[4, 11, 12]]
y = [0.1, 0.2, 0.3, 0.4]
estimator.fit(X, y)
myret = estimator.predict([[3, 11, 10]])
print('myret-->', myret)
3、距离度量方法
(一)、欧式距离
d 12 = ( x 1 − x 2 ) 2 + ( y 1 − y 2 ) 2 d 12 = ( x 1 − x 2 ) 2 + ( y 1 − y 2 ) 2 + ( z 1 − z 2 ) 2 d 12 = ∑ i = 1 N ( x 1 k − x 2 k ) 2 d_{12} = \sqrt{(x_1-x_2)^2+(y_1-y_2)^2}\\ d_{12} = \sqrt{(x_1-x_2)^2+(y_1-y_2)^2+(z_1-z_2)^2}\\ d_{12} = \sqrt{\sum_{i=1}^N(x_{1k}-x_{2k})^2} d12=(x1−x2)2+(y1−y2)2d12=(x1−x2)2+(y1−y2)2+(z1−z2)2d12=i=1∑N(x1k−x2k)2
(二)、曼哈顿距离
d 12 = ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ d 12 = ∑ i = 1 N ∣ x 1 k − x 2 k ∣ d_{12} = |x_1 - x_2|+|y_1 - y_2|\\ d_{12} = \sqrt{\sum_{i=1}^N|x_{1k} - x_{2k}|} d12=∣x1−x2∣+∣y1−y2∣d12=i=1∑N∣x1k−x2k∣
(三)、切比雪夫距离
d 12 = m a x ( ∣ x 1 − x 2 ∣ , ∣ y 1 − y 2 ) d 12 = m a x ( ∣ x 1 i − x 2 i ∣ ) d_{12} = max(|x_1 - x_2|, |y_1 - y_2)\\ d_{12} = max(|x_{1i} - x_{2i}|) d12=max(∣x1−x2∣,∣y1−y2)d12=max(∣x1i−x2i∣)
(四)、闵式距离
d 12 = ∑ i = 1 N ∣ x 1 k − x 2 k ∣ p p d_{12} = \sqrt[p]{\sum_{i=1}^N|x_{1k} - x_{2k}|^p} d12=pi=1∑N∣x1k−x2k∣p
p是一个变参数:
- p=1时,就是曼哈顿距离
- p=2时,就是欧式距离
- p->∞时,就是切比雪夫距离
4、特征预处理
特征的单位或者大小相差较大,或者某特征的方差相比其他的特征要大出几个数量级,容易影响(支配)目标结果,使得一些模型(算法)无法学习到其它的特征。
(一)、归一化
X ‘ = x − m i n m a x − m i n X ‘ ‘ = X ‘ ∗ ( m x − m i ) + m i X^` = \frac{x - min}{max - min}\\ X^{``} = X^` * (mx - mi) + mi X‘=max−minx−minX‘‘=X‘∗(mx−mi)+mi
数据归一化的API实现
sklearn.preprocessing.MinMaxScaler (feature_range=(0,1)… )
对原始数据做处理, 获取到1个 默认[mi, mx] => [0, 1] 区间的值
例如
# 导包
from sklearn.preprocessing import MinMaxScaler # 归一化的类
# 1. 准备特征数据. 每个子列表 = 1个样本(Sample)
data = [[90, 2, 10, 40], [60, 4, 15, 45], [75, 3, 13, 46]]
# 2. 创建归一化对象.
transfer = MinMaxScaler()
# 3. 具体的 归一化动作.
# fit_transform(): 训练 + 转换 => 适用于 训练集.
# transform(): 直接转换 => 适用于 测试集.
new_data = transfer.fit_transform(data)
# 4. 打印 归一化后的结果
print(f'归一化后, 数据集为: {new_data}')
归一化受到最大值与最小值的影响,这种方法容易受到异常数据的影响, 鲁棒性较差,适合传统精确小数据场景
(二)、标准化
X ‘ = x − m e a n σ X^` = \frac{x - mean}{\sigma} X‘=σx−mean
- mean为特征的平均值
- σ 为特征的标准差
数据标准化的API实现
sklearn.preprocessing. StandardScaler()
对原始数据做处理, 转换为均值为0, 标准差为1的标准正态分布序列.
例如
# 导包
from sklearn.preprocessing import StandardScaler # 标准化的类
# 1. 准备特征数据. 每个子列表 = 1个样本(Sample)
data = [[90, 2, 10, 40], [60, 4, 15, 45], [75, 3, 13, 46]]
# 2. 创建 标准化 对象.
transfer = StandardScaler()
# 3. 具体的 标准化 动作.
# fit_transform(): 训练 + 转换 => 适用于 训练集.
# transform(): 直接转换 => 适用于 测试集.
new_data = transfer.fit_transform(data)
# 4. 打印 标准化 后的结果
print(f'标准化后, 数据集为: {new_data}')
# 5. 打印每个特征列的 平均值 和 标准差
print(f'均值: {transfer.mean_}')
print(f'方差: {transfer.var_}')
对于标准化来说,如果出现异常点,由于具有一定数据量,少量的异常点对于平均值的影响并不大,标准化适用于 大数据集的 特征预处理
5、超参数选择
(一)、交叉验证
交叉验证是一种数据集的分割方法,将训练集划分为 n 份,其中一份做验证集、其他n-1份做训练集集
交叉验证法原理:将数据集划分为 cv=10 份:
1.第一次:把第一份数据做验证集,其他数据做训练
2.第二次:把第二份数据做验证集,其他数据做训练
3… 以此类推,总共训练10次,评估10次。
4.使用训练集+验证集多次评估模型,取平均值做交叉验证为模型得分
5.若k=5模型得分最好,再使用全部训练集(训练集+验证集) 对k=5模型再训练一边,再使用测试集对k=5模型做评估
交叉验证法是划分数据集的一种方法,目的就是为了得到更加准确可信的模型评分。
(二)、网格搜索
模型有很多超参数,其能力也存在很大的差异,需要手动产生很多超参数组合,来训练模型;每组超参数都采用交叉评估验证,最后选出最优参数组合建立模型。
只需要将若干参数传递给网格搜索对象,它自动就会帮我们完成不同的超参数的组合,模型训练,模型评估。最终返回一组最优的超参数。
(三)、组合
交叉验证解决模型的数据输入(数据集划分)得到更可靠的模型,网格搜索解决超参数的组合,两个组合再一起形成一个模型参数调优的解决方案。
# 导包
from sklearn.datasets import load_iris # 加载鸢尾花测试集的.
from sklearn.model_selection import train_test_split, GridSearchCV # 分割训练集和测试集的, 网格搜索 => 找最优参数组合
from sklearn.preprocessing import StandardScaler # 数据标准化的
from sklearn.neighbors import KNeighborsClassifier # KNN算法 分类对象
from sklearn.metrics import accuracy_score # 模型评估的, 计算模型预测的准确率
# 1. 加载数据.
iris_data = load_iris()
# 2. 数据预处理, 即: 划分 训练集, 测试集.
x_train, x_test, y_train, y_test = train_test_split(iris_data.data, iris_data.target, test_size=0.2, random_state=21)
# 3. 特征工程, 即: 特征的预处理 => 数据的标准化.
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train) # 训练 + 转换 => 适用于: 训练集.
x_test = transfer.transform(x_test) # 直接转换 => 适用于: 测试集.
# 4. 模型训练.
# 4.1 创建 估计器对象.
estimator = KNeighborsClassifier()
# 4.2 定义网格搜索的参数, 即: 样本可能存在的参数组合值 => 超参数.
param_dict = {'n_neighbors': [1, 2, 3, 5, 7]}
# 4.3 创建网格搜索对象, 帮我们找到最优的参数组合.
# 参1: 估计器对象, 传入1个估计器对象, 网格搜索后, 会自动返回1个功能更加强大(最优参数)的 估计器对象.
# 参2: 网格搜索的参数, 传入1个字典, 键: 参数名, 值: 参数值列表.
# 参3: 交叉验证的次数, 指定值为: 4
estimator = GridSearchCV(estimator, param_dict, cv=5)
# 4.4 调用 估计器对象的 fit方法, 完成模型训练.
estimator.fit(x_train, y_train)
# 4.5 查看网格搜索后的参数
print(f'最优组合平均分: {estimator.best_score_}')
print(f'最优估计器对象: {estimator.best_estimator_}') # 3
print(f'具体的验证过程: {estimator.cv_results_}')
print(f'最优的参数: {estimator.best_params_}')
# 5. 得到超参数最优值之后, 再次对模型进行训练.
estimator = KNeighborsClassifier(n_neighbors=3)
# 模型训练
estimator.fit(x_train, y_train)
# 模型评估
print(estimator.score(x_test, y_test)) # 0.9666666666666667
五、线性回归
1、概述
利用 回归方程(函数) 对 1个或者多个自变量(特征) 和 因变量(目标值, 标签)进行 建模分析的 思路(算法)。一个特征和一个标签的是一元线性回归,多个特征和一个标签的是多元线性回归。通常在有特征有连续标签的情况下使用。
在一元线性回归中,y=kx+b,k: 斜率, 在机器学习中叫 权重(Weight), 简称: w,b: 截距, 在机器学习中叫 偏差/偏置(Bios), 简称: b;在多元线性回归中,y = w1x1 + w2x2 + w3x3… + b => w转置 * x + b。
2、损失函数
在线性回归中,调整w和b的值找到J函数的最小值,能获得这个最小值的w和b一般就是线性回归的最佳参数值。
用来衡量 预测值 和 真实值关系的, 分类如下:
-
最小二乘法:
每个样本的 预估值 - 真实值 的平方和
J ( w , b ) = ∑ i = 0 m ( f w , b ( x ( i ) ) − y ( i ) ) 2 J(w,b) =\sum_{i=0}^m(f_{w,b}(x^{(i)}) - y^{(i)})^2 J(w,b)=i=0∑m(fw,b(x(i))−y(i))2 -
均方误差(Mean Square Error => MSE):
每个样本的 预估值 - 真实值 的平方和 / 样本数
J ( w , b ) = 1 m ∑ i = 0 m ( f w , b ( x ( i ) ) − y ( i ) ) 2 J(w,b) = \frac{1}{m}\sum_{i=0}^m(f_{w,b}(x^{(i)}) - y^{(i)})^2 J(w,b)=m1i=0∑m(fw,b(x(i))−y(i))2
- 平均绝对误差(Mean Absolute Error => MAE)
每个样本的 预估值 - 真实值 的绝对值的 和 / 样本数
J ( w , b ) = 1 m ∑ i = 0 m ∣ f w , b ( x ( i ) ) − y ( i ) ∣ J(w,b) = \frac{1}{m}\sum_{i=0}^m|f_{w,b}(x^{(i)}) - y^{(i)}| J(w,b)=m1i=0∑m∣fw,b(x(i))−y(i)∣
使用函数会帮助自动创建线性回归模型对象:
# 导包
from sklearn.linear_model import LinearRegression
# 1. 准备数据 => 训练集.
x_train = [[160], [166], [172], [174], [180]]
y_train = [56.3, 60.6, 65.1, 68.5, 75]
# 2. 创建 线性回归 模型对象.
estimator = LinearRegression()
# 3. 模型训练.
estimator.fit(x_train, y_train)
# 4. 查看下模型的参数, 即: 斜率 和 截距.
print(f'斜率 => 也叫: 权重(weight): {estimator.coef_}') # 0.92942177
print(f'截距 => 也叫: 偏置(Bios): {estimator.intercept_}') # -93.27346938775514
# 5. 模型预测.
x_test = [[176]] # 准备: 测试集的 特征.
y_predict = estimator.predict(x_test) # 预测的结果值.
print(f'预测值结果为: {y_predict}') # [70.3047619]
3、前置知识
(一)、多特征
在上述的线性回归模型中,我们只有一个特征,但是这在现实生活中的应用场景可以说是非常稀少,一般一件事物的结果都会受到好几种特征的共同影响,所以更为泛化的回归公式一般为:
f
w
,
b
(
x
)
=
w
1
x
1
+
w
2
x
2
+
w
3
x
3
+
.
.
.
.
+
w
n
x
n
+
b
f_{w,b}(x) = w_1x_1 + w_2x_2 + w_3x_3 + ....+w_nx_n + b
fw,b(x)=w1x1+w2x2+w3x3+....+wnxn+b
公式中的各个x就是事物的不同特征,w可以理解为该特征所占权重,b依旧是常数项,这些特征的共同作用下获得最终的结果。
该公式可以简化表示为:
f
w
→
,
b
(
X
→
)
=
W
→
⋅
X
→
+
b
f_{\overrightarrow{w},b}(\overrightarrow{X}) = {\overrightarrow{W}} ·{\overrightarrow{X}} + b
fw,b(X)=W⋅X+b
也就是简化为两个向量矩阵相乘。
此处需要使用numpy来对向量进行运算,
f
w
→
,
b
(
X
→
)
=
∑
i
=
1
N
w
j
x
j
+
b
f_{\overrightarrow{w},b}(\overrightarrow{X}) = \sum_{i=1}^Nw_jx_j + b
fw,b(X)=i=1∑Nwjxj+b
对每个相乘的结果进行求和运算,最终得到目标结果。
在单特征当中,权重和常数项的计算公式为:
w
=
w
−
α
1
m
∑
i
=
1
m
(
f
w
,
b
(
x
(
i
)
)
−
y
(
i
)
)
x
(
i
)
b
=
b
−
α
1
m
∑
i
=
1
m
(
f
w
,
b
(
x
(
i
)
)
−
y
(
i
)
)
w = w -\alpha\frac{1}{m}\sum_{i=1}^m(f_{w,b}(x^{(i)}) - y^{(i)})x^{(i)}\\ b = b -\alpha\frac{1}{m}\sum_{i=1}^m(f_{w,b}(x^{(i)}) - y^{(i)})
w=w−αm1i=1∑m(fw,b(x(i))−y(i))x(i)b=b−αm1i=1∑m(fw,b(x(i))−y(i))
但是多特征当中权重值有多个,分别代表不同特征的权重,最终求和,所以我们需要将不同的权重做一个标识。
w
1
=
w
1
−
α
1
m
∑
i
=
1
m
(
f
w
→
,
b
(
x
→
(
i
)
)
−
y
(
i
)
)
x
1
(
i
)
w
n
=
w
n
−
α
1
m
∑
i
=
1
m
(
f
w
→
,
b
(
x
→
(
i
)
)
−
y
(
i
)
)
x
n
(
i
)
b
=
b
−
α
1
m
∑
i
=
1
m
(
f
w
→
,
b
(
x
→
(
i
)
)
−
y
(
i
)
)
w_1 = w_1 -\alpha\frac{1}{m}\sum_{i=1}^m(f_{\overrightarrow{w},b}(\overrightarrow{x}^{(i)}) - y^{(i)})x_1^{(i)}\\ w_n = w_n -\alpha\frac{1}{m}\sum_{i=1}^m(f_{\overrightarrow{w},b}(\overrightarrow{x}^{(i)}) - y^{(i)})x_n^{(i)}\\ b = b -\alpha\frac{1}{m}\sum_{i=1}^m(f_{\overrightarrow{w},b}(\overrightarrow{x}^{(i)}) - y^{(i)})
w1=w1−αm1i=1∑m(fw,b(x(i))−y(i))x1(i)wn=wn−αm1i=1∑m(fw,b(x(i))−y(i))xn(i)b=b−αm1i=1∑m(fw,b(x(i))−y(i))
这标识多个权重全部一起计算,每次从1到n更新权重值,这就是多元回归的梯度下降。
(二)、特征缩放
在几个特征值差别较大时,会对梯度下降的速度造成影响,所以我们一般会对较大或者较小的数据进行缩放处理,一般来说缩放后的范围一般在-1到1之间。
(三)、选择合适的学习率
在上文我们能得出结论,在学习率过小的时候,我们需要的迭代次数会非常的大,在学习率过大的时候,又会导致数据无法收敛,所以在学习率的选择上,我们通常会选择0.001开始,然后0.003,再0.01,依次类推,直到学习率过大或者达到1为止,每次的学习率都是上一次学习率的3倍左右,这样可以达到一个相对节省资源的状态。
4、正规方程法求解
(一)、一元线性回归
损失函数为:
J
(
w
,
b
)
=
∑
i
=
1
m
(
f
w
,
b
(
x
(
i
)
)
−
y
(
i
)
)
2
=
∑
i
=
1
m
(
w
x
(
i
)
+
b
−
y
(
i
)
)
2
x
(
i
)
代表第
i
个样本的特征值
y
(
i
)
代表第
i
个样本的预测值
J(w,b) =\sum_{i=1}^m(f_{w,b}(x^{(i)}) - y^{(i)})^2=\sum_{i=1}^m(wx^{(i)} + b - y^{(i)})^2 \\x^{(i)}代表第i个样本的特征值 \\y^{(i)}代表第i个样本的预测值
J(w,b)=i=1∑m(fw,b(x(i))−y(i))2=i=1∑m(wx(i)+b−y(i))2x(i)代表第i个样本的特征值y(i)代表第i个样本的预测值
对上面的式子进行偏导求解。
∂
J
(
w
,
b
)
∂
w
=
∑
i
=
1
m
(
2
w
(
x
(
i
)
)
2
+
2
b
x
(
i
)
−
2
x
(
i
)
y
(
i
)
=
0
∂
J
(
w
,
b
)
∂
b
=
∑
i
=
1
m
(
2
w
(
x
(
i
)
)
2
+
2
b
−
2
y
(
i
)
=
0
\frac{\partial J(w,b)}{\partial w} = \sum_{i=1}^m(2w(x^{(i)})^{2} + 2bx^{(i)}-2x^{(i)}y^{(i)}=0\\ \frac{\partial J(w,b)}{\partial b} = \sum_{i=1}^m(2w(x^{(i)})^{2} + 2b-2y^{(i)}=0
∂w∂J(w,b)=i=1∑m(2w(x(i))2+2bx(i)−2x(i)y(i)=0∂b∂J(w,b)=i=1∑m(2w(x(i))2+2b−2y(i)=0
然后将特征值带入,计算出 w和b的值,最终得到y=wx+b的式子
(二)、多元线性回归
根据一元损失函数易得多元损失函数为:
J
(
w
,
b
)
=
∑
i
=
1
m
(
w
i
x
i
+
b
−
y
i
)
2
将上述公式转为矩阵形式:
∑
i
=
1
m
(
f
(
x
i
)
−
y
i
)
2
=
∣
∣
X
w
−
y
∣
∣
2
2
数据集为
D
=
{
(
x
1
,
y
1
)
,
(
x
2
,
y
2
)
,
.
.
.
.
,
(
x
n
,
y
n
)
}
J(w,b) =\sum_{i=1}^m(w_ix_{i} + b - y_{i})^2\\ 将上述公式转为矩阵形式:\sum_{i=1}^m(f(x_i)-y_i)^2=||Xw - y||_2^2\\ 数据集为D = \{(x_1,y_1),(x_2,y_2),....,(x_n,y_n)\}
J(w,b)=i=1∑m(wixi+b−yi)2将上述公式转为矩阵形式:i=1∑m(f(xi)−yi)2=∣∣Xw−y∣∣22数据集为D={(x1,y1),(x2,y2),....,(xn,yn)}
再计算损失函数的最小值:
2
(
X
→
w
−
y
)
∗
X
→
=
0
2
(
X
→
w
−
y
)
∗
(
X
→
X
→
T
)
=
0
X
→
T
2
(
X
→
w
−
y
)
∗
(
X
→
X
→
T
)
∗
(
X
→
X
→
T
)
−
1
=
0
X
→
T
∗
(
X
→
X
→
T
)
−
1
2
(
X
→
w
−
y
)
=
0
X
→
w
=
y
X
→
T
X
→
w
=
X
→
T
y
(
X
→
T
X
→
)
−
1
(
X
→
T
X
→
)
∗
w
=
(
X
→
T
X
→
)
−
1
∗
X
→
T
y
w
=
(
X
→
T
X
→
)
−
1
∗
X
→
T
y
2(\overrightarrow Xw-y)*\overrightarrow X = 0\\ 2(\overrightarrow Xw-y)*(\overrightarrow X \overrightarrow X^T)=0\overrightarrow X^T\\ 2(\overrightarrow Xw-y)*(\overrightarrow X \overrightarrow X^T)*(\overrightarrow X \overrightarrow X^T)^{-1}=0\overrightarrow X^T*(\overrightarrow X \overrightarrow X^T)^{-1}\\ 2(\overrightarrow Xw - y)=0\\ \overrightarrow Xw=y\\ \overrightarrow X^T\overrightarrow Xw = \overrightarrow X^Ty\\ (\overrightarrow X^T \overrightarrow X)^{-1}(\overrightarrow X^T \overrightarrow X)*w=(\overrightarrow X^T \overrightarrow X)^{-1}*\overrightarrow X^Ty\\ w = (\overrightarrow X^T \overrightarrow X)^{-1}*\overrightarrow X^Ty
2(Xw−y)∗X=02(Xw−y)∗(XXT)=0XT2(Xw−y)∗(XXT)∗(XXT)−1=0XT∗(XXT)−12(Xw−y)=0Xw=yXTXw=XTy(XTX)−1(XTX)∗w=(XTX)−1∗XTyw=(XTX)−1∗XTy
得出正规方程的解析解答案
5、梯度下降
(一)、概述
单变量函数中,梯度就是某一点切线斜率(某一点的导数);有方向为函数增长最快的方向
多变量函数中,梯度就是某一个点的偏导数;有方向:偏导数分量的向量方向
(二)、求导
w = w − α ∂ ∂ w J ( w , b ) b = b − α ∂ ∂ b J ( w , b ) α : 学习率 ( 步长 ) 不能太大 , 也不能太小 . 机器学习中: 0.001 − 0.01 w = w - \alpha\frac{\partial}{\partial{w}}J(w, b)\\ b = b - \alpha\frac{\partial}{\partial{b}}J(w, b)\\ α: 学习率(步长) 不能太大, 也不能太小. 机器学习中:0.001 - 0.01 w=w−α∂w∂J(w,b)b=b−α∂b∂J(w,b)α:学习率(步长)不能太大,也不能太小.机器学习中:0.001−0.01
每次走一小步,向下降最快的方向前进(在一小步范围内最优结果的方向,或者可以理解为曲率最大的方向前进),直到找到最优解的点。所以对于学习率的选取尤为重要,如果太小可能会导致优化次数的增加,如果太大可能会导致学习函数不收敛,导致一直找不到目标数值,从而获取不到目标的最优解。
(三)、分类
- 全梯度下降算法FGD–每次迭代,使用全部样本的梯度值,所以速度较慢。
w i + 1 = w i − α ∑ j = 0 m ( f ( w , b ) θ ( x 0 ( j ) , x 1 ( j ) , . . . , x n ( j ) ) − y j ) x i ( j ) w_{i+1} = w_i-\alpha\sum_{j=0}^m(f(w,b)_\theta(x_0^{(j)},x_1^{(j)},...,x_n^{(j)})-y_j)x_i^{(j)} wi+1=wi−αj=0∑m(f(w,b)θ(x0(j),x1(j),...,xn(j))−yj)xi(j)
-
随机梯度下降算法SGD–每次迭代,随机选择并使用一个样本梯度值。
w i + 1 = w i − α ( f ( w , b ) ( ( x 0 ( j ) , x 1 ( j ) , . . . , x n ( j ) ) − y j ) x i ( j ) w_{i+1} = w_i -\alpha(f(w,b)((x_0^{(j)},x_1^{(j)},...,x_n^{(j)})-y_j)x_i^{(j)} wi+1=wi−α(f(w,b)((x0(j),x1(j),...,xn(j))−yj)xi(j) -
小批量梯度下降算法mini-bantch–每次迭代时,随机选择并使用小批量的样本梯度值,从m个样本中选择x个样本进行迭代(1<x<m)。目前使用最多。
w i + 1 = w i − α ∑ j = t t + x − 1 ( f ( w , b ) θ ( x 0 ( j ) , x 1 ( j ) , . . . , x n ( j ) ) − y j ) x i ( j ) 如果 b a t c h s i z e = 1 ,就变成了 S G D ;如果 b a t c h s i z e = n ,就变成了 F G D w_{i+1} = w_i-\alpha\sum_{j=t}^{t+x-1}(f(w,b)_\theta(x_0^{(j)},x_1^{(j)},...,x_n^{(j)})-y_j)x_i^{(j)}\\ 如果batchsize=1,就变成了SGD;如果batchsize=n,就变成了FGD wi+1=wi−αj=t∑t+x−1(f(w,b)θ(x0(j),x1(j),...,xn(j))−yj)xi(j)如果batchsize=1,就变成了SGD;如果batchsize=n,就变成了FGD
- 随机平均梯度下降算法SAG–每次迭代时,随机选择一个样本的梯度值和以往样本的梯度值的均值,训练出去表现不佳,优化速度较慢。
w i + 1 = w i − α n ∑ j = 0 n ( f ( w , b ) θ ( x 0 ( j ) , x 1 ( j ) , . . . , x n ( j ) ) − y j ) x i ( j ) w_{i+1} = w_i-\frac{\alpha}{n}\sum_{j=0}^n(f(w,b)_\theta(x_0^{(j)},x_1^{(j)},...,x_n^{(j)})-y_j)x_i^{(j)} wi+1=wi−nαj=0∑n(f(w,b)θ(x0(j),x1(j),...,xn(j))−yj)xi(j)
6、正规方程与梯度下降对比
-
正规方程
- 不需要学习率
- 一次运算得出,一蹴而就
- 应用场景:小数据量场景、精准的数据场景
- 缺点:计算量大、容易收到噪声、特征强相关性的影响
- 注意:X^TX的逆矩阵不存在时,无法求解
- 注意:计算X^TX的逆矩阵非常耗时
- 如果数据规律不是线性的,无法使用或效果不好
-
梯度下降
- 需要选择学习率
- 需要迭代求解
- 特征数量较大可以使用应用场景:更加普适,迭代的计算方式,适合于嘈杂、大数据应用场景
- 注意:梯度下降在各种损失函数(目标函数)求解中大量使用。深度学习中更是如此,深度学习模型参数很轻松就上亿,只能通过迭代的方式求最优解。
7、模型评估
我们希望衡量预测值和真实值之间的差距,我们会用到MAE、MSE、RMSE多种测评函数进行评价
(一)、均方误差MSE–Mean Squared Error
M S E = 1 n ∑ i = 1 n ( y i − y i ^ ) 2 n 为样本数量、 y 为实际值、 y ^ 为预测值 MSE = \frac{1}{n}\sum_{i=1}^n(y_i-\hat{y_i})^2\\ n为样本数量、y为实际值、\hat{y}为预测值 MSE=n1i=1∑n(yi−yi^)2n为样本数量、y为实际值、y^为预测值
MSE越小模型预测越准确
from sklearn.metrics import mean_squared_error
mean_squared_error(y_test,y_predict)
(二)、平均绝对误差MAE–Mean Absolute Error
M A E = 1 n ∑ i = 1 n ∣ y i − y i ^ ∣ n 为样本数量、 y 为实际值、 y ^ 为预测值 MAE = \frac{1}{n}\sum_{i=1}^n|y_i - \hat{y_i}|\\ n为样本数量、y为实际值、\hat{y}为预测值 MAE=n1i=1∑n∣yi−yi^∣n为样本数量、y为实际值、y^为预测值
MAE越小模型预测越准确
from sklearn.metrics import mean_absolute_error
mean_absolute_error(y_test,y_predict)
(三)、均方根误差RMSE–Root Mean Squared Error
R M S E = 1 n ∑ i = 1 n ( y i − y i ^ ) 2 n 为样本数量、 y 为实际值、 y ^ 为预测值 RMSE = \sqrt{\frac{1}{n}\sum_{i=1}^n(y_i-\hat{y_i})^2}\\ n为样本数量、y为实际值、\hat{y}为预测值 RMSE=n1i=1∑n(yi−yi^)2n为样本数量、y为实际值、y^为预测值
RMSE越小模型预测越准确
RMSE 是 MSE 的平方根,某些情况下比MES更有用
(四)、三种指标对比
一般使用MAE 和 RMSE 这两个指标
-
MAE反应的是“真实”的平均误差,RMSE会将误差大的数据点放大
-
大多数情况下RMSE>MAE,RMSE > MAE都能反应真实误差,但是RMSE会对异常点更加敏感
-
如果RMSE指标训练的非常低,模型对异常点(对噪声)也拟合的非常好,这样模型就容易过拟合了。所以评价指标要综合的看
8、经典波士顿房价预估模型
(一)、正规方程
# 导包
# from sklearn.datasets import load_boston # 数据
from sklearn.preprocessing import StandardScaler # 特征处理
from sklearn.model_selection import train_test_split # 数据集划分
from sklearn.linear_model import LinearRegression # 正规方程的回归模型
from sklearn.linear_model import SGDRegressor # 梯度下降的回归模型
from sklearn.metrics import mean_squared_error, mean_absolute_error, root_mean_squared_error # 均方误差评估
from sklearn.linear_model import Ridge, RidgeCV
import pandas as pd
import numpy as np
# 1. 加载数据集.
# 数据集的URL地址
data_url = "http://lib.stat.cmu.edu/datasets/boston"
# pandas读取数据集
raw_df = pd.read_csv(data_url, sep="\\s+", skiprows=22, header=None)
# 从数据集中获取: 特征数据
data = np.hstack([raw_df.values[::2, :], raw_df.values[1::2, :2]])
# 从数据集中获取: 标签数据
target = raw_df.values[1::2, 2]
# 打印结果
print(len(data), len(target)) # 506, 506
# 2. 数据的预处理, 把总数据506条 => 按照8:2的比例分为训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(data, target, test_size=0.2, random_state=21)
# 3. 特征工程: 特征预处理(归一化, 标准化)
# 3.1 创建 标准化对象.
transfer = StandardScaler()
# 3.2 标准化 训练集.
x_train = transfer.fit_transform(x_train)
# 3.3 标准化 测试集.
x_test = transfer.transform(x_test)
print(len(x_train), len(x_test))
# 4. 模型训练.
# 4.1 创建 线性回归模型对象 => 正规方程的方式.
# 参数: fit_intercept 意思是 是否需要计算截距值(偏置), 默认是: True
estimator = LinearRegression(fit_intercept=True)
# 4.2 模型训练.
estimator.fit(x_train, y_train) # 训练集的特征, 训练集的标签
# 4.3 打印 模型的 权重和偏置.
print(f'权重: {estimator.coef_}')
print(f'偏置: {estimator.intercept_}')
# 5. 模型预测.
y_predict = estimator.predict(x_test) # 测试集的特征
print(f'模型预测结果: {y_predict}')
# 6. 模型评估.
# 6.1 基于 预测值(y_predict) 和 真实值(y_test)计算, 模型的: 均方误差(Mean Square Error => MSE)
print(f'该模型的均方误差: {mean_squared_error(y_test, y_predict)}') # 26.82540057393935
# 6.2 平均绝对误差
print(f'该模型的平均绝对误差: {mean_absolute_error(y_test, y_predict)}')
# 6.3 均方根误差
print(f'该模型的均方根误差: {root_mean_squared_error(y_test, y_predict)}')
(二)、梯度下降
# 导包
# from sklearn.datasets import load_boston # 数据
from sklearn.preprocessing import StandardScaler # 特征处理
from sklearn.model_selection import train_test_split # 数据集划分
from sklearn.linear_model import LinearRegression # 正规方程的回归模型
from sklearn.linear_model import SGDRegressor # 梯度下降的回归模型
from sklearn.metrics import mean_squared_error, mean_absolute_error, root_mean_squared_error # 均方误差评估
from sklearn.linear_model import Ridge, RidgeCV
import pandas as pd
import numpy as np
# 1. 加载数据集.
# 数据集的URL地址
data_url = "http://lib.stat.cmu.edu/datasets/boston"
# pandas读取数据集
raw_df = pd.read_csv(data_url, sep="\\s+", skiprows=22, header=None)
# 从数据集中获取: 特征数据
data = np.hstack([raw_df.values[::2, :], raw_df.values[1::2, :2]])
# 从数据集中获取: 标签数据
target = raw_df.values[1::2, 2]
# 打印结果
print(len(data), len(target)) # 506, 506
# 2. 数据的预处理, 把总数据506条 => 按照8:2的比例分为训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(data,
target, test_size=0.2, random_state=21)
# 3. 特征工程: 特征预处理(归一化, 标准化)
# 3.1 创建 标准化对象.
transfer = StandardScaler()
# 3.2 标准化 训练集.
x_train = transfer.fit_transform(x_train)
# 3.3 标准化 测试集.
x_test = transfer.transform(x_test)
print(len(x_train), len(x_test))
# 4. 模型训练.
# 4.1 创建 线性回归模型对象 => 梯度下降的方式. 简单理解梯度下降: 新的点 = 当前点 - 学习率 * 梯度
# 参数: fit_intercept 意思是 是否需要计算截距值(偏置), 默认是: True
# estimator = LinearRegression(fit_intercept=True) # 正规方程-线性回归模型对象.
# constant: 常量, 即: 学习率的值.
estimator = SGDRegressor(fit_intercept=True,
learning_rate='constant', eta0=0.001)
# 4.2 模型训练.
estimator.fit(x_train, y_train) # 训练集的特征, 训练集的标签
# 4.3 打印 模型的 权重和偏置.
print(f'权重: {estimator.coef_}')
print(f'偏置: {estimator.intercept_}')
# 5. 模型预测.
y_predict = estimator.predict(x_test) # 测试集的特征
print(f'模型预测结果: {y_predict}')
# 6. 模型评估.
# 6.1 基于 预测值(y_predict) 和 真实值(y_test)计算, 模型的: 均方误差(Mean Square Error => MSE)
print(f'该模型的均方误差: {mean_squared_error(y_test, y_predict)}') # 26.82540057393935
# 6.2 平均绝对误差
print(f'该模型的平均绝对误差: {mean_absolute_error(y_test, y_predict)}')
# 6.3 均方根误差
print(f'该模型的均方根误差: {root_mean_squared_error(y_test, y_predict)}')
9、欠拟合和过拟合
(一)、概述
欠拟合:
模型在训练集上表现不好,在测试集上也表现不好。模型过于简单,在训练集和测试集上的误差都较大
过拟合:
模型在训练集上表现好,在测试集上表现不好。模型过于复杂,在训练集上误差较小,而测试集上误差较大
(二)、出现原因和解决方案
(1)、欠拟合
出现原因:
- 学习到数据的特征过少
解决方案:
-
添加其他特征
-
有时出现欠拟合是因为特征项不够导致的,可以添加其他特征项来解决
-
“组合”、“泛化”、“相关性”三类特征是特征添加的重要手段
-
-
添加多项式特征项
- 模型过于简单时的常用套路,例如将线性模型通过添加二次项或三次项使模型泛化能力更强
(2)、过拟合
出现原因:
- 原始特征过多,存在一些嘈杂特征, 模型过于复杂是因为模型尝试去兼顾各个测试数据点
解决方案:
- 重新清洗数据
- 对于过多异常点数据、数据不纯的地方再处理
- 增大数据的训练量
- 对原来的数据训练的太过了,增加数据量的情况下,会缓解
- 正则化
- 解决模型过拟合的方法,在机器学习、深度学习中大量使用
- 减少特征维度,防止维灾难
- 由于特征多,样本数量少,导致学习不充分,泛化能力差。
(三)、正则化
(1)、概述
在模型训练时,数据中有些特征影响模型复杂度、或者某个特征的异常值较多, 所以要尽量减少这个特征的影响(甚至删除某个特征的影响),这就是正则化
(2)、作用
在损失函数中增加正则化项分为L1正则化、L2正则化。分别可以筛出异常值和减小异常值影响。
①L1正则化
J ( w ) = M S E ( w ) + α ∑ i = 1 n ∣ w i ∣ α 叫做惩罚系数 J(w) = MSE(w) +\alpha\sum_{i=1}^n|w_i|\\ \alpha叫做惩罚系数 J(w)=MSE(w)+αi=1∑n∣wi∣α叫做惩罚系数
惩罚系数越大则权重调整的幅度就越大,即:表示对特征权重惩罚力度就越大
L1 正则化会使得权重趋向于 0,甚至等于 0,使得某些特征失效,达到特征筛选的目的
使用 L1 正则化的线性回归模型是 Lasso 回归,Lasso回归L1正则 会将高次方项系数变为0
from sklearn.linear_model import Lasso
②L2正则化
J ( w ) = M S E ( w ) + α ∑ i = 1 n w i 2 α 叫做惩罚系数 J(w)=MSE(w)+\alpha\sum_{i=1}^nw_i^2\\ \alpha叫做惩罚系数 J(w)=MSE(w)+αi=1∑nwi2α叫做惩罚系数
惩罚系数越大则权重调整的幅度就越大,即:表示对特征权重惩罚力度就越大
L2 正则化会使得权重趋向于 0,一般不等于 0
使用 L2 正则化的线性回归模型是岭回归,Ridge线性回归l2正则不会将系数变为0 但是对高次方项系数影响较大
from sklearn.linear_model import Ridge
在工程开发中一般倾向使用L2正则。
(四)、代码模拟
# 导包
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error # 计算均方误差
from sklearn.model_selection import train_test_split
from sklearn.linear_model import Ridge, Lasso
(1)、欠拟合
# 1. 定义函数, 表示: 欠拟合.
def dm01_欠拟合():
# 1. 准备数据.
# 准备噪声(可以简单理解为就是: 随机种子), 噪声相同, 每次生成的随机数(点)相同.
np.random.seed(21)
# x: 表示特征, -3 ~ 3之间 随机的小数, 生成: 100个.
x = np.random.uniform(-3, 3, size=100)
# y: 表示标签(目标值), 线性关系: y = 0.5x² + x + 2 + 正态分布 + 噪声.
# np.random.normal(0, 1, size=100) 意思是: 均值为0, 标准差为1, 生成100个.
y = 0.5 * x ** 2 + x + 2 + np.random.normal(0, 1, size=100)
# 模型训练.
# 2. 创建 线性回归-正规方程 模型对象.
estimator = LinearRegression(fit_intercept=True) # 计算: 偏置.
# 3. 对数据集做处理.
X = x.reshape(-1, 1)
# print(f'处理前 x => {x}') # 假设: x = [1, 2, 3]
# print(f'处理后 X => {X}') # 处理后: X = [[1], [2], [3]]
# 4. 模型训练.
estimator.fit(X, y) # 这里传的是, 处理后的x的值, 即: 二维数组.
# 5. 模型预测.
y_predict = estimator.predict(X)
print(f'预测值为: {y_predict}')
# 6. 模型评估.
print(f'均方误差: {mean_squared_error(y, y_predict)}') # 2.0683653437315512
# 7. 数据可视化, 绘制图像.
plt.scatter(x, y) # 基于: 原始的x(特征), y值(真实值)绘制 散点图.
plt.plot(x, y_predict, c='r') # 基于: 原值的x(特征), y值(预测值)绘制 折线图(就是我们的 拟合回归线)
plt.show()
(2)、过拟合
# 2. 定义函数, 表示: 过拟合.
def dm02_过拟合():
# 1. 准备数据.
# 准备噪声(可以简单理解为就是: 随机种子), 噪声相同, 每次生成的随机数(点)相同.
np.random.seed(21)
# x: 表示特征, -3 ~ 3之间 随机的小数, 生成: 100个.
x = np.random.uniform(-3, 3, size=100)
# y: 表示标签(目标值), 线性关系: y = 0.5x² + x + 2 + 正态分布 + 噪声.
# np.random.normal(0, 1, size=100) 意思是: 均值为0, 标准差为1, 生成100个.
y = 0.5 * x ** 2 + x + 2 + np.random.normal(0, 1, size=100)
# 模型训练.
# 2. 创建 线性回归-正规方程 模型对象.
estimator = LinearRegression(fit_intercept=True) # 计算: 偏置.
# 3. 对数据集做处理.
# 3.1 把数据从 一维数组 => 二维数组, 即: 从 [1, 2, 3] => [[1], [2], [3]]
X = x.reshape(-1, 1)
# 3.2 拼接: x, x的平方, x的立方, x的四次方..., 把数据从 [[1], [2], [3]] => [[1, 1....], [2, 4, 8, 16, 32, 64...], [3, 9, 27...]] 一元线性回归 => 二元线性回归
X3 = np.hstack([X, X ** 2, X ** 3, X ** 4, X ** 5, X ** 6, X ** 7, X ** 8, X ** 9, X ** 10]) # 继续增加 最高次项
print(f'处理前 x => {x}') # 假设: x = [1, 2, 3]
print(f'处理后 X => {X}') # 处理后: X = [[1], [2], [3]]
print(f'处理后 X2 => {X3}') # 处理后: X = [[1], [2], [3]]
# 4. 模型训练.
estimator.fit(X3, y) # 这里传的是, 处理后的x的值, 即: 二维数组 => 多元线性回归
# 5. 模型预测.
y_predict = estimator.predict(X3)
print(f'预测值为: {y_predict}')
# 6. 模型评估.
print(f'均方误差: {mean_squared_error(y, y_predict)}') # 均方误差: 0.9646255969834893
# 7. 数据可视化, 绘制图像.
plt.scatter(x, y) # 基于: 原始的x(特征), y值(真实值)绘制 散点图.
# 细节: 要对x的值进行升序排列, 然后再绘制, 否则会出现: 散点没有连贯性.
# plt.plot(x, y_predict, c='r') # 基于: 原值的x(特征), y值(预测值)绘制 折线图(就是我们的 拟合回归线)
# np.sort(x): 按照x的值 升序排列.
# np.argsort(x): 按照x的值 升序排列, 返回(x对应的)索引值.
plt.plot(np.sort(x), y_predict[np.argsort(x)], c='r') # 基于: 原值的x(特征), y值(预测值)绘制 折线图(就是我们的 拟合回归线)
plt.show()
(3)、刚好拟合
# 3. 定义函数, 表示: 正好拟合.
def dm03_正好拟合():
# 1. 准备数据.
# 准备噪声(可以简单理解为就是: 随机种子), 噪声相同, 每次生成的随机数(点)相同.
np.random.seed(21)
# x: 表示特征, -3 ~ 3之间 随机的小数, 生成: 100个.
x = np.random.uniform(-3, 3, size=100)
# y: 表示标签(目标值), 线性关系: y = 0.5x² + x + 2 + 正态分布 + 噪声.
# np.random.normal(0, 1, size=100) 意思是: 均值为0, 标准差为1, 生成100个.
y = 0.5 * x ** 2 + x + 2 + np.random.normal(0, 1, size=100)
# 模型训练.
# 2. 创建 线性回归-正规方程 模型对象.
estimator = LinearRegression(fit_intercept=True) # 计算: 偏置.
# 3. 对数据集做处理.
# 3.1 把数据从 一维数组 => 二维数组, 即: 从 [1, 2, 3] => [[1], [2], [3]]
X = x.reshape(-1, 1)
# 3.2 拼接: x 和 x的平方, 把数据从 [[1], [2], [3]] => [[1, 1], [2, 4], [3, 9]] 一元线性回归 => 二元线性回归
X2 = np.hstack([X, X ** 2]) #
print(f'处理前 x => {x}') # 假设: x = [1, 2, 3]
print(f'处理后 X => {X}') # 处理后: X = [[1], [2], [3]]
print(f'处理后 X2 => {X2}') # 处理后: X = [[1], [2], [3]]
# 4. 模型训练.
estimator.fit(X2, y) # 这里传的是, 处理后的x的值, 即: 二维数组 => 二元线性回归
# 5. 模型预测.
y_predict = estimator.predict(X2)
print(f'预测值为: {y_predict}')
# 6. 模型评估.
print(f'均方误差: {mean_squared_error(y, y_predict)}') # 均方误差: 1.0009503498374301
# 7. 数据可视化, 绘制图像.
plt.scatter(x, y) # 基于: 原始的x(特征), y值(真实值)绘制 散点图.
# 细节: 要对x的值进行升序排列, 然后再绘制, 否则会出现: 散点没有连贯性.
# plt.plot(x, y_predict, c='r') # 基于: 原值的x(特征), y值(预测值)绘制 折线图(就是我们的 拟合回归线)
# np.sort(x): 按照x的值 升序排列.
# np.argsort(x): 按照x的值 升序排列, 返回(x对应的)索引值.
plt.plot(np.sort(x), y_predict[np.argsort(x)], c='r') # 基于: 原值的x(特征), y值(预测值)绘制 折线图(就是我们的 拟合回归线)
plt.show()
(4)、L1正则化–Lasso回归
# 4. 定义函数, 表示: L1正则化 => 解决 过拟合问题的, 降低模型复杂度, 可能会使得权重变为0 => 特征选取.
def dm04_L1正则化():
# 1. 准备数据.
# 准备噪声(可以简单理解为就是: 随机种子), 噪声相同, 每次生成的随机数(点)相同.
np.random.seed(21)
# x: 表示特征, -3 ~ 3之间 随机的小数, 生成: 100个.
x = np.random.uniform(-3, 3, size=100)
# y: 表示标签(目标值), 线性关系: y = 0.5x² + x + 2 + 正态分布 + 噪声.
# np.random.normal(0, 1, size=100) 意思是: 均值为0, 标准差为1, 生成100个.
y = 0.5 * x ** 2 + x + 2 + np.random.normal(0, 1, size=100)
# 模型训练.
# 2. 创建 线性回归-正规方程 模型对象.
# estimator = LinearRegression(fit_intercept=True) # 计算: 偏置.
# 2. 创建 线性回归-L1正则化 模型对象.
estimator = Lasso(alpha=0.1) # alpha: 正则化参数, 其值越大, 则正则化程度越高, 即: 权重值越小, 则越容易被截断为0.
# 3. 对数据集做处理.
# 3.1 把数据从 一维数组 => 二维数组, 即: 从 [1, 2, 3] => [[1], [2], [3]]
X = x.reshape(-1, 1)
# 3.2 拼接: x, x的平方, x的立方, x的四次方..., 把数据从 [[1], [2], [3]] => [[1, 1....], [2, 4, 8, 16, 32, 64...], [3, 9, 27...]] 一元线性回归 => 二元线性回归
X3 = np.hstack([X, X ** 2, X ** 3, X ** 4, X ** 5, X ** 6, X ** 7, X ** 8, X ** 9, X ** 10]) # 继续增加 最高次项
print(f'处理前 x => {x}') # 假设: x = [1, 2, 3]
print(f'处理后 X => {X}') # 处理后: X = [[1], [2], [3]]
print(f'处理后 X2 => {X3}') # 处理后: X = [[1], [2], [3]]
# 4. 模型训练.
estimator.fit(X3, y) # 这里传的是, 处理后的x的值, 即: 二维数组 => 多元线性回归
# 5. 模型预测.
y_predict = estimator.predict(X3)
print(f'预测值为: {y_predict}')
# 6. 模型评估.
print(f'均方误差: {mean_squared_error(y, y_predict)}') # 均方误差: 1.026270345364126
# 7. 数据可视化, 绘制图像.
plt.scatter(x, y) # 基于: 原始的x(特征), y值(真实值)绘制 散点图.
# 细节: 要对x的值进行升序排列, 然后再绘制, 否则会出现: 散点没有连贯性.
# plt.plot(x, y_predict, c='r') # 基于: 原值的x(特征), y值(预测值)绘制 折线图(就是我们的 拟合回归线)
# np.sort(x): 按照x的值 升序排列.
# np.argsort(x): 按照x的值 升序排列, 返回(x对应的)索引值.
plt.plot(np.sort(x), y_predict[np.argsort(x)], c='r') # 基于: 原值的x(特征), y值(预测值)绘制 折线图(就是我们的 拟合回归线)
plt.show()
(5)、L2正则化–Ridge回归
# 5. 定义函数, 表示: L2正则化 => 解决 过拟合问题的, 降低模型复杂度. 会使得权重趋向于0, 不会变为0.
def dm05_L2正则化():
# 1. 准备数据.
# 准备噪声(可以简单理解为就是: 随机种子), 噪声相同, 每次生成的随机数(点)相同.
np.random.seed(21)
# x: 表示特征, -3 ~ 3之间 随机的小数, 生成: 100个.
x = np.random.uniform(-3, 3, size=100)
# y: 表示标签(目标值), 线性关系: y = 0.5x² + x + 2 + 正态分布 + 噪声.
# np.random.normal(0, 1, size=100) 意思是: 均值为0, 标准差为1, 生成100个.
y = 0.5 * x ** 2 + x + 2 + np.random.normal(0, 1, size=100)
# 模型训练.
# 2. 创建 线性回归-正规方程 模型对象.
# estimator = LinearRegression(fit_intercept=True) # 计算: 偏置.
# 2. 创建 线性回归-L2正则化 模型对象.
estimator = Ridge(alpha=0.1) # alpha: 正则化参数, 其值越大, 则正则化程度越高, 即: 权重值越小, 则越容易被截断为0.
# 3. 对数据集做处理.
# 3.1 把数据从 一维数组 => 二维数组, 即: 从 [1, 2, 3] => [[1], [2], [3]]
X = x.reshape(-1, 1)
# 3.2 拼接: x, x的平方, x的立方, x的四次方..., 把数据从 [[1], [2], [3]] => [[1, 1....], [2, 4, 8, 16, 32, 64...], [3, 9, 27...]] 一元线性回归 => 二元线性回归
X3 = np.hstack([X, X ** 2, X ** 3, X ** 4, X ** 5, X ** 6, X ** 7, X ** 8, X ** 9, X ** 10]) # 继续增加 最高次项
print(f'处理前 x => {x}') # 假设: x = [1, 2, 3]
print(f'处理后 X => {X}') # 处理后: X = [[1], [2], [3]]
print(f'处理后 X2 => {X3}') # 处理后: X = [[1], [2], [3]]
# 4. 模型训练.
estimator.fit(X3, y) # 这里传的是, 处理后的x的值, 即: 二维数组 => 多元线性回归
# 5. 模型预测.
y_predict = estimator.predict(X3)
print(f'预测值为: {y_predict}')
# 6. 模型评估.
print(f'均方误差: {mean_squared_error(y, y_predict)}') # 均方误差: 0.964988964298911
# 7. 数据可视化, 绘制图像.
plt.scatter(x, y) # 基于: 原始的x(特征), y值(真实值)绘制 散点图.
# 细节: 要对x的值进行升序排列, 然后再绘制, 否则会出现: 散点没有连贯性.
# plt.plot(x, y_predict, c='r') # 基于: 原值的x(特征), y值(预测值)绘制 折线图(就是我们的 拟合回归线)
# np.sort(x): 按照x的值 升序排列.
# np.argsort(x): 按照x的值 升序排列, 返回(x对应的)索引值.
plt.plot(np.sort(x), y_predict[np.argsort(x)], c='r') # 基于: 原值的x(特征), y值(预测值)绘制 折线图(就是我们的 拟合回归线)
plt.show()
六、逻辑回归
1、概述
一种分类模型,将线性回归的输出作为逻辑回归的输入,利用sigmoid函数做转换,输出(0,1)之间的值。
利用线性模型
f
(
x
)
=
w
T
x
+
b
f(x)=w^Tx + b
f(x)=wTx+b
根据特性的重要性计算出一个值,再使用sigmoid函数将f(x)的输出值映射出概率值,设置阈值为0.5,输出概率值大于0.5,则将未知样本输出为1类,否则为0类。
逻辑回归的假设函数
:
h
(
w
)
=
s
i
g
m
o
i
d
(
w
T
x
+
b
)
逻辑回归的假设函数:h(w) = sigmoid(w^Tx + b)
逻辑回归的假设函数:h(w)=sigmoid(wTx+b)
2、损失函数
L o s s ( L ) = − ∑ i = 1 m ( y i l o g ( p i ) + ( 1 − y i ) l o g ( 1 − p i ) ) p i = s i g m o i d ( w T x + b ) 是逻辑回归的输出结果 Loss(L)=-\sum_{i=1}^m(y_ilog(p_i)+(1-y_i)log(1-p_i))\\ p_i=sigmoid(w^Tx + b)是逻辑回归的输出结果 Loss(L)=−i=1∑m(yilog(pi)+(1−yi)log(1−pi))pi=sigmoid(wTx+b)是逻辑回归的输出结果
损失函数的工作原理:每个样本预测值有A、B两个类别,真实类别对应的位置,概率值越大越好。
当只有一个样本时,他的概率为:
L
=
{
p
i
f
y
=
1
1
−
p
i
f
y
=
0
L=\begin{cases}p\ \ \ \ if\ \ \ \ y=1 \\1-p\ \ \ \ if\ \ \ \ y=0 \end{cases}
L={p if y=11−p if y=0
当样本时1类别时模型预测的p越大越好,当样本时0类别时模型预测的(1-p)越大越好
当有n个样本时,他的概率为:
p
=
p
(
y
1
∣
x
1
)
p
(
y
2
∣
x
2
)
.
.
.
p
(
y
n
∣
x
n
)
=
∏
i
=
1
n
p
y
i
(
1
−
p
)
1
−
y
i
p
i
表示每个样本被分类正确时的概率
y
i
表示每个样本真实类别
(
0
或
1
)
p=p(y_1|x_1)p(y_2|x_2)...p(y_n|x_n)=\prod_{i=1}^{n}p^{y_i}(1-p)^{1-{y_i}}\\ p_i表示每个样本被分类正确时的概率\\ y_i表示每个样本真实类别(0或1)
p=p(y1∣x1)p(y2∣x2)...p(yn∣xn)=i=1∏npyi(1−p)1−yipi表示每个样本被分类正确时的概率yi表示每个样本真实类别(0或1)
问题转化为:让联合概率时间最大时,估计w,b的权重参数,这就是极大似然估计。
极大似然损失转为对数似然损失,取log优化损失函数。
L
o
s
s
(
L
)
=
∑
i
=
1
m
(
y
i
l
o
g
(
p
i
)
+
(
1
−
y
i
)
l
o
g
(
1
−
p
i
)
)
p
i
=
1
1
−
e
w
T
x
+
b
Loss(L)=\sum_{i=1}^m(y_ilog(p_i) + (1 - y_i)log(1-p_i))\\ p_i=\frac{1}{1-e^{w^Tx+b}}
Loss(L)=i=1∑m(yilog(pi)+(1−yi)log(1−pi))pi=1−ewTx+b1
最大化问题转化为最小问题
L
o
s
s
(
L
)
=
−
∑
i
=
1
m
(
y
i
l
o
g
(
p
i
)
+
(
1
−
y
i
)
l
o
g
(
1
−
p
i
)
)
Loss(L)=-\sum_{i=1}^m(y_ilog(p_i)+(1 -y_i)log(1-p_i))
Loss(L)=−i=1∑m(yilog(pi)+(1−yi)log(1−pi))
再使用梯度下降优化算法,更新逻辑回归算法的权重系数。
3、分类评估
(一)、混淆矩阵
正例 | 假例 | |
---|---|---|
正例 | 真正例TP | 伪反例FN |
假例 | 伪正例FP | 真反例TN |
上侧为预测结果,左侧为真实结果
- 真实值是 正例 的样本中,被分类为 正例 的样本数量有多少,叫做真正例(TP,True Positive)
- 真实值是 正例 的样本中,被分类为 假例 的样本数量有多少,叫做伪反例(FN,False Negative)
- 真实值是 假例 的样本中,被分类为 正例 的样本数量有多少,叫做伪正例(FP,False Positive)
- 真实值是 假例 的样本中,被分类为 假例 的样本数量有多少,叫做真反例(TN,True Negative)
from sklearn.metrics import confusion_matrix
(二)、精确率–precision
查准率,对正例样本的预测准确率。
计算方式:
P
=
T
P
T
P
+
F
P
P = \frac{TP}{TP+FP}
P=TP+FPTP
也就是预测结果中确实为正例的比例。
精确率是指预测为正例中实际为正例的比例
from sklearn.metrics import precision_score
(三)、召回率–Recall
查全率,预测真正例样本占所有真实正例样本的比例。
计算方式:
P
=
T
P
T
P
+
F
N
P=\frac{TP}{TP+FN}
P=TP+FNTP
也就是预测结果中能对实际正例判断正确的比例。
召回率是指实际为正例中被预测为正例的比例
from sklearn.metrics import recall_score
(四)、F1-score
对模型的精度、召回率都有要求,计算模型在这两个评估方向的综合预测能力
p
=
2
∗
p
r
e
c
i
s
i
o
n
∗
r
e
c
a
l
l
p
r
e
c
i
s
i
o
n
+
r
e
c
a
l
l
p = \frac{2*precision*recall}{precision+recall}
p=precision+recall2∗precision∗recall
F1 值是精确率和召回率的调和平均数
from sklearn.metrics import f1_score
(五)、ROC曲线
在ROC曲线中,我们需要考虑正负样本的情况:
- 正样本中被预测为正样本的概率,即:TPR (True Positive Rate)
- 负样本中被预测为正样本的概率,即:FPR (False Positive Rate)
是一种常用于评估分类模型性能的可视化工具。ROC曲线以模型的真正率TPR为纵轴,假正率FPR为横轴,它将模型在不同阈值下的表现以曲线的形式展现出来。
ROC 曲线图像中,4 个特殊点的含义:
- (0, 0) 表示所有的正样本都预测为错误,所有的负样本都预测正确
- (1, 0) 表示所有的正样本都预测错误,所有的负样本都预测错误
- (1, 1) 表示所有的正样本都预测正确,所有的负样本都预测错误
- (0, 1) 表示所有的正样本都预测正确,所有的负样本都预测正确
从图像上看,曲线越靠近 (0,1) 点则模型对正负样本的辨别能力就越强
(六)、AUC指标
AUC 是 ROC 曲线下面的面积,该值越大,则模型的辨别能力就越强,AUC 范围在 [0, 1] 之间
当AUC=0.5时,表示分类器的性能等同于随机猜测
当AUC=1时,表示分类器的性能完美,能够完全正确地将正负例分类
(七)、例子
# 导包
import pandas as pd
from sklearn.metrics import confusion_matrix, precision_score, recall_score, f1_score
# 1. 准备 样本集(10条), 6个 => 恶性肿瘤, 4个 => 良性肿瘤. 即: 训练集的标签.
y_train = ['恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '良性', '良性', '良性', '良性']
# 2. 准备标签.
label = ['恶性', '良性']
dataframe_label = ['恶性(正例)', '良性(假例)']
# 3. 准备预测值, 即: 模型A => 预测对了3个恶性肿瘤, 预测对了4个良性肿瘤.
y_predict_A = ['恶性', '恶性', '恶性', '良性', '良性', '良性', '良性', '良性', '良性', '良性']
# 4. 准备预测值, 即: 模型B => 预测对了6个恶性肿瘤, 预测对了1个良性肿瘤.
y_predict_B = ['恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '恶性', '良性']
# 5. 基于模型A, 构建: 混淆矩阵(confusion_matrix)
# 参1: 真实值, 参2: 预测值, 参3: 模型标签
confusion_matrix_A = confusion_matrix(y_train, y_predict_A, labels=label)
print(f'混淆矩阵A: \n {confusion_matrix_A}')
# 6. 把上述的混淆矩阵, 转成 DataFrame即可.
df_A = pd.DataFrame(confusion_matrix_A, index=dataframe_label, columns=dataframe_label)
print(f'DataFrame对象A: \n {df_A}')
# 7. 基于模型B, 构建: 混淆矩阵(confusion_matrix), 然后转成DF对象.
confusion_matrix_B = confusion_matrix(y_train, y_predict_B, labels=label)
print(f'混淆矩阵B: \n {confusion_matrix_B}')
# 把上述的混淆矩阵, 转成 DataFrame即可.
df_B = pd.DataFrame(confusion_matrix_B, index=dataframe_label, columns=dataframe_label)
print(f'DataFrame对象B: \n {df_B}')
# 8. 分别计算 模型A 和 模型B的 精确率
# 参1: 真实值, 参2: 预测值, 参3: 正例标签
print(f'模型A的精确率: {precision_score(y_train, y_predict_A, pos_label="恶性")}') # 1.0
print(f'模型B的精确率: {precision_score(y_train, y_predict_B, pos_label="恶性")}') # 0.6666666666666666
# 9. 分别计算 模型A 和 模型B的 召回率
print(f'模型A的召回率(查全率): {recall_score(y_train, y_predict_A, pos_label="恶性")}') # 1.0
print(f'模型B的召回率(查全率): {recall_score(y_train, y_predict_B, pos_label="恶性")}') # 0.6666666666666666
# 10. 分别计算 模型A 和 模型B的 F1值.
print(f'模型A的F1-Score(F1值): {f1_score(y_train, y_predict_A, pos_label="恶性")}') # 0.6666666666666666
print(f'模型B的F1-Score(F1值): {f1_score(y_train, y_predict_B, pos_label="恶性")}') # 0.8