多层感知机

感知机

给定输入x,权重w,和偏移b,感知机输出

$$ \begin{equation} o = \sigma(\langle w, x \rangle + b) \ \ \ \ \ \sigma(x) = \begin{cases} 1 & \text{if } x > 0 \\ 0 & \text{otherwise 理论上也可以是-1} \end{cases} \end{equation} $$

线性分类输出的是一个实数,而这里输出的是一个离散的类,感知机最多做二分类

因为输出不是-1就是1,那么预期结果只和输出都为1。因此只有当相同的项相乘才会大于0。也就是结果正确。他等价于批量大小为1的梯度下降。最原始的感知机不需要随机这个操作

收敛定理

假设数据在半径r内,余量$\rho$分类俩类(其实就是做划分之后,还需要给俩边留有一定的余量)

$$ y(x^\top w+b)\geq\rho $$

收敛定理指的是什么时候停止训练

对于$||w||^2+b^2\leq1$

感知机保证在$\frac{r^2+1}{p^2}$步后收敛

如果俩个数据分的很开的话,收敛速度就特别快。

然而感知机不能拟合XOR函数(亦或),只能产生线性分割面。

因为无法用一条线进行切分。感知机是一个二分类的模型

多层感知机

如图我们先学习一个蓝色的线,再学习黄色的线,

简单来说就是学习到俩个简单函数,然后对俩个简单函数进行一次函数计算,然后得到最终的结果

单隐藏层

  • 输入$x \in \mathbb R^n$(表示x属于n个实数组成的向量)
  • 隐藏层$W_1 \in \mathbb R^{m \times n},\mathbf b_1 \in \mathbb R^m$(权重的数量是m x n个,这里的b的数量是和神经元的数量一样。w1表示输入层到隐藏层之间的权重)
  • 输出层$\mathbf w_2 \in \mathbb R^m,b_2 \in \mathbb R$(w2表示隐藏层到输出层之间的权重)

$$ h=\sigma(\mathbf W_1\mathbf x+\mathbf b_1);\\ o=\mathbf w^\top_2+b_2 $$

这里的h是输入层到隐藏层的结果,如果输出层是一个,这里的o。$\sigma$是按元素的激活函数

为什么需要非线性的激活函数?将因式展开后会发现仍然是一个线性函数。


如果解决多分类问题

  • 输入$x \in \mathbb R^n$
  • 隐藏层$W_1 \in \mathbb R^{m \times n},\mathbf b_1 \in \mathbb R^m$
  • 输出层$\mathbf w_2 \in \mathbb R^{m \times k},\mathbf b_2 \in \mathbb R^k$

$$ h=\sigma(\mathbf W_1\mathbf x+\mathbf b_1);\\ \mathbf o=\mathbf w^\top_2+\mathbf b_2;\\ y=\operatorname {softmax}(\mathbf o); $$

多隐藏层同理,但是隐藏层一般来说是先扩张再压缩,这样能够提取足够的信息

激活函数

sigmoid函数

将头一年到(0,1),是一个软的阶跃函数,$sigmoid(x) = \frac{1}{1 + e^{-x}}$

Tanh激活函数

$$ tanh(x)=\frac{1-\exp(-2x)}{1+\exp(-2x)} $$

将输入投影到-1,1的区间里,他仍然是软的阶跃函数

ReLU

ReLU(x)=max(x,0)

虽然ReLU的性能并不会比其他激活函数好太多,但它可以减少指数元素。这对于硬件非常友好(指数运算很贵,一次指数运算等于算上百次乘法)

代码

import torch
from torch import nn
from d2l import torch as d2l
import softmax_regression_2

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
# pytorch不会隐式地调整输入的形状
# 因此我们定义了展平层(flatten)在线性层之前调整网络输入形状
6net = nn.Sequential(nn.Flatten(), nn.Linear(784, 10))


def init_weight(m):
    # m的类型是一个线性的
    if type(m) == nn.Linear:
        nn.init.normal_(m.weight, std=0.01)


net.apply(init_weight)
loss = nn.CrossEntropyLoss()
# 使用学习率为0.1的小批量随机梯度下降最为优化算法,返回训练器
trainer = torch.optim.SGD(net.parameters(), lr=0.1)
num_epochs = 10
softmax_regression_2.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)

简单实现

nn.Sequential 是 PyTorch 中的一个模块容器,它用于构建由一系列子模块按顺序连接而成的神经网络。nn.Sequential 允许你将多个神经网络层或模块以定义好的顺序堆叠起来,形成一个更复杂的网络结构。当输入数据通过这样的网络时,数据会按顺序通过每一个模块进行处理。

nn.init.normal_() 是一个用于初始化张量权重的函数,它按照正态分布(也称高斯分布)来填充张量。这个函数直接修改传递给它的张量,而不是返回一个新的张量。

import torch
from torch import nn
from d2l import torch as d2l
from softmax_regression_2 import train_ch3

net = nn.Sequential(nn.Flatten(), nn.Linear(784, 256),
                    nn.ReLU(), nn.Linear(256, 10))


# 初始化隐藏层的权重的采样方式,
def init_weight(m):
    if type(m) == nn.Linear:
        nn.init.normal_(m.weight, std=0)


net.apply(init_weight)
num_epochs, lr, batch_size = 10, 0.1, 256
loss = nn.CrossEntropyLoss()
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
trainer = torch.optim.SGD(net.parameters(), lr=0.1)
train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)
Last modification:July 11, 2024
如果觉得我的文章对你有用,请随意赞赏