最近老师布置了一项作业,编码实现MICD分类器,我觉得在网上找一堆类似的代码意义不大,因为编码的目的是让我们对理论知识有更深入的了解,所以应该自己写。网上别人的代码各种调用,长的甚至有几百行,没得看。刚好学过一点PyTorch,用这个框架实现矩阵和向量的计算还是很容易的。
import torch data = torch.tensor([[2,3],[3,3],[7,5],[9,4],[1,4],[8,5],[9,3],[2,2],[8,9],[6,8],[2,4],[3,2]]) label=['A','A','B','B','A','B','B','A','B','B','A','A'] test=torch.tensor([5,7])
讯享网
我先不考虑一般性的问题,数据集data是我自己设置的,样本数量也很有限,但是对初学者来说很合适。label就是标签,跟data是一一对应的。我要解决的是二分类问题,用A和B表示两个不同的类别,数据全是有标签的。test是测试样本,先只用一个样本测试吧。
讯享网#计算A类样本的均值和协方差矩阵 countA=0 meanA=torch.tensor([0,0]) sigmaA=torch.tensor([[0,0],[0,0]]) for i in range(len(data)): if label[i]=='A': countA+=1 meanA+=data[i] if countA!=0: meanA=meanA/countA for i in range(len(data)): if label[i]=='A': sigmaA=torch.mm((data[i]-meanA).reshape(2,1),(data[i]-meanA).reshape(2,1).T) if countA!=0: sigmaA=sigmaA/countA
count其实是为了计算每一类样本的数量,因为需要计算均值和协方差矩阵,所以最后要除以count。meanA就是A类样本的均值向量,初始化为零向量,扫描训练样本的时候,先把A类所有样本相加,同时统计目前A类样本的个数,最后再做除法。sigma是协方差矩阵,这个必须等均值向量计算完成后才能开始算。
我一开始没有关注到矩阵和向量的大小,所以代码跑不动。后来用了reshape()函数,统一转换成矩阵计算,比如矩阵乘法就是torch.mm(),矩阵转置就是.T,并不复杂。
#计算B类样本的均值和协方差矩阵 countB=0 meanB=torch.tensor([0,0]) sigmaB=torch.tensor([[0,0],[0,0]]) for i in range(len(data)): if label[i]=='B': countB+=1 meanB+=data[i] if countB!=0: meanB=meanB/countB for i in range(len(data)): if label[i]=='B': sigmaB=torch.mm((data[i]-meanB).reshape(2,1),(data[i]-meanB).reshape(2,1).T) if countB!=0: sigmaB=sigmaB/countB
B类样本的均值向量和协方差矩阵的计算,跟A类是一样的。
讯享网#计算协方差矩阵的逆 invA=torch.inverse(sigmaA) invB=torch.inverse(sigmaB)
因为MICD分类器是基于马氏距离的,而计算马氏距离需要用到协方差矩阵的逆,所以调用了torch.inverse()函数。
#计算马氏距离 M1A=torch.mm((test-meanA).reshape(2,1).T,invA) M2A=torch.mm(M1A,(test-meanA).reshape(2,1)) d2A=abs(torch.det(M2A)) M1B=torch.mm((test-meanB).reshape(2,1).T,invB) M2B=torch.mm(M1B,(test-meanB).reshape(2,1)) d2B=abs(torch.det(M2B)) #预测样本类别 if d2A<=d2B: print("测试样本预测为A类") else: print("测试样本预测为B类")
对马氏距离有了解的朋友,就会知道这其实是做了几次矩阵乘法而已。我是把向量转换成矩阵来计算了。abs()函数是给距离加个绝对值,保证距离非负。最后结果如下:
讯享网测试样本预测为B类
完整的代码如下:
import torch data = torch.tensor([[2,3],[3,3],[7,5],[9,4],[1,4],[8,5],[9,3],[2,2],[8,9],[6,8],[2,4],[3,2]]) label=['A','A','B','B','A','B','B','A','B','B','A','A'] test=torch.tensor([5,7]) #计算A类样本的均值和协方差矩阵 countA=0 meanA=torch.tensor([0,0]) sigmaA=torch.tensor([[0,0],[0,0]]) for i in range(len(data)): if label[i]=='A': countA+=1 meanA+=data[i] if countA!=0: meanA=meanA/countA for i in range(len(data)): if label[i]=='A': sigmaA=torch.mm((data[i]-meanA).reshape(2,1),(data[i]-meanA).reshape(2,1).T) if countA!=0: sigmaA=sigmaA/countA #计算B类样本的均值和协方差矩阵 countB=0 meanB=torch.tensor([0,0]) sigmaB=torch.tensor([[0,0],[0,0]]) for i in range(len(data)): if label[i]=='B': countB+=1 meanB+=data[i] if countB!=0: meanB=meanB/countB for i in range(len(data)): if label[i]=='B': sigmaB=torch.mm((data[i]-meanB).reshape(2,1),(data[i]-meanB).reshape(2,1).T) if countB!=0: sigmaB=sigmaB/countB #计算协方差矩阵的逆 invA=torch.inverse(sigmaA) invB=torch.inverse(sigmaB) #计算马氏距离 M1A=torch.mm((test-meanA).reshape(2,1).T,invA) M2A=torch.mm(M1A,(test-meanA).reshape(2,1)) d2A=abs(torch.det(M2A)) M1B=torch.mm((test-meanB).reshape(2,1).T,invB) M2B=torch.mm(M1B,(test-meanB).reshape(2,1)) d2B=abs(torch.det(M2B)) #预测样本类别 if d2A<=d2B: print("测试样本预测为A类") else: print("测试样本预测为B类")

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/124755.html