Programmers don't understand Economics

On the phackers slack #careeradvice channel, a recurring theme seems to be the higher salaries that developers overseas are paid.

It always starts out with a developer -- usually a novice but not always -- discovering that developers in some other country with the same skillset as him are getting paid 5x (or whatever multiple) he is getting here. Other developers will then helpfully remind him of the greater cost-of-living, higher taxes, etc. in those countries. Invariably someone will say that Pinoy developers are worth more than what they're getting now.

Well, here's an important concept that I have had to explain multiple times:

You're worth whatever the market determines you're worth.

People often forget or ignore the fact that it's not just them and the employer that are negotiating. It's other employers, AND other workers. If you're negotiating with company, do you honestly think you're the only candidate they're considering? Other candidates or applicants may have the same skillset as you, but offer to work for a lower salary (for whatever reason). Other workers competing for the same jobs determine what you'll end up getting as well.

The real way to command a higher rate, regardless of whether it's local employment or remote, is to be as @mparaz and @radeinla put it, the special snowflake. If you're a commodity programmer, you get the commodity programmer rate because there are so many other candidates with the same or similar skillset.

He's been out of the job market for a while.

If you have, or can signal that you have a particular set of skills and there is a demand for those skills, then congrats, special snowflake, you can command a higher rate. The more difficult to obtain those skills (or signals) are, and the greater the demand, the better able you will be to command a higher rate whether here or abroad.

Google IO Extended 2017

For developers unable to make it to the annual Google I/O conference, Google holds I/O Extended events in cities around the world. This year Google Developer Group Philippines went all out and held I/O Extended events in five major cities, demonstrating their new APIs and services available to developers.

For the Manila leg, I ran a workshop for Google Cloud Platform's Natural Language API, for an audience of mostly students. In retrospect, NLP is too advanced and specialized field for undergrads or novice developers, unless they have a specific application or are using NLP already.

A number of the students couldn't get past signing up with GCP, which requires a credit card.

In the future, I'll need to be more upfront with the prerequisites and level of experience needed to get the most out of my workshops.

AI and Machine Learning for Software Engineers at Dev Festival

Yesterday morning at Microsoft Philippines, I gave a short talk introducing AI and machine learning to software engineers. Instead of walking through my usual R or Python code, I did a demo using Microsoft's own ML Studio, which was helpful for visualizing the machine learning process.

Most of the Q&A was about the possible impact of AI on jobs, inequality and security/privacy.

Installing kerasR

This is a quick reference to installing kerasR, a slim wrapper around Keras starting with the required Python packages.

Python packages

Create a virtualenv:

$ virtualenv pydata --python=/usr/bin/python3
Running virtualenv with interpreter /usr/bin/python3
Using base prefix '/usr'
New python executable in /home/brian/pydata/bin/python3
Also creating executable in /home/brian/pydata/bin/python
Installing setuptools, pip, wheel...done.
$ source pydata/bin/activate
(pydata) $

Install keras. This will also install the other prerequisites for doing any sort of datasciency stuff in Python (numpy, pandas) as well as Theano. Tensorflow will be installed in the next step.

(pydata) $ pip install keras
Collecting keras
Collecting six (from keras)
Using cached six-1.10.0-py2.py3-none-any.whl
Collecting theano (from keras)
Collecting pyyaml (from keras)
Collecting scipy>=0.14 (from theano->keras)
  Downloading scipy-0.19.0-cp35-cp35m-manylinux1_x86_64.whl (47.9MB)
    100% |████████████████████████████████| 47.9MB 27kB/s
Collecting numpy>=1.9.1 (from theano->keras)
  Downloading numpy-1.13.0-cp35-cp35m-manylinux1_x86_64.whl (16.9MB)
    100% |████████████████████████████████| 16.9MB 66kB/s
Installing collected packages: six, numpy, scipy, theano, pyyaml, keras
Successfully installed keras-2.0.4 numpy-1.13.0 pyyaml-3.12 scipy-0.19.0 six-1.10.0 theano-0.9.0

Install Tensorflow:

(pydata) $ pip install tensorflow


In R, install the kerasR package:

> install.packages("kerasR")
Installing package into ‘/home/brian/R/x86_64-pc-linux-gnu-library/3.4’
** testing if installed package can be loaded
successfully loaded keras
* DONE (kerasR)

This may also install the reticulate package, which is an interface to Python objects and methods.

A guide to using kerasR is provided as a vignette.


If you get an error message when executing library(kerasR) saying:

> library(kerasR)

keras not available
See reticulate::use_python() to set python path,
then use kerasR::keras_init() to retry

this means kerasR (or more specifically, reticulate) can't find the keras python package, you need to start R after loading your virtualenv:

$ source pydata/bin/activate
(pydata) $ R
> library(kerasR)
Using TensorFlow backend.
successfully loaded keras

Philippine Startups Wordcloud

In [2]:
import pandas as pd
from nltk.tokenize import word_tokenize
from nltk.corpus import stopwords
from string import punctuation

I went to the Kickstart and Ideaspace websites and scraped the descriptions of the startups they funded.

And by scraped, I mean I cut-and-paste stuff into a Google Sheets document.

In [3]:
raw = pd.read_csv("../files/Philippine Startups - Sheet1.csv")
In [4]:
descriptions = raw['Long Description']
0    Arthrologic designs and develops a TKA (Total ...
1    ​BluLemons Gaming Studio is an all-Filipino th...
2    Croo enables people to swiftly send informatio...
3    The Company has the opportunity to create the ...
4    Despite current transponder technologies avail...
Name: Long Description, dtype: object
In [5]:
raw_words = word_tokenize(" ".join(descriptions))
In [6]:
stop_words = set(stopwords.words('english') + list(punctuation))

words = [w.lower() for w in raw_words if w.lower() not in stop_words and not w.isdigit() and len(w) > 3]
In [7]:
In [8]:
word_str = " ".join(words)
'arthrologic designs develops total knee arthroplasty system simple evidence-based utilizing successful clinical data improve surgical skills easy-to-use surgeon-friendly instrumentation assure successful predictable results offer competitive cost provide greater majority patients access technology improve living \u200bthe product asian-fit 2-component total knee arthroplasty system definitive surgical treatment severe end-stage osteoarthritic knees \u200bblulemons gaming studio all-filipino theme mobile gaming studio develop games based filipino culture \u200bthey believe creating mobile games great avenue showcase philippines offer globally vision create games impact filipino youth across cultures croo enables people swiftly send information loved ones need arises without typing anything calling anyone button accessory clicked sent predetermined emergency contacts smartphone application text message contains important information person’s current location nearby landmarks person’s contacts equipped '
In [9]:
with open("../files/phstartupwords.txt","w") as f:

Lazy Wordcloud Visualization

Enter the contents of the file generated into, and manually remove the words that occur less than 3 times:

Disabling/Enabling the Asus UX303 Touchscreen in Ubuntu 16.04

Find the Atmel touchscreen device:

$ xinput --list
⎡ Virtual core pointer                        id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                      id=4    [slave  pointer  (2)]
⎜   ↳ FocalTechPS/2 FocalTech FocalTech Touchpad      id=17   [slave  pointer  (2)]
⎜   ↳ Logitech USB Optical Mouse                      id=20   [slave  pointer  (2)]
⎜   ↳ Atmel                                           id=10   [slave  pointer  (2)]
⎣ Virtual core keyboard                       id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard                     id=5    [slave  keyboard (3)]
    ↳ Power Button                                    id=6    [slave  keyboard (3)]
    ↳ Sleep Button                                    id=9    [slave  keyboard (3)]
    ↳ USB2.0 UVC HD Webcam                            id=13   [slave  keyboard (3)]
    ↳ Video Bus                                       id=7    [slave  keyboard (3)]
    ↳ AT Translated Set 2 keyboard                    id=16   [slave  keyboard (3)]
    ↳ Video Bus                                       id=8    [slave  keyboard (3)]
    ↳ Asus WMI hotkeys                                id=15   [slave  keyboard (3)]

The Atmel device is our touchscreen.

Use the xinput disable and enable commands to turn the touchscreen off or on again.:

$ xinput disable Atmel
$ xinput enable Atmel

Both commands are silent, unless you specify a device that doesn't exist.