一、简介
Gradient Descent,又称梯度下降法,是一种用于机器学习的优化算法。通俗地说,就是在参数空间中找到使损失函数最小化的参数值。
梯度下降算法的核心思想是沿着损失函数梯度方向的相反方向搜索最小值点,每次迭代根据当前位置的梯度值和学习率,更新参数的值,以此来不断逼进最优解。
二、原理与应用
梯度信息描述了函数在某个点的变化方向,它是求导数值在多维空间中的推广。梯度下降算法的核心思想是,从当前的参数点出发,每次移动一个步长,采用负梯度方向的方向,每次迭代能够得到一个新的解,并使目标函数值向着更小的方向逼近。
梯度下降算法是一种迭代方法,需要设置学习率,过大或过小都会影响算法的速度和稳定性。学习率过大可能会导致算法不收敛,学习率过小则会导致算法收敛过慢。一般通过交叉验证法和实验比较得出一个合适的学习率。
梯度下降算法广泛应用于神经网络、线性回归、逻辑回归等机器学习和深度学习领域。
三、算法优化
1. 随机梯度下降
梯度下降算法每次迭代需要用到全部样本的数据,运算量随样本数增加而增加,效率较低。随机梯度下降算法将全局搜索转化为随机搜索,每次只使用一个样本来更新参数,通过随机选取样本的方式避免了样本的依赖性,可以加速模型的训练。
随机梯度下降算法虽然收敛速度比梯度下降算法要快,但由于只使用一个样本而不是全部样本,可能会造成噪声的影响,导致结果不稳定。
2. 批量梯度下降
批量梯度下降算法是指每次使用一个固定大小的批量样本来更新参数,这个批量的大小称为batch size。批量梯度下降算法可以在保证更新的稳定性前提下,加速模型的训练。
批量梯度下降算法相比随机梯度下降算法,虽然迭代过程中需要运算的样本数目变多,但由于多个样本堆叠起来形成的样本都是随机的,样本的偏差因此降低,对于非凸函数求解尤为重要。
四、代码示例
1. 梯度下降
import numpy as np def gradient_descent(x, y, alpha, num_iters): m = len(y) theta = np.zeros((2,1)) J_history = np.zeros((num_iters,1)) for i in range(num_iters): h = np.dot(x, theta) loss = h - y gradient = np.dot(x.transpose(),loss)/m theta = theta - alpha * gradient J_history[i] = compute_cost(x, y, theta) return theta,J_history def compute_cost(X, y, theta): m = len(y) J = 0 J = np.sum((np.dot(X,theta)-y)**2)/(2*m) return J X = np.array([[1,1],[1,2],[1,3]]) y = np.array([[1],[2],[3]]) theta, J_history = gradient_descent(X, y, 0.1, 1000)
2. 随机梯度下降
import numpy as np def gradient_descent(x, y, alpha, num_iters): m = len(y) theta = np.zeros((2,1)) J_history = np.zeros((num_iters,1)) for i in range(num_iters): index = np.random.randint(m) h = np.dot(x[index,:], theta) loss = h - y[index,:] gradient = x[index,:].transpose() * loss theta = theta - alpha * gradient J_history[i] = compute_cost(x, y, theta) return theta, J_history def compute_cost(X, y, theta): m = len(y) J = 0 J = np.sum((np.dot(X,theta)-y)**2)/(2*m) return J X = np.array([[1,1],[1,2],[1,3]]) y = np.array([[1],[2],[3]]) theta, J_history = gradient_descent(X, y, 0.1, 1000)
3. 批量梯度下降
import numpy as np def gradient_descent(x, y, alpha, num_iters,batch_size): m = len(y) theta = np.zeros((2,1)) J_history = np.zeros((num_iters,1)) for i in range(num_iters): index = np.random.choice(m,batch_size,replace=False) h = np.dot(x[index,:], theta) loss = h - y[index,:] gradient = np.dot(x[index,:].transpose(), loss)/batch_size theta = theta - alpha * gradient J_history[i] = compute_cost(x, y, theta) return theta,J_history def compute_cost(X, y, theta): m = len(y) J = 0 J = np.sum((np.dot(X,theta)-y)**2)/(2*m) return J X = np.array([[1,1],[1,2],[1,3]]) y = np.array([[1],[2],[3]]) theta, J_history = gradient_descent(X, y, 0.1, 1000,2)