多层感知机
感知机
给定输入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)