Pytorch基础 简单逻辑回归

参照动手深度学习的相关章节,对于基本的代码和网络搭建进行一个小结和回顾;

逻辑回归基本表示:

对于简单逻辑回归,我们可以采用一个神经网络进行表示:

up-a1db92c5365cadb6c7bb5cc57566591adb0.png

所以可以看到,输入为两个输入,所以对应的权值也是两个,权值矩阵为2*1的矩阵;

输出为o=w1*x1+w2*x2;

对于三个样本,可以看到如下公式:

up-47e1f9ba9f8d9566929c00f769bbd2abef0.png

所以转换为矢量乘积方式:

up-0259372983fc7c2b0df3628e2527270e512.png

所以,针对于三个参数,可以得到梯度向量:

up-5a487234629cd4a9b4d3f19ef523de0808e.png

输入处理:

num_inputs=2#输入个数
num_examples=1000#样本个数
true_w=[2,-3.4] #w参数矩阵
true_b=4.2  #b偏置参数
features=torch.tensor(np.random.normal(0,1,(num_examples,num_inputs)),dtype=torch.float)
#构建基本样本集:其中采用0~1的分布采样,输入的样本集为2*1000;
labels=true_w[0]*features[:,0]*features[:,0]+true_w[1]*features[:,1]+true_b
#标签集,也就是最后的y,直接进行公式累乘即可;
labels+=torch.tensor(np.random.normal(0,0.01,size=labels.size()),dtype=torch.float)
#增加一个扰动项
batch_size=10
dataset=Data.TensorDataset(features,labels)
#使用Data函数构建数据集;
data_iter=Data.DataLoader(dataset,batch_size,shuffle=True)
#对构建的dataset进行切分,按照的个数参照batch_size

对于输入可以参照上述,对于自己的数据集可以直接采用Data.TensorDataset来进行构造;

之后我们指定网络的结构和初始参数,直接进行加载dataset进行参数学习即可;

网络结构:

对于网络结构的定义,通常有两种方式:
1.采用类继承进行定义;

2.通过使用函数传参逐层累加的方式进行定义;

如果通过类继承进行定义:

class LinearNet(nn.Module):
    def __init__(self, n_feature):
        super(LinearNet, self).__init__()
        self.linear = nn.Linear(n_feature, 1)
    # forward 定义前向传播
    def forward(self, x):
        y = self.linear(x)
        return y

net = LinearNet(num_inputs)

可以看到LinearNet类继承自nn.Module类;

如果通过逐层类加进行定义:

通常是使用Sequential函数进行定义:

# 写法一
net = nn.Sequential(
    nn.Linear(num_inputs, 1)
    # 此处还可以传入其他层
    )
# 写法二
net = nn.Sequential()
net.add_module('linear', nn.Linear(num_inputs, 1))
# net.add_module ......
# 写法三
from collections import OrderedDict
net = nn.Sequential(OrderedDict([
          ('linear', nn.Linear(num_inputs, 1))
          # ......
        ]))

可以看到三种最常用的方法;

其实网络结构写法很多,也可以采用自己定义的网络构造函数返回一个net,这样也是比较常见的操作;

在构建网络后,需要初始化模型参数,也就是要把网络中的w,b全部给予一个默认值:

init.normal_(net[0].weight,mean=0,std=0.01)
init.constant_(net[0].bias,val=0)

将权重参数每个元素初始化为随机采样于均值为0、标准差为0.01的正态分布,偏差初始化为零;

之后我们定义一个损失函数,对于线性回归,采用MSEloss即可;

对于优化器,我们采用learning rate=0.03,SGD梯度下降算法进行优化;

loss=nn.MSELoss()
optimizer=optim.SGD(net.parameters(),lr=0.003);

对于学习率的调整,我们也可以进行动态调整,例如分层调整,动态调整:

optimizer =optim.SGD([
                # 如果对某个参数不指定学习率,就使用最外层的默认学习率
                {'params': net.subnet1.parameters()}, # lr=0.03
                {'params': net.subnet2.parameters(), 'lr': 0.01}
            ], lr=0.03)

# 调整学习率
for param_group in optimizer.param_groups:
    param_group['lr'] *= 0.1 # 学习率为之前的0.1倍

训练阶段:

num_epochs = 3
for epoch in range(1, num_epochs + 1):
    for X, y in data_iter:
        output = net(X)
        l = loss(output, y.view(-1, 1))
        optimizer.zero_grad() # 梯度清零,等价于net.zero_grad()
        l.backward()
        optimizer.step()
    print('epoch %d, loss: %f' % (epoch, l.item()))

dense = net[0]
print(true_w, dense.weight)
print(true_b, dense.bias)

所以看到,最后可以通过查看参数,来进行对比;

值得注意的是,每轮训练之后,要记得将优化器的残留梯度清0,防止累加;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值