tensorflow2.x针对h5模型的自定义评测(acc,召回率,精确率,混淆矩阵和混淆矩阵绘图代码)以及常用的四种图片读取方式

该博客展示了如何在TensorFlow2.x中对h5模型进行自定义评估,包括计算准确率、精确率、召回率和绘制混淆矩阵。通过读取数据、预处理、加载模型,然后计算整体和每个类别的指标,最后绘制混淆矩阵图。代码详细解释了每一步操作,适合理解模型性能和进行模型调优。
摘要由CSDN通过智能技术生成
# tensorflow2.x针对h5模型的自定义评测(acc,召回率,精确率,混淆矩阵和混淆矩阵绘图代码)
import tensorflow as tf
import numpy as np
from tqdm import tqdm
import os

# 读取数据
IMG_SIZE = (128, 128)
BATCH_SIZE = 128
test_dir = "./train"
# test_dir = "./test"

# 得到dir路径下所有文件的具体路径以及标签,file_paths_list, labels_list都是list分别对应着每个文件的具体路径和标签编号,class_names对应标签名
def load_file_paths_and_labels(dir):
    print("--> Loading file paths and labels...")
    image_format = ["bmp", "jpg", "jpeg", "png"]  # 可以读取的文件类型
    file_paths_list, labels_list, class_names = [], [], []
    for path, _, files in os.walk(dir):           # path是dir路径下每个文件夹的路径和dir文件夹本身的路径,files是每个文件夹下的文件名列表
        if path == dir: continue                  # dir本身路径不要
        for file in files:
            if file.split(".")[-1] not in image_format:           # 在mac中每个文件夹里有一个隐藏的.DS_Store,予以删除
                continue
            file_paths_list.append(os.path.join(path, file))
            labels_list.append(path.split("/")[-1])
        class_names.append(path.split("/")[-1])
    class_names.sort()                            # 标签名按照字母顺序排列
    labels_list = [class_names.index(label) for label in labels_list]
    print("<-- Loading end...(total num = %d)" % len(labels_list))
    return file_paths_list, labels_list, class_names

# 对path路径下的图片进行读取和预处理,当前针对分类问题,没有对标签进行处理,如果是检测问题,也可以对label进行处理
def load_preprosess_image(path, label):
    # 读取图片文件得到字符串
    image = tf.io.read_file(path)
    # 解码字符串得到图片
    image = tf.io.decode_image(image, channels=3)  # 彩色图像为3个channel
    # 对图片尺寸进行等比例拉伸
    image = tf.image.resize_with_pad(image, IMG_SIZE[0], IMG_SIZE[1])
    # 改变数据类型
    image = tf.cast(image, tf.float32)
    # 对图像进行归一化,归一化的方法有很多,这个是其中一种,归一化到[-1, 1]
    image = image/127.5 - 1.0
    return image, label

# 训练集:得到图片预处理类tf.data.dataset,相当于yolov4自己写的数据预处理类,但是自带的性能更好
file_paths_list, labels_list, test_labels = load_file_paths_and_labels(test_dir)       # 读取文件列表
test_dataset = tf.data.Dataset.from_tensor_slices((file_paths_list, labels_list))      # 生成dataset对象
AUTOTUNE = tf.data.experimental.AUTOTUNE                                               # 根据计算机性能进行运算速度的调整
test_dataset = test_dataset.map(load_preprosess_image, num_parallel_calls=AUTOTUNE)    # 设置数据处理函数
test_dataset = test_dataset.batch(BATCH_SIZE)                                          # 设置dataset属性,数据集顺序并未打乱
test_dataset = test_dataset.prefetch(AUTOTUNE)                                         # 预处理一部分处理,准备读取

# 读取h5模型
model = tf.keras.models.load_model("./xxx.h5")

# 计算整体的acc
loss, accuracy = model.evaluate(test_dataset)
print("last loss: {:.2f}".format(loss))
print("last accuracy: {:.2f}".format(accuracy))

###################################################################################################################
## 自定义计算acc、prs、recall和混淆矩阵 ###############################################################################
################################################################################################################### 

# 计算每个类别的acc, precision,rec和混淆矩阵
label_name = ["background", "bus", "car", "person", "rider", "truck", "two-wheeled"] 
num_prs = [0.000000001 for _ in range(len(label_name))]
num_rec = [0.000000001 for _ in range(len(label_name))]
num_mat = [[0] * len(label_name) for _ in range(len(label_name))]
label_true, label_pred = [], []
for images, labels in tqdm(test_dataset, desc='Processing'):
    pred = np.argmax(model.predict(images.numpy()), axis=1)
    for i in range(labels.numpy().size):
        num_prs[int(pred[i])] += 1
        num_rec[int(labels.numpy()[i])] += 1
        num_mat[int(labels.numpy()[i])][int(pred[i])] += 1
        label_true.append(int(labels.numpy()[i]))
        label_pred.append(int(pred[i]))

# 计算总的准确率accuracy
num1, num2, num3 = 0, 0, 0
for i in range(len(label_name)):
    num1 += num_mat[i][i]
    num2 += num_prs[i]
    num3 += num_rec[i]
assert int(num2) == int(num3)
accuracy = (num1/num2*100*100//1)/100
print("total accuracy: "+ str(accuracy))

# 计算每个类别的precision
result_prs = {}
prs = [float(num_mat[i][i])/float(num_prs[i])*100 for i in range(len(label_name))]
for i in range(len(label_name)):
    result_prs[label_name[i]] = (prs[i]*100//1)/100
print("every precision: "+ str(result_prs))

# 计算每个类别的recall
result_rec = {}
rec = [float(num_mat[i][i])/float(num_rec[i])*100 for i in range(len(label_name))]
for i in range(len(label_name)):
    result_rec[label_name[i]] = (rec[i]*100//1)/100
print("every recall:   "+ str(result_rec))

# 打印混淆矩阵
print(test_labels)
print(np.array(num_mat))


###################################################################################################################
## 绘制混淆矩阵的图 #################################################################################################
###################################################################################################################
from sklearn.metrics import confusion_matrix
import matplotlib.pyplot as plt
import numpy as np

# 绘制的接口,外部仅需要输入label_true,label_pred,test_labels
y_true = np.array(label_true)
y_pred = np.array(label_pred)
labels = test_labels

# 计算混淆矩阵
cm = confusion_matrix(y_true, y_pred)  # 矩阵原数
np.seterr(divide='ignore',invalid='ignore')                  # 防止分母为零
cm_rec = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]  # 召回率矩阵
cm_prs = cm.astype('float') / cm.sum(axis=0)[np.newaxis, :]  # 正确率矩阵

# 设置打印属性,保留两位小数,打印原数矩阵
np.set_printoptions(precision=2)
# print(cm)

# 设置plt基本属性
plt.rcParams['font.family'] = 'Times New Roman'
plt.rcParams['font.size'] = 16
plt.rcParams['font.weight'] = 'bold'
font1 = {'family':'Times New Roman', 'style':'normal', 'weight':'bold', 'color':'red', 'size':16}
font2 = {'family':'Times New Roman', 'style':'normal', 'weight':'bold', 'color':'black', 'size':16}

# 创建画板和绘图
plt.figure(figsize=(12, 10), dpi=150)
plt.imshow(cm, interpolation='nearest', cmap="Greens")
plt.colorbar()

# 向图中每个格子中填入具体数字
ind_array = np.arange(len(labels))
x, y = np.meshgrid(ind_array, ind_array)
for x_val, y_val in zip(x.flatten(), y.flatten()):
    c = cm[y_val][x_val]
    plt.text(x_val, y_val, "%d" % (c,), color='red', va='center', ha='center')

# 设置图片框、留白、分割线等属性
x_tick_marks = np.array(range(len(labels))) + 0.5
y_tick_marks = np.array(range(len(labels))) + 0.5
plt.gca().set_xticks(x_tick_marks, minor=True)
plt.gca().set_yticks(y_tick_marks, minor=True)
plt.gca().xaxis.set_ticks_position('none')
plt.gca().yaxis.set_ticks_position('none')
plt.gcf().subplots_adjust(bottom=0.3)  # 页面留白,数值太小的话,页面下面的标签显示不全
plt.grid(True, which='minor', linestyle='-')

# 设置图片周围的各种辅助文字
xlocations = np.array(range(len(labels)))
xlabels = [label + " (" + str((cm_prs[i][i]*100//1)/100) + ")" for i, label in enumerate(labels)]
ylocations = np.array(range(len(labels)))
ylabels = [label + " (" + str((cm_rec[i][i]*100//1)/100) + ")" for i, label in enumerate(labels)]
plt.xticks(xlocations, xlabels, rotation=60)
plt.yticks(ylocations, ylabels)
plt.xlabel('Predicted label', fontdict=font2)
plt.ylabel('True label', fontdict=font2)
plt.title('Confusion Matrix', fontdict=font2)

# 保存图片和展示图片
plt.savefig('./confusion_matrix.png', format='png')
plt.show()
# python和tensorflow2.x常用的四种图片读取方式
import cv2
import numpy as np
from PIL import Image
import tensorflow as tf
from tensorflow.keras.preprocessing import image_dataset_from_directory

path = "./images/car.jpg"

# no.1 opencv读取图片
image1 = cv2.imread(path).astype("float32")
image1 = cv2.cvtColor(image1, cv2.COLOR_BGR2RGB)
image1 = cv2.resize(image1, (128,128))
image1 = np.expand_dims(image1, axis=0)

# no.2 PIL读取图片
image2 = Image.open(path)
image2 = np.asarray(image2).astype("float32")
image2 = cv2.resize(image2, (128,128))
image2 = np.expand_dims(image2, axis=0)

# no.3 tf里的image_dataset_from_directory读取图片,一般使用这个读取训练集和测试集,注意文件夹下应该是只能有一幅图片,这个是用来读取数据集的
test_dataset = image_dataset_from_directory("./images/images2", labels=None, image_size=(128,128))
for image3 in test_dataset.take(1):
    image3 = image3.numpy()

# no.4 tf里的语句读取图片
image4 = tf.io.read_file(path)
image4 = tf.io.decode_jpeg(image4, channels=3, ratio=1, fancy_upscaling=True)
image4 = cv2.resize(image4.numpy().astype("float32"), (128,128))
image4 = np.expand_dims(image4, axis=0)

# 计算四种读取方式的差别
tmp12 = np.sqrt((image1-image2) * (image1-image2))
tmp13 = np.sqrt((image1-image3) * (image1-image3))
tmp14 = np.sqrt((image1-image4) * (image1-image4))
tmp34 = np.sqrt((image3-image4) * (image3-image4))

# 打印结果
print("-"*50)
print(("image1", image1.shape, image1.dtype, np.max(image1), np.min(image1), np.mean(image1)))
print(("image2", image2.shape, image2.dtype, np.max(image2), np.min(image2), np.mean(image2)))
print(("image3", image3.shape, image3.dtype, np.max(image3), np.min(image3), np.mean(image3)))
print(("image4", image4.shape, image4.dtype, np.max(image4), np.min(image4), np.mean(image4)))

print("-"*50)
print(("image1-image2", tmp12.shape, tmp12.dtype, np.max(tmp12), np.min(tmp12), np.mean(tmp12)))
print(("image1-image3", tmp13.shape, tmp13.dtype, np.max(tmp13), np.min(tmp13), np.mean(tmp13)))
print(("image1-image4", tmp14.shape, tmp14.dtype, np.max(tmp14), np.min(tmp14), np.mean(tmp14)))
print(("image3-image4", tmp34.shape, tmp34.dtype, np.max(tmp34), np.min(tmp34), np.mean(tmp34)))

# cv2.imwrite("./image1.jpg", cv2.cvtColor(image1[0], cv2.COLOR_RGB2BGR))
# cv2.imwrite("./image2.jpg", cv2.cvtColor(image2[0], cv2.COLOR_RGB2BGR))
# cv2.imwrite("./image3.jpg", cv2.cvtColor(image3[0], cv2.COLOR_RGB2BGR))
# cv2.imwrite("./image4.jpg", cv2.cvtColor(image4[0], cv2.COLOR_RGB2BGR))

# 用网络实际检测图片
print("-"*50)
label1 = ["background", "bus", "car", "person", "rider", "truck", "two-wheeled"]
label2 = ["bicycle", "bus", "car", "closed-tricycle", "forklift", "motorcycle", "open-tricycle", "person", "truck", "van"]
model = tf.keras.models.load_model("./xxx.h5")

output = model.predict(image1)
label_id = np.argmax(output[0])
pred_prob = output[0][label_id]
print("-"*50)
print((("image1", label1[label_id], pred_prob)))

output = model.predict(image2)
label_id = np.argmax(output[0])
pred_prob = output[0][label_id]
print((("image2", label1[label_id], pred_prob)))

output = model.predict(image3)
label_id = np.argmax(output[0])
pred_prob = output[0][label_id]
print((("image3", label1[label_id], pred_prob)))

output = model.predict(image4)
label_id = np.argmax(output[0])
pred_prob = output[0][label_id]
print((("image4", label1[label_id], pred_prob)))

print("-"*50)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值