训练设备内存不足导致自动重启
训练设备内存不足导致自动重启
帮我看看如下代码,我的训练设备是8259u处理器,四核心八线程,8G内存,显卡是gtx1050,4g显存,训练过程中会自动关机重启,帮我判断一下原因,和代码怎么优化一下,代码是import pandas as pd import numpy as np import gc import lightgbm as lgb from sklearn.model_selection import TimeSeriesSplit from scipy.sparse import csr_matrix # 加载数据时指定类型节省内存 dtypes = { 'row_id': 'int64', 'timestamp': 'int64', 'user_id': 'int32', 'content_id': 'int16', 'content_type_id': 'int8', 'task_container_id': 'int16', 'user_answer': 'int8', 'answered_correctly': 'int8', 'prior_question_elapsed_time': 'float32', 'prior_question_had_explanation': 'boolean' } # 1. 分块读取数据,按需过滤 chunk_size = 100000 # 根据内存情况调整 chunks = pd.read_csv('train.csv', dtype=dtypes, chunksize=chunk_size) filtered_chunks = [] for chunk in chunks: # 过滤掉讲座事件(只保留问题) chunk = chunk[chunk['content_type_id'] == 0] chunk.drop(columns=['content_type_id'], inplace=True) # 删除不需要的列 filtered_chunks.append(chunk) train = pd.concat(filtered_chunks, ignore_index=True) # 2. 合并题目元数据 questions = pd.read_csv('questions.csv') train = train.merge(questions, left_on='content_id', right_on='question_id', how='left') # 3. 处理空值 train['prior_question_elapsed_time'] = train['prior_question_elapsed_time'].fillna( train['prior_question_elapsed_time'].median()) train['prior_question_had_explanation'] = train['prior_question_had_explanation'].fillna(False) # 4. 标签多热编码 tags_series = train['tags'].astype(str).str.split() unique_tags = set(tag for sublist in tags_series for tag in sublist) # 使用稀疏矩阵处理标签 row_indices = [] col_indices = [] for i, tags in enumerate(tags_series): for tag in tags: col_idx = list(unique_tags).index(tag) row_indices.append(i) col_indices.append(col_idx) tags_sparse = csr_matrix(([1] * len(row_indices), (row_indices, col_indices))) # 将稀疏矩阵转换为DataFrame(可选) tags_df = pd.DataFrame.sparse.from_spmatrix(tags_sparse, columns=unique_tags) train = pd.concat([train, tags_df], axis=1) # 5. 用户累计正确率 user_correct = train.groupby('user_id')['answered_correctly'].agg(['mean', 'count']) user_correct.columns = ['user_hist_correct_rate', 'user_hist_question_count'] train = train.merge(user_correct, on='user_id', how='left') # 6. 用户最近20题正确率(滑动窗口) train['user_recent_20_correct'] = train.groupby('user_id')['answered_correctly'].transform( lambda x: x.rolling(20, min_periods=1).mean() ) # 7. 题目全局正确率 question_diff = train.groupby('question_id')['answered_correctly'].mean().reset_index() question_diff.columns = ['question_id', 'question_difficulty'] train = train.merge(question_diff, on='question_id', how='left') # 8. 题目在用户所属分组的难度(如TOEIC part) part_diff = train.groupby('part')['answered_correctly'].mean().reset_index() part_diff.columns = ['part', 'part_avg_correct'] train = train.merge(part_diff, on='part', how='left') # 9. 用户答题间隔时间变化率 train['time_diff_rate'] = train.groupby('user_id')['timestamp'].diff().fillna(0) / 1e3 # 转换为秒 # 10. 用户当前任务容器与上次的时间差 train['task_container_gap'] = train.groupby('user_id')['task_container_id'].diff().fillna(0) # 释放不再需要的中间变量以节省内存 del questions, tags_series, tags_sparse, tags_df gc.collect() # 11. 特征列选择 features = [ 'user_hist_correct_rate', 'user_hist_question_count', 'user_recent_20_correct', 'question_difficulty', 'part_avg_correct', 'prior_question_elapsed_time', 'prior_question_had_explanation', 'time_diff_rate', 'task_container_gap' ] + list(tags_df.columns) # 12. 时间序列交叉验证 tscv = TimeSeriesSplit(n_splits=5) X = train[features] y = train['answered_correctly'] # 13. 定义LightGBM模型训练 for fold, (train_idx, val_idx) in enumerate(tscv.split(X, y)): X_train, y_train = X.iloc[train_idx], y.iloc[train_idx] X_val, y_val = X.iloc[val_idx], y.iloc[val_idx] # 数据集转换 dtrain = lgb.Dataset(X_train, label=y_train) dval = lgb.Dataset(X_val, label=y_val) # 训练参数配置 params = { 'objective': 'binary', 'metric': 'auc', 'device': 'cpu', # 改为使用CPU,防止GPU显存不足 'num_leaves': 31, 'learning_rate': 0.05, 'feature_fraction': 0.8 } # 训练模型 model = lgb.train(params, dtrain, valid_sets=[dval], callbacks=[lgb.log_evaluation(100)]) # 保存模型 model.save_model(f'lgbm_fold{fold}.txt') # 释放内存 del dtrain, dval, model gc.collect() # 最终内存优化 float_cols = train.select_dtypes(include=['float64']).columns train[float_cols] = train[float_cols].astype('float32') int_cols = train.select_dtypes(include=['int64']).columns train[int_cols] = train[int_cols].astype('int32') # 删除标签列,减少内存占用 train.drop(columns=['tags'], inplace=True) gc.collect()
嗯,用户在使用LightGBM训练模型时遇到了训练过程中自动关机重启的问题。我需要先分析可能的原因,然后看看代码中有什么可以优化的地方。
首先,用户的硬件配置是i5-8259U处理器,四核八线程,8G内存,GTX1050显卡4G显存。自动关机重启通常和硬件问题有关,比如过热或者电源不足,但也可能是内存或显存不足导致系统崩溃。
代码里用户已经做了一些内存优化的措施,比如分块读取数据、使用稀疏矩阵处理标签、类型转换和及时释放内存。不过可能还存在问题。
首先看内存使用情况。用户只有8G内存,而训练数据可能很大。分块处理是好的,但合并后的数据可能仍然很大。用户在处理过程中生成了一些中间变量,比如合并后的train DataFrame,可能占用大量内存。特别是在生成稀疏矩阵转换为DataFrame后,如果unique_tags很多,tags_df可能会占用较多内存。虽然用了稀疏矩阵,但转换为DataFrame后是否依然保持稀疏需要确认。另外,用户可能在特征工程阶段增加了许多列,导致内存压力增大。
接下来看显存,用户用的是GTX1050 4G显存,但代码中设置的是device='cpu',所以应该是在用CPU训练,这时候显存可能不是问题。但如果之前可能尝试过使用GPU,而显存不足导致崩溃,不过现在代码里已经指定了CPU,所以可能问题不在显存。不过要确认用户是否确实运行的是修改后的代码,或者是否有其他地方的设置。
另一个可能的原因是CPU或内存过热,或者电源供应不足。如果CPU长时间高负荷运行,散热不好可能导致过热关机。但用户的问题发生在训练过程中,可能更可能是内存不足导致系统崩溃,因为当物理内存耗尽时,系统可能会使用交换空间,但如果交换空间也不足,可能导致OOM(Out Of Memory)错误,进而导致系统不稳定,甚至重启。
在代码中,虽然用户进行了分块读取,但最终将所有的filtered_chunks合并成一个train DataFrame,可能这个train占用了过多内存。例如,如果原始数据很大,合并后的train可能超过8G内存。特别是在特征工程部分,添加了多个新特征,进一步增加了内存占用。
另外,用户在处理标签的多热编码时,先创建了一个稀疏矩阵tags_sparse,然后将其转换为DataFrame,并合并到train中。这一步可能会占用较多内存,尤其是当标签数量较大时。虽然稀疏矩阵节省空间,但转换为DataFrame后是否保持稀疏格式?查看代码发现用了pd.DataFrame.sparse.from_spmatrix,这应该会保持稀疏格式,但可能某些操作导致内存占用增加。
用户还在循环中进行了交叉验证,每次迭代可能加载大量数据到内存。可能在训练过程中,尤其是创建LightGBM的数据集时,内存需求进一步增加,导致系统内存耗尽。
可能的优化方向包括:
1. 减少内存占用:进一步优化数据类型的转换,比如将更多的列转换为更小的数据类型。例如,检查是否有float32可以转换的列,或者int32转换为int16或int8。同时,及时删除中间变量,释放内存。
2. 使用更节省内存的特征工程方法:例如,用户累计正确率等特征是否可以在分块处理时逐步计算,而不是在整个数据集上操作,这样避免一次性加载全部数据。
3. 调整交叉验证的方式:时间序列交叉验证可能需要在每次拆分时保持数据的时间顺序,但如果数据量太大,可以考虑减少n_splits或者采用其他验证方法。
4. 使用更轻量级的模型或者降低模型复杂度:例如,减少num_leaves,增加feature_fraction,或者降低learning_rate以减少内存需求。
另外,用户可能没有监控系统资源的使用情况,建议在训练时监控内存和CPU温度,看是否在崩溃前内存使用达到极限,或者温度过高。
具体到代码优化:
- 检查train的数据量,是否可以考虑逐块处理特征,而不是一次性处理整个数据集。例如,用户累计正确率可以在分块处理时逐步计算,而不是最后在整个数据集上groupby。或者使用更高效的方法,如分块更新统计量。
- 在特征工程部分,例如用户滑动窗口的transform操作,可能会产生较大的临时内存占用。考虑使用更高效的方式计算,或者分块处理。
- 对于标签的多热编码,可能可以考虑在分块处理时逐步构建,而不是一次性处理整个数据集。例如,每个chunk处理时生成对应的稀疏矩阵块,逐步合并,避免一次性生成大的稀疏矩阵。
- 在交叉验证循环中,及时删除不再需要的变量,如X_train, y_train等,并手动调用gc.collect()。
- 调整LightGBM的参数,比如降低num_leaves,使用更小的max_bin,或者启用subsample来减少内存使用。
此外,用户可以考虑将数据转换为更节省内存的格式,例如使用parquet格式,或者使用dask等库进行分布式处理,但考虑到用户的硬件条件,可能不太现实。
最后,建议用户尝试减少数据量,比如先使用部分数据进行训练,看是否还会出现重启问题。如果小数据量下正常,则问题可能出在内存不足;如果仍然有问题,可能需要检查硬件问题。
根据你的硬件配置和代码情况,训练过程中自动关机重启的主要原因可能有以下两个方面:
一、硬件资源不足导致系统崩溃
内存不足(关键问题)
8G内存难以支撑全量数据处理:
python
复制
# 原始代码中的内存密集型操作: train = pd.concat(filtered_chunks) # 合并后数据可能超过4GB tags_df = pd.DataFrame.sparse.from_spmatrix(...) # 稀疏矩阵转换可能产生内存峰值 user_correct = train.groupby(...) # 全量数据分组计算CPU过热保护
四核处理器在全量数据+LightGBM计算时可能触发温度墙
显存误用风险
虽然设置了
device='cpu',但需确认实际运行中是否完全禁用GPU:python
复制
# 建议显式禁用GPU params = { 'device': 'cpu', 'force_row_wise': True # 强制行式计算模式 }二、代码优化方案(分步实施)
第一步:内存优化(关键)
python
复制
# 优化1:分块处理特征工程 user_stats = {} # 用户状态缓存字典 def process_chunk(chunk): # 用户累计统计(分块更新) for user_id, group in chunk.groupby('user_id'): if user_id in user_stats: prev = user_stats[user_id] new_correct = prev['total_correct'] + group['answered_correctly'].sum() new_count = prev['total_count'] + len(group) else: new_correct = group['answered_correctly'].sum() new_count = len(group) user_stats[user_id] = { 'total_correct': new_correct, 'total_count': new_count, 'last_20': deque(maxlen=20) } # 滑动窗口计算 chunk.loc[group.index, 'user_recent_20_correct'] = np.mean(list(user_stats[user_id]['last_20'])) user_stats[user_id]['last_20'].extend(group['answered_correctly'].values) return chunk # 优化2:增量式标签编码 unique_tags = set() for chunk in filtered_chunks: chunk_tags = chunk['tags'].astype(str).str.split() unique_tags.update(tag for sublist in chunk_tags for tag in sublist) # 优化3:类型压缩 dtype_rules = { 'float64': 'float16', 'int64': 'int16', 'int32': 'int8' } def optimize_dtypes(df): for col in df.columns: col_type = str(df[col].dtype) if col_type in dtype_rules: df[col] = df[col].astype(dtype_rules[col_type]) return df第二步:计算优化
python
复制
# 优化4:LightGBM参数调整 params = { 'objective': 'binary', 'metric': 'auc', 'device': 'cpu', 'num_leaves': 63, # 原31改为63保持容量 'learning_rate': 0.1, 'feature_fraction': 0.7, 'max_depth': 5, # 限制树深 'bin_construct_sample_cnt': 20000000, # 减少分箱内存 'verbose': -1 # 关闭冗余日志 } # 优化5:增量式验证 tscv = TimeSeriesSplit(n_splits=3) # 减少交叉验证次数第三步:系统级优化建议
硬件监控
bash
复制
# Linux系统安装监控工具 sudo apt-get install lm-sensors sensors # 查看CPU温度虚拟内存扩展
bash
复制
# Windows设置至少16GB页面文件 # 系统属性 -> 高级 -> 性能设置 -> 高级 -> 虚拟内存更改物理散热改善
使用笔记本散热底座
清灰并更换导热硅脂
三、完整优化代码示例
python
复制
# 新增内存监控装饰器 import psutil def memory_monitor(func): def wrapper(*args, **kwargs): process = psutil.Process() start_mem = process.memory_info().rss / 1024**2 result = func(*args, **kwargs) end_mem = process.memory_info().rss / 1024**2 print(f"Memory usage: {end_mem - start_mem:.2f} MB") return result return wrapper @memory_monitor def main_process(): # 分块处理主逻辑 user_stats = {} unique_tags = set() # 第一遍遍历:收集元信息 for chunk in pd.read_csv('train.csv', chunksize=50000): chunk = chunk[chunk['content_type_id'] == 0] chunk_tags = chunk['tags'].astype(str).str.split() unique_tags.update(tag for sublist in chunk_tags for tag in sublist) # 第二遍遍历:处理特征 for chunk in pd.read_csv('train.csv', chunksize=50000): chunk = process_chunk(chunk) chunk = optimize_dtypes(chunk) # 流式特征处理 yield chunk # 改为生成器模式 # 流式训练 train_generator = main_process() for fold_idx, (train_chunk, val_chunk) in enumerate(tscv.split(train_generator)): # 增量训练逻辑 model = lgb.train(params, init_model=model, ...) # 使用增量训练四、应急方案(如果仍需全量训练)
python
复制
# 启用内存交换(需SSD) import os os.environ['LIGHTGBM_USE_SWAP'] = 'true' # 允许LightGBM使用磁盘交换 # 强制垃圾回收 import gc gc.set_threshold(50, 10, 10) # 调整回收频率 # 使用低精度训练 params.update({ 'data_random_seed': 42, 'two_round': True, # 减少内存占用 'boost_from_average': False, 'num_threads': 4 # 限制CPU线程数 })建议按照以下顺序实施优化:
优先实施分块处理(process_chunk函数)
添加内存监控装饰器定位内存瓶颈
调整LightGBM参数限制资源使用
最后考虑启用磁盘交换
如果经过上述优化仍出现重启现象,建议优先考虑升级内存至16GB或改用云服务器训练。您的硬件配置(特别是8GB内存)在处理大规模机器学习任务时存在先天不足,这些优化只能缓解但不能根本解决资源瓶颈问题。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐

所有评论(0)