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:
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.
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
Posting Komentar