zoukankan      html  css  js  c++  java
  • L0 torch 构建网络初步

    L0 pytorch 构建简单网络

    本文是L0, 目的是把pytorch构建感知器的程序,仔细剖析理解。

    import torch
    from torch import nn
    
    torch.__version__
    
    '1.3.0'
    

    STEP 1 手工定义全连接层Linear

    #torch.nn是专门为深度学习设计的模块。torch.nn的核心数据结构是Module
    #它是一个抽象的概念,#既可以表示神经网络中的某个层(layer),
    #也可以表示一个包含很多层的神经网络
    #class Linear(nn.Module):
    #    def __init__(self,in_dim,out_dim):
    #    def forward(self,x):
    
    
    # 手工定义全连接层,写forward
    class Linear(nn.Module):
        def __init__(self,in_dim,out_dim):
            super(Linear,self).__init__() 
            #调用nn.Moudule 的初始化函数,首先找到Linear的父类nn.Moudle
            #然后把类Linear的对象self转换为类nn.Moudle的对象,然后“被转换”的类nn.Moudle对象调用自己的__init__函数
            #也可以写成nn.Module.__init__(self)
            
            #在构造函数__init__中必须自己定义可学习的参数,并封装成Parameter
            # parameter是一种特殊的Variable,但其默认需要求导(requires_grad = True)
            self.w = nn.Parameter(torch.randn(in_dim,out_dim))
            self.b = nn.Parameter(torch.randn(out_dim))
            
        def forward(self ,x):
            x=x.matmul(self.w) #使用Tensor.matmul 实现w*x矩阵相乘
            y=x+self.b.expand_as(x) #即 y=wx + b 使用Tensor.expand_as 保证x 和b形状一致
            print("调式点1:y的输出维度为",y.shape) #测试x的维度
            return y
      
    

    STEP2 测试Linear 层是否能正常工作

    # 初始化 Linear层结构为 4*3 
    layer = Linear(4, 3)
    
    # 测试喂数据,是否有输出,理解输入输出的维度
    #from torch.autograd import Variable as V
    #input = V(torch.randn(2, 4))
    input = torch.randn(2,4)#输入为二行样本,每行4个特征
    output = layer(input)   #模型每次输入4个特征,输出3个值。
    print(output) # 二行样本,输出2个3维的结果,因此y的输入维度为  torch.size([2,3])
    
    调式点1:y的输出维度为 torch.Size([2, 3])
    tensor([[-1.2798, -1.4936,  0.2399],
            [-1.1742,  1.2190, -2.8469]], grad_fn=<AddBackward0>)
    

    理解
    input = torch.randn(2,4)
    output = layer(input)
    1) 定义layer对输入形状都有假设:输入的不是单行样本数据,而是一个batch。此处batch的大小为2
    2)若想输入单行样本数据 必须调用unsqueeze(0)函数将数据伪装成batch_size=1的batch。

    # 原数据2*4,为batch为2,每batch数据为4维
    #通过unsqueeze 将2*4的数据伪装成 1*2*4的数据,batch变成1,每个batch数据变成2*4
    input = torch.randn(2,4)
    input.unsqueeze(0).size()
    
    torch.Size([1, 2, 4])
    
    
    
    # 测试目前网络的参数,理解参数的维度
    for name, param in layer.named_parameters():
        print(name) 
        print(param) 
        #w 维度为4*3 b的维度为1*3
    
    w
    Parameter containing:
    tensor([[-0.3579, -0.6608,  0.1783],
            [ 1.6277, -0.4486, -1.9849],
            [ 0.9500, -0.1879,  1.7154],
            [-0.5778, -0.2012,  1.5576]], requires_grad=True)
    b
    Parameter containing:
    tensor([-0.9491, -0.1104, -1.2390], requires_grad=True)
    
    for name, param in layer.named_parameters():
        print(name, param.size())
    
    w torch.Size([4, 3])
    b torch.Size([3])
    

    module中parameter的命名规范:
    1)对于类似self.param_name = nn.Parameter(t.randn(3, 4)),命名为param_name
    2)对于子Module中的parameter,会其名字之前加上当前Module的名字。
    如对于self.sub_module = SubModel(),SubModel中有个parameter的名字叫做param_name,
    那么二者拼接而成的parameter name 就是sub_module.param_name。
    见后续采用Linear类进一步构建多层感知器的例子

    STEP3 组建 二个全连接层的感知器

    class Perceptron (nn.Module):
        def __init__(self, in_features, hidden_features, out_features):
            super(Perceptron,self).__init__()  #或写成nn.Module.__init__(self)
            # 利用 Linear subModel组建 layer 1 ,layer 2
            self.layer1 = Linear(in_features, hidden_features)
            self.layer2 = Linear(hidden_features, out_features)
             
        def forward(self, x):
            x = self.layer1(x)
            x = torch.sigmoid(x)
            x = self.layer2(x)
            y = torch.sigmoid(x)
            return y
     
    per = Perceptron(3, 4, 1)
    
    
    per
    
    Perceptron(
      (layer1): Linear()
      (layer2): Linear()
    )
    
    # 测试网络参数
    for name, param in per.named_parameters():
        print("sub_module.param_name::",name, param.size())
    
    sub_module.param_name:: layer1.w torch.Size([3, 4])
    sub_module.param_name:: layer1.b torch.Size([4])
    sub_module.param_name:: layer2.w torch.Size([4, 1])
    sub_module.param_name:: layer2.b torch.Size([1])
    

    1)Module中的可学习参数可以通过**named_parameters()**或者parameters()返回迭代器,前者会给每个parameter都附上名字,使其更具有辨识度。
    2)Module能够自动检测到自己的Parameter,并将其作为学习参数。

    # 测试网络输入,输出
    data=torch.randn(4,3)
    output=per(data)
    output
    
    调式点1:y的输出维度为 torch.Size([4, 4])
    调式点1:y的输出维度为 torch.Size([4, 1])
    
    
    
    
    
    tensor([[0.5478],
            [0.6146],
            [0.6252],
            [0.8016]], grad_fn=<SigmoidBackward>)
    

    STEP 4 利用nn.Sequential 快速搭建网络

    从上面的例子,可以看出在forward()方法中必须理解网络结构,并根据网络层次的之间的关系完成网络组装。
    当模型仅仅是简单的前馈网络时,可以采用nn.Sequentail()模块来快速搭建模块,而不必手动的在forward()方法手工构建。
    Image Name

    class Seq_Perceptron (nn.Module):
        
        def __init__(self, in_features, hidden_features, out_features):
            super(Seq_Perceptron ,self).__init__()  #或写成nn.Module.__init__(self)
            # 利用 Linear subModel组建 layer 1 ,layer 2
            #self.layer1 = Linear(in_features, hidden_features)
            #self.layer2 = Linear(hidden_features, out_features)
            self.seq_layer = nn.Sequential(
                nn.Linear(in_features,hidden_features),
                nn.Sigmoid(),
                nn.Linear(hidden_features,out_features),
                nn.Sigmoid()
                )
           
        def forward(self, x):
            y =  self.seq_layer(x)
            return y
    
    # 测试网络输入,输出
    per = Seq_Perceptron(3, 4, 1)
    data=torch.randn(4,3)
    output=per(data)
    output
    
    tensor([[0.5853],
            [0.6061],
            [0.5967],
            [0.6131]], grad_fn=<SigmoidBackward>)
    
    
    
  • 相关阅读:
    关于JAVA的线程问题
    Java 对JTextField添加回车响应
    Failed to install *.apk on device 'emulator-5554': timeout .
    静态属性
    类与对象的实例属性

    面向对象2
    面向对象设计
    re模块,主要用来查询
    xml对标签操作,
  • 原文地址:https://www.cnblogs.com/supercodeing/p/12332772.html
Copyright © 2011-2022 走看看