Pytorch学习笔记(二)

Tips:实践过程中多参考Pytorch官方文档torch.nn

 

Pytorch-CNN

nn_module.py 


import torch
from torch import nn
#定义自己的神经网络模型,继承pytorch.nn.Module类
class MyModule(nn.Module):
    #nn.Module类中有两个方法需要重写:init and forward
    #可以手动重写方法/Code-Generate-Override Method-init
    def __init__(self):
        super().__init__()

    def forward(self,input):
        output=input+1 #神经网络中输入与输出的关系
        return output

#创建神经网络
myModule=MyModule()
# Note:torch.Tensor torch.tensor
x=torch.tensor(1.0) #input
output=myModule(x)
print(output)#tensor(2.)

# x=torch.Tensor([1.0])
# output=myModule(x)
# print(output)#tensor([2.])

卷积层nn.Conv.py 


#输入单个数据进行卷积
import torch
import torch.nn.functional as F

input = torch.tensor([[1,2,0,3,1],
                    [0,1,2,3,1],
                    [1,2,1,0,0],
                    [5,2,3,1,1],
                    [2,1,0,1,1]])#图像输入为5*5二维矩阵,将其转换为tensor类型
kernel = torch.tensor([[1,2,1],
                     [0,1,0],
                     [2,1,0]])#卷积核为3*3二维矩阵  kernel也就是weight
# print(input.shape)
# print(kernel.shape)
#此时输出的只有两个数,不满足参数要求

#pytorch官网-torch.nn.functional 文档中有conv2d的使用参数说明
#input、kernel格式要求均需要四个数字
#Parameters
#input – input tensor of shape (\text{minibatch} , \text{in\_channels} , iT , iH , iW)(minibatch,in_channels,iT,iH,iW)
#weight – filters of shape (\text{out\_channels} , \frac{\text{in\_channels}}{\text{groups}} , kT , kH , kW)(out_channels, in_channels/groups ,kT,kH,kW)

#使用pytorch提供的尺寸变化
input = torch.reshape(input,(1,1,5,5)) #batchsize=1,channels=1 数据维度=5*5
kernel = torch.reshape(kernel,(1,1,3,3)) #out_channel=1,in_channel=1 数据维度=3*3
print(input.shape)
print(kernel.shape)

#reshape为四维,所以输出也是四维
output = F.conv2d(input,kernel,stride=1)
print(output)

output2 = F.conv2d(input,kernel,stride=2)
print(output2)

output3 = F.conv2d(input,kernel,stride=1,padding=1)
print(output3)
#使用padding可以使输出与输入维度相同

卷积层nn_Conv2d.py

#输入整个数据集进行卷积
#卷积层进行的处理就是卷积运算 对于输入数据,卷积运算以一定间隔stride滑动滤波器的窗口(卷积核)并应用。
#卷积核中的数字对应全连接网络中的权重
#将各个位置上滤波器(卷积核)的元素和输入的对应元素进行乘积累加运算,输出到对应位置
#在进行卷积层运算前,有时会使用padding填充,向输入数据的周围填入固定的数据(比如0等)
#padding的目的/作用是调整输出的大小
import torch
import torchvision
from torch import nn
from torch.nn import Conv2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

