diff --git a/.DS_Store b/.DS_Store index bf98a860ffe69b0ba098dbe9de9827de9120b288..933ebbfc1f6463b8a8eba24a631005079c6cb8d8 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/autoaug/autoaugment_learners/AaLearner.py b/autoaug/autoaugment_learners/AaLearner.py index 808108d3d54824e541acef154144a6b9f25ebba5..6bc2f68fbd8a36b6ae84de40a1762905e9b610dc 100644 --- a/autoaug/autoaugment_learners/AaLearner.py +++ b/autoaug/autoaugment_learners/AaLearner.py @@ -462,3 +462,22 @@ class AaLearner: megapol += pol[0] return megapol + + + def get_n_best_policies(self, number_policies=5): + """ + returns the n best policies + + + Args: + number_policies (int): Number of (sub)policies to return + + Returns: + list of best n policies + """ + + number_policies = max(number_policies, len(self.history)) + + inter_pol = sorted(self.history, key=lambda x: x[1], reverse = True)[:number_policies] + + return inter_pol[n] diff --git a/autoaug/autoaugment_learners/UcbLearner.py b/autoaug/autoaugment_learners/UcbLearner.py index 7e3e707780bec802c254fe08aab563faacfb612c..d0b3cae7ab225d35f7b5dd988c228ec34967f23e 100644 --- a/autoaug/autoaugment_learners/UcbLearner.py +++ b/autoaug/autoaugment_learners/UcbLearner.py @@ -153,8 +153,7 @@ class UcbLearner(RsLearner): train_dataset, test_dataset, child_network_architecture, - iterations=15, - print_every_epoch=False): + iterations=15,): """continue the UCB algorithm for ``iterations`` number of turns """ @@ -173,7 +172,6 @@ class UcbLearner(RsLearner): train_dataset, test_dataset, logging=False, - print_every_epoch=print_every_epoch ) # update q_values (average accuracy) self.avg_accs[this_policy_idx] = acc @@ -188,7 +186,6 @@ class UcbLearner(RsLearner): train_dataset, test_dataset, logging=False, - print_every_epoch=print_every_epoch ) # update q_values (average accuracy) self.avg_accs[this_policy_idx] = (self.avg_accs[this_policy_idx]*self.cnts[this_policy_idx] + acc) / (self.cnts[this_policy_idx] + 1) @@ -246,6 +243,30 @@ class UcbLearner(RsLearner): return megapol + + def get_n_best_policies(self, number_policies=5): + """ + returns the n best policies + + + Args: + number_policies (int): Number of (sub)policies to return + + Returns: + list of best n policies + """ + + temp_avg_accs = [x if x is not None else 0 for x in self.avg_accs] + + temp_history = list(zip(self.policies, temp_avg_accs)) + + number_policies = max(number_policies, len(temp_history)) + + inter_pol = sorted(temp_history, key=lambda x: x[1], reverse = True)[:number_policies] + + return inter_pol[n] + + diff --git a/flask_mvp/auto_augmentation/progress.py b/flask_mvp/auto_augmentation/progress.py index e72a5b753ceab943807238f999f736c7f9a0c262..cc08843c5adfad31f8aac59df25886d3a2186191 100644 --- a/flask_mvp/auto_augmentation/progress.py +++ b/flask_mvp/auto_augmentation/progress.py @@ -6,7 +6,7 @@ import torch torch.manual_seed(0) -import temp_util.wapp_util as wapp_util +import react_backend.wapp_util as wapp_util bp = Blueprint("progress", __name__) diff --git a/flask_mvp/auto_augmentation/training.py b/flask_mvp/auto_augmentation/training.py index be5c7254ca211e14096f077509d56e0d41a8eceb..4ac0c82c2aa961c9eac84916f8e824ea14d41c16 100644 --- a/flask_mvp/auto_augmentation/training.py +++ b/flask_mvp/auto_augmentation/training.py @@ -5,7 +5,7 @@ import torch torch.manual_seed(0) -import temp_util.wapp_util as wapp_util +import react_backend.wapp_util as wapp_util bp = Blueprint("training", __name__) diff --git a/notebooks/UCB1_JC.ipynb b/notebooks/UCB1_JC.ipynb index 97d4ee68d62418003d549bcafc213c1188853a7b..406b4f4ecfdcc6690dbad847e7a69ee442e15392 100644 --- a/notebooks/UCB1_JC.ipynb +++ b/notebooks/UCB1_JC.ipynb @@ -425,7 +425,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "<Figure size 432x288 with 1 Axes>" ] diff --git a/react_app.py b/react_app.py index 82fe9845a881d311cc531ce9a3446e7eb7beaffd..42c761fd04e2db99a78b67764bb942f228b929d2 100644 --- a/react_app.py +++ b/react_app.py @@ -1,15 +1,15 @@ from dataclasses import dataclass from flask import Flask, request, current_app, send_file, send_from_directory, redirect, url_for, session from flask_cors import CORS, cross_origin - import os import zipfile - import torch -from numpy import save, load -# import temp_util.wapp_util as wapp_util -import time - +from numpy import int0, save, load +from react_backend.wapp_util import parse_users_learner_spec +import pprint +import matplotlib +matplotlib.use('Agg') +import matplotlib.pyplot as plt import os import sys sys.path.insert(0, os.path.abspath('..')) @@ -39,22 +39,22 @@ def get_form_data(): print('@@@ required user input:', 'ds', ds, 'IsLeNet:', IsLeNet, 'auto_aug_leanrer:',auto_aug_learner) # advanced input - if form_data['batch_size'] != 'undefined': - batch_size = form_data['batch_size'] # size of batch the inner NN is trained with + if form_data['batch_size'] not in ['undefined', ""]: + batch_size = int(form_data['batch_size'] ) # size of batch the inner NN is trained with else: - batch_size = 1 # this is for demonstration purposes - if form_data['learning_rate'] != 'undefined': - learning_rate = form_data['learning_rate'] # fix learning rate + batch_size = 16 # this is for demonstration purposes + if form_data['learning_rate'] not in ['undefined', ""]: + learning_rate = float(form_data['learning_rate']) # fix learning rate else: - learning_rate = 10-1 - if form_data['toy_size'] != 'undefined': - toy_size = form_data['toy_size'] # total propeortion of training and test set we use + learning_rate = 1e-2 + if form_data['toy_size'] not in ['undefined', ""]: + toy_size = float(form_data['toy_size']) # total propeortion of training and test set we use else: - toy_size = 1 # this is for demonstration purposes - if form_data['iterations'] != 'undefined': - iterations = form_data['iterations'] # total iterations, should be more than the number of policies + toy_size = 0.01 # this is for demonstration purposes + if form_data['iterations'] not in ['undefined', ""]: + iterations = int(form_data['iterations']) # total iterations, should be more than the number of policies else: - iterations = 10 + iterations = 2 exclude_method = form_data['select_action'] print('@@@ advanced search: batch_size:', batch_size, 'learning_rate:', learning_rate, 'toy_size:', toy_size, 'iterations:', iterations, 'exclude_method', exclude_method) @@ -156,15 +156,54 @@ def training(): num_sub_policies = 5 # fix number of sub-policies in a policy data = current_app.config.get('data') - # fake training - print('pretend it is training') - time.sleep(1) - print('epoch: 1') - time.sleep(1) - print('epoch: 2') - time.sleep(1) - print('epoch: 3') - print('it has finished training') + # parse the settings given by the user to obtain tools we need + train_dataset, test_dataset, child_archi, agent = parse_users_learner_spec( + max_epochs=max_epochs, + early_stop_num=early_stop_num, + num_policies=num_policies, + num_sub_policies=num_sub_policies, + **data + ) + + # train the autoaugment learner for number of `iterations` + agent.learn( + train_dataset=train_dataset, + test_dataset=test_dataset, + child_network_architecture=child_archi, + iterations=data['iterations'] + ) + + print('the history of all the policies the agent has tested:') + pprint.pprint(agent.history) + + # get acc graph and best acc graph + acc_list = [acc for (policy,acc) in agent.history] + best_acc_list = [] + best_til_now = 0 + for acc in acc_list: + if acc>best_til_now: + best_til_now=acc + best_acc_list.append(best_til_now) + + # plot both here + fig = plt.figure() + ax = fig.add_subplot(1, 1, 1) + ax.plot(acc_list) + ax.plot(best_acc_list) + ax.set_xlabel('Number of Iterations') + ax.set_ylabel('Accuracy') + ax.set_title('Auto-augmentation Learner Performance Curve') + with open("./react_frontend/src/pages/output.png", 'wb') as f: + fig.savefig(f) + + print("best policies:") + best_policy = agent.get_mega_policy(number_policies=4) + print(best_policy) + with open("./react_backend/policy.txt", 'w') as f: + # save the best_policy in pretty_print string format + f.write(pprint.pformat(best_policy, indent=4)) + + print('') return {'status': 'Training is done!'} diff --git a/temp_util/parse_ds_cn_arch.py b/react_backend/parse_ds_cn_arch.py similarity index 92% rename from temp_util/parse_ds_cn_arch.py rename to react_backend/parse_ds_cn_arch.py index 8a167460e0ab7d3307043b109ec55622d4033c1a..b334bce2b7f67040c08348a0f292a699da3f9ce8 100644 --- a/temp_util/parse_ds_cn_arch.py +++ b/react_backend/parse_ds_cn_arch.py @@ -36,12 +36,15 @@ def parse_ds_cn_arch(ds, ds_name, IsLeNet): len_train = int(0.8*len(dataset)) train_dataset, test_dataset = torch.utils.data.random_split(dataset, [len_train, len(dataset)-len_train]) - # check sizes of images - img_height = len(train_dataset[0][0][0]) - img_width = len(train_dataset[0][0][0][0]) - img_channels = len(train_dataset[0][0]) - + my_image = train_dataset[0][0] + my_transform = torchvision.transforms.ToTensor() + my_image = my_transform(my_image) + # check sizes of images + img_height = len(my_image[0]) + img_width = len(my_image[0][0]) + img_channels = len(my_image) + # check output labels if ds == 'Other': num_labels = len(dataset.class_to_idx) diff --git a/react_backend/policy.txt b/react_backend/policy.txt index ba1f82e0664d8cca0732c7db753ac93c122986de..2ab6b8100a10216936864ffcbb9848817cfdcbad 100644 --- a/react_backend/policy.txt +++ b/react_backend/policy.txt @@ -1 +1,10 @@ -0.7018545454545454,0.6530636363636364,0.6565090909090909,0.7029727272727273,0.6615000000000001,0.6610181818181818,0.6333545454545454,0.6617909090909091,0.6584636363636364,0.6933909090909091 \ No newline at end of file +[ (('Brightness', 0.4, 4), ('Color', 0.0, 8)), + (('Posterize', 0.1, 0), ('Rotate', 0.3, 3)), + (('Equalize', 0.8, None), ('TranslateX', 0.7, 4)), + (('Equalize', 0.1, None), ('Posterize', 0.4, 1)), + (('AutoContrast', 0.3, None), ('Solarize', 0.2, 3)), + (('Sharpness', 1.0, 9), ('ShearY', 0.9, 9)), + (('Posterize', 0.6, 0), ('Color', 1.0, 0)), + (('TranslateX', 0.9, 0), ('Solarize', 0.1, 2)), + (('Rotate', 1.0, 9), ('Equalize', 0.3, None)), + (('ShearX', 0.3, 5), ('TranslateX', 0.0, 7))] \ No newline at end of file diff --git a/temp_util/wapp_util.py b/react_backend/wapp_util.py similarity index 95% rename from temp_util/wapp_util.py rename to react_backend/wapp_util.py index a23a98266bf603f1997c16e6244c5d1aad7772ea..8b580bb3e998999c8b278def417f1e188db3b70f 100644 --- a/temp_util/wapp_util.py +++ b/react_backend/wapp_util.py @@ -26,7 +26,6 @@ def parse_users_learner_spec( auto_aug_learner, # search space settings exclude_method, - num_funcs, num_policies, num_sub_policies, # child network settings @@ -35,7 +34,9 @@ def parse_users_learner_spec( early_stop_num, iterations, learning_rate, - max_epochs + max_epochs, + # dummy variable which does nothing + network_name, ): train_dataset, test_dataset, child_archi = parse_ds_cn_arch( ds, @@ -111,8 +112,4 @@ def parse_users_learner_spec( early_stop_num=early_stop_num, ) - - agent.learn(train_dataset, - test_dataset, - child_network_architecture=child_archi, - iterations=iterations) \ No newline at end of file + return train_dataset, test_dataset, child_archi, agent \ No newline at end of file diff --git a/react_frontend/src/pages/Confirm.js b/react_frontend/src/pages/Confirm.js index 2d6b0d9ded4ed42bdd97698ca0a7d486899fde04..5416d7c672c234356e50a748d62a5832389e380c 100644 --- a/react_frontend/src/pages/Confirm.js +++ b/react_frontend/src/pages/Confirm.js @@ -8,17 +8,21 @@ export default function Confirm() { const [myData, setMyData] = useState([]) const [dataset, setDataset] = useState() const [network, setNetwork] = useState() + const [yes, setYes] = useState() - // console.log('already in confirm react') + console.log('already in confirm react') useEffect(() => { const res = fetch('/home').then( response => response.json() ).then(data => {setMyData(data); if (data.ds == 'Other'){setDataset(data.ds_name)} else {setDataset(data.ds)}; if (data.IsLeNet == 'Other'){setNetwork(data.network_name)} else {setNetwork(data.IsLeNet)}; + setYes('hey'); + console.log('setYes', yes); }); }, []); + let navigate = useNavigate(); const onSubmit = async () => { navigate('/progress', {replace:true}); @@ -27,7 +31,7 @@ export default function Confirm() { return ( <div className="App" style={{padding:"60px"}}> <Typography gutterBottom variant="h3" align="center" > - Data Auto-Augmentation + Data Auto-Augmentation {yes} </Typography> <Grid> <Card style={{ maxWidth: 900, padding: "10px 5px", margin: "0 auto" }}> diff --git a/react_frontend/src/pages/Home.js b/react_frontend/src/pages/Home.js index 9531538dabd911a6171d587e4b64bdb6e5435c35..e8c12f3c377f5597b31426b3a02c491e05cb0a09 100644 --- a/react_frontend/src/pages/Home.js +++ b/react_frontend/src/pages/Home.js @@ -27,7 +27,6 @@ const ExpandMore = styled((props) => { export default function Home() { const [selectAction, setSelectAction] = useState([]); - const [validation, setValidation] = useState([]); // for form submission const {register, control, handleSubmit, setValue, watch, formState: { errors, dirtyFields}} = useForm(); @@ -66,31 +65,8 @@ export default function Home() { response => response.json() ).then(data => { if ('error' in data){navigate('/error', data)} else {navigate('/confirm', {replace:true})} - }); - - // - ///////// testing - // .then((response)=> { - // responseClone = response.clone(); // 2 - // return response.json(); - // }) - // .then(function (data) { - // console.log('data from flask', data) - // }, function (rejectionReason) { // 3 - // console.log('Error parsing JSON from response:', rejectionReason, responseClone); // 4 - // responseClone.text() // 5 - // .then(function (bodyText) { - // console.log('Received the following instead of valid JSON:', bodyText); // 6 - // }); - // }); - + }); }; - - - // body: JSON.stringify(data) - // console.log('errors', errors); - // console.log('handleSubmit', handleSubmit) - // handling action selection const handleActionSelect = (value) => { @@ -328,10 +304,10 @@ export default function Home() { <TextField type="number" inputProps={{step: "0.000000001",min: 0}} {...register("learning_rate")} name="learning_rate" placeholder="Learning Rate" label="Learning Rate" variant="outlined" fullWidth /> </Grid> <Grid xs={12} sm={6} item> - <TextField type="number" InputProps={{step:"1", inputProps: { min: 0, max: 1} }} {...register("iterations")} name="iterations" placeholder="Number of Iterations" label="Iterations" variant="outlined" fullWidth /> + <TextField type="number" InputProps={{step:"1", inputProps: { min: 0} }} {...register("iterations")} name="iterations" placeholder="Number of Iterations" label="Iterations" variant="outlined" fullWidth /> </Grid> <Grid xs={12} sm={6} item> - <TextField type="number" inputProps={{step: "0.01", min: 0, max: 1}} {...register("toy_size")} name="toy_size" placeholder="Dataset Proportion" label="Dataset Proportion" variant="outlined" fullWidth /> + <TextField type="number" inputProps={{step: "0.0001", min: 0, max: 1}} {...register("toy_size")} name="toy_size" placeholder="Dataset Proportion" label="Dataset Proportion" variant="outlined" fullWidth /> </Grid> <FormLabel variant="h8" align='centre'> * Dataset Proportion defines the percentage of original dataset our auto-augment learner will use to find the diff --git a/react_frontend/src/pages/Result.js b/react_frontend/src/pages/Result.js index 70dec30c7784651f839bdf6e1b56f04c72946f8c..746998501b6d4714626056e9e252d958de187550 100644 --- a/react_frontend/src/pages/Result.js +++ b/react_frontend/src/pages/Result.js @@ -1,6 +1,6 @@ import React, { useState, useEffect } from "react"; import { Grid, List, ListItem, Avatar, ListItemAvatar, ListItemText, Card, CardContent, Typography, Button, CardMedia } from '@mui/material'; -import output from './pytest.png' +import output from './output.png' import {useNavigate, Route} from "react-router-dom"; import axios from 'axios' import fileDownload from 'js-file-download' @@ -28,10 +28,10 @@ export default function Result() { Here are the results from our auto-augment agent: </Typography> <Grid style={{padding:"30px"}} container spacing={4} alignItems="center"> - <Grid xs={7} item> + <Grid xs={6} item> <img src={output} alt='output' /> </Grid> - <Grid xs={5} item> + <Grid xs={6} item> <Typography> write something here to explain the meaning of the graph to the user </Typography> @@ -41,6 +41,7 @@ export default function Result() { <Typography gutterBottom variant='h6' align='center'> You can download the augentation policy here </Typography> + <Button type="submit" variant="contained" @@ -50,9 +51,13 @@ export default function Result() { > Download </Button> - <Typography> - Please follow our documentation to apply this policy to your dataset. - </Typography> + + <Grid style={{padding:'10px'}}> + <Typography> + Please follow our documentation to apply this policy to your dataset. + </Typography> + </Grid> + </CardContent> </Card> diff --git a/react_frontend/src/pages/output.png b/react_frontend/src/pages/output.png new file mode 100644 index 0000000000000000000000000000000000000000..2578c96febcab65581394b498ab5f62130d0a7f7 Binary files /dev/null and b/react_frontend/src/pages/output.png differ diff --git a/react_frontend/src/pages/pytest.png b/react_frontend/src/pages/pytest.png deleted file mode 100644 index 272b44ed38c9107f19c99dc9a5ac38593493604f..0000000000000000000000000000000000000000 Binary files a/react_frontend/src/pages/pytest.png and /dev/null differ