Paddle实现迁移学习
本项目仅用于参考,提供思路和想法并非标准答案!请谨慎抄袭!
迁移学习
三岁出品,必是精品!
迁移学习:先训练一个模型然后把该模型的参数给类似的项目直接进行训练,效果好极了!
基于这个原理我们开始思考流程
1、数据处理
2、网络定义
3、训练模型
4、固定参数
5、加载模型参数
6、进行迁移学习
本项目的最后结果差的离谱,原因原始模型就不好。
提高分数建议:
1、修改原始网络
2、提高原始模型质量
3、修改训练轮数
4、数据处理更加精准
作业5-迁移学习
项目描述
本作业的任务是迁移学习中的领域对抗性训练(Domain Adversarial Training)。
也就是左下角的那一块。
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}
作者简介
作者:三岁
经历:自学python,现在混迹于paddle社区,希望和大家一起从基础走起,一起学习Paddle
csdn地址:blog.csdn.net/weixin_4562…
我在AI Studio上获得至尊等级,点亮9个徽章,来互关呀~ aistudio.baidu.com/aistudio/pe…
传说中的飞桨社区最菜代码人,让我们一起努力!
记住:三岁出品必是精品 (不要脸系列)