TypeError: ‘numpy._DTypeMeta‘ object is not subscriptable
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)
# 函数创建了一个从 1 到 15 的等差数列,长度为 15,并将其转换为一个 torch::Tensor 张量。该张量的形状为 [15]。
auto linspace = torch::linspace(1, 15, 15); //[1]
auto unsqueeze = torch::Tensor(linspace).unsqueeze(1);//[15,1]
auto tensor = unsqueeze.repeat({ 1,3 });//第一个维度不变,第二个维度重复3次 [15,3]
auto unsqueeze1 = tensor.unsqueeze(0);//[1,15,3]
auto lstm_input = unsqueeze1.repeat({ 4,1,1 });//第一个维度重复4次,第二、三个维度不变[4,15,3]
print("Original Permuted Tensor Shape:", permuted_tensor.shape)
print("Unsqueezed Tensor Shape:", unsqueezed_tensor.shape)
#在 PyTorch 中,y = x.repeat((4,1,1)) 表示将 x 张量沿着第一个维度重复 4 次,不重复第二个和第三个维度。
以下代码使用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语句...
在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 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 });//BxCxHxW
std::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 pixels
std::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)
索引需要特别描述。在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)])
有网友提出疑问:从索引得到的张量是深度复制的结果,也就是得到了一个新的张量。然后如何修改原张量掩码所指向的值。搜索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)
C++代码
class LinearBnReluImpl : public torch::nn::Module{
public:
LinearBnReluImpl(int intput_features, int output_features);
torch::Tensor forward(torch::Tensor x);
private:
//layers
torch::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
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 layers
torch::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
C++代码
#include
#include
class LinearBnReluImpl : public torch::nn::Module
{
public:
LinearBnReluImpl(int intput_features, int output_features);
torch::Tensor forward(torch::Tensor x);
private:
//layers
torch::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 nn
class 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 x
mlp = 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))
C++代码
#include
#include
inline torch::nn::Conv2dOptions conv_options(int64_t in_channels, int64_t out_channels, 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_channels, out_channels, 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 layers
torch::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)
{
auto conv2d_options = conv_options(input_channel, output_channel, kernel_size, stride, kernel_size / 2);
torch::nn::Conv2d conv2d_impl(conv2d_options);
conv = register_module("conv", conv2d_impl);
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;
}
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) {//{ 32,64,128 };
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;
}
int main()
{
auto cnn = plainCNN(3, 1);
auto cnn_input = torch::randint(255, { 1,3,224,224 });
torch::optim::Adam optimizer_cnn(cnn.parameters(), 0.0003);
auto cnn_target = torch::zeros({ 1,1,26,26 });
for (int i = 0; i < 30; i++) {
optimizer_cnn.zero_grad();
auto out = cnn.forward(cnn_input);
auto loss = torch::mse_loss(out, cnn_target);
loss.backward();
optimizer_cnn.step();
std::cout << out[0][0][0];
}
return 0;
}
python代码
import torch
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], 3,stride=1,padding=1,bias=False),
nn.ReLU(),
nn.BatchNorm2d(self.mid_channels[0]))
self.down1 = nn.Sequential(nn.Conv2d(self.mid_channels[0], self.mid_channels[0], 3,stride=2,padding=1,bias=False),
nn.ReLU(),
nn.BatchNorm2d(self.mid_channels[0]))
self. conv2 = nn.Sequential(nn.Conv2d(self.mid_channels[0], self.mid_channels[1], 3,stride=1,padding=1,bias=False),
nn.ReLU(),
nn.BatchNorm2d(self.mid_channels[1]))
self.down2 = nn.Sequential(nn.Conv2d(self.mid_channels[1], self.mid_channels[1], 3,stride=2,padding=1,bias=False),
nn.ReLU(),
nn.BatchNorm2d(self.mid_channels[1]))
self. conv3 = nn.Sequential(nn.Conv2d(self.mid_channels[1], self.mid_channels[2], 3,stride=1,padding=1,bias=False),
nn.ReLU(),
nn.BatchNorm2d(self.mid_channels[2]))
self.down3 = nn.Sequential(nn.Conv2d(self.mid_channels[2], self.mid_channels[2], 3,stride=2,padding=1,bias=False),
nn.ReLU(),
nn.BatchNorm2d(self.mid_channels[2]))
self.out_conv =nn.Conv2d(self.mid_channels[2], out_channels, 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
if __name__ == '__main__':
cnn = plainCNN(3, 1)
cnn_input = torch.randint(255, (1, 3, 224, 224))
cnn_input = cnn_input.type(torch.float)
optimizer_cnn = torch.optim.Adam(cnn.parameters(), lr=0.0003)
cnn_target = torch.zeros((1, 1, 26, 26))
for i in range(30):
optimizer_cnn.zero_grad()
out = cnn(cnn_input)
loss = torch.nn.functional.mse_loss(out, cnn_target)
loss.backward()
optimizer_cnn.step()
print(out[0, 0, 0])
C++代码
#pragma once
#include
#include
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;
};
LSTM::LSTM(int in_features, int hidden_layer_size, int out_size, int num_layers, bool batch_first)
{
lstm = torch::nn::LSTM(lstmOption(in_features, hidden_layer_size, num_layers, batch_first));
ln = torch::nn::Linear(hidden_layer_size, out_size);
lstm = register_module("lstm", lstm);
ln = register_module("ln", ln);
}
torch::Tensor LSTM::forward(torch::Tensor x) {
auto lstm_out = lstm->forward(x);
auto predictions = ln->forward(std::get<0>(lstm_out));
return predictions.select(1, -1);
}
int main()
//LSTM part
auto lstm = LSTM(3, 100, 2,1,true);
auto lstm_input = torch::Tensor(torch::linspace(1,15,15)).unsqueeze(1).repeat({1,3}).unsqueeze(0).repeat({4,1,1});//[4,15,3]
auto lstm_target = torch::full({4,2},16).to(torch::kFloat);
auto optimizer_lstm = torch::optim::Adam(lstm.parameters(),0.003);
for(int i=0; i<130;i++){
optimizer_lstm.zero_grad();
auto out = lstm.forward(lstm_input.to(torch::kFloat));
auto loss = torch::mse_loss(out,lstm_target);
loss.backward();
optimizer_lstm.step();
cout<<out;
}
return 0;
}
python代码
import torch
class LSTM(torch.nn.Module):
def __init__(self, in_features, hidden_layer_size, out_size, num_layers, batch_first=True):
super(LSTM, self).__init__()
self.lstm = torch.nn.LSTM(in_features, hidden_layer_size, num_layers, batch_first=batch_first)
self.ln = torch.nn.Linear(hidden_layer_size, out_size)
def forward(self, x):
lstm_out = self.lstm(x)
predictions = self.ln(lstm_out[0])
return predictions[:, -1]
# LSTM part
lstm = LSTM(3, 100, 2, 1, batch_first=True)
lstm_input = torch.linspace(1, 15, 15).unsqueeze(1).repeat(1, 3).unsqueeze(0).repeat(4, 1, 1) # [4, 15, 3]
lstm_target = torch.full((4, 2), 16).float()
optimizer = torch.optim.Adam(lstm.parameters(), lr=0.003)
mse_loss = torch.nn.MSELoss()
for i in range(130):
optimizer.zero_grad()
out = lstm(lstm_input)
loss = mse_loss(out, lstm_target)
loss.backward()
optimizer.step()
print(out)
数据下载地址下载到本地并解压
Picture file traversal
C++代码
#pragma once
#include
#include
#include
#include
void load_data_from_folder(std::string path, std::string type, std::vector<std::string>& list_images, std::vector<int>& list_labels, int label);
class DataSetClc :public torch::data::Dataset<DataSetClc >
{
public:
int num_classes = 0;
DataSetClc(std::string image_dir, std::string type)
{
load_data_from_folder(image_dir, std::string(type), image_paths, labels, num_classes);
}
// Override get() function to return tensor at location index
torch::data::Example<> get(size_t index) override
{
std::string image_path = image_paths.at(index);
cv::Mat image = cv::imread(image_path);
cv::resize(image, image, cv::Size(224, 224));
int label = labels.at(index);
torch::Tensor img_tensor = torch::from_blob(image.data, { image.rows, image.cols, 3 }, torch::kByte).permute({ 2, 0, 1 }); // Channels x Height x Width
torch::Tensor label_tensor = torch::full({ 1 }, label);
return { img_tensor.clone(), label_tensor.clone() };
}
// Return the length of data
torch::optional<size_t> size() const override
{
return image_paths.size();
};
private:
std::vector<std::string> image_paths;
std::vector<int> labels;
};
//遍历该目录下的.jpg图片
void load_data_from_folder(std::string path, std::string type, std::vector<std::string>& list_images, std::vector<int>& list_labels, int label)
{
long long hFile = 0; //句柄
struct _finddata_t fileInfo;
std::string pathName;
if ((hFile = _findfirst(pathName.assign(path).append("\\*.*").c_str(), &fileInfo)) == -1)
{
return;
}
do
{
const char* s = fileInfo.name;
const char* t = type.data();
if (fileInfo.attrib & _A_SUBDIR) //是子文件夹
{
//遍历子文件夹中的文件(夹)
if (strcmp(s, ".") == 0 || strcmp(s, "..") == 0) //子文件夹目录是.或者..
continue;
std::string sub_path = path + "\\" + fileInfo.name;
label++;
load_data_from_folder(sub_path, type, list_images, list_labels, label);
}
else //判断是不是后缀为type文件
{
if (strstr(s, t))
{
std::string image_path = path + "\\" + fileInfo.name;
list_images.push_back(image_path);
list_labels.push_back(label);
}
}
} while (_findnext(hFile, &fileInfo) == 0);
return;
}
int main()
{
int batch_size = 2;
std::string image_dir = "E:\\data\\hymenoptera_data\\train";
auto mdataset = DataSetClc(image_dir, ".jpg").map(torch::data::transforms::Stack<>());
auto mdataloader = torch::data::make_data_loader<torch::data::samplers::RandomSampler>(std::move(mdataset), batch_size);
for (auto& batch : *mdataloader)
{
auto data = batch.data;
auto target = batch.target;
std::cout << data.sizes() << target;
}
return 0;
}
python代码
import torch
import cv2
import os
def load_data_from_folder(path, type, list_images, list_labels, label):
# Traverse the .jpg images in the directory
for file in os.listdir(path):
s = file
t = type
if os.path.isdir(os.path.join(path, file)): # If it is a subfolder
# Traverse the files (folders) in the subfolder
if s == "." or s == "..": # If the subfolder directory is . or ..
continue
sub_path = os.path.join(path, file)
label += 1
load_data_from_folder(sub_path, type, list_images, list_labels, label)
else: # Check if it is a file with suffix type
if t in s:
image_path = os.path.join(path, file)
list_images.append(image_path)
list_labels.append(label)
return
class DataSetClc(torch.utils.data.Dataset):
def __init__(self, image_dir, type):
self.num_classes = 0
self.image_paths = []
self.labels = []
load_data_from_folder(image_dir, type, self.image_paths, self.labels, self.num_classes)
def __getitem__(self, index):
# Override get() function to return tensor at location index
image_path = self.image_paths[index]
image = cv2.imread(image_path)
image = cv2.resize(image, (224, 224))
label = self.labels[index]
img_tensor = torch.from_numpy(image).permute(2, 0, 1) # Channels x Height x Width
label_tensor = torch.full((1,), label)
return img_tensor.clone(), label_tensor.clone()
def __len__(self):
# Return the length of data
return len(self.image_paths)
def main():
batch_size = 2
image_dir = "E:\\data\\hymenoptera_data\\train"
mdataset = DataSetClc(image_dir, ".jpg")
mdataloader = torch.utils.data.DataLoader(mdataset, batch_size=batch_size, shuffle=True)
for batch in mdataloader:
data = batch[0]
target = batch[1]
print(data.size(), target)
if __name__ == "__main__":
main()
C++代码
python代码
C++代码
python代码
C++代码
python代码
C++代码
python代码
C++代码
python代码
C++代码
python代码
C++代码
python代码