计算机视觉入门--图像分类简介及算法

本文介绍了计算机视觉中的图像分类任务,探讨了Nearest Neighbor和K-Nearest Neighbor两种简单算法,以及Linear Classification和卷积神经网络(CNN)在提高分类准确率上的应用。通过Python和PyTorch实现,展示了CNN如何显著提升图像分类的性能。
摘要由CSDN通过智能技术生成

简介

图像分类的任务就是给定一个图像,正确给出该图像所属的类别。对于超级强大的人类视觉系统来说,判别出一个图像的类别是件很容易的事,但是对于计算机来说,并不能像人眼那样一下获得图像的语义信息。
计算机能看到的只是一个个像素的数值,对于一个RGB图像来说,假设图像的尺寸是32*32,那么机器看到的就是一个形状为3*32*32的矩阵,或者更正式地称其为“张量”(“张量”简单来说就是高维的矩阵),那么机器的任务其实也就是寻找一个函数关系,这个函数关系能够将这些像素的数值映射到一个具体的类别(类别可以用某个数值表示)。

算法

较为简单的算法

Nearest Neighbor

"Nearest Neighbor"是处理图像分类问题一个较为简单、直接、粗暴的方法:首先在系统中“记住”所有已经标注好类别的图像(其实这就是训练集),当遇到一个要判断的还未标注的图像(也就是测试集中的某个图像)时,就去比较这个图像与“记住的”图像的“相似性”,找到那个最相似的已经标注好的图像,用那个图像的类别作为正在分类的图像的类别,这也就是"Nearest Neighbor"名称的含义。

关于如何判断图像“最相似”,可以有多种方法,比如直接求相同位置像素值的差的总和(也就是两个图像的L1距离),也可以采用两个图像的L2距离,也就是先对相同位置像素值作差并求平方,然后对所有平方值求和,最后总体开方,准确的表述如下:记图像分别为 I 1 I_1 I1 I 2 I_2 I2 I 1 k I^k_1 I1k表示图像 I 1 I_1 I1在k位置处的像素值,那么图像 I 1 I_1 I1 I 2 I_2 I2的L1和L2距离可以分别表示为:
d 1 ( I 1 , I 2 ) = ∑ k ∣ I 1 k − I 2 k ∣ d_1(I_1, I_2) = \sum_k|I^k_1 - I^k_2| d1(I1,I2)=kI1kI2k d 2 ( I 1 , I 2 ) = ∑ k ( I 1 k − I 2 k ) 2 d_2(I_1, I_2) = \sqrt{\sum_k(I^k_1 - I^k_2)^2} d2(I1,I2)=k(I1kI2k)2

"Nearest Neighbor"容易实现,但是存在诸多缺点:

  1. 预测/测试的过程太慢,给定一个图像时,需要一个个去比较训练集中的图像,每预测一次的计算量都很大,特别是图片的尺寸较大时
  2. 预测/测试时,仍需要较大的空间去存储训练集
  3. 准确率不高,实验发现,该方法在CIFAR-10上只能取得38.59%左右的正确率(其实也不算太糟糕,因为总共有10个类别,如果完全随机猜的话,正确率只有10%),其实是因为该方法没有足够的理论支撑(只有一定的道理),显然的例子是:对于一个图像,如果将其中的物体向左平移一点获得一个新的图像,则这两个图像应该是相同的类别,但是利用"Nearest Neighbor"判断时,则有可能因为相同位置的像素值不再一样而判断错误(因为L1距离和L2距离都是计算相同位置像素值的接近程度,一平移后相同位置的像素值有可能会发生很大的改变)
Nearest Neighbor的代码实现

环境:Python 3.6 + PyTorch 1.0

import torch
import torchvision


class NearestNeighbor:
    def __init__(self):
        self.x_train = 0
        self.y_train = 0
    
    # 训练阶段:存储训练集
    def train(self, x_train, y_train):
        self.x_train = x_train
        self.y_train = y_train
    
    # 测试阶段:比较待分类的图像与所有训练图像的L1距离,取最小距离的图像的类别
    def test(self, x_test):
        L1_distance = torch.sum(torch.abs(x_test - self.x_train), 1)
        min_index = torch.argmin(L1_distance)
        return self.y_train[min_index]


if __name__ == '__main__':
    # 定义要对数据集的原始数据进行的变换,此处的变换是将图像转化为Tensor
    transform = torchvision.transforms.Compose([torchvision.transforms.ToTensor()])
    # 加载数据集
    trainset = torchvision.datasets.CIFAR10(root='./', train=True, download=False, transform=transform)
    trainloader = torch.utils.data.DataLoader(trainset, batch_size=1, shuffle=False)
    testset = torchvision.datasets.CIFAR10(root='./', train=False, download=False, transform=transform)
    testloader = torch.utils.data.DataLoader(testset, batch_size=1, shuffle=False)
    # 构造一个训练集和测试集的迭代器,用于遍历
    train_iterator = iter(trainloader)
    test_iterator = iter(testloader)

    # 训练集,x_train是所有图像像素形成的Tensor,y_train是所有图像的label
    # 将每一个形状为3*32*32的图像都展开成了长度为3*32*32的行向量
    x_train = torch.zeros((len(trainset), 3 * 32 * 32))
    y_train = torch.zeros((len(trainset), 1))
    for i, (image, label) in enumerate(train_iterator):
        x_train[i] = image.reshape(-1)
        y_train[i] = label

    nn = NearestNeighbor()
    nn.train(x_train, y_train)
    # 正确预测的数目、总数目
    right_num, total_num = 0, 0
    for i, (image, label) in enumerate(test_iterator):
        predict_label = nn.test(image.reshape(1, -1))
        if predict_label.item() == label.item():
            right_num += 1
        total_num += 1
    print('Accuracy is %.2f' % (right_num / total_num * 100) + '%')

K-Nearest Neighbor

"K-Nearest Neighbor

  • 20
    点赞
  • 147
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值