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

标签 python python-3.x python-2.7 dataset ocr

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

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

是否有任何解决方法,以便我可以在我的电脑上运行它?任何帮助将不胜感激。

%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)在磁盘空间、内存(字符串)和处理(读取、解析和转换为其他类型)方面都很昂贵。每次 pandas 读取 CSV 文件时,它都会逐行读取,解析下一个并构造 python 对象。这很耗时。
  2. 大型文本文件,特别是大型 .csv 文件,不适用于 pandas。我真的无法指出确切的原因,但我无法使用 16GB 内存机器将超过 2GB 的 csv 文件加载到数据框中。
  3. 良好的数据序列化总是比一般的数据序列化要好。然而,pickle 是一种非常通用的 Python 对象序列化方法,对于许多类型的对象都表现良好。当然,它有漏洞,等等。对于纯粹的 Python 研究工作来说,这是保存对象的简单方法。 Panda 的 DataFrame 将其与其他方法集成以保存对象。使用 `df.to_pickle('/path/to/file.pkl')
  4. 巨大的文件会导致单点故障。我认为最好有多个文件并使用适当的数据读取器来完成您的任务。

话虽如此,这是我的

%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)

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

附注 既然你使用魔法,我假设你使用 Jupyter。 您的机器是 +/- 笔记本电脑;我建议关闭 jupyter 笔记本/实验室中所有正在运行的内核,并在处理大数据时仅使用一个内核。

关于python - 处理大量文件的错误代码逻辑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55290125/

相关文章:

python - python tkinter 应用程序中的简单按键事件

python - 有没有办法在 MacOS 上为 st_dev 获得有意义的挂载点?

python - Windows下查看Python程序最大内存使用

python - 处理 settrace 'return' 调用中的异常

Python 多重处理 - 太慢

python - 如何使用方向键触发PyQt4事件

python - Numpy,连接整数和 ndarrays 的简单公式

python-3.x - 使用 urllib.request 查询具有一系列 x-api-key header 的 url

python - 将 Azure 服务管理与 python sdk 连接

python - 分配字母数值