• 【python_学习笔记】


    TypeError: ‘numpy._DTypeMeta‘ object is not subscriptable

    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)
    
    # 函数创建了一个从 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 次,不重复第二个和第三个维度。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    张量的布尔运算

    以下代码使用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()))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    固定大小和值的初始化

    以下代码创建了五个不同的张量。第一,二,三行分别创建了一个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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    固定大小和值随机初始化

    以下代码使用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语句...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    第三种是从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 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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    已有张量初始化张量

    在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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    张量截取

    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]
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    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) });
    
    • 1
    • 2
    • 3
    • 4
    • 5

    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)])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    张量拼接和堆叠

    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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    BasicModels

    线性层的前向传播函数

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    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 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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    Simple MLP

    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;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

    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))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    CNN

    官网介绍Conv2d的用法
    在这里插入图片描述

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100

    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])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    简单LSTM

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    DatasetUtilization

    数据下载地址下载到本地并解压
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89

    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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    TrainingVGG

    C++代码
    python代码

    C++代码
    python代码

    C++代码
    python代码

    C++代码
    python代码

    C++代码
    python代码

    C++代码
    python代码

    C++代码
    python代码

  • 相关阅读:
    linux上的代码在windows上运行
    【贪心算法题记录】1005. K 次取反后最大化的数组和
    【 InnoDB Cluster 】安装部署 MySQL Router
    指定编码“gbk“,防止中文字符乱码
    激光雷达的厮杀18年:西方“诸神黄昏”,东方“新王隐现”
    单精度浮点数计算误差与消减方法
    【零基础SRC】成为漏洞赏金猎人的第一课:加入玲珑安全漏洞挖掘班。
    静态路由 网络实验
    腾讯mini项目-【指标监控服务重构】2023-08-25
    《痞子衡嵌入式半月刊》 第 102 期
  • 原文地址:https://blog.csdn.net/qq_41610493/article/details/133870602