Lecture2: Image Classification Pipeline

Lecture2 Image Classification Pipeline

1. 图片在计算机中的储存方式&图像识别

1.1 图片在计算机中的储存方式

    计算机中的图片有两种,位图和矢量图,其中矢量图储存的是该图片的计算方式,比如在这张图距离顶部10%,距离右边20%的地方有一个点,哪里有一条线,线有多长等等。从这里我们们可以看出,矢量图放大是没有损失的。但是位图不一样。位图储存的是像素点,也就是说把图片当作矩阵来存储。

    我们知道,红黄蓝三种颜色混合可以构成不同的颜色。因此我们可以用三个矩阵来储存一张图片,即RGB三色,我们用一个0-255的数字表示这个颜色的深度,比如说一个像素点可以是R110,G250,B120混合而成

1.2 图像识别

    图像识别顾名思义,就是把图片中的内容提取出来。从Image 到 Label。

    其实很多任务都可以归结为,给一个输入,给一个输出(或者多个输出)。也就是说,我们需要找到一个函数,这个函数在给定输入图片的像素矩阵之后,可以输出这张照片是什么,比如是一只猫。

    对于我们人类来说,看一眼就知道了,但是电脑毕竟需要我们来编程他不会自己想(起码现在不会)如何让电脑来识别猫呢?

    我们可以尝试自己写出一个函数来识别猫吗?这……有点困难。当然我们也不会这么做。我们想让计算机来自己学习出猫长什么样,就像人一样。我们是怎么知道一只动物是猫的呢?我们见过很多相似的动物(train_image)同时又有别人告诉我们这是猫(train_label)于是,当我们再见到一个动物的时候,我们可以根据之前的“训练”来判断我们面前的是不是猫。

    因此我们希望也能对计算机执行类似的操作,我们想要训练一个模型,基本步骤如下:

  • 输入:输入是包含N个图像的集合,每个图像的标签是K种分类标签中的一种。这个集合称为训练集(train_set)。
  • 学习:这一步的任务是使用训练集来学习每个类到底长什么样。一般该步骤叫做训练分类器或者学习一个模型。
  • 评价:让分类器来预测它未曾见过的图像(验证集 validation_set)的分类标签,并以此来评价分类器的质量。我们会把分类器预测的标签和图像真正的分类标签对比。毫无疑问,分类器预测的分类标签和图像真正的分类标签如果一致,那就是好事,这样的情况越多越好。

2. Nearest Neighbor 分类器

2.1 Nearest Neighbor 分类器

    我们知道,判断两张照片里面的是不是同一种生物,最简单的方法就是对比和两张图片的相似度,长得像,就应该是一个,Nearest Neighbor 分类器正是这么想的。我们首先要定义一个距离函数,来度量两张图片之间的距离,距离越近越有可能是同类。因此,我们对于一张图片,计算他和训练集所有图片之间的距离,取最近距离图片的标签来作为这张图片的标签。

2.2 KNN

    但是上面的那种方法有点不足,就是可能会出现个别特例,万一,有只狗像猫,我们送进去的猫的图片还就特别像怎么办?所以,我们改进上述方案,不只用一个了,用好多个,我们取K个离输入图片距离最近的训练图片,投票,那个label最多,就是哪个。


分类可视化的结果

2.3 超参数

    这是我们第一次面临选择,距离?图片的距离?图片有什么距离啊。我们已经知道图片在计算机中使用像素点存储,一种比较自然的想法就是,所有像素点数值相减取绝对值加和。这种距离称为L1距离(曼哈顿距离)。

  • 曼哈顿距离 Manhattan Distance(L1)
    d_1(I_1,I_2) = \sum \left|I_1^p - I_2^p \right|
  • 欧氏距离 Euclidean Distance (L2)
    d_1(I_1,I_2) =\sqrt{ \sum (I_1^p - I_2^p )^2}
       为什么叫做超参数呢,就是因为这两种哪种好其实谁都不知道,这个是试出来的有兴趣的可以试试,我给的代码里是L2距离。

    还有一个选择是K,K取多少比较合适呢?这个……自己慢慢试去吧。

2.4 数据集

数据集可以分为以下几个类:训练集(train_set),验证集(validation_set),测试集(test_set)。

  • 训练集:用来训练模型,得出参数(过一会将出现的权重)的。
  • 验证集:用来调超参数的。
  • 测试集:评估最后结果的。
       注意,训练集只是整个数据集的一部分,因为如果训练集包括了所有的数据,那么他们可能在这个数据集上表现良好,换一个就变差了,毕竟,这是用这个数据集训练出来的(过拟合)。
       但是有时候数据较少,没有那么多可以划分,这时,可以使用交叉验证。我们将一份数据分成N份,前N-1份用于训练,第N份用于验证,循环着来,取N次验证的平均值做最后结果。

3. 线性分类

3.1 开始“学习”

   从KNN中我们可以看出去,其实这个算法是没有在“学习”的,用我的话来说,KNN只是跟过往的经验来从表层判断,没有从中抽象出一般规律。这一点表现在,KNN的“训练”只是简单的把训练集输入,没有任何参数改变。我们可以想象,这种方法在处理未知图片时正确率一定不理想。我们希望从训练集中抽象出一般规律,这样可以更好地应对未知的情况。

3.2 线性分类

    我们先想下,比较理想的模型应该是什么样的,给定输入的图片矩阵,直接输出这张图片是什么,比如这张图片是狗,那就输出一个【dog】。这显然有点困难,毕竟从图片到文字人类进化了几百万年?我们简化一下问题,输入一个图片矩阵,输出一个矩阵(或者列向量)这个向量的n维代表n种类别,我们让这个模型不管怎么样,必须归一类(或者你把其中一类定成Null)。那么最简单的模型是什么样的呢?没错,就是输出列向量,是输入列向量乘上一个矩阵,也就是输出是输入的线性组合。
f(W,x_i) = W x_i + b

图示

    我们希望通过学习,定出参数矩阵W

3.3 线性回归-理解

    为什么这样可以分类呢。我们在一个二维平面上,给一堆点,我们可以使用一条直线把它分成两部分,这个时候这条直线就是y = kx + b我们与这个类似,线性回归,可以看作把这些图片映射到高维空间,在高维空间,他们是线性可分的。

例子

4. KNN实现(Python)

4.1 环境

  • Python 3.6.6
    * Numpy == 1.14.5
  • Pycharm 2018.2 Professional
  • DataSet
    * CIFAR-10 DataSet

4.2 代码

https://github.com/lisixu1999/cs231n_programs/blob/master/Lecture%201/KNN/KNN.py

# 这是KNN分类器的示例程序
# 2018-8-15

import numpy as np

par_k = 3
#定义Knn的K
path = "E:\\2017-2018 Summer Vacation\\cs231n_program\\DataSets\\"
#这是存放数据集的路径,这个数据集我自己处理过
train_images = np.reshape(np.load(path + "cifar10_images.npy"), (10000, 3 * 32 * 32))
train_labels = np.load(path + "cifar10_labels.npy")
validation_images = np.reshape(np.load(path + "cifar10_images_validation.npy"), (10000, 3 * 32 * 32))
validation_labels = np.load(path + "cifar10_labels_validation.npy")

train_images = train_labels[:10]
train_labels = train_labels[:10]
validation_images = train_labels[:10]
validation_labels = train_labels[:10]
#不想使用整个数据集做实验的可以从中选一部分,要不然根本跑不完,
#i5-5200U下跑1000就费劲了
print(train_images.shape)
print(train_labels.shape)
print(validation_images.shape)
print(validation_labels.shape)

#L1范数
def distance_l1(a, b):
    return np.sum(np.abs(a - b), axis=1)

#L2范数
def distance_l2(a, b):
    return np.sqrt(np.sum(np.power(a - b, 2)))

#定义一个正确率的计算
def accuracy(a, b):
    total = a.shape[0]
    counter = 0
    for i in range(0, total):
        if a[i] == b[i]:
            counter = counter + 1
    return counter / total

#正儿八经的代码
class KNN(object):
    def __init__(self):
        k = par_k
        pass
    #训练代码就是把数据存进去
    def train(self, train_im, train_la):
        self.tr_data = train_im
        self.tr_label = train_la
        pass
    #预测代码就是把每个距离算出来,依次比较
    def predict(self, input_vector):
        k = par_k
        round = input_vector.shape[0]
        n_train = self.tr_data.shape[0]
        dis_array = np.zeros((round, n_train))
        label_test = np.zeros(round)
        for i in range(0, round):
            for j in range(0, n_train):
                dis_array[i, j] = distance_l2(input_vector[i], self.tr_data[j])
        for i in range(0, round):
            temp = np.argsort(dis_array[i])
            temp_label = np.zeros(par_k)
            for j in range(0, par_k):
                temp_label[j] = self.tr_label[temp[j]]
            label_test[i] = np.argmax(np.bincount(temp_label.astype(int)))
        return label_test



if __name__ == "__main__":
    myknn = KNN()
    myknn.train(train_im=train_images, train_la=train_labels)
    predict_results = myknn.predict(input_vector=validation_images)
    accuracy = accuracy(predict_results, validation_labels)
    print(accuracy)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容