首页 > 其他分享 >【paddlepaddle速成】paddlepaddle图像分类从模型自定义到测试

【paddlepaddle速成】paddlepaddle图像分类从模型自定义到测试

时间:2023-07-04 19:38:32浏览次数:82  
标签:img 自定义 image paddlepaddle fluid paddle 速成 input import

这是给大家准备的paddlepaddle与visualdl速成例子

这一次我们讲讲paddlepadle这个百度开源的机器学习框架,一个图像分类任务从训练到测试出结果的全流程。

将涉及到paddlepaddle和visualdl,git如下:https://github.com/PaddlePaddle

相关的代码、数据都在我们 Git 上,希望大家 Follow 一下这个 Git 项目,后面会持续更新不同框架下的任务。

https://github.com/longpeng2008/LongPeng_ML_Course

作者&编辑 | 言有三  

 

01 paddlepaddle是什么

正所谓google有tensorflow,facebook有pytorch,amazon有mxnet,作为国内机器学习的先驱,百度也有PaddlePaddle,其中Paddle即Parallel Distributed Deep Learning(并行分布式深度学习),整体使用起来与tensorflow非常类似。

sudo pip install paddlepaddle

安装就是一条命令,话不多说上代码。

 

02 paddlepaddle训练

训练包括三部分,数据的定义,网络的定义,以及可视化和模型的存储。

2.1 数据定义

定义一个图像分类任务的dataset如下:

from multiprocessing import cpu_count
import paddle.v2 as paddle
class Dataset:
    def __init__(self,cropsize,resizesize):
        self.cropsize = cropsize
        self.resizesize = resizesize
    def train_mapper(self,sample):
        img, label = sample
        img = paddle.image.load_image(img)
        img = paddle.image.simple_transform(img, self.resizesize, self.cropsize, True)
        #print "train_mapper",img.shape,label
        return img.flatten().astype('float32'), label
    def test_mapper(self,sample):
        img, label = sample
        img = paddle.image.load_image(img)
        img = paddle.image.simple_transform(img, self.resizesize, self.cropsize, False)
        #print "test_mapper",img.shape,label
        return img.flatten().astype('float32'), label
    def train_reader(self,train_list, buffered_size=1024):
        def reader():
            with open(train_list, 'r') as f:
                lines = [line.strip() for line in f.readlines()]
                print "len of train dataset=",len(lines)
                for line in lines:
                    img_path, lab = line.strip().split(' ')
                    yield img_path, int(lab)
        return paddle.reader.xmap_readers(self.train_mapper, reader,
                                          cpu_count(), buffered_size)
    def test_reader(self,test_list, buffered_size=1024):
        def reader():
            with open(test_list, 'r') as f:
                lines = [line.strip() for line in f.readlines()]
                print "len of val dataset=",len(lines)
                for line in lines:
                    img_path, lab = line.strip().split(' ')
                    yield img_path, int(lab)
        return paddle.reader.xmap_readers(self.test_mapper, reader,
                                          cpu_count(), buffered_size)
 
从上面代码可以看出:
(1) 使用了paddle.image.load_image进行图片的读取,
 paddle.image.simple_transform进行了简单的图像变换,这里只有图像crop操作,更多的使用可以参考API。(2)  使用了paddle.reader.xmap_readers进行数据的映射。
2.2 网络定义
# coding=utf-8
 import paddle.fluid as fluid
 def simplenet(input):
    # 定义卷积块 
    conv1 = fluid.layers.conv2d(input=input, num_filters=12,stride=2,padding=1,filter_size=3,act="relu")
    bn1 = fluid.layers.batch_norm(input=conv1)
    conv2 = fluid.layers.conv2d(input=bn1, num_filters=12,stride=2,padding=1,filter_size=3,act="relu")
    bn2 = fluid.layers.batch_norm(input=conv2)
    conv3 = fluid.layers.conv2d(input=bn2, num_filters=12,stride=2,padding=1,filter_size=3,act="relu")
    bn3 = fluid.layers.batch_norm(input=conv3)
    fc1 = fluid.layers.fc(input=bn3, size=128, act=None)
    return fc1,conv1

与之前的caffe,pytorch,tensorflow框架一样,定义了一个3层卷积与2层全连接的网络。为了能够更好的进行可视化,我们使用了PaddlePaddle Fluid,Fluid的设计也是用来让用户像Pytorch和Tensorflow Eager Execution一样可以执行动态计算而不需要创建图。

2.3可视化

