算法概述
回归 : 对数据进行拟合
当曲线是一条直线,就是线性回归
在训练学习样本时,不仅需要提供特征向量X,还需要提供样本的实际结果(标记label),因此线性回归模型属于监督学习里的回归模型。

一元线性回归
一个自变量,一个因变量
回归分析用来建立方程模拟两个或者多个变量之间如何关联 因变量:被预测的变量 自变量:被用来进行预测的变量

基于均方误差最小化来进行模型求解的方法称为“最小二乘法”
在线性回归中,最小二乘法就是试图找到一条直线,使所有样本到直线上的欧氏距离之和最小。

偏导取0后可得:

实验实现
1. 使用最小二乘法进行房价预测:
给定训练样本集合如下:

import numpy as npfrom sklearn.linear_model import LinearRegression
x_train = np.array([[10],[15],[20],[30],[50],[60],[60],[70]])y_train = np.array([0.8, 1, 1.8, 2, 3.2, 3, 3.1, 3.5])
model = LinearRegression()model.fit(x_train, y_train)predict = model.predict([[55]])print(f"输入 55 时的预测结果为: {predict[0]:.4f}")多元线性回归

实验实现
求解:当工资18000、年龄30时,额度是多少?

import numpy as npfrom sklearn.linear_model import LinearRegression
x_train = np.array([[4000,25],[8000,30],[5000,28],[7500,33],[12000,40]])y_train = np.array([20000,70000,35000,50000,85000])
model = LinearRegression()model.fit(x_train, y_train)predict = model.predict([[18000,30]])print(f"当工资18000、年龄30时的预测结果为: {predict[0]:.4f}")最小二乘法的局限性
首先,最小二乘法需要计算的逆矩阵,有可能它的逆矩阵不存在,这样就没有办法使用最小二乘法了 ;
第二,当样本特征非常多的时候,计算的逆矩阵是一个非常耗时的工作,甚至不可行 ;
第三,如果拟合函数不是线性的,这时无法使用最小二乘法,需要通过一些技巧转化为线性才能使用。
算法流程

梯度下降法
想象一下,你被蒙住双眼,随机降落在了一座高山上的某个位置。你的目标是走到这座山的最低谷。因为眼睛看不见,你只能用脚去感受地面的倾斜程度。你会怎么做?
- 感受坡度(计算梯度): 你用脚试探周围,找到往下最陡峭的方向。
- 迈出一步(更新参数): 顺着这个最陡的下坡方向,你往前迈出一步
- 不断重复(迭代): 在新的位置上,你再次感受坡度,再朝着最陡的方向迈步。
- 到达谷底(收敛): 当你发现四周都没有下坡路,或者坡度平缓到几乎感觉不到时,你就可以认为自己已经到达了谷底。
在数学上,梯度(Gradient) 指的是一个函数在某一点上变化最快的方向。因为我们想要找到最小值,所以我们需要沿着梯度的相反方向(即负梯度方向)前进。
梯度下降法的核心更新公式非常简单:
公式里的符号代表:
- :我们要优化的模型参数(也就是你在山上的坐标)。
- :学习率(Learning Rate)。它控制了你每次下山迈出的“步伐大小”。
- :损失函数。
- :损失函数在当前参数下的梯度(也就是当前的坡度)。
代码分析
import numpy as npimport matplotlib.pyplot as plt
# 1 获得x,y数据 ###########iter = 50X = np.random.rand(iter) * 20noise = np.random.randn(iter)y = 0.5 * X + noiseplt.scatter(X, y)plt.show()
# 2 初始化参数 ##########w = np.random.randn(1)b = np.zeros(1)lr = 0.001
for iteration in range(40):
# 初始化拟合 y_pred = w * X + b
# 梯度更新 w_gradient = 0 b_gradient = 0 N = len(X) for i in range(N): w_gradient += (w * X[i] + b - y[i]) * X[i] b_gradient += (w * X[i] + b - y[i])
w -= lr * w_gradient / N b -= lr * b_gradient / N
# 更新后拟合 y_pred = w * X + b
# 显示 plt.scatter(X, y, c="blue") plt.plot(X, y_pred, c="red") plt.pause(0.2)制造地形与目标点(准备数据)
iter = 50 X = np.random.rand(iter)*20 noise = np.random.randn(iter) y = 0.5 * X + noise-
核心思路: 这一步相当于我们在现实中收集数据。代码生成了50个点,这些点大致服从一条直线方程:。
-
为了模拟真实世界的不完美,代码特意加上了
noise(随机噪声)。我们的最终目标,就是让算法在不知道真实斜率是 的情况下,自己通过梯度下降法把这个 给“摸索”出来。
随机空降,准备下山(初始化参数)
w = np.random.randn(1) b = np.zeros(1) lr = 0.001-
核心思路: 这里的 (斜率/权重)和 (截距/偏置)就是我们的模型参数,也就是“我们在山上的坐标”。
-
算法一开始什么都不知道,所以我们给 随便塞一个随机数,给 塞个 。此时画出来的红线(预测线)通常会偏得离谱。
-
lr = 0.001就是我们之前提到的学习率(步伐大小)。
核心大循环:感受坡度,不断迈步(梯度下降迭代)
这部分是算法的灵魂。for iteration in range(40): 代表我们要走 40 步。每一步都包含了以下关键动作:
动作 A:评估现状(计算误差)
w_gradient = 0 b_gradient = 0 N = len(X) for i in range(N): w_gradient += (w * X[i] + b - y[i]) * X[i] b_gradient += (w * X[i] + b - y[i])-
这段代码其实在算梯度(坡度)。它的背后是均方误差(MSE)的求导公式。
-
注意看括号里的这部分:
(w * X[i] + b - y[i])。这其实就是 预测值 - 真实值,我们叫它误差。- 如果预测值比真实值大(红线在蓝点上方),误差是正的。
- 如果预测值比真实值小(红线在蓝点下方),误差是负的。
-
对于 的梯度: 直接把所有点的误差累加起来。
-
对于 的梯度: 把误差乘上了对应的 再累加。这就是在计算损失函数对 的偏导数:
动作 B:向下迈步(更新参数)
w -= lr * w_gradient / N b -= lr * b_gradient / N-
这里完美体现了梯度下降的公式:新位置 = 老位置 - 学习率 × 梯度。
-
注意它除了
N,因为上面的for循环是累加求和,除以N就变成了平均梯度。这确保了无论你有 50 个数据还是 5000 个数据,梯度的量级是稳定的,也就是我们之前提到的 批量梯度下降(BGD)。
实时录像(可视化更新过程)
# 更新后拟合 y_pred = w * X + b # 显示 plt.scatter(X, y, c="blue") plt.plot(X, y_pred, c="red") plt.pause(0.2)- 经过一次更新, 和 变得更准确了一点。代码用新的参数重新画了一条红线。
plt.pause(0.2)让画面暂停 0.2 秒。在 40 次循环中,你会亲眼看到一条一开始乱跑的红线,一步一步地向蓝点群的中心靠拢,最终完美穿过它们。
梯度下降法求极值的主要问题
- 梯度下降中的超参数设置
上面的梯度下降中提到了一个参数 ɑ,它又称为步长。这种算法是需要人为设置的,而非用来学习的参数,所以叫做超参数。步长是梯度下降算法中最重要的超参数,设置时需要精心考虑。

- 梯度下降的问题
如果目标函数有多个极小值点(很多个低谷),那么如果开始位置不理想,很可能导致最终卡在一个局部极小值。比如下图的例子。这是梯度下降算法的一大挑战。

梯度下降的方式

逻辑回归
用线性模型做“分类”
二分类任务
思路:找线性回归结果z和期望输出结果y的关系

理想的函数应该是:
例如,当我们预测出来的结果大于50岁的时候,我们应该输出年老,小于50岁的时候应该输出年轻,但是这个函数是分段函数性质不好.
引入Logistic函数:

这里要区分两个概念: Logistic函数: Logit函数:
基本思路就是:先回归,在经过Logistic函数转为分类问题
逻辑回归的语法
导入包含分类方法的类:
from sklearn.linear_model import LogisticRegression
创建该类的一个实例:
LR = LogisticRegression(penalty = 'l2', C = 10.0)
拟合训练数据并预测:
LR = LR.fit(X_train, y_train)
y_predict = LR.predict(X_test)
评价指标
混淆矩阵

混淆矩阵包含四部分的信息:
1) 真阴性(TN)表明实际是负样本预测成负样本的样本数。 2) 假阳性(FP)表明实际是负样本预测成正样本的样本数。 3) 假阴性(FN)表明实际是正样本预测成负样本的样本数。 4) 真阳性(TP)表明实际是正样本预测成正样本的样本数。
准确率
虽然准确率可以判断总体正确率,但在样本不平衡的情况下,并不能作为很好的指标来衡量结果。假设在所有样本中,正样本占90%,负样本占10%,样本严重不平衡。模型将全部样本预测为正样本即可得到90%的高准确率,如果仅使用准确率这一单一指标,模型就可以像这样偷懒获得很高的评分。因此,衍生出了其它两种指标:精确率和召回率。
精确率与召回率

精确率何时重要 在某些问题域中,精度比查全率更为重要。比如,当你在一家网店买东西时,他们的推荐系统经常会回馈像“买了X的顾客同时也买了Y”这样的信息。该信息的意图明显是想诱导你也购买Y。
推荐系统通过机器学习技术对公司历史数据进行分析完成。在评估其性能时,工程师希望得到较高的精度。这样,顾客也许会对推荐机制感到更加满意,否则很可能忽略推荐内容。
在这些问题域中,查全率的价值是不重要的。网店推荐清单的规模只能是有限的,因此即使系统只能辨认出一小部分顾客喜欢的产品也没太大关系。
高查全率何时重要 查全率同精度恰恰相反,在其它问题域中,查全率更为重要。这种情况在医药诊断中比较常见。例如:一个患X疾病的病人被确诊患X疾病,即真正类。患X疾病的病人没被诊断出患X疾病,即假负类。这是医生想要避免的一种情况——这意味着应该要小。在查全率的定义中, 假负类的数量在分母上,因此小的意味着高的查全率。
PR曲线
分类模型对每个样本点都会输出一个置信度。通过设定置信度阈值,就可以完成分类。不同的置信度阈值对应着不同的精确率和召回率。一般来说,置信度阈值较低时,大量样本被预测为正例,所以召回率较高,而精确率较低;置信度阈值较高时,大量样本被预测为负例,所以召回率较低,而精确率较高。
PR曲线就是以查准率为纵坐标,以查全率为横坐标做出的曲线,如图

ROC曲线与AUC曲线
对于某个二分类分类器来说,输出结果标签(0还是1)往往取决于置信度以及预定的置信度阈值。比如常见的阈值就是0.5,大于0.5的认为是正样本,小于0.5的认为是负样本。如果增大这个阈值,预测错误(针对正样本而言,即指预测是正样本但是预测错误,下同)的概率就会降低,但是随之而来的就是预测正确的概率也降低;如果减小这个阈值,那么预测正确的概率会升高但是同时预测错误的概率也会升高。实际上,阈值的选取一定程度上反映了分类器的分类能力。我们当然希望无论选取多大的阈值,分类都能尽可能地正确。为了形象地衡量这种分类能力,ROC曲线进行了表征。
假阳率(FPR):
真阳率(TPR):

现在分析几个ROC曲线的特殊情况,更好地掌握其性质
(0, 0):假阳率和真阳率都为0,即分类器全部预测成负样本。 (0, 1):假阳率为0,真阳率为1,全部完美预测正确。 (1, 0):假阳率为1,真阳率为0,全部完美预测错误。 (1, 1):假阳率和真阳率都为1,即分类器全部预测成正样本
当TPR=FPR为一条斜对角线时,表示预测为正样本的结果一半对,一半错,即为随机分类器的预测效果。ROC曲线在斜对角线以下,表示该分类器效果差于随机分类器;反之,效果好于随机分类器。当然,我们希望ROC曲线尽量位于斜对角线以上,也就是向左上角(0, 1)凸。
c1和c2哪条曲线更好?

答案只能基于实际应用中的特定需求来回答。根据图像可以得出以下结论:就正类而言,在负类错误率低的区域,c1的表现优于c2。随着负类样例错误率的增加,c2在正类样例上的表现优于c1。再者,分类器表现的好坏取决于用户的标准。
scikit-learn库函数
accuracy_score:用于评价分类问题的准确率。其函数原型为:
sklearn.metrics.accuracy_score(y_true, y_pred, normalize=True, sample_weight=None)
precision_score:用于评价分类问题的查准率,其值为TP/(TP + FP),其中TP是真正的正例数目、FP是假阳性的数量。其函数原型为:
sklearn.metrics.precision_score(y_true, y_pred, labels=None, pos_label=1, average =’binary’, sample_weight=None)

计算分类结果的F_1值的f1_score; 计算分类结果的F_𝛽值的fbeata_score 计算分类结果的P-R曲线的precision_recall_curve 计算分类结果的ROC曲线的roc_curve 评价估计器在不同样本集上学习性能的函数learning_curve等等
