模型优化学习笔记—Adam算法
首先复习一下:
- 动量梯度下降:
1、算出dw、db
2、计算指数加权(移动)平均
vdw = k *vdw + (1-k)*dw
vdb = k *vdb + (1-k)*db
3、梯度下降
w = w - r*vdw
b = b - r*vdb
- RMSprop:
1、算出dw和db
2、算指数平均值(dw的平方是元素平方)
Sdw = k*Sdw + (1-k)dw^2
Sdb = k * Sdb + (1-k)dw^2
3、梯度下降(其中sqrt表示开平方,u取10^(-8) )
w = w -r * ( dw / sqrt(Sdw+u) )
b = b - r * ( db / sqrt(Sdb+u) )
Adam算法:
假设动量梯度下降,可以在30个epoch能找到最小值,那么RMSprop能在20个epoch中找到,而Adam更厉害,因为它是动量梯度下降和RMSprop的结合体。运算步骤:
1、算出dw、db
2、Vdw = k1 * Vdw + (1-k1) * dw
, Vdb = K1 * Vdb + (1-k1) * db
,算出指数加权移动平均,即动量梯度下降
3、Sdw = k2 * Sdw + (1-K2) *dw^2
, Sdb = k2 * Sdb + (1-k2)*db^2
,算出RMSprop
4、Vdw修 = Vdw / (1-k1^t)
,Vdb修 = Vdb / (1-k1^t)
,修正动量梯度下降的值
5、Sdw修 = Sdw/ (1-k2^t)
,Sdb修 = Sdb / (1-k2^t)
,修正RMSprop
6、w = w -r * (Vdw修) / sqrt(Sdw修 + u)
,b = b - r * (Vdb修) / sqrt(Sdb修+u)
超参数:r、k1、k2,一般k1和k2取0.9和0.999且很少改变。 调参主要调整学习率。t表示梯度下降的次数,u用来防止除0
这里Adam的理解可以为自适应改变学习率
: 虽然表面r没变,但是w=w-rdw,当dw变大,w变小,相当于r变大的效果。起到了与调整r的同样的作用:改变了梯度下降在某个方向的学习速度。
def initialize_adam(parameters):L = len(parameters) // 2v = {}s = {}for l in range(1, L + 1):v[f"dW{l}"] = np.zeros_like(parameters[f"W{l}"])v[f"db{l}"] = np.zeros_like(parameters[f"b{l}"])s[f"dW{l}"] = np.zeros_like(parameters[f"W{l}"])s[f"db{l}"] = np.zeros_like(parameters[f"b{l}"])return v, sdef update_parameters_with_adam(parameters, grads, v, s, t, learning_rate=0.01, beta1=0.9, beta2=0.999, epsilon=1e-8):L = len(parameters) // 2v_corrected = {}s_corrected = {} # 修正后值for l in range(1, L + 1):# 算出v值,等式左边的为本次计算的新Vdw,等式右边为上次调用update_parameters_with_adam留下的Vdw值,注意不是for循环的上个值哦!for循环里的是多个dW1、dW2...等,别搞混了v[f"dW{l}"] = beta1 * v[f"dW{l}"] + (1 - beta1) * grads[f"dW{l}"]v[f"db{l}"] = beta1 * v[f"db{l}"] + (1 - beta1) * grads[f"db{l}"]v_corrected[f"dW{l}"] = v[f"dW{l}"] / (1 - np.power(beta1, t))v_corrected[f"db{l}"] = v[f"db{l}"] / (1 - np.power(beta1, t))# 算出s值s[f"dW{l}"] = beta2 * s[f"dW{l}"] + (1 - beta2) * np.power(grads[f"dW{l}"], 2)s[f"db{l}"] = beta2 * s[f"db{l}"] + (1 - beta2) * np.power(grads[f"db{l}"], 2)s_corrected[f"dW{l}"] = s[f"dW{l}"] / (1 - np.power(beta2, t))s_corrected[f"db{l}"] = s[f"db{l}"] / (1 - np.power(beta2, t)) # t为梯度下降次数,也就是调用该update_parameters_with_adam()方法的累计次数。parameters[f"W{l}"] = parameters[f"W{l}"] - learning_rate * v_corrected[f"dW{l}"] / np.sqrt(s_corrected[f"dW{l}"] + epsilon)parameters[f"b{l}"] = parameters[f"b{l}"] - learning_rate * v_corrected[f"db{l}"] / np.sqrt(s_corrected[f"db{l}"] + epsilon)return parameters, v, s