import matplotlib.pyplot as plt
import torch
import torchvision
from torchvision import transforms
from torch.utils import data
import d2l
from torch import nn

trans = transforms.ToTensor() #把图片转成预处理,转成张量
mnist_train = torchvision.datasets.FashionMNIST(
    root="D:\PycharmDocument\limu\data", train=True, transform=trans, download=True)
mnist_test = torchvision.datasets.FashionMNIST(
    root="D:\PycharmDocument\limu\data", train=False, transform=trans, download=True)
batch_size=256
train_iter = data.DataLoader(mnist_train, batch_size, shuffle=True,num_workers=0)
test_iter = data.DataLoader(mnist_test, batch_size, shuffle=True,num_workers=0)

net=nn.Sequential(nn.Flatten(),nn.Linear(28*28,10))#设置网络
Loss=nn.CrossEntropyLoss()#设置损失函数
def init_weights(m):#对权重初始化,并为采用内置初始化
    if type(m) == nn.Linear:#判断是否是线性层,如果是将其初始化为正态分布
        nn.init.normal_(m.weight, mean=0, std=0.01)#只初始化w
net.apply(init_weights)#遍历整个网络,对线性层初始化
optimizer=torch.optim.SGD(net.parameters(),lr=0.01)
eochs=10
for epoch in range(eochs):
    for X,y in train_iter:
        optimizer.zero_grad()
        y_pred = net(X)
        l=Loss(y_pred,y)
        l.backward()
        optimizer.step()
    print(f'epoch:{epoch+1},loss:{l.item()}')

Q1为什么要对模型初始化,没有采用内置的初始化。

因为内置一般适用于深度网络。默认初始化是「Kaiming uniform」或「Xavier uniform」(取决于层)

例如 Linear 的默认初始化:

bound = 1 / sqrt(n) U(-bound, bound)

如果输入是 784(28×28 图像),那:

bound = 1/sqrt(784) ≈ 0.0357

这比 N(0,0.01) 要大不少。

Linear 的输出:z=xW+b

因为 W 比较大(范围约 ±0.0357),所以 z 很容易达到:1.0 ~ 3.0

这么大的值带入 softmax:e^3 ≈ 20,softmax 直接偏向某个类,梯度非常不稳定,导致初始训练阶段 loss 掉得特别慢

更多推荐