{"id":24746615,"url":"https://github.com/samuelmarks/ml-params","last_synced_at":"2026-04-18T14:35:19.755Z","repository":{"id":150265345,"uuid":"275791838","full_name":"SamuelMarks/ml-params","owner":"SamuelMarks","description":"Consistent CLI and Python SDK API for every popular ML framework.","archived":false,"fork":false,"pushed_at":"2022-05-29T23:26:14.000Z","size":197,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-23T01:27:45.552Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SamuelMarks.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-06-29T11:19:59.000Z","updated_at":"2022-05-26T18:03:32.000Z","dependencies_parsed_at":null,"dependency_job_id":"cc033742-d99b-43a5-b514-d60326ae4909","html_url":"https://github.com/SamuelMarks/ml-params","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/SamuelMarks/ml-params","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamuelMarks%2Fml-params","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamuelMarks%2Fml-params/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamuelMarks%2Fml-params/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamuelMarks%2Fml-params/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SamuelMarks","download_url":"https://codeload.github.com/SamuelMarks/ml-params/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SamuelMarks%2Fml-params/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31972524,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T00:39:45.007Z","status":"online","status_checked_at":"2026-04-18T02:00:07.018Z","response_time":103,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2025-01-28T04:29:41.222Z","updated_at":"2026-04-18T14:35:19.731Z","avatar_url":"https://github.com/SamuelMarks.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"ml_params\n=========\n![Python version range](https://img.shields.io/badge/python-3.5%20|%203.6%20|%203.7%20|%203.8%20|%203.9%20|%203.10%20|%203.11.0b1-blue.svg)\n![Python implementation](https://img.shields.io/badge/implementation-cpython-blue.svg)\n[![License](https://img.shields.io/badge/license-Apache--2.0%20OR%20MIT-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![Linting, testing, and coverage](https://github.com/SamuelMarks/ml-params/workflows/Linting,%20testing,%20and%20coverage/badge.svg)](https://github.com/SamuelMarks/ml-params/actions)\n![Tested OSs, others may work](https://img.shields.io/badge/Tested%20on-Linux%20|%20macOS%20|%20Windows-green)\n![Documentation coverage](.github/doccoverage.svg)\n[![codecov](https://codecov.io/gh/SamuelMarks/ml-params/branch/master/graph/badge.svg)](https://codecov.io/gh/SamuelMarks/ml-params)\n[![black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat\u0026labelColor=ef8336)](https://pycqa.github.io/isort/)\n\nConsistent CLI and Python SDK API for †every popular ML framework.\n\n†that's the goal anyway! - PR or just suggestions for other ML frameworks to add are welcome :grin:\n\nThe approach is type-focussed, with explicit static code-generation of `Literal`ally:\n\n  - Transfer learning models\n  - Optimizers\n  - Loss functions\n  - \u0026etc., including non-NN related [scikit.learn](https://scikit-learn.org), [XGBoost](https://xgboost.ai)\n\nFor example, the following would be exposed, and thereby become useful from Python, in GUIs, REST/RPC APIs, and CLIs:\n```python\nfrom typing import Literal\n\nlosses = Literal['BinaryCrossentropy', 'CategoricalCrossentropy', 'CategoricalHinge', 'CosineSimilarity', 'Hinge',\n                 'Huber', 'KLD', 'KLDivergence', 'LogCosh', 'MAE', 'MAPE', 'MSE', 'MSLE', 'MeanAbsoluteError',\n                 'MeanAbsolutePercentageError', 'MeanSquaredError', 'MeanSquaredLogarithmicError', 'Poisson',\n                 'Reduction', 'SparseCategoricalCrossentropy', 'SquaredHinge']\n```\n\n## Developer guide\n\nThe [cdd](https://github.com/offscale/cdd-python) project was developed to make ml-params—and its implementations—possible… without a ridiculous amount of hand-written duplication. The duplication is still present, but cdd will automatically keep them in sync, multi-directionally. So you can edit any of these, and it'll translate the changes until every 'interface' is equivalent:\n\n  - CLI (and GUI from this)\n  - Class\n  - Function/method\n  - SQL model (SQLalchemy)\n\nIt will also expand a specific property, like your `get_losses` function could generate the aforementioned `Literal`.\n\n## Install dependencies\n\n    pip install -r requirements.txt\n\n## Install package\n\n    pip install .\n\n## Usage\n\n    $ python -m ml_params --help\n    usage: python -m ml_params [-h] [--version] [--engine {tensorflow}]\n    \n    Consistent CLI for every popular ML framework.\n    \n    optional arguments:\n      -h, --help            show this help message and exit\n      --version             show program's version number and exit\n      --engine {tensorflow}\n                            ML engine, e.g., \"TensorFlow\", \"JAX\", \"pytorch\"\n    usage: python -m ml_params [-h] [--version] [--engine {tensorflow}]\n\nNote that this is dynamic, so if you set `--engine` or the `ML_PARAMS_ENGINE` environment variable, you'll get this output:\n\n    $ python -m ml_params --engine 'tensorflow' --help\n    usage: python -m ml_params [-h] [--version] [--engine {tensorflow}] {load_data,load_model,train} ...\n    \n    Consistent CLI for every popular ML framework.\n    \n    positional arguments:\n      {load_data,load_model,train}\n                            subcommand to run. Hacked to be chainable.\n    \n    optional arguments:\n      -h, --help            show this help message and exit\n      --version             show program's version number and exit\n      --engine {tensorflow}\n                            ML engine, e.g., \"TensorFlow\", \"JAX\", \"pytorch\"\n\n### TensorFlow example\n\nFirst let's get some help text:\n\n#### `load_data`\n\n    $ python -m ml_params --engine 'tensorflow' load_data --help\n    usage: python -m ml_params load_data [-h] --dataset_name\n                                         {boston_housing,cifar10,cifar100,fashion_mnist,imdb,mnist,reuters}\n                                         [--data_loader {np,tf}]\n                                         [--data_type DATA_TYPE]\n                                         [--output_type OUTPUT_TYPE] [--K {np,tf}]\n                                         [--data_loader_kwargs DATA_LOADER_KWARGS]\n    \n    Load the data for your ML pipeline. Will be fed into `train`.\n    \n    optional arguments:\n      -h, --help            show this help message and exit\n      --dataset_name {boston_housing,cifar10,cifar100,fashion_mnist,imdb,mnist,reuters}\n                            name of dataset\n      --data_loader {np,tf}\n                            function that returns the expected data type.\n      --data_type DATA_TYPE\n                            incoming data type\n      --output_type OUTPUT_TYPE\n                            outgoing data_type\n      --K {np,tf}           backend engine, e.g., `np` or `tf`\n      --data_loader_kwargs DATA_LOADER_KWARGS\n                            pass this as arguments to data_loader function\n\n#### `load_model`\n\n    $ python -m ml_params --engine 'tensorflow' load_model --help\n    usage: python -m ml_params load_model [-h] --model\n                                          {DenseNet121,DenseNet169,DenseNet201,EfficientNetB0,EfficientNetB1,EfficientNetB2,EfficientNetB3,EfficientNetB4,EfficientNetB5,EfficientNetB6,EfficientNetB7,InceptionResNetV2,InceptionV3,MobileNet,MobileNetV2,NASNetLarge,NASNetMobile,ResNet101,ResNet101V2,ResNet152,ResNet152V2,ResNet50,ResNet50V2,Xception}\n                                          [--call CALL]\n                                          [--model_kwargs MODEL_KWARGS]\n    \n    Load the model. Takes a model object, or a pipeline that downloads \u0026\n    configures before returning a model object.\n    \n    optional arguments:\n      -h, --help            show this help message and exit\n      --model {DenseNet121,DenseNet169,DenseNet201,EfficientNetB0,EfficientNetB1,EfficientNetB2,EfficientNetB3,EfficientNetB4,EfficientNetB5,EfficientNetB6,EfficientNetB7,InceptionResNetV2,InceptionV3,MobileNet,MobileNetV2,NASNetLarge,NASNetMobile,ResNet101,ResNet101V2,ResNet152,ResNet152V2,ResNet50,ResNet50V2,Xception}\n                            model object, e.g., a tf.keras.Sequential, tl.Serial,\n                            nn.Module instance\n      --call CALL           whether to call `model()` even if `len(model_kwargs)\n                            == 0`\n      --model_kwargs MODEL_KWARGS\n                            to be passed into the model. If empty, doesn't call,\n                            unless call=True.\n\n#### `train`\n\n    $ python -m ml_params --engine 'tensorflow' train --help\n    usage: python -m ml_params train [-h]\n                                     [--callbacks {BaseLogger,CSVLogger,Callback,CallbackList,EarlyStopping,History,LambdaCallback,LearningRateScheduler,ModelCheckpoint,ProgbarLogger,ReduceLROnPlateau,RemoteMonitor,TensorBoard,TerminateOnNaN}]\n                                     --epochs EPOCHS --loss\n                                     {BinaryCrossentropy,CategoricalCrossentropy,CategoricalHinge,CosineSimilarity,Hinge,Huber,KLDivergence,LogCosh,MeanAbsoluteError,MeanAbsolutePercentageError,MeanSquaredError,MeanSquaredLogarithmicError,Poisson,Reduction,SparseCategoricalCrossentropy,SquaredHinge}\n                                     [--metrics {binary_accuracy,binary_crossentropy,categorical_accuracy,categorical_crossentropy,hinge,kl_divergence,kld,kullback_leibler_divergence,mae,mape,mean_absolute_error,mean_absolute_percentage_error,mean_squared_error,mean_squared_logarithmic_error,mse,msle,poisson,sparse_categorical_accuracy,sparse_categorical_crossentropy,sparse_top_k_categorical_accuracy,squared_hinge,top_k_categorical_accuracy}]\n                                     --optimizer\n                                     {Adadelta,Adagrad,Adam,Adamax,Ftrl,Nadam,RMSprop}\n                                     [--metric_emit_freq METRIC_EMIT_FREQ]\n                                     [--save_directory SAVE_DIRECTORY]\n                                     [--output_type OUTPUT_TYPE]\n                                     [--validation_split VALIDATION_SPLIT]\n                                     [--batch_size BATCH_SIZE] [--kwargs KWARGS]\n    \n    Run the training loop for your ML pipeline.\n    \n    optional arguments:\n      -h, --help            show this help message and exit\n      --callbacks {BaseLogger,CSVLogger,Callback,CallbackList,EarlyStopping,History,LambdaCallback,LearningRateScheduler,ModelCheckpoint,ProgbarLogger,ReduceLROnPlateau,RemoteMonitor,TensorBoard,TerminateOnNaN}\n                            Collection of callables that are run inside the\n                            training loop\n      --epochs EPOCHS       number of epochs (must be greater than 0)\n      --loss {BinaryCrossentropy,CategoricalCrossentropy,CategoricalHinge,CosineSimilarity,Hinge,Huber,KLDivergence,LogCosh,MeanAbsoluteError,MeanAbsolutePercentageError,MeanSquaredError,MeanSquaredLogarithmicError,Poisson,Reduction,SparseCategoricalCrossentropy,SquaredHinge}\n                            Loss function, can be a string (depending on the\n                            framework) or an instance of a class\n      --metrics {binary_accuracy,binary_crossentropy,categorical_accuracy,categorical_crossentropy,hinge,kl_divergence,kld,kullback_leibler_divergence,mae,mape,mean_absolute_error,mean_absolute_percentage_error,mean_squared_error,mean_squared_logarithmic_error,mse,msle,poisson,sparse_categorical_accuracy,sparse_categorical_crossentropy,sparse_top_k_categorical_accuracy,squared_hinge,top_k_categorical_accuracy}\n                            Collection of metrics to monitor, e.g., accuracy, f1\n      --optimizer {Adadelta,Adagrad,Adam,Adamax,Ftrl,Nadam,RMSprop}\n                            Optimizer, can be a string (depending on the\n                            framework) or an instance of a class\n      --metric_emit_freq METRIC_EMIT_FREQ\n                            `None` for every epoch. E.g., `eq(mod(epochs, 10), 0)`\n                            for every 10.\n      --save_directory SAVE_DIRECTORY\n                            Directory to save output in, e.g., weights in h5\n                            files. If None, don't save.\n      --output_type OUTPUT_TYPE\n                            `if save_directory is not None` then save in this\n                            format, e.g., 'h5'.\n      --validation_split VALIDATION_SPLIT\n                            Optional float between 0 and 1, fraction of data to\n                            reserve for validation.\n      --batch_size BATCH_SIZE\n                            batch size at each iteration.\n      --kwargs KWARGS       additional keyword arguments\n\n\nYou can also go further, and provide [meta]parameters for your parameters—with `:`—including asking for help text:\n\n    $ python -m ml_params train --engine 'tensorflow' \\ \n                                --callbacks 'TensorBoard: --log_dir \"/tmp\" --help'\n\n    usage: --callbacks 'TensorBoard: [-h] [--log_dir LOG_DIR]\n                                     [--histogram_freq HISTOGRAM_FREQ]\n                                     [--write_graph WRITE_GRAPH]\n                                     [--write_images WRITE_IMAGES]\n                                     [--update_freq UPDATE_FREQ]\n                                     [--profile_batch PROFILE_BATCH]\n                                     [--embeddings_freq EMBEDDINGS_FREQ]\n                                     [--embeddings_metadata EMBEDDINGS_METADATA]\n                                     [--kwargs KWARGS]\n    \n    Enable visualizations for TensorBoard. TensorBoard is a visualization tool\n    provided with TensorFlow. This callback logs events for TensorBoard,\n    including: * Metrics summary plots * Training graph visualization * Activation\n    histograms * Sampled profiling If you have installed TensorFlow with pip, you\n    should be able to launch TensorBoard from the command line: ``` tensorboard\n    --logdir=path_to_your_logs ``` You can find more information about TensorBoard\n    [here](https://www.tensorflow.org/get_started/summaries_and_tensorboard).\n    Example (Basic): ```python tensorboard_callback =\n    tf.keras.callbacks.TensorBoard(log_dir=\"./logs\") model.fit(x_train, y_train,\n    epochs=2, callbacks=[tensorboard_callback]) # run the tensorboard command to\n    view the visualizations. ``` Example (Profile): ```python # profile a single\n    batch, e.g. the 5th batch. tensorboard_callback =\n    tf.keras.callbacks.TensorBoard(log_dir='./logs', profile_batch=5)\n    model.fit(x_train, y_train, epochs=2, callbacks=[tensorboard_callback]) # Now\n    run the tensorboard command to view the visualizations (profile plugin). #\n    profile a range of batches, e.g. from 10 to 20. tensorboard_callback =\n    tf.keras.callbacks.TensorBoard(log_dir='./logs', profile_batch='10,20')\n    model.fit(x_train, y_train, epochs=2, callbacks=[tensorboard_callback]) # Now\n    run the tensorboard command to view the visualizations (profile plugin). ```\n    Raises: ValueError: If histogram_freq is set and no validation data is\n    provided.\n    \n    optional arguments:\n      -h, --help            show this help message and exit\n      --log_dir LOG_DIR     the path of the directory where to save the log files\n                            to be parsed by TensorBoard.\n      --histogram_freq HISTOGRAM_FREQ\n                            frequency (in epochs) at which to compute activation\n                            and weight histograms for the layers of the model. If\n                            set to 0, histograms won't be computed. Validation\n                            data (or split) must be specified for histogram\n                            visualizations.\n      --write_graph WRITE_GRAPH\n                            whether to visualize the graph in TensorBoard. The log\n                            file can become quite large when write_graph is set to\n                            True.\n      --write_images WRITE_IMAGES\n                            whether to write model weights to visualize as image\n                            in TensorBoard.\n      --update_freq UPDATE_FREQ\n                            `'batch'` or `'epoch'` or integer. When using\n                            `'batch'`, writes the losses and metrics to\n                            TensorBoard after each batch. The same applies for\n                            `'epoch'`. If using an integer, let's say `1000`, the\n                            callback will write the metrics and losses to\n                            TensorBoard every 1000 batches. Note that writing too\n                            frequently to TensorBoard can slow down your training.\n      --profile_batch PROFILE_BATCH\n                            Profile the batch(es) to sample compute\n                            characteristics. profile_batch must be a non-negative\n                            integer or a tuple of integers. A pair of positive\n                            integers signify a range of batches to profile. By\n                            default, it will profile the second batch. Set\n                            profile_batch=0 to disable profiling.\n      --embeddings_freq EMBEDDINGS_FREQ\n                            frequency (in epochs) at which embedding layers will\n                            be visualized. If set to 0, embeddings won't be\n                            visualized.\n      --embeddings_metadata EMBEDDINGS_METADATA\n                            a dictionary which maps layer name to a file name in\n                            which metadata for this embedding layer is saved. See\n                            the [details]( https://www.tensorflow.org/how_tos/embe\n                            dding_viz/#metadata_optional) about metadata files\n                            format. In case if the same metadata file is used for\n                            all embedding layers, string can be passed.\n      --kwargs KWARGS\n\nNow let's run multiple commands, which behind the scenes constructs a `Trainer` object and calls the relevant methods (subcommands) in the order you reference them:\n\n    $ ML_PARAMS_ENGINE='tensorflow'\n    $ python -m ml_params load_data --dataset_name 'mnist' \\\n                                    --data_type 'infer' \\\n                          load_model --model 'MobileNet' \\\n                          train --epochs 3 \\\n                          --loss 'CategoricalCrossentropy' \\\n                          --optimizer 'Adam' \\\n                          --output_type 'numpy' \\\n                          --validation_split '0.5' \\\n                          --batch_size 128\n\n## Official implementations\n\n| Google | Other vendors |\n| -------| ------------- |\n| [tensorflow](https://github.com/SamuelMarks/ml-params-tensorflow)  | [pytorch](https://github.com/SamuelMarks/ml-params-pytorch) |\n| [keras](https://github.com/SamuelMarks/ml-params-keras)  | [skorch](https://github.com/SamuelMarks/ml-params-skorch) |\n| [flax](https://github.com/SamuelMarks/ml-params-flax) | [sklearn](https://github.com/SamuelMarks/ml-params-sklearn) |\n| [trax](https://github.com/SamuelMarks/ml-params-trax) | [xgboost](https://github.com/SamuelMarks/ml-params-xgboost) |\n| [jax](https://github.com/SamuelMarks/ml-params-jax) | [cntk](https://github.com/SamuelMarks/ml-params-cntk) |\n \n## Related official projects\n\n  - [ml-prepare](https://github.com/SamuelMarks/ml-prepare)\n\n## Similar open-source projects\n\n  - Exposing model layers as command-line arguments: [Calamari-OCR](https://github.com/Calamari-OCR/calamari/blob/445d990/docs/source/doc.command-line-usage.rst#advanced)\n  - Dynamic parameter exposure and entry: https://github.com/google/gin-config\n  - An open source inference server for your machine learning models: https://github.com/SeldonIO/mlserver\n  - Abstracted interface to multiple frameworks—without any type or even internal exposure—and related tooling: https://github.com/mlflow/mlflow\n  - Similar to MLflow: https://github.com/VertaAI/modeldb\n  - Project oriented (again, lacking type exposure): https://github.com/logicalclocks/hopsworks\n\nThe big drawbacks with all these solutions are that they treat:\n\n  - categorical parameters as a blackbox (no dropdown menu to select \"Optimizer\", \"Loss function\", \"Transfer learning model\");\n  - continuous parameters as arbitrary (arbitrary floating point and integer precision).\n\nWith the [cdd-python](https://github.com/offscale/cdd-python) implemented ml-params these drawbacks don't apply, enabling [future work](#future-work).\n\nTechnically with this library-directed implementation contributions to these 'similar' projects could be made, overcoming their inherent drawbacks.\n\n## Future work\n\nConstruct a *search space* database—in memory or disk persisted—that can be iterated through via various *strategies*.\n\n*Search space* refers to the:\n  - `Dataset`s\n  - `Model`s\n  - `Model` internals\n    - Categorical parameters\n      - `Loss` functions\n      - `Optimizer`s\n      - …\n    - Continuous [hyper]parameters, provided to model-internals and/or directly to `Model`s:\n      - Learning-rate\n      - gamma, alpha, epsilon, \u0026etc.\n  - `Metric`s\n    - Accuracy\n    - F1 score\n    - AUCROC\n    - …\n\n_Strategies_ for exploring this search space:\n  - Greedy (grid-search)\n  - Genetic algorithms\n  - SVM\n  - Bayesian\n  - Raytuning ([multi](https://docs.ray.io/en/latest/tune/api_docs/suggestion.html));\n  - Use ml-params as input to explore the different strategies (self-optimizing self-optimizer!)\n\nAdditionally, concurrency controls to enable rapid explanation of the search space, akin to [Apache Hop](https://hop.apache.org) and [Apache Beam](https://beam.apache.org):\n  - Single machine\n    - Different hardware (GPU0 not GPU1)\n    - Different experiment per thread and/or per process\n    - Memory sharing, IPC, \u0026 other techniques\n  - Multi-machine\n    - RPC and/or pubsub system linked to database to acquire params and update progress\n\nLikely these last use-cases will be better facilitated through contributions planned for Google's TensorBoard for full db support (from this project!).\n\nFurthermore, contributions to TensorFlow, PyTorch, and other frameworks are being prepared so that they officially expose granular types… making projects like ml-params more useful and accurate.\n\n## Python 2.7\nPython 2.7 support isn't difficult. Just remove the keyword-only arguments. For the type annotations, use `cdd` to automatically replace them with docstrings. Effort has been put into making everything else Python 2/3 compatible.\n\n---\n\n## License\n\nLicensed under either of\n\n- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or \u003chttps://www.apache.org/licenses/LICENSE-2.0\u003e)\n- MIT license ([LICENSE-MIT](LICENSE-MIT) or \u003chttps://opensource.org/licenses/MIT\u003e)\n\nat your option.\n\n### Contribution\n\nUnless you explicitly state otherwise, any contribution intentionally submitted\nfor inclusion in the work by you, as defined in the Apache-2.0 license, shall be\ndual licensed as above, without any additional terms or conditions.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamuelmarks%2Fml-params","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsamuelmarks%2Fml-params","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamuelmarks%2Fml-params/lists"}