Wednesday, 26 February 2020

The Rise of Canvas and WebAssembly

Before the time of Canvas and WebAssembly there were these kinds of web embeds:
  • ActiveX - C/C++ code, for browsers on Windows only
  • Flash/Flex - ActionScript code, for all platforms
  • Java Applet - Java code, for all platforms
  • Java FX - Java code, for all platforms
  • And some more
Since the introduction of Canvas in HTML5, most of all embeds can be done with 'canvas' tag and JavaScript; browsers JIT-compile JS to native code but no types, so it's slow.

However, for high performance, WebAssembly is, near-native performance. WebAssembly works in its own embed (window). WebAssembly has a drawback: no simple way to access DOM presently.

Solutions to choose:
  • JS/Canvas: Draw UI with something like Zebkit, or raw canvas APIs
  • C++(Emscripten)/Canvas: Draw UI with Qt, or raw OpenGL (browser renders as WebGL)
  • Basically go for these canvases only when complex graphics, or native performance needed.
Compile to WebAssembly with:
  • C/C++: Emscripten (WebGL, Qt, etc.)
  • Python, Rust: Google will tell :)
Hello World in Emscripten:

1) Download
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh

2) Check version
em++ -v

3) Hello World (hello.cpp)
#include <iostream>
using namespace std;
int main(int Argc,char* Args[]){
  cout <<"Hello!" <<endl;
}

4) Build (output files: .wasm, .js, .html)
em++ hello.cpp -o hello.html

5) Config web server
micro /etc/nginx/mime.types
#Add 1 line to types:
application/wasm wasm;

6) Edit /etc/hosts, create .conf file in /etc/nginx/conf.d
127.0.0.1 hello.local

7) Clone hello.html to show canvas only
cp hello.html hello.custom.html

8) Open web browser to http://hello.local/hello.custom.html

Reference:

Monday, 24 February 2020

The Easy Understanding of YAML

YAML compared to JSON is like Python compared to JavaScript. YAML is smarter with tree of nodes instead of opening and closing blocks.

For a parent-child relation, it is read with the parent first in JSON:
  • Starting with { is an object
  • Starting with [ is an array
However, with the same parent-child relation, it is read with the child first in YAML:
  • A node followed by ':' (colon) means the parent is an object
  • A node starts with '- ' (dash and space) means the parent is a list
  • A node starts with '- ' (dash and space) and followed by ':' (colon) means it's starting key of an object and the parent is a list.
  • Indent below an object key to make child object key.
Examples of YAML
Example 1. Root is object
Foo: "value1"
Bar: "value2"

Example 2: Root is list
- "value1"
- "value2"

Example 3: Object (root) of objects
Foo:
  Child1: "value1"
  Child2: "value2"

Example 4: Object (root) of lists
Foo:
  Child1:
  - "value1"
  - "value2"
  Child2:
  - "value3"
  - "value4"

Example 4: List of items
List:
- "value1"
- "value2"

Example 5: List of objects
List:
- Foo: "value1"
  Bar: "value2"
- Foo: "value3"
  Bar: "value4"

Friday, 21 February 2020

Change Jupyter (Not JupyterLab) Terminal Background Colour and Foreground Colour

Jupyter (Classic), not the new JupyterLab has black background terminal. The terminal is a canvas and stuff are drawn inside, CSS won't work. To change the terminal:

1) Install Tampermonkey for browser

2) Go to OpenUserJS.org and create account

3) Add this script:
// ==UserScript==
// @name     localhost:8888
// @include  http://localhost:8888/*
// @run-at   document-start
// @license  MIT
// ==/UserScript==

setTimeout(()=>{
  terminal.term.setOption(
    "theme",
    {background:"#bbbbbb",foreground:"black"}
  );
},3000);
//EOF

Public Tampermonkey script:
https://openuserjs.org/scripts/datdinhquoc/localhost8888

Thursday, 20 February 2020

Work with 2D Array and Floating-point Numbers in Bash

Bash supports only 1D array, however, there's a work-around, for example:

List=("value00 value01" "value10 value11" "value20 value21");

#Example I,J
I=1;
J=1;
Row=(${List[I]}); #Wrap in parentheses
Cell=${Row[J]};

Bash supports only integers, the work-around to do floating-point maths is creating new functions based on something like Perl:

function + {
  perl -e "print($1 + $2)";
}

function - {
  perl -e "print($1 - $2)";
}

function x { #Can't use *, Bash expands * to files
  perl -e "print($1 "'*'" $2)";
}

function / {
  perl -e "print($1 / $2)";
}

function p { #A to power B
  perl -e "print(($1) ** $2)"; #Parentheses for negative values
}

function random {
  printf $(/ $RANDOM 32767);
}

#Examples of using those functions:
echo $(+ $(random) $(random));
echo $(- $(random) $(random));
echo $(x $(random) $(random));
echo $(/ $(random) $(random));
echo $(p $(random) $(random));

Tuesday, 18 February 2020

SSH Port Forwarding for Jupyter without Wasting a Terminal Just to Channel

When launching Jupyter on server, Jupyter generates a token and it is used as access token to the Jupyter notebook.

However, the URL with the generated token is accessed through 'localhost' (at the server), and Google Colab only supports adding 'localhost' at desk machine.

In order to have server-based Jupyter added as run-time to Colab, pipe the port between desk machine and server:

ssh -L 8888:localhost:8888 SOMESERVER

However, the command above will waste a whole terminal just to do port forwarding (port channelling), 2 lines below save a whole terminal :)

#!/bin/bash
sudo pkill -f localhost:8888 & wait $!;
ssh -fNL 8888:localhost:8888 SOMESERVER;
#EOF

The option 'L' is for port forwarding as usual.
The option 'f' is to but the 'ssh' to background.
The option 'N' is a must to go along with option 'f'.

Use Colab with Private Server Instead of Free Run-time Environment

Google Colab by default provides free run-time environment, in order to connect to personal or private servers, do these:
  1. Install jupyterlab on server:
    1. ssh MYSERVER
    2. sudo yum install jupyterlab
  2. Open terminal, create SSH port channelling:
    1. ssh -L 8888:localhost:8888 MYSERVER
    2. Leave this terminal open
  3. Open another terminal, start Jupyter
    1. ssh MYSERVER
    2. jupyter notebook [THIS WON'T WORK]
    3. jupyter notebook like in this guide:
      https://research.google.com/colaboratory/local-runtimes.html
    4. Get the localhost URL shown
  4. Switch to Colab to connect
    1. Click the run-time box at top-right
    2. Click 'Connect to local run-time'
    3. Use the URL gotten above.
    4. Edit the IPython notebook as usual
  5. To edit other files:
    1. Open new browser tab
    2. Paste the localhost link above
    3. Navigate and click a file to edit.

Use 'expect' in Bash Script to Automate Entering Inputs

expect <<HEREDOC
  spawn some long command;

  expect {
    "some text 1" {
      set timeout -1;
      send "some input\r";
      exp_continue;
    }
    "some text 2" {
      set timeout -1;
      send "some input\r";
      exp_continue;
    }
    "some text 3" {
      set timeout -1;
      send "some input\r";
      exp_continue;
    }
  }
HEREDOC

Nginx Config File for Web Service with HTTPS Cert Provided by Let's Encrypt

Certbot has a few modes to create free certs:
  • --standalone
    • Certbot needs port 80 to start a temporary server for domain verification
    • Nginx will need to be shut down for a while
    • Not suggested method, big down time during creating or renewing certs
  • --webroot
    • Certbot won't start temporary server
    • Nginx stays intact
    • Suggested method, fast verification, no down time.
  • --certbot-dns-SOMESERVICE
    • Certbot supports domain verification by DNS
    • Some supported plugins available fro Google Cloud, Amazon AWS, etc.
      • --certbot-dns-route53
      • --certbot-dns-google
      • --certbot-dns-digitalocean
      • etc.
    • Not suggested method, DNS verification is slow
Nginx config file for HTTP/HTTPS with cert by Let's Encrypt, using --webroot method,
File /etc/nginx/conf.d/MYDOMAIN.EXT.conf:
server {
  listen 80;
  server_name MYDOMAIN.EXT;

  listen 443 ssl;
  ssl_certificate /etc/letsencrypt/live/MYDOMAIN.EXT/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/MYDOMAIN.EXT/privkey.pem;

  location /.well-known/acme-challenge {
    alias /usr/share/nginx/html/.well-known/acme-challenge;
  }

  location / {
    if ($scheme = "http"){
      return https://$host$request_uri;
    }

    root /some/dir;
    #OR:
    #proxy_pass http://localhost:SOMEPORT;

    #OR:
    #if ($host = "...")         { proxy_pass ... }
    #if ($host ~ "(...)|(...)") { proxy_pass ... }
  }
}


1) Create the file above, comment out the 3 SSL lines, and restart Nginx:
sudo systemctl restart nginx

2) Get cert, and run:
sudo certbot certonly --webroot --webroot-path /usr/share/nginx/html \
--cert-name MYDOMAIN.EXT --domains MYDOMAIN.EXT

3) Got the cert, enable back the 3 SSL lines, and restart Nginx:
sudo systemctl restart nginx

4) Renew cert any time later with:
sudo certbot renew --webroot --webroot-path /usr/share/nginx/html \
--cert-name MYDOMAIN.EXT --expand --domains MYDOMAIN.EXT

Monday, 17 February 2020

Route Domains to Different Service Ports Using Pure Google Cloud Balancer or Nginx

Solution 1: Use Google Balancer for simple mapping domains to service ports:
  1. Create different backends for different service ports
  2. Create host and path rules for mapping domains to backends
  3. Create the frontend (proxy) to receive requests
  4. Notes:
    1. Client -> Proxy -> Host/path rules -> Backend:Port
    2. Use SSL/TLS cert on frontend, not necessary elsewhere
  5. Pros:
    1. Multiple healthchecks for multiple services
  6. Cons:
    1. No advanced config on proxy
Solution 2: Use Google Balancer + Nginx for advanced mapping domains to service ports:
  1. Create a single backend to Nginx at port 80
  2. No need host/path rules
  3. Create frontend (proxy) to receive requests
  4. Config Nginx on all instances to add custom configurations, e.g. HTTP Upgrade for socket.io, etc.
  5. Notes:
    1. Client -> Frontend (Proxy) -> Skip:Host/path rules --> Nginx --> Service:Port
    2. Use SSL/TLS cert on frontend, not necessary elsewhere.
  6. Pros:
    1. Advanced config on Nginx proxy
  7. Cons:
    1. Only a single healthcheck, when deploying services on an instance, shutting down Nginx is required to notify the healthcheck; all services on this instance is down at the same time. When all services on this instance are up back, turn on Nginx to notify healthcheck again.

Saturday, 15 February 2020

XMinG for Local Use and XMinG for X11 Forwarding

Windows 10 has WSL (Windows Subsystem Linux) and it launches a terminal by default. Here's how to run Linux GUI apps from that terminal:
  • On Windows, install XMinG
  • In terminal:
    • Open ~/.bashrc
    • Add a line: 
      • export DISPLAY=0.0
    • Run: 
      • source ~/.bashrc
    • Test: 
      • sudo yum install xclock -y && xclock
VNC is boring with all remote apps shown in a virtual display rectangle, here's how to use X11 Forwarding to open remote apps in separate windows:
  • Install and test XMinG as above.
  • Enable X11 Forwarding on server:
    • ssh someserver
    • sudo micro /etc/ssh/sshd_config
    • Find and set these:
      • X11UseLocalhost no
      • X11Forwarding yes
    • sudo systemctl restart sshd
    • sudo yum install xauth -y
    • logout
  • Run test:
    • ssh -Xv someserver
    • It says: ".Xauthority does not exist", run again:
    • ssh -Xv someserver
    • xclock

SSH Port Tunnelling Example

Run this command to tunnel server port SERVERPORT to localhost port LOCALPORT:
sudo ssh -L LOCALPORT:localhost:SERVERPORT myserver.com

For example, tunnel server port 80 to localhost port 8080:
sudo ssh -L 8080:localhost:80 myserver.com

Now, instead of opening:
http://myserver.com:80

Open:
http://localhost:8080

Friday, 14 February 2020

DNN: Number of Neurons, Number of Params, and Number of Combinations

Consider a DNN with 2 dense layers of 10 neurons and 10 neurons.

Number of neurons:
10 + 10 = 20

Number of params:
10*10 + 10*10 = 100 + 100 = 200

Number of combinations:
100 * 100 = 10,000

The DNN should be big enough to fit (but don't overfit, no use):
  • More layers enough to fit desired number of  separations
  • More neurons in layers enough to fit number of input combinations

YAML Syntax and Conversion to JSON

YAML is a good markup lang for config, it's simpler than JSON, and it has comments, although JSON5 allows comments too.

Tool:
https://codebeautify.org/yaml-to-json-xml-csv

YAML syntax:
1) Colon, newline, indent, key --> Object
2) Colon, newline, indent, dash, value --> List of values
3) Colon, newline, indent, dash, key, colon, value --> List of objects

Example YAML:
#Object
objkey:
  subkey1: "foo"
  subkey2: "bar"
  
#List of values
listkey1:
  - "foo"
  - "bar"
  
#List of objects
listkey2:
  - foo1: "foo1"
    foo2: "foo2"
  - bar1: "bar1"
    bar2: "bar2"

#Shorthands    
#List of values (single line)
listkey3: ["foo","bar"]

Conversion to JSON:
{
  "objkey": {
    "subkey1": "foo",
    "subkey2": "bar"
  },

  "listkey1": [
    "foo",
    "bar"
  ],

  "listkey2": [
    {
      "foo1": "foo1",
      "foo2": "foo2"
    },
    {
      "bar1": "bar1",
      "bar2": "bar2"
    }
  ],
  "listkey3":["foo","bar"]
}

Wednesday, 12 February 2020

Fortran & Lisp: The First High-level Structured Language and Functional Language

Fortran: The first high-level structured language
program bubble_test

  implicit none
  integer, dimension(6) :: vec 
  integer :: temp, bubble, lsup, j

  read *, vec !the user needs to put 6 values on the array
  lsup = 6 !lsup is the size of the array to be used

  do while (lsup > 1)
    bubble = 0 !bubble in the greatest element out of order
    do j = 1, (lsup-1)
      if (vec(j) > vec(j+1)) then
        temp = vec(j)
        vec(j) = vec(j+1)
        vec(j+1) = temp
        bubble = j
      endif 
    enddo
    lsup = bubble   
  enddo   
  print *, vec
end program
Lisp: The  first high-level functional language
(defun bubble-sort (lst)
  (loop repeat (1- (length lst)) do
    (loop for ls on lst while (rest ls) do
      (when (> (first ls) (second ls))
        (rotatef (first ls) (second ls)))))
  lst)

Free GPU-enabled General Programming and ML Services

Google Colab:
  • https://colab.research.google.com
  • Pros:
    • Free GPU time
    • Save documents to Google Drive
    • Document outline (headings) available on UI
    • Run any language using %%writefile and %%script bash
    • Install anything with sudo apt install
    • Anything! basically it's a server without public ports
  • Cons:
    • No file manager side panel
    • No opened file tabs
    • Session is not persistent, opening .ipynb files will lead to random environment without previous saved files.
    • No public ports
    • No terminal
Paperspace Gradient:
  • https://paperspace.com
  • Pros:
    • Free GPU time
    • Save documents to the Docker container (or VM?) itself
    • Create/open/run any file, not just %%writefile and %%script bash in .ipynb files
    • Install anything with sudo apt install
    • It's a private server without public ports
    • Persistent saved files, persistent environment, open Gradient again with the same opened file tabs
    • Based on JupyterLab, file manager available, opened file tabs
    • Terminal default in 'sh' but run 'bash' to have Bash terminal
    • Anything! basically it's a persistent server without public ports
  • Cons:
    • No public ports
    • Can't save to Google Drive
    • No .ipynb document outline (headings)

Wednesday, 5 February 2020

Google Sign-in Button, Chatfuel, Their Usefulness and Trade-off

Google Sign-in button:
  • Usefulness: 
    • Visitors don't need to create accounts, visitors are very lazy nowadays. This catch more visitors than enforcing the to register to use, enforcing visitors means losing visitors.
  • Trade-off: 
    • There's a latency below 1 second to have user data ready to render contents.
Chatfuel:
  • Usefulness: 
    • Visitors don't need to create accounts, use Facebook accounts to chat.
    • Direct chat pop-up in current website page without the need to open new tab to chat. Chatfuel is the best app for integrating Facebook chat in a website as Facebook doesn't provide chat HTML embed for websites. Besides, Chatfuel is even better than other apps for Facebook chats that it is AI-powered, although not yet with powerful AI (doesn't pass Turing test, uses text classification to make responses).
  • Trade-off: 
    • No trade-off, perfect chat embed!

Browser History and Good Browsers Now

Early Internet era:
  • Internet Explorer (Winner of the first browser war but now used to download other browsers only)
  • Netscape (Eliminated in the first browser war)
  • Mozilla (Changed name to Firefox later)
  • Opera (Died out with fewer users)
Present time (2020) browsers:
  • Vivaldi (Chromium-based, with mouse gesture and web panels)
  • Chrome (Chromium-based, very popular)
  • Firefox (Gecko-based, better than Chrome with tabs in full-screen mode)
  • Edge (Trident-based, just like IE, for downloading other browsers only)
  • IE: Rested in peace!
Non-Windows browsers:
  • Safari: MacOS only
  • Konqueror: KDE only

Tuesday, 4 February 2020

L1 and L2: Losses, Norms, Regularisations, and Deviations

1. Losses

With Ui is output, Yi is true value,
L1 Loss:
Loss=|U1Y1|+..+|UnYn|N
L2 Loss:
Loss=(U1Y1)2+..+(UnYn)2N

2. Norms

With Wi is weight,
L1 Norm:
Norm=W1+..+Wn
L2 Norm:
Norm=W21+..+W2n

3. Regularisations

L1 Regularisation:
Regularisation=Ratio×L1Norm
L2 Regularisation:
Regularisation=Ratio×L2Norm

4. Bonus: Deviations

L1 Deviation:
L1Variance=|X1Mean|+..+|XnMean|N
MeanDeviation=L1Variance
L2 Deviation:
L2Variance=(X1Mean)2+..+(XnMean)2N
StandardDeviation=L2Variance
Deviations are important, used in generator in GANs. After training an auto-encoder, use the decoder as generator. In the auto-encoder model, additional deviation layer makes it work better.