"...overview/git@developer.sourcefind.cn:OpenDAS/nni.git" did not exist on "b40e3db7eae576b59d5822a3a6a3e3fc57f58a23"
Unverified Commit 3beaa3fd authored by Yan Ni's avatar Yan Ni Committed by GitHub
Browse files

export trial status to csv (#905)

* export to csv core code done

* add nnictl trail export

* fix bug

* add dependency for pandas

* remove pandas from dependency

* add multi phase support

* add document
parent c4ed2a35
...@@ -298,6 +298,22 @@ nnictl support commands: ...@@ -298,6 +298,22 @@ nnictl support commands:
nnictl trial [trial_id] --vexperiment [experiment_id] nnictl trial [trial_id] --vexperiment [experiment_id]
``` ```
* __nnictl trial export__
* Description
You can use this command to export reward & hyper-parameter of trial jobs to a csv file.
* Usage
```bash
nnictl trial export [OPTIONS]
```
* Options
|Name, shorthand|Required|Default|Description|
|------|------|------ |------|
|id| False| |ID of the experiment |
|--file| True| |File path of the output csv file |
<a name="top"></a> <a name="top"></a>
![](https://placehold.it/15/1589F0/000000?text=+) `nnictl top` ![](https://placehold.it/15/1589F0/000000?text=+) `nnictl top`
......
...@@ -50,6 +50,7 @@ setup( ...@@ -50,6 +50,7 @@ setup(
'hyperopt', 'hyperopt',
'json_tricks', 'json_tricks',
'numpy', 'numpy',
'pandas',
'psutil', 'psutil',
'pyyaml', 'pyyaml',
'requests', 'requests',
......
...@@ -101,6 +101,10 @@ def parse_args(): ...@@ -101,6 +101,10 @@ def parse_args():
parser_trial_kill.add_argument('id', nargs='?', help='id of the trial to be killed') parser_trial_kill.add_argument('id', nargs='?', help='id of the trial to be killed')
parser_trial_kill.add_argument('--experiment', '-E', required=True, dest='experiment', help='experiment id of the trial') parser_trial_kill.add_argument('--experiment', '-E', required=True, dest='experiment', help='experiment id of the trial')
parser_trial_kill.set_defaults(func=trial_kill) parser_trial_kill.set_defaults(func=trial_kill)
parser_trial_export = parser_trial_subparsers.add_parser('export', help='export trial job results to csv')
parser_trial_export.add_argument('id', nargs='?', help='the id of experiment')
parser_trial_export.add_argument('--file', '-f', required=True, dest='csv_path', help='target csv file path')
parser_trial_export.set_defaults(func=export_trials_data)
#parse experiment command #parse experiment command
parser_experiment = subparsers.add_parser('experiment', help='get experiment information') parser_experiment = subparsers.add_parser('experiment', help='get experiment information')
......
...@@ -18,11 +18,13 @@ ...@@ -18,11 +18,13 @@
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import csv
import os import os
import psutil import psutil
import json import json
import datetime import datetime
import time import time
from subprocess import call, check_output from subprocess import call, check_output
from .rest_utils import rest_get, rest_delete, check_rest_server_quick, check_response from .rest_utils import rest_get, rest_delete, check_rest_server_quick, check_response
from .config_utils import Config, Experiments from .config_utils import Config, Experiments
...@@ -468,3 +470,50 @@ def monitor_experiment(args): ...@@ -468,3 +470,50 @@ def monitor_experiment(args):
except Exception as exception: except Exception as exception:
print_error(exception) print_error(exception)
exit(1) exit(1)
def parse_trial_data(content):
"""output: List[Dict]"""
trial_records = []
for trial_data in content:
for phase_i in range(len(trial_data['hyperParameters'])):
hparam = json.loads(trial_data['hyperParameters'][phase_i])['parameters']
if 'finalMetricData' in trial_data.keys() and phase_i < len(trial_data['finalMetricData']):
reward = json.loads(trial_data['finalMetricData'][phase_i]['data'])
if isinstance(reward, (float, int)):
dict_tmp = {**hparam, **{'reward': reward}}
elif isinstance(reward, dict):
dict_tmp = {**hparam, **reward}
else:
raise ValueError("Invalid finalMetricsData format: {}/{}".format(type(reward), reward))
else:
dict_tmp = hparam
trial_records.append(dict_tmp)
return trial_records
def export_trials_data(args):
"""export experiment metadata to csv
:param: csv file path to export
"""
nni_config = Config(get_config_filename(args))
rest_port = nni_config.get_config('restServerPort')
rest_pid = nni_config.get_config('restServerPid')
if not detect_process(rest_pid):
print_error('Experiment is not running...')
return
running, response = check_rest_server_quick(rest_port)
if running:
response = rest_get(trial_jobs_url(rest_port), 20)
if response is not None and check_response(response):
content = json.loads(response.text)
# dframe = pd.DataFrame.from_records([parse_trial_data(t_data) for t_data in content])
# dframe.to_csv(args.csv_path, sep='\t')
records = parse_trial_data(content)
with open(args.csv_path, 'w') as f_csv:
writer = csv.DictWriter(f_csv, set.union(*[set(r.keys()) for r in records]))
writer.writeheader()
writer.writerows(records)
else:
print_error('Export failed...')
else:
print_error('Restful server is not Running')
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment