深度学习笔记004LinearRegression&005LinearRegressionBuildingUpByPytorch线性回归/基础优化算法

今天,跟着李沐老师学习了单层的神经网络,也就是机器学习里面的线性回归,分为三个阶段——理论知识学习;手搓线性回归;调库写线性回归,笔记如下:

  1 # https://blog.csdn.net/w5688414/article/details/103058802 评论区解决No module named 'torchvision.models.detection的问题
  2 
  3 # 线性回归
  4 '''
  5 假设1: 影响房价的关键因素是卧室个数,卫生间个数,居住面积(x1,x2,x3)
  6 假设2:成交价是关键因素的加权和 y=w1x1+w2y2+w3y3+b
  7 可以将x看作一个输入向量,w看作权重向量,b是标准偏差
  8 y=<x,w>+b
  9 这种简单的线性模型可以看做一个单层的神经网络
 10 
 11 评估一个模型的平方损失:
 12     假设y是真实值,Y是估计值,(y-Y)²/2即为平方损失
 13     可见,平方损失越小,模型越好
 14 训练损失:
 15     X,训练集样本
 16     y,训练集加权和
 17     w,目标权重
 18     b,目标标准偏差
 19     f(X,y,w,b)=(1/2n)||y-Xw-b||²
 20     最小化损失来学习参数:w*,b* = arg min(f(X,y,w,b))
 21 
 22 线性回归是对N维输入的加权,外加偏差;
 23 常用平方损失来衡量预测值和真实值的差异;
 24 线性回归有显示解;(有显示解的,一般都是简单模型,大部分常用模型是没有显示解的。    显示解,即可以用数学方式求出来的解)
 25 线性回归可以看做单层神经网络。
 26 
 27 深度学习常用的是小批量梯度下降(梯度下降一般不使用,太贵了)
 28 梯度下降:不断沿着反梯度方向更新参数求解
 29 深度学习默认的求解算法:小批量随即梯度下降
 30 两个重要的超参数:批量大小,学习率
 31 
 32 '''
 33 
 34 # 线性回归从零开始实现
 35 # %matplotlib inline
 36 import random
 37 import torch
 38 from d2l import torch as d2l
 39 import os
 40 
 41 
 42 # 根据带有噪声的线性模型构造一个人造数据集,w=【2,-3.4】;b=4.2,外加一个噪声
 43 def synthetic_data(w, b, num_example):
 44     # 生成 y=Xw+b
 45     X = torch.normal(0, 1, (num_example, len(w)))
 46     y = torch.matmul(X, w) + b
 47     y += torch.normal(0, 0.01, y.shape)
 48     return X, y.reshape((-1, 1))
 49 
 50 
 51 true_w = torch.tensor([2, -3.4])
 52 true_b = 4.2
 53 features, labels = synthetic_data(true_w, true_b, 1000)
 54 print(features[0], labels[0])
 55 
 56 d2l.set_figsize()
 57 d2l.plt.scatter(features[:, 1].detach().numpy(), labels.detach().numpy(), 1);
 58 #这里的detach就是将features从计算图里拿出来放到numpy中去
 59 
 60 
 61 # d2l.plt.show()
 62 
 63 # 随机选取批量的函数
 64 def data_iter(batch_size, features, labels):
 65     num_examples = len(features)
 66     indices = list(range(num_examples))
 67     random.shuffle(indices)
 68     for i in range(0, num_examples, batch_size):
 69         batch_indices = indices[i:min(i + batch_size, num_examples)]
 70         yield features[batch_indices], labels[batch_indices]  # 相当于return,或者迭代器,但是节省内存,不需要一次性计算出来
 71 
 72 
 73 
 74 batch_size = 10
 75 for X, y in data_iter(batch_size, features, labels):
 76     print(X, '\n', y)
 77     break
 78 
 79 # 定义模型
 80 w = torch.normal(0, 0.01, size=(2, 1), requires_grad=True)
 81 b = torch.zeros(1, requires_grad=True)
 82 
 83 
 84 def linreg(X, w, b):
 85     return torch.matmul(X, w) + b
 86 
 87 
 88 # 损失函数
 89 def squared_loss(y_hat, y):
 90     return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2
 91 
 92 
 93 def sgd(params, lr, batch_Size):
 94     # 小批量随即梯度下降
 95     with torch.no_grad():
 96         for param in params:
 97             param -= lr * param.grad / batch_Size  # 这里的batch_Size是求均值,在损失函数求也行在这里也行
 98             param.grad.zero_()
 99 
100 
101 # 指定超参数:学习率、循环次数、模型、损失函数
102 lr = 0.03
103 num_epochs = 3
104 net = linreg
105 loss = squared_loss
106 
107 for epoch in range(num_epochs):
108     for X, y in data_iter(batch_size, features, labels):
109         l = loss(net(X, w, b), y)  # x和y的小批量损失
110         l.sum().backward()  # 对损失进行求和之后求梯度,这里可以理解为把所有的l求和求梯度,所以必须除以batch_size在sgd里面
111         # 换句话说,这里的l是一个(batch_size,1),而不是一个标量
112         sgd([w, b], lr, batch_size)  # 这里使用参数的梯度更新里面batch_size有问题,可能不能整除则就会在最后一个batch里面过大
113     with torch.no_grad():
114         train_l = loss(net(features, w, b), labels)
115         print(f'epoch {epoch + 1},loss{float(train_l.mean()):f}')
116 
117 print(f'w的估算误差:{true_w-w.reshape(true_w.shape)}')
118 print(f'b的估算误差:{true_b-b}')
 1 #关于星号和双星号的用法(多非关键字变量、关键字变量的关系,参考这篇非常清晰的博客:https://www.cnblogs.com/empty16/p/6229538.html
 2 
 3 import numpy as np
 4 import torch
 5 from torch.utils import data
 6 from d2l import torch as d2l
 7 
 8 true_w=torch.tensor([2,-3.4])
 9 true_b=4.2
10 
11 features,labels=d2l.synthetic_data(true_w,true_b,1000)
12 
13 # 构造一个pytorch的数据迭代器
14 def load_array(data_arrays,batch_size,is_train=True):
15     dataset=data.TensorDataset(*data_arrays)    #一个星号代表这里可以传入多个非关键字变量,在*data_arrays位置会被处理成为元组
16     return data.DataLoader(dataset,batch_size,shuffle=is_train)
17 
18 batch_size=10
19 data_iter=load_array((features,labels),batch_size,True)
20 
21 print(next(iter(data_iter)))
22 
23 from torch import nn
24 net = nn.Sequential(nn.Linear(2,1)) #这里2代表输入层维度,1代表输出层维度
25 # Sequential可以理解为把神经网络放在一个层的容器里,即list of layers
26 net[0].weight.data.normal_(0,0.01) #替换之前的w
27 net[0].bias.data.fill_(0) #替换之前的b
28 loss =nn.MSELoss()  #均方误差:MSE
29 trainer=torch.optim.SGD(net.parameters(),lr=0.03)  #之前实例化好的SGD
30 
31 # 开始训练!!!
32 num_epochs=3
33 for epoch in range(num_epochs):
34     for X,y in data_iter:
35         l=loss(net(X),y)  #net内本身有w和b,接口实现了,不用传参
36         trainer.zero_grad()
37         l.backward()  #接口已经帮你实现了sum(),不用额外求sum()
38         trainer.step()  #进行模型更新
39     l=loss(net(features),labels)
40     print(f'epoch{epoch+1},loss {l:f}')

 

posted @ 2022-01-02 20:31  爱和九九  阅读(89)  评论(0)    收藏  举报