From 27508362877000f1761f83c706d00dddd42fa59b Mon Sep 17 00:00:00 2001 From: Andrey Velichkevich Date: Wed, 9 Oct 2024 23:15:28 +0100 Subject: [PATCH] Update README and out-of-date docs Signed-off-by: Andrey Velichkevich --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- docs/developer-guide.md => CONTRIBUTING.md | 17 +- README.md | 137 +++---------- docs/README.md | 5 + docs/images-location.md | 10 +- docs/images/SystemFlow.png | Bin 104398 -> 0 bytes docs/new-algorithm-service.md | 185 ------------------ .../README.md} | 2 +- .../README.md} | 4 +- .../conformance-crd-test.png | Bin .../README.md} | 30 +-- .../README.md} | 17 +- .../push-based-metrics-collection.png | Bin .../README.md} | 2 +- .../README.md} | 101 +++++----- .../README.md} | 4 +- .../metrics-collector-design.png | Bin docs/release/README.md | 2 +- docs/workflow-design.md | 2 + 19 files changed, 132 insertions(+), 388 deletions(-) rename docs/developer-guide.md => CONTRIBUTING.md (94%) create mode 100644 docs/README.md delete mode 100644 docs/images/SystemFlow.png delete mode 100644 docs/new-algorithm-service.md rename docs/proposals/{trial-custom-crd.md => 1214-custom-crd-in-trial/README.md} (99%) rename docs/proposals/{conformance-test.md => 2044-conformance-program/README.md} (98%) rename docs/{images => proposals/2044-conformance-program}/conformance-crd-test.png (100%) rename docs/proposals/{llm-hyperparameter-optimization-api.md => 2339-hpo-for-llm-fine-tuning/README.md} (95%) rename docs/proposals/{push-based-metrics-collection.md => 2340-push-based-metrics-collector/README.md} (98%) rename docs/{images => proposals/2340-push-based-metrics-collector}/push-based-metrics-collection.png (100%) rename docs/proposals/{parameter-distribution.md => 2374-parameter-distribution/README.md} (99%) rename docs/proposals/{suggestion.md => 507-suggestion-crd/README.md} (84%) rename docs/proposals/{metrics-collector.md => 685-metrics-collector/README.md} (98%) rename docs/{images => proposals/685-metrics-collector}/metrics-collector-design.png (100%) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index f2be2ee23ed..5881e55a6e2 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,6 +1,6 @@ diff --git a/docs/developer-guide.md b/CONTRIBUTING.md similarity index 94% rename from docs/developer-guide.md rename to CONTRIBUTING.md index 955c44e5ae5..705aba59e6c 100644 --- a/docs/developer-guide.md +++ b/CONTRIBUTING.md @@ -2,13 +2,12 @@ This developer guide is for people who want to contribute to the Katib project. If you're interesting in using Katib in your machine learning project, -see the following user guides: +see the following guides: -- [Concepts](https://www.kubeflow.org/docs/components/katib/overview/) - in Katib, hyperparameter tuning, and neural architecture search. - [Getting started with Katib](https://kubeflow.org/docs/components/katib/hyperparameter/). -- Detailed guide to [configuring and running a Katib - experiment](https://kubeflow.org/docs/components/katib/experiment/). +- [How to configure Katib Experiment](https://kubeflow.org/docs/components/katib/experiment/). +- [Katib architecture and concepts](https://www.kubeflow.org/docs/components/katib/reference/architecture/) + for hyperparameter tuning and neural architecture search. ## Requirements @@ -93,10 +92,6 @@ Below is a list of command-line flags accepted by Katib DB Manager: | --------------- | ------------- | ------- | ------------------------------------------------------- | | connect-timeout | time.Duration | 60s | Timeout before calling error during database connection | -## Workflow design - -Please see [workflow-design.md](./workflow-design.md). - ## Katib admission webhooks Katib uses three [Kubernetes admission webhooks](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/). @@ -113,7 +108,7 @@ Katib uses three [Kubernetes admission webhooks](https://kubernetes.io/docs/refe 1. `mutator.pod.katib.kubeflow.org` - Mutating admission webhook to inject the metrics collector sidecar container to the training pod. Learn more about the Katib's metrics collector in the - [Kubeflow documentation](https://www.kubeflow.org/docs/components/katib/experiment/#metrics-collector). + [Kubeflow documentation](https://www.kubeflow.org/docs/components/katib/user-guides/metrics-collector/). You can find the YAMLs for the Katib webhooks [here](../manifests/v1beta1/components/webhook/webhooks.yaml). @@ -168,4 +163,4 @@ they'll be executed against every file in the repository. Specific programmatically generated files listed in the `exclude` field in [.pre-commit-config.yaml](../.pre-commit-config.yaml) are deliberately excluded -from the hooks. +from the hooks. diff --git a/README.md b/README.md index f9c0dc1806a..3d7cdeb1f9b 100644 --- a/README.md +++ b/README.md @@ -29,13 +29,13 @@ and many more. Katib stands for `secretary` in Arabic. -# Search Algorithms +## Search Algorithms Katib supports several search algorithms. Follow the -[Kubeflow documentation](https://www.kubeflow.org/docs/components/katib/experiment/#search-algorithms-in-detail) +[Kubeflow documentation](https://www.kubeflow.org/docs/components/katib/user-guides/hp-tuning/configure-algorithm/#hp-tuning-algorithms) to know more about each algorithm and check the -[Suggestion service guide](/docs/new-algorithm-service.md) to implement your -custom algorithm. +[this guide](https://www.kubeflow.org/docs/components/katib/user-guides/hp-tuning/configure-algorithm/#use-custom-algorithm-in-katib) +to implement your custom algorithm. @@ -137,141 +137,68 @@ custom algorithm.
-To perform above algorithms Katib supports the following frameworks: +To perform the above algorithms Katib supports the following frameworks: - [Goptuna](https://github.com/c-bata/goptuna) - [Hyperopt](https://github.com/hyperopt/hyperopt) - [Optuna](https://github.com/optuna/optuna) - [Scikit Optimize](https://github.com/scikit-optimize/scikit-optimize) -# Installation - -For the various Katib installs check the -[Kubeflow guide](https://www.kubeflow.org/docs/components/katib/hyperparameter/#katib-setup). -Follow the next steps to install Katib standalone. - ## Prerequisites -This is the minimal requirements to install Katib: - -- Kubernetes >= 1.27 -- `kubectl` >= 1.27 +Please check [the official Kubeflow documentation](https://www.kubeflow.org/docs/components/katib/installation/#prerequisites) +for prerequisites to install Katib. -## Latest Version +## Installation -For the latest Katib version run this command: - -``` -kubectl apply -k "github.com/kubeflow/katib.git/manifests/v1beta1/installs/katib-standalone?ref=master" -``` +Please follow [the Kubeflow Katib guide](https://www.kubeflow.org/docs/components/katib/installation/#installing-katib) +for the detailed instructions on how to install Katib. -## Release Version +### Installing the Control Plane -For the specific Katib release (for example `v0.14.0`) run this command: +Run the following command to install the latest stable release of Katib control plane: ``` -kubectl apply -k "github.com/kubeflow/katib.git/manifests/v1beta1/installs/katib-standalone?ref=v0.14.0" +kubectl apply -k "github.com/kubeflow/katib.git/manifests/v1beta1/installs/katib-standalone?ref=v0.17.0" ``` -Make sure that all Katib components are running: +Run the following command to install the latest changes of Katib control plane: ``` -$ kubectl get pods -n kubeflow - -NAME READY STATUS RESTARTS AGE -katib-controller-566595bdd8-hbxgf 1/1 Running 0 36s -katib-db-manager-57cd769cdb-4g99m 1/1 Running 0 36s -katib-mysql-7894994f88-5d4s5 1/1 Running 0 36s -katib-ui-5767cfccdc-pwg2x 1/1 Running 0 36s +kubectl apply -k "github.com/kubeflow/katib.git/manifests/v1beta1/installs/katib-standalone?ref=master" ``` For the Katib Experiments check the [complete examples list](./examples/v1beta1). -# Quickstart +### Installing the Python SDK -You can run your first HyperParameter Tuning Experiment using [Katib Python SDK](./sdk/python/v1beta1). +Katib implements [a Python SDK](https://pypi.org/project/kubeflow-katib/) to simplify creation of +hyperparameter tuning jobs for Data Scientists. -In the following example we are going to maximize a simple objective function: -$F(a,b) = 4a - b^2$. The bigger $a$ and the lesser $b$ value, the bigger the function value $F$. +Run the following command to install the latest stable release of Katib SDK: -```python -import kubeflow.katib as katib - -# Step 1. Create an objective function. -def objective(parameters): - # Import required packages. - import time - time.sleep(5) - # Calculate objective function. - result = 4 * int(parameters["a"]) - float(parameters["b"]) ** 2 - # Katib parses metrics in this format: =. - print(f"result={result}") - -# Step 2. Create HyperParameter search space. -parameters = { - "a": katib.search.int(min=10, max=20), - "b": katib.search.double(min=0.1, max=0.2) -} - -# Step 3. Create Katib Experiment. -katib_client = katib.KatibClient() -name = "tune-experiment" -katib_client.tune( - name=name, - objective=objective, - parameters=parameters, - objective_metric_name="result", - max_trial_count=12 -) - -# Step 4. Get the best HyperParameters. -print(katib_client.get_optimal_hyperparameters(name)) +```sh +pip install -U kubeflow-katib ``` -# Documentation - -- Check - [the Katib getting started guide](https://www.kubeflow.org/docs/components/katib/hyperparameter/#example-using-random-search-algorithm). - -- Learn about Katib **Concepts** in this - [guide](https://www.kubeflow.org/docs/components/katib/overview/#katib-concepts). - -- Learn about Katib **Interfaces** in this - [guide](https://www.kubeflow.org/docs/components/katib/overview/#katib-interfaces). - -- Learn about Katib **Components** in this - [guide](https://www.kubeflow.org/docs/components/katib/hyperparameter/#katib-components). - -- Know more about Katib in the [presentations and demos list](./docs/presentations.md). +## Getting Started -# Community +Please refer to [the getting started guide](https://www.kubeflow.org/docs/components/katib/getting-started/#getting-started-with-katib-python-sdk) +to quickly create your first hyperparameter tuning Experiment using the Python SDK. -We are always growing our community and invite new users and AutoML enthusiasts -to contribute to the Katib project. The following links provide information -about getting involved in the community: +## Community -- Subscribe to the - [AutoML calendar](https://calendar.google.com/calendar/u/0/r?cid=ZDQ5bnNpZWZzbmZna2Y5MW8wdThoMmpoazRAZ3JvdXAuY2FsZW5kYXIuZ29vZ2xlLmNvbQ) - to attend Working Group bi-weekly community meetings. +The following links provide information on how to get involved in the community: -- Check the - [AutoML and Training Working Group meeting notes](https://docs.google.com/document/d/1MChKfzrKAeFRtYqypFbMXL6ZIc_OgijjkvbqmwRV-64/edit). - -- If you use Katib, please update [the adopters list](ADOPTERS.md). +- Attend [the bi-weekly AutoML and Training Working Group](https://bit.ly/2PWVCkV) + community meeting. +- Join our [`#kubeflow-katib`](https://www.kubeflow.org/docs/about/community/#kubeflow-slack-channels) + Slack channel. +- Check out [who is using Katib](ADOPTERS.md) and [presentations about Katib project](docs/presentations.md). ## Contributing -Please feel free to test the system! [Developer guide](./docs/developer-guide.md) -is a good starting point for our developers. - -## Blog posts - -- [Kubeflow Katib: Scalable, Portable and Cloud Native System for AutoML](https://blog.kubeflow.org/katib/) - (by Andrey Velichkevich) - -## Events - -- [AutoML and Training WG Summit. 16th of July 2021](https://docs.google.com/document/d/1vGluSPHmAqEr8k9Dmm82RcQ-MVnqbYYSfnjMGB-aPuo/edit?usp=sharing) +Please refer to the [CONTRIBUTING guide](CONTRIBUTING.md). ## Citation diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000000..b199e066e7a --- /dev/null +++ b/docs/README.md @@ -0,0 +1,5 @@ +# Katib Documentation + +Welcome to Kubeflow Katib! + +The Katib documentation is available on [kubeflow.org](https://www.kubeflow.org/docs/components/katib/). diff --git a/docs/images-location.md b/docs/images-location.md index 0cbf78d7618..c20b60a43e4 100644 --- a/docs/images-location.md +++ b/docs/images-location.md @@ -5,7 +5,7 @@ Here you can find the location for images that are used in Katib. ## Katib Components Images The following table shows images for the -[Katib components](https://www.kubeflow.org/docs/components/katib/hyperparameter/#katib-components). +[Katib components](https://www.kubeflow.org/docs/components/katib/reference/architecture/#katib-control-plane-components). @@ -70,7 +70,7 @@ The following table shows images for the ## Katib Metrics Collectors Images The following table shows images for the -[Katib Metrics Collectors](https://www.kubeflow.org/docs/components/katib/experiment/#metrics-collector). +[Katib Metrics Collectors](https://www.kubeflow.org/docs/components/katib/user-guides/metrics-collector/).
@@ -113,8 +113,8 @@ The following table shows images for the ## Katib Suggestions and Early Stopping Images The following table shows images for the -[Katib Suggestions](https://www.kubeflow.org/docs/components/katib/experiment/#search-algorithms-in-detail) -and the [Katib Early Stopping algorithms](https://www.kubeflow.org/docs/components/katib/early-stopping/). +[Katib Suggestion services](https://www.kubeflow.org/docs/components/katib/reference/architecture/#suggestion) +and the [Katib Early Stopping algorithms](https://www.kubeflow.org/docs/components/katib/user-guides/early-stopping/#early-stopping-algorithms).
@@ -223,7 +223,7 @@ and the [Katib Early Stopping algorithms](https://www.kubeflow.org/docs/componen ## Training Containers Images The following table shows images for training containers which are used in the -[Katib Trials](https://www.kubeflow.org/docs/components/katib/experiment/#packaging-your-training-code-in-a-container-image). +[Katib Trials](https://www.kubeflow.org/docs/components/katib/reference/architecture/#trial).
diff --git a/docs/images/SystemFlow.png b/docs/images/SystemFlow.png deleted file mode 100644 index 8a147437676f674c7b74da71acae8b0755c6a0e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 104398 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�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ⓈZiEF`fiwS23iCD{*mg)eIg=a*g=~S1v%5uR}v!>7a3Pm@ekoKMl!5d1ZMY z4cZ?GWX)Ct0!KUTd-uHV`}?0AuiwK@O5nMq4ka3|UOIKB#&K|hw=*%Q)xVhre8R;Th77rAY0)2u`n3vk9U{d zCV)xg^cXaDN<3GFd-PQkN{rCH7N~X<7iJiEy+_5IylLM4wDB3+35E)342VJbxI+9a zX$7c7BPiNQoTL+OQG)zb7St&NxbD6Au?OA3rc_%CC*?=xSXoHgl=9uXrbke8agYL1 z_G(I(aO9ddXsrq1lJjI80VHjRWYX!Vd*D1dzclhFfl3@4(B|VT%6QfH&ZzpiP@w(_ zT3wYhpf;27TFoWty^fx-jsVb9$AKfefs@s3yjrzz16AviC9t4omcPGUC4}Y#t(dif z4&gT-t`nmQ|L%MfiU7ENqg^r{G|bqdfs{OE(jiE~cqs(p0wuvDs zXV8`j1$?f8g_)Td{rwSvj;c=BH8W(EG_pR`C?(|bt22FMyp3S#YvI63u~y-qD}86Y zLM#|G(r*F2Ou{C*>4A)*l zk6(nt7=@`zD~9C@SVd=GVS3!04SNpMb}AvR{+=F&jbAa^w?}x4q=D;NzX|YCMS)dm z+q)wG3y~sLYoI>$n!<>4l2fD`r3B*Xy8YF$jqi{NrQ*-IUy?KHj$t^o=!*1y@FAR} zt z+6i;fzLsCPaCt5eaKVG`*G->fp%sA*B=-69`*5hEFMvs&)#5aWmGk32f>PM61(e5(T zq0TX(Kp-JlZ%{NhgrPzl1J=Ws4-&YN)FCTr^oO0_M`o!$ zD3oY*v?8vSZBP$#I$Nuoq1~<)l>yR5lSt>h=hdhn%S#BOJ4wqbI)+GgW$YggA2lWedKltCH&G8R}e@1K?B62 zJ0)kmzwv@Vw-E)H#`XL_702`B5UnPPKNl%Y*Gy59KC|(`SFC#s^$9TQ8So|PyMQZ> zhI7&K+f6rmZaBjJo|=1mdux4qps{PnfJ$*HiQ@)EnYaxa?Cv>=23r}lA=Ot^BqR{& zYb+NJmloQfZG%#i_XD5|wVnaEuPRZ(V88XF?Flci>5rjJM&P=oj`H}5l5~N?*zwRq zcnmKPMh3p9UV*CkP<(k2K}=xeoxAxa5)#BQ625;<043s<+68K^+Qp;3Ra)@6&UJIQ zfRJU!E#0^AO6BRiE8C|FSS(O`fiDIw!dvyTtZojo^N9D3tfKWpLJ3L8#B7uW}W>rW4e z`@hQ<>Ozew3H<@^xD*ooRNF73u<}PtmY0{$V*_!b z>0r5L$cSQk_}#w-W8|d@Sh2G~f|5I=RjhY+03$E4=2>3~a4nzEr>3NM--e8sAG{lR zMn*x_rAuSY1=*#4tRibW2qZk`_mHCVqkQ_*)AMe)yejtw{n|g-rc$9c*_aAW-p|Dz z0X+|nBT>xyL5`s=EDIy6mXZ|n4!Q8{E6lhKGlmaQp31@x4vaQ(eMp~ z1oYh8(aaaMDRf(l8wXSXZy3I@oMG+wsP3`Ur@0Iyogi0 zSg&bNZY5dC3QE%1`85RuSSx2Xm!;lzh`~*ouEb5S0+x%^duvO}&6<%ZSeOtWjSP%D zWXJanV2y%REm4tPSX|8Y-CsvCLDa!xT{#6*75Y_hfmd(^PIdF%@#+3dG?LpltaVo& z0FccOWTwF8l6((FAr$@v4N^smNf^X5^w}jYu{u(Njlb9A#oKbYK;nBoOypr724oFg!pPdR%R2)KSS0gfOKIq;xb&Mu{2Uj_8f;I_-Jp{@O)^L z#&fcbIAIIAqJDyUD)-spKtOQCj3_7pxy-&0G7zNo{mrW$lL28{;zKLi0;$2k$X=+9jc??>$Ez1R&ks6u2 zCNEVTfiS7aY-wdBfoCQIeQK@EEO*g{K&F8ebvXlH`vyI0@ATt+<4O0gsz2Brz`|N# z^M}{NdXNJFtcB@Ql*j@(5^6j6D0OBY_A!B7?-z(6cD!56h(Hoppl_oil7gQ@19%uV zzkn24`_u@cBMohBOHP?nFi@MoHT&_({&m}J=5)((Yw!FWt#9LFK>y@)xxLlZN(Z(7 zMBxb_4}fGZewzQ$ax%Y7)J@r*hBy9YQkQ-})Xve?=cAU)(?(Q(HM)lPekWFq-AM1z z`CLyNr-ng8`6v7Ha)F47mZM&x0q3SI1gQ1kBY8)<5}p%|LMMldnWR9--9NdPm;+D` z-}h4+*EJ@3)%B_RS|D(Z4#K_NAR{4>$Vf`sH@`2Eo}YLDeE|4>aaHE!q$PJg@sIwV ztg-#N37+5=w9|Y9S!9kN`Jk?Gp|f-7b*p~*6G%XIVbw_{KG;aUAYil3p9wUF(?LN{ z*Wfz^k69p-q;un%AP9C&8HD#r=6^v#gFG(3unTc|oDHyg>p^NTS(%*}R4#jnzm(p9w4+AxPFD34o6CGa|&_iZrg-vvS(7 zAS-%xwXW8&9&?d)KvC+mk}*F5cERjYZgj1GhTrz>z6_x6bTzxCDAE@lXL?^BVXQ*} zW~u^tf51eZN~fi#H$Mcf=SS^5iRgq84YVr0TSwv)K#c-pSk#MgU7pTnh~=Q3I*v@9 z!faNHQ2`z@di>j%H6ex>qpT%unMioOQQ z3h#E~_+vQYlqHoHok49mY(gF9`~CQUJo>e-h0$*v5|zq?u5eVTgp zp~F`hOq!=qx@mt!IInUaKz2aB@j>UyQ9%I#G!#iAkXf~=9eHgbBNH_8eEXhusqSYx zq17GG-!!OxQ^Ss$@@YxWBo1lX_`|Zl|H1|M%(?z~e+jV7=pI&ARY~@J{wy(BS_Oz^ zoK;{?N_hIC?>#OzxQ-|4U2@+pewxl)5U#$0T?fjoOFc>dT#%`!j4ymI;fu@>K*L1) zEBU;G*&#J9?D;avB+G3Ss_+Uht_JNf(D!vW(`SWM*?p)EdI7DK^Tv-!Sr3vIV1eY3 zu<{8~)6XhkuKQ&o%j{jhv$NCVBrooyH=2=nzz&^r2D(`A&DkD`&wxD}%)23CtHZB8 zOOu)RSG}xCOVG*mI^TwV_R@9vC8RYpLXmn!0RL)coF_G5bP2vA`lPt=jui}>M{6RF@Ym(ijFDgmTx*>ykiJ9(cr|A|x3tOM*cReq9{7bgp zdO3d{6qeO?jaBlIs`U;th$g)7dF;f9eA^pU+NqO(w=Q!Hd@%re?Jj!NKi+m*Q`+^< zvpy6Ni)x@;Ctm#!m{w@&N;d}0apn3H>rAsmx44>T9l8#-X3MRfLRMV6&FeL9!qGpx zNpi(Vv-?!vDC47qIhe2NV9$m5>GG;G-J=>6E>%k!WT!ghhtr}YahUO&ru{3Mn}nB@ z)=hH*=N<5Etn077Df=osway*a<*SaW&4@O%b{5y%3h-^bUf#u97k3*tssVm%dB2G< z^*aO%(Q2CpKfE1h@D)rhEA=;Qx+|=={!&5g`)bT-1Zq%cxb=&SYKmoG^gOv;PZrUK z!79l5z2VWC9cRa^%#Ewh^7pg05)k4KpE7PBwapOC$prTh=rx z?OHeAoeW6Q#O=+WzuS%8I|l9ZGOGxq1!2HGTGP8kyf)3o8vF9L)~!$yQc}k0B_vL- zphP_S{cQ`03t&F70lToCc$*?VP~~zapJIGq(tc|wqsH5Rl&gMv+ysl!Y%PCmaz(si z?YOPm9)!e&3e?i=n%Sc^LS{>GA-c8vd@^1rww>;traxDl@JEKej4Y|s<&X`39@)aKxza!615_RsUJnFId27NY;f1^6lqwYEEdeVGUH%ML3*cR_JU5T(A>?G|)C zT^T9SSrvTvVsE$Zun#-mUza1Om^N^KwKX>cY?`l*UZXOM- zXnTj+!I@-BW^~RDl**!+1P(JKxD+{8o#Fc|AA7l8U)zx;@-1e&+dM}EG;^+J^Eh)5 zjW~YJ+19yy^}PexGlvs%Hm7~EkBwZ57@!C%SWsAKSSUaOgtx-{d`GC~94!M?bp`0h zX}L+PO!Uop>=XYiOhD^$Cnm&Is}CwJWsLnHws+hvZWfjcDHPIl(C`~6*7_)_^t4cE zd*iBO+NGMi;d6aG-~sHzK0%?$kXvn$NVlavJ*N`L;iEy~5aX34B=uRasvUkuTUVWP z)n3n^bFkD8V1I02t*cAQ)x4{zTm-JBXLOb1_gCI`mV4khYyUX6K(p#7t#ZHi5Tb9P z%yRjwaNI^vs{xN~lP`_*2Wxsd#2aJ&7$@Hx-#-u>Td*n*GW^&(p@*b^1b3d8|V+tq|&QOf0=Vk1=hozkB+&3U2Rje&CHKp~g33LVt)CZ&JA(eqO4{ z(rZp^B~R~O0|6{A@AC)*>ImOIY9L%=eQ=Mh1gu`|{NpD3V=Hk_w13q+%xH!H>Kjq? zRUfO<&wZj^<`WmOM82$h)8?m=iTJ=WQL*_*E~GgdWGZ-dEDxm;?jh793kcRQ?_BKA zshMSP;BIQ1>3oX7^k3orwyw?mUzHSVLS$%6D*v|Y3WUZc>bTje%&1KAs#vA#wh0g$ z4)wCVw+~u;`}l5lg85`0Q<;C=ho{?Vk^4n8{6#2t(D;mK8Br--pQ$^ZFhKS(kU3f$ z&jQve(shGL-IEzL-!`X!Pn_iKm_4bwhIhN8kQK zQgmC|_Ek}F*|qER?APW_+>p%46QyO#reh6!pxbiAtOY~f zD+H_sAIr96((3gr5E3&j^!nUxe=ONZ2Kmkn6Blo_F5h}PBY($WWCqkR&p;IOa|M5- ziw;d@>ionu{Z1GkvKe*X1kJ;fNd46fJGPEoitb)4k#i&HH({636s6ekAMSX;ck%O6 zOA`AIVB$V%Cg#XOFl6eERa_v0JZa%g1M{NTEbIi@6ewQbR5Aue{?rIV7`b@|{`C;9 zvRYRo)%=0^HRNgzMNfN}Jjcj$)4gMR@f`~U+R9BJ0=7&t9y9Jiq@Ku7ge0s5>Q*k4 zAs&hba-(WvzL5$XN2z80GD(U8gtaTu{vwA5)_+n^`qAFdC;GS6*KF-6Wi7SdNC+(B zYiPBK4|I>tr%FtV^c3pd>QGQejmOBNYhG=_L9T235H<4iKQR;~dLfSzdlf@9EFT9` zkptmA(9F=3FduRS2B3e#mBtH1L%~HYyPNe+?b6&`lzx;=3l$YS^i9q{N|Y!R9-{ZG zDAQ_Lzgw@v?`3<}x)}HW_Itmh+#@HB25?2NZSo z#Qw8p_P~!Q+UPtK@5fQ_FgED}4N*D5$6Fb1D2S|rp6_8m_y@XQZ~jEgPm#S(EcuZb zSa$hs)edsE{;$`cNIPvg6*Y?~(C~h{Gj`zH%7T9*aRv6NyyHlyPP&?T^4Jr_4b=$W z%wRH-0irGzSH#Pl;f$>&QNgeG45Xo-Xs?p{vQhY8cw)QmH^64rMT()(ieu`{oMls^ zMiiak#i=@7GF}AjPEniu_=Src7Ek7FCp+?@zQj#2W=6H52rl6bJgZFkkZz&s!*~PX zU4)mE^eBweYTl%K-34vv?DQVWi3oFIW^lAG%b_zj$~BbV=vnB2*eHLZ){4tiq-!s2 zzQC{)rdCDcqdqkoYwz*G*L%@dp^7{fmi6LtaKTTrzaJovbf#3f7OMvMGK%?W<*aoz zv|dfLDkq25pAGkT#l!YCzm@$gMwyPF$&wxHX3Cq#?moVc`BVIAH8J-|eVzwyU_qr- z`PH%~_p4tfV0U{l7)+aslMoHzSfb%+-`0c+aj(I=r^m}Pms-jJgGBna^wD5re;+^) z{dZVDU)UDvV7o9qz+##isrVX^zdktp_^NaCXFSrbn~PGsGTl~%S6^)L$4FQN$J}@G zcX+gkha!H{!|M|wsnd1l`X&0L4p#~e8$R!b)ek_RyGF0P5tL_~G1NQWcW@+fgBx|3 zTqhr!iJo14&K`|9nB)1Gg2Zjyuu7Or!0POVJ9PgBtJ6oIt%!P1q^N{bQxvuk2S$zt#t2*joVsR5b^(ZVSjgXJ=2rG{sKqu)x}W}!5AT` z0JO(PUeNMUI!63FR>>=rD%9VhoFY@YCANN6A*XdmmHYDFk8jMzS$8?apGEc=@1WE~ zeZF<1poTUiG5r7XTS&0kqF;67zey|iqkYd*X;no_vgcV1Ps)ap+3FAg@3jvHayXb| zvmmuqE>uk&Wuu@n@1X)1>)-j!9l?zGt6QJ=2at7zF_<~9mEPWB3|O)=uC`1zP#vy# z?B}`9Lm-rQEXziJxDs`W+Jqk1r~kMa_NZeDdiv#OKSn!GWurH0>&0L!^ruI_$Qv$$ zDogCU;!!6g@cTd?<<>xkgefI7eCpj^x|}Ti@1VJyR4Ks7|2t-{0)6=6^m%A}>PPTJ zKb;42K9qKZ;7jfNu72mJ1HT5@+yd2sDC1g(l+*PQ`qDV}aexR@&Oc6j1nTKnO`Q(0 zWHWJJzJpI6{FG5%nj`d57vEAAqwu4TCh9V8BC!(bXg&(E{Rze*z1kSXNJ?PKm>s^G z6TeTy^ECEp)A_{MezKxUcjMaB<9_4);{yWMeo5box9c9<{hZ_Ds!!T}#6o-0X8ED8 zxIz|$cVa*@ipB})NR3Si*E>?SesNEk3++p$k<&>A1y0`Gt0?G)HaX_>>BIp%NJ5bbbNUu90t+Nk8(>VvX5H<3dn&nWKp< zcQMg;Vk9+gF(QVT)vs$8Odtl<4zNjpT$WXNxUXOa4#9@6v>GLCyZ z?(jtRukx8+Jf zQBf$+z}^Bu&qHwyda(@o#-hsS-<~xUQP}s&pd7_@T;dZUKqXhoWI;m=Q4cy%iPz1h zmX3}OBI~kMK!jUFGS18a>q*CrdJu3c(An^U%U=$>{5?Phr*o*}h$xF-i8=u1)s=!i ztz#tix#$;1Uj?Pd-;~f?3_VQqq-12yx7%YAxEN#tOh%$SniWxwb~4Z{)kQ9r9f6Z4 zk~1af<@8ZVuY4yLa2bT9rKJiDOsvs>e!nNs%yZrESBFU2p%x7k@C7{ACpQ5OT#Zjm z%+LX$G1Eoe7~532 z)G{R>w?Wd3@HLLTe(L?=(&$}Dv@fRHydT5E7*Nnt$klqIgM$PVvoB7j@@P>d7u z?0N()CAF!h<`8sHO?k=N?^TsQl7oeQ1fMzw1-sK!rR&@2@c{%c3tH`hI#J3A0?%r4 zv`X)r(Z9{9UV;C8CS0p+a}#TMXU9v4)h&;L8~@npVRK~^!>$dD*r%FklwBJ-S-FRp zu%n(2NytcGPnn#AjF79!seq394l66DY5@1O&?xWIvoed2ls|-lXTL2%vDWEP(3kOE z|H^5XewEv~_PlTHV4>v01A2NgQ~~ur@7ngdM4x}j^!Uy56_zOTF%DrH4Tc&0RGW^G zHo1~peErnJivvrJi!sL-i0G9Rs-M31k>IF0ipKgoY;<)r17rOY6r4P<`tXR$=(bTr zbyQr)gGQPg6ljF;MS6S@F-EmYek)+KvP0z(B<#hZb0pX+!3Sx-H=!5(-*yykc+@y)E&pHu< z($ZXL53+u{Jz0I>fs-w@`pvxHF-DfuF*#$f7+lkaC#Cg8a8X%Y8h^U}-)%;l*=FfO zVZYdS`eD%uvPr_a`KHzY> zHuxo_<4W%7U)wPIpSHpBS3J}qrjlY~t5~V=q~iXsfBJgv_?<4wFull^e{WC1G-5$1 zz`@)5unCkn7l~8N9j{V~+Si*Wo)aL?fZKmusIrV$kY-~jE-tQndMn#$B)V1z4L4ol zgl9tP;^y4^k2i-ljcD5Ydd}+}p6E1eN>P_WEFz+CMl`MVe2_D>$Yn5YsnE)|S9~AnGeJAX6 zl5?}4PzFighcCHjt!7 z;-CnJqwFrSq+u=4gD1fYW)-=LlgIJMjNah_
L=ACZyY>+oeUl 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%0Dq>7qF=xK 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 diff --git a/docs/new-algorithm-service.md b/docs/new-algorithm-service.md deleted file mode 100644 index 6955b53d1c1..00000000000 --- a/docs/new-algorithm-service.md +++ /dev/null @@ -1,185 +0,0 @@ -# Document about how to add a new algorithm in Katib - -## Implement a new algorithm and use it in Katib - -### Implement the algorithm - -The design of Katib follows the `ask-and-tell` pattern: - -> They often follow a pattern a bit like this: 1. ask for a new set of parameters 1. walk to the Experiment and program in the new parameters 1. observe the outcome of running the Experiment 1. walk back to your laptop and tell the optimizer about the outcome 1. go to step 1 - -When an Experiment is created, one algorithm service will be created. Then Katib asks for new sets of parameters via `GetSuggestions` GRPC call. After that, Katib creates new trials according to the sets and observe the outcome. When the trials are finished, Katib tells the metrics of the finished trials to the algorithm, and ask another new sets. - -The new algorithm needs to implement `Suggestion` service defined in [api.proto](../pkg/apis/manager/v1beta1/api.proto). One sample algorithm looks like: - -```python -from pkg.apis.manager.v1beta1.python import api_pb2 -from pkg.apis.manager.v1beta1.python import api_pb2_grpc -from pkg.suggestion.v1beta1.internal.search_space import HyperParameter, HyperParameterSearchSpace -from pkg.suggestion.v1beta1.internal.trial import Trial, Assignment -from pkg.suggestion.v1beta1.hyperopt.base_service import BaseHyperoptService -from pkg.suggestion.v1beta1.internal.base_health_service import HealthServicer - - -# Inherit SuggestionServicer and implement GetSuggestions. -class HyperoptService( - api_pb2_grpc.SuggestionServicer, HealthServicer): - def ValidateAlgorithmSettings(self, request, context): - # Optional, it is used to validate algorithm settings defined by users. - pass - def GetSuggestions(self, request, context): - # Convert the Experiment in GRPC request to the search space. - # search_space example: - # HyperParameterSearchSpace( - # goal: MAXIMIZE, - # params: [HyperParameter(name: param-1, type: INTEGER, min: 1, max: 5, step: 0), - # HyperParameter(name: param-2, type: CATEGORICAL, list: cat1, cat2, cat3), - # HyperParameter(name: param-3, type: DISCRETE, list: 3, 2, 6), - # HyperParameter(name: param-4, type: DOUBLE, min: 1, max: 5, step: )] - # ) - search_space = HyperParameterSearchSpace.convert(request.experiment) - # Convert the trials in GRPC request to the trials in algorithm side. - # trials example: - # [Trial( - # assignment: [Assignment(name=param-1, value=2), - # Assignment(name=param-2, value=cat1), - # Assignment(name=param-3, value=2), - # Assignment(name=param-4, value=3.44)], - # target_metric: Metric(name="metric-2" value="5643"), - # additional_metrics: [Metric(name=metric-1, value=435), - # Metric(name=metric-3, value=5643)], - # Trial( - # assignment: [Assignment(name=param-1, value=3), - # Assignment(name=param-2, value=cat2), - # Assignment(name=param-3, value=6), - # Assignment(name=param-4, value=4.44)], - # target_metric: Metric(name="metric-2" value="3242"), - # additional_metrics: [Metric(name=metric=1, value=123), - # Metric(name=metric-3, value=543)], - trials = Trial.convert(request.trials) - #-------------------------------------------------------------- - # Your code here - # Implement the logic to generate new assignments for the given current request number. - # For example, if request.current_request_number is 2, you should return: - # [ - # [Assignment(name=param-1, value=3), - # Assignment(name=param-2, value=cat2), - # Assignment(name=param-3, value=3), - # Assignment(name=param-4, value=3.22) - # ], - # [Assignment(name=param-1, value=4), - # Assignment(name=param-2, value=cat4), - # Assignment(name=param-3, value=2), - # Assignment(name=param-4, value=4.32) - # ], - # ] - list_of_assignments = your_logic(search_space, trials, request.current_request_number) - #-------------------------------------------------------------- - # Convert list_of_assignments to - return api_pb2.GetSuggestionsReply( - trials=Assignment.generate(list_of_assignments) - ) -``` - -### Make a GRPC server for the algorithm - -Create a package under [cmd/suggestion](../cmd/suggestion). Then create the main function and Dockerfile. The new GRPC server should serve in port 6789. - -Here is an example: [cmd/suggestion/hyperopt](../cmd/suggestion/hyperopt). -Then build the Docker image. - -### Use the algorithm in Katib. - -Update the [Katib config](../manifests/v1beta1/installs/katib-standalone/katib-config.yaml) with the new algorithm entity: - -```diff - runtime: - suggestions: - - algorithmName: random - image: docker.io/kubeflowkatib/suggestion-hyperopt:$(KATIB_VERSION) - - algorithmName: tpe - image: docker.io/kubeflowkatib/suggestion-hyperopt:$(KATIB_VERSION) -+ - algorithmName: -+ image: "image built in the previous stage":$(KATIB_VERSION) -``` - -Learn more about Katib config in the -[Kubeflow documentation](https://www.kubeflow.org/docs/components/katib/katib-config/) - -### Contribute the algorithm to Katib - -If you want to contribute the algorithm to Katib, you could add unit test and/or -e2e test for it in the CI and submit a PR. - -#### Unit Test - -Here is an example [test_hyperopt_service.py](../test/unit/v1beta1/suggestion/test_hyperopt_service.py): - -```python -import grpc -import grpc_testing -import unittest - -from pkg.apis.manager.v1beta1.python import api_pb2_grpc -from pkg.apis.manager.v1beta1.python import api_pb2 - -from pkg.suggestion.v1beta1.hyperopt.service import HyperoptService - -class TestHyperopt(unittest.TestCase): - def setUp(self): - servicers = { - api_pb2.DESCRIPTOR.services_by_name['Suggestion']: HyperoptService() - } - - self.test_server = grpc_testing.server_from_dictionary( - servicers, grpc_testing.strict_real_time()) - - -if __name__ == '__main__': - unittest.main() -``` - -You can setup the GRPC server using `grpc_testing`, then define your own test cases. - -#### E2E Test (Optional) - -E2E tests help Katib verify that the algorithm works well. -Follow below steps to add your algorithm (Suggestion) to the Katib CI -(replace `` with your Suggestion name): - -1. Submit a PR to add a new ECR private registry to the AWS - [`ECR_Private_Registry_List`](https://github.com/kubeflow/testing/blob/master/aws/IaC/CDK/test-infra/config/static_config/ECR_Resources.py#L18). - Registry name should follow the pattern: `katib/v1beta1/suggestion-` - -1. Create a new Experiment YAML in the [examples/v1beta1](../examples/v1beta1) - with the new algorithm. - -1. Update [`setup-katib.sh`](../test/e2e/v1beta1/scripts/setup-katib.sh) - script to modify `katib-config.yaml` with the new test Suggestion image name. - For example: - - ```sh - sed -i -e "s@docker.io/kubeflowkatib/suggestion-@${ECR_REGISTRY}/${REPO_NAME}/v1beta1/suggestion-@" ${CONFIG_PATCH} - ``` - -1. Update the following variables in [`argo_workflow.py`](../test/e2e/v1beta1/argo_workflow.py): - -- [`KATIB_IMAGES`](../test/e2e/v1beta1/argo_workflow.py#L43) with your Suggestion Dockerfile location: - -```diff - . . . - "suggestion-goptuna": "cmd/suggestion/goptuna/v1beta1/Dockerfile", - "suggestion-optuna": "cmd/suggestion/optuna/v1beta1/Dockerfile", -+ "suggestion-": "cmd/suggestion//v1beta1/Dockerfile", - . . . -``` - -- [`KATIB_EXPERIMENTS`](../test/e2e/v1beta1/argo_workflow.py#L69) with your Experiment YAML location: - -```diff - . . . - "multivariate-tpe": "examples/v1beta1/hp-tuning/multivariate-tpe.yaml", - "cmaes": "examples/v1beta1/hp-tuning/cma-es.yaml", -+ ": "examples/v1beta1/hp-tuning/.yaml", - . . . -``` diff --git a/docs/proposals/trial-custom-crd.md b/docs/proposals/1214-custom-crd-in-trial/README.md similarity index 99% rename from docs/proposals/trial-custom-crd.md rename to docs/proposals/1214-custom-crd-in-trial/README.md index a939f77011a..bd27edb5b4e 100644 --- a/docs/proposals/trial-custom-crd.md +++ b/docs/proposals/1214-custom-crd-in-trial/README.md @@ -1,4 +1,4 @@ -# Support custom CRD in Trial Job proposal +# KEP-1214: Support custom CRD in Trial Job proposal diff --git a/docs/proposals/conformance-test.md b/docs/proposals/2044-conformance-program/README.md similarity index 98% rename from docs/proposals/conformance-test.md rename to docs/proposals/2044-conformance-program/README.md index 900399a30de..7018c5e1af3 100644 --- a/docs/proposals/conformance-test.md +++ b/docs/proposals/2044-conformance-program/README.md @@ -1,4 +1,4 @@ -# Conformance Test for AutoML and Training Working Group +# KEP-2044: Conformance Test for AutoML and Training Working Group Andrey Velichkevich ([@andreyvelich](https://github.com/andreyvelich)) Johnu George ([@johnugeorge](https://github.com/johnugeorge)) @@ -61,7 +61,7 @@ the 3 category of tests: ## Design for the CRD-based tests -![conformance-crd-test](../images/conformance-crd-test.png) +![conformance-crd-test](conformance-crd-test.png) The design is similar to the KFP conformance program for the API-based tests. diff --git a/docs/images/conformance-crd-test.png b/docs/proposals/2044-conformance-program/conformance-crd-test.png similarity index 100% rename from docs/images/conformance-crd-test.png rename to docs/proposals/2044-conformance-program/conformance-crd-test.png diff --git a/docs/proposals/llm-hyperparameter-optimization-api.md b/docs/proposals/2339-hpo-for-llm-fine-tuning/README.md similarity index 95% rename from docs/proposals/llm-hyperparameter-optimization-api.md rename to docs/proposals/2339-hpo-for-llm-fine-tuning/README.md index 01f74f9a2fd..f3086f13b32 100644 --- a/docs/proposals/llm-hyperparameter-optimization-api.md +++ b/docs/proposals/2339-hpo-for-llm-fine-tuning/README.md @@ -1,13 +1,13 @@ -# HyperParameter Optimization API for LLM Fine-Tuning +# KEP-2339: HyperParameter Optimization API for LLM Fine-Tuning - [HyperParameter Optimization API for LLM Fine-Tuning](#hyperparameter-optimization-api-for-llm-fine-tuning) - * [Links](#links) - * [Motivation](#motivation) - * [Goals](#goals) - * [Non-Goals](#non-goals) - * [Design for API](#design-for-api) - + [Example](#example) - * [Implementation](#implementation) + - [Links](#links) + - [Motivation](#motivation) + - [Goals](#goals) + - [Non-Goals](#non-goals) + - [Design for API](#design-for-api) + - [Example](#example) + - [Implementation](#implementation) ## Links @@ -37,10 +37,10 @@ import kubeflow.katib as katib from kubeflow.katib import KatibClient class KatibClient(object): - + def tune( self, - name: str, + name: str, namespace: Optional[str] = None, model_provider_parameters: Optional[HuggingFaceModelParams] = None, dataset_provider_parameters: Optional[Union[HuggingFaceDatasetParams, S3DatasetParams]] = None, @@ -152,9 +152,9 @@ cl.tune( lora_dropout = 0.1, bias = "none", ), - ), - objective_metric_name = "train_loss", - objective_type = "minimize", + ), + objective_metric_name = "train_loss", + objective_type = "minimize", algorithm_name = "random", max_trial_count = 10, parallel_trial_count = 2, @@ -214,7 +214,7 @@ container_spec = client.V1Container( "--transformer_type", model_provider_parameters.transformer_type.__name__, "--model_dir", - "REPLACE_WITH_ACTUAL_MODEL_PATH", + "REPLACE_WITH_ACTUAL_MODEL_PATH", "--dataset_dir", "REPLACE_WITH_ACTUAL_DATASET_PATH", "--lora_config", @@ -228,7 +228,7 @@ container_spec = client.V1Container( **Hyperparameter Optimization**: This API will create an Experiment that defines the search space for identified tunable hyperparameters, the objective metric, optimization algorithm, etc. The Experiment will orchestrate the hyperparameter tuning process, generating Trials for each configuratin. Each Trial will be implemented as a Kubernete PyTorchJob, with the `trialTemplate` specifying the exact values for hyperparameters. The `trialTemplate` will also define master and worker containers, facilitating effective resource distribution and parallel execution of Trials. Trial results will then be fed back to the Experiment, which will evaluate the outcomes to identify the optimal set of hyperparameters. - **Dependencies Update**: To reuse existing assets from the Training Python SDK and integrate packages from HuggingFace, dependencies will be added to the `setup.py` of the Katib Python SDK as follows: +**Dependencies Update**: To reuse existing assets from the Training Python SDK and integrate packages from HuggingFace, dependencies will be added to the `setup.py` of the Katib Python SDK as follows: ```python setuptools.setup( diff --git a/docs/proposals/push-based-metrics-collection.md b/docs/proposals/2340-push-based-metrics-collector/README.md similarity index 98% rename from docs/proposals/push-based-metrics-collection.md rename to docs/proposals/2340-push-based-metrics-collector/README.md index 7f7020bb948..9bef7365253 100644 --- a/docs/proposals/push-based-metrics-collection.md +++ b/docs/proposals/2340-push-based-metrics-collector/README.md @@ -1,4 +1,4 @@ -# Push-based Metrics Collection Proposal +# KEP-2340: Push-based Metrics Collection Proposal ## Links @@ -12,11 +12,12 @@ In the procedure of tuning hyperparameters, Metrics Collector, which is implemen However, current implementation of Metrics Collector is pull-based, raising some [design problems](https://github.com/kubeflow/training-operator/issues/722#issuecomment-405669269) such as determining the frequency we scrape the metrics, performance issues like the overhead caused by too many sidecar containers, and restrictions on developing environments which must support sidecar containers. Thus, we should implement a new API for Katib Python SDK to offer users a push-based way to store metrics directly into the Katib DB and resolve those issues raised by pull-based metrics collection. -![](../images/push-based-metrics-collection.png) +![](./push-based-metrics-collection.png) Fig.1 Architecture of the new design ### Goals + 1. **A new parameter in Python SDK function `tune`**: allow users to specify the method of collecting metrics(push-based/pull-based). 2. **A new interface `report_metrics` in Python SDK**: push the metrics to Katib DB directly. @@ -24,11 +25,11 @@ Fig.1 Architecture of the new design 3. The final metrics of worker pods should be **pushed to Katib DB directly** in the push mode of metrics collection. ### Non-Goals + 1. Implement authentication model for Katib DB to push metrics. 2. Support pushing data to different types of storage system(prometheus, self-defined interface etc.) - ## API ### New Parameter in Python SDK Function `tune` @@ -58,9 +59,9 @@ def tune( packages_to_install: List[str] = None, pip_index_url: str = "https://pypi.org/simple", # The newly added parameter metrics_collector_config. - # It specifies the config of metrics collector, for example, + # It specifies the config of metrics collector, for example, # metrics_collector_config={"kind": "Push"}, - metrics_collector_config: Dict[str, Any] = {"kind": "StdOut"}, + metrics_collector_config: Dict[str, Any] = {"kind": "StdOut"}, ) ``` @@ -76,7 +77,7 @@ def tune( For examle, `metrics = {"loss": 0.01, "accuracy": 0.99}`. db-manager-address: Address for the Katib DB Manager in this format: `ip-address:port`. timeout: Optional, gRPC API Server timeout in seconds to report metrics. - + Raises: RuntimeError: Unable to push Trial metrics to Katib DB. """ @@ -138,7 +139,7 @@ As mentioned above, we decided to add `metrics_collector_config` to the tune fun ### New Interface `report_metrics` in Python SDK -We decide to implement this funcion to push metrics directly to Katib DB with the help of grpc. Trial name should always be passed into Katib Trials (and then into this function) as env variable `KATIB_TRIAL_NAME`. +We decide to implement this funcion to push metrics directly to Katib DB with the help of grpc. Trial name should always be passed into Katib Trials (and then into this function) as env variable `KATIB_TRIAL_NAME`. Also, the function is supposed to be implemented as **global function** because it is called in the user container. @@ -164,6 +165,7 @@ if jobStatus.Condition == trialutil.JobSucceeded && instance.Status.Observation return errMetricsNotReported } ``` + 1. Distinguish pull-based and push-based metrics collection We decide to add a if-else statement in the code above to distinguish pull-based and push-based metrics collection. In the push-based collection, the Trial does not need to be requeued. Instead, we'll insert a unavailable value to Katib DB. @@ -172,7 +174,6 @@ We decide to add a if-else statement in the code above to distinguish pull-based In the current implementation of pull-based metrics collection, Trials will be re-queued when the metrics collector finds the `.Status.Observation` is empty. However, it's not compatible with push-based metrics collection because the forgotten metrics won't be reported in the new round of reconcile. So, we need to update its status in the function `UpdateTrialStatusCondition` in accommodation with the pull-based metrics collection. The following code will be insert into lines before [trial_controller_util.go#L69](https://github.com/kubeflow/katib/blob/7959ffd54851216dbffba791e1da13c8485d1085/pkg/controller.v1beta1/trial/trial_controller_util.go#L69) - ```Golang else if instance.Spec.MetricCollector.Collector.Kind == "Push" { ... // Update the status of this Trial to `MetricsUnavailable` and output the reason. diff --git a/docs/images/push-based-metrics-collection.png b/docs/proposals/2340-push-based-metrics-collector/push-based-metrics-collection.png similarity index 100% rename from docs/images/push-based-metrics-collection.png rename to docs/proposals/2340-push-based-metrics-collector/push-based-metrics-collection.png diff --git a/docs/proposals/parameter-distribution.md b/docs/proposals/2374-parameter-distribution/README.md similarity index 99% rename from docs/proposals/parameter-distribution.md rename to docs/proposals/2374-parameter-distribution/README.md index ebe062c02d0..b6ca0fbc499 100644 --- a/docs/proposals/parameter-distribution.md +++ b/docs/proposals/2374-parameter-distribution/README.md @@ -1,4 +1,4 @@ -# Proposal for Supporting various parameter distributions in Katib +# KEP-2374: Proposal for Supporting various parameter distributions in Katib ## Summary The goal of this project is to enhance the existing Katib Experiment APIs to support various parameter distributions such as uniform, log-uniform, and qlog-uniform. Then extend the suggestion services to be able to configure distributions for search space using libraries provided in each framework. diff --git a/docs/proposals/suggestion.md b/docs/proposals/507-suggestion-crd/README.md similarity index 84% rename from docs/proposals/suggestion.md rename to docs/proposals/507-suggestion-crd/README.md index 75f44e83539..b083cbd1c5f 100644 --- a/docs/proposals/suggestion.md +++ b/docs/proposals/507-suggestion-crd/README.md @@ -1,28 +1,27 @@ -# Suggestion CRD Design Document - -Table of Contents -================= - - * [Suggestion CRD Design Document](#suggestion-crd-design-document) - * [Table of Contents](#table-of-contents) - * [Background](#background) - * [Goals](#goals) - * [Non-Goals](#non-goals) - * [Design](#design) - * [Kubernetes API](#kubernetes-api) - * [GRPC API](#grpc-api) - * [Workflow](#workflow) - * [Example](#example) - * [Algorithm Supports](#algorithm-supports) - * [Random](#random) - * [Grid](#grid) - * [Bayes Optimization](#bayes-optimization) - * [HyperBand](#hyperband) - * [BOHB](#bohb) - * [TPE](#tpe) - * [SMAC](#smac) - * [CMA-ES](#cma-es) - * [Sobol](#sobol) +# KEP-507: Suggestion CRD Design Document + +# Table of Contents + +- [Suggestion CRD Design Document](#suggestion-crd-design-document) +- [Table of Contents](#table-of-contents) + - [Background](#background) + - [Goals](#goals) + - [Non-Goals](#non-goals) + - [Design](#design) + - [Kubernetes API](#kubernetes-api) + - [GRPC API](#grpc-api) + - [Workflow](#workflow) + - [Example](#example) + - [Algorithm Supports](#algorithm-supports) + - [Random](#random) + - [Grid](#grid) + - [Bayes Optimization](#bayes-optimization) + - [HyperBand](#hyperband) + - [BOHB](#bohb) + - [TPE](#tpe) + - [SMAC](#smac) + - [CMA-ES](#cma-es) + - [Sobol](#sobol) Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc) @@ -118,7 +117,7 @@ message ExperimentSpec { } message ParameterSpecs { - repeated ParameterSpec parameters = 1; + repeated ParameterSpec parameters = 1; } message AlgorithmSpec { @@ -228,28 +227,28 @@ spec: algorithmName: random trialTemplate: goTemplate: - rawTemplate: |- - apiVersion: batch/v1 - kind: Job - metadata: - name: {{.Trial}} - namespace: {{.NameSpace}} - spec: - template: - spec: - containers: - - name: {{.Trial}} - image: katib/mxnet-mnist-example - command: - - "python" - - "/mxnet/example/image-classification/train_mnist.py" - - "--batch-size=64" - {{- with .HyperParameters}} - {{- range .}} - - "{{.Name}}={{.Value}}" - {{- end}} - {{- end}} - restartPolicy: Never + rawTemplate: |- + apiVersion: batch/v1 + kind: Job + metadata: + name: {{.Trial}} + namespace: {{.NameSpace}} + spec: + template: + spec: + containers: + - name: {{.Trial}} + image: katib/mxnet-mnist-example + command: + - "python" + - "/mxnet/example/image-classification/train_mnist.py" + - "--batch-size=64" + {{- with .HyperParameters}} + {{- range .}} + - "{{.Name}}={{.Value}}" + {{- end}} + {{- end}} + restartPolicy: Never parameters: - name: --lr parameterType: double @@ -265,9 +264,9 @@ spec: parameterType: categorical feasibleSpace: list: - - sgd - - adam - - ftrl + - sgd + - adam + - ftrl ``` Then, Experiment controller needs 3 parallel trials to run. It creates the Suggestions: diff --git a/docs/proposals/metrics-collector.md b/docs/proposals/685-metrics-collector/README.md similarity index 98% rename from docs/proposals/metrics-collector.md rename to docs/proposals/685-metrics-collector/README.md index 4a780c621c3..fd89fe5fcc0 100644 --- a/docs/proposals/metrics-collector.md +++ b/docs/proposals/685-metrics-collector/README.md @@ -1,4 +1,4 @@ -# Metrics Collector Proposal +# KEP-685: Metrics Collector Proposal - [Metrics Collector Proposal](#metrics-collector-proposal) - [Links](#links) @@ -33,7 +33,7 @@ In the new design, Katib use mutating webhook to inject metrics collector contai The sidecar collects metrics of the master and then store them on the persistent layer (e.x. katib-db-manager and metadata server).
- + Fig. 1 Architecture of the new design diff --git a/docs/images/metrics-collector-design.png b/docs/proposals/685-metrics-collector/metrics-collector-design.png similarity index 100% rename from docs/images/metrics-collector-design.png rename to docs/proposals/685-metrics-collector/metrics-collector-design.png diff --git a/docs/release/README.md b/docs/release/README.md index 75823be8068..74291c3d2a8 100644 --- a/docs/release/README.md +++ b/docs/release/README.md @@ -4,7 +4,7 @@ This is the instruction on how to make a new release for the Katib project. ## Prerequisite -- Tools, defined in the [Developer Guide](./../developer-guide.md#requirements). +- Tools, defined in the [Contributing Guide](./../../CONTRIBUTING.md#requirements). - [Write](https://docs.github.com/en/organizations/managing-access-to-your-organizations-repositories/repository-permission-levels-for-an-organization#permission-levels-for-repositories-owned-by-an-organization) permission for the Katib repository. diff --git a/docs/workflow-design.md b/docs/workflow-design.md index 76dac322bc0..006b606a3ab 100644 --- a/docs/workflow-design.md +++ b/docs/workflow-design.md @@ -1,5 +1,7 @@ # How Katib v1beta1 tunes hyperparameters automatically in a Kubernetes native way +TODO (andreyvelich): This doc is out of date. We should update it and move to the Kubeflow website. + Follow the Kubeflow documentation guides: - [Concepts](https://www.kubeflow.org/docs/components/katib/overview/)