【李沐AI自学】预备知识(2)

微积分

四种输出形式

https://blog.csdn.net/qq_45664055/article/details/118271642

+加号拼接(针对字符串)

str1 = "27.56"
float1 = 27.56
print("数据为:" + str1)
print("数据为:" + str(float1))

结果:
	数据为:27.56
	数据为:27.56

.format格式

a = 27.56
b = 28.99
c = 29.66

print("数据为:{}".format(b))

print("abc的数据分别为:{0},{1},{2}".format(a, b, c))

print("abc的数据分别为:{1},{0},{2}".format(a, b, c))

结果:
	数据为:28.99
	abc的数据分别为:27.5628.9929.66
	abc的数据分别为:28.9927.5629.66

print(f “{}”) 的用法

a = 27.56
b = 28.99
c = 29.66

print(f"数据为:{a}")

print(f"abc的数据分别为:{a}{b}{c}")

结果:
	数据为:27.56
	abc的数据分别为:27.5628.9929.66

输出百分比方法
在这里插入图片描述


d = 29.6666

print('数据为:%.0f%%' % (d))

print('数据为:%.1f%%' % (d))

print('数据为:%.2f%%' % (d))

结果:
	数据为:30%
	数据为:29.7%
	数据为:29.67%

%s:代表字符串的占位 %d:整型的占位

name = 'wan'
age = 26

print('%s的年龄是%d' % (name, age))

age = 26.68
print('%s的年龄是%d' % (name, age))

age = "26"
print('%s的年龄是%s' % (name, age))

结果:
	wan的年龄是26
	wan的年龄是26  # 浮点型,取整数部分
	wan的年龄是26  #  字符串使用%s

导数和微分

为了更好地解释导数,让我们做⼀个实验。定义u = f(x) = 3x2 − 4x如下:

%matplotlib inline
import numpy as np
from matplotlib_inline import backend_inline
from d2l import torch as d2l
def f(x):
return 3 * x ** 2 - 4 * x

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:.5f}, numerical limit={numerical_lim(f, 1, h):.5f}') 
h *= 0.1

在这里插入图片描述

为了对导数的这种解释进⾏可视化,我们将使⽤matplotlib,这是⼀个Python中流⾏的绘图库。
要配置matplotlib⽣成图形的属性,我们需要定义⼏个函数。在下⾯,use_svg_display函数指
定matplotlib软件包输出svg图表以获得更清晰的图像。注意,注释#@save是⼀个特殊的标记,会将对应的函数、类或语句保存在d2l包中。因此,以后⽆须重新定义就可以直接调⽤它们(例如,d2l.use_svg_display())。

def use_svg_display(): #@save
"""使⽤svg格式在Jupyter中显⽰绘图"""
backend_inline.set_matplotlib_formats('svg')

我们定义set_figsize函数来设置图表⼤⼩。注意,这⾥我们直接使⽤d2l.plt,因为导⼊语句 from matplotlib import pyplot as plt已标记为保存到d2l包中。

def set_figsize(figsize=(3.5, 2.5)): #@save
"""设置matplotlib的图表⼤⼩"""
use_svg_display()
d2l.plt.rcParams['figure.figsize'] = figsize

下⾯的set_axes函数⽤于设置由matplotlib⽣成图表的轴的属性。

#@save
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函数来简洁地绘制多条曲线,因为我们需要在整个书中可视化许多曲线。

#@save
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()
# 如果X有⼀个轴,输出True
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)

现在我们可以绘制函数u = f(x)及其在x = 1处的切线y = 2x − 3,其中系数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)向量。具体⽽⾔,设函数f : Rn → R的输⼊是⼀个n维向量x = [x1, x2, . . . , xn]⊤,并且输出是⼀个标量。函数f(x)相对于x的梯度是⼀个包含n个偏导数的向量:
在这里插入图片描述

在这里插入图片描述

自动微分

⼀个简单的例⼦

作为⼀个演⽰例⼦,假设我们想对函数y = 2x⊤x关于列向量x求导。⾸先,我们创建变量x并为其分配⼀个初始值。

import torch
x = torch.arange(4.0)
x
#tensor([0., 1., 2., 3.])

在我们计算y关于x的梯度之前,我们需要⼀个地⽅来存储梯度。重要的是,我们不会在每次对⼀个参数求导时都分配新的内存。因为我们经常会成千上万次地更新相同的参数,每次都分配新的内存可能很快就会将内存耗尽。注意,⼀个标量函数关于向量x的梯度是向量,并且与x具有相同的形状。

x.requires_grad_(True) # 等价于x=torch.arange(4.0,requires_grad=True)
x.grad # 默认值是None
y = 2 * torch.dot(x, x)
y
#tensor(28., grad_fn=<MulBackward0>)

x是⼀个⻓度为4的向量,计算x和x的点积,得到了我们赋值给y的标量输出。接下来,我们通过调⽤反向传播函数来⾃动计算y关于x每个分量的梯度,并打印这些梯度。

y.backward()
x.grad
#tensor([ 0., 4., 8., 12.])

函数y = 2x⊤x关于x的梯度应为4x。让我们快速验证这个梯度是否计算正确。

x.grad == 4 * x
#tensor([True, True, True, True])

现在让我们计算x的另⼀个函数。

# 在默认情况下,PyTorch会累积梯度,我们需要清除之前的值
x.grad.zero_()
y = x.sum()
y.backward()
x.grad
#tensor([1., 1., 1., 1.])

⾮标量变量的反向传播

当y不是标量时,向量y关于向量x的导数的最⾃然解释是⼀个矩阵。对于⾼阶和⾼维的y和x,求导的结果可以是⼀个⾼阶张量。然⽽,虽然这些更奇特的对象确实出现在⾼级机器学习中(包括深度学习中),但当我们调⽤向量的反向计算时,我们通常会试图计算⼀批训练样本中每个组成部分的损失函数的导数。这⾥,我们的⽬的不是计算微分矩阵,⽽是单独计算批量中每个样本的偏导数之和。

# 对⾮标量调⽤backward需要传⼊⼀个gradient参数,该参数指定微分函数关于self的梯度。
# 在我们的例⼦中,我们只想求偏导数的和,所以传递⼀个1的梯度是合适的
x.grad.zero_()
y = x * x
# 等价于y.backward(torch.ones(len(x)))
y.sum().backward()#其实就是把y变成标量形式x1^2+x2^2+x3^2+x4^2
y.backward(torch.ones(len(x)))#同上,如果torch.ones(len(x))+1,结果乘2,就是加了个系数
x.grad
#tensor([0., 2., 4., 6.])

分离计算

有时,我们希望将某些计算移动到记录的计算图之外。例如,假设y是作为x的函数计算的,⽽z则是作为y和x的函数计算的。想象⼀下,我们想计算z关于x的梯度,但由于某种原因,我们希望将y视为⼀个常数,并且只考虑到x在y被计算后发挥的作⽤。在这⾥,我们可以分离y来返回⼀个新变量u,该变量与y具有相同的值,但丢弃计算图中如何计算y的任何信息。换句话说,梯度不会向后流经u到x。因此,下⾯的反向传播函数计算z=ux关于x的偏导数,同时将u作为常数处理,⽽不是z=xx*x关于x的偏导数。

x.grad.zero_()
y = x * x 
u = y.detach()
z = u * x 
z.sum().backward()
x.grad == u

Python控制流的梯度计算

使⽤⾃动微分的⼀个好处是:即使构建函数的计算图需要通过Python控制流(例如,条件、循环或任意函数调⽤),我们仍然可以计算得到的变量的梯度。在下⾯的代码中,while循环的迭代次数和if语句的结果都取决于输⼊a的值。我们现在可以分析上⾯定义的f函数。请注意,它在其输⼊a中是分段线性的。换⾔之,对于任何a,存在某个常量标量k,使得f(a)=k*a,其中k的值取决于输⼊a。因此,我们可以⽤d/a验证梯度是否正确。

def f(a):
b = a * 2
while b.norm() < 1000: b = b * 2
if b.sum() > 0: c = b
else:c = 100 * b
return c
a = torch.randn(size=(), requires_grad=True) d = f(a)
d.backward()
a.grad == d / a

概率没看

查阅文档

查找模块中的所有函数和类

为了知道模块中可以调⽤哪些函数和类,我们调⽤dir函数。例如,我们可以查询随机数⽣成模块中的所有属性:

import torch
print(dir(torch.distributions))

在这里插入图片描述
通常,我们可以忽略以“__”(双下划线)开始和结束的函数(它们是Python中的特殊对象),或以单个“_”(单下划线)开始的函数(它们通常是内部函数)。根据剩余的函数名或属性名,我们可能会猜测这个模块提供了各种⽣成随机数的⽅法,包括从均匀分布(uniform)、正态分布(normal)和多项分布(multinomial)中采样。

查找特定函数和类的⽤法

有关如何使⽤给定函数或类的更具体说明,我们可以调⽤help函数。例如,我们来查看张量ones函数的⽤法。

help(torch.ones)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值