什么是梯度下降法
梯度下降法不是一种机器学习算法,而是一种基于搜索的最优化方法。
梯度下降法的作用在于最小化损失函数(目标函数)
与梯度下降法相对的是梯度上升法,梯度上升法在于最大化一个效用函数(目标函数)
使用梯度下降法之前,最好对数据进行归一化(正规化)处理。
图解
成为学习率(learning rate)
的取值影响获得最优解的速度;太小,收敛速度慢,太大收敛速度快,甚至无最优解。
取值不合理,甚至不能得到最优解
是梯度下降法的超参数
简单梯度下降法实现
一元二次方程梯度实现求极值。
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-1,6,141)
y = (x-2.5)**2 -1
plt.plot(x,y )
代码实现:
def dJ(theta):
'''定义求导函数'''
return 2*(theta-2.5)
def J(theta):
'''定义损失函数'''
return (theta-2.5)**2 -1
# 实现梯度下降搜索算法
eta = 0.1
epsilon = 1e-8
theta = 0.0
while True:
grd = dJ(theta)
last_theta = theta
theta = theta - eta * grd
if abs(J(theta) - J(last_theta)) < epsilon:
break
print(theta)
print(J(theta))
print(dJ(theta))
问题:可能得到局部最优解,而非全局最优解
解决办法:多次运行随机化初始点,初始点也是一个超参数。
实现线性回归的梯度下降法
目标函数尽可能小:
一般采用均值作为目标函数:
其中:
损失(目标)函数对 求梯度:
梯度表达式向量化:
代码实现
def fit_gd(self, X_train, y_train, eta=0.01, n_iters=1e4):
def J(theta, X_b, y):
try:
return np.sum((y - X_b.dot(theta)) ** 2) / len(y)
except:
return float('inf')
def dJ(theta, X_b, y):
return X_b.T.dot(X_b.dot(theta) - y) * 2. / len(X_b)
def gradient_descent(X_b, y, initial_theta, eta, n_iters=1e4, epsilon=1e-8):
theta = initial_theta
cur_iter = 0
while cur_iter < n_iters:
gradient = dJ(theta, X_b, y)
last_theta = theta
theta = theta - eta * gradient
if (abs(J(theta, X_b, y) - J(last_theta, X_b, y)) < epsilon):
break
cur_iter += 1
return theta
X_b = np.hstack([np.ones((len(X_train), 1)), X_train])
initial_theta = np.zeros(X_b.shape[1])
theta = gradient_descent(X_b, y_train, initial_theta, eta, n_iters)
return theta
后续还可以对 添加L1或L2正则化项,实现对 的惩罚。
学习笔记参考:
《机器学习实战》和《Python3入门机器学习 经典算法与应用》