<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Adrien Treuille on Medium]]></title>
        <description><![CDATA[Stories by Adrien Treuille on Medium]]></description>
        <link>https://medium.com/@adrien.g.treuille?source=rss-39dfc90d7a34------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/2*p1XpZztbSsl7q45ooNneSQ.jpeg</url>
            <title>Stories by Adrien Treuille on Medium</title>
            <link>https://medium.com/@adrien.g.treuille?source=rss-39dfc90d7a34------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 00:59:35 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@adrien.g.treuille/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Introducing Streamlit Sharing]]></title>
            <link>https://medium.com/data-science/introducing-streamlit-sharing-b4f520e3d95?source=rss-39dfc90d7a34------2</link>
            <guid isPermaLink="false">https://medium.com/p/b4f520e3d95</guid>
            <category><![CDATA[deployment]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[streamlit]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[Adrien Treuille]]></dc:creator>
            <pubDate>Thu, 15 Oct 2020 19:31:02 GMT</pubDate>
            <atom:updated>2020-10-16T05:39:45.602Z</atom:updated>
            <content:encoded><![CDATA[<h4>Deploy, manage, and share your Streamlit apps for free</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4kPwfwTWQgwg7W_-scycqg.gif" /></figure><p>Machine learning and data science code is easy to share but hard to use. GitHub overflows with models, algorithms, and datasets. But code is static. Can you play with the models? See the algorithms? Interact with the data? Doing so requires following complex instructions, installing packages, or reading dense code snippets. Frustrated by this, we decided that <strong>we need a simple, sharable “play” button for machine learning code.</strong></p><p>There are two challenges here. The first is <strong>creating</strong> apps that make data science and machine learning code interactive. The second is <strong>sharing</strong> these apps so that the world can experience your work.</p><p>A year ago, we addressed the first challenge — <strong>creating — </strong>by releasing Streamlit, an open-source library that lets you transform Python scripts into interactive apps. Streamlit lets you easily demonstrate algorithms, play with models, manipulate data, and combine all of these superpowers into beautiful apps. The response has been tremendous. We just crossed our millionth download. Hundreds of thousands of Streamlit apps have been created all over the world. <strong>But creating great apps only solves half the problem.</strong></p><h3>Easily deploy and share your Streamlit apps</h3><p>Today, we address the second challenge — <strong>sharing</strong> — by announcing a brand-new sharing platform for Streamlit. Streamlit sharing lets you deploy, manage, and share your apps — all for free! If you have a Streamlit app hosted publicly on GitHub, you are now one click away from sharing it with the world.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*qJCQcHZ-tg38n1nC.png" /></figure><h3>GitHub and Streamlit — Better Together</h3><p>Streamlit sharing <strong>combines the best of Streamlit with the best of GitHub.</strong> From Streamlit you get a simple framework for creating incredibly rich and useful apps. From GitHub you inherit an incredible framework for social collaboration. Paste your GitHub link into Streamlit’s sharing platform and almost instantly you have a live app. Or, click on the menu for any live app and see its source code on GitHub. Collaborate for free simply by forking and editing the code. It’s global, shareable, fork-able, collaborative data science!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Pb1NNjiDgDOj_VCd.png" /></figure><h3>Endless Possibilities</h3><p>Taken together, Streamlit and GitHub enable an <a href="https://streamlit.io/gallery">incredibly rich and diverse ecosystem of useful apps</a> — from dashboards to deep nets and beyond! (As former Carnegie Mellon folks, we’re especially proud that students taking the <a href="https://dig.cmu.edu/courses/2020-fall-interactive-ds.html">Interactive Data Science</a> class now submit their homework using Streamlit sharing 🤗) Here are some awesome examples of shared Streamlit apps that you can play with right now.</p><p>While this post has focused on open source applications, Streamlit is also used by thousands of companies to build sophisticated internal data tools. For example, Uber has deployed Streamlit company-wide, enabling data scientists to share their work throughout the company. <strong>Streamlit for Teams</strong> extends Streamlit’s sharing platform to bring secure, seamless app deployment, management, and collaboration <em>within</em> your enterprise. If you’re interested please <a href="https://streamlit.io/for-teams">sign up for the beta for Streamlit for Teams</a>.</p><h3>Get Your Invitation to Streamlit Sharing</h3><p>To celebrate the launch, we’ll be<strong> releasing 1,000 invitations for Streamlit sharing</strong> <strong>— </strong>with more invites coming as our server capacity grows. If you don’t have one in your inbox already, please <a href="https://streamlit.io/sharing">request an invite</a> and we’ll get you one soon.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*f7XvOlawiwOSRc6B.png" /></figure><h3>The Streamlit Play Button</h3><p>This new sharing superpower completes the Streamlit circle — from creation to sharing, and back again. So create! Share with the world! Let others see your work, fork, merge, and contribute to the cycle of knowledge creation. In that spirit, we offer one last gift: <strong>This is our “play” button.</strong></p><figure><a href="https://share.streamlit.io/streamlit/demo-uber-nyc-pickups/"><img alt="" src="https://cdn-images-1.medium.com/max/135/1*BuBYzjmSARgadMhzMURFog@2x.png" /></a></figure><p>This brand-new badge helps others find and play with your Streamlit app. Embed it right into your GitHub readme.md as follows:</p><pre>[![Streamlit App](https://static.streamlit.io/badges/streamlit_badge_black_white.svg)](https://share.streamlit.io/yourGitHubName/yourRepo/yourApp/)</pre><p>Thank you all for inspiring us with your amazing creations. We’re excited to see what you build and share. 🎈</p><p><em>A huge thank you from all of us at Streamlit to all of you in the community — and especially the inaugural Streamlit Creators, </em><a href="https://discuss.streamlit.io/u/ash2shukla/summary"><em>Ashish</em></a><em>, </em><a href="https://discuss.streamlit.io/u/charly_wargnier/summary"><em>Charly</em></a><em>, </em><a href="https://discuss.streamlit.io/u/andfanilo/summary"><em>Fanilo</em></a><em>, </em><a href="https://discuss.streamlit.io/u/napoles3d/summary"><em>José</em></a><em>, </em><a href="https://discuss.streamlit.io/u/jesse_jcharis/summary"><em>Jesse</em></a><em>, and </em><a href="https://discuss.streamlit.io/u/synode/summary"><em>Synode</em></a><em> — for your kindness, your feature requests, your bug reports, and your enthusiasm. Special thanks also to all the launch app creators, Alex, Dan, Ines | Explosion, and finally Tyler who created not only the </em><a href="https://share.streamlit.io/tylerjrichards/book_reco/master/books.py"><em>Goodreads app</em></a><em> but also a great sharing tutorial.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b4f520e3d95" width="1" height="1" alt=""><hr><p><a href="https://medium.com/data-science/introducing-streamlit-sharing-b4f520e3d95">Introducing Streamlit Sharing</a> was originally published in <a href="https://medium.com/data-science">TDS Archive</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Introducing Streamlit Components]]></title>
            <link>https://blog.streamlit.io/introducing-streamlit-components-d73f2092ae30?source=rss-39dfc90d7a34------2</link>
            <guid isPermaLink="false">https://medium.com/p/d73f2092ae30</guid>
            <dc:creator><![CDATA[Adrien Treuille]]></dc:creator>
            <pubDate>Tue, 14 Jul 2020 14:40:18 GMT</pubDate>
            <atom:updated>2020-07-14T17:11:17.273Z</atom:updated>
            <content:encoded><![CDATA[<h4>A new way to add and share custom functionality for Streamlit apps</h4><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FCmSKVW1v0xM&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DCmSKVW1v0xM&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/457e35689b6e49b2d1516caf6ee77c44/href">https://medium.com/media/457e35689b6e49b2d1516caf6ee77c44/href</a></iframe><p>In the ten months since Streamlit was released, the community has created over 250,000 apps for everything from <a href="http://adilmoujahid.com/posts/2020/06/streamlit-messi-ronaldo/">analyzing soccer games</a> to <a href="https://github.com/TKassis/OrgaQuant">measuring organoids</a>, and from <a href="http://predictivehealthcare.pennmedicine.org/2020/03/14/accouncing-chime.html">COVID-19 tracking</a> to <a href="https://huggingface.co/zero-shot/">zero-shot topic classification</a>. Inspired by your creativity, we added <a href="https://github.com/streamlit/streamlit/pull/488">file uploaders</a>, <a href="https://github.com/streamlit/streamlit/pull/1325">color pickers</a>, <a href="https://github.com/streamlit/streamlit/pull/1483">date ranges</a>, and other features. But as the complexity of serving the community grew, we realized that we needed a more scalable way to grow Streamlit’s functionality. So we’re turning to Streamlit’s best source of ideas: you!</p><p>Today, we are excited to announce <em>Streamlit Components, </em>the culmination of a multi-month project to enable the Streamlit community to create and share bits of functionality. Starting in Streamlit version 0.63, you can tap into the component ecosystems of React, Vue, and other frameworks. Create new widgets with custom styles and behaviors or add new visualizations and charting types. The possibilities are endless!</p><h3>The Streamlit Components Gallery</h3><p>The first thing you should do is check out the <a href="http://streamlit.io/components">Streamlit Components Gallery</a> to see what others have created and shared.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iVJmnUvv83cM6HvJ2NcZ9g.png" /></figure><p>Each component can be installed with just a single line of code:</p><pre>pip install some_cool_component</pre><p>If you don’t find a component that works for you, you can make your own!</p><h3>Building your own components</h3><p>Streamlit has a unique, functional style which lets you create rich, interactive experiences in very few lines of code. For example, let’s check out this simple Streamlit app:</p><pre>import streamlit as st</pre><pre>x = st.slider(&#39;x&#39;)<br>st.markdown(f&#39;`{x}` squared is `{x * x}`&#39;)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hvNO9Y68zvwqoQmgHbaqkQ.png" /></figure><p>Looking at this code, you can see that Streamlit calls come in two flavors: <strong>static components</strong> like st.markdown are stateless and only send data <em>to</em> the browser, whereas <strong>bidirectional components</strong> like st.slider have internal state and send data <em>back from</em> the browser.</p><p>Our challenge was to provide an API that embraces Streamlit’s functional style while capturing these use-cases as simply as possible. A few months ago, two amazing Streamlit engineers, Tim Conkling and Henrikh Kantuni, tackled this challenge and came up with a super elegant solution. The result is the new streamlit.components.v1 package which comprises three functions. For static components, we added:</p><ul><li>html(...), which lets you build components out of HTML, Javascript, and CSS</li><li>iframe(...) , which lets you embed external websites</li></ul><p>For bidirectional components, we added:</p><ul><li>declare_component(...), which lets you build interactive widgets which bidirectionally communicate between Streamlit and the browser.</li></ul><p>Let’s dive into how it works!</p><h3>Static Components</h3><p>Let’s start with a simple <strong>static component</strong> to embed snippets of code called <em>Github gists </em>in your app. Ideally, adding the component should just be a single function call:</p><pre># Render a gist<br>github_gist(&#39;tc87&#39;, &#39;9382eafdb6eebde0bca0c33080d54b58&#39;)</pre><p>which would render a gist like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rUEG-BKT4aM1khaEYSgvog.png" /></figure><p>To create such a component, we start by importing the Streamlit Components library:</p><pre>import streamlit.components.v1 as components</pre><p>This somewhat wordy import statement serves two purposes:</p><ol><li>It versions the components API so that future changes don’t break existing components.</li><li>It reminds us that we’re starting to use deep magic which we should hide from the user.</li></ol><p>Now let’s use the html(...) method to serve up the gist:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c324152fb93f6a032ccd00d5d8676a5b/href">https://medium.com/media/c324152fb93f6a032ccd00d5d8676a5b/href</a></iframe><p>This approach has a few awesome properties. First, it’s really simple and functional. In fact, this pattern lets you hide the ugly-looking HTML and wrap it into a pretty, Pythonic function call, github_gist(...). You can wrap code in a function and reuse it throughout your project. (Better yet, put it in a package and share it with the community in the gallery.) Second, note that we can add arbitrary HTML in this component — divs, spans, and yes, scripts! We can do this safely because the component is sandboxed in an iframe which lets us include external scripts without worrying about security problems.</p><h3>Getting widget with it!</h3><p>What if you want to create a stateful <strong>bidirectional component</strong> that passes information back to Python from the browser, or in other words, a <em>widget</em>? You can do this too! For example, let’s create a counter component:</p><pre>count = counter(name=&quot;Fanilo&quot;)<br>st.write(&#39;The count is&#39;, count)</pre><p>which creates this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OiHcNHh-zVYRF6MHr9wT0w.png" /></figure><p>Note that this code follows Streamlit’s unique functional style and captures the counter <em>state</em> embedded in the component. How did we achieve this? Happily, a single function call, declare_component, does all the work to enable bidirectional communication with Streamlit.</p><pre># Declare a simple counter component.<br>import streamlit.components.v1 as components<br>counter = components.declare_component(&quot;counter&quot;, path=BUILD_PATH)</pre><p>Nice! Under the hood, BUILD_PATH points to a component built using React, Vue, or any frontend technology you like. For this example we decided to use React and Typescript giving us this render function:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/86ba5e661f92c94e0ec1f2666ce6d951/href">https://medium.com/media/86ba5e661f92c94e0ec1f2666ce6d951/href</a></iframe><p>and this callback:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6d43ff0fe6650a14de14fa53117bc87a/href">https://medium.com/media/6d43ff0fe6650a14de14fa53117bc87a/href</a></iframe><p>Donezo! You’ve now created a simple, stateful component which “feels like React” on the website, and “feels like Streamlit” on the Python side. Information is passed back to Python using Streamlit.setComponentValue(...). Because we’re using React in this case, the component’s state is stored in this.state. For more details on this example, see our <a href="http://github.com/streamlit/component-template">component template</a>.</p><p>A neat benefit of this architecture is that you’re not limited to React. You can use any language or framework which compiles for the web. <a href="https://github.com/kantuni/streamlit-meets-cljs">Here is the same counter component</a> written in ClojureScript.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/136e3e14c937d30e2ce9e092a5b4fb42/href">https://medium.com/media/136e3e14c937d30e2ce9e092a5b4fb42/href</a></iframe><p>Another cool feature of this API is that you can do hot-reloading as you develop your component like this:</p><pre>components.declare_component(name, url=&quot;http://localhost:3001&quot;)      </pre><p>Here, the url parameter lets you specify a dev server for the component <a href="https://github.com/streamlit/component-template#quickstart">created with </a><a href="https://github.com/streamlit/component-template#quickstart">npm run start</a>.</p><p>What we’ve shown you so far just scratches the surface. For more details, <a href="https://docs.streamlit.io/en/stable/streamlit_components.html">please check our documentation</a>.</p><h3>Sharing with the world</h3><p>Did you create something broadly useful for the Streamlit community? Sure, you could keep that superpower for yourself, but it would be even cooler to share it! Get community feedback and praise. 😇 You can easily wrap your component in a PyPi package and <a href="https://docs.streamlit.io/en/stable/publish_streamlit_components.html#publish-streamlit-component-to-pypi">submit it to our Gallery by following these instructions</a>.</p><h3>Try it out and let us know what you think!</h3><p>We’re excited to unlock for the community a new way to plug-and-play functionality into Streamlit. Streamlit Components let you write simple HTML extensions or tap into the whole ecosystem provided by React, Vue, and other frameworks. Your feedback drives innovation in Streamlit. Please tell us what you think and what you’d like next. Show off your shiny new components and share them with the world. We can’t wait to see what you build! 🎈</p><p><em>Special thanks to Fanilo Andrianasolo, Daniel Haziza, Synode, and the entire Streamlit Components beta community who helped refine this architecture and inspired us with their feedback and ideas. Thanks also to TC Ricks, Amanda Kelly, Thiago Teixeira, Beverly Treuille, Regan Carey, and Cullan Carey for their input on this article.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d73f2092ae30" width="1" height="1" alt=""><hr><p><a href="https://blog.streamlit.io/introducing-streamlit-components-d73f2092ae30">Introducing Streamlit Components</a> was originally published in <a href="https://blog.streamlit.io/">Streamlit</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Announcing Streamlit’s $21M Series A]]></title>
            <link>https://blog.streamlit.io/announcing-streamlits-21m-series-a-ae05daa6c885?source=rss-39dfc90d7a34------2</link>
            <guid isPermaLink="false">https://medium.com/p/ae05daa6c885</guid>
            <dc:creator><![CDATA[Adrien Treuille]]></dc:creator>
            <pubDate>Tue, 16 Jun 2020 13:50:36 GMT</pubDate>
            <atom:updated>2020-06-16T17:36:37.222Z</atom:updated>
            <content:encoded><![CDATA[<p>Developing new superpowers for the data science community.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cNmECa-_RIRXQRfofXILuQ.jpeg" /></figure><p>In 2018, we began building the tools to visualize Python scripts that became Streamlit. By then, Python was the preeminent language of machine learning, bristling with powerful libraries like Keras and OpenCV. Python made it easy to analyze rich datasets and train detailed models. However, our decade of machine learning work at Carnegie Mellon, Google, and Zoox had shown us the difficulty of extending these newfound powers throughout an organization. We wanted to share models and insights with coworkers. We wanted to build custom tools that made machine learning repeatable, shareable, modifiable, and usable throughout an organization. We wanted to show off our work in beautiful apps that let others use what we had created.</p><p>Last Fall, after a year of development, we released <a href="http://streamlit.io/">Streamlit</a>, an open-source framework <a href="https://towardsdatascience.com/coding-ml-tools-like-you-code-ml-models-ddba3357eace?source=friends_link&amp;sk=f7774c54571148b33cde3ba6c6310086">to turn Python scripts into interactive apps</a>. The response exceeded our greatest expectations. Streamlit has been downloaded over 400,000 times and is now democratizing data-driven decision making across virtually every industry, from tech giants like Google and Uber to Delta Dental, 7–11, and even the NBA! Over 200,000 Streamlit apps have been created, and every day we see the Streamlit community share apps to predict COVID rates, visualize new chemical compounds, analyze music playlists, recommend movies, and <a href="http://streamlit.io/gallery">much, much more</a>. We are awed, inspired, and delighted daily by the community’s creativity.</p><p>Today we are excited to announce a $21 million Series A investment into Streamlit, co-led by GGV Capital and Gradient Ventures, and with participation from Bloomberg Beta, Elad Gil, Daniel Gross, and few other amazing investors.</p><p>This investment will enable us to develop new <a href="https://twitter.com/stbunzel/status/1187106264335171584">superpowers</a> for the Streamlit community. Our goal is to make Streamlit not only the most productive (and fun!) app-building experience in Python, but also <a href="https://discuss.streamlit.io/t/the-streamlit-roadmap-big-plans-for-2020/2054">the most powerful</a>. We’ll be introducing new ways to extend apps, including releases for custom layout and programmable state. The investment will also accelerate the development of Streamlit for Teams, our forthcoming paid offering for deploying, securing, and sharing Streamlit apps, that includes a free tier for public Github repos. It’s currently in closed beta, and we’ll be expanding the beta soon! Thank you for your patience, and if you haven’t signed up yet, <a href="https://www.streamlit.io/for-teams">click here</a>.</p><p>Thank you for trying, using, and loving Streamlit. The apps you create, articles you share, and messages you send make us eager to come to work every day and build Streamlit into an even more amazing tool for everyone. We’re excited to start this new chapter with you and to see what we can build together. Let’s start creating! 🎈</p><p>Adrien Treuille, Amanda Kelly, and Thiago Teixeira <br>- Streamlit Co-founders</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ae05daa6c885" width="1" height="1" alt=""><hr><p><a href="https://blog.streamlit.io/announcing-streamlits-21m-series-a-ae05daa6c885">Announcing Streamlit’s $21M Series A</a> was originally published in <a href="https://blog.streamlit.io/">Streamlit</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Build an app to synthesize photorealistic faces using TensorFlow and Streamlit]]></title>
            <link>https://medium.com/data-science/build-an-app-to-synthesize-photorealistic-faces-using-tensorflow-and-streamlit-dd2545828021?source=rss-39dfc90d7a34------2</link>
            <guid isPermaLink="false">https://medium.com/p/dd2545828021</guid>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[app-development]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[python]]></category>
            <dc:creator><![CDATA[Adrien Treuille]]></dc:creator>
            <pubDate>Wed, 01 Apr 2020 02:43:11 GMT</pubDate>
            <atom:updated>2020-04-01T18:27:49.212Z</atom:updated>
            <content:encoded><![CDATA[<h3>Build an app to generate photorealistic faces using TensorFlow and Streamlit</h3><h4>We’ll show you how to quickly build a Streamlit app to synthesize celebrity faces using GANs, Tensorflow, and st.cache.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*kqTo76YSl92YkYDV" /><figcaption>[GAN-synthesized face]</figcaption></figure><p>Machine learning models are black boxes. Yes, you can run them on test sets and plot fancy performance curves, but it’s <em>still</em> often hard to answer basic questions about how they perform. A surprisingly powerful source of insight is simply to <strong>play with your models</strong>! Tweak inputs. Watch outputs. Let your coworkers and managers play with them too. This interactive approach is not only a powerful way to gain intuition, but also a great way to get people excited about your work.</p><p>Making interactive models is one of the use-cases that inspired <a href="http://streamlit.io/">Streamlit</a>, a Python framework that makes <a href="https://towardsdatascience.com/coding-ml-tools-like-you-code-ml-models-ddba3357eace?source=friends_link&amp;sk=f7774c54571148b33cde3ba6c6310086">writing apps as easy as writing Python scripts</a>. This overview will walk you through creating a Streamlit app to play with one of the hairiest and black-box-iest models out there: a deep <em>Generative Adversarial Network</em> (GAN). In this case, we’ll visualize Nvidia’s <a href="https://research.nvidia.com/publication/2017-10_Progressive-Growing-of">PG-GAN</a> [1] using TensorFlow to synthesize photorealistic human faces from thin air. Then, using Shaobo Guan’s amazing <a href="https://blog.insightdatascience.com/generating-custom-photo-realistic-faces-using-ai-d170b1b59255">TL-GAN</a> model [2], we’ll create an <a href="https://github.com/streamlit/demo-face-gan">app that gives us</a> the ability to tweak GAN-synthesized celebrity faces by attributes like age, smileyness, male likeness, and hair color. By the end of the tutorial, you’ll have a fully parametric model of humans! (Note we didn’t create the attributes. They came from the <a href="http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html">CelebA dataset</a> [3], and some of them can get a bit weird…)</p><h3>Getting started with Streamlit</h3><p>If you haven’t installed Streamlit yet, you can do so by running:</p><pre>pip install streamlit<br>streamlit hello</pre><p>And if you’re a seasoned Streamlit-er, you’ll need to be on 0.57.1 or later, so make sure to upgrade!</p><pre>pip install --upgrade streamlit</pre><h3>Setting up your environment</h3><p>Before we begin, use the commands below to check out the project’s GitHub repo and running the <a href="https://github.com/streamlit/demo-face-gan">Face GAN demo</a> for yourself. This demo depends on Tensorflow 1, which does not support Python 3.7 or 3.8, so you’ll need Python 3.6. On Mac and Linux, we recommend using <a href="https://github.com/pyenv/pyenv">pyenv</a> to install Python 3.6 alongside your current version, then setting up a new virtual environment using venv or virtualenv. On Windows, the <a href="https://docs.anaconda.com/anaconda/navigator/">Anaconda Navigator</a> allows you to <a href="https://docs.anaconda.com/anaconda/navigator/tutorials/use-multiple-python-versions/">pick your Python version</a> with a point-and-click interface.</p><p>When you’re all set, open a terminal window and type:</p><pre>git clone <a href="https://github.com/streamlit/demo-face-gan.git">https://github.com/streamlit/demo-face-gan.git</a><br>cd demo-face-gan<br>pip install -r requirements.txt<br>streamlit run app.py</pre><p>Give it a minute to finish downloading the trained GAN and then try playing with the sliders to explore the different faces the GAN can synthesize. Pretty cool, right?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*u-XAUMWozCKyaz1a_t_r-g.gif" /></figure><p>The full app code is a file that has ~190 lines of code, out of which only 13 are Streamlit calls. <strong>That’s right, the entire UI above is drawn from just those 13 lines!</strong></p><p>Let’s take a look at how the app is structured:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0ec5b02972b68ae57c441a920be8008b/href">https://medium.com/media/0ec5b02972b68ae57c441a920be8008b/href</a></iframe><p>Now that you have a sense of how it is structured, let’s dive into each of the 5 steps above to see how they work.</p><h3>Step 1. Download models and data files</h3><p>This step downloads the files we need: a pre-trained PG-GAN model and a TL-GAN model pre-fitted to it (we’ll dive into these a little bit later!).</p><p>The download_file utility function is a little smarter than a pure downloader:</p><ul><li>It checks if the file is already present in the local directory, so it only downloads it if needed. It also checks if the downloaded file’s size is what we expected it to be, so it’s able to fix interrupted downloads. This is a great pattern to follow!</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d9a43a87092026d7ca9cd74dbdea4831/href">https://medium.com/media/d9a43a87092026d7ca9cd74dbdea4831/href</a></iframe><ul><li>It uses st.progress() and st.warning() to show a nice UI to the user while the file downloads. Then it calls .empty() on those UI elements to hide them when done.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/44798b1a4c567d800a3eab927c33a6a6/href">https://medium.com/media/44798b1a4c567d800a3eab927c33a6a6/href</a></iframe><h3>Step 2. Load the models into memory</h3><p>The next step is to load these models into memory. Here is the code for loading the PG-GAN model:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/13360ea918964b3db5d74b9fe7d0ab04/href">https://medium.com/media/13360ea918964b3db5d74b9fe7d0ab04/href</a></iframe><p>Notice the @st.cache decorator at the start of load_pg_gan_model(). Normally in Python, you could just run load_pg_gan_model() and reuse that variable over and over. Streamlit’s <a href="https://docs.streamlit.io/main_concepts.html?highlight=execution%20model#data-flow">execution model</a> is unique, however, in that every time a user interacts with a UI widget your script executes again <em>in</em> <em>its entirety, </em>from top to bottom. By adding @st.cache to the costly model-loading functions, we are telling Streamlit to only run those functions the first time the script executes — and just reuse the cache output for every execution after that. That is one of Streamlit’s most fundamental features, as it lets you run scripts efficiently by caching the results of function calls. This way, the large fitted GAN models will be loaded into memory exactly once; and by the same token, our TensorFlow session will be created exactly once, as well. (See our <a href="https://towardsdatascience.com/coding-ml-tools-like-you-code-ml-models-ddba3357eace?source=friends_link&amp;sk=f7774c54571148b33cde3ba6c6310086">launch article</a> for a refresher on Streamlit’s execution model.)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/0*RLK-hVUVjSVhr62f" /><figcaption>[Figure 1. How caching works in Streamlit’s execution model]</figcaption></figure><p>There’s one wrinkle, though: the TensorFlow session object can mutate internally as we use it to run different computations. Ordinarily, <a href="https://docs.streamlit.io/caching.html#example-6-mutating-cached-values">we don’t want cached objects to mutate</a>, as that can lead to unexpected results. So when Streamlit detects such mutations, it issues a warning to the user. However, in this case we happen to know that it’s OK if the TensorFlow session object mutates, so <a href="https://docs.streamlit.io/troubleshooting/caching_issues.html#how-to-fix-the-cached-object-mutated-warning">we bypass the warning</a> by setting allow_output_mutation=True.</p><h3>Step 3. Draw the sidebar UI</h3><p>If this is the first time you’re seeing Streamlit’s API for drawing widgets, here’s the 30-second crash course:</p><ul><li>You add widgets by calling API methods like st.slider() and st.checkbox().</li><li>The return value of those methods is the value shown in the UI. For example, when the user moves a slider to position 42, your script will be re-executed and in that execution the return value of that st.slider() will be 42.</li><li>You can put anything in a sidebar by prepending it with st.sidebar. For example, st.sidebar.checkbox().</li></ul><p>So to add a slider in the sidebar, for example — a slider to allow the user to tune the brown_hair parameter, you would just add:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c0b765294e77ecfe57579da6ad09a702/href">https://medium.com/media/c0b765294e77ecfe57579da6ad09a702/href</a></iframe><p>In our app we want to get a little fancy to show off just how easy it is to make the UI itself modifiable in Streamlit! We want to allows users to first use a multiselect widget to pick a set of features they want to control in the generated image, which means our UI needs to be drawn programmatically:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*BwanS6qqSNmjZr66" /></figure><p>With Streamlit, the code for that is actually quite simple:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d2bb775dbca55365bab927cad5a4b50e/href">https://medium.com/media/d2bb775dbca55365bab927cad5a4b50e/href</a></iframe><h3>Step 4. Synthesize the image</h3><p>Now that we have a set of features telling us what kind of face to synthesize, we need to do the heavy lifting of synthesizing the face. The way we’ll do that is by passing the features into the TL-GAN to generate a vector in the PG-GAN’s latent space, then feed that vector to PG-GAN. If that sentence made no sense to you, let’s take a detour and talk about how our two neural nets work.</p><h3><strong>A detour into GANs</strong></h3><p>To understand how the above app generates faces from slider values, you first have to understand something about how PG-GAN and TL-GAN work — but don’t worry, <strong>you can skip this section and still understand how the app works at a higher level!</strong></p><p>PG-GAN, like any GAN, is fundamentally<em> a pair</em> of neural networks, one generative and one discriminative, which are trained against each other, forever locked in mortal combat. The generative network is in charge of synthesizing images it believes look like faces, and the discriminative network is in charge of deciding whether or not the images are indeed faces. The two networks are iteratively trained against each other’s output, so each one does its best to learn to fool the other network. The end result is the final generative network is able to synthesize realistic-looking faces even though at the start of training all it could synthesize was random noise. Its really quite amazing! In this case, the face-generating GAN we use was trained on celebrity faces by Karras <em>et al</em> using their <a href="https://github.com/tkarras/progressive_growing_of_gans">Progressive Growing of GANs</a> algorithm (PG-GAN), which trains GANs using progressively higher-resolution images. [1]</p><p>The input to PG-GAN is a high-dimensional vector belonging to its so-called <em>latent-space</em>. The latent-space is basically the space of all possible faces the network can generate, so each random vector in that space corresponds to a unique face (or at least it should! Sometimes you get weird results…) The way you typically use a GAN is to give it a random vector and then check out what face gets synthesized (Figure 2.a).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*5LDbOi-hV71ZcNhi" /><figcaption>[Figure 2.a]</figcaption></figure><p>However, that sounds a bit dull and we’d rather have some more control over the output. We’d like to tell PG-GAN “generate an image of a man with a beard”, or “generate an image of a brown-haired woman”. That’s where the TL-GAN comes in.</p><p>The TL-GAN is yet another neural network, this one trained by entering random vectors into PG-GAN, taking the generated faces, and running them through classifiers for attributes like “is young-looking”, “is bearded”, “is brown-haired”, etc. In the training phase, TL-GAN labels thousands of faces from PG-GAN with those classifiers and identifies directions in the latent space that correspond to changes in the labels we care about. As a result, the TL-GAN learns how to map those classes (i.e. “young-looking”, “bearded”, “brown-haired”) into the appropriate random-looking vector that should be input into PG-GAN to generate a face with those characteristics (Figure 2.b).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*0yIP_XPlxdddzS4B" /><figcaption>[Figure 2.b]</figcaption></figure><p>Going back to our app, at this point we’ve already downloaded the pre-trained GAN models and loaded them into memory, and we’ve also grabbed a feature vector from the UI. So now we just have to feed those features into TL-GAN and then PG-GAN to get an image out:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/eb05e20f298a811853122f6a20b9f2c6/href">https://medium.com/media/eb05e20f298a811853122f6a20b9f2c6/href</a></iframe><h3>Optimize performance</h3><p>The generate_image() function above can take some time to execute, especially when running on a CPU. To improve our app’s performance it would be great if we could cache the output of that function, so we don’t have to re-synthesize faces we’ve already seen as we move the slider back and forth.</p><p>Well, as you may have noticed in the snippet above already, the solution here is to once again use the @st.cache decorator.</p><p>But notice the two arguments we passed to @st.cache in this case: show_spinner=False and hash_funcs={tf.Session: id}. What are those there for?</p><p>The first one is easy to explain: by default, @st.cache shows a status box in the UI letting you know that a slow-running function is currently executing. We call that a “spinner”. However, in this case, we’d like to avoid showing it, so the UI doesn’t jump around unexpectedly. So we set show_spinner to False.</p><p>The next one solves a more involved problem: the TensorFlow session object, which is passed as an argument to generate_image(), is usually mutated by TensorFlow’s internals in between runs of this cached function. This means the input arguments to generate_image() will always be different and we’ll never actually get a cache hit. In other words, the @st.cache decorator won’t actually do anything! How can we solve this?</p><h3>Hash_funcs to the rescue</h3><p>The hash_funcs option allows us to specify custom hash functions that tell @st.cache how it should interpret different objects when checking whether this is a cache hit or a cache miss. In this case, we’re going to use that option to tell Streamlit to hash a TensorFlow session by calling Python’s id() function rather than by examining its contents:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a53102c05bb3723b48714ec62d198269/href">https://medium.com/media/a53102c05bb3723b48714ec62d198269/href</a></iframe><p>This works for us because the session object in our case is actually a singleton across all executions of the underlying code since it comes from the @st.cache’d load_pg_gan_model() function.</p><p>For more information about hash_funcs, check out our documentation about <a href="https://docs.streamlit.io/api.html?highlight=cache#streamlit.cache">advanced caching techniques</a>.</p><h3>Step 5. Draw the synthesized image</h3><p>Now that we have the output image, drawing it is a piece of cake! Just call Streamlit’s st.image function:</p><pre>st.image(image_out, use_column_width=True)</pre><p>And we’re done!</p><h3>Wrapping up</h3><p>So there you have it: interactive face synthesis with TensorFlow in a 190-line Streamlit app and only 13 Streamlit function calls! Have fun exploring the space of faces these two GANs can draw, and many thanks to <a href="https://github.com/tkarras/progressive_growing_of_gans">Nvidia</a> and <a href="https://github.com/SummitKwan/transparent_latent_gan">Shaobo Guan</a> for letting us build off their super cool demos. We hope that you have as much fun building apps and playing with models as we do. 🎈</p><p>For more Streamlit app examples, you can check out our gallery at<a href="https://www.streamlit.io/gallery"> https://www.streamlit.io/gallery</a>.</p><p><em>Thanks to Ash Blum, TC Ricks, Amanda Kelly, Thiago Teixeira, Jonathan Rhone and Tim Conkling for their helpful input on this article.</em></p><p><strong>References:</strong></p><p>[1] T. Karras, T. Aila, S. Laine, J. Lehtinen. <em>Progressive Growing of GANs for Improved Quality, Stability, and Variation</em>. International Conference on Learning Representations (ICLR 2018)</p><p>[2] S. Guan. <em>Controlled image synthesis and editing using a novel TL-GAN model</em>. Insight Data Science Blog (2018)</p><p>[3] Z. Liu, P. Luo, X. Wang, X. Tang. <em>Deep Learning Face Attributes in the Wild. </em>International Conference on Computer Vision (ICCV 2015)</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=dd2545828021" width="1" height="1" alt=""><hr><p><a href="https://medium.com/data-science/build-an-app-to-synthesize-photorealistic-faces-using-tensorflow-and-streamlit-dd2545828021">Build an app to synthesize photorealistic faces using TensorFlow and Streamlit</a> was originally published in <a href="https://medium.com/data-science">TDS Archive</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Turn Python Scripts into Beautiful ML Tools]]></title>
            <link>https://medium.com/data-science/coding-ml-tools-like-you-code-ml-models-ddba3357eace?source=rss-39dfc90d7a34------2</link>
            <guid isPermaLink="false">https://medium.com/p/ddba3357eace</guid>
            <category><![CDATA[deep-learning]]></category>
            <category><![CDATA[autonomous-vehicles]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[data-science]]></category>
            <dc:creator><![CDATA[Adrien Treuille]]></dc:creator>
            <pubDate>Tue, 01 Oct 2019 13:55:07 GMT</pubDate>
            <atom:updated>2019-10-01T15:26:21.610Z</atom:updated>
            <content:encoded><![CDATA[<h4>Introducing Streamlit, an app framework built for ML engineers</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/1*Mbn2SxozueUkGKPW1NJkOw.gif" /><figcaption>Coding a semantic search engine with real-time neural-net inference in 300 lines of Python.</figcaption></figure><p>In my experience, every nontrivial machine learning project is eventually stitched together with bug-ridden and unmaintainable internal tools. These tools — often a patchwork of Jupyter Notebooks and Flask apps — are difficult to deploy, require reasoning about client-server architecture, and don’t integrate well with machine learning constructs like Tensorflow GPU sessions.</p><p>I saw this first at Carnegie Mellon, then at Berkeley, Google X, and finally while building autonomous robots at Zoox. These tools were often born as little Jupyter notebooks: the sensor calibration tool, the simulation comparison app, the LIDAR alignment app, the scenario replay tool, and so on.</p><p>As a tool grew in importance, project managers stepped in. Processes sprouted. Requirements flowered. These solo projects gestated into scripts, and matured into gangly maintenance nightmares.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5BWfc_oBn2yypksY8-QuKA.png" /><figcaption>The machine learning engineers’ ad-hoc app building flow.</figcaption></figure><p>When a tool became crucial, we <strong>called in the tools team</strong>. They wrote fluent Vue and React. They blinged their laptops with stickers about declarative frameworks. They had a <em>design process</em>:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hNO5NYKjcsEV7jIpEaz8Eg.png" /><figcaption>The tools team’s clean-slate app building flow.</figcaption></figure><p>Which was awesome. But these tools all needed new features, like weekly. And the tools team was supporting ten other projects. They would say, “we’ll update your tool again in two months.”</p><p>So we were back to building our own tools, deploying Flask apps, writing HTML, CSS, and JavaScript, and trying to version control everything from notebooks to stylesheets. So my old Google X friend, Thiago Teixeira, and I began thinking about the following question: <strong>What if we could make building tools as easy as writing Python scripts?</strong></p><p>We wanted machine learning engineers to be able to create beautiful apps without needing a tools team. These internal tools should arise as a natural byproduct of the ML workflow. Writing such tools should <em>feel</em> like training a neural net or performing an ad-hoc analysis in Jupyter! At the same time, we wanted to preserve all of the flexibility of a powerful app framework. We wanted to create beautiful, performant tools that engineers could show off. Basically, we wanted this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gdD55KRcRVRvfjsQ_Ls-XA.png" /><figcaption>The Streamlit app building flow.</figcaption></figure><p>With an amazing beta community including engineers from Uber, Twitter, Stitch Fix, and Dropbox, we worked for a year to create <a href="https://streamlit.io/">Streamlit</a>, a <a href="https://github.com/streamlit/streamlit/">completely free and open source</a> app framework for ML engineers. With each prototype, the core principles of Streamlit became simpler and purer. They are:</p><p><strong>#1: Embrace Python scripting.</strong> Streamlit apps are really just scripts that run from top to bottom. There’s no hidden state. You can factor your code with function calls. If you know how to write Python scripts, you can write Streamlit apps. For example, this is how you write to the screen:</p><pre>import streamlit as st</pre><pre>st.write(&#39;Hello, world!&#39;)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VNqEOqFJQl5fB7Z0ed5lMw.png" /><figcaption>Nice to meet you.</figcaption></figure><p><strong>#2: Treat widgets as variables. </strong>There are <em>no callbacks in Streamlit</em>! Every interaction simply reruns the script from top to bottom. This approach leads to really clean code:</p><pre>import streamlit as st</pre><pre>x = st.slider(&#39;x&#39;)<br>st.write(x, &#39;squared is&#39;, x * x)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*h8BwonRrhnh3KtjO5cDEcA.png" /><figcaption>An interactive Streamlit app in three lines of code.</figcaption></figure><p><strong>#3: Reuse data and computation. </strong>What if you download lots of data or perform complex computation? The key is to <em>safely reuse</em> information across runs. Streamlit introduces a cache primitive that behaves like a persistent, immutable-by-default, data store that lets Streamlit apps safely and effortlessly reuse information. For example, this code<strong> downloads data only once</strong> from the <a href="https://github.com/udacity/self-driving-car">Udacity Self-driving car project</a>, yielding a simple, fast app:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/00011aba57fc3d7408cc828a37fbebb9/href">https://medium.com/media/00011aba57fc3d7408cc828a37fbebb9/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vLvk0xZUVEx1GcrzYhWxXQ.png" /><figcaption>The output of running the st.cache example above.</figcaption></figure><p>In short, Streamlit works like this:</p><ol><li>The entire script is run from scratch for each user interaction.</li><li>Streamlit assigns each variable an up-to-date value given widget states.</li><li>Caching allows Streamlit to skip redundant data fetches and computation.</li></ol><p>Or in pictures:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*l4gxFYEZnRhysQ_QWIVJgA.png" /><figcaption>User events trigger Streamlit to rerun the script from scratch. Only the cache persists across runs.</figcaption></figure><p>If this sounds intriguing, you can try it right now! Just run:</p><pre>$ pip install --upgrade streamlit <br>$ streamlit hello</pre><pre><strong>   You can now view your Streamlit app in your browser.</strong></pre><pre>   <strong>Local URL:</strong> <a href="http://localhost:8501/">http://localhost:8501</a><br>   <strong>Network URL:</strong> <a href="http://10.0.1.29:8501/">http://10.0.1.29:8501</a></pre><p>This will automatically pop open a web browser pointing to your local Streamlit app. If not, just click the link.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_Btm7O0pYqAk_enXUPECLw.png" /><figcaption>To see more examples like this fractal animation, run <strong>streamlit hello</strong> from the command line.</figcaption></figure><p>Ok. Are you back from playing with fractals? Those can be mesmerizing.</p><p>The simplicity of these ideas does not prevent you from creating incredibly rich and useful apps with Streamlit. During my time at Zoox and Google X, I watched as self-driving car projects ballooned into gigabytes of visual data, which needed to be searched and understood, including running models on images to compare performance. Every self-driving car project I’ve seen eventually has had entire teams working on this tooling.</p><p>Building such a tool in Streamlit is easy. <a href="http://github.com/streamlit/demo-self-driving">This Streamlit demo</a> lets you perform semantic search across the entire <a href="https://github.com/udacity/self-driving-car">Udacity self-driving car photo dataset</a>, visualize human-annotated ground truth labels, and <strong>run a complete neural net (</strong><a href="https://pjreddie.com/darknet/yolo/"><strong>YOLO</strong></a><strong>) in real time </strong>from within the app [1].</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*p3XPm-x0TUIuMmQQa4mjHQ.gif" /><figcaption>This 300-line Streamlit demo combines semantic visual search with interactive neural net inference.</figcaption></figure><p>The whole app is a completely self-contained, 300-line Python script, most of which is machine learning code. In fact, there are <a href="https://github.com/streamlit/demo-self-driving/blob/master/app.py">only 23 Streamlit calls in the whole app</a>. You can run it yourself right now!</p><pre>$ pip install --upgrade streamlit opencv-python<br>$ streamlit run<br><a href="https://raw.githubusercontent.com/streamlit/demo-self-driving/master/app.py">https://raw.githubusercontent.com/streamlit/demo-self-driving/master/app.py</a></pre><p>As we worked with machine learning teams on their own projects, we came to realize that these simple ideas yield a number of important benefits:</p><p><strong>Streamlit apps are pure Python files. </strong>So you can use your favorite editor and debugger with Streamlit.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4KMALKoeS_3TUSBn0ryzYg.png" /><figcaption>My favorite layout for writing Streamlit apps has VSCode on the left and Chrome on the right.</figcaption></figure><p><strong>Pure Python scripts work seamlessly with Git</strong> and other source control software, including commits, pull requests, issues, and comments. Because Streamlit’s underlying language is pure Python, you get all the benefits of these amazing collaboration tools for free 🎉.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*pY7e7BLPI2atT_-V" /><figcaption>Because Streamlit apps are just Python scripts, you can easily version control them with Git.</figcaption></figure><p><strong>Streamlit provides an immediate-mode live coding environment.</strong> Just click <em>Always rerun</em> when Streamlit detects a source file change.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*P3vtLk-HGeCRH_Gu5B5ifg.png" /><figcaption>Click “Always rerun” to enable live coding.</figcaption></figure><p><strong>Caching simplifies setting up computation pipelines. </strong>Amazingly, chaining cached functions automatically creates efficient computation pipelines! Consider <a href="https://gist.github.com/treuille/ac7755eb37c63a78fac7dfef89f3517e">this code</a> adapted from our <a href="https://github.com/streamlit/demo-self-driving">Udacity demo</a>:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9f9b974ae076076a6b9dda8e1be9f6d6/href">https://medium.com/media/9f9b974ae076076a6b9dda8e1be9f6d6/href</a></iframe><p>Basically, the pipeline is load_metadata → create_summary. Every time the script is run <strong>Streamlit only recomputes whatever subset of the pipeline is required to get the right answer</strong>. Cool!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*e0-z12L0pXYlCE5OM3n6LA.png" /><figcaption>To make apps performant, Streamlit only recomputes whatever is necessary to update the UI.</figcaption></figure><p><strong>Streamlit is built for GPUs. </strong>Streamlit allows direct access to machine-level primitives like TensorFlow and PyTorch and complements these libraries. For example in this demo, Streamlit’s cache stores the entire <a href="https://research.nvidia.com/publication/2017-10_Progressive-Growing-of">NVIDIA celebrity face GAN</a> [2]. This approach enables nearly instantaneous inference as the user updates sliders.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/1*188SkUE1onGcpQIuSZsiMQ.gif" /><figcaption>This Streamlit app demonstrates <a href="https://research.nvidia.com/publication/2017-10_Progressive-Growing-of">NVIDIA celebrity face GAN</a> [2] model using <a href="https://blog.insightdatascience.com/generating-custom-photo-realistic-faces-using-ai-d170b1b59255">Shaobo Guan’s TL-GAN</a> [3].</figcaption></figure><p><strong>Streamlit is a free and open-source library rather than a proprietary web app</strong>. You can serve Streamlit apps on-prem without contacting us. You can even run Streamlit locally on a laptop without an Internet connection! Furthermore, existing projects can adopt Streamlit incrementally.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nyOMWYNcM9mPTU5mHf1CxQ.png" /><figcaption>Several ways incrementally adopt Streamlit. (Icons courtesy of <a href="https://www.freepik.com/free-vector/computer-technology-isometric-icon-server-room-digital-device-set-element-design-pc-laptop_4103157.htm">fullvector / Freepik</a>.)</figcaption></figure><p>This just scratches the surface of what you can do with Streamlit. One of the most exciting aspects of Streamlit is how these primitives can be easily composed into complex apps that look like scripts. There’s a lot more we could say about how our architecture works and the features we have planned, but we’ll save that for future posts.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wmwwsWkOHzsYLe8pB2RzBA.png" /><figcaption><em>Block diagram of Streamlit’s components. More coming soon!</em></figcaption></figure><p>We’re excited to finally share Streamlit with the community today and see what you all build with it. We hope that you’ll find it easy and delightful to turn your Python scripts into beautiful ML apps.</p><p><em>Thanks to Amanda Kelly, Thiago Teixeira, TC Ricks, Seth Weidman, Regan Carey, Beverly Treuille, Geneviève Wachtell, and Barney Pell for their helpful input on this article.</em></p><p><strong>References:</strong></p><p>[1] J. Redmon and A. Farhadi, <em>YOLOv3: An Incremental Improvement </em>(2018), arXiv.</p><p>[2] T. Karras, T. Aila, S. Laine, and J. Lehtinen, <em>Progressive Growing of GANs for Improved Quality, Stability, and Variation</em> (2018), ICLR.</p><p>[3] S. Guan, <em>Controlled image synthesis and editing using a novel TL-GAN model </em>(2018), Insight Data Science Blog.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ddba3357eace" width="1" height="1" alt=""><hr><p><a href="https://medium.com/data-science/coding-ml-tools-like-you-code-ml-models-ddba3357eace">Turn Python Scripts into Beautiful ML Tools</a> was originally published in <a href="https://medium.com/data-science">TDS Archive</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>