动手学深度学习(pytorch土堆)-05-1神经网络
Neural network
以下是 torch.nn
库中各个组件的详细分类:
1. 容器 (Containers)
torch.nn.Sequential
: 顺序容器,用于将层按顺序堆叠在一起。torch.nn.ModuleList
: 模块列表,用于存储多个子模块。torch.nn.ModuleDict
: 模块字典,用于存储以字典形式组织的子模块。
2. 卷积层 (Convolution Layers)
torch.nn.Conv1d
: 1D 卷积层,适用于处理序列数据。torch.nn.Conv2d
: 2D 卷积层,常用于处理图像数据。torch.nn.Conv3d
: 3D 卷积层,用于处理三维数据,例如视频帧。
3. 池化层 (Pooling Layers)
torch.nn.MaxPool1d
: 1D 最大池化层,用于序列数据。torch.nn.MaxPool2d
: 2D 最大池化层,用于图像数据。torch.nn.AvgPool2d
: 2D 平均池化层,用于图像数据。
4. 填充层 (Padding Layers)
torch.nn.ConstantPad1d
: 1D 常数填充层。torch.nn.ReflectionPad2d
: 2D 反射填充层。torch.nn.ReplicationPad2d
: 2D 复制填充层。
5. 非线性激活 (Weighted Sum, Nonlinearity)
torch.nn.ReLU
: Rectified Linear Unit 激活函数。torch.nn.Sigmoid
: Sigmoid 激活函数。torch.nn.Tanh
: Tanh 激活函数。
6. 非线性激活 (其他)
torch.nn.LeakyReLU
: 带泄漏的 ReLU 激活函数。torch.nn.PReLU
: 参数化 ReLU 激活函数。
7. 归一化层 (Normalization Layers)
torch.nn.BatchNorm1d
: 1D 批归一化层。torch.nn.BatchNorm2d
: 2D 批归一化层。torch.nn.LayerNorm
: 层归一化层。
8. 递归层 (Recurrent Layers)
torch.nn.RNN
: 循环神经网络层。torch.nn.LSTM
: 长短期记忆网络层。torch.nn.GRU
: 门控循环单元层。
9. Transformer 层 (Transformer Layers)
torch.nn.Transformer
: Transformer 模型的实现。torch.nn.MultiheadAttention
: 多头自注意力机制。
10. 线性层 (Linear Layers)
torch.nn.Linear
: 全连接层。
11. Dropout 层 (Dropout Layers)
torch.nn.Dropout
: Dropout 层,用于减少过拟合。torch.nn.Dropout2d
: 2D Dropout 层。
12. 稀疏层 (Sparse Layers)
torch.nn.Embedding
: 嵌入层,用于处理稀疏数据(如词汇表中的词向量)。
13. 距离函数 (Distance Functions)
torch.nn.PairwiseDistance
: 计算一对样本之间的距离。torch.nn.CosineSimilarity
: 计算余弦相似度。
14. 损失函数 (Loss Functions)
torch.nn.CrossEntropyLoss
: 交叉熵损失函数。torch.nn.MSELoss
: 均方误差损失函数。torch.nn.BCEWithLogitsLoss
: 结合了 Sigmoid 激活和二元交叉熵损失的损失函数。
15. 视觉层 (Vision Layers)
torch.nn.Conv2d
: 2D 卷积层。torch.nn.MaxPool2d
: 2D 最大池化层。torch.nn.AdaptiveAvgPool2d
: 自适应平均池化层。
16. Shuffle 层 (Shuffle Layers)
torch.nn.PixelShuffle
: 像素重排层,用于超分辨率任务。
17. DataParallel 层 (多 GPU,分布式)
torch.nn.DataParallel
: 用于多 GPU 训练的封装器。
18. 实用工具 (Utilities)
torch.nn.init
: 权重初始化函数。torch.nn.functional
: 包含各种功能性操作(如激活函数、卷积操作等)。
19. 量化函数 (Quantized Functions)
torch.nn.quantized
: 用于量化模型的模块和函数。
20. 惰性模块初始化 (Lazy Modules Initialization)
torch.nn.LazyLinear
: 懒初始化的全连接层。torch.nn.LazyConv2d
: 懒初始化的卷积层。
这些组件共同构成了 PyTorch 的神经网络构建和训练的基础。
Model示例
在这段代码中,Model(nn.Module)
是一个类定义语法的部分,涉及到几个重要的 Python 和 PyTorch 语法和概念。具体说明如下:
类定义 (class
语法)
class Model(nn.Module):
class
: 这是 Python 中定义类的关键字。Model
: 这是你定义的类的名称。(nn.Module)
: 这是类的基类,表示Model
继承自nn.Module
。
继承 (inheritance
)
-
nn.Module
: 是 PyTorch 提供的一个基类,用于所有神经网络模型的构建。它提供了基本的功能,如参数的注册、前向传播的定义等。通过继承nn.Module
,Model
类可以使用这些功能。 -
继承的意义:
- 继承
nn.Module
允许Model
类拥有nn.Module
的所有方法和属性。 - 自定义的神经网络类需要继承自
nn.Module
,并重写forward
方法,定义前向传播的具体逻辑。
- 继承
初始化 (__init__
方法)
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(1, 20, 5)
self.conv2 = nn.Conv2d(20, 20, 5)
__init__
: 是 Python 中的构造函数,用于初始化类的实例。在创建Model
实例时,会调用这个方法来初始化网络层。super().__init__()
: 调用基类(nn.Module
)的初始化方法,确保父类的初始化逻辑也被执行。self.conv1
和self.conv2
: 这些是Model
类的属性,定义了网络的卷积层。
前向传播 (forward
方法)
def forward(self, x):
x = F.relu(self.conv1(x))
return F.relu(self.conv2(x))
forward
: 是一个必须重写的方法,用于定义数据如何通过网络传递。在这里,x
是输入数据,经过两个卷积层和 ReLU 激活函数后返回结果。F.relu
: 是torch.nn.functional
中的 ReLU 激活函数。它在每个卷积层后应用,以引入非线性特征。
关键点总结
- 继承:
Model
继承自nn.Module
,使其具有构建神经网络的能力。 - 初始化: 使用
__init__
方法初始化网络层。 - 前向传播:
forward
方法定义了数据流经网络的过程。
这段代码展示了 PyTorch 中定义和实现自定义神经网络模型的基本方法。
Model示例
import torch
from torch import nn
import torch.nn.functional as F
class xkk(nn.Module):
def __init__(self):
super().__init__()
# self.conv1 = nn.Conv2d(1, 20, 5)
# self.conv2 = nn.Conv2d(20, 20, 5)
def forward(self, input):
output=input+1
return output
Xkk=xkk()
x=torch.tensor(1.0)
output=Xkk(x)#调用了模块的 __call__ 方法,而 __call__ 方法会自动执行 forward 函数。
print(output)
CONV2D
卷积
设置padding=1
在 PyTorch 的 conv2d 函数中,padding=1 是指在输入的边缘添加 1 层像素的填充(通常填充 0)。
填充的目的是保持输入的空间尺寸不变或者控制输出的尺寸
import torch
import torch.nn.functional as F
input=torch.tensor([[1,2,0,3,1],
[0,1,2,3,1],
[5,2,3,1,1],
[1,2,1,0,0],
[2,1,0,1,1]])
kernel=torch.tensor([[1,2,1],
[0,1,0],
[2,1,0]])
"""
在 PyTorch 中执行二维卷积时,输入数据和卷积核需要遵循特定的格式。将 input 和 kernel 张量分别重新调整为 (1, 1, 5, 5) 和 (1, 1, 3, 3)
是为了符合 conv2d 函数的输入要求。
具体来说,conv2d 的输入和卷积核的张量格式是四维的,分别表示 [batch_size, channels, height, width]。每个维度的含义如下:
batch_size (批大小):表示同时输入的样本数量。在这个例子中,只进行一次卷积,因此批大小为 1。
channels (通道数):表示输入的通道数量,通常对于灰度图像为 1,对于彩色图像为 3(对应 RGB 三个通道)。这里输入和卷积核的通道数均为 1。
height (高度) 和 width (宽度):表示输入图像的大小或卷积核的大小。
因此,input=torch.reshape(input,(1,1,5,5)) 将原始的 5x5 输入张量变为 (1, 1, 5, 5) 的四维张量,以符合 conv2d 函数的输入格式。
类似地,kernel=torch.reshape(kernel,(1,1,3,3)) 是将 3x3 的卷积核也调整为四维格式 (1, 1, 3, 3)。
"""
input=torch.reshape(input,(1,1,5,5))
kernel=torch.reshape(kernel,(1,1,3,3))
output=F.conv2d(input,kernel,stride=1)
print(output)
"""
在 PyTorch 的 conv2d 函数中,padding=1 是指在输入的边缘添加 1 层像素的填充(通常填充 0)。
填充的目的是保持输入的空间尺寸不变或者控制输出的尺寸
"""
output2=F.conv2d(input,kernel,stride=1,padding=1)
print(output2)
神经网络-卷积层
torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode=‘zeros’, device=None, dtype=None)
in_channels (int) – 输入图像中的通道数
out_channels (int) – 卷积产生的通道数
kernel_size (int or tuple) – 卷积内核的大小
stride (int or tuple, optional) - 卷积的步幅。默认值:1
padding (int, tuple or str, optional) – 添加到 的所有四个边的填充 输入。默认值:0
padding_mode (str,可选) – 、 或 .违约:‘zeros’‘reflect’‘replicate’‘circular’‘zeros’
dilation (int 或 tuple,可选) – 内核元素之间的间距。默认值:1
groups (int, optional) – 来自输入的阻塞连接数 channels 设置为 output channels。默认值:1
bias (bool,可选) – 如果 ,则向 输出。违约:TrueTrue
import torch
import torch.nn.functional as F
import torchvision
from torch import nn
from torch.nn import Conv2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
writer=SummaryWriter("conv2")
dataset=torchvision.datasets.CIFAR10("./data_nn",train=False,transform=torchvision.transforms.ToTensor(),
download=True )
dataloader=DataLoader(dataset,batch_size=64)
class xkkk(nn.Module):
def __init__(self):
super(xkkk,self).__init__()
self.conv1=Conv2d(3,6,3,stride=1,padding=0)
def forward(self, x):
x=self.conv1(x)
return x
XKK=xkkk()
i=0
for data in dataloader:
imgs,targets=data
output=XKK(imgs)
print(imgs.shape)
print(output.shape)
writer.add_images("input",imgs,1,i)
output=torch.reshape(output,(-1,3,30,30))#torch.Size([64, 6, 30, 30])---->torch.Size([64, 3, 30 ,30])
writer.add_images("output", output, 1, i)
i=i+1
池化层
torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)
kernel_size (Union[int, Tuple[int, int]]) – 要达到最大值的窗口大小
stride (Union[int, Tuple[int, int]]) —— 窗口的步幅。默认值为kernel_size
padding (Union[int, Tuple[int, int]]) – 要在两侧添加的隐式负无穷大填充
dilation (Union[int, Tuple[int, int]]) – 控制窗口中元素步幅的参数
return_indices (bool) – 如果 ,将返回最大索引以及输出。 对以后有用True
ceil_mode (bool) – 当 True 时,将使用 ceil 而不是 floor 来计算输出形状
池化操作
池化(Pooling)是卷积神经网络(CNN)中的一种下采样操作,用于减少特征图的尺寸,同时保留关键信息。其主要目的是降低数据量和计算复杂度,防止过拟合,并且提高模型的鲁棒性。
常见的池化操作有以下两种:
-
最大池化(Max Pooling):取池化窗口内的最大值。其作用是保留该区域内最显著的特征,常用于提取边缘和其他强特征。
- 举例:如果一个2x2的池化窗口中的值是[1, 3, 2, 0],最大池化会取值3。
-
平均池化(Average Pooling):取池化窗口内所有值的平均值。这个操作可以平滑特征图,减缓最大池化可能导致的过于强调局部特征的问题。
- 举例:对于一个2x2的窗口[1, 3, 2, 0],平均池化会取值(1+3+2+0)/4 = 1.5。
常见的池化参数:
- 池化窗口大小:窗口的大小决定了要处理的区域范围,通常为2x2或3x3。
- 步长(stride):每次移动窗口的距离。步长越大,池化后的特征图越小。
池化是无参操作,不会影响模型的可学习参数。
#ceil_mode (bool) =True
import torch
from torch import nn
from torch.nn import MaxPool2d
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
)
input=torch.reshape(input,(-1,1,5,5))
print(input.shape)
class xkkk(nn.Module):
def __init__(self):
super(xkkk,self).__init__()
self.maxpool1=MaxPool2d(kernel_size=3,ceil_mode=True)
def forward(self, x):
output=self.maxpool1(x)
return output
XKK=xkkk()
output=XKK(input)
print(output)
结果
tensor([[[[2., 3.],
[5., 1.]]]])
#ceil_mode=False
import torch
from torch import nn
from torch.nn import MaxPool2d
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
)
input=torch.reshape(input,(-1,1,5,5))
print(input.shape)
class xkkk(nn.Module):
def __init__(self):
super(xkkk,self).__init__()
self.maxpool1=MaxPool2d(kernel_size=3,ceil_mode=False)
def forward(self, x):
output=self.maxpool1(x)
return output
XKK=xkkk()
output=XKK(input)
print(output)
结果
tensor([[[[2.]]]])
对图片进行池化操作
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
writer=SummaryWriter("maxpool")
dataset=torchvision.datasets.CIFAR10("./data_nn",train=False,transform=torchvision.transforms.ToTensor(),
download=True )
dataloader=DataLoader(dataset,batch_size=64)
class xkkk(nn.Module):
def __init__(self):
super(xkkk,self).__init__()
self.maxpool1=MaxPool2d(kernel_size=3,ceil_mode=True)
def forward(self, x):
x=self.maxpool1(x)
return x
XKK=xkkk()
i=0
for data in dataloader:
imgs,targets=data
output=XKK(imgs)
# print(imgs.shape)
# print(output.shape)
writer.add_images("input",imgs,i)
# output=torch.reshape(output,(-1,3,30,30))#torch.Size([64, 6, 30, 30])---->torch.Size([64, 3, 30 ,30])
writer.add_images("output", output, i)
i=i+1
writer.close()
RELU
ReLU(Rectified Linear Unit,线性整流函数)是深度神经网络中常用的激活函数。它的主要作用是引入非线性,从而使得神经网络能够学习复杂的模式和特征。
ReLU 的数学定义为:
[ f(x) = \max(0, x) ]
即:
- 当 ( x > 0 ) 时,输出 ( x );
- 当 ( x \leq 0 ) 时,输出 0。
ReLU 的特点:
- 计算简单:相比于其他激活函数(如 Sigmoid 或 Tanh),ReLU 的计算非常简单,仅涉及判断和取值操作,加快了训练速度。
- 解决梯度消失问题:在深层网络中,Sigmoid 和 Tanh 激活函数容易导致梯度消失,而 ReLU 的正区间( ( x > 0 ) )不会出现这种问题,能够更好地传播梯度。
- 稀疏激活:由于 ReLU 的输出会将负值部分置为0,这会使得一部分神经元不被激活,从而产生稀疏性,有助于提高模型的效率和鲁棒性。
ReLU 的缺点:
- 死亡ReLU(Dying ReLU)问题:如果输入的权重或偏置导致神经元的输出始终为负,那么 ReLU 的输出将一直为 0,导致该神经元不再对输入数据产生任何反应。这种现象会导致部分神经元“死亡”,从而影响模型的表现。
ReLU 的变种:
为了解决死亡 ReLU 的问题,出现了几种 ReLU 的变种:
-
Leaky ReLU:在负区间引入一个小的斜率,使得负数也可以有小的非零输出。定义为:
[ f(x) = \max(0.01x, x) ] -
Parametric ReLU(PReLU):类似 Leaky ReLU,但负区间的斜率是一个可学习的参数。
-
Exponential Linear Unit (ELU):在负区间采用指数函数,使得其输出更加平滑。
import torch
from torch.nn import ReLU
import torch.nn
input=torch.tensor(
[
[1,-0.5]
,[-1,3]
]
)
input=torch.reshape(input,(-1,1,2,2))
class xkkk(torch.nn.Module):
def __init__(self):
super(xkkk,self).__init__()
self.relu=ReLU()
def forward(self, x):
x=self.relu(x)
return x
XKK=xkkk()
output=XKK(input)
print(output)
结果
tensor([[[[1., 0.],
[0., 3.]]]])
sigmoid
Sigmoid函数(S形函数)是机器学习和神经网络中的一个常用激活函数。其特点是将任意实数输入转换为介于0和1之间的输出值,具有S形曲线的特性。
数学公式
Sigmoid函数的公式为:
[
\sigma(x) = \frac{1}{1 + e^{-x}}
]
其中,( e ) 是自然对数的底数,( x ) 是输入值。
特点
-
输出范围: Sigmoid函数将输入值压缩到0和1之间,这使得它特别适合用于二元分类问题,例如二分类的输出。
-
S形曲线: Sigmoid函数的图形是光滑的S形曲线,当输入值为0时,输出为0.5。当输入值趋于正无穷时,输出接近1;当输入值趋于负无穷时,输出接近0。
-
平滑和可微性: Sigmoid函数是连续且可导的,导数可以用于梯度下降等优化算法中。
-
概率解释: 由于其输出值在(0, 1)之间,常用作表示某事件发生的概率,尤其在逻辑回归和二分类神经网络输出层中广泛应用。
缺点
-
梯度消失问题: 当输入值过大或过小时,Sigmoid函数的梯度会接近于零,这会导致神经网络训练过程中梯度更新很慢,从而影响模型的收敛速度。
-
非零中心输出: Sigmoid函数的输出值范围是(0, 1),使得它是非零中心的,这可能会影响反向传播时的梯度计算效率,导致收敛较慢。
导数
Sigmoid函数的导数可以通过以下公式计算:
[
\sigma’(x) = \sigma(x) \cdot (1 - \sigma(x))
]
这意味着其导数与输出值有关,在反向传播中可以方便地计算。
应用场景
- 二元分类: 在逻辑回归模型和二元分类神经网络中,Sigmoid通常用于输出层,将模型的输出映射为概率值。
- 概率预测: 因为Sigmoid的输出在0和1之间,常用来表示事件发生的概率。
尽管在一些深度学习模型中,ReLU等激活函数逐渐取代了Sigmoid函数,但它在特定任务中仍然有着广泛的应用。
import torch
import torchvision
from torch.nn import ReLU, Sigmoid
import torch.nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
writer=SummaryWriter("sigmoid")
dataset=torchvision.datasets.CIFAR10("./data_nn",train=False,transform=torchvision.transforms.ToTensor(),
download=True )
dataloader=DataLoader(dataset,batch_size=64)
class xkkk(torch.nn.Module):
def __init__(self):
super(xkkk,self).__init__()
self.sigmoid=Sigmoid()
def forward(self, x):
x=self.sigmoid(x)
return x
XKK=xkkk()
i=0
for data in dataloader:
imgs,targets=data
output=XKK(imgs)
# print(imgs.shape)
# print(output.shape)
writer.add_images("input",imgs,i)
# output=torch.reshape(output,(-1,3,30,30))#torch.Size([64, 6, 30, 30])---->torch.Size([64, 3, 30 ,30])
writer.add_images("output", output, i)
i=i+1
writer.close()
线性层以及其它层介绍
import torch
import torchvision
from torch.nn import Linear
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
dataset=torchvision.datasets.CIFAR10("./data_nn",train=False,transform=torchvision.transforms.ToTensor(),
download=True )
dataloader=DataLoader(dataset,batch_size=64)
class xkkk(torch.nn.Module):
def __init__(self):
super(xkkk,self).__init__()
self.linear1=Linear(196608,10)
def forward(self, x):
output=self.linear1(x)
return output
XKK=xkkk()
for data in dataloader:
imgs,targets=data
print(imgs.shape)
# output=torch.reshape(imgs,(1,1,1,-1))
output=torch.flatten(imgs)
print(output.shape)
output=XKK(output)
print(output.shape)
结果
.....
torch.Size([10])
torch.Size([64, 3, 32, 32])
torch.Size([196608])
torch.Size([10])
torch.Size([64, 3, 32, 32])
torch.Size([196608])
.....
小型实战和Sequential
在 PyTorch 中,torch.nn.Sequential
是一个简单而强大的容器,它可以将多个层按照顺序组合成一个模型。这对于构建多层神经网络尤其有用,因为它允许将一系列的神经网络层按顺序堆叠起来,使得代码更加简洁。
Sequential
的定义与使用
1. 基本使用
可以将多个层按照顺序传递给 Sequential
,然后 PyTorch 会自动将数据按顺序通过这些层。
import torch
import torch.nn as nn
# 使用 Sequential 定义一个简单的神经网络
model = nn.Sequential(
nn.Linear(10, 20), # 线性层,将输入维度10映射到输出维度20
nn.ReLU(), # 激活函数ReLU
nn.Linear(20, 1), # 线性层,将输入维度20映射到输出维度1
nn.Sigmoid() # 激活函数Sigmoid
)
# 打印模型结构
print(model)
# 定义输入张量
input_tensor = torch.randn(1, 10)
# 前向传播
output = model(input_tensor)
print(output)
在这个例子中,Sequential
包含了两个线性层和两个激活函数,数据会从输入传递到第一层,然后按顺序通过每一层,最终输出结果。
2. 命名层
如果需要给每一层命名,可以使用 OrderedDict
来实现。这样可以更方便地根据层的名字进行访问和操作。
from collections import OrderedDict
model = nn.Sequential(OrderedDict([
('fc1', nn.Linear(10, 20)),
('relu1', nn.ReLU()),
('fc2', nn.Linear(20, 1)),
('sigmoid', nn.Sigmoid())
]))
# 打印模型
print(model)
# 可以通过名字访问某一层
print(model.fc1)
3. 动态构建
你也可以通过循环等方式动态地创建模型。例如,可以根据用户输入的层数来构建一个网络。
layers = []
input_size = 10
hidden_size = 20
for i in range(3): # 动态添加三层
layers.append(nn.Linear(input_size, hidden_size))
layers.append(nn.ReLU())
input_size = hidden_size # 下一层的输入是上一层的输出
layers.append(nn.Linear(hidden_size, 1))
layers.append(nn.Sigmoid())
# 使用 Sequential 构建模型
model = nn.Sequential(*layers)
print(model)
Sequential
的特点
- 简洁:可以轻松地按顺序堆叠层,适用于简单的网络结构。
- 模块化:方便将复杂的模型模块化,每个部分的功能清晰且独立。
- 灵活性较低:不适合有复杂控制流或多个输入/输出的模型。例如,
Sequential
不适合具有分支或跳跃结构的网络。
适用场景
Sequential
适用于构建简单的前馈神经网络,如:
- 全连接网络(MLP)
- 卷积神经网络(CNN)
- 自编码器
如果你的模型结构比较简单,Sequential
是一种非常高效和易用的方式来定义神经网络。
import torch
import torchvision
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
class xkkk(torch.nn.Module):
def __init__(self):
super(xkkk,self).__init__()
# self.conv1=Conv2d(3,32,5,padding=2)
# self.maxpool1=MaxPool2d(kernel_size=2)
# self.conv2 = Conv2d(32, 32, 5, padding=2)
# self.maxpool2 = MaxPool2d(kernel_size=2)
# self.conv3 = Conv2d(32, 64, 5, padding=2)
# self.maxpool3 = MaxPool2d(kernel_size=2)
# self.flatten=Flatten()
# self.linear1=Linear(1024,64)#1024=64*4*4
# self.linear2=Linear(64,10)
self.model1=torch.nn.Sequential(
Conv2d(3, 32, 5, padding=2),
MaxPool2d(kernel_size=2),
Conv2d(32, 32, 5, padding=2),
MaxPool2d(kernel_size=2),
Conv2d(32, 64, 5, padding=2),
MaxPool2d(kernel_size=2),
Flatten(),
Linear(1024, 64), # 1024=64*4*4,
Linear(64, 10)
)
def forward(self, x):
# output=self.conv1(x)
# output=self.maxpool1(output)
# output=self.conv2(output)
# output=self.maxpool2(output)
# output=self.conv3(output)
# output=self.maxpool3(output)
# output=self.flatten(output)
# output=self.linear1(output)
# output=self.linear2(output)
output=self.model1(x)
return output
XKK=xkkk()
print(XKK)
input=torch.ones(64,3,32,32)
writer=SummaryWriter("nn_sequential")
writer.add_graph(XKK,input)
writer.close()