小样本学习-小样本分类:KNN+Faiss【Metric Based 方法:通过度量测试集中的样本和support集中样本的距离,借助最近邻的思想完成分类】

人类本身能够通过极少量的样本识别一个新物体,即使是一个小孩也能凭借动物图册上的几张小小的插画记住不同的动物。在人类的快速学习能力的启发下,研究人员希望机器学习模型在学习了一定类别的大量数据后,对于新的类别,只需要少量的样本就能快速学习,这就是 Few-shot Learning 要解决的问题。它可以用先验知识,从受监督的经验有限的新任务中,快速得出结论。可以给小样本学习这样定义:它是一种机器学习问题,经验E在任务T上有少量的监督信息的样本情况下来获得。典型的应用有字符生成,机器人技术(一键模仿,视觉导航,连续控制),药物发现,FSL翻译,冷启动项目推荐等等。另外,FSL还可以减少标签数据的收集和减少数据密集型应用的数据收集。比如:图像分类、图像检索、目标跟踪、手势识别、图像理解、视觉问题回答、视频时间检测、语言建模和神经结构搜索等等。

最初的 few-shot learning 研究领域主要集中在图像 领域,大致可分为三类:Mode Based、Metric Based 和 Optimization Based。 

一、小样本学习概述

1、Model Based 方法  

Model Based 方法旨在通过模型结构的设计快速在少量样本上更新参数,直接建立输入 x 和预测值 P 的映射函数;

Santoro 等人 [5] 提出使用记忆增强的方法来解决 Few-shot Learning 任务。基于记忆的神经网络方法早在 2001 年被证明可以用于 meta-learning。他们通过权重更新来调节 bias,并且通过学习将表达快速缓存到记忆中来调节输出。然而,利用循环神经网络的内部记忆单元无法扩展到需要对大量新信息进行编码的新任务上。因此,需要让存储在记忆中的表达既要稳定又要是元素粒度访问的,前者是说当需要时就能可靠地访问,后者是说可选择性地访问相关的信息;另外,参数数量不能被内存的大小束缚。神经图灵机(NTMs)和记忆网络就符合这种必要条件。

文章基于神经网络图灵机(NTMs)的思想,因为 NTMs 能通过外部存储(external memory)进行短时记忆,并能通过缓慢权值更新来进行长时记忆,NTMs 可以学习将表达存入记忆的策略,并如何用这些表达来进行预测。由此,文章方法可以快速准确地预测那些只出现过一次的数据[6]。

基于 LSTM 等 RNN 的模型,将数据看成序列来训练,在测试时输入新的类的样本进行分类。具体地,在当前时刻预测输入样本的类别,并在下一时刻给出真实的 label,并且添加了 external memory 存储上一次的 x 输入,这使得下一次输入后进行反向传播时,可以让 y( label)和 x 建立联系,使得之后的 x 能够通过外部记忆获取相关图像进行比对来实现更好的预测。

2、Metric Based 方法 

Metric Based 方法通过度量 batch 集中的样本和 support 集中样本的距离,借助最近邻的思想完成分类[7];

Few-shot Learning 最大的问题就是过拟合。如果在 Few-shot Learning 的任务中去训练普通的基于 cross-entropy 的神经网络分类器,那么几乎肯定是会过拟合,因为神经网络分类器中有数以万计的参数需要优化。

相反,很多非参数化的方法(最近邻、K-NN、Kmeans)是不需要优化参数的,因此可以在 Meta-learning 的框架下构造一种可以端到端训练的 few-shot 分类器。该方法是对样本间距离分布进行建模,使得同类样本靠近,异类样本远离。

3、Optimization Based 方法 

它认为普通的梯度下降方法难以在 few-shot 场景 下拟合,因此通过调整优化方法来完成小样本分类的任务 [8]。

上述方法是 Few-shot Learning 的一些初始应用,由于这个理论相对比较新,应用暂时集中在图像分类、图像识别、文本分类等领域,应用还比较窄,这些方法只是简单介绍,事实上后面还有许多进一步的优化和更复杂的网络构建。

二、Metric Based 方法 代码实现

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import numpy as np 
from collections import Counter 
from scipy import stats
import os 
import faiss
import time 

class FaissKNNImpl:
    def __init__(self,k,faiss):
        self.k = k # k nearest neighbor value
        self.faiss = faiss # FAISS instance
        self.index = 0
        self.gpu_index_flat = 0 
        self.train_labels = []  
        self.test_label_faiss_output = [] 
        
    def fitModel(self,train_features,train_labels): 
        self.train_labels = train_labels    # 将train_labels赋值给self
        num_dim = train_features.shape[1]   # 获取数据的维度
        self.index = self.faiss.IndexFlatL2(num_dim)   # 为向量集构建IndexFlatL2索引,它是最简单的索引类型,只执行强力L2距离搜索
        self.index.add(train_features)       # add vectors to the index
        
    def fitModel_GPU(self,train_features,train_labels):
        no_of_gpus = self.faiss.get_num_gpus()
        self.train_labels = train_labels
        self.gpu_index_flat = self.index = self.faiss.IndexFlatL2(train_features.shape[1])   # build the index 
        if no_of_gpus > 0:
            self.gpu_index_flat = self.faiss.index_cpu_to_all_gpus(self.index) 
            
        self.gpu_index_flat.add(train_features)       # add vectors to the index 

        return no_of_gpus

    def predict(self,test_features): 
        distance, test_features_faiss_Index = self.index.search(test_features, self.k)
        self.test_label_faiss_output = stats.mode(self.train_labels[test_features_faiss_Index],axis=1)[0]
        self.test_label_faiss_output = np.array(self.test_label_faiss_output.ravel())
        #for test_index in range(0,test_features.shape[0]):
        #    self.test_label_faiss_output[test_index] = stats.mode(self.train_labels[test_features_faiss_Index[test_index]])[0][0] #Counter(self.train_labels[test_features_faiss_Index[test_index]]).most_common(1)[0][0] 
        return self.test_label_faiss_output
      
    def predict_GPU(self,test_features): 
        distance, test_features_faiss_Index = self.gpu_index_flat.search(test_features, self.k) 
        self.test_label_faiss_output = stats.mode(self.train_labels[test_features_faiss_Index],axis=1)[0]
        self.test_label_faiss_output = np.array(self.test_label_faiss_output.ravel())

        return self.test_label_faiss_output

    def getAccuracy(self,test_labels):
        accuracy = (self.test_label_faiss_output == test_labels).mean() 
        accuracy = round(accuracy,2) 

        return accuracy


if __name__=="__main__":
    data_dir = "raw" 
    raw_data_file = os.path.join(data_dir, "covtype.data.gz")  
    print("Reading raw data from {}".format(raw_data_file))
    raw_data = np.loadtxt(raw_data_file, delimiter=',', dtype=int)


    # 一、数据准备【Prepare Training and Test Data using 58k datapoints and 54 features】
    # 原始数据的维度为:55维,其中最后一维是分类标签

    np.random.seed(0)
    np.random.shuffle(raw_data)

    train_size = int(0.9 * raw_data.shape[0])

    train_features = raw_data[:train_size, :-1].astype('float32')
    train_labels = raw_data[:train_size, -1].astype('float32')
    test_features = raw_data[train_size:, :-1].astype('float32')
    test_labels = raw_data[train_size:, -1].astype('float32')


    # 二、Train FAISS KNN model with k = 5, 10
    k_list = [5, 10]
    for k in k_list:
        print("Training FAISS KNN model with k = {}".format(k))
        start_time = time.time()
        faissobj = FaissKNNImpl(k,faiss)
        faissobj.fitModel_GPU(train_features,train_labels)
        run_time = time.time() - start_time
        print('time required for training %d data points at k = %d: %.2f seconds' % (train_features.shape[0], k , run_time))

        start_time = time.time()
        predictions = faissobj.predict_GPU(test_features)
        run_time = time.time() - start_time
        print('time required for predicting %d data point at k = %d: %.2f seconds【平均每条数据预测用时:%.2fμs】' % (test_features.shape[0], k, run_time, run_time*1000000/test_features.shape[0]))

        accuracy = faissobj.getAccuracy(test_labels) 
        print('Accuracy for K = %d : %d' % (k, accuracy*100),'%')

        from sklearn.metrics import classification_report
        y_true = test_labels
        y_pred = predictions
        target_names = ['class 1', 'class 2', 'class 3','class 4', 'class 5', 'class 6','class 7']
        print(classification_report(y_true, y_pred, target_names=target_names)) 

https://www.cnblogs.com/huadongw/p/17032810.html

Facebook: 亿级向量相似度检索库Faiss 原理+应用_kaiyuan_sjtu的博客-CSDN博客

软件测试 | 测试开发 | 高性能高维向量的KNN搜索方案_faiss 精确 knn 检索xingn_霍格沃兹-慕漓的博客-CSDN博客

相似向量检索库-Faiss-简介及原理_金色麦田~的博客-CSDN博客

在点云中构建KNN近邻图(使用faiss库实现GPU快速计算KNN)_点云knn_Tinet-的博客-CSDN博客

Faiss - Kmeans及KNN使用示例 - AI备忘录

https://towardsdatascience.com/make-knn-300-times-faster-than-scikit-learns-in-20-lines-5e29d74e76bb 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值