Pytorch神经网络自定义层(layer)

目录

一、不带参数的层

二、带参数的层


       深度学习成功背后的一个因素是神经网络的灵活性:我们可以用创造性的方式组合不同的层,从而设计出适用于各种任务的架构。例如,研究人员发明了专门用于处理图像、文本、序列数据和执行动态规划的层。有时我们会遇到或要自己发明一个现在在深度学习框架中还不存在的层。在这些情况下,必须构建自定义层。自定义层和自定义网络没有本质区别,因为层(layer)其实也是nn.Module的子类。

一、不带参数的层

       首先,我们构造一个没有任何参数的自定义层。下面的`CenteredLayer`类要从其输入中减去均值。要构建它,我们只需继承基础层类并实现前向传播功能。

import torch
import torch.nn.functional as F
from torch import nn


class CenteredLayer(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, X):
        return X - X.mean()

       让我们向该层提供一些数据,验证它是否能按预期工作。

layer = CenteredLayer()
layer(torch.FloatTensor([1, 2, 3, 4, 5]))
tensor([-2., -1.,  0.,  1.,  2.])

       现在,我们可以将层作为组件合并到更复杂的模型中。

net = nn.Sequential(nn.Linear(8, 128), CenteredLayer())

       作为额外的健全性检查,我们可以在向该网络发送随机数据后,检查均值是否为0。由于我们处理的是浮点数,因为存储精度的原因,我们仍然可能会看到一个非常小的非零数。

Y = net(torch.rand(4, 8))
Y.mean()
tensor(-4.1910e-09, grad_fn=<MeanBackward0>)

二、带参数的层

       以上我们知道了如何定义简单的层,下面我们继续定义具有参数的层,这些参数可以通过训练进行调整。我们可以使用内置函数来创建参数,这些函数提供一些基本的管理功能。比如管理访问、初始化、共享、保存和加载模型参数。这样做的好处之一是:我们不需要为每个自定义层编写自定义的序列化程序。

       现在,让我们实现自定义版本的全连接层,该层需要两个参数,一个用于表示权重,另一个用于表示偏置项。该层需要输入参数:`in_units`和`units`,分别表示输入数和输出数。在此实现中,我们使用修正线性单元作为激活函数。

class MyLinear(nn.Module):
    def __init__(self, in_units, units):
        super().__init__()
        self.weight = nn.Parameter(torch.randn(in_units, units))    # 也算是初始化权重的一种方式
        self.bias = nn.Parameter(torch.randn(units,))               # torch.randn()返回一个符合均值为0,方差为1的正态分布(标准正态分布)中填充随机数的张量
    def forward(self, X):
        # torch.matmul是tensor的乘法,输入可以是高维的。当输入都是二维时,就是普通的矩阵乘法,和tensor.mm函数用法相同。当输入有多维时,把多出的一维作为batch提出来,其他部分做矩阵乘法。
        linear = torch.matmul(X, self.weight.data) + self.bias.data
        return F.relu(linear)

       接下来,我们实例化`MyLinear`类并访问其模型参数。

linear = MyLinear(5, 3)
print(linear.weight)
print(linear.bias)
Parameter containing:
tensor([[-1.0704, -0.8003, -0.5793],
        [-0.6250,  0.2337, -0.2898],
        [-0.7425, -0.7948,  0.3498],
        [-0.5903,  0.4115, -0.2875],
        [-0.7593,  0.4104, -0.8873]], requires_grad=True)
Parameter containing:
tensor([ 1.4250,  0.1016, -0.3040], requires_grad=True)

       我们可以使用自定义层直接执行前向传播计算。

linear(torch.rand(2, 5))    # torch.rand()返回一个在区间[0, 1)的均匀分布中抽取的一组随机数的张量
tensor([[0., 0., 0.],
        [0., 0., 0.]])

       我们还可以使用自定义层构建模型,就像使用内置的全连接层一样使用自定义层。

net = nn.Sequential(MyLinear(64, 8), MyLinear(8, 1))
net(torch.rand(2, 64))
tensor([[0.],
        [0.]])

       补充:关于torch.rand()、torch.randn()、torch.randint()、torch.randperm()用法:torch.rand()、torch.randn()、torch.randint()、torch.randperm()用法-CSDN博客文章浏览阅读10w+次,点赞100次,收藏459次。torch.rand和torch.randn有什么区别? 一个均匀分布,一个是标准正态分布。torch.rand()#rand(*size, out=None, dtype=None)t1 = torch.rand(2,3)print(t1,t1.type())randn(*size, out=None, dtype=None)和randn_like(input, dtype=None)#randn(*size, out=None, dtype=None)#randn_like(in_torch.randhttps://blog.csdn.net/leilei7407/article/details/107710852

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这个问题比较复杂。首先,我们需要加载自定义图像数据集,并训练一个自定义神经网络模型。然后,我们需要提取任意的特征向量,并使用t-SNE算法对这些特征向量进行降维和可视化。 以下是一个简单的实现步骤: 1. 加载自定义图像数据集 使用PyTorch的ImageFolder类可以很容易地加载自定义图像数据集。你需要将数据集划分为训练集和测试集,并使用transforms对图像进行预处理。 ```python import torchvision.transforms as transforms from torchvision.datasets import ImageFolder transform = transforms.Compose([ transforms.Resize((224, 224)), # 将图像大小调整为(224, 224) transforms.ToTensor(), # 将图像转换为Tensor transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) # 归一化 ]) train_dataset = ImageFolder('path/to/train/dataset', transform=transform) test_dataset = ImageFolder('path/to/test/dataset', transform=transform) ``` 2. 训练自定义神经网络模型 使用PyTorch可以非常方便地定义和训练自定义神经网络模型。你可以根据自己的需要定义任意数的模型,并在训练过程中使用任意的损失函数和优化器。 ```python import torch.nn as nn import torch.optim as optim class CustomNet(nn.Module): def __init__(self): super(CustomNet, self).__init__() # 定义你自己的网络结构 def forward(self, x): # 定义前向传播过程 model = CustomNet() criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9) def train(model, train_loader, criterion, optimizer, num_epochs): for epoch in range(num_epochs): running_loss = 0.0 for i, data in enumerate(train_loader, 0): inputs, labels = data optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item() print('Epoch %d loss: %.3f' % (epoch + 1, running_loss / len(train_loader))) ``` 3. 提取任意的特征向量 在训练完成后,我们可以使用PyTorch提供的钩子(hook)机制来提取任意的特征向量。我们可以在前向传播过程中注册一个钩子来获取中间的输出。 ```python features = {} def get_features(name): def hook(model, input, output): features[name] = output.detach() return hook model.layer.register_forward_hook(get_features('layer_output')) def extract_features(model, dataloader): model.eval() with torch.no_grad(): for i, data in enumerate(dataloader, 0): inputs, labels = data outputs = model(inputs) ``` 4. 使用t-SNE算法进行特征可视化 最后,我们可以使用scikit-learn提供的t-SNE算法对特征向量进行降维和可视化。我们可以将特征向量作为输入,将它们降到2维或3维,然后使用matplotlib将它们可视化。 ```python from sklearn.manifold import TSNE import matplotlib.pyplot as plt def visualize_features(features, labels): tsne = TSNE(n_components=2, init='pca', random_state=0) X_tsne = tsne.fit_transform(features) plt.scatter(X_tsne[:, 0], X_tsne[:, 1], c=labels) plt.show() visualize_features(features['layer_output'], train_dataset.targets) ``` 这就是一个简单的实现步骤。当然,你可以根据自己的需要进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值