《动手学深度学习》第三章-softmax回归总结

《动手学深度学习》第三章-softmax回归总结

1.从fashion_mnist导入数据(d2l.load_data_fashion_mnist(batch_size))

def load_data_fashion_mnist(batch_size, resize=None):
    """Download the Fashion-MNIST dataset and then load it into memory.

    Defined in :numref:`sec_fashion_mnist`"""
    trans = [transforms.ToTensor()]
    if resize:
        trans.insert(0, transforms.Resize(resize))
    trans = transforms.Compose(trans)
    mnist_train = torchvision.datasets.FashionMNIST(
        root="../data", train=True, transform=trans, download=True)
    mnist_test = torchvision.datasets.FashionMNIST(
        root="../data", train=False, transform=trans, download=True)
    return (data.DataLoader(mnist_train, batch_size, shuffle=True,
                            num_workers=get_dataloader_workers()),
            data.DataLoader(mnist_test, batch_size, shuffle=False,
                            num_workers=get_dataloader_workers()))

torchvision : This library is part of the PyTorch project. PyTorch is an open source machine learning framework.

DataLoader : Combines a dataset and a sampler, and provides an iterable over the given dataset.The DataLoader supports both map-style and iterable-style datasets with single- or multi-process loading, customizing loading order and optional automatic batching (collation) and memory pinning.

返回值:mnist_train和mnist_test的迭代器

在这里插入图片描述

2.网络的定义

def net(X):
    return softmax(torch.matmul( X.reshape(-1,W.shape[0])) ,W) + b)

torch.matmul:matmul是tensor的乘法,输入可以是高维的。

(1)若输入都是二维,即普通的矩阵乘法。

(2)若输入是多维的,把多出的一维作为batch提出来,其余部分做矩阵乘法。

(5,3,4) @(4,2) -> (5,3,2)

(2,5,3) @ (1,3,4)->(2,5,4)

(2,1,3,4)@(5,4,2)->(2,5,3,2)

在进行tensor的乘法时,需要对输入的X进行reshape,size=(-1,28*28)

X.reshape(-1,W.shape[0])的size为[256,28*28]

W的size为[28*28,10]

b会经过广播机制为[256,10]

3.计算正确分类的样本数

#计算模型精度
def accuracy(y_hat,y):
    if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:
        y_hat = torch.argmax(y_hat,axis=1)
    cmp = y_hat.type(y.dtype) == y
    return float( cmp.type(y.dtype).sum() )

(1)y_hat = torch.argmax(y_hat,axis=1),y_hat的shape为[256,10],按行选择最大概率的下标,并且将下标保存到y_hat中。

(2)==比较运算符对类型敏感,先对y_hat类型进行转换。

4.累加器实现

在这里插入图片描述

(1)add(self,*args)该函数在定义时,实现的可变参数args。

例:Accumulator(2),累加器中有两个元素,第一个是正确数,第二个是总数。传参的时候也有两个参数(正确数,总数)

假设Accumulator中原有元素为[2,10],传参为[3,6]

zip(self.data,args) = [(2,3),(10,6)]

在第一轮for循环时,取出的a=2,b=3,即相加后正确数为5。

在第二轮for循环时,取出的a=10,b=6,即相加后总数为16。

5.训练过程设计思路

def train_epoch(net,train_iter,loss,updater):
    #将模型设置为训练模式
    if isinstance(net,torch.nn.Module):
        net.train()
    #定义三个累加器存放 损失总和,正确样本数,总样本数
    metric = Accumulator(3)
    for X,y in train_iter:
        y_hat = net(X)
        l = loss(y_hat,y)
        #更新参数
        if isinstance(updater,torch.optim.Optimizer):
            #若优化器使用python内置的
            updater.zero_grad()
            l.mean().backward()
            updater.step()
        else:
            l.sum().backward()
            updater(X.shape[0])
        metric.add(float(l.sum()), accuracy(y_hat, y), y.numel())
    # 返回训练损失和训练精度
    return metric[0] / metric[2], metric[1] / metric[2]

