1、用pytorch实现softmax回归
import torch
from IPython import display
from d2l import torch as d2l
batch_size = 256 #batch_size:小批量的个数
#导入数据
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
#nn.Flatten() 是干什么的?调整网络输入的形状
#在这里相当将图片从一个2维据(28*28)变成了一个一维向量(784*1)
#nn.Sequential()是一个容器
net = nn.Sequential(nn.Flatten(), nn.Linear(784, 10))
#其实都不用去对layer进行初始化,pytorch会自动对layer进行初始化,意思就是说下面这个初始化的过程全部注释掉也能行的通
#对layer进行初始化
def init_weights(m):
if type(m) == nn.Linear:
nn.init.normal_(m.weight, std=0.01)
#对每一层都用init_weights这个函数,对有参数的层进行初始化
net.apply(init_weights)
#用loss接一下交叉熵损失函数
#Pytorch中CrossEntropyLoss()函数的主要是将softmax-log-NLLLoss合并到一块得到的结果。
#也就是说softmax的过程是在损失函数里面做的
#https://zhuanlan.zhihu.com/p/98785902
#重点:y_target在函数内部会自动处理为one-hot的形式
loss = nn.CrossEntropyLoss()
#训练器——lr代表的是学习,它是一个超参数
trainer = torch.optim.SGD(net.parameters(), lr=0.1)
#训练的过程就是参数更行的过程,num_epochs = 10就是参数进行10次更新
num_epochs = 10
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)
2、softmax回归的从零开始实现
import torch
from IPython import display
from d2l import torch as d2l
batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
num_inputs = 784
num_outputs = 10
#定义layer并且对它的参数进行初始化
#重点:requires_grad=True,代表要对这个矩阵求梯度
W = torch.normal(0, 0.01, size=(num_inputs, num_outputs), requires_grad=True)
b = torch.zeros(num_outputs, requires_grad=True)
#定义softmax layer
def softmax(X):
X_exp = torch.exp(X)
partition = X_exp.sum(1, keepdim=True) #这个1代表的按列进行sum,0代表按行进行sum
return X_exp / partition
#定义模型——将前面所以的layer全部组合到一起
def net(X):
#X.reshape((-1, W.shape[0]))就是一个将图片拉长为一个行向量的过程
#X.reshape((W.shape[0], -1))就是拉成一个列向量
#W.shape[0]是求得W矩阵中所有元素的个数,在这里W.shape[0]=18*18=784(18*18的图片)
return softmax(torch.matmul(X.reshape((-1, W.shape[0])), W) + b)
#实现交叉熵损失函数——这里还是看的有点模糊
def cross_entropy(y_hat, y):
#len(matrix)——求的是矩阵的行
return -torch.log(y_hat[range(len(y_hat)), y])
def accuracy(y_hat, y):
"""计算预测正确的数量。"""
if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:
#argmax返回的是最大数的索引。argmax有一个参数axis,默认是0,表示每一列的最大值的索引,axis=1表示每一行的最大值的索引。
y_hat = y_hat.argmax(axis=1) #找出y_hat中每列最大的数的索引——在大数所在的位置
cmp = y_hat.type(y.dtype) == y
return float(cmp.type(y.dtype).sum())
trainer = torch.optim.SGD(net.parameters(), lr=0.03)
num_epochs = 3 #num_epochs = 3 代表着我们对模型进行三次训练
for epoch in range(num_epochs):
for X, y in train_iter: #随机取出10个样本(小批量)去训练模型
l = loss(net(X), y) #计算损失
trainer.zero_grad() #梯度归零
l.backward() #求解最新梯度
trainer.step() #参数更新
l = loss(net(features), labels)