Author Archives: sunapi386

On planning for the future

Growing up, I looked up to a lot of heroes for motivation, and Steve Jobs is one such inspirational hero for me. He was influential to a lot of the values I hold true today. I had read his autobiography – multiple times – and I think it is one of the best books I've read. I wish I had been able to be join Apple while he was still around, to work with him, and experience the reality distortion field™ in person.

Most of the conversation I have with my friends and family would generally contain topics of what my ideas are, and how I plan to achieve them. They are interest in what my values are, how I make decisions. Usually I end up paraphrasing things that I've before, to others.

I want to summarize some of the principles I hold, as best as I could. Hopefully I don't forget too much.


On What You Should Do

In the FB post, I talked about two principles (that help decide what you should do).

  1. Do the things that inspire you, that you love, and
  2. try to be really good at it, hopefully having commitment and courage to do it.

Let me elaborate on this, and then talk about some additional principles for how to get you to the goals you want.

Firstly, by doing the things that inspire you and that you love, this results in personal satisfaction. It's very important, because it keeps you motivated for when the problems get tough – and there are going to be a lot of tough problems.

Anything worth doing is going to be difficult.

Of course, the assumption is that these things that you do are going to be creating value; whether it be for yourself or others. Just don't use this as an excuse for binge playing video games, or binge watching Netflix.

Secondly, trying to be really good at it is important for you to create something of value. It's important to have both breadth and depth – and being good at something gives you depth, a competitive edge over others.

Sure, there may be others that are smarter than you. But they have only 24 hours in a day, just as you do. So that places a limit on what others can possibly do, during their spare time. You don't have to be the smartest to have a competitive edge – it's sufficient to excel at skill, albeit seemingly small.

Commitment and courage are other necessary conditions to developing the skill necessary. You should already have the motivation and desire to pursuit something you like doing; whether it be solving a problem or becoming really good in a skill.

The second point complements the first.

These two principles are just about sufficient to be a guide on how to decide what to do, what your next target is, but not how to get there.

On How To Get There

Now that the objectives have been set, what determines the success of it is how to get there.

  1. Manage your free time. We all have 24 hours, how that time is spent that really matters.
    • Identify things that you should invest your time in, in order to reap the fruits of your labor.
    • But also balance life and work. Allocate your most valuable resource, your time, well – with significant others, working out, even video games. The important concept is moderation. For example, watching a season of Netflix is probably no use to getting to your goal.
  2. Read more. Non-fiction. On topics that immediately relevant to you.
    • The value of information depends on context. If I told you what the stock price of some company would be in the future, that would be very valuable; on the other hand, stock price in the past is less valuable.
    • Knowledge is key. Sharing knowledge is also key. Don't forget about your peers.
    • Reading can give you a head start, often what your peers cannot obtain. Compared to others, you are making more informed decisions, better strategies and tactics. Against competition, even the smallest leverage or advantage makes a difference.
  3. Build projects. Develop your skills.
    • But don't work in isolation. Get feedback to improve faster.
    • Success and failure doesn't matter as much; there are things to be learnt even within failures.
  4. Network with others, build your connections.
    • The brain's neurons work with others to achieve a common goal. A single neuron can't achieve much on its own. As I said earlier, anything worth doing is going to be difficult. And difficult things need more resources to be tackled.
    • In machine learning, a neural network is inspired by the neuron architecture. When you learn, you are making new connections; and when you practice, you are strengthening the connections.
    • A strong network makes you better informed, helps you get relevant information quicker, creates more opportunities.
  5. Start today, rather than tomorrow.
    • Why is today such a good place to start? Starting today gives you a head start than starting tomorrow. And since you didn't start yesterday, then today is the optimal day.
    • Take a small step, begin by just doing a little. Great accomplishments don't happen overnight. Great Wall of China wasn't built in a day.

That's all for now folks. Thanks for reading!


I'm writing this while at the Starbucks on El Camino Real near my house, and coffee's power is fading. I will try to contribute and share knowledge more often.

If you found this blog to be useful, let me know! My email is and Facebook is – feel free to contact me.

Music: Driftmoon.

How I met Sophie

This is a tale about how I met my Sophie. Happy Valentine, Sophie! 情人节快乐!

In February 2016, I spent the first two weeks travelling in China and celebrating Chinese New Year. Having family across the world felt great, and I could visit them any time. China is in an economic boom, and growing very fast. It felt good to be connected to other parts of the world. I had recently graduated university and moved to the Bay Area for just about 3 months. I still felt there was a lot of travelling I could do, to explore the world. But travel is costly, from the time and financial perspective. Is there is another way?

Becoming a hosting on

From December to end of March, I was renting the master bedroom in a two bedroom apartment. Since our apartment had two couches, I felt I could make use of them to use it to host some couchsurfers and make friends from all over the world. So I subscribed to the couchsurfing email newsletter.

One day while scanning through my email of couchsurfers looking for hosts, Sophie's profile photo caught my eye. She was very pretty. Her profile described herself as a high level headhunter, ambitious, eager, and interested in startups.

I offered to host her on the first day she lands in US. But she replied with moderate interest, and describing an overly ambitious schedule of visiting too many cities.

Unfortunately, she had found a host already, but she was willing to meeting up for coffee. We met on Sunday Feb. 21, 2016.

That Friday and Saturday, I was hosting my first couchsurfer, Satoshi, from Japan. His profile described him as an aspiring entrepreneur visiting SV. I was hosting him, my friend Shaon was looking to buy a house. While we drove around, I was messaging Sophie to see when and where she can meet up with us.

Meeting my 2nd couchsurfer

At the end, we settled for meeting at my home, and both Sophie and her host met my friend Shaon and Satoshi.

When I first saw her, I had two impressions: "oh my goodness she is beautiful, cuter than her profile photo" and followed by "oh she's shorter than I thought".

After getting acquainted, we all went on a spontaneous trip to see Half Moon Bay and try to catch sunset. I briefly chatted with Sophie in the backseat, before doing the driving myself.

Returning, we went to visit Facebook, which was a fun place and suitable for visitors. Apple had no such open door policy. Sophie and I chatted some more about who we were.

Taking silly photos at Instagram HQ

Taking silly photos at Instagram HQ

Towards the end of our visit at Facebook, I had made a good impression with Sophie. She had changed her mind about not staying over and asked her couchsurfer whether it was okay to stay with me. Of course it was.

First impressions

We chatted late into the night. And as I closed my eyes, I knew I liked her. A lot. I was so excited that I woke up at 5 am to blog. And then after I was done, I woke her up to chat.

We had talked and next thing I know, it was morning. I still had to work, but I decided to take half day off to get up later, show Sophie around my office, then drop her off at Stanford University. And I missed her immediately.

Date #1: Las Vegas

Immediately after dropping her off, I convinced and coordinated with her so I can come to Las Vegas and travel together. Below is a cute video taken at Hoover Dam. I had rented a yellow Camaro. I had always wanted to drive a yellow sports car!

After this trip, Sophie had returned to China. We decided to try long-distance dating, and we did video calling consistently, about 3 times a day, 30 minutes each time.

Date #2: Hawaii

After a while, we wanted to meet up again. My family wanted to do a big vacation, and we settled on going to Hawaii. I invited Sophie to meet with my family.

After the trip to Hawaii, we still continued to do long-distance, and we meet up again. This time I wanted to meet her parents. So I visited China.

Date #3: Shanghai

Being with Sophie in China is like being a tourist. Although I had gone to Shanghai before, having Sophie show me around is a completely different experience.

I had remembered to take some videos this time. (I didn't have videos from Hawaii trip. Shame.)

We are now progressing well.

Ember rails developer


Since April this year, I essentially transitioned from an application developer to a web developer. Full stack.  It's quite exciting! There are some who perceive web development as an inferior choice of work, but I have to disagree. In an era where mom and pop shops have websites, not having a webpage front for your business essentially means you don't exist. Because having a webpage allows you to reach a greater audience. So, I see it as a very powerful leverage.

I have a little background developing for Ruby on Rails, from my Dotabuff scraper project. Now that I look at it, my understanding of rails is fairly incomplete. Rails, and Ember alike, are scaffolding heavy. The intuition is that as the creators of the web framework, they are more knowledgable about how you should go about designing the architecture than you are. Consequently, it means transitioning from one Ember/Rails project to another means very little time is required.

What is Rails/Ember

Rails is a complete web framework. It handles the entire web pipeline. From

  1. routing a URI,
  2. to finding the controller for the page,
  3. who translates the URI to some requests on the data model and accessing the database,
  4. to finally rendering the web page template.

Rails 5 (which should come out of beta this year) has an API-only mode. That means it doesn't template web pages (no step #4). Rather, it replies with the data directly in JSON format.

Ember is like Rails, but it's designed to handle the frontend, leaving the backend architecture up to the user. It means the focus of this framework is on rendering web page template. Any dynamic data that needs to be displayed gets translated to an API call to go fetch the data. Then it converts the response into an ember-data model, and finally fills in the template to display it.

Why make it more complicated by using yet another framework just for the frontend?

So at this point, you're probably wondering why the additional complexity? Why not just use Rails since it supports the entire process?

Well, you see, it's about speed and responsivenessEvery time you visit a different web page on Rails, an entire html file is rendered for you by the Rails server and sent to you. 

Think about that. What does it mean? It means it's slow. Unresponsive.

Rendering pages cost time. Sending the rendered page across the network also cost time. The larger the rendered file size, the longer it takes. And this is not cheap, you notice the web page flashing when you visit different pages.

So that begs the question of how do we avoid sending out rendered pages from the server? Rendering could be done on the client, rather by the server. This is where frontend frameworks come in. Rather than requesting entire web pages all the time, just request the data the page needs as an API call, and render it on the client. In between visiting different pages, data that was available before is put into client's local storage, for faster access via the cache.

Frontend frameworks

Ember is one of three popular frameworks. It's also the most complete framework, as in the most to learn. In terms of scaffolding and complexity, they rank like this:

  1. Ember. The framework for ambitious projects.
  2. Angular. Somewhere in-between.
  3. React. So lightweight, it can hardly be considered a framework.

Any of these would be fine. Indeed, as with any beginner, I did some digging. And discovered that the bigger I dig, the more mess I got myself into. As a rule of thumb, I certainly knew I had no clue what I'm doing with a frontend framework. So if I'm to learn a frontend framework, I might as well learn from what are the best practices, the most scaffolding frameworks. For the same reasons why I prefer Rails as well.

My project

Currently I am building an internal project for Apple, and I (obviously) can't disclose what it is. But it uses Ember and Rails 5 API-only mode.

I setup both Ember and Rails to use web-sockets, but not really hooking them up at the moment, because I'm working on getting out a functional demo website. When the time comes, this website will not only be responsive, but updates in real-time.

See you at my next blog post folks!

Migrating copying blog from QQ Qzone to WordPress

Recently I made a website for Sophie ( and scraped her blog from QQ's QZone.
QQ has an API that can be used for QZone, but it is hard to develop for. Mainly the API is poorly documented and hard to use for a native English speaker. Although I could read Chinese (slowly), reading professional terms is something I have to work on.

Workflow screenshots

Anyhow, I decided to practice javascript and manually scrape it. Here are the steps I took:

Screen Shot 2016-04-03 at 18.43.17

This is what the QZone page looks like.

Screen Shot 2016-04-03 at 18.45.12

This is running the fetching script.

Screen Shot 2016-04-03 at 18.44.22

After running the fetching script, it all of the blog links as individual iframes onto the page. Because these loads are network requests, I manually wait until all of them are loaded. The javascript console will stop scrolling and printing things if they've all completely loaded.

Screen Shot 2016-04-03 at 18.45.31

Here are all the frames after being loaded. Then I run the scraper javascript, and it scrapes the iframe for their blog content and post them to the current screen.

Screen Shot 2016-04-03 at 18.45.28

I manually copy paste them into csv files.

Screen Shot 2016-04-03 at 18.46.21

This is the first line of a csv entry.

Screen Shot 2016-04-03 at 18.46.40

Then I wrote a ruby script to add these csv to a wordpress blog.

Screen Shot 2016-04-03 at 18.48.05

Here's what running it looks like.

Screen Shot 2016-04-03 at 18.48.43

Source code

Run the fetcher.js on the blog page.


// fetcher.js
// Javascript to paste into chrome console to fetch the posts.

var ul = document.createElement("UL") // Create a <ul> node
ul.setAttribute("id", "myList")
var s = "|^@^|"; // seperator
var iframesArray = [];
var messagesArray = [];
var posts = document.getElementById("tblog").contentWindow.document.getElementById("listArea").getElementsByTagName("li")
for (var i = 0; i < posts.length /**/; i++) {
 var postTitle = posts[i].getElementsByClassName("article")[0].textContent;
 var postLink = posts[i].getElementsByClassName("article")[0].getElementsByTagName("a")[0].href
 var entryDate = posts[i].getElementsByClassName("list_op")[0].childNodes[0].textContent;
 var readCount = posts[i].getElementsByClassName("list_op")[0].childNodes[2].textContent;
 var message = i +s+ postTitle +s+ entryDate +s+ readCount +s+ postLink +s;
 var iframe = document.createElement('iframe')
 iframe.src = postLink;

After you manually determine the time to wait, run this to scrape all the iframes and add to the current html. There you can copy paste into a csv file.

// scraper.js
// Execute this when everything seems to have laoded
for (var i = 0; i < iframesArray.length /**/; i++) {
 var contWin = iframesArray[i].contentWindow;
 var win = contWin.document;
 // Scraping
 var blogsection = win.getElementById("tblog").contentWindow.document;
 var postTexts = blogsection.getElementById('blogDetailDiv').children;
 var postString = "";

 // Stupid check because sometimes if there are no childrens.
 if (postTexts.length == 0) {
 postString = blogsection.getElementById('blogDetailDiv').innerHTML;
 else if (postTexts[0].tagName == "BR") {
 var brString = blogsection.getElementById('blogDetailDiv').innerHTML;
 postString = brString; // .replace(/<br>/g, "\n")
 else {
 for (var p = 0; p < postTexts.length; p++) {
 postString += "<p>" + postTexts[p].innerHTML + "\n&nbsp;</p>";

 postString = postString.trim();
 if (postString.length == 0) {
 postString = "ERROR parsing!";

 var message = messagesArray[i] + postString;
 var node = document.createElement("LI") // Create a <li> node
 var textnode = document.createTextNode(message) // Create a text node
 node.appendChild(textnode) // Append the text to <li>
 document.getElementById("myList").appendChild(node) // Append <li> to <ul> with id="myList"
 // document.body.removeChild(iframe)
 // win.body.parentNode.removeChild(win.body)

Once the csv files are created, post it to the wordpress blog.

require 'rubypress'
require "csv"
require 'sanitize'
wp = => "",
 :username => "sophie",
 :password => "1Smoosophie!",
 # :use_ssl => true,
 :retry_timeouts => true)
Dir["*.csv"].each do |name|
 puts "============= #{name} ============="
 csv =, {:col_sep => "|^@^|", :quote_char => "" }) # whatahack 
 csv.each do |row|
 id, title, pubdate, readcount, link, text = row
 cleantext = Sanitize.clean(text, :elements => ['br','p', 'a'])
 # puts("#id #{id}, title #{title}, pubdate #{pubdate}, readcount #{readcount}, link #{link}, text #{text}")
 retries ||= 0
 puts "try ##{ retries }"
 wp.newPost( :blog_id => "0", # 0 unless using WP Multi-Site, then use the blog id
 :content => {
 :post_status => "publish",
 :post_date => Time.parse(pubdate),
 :post_content => cleantext,
 :post_title => title,
 :post_author => 1, # 1 if there only is admin user, otherwise user's id
 :terms_names => {:category => ['QQZone'], :post_tag => ['QQZone'] }
 retry if (retries += 1) < 3


Neural Style

Inspiration comes from
Because installing all the required toolchains on OS X 10.11.3 is a bit challenging, I here are my installation steps.

 cd workspace/
 git clone
 git clone ~/torch --recursive
 cd ~/torch; bash install-deps;

This will fail a few times if you have already installed them (but different versions). I needed fiddle around unlinking things.

 brew unlink qt
 brew linkapps qt
 brew link --overwrite wget
 bash install-deps;
 brew unlink cmake
 bash install-deps;
 brew unlink imagemagick
 brew unlink brew-cask
 bash install-deps;

Anyhow, make sure the install-deps script doesn't error out, otherwise you'll be missing dependencies.


This succeeds. It tells you to activate, but I'm using non-standard shell (fish shell), so I mess with the fish config.

 . /Users/jason/torch/install/bin/torch-activate
 th #checking this exists in path, and it doesn't
 luarocks install image
 source ~/.profile
 . ~/.profile
 vim ~/.bashrc
 subl /Users/jason/torch/install/bin/torch-activate
 subl ~/.config/fish/
 th #now it exists

The change into fish.config that was necessary (for my user, my paths) was:

# . /Users/jason/torch/install/bin/torch-activate
set LUA_PATH '/Users/jason/.luarocks/share/lua/5.1/?.lua;/Users/jason/.luarocks/share/lua/5.1/?/init.lua;/Users/jason/torch/install/share/lua/5.1/?.lua;/Users/jason/torch/install/share/lua/5.1/?/init.lua;./?.lua;/Users/jason/torch/install/share/luajit-2.1.0-beta1/?.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua'
set LUA_CPATH '/Users/jason/.luarocks/lib/lua/5.1/?.so;/Users/jason/torch/install/lib/lua/5.1/?.so;./?.so;/usr/local/lib/lua/5.1/?.so;/usr/local/lib/lua/5.1/'
set PATH /Users/jason/torch/install/bin $PATH
set LD_LIBRARY_PATH /Users/jason/torch/install/lib $LD_LIBRARY_PATH
set DYLD_LIBRARY_PATH /Users/jason/torch/install/lib $DYLD_LIBRARY_PATH
set LUA_CPATH '/Users/jason/torch/install/lib/?.dylib;'$LUA_CPATH

Convert the bash syntax to fish syntax by replacing "export" with "set" and ":" with " ".
I have a Nvidia graphics card, so I download and install CUDA.

Cuda Preferences

Then we can continue installing dependencies.

 brew install protobuf
 luarocks install loadcaffe
 luarocks install torch
 luarocks install nn

I found that having Xcode 7 means the clang compiler is too new and not supported by cutorch and cunn. The error you would see is this:

nvcc fatal   : The version ('70002') of the host compiler ('Apple clang') is not supported

Sometimes the error messages are garbled. Concurrency build, I presume. I downloaded Xcode 6.4, and replaced my Xcode 7:

cd /Applications
sudo mv
sudo mv Xcode\ # this is Xcode 6.4 when you install it
sudo xcode-select -s /Applications/
clang -v 
#Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
#Target: x86_64-apple-darwin15.3.0
#Thread model: posix

But now I get another fatal issue:

/usr/local/cuda/include/common_functions.h:65:10: fatal error: 'string.h' file not found

Seems like this is an issue people have, cutorch issue 241. Can be resolved by doing

xcode-select --install

This gets me a little further, now the issue seems related to torch.

make[2]: *** No rule to make target `/Applications/', needed by `lib/THC/libTHC.dylib'.  Stop.
make[2]: *** Waiting for unfinished jobs....
[ 64%] Building C object lib/THC/CMakeFiles/THC.dir/THCGeneral.c.o
[ 69%] Building C object lib/THC/CMakeFiles/THC.dir/THCAllocator.c.o
[ 71%] Building C object lib/THC/CMakeFiles/THC.dir/THCStorage.c.o
[ 76%] Building C object lib/THC/CMakeFiles/THC.dir/THCTensorCopy.c.o
[ 76%] Building C object lib/THC/CMakeFiles/THC.dir/THCStorageCopy.c.o
[ 76%] Building C object lib/THC/CMakeFiles/THC.dir/THCTensor.c.o
/tmp/luarocks_cutorch-scm-1-3748/cutorch/lib/THC/THCGeneral.c:633:7: warning: absolute value function 'abs' given an
      argument of type 'long' but has parameter of type 'int' which may cause truncation of value [-Wabsolute-value]
  if (abs(state->heapDelta) < heapMaxDelta) { ^ /tmp/luarocks_cutorch-scm-1-3748/cutorch/lib/THC/THCGeneral.c:633:7: note: use function 'labs' instead if (abs(state->heapDelta) < heapMaxDelta) {
1 warning generated.
make[1]: *** [lib/THC/CMakeFiles/THC.dir/all] Error 2
make: *** [all] Error 2

Error: Build error: Failed building.

Since I just updated to OS X 10.11, I presume frameworks in 10.10 should be ok. So this hack should be ok as well, to make Accelerate.framework appear.

ln -s "/Applications/" "/Applications/"

Finally I try to install cutorch, with success.

luarocks install cutorch
luarocks install cunn #this installs fine as well, it didn't before

Everything should be good to go. But nothing works smooth.

jason@jmbp15-nvidia ~/w/neural-style (master)> 
th neural_style.lua -style_image IMG_2663.JPG -content_image IMG_2911.JPG 
[libprotobuf WARNING google/protobuf/io/] Reading dangerously large protocol message.  If the message turns out to be larger than 1073741824 bytes, parsing will be halted for security reasons.  To increase the limit (or to disable these warnings), see CodedInputStream::SetTotalBytesLimit() in google/protobuf/io/coded_stream.h.
[libprotobuf WARNING google/protobuf/io/] The total number of bytes read was 574671192
Successfully loaded models/VGG_ILSVRC_19_layers.caffemodel
conv1_1: 64 3 3 3
conv1_2: 64 64 3 3
conv2_1: 128 64 3 3
conv2_2: 128 128 3 3
conv3_1: 256 128 3 3
conv3_2: 256 256 3 3
conv3_3: 256 256 3 3
conv3_4: 256 256 3 3
conv4_1: 512 256 3 3
conv4_2: 512 512 3 3
conv4_3: 512 512 3 3
conv4_4: 512 512 3 3
conv5_1: 512 512 3 3
conv5_2: 512 512 3 3
conv5_3: 512 512 3 3
conv5_4: 512 512 3 3
fc6: 1 1 25088 4096
fc7: 1 1 4096 4096
fc8: 1 1 4096 1000
THCudaCheck FAIL file=/tmp/luarocks_cutorch-scm-1-5715/cutorch/lib/THC/generic/ line=40 error=2 : out of memory
/Users/jason/torch/install/bin/luajit: /Users/jason/torch/install/share/lua/5.1/nn/utils.lua:11: cuda runtime error (2) : out of memory at /tmp/luarocks_cutorch-scm-1-5715/cutorch/lib/THC/generic/
stack traceback:
	[C]: in function 'resize'
	/Users/jason/torch/install/share/lua/5.1/nn/utils.lua:11: in function 'torch_Storage_type'
	/Users/jason/torch/install/share/lua/5.1/nn/utils.lua:57: in function 'recursiveType'
	/Users/jason/torch/install/share/lua/5.1/nn/Module.lua:123: in function 'type'
	/Users/jason/torch/install/share/lua/5.1/nn/utils.lua:45: in function 'recursiveType'
	/Users/jason/torch/install/share/lua/5.1/nn/utils.lua:41: in function 'recursiveType'
	/Users/jason/torch/install/share/lua/5.1/nn/Module.lua:123: in function 'cuda'
	neural_style.lua:76: in function 'main'
	neural_style.lua:500: in main chunk
	[C]: in function 'dofile'
	...ason/torch/install/lib/luarocks/rocks/trepl/scm-1/bin/th:145: in main chunk
	[C]: at 0x0109a0dd50

I guess I ran out of GPU memory? Seems to be an issue here My pictures aren't that small, I guess. I'll just resize them.

jason@jmbp15-nvidia ~/w/neural-style (master)> ls -lh
total 5480
-rw-r--r--@ 1 jason  staff   2.4M 11 Mar 21:39 IMG_2663.JPG
-rw-r--r--@ 1 jason  staff   235K 11 Mar 21:38 IMG_2911.JPG
-rw-r--r--  1 jason  staff   9.1K 11 Mar 20:34
-rw-r--r--  1 jason  staff   1.1K 11 Mar 20:34 LICENSE
-rw-r--r--  1 jason  staff    16K 11 Mar 20:34
drwxr-xr-x  4 jason  staff   136B 11 Mar 20:34 examples
drwxr-xr-x  8 jason  staff   272B 12 Mar 06:24 models
-rw-r--r--  1 jason  staff    16K 11 Mar 20:34 neural_style.lua
jason@jmbp15-nvidia ~/w/neural-style (master)> sips IMG_2663.JPG -Z 680
 [ (kCGColorSpaceDeviceRGB)] ( 0 0 0 1 )
jason@jmbp15-nvidia ~/w/neural-style (master)> sips IMG_2911.JPG  -Z 680
 [ (kCGColorSpaceDeviceRGB)] ( 0 0 0 1 )
jason@jmbp15-nvidia ~/w/neural-style (master)> ls -lh
total 2224
-rw-r--r--  1 jason  staff   105K 12 Mar 06:27 IMG_2663.JPG
-rw-r--r--  1 jason  staff   64K 12 Mar 06:28 IMG_2911.JPG
-rw-r--r--  1 jason  staff   9.1K 11 Mar 20:34
-rw-r--r--  1 jason  staff   1.1K 11 Mar 20:34 LICENSE
-rw-r--r--  1 jason  staff    16K 11 Mar 20:34
drwxr-xr-x  4 jason  staff   136B 11 Mar 20:34 examples
drwxr-xr-x  8 jason  staff   272B 12 Mar 06:24 models
-rw-r--r--  1 jason  staff    16K 11 Mar 20:34 neural_style.lua
jason@jmbp15-nvidia ~/w/neural-style (master)> 

Well resizing didn't work, still runs out of memory. Default `th` uses nn, so I will try using cudnn, but not working.

jason@jmbp15-nvidia ~/w/neural-style (master)> 
th neural_style.lua -style_image IMG_2663.JPG -content_image IMG_2911.JPG  -backend cudnn
/Users/jason/torch/install/bin/luajit: /Users/jason/torch/install/share/lua/5.1/trepl/init.lua:384: /Users/jason/torch/install/share/lua/5.1/trepl/init.lua:384: /Users/jason/torch/install/share/lua/5.1/cudnn/ffi.lua:1279: 'libcudnn (R4) not found in library path.
Please install CuDNN from
Then make sure files named as or libcudnn.4.dylib are placed in your library load path (for example /usr/local/lib , or manually add a path to LD_LIBRARY_PATH)

stack traceback:
	[C]: in function 'error'
	/Users/jason/torch/install/share/lua/5.1/trepl/init.lua:384: in function 'require'
	neural_style.lua:64: in function 'main'
	neural_style.lua:500: in main chunk
	[C]: in function 'dofile'
	...ason/torch/install/lib/luarocks/rocks/trepl/scm-1/bin/th:145: in main chunk
	[C]: at 0x0106769d50

So I go to and download cudnn-7.0-osx-x64-v4.0-prod.tgz and follow their install guide:


    CUDA 7.0 and a GPU of compute capability 3.0 or higher are required.


    Extract the cuDNN archive to a directory of your choice, referred to below as .
    Then follow the platform-specific instructions as follows.



    Add  to your build and link process by adding -I to your compile
    line and -L -lcudnn to your link line.



    Add  to your build and link process by adding -I to your compile
    line and -L -lcudnn to your link line.


    Add  to the PATH environment variable.

    In your Visual Studio project properties, add  to the Include Directories 
    and Library Directories lists and add cudnn.lib to Linker->Input->Additional Dependencies.

Opening the tgz file gives me cuda folder. I just need to add this my path

jason@jmbp15-nvidia ~/workspace> cd cuda/
jason@jmbp15-nvidia ~/w/cuda> set DYLD_LIBRARY_PATH (pwd) $DYLD_LIBRARY_PATH
jason@jmbp15-nvidia ~/w/cuda> echo $DYLD_LIBRARY_PATH
/Users/jason/workspace/cuda /Users/jason/torch/install/lib
jason@jmbp15-nvidia ~/w/cuda [127]> tree 
├── cd
├── include
│   └── cudnn.h
└── lib
    ├── libcudnn.4.dylib
    ├── libcudnn.dylib -> libcudnn.4.dylib
    └── libcudnn_static.a

2 directories, 5 files
jason@jmbp15-nvidia ~/w/cuda> set LD_LIBRARY_PATH (pwd)/lib/ $LD_LIBRARY_PATH
jason@jmbp15-nvidia ~/w/cuda> echo $LD_LIBRARY_PATH
/Users/jason/workspace/cuda/lib/ /Users/jason/torch/install/lib


Recently I hosted two couchsurfers. It has been a very rewarding experience and I think opened me to meeting new people. Couchsurfing is a tool that solves the problem of not meeting enough interesting people. In our day to day grind, it is difficult to meet new friends.

This summarizes my initial experience with hosting couchsurfing guests.

I had two guests. Satoshi and Sophie. Both of these guests I selected for their entrepreneurial drive and could be considered seasoned travellers. I've had a couchsurfing account since 2012 and never done it before. I feared that it would be unsafe. The reason being if as a travelling couchsurfer, not being in your native country and on a time schedule, there is little that you can do if something goes wrong. Every legal due process would take extremely long. I decided to start as a host because I have the option to turn down guests and being in my familiar territory. I thought this would make a good transition into becoming a full fledged couchsurfer. Anyways, I selected these guests based on their profile. I don't just host anyone, but rather only people whom I see have a high chance of being friends. This reduces the safety risk and is a more efficient use of time than hosting random strangers.

Satoshi comes from Tokyo and travels a lot. Currently taking time off from work and school, he has 6 more months left of his undergraduate in business. He's been across a large number of situations such as being homeless. I admire his courage. He's travelled good parts of the world. He's also tried and failed to create a a startup. This tells me he's a safe choice to host and there'll be many commonalities we share. I'd love to make a friend in Tokyo to visit in the future. I learned a lot about Japanese culture and can't wait to actually go experience it one day.

Sophie comes from Shanghai and is taking this trip as a vacation. She is normally working full time in Shanghai and is a headhunter. She has a wonderful cheerful personality that I could best describe as 小燕子 in 还珠格格. Both in looks and personality. I admire her bravery even more than Satoshi because she travels as a single girl, and at her height, she's probably 1.56m. Here I am worrying about whether if it'd safe for me to couchsurf. Silly. I found her to be very driven and goal oriented personality. She has such a lively personality that would be of a great asset to any company. There are a lot of traits to be admired.

This is just the start of the couchsurfing experience for me. I'm sure there are many adventures that await me ahead and can't wait to spend more time meeting interesting people around the world!

Projects I want to work on

Lately, Feb 16 2016, I have had a few projects in mind I want to dig deeper into. I just returned from a trip to China, for Chinese New Year.

  • Family Tree – Document the best to my knowledge who I am from the perspective of who my families were.
  • Violin – A friend of my Father gifted me a violin when I went on trip to China. I intend to start practicing this. Perhaps look into going to local Meetups.
  • Shipping Info - Elementary school friend of my Father runs a shipping company in China. He intends on doing IPO (Initial Public Offering). In order to make the company worth more, he desires to build a ecommerce website so it would be more competitive. I need to explore similar web platforms and provide some references.
  • Make Friends – Since moving to California full time, I have mostly spent time settling down and getting used to the flow. It is as if I was in first year university, going into an environment I'm not comfortable with. It is as if I was in Switzerland, too. Difference here is that there are relatively less networking events.

Computer Science Topics


I've been keeping track a list of interesting articles to read. Right now they are scattered across Google Docs, Pocket, bookmarks, and pdf files I've downloaded. I'll combine them all into this list, without any explicit ordering – although the topics on top should be more interesting. I'll also explain why I have them on my list.

List of projects I want to build

Software Architecture

  • Different GUI architectures.
    • Unlike school assignments, anytime one builds a customer facing product, the user interface needs to be considered. Building the UI is no trivial work, so knowing good design patterns is important. This article provides some fast overview.

Machine Learning

  • Deep Learning for Computer Vision
    • Wouldn't it be cool to feed your computer a video and have it learn about things that appears in it? You can train the computer to do this. GPU technology has advanced quite a bit since its invention during the 90s. It just so happens that neural networks are coming back into popularity. This article blogs about leveraging the two of the best platforms we have today: Matlab and Nvidia cuDNN (cuda Deep Neural Network).
  • Question Answering on a computer
    • This article came around as I was working on a project with my professor for artificial intelligence. Our goal was to try and recommend previously given answers based on a similar sounding question.

How this list came to be

My usual conversations with friends borders somewhat about computer science topics. They are just interesting problems discuss. In particular, I have a few friends who I always strive to learn from, and I admire how they keep talking about these things. I must do my part and keep up.

Why I need this list

Computer science is a wide field, I've only opened the door and had a glimpse into the world. I have a bunch of interesting things I want to build, and I've been keeping them on the back burner for far too long. This list will motivate me by serving as a reminder of just how much of exploration is possible.

Learning Cocoa


Haven't blogged in a while, been caught up with transitions to work from just graduating. Recently I started learning Cocoa for work. I'm not completely new to making apps using frameworks, but still pretty fresh out of school.

I have some experience with Android, so this post will describe my experiences learning Cocoa coming from more Android side.

Cocoa vs Android

I found the whole Cocoa framework to pretty acceptable and usable. That being said, tutorials for OS X Cocoa are pretty non-existent, and iOS is marginally better. So unless you pay to buy books, expect heavy digging. Buying a book from Big Nerd Ranch is probably your best bet. Android is much better to learn as a beginner. And then the transition into Cocoa isn't too bad.

If only Apple spent more resources developing and maintaining a set of tutorials for Cocoa, like Google does for Android, I think Cocoa would become slightly more popular.

Of course, the barrier to entry for Cocoa development is still limited by how costly it is for a setup. You'd need iOS or OS X device, and pay $99 for developer access per year. Where as pretty much any phone can run Android, and it's free to develop.

Cocoa's IDE: Xcode vs AppCode

But being a programmer by trade, I'm a little hesitant of doing any work that involves heavy use of GUIs. And developing for Cocoa you'll almost certainly be using Xcode. The alternative is to use another IDE or use the plain old text editor.

Let's face it. You can't manage this with text editors. Given how some files are structured, like XIB files, it pretty much screams at you to use an IDE.

XIB stands for the XML Interface Builder. Interface Builder is a software application which allows you to develop Graphical User Interface with the help of Cocoa and carbon. The generated files are either stored as NIB or XIB files.

If you're looking at IDEs, the major competitor to Xcode would be AppCode. Now Xcode isn't bad itself, anyone who've ever used JetBrains software knows that Xcode's compiler reasoning is garbage. Definitely AppCode wins here. Not only here, but across the board for compiled language IDEs. Making recommendations is their specialty. Ironically, because AppCode is put so much effort here, it isn't very good for making GUIs like Xcode. Among other things utilities like Instruments (monitoring your app), etc. But keep in mind I have used JetBrains stuff longer than I have Xcode, so I have my biases here.

In short, AppCode for writing code. Xcode for making interfaces, because Interface Builder is king.

Programming Paradigms

Both Android and Cocoa follow similar patterns, mainly MVC. Sometime in the future, I want to learn more about Reactive Programming, rather the observer pattern. But for now, I can't comment much, because I haven't got anything to compare to.


Well a lot more can be said about programming for Cocoa. But that's all the blogging I will do for now. Sleep, and I may come back to this post.

Guest Wifi Setup DD-WRT Tutorial

This is a tutorial for setting up a DD-WRT router to have a separate isolated (virtual) guest wifi access point. At the end of the tutorial you will have two wifi networks, one private, and one public for the guests. Guests will not have access to the router or anything else on your network.

  1. Your build must be ≥ 23020. There should be a network already running and you can access the internet.0 network basic setup
  2. Create the virtual access point for your guests.
    1. Go to Wireless -> Basic Setup
    2. Click Add in Virtual Interfaces. Fill out the details as in the image.1 wireless settings
  3. Optional: Go to Wireless -> Wireless Security, choose your encryption for the guest wifi.
  4. Now enable DHCPD for the guest wifi so IP addresses can be assigned.
    1. Go to Setup->Networking and add another dhcp server for the guest network as shown.2 networking
  5. Optional: Setup Quality of service (QoS) to limit guest network bandwidth.
    1. Configure QoS as shown.3 qos
    2. Results from my speed test.4 speed test
  6. Restart the router. Important because I found sometimes changing settings they take a while to activate and you're not sure if it has had any effect.


Links I found useful.