首页 > 编程问答 >RuntimeError:预期 2D(未批处理)或 3D(批处理)输入到 conv1d,但得到的输入大小为:[64, 64, 358, 12]

RuntimeError:预期 2D(未批处理)或 3D(批处理)输入到 conv1d,但得到的输入大小为:[64, 64, 358, 12]

时间:2024-08-09 02:48:08浏览次数:17  
标签:python deep-learning pytorch

我正在尝试运行一个名为“STFGNN”的图神经网络模型(可在 GitHub 上获取 https://github.com/lwm412/STFGNN-Pytorch/tree/main?tab=readme-ov-file|| |) 在 Kaggle 上。但是,我遇到了几个问题: 1:运行时警告:除法返回(a-mu)/std0中遇到无效值

2:

我尝试使用以下标准化函数:

Traceback (most recent call last):
  File "/kaggle/working/STFGNN/STFGNN-Pytorch-main/main.py", line 33, in <module>
    executor.train(train_data, valid_data)
  File "/kaggle/working/STFGNN/STFGNN-Pytorch-main/executor/multi_step_executor.py", line 82, in train
    output = self.model(trainx)
  File "/opt/conda/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1518, in _wrapped_call_impl
    return self._call_impl(*args, **kwargs)
  File "/opt/conda/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1527, in _call_impl
    return forward_call(*args, **kwargs)
  File "/kaggle/working/STFGNN/STFGNN-Pytorch-main/model/STFGNN.py", line 420, in forward
    x = model(x, self.mask)
  File "/opt/conda/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1518, in _wrapped_call_impl
    return self._call_impl(*args, **kwargs)
  File "/opt/conda/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1527, in _call_impl
    return forward_call(*args, **kwargs)
  File "/kaggle/working/STFGNN/STFGNN-Pytorch-main/model/STFGNN.py", line 207, in forward
    data_left = torch.sigmoid(self.conv1(data_temp))
  File "/opt/conda/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1518, in _wrapped_call_impl
    return self._call_impl(*args, **kwargs)
  File "/opt/conda/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1527, in _call_impl
    return forward_call(*args, **kwargs)
  File "/opt/conda/lib/python3.10/site-packages/torch/nn/modules/conv.py", line 310, in forward
    return self._conv_forward(input, self.weight, self.bias)
  File "/opt/conda/lib/python3.10/site-packages/torch/nn/modules/conv.py", line 306, in _conv_forward
    return F.conv1d(input, weight, bias, self.stride,

RuntimeError: Expected 2D (unbatched) or 3D (batched) input to conv1d, but got input of size: [64, 64, 358, 12]

然而,我仍然遇到这些问题。下面是我正在使用的主要代码和模型(STFGNN)的片段。您能否就可能出现的问题提供一些指导?

def normalize(a):
    mu=np.mean(a,axis=1,keepdims=True)
    std=np.std(a,axis=1,keepdims=True)
    return (a-mu)/std

Main:

STFGNN:


config = {}
for filename in ["config/PEMS03.json", "config/STFGNN.json"]:
    with open(filename, "r") as f:
        _config = json.load(f)
        for key in _config:
            if key not in config:
                config[key] = _config[key]

dataset = STFGNNDataset(config)

train_data, valid_data, test_data = dataset.get_data()
data_feature = dataset.get_data_feature()

model_cache_file = 'cache/model_cache/PEMS03_STFGNN.m'

model = STFGNN(config, data_feature)

executor = STFGNNExecutor(config, model)


train = True #标识是否需要重新训练

if train or not os.path.exists(model_cache_file):
    executor.train(train_data, valid_data)
    executor.save_model(model_cache_file)
else:
    executor.load_model(model_cache_file)
# 评估,评估结果将会放在 cache/evaluate_cache 下
executor.evaluate(test_data)

STFGNN:


class gcn_operation(nn.Module):
    def __init__(self, adj, in_dim, out_dim, num_vertices, activation='GLU'):
        """
        图卷积模块
        :param adj: 邻接图
        :param in_dim: 输入维度
        :param out_dim: 输出维度
        :param num_vertices: 节点数量
        :param activation: 激活方式 {'relu', 'GLU'}
        """
        super(gcn_operation, self).__init__()
        self.adj = adj
        self.in_dim = in_dim
        self.out_dim = out_dim
        self.num_vertices = num_vertices
        self.activation = activation

        assert self.activation in {'GLU', 'relu'}

        if self.activation == 'GLU':
            self.FC = nn.Linear(self.in_dim, 2 * self.out_dim, bias=True)
        else:
            self.FC = nn.Linear(self.in_dim, self.out_dim, bias=True)

    def forward(self, x, mask=None):
        """
        :param x: (3*N, B, Cin)
        :param mask:(3*N, 3*N)
        :return: (3*N, B, Cout)
        """
        adj = self.adj
        if mask is not None:
            adj = adj.to(mask.device) * mask

        x = torch.einsum('nm, mbc->nbc', adj.to(x.device), x)  # 4*N, B, Cin

        if self.activation == 'GLU':
            lhs_rhs = self.FC(x)  # 4*N, B, 2*Cout
            lhs, rhs = torch.split(lhs_rhs, self.out_dim, dim=-1)  # 4*N, B, Cout

            out = lhs * torch.sigmoid(rhs)
            del lhs, rhs, lhs_rhs

            return out

        elif self.activation == 'relu':
            return torch.relu(self.FC(x))  # 3*N, B, Cout


class STSGCM(nn.Module):
    def __init__(self, adj, in_dim, out_dims, num_of_vertices, activation='GLU'):
        """
        :param adj: 邻接矩阵
        :param in_dim: 输入维度
        :param out_dims: list 各个图卷积的输出维度
        :param num_of_vertices: 节点数量
        :param activation: 激活方式 {'relu', 'GLU'}
        """
        super(STSGCM, self).__init__()
        self.adj = adj
        self.in_dim = in_dim
        self.out_dims = out_dims
        self.num_of_vertices = num_of_vertices
        self.activation = activation

        self.gcn_operations = nn.ModuleList()

        self.gcn_operations.append(
            gcn_operation(
                adj=self.adj,
                in_dim=self.in_dim,
                out_dim=self.out_dims[0],
                num_vertices=self.num_of_vertices,
                activation=self.activation
            )
        )

        for i in range(1, len(self.out_dims)):
            self.gcn_operations.append(
                gcn_operation(
                    adj=self.adj,
                    in_dim=self.out_dims[i-1],
                    out_dim=self.out_dims[i],
                    num_vertices=self.num_of_vertices,
                    activation=self.activation
                )
            )

    def forward(self, x, mask=None):
        """
        :param x: (3N, B, Cin)
        :param mask: (3N, 3N)
        :return: (N, B, Cout)
        """
        need_concat = []

        for i in range(len(self.out_dims)):
            x = self.gcn_operations[i](x, mask)
            need_concat.append(x)

        # shape of each element is (1, N, B, Cout)
        need_concat = [
            torch.unsqueeze(
                h[self.num_of_vertices: 2 * self.num_of_vertices], dim=0
            ) for h in need_concat
        ]

        out = torch.max(torch.cat(need_concat, dim=0), dim=0).values  # (N, B, Cout)

        del need_concat

        return out


class STSGCL(nn.Module):
    def __init__(self,
                 adj,
                 history,
                 num_of_vertices,
                 in_dim,
                 out_dims,
                 strides=4,
                 activation='GLU',
                 temporal_emb=True,
                 spatial_emb=True):
        """
        :param adj: 邻接矩阵
        :param history: 输入时间步长
        :param in_dim: 输入维度
        :param out_dims: list 各个图卷积的输出维度
        :param strides: 滑动窗口步长,local时空图使用几个时间步构建的,默认为3
        :param num_of_vertices: 节点数量
        :param activation: 激活方式 {'relu', 'GLU'}
        :param temporal_emb: 加入时间位置嵌入向量
        :param spatial_emb: 加入空间位置嵌入向量
        """
        super(STSGCL, self).__init__()
        self.adj = adj
        self.strides = strides
        self.history = history
        self.in_dim = in_dim
        self.out_dims = out_dims
        self.num_of_vertices = num_of_vertices

        self.activation = activation
        self.temporal_emb = temporal_emb
        self.spatial_emb = spatial_emb


        self.conv1 = nn.Conv1d(self.in_dim, self.out_dims[-1], kernel_size=(1, 2), stride=(1, 1), dilation=(1, 3))
        self.conv2 = nn.Conv1d(self.in_dim, self.out_dims[-1], kernel_size=(1, 2), stride=(1, 1), dilation=(1, 3))


        self.STSGCMS = nn.ModuleList()
        for i in range(self.history - self.strides + 1):
            self.STSGCMS.append(
                STSGCM(
                    adj=self.adj,
                    in_dim=self.in_dim,
                    out_dims=self.out_dims,
                    num_of_vertices=self.num_of_vertices,
                    activation=self.activation
                )
            )

        if self.temporal_emb:
            self.temporal_embedding = nn.Parameter(torch.FloatTensor(1, self.history, 1, self.in_dim))
            # 1, T, 1, Cin

        if self.spatial_emb:
            self.spatial_embedding = nn.Parameter(torch.FloatTensor(1, 1, self.num_of_vertices, self.in_dim))
            # 1, 1, N, Cin

        self.reset()

    def reset(self):
        if self.temporal_emb:
            nn.init.xavier_normal_(self.temporal_embedding, gain=0.0003)

        if self.spatial_emb:
            nn.init.xavier_normal_(self.spatial_embedding, gain=0.0003)

    def forward(self, x, mask=None):
        """
        :param x: B, T, N, Cin
        :param mask: (N, N)
        :return: B, T-3, N, Cout
        """
        if self.temporal_emb:
            x = x + self.temporal_embedding

        if self.spatial_emb:
            x = x + self.spatial_embedding

        #############################################
        # shape is (B, C, N, T)
        data_temp = x.permute(0, 3, 2, 1)
        data_left = torch.sigmoid(self.conv1(data_temp))
        data_right = torch.tanh(self.conv2(data_temp))
        data_time_axis = data_left * data_right
        data_res = data_time_axis.permute(0, 3, 2, 1)
        # shape is (B, T-3, N, C)
        #############################################

        need_concat = []
        batch_size = x.shape[0]

        for i in range(self.history - self.strides + 1):
            t = x[:, i: i+self.strides, :, :]  # (B, 4, N, Cin)

            t = torch.reshape(t, shape=[batch_size, self.strides * self.num_of_vertices, self.in_dim])
            # (B, 4*N, Cin)

            t = self.STSGCMS[i](t.permute(1, 0, 2), mask)  # (4*N, B, Cin) -> (N, B, Cout)

            t = torch.unsqueeze(t.permute(1, 0, 2), dim=1)  # (N, B, Cout) -> (B, N, Cout) ->(B, 1, N, Cout)

            need_concat.append(t)

        mid_out = torch.cat(need_concat, dim=1)  # (B, T-3, N, Cout)
        out = mid_out + data_res

        del need_concat, batch_size

        return out


class output_layer(nn.Module):
    def __init__(self, num_of_vertices, history, in_dim, out_dim, 
                 hidden_dim=128, horizon=12):
        """
        预测层,注意在作者的实验中是对每一个预测时间step做处理的,也即他会令horizon=1
        :param num_of_vertices:节点数
        :param history:输入时间步长
        :param in_dim: 输入维度
        :param hidden_dim:中间层维度
        :param horizon:预测时间步长
        """
        super(output_layer, self).__init__()
        self.num_of_vertices = num_of_vertices
        self.history = history
        self.in_dim = in_dim
        self.out_dim = out_dim
        self.hidden_dim = hidden_dim
        self.horizon = horizon

        #print("#####################")
        #print(self.in_dim)
        #print(self.history)
        #print(self.hidden_dim)

        self.FC1 = nn.Linear(self.in_dim * self.history, self.hidden_dim, bias=True)

        #self.FC2 = nn.Linear(self.hidden_dim, self.horizon , bias=True)

        self.FC2 = nn.Linear(self.hidden_dim, self.horizon * self.out_dim, bias=True)

    def forward(self, x):
        """
        :param x: (B, Tin, N, Cin)
        :return: (B, Tout, N)
        """
        batch_size = x.shape[0]

        x = x.permute(0, 2, 1, 3)  # B, N, Tin, Cin

        out1 = torch.relu(self.FC1(x.reshape(batch_size, self.num_of_vertices, -1)))
        # (B, N, Tin, Cin) -> (B, N, Tin * Cin) -> (B, N, hidden)

        out2 = self.FC2(out1)  # (B, N, hidden) -> (B, N, horizon * 2)

        out2 = out2.reshape(batch_size, self.num_of_vertices, self.horizon, self.out_dim)

        del out1, batch_size

        return out2.permute(0, 2, 1, 3)  # B, horizon, N
        # return out2.permute(0, 2, 1)  # B, horizon, N


class STFGNN(nn.Module):
    def __init__(self, config, data_feature):
        """

        :param adj: local时空间矩阵
        :param history:输入时间步长
        :param num_of_vertices:节点数量
        :param in_dim:输入维度
        :param hidden_dims: lists, 中间各STSGCL层的卷积操作维度
        :param first_layer_embedding_size: 第一层输入层的维度
        :param out_layer_dim: 输出模块中间层维度
        :param activation: 激活函数 {relu, GlU}
        :param use_mask: 是否使用mask矩阵对adj进行优化
        :param temporal_emb:是否使用时间嵌入向量
        :param spatial_emb:是否使用空间嵌入向量
        :param horizon:预测时间步长
        :param strides:滑动窗口步长,local时空图使用几个时间步构建的,默认为4
        """
        super(STFGNN, self).__init__()

        self.config = config
        self.data_feature = data_feature
        self.scaler = data_feature["scaler"]
        self.num_batches = data_feature["num_batches"]

        adj = self.data_feature["adj_mx"]
        history = self.config.get("window", 12)
        num_of_vertices = self.config.get("num_nodes", None)
        in_dim = self.config.get("input_dim", 1)
        out_dim = self.config.get("output_dim", 1)
        hidden_dims = self.config.get("hidden_dims", None)
        first_layer_embedding_size = self.config.get("first_layer_embedding_size", None)
        out_layer_dim = self.config.get("out_layer_dim", None)
        activation = self.config.get("activation", "GLU")
        use_mask = self.config.get("mask")
        temporal_emb = self.config.get("temporal_emb", True)
        spatial_emb = self.config.get("spatial_emb", True)
        horizon = self.config.get("horizon", 12)
        strides = self.config.get("strides", 4)

        self.adj = adj
        self.num_of_vertices = num_of_vertices
        self.hidden_dims = hidden_dims
        self.out_layer_dim = out_layer_dim
        self.activation = activation
        self.use_mask = use_mask

        self.temporal_emb = temporal_emb
        self.spatial_emb = spatial_emb
        self.horizon = horizon
        self.strides = 4

        self.First_FC = nn.Linear(in_dim, first_layer_embedding_size, bias=True)
        self.STSGCLS = nn.ModuleList()
        #print("____________________")
        #print(history)

        self.STSGCLS.append(
            STSGCL(
                adj=self.adj,
                history=history,
                num_of_vertices=self.num_of_vertices,
                in_dim=first_layer_embedding_size,
                out_dims=self.hidden_dims[0],
                strides=self.strides,
                activation=self.activation,
                temporal_emb=self.temporal_emb,
                spatial_emb=self.spatial_emb
            )
        )

        in_dim = self.hidden_dims[0][-1]
        history -= (self.strides - 1)

        #print("!!!!!!!!!!!!!!!!!!!")
        #print(history)

        for idx, hidden_list in enumerate(self.hidden_dims):
            #print("?????? ", idx)
            if idx == 0:
                continue
            #print("---------", idx)
            self.STSGCLS.append(
                STSGCL(
                    adj=self.adj,
                    history=history,
                    num_of_vertices=self.num_of_vertices,
                    in_dim=in_dim,
                    out_dims=hidden_list,
                    strides=self.strides,
                    activation=self.activation,
                    temporal_emb=self.temporal_emb,
                    spatial_emb=self.spatial_emb
                )
            )
            history -= (self.strides - 1)
            in_dim = hidden_list[-1]

        self.predictLayer = nn.ModuleList()
        #print("***********************")
        #print(history)
        for t in range(self.horizon):
            self.predictLayer.append(
                output_layer(
                    num_of_vertices=self.num_of_vertices,
                    history=history,
                    in_dim=in_dim,
                    out_dim = out_dim,
                    hidden_dim=out_layer_dim,
                    horizon=1
                )
            )

        if self.use_mask:
            mask = torch.zeros_like(self.adj)
            mask[self.adj != 0] = self.adj[self.adj != 0]
            self.mask = nn.Parameter(mask)
        else:
            self.mask = None

    def forward(self, x):
        """
        :param x: B, Tin, N, Cin)
        :return: B, Tout, N
        """

        x = torch.relu(self.First_FC(x))  # B, Tin, N, Cin
        #print(1)

        for model in self.STSGCLS:
            x = model(x, self.mask)
        # (B, T - 8, N, Cout)
        #print(2)
        need_concat = []
        for i in range(self.horizon):
            out_step = self.predictLayer[i](x)  # (B, 1, N, 2)
            need_concat.append(out_step)
        #print(3)
        out = torch.cat(need_concat, dim=1)  # B, Tout, N, 2

        del need_concat

        return out

The error message you're seeing, "RuntimeError: Expected 2D (unbatched) or 3D (batched) input to conv1d, but got input of size: [64, 64, 358, 12]", tells us that your 1D convolutional layer ( conv1d ) is receiving a tensor with an unexpected shape. Let's break down why this is happening and how to fix it:

Understanding the Problem

  • 1D Convolution Expectation: The conv1d layer in PyTorch is designed for input tensors that represent sequences. It expects the input to be in one of these formats:

    • 2D (Unbatched): (sequence_length, features)
    • 3D (Batched): (batch_size, sequence_length, features)
  • Your Input Shape: Your error indicates you're feeding a tensor of shape [64, 64, 358, 12] to conv1d . This looks like you have:

    • batch_size = 64
    • sequence_length = 358 (or possibly 12, depending on your data's structure)
    • features = 64 (or possibly 358 x 12)
    • An extra dimension: The extra dimension (the second '64') is causing the issue.

Solution: Reshaping Your Data

You need to reshape your input tensor to fit the expectations of conv1d . Here's the general approach:

  1. Identify the Correct Dimensions:
  2. batch_size : This is likely 64, as in your error message.
  3. sequence_length : Determine the length of your sequences (e.g., time steps in time series data).
  4. features : The number of features per time step.

  5. Reshape Using view or reshape : Use PyTorch's tensor manipulation functions to achieve the desired 3D shape:

```python # Assuming sequence_length = 358 and features = 64 new_shape = (batch_size, sequence_length, features)
input_tensor = input_tensor.view(new_shape) # or input_tensor.reshape(new_shape)

# ... rest of your model code ... ```

Addressing the Normalization Warning

The warning "RuntimeWarning: invalid value encountered in true_divide" suggests you might have zero values in the standard deviation ( std ) calculation within your normalize function. This leads to division by zero errors.

Improved Normalization Function:

def normalize(a):
    mu = np.mean(a, axis=1, keepdims=True)
    std = np.std(a, axis=1, keepdims=True)
    std[std == 0] = 1e-8  # Replace zeros with a small value to avoid division by zero
    return (a - mu) / std 

Additional Tips:

  • Data Understanding: Carefully examine the structure of your input data to confirm you're reshaping it correctly. Use print statements to check the shapes of tensors at different points in your code.
  • Debugging: Use a debugger or strategically placed print statements to understand the flow of data through your model and identify the exact point where the shape mismatch occurs.

By reshaping your input tensor and handling potential zero values in your normalization, you'll address the RuntimeError and the warning, allowing your STFGNN model to process data as intended.

标签:python,deep-learning,pytorch
From: 78849990

相关文章

  • pyocr,一个超酷的Python库!
    pyocr是一个用于光学字符识别(OCR)的Python库,它提供了一个简单的接口,允许开发者将图片中的文本提取出来。这个库是对Tesseract-OCR的封装,使得在Python环境中使用OCR技术变得更加便捷。如何安装pyocr首先,要使用pyocr库,您需要安装它。可以使用pip包管理工具来进......
  • pattern,一款超牛的Python库
    在程序开发中,处理文本数据和进行自然语言处理是常见需求。pattern是一个强大的Python库,专为文本分析而设计,提供了丰富的功能,包括自然语言处理、数据挖掘和网络分析等。它简单易用,让程序员能够快速实现复杂的文本处理任务。如何安装pattern在开始使用pattern库之前,首先......
  • 【Playwright+Python】系列教程(八)鉴权Authentication的使用
    写在前面还是有些絮叨的感觉,官方翻译和某些博主写那个玩楞,基本都是软件直接翻译后的产物。读起来生硬不说,甚至有的时候不到是什么意思,真的是实在不敢恭维。到底是什么意思?就是你已经登陆过一次,在Session、Cookie未失效的情况下,登录过一次后,下次就不用再走一遍登录的过程,从而缩......
  • 基于CNN-GRU-Attention混合神经网络的负荷预测方法(Python代码实现)
    ......
  • Python和AI库NumPy(二):数组创建与操作的深入探索
    目录1.数组创建1.1基本数组创建1.2使用内置函数创建数组1.3特殊数组的创建2.数组的基本操作2.1数组属性2.2数组索引和切片2.3数组的形状操作2.4数组拼接与分割3.数组的数学操作3.1基本算术操作3.2广播机制3.3线性代数运算4.高级数组操作4.1花式......
  • 如何为本地python共享文件网页配置公网地址实现跨网络远程访问
    文章目录前言1.本地文件服务器搭建1.1.Python的安装和设置1.2.cpolar的安装和注册2.本地文件服务器的发布2.1.Cpolar云端设置2.2.Cpolar本地设置3.公网访问测试4.结语前言本文主要介绍如何在Windows系统电脑上使用python这样的简单程序语言,在自己的电脑上搭建一个......
  • 基于YOLOv10深度学习的交通信号灯检测识别系统【python源码+Pyqt5界面+数据集+训练代
    《博主简介》小伙伴们好,我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。✌更多学习资源,可关注公-仲-hao:【阿旭算法与机器学习】,共同学习交流~......
  • 用Python简单操作MySQL!轻松实现数据读写
    PyMySQL是Python编程语言中的一个第三方模块,它可以让Python程序连接到MySQL数据库并进行数据操作。它的使用非常简单,只需要安装PyMySQL模块,然后按照一定的步骤连接到MySQL数据库即可。本文将介绍PyMySQL的安装、连接MySQL数据库、创建表、插入数据、查询数据、更新数据和删除数据......
  • [python][代码]Python中操作DataFrame的常用方法
    Python中操作DataFrame的常用方法主要依赖于pandas库,这是一个功能强大的数据分析工具。以下是一些基本和常用的DataFrame操作方法:1.创建DataFrame:pythonimportpandasaspddata={'Column1':[1,2,3],'Column2':['a','b','c']}df=pd.DataFrame(......
  • 使用 Python 优雅地编排 Dockerfile
    使用python替代dockercompose编排容器dockercompose是docker的容器编排工具,它是基于YAML配置,YAML是一种配置文件格式,支持传递环境变量,但是对于复杂的容器编排显得力不从心。于是我便开发这个程序,可以像写程序一样编排docker,可以充分发挥程序猿的想象力。pipi......