我的 Azure 数据存储中有数千个图像文件。我想将它们流式传输到 AzureML Jupyter 笔记本实例中的
datasets
对象中。
我正在使用下面的代码,但它在 45 分钟后继续运行,看不到尽头:
from azureml.fsspec import AzureMachineLearningFileSystem
from datasets import Dataset
fs = AzureMachineLearningFileSystem('azureml://subscriptions/<sub_id>/resourcegroups/<rg_name>/workspaces/<ws_name>/datastores/<ds_name')
file_lst = fs.ls('datastore_subdir/')[1:]
def process_image():
for file in file_lst:
img = Image.open(fs.open(file))
yield {'image': img}
image_ds = Dataset.from_generator(process_image)
我已经使用this问题的答案进行了这项工作。但是,想了解是否有办法使用生成器方法让它工作。
作为比较,以下内容在 1.5 分钟内完成:
import io
img_lst = []
for file in fs.ls('datastore_subdir/')[1:]:
with fs.open(file) as f:
print(counter)
img = Image.open(io.BytesIO(f.read()))
img_lst.append(img)
Dataset.from_generator
方法是创建数据集最节省内存的方法。您可以参考here有关此内容的文档。
还提到它对于内存无法容纳的大型数据集非常有用。
如果您面临性能问题(例如消耗更多时间),那是因为磁盘上逐渐生成的大型数据集。
因此,如果您有足够的内存来容纳如此大的数据集,请使用
Dataset.from_dict
本身。
此外,如果您需要,您可以与
concurrent.futures
模块并行生成图像列表。
以下是示例代码。
import io
from PIL import Image
from concurrent.futures import ThreadPoolExecutor
def load_and_process_images(file_list):
def process_image(file):
with fs.open(file) as f:
img = Image.open(io.BytesIO(f.read()))
return img
with ThreadPoolExecutor() as executor:
processed_images = list(executor.map(process_image, file_list))
return processed_images
file_lst = fs.ls('Siirt_Pistachio/')
print(f"Total images {len(file_lst)}")
batch_size = 50
processed_data = []
for i in range(0, len(file_lst), batch_size):
batch_files = file_lst[i:i + batch_size]
print(i)
processed_data.extend(load_and_process_images(batch_files))
image_ds = Dataset.from_dict({'image':processed_data})
输出: