一维梯度下降(with codes)

程序:使用梯度下降求解方程y=x22x+1y=x^{2} - 2x + 1的最小值。
观察学习率对梯度下降的影响。学习率不是越大越好,也不是越小越好。

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.rcParams["font.family"] = "SimHei"
mpl.rcParams["axes.unicode_minus"]=False

# 定义原函数方程。
def f(x):
    return x ** 2 - 2 * x + 1

# 定义梯度方程(导函数方程)
def gradient(x):
    return 2 * x - 2

# 定义初始值,即梯度下降最开始的迭代点。
x = 10
# 保存每次调整后,x的值以及x所对应的y值。即调整过程中,x与y的移动轨迹。
x_list = []
y_list = []
# 定义学习率(每次进行调整的幅度系数)
# 关于学习率的设置:学习率要设置得当,既不是越大越好,也不是越小越好。
# 如果学习率设置过小,则每次更新的非常缓慢,需要迭代很多次才能到极值附近。
# 如果学习率设置过大,则会出现震荡发散的情况,导致跳过最优解!
eta = 0.1

# 进行迭代
for i in range(30):
    # 将每次调整的值加入到列表中。
    x_list.append(x)
    y_list.append(f(x))
    # 根据梯度值来调整x,使得调整的x,能够令f(x)的值更小。
    x -= eta * gradient(x)
# 输出更新的值(更新的轨迹)
print(y_list)
print(x_list)

19-2. 梯度下降算法(程序实现)

注意:

  • 初始值是随机的
  • 损失函数公式:
    w = w - eta * 导函数 ,在代码中,w就是x,j(w)就是y
  • 脑海中回想回想损失函数的图,下图:
    自然得出结论:梯度下降过程汇总,梯度值是越来越小的
  • 看到代码输出结果:
  1. y_list里面的值是越来越小,x_list里面的值也是越来越小
  2. 下降的幅度越来越慢,也就是w的更新幅度越来越慢,因为梯度值是变小的,因为梯度值就是tan,tan越来越小,回想图,
    19-2. 梯度下降算法(程序实现)
  • 原函数 y=x22x+1y=x^{2}-2x+1,开口向上的二次函数,极小值点取(1,0)
    观察结果,y值趋近于0,x值趋近于1
  • 所以梯度下降算法是可以求极小值的,不仅仅是之前的最小二乘法可以求极小值
  • 注意是沿着梯度的反方向越来越小
  • 梯度不是也是幅度吗?why要加上eta,因为梯度作为幅度太单一了,加上eta作为辅助的幅度

迭代次数增加:
19-2. 梯度下降算法(程序实现)

%matplotlib qt
x = np.linspace(-9, 11, 200)
y = x ** 2 - 2 * x + 1
plt.plot(x, y)
# title中也支持Latex公式。
plt.title("函数$y=x^{2}-2x+1$的图像")
plt.plot(x_list, y_list, "ro--")
plt.show()

19-2. 梯度下降算法(程序实现)

  • 如果将学习率调小,下降的步幅很慢很慢
    19-2. 梯度下降算法(程序实现)

  • 将学习率调的话一定好吗?再打就有问题
    看值的话也是一正一副
    19-2. 梯度下降算法(程序实现)
    19-2. 梯度下降算法(程序实现)

  • x一正一副,且绝对值越来越大;如下图,连图像都没有了
    19-2. 梯度下降算法(程序实现)

二维梯度下降(with codes)

程序:使用梯度下降求解方程y=0.2(x1+x2)20.3x1x2+0.4y = 0.2(x1 + x2) ^ {2} - 0.3x1x2 + 0.4的最小值。

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
%matplotlib qt

mpl.rcParams["font.family"] = "SimHei"
mpl.rcParams["axes.unicode_minus"]=False

# 定义原函数
def f(x1, x2):
    return 0.2 * (x1 + x2) ** 2 - 0.3 * x1 * x2 + 0.4

# 针对x1求梯度值。
def gradient_x1(x1, x2):
    return 0.4 * (x1 + x2) - 0.3 * x2

