《从零开始:机器学习的数学原理和算法实践》chap6 学习笔记
凸集
凸函数
我记得这里有些地方定义不同 ,去查了查
为什么不同教材中凸函数和凹函数的定义是不同的? 知乎 https://www.zhihu.com/question/31160556/answer/50926576
算了算了,都是凸的,上凸下凸,还有头秃(bushi)
wiki百科关于凹凸函数的定义
机器学习”热爱“凸函数
很多机器学习算法都可归结为凸优化问题的求解,因此凸优化问题在机器学习中具有特别重要的地位,而梯度下降法是最简单、也是最常见的一种最优化问题求解方法。
机器学习中一般将 凸优化问题统一表述为函数极小值求解问题,即 min f ( x ) \min{f(x)} minf(x)。其中 x 是需要被优化的变量,f 为目标函 数。
以山作比
梯度的本质是一个向量,表示某一函数在该 点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)变化最 快,变化率(该梯度的模)最大。一般来说,梯度可以定义为一个函数的全部偏导数构成的向 量。总结来说有如下两种情况
梯度是一个向量,它的方向就是函数在给定点上升最快的方向,因此负梯度方向就是函数 在给定点下降最快的方向。一旦我们知道了梯度,就相当于知道了凸函数下降最快的方向
这需要用到方向导数的概念,下面这几个我觉得写的不错
我想尝试用直观的角度来理解
很多例子用下山,说下山走最陡的方向,但是怎么判断最陡峭呢?
我尝试用 z = x 2 + y 2 z=x^2+y^2 z=x2+y2,从物理上矢量合成的角度来不严谨地解释一下
如图是 z = x 2 + y 2 z=x^2+y^2 z=x2+y2,每个点有x方向的偏导数和y方向的偏导数
对于一元函数z=f(y)和z=f(x)来说,每个点都可以往两个方向去变化,就是往直线的一端去或者直线的另一端去,
而当变成了二元函数,就可以往四面八方去了
偏导数组成了向量{2x,2y},那这个变化率用矢量合成我们可以这样来看
可以看成提供了2x,-2x,2y,-2y合成的四个方向基本的力,拉着自己在山上动,
假设我们要从x>0,y>0那块区域上山,我们在x方向和y方向上的变化率分别为在这两个方向的偏导数,可以由图比较明显的看到,要往上走得快,那应该是x方向要往x变大的方向,y方向上也应该是往y变大的方向
那么很显然,2x和2y由平行四边形法则合成的矢量方向是很合适的,上升最快的
而图中蓝色和红色方向上提供的力都没有那么大(呜呜很不严谨,也不知道说的对不对)
反过来,-2x和-2y合成的那个向量就是下降最快的方向
这段话没有组织好… 感觉自己想表达的意思没表达出来而且说的很乱呜呜呜,等想好了再来更新
关于泰勒公式和梯度下降
https://mp.weixin.qq.com/s/k26Fm0GL3fdVA9VbQIVAuQ
从泰勒公式到梯度下降 - 知乎 https://zhuanlan.zhihu.com/p/144855529
https://sm1les.com/2019/03/01/gradient-descent-and-newton-method/
这个好像很多地方说法略有不同
梯度 下降法中最重要的是如下的迭代式。
θ 1 = θ 0 − a ∇ J ( θ ) \\\\\theta^{1}=\theta^{0}-a \nabla J(\theta) θ1=θ0−a∇J(θ)
上述公式表示的含义是, 任意给定一组初始参数值 θ 0 \theta^{0} θ0, 只要沿着损失函数$ J(\theta)$ 的梯度下降 方向前进一段距离 a, 就可以得到一组新的参数值 θ 1 \theta^{1} θ1 。这里的 θ 0 \theta^{0} θ0 和 θ 1 \theta^{1} θ1 对应到机器学习中就是指 模型参数 (如 ω \omega ω 和 b b b )。
例
import matplotlib. pyplot as plt
import mpl_toolkits.axisartist as axisartist
import numpy as np
#创建画布
fig = plt.figure(figsize=(8,8))
#使用axisartist.Subplot方法创建绘图区对象ax
ax = axisartist.Subplot(fig,111)
#把绘图区对象添加至画布
fig.add_axes(ax)
#使用set_visible方法隐藏绘图区原有所有坐标轴
ax.axis[:].set_visible(False)
#使用ax.new_floating_axis添加新坐标轴
ax.axis["x"] = ax.new_floating_axis(0,0)
#给x轴添加箭头
ax.axis["x"].set_axisline_style("->", size = 1.0)
ax.axis["y"] = ax.new_floating_axis(1,0)
#给y轴添加箭头
ax.axis["y"].set_axisline_style("->", size = 1.0)
#设置刻度显示方向,x轴为下方显示,y轴为右侧显示
ax.axis["x"].set_axis_direction("bottom")
ax.axis["y"].set_axis_direction("right")
#x轴范围为-10~10,且分割为100份
x=np.linspace(-10,10,100)
y=x**2+3
#设置x、y轴范围
plt.xlim(-12,12)
plt.ylim(-10,100)
plt.plot(x, y)
plt.show()
def grad_1(x):
return x*2
def grad_descent(grad,x_current,learning_rate,precision,iters_max):
for i in range(iters_max):
print ('第',i,'次迭代x值为:',x_current)
grad_current=grad(x_current)
if abs(grad_current)<precision:
break # 当梯度值小于阈值时,停止迭代
else:
x_current=x_current-grad_current*learning_rate
print ('极小值处x为:' ,x_current)
return x_current
if __name__=="__main__":
grad_descent(grad_1,x_current=5,learning_rate=0.1,precision=0.000001,iters_max=10000)
import numpy as np
import matplotlib. pyplot as plt
import mpl_toolkits.mplot3d
x, y = np.mgrid[-2:2:20j,-2:2:20j] #测试数据
z=(x**2+y**2)#三维图形
ax = plt.subplot(111,projection='3d')
ax.set_title('f(x,y)=x^2+y^2') ;
ax.plot_surface(x,y,z,rstride=9,cstride=1,cmap=plt.cm.Blues_r)#设置坐标轴标签
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.show()
# 定义多元函数f(x,y)=x2+y2的梯度f'(x)=2x,f'(y)=2y,
def grad_2(p):
derivx = 2 * p[0]
derivy = 2 * p[1]
return np.array([derivx, derivy])
# 定义梯度下降函数
def grad_descent(grad,p_current,learning_rate,precision,iters_max):
for i in range(iters_max):
print ('第',i,'次迭代p值为:',p_current)
grad_current=grad(p_current)
if np.linalg.norm(grad_current, ord=2)<precision:
break # 当梯度趋近于 0 时,视为收敛
else:
p_current=p_current-grad_current* learning_rate
print ('极小值处p为:',p_current)
return p_current
#执行模块
if __name__=='__main__':
grad_descent(grad_2,p_current=np.array([1,-1]),
learning_rate=0.1,precision=0.000001,iters_max=10000)