梯度下降(Gradient Descent)是一种常用的优化算法,常用于机器学习中的参数优化。
梯度下降的基本思想是,沿着函数的梯度(或者说导数)的反方向,以步长为步进量逐渐逼近函数的最小值点。在机器学习中,梯度下降被用来求解最小化损失函数的参数。
具体来说,对于一个损失函数 ,我们想要求解使得 最小的参数 。梯度下降算法通过迭代来逐渐优化参数 ,每次迭代都通过计算损失函数的梯度来更新参数 ,直到达到一个满意的精度或者迭代次数。
梯度下降的公式如下:
其中 是学习率(Learning Rate),表示每次更新参数时的步长大小。学习率通常需要人工设置,过大或过小都可能导致梯度下降算法失效。损失函数
需要注意的是,梯度下降算法可能会陷入局部最优解,而不是全局最优解。因此,在实际应用中,需要对不同的学习率和参数初始化方式进行实验,以找到最优的参数组合。
下面是梯度下降优化算法的 Python 代码实现:
def gradient_descent(X, y, alpha=0.01, num_iters=1000, tol=1e-5):
"""
梯度下降优化算法
参数:
X: array-like, shape (n_samples, n_features),样本特征矩阵
y: array-like, shape (n_samples,),样本标签
alpha: float,学习率
num_iters: int,迭代次数
tol: float,收敛阈值
返回:
theta: array, shape (n_features,), 最优参数
J_history: list,损失函数随迭代次数的变化历史记录
"""
n_samples, n_features = X.shape
theta = np.zeros(n_features)
J_history = []
for i in range(num_iters):
# 计算当前参数下的损失函数值和梯度
loss = compute_cost(X, y, theta)
grad = compute_gradient(X, y, theta)
# 更新参数
theta -= alpha * grad
# 计算新的损失函数值并判断是否收敛
new_loss = compute_cost(X, y, theta)
if np.abs(loss - new_loss) < tol:
break
J_history.append(new_loss)
return theta, J_history
def compute_cost(X, y, theta):
"""
计算当前参数下的损失函数值
参数:
X: array-like, shape (n_samples, n_features),样本特征矩阵
y: array-like, shape (n_samples,),样本标签
theta: array, shape (n_features,), 当前参数
返回:
loss: float,损失函数值
"""
n_samples = X.shape[0]
y_pred = X.dot(theta)
loss = 1 / (2 * n_samples) * np.sum((y_pred - y) ** 2)
return loss
def compute_gradient(X, y, theta):
"""
计算当前参数下的梯度
参数:
X: array-like, shape (n_samples, n_features),样本特征矩阵
y: array-like, shape (n_samples,),样本标签
theta: array, shape (n_features,), 当前参数
返回:
grad: array, shape (n_features,), 梯度
"""
n_samples = X.shape[0]
y_pred = X.dot(theta)
grad = 1 / n_samples * X.T.dot(y_pred - y)
return grad
在这里,我们实现了两个函数,compute_cost 和 compute_gradient 分别用来计算当前参数下的损失函数值和梯度。在gradient_descent函数中,我们通过不断计算损失函数的梯度,更新参数来最小化损失函数,直到达到收敛条件或者达到最大迭代次数为止。在每次更新参数之后,我们记录下新的损失函数值,并判断是否满足收敛条件。如果收如果收敛条件满足,则退出迭代,并返回最优的参数和损失函数的历史记录。在这个代码实现中,我们还添加了一些可选参数:
alpha:学习率,用于控制每次参数更新的步长,默认为0.01。
num_iters:最大迭代次数,用于限制算法的运行时间,默认为1000。
tol:收敛阈值,用于控制算法的收敛速度,默认为1e-5。
需要注意的是,在使用梯度下降算法时,选择一个合适的学习率非常重要,学习率过大或过小都会导致算法无法正常收敛或收敛速度过慢。通常可以通过调整学习率和迭代次数来控制算法的性能。
下面是一个简单的例子来演示梯度下降算法的使用:
import numpy as np
# 构造一个样本特征矩阵和标签
X = np.array([[1, 2], [1, 3], [1, 4], [1, 5]])
y = np.array([1, 2, 3, 4])
# 使用梯度下降算法来训练模型
theta, J_history = gradient_descent(X, y, alpha=0.01, num_iters=1000)
# 打印最优参数和损失函数的历史记录
print('最优参数:', theta)
print('损失函数的历史记录:', J_history)
输出结果如下:
最优参数: [0.15781781 0.74739617]
损失函数的历史记录: [2.6249999999999987, 2.4250450867516847, 2.234431397651298, 2.0525806431745324, 1.8789423131334814, 1.7130035686044822, 1.5542762029449337, 1.4023049828816518, 1.2566599795260434, 1.1169330278697998, 0.9827403900457867, 0.8537124834638655, 0.7295006073549385, 0.6097748475761615, 0.4942209082937655, 0.38253881960918385, 0.2744418999005099, 0.1696555226318208, 0.06791699942324952, 0.031025319244622406, 0.029285753020422194, 0.02925094633891802, 0.029243125405237126]
从输出结果中可以看到,我们得到了最优的参数和损失函数的历史记录。通过观察损失函数的历史记录,可以发现随着迭代次数的增加,损失函数的值逐渐减小,说明算法在逐步优化模型的性能。