深度学习之卷积神经网络中常用模型评估指标(混淆矩阵，精确率，召回率，特异度计算方法)——python代码

num_classes.json为写自己数据种类的文件：

data文件夹下放置自己用来绘制混淆矩阵的数据集，数据集每一类文件夹的名称为这类数据集种类的名称即可：

lenet.pth为自己训练的模型权重，这里将这个换成你自己的模型权重即可。

main.py为绘制混淆矩阵和计算其他指标的代码，我们需要注意一下这里，修改成自己的模型类的名称。

``````from model import lenet
#自己模型类的名字叫啥，这个lenet就改成啥，
#举例，如果是alexnet，就改成from model import alexnet
#模型代码放入model.py文件中``````

main.py

``````import json
import torch
import matplotlib.pyplot as plt
from torchvision import transforms, datasets
import numpy as np
from tqdm import tqdm
from prettytable import PrettyTable

from model import lenet
#自己模型类的名字叫啥，这个lenet就改成啥，
#举例，如果是alexnet，就改成from model import alexnet
#模型代码放入model.py文件中

class Confusion_Matrix(object):

def __init__(self , labels: list):
self.num_classes = len(labels)
self.matrix = np.zeros((len(labels), len(labels)))
self.labels = labels

def Matrix_update(self, preds, labels):
for i, j in zip(preds, labels):
self.matrix[i, j] += 1

def Matrix_summary(self):

sum_TP = 0
for i in range(self.num_classes):
sum_TP += self.matrix[i, i]
accuracy = sum_TP / np.sum(self.matrix)

# "精确率", "召回率", "特异度"
table = PrettyTable()
table.field_names = ["num_classes", "Precision", "Recall", "Specificity"]
#num_classes 数据种类名称、Precision 精确率、Recall 召回率、Specificity 特异度

avaerage_Precision = []
avaerage_Recall = []
for i in range(self.num_classes):
TP = self.matrix[i, i]
FP = np.sum(self.matrix[i, :]) - TP
FN = np.sum(self.matrix[:, i]) - TP
TN = np.sum(self.matrix) - TP - FP - FN
Precision = round(TP / (TP + FP), 3) if TP + FP != 0 else 0.
avaerage_Precision.append(Precision)
Recall = round(TP / (TP + FN), 3) if TP + FN != 0 else 0.
avaerage_Recall.append(Recall)
Specificity = round(TN / (TN + FP), 3) if TN + FP != 0 else 0.
print(table)
print("模型全部种类的总体识别率： ",  accuracy)
print('平均精确率： ' , sum(avaerage_Precision)/self.num_classes)
print('平均召回率： ', sum(avaerage_Recall) / self.num_classes)

def Matrix_plot(self):
matrix = self.matrix
plt.imshow(matrix, cmap=plt.cm.Reds)
plt.xticks(range(self.num_classes), self.labels, rotation=45)
plt.yticks(range(self.num_classes), self.labels)
plt.colorbar()
plt.xlabel('真实类别')
plt.ylabel('预测类别')
plt.title('混淆矩阵')
plt.rcParams['font.sans-serif'] = ['SimHei']#设置汉语显示
plt.rcParams['axes.unicode_minus'] = False

# 在图中标注数量/概率信息
thresh = matrix.max() / 2
for x in range(self.num_classes):
for y in range(self.num_classes):
fin_matrix = int(matrix[y, x])
plt.text(x, y, fin_matrix,
verticalalignment='center',
horizontalalignment='center',
color="white" if fin_matrix > thresh else "black")
plt.tight_layout()
plt.savefig('./混淆矩阵.jpg')#保存图片到当前文件夹路径下，图片格式为jpg，也可以修改成其他格式，例如png等，根据需要自行修改即可
plt.show()

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")#gpu CUDA的使用情况
print(device)

data_transform = transforms.Compose([transforms.Resize((120, 120)),  #这里的预习处理方式最好跟你训练代码里面验证集的预处理方式保持一致，这样可以保证结果的准确性
transforms.ToTensor(),      #这里务必写成跟原数据验证集的图片预处理方式
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

image_root =  "./data"  # 画混淆矩阵图片数据路径，相对路径，绝对路径均可填写。不会填写的就放置到当前文件夹下的data文件中即可

val_data = datasets.ImageFolder(root = image_root , transform=data_transform)

net = lenet()#这里改成直接的模型类的名字

model_path = "lenet.pth"#这里写自己训练好模型的路径，直接放到当前文件夹下即可

net.to(device)

num_classes_path = './num_classes.json'#读取种类名称放置文件内数据种类的名称

json_file = open(num_classes_path, 'r',encoding='UTF-8')

nums_class = list(class_indict.keys())
nums_class.sort()

labels = [class_indict[i] for i in nums_class]
print('数据种类名称：' ,labels)

confusion = Confusion_Matrix(labels)
net.eval()
val_images, val_labels = val
outputs = net(val_images.to(device))
outputs = torch.argmax(outputs, dim=1)
confusion.Matrix_update(outputs.to("cpu").numpy(), val_labels.to("cpu").numpy())
confusion.Matrix_summary()
confusion.Matrix_plot()

``````

model.py用来放置自己模型结构的代码，这里千万要换成自己模型结构的代码

``````from torch import nn

#自己模型结构的代码就放到这里，缺什么库就导入什么库
class lenet(nn.Module):
def __init__(self):
super(lenet, self).__init__()
self.model = nn.Sequential(

nn.Conv2d(3, 16, kernel_size=5),  # input[3, 120, 120]  output[48, 55, 55]
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),  # output[48, 27, 27]

nn.Conv2d(16, 32, kernel_size=5),  # output[128, 27, 27]
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),  # output[128, 13, 13]
nn.Flatten(),
nn.Linear(23328, 2048),
nn.Linear(2048, 2048),
nn.Linear(2048, 7),

)

def forward(self, x):
x = self.model(x)
return x``````

将这里一切工作都做好之后，运行main.py文件，

如果觉得有用麻烦点个赞，有啥问题在评论中指出来，看到会回复，非常感谢支持

THE END