在求解机器学习算法的模型参数,即无约束优化问题时,梯度下降(Gradient Descent)是最常用的方法之一。
一、梯度
在微积分里,对多元函数参数求偏导,把求得的各个参数的偏导数以向量的形式写出来,就是梯度。如果是一元函数,梯度就是偏导。
例如,f(x1,x2),分别求偏导,梯度向量就是(∂f/∂x1, ∂f/∂x2)
梯度向量的意义:从几何意义上来讲,就是函数变化增加(上升)最快的方向。
二、梯度下降
在机器学习算法中,在最小化损失函数时,可以通过梯度下降来一步步的迭代求解,得到最小化的损失函数和模型参数
相关概念:
1、步长(Learning rate),又称学习率,它决定了在梯度下降迭代过程中,每一步沿着梯度负方向前进的长度。
2、假设函数(hypothesis function): 在监督学习中,为了你和输入样本,而是用假设函数,记作比如对于单个特征的m个样本
可以采用拟合函数如下:
,
3、损失函数(Lost function):为了评估模型的好坏,通常用损失函数来度量拟合的程度。损失函数最小化,意味着拟合最好,对应的模型参数为最好。在线性回归中,损失函数通常为均方误差。对于m个样本,损失函数为
梯度
对于线性回归,假设函数为,其中
(i=0,1,2,...,n)为模型参数,
(I=1,2,...,n)为每个样本的n个特征。我们增加一个
,则上面可以简化为
对于上述函数,损失函数为
对求偏导为
由于样本中没有,上式中令所有
为1
的更新表达式为
上式中,为步长
三、代码实现,非矩阵形式
#二元线性回归梯度下降,函数直接实现
import numpy as np
SEED = 23455
rdm = np.random.RandomState(seed=SEED)
#参数初始化,随机的效果比全为0的好
theta0 = rdm.rand() * 10
theta1 = rdm.rand()* 10
theta2 = rdm.rand()* 10
# theta0 = 0
# theta1 = 0
# theta2 = 0
epochs = 24001
alpha = 0.001
#模拟生成数据
X = rdm.rand(32, 2) #32行,2列
print(X)
X = X * 10;
#模型,加入随机噪声
Y = [[x1 + x2 + 8 + (rdm.rand() - 0.5)] for (x1, x2) in X]
print(X)
print(Y)
#代价函数
def cost(X, Y, theta0, theta1, theta2):
loss = 0
m = len(Y)
for i in range(m):
loss += (theta0 + theta1*X[i,0] + theta2*X[i,1] - Y[i])**2
loss = loss/(2*m)
return loss
#梯度下降
def grad_des(X,Y, theta0, theta1, theta2, alpha, epochs):
m = len(Y)
for z in range(epochs):
theta0_grad = 0
theta1_grad = 0
theta2_grad = 0
for i in range(m):
theta0_grad += (theta0 + theta1*X[i,0] + theta2*X[i,1] - Y[i])
theta1_grad += (theta0 + theta1*X[i,0] + theta2*X[i,1] - Y[i])*X[i,0]
theta2_grad += (theta0 + theta1*X[i,0] + theta2*X[i,1] - Y[i])*X[i,1]
theta0_grad = theta0_grad/m
theta1_grad = theta1_grad/m
theta2_grad = theta2_grad/m
theta0 -= alpha*theta0_grad
theta1 -= alpha*theta1_grad
theta2 -= alpha*theta2_grad
if z % 100 == 0:
print('epochs={}.theta0={},theta1={},theta2={},loss={}'.format(z, theta0, theta1, theta2,
cost(X, Y, theta0, theta1, theta2)))
return theta0,theta1,theta2
print('begin...theta0={},theta1={},theta2={},loss={}'.format(theta0,theta1,theta2,cost(X,Y,theta0,theta1,theta2)))
print('running...')
theta0,theta1,theta2 = grad_des(X,Y,theta0,theta1,theta2,alpha,epochs)