torch.nn中的nn全称为neural network,意思是神经网络,是torch中构建神经网络的模块。
CNN卷积神经网络基本包含五个层
下面代码模拟了一下卷积操作:
# 模拟一下卷积操作
# 目标矩阵
objA=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]])
# 卷积核
coCore=torch.tensor([[1,2,1],
[0,1,0],
[2,1,0]])
input=torch.reshape(objA,(1,1,5,5))
coCore=torch.reshape(coCore,(1,1,3,3))
# 步长为1没有外边界填充
output1=F.conv2d(input,coCore,stride=1)
# 向外扩充一圈
output2=F.conv2d(input,coCore,stride=1,padding=1)
print(output1)
print(output2)
结果(可以自己计算测试一下):
tensor([[[[10, 12, 12],
[18, 16, 16],
[13, 9, 3]]]])
tensor([[[[ 1, 3, 4, 10, 8],
[ 5, 10, 12, 12, 6],
[ 7, 18, 16, 16, 8],
[11, 13, 9, 3, 4],
[14, 13, 9, 7, 4]]]])
Process finished with exit code 0
将数据传入神经网络,进行多层卷积会得到具有明显特征的图片
测试一下神经网络中的卷积:
import os
import torch
import torchvision.datasets
from torch import nn
from torch.nn import Conv2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
'''
将数据传入神经网络,进行多层卷积会得到具有明显特征的图片
'''
basepath=os.path.split(os.getcwd())[0]
# 获取需要使用的数据集
dataset=torchvision.datasets.CIFAR10(basepath+r"\数据集",train=False,transform=torchvision.transforms.ToTensor(),download=True)
# 加载数据集其中64个打包分成一块
dataloader=DataLoader(dataset,batch_size=64)
# 自定义一个神经网络类
class Model(nn.Module):
def __init__(self):
super(Model,self).__init__()
# 初始化一层卷积
# channels 英文意思是频道
# in_channels 向神经网络输送的数据频道数量
# out_channels 神经网络输出的频道数量
# kernel_size 卷积核的大小,输出的时候会将卷积核根据其大小正方形化
# stride 每次卷积移动的步长,输出的时候也是一个元组,代表左右上下都是移动1
self.conv1=Conv2d(in_channels=3,out_channels=6,kernel_size=3,stride=1,padding=0)
def forward(self,x):
x=self.conv1(x)
return x
# 创建日志文件,显示图像表示的效果
writer=SummaryWriter("logs_Conv")
# 生成神经网络模型
myModel=Model()
# print(myModel)
stept=0
# 迭代打包好的数据,将数据输送到神经网络进行卷积,最后得出卷积后的图片
for data in dataloader:
# 获取数据与标签
imgs,targets=data
# 将数据输送到神经网络
output=myModel(imgs)
print(imgs.shape)
print(output.shape)
# 输出的数据是3,6,30,30 30为尺寸
# tensorboard无法识别6维的图片,使用reshape修改图片形状
output=torch.reshape(output,(-1,3,30,30))
# 将图片加入到tensorBoard中
writer.add_images("input",imgs,stept)
writer.add_images("output",output,stept)
stept=stept+1
# 如果一个图片经过卷积尺寸没有改变并且维度变大,那么可能进行了卷积时的边界填充
最大池化的作用:
通过卷积核大小将图片各个区域的最大值选出来
一般最大池化后会将数据的大小大大减小,以此提高训练速度
最大池化会将数据比较明显的特征提取出来
在日常神经网络训练过程中,通常将卷积,最大池化,激活函数交替使用
最大池化,Tensor变化,我记得还有平均池化之类的东西,感兴趣大家自己研究研究。
import os
import torch.nn as nn
import torch
import torchvision
from torch.nn import MaxPool2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
basepath=os.path.split(os.getcwd())[0]
# 初始化数据集
writer=SummaryWriter(basepath+r"\logss\logs9_1")
dataset=torchvision.datasets.CIFAR10(basepath+r"\数据集",train=False,transform=torchvision.transforms.ToTensor())
dataloader=DataLoader(dataset,64)
class Model(nn.Module):
def __init__(self):
super(Model,self).__init__()
self.pool1=MaxPool2d(kernel_size=2,ceil_mode=True)
def forward(self,input):
output=self.pool1(input)
return output
# 创建神经网络模型
myModel=Model()
step=0
for data in dataloader:
imgs,targes=data
output=myModel(imgs)
writer.add_images("pool_test",output,step)
step=step+1
writer.close()
当数据混乱冗杂时,不带激活函数的单层感知机是一个线性分类器,线性函数无法对各个类别进行分类
激活函数是用来加入非线性因素的,提高神经网络对模型的表达能力,解决线性模型无法解决的问题
单层感知机是最基础的神经网络,感知机网络与卷积网络都属于前馈型网络
单层感知机网络是二分类的线性分类模型,输入是被感知数据集的特征向量,输出是数据集的类别
Linear Layers线性层
Dropout Layers 随机将一些数据置为0
Dropout函数参数
第一个参数p是被置为0的概率,第二个参数inplace 是否在本次样本进行操作默认为false
Normalization正则化层
Recurrent Layers
Transformer Layers
Sparse Layers 一般用于自然语言处理
import os
import torch.nn as nn
import torch
import torchvision.datasets
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
basepath=os.path.split(os.getcwd())[0]
# 预处理数据集
dataset=torchvision.datasets.CIFAR10(basepath+r"\数据集",train=False,transform=torchvision.transforms.ToTensor())
dataloader=DataLoader(dataset,64)
writer=SummaryWriter(basepath+r"\logss\log_6")
class Model(nn.Module):
def __init__(self):
super(Model,self).__init__()
'''
Linear()
第一个参数是输入的样本大小,第二个是输出的样本大小,第三个是是否偏执,默认为true
'''
self.line1=nn.Linear(196608,10)
def forward(self,input):
output=self.line1(input)
return output
myModel=Model()
step=0
for data in dataloader:
imgs,targets=data
print(imgs.shape)
# 该函数直接将多维数组直接转换成一维数组
output=torch.flatten(imgs)
print(output.shape)
output=myModel(output)
print(output.shape)
# writer.add_images("test",output,step)
step=step+1
普通方式
import os
import torch
import torch.nn as nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.tensorboard import SummaryWriter
basepath=os.path.split(os.getcwd())[0]
class Model(nn.Module):
def __init__(self):
super(Model,self).__init__()
self.con1=Conv2d(3, 32, 5, padding=2)
self.maxp1=MaxPool2d(2)
self.con2=Conv2d(32, 32, 5, padding=2)
self.maxp2=MaxPool2d(2)
self.con3=Conv2d(32, 64, 5, padding=2)
self.maxp3=MaxPool2d(2)
self.fla=Flatten()
self.lin1=Linear(1024, 64)
self.lin2=Linear(64, 10)
def forward(self,x):
x=self.con1(x)
x=self.maxp1(x)
x=self.con2(x)
x=self.maxp2(x)
x=self.con3(x)
x=self.maxp3(x)
x=self.fla(x)
x=self.lin1(x)
x=self.lin2(x)
return x
Sequential方式
构建神经网络的另一个方法,也可以说是快速构建方法,就是通过torch.nn.Sequential,直接完成对神经网络的建立。
import os
import torch
import torch.nn as nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.tensorboard import SummaryWriter
basepath=os.path.split(os.getcwd())[0]
class Model(nn.Module):
def __init__(self):
super(Model,self).__init__()
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):
x=self.model1(x)
return x
直接打印创建的对象可以看到网络结构,也可以通过之前介绍到的tensorboard查看网络结构:
myModel=Model()
writer=SummaryWriter(basepath+r"\logss\log_7")
print(myModel)
input=torch.ones((64,3,32,32))
output=myModel(input)
print(output.shape)
# 将搭建的神经网络结构绘制到tensorboard中
writer.add_graph(myModel,input)
writer.close()
输出结果如下:
Model(
(model1): Sequential(
(0): Conv2d(3, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
(1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(2): Conv2d(32, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
(3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(4): Conv2d(32, 64, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
(5): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(6): Flatten(start_dim=1, end_dim=-1)
(7): Linear(in_features=1024, out_features=64, bias=True)
(8): Linear(in_features=64, out_features=10, bias=True)
)
)
torch.Size([64, 10])
Process finished with exit code 0
import torch
from torch.nn import L1Loss
import torch.nn as nn
input=torch.tensor([1,2,3],dtype=torch.float32)
target=torch.tensor([1,2,5])
input=torch.reshape(input,(1,1,1,3))
target=torch.reshape(target,(1,1,1,3))
# 获取损失函数计算器(计算差值)
# reduction可以进行修改
loss=L1Loss(reduction="sum")
result_loss=loss(input,target)
print(result_loss)
# 计算平方差
loss_mse=nn.MSELoss()
result_loss_mse=loss_mse(input,target)
print(result_loss_mse)
# 交叉熵
x=torch.tensor([0.1,0.2,0.3])
y=torch.tensor([1])
# 这里(1,3)代表有三个类别一个进行选择
x=torch.reshape(x,(1,3))
loss_cross=nn.CrossEntropyLoss()
result_loss=loss_cross(x,y)
print(result_loss)
import os
import torchvision.datasets
from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
import torch
import torch.nn as nn
from torch.utils.data import DataLoader
basepath=os.path.split(os.getcwd())[0]
dataset=torchvision.datasets.CIFAR10(basepath+r"\数据集",train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader=DataLoader(dataset,1)
class Model(nn.Module):
def __init__(self):
super(Model,self).__init__()
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):
x=self.model1(x)
return x
myModel=Model()
# 创建损失函数
loss=nn.CrossEntropyLoss()
# 获取优化器
optim=torch.optim.SGD(myModel.parameters(),lr=0.01)#lr指的是训练速率,这个速率不可以过高,也不可以太低,过高会使模型不稳定
for x in range(20):#过低训练速度太慢
runing_loss=0.0
for data in dataloader:
imgs,targets=data
output=myModel(imgs)
# print(output)
# print(targets)
result_loss=loss(output,targets)
optim.zero_grad()
result_loss.backward()
optim.step()
runing_loss=runing_loss+result_loss
print(runing_loss)