【d2l】4.1-2.多层感知机及实现
【d2l】4.1-2.多层感知机及实现
多层感知机
隐藏层
此前已经对仿射变换进行了深入的研究,但是仿射变换对应的是线性关系,而线性关系是一种很强的假设
在这样的情况下,线性模型可能会不适用
假设一个猫狗分类的场景,我们需要决定某一个像素对于结果的权重,但是这个像素的强度对于判断为猫/狗的似然很难是一个简单的线性(单调)关系。而且就算是单调的,同样的图片反色之后势必会产生相反的结果
因此可以发现如果网络只有仿射变换的化,模型的泛化能力会受到限制,这时候就出现了隐藏层
我们可以通过在输入层和输出层中间加入一个或多个层级,把最后一层视作线性映射,这样或许能够突破线性的限制。这种架构通常称为"多重感知机(multilayer perceptron, MLP)"
多层感知机的基础上,假设隐藏层中做了\(\mathbf{H^{(k-1)}W^{(k)} + b}\),这个时候加入一个非线性函数\(\sigma\)使得\(\mathbf{H^{(k)}} = \sigma(\mathbf{H^{(k-1)}W^{(k)} + b})\)
就这样通过网络的堆叠,能够让模型的表达力变得更强
激活函数
下面是一些常用的非线性函数\(\sigma(\cdot)\)
ReLU函数

这个函数是修正线性单元(recitified linear unit, ReLU),它实现起来简单,并且在各种预测任务中表现良好
这个函数在0处不可导,因此在工程中一般使用0处导数为0,视作忽略了输入为0的情况

在ReLU基础上还有参数化ReLU(paarameterized ReLU, pReLU),加上了一个线性的项,可以让某些负数信息被激活
sigmoid函数

这个函数的数值特点是可以将\((-\infty,+\infty)\)的数据压缩到\((0, 1)\),并且是平滑可微的

tanh函数

导数如下

多层感知机从零开始实现
初始化模型参数
网络单元分配如下
28×28 --> 256 --> 10
接着对于这个三层结构,有两组\((\mathbf{W, b})\)
num_inputs, num_outputs, num_hiddens = 784, 10, 256
W1 = nn.Parameter(torch.randn(
num_inputs, num_hiddens, requires_grad = True
) * 0.01)
b1 = nn.Parameter(torch.zeros(num_hiddens, requires_grad = True))
W2 = nn.Parameter(torch.randn(
num_hiddens, num_outputs, requires_grad = True
) * 0.01)
b2 = nn.Parameter(torch.zeros(num_outputs, requires_grad = True))
params = [W1, b1, W2, b2]
基本函数
激活函数选取ReLU
def relu(X):
a = torch.zeros_like(X)
return torch.max(X, a)
每个单元都被压平成了向量,因此模型的计算不难写
def net(X):
X = X.reshape(-1, num_inputs)
H = relu(X @ W1 + b1) # @为矩阵乘法
return (H @ W2 + b2)
损失函数依旧采用softmax和交叉熵损失
loss = nn.CrossEntropyLoss(reduction = 'none')
训练
此前已经写过了训练的代码,结果也与之前相似,就不附图片了
num_epochs, lr = 10, 0.1
updater = torch.optim.SGD(params, lr = lr)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)
d2l.predict_ch3(net, test_iter)
多层感知机的简洁实现
MLP已经完全可以通过torch内置的函数实现
net = nn.Sequential(
nn.Flatten(),
nn.Linear(784, 256),
nn.ReLU(),
nn.Linear(256, 10)
)
def init_weights(m):
if type(m) == nn.Linear:
nn.init.normal_(m.weight, std = 0.01)
net.apply(init_weights)
batch_size, lr, num_epochs = 256, 0.1, 10
loss = nn.CrossEntropyLoss(reduction = 'none')
trainer = torch.optim.SGD(net.parameters(), lr = lr)
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)

浙公网安备 33010602011771号