简体   繁体   中英

Change 3d array to 4d array numpy

From following code, I have got 'log_specgrams' with shape (20,1,12060). I want to change the shape to (20, 60, 201, 1). So I wrote the code like this.

log_specgrams = np.asarray(log_specgrams).reshape(len(log_specgrams), 60, 201, 1)

But I gave an error:

Traceback (most recent call last):
  File "D:/for-test.py", line 26, in <module>
    features = extract_features(parent_dir,sub_dirs)
  File "D:/for-test.py", line 17, in extract_features
    log_specgrams = np.asarray(log_specgrams).reshape(len(log_specgrams), 60, 201, 1)
  File "C:\Users\CHS\Anaconda3\lib\site-packages\numpy\core\numeric.py", line 482, in asarray
    return array(a, dtype, copy=False, order=order)
ValueError: could not broadcast input array from shape (12060) into shape (1)
(1, 12060)

The whole code:

import glob
import os
import librosa
import numpy as np

def extract_features(parent_dir, sub_dirs, file_ext="*.wav"):
        log_specgrams = []
        for l, sub_dir in enumerate(sub_dirs):
                for fn in glob.glob(os.path.join(parent_dir, sub_dir, file_ext)):
                        X_in, sample_rate = librosa.load(fn)
                        melspec = librosa.feature.melspectrogram(y=X_in, sr=sample_rate, n_fft=1024, hop_length=441, n_mels=60)
                        logmel = librosa.logamplitude(melspec)
                        logmel = logmel.T.flatten()[:, np.newaxis].T
                        log_specgrams.append(logmel)

        print(np.shape(logmel))
        log_specgrams = np.asarray(log_specgrams).reshape(len(log_specgrams), 60, 201, 1)
        print(np.shape(log_specgrams))
        A = features

        return np.array(log_specgrams)


parent_dir = 'Sound-Data_small'
sub_dirs= ['fold1','fold2']
features = extract_features(parent_dir,sub_dirs)

I really want to change the shape of 'log_specgrams', (20,1,12060) to (20, 60, 201, 1).

Reshape takes the parameters as a tuple, ie

log_specgrams = np.asarray(log_specgrams).reshape((len(log_specgrams), 60, 201, 1))

or

log_specgrams = np.asarray(log_specgrams).reshape((None, 60, 201, 1))

None computes the missing dimension itself

Assuming that the input is (20,1,12060) and the desired output is (20, 60, 201, 1) with the 1 dimension swapped, the following should work just fine:

data = np.asarray(log_specgrams)
data = data.swapaxes(1, 2).reshape(20, 60, 201, 1)

Example with random data:

>>> data = np.random.randn(20, 1, 12060)
>>> data.shape
(20, 1, 12060)

Then,

>>> data = data.swapaxes(1, 2).reshape(20, 60, 201, 1)
>>> data.shape
(20, 60, 201, 1)

It can be noted that the operation has two components. The first part swapes the 2nd and 3rd axis, transforming the data from (20, 1, 12060) to (20, 12060, 1) . The second part divides the 2nd axis 12060 in two new ones of size 60 x 201 .

It works for arbitrary axes of different size, but for axes of size 1 that require no data rearranging, data.reshape(20, 60, 201, 1) or @yar's answer with a single reshape might be more straight forward. This solution just extends to other problems with axis size different from 1 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM