深度学习笔记(6)——多进程数据集批处理
深度学习算法训练时的输入一般都是固定的形式,如定长的信号、尺寸一样的图片以及分辨率相同的视频等等。但是用于训练神经网络的数据往往来自于多种渠道,所以处理数据集是我们必须要解决的一大问题,然而海量数据集的处理时长也会成倍增长,所以为了节省处理时间,需要使用多进程来对数据进行批处理以节省数据处理的时间。从而留出更多的时间用于训练。
本次笔记包含以下内容,目的是学会使用多进程来操作数据集:
- 查看电脑的核心数
- map函数介绍
- 使用函数来进行处理数据,以STFT作为一个例子实现
- 使用map来进行多进程方法处理数据
- 与串行处理方法进行对比,说明多进程是否可以减少运行时间
1. 查看电脑的cpu核心数
linux查看电脑是多少核的方法:
1、登录linux系统,在桌面的空白处右击,在弹出的下拉选项里,选择“打开终端
”;
2、在终端窗口中,执行“cat /proc/cpuinfo
”命令;
3、在输出结果中查看“cpu cores
”项的值,即可获取cpu的核数。
windows查看电脑是多少核的方法:
1、首先是找到并打开我们电脑的“设备管理器
”,打开的方式和方法有很多,在这里列举一二:可以右键点击“此电脑
”,选择点击“属性
”。
2、然后在左上角就有“设备管理器”
,我们就可以点击进入。
3、然后双击右侧出现的“处理器选项
”然后就可以看到有多少个cpu内核了
2. 多进程中map函数介绍
map函数一手包办了序列操作,参数传递和结果保存等一系列的操作。
学会使用map函数是掌握多进程必要手段
from multiprocessing.dummy import Pool
num_worker = 12
poop = Pool(num_worker) # num_worker代表电脑的cpu核心数
results = pool.map(函数,列表)
3. STFT数据处理
下面进行举例,使用STFT处理音频文件wav格式文件,文件夹/.data
下面放n条{signal}.wav
的数据,然后对每条数据进行短时傅里叶变换处理,并将处理结果放到./mel
目录下命名为{signal}_audio.npy
import numpy as np
from scipy import signal
import torch
import librosa
import os
def stft_c(audio_path, save_dir,length,save_results = True):
sig, _ = librosa.load(audio_path, sr=22050)
# 信号预处理
y = np.zeros(length)
if sig.shape[0] < length:
y[:len(sig)] = sig
else:
y = sig[:length]
# 归一化信号
sig_norm = y /np.max(np.abs(y))
# 对信号做短时傅里叶变换
f, t, zxx = signal.stft(sig_norm,fs = 25600 ,nperseg=159)
# 取出实部
zxx_zeal = np.array(np.abs(np.real(zxx)))
zxx_zeal = torch.FloatTensor(zxx_zeal)
print('111111')
if save_results:
os.makedirs(save_dir, exist_ok=True)
# 文件名
audio_name = os.path.basename(audio_path).split('.')[0]
# 保存为npy
np.save(os.path.join(save_dir, audio_name + '_audio.npy'), zxx_zeal) # 先不保存audio文件
else:
return zxx_zeal
4. 使用map来进行多进程方法处理数据
首先要
import os
from glob import glob
from pathlib import Path
from functools import partial
from multiprocessing.dummy import Pool.
# 输入文件夹,存放待处理的wav格式数据
input_dir = './data'
# 输出文件夹,保存将生成的文件
output_dir = './mel'
# 电脑的cup核个数
num_worker = 12
# 所有数据文件的名字列表
audio_paths = glob(os.path.join(input_dir, "*.wav"))
audio_paths.sort()
# 分配进程
pool = Pool(num_worker) # num_worker代表电脑的cpu核心数
# 在进程里处理数据
pool.map(partial(stft_c, save_dir=output_dir, length=25600), audio_paths)
5. 多线程与串行处理对比实验
单线程
使用单线程的for循环来处理数据,并计算其时间
time2 = time.time()
for i in range(len(audio_paths)):
stft_c(audio_paths[i], save_dir='./for',length=25600,save_results = True)
print('单进程循环共用时:{}'.format(time.time()-time2))
多线程运行时间
使用map部署到12个核心的电脑上
time1 = time.time()
pool = Pool(num_worker) # num_worker代表电脑的cpu核心数
# results = pool.map(stft_c, audio_paths)
pool.map(partial(stft_c, save_dir=output_dir, length=25600), audio_paths)
print('多进程共用时:{}'.format(time.time()-time1))
运行结果
运行结果如下所示
1)当数据量为60,运行时间结果如下所示:
数据个数为:60
多进程共用时:1.5292413234710693
单进程循环共用时:0.5117542743682861
出现这种情况和我们预期想的不一样,这是为什么呢?我们继续往下看
2)当数据量为672,运行时间结果如下所示:
数据个数为:672
多进程共用时:6.521606922149658
单进程循环共用时:7.452465295791626
当数据增加到672个时情况发现了反转,多进程所用的时间明显少于单进程循环,多进程的优势瞬间体现了出来。