tjdnbj 2024-03-10 18:07 采纳率: 41.2%
浏览 6
已结题

深度学习循环神经网络提问2

以下是我的代码,想问一下运行后为何会出现TypeError: zeros(): argument 'size' must be tuple of ints, but found element of type Linear at pos 2的错误呢?该如何修改呢?

import time
import math
import zipfile

import numpy as np
import torch
from torch import nn,optim
import torch.nn.functional as F

import sys
sys.path.append("C:/Users/zyx20/Desktop/深度学习编程/pythonProject")
import d2lzh_pytorch as d2l
device=torch.device('cuda' if torch.cuda.is_available() else 'cpu')

with zipfile.ZipFile('C:/Users/zyx20/Desktop/深度学习编程/data20201205-master/Data20201205/jaychou_lyrics.txt.zip') as zin:
    with zin.open('jaychou_lyrics.txt') as f:
        corpus_chars=f.read().decode('utf-8')
corpus_chars=corpus_chars.replace('\n','').replace('\r','')
idx_to_char=list(set(corpus_chars))
char_to_idx=dict([(char,i) for i,char in enumerate(idx_to_char)])
vocab_size=len(char_to_idx)
corpus_indices=[char_to_idx[char] for char in corpus_chars]

num_hiddens=256
rnn_layer=nn.RNN(input_size=vocab_size,hidden_size=num_hiddens)

class RNNModel(nn.Module):
    def __init__(self,rnn_layer,vocab_size):
        super(RNNModel,self).__init__()
        self.rnn=rnn_layer
        self.hidden_size=rnn_layer.hidden_size*(2 if rnn_layer.bidirectional else 1)
        self.vocab_size=nn.Linear(self.hidden_size,vocab_size)
        self.state=None

    def forward(self,inputs,state):
        x=d2l.to_onehot(inputs,self.vocab_size)
        y,self.state=self.rnn(torch.stack(x),state)
        output=self.dense(y.view(-1,y.shape[-1]))
        return output,self.state
#定义预测函数
def predict_rnn_pytorch(prefix,num_chars,model,vocab_size,device,idx_to_char,char_to_idx):
    state=None
    output=[char_to_idx[prefix[0]]]
    for t in range(num_chars+len(prefix)-1):
        x=torch.tensor([output[-1]],device=device).view(1,1)
        if state is not None:
            if isinstance(state,tuple):
                state=(state[0].to(device),state[1].to(device))
            else:
                state=state.to(device)

        (y,state)=model(x,state)
        if t<len(prefix)-1:
            output.append(char_to_idx[prefix[t+1]])
        else:
            output.append(int(y.argmax(dim=1).item()))
    return ''.join([idx_to_char[i] for i in output])
model=RNNModel(rnn_layer,vocab_size).to(device)
#定义模型训练函数
def train_and_predict_rnn(model,num_hiddens,vocab_size,device,corpus_indices,
                          idx_to_char,char_to_idx,num_epochs,num_steps,lr,clipping_theta,
                          batch_size,pred_period,pred_len,prefixes):
    optimizer=torch.optim.Adam(model.parameters(),lr=lr)
    model.to(device)
    state=None
    loss=nn.CrossEntropyLoss()

    for epoch in range(num_epochs):
        l_sum,n,start=0.0,0,time.time()
        data_iter=d2l.data_iter_consecutive(corpus_indices,batch_size,num_steps,device)
        for x,y in data_iter:
            if state is not None:
                if isinstance(state,tuple):
                    state=(state[0].to(device),state[1].to(device))
                else:
                    state=state.detach()

        (output,state)=model(x,state)
        y=torch.transpose(y,0.1).contiguous.view(-1)
        l=loss(output,y.long())

        optimizer.zero_grad()
        l.backward()
        d2l.grad_clipping(model.parameters(), clipping_theta, device)
        optimizer.step()
        l_sum += l.item() * y.shape[0]
        n += y.shape[0]

        if (epoch+1)%pred_period==0:
            print('epoch %d,perplexity %f,time %.2f sec'%(epoch+1,math.exp(l_sum/n),time.time()-start))
            for prefix in prefixes:
                print(' -',predict_rnn_pytorch(prefix,pred_len,model,vocab_size,device,idx_to_char,char_to_idx))

num_epochs,num_steps,batch_size,lr,clipping_theta=250,35,32,1e-3,1e-2
pred_period,pred_len,prefixes=50,50,['分开','不分开']
train_and_predict_rnn(model,num_hiddens,vocab_size,device,corpus_indices,
                          idx_to_char,char_to_idx,num_epochs,num_steps,lr,clipping_theta,
                          batch_size,pred_period,pred_len,prefixes)

  • 写回答

2条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-03-10 18:08
    关注

    引自免费微信小程序:皆我百晓生

    在您提供的代码中,错误出现在 RNNModel 类的初始化函数内,具体是这一行:

    self.vocab_size=nn.Linear(self.hidden_size,vocab_size)
    

    这里的 vocab_size 是一个整数,代表词汇表大小,但 nn.Linear 需要的第一个参数(输入维度)和第二个参数(输出维度)都应该是整数。显然,您想在这里构建一个线性层作为最后的输出层,将隐藏状态映射到词汇表大小的输出概率分布上。

    修正的办法是将这个变量名改为其他名称以避免与 vocab_size 整数混淆,并赋予正确的输入维度,假设这里输入维度就是 RNN 的隐藏层大小,可以修改为:

    self.output_layer = nn.Linear(self.hidden_size, vocab_size)
    

    然后,在 forward 函数里,将原来使用 vocab_size 的地方改为 self.output_layer

    output = self.output_layer(y.view(-1, y.shape[-1]))
    

    因此,完整的 RNNModel 类定义应修改为:

    class RNNModel(nn.Module):
        def __init__(self, rnn_layer, vocab_size):
            super(RNNModel, self).__init__()
            self.rnn = rnn_layer
            self.hidden_size = rnn_layer.hidden_size * (2 if rnn_layer.bidirectional else 1)
            self.output_layer = nn.Linear(self.hidden_size, vocab_size)  # 修改这里
            self.state = None
    
        def forward(self, inputs, state):
            x = d2l.to_onehot(inputs, vocab_size)  # 假设 to_onehot 函数正确处理了 one-hot 编码
            y, self.state = self.rnn(torch.stack(x), state)
            output = self.output_layer(y.view(-1, y.shape[-1]))  # 修改这里
            return output, self.state
    

    请注意,根据您的代码上下文,d2l.to_onehot(inputs, vocab_size) 这部分可能也需要确保其正确性,因为通常循环神经网络模型不需要对输入数据进行 one-hot 编码,而是直接传入索引值即可。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 3月18日
  • 已采纳回答 3月10日
  • 创建了问题 3月10日

悬赏问题

  • ¥15 vscode编译ros找不到头文件,cmake.list文件出问题,如何解决?(语言-c++|操作系统-linux)
  • ¥15 通过AT指令控制esp8266发送信息
  • ¥15 有哪些AI工具提供可以通过代码上传EXCEL文件的API接口,并反馈分析结果
  • ¥15 二维装箱算法、矩形排列算法(相关搜索:二维装箱)
  • ¥20 nrf2401上电之后执行特定任务概率性一直处于最大重发状态
  • ¥15 二分图中俩集合中节点数与连边概率的关系
  • ¥20 wordpress如何限制ip访问频率
  • ¥15 自研小游戏,需要后台服务器存储用户数据关卡配置等数据
  • ¥15 请求解答odoo17外发加工某工序的实操方法
  • ¥20 IDEA ssm项目 跳转页面报错500