基于softmax回归的图像分类一

欢迎关注

基于softmax回归的图像分类一

1.导入基础包

import torch
import torchvision
import numpy as np
import torchvision.transforms as transforms
import sys
from matplotlib import pyplot as plt
# sys.path.append('..')#为了导入上层目录的d21zh_pytorch
# import d21zh_pytorch as d21

2.获取和读取数据

def load_data_fashion_mnist(batch_size):
    if sys.platform.startswith('win'):
        num_workers=2#0表示不用额外进程来加速读取数据
    else:
        num_workers=4
    mnist_train=torchvision.datasets.FashionMNIST(root='~/Datasets/FashionMNIST',train=True,download=True,
                                  transform=transforms.ToTensor())
    mnist_test=torchvision.datasets.FashionMNIST(root='~/Datasets/FashionMNIST',train=False,download=True,transform=transforms.ToTensor())
    train_iter=torch.utils.data.DataLoader(mnist_train,batch_size=batch_size,shuffle=True										,num_workers=num_workers)
    test_iter=torch.utils.data.DataLoader(mnist_test,batch_size=batch_size,shuffle=False,
                                       num_workers=num_workers)
    return train_iter,test_iter

batch_size=256
train_iter,test_iter=load_data_fashion_mnist(batch_size)
# print(train_iter,test_iter)

3.初始化模型参数

num_inputs=784
num_outputs=10

w=torch.tensor(np.random.normal(0,0.01,(num_inputs,num_outputs)),dtype=torch.float,requires_grad=True)
# print(w[0])
b=torch.zeros(num_outputs,dtype=torch.float,requires_grad=True)

4.实现softmax运算

多维Tensor按维度操作

def softmax(x):
    x_exp=x.exp()
    partition=x_exp.sum(dim=1,keepdim=True)#dim=1:同一行
    return x_exp/partition#这里应用了广播机制

x=torch.rand((2,5))
x_pro=softmax(x)
print(x_pro,x_pro.sum(dim=1))
tensor([[0.2383, 0.2519, 0.2291, 0.1340, 0.1467],
        [0.2451, 0.1833, 0.1831, 0.1269, 0.2616]]) tensor([1., 1.])

5.定义模型

def net(x):
    return softmax(torch.mm(x.view((-1,num_inputs)),w)+b)

6.定义损失函数

#首先学习一下torch.gather用法
y_hat=torch.tensor([[0.1,0.3,0.6],[0.3,0.2,0.5]])
y=torch.LongTensor([0,2])
y_hat.gather(1,y.view(-1,1))#dim为1表示在第二个维度上进行聚合,索引为列号

运行结果:

tensor([[0.1000],
        [0.5000]])

点我详细了解torch.gather用法

代码:

def cross_entropy(y_hat,y):
    return -torch.log(y_hat.gather(1,y.view(-1,1)))

def sgd(params,lr,batch_size):
    for param in params:
        param.data -= lr*param.grad/batch_size

7.计算分类准确率

def accuracy(y_hat,y):#y_hat为预测的值,y为真实值
    print(y_hat.argmax(dim=1))#返回每行元素最大概率所在的索引,返回的结果与y形状相同
    return (y_hat.argmax(dim=1)==y).float().mean().item()

让我们继续使用在演示gather函数时定义的变量y_hat和y,并将它们分别作为预测概率分布和标签。可以看到,第一个样本预测类别为2(该行最大元素0.6在本行的索引为2),与真实标签0不一致;第二个样本预测类别为2(该行最大元素0.5在本行的索引为2),与真实标签2一致;因此,这两个样本上的分类正确概率为0.5

print(accuracy(y_hat,y))

运行结果:

tensor([2, 2])
0.5

代码:

def evaluate_accuracy(data_iter,net):
    acc_sum,n=0.0,0
    for x,y in data_iter:
#         print('net(x): ',net(x).shape,'结束')#256行10列
        acc_sum+=(net(x).argmax(dim=1)==y).float().sum().item()#.sum()不是.mean(),这是统计正确的个数,与上面不同
#         print('acc_sum: ',acc_sum)
#         print('y.shape[0]:',y.shape[0])#:y.shape[0]=256
        n+=y.shape[0]
    return acc_sum/n
print(evaluate_accuracy(test_iter,net))

运行结果:

0.8271

8.训练模型

num_epochs,lr=5,0.1
def train_ch3(net,train_iter,test_iter,loss,num_epochs,batch_size,params=None,lr=None,optimizer=None):
    for epoch in range(num_epochs):
        train_1_sum,train_acc_sum,n=0.0,0.0,0
        for x,y in train_iter:
            y_hat=net(x)
            L=loss(y_hat,y).sum()
            #梯度清零
            if optimizer is not None:
                optimizer.zero_grad()
            elif params is not None and params[0].grad is not None:
                for param in params:
                    param.grad.data.zero_()
            L.backward()
            if optimizer is None:
                sgd(params,lr,batch_size)
            else:
                optimizer.step()#softmax回归的简介实现方式
                
            train_1_sum+=L.item()
            train_acc_sum+=(y_hat.argmax(dim=1)==y).sum().item()
            n+=y.shape[0]
        test_acc=evaluate_accuracy(test_iter,net)
        print('epoch %d loss % .4f train_acc %.3f test_acc %.3f ' % (epoch+1,train_1_sum/n,
                                                                     train_acc_sum/n,test_acc))
train_ch3(net,train_iter,test_iter,cross_entropy,num_epochs,batch_size,[w,b],lr)

运行结果:

epoch 1 loss  0.7875 train_acc 0.748 test_acc 0.792 
epoch 2 loss  0.5697 train_acc 0.813 test_acc 0.812 
epoch 3 loss  0.5253 train_acc 0.825 test_acc 0.818 
epoch 4 loss  0.5011 train_acc 0.832 test_acc 0.825 
epoch 5 loss  0.4861 train_acc 0.837 test_acc 0.827 

9.预测

训练完成后,现在可以演示如何对图像进行分类了。给定一系列图像,我们比较一下他们的真实标签(第一行文本输出)和模型的结果第二行文本输出。

def get_fashion_mnist_labels(labels):
    text_labels = ['t-shirt', 'trouser', 'pullover', 'dress',
                                'coat','sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']
    return [text_labels[i] for i in labels]

#图片设置
def use_svg_display():
    """用矢量图显示svg"""
#在一行里面画出多张图像和对应标签的函数
def show_fashion_mnist(images,labels):
    use_svg_display()
    #'_'表示我们忽略,不使用的变量
    _,figs=plt.subplots(1,len(images),figsize=(25,25))#
    for f,img,lbl in zip(figs,images,labels):
        f.imshow(img.view((28,28)).numpy())
        f.set_title(lbl)
        f.axes.get_xaxis().set_visible(False)
        f.axes.get_yaxis().set_visible(False)
    plt.show()
    
x,y=iter(test_iter).next()
true_labels=get_fashion_mnist_labels(y.numpy())
pred_labels=get_fashion_mnist_labels(net(x).argmax(dim=1).numpy())
titles=[true+'\n'+pred for true,pred in zip(true_labels,pred_labels)]
show_fashion_mnist(x[0:9],titles[0:9])

运行结果:

预测结果

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值