机器学习中的优化器的方法

损失函数(Loss Function)

损失函数是用来估量模型的预测值与真实值的不一致程度,是一个非负实值函数, 损失函数越小,模型的鲁棒性就越好。损失函数越小表示算法达到意义上的最优。

nn.CrossEntropyLoss(多分类交叉熵损失函数)

深度神经网络中的优化器有各种各样的方法

梯度下降

参考:梯度下降法

梯度下降法(gradient descent)或最速下降法(steepest descent),是求解无约束最优化问题的一种最常用的方法。梯度下降法是一种迭代算法, 每一步会求解目标函数的梯度向量。

梯度的本意是一个向量, 表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向的变化最快, 变化率最大(梯度的模)

对于函数f(x_{1}, x_{2}) = 2 x_{1}^{3} - x_{2}^{2}来说, 其梯度就是g(x_{1}, x_{2}) = [6x_{1}^{2}, -2x_{2}]。对于给定点[x_{1}, x_{2}]的附近处, 它在[6x_{1}^{2}, -2x_{2}]方向变化率最大。在点[2, 3]附近处, 其梯度方向就是[24, 6], 朝着这个方向移动,会使得函数值增加的速率最快。

例:

f(x) \approx f(x_{k}) + g_{k}(x - x_{k}), 这里, g_{k} = g(x_{k}) = \triangledown f(x_{k})f(x)x_{k}的梯度。

假定设置了一个初始值x_{0}, 现在需要确定一个x_{1}, 代入上式可得:

f(x_{1}) \approx f(x_{0}) + g_{0}(x_{1} - x_{0}), 为了使得f(x_{1})最小(贪心策略), 应该有:

可以得到

其中\lambda_{0} = \frac{\left | x_{1} - x_{0} \right |}{\left | g_{0} \right |}定义为学习率,它实际上步长除以梯度的模。因此当学习率一定时, 步长其实是一直变化的。当梯度较大时,步长也较大;而当梯度较小时,步长也较小。这往往是我们希望的性质, 因为当接近于局部最优解时,梯度变得较小, 这时往往也需要步长变得更小,以有利于找到局部最优解。

其中,学习率要足够小,使得(1)满足泰勒公式所需要的精度。(2)能够很好地捕捉到极小值。

然而, 局限性

由于“梯度过小”,梯度下降法可能无法确定前进的方向了。即使人为增加收敛条件中的精度,也会由于梯度过小,导致迭代中前进的步长距离过小,循环时间过长。

梯度下降法实现简单,原理也易于理解,但它有自身的局限性,因此有了后面很多算法对它的改进。对于梯度过小的情况,梯度下降法可能难以求解。

此外,梯度下降法适合求解只有一个局部最优解的目标函数,对于存在多个局部最优解的目标函数,一般情况下梯度下降法不保证得到全局最优解(由于凸函数有个性质是只存在一个局部最优解,所有也有文献的提法是:当目标函数是凸函数时,梯度下降法的解才是全局最优解)。

由于泰勒公式的展开是近似公式,要求迭代步长要足够小,因此梯度下降法的收敛速度并非很快的。

利用梯度下降法求根号2的值

梯度下降法用来求函数的极值。假设一个函数f(x)可导,要计算其极值,求解过程为f^{'}(x) = 0。对于一般的函数,我们可以使用梯度下降法来迭代计算。具体地, 不断进行如下更新:

x \leftarrow x - \alpha f^{'}(x)

直到f^{'}(x) \approx 0,求得函数的极值。

倘若一个函数的极小值是根号2, 我们即可通过梯度下降法找到这个极值点。这个函数应该满足以下条件:【函数在某个区间内,只有根号2这一个极值点。假设求根号2为极小值点】

解:

如果函数的极小值是根号2, 那么它的导函数是以根号2为根。在上述区间内,导函数单调递增且经过零点

梯度下降法代码:

def gradient_descent(y):
    x = 1
    alpha = 0.001
    deta = 1
    count = 1
    while abs(deta) > 0.00001:
        deta = 4 * x * (x * x - y)
        x -= alpha * deta
        count = count + 1
    return x

y = 2
ans = gradient_descent(y)
print(ans)

利用二分法求根号2的值

使用二分法求解开根号的值比较简单,但是运行的效率较低,花费较长的时间。

def binary_search(y):
    l = 0
    r = y
    mid = (l + r) / 2
    while True:
        if mid * mid <= y and (mid + 0.00001) * (mid + 0.00001) > y:
            break
        if mid * mid <= y:
            l = mid + 0.00001;
            mid = (l + r) / 2;
        elif mid * mid > y:
            r = mid - 0.00001
            mid = (l + r) / 2
    return mid

y = 2
ans = binary_search(y)
print(ans)

利用牛顿迭代法求根号2的值

牛顿法不仅可以用来求解函数的极值问题, 还可以用来求解方程的根。二者在本质上是一个问题。因为求解函数极值的思路是寻找导数为0的点, 如果要求f(x)的极值, 也就是求f^{'}(x) = 0的根。

机器学习中的优化器 x_{n + 1} = x_{n} - f(x_{n}) / f^{'}(x_{n})

求解根号2的值x^{2} = 2, 转化成函数f(x) = x^{2} - 2, 求解该函数的近似正根。

def deal_num(y):
    # 初始化x值
    x = 2
    fx = x ** 2 - y

    while 1:
        if fx < 0.0000001:
            break
        else:
            x = x - fx / (2.0 * x)
            fx = x ** 2 - y

    return x

y = 2
ans = binary_search(y)
print(ans)

Guess you like

Origin blog.csdn.net/jiangchao98/article/details/120298644