Sunday, January 31, 2016

Penghitung Langkah Kaki menggunakan Accelerometer Handphone

Pernah melihat dan menggunakan Fitbit sebelumnya? Alat kecil seperti gelang ini ketika digunakan ditangan bisa menghitung berapa banyak Anda melangkah setiap hari. Beberapa aplikasi penghitung langkah ini juga banyak tersedia di Android dan Apple. Sebenarnya bagaimanakah mekanisme penghitung langkah ini bekerja? Kali ini kita mencoba mengkaji salah satu caranya menggunakan accelerometer. Fitbit dan alat kommersial lainnya tentu saja punya teknik lainnya yang proprietary. Kita tidak membicarakan cara mereka disini, poinnya adalah untuk mengetahui kira-kira bagaimana alat tersebut bekerja.

Perhatikan cara kerja accelerometer berikut:

Jika digerakkan keatas Y akan bernilai positif dan sebaliknya. Bagaimana kalau handphone sedang dalam keadaan diam? Dia akan negatif karena ada gravitasinya bumi 9.8 m/s2. Bagaimana jika handphone tersebut ditaruh didalam saku celana?


Perhatikan kondisi ketika ketika berjalan dan handphone berapa disaku celana.
  1. Berjalan biasa, berjalan cepat, ataupun berlari akan membuat handphone berayun sesuai dengan langkah kaki. Ayunan ini mengakibatkan ada percepatan yang ditangkap oleh accelerometer pada handphone. Dengan menangkap semua angka pada frekuensi tinggi (100Hz) atau sekitar 100 data poin setiap detik kita akan mendapatkan pergerakan angka-angka ayunan kaki tersebut secara granular.
  2. Langkah kaki pada umumnya bergerak pada bidang planar (mengayun ke atas dan bergerak ke depan). Artinya secara teori hanya dua sumbu accelerometer yang mendeteksi percepatan gerakan.
  3. Pada saku yang tidak ketat, handphone kemungkinan berpindah-pindah posisi sehingga deteksi percepatan mungkin terjadi pada semua sensor axis


Bagaimana kita bisa menyatukan semua gerakan axis accelerometer hingga bisa mendeteksi gerakan? Cara yang sederhana adalah dengan menambahkan nilai kuadrat semua nilainya.

Sensor Number= X2 + Y2 + Z2

Kenapa rumus diatas?
  1. Angka accelerometer ada yang negative, kuadrat akan membuat semua nilai positif
  2. Tipikal gerakan mengayun pada bidang planar secara teori mengakibatkan hanya dua axis yang meregister ayunan
  3. Apabila handphone berputar di dalam saku, pengurangan nilai pada satu axis akan dikompensasi dari nilai axis lainnya, akibatkan jumlah ketiganya secara probabilitas masih dalam angka yang sama


PROGRAM-nya:
Testing menggunakan Samsung Galaxy S4 dengan setting sensor maksimal. Alasannya karena hardware Samsung Galaxy S4 cukup akurat (flagship Samsung) dan sensor maksimal untuk memastikan granularity data.

Set sensor Android di 100Hz:
  @Override
  protected void onResume() {
    super.onResume();
    sensorManager.registerListener(this,
        sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
        SensorManager.SENSOR_DELAY_FASTEST);
    sensorManager.registerListener(this,
            sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE),
            SensorManager.SENSOR_DELAY_FASTEST);
  }


Ambil nilainya:
  @Override
  public void onSensorChanged(SensorEvent event) {
    if ((event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)&&(Running)) {
      getAccelerometer(event);
    }
    if ((event.sensor.getType() == Sensor.TYPE_GYROSCOPE)&&(Running)) {
        getGyroscope(event);
      }
  }

  private void getAccelerometer(SensorEvent event) {
    float[] values = event.values;
    long actualTime = System.nanoTime();
    float x = values[0];
    float y = values[1];
    float z = values[2];
    try {
        result= result+ "ACC\t"+actualTime+"\t"+x+"\t"+y+"\t"+z+"\n";
        counter++;
        if (counter%15==0){
            out.append(result);
            counter=0;
            result="";
        }
    } catch (Exception e){
        e.printStackTrace();
    }

  }


Selain itu, perhatikan hal-hal teknis berikut:
  1. Rekam ke dalam sdcard data hasil sensor minal untuk setiap 20 record. Kecepatan penulisan SDCard berbeda-beda dan kita berusaha menghindari masalah I/O
  2. Prevent Sleeping pada Andorid. Ini supaya sensor terus bekerja meskipun didalam celana
  3. Time series ubah ke dalam System.nanoTime();  untuk memastikan granularity

 Perhatikan plot hasil rekaman accelerometer diatas dalam chart berikut:


Anda lihat? terdapat pola pada setiap langkah kita? Hmm silahkan explore lebih lanjut ya, dengan menquantifisir chart tersebut ke dalam algoritma SAX dan PLA, kita bisa membedakan mana yang jalan biasa, jalan cepat, dan berlari. 

Friday, January 29, 2016

Mempersiapkan Ubuntu agar bisa diinstall dengan Hadoop (Cloudera)

Anda sudah melihat petunjuk instalasi Hadoop (Cloudera) di internet namun setelah mencoba-coba sendiri Anda menemukan proses tersebut tidak selancar apa yang disampaikan? Saya juga mengalami hal yang sama, namun setelah pengalaman instalasi beberapa kali, problem-problem tersebut muncul karena mengabaikan beberapa hal-hal kecil yang perlu dipersiapkan. Big Data Cloudera pada dasarnya distributed computing dimana beberapa server bekerja secara bersama untuk menyimpan dan mengolah data. Setiap server harus saling berkomunikasi dan saling sinkron, bahkan sampai ke detik jam server tersebut! 

