{"id":22039392,"url":"https://github.com/mpolinowski/tf-i-know-flowers","last_synced_at":"2026-05-03T16:33:03.753Z","repository":{"id":189505142,"uuid":"680791359","full_name":"mpolinowski/tf-i-know-flowers","owner":"mpolinowski","description":"Tensorflow image classifier Keras Applications model comparison","archived":false,"fork":false,"pushed_at":"2023-08-20T13:04:32.000Z","size":7982,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-23T13:14:11.517Z","etag":null,"topics":["image-classifier","keras-application","model-deployment","model-evaluation-and-selection","tensorflow-serving","tensorflow2"],"latest_commit_sha":null,"homepage":"https://mpolinowski.github.io/docs/IoT-and-Machine-Learning/ML/2023-08-01-tensorflow-i-know-flowers-intro/2023-08-01","language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mpolinowski.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-08-20T12:20:44.000Z","updated_at":"2023-08-20T13:02:10.000Z","dependencies_parsed_at":"2023-08-20T14:54:15.597Z","dependency_job_id":null,"html_url":"https://github.com/mpolinowski/tf-i-know-flowers","commit_stats":null,"previous_names":["mpolinowski/tf-i-know-flowers"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mpolinowski/tf-i-know-flowers","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpolinowski%2Ftf-i-know-flowers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpolinowski%2Ftf-i-know-flowers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpolinowski%2Ftf-i-know-flowers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpolinowski%2Ftf-i-know-flowers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mpolinowski","download_url":"https://codeload.github.com/mpolinowski/tf-i-know-flowers/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpolinowski%2Ftf-i-know-flowers/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32577122,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T06:36:36.687Z","status":"ssl_error","status_checked_at":"2026-05-03T06:36:09.306Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["image-classifier","keras-application","model-deployment","model-evaluation-and-selection","tensorflow-serving","tensorflow2"],"created_at":"2024-11-30T11:10:35.727Z","updated_at":"2026-05-03T16:33:03.732Z","avatar_url":"https://github.com/mpolinowski.png","language":"Jupyter Notebook","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tf Image Classifier\n\n## Model Training\n\n* [Evaluation Overview](/notebooks/)\n  * [EfficientNetV2B0](https://mpolinowski.github.io/docs/IoT-and-Machine-Learning/ML/2023-08-04-tensorflow-i-know-flowers-efficientnetv2b0/2023-08-04)\n  * [EfficientNetV2S](https://mpolinowski.github.io/docs/IoT-and-Machine-Learning/ML/2023-08-05-tensorflow-i-know-flowers-efficientnetv2s/2023-08-05)\n  * [Xception](https://mpolinowski.github.io/docs/IoT-and-Machine-Learning/ML/2023-08-12-tensorflow-i-know-flowers-xception/2023-08-12)\n  * [InceptionV3](https://mpolinowski.github.io/docs/IoT-and-Machine-Learning/ML/2023-08-06-tensorflow-i-know-flowers-inceptionv3/2023-08-06)\n  * [NASNetMobile](https://mpolinowski.github.io/docs/IoT-and-Machine-Learning/ML/2023-08-10-tensorflow-i-know-flowers-nasnetmobile/2023-08-10)\n  * [MobileNetV3Small](https://mpolinowski.github.io/docs/IoT-and-Machine-Learning/ML/2023-08-09-tensorflow-i-know-flowers-mobilenetv3small/2023-08-09)\n  * [MobileNetV3Large](https://mpolinowski.github.io/docs/IoT-and-Machine-Learning/ML/2023-08-08-tensorflow-i-know-flowers-mobilenetv3large/2023-08-08)\n  * [MobileNetV2](https://mpolinowski.github.io/docs/IoT-and-Machine-Learning/ML/2023-08-07-tensorflow-i-know-flowers-mobilenetv2/2023-08-07)\n  * [vit-base-patch16-224](https://mpolinowski.github.io/docs/IoT-and-Machine-Learning/ML/2023-08-11-tensorflow-i-know-flowers-vit/2023-08-11)\n  * [DeiT](https://mpolinowski.github.io/docs/IoT-and-Machine-Learning/ML/2023-08-03-tensorflow-i-know-flowers-deit/2023-08-03)\n\n\n![Tf Image Classifier](./notebooks/assets/Model_Eval_04.webp)\n\n\n![Tf Image Classifier](./notebooks/assets/Model_Eval_07.webp)\n\n\n### Docker Setup\n\n```bash\ndocker pull tensorflow/tensorflow:latest-gpu-jupyter\n```\n\nAll notebooks mounted into `/tf/notebooks` will be accessible from the served Jupyter Notebook. After running the command you can access the Jupyter UI on `localhost:8888`:\n\n```bash\ndocker run --gpus all --rm -p 8888:8888 --name tf-notebook \\\n--mount type=bind,source=$(pwd),target=/tf/notebooks \\\ntensorflow/tensorflow:latest-gpu-jupyter\n```\n\n```bash\nTo access the notebook, open this file in a browser:\n        file:///root/.local/share/jupyter/runtime/nbserver-1-open.html\n    Or copy and paste one of these URLs:\n        http://b62cc9c31655:8888/?token=484cd6b995e8dc53f878795f00a83015c74410771882141c\n     or http://127.0.0.1:8888/?token=484cd6b995e8dc53f878795f00a83015c74410771882141c\n```\n\n\n![Tf Image Classifier](./notebooks/assets/Model_Eval_08.webp)\n\n\n## Model Serving\n\nI am going to use the official Tensorflow `tensorflow-serving` Docker container to deploy the model:\n\n* [Tensorflow Docker Model Server](https://mpolinowski.github.io/docs/IoT-and-Machine-Learning/AIOps/2023-01-01-tf-model-server/2023-01-01/)\n\n\nSimply point the source directory to the model save path that you want to use, e.g. `Efficientv2B0`:\n\n\n```bash\ndocker run --gpus all -p 8501:8501 --name tf-serve \\\n--mount type=bind,source=$(pwd)/saved_model,target=/models \\\n-e MODEL_NAME=efficientv2b0_model -t tensorflow/serving:latest-gpu\n```\n\n\n### Inference Server\n\n#### REST API\n\nFor testing I will just start a simple python container and install my dependencies manually:\n\n```bash\ndocker run --rm -ti --network host \\\n--mount type=bind,source=$(pwd)/api_request,target=/opt/app \\\npython:alpine /bin/ash\n```\n\n\n```bash\npip install pillow requests numpy\n```\n\nExecuting the API request script `/opt/app/api_request/rest_request.py` inside the container will send 1 of 3 test images to the Tensorflow model API to retrieve a prediction:\n\n\n```bash\npython /opt/app/rest_request.py\n\nClass probabilities:  [[2.02370361e-13 5.45808624e-12 3.14568647e-17 4.50543422e-11\n  1.74268600e-09 2.22335952e-12 5.15965439e-12 2.28333991e-10\n  3.17855503e-18 3.61456546e-12 1.40493947e-17 1.46841839e-09\n  3.42843321e-13 2.59899831e-16 2.68869540e-12 1.53930095e-08\n  1.36200578e-12 6.06594810e-16 2.21194929e-14 5.79839779e-17\n  1.05216942e-12 6.55278443e-10 2.30210545e-13 6.22206000e-15\n  5.16498033e-16 1.86334712e-15 7.34451477e-09 9.92521278e-13\n  1.40660292e-08 5.47506651e-10 3.36575397e-16 1.56563315e-12\n  4.54165000e-09 4.07618221e-13 1.69515952e-05 1.08003778e-05\n  2.42027980e-08 1.65058089e-09 1.25125591e-13 4.95898966e-09\n  1.62804418e-16 5.25978046e-17 1.91704139e-14 2.93358880e-18\n  3.04848768e-08 1.63559369e-14 9.99972224e-01 2.25344784e-10]]\n\nPredicted class:  Viola\n```\n\n\n## Serving Multiple Models\n\nOk, with this working I want to configure the Model Server to serve all the trained models.\n\n\n```bash\ntree -L 2 saved_model\n\nsaved_model\n├── deit_model\n│   └── 1\n├── efficients_model\n│   └── 1\n├── efficientv2b0_model\n│   └── 1\n├── inception_model_model_ft\n│   └── 1\n├── mobilenet2_model_ft\n│   └── 1\n├── mobilenetv3L_model_ft\n│   └── 1\n├── mobilenetv3S_model\n│   └── 1\n├── nasnetmobile_model_ft\n│   └── 1\n├── vit_model\n│   └── 1\n└── xception_model\n    └── 1\n```\n\nFor this we have to add a [models.config](https://www.tensorflow.org/tfx/serving/serving_config) file inside the `models` container. The configuration file can then be added by adding the following flags (the automatic reload is optional):\n\n\n```bash\ndocker run -t --rm -p 8501:8501 --name tf-serve \\\n    --mount type=bind,source=$(pwd)/saved_model,target=/models \\\n    tensorflow/serving:latest-gpu \\\n    --model_config_file=/models/models.config \\\n    --model_config_file_poll_wait_seconds=60\n```\n\n\n_./saved\\_model/models.config_\n\n\n```bash\nmodel_config_list {\n  config {\n    name: 'efficientv2b0_model'\n    base_path: '/models/efficientv2b0_model/'\n    model_platform: 'tensorflow'\n    model_version_policy {\n    specific {\n      versions: 1\n      }\n    }\n  }\n  config {\n    name: 'mobilenetv3S_model'\n    base_path: '/models/mobilenetv3S_model/'\n    model_platform: 'tensorflow'\n    model_version_policy {\n    specific {\n      versions: 1\n      }\n    }\n  }\n  config {\n    name: 'vit_model'\n    base_path: '/models/vit_model/'\n    model_platform: 'tensorflow'\n    model_version_policy {\n    specific {\n      versions: 1\n      }\n    }\n  }\n}\n```\n\nStarting up the container I can now see that Tensorflow is reloading all three models in a 60s interval:\n\n\n```bash\ntensorflow_serving/model_servers/server.cc:430] Exporting HTTP/REST API at:localhost:8501 ...\ntensorflow_serving/model_servers/server_core.cc:465] Adding/updating models.\ntensorflow_serving/model_servers/server_core.cc:594]  (Re-)adding model: efficientv2b0_model\ntensorflow_serving/model_servers/server_core.cc:594]  (Re-)adding model: mobilenetv3S_model\ntensorflow_serving/model_servers/server_core.cc:594]  (Re-)adding model: vit_model\ntensorflow_serving/model_servers/server_core.cc:486] Finished adding/updating models\n```\n\n\nI now added the URL for all three models to the Python request script:\n\n\n```python\nurl1 = 'http://localhost:8501/v1/models/efficientv2b0_model:predict'\nurl2 = 'http://localhost:8501/v1/models/mobilenetv3S_model:predict'\nurl3 = 'http://localhost:8501/v1/models/vit_model:predict'\n```\n\n\nThat will now return 3 predictions:\n\n\n```bash\npython /opt/app/rest_request.py\nPrediction Results: EfficientV2B0\nClass probabilities:  [[1.27231669e-18 7.36642785e-15 2.12142088e-16 8.37840160e-13\n  2.54633266e-15 2.23082670e-22 1.22582740e-17 1.58766519e-16\n  3.15969443e-21 3.40760905e-12 9.31879706e-21 1.35364190e-16\n  4.19998346e-13 6.28031038e-19 1.42876893e-08 1.52733778e-16\n  1.71126649e-18 6.26449727e-18 1.70084369e-22 5.93363685e-27\n  1.35457736e-23 9.82926604e-26 1.07540425e-15 1.03456081e-16\n  5.33486490e-14 1.70107328e-19 1.25875951e-20 1.54503871e-19\n  2.05770212e-19 9.31224634e-16 2.43002143e-25 1.00000000e+00\n  1.49300737e-20 6.64273082e-17 4.00534170e-18 3.18333764e-19\n  1.38794318e-24 5.08237766e-13 4.06667683e-19 4.50689589e-13\n  4.09000394e-16 6.34139226e-13 2.21711468e-24 3.38089155e-23\n  1.83935487e-19 3.32891393e-19 1.46283768e-16 3.42905371e-23]]\nPredicted class:  Nymphaea_Tetragona\nCertainty:  100.0 %\nPrediction Results: MobileNetV3S\nClass probabilities:  [[6.27168000e-08 9.36711274e-07 3.32008640e-05 1.82103206e-04\n  3.65090000e-05 7.08905601e-10 5.29715000e-09 2.18803660e-08\n  1.43549421e-08 2.40992620e-07 2.09935107e-12 9.32755886e-11\n  1.55253754e-10 2.58531685e-08 1.72480277e-03 9.44796508e-09\n  1.51912500e-12 3.97989908e-07 4.73708963e-13 2.97169041e-14\n  4.57825137e-14 4.23965169e-11 4.12751433e-07 1.92947700e-05\n  8.95965513e-06 5.97457550e-09 4.81428591e-13 3.20082150e-13\n  1.89814697e-09 9.56469748e-09 3.24247695e-09 9.97930884e-01\n  9.90472593e-09 2.25990516e-06 2.97242941e-09 4.48806965e-08\n  8.23452157e-12 5.94276535e-05 3.16433564e-08 3.98971480e-07\n  2.16912586e-08 8.35711322e-09 1.56445000e-12 1.42842169e-10\n  2.86222768e-10 7.43138450e-12 1.27389072e-10 1.44366144e-10]]\nPredicted class:  Nymphaea_Tetragona\nCertainty:  99.793 %\nPrediction Results: ViT\nClass probabilities:  [[2.62611400e-04 9.45560227e-04 7.97024090e-03 2.50866893e-03\n  5.62246714e-04 9.96018527e-04 5.78884617e-04 1.15711347e-03\n  1.87621685e-03 2.56323745e-03 1.19275635e-03 5.13695000e-04\n  8.98167782e-04 4.11458139e-04 1.77495480e-02 3.71844682e-04\n  3.45975481e-04 1.64183730e-04 1.62366749e-04 4.10321372e-04\n  5.85561967e-04 4.59756848e-04 7.18721712e-04 2.03839969e-03\n  2.18398985e-03 8.30425473e-04 5.62683621e-04 1.05744123e-03\n  1.08664425e-03 8.36106890e-04 4.69557708e-04 9.25359428e-01\n  7.82242860e-04 8.19175097e-04 4.58333000e-04 2.90713477e-04\n  2.36424108e-04 8.55224300e-03 6.25506684e-04 9.37757781e-04\n  5.16826578e-04 4.17304225e-03 5.67917000e-04 4.71120235e-04\n  7.65961187e-04 7.77638000e-04 1.47661043e-03 7.18727824e-04]]\nPredicted class:  Nymphaea_Tetragona\nCertainty:  92.536 %\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmpolinowski%2Ftf-i-know-flowers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmpolinowski%2Ftf-i-know-flowers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmpolinowski%2Ftf-i-know-flowers/lists"}