Jekyll2023-03-22T14:40:01+05:30http://pritesh-shrivastava.github.io/feed.xmlPritesh Shrivastava’s BlogMy blog on programming and data science (mostly)Pritesh ShrivastavaAI, consciousness & Vedanta2022-12-16T00:00:00+05:302022-12-16T00:00:00+05:30http://pritesh-shrivastava.github.io/blog/2022/12/16/ai-cant-be-conscious<p>The most common trope in all Western sci-fi movies is AI somehow getting conscious & taking over the world. The idea specially gained traction with movies like Terminator, Westworld, the Matrix and more recently Dark Mirror, etc. The current state of the art ML models are getting better and better at pattern recognition, but that in no way makes them anything remotely close to a sentient being.</p>
<p>To start with, do we even have a specific definition of “consciosness” ? It’s hard to find a commonly accepted idea in Western philosophy about this concept. The closest one gets is,
<code class="language-plaintext highlighter-rouge">I think therefore I am</code> by Descartes. So thought is the root of consciousness according to this theory.
But coming from an eastern perspective, there are so many things wrong with this idea. The “I” in this statement is what we are assuming to be our consciousness. But this is in stark contrast to the concept of Self (“aatm”) or Universal Consciousness in Advaita Vedanta.</p>
<h4 id="do-we-understand-consciousness-">Do we understand “consciousness” ?</h4>
<p>When we usually talk about who am I, we are referring to a story we keep telling ourselves. Identifying ourselves with the body & mind. The running stream of thoughts is giving a continuity to this sense of “I”. But is this the real self ? In Buddhism, this is simply referred to as mental conditioning.</p>
<p>Forget about the human mind, do we even understand what makes a plant conscious? Or even a single celled amoeba conscious ?</p>
<h4 id="are-ai-programs-replicating-the-ego-or-the-consiousness-">Are AI programs replicating the ego or the consiousness ?</h4>
<p>The consciousness that exists within all of us is something much deeper than our individual sense of “I”. Sure, we can give our program a human name like Alexa or Siri, which can visually classify cats and dogs through pattern recognition, regurgitate a movie review based on the 1000s of other reviews it had seen in the past.. You can direct the program to have a certain personality of likes and dislikes, desires, quirks, fears, etc. But as close as we ever come to doing this, the program can only ever replicate an image of our ego. It can not be said to be alive or sentient.</p>
<p>Consciousness doesn’t seem to be a computation. More compute power cannot really make our narrow AI more “conscious”. Ancient philosophies like Vedanta & Buddhism can help us understand if we are even asking the right questions.</p>Pritesh ShrivastavaBook recommendations from my Covid reading list2022-06-18T00:00:00+05:302022-06-18T00:00:00+05:30http://pritesh-shrivastava.github.io/blog/2022/06/18/book-recommendations<p>I’m getting back to blogging after a <em>looong</em> time. This post is slightly different.
I spent the major portion of the last 2 years working from my home due to COVID. This freed up a lot of my time. Among other things, I did a lot of reading during this period. & some of these books have had a lasting impression on my world view. Here I just wanted to talk about some of the most mind bending books that led me to change or atleast challenge my existing world views.</p>
<h4 id="mindfulness-in-plain-english---bhante-gunaratne">Mindfulness in Plain English - Bhante Gunaratne</h4>
<p><a href="https://www.goodreads.com/book/show/11028017-mindfulness-in-plain-english">Goodreads link</a></p>
<p>This book’s major focus is <em>Vipassana</em> meditation. I had done a 10-day <em>Vipassana</em> course a few years back but didn’t really continue the daily practise. As for the course experience, it’s really something you’ve to got to try out and experience yourself first hand. Atleast for now, I think any attempt by me to describe that journey would not remotely do any justice to it.<br />
In the last few months, I tried to go back to practising <em>Vipassana</em> or mindfulness meditation, and this
book is a very clear and helpful guide for anyone who wants to explore mindfulness.</p>
<h4 id="practical-vedanta---swami-vivekananda">Practical Vedanta - Swami Vivekananda</h4>
<p><a href="https://www.goodreads.com/book/show/6348194-practical-vedanta">Goodreads link</a></p>
<p>Or practicially, any other book by Vivekanada. It’s a pity I discovered Vivekananda’s books so late. I also read <a href="">My Master</a> & currently reading <a href="">Raja Yoga</a>.
Vivekananda was a strong proponent of <em>Vedanta</em>, especially the philosphy of <em>Advaita</em> or non-duality.
<em>Advaita Vedanta</em> & Buddhist philosophy seem to be like mirror images of each other.
One talks about infinity while the other talks about shunyata or the void. It’s no surprise that the concepts of <em>0</em> & infinity were discovered in India much earlier than anywhere else.</p>
<h4 id="autobiography-of-a-yogi--apprenticed-to-a-himalyan-master">Autobiography of a Yogi & Apprenticed to a Himalyan Master</h4>
<p><a href="https://www.goodreads.com/book/show/639864.Autobiography_of_a_Yogi">Link 1</a> &
<a href="https://www.goodreads.com/book/show/10125596-apprenticed-to-a-himalayan-master">Link 2</a></p>
<p>For an alternate perpective on life, these 2 books offer a peak into the world of mysticism. Read either one or both. I’m clubbing them together because both books talk about a specific path of <em>yoga</em> & offer amazing & sometimes bizarre accounts of 2 real life practitioners.
A couple of interesting facts about the writers of these 2 books -</p>
<p>100’s of copies of Paramhansa Yogananda’s <em>Autobiography of a Yogi</em> were distributed at the memorial service of Steve Jobs as his last gift.</p>
<p>Mumtaz Ali, referred to as Sri M, author of <em>Apprenticed to a Himalayan Master</em>, received the 3rd highest civilian honor of India, <em>Padma Bhushan</em> in 2020.</p>
<h4 id="a-brief-history-of-time---stephen-hawking">A Brief History of Time - Stephen Hawking</h4>
<p><a href="https://www.goodreads.com/book/show/3869.A_Brief_History_of_Time">Goodreads link</a></p>
<p>What is time ? Does it really exist ? Or is it a figment of imagination ?
After all, we always live in the <em>present</em> moment, the <em>now</em>. The past only lives in the memory & the future is but an expectation or projection of the mind. Is time a trick played by our mind ?
The continuity of our stream of thoughts leading us to believe we are definite entity moving forward in time, and space. This book is surely a mind bending experience & it was exciting to try to understand a brilliant physicist’s views on the concepts of space-time. A couple of my take-aways :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>All theories are wrong. Some are useful.
Science moves forward one funeral at a time.
</code></pre></div></div>Pritesh Shrivastava5 books to offer a different perspctive on lifeIs Data Structures & Algorithms important for a data scientist2021-08-30T00:00:00+05:302021-08-30T00:00:00+05:30http://pritesh-shrivastava.github.io/blog/2021/08/30/is-leetcode-needed-for-ds<h4 id="does-leetcode-grinding-make-you-a-better-data-scientist-">Does Leetcode grinding make you a better data scientist ?</h4>
<p><strong>TLDR</strong> - NOPE</p>
<p>In my 5 year expereince, spread across startups to large scale MNCs, I have hardly ever needed to know <code class="language-plaintext highlighter-rouge">how to traverse a binary tree</code>, say, in my day to day job as a data scientist! Yet, you’ll still find a lot of big tech companies include some Leetcode questions for the first round of most DS job interviews.</p>
<p>When I ask my colleagues the same question, they also respond in a similar manner that it’s a pointless skill in the data science domain, but something you need to learn to crack the interviews anyway. If you’re interested in a more non-anecdotal answer, check out a dicussion topic I started on <a href="https://www.kaggle.com/questions-and-answers/225859">Kaggle forum</a> some time back. Largely, the only argument in favour of Leetcode style interviews is that it is a standard practise in the tech industry for hiring Software Engineers, and is a good step to filter out from 100’s, if not 1000’s, of applicants for DS job roles right now.</p>
<p>Honestly, Leetcode grinding (OR HackerRank OR HackerEarth) just seems depressing to me. Leetcode has become to FAANG what CAT is to IIMs or JEE is to IITs (Indian context), but in a wierd twisted way. Spend enough time on practising such problems and most people would be able to solve (regurgigate?) these typical problems after a while.</p>
<p>Data Structures and Algorithms, as a topic of learning though, is actually a very interesting and intellectually stimulating topic in itself. though. And it does make sense for Software Engineers to understand these concepts well for their day jobs. But for someone who has decent programming skills and is more interested in data analysis, studying this topic for the sole aim of a job interview will be a dry, abstract and meaningless process.</p>
<p>Leetcode questions are essentially gatekeeping DS roles from non-CS background candidates. Imagine a farcical hypothetical scenario where a candidate with Math PhD, who has sufficient programming skills to build and deploy ML models for his research, then has to practise manipulating a linked list and inverting a binary tree for his job interviews. Data science is a very broad field with people from diverse disciplines like Economics, Biology, Astrophysics, etc already using ML to solve cutting edge problems in their domains. Leetcoding problems today are essentially gatekeeping this diverse community from moving into the tech industry.</p>
<p>The good news is that some companies have started moving away from this process slowly and started testing their candidates on stuff that really matters For eg. statistics, probability or data manipulation, using case studies / take home assignements on ML and EDA. I hope this trend catches on as the data science ecosystem matures further, thus making the Data Science community more inclusive.</p>Pritesh ShrivastavaWhy do many companies still ask CS puzzle type questions in their coding round for DS rolesStructural and Generative Recursion2021-05-30T00:00:00+05:302021-05-30T00:00:00+05:30http://pritesh-shrivastava.github.io/blog/2021/05/30/quick-sort-insertion-sort<p>Recursion is a central component in functional programming, and one of my favourity programming concepts. In this post, we are going to look at two distinct ways in which recursive functions can be designed.</p>
<p>We’ll using the examples of 2 very common sorting algorithms for numbers, ie, insertion sort and the quick sort. The code snippets used below have been adapted the free e-book <a href="https://htdp.org/2020-5-6/Book/index.html#%28part._htdp2e%29">How to Design Programs (HtDP)</a> and translated to MIT Scheme (from a teaching language created in Racket).</p>
<h3 id="insertion-sort-and-structural-recursion">Insertion Sort and Structural Recursion</h3>
<p>This is the most common type of recursive functions that we see in functional programming languages.
It follows a common template which is very similar to wishful thinking! It really intrigued me when I learnt about it back in high school and still intrigues me to this day.</p>
<p>“Structural” recursion uses the underlying data “structures” naturally. Here, we only ever solve a very trivial case of the problem, and then, as if by magic, recursion solves the complete problem without us telling the computer how to do it!</p>
<p>Let’s look at the <code class="language-plaintext highlighter-rouge">insertion-sort</code> function that takes a list of numbers as its argument.</p>
<div class="language-scheme highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">; sorts a list l in increasing order</span>
<span class="c1">; List-of-numbers -> List-of-numbers</span>
<span class="p">(</span><span class="k">define</span> <span class="p">(</span><span class="nf">insertion-sort</span> <span class="nv">l</span><span class="p">)</span>
<span class="p">(</span><span class="k">cond</span>
<span class="p">((</span><span class="nb">null?</span> <span class="nv">l</span><span class="p">)</span> <span class="o">'</span><span class="p">())</span>
<span class="p">(</span><span class="k">else</span> <span class="p">(</span><span class="nf">insert</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">l</span><span class="p">)</span> <span class="p">(</span><span class="nf">insertion-sort</span> <span class="p">(</span><span class="nb">cdr</span> <span class="nv">l</span><span class="p">))))))</span>
</code></pre></div></div>
<p>We have not yet defined the <code class="language-plaintext highlighter-rouge">insert</code> function so far. This is “wishful thinking” !!
If a function <code class="language-plaintext highlighter-rouge">insert</code> existed that would insert a given no into a sorted list at the right position, that would solve our problem! And so we just used in our recursive definition of <code class="language-plaintext highlighter-rouge">insertion-sort</code>. Notice that all we have really just solved the trivial case of sorting an empty list. And then, we are relying on recursion to sort the entire list by just naturally traversing the data structure, ie, the list.</p>
<div class="language-scheme highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">; We now define the 'insert' function from our wish list, after which our problem is solved.</span>
<span class="c1">; Helper function that inserts a number n into a sorted list of numbers l at its correct position </span>
<span class="c1">; Number List-of-numbers -> List-of-numbers</span>
<span class="p">(</span><span class="k">define</span> <span class="p">(</span><span class="nf">insert</span> <span class="nv">n</span> <span class="nv">l</span><span class="p">)</span>
<span class="p">(</span><span class="k">cond</span>
<span class="p">((</span><span class="nb">null?</span> <span class="nv">l</span><span class="p">)</span> <span class="p">(</span><span class="nb">cons</span> <span class="nv">n</span> <span class="o">'</span><span class="p">()))</span>
<span class="p">(</span><span class="k">else</span> <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb"><=</span> <span class="nv">n</span> <span class="p">(</span><span class="nf">first</span> <span class="nv">l</span><span class="p">))</span>
<span class="p">(</span><span class="nb">cons</span> <span class="nv">n</span> <span class="nv">l</span><span class="p">)</span>
<span class="p">(</span><span class="nb">cons</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">l</span><span class="p">)</span> <span class="p">(</span><span class="nf">insert</span> <span class="nv">n</span> <span class="p">(</span><span class="nb">cdr</span> <span class="nv">l</span><span class="p">)))))))</span>
<span class="c1">; testing the insert sort function with an example</span>
<span class="p">(</span><span class="nf">insertion-sort</span> <span class="o">'</span><span class="p">(</span><span class="nf">72</span> <span class="mi">45</span> <span class="mi">43</span> <span class="mi">29</span> <span class="mi">34</span><span class="p">))</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(29 34 43 45 72)
</code></pre></div></div>
<h3 id="quick-sort-and-generative-recursion">Quick Sort and Generative Recursion</h3>
<p>We see how structural recursion has a very natural design template.
In generative recursion though, instead of following a simple template like we did with Insertion Sort, we need some kind of mathematical insight into the problem itself to come up with the algorithm design. For quick sort, it’s ofcourse the “divide and conquer” strategy.</p>
<div class="language-scheme highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">; [List-of Number] -> [List-of Number]</span>
<span class="c1">; produces a sorted version of list l, assume the numbers are all distinct </span>
<span class="p">(</span><span class="k">define</span> <span class="p">(</span><span class="nf">quick-sort</span> <span class="nv">l</span><span class="p">)</span>
<span class="p">(</span><span class="k">cond</span>
<span class="p">((</span><span class="nb">null?</span> <span class="nv">l</span><span class="p">)</span> <span class="o">'</span><span class="p">())</span>
<span class="p">(</span><span class="k">else</span> <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nf">pivot</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">l</span><span class="p">)))</span>
<span class="p">(</span><span class="nb">append</span> <span class="p">(</span><span class="nf">quick-sort</span> <span class="p">(</span><span class="nf">smallers</span> <span class="nv">l</span> <span class="nv">pivot</span><span class="p">))</span>
<span class="p">(</span><span class="nb">list</span> <span class="nv">pivot</span><span class="p">)</span>
<span class="p">(</span><span class="nf">quick-sort</span> <span class="p">(</span><span class="nf">largers</span> <span class="nv">l</span> <span class="nv">pivot</span><span class="p">)))))))</span>
</code></pre></div></div>
<p>Here, again we used 2 functions <code class="language-plaintext highlighter-rouge">smallers</code> and <code class="language-plaintext highlighter-rouge">largers</code> that haven’t been defined yet, using wishful thinking once again!</p>
<div class="language-scheme highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">; returns the sub list of numbers from a given list of numbers that are greater than the given number n</span>
<span class="c1">; [List-of Number] Number -> [List-of Number]</span>
<span class="p">(</span><span class="k">define</span> <span class="p">(</span><span class="nf">largers</span> <span class="nv">alon</span> <span class="nv">n</span><span class="p">)</span>
<span class="p">(</span><span class="k">cond</span>
<span class="p">((</span><span class="nb">null?</span> <span class="nv">alon</span><span class="p">)</span> <span class="o">'</span><span class="p">())</span>
<span class="p">(</span><span class="k">else</span> <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">></span> <span class="p">(</span><span class="nb">car</span> <span class="nv">alon</span><span class="p">)</span> <span class="nv">n</span><span class="p">)</span>
<span class="p">(</span><span class="nb">cons</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">alon</span><span class="p">)</span> <span class="p">(</span><span class="nf">largers</span> <span class="p">(</span><span class="nb">cdr</span> <span class="nv">alon</span><span class="p">)</span> <span class="nv">n</span><span class="p">))</span>
<span class="p">(</span><span class="nf">largers</span> <span class="p">(</span><span class="nb">cdr</span> <span class="nv">alon</span><span class="p">)</span> <span class="nv">n</span><span class="p">)))))</span>
<span class="c1">; returns the sub list of numbers from a given list of numbers that are smaller than the given number n </span>
<span class="c1">; [List-of Number] Number -> [List-of Number]</span>
<span class="p">(</span><span class="k">define</span> <span class="p">(</span><span class="nf">smallers</span> <span class="nv">alon</span> <span class="nv">n</span><span class="p">)</span>
<span class="p">(</span><span class="k">cond</span>
<span class="p">((</span><span class="nb">null?</span> <span class="nv">alon</span><span class="p">)</span> <span class="o">'</span><span class="p">())</span>
<span class="p">(</span><span class="k">else</span> <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb"><</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">alon</span><span class="p">)</span> <span class="nv">n</span><span class="p">)</span>
<span class="p">(</span><span class="nb">cons</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">alon</span><span class="p">)</span> <span class="p">(</span><span class="nf">smallers</span> <span class="p">(</span><span class="nb">cdr</span> <span class="nv">alon</span><span class="p">)</span> <span class="nv">n</span><span class="p">))</span>
<span class="p">(</span><span class="nf">smallers</span> <span class="p">(</span><span class="nb">cdr</span> <span class="nv">alon</span><span class="p">)</span> <span class="nv">n</span><span class="p">)))))</span>
</code></pre></div></div>
<p>Now, our function <code class="language-plaintext highlighter-rouge">quick-sort</code> is complete, and we can test it similarly as above. Notice that the helper functions <code class="language-plaintext highlighter-rouge">largers</code> and <code class="language-plaintext highlighter-rouge">smallers</code> still follow the simple template of structural recursion only.</p>
<div class="language-scheme highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">; testing the insert sort function with an example</span>
<span class="p">(</span><span class="nf">quick-sort</span> <span class="o">'</span><span class="p">(</span><span class="nf">72</span> <span class="mi">45</span> <span class="mi">43</span> <span class="mi">29</span> <span class="mi">34</span><span class="p">))</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(29 34 43 45 72)
</code></pre></div></div>
<p>It’s generally always easier to frame a recursive function as structural recursion, rather than to wait for an “AHA” moment to design a generative recursive function. However, sometimes the extra ingenuity can be worth it. For eg., the time completexity of quick sort is <code class="language-plaintext highlighter-rouge">O(n * log n)</code> (appending the list of <code class="language-plaintext highlighter-rouge">smallers</code>, <code class="language-plaintext highlighter-rouge">pivot</code> and <code class="language-plaintext highlighter-rouge">largers</code>, which is <code class="language-plaintext highlighter-rouge">O(n)</code>, exactly <code class="language-plaintext highlighter-rouge">log</code><sub>2</sub><code class="language-plaintext highlighter-rouge"> n</code> times). This is much better than our simple insertion sort function, <code class="language-plaintext highlighter-rouge">O(n * n)</code> (the <code class="language-plaintext highlighter-rouge">insert</code> function <code class="language-plaintext highlighter-rouge">O(n)</code> is called <code class="language-plaintext highlighter-rouge">n</code> times).</p>
<p>If you find the field of functional programming interesting, I would encourage you to check out the excellent books <a href="https://sarabander.github.io/sicp/html/index.xhtml#SEC_Contents">Structure & Interpretation of Computer Programs or SICP</a> or <a href="https://htdp.org/2020-5-6/Book/index.html#%28part._htdp2e%29">HtDP</a>. The <a href="https://www.youtube.com/playlist?list=PLE18841CABEA24090">Youtube lectures</a> from MIT by the authors of the SICP are also a great learning resource. I’ve written a couple other blog posts on functional programming in Lisp dialects, which you might wanna check out <a href="https://pritesh-shrivastava.github.io/tags/lisp">here</a>.</p>Pritesh ShrivastavaLooking at the design recipes for 2 common sorting algorithms in SchemeYou are never going to be an expert in data science2021-05-25T00:00:00+05:302021-05-25T00:00:00+05:30http://pritesh-shrivastava.github.io/blog/2021/05/25/learn-ds-10-yrs<p>I’m so glad that data science is not the “hottest” job anymore.
Thank you blockchain and cryptocurrencies!</p>
<p>In the past couple of years, we’ve seen hundreds, if not thousands, of training academies prop up in the ed-tech space claiming to teach you data science in 2 weeks / 2 months / 6 months. Because of the high demand from students and beginner data scientists, these businesses have been booming so far but they’ve also setup unreal expectations for their students.</p>
<p>I’ve been working in this field for about 5 years now, and I would consider myself far from being an expert. But don’t take my word for it. Listen to Francois Chollet, the creator of on of the most popular DL libraries, Keras -</p>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">I don't consider myself a deep learning expert by any means. There are still a lot more things I don't know than things I know (it's not even close). I've only been working with neural networks since 2009, which is a lot less than many of you.</p>— François Chollet (@fchollet) <a href="https://twitter.com/fchollet/status/1386369978220253190?ref_src=twsrc%5Etfw">April 25, 2021</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<blockquote class="twitter-tweet" data-conversation="none"><p lang="en" dir="ltr">Besides, I'm not sure that "deep learning experts" exist. People with the highest h-index can't write a GPU kernel or design a DL ASIC. Nor could they win a Kaggle competition. Nor, for the most part, write reusable code (which is really the core of DL).</p>— François Chollet (@fchollet) <a href="https://twitter.com/fchollet/status/1386370113809522690?ref_src=twsrc%5Etfw">April 25, 2021</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<blockquote class="twitter-tweet" data-conversation="none"><p lang="en" dir="ltr">Not only that, but when I chat with experts, I'm often surprised by how few of them seem to have a clear mental model of what DL is and how it works. In fact, many big-name researchers often say things that are manifestly untrue and easy to disprove!</p>— François Chollet (@fchollet) <a href="https://twitter.com/fchollet/status/1386370359016890370?ref_src=twsrc%5Etfw">April 25, 2021</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<blockquote class="twitter-tweet" data-conversation="none"><p lang="en" dir="ltr">If someone tells you they're a top expert, a pioneer, the main thing they're an expert at is playing status games. The same people will probably also try to demean those they feel are in competition with them, because that's how status games work.</p>— François Chollet (@fchollet) <a href="https://twitter.com/fchollet/status/1386371194870398976?ref_src=twsrc%5Etfw">April 25, 2021</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>Peter Norvig, who works as the Director of Research at Google, wrote a beautiful essay titled <a href="https://norvig.com/21-days.html">Teach Yourself Programming in 10 Years</a>. Data science is no exception.</p>
<p>This philosophy is what some people call the “craftsman” mindset. Such kind of roles or careers are best suited to people who enjoy doing <a href="https://www.amazon.com/Deep-Work-Focused-Success-Distracted/dp/1455586692">“deep work”</a>. I must also admit that such flow states arising from deep work are few and far between.</p>
<p>With time, I hope this hype around AI settles down, and both job seekers AND employers have a more clear expectation about the data scientist roles. As for me, I’ve enjoyed working in this space for the most part. There is still so much I WANT to learn, and then some more, that I NEED to learn. This was also a major motivating factor for me to start writing this blog. Something that will push me to share what I’m learning regularly, something that I will continue to do in the next few years.</p>Pritesh ShrivastavaDon't teach yourself data science in 10 days, but in 10 yearsTips and Tricks that helped me find a new job2021-03-29T00:00:00+05:302021-03-29T00:00:00+05:30http://pritesh-shrivastava.github.io/blog/2021/03/29/tips-job-search<p>A few weeks back, I moved to my dream company Microsoft as a Senior Data Scientist in the cybersecurity domain. Apart from this job offer, I also got multiple other great offers from top tech companies in the OTT, travel and e-commerce sectors. To me, this was a bit surprising as my previous job searches never had such a great response. So, what changed this time around? Here’s a small list of things I tried to do differently and that might help anyone else right now as well -</p>
<h3 id="beating-the-ats">Beating the ATS</h3>
<p>Resumes are not read by humans anymore, especially not in the initial screening round. Most top companies use a tool called Applicant Tracking System which maps the candidates resume and measures its similarity with the given job description. So instead of making a standard resume that you then forward to 100s of companies, try and optimize the % match score for the roles that you really like. Websites like <a href="https://resumeworded.com/">resumeworded.com</a> do a great job in this regard. I was able to improve my resume scores from low 40s to high 70s by interchanging or adding keywords in my resume targeted towards my top 4-5 companies and roles.</p>
<p>What tools you use to make your resume, ie, Word, Latex or some other creative design tool doesn’t really matter as long as your resume can be read easily by an ATS. I personally preferred Latex as it gave me the opportunity to learn an interesting software while working on a mundane job like resume building. As for the length of your resume, the thumb rule is that if you have more than 5 yrs of work ex, use a 2 page resume, else stick to 1 page.</p>
<h3 id="dont-waste-time-creating-your-profiles-on-workday--taleo--other-recruiting-platforms">Don’t waste time creating your profiles on Workday / Taleo / other recruiting platforms</h3>
<p>Now, that you have created a targeted resume, your first instinct is to apply to as many companies and profiles as possible, right ? Wrong!</p>
<p>Do not apply to any profile direclty on a company portal. Infact, that should be your last option. Even with a highly targeted resume, you will still face competition for 100s, if not 1000s, of similarly qualified candidates. Your best bet is to get a referral from someone in that company. As soul crushing as this fact sounds, it’s true. Referred candidates get a MUCH higher response rate compared to any other similarly qualified candidate in the job market.</p>
<p>I personally feel that the whole process of referrals feels a lot like gate keeping. Referrals just help ensure you only end up referring candidates from your own school or past employer or social group, but that’s the hard reality of hiring processes everywhere.</p>
<p>As I did not have a good network of friends or past coworkers in the data science or ML space, so I had to resolve to the next best option.</p>
<h3 id="leverage-social-media">Leverage social media</h3>
<p>Get LinkedIn Premium. Buy more InMails if you need.
Create a well crafted 8-10 lines of cover letter for LinkedIn messages.
And then reach out to hiring managers directly on their LinkedIn. Maybe only 10-20% of the hiring managers will reply to your messages, but that is still a HUGE improvement over applying direclty on the companies job portal (~4-5% response rate). Plus, the hiring manager will appreciate your initiative and might give you some helpful recommendations to improve your application.</p>
<p>In the long run, your industry connections with people on LinkedIn, Github or Twitter might help you in more ways than just your job search. For me, it helped me reconnect with old colleages, meet interesting people, work on interesting side projects and learn about great oppurtunities I would have never known without these social media platforms.</p>
<p>Beyond all this, I think one must not underplay the role of luck as well. Due to the ongoing COVID situation, all kinds of interviews were being held remotely and this led to hirng managers be less choosy about the candidates who were living in a different city or state right now. For candiates, this gave them the opportunity to give multiple telephonic / video call interviews in a day for different companies without the need to travel anywhere. The remote working situation has opened up the competition geographically and also helps level the playing feild by giving more opportunities to candidates who would have been less preferred earlier due to logistical reasons. Also, giving interviews remotely from the comfort of your own home can help reduce the anxiety or stress factors as well during the interview process.</p>
<p>That’s all for now! Feel free to add more useful job search hacks in the comments section below that helped you in some way. If you are currently looking out for a job in the data science / ML space, you might find this post on SQL useful as well :</p>
<ul>
<li><a href="https://pritesh-shrivastava.github.io/blog/2021/01/29/how-much-sql-for-ds">How much SQL should one know for data science job roles</a></li>
</ul>Pritesh ShrivastavaSome valuable lessons I learnt in my recent job search experienceA lookback at what I was studying as a beginner data scientist2021-02-19T00:00:00+05:302021-02-19T00:00:00+05:30http://pritesh-shrivastava.github.io/blog/2021/02/19/review-4-yr-old-courses<p>If you search online, you’ll find 1000s of listicles like “Your Data Science Roadmap in 2021”, but “data science” in its current sense is a very vast field, and no one ever knows everything. And you’re NOT even expected to know everything. There is no 1 size fits all kind of a checklist or a roadmap that everyone needs to follow to become a “data scientist” (the term itself is so vague that I’m pretty sure it’ll disappear in a few years time and evolve into specialized roles like ML Engineer, DL Engineer, MLOps, etc). In this post, I just want to talk about the things I tried in my initial couple of years as a data scientist, what worked for me & what didn’t.</p>
<p>Since my data science first job was at a startup where I worked with a fairly small team, I had to figure out my learnig path on my own. Mostly, I was trying to learn more about the tools that I was using at my workplace. A major focus of my projects was to deliver insights to our customers, both internal and external. This meant building lots of dashboards and interactive web apps. Now I know “GUI is for wimps”, but if, like me, you come from a non CS background, tools like Tableau make it very easy for you to productionize your analysis and distribute it easily with your team without much coding efforts.</p>
<ul>
<li><a href="https://www.coursera.org/specializations/data-visualization">Data Visualization with Tableau</a> - The course was good, but more importantly, they also give you 2 Tableau Desktop licenses for a period of 6 months once you enroll in the course!</li>
</ul>
<p>I did realize very soon that proprietary softwares like Tableau have many limitations but most importantly, they are also very costly. Although it’s pretty quick to build the MVP of a dashboard on Tableau, mainitaining it over a long time frame is very costly and inefficient. I had to quickly switch to either Python or R. Unfortunately, my beginning with Python was not that great.</p>
<ul>
<li>
<p><a href="https://learning.edx.org/course/course-v1:Microsoft+DAT208x+3T2018/home">Introduction to Python for Data Science</a> - It was an okayish course but for some reason, I found learning R much easier than learning Python as a beginner. And so, I decided to build web apps in R using the high level Shiny framework.</p>
</li>
<li>
<p><a href="https://www.coursera.org/specializations/jhu-data-science">JHU’s Data Science specialization</a> - Although I did not complete the entire 10 course specialization, I really liked the instruction style of professors Brian Caffo, Jeff Leak and Roger Peng. I also ended up reading a couple of their e-books like Executive Data Sceince and Developing Data Products in R. In hindsight, I’ve found that <a href="https://r4ds.had.co.nz/">R for Data Science</a> by Hadley Wickham is the best book for a beginner if he / she is interested in R, but ofcourse, I discovered this book much later!</p>
</li>
</ul>
<p>For machine learning, Prof Andrew Ng’s Machine Learning and Deep Learning courses were very popular back then and I did start working through them as well, but I also wanted to learn about deploying ML models on the cloud, especially GCP, I found the followging course to be fairly practical and useful:</p>
<ul>
<li><a href="https://www.coursera.org/specializations/machine-learning-tensorflow-gcp">ML with Tensorflow on GCP</a> - I started this course back then but it took me over a year to finish the 5 course specialization.</li>
</ul>
<p>I also wanted to learn more about databases since I spent a significant writing ETL queries. I did the following couple of courses and they were okay but I wouln’t recommend them to anyone now.</p>
<ul>
<li><a href="https://www.coursera.org/learn/introduction-mongodb">Intro to MongoDB</a></li>
<li><a href="https://www.coursera.org/learn/sql-data-science">SQL for Data Science</a></li>
</ul>
<p>I also tried some very forgettable courses on LinkedIn Learning (Lynda, back then) and Udemy. I never really liked these platforms because they usually just had a playlist of videos, 2-4 hours duration with little or no exercises. It was also around this time that I started using Kaggle properly, moved from the default Novice tier to the Contributor tier by getting involved in Discussions, publishing Notebooks and entering some competitions.</p>
<p>So as you can see, it was mostly very introductory level stuff. Some courses were good, some not so much. I wouln’t recommend the above set of courses to anyone. Everyone is working on different applications, different technology stacks and over very different time frames. So you dont need to have a FOMO about THAT book / course everyone keeps talking about! Just try to learn about what you actually NEED in your (current / future) day-to-day job, the small things which can give you some immediate short term value. Because these small things always add up:</p>
<blockquote class="twitter-tweet" data-conversation="none" data-theme="dark"><p lang="en" dir="ltr">Play iterated games. All the returns in life, whether in wealth, relationships, or knowledge, come from compound interest.</p>— Naval (@naval) <a href="https://twitter.com/naval/status/1002103908947263488?ref_src=twsrc%5Etfw">May 31, 2018</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>Pritesh ShrivastavaAnd why you don't need another 'How to become a data scientist in 2021' listicleHow matrices transform space2021-02-09T00:00:00+05:302021-02-09T00:00:00+05:30http://pritesh-shrivastava.github.io/blog/2021/02/09/matrix-transformation<h2 id="matrices-are-objects-that-operate-on-vectors">Matrices are objects that operate on vectors</h2>
<p>When we mulitply a matrix with an n-dimensional vector, it essentially transforms the vector in n-dimensional space!
This wonderful video by 3 Blue 1 Brown expplains this concept through beautiful visualizations - <a href="https://youtu.be/kYB8IZa5AuE">YouTube link</a></p>
<p>We can take a 2x2 matrix A to consider how it will transform the 2-D space using Python.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="n">np</span>
<span class="o">%</span><span class="n">matplotlib</span> <span class="n">inline</span>
<span class="kn">from</span> <span class="nn">matplotlib</span> <span class="kn">import</span> <span class="n">pyplot</span>
</code></pre></div></div>
<p>We’ll also need a helper script to plot gridlines in a 2-D space, which we can import from the Github repo of this awesome <a href="https://github.com/engineersCode/EngComp4_landlinear">MOOC</a>.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">## Source : https://github.com/engineersCode/EngComp4_landlinear
</span><span class="kn">from</span> <span class="nn">urllib.request</span> <span class="kn">import</span> <span class="n">urlretrieve</span>
<span class="n">URL</span> <span class="o">=</span> <span class="s">'https://go.gwu.edu/engcomp4plot'</span>
<span class="n">urlretrieve</span><span class="p">(</span><span class="n">URL</span><span class="p">,</span> <span class="s">'plot_helper.py'</span><span class="p">)</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>('plot_helper.py', <http.client.HTTPMessage at 0x7fc7a1c3f0d0>)
</code></pre></div></div>
<p>Importing functions (<code class="language-plaintext highlighter-rouge">plot_vector</code>, <code class="language-plaintext highlighter-rouge">plot_linear_transformation</code>, <code class="language-plaintext highlighter-rouge">plot_linear_transformations</code>) from the helper script</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">plot_helper</span> <span class="kn">import</span> <span class="o">*</span>
</code></pre></div></div>
<p>Now, let’s take an example of a 2x2 matrix A.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">A</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">array</span><span class="p">([[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">],</span>
<span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">]])</span>
</code></pre></div></div>
<p>Let’s just start with the basis vectors, <code class="language-plaintext highlighter-rouge">i_hat</code> and <code class="language-plaintext highlighter-rouge">j_hat</code> in 2-D coordinate system, and see how matrix multiplication transforms these 2 basis vectors.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">i_hat</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">array</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">])</span>
<span class="n">j_hat</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">array</span><span class="p">([</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">])</span>
</code></pre></div></div>
<p>How does the matrix A transform <code class="language-plaintext highlighter-rouge">i_hat</code> via multiplication ?</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">A</span> <span class="o">@</span> <span class="n">i_hat</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>array([ 3, -2])
</code></pre></div></div>
<p>This is just the 1st column of matrix A.</p>
<p>How does the matrix A transform <code class="language-plaintext highlighter-rouge">j_hat</code>?</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">A</span> <span class="o">@</span> <span class="n">j_hat</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>array([2, 1])
</code></pre></div></div>
<p>Similary, multiplication of A with <code class="language-plaintext highlighter-rouge">j_hat</code> just gives the second column of matrix A.</p>
<p>So the columns a matrix, in fact, just give us the location of where our original basis vectors will land.
Here’s a screenshot of the above 3B1B video that shows how we can understand this 2-D transformation by simply looking at the columns of the matrix A.</p>
<p><img src="/assets/images/matrices-as-linear-transformations-of-space_files/Screenshot_3b1b.png" alt="ss" /></p>
<p>Using our helper script, we can better understand this transformation by looking at the gridlines of our 2-D space before and after transformation.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">plot_linear_transformation</span><span class="p">(</span><span class="n">A</span><span class="p">)</span>
</code></pre></div></div>
<p><img src="/assets/images/matrices-as-linear-transformations-of-space_files/matrices-as-linear-transformations-of-space_13_0.png" alt="png" /></p>
<p>Let’s look at another example using another 2x2 matrix M and see how M transforms the 2-D space!</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">M</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">array</span><span class="p">([[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">]])</span>
<span class="n">plot_linear_transformation</span><span class="p">(</span><span class="n">M</span><span class="p">)</span>
</code></pre></div></div>
<p><img src="/assets/images/matrices-as-linear-transformations-of-space_files/matrices-as-linear-transformations-of-space_14_0.png" alt="png" /></p>
<p>This also reminds us why “linear algebra” is called “linear”, because A) the origin does not move and B) the gridlines remain parallel straight lines after transformation!</p>
<p>We can now start looking at matrices as not just a collection of numbers in row / column format, but as objects that we can use to transform space the way we want it. And we just need to look at the columns a matrix to understnad where the original basis vectors will land after the transformation!</p>
<p>Here’s another example with the matrix N.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">N</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">array</span><span class="p">([[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],[</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">]])</span>
<span class="n">plot_linear_transformation</span><span class="p">(</span><span class="n">N</span><span class="p">)</span>
</code></pre></div></div>
<p><img src="/assets/images/matrices-as-linear-transformations-of-space_files/matrices-as-linear-transformations-of-space_15_0.png" alt="png" /></p>
<h2 id="special-matrices">Special matrices</h2>
<p>Now, let’s look at the some special kinds of matrices. We can rotate the 2-D space by 90 degrees counter clockwise by just rotating the original basis vectors in that direction.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">rotation</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">array</span><span class="p">([[</span><span class="mi">0</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">]])</span>
<span class="n">plot_linear_transformation</span><span class="p">(</span><span class="n">rotation</span><span class="p">)</span>
</code></pre></div></div>
<p><img src="/assets/images/matrices-as-linear-transformations-of-space_files/matrices-as-linear-transformations-of-space_16_0.png" alt="png" /></p>
<p>We can even shear the 2-D space by designing our transformation matrix accordingly.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">shear</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">array</span><span class="p">([[</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">],</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">]])</span>
<span class="n">plot_linear_transformation</span><span class="p">(</span><span class="n">shear</span><span class="p">)</span>
</code></pre></div></div>
<p><img src="/assets/images/matrices-as-linear-transformations-of-space_files/matrices-as-linear-transformations-of-space_17_0.png" alt="png" /></p>
<p>We can scale the X-axis by 2x and Y-axis by 0.5x using the below matrix.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">scale</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">array</span><span class="p">([[</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">],</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mf">0.5</span><span class="p">]])</span>
<span class="n">plot_linear_transformation</span><span class="p">(</span><span class="n">scale</span><span class="p">)</span>
</code></pre></div></div>
<p><img src="/assets/images/matrices-as-linear-transformations-of-space_files/matrices-as-linear-transformations-of-space_18_0.png" alt="png" /></p>
<p>Interestingly, we can compose multiple transformations of 2-D space by mulitplying our transformation matrices together.
So, applying the above shear and rotation transformations will be the same when done sequentially OR just using the product of the 2 matrices as one single transformation.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">plot_linear_transformation</span><span class="p">(</span><span class="n">shear</span><span class="o">@</span><span class="n">rotation</span><span class="p">)</span>
</code></pre></div></div>
<p><img src="/assets/images/matrices-as-linear-transformations-of-space_files/matrices-as-linear-transformations-of-space_19_0.png" alt="png" /></p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">plot_linear_transformations</span><span class="p">(</span><span class="n">rotation</span><span class="p">,</span> <span class="n">shear</span><span class="p">)</span>
</code></pre></div></div>
<p><img src="/assets/images/matrices-as-linear-transformations-of-space_files/matrices-as-linear-transformations-of-space_20_0.png" alt="png" /></p>
<p>However, the order of these transformations is important as matrix multiplication is not commutative!</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">plot_linear_transformations</span><span class="p">(</span><span class="n">shear</span><span class="p">,</span> <span class="n">rotation</span><span class="p">)</span>
</code></pre></div></div>
<p><img src="/assets/images/matrices-as-linear-transformations-of-space_files/matrices-as-linear-transformations-of-space_21_0.png" alt="png" /></p>
<p>This concept of space transformation also gives a new meaning to a matrix inverse. The inverse of a matrix simply reverses the transformation of space to its original state.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">M</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">array</span><span class="p">([[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">]])</span>
<span class="n">M_inv</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">linalg</span><span class="p">.</span><span class="n">inv</span><span class="p">(</span><span class="n">M</span><span class="p">)</span>
<span class="n">plot_linear_transformations</span><span class="p">(</span><span class="n">M</span><span class="p">,</span> <span class="n">M_inv</span><span class="p">)</span>
</code></pre></div></div>
<p><img src="/assets/images/matrices-as-linear-transformations-of-space_files/matrices-as-linear-transformations-of-space_22_0.png" alt="png" /></p>
<p>Degenerate matrices will reduce the dimension of the space. For eg, the below matrix D reduces the 2-D space into a 1-D line!</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">D</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">array</span><span class="p">([[</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mf">0.5</span><span class="p">]])</span>
<span class="n">plot_linear_transformation</span><span class="p">(</span><span class="n">D</span><span class="p">)</span>
</code></pre></div></div>
<p><img src="/assets/images/matrices-as-linear-transformations-of-space_files/matrices-as-linear-transformations-of-space_24_0.png" alt="png" /></p>
<h2 id="applications-in-image-processing">Applications in Image Processing</h2>
<p>So where can we use this concept of matrix vector multiplication other than in thinking about abstract spaces ?
One very important application of this concept can be see in image processing applications. We can consider an image to be a collection of vectors. Let’s consider grayscale images for simplicity, then a grayscale image basically is just a collection of vectors in 2-D space (location of grayscale pixels can be considered a 2-D vector). And we can multiply each pixel vector with a given matrix to transform the entire image!</p>
<p>Let’s import necessary libraries for image manipulation and downloading sample images from the web.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">PIL</span> <span class="kn">import</span> <span class="n">Image</span>
<span class="kn">import</span> <span class="nn">requests</span>
<span class="c1">## Sample image URL
</span><span class="n">url</span> <span class="o">=</span> <span class="s">'https://images.pexels.com/photos/2850833/pexels-photo-2850833.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940'</span>
</code></pre></div></div>
<p>Let’s look at our sample image!</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">im</span> <span class="o">=</span> <span class="n">Image</span><span class="p">.</span><span class="nb">open</span><span class="p">(</span><span class="n">requests</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">stream</span><span class="o">=</span><span class="bp">True</span><span class="p">).</span><span class="n">raw</span><span class="p">)</span>
<span class="n">plt</span><span class="p">.</span><span class="n">imshow</span><span class="p">(</span><span class="n">im</span><span class="p">)</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><matplotlib.image.AxesImage at 0x7fa0e20d8910>
</code></pre></div></div>
<p><img src="/assets/images/linear-transformations-of-images-with-matrices_files/linear-transformations-of-images-with-matrices_2_1.png" alt="png" /></p>
<p>We will convert this image to grayscale format using the Pillow library.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">im</span> <span class="o">=</span> <span class="n">im</span><span class="p">.</span><span class="n">convert</span><span class="p">(</span><span class="s">'LA'</span><span class="p">)</span>
<span class="n">im</span>
</code></pre></div></div>
<p><img src="/assets/images/linear-transformations-of-images-with-matrices_files/linear-transformations-of-images-with-matrices_3_0.png" alt="png" /></p>
<p>Let’s first check the dimensions of our image.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">b</span><span class="p">,</span> <span class="n">h</span> <span class="o">=</span> <span class="n">im</span><span class="p">.</span><span class="n">size</span>
<span class="n">b</span><span class="p">,</span> <span class="n">h</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(1300, 1300)
</code></pre></div></div>
<p>Now, we define a function that will multiply each pixel (2-D vector) of our image with a given matrix.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">linear_transform</span><span class="p">(</span><span class="n">trans_mat</span><span class="p">,</span> <span class="n">b_new</span> <span class="o">=</span> <span class="n">b</span><span class="p">,</span> <span class="n">h_new</span> <span class="o">=</span> <span class="n">h</span><span class="p">):</span>
<span class="s">'''
Effectively mulitplying each pixel vector by the transformation matrix
PIL uses a tuple of 1st 2 rows of the inverse matrix
'''</span>
<span class="n">Tinv</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">linalg</span><span class="p">.</span><span class="n">inv</span><span class="p">(</span><span class="n">trans_mat</span><span class="p">)</span>
<span class="n">Tinvtuple</span> <span class="o">=</span> <span class="p">(</span><span class="n">Tinv</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">],</span><span class="n">Tinv</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">],</span> <span class="n">Tinv</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">2</span><span class="p">],</span> <span class="n">Tinv</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">],</span><span class="n">Tinv</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">],</span><span class="n">Tinv</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">])</span>
<span class="k">return</span> <span class="n">im</span><span class="p">.</span><span class="n">transform</span><span class="p">((</span><span class="nb">int</span><span class="p">(</span><span class="n">b_new</span><span class="p">),</span> <span class="nb">int</span><span class="p">(</span><span class="n">h_new</span><span class="p">)),</span> <span class="n">Image</span><span class="p">.</span><span class="n">AFFINE</span><span class="p">,</span> <span class="n">Tinvtuple</span><span class="p">,</span> <span class="n">resample</span><span class="o">=</span><span class="n">Image</span><span class="p">.</span><span class="n">BILINEAR</span><span class="p">)</span>
</code></pre></div></div>
<p>Now let’s try scaling our image, 0.25x for X-axis and 0.5x for Y-axis. So our transformation matrix should look like ([0.25, 0], [0, 0.5]). However the Pillow library uses 3x3 matrices rather than a 2x2 matrix. So we can just add the third basis vector to our image without any transformation on it, ie, <code class="language-plaintext highlighter-rouge">k_hat</code>.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">T</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">matrix</span><span class="p">([[</span><span class="mi">1</span><span class="o">/</span><span class="mi">4</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="o">/</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">]])</span>
<span class="n">trans</span> <span class="o">=</span> <span class="n">linear_transform</span><span class="p">(</span><span class="n">T</span><span class="p">,</span> <span class="n">b</span><span class="o">/</span><span class="mi">4</span><span class="p">,</span> <span class="n">h</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span>
<span class="n">trans</span>
</code></pre></div></div>
<p><img src="/assets/images/linear-transformations-of-images-with-matrices_files/linear-transformations-of-images-with-matrices_8_0.png" alt="png" /></p>
<p>We can rotate our image by 45 degrees counter clockwise using the below matrix.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">mat_rotate</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="o">/</span> <span class="n">np</span><span class="p">.</span><span class="n">sqrt</span><span class="p">(</span><span class="mi">2</span><span class="p">))</span> <span class="o">*</span> \
<span class="n">np</span><span class="p">.</span><span class="n">matrix</span><span class="p">([[</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">np</span><span class="p">.</span><span class="n">sqrt</span><span class="p">(</span><span class="mi">2</span><span class="p">)]])</span>
<span class="n">trans</span> <span class="o">=</span> <span class="n">linear_transform</span><span class="p">(</span><span class="n">mat_rotate</span><span class="p">)</span>
<span class="n">trans</span>
</code></pre></div></div>
<p><img src="/assets/images/linear-transformations-of-images-with-matrices_files/linear-transformations-of-images-with-matrices_10_0.png" alt="png" /></p>
<p>After rotation, some pixels move out of our Matplotlib axes frame so we end with a cropped image.
We can also combine the scaling and rotation transformations together by using the product of the 2 transformation matrices!</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="n">T</span> <span class="o">=</span> <span class="n">mat_rotate</span> <span class="o">@</span> <span class="n">np</span><span class="p">.</span><span class="n">matrix</span><span class="p">(</span>
<span class="p">[[</span><span class="mi">1</span><span class="o">/</span><span class="mi">4</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="o">/</span><span class="mi">4</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span>
<span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">]])</span>
<span class="n">linear_transform</span><span class="p">(</span><span class="n">T</span><span class="p">,</span> <span class="n">b</span><span class="o">/</span><span class="mi">4</span><span class="p">,</span> <span class="n">h</span><span class="o">/</span><span class="mi">4</span><span class="p">)</span>
</code></pre></div></div>
<p><img src="/assets/images/linear-transformations-of-images-with-matrices_files/linear-transformations-of-images-with-matrices_11_0.png" alt="png" /></p>
<p>I found this idea of matrix vector multiplication very insightful and it’s a pity I never learnt matrix multiplication this was in school or college. If only my school textbooks explained what matrix multiplication actually does rather than just memorizing the formula in a mechanical fashion, I would have really enjoyed learning linear algebra!</p>
<p>If you’re interested to go deep into this topic, I would urge you to check out the YouTube playlist, <a href="https://www.youtube.com/playlist?list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab">Essence of Linear Algebra</a>, from 3Blue1Brown. There is also a free MOOC from the George Washington University <a href="https://openedx.seas.gwu.edu/courses/course-v1:GW+EngComp4+2019/about">here</a> and paid one on Coursera available <a href="https://www.coursera.org/learn/linear-algebra-machine-learning">here</a>.</p>
<p>This blog post is written on Jupyter notebooks hosted on Kaggle <a href="https://www.kaggle.com/priteshshrivastava/matrices-as-linear-transformations-of-space">here</a> and <a href="https://www.kaggle.com/priteshshrivastava/linear-transformations-of-images-with-matrices">here</a>.</p>Pritesh ShrivastavaAn intuitive way to look at matrix vector multiplication, with applications in image processingHow much should one know in SQL for data science2021-01-29T00:00:00+05:302021-01-29T00:00:00+05:30http://pritesh-shrivastava.github.io/blog/2021/01/29/how-much-sql-for-ds<p>Do data scientists need to be experts at SQL?
Not quite. I’d say that an intermediate level of SQL knowledge is good enough and I’ll explain what this “intermediate” level is in more detail below.</p>
<p>For our typical “small” datasets, ie, data that fits into your computer’s memory, I’ve found <code class="language-plaintext highlighter-rouge">dplyr</code> to be much more efficient and practical for data manipulation. If you’re working on Python, <code class="language-plaintext highlighter-rouge">pandas</code> does a pretty good job at data manipulation there as well. So for all kinds of filters, joins or aggregations, SQL is usually the 3rd best alternative.</p>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">import pandas as better_sql </p>
— Chris Albon (@chrisalbon) <a href="https://twitter.com/chrisalbon/status/1319349424145924096?ref_src=twsrc%5Etfw">October 22, 2020</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>When we talk about “big data” applications, <code class="language-plaintext highlighter-rouge">Apache Spark</code> has really made things pretty easy now. You can run queries on distributed systems in a more expressive manner using <code class="language-plaintext highlighter-rouge">sparklyr</code> or <code class="language-plaintext highlighter-rouge">pyspark</code> depending on your programming language. You can even code natively in <code class="language-plaintext highlighter-rouge">Scala</code> for Spark related applications for better flexibility and performance.</p>
<p>So the only area where SQL really seems to be irreplaceable is data extraction (and ofcourse, data definition), ie, working directly with the databases. And most data science interview questions at Tech firms usually involve atleast 1 SQL based problem in their initial coding round of interview to setup a minimum baseline. Yes, you can always have better tools to write your data manipulation queries but you should still be able to work with good old SQL to pull data from a real world database.</p>
<p>In addition to the introductory SQL clauses (WHERE, GROUP BY, ORDER BY, HAVING, etc.), I’ve seen that if you understand JOINs, UNIONs and <a href="https://www.kaggle.com/alexisbcook/analytic-functions">analytic functions</a> in SQL, you should be good enough to solve most problems thrown at you during interviews or in your day-to-day job. Out of these topics, JOINs and analytic functions seem to be the most popular interview topics. Unlike aggregate functions like SUM or MAX which return a single value, analytic functions operate OVER sets of rows & can return sets of rows using PARTITION BY, ORDER BY or window frame clauses.</p>
<p>The best resource I’ve found online that covers these topics well is this course on Kaggle - <a href="https://www.kaggle.com/learn/advanced-sql">Advanced SQL</a>. If you feel a bit rusty with SQL syntax, you can try their <a href="https://www.kaggle.com/learn/intro-to-sql">introductory SQL</a> coure as well. They’re fairly short, hands on and most of all, free!</p>
<p>Again, this is based on my personal experience so far. If you feel I’m missing some important topics in the above list or have a different opinion, let me know in the comments below. I’ll be talking about another common topic featuring in data science interviews at big tech firms, data structures and algorithms, soon.</p>Pritesh ShrivastavaMost tech firm interviews include SQL problems for DS roles, so how should you prepare for them?Matrix algebra operations using recursion2020-12-24T00:00:00+05:302020-12-24T00:00:00+05:30http://pritesh-shrivastava.github.io/blog/2020/12/24/matrix_algebra_recursion<p>This post is inspired by a couple of <a href="https://sarabander.github.io/sicp/html/2_002e2.xhtml#Exercise-2_002e37">exercises</a> from the classical book, <a href="https://sarabander.github.io/sicp/html/index.xhtml">SICP</a>. I found them pretty interesting as they were just using recursion & some common list operations to multiply matrices !! I also wanted to try out the Jupyter notebook kernel for <a href="https://github.com/joeltg/mit-scheme-kernel">MIT Scheme</a>.</p>
<h4 id="representation--problem-statement">Representation & Problem Statement</h4>
<p>Suppose we represent vectors v = ( v<sub>i</sub> ) as sequences of numbers, and matrices m = ( m<sub>ij</sub> ) as sequences of vectors (the rows of the matrix). For example, the matrix</p>
<div align="center">
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
</tr>
<tr>
<td>9</td>
<td>10</td>
<td>11</td>
<td>12</td>
</tr>
</table>
</div>
<p>is represented as the sequence <code class="language-plaintext highlighter-rouge">((1 2 3 4) (5 6 7 8) (9 10 11 12))</code>. With this representation, we can use sequence operations to concisely express the basic matrix and vector operations.</p>
<p>We will look at the following 4 basic operations on matrices:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">(dot-product v w)</code> returns the sum ∑<sub>i</sub> = v<sub>i</sub> w<sub>i</sub></li>
<li><code class="language-plaintext highlighter-rouge">(matrix-*-vector m v)</code> returns the vector <code class="language-plaintext highlighter-rouge">t</code> , where t<sub>i</sub> = ∑<sub>j</sub> m<sub>ij</sub> v<sub>j</sub></li>
<li><code class="language-plaintext highlighter-rouge">(transpose m)</code> returns the matrix <code class="language-plaintext highlighter-rouge">n</code> , where n<sub>ij</sub> = m<sub>ji</sub></li>
<li><code class="language-plaintext highlighter-rouge">(matrix-*-matrix m n)</code> returns the matrix <code class="language-plaintext highlighter-rouge">p</code> , where p<sub>ij</sub> = ∑<sub>k</sub> m<sub>ik</sub> n<sub>kj</sub></li>
</ul>
<p>Dot product of 2 vectors in this notation can be done by using 2 higher order functions, <code class="language-plaintext highlighter-rouge">map</code> and <code class="language-plaintext highlighter-rouge">fold</code>, both of which are implemented using recursion.</p>
<p>Implementation of <code class="language-plaintext highlighter-rouge">map</code>:</p>
<div class="language-scheme highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">define</span> <span class="p">(</span><span class="nb">map</span> <span class="nv">proc</span> <span class="nv">items</span><span class="p">)</span>
<span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">null?</span> <span class="nv">items</span><span class="p">)</span>
<span class="nv">nil</span>
<span class="p">(</span><span class="nb">cons</span> <span class="p">(</span><span class="nf">proc</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">items</span><span class="p">))</span>
<span class="p">(</span><span class="nb">map</span> <span class="nv">proc</span> <span class="p">(</span><span class="nb">cdr</span> <span class="nv">items</span><span class="p">)))))</span>
</code></pre></div></div>
<p>Implementation of <code class="language-plaintext highlighter-rouge">fold-right</code>:</p>
<div class="language-scheme highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">define</span> <span class="p">(</span><span class="nf">fold-right</span> <span class="nv">op</span> <span class="nv">initial</span> <span class="nv">sequence</span><span class="p">)</span>
<span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">null?</span> <span class="nv">sequence</span><span class="p">)</span>
<span class="nv">initial</span>
<span class="p">(</span><span class="nf">op</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">sequence</span><span class="p">)</span>
<span class="p">(</span><span class="nf">fold-right</span> <span class="nv">op</span> <span class="nv">initial</span> <span class="p">(</span><span class="nb">cdr</span> <span class="nv">sequence</span><span class="p">)))))</span>
</code></pre></div></div>
<p>We can use either <code class="language-plaintext highlighter-rouge">fold-left</code> or <code class="language-plaintext highlighter-rouge">fold-right</code> for <code class="language-plaintext highlighter-rouge">dot-product</code>.</p>
<div class="language-scheme highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; Define dot product of 2 vectors of equal length</span>
<span class="p">(</span><span class="k">define</span> <span class="p">(</span><span class="nf">dot-product</span> <span class="nv">v</span> <span class="nv">w</span><span class="p">)</span>
<span class="p">(</span><span class="nf">fold-right</span> <span class="nv">+</span> <span class="mi">0</span> <span class="p">(</span><span class="nb">map</span> <span class="nv">*</span> <span class="nv">v</span> <span class="nv">w</span><span class="p">))</span>
<span class="p">)</span>
<span class="c1">;; testing our function</span>
<span class="p">(</span><span class="k">define</span> <span class="nv">vec1</span> <span class="p">(</span><span class="nb">list</span> <span class="mi">1</span> <span class="mi">2</span> <span class="mi">3</span><span class="p">)</span> <span class="p">)</span>
<span class="p">(</span><span class="k">define</span> <span class="nv">vec2</span> <span class="p">(</span><span class="nb">list</span> <span class="mi">1</span> <span class="mi">1</span> <span class="mi">1</span><span class="p">)</span> <span class="p">)</span>
<span class="p">(</span><span class="nf">dot-product</span> <span class="nv">vec1</span> <span class="nv">vec2</span><span class="p">)</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>6
</code></pre></div></div>
<p>Calculating a dot product was really easy with a couple of higher order functions!
Let’s work with matrices now. We will now right a function to multiply a matrix and a vector:</p>
<div class="language-scheme highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">define</span> <span class="p">(</span><span class="nf">matrix-*-vector</span> <span class="nv">m</span> <span class="nv">v</span><span class="p">)</span>
<span class="p">(</span><span class="nb">map</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nf">m-row</span><span class="p">)(</span><span class="nf">dot-product</span> <span class="nv">m-row</span> <span class="nv">v</span><span class="p">)</span> <span class="p">)</span>
<span class="nv">m</span><span class="p">)</span>
<span class="p">)</span>
<span class="c1">;; testing the function</span>
<span class="p">(</span><span class="k">define</span> <span class="nv">mat1</span> <span class="p">(</span><span class="nb">list</span> <span class="p">(</span><span class="nb">list</span> <span class="mi">1</span> <span class="mi">0</span> <span class="mi">0</span><span class="p">)</span> <span class="p">(</span><span class="nb">list</span> <span class="mi">0</span> <span class="mi">1</span> <span class="mi">0</span><span class="p">)</span> <span class="p">(</span><span class="nb">list</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">1</span><span class="p">)))</span>
<span class="p">(</span><span class="nf">matrix-*-vector</span> <span class="nv">mat1</span> <span class="nv">vec1</span><span class="p">)</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(1 2 3)
</code></pre></div></div>
<p>Let’s look at transpose now! For this, we will need to implement a helper function, <code class="language-plaintext highlighter-rouge">accumulate-n</code>, which is similar to <code class="language-plaintext highlighter-rouge">fold</code> except that it takes as its third argument a sequence of sequences, which are all assumed to have the same number of elements.</p>
<div class="language-scheme highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; Defining helper functions for transpose to </span>
<span class="c1">;; apply the operation op to combine all the first elements of the sequences,</span>
<span class="c1">;; all the second elements of the sequences, and so on, </span>
<span class="c1">;; and returns a sequence of the results. </span>
<span class="p">(</span><span class="k">define</span> <span class="p">(</span><span class="nf">accumulate-n</span> <span class="nv">op</span> <span class="nv">init</span> <span class="nv">seqs</span><span class="p">)</span>
<span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">null?</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">seqs</span><span class="p">))</span>
<span class="o">'</span><span class="p">()</span>
<span class="p">(</span><span class="nb">cons</span> <span class="p">(</span><span class="nf">fold-right</span> <span class="nv">op</span> <span class="nv">init</span> <span class="p">(</span><span class="nb">map</span> <span class="nv">car</span> <span class="nv">seqs</span><span class="p">))</span>
<span class="p">(</span><span class="nf">accumulate-n</span> <span class="nv">op</span> <span class="nv">init</span> <span class="p">(</span><span class="nb">map</span> <span class="nv">cdr</span> <span class="nv">seqs</span><span class="p">))</span>
<span class="p">)</span>
<span class="p">)</span>
<span class="p">)</span>
<span class="p">(</span><span class="k">define</span> <span class="p">(</span><span class="nf">transpose</span> <span class="nv">mat</span><span class="p">)</span>
<span class="p">(</span><span class="nf">accumulate-n</span> <span class="nv">cons</span> <span class="o">'</span><span class="p">()</span> <span class="nv">mat</span><span class="p">)</span>
<span class="p">)</span>
<span class="c1">;; testing transpose</span>
<span class="p">(</span><span class="k">define</span> <span class="nv">mat2</span> <span class="p">(</span><span class="nb">list</span> <span class="p">(</span><span class="nb">list</span> <span class="mi">1</span> <span class="mi">2</span> <span class="mi">3</span><span class="p">)</span> <span class="p">(</span><span class="nb">list</span> <span class="mi">4</span> <span class="mi">5</span> <span class="mi">6</span><span class="p">)</span> <span class="p">(</span><span class="nb">list</span> <span class="mi">7</span> <span class="mi">8</span> <span class="mi">9</span><span class="p">)))</span>
<span class="p">(</span><span class="nf">transpose</span> <span class="nv">mat2</span><span class="p">)</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>((1 4 7) (2 5 8) (3 6 9))
</code></pre></div></div>
<p>Now, let’s use this transpose function to do matrix multiplication:</p>
<div class="language-scheme highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">; Matrix multiplication</span>
<span class="p">(</span><span class="k">define</span> <span class="p">(</span><span class="nf">matrix-*-matrix</span> <span class="nv">m</span> <span class="nv">n</span><span class="p">)</span>
<span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nf">n-cols</span> <span class="p">(</span><span class="nf">transpose</span> <span class="nv">n</span><span class="p">)))</span>
<span class="p">(</span><span class="nb">map</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nf">m-row</span><span class="p">)(</span><span class="nf">matrix-*-vector</span> <span class="nv">n-cols</span> <span class="nv">m-row</span><span class="p">))</span>
<span class="nv">m</span><span class="p">)</span>
<span class="p">)</span>
<span class="p">)</span>
<span class="c1">;; For testing</span>
<span class="p">(</span><span class="nf">matrix-*-matrix</span> <span class="nv">mat2</span> <span class="nv">mat1</span><span class="p">)</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>((1 2 3) (4 5 6) (7 8 9))
</code></pre></div></div>
<p>We can even write recursive procedures to create some special kinds of matrices, for eg, an identity matrix. Here is a recursive procudure to create an identity matrix of length <code class="language-plaintext highlighter-rouge">n</code>:</p>
<div class="language-scheme highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; Create an identity matrix of length n</span>
<span class="c1">; N -> [List-of [List-of N]]</span>
<span class="p">(</span><span class="k">define</span> <span class="p">(</span><span class="nf">identityM</span> <span class="nv">n</span><span class="p">)</span>
<span class="p">(</span><span class="k">letrec</span> <span class="c1">;; Documentation for letrec : https://groups.csail.mit.edu/mac/ftpdir/scheme-7.4/doc-html/scheme_3.html</span>
<span class="p">(</span>
<span class="c1">;; N -> [List-of [List-of N]]</span>
<span class="p">(</span><span class="nf">generate-matrix</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nf">row</span><span class="p">)</span>
<span class="p">(</span><span class="k">cond</span>
<span class="p">((</span><span class="nb">=</span> <span class="nv">row</span> <span class="mi">0</span><span class="p">)</span> <span class="o">'</span><span class="p">())</span>
<span class="p">(</span><span class="k">else</span> <span class="p">(</span><span class="nb">cons</span> <span class="p">(</span><span class="nf">generate-row</span> <span class="nv">row</span> <span class="nv">n</span><span class="p">)</span>
<span class="p">(</span><span class="nf">generate-matrix</span> <span class="p">(</span><span class="nb">-</span> <span class="nv">row</span> <span class="mi">1</span><span class="p">)))))))</span>
<span class="c1">;; N N -> [List-of N]</span>
<span class="p">(</span><span class="nf">generate-row</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nf">row</span> <span class="nv">col</span><span class="p">)</span>
<span class="c1">;; col goes from column n to 0</span>
<span class="p">(</span><span class="k">cond</span>
<span class="p">((</span><span class="nb">=</span> <span class="nv">col</span> <span class="mi">0</span><span class="p">)</span> <span class="o">'</span><span class="p">())</span>
<span class="p">(</span><span class="k">else</span> <span class="p">(</span><span class="nb">cons</span> <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">=</span> <span class="nv">row</span> <span class="nv">col</span><span class="p">)</span> <span class="mi">1</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">(</span><span class="nf">generate-row</span> <span class="nv">row</span> <span class="p">(</span><span class="nb">-</span> <span class="nv">col</span> <span class="mi">1</span><span class="p">)))))))</span>
<span class="p">)</span>
<span class="p">(</span><span class="nf">generate-matrix</span> <span class="nv">n</span><span class="p">)</span>
<span class="p">)</span>
<span class="p">)</span>
<span class="p">(</span><span class="nf">identityM</span> <span class="mi">3</span><span class="p">)</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>((1 0 0) (0 1 0) (0 0 1))
</code></pre></div></div>
<p>If you found these functions interesting, I’de definitely encourage to go read SICP. I wrote about why I’m reading SICP <a href="https://pritesh-shrivastava.github.io/blog/2020/08/30/sicp-so-far">here</a>.</p>Pritesh ShrivastavaImplementing basic matrix algebra operations in Scheme using a Jupyter notebook