【paddlehub】用paddlehub在自己数据集上做迁移学习

paddlehub

paddlehub是百度paddlepaddle深度学习框架提供的配套预训练模型应用管理工具,提供Python API和命令行两种调用模式,目前的预训练模型覆盖了图像分类、语义模型、视频分类、图像生成、图像分割、文本审核、关键点检测等业界主流模型,功能十分强大。Github地址:https://github.com/PaddlePaddle/PaddleHub
在这里插入图片描述

paddlehub的强大,但是官方提供做自己数据集迁移学习的demo较少,目前网上提供资料也不多且较散,这里我就以我自己的一个简单的project为例,给大家讲解一下paddlehub的迁移学习使用入门。

数据集

完整项目地址:https://aistudio.baidu.com/aistudio/projectdetail/782743
数据集可在kaggle官网下载,但有的同学嫌翻墙麻烦下载慢,我也在百度网盘和aistudio上放了一份:
百度网盘:链接: https://pan.baidu.com/s/12RbvTpOfUL8eM9vNwWW72A提取码: 4fe4
aistudio:https://aistudio.baidu.com/aistudio/datasetdetail/38429
kaggle:https://www.kaggle.com/c/state-farm-distracted-driver-detection

运行环境

paddlepaddle 1.8.0 + paddlehub 1.8.4

1.数据分析

!unzip -o -q data/data38429/distracted_driver_detection.zip
print("done")

解压数据集,可以看到最后生成:train文件夹+test文件+driver_imgs_list.csv

我们先来分析一下mgs_list.csv文件,打开可以看到共有三个信息:

  • subject:拍摄的司机编号
  • classname:分心行为对应的标签
  • img:对应的图片数据名
    先来看看司机数据的数据分布:
#csv文件路径
dir = "driver_imgs_list.csv"

#读取csv中subject的数据
#subject对应的是司机的编号
img_csv = os.path.join(dir)
csv_data = pd.read_csv(img_csv)
driver_name = csv_data['subject']

#储存所有司机的编号
names = []
for name in driver_name:
    if(name not in names):
        names.append(name)

#计算每个司机有多少张图片
driver_num = csv_data.groupby('subject')['img'].count()

#显示每个司机图片数量
print(driver_num)

#显示总共多少个司机
print("drivers count = {}".format(len(names)))

#可视化
plt.bar(x=names, height=driver_num, width=0.8)
plt.show()

从输出可以看到,司机一共是26个,每个司机的数据分布并没有一个明显的特征,下面再分析分析10个分类的样本数据

class_name = csv_data['classname']

#储存所有类别
class_names = []
for name in class_name:
    if(name not in class_names):
        class_names.append(name)

#计算每个类别有多少张图片
class_num = csv_data.groupby('classname')['img'].count()

#显示每个类别图片数量
print(class_num)

#显示总共多少类
print("class count = {}".format(len(class_names)))

#可视化
plt.bar(x=class_names, height=class_num, width=0.8)
plt.show()

从输出结果可以看到,分类是c0-c9共十个类别,且样本数分布较为均匀,诶很奈斯。

提供的数据集中除了储存标注信息的csv文件外,只有train文件夹+test文件,无val集,所以下一步要对数据进行处理,划分出val集。

2.数据处理

因为提供的数据集中只有train和test无val集,所以人为的在train集中划分一部分数据作为val集并生成储存图片位置与类别的txt文件

path = "train/"
folders_name = os.listdir(path)

a = open("train_list.txt", "w")
b = open("val_list.txt", "w")

count = 0
val_count = 0
train_count = 0

for name in folders_name:
    image_names = os.listdir(path+name)
    for img_name in image_names:
        if(count % 20 == 0):
            b.write(path+name+"/"+img_name+name.replace("c"," ")+'\n')
            val_count = val_count + 1
        else:
            a.write(path+name+"/"+img_name+name.replace("c"," ")+'\n')
            train_count = train_count + 1
        count = count + 1

a.close()
b.close()
print("train_list生成完毕,train数据集共{}个数据".format(train_count))
print("val_list生成完毕,val数据集共{}个数据".format(val_count))
print("合计{}个数据".format(count))

将test集图片信息写入predict_list.txt文件中

f = open("predict_list.txt", "w")
predict_data = []

path = "test/"
folders_name = os.listdir(path)
for name in folders_name:
    f.write(path+name+'\n')
    predict_data.append(path+name)
print("predict_list.txt文件成功生成")
f.close()

生成储存标签信息的label_list.txt文件

w = open("label_list.txt", "w")
path = "train/"
folders_name = os.listdir(path)
for name in folders_name:
    w.write(name+'\n')
print("label_list.txt文件成功生成")
w.close()

3.训练配置

装载选中的模型(这边主要是举例,所以随便选的加载的模型)

import paddlehub as hub
module = hub.Module(name="mobilenet_v2_imagenet")
input_dict, output_dict, program = module.context(trainable=True)

定义了一个DemoDataset读取自己的数据集

  • train_list_file:训练集

  • validate_list_file:val集

  • test_list_file:测试集

  • predict_file:实际中做的要预测的数据

因为没有predict_file就可以注释掉不管他了

from paddlehub.dataset.base_cv_dataset import BaseCVDataset
   
class DemoDataset(BaseCVDataset):	
   def __init__(self):	
       # 数据集存放位置
       self.dataset_dir = ""
       super(DemoDataset, self).__init__(
           base_path=self.dataset_dir,
           train_list_file="train_list.txt",
           validate_list_file="val_list.txt",
           test_list_file="predict_list.txt",
           #predict_file="predict_list.txt",
           label_list_file="label_list.txt",
           )
dataset = DemoDataset()

这里是于图像分类问题,所以选择ImageClassificationReader:图像分类数据预处理器,会修改输入数据集图像的尺寸、进行标准化处理、图像增广处理等操作。

data_reader = hub.reader.ImageClassificationReader(
    image_width=module.get_expected_image_width(),
    image_height=module.get_expected_image_height(),
    images_mean=module.get_pretrained_images_mean(),
    images_std=module.get_pretrained_images_std(),
    dataset=dataset)

配置训练的一些超参数,在strategy里可以配置很多优化的参数,这里的优化策略选取的默认优化策略。其对应参数如下:

  • learning_rate: 全局学习率。默认为1e-4。

  • optimizer_name: 优化器名称。默认adam。

  • regularization_coeff: 正则化的λ参数。默认为1e-3。

config = hub.RunConfig(
    use_cuda=True,                               #是否使用GPU训练
    num_epoch=10,                                #Fine-tune的轮数
    checkpoint_dir="source",                     #模型checkpoint保存路径
    batch_size=16,                               #训练的批大小
    eval_interval=100,                           #模型评估的间隔
    strategy=hub.finetune.strategy.DefaultFinetuneStrategy())  #Fine-tune优化策略;

把设置好的参数写入并建立ImageClassifierTask任务

feature_map = output_dict["feature_map"]
feed_list = [input_dict["image"].name]

#ImageClassifierTask:通用的分类任务Task,该Task基于输入的特征,添加一个或多个全连接层来创建一个分类任务用于Fine-tune
task = hub.ImageClassifierTask(
    data_reader=data_reader,           #提供数据的reader
    feed_list=feed_list,               #待feed变量的名字列表
    feature=feature_map,               #输入的特征矩阵
    num_classes=dataset.num_labels,    #分类任务的类别数量
    config=config)                     #运行配置

这两步可能会报的错误:

  1. AttributeError: ‘Parameter’ object has no attribute
    ‘gradient_clip_attr’
    paddlehub不是最新版导致的,建议升级paddlehub至1.8.2再试一试,如果还不行就检查一下自己paddlepaddle版本是不是1.8以上的
  2. Error: Blocking queue is killed because the data reader raises an
    exception 这个报错问题出在reader上,在这个报错向上找,如果能找到类似:ValueError: invalid
    literal for int() with base 10: 'c2’的语句,就铁锤是因为便签设置的问题
    我这里是十分类问题,对应标签是c0-c9十个,但是最后分类对应的标签应该是0-9这种整数,在前面生成txt那里进行修改就可以解决了

4.开始训练

激活task的finetune和eval

run_states = task.finetune_and_eval()

5.结果预测

调用task.predict来进行预测,最后返回的预测结果是一个batch一个batch大小返回的

import numpy as np
label_map = dataset.label_dict()
index = 0
run_states = task.predict(data=predict_data)
results = [run_state.run_results for run_state in run_states]

images_data= []
res_data= []
for batch_result in results:
    batch_result = np.argmax(batch_result, axis=2)[0]
    for result in batch_result:
        index += 1
        result = label_map[result]
        print("input %i is %s, and the predict result is %s" %
              (index, predict_data[index - 1], result))
        images_data.append(predict_data[index - 1])
        res_data.append(result)
print(res_data)

paddlehub功能强大学会使用可以给自己做项目省很多精力,希望这篇博客能解决大家刚开始使用paddlehub的一些问题。
项目地址如下,欢迎大家fork、讨论
项目地址:https://aistudio.baidu.com/aistudio/projectdetail/782743

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fitzie

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值