{"id":13710,"date":"2020-11-07T11:50:52","date_gmt":"2020-11-07T11:50:52","guid":{"rendered":"http:\/\/stblog.lunaeme.com\/?p=13710"},"modified":"2023-09-20T15:30:48","modified_gmt":"2023-09-20T15:30:48","slug":"implementing-the-statsmodels-flavor-in-mlflow","status":"publish","type":"post","link":"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/","title":{"rendered":"Implementing the statsmodels flavor in MLflow"},"content":{"rendered":"<p><a href=\"https:\/\/mlflow.org\/\">MLflow<\/a>, the open-source platform released by Databricks in June 2018, has found a quick and broad acceptance in companies around the world. As stated by Databrick\u2019s co-founder and CTO Matei Zaharia in their <a href=\"https:\/\/databricks.com\/blog\/2018\/06\/05\/introducing-mlflow-an-open-source-machine-learning-platform.html\">presentation post<\/a>, there were a lot of different tools prior to this, created to track and\/or take ML models into production, but they were either proprietary, language-dependent, or able to address only one aspect of the complete Machine Learning lifecycle. MLflow aims to be open in all senses &#8211; open source software but also language-agnostic (open interface).<\/p>\n<p><!--more--><\/p>\n<p>Here at Stratio, MLflow has a prominent role as it is embedded in Stratio Rocket, the evolution of the primitive <a href=\"https:\/\/www.stratio.com\/blog\/apache-spark-visual-tool-sparta\/\">Stratio Sparta<\/a> module that enables the design of data processing workflows with little or no code at all, using just a visual tool. In a broad sense, Rocket is an analytical environment that comprises a number of unique features to get the most out of the data you have stored in the <a href=\"https:\/\/www.stratio.com\/a-data-centric-product\/\">Stratio DataCentric<\/a> platform. From a data-centric perspective, Rocket constitutes the data intelligence layer.<\/p>\n<p>From the very beginning, Stratio Rocket allows automatically deploying a trained model as a microservice. Before MLflow was released, this functionality was restricted to Spark or Scikit-learn models, as Rocket relies on the MLeap library which only supports these two frameworks. Currently, any model that MLflow is able to deploy, can also be deployed with two mouse clicks from Stratio Rocket. This includes models created with a number of popular ML frameworks and libraries, such as Spark ML, Tensorflow, PyTorch, Scikit-Learn, LightGBM, XGBoost, and more. However, not every ML package out there is supported by MLflow, and therefore, some users still cannot see their models deployed and exploited as microservices.<\/p>\n<p>Before going into detail on what it means to support a new framework, let\u2019s briefly review MLflow\u2019s features and benefits.<\/p>\n<h2><b>MLflow key components<\/b><\/h2>\n<p>MLflow is composed of four main components, each aimed at a different purpose:<\/p>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>&lt;li&#8221;&gt;<\/ul>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/www.mlflow.org\/docs\/latest\/tracking.html\">MLflow Tracking<\/a><\/p>\n<ul>: devoted to saving all the configurations tried by a data scientist with different algorithms and the results (performance metrics) obtained. This way, we can later query, review and compare them, always having the results linked with the parameter configuration that generated it. &lt;\/li&#8221;&gt;<\/ul>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>&lt;li&#8221;&gt;<\/ul>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/www.mlflow.org\/docs\/latest\/projects.html\">MLflow Projects<\/a><\/p>\n<ul>: devoted to automatically creating a self-contained environment that includes code, data, libraries (dependencies) and configurations, ready to be shared with other team members. It is a step towards the reproducibility and reusability of data science code. &lt;\/li&#8221;&gt;<\/ul>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>&lt;li&#8221;&gt;<\/ul>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/www.mlflow.org\/docs\/latest\/models.html\">MLflow Models<\/a><\/p>\n<ul>: devoted to automatically deploying a trained model as a microservice that can later be queried in a totally language-agnostic manner via API REST. It also supports the deployment of any non-distributed model as a Spark UDF so that we can use Spark to make batch predictions with that model on a large dataset of unlabeled data. &lt;\/li&#8221;&gt;<\/ul>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>&lt;li&#8221;&gt;<\/ul>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/www.mlflow.org\/docs\/latest\/model-registry.html\">MLflow Model regihttps:\/\/github.com\/mlflow\/mlflow\/pull\/3304stry<\/a><\/p>\n<ul>: this more recent component was added later, and covers the needs for a model repository where the user can track how the model was generated (parameter configuration, data), model versioning and lifecycle. &lt;\/li&#8221;&gt;<\/ul>\n<h2><b>MLflow flavors<\/b><\/h2>\n<p>In order for a model to be easily logged with MLflow or make it deployable (for example, to use MLflow Tracking or MLflow Models with it), there must exist an <a href=\"https:\/\/www.mlflow.org\/docs\/latest\/models.html#built-in-model-flavors\">MLflow <i>flavor<\/i><\/a> which determines&nbsp; how the models created by a concrete ML framework should be saved to disk, loaded into memory again, and queried to get predictions. When an ML framework is not directly supported by MLflow, there\u2019s still an option to implement a custom code using MLflow\u2019s <i>Python function (pyfunc)<\/i> facility. It is a mechanism to obtain an ad-hoc, fully customized solution in which the user must implement a few functions that are common to any flavor already supported by MLflow.<\/p>\n<p>Despite being valid, this approach requires a deep understanding of MLflow internals, and therefore it is addressed mostly to developers and ML engineers rather than Data Scientists. Ideally, we as users would like to have native support of as many ML frameworks as possible. What if we are using a library that is not supported by MLflow? Instead of just creating an ad-hoc pyfunc and using it in our personal projects, let\u2019s implement the native support by extending MLflow code, and then submit a Pull Request to the MLflow repository so that others can benefit from it in the future! [SPOILER ALERT: check the <a href=\"https:\/\/github.com\/mlflow\/mlflow\/pull\/3304\">statsmodels flavor Pull Request<\/a>]<\/p>\n<h2><b>The statsmodels package<\/b><\/h2>\n<p>While MLflow already includes many common ML libraries, it lacks a very important one, namely <a href=\"https:\/\/www.statsmodels.org\/\"><i>statsmodels<\/i><\/a>. This Python package was created back in 2010 and is one of the few packages that provide statistical modeling capabilities in Python [1]. Differently from scikit-learn, statsmodels emphasizes the probabilistic nature of the models and their statistical properties, not just for prediction tasks. According to the authors, statsmodels can accomplish <i>statistical computations including descriptive statistics, estimation, and inference for statistical models.<\/i> It covers many classic statistical models such as generalized linear models (including p-values and inference), linear mixed models, additive models, ANOVA, time series analysis, and survival analysis. A complete list of the models available can be found <a href=\"https:\/\/www.statsmodels.org\/stable\/user-guide.html\">here<\/a>.<\/p>\n<p><b>Model serialization with statsmodels<\/b>: fortunately, statsmodels follows the standard practice of python ML libraries and hence uses <a href=\"https:\/\/docs.python.org\/3\/library\/pickle.html\">Pickle<\/a> to save\/load models to\/from disk. This is the same format used by, e.g. Scikit-learn which is already supported by MLflow, which gives us a clue that it should not be very difficult to incorporate statsmodels to MLflow.<\/p>\n<h2><b>How to implement a new MLflow flavor<\/b><\/h2>\n<p>First of all, we should carefully read <a href=\"https:\/\/github.com\/mlflow\/mlflow\/blob\/master\/CONTRIBUTING.rst\">this guide<\/a> and particularly <a href=\"https:\/\/github.com\/mlflow\/mlflow\/blob\/master\/CONTRIBUTING.rst#id23\">this section<\/a>. It definitely helps a lot to examine the code of the LightGBM flavor that <a href=\"https:\/\/github.com\/mlflow\/mlflow\/pull\/2136\/files\">was added recently<\/a>. Basically, we need to implement the following functions:<\/p>\n<ul>&lt;li&#8221;&gt;def save_model(statsmodels_model, &lt;\/li&#8221;&gt;<\/ul>\n<p>path,<\/p>\n<p>conda_env=None,<\/p>\n<p>mlflow_model=None,<\/p>\n<p>remove_data: bool = False,<\/p>\n<p>signature: ModelSignature = None,<\/p>\n<p>input_example: ModelInputExample = None<\/p>\n<p>)<\/p>\n<ul>&lt;li&#8221;&gt;def log_model( &lt;\/li&#8221;&gt;<\/ul>\n<p>statsmodels_model,<\/p>\n<p>artifact_path,<\/p>\n<p>conda_env=None,<\/p>\n<p>registered_model_name=None,<\/p>\n<p>remove_data: bool = False,<\/p>\n<p>signature: ModelSignature = None,<\/p>\n<p>input_example: ModelInputExample = None,<\/p>\n<p>**kwargs<\/p>\n<p>)<\/p>\n<ul>&lt;li&#8221;&gt;def _load_pyfunc(path) # called by mlflow.pyfunc.load_model &lt;li&#8221;&gt;def load_model(model_uri) &lt;li&#8221;&gt;def autolog() &lt;\/li&#8221;&gt;&lt;\/li&#8221;&gt;&lt;\/li&#8221;&gt;<\/ul>\n<p>Most of the above functions are self-descriptive. We have added the <i>remove_data <\/i>argument that is fed into the internal call to statsmodels save function, and allows not saving the dataset that was used for training the model, saving a lot of space.<\/p>\n<p><b>Autolog in MLflow<\/b>: most often the user will call mlflow.statsmodels.log_param(s) or mlflow.statsmodels.log_metric(s) to log the metrics or parameters he\/she needs, many MLflow flavors have an autolog function. The user calls autolog() only once, before starting the execution of the ML code that uses his\/her favorite ML library (be it scikit, tensorflow, etc). The user code remains unchanged, with no references to MLflow except for the call to mlflow.&lt;<i>flavor_name&gt;.<\/i>autolog() at the beginning. Under the hood, every call to the ML library causes MLflow to automatically log a few parameters and\/or metrics, in a way that is totally transparent to the user.<\/p>\n<p>Implementing function mlflow.statsmodels.autolog is a bit more complicated than other frameworks. In this first version of the statsmodels flavor, we only support method <i>fit <\/i>of a statsmodels algorithm. It will cause MLflow to log the fit arguments <b>and<\/b> the results, including fitted model parameters and performance metrics, with an emphasis on p-values and statistical properties of the fitted model. <i>We only autolog those parameters that are either one-dimensional (real numbers or strings), or n-dimensional vectors with n = number of features in the data<\/i>.<\/p>\n<h2><b>Monkey patching&nbsp;<\/b><\/h2>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-13711 aligncenter\" src=\"http:\/\/blog.stratio.com\/wp-content\/uploads\/2020\/08\/pasted-image-0.png\" alt=\"\" width=\"200\" height=\"200\"><\/p>\n<p>In Python and other languages, monkey patching is a technique that consists in replacing existing methods or functions by other ones at runtime. It helps in implementing autolog as it allows replacing the native statsmodels functions (in our case, only the <i>fit <\/i>function) by our own function which will log model parameters and metrics before and after calling the original statsmodels fit function. Inspired by the LightGBM flavor code, we have used the <a href=\"https:\/\/gorilla.readthedocs.io\/_\/downloads\/en\/latest\/pdf\/\"><i>gorilla<\/i> python package<\/a> for this, carefully ensuring that our function keeps a link to the original statsmodels <i>fit<\/i> function.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-13712 aligncenter\" src=\"http:\/\/blog.stratio.com\/wp-content\/uploads\/2020\/08\/unnamed.png\" alt=\"\" width=\"512\" height=\"112\"><\/p>\n<p>Figure 1: the statsmodels class hierarchy (showing models classes only)<\/p>\n<p>Here comes the tricky part: when we examined the class hierarchy (Fig. 1) of the statsmodels package, we realized that many algorithms override the fit function, and furthermore, an overridden fit function often calls the superclass <i>fit<\/i> at some point of its own implementation, but <b>within the context of the subclass<\/b>. For this reason, keeping the <i>right<\/i> link to the original function was a bit more complicated and could not be fully accomplished with the gorilla package, so we had to design a different mechanism:<\/p>\n<p>def wrapper_fit(original_method):&nbsp; # function object with the original fit func<\/p>\n<p>def fit(self, *args, **kwargs):<\/p>\n<p># Do stuff. Check if this is the outermost call<\/p>\n<p>model = original_method(self, args, kwargs) # call original fit<\/p>\n<p># More stuff: if this is the outermost call, log params and metrics<\/p>\n<p>return model<\/p>\n<p>return fit<\/p>\n<p>Moreover, since there are many different <i>fit <\/i>functions inside statsmodels, we had to monkey-patch (i.e. replace) all of them, which required recursively traversing the whole statsmodels class hierarchy, examining each class to check whether it overrides <i>fit<\/i> or not, and if it&nbsp; does, replacing it with our own <i>fit<\/i> function:<\/p>\n<p>subclasses = set(find_subclasses_recursive(statsmodels.base.model.Model))<\/p>\n<p># Create a patch for every method that needs to be patched: those<\/p>\n<p># which actually override an autologgable method<\/p>\n<p># Link the patched function with the original via a local variable<\/p>\n<p># in the closure to allow invoking superclass methods in the context<\/p>\n<p># of the subclass, and not losing the trace of the original method<\/p>\n<p>patches_list = [<\/p>\n<p>gorilla.Patch(c, &#8220;fit&#8221;,<\/p>\n<p>wrapper_fit(getattr(c, &#8220;fit&#8221;)), settings=glob_settings)<\/p>\n<p>for c in subclasses if overrides(c, &#8220;fit&#8221;)<\/p>\n<p>]<\/p>\n<p># Finally, apply all patches<\/p>\n<p>for p in patches_list:<\/p>\n<p>apply_gorilla_patch(p) &nbsp; &nbsp; # a customized apply patch function<\/p>\n<p>Our <i>fit<\/i> implementation just creates a new MLflow run if there\u2019s none running, logs the arguments, calls the original function and logs the results when it returns. IMPORTANT: no matter how many internal calls are done to other classes\u2019 <i>fit <\/i>method, the only call that should log the results is the <i>most external<\/i> one, i.e. the <i>fit<\/i> method that was called directly by the user. We account for this through a class variable (a shared boolean flag) that is set by the first call to <i>fit <\/i>(i.e. the most external, invoked by the user). This flag prevents any other recursive (internal) call to the patched <i>fit <\/i>from also logging stuff since it will find the flag already set.<\/p>\n<p>Of course, at the same time, we develop our code, we must develop enough test cases to cover all the new functionality. The test cases were heavily inspired by those of the LightGBM Pull Request, including a number of different statsmodels models to ensure they can be saved and loaded, logged, and also auto-logged. Keep in mind that some statsmodels models do not have a predict method (although most do have) and some others are not pickable.<\/p>\n<h2><b>Summary<\/b><\/h2>\n<p>MLflow is a very nice open-source framework that solves the most common needs related to ML model&#8217;s lifecycle, covering code sharing, experiment tracking, model deployment, and lifecycle management. It is compatible with many popular ML frameworks and libraries, but still lacks integration with the statsmodels package. We deem this integration necessary as statsmodels is among the few Python packages that perform statistical modeling and inference. We have described how the integration can be accomplished as a new flavor for MLflow. We hope the Pull Request will eventually be accepted and merged so that we can benefit from it in the next MLflow release. Fingers crossed!<\/p>\n<h2><b>References<\/b><\/h2>\n<p>[1] Seabold, S. and Perktold, J. (2010) <a href=\"https:\/\/conference.scipy.org\/proceedings\/scipy2010\/pdfs\/seabold.pdf\">Statsmodels: Econometric and Statistical Modeling with Python<\/a>. <i>Proc. of the 9th Python in Science Conference (SCIPY)<\/i>, 92 &#8211; 96.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>MLflow, the open-source platform released by Databricks in June 2018, has found a quick and broad acceptance in companies around the world.<\/p>\n","protected":false},"author":2,"featured_media":13713,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[686],"tags":[16,19,534],"ppma_author":[794],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v22.9 (Yoast SEO v22.9) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Implementing the statsmodels flavor in MLflow<\/title>\n<meta name=\"description\" content=\"Over the last few years and even now, we usually hear that in order to build a microservices architecture or any distributed system, the services must be stateless. However, these systems also need to store the state in some way. Discover how we can address this problem using stateful services that could manage distributed state at scale.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Implementing the statsmodels flavor in MLflow\" \/>\n<meta property=\"og:description\" content=\"Over the last few years and even now, we usually hear that in order to build a microservices architecture or any distributed system, the services must be stateless. However, these systems also need to store the state in some way. Discover how we can address this problem using stateful services that could manage distributed state at scale.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/\" \/>\n<meta property=\"og:site_name\" content=\"Stratio\" \/>\n<meta property=\"article:published_time\" content=\"2020-11-07T11:50:52+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-09-20T15:30:48+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.stratio.com\/blog\/wp-content\/uploads\/2020\/08\/MLflow_imagen_post.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1300\" \/>\n\t<meta property=\"og:image:height\" content=\"820\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@stratiobd\" \/>\n<meta name=\"twitter:site\" content=\"@stratiobd\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/\"},\"author\":{\"name\":\"admin\",\"@id\":\"https:\/\/www.stratio.com\/blog\/#\/schema\/person\/af4f5fbbeb95bd7d55f79d9a677e615d\"},\"headline\":\"Implementing the statsmodels flavor in MLflow\",\"datePublished\":\"2020-11-07T11:50:52+00:00\",\"dateModified\":\"2023-09-20T15:30:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/\"},\"wordCount\":2043,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.stratio.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.stratio.com\/blog\/wp-content\/uploads\/2020\/08\/MLflow_imagen_post.jpg\",\"keywords\":[\"Artifical Intelligence\",\"Big Data\",\"Cloud\"],\"articleSection\":[\"Product\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/\",\"url\":\"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/\",\"name\":\"Implementing the statsmodels flavor in MLflow\",\"isPartOf\":{\"@id\":\"https:\/\/www.stratio.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.stratio.com\/blog\/wp-content\/uploads\/2020\/08\/MLflow_imagen_post.jpg\",\"datePublished\":\"2020-11-07T11:50:52+00:00\",\"dateModified\":\"2023-09-20T15:30:48+00:00\",\"description\":\"Over the last few years and even now, we usually hear that in order to build a microservices architecture or any distributed system, the services must be stateless. However, these systems also need to store the state in some way. Discover how we can address this problem using stateful services that could manage distributed state at scale.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/#primaryimage\",\"url\":\"https:\/\/www.stratio.com\/blog\/wp-content\/uploads\/2020\/08\/MLflow_imagen_post.jpg\",\"contentUrl\":\"https:\/\/www.stratio.com\/blog\/wp-content\/uploads\/2020\/08\/MLflow_imagen_post.jpg\",\"width\":1300,\"height\":820},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.stratio.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Implementing the statsmodels flavor in MLflow\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.stratio.com\/blog\/#website\",\"url\":\"https:\/\/www.stratio.com\/blog\/\",\"name\":\"Stratio Blog\",\"description\":\"Corporate blog\",\"publisher\":{\"@id\":\"https:\/\/www.stratio.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.stratio.com\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.stratio.com\/blog\/#organization\",\"name\":\"Stratio\",\"url\":\"https:\/\/www.stratio.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.stratio.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/stratio.com\/blog\/wp-content\/uploads\/2020\/06\/stratio-web-logo-1.png\",\"contentUrl\":\"https:\/\/stratio.com\/blog\/wp-content\/uploads\/2020\/06\/stratio-web-logo-1.png\",\"width\":260,\"height\":55,\"caption\":\"Stratio\"},\"image\":{\"@id\":\"https:\/\/www.stratio.com\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/stratiobd\",\"https:\/\/es.linkedin.com\/company\/stratiobd\",\"https:\/\/www.youtube.com\/c\/StratioBD\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.stratio.com\/blog\/#\/schema\/person\/af4f5fbbeb95bd7d55f79d9a677e615d\",\"name\":\"admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.stratio.com\/blog\/#\/schema\/person\/image\/589aaf4b404b1fe099b09564062c4563\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/9b181ae4395243dccaf1c3e3a4749d81?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/9b181ae4395243dccaf1c3e3a4749d81?s=96&d=mm&r=g\",\"caption\":\"admin\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Implementing the statsmodels flavor in MLflow","description":"Over the last few years and even now, we usually hear that in order to build a microservices architecture or any distributed system, the services must be stateless. However, these systems also need to store the state in some way. Discover how we can address this problem using stateful services that could manage distributed state at scale.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/","og_locale":"en_US","og_type":"article","og_title":"Implementing the statsmodels flavor in MLflow","og_description":"Over the last few years and even now, we usually hear that in order to build a microservices architecture or any distributed system, the services must be stateless. However, these systems also need to store the state in some way. Discover how we can address this problem using stateful services that could manage distributed state at scale.","og_url":"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/","og_site_name":"Stratio","article_published_time":"2020-11-07T11:50:52+00:00","article_modified_time":"2023-09-20T15:30:48+00:00","og_image":[{"width":1300,"height":820,"url":"https:\/\/www.stratio.com\/blog\/wp-content\/uploads\/2020\/08\/MLflow_imagen_post.jpg","type":"image\/jpeg"}],"author":"admin","twitter_card":"summary_large_image","twitter_creator":"@stratiobd","twitter_site":"@stratiobd","twitter_misc":{"Written by":"admin","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/#article","isPartOf":{"@id":"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/"},"author":{"name":"admin","@id":"https:\/\/www.stratio.com\/blog\/#\/schema\/person\/af4f5fbbeb95bd7d55f79d9a677e615d"},"headline":"Implementing the statsmodels flavor in MLflow","datePublished":"2020-11-07T11:50:52+00:00","dateModified":"2023-09-20T15:30:48+00:00","mainEntityOfPage":{"@id":"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/"},"wordCount":2043,"commentCount":0,"publisher":{"@id":"https:\/\/www.stratio.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/#primaryimage"},"thumbnailUrl":"https:\/\/www.stratio.com\/blog\/wp-content\/uploads\/2020\/08\/MLflow_imagen_post.jpg","keywords":["Artifical Intelligence","Big Data","Cloud"],"articleSection":["Product"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/","url":"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/","name":"Implementing the statsmodels flavor in MLflow","isPartOf":{"@id":"https:\/\/www.stratio.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/#primaryimage"},"image":{"@id":"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/#primaryimage"},"thumbnailUrl":"https:\/\/www.stratio.com\/blog\/wp-content\/uploads\/2020\/08\/MLflow_imagen_post.jpg","datePublished":"2020-11-07T11:50:52+00:00","dateModified":"2023-09-20T15:30:48+00:00","description":"Over the last few years and even now, we usually hear that in order to build a microservices architecture or any distributed system, the services must be stateless. However, these systems also need to store the state in some way. Discover how we can address this problem using stateful services that could manage distributed state at scale.","breadcrumb":{"@id":"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/#primaryimage","url":"https:\/\/www.stratio.com\/blog\/wp-content\/uploads\/2020\/08\/MLflow_imagen_post.jpg","contentUrl":"https:\/\/www.stratio.com\/blog\/wp-content\/uploads\/2020\/08\/MLflow_imagen_post.jpg","width":1300,"height":820},{"@type":"BreadcrumbList","@id":"https:\/\/www.stratio.com\/blog\/implementing-the-statsmodels-flavor-in-mlflow\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.stratio.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Implementing the statsmodels flavor in MLflow"}]},{"@type":"WebSite","@id":"https:\/\/www.stratio.com\/blog\/#website","url":"https:\/\/www.stratio.com\/blog\/","name":"Stratio Blog","description":"Corporate blog","publisher":{"@id":"https:\/\/www.stratio.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.stratio.com\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.stratio.com\/blog\/#organization","name":"Stratio","url":"https:\/\/www.stratio.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.stratio.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/stratio.com\/blog\/wp-content\/uploads\/2020\/06\/stratio-web-logo-1.png","contentUrl":"https:\/\/stratio.com\/blog\/wp-content\/uploads\/2020\/06\/stratio-web-logo-1.png","width":260,"height":55,"caption":"Stratio"},"image":{"@id":"https:\/\/www.stratio.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/stratiobd","https:\/\/es.linkedin.com\/company\/stratiobd","https:\/\/www.youtube.com\/c\/StratioBD"]},{"@type":"Person","@id":"https:\/\/www.stratio.com\/blog\/#\/schema\/person\/af4f5fbbeb95bd7d55f79d9a677e615d","name":"admin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.stratio.com\/blog\/#\/schema\/person\/image\/589aaf4b404b1fe099b09564062c4563","url":"https:\/\/secure.gravatar.com\/avatar\/9b181ae4395243dccaf1c3e3a4749d81?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/9b181ae4395243dccaf1c3e3a4749d81?s=96&d=mm&r=g","caption":"admin"}}]}},"authors":[{"term_id":794,"user_id":2,"is_guest":0,"slug":"admin","display_name":"admin","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/9b181ae4395243dccaf1c3e3a4749d81?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.stratio.com\/blog\/wp-json\/wp\/v2\/posts\/13710"}],"collection":[{"href":"https:\/\/www.stratio.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.stratio.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.stratio.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.stratio.com\/blog\/wp-json\/wp\/v2\/comments?post=13710"}],"version-history":[{"count":10,"href":"https:\/\/www.stratio.com\/blog\/wp-json\/wp\/v2\/posts\/13710\/revisions"}],"predecessor-version":[{"id":15653,"href":"https:\/\/www.stratio.com\/blog\/wp-json\/wp\/v2\/posts\/13710\/revisions\/15653"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.stratio.com\/blog\/wp-json\/wp\/v2\/media\/13713"}],"wp:attachment":[{"href":"https:\/\/www.stratio.com\/blog\/wp-json\/wp\/v2\/media?parent=13710"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.stratio.com\/blog\/wp-json\/wp\/v2\/categories?post=13710"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.stratio.com\/blog\/wp-json\/wp\/v2\/tags?post=13710"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.stratio.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=13710"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}