1"use strict";(globalThis.webpackChunkmikes_dev_notebook=globalThis.webpackChunkmikes_dev_notebook||[]).push([[9680],{800947(e,n,a){a.r(n),a.d(n,{assets:()=>o,contentTitle:()=>i,default:()=>p,frontMatter:()=>l,metadata:()=>s,toc:()=>c});const s=JSON.parse('{"id":"IoT-and-Machine-Learning/AIOps/2024-02-24-mlflow-hyperparameter-tuning/index","title":"MLFlow Hyperparameter Tuning in Docker","description":"Experiment to run pyTorch, Jupyter, Hyperopt and MLFlow in Docker","source":"@site/docs/IoT-and-Machine-Learning/AIOps/2024-02-24-mlflow-hyperparameter-tuning/index.md","sourceDirName":"IoT-and-Machine-Learning/AIOps/2024-02-24-mlflow-hyperparameter-tuning","slug":"/IoT-and-Machine-Learning/AIOps/2024-02-24-mlflow-hyperparameter-tuning/2024-02-24","permalink":"/docs/IoT-and-Machine-Learning/AIOps/2024-02-24-mlflow-hyperparameter-tuning/2024-02-24","draft":false,"unlisted":false,"editUrl":"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/IoT-and-Machine-Learning/AIOps/2024-02-24-mlflow-hyperparameter-tuning/index.md","tags":[{"inline":true,"label":"Python","permalink":"/docs/tags/python"},{"inline":true,"label":"Machine Learning","permalink":"/docs/tags/machine-learning"},{"inline":true,"label":"MLFlow","permalink":"/docs/tags/ml-flow"},{"inline":true,"label":"Docker","permalink":"/docs/tags/docker"}],"version":"current","sidebarPosition":4569,"frontMatter":{"sidebar_position":4569,"slug":"2024-02-24","title":"MLFlow Hyperparameter Tuning in Docker","authors":"mpolinowski","tags":["Python","Machine Learning","MLFlow","Docker"],"description":"Experiment to run pyTorch, Jupyter, Hyperopt and MLFlow in Docker"},"sidebar":"tutorialSidebar","previous":{"title":"MLflow Integration for Ultralytics YOLO","permalink":"/docs/IoT-and-Machine-Learning/AIOps/2024-02-26-mlflow-with-yolov81/2024-02-26"},"next":{"title":"MLFlow with PyTorch Lighning in Docker","permalink":"/docs/IoT-and-Machine-Learning/AIOps/2024-02-21-mlflow-pytorch-lightning-docker/2024-02-21"}}');var r=a(474848),t=a(28453);const l={sidebar_position:4569,slug:"2024-02-24",title:"MLFlow Hyperparameter Tuning in Docker",authors:"mpolinowski",tags:["Python","Machine Learning","MLFlow","Docker"],description:"Experiment to run pyTorch, Jupyter, Hyperopt and MLFlow in Docker"},i="MLFlow Docker",o={},c=[{value:"Hyperopt",id:"hyperopt",level:2},{value:"MLFlow",id:"mlflow",level:2},{value:"Best Model Evaluation",id:"best-model-evaluation",level:2},{value:"Model Registry",id:"model-registry",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",img:"img",li:"li",p:"p",pre:"pre",ul:"ul",...(0,t.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"Guangzhou, China",src:a(926130).A+"",width:"1061",height:"405"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.a,{href:"#mlflow-docker",children:"MLFlow Docker"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#hyperopt",children:"Hyperopt"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#mlflow",children:"MLFlow"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#best-model-evaluation",children:"Best Model Evaluation"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.a,{href:"#model-registry",children:"Model Registry"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"mlflow-docker",children:"MLFlow Docker"})}),"\n",(0,r.jsxs)(n.p,{children:["Part 2 of ",(0,r.jsx)(n.a,{href:"/docs/IoT-and-Machine-Learning/AIOps/2024-02-21-mlflow-pytorch-lightning-docker/2024-02-21/",children:"MLFlow in Docker"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"hyperopt",children:"Hyperopt"}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://hyperopt.github.io/hyperopt/",children:"Distributed Asynchronous Hyper-parameter Optimization"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"pip install hyperopt\n"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"from hyperopt import fmin, tpe, hp, Trials\n"})}),"\n",(0,r.jsx)(n.p,{children:"Define the parameter you want to tune:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:'search_space = {\n "lr": hp.loguniform("lr", -10, -8),\n "l1": hp.choice("l1", [32, 64, 128]),\n "l2": hp.choice("l2", [64, 128, 256])\n}\n'})}),"\n",(0,r.jsx)(n.p,{children:"And replace all parameters inside the lightning model accordingly:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:'class EmnistModel(pl.LightningModule):\n def __init__(self, hparams):\n super().__init__()\n\n self.save_hyperparameters(hparams)\n \n self.criterion = nn.CrossEntropyLoss()\n\n self.network = nn.Sequential(\n nn.Conv2d(1,32,kernel_size=3,padding=1),\n nn.ReLU(),\n nn.Conv2d(32,64,kernel_size=3,padding=1),\n nn.ReLU(),\n nn.MaxPool2d(2,2), # 64*14*14\n\n nn.Conv2d(64,128,kernel_size=3,padding=1),\n nn.ReLU(),\n nn.Conv2d(128,256,kernel_size=3,padding=1),\n nn.ReLU(),\n nn.MaxPool2d(2,2), # 256*7*7\n\n nn.Flatten(),\n nn.Linear(256*7*7, self.hparams["l1"]),\n nn.ReLU(),\n\n nn.Linear(self.hparams["l1"], self.hparams["l2"]),\n nn.ReLU(),\n\n nn.Linear(self.hparams["l2"], 26) \n )\n\n def forward(self, xb):\n return self.network(xb.reshape(-1,1,28,28))\n\n def configure_optimizers(self):\n return optim.Adam(self.parameters(), lr = self.hparams["lr"])\n\n def training_step(self, batch, batch_idx):\n # batches consists of images and labels\n x, y = batch\n # labels start at 1 but the classes at 0\n y -= 1\n\n y_hat = self(x)\n loss
1= self.criterion(y_hat, y.long())\n pred = y_hat.argmax(dim = 1)\n\n acc = accuracy(pred, y, task="multiclass", num_classes=26)\n\n self.log("train_loss", loss, on_epoch=True, prog_bar=True)\n self.log("train_acc", acc, on_epoch=True, prog_bar=True)\n\n return loss\n\n def validation_step(self, batch, batch_idx):\n x, y = batch\n y -= 1\n\n y_hat = self(x)\n loss = self.criterion(y_hat, y.long())\n pred = y_hat.argmax(dim=1)\n\n acc = accuracy(pred, y, task="multiclass", num_classes=26)\n \n self.log("val_loss", loss, on_epoch=True, prog_bar=True)\n self.log("val_acc", acc, on_epoch=True, prog_bar=True)\n\n return acc\n\n def test_step(self, batch, batch_idx):\n x, y = batch\n y -= 1\n\n y_hat = self(x)\n loss = self.criterion(y_hat, y.long())\n pred = y_hat.argmax(dim=1)\n\n acc = accuracy(pred, y, task="multiclass", num_classes=26)\n \n self.log("test_loss", loss, on_epoch=True, prog_bar=True)\n self.log("test_acc", acc, on_epoch=True, prog_bar=True)\n\n return acc\n\n def predict_step(self, batch, batch_idx, dataloaders_idx=0):\n x, y = batch\n \n return self(x)\n'})}),"\n",(0,r.jsx)(n.h2,{id:"mlflow",children:"MLFlow"}),"\n",(0,r.jsx)(n.p,{children:"The model can now be executed with MLFlow:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:'def train_emnist(params):\n # create a group of mlflow runs that nests all experiments\n with mlflow.start_run(nested=True):\n model = EmnistModel(params)\n\n trainer = pl.Trainer(max_epochs=10, accelerator="gpu")\n trainer.fit(model, train_dataloaders=train_dl, val_dataloaders=val_dl)\n\n train_loss = trainer.callback_metrics["train_loss"].item()\n train_acc = trainer.callback_metrics["train_acc"].item()\n valid_loss = trainer.callback_metrics["val_loss"].item()\n valid_acc = trainer.callback_metrics["val_acc"].item()\n\n mlflow.log_params(params)\n\n mlflow.log_metrics({\n "train_loss_avg": train_loss, "train_acc_avg": train_acc,\n "val_loss_avg": valid_loss, "val_loss_avg": valid_acc\n })\n\n input_schema = Schema([TensorSpec(np.dtype(np.float32), (-1, 1, 28, 28))])\n output_schema = Schema([TensorSpec(np.dtype(np.float32), (-1, 26))])\n\n signature = ModelSignature(inputs=input_schema, outputs=output_schema)\n\n mlflow.pytorch.log_model(model, "emnist_classifier_hyper__cnn", signature=signature)\n\n return -valid_acc # run optimization to minimize negative validation accuracy\n'})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"with mlflow.start_run():\n best_result = fmin(\n fn=train_emnist,\n space=search_space,\n algo=tpe.suggest,\n max_evals=10\n )\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"MLFlow in Docker",src:a(549765).A+"",width:"1423",height:"640"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"MLFlow in Docker",src:a(830990).A+"",width:"1264",height:"639"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"MLFlow in Docker",src:a(820983).A+"",width:"1265",height:"558"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"MLFlow in Docker",src:a(241368).A+"",width:"1266",height:"559"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"MLFlow in Docker",src:a(514081).A+"",width:"1266",height:"556"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"MLFlow in Docker",src:a(565098).A+"",width:"1265",height:"545"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"MLFlow in Docker",src:a(415859).A+"",width:"1995",height:"829"})}),"\n",(0,r.jsx)(n.h2,{id:"best-model-evaluation",children:"Best Model Evaluation"}),"\n",(0,r.jsx)(n.p,{children:"The model with the best validation accuracy is:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"print(hyperopt.space_eval(search_space, best_result))\n# {'l1': 128, 'l2': 256, 'lr': 0.00013761616014749492}\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"MLFlow in Docker",src:a(120564).A+"",width:"1111",height:"872"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"# get run ID for the above model from the MLFlow dashboard\nlogged_model = 'runs:/80f82f97d942473aab55f5ba47df8db2/emnist_classifier_hyper__cnn'\n\n# Load model as a PyFuncModel.\nloaded_model = mlflow.pyfunc.load_model(logged_model)\n\npredictions = loaded_model.predict(test_images.numpy().reshape(-1,1,28,28))\n\nprint(\"Predicted Class:\", classes[np.argmax(predictions[0])])\n"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:'test_samples = np.random.randint(0, len(test_images), 16)\n\nfig = plt.figure(figsize = (8, 8))\n\nfor i, idx in enumerate(test_samples):\n true_label = classes[int(test_labels[idx].item()) - 1]\n pred_label = classes[np.argmax(predictions[idx])]\n \n plt.subplot(4, 4, i+1)\n plt.imshow(test_images[idx].numpy().reshape(-1,1,28,28).squeeze() / 255.0, cmap="gray")\n plt.title(f"True: {true_label} || Pred: {pred_label}")\n plt.axis(\'off\')\n\nplt.tight_layout()\nplt.show()\n'})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"MLFlow in Docker",src:a(341693).A+"",width:"1180",height:"787"})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:"y_pred = []\ny_true = []\n\nfor inputs, labels in test_dl:\n output = loaded_model.predict(inputs.numpy().reshape(-1,1,28,28))\n\n output = np.argmax(output, axis=1).astype('float64').tolist()\n y_pred.extend(output)\n\n labels = [x-1 for x in labels.tolist()]\n y_true.extend(labels)\n\ncm = confusion_matrix(y_true, y_pred)\nconfusion = ConfusionMatrixDisplay(cm, display_labels=classe
1s)\n\nfig, ax = plt.subplots(figsize = (12,8))\nconfusion.plot(ax = ax)\n"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"MLFlow in Docker",src:a(285959).A+"",width:"1184",height:"708"})}),"\n",(0,r.jsx)(n.h2,{id:"model-registry",children:"Model Registry"}),"\n",(0,r.jsx)(n.p,{children:"Once you picked a model to be the best model for your task you can register it in the MLFlow model registry:"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"MLFlow in Docker",src:a(110174).A+"",width:"1283",height:"615"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"MLFlow in Docker",src:a(430549).A+"",width:"1284",height:"240"})}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"MLFlow in Docker",src:a(518924).A+"",width:"1282",height:"384"})})]})}function p(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},549765(e,n,a){const s=a.p+"assets/images/MLFlow_Docker_01-50b2448b84544a46f34065497cc65117.png";a.d(n,["A",0,s])},830990(e,n,a){const s=a.p+"assets/images/MLFlow_Docker_02-9cf3f8596b7fb0eb12eecdc58e77c15c.png";a.d(n,["A",0,s])},820983(e,n,a){const s=a.p+"assets/images/MLFlow_Docker_03-4cc727c8ac90bd7764c16437b29e8b89.png";a.d(n,["A",0,s])},241368(e,n,a){const s=a.p+"assets/images/MLFlow_Docker_04-53c8ecd2750dc83ec1e06c5c0e74ebd1.png";a.d(n,["A",0,s])},514081(e,n,a){const s=a.p+"assets/images/MLFlow_Docker_05-b840dc3a4c554c1ffdd48eb941cedfe9.png";a.d(n,["A",0,s])},565098(e,n,a){const s=a.p+"assets/images/MLFlow_Docker_06-14d8951795939abe78c2a37e16939f03.png";a.d(n,["A",0,s])},415859(e,n,a){const s=a.p+"assets/images/MLFlow_Docker_07-62209b4221dc19c0f71687d50b08433a.png";a.d(n,["A",0,s])},120564(e,n,a){const s=a.p+"assets/images/MLFlow_Docker_08-041627a2baf9d53afc9260e9fd9a885c.png";a.d(n,["A",0,s])},341693(e,n,a){const s=a.p+"assets/images/MLFlow_Docker_09-995324ae84fe1df36fa5d8834b238c86.png";a.d(n,["A",0,s])},285959(e,n,a){const s=a.p+"assets/images/MLFlow_Docker_10-3d3b7b8dc1a80906ae7d26a0395abbf1.png";a.d(n,["A",0,s])},110174(e,n,a){const s=a.p+"assets/images/MLFlow_Docker_11-bcc64bf096159eef2bd8f577c8d625f7.png";a.d(n,["A",0,s])},430549(e,n,a){const s=a.p+"assets/images/MLFlow_Docker_12-6a15cf144c15b397e0b0869ba46b6b3d.png";a.d(n,["A",0,s])},518924(e,n,a){const s=a.p+"assets/images/MLFlow_Docker_13-4ca47279d29bd08b79846d86a6336965.png";a.d(n,["A",0,s])},926130(e,n,a){const s=a.p+"assets/images/photo-kt443t6d_64hdh43hfh6dgjdfhg4_d-fe9bbb57ea8da08fea2f3fef2bf2515b.jpg";a.d(n,["A",0,s])},28453(e,n,a){a.d(n,{R:()=>l,x:()=>i});var s=a(296540);const r={},t=s.createContext(r);function l(e){const n=s.useContext(t);return s.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:l(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.