getting AttributeError: 'numpy.ndarray' object has no attribute 'dim' when converting tensorflow code to pytorch

Question:

I was translating my TensorFlow code to PyTorch and suddenly faced this error.

What am I doing wrong here?

    AttributeError                            Traceback (most recent call last)
    <ipython-input-36-058644576709> in <module>
          3 batch_size = 1024
          4 Xtrain = torch.concat(
    ----> 5     [transforms(Xtrain[batch_size*batch:batch_size*(batch +1)]) for batch in range(len(Xtrain)//batch_size+1)],
          6     axis=0
          7 )
    
    <ipython-input-36-058644576709> in <listcomp>(.0)
          3 batch_size = 1024
          4 Xtrain = torch.concat(
    ----> 5     [transforms(Xtrain[batch_size*batch:batch_size*(batch +1)]) for batch in range(len(Xtrain)//batch_size+1)],
          6     axis=0
          7 )
    
    <ipython-input-22-9fc8aa48e3e2> in transforms(x)
          1 def transforms(x: torch.Tensor) -> torch.Tensor:
          2     """Return Fourrier spectrogram."""
    ----> 3     spectrograms = torch.stft(x, win_length=32, n_fft=4, hop_length=64)
          4     spectrograms = torch.abs(spectrograms)
          5     return torch.einsum("...ijk->...jki", spectrograms)
    
    ~anaconda3libsite-packagestorchfunctional.py in stft(input, n_fft, hop_length, win_length, window, center, pad_mode, normalized, onesided, return_complex)
        565     #       this and F.pad to ATen.
        566     if center:
    --> 567         signal_dim = input.dim()
        568         extended_shape = [1] * (3 - signal_dim) + list(input.size())
        569         pad = int(n_fft // 2)
    
    AttributeError: 'numpy.ndarray' object has no attribute 'dim'

The following is the approach I have tried already:


    #!/usr/bin/env python
    # coding: utf-8
    
    # # Import library
    
    # In[1]:
    
    
    get_ipython().run_line_magic('matplotlib', 'inline')
    get_ipython().run_line_magic('load_ext', 'autoreload')
    get_ipython().run_line_magic('autoreload', '2')
    #%matplotlib qt 
    
    
    # # Load pooled data
    
    # In[2]:
    
    
    from nu_smrutils import loaddat
    import pandas as pd
    
    
    # In[26]:
    
    
    import pickle
    import mne
    import numpy as np
    import matplotlib.pyplot as plt
    import seaborn as sns # Seaborn is a Python
    #  data visualization library built on top of Matplotlib.
    import datetime # module supplies classes for manipulating dates and times.
    
    import nu_smrutils # utils for SMR
    import nu_MIdata_loader # MI data loader
    
    import tensorflow as tf
    from tensorflow import keras
    from tensorflow.keras import layers
    
    
    # In[3]:
    
    
    dname = dict(BNCI2014004 = 'aBNCI2014004R.pickle',
                 BNCI2014001 = 'aBNCI2014001R.pickle',
                 Weibo2014   = 'aWeibo2014R.pickle',
                 Physionet   = 'aPhysionetRR.pickle')
    
    
    # In[4]:
    
    
    # itemname is one of : ['BNCI2014004', 'BNCI2014001', 'Weibo2014', 'Physionet']
    itemname = 'BNCI2014004'
    filename = dname[itemname]
    iname = itemname + '__'    
    
    
    # In[5]:
    
    
    data = loaddat(filename)
    
    
    # In[6]:
    
    
    data[0]['right_hand'].plot();
    
    
    # In[7]:
    
    
    from nu_smrutils import load_pooled, augment_dataset, crop_data
    
    
    # In[8]:
    
    
    subjectIndex = list(range(108))
    class_name = ['left_hand', 'right_hand']
    
    dat = load_pooled(data, subjectIndex, class_name, 
                      normalize = True, test_size = 0.15)
    
    
    # # Data augmentation 
    
    # In[9]:
    
    
    print(dat.keys())
    dat['xtrain'].shape
    
    
    # In[10]:
    
    
    get_ipython().run_line_magic('pinfo', 'augment_dataset')
    
    
    # In[11]:
    
    
    augdata = dict(std_dev = 0.01, multiple = 2)
    
    
    # In[12]:
    
    
    xtrain, ytrain = augment_dataset(dat['xtrain'], dat['ytrain'], 
                                     augdata['std_dev'], augdata['multiple'])
    
    print("Shape after data augmentation :", xtrain.shape)
    dat['xtrain'], dat['ytrain'] = xtrain, ytrain
    
    
    # # Data Cropping
    
    # In[14]:
    
    
    fs = 80 # sampling frequency 
    crop_len = 1.5 #or None
    crop = dict(fs = fs, crop_len = crop_len)
    
    #if crop['crop_len']:
    X_train,y_train = crop_data(crop['fs'],crop['crop_len'], 
                                dat['xtrain'], dat['ytrain'], 
                                xpercent = 50)
    
    X_valid,y_valid = crop_data(crop['fs'],crop['crop_len'], 
                                dat['xvalid'], dat['yvalid'], 
                                xpercent = 50)
    
    X_test, y_test  = crop_data(crop['fs'],crop['crop_len'], 
                                dat['xtest'], dat['ytest'], 
                                xpercent = 50)
    
    dat = dict(xtrain = X_train, xvalid = X_valid, xtest = X_test,
               ytrain = y_train, yvalid = y_valid, ytest = y_test)
    
    
    # In[16]:
    
    
    print('data shape after cropping :',dat['xtrain'].shape)
    
    
    # # Pytorch dataloaders 
    
    # In[18]:
    
    
    import torch 
    from torch.utils.data import TensorDataset, DataLoader  
    
    def get_data_loaders(dat, batch_size, EEGNET = None):    
        # convert data dimensions to into to gray scale image format
        if EEGNET: ### EEGNet model requires the last dimension to be 1 
            ff = lambda dat: torch.unsqueeze(dat, dim = -1)    
        else:
            ff = lambda dat: torch.unsqueeze(dat, dim = 1)    
        
        x_train, x_valid, x_test = map(ff,(dat['xtrain'], dat['xvalid'],dat['xtest']))    
        y_train, y_valid, y_test = dat['ytrain'], dat['yvalid'], dat['ytest']
        print('Input data shape', x_train.shape)       
        
        # TensorDataset & Dataloader    
        train_dat    = TensorDataset(x_train, y_train) 
        val_dat      = TensorDataset(x_valid, y_valid) 
        
        train_loader = DataLoader(train_dat, batch_size = batch_size, shuffle = True)
        val_loader   = DataLoader(val_dat,   batch_size = batch_size, shuffle = False)
    
        output = dict(dset_loaders = {'train': train_loader, 'val': val_loader}, 
                      dset_sizes  =  {'train': len(x_train), 'val': len(x_valid)},
                      test_data   =  {'x_test' : x_test, 'y_test' : y_test})          
        return output 
    
    
    # In[19]:
    
    
    dat = get_data_loaders(dat, batch_size = 64)
    dat.keys()
    
    
    # In[20]:
    
    
    # Sanity check begin 
    dset_loaders = dat['dset_loaders']
    dset_sizes = dat['dset_sizes']
    dset_sizes
    
    dtrain = dset_loaders['train']
    dval   = dset_loaders['val']
    
    dtr = iter(dtrain)
    dv  = iter(dval)
    
    
    # In[21]:
    
    
    inputs, labels = next(dtr)
    print(inputs.shape, labels.shape)
    # Sanity check end 
    
    
    # In[29]:
    
    
    augmentdata = dict(std_dev = 0.01,  multiple = 1) # to augment data
    fs = 80
    
    crop_length = 1.5 #seconds
    crop = dict(fs = fs, crop_length = crop_length) # crop length
    
    class1, class2 = 'left_hand', 'right_hand'
    s = list(range(108))
    
    
    # In[31]:
    
    
    def convertY(Y):
        return np.concatenate([Y[:, None], np.where(Y == 0, 1, 0)[:, None]], axis=-1)
    
    
    # In[33]:
    
    
    def convert(d): # converting tran method
        Xtrain = d['xtrain'].numpy()    
        Xval   = d['xvalid'].numpy()
        Xtest  = d['xtest'].numpy()
    
        Ytrain = convertY(d['ytrain'].numpy())
        Yval   = convertY(d['yvalid'].numpy())
        Ytest  = convertY(d['ytest'].numpy()) 
        
        return Xtrain, Xval, Xtest, Ytrain, Yval, Ytest
    
    
    # In[34]:
    
    
    files = ['aBNCI2014004R.pickle', ]
    
    # In data we storage sample from different files
    Data = []
    for file in files:
        d = nu_MIdata_loader.EEGDataLoader(file, class_name = [class1, class2])
        d1 = d.load_pooled(s, normalize = True, crop = crop, test_size = 0.01, augmentdata = augmentdata)
        Data.append(convert(d1))
    
    
    # In[35]:
    
    
    # concatenate all data if there more then one file
    Xtrain = np.concatenate([d[0] for d in Data])
    Xval   = np.concatenate([d[1] for d in Data])
    Xtest  = np.concatenate([d[2] for d in Data])
    Xtrain = np.concatenate([Xtrain, Xval], axis=0)
    
    Ytrain = np.concatenate([d[3] for d in Data])
    Yval   = np.concatenate([d[4] for d in Data])
    Ytest  = np.concatenate([d[5] for d in Data])
    Ytrain = np.concatenate([Ytrain, Yval], axis=0)
    
    
    # In[22]:
    
    
    def transforms(x: torch.Tensor) -> torch.Tensor:
        """Return Fourrier spectrogram."""
        spectrograms = torch.stft(x, win_length=32, n_fft=4, hop_length=64)
        spectrograms = torch.abs(spectrograms)
        return torch.einsum("...ijk->...jki", spectrograms)
    
    
    # In[36]:
    
    
    # Convert data in batchs 
    # Cause outofmemort or python crash
    batch_size = 1024
    Xtrain = torch.concat(
        [transforms(Xtrain[batch_size*batch:batch_size*(batch +1)]) for batch in range(len(Xtrain)//batch_size+1)],
        axis=0
    )
    Xtest = torch.concat(
        [transforms(Xtest[batch_size*batch:batch_size*(batch +1)]) for batch in range(len(Xtest)//batch_size+1)],
        axis=0
    )
    
    # Convert to tensorflow tensors
    Ytrain = torch.cast(Ytrain, dtype='float32')
    Ytest = torch.cast(Ytest, dtype='float32')

Asked By: longwild laptop

||

Answers:

torch.stft is a PyTorch function and expects a Tensor as the input. You must convert your NumPy array into a tensor and then pass that as the input. You can use torch.from_numpy to do this.

Answered By: Hossein