def train(net, train_iter, test_iter, loss, num_epochs, updater):  #@save
    """训练模型"""
    animator = Animator(xlabel='epoch', xlim=[1, num_epochs], ylim=[0.3, 0.9],
                        legend=['train loss', 'train acc', 'test acc'])
    for epoch in range(num_epochs):
        train_metrics = train_epoch(net, train_iter, loss, updater)
        test_acc = evaluate_accuracy(net, test_iter)
        animator.add(epoch + 1, train_metrics + (test_acc,))
    train_loss, train_acc = train_metrics
    assert train_loss < 0.5, train_loss
    assert train_acc <= 1 and train_acc > 0.7, train_acc
    assert test_acc <= 1 and test_acc > 0.7, test_acc

(1)train_epoch:在一个epoch中,我们将完整遍历一次数据集(train_data),不停地从中获取一个小批量的输入和相应的标签。对于每一个小批量,我们会进行以下步骤:

  • 通过调用net(X)生成预测并计算损失l(前向传播)。
  • 通过进行反向传播来计算梯度。
  • 通过调用优化器来更新模型参数。

为了更好的衡量训练效果,我们计算每个迭代周期后的损失,并打印它来监控训练过程。

6.softmax简洁实现关于层定义

#初始化网络模型
#需要在线性层前定义flatten,调整网络输入的形状
net = nn.Sequential(nn.Flatten(),nn.Linear(28*28,10))

torch.nn.Flatten(start_dim=1, end_dim=- 1)

在这里插入图片描述

输入维度是(32,1,28,28),经过Flatten()为(32,1*28,28)

作业:

  1. 在本节中,我们直接实现了基于数学定义softmax运算的softmax函数。这可能会导致什么问题?
  2. 本节中的函数cross_entropy是根据交叉熵损失函数的定义实现的。它可能有什么问题?提示:考虑对数的定义域。
  3. 你可以想到什么解决方案来解决上述两个问题?
  4. 返回概率最大的分类标签总是最优解吗?例如,医疗诊断场景下你会这样做吗?
  5. 假设我们使用softmax回归来预测下一个单词,可选取的单词数目过多可能会带来哪些问题?

(1)经过softmax函数转换时,分母是exp求和,若某个输入很大,会造成分母很大,进而引起数值范围错误。

(2)对数函数在X接近0时,其值趋于负无穷大。若某个输入经过softmax函数,输出的值可能是接近0,会造成loss值无限大,产生范围错误。

(3)softmax-concise课程的重新审视softmax函数设计。
log ⁡ ( y ^ j ) = log ⁡ ( exp ⁡ ( o j − max ⁡ ( o k ) ) ∑ k exp ⁡ ( o k − max ⁡ ( o k ) ) ) = log ⁡ ( exp ⁡ ( o j − max ⁡ ( o k ) ) ) − log ⁡ ( ∑ k exp ⁡ ( o k − max ⁡ ( o k ) ) ) = o j − max ⁡ ( o k ) − log ⁡ ( ∑ k exp ⁡ ( o k − max ⁡ ( o k ) ) ) . \begin{aligned} \log{(\hat y_j)} & = \log\left( \frac{\exp(o_j - \max(o_k))}{\sum_k \exp(o_k - \max(o_k))}\right) \\ & = \log{(\exp(o_j - \max(o_k)))}-\log{\left( \sum_k \exp(o_k - \max(o_k)) \right)} \\ & = o_j - \max(o_k) -\log{\left( \sum_k \exp(o_k - \max(o_k)) \right)}. \end{aligned} log(y^j)=log(kexp(okmax(ok))exp(ojmax(ok)))=log(exp(ojmax(ok)))log(kexp(okmax(ok)))=ojmax(ok)log(kexp(okmax(ok))).
(4)在医疗场景中,比如通过照片判断疾病类别,概率最大的分类标签不一定是最优解,需要具体问题,具体分析。

(5)当可选单词过于多,而神经网络参数学习效果不佳时,可能每个分类的概率都很小,成为随机选择分类。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值