pytorch:EDSR 生成训练数据的方法
Pytorch:EDSR 生成训练数据的方法
引言
Winter is coming
正文
pytorch
提供的DataLoader
是用来包装你的数据的工具. 所以你要将自己的 (numpy array 或其他)
数据形式装换成 Tensor
, 然后再放进这个包装器中. 使用 DataLoader
有什么好处呢?
就是他们帮你有效地迭代数据, 举例:
import torch
import torch.utils.data as Data #utils是torch中的一个模块,Data是进行小批训练的途径或模块
x = torch.linspace(1, 10, 10) # x data (torch tensor): 初始的数据
y = torch.linspace(10, 1, 10) # y data (torch tensor): 目标的数据
- 先转换成
torch
能识别的Dataset
torch_dataset = Data.TensorDataset(data_tensor=x, target_tensor=y)
torch_dataset
为用 torch
定义的一个数据库,然后将要训练的数据放到数据库中。
x为用来训练的数据,y为用于算误差的数据
- 把
dataset
放入DataLoader
BATCH_SIZE = 5 # 批训练大小为五,即每次抽取五个数据进行训练
loader = Data.DataLoader(
dataset=torch_dataset, # torch TensorDataset format
batch_size=BATCH_SIZE, # mini batch size
shuffle=True, # 要不要打乱数据 (打乱比较好)
num_workers=2, # 多线程来读数据,更有效率
)
我们使用 DataLoader()
来使我们的训练过程变成一批一批,shuffle
是 Bool
型变量,为真时随机打乱数据后进行抽样
for epoch in range(3): # 训练整套数据 3 次
for step, (batch_x, batch_y) in enumerate(loader):
# 每一步loader释放一小批数据用来学习,因为一组总共有10个data,batch_size又为5,所以训练一次数据有2个step
# 假设这里就是你训练的地方...
# 打出来一些数据
print('Epoch: ', epoch, '| Step: ', step, '| batch x: ', batch_x.numpy(), '| batch y: ', batch_y.numpy())
结果如下:
Epoch: 0 | Step: 0 | batch x: [ 6. 7. 2. 3. 1.] | batch y: [ 5. 4. 9. 8. 10.]
Epoch: 0 | Step: 1 | batch x: [ 9. 10. 4. 8. 5.] | batch y: [ 2. 1. 7. 3. 6.]
Epoch: 1 | Step: 0 | batch x: [ 3. 4. 2. 9. 10.] | batch y: [ 8. 7. 9. 2. 1.]
Epoch: 1 | Step: 1 | batch x: [ 1. 7. 8. 5. 6.] | batch y: [ 10. 4. 3. 6. 5.]
Epoch: 2 | Step: 0 | batch x: [ 3. 9. 2. 6. 7.] | batch y: [ 8. 2. 9. 5. 4.]
Epoch: 2 | Step: 1 | batch x: [ 10. 4. 8. 1. 5.] | batch y: [ 1. 7. 3. 10. 6.]
可以看出, 每步都导出了5个数据进行学习. 然后每个 epoch
的导出数据都是先打乱了以后再导出.
真正方便的还不是这点. 如果我们改变一下令 BATCH_SIZE = 8
, 这样我们就知道, step=0 会导出8个数据, 但是, step=1
时数据库中的数据不够 8个, 这时怎么办呢:
BATCH_SIZE = 8 # 批训练的数据个数
for ...:
for ...:
...
print('Epoch: ', epoch, '| Step: ', step, '| batch x: ',
batch_x.numpy(), '| batch y: ', batch_y.numpy())
结果如下:
Epoch: 0 | Step: 0 | batch x: [ 6. 7. 2. 3. 1. 9. 10. 4.] | batch y: [ 5. 4. 9. 8. 10. 2. 1. 7.]
Epoch: 0 | Step: 1 | batch x: [ 8. 5.] | batch y: [ 3. 6.]
Epoch: 1 | Step: 0 | batch x: [ 3. 4. 2. 9. 10. 1. 7. 8.] | batch y: [ 8. 7. 9. 2. 1. 10. 4. 3.]
Epoch: 1 | Step: 1 | batch x: [ 5. 6.] | batch y: [ 6. 5.]
Epoch: 2 | Step: 0 | batch x: [ 3. 9. 2. 6. 7. 10. 4. 8.] | batch y: [ 8. 2. 9. 5. 4. 1. 7. 3.]
Epoch: 2 | Step: 1 | batch x: [ 1. 5.] | batch y: [ 10. 6.]
这时, 在 step=1
就只给你返回这个 epoch 中剩下的data.
在阅读edsr
的源码时发现了下面这段代码:
opt.seed = random.randint(1,10000)
print("Random Seed: ",opt.seed)
torch.manual_seed(opt.seed) # 为当前cpu设置随机种子,值为范围在1到10000里的一个随机数
if cuda:
torch.cuda.manual_seed(opt.seed) # 为当前gpu设置随机种子
cudnn.banchmark = Ture
在训练开始时,参数的初始化为随机的,为了让每次的结果都一致,我们要设置随机种子。
而cudnn.banchmark
这个方法可以让CuDNN
的auto-tuner
自动寻找最适合当前配置的高效算法,如果每次迭代输入不变,可以增加,如果输入会产生变化,则会降低计算的效率。
接下来是edsr
中使用 DataLoader
的方法。
print("===> Loading datasets")
train_set = DatasetFromHdf5("path_to_dataset.h5")
training_data_loader = DataLoader(dataset=train_set, num_workers=opt.threads, batch_size=opt.batchSize, shuffle=True)
我仔细研究了两天发现,运行到这步时,图片似乎已经处理好了,因为这只是对图片进行打乱后再输入网络进行训练。
重新阅读 master
中的 ReadMe
后发现了这两行文字:
Prepare Training dataset
- Please refer Code for Data Generation for creating training files.
- Data augmentations including flipping, rotation, downsizing are adopted.
通过链接找到了具体的生成测试数据的方法,下面是edsr
的生成训练数据的方式:
clear;
close all;
folder = 'path/to/train/folder';
savepath = 'edsr_x4.h5'; % 将模型保存为edsr_x4.h5文件,x4为该模型的放大倍数
%% scale factors
scale = 4; % 放大倍数
size_label = 192; % 最终经过调整后的图片的大小
size_input = size_label/scale; % 输入大小 = 最终大小/放大倍数 = 48
stride = 96; % 步长大小为96
%% downsizing
downsizes = [1,0.7,0.5]; % 调整大小的三维向量
data = zeros(size_input, size_input, 3, 1); % init一个名为data的大小为48x48x3的零矩阵
label = zeros(size_label, size_label, 3, 1); % init一个名为label的大小为192x192x3的零矩阵
count = 0;
margain = 0; % 应为边缘信息一类的变量值
%% generate data 准备数据
filepaths = []; % 声明一个读取文件的目录
filepaths = [filepaths; dir(fullfile(folder, '*.png'))]; % 得到目录中所有图片的列表
length(filepaths) % 图片的个数
for i = 1 : length(filepaths) % 遍历所有图片
for flip = 1: 3 % 每张图片翻转三次
for degree = 1 : 4 % 从4个角度?
for downsize = 1 : length(downsizes)
image = imread(fullfile(folder,filepaths(i).name)); % 读取第i张图片
if flip == 1 % 当flip为1时,对图片进行上下翻转
image = flipd(image ,1);
end
if flip == 2 % 当flip为2时,对图片进行左右翻转
image = flipd(image ,2);
end
image = imrotate(image, 90 * (degree - 1)); % 逆时针方向旋转图片0-90-180-270度(角度为正则逆时针旋转,为负则顺时针)
image = imresize(image,downsizes(downsize),'bicubic'); % 通过双三次插值的方法将图像调整为之前的1-0.7-0.5的大小
if size(image,3)==3 % 当图片为三通道RGB图像时,进行以下的操作
%image = rgb2ycbcr(image);
image = im2double(image);
im_label = modcrop(image, scale); % 这个函数将取模后的图片赋给im_label
作者定义了一个对图像进行处理的函数(在Matlab Doc中是找不到滴):modcrop.m
,在同个文件夹下可以找到
function imgs = modcrop(imgs, modulo)
if size(imgs,3)==1 % 灰度图,或者可以理解为仅有一个y通道的图像
sz = size(imgs);
sz = sz - mod(sz, modulo);
imgs = imgs(1:sz(1), 1:sz(2));
else
tmpsz = size(imgs); % 获取图片尺寸
sz = tmpsz(1:2); % 把图片的height和width赋给sz
sz = sz - mod(sz, modulo); % height和width对modulo取模,并减去这个值,使得sz的大小正好可以整除modulo
imgs = imgs(1:sz(1), 1:sz(2),:); % 得到新的尺寸的图片
end
现在继续对取模后的三通道图片进行操作:
[hei,wid, c] = size(im_label); % 得到这张图片的现在的大小
% 使用大小为size_label*size_label的卷积核在图片上进行卷积,步长为stride
% subim_input 作为输入的图片,存入到data数组中
% subim_label 为放大4倍后的图片,存入到label数组中
filepaths(i).name
for x = 1 + margain : stride : hei-size_label+1 - margain
for y = 1 + margain :stride : wid-size_label+1 - margain
subim_label = im_label(x : x+size_label-1, y : y+size_label-1, :);
subim_input = imresize(subim_label,1/scale,'bicubic');
% figure;
% imshow(subim_input);
% figure;
% imshow(subim_label);
count=count+1;
data(:, :, :, count) = subim_input; % 第count组数据
label(:, :, :, count) = subim_label;
end
end
end
end
end
end
end
order = randperm(count); % 生成一行从1到count的整数,打乱后返回
data = data(:, :, :, order); % 将打乱后的样本顺序返回给 data 和 label 数组
label = label(:, :, :, order);
%% writing to HDF5
chunksz = 64; % 每次写入的数据个数
created_flag = false;
totalct = 0;
for batchno = 1:floor(count/chunksz)
batchno
last_read=(batchno-1)*chunksz;
batchdata = data(:,:,:,last_read+1:last_read+chunksz);
batchlabs = label(:,:,:,last_read+1:last_read+chunksz);
startloc = struct('dat',[1,1,1,totalct+1], 'lab', [1,1,1,totalct+1]);
curr_dat_sz = store2hdf5(savepath, batchdata, batchlabs, ~created_flag, startloc, chunksz);
created_flag = true;
totalct = curr_dat_sz(end);
end
h5disp(savepath);
现在我已经大致明白了这个.m文件要做什么了:
- 初始化各种参数
- 使用
flipping
,rotation
,downsizing
方法对图片调整大小 - 对图片使用大小为
size_label*size_label
的卷积核进行卷积得到标签图,缩小后得到输入图 - 将数据打乱后写入HDF5文件中
我在总结到这一步时恍然大悟,原来main_edsr.py
文件头部的引用中那段
form dataset import DatasetFromHdf5
代码的意思是:从data文件夹中引用格式为Hdf5的,你已经生成好的训练文件(刚才训练好的edsr_x4.h5
文件)!!!
好了,看了这么就,不实现一下就说不过去了。可是我一点运行,matlab就报错说我没有一下函数。这问题也不是一两次了,我觉得有可能是我没有训练数据(原始图片)的问题,于是我仿照我之前学习caffe框架下SRCNN的方法对代码的一下部分进行了修改。
% 第三行
folder = 'train';
% 55到58行去掉注释,我想看具体的图片长什么样子
figure;
imshow(subim_input);
figure;
imshow(subim_label);
然后报错:未定义函数或变量 'flipd'
,其实我之前在Matlab Doc中查找有关flip
函数信息时,就发现没有filpd
这个函数了。将d去掉后发现会报下标必须为整形的错误。可是flip
的用法没错啊。索性我直接将dim=1
时的函数替换为flipud(image)
即上下翻转图片,将dim=2
时的函数替换为fliplr(image)
左右翻转图片。这次运行没报错了,但是图片显示很是鬼畜,然后
我的电脑就蓝屏了,我*************************,啊啊啊啊啊啊
算了,我脾气超好!
凭着刚才的印象发现,编号为偶数的图片大于编号为奇数的图片,也就是说,我们的subim_label
的大小大于subim_input
这种最基本的问题没出错,还好还好。重启电脑后发现,博客还在,就是网联不上了,又重启一次后一切正常了。行吧,原谅你了,谁让我上午心情好呢。
写在后面
- 到这一步来说,应该算是学习结束了,基本弄清楚了训练文件是怎么产生的。昨天晚上和今天早上真是收获颇丰呢!弄清楚了很多东西,nice!我真bang(苦笑.jpg)
- 我在舍友的呼噜声中把这篇学习博客完成了,刚开始还想,我打字的声音会不会吵醒他们?,后来发现完全是多虑了,他们呼噜声超大,影响我学习?!,没有没有,开玩笑开玩笑,把刀放下好好说话……鬼知道为什么我昨晚最晚睡(3:00 am),却是最早起床的(8:30 am),orz
- Happy Birthday To nado, my dear idol
结语
真心喜欢过的人没法做朋友 因为看多几眼 都还是想拥有
pytorch:EDSR 生成训练数据的方法的更多相关文章
- oracle中生成大批量数据的方法-下
方法五:使用PLSQL的数据生成器 首先测试环境建立:dept表 CREATE TABLE dept(deptno NUMBER(6),dname VARCHAR2(20),loc VARCHAR2( ...
- 生成JSON数据--官方方法
官方生成方法: 1)需要什么就给什么,要属性就给属性,要对象就给对象,要集合就给集合 2)添加都是使用put()方法 要求: 1.生成如下JSON数据: {"age":4,&quo ...
- QT使用QJson生成解析Json数据的方法
QT中使用json还是比较方便的,下面用例子直接说明 举例子之前首先推荐一个在线解析json格式的网站,具体格式用法如下图所示: 之后根据这个格式进行json数据解析. QT使用json需要包含的头文 ...
- 谷歌BERT预训练源码解析(一):训练数据生成
目录预训练源码结构简介输入输出源码解析参数主函数创建训练实例下一句预测&实例生成随机遮蔽输出结果一览预训练源码结构简介关于BERT,简单来说,它是一个基于Transformer架构,结合遮蔽词 ...
- sklearn6_生成分类数据
sklearn实战-乳腺癌细胞数据挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003& ...
- 生成JSON数据--fastjson(阿里)方法
fastjson(阿里)方法生成JSON数据: 与Gson类似,创建相应类,再使用JSON.toJSONString()添加对象 要求:生成如下JSON数据 1.{"age":3, ...
- 生成JSON数据--Gson(谷歌)方法
Gson生成JSON数据方法: 创建相应的类,然后创建对象,toJson()进去就可以了 要求:生成如下JSON数据 1.{"age":4,"name":&qu ...
- [Oracle]快速生成大量模拟数据的方法
快速生成大量模拟数据的方法: create table TEST(id integer, TEST_NUMBER NUMBER(18,6)); insert into TEST select i+j, ...
- PyTorch 常用方法总结1:生成随机数Tensor的方法汇总(标准分布、正态分布……)
在使用PyTorch做实验时经常会用到生成随机数Tensor的方法,比如: torch.rand() torch.randn() torch.normal() torch.linespace() 在很 ...
随机推荐
- System.Web.UI.HtmlControls
用来创建一个标签.HtmlContainerControl 一般用此类来新建标签. 可能我们熟悉System.Web.UI.WebControls;空间.System.Web.UI.WebContro ...
- 【Java】重载(Overload)与重写(Override)
方法的语法 修饰符 返回值类型 方法名(参数类型 参数名){ ... 方法体 ... return 返回值; } 重载(overload) /** * 重载Overload: * 同一个类中,多个方法 ...
- hdu_5288_OO’s Sequence
OO has got a array A of size n ,defined a function f(l,r) represent the number of i (l<=i<=r) ...
- linux 安装 zookeeper
第一步 下载 zookeeper: http://archive.apache.org/dist/zookeeper/ 第二步 解压: tar -xzvf zookeeper-3.4.5.tar.gz ...
- Hbase学习指南
本篇Hbase组件基于CDH5进行安装,安装过程:https://www.cnblogs.com/dmjx/p/10037066.html Hbase简介 HBase是一个高可靠.高性能.面向列.可伸 ...
- Mysql_Binary_Install_Scripts(采用二进制方式安装)
1.1 MYSQL实现代码 #!/bin/bash ######################################## #auth:wolf_dreams #time:2018-1 ...
- java 计算数学表达式及执行脚本语言
java SE6中对常用的脚本语言做了支持. 可供使用者在java代码中执行脚本语言,还可以利用get("key"),put("key","value ...
- ethereum(以太坊)(六)--整型(int)
pragma solidity ^0.4.20; /* uint8 uint16 ...uint256 int8 int16 int24 ..int256 uint => uint256 int ...
- php-安装与配置-未完待续2
一,准备工作 在入门指引中,我们已经知道PHP的3个应用领域,不同的场景,需要安装的东西是不同的.具体如下: 服务器端脚本,在通常情况下,需要三样东西:PHP 自身.一个 web 服务器和一个 web ...
- Hive学习路线图