3.1 线性回归 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 32 33 34 35 36 37 38 39 %matplotlib inline import mathimport timeimport numpy as npimport torchfrom d2l import torch as d2ln=10000 a=torch.ones([n]) b=torch.ones([n]) class Timer : def __init__ (self ): self.times=[] self.start() def start (self ): self.tik=time.time() def stop (self ): self.times.append(time.time()-self.tik) return self.times[-1 ] def avg (self ): return sum (self.times)/len (self.times) def sum (self ): return sum (self.times) def cumsum (self ): return np.array(self.times).cumsum().tolist()
1 2 3 4 5 c=torch.zeros(n) timer=Timer() for i in range (n): c[i]=a[i]+b[i] f'{timer.stop():.5 f} sec'
'0.14660sec'
1 2 3 timer.start() d=a+b f'{timer.stop():.5 f} sec'
'0.00000sec'
1 2 3 4 5 6 7 8 9 10 def normal (x,mu,sigma ): p=1 /math.sqrt(2 *math.pi*sigma**2 ) return p*np.exp(-0.5 /sigma**2 *(x-mu)**2 ) x=np.arange(-7 ,7 ,0.01 ) params=[(0 ,1 ),(0 ,2 ),(3 ,1 )] d2l.plot(x,[normal(x,mu,sigma)for mu,sigma in params],xlabel='x' ,ylabel='p(x)' ,figsize=(4.5 ,2.5 ),legend=[f'mean{mu} ,std{sigma} ' for mu,sigma in params])
3.2 线性回归的从零开始实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 %matplotlib inline import randomimport torchfrom d2l import torch as d2ldef synthetic_data (w,b,num_examples ): X=torch.normal(0 ,1 ,(num_examples,len (w))) y=torch.matmul(X,w)+b y+=torch.normal(0 ,0.01 ,y.shape) return X,y.reshape((-1 ,1 )) true_w=torch.tensor([2 ,-3.4 ]) true_b=4.2 features,labels=synthetic_data(true_w,true_b,1000 ) print ('features:' ,features[0 ],'\nlabel:' ,labels[0 ])
features: tensor([ 0.7328, -0.5520])
label: tensor([7.5513])
1 2 d2l.set_figsize() d2l.plt.scatter(features[:,1 ].detach().numpy(),labels.detach().numpy(),1 );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def data_iter (batch_size,features,labels ): num_examples=len (features) indices=list (range (num_examples)) random.shuffle(indices) for i in range (0 ,num_examples,batch_size): batch_indices=torch.tensor(indices[i:min (i+batch_size,num_examples)]) yield features[batch_indices],labels[batch_indices] batch_size=10 for X,y in data_iter(batch_size,features,labels): print (X,'\n' ,y) break
tensor([[ 0.9175, -0.1441],
[-0.3328, -0.4237],
[-0.1287, 1.6801],
[ 0.8705, -0.9030],
[-0.4966, 1.4015],
[ 1.3378, -1.8026],
[ 0.5129, 1.2806],
[ 1.1026, 1.2080],
[ 0.6151, 0.6337],
[-0.4683, -0.4388]])
tensor([[ 6.5336],
[ 4.9801],
[-1.7645],
[ 9.0089],
[-1.5652],
[12.9979],
[ 0.8680],
[ 2.2893],
[ 3.2902],
[ 4.7695]])
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 32 33 34 35 36 37 38 39 w=torch.normal(0 ,0.01 ,size=(2 ,1 ),requires_grad=True ) b=torch.zeros(1 ,requires_grad=True ) def linreg (X,w,b ): return torch.matmul(X,w)+b def squared_loss (y_hat,y ): return (y_hat-y.reshape(y_hat.shape))**2 /2 def sgd (params,lr,batch_size ): with torch.no_grad(): for param in params: param-=lr*param.grad/batch_size param.grad.zero_() lr=0.03 num_epochs=3 net=linreg loss=squared_loss for epoch in range (num_epochs): for X,y in data_iter(batch_size,features,labels): l=loss(net(X,w,b),y) l.sum ().backward() sgd([w,b],lr,batch_size) with torch.no_grad(): train_l=loss(net(features,w,b),labels) print (f'epoch{epoch+1 } ,loss{float (train_l.mean()):f} ' )
epoch1,loss0.036941
epoch2,loss0.000134
epoch3,loss0.000049
1 2 print (f'w的估计误差:{true_w-w.reshape(true_w.shape)} ' )print (f'b的估计误差:{true_b-b} ' )
w的估计误差:tensor([ 0.0002, -0.0002], grad_fn=<SubBackward0>)
b的估计误差:tensor([0.0002], grad_fn=<RsubBackward1>)
3.3 线性回归的简洁实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import numpy as npimport torchfrom torch.utils import datafrom d2l import torch as d2ltrue_w=torch.tensor([2 ,-3.4 ]) true_b=4.2 features,labels=d2l.synthetic_data(true_w,true_b,1000 ) def load_array (data_arrays,batch_size,is_train=True ): dataset=data.TensorDataset(*data_arrays) return data.DataLoader(dataset,batch_size,shuffle=is_train) batch_size=10 data_iter=load_array((features,labels),batch_size) next (iter (data_iter))
[tensor([[-0.6422, -0.7470],
[-2.1785, 0.3340],
[ 1.4011, -1.1104],
[-0.8083, -0.3035],
[ 0.1077, -0.1201],
[-0.4151, -0.1079],
[ 1.8074, 0.0904],
[-0.3707, 0.6197],
[ 0.3739, 0.2972],
[ 0.2383, 1.1791]]),
tensor([[ 5.4457],
[-1.3122],
[10.7837],
[ 3.6281],
[ 4.8105],
[ 3.7284],
[ 7.5017],
[ 1.3465],
[ 3.9247],
[ 0.6800]])]
1 2 3 4 5 6 from torch import nnnet=nn.Sequential(nn.Linear(2 ,1 )) net[0 ].weight.data.normal_(0 ,0.01 ),net[0 ].bias.data.fill_(0 )
(tensor([[ 0.0106, -0.0055]]), tensor([0.]))
1 2 3 4 loss=nn.MSELoss() trainer=torch.optim.SGD(net.parameters(),lr=0.03 )
1 2 3 4 5 6 7 8 9 num_epochs=3 for epoch in range (num_epochs): for X,y in data_iter: l=loss(net(X),y) trainer.zero_grad() l.backward() trainer.step() l=loss(net(features),labels) print (f'epoch{epoch+1 } ,loss{l:f} ' )
epoch1,loss0.000223
epoch2,loss0.000112
epoch3,loss0.000112
1 2 3 4 w=net[0 ].weight.data print ('w的估计误差:' ,true_w-w.reshape(true_w.shape))b=net[0 ].bias.data print ('b的估计误差:' ,true_b-b)
w的估计误差: tensor([ 0.0014, -0.0004])
b的估计误差: tensor([0.0008])