广义学习矢量量化(GLVQ)分类算法介绍和代码实现

news/2024/4/19 4:26:49/文章来源:https://blog.csdn.net/m0_46510245/article/details/129157113

广义学习矢量量化(Generalized Learning Vector Quantization,GLVQ)是一种基于原型的分类算法,用于将输入数据分配到先前定义的类别中。GLVQ是LVQ(Learning Vector Quantization)的一种扩展形式,LVQ在特征空间中利用一组代表性原型来对输入数据进行分类。

GLVQ

GLVQ是一种监督学习算法,属于学习矢量量化(LVQ)算法的范畴。LVQ算法是一种基于原型的分类算法,它根据类与代表每个类的一组原型(也称为范例或参考向量)的距离将类分配给数据点。GLVQ通过允许类之间更灵活的决策边界来扩展LVQ,这在数据类不可线性可分时尤其有用。

GLVQ与LVQ的主要区别在于,GLVQ将类别之间的区别表示为权重矩阵,而不是在特征空间中使用距离度量。GLVQ中的权重矩阵可以从数据中学习,使得分类器可以自适应地调整权重,以便更好地区分不同的类别。此外,GLVQ还可以使用非线性映射将输入数据投影到一个新的特征空间中,这样就可以更好地处理非线性分类问题。

GLVQ可以应用于各种分类问题,尤其是在需要处理高维度数据和非线性分类问题的情况下。以下是GLVQ的一些具体应用:

  1. 模式识别:GLVQ可以用于模式识别,例如人脸识别、手写数字识别、图像分类等。通过将输入数据映射到原型向量空间,GLVQ可以在原型向量之间寻找最佳匹配,实现分类的目的。
  2. 计算机视觉:GLVQ可以用于计算机视觉领域的各种任务,例如目标检测、图像分割、物体跟踪等。GLVQ可以将输入数据投影到一个低维空间,然后利用原型向量来分类数据。
  3. 生物医学工程:GLVQ可以应用于生物医学工程领域,例如基因表达数据分析、心电信号分类等。GLVQ可以用于分析和分类复杂的生物医学数据,帮助研究人员识别疾病的特征并做出预测。
  4. 自然语言处理:GLVQ可以用于自然语言处理领域,例如文本分类、情感分析、机器翻译等。GLVQ可以通过将文本数据映射到原型向量空间来实现文本分类和情感分析等任务。

GLVQ的目标是学习一个权重矩阵,该矩阵将输入向量映射到类别空间中的向量。该映射可以通过最小化一个目标函数来学习,该目标函数将输入向量映射到它们正确的类别向量的距离最小化。

具体来说,GLVQ学习一个由原型向量组成的集合,其中每个原型向量代表一个类别。对于一个新的输入向量,GLVQ计算该向量与每个原型向量之间的距离,并将其分配给与其距离最近的原型向量所代表的类别。GLVQ可以根据分类的准确性调整原型向量的位置,以便更好地区分不同的类别。

GLVQ有许多变体,包括适应性GLVQ(Adaptive GLVQ)、增强型GLVQ(Enhanced GLVQ)和概率GLVQ(Probabilistic GLVQ),它们在权重矩阵的形式、目标函数和学习算法等方面有所不同。这些变体广泛应用于模式识别、计算机视觉、语音识别等领域,以解决各种分类问题。

数学解释和python代码

广义学习矢量量化(Generalized Learning Vector Quantization,GLVQ)的分类原理是将输入样本映射到原型向量上,并找到距离最近的原型向量,将输入样本分配给与其距离最近的原型向量所代表的类别。

在 GLVQ 中,每个类别都有一个原型向量,表示该类别在特征空间中的位置。输入样本与原型向量之间的距离可以通过欧几里得距离或曼哈顿距离等度量方法来计算。下图为二元分类的代码

 # normalize the datadefnormalization(self, input_data):minimum=np.amin(input_data, axis=0)maximum=np.amax(input_data, axis=0)normalized_data= (input_data-minimum)/(maximum-minimum)returnnormalized_data# define prototypesdefprt(self, input_data, data_labels, prototype_per_class):# prototype_labels areprototype_labels=np.unique(data_labels)prototype_labels=list(prototype_labels) *prototype_per_class# prototypes areprt_labels=np.expand_dims(prototype_labels, axis=1)expand_dimension=np.expand_dims(np.equal(prt_labels, data_labels),axis=2)count=np.count_nonzero(expand_dimension, axis=1)proto=np.where(expand_dimension, input_data, 0)prototypes=np.sum(proto, axis=1)/countself.prt_labels=prototype_labelsreturnself.prt_labels, prototypes# define euclidean distancedefeuclidean_dist(self, input_data, prototypes):expand_dimension=np.expand_dims(input_data, axis=1)distance=expand_dimension-prototypesdistance_square=np.square(distance)sum_distance=np.sum(distance_square, axis=2)eu_dist=np.sqrt(sum_distance)returneu_dist# define d_plusdefdistance_plus(self, data_labels, prototype_labels,prototypes, eu_dist):expand_dimension=np.expand_dims(prototype_labels, axis=1)label_transpose=np.transpose(np.equal(expand_dimension, data_labels))# distance of matching prototypesplus_dist=np.where(label_transpose, eu_dist, np.inf)d_plus=np.min(plus_dist, axis=1)# index of minimum distance for best matching prototypesw_plus_index=np.argmin(plus_dist, axis=1)w_plus=prototypes[w_plus_index]returnd_plus, w_plus, w_plus_index# define d_minusdefdistance_minus(self, data_labels, prototype_labels,prototypes, eu_dist):expand_dimension=np.expand_dims(prototype_labels, axis=1)label_transpose=np.transpose(np.not_equal(expand_dimension,data_labels))# distance of non matching prototypesminus_dist=np.where(label_transpose, eu_dist, np.inf)d_minus=np.min(minus_dist, axis=1)# index of minimum distance for non best matching prototypesw_minus_index=np.argmin(minus_dist, axis=1)w_minus=prototypes[w_minus_index]returnd_minus, w_minus, w_minus_index

 # define classifier functiondef classifier_function(self, d_plus, d_minus):classifier = (d_plus - d_minus) / (d_plus + d_minus)return classifier# define sigmoid functiondef sigmoid(self, x, beta=10):return (1/(1 + np.exp(-beta * x)))

GLVQ 将该样本映射到所有原型向量上,并计算每个映射结果与该输入样本的距离。然后GLVQ 将输入样本 x 分类为距离最近的原型向量所代表的类别。

 # define delta_w_plusdefchange_in_w_plus(self, input_data, prototypes, lr, classifier,w_plus, w_plus_index, d_plus, d_minus):sai= (2) * (d_minus/ (np.square(d_plus+d_minus))) * \(self.sigmoid(classifier)) * (1-self.sigmoid(classifier))expand_dimension=np.expand_dims(sai, axis=1)change_w_plus=expand_dimension* (input_data-w_plus) *lr# index of w_plusunique_w_plus_index=np.unique(w_plus_index)unique_w_plus_index=np.expand_dims(unique_w_plus_index, axis=1)add_row_change_in_w=np.column_stack((w_plus_index, change_w_plus))check=np.equal(add_row_change_in_w[:, 0], unique_w_plus_index)check=np.expand_dims(check, axis=2)check=np.where(check, change_w_plus, 0)sum_change_in_w_plus=np.sum(check, axis=1)returnsum_change_in_w_plus, unique_w_plus_index# define delta_w_minusdefchange_in_w_minus(self, input_data, prototypes, lr, classifier,w_minus, w_minus_index, d_plus, d_minus):sai= (2) * (d_plus/ (np.square(d_plus+d_minus))) * \(self.sigmoid(classifier)) * (1-self.sigmoid(classifier))expand_dimension=np.expand_dims(sai, axis=1)change_w_minus= (expand_dimension) * (input_data-w_minus) *lr# index of w_minusunique_w_minus_index=np.unique(w_minus_index)unique_w_minus_index=np.expand_dims(unique_w_minus_index, axis=1)add_row_change_in_w=np.column_stack((w_minus_index, change_w_minus))check=np.equal(add_row_change_in_w[:, 0], unique_w_minus_index)check=np.expand_dims(check, axis=2)check=np.where(check, change_w_minus, 0)sum_change_in_w_minus=np.sum(check, axis=1)returnsum_change_in_w_minus, 

可以使用下面代码绘制数据:

 # plot  datadefplot(self, input_data, data_labels, prototypes, prototype_labels):plt.scatter(input_data[:, 0], input_data[:, 2], c=data_labels,cmap='viridis')plt.scatter(prototypes[:, 0], prototypes[:, 2], c=prototype_labels,s=60, marker='D', edgecolor='k')

我们的训练代码如下:

 # fit functiondeffit(self, input_data, data_labels, learning_rate, epochs):normalized_data=self.normalization(input_data)prototype_l, prototypes=self.prt(normalized_data, data_labels,self.prototype_per_class)error=np.array([])plt.subplots(8, 8)foriinrange(epochs):eu_dist=self.euclidean_dist(normalized_data, prototypes)d_plus, w_plus, w_plus_index=self.distance_plus(data_labels,prototype_l,prototypes,eu_dist)d_minus, w_minus, w_minus_index=self.distance_minus(data_labels,prototype_l,prototypes,eu_dist)classifier=self.classifier_function(d_plus, d_minus)sum_change_in_w_plus, unique_w_plus_index=self.change_in_w_plus(normalized_data, prototypes, learning_rate, classifier,w_plus, w_plus_index,  d_plus, d_minus)update_w_p=np.add(np.squeeze(prototypes[unique_w_plus_index]), sum_change_in_w_plus)np.put_along_axis(prototypes, unique_w_plus_index,update_w_p, axis=0)sum_change_in_w_m, unique_w_minus_index=self.change_in_w_minus(normalized_data, prototypes, learning_rate, classifier,w_minus, w_minus_index, d_plus, d_minus)update_w_m=np.subtract(np.squeeze(prototypes[unique_w_minus_index]), sum_change_in_w_m)np.put_along_axis(prototypes, unique_w_minus_index, update_w_m, axis=0)err=np.sum(self.sigmoid(classifier), axis=0)change_in_error=0if (i==0):change_in_error=0else:change_in_error=error[-1] -errerror=np.append(error, err)print("Epoch : {}, Error : {} Error change : {}".format(i+1, err, change_in_error))plt.subplot(1, 2, 1)self.plot(normalized_data, data_labels, prototypes, prototype_l)plt.subplot(1, 2, 2)plt.plot(np.arange(i+1), error, marker="d")plt.pause(0.5)plt.show()accuracy=np.count_nonzero(d_plus<d_minus)acc=accuracy/len(d_plus) *100print("accuracy = {}".format(acc))self.update_prototypes=prototypesreturnself.update_prototypes

GLVQ 的训练过程是通过不断更新原型向量来进行的,这个过程可以迭代多次,直到分类结果收敛或达到指定的迭代次数为止。同时,为了防止过拟合,可以引入正则化项对原型向量的更新进行限制。

GLVQ 的数学解释相对简单,但需要注意的是,不同的距离度量方法、学习率调度方法和正则化项都会对算法的性能产生影响,需要根据具体问题进行选择和调整。

预测数据:

 # data predictdefpredict(self, input_value):input_value=self.normalization(input_value)prototypes=self.update_prototypeseu_dist=self.euclidean_dist(input_value, prototypes)m_d=np.min(eu_dist, axis=1)expand_dims=np.expand_dims(m_d, axis=1)ylabel=np.where(np.equal(expand_dims, eu_dist),self.prt_labels, np.inf)ylabel=np.min(ylabel, axis=1)print(ylabel)returnylabel

需要注意的是,GLVQ 的分类结果不一定是唯一的,因为在一些情况下,输入样本可能与多个原型向量的距离相等。为了解决这个问题,可以引入一些规则来确定分类结果,例如优先将输入样本分配给更接近的原型向量所代表的类别,或根据原型向量所代表的类别的先验概率分布来确定分类结果。

Pytorch实现

上面我们介绍的是python的实现,下面我们尝试使用pytorch来实现这个过程(注意:这里是根据原理编写,不保证100%正确,如果发现问题请留言指出)

在 PyTorch 中实现 GLVQ 的方法,主要分为以下几步:

  1. 准备数据:需要准备训练集和测试集的数据,并进行数据预处理,例如标准化、归一化等操作,以便进行训练和测试。
  2. 定义模型:需要定义 GLVQ 模型,包括原型向量、距离度量、更新规则等。在 PyTorch 中,可以通过自定义 nn.Module 类来实现 GLVQ 模型,其中包括前向传播和反向传播的方法。
  3. 定义损失函数:GLVQ 的损失函数通常采用类间距离最小化和类内距离最大化的原则,可以通过自定义 nn.Module 类来实现 GLVQ 的损失函数,其中包括计算损失值和反向传播的方法。
  4. 训练模型:需要利用训练集对 GLVQ 模型进行训练,并在测试集上进行测试。在 PyTorch 中,可以使用标准的训练和测试流程来训练和测试 GLVQ 模型。
 importtorchimporttorch.nnasnnclassGLVQ(nn.Module):def__init__(self, num_prototypes, input_size, output_size):super(GLVQ, self).__init__()self.num_prototypes=num_prototypesself.input_size=input_sizeself.output_size=output_sizeself.prototypes=nn.Parameter(torch.randn(num_prototypes, input_size))self.output_layer=nn.Linear(num_prototypes, output_size)defforward(self, x):distances=torch.cdist(x, self.prototypes)activations=-distances.pow(2)outputs=self.output_layer(activations)returnoutputsclassGLVQLoss(nn.Module):def__init__(self, prototype_labels, prototype_lambda):super(GLVQLoss, self).__init__()self.prototype_labels=prototype_labelsself.prototype_lambda=prototype_lambdadefforward(self, outputs, targets):distances=torch.cdist(outputs, self.prototype_labels)class_distances=torch.gather(distances, 1, targets.unsqueeze(1))other_distances=distances.clone()other_distances[torch.arange(outputs.size(0)), targets] =float('inf')other_class_distances, _=other_distances.min(1)loss=torch.mean(class_distances-other_class_distances+self.prototype_lambda*distances.pow(2))returnloss# Trainingmodel=GLVQ(num_prototypes=10, input_size=784, output_size=10)criterion=GLVQLoss(prototype_labels=torch.tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), prototype_lambda=0.1)optimizer=torch.optim.SGD(model.parameters(), lr=0.01)forepochinrange(10):fori, (inputs, labels) inenumerate(train_loader):optimizer.zero_grad()outputs=model(inputs.view(inputs.size(0), -1))loss=criterion(outputs, labels)loss.backward()

上述代码实现了一个 GLVQ 模型,其中包含了一个原型向量矩阵 W,每一行表示一个类别的原型向量。训练过程中,输入样本 x 通过计算与每个类别的原型向量之间的距离来进行分类,并将其分配给与其距离最近的原型向量所代表的类别。然后,根据分类结果和样本真实标签之间的误差来更新原型向量,使其向输入样本的方向移动。这样,通过不断更新原型向量,GLVQ 可以学习到特征空间中不同类别之间的边界,并用于分类新的输入样本。

主要说明下GLVQLoss :具体而言,假设输入样本 x 分配给类别 c_{min},则 GLVQ 损失可以表示为:

其中 W_{c_{min}} 和 W_{c_{not min}} 分别表示输入样本 x 分配给的类别和未分配给的其他类别的原型向量,||\cdot||_2 表示欧几里得范数。该损失表示了输入样本 x 与其正确类别原型向量之间的距离与其他类别原型向量之间距离之差,即正确类别的原型向量应该更接近输入样本 x。GLVQLoss 是一个带有动态原型向量矩阵的损失函数,它可以根据输入样本和当前的原型向量矩阵来计算损失,并使用梯度下降算法来更新原型向量。

总结

综上所述,广义学习向量量化(GLVQ)是一种强大而灵活的基于原型的分类算法,可以处理非线性可分类。通过允许更灵活的决策边界,GLVQ可以在许多分类任务上实现更高的精度。

总的来说,GLVQ提供了一种独特而强大的分类方法,其处理非线性可分离数据的能力使其成为可用的分类算法集的一个有价值的补充。

https://avoid.overfit.cn/post/d5792b8b6f324ab184fbdfd5aefdbc28

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_72387.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

性能分析之vmstat工具

vmstat 工具的使用 命令&#xff1a;vmstat 1 60> /tmp/cpu.txt 说明&#xff1a;每秒采样 1 次&#xff0c;共采集 100 次 格式化显示&#xff1a;cat /tmp/cpu.txt|column -t &#xff08;1&#xff09;procs r&#xff1a; 表示运行和等待 CPU 时间片的进程数&#xff0…

go进阶(1) -深入理解goroutine并发运行机制

并发指的是同时进行多个任务的程序&#xff0c;Web处理请求&#xff0c;读写处理操作&#xff0c;I/O操作都可以充分利用并发增长处理速度&#xff0c;随着网络的普及&#xff0c;并发操作逐渐不可或缺 一、goroutine简述 在Golang中一个goroutines就是一个执行单元&#xff…

多种调度模式下的光储电站经济性最优储能容量配置分析(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Crafting interpreters 中文翻译(全),持续修正

本书在线地址 http://craftinginterpreters.com/ 感谢作者 作者用近 4 年的时间持续创作和改进本书&#xff0c;并把其 Web 版本公开在网上。这本纸质书于今年 7 月出版&#xff0c;立刻在 Hacker News 等网络媒介上引起关注和讨论。 书中作者首先定义了一个动态类型的语言 …

23年PMP真的值得考吗?分析+资料分享

我觉得&#xff0c;如过是真的想学习项目管理&#xff0c;或者工作要求考PMP&#xff0c;招聘要求又的确“PMP证书”优先&#xff0c;那考一个是划算的&#xff0c;毕竟在项目管理这一块&#xff0c;PMP是专业和知名度最高的证书了。 它是由美国项目管理协会(PMI)在全球范围内推…

数组-二分查找-搜索插入位置/在排序数组中查找元素的第一个和最后一个位置/x 的平方根/有效的完全平方数

二分查找 35搜索插入位置 https://leetcode.cn/problems/search-insert-position/submissions/ class Solution:def searchInsert(self, nums: List[int], target: int) -> int:l 0r len(nums)-1# // 整数除法 int /浮点数除法while(l<r):mid l (r - l)//2if nums…

二叉树——找树左下角的值

找树左下角的值 链接 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 示例 1: 输入: root [2,1,3] 输出: 1 示例 2: 输入: [1,2,3,4,null,5,6,null,null,7] 输出: 7 递归法 二叉树的 最底层 最左…

一维,二维差分の详解(简单易懂)

一,差分定义差分,就是前缀和的逆运算。二,具体过程1.一维差分例题构造差分数组首先给定一个原数组a&#xff1a;a[1], a[2], a[3],,,,,, a[n];然后我们构造一个数组b &#xff1a; b[1], b[2], b[3],,,,,, b[i];使得 a[i] b[1] b[2] b[3] ,,,,,, b[i]也就是说&#xff0c;…

Redis分布式锁实现及使用

文章目录分布式锁全局ID生成器一人一单实现超卖问题一人一单分布式锁Redis setnx实现分布式锁Redis在业内解决秒杀等业务场景有非常广的应用&#xff0c;如何设计实现一个分布式锁是解决超卖、一人一单问题非常重要… 分布式锁 分布式锁是控制分布式系统之间同步访问共享资源的…

CRM客户管理系统的作用和四大优势

CRM系统是一种以客户管理为核心&#xff0c;帮助营销、销售、服务部门实现业务自动化&#xff0c;为企业进行客户数据的收集、管理和分析&#xff0c;提高客户体验和留存&#xff0c;实现以客户为中心的管理模式的企业管理工具。那么&#xff0c;企业为什么要使用CRM系统&#…

Javaweb之mybits入门

2.1 Mybatis概述 2.1.1 Mybatis概念 MyBatis 是一款优秀的持久层框架&#xff0c;用于简化 JDBC 开发 MyBatis 本是 Apache 的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code&#xff0c;并且改名为MyBatis 。2013年11月迁移到Github …

XSS注入进阶练习篇(三) XSS原型链污染

XSS原型链污染1.原型链的概念1.1 构造函数的缺点1.2 prototype 属性的作用1.3 原型链1.4 constructor属性1.5 prototype和__proto__2. 原型链污染2.1 原型链污染是什么&#xff1f;2.2 原型链污染的条件2.3 原型连污染实例2.3.1 hackit 20182.3.2 challenge-04223.总结1.原型链…

新项目分析

1&#xff1a;数据类型处理 # sep‘\s‘ 这是正则表达式&#xff0c;通过一定规则的表达式来匹配字符串用的 \s 表示空白字符&#xff0c;包括但不限于空格、回车(\r)、换行(\n)、tab或者叫水平制表符(\t)等&#xff0c;这个根据编码格式不同代表的含义也不一样&#xff0c;感…

Codeforces Round #851 (Div. 2) A-E

题目链接&#xff1a;https://codeforces.com/contest/1788 A - One and Two 解题思路&#xff1a;将数组分成两半&#xff0c;两边二一样多就行了。 #include<bits/stdc.h> using namespace std; #define inf 0x3f3f3f3f #define lson l,mid,rt<<1 #define rso…

Kaggle系列之识别狗的品种类别(深度残差网络模型ResNet-34)

我们来到这个比赛页面&#xff1a;https://www.kaggle.com/competitions/dog-breed-identification这个数据集的目标是Determine the breed of a dog in an image(确定图像中狗的品种)我们先下载数据集解压之后来看下(当然不手动解压&#xff0c;也可以使用)&#xff0c;这里我…

记住这12个要点,你也能打造出让HR和技术主管前一亮的前端简历

第一篇章&#xff1a;吸引HR 如果你想在众多简历中脱颖而出&#xff0c;需要注意以下几点&#xff1a; 1、突出你的亮点&#xff1a; 给你的简历一个吸引人的文件命名和头部&#xff0c;突出你的关键技能和经验。 2、采用简洁的语言&#xff1a; 用简单易懂的语言来描述你的…

笔记本cpu温度多少正常?温度过高的4个常见原因

电脑CPU指的是中央处理器&#xff0c;它与电脑运行速度的快慢存在很大关系。如果电脑的处理器温度过高&#xff0c;就会影响我们电脑的运行速度&#xff0c;甚至出现蓝屏、卡顿的情况。 那么&#xff0c;对于电脑来说&#xff0c;笔记本cpu温度多少正常&#xff1f;有什么原因…

macOS Big Sur 11.7.4(20g1220)With OpenCore 0.8.9正式版 and winPE双引导分区原版镜像

原文来源于黑果魏叔官网&#xff0c;转载需注明出处。镜像特点完全由黑果魏叔官方制作&#xff0c;针对各种机型进行默认配置&#xff0c;让黑苹果安装不再困难。系统镜像设置为双引导分区&#xff0c;全面去除clover引导分区&#xff08;如有需要&#xff0c;可以自行直接替换…

KT1025A蓝牙音频芯片_立讯KC认证FCC测试现场整改记录

目录 一、问题说明简介 测试机构立讯反馈&#xff0c;客户寄的样板进行无线KC【韩国】测试不过&#xff0c;体现在如下两点 蓝牙部分接收杂散不过 蓝牙的发射功率偏低 2.1 单独只给蓝牙部分供电的测试图片--OK 2.2 单独给整板供电--但是使用电池供电 2.3 单独给整板供电-…

关于机器人坐标系变换的笔记

ROS TFros中&#xff0c;可以通过TF Tree来进行获取 机器人不同坐标系之间的转换关系&#xff0c;命令如下&#xff1a;rosrun tf tf_echo base_link head_link1意思为&#xff0c;从源坐标系base_link&#xff0c;到目标坐标系head_link1的变换关系&#xff0c;结果如下所示。…