新闻中心
优化大规模CSV文件读取:解决Pandas与XGBoost内存问题的策略

本文旨在解决使用pandas和多进程读取数千个大型csv文件时遇到的内存溢出问题。我们将探讨两种核心策略:一是利用xgboost的外部内存dmatrix功能,避免一次性加载全部数据进行模型训练;二是通过优化pandas的并行读取流程,包括合理选择线程池而非进程池,并避免在循环中频繁拼接dataframe,从而提高效率并减少内存消耗。
1. 大规模CSV文件读取的内存挑战
在处理海量数据集时,例如将数千个CSV文件合并成一个大型DataFrame以供机器学习模型训练,内存溢出是一个常见且棘手的问题。尤其当数据集规模达到数十GB甚至更大时,即使拥有数十GB内存的计算实例也可能难以应对。传统的做法是使用pandas.read_csv结合Python的multiprocessing模块并行读取文件,然后通过pd.concat将结果合并。然而,这种方法在以下两个方面容易导致内存瓶颈:
- 进程间数据拷贝与开销: ProcessPoolExecutor会为每个任务创建独立的进程,每个进程拥有自己的内存空间。当每个进程读取一个大型CSV文件并返回一个DataFrame时,这些DataFrame需要被序列化并在主进程中反序列化,这会产生显著的内存和CPU开销。
- pd.concat的低效使用: 在循环中频繁地使用pd.concat将新读取的DataFrame与现有DataFrame进行拼接,会导致大量的中间DataFrame对象生成和数据拷贝。每次拼接都可能需要重新分配内存来容纳更大的DataFrame,这不仅效率低下,更是内存消耗的黑洞。
2. 针对XGBoost的外部内存解决方案
如果最终目标是将处理后的数据用于XGBoost模型训练,那么最直接且高效的解决方案是利用XGBoost自身提供的外部内存(External Memory)功能。XGBoost从1.5版本开始支持自定义迭代器,允许用户以分块(chunk)的方式加载数据进行训练,从而避免将整个数据集一次性载入内存。
这种方法的核心是使用XGBoost.DMatrix,并配置其外部内存特性。这意味着您不需要预先将所有CSV文件合并成一个巨大的Pandas DataFrame。相反,您可以创建一个数据迭代器,XGBoost在训练过程中会按需从该迭代器中获取数据块。这对于处理远超机器物理内存限制的数据集尤为关键。
核心优势:
- 内存效率高: 避免一次性加载全部数据,显著降低内存需求。
- 扩展性强: 能够处理任意大小的数据集,只要存储空间足够。
- 训练与预测均适用: 外部内存功能不仅可用于训练,也可用于预测和评估。
使用示例(概念性):
虽然具体实现需要根据XGBoost的官方文档构建自定义数据迭代器,但其基本思想是提供一个可迭代对象,每次迭代返回一个数据块。
美图云修
商业级AI影像处理工具
50
查看详情
import xgboost as xgb
import pandas as pd
from typing import List
# 假设您有一个自定义的迭代器类,用于分块读取CSV文件
class CSVBatchIterator(xgb.DataIter):
def __init__(self, file_paths: List[str], batch_size: int):
super().__init__()
self.file_paths = file_paths
self.batch_size = batch_size
self.it = iter(self._read_chunks())
self.data = None
self.labels = None
def _read_chunks(self):
# 这是一个简化示例,实际可能需要更复杂的逻辑来处理跨文件分块
for path in self.fi
le_paths:
df = pd.read_csv(path)
# 假设最后一列是标签,其余是特征
features = df.iloc[:, :-1]
labels = df.iloc[:, -1]
# 进一步将单个文件的DataFrame分块
for i in range(0, len(features), self.batch_size):
yield features.iloc[i:i+self.batch_size], labels.iloc[i:i+self.batch_size]
def next(self, input_data):
try:
features, labels = next(self.it)
self.data = features
self.labels = labels
input_data(data=self.data, label=self.labels)
return 1 # Return 1 for successful iteration
except StopIteration:
return 0 # Return 0 for end of iteration
# 示例使用
# file_paths = ["path/to/file1.csv", "path/to/file2.csv", ...]
# batch_iterator = CSVBatchIterator(file_paths, batch_size=100000)
# dtrain = xgb.DMatrix(batch_iterator)
#
# # 训练模型
# # params = {'objective': 'binary:logistic', 'eval_metric': 'logloss'}
# # bst = xgb.train(params, dtrain)注意事项: 实际的外部内存DMatrix实现会比上述示例更复杂,需要仔细遵循XGBoost官方文档中关于自定义数据迭代器的指导。核心思想是避免在Python层面将所有数据加载到内存,而是让XGBoost在底层直接处理数据流。
3. 优化Pandas并行读取策略
如果您的场景不直接使用XGBoost的外部内存功能,或者需要先将数据整合为Pandas DataFrame进行其他预处理,那么优化Pandas的并行读取策略是关键。
3.1 线程池与进程池的选择
对于文件I/O密集型操作(如pd.read_csv),concurrent.futures.ThreadPoolExecutor通常是比ProcessPoolExecutor更优的选择。
- I/O密集型任务: 文件读取操作大部分时间都在等待磁盘或网络I/O,而不是CPU计算。在这种情况下,使用多线程可以有效利用I/O等待时间,一个线程在等待时,其他线程可以继续读取文件。
- 内存共享与开销: 线程共享同一进程的内存空间,避免了进程间昂贵的数据序列化和反序列化开销,以及每个进程独立的内存副本。这显著降低了内存使用量和上下文切换的成本。
- GIL的影响: 尽管Python的全局解释器锁(GIL)限制了多线程在CPU密集型任务中的并行性,但对于I/O密集型任务,当线程执行I/O操作时,GIL会被释放,允许其他线程运行。
3.2 避免循环内频繁拼接DataFrame
如前所述,在循环中反复使用pd.concat是导致内存和性能问题的主要原因之一。正确的做法是收集所有子DataFrame到一个列表中,然后在所有读取任务完成后,执行一次性的大规模拼接。
优化后的代码示例:
import pandas as pd
import multiprocessing as mp
from concurrent.futures import ThreadPoolExecutor, wait, FIRST_EXCEPTION
from typing import List
import logging
logger = logging.getLogger(__name__)
def _read_training_data(training_data_path: str) -> pd.DataFrame:
"""
单个CSV文件读取函数。
"""
df = pd.read_csv(training_data_path)
return df
def read_training_data_optimized(
paths: List[str]
) -> pd.DataFrame:
"""
优化后的并行读取训练数据函数。以上就是优化大规模CSV文件读取:解决Pandas与XGBoost内存问题的策略的详细内容,更多请关注其它相关文章!
# 数十
# 网络营销seo网站推广
# 铁观音营销推广策划案
# 商丘网站建设文章
# 什么是seo网站效果
# 惠州手机网站建设费用
# 行业网站建设解读
# 酒店口碑营销推广案例
# 营销活动为什么会有推广费
# 上海SEO优化设计软件
# 区教研室网站建设
# 转换为
# 数千
# python
# 更大
# 序列化
# 加载
# 多线程
# 美图
# 自定义
# 迭代
# 可迭代对象
# csv文件
# ai
# csv
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
QQ邮箱网页版入口 QQ邮箱官方邮箱登录通道
菜鸟取件码是什么怎么查 最全查询渠道汇总
Composer的 archive 命令怎么用_快速打包你的PHP项目及其Composer依赖
QQ邮箱官方网页版登录 QQ邮箱个人邮箱快速访问
如何使用spryker/configurable-bundles-products-resource-relationship模块解决复杂产品捆绑关系难题
Yandex官方入口网址 Yandex俄罗斯搜索引擎最新在线地址
最新韩小圈网页版登录入口_官网在线观看官方链接
Gmail邮箱申请注册直达_Gmail邮箱免费注册PC版官网入口2025
一加Ace 6T实拍样张首次公布!李杰:主摄实力完全看齐4K档性能旗舰
192.168.1.1管理中心入口 192.168.1.1路由器网页设置平台
Selenium Python中处理点击后新窗口加载冻结问题的策略与实践
在WordPress中通过REST API获取BasicAuth保护的远程文章
php源码怎么在电脑上测试_电脑测试php源码方法步骤【教程】
sublime怎么覆盖插件的默认快捷键_sublime快捷键优先级与设置
Win11怎么设置开机NumLock亮 Win11修改注册表InitialKeyboardIndicators值
三星GalaxyZFold5怎样在相册制作折叠屏分镜_iPhone三星GalaxyZFold5相册制作折叠屏分镜【创意编辑】
《GTA6》开发画面疑似泄露!这次可不是AI了
支付宝如何管理隐私设置_支付宝隐私保护的配置技巧
邮政快递单号查询入口 邮政快递物流信息在线查询入口
动漫岛观看全网网 动漫岛在线正版动漫入口
AO3官方在线访问地址 Archive of Our Own最新镜像合集
蛙漫漫画官网在线入口 蛙漫全本漫画免费阅读平台
钉钉视频会议画面卡顿如何解决 钉钉会议画面优化方法
Django AJAX 文件上传教程:解决图片无法保存到模型的常见问题
c++中的std::launder有什么实际用途_c++对象生命周期与指针优化
C++20的source_location是什么_C++在编译期获取源码位置信息用于日志和断言
Win11怎么关闭快速启动_Win11彻底关机设置教程
印象笔记怎样用批量导出备知识库_印象笔记用批量导出备知识库【备份方法】
Golang如何使用const iota_Go iota常量计数器讲解
使用CSS更改登录屏幕输入框中PNG图标颜色的策略与局限性
在Socket.IO连接中实现Access Token自动更新与动态重连
文心一言怎样用批量生成做多版文案_文心一言用批量生成做多版文案【批量创作】
iwriter统一登录平台 iwrite账号密码登录页面
2026年CSGO开箱网站推荐 CSGO开箱平台精选
优酷会员付费后没到账怎么办_优酷会员充值异常及解决方法
C++如何解决segmentation fault_C++段错误调试与原因分析
漫蛙漫画网页端入口 漫蛙2官方正版漫画站点
蛙漫画网页版全站入口 蛙漫热门作品免费浏览
怎样使用“本地安全策略”提升Windows安全性_Secpol.msc配置指南【高手】
必由学在线入口 必由学网页版快速登录入口
Linux如何排查内存不足OOME问题_LinuxOOM分析教程
抓大鹅解压小游戏 抓大鹅摸鱼解压入口
大麦的“候补”是什么意思 大麦候补购票规则【详解】
如何在J*a中实现统一对象行为接口_项目大型化时的接口规范化
微信怎么把收藏的内容分类管理 微信收藏内容标签分类方法
QQ邮箱官方邮箱登录入口 QQ邮箱网页版快速访问
如何高效处理PHP中的Excel数据导入导出?PortPHP/Spreadsheet助你轻松搞定!
mysql如何设置表访问权限_mysql表访问权限配置
抖音创作助手登录入口_抖音创作辅助工具官网直达
动漫花园资源网使用步骤_动漫花园资源网下载流程


2025-11-26
浏览次数:次
返回列表
le_paths:
df = pd.read_csv(path)
# 假设最后一列是标签,其余是特征
features = df.iloc[:, :-1]
labels = df.iloc[:, -1]
# 进一步将单个文件的DataFrame分块
for i in range(0, len(features), self.batch_size):
yield features.iloc[i:i+self.batch_size], labels.iloc[i:i+self.batch_size]
def next(self, input_data):
try:
features, labels = next(self.it)
self.data = features
self.labels = labels
input_data(data=self.data, label=self.labels)
return 1 # Return 1 for successful iteration
except StopIteration:
return 0 # Return 0 for end of iteration
# 示例使用
# file_paths = ["path/to/file1.csv", "path/to/file2.csv", ...]
# batch_iterator = CSVBatchIterator(file_paths, batch_size=100000)
# dtrain = xgb.DMatrix(batch_iterator)
#
# # 训练模型
# # params = {'objective': 'binary:logistic', 'eval_metric': 'logloss'}
# # bst = xgb.train(params, dtrain)