18.3:tensorflow分类模型mobilenetv2训练(数据增强,保存模型,衰减学习率,tensorboard),预测图像(单张,批量预测),导出为pb完整示例

三、生成pb文件并预测。

他查阅资料发现,生成pb文件需要三个文件,也就是model_save中保存的。如:

此外,还需要知道输入节点,输出节点的名称。然而在他的训练的代码中并不好找到哪个是输入节点,在tensorboard的结构图中也没有找到。

但他又想了一个方法,从保存的模型中再加载一次模型,并建立一个输入,输出节点,然后再保存。于是他写了这个ckpt_to_pd.py文件:

save_new_ckpt函数可以加入新的输入节点(input_1),输出节点(softmax_out)。

把model.ckpt-250000模型加载后,重新编辑加入输入输出节点后,再保存为modelnew.ckpt,会生成3个新文件。再使用这3个文件根据函数freeze_graph生成pb文件。

print_pb函数可以打印生成的pb文件中参数名字及尺寸。

#coding:utf-8

import tensorflow as tf
from tensorflow.python.framework import graph_util

import model


label_dict, label_dict_res = {}, {}
# 手动指定一个从类别到label的映射关系
with open("label.txt", 'r') as f:
    for line in f.readlines():
        folder, label = line.strip().split(':')[0], line.strip().split(':')[1]
        label_dict[folder] = label
        label_dict_res[label] = folder
print(label_dict)

IMG_W = 224
N_CLASSES = len(label_dict)

def print_pb(output_graph_path):
    tf.reset_default_graph()  # 重置计算图
    sess = tf.Session()
    sess.run(tf.global_variables_initializer())
    output_graph_def = tf.GraphDef()
    # 获得默认的图
    graph = tf.get_default_graph()
    with open(output_graph_path, "rb") as f:
        output_graph_def.ParseFromString(f.read())
        _ = tf.import_graph_def(output_graph_def, name="")
        # 得到当前图有几个操作节点
        print("%d ops in the final graph." % len(output_graph_def.node))
        #tensor_name = [tensor.name for tensor in output_graph_def.node]
        #print(tensor_name)
        print('---------------------------')
        for op in graph.get_operations():
            # print出tensor的name和值
            print(op.name, op.values())
    sess.close()


def save_new_ckpt(logs_train_dir, newckpt):
    x = tf.placeholder(tf.float32, shape=[None, IMG_W, IMG_W, 3], name="input_1")
    # predict
    logit = model.MobileNetV2(x, num_classes=N_CLASSES, is_training=False).output
    #logit = model.model4(x, N_CLASSES, is_trian=False)
    #logit = model.model2(x_4d, batch_size=1, n_classes=N_CLASSES)
    pred = tf.nn.softmax(logit, name="softmax_out")

    saver = tf.train.Saver()
    sess = tf.Session()
    saver.restore(sess, logs_train_dir)
    print("load model done...")
    saver.save(sess, newckpt)
    sess.close()
    print('save new model done...')


def freeze_graph(input_checkpoint, output_graph):
    # 指定输出的节点名称,该节点名称必须是原模型中存在的节点
    output_node_names = ["input_1", "softmax_out"]
    saver = tf.train.import_meta_graph(input_checkpoint + '.meta', clear_devices=True)
 
    with tf.Session() as sess:
        saver.restore(sess, input_checkpoint) #恢复图并得到数据
        output_graph_def = graph_util.convert_variables_to_constants(  # 模型持久化,将变量值固定
            sess=sess,
            input_graph_def=sess.graph_def, # 等于:sess.graph_def
            output_node_names=output_node_names)
 
        with tf.gfile.GFile(output_graph, "wb") as f: #保存模型
            f.write(output_graph_def.SerializeToString()) #序列化输出
        print("%d ops in the final graph." % len(output_graph_def.node)) #得到当前图有几个操作节点


if __name__ == "__main__":
    model_path = './model_save/model.ckpt-250000'
    new_model_path = './model_save/modelnew.ckpt'
    pb_model = "model_tf.pb"
    save_new_ckpt(model_path, new_model_path)
    freeze_graph(new_model_path, pb_model)
    print_pb(pb_model)

使用.pb模型进行预测:

有了model_tf.pb文件后,也知道了输入,输出节点了。之后就可以无需定义网络结构就可以直接进行预测了,使用比较方便。

调用pb文件并进行预测的代码为predict_pb.py:

#coding:utf-8
import os, cv2
import numpy as np
import tensorflow as tf
import glob

from tensorflow.python.platform import gfile


config = tf.ConfigProto()
config.gpu_options.allow_growth = True
os.environ["CUDA_VISIBLE_DEVICES"] = "0"  # use gpu 0

label_dict, label_dict_res = {}, {}
with open("label.txt", 'r') as f:
    for line in f.readlines():
        folder, label = line.strip().split(':')[0], line.strip().split(':')[1]
        label_dict[folder] = label
        label_dict_res[label] = folder
print(label_dict)

N_CLASSES = len(label_dict)
IMG_W = 224
IMG_H = IMG_W

def init_tf():
    global sess, pred, x
    sess = tf.Session(config=config)
    with gfile.FastGFile('./model_tf.pb', 'rb') as f:
        graph_def = tf.GraphDef()
        graph_def.ParseFromString(f.read())
        sess.graph.as_default()
        tf.import_graph_def(graph_def, name='')

    # 获取输入tensor
    x = tf.get_default_graph().get_tensor_by_name("input_1:0")
    print("input:", x)
    # 获取预测tensor
    pred = tf.get_default_graph().get_tensor_by_name("softmax_out:0")  #mobilenet_v2
    print('load model done...')

def evaluate_image(img_dir):
    # read and process image
    image = cv2.imread(img_dir)
    image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
    # pre-process the image for classification
    image = cv2.resize(image, (IMG_W, IMG_W))
    #image = image.astype("float") / 255.0
    im_mean = np.mean(image)
    stddev = max(np.std(image), 1.0/np.sqrt(IMG_W*IMG_W*3))
    image = (image - im_mean) / stddev #代替tf.image.per_image_standardization
    #image_array = np.array(image)
    image = np.expand_dims(image, axis=0)

    prediction = sess.run(pred, feed_dict={x: image})
    max_index = np.argmax(prediction)
    pred_label = label_dict_res[str(max_index)]
    print("%s, predict: %s(index:%d), prob: %f" %(img_dir, pred_label, max_index, prediction[0][max_index]))
    

if __name__ == '__main__':
    init_tf()
    data_path = "/media/DATA2/sku_val"
    label = os.listdir(data_path)
    for l in label:
        if os.path.isfile(os.path.join(data_path, l)):
            continue
        for img in glob.glob(os.path.join(data_path, l, "*.jpg")):
            evaluate_image(img_dir=img)
    sess.close()

至于如何修改为批量预测,根据上一个博客18.2修改把。。。

利用混淆矩阵计算准确率和召回

#coding:utf-8
import os, cv2
import numpy as np
import shutil
import glob
import tqdm
import matplotlib.pyplot as plt
from tensorflow.python.platform import gfile
import tensorflow as tf


os.environ["CUDA_VISIBLE_DEVICES"] = "0"  # use gpu 0
config = tf.ConfigProto()
#config.gpu_options.allow_growth = True
config.gpu_options.per_process_gpu_memory_fraction = 0.2

label_dict, label_dict_res = {}, {}
with open("label.txt", 'r') as f:
    for line in f.readlines():
        folder, label = line.strip().split(':')[0], line.strip().split(':')[1]
        label_dict[folder] = label
        label_dict_res[label] = folder
print(label_dict)

N_CLASSES = len(label_dict)
IMG_W = 224
IMG_H = IMG_W


def mkdir(path, rm=False):
    if os.path.exists(path):
        if rm:
            shutil.rmtree(path)
            os.mkdir(path)
    else:
        os.mkdir(path)


def save_conf_mat(confusion_mat, classes):
    # 归一化
    confusion_mat_N = confusion_mat.copy()
    for i in range(len(classes)):
        confusion_mat_N[i, :] = confusion_mat[i, :] / (confusion_mat[i, :].sum() + 1e-9)

    # 获取颜色
    fig=plt.figure(figsize=(35, 35))
    cmap = plt.cm.get_cmap('Greys')  # 更多颜色: http://matplotlib.org/examples/color/colormaps_reference.html
    plt.imshow(confusion_mat_N, cmap=cmap)
    plt.colorbar()

    # 设置文字
    xlocations = np.array(range(len(classes)))
    plt.xticks(xlocations, list(classes), rotation=30)
    plt.yticks(xlocations, list(classes))
    plt.xlabel('Predict label')
    plt.ylabel('True label')
    plt.title('result')

    # 打印数字
    for i in range(confusion_mat_N.shape[0]):
        for j in range(confusion_mat_N.shape[1]):
            plt.text(x=j, y=i, s=int(confusion_mat[i, j]), va='center', ha='center', color='red', fontsize=10)
    # 保存
    plt.savefig('result.png')
    plt.close()
    print("save result.png")


def init_tf():
    global sess, pred, x
    sess = tf.Session(config=config)
    with gfile.FastGFile('./model.pb', 'rb') as f:
        graph_def = tf.GraphDef()
        graph_def.ParseFromString(f.read())
        sess.graph.as_default()
        tf.import_graph_def(graph_def, name='')

    # 获取输入tensor
    x = tf.get_default_graph().get_tensor_by_name("input_1:0")
    print("input:", x)
    # 获取预测tensor
    pred = tf.get_default_graph().get_tensor_by_name("softmax_out:0")  #mobilenet_v2
    print('load model done...')

def evaluate_image(image):
    # read and process image
    #image = cv2.imread(img_dir)
    image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
    # pre-process the image for classification
    image = cv2.resize(image, (IMG_W, IMG_W))
    #image = image.astype("float") / 255.0
    im_mean = np.mean(image)
    stddev = max(np.std(image), 1.0/np.sqrt(IMG_W*IMG_W*3))
    image = (image - im_mean) / stddev #代替tf.image.per_image_standardization
    #image_array = np.array(image)
    image = np.expand_dims(image, axis=0)

    prediction = sess.run(pred, feed_dict={x: image})
    max_index = np.argmax(prediction)
    pred_label = label_dict_res[str(max_index)]
    print("%s, predict: %s(index:%d), prob: %f" %(img_dir, pred_label, max_index, prediction[0][max_index]))
    return pred_label, prediction[0][max_index]
    

if __name__ == '__main__':
    init_tf()
    output = "error_result"
    f = open("result.txt", "w")
    mkdir(output, rm=True)
    data_path = "/media/lishundong/DATA2/docker/data/sku_for_classify2/sku_val"
    #data_path = "/media/lishundong/DATA2/docker/data/sku_for_classify2/sku_val_small"
    #data_path = "/media/lishundong/DATA2/docker/data/sku_for_classify2/sku_train"
    label = os.listdir(data_path)
    cls_num = N_CLASSES
    conf_mat = np.zeros([cls_num, cls_num])
    for l in tqdm.tqdm(label):
        if os.path.isfile(os.path.join(data_path, l)):
            continue
        for img_dir in glob.glob(os.path.join(data_path, l, "*.jpg")):
            img = cv2.imread(img_dir)
            pre_label, prob = evaluate_image(img)
            if l != pre_label:
                save_badcase_dir = os.path.join(output, pre_label)
                mkdir(save_badcase_dir, rm=False)
                shutil.copyfile(img_dir, save_badcase_dir + "/" + os.path.basename(img_dir))
            index_l = int(label_dict[l])
            index_pre_label = int(label_dict[pre_label])
            conf_mat[index_l, index_pre_label] += 1.0
    for i in range(cls_num):
        cls = label_dict_res[str(i)]
        gt_num_this_cls = max(1e-9, np.sum(conf_mat[i, :]))
        predict_right = np.sum(conf_mat[i, i])
        predict_this_cls = max(1e-9, np.sum(conf_mat[:, i]))
        precise = predict_right / predict_this_cls
        recall = predict_right / gt_num_this_cls
        log = 'class:{:<5} total num:{:<5} right num:{:<5} Precision: {:.2%}({}/{})  Recall: {:.2%}({}/{})'.format(cls, int(gt_num_this_cls), int(predict_right), precise, int(predict_right), int(predict_this_cls), recall, int(predict_right), int(gt_num_this_cls))
        print(log)
        f.write(log + "\n")
    log = 'All accuracy:{:.2%}({}/{})'.format(np.trace(conf_mat) / np.sum(conf_mat), int(np.trace(conf_mat)), np.sum(conf_mat))
    print(log)
    f.write(log)
    save_conf_mat(conf_mat, [label_dict_res[str(index)] for index in range(cls_num)])
    sess.close()

显示:

class:10    total num:336   right num:335   Precision: 99.70%(335/336)  Recall: 99.70%(335/336)
class:104   total num:703   right num:703   Precision: 100.00%(703/703)  Recall: 100.00%(703/703)
class:105   total num:498   right num:497   Precision: 100.00%(497/497)  Recall: 99.80%(497/498)
class:106   total num:558   right num:558   Precision: 99.11%(558/563)  Recall: 100.00%(558/558)
class:11    total num:135   right num:135   Precision: 100.00%(135/135)  Recall: 100.00%(135/135)
class:112   total num:324   right num:324   Precision: 99.69%(324/325)  Recall: 100.00%(324/324)
class:113   total num:436   right num:436   Precision: 100.00%(436/436)  Recall: 100.00%(436/436)
class:114   total num:499   right num:498   Precision: 100.00%(498/498)  Recall: 99.80%(498/499)
......

 

下一篇:使用nvidia的tensorrt加速.pb文件https://blog.csdn.net/u010397980/article/details/86382849

### 回答1: MobileNetV2是一种用于图像分类和目标检测的轻量级卷积神经网络模型,PyTorch是一种常用的深度学习框架,而ONNX是一种用于模型的开放式神经网络交换格式。 在PyTorch中使用MobileNetV2进行训练,可以通过加载预训练模型,并进行微调来实现。我们可以使用PyTorch提供的torchvision模块来加载MobileNetV2模型的预训练权重,然后将数据集导入模型进行训练训练过程中,我们可以使用交叉熵损失函数和随机梯度下降(SGD)优化器。通过迭代训练数据集,不断更新模型的权重参数,使模型能够应对新的输入数据。 训练完成后,我们可以将PyTorch模型转换为ONNX格式,以便在其他平台上使用。在PyTorch中,可以使用torch.onnx.export()函数将模型转换为ONNX格式。此函数需要指定输入张量的形状和文件路径,以保存转换后的模型。 使用ONNX格式的模型,可以在不同的深度学习框架(如TensorFlow)或硬件平台上进行推理和部署。通过将模型转换为ONNX格式,可以实现更好的跨平台兼容性,并加速模型的部署过程。 总之,使用PyTorch训练MobileNetV2模型,并将其转换为ONNX格式,可以提供一种灵活而高效的方式,用于图像分类和目标检测任务,并实现跨平台部署的便利性。 ### 回答2: MobileNetV2是一种轻量级的卷积神经网络,适用于移动设备和嵌入式系统。PyTorch是一个流行的深度学习框架,提供了训练和部署模型的功能。而ONNX是一种开放的中间表示格式,可以在不同的深度学习框架之间共享模型。 要使用PyTorch训练MobileNetV2模型并将其转换为ONNX格式,可以按照以下步骤进行。 首先,需要导入所需的PyTorch和ONNX库: ```python import torch import torchvision.models as models import onnx ``` 然后,加载MobileNetV2模型并进行训练,可以使用PyTorch提供的预训练模型或自定义训练数据集来进行训练训练过程可以根据具体任务进行配置,包括选择优化器、损失函数和训练迭代次数等。 训练完成后,可以将模型保存为PyTorch的.pth文件: ```python torch.save(model.state_dict(), 'mobilenetv2.pth') ``` 接下来,使用ONNX库将.pth文件转换为ONNX格式: ```python dummy_input = torch.randn(1, 3, 224, 224) # 定义一个虚拟输入作为示例 model = models.mobilenet_v2(pretrained=True) # 加载预训练模型 model.load_state_dict(torch.load('mobilenetv2.pth')) # 加载训练权重 torch.onnx.export(model, dummy_input, 'mobilenetv2.onnx', verbose=True) # 导出为ONNX模型 ``` 最后,将训练和转换得到的.onnx文件用于推理和部署。可以使用ONNX Runtime或其他支持ONNX格式的推理框架加载和运行模型。 通过以上步骤,我们可以使用PyTorch训练MobileNetV2模型,并将其转换为ONNX格式,以实现模型的跨框架和跨平台应用。 ### 回答3: MobileNetV2是一种轻量级的神经网络架构,适用于移动设备等资源受限的环境下进行图像分类任务。PyTorch是一种深度学习框架,具有易用性和高效性,训练神经网络模型时是使用PyTorch进行的。 ONNX是一种开放的深度学习模型格式,能够在不同的深度学习框架之间进行模型的互操作性。将MobileNetV2模型训练为ONNX格式,可以使得该模型能够运行在不同的深度学习框架中,而不仅仅局限于PyTorch。 要将MobileNetV2模型训练为ONNX格式,可以按照以下步骤进行: 1. 准备训练数据集:使用包含图像和对应标签的数据集进行训练,例如ImageNet数据集。 2. 定义并训练MobileNetV2模型:使用PyTorch定义MobileNetV2模型,并使用训练数据集进行模型训练。 3. 导出模型为ONNX格式:在模型训练完成后,使用PyTorch提供的导出函数将训练好的模型转换为ONNX格式。这可以通过调用`torch.onnx.export()`函数完成,将模型定义、训练好的参数和输入的形状等信息导出为ONNX模型文件。 4. 验证导出的ONNX模型:载入导出的ONNX模型,并使用测试数据进行验证,以确保模型导出正确无误。 通过将MobileNetV2模型训练为ONNX格式,可以使得该模型能够在其他深度学习框架中进行部署和应用。此外,ONNX格式还支持模型量化和优化等功能,有助于进一步减小模型的体积和提高模型的执行效率。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值