欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-03-20 23:59:16
...

文章目录

1 线性回归
2 Softmax与分类模型
3 多层感知机MLP

1 线性回归

1.1 定义

        线性回归,就是能够用一个直线较为精确地描述数据之间的关系。这样当出现新的数据的时候,就能够预测出一个简单的值。线性回归中最常见的就是房价的问题。

1.2 模型

        为了简单起见,这里我们假设价格只取决于房屋状况的两个因素,即面积(平方米)和房龄(年)。接下来我们希望探索价格与这两个因素的具体关系。线性回归假设输出与各个输入之间是线性关系:
《动手学深度学习》Task01:线性回归+Softmax与分类模型+多层感知机MLP

1.3 代价函数

       通过线性回归算法,我们可能会得到很多的线性回归模型,但是不同的模型对于数据的拟合或者是描述能力是不一样的。我们的目的最终是需要找到一个能够最精确地描述数据之间关系的线性回归模型。这是就需要用到代价函数。代价函数就是用来描述线性回归模型与正式数据之前的差异。如果完全没有差异,则说明此线性回归模型完全描述数据之前的关系。如果需要找到最佳拟合的线性回归模型,就需要使得对应的代价函数最小,相关的公式描述如下:
《动手学深度学习》Task01:线性回归+Softmax与分类模型+多层感知机MLP

1.4 优化函数 - 随机梯度下降

       当模型和损失函数形式较为简单时,上面的误差最小化问题的解可以直接用公式表达出来。这类解叫作解析解(analytical solution)。本节使用的线性回归和平方误差刚好属于这个范畴。然而,大多数深度学习模型并没有解析解,只能通过优化算法有限次迭代模型参数来尽可能降低损失函数的值。这类解叫作数值解(numerical solution)。

       在求数值解的优化算法中,小批量随机梯度下降(mini-batch stochastic gradient descent)在深度学习中被广泛使用。它的算法很简单:先选取一组模型参数的初始值,如随机选取;接下来对参数进行多次迭代,使每次迭代都可能降低损失函数的值。在每次迭代中,先随机均匀采样一个由固定数目训练数据样本所组成的小批量(mini-batch)B
,然后求小批量中数据样本的平均损失有关模型参数的导数(梯度),最后用此结果与预先设定的一个正数的乘积作为模型参数在本次迭代的减小量。
《动手学深度学习》Task01:线性回归+Softmax与分类模型+多层感知机MLP学习率:    η代表在每次优化中,能够学习的步长的大小
批量大小: B是小批量计算中的批量大小batch size

总结一下,优化函数的有以下两个步骤:
    (i)初始化模型参数,一般来说使用随机初始化;
    (ii)我们在数据上迭代多次,通过在负梯度方向移动参数来更新每个参数。
/****************
      通过实验可以得出,矢量加法比将两个向量使用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与分类模型

内容包含:

2.1 softmax回归的基本概念
2.2 交叉熵损失函数:
2.3 softmax回归模型的从零开始实现,实现一个对Fashion-MNIST训练集中的图像数据进行分类的模型
2.4 使用pytorch重新实现softmax回归模型

2.1 softmax回归的基本概念

Softmax是用于分类过程,用来实现多分类的,简单来说,它把一些输出的神经元映射到(0-1)之间的实数,并且归一化保证和为1,从而使得多分类的概率之和也刚好为1。函数定义如下:
《动手学深度学习》Task01:线性回归+Softmax与分类模型+多层感知机MLP
其中,Vi 是分类器前级输出单元的输出。i 表示类别索引,总的类别个数为 C。Si 表示的是当前元素的指数与所有元素指数和的比值。通过这个Softmax函数 就可以将多分类的输出数值转化为相对概率。

softmax回归解决了两个问题:
(1)由于输出层的输出值的范围不确定,我们难以直观上判断这些值的意义。
(2)由于真实标签是离散值,这些离散值与不确定范围的输出值之间的误差难以衡量。

2.2 交叉熵损失函数

想要预测分类结果正确,我们其实并不需要预测概率完全等于标签概率。对于某些分类问题,如果判定为某类的概率大于百分之五十,就不用精确地计算出其他值为多少,而平方损失则过于严格,就有了更适合衡量两个概率分布差异的测量函数,即交叉熵损失函数。
《动手学深度学习》Task01:线性回归+Softmax与分类模型+多层感知机MLP
其中带下标的 ????(????)???? 是向量 ????(????) 中非0即1的元素,需要注意将它与样本 ???? 类别的离散数值,即不带下标的 ????(????) 区分。交叉熵只关心对正确类别的预测概率,因为只要其值足够大,就可以确保分类结果正确。
‘’‘
/待补齐*/
2.3 softmax回归模型的从零开始实现,实现一个对Fashion-MNIST训练集中的图像数据进行分类的模型
2.4 使用pytorch重新实现softmax回归模型
’‘’

3 多层感知机MLP

内容包括:

3.1 多层感知机的基本知识
3.2 使用pytorch的简洁实现

3.1 多层感知机的基本知识

深度学习主要关注多层模型。在这里,我们将以多层感知机(multilayer perceptron,MLP)为例,介绍多层神经网络的概念。除了输入输出层,它中间可以有多个隐层,最简单的MLP只含一个隐层,即三层的结构,如下图:
《动手学深度学习》Task01:线性回归+Softmax与分类模型+多层感知机MLP**函数

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

问:为什么需要引入**函数?
a. 不使用**函数,每一层输出都是上层输入的线性函数,无论神经网络有多少层,输出都是输入的线性组合。
b. 使用**函数,能够给神经元引入非线性因素,使得神经网络可以任意逼近任何非线性函数,这样神经网络就可以利用到更多的非线性模型中。

关于**函数的选择:
a. ReLu函数是一个通用的**函数,目前在大多数情况下使用。但 是,ReLU函数只能在隐藏层中使用。
b. 用于分类器时,sigmoid函数及其组合通常效果更好。由于梯度消失问题,有时要避免使用sigmoid和tanh函数。
c. 在神经网络层数较多的时候,最好使用ReLu函数,ReLu函数比较简单计算量少,而sigmoid和tanh函数计算量大很多。
d. 在选择**函数的时候可以先选用ReLu函数如果效果不理想可以尝试其他**函数。

3.2 使用pytorch的简洁实现

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)

references:https://www.boyuai.com/elites/course/cZu18YmweLv10OeV/jupyter/U-WdzWhU6C29MaLj0udI5