@可视化工具wandb & tensorboard在使用远程服务器时的离线同步
wandb和tensorboard是两个机器学习项目进行可视化的重要工具。但在进行机器学习训练时,我们接入的远程服务器集群因为安全等原因只能通过局域网接入,而无法连接到互联网。这导致服务器无法直接通过使用tensorboard或者wandb等可视化工具进行实时数据上传和可视化。我们分别针对两种工具讨论解决方法:
Tensorboard
对于tensorboard,我们可以通过端口映射将数据映射到本地进行查看。
步骤
- 源代码 :确定加载训练数据的文件夹
- 运行源代码:训练数据log将根据路径保存
- 远程服务器terminal运行tensorboard服务器:在本地terminal中连接远程服务器,并输入 tensorboard --logdir $logdir(log的目录) --port=Remote_port 链接到本地端口
- 本地terminal运行ssh服务并进行端口映射:ssh -L $Local_port:127.0.0.1: $Remote_port $Remote_user@ $Remote_ip -p $Remote_port
注意:这里需要输入远程服务器的password进行登录,但如果采用sshpass工具可以进行自动登录。具体可查阅sshpass相关用法 - 本地主机:打开地址 http://127.0.0.1:6006/ 即可获得在线更新的tensorboard数据
参考网址:链接: https://zhuanlan.zhihu.com/p/687904515.
缺点
对于远程服务器具有多个计算节点的情形,每运行一次代码每次都需要确定在哪个计算节点上进行运行,以进行端口的映射。
Wandb
我们可以通过Wandb离线模式解决以上困难。编写一个脚本通过拉取远程服务器上的文件,和文件变化列表来进行可视化数据的上传。
步骤
- 代码:确定加载训练数据的文件夹,并设置Wandb offline 模式
- 同步python代码fetch_file.py:根据本地和remote服务器的部署路径,维护一个列表,包含当前需要同步的数据路径和最新修改时间
wandb生成的同步目录均以‘offline-run’开头,找到所有需要离线目录的目录路径
def get_all_offline_run_directories(path):
offline_run_dirs = []
for root, dirs, files in os.walk(path):
for dir_name in dirs:
if dir_name.startswith('offline-run'):
offline_run_dirs.append(os.path.join(root, dir_name))
return offline_run_dirs
返回目录最新修改时间
def get_modification_time(path):
return os.path.getmtime(path)
定义目录修改时间保存格式
def format_time(epoch_time):
return datetime.fromtimestamp(epoch_time).strftime('%Y-%m-%d %H:%M:%S')
def parse_time(time_str):
return datetime.strptime(time_str, '%Y-%m-%d %H:%M:%S')
读取存储同步路径和最新修改时间的列表
def read_csv(file_path):
dirs_with_mtime = []
with open(file_path, 'r') as file:
reader = csv.reader(file)
next(reader) # Skip header
for row in reader:
dirs_with_mtime.append((row[0], datetime.strptime(row[1], '%Y-%m-%d %H:%M:%S')))
return dirs_with_mtime
if __name__ == '__main__':
remote_path = $Remote_path/results #远程结果目录
local_path = $Local_path/results #本地映射的结果目录
last_file = remote_path + "last_file.csv" #上次同步的结果目录
sync_file = remote_path + "sync_file.txt" #本次需要同步的目录
offline_run_directories = get_all_offline_run_directories(remote_path)
new_dirs = [(directory, format_time(get_modification_time(directory))) for directory in
offline_run_directories]
if not os.path.exists(last_file):
# 如果CSV文件不存在,则将当前目录及其修改时间保存到CSV文件
with open(last_file, 'w', newline='') as file:
writer = csv.writer(file)
writer.writerow(['Directory', 'Last Modified'])
for directory, mtime in new_dirs:
writer.writerow([directory, mtime])
print(f"Directory and modification times saved to {last_file}")
else:
# 读取之前保存的CSV文件
old_dirs = read_csv(last_file)
last_dirs = {dir: mtime for dir, mtime in old_dirs}
dirs_to_sync = []
for directory, mtime in new_dirs:
mtime = parse_time(mtime)
if directory not in last_dirs.keys() or last_dirs[directory] != mtime:
directory = directory.replace(remote_path, local_path)
dirs_to_sync.append(directory)
if dirs_to_sync:
with open(sync_file, 'w') as file:
for dir in dirs_to_sync:
file.write(dir + '\n')
print(f'路径列表已保存到 {dirs_to_sync}')
with open(last_file, 'w', newline='') as file:
writer = csv.writer(file)
writer.writerow(['Directory', 'Last Modified'])
for directory, mtime in new_dirs:
writer.writerow([directory, mtime])
print(f"CSV 文件已更新 {last_file}")
- 本地wandb login:terminal输入wandb login,复制粘贴自己的api编号登录
- 本地自动拉取脚本sync_wandb.sh:
#!/bin/bash
# 定义远程服务器信息
REMOTE_USER= $Remote_user
REMOTE_HOST= $Remote_ip
REMOTE_DIR= "$Remote_path/results"
LOCAL_DIR= "$Local_path/results"
INTERVAL=120 # 同步拉取时间间隔:2分钟
SYNC_FILE="${LOCAL_DIR}sync_file.txt"
FETCH_SCRIPT="${REMOTE_DIR}fetch_file.py"
SSH_PASSWORD= $Remote_password
# 捕捉中断信号
trap "echo 'Script interrupted. Exiting...'; exit" SIGINT SIGTERM
# 无限循环
while true; do
# 运行远程脚本
sshpass -p $SSH_PASSWORD ssh ${REMOTE_USER}@${REMOTE_HOST} "python3 $FETCH_SCRIPT"
sshpass -p "$SSH_PASSWORD" rsync -avzhe "ssh" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/" "$LOCAL_DIR/"
# 检查 sync_file.txt 是否存在
if [ -f "$SYNC_FILE" ]; then
echo "读取 sync_file.txt 中的路径并处理"
while IFS= read -r dir; do
echo "处理目录: $dir"
# 在这里添加你需要对每个目录执行的 wandb 操作
# 假设是使用 wandb 命令同步目录
wandb sync "$dir"
done < "$SYNC_FILE"
# 删除 sync_file.txt
rm "$SYNC_FILE"
echo "文件 $SYNC_FILE 已删除"
else
echo "文件 $SYNC_FILE 不存在"
fi
# 等待两分钟
sleep $Interval
done
- 给予可执行权限:chmod +x sync_wandb.sh
- 运行同步脚本:./sync_wandb.sh
步 - 退出:ctrl + c
以上在macos中进行测试,windows中的命令行用法会稍有不同。