11.2. ループを並列処理する方法#

画像処理では、同じアルゴリズムを大量の画像のバッチに適用することがよくあります。このセクションでは、joblib を使用してループを並列処理する方法を提案します。以下は、このような繰り返しタスクの例です。

import skimage as ski

def task(image):
    """
    Apply some functions and return an image.
    """
    image = ski.restoration.denoise_tv_chambolle(
        image[0][0], weight=0.1, channel_axis=-1
    )
    fd, hog_image = ski.feature.hog(
        ski.color.rgb2gray(image),
        orientations=8,
        pixels_per_cell=(16, 16),
        cells_per_block=(1, 1),
        visualize=True
    )
    return hog_image


# Prepare images
hubble = ski.data.hubble_deep_field()
width = 10
pics = ski.util.view_as_windows(
    hubble, (width, hubble.shape[1], hubble.shape[2]), step=width
)

リスト pics の各要素に対して task 関数を実行するには、for ループを記述するのが一般的です。このループの実行時間を測定するには、ipython を使用して %timeit で実行時間を測定できます。

def classic_loop():
    for image in pics:
        task(image)


%timeit classic_loop()

このループをコーディングするもう 1 つの方法は、同じ効率を持つコ​​ンプリヘンションリストを使用することです。

def comprehension_loop():
    [task(image) for image in pics]

%timeit comprehension_loop()

joblib は、コ​​ンプリヘンションリストがあれば for ループを簡単に並列処理する方法を提供するライブラリです。ジョブの数も指定できます。

from joblib import Parallel, delayed
def joblib_loop():
    Parallel(n_jobs=4)(delayed(task)(i) for i in pics)

%timeit joblib_loop()