# 针对x2求梯度值。
def gradient_x2(x1, x2):
    return 0.4 * (x1 + x2) - 0.3 * x1

# 定义学习率
alpha = 0.5
# 定义列表,存放x1,x2与y的移动轨迹。
x1_list = []
x2_list = []
y_list = []

# 定义初始点。
x1, x2 = 4.8, 4.5

for i in range(50):
    # 使用列表加入x1,x2,与y的轨迹信息。
    x1_list.append(x1)
    x2_list.append(x2)
    y_list.append(f(x1, x2))
    # 根据梯度值调整每个自变量。
    x1 -= alpha * gradient_x1(x1, x2)
    x2 -= alpha * gradient_x2(x1, x2)

print(x1_list)
print(x2_list)
print(y_list)

19-2. 梯度下降算法(程序实现)
注意:

  • 存放list,为了可视化
  • 初始值,都可以以,只要是凸函数
  • 对谁调整,对谁求偏导
    wj = wj - η * (J(w)/Wj)
  • 二维与一维的区别,2各变量
X1 = np.arange(-5, 5, 0.1)
X2 = np.arange(-5, 5, 0.1)
X1, X2 = np.meshgrid(X1, X2)
Y = np.array([X1.ravel(), X2.ravel()]).T
Y = f(Y[:, 0], Y[:, 1])
Y = Y.reshape(X1.shape)

fig = plt.figure()
ax = Axes3D(fig)
# 绘制方程曲面。
surf = ax.plot_surface(X1, X2, Y, rstride=5, cstride=5, cmap="rainbow")
# 绘制x1,x2,y的移动轨迹。
ax.plot(x1_list, x2_list, y_list, 'bo--')
# 指定为哪一个图形生成颜色条。
fig.colorbar(surf)
plt.title("函数$y = 0.2(x1 + x2) ^ {2} - 0.3x1x2 + 0.4$")
plt.show()

19-2. 梯度下降算法(程序实现)

plt.scatter(x1_list, x2_list, c="r")

19-2. 梯度下降算法(程序实现)

# m = plt.contourf(X1, X2, Y, 10)
# 画出等高线。
# 第4个参数(level):用来指定等高线的数量与位置。
# 直观的讲,该值越大,则等高线越密,否则越稀疏。
# m = plt.contour(X1, X2, Y, 25)

# 绘制填充的等高线。
m = plt.contourf(X1, X2, Y, 15)
# 在等高线上绘制x1与x2的移动轨迹。
plt.scatter(x1_list, x2_list, c="r")
plt.colorbar(m)

19-2. 梯度下降算法(程序实现)

更新

对于损失函数:
J(w)=12i=1m(y(i)wTx(i))2J(w) = \frac{1}{2}\sum_{i=1}^{m}(y ^ {(i)} - w ^ {T}x ^ {(i)}) ^ {2}
我们可以使用梯度下降的方式,不断去调整权重w,进而去减小损失函数J(w)的值。经过不断迭代,最终求得最优的权重w,使得损失函数的值最小(近似最小)
调整方式为:
wj=wjηJ(w)wjw_j = w_j - \eta\frac{\partial J(w)}{\partial w_j}
我们这里先单独对一个样本求梯度来演示,所有样本,只需要分别对每个式子进行求梯度,最后将每个求梯度的结果求和即可。

19-2. 梯度下降算法(程序实现)
不断调整w

按照每个分量的偏量方向 调整
对每个自变量求偏导
19-2. 梯度下降算法(程序实现)
梯度下降能求解,能作用于损失函数

梯度 向量 分量 取值 每个函数取偏导
认为是向量

梯度的特征:3点

特度更重要的记住:梯度是方向导数
取梯度的时候,梯度值
更重要的是 梯度值>0 则原函数是单调递增

找到w使得jw损失函数最小
梯度下降 求线性回归也是可以的
使用梯度下降求梯度下降

梯度值 凸函数 有 极小值
梯度下降的精髓:
19-2. 梯度下降算法(程序实现)
数学里面不管,只管
上升和下降没怎么关

通常情况下梦不到
但是我们可以取调整

最开始给定的w是这个

