机器学习入门(一)

一、机器学习概述

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,他试图通过采取(即行走)来操纵环境(地面),

  • 并且从一个状态转变到另一个状态(即他走的每一步),

  • 当他完成任务的子任务(即走了几步)时,孩子得到奖励(给巧克力吃),

  • 并且当他不能走路时,就不会给巧克力。

(五)、总结

Inout目的案例
监督学习有标签有反馈预测结果猫狗分类 房价预测
无监督学习无标签无反馈发现潜在结构物以类聚 人与群分
半监督学习部分有标签,部分无标签有反馈降低数据标记的难度
强化学习决策流程及激励系统一系列行动长期利益最大化围棋

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=(x1x2)2+(y1y2)2 d12=(x1x2)2+(y1y2)2+(z1z2)2 d12=i=1N(x1kx2k)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=x1x2+y1y2d12=i=1Nx1kx2k

(三)、切比雪夫距离

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(x1x2,y1y2)d12=max(x1ix2i)

(四)、闵式距离

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=1Nx1kx2kp

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=maxminxminX‘‘=X(mxmi)+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=σxmean

  • 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=0m(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=0m(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=0mfw,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=1Nwjxj+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=1m(fw,b(x(i))y(i))x(i)b=bαm1i=1m(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=1m(fw ,b(x (i))y(i))x1(i)wn=wnαm1i=1m(fw ,b(x (i))y(i))xn(i)b=bαm1i=1m(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=1m(fw,b(x(i))y(i))2=i=1m(wx(i)+by(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 wJ(w,b)=i=1m(2w(x(i))2+2bx(i)2x(i)y(i)=0bJ(w,b)=i=1m(2w(x(i))2+2b2y(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=1m(wixi+byi)2将上述公式转为矩阵形式:i=1m(f(xi)yi)2=∣∣Xwy22数据集为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(X wy)X =02(X wy)(X X T)=0X T2(X wy)(X X T)(X X T)1=0X T(X X T)12(X wy)=0X w=yX TX w=X Ty(X TX )1(X TX )w=(X TX )1X Tyw=(X TX )1X Ty
得出正规方程的解析解答案

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αwJ(w,b)b=bαbJ(w,b)α:学习率(步长)不能太大,也不能太小.机器学习中:0.0010.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=0m(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=tt+x1(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=winαj=0n(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=1n(yiyi^)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=1nyiyi^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=1n(yiyi^)2 n为样本数量、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=1nwiα叫做惩罚系数

惩罚系数越大则权重调整的幅度就越大,即:表示对特征权重惩罚力度就越大

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=1nwi2α叫做惩罚系数

惩罚系数越大则权重调整的幅度就越大,即:表示对特征权重惩罚力度就越大

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=1m(yilog(pi)+(1yi)log(1pi))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=11p    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(y1x1)p(y2x2)...p(ynxn)=i=1npyi(1p)1yipi表示每个样本被分类正确时的概率yi表示每个样本真实类别(01)
问题转化为:让联合概率时间最大时,估计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=1m(yilog(pi)+(1yi)log(1pi))pi=1ewTx+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=1m(yilog(pi)+(1yi)log(1pi))
再使用梯度下降优化算法,更新逻辑回归算法的权重系数。

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+recall2precisionrecall
F1 值是精确率和召回率的调和平均数

from sklearn.metrics import f1_score

(五)、ROC曲线

在ROC曲线中,我们需要考虑正负样本的情况:

  • 正样本中被预测为正样本的概率,即:TPR (True Positive Rate)
  • 负样本中被预测为正样本的概率,即:FPR (False Positive Rate)

是一种常用于评估分类模型性能的可视化工具。ROC曲线以模型的真正率TPR为纵轴,假正率FPR为横轴,它将模型在不同阈值下的表现以曲线的形式展现出来。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

ROC 曲线图像中,4 个特殊点的含义:

  1. (0, 0) 表示所有的正样本都预测为错误,所有的负样本都预测正确
  2. (1, 0) 表示所有的正样本都预测错误,所有的负样本都预测错误
  3. (1, 1) 表示所有的正样本都预测正确,所有的负样本都预测错误
  4. (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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值