【AI】斯坦福CS231n课程练习(1)—— KNN和SVM分类

一、前言

1、CS231n是啥?

  • CS231n全称是: Convolutional Neural Networks for Visual Recognition,即面向视觉识别的卷积神经网络。

2、本篇博客任务

  • 在 Google Colab 上使用 KNN 和 SVM 进行图像分类,具体细节可以查看官方要求
  • 只完成 Q1: k-Nearest Neighbor classifier 和 Q2: Training a Support Vector Machine 即可。

3、使用的数据集

  • CIFAR-10是一个非常流行的图像分类数据集,包含了60000张32X32的小图像。
  • 每张图像都有10种分类标签中的一种。
  • 这60000张图像被分为包含50000张图像的训练集和包含10000张图像的测试集。

二、知识准备

1、KNN是什么?

KNN全称——k-Nearest Neighbor分类器,它是在Nearest Neighbor的基础上改进而来:

  • Nearest Neighbor是最简单的图片分类器,它不是个神经网络,其核心思想就是计算输入图片和数据库中每一张图片的L1举例,距离近就是相似,之后它最像的那张图片的标签是什么,我们就认为这张输入图像的标签就是什么。
  • 再说k-Nearest Neighbor分类器,它找的是最相似的k个图片的标签,然后让他们针对测试图片进行投票,最后把票数最高的标签作为对测试图片的预测。
  • 所以当k=1的时候,k-Nearest Neighbor分类器就是Nearest Neighbor分类器
    在这里插入图片描述

K-Nearest Neighbor分类器的优缺点及应用场景:

  • 易于理解,实现简单。
  • 算法的训练不需要花时间,因为其训练过程只是将训练集数据存储起来。然而测试要花费大量时间计算,因为每个测试图像需要和所有存储的训练图像进行比较,这显然是一个缺点。
  • 分类器必须记住所有训练数据并将其存储起来,以便于未来测试数据用于比较。这在存储空间上是低效的,数据集的大小很容易就以GB计。
  • 在数据维度较低时,可能是不错的选择。但是在实际的图像分类工作中,很少使用。因为图像都是高维度数据(他们通常包含很多像素),而高维度向量之间的距离通常是反直觉的。

2、SVM是什么?

SVM全称——支持向量机 Support Vector Machine ,是一种二分类模型,也就是线性模型分类器。
要讲SVM,先从最简单的函数开始——一个线性映射:

在这里插入图片描述

  • 这个公式就是平时最常见到的线性函数,常为一维线性函数(即 W 为一维的)。
  • 当这种函数扩展到多维度的情况下时就是我们SVM要面临的情况。
  • 首先我们要做的处理是将每个图像数据都拉长为一个长度为D的列向量,大小为 [D * 1] 。其中大小为 [K * D] 的矩阵W和大小为 [K 1] 列向量 b 为该函数的参数。
  • 以CIFAR-10为例,CIFAR-10中一个图像的大小等于 [32323] ,含了该图像的所有像素信息,这些信息被拉成为一个 [3072 * 1] 的列向量, W 大小为 [103072] , b 的大小为 [10*1] 。
  • 因此,3072个数字(素数值)输入函数,函数输出10个数字(不同分类得到的评分)。参数 W 被称为权重(weights)。 b 被称为偏差向量(bias vector)。

举个例子,在高维度情况下,以CIFAR-10为例:

  • CIFAR-10中的图片转化成一个向量(3072维)后,就是一个高维度问题,而一个向量(3色通道转化而来)可以看作是3072维空间中的一个点,而线性分类器就是在高维度空间中的一个超平面,将各个空间点分开。如图所示:

在这里插入图片描述

  • 图像空间的示意图。其中每个图像是一个点,有3个分类器。以红色的汽车分类器为例,红线表示空间中汽车分类分数为0的点的集合,红色的箭头表示分值上升的方向。所有红线右边的点的分数值均为正,且线性升高。红线左边的点分值为负,且线性降低。
  • 目标:而我们要做的就是寻找一个W和一个b,使得这个超平面能很好的区分各个类。寻找方法就是不停的改变w和b的值,即不停的旋转平移,直到它使分类的偏差较小。
SVM的组成:
  1. 图像数据预处理:
    在上面的例子中,所有图像都是使用的原始像素值(从0到255)。在机器学习中,对于输入的特征做归一化(normalization)是必然的。在图像处理中,每个像素点可以看作是一个简单的特征,在一般使用过程中,我们都先将特征“集中”,即训练集中所有的图像计算出一个平均图像值,然后每个图像都减去这个平均值,这样图像的像素值就大约分布在[-127, 127]之间了,下一个常见步骤是,让所有数值分布的区间变为[-1, 1]。

  2. 损失函数(loss function):
    如何评判分类器的偏差就是当前的问题,解决这问题的方法就是损失函数:在这里插入图片描述
    这个函数得到的就是当前分类的偏差值。

  3. 正则化(Regularization):
    上面损失函数有一个问题。假设有一个数据集和一个权重集W能够正确地分类每个数据(即所有的边界都满足,对于所有的i都有)。