19-2. 梯度下降算法(程序实现)
我们可以往左调 可以往有调
取决于 梯度值 》0 <0 不看等于0 等于0就是季度之
一般是到不了极值点 越接近 越换

一维的时候 左右?
19-2. 梯度下降算法(程序实现)
二维,有w1 w2 w1 有左右 w2上下

19-2. 梯度下降算法(程序实现)
调整左还是右呢?
大于0 单调递增 w越大 梯度越大 我们得然他减小
应该往左

19-2. 梯度下降算法(程序实现)
19-2. 梯度下降算法(程序实现)

右边 > 0 继续减
左边 <0 w增大 让它往右

如此迭代反复,我们就能让它接近极值点

和我们增加最快,减小最快,其实一点关系都没有!!!

因为梯度的方向很可能并不能指向极值点,但是我们移动的时候靠近极值点

不是一条直线 梯度值都一样
19-2. 梯度下降算法(程序实现)
因为我们只能保证这一点的梯度,所以跟上升最快下降最快一点关系没有

所以梯度 只是控制方向,梯度大小,只是跟学习率有关
我们可以卖一步很小 卖一步很大
Delta w取多少?

我们就以梯度为移动不服,不是为了快,而是为了方便

所以我们有eta系数

取决于梯度值 大于0 还是小于0
梯度值》0 我们
梯度值<0

所以deltaw沃恩应该是让它增加还是减小了呢?
所以我们用w的性质

根据w来的
所以我们可以用求偏导数来控制

0 减一个w

19-2. 梯度下降算法(程序实现)
上面就是这个式子

所以梯度不是不符
梯度只是控制方向

不符和大小由eta控制

最后更新的式子
19-2. 梯度下降算法(程序实现)

然后是程序的实例:

一维的

二维的

关于eta值,不易于过大,就越过了极值点

19-2. 梯度下降算法(程序实现)

如果是多维的,就对每一个维度进行更新
更新x1的时候就对x1求偏导
X2 就是 x2求偏导

数据的维度,是和数组的维度一样吗?

嵌套的层数,数组的

数据集的维度,特征的数量,就是多少列,多少个维度,why?

Eg.人员

年龄,身高,体重,
三列,三个周,三个维度
19-2. 梯度下降算法(程序实现)
一个坐标轴就是一个维度

可视化画图

画等高线 新学的
X1 x2 取不同值的时候,能让y相等

最后说了下

损失函数不同,难道每个w写一个梯度函数吗?
19-2. 梯度下降算法(程序实现)
从通用角度来看,能不能有通用形式?对蓝求偏导
19-2. 梯度下降算法(程序实现)

19-2. 梯度下降算法(程序实现)
拆开 对 a+b 求导

标签求导0 后面一部分
对里面的一项 wj 求偏导 其他都是常数 0
19-2. 梯度下降算法(程序实现)
最后的结果是xj
19-2. 梯度下降算法(程序实现)

所以对w更新 有一个通用的公式

然后利用它不断迭代 能够求出来

19-2. 梯度下降算法(程序实现)
19-2. 梯度下降算法(程序实现)
生成数据集

然后拆分,拆不拆其实无所谓
还是拆一下

这是线性回归的结果:
19-2. 梯度下降算法(程序实现)
然后我们用梯度下降解一下

SGD随机梯度下降
学习率 给定迭代次数 模仿下面的
19-2. 梯度下降算法(程序实现)
放到相关的对象中

也定义一个方法
Wb

不可能是构造器里进行初始化的,都是fit学出来的,所以后面加上
就是命名惯例

初始化的构造器里面指定的就是超参数

就能知道参数到底是学习出来的还是指定出来的

对于每一个样本用这个公式
19-2. 梯度下降算法(程序实现)
循环一次拿出值

平行遍历多个可迭代对象 用zip
19-2. 梯度下降算法(程序实现)
19-2. 梯度下降算法(程序实现)
19-2. 梯度下降算法(程序实现)
19-2. 梯度下降算法(程序实现)
19-2. 梯度下降算法(程序实现)
套入公式后不断迭代

超参数 eta 慎重 给0.01 itertime 100
Diaoyong fit方法 xtrain ytrina 传进去

