栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

P2:图像分类:KNN与线性分类器

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

P2:图像分类:KNN与线性分类器

自豪兄YYDS:
https://www.bilibili.com/video/BV1K7411W7So?p=2

一、kNN

KNN 从数据集中选择距离测试用例最近的K个测试用例,根据K个测试用例的类别来判断测试用例的分类。
在实际使用中是将一张图片转换为数字矩阵,对数字矩阵进行操作,一般有两种距离的选择:L1和L2距离。L1距离指的是曼哈顿距离,对于数字矩阵来说,每个位置对应的元素相减后去绝对值相加作为两个图片的L1距离。L2距离就是常用的两点之间的距离公式,对于数字矩阵也是一样操作,计算每个对应位置上的L2距离后求和作为两张图片的距离。得到所有 距离之后,再选出距离最近的K张图片,以这些图片的类别来确定待分类图片的类别。
这个分类方法十分懒惰,从实际运行过程来看,整个算法相当于没有真正意义上的训练的过程,只有一个测试的过程,但是在测试过程中会拿待测的图片去比较整个数据集的数据,也就是一次测试,访问全部数据集,开销其实并不小。
Python代码实现如下:

import numpy as np
import pickle
import os


class kNearestNeighbor:
    def __init__(self):
        pass

    def train(self, X, y):
        self.Xtr = X
        self.ytr = y
        # KNN算法中没有真正意义上的训练过程 这里只需要初始化就够了

    def predict(self, X, k=1):
        # 进行测试 找距离最近的K个临近点
        num_test = X.shape[0]
        Ypred = np.zeros(num_test, dtype=self.ytr.dtype)
        for i in range(num_test):
            distances = np.sum(np.abs(self.Xtr - X[i, :]), axis=1)
            closest_y = y_train[np.argsort(distances)[:k]]
            u, indices = np.unique(closest_y, return_inverse=True)
            # unique函数 返回去重排序后的数组和去重后元素在原数组之中的下标
            Ypred[i] = u[np.argmax(np.bincount(indices))]
            # bincount函数返回统计量 根据判断的类别确定最后的预测结果
        return Ypred


def load_Data_batch(filename):
    # 从具体文件中加载数据
    with open(filename, 'rb') as f:
        datadict = pickle.load(f, encoding='latin1')
        # 打开文件

        X = datadict['data']
        # 存储图像的信息
        Y = datadict['labels']
        # 存储图像的正确类别

        X = X.reshape(10000, 3, 32, 32).transpose(0, 2, 3, 1).astype("float")
        # 调整X的形状 一万个 3*32*32的矩阵 3表示RGB三通道 32*32表示图片的大小

        Y = np.array(Y)
        return X, Y


def load_Data(ROOT):
    # 加载数据
    xs = []
    ys = []
    for b in range(1, 6):
        # 加载全部文件
        f = os.path.join(ROOT, 'data_batch_%d' % (b))
        print('loading ' + f)
        X, Y = load_Data_batch(f)
        xs.append(X)
        ys.append(Y)
    Xtr = np.concatenate(xs)
    Ytr = np.concatenate(ys)
    # 将五个文件的数据整合到一起

    Xte, Yte = load_Data_batch(os.path.join(ROOT, 'test_batch'))
    # 加载测试集
    return Xtr, Ytr, Xte, Yte


Xtr, Ytr, Xte, Yte = load_Data('cifar10')
Xtr_rows = Xtr.reshape(Xtr.shape[0], 32 * 32 * 3)
Xte_rows = Xte.reshape(Xte.shape[0], 32 * 32 * 3)


num_training = 5000
num_test = 500
x_train = Xtr_rows[:num_training, :]
y_train = Ytr[:num_training]
x_test = Xte_rows[:num_test, :]
y_test = Yte[:num_test]
# 从训练集和测试集中选择一部分

knn = kNearestNeighbor()
knn.train(x_train, y_train)
y_predict = knn.predict(x_test, k=7)
acc = np.mean(y_predict == y_test)
print('accuracy : %f' % (acc))

PS:终于不用像大三那样用c++硬写kNN了

二、线性分类器

线性分类器是拿多个权重去与测试用例去计算,根据计算得到的结果转换为概率,用概率值来判断分类的结果。但是线性分类器对于非线性分类问题无法处理。
在几何上来看,线性分类器就是从平面上找出了一条直线,利用这条直线将二维平面的例子拆分成了两类。但是对于非线性分类问题,例子的分类不能简单的用一条直线来分类,而是需要用一条曲线来分类,这种情况下线性分类器就无用武之地了。
线性分类器的结果是一个数值,这个数值用Softmax处理过之后得到一个概率,这个概率表示的就是认为的类别的概率,一般是取概率的最大值作为最终的判断结果。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/329273.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号