梯度下降一般有以下三种,分别是:批梯度下降(BGD)、随机梯度下降(SGD)、小批量梯度下降(MBGD)
多元回归或者逻辑回归的梯度下降公式如下:
1.批量梯度下降法(Batch Gradient Descent,简称BGD),它是梯度下降法最原始的形式,具体思路是在更新每一参数时都使用所有的样本来进行更新,也就是方程(1)中的m表示样本的所有个数。
优点:全局最优解;易于并行实现;
缺点:当样本数目很多时,训练过程会很慢。
2.随机梯度下降法:它的具体思路是在更新每一参数时都使用一个样本来进行更新,也就是方程中的m等于1。每一次跟新参数都用一个样本,更新很多次。如果样本量很大的情况(例如几十万),那么可能只用其中几万条或者几千条的样本,就已经将theta迭代到最优解了,对比上面的批量梯度下降,迭代一次需要用到十几万训练样本,一次迭代不可能最优,如果迭代10次的话就需要遍历训练样本10次,这种跟新方式计算复杂度太高。
但是,SGD伴随的一个问题是噪音较BGD要多,使得SGD并不是每次迭代都向着整体最优化方向。
优点:训练速度快;
缺点:准确度下降,并不是全局最优;不易于并行实现。
从迭代的次数上来看,SGD迭代的次数较多,在解空间的搜索过程看起来很盲目。
小批量梯度下降法(Mini-batch Gradient Descent,简称MBGD):它的具体思路是在更新每一参数时都使用一部分样本来进行更新,也就是方程中的m的值大于1小于所有样本的数量。为了克服上面两种方法的缺点,又同时兼顾两种方法的有点。
样本量较少时,一般采用BGD,样本量很大时,常常采用MBGD
以下是三种梯度下降算法的python实现:
# 在多元回归上比较不同的梯度下降法:批梯度下降(BGD)、随机梯度下降(SGD)、小批量梯度下降(MBGD)
x0=np.random.randint(1,2,100).reshape(100,1) #x0全为1
x1=np.random.randint(1,10,100).reshape(100,1)
x2=np.random.randint(1,10,100).reshape(100,1)
x3=np.random.random(100).reshape(100,1)
# y=x0+x1+2*x2+3*x3
# X=np.hstack((x0,x1,x2,x3))
y=x0+x1
X=np.hstack((x0,x1))
#BGD
def BGD(X,y):
ept=0.001 #精度
loss=1 #定义一个损失 方便进入循环体 后来表示两次迭代损失函数的差异
alpha=0.01 #学习率
max_iter=0 #梯度更新次数
theta=np.random.randint(1,10,(X.shape[1],1)) #初始化theta
while max_iter<10000 and loss>ept:
partial=(1/X.shape[0])*X.T.dot(X.dot(theta)-y) #损失函数关于theta的偏导数
theta=theta-alpha*partial
max_iter+=1
loss=(1/(2*X.shape[0]))*np.sum((X.dot(theta)-y)**2) #计算两次迭代之间的差异(损失函数) 无明显差异就说明算法收敛到了全局最优解
return max_iter,theta
max_iter,theta=BGD(X,y)
print('BGD:max_iter:%s\ntheta:%s'%(max_iter,theta))
def SGD(X,y):
ept=0.001 #精度
loss=1 #定义一个损失 方便进入循环体 后来表示两次迭代损失函数的差异
alpha=0.01 #学习率
max_iter=0 #梯度更新次数
theta=np.random.randint(1,10,(X.shape[1],1)) #初始化theta
numsSample=X.shape[0]
while max_iter<10000 and loss>ept:
i = np.random.randint(0, numsSample) #随机抽取一个样本
# for i in range(numsSample): 这样其实也是遍历了所有数据
# partial=X[i:i+1,:].T.dot((X[i:i+1,:].dot(theta)-y[i,:]).reshape(1,1)) #损失函数关于theta的偏导数
# theta=theta-alpha*partial
partial=X[i:i+1,:].T.dot((X[i:i+1,:].dot(theta)-y[i,:]).reshape(1,1)) #损失函数关于theta的偏导数 注意shape必须都为2维
theta=theta-alpha*partial
max_iter+=1
loss=(1/(2*X.shape[0]))*np.sum((X.dot(theta)-y)**2) #计算两次迭代之间的差异(损失函数) 无明显差异就说明算法收敛到了全局最优解
return max_iter,theta
max_iter,theta=SGD(X,y)
print('SGD:max_iter:%s\ntheta:%s'%(max_iter,theta))
def MBGD(X,y):
ept=0.001 #精度
loss=1 #定义一个损失 方便进入循环体 后来表示两次迭代损失函数的差异
alpha=0.01 #学习率
max_iter=0 #梯度更新次数
numsSample = X.shape[0]#样本数量
theta=np.random.randint(1,10,(X.shape[1],1)) #初始化theta
while max_iter<10000 and loss>ept:
#这里的小批量梯度下降每次选取两个样本
i = np.random.randint(0, numsSample-1) # 随机抽取一个样本
# j=(i+1)%numsSample #选取另一个样本
partial=(1/2)*X[i:i+2,:].T.dot(X[i:i+2,:].dot(theta)-y[i:i+2,:]) #损失函数关于theta的偏导数
theta=theta-alpha*partial
max_iter+=1
loss=(1/(2*X.shape[0]))*np.sum((X.dot(theta)-y)**2) #计算两次迭代之间的差异(损失函数) 无明显差异就说明算法收敛到了全局最优解
return max_iter,theta
max_iter,theta=MBGD(X,y)
print('MBGD:max_iter:%s\ntheta:%s'%(max_iter,theta))
这是算法收敛的迭代次数对比
BGD:max_iter:2151
SGD:max_iter:1266
MBGD:max_iter:987
参考文章:
https://blog.csdn.net/UESTC_C2_403/article/details/74910107