#加载数据
dataset=torchvision.datasets.CIFAR10("./dataset",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader=DataLoader(dataset,batch_size=64)

#定义神经网络模型
class myModel(nn.Module):
    #初始化方法
    def __init__(self): #Note:不要把init写成int
        super(myModel,self).__init__()#父类初始化
        #定义卷积层
        self.conv1=Conv2d(in_channels=3,out_channels=6,kernel_size=3,stride=1,padding=0)#kernel:3*3
        #卷积核中数据是自动生成的,在训练过程中自动更新。这些数字就是我们所需要的结果。

    def forward(self,x):
        x=self.conv1(x)
        return x

model=myModel()
# print(model)
writer=SummaryWriter("logs")

step=0
for data in dataloader:
    imgs,targets = data
    output = model(imgs)
    print(imgs.shape) #torch.Size([64, 3, 32, 32]) batchsize=64 in_channels=3 输入数据32*32
    print(output.shape) #torch.Size([64, 6, 30, 30]) batchsize=64 out_channels=6 输出数据30*30
    # 卷积核的通道数等于输入的通道数(In_channel)
    # 卷积层特征图的通道数(Out_channel)等于该卷积层中卷积核的数量 同一个卷积核得到的数据叠加为一个通道
    # torch.Size([64, 3, 32, 32])
    writer.add_images("input",imgs,step)#同时显示多张图片,注意使用images
    # torch.Size([64, 6, 30, 30])->[xxx,3,30,30]  6个通道转换成3个通道,多余的像素就放在batchsize中
    # 只有3个通道才可以在tensorboard可视化出来,所以需要转换shape
    output=torch.reshape(output,(-1,3,30,30)) #-1是让机器自己配置batchsize
    writer.add_images("output",output,step)
    step = step+1
#writer.close()

nn.maxpool.py

#最大池化取局部接受域中值最大的点
#最大池化的目的在于保留原特征的同时减少神经网络训练的参数,使得训练时间减少。相当于1080p的视频变为了720p
#图像经最大池化后会变模糊,类似于马赛克效果
import torch
import torchvision
from torch import nn
from torch.nn import MaxPool2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

#加载数据集
dataset=torchvision.datasets.CIFAR10("./dataset",train=False,download=True,transform=torchvision.transforms.ToTensor())
dataloader=DataLoader(dataset,batch_size=64)

#输入单个数据
# input=torch.tensor([[1,2,0,3,1],
#                     [0,1,2,3,1],
#                     [1,2,1,0,0],
#                     [5,2,3,1,1],
#                     [2,1,0,1,1]],dtype=torch.float32)#添加dtype是因为不支持输入"Long"型数据,直接放进神经网络训练会报错
# print(input.shape)#目前input只含H,W信息

# #Maxpool2d要求input需要有四个参数,batch_size、channels、输入的高H、输入的宽W,则进行reshape:
# input=torch.reshape(input,(-1,1,5,5))
# print(input.shape)

#创建神经网络
class myModel(nn.Module):
    def __init__(self):
        super(myModel, self).__init__()
        self.maxpool1=MaxPool2d(kernel_size=3,ceil_mode=False)
        # kernel_size池化核3*3 默认stride=kernel_size
        # 若池化核移动过程中数据没有凑足kernel_size的大小,便涉及取舍问题
        # ceil_mode=True时,当移动stride后不足3*3有空值时,采用ceil保留;ceil_mode=False时,采用舍弃 默认为False

    def forward(self,input):
        output=self.maxpool1(input)
        return output

model=myModel()
#输入单个数据时的输出测试
# output=model(input)
# print(output)

#数据集池化的可视化
writer=SummaryWriter("logs")
step=0
for data in dataloader:
    imgs,targets=data
    writer.add_images("maxpool_input",imgs,step)
    output=model(imgs)#池化不影响channel数,原来是三维,经过池化后还是三维的,所以不需要像conv后还要reshape
    writer.add_images("maxpool_output",output,step)
    step += 1
writer.close()

nn.ReLU/sigmoid.py

#激活函数实际上是给模型增加非线性的表达能力或者因素,有了非线性函数模型的表达能力就会更强
#没有激活函数的神经网络实际上是线性可加的,那么多线性层其实可以归为一层
#只具有线性的神经网络表达能力极其有限
import torch
import torchvision
from torch import nn
from torch.nn import ReLU, Sigmoid
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

input=torch.tensor([[1,-0.5],
                   [-1,3]])
output=torch.reshape(input,(-1,1,2,2))#input要有batch_size
print(output.shape)

dataset=torchvision.datasets.CIFAR10("./dataset",train=False,download=True,transform=torchvision.transforms.ToTensor())
dataloader=DataLoader(dataset,batch_size=64)

class myModel(nn.Module):
    def __init__(self):
        super(myModel, self).__init__()
        self.relu1=ReLU()
        #inplace就是原地操作的意思 默认为False
        # Input=-1,ReLU(input,inplace=True)=>Input=0
        # Input=-1,Output=ReLU(input,inplace=False)=>Input=-1 Output=0
        self.sigmoid1=Sigmoid()

    def forward(self,input):
        # output=self.relu1(input)
        output = self.sigmoid1(input)
        return output

model=myModel()
output=model(input)
print(output)

writer=SummaryWriter("logs")
step=0
for data in dataloader:
    imgs,targets=data
    writer.add_images("sigmoid_input",imgs,step)
    output=model(imgs)
    writer.add_images("sigmoid_output",output,step)
    step+=1
writer.close()

nn.Linear.py

#线性层
#全连接层包括线性层和非线性激活
#in_feature就是Input layer的神经元个数,输入数据的特征数
#out_feature是Output layer的神经元个数,输出数据
#该代码展示将特征矩阵展平为一维向量,再进行线性输入
import torch
import torchvision
from torch import nn
from torch.nn import Linear
from torch.utils.data import DataLoader

dataset=torchvision.datasets.CIFAR10("./dataset",train=False,download=True,transform=torchvision.transforms.ToTensor())
dataloader=DataLoader(dataset,batch_size=64,drop_last=True)

class myModel(nn.Module):
    def __init__(self):
        super(myModel, self).__init__()
        self.linear1=Linear(196608,10) #in_feature out_feature

    def forward(self,input):
        output=self.linear1(input)
        return output

model=myModel()

for data in dataloader:
    imgs,targets=data
    print(imgs.shape)#torch.Size([64, 3, 32, 32])
    # #展平 方法①
    # output=torch.reshape(imgs,(1,1,1,-1)) #batch_size,channels,h,w 把原来的张量flatten为一个行向量
    #展平 方法②
    output=torch.flatten(imgs)#把原来的张量flatten为一个行向量 torch.Size([196608])
    print(output.shape)#torch.Size([1, 1, 1, 196608])

    output=model(output)
    print(output.shape)#torch.Size([10])

nn.sequential.py


#搭建小实战和Sequential的使用
#把网络结构直接放入Sequential中
#写一个对CIFAR-10数据集进行分类的网络
#使用Sequential使得代码更简洁,并且运行后各层会序列化
import torch
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.tensorboard import SummaryWriter


class myModel(nn.Module):
    #model结构:conv1-maxpool1-conv2-maxpool2-conv3-maxpool3-flatten-linear1-linear2
    def __init__(self):
        super(myModel, self).__init__()

        #①逐层创建网络

        # Inputs3@32*32 Convolution 5*5 kernel => Feature maps 32@32*32
        # 根据Inputs\Conv kernel\Feature maps可以得出in_channels、out_channels、kernel_size;
        # 默认 dilation=1 根据输出尺寸32*32计算公式可以求出padding、stride值
        self.conv1 = Conv2d(in_channels=3, out_channels=32, kernel_size=5, padding=2, stride=1, dilation=1)

        #Feature maps 32@32*32 Max-pooling 2*2 kernel => Feature maps 32@16*16
        self.maxpool1=MaxPool2d(kernel_size=2)#池化的stride默认为kernel_size 池化不更改channel数

        #Feature maps 32@16*16 Convolution 5*5 kernel => Feature maps 32@16*16
        # 同样根据输入、输出、kernel可以计算出个参数值
        self.conv2=Conv2d(in_channels=32,out_channels=32,kernel_size=5,padding=2)

        # Feature maps 32@16*16 Max-pooling 2*2 kernel => Feature maps 32@8*8
        self.maxpool2 = MaxPool2d(kernel_size=2)

        # Feature maps 32@8*8 Convolution 5*5 kernel => Feature maps 64@8*8
        # 同样根据输入、输出、kernel可以计算出个参数值
        self.conv3 = Conv2d(in_channels=32, out_channels=64, kernel_size=5, padding=2)

        # Feature maps 64@16*16 Max-pooling 2*2 kernel => Feature maps 64@4*4
        self.maxpool3 = MaxPool2d(kernel_size=2)

        # Feature maps 64@4*4 => 64*4*4=1024(线性层的In_feature)
        self.flatten = Flatten()

        # 64*4*4=1024(线性层的In_features) =>Hidden units 64(线性层的Out_features)
        self.linear1=Linear(in_features=1024,out_features=64)

        # Hidden units 64(线性层的In_features) =>Outputs 10(线性层的Out_features,10个类别)
        self.linear2 = Linear(in_features=64, out_features=10)

        #②使用Sequential创建网络
        self.model1=Sequential(
            Conv2d(3,32,5,padding=2),
            MaxPool2d(2),
            Conv2d(32,32,5,padding=2),
            MaxPool2d(2),
            Conv2d(32,64,5,padding=2),
            MaxPool2d(2),
            Flatten(),
            Linear(1024,64),
            Linear(64,10),
        )
        #层与层之间用逗号分隔


    def forward(self,x):
        #①逐层创建网络对应的forward函数内容
        x = self.conv1(x)
        x = self.maxpool1(x)
        x = self.conv2(x)
        x = self.maxpool2(x)
        x = self.conv3(x)
        x = self.maxpool3(x)
        x = self.flatten(x)
        #若我们不知道展开后线性输入数据是多大,我们可以将下面两行linear注释掉,运行后会看到模型经前面操作后得到的尺寸
        #torch.Size([64, 1024]) batch_size=64,每张图片都会展开为1024个
        x = self.linear1(x)
        x = self.linear2(x)
        return x

        #②使用Sequential对应的forward函数内容
        x=self.model1(x)
        return x

model = myModel()
print(model)

#对网络进行检验
input = torch.ones((64,3,32,32))#batch_size channels H W
output = model(input)
print(output.shape)#torch.Size([64, 10])

#可视化网络
#在tensorboard中双击可以看到网络结构
writer=SummaryWriter("logs")
writer.add_graph(model,input)
writer.close()

①逐层搭建网络

②将model添加到Sequential中

tensorboard中网络可视化 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值