三、实验——KNN和SVM分类

本次实验的环境依然是Google Colab,我们需要把作业包导入云端环境:

  • 云端环境和本机文件目录有所区别。所以如何在代码中读Colab的文件(图片)也成为了一个问题。
  • 需要输入以下指令获取Colab的Drive网盘权限(我姑且先这么翻译)。
    在这里插入图片描述
  • 之后会提示让你输入一个权限码:在这里插入图片描述
    并将文件存放至云盘:

在这里插入图片描述

1、KNN图片分类(重要步骤将在目录上体现)

接下来的操作代码都在CoLab上运行:

(1)在colab上切换目录,加载dataset
from google.colab import drive

drive.mount('/content/drive', force_remount=True)

#这一步就是切换到作业目录,没啥好说的
# enter the foldername in your Drive where you have saved the unzipped
# 'cs231n' folder containing the '.py', 'classifiers' and 'datasets' folders.
# e.g. 'cs231n/assignments/assignment1/cs231n/'

FOLDERNAME = 'assignment1/cs231n'#这里是我自己的云盘目录
assert FOLDERNAME is not None, "[!] Enter the foldername."

%cd drive/My\ Drive
%cp -r $FOLDERNAME ../../
%cd ../../
%cd cs231n/datasets/
!bash get_datasets.sh
%cd ../../

运行成功后如下图:
在这里插入图片描述

(2)加载包、设置和外部模块


#倒入一些包和设置

# Run some setup code for this notebook.
import random
import numpy as np
from cs231n.data_utils import load_CIFAR10
import matplotlib.pyplot as plt

# This is a bit of magic to make matplotlib figures appear inline in the notebook rather than in a new window.
%matplotlib inline
plt.rcParams['figure.figsize'] = (10.0, 8.0) # set default size of plots
plt.rcParams['image.interpolation'] = 'nearest'
plt.rcParams['image.cmap'] = 'gray'

# Some more magic so that the notebook will reload external python modules;
#加载外部模块
# see http://stackoverflow.com/questions/1907993/autoreload-of-modules-in-ipython
%load_ext autoreload
%autoreload 2
(3)加载、初步处理数据
# Load the raw CIFAR-10 data.
#加载原始数据
cifar10_dir = 'cs231n/datasets/cifar-10-batches-py'

# Cleaning up variables to prevent loading data multiple times (which may cause memory issue)
#清理变量以防止多次加载数据
try:
   del X_train, y_train
   del X_test, y_test
   print('Clear previously loaded data.')
except:
   pass

X_train, y_train, X_test, y_test = load_CIFAR10(cifar10_dir)

# As a sanity check, we print out the size of the training and test data.
#作为完备性检查,我们打印出训练和测试数据的大小
print('Training data shape: ', X_train.shape)
print('Training labels shape: ', y_train.shape)
print('Test data shape: ', X_test.shape)
print('Test labels shape: ', y_test.shape)

运行成功后:
在这里插入图片描述

(4)可视化打印一些图片看看我们的数据集长什么样
# Visualize some examples from the dataset.
#可视化数据集中的一些示例
# We show a few examples of training images from each class.
#展示每个类的一些训练图像的例子

classes = ['plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
num_classes = len(classes)
samples_per_class = 7
for y, cls in enumerate(classes):
    idxs = np.flatnonzero(y_train == y)
    idxs = np.random.choice(idxs, samples_per_class, replace=False)
    for i, idx in enumerate(idxs):
        plt_idx = i * num_classes + y + 1
        plt.subplot(samples_per_class, num_classes, plt_idx)
        plt.imshow(X_train[idx].astype('uint8'))
        plt.axis('off')
        if i == 0:
            plt.title(cls)
plt.show()

在这里插入图片描述

(5)对测试、训练数据进行分组
# Subsample the data for more efficient code execution in this exercise
#对数据进行分组
num_training = 5000
mask = list(range(num_training))
X_train = X_train[mask]
y_train = y_train[mask]

num_test = 500
mask = list(range(num_test))
X_test = X_test[mask]
y_test = y_test[mask]

# Reshape the image data into rows
X_train = np.reshape(X_train, (X_train.shape[0], -1))
X_test = np.reshape(X_test, (X_test.shape[0], -1))

#打印训练集、测试集的规模
print(X_train
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值