进行迭代一轮 一共迭代itertime轮

如果50轮达到很好的效果,就不用

加上self
19-2. 梯度下降算法(程序实现)
训练完周后 w He b就像有了
19-2. 梯度下降算法(程序实现)
梯度下降的方式也很不错
19-2. 梯度下降算法(程序实现)
那么给我们一个未知的p就能预知
19-2. 梯度下降算法(程序实现)
W跟新的时候没用循环 采用的时矢量化计算

现在可以预测了

预测的第一个样本的第一个特征

N个特征 m个样本
19-2. 梯度下降算法(程序实现)
第m个样本的第n个特征,这就是带特征的预测集
一会儿传测试集

常规方式的话 每次用循环 一次提一个小样本

广播之后 矢量化计算
19-2. 梯度下降算法(程序实现)
19-2. 梯度下降算法(程序实现)
一次 对位相乘 再相加
最后的 yhat 。。
一下子 预测值都得出
所以我们就可以利用numpy的矩阵方法 dot方法,不用循环

多维和一维 w 和 b
19-2. 梯度下降算法(程序实现)
解决方法 点乘+b就搞定了

模型最难的时fit fit学习参数

这个结果
19-2. 梯度下降算法(程序实现)
还是差不多 有的用e表示 这就his预测表示的结果

别只记得score 还有
19-2. 梯度下降算法(程序实现)
值传进来

把 ytrue ypredict穿过来 0.99 高 因为 noise小
19-2. 梯度下降算法(程序实现)
最关键的 是用梯度下降进行更新

19-2. 梯度下降算法(程序实现)
注意
19-2. 梯度下降算法(程序实现)

这一个快 对 w0 求骗到 w0 * 1

更新b前面乘以1 等于没成

根据方式求梯度下降 求 wj 最后得到比较理想的结果

梯度下降非常有意义,因为后面的梯度下降就靠这个算法
梯度下降球迷 最好的解决放啊发

之前学的就是随机梯度下降

现在使用的时批量梯度下降

批量梯度下降的更新方式:
不同之处在于:样本集汇中具有m个样本

随机梯度下降 M个样本会更新m次 速度快
只会更新wj 因为要进行累计求和 再
19-2. 梯度下降算法(程序实现)
训练集100轮迭代
19-2. 梯度下降算法(程序实现)
100Epoch 100个epoch

随机梯度下降 SGD 会进行多少次更新?

SGD
BGD

一轮只更新一次
求和进行更新

对于批量梯度下降 一轮不管有多少个
100轮 更新100次
样本集大的,耗内存多

有差异性,带表损失函数不一致

一个样本一个样本更新,带有误差,噪声大 异常样本
样本和样本之间,更新的方向也会有影响

随机梯度下降,更新的方向会语无伦次

19-2. 梯度下降算法(程序实现)
尽管是向着极值点进行起那就,但是多轮次

最后再极值点附近进行徘徊,因为每一个样本每一个样本更新

19-2. 梯度下降算法(程序实现)
就会比较稳定

所以SGD BSD对比
评率快快 但是 波折性
Bsd 跟新慢 但更新起来基本会朝着稳定的方向

因为SGD根据每个样本嘛

SGD可能跳过局部最优点 凸函数 因为是晃荡的
19-2. 梯度下降算法(程序实现)
19-2. 梯度下降算法(程序实现)
能不能在SGD 和 BGD之间找到结合的?

小批量梯度下降 MBGD
19-2. 梯度下降算法(程序实现)
M个样本
一次取k
0<=k<=m

小批量梯度下降
K=1 累加没了 就是随机
K=m 就是批量梯度下降

之前是手写梯度下降,但是主要是让大家明白原理,对线性回归也是促进作用

那我们看skleran中的

19-2. 梯度下降算法(程序实现)
SGRegressor
一点一点来 慢慢来
Eta0 初始 随着迭代次数一点一点减少 学习率的衰减
19-2. 梯度下降算法(程序实现)
19-2. 梯度下降算法(程序实现)
Max iter指定,不指定警告
19-2. 梯度下降算法(程序实现)

使用梯度下降求解之前的线性回归问题。

X, y, coef = make_regression(n_samples=1000, n_features=10, coef=True, bias=5.5, random_state=0, noise=10)

提示:
定义一个数组w,含有元素的数量与生成的特征数量一致。
定义一个偏置b。

梯度下降,需要自变量具有一个初始值,这里可以将w与b全部设置为初始值0,或者很小的数值。
自定义一个合适的学习了eta值。

再来一层循环【定义对所有的样本迭代的次数】
对X与y进行遍历,每次取出一个样本的数据(x)与对应的标签(target)【循环】
y_hat = w与每一个样本数据x进行对位相乘再相加, 再加上b。
w = w + eta * (y - y_hat)
再说一下 标准化处理

by梯度下降, 求解线性回归问题(with codes)

X, y, coef = make_regression(n_samples=1000, n_features=10, coef=True, bias=5.5, random_state=0, noise=10)

提示:
定义一个数组w,含有元素的数量与生成的特征数量一致。
定义一个偏置b。

梯度下降,需要自变量具有一个初始值,这里可以将w与b全部设置为初始值0,或者很小的数值。
自定义一个合适的学习了eta值。

再来一层循环【定义对所有的样本迭代的次数】
对X与y进行遍历,每次取出一个样本的数据(x)与对应的标签(target)【循环】
y_hat = w与每一个样本数据x进行对位相乘再相加, 再加上b。
w = w + eta * (y - y_hat)

from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
import numpy as np

# 生成数据集
X, y, coef = make_regression(n_samples=1000, n_features=10, coef=True, bias=5.5, random_state=0, noise=10)
print(f"真是的权重")
print(coef)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=0)
lr = LinearRegression()
lr.fit(X_train, y_train)
print("使用线性回归训练的权重与偏置:")
print(lr.coef_)
print(lr.intercept_)
# 使用梯度下降的方式进行求解回归问题。
class SGD:
    # 定义初始化方法。
    # eat: 学习率
    # iter_time: 迭代次数。
    def __init__(self, eta, iter_time):
        self.eta = eta
        self.iter_time = iter_time
    
    # 定义用于训练模型的方法。
    # X 样本训练数据。
    # y 样本对应的标签。
    # 简单说:fit方法就是用来求解(学习)w与b的。
    def fit(self, X, y):
        # 定义权重与偏置。
        # scikit-learn命名惯例:对于不是在构造器中指定,而是通过学习计算出来的属性,习惯在
        # 属性名后面加上下划线(_)。
        # w_的长度需要与数据集X的特征数量一致(列数)。这里全部初始化为0。
        self.w_ = np.zeros(X.shape[1])
        # b_的长度为1。这里初始化为0。
        self.b_ = 0
        
        # 对所有样本进行iter_time轮的迭代重复。
        for i in range(self.iter_time):
            # 从样本集(训练集)中取出一条样本数据(x)与该样本数据对应的标签(target)。
            for x, target in zip(X, y):
                # 计算预测值y_hat   y_hat = wT * x + b
                y_hat = np.dot(self.w_, x) + self.b_
                # 根据公式 wj = wj - eta * [-(y - y_hat) * xj] = wj + eta * (y - y_hat) * xj
                self.w_ = self.w_ + self.eta * (target - y_hat) * x
                self.b_ = self.b_ + self.eta * (target - y_hat)
           
    # 预测方法。根据样本X,返回对应的标签y。
    def predict(self, X):
        return np.dot(X, self.w_) + self.b_
    
#     def socre()
    
    
# 对SGD类进行测试。
sgd = SGD(0.01, 100)
sgd.fit(X_train, y_train)
print(coef)
print(sgd.w_)
print(sgd.b_)
y_hat = sgd.predict(X_test)
print(y_hat[:10])
print(y_test[:10])

from sklearn.metrics import r2_score
print(r2_score(y_test, y_hat))

相关文章:

猜你喜欢
  • 2022-01-08
  • 2021-07-08
  • 2021-11-21
  • 2021-08-17
  • 2021-05-16
  • 2021-11-27
相关资源
相似解决方案