用pytorch搭建一个超级简单的神经网络

本文作者分享了使用PyTorch实现简单卷积神经网络的过程,从定义网络结构到训练迭代,探讨了学习率调整对结果的影响,并展示了损失与迭代次数的关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 最近在自学pytorch一些内容,虽然是找着手册来的,但有时候往往一行代码也要我理解很久。

    学习了一些简单的原理和pytorch变成方法后,我试着自己搭建了一个卷积神经网络。

    流程大致是用一个33的卷积核对一个55的张量进行卷积,通过迭代使其结果变为一个3*3的单位张量。

所用环境为Ubuntu18.04 pytorch1.10 cuda10.2 python3.6

import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt

class Net(nn.Module):

    def __init__(self):
        super().__init__()                              #inheritance the classes from nn.Module
        self.conv1 = nn.Conv2d(1, 1, 3)                 #define a kernal(input1,output1,windowsize(3*3))

    def forward(self,x):
        x = self.conv1(x)                               #define forward function,only one layer and no activation function
        return x

net = Net()

net = net.cuda()                                        #use GPU accelerate,need to put the module and tensors on GPU by cuda()

# print(list(net.parameters()))

input = torch.randn(1, 1, 5, 5, requires_grad=True)     #generate input by torch.randn
input = input.cuda()


para = list(net.parameters())                           #net.parameters() have 2 dimensions,one is weights,one is bias
# print(para[0])                                        #can also use net.kernal.bias or net.kernal.weight to show

# print(net.conv1.bias.grad)                            #use net.parameters()[].grad or net.kernal.bias(weight).grad to show the grad



target = torch.ones(1, 1, 3, 3).cuda()                  #generate the target data

learning_rate = 0.00000000001                           #define learning rate

iterations = []                                         #use lists to record iteration times corresponding lossnum
lossnum = []


for i in range(200001):
    loss = nn.MSELoss()                                 #the mean squared error,only single number
    output = net(input).cuda()
    loss = loss(output, target).cuda()
    iterations.append(i)                                #add num in the list
    lossnum.append(loss.cpu().detach().numpy())
    if i%1000 == 0:
        print("iteration times:",i)
        print(loss)
    loss.backward()                                     #do back propagation

    # print(para)
    # print(net.conv1.weight.grad)
    for f in net.parameters():
        f.data.sub_(f.grad.data * learning_rate)        #update the weights and bias,use f in net.parameters() to traverse all parameters
                                                        #use data.sub_() to subtract grad*learning_rate to update

output = net(input).cuda()
print(output)
print(type(lossnum[0]))

plt.xlim()
plt.ylim()
plt.plot(iterations,lossnum,'ro')
plt.show()                                              #plot the curve to show the relationship between iteration times and loss
# print(para)

# output2 = net(input)
# loss2 = nn.MSELoss()
# loss2 = loss2(output2, target)
# print(loss2)
# print(net.conv1.weight.grad)

因为ubuntu这个搜狗输入法在pycharm里一直贴在左下角,很难用,就用英文写了注释,包含了我对一些函数的理解和用法,如有不对也请指正。

一开始学习率设在了0.01左右,发现效果奇差,后来改成了特别小,效果才好起来,可能是本身数据也小吧。

最后自己跑出来的迭代次数和损失值的关系最后自己跑出来的迭代次数和损失值的关系,感觉这样应该算是收敛了吧。

<think>嗯,用户想用PyTorch从零搭建一个循环神经网络。首先,我得确定他们是否了解RNN的基础知识。可能他们需要一些理论背景,但问题更偏向于实践。所以,我应该先简要介绍RNN的结构,然后逐步讲解如何实现。 接下来,用户可能希望看到代码示例,但需要确保代码符合PyTorch的最佳实践。比如,应该继承nn.Module类,并实现forward方法。同时,需要处理输入数据的形状,比如时间步、批次大小和输入维度。 然后,初始化隐藏状态是关键。RNNCell需要手动管理隐藏状态,而如果是用nn.RNN的话,可能更简单。但用户要求从零搭建,可能意味着不使用内置的RNN模块,所以用RNNCell更合适。 在代码部分,要解释每个步骤的作用,比如输入和隐藏状态的维度,矩阵乘法和激活函数的应用。同时,要提到参数初始化的方法,比如Xavier初始化,这对训练效果很重要。 之后,可能需要提供一个使用示例,展示如何实例化模型、生成随机输入数据,并进行前向传播。这会帮助用户理解实际应用中数据的流动。 另外,用户可能想知道如何扩展这个基础RNN,比如堆叠多层、使用不同的激活函数,或者处理变长序列。这些扩展点可以增强他们的理解,并指导后续的学习方向。 最后,需要检查代码是否符合PyTorch的语法,确保没有错误,比如张量的形状是否正确,参数是否需要梯度。同时,提醒用户注意训练时的细节,比如梯度裁剪和优化器的选择,这些对模型收敛很重要。 可能用户的实际需求是学习如何构建RNN,用于时间序列或自然语言处理任务。因此,强调输入输出的结构和参数的作用有助于他们应用到具体问题中。确保回答结构清晰,分步骤讲解,让用户能够逐步跟随并实现自己的网络。</think>好的,我将分步骤为您讲解如何用PyTorch从零搭建循环神经网络(RNN)。以下是详细的实现过程: --- ### 一、RNN基本原理 循环神经网络的核心公式: $$ h_t = \tanh(W_{ih}x_t + b_{ih} + W_{hh}h_{t-1} + b_{hh}) $$ 其中: - $x_t$:时间步$t$的输入 - $h_t$:隐藏状态 - $W$和$b$:可学习参数 --- ### 二、基础RNN实现代码 ```python import torch import torch.nn as nn class SimpleRNN(nn.Module): def __init__(self, input_size, hidden_size, output_size): super(SimpleRNN, self).__init__() self.hidden_size = hidden_size # 输入到隐藏层的权重 self.W_ih = nn.Parameter(torch.Tensor(input_size, hidden_size)) # 隐藏层到隐藏层的权重 self.W_hh = nn.Parameter(torch.Tensor(hidden_size, hidden_size)) # 输出层权重 self.W_out = nn.Parameter(torch.Tensor(hidden_size, output_size)) # 参数初始化 self.reset_parameters() def reset_parameters(self): nn.init.xavier_uniform_(self.W_ih) nn.init.xavier_uniform_(self.W_hh) nn.init.xavier_uniform_(self.W_out) def forward(self, x, hidden=None): # x形状:(seq_len, batch, input_size) seq_len, batch_size, _ = x.size() if hidden is None: hidden = torch.zeros(batch_size, self.hidden_size) outputs = [] for t in range(seq_len): hidden = torch.tanh( x[t] @ self.W_ih + hidden @ self.W_hh ) outputs.append(hidden @ self.W_out) return torch.stack(outputs), hidden ``` --- ### 三、关键组件说明 1. **参数初始化**: - 使用Xavier初始化保证参数在合理范围 - 防止梯度爆炸/消失 2. **前向传播**: - 处理时序数据时逐个时间步计算 - 每个时间步更新隐藏状态$h_t$ - 输出层计算:$y_t = h_tW_{out}$ 3. **输入输出维度**: - 输入形状:`(序列长度, batch大小, 输入维度)` - 输出形状:`(序列长度, batch大小, 输出维度)` --- ### 四、使用示例 ```python # 超参数 input_size = 10 hidden_size = 20 output_size = 5 seq_len = 7 batch_size = 3 # 实例化模型 rnn = SimpleRNN(input_size, hidden_size, output_size) # 生成随机输入 x = torch.randn(seq_len, batch_size, input_size) # 前向传播 outputs, hidden = rnn(x) print(outputs.shape) # torch.Size([7, 3, 5]) ``` --- ### 五、扩展改进建议 1. **多层RNN**: ```python class MultiLayerRNN(nn.Module): def __init__(self, num_layers, ...): self.layers = nn.ModuleList([RNNCell(...) for _ in range(num_layers)]) ``` 2. **双向RNN**: - 同时处理正向和反向序列 3. **变种结构**: - LSTM:增加遗忘门/输入门/输出门 - GRU:简化门控机制 --- ### 六、训练注意事项 1. **梯度裁剪**: ```python torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=5) ``` 2. **序列处理技巧**: - 使用pack_padded_sequence处理变长序列 - Teacher Forcing训练策略 --- 通过这个基础实现,您可以理解RNN的核心工作机制。实际应用中建议使用PyTorch内置的`nn.RNN`、`nn.LSTM`等模块,它们已优化了计算效率并支持更多功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值