在将处理过的数据转换为 numpy 数组时,我遇到了内存问题。我有 57GB 内存,但内存很快就饱和了,内核会在 np.array(processed_X)
处重启。以下是我的代码:
import numpy as np
导入 scipy.signal
from skimage.transform import resize
from tqdm import tqdm
def apply_stft(signal, nperseg=256, noverlap=128):
f、t、Zxx = scipy.signal.stft(signal, nperseg=nperseg, noverlap=noverlap)
返回 np.abs(Zxx)
def resize_stft(stft_result, output_shape=(224, 224)):
return resize(stft_result, output_shape, mode='constant')
def process_dataset(X):
processed_X = []
for example in tqdm(X):
stft_results = [apply_stft(example[:, i]) for i in range(example.shape[1])
resized_stft = [Resize_stft(stft) for stft in stft_results] (stft_results中的stft)
stacked_stft = np.stack(resized_stft, axis=-1)
processed_X.append(stacked_stft)
del stft_results,resized_stft,stacked_stft
print(len(processed_X))
print('FINISHED !!!')
return np.array(processed_X)
当代码执行到 np.array(processed_X)
时,我的内存使用率迅速飙升,最终耗尽所有可用内存并导致内核重启。我如何才能避免这一内存问题?
感谢您的帮助!
采取的步骤:
- 尝试删除中间变量以释放内存。
- 验证了问题发生在
np.array(processed_X)
行。
代码在处理大量数据时遇到内存问题的原因是,它将所有已处理的数据存储在一个名为 processed_X
的 Python 列表中,然后尝试一次性将该列表转换为 NumPy 数组。这会导致巨大的内存分配,从而使的系统不堪重负。
可以通过以下方法解决此问题,而无需一次性将所有数据加载到内存中:
- 使用内存映射文件:内存映射文件允许通过将文件映射到内存来处理大于可用内存的数据集。可以使用
numpy.memmap
创建一个空的内存映射文件,然后在处理每个示例时将处理后的数据逐步写入该文件。
```python import numpy as np import scipy.signal from skimage.transform import resize from tqdm import tqdm
def apply_stft(signal, nperseg=256, noverlap=128): f, t, Zxx = scipy.signal.stft(signal, nperseg=nperseg, noverlap=noverlap) return np.abs(Zxx)
def resize_stft(stft_result, output_shape=(224, 224)): return resize(stft_result, output_shape, mode='constant')
# 获取处理后的数据的形状 example_shape = None # 将其替换为处理后的单个示例的形状
# 创建一个空的内存映射数组 processed_X = np.memmap('processed_data.dat', dtype='float32', mode='w+', shape=(len(X), *example_shape))
def process_dataset(X): for i, example in enumerate(tqdm(X)): stft_results = [apply_stft(example[:, j]) for j in range(example.shape[1])] resized_stft = [resize_stft(stft) for stft in stft_results] stacked_stft = np.stack(resized_stft, axis=-1) # 将处理后的数据直接写入内存映射数组 processed_X[i] = stacked_stft print('FINISHED !!!') return processed_X
processed_X = process_dataset(X) ```
这将创建一个名为 processed_data.dat
的文件,其中包含已处理的数据。可以像处理常规 NumPy 数组一样访问和处理此内存映射数组,而无需将其全部加载到内存中。
- 使用生成器进行批处理:将数据分成较小的批次,并使用生成器一次处理一批。这将减少内存使用量,因为一次只会在内存中保留一小部分数据。
```python def process_batch(X_batch): processed_batch = [] for example in X_batch: stft_results = [apply_stft(example[:, i]) for i in range(example.shape[1])] resized_stft = [resize_stft(stft) for stft in stft_results] stacked_stft = np.stack(resized_stft, axis=-1) processed_batch.append(stacked_stft) return np.array(processed_batch)
def data_generator(X, batch_size): for i in range(0, len(X), batch_size): yield X[i:i + batch_size]
batch_size = # 选择合适的批次大小 for X_batch in data_generator(X, batch_size): processed_batch = process_batch(X_batch) # 使用处理后的批次执行其他操作,例如将其保存到磁盘或将其馈送到模型中 ```
这允许以较小的块的形式处理数据,从而防止内存不足错误。
请记住,最佳方法取决于的特定需求和数据大小。如果的数据仍然太大,请考虑使用分布式计算框架(如 Dask 或 Spark)来跨多台机器分配处理。
标签:python,arrays,numpy,out-of-memory,large-data From: 78553578