对于机器学习应用程序,我试图在python中编写一个读取图像的图像读取器类,对它们进行预处理并将它们分批传递给应用程序。
读取和预处理需要与机器学习培训/测试并行进行,这很容易使用线程和队列来实现。然而,由于预处理在计算上是昂贵的,我想进一步并行化,以便在不同的过程中并行地读取和预处理各个图像。我试图通过以下方式实现这一点(请注意,该示例将删除与问题无关的所有内容,例如读取标签)
import numpy as np
import cv2
import csv
from multiprocessing import Queue, Pool
def load_image(fname):
return cv2.imread(fname)[:,:,[2,1,0]].astype(np.float32)
class ImageReader(object):
def __init__(self, path_to_csv, batchsize, transform=None):
self.path_to_csv = path_to_csv
self.batchsize = batchsize
self.transform = transform
self.fnames = []
csvfile = open(path_to_csv, 'rb')
reader = csv.reader(csvfile)
for row in reader:
self.fnames.append(row[0])
self.num_samples = len(self.fnames)
def __iter__(self):
q = Queue(maxsize=3*self.batchsize)
def producer(fname):
if self.transform is None:
q.put(load_image(fname))
else:
q.put(self.transform(load_image(fname)))
p = Pool()
p.map(producer, self.fnames)
for i in range(self.num_samples//self.batchsize):
Xlst = []
for j in range(self.batchsize):
Xlst.append(q.get())
yield np.array(Xlst)
if __name__ == '__main__':
r = ImageReader('some_path', 128, transform=None)
for Xb in r:
print Xb.shape
重要的部分是
q = Queue(maxsize=3*self.batchsize)
def producer(fname):
if self.transform is None:
q.put(load_image(fname))
else:
q.put(self.transform(load_image(fname)))
p = Pool()
p.map(producer, self.fnames)
我想让一个工作池并行处理图像(在文件名列表中指定)并将它们放入稍后访问的队列中。
由于producer
在类中定义,因此无法进行pickle,因此失败。 stackoverflow中有一些变通方法可以使函数成为可选择的,但是在我的特殊情况下它们似乎都不起作用,其中producer
将项放入队列中。有没有人对我的具体情况有所了解?
另外:除了拾取性问题之外,我还有正确的方法吗?我不太确定,因为这是我第一次使用多处理。
答案 0 :(得分:0)
你考虑过使用joblib吗? e.g。
from scipy.misc import imread, imsave
from sklearn.externals.joblib import Parallel, delayed
def read_images(image_paths_list):
images = Parallel(n_jobs=4, verbose=5)(
delayed(imread)(f) for f in image_paths_list
)
return images
那可以并行读取一批图像,然后可以使用类似的模式对它们进行后期处理?