1.成本函数可视化的思考
回顾一下上篇文章关于线性回归的介绍。我们了解了成本函数的概念,以及训练模型的最终目的是匹配到成本函数最小的情况 - 即三维坐标中的“碗底”
对应二维平面,则是等高线图的最小椭圆中心。
然而,生活中的实际情况,我们得到的成本函数的图形化会更为复杂。会出现多个“碗底”。
我们需要初始确认一点,并且从这点开始,找到一条路径,最终走到我们的“碗底”。而这个过程,就需要一套算法来指导。我们称之为梯度下降算法(Gradient Descent)。
2.梯度下降算法
梯度下降算法是一种优化算法,用于最小化一个函数的值,通常用于机器学习和深度学习中的参数优化。其核心思想是通过迭代的方式不断地沿着函数梯度的反方向更新参数,直至达到函数的最小值或收敛。
以下是梯度下降算法的基本步骤:
-
初始化参数:首先需要初始化模型的参数,可以随机选择或者使用一些启发式方法进行初始化。
-
计算梯度:在每次迭代中,计算目标函数对于当前参数的梯度。梯度指示了函数在当前点的变化率和方向,梯度的反方向是函数值下降最快的方向。
-
更新参数:根据梯度的反方向更新参数。通常使用学习率(learning rate)来控制每次更新的步长,防止参数更新过大导致错过最优解或者无法收敛。
-
重复迭代:重复步骤2和步骤3,直到满足停止条件。停止条件可以是达到最大迭代次数、参数变化小于某个阈值或者函数值变化小于某个阈值等。
我们的目标是最小化成本函数 J(w,b)。(这里除2是为了后续计算方便,无伤大雅)
J ( w , b ) = 1 2 m ∑ i = 0 m − 1 ( f w , b ( x ( i ) ) − y ( i ) ) 2 J(w,b) = \frac{1}{2m} \sum\limits_{i = 0}^{m-1} (f_{w,b}(x^{(i)}) - y^{(i)})^2 J(w,b)=2m1i=0∑m−1(fw,b(x(i))−y(i))2
为了使用梯度下降算法来更新参数 w 和 b,需要计算成本函数对于参数的偏导数(梯度)。这里的 α \alpha α我们称之为学习率,用于控制每次参数更新的步长大小。
w = w − α ∂ J ∂ w w = w - \alpha \frac{\partial J}{\partial w} w=w−α∂w∂J
b = b − α ∂ J ∂ b b = b - \alpha \frac{\partial J}{\partial b} b=b−α∂b∂J
∂ J ( w , b ) ∂ w = 1 m ∑ i = 0 m − 1 ( f w , b ( x ( i ) ) − y ( i ) ) x ( i ) ∂ J ( w , b ) ∂ b = 1 m ∑ i = 0 m − 1 ( f w , b ( x ( i ) ) − y ( i ) ) \begin{align} \frac{\partial J(w,b)}{\partial w} &= \frac{1}{m} \sum\limits_{i = 0}^{m-1} (f_{w,b}(x^{(i)}) - y^{(i)})x^{(i)} \tag{1}\\ \frac{\partial J(w,b)}{\partial b} &= \frac{1}{m} \sum\limits_{i = 0}^{m-1} (f_{w,b}(x^{(i)}) - y^{(i)}) \tag{2}\\ \end{align} ∂w∂J(w,b)∂b∂J(w,b)=m1i=0∑m−1(fw,b(x(i))−y(i))x(i)=m1i=0∑m−1(fw,b(x(i))−y(i))(1)(2)
3.多类特征和向量化
之前例子中房屋的价格只和面积相关,当我们引入其他影响因素时,比如房子的数量,房子的层数,地段等等,房屋的价格函数会变得复杂。这些不同的影响因素我们称之为多类特征(Mutiple features)。
比如:
然后我们可以通过线性代数的思想将其向量化
向量化操作可以交给Numpy。NumPy 的向量化操作是利用 NumPy 数组的优势,以一种高效的方式处理数组,避免了使用显式循环。这种方式通常比使用显式循环更快速,因为它是在底层 C 语言中执行的,而且能够充分利用现代计算机的并行性。
向量化操作的主要优势包括:
代码简洁性:向量化操作使得代码更加简洁和易读,不需要编写显式的循环。
性能优化:NumPy 底层的实现能够充分利用现代计算机的并行性和优化,从而提高计算效率。
广播:NumPy 支持广播(broadcasting),允许对不同形状的数组进行操作,而无需显式地扩展数组。
更高级的抽象操作:向量化操作使得可以使用更高级的操作,例如矩阵乘法、逻辑运算、统计计算等。
以下是一个简单的示例,演示了使用向量化操作和使用显式循环的比较:
import numpy as np
# 使用显式循环计算两个数组的元素级乘积
def elementwise_multiply(a, b):
result = np.empty_like(a)
for i in range(len(a)):
result[i] = a[i] * b[i]
return result
# 使用向量化操作计算两个数组的元素级乘积
def vectorized_multiply(a, b):
return a * b
# 创建两个数组
a = np.array([1, 2, 3, 4])
b = np.array([5, 6, 7, 8])
# 使用显式循环进行计算
result_loop = elementwise_multiply(a, b)
# 使用向量化操作进行计算
result_vectorized = vectorized_multiply(a, b)
print("显式循环计算结果:", result_loop)
print("向量化操作计算结果:", result_vectorized)
4.多元线性回归的梯度下降算法
回顾一下房屋价格只和面积有关的线性回归
当有多个特征时, 就演变成: