题目一:用梯度下降法求得y=(x-2.5)²+3的最小值点

        我们首先给出公式:X = X - α * grad,接下来,我将从两个方面对梯度下降进行讲解

(1)什么是梯度下降?

        在二元一次方程中,如何让计算机求解出最小值呢,梯度下降法就可以解决

梯度下降矩阵分解 梯度下降解方程_梯度下降

         如图所示,梯度下降法就好像是一个人,从半坡走到波谷的过程。首先以他当前的所处的位置为基准,寻找这个位置最陡峭的地方,然后朝着下降方向走一步,然后又继续以当前位置为基准,再找最陡峭的地方,再走直到最后到达最低处;同理上山也是如此,只是这时候就变成梯度上升算法了

        对于题目上的方程来讲,y=(x-2.5)²+3,导数即可写为:

grad = 2 * x - 5

        我们可以看到,梯度就是变量进行微分,说明梯度其实一个向量。

        梯度是微积分中一个很重要的概念,在单变量的函数中,梯度其实就是函数的微分,代表着函数在某个给定点的切线的斜率。在多变量函数中,梯度是一个向量,向量有方向,梯度的方向就指出了函数在给定点的上升最快的方向

(2) α是什么含义?

        α在梯度下降算法中被称作为学习率或者步长,意味着我们可以通过α来控制每一步走的距离。不要走太快,错过了最低点。同时也要保证不要走的太慢,导致太阳下山了,还没有走到山下。所以α的选择在梯度下降法中往往是很重要的!α不能太大也不能太小,太小的话,可能导致迟迟走不到最低点,太大的话,会导致错过最低点!

        所以在实际步骤上,我们对 x 进行一个随意的初始赋值,然后通过梯度下降算法,对最低点进行运算,代码如下:

x = 3.5                        #初始赋值
grad = 2 * x - 5               
lr = 0.1                       #学习率α
i = 0
while abs(grad) > 0.0001:      #循环截至条件为梯度值小于0。0001,即约等于0
    i += 1                     #统计次数
    grad = 2 * x - 5
    x = x - lr * grad          #梯度代换
    print("次数:{}      X的值:{}".format(i,x))               #对结果进行输出

        运行结果如图:

        

梯度下降矩阵分解 梯度下降解方程_算法_02

题目二:通过梯度下降求线性回归方程

        对于梯度下降,我们通常用他来解决的实际问题是线性回归

                        

梯度下降矩阵分解 梯度下降解方程_梯度下降矩阵分解_03

         通过分析披萨的直径与价格的线性关系,来预测任一直径的披萨的价格。而在这里,会用到损失函数的概念

(1)损失函数


梯度下降矩阵分解 梯度下降解方程_梯度下降_04

        在此公式中:

        m是数据集中数据点的个数,也就是样本数
        ½是一个常量,这样是为了在求梯度的时候,二次方乘下来的2就和这里的½抵消了,自然就没有多余的常数系数,方便后续的计算,同时对结果不会有影响
        y 是数据集中每个点的真实y坐标的值,也就是类标签
        h 是我们的预测函数(假设函数),根据每一个输入x,根据Θ 计算得到预测的y值,即

        

梯度下降矩阵分解 梯度下降解方程_机器学习_05

        代码如下:

        首先,我们需要定义数据集和学习率

from numpy import *

# 数据集大小 即20个数据点
m = 20
# x的坐标以及对应的矩阵
X0 = ones((m, 1))  # 生成一个m行1列的向量,也就是x0,全是1
X1 = arange(1, m+1).reshape(m, 1)  # 生成一个m行1列的向量,也就是x1,从1到m
X = hstack((X0, X1))  # 按照列堆叠形成数组,其实就是样本数据
# 对应的y坐标
y = np.array([
    7, 9, 13, 17.5, 18
]).reshape(m, 1)
# 学习率
alpha = 0.01

 接下来我们以矩阵向量的形式定义代价函数和代价函数的梯度

# 定义代价函数
def cost_function(theta, X, Y):
    diff = dot(X, theta) - Y  # dot() 数组需要像矩阵那样相乘,就需要用到dot()
    return (1/(2*m)) * dot(diff.transpose(), diff)


# 定义代价函数对应的梯度函数
def gradient_function(theta, X, Y):
    diff = dot(X, theta) - Y
    return (1/m) * dot(X.transpose(), diff)

最后就是算法的核心部分,梯度下降迭代计算

# 梯度下降迭代
def gradient_descent(X, Y, alpha):
    theta = array([1, 1]).reshape(2, 1)
    gradient = gradient_function(theta, X, Y)
    while not all(abs(gradient) <= 1e-5):
        theta = theta - alpha * gradient
        gradient = gradient_function(theta, X, Y)
    return theta


optimal = gradient_descent(X, Y, alpha)
print('optimal:', optimal)
print('cost function:', cost_function(optimal, X, Y)[0][0])

当梯度小于1e-5时,说明已经进入了比较平滑的状态,类似于山谷的状态,这时候再继续迭代效果也不大了,所以这个时候可以退出循环!
运行代码,计算得到的结果如下:

print('optimal:', optimal)  # 结果 [[0.51583286][0.96992163]]
print('cost function:', cost_function(optimal, X, Y)[0][0])  # 1.014962406233101

通过matplotlib画出图像,

# 根据数据画出对应的图像
def plot(X, Y, theta):
    import matplotlib.pyplot as plt
    ax = plt.subplot(111)  # 这是我改的
    ax.scatter(X, Y, s=30, c="red", marker="s")
    plt.xlabel("X")
    plt.ylabel("Y")
    x = arange(0, 21, 0.2)  # x的范围
    y = theta[0] + theta[1]*x
    ax.plot(x, y)
    plt.show()

plot(X1, Y, optimal)

图下如下:

                

梯度下降矩阵分解 梯度下降解方程_梯度下降_06

结语:

        最后不得不说,通过短期的学习,最后能够看到自己画出的图像,还是很自豪的哈