From 370feb7fab4ad91805bdbd7bf28421ce73298ff0 Mon Sep 17 00:00:00 2001 From: chicm-ms <38930155+chicm-ms@users.noreply.github.com> Date: Wed, 7 Nov 2018 15:43:24 +0800 Subject: [PATCH 1/8] Merge v0.3 into master (#337) * Fix pypi package missing python module * Fix pypi package missing python module * fix bug in smartparam example (#322) * Fix nnictl update trialnum and document (#326) 1.Fix restful server of update 2.Update nnictl document of update 3.Add tensorboard in docement * Update the version numbers from 0.3.2 to 0.3.3 --- README.md | 2 +- deployment/docker/Dockerfile | 4 ++-- deployment/pypi/Makefile | 15 ++++++++++----- deployment/pypi/setup.py | 5 +++-- docs/NNICTLDOC.md | 18 ++++++++++++++++++ examples/trials/mnist-smartparam/mnist.py | 1 + setup.py | 2 +- .../rest_server/restValidationSchemas.ts | 4 +++- src/sdk/pynni/nni/trial.py | 1 + 9 files changed, 40 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 53ad6b5537..1dd1b14c00 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Note: If you are in docker container (as root), please remove `--user` from the * We only support Linux (Ubuntu 16.04 or higher) in our current stage. * Run the following commands in an environment that has `python >= 3.5`, `git` and `wget`. ```bash - git clone -b v0.3.3 https://github.com/Microsoft/nni.git + git clone -b v0.3.3 https://github.com/Microsoft/nni.git cd nni source install.sh ``` diff --git a/deployment/docker/Dockerfile b/deployment/docker/Dockerfile index a14cb0ab37..b868f1c9fd 100644 --- a/deployment/docker/Dockerfile +++ b/deployment/docker/Dockerfile @@ -53,7 +53,7 @@ RUN python3 -m pip --no-cache-dir install \ # #Install NNI # -RUN python3 -m pip install --user nni +RUN python3 -m pip install nni # #Tensorflow 1.10.0 @@ -68,6 +68,6 @@ RUN python3 -m pip --no-cache-dir install Keras==2.1.6 #sklearn RUN python3 -m pip --no-cache-dir install scikit-learn -ENV PATH=/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/root/.local/bin:/usr/bin: +ENV PATH=/usr/local/nvidia/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/root/.local/bin:/usr/bin:/bin:/sbin WORKDIR /root \ No newline at end of file diff --git a/deployment/pypi/Makefile b/deployment/pypi/Makefile index 2e3cc8ba8b..a4b77b39aa 100644 --- a/deployment/pypi/Makefile +++ b/deployment/pypi/Makefile @@ -9,11 +9,16 @@ build: tar xf $(CWD)node-linux-x64.tar.xz -C node-linux-x64 --strip-components 1 cd $(CWD)../../src/nni_manager && yarn && yarn build cd $(CWD)../../src/webui && yarn && yarn build - rm -rf $(CWD)nni - cp -r $(CWD)../../src/nni_manager/dist $(CWD)nni - cp -r $(CWD)../../src/webui/build $(CWD)nni/static - cp $(CWD)../../src/nni_manager/package.json $(CWD)nni - cd $(CWD)nni && yarn --prod + rm -rf $(CWD)nni_pkg + cp -r $(CWD)../../src/nni_manager/dist $(CWD)nni_pkg + cp -r $(CWD)../../src/webui/build $(CWD)nni_pkg/static + cp $(CWD)../../src/nni_manager/package.json $(CWD)nni_pkg + cd $(CWD)nni_pkg && yarn --prod + rm -rf $(CWD)nnicmd + rm -rf $(CWD)nni_annotation + cp -r $(CWD)../../tools/nnicmd $(CWD)nnicmd + cp -r $(CWD)../../tools/nni_annotation $(CWD)nni_annotation + cp -r $(CWD)../../tools/trial_tool $(CWD)trial_tool cd $(CWD) && python3 setup.py bdist_wheel cd $(CWD)../../src/sdk/pynni && python3 setup.py bdist_wheel cp -r $(CWD)../../src/sdk/pynni/dist/*.whl $(CWD)dist diff --git a/deployment/pypi/setup.py b/deployment/pypi/setup.py index ddaa4ff0af..40cc12c75e 100644 --- a/deployment/pypi/setup.py +++ b/deployment/pypi/setup.py @@ -11,7 +11,7 @@ setuptools.setup( name = 'nni', - version = '0.3.2', + version = '0.3.3', author = 'Microsoft NNI team', author_email = 'nni@microsoft.com', description = 'Neural Network Intelligence package', @@ -32,7 +32,8 @@ 'pyyaml', 'psutil', 'requests', - 'astor' + 'astor', + 'pyhdfs' ], classifiers = [ 'Programming Language :: Python :: 3', diff --git a/docs/NNICTLDOC.md b/docs/NNICTLDOC.md index bbdbd3aac3..1c864ca515 100644 --- a/docs/NNICTLDOC.md +++ b/docs/NNICTLDOC.md @@ -15,6 +15,7 @@ nnictl experiment nnictl config nnictl log nnictl webui +nnictl tensorboard ``` ### Manage an experiment * __nnictl create__ @@ -122,6 +123,23 @@ nnictl webui | ------ | ------ | ------ |------ | | id| False| |ID of the experiment you want to set| | --value, -v| True| |the experiment duration will be NUMBER seconds. SUFFIX may be 's' for seconds (the default), 'm' for minutes, 'h' for hours or 'd' for days.| + + * __nnictl update trialnum__ + * Description + + You can use this command to update an experiment's maxtrialnum. + + * Usage + + nnictl update trialnum [OPTIONS] + + Options: + + | Name, shorthand | Required|Default | Description | + | ------ | ------ | ------ |------ | + | id| False| |ID of the experiment you want to set| + | --value, -v| True| |the new number of maxtrialnum you want to set| + * __nnictl trial__ diff --git a/examples/trials/mnist-smartparam/mnist.py b/examples/trials/mnist-smartparam/mnist.py index 2b90018b52..a3d8a98578 100644 --- a/examples/trials/mnist-smartparam/mnist.py +++ b/examples/trials/mnist-smartparam/mnist.py @@ -223,6 +223,7 @@ def generate_defualt_params(): if __name__ == '__main__': try: + nni.get_next_parameter() main(generate_defualt_params()) except Exception as exception: logger.exception(exception) diff --git a/setup.py b/setup.py index 8a09d581b6..7b8d429776 100644 --- a/setup.py +++ b/setup.py @@ -35,7 +35,7 @@ def run(self): setup( name = 'nni', - version = '0.3.2', + version = '0.3.3', author = 'Microsoft NNI Team', author_email = 'nni@microsoft.com', description = 'Neural Network Intelligence project', diff --git a/src/nni_manager/rest_server/restValidationSchemas.ts b/src/nni_manager/rest_server/restValidationSchemas.ts index f429c503ea..a95c81765c 100644 --- a/src/nni_manager/rest_server/restValidationSchemas.ts +++ b/src/nni_manager/rest_server/restValidationSchemas.ts @@ -94,7 +94,9 @@ export namespace ValidationSchemas { params: joi.object(STARTEXPERIMENT.body).required(), execDuration: joi.number().required(), startTime: joi.number(), - endTime: joi.number() + endTime: joi.number(), + logDir: joi.string(), + maxSequenceId: joi.number() } }; export const STARTTENSORBOARD = { diff --git a/src/sdk/pynni/nni/trial.py b/src/sdk/pynni/nni/trial.py index 35d0397795..14c64569c1 100644 --- a/src/sdk/pynni/nni/trial.py +++ b/src/sdk/pynni/nni/trial.py @@ -47,6 +47,7 @@ def get_next_parameter(): return _params['parameters'] def get_current_parameter(tag): + global _params if _params is None: return None return _params['parameters'][tag] From 8f7dfc88a658d4a99be2028f279b75169a3d9a30 Mon Sep 17 00:00:00 2001 From: Scarlett Li <39592018+scarlett2018@users.noreply.github.com> Date: Wed, 7 Nov 2018 15:55:08 +0800 Subject: [PATCH 2/8] Fix contributing doc problems (#335) broken link wrong step refine wording --- docs/CONTRIBUTING.md | 2 +- docs/SetupNNIDeveloperEnvironment.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 4d0f488082..9fc7ff3c96 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -28,7 +28,7 @@ When raising issues, please specify the following: Provide PRs with appropriate tags for bug fixes or enhancements to the source code. Do follow the correct naming conventions and code styles when you work on and do try to implement all code reviews along the way. -If you are looking for How to go about contributing and debugging the NNI source code, you can refer our [How to Contribute](./HowToContribute.md) file in the `docs` folder. +If you are looking for How to develop and debug the NNI source code, you can refer to [How to set up NNI developer environment doc](./SetupNNIDeveloperEnvironment.md) file in the `docs` folder. Similarly for [writing trials](./WriteYourTrial.md) or [starting experiments](StartExperiment.md). For everything else, refer [here](https://github.com/Microsoft/nni/tree/master/docs). diff --git a/docs/SetupNNIDeveloperEnvironment.md b/docs/SetupNNIDeveloperEnvironment.md index a9a9cb9d01..ea93ce60e2 100644 --- a/docs/SetupNNIDeveloperEnvironment.md +++ b/docs/SetupNNIDeveloperEnvironment.md @@ -47,7 +47,7 @@ And open WebUI to check if everything is OK **6. Redeploy** -After you change some code, just use **step 4** to rebuild your code, then the change will take effect immediately +After the code changes, use **step 3** to rebuild your codes, then the changes will take effect immediately. --- At last, wish you have a wonderful day. From a87517cf375334009c716babe1054c8ec7af8305 Mon Sep 17 00:00:00 2001 From: Lijiao <35484733+lvybriage@users.noreply.github.com> Date: Wed, 7 Nov 2018 16:03:13 +0800 Subject: [PATCH 3/8] Add download button (#332) --- src/webui/src/components/Overview.tsx | 32 +++++++++++++--- .../src/components/overview/BasicInfo.tsx | 2 +- .../src/components/overview/TrialProfile.tsx | 2 +- src/webui/src/index.css | 3 -- src/webui/src/static/img/icon/download.png | Bin 0 -> 376 bytes src/webui/src/static/style/logPath.scss | 1 - src/webui/src/static/style/overview.scss | 33 +++++++++++++++++ src/webui/src/static/style/progress.scss | 4 +- src/webui/src/static/style/table.scss | 2 + src/webui/src/static/style/tableStatus.css | 35 ------------------ 10 files changed, 66 insertions(+), 48 deletions(-) create mode 100644 src/webui/src/static/img/icon/download.png diff --git a/src/webui/src/components/Overview.tsx b/src/webui/src/components/Overview.tsx index 28584c1466..063fe00a7d 100644 --- a/src/webui/src/components/Overview.tsx +++ b/src/webui/src/components/Overview.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import axios from 'axios'; -import { Row, Col } from 'antd'; +import { Row, Col, Button } from 'antd'; import { MANAGER_IP } from '../static/const'; import { Experiment, TableObj, @@ -31,6 +31,7 @@ interface SessionState { bestAccuracy: string; accNodata: string; trialNumber: TrialNumber; + downBool: boolean; } class Overview extends React.Component<{}, SessionState> { @@ -81,7 +82,8 @@ class Overview extends React.Component<{}, SessionState> { runTrial: 0, unknowTrial: 0, totalCurrentTrial: 0 - } + }, + downBool: false }; } @@ -263,6 +265,9 @@ class Overview extends React.Component<{}, SessionState> { } downExperimentContent = () => { + this.setState(() => ({ + downBool: true + })); axios .all([ axios.get(`${MANAGER_IP}/experiment`), @@ -307,6 +312,9 @@ class Overview extends React.Component<{}, SessionState> { eventMouse.initEvent('click', false, false); downTag.dispatchEvent(eventMouse); } + this.setState(() => ({ + downBool: false + })); } })); } @@ -389,14 +397,28 @@ class Overview extends React.Component<{}, SessionState> { accNodata, status, trialNumber, - bestAccuracy + bestAccuracy, + downBool } = this.state; return (
{/* status and experiment block */} - - + + + + + + + diff --git a/src/webui/src/components/overview/BasicInfo.tsx b/src/webui/src/components/overview/BasicInfo.tsx index d1a500f978..8abef523c1 100644 --- a/src/webui/src/components/overview/BasicInfo.tsx +++ b/src/webui/src/components/overview/BasicInfo.tsx @@ -52,7 +52,7 @@ class BasicInfo extends React.Component {

LogPath

-
+
{trialProfile.logDir} diff --git a/src/webui/src/components/overview/TrialProfile.tsx b/src/webui/src/components/overview/TrialProfile.tsx index 8198aea3a6..3a429d62b6 100644 --- a/src/webui/src/components/overview/TrialProfile.tsx +++ b/src/webui/src/components/overview/TrialProfile.tsx @@ -23,7 +23,7 @@ class TrialInfo extends React.Component { clusterMetaData: tiralProInfo.clusterMetaData ? tiralProInfo.clusterMetaData : undefined }); return ( -
+
                     {JSON.stringify(showProInfo[0], null, 4)}
                 
diff --git a/src/webui/src/index.css b/src/webui/src/index.css index d3f609f92d..139ac33243 100644 --- a/src/webui/src/index.css +++ b/src/webui/src/index.css @@ -49,9 +49,6 @@ table { border-collapse: collapse; border-spacing: 0; } -pre{ - overflow: hidden; -} @font-face { font-family: 'Segoe'; src: url('./static/font/SegoePro-Regular.ttf'); diff --git a/src/webui/src/static/img/icon/download.png b/src/webui/src/static/img/icon/download.png new file mode 100644 index 0000000000000000000000000000000000000000..4182f1a70e10e087950b09321fba2d1add3b95f0 GIT binary patch literal 376 zcmeAS@N?(olHy`uVBq!ia0vp^l0dA^!3HFM&3wEMNO2Z;L>4nJ=qZCRW5rVYGLWhg z*NBqf{Irtt#G+IN$CUh}R0Yr6#Prml)Wnp^!jq{s3=E8{o-U3d6}R3@`^$SsLEz}d zkN=IDq(#&>EG}v3yWm?QT*_3)?7l+y!9_bC)h$l@g_Ni75y`0B&){C=qj{7mWTn}v z36-4Dib^U@5LCyd1?Yt#6xBF>#_wn3?LCb15&TFI%MHVX7tg zS44TW=*5qLA8O_QbWWK(Z^@N6Pfv(0`Ec{_cjetrSSIkEc=+5WQCwp_(~I5eW-olS zsu-&Nn6XIg>QOuW?uESU0;b12_bnNHYgQ&(dX{Z+jq< Date: Wed, 7 Nov 2018 20:08:04 +0800 Subject: [PATCH 4/8] Merge v0.3 to master (#339) * Fix pypi package missing python module * Fix pypi package missing python module * fix bug in smartparam example (#322) * Fix nnictl update trialnum and document (#326) 1.Fix restful server of update 2.Update nnictl document of update 3.Add tensorboard in docement * Update the version numbers from 0.3.2 to 0.3.3 * Update examples (#331) * update mnist-annotation * fix mnist-annotation typo * update mnist example * update mnist-smartparam * update mnist-annotation * update mnist-smartparam * change learning rate * update mnist assessor maxTrialNum * update examples * update examples * update maxTrialNum * fix breaking path in config_assessor.yml --- examples/trials/mnist-annotation/mnist.py | 19 ++++++++++--------- examples/trials/mnist-smartparam/mnist.py | 10 +++++----- examples/trials/mnist/config_assessor.yml | 6 +++--- examples/trials/mnist/mnist.py | 7 ++++--- examples/trials/mnist/search_space.json | 3 ++- 5 files changed, 24 insertions(+), 21 deletions(-) diff --git a/examples/trials/mnist-annotation/mnist.py b/examples/trials/mnist-annotation/mnist.py index 69ef283336..829c2fe65d 100644 --- a/examples/trials/mnist-annotation/mnist.py +++ b/examples/trials/mnist-annotation/mnist.py @@ -157,8 +157,8 @@ def main(params): ''' # Import data mnist = input_data.read_data_sets(params['data_dir'], one_hot=True) - print('Mnist download data down.') - logger.debug('Mnist download data down.') + print('Mnist download data done.') + logger.debug('Mnist download data done.') # Create the model # Build the graph for the deep net @@ -180,15 +180,15 @@ def main(params): test_acc = 0.0 with tf.Session() as sess: sess.run(tf.global_variables_initializer()) - """@nni.variable(nni.choice(50, 250, 500), name=batch_num)""" - batch_num = params['batch_num'] - for i in range(batch_num): - batch = mnist.train.next_batch(batch_num) - """@nni.variable(nni.choice(1, 5), name=dropout_rate)""" + """@nni.variable(nni.choice(1, 4, 8, 16, 32), name=batch_size)""" + batch_size = params['batch_size'] + for i in range(params['batch_num']): + batch = mnist.train.next_batch(batch_size) + """@nni.variable(nni.choice(0.5, 0.9), name=dropout_rate)""" dropout_rate = params['dropout_rate'] mnist_network.train_step.run(feed_dict={mnist_network.images: batch[0], mnist_network.labels: batch[1], - mnist_network.keep_prob: dropout_rate} + mnist_network.keep_prob: 1 - dropout_rate} ) if i % 100 == 0: @@ -224,7 +224,8 @@ def generate_defualt_params(): 'pool_size': 2, 'hidden_size': 1024, 'learning_rate': 1e-4, - 'batch_num': 200} + 'batch_num': 2000, + 'batch_size': 32} return params diff --git a/examples/trials/mnist-smartparam/mnist.py b/examples/trials/mnist-smartparam/mnist.py index a3d8a98578..28b9fb8b31 100644 --- a/examples/trials/mnist-smartparam/mnist.py +++ b/examples/trials/mnist-smartparam/mnist.py @@ -180,13 +180,13 @@ def main(params): test_acc = 0.0 with tf.Session() as sess: sess.run(tf.global_variables_initializer()) - batch_num = nni.choice(50, 250, 500, name='batch_num') - for i in range(batch_num): - batch = mnist.train.next_batch(batch_num) - dropout_rate = nni.choice(1, 5, name='dropout_rate') + batch_size = nni.choice(1, 4, 8, 16, 32, name='batch_size') + for i in range(2000): + batch = mnist.train.next_batch(batch_size) + dropout_rate = nni.choice(0.5, 0.9, name='dropout_rate') mnist_network.train_step.run(feed_dict={mnist_network.images: batch[0], mnist_network.labels: batch[1], - mnist_network.keep_prob: dropout_rate} + mnist_network.keep_prob: 1 - dropout_rate} ) if i % 100 == 0: diff --git a/examples/trials/mnist/config_assessor.yml b/examples/trials/mnist/config_assessor.yml index 862a262a28..d5a3c33d23 100644 --- a/examples/trials/mnist/config_assessor.yml +++ b/examples/trials/mnist/config_assessor.yml @@ -2,10 +2,10 @@ authorName: default experimentName: example_mnist trialConcurrency: 1 maxExecDuration: 1h -maxTrialNum: 1 +maxTrialNum: 20 #choice: local, remote trainingServicePlatform: local -searchSpacePath: ~/nni/examples/trials/mnist/search_space.json +searchSpacePath: search_space.json #choice: true, false useAnnotation: false tuner: @@ -23,5 +23,5 @@ assessor: optimize_mode: maximize trial: command: python3 mnist.py - codeDir: ~/nni/examples/trials/mnist + codeDir: . gpuNum: 0 diff --git a/examples/trials/mnist/mnist.py b/examples/trials/mnist/mnist.py index d5c6347b5a..d6384ecdef 100644 --- a/examples/trials/mnist/mnist.py +++ b/examples/trials/mnist/mnist.py @@ -173,10 +173,10 @@ def main(params): with tf.Session() as sess: sess.run(tf.global_variables_initializer()) for i in range(params['batch_num']): - batch = mnist.train.next_batch(params['batch_num']) + batch = mnist.train.next_batch(params['batch_size']) mnist_network.train_step.run(feed_dict={mnist_network.images: batch[0], mnist_network.labels: batch[1], - mnist_network.keep_prob: params['dropout_rate']} + mnist_network.keep_prob: 1 - params['dropout_rate']} ) if i % 100 == 0: @@ -212,7 +212,8 @@ def generate_default_params(): 'pool_size': 2, 'hidden_size': 1024, 'learning_rate': 1e-4, - 'batch_num': 200} + 'batch_num': 2000, + 'batch_size': 32} return params diff --git a/examples/trials/mnist/search_space.json b/examples/trials/mnist/search_space.json index 1d416cbfa6..c9b68a7a4f 100644 --- a/examples/trials/mnist/search_space.json +++ b/examples/trials/mnist/search_space.json @@ -1,6 +1,7 @@ { - "dropout_rate":{"_type":"uniform","_value":[0.1,0.5]}, + "dropout_rate":{"_type":"uniform","_value":[0.5, 0.9]}, "conv_size":{"_type":"choice","_value":[2,3,5,7]}, "hidden_size":{"_type":"choice","_value":[124, 512, 1024]}, + "batch_size": {"_type":"choice", "_value": [1, 4, 8, 16, 32]}, "learning_rate":{"_type":"choice","_value":[0.0001, 0.001, 0.01, 0.1]} } From 3f0697ad7061f1d54c3d39b43b229283676f6c54 Mon Sep 17 00:00:00 2001 From: Lijiao <35484733+lvybriage@users.noreply.github.com> Date: Thu, 8 Nov 2018 10:47:19 +0800 Subject: [PATCH 5/8] Add error message when experiment's status is error (#338) * Add error message when experiment error * delete unuseful code * Fix bug of bgcolor when experiment status is running --- src/webui/src/components/Overview.tsx | 33 +++++++--- .../src/components/overview/Progress.tsx | 37 +++++++++-- .../src/components/overview/ProgressItem.tsx | 9 +-- src/webui/src/static/style/button.scss | 1 - src/webui/src/static/style/overview.scss | 6 +- src/webui/src/static/style/probar.scss | 61 +++++++++++++++++++ src/webui/src/static/style/progress.scss | 9 +-- src/webui/src/static/style/trialStatus.scss | 44 ------------- 8 files changed, 128 insertions(+), 72 deletions(-) create mode 100644 src/webui/src/static/style/probar.scss delete mode 100644 src/webui/src/static/style/trialStatus.scss diff --git a/src/webui/src/components/Overview.tsx b/src/webui/src/components/Overview.tsx index 063fe00a7d..80a5fe2591 100644 --- a/src/webui/src/components/Overview.tsx +++ b/src/webui/src/components/Overview.tsx @@ -20,10 +20,11 @@ require('../static/style/accuracy.css'); require('../static/style/table.scss'); require('../static/style/overviewTitle.scss'); -interface SessionState { +interface OverviewState { tableData: Array; searchSpace: object; status: string; + errorStr: string; trialProfile: Experiment; option: object; noData: string; @@ -34,7 +35,7 @@ interface SessionState { downBool: boolean; } -class Overview extends React.Component<{}, SessionState> { +class Overview extends React.Component<{}, OverviewState> { public _isMounted = false; public intervalID = 0; @@ -45,6 +46,7 @@ class Overview extends React.Component<{}, SessionState> { this.state = { searchSpace: {}, status: '', + errorStr: '', trialProfile: { id: '', author: '', @@ -126,8 +128,8 @@ class Overview extends React.Component<{}, SessionState> { switch (key) { case 'loguniform': case 'qloguniform': - const a = Math.pow(10, value[0]); - const b = Math.pow(10, value[1]); + const a = Math.pow(Math.E, value[0]); + const b = Math.pow(Math.E, value[1]); value = [a, b]; searchSpace[item]._value = value; break; @@ -150,17 +152,30 @@ class Overview extends React.Component<{}, SessionState> { } } }); + this.checkStatus(); + } + + checkStatus = () => { axios(`${MANAGER_IP}/check-status`, { method: 'GET' }) .then(res => { if (res.status === 200 && this._isMounted) { - this.setState({ - status: res.data.status - }); + const errors = res.data.errors; + if (errors.length !== 0) { + this.setState({ + status: res.data.status, + errorStr: res.data.errors[0] + }); + } else { + this.setState({ + status: res.data.status, + }); + } } }); + } showTrials = () => { @@ -396,6 +411,7 @@ class Overview extends React.Component<{}, SessionState> { accuracyData, accNodata, status, + errorStr, trialNumber, bestAccuracy, downBool @@ -414,7 +430,7 @@ class Overview extends React.Component<{}, SessionState> { onClick={this.downExperimentContent} disabled={downBool} > - Download + Download icon @@ -430,6 +446,7 @@ class Overview extends React.Component<{}, SessionState> { trialProfile={trialProfile} bestAccuracy={bestAccuracy} status={status} + errors={errorStr} /> {/* experiment parameters search space tuner assessor... */} diff --git a/src/webui/src/components/overview/Progress.tsx b/src/webui/src/components/overview/Progress.tsx index cf1022ba57..45de55fb59 100644 --- a/src/webui/src/components/overview/Progress.tsx +++ b/src/webui/src/components/overview/Progress.tsx @@ -2,17 +2,20 @@ import * as React from 'react'; import { Row, Col, + Popover } from 'antd'; import { Experiment, TrialNumber } from '../../static/interface'; import { convertTime } from '../../static/function'; import ProgressBar from './ProgressItem'; import '../../static/style/progress.scss'; +import '../../static/style/probar.scss'; interface ProgressProps { trialProfile: Experiment; trialNumber: TrialNumber; bestAccuracy: string; status: string; + errors: string; } class Progressed extends React.Component { @@ -24,7 +27,7 @@ class Progressed extends React.Component { render() { const { trialProfile, trialNumber, bestAccuracy, - status + status, errors } = this.props; // remaining time const bar2 = trialNumber.totalCurrentTrial - trialNumber.waitTrial - trialNumber.unknowTrial; @@ -32,23 +35,49 @@ class Progressed extends React.Component { const percent = (trialProfile.execDuration / trialProfile.maxDuration) * 100; const runDuration = convertTime(trialProfile.execDuration); const remaining = convertTime(trialProfile.maxDuration - trialProfile.execDuration); - + let errorContent; + if (errors !== '') { + errorContent = ( +
+ {errors} +
+ ); + } return ( - +

Status

-
{status}
+
+ {status} + { + status === 'ERROR' + ? + + i + + : + + } + +
diff --git a/src/webui/src/components/overview/ProgressItem.tsx b/src/webui/src/components/overview/ProgressItem.tsx index b911118ee4..652cd3864f 100644 --- a/src/webui/src/components/overview/ProgressItem.tsx +++ b/src/webui/src/components/overview/ProgressItem.tsx @@ -6,6 +6,7 @@ interface ProItemProps { percent: number; description: string; maxString: string; + bgclass: string; } class ProgressBar extends React.Component { @@ -16,11 +17,11 @@ class ProgressBar extends React.Component { } render() { - const { who, percent, description, maxString } = this.props; + const { who, percent, description, maxString, bgclass } = this.props; return (
- +
{who}
@@ -34,8 +35,8 @@ class ProgressBar extends React.Component { />
- 0 - {maxString} + 0 + {maxString}
diff --git a/src/webui/src/static/style/button.scss b/src/webui/src/static/style/button.scss index 73f373df08..37b407c97f 100644 --- a/src/webui/src/static/style/button.scss +++ b/src/webui/src/static/style/button.scss @@ -2,7 +2,6 @@ Button.changeBtu, Button.changeBtu:hover, Button.changeBtu:focus{ background-color: #3c8dbc; border-color: #3c8dbc; line-height: 30px; - font-size: 16px; } Button.tableButton{ diff --git a/src/webui/src/static/style/overview.scss b/src/webui/src/static/style/overview.scss index 2104d38e23..452df13ebc 100644 --- a/src/webui/src/static/style/overview.scss +++ b/src/webui/src/static/style/overview.scss @@ -60,15 +60,15 @@ border: 1px solid #fff; border-radius: 0; margin-top: 4px; + background-color: #0071BC; span{ font-family: 'Segoe'; - font-size: 16px; - line-height: 30px; + font-size: 14px; } img{ - height: 16px; + height: 14px; margin-left: 10px; margin-top: -6px; } diff --git a/src/webui/src/static/style/probar.scss b/src/webui/src/static/style/probar.scss new file mode 100644 index 0000000000..c6ff7549f7 --- /dev/null +++ b/src/webui/src/static/style/probar.scss @@ -0,0 +1,61 @@ +#barBack{ + /* status: 'INITIALIZED' | 'EXPERIMENT_RUNNING' | 'ERROR' | 'STOPPING' | 'STOPPED' | 'DONE' */ + .EXPERIMENT_RUNNING, .STOPPING, .INITIALIZED{ + /* specific status color */ + color: #0071bc; + .ant-progress-bg { + background-color: #0071bc; + } + .ant-progress-text{ + color: #0071bc; + } + } + .DONE, .STOPPED{ + color: #009245; + .ant-progress-bg { + background-color: #009245; + } + .ant-progress-text{ + color: #009245; + } + } + .ERROR{ + color: #eb0716; + .ant-progress-bg { + background-color: #eb0716; + } + .ant-progress-text{ + color: #eb0716; + } + + } + .ant-progress-bg{ + border-radius: 0 !important; + } + .ant-progress-status-success .ant-progress-bg{ + border-radius: 0 12px 12px 0 !important; + } +} + +.errorBtn{ + margin-left: 15px; + display: inline-block; + width: 18px; + height: 18px; + line-height: 18px; + text-align: center; + font-size: 14px; + border: 1px solid #4d4d4d; + border-radius: 50%; + background-color: #4d4d4d; + color: #fff; +} +.errorBtn:hover{ + cursor: pointer; +} + +.errors{ + width: 240px; + font-size: 14px; + color: #212121; +} diff --git a/src/webui/src/static/style/progress.scss b/src/webui/src/static/style/progress.scss index 5108809c14..dccae5fe9c 100644 --- a/src/webui/src/static/style/progress.scss +++ b/src/webui/src/static/style/progress.scss @@ -17,14 +17,6 @@ border: 2px solid #e6e6e6; border-radius: 0 12px 12px 0 !important; } - .ant-progress-bg { - border-radius: 0 !important; - } - .ant-progress-status-success .ant-progress-bg{ - border-radius: 0 12px 12px 0 !important; - color: #009245; - background-color: #009245; - } .name{ height: 34px; line-height: 30px; @@ -43,6 +35,7 @@ width: 100%; line-height: 24px; font-size: 12px; + color: #212121; .right{ text-align: right; } diff --git a/src/webui/src/static/style/trialStatus.scss b/src/webui/src/static/style/trialStatus.scss deleted file mode 100644 index 017655399a..0000000000 --- a/src/webui/src/static/style/trialStatus.scss +++ /dev/null @@ -1,44 +0,0 @@ -.hyper{ - width: 98%; - margin: 30px auto; -} -.rungraph{ - width: 100%; -} - -pre.hyperpar{ - text-align: left; -} -.tables{ - width: 100%; -} - -/* the position of the pagination */ -.ant-table-pagination.ant-pagination{ - margin: 16px 0; - float: right; - margin-right: 30px; -} -Button.tableButton{ - background: #3c8dbc; - border-color: #3c8dbc; - height: 28px; - line-height: 28px; - /* padding: 3px 4px; */ -} - -.hyperpar ul, .hyperpar ul li{ - background: none !important; -} -/* kill btn style: delete its own hover style */ -/* after button click the color not change */ -Button.tableButton:hover, Button.tableButton:focus{ - background-color: #3c8dbc; - border-color: #3c8dbc; -} -.ant-modal-title{ - font-size: 20px; -} - - - From b827ceaa09b37b213f77daa6266c6c12d2ca8d58 Mon Sep 17 00:00:00 2001 From: fishyds Date: Fri, 9 Nov 2018 10:07:47 +0800 Subject: [PATCH 6/8] Change base image from devel to runtime, to reduce docker image size (#343) --- deployment/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deployment/docker/Dockerfile b/deployment/docker/Dockerfile index b868f1c9fd..3db87f093a 100644 --- a/deployment/docker/Dockerfile +++ b/deployment/docker/Dockerfile @@ -18,7 +18,7 @@ # 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. -FROM nvidia/cuda:9.0-cudnn7-devel-ubuntu16.04 +FROM nvidia/cuda:9.0-cudnn7-runtime-ubuntu16.04 LABEL maintainer='Microsoft NNI Team' From 53ed465a56c96878f4ed8f7264391a30a23eab1e Mon Sep 17 00:00:00 2001 From: goooxu <22703054+goooxu@users.noreply.github.com> Date: Fri, 9 Nov 2018 10:08:08 +0800 Subject: [PATCH 7/8] Update version number since v0.3.4 has been released (#342) --- README.md | 4 ++-- deployment/pypi/setup.py | 2 +- docs/GetStarted.md | 2 +- docs/InstallNNI_Ubuntu.md | 2 +- setup.py | 2 +- tools/setup.py | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 1dd1b14c00..64c49ff943 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Note: If you are in docker container (as root), please remove `--user` from the * We only support Linux (Ubuntu 16.04 or higher) in our current stage. * Run the following commands in an environment that has `python >= 3.5`, `git` and `wget`. ```bash - git clone -b v0.3.3 https://github.com/Microsoft/nni.git + git clone -b v0.3.4 https://github.com/Microsoft/nni.git cd nni source install.sh ``` @@ -47,7 +47,7 @@ Note: If you are in docker container (as root), please remove `--user` from the The following example is an experiment built on TensorFlow. Make sure you have **TensorFlow installed** before running it. * Download the examples via clone the source code. ```bash - git clone -b v0.3.3 https://github.com/Microsoft/nni.git + git clone -b v0.3.4 https://github.com/Microsoft/nni.git ``` * Run the mnist example. ```bash diff --git a/deployment/pypi/setup.py b/deployment/pypi/setup.py index 40cc12c75e..3214261d88 100644 --- a/deployment/pypi/setup.py +++ b/deployment/pypi/setup.py @@ -11,7 +11,7 @@ setuptools.setup( name = 'nni', - version = '0.3.3', + version = '0.3.4', author = 'Microsoft NNI team', author_email = 'nni@microsoft.com', description = 'Neural Network Intelligence package', diff --git a/docs/GetStarted.md b/docs/GetStarted.md index cde8a3cb85..096804da2a 100644 --- a/docs/GetStarted.md +++ b/docs/GetStarted.md @@ -18,7 +18,7 @@ * __Install NNI through source code__ - git clone -b v0.3.3 https://github.com/Microsoft/nni.git + git clone -b v0.3.4 https://github.com/Microsoft/nni.git cd nni source install.sh diff --git a/docs/InstallNNI_Ubuntu.md b/docs/InstallNNI_Ubuntu.md index 3256028db0..d76b09dd86 100644 --- a/docs/InstallNNI_Ubuntu.md +++ b/docs/InstallNNI_Ubuntu.md @@ -16,7 +16,7 @@ * __Install NNI through source code__ - git clone -b v0.3.3 https://github.com/Microsoft/nni.git + git clone -b v0.3.4 https://github.com/Microsoft/nni.git cd nni source install.sh diff --git a/setup.py b/setup.py index 7b8d429776..7f59348054 100644 --- a/setup.py +++ b/setup.py @@ -35,7 +35,7 @@ def run(self): setup( name = 'nni', - version = '0.3.3', + version = '0.3.4', author = 'Microsoft NNI Team', author_email = 'nni@microsoft.com', description = 'Neural Network Intelligence project', diff --git a/tools/setup.py b/tools/setup.py index 09dcf23a57..cdb20f32b3 100644 --- a/tools/setup.py +++ b/tools/setup.py @@ -2,7 +2,7 @@ setuptools.setup( name = 'nnictl', - version = '0.3.2', + version = '0.3.4', packages = setuptools.find_packages(exclude=['*test*']), python_requires = '>=3.5', From 55493edf52d7bdf8aaff5c2f5e3683c955e6ccc4 Mon Sep 17 00:00:00 2001 From: Gems Guo Date: Mon, 5 Nov 2018 17:41:32 +0800 Subject: [PATCH 8/8] Fixed the issue that pip install --user doesn't work in docker as root user --- deployment/pypi/Makefile | 15 +++++---------- .../local/localTrainingService.ts | 14 +++++++------- tools/nni_cmd/launcher.py | 11 +++-------- 3 files changed, 15 insertions(+), 25 deletions(-) diff --git a/deployment/pypi/Makefile b/deployment/pypi/Makefile index a4b77b39aa..2e3cc8ba8b 100644 --- a/deployment/pypi/Makefile +++ b/deployment/pypi/Makefile @@ -9,16 +9,11 @@ build: tar xf $(CWD)node-linux-x64.tar.xz -C node-linux-x64 --strip-components 1 cd $(CWD)../../src/nni_manager && yarn && yarn build cd $(CWD)../../src/webui && yarn && yarn build - rm -rf $(CWD)nni_pkg - cp -r $(CWD)../../src/nni_manager/dist $(CWD)nni_pkg - cp -r $(CWD)../../src/webui/build $(CWD)nni_pkg/static - cp $(CWD)../../src/nni_manager/package.json $(CWD)nni_pkg - cd $(CWD)nni_pkg && yarn --prod - rm -rf $(CWD)nnicmd - rm -rf $(CWD)nni_annotation - cp -r $(CWD)../../tools/nnicmd $(CWD)nnicmd - cp -r $(CWD)../../tools/nni_annotation $(CWD)nni_annotation - cp -r $(CWD)../../tools/trial_tool $(CWD)trial_tool + rm -rf $(CWD)nni + cp -r $(CWD)../../src/nni_manager/dist $(CWD)nni + cp -r $(CWD)../../src/webui/build $(CWD)nni/static + cp $(CWD)../../src/nni_manager/package.json $(CWD)nni + cd $(CWD)nni && yarn --prod cd $(CWD) && python3 setup.py bdist_wheel cd $(CWD)../../src/sdk/pynni && python3 setup.py bdist_wheel cp -r $(CWD)../../src/sdk/pynni/dist/*.whl $(CWD)dist diff --git a/src/nni_manager/training_service/local/localTrainingService.ts b/src/nni_manager/training_service/local/localTrainingService.ts index 6dbde68f87..9927f0c4f5 100644 --- a/src/nni_manager/training_service/local/localTrainingService.ts +++ b/src/nni_manager/training_service/local/localTrainingService.ts @@ -78,7 +78,7 @@ class LocalTrialJobDetail implements TrialJobDetail { public pid?: number; constructor(id: string, status: TrialJobStatus, submitTime: number, - workingDirectory: string, form: JobApplicationForm, sequenceId: number) { + workingDirectory: string, form: JobApplicationForm, sequenceId: number) { this.id = id; this.status = status; this.submitTime = submitTime; @@ -283,13 +283,13 @@ class LocalTrainingService implements TrainingService { public getClusterMetadata(key: string): Promise { switch (key) { case TrialConfigMetadataKey.TRIAL_CONFIG: - let getResult : Promise; - if(!this.localTrailConfig) { + let getResult: Promise; + if (!this.localTrailConfig) { getResult = Promise.reject(new NNIError(NNIErrorNames.NOT_FOUND, `${key} is never set yet`)); } else { - getResult = Promise.resolve(!this.localTrailConfig? '' : JSON.stringify(this.localTrailConfig)); + getResult = Promise.resolve(!this.localTrailConfig ? '' : JSON.stringify(this.localTrailConfig)); } - return getResult; + return getResult; default: return Promise.reject(new NNIError(NNIErrorNames.NOT_FOUND, 'Key not found')); } @@ -297,7 +297,7 @@ class LocalTrainingService implements TrainingService { public cleanUp(): Promise { this.stopping = true; - for(const stream of this.streams) { + for (const stream of this.streams) { stream.destroy(); } return Promise.resolve(); @@ -359,7 +359,7 @@ class LocalTrainingService implements TrainingService { await cpp.exec(`mkdir -p ${trialJobDetail.workingDirectory}`); await cpp.exec(`mkdir -p ${path.join(trialJobDetail.workingDirectory, '.nni')}`); await cpp.exec(`touch ${path.join(trialJobDetail.workingDirectory, '.nni', 'metrics')}`); - await fs.promises.writeFile(path.join(trialJobDetail.workingDirectory, 'run.sh'), runScriptLines.join('\n'), { encoding: 'utf8' }); + await fs.promises.writeFile(path.join(trialJobDetail.workingDirectory, 'run.sh'), runScriptLines.join('\n'), { encoding: 'utf8', mode: 0o777 }); await this.writeParameterFile(trialJobDetail.workingDirectory, (trialJobDetail.form).hyperParameters); await this.writeSequenceIdFile(trialJobId); const process: cp.ChildProcess = cp.exec(`bash ${path.join(trialJobDetail.workingDirectory, 'run.sh')}`); diff --git a/tools/nni_cmd/launcher.py b/tools/nni_cmd/launcher.py index b0819e52d3..065ce22512 100644 --- a/tools/nni_cmd/launcher.py +++ b/tools/nni_cmd/launcher.py @@ -35,7 +35,6 @@ import time import random import string -import site from pathlib import Path @@ -67,12 +66,8 @@ def start_rest_server(port, platform, mode, config_file_name, experiment_id=None exit(1) print_normal('Starting restful server...') - if os.geteuid() == 0: - site_dir = site.getsitepackages()[0] - else: - site_dir = site.getusersitepackages() - python_dir = str(Path(site_dir).parents[2]) - cmds = ['node', os.path.join(python_dir, 'nni', 'main.js'), '--port', str(port), '--mode', platform, '--start_mode', mode] + base_dir = str(Path(os.path.dirname(__file__)).parents[3]) + cmds = ['node', os.path.join(base_dir, 'nni', 'main.js'), '--port', str(port), '--mode', platform, '--start_mode', mode] if mode == 'resume': cmds += ['--experiment_id', experiment_id] stdout_full_path, stderr_full_path = get_log_path(config_file_name) @@ -83,7 +78,7 @@ def start_rest_server(port, platform, mode, config_file_name, experiment_id=None log_header = LOG_HEADER % str(time_now) stdout_file.write(log_header) stderr_file.write(log_header) - process = Popen(cmds, cwd=os.path.join(python_dir, 'nni'), stdout=stdout_file, stderr=stderr_file) + process = Popen(cmds, cwd=os.path.join(base_dir, 'nni'), stdout=stdout_file, stderr=stderr_file) return process, str(time_now) def set_trial_config(experiment_config, port, config_file_name):