Langsung ke konten utama

Data Analysis Series: Tutorial Membangun DSS Berbasis Naive Bayes Classifier Menggunakan Scikit-Learn dan Flask Framework (2)

Tentang Flask

Saya menggunakan Flask, sebuah web framework Python untuk mensederhanakan proses eksekusi model classifier yang sudah dibangun. Tentu user yang awam akan teknologi, tidak akan nyaman dengan text editor, interpreter apapun untuk melakukan tugas sehari-harinya. Maka di sini saya menggunakan Flask, yang sebelumnya sudah saya perkenalkan pada beberapa bulan yang lalu. Oh ya, jika anda ingin tahu lebih banyak tentang Flask dan cara instalasinya, anda bisa buka laman resminya: flask.pocoo.org/

Skeleton/Struktur Project Web Application

Berbeda dengan beberapa framework PHP seperti laravel yang menggunakan composer untuk membuat skeleton project, struktur/skeleton dari aplikasi web berbasis Flask harus dibuat secara manual. Namun demikian, tidaklah susah membuat struktur dari Flask. Untuk contoh project kali ini, saya akan menggunakan struktur proyek sebagai berikut:

BankMarketing/
       app/
          static/
          templates/
       tmp/



Jika anda sudah familiar dengan web framework yang populer seperti PHP CodeIgniter, PHP Yii, atau Java Spring, anda tentu sudah bisa menebak wadah-wadah yang digunakan pada struktur project tersebut. Flask sama halnya web framework pada umumnya, menggunakan konsep Model-View-Controller (MVC). Namun pada Flask, standar penamaan layer-layer tersebut tidak secara eksplisit digunakan. Sebaliknya, untuk Controller, Flask menggunakan folder app untuk menampung semua controller aplikasi. Untuk View, Flask menggunakan folder templates untuk file-file HTML, sedangkan file-file resource statis seperti CSS, JavaScript ditempatkan pada folder static. Sedangkan untuk model, secara opsional ditampung pada folder tmp.

Controller 

Sebagai awalan, buat file index.py di bawah folder app, sehingga struktur project menjadi seperti ini:

BankMarketing/
       app/
          static/
          templates/
          index.py
       tmp/

Buka file index.py, tulis kode di bawah ini:

1  from flask import render_template
2  from app import app
3  from numpy import genfromtxt
4  from flask import request
5
6
7  @app.route('/')
8  @app.route('/index')
9  def index():
10    user = {'nickname': 'Irfan'}
11    return render_template('index.html',
12                           title='Home',
13                           user=user)

Penjelasan dari script di atas adalah, pada baris ke 1 sampai dengan baris ke 4, modul index ini akan mengimpor library render_template untuk melakukan rendering view yang akan ditampilkan di browser, library app untuk memanggil core library dari Flask, library numpy untuk memproses perhitungan scientific, dan libraru request untuk memproses lemparan parameter dari form pada view.

Baris ke-7 dan 8 menunjukkan bahwa aplikasi dapat diakses dari dua directive, yaitu http://localhost/ maupun http://localhost/index. Baris ke-9 menjelaskan bahwa dua directive tersebut di-binding ke sebuah method yaitu index(). Jadi setiap kali user mengakses kedua directive tersebut, aplikasi akan melakukan callback ke method index(). Method index() sendiri, mempunyai blok prosedur yang dapat dilihat pada baris ke-10 sampai 13. Pada baris ke-10 terdapat deklarasi variabel dalam bentuk Python List, dengan nama variabel nickname, dan value 'Irfan'. Variabel tersebut akan dilempar pada sebuah view bernama 'index.html' pada baris ke 11 sampai dengan 13.

Buat controller ke-dua, masih pada file yang sama, index.py, yang akan menampilkan view yang berisi input field/atribut yang akan digunakan untuk proses klasifikasi:

1  from flask import render_template
2  from app import app
3  from numpy import genfromtxt
4  from flask import request
5
6
7  @app.route('/')
8  @app.route('/classify')
9  def index():
10    user = {'nickname': 'Irfan'}
11    return render_template('classify.html',
12                           title='Home',
13                           user=user)

Controller tersebut akan menampilkan view classify.html ketika user mengakses directive http://localhost:5000/classify/

Sedangkan untuk controller yang akan memproses klasifikasi data nasabah, tulis kode yang sudah dijelaskan pada post sebelumnya, seperti berikut ini.

1  @app.route('/classify_use_nb', methods = ['POST'])
2  def classify_use_nb():
3     age = (int)(request.form['age'])
4     job = (int)(request.form['job'])
5     education = (int)(request.form['education'])
6     marital = (int)(request.form['marital'])
7     default = (int)(request.form['default'])
8     balance = (int)(request.form['balance'])
9     housing = (int)(request.form['housing'])
10    loan = (int)(request.form['loan'])
11    contact = (int)(request.form['contact'])
12    day = (int)(request.form['day'])
13    month = (int)(request.form['month'])
14    duration = (int)(request.form['duration'])
15    campaign = (int)(request.form['campaign'])
16    pday = (int)(request.form['pday'])
17    previous = (int)(request.form['previous'])
18    poutcome = (int)(request.form['poutcome'])
19
20
21    test_data = [age, job, education, marital, default, balance, housing, loan,   22                   contact, day, month, duration, campaign, pday, previous,       23                  poutcome]
24    print(test_data)
25    bank_data = genfromtxt('bank_marketing.csv', delimiter=',')
26    label =  genfromtxt('label.csv', delimiter=',')
27    from sklearn.naive_bayes import GaussianNB
28    gnb = GaussianNB()
29    y_pred = gnb.fit(bank_data, label).predict(test_data)
30
31    if y_pred == 1.0:
32     return str([test_data, "Layak"])
33    else:
34     return str([test_data, "Tidak Layak"])

Sama halnya dengan controller pertama, controller kedua ini mempunyai directive (classify_use_nb) dan binding method. Dapat dilihat method ini mempunyai body yang sama persis dengan apa yang sudah saya jelaskan sebelumnya, namun, sumber datanya berasal dari view yang diakses oleh user. Karena menggunakan method post, untuk meretrieve parameter yang dilempar digunakan fungsi request.form('<nama_form>').

Return dari method ini cukup sederhana yaitu menulis ke laman hasil klasifikasi nasabah yang dilakukan model Naive Bayes milik Scikit-Learn yang sudah kita latih, yaitu "Layak" atau "Tidak Layak".

View

Sebagai landing page, buat sebuah file dengan nama index.html pada folder static. Tulis kode HTML berikut ini:

<html>
  <head>
    <title>{{ title }} - Decision Support System</title>
  </head>
  <body>
      <h1>Hello, {{ user.nickname }}!</h1>
  </body>
</html>

Untuk menampung variabel yang dilempar oleh controller, digunakan beberapa variabel Jinja (template engine) yaitu dinotasikan sebagai {{ title }} dan {{ user.nickname }. Anda juga bisa menambahkan beberapa logic seperti if..else, loop dan lain sebagainya.

Sedangkan untuk view decision support system untuk kasus yang kita gunakan yaitu Bank Marketing, buat file kedua yaitu classify.html di bawah folder yang sama, yaitu static. Tulis kode di bawah ini:

<!DOCTYPE html>
<html>
<head>
<title>
</title>
</head>
<body>
<form action="/classify_use_nb" method="post">

Umur: <input type="text" name="age" id="age"> <br>
Pekerjaan: <select name="job">
<option value="0">unknown</option>
<option value="1">admin</option>
<option value="2">blue-collar</option>
<option value="3">enterpreneur</option>
<option value="4">house maid</option>
<option value="5">management</option>
<option value="6">retired</option>
<option value="7">self-employed</option>
<option value="8">services</option>
<option value="9">student</option>
<option value="10">technician</option>
<option value="11">unemployed</option>
</select> <br>
Status Pernikahan: <select name="marital"> <br>
<option value="0">unknown</option>
<option value="1">divorced</option>
<option value="2">married</option>
<option value="3">single</option>
</select> <br>
Pendidikan: <select name="education"> <br>
<option value="0">unknown</option>
<option value="1">primary</option>
<option value="2">secondary</option>
<option value="3">tertiary</option>
</select> <br>
Wanprestasi: <select name="default"> <br>
<option value="0">unknown</option>
<option value="1">no</option>
<option value="2">yes</option>
</select> <br>
Saldo: <input type="text" name="balance" id="balance"><br>
KPR: <select name="housing"> <br>
<option value="0">no</option>
<option value="1">yes</option>
</select> <br>
Loan: <select name="loan"> <br>
<option value="0">no</option>
<option value="1">yes</option>
</select> <br>
Contact: <select name="contact"> <br>
<option value="0">unknown</option>
<option value="1">telephone</option>
<option value="2">cellular</option>
</select> <br>
Day: <select name="day"> <br>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
<option value="8">8</option>
<option value="9">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="18">18</option>
<option value="19">19</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
<option value="28">28</option>
<option value="29">29</option>
<option value="30">30</option>
<option value="31">31</option>
</select> <br>
Month: <select name="month"> <br>
<option value="1">Jan</option>
<option value="2">Feb</option>
<option value="3">Mar</option>
<option value="4">Apr</option>
<option value="5">Mei</option>
<option value="6">Jun</option>
<option value="7">Jul</option>
<option value="8">Aug</option>
<option value="9">Sep</option>
<option value="10">Okt</option>
<option value="11">Nov</option>
<option value="12">Des</option>
</select> <br>
Durasi: <input type="text" name="duration" id="duration"><br>
Campaign: <input type="text" name="campaign" id="campaign"><br>
PDay: <input type="text" name="pday" id="pday"><br>
Previous: <input type="text" name="previous" id="previous"><br>
POutcome: <select name="poutcome"> <br>
<option value="0">unknown</option>
<option value="1">failure</option>
<option value="2">other</option>
<option value="3">success</option>
</select><br><br>
<input type="submit" value="Predict"></input>
</form>
</body>
</html>

View di atas memuat sebuah form yang berisi 16 field-sesuai dengan jumlah atribut dari model yang kita bangun-, dan sebuah tombol submit. Method yang akan digunakan di sini adalah post (anda juga dapat menggunakan method get), dengan target controller adalah classify_use_nb.

Smoke Testing

Okay, tiba saatnya untuk smoke test, run the project. Buat sebuah file di bawah root project dengan nama run.py (untuk nama opsional). Tulis kode di bawah ini:

#!flask/bin/python
from app import app
app.run(debug=True)

Build file run.py melalui CLI atau jika dari SublimeText, tekan Ctrl-B. Jika semua dependency library terpenuhi dan tidak ada error script, seharusnya di CLI akan memunculkan informasi sebagai berikut:

 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger pin code: 329-312-961

Port 5000 adalah default port dari Flask, anda dapat mengubahnya sewaktu-waktu. Berikutnya, buka browser, dan akses aplikasi melalui URL http://127.0.0.1:5000/


Buka laman classifier nasabah melalui URL http://localhost:5000/classify
Isikan nilai masing-masing field, kemudian klik Predict:
Output dari klasifikasi, untuk percobaan ini menghasilkan keputusan "Layak"
Berikutnya, anda bisa mencoba beberapa kombinasi input, atau mencoba mengambil nilai dari salah satu baris data yang digunakan untuk proses training. 

Mungkin respon proses klasifikasi ini terasa agak lama, hal ini dikarenakan model masih harus melakukan training. Menurut dokumentasi dari Sklearn, model yang pernah kita training sebenarnya tidak perlu dilatih kembali, namun bisa kita simpan hasil yang paling optimumnya dalam bentuk binary file, dan dibuka kembali pada saat diimplementasi pada aplikasi. Akan saya bahas pada post berikutnya.

Komentar

Postingan populer dari blog ini

Berkenalan dengan Laravel

Cukup disayangkan, Codeigniter sudah sampai ke tahap "penguburan" - paling tidak ini klaim dari Ellis Lab- dan ini cukup mengusik kenyamanan saya untuk menggunakan CI. Padahal juga sesuai dengan pengakuan rekan-rekan web developer, CI menurut saya cukup mudah dan powerful untuk digunakan dalam membangun sebuah web apps, dan terbukti juga CI sempat jadi trendsetter untuk framework PHP. Saya jadi penasaran framework PHP apa yang jadi the next PHP Framework star setelah CI, setelah menggali informasi beberapa kali, saya temukan Laravel saat ini banyak jadi batu loncatan developer CI. Alasannya sederhana, Laravel banyak kemiripan dengan CI. Dari analisa Google Trends juga terlihat kepopuleran Laravel saat tulisan ini dibuat juga menanjak meskipun masih kalah populer dengan CI (cukup mengherankan CI masih memimpin untuk masalah kepopuleran). Jadi langsung saja saya mencoba mengeksplorasi barang baru ini. Berikut langkah-langkahnya: 0. Install curl 1. Install composer: ...

Perbandingan Algoritme Dynamic Programming, Greedy, dan Backtrack Programming.

Sebetulnya posting ini bisa dibilang sudah kadaluarsa.  But, Better be late than never at all, right mate ? Ok, sebetulnya(lagi) Saya ingin menulis ulang semua yang ada di tugas semester 1 mata kuliah Analisa Algoritme, namun setelah dipikir-pikir lagi rasa-rasanya akan mubadzir, jadi di sini akan Saya gambarkan ulang secara ringkas saja apa perbedaan Dynamic Programming, Greedy dan Backtrack. Sebelum menyentuh ke dalam algoritmenya, Kita lihat terlebih dahulu kasus permasalahannya. Tentu belajar akan lebih mudah apabila tidak hanya dengan mempelajari teorinya saja. Umumnya orang akan lebih semangat apabila ada kasus menarik yang dipelajari. Tentang Knapsack Knapsack sendiri merupakan permasalahan pencuri yang ingin mencuri barang dengan cara memasukkan sebanyak-banyaknya dan seberharga-berharganya barang yang ada ( of course, its a theft ), sejumlah wadah yang pencuri tersebut punya. Diharapkan dengan menerapkan beberapa algoritme ini pencuri dapat meraup keuntungan sebanyak...

Data Analysis Series: Perceptron - Basic Artificial Neural Network

Pendahuluan Pada posting berikut ini saya akan menyampaikan materi tentang (Artificial) Neural Network. Algoritme yang satu ini terinspirasi dari cara kerja sel otak dalam memproses informasi. Sedikit di bawah ini pertama-tama akan saya sampaikam penjelasan bagaimana sel otak bekerja, untuk mempermudah pemahaman bagaimana ANN dapat terinspirasi. Sel Otak (Sumber:  www.wealltest.com ) Seperti yang kita ketahui, otak terdiri atas milyaran sel. Tiap-tiap sel tersebut terbagi atas tiga bagian, yaitu Dendrites, atau receptor, bagian yang menerima sinyal/stimulasi dari sel-sel otak yang lain. Sinyal/stimulasi yang masuk ke dendrite tersebut awalnya berasal dari indra perangsang kita, seperti mata, kulit, telinga, dan lidah. Dari dendrite, sinyal kemudian diteruskan melalui Axon, semacam pipa penghubung, yang mentransmisikan sinyal dari dendrite, untuk ditransmisikan ulang ke sel lain melalui Synapse. Bisa dikatakan, Synapse ini berfungsi sebagai akumulator untuk dari info...