<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Narendran Thangarajan</title>
    <description>Building a better future, one step at a time.
</description>
    <link>https://narendran.github.io/</link>
    <atom:link href="https://narendran.github.io/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Tue, 30 Jul 2024 13:16:33 +0000</pubDate>
    <lastBuildDate>Tue, 30 Jul 2024 13:16:33 +0000</lastBuildDate>
    <generator>Jekyll v3.9.5</generator>
    
      <item>
        <title>Search Engineer in 2024: Things to know</title>
        <description>&lt;p&gt;This blog is a living document, and I will continue to update it as I continue to learn more.&lt;/p&gt;

&lt;p&gt;For a long-time now, I’ve found connecting people to the right information as truly meaningful and deeply energizing. Since I was in high school, I’ve loved organizing information and things and serving them to people in a way that they leave more knowledgeable and fulfilled – more on this in a separate personal blog. I’ve recently realized that information search in companies like Google and Uber (where I’ve worked previously) is literally a planet-scale incarnation of the same theme and that is what drives me everyday to gain the skills and solve relevant, meaningful problems using those skills. Search is about &lt;strong&gt;connecting a user’s &lt;ins&gt;verbalized intent&lt;/ins&gt; (aka “query”) to the &lt;ins&gt;information/product&lt;/ins&gt; (aka “document”)&lt;/strong&gt; that will fully satisfy their need. The goal of this article is to take this previous line, and unpack it component by component. Typical search systems have retrieval, query understanding and re-ranking.&lt;/p&gt;

&lt;h2 id=&quot;retrieval&quot;&gt;Retrieval&lt;/h2&gt;

&lt;p&gt;At the highest level of abstraction, search is about finding the documents which “match” the given query. This is technically called retrieval. There are typically two ways you can match a document based on the query.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Lexical Matching is based on query and document having a lexical aka word/token level match. Conceptually, lexical matching needs a map of query-like tokens pointing to documents. So a document like &lt;em&gt;D1:”Dogs are animals”&lt;/em&gt; would be 3 different mappings of &lt;em&gt;dog:D1, are:D1, animals:D1&lt;/em&gt;. Now, a user query of “cat” would lead to no matches, while “dog” would retrieve D1 as a lexical match. In practice, we would have millions of documents and hence the map (or index) looks more like &lt;em&gt;dog:[D11, D13, D4, D9]&lt;/em&gt; and order of linked documents under a token is typically based on document popularity.&lt;/li&gt;
  &lt;li&gt;Semantic Matching involves augmenting the document with semantically matching tokens and indexing the document for those tokens as well. In the symbolic approach, we can add semantically relevant terms to the document (e.g. relevance feedback). With the wide adoption of neural networks, the more recent approach is to represent the document as a vector/embedding which captures the semantics of the full document, and we would use the same neural encoder to get the query embeddings. Then we would use nearest neighbour search algorithms to find the N closest document embeddings to the given query embedding. Semantic matching also help with precision since it naturally factors in the context in which the words occur e.g. “milk chocolate” vs. “chocolate milk”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both matching techniques have their pros and cons: for instance, lexical matching works well irrespective of domain but has a fixed upper limit in terms of quality, and semantic matching brings in intelligence but its quality is limited by embedding quality (and transitively to the finetuning dataset size). If your domain has smaller sized queries and documents compared to web search, I would personally start with lexical matching first, and progressively add semantic retrieval as needed by the business. In more advanced deployments, we would see both retrieval strategies used simulataneously with a blending layer to merge the search results from both the retrieval strategies before going to re-ranking stage.&lt;/p&gt;

&lt;p&gt;Also, there are a few things which apply to both the retrieval paradigms: challenges with scaling up index sizes, live indexing, filters to skip documents (could be user-selected like time range or machine inferred like the query needs only “job” or “person” documents only), and there is a maximum limit on how many documents we want to match before considering retrieval done.&lt;/p&gt;

&lt;p&gt;Things to know in 2024:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Hybrid retrieval techniques are getting widely implemented. E.g. Native support in &lt;a href=&quot;https://sease.io/2023/12/hybrid-search-with-apache-solr.html&quot;&gt;Apache Solr&lt;/a&gt;, hybrid indexing in &lt;a href=&quot;https://www.pinecone.io/learn/hybrid-search-intro/&quot;&gt;Pinecone&lt;/a&gt;. However, more commonly seen are custom solutions like Elastic Search for sparse + Vespa/Weaviate/Milvus/QDrant for dense retrieval. If there is a good overlap of candidates from both retrieval sources, then a classic, score-agnostic ranking technique called Reciprocal Ranking Fusion (RRF) also has proven to work very well. If you want to find a good middle ground: Staring with lexical matching and using Splade V2 for semantic expansion can take you a long way towards hybrid retrieval. Read up on the original &lt;a href=&quot;https://arxiv.org/pdf/2107.05720.pdf&quot;&gt;Splade&lt;/a&gt; technique.&lt;/li&gt;
  &lt;li&gt;Two-tower siamese networks continue to be the industry SOTA in building embeddings for embedding-based semantic retrieval. Graph embeddings, say for users/documents are used as input features on the document tower. E.g. &lt;a href=&quot;https://arxiv.org/pdf/2306.04833.pdf&quot;&gt;Personalized Retrieval in Etsy&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;LLM-based search experiences would be a step function capability in helping users. E.g. giving them &lt;a href=&quot;https://arxiv.org/pdf/2308.04226.pdf&quot;&gt;product reviews&lt;/a&gt;, generating semantic tags for products, reducing the need for enterprises to build KG ontologies and maintain algorithms to convert unstructured information in the wild to map to their ontologies. Additionally, even with semantic retrieval, it is still non-trivial to answer questions like “healthy snacks for kids”, “thanksgiving dinner ideas” etc. This is a place where LLMs can directly help.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;query-understanding&quot;&gt;Query Understanding&lt;/h2&gt;

&lt;p&gt;Given that the user query comes from… humans, expect it to be imperfect and non-canonical. Once the query is corrected, we need to enrich it with information needed for effective retrieval. Following are some steps you could expect to see in a query understanding system.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Spelling correction: Refer Symspell.&lt;/li&gt;
  &lt;li&gt;Multi-lingual complexities: Handling tick signs in languages like Portuguese and Spanish (e.g. azúcar), normalizing queries from different Japanese writing systems.&lt;/li&gt;
  &lt;li&gt;Compounding and decompounding&lt;/li&gt;
  &lt;li&gt;Expansions&lt;/li&gt;
  &lt;li&gt;Category classification: Many search systems today could retrieve results from multiple domains/verticals/categories.&lt;/li&gt;
  &lt;li&gt;Entity classification: Person vs. Job Title, Food vs. Restaurant, Celebrity vs. Product etc.&lt;/li&gt;
  &lt;li&gt;Named Entity Recognition: Segmenting the different parts of the query into different facets. E.g. “Naren who worked in Google” should be a Person entity search for the token “Naren” and employer facet being “Google”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once done, we have corrected and enriched the query with a lot of metadata to help with both increasing the radius of retrieval (aka recall) and simultaneously scoping down to increase the relevance of results retrieved (aka precision).&lt;/p&gt;

&lt;p&gt;Tools and Techniques to know in 2024:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;LLMs with their instruction following + world knowledge capabilities make excellent query understanders. Depending on the usecase, we could cache the query understanding result + run the LLM inference online for a different subset of queries. Note that we will have to run the same inferences on the document side as well to be able to match and boost.&lt;/li&gt;
  &lt;li&gt;Rethinking eCommerce search to be done on unstructured, textual data instead of structured data. &lt;a href=&quot;https://arxiv.org/pdf/2312.03217.pdf&quot;&gt;Position paper&lt;/a&gt; by Instacart. However, I think relying on the LLM to generate product IDs is not a good idea, and we should expect inaccuracies.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;re-ranking&quot;&gt;Re-ranking&lt;/h2&gt;

&lt;p&gt;The final step after query understanding and retrieval is deciding the final order of results to show to the user. This is usually an optional step, and typically needed to add a different preference order. For instance, in eCommerce search, the goal for both the user and the platform is for the user to purchase from the shop or purchase the item being shown, which means ranking based on probability of purchase, some combination of query-document relevance and ordering probability both work well. Typically, there is also filtering to remove away documents based on relevance conditions. Also, its not uncommon to have more than one re-ranking step.&lt;/p&gt;

&lt;p&gt;Tools and Techniques to know in 2024:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;XGBoost models are continuing to be strong baselines, with deep learning models used to eke out the final few percentage points in NDCG.&lt;/li&gt;
  &lt;li&gt;LLMs can help with evaluating ranking model performances, and also for generating relevance labels.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;closing-thoughts&quot;&gt;Closing Thoughts&lt;/h2&gt;

&lt;p&gt;Finally, like in any real-world project, you would run into a ton of real-world idiosyncrasies, which you get progressively better at with more experience, like the following&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Users usually prefer previously clicked documents (exact and similar). E.g. reordering same meal, preferring the same 2% fat milk product, preferring wikipedia for informational needs etc. So you might want to build that capability into all information surfaces. This is typically called &lt;strong&gt;personalization&lt;/strong&gt;, and makes a significant improvement in user satisfaction especially in head/high-traffic queries.&lt;/li&gt;
  &lt;li&gt;In every layer and each component in that layer, we run into &lt;strong&gt;coverage vs. quality tradeoffs&lt;/strong&gt; though in theory we need 100% on both. The choice in the tradeoff is highly dependent on the kind of product (ecommerce shopping, home assistant, information search results page, job search etc.), the kind of queries users are issuing on your platform and the number of documents we have to serve from.&lt;/li&gt;
  &lt;li&gt;While addressing the coverage vs. quality tradeoff, we inevitably run into machine learning solutions which come with their own complexities. In practice, its useful to have &lt;strong&gt;override systems&lt;/strong&gt; which can be updated in real-time. This is usually implemented in a configuration language which takes effect without a server restart. E.g. the query classification ML model in your job search could classify “Naren” as a “Job Title” while in reality it should be “Person”. Secondly, given that the rules of ML model are driven by real-world user data, it is important to have a continuous update and &lt;strong&gt;continuous monitoring&lt;/strong&gt; setup for relevant models.&lt;/li&gt;
  &lt;li&gt;Once your information search surface gets popular, it becomes a good surface to show &lt;strong&gt;sponsored information&lt;/strong&gt; related to the user and the user’s intent – and a precondition here is convincing ourselves that sponsored results are win-win-win for the sponsorer, the search platform and the user (to discover new products). However, remember that anything that is inserted in the middle of a relevance-ordered list would decrease user-perceived relevance, and hence its critical to continuously assess where we are in the tradeoff spectrum and adjust the triggering logic of sponsored items accordingly. Especially, its important to setup hold-out experiments to understand long-term effects of such changes.&lt;/li&gt;
  &lt;li&gt;Like any engineered product, there is a tradeoff between adding &lt;strong&gt;complexity vs. maintainability&lt;/strong&gt;. But adding complexity is required to bring out magical user experiences. My advice here would be to keep adding complexity as needed and periodically assess the direction and perform simplifications.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Will keep adding more to this document as I keep learning. Please let me know if I am missing any other component here.&lt;/p&gt;

&lt;p&gt;Thank you!&lt;/p&gt;
</description>
        <pubDate>Sun, 31 Dec 2023 10:00:00 +0000</pubDate>
        <link>https://narendran.github.io/tech/2023/12/31/2024-search-engineer.html</link>
        <guid isPermaLink="true">https://narendran.github.io/tech/2023/12/31/2024-search-engineer.html</guid>
        
        
        <category>tech</category>
        
      </item>
    
      <item>
        <title>Turning 30</title>
        <description>&lt;p&gt;Today, I turn 30.&lt;/p&gt;

&lt;p&gt;I have been getting a lot of “You are 30 now! How do you feel?” and my answer has been simply “older”. This blog is an attempt to understand what getting “older” and especially what turning 30 means. This essay might make more sense if you are already like 25+ and I hope it is useful otherwise too.&lt;/p&gt;

&lt;p&gt;Almost a decade back, I had written a similar blog about &lt;a href=&quot;https://narnicles.wordpress.com/2011/09/04/life-lessons-what-i-learnt-from-my-20-year-experience-on-earth/&quot;&gt;turning 20&lt;/a&gt; which made for a fun read a few days back. Hopefully this blog is less embarrassing than that.&lt;/p&gt;

&lt;p&gt;[12 minute read]&lt;/p&gt;

&lt;h1 id=&quot;thousands-of-decisions-and-their-consequences&quot;&gt;&lt;strong&gt;Thousands of Decisions and their Consequences&lt;/strong&gt;&lt;/h1&gt;

&lt;p&gt;Turning 30 does mark a significant milestone in your life.&lt;/p&gt;

&lt;p&gt;It concludes the first decade of a completely independent life. At this point, you have made thousands of decisions (large and small) affecting things ranging from yourself to your family to your career and to the society at large. Besides MAKING those decisions, by the age of 30 you’ve had the opportunity to witness and respond to the CONSEQUENCES of thousands of such decisions. No, I do not exaggerate when I say “thousands” of decisions. Imagine the gamut of decisions you have taken since your early 20s, which in your teens someone else was deciding for you:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On Education and Work&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Which university should I apply to?&lt;/li&gt;
  &lt;li&gt;Got admits! Which one to go to?&lt;/li&gt;
  &lt;li&gt;Should I get an education loan or see what luck has for me with on-campus jobs?&lt;/li&gt;
  &lt;li&gt;Which team should I join for the group project?&lt;/li&gt;
  &lt;li&gt;Hmm, I don’t have a side hustle yet and I don’t have money for next quarter’s tuitions – should I silently go back home after this quarter?&lt;/li&gt;
  &lt;li&gt;Everyone in college looks so cool and confident. What should I do to feel less awkward?&lt;/li&gt;
  &lt;li&gt;Should I get a 6-inch from Subway and look cool in front of my new friends or get a foot-long and secretly hide half of it for dinner?&lt;/li&gt;
  &lt;li&gt;Which career path should I take after graduation?&lt;/li&gt;
  &lt;li&gt;Which shirt should I wear for that job interview?&lt;/li&gt;
  &lt;li&gt;Which of these opportunities promises a happy life and secure future?&lt;/li&gt;
  &lt;li&gt;Yay! First salary! Should I spend it on traveling or save it up for rainy days?&lt;/li&gt;
  &lt;li&gt;Where should I put this $100 - retirement account, stock/options trading, mortgage payments, better health insurance, 6-month emergency fund?&lt;/li&gt;
  &lt;li&gt;Do I need external monitors?&lt;/li&gt;
  &lt;li&gt;Its 9 am, check email or get some work done?&lt;/li&gt;
  &lt;li&gt;Should we hire X or not?&lt;/li&gt;
  &lt;li&gt;Suggest this design or that?&lt;/li&gt;
  &lt;li&gt;Attend this meeting or skip?&lt;/li&gt;
  &lt;li&gt;Its 3pm, should I have a second coffee now?&lt;/li&gt;
  &lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;On Personal Life&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;What should I cook for dinner tonight?&lt;/li&gt;
  &lt;li&gt;Who should I watch the next Game of Thrones episode with?&lt;/li&gt;
  &lt;li&gt;Which class do I try? Piano/Triathlon/Tennis/Skiing/Swimming?&lt;/li&gt;
  &lt;li&gt;What to do this weekend? Movie/Clubbing/Sleepover/Board Games/Birthday Party?&lt;/li&gt;
  &lt;li&gt;Best friend is getting married! Vegas or Los Angeles for Bachelor Party?&lt;/li&gt;
  &lt;li&gt;Should I get married?&lt;/li&gt;
  &lt;li&gt;Wow, she looks good, could she be the One?&lt;/li&gt;
  &lt;li&gt;Repeat previous question N times.&lt;/li&gt;
  &lt;li&gt;Woohoo! I am getting married. Should I invite 10 people or 1000 people to my wedding?&lt;/li&gt;
  &lt;li&gt;Where should I go for a vacation this July 4th weekend?&lt;/li&gt;
  &lt;li&gt;Skyscanner.com or Kayak.com?&lt;/li&gt;
  &lt;li&gt;Canoeing or Kayaking?&lt;/li&gt;
  &lt;li&gt;AirBnb or Holiday Inn? Car camping or RV?&lt;/li&gt;
  &lt;li&gt;Is Top of the Rock worth the money?&lt;/li&gt;
  &lt;li&gt;Damn, I broke my legs! Drop-in at my doctor’s place or urgent care or emergency or call 911?&lt;/li&gt;
  &lt;li&gt;Should I get a pet?&lt;/li&gt;
  &lt;li&gt;Should I have a kid?&lt;/li&gt;
  &lt;li&gt;Which of the 8 different genetic tests do I want to take?&lt;/li&gt;
  &lt;li&gt;Huggies or Pampers or Cloth diapers?&lt;/li&gt;
  &lt;li&gt;Cocomelon or Word Party?&lt;/li&gt;
  &lt;li&gt;Disney or Universal Studios or both?&lt;/li&gt;
  &lt;li&gt;Should I sell the crib and donate all the baby clothes now?&lt;/li&gt;
  &lt;li&gt;Should I have a second kid?&lt;/li&gt;
  &lt;li&gt;Should I rent a bigger place then?&lt;/li&gt;
  &lt;li&gt;OMG $3000! Should I consider buying a house now or will the market crash due to a second deadly wave of CoViD?&lt;/li&gt;
  &lt;li&gt;Which school district do I want?&lt;/li&gt;
  &lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Well, you get it. Hopefully you are convinced now that I was not exaggerating about the “thousands” of decisions. And yes, you made all those decisions! How cool is that? And all these decisions, though simple and innocent in appearance, have significant repercussions on your life. These decisions define who you are. And that is exactly why turning 30 is a significant milestone in the formation of your own identity.&lt;/p&gt;

&lt;p&gt;Now, nobody really trains you to make these decisions. You sort of stumble upon them and figure it out on the way. By the time you are 30, you have automatic responses to many of the above questions and spend your precious mental energy on the remaining new and exciting questions. No big deal, life moves on and you stumble on more unseen experiences. And as you might expect such a way of life will have ups and downs by design leading to moments of pride and pondering. On that note, I would like to contemplate on the top two life lessons from my decade of independent decision making: Logic Can Fail and Embrace Grey.&lt;/p&gt;

&lt;h1 id=&quot;learning-1-logic-can-fail&quot;&gt;&lt;strong&gt;Learning #1: Logic Can Fail&lt;/strong&gt;&lt;/h1&gt;

&lt;p&gt;Logic fails in surprising ways. By logic, I mean being too smart.&lt;/p&gt;

&lt;p&gt;This is how I would describe my 25-year-old self: I have lived for 25 long years now and amassed tons of personal and vicarious life experiences. I have read voraciously from verified, reliable sources. I am trained in logical and critical thinking. I am up-to-date on politics, sports, finance, technology, science etc.. I can articulate my points with impeccable logic backed by undeniable science and powerful personal/historical anecdotes.&lt;/p&gt;

&lt;p&gt;In a nutshell, I felt simply invincible. Each time I crushed an argument, and put the other person out of words, the implicit feedback I got only reinforced my already strong convictions. I was right. I was right EVERY SINGLE TIME. Except that… I utterly failed. Turns out, each time the argument ended, the other person had simply given up on me or in case of my parents, punted the discussion to a later time when I am more mature. You can be right, and still fail spectacularly.&lt;/p&gt;

&lt;h1 id=&quot;logic-fails-due-to-lack-of-full-information&quot;&gt;Logic Fails… Due to Lack of Full Information&lt;/h1&gt;

&lt;p&gt;This is probably the biggest class of logic failures.&lt;/p&gt;

&lt;p&gt;Logic provides guarantee of correctness when provided with complete information. But in real-life you never have complete information on anything you make decisions on. Even when you have all the relevant people in the room, there is no reason they should share all their knowledge, their feelings and more importantly, their deep-rooted insecurities with you. And many times you just won’t have the time and resources to hunt down all the relevant information. Logic can only do so much in this setting.&lt;/p&gt;

&lt;p&gt;Turns out as you grow older you naturally build an extensive graph of probabilities and useful mental models on what can and cannot happen in life. This makes decision making more accurate and easier over time. You stop judging people and see yourself saying “it happens” often. So, keep learning from your own and others’ lives and when it comes to decision making, stay open to the fact that you could be missing/misunderstanding critical details.&lt;/p&gt;

&lt;h1 id=&quot;logic-fails-due-to-band-aid-situations&quot;&gt;Logic Fails… Due to Band-Aid Situations&lt;/h1&gt;

&lt;p&gt;There are times when you feel you have all the information in hand, but you simply don’t want or don’t have the time to fix the problem. This shows up a lot in relationships in life and work.&lt;/p&gt;

&lt;p&gt;In engineering, there is a method of problem solving called &lt;a href=&quot;https://en.wikipedia.org/wiki/Root_cause_analysis&quot;&gt;Root Cause Analysis&lt;/a&gt; which involves identifying the root cause of a problem and then performing corrective actions to prevent re-occurrence. Some problems in life could take months of Root Cause Analysis and then could take years to fix. Yes, you read it right, YEARS. And depending on the thing or (more likely) the person you are acting upon, this could be completely worth the effort. However, you will often run into cases when you should deliberately accept failure of logic owing to lack of time where you disagree, shake hands and move on without fixing the root cause. When the problem surfaces again, you do the same – just patch it and move on. I call these &lt;strong&gt;band-aid situations&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Applying a band-aid does not mean lack of courage or perseverance on your part. In fact, more often than you think, this is good for both yourself and the others involved.&lt;/p&gt;

&lt;h1 id=&quot;logic-fails-due-to-deep-rooted-beliefs&quot;&gt;Logic Fails… Due to Deep-Rooted Beliefs&lt;/h1&gt;

&lt;p&gt;In the last decade, I’ve moved from making fun of deep-rooted beliefs my parents espoused, to convincing myself that I would recommend the same to my next generation (and be that “out-dated, unscientific, illogical” parent for the next couple of decades). I like to call this class of logic failures as “subconscious safety nets” due to their ability to protect you from your conscious, rational self.&lt;/p&gt;

&lt;p&gt;On the topic of buying &lt;strong&gt;Gold&lt;/strong&gt;, following used to be a very typical conversation between me and my dad.&lt;/p&gt;

&lt;div style=&quot;background-color:rgba(0, 0, 200, 0.1); vertical-align: middle; padding:20px; margin: 10px; border-radius: 15px; font-style: italic;&quot;&gt;
  Me: &quot;Dad, sooo.. have you sold Gold before?&quot; &lt;br /&gt;
  Dad: &quot;Nope. In fact, I personally don't know anyone who ever did that.&quot; &lt;br /&gt;&lt;br /&gt;
  Me: &quot;So where do I sell gold when I need to sell it?&quot; &lt;br /&gt;
  Dad: &quot;What do you mean? You NEVER, EVER sell your gold. You only keep buying it whenever you can.&quot; &lt;br /&gt;&lt;br /&gt;
  Me: &quot;Wait, that simply does not make sense. Why would I buy it then?&quot; &lt;br /&gt;
  Dad: &quot;I cannot imagine how you can think of SELLING gold! Don't even think of touching it.&quot;
&lt;/div&gt;

&lt;p&gt;And I couldn’t fathom how I would have a chunk of my net worth sitting in a safe deposit box with no apparent purpose. My parents, as they usually do, would just accept the ridicule and move on to a different topic. In a few years, this topic vanished from our conversations. Then I witnessed something.. which proved to be a turning point.&lt;/p&gt;

&lt;p&gt;There was a 30-something affluent, happy couple named Raj and Riya. They were happily wed for 4 years and had a beautiful 2 year old daughter. They had a wonderful house, business was booming, and things simply cannot get better. And then, suddenly Raj’s behavior started changing and it changed rapidly with every passing day. He became short-tempered, was over-reacting and a dreaded dementia started setting in. He was not open to treatments and started making blatant mistakes in his business and investments. He made bigger mistakes to cover up previous mistakes. When he finally agreed to visit a doctor, to everyone’s horror, he was diagnosed with Alzheimer’s. This had a huge impact on his confidence, and he turned to gambling to find the much needed acceptance. Before Riya could react, all their hard-earned money including their sprawling, coveted primary residence at the city center… was simply gone. Riya finally made peace with the situation and moved out with their daughter to her parents’ place and started off a new life from scratch. Raj continued visiting her asking for more money to gamble. After being told off a few times, Raj stopped bothering her. And in a few days, she learnt that he was… dead. Amid the devastation the family was going through, Riya was purging all their bank accounts to ensure it cannot be misused further by Raj’s business partners. To her surprise, there was one account which was still untouched.&lt;/p&gt;

&lt;p&gt;The account was their safety deposit box with.. Gold.&lt;/p&gt;

&lt;p&gt;This experience, though second-hand, was so powerful to etch the importance of having an absolutely untouchable asset, an asset which can endure catastrophes of our own pristine minds and protect families and generations to come from our own selves. As you can see, you can replace Gold with any financial asset here, but in my family’s case and in Raj’s case Gold turned out to be the traditional choice for the untouchable asset.&lt;/p&gt;

&lt;p&gt;One other subconscious safety net where I’ve gone from mockery -&amp;gt; ignoring it -&amp;gt; outright rejection —–&amp;gt; acceptance is the indispensable role of &lt;strong&gt;God&lt;/strong&gt; in life.&lt;/p&gt;

&lt;p&gt;Following are some of my own quotes from the past decade in chronological order on the concept of God.&lt;/p&gt;

&lt;div style=&quot;background-color:rgba(0, 0, 200, 0.1); vertical-align: middle; padding:20px; margin: 10px; border-radius: 15px; font-style: italic;&quot;&gt;
  &lt;ul&gt;
  &lt;li&gt;&quot;I do not care if there is a God or not. Why are people so obsessed about it?&quot;&lt;/li&gt;
  &lt;li&gt;&quot;Seek scientific truth. Where is God? Do you see Him? Has anyone seen Him at all?&quot;&lt;/li&gt;
  &lt;li&gt;&quot;If there is no evidence, then God simply does not exist. The end.&quot;&lt;/li&gt;
  &lt;li&gt;&quot;Have you even listened to Richard Dawkins&quot;&lt;/li&gt;
  &lt;li&gt;&quot;See, why do I need a God while science can and will fully explain the universe?&quot;&lt;/li&gt;
  &lt;li&gt;&quot;If there was a God, He wouldn't let his people suffer. Would He?&quot;&lt;/li&gt;
  &lt;li&gt;&quot;Why do you have to bribe God in temples. Don't you understand this is just a business transaction at this point?&quot;&lt;/li&gt;
  &lt;li&gt;&quot;I've never thought harm to an ant, why did God break my ankle and make me bed-ridden for months?&quot;&lt;/li&gt;
  &lt;li&gt;&quot;The concept of God blinds children from looking further into the truth!&quot;&lt;/li&gt;
  &lt;li&gt;&quot;Ok, God might apply to you. I do not need Him though. That said, I won't scoff at people who need Him.&quot;&lt;/li&gt;
  &lt;li&gt;&quot;Damn! I get it now. God is a crucial part of a healthy society -- especially one that is 7bn+ people large.&quot; &lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;

&lt;p&gt;Let’s leave it at that. If you are curious to know how the last transition happened, we should meet over coffee/dinner. That by itself warrants another essay.&lt;/p&gt;

&lt;p&gt;So, when you find someone, especially smart and well-meaning elders, with an irrational belief or unexplainable practice – give them an opportunity to explain it to their best potential. There is a chance, however small, that there is an unconscious safety net waiting for you to explore.&lt;/p&gt;

&lt;h1 id=&quot;learning-2-embrace-grey&quot;&gt;&lt;strong&gt;Learning #2: Embrace Grey&lt;/strong&gt;&lt;/h1&gt;

&lt;p&gt;By the time you are 30, most of the choices you are faced with are not as stark as black and white. If they are black and white, and you are still confused, talk to a buddy, get a cup of coffee or.. simply go to sleep and decide the next day. You got this.&lt;/p&gt;

&lt;p&gt;Let’s talk about the Grey between the black and white.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;On Conflicts: There are no Heroes and Villains&lt;/strong&gt;: The famous quote from Aesop goes &lt;em&gt;“A man is known by the company he keeps”&lt;/em&gt; and there is a lot of truth to it. You should assume people around you to be as smart/stupid and good-intentioned as you are. In that setting, when your friends John and Jane have a conflict, it is highly unlikely that one of them is a clear villain there and do not make haste to label them as such. In fact, it is easy and interesting to do so. The truth is usually somewhere in between a Hero and Villain. As you navigate the space of evidences and decisions to solve the conflict, you will come across many, many choices of Grey. The real skill there comes in assigning each of those choices different shades of grey, make a choice and articulate them effectively. So, get comfortable in thinking and communicating Grey.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;On Measuring: There is no One Metric to rule them all&lt;/strong&gt;: Step count alone does not determine your fitness and year-over-year profit alone does not determine long-term growth of a company. Many times, society will lead you to believe that there is a single magic number to base our decisions on and provide you products and services around that magic number. This spans across various walks of life like health, personal finance, health of relationships, nurturing kids, measuring work, optimizing investing, buying a home, tracking CoViD, and even general happiness in life. When society throws such a number at you, put it in perspective with other numbers around it (in space/time) and deliberately move it to a grey zone. I promise your decisions will be much better than otherwise.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;On being emotional: Being Dispassionate vs. Passionate&lt;/strong&gt;: One of the recurring themes of my 20s was experimenting between living a dispassionate vs. passionate life. You go about your life as usual - you meet your friends, you listen to their joys and sorrows, you go to work, you face ups and downs. But you can &lt;em&gt;perceive&lt;/em&gt; these events either by deeply connecting with the event/person or dispassionately pass through those events emotionally unaffected. In my early 20’s I was heavily influenced by Stoicism and practiced living a dispassionate life. It worked really, really well in the USA’s individualistic culture for a long time. I had lots of very good friends and maintain excellent relationship with my family. I went from being single to getting married, and then one day suddenly the ideal of dispassionate living stopped working for me – the arrival of my daughter changed things quite drastically. I cared too deeply for my daughter that I simply couldn’t have my brain regulate my heart every time something unnecessary is enforced on her. I’ve moved considerably to the passionate side of the scale and I feel more human now.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;div style=&quot;background-color:rgba(0, 0, 200, 0.1); vertical-align: middle; padding:20px; margin: 10px; border-radius: 15px; font-style: italic;&quot;&gt;
&quot;Discovering more joy does not, I’m sorry to say, save us from the inevitability of hardship and heartbreak. In fact, we may cry more easily, but we will laugh more easily, too. Perhaps we are just more alive. Yet as we discover more joy, we can face suffering in a way that ennobles rather than embitters. We have hardship without becoming hard. We have heartbreak without being broken.&quot; &lt;br /&gt;&lt;br /&gt;- Archbishop Desmond Tutu, in The Book of Joy: Lasting Happiness in a Changing World.
&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;On thinking styles: Analytical vs. Creative&lt;/strong&gt;: Analysis and creation fundamentally require two different mindsets. Analysis requires you to observe a phenomenon carefully from different angles, attend to its details, understand patterns, and come out with an insight which informs your next step. Creation requires you to do a wide-range of observations, completely disconnect and let your subconscious brain make connections which did not exist before. To be a successful and happy individual in life, you need both. Success, to some extent, can be chased by over-leveraging on analytical thinking. However, creativity is what lets your originality and authentic-self shine through leading to exponential jumps in career and in personal life. I am convinced at this point that you can’t be creative and analytical at the same point of time. The Grey here is to allot time for both creativity and analytical thinking in a given time interval so that on the whole your thinking style looks Grey.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, get comfortable with grey and when given options A and B, choose C. Your identity is pretty much where you fall in this infinite-dimensional spectrum of grey. As you grow older you will add more dimensions and higher resolution to each of the spectrums, and continue taking a stand on where you fall within each of them making life richer and easier in the process.&lt;/p&gt;

&lt;h1 id=&quot;closing-thoughts-living-fully&quot;&gt;&lt;strong&gt;Closing Thoughts: Living Fully&lt;/strong&gt;&lt;/h1&gt;

&lt;p&gt;With the human life expectancy of ~79 years (&lt;a href=&quot;https://www.cdc.gov/nchs/fastats/life-expectancy.htm&quot;&gt;CDC&lt;/a&gt;), turning 30 is a moment when you realize that life is short and long at the same time. I’ve always lived in competitive environments from my early childhood. I’ve forever been driven to reach some “goal” at any point in my life – get 100/100 marks, get that gold medal, get into a top university, get hired by a top company, get promoted every 2 years, etc. If I reach the goal I am awesome and acknowledged, otherwise I am a disaster and should rethink the purpose of my life. Interestingly, the society keeps manufacturing and surfacing these “goals” and has well-established, evolved multi-agent processes and reward structures around it. I kept my heads down and slogged tirelessly to see the end of this tunnel so I can finally start to… you know.. live, whatever that means. Somewhere in this daisy-chained rat race, my parents felt I was doing great on my own and let me drive by myself. &lt;em&gt;Wait, what?! Where are you going?&lt;/em&gt;&lt;/p&gt;

&lt;div style=&quot;background-color:rgba(0, 0, 200, 0.1); vertical-align: middle; padding:20px; margin: 10px; border-radius: 15px;&quot;&gt;
  &quot;The journey is the destination&quot;
  - Dan Eldon
&lt;/div&gt;

&lt;p&gt;By the time you are 30, you know a lot more about what you really want and what the world can offer. You realize that the world can give you a much richer and fuller life if you simply pause occasionally, look around, take a detour and smell those byway flowers rather than repeatedly devise optimized route plans and drive straight to the made-up destinations. It’s the journey that matters. Note that this does not mean you become less ambitious, in fact surprisingly you become highly ambitious on a lot of things.&lt;/p&gt;

&lt;p&gt;Looking forward to the next decade of life!&lt;/p&gt;
</description>
        <pubDate>Sat, 01 Aug 2020 10:00:00 +0000</pubDate>
        <link>https://narendran.github.io/general/2020/08/01/turning-30.html</link>
        <guid isPermaLink="true">https://narendran.github.io/general/2020/08/01/turning-30.html</guid>
        
        
        <category>general</category>
        
      </item>
    
      <item>
        <title>The Differentiable Bread Toaster: A Discontinuity in Modern Software Systems</title>
        <description>&lt;p&gt;In the last couple of years, I’ve had the opportunity to improve some highly-used software systems applying recent developments in machine learning (ML). Amid all the joys and the noise in developing and deploying ML models in production, there is a nagging discontinuity in both the thought-process and actual software development which has felt unnatural to me. The discontinuity is between the Java/C++/Python/Go programs we write as part of standard software development and the artifacts of ML i.e. learned models. In this post, I will quickly describe the problem and a potential opportunity to address it using differentiable programming.&lt;/p&gt;

&lt;p&gt;[8 minute read]&lt;/p&gt;

&lt;h1 id=&quot;what-is-differentiable-programming&quot;&gt;What is Differentiable Programming&lt;/h1&gt;

&lt;p&gt;Differentiable programming allows you to write computer programs that could be differentiated with respect to their inputs. This has been possible for decades now either via numerical approximations to differentiation (which suffers from inaccuracies) or using symbolic differentiation techniques like what is done in Python’s SymPy package and in Wolfram (which suffers from lack of speed and flexibility required in practice). Recent improvements in Automatic Differentiation has allowed libraries like AutoDiff, AutoGrad, and JAX (which is used in this post) to address these concerns enabling differentiation as a first-class tool in mainstream software development.&lt;/p&gt;

&lt;p&gt;Following is a very simple example of a differentiable program. By the end of this post, I will give an idea of how composing such simple programs enables us to build software systems which were hitherto hard to build or even inconceivable.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;squared&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;squared&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#  x^2 = 16
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;grad&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;squared&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#  First order derivative = 2*x = 8
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;grad&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;grad&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;squared&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#  Second order derivative = 2 for all values of x.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;current-applications-and-state-of-differentiable-programs&quot;&gt;Current Applications and State of Differentiable Programs&lt;/h1&gt;

&lt;p&gt;Differentiation has been largely applied in scientific computing for decades now and following is a small sample from the application domains.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Finance: Black Scholes equation for pricing options.&lt;/li&gt;
  &lt;li&gt;Physics: Equation of motion, Heat dissipation, Brownian motion.&lt;/li&gt;
  &lt;li&gt;Biology: Population growth models, Neuron action potentials.&lt;/li&gt;
  &lt;li&gt;Chemistry: Rate equation to predict rate of change of concentration of reactants and products.&lt;/li&gt;
  &lt;li&gt;Archaeology: Carbon dating.&lt;/li&gt;
  &lt;li&gt;Web: Content ranking, Click prediction.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And we have lots of tools to perform differentiation using computers. Today, there are Domain Specific Languages like MatLab, R, Julia &amp;amp; Wolfram, and General-purpose Programming Languages like C++ and Python which have extensions to do differentiation. However, when thought about in the context of mainstream software development, they suffer two problems.&lt;/p&gt;

&lt;p&gt;Firstly, to make the discussion easier, let’s pick a specific area and programming language, say Supervised ML and Python. There is a dichotomy in thought and code when we think about where our classical programs end and supervised “intelligence” begins today. For instance, where do TensorFlow SavedModels and pickled PyTorch models fit in our software? At best, we can think of them as opaque learned functions with rigid expectations on inputs and outputs. As a software developer if I have to modify their functionality a little bit, there is a completely different set of tools and terminology I have to work with – let’s call it the &lt;a href=&quot;https://medium.com/@karpathy/software-2-0-a64152b37c35&quot; target=&quot;_blank&quot;&gt;Software 2.0&lt;/a&gt; workflow. This dichotomy shows through right from the code, to the developers’ perception, the surrounding workflow, inter-team coordination and bubbles up all the way to the job listings from companies (like SWE, SWE-ML, ML-SWE, Research Engineer, Applied Scientist in ML etc.) and university courses/programs.&lt;/p&gt;

&lt;p&gt;Secondly, today’s Supervised ML frameworks are too complex and have too many assumptions built in. The latter can be worked around by using more granular components of the framework like TensorFlow. The argument on complexity still remains. When I got introduced to ML, I was astounded at the level of complexity in systems like Tensorflow and PyTorch. What are they? Libraries/runtimes/programming languages? Even before I answered those questions, I had gotten used to the workflow and deferred thinking about it. Over time I realized that bringing together the core pieces required for mainstream machine learning is very, very hard. As this &lt;a href=&quot;https://julialang.org/blog/2017/12/ml-pl/&quot; target=&quot;_blank&quot;&gt;blog from Julia team&lt;/a&gt; puts it, machine learning is heavy on numerics, derivatives and parallelism which explains the complexity in developing ML systems of today.&lt;/p&gt;

&lt;p&gt;In that backdrop, it is exciting to see a coherent suite for ML coming together in Python. There is always numpy to take care of the numerics. Recent developments in well-thought Automatic Differentiation libraries can take care of the derivatives and parallelism aspects while also allowing programming flexibility by differentiating through constructs like variables, loops and conditionals. Woohoo! Ok, what can we do with this capability?&lt;/p&gt;

&lt;h1 id=&quot;using-differentiation-as-a-first-class-programming-primitive&quot;&gt;Using Differentiation as a first-class programming primitive&lt;/h1&gt;

&lt;p&gt;To some approximation, software developers observe how humans communicate and exchange in real world and model those behaviors in computer programs. In this paradigm, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f(x,y) = x + y&lt;/code&gt; will always return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x + y&lt;/code&gt; irrespective of the actual real-world function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f&lt;/code&gt; has to approximate. And when the underlying assumptions on real-world behaviors do change, we have channels like monitoring, product forums, brand analysis etc. to detect a shift in expectations, re-design, re-implement, rinse and repeat.&lt;/p&gt;

&lt;p&gt;But.. what if programs can automatically adapt and rewrite themselves over time? Like the way humans grow intelligent by composing knowledge extracted from daily observations on top of existing knowledge, can we continually feed soft rules into the program and make it increasingly aware of its purpose in life? Yes, we can. A ~20 line artificial neuron (&lt;strong&gt;&lt;a href=&quot;https://github.com/narendran/differentiable-programming/tree/master/jaxnn&quot; target=&quot;_blank&quot;&gt;code&lt;/a&gt;&lt;/strong&gt;) could arguably be the smallest unit of such a composable, learning program. And here is a &lt;strong&gt;&lt;a href=&quot;https://github.com/narendran/differentiable-programming/blob/master/jaxnn/jaxnn_test.py#L57&quot; target=&quot;_blank&quot;&gt;tiny demo&lt;/a&gt;&lt;/strong&gt; where we learn the rule “given three numbers, always return the second number”. The differentiable program learns it with just 20 examples! Composing this idea of an artificial neuron with some structural assumptions, we get differentiable data structures and programming constructs like Attention, RNNs, Pooling techniques and even CNNs. These could be considered differentiable equivalents of hashmaps, loops, conditionals and image filters. So from latest trends in ML, we have been exploiting differentiable image filters to make sense of images and differentiable hashmaps to keep track of the words in a document.&lt;/p&gt;

&lt;p&gt;We don’t need to stop with the differentiable versions of data structures and programming constructs.&lt;/p&gt;

&lt;p&gt;Let’s look at programming from the other direction i.e. from top to bottom. I have a physical process I want to emulate, and I have very little understanding of how it works. However, I can observe how it operates under different inputs. To help our imagination, let’s consider a simple bread toaster (because… why not?) which can take in different number of bread slices, say &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N&lt;/code&gt;, and toasts them in an unknown &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f(N)&lt;/code&gt; seconds. I have been manually powering down this toaster all these days and I really want to automate it. Let’s consider three hypotheses about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f(N)&lt;/code&gt;.&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f(N) = 30 * N&lt;/code&gt; // It says 30 seconds on the toaster’s manual, no learning needed.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f(N) = 30 * N&lt;/code&gt; // Its not on the manual, needs a learning program.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;f(N) = 7th order Taylor approximation of sin(N)&lt;/code&gt; // Its not on the manual, needs some biased learning program.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Our differentiable bread toaster (&lt;strong&gt;&lt;a href=&quot;https://github.com/narendran/differentiable-programming/blob/master/bread_toaster&quot; target=&quot;_blank&quot;&gt;code&lt;/a&gt;&lt;/strong&gt;) can handle all these cases now. And we can improve its accuracy further by adding well-known physical phenomena like the equation for heat dissipation + structure of the grill inside the toaster and Automatic Differentiation would effortlessly differentiate it for you. Similar ideas have been seen in robotics with differentiable physics engines, improving computer vision with differentiable modules for image transformation + camera calibration and dramatically improving computer graphics rendering using differentiable ray tracers. Tesla’s AutoPilot can be framed as a gigantic differentiable program where we plug in high-precision algorithms or learned models for different aspects of driving and compose them in a principled manner with appropriate differentiable data structures and algorithms to output steering, braking and acceleration. As we can see, the possibilities are endless.&lt;/p&gt;

&lt;h1 id=&quot;lets-build&quot;&gt;Let’s build!&lt;/h1&gt;

&lt;p&gt;I strongly believe differentiable programming can address the aforementioned discontinuity in modern software systems by seamlessly blending hand-coded and learned rules. Plus, we can leverage all the existing hard-earned, well-tested knowledge on algorithms and data structures to tackle grander challenges in software engineering. It’s time to differentiate our bread toasters and build the next “AutoPilot”.&lt;/p&gt;

&lt;div style=&quot;background-color:rgba(0, 0, 200, 0.1); vertical-align: middle; padding:20px; margin: 10px; border-radius: 15px;&quot;&gt;
  If our small minds, for some convenience, divide this glass of wine, this universe, into parts -- physics, biology, geology, astronomy, psychology, and so on -- remember that nature does not know it!
  - Richard P. Feynman
&lt;/div&gt;

&lt;h1 id=&quot;references&quot;&gt;References&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/google/jax&quot;&gt;JAX&lt;/a&gt;, &lt;a href=&quot;https://www.ijaiem.org/Volume6Issue7/IJAIEM-2017-07-13-30.pdf&quot;&gt;Engineering Applications of Differential equation&lt;/a&gt;, &lt;a href=&quot;https://pages.cpsc.ucalgary.ca/~robin/FMCS/FMCS2019/slides/GordonPlotkin-FMCS2019.pdf&quot;&gt;Differential programming languages&lt;/a&gt;, &lt;a href=&quot;https://medium.com/@karpathy/software-2-0-a64152b37c35&quot;&gt;Software 2.0&lt;/a&gt;, &lt;a href=&quot;https://julialang.org/blog/2017/12/ml-pl/#what_might_a_tailor-made_ml_language_look_like&quot;&gt;Tailor-made ML language&lt;/a&gt;, &lt;a href=&quot;https://fluxml.ai/2019/02/07/what-is-differentiable-programming.html&quot;&gt;Differentiable Programming&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Wed, 20 May 2020 10:00:00 +0000</pubDate>
        <link>https://narendran.github.io/tech/2020/05/20/differentiable-programming.html</link>
        <guid isPermaLink="true">https://narendran.github.io/tech/2020/05/20/differentiable-programming.html</guid>
        
        
        <category>tech</category>
        
      </item>
    
      <item>
        <title>MongoDB vs. RethinkDB</title>
        <description>&lt;p&gt;As a student, I prefer building prototypes before building the full-fledged systems. So when it comes to choice of data storage, firstly, I would prefer having no schema enforced on my data since it will almost always change with time. Secondly, once the system is up and running, I would expect robust data collection, efficient querying and easy-to-use analytics systems to make sense of the data. Ever since MongoDB was initially released in 2009, I have always used it for all my personal and research projects. However nowadays, I have started seeing a lot of blog posts which complain about the performance of MongoDB. So in this blog post, I attempt to study and compare document-based databases MongoDB and the recent favorite, RethinkDB, since I am starting to consider RethinkDB for my future projects (though it has been around since 2012). One common paradigm which I like in both is that they store data in the same way it is (most likely) used in the application layer, i.e. as JSON documents, reducing impedance mismatch in data representation.&lt;/p&gt;

&lt;h1 id=&quot;philosophy&quot;&gt;Philosophy&lt;/h1&gt;

&lt;p&gt;RethinkDB, which has been in active development for three years now, was designed with a &lt;em&gt;bottom-up&lt;/em&gt; perspective with the design goals of ease of use, high availability and high scalability in mind. From the MongoDB architecture guide, we can understand that MongoDB was designed &lt;em&gt;top-down&lt;/em&gt; by taking an existing system (like MySQL) and enhancing it with dynamic schemas while still providing the relational database features like indexes and updates.&lt;/p&gt;

&lt;h1 id=&quot;data-model&quot;&gt;Data Model&lt;/h1&gt;

&lt;p&gt;Firstly, lets talk about the physical data model. In MongoDB, data is stored as &lt;a href=&quot;http://bsonspec.org&quot;&gt;BSON&lt;/a&gt; documents while in RethinkDB, data is stored as JSON documents. One of the advantage of BSON documents is that in addition to the existing JSON datatypes (string, number, object, array, boolean and null) it provides int, long and double types. The full list of BSON types can be found &lt;a href=&quot;http://docs.MongoDB.org/manual/reference/bson-types/&quot;&gt;here&lt;/a&gt;. This enables more granular comparison (and hence sorting) of data. For instance, since MongoDB comes with an inbuilt &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;date&lt;/code&gt; type, it is straight-forward to construct date range queries which I have found to be very useful while working with Twitter data for my recent projects.&lt;/p&gt;

&lt;div style=&quot;background-color:rgba(0, 0, 200, 0.1); vertical-align: middle; padding:20px; margin: 10px; border-radius: 15px;&quot;&gt;
&lt;b&gt;@coffeemug:&lt;/b&gt;  RethinkDB implements an extended version of JSON, so it supports additional data types (like dates, geometric primitives, etc.) It isn't necessarily better or worse than BSON -- there are a few nuanced tradeoffs (e.g. JSON library implementations in languages with smaller ecosystems are better), but from the functionality perspective both approaches are very similar.
&lt;/div&gt;

&lt;p&gt;Secondly, talking about conceptual data model, both RethinkDB and MongoDB are pretty simple. From MongoDB’s &lt;a href=&quot;http://www.mongodb.org/about/introduction/#mongodb-data-model&quot;&gt;documentation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A MongoDB deployment hosts a number of databases. A database holds a set of collections. A collection holds a set of documents. A document is a set of key-value pairs. Documents have dynamic schema.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Similarly, a RethinkDB deployment has a bunch of databases. Each database has a bunch of tables, where each table contains related documents (which have dynamic schema).&lt;/p&gt;

&lt;h1 id=&quot;query-language&quot;&gt;Query Language&lt;/h1&gt;

&lt;p&gt;Instead of going to a new query language, MongoDB keeps it simple by hooking directly into the programming language using which it is called. However, RethinkDB has introduced a new query language called &lt;a href=&quot;http://rethinkdb.com/docs/introduction-to-reql/&quot;&gt;ReQL&lt;/a&gt; which is inspired by functional languages like Haskell. If you love functional programming paradigm, you will love ReQL as well since it provides the same simplicity and power. Also, the functional language paradigm makes it easy to parallelize execution among multiple cores/servers/datacenters.&lt;/p&gt;

&lt;h1 id=&quot;performance&quot;&gt;Performance&lt;/h1&gt;

&lt;p&gt;The scripts used for performing the following performance study can be found &lt;a href=&quot;https://github.com/narendran/blogs/tree/master/mongo-vs-rethink/code&quot;&gt;here&lt;/a&gt;. The following readings were taken on a mid-2013 Macbook Air with 1.7 Ghz Intel Core i7 (2 cores) , 8 GB 1600 MHz DDR3 memory, 256 KB L2 cache (per core), 4MB L3 cache and 250 GB APPLE SSD. The system run OS X 10.10.2 (Yosemite) and MongoDB version 2.6.5 was accessed with pymongo version 2.6.3. To access RethinkDB, version 2.0.0-2 of python &lt;em&gt;rethinkdb&lt;/em&gt; package was used on RethinkDB 2.0.2. To make the results glanceable, I have plotted the average execution time with a blue line in all the plots below. All the performance numbers are in microseconds (us).&lt;/p&gt;

&lt;h4 id=&quot;write-performance&quot;&gt;Write Performance&lt;/h4&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;MongoDB writes (Avg. : 37130 us)&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;RethinkDB writes (Avg. : 12680 us)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;https://raw.githubusercontent.com/narendran/blogs/master/mongo-vs-rethink/plots/mongo_writes_w1_jTrue.png&quot; alt=&quot;MongoDB writes performance&quot; /&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;https://raw.githubusercontent.com/narendran/blogs/master/mongo-vs-rethink/plots/rethink_writes.png&quot; alt=&quot;RethinkDB writes performance&quot; /&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;As we can see clearly, there is a remarkable difference in the write performance. Besides the higher average latency, MongoDB has a higher variance of 1744 us as compared to 1468 us in RethinkDB. This is where MongoDB’s &lt;strong&gt;write concern&lt;/strong&gt; gives us choice. Following plots show the performance differences with the three different write concerns in mongoDB. I haven’t tested the replica write concern since I working on a single server configuration.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;MongoDB Unacknowledged (115.00 us : memory, maybe)&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;MongoDB Acknowledged (265.2 us : memory)&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;MongoDB Journaled (37130 us : disk)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;https://raw.githubusercontent.com/narendran/blogs/master/mongo-vs-rethink/plots/mongo_writes_w0.png&quot; alt=&quot;Unacknowledged&quot; /&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;https://raw.githubusercontent.com/narendran/blogs/master/mongo-vs-rethink/plots/mongo_writes_w1.png&quot; alt=&quot;Acknowledged&quot; /&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;https://raw.githubusercontent.com/narendran/blogs/master/mongo-vs-rethink/plots/mongo_writes_w1_jTrue.png&quot; alt=&quot;Journaled&quot; /&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;So the right way to compare with RethinkDB’s write performance would be with the &lt;em&gt;Journaled&lt;/em&gt; write concern which actually persists data to disk (which is RethinkDB’s default write behaviour). In terms of speed of persistent writes, RethinkDB wins. Thanks to the recent comment from RethinkDB cofounder @coffeemug, I realized that RethinkDB also offers more flexibility when it comes to writes.&lt;/p&gt;

&lt;div style=&quot;background-color:rgba(0, 0, 200, 0.1); vertical-align: middle; padding:20px; margin: 10px; border-radius: 15px;&quot;&gt;
&lt;b&gt;@coffeemug:&lt;/b&gt;  RethinkDB also offers a way to configure the write mode (see the `durability` option in &lt;a href=&quot;http://rethinkdb.com/api/javascript/run/&quot;&gt;http://rethinkdb.com/api/javascript/run/&lt;/a&gt; and `write_acks` option in &lt;a href=&quot;http://rethinkdb.com/docs/consistency/&quot;&gt;http://rethinkdb.com/docs/consistency/&lt;/a&gt;). Everything is fully configurable, and there is full support for high availability in case of hardware failure.
&lt;/div&gt;

&lt;h4 id=&quot;read-performance&quot;&gt;Read performance&lt;/h4&gt;

&lt;p&gt;For studying the read performance in both databases, the generated primary key fields were used for reading a single document. MongoDB generates a &lt;em&gt;_id&lt;/em&gt; field and RethinkDB generates a &lt;em&gt;id&lt;/em&gt; field when a primary key is not part of the input document.&lt;/p&gt;

&lt;div style=&quot;background-color:rgba(0, 0, 200, 0.1); vertical-align: middle; padding:20px; margin: 10px; border-radius: 15px;&quot;&gt;
&lt;b&gt;Update:&lt;/b&gt; The following readings have been updated after the RethinkDB team reported the problem with using `find` in mongoDB. Based on that, the script used for measuring read timings has been updated.
&lt;/div&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;MongoDB reads (cached) (Avg. : 270.77 us)&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;MongoDB reads (not cached) (Avg. : 452.54 us)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;https://raw.githubusercontent.com/narendran/blogs/master/mongo-vs-rethink/plots/mongo_reads_cache.png&quot; alt=&quot;MongoDB reads (cache support)&quot; /&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;https://raw.githubusercontent.com/narendran/blogs/master/mongo-vs-rethink/plots/mongo_reads_no_cache.png&quot; alt=&quot;MongoDB reads (no cache support)&quot; /&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;In either case, the first call to find() takes a longer time since it has OS level operations like getting file handle to the appropriate BSON file. However, since we are working with 1000 iterations, the effect of the first call will be suppressed. In real-world deployments, MongoDB will have huge memory and cache at its disposal. So, to be fair, I felt it was needed to show how MongoDB would perform in both cases - when data is in cache and when data is flushed out of cache.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;RethinkDB reads (cached) (Avg. : 558.4 us)&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;RethinkDB reads (not cached) (Avg. : 740.2 us)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;https://raw.githubusercontent.com/narendran/blogs/master/mongo-vs-rethink/plots/rethinkdb_reads_cache.png&quot; alt=&quot;RethinkDB reads (cache support)&quot; /&gt;&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;https://raw.githubusercontent.com/narendran/blogs/master/mongo-vs-rethink/plots/rethinkdb_reads_no_cache.png&quot; alt=&quot;RethinkDB reads (no cache support)&quot; /&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;In terms of read performance, MongoDB wins RethinkDB by a huge margin. I do not clearly understand why though. However, considering &lt;strong&gt;map-reduce&lt;/strong&gt; queries as a specialized read query, let’s talk about it here. RethinkDB parallelizes map-reduce operations across shards and CPU cores whenever possible (source: RethinkDB documentation). However, MongoDB’s map-reduce queries are painfully slow since they use only one core even if you have 32 cores (source: experience). In case you have a use-case to execute map-reduce on MongoDB, I would suggest you to translate them to aggregation queries which run on their (relatively recent and much faster) C++ based aggregation framework.&lt;/p&gt;

&lt;h1 id=&quot;real-time-feeds&quot;&gt;Real time feeds&lt;/h1&gt;

&lt;p&gt;With the rise of social media, we have a lot of sources which provide real-time data. To make better sense of the high-volume, high-velocity data we see everyday, we need some processing to be setup on arrival of each datapoints (aka event). The processing can be throwing the datapoint to a front-end which in turn plots it on a map like &lt;a href=&quot;http://tweetping.net&quot;&gt;Tweet Ping&lt;/a&gt; dashboard or using the data point for recalculating Bollinger Bands in a chart showing real-time trends. With the advent of Apache Spark, real-time machine learning has become much easier as well. All that said, such kinds of processing should be done without much overhead when using high velocity data. For instance, if you use the most basic sample hose streaming API from Twitter to get 1% sample of all global tweets, you would get roughly 70 tweets per second.&lt;/p&gt;

&lt;p&gt;MongoDB’s advised way of going about it is to use tailable cursors which was originally inspired by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tail -f&lt;/code&gt; command in UNIX systems which we generally use to monitor log files. However, the catch is that tailable cursors can be created only for special collections called &lt;em&gt;capped collections&lt;/em&gt;. Making a  collection &lt;em&gt;callable&lt;/em&gt; is possible only when we create the collection. This basically takes two lines in python.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;createCollection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;capped_collection&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;capped&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;cur&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;capped_collection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tailable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Tailable cursors and capped collection would work only for insertions. If you are interested in all operations on the collection, the way to go is to poll the operational logs files called &lt;em&gt;oplog&lt;/em&gt;. There are tools around this like &lt;a href=&quot;https://www.npmjs.com/package/mongo-watch&quot;&gt;mongo-watch&lt;/a&gt; to make our lives easier. And the &lt;em&gt;oplog&lt;/em&gt; way doesn’t require any kind of special collections.&lt;/p&gt;

&lt;p&gt;RethinkDB provides a very intuitive way to get notifications on changes. The composability ReQL allows helps us to chain operations in any order giving us much more flexibility than what was possible with MongoDB. A simple ReQL snippet like&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;change&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;db&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;test_db&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;test_table&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;changes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;connection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;change&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;gives us real-time notification. You can take a look at the &lt;a href=&quot;http://rethinkdb.com/api/python/changes/&quot;&gt;documentation&lt;/a&gt; on this feature to appreciate the level of flexibility it provides.&lt;/p&gt;

&lt;p&gt;Hopefully, this blog post gave an overall idea on where RethinkDB and MongoDB stand and if they are suitable for your project. In my case, given the tolerance to lossy writes on machine failure and need for faster reads &amp;amp; writes than RethinkDB’s, my projects are going to stay with MongoDB, while I wait for RethinkDB to become more impressive in terms of performance.&lt;/p&gt;
</description>
        <pubDate>Thu, 04 Jun 2015 16:00:00 +0000</pubDate>
        <link>https://narendran.github.io/tech/2015/06/04/mongo-vs-rethink.html</link>
        <guid isPermaLink="true">https://narendran.github.io/tech/2015/06/04/mongo-vs-rethink.html</guid>
        
        
        <category>tech</category>
        
      </item>
    
  </channel>
</rss>
