MICD分类器原来这样就能实现

最近老师布置了一项作业,编码实现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类")

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值