梯度下降算法Python代码实现--批量梯度下降+随机梯度下降
+⼩批量梯度下降法
⼀、 ⾸先,我们⽤⼀个简单的⼆元函数⽤梯度下降法看下算法收敛的过程
也可以改⼀下eta,看⼀下步长如果⼤⼀点,算法的收敛过程
import numpy as np
import matplotlib.pyplot as plt
plot_x = np.linspace(-1,6,140)
plot_y = (plot_x-2.5)**2-1
#先算出来当前函数的导数
def dJ(theta):
return 2*(theta-2.5)
#梯度函数
def J(theta):
return (theta-2.5)**2-1
#初始化theta=0
#步长eta设置为0.1
eta = 0.1
theta_history = []
theta = 0
epsilon = 1e-8
while True:
gredient = dJ(theta)
last_theta = theta
theta = theta - eta*gredient
theta_history.append(theta)
if(abs(J(theta) - J(last_theta)) < epsilon):
break
print(theta)
print(J(theta))
plt.plot(plot_x, J(plot_x))
plt.plot(np.array(theta_history),J(np.array(theta_history)),color='r',marker='+')
plt.show()
出来的结果如下:
⼆、在线性回归模型中训练算法--批量梯度下降Batch Gradient Descent ⾸先,构建⼀个函数
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(666)
x = 2 * np.random.random(size=100)
y = x*3. + 4. + al(size=100)
#然后改成向量的形式
X = x.reshape(-1,1)
plt.scatter(x,y)
plt.show()
然后写实现梯度下降法求解我们构建的这个函数:
def J(theta , X_b , y):
try:
return sum((y-X_b.dot(theta))**2)/len(X_b)
except:
return float('inf')
#这⾥使⽤的是每次求⼀个参数,然后组合在了⼀起成了res
def dJ(theta, X_b ,y):
res = np.empty(len(theta))
res[0] = np.sum(X_b.dot(theta) - y)
for i in range(1, len(theta)):
res[i] = (X_b.dot(theta) - y).dot(X_b[:,i])
return res * 2 / len(X_b)
#这⾥也可以直接⽤矩阵运算求出所有的参数,效率更⾼
#return X_b.T.dot(X_b.dot(theta)-y)*2. / len(y)
然后把上⾯的过程封装成函数形式:
#把整个算法写成函数的形式
def gradient_descent(X_b, y ,inital_theta, eta ,n_inters = 1e4, epsilon = 1e-8): theta = initial_theta
i_inter = 0
while i_inter < n_inters:
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
i_inter += 1
return theta
然后⽤我们实现的算法求解上⾯那个函数:
#这⾥加⼀列1
X_b = np.hstack([np.ones((len(x),1)), x.reshape(-1,1)])
#初始theta设置为0
initial_theta = np.zeros(X_b.shape[1])
eta = 0.01
theta = gradient_descent(X_b, y, initial_theta, eta)
theta
输出结果如下:
array([4.02145786, 3.00706277])
使⽤梯度下降法时,由于不同维度之间的值⼤⼩不⼀,最好将数据进⾏归⼀化,否则容易造成不收敛
三、在线性回归模型中训练算法--随机梯度下降Stochastic Gradient Descent
随机梯度下降法可以训练更少的样本就得到⽐较好的效果,下⾯⽤两段代码⽐较下。
这个就是之前的批量梯度下降,不过换了⼀个数据集
import numpy as np
import matplotlib.pyplot as plt
m = 100000
x = al(size = m)
X = x.reshape(-1,1)
快速排序python实现y = 4. * x + 3. +al(0,3,size = m)
def J(theta , X_b , y):
try:
return sum((y-X_b.dot(theta))**2)/len(X_b)
except:
return float('inf')
def dJ(theta, X_b ,y):
return X_b.T.dot(X_b.dot(theta)-y)*2. / len(y)
def gradient_descent(X_b, y ,inital_theta, eta ,n_inters = 1e4, epsilon = 1e-8):
theta = initial_theta
i_inter = 0
while i_inter < n_inters:
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
i_inter += 1
return theta
%%time
X_b = np.hstack([np.ones((len(x),1)), X])
initial_theta = np.zeros(X_b.shape[1])
eta = 0.01
theta = gradient_descent(X_b, y, initial_theta, eta)
theta
结果如下:
Wall time: 37.2 s
theta:
array([3.00590902, 4.00776602])
下⾯我们⽤随机梯度下降:
#这⾥每次求⼀⾏数据的梯度,所以后⾯不⽤除以m
def dJ_sgd(theta, X_b_i, y_i):
return X_b_i.T.dot(X_b_i.dot(theta) - y_i)* 2.
#随机梯度下降法学习率设置t0/(t+t1)这种形式
#由于梯度下降法随机性,设置最后的结果的时候只设置最⼤迭代次数
def sgd(X_b, y, initial_theta, n_iters):
t0 = 5
t1 = 50
def learning_rate(t):
return t0/(t+t1)
theta = initial_theta
for cur_iter in range(n_iters):
#下⾯是设置每次随机取⼀个样本
rand_i = np.random.randint(len(X_b))
gradient = dJ_sgd(theta, X_b[rand_i], y[rand_i])
theta = theta - learning_rate(cur_iter) * gradient
return theta
%%time
X_b = np.hstack([np.ones((len(x),1)), X])
initial_theta = np.zeros(X_b.shape[1])
theta = sgd(X_b, y, initial_theta, n_iters=len(X_b)//3)
结果如下:
Wall time: 481 ms
theta:
array([2.93906903, 3.99764075])
对⽐下两者的运⾏时间,随机梯度下降法计算量更⼩,时间也⼤⼤减少。
四、⼩批量梯度下降法-Mini-Batch Gradient Descent
这个完全按照⾃⼰理解写下,如果有⼤⽜指点下不胜感激。
⼩批量梯度下降法主要在于每次训练的数据量不同,随机梯度下降是有⼀个样本就训练⼀次,⼩批量梯度下降是有⼀批样本训练⼀次,这⾥默认参数我给100
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论