Softmax简介
Softmax回归是一个用于多类分类问题的线性模型,它是从Logistic回归模型演变而来的。Softmax回归与Logistic回归类似,但是输出不再是二元的,而是多类的。Softmax回归引入了softmax激活函数来将输出转换为合理的概率分布。与线性回归不同的是,Softmax回归的输出单元从⼀个变成了多个,因此Softmax回归的输入为向量。在图像识别问题中,Softmax回归可以计算输入图像属于每个类别的概率,最后预测出最可能所属的类别。
Softmax回归实现
Pyroch简洁实现一个softmax回归
简洁Softmax回归使用Pytorch提供的API进行实现,由于不需要手工实现求导,直接使用Pytorch的自动求导功能,节省了许多代码。
# 定义softmax模型
class Net(nn.Module):
"""定义softmax模型"""
def __init__(self):
super(Net,self).__init__()
self.fc1 = nn.Linear(784,10)
def forward(self,x):
# 展平数据 (n,1,28,28) --> (n,784)
x = x.view(-1,784)
return softmax(self.fc1(x),dim=1)
使用pytorch实现softmax回归不再需要损失函数和损失函数求导,而是直接使用nn模块中现成的交叉熵函数和自动求导即可。
定义迭代训练模型的train函数
# 迭代训练模型
def train(epochs,train_loader,model,optimizer,loss_fn,print_every):
for epoch in range(epochs):
# 每次输入batch_idx个数据
loss_acc = 0.0 # 累计损失
for batch_idx,(data,target) in enumerate(train_loader):
# 梯度清零
optimizer.zero_grad()
# 前向传播
output = model(data)
# 损失
loss = loss_fn(output,target)
# 反向传播
loss.backward()
# 更新参数
optimizer.step()
loss_acc += loss.item()
if batch_idx % print_every == print_every-1:
print('[%d,%5d]损失:%.3f'%(epoch+1,batch_idx+1,loss_acc/print_every))
模型测试
# 模型测试
def test(model,test_loader):
'''测试'''
correct = 0
total = 0
# 预测不需要梯度来修改参数
with torch.no_grad():
for data in test_loader:
images,labels = data
outputs = model(images)
_,predicted = torch.max(outputs.data,1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f"在测试集中的预测准确率:{correct/total}")
调用模型训练和测试的部分代码
if __name__ == '__main__':
model = Net()
# 交叉熵损失函数
loss_fn = nn.CrossEntropyLoss()
# 优化算法
optimizer = torch.optim.Adam(model.parameters(),lr=0.001)
train(20,train_dataloader,model,optimizer,loss_fn,50)
test(model=model,test_loader=test_dataloader)
完整代码
import torch
import torchvision
from torch import nn
from torch.nn.functional import softmax
from torch.utils.data import DataLoader
# 准备数据
train_data = torchvision.datasets.FashionMNIST(root='./data',train=True,transform=torchvision.transforms.ToTensor(),download=True)
test_data = torchvision.datasets.FashionMNIST(root='./data',train=False,transform=torchvision.transforms.ToTensor(),download=True)
# 读数据
train_dataloader = DataLoader(train_data,batch_size=64)
test_dataloader = DataLoader(test_data,batch_size=64)
# 定义softmax模型
class Net(nn.Module):
"""定义softmax模型"""
def __init__(self):
super(Net,self).__init__()
self.fc1 = nn.Linear(784,10)
def forward(self,x):
# 展平数据 (n,1,28,28) --> (n,784)
x = x.view(-1,784)
return softmax(self.fc1(x),dim=1)
# 迭代训练模型
def train(epochs,train_loader,model,optimizer,loss_fn,print_every):
for epoch in range(epochs):
# 每次输入batch_idx个数据
loss_acc = 0.0 # 累计损失
for batch_idx,(data,target) in enumerate(train_loader):
# 梯度清零
optimizer.zero_grad()
# 前向传播
output = model(data)
# 损失
loss = loss_fn(output,target)
# 反向传播
loss.backward()
# 更新参数
optimizer.step()
loss_acc += loss.item()
if batch_idx % print_every == print_every-1:
print('[%d,%5d]损失:%.3f'%(epoch+1,batch_idx+1,loss_acc/print_every))
# 模型测试
def test(model,test_loader):
'''测试'''
correct = 0
total = 0
# 预测不需要梯度来修改参数
with torch.no_grad():
for data in test_loader:
images,labels = data
outputs = model(images)
_,predicted = torch.max(outputs.data,1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f"在测试集中的预测准确率:{correct/total}")
if __name__ == '__main__':
model = Net()
# 交叉熵损失函数
loss_fn = nn.CrossEntropyLoss()
# 优化算法
optimizer = torch.optim.Adam(model.parameters(),lr=0.001)
train(20,train_dataloader,model,optimizer,loss_fn,50)
test(model=model,test_loader=test_dataloader)