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{
} ]
上記のメソッドに加えて、index
Tensor オブジェクトの関数を使用して要素を取得することもできます。その利点の 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);