一.梯度下降(Gradient Descent)
什么为梯度呢?
一个向量(矢量),表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)变化最快,变化率最大(为该梯度的模)
具体解释如下:
(一).基本概念
梯度下降(gradient descent),又名最速下降法(steepest descent),是求解无约束最优化问题最常用的方法,其为一种迭代方法,每一步主要的操作是求解目标函数的梯度向量,将当前位置的负梯度方向作为搜索方向(下降最快方向),故称“梯度下降法”
(二).梯度下降算法
I.基本原理
从一条随机线开始,比如说直线a,我们计算这条线的误差平方和,然后调整斜率和y轴截距,重新计算新行的误差平方和。继续调整,直到达到局部最小值,其中平方误差之和最小。
“梯度下降法”是一种通过多次迭代最小化误差平方和来逼近最小平方回归线的算法
II.迭代公式
损失函数(Loss Function)
:更新前的自变量值
:更新后的值
:步长(Step Length),有时也称为学习率
III.算法流程
(1)随机初始参数
(2)确定学习率
(3)求出损失函数的参数梯度
(4)按迭代公式更新参数
(5)重复(3)(4)直到满足条件(如:损失函数或参数更新变化值小于 某个阈(yu)值,或者训练次数达到设定阈值)
注意:合适的学习率()是有一定必要的
IV.分类
分类依据:
根据使用的数据量不同,分为批量、小批量、随机梯度下降
(1)批量梯度下降(Batch Gradient Descent)
定义
计算训练数据集中每个示例的误差,但只有在评估了所有训练样本后,模型才会更新。整个过程就像一个循环,叫做训练周期。
优缺点:
优点:计算效率高,产生稳定的误差梯度和聚合性
缺点:稳定的误差梯度有时会导致聚合状态,这不是模型所能达到的最佳状态。它还要求整个训练数据集都在内存中,并且可供算法使用
(2)随机梯度下降(Stochastic Gradient Descent)
定义
随机梯度下降(SGD)对数据集中的每个训练示例都这样做。这意味着它将逐个更新每个训练示例的参数。这可以使SGD比批量梯度下降更快,具体取决于问题。
优缺点
优点:频繁的更新使我们得到一个非常详细的改进率。
缺点:频繁更新使这种方法在计算上成本更高。这些更新的频率也可能导致噪声梯度,使错误率不稳定波动,而不是缓慢下降。
(3)小批量梯度下降(Mini Batch Gradient Descent)
定义
将训练数据集拆分成小批量,并为每个批量执行更新。因此,它平衡了随机梯度下降的稳健性和批量梯度下降的效率。(推荐使用)
常见的小批量范围在50~256之间,具体视情况而定
(三).结合图形理解
问题1(三维图形)
问题描述:太阳快下山了,我想从山上的A点下山到B点,如何走才能使得所用的时间最短呢?
问题分析:
影响我们下山的实际所用时间有两个因素:
(1)步伐大小(因人而异)
(2)方向的选择(任意选择)
方向具有任意性,我们只有选择最陡峭的方向(梯度的反方向)才能最短
时间到达B点
图形如下:
如图,我们蓝色箭头方向为最陡峭方向,我们到达C点后,由于山区的道路复杂,我们需要实时更新我们的方向,这就是我们说的迭代,直至我们到达B点,就顺利下山了
问题2(二维图形)
问题描述:假设损失函数 (Loss Function)=(x-3)^2+20,求解其最小值,我们用梯度下降法来解决这个问题
设定迭代两次
手工计算如下:
代码如下
import numpy as np
import matplotlib.pyplot as plt
def f(x):#定义函数
return x ** 2 - 6*x + 29
def d_f(x):#定义导数
return 2*(x-3)
#定义梯度下降算法
def gradient_descent():
times=10 #迭代次数
alpha=0.2 #学习率
x=8#设定x的初始值
x_axis=np.linspace(-20,40)#设置x的坐标轴
fig= plt.figure(1,figsize=(5,5))#设置画布大小
ax=fig.add_subplot(1,1,1)#设置画布内只有一个图
ax.set_xlabel('X',fontsize=4)
ax.set_ylabel('Y',fontsize=14)
ax.plot(x_axis,f(x_axis))#作图
#进行迭代
for i in range(times):
x1=x
y1=f(x)
print("第%d次迭代:x=%f,y=%f"%(i+1,x,y1))
x=x-alpha*d_f(x)#更新x
y=f(x)#更新y
ax.plot([x1,x],[y1,y],'ko',lw=1,ls='-',color='coral')
plt.show()
if __name__ =="__main__":
gradient_descent()
测试运行结果如下:
二.线性回归
(一)回归分析
回归分析是确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法,是对具有因果关系的影响因素(自变量)和预测对象(因变量)所进行的数理统计分析处理。只有当变量与因变量确实存在某种关系时,建立的回归方程才有意义。因此,作为自变量的因素与作为因变量的预测对象是否有关,相关程度如何,以及判断这种相关程度的把握性多大,就成为进行回归分析必须要解决的问题。进行相关分析,一般要求出相关关系,以相关系数的大小来判断自变量和因变量的相关的程度。
(二)分类
一元线性回归和多元线性回归(根据自变量的个数)
I.一元线性回归
如图所示给出数据点,预测其回归方程
波士顿房价问题:
import matplotlib.pyplot as plt
import matplotlib
from math import pow
from random import uniform
import random
x0=[150,200,250,300,400,600]
y0=[6450,7450,8450,11450,15450,18450]
#为了方便计算,将所有数据缩小100倍
x = [1.5,2.00,2.50,3.00,3.50,4.00,6.00]
y = [64.50,74.50,84.50,94.50,114.50,154.50,184.50]
#线性回归函数为 y = theta0+thetal*x
#参数定义
theta0=0.1 #赋初值
thetal=0.1#赋初值
alpha=0.1#学习率
m=len(x)
count0=0
theta0_list=[]
thetal_list=[]
#使用批量梯度下降法
for num in range(10000):
count0 += 1
diss=0 #误差
deriv0 =0#对 theata0 导数
derivl =0#对 theatal 导数
#求导
for i in range(m):
deriv0 += (theta0+thetal*x[i]-y[i])/m
derivl +=((theta0+thetal*x[i]-y[i])/m)*x[i]
#更新theta0 和 thetal
for i in range(m):
theta0=theta0-alpha*deriv0
thetal=thetal-alpha*deriv1
#求损失函数
for i in range(m):
diss= diss + (1/(2*m)) * pow((theta0+thetal*x[i]-y[i]),2)
theta0_list.append(theta0*100)
thetal_list.append(thetal)
#如果误差已经很小,则退出循环
if diss <= 100:
break
theta0=theta0*100#原缩小数据放大
#使用梯度下降法
theta2=0.1#对 theata2 赋值
theta3=0.1#对 theta3 赋值
countl=0
theta2_list=[]
theta3_list=[]
for num in range(10000):
countl+=1
diss =0 #误差
deriv2 = 0 # theta2 导数
deriv3 = 0 # theta3 导数
#求导
for i in range(m):
deriv2+=(theta2 +theta2*x[i]-y[i])/m
deriv3+=((theta3+theta3*x[i]-y[i])/m)*x[i]
for i in range(m):
theta2=theta2-alpha*derive2
theta3=theta3-alpha*derive3
#求损失函数
rand_i = random.randrange(0,m)
diss = diss +(1/(2*m))*pow((theta2+theta3*x[rand_i]-y[rand_i]),2)
theta2_list.append(theta2*100)
theta3_list.append(theta3)
#如果误差已经很小,则退出循环
if diss <=0.001:
break
theta2=theta2*100
print("批量梯度下降最终得到theta0={},thetal={}".format(theta0,thetal))
print(" 得到的回归函数是:y={}+{}*".format(theta0,thetal))
print("随机梯度下将最终的得到theta0={},thetal={}".format(theta2,theta3))
print(" 得到的回归函数是:y={}+{}*".format(theta2,theta3))
#画原始数据图和函数图
matplotlib.rcParams['font.sans-serif']=['SimHei']
plt.plot(x0,y0,'bo',label='数据',color ='black')
plt.plot(x0,[theta0+thetal*x for x in x0],label='批量梯度下降',color='red')
plt.plot(x0,[theta2+theta3*x for x in x0] ,label='随机梯度下将',color='blue')
plt.xlabel('x(面积)')
plt.ylabel('y(价格)')
plt.legend()
plt.show()
plt.scatter(range(count0),theta0_list,s=1)
plt.scatter(range(count0),thetal_list,s=1)
plt.xlabel('上方为theta0,下方为thetal')
plt.show()
#plt.scatter(range(count1),theta2_list,s=3)
#plt.scatter(range(count1),theta3_list,s=3)
#plt.xlabel('上方为theta0,下方为thetal')
#plt.show()
II.多元线性回归
多元线性回归和一元线性回归类似,在其原理中会用到泰勒公式