《动手学深度学习》Task01线性回归;Softmax与分类模型、多层感知机

21 篇文章 0 订阅
13 篇文章 0 订阅

首先感谢伯禹教育、Datawhale、和鲸科技和各位志愿者给我们的这个机会来组织大家一起学习,本次学习的内容是《动手学深度学习PyTorch版》。

Task01:线性回归;Softmax与分类模型、多层感知机

1.线性回归基本要素:

  • 模型:对于线性回归,我们需要确定其模型,我们初设为输出与各个输入之间是线性关系,确定了模型之后再来确定模型的参数。

  • 数据集:我们通常收集一系列的真实数据,例如多栋房屋的真实售出价格和它们对应的面积和房龄。我们希望在这个数据上面寻找模型参数来使模型的预测价格与真实价格的误差最小。在机器学习术语里,该数据集被称为训练数据集(training data set)或训练集(training set),一栋房屋被称为一个样本(sample),其真实售出价格叫作标签(label),用来预测标签的两个因素叫作特征(feature)。特征用来表征样本的特点。

  • 损失函数:在模型训练中,我们需要衡量价格预测值与真实值之间的误差。通常我们会选取一个非负数作为误差,且数值越小表示误差越小。一个常用的选择是平方函数。
    1/2是为了求导方便便于梯度下降算法

  • 优化函数 - 随机梯度下降:当模型和损失函数形式较为简单时,上面的误差最小化问题的解可以直接用公式表达出来。这类解叫作解析解(analytical solution)。本节使用的线性回归和平方误差刚好属于这个范畴。然而,大多数深度学习模型并没有解析解,只能通过优化算法有限次迭代模型参数来尽可能降低损失函数的值。这类解叫作数值解(numerical solution)。
    在求数值解的优化算法中,小批量随机梯度下降(mini-batch stochastic gradient descent)在深度学习中被广泛使用。它的算法很简单:先选取一组模型参数的初始值,如随机选取;接下来对参数进行多次迭代,使每次迭代都可能降低损失函数的值。在每次迭代中,先随机均匀采样一个由固定数目训练数据样本所组成的小批量(mini-batch),然后求小批量中数据样本的平均损失有关模型参数的导数(梯度),最后用此结果与预先设定的一个正数的乘积作为模型参数在本次迭代的减小量。
    在这里插入图片描述
    学习率: 代表在每次优化中,能够学习的步长的大小
    批量大小: 是小批量计算中的批量大小batch size

     通过实验可以得出,矢量加法比将两个向量使用for循环按元素逐一做标量加法快很多,因此,我们应该尽可能采用矢量计算,以提升计算效率。
    

下面给出线性回归模型使用pytorch的简洁实现:

import torch
from torch import nn
import numpy as np
torch.manual_seed(1)
from torch.nn import init
import torch.optim as optim

torch.set_default_tensor_type('torch.FloatTensor')
num_inputs = 2
num_examples = 1000

true_w = [2, -3.4]
true_b = 4.2

features = torch.tensor(np.random.normal(0, 1, (num_examples, num_inputs)), dtype=torch.float)
labels = true_w[0] * features[:, 0] + true_w[1] * features[:, 1] + true_b
labels += torch.tensor(np.random.normal(0, 0.01, size=labels.size()), dtype=torch.float)
import torch.utils.data as Data

batch_size = 10

# combine featues and labels of dataset
dataset = Data.TensorDataset(features, labels)

# put dataset into DataLoader
data_iter = Data.DataLoader(
    dataset=dataset,            # torch TensorDataset format
    batch_size=batch_size,      # mini batch size
    shuffle=True,               # whether shuffle the data or not
    num_workers=2,              # read data in multithreading
)
for X, y in data_iter:
    print(X, '\n', y)
    break
    # ways to init a multilayer network
# method one
net = nn.Sequential(
    nn.Linear(num_inputs, 1)
    # other layers can be added here
    )

# method two
net = nn.Sequential()
net.add_module('linear', nn.Linear(num_inputs, 1))
# net.add_module ......

# method three
from collections import OrderedDict
net = nn.Sequential(OrderedDict([
          ('linear', nn.Linear(num_inputs, 1))
          # ......
        ]))

print(net)
print(net[0])

init.normal_(net[0].weight, mean=0.0, std=0.01)
init.constant_(net[0].bias, val=0.0)  # or you can use `net[0].bias.data.fill_(0)` to modify it direct

for param in net.parameters():
    print(param)
loss = nn.MSELoss()    # nn built-in squared loss function
                       # function prototype: `torch.nn.MSELoss(size_average=None, reduce=None, reduction='mean')`

optimizer = optim.SGD(net.parameters(), lr=0.03)   # built-in random gradient descent function
print(optimizer)  # function prototype: `torch.optim.SGD(params, lr=, momentum=0, dampening=0, weight_decay=0, nesterov=False)

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() # reset gradient, equal to net.zero_grad()
        l.backward()
        optimizer.step()
    print('epoch %d, loss: %f' % (epoch, l.item()))
    # result comparision
    
dense = net[0]
print(true_w, dense.weight.data)
print(true_b, dense.bias.data)

2.softmax和分类模型

softmax回归同线性回归一样,也是一个单层神经网络。由于每个输出 𝑜1,𝑜2,𝑜3 的计算都要依赖于所有的输入 𝑥1,𝑥2,𝑥3,𝑥4 ,softmax回归的输出层也是一个全连接层。
在这里插入图片描述
softmax回归解决了两个问题:
(1)由于输出层的输出值的范围不确定,我们难以直观上判断这些值的意义。
(2)由于真实标签是离散值,这些离散值与不确定范围的输出值之间的误差难以衡量。

softmax运算符(softmax operator)解决了以上两个问题。它通过下式将输出值变换成值为正且和为1的概率分布:
在这里插入图片描述

  • 交叉熵损失函数:
    想要预测分类结果正确,我们其实并不需要预测概率完全等于标签概率。对于某些分类问题,如果判定为某类的概率大于百分之五十,就不用精确地计算出其他值为多少,而平方损失则过于严格,就有了更适合衡量两个概率分布差异的测量函数,即交叉熵损失函数。

    在这里插入图片描述
    其中带下标的 𝑦(𝑖)𝑗 是向量 𝑦(𝑖) 中非0即1的元素,需要注意将它与样本 𝑖 类别的离散数值,即不带下标的 𝑦(𝑖) 区分。交叉熵只关心对正确类别的预测概率,因为只要其值足够大,就可以确保分类结果正确。

softmax实现:

def softmax(X):
    X_exp = X.exp()
    partition = X_exp.sum(dim=1, keepdim=True)
    # print("X size is ", X_exp.size())
    # print("partition size is ", partition, partition.size())
    return X_exp / partition  # 这里应用了广播机制

一个例子,我们可以看出SoftMax将类型概率映射至0-1,他们的总和为1。
在这里插入图片描述

3.多层感知机(MLP)

从前面的神经网络来看,如果我们只是单纯的添加线性隐藏层,那么就依然等价于一个单层神经网络:只是另外一个线性变换而已,为了解决这种问题,我们需要引入激活函数。

上述问题的根源在于全连接层只是对数据做仿射变换(affine transformation),而多个仿射变换的叠加仍然是一个仿射变换。解决问题的一个方法是引入非线性变换,例如对隐藏变量使用按元素运算的非线性函数进行变换,然后再作为下一个全连接层的输入。这个非线性函数被称为激活函数(activation function)。
几个常用的激活函数:

  • ReLU函数:
    ReLU(rectified linear unit)函数提供了一个很简单的非线性变换。给定元素 𝑥 ,该函数定义为

    函数图像:
    在这里插入图片描述
  • Sigmoid函数
    sigmoid函数可以将元素的值变换到0和1之间:
    在这里插入图片描述
    在这里插入图片描述
    特别的,依据链式法则,sigmoid函数的导数在这里插入图片描述
  • tanh函数:
    tanh(双曲正切)函数可以将元素的值变换到-1和1之间:

在这里插入图片描述

在这里插入图片描述

关于激活函数的选择:

ReLu函数是一个通用的激活函数,目前在大多数情况下使用。但是,ReLU函数只能在隐藏层中使用。

用于分类器时,sigmoid函数及其组合通常效果更好。由于梯度消失问题,有时要避免使用sigmoid和tanh函数。

在神经网络层数较多的时候,最好使用ReLu函数,ReLu函数比较简单计算量少,而sigmoid和tanh函数计算量大很多。

在选择激活函数的时候可以先选用ReLu函数如果效果不理想可以尝试其他激活函数。

回到多层感知机上

多层感知机就是含有至少一个隐藏层的由全连接层组成的神经网络,且每个隐藏层的输出通过激活函数进行变换。多层感知机的层数和各隐藏层中隐藏单元个数都是超参数。以单隐藏层为例并沿用本节之前定义的符号,多层感知机按以下方式计算输出:
在这里插入图片描述

简洁实现:

import torch
from torch import nn
from torch.nn import init
import numpy as np
import sys
sys.path.append("/home/kesci/input")
import d2lzh1981 as d2l

num_inputs, num_outputs, num_hiddens = 784, 10, 256
    
net = nn.Sequential(
        d2l.FlattenLayer(),
        nn.Linear(num_inputs, num_hiddens),
        nn.ReLU(),
        nn.Linear(num_hiddens, num_outputs), 
        )
    
for params in net.parameters():
    init.normal_(params, mean=0, std=0.01)

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size,root='/home/kesci/input/FashionMNIST2065')
loss = torch.nn.CrossEntropyLoss()

optimizer = torch.optim.SGD(net.parameters(), lr=0.5)

num_epochs = 5
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, None, None, optimizer)

参考文档:
https://www.kesci.com/org/boyuai/workspace/project
https://www.boyuai.com/elites/course/cZu18YmweLv10OeV/jupyter/sgHW6P_Qf9EfSEMnIfBJx https://www.boyuai.com/elites/course/cZu18YmweLv10OeV/jupyter/UWdzWhU6C29MaLj0udI5

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值