Libtorchの基本操作

Libtorch の Tensor は、Pytorch の Tensor に対応します。これは、ライブラリのコア データ構造であり、さまざまなデバイス上で実行でき、勾配をサポートする tensor です。使用法は Pytorch の Tensor に似ていますが、スライス操作など、一部の Python ではサポートされているが C++ ではサポートされていない構文にいくつかの違いがあります。

Libtorch を使用する前に、Libtorch のヘッダー ファイルをインクルードする必要がありますtorch/torch.h

#include <torch/torch.h>

使用される多くの関数はこのヘッダー ファイルで宣言されており、これらの関数の名前空間はすべて であるtorchため、torch::xxxの形式で呼び出すことができます。

テンソルの作成

Tensor は、リテラル、C++ 配列、ベクトル、Libtorch の関数など、さまざまな方法で作成できます。

リテラルで Tensor を作成します。

#include <torch/torch.h>
#include <iostream>

int main(){
    
    
	torch::Tensor x = torch::tensor({
    
    1, 2, 3, 4});
	
	std::cout << x << std::endl;
	
	system("pause");
	
	return 0;
}
---------
1
2
3
4
[ CPULongType{
    
    4} ]

配列から Tensor を作成するtorch::from_blob()と、配列を Tensor に変換するときに関数が再形成されます。

#include <torch/torch.h>
#include <iostream>

int main(){
    
    
	float arr[5] = {
    
    1, 2, 3, 4, 5};
	torch::Tensor x = torch::from_blob(arr, {
    
    1, 5});  // 第一个参数为数组,第二个参数为创建的Tensor shape
	
	std::cout << x << std::endl;
	
	system("pause");
	
	return 0;
}
---------
 1  2  3  4  5
[ CPUFloatType{
    
    1,5} ]

ベクトルからテンソルを作成します。

#include <torch/torch.h>
#include <iostream>

int main(){
    
    
	std::vector<float> v = {
    
    1.0, 2, 3, 4.0};
	torch::Tensor x = torch::from_blob(v.data(), {
    
    2, 2});
	
	std::cout << x << std::endl;
	
	system("pause");
	
	return 0;
}
---------
1  2
3  4
[ CPUFloatType{
    
    2,2} ]

Libtorch の関数を使用して Tensor を作成します。

#include <torch/torch.h>
#include <iostream>

int main(){
    
    
	torch::Tensor x1 = torch::arange(4);
	torch::Tensor x2 = torch::arange(12);
	x2 = torch::reshape(x2, {
    
    3, 4});  // C++中没有tuple类型,因此参数不能用小括号,否则会出错
	torch::Tensor x3 = torch::ones(3);
	torch::Tensor x4 = torch::ones({
    
    3, 3});
	torch::Tensor x5 = torch::zeros(4);
	torch::Tensor x6 = torch::eye(3);
	torch::Tensor x7 = torch::rand({
    
    2, 3});
	torch::Tensor x8 = torch::randn({
    
    1, 5});
	
	std::cout << x1 << std::endl;
	std::cout << x2 << std::endl;
	std::cout << x3 << std::endl;
	std::cout << x4 << std::endl;
	std::cout << x5 << std::endl;
	std::cout << x6 << std::endl;
	std::cout << x7 << std::endl;
	std::cout << x8 << std::endl;
	
	system("pause");
	
	return 0;
}
---------
 0
 1
 2
 3
[ CPULongType{
    
    4} ]
 0   1   2   3
 4   5   6   7
 8   9  10  11
[ CPULongType{
    
    3,4} ]
 1
 1
 1
[ CPUFloatType{
    
    3} ]
 1  1  1
 1  1  1
 1  1  1
[ CPUFloatType{
    
    3,3} ]
 0
 0
 0
 0
[ CPUFloatType{
    
    4} ]
 1  0  0
 0  1  0
 0  0  1
[ CPUFloatType{
    
    3,3} ]
 0.1380  0.1055  0.2361
 0.4628  0.0153  0.0506
[ CPUFloatType{
    
    2,3} ]
 0.2509  0.4332 -1.6624 -0.5655  1.4356
[ CPUFloatType{
    
    1,5} ]

Tensor オブジェクトのプロパティ関数

Tensor を作成した後、多くの場合、それらのプロパティの一部をチェックして、期待どおりかどうかを確認する必要があります。Libtorch の Tensor にはパブリックにアクセスできるプロパティがなく、Tensor のプロパティ情報はプロパティ関数を通じて取得する必要があります。一般的な属性関数は次のとおりです。

  • dim(): テンソル次元
  • size(): Pytorchのshape属性と同じ
  • size(n): n 次元の形状
  • numel(): 要素の総数。size() の要素が乗算されます。
  • dtype(): データ型
  • device(): Tensor が配置されているデバイス タイプ (CPU、CUDA、MPS など)。
#include <torch/torch.h>
#include <iostream>

int main(){
    
    
	torch::Tensor x = torch::tensor({
    
    {
    
    1, 2, 3}, {
    
    4, 5, 6}});
	
	auto dim = x.dim();  // 2
	auto sizes = x.sizes();  // [2, 3]
	auto size_0 = x.size(0);  // 2
	auto numel = x.numel();  // 6
	auto dtype = x.dtype();  // int64
	auto device = x.device();  // cpu
	
	std::cout << "dim: \n" << dim << std::endl;
	std::cout << "sizes: \n" << sizes << std::endl;
	std::cout << "size_0: \n" << size_0 << std::endl;
	std::cout << "numel: \n" << numel << std::endl;
	std::cout << "dtype: \n" << dtype << std::endl;
	std::cout << "device: \n" << device << std::endl;
	
	system("pause");
	
	return 0;
}
---------
dim:
2
sizes:
[2, 3]
size_0:
2
numel:
6
dtype:
__int64
device:
cpu

Tensor オブジェクトのインデックス

Libtorch の Tensor は、Pytorch の Tensor のように添え字によって要素を取得することもできます。

#include <torch/torch.h>
#include <iostream>

int main(){
    
    
	torch::Tensor x = torch::tensor({
    
    {
    
    1, 2, 3}, {
    
    4, 5, 6}});
	auto ele = x[0][2];
	
	std::cout << ele << std::endl;
	
	system("pause");
	
	return 0;
}
---------
3
[ CPULongType{
    
    } ]

上記のメソッドに加えて、indexTensor オブジェクトの関数を使用して要素を取得することもできます。その利点の 1 つは support ですSlice単一の要素を取得するには、index({dim_0, dim_1, dim_2})メソッドを直接使用してインデックスを作成できます。

#include <torch/torch.h>
#include <iostream>

int main(){
    
    
	torch::Tensor x = torch::rand({
    
    1, 3, 4, 4});  // 生成一个4维的Tensor
	auto ele1 = x.index({
    
    0, 1, 2, 2});  // 通过index方式获取单个元素
	auto ele2 = x[0][1][2][2];  // 通过下标方式获取单个元素
	
	std::cout << ele1 << std::endl;
	std::cout << ele2 << std::endl;
	
	system("pause");
	
	return 0;
}
---------
0.627059
[ CPUFloatType{
    
    } ]
0.627059
[ CPUFloatType{
    
    } ]

Python のように x[:, 0:1, 2:, :-1] のようなスライスを取得したい場合、Libtorch ではどのように表現すればよいでしょうか? ここでは、オブジェクトを使用して Python で Slice を実装する必要がありますtorch::indexing::Slice。例は次のとおりです。

#include <torch/torch.h>
#include <iostream>
using namespace torch::indexing;  // 使用该命名空间后,在使用Slice时便可直接写成Slice,而无需写成torch::indexing::Slice

int main(){
    
    
	torch::Tensor x = torch::rand({
    
    1, 3, 4, 4});  // 生成一个4维的Tensor
	auto ele = x.index({
    
    Slice(), Slice(0, 1), Slice(2, None), Slice(None, -1)});  // 等效于Python中的x[:, 0:1, 2:, :-1]
	
	std::cout << ele << std::endl;
	
	system("pause");
	
	return 0;
}
---------
(1,1,.,.) =
  0.1014  0.1333  0.8851
  0.1299  0.1242  0.1836
[ CPUFloatType{
    
    1,1,2,3} ]

Tensor でデータを取得する

Tensor は Libtorch オブジェクトですが、その中のデータをファイルに保存したり、他の関数に渡したりするにはどうすればよいでしょうか? 関数を使用するdata_ptrだけです:

#include <torch/torch.h>
#include <iostream>

int main(){
    
    
	torch::Tensor x = torch::rand({
    
    2, 3});  
	float* data = x.data_prt<float>();
	
	std::cout << data << std::endl;
	
	system("pause");
	
	return 0;
}
---------
00000192CDA7A580

単一要素の Tensor の場合、item関数を使用して特定の値を取得することもできます。

#include <torch/torch.h>
#include <iostream>

int main(){
    
    
	torch::Tensor x = torch::tensor({
    
    {
    
    23.27}});  
	float value = x.item<float>();
	
	std::cout << value << std::endl;
	
	system("pause");
	
	return 0;
}
---------
23.27

データの種類

Libtorch は、float16、float32、float64、int8、int16、int32、int64、uint8 の Tensor データ型をサポートしており、to型変換には関数を使用できます。

bar = foo.to(torch::kF16);
bar = foo.to(torch::kF32);
bar = foo.to(torch::kF64);
bar = foo.to(torch::kFloat16);
bar = foo.to(torch::kFloat32);
bar = foo.to(torch::kFloat64);
bar = foo.to(torch::kI8);
bar = foo.to(torch::kI16);
bar = foo.to(torch::kI32);
bar = foo.to(torch::kI64);
bar = foo.to(torch::kInt8);
bar = foo.to(torch::kInt16);
bar = foo.to(torch::kInt32);
bar = foo.to(torch::kInt64);
bar = foo.to(torch::kU8);
bar = foo.to(torch::kUInt8);

設備の種類

デバイスタイプとはTensorを保存するデバイスの種類のことで、LibtorchはCPUだけでなく様々な種類のGPUをサポートしているため、デバイスタイプが多くなります。

Libtorch でサポートされているすべてのデバイス タイプを以下に示します。

Variable c10::kCPU
Variable c10::kCUDA
Variable c10::kFPGA
Variable c10::kHIP
Variable c10::kHPU
Variable c10::kIPU
Variable c10::kLazy
Variable c10::kMeta
Variable c10::kMetal
Variable c10::kMPS
Variable c10::kMTIA
Variable c10::kORT
Variable c10::kPrivateUse1
Variable c10::kVE
Variable c10::kVulkan
Variable c10::kXLA
Variable c10::kXPU

デバイスはコンパイル時の設定とマシンがデバイスをサポートするかどうかに大きく関係しており、デバイスによってはデバイスが十分にサポートされていないことに注意してください。

テンソルの変形関数

多くの場合、Tensor の形状を変更する必要があります。Libtorch には、この点に関する追加のサポートもあります。具体的なサポートは次のとおりです。

  • 形を変える
  • 平らにする
  • 絞る
  • 絞る
  • 転置
  • 猫/連結/連結

そして、torch::reshapeこの種の静的関数とtensor.reshapeこの種のオブジェクト関数をサポートします。

#include <torch/torch.h>
#include <iostream>

int main(){
    
    
	torch::Tensor x = torch::arange(12);
	
	auto x1 = x.reshape({
    
    3, 4});  // 也可以写成torch::reshape({3, 4});
	auto x2 = x1.flatten();  // 所有维度展平成一维向量
	auto x3 = x1.unsqueeze(0);  // 在第0维增加一个维度
	auto x4 = x3.squeeze();  // 压缩维度,将所有数值为1的维度删除
	auto x5 = x1.transpose(1, 0);  // 转置,将x1的第一维放到x5的第0维,将x1的第0维放到x5的第一维
	auto x6 = torch::cat({
    
    x1, x1}, 1);  // 沿着第一维进行拼接
	
	std::cout << x1 << std::endl;
	std::cout << x2 << std::endl;
	std::cout << x3 << std::endl;
	std::cout << x4 << std::endl;
	std::cout << x5 << std::endl;
	std::cout << x6 << std::endl;
	
	system("pause");
	
	return 0;
}
---------
 0   1   2   3
 4   5   6   7
 8   9  10  11
[ CPULongType{
    
    3,4} ]
  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
[ CPULongType{
    
    12} ]
(1,.,.) =
   0   1   2   3
   4   5   6   7
   8   9  10  11
[ CPULongType{
    
    1,3,4} ]
  0   1   2   3
  4   5   6   7
  8   9  10  11
[ CPULongType{
    
    3,4} ]
  0   4   8
  1   5   9
  2   6  10
  3   7  11
[ CPULongType{
    
    4,3} ]
  0   1   2   3   0   1   2   3
  4   5   6   7   4   5   6   7
  8   9  10  11   8   9  10  11
[ CPULongType{
    
    3,8} ]

特別な機能は、transpose が 2 つの軸の交換のみをサポートしており、複数の軸の交換を実現するには複数回呼び出す必要があることです。

Tensor間の演算関数

Tensor ライブラリでは、行列の乗算、内積の計算、外積の計算など、Tensor と Tensor 間の演算は非常に一般的です。組み込み関数のサポートにより、多くの追加の開発作業を回避できます。

#include <torch/torch.h>
#include <iostream>

int main(){
    
    
	torch::Tensor x = torch::tensor({
    
    {
    
    1, 2, 3}, {
    
    4, 5, 6}});
	torch::Tensor y = torch::tensor({
    
    {
    
    10, 20}, {
    
    30, 40}, {
    
    50, 60}});
	torch::Tensor z = torch::tensor({
    
    {
    
    10, 20, 30}, {
    
    40, 50, 60}});
	
	auto z1 = torch::matmul(x, y);  // 矩阵乘法
	auto z2 = torch::mul(x, z);  // 矩阵点乘,两个矩阵的维度需一致
	
	std::cout << z1 << std::endl;
	std::cout << z2 << std::endl;
	
	system("pause");
	
	return 0;
}
---------
 220  280
 490  640
[ CPULongType{
    
    2,2} ]
  10   40   90
 160  250  360
[ CPULongType{
    
    2,3} ]

ニューラルネットワーク相関関数

ニューラル ネットワークは、torch のコア モジュールです。いくつかの一般的な畳み込み層と全結合層は、関数の形式で Tensor に適用できます。いくつかの簡単な例を次に示します:

bar = torch::softmax(foo, -1);
bar = torch::sigmoid(foo);
bar = torch::relu(foo);
bar = torch::gelu(foo);

おすすめ

転載: blog.csdn.net/weixin_48158964/article/details/132302333