能用张量处理就用张量,不要使用for in 跑循环,一个是容易出错,一个是比较浪费时间,应用广播机制的话去做很容易的
1.5
使用mean处理平均值
2.
在处理梯度的时候无法更改自身,因此使用的办法是with
一个简单的例子:
import torch as tt

x=tt.tensor(range(20))

y=x+3

w=tt.tensor([1.0],requires_grad=True)

b=tt.tensor([1.0],requires_grad=True)

def loss_fn(x,y,w,b):
det=0.5(y-wx-b)**2
det=det.mean()
return det

def training_loop(n_epochs, learning_rate, w,b,x, y):
for epoch in range(1, n_epochs + 1):
if w.grad is not None:
w.grad.zero_()
b.grad.zero_()
y=w*x+b
loss = loss_fn(x,y,w,b)
loss.backward()
with torch.no_grad():
w -= learning_rate * w.grad
return w,b
training_loop(10,1e-2,w,b,x,y)

这里的with是切换上下文,后面的torch.no_grad()是强制断图,在需要对叶子节点本身进行修改的时候使用

再补充一下
所谓标量y对矢量x求导,指的是,总的贡献y,对于每个分量贡献x进行求导,如果有n个x,里面代表的是,不同的x
比如卖苹果
苹果的价格是总的贡献,每个x的标度,比如口味,地址,大小是分贡献,每个Y,对应一个序列,(x1,x2,x3……)
而如果是矢量y对矢量x求导,代表的是y的每个分量对于x进行求导,需要传入一个和y相同大小的,代表y在每个方向上的权重。(一般是1,1,1但是也可以是1,2,3,权重是直接乘上去的)

retain_graph=True的意义在于不加的话,每次back时都会拆掉已经构建好的图,而第二次的时候依旧会尝试访问拆掉的图,所以会导致报错,这时候就需要这个东西

torch.autograd.grad这个函数的意义在于不用遍历全图求梯度但是图还是建了的,而且可以用来求单个梯度,但是并没有累积在其中,因此需要使用诸如:

print(torch.autograd.grad)之类的来访问,对于一次性的东西来说很方便

4.玩back(反向求导)的时候梯度会累加,这可能是因为第二次计算的结果,因此多次更新/多次反向时需要将梯度至为0

posted on 2022-10-08 19:25  mitudesk  阅读(48)  评论(0)    收藏  举报