paddlepaddle有与之配套使用的可视化框架,即visualdl。

visualdl是百度数据可视化实验室发布的深度学习可视化平台,它的定位与tensorboard很像,可视化内容包含了向量,参数直方图分布,模型结构,图像等功能,以后我们会详细给大家讲述,这次直接在代码中展示如何使用。

安装使用pip install --upgrade visualdl,使用下面的命令可以查看官方例子:

vdl_create_scratch_log

visualDL --logdir ./scratch_log --port 8080

http://127.0.0.1:8080

下面是loss和直方图的查看

【paddlepaddle速成】paddlepaddle图像分类从模型自定义到测试_paddlepaddle

【paddlepaddle速成】paddlepaddle图像分类从模型自定义到测试_计算机视觉_02

在咱们项目中,具体使用方法如下

# 首先定义相关变量
 # 创建VisualDL,并指定log存储路径
 logdir = "./logs"
 logwriter = LogWriter(logdir, sync_cycle=10)

 # 创建loss的趋势图
 with logwriter.mode("train") as writer:
    loss_scalar = writer.scalar("loss")

 # 创建acc的趋势图
 with logwriter.mode("train") as writer:
    acc_scalar = writer.scalar("acc")

 # 定义输出频率
 num_samples = 4
 # 创建卷积层和输出图像的图形化展示
 with logwriter.mode("train") as writer:
    conv_image = writer.image("conv_image", num_samples, 1)
    input_image = writer.image("input_image", num_samples, 1)

 # 创建可视化的训练模型结构
 with logwriter.mode("train") as writer:
    param1_histgram = writer.histogram("param1", 100)然后在训练过程中进行记录,这是完整的训练代码,红色部分就是记录结果。
# coding=utf-8
 import numpy as np
 import os
 import paddle.fluid as fluid
 import paddle.fluid.framework as framework
 import paddle.v2 as paddle
 from paddle.fluid.initializer import NormalInitializer
 from paddle.fluid.param_attr import ParamAttr
 from visualdl import LogWriter
 from dataset import Dataset
 from net_fluid import simplenet

 # 创建VisualDL,并指定当前该项目的VisualDL的路径
 logdir = "./logs"
 logwriter = LogWriter(logdir, sync_cycle=10)

 # 创建loss的趋势图
 with logwriter.mode("train") as writer:
    loss_scalar = writer.scalar("loss")

 # 创建acc的趋势图
 with logwriter.mode("train") as writer:
    acc_scalar = writer.scalar("acc")

 # 定义输出频率
 num_samples = 4
 # 创建卷积层和输出图像的图形化展示
 with logwriter.mode("train") as writer:
    conv_image = writer.image("conv_image", num_samples, 1)
    input_image = writer.image("input_image", num_samples, 1)

 # 创建可视化的训练模型结构
 with logwriter.mode("train") as writer:
    param1_histgram = writer.histogram("param1", 100)

 def train(use_cuda, learning_rate, num_passes, BATCH_SIZE=128):
    class_dim = 2
    image_shape = [3, 48, 48]
    image = fluid.layers.data(name='image', shape=image_shape, dtype='float32')
    label = fluid.layers.data(name='label', shape=[1], dtype='int64')

    net, conv1 = simplenet(image)
    # 获取全连接输出
    predict = fluid.layers.fc(
        input=net,
        size=class_dim,
        act='softmax',
        param_attr=ParamAttr(name="param1", initializer=NormalInitializer()))

    # 获取损失
    cost = fluid.layers.cross_entropy(input=predict, label=label)
    avg_cost = fluid.layers.mean(x=cost)

    # 计算batch,从而来求平均的准确率
    batch_size = fluid.layers.create_tensor(dtype='int64')
    print "batchsize=",batch_size
    batch_acc = fluid.layers.accuracy(input=predict, label=label, total=batch_size)

    # 定义优化方法
    optimizer = fluid.optimizer.Momentum(
        learning_rate=learning_rate,
        momentum=0.9,
        regularization=fluid.regularizer.L2Decay(5 * 1e-5))

    opts = optimizer.minimize(avg_cost)

    # 是否使用GPU
    place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
    # 创建调试器
    exe = fluid.Executor(place)
    # 初始化调试器
    exe.run(fluid.default_startup_program())
    # 保存结果
    model_save_dir = "./models"

    # 获取训练数据
    resizesize = 60
    cropsize = 48
    mydata = Dataset(cropsize=cropsize,resizesize=resizesize)
    mydatareader = mydata.train_reader(train_list='./all_shuffle_train.txt')
    train_reader = paddle.batch(reader=paddle.reader.shuffle(reader=mydatareader,buf_size=50000),batch_size=128)
    
    # 指定数据和label的对应关系
    feeder = fluid.DataFeeder(place=place, feed_list=[image, label])

    step = 0
    sample_num = 0
    start_up_program = framework.default_startup_program()
    param1_var = start_up_program.global_block().var("param1")

    accuracy = fluid.average.WeightedAverage()
    # 开始训练,使用循环的方式来指定训多少个Pass
    for pass_id in range(num_passes):
        # 从训练数据中按照一个个batch来读取数据
        accuracy.reset()
        for batch_id, data in enumerate(train_reader()):
            loss, conv1_out, param1, acc, weight = exe.run(fluid.default_main_program(),
                                                           feed=feeder.feed(data),
                                                           fetch_list=[avg_cost, conv1, param1_var, batch_acc,batch_size])
            accuracy.add(value=acc, weight=weight)
            pass_acc = accuracy.eval()

            # 重新启动图形化展示组件
            if sample_num == 0:
                input_image.start_sampling()
                conv_image.start_sampling()
            # 获取taken
            idx1 = input_image.is_sample_taken()
            idx2 = conv_image.is_sample_taken()
            # 保证它们的taken是一样的
            assert idx1 == idx2
            idx = idx1
            if idx != -1:
                # 加载输入图像的数据数据
                image_data = data[0][0]
                input_image_data = np.transpose(
                    image_data.reshape(image_shape), axes=[1, 2, 0])
                input_image.set_sample(idx, input_image_data.shape,
                                       input_image_data.flatten())
                # 加载卷积数据
                conv_image_data = conv1_out[0][0]
                conv_image.set_sample(idx, conv_image_data.shape,
                                      conv_image_data.flatten())
                # 完成输出一次
                sample_num += 1
                if sample_num % num_samples == 0:
                    input_image.finish_sampling()
                    conv_image.finish_sampling()
                    sample_num = 0

           # 加载趋势图的数据
            loss_scalar.add_record(step, loss)
            acc_scalar.add_record(step, acc)
            # 添加模型结构数据
            param1_histgram.add_record(step, param1.flatten())
                      # 输出训练日志
            print("loss:" + str(loss) + " acc:" + str(acc) + " pass_acc:" + str(pass_acc))
            step += 1
            model_path = os.path.join(model_save_dir,str(pass_id))
            if not os.path.exists(model_save_dir):
                os.mkdir(model_save_dir)
            fluid.io.save_inference_model(model_path,['image'],[predict],exe)

 if __name__ == '__main__':
    # 开始训练
    train(use_cuda=False, learning_rate=0.005, num_passes=300)

2.4训练结果

看看acc和loss的曲线,可见已经收敛

【paddlepaddle速成】paddlepaddle图像分类从模型自定义到测试_开源框架_03

 

【paddlepaddle速成】paddlepaddle图像分类从模型自定义到测试_机器学习_0403 paddlepaddle测试

训练的时候使用了fluid,测试的时候也需要定义调试器,加载训练好的模型,完整的代码如下

# encoding:utf-8
 import sys
 import numpy as np
 import paddle.v2 as paddle
 from PIL import Image
 import os
 import cv2
 # coding=utf-8
 import numpy as np
 import paddle.fluid as fluid
 import paddle.fluid.framework as framework
 import paddle.v2 as paddle
 from paddle.fluid.initializer import NormalInitializer
 from paddle.fluid.param_attr import ParamAttr
 from visualdl import LogWriter
 from net_fluid import simplenet

 if __name__ == "__main__":
    # 开始预测
    type_size = 2
    testsize = 48

    imagedir = sys.argv[1]
    images = os.listdir(imagedir)
           # 定义调试器
    save_dirname = "./models/299"
    exe = fluid.Executor(fluid.CPUPlace())
    inference_scope = fluid.core.Scope()
    with fluid.scope_guard(inference_scope):
    # 加载模型 [inference_program,feed_target_names,fetch_targets] = fluid.io.load_inference_model(save_dirname,exe)

        predicts = np.zeros((type_size,1))
        for image in images:
            imagepath = os.path.join(imagedir,image)
            img = paddle.image.load_image(imagepath)
            img = paddle.image.simple_transform(img,testsize,testsize,False)
            img = img[np.newaxis,:]

            #print img.shape

            results = np.argsort(-exe.run(inference_program,feed={feed_target_names[0]:img},
                    fetch_list=fetch_targets)[0])
            label = results[0][0]
            predicts[label] += 1
    
    print predicts

由于所有框架的测试流程都差不多,所以就不对每一部分进行解释了,大家可以自行去看代码。


标签:img,自定义,image,paddlepaddle,fluid,paddle,速成,input,import
From: https://blog.51cto.com/u_14122493/6624468

相关文章

  • 【本周特惠课程】深度学习6大模型部署场景(Pytorch+NCNN+MNN+Tengine+TensorRT+微信小
    前言欢迎大家关注有三AI的视频课程系列,我们的视频课程系列共分为5层境界,内容和学习路线图如下:第1层:掌握学习算法必要的预备知识,包括Python编程,深度学习基础,数据使用,框架使用。第2层:掌握CV算法最底层的能力,包括模型设计基础,图像分类,模型分析。第3层:掌握CV算法最核心的方向,包括图像分......
  • 自定义日期选择器
    HTML部分代码使用popup组件将它弹出<view> <uni-popupref="popupDate"type="bottom"> <viewclass="popup-top-box"> <text>日期选择</text> <textclass="cancel-btn"@click="closeFun"......
  • 前端Vue自定义精美上下滚动通告栏组件 常用于展示公告信息 上下滚动跑马灯 上下滚动广
    前端Vue自定义精美上下滚动通告栏组件常用于展示公告信息上下滚动跑马灯上下滚动广播,下载完整代码请访问uni-app插件市场地址:https://ext.dcloud.net.cn/plugin?id=13318效果图如下:cc-noticeBar使用方法<!--默认颜色#333公告栏--><viewclass="header">默认颜色......
  • 前端Vue自定义精美悬浮菜单按钮fab button 可设置按钮背景颜色 菜单按钮展开条目
    前端Vue自定义精美悬浮菜单按钮fabbutton可设置按钮背景颜色菜单按钮展开条目,下载完整代码请访问uni-app插件市场地址:https://ext.dcloud.net.cn/plugin?id=13321效果图如下:cc-suspensionMenu使用方法<!--scrollShow:是否显示滑动到顶悬浮按钮 color:悬浮按钮背......
  • 前端Vue自定义精美宫格菜单按钮组件 可设置一行展示个数 可设置成九宫格 十二宫格 十
    前端Vue自定义精美宫格菜单按钮组件可设置一行展示个数可设置成九宫格十二宫格十五宫格,下载完整代码请访问uni-app插件市场地址:https://ext.dcloud.net.cn/plugin?id=13315效果图如下:cc-categoryMenu使用方法<viewclass="header">十五宫格菜单</view><!--推荐宫......
  • .net core 自定义配置文件
    publicvoidConfigureServices(IServiceCollectionservices){varconfigBuilder=newConfigurationBuilder().SetBasePath(Path.Combine(Directory.GetCurrentDirectory(),"Config")).AddJsonFile(&q......
  • nginx 错误页 指向 自定义页面
    1、安装简易版nginx可参考:https://www.cnblogs.com/fanyann/p/17500960.html以下所有操作均给予上面安装链接的系统版本和软件版本。2、首先,创建你自己的HTML错误页面,例如error.html。3、找到你的nginx.conf,它可能在/usr/local/nginx/conf,/etc/nginx,/usr/local/etc/nginx......
  • 微信小程序uniapp解决真机顶部自定义菜单显示(手机状态栏覆盖)
    1.在data里面加入参数statusBarHeight:uni.getSystemInfoSync().statusBarHeight,//状态栏高度2.对返回按钮处理<!--空出状态栏高度--><view:style="'height:'+statusBarHeight+'px;'"></view><!--返回按钮--><di......
  • react之自定义hooks
    原文合集地址如下,有需要的朋友可以关注本文地址合集地址任何相对独立、复用性强的逻辑,都可以extract为自定义Hook,自定义Hook是一种复用React的状态逻辑的函数。自定义Hook的主要特点是:抽象组件间的状态逻辑,方便复用让功能组件更纯粹,更易于维护自定义Hook可......
  • ES 中文分词器ik及自定义远程词库
    ik分词器安装部署 下载地址:https://github.com/medcl/elasticsearch-analysis-ik注意es和ik分词器的版本匹配.这里下载7.9.3的ik分词器下载完毕之后去es的工作目录的plugins文件夹下新建ik文件夹,将下载下来的ik压缩包解压缩至ik文件夹下,重启e   词库介绍ik分词器主......