<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Sematic</title>
    <description>The latest articles on Forem by Sematic (@sematic).</description>
    <link>https://forem.com/sematic</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F6539%2F36756d0f-8768-45ad-9a36-29e547ec7f6a.png</url>
      <title>Forem: Sematic</title>
      <link>https://forem.com/sematic</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/sematic"/>
    <language>en</language>
    <item>
      <title>Sematic + Ray: The Best of Orchestration and Distributed Compute at your Fingertips</title>
      <dc:creator>Josh Bauer</dc:creator>
      <pubDate>Mon, 17 Apr 2023 19:56:08 +0000</pubDate>
      <link>https://forem.com/sematic/sematic-ray-the-best-of-orchestration-and-distributed-compute-at-your-fingertips-328m</link>
      <guid>https://forem.com/sematic/sematic-ray-the-best-of-orchestration-and-distributed-compute-at-your-fingertips-328m</guid>
      <description>&lt;h2&gt;
  
  
  Finding Dynamic Combos
&lt;/h2&gt;

&lt;p&gt;Getting Machine Learning (ML) infrastructure right is really hard. One of the challenges for any ML project getting off the ground is finding the right tools for the job. The number of tools out there that target different parts of the ML lifecycle can easily feel overwhelming.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KloZ6xaD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7ygrfb593b5trui8yfoa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KloZ6xaD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7ygrfb593b5trui8yfoa.png" alt="A sampling of tools that help with ML development, created by the Linux Foundation." width="512" height="300"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;em&gt;A sampling of tools that help with ML development, created by the &lt;a href="https://landscape.lfai.foundation/"&gt;Linux Foundation&lt;/a&gt;.&lt;/em&gt;



&lt;p&gt;Sometimes, two tools seem to “just fit” together, and you forget that you’re even working with multiple tools as the lines blur into a coherent experience. One example that every ML Engineer or Data Scientist is familiar with is &lt;a href="https://numpy.org/"&gt;numpy&lt;/a&gt; and &lt;a href="https://pandas.pydata.org/"&gt;pandas&lt;/a&gt;. Numpy enables fast and powerful mathematical computations with arrays/matrices in Python. Pandas provides higher-level data structures for manipulating tabular data. While you can of course use one without (explicitly) using the other, they complement each other so well that they are often used together. Pandas works as a usability layer, while numpy supercharges it with compute efficiency.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SarkDuHf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qgdtc8q36skbu05d28zk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SarkDuHf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qgdtc8q36skbu05d28zk.png" alt="Pandas and numpy working together seamlessly." width="512" height="133"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;em&gt;Pandas and numpy working together seamlessly.&lt;/em&gt;



&lt;p&gt;At Sematic, we care &lt;strong&gt;a lot&lt;/strong&gt; about usability. We aim to make your ML workflows as simple and intuitive as possible, while providing you with best-in-class lineage tracking, reproducibility guarantees, local/cloud parity, and more. You can chain together the different parts of your ML pipelines using Sematic, &lt;a href="https://docs.sematic.dev/public-api-reference/api#resource-requirements"&gt;and specify what kind of resources&lt;/a&gt; you need in the cloud. But many parts of the modern ML lifecycle require more than one computing node–you need a cluster. For example, training the &lt;a href="https://arxiv.org/abs/1709.05011"&gt;original ResNet-50 on a single GPU takes 14 days&lt;/a&gt;. Leveraging cluster computing can cut this time drastically. Sematic needed a tool to help supercharge it with cluster computing resources, ideally in a way that “just fits” with another tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ray
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.ray.io/"&gt;Ray&lt;/a&gt; pitches itself as “an open-source unified compute framework that makes it easy to scale AI and Python workloads.” Ray can be broken down into three major pieces:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Ray Core&lt;/strong&gt;:  some primitives for distributed communication, defining workloads and logic to be executed by the distributed compute layer, and initializing computing resources to interact with the system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ray-native domain libraries&lt;/strong&gt;: libraries provided “out of the box” with Ray for various parts of ML development, such as &lt;a href="https://docs.ray.io/en/latest/tune/index.html"&gt;hyperparameter tuning&lt;/a&gt;, &lt;a href="https://docs.ray.io/en/latest/data/dataset.html"&gt;data processing&lt;/a&gt;, and &lt;a href="https://docs.ray.io/en/latest/train/train.html"&gt;training&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ecosystem of integrations&lt;/strong&gt;: Ray integrates with many popular tools and frameworks within the broader ML landscape, such as Hugging Face, Spark, PyTorch, and many more.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With these pieces, Ray easily stands as a powerhouse for distributed computing within ML.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sematic + Ray
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wxlfIXmD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2jh947qdh5on3lbx8gfp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wxlfIXmD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2jh947qdh5on3lbx8gfp.png" alt="How Ray and Sematic complement each other." width="512" height="375"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;em&gt;How Ray and Sematic complement each other.&lt;/em&gt;



&lt;p&gt;Sematic was designed to let you create end-to-end ML pipelines with minimal development overhead, while adding visualization, lineage tracking, reproducibility, and more. In the language of Sematic, your pipeline steps are Sematic Functions–perhaps one for data processing, one for training, one for evaluation, and so on. Then, within these Sematic Functions, you can use Ray to efficiently scale data processing beyond a single compute node.&lt;/p&gt;

&lt;p&gt;That’s great as a conceptual model, but how does Sematic integrate with Ray in practice?&lt;/p&gt;

&lt;p&gt;When you’re authoring a pipeline, using Ray within a Sematic Function is as easy as using the RayCluster context manager inside the function. This will spin up a Ray cluster on-demand and enter the ‘with’ context only once the cluster is ready for use. Your code can then use Ray just like it would in any other situation. When your code is done executing (either successfully or unsuccessfully), the Ray cluster will be cleaned up for you. The Ray cluster uses the same container image as your pipeline so that the same code and dependencies are guaranteed to be present on every node.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--N3hYZGT---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nbju0qmij22yek5xguou.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--N3hYZGT---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nbju0qmij22yek5xguou.png" alt="Using Ray within Sematic." width="512" height="214"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;em&gt;Using Ray within Sematic.&lt;/em&gt;



&lt;p&gt;If you’re familiar with Ray or Sematic, you likely know that both can be used locally as well as in the cloud. Sematic’s Ray integration is no exception! When you execute the code above locally, a local-process based Ray cluster will be created instead of one executing on Kubernetes. This enables rapid local development, where you can use all of your favorite debuggers and other tools until you’re ready to move execution to the cloud.&lt;/p&gt;

&lt;h2&gt;
  
  
  Unlocking New Use Cases
&lt;/h2&gt;

&lt;p&gt;This combination of Sematic + Ray can jumpstart your journey to a world-class ML platform. Using these tools together, your Sematic Functions can now do things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do quick and efficient distributed training on a &lt;a href="https://pytorch.org/"&gt;PyTorch&lt;/a&gt; image classifier using &lt;a href="https://lightning.ai/docs/pytorch/stable/"&gt;PyTorch Lightning&lt;/a&gt; and Ray.&lt;/li&gt;
&lt;li&gt;Perform distributed Hyperparameter tuning of a &lt;a href="https://www.tensorflow.org/"&gt;TensorFlow&lt;/a&gt; natural language model using &lt;a href="https://docs.ray.io/en/latest/tune/index.html"&gt;Ray Tune&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Do distributed data processing and ingest with &lt;a href="https://docs.ray.io/en/latest/data/dataset.html"&gt;Ray Datasets&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And you can do all these things while taking advantage of Sematic’s lineage tracking, visualization and orchestration capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Look Behind the Scenes
&lt;/h2&gt;

&lt;p&gt;When you use RayCluster as above, there’s a lot going on behind the scenes. Sematic uses &lt;a href="https://docs.ray.io/en/latest/cluster/kubernetes/index.html"&gt;KubeRay&lt;/a&gt;, a tool developed by the maintainers of Ray to manage Ray clusters within Kubernetes. Your code execution will result in calls to the Sematic server, which will in turn publish information about the required cluster to KubeRay. KubeRay will then create and manage the new Ray cluster for you.&lt;/p&gt;

&lt;p&gt;Since Sematic knows all about your code and what container image it’s using, it can ensure that KubeRay uses that same image for the Ray head and workers. This means that you don’t have to worry about any new dependency management when using Ray from Sematic – any code that can be used from your Sematic Functions can be used from Ray, even without using Ray’s &lt;a href="https://docs.ray.io/en/latest/ray-core/handling-dependencies.html#runtime-environments"&gt;Runtime environments&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sJpoUyMo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wjx9olrh8yllkuwqf7zu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sJpoUyMo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wjx9olrh8yllkuwqf7zu.png" alt="Architecture of Ray + Sematic" width="512" height="419"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;em&gt;Architecture of Ray + Sematic&lt;/em&gt;



&lt;h2&gt;
  
  
  Learning More
&lt;/h2&gt;

&lt;p&gt;If you want to know more about Sematic’s Ray integration, you can check out &lt;a href="https://docs.sematic.dev/integrations/ray"&gt;our docs&lt;/a&gt;. If you’re looking for something more hands on, check out one of our examples doing distributed training and evaluation using Ray from Sematic. One uses PyTorch Lightning to &lt;a href="https://github.com/sematic-ai/sematic/blob/main/sematic/examples/lightning_resnet/README.md"&gt;do distributed training of a ResNet model&lt;/a&gt;, and another uses Ray’s AIR APIs (including Ray Datasets) to &lt;a href="https://github.com/sematic-ai/sematic/blob/main/sematic/examples/cifar_classifier/README.md"&gt;do distributed training of a simple image classifier&lt;/a&gt; on the &lt;a href="https://www.cs.toronto.edu/~kriz/cifar.html"&gt;CIFAR10 dataset&lt;/a&gt;. You can also join our Discord if you’d like to ask some questions. We’re always happy to help!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sematic’s Ray integration is part of Sematic’s paid “Enterprise Edition”. Get in touch if you’d like to use it! Rather play around with Sematic for free first? Most of it is &lt;a href="https://github.com/sematic-ai/sematic"&gt;free and open-source!&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>mlops</category>
      <category>datascience</category>
      <category>devops</category>
    </item>
    <item>
      <title>Implementing Deep Links in React with Atoms</title>
      <dc:creator>Chance An</dc:creator>
      <pubDate>Fri, 03 Feb 2023 22:38:36 +0000</pubDate>
      <link>https://forem.com/sematic/implementing-deep-links-in-react-with-atoms-289d</link>
      <guid>https://forem.com/sematic/implementing-deep-links-in-react-with-atoms-289d</guid>
      <description>&lt;h2&gt;
  
  
  What are deep links and why are they useful?
&lt;/h2&gt;

&lt;p&gt;Broadly speaking, Deep Links are a mobile app platform (Android/iOS) concept which allows users to get to a specific in-app location following a hyperlink. When this idea is generalized back to single-page applications (SPAs) on the web, it refers to using a URL enriched with additional information to guide a user to a specific state of the SPA. &lt;/p&gt;

&lt;p&gt;It allows users to return to the exact spot they were at, even after closing the app. Users can also share deep links with others to reproduce what the original user sees or refers to.&lt;/p&gt;

&lt;p&gt;So we need to persist the UI state in the URL. What states should be persisted in the URL? There is a limitation on how many characters you can put in the URL. Different browsers and server-ware enforce different limits. To be on the safe side, one should not design a URL that exceeds 2048 bytes in length.&lt;/p&gt;

&lt;p&gt;We cannot encode every state info a SPA uses into the URL. However, the user interactions applied to the app are in a controllable size; we can encode interaction-related information into the URL, hoping to recover the application state from the point when the user has already initiated the same interactions. &lt;/p&gt;

&lt;p&gt;Let's look at two examples:&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://sematic.dev" rel="noopener noreferrer"&gt;Sematic&lt;/a&gt;, when a user selects a nested run, we hope to share what the user sees with someone else through a deep link. So when other users open the website using the deep link, they will see the same nested run being selected. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F23tdf16q5y8abhsmbtte.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F23tdf16q5y8abhsmbtte.png" alt="Selecting a nested run in the Sematic Dashboard." width="726" height="1084"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The deep link has a form of&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://sematic.host/pipelines/pipeline_name/[root_run_id]#run=[nested_run_id]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Separately, when the user selects a view-specific tab on the run details page, we also hope the deep link reflects this selection. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe6wj7iv1nye8nctzzrmb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe6wj7iv1nye8nctzzrmb.png" alt="Run tabs in the Sematic Dashboard." width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this purpose, we add the &lt;code&gt;tab=tab_name&lt;/code&gt; hash segment into the URL with the following form.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://sematic.host/pipelines/pipeline_name/[root_run_id]#run=[nested_run_id]&amp;amp;tab=[tab]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://sematic.host/pipelines/pipeline_name/864ae3#run=33d7f&amp;amp;tab=output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why use hashes instead of paths or query strings?
&lt;/h2&gt;

&lt;p&gt;The other alternatives are to encode the information using query strings or as a part of the URL path segments.&lt;/p&gt;

&lt;p&gt;URL paths are reserved for React Router usage. We want to keep the deep linking and React Router operations separate for the sake of separating concerns. This way, we simplify React Router's work and avoid potential re-routing due to path changes.&lt;/p&gt;

&lt;p&gt;We didn't choose query strings because of a narrow interpretation of the differences between a query string and a hash:&lt;/p&gt;

&lt;p&gt;A hash works as an anchor on the webpage; conventionally, changing the URL hash should not trigger UI mutations. However, a navigational shift, like scrolling to a designated location, is typical for hash changes. Turning to a specific page of a business entity fits the semantics of hash changes. So this becomes one reason to adopt hash for deep linking.&lt;/p&gt;

&lt;p&gt;Another reason for choosing hash is because the Jotai library we adopted directly supports an easy API for manipulating and syncing with URL hash, which we will elaborate on next.&lt;/p&gt;

&lt;p&gt;Thirdly, hash fragments are not sent to the server. The browsers' side is usually more generous on the URL length limitation than the server applications. We have more room to store the deep link information on the hash fragments if we need to. &lt;/p&gt;

&lt;p&gt;Meanwhile, we also reserve the query strings to store feature flags, view settings, debug options, etc.&lt;/p&gt;

&lt;p&gt;It is also worth noting that choosing query parameters to store deep link information is also reasonable. For example, the Recoil library supports both.&lt;/p&gt;

&lt;p&gt;To summarize, in Sematic, we assign the following distinct responsibilities to different URL components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Path&lt;/strong&gt;: reserved for routing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Query string parameters&lt;/strong&gt;: feature flags and view settings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hash&lt;/strong&gt;: deep links &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Jotai and Recoil library
&lt;/h2&gt;

&lt;p&gt;Before talking about Jotai, let us first introduce &lt;a href="https://recoiljs.org" rel="noopener noreferrer"&gt;Recoil&lt;/a&gt;, from which the Jotai library gets a lot of inspiration. &lt;/p&gt;

&lt;p&gt;An Atom from Recoil is a unit of a state that is declared outside of the React component hierarchy. Different React components can subscribe to the changes of such an atom and can mutate the atom's state. The mutation of the atom will be propagated to each subscribing component and trigger its re-rendering. Using a Recoil atom is a way of sharing a global state across multiple components regardless of their locations in the component tree.&lt;/p&gt;

&lt;p&gt;How does this compare to &lt;a href="https://reactjs.org/docs/context.html" rel="noopener noreferrer"&gt;React Context&lt;/a&gt;? &lt;/p&gt;

&lt;p&gt;React Context API is more verbose in injecting context providers in the ancestry. It sometimes causes unnecessary re-renderings. One way to avoid those is to disintegrate the state groups in smaller, dispersed contexts. But this might also lead to pyramids of doom when writing too many nested provider declarations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;context1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;context2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;context3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;context4&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value4&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;context5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;value5&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/context5.Provider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/context4.Provider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/context3.Provider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/context2.Provider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/context1.Provider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An Atom is more lightweight. It can be declared individually. As its name suggests, it is atomic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;todoListState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
 &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TodoList&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
 &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;TodoList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;todoList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRecoilValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;todoListState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* &amp;lt;TodoListStats /&amp;gt; */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* &amp;lt;TodoListFilters /&amp;gt; */&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TodoItemCreator&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;

     &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todoList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;todoItem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
       &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TodoItem&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todoItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;todoItem&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;     &lt;span class="p"&gt;))}&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://jotai.org" rel="noopener noreferrer"&gt;Jotai&lt;/a&gt; is another library that shares a lot of features with Recoil. This article will focus on one particular hook &lt;a href="https://jotai.org/docs/integrations/location#atom-with-hash" rel="noopener noreferrer"&gt;&lt;code&gt;atomWithHash()&lt;/code&gt;&lt;/a&gt; in the jota-location integration, which allows us to manipulate URL hash segments and subscribe to their changes directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useAtom&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jotai&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;atomWithHash&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jotai-location&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;countAtom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;atomWithHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;count&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAtom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;countAtom&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;     &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This &lt;code&gt;useAtom&lt;/code&gt; hook returns the current value of a hash segment and a state updater function. The hook consumers will be notified of the updated value in a new rendering cycle whenever the hash segment changes. The state updater function updates the atom's value and the URL's corresponding hash fragment. &lt;/p&gt;

&lt;p&gt;In Sematic, we think having a global state utility using the atom mechanism is applicable. Jotai is more streamlined with updated ergonomic APIs. We have adopted Jotai in the front-end application of Sematic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation of deep links
&lt;/h2&gt;

&lt;p&gt;With the help of &lt;code&gt;jotai&lt;/code&gt;, implementing deep-link becomes easy. For instance, when we need to generate a deep link of the selected nested run, we store the selected run ID with a Jotai hash atom. So whenever the atom for storing the selected run ID is changed, the corresponding hash linked to the atom will be automatically updated in the URL. The user will directly pick the updated URL in the browser address bar as the new deep link. &lt;/p&gt;

&lt;p&gt;When a user opens a deep link in a new browser tab, the initial state of the atom will be hydrated with the value from the URL hash segment. So the consumer components will retrieve the selected run ID represented by the hash in the deep link URL, then drive the successive rendering. &lt;/p&gt;

&lt;p&gt;During the implementation, we also learned about the following caveats, which might be interesting to the readers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Serialization
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;atomWithHash()&lt;/code&gt; has a config option to support serializing the state value into the hash string and vice versa. By default, it uses JSON serialization and deserialization. If the atom's value type is string, it will become "value" (quotes included) in the hash string because a JSONified string value has quote marks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr43u7y25ovt1rljknnvq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr43u7y25ovt1rljknnvq.png" alt="Jsonfying a Javascript string in the console of Chrome developer tools." width="414" height="130"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A straight string-to-string conversion will eliminate the quote marks. &lt;/p&gt;

&lt;p&gt;With default serialization, we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://sematic.host/pipelines/pipeline_name/864ae3#tab="output"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After using custom serialization/deserialization functions, we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://sematic.host/pipelines/pipeline_name/864ae3#tab=output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Hash change with unwanted intermediate states
&lt;/h2&gt;

&lt;p&gt;After the Jotai takes over certain hash segments atoms, for most cases, one should not touch the hash in the URL directly instead of using the atom updater function to drive the hash change. There are, however, some edge cases when you have to manually change some hash segments when you want to update the URL path component simultaneously. This can happen when you want to navigate to a new page with an alternative hash value. If you use the updater function to change the hash, followed by a URL path change, you get two records in the browser history stack. The problem will surface when a user uses the browser's back button to navigate back, which will lead the user to an invalid intermediate page state.&lt;/p&gt;

&lt;p&gt;Analyzing Jotai's &lt;a href="https://github.com/jotaijs/jotai-location/blob/9debe926481f27b21617c587a3a6442ff0bad58d/src/atomWithHash.ts#L88" rel="noopener noreferrer"&gt;source code&lt;/a&gt; leads us to a solution. Jotai uses &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams" rel="noopener noreferrer"&gt;&lt;code&gt;URLSearchParams&lt;/code&gt;&lt;/a&gt; to manipulate the hash portion of the URL. This approach can change only a specific sub-component of the hash portion instead of rewriting the entire hash string. When we do page navigation, we will likely only need to change one hash sub-component while keeping other sub-components in the deep link untouched. After understanding its principle, whenever you have to do a path change with a hash change. Do the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Grab the current hash component of the URL&lt;/li&gt;
&lt;li&gt;Utilize &lt;code&gt;URLSearchParams&lt;/code&gt; to replace the value of a specific hash chip in the entire hash string.&lt;/li&gt;
&lt;li&gt;Take the revised hash component by reading &lt;code&gt;URLSearchParams&lt;/code&gt; again (&lt;code&gt;.toString()&lt;/code&gt;). Combine it with the new path value and update the URL in an atomic operation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Jotai's &lt;code&gt;atomWithHash&lt;/code&gt; supports an option &lt;code&gt;replaceState&lt;/code&gt;, which controls whether hash updates will create new browser history records. Unfortunately, it is an atom-level configuration. It would perfectly solve the issue above if it could be specified on a per-update basis.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do you implement deep linking in your project?
&lt;/h3&gt;

&lt;p&gt;Reach out to us on &lt;a href="https://discord.gg/4KZJ6kYVax" rel="noopener noreferrer"&gt;Discord&lt;/a&gt; to discuss deep links or other topics.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/notsidney/how-and-why-you-should-store-react-ui-state-in-the-url-34pi"&gt;https://dev.to/notsidney/how-and-why-you-should-store-react-ui-state-in-the-url-34pi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://recoiljs.org/docs/recoil-sync/url-persistence/#part-of-the-url" rel="noopener noreferrer"&gt;https://recoiljs.org/docs/recoil-sync/url-persistence/#part-of-the-url&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jotai.org/" rel="noopener noreferrer"&gt;https://jotai.org/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>career</category>
      <category>productivity</category>
      <category>discuss</category>
    </item>
    <item>
      <title>What is “production” Machine Learning?</title>
      <dc:creator>Emmanuel Turlay</dc:creator>
      <pubDate>Wed, 18 Jan 2023 23:28:31 +0000</pubDate>
      <link>https://forem.com/sematic/what-is-production-machine-learning-22mk</link>
      <guid>https://forem.com/sematic/what-is-production-machine-learning-22mk</guid>
      <description>&lt;p&gt;In traditional software development, “production” typically refers to instances of an application that are used by actual users – human or machine.&lt;/p&gt;

&lt;p&gt;Whether it’s a web application, an application embedded in a device or machine, or a piece of infrastructure, production systems receive real-world traffic and are supposed to accomplish their mission without issues.&lt;/p&gt;

&lt;p&gt;Production systems usually come with these guarantees:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Safety&lt;/strong&gt; – Before the application is deployed in production, it is thoroughly tested by an extensive suite of unit tests, integration tests, and sometimes manual tests. Scenarios covering happy-paths and corner cases are checked against expected results.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Traceability&lt;/strong&gt; – A record is kept of exactly what code was deployed, by whom, at what time, with what configurations, and to what infrastructure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observability&lt;/strong&gt; – Once the system is in production, it is possible to access logs, observe real-time resource usage, and get alerted when certain metrics veer outside of acceptable bounds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt; – The production system is able to withstand the expected incoming traffic and then some. If necessary, it is capable of scaling up or down based on demand and cost constraints.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is a production ML system?
&lt;/h2&gt;

&lt;p&gt;Some ML models are deployed and served by an endpoint (e.g. REST, gRPC), or directly embedded inside a larger application. They generate inferences on demand for each new sets of features sent their way (i.e. real-time inferencing).&lt;/p&gt;

&lt;p&gt;Others are developed for the purpose of generating a set of inferences and persisting them in a database table as a one time task (i.e. batch inferencing). For example, a model can predict a set of customers’ lifetime value, write those in a table for consumption by other systems (metrics dashboard, downstream models, production applications, etc.).&lt;/p&gt;

&lt;p&gt;Whether built for real-time or batch inferencing, a production ML system refers to the end-to-end training and inferencing pipeline: the entire chain of transformations that turn raw data sitting in a data warehouse, into a trained model, which is then used to generate inferences.&lt;/p&gt;

&lt;h2&gt;
  
  
  What guarantees for production ML systems?
&lt;/h2&gt;

&lt;p&gt;We saw at the top what guarantees are expected from a traditional software system. What similar guarantees should we expect from production-grade ML systems?&lt;/p&gt;

&lt;h3&gt;
  
  
  Safety
&lt;/h3&gt;

&lt;p&gt;In ML, safety means having a high level of certainty that inferences produced by a model fall within the bounds of expected and acceptable values, and do not endanger users – human or machine.&lt;/p&gt;

&lt;p&gt;For example, safety means that a self-driving car will not drive dangerously on the road, or that a facial recognition model will not show biases, or that a chat bot will not generate abusive messages.&lt;/p&gt;

&lt;p&gt;Safety in ML systems can be guaranteed in the following ways.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unit testing&lt;/strong&gt; – Each piece of code used to generate a trained model should be unit-tested. Data transformation functions, data sampling strategies, evaluation methods, etc. should be confronted to both happy-path inputs and a reasonable set of corner cases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model testing, simulation&lt;/strong&gt; – After the model is trained and evaluated, real production data should be sent to it to establish an estimate of how the model will behave once deployed. This can be achieved by e.g. sending a small fraction of live production traffic to a candidate model and monitoring inferences, or by subjecting the model to a set of must-pass scenarios (real or synthetic) to ensure that no regressions are introduced.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Traceability
&lt;/h3&gt;

&lt;p&gt;In ML, beyond simply tracking what model version was deployed, it is crucial to enable exhaustive so-called Lineage Tracking.&lt;/p&gt;

&lt;p&gt;End-to-end Lineage Tracking means a complete bookkeeping of ALL the assets and artifacts involved in the production of every single inference.&lt;/p&gt;

&lt;p&gt;This means tracking&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The raw dataset used as input&lt;/li&gt;
&lt;li&gt;All of the intermediate data transformation steps&lt;/li&gt;
&lt;li&gt;Configurations used at every step: featurization, training, evaluation, etc.&lt;/li&gt;
&lt;li&gt;The actual code used at every step&lt;/li&gt;
&lt;li&gt;What resources the end-to-end pipeline used (map/reduce clusters, GPU types, etc.)&lt;/li&gt;
&lt;li&gt;Inferences generated by the deploy model&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;as well as the lineage relationships between those.&lt;/p&gt;

&lt;p&gt;Lineage Tracking enables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Auditability&lt;/strong&gt; – If a deployed model leads to undesired behaviors, an in-depth post-mortem investigation is made possible by using lineage data. This is especially important for models performing safety critical tasks (e.g. self-driving cars) where legal and compliance requirements demand auditability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debugging&lt;/strong&gt; – It is virtually impossible to debug a model without knowing what data, configuration, code, and resources were used to train it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reproducibility&lt;/strong&gt; – See below.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Reproducibility
&lt;/h3&gt;

&lt;p&gt;If a particular inference cannot be reproduced from scratch (within stochastic variations) starting from raw data, the corresponding model should arguably not be used in production. This would be like deploying an application when you had lost the source code with no way to retrieve it.&lt;/p&gt;

&lt;p&gt;Without the ability to reproduce a particular trained model, there is no explainability of the model and its inferences. It is impossible to debug production issues.&lt;/p&gt;

&lt;p&gt;Additionally, reproducibility enables rigorous experimentation. The entire end-to-end pipeline can be re-run while changing a single degree of freedom at a time (e.g. input data selection, sampling strategy, hyper-parameters, hardware resources, training code, etc.)&lt;/p&gt;

&lt;h3&gt;
  
  
  Automation
&lt;/h3&gt;

&lt;p&gt;ML models are not one-and-done type of projects. Often times, the characteristics of the training data change over time, and the model needs to be retrained recurrently to pick up on new trends.&lt;/p&gt;

&lt;p&gt;For example, when real-world conditions change (e.g. COVID, macro-economic changes, user trends, etc.), models can lose predictive power if they are not retrained frequently.&lt;/p&gt;

&lt;p&gt;This frequent retraining can only be achieved if an end-to-end pipeline exists. If engineers can simply run or schedule a pipeline pointing to new data, and all steps are automated (data processing, featurization, training, evaluation, testing, etc.) then refreshing a model is no harder than deploying a web app.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Sematic provides production-grade guarantees
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://sematic.dev" rel="noopener noreferrer"&gt;Sematic&lt;/a&gt; is an open-source framework to build and execute end-to-end ML pipelines of arbitrary complexity.&lt;/p&gt;

&lt;p&gt;Sematic helps build production-grade pipelines by ensuring the guarantees listed above in the following way, without requiring any additional work.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Safety&lt;/strong&gt; – In Sematic, all pipelines steps are just Python functions. Therefore, they can be unit-tested as part of a CI pipeline. Model testing/simulation is enabled by simply adding downstream steps after model training and evaluations steps. Trained model can be subjected to real or simulated data to ensure the absence of regressions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Traceability&lt;/strong&gt; – Sematic keeps an exhaustive lineage graph of ALL assets consumed and produced by all steps in your end-to-end pipelines: inputs and outputs of all steps, code, third-party dependencies, hardware resources, etc. All these are visualizable in the Sematic UI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reproducibility&lt;/strong&gt; – By enabling complete traceability of all assets, Sematic lets you re-execute any past pipeline with the same or different inputs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automation&lt;/strong&gt; – Sematic enables users to build true end-to-end pipelines, from raw data to deployed model. These can then be scheduled to pick up on new data automatically&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check us out at &lt;a href="https://sematic.dev" rel="noopener noreferrer"&gt;sematic.dev&lt;/a&gt;, &lt;a href="https://github.com/sematic-ai/sematic" rel="noopener noreferrer"&gt;star us on Github&lt;/a&gt;, and &lt;a href="https://discord.gg/4KZJ6kYVax" rel="noopener noreferrer"&gt;join us on Discord&lt;/a&gt; to discuss production ML.&lt;/p&gt;

</description>
      <category>welcome</category>
      <category>community</category>
    </item>
  </channel>
</rss>