Installasi ini sedikit banyak juga berlaku buat OS lain seperti CentOS. Pemilihan saya menggunakan Ubuntu adalah karena kemudahan setting dan update OS-nya yang rutin setiap saat. Instalasi ini mengasumsikan minimal ada 3 node dimana satu node berfungsi sebagai Cloudera Server Manager, satu node untuk Namenode, dan satu node lagi untuk Datanode.
  1. Install Ubuntu dengan USB drive karena Anda akan menginstall pada banyak server / node. Dengan USB Drive kita juga dapat memperbanyak ke USB Drive yang lain sehingga installasi dapat dilakukan secara parallel.
  2. Konek ke internet dan lakukan update setelah installasi selesai.
    • pada layar terminal lakukan sudo apt-get update dilanjutkan dengan sudo apt-get install
    • Lakukan update pada menu system update (search update di start menu)
  3. Salah satu server harus bertindak sebagai ntp server untuk mensinkronkan jam setiap server. Pada server tersebut lakukan 
    • sudo apt-get install ntp
    • setelah terinsall stop terlebih dahulu sudo service ntp stop
    • sync dengan ntp server seperti sudo ntpdate time.nist.gov
    • start kembali ntp server sudo service ntp start
    • Pada server lainnya nanti lakukan sudo ntpdate [server ntp tersebut]
  4. Install java dengan mendownload tarnya pada browser (bawaan Ubuntu adalah firefox). Misalnya jalankan sudo tar -xvf jdk-7u75-linux-x64.tar.gz pada folder /usr/lib/jvm. Hati-hati apabila anda sudah pernah memiliki installasi java sebelumnya karena jika demikian, anda harus pastikan Ubuntu memilih java yang mana untuk Cloudera. Ubah ranking dan akses level sesuai petunjuk di stackoverflow berikut.
    1. sudo update-alternatives --install "/usr/bin/java" "java" "/usr/lib/jvm/jdk1.7.0_75/bin/java" 1
      sudo update-alternatives --install "/usr/bin/javac" "javac" "/usr/lib/jvm/jdk1.7.0_75/bin/javac" 1
      sudo update-alternatives --install "/usr/bin/javaws" "javaws" "/usr/lib/jvm/jdk1.7.0_75/bin/javaws" 1
      This will assign Oracle JDK a priority of 1, which means that installing other JDKs will replace it as the default. Be sure to use a higher priority if you want Oracle JDK to remain the default.
      
      Correct the file ownership and the permissions of the executables:
      
      sudo chmod a+x /usr/bin/java
      sudo chmod a+x /usr/bin/javac
      sudo chmod a+x /usr/bin/javaws
      sudo chown -R root:root /usr/lib/jvm/jdk1.7.0_75
  5. Setting JAVA_HOME di /etc/environment dengan command sudo gedit /etc/environment kemudian tambahkan line JAVA_HOME="/usr/lib/jvm/jdk1.7.0_75/bin"
  6. install ssh-server karena cloudera server manager (satu server yang me-maintain semua node) harus bisa mengakses seluruh server yang lain. 
    • di semua node install sudo apt-get install openssh-server
    • di cloudera manager server dan namenode server buat ssh key dengan command ssh-keygen -t rsa
    • buat authorized keys untuk dengan command cat ~/.ssh/id_rsa.pub authorized_keys
    • copy authorized_keys tersebut disemua node pada folder ~/.ssh/authorized_keys 
  7. Install ethtool dengan command sudo apt-get install ethtool. Ethtool berguna untuk mengubah kecepatan ethernet card server. Perlu diperhatikan kalau Cloudera akan mereport error apabila ada kecepatan ethernet salah satu node tidak sama dengan yang lain. Kejadian ini bisa saja terjadi karena operational Big Data sangat berat di network, seringkali perangkat switch dan ethernet server down atau menurun kecepatannya dari 1Gbs ke 100Mbs. Untuk setting permanent tambahkan line post-up /sbin/ethtool -s $eth0 speed 1000 duplex full autoneg off
  8. Untuk datanode dan namenode di Server-Server tersebut gunakan harddisk yang terpisah dan tiap harddisk menggunakan satu mount sendiri. Apabila harddisk terbatas dan anda ingin harddisk yang terinstall OS juga berfungsi sebagai datanode/namenode, pastikan untuk menginstall quota. Fungsi quota untuk memastikan file datanode Anda membesar melebih kapasitas harddisk untuk OS sendiri. 
    • install quota dengan command sudo apt-get install quota
    • buat quota di folder user seperti mkdir -p /usr/disk-img
    • buat quota misalnya 230GB dengan command dd if=/dev/zero of=/usr/disk-img/disk-quota.ext3 count=450560000
    • edit gedit /etc/fstab tambahkan /usr/disk-img/disk-quota.ext3 /dfs ext3 rw,loop,usrquota,grpquota 0 0
    • Format quota yang sudah dibuat dengan command sudo mkfs -t ext3 -q /usr/disk-img/disk-quota.ext3 -F
    • mount dengan command sudo mount /dfs
  9. Pada harddisk terpisah terutama yang ukurannya lebih dari 2GB gunakan format GPT. Kalau tidak, maksimum kapasitas yang terlihat hanyalah 2GB meskipun kapasitas Harddisk sendiri adalah 4GB. Cara berikut asumsinya Anda pakai harddisk 4GB yang didetect sebagai sbd pada Ubuntu
    • sudo parted /dev/sdb
    • mklabel gpt
    • mkpart primary ext3 0GB 4000.8GB
    • quit
    • sudo mkfs.ext3 /dev/sdb1
  10. Hentikan automatic upgrade apabila semua proses diatas selesai. Perlu diperhatikan untuk menggunakan sistem operasi yang sama berikut versinya pada semua server. Automatic upgrade dapat dicegah dengan command sudo gedit /etc/update-manager/release-upgrades  Prompt=never
Demikian, semoga Anda tidak menemukan error yang pernah saya alami.

String Similarity menggunakan UDF pada HIVE

