回归算法
函数与导数
初等数学的研究对象基本上是不变的量,而高等数学的研究对象是变化的量。高等数学对学习编程具有重要的意义,因为编程涉及到许多与数学密切相关的概念和技能。
本章节内容主要源自《高等数学(第七版)》,仅对语序、相似内容做调整。学习更多高等数学知识请移步其他平台。
本章提到的符号含义如下:
表集合、定义域或值域
- 表示集合 包含元素
- 表示函数 的值域是所有 的值,其中 是实数。
表逻辑关系,
-
如 表示 推导出 .
-
表示 是从 到 的一个映射。
-
不同场景还可表示:变换、趋向、收敛、极限等。
表“使得”或“满足”,,表示一个实数集合 ,其中包含所有满足 条件的实数 。
表属于,如果 是集合 的元素,记作 .
表子集,如果 A 是集合 B 的子集(A 与 B 可以相等), 记作 .
表真子集, 如果 A 是集合 B 的真子集(A 与 B 不相等), 记作 .
函数
映射的概念
定义:设 和 是两个非空集合,
如果存在一个对应关系 ,使得对于 中的任意一个元素 ,在 中都有唯一确定的元素 和它对应,
那么就称 为从 到 的一个映射,记作 ,
其中, 称为 在映射 下的像,记作 。而 中的元素 称为 的原像。
并称 为的定义域,记作 ;
为的值域,记作 。
构成一个映射的条件是:
- 集合 ,即定义域
- 集合 ,即值域
- 对应法则,对于 中的任意一个元素 ,在 中都有唯一确定的元素 和它对应
注意:
对每个 , 必须是确定唯一与之对应的
对于 , 可以有多个原像。
例如,, 的原像可以是 或 。
值域 是 的子集,即 ,而不一定是
导数
假设有一辆小电动车,装有一根透明的长管。管子的中点代表零,两端分别象征正无穷和负无穷,管内静置着一颗小球。当车辆运动小球也会跟着运动,小球的数值就是导数。
- 平直道路:当车辆在平坦路面上行驶时,小球始终保持在零点位置。(常数的导数)
- 爬坡下坡:上坡时,由于斜度影响,小球逐渐向正无穷移动;下坡时则向负无穷滑动。
- 悬崖处:如果电动车遇到悬崖直接坠落,这代表函数在此处不连续,也就是不可导。
- 起伏道路:当车辆行驶在起伏不断的路面上时,小球的运动轨迹类似波浪。这种变化与三角函数之间的关系异曲同工:例如,sin 的导数变为 cos。
幂函数求导
幂函数求导的通用法则:
- “指数向前”: 将指数 移到变量 的前面作为系数。
- “并减一”: 将原指数 减去1,得到新的指数 。
-
基本形式: 求 的导数。 将指数2移到前面,并将指数2减去1(2-1=1),所以导数是 。
-
常数乘以幂函数: 求 的导数。 常数5保持不变,对 使用法则。将指数3移到前面,与常数5相乘,并将指数3减去1。
-
分式形式: 求 的导数。
首先,将分式转化为指数形式:。
然后使用法则,将指数-4移到前面,并将指数-4减去1()。
线性回归
线性回归是利用连续性变量来估计实际数值(例如房价,呼叫次数和总销售额等)。
我们通过线性回归算法找出自变量和因变量间的最佳线性关系,图形上可以确定一条最佳直线。
这条最佳直线就是回归线。这个回归关系可以用 表示。
多个数据可以用 表示。
损失函数
如何评估数据的离散程度呢?
平均值:数据相加除以数据个数
平均差:数据与平均值的差的绝对值相加除以数据个数
均方误差:数据与平均值的差的平方相加除以数据个数
| 数据1 | 数据2 | 平均值 | 平均差 | 均方误差 |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| -4 | 4 | 0 | 4 | 16 |
| 7 | 1 | 4 | 4 | 25 |
我们预期中,理想效果应该是 0、0 好于 -4、4 好于 7、1。只有均方误差正确的反应了这一点。
在预测出来的 值和目标值之间差的部分,我们称之为损失,均方误差常见的用于评估数据离散程度的损失函数,以下是常见的损失函数及其特点
| 名称 | 数学表达式 | 值域 | 导数表达式 | 优点 | 缺点 |
|---|---|---|---|---|---|
| 交叉熵损失(Cross Entropy) | 最常用,适合 one-hot 标签,梯度清晰,收敛快 | 对异常值敏感,需要防止概率为0的情况 | |||
| 均方误差(MSE) | 简单直观,易于理解 | 不适合分类任务,梯度在误差较大时过大 | |||
| 平均绝对误差(MAE) | 对异常值不敏感,稳定性好 | 在零点不可导,优化困难 |
求导
通过误差的大小,我们可以慢慢修正我们的参数让线性拟合更好, 导数可以反应数据变化的趋势,所以我们可以求导来修改参数。
这个过程也叫:求梯度、反向传播(狭义)
误差我们用的是均方误差:求了每个数据与平均值的差的平方,再加和,再求平均
每个数据的误差我们一般叫损失,写作 ,他的值等于数据集中的目标值,减去我们线性公式算出来的预测值。
即:
这个表达式中,loss 是算出来的,y 是目标值,源自数据集,x 是特征值,源自数据集。
我们调整 w 和 b 的值就可以间接控制 loss 的值变大或变小(这里主要是期望变小)。
我想既更新 w,也更新 b。
所以分 2 次求导,第一次求:
第二次求:。
手写线性回归
import numpy as np
from matplotlib import pyplot as plt
class Line:
def __init__(self, data):
self.w = 1
self.b = 0
self.learning_rate = 0.01
self.fig, (self.ax1, self.ax2) = plt.subplots(2, 1)
self.loss_list = []
def get_data(self, data):
self.X = np.array(data)[:, 0]
self.y = np.array(data)[:, 1]
def predict(self, x):
return self.w * x + self.b
def train(self, epoch_times):
for epoch in range(epoch_times):
total_loss = 0
for x, y in zip(self.X, self.y):
y_pred = self.predict(x)
# Calculate gradients
gradient_w = -2 * x * (y - y_pred)
gradient_b = -2 * (y - y_pred)
# Update weights
self.w -= self.learning_rate * gradient_w
self.b -= self.learning_rate * gradient_b
# Calculate loss
loss = (y - y_pred) ** 2
total_loss += loss
epoch_loss = total_loss / len(self.X)
self.loss_list.append(epoch_loss)
if epoch % 10 == 0:
print(f"loss: {epoch_loss}")
self.plot()
plt.ioff()
plt.show()
def plot(self):
plt.ion() # Enable interactive mode
self.ax2.clear()
self.ax1.clear()
x = np.linspace(0, 10, 100)
self.ax1.scatter(self.X, self.y, c="g")
self.ax1.plot(x, self.predict(x), c="b")
self.ax2.plot(list(range(len(self.loss_list))), self.loss_list)
plt.show()
plt.pause(0.1)
if __name__ == "__main__":
# Input data
data = [(1, 1), (1.8, 2), (2.5, 3), (4.2, 4), (5, 5), (6, 6), (7, 7)]
s = Line(data)
s.get_data(data)
s.train(100)