【画像処理にも応用可能】PyTorch cumprod_関数:累積積を使って画像解析をレベルアップ


torch.Tensor.cumprod_ は、PyTorchにおけるテンソルの累積積を求める関数です。与えられたテンソルの各要素を、その前の要素との積として計算し、新しいテンソルとして返します。

詳細

この関数の動作は以下の通りです。

  1. 入力テンソル input を受け取ります。
  2. 指定された次元 dim に沿ってテンソルの要素を積算します。
  3. 積算結果を新しいテンソルとして返します。

import torch

# サンプルデータ
data = torch.tensor([1, 2, 3, 4, 5])

# 0番目の次元(行方向)に沿って累積積を求める
result = data.cumprod_(dim=0)

print(result)

このコードを実行すると、以下の出力が得られます。

tensor([1, 2, 6, 24, 120])

上記の通り、result テンソルは data テンソルの各要素を、その前の要素との積として計算した結果となっています。

オプション

torch.Tensor.cumprod_ は、以下のオプション引数を受け取ります。

  • out: 計算結果を出力するテンソルを指定します。デフォルトは新しいテンソルが作成されます。
  • dtype: 返されるテンソルのデータ型を指定します。デフォルトは入力テンソルのデータ型です。


2つの次元における累積積

この例では、2つの次元における累積積を求めます。

import torch

# サンプルデータ
data = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# 0番目の次元と1番目の次元それぞれに沿って累積積を求める
result1 = data.cumprod_(dim=0)
result2 = data.cumprod_(dim=1)

print(result1)
print(result2)
tensor([[1, 2, 6],
       [4, 10, 30],
       [7, 28, 84]])
tensor([[1, 2, 3],
       [4, 10, 20],
       [7, 14, 21]])

説明

  • result2 は、1番目の次元(列方向)に沿って累積積を求めた結果です。各列の要素は、その前の要素との積として計算されています。
  • result1 は、0番目の次元(行方向)に沿って累積積を求めた結果です。各行の要素は、その前の要素との積として計算されています。

特定のデータ型への変換

この例では、累積積の結果を特定のデータ型に変換します。

import torch

# サンプルデータ
data = torch.tensor([1, 2, 3, 4, 5], dtype=torch.float32)

# 0番目の次元と1番目の次元それぞれに沿って累積積を求める
result1 = data.cumprod_(dim=0, dtype=torch.float64)
result2 = data.cumprod_(dim=1, dtype=torch.int64)

print(result1)
print(result2)
tensor([1.00000000e+00, 2.00000000e+00, 6.00000000e+00,
       2.40000000e+01, 1.20000000e+02], dtype=torch.float64)
tensor([[1, 2, 3],
       [4, 10, 20],
       [7, 14, 21]], dtype=torch.int64)

説明

  • result2 は、1番目の次元(列方向)に沿って累積積を求めた結果です。結果は torch.int64 型に変換されています。
  • result1 は、0番目の次元(行方向)に沿って累積積を求めた結果です。結果は torch.float64 型に変換されています。

この例では、累積積の結果を既存のテンソルに書き込みます。

import torch

# サンプルデータ
data = torch.tensor([1, 2, 3, 4, 5])
result = torch.tensor([0, 0, 0, 0, 0])

# 0番目の次元と1番目の次元それぞれに沿って累積積を求める
data.cumprod_(dim=0, out=result)
data.cumprod_(dim=1, out=result)

print(result)
tensor([1, 2, 6, 24, 120])
  • cumprod_ 関数は、out 引数で指定されたテンソルに結果を書き込みます。
  • result テンソルは、data テンソルの累積積結果で初期化されています。


forループによる逐次積算

最もシンプルな代替方法は、forループを使用して要素ごとに逐次的に積算していく方法です。

import torch

def cumprod_naive(data, dim):
    result = torch.ones_like(data)
    for i in range(data.size(dim)):
        result[:, i] = result[:, i - 1] * data[:, i]
    return result

# サンプルデータ
data = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# 0番目の次元と1番目の次元それぞれに沿って累積積を求める
result1 = cumprod_naive(data, dim=0)
result2 = cumprod_naive(data, dim=1)

print(result1)
print(result2)
tensor([[1, 2, 6],
       [4, 10, 30],
       [7, 28, 84]])
tensor([[1, 2, 3],
       [4, 10, 20],
       [7, 14, 21]])

scan 関数による累積操作

PyTorchには scan 関数が用意されており、累積操作を効率的に実行することができます。

import torch

def cumprod_scan(data, dim):
    return torch.scan(torch.mul, data, dim=dim)

# サンプルデータ
data = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# 0番目の次元と1番目の次元それぞれに沿って累積積を求める
result1 = cumprod_scan(data, dim=0)
result2 = cumprod_scan(data, dim=1)

print(result1)
print(result2)
tensor([[1, 2, 6],
       [4, 10, 30],
       [7, 28, 84]])
tensor([[1, 2, 3],
       [4, 10, 20],
       [7, 14, 21]])

NumPy ライブラリの利用

PyTorchと併用して NumPy ライブラリを使用することもできます。

import torch
import numpy as np

def cumprod_numpy(data, dim):
    return torch.from_numpy(np.cumprod(data.numpy(), axis=dim))

# サンプルデータ
data = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# 0番目の次元と1番目の次元それぞれに沿って累積積を求める
result1 = cumprod_numpy(data, dim=0)
result2 = cumprod_numpy(data, dim=1)

print(result1)
print(result2)
tensor([[1, 2, 6],
       [4, 10, 30],
       [7, 28, 84]])
tensor([[1, 2, 3],
       [4, 10, 20],
       [7, 14, 21]])