Membuat API untuk Model Machine Learning menggunakan Apache Livy dan Spark

Danau Data
5 min readMar 24, 2019

--

Mungkin pernah terbayang bagaimana ketika sudah membuat model machine learning, kita ingin mempublikasikannya sebagai sebuah layanan sehingga model prediktif kita bisa digunakan oleh pihak lain. Kemudian pertanyaan lain muncul? bagaimana implementasinya di cluster big data? Well, pada artikel kali ini akan kita bahas tentang bagaimana membuat sebuah API untuk model Machine Learning menggunakan Apache Livy sebagai platform API, Apache Spark sebagai sistem komputasi terdistribusi, dan Hadoop File System sebagai sistem repository.

Tentang Apache Livy

Apache Livy merupakan salah satu project inkubasi di inkubasi Apache Foundation. Fitur utama dari Livy sendiri adalah menyediakan platform bagi para engineer untuk membuat sebuah REST Service yang memungkinkan sebuah sistem/aplikasi untuk bisa berinteraksi dengan, dan menggunakan resource komputasi Apache Spark.

Arsitektur Apache Livy

Terdapat beberapa cara teknik deployment dan cara interaksi Apache Livy dan Apache Spark, di antaranya adalah model batch dan model interaktif. Pada artikel ini akan dicoba pada penggunaan model interaktif, seperti halnya kita menggunakan interpreter Python ataupun notebook seperti Jupyter.

Menyiapkan Environment

Anda bisa mendownload binary Apache Livy dari tautan yang disediakan pada homepage Apache Livy, https://livy.incubator.apache.org/get-started/. Sebelumnya, pastikan SPARK_HOME dan JAVA_HOME sudah dikonfigurasi dari awal di environment variable. Untuk bisa memulai service Livy anda bisa menjalankan command di bawah ini

$ bin/livy-server start

Jika tidak terdapat pesan error, buka browser dan arahkan ke alamat IP dan port 8998

Tampilan awal Apache Livy

Create Session

Penggunaan session ini berguna untuk mengisolasi resource yang digunakan pada cluster Spark. Untuk memulai menjalankan cluster, dengan menggunakan curl jalankan perintah di bawah ini untuk mengirim REST request pada server Livy.

curl -X POST --data '{"kind": "pyspark"}' -H "Content-Type: application/json" localhost:8998/sessions

Di mana localhost di sini bisa juga diganti dengan IP Address dari server Livy. Apabila sukses, session yang baru saja dibuat akan terlihat pada dashboard Apache Livy dan Spark WebUI.

Status session yang baru saja dibuat, tunggu sampai status berubah menjadi idle

Untuk Spark Web UI sendiri dapat diakses pada alamat http://ip-address:8888

Status session Livy yang baru saja dibbuat

Show Time

Untuk mencoba fitur dari Livy mungkin kita bisa mencoba dengan mengeksekusi statement yang simple, yaitu perhitungan Pi. Kita akan coba membuat sebuah fungsi yang akan diekspos menjadi sebuah REST Web Method untuk menghitung nilai Pi. Namun karena yang akan dikirim ke Livy adalah bentuk potongan program, maka kita perlu aplikasi REST Web Client seperti Postman atau Boomerang untuk mengemulasi proses ini.

Pada Postman, set url ke ‘http://192.168.0.102:8998/sessions/1’, di mana sessions/1 menunjukkan id session tempat kita akan mengeksekusi script method. Sedangkan pada body message pilih opsi raw untuk menampilkan konten dari body message. Isi dengan potongan kode berikut:

{'code': '\nimport random\nNUM_SAMPLES = 100000\ndef sample(p):\n  x, y = random.random(), random.random()\n  return 1 if x*x + y*y < 1 else 0\n\ncount = sc.parallelize(range( NUM_SAMPLES)).map(sample).reduce(lambda a, b: a + b)\nprint("Pi is roughly %f" % (4.0 * count / NUM_SAMPLES))\n'}

Potongan kode di atas bisa dibuat pada text editor dan untuk formatting seperti di atas bisa menggunakan textwrap. Potongan kode asli:

import random
NUM_SAMPLES = 100000
def sample(p):
x, y = random.random(), random.random()
return 1 if x*x + y*y < 1 else 0
count = sc.parallelize(range( NUM_SAMPLES)).map(sample).reduce(lambda a, b: a + b)
print("Pi is roughly %f" % (4.0 * count / NUM_SAMPLES))
Contoh pengiriman request pada Postman

Melihat Hasil Eksekusi

Response dari Livy kurang lebih akan terlihat seperti ini

{'code': '\n'
'import random\n'
'NUM_SAMPLES = 100000\n'
'def sample(p):\n'
' x, y = random.random(), random.random()\n'
' return 1 if x*x + y*y < 1 else 0\n'
'\n'
'count = sc.parallelize(range( '
'NUM_SAMPLES)).map(sample).reduce(lambda a, b: a + b)\n'
'print("Pi is roughly %f" % (4.0 * count / NUM_SAMPLES))\n',
'id': 0,
'output': None,
'progress': 0.0,
'state': 'waiting'}

Bisa dilihat terdapat status ‘waiting’ artinya proses sedang dieksekusi di Apache Spark.

Hasil eksekusi juga bisa dilihat pada dashboard Livy.

Semua hasil output return dari eksekusi kode kita dapat terlihat di dashboard Livy

Atau bisa juga kita baca melalui REST request, dari Postman

http://192.168.0.102:8998/sessions/1/statements/1#Response:
{
"id": 1,
"code": "\nimport random\nNUM_SAMPLES = 100000\ndef sample(p):\n x, y = random.random(), random.random()\n return 1 if x*x + y*y < 1 else 0\n\ncount = sc.parallelize(range( NUM_SAMPLES)).map(sample).reduce(lambda a, b: a + b)\nprint(\"Pi is roughly %f\" % (4.0 * count / NUM_SAMPLES))\n",
"state": "available",
"output": {
"status": "ok",
"execution_count": 1,
"data": {
"text/plain": "Pi is roughly 3.144400"
}
},
"progress": 1
}

Integrasi dengan Model Machine Learning

Untuk integrasi dengan Machine Learning, kita bisa gunakan model Logistic Regression untuk prediksi keganasa kanker, yang sudah dibahas pada tutorial ini https://medium.com/@planet.pintar/membuat-model-logistic-regression-di-apache-spark-4a2c31f34146.

Di sini kita akan mengirim sebuah data baru untuk diprediksi. Berikut potongan kodenya.

from pyspark.ml.classification import LogisticRegressionModel
from pyspark.ml.feature import VectorAssembler
import pandas as pd
lr = LogisticRegressionModel.load("/home/ilmuwan/Projects/lr_model.spark")test_data = {"irradiat_index":[1.0],
"node-caps_index":[2.0],
"inv-nodes_index":[3.0],
"deg-malig_index":[2.0],
"tumor-size_index":[4.0],
"age_index":[2.0],
"menopause_index":[1.0],
"breast-quad_index":[2.0],
"breast_index":[1.0]}
df_test_data = pd.DataFrame(test_data)
sdf_test_data = spark.createDataFrame(df_test_data)
vectorAssembler = VectorAssembler()
vectorAssembler = vectorAssembler.setInputCols(sdf_test_data.columns).setOutputCol("features")
sdf_test_data_transformed = vectorAssembler.transform(sdf_test_data)
result = lr.transform(sdf_test_data_transformed)
print(result.toJSON().collect()[0])

Sama dengan contoh perhitungan Pi di atas atur kode dengan library textwrap, dan jalankan di Postman.

Dapat dilihat di kolom output, hasil prediksi dari model Machine Learning

Lalu, apabila method sudah dideploy pada Livy, apakah perlu kita mendefinisikannya lagi? Jawabnya tidak, kita hanya perlu melakukan invoke terhadap method tersebut, sehingga kita dapat menghemat waktu dengan hanya memanggil method tersebut.

Tanpa menggunakan Postman, berikutnya anda bisa mengintegrasikan service API Livy ini dengan sistem/aplikasi buatan anda sendiri…Selamat mencoba!

--

--

Danau Data
Danau Data

No responses yet