如何在IPython Notebook中循环执行命令行调用Python文件进行超参调优
在IPython Notebook中循环调优超参数并可视化结果
我之前做模型超参数调优时也碰到过一模一样的需求——在Notebook里批量跑training.py,还得收集结果画图。这里分享两种实用的方法,你可以根据自己的场景选:
方法1:用subprocess直接调用命令行脚本
这种方法不用改training.py的代码,直接在Notebook里循环执行命令行,适合不想动原脚本的情况。
步骤:
- 先确保你的
training.py会输出需要的指标(比如训练损失、验证准确率),最好让脚本在训练结束后打印出关键指标(比如最后一行输出Validation Loss: 0.23 Accuracy: 0.92),方便我们后续解析。 - 在Notebook里编写循环逻辑:
import subprocess import re import matplotlib.pyplot as plt # 定义要测试的dropout候选值 dropout_values = [0.4, 0.5, 0.6, 0.65, 0.7, 0.8] results = [] for dropout in dropout_values: print(f"正在运行dropout={dropout}的训练任务...") # 构造命令行命令 cmd = [ "python", "training.py", "--cuda", "--emsize", "1500", "--nhid", "1500", "--dropout", str(dropout), "--epochs", "10" ] # 执行命令并捕获输出 result = subprocess.run(cmd, capture_output=True, text=True) # 解析输出中的关键指标(这里假设脚本最后输出了类似"Validation Loss: X"的内容) output = result.stdout loss_match = re.search(r"Validation Loss: (\d+\.\d+)", output) acc_match = re.search(r"Accuracy: (\d+\.\d+)", output) if loss_match and acc_match: val_loss = float(loss_match.group(1)) accuracy = float(acc_match.group(1)) results.append({"dropout": dropout, "val_loss": val_loss, "accuracy": accuracy}) else: print(f"警告:dropout={dropout}的任务输出未找到预期指标") # 打印收集到的结果 print("所有任务执行完成,结果:") for res in results: print(res) # 可视化结果 plt.figure(figsize=(12, 5)) plt.subplot(121) plt.plot([r["dropout"] for r in results], [r["val_loss"] for r in results], marker='o', color='b') plt.xlabel("Dropout Value") plt.ylabel("Validation Loss") plt.title("Dropout vs Validation Loss") plt.subplot(122) plt.plot([r["dropout"] for r in results], [r["accuracy"] for r in results], marker='s', color='r') plt.xlabel("Dropout Value") plt.ylabel("Accuracy") plt.title("Dropout vs Accuracy") plt.tight_layout() plt.show()
方法2:重构training.py为可调用函数(更高效)
如果可以修改training.py,把训练逻辑封装成函数,这样不用每次启动新的Python进程,速度会快很多,而且参数传递更灵活。
步骤:
- 修改
training.py,把核心训练逻辑封装成函数,比如:
# training.py中新增函数 def train_model(emsize=1500, nhid=1500, dropout=0.65, epochs=10, cuda=True): # 原有的训练逻辑(数据加载、模型定义、训练循环等) # ... # 训练结束后返回关键指标 return val_loss, accuracy
- 在Notebook里直接导入这个函数,循环调用:
from training import train_model import matplotlib.pyplot as plt dropout_values = [0.4, 0.5, 0.6, 0.65, 0.7, 0.8] results = [] for dropout in dropout_values: print(f"正在训练dropout={dropout}...") val_loss, accuracy = train_model( emsize=1500, nhid=1500, dropout=dropout, epochs=10, cuda=True ) results.append({"dropout": dropout, "val_loss": val_loss, "accuracy": accuracy}) # 可视化(和方法1一样的代码) plt.figure(figsize=(12, 5)) plt.subplot(121) plt.plot([r["dropout"] for r in results], [r["val_loss"] for r in results], marker='o', color='b') plt.xlabel("Dropout Value") plt.ylabel("Validation Loss") plt.title("Dropout vs Validation Loss") plt.subplot(122) plt.plot([r["dropout"] for r in results], [r["accuracy"] for r in results], marker='s', color='r') plt.xlabel("Dropout Value") plt.ylabel("Accuracy") plt.title("Dropout vs Accuracy") plt.tight_layout() plt.show()
额外小技巧:
- 如果任务多,可以用
tqdm加个进度条,看着更直观:from tqdm.notebook import tqdm,然后把循环改成for dropout in tqdm(dropout_values): - 可以把结果保存成CSV文件,方便后续分析:
import pandas as pd; pd.DataFrame(results).to_csv("dropout_tuning_results.csv", index=False)
内容的提问来源于stack exchange,提问作者Shikha




