Exploratory writing

On some rare occasions, I get an idea for a blog post or essay and I instantly recognize the point that I want to make. And how I'm going to go ahead and make that point. After that, getting it written is a fairly easy task. It requires effort but I just need to go with the flow. What happens much more often though, is that I only have a very vague idea of what I might want to write. And because I don't have a clear picture of what I want to produce, I don't get started at all.

Instead, it recently occurred to me that I should start with the vague ideas anyway, hoping that at least some of these ideas will start to take better shape as I begin writing them down. The reason I believe this could work is that trying to put that vague idea down into paper will hopefully force me into thinking about it. This, I think, is not something that I can do effectively inside my head. I've found that trying to write something in my head is difficult- the words just don't hold. Writing can be thought of as "materialized thoughts" so they are more ephemeral and can be better dealt with.

I think the great thing about this exercise is that even if I don't produce a complete piece, I'll have a clearer picture of an initially vague idea. This is definitely something I ought to try.

Doctor Gruntwork

Doctors everywhere in the world get a lot of respect. Society treats them differently- they get a special title, instead of the lousy Mr., Ms. or Mrs. And perhaps more importantly, they get paid well. And why not? After all, they're life-savers.

But if you think about it, what most doctors do is solve problems whose solutions are already known. They do a pretty good job of providing treatment if the disease and the treatment has been dealt with before. And they get dumbfounded when they encounter something new. Not a big surprise. This still requires them to make use of their brains. They need to use their judgement and these could be critical, life-or-death kind of judgements. And doctors do need to have the skills, often surgically precise skills. However, both of these can be taught to computers. The field of machine learning is enabling computers to make intelligent inferences from data. And, needless to say, a lot of people believe that this will eventually enable computers to make precise diagnoses and suggest an optimal course of treatment.

So it looks like what most doctors do right now could be characterized as "grunt work", although admittedly also requiring some brains to go with the grunt. And to their credit, they really do save lives. But I think that reason there is such prestige attached to the medical profession is not that society thinks that what doctors do is more nobler than other occupations but simply that society right now needs doctors to be around. Simple economics, really.

It will probably take a long time for computers and robots to replace doctors, if that time will ever come, but I feel like more doctors and especially would-be doctors need to realize this so that they can stop being all smug about their profession.

Understanding minds with machines

A lot of what we call machine intelligence is really just building statistical models based on data and then checking if new data fits that statistical model. Or other times, creating data based on the model. Let me illustrate with a concept that I find fairly simple: n-gram language modeling. Needless to say, the model being built here is of some language. We'll see how we do this in the paragraphs that follow.

You break a sentence into n-sized "ngrams". For example, the 3-grams(which are ngrams of size 3, also called trigrams) of the previous sentence would be You break a, break a sentence, a sentence into, sentence into n-sized, into n-sized ngrams.

If our entire corpus consisted of only that sentence, then the way we would evaluate the "correctness" of a new sentence, say the sentence is just "You break a sentence.", would be to break the new sentence into trigrams too and then check if each trigram in the new sentence has occurred in the corpus. Note that most correct sentences won't pass this test at all.

Now, with the huge amounts of text available on the Internet, it wouldn't be very hard to imagine that we can get many more ngrams, and thus a better representation of the language. And with this huge amount of ngrams, we will notice that many of these ngrams occur more than once. So we now make the logical move of calculating the frequency of each ngram in our corpus. We then proceed to also calculate the (n-1)gram frequencies. So, if we were initially calculating trigrams, we'll also start counting bigrams(which as you might have guessed are 2-grams).

To evaluate the "correctness score" of a sentence, we will now take each trigram and calculate the probability of the third word in the trigram following the first two words(the bigram):

$$P(\text{a|You break})=\frac{\text{count("You break a")}}{\text{count("You break")}}$$

The score of a sentence is the product of each of these probabilities:

$$P(\text{"You break a sentence"}) = P(\text{a|You break}) \times P(\text{sentence|break a})$$

So here we have a program, which if given a corpus, can tell whether a sentence "looks correct". Of course, this is a very simplified explanation. Making a more accurate and complete model would require us to be mindful of many more nuances.

Now, I'll argue that an analogous process happens in our own minds too. This is how humans recognize a weird sentence. By reading(and listening to) a lot of correct sentences, we have built a "language model" in our mind. Then, when we encounter a strangely formed sentence, we get a feeling that the sentence is wrong. This same model is also used to create sentences. Like this one. What I refer to as "building a language model" is simply our ability to understand the structure and meaning of language.

The big difference here is that our brains probably don't employ probabilistic methods to do this modeling. This is worth thinking about because if we want to move towards building sentient machines then perhaps it would help if we better understood how our own minds work. But this was already obvious- AI researchers started looking into cognitive science right from the start.

The more interesting thing to notice here is that by writing a computer program we were able to understand, or at least make a good attempt at understanding how one of our mental processes works. Which, at least to me, wasn't very obvious from the get-go. When thinking about how to go about understanding our mind, I think it would be more obvious to try "reverse engineering" the brain the same way you could try to understand a computer program by looking at what bits it moves. The alternative way would be to look at and try to understand what it is the software is doing.

I hope I didn't mix up any of the analogies. I just found the idea of simulating mental processes to understand the mind, which I read about in Douglas Hofstadter's I am a Strange Loop, very intriguing. I definitely do not have the expertise in artificial intelligence or cognitive science so please correct me if I made an error or if I said something stupid.

Moving things with Clojurescript and your phone accelerometer

Until recently I had quite naively assumed that smartphone browsers were not be able to access the phone's accelerometer and gyroscope. Well, turns out that you can. You can even get the phone's GPS coordinates(with the user's permission, of course).

In this post, we'll be using a phone accelerometer to control a blob inside a HTML canvas.

Initial setup

Before doing anything else, start a Lein project:

lein new motion-cljs


And setup the project.clj as follows:

(defproject motion-cljs "0.1.0-SNAPSHOT"
:description "Moving things with Clojurescript"
:dependencies [[org.clojure/clojure "1.5.1"]
[prismatic/dommy "0.1.1"]]
:plugins [[lein-cljsbuild "0.3.2"]]
:cljsbuild {:builds
[{:source-paths ["src/accelerometer"]
:compiler {:output-to "resources/public/accelerometer.js"
:optimizations :simple
:pretty-print true}}
{:source-paths ["src/motion"]
:compiler {:output-to "resources/public/motion.js"
:optimizations :simple
:pretty-print true}}]})


As you can see, we have two source paths. We'll be using the first one, accelerometer in the next section to make sure we're able to read the accelerometer data. After that we'll get things moving.

Accessing accelerometer data

First of all, here's how to use Clojurescript to display the accelerometer data in a web page:

(ns accelerometer
(:use-macros [dommy.macros :only [sel1]])
(:require [dommy.core]))

(fn [event]
(let [a (.-accelerationIncludingGravity event)]
(dommy/set-text! (sel1 ".acc-x")
(.-x a))
(dommy/set-text! (sel1 ".acc-y")
(.-y a))
(dommy/set-text! (sel1 ".acc-z")
(.-z a)))))


Here, we add a listener for the devicemotion event. The event will also contain a .-acceleration property(that is, acceleration excluding the effect of gravity). But we'll use the one including gravity in this post.

Compile the Clojurescript file using lein cljsbuild once, then load the compiled Javascript file in a HTML file containing this:

Acc-x: <span class="acc-x"></span></br>
Acc-y: <span class="acc-y"></span></br>
Acc-z: <span class="acc-z"></span></br>


Serve the directory containing the HTML file using:

cd resources/public
python -m SimpleHTTPServer


hostname -i
# should give you something like 192.168.1.15


So now if you visit http://192.168.1.15:8000/accelerometer.html on your mobile device, you should see the accelerometer data.

Motion

Now let's get to actually moving things. We'll use a canvas element of width and height both 300 pixels.

(def width 300)
(def height 300


We'll store the x and y coordinates of our blob in an atom,

(def state (atom {:x (/ width 2)
:y (/ height 2)}))


Our draw function will draw our blob into the x and y coordinates:

(defn draw
[]
(let [canvas (.getElementById js/document "canvas")
ctx (.getContext canvas "2d")
[r g b] [200 0 0]
x (:x @state)
y (:y @state)]
(.clearRect ctx 0 0 width height)
(set! (.-fillStyle ctx)
(str "rgb(" r "," g "," b ")"))
(.fillRect ctx x y 50 50)))


.clearRect above clears the canvas and .fillRect draws a square with length 50px. The .-fillStyle property gives us a red square.

Let's also show the x and y coordinates:

(defn show-coords
[]
(let [x (:x @state)
y (:y @state)]
(dommy/set-text! (sel1 ".x")
(:x @state))
(dommy/set-text! (sel1 ".y")
(:y @state))))


As before let's add our event listener,

(.addEventListener js/window "devicemotion"
(fn [event]
(let [a (.-accelerationIncludingGravity event)]
;;(.log js/console a)
(dommy/set-text! (sel1 ".acc-x")
(.-x a))
(dommy/set-text! (sel1 ".acc-y")
(.-y a))
(swap! state update-in [:x] + (.-x a))
(swap! state update-in [:y] - (.-y a)))))


The interesting thing above are the two swap! blocks. They add the magnitudes of acceleration in the x and y coordinates respectively. This isn't a very good physical model, but this one works fine too so we'll let it pass, okay?

We'll have the canvas re-drawn every 100 milliseconds:

(defn ^:export init
[]
(.setInterval js/window draw 100)
(.setInterval js/window show-coords 100))


Finally, put this into an HTML file:

<html>
<style type="text/css">
canvas { border: 1px solid black; }
</style>
<meta name="viewport" content="width=device-width, initial-scale=1">
<body>

Acc-x: <span class="acc-x"></span></br>
Acc-y: <span class="acc-y"></span></br>

x:  <span class="x"></span></br>
y:  <span class="y"></span></br>

<script type="text/javascript" src="motion.js"></script>

<canvas id="canvas" width="300" height="300">
Your browser does not support HTML5 Canvas.
</canvas>

<script>
motion.init();
</script>
</body>
</html>


As before, open this on your mobile device and you should see a canvas with a square which moves around when you tilt your phone.

Making a streaming API from scraped data using Clojure

I recently found myself having to play around with some stock exchange data. The stock exchange in Nepal, unsurprisingly, doesn't provide a data API so I had to scrape their website. The non-realtime data isn't very interesting, just regular old scraping made a little more tedious by the fact that whoever designed the website didn't know about how to use HTML id attributes.

Now, to the live trading data. For the live data, the website shows a ticker of stock prices, which I think is a really bad representation of the data. If you want to know at what price ZXY was traded at, you have to wait till the end of the ticker. If the ZXY stock was all you were interested in, you'd still have to bear with the rest of the ticker. And to get the actual live data, you have to hit refresh. This is kind of okay on TV, but having to do this on a computer is terrible. Computers are more interactive than TV sets and should be treated as such. Bret Victor has given a great talk titled "Stop Drawing Dead Fish" that conveys this in a much more articulated way. The talk is about art, but I think having data represented on a ticker is like drawing dead fish.

So, I got around to thinking about how to build a better interface for the live trading data. To do that, I first had to build a streaming API which pushes stock prices as the trades happen. And doing that wasn't all that complicated, thanks to clojure.data/diff, watches and http-kit.

The first step is to pull in the page and scrape out the ticker data to get a map of the latest trades for each company like this:

{"ABC" {:price 100
:volume 12}
"FOO" {:price 432
:volume 22}
"BAR" {:price 94
:volume 34}}


I used laser for the scraping- you could use that; Enlive seems to be great too. I won't go into the details of the scraping.

Store this into an atom, lets call this atom current-prices. After, say, 5 seconds when we scrape again, new trades will have happened and the map we get will be different than the one above:

{"ABC" {:price 100
:volume 12}
"FOO" {:price 434 ;; this has changed
:volume 300}
"BAR" {:price 90 ;; this too
:volume 25}}


Since we called our atom current-prices, it would be sensible to reset! it now to hold the second, more recent map of trading data. Its nice that we now have the trading data in a Clojure data structure but note that reset!-ing our atom is really just the equivalent of refreshing our browser- we aren't done yet.

Now, Clojure comes with a handy function called diff which is in the clojure.data namespace. Here's how it works:

(require 'clojure.data)

(clojure.data/diff {:a 42 :b "foo"}
{:a 43 :b "foo"})
;; ({:a 42} {:a 43} {:b "foo"})


The diff function tells how one data structure varies from another. The first map shows the key-value pairs that exist in the first map but not in the second; the second map shows the pairs existent in only the second map. And the third map shows the pairs that exist in both of the maps.

diff works on seqs too, but we won't bother with that right now.

Let's see what we get when we diff the older and newer versions of our current-prices atom:

(clojure.data/diff {"ABC" {:price 100
:volume 12}
"FOO" {:price 432
:volume 22}
"BAR" {:price 94
:volume 34}}

{"ABC" {:price 100
:volume 12}
"FOO" {:price 434 ;; this has changed
:volume 300}
"BAR" {:price 90 ;; this too
:volume 25}})
;; ({"FOO" {:price 432, :volume 22},  "BAR" {:price 94, :volume 34}}
;;  {"FOO" {:price 434, :volume 300}, "BAR" {:price 90, :volume 25}}
;;  {"ABC" {:price 100, :volume 12}})


Great. This is telling us that no trade happened for ABC. For FOO and BAR this is showing the older and newer trading data.

Now, lets add a watch to our current-prices atom, so that whenever we pull in new data, the watch function finds out the stocks for which new trades happened and pushes its prices to the appropriate clients.

(add-watch current-prices :send
(fn [key identity old new]
(let [diff (clojure.data/diff old new)

Every time the current-prices atom is reset! or swap!-ed, the function above gets called.
Here we're simply sending all our clients a string. In practice, you'd probably pass JSON or EDN to only those clients who are interested in a specific company. The send! function is from http-kit which has a unified API for WebSockets, HTTP long polling and streaming. I wrote about using Websockets with http-kit in a previous post.
And that's it. We have now built a streaming API using just a watch function and clojure.data/diff. I think that's pretty cool.