Pytorch learning notes2 –微积分实现 为了更好地在python中实现导数,让我们做一个实验。 定义𝑢=𝑓(𝑥)=3𝑥2−4𝑥如下:
1 2 3 4 5 6 %matplotlib inline import numpy as npimport matplotlib.pyplot as pltfrom d2l import torch as d2ldef f (x ): return 3 * x ** 2 - 4 * x
通过令𝑥=1并让ℎ接近0,[𝑓(𝑥+ℎ)−𝑓(𝑥)]/ℎ的数值结果接近2。 虽然这个实验不是一个数学证明,但稍后会看到,当𝑥=1时,导数𝑢′是2。
1 2 3 4 5 6 7 def numerical_lim (f, x, h ): return (f(x + h) - f(x)) / h h = 0.1 for i in range (5 ): print (f'h={h:.5 f} , numerical limit={numerical_lim(f, 1 , h):.5 f} ' ) h *= 0.1
1 2 3 4 5 h=0.10000 , numerical limit=2.30000 h=0.01000 , numerical limit=2.03000 h=0.00100 , numerical limit=2.00300 h=0.00010 , numerical limit=2.00030 h=0.00001 , numerical limit=2.00003
为了对导数的这种解释进行可视化,我们将使用**matplotlib**
, 一个Python中流行的绘图库。 要配置matplotlib
生成图形的属性,我们需要定义几个函数。 在下面,use_svg_display
函数指定matplotlib
软件包输出svg图表以获得更清晰的图像。
注释#@save
是一个特殊的标记,会将对应的函数、类或语句保存在d2l
包中。 因此,以后无须重新定义就可以直接调用它们(例如,d2l.use_svg_display()
)。
1 2 3 def use_svg_display (): """使用svg格式在Jupyter中显示绘图""" backend_inline.set_matplotlib_formats('svg' )
我们定义set_figsize
函数来设置图表大小。 注意,这里可以直接使用d2l.plt
,因为导入语句 from matplotlib import pyplot as plt
已标记为保存到d2l
包中。
1 2 3 4 def set_figsize (figsize=(3.5 , 2.5 ) ): """设置matplotlib的图表大小""" use_svg_display() d2l.plt.rcParams['figure.figsize' ] = figsize
下面的set_axes
函数用于设置由matplotlib
生成图表的轴的属性。
1 2 3 4 5 6 7 8 9 10 11 12 def set_axes (axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend ): """设置matplotlib的轴""" axes.set_xlabel(xlabel) axes.set_ylabel(ylabel) axes.set_xscale(xscale) axes.set_yscale(yscale) axes.set_xlim(xlim) axes.set_ylim(ylim) if legend: axes.legend(legend) axes.grid()
通过这三个用于图形配置的函数,定义一个plot
函数来简洁地绘制多条曲线, 因为我们需要在整个书中可视化许多曲线。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 def plot (X, Y=None , xlabel=None , ylabel=None , legend=None , xlim=None , ylim=None , xscale='linear' , yscale='linear' , fmts=('-' , 'm--' , 'g-.' , 'r:' ), figsize=(3.5 , 2.5 ), axes=None ): """绘制数据点""" if legend is None : legend = [] set_figsize(figsize) axes = axes if axes else d2l.plt.gca() def has_one_axis (X ): return (hasattr (X, "ndim" ) and X.ndim == 1 or isinstance (X, list ) and not hasattr (X[0 ], "__len__" )) if has_one_axis(X): X = [X] if Y is None : X, Y = [[]] * len (X), X elif has_one_axis(Y): Y = [Y] if len (X) != len (Y): X = X * len (Y) axes.cla() for x, y, fmt in zip (X, Y, fmts): if len (x): axes.plot(x, y, fmt) else : axes.plot(y, fmt) set_axes(axes, xlabel, ylabel, xlim, ylim, xscale, yscale, legend)
现在我们可以绘制函数𝑢=𝑓(𝑥)及其在𝑥=1处的切线𝑦=2𝑥−3, 其中系数2是切线的斜率。
1 2 x = np.arange(0 , 3 , 0.1 ) plot(x, [f(x), 2 * x - 3 ], 'x' , 'f(x)' , legend=['f(x)' , 'Tangent line (x=1)' ])
梯度 我们可以连结一个多元函数对其所有变量的偏导数,以得到该函数的梯度 (gradient)向量。 具体而言,设函数𝑓:𝑅𝑛→𝑅的输入是 一个𝑛维向量𝑥=[𝑥1,𝑥2,…,𝑥𝑛]⊤,并且输出是一个标量。 函数𝑓(𝑥)相对于𝑥的梯度是一个包含𝑛个偏导数的向量: