%matplotlib inline import numpy as np import torch torch.set_printoptions(edgeitems=2, threshold=75)
In [2]:
t_c=[0.5,14.0,15.0,28.0,11.0,8.0,3.0,-4.0,6.0,13.0,21.0] t_u=[35.7,55.9,58.2,81.9,56.3,48.9,33.9,21.8,48.4,60.4,68.4]
In [3]:
t_c=torch.tensor(t_c) t_u=torch.tensor(t_u)
In [4]:
t_u
Out[4]:
tensor([35.7000, 55.9000, 58.2000, 81.9000, 56.3000, 48.9000, 33.9000, 21.8000,
48.4000, 60.4000, 68.4000])
In [5]:
import matplotlib.pyplot as plt fig=plt.figure() plt.scatter(t_c,t_u,c='b',edgecolors="r")
Out[5]:
<matplotlib.collections.PathCollection at 0x226b216e090>

In [6]:
def model(t_u,w,b):
return t_u*w+b
In [7]:
def loss_fn(t_p,t_c):
squared_diffs=(t_p-t_c)**2
return squared_diffs.mean()
In [8]:
w=torch.ones(()) b=torch.zeros(()) t_p=model(t_u,w,b) t_p
Out[8]:
tensor([35.7000, 55.9000, 58.2000, 81.9000, 56.3000, 48.9000, 33.9000, 21.8000,
48.4000, 60.4000, 68.4000])
In [9]:
w
Out[9]:
tensor(1.)
In [10]:
loss=loss_fn(t_p,t_c) loss
Out[10]:
tensor(1763.8848)
In [11]:
w=torch.zeros(()) b=torch.zeros(()) t_p=model(t_u,w,b) t_p
Out[11]:
tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
In [12]:
loss=loss_fn(t_p,t_c) loss # 通过损失函数来调整参数
Out[12]:
tensor(187.3864)
广播机制
In [14]:
x=torch.ones(()) y=torch.ones(3,1) z=torch.ones(1,3) a=torch.ones(2,1,1)
In [15]:
print("x*y",(x*y).shape)
x*y torch.Size([3, 1])
In [16]:
print("y*z",(y*z).shape)
y*z torch.Size([3, 3])
In [17]:
print("y*z*a",(y*z*a).shape)
y*z*a torch.Size([2, 3, 3])
In [18]:
x=torch.ones(5,2,4,1) y=torch.ones(3,1,1) #有数维度太高无法理解广播机制就起不了作用
梯度
编写梯度代码
In [20]:
def dloss_fn(t_p,t_c):
dsq_diffs=2*(t_p-t_c)/t_p.size(0)
return dsq_diffs
def dmodel_dw(t_u,w,b):
return t_u
def dmodel_db(t_u,w,b):
return 1.0
In [21]:
def grad_fn(t_u,t_c,t_p,w,b):
dloss_dtp=dloss_fn(t_p,t_c)
dloss_dw=dloss_dtp*dmodel_dw(t_u,w,b)
dloss_db=dloss_dtp*dmodel_db(t_u,w,b)
return torch.stack([dloss_dw.sum(),dloss_db.sum()])
In [22]:
delta=0.1 loss_rate_of_change_w=(loss_fn(model(t_u,w+delta,b),t_c))-(loss_fn(model(t_u,w-delta,b),t_c))/(2.0*delta) learning_rate=1e-2 w=w-learning_rate*loss_rate_of_change_w loss_rate_of_change_b=(loss_fn(model(t_u, w,b+delta),t_c)-loss_fn(model(t_u, w, b-delta),t_c))/(2.0*delta) b=b-learning_rate*loss_rate_of_change_b
In [23]:
def training_loop(n_epochs,learning_rate,params,t_u,t_c):
for epoch in range(1,n_epochs+1):
w,b=params
t_p=model(t_u,w,b)
loss=loss_fn(t_p,t_c)
grad=grad_fn(t_u,t_c,t_p,w,b)
params=params-learning_rate*grad
print("Epoch %d,loss %f" % (epoch,float(loss)))
return params
In [24]:
t_un=0.1*t_u params=training_loop(n_epochs=20000,learning_rate=1e-2,params=torch.tensor([10,0.0]),t_u=t_un,t_c=t_c) print(params)
Epoch 19994,loss 2.927645 Epoch 19995,loss 2.927645 Epoch 19996,loss 2.927645 Epoch 19997,loss 2.927645 Epoch 19998,loss 2.927645 Epoch 19999,loss 2.927645 Epoch 20000,loss 2.927645 tensor([ 5.3676, -17.3042])
In [25]:
%matplotlib inline
from matplotlib import pyplot as plt
t_p=model(t_un,*params)
fig=plt.figure(dpi=600)
plt.xlabel("Temperature Fahrenheit")
plt.ylabel("Temperature Celsius")
plt.plot(t_u.numpy(),t_p.detach().numpy())
plt.plot(t_u.numpy(),t_c.numpy(),"o")
plt.savefig("temp_unknow_plot.png")

PyTorch自动梯度计算
自动求导
In [28]:
t_c=torch.tensor([0.5,14.0,15.0,28.0,11.0,8.0,3.0,-4.0,6.0,13.0,21.0])
t_u=torch.tensor([35.7,55.9,58.2,81.9,56.3,48.9,33.9,21.8,48.4,60.4,68.4])
# 定义函数
def model(t_u,w,b):
return t_u*w+b
# 算方差
def loss_fn(t_p,t_c):
squared_diffs=(t_p-t_c)**2
return squared_diffs.mean()
# 唯一改变
params=torch.tensor([1.0,0.0],requires_grad=True)
# 反向传播
loss=loss_fn(model(t_u,*params),t_c)
loss.backward()
# 输出params的梯度看看
params.grad
Out[28]:
tensor([4517.2969, 82.6000])
In [29]:
def training_loop(n_epochs,learning_rate,params,t_u,t_c):
for epoch in range(1,n_epochs+1):
if params[0].grad is None:
params.grad.zero_()
t_p=model(t_u,*params)
loss=loss_fn(t_p,t_c)
loss.backward()
with torch.no_grad():
params-=learning_rate*params.grad
if epoch%500==0:
print("Epoch %d,loss %f" % (epoch,float(loss)))
return params
In [30]:
t_un=0.1*t_u params=training_loop(n_epochs=3000,learning_rate=1e-2,params=params,t_u=t_un,t_c=t_c) print(params)
C:\Users\tanhaowen\AppData\Local\Temp\ipykernel_13452\3767616033.py:3: UserWarning: The .grad attribute of a Tensor that is not a leaf Tensor is being accessed. Its .grad attribute won't be populated during autograd.backward(). If you indeed want the .grad field to be populated for a non-leaf Tensor, use .retain_grad() on the non-leaf Tensor. If you access the non-leaf Tensor by mistake, make sure you access the leaf Tensor instead. See github.com/pytorch/pytorch/pull/30531 for more informations. (Triggered internally at C:\cb\pytorch_1000000000000\work\build\aten\src\ATen/core/TensorBody.h:494.) if params[0].grad is None:
Epoch 500,loss 7.860115 Epoch 1000,loss 3.828538 Epoch 1500,loss 3.092191 Epoch 2000,loss 2.957698 Epoch 2500,loss 2.933134 Epoch 3000,loss 2.928648 tensor([ 5.3489, -17.1980], requires_grad=True)
PyTorch的优化器
In [32]:
import torch.optim as optim params=torch.tensor([1.0,0.0],requires_grad=True) learning_rate=1e-5 optimizer=optim.SGD([params],lr=learning_rate) t_p=model(t_u,*params) loss=loss_fn(t_p,t_c) loss.backward() optimizer.step() params
Out[32]:
tensor([ 9.5483e-01, -8.2600e-04], requires_grad=True)
In [33]:
def training_loop(n_epochs,optimizer,params,t_u,t_c):
for epoch in range(1,n_epochs+1):
t_p=model(t_u,*params)
loss=loss_fn(t_p,t_c)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if epoch%500==0:
print("Epoch %d,loss %f" % (epoch,float(loss)))
return params
In [34]:
params=torch.tensor([1.0,0.0],requires_grad=True) learning_rate=1e-2 optimizer=optim.SGD([params],lr=learning_rate) training_loop(n_epochs=1000,optimizer=optimizer,params=params,t_u=t_un,t_c=t_c)
Epoch 500,loss 7.860115 Epoch 1000,loss 3.828538
Out[34]:
tensor([ 4.8021, -14.1031], requires_grad=True)
In [35]:
# 激活函数 %matplotlib inline import numpy import torch import torch.optim as optim torch.set_printoptions(edgeitems=2,linewidth=75) t_c=[0.5,14.0,15.0,28.0,11.0,8.0,3.0,-4.0,6.0,13.0,21.0] t_u=[35.7,55.9,58.2,81.9,56.3,48.9,33.9,21.8,48.4,60.4,68.4] t_c=torch.tensor(t_c).unsqueeze(1) t_u=torch.tensor(t_u).unsqueeze(1)
In [36]:
t_u.shape
Out[36]:
torch.Size([11, 1])
In [37]:
n_samples=t_u.shape[0] n_val=int(0.2*n_samples) shuffled_indices=torch.randperm(n_samples) train_indices=shuffled_indices[:-n_val] val_indices=shuffled_indices[-n_val:] t_u_train=t_u[train_indices] t_c_train=t_c[train_indices] t_u_val=t_u[val_indices] t_c_val=t_c[val_indices] t_un_train=0.1*t_u_train t_un_val=0.1*t_u_val
In [38]:
import torch.nn as nn linear_model=nn.Linear(1,1) linear_model(t_un_val)
Out[38]:
tensor([[2.3831],
[2.0567]], grad_fn=<AddmmBackward0>)
In [39]:
linear_model.weight
Out[39]:
Parameter containing: tensor([[0.3331]], requires_grad=True)
In [40]:
linear_model.bias
Out[40]:
Parameter containing: tensor([0.4445], requires_grad=True)
In [41]:
x=torch.ones(10,1) linear_model(x)
Out[41]:
tensor([[0.7776],
[0.7776],
[0.7776],
[0.7776],
[0.7776],
[0.7776],
[0.7776],
[0.7776],
[0.7776],
[0.7776]], grad_fn=<AddmmBackward0>)
In [42]:
optimizer=optim.SGD(
linear_model.parameters(),
lr=1e-2
)
list(linear_model.parameters())
Out[42]:
[Parameter containing: tensor([[0.3331]], requires_grad=True), Parameter containing: tensor([0.4445], requires_grad=True)]
In [43]:
def train_loop(n_epochs,optimizer,model,loss_fn,t_u_train,t_u_val,t_c_train,t_c_val):
for epoch in range(1,n_epochs+1):
t_p_train=model(t_u_train)
loss_train=loss_fn(t_p_train,t_c_train)
t_p_val=model(t_u_val)
loss_val=loss_fn(t_p_train,t_c_train)
optimizer.zero_grad()
loss_train.backward()
optimizer.step()
if epoch==1 or epoch %1000==0:
print(f"Epoch {epoch},Training loss loss {loss_train.item():.4f},"f"Validation loss {loss_val.item():.4f}")
In [44]:
def loss_fn(t_p,t_c):
squard_diffs=(t_p-t_c)**2
return squard_diffs.mean()
linear_model=nn.Linear(1,1)
optimizer=optim.SGD(linear_model.parameters(),lr=1e-2)
train_loop(
n_epochs=3000,
optimizer=optimizer,
model=linear_model,
loss_fn=loss_fn,
t_u_train=t_u_train,
t_u_val=t_u_val,
t_c_train=t_c_train,
t_c_val=t_c_val,
)

发表回复