Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ RLA.egg-info**
**/.ipynb_checkpoints/*
**/.DS_Store
test/target_data_root/*
**/private_config.py
20 changes: 12 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Currently, we store the data items in standard file systems and manage the relat
- The directory "code" is a backup of code for experiment reproducibility.
- The directory "checkpoint" save weights of neural networks.
- We have a table named "demo_task", which is the root directory of log/archive_tester/checkpoint/code/results.
- The "index" of experiments in named in the formulation of `${%Y}/${%m}/${%d}/${%H-%M-%S-%f} ${ip address} ${tracked hyper-parameters}`.
- The "index" of experiments in named in the formulation of `${%Y}/${%m}/${%d}/${%H-%M-%S-%f}_${ip address}_${tracked hyper-parameters}`.


### Tools to Manage the Database
Expand Down Expand Up @@ -226,21 +226,24 @@ In practice, we might conduct our experiments in multiple physical machines for
```
SEND_LOG_FILE: True
REMOTE_SETTING:
ftp_server: ''
username: ''
password: ''
remote_data_root: ''
ftp_server: '114.114.114.114'
username: 'agent'
password: '123'
remote_data_root: 'remote_project/data_root/'
file_transfer_protocol: 'sftp'
```
where we set `SEND_LOG_FILE` to True and `ftp_server`, `username` and `password` are the ip address, username and passward of the master node. `remote_data_root` define the data_root of the database in the main node. For the main node, just keep `SEND_LOG_FILE` to False. In our experiment code, we should call the function `RLA.easy_log.tester.exp_manager.sync_log_file` periodically, then the data items we be sent to the `remote_data_root` of the main node. For example,
where `SEND_LOG_FILE` is set to True, `ftp_server`, `username` and `password` are the ip address, username and passward of the master node respectively, and `file_transfer_protocol` is the protocol to send data. `remote_data_root` defines the data_root of the database in the main node.
For the main node, configure the exp_manger by `exp_manager.configure(..., is_master_node=True)`.
In our experiment code, we should call the function `RLA.easy_log.tester.exp_manager.sync_log_file` periodically, for example,
```
for i in range(1000):
# your trianing code.
exp_manager.sync_log_file()
```
Since `SEND_LOG_FILE` is set to False in the main node, the `exp_manager.sync_log_file()` will be skipped in the main node.
then the data items we be sent to the `remote_data_root` of the main node. Since `SEND_LOG_FILE` is set to False in the main node, the `exp_manager.sync_log_file()` will be skipped in the main node.

PS:
1. You might meet "socket.error: [Errno 111] Connection refused" problem in this process. The solution can be found [here](https://stackoverflow.com/questions/16428401/unable-to-use-ip-address-with-ftplib-python).
1. You might meet "socket.error: [Errno 111] Connection refused" problem in this process. The solution can be found [here](https://stackoverflow.com/a/70784201/6055868).

2. An alternative way is building your own NFS for your physical machines and locate data_root to the NFS.

Expand All @@ -251,3 +254,4 @@ PS:
- [ ] add comments and documents to the functions.
- [ ] add an auto integration script.
- [ ] download / upload experiment logs through timestamp.
- [ ] add a document to the plot function.
17 changes: 14 additions & 3 deletions RLA/auto_ftp.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,20 @@
import shutil
import os
import traceback
from RLA.const import *
from RLA.easy_log import logger

import pysftp


def ftp_factory(name, server, username, password, ignore=None):
if name == FTP_PROTOCOL_NAME.FTP:
return FTPHandler(ftp_server=server, username=username,password=password, ignore=ignore)
elif name == FTP_PROTOCOL_NAME.SFTP:
return SFTPHandler(sftp_server=server, username=username, password=password, ignore=ignore)
else:
raise NotImplementedError

class FTPHandler(object):

def __init__(self, ftp_server, username, password, ignore=None):
Expand Down Expand Up @@ -193,17 +203,18 @@ def upload_file(self, remote_dir, local_dir, local_file):
raise expection
logger.warn('create dir succeed {}'.format(remote_dir))
self.sftp.cwd(remote_dir)
self.sftp.put(local_dir + local_file)
self.sftp.put(os.path.join(local_dir, local_file))
self.close()

def download_file(self, remote_file, local_file):
self.sftp = self.sftpconnect()
logger.info("try download {}".format(local_file))
if not os.path.isfile(local_file):
logger.info("new file {}".format(local_file))
self.sftp.get(remote_file)
self.sftp.get(remote_file, local_file)
elif self.sftp.stat(remote_file).st_size != os.path.getsize(local_file):
logger.info("update file {}".format(local_file))
self.sftp.get(remote_file)
self.sftp.get(remote_file, local_file)
else:
logger.info("skip download file {}".format(remote_file))

Expand Down
6 changes: 5 additions & 1 deletion RLA/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@

class FRAMEWORK:
tensorflow = 'tensorflow'
torch = 'torch'
torch = 'torch'

class FTP_PROTOCOL_NAME:
FTP = 'ftp'
SFTP = 'sftp'
30 changes: 29 additions & 1 deletion RLA/easy_log/complex_data_recorder.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import matplotlib.pyplot as plt
from RLA.easy_log.tester import exp_manager
from RLA.easy_log.time_step import time_step_holder
from typing import Callable
# video recorder


Expand All @@ -27,8 +28,35 @@ def save(cls, name=None, fig=None, cover=False, add_timestamp=True, **kwargs):
plt.savefig(save_path, **kwargs)

@classmethod
def pretty_plot_wrapper(cls, name, plot_func, cover=False, legend_outside=False, xlabel='', ylabel='', title='',
def pretty_plot_wrapper(cls, name:str, plot_func:Callable,
cover=False, legend_outside=False, xlabel='', ylabel='', title='',
add_timestamp=True, *args, **kwargs):
"""
Save the customized plot figure to the RLA database.

:param name: file name to save.
:type name: str
:param plot_func: the function to plot figures
:type plot_func: function
:param cover: if you would like to cover the original figure with the same name, you can set cover to True
:type cover: bool
:param legend_outside: let legend be outside of the figure.
:type legend_outside: bool
:param xlabel: name of xlabel
:type xlabel: str
:param ylabel: name of xlabel
:type ylabel: str
:param title: title of the plotted figure
:type title: str
:param add_timestamp: add the timestamp (recorded by the timestep holder) to the name.
:type add_timestamp: str
:param args: other parameters to plt.savefig
:type args:
:param kwargs: other parameters to plt.savefig
:type kwargs:
:return:
:rtype:
"""
plt.cla()
plot_func()
lgd = plt.legend(prop={'size': 15}, loc=2 if legend_outside else None,
Expand Down
Loading