Seorang nasabah Bank Mandiri bernama Anto Febrianto selalu mentranfer uangnya ke BCA setiap bulan dengan nama AntoFebriant. Dari dua nama tersebut kita mungkin bisa dengan mudah memahami keduanya adalah orang yang sama. Bagaimana caranya agar sistem dapat mengetaui kalau itu adalah orang yang sama dengan cepat pada ratusan juta record transaksi setiap bulan? Hal ini dapat dilakukan dengan pengembangan teknik Levenshtein Distance. Silahkan cek wikipedia untuk mengenal Levenshtein Distance. Topik yang saya bahas disini adalah bagaimana menggunakan Leveshtein Distance untuk menyelesaikan masalah nyata di lapangan.

Hal yang perlu diperhatikan adalah sebagai berikut:
  1. Levenshtein Distance dari dua kata yang identik adalah 0. Misalnya PERTAMINA dan PERTAMINA memiliki distance 0 karena sama. Apabila kita bandingkan antara PERTAMINA dengan PERTAMINI nilainya adalah 1 karena ada satu karakter yang berbeda.
  2. Dari nilai yang obsolut diatas, tidak ada kejelasan kapan kita bisa yakin bahwa dua kalimat tertentu adalah sama meskipun distance-nya adalah 4. Kita harus mengubahnya ke dalam persentase sehingga bisa lebih intuitive menentukan treshold kesamaan dua nama.
  3. Beberapa stop word (kata tidak penting) harus dihapus. Pada kasus perbankan, kata kata seperti PT, Persero, Tbk, Sdr. Mrs. Ny. Tn. harus dihapus karena attribute yang tidak bisa membedakan antara nasabah yang satu dengan yang lain.

Berikut kodenya:

package com.anto.udfprm;

import java.util.HashMap;
import java.util.Map;

import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.io.Text;

public class _antoUDFLevenshtein extends UDF {
  public Float evaluate(Text s1, Text s2) throws HiveException{
    if (s1 == null || s2 == null) {
      return null;
    }
    return computeLevenshteinDistance(s1.toString(), s2.toString());
  }

  private static int minimum(int a, int b, int c) {
    if (a<=b && a<=c)
      return a;
    if (b<=a && b<=c)
     return b;
    return c;
  }
    
  private static float computeLevenshteinDistance(String s1, String s2) {
    //kumpulkan daftar stop word
 String stopword="SERVIS|SERVICE|HOLDING|GROUP|LEASING|(T\\.?B\\.?K\\.?)|PERSR|PERSERO|(L\\.?T\\.?D\\.?)|(P\\.?T\\.?E\\.?)|(C\\.?V\\.?)|(P\\.?T\\.?)|\\d\\d\\d*|[\\_\\-\\*\\&\\^\\%\\$\\#\\@\\(\\)\\+\\=\\`\\~\\,\\.\\/\\<\\>\"\']";
    String s1String= s1.toString().toUpperCase().replaceAll(stopword, " ");
    
    //atur spasi dan susun rapi nama standard yang baru
    String[] s1_ins= s1String.split(" ");
    String s1_new="";
 for (String s1_in: s1_ins) {
  if (s1_in.trim().length()!=0) {
   s1_new = s1_new + " "+(s1_in).trim();
  }
 }
 s1_new= s1_new.trim();
 
 String s2String= s2.toString().toUpperCase().replaceAll(stopword, " ");
 String[] s2_ins= s2String.split(" ");
 String s2_new="";
 for (String s2_in: s2_ins) {
  if (s2_in.trim().length()!=0) {
   s2_new = s2_new + " "+(s2_in).trim();
  }
 }
 s2_new= s2_new.trim();
 
 //Ubah huruf romawi jadi angka
 Map romawi= new HashMap();
 romawi.put("I", "1"); romawi.put("II", "2"); romawi.put("III", "3"); romawi.put("IV", "4"); romawi.put("V", "5");
 romawi.put("VI", "6"); romawi.put("VII", "7"); romawi.put("VIII", "8"); romawi.put("IX", "9"); romawi.put("X", "10");
 romawi.put("XI", "11"); romawi.put("XII", "12"); romawi.put("XIII", "13"); romawi.put("XIV", "14"); romawi.put("XV", "15");
 romawi.put("XVI", "16"); romawi.put("XVII", "17"); romawi.put("XVIII", "18"); romawi.put("XIX", "19"); romawi.put("XX", "20");
    
 s1_ins= s1_new.split(" ");
    int len= s1_ins.length-1;
    s1_new="";
    int n=0;
 for (String s1_in: s1_ins) {
  if (n==len){
   if (romawi.containsKey(s1_in.trim())){
    s1_new = s1_new + " "+romawi.get(s1_in.trim());
   } else {
    s1_new = s1_new + " "+(s1_in).trim();
   }
  } else {
   s1_new = s1_new + " "+(s1_in).trim();
  }
  n++;
 }
 s1_new= s1_new.trim();
    
 s2_ins= s2_new.split(" ");
    len= s2_ins.length-1;
    s2_new="";
    n=0;
 for (String s2_in: s2_ins) {
  if (n==len){
   if (romawi.containsKey(s2_in.trim())){
    s2_new = s2_new + " "+romawi.get(s2_in.trim());
   } else {
    s2_new = s2_new + " "+(s2_in).trim();
   }
  } else {
   s2_new = s2_new + " "+(s2_in).trim();
  }
  n++;
 }
 s2_new= s2_new.trim();
  
 char[] str1= s1_new.toCharArray();
 char[] str2= s2_new.toCharArray();
 
    int[][] distance = new int[str1.length+1][];

    for(int i=0; i<=str1.length; i++) {
      distance[i] = new int[str2.length+1];
      distance[i][0] = i;
    }

    for(int j=0; j=lenstr2) {
     if (lenstr1>dist){
      return (lenstr1 - dist)/lenstr1;
     } else {
         return 0; 
     }
    } else {
     if (lenstr2>dist){
      return ((lenstr2 - dist)/lenstr2);
     } else {
      return 0;
     }
    }
  } 
}


Kode tersebut dipaket ke dalam Jar kemudian diupload ke hadoop melalui Hue.

Setelah itu, fungsi di buat pada hive.



Selanjutnya diuji,


Demikian, kita sudah bisa membuat fungsi UDF pada hive dan membuat kasus menarik untuk Big Data yakni String Similarity.


Sains dibelakang Big Data Analitik

Sains dibelakang Big Data Analitik berbicara mengenai algoritma apa yang digunakan untuk kasus apa. Tidak semua sainsnya dapat diterapkan untuk semua kasus, misalnya pada Twitter apabila kita berbicara mengenai trending, analysisnya lebih pada analisis time series (contoh temporal analysis) sementara bila kita bicara mengenai sentimen posting, analysisnya lebih pada analysis classification (contoh naive bayes). Umumnya mata kuliah sains ini dipelajari pada jurusan statistik dan ilmu komputer. Mata kuliah tersebut diantaranya artificial intelligence, data mining, information retrieval, dan statistics inference.

Untuk memudahkan pemahaman sains ini, saya akan mengambil contoh penggunakan naive bayes dalam klasifikasi kalimat. Contoh ini dapat dikembangkan untuk tujuan lainnya seperti mengukur sentimen tweet di Twitter. Contoh ini saya ambil dari link Stanford NLP (Natural Language Processing) website.



Dari gambar diatas terlihat dari semua training data terdapat 3 record dengan klasifikasi c dan 1 record dengan klasifikasi j (atau bukan c). Berdasarkan data training tersebut (yang secara teoritiknya diambil secara random) kita dapatkan:

Prior Probability:
Probabilitas dokumen dengan klasifikasi c atau P(c) = 3/4
Probabilitas dokumen dengan klasifikasi bukan c atau P(j) = 1/4

Jumlah kata unique dalam semua kalimat training diatas adalah 6

Sekarang kita lihat Testing data yang terdiri dari kata Chinese Chinese Chinese Tokyo Japan. Kita hitung probabilitas tiap kata tersebut satu persatu.

Probability kata Chinese pada saat kategorynya c
P(Chinese|c) = (5 + 1)/(8+ 6) = 6/14 atau 3/7

5 berasal dari lima kali kata chinese muncul pada saat klasifikasi c
1 adalah digunakan untuk normalisasi pembilang
8 berasal dari jumlah semua kata pada saat klasifikasi c
6 berasal dari jumlah semua kata unik pada training data

Seterusnya untuk semua istilah kita dapatkan
P(Tokyo|c)      = P(Japan|c) = (0 + 1)/(8+ 6) = 1/14 
P(Chinese|j)    = (1 + 1)/(3+ 6) = 2/9
P(Tokyo|j)       = P(Japan|j) = (1 + 1)/(3+ 6) = 2/9

Jadi berapa probability Chinese Chinese Chinese Tokyo Japan untuk c dan j?
P(c|test data) = 3/4 * (3/7)*(3/7)*(3/7) * (1/14)*(1/14) = 0.0003
P(j|test data) = 1/4 * (2/9)*(2/9)*(2/9) * (2/9)*(2/9)= 0.0001

Terlihat disana kalau kalimat baru basuk ke dalam klasifikasi c.

Untuk mudahnya silahkan lihat video berikut:



Naive Bayes hanyalah salah satu contoh dari sekian banyak sains pada Big Data Analytics. Beberapa lainnya seperti Neural Network dan Logistic Regression. 


Reference: Stanford NLP


Wednesday, January 27, 2016

Memahami Perbedaan Big Data dan Data Warehouse

Hal pertama yang sering kita dengar tentang perbedaan Big Data dengan Data Warehouse (DWH) adalah Big Data untuk data tak terstruktur seperti percakapan di twitter sedangkan DWH untuk data terstruktur seperti record rekening bank Anda. Pernyataan ini sebenarnya tidak sepenuhnya benar karena Big Data juga bisa menangani data terstruktur sedangkan DWH juga bisa diinput dengan data tak terstruktur (seperti BLOB). Untuk lebih lengkapnya, berikut perbandingan Big Data dan DWH:
  1. Big Data teroptimasi untuk mengolah data tak terstruktur. File dalam HDFS atau hadoop secara sederhana seperti file yang kita miliki dalam folder windows explorer atau handphone. Kita bisa menaruh file apapun di dalamnya seperti file foto, video, dan lain-lain. Itulah maksudnya teroptimasi untuk data tak terstruktur. Dilain pihak, DWH justru teroptimasi untuk data terstruktur seperti tabel. Pada data terstruktur, tipe data terdefinisi dengan jelas misalnya nama orang bertipe varchar dengan ukuran 50 karakter. Selain itu secara default terdapat primary key untuk menjaga keunikan seluruh data. 
    Stream Twitter yang tersimpan didalam Hadoop dilihat menggunakan Hue. Seperti terlihat diatas, stream twitter yang berformat JSON tidak akan mudah diolah dengan RDBMS. Dilain pihak, Hive pada Big Data dapat mengolah data tersebut dengan mudah.
  2. Schema on the fly atau sederhananya "schema tabel belakangan saja". Ketika kita melakukan memasukkan data dan memanipulasinya di RDBMS, kita harus mempertimbangkan schema data dari awal. Misalnya apakah nomor kartu kredit disimpan sebagai bilangan integer atau karakter string. Keputusan pemilihan ini harus konsisten untuk setiap table karena berpengaruh ketika analysis memerlukan operasi join beberapa tabel. Hal tersebut tidak berlaku pada Big Data. Schema dapat diset dan diubah belakangan
Bagaimana dengan ukuran data? Perbedaannya adalah bagaimana teknologi Big Data (Hadoop related) menangani data berukuran besar. Big Data memang dari awal didesain untuk bisa menangani data berukuran besar dengan mendistribusikan data tersebut ke banyak server. Ketika server-server tersebut penuh, kita bisa menambahkan server baru (node) untuk menambah kapasitasnya. Pada DWH hal tersebut tidak dimungkinkan, ketika server melebihi kapasitasnya, kita diharuskan untuk membeli server yang baru yang lebih besar.
Menambahkan Node Baru di Cloudera hanya dengan menggunakan wizard. Node baru bisa digunakan untuk menambah kapasitas Big Data