处理大量文件的错误代码逻辑

Wrong code logic for processing large number of files

我是初学者,不熟悉 python 和图像处理。对于一个大学项目,我试图训练一种区域语言的字符识别。我有一个非常庞大的数据集(大约 90000 张图像)。下面的代码部分用于将图像提取到数据集。但是,当我 运行 代码耗尽我的 8GB RAM 时,我的电脑死机了。这可能是由于处理了大量图像。

My PC Specs: Intel Core I5 8th Gen 8GB RAM NVIDIA Geforce GTX 1060 6GB.

是否有解决此问题的方法,以便我可以 运行 在我的 PC 上使用它?任何帮助将不胜感激。

%matplotlib inline


root_dir = os.getcwd()
img_dir = os.path.join(root_dir, 'images')

pixels = np.array(['pixel_{:04d}'.format(x) for x in range(1024)])
flag = True

for char_name in sorted(os.listdir(img_dir)):
    char_dir = os.path.join(img_dir, char_name)
    img_df = pd.DataFrame(columns=pixels)

    for img_file in sorted(os.listdir(char_dir)):
        image = pd.Series(imageio.imread(os.path.join(char_dir, img_file)).flatten(), index=pixels)
        img_df = img_df.append(image.T, ignore_index=True)

    img_df = img_df.astype(np.uint8)
    img_df['character'] = char_name

    img_df.to_csv('data.csv', index=False, mode='a', header=flag)
    flag=False

    print('=', end='')


df = pd.read_csv('data.csv')

df['character_class'] = LabelEncoder().fit_transform(df.character)
df.drop('character', axis=1, inplace=True)
df = df.astype(np.uint8)

虽然我不是您问题的根本原因,但我会根据我处理大型数据集的经验添加一些注释。

  1. 文本文件,其中包括 CSV,在磁盘 space、内存(字符串)和处理(读取、解析和转换为其他类型)方面非常昂贵。每次 pandas 读取一个 CSV 文件,它会逐行读取,解析下一个并构造 python 个对象。这很费时间。
  2. 大型文本文件,特别是大型 .csv 文件,不适用于 pandas。我真的不能指出确切的原因,但我无法将超过 2GB 的 csv 文件加载到具有 16GB ram 机器的数据框中。
  3. 良好的数据序列化总是比一般的序列化更好。但是,pickle 是一种非常通用的 python 对象序列化方法,可以很好地处理许多类型的对象。当然,它有漏洞,等等。对于纯粹的 python 研究工作,这是保存对象的好方法 easy。 Panda 的 DataFrame 将它与其他方式集成在一起来保存您的对象。使用`df.to_pickle('/path/to/file.pkl')
  4. 大文件是单点故障。我认为最好有几个文件并使用适当的数据 reader 来完成您的任务。

话虽如此,这是我的

%matplotlib inline


root_dir = os.getcwd()
img_dir = os.path.join(root_dir, 'images')

pixels = np.array(['pixel_{:04d}'.format(x) for x in range(1024)])
flag = True
chars = sorted(os.listdir(img_dir))

for char_name in chars:
    char_dir = os.path.join(img_dir, char_name)
    img_df = pd.DataFrame(columns=pixels)

    for img_file in sorted(os.listdir(char_dir)):
        image = pd.Series(imageio.imread(os.path.join(char_dir, img_file)).flatten(), index=pixels)
        img_df = img_df.append(image.T, ignore_index=True)

    img_df = img_df.astype(np.uint8)
    img_df['character'] = char_name

    img_df.to_pickle(f'{char_name}_data.pkl')
    flag=False

    print('=', end='')


df = pd.concat([pd.read_pickle(f'{char_name}_data.pkl') for char_name in chars],axis=0)

df['character_class'] = LabelEncoder().fit_transform(df.character)
df.drop('character', axis=1, inplace=True)
df = df.astype(np.uint8)

或者,您仍然可以通过附加数据框并保存最终文件来使用单个文件:

%matplotlib inline


root_dir = os.getcwd()
img_dir = os.path.join(root_dir, 'images')

pixels = np.array(['pixel_{:04d}'.format(x) for x in range(1024)])
df = pd.DataFrame(columns=['character'] + pixels.tolist())
for char_name in sorted(os.listdir(img_dir)):
    char_dir = os.path.join(img_dir, char_name)
    img_df = pd.DataFrame(columns=pixels)

    for img_file in sorted(os.listdir(char_dir)):
        image = pd.Series(imageio.imread(os.path.join(char_dir, img_file)).flatten(), index=pixels)
        img_df = img_df.append(image.T, ignore_index=True)

    img_df = img_df.astype(np.uint8)
    img_df['character'] = char_name
    df.append(image_df)
    print('=', end='')

df.to_pickle('data.pkl')
df = pd.read_pickle('data.pkl')

df['character_class'] = LabelEncoder().fit_transform(df.character)
df.drop('character', axis=1, inplace=True)
df = df.astype(np.uint8)

如果这能解决您的问题,请告诉我。 这似乎是一个小问题,但我知道这类事情调试起来可能很耗时。

P.S。 由于您使用魔法,我假设您使用 Jupyter。 您的机器是 +/- 笔记本电脑;我建议关闭 jupyter notebook/lab 中的所有 运行 内核,并在处理大数据时只使用一个内核。