【DeepLearning】PyTorchは損失関数(Loss Function)をどのようにカスタマイズしますか?
22122 ワード
変換元:https://www.zhihu.com/question/66988664
文書ディレクトリ 1. 直接利用Tensorが提供するインタフェース 2. PyTorchによるnumpy/scipy拡張 3. PyTorchを書くC拡張 1.torchを直接利用する.Tensorが提供するインタフェース
カスタムlossのみが必要であるため、lossは1つ以上のTensorに対する混合計算と見なすことができ、例えば3元グループのLoss(Triplet Loss)を計算するには、(入力された3つの(anchor,positive,negative)テンソル次元がbatch_であると仮定する)テンソル次元がsize * 400)
図に示すように、init__()でスーパーパラメータを定義し、forward()で計算プロセスを定義すればよい.torchが提供するテンソル計算インタフェース(numpyとscipyも同様に使用できるが、感覚効率は低下する)を使用してcudaを呼び出すことができる(torchインタフェースまたはpython内蔵メソッドのみを使用することができる).つまり、インスタンス化オブジェクトの.cuda()メソッドを直接使用することができる.
nnを受け継いだからModuleなので、このLossクラスはインスタンス化後に直接実行できます_call__()メソッド、つまり
それでいいです.これが最初の方法です.
2.PyTorchによるnumpy/scipy拡張
もしあなたが細心の注意を払うなら、私がtorchを使っていることに気づきます.nn.functionalモジュールの関数ですが、問題が来ました.もし必要な計算がこのモジュールになかったらどうしますか.では、問題が来ました.もし必要な計算がこのモジュールになかったらどうしますか.公式サイトのチュートリアルはここです(公式サイトのチュートリアルは高速フーリエ変換をネットワークにカスタマイズし、操作を定義してlossで使用することもできます).https://pytorch.org/tutorials/advanced/numpy_extensions_tutorial.html必要な操作はほんの一歩です
forward()とbackward()の2つのメソッドを定義するだけでいいので、入力を先に呼び出す必要があります.numpy()メソッドは、返す値をtorchにする必要がある.Tensor.
ここまで書くと、ほとんどのニーズを満たしていますが、もう一つの問題があります.もし私が計算する必要があるものがたくさんある(例えば、ピクセルレベルの計算が必要)か、複雑なものがあるか、numpy/scipyにこれらの操作がない場合はどうしますか.
はい、それは最後の方法しかありませんが、C言語の基礎とCUDAプログラミングが必要です(MSRAにはCUDAを書く熟練した神がたくさんいるそうです)
3.PyTorchのC拡張を書く
うん....最近またこれに振り回されて、まだcuda 23333を学んで、これに対して、私は先に公式サイトの教程をあげます
PyTorch C拡張https://pytorch.org/tutorials/advanced/cpp_extension.html#
ある大神が書いたroi_poolingのC拡張ROI
具体的には、基本的なC/CUDA演算を定義する必要があります
文書ディレクトリ
カスタムlossのみが必要であるため、lossは1つ以上のTensorに対する混合計算と見なすことができ、例えば3元グループのLoss(Triplet Loss)を計算するには、(入力された3つの(anchor,positive,negative)テンソル次元がbatch_であると仮定する)テンソル次元がsize * 400)
import torch
import torch.nn as nn
import torch.nn.functional as func
class TripletLossFunc(nn.Module):
def __init__(self, t1, t2, beta):
super(TripletLossFunc, self).__init__()
self.t1 = t1
self.t2 = t2
self.beta = beta
return
def forward(self, anchor, positive, negative):
matched = torch.pow(func.pairwise_distance(anchor, positive), 2)
(func.pairwise_distance(anchor, positive), 2)
part_1 = torch.clamp(matched - mismatched, min=self.t1)
part_2 = torch.clamp(matched, min=self.t2)
dist_hinge = part_1 + self.beta * part_2
loss = torch.mean(dist_hinge)
return loss
図に示すように、init__()でスーパーパラメータを定義し、forward()で計算プロセスを定義すればよい.torchが提供するテンソル計算インタフェース(numpyとscipyも同様に使用できるが、感覚効率は低下する)を使用してcudaを呼び出すことができる(torchインタフェースまたはpython内蔵メソッドのみを使用することができる).つまり、インスタンス化オブジェクトの.cuda()メソッドを直接使用することができる.
nnを受け継いだからModuleなので、このLossクラスはインスタンス化後に直接実行できます_call__()メソッド、つまり
a = TripletLossFunc(...)
loss = a(anchor, positive, negative)
それでいいです.これが最初の方法です.
2.PyTorchによるnumpy/scipy拡張
もしあなたが細心の注意を払うなら、私がtorchを使っていることに気づきます.nn.functionalモジュールの関数ですが、問題が来ました.もし必要な計算がこのモジュールになかったらどうしますか.では、問題が来ました.もし必要な計算がこのモジュールになかったらどうしますか.公式サイトのチュートリアルはここです(公式サイトのチュートリアルは高速フーリエ変換をネットワークにカスタマイズし、操作を定義してlossで使用することもできます).https://pytorch.org/tutorials/advanced/numpy_extensions_tutorial.html必要な操作はほんの一歩です
import torch
from torch.autograd import Function
from troch.autograd import Variable
class OwnOp(Function):
def forward(input_tensor):
tensor = input_tensor.numpy()
...... # numpy/scipy
result = ......
return torch.Tensor(result)
def backward(grad_output):
forward()とbackward()の2つのメソッドを定義するだけでいいので、入力を先に呼び出す必要があります.numpy()メソッドは、返す値をtorchにする必要がある.Tensor.
ここまで書くと、ほとんどのニーズを満たしていますが、もう一つの問題があります.もし私が計算する必要があるものがたくさんある(例えば、ピクセルレベルの計算が必要)か、複雑なものがあるか、numpy/scipyにこれらの操作がない場合はどうしますか.
はい、それは最後の方法しかありませんが、C言語の基礎とCUDAプログラミングが必要です(MSRAにはCUDAを書く熟練した神がたくさんいるそうです)
3.PyTorchのC拡張を書く
うん....最近またこれに振り回されて、まだcuda 23333を学んで、これに対して、私は先に公式サイトの教程をあげます
PyTorch C拡張https://pytorch.org/tutorials/advanced/cpp_extension.html#
ある大神が書いたroi_poolingのC拡張ROI
具体的には、基本的なC/CUDA演算を定義する必要があります
/* triplest_cal.c */
#include
#include
int triplet_cal_forward(...)
{
//
}
int triplet_cal_backward(...)
{
//
}
/* triplet_cal.h *?
int triplet_cal_forward(...);
int triplet_cal_backward(...);
ここのファイル はモジュール と じでなければなりません. えば、モジュール はtriplet_です.cal、ファイル は の りです.そしてforward、backwardの2つの もこのフォーマットに わなければなりません.PyTorch がヘッダファイルを するためのParseを っているので、 する を います.
Cudaも じようにtriplet_を する がありますcal_cuda.cとtriplet_cal_cuda.h cudaはcuda を する がある/* triplet_cal_kernel.cu */
#ifdef __cplusplus
extern "C"{
#endif
#include
#include
#include
#include "triplet_cal_kernel.h"
}
/*
CUDA233333
*/
その 、buildを する があります.py、この を してPyTorchに け れられるようにします( の はまだここまで いていないので、roi_poolingのものを23333 ってきました.このモジュール はroi_poolingと ばれています)import os
import torch
from torch.utils.ffi import create_extension
sources = ['src/roi_pooling.c']
headers = ['src/roi_pooling.h']
definex = []
with_cuda = False
if torch.cuda.is_available():
print('Including CUDA code.')
sources += ['src/roi_pooling_cuda.c']
headers += ['src/roi_pooling.cuda.h']
defines += [('WITH_CUDA', None)]
with_cuda = True
this_file = os.path.dirname(os.path.realpath(__file__))
print(this_file)
extra_objects = ['src/cuda/roi_pooling.cu.o']
extra_objects = [os.path.join(this_file, name) for fname in extra_objects]
ffi = create_extension(
'_ext.roi_pooling',
headers=headers,
sources=sources,
define_macros=defines,
relative_to = __file__,
with_cuda=with_cuda
extra_objects=extra_objects
)
if __name__ == '__main__'
ffi.build()
あと、やるべきことは2とあまり がないので、 び せばいいのですが、 び す にfrom _ext import roi_pooling
にクラスを きます(メソッド2と にforwardとbackwardでroi_poolingを び せばいいです)
があるかもしれません