Paddle实现迁移学习

简介: Paddle实现迁移学习

项目说明,本项目是李宏毅老师在飞桨授权课程的作业解析

课程 传送门

该项目AiStudio项目 传送门

数据集 传送门

本项目仅用于参考,提供思路和想法并非标准答案!请谨慎抄袭!


迁移学习



三岁出品,必是精品!


迁移学习:先训练一个模型然后把该模型的参数给类似的项目直接进行训练,效果好极了!

基于这个原理我们开始思考流程


1、数据处理

2、网络定义

3、训练模型

4、固定参数

5、加载模型参数

6、进行迁移学习


本项目的最后结果差的离谱,原因原始模型就不好。

提高分数建议:

1、修改原始网络

2、提高原始模型质量

3、修改训练轮数

4、数据处理更加精准


作业5-迁移学习



项目描述


本作业的任务是迁移学习中的领域对抗性训练(Domain Adversarial Training)。


c45384f70bd12de95861b9fdfcc724b0.png


也就是左下角的那一块。


Domain Adaptation是让模型可以在训练时只需要 A dataset label,不需要 B dataset label 的情况下提高 B dataset 的准确率。 (A dataset & task 接近 B dataset & task)也就是给定真实图片 & 标签以及大量的手绘图片,请设计一种方法使得模型可以预测出手绘图片的标签是什么。


数据集介绍


这次的任务是源数据: 真实照片,目标数据: 手画涂鸦。

我们必须让model看过真实照片以及标签,尝试去预测手画涂鸦的标签为何。

资料位于’data/data58171/real_or_drawing.zip’


  • Training : 5000 张真实图片 + label, 32 x 32 RGB
  • Testing : 100000 张手绘图片,28 x 28 Gray Scale
  • Label: 总共需要预测 10 个 class。
  • 资料下载下来是以 0 ~ 9 作为label


特别注意一点: **这次的源数据和目标数据的图片都是平衡的,你们可以使用这个资料做其他事情。 **


项目要求


  • 禁止手动标记label或在网上寻找label
  • 禁止使用pre-trained model


数据准备


!unzip -oq /home/aistudio/data/data75815/real_or_drawing.zip


import os
import paddle
import paddle.vision.transforms as T
import numpy as np
from PIL import Image
import paddle.nn.functional as F
import random


数据处理


data_path = '/home/aistudio/real_or_drawing/train_data'  # 设置初始文件地址
character_folders = os.listdir(data_path)  # 查看地址下文件夹
character_folders


['2', '1', '5', '3', '8', '7', '6', '9', '4', '0']
# 新建标签列表
def img_list_text(train='train'):
    data_path = f'/home/aistudio/real_or_drawing/{train}_data'  # 设置初始文件地址
    character_folders = os.listdir(data_path)  # 查看地址下文件夹
    if(os.path.exists(f'./{train}_train_imglist.txt')):  # 判断文件是否存在
        os.remove(f'./{train}_train_imglist.txt')  # 删除文件
    if(os.path.exists(f'./{train}_test_imglist.txt')):  # 判断文件是否存在
        os.remove(f'./{train}_test_imglist.txt')  # 删除文件
    with open(f'./{train}_train_imglist.txt', 'w')as f_train:
        with open(f'./{train}_test_imglist.txt', 'w')as f_test:
            img_list = []
            for character_folder in character_folders:  #  循环文件夹列表  
                character_imgs = os.listdir(os.path.join(data_path,character_folder))  # 读取文件夹下面的内容
                count = 0
                for img in character_imgs:  # 循环图片列表
                    img_list.append(os.path.join(data_path,character_folder,img) + '\t' + character_folder + '\n')  # 写入地址及标签
                    count += 1
                print(character_folder,count)  # 查看各个目录的图片数量
            random.shuffle(img_list)  # 打乱列表
            count_1 = 0
            for img in img_list:  # 循环列表
                if count_1 < int(len(img_list)*0.8):  # 输出前80%为训练集
                    f_train.write(img)
                    count_1 += 1
                else:  # 剩下来的为验证集
                    f_test.write(img)
                    count_1 += 1
            print(len(img_list),int(len(img_list)*0.8))  # 查看总数量和训练集数量
img_list_text('train')  # 实例化数据
img_list_text('test')
2 500
1 500
5 500
3 500
8 500
7 500
6 500
9 500
4 500
0 500
5000 4000
0 100000
100000 80000
# 继承paddle.io.Dataset对数据集做处理
class FoodDataset(paddle.io.Dataset):
    """
    数据集类的定义
    """
    def __init__(self, mode='train'):
        """
        初始化函数
        """
        self.data = []
        with open(f'{mode}_imglist.txt') as f:  # 打开文件
            for line in f.readlines():  # 逐行读取
                info = line.strip().split('\t')  # 以\t进行分隔
                if len(info) > 0:
                    self.data.append([info[0].strip(), info[1].strip()])   # 写入文件
    def __getitem__(self, index):
        """
        读取图片,对图片进行归一化处理,返回图片和 标签
        """
        image_file, label = self.data[index]  # 获取数据
        img = Image.open(image_file)  # 读取图片
        img = img.resize((28, 28), Image.ANTIALIAS)  # 图片大小样式归一化
        img = np.array(img).astype('float32')  # 转换成数组类型浮点型32位
        img = img.transpose((2, 0, 1))     #读出来的图像是rgb,rgb,rbg..., 转置为 rrr...,ggg...,bbb...
        img = img/255.0  # 数据缩放到0-1的范围
        return img, np.array(label, dtype='int64')
    def __len__(self):
        """
        获取样本总数
        """
        return len(self.data)
train_train_img = FoodDataset('train_train')
train_test_img = FoodDataset('train_test')
# 查看训练和测试数据的大小
print('train大小:', train_train_img.__len__())
print('eval大小:', train_test_img.__len__())
# 查看图片数据、大小及标签
for data, label in train_train_img:
    print(data[0][1])
    print(np.array(data).shape)
    print(label)
    break
train大小: 4000
eval大小: 1000
[1.         0.99215686 0.96862745 0.92156863 0.87058824 0.83137256
 0.8039216  0.76862746 0.73333335 0.69803923 0.6784314  0.6784314
 0.6784314  0.68235296 0.69803923 0.7176471  0.7372549  0.77254903
 0.8        0.8156863  0.8156863  0.8039216  0.7921569  0.7647059
 0.72156864 0.6745098  0.6117647  0.6313726 ]
(3, 28, 28)
6


定义网络


# 继承paddle.nn.Layer类,用于搭建模型
class MLPModel(paddle.nn.Layer):  # 继承paddle.nn.Layer类
    def __init__(self):
        super(MLPModel, self).__init__()
        self.flatten=paddle.nn.Flatten()  # 数据拉直
        self.hidden=paddle.nn.Linear(in_features=2352,out_features=128)  # 线性输入784输出128
        self.output=paddle.nn.Linear(in_features=128,out_features=10)  # 线性输入128输出10
    def forward(self, x):
        x=self.flatten(x)  #  拉直
        x=self.hidden(x)  # 经过隐藏层(线性层1)
        x=F.relu(x) # 经过激活层
        x=self.output(x)  # 经过输出层
        return x
model=paddle.Model(MLPModel())  # 实例化模型


model.summary((1,3,28,28))


---------------------------------------------------------------------------
 Layer (type)       Input Shape          Output Shape         Param #    
===========================================================================
   Flatten-6      [[1, 3, 28, 28]]        [1, 2352]              0       
   Linear-19        [[1, 2352]]            [1, 128]           301,184    
   Linear-20         [[1, 128]]            [1, 10]             1,290     
===========================================================================
Total params: 302,474
Trainable params: 302,474
Non-trainable params: 0
---------------------------------------------------------------------------
Input size (MB): 0.01
Forward/backward pass size (MB): 0.02
Params size (MB): 1.15
Estimated Total Size (MB): 1.18
---------------------------------------------------------------------------
{'total_params': 302474, 'trainable_params': 302474}


模型训练


# model = paddle.Model(network)  # 模型封装
# 配置优化器、损失函数、评估指标
model.prepare(paddle.optimizer.Adam(learning_rate=0.0001, parameters=model.parameters()), 
              paddle.nn.CrossEntropyLoss(), 
              paddle.metric.Accuracy())
# 训练可视化VisualDL工具的回调函数
visualdl = paddle.callbacks.VisualDL(log_dir='visualdl_log')   
# 启动模型全流程训练
model.fit(train_train_img,  # 训练数据集
        train_test_img,   # 评估数据集
        epochs=5,       # 训练的总轮次
        batch_size=64,  # 训练使用的批大小
        verbose=1,      # 日志展示形式
        callbacks=[visualdl])  # 设置可视化


The loss value printed in the log is the current step, and the metric is the average value of previous step.
Epoch 1/5
step 63/63 [==============================] - loss: 1.4922 - acc: 0.4325 - 13ms/step        
Eval begin...
The loss value printed in the log is the current batch, and the metric is the average value of previous step.
step 16/16 [==============================] - loss: 2.1877 - acc: 0.4000 - 12ms/step        
Eval samples: 1000
Epoch 2/5
step 63/63 [==============================] - loss: 1.6968 - acc: 0.4325 - 13ms/step        
Eval begin...
The loss value printed in the log is the current batch, and the metric is the average value of previous step.
step 16/16 [==============================] - loss: 2.1877 - acc: 0.4000 - 12ms/step        
Eval samples: 1000
Epoch 3/5
step 63/63 [==============================] - loss: 1.6774 - acc: 0.4325 - 13ms/step        
Eval begin...
The loss value printed in the log is the current batch, and the metric is the average value of previous step.
step 16/16 [==============================] - loss: 2.1877 - acc: 0.4000 - 12ms/step        
Eval samples: 1000
Epoch 4/5
step 63/63 [==============================] - loss: 1.6447 - acc: 0.4325 - 14ms/step        
Eval begin...
The loss value printed in the log is the current batch, and the metric is the average value of previous step.
step 16/16 [==============================] - loss: 2.1877 - acc: 0.4000 - 12ms/step        
Eval samples: 1000
Epoch 5/5
step 63/63 [==============================] - loss: 1.7489 - acc: 0.4325 - 13ms/step        
Eval begin...
The loss value printed in the log is the current batch, and the metric is the average value of previous step.
step 16/16 [==============================] - loss: 2.1877 - acc: 0.4000 - 13ms/step        
Eval samples: 1000
model.save('finetuning/mnist')  # 保存模型


迁移学习


# 数据处理
test_train_img = FoodDataset('test_train')
test_test_img = FoodDataset('test_test')
# 查看训练和测试数据的大小
print('train大小:', train_train_img.__len__())
print('eval大小:', train_test_img.__len__())
# 查看图片数据、大小及标签
for data, label in train_train_img:
    print(data[0][1])
    print(np.array(data).shape)
    print(label)
    break
train大小: 80000
eval大小: 20000
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 0. 0. 0. 0.]
(3, 28, 28)
0
# 模型封装,为了后面保存预测模型,这里传入了inputs参数
model_2 = paddle.Model(MLPModel())  # 实例化模型
# 加载之前保存的阶段训练模型
model_2.load('finetuning/mnist')
# 模型配置
model_2.prepare(paddle.optimizer.Adam(learning_rate=0.001, parameters=network.parameters()),
                paddle.nn.CrossEntropyLoss(),
                paddle.metric.Accuracy())
# 模型全流程训练
model_2.fit(test_train_img, 
            test_test_img,
            epochs=2,
            batch_size=64,
            verbose=1)
The loss value printed in the log is the current step, and the metric is the average value of previous step.
Epoch 1/2
step 1250/1250 [==============================] - loss: 2.6177 - acc: 0.0119 - 11ms/step        
Eval begin...
The loss value printed in the log is the current batch, and the metric is the average value of previous step.
step 313/313 [==============================] - loss: 2.6651 - acc: 0.0119 - 12ms/step        
Eval samples: 20000
Epoch 2/2
step 1250/1250 [==============================] - loss: 2.8404 - acc: 0.0119 - 9ms/step        
Eval begin...
The loss value printed in the log is the current batch, and the metric is the average value of previous step.
step 313/313 [==============================] - loss: 2.6651 - acc: 0.0119 - 8ms/step         
Eval samples: 20000


验证结果


result = model.evaluate(test_test_img, verbose=1)  # 验证
print(result)



Eval begin...
The loss value printed in the log is the current batch, and the metric is the average value of previous step.
step 20000/20000 [==============================] - loss: 2.4581 - acc: 0.0119 - 2ms/step         
Eval samples: 20000
{'loss': [2.4580889], 'acc': 0.0119}

传说中的飞桨社区最菜代码人,让我们一起努力!

记住:三岁出品必是精品 (不要脸系列


目录
相关文章
|
数据挖掘
基于PaddlePaddle的中风患者线性模型预测
基于PaddlePaddle的中风患者线性模型预测
62 0
|
3月前
|
数据采集 自然语言处理 API
百度飞桨(PaddlePaddle)-数字识别
百度飞桨(PaddlePaddle)-数字识别
57 1
|
机器学习/深度学习 自然语言处理 索引
深入了解 Transformers – Part 1: 介绍 Transformer 模型
深入了解 Transformers – Part 1: 介绍 Transformer 模型
1263 1
|
机器学习/深度学习 数据采集 存储
基于PaddlePaddle的词向量实战 | 深度学习基础任务教程系列
基于PaddlePaddle的词向量实战 | 深度学习基础任务教程系列
|
机器学习/深度学习 自然语言处理 算法
瞎聊深度学习——PaddlePaddle的使用(一)
瞎聊深度学习——PaddlePaddle的使用(一)
|
API 异构计算
使用OpenVINO 和 PaddlePaddle 进行图像分类预测
使用OpenVINO 和 PaddlePaddle 进行图像分类预测
283 0
使用OpenVINO 和 PaddlePaddle 进行图像分类预测
|
机器学习/深度学习 编解码 算法
Paddle目标检测学习笔记
Paddle目标检测学习笔记
214 0
Paddle目标检测学习笔记
|
编解码 算法 计算机视觉
Paddle目标检测学习笔记(二)
Paddle目标检测学习笔记(二)
174 0
Paddle目标检测学习笔记(二)
|
机器学习/深度学习 算法 计算机视觉
Paddle目标检测学习笔记(一)
Paddle目标检测学习笔记(一)
144 0
Paddle目标检测学习笔记(一)
|
开发工具 计算机视觉 git
Paddle实现YOLOv3 目标检测
Paddle实现YOLOv3 目标检测
227 0
Paddle实现YOLOv3 目标检测