【libtorch_学习笔记】
最佳答案 问答题库698位专家为你答疑解惑
TypeError: ‘numpy._DTypeMeta‘ object is not subscriptable
文章目录
- Tensor initialization
- 初始化张量
- 张量的布尔运算
- 固定大小和值的初始化
- 固定大小和值随机初始化
- 第三种是从c++中的其他数据类型转换而来
- 已有张量初始化张量
- 张量截取
- Mask过滤张量
- Mask修改张量的值
- 张量拼接和堆叠
- Basic module construction
- 线性层的前向传播函数
- CNN的基本单元构造
- Simple MLP
- CNN
- 简单LSTM
Tensor initialization
初始化张量
import torch# 创建一个形状为 (3, 4, 5) 的张量
tensor = torch.randn(3, 4, 5)# 使用 permute 重新排列维度,例如 (3, 5, 4)
permuted_tensor = tensor.permute(0, 2, 1)print("Original Tensor Shape:", tensor.shape)
print("Permuted Tensor Shape:", permuted_tensor.shape)# 在第二个位置添加一个维度,大小为 1 (3, 1, 5, 4)
unsqueezed_tensor = permuted_tensor.unsqueeze(1)print("Original Permuted Tensor Shape:", permuted_tensor.shape)print("Unsqueezed Tensor Shape:", unsqueezed_tensor.shape)
张量的布尔运算
以下代码使用PyTorch库生成两个3x4的随机矩阵,并打印它们。然后,代码执行矩阵乘法和除法,并打印结果。最后,执行矩阵乘法(不是点乘)并打印结果。注意,在PyTorch中,torch.mm()函数执行矩阵乘法,而.t()函数返回矩阵的转置。
import torch #auto b = torch::rand({ 3,4 });
b = torch.rand([3, 4]) #auto c = torch::rand({ 3,4 });
c = torch.rand([3, 4]) #std::cout << b << std::endl;
print(b) #std::cout << c << std::endl;
print(c) #std::cout << b * c << std::endl;
print(b * c) #std::cout << b / c << std::endl;
print(b / c) #std::cout << b.mm(c.t()) << std::endl;
print(torch.mm(b, c.t()))
固定大小和值的初始化
以下代码创建了五个不同的张量。第一,二,三行分别创建了一个3x4的全0,全1,和4x4的对角线为1其余为0的单位矩阵的张量。第四行创建了一个3x4的全为10的张量。最后一行创建了一个长度为3的一维张量。在每个创建张量后,都使用print()函数将张量打印出来。
import torch # auto b = torch::zeros({ 3,4 });
b = torch.zeros((3, 4))
print(b) # b = torch::ones({ 3,4 });
b = torch.ones((3, 4))
print(b) # b = torch::eye(4);
b = torch.eye(4)
print(b) # b = torch::full({ 3,4 }, 10);
b = torch.full((3, 4), 10)
print(b) # b = torch::tensor({ 33,22,11 });
b = torch.tensor([33, 22, 11])
print(b)
固定大小和值随机初始化
以下代码使用PyTorch库生成随机的3x4矩阵、3x3矩阵,以及从0到4的随机整数3x3矩阵,并分别打印出来。注意,在PyTorch中,我们使用torch.rand()来生成[0,1)区间的均匀随机数,使用torch.randn()来生成标准正态分布的随机数,使用torch.randint()来生成指定范围内的随机整数。
import torch # auto r = torch::rand({ 3,4 });
r = torch.rand((3, 4))
print(r) # r = torch::randn({ 3, 4 });
r = torch.randn((3, 4))
print(r) # std::cout << r << std::endl;
# ...省略cout语句... # r = torch::randint(0, 4, { 3,3 });
r = torch.randint(0, 4, (3, 3))
print(r) # std::cout << r << std::endl;
# ...省略cout语句...
第三种是从c++中的其他数据类型转换而来
在Python的torch中,创建tensor可以使用torch.tensor()函数,如果传入的数据是列表,那么它会自动将数据转换为float类型。在C++中,要明确数据的类型,比如用torch::kFloat表示为float类型。您在代码中使用的torch::from_blob()在Python torch中并没有对应的函数。
import torch # int aa[3] = { 3,4,6 };
aa = [3, 4, 6] # std::vector<float> aaaa = { 3,4,6 };
aaaa = torch.tensor([3.0, 4.0, 6.0]) # auto aaaaa = torch::from_blob(aa, { 3 }, torch::kInt32); //{3}初始值为3,4,6
aaaaa = torch.tensor(aa, dtype=torch.int32)
print(aaaaa) # auto aaa = torch::from_blob(aaaa.data(), { 3 }, torch::kFloat); //{3}初始值为3,4,6
aaa = torch.tensor(aaaa.data, dtype=torch.float32)
print(aaa)
已有张量初始化张量
在Python的PyTorch中,我们使用torch.Tensor()来从另一个张量创建新的张量,这与C++版本的中的torch::Tensor()类似。另外,Python的PyTorch使用dtype参数来指定张量的数据类型,而不是像C++那样使用torch::kFloat等枚举类型。因此,在torch::rand_like(b, torch::kFloat)的Python等价代码中,我们传递dtype=torch.float32来指定生成随机张量的数据类型为float32。
import torch # auto b = torch::zeros({ 3,4 });
b = torch.zeros((3, 4))
print(b) # auto d = torch::Tensor(b);
d = torch.Tensor(b)
print(d) # d = torch::zeros_like(b);
d = torch.zeros_like(b)
print(d) # d = torch::ones_like(b);
d = torch.ones_like(b)
print(d) # d = torch::rand_like(b, torch::kFloat);
d = torch.rand_like(b, dtype=torch.float32)
print(d) # d = b.clone();
d = b.clone()
print(d)
张量截取
C++示例如下
auto b = torch::rand({ 10,3,28,28 });//BxCxHxWstd::cout << b[0].sizes() << std::endl;//[3, 28, 28]std::cout << b[0][0].sizes() << std::endl;//[28, 28]std::cout << b[0][0][0].sizes() << std::endl;//[28]std::cout << b[0][0][0][0].sizes() << std::endl;//[] 0th picture, 0th channel, 0th row, 0th column pixelsstd::cout << b.index_select(0, torch::tensor({ 0, 3, 3 })).sizes() << std::endl;//choose 0th dimension at 0,3,3 to form a tensor of [3,3,28,28]std::cout << b.index_select(1, torch::tensor({ 0,2 })).sizes() << std::endl; //choose 1th dimension at 0 and 2 to form a tensor of[10, 2, 28, 28]std::cout << b.index_select(2, torch::arange(0, 8)).sizes() << std::endl; //choose all the pictures' first 8 rows [10, 3, 8, 28]std::cout << b.narrow(1, 0, 2).sizes() << std::endl;//choose 1th dimension, from 0, cutting out a lenth of 2, [10, 2, 28, 28]std::cout << b.select(3, 2).sizes() << std::endl;//选择第三维的第二个张量, that is, the tensor composed of the second row of all pictures [10, 3, 28]
Python示例如下
import torch # BxCxHxW
b = torch.rand(10, 3, 28, 28) # [3, 28, 28]
print(b[0].shape) # [28, 28]
print(b[0][0].shape) # [28]
print(b[0][0][0].shape) # [] 0th picture, 0th channel, 0th row, 0th column pixels
print(b[0][0][0][0].shape) # choose 0th dimension at 0,3,3 to form a tensor of [3,3,28,28]
index_select_0 = torch.tensor([0, 3, 3])
print(b.index_select(0, index_select_0).shape) # choose 1th dimension at 0 and 2 to form a tensor of[10, 2, 28, 28]
index_select_1 = torch.tensor([0, 2])
print(b.index_select(1, index_select_1).shape) # choose all the pictures' first 8 rows [10, 3, 8, 28]
index_select_2 = torch.arange(0, 8)
print(b.index_select(2, index_select_2).shape) # choose 1th dimension, from 0, cutting out a lenth of 2, [10, 2, 28, 28]
narrow_1 = slice(0, 2)
print(b.narrow(1, narrow_1).shape) # select third dimension's second tensor, that is, the tensor composed of the second row of all pictures [10, 3, 28]
select_3 = 2
print(b.select(3, select_3).shape)
Mask过滤张量
索引需要特别描述。在pytorch中,很容易通过掩码mask直接过滤张量Tensor[mask]。但是,它不能在c++中直接使用,需要通过index函数来实现。代码如下:
C++实现
auto c = torch::randn({ 3,4 });auto mask = torch::zeros({ 3,4 });mask[0][0] = 1;std::cout << c;std::cout << c.index({ mask.to(torch::kBool) });
python实现
import torch # 生成一个形状为 (3, 4) 的标准正态分布张量
c = torch.randn((3, 4)) # 生成一个形状为 (3, 4) 的全零张量
mask = torch.zeros((3, 4)) # 将 mask 中的第0行第0列元素设为1
mask[0, 0] = 1 # 输出 mask 和 c
print(mask)
print(c) # 根据 mask 将 c 中对应的元素取出来,注意在 Python 中索引是从0开始的,因此是[0, 0]而不是[0][0]
print(c[mask.to(torch.bool)])
Mask修改张量的值
有网友提出疑问:从索引得到的张量是深度复制的结果,也就是得到了一个新的张量。然后如何修改原张量掩码所指向的值。搜索torch的api,发现还有一个index_put_函数可以直接放置指定的张量或常量。index_put_和index函数的组合可以实现此任务。
C++实现
auto c = torch::randn({ 3,4 });auto mask = torch::zeros({ 3,4 });mask[0][0] = 1;mask[0][2] = 1;std::cout << c << std::endl;std::cout << c.index({ mask.to(torch::kBool) }) << std::endl;std::cout << c.index_put_({ mask.to(torch::kBool) }, c.index({ mask.to(torch::kBool) }) + 1.5) << std::endl;std::cout << c << std::endl;
python实现
import torch # 生成一个形状为 (3, 4) 的标准正态分布张量
c = torch.randn((3, 4)) # 生成一个形状为 (3, 4) 的全零张量
mask = torch.zeros((3, 4)) # 将 mask 中的第0行第0列元素设为1,第0行第2列元素设为1
mask[0, 0] = 1
mask[0, 2] = 1 # 输出 c 和应用 mask 后得到的新张量
print(c)
print(c[mask.to(torch.bool)]) # 输出应用 mask 后得到的索引位置的张量,并将这些位置的元素更新为 c 中对应索引位置元素 + 1.5
print(c.index_put_(mask.to(torch.bool), c[mask.to(torch.bool)] + 1.5))
print(c)
张量拼接和堆叠
C++代码
auto b = torch::ones({ 3,4 });auto c = torch::zeros({ 3,4 });auto cat = torch::cat({ b,c }, 1);//1 refers to 1th dim, output a tensor of shape [3,8]auto stack = torch::stack({ b,c }, 1);//1refers to 1th dim, output a tensor of shape [3,2,4]std::cout << b << std::endl;std::cout << c << std::endl;std::cout << cat << std::endl;std::cout << stack << std::endl;
python代码
import torch # 生成一个形状为 (3, 4) 的全1张量
b = torch.ones((3, 4))
# 生成一个形状为 (3, 4) 的全0张量
c = torch.zeros((3, 4)) # 在第1维(包括)之后拼接 b 和 c,结果张量的形状为 [3, 8]
cat = torch.cat((b, c), dim=1) # 在第1维(包括)之后堆叠 b 和 c,结果张量的形状为 [3, 2, 4]
stack = torch.stack((b, c), dim=1) # 输出 b、c、cat 和 stack
print(b)
print(c)
print(cat)
print(stack)
Basic module construction
线性层的前向传播函数
C++代码
class LinearBnReluImpl : public torch::nn::Module{
public:LinearBnReluImpl(int intput_features, int output_features);torch::Tensor forward(torch::Tensor x);
private://layerstorch::nn::Linear ln{nullptr};torch::nn::BatchNorm1d bn{nullptr};
};
TORCH_MODULE(LinearBnRelu);LinearBnReluImpl::LinearBnReluImpl(int in_features, int out_features){ln = register_module("ln", torch::nn::Linear(torch::nn::LinearOptions(in_features, out_features)));bn = register_module("bn", torch::nn::BatchNorm1d(out_features));
}torch::Tensor LinearBnReluImpl::forward(torch::Tensor x){x = torch::relu(ln->forward(x));x = bn(x);return x;
}
python代码
import torch
import torch.nn as nn class LinearBnRelu(nn.Module): def __init__(self, input_features, output_features): super(LinearBnRelu, self).__init__() self.linear = nn.Linear(input_features, output_features) self.bn = nn.BatchNorm1d(output_features) def forward(self, x): x = torch.relu(self.linear(x)) x = self.bn(x) return x
CNN的基本单元构造
C++代码
inline torch::nn::Conv2dOptions conv_options(int64_t in_planes, int64_t out_planes, int64_t kerner_size,int64_t stride = 1, int64_t padding = 0, bool with_bias = false) {torch::nn::Conv2dOptions conv_options = torch::nn::Conv2dOptions(in_planes, out_planes, kerner_size);conv_options.stride(stride);conv_options.padding(padding);conv_options.bias(with_bias);return conv_options;
}
class ConvReluBnImpl : public torch::nn::Module {
public:ConvReluBnImpl(int input_channel=3, int output_channel=64, int kernel_size = 3, int stride = 1);torch::Tensor forward(torch::Tensor x);
private:// Declare layerstorch::nn::Conv2d conv{ nullptr };torch::nn::BatchNorm2d bn{ nullptr };
};
TORCH_MODULE(ConvReluBn);ConvReluBnImpl::ConvReluBnImpl(int input_channel, int output_channel, int kernel_size, int stride) {conv = register_module("conv", torch::nn::Conv2d(conv_options(input_channel,output_channel,kernel_size,stride,kernel_size/2)));bn = register_module("bn", torch::nn::BatchNorm2d(output_channel));}torch::Tensor ConvReluBnImpl::forward(torch::Tensor x) {x = torch::relu(conv->forward(x));x = bn(x);return x;
}
python代码
import torch
import torch.nn as nn class ConvReluBn(nn.Module): def __init__(self, input_channel=3, output_channel=64, kernel_size=3, stride=1): super(ConvReluBn, self).__init__() self.conv = nn.Conv2d(input_channel, output_channel, kernel_size, stride, kernel_size//2) self.bn = nn.BatchNorm2d(output_channel) def forward(self, x): x = nn.functional.relu(self.conv(x)) x = self.bn(x) return x
Simple MLP
C++代码
#include <torch/torch.h>
#include <torch/script.h>
class LinearBnReluImpl : public torch::nn::Module
{
public:LinearBnReluImpl(int intput_features, int output_features);torch::Tensor forward(torch::Tensor x);
private://layerstorch::nn::Linear ln{ nullptr };torch::nn::BatchNorm1d bn{ nullptr };
};TORCH_MODULE(LinearBnRelu);
LinearBnReluImpl::LinearBnReluImpl(int in_features, int out_features)
{ln = register_module("ln", torch::nn::Linear(torch::nn::LinearOptions(in_features, out_features)));bn = register_module("bn", torch::nn::BatchNorm1d(out_features));
}torch::Tensor LinearBnReluImpl::forward(torch::Tensor x)
{x = torch::relu(ln->forward(x));x = bn(x);return x;
}class MLP : public torch::nn::Module
{
public:MLP(int in_features, int out_features);torch::Tensor forward(torch::Tensor x);
private:int mid_features[3] = { 32,64,128 };LinearBnRelu ln1{ nullptr };LinearBnRelu ln2{ nullptr };LinearBnRelu ln3{ nullptr };torch::nn::Linear out_ln{ nullptr };
};MLP::MLP(int in_features, int out_features)
{ln1 = LinearBnRelu(in_features, mid_features[0]);ln2 = LinearBnRelu(mid_features[0], mid_features[1]);ln3 = LinearBnRelu(mid_features[1], mid_features[2]);out_ln = torch::nn::Linear(mid_features[2], out_features);ln1 = register_module("ln1", ln1);ln2 = register_module("ln2", ln2);ln3 = register_module("ln3", ln3);out_ln = register_module("out_ln", out_ln);
}torch::Tensor MLP::forward(torch::Tensor x)
{x = ln1->forward(x);x = ln2->forward(x);x = ln3->forward(x);x = out_ln->forward(x);return x;
}int main()
{auto mlp = MLP(10, 1);auto mlp_input = torch::rand({ 2,10 });auto mlp_target = torch::ones({ 2,1 });torch::optim::Adam optimizer_mlp(mlp.parameters(), 0.0005);for (int i = 0; i < 400; i++) {optimizer_mlp.zero_grad();auto out = mlp.forward(mlp_input);auto loss = torch::mse_loss(out, mlp_target);loss.backward();optimizer_mlp.step();std::cout << out;}return 0;
}
python代码
import torch
import torch.nn as nnclass MLP(nn.Module):def __init__(self, in_features, out_features):super(MLP, self).__init__()self.mid_features = [32, 64, 128]self.ln1 = nn.Sequential(nn.Linear(in_features, self.mid_features[0]),nn.BatchNorm1d(self.mid_features[0]),nn.ReLU())self.ln2 = nn.Sequential(nn.Linear(self.mid_features[0], self.mid_features[1]),nn.BatchNorm1d(self.mid_features[1]),nn.ReLU())self.ln3 = nn.Sequential(nn.Linear(self.mid_features[1], self.mid_features[2]),nn.BatchNorm1d(self.mid_features[2]),nn.ReLU())self.out_ln = nn.Linear(self.mid_features[2], out_features)def forward(self, x):x = self.ln1(x)x = self.ln2(x)x = self.ln3(x)x = self.out_ln(x)return xmlp = MLP(10, 1)
mlp_input = torch.rand(2, 10)
mlp_target = torch.ones(2, 1)
optimizer = torch.optim.Adam(mlp.parameters(), lr= 0.005)
mse_loss = torch.nn.MSELoss()
for i in range(400) :optimizer.zero_grad()out = mlp.forward(mlp_input)loss = mse_loss(out, mlp_target)loss.backward()optimizer.step()print('train_loss: %.3f ' %(loss))
CNN
C++代码
class plainCNN : public torch::nn::Module{
public:plainCNN(int in_channels, int out_channels);torch::Tensor forward(torch::Tensor x);
private:int mid_channels[3] = {32,64,128};ConvReluBn conv1{nullptr};ConvReluBn down1{nullptr};ConvReluBn conv2{nullptr};ConvReluBn down2{nullptr};ConvReluBn conv3{nullptr};ConvReluBn down3{nullptr};torch::nn::Conv2d out_conv{nullptr};
};plainCNN::plainCNN(int in_channels, int out_channels){conv1 = ConvReluBn(in_channels,mid_channels[0],3);down1 = ConvReluBn(mid_channels[0],mid_channels[0],3,2);conv2 = ConvReluBn(mid_channels[0],mid_channels[1],3);down2 = ConvReluBn(mid_channels[1],mid_channels[1],3,2);conv3 = ConvReluBn(mid_channels[1],mid_channels[2],3);down3 = ConvReluBn(mid_channels[2],mid_channels[2],3,2);out_conv = torch::nn::Conv2d(conv_options(mid_channels[2],out_channels,3));conv1 = register_module("conv1",conv1);down1 = register_module("down1",down1);conv2 = register_module("conv2",conv2);down2 = register_module("down2",down2);conv3 = register_module("conv3",conv3);down3 = register_module("down3",down3);out_conv = register_module("out_conv",out_conv);
}torch::Tensor plainCNN::forward(torch::Tensor x){x = conv1->forward(x);x = down1->forward(x);x = conv2->forward(x);x = down2->forward(x);x = conv3->forward(x);x = down3->forward(x);x = out_conv->forward(x);return x;
}
python代码
import torch.nn as nn class PlainCNN(nn.Module): def __init__(self, in_channels, out_channels): super(PlainCNN, self).__init__() self.mid_channels = [32, 64, 128] self.conv1 = nn.Sequential(nn.Conv2d(in_channels, self.mid_channels[0], kernel_size=3, padding=1), nn.ReLU()) self.down1 = nn.Sequential(nn.Conv2d(self.mid_channels[0], self.mid_channels[0], kernel_size=3, stride=2, padding=1), nn.ReLU()) self.conv2 = nn.Sequential(nn.Conv2d(self.mid_channels[0], self.mid_channels[1], kernel_size=3, padding=1), nn.ReLU()) self.down2 = nn.Sequential(nn.Conv2d(self.mid_channels[1], self.mid_channels[1], kernel_size=3, stride=2, padding=1), nn.ReLU()) self.conv3 = nn.Sequential(nn.Conv2d(self.mid_channels[1], self.mid_channels[2], kernel_size=3, padding=1), nn.ReLU()) self.down3 = nn.Sequential(nn.Conv2d(self.mid_channels[2], self.mid_channels[2], kernel_size=3, stride=2, padding=1), nn.ReLU()) self.out_conv = nn.Conv2d(self.mid_channels[2], out_channels, kernel_size=3) def forward(self, x): x = self.conv1(x) x = self.down1(x) x = self.conv2(x) x = self.down2(x) x = self.conv3(x) x = self.down3(x) x = self.out_conv(x) return x
简单LSTM
C++代码
inline torch::nn::LSTMOptions lstmOption(int in_features, int hidden_layer_size, int num_layers, bool batch_first = false, bool bidirectional = false){torch::nn::LSTMOptions lstmOption = torch::nn::LSTMOptions(in_features, hidden_layer_size);lstmOption.num_layers(num_layers).batch_first(batch_first).bidirectional(bidirectional);return lstmOption;
}//batch_first: true for io(batch, seq, feature) else io(seq, batch, feature)
class LSTM: public torch::nn::Module{
public:LSTM(int in_features, int hidden_layer_size, int out_size, int num_layers, bool batch_first);torch::Tensor forward(torch::Tensor x);
private:torch::nn::LSTM lstm{nullptr};torch::nn::Linear ln{nullptr};std::tuple<torch::Tensor, torch::Tensor> hidden_cell;
};
python代码
import torch
import torch.nn as nn def lstm_options(in_features, hidden_layer_size, num_layers, batch_first=False, bidirectional=False): lstm_options = nn.LSTM(in_features, hidden_layer_size, num_layers, batch_first, bidirectional) return lstm_options class LSTM(nn.Module): def __init__(self, in_features, hidden_layer_size, out_size, num_layers, batch_first): super(LSTM, self).__init__() self.lstm = lstm_options(in_features, hidden_layer_size, num_layers, batch_first) self.ln = nn.Linear(hidden_layer_size, out_size) def forward(self, x): lstm_out, _ = self.lstm(x) predictions = self.ln(lstm_out[:, -1, :]) return predictions
99%的人还看了
相似问题
猜你感兴趣
版权申明
本文"【libtorch_学习笔记】":http://eshow365.cn/6-19966-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!