Klasifikasi Teks Motivasi Dengan Pre-Trained Model Indobert Untuk Seleksi Peserta Bootcamp It

Klasifikasi Teks Motivasi Dengan Pre-Trained Model Indobert Untuk Seleksi Peserta Bootcamp It

Seleksi peserta dalam program pelatihan bertujuan untuk menjaring individu yang tepat dan berkomitmen. Pernyataan motivasi menjadi indikator penting dalam proses ini, namun klasifikasinya melalui teks masih jarang diterapkan. Penelitian ini memanfaatkan pendekatan NLP dengan metode CRISP-DM serta model IndoBERT untuk mengolah data berbahasa Indonesia. Hasilnya, model berhasil mengklasifikasikan motivasi dengan f1-score sebesar 87% pada konfigurasi batch size 16, learning rate 2e-5, dan 3 epoch, menunjukkan performa yang efektif pada data yang digunakan.

Seleksi peserta dalam program pelatihan bertujuan untuk menjaring individu yang tepat dan berkomitmen. Pernyataan motivasi menjadi indikator penting dalam proses ini, namun klasifikasinya melalui teks masih jarang diterapkan. Penelitian ini memanfaatkan pendekatan NLP dengan metode CRISP-DM serta model IndoBERT untuk mengolah data berbahasa Indonesia. Hasilnya, model berhasil mengklasifikasikan motivasi dengan f1-score sebesar 87% pada konfigurasi batch size 16, learning rate 2e-5, dan 3 epoch, menunjukkan performa yang efektif pada data yang digunakan.

Category

May 15, 2024

Data Science, NLP

Data Science, NLP

Services

May 15, 2024

Client

May 15, 2024

Bachelor Thesis Project

Bachelor Thesis Project

Year

May 15, 2024

2023

2023

Background

Natural Language Processing (NLP) adalah teknologi yang memungkinkan komputer memahami dan memproses bahasa manusia, baik dalam bentuk teks maupun suara. NLP menggabungkan linguistik komputasional, statistik, machine learning, dan deep learning. Teknologi ini semakin luas digunakan dalam berbagai sektor, seperti analisis sentimen, chatbot, hingga pengolahan data komunikasi.

Dalam konteks program pelatihan IT, seleksi calon peserta sangat penting untuk menjaring individu dengan motivasi tinggi yang mampu berkontribusi secara optimal. Salah satu indikator motivasi tersebut dikumpulkan melalui pernyataan dalam bentuk teks, biasanya diisi lewat Google Form. Karena jumlah pendaftar yang besar dan kuota terbatas, analisis otomatis terhadap motivasi peserta menjadi krusial. NLP memungkinkan klasifikasi motivasi dilakukan secara efisien berbasis data teks.

Proyek ini menggunakan model IndoBERT untuk klasifikasi, yaitu versi Bahasa Indonesia dari algoritma BERT (Bidirectional Encoder Representations from Transformers).

Goals

Penelitian ini bertujuan mengklasifikasikan motivasi calon peserta pelatihan IT menggunakan metode CRISP-DM dan model IndoBERT. Tujuan utamanya adalah:

  1. Menerapkan CRISP-DM dalam proses klasifikasi motivasi,

  2. Menentukan model IndoBERT terbaik untuk tugas tersebut, dan

  3. Mengevaluasi performa model berdasarkan akurasi dan f1-score.

Prosedur Pengerjaan

Business Understanding

Pada tahap ini dilakukan studi literatur terkait seleksi, motivasi, dan penerapan NLP guna membangun pemahaman bisnis (business understanding). NLP berperan dalam mengidentifikasi pola informasi dalam data teks, yang pada konteks ini digunakan untuk menganalisis pernyataan motivasi calon peserta pelatihan. Proses ini diharapkan dapat meningkatkan efisiensi seleksi dan membantu memperoleh sumber daya manusia yang sesuai.

Salah satu komponen penting dalam seleksi administrasi adalah penilaian terhadap pernyataan motivasi calon peserta. Dengan menyesuaikan program pelatihan berdasarkan motivasi peserta, pelatihan dapat lebih tepat sasaran dan relevan dengan kebutuhan mereka. Hal ini diharapkan dapat mendorong partisipasi aktif, menghasilkan umpan balik positif, serta membangun citra program yang baik di masyarakat. Pada akhirnya, keberhasilan ini dapat mendorong pelaksanaan program pelatihan secara berkelanjutan.

Data Understanding

Setelah tahap pemahaman bisnis, langkah selanjutnya adalah memahami data yang digunakan. Penelitian ini menggunakan 3.024 data teks berupa pernyataan motivasi yang diperoleh dari formulir pendaftaran Coding Camp di Jawa Barat melalui Google Form.

Pengumpulan Data

Penelitian ini menggunakan studi kasus seleksi peserta program pelatihan IT dengan fokus pada analisis tingkat motivasi calon peserta. Karena keterbatasan kuota, panitia menilai pernyataan motivasi sebagai bagian dari seleksi administrasi untuk memastikan kecocokan peserta dengan kriteria program.

Data yang digunakan berasal dari pendaftaran Coding Camp di Jawa Barat, dikumpulkan melalui Google Form dan diunduh dalam format Excel. Selanjutnya, hanya kolom berisi pernyataan motivasi yang digunakan untuk analisis, sementara kolom lain yang tidak relevan dihapus.

Data Preparation

Pada tahap ini dilakukan pelabelan dan preprocessing data sebagai persiapan menuju proses pemodelan. Pelabelan bertujuan memberi kategori pada data, sementara preprocessing mencakup pembersihan dan penyesuaian format agar data siap dianalisis. Langkah ini penting untuk memastikan kualitas data yang baik sehingga model dapat menghasilkan output yang optimal.

Data Labelling

Tahap pelabelan dilakukan setelah memahami data, dengan tujuan mengklasifikasikan tingkat motivasi peserta menjadi tiga kategori: kuat, sedang, dan lemah. Pelabelan ini mengacu pada teori motivasi intrinsik dan ekstrinsik. Motivasi intrinsik—seperti keinginan untuk belajar atau meningkatkan keterampilan—dikategorikan sebagai motivasi kuat, sedangkan motivasi ekstrinsik—seperti dorongan ekonomi atau mencari pekerjaan—masuk dalam motivasi lemah. Kategori sedang digunakan untuk motivasi intrinsik yang tidak sesuai dengan kriteria utama program.

Data yang digunakan berasal dari formulir pendaftaran Candradimuka Jabar Coding Camp. Proses pelabelan mengacu pada beberapa sumber, termasuk situs careerkarma.com dan laman resmi jabarcodingcamp.jabarprov.go.id, yang memuat kriteria peserta seperti komitmen, minat terhadap teknologi, dan kesiapan mengikuti program secara penuh.

Contoh pelabelan:

  • "Saya ingin meningkatkan skill di bidang programming" → Kuat

  • "Ingin mendapatkan pekerjaan" → Lemah

  • "Ingin berkontribusi untuk bangsa" → Sedang

Pelabelan ini menjadi dasar dalam proses klasifikasi motivasi menggunakan NLP.

Data Preprocessing

Tahap preprocessing dalam penelitian ini mencakup beberapa langkah utama untuk membersihkan dan menyiapkan data teks agar siap diproses oleh model. Tahapan tersebut meliputi:

  1. Casefolding
    Mengubah seluruh huruf dalam teks menjadi huruf kecil untuk menyeragamkan data dan menghindari duplikasi kata berdasarkan kapitalisasi.


    code:
    df_motivasi['motivasi'] = df_motivasi['motivasi'].astype(str)
    df_motivasi['motivasi'] = df_motivasi['motivasi'].str.lower()


  2. Remove Noise
    Menghapus elemen tidak relevan seperti tautan, angka, tanda baca, karakter tunggal, serta kata-kata yang tidak memiliki makna penting, guna memperoleh data yang bersih dan representatif.


    Code:
    import string
    import re
    from nltk.tokenize import word_tokenize
    from nltk.probability import FreqDist
    
    def remove_links(text):
        # menghapus tab, new line, ans back slice
        text = text.replace('\\t'," ").replace('\\n'," ").replace('\\u'," ").replace('\\',"")
        # menghapus non ASCII (emoticon, chinese word, .etc)
        text = text.encode('ascii', 'replace').decode('ascii')
        # menghapus mention, link, hashtag
        text = ' '.join(re.sub("([@#][A-Za-z0-9]+)|(\w+:\/\/\S+)"," ", text).split())
        # menghapus URL
        return text.replace("http://", " ").replace("https://", " ")
    df_motivasi['motivasi'] = df_motivasi['motivasi'].apply(remove_links)
    
    #menghapus number
    def remove_number(text):
        return  re.sub(r"\d+", " ", text)
    df_motivasi['motivasi'] = df_motivasi['motivasi'].apply(remove_number)
    
    #menghapus punctuation
    def remove_punctuation(text):
        return text.translate(str.maketrans("","",string.punctuation))
    
    df_motivasi['motivasi'] = df_motivasi['motivasi'].apply(remove_punctuation)
    
    # menghapus single char
    def remove_singl_char(text):
        return re.sub(r"\b[a-zA-Z]\b", " ", text)
    
    df_motivasi['motivasi'] = df_motivasi['motivasi'].apply(remove_singl_char)
    
    # menghapus single char
    def remove_singl_char(text):
        return re.sub(r"\b[a-zA-Z]\b", " ", text)
    
    df_motivasi['motivasi'] = df_motivasi['motivasi'].apply(remove_singl_char)



  3. Tokenizing
    Memecah teks menjadi unit-unit kecil yang disebut token, seperti kata atau frasa, yang memudahkan proses analisis lebih lanjut.


    Code:
    # Tokenisasi
    def word_tokenize_wrapper(text):
        return word_tokenize(text)
    
    df_motivasi['motivasi_tokenize'] = df_motivasi['motivasi'].apply(word_tokenize_wrapper


  4. Stopword Removal
    Menghilangkan kata-kata umum (seperti "dan", "adalah", "yang") yang tidak memberikan kontribusi signifikan terhadap pemahaman konteks teks, agar fokus pada kata kunci lebih relevan.


    Code:

    from nltk.corpus import stopwords
    list_stopwords = stopwords.words('indonesian')
    #remove stopword pada list token
    def stopwords_removal(words):
        return [word for word in words if word not in list_stopwords]
    
    df_motivasi['motivasi_stop_removed'] = df_motivasi['motivasi_normalized'].apply(stopwords_removal)
    data_sementara['motivasi_stop_removed'] = data_sementara['motivasi_normalized'].apply(stopwords_removal)


  5. Stemming
    Mengubah kata ke bentuk dasarnya dengan menghapus awalan atau akhiran, sehingga variasi kata dengan akar yang sama bisa disederhanakan, memperkuat konsistensi dalam analisis.


    Code:

    pip install Sastrawi
    pip install swifter
    
    # import Sastrawi package
    from Sastrawi.Stemmer.StemmerFactory import StemmerFactory
    import swifter
    
    
    # create stemmer
    factory = StemmerFactory()
    stemmer = factory.create_stemmer()
    
    # stemmed
    def stemmed_wrapper(term):
        return stemmer.stem(term)
    
    term_dict = {}
    
    for document in df_motivasi['motivasi_stop_removed']:
        for term in document:
            if term not in term_dict:
                term_dict[term] = ' '
    
    
    print(len(term_dict))
    print("------------------------")
    
    for term in term_dict:
        term_dict[term] = stemmed_wrapper(term)
        print(term,":" ,term_dict[term])
    
    print(term_dict)
    print("------------------------")
    
    
    # apply stemmed term to dataframe
    def get_stemmed_term(document):
        return [term_dict[term] for term in document]
    
    df_motivasi['motivasi_stemmed'] = df_motivasi['motivasi_stop_removed'].swifter.apply(get_stemmed_term)
    data_sementara['motivasi_stemmed'] = data_sementara['motivasi_stop_removed'].swifter.apply(get_stemmed_term)

Setiap tahap dilakukan untuk meningkatkan kualitas data teks sehingga model klasifikasi dapat bekerja lebih efektif dan menghasilkan hasil yang lebih akurat.

Modelling

Setelah data melalui tahap preprocessing dan pelabelan, proses dilanjutkan dengan Exploratory Data Analysis (EDA) untuk melihat distribusi label motivasi (kuat, sedang, lemah). Data kemudian dibagi menjadi data latih (80%) dan validasi (20%), lalu data validasi dibagi lagi menjadi data validasi (80%) dan tes (20%), dari total 3024 data teks.

Selanjutnya, dilakukan pemodelan menggunakan IndoBERT (varian IndoBERTBASE P2 - uncased) sebagai model pre-trained karena relevan dengan bahasa Indonesia. Model ini diakses menggunakan library Transformers dari Huggingface, yang memungkinkan proses NLP berbasis BERT di Python.

Tokenisasi dan Word Embedding

Data yang telah dibersihkan diubah ke format input IndoBERT menggunakan tokenizer indobenchmark/indobert-base-p2. Tokenisasi penting karena pre-trained model hanya menerima input sesuai kamus aslinya. Script utama menggunakan AutoTokenizer dari Huggingface. Sebelum model dilatih, data perlu disesuaikan dengan input format BERT.:

  • Tokenisasi dengan BERT tokenizer.

  • Penambahan token khusus seperti [CLS], [SEP], dan [PAD].

  • Konversi token ke ID berdasarkan kamus BERT.

  • Penambahan segment embedding untuk membedakan bagian input dan padding.

Load Model

Model pre-trained IndoBERT dimuat menggunakan AutoModelForSequenceClassification dengan 3 label kelas (kuat, sedang, lemah).

Fine-Tuning IndoBERT

Proses fine-tuning dilakukan dengan library Transformers melalui konfigurasi TrainingArguments. Parameter yang disetel meliputi:

  • Epochs: 3 atau 10

  • Batch size: 8 dan 16

  • Learning rate: 2e-5 dan 2e-3

  • Evaluation strategy: per epoch

  • Logging: setiap 100 langkah

Tujuan fine-tuning adalah mengadaptasi IndoBERT pada tugas klasifikasi motivasi berdasarkan data yang telah diberi label.

Proses pemantauan dilakukan dengan melihat nilai akurasi dan loss. Kombinasi hyperparameter yang optimal ditentukan berdasarkan performa model selama training.

Code:

from datasets import load_dataset

files = {
    "train": "train.csv",
    "eval": "eval.csv",
    "test": "test.csv",
}

dataset = load_dataset('csv', data_files=files)

from transformers import AutoTokenizer

print('Loading BERT tokenizer...')
tokenizer = AutoTokenizer.from_pretrained("indobenchmark/indobert-base-p2")

def tokenize_function(text):
    return tokenizer(text["text"], padding='max_length', max_length=256)

tokenized_datasets = dataset.map(tokenize_function, batched=True)
from datasets import concatenate_datasets, Dataset

train_data = pd.DataFrame(concatenate_datasets([train_dataset, eval_dataset]))
train_data.head()

import torch
torch.cuda.empty_cache()

device = "cuda:0" if torch.cuda.is_available() else "cpu"
device

model = AutoModelForSequenceClassification.from_pretrained("indobenchmark/indobert-base-p2", num_labels=3)
model

from transformers import TrainingArguments

training_args = TrainingArguments(
    #"test_trainer",
    output_dir="./results",  # Direktori output hasil pelatihan
    num_train_epochs=3,      # Jumlah epoch pelatihan
    per_device_train_batch_size=16,  # Ukuran batch pelatihan
    per_device_eval_batch_size=16,   # Ukuran batch evaluasi
    warmup_steps=100,        # Jumlah langkah pemanasan
    learning_rate=2e-5,      # Learning rate yang disesuaikan
    logging_dir="./logs",    # Direktori logging
    logging_steps=100,
    evaluation_strategy="epoch"
)

#from sklearn.metrics import precision_score, recall_score, f1_score, accuracy_score

metric = load_metric("accuracy")

def compute_metrics(eval_pred):
    logits, labels = eval_pred
    predictions = np.argmax(logits, axis=-1)

    return metric.compute(predictions=predictions, references=labels)

torch.cuda.empty_cache()

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=train_dataset,
    eval_dataset=eval_dataset,
    compute_metrics=compute_metrics,
)

training_history = trainer.train()
#training_history
Hasil dari Pelatihan dan Modelling

Setelah pembagian data selesai, tahap modelling dimulai dengan tokenisasi, load model, fine-tuning, hingga evaluasi hasil pelatihan.

Beberapa kombinasi hyperparameter diuji untuk menemukan performa terbaik. Berikut hasil utama:

✅ Kombinasi Terbaik

  • Batch Size 8, Learning Rate 2e-5, Epoch 3
    Akurasi mencapai 86% dengan training loss dan validation loss yang cukup stabil.

  • Batch Size 16, Learning Rate 2e-5, Epoch 3
    Akurasi hingga 87% dan tidak menunjukkan tanda overfitting signifikan.

⚠️ Potensi Overfitting

  • Epoch 10 (baik batch size 8 maupun 16) menunjukkan penurunan training loss tapi kenaikan validation loss, menandakan overfitting.

❌ Kombinasi Kurang Baik

  • Learning Rate 2e-3, Batch Size 8, Epoch 3
    Akurasi hanya sekitar 37%, menunjukkan model gagal generalisasi dengan baik.

Kesimpulan

Konfigurasi batch size 8 atau 16, learning rate 2e-5, dan epoch 3 adalah pilihan paling optimal untuk tugas klasifikasi motivasi menggunakan IndoBERT. Penggunaan epoch terlalu tinggi atau learning rate besar dapat menurunkan performa karena overfitting atau pembelajaran yang terlalu agresif.

Evaluasi Kinerja Model IndoBERT

Setelah proses pelatihan, model dievaluasi terhadap data validasi dan tes menggunakan berbagai kombinasi hyperparameter. Evaluasi dilakukan dengan metrik Precision, Recall, F1-Score, dan Confusion Matrix untuk tiap kelas: Lemah, Sedang, dan Kuat.

test_dataset = tokenized_datasets["test"]

prediction = trainer.predict(test_dataset)
prediction = prediction.predictions.argmax(1)

print(classification_report(prediction, actual_label, target_names=["Lemah", "Sedang", "Kuat"]))

def show_confusion_matrix(confusion_matrix):
        hmap = sns.heatmap(confusion_matrix, annot=True, fmt="d", cmap="Blues")
        hmap.yaxis.set_ticklabels(hmap.yaxis.get_ticklabels(), rotation=0, ha='right')
        hmap.xaxis.set_ticklabels(hmap.xaxis.get_ticklabels(), rotation=30, ha='right')

        plt.ylabel('True Label')
        plt.xlabel('Predicted Label')

cm = confusion_matrix(prediction, actual_label)
show_confusion_matrix(cm)

df_hasil=pd.DataFrame({
    'Teks Validasi': df_test['text'],
    'Label Sebenarnya': actual_label,
    'Hasil Prediksi Model': prediction
})

# Kategorikan label dengan dictionary
label_mapping = {2: 'Kuat', 0: 'Sedang', 1: 'Lemah'}

# Mengganti nilai dalam kolom "Label Sebenarnya" dan "Hasil Prediksi Model" dengan kategori yang sesuai
df_hasil['Label Sebenarnya'] = df_hasil['Label Sebenarnya'].replace(label_mapping)
df_hasil['Hasil Prediksi Model'] = df_hasil['Hasil Prediksi Model'].replace(label_mapping)

# Buat kolom baru "Benar" yang menunjukkan apakah prediksi benar atau salah
df_hasil['Benar'] = (df_hasil['Label Sebenarnya'] == df_hasil['Hasil Prediksi Model'])

# Menampilkan DataFrame dengan kolom "Benar" yang menunjukkan apakah prediksi benar atau salah
df_hasil.head()
🔎 Evaluasi pada Pengaturan Terbaik: Lr = 2e-5, Batch Size = 8
  • Epoch 3

    • F1-Score rata-rata: 86% (baik pada data tes & validasi)

    • Kelas Lemah dan Kuat: Akurasi tinggi

    • Kelas Sedang: Performa lebih rendah

  • Epoch 10

    • F1-Score menurun: 83% (tes), 84% (validasi)

    • Tanda-tanda overfitting, terutama pada kelas Sedang

✅ Kesimpulan: Epoch 3 lebih stabil dan akurat dibandingkan Epoch 10.

🔎 Evaluasi pada Batch Size = 16, Lr = 2e-5
  • Epoch 3

    • F1-Score rata-rata: 85–87%

    • Semua kelas terprediksi dengan cukup baik, terutama Lemah dan Kuat

  • Epoch 10 (Tabel 4.11 & 4.13)

    • F1-Score sedikit menurun ke 83–84%

    • Kelas Sedang tetap jadi titik lemah model

✅ Kesimpulan: Batch size 16 dan epoch 3 juga cukup optimal, dengan akurasi setara batch size 8.

⚠️ Evaluasi pada Lr = 2e-3, Batch Size = 8, Epoch 3
  • F1-Score sangat rendah: 44% (tes) dan 38% (validasi)

  • Hanya kelas Kuat yang berhasil diprediksi, sisanya gagal total

  • Precision 1.00 tetapi recall sangat rendah (underfitting)

  • Kelas Lemah dan Sedang tidak terdeteksi sama sekali

❌ Kesimpulan: Learning rate terlalu tinggi → model gagal belajar dengan baik

📌 Kesimpulan Umum
  • Model paling stabil dan akurat saat menggunakan:

    • Learning rate: 2e-5

    • Batch size: 8 atau 16

    • Epoch: 3

  • Kelas "Sedang" secara konsisten memiliki performa terendah → kemungkinan besar disebabkan oleh jumlah data yang tidak seimbang

  • Epoch 10 cenderung menyebabkan overfitting, terutama terlihat dari turunnya performa pada kelas Sedang

  • Learning rate 2e-3 terlalu tinggi dan menyebabkan underfitting, model hanya bisa memprediksi satu kelas saja

Deployment

Setelah proses modelling, tahap deployment dilakukan dengan mengintegrasikan model ke dalam lingkungan operasional, seperti website.

Implementasi Halaman

Halaman beranda dirancang untuk memberikan informasi lengkap tentang fungsi dan cara penggunaan aplikasi, sekaligus memungkinkan pengguna langsung melakukan prediksi dari kalimat motivasi yang dimasukkan.

Code:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Text Motivation Analyzer</title>
    <link
      href="https://fonts.googleapis.com/css?family=Pacifico"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://fonts.googleapis.com/css?family=Arimo"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://fonts.googleapis.com/css?family=Hind:300"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300"
      rel="stylesheet"
      type="text/css"
    />
    <link rel="stylesheet" href="../static/style.css" />
  </head>

  <body style="background: whitesmoke">
    <header>
      <img class="logo" src="../static/logo.png" alt="logo" href="index.html" />
      <!--<nav>
        <ul class="nav_links">
          <li><a href="index.html">Home</a></li>
          <li><a href="#">About</a></li>
        </ul>
      </nav> -->
    </header>
    <div class="login">
      <h1>Text Motivation Analyzer</h1>
      <p class="desc">
        Welcome to "Motivation Classification Website"! We are an online
        platform dedicated to studying, analyzing, and classifying various types
        of motivation. Our main goal is to provide deep insights and
        understanding into motivation in various contexts in IT Bootcamp.Type a
        motivation sentence, click on the submit button and wait for your
        prediction.
      </p>

      <!-- Main Input For Receiving Query to our ML -->

      <form action="/predict" method="post">
        <input
          type="text"
          name="text"
          placeholder="input text here"
          required="required"
        />
        <button type="submit" class="btn btn-primary btn-block btn-large">
          Predict the classification
        </button>
      </form>

      <br />
      <br />
      <h3 class="prediction_answer">{{ prediction_text }}</h3>
    </div>
  </body>
</html>

Pada halaman beranda, pengguna cukup memasukkan kalimat dan menekan tombol prediksi untuk mendapatkan hasil klasifikasi teks.

Code:

!pip install flask --quiet
!pip install flask-ngrok --quiet
!pip install transformers==4.28.0. --quiet
print("Completed!")

!wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.tgz
!tar -xvf /content/ngrok-stable-linux-amd64.tgz

!./ngrok authtoken 2Q9HsXd7zHIZa5Hek4qVsaJrXWZ_6pWh1cwMaxUUy6pCa8iqM

from transformers import Trainer
from transformers import AutoTokenizer
from transformers import AutoModelForSequenceClassification

from flask import Flask, render_template
from flask import request
from flask_ngrok import run_with_ngrok

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np

from google.colab import drive
drive.mount('/content/drive')

from logging import FileHandler, WARNING

app = Flask(__name__)
run_with_ngrok(app)

tokenizer = AutoTokenizer.from_pretrained("/content/drive/MyDrive/dataset/tokenizer")
model = AutoModelForSequenceClassification.from_pretrained("/content/drive/MyDrive/dataset/model")
trainer = Trainer(model=model)

@app.route('/')
def my_form():
  return render_template('index.html')

@app.route('/predict', methods=['POST'])
def my_form_post():
  text = request.form['text']
  tokenized = tokenizer(text, padding='max_length', max_length=256)
  label = trainer.predict([tokenized]).predictions.argmax(1)[0]
  if label == 0:
    prediction_text = f'Predicted: Lemah [{label}]'
    print(f'Predicted: Lemah [{label}]')
  elif label == 1:
    prediction_text = f'Predicted: Sedang [{label}]'
    print(f'Predicted: Sedang [{label}]')
  else:
    prediction_text = f'Predicted: Kuat [{label}]'
    print(f'Predicted: Kuat [{label}]')

  return render_template('index.html', prediction_text=prediction_text)

run_with_ngrok(app)
app.run()

Background

Natural Language Processing (NLP) adalah teknologi yang memungkinkan komputer memahami dan memproses bahasa manusia, baik dalam bentuk teks maupun suara. NLP menggabungkan linguistik komputasional, statistik, machine learning, dan deep learning. Teknologi ini semakin luas digunakan dalam berbagai sektor, seperti analisis sentimen, chatbot, hingga pengolahan data komunikasi.

Dalam konteks program pelatihan IT, seleksi calon peserta sangat penting untuk menjaring individu dengan motivasi tinggi yang mampu berkontribusi secara optimal. Salah satu indikator motivasi tersebut dikumpulkan melalui pernyataan dalam bentuk teks, biasanya diisi lewat Google Form. Karena jumlah pendaftar yang besar dan kuota terbatas, analisis otomatis terhadap motivasi peserta menjadi krusial. NLP memungkinkan klasifikasi motivasi dilakukan secara efisien berbasis data teks.

Proyek ini menggunakan model IndoBERT untuk klasifikasi, yaitu versi Bahasa Indonesia dari algoritma BERT (Bidirectional Encoder Representations from Transformers).

Goals

Penelitian ini bertujuan mengklasifikasikan motivasi calon peserta pelatihan IT menggunakan metode CRISP-DM dan model IndoBERT. Tujuan utamanya adalah:

  1. Menerapkan CRISP-DM dalam proses klasifikasi motivasi,

  2. Menentukan model IndoBERT terbaik untuk tugas tersebut, dan

  3. Mengevaluasi performa model berdasarkan akurasi dan f1-score.

Prosedur Pengerjaan

Business Understanding

Pada tahap ini dilakukan studi literatur terkait seleksi, motivasi, dan penerapan NLP guna membangun pemahaman bisnis (business understanding). NLP berperan dalam mengidentifikasi pola informasi dalam data teks, yang pada konteks ini digunakan untuk menganalisis pernyataan motivasi calon peserta pelatihan. Proses ini diharapkan dapat meningkatkan efisiensi seleksi dan membantu memperoleh sumber daya manusia yang sesuai.

Salah satu komponen penting dalam seleksi administrasi adalah penilaian terhadap pernyataan motivasi calon peserta. Dengan menyesuaikan program pelatihan berdasarkan motivasi peserta, pelatihan dapat lebih tepat sasaran dan relevan dengan kebutuhan mereka. Hal ini diharapkan dapat mendorong partisipasi aktif, menghasilkan umpan balik positif, serta membangun citra program yang baik di masyarakat. Pada akhirnya, keberhasilan ini dapat mendorong pelaksanaan program pelatihan secara berkelanjutan.

Data Understanding

Setelah tahap pemahaman bisnis, langkah selanjutnya adalah memahami data yang digunakan. Penelitian ini menggunakan 3.024 data teks berupa pernyataan motivasi yang diperoleh dari formulir pendaftaran Coding Camp di Jawa Barat melalui Google Form.

Pengumpulan Data

Penelitian ini menggunakan studi kasus seleksi peserta program pelatihan IT dengan fokus pada analisis tingkat motivasi calon peserta. Karena keterbatasan kuota, panitia menilai pernyataan motivasi sebagai bagian dari seleksi administrasi untuk memastikan kecocokan peserta dengan kriteria program.

Data yang digunakan berasal dari pendaftaran Coding Camp di Jawa Barat, dikumpulkan melalui Google Form dan diunduh dalam format Excel. Selanjutnya, hanya kolom berisi pernyataan motivasi yang digunakan untuk analisis, sementara kolom lain yang tidak relevan dihapus.

Data Preparation

Pada tahap ini dilakukan pelabelan dan preprocessing data sebagai persiapan menuju proses pemodelan. Pelabelan bertujuan memberi kategori pada data, sementara preprocessing mencakup pembersihan dan penyesuaian format agar data siap dianalisis. Langkah ini penting untuk memastikan kualitas data yang baik sehingga model dapat menghasilkan output yang optimal.

Data Labelling

Tahap pelabelan dilakukan setelah memahami data, dengan tujuan mengklasifikasikan tingkat motivasi peserta menjadi tiga kategori: kuat, sedang, dan lemah. Pelabelan ini mengacu pada teori motivasi intrinsik dan ekstrinsik. Motivasi intrinsik—seperti keinginan untuk belajar atau meningkatkan keterampilan—dikategorikan sebagai motivasi kuat, sedangkan motivasi ekstrinsik—seperti dorongan ekonomi atau mencari pekerjaan—masuk dalam motivasi lemah. Kategori sedang digunakan untuk motivasi intrinsik yang tidak sesuai dengan kriteria utama program.

Data yang digunakan berasal dari formulir pendaftaran Candradimuka Jabar Coding Camp. Proses pelabelan mengacu pada beberapa sumber, termasuk situs careerkarma.com dan laman resmi jabarcodingcamp.jabarprov.go.id, yang memuat kriteria peserta seperti komitmen, minat terhadap teknologi, dan kesiapan mengikuti program secara penuh.

Contoh pelabelan:

  • "Saya ingin meningkatkan skill di bidang programming" → Kuat

  • "Ingin mendapatkan pekerjaan" → Lemah

  • "Ingin berkontribusi untuk bangsa" → Sedang

Pelabelan ini menjadi dasar dalam proses klasifikasi motivasi menggunakan NLP.

Data Preprocessing

Tahap preprocessing dalam penelitian ini mencakup beberapa langkah utama untuk membersihkan dan menyiapkan data teks agar siap diproses oleh model. Tahapan tersebut meliputi:

  1. Casefolding
    Mengubah seluruh huruf dalam teks menjadi huruf kecil untuk menyeragamkan data dan menghindari duplikasi kata berdasarkan kapitalisasi.


    code:
    df_motivasi['motivasi'] = df_motivasi['motivasi'].astype(str)
    df_motivasi['motivasi'] = df_motivasi['motivasi'].str.lower()


  2. Remove Noise
    Menghapus elemen tidak relevan seperti tautan, angka, tanda baca, karakter tunggal, serta kata-kata yang tidak memiliki makna penting, guna memperoleh data yang bersih dan representatif.


    Code:
    import string
    import re
    from nltk.tokenize import word_tokenize
    from nltk.probability import FreqDist
    
    def remove_links(text):
        # menghapus tab, new line, ans back slice
        text = text.replace('\\t'," ").replace('\\n'," ").replace('\\u'," ").replace('\\',"")
        # menghapus non ASCII (emoticon, chinese word, .etc)
        text = text.encode('ascii', 'replace').decode('ascii')
        # menghapus mention, link, hashtag
        text = ' '.join(re.sub("([@#][A-Za-z0-9]+)|(\w+:\/\/\S+)"," ", text).split())
        # menghapus URL
        return text.replace("http://", " ").replace("https://", " ")
    df_motivasi['motivasi'] = df_motivasi['motivasi'].apply(remove_links)
    
    #menghapus number
    def remove_number(text):
        return  re.sub(r"\d+", " ", text)
    df_motivasi['motivasi'] = df_motivasi['motivasi'].apply(remove_number)
    
    #menghapus punctuation
    def remove_punctuation(text):
        return text.translate(str.maketrans("","",string.punctuation))
    
    df_motivasi['motivasi'] = df_motivasi['motivasi'].apply(remove_punctuation)
    
    # menghapus single char
    def remove_singl_char(text):
        return re.sub(r"\b[a-zA-Z]\b", " ", text)
    
    df_motivasi['motivasi'] = df_motivasi['motivasi'].apply(remove_singl_char)
    
    # menghapus single char
    def remove_singl_char(text):
        return re.sub(r"\b[a-zA-Z]\b", " ", text)
    
    df_motivasi['motivasi'] = df_motivasi['motivasi'].apply(remove_singl_char)



  3. Tokenizing
    Memecah teks menjadi unit-unit kecil yang disebut token, seperti kata atau frasa, yang memudahkan proses analisis lebih lanjut.


    Code:
    # Tokenisasi
    def word_tokenize_wrapper(text):
        return word_tokenize(text)
    
    df_motivasi['motivasi_tokenize'] = df_motivasi['motivasi'].apply(word_tokenize_wrapper


  4. Stopword Removal
    Menghilangkan kata-kata umum (seperti "dan", "adalah", "yang") yang tidak memberikan kontribusi signifikan terhadap pemahaman konteks teks, agar fokus pada kata kunci lebih relevan.


    Code:

    from nltk.corpus import stopwords
    list_stopwords = stopwords.words('indonesian')
    #remove stopword pada list token
    def stopwords_removal(words):
        return [word for word in words if word not in list_stopwords]
    
    df_motivasi['motivasi_stop_removed'] = df_motivasi['motivasi_normalized'].apply(stopwords_removal)
    data_sementara['motivasi_stop_removed'] = data_sementara['motivasi_normalized'].apply(stopwords_removal)


  5. Stemming
    Mengubah kata ke bentuk dasarnya dengan menghapus awalan atau akhiran, sehingga variasi kata dengan akar yang sama bisa disederhanakan, memperkuat konsistensi dalam analisis.


    Code:

    pip install Sastrawi
    pip install swifter
    
    # import Sastrawi package
    from Sastrawi.Stemmer.StemmerFactory import StemmerFactory
    import swifter
    
    
    # create stemmer
    factory = StemmerFactory()
    stemmer = factory.create_stemmer()
    
    # stemmed
    def stemmed_wrapper(term):
        return stemmer.stem(term)
    
    term_dict = {}
    
    for document in df_motivasi['motivasi_stop_removed']:
        for term in document:
            if term not in term_dict:
                term_dict[term] = ' '
    
    
    print(len(term_dict))
    print("------------------------")
    
    for term in term_dict:
        term_dict[term] = stemmed_wrapper(term)
        print(term,":" ,term_dict[term])
    
    print(term_dict)
    print("------------------------")
    
    
    # apply stemmed term to dataframe
    def get_stemmed_term(document):
        return [term_dict[term] for term in document]
    
    df_motivasi['motivasi_stemmed'] = df_motivasi['motivasi_stop_removed'].swifter.apply(get_stemmed_term)
    data_sementara['motivasi_stemmed'] = data_sementara['motivasi_stop_removed'].swifter.apply(get_stemmed_term)

Setiap tahap dilakukan untuk meningkatkan kualitas data teks sehingga model klasifikasi dapat bekerja lebih efektif dan menghasilkan hasil yang lebih akurat.

Modelling

Setelah data melalui tahap preprocessing dan pelabelan, proses dilanjutkan dengan Exploratory Data Analysis (EDA) untuk melihat distribusi label motivasi (kuat, sedang, lemah). Data kemudian dibagi menjadi data latih (80%) dan validasi (20%), lalu data validasi dibagi lagi menjadi data validasi (80%) dan tes (20%), dari total 3024 data teks.

Selanjutnya, dilakukan pemodelan menggunakan IndoBERT (varian IndoBERTBASE P2 - uncased) sebagai model pre-trained karena relevan dengan bahasa Indonesia. Model ini diakses menggunakan library Transformers dari Huggingface, yang memungkinkan proses NLP berbasis BERT di Python.

Tokenisasi dan Word Embedding

Data yang telah dibersihkan diubah ke format input IndoBERT menggunakan tokenizer indobenchmark/indobert-base-p2. Tokenisasi penting karena pre-trained model hanya menerima input sesuai kamus aslinya. Script utama menggunakan AutoTokenizer dari Huggingface. Sebelum model dilatih, data perlu disesuaikan dengan input format BERT.:

  • Tokenisasi dengan BERT tokenizer.

  • Penambahan token khusus seperti [CLS], [SEP], dan [PAD].

  • Konversi token ke ID berdasarkan kamus BERT.

  • Penambahan segment embedding untuk membedakan bagian input dan padding.

Load Model

Model pre-trained IndoBERT dimuat menggunakan AutoModelForSequenceClassification dengan 3 label kelas (kuat, sedang, lemah).

Fine-Tuning IndoBERT

Proses fine-tuning dilakukan dengan library Transformers melalui konfigurasi TrainingArguments. Parameter yang disetel meliputi:

  • Epochs: 3 atau 10

  • Batch size: 8 dan 16

  • Learning rate: 2e-5 dan 2e-3

  • Evaluation strategy: per epoch

  • Logging: setiap 100 langkah

Tujuan fine-tuning adalah mengadaptasi IndoBERT pada tugas klasifikasi motivasi berdasarkan data yang telah diberi label.

Proses pemantauan dilakukan dengan melihat nilai akurasi dan loss. Kombinasi hyperparameter yang optimal ditentukan berdasarkan performa model selama training.

Code:

from datasets import load_dataset

files = {
    "train": "train.csv",
    "eval": "eval.csv",
    "test": "test.csv",
}

dataset = load_dataset('csv', data_files=files)

from transformers import AutoTokenizer

print('Loading BERT tokenizer...')
tokenizer = AutoTokenizer.from_pretrained("indobenchmark/indobert-base-p2")

def tokenize_function(text):
    return tokenizer(text["text"], padding='max_length', max_length=256)

tokenized_datasets = dataset.map(tokenize_function, batched=True)
from datasets import concatenate_datasets, Dataset

train_data = pd.DataFrame(concatenate_datasets([train_dataset, eval_dataset]))
train_data.head()

import torch
torch.cuda.empty_cache()

device = "cuda:0" if torch.cuda.is_available() else "cpu"
device

model = AutoModelForSequenceClassification.from_pretrained("indobenchmark/indobert-base-p2", num_labels=3)
model

from transformers import TrainingArguments

training_args = TrainingArguments(
    #"test_trainer",
    output_dir="./results",  # Direktori output hasil pelatihan
    num_train_epochs=3,      # Jumlah epoch pelatihan
    per_device_train_batch_size=16,  # Ukuran batch pelatihan
    per_device_eval_batch_size=16,   # Ukuran batch evaluasi
    warmup_steps=100,        # Jumlah langkah pemanasan
    learning_rate=2e-5,      # Learning rate yang disesuaikan
    logging_dir="./logs",    # Direktori logging
    logging_steps=100,
    evaluation_strategy="epoch"
)

#from sklearn.metrics import precision_score, recall_score, f1_score, accuracy_score

metric = load_metric("accuracy")

def compute_metrics(eval_pred):
    logits, labels = eval_pred
    predictions = np.argmax(logits, axis=-1)

    return metric.compute(predictions=predictions, references=labels)

torch.cuda.empty_cache()

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=train_dataset,
    eval_dataset=eval_dataset,
    compute_metrics=compute_metrics,
)

training_history = trainer.train()
#training_history
Hasil dari Pelatihan dan Modelling

Setelah pembagian data selesai, tahap modelling dimulai dengan tokenisasi, load model, fine-tuning, hingga evaluasi hasil pelatihan.

Beberapa kombinasi hyperparameter diuji untuk menemukan performa terbaik. Berikut hasil utama:

✅ Kombinasi Terbaik

  • Batch Size 8, Learning Rate 2e-5, Epoch 3
    Akurasi mencapai 86% dengan training loss dan validation loss yang cukup stabil.

  • Batch Size 16, Learning Rate 2e-5, Epoch 3
    Akurasi hingga 87% dan tidak menunjukkan tanda overfitting signifikan.

⚠️ Potensi Overfitting

  • Epoch 10 (baik batch size 8 maupun 16) menunjukkan penurunan training loss tapi kenaikan validation loss, menandakan overfitting.

❌ Kombinasi Kurang Baik

  • Learning Rate 2e-3, Batch Size 8, Epoch 3
    Akurasi hanya sekitar 37%, menunjukkan model gagal generalisasi dengan baik.

Kesimpulan

Konfigurasi batch size 8 atau 16, learning rate 2e-5, dan epoch 3 adalah pilihan paling optimal untuk tugas klasifikasi motivasi menggunakan IndoBERT. Penggunaan epoch terlalu tinggi atau learning rate besar dapat menurunkan performa karena overfitting atau pembelajaran yang terlalu agresif.

Evaluasi Kinerja Model IndoBERT

Setelah proses pelatihan, model dievaluasi terhadap data validasi dan tes menggunakan berbagai kombinasi hyperparameter. Evaluasi dilakukan dengan metrik Precision, Recall, F1-Score, dan Confusion Matrix untuk tiap kelas: Lemah, Sedang, dan Kuat.

test_dataset = tokenized_datasets["test"]

prediction = trainer.predict(test_dataset)
prediction = prediction.predictions.argmax(1)

print(classification_report(prediction, actual_label, target_names=["Lemah", "Sedang", "Kuat"]))

def show_confusion_matrix(confusion_matrix):
        hmap = sns.heatmap(confusion_matrix, annot=True, fmt="d", cmap="Blues")
        hmap.yaxis.set_ticklabels(hmap.yaxis.get_ticklabels(), rotation=0, ha='right')
        hmap.xaxis.set_ticklabels(hmap.xaxis.get_ticklabels(), rotation=30, ha='right')

        plt.ylabel('True Label')
        plt.xlabel('Predicted Label')

cm = confusion_matrix(prediction, actual_label)
show_confusion_matrix(cm)

df_hasil=pd.DataFrame({
    'Teks Validasi': df_test['text'],
    'Label Sebenarnya': actual_label,
    'Hasil Prediksi Model': prediction
})

# Kategorikan label dengan dictionary
label_mapping = {2: 'Kuat', 0: 'Sedang', 1: 'Lemah'}

# Mengganti nilai dalam kolom "Label Sebenarnya" dan "Hasil Prediksi Model" dengan kategori yang sesuai
df_hasil['Label Sebenarnya'] = df_hasil['Label Sebenarnya'].replace(label_mapping)
df_hasil['Hasil Prediksi Model'] = df_hasil['Hasil Prediksi Model'].replace(label_mapping)

# Buat kolom baru "Benar" yang menunjukkan apakah prediksi benar atau salah
df_hasil['Benar'] = (df_hasil['Label Sebenarnya'] == df_hasil['Hasil Prediksi Model'])

# Menampilkan DataFrame dengan kolom "Benar" yang menunjukkan apakah prediksi benar atau salah
df_hasil.head()
🔎 Evaluasi pada Pengaturan Terbaik: Lr = 2e-5, Batch Size = 8
  • Epoch 3

    • F1-Score rata-rata: 86% (baik pada data tes & validasi)

    • Kelas Lemah dan Kuat: Akurasi tinggi

    • Kelas Sedang: Performa lebih rendah

  • Epoch 10

    • F1-Score menurun: 83% (tes), 84% (validasi)

    • Tanda-tanda overfitting, terutama pada kelas Sedang

✅ Kesimpulan: Epoch 3 lebih stabil dan akurat dibandingkan Epoch 10.

🔎 Evaluasi pada Batch Size = 16, Lr = 2e-5
  • Epoch 3

    • F1-Score rata-rata: 85–87%

    • Semua kelas terprediksi dengan cukup baik, terutama Lemah dan Kuat

  • Epoch 10 (Tabel 4.11 & 4.13)

    • F1-Score sedikit menurun ke 83–84%

    • Kelas Sedang tetap jadi titik lemah model

✅ Kesimpulan: Batch size 16 dan epoch 3 juga cukup optimal, dengan akurasi setara batch size 8.

⚠️ Evaluasi pada Lr = 2e-3, Batch Size = 8, Epoch 3
  • F1-Score sangat rendah: 44% (tes) dan 38% (validasi)

  • Hanya kelas Kuat yang berhasil diprediksi, sisanya gagal total

  • Precision 1.00 tetapi recall sangat rendah (underfitting)

  • Kelas Lemah dan Sedang tidak terdeteksi sama sekali

❌ Kesimpulan: Learning rate terlalu tinggi → model gagal belajar dengan baik

📌 Kesimpulan Umum
  • Model paling stabil dan akurat saat menggunakan:

    • Learning rate: 2e-5

    • Batch size: 8 atau 16

    • Epoch: 3

  • Kelas "Sedang" secara konsisten memiliki performa terendah → kemungkinan besar disebabkan oleh jumlah data yang tidak seimbang

  • Epoch 10 cenderung menyebabkan overfitting, terutama terlihat dari turunnya performa pada kelas Sedang

  • Learning rate 2e-3 terlalu tinggi dan menyebabkan underfitting, model hanya bisa memprediksi satu kelas saja

Deployment

Setelah proses modelling, tahap deployment dilakukan dengan mengintegrasikan model ke dalam lingkungan operasional, seperti website.

Implementasi Halaman

Halaman beranda dirancang untuk memberikan informasi lengkap tentang fungsi dan cara penggunaan aplikasi, sekaligus memungkinkan pengguna langsung melakukan prediksi dari kalimat motivasi yang dimasukkan.

Code:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Text Motivation Analyzer</title>
    <link
      href="https://fonts.googleapis.com/css?family=Pacifico"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://fonts.googleapis.com/css?family=Arimo"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://fonts.googleapis.com/css?family=Hind:300"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300"
      rel="stylesheet"
      type="text/css"
    />
    <link rel="stylesheet" href="../static/style.css" />
  </head>

  <body style="background: whitesmoke">
    <header>
      <img class="logo" src="../static/logo.png" alt="logo" href="index.html" />
      <!--<nav>
        <ul class="nav_links">
          <li><a href="index.html">Home</a></li>
          <li><a href="#">About</a></li>
        </ul>
      </nav> -->
    </header>
    <div class="login">
      <h1>Text Motivation Analyzer</h1>
      <p class="desc">
        Welcome to "Motivation Classification Website"! We are an online
        platform dedicated to studying, analyzing, and classifying various types
        of motivation. Our main goal is to provide deep insights and
        understanding into motivation in various contexts in IT Bootcamp.Type a
        motivation sentence, click on the submit button and wait for your
        prediction.
      </p>

      <!-- Main Input For Receiving Query to our ML -->

      <form action="/predict" method="post">
        <input
          type="text"
          name="text"
          placeholder="input text here"
          required="required"
        />
        <button type="submit" class="btn btn-primary btn-block btn-large">
          Predict the classification
        </button>
      </form>

      <br />
      <br />
      <h3 class="prediction_answer">{{ prediction_text }}</h3>
    </div>
  </body>
</html>

Pada halaman beranda, pengguna cukup memasukkan kalimat dan menekan tombol prediksi untuk mendapatkan hasil klasifikasi teks.

Code:

!pip install flask --quiet
!pip install flask-ngrok --quiet
!pip install transformers==4.28.0. --quiet
print("Completed!")

!wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.tgz
!tar -xvf /content/ngrok-stable-linux-amd64.tgz

!./ngrok authtoken 2Q9HsXd7zHIZa5Hek4qVsaJrXWZ_6pWh1cwMaxUUy6pCa8iqM

from transformers import Trainer
from transformers import AutoTokenizer
from transformers import AutoModelForSequenceClassification

from flask import Flask, render_template
from flask import request
from flask_ngrok import run_with_ngrok

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np

from google.colab import drive
drive.mount('/content/drive')

from logging import FileHandler, WARNING

app = Flask(__name__)
run_with_ngrok(app)

tokenizer = AutoTokenizer.from_pretrained("/content/drive/MyDrive/dataset/tokenizer")
model = AutoModelForSequenceClassification.from_pretrained("/content/drive/MyDrive/dataset/model")
trainer = Trainer(model=model)

@app.route('/')
def my_form():
  return render_template('index.html')

@app.route('/predict', methods=['POST'])
def my_form_post():
  text = request.form['text']
  tokenized = tokenizer(text, padding='max_length', max_length=256)
  label = trainer.predict([tokenized]).predictions.argmax(1)[0]
  if label == 0:
    prediction_text = f'Predicted: Lemah [{label}]'
    print(f'Predicted: Lemah [{label}]')
  elif label == 1:
    prediction_text = f'Predicted: Sedang [{label}]'
    print(f'Predicted: Sedang [{label}]')
  else:
    prediction_text = f'Predicted: Kuat [{label}]'
    print(f'Predicted: Kuat [{label}]')

  return render_template('index.html', prediction_text=prediction_text)

run_with_ngrok(app)
app.run()

Background

Natural Language Processing (NLP) adalah teknologi yang memungkinkan komputer memahami dan memproses bahasa manusia, baik dalam bentuk teks maupun suara. NLP menggabungkan linguistik komputasional, statistik, machine learning, dan deep learning. Teknologi ini semakin luas digunakan dalam berbagai sektor, seperti analisis sentimen, chatbot, hingga pengolahan data komunikasi.

Dalam konteks program pelatihan IT, seleksi calon peserta sangat penting untuk menjaring individu dengan motivasi tinggi yang mampu berkontribusi secara optimal. Salah satu indikator motivasi tersebut dikumpulkan melalui pernyataan dalam bentuk teks, biasanya diisi lewat Google Form. Karena jumlah pendaftar yang besar dan kuota terbatas, analisis otomatis terhadap motivasi peserta menjadi krusial. NLP memungkinkan klasifikasi motivasi dilakukan secara efisien berbasis data teks.

Proyek ini menggunakan model IndoBERT untuk klasifikasi, yaitu versi Bahasa Indonesia dari algoritma BERT (Bidirectional Encoder Representations from Transformers).

Goals

Penelitian ini bertujuan mengklasifikasikan motivasi calon peserta pelatihan IT menggunakan metode CRISP-DM dan model IndoBERT. Tujuan utamanya adalah:

  1. Menerapkan CRISP-DM dalam proses klasifikasi motivasi,

  2. Menentukan model IndoBERT terbaik untuk tugas tersebut, dan

  3. Mengevaluasi performa model berdasarkan akurasi dan f1-score.

Prosedur Pengerjaan

Business Understanding

Pada tahap ini dilakukan studi literatur terkait seleksi, motivasi, dan penerapan NLP guna membangun pemahaman bisnis (business understanding). NLP berperan dalam mengidentifikasi pola informasi dalam data teks, yang pada konteks ini digunakan untuk menganalisis pernyataan motivasi calon peserta pelatihan. Proses ini diharapkan dapat meningkatkan efisiensi seleksi dan membantu memperoleh sumber daya manusia yang sesuai.

Salah satu komponen penting dalam seleksi administrasi adalah penilaian terhadap pernyataan motivasi calon peserta. Dengan menyesuaikan program pelatihan berdasarkan motivasi peserta, pelatihan dapat lebih tepat sasaran dan relevan dengan kebutuhan mereka. Hal ini diharapkan dapat mendorong partisipasi aktif, menghasilkan umpan balik positif, serta membangun citra program yang baik di masyarakat. Pada akhirnya, keberhasilan ini dapat mendorong pelaksanaan program pelatihan secara berkelanjutan.

Data Understanding

Setelah tahap pemahaman bisnis, langkah selanjutnya adalah memahami data yang digunakan. Penelitian ini menggunakan 3.024 data teks berupa pernyataan motivasi yang diperoleh dari formulir pendaftaran Coding Camp di Jawa Barat melalui Google Form.

Pengumpulan Data

Penelitian ini menggunakan studi kasus seleksi peserta program pelatihan IT dengan fokus pada analisis tingkat motivasi calon peserta. Karena keterbatasan kuota, panitia menilai pernyataan motivasi sebagai bagian dari seleksi administrasi untuk memastikan kecocokan peserta dengan kriteria program.

Data yang digunakan berasal dari pendaftaran Coding Camp di Jawa Barat, dikumpulkan melalui Google Form dan diunduh dalam format Excel. Selanjutnya, hanya kolom berisi pernyataan motivasi yang digunakan untuk analisis, sementara kolom lain yang tidak relevan dihapus.

Data Preparation

Pada tahap ini dilakukan pelabelan dan preprocessing data sebagai persiapan menuju proses pemodelan. Pelabelan bertujuan memberi kategori pada data, sementara preprocessing mencakup pembersihan dan penyesuaian format agar data siap dianalisis. Langkah ini penting untuk memastikan kualitas data yang baik sehingga model dapat menghasilkan output yang optimal.

Data Labelling

Tahap pelabelan dilakukan setelah memahami data, dengan tujuan mengklasifikasikan tingkat motivasi peserta menjadi tiga kategori: kuat, sedang, dan lemah. Pelabelan ini mengacu pada teori motivasi intrinsik dan ekstrinsik. Motivasi intrinsik—seperti keinginan untuk belajar atau meningkatkan keterampilan—dikategorikan sebagai motivasi kuat, sedangkan motivasi ekstrinsik—seperti dorongan ekonomi atau mencari pekerjaan—masuk dalam motivasi lemah. Kategori sedang digunakan untuk motivasi intrinsik yang tidak sesuai dengan kriteria utama program.

Data yang digunakan berasal dari formulir pendaftaran Candradimuka Jabar Coding Camp. Proses pelabelan mengacu pada beberapa sumber, termasuk situs careerkarma.com dan laman resmi jabarcodingcamp.jabarprov.go.id, yang memuat kriteria peserta seperti komitmen, minat terhadap teknologi, dan kesiapan mengikuti program secara penuh.

Contoh pelabelan:

  • "Saya ingin meningkatkan skill di bidang programming" → Kuat

  • "Ingin mendapatkan pekerjaan" → Lemah

  • "Ingin berkontribusi untuk bangsa" → Sedang

Pelabelan ini menjadi dasar dalam proses klasifikasi motivasi menggunakan NLP.

Data Preprocessing

Tahap preprocessing dalam penelitian ini mencakup beberapa langkah utama untuk membersihkan dan menyiapkan data teks agar siap diproses oleh model. Tahapan tersebut meliputi:

  1. Casefolding
    Mengubah seluruh huruf dalam teks menjadi huruf kecil untuk menyeragamkan data dan menghindari duplikasi kata berdasarkan kapitalisasi.


    code:
    df_motivasi['motivasi'] = df_motivasi['motivasi'].astype(str)
    df_motivasi['motivasi'] = df_motivasi['motivasi'].str.lower()


  2. Remove Noise
    Menghapus elemen tidak relevan seperti tautan, angka, tanda baca, karakter tunggal, serta kata-kata yang tidak memiliki makna penting, guna memperoleh data yang bersih dan representatif.


    Code:
    import string
    import re
    from nltk.tokenize import word_tokenize
    from nltk.probability import FreqDist
    
    def remove_links(text):
        # menghapus tab, new line, ans back slice
        text = text.replace('\\t'," ").replace('\\n'," ").replace('\\u'," ").replace('\\',"")
        # menghapus non ASCII (emoticon, chinese word, .etc)
        text = text.encode('ascii', 'replace').decode('ascii')
        # menghapus mention, link, hashtag
        text = ' '.join(re.sub("([@#][A-Za-z0-9]+)|(\w+:\/\/\S+)"," ", text).split())
        # menghapus URL
        return text.replace("http://", " ").replace("https://", " ")
    df_motivasi['motivasi'] = df_motivasi['motivasi'].apply(remove_links)
    
    #menghapus number
    def remove_number(text):
        return  re.sub(r"\d+", " ", text)
    df_motivasi['motivasi'] = df_motivasi['motivasi'].apply(remove_number)
    
    #menghapus punctuation
    def remove_punctuation(text):
        return text.translate(str.maketrans("","",string.punctuation))
    
    df_motivasi['motivasi'] = df_motivasi['motivasi'].apply(remove_punctuation)
    
    # menghapus single char
    def remove_singl_char(text):
        return re.sub(r"\b[a-zA-Z]\b", " ", text)
    
    df_motivasi['motivasi'] = df_motivasi['motivasi'].apply(remove_singl_char)
    
    # menghapus single char
    def remove_singl_char(text):
        return re.sub(r"\b[a-zA-Z]\b", " ", text)
    
    df_motivasi['motivasi'] = df_motivasi['motivasi'].apply(remove_singl_char)



  3. Tokenizing
    Memecah teks menjadi unit-unit kecil yang disebut token, seperti kata atau frasa, yang memudahkan proses analisis lebih lanjut.


    Code:
    # Tokenisasi
    def word_tokenize_wrapper(text):
        return word_tokenize(text)
    
    df_motivasi['motivasi_tokenize'] = df_motivasi['motivasi'].apply(word_tokenize_wrapper


  4. Stopword Removal
    Menghilangkan kata-kata umum (seperti "dan", "adalah", "yang") yang tidak memberikan kontribusi signifikan terhadap pemahaman konteks teks, agar fokus pada kata kunci lebih relevan.


    Code:

    from nltk.corpus import stopwords
    list_stopwords = stopwords.words('indonesian')
    #remove stopword pada list token
    def stopwords_removal(words):
        return [word for word in words if word not in list_stopwords]
    
    df_motivasi['motivasi_stop_removed'] = df_motivasi['motivasi_normalized'].apply(stopwords_removal)
    data_sementara['motivasi_stop_removed'] = data_sementara['motivasi_normalized'].apply(stopwords_removal)


  5. Stemming
    Mengubah kata ke bentuk dasarnya dengan menghapus awalan atau akhiran, sehingga variasi kata dengan akar yang sama bisa disederhanakan, memperkuat konsistensi dalam analisis.


    Code:

    pip install Sastrawi
    pip install swifter
    
    # import Sastrawi package
    from Sastrawi.Stemmer.StemmerFactory import StemmerFactory
    import swifter
    
    
    # create stemmer
    factory = StemmerFactory()
    stemmer = factory.create_stemmer()
    
    # stemmed
    def stemmed_wrapper(term):
        return stemmer.stem(term)
    
    term_dict = {}
    
    for document in df_motivasi['motivasi_stop_removed']:
        for term in document:
            if term not in term_dict:
                term_dict[term] = ' '
    
    
    print(len(term_dict))
    print("------------------------")
    
    for term in term_dict:
        term_dict[term] = stemmed_wrapper(term)
        print(term,":" ,term_dict[term])
    
    print(term_dict)
    print("------------------------")
    
    
    # apply stemmed term to dataframe
    def get_stemmed_term(document):
        return [term_dict[term] for term in document]
    
    df_motivasi['motivasi_stemmed'] = df_motivasi['motivasi_stop_removed'].swifter.apply(get_stemmed_term)
    data_sementara['motivasi_stemmed'] = data_sementara['motivasi_stop_removed'].swifter.apply(get_stemmed_term)

Setiap tahap dilakukan untuk meningkatkan kualitas data teks sehingga model klasifikasi dapat bekerja lebih efektif dan menghasilkan hasil yang lebih akurat.

Modelling

Setelah data melalui tahap preprocessing dan pelabelan, proses dilanjutkan dengan Exploratory Data Analysis (EDA) untuk melihat distribusi label motivasi (kuat, sedang, lemah). Data kemudian dibagi menjadi data latih (80%) dan validasi (20%), lalu data validasi dibagi lagi menjadi data validasi (80%) dan tes (20%), dari total 3024 data teks.

Selanjutnya, dilakukan pemodelan menggunakan IndoBERT (varian IndoBERTBASE P2 - uncased) sebagai model pre-trained karena relevan dengan bahasa Indonesia. Model ini diakses menggunakan library Transformers dari Huggingface, yang memungkinkan proses NLP berbasis BERT di Python.

Tokenisasi dan Word Embedding

Data yang telah dibersihkan diubah ke format input IndoBERT menggunakan tokenizer indobenchmark/indobert-base-p2. Tokenisasi penting karena pre-trained model hanya menerima input sesuai kamus aslinya. Script utama menggunakan AutoTokenizer dari Huggingface. Sebelum model dilatih, data perlu disesuaikan dengan input format BERT.:

  • Tokenisasi dengan BERT tokenizer.

  • Penambahan token khusus seperti [CLS], [SEP], dan [PAD].

  • Konversi token ke ID berdasarkan kamus BERT.

  • Penambahan segment embedding untuk membedakan bagian input dan padding.

Load Model

Model pre-trained IndoBERT dimuat menggunakan AutoModelForSequenceClassification dengan 3 label kelas (kuat, sedang, lemah).

Fine-Tuning IndoBERT

Proses fine-tuning dilakukan dengan library Transformers melalui konfigurasi TrainingArguments. Parameter yang disetel meliputi:

  • Epochs: 3 atau 10

  • Batch size: 8 dan 16

  • Learning rate: 2e-5 dan 2e-3

  • Evaluation strategy: per epoch

  • Logging: setiap 100 langkah

Tujuan fine-tuning adalah mengadaptasi IndoBERT pada tugas klasifikasi motivasi berdasarkan data yang telah diberi label.

Proses pemantauan dilakukan dengan melihat nilai akurasi dan loss. Kombinasi hyperparameter yang optimal ditentukan berdasarkan performa model selama training.

Code:

from datasets import load_dataset

files = {
    "train": "train.csv",
    "eval": "eval.csv",
    "test": "test.csv",
}

dataset = load_dataset('csv', data_files=files)

from transformers import AutoTokenizer

print('Loading BERT tokenizer...')
tokenizer = AutoTokenizer.from_pretrained("indobenchmark/indobert-base-p2")

def tokenize_function(text):
    return tokenizer(text["text"], padding='max_length', max_length=256)

tokenized_datasets = dataset.map(tokenize_function, batched=True)
from datasets import concatenate_datasets, Dataset

train_data = pd.DataFrame(concatenate_datasets([train_dataset, eval_dataset]))
train_data.head()

import torch
torch.cuda.empty_cache()

device = "cuda:0" if torch.cuda.is_available() else "cpu"
device

model = AutoModelForSequenceClassification.from_pretrained("indobenchmark/indobert-base-p2", num_labels=3)
model

from transformers import TrainingArguments

training_args = TrainingArguments(
    #"test_trainer",
    output_dir="./results",  # Direktori output hasil pelatihan
    num_train_epochs=3,      # Jumlah epoch pelatihan
    per_device_train_batch_size=16,  # Ukuran batch pelatihan
    per_device_eval_batch_size=16,   # Ukuran batch evaluasi
    warmup_steps=100,        # Jumlah langkah pemanasan
    learning_rate=2e-5,      # Learning rate yang disesuaikan
    logging_dir="./logs",    # Direktori logging
    logging_steps=100,
    evaluation_strategy="epoch"
)

#from sklearn.metrics import precision_score, recall_score, f1_score, accuracy_score

metric = load_metric("accuracy")

def compute_metrics(eval_pred):
    logits, labels = eval_pred
    predictions = np.argmax(logits, axis=-1)

    return metric.compute(predictions=predictions, references=labels)

torch.cuda.empty_cache()

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=train_dataset,
    eval_dataset=eval_dataset,
    compute_metrics=compute_metrics,
)

training_history = trainer.train()
#training_history
Hasil dari Pelatihan dan Modelling

Setelah pembagian data selesai, tahap modelling dimulai dengan tokenisasi, load model, fine-tuning, hingga evaluasi hasil pelatihan.

Beberapa kombinasi hyperparameter diuji untuk menemukan performa terbaik. Berikut hasil utama:

✅ Kombinasi Terbaik

  • Batch Size 8, Learning Rate 2e-5, Epoch 3
    Akurasi mencapai 86% dengan training loss dan validation loss yang cukup stabil.

  • Batch Size 16, Learning Rate 2e-5, Epoch 3
    Akurasi hingga 87% dan tidak menunjukkan tanda overfitting signifikan.

⚠️ Potensi Overfitting

  • Epoch 10 (baik batch size 8 maupun 16) menunjukkan penurunan training loss tapi kenaikan validation loss, menandakan overfitting.

❌ Kombinasi Kurang Baik

  • Learning Rate 2e-3, Batch Size 8, Epoch 3
    Akurasi hanya sekitar 37%, menunjukkan model gagal generalisasi dengan baik.

Kesimpulan

Konfigurasi batch size 8 atau 16, learning rate 2e-5, dan epoch 3 adalah pilihan paling optimal untuk tugas klasifikasi motivasi menggunakan IndoBERT. Penggunaan epoch terlalu tinggi atau learning rate besar dapat menurunkan performa karena overfitting atau pembelajaran yang terlalu agresif.

Evaluasi Kinerja Model IndoBERT

Setelah proses pelatihan, model dievaluasi terhadap data validasi dan tes menggunakan berbagai kombinasi hyperparameter. Evaluasi dilakukan dengan metrik Precision, Recall, F1-Score, dan Confusion Matrix untuk tiap kelas: Lemah, Sedang, dan Kuat.

test_dataset = tokenized_datasets["test"]

prediction = trainer.predict(test_dataset)
prediction = prediction.predictions.argmax(1)

print(classification_report(prediction, actual_label, target_names=["Lemah", "Sedang", "Kuat"]))

def show_confusion_matrix(confusion_matrix):
        hmap = sns.heatmap(confusion_matrix, annot=True, fmt="d", cmap="Blues")
        hmap.yaxis.set_ticklabels(hmap.yaxis.get_ticklabels(), rotation=0, ha='right')
        hmap.xaxis.set_ticklabels(hmap.xaxis.get_ticklabels(), rotation=30, ha='right')

        plt.ylabel('True Label')
        plt.xlabel('Predicted Label')

cm = confusion_matrix(prediction, actual_label)
show_confusion_matrix(cm)

df_hasil=pd.DataFrame({
    'Teks Validasi': df_test['text'],
    'Label Sebenarnya': actual_label,
    'Hasil Prediksi Model': prediction
})

# Kategorikan label dengan dictionary
label_mapping = {2: 'Kuat', 0: 'Sedang', 1: 'Lemah'}

# Mengganti nilai dalam kolom "Label Sebenarnya" dan "Hasil Prediksi Model" dengan kategori yang sesuai
df_hasil['Label Sebenarnya'] = df_hasil['Label Sebenarnya'].replace(label_mapping)
df_hasil['Hasil Prediksi Model'] = df_hasil['Hasil Prediksi Model'].replace(label_mapping)

# Buat kolom baru "Benar" yang menunjukkan apakah prediksi benar atau salah
df_hasil['Benar'] = (df_hasil['Label Sebenarnya'] == df_hasil['Hasil Prediksi Model'])

# Menampilkan DataFrame dengan kolom "Benar" yang menunjukkan apakah prediksi benar atau salah
df_hasil.head()
🔎 Evaluasi pada Pengaturan Terbaik: Lr = 2e-5, Batch Size = 8
  • Epoch 3

    • F1-Score rata-rata: 86% (baik pada data tes & validasi)

    • Kelas Lemah dan Kuat: Akurasi tinggi

    • Kelas Sedang: Performa lebih rendah

  • Epoch 10

    • F1-Score menurun: 83% (tes), 84% (validasi)

    • Tanda-tanda overfitting, terutama pada kelas Sedang

✅ Kesimpulan: Epoch 3 lebih stabil dan akurat dibandingkan Epoch 10.

🔎 Evaluasi pada Batch Size = 16, Lr = 2e-5
  • Epoch 3

    • F1-Score rata-rata: 85–87%

    • Semua kelas terprediksi dengan cukup baik, terutama Lemah dan Kuat

  • Epoch 10 (Tabel 4.11 & 4.13)

    • F1-Score sedikit menurun ke 83–84%

    • Kelas Sedang tetap jadi titik lemah model

✅ Kesimpulan: Batch size 16 dan epoch 3 juga cukup optimal, dengan akurasi setara batch size 8.

⚠️ Evaluasi pada Lr = 2e-3, Batch Size = 8, Epoch 3
  • F1-Score sangat rendah: 44% (tes) dan 38% (validasi)

  • Hanya kelas Kuat yang berhasil diprediksi, sisanya gagal total

  • Precision 1.00 tetapi recall sangat rendah (underfitting)

  • Kelas Lemah dan Sedang tidak terdeteksi sama sekali

❌ Kesimpulan: Learning rate terlalu tinggi → model gagal belajar dengan baik

📌 Kesimpulan Umum
  • Model paling stabil dan akurat saat menggunakan:

    • Learning rate: 2e-5

    • Batch size: 8 atau 16

    • Epoch: 3

  • Kelas "Sedang" secara konsisten memiliki performa terendah → kemungkinan besar disebabkan oleh jumlah data yang tidak seimbang

  • Epoch 10 cenderung menyebabkan overfitting, terutama terlihat dari turunnya performa pada kelas Sedang

  • Learning rate 2e-3 terlalu tinggi dan menyebabkan underfitting, model hanya bisa memprediksi satu kelas saja

Deployment

Setelah proses modelling, tahap deployment dilakukan dengan mengintegrasikan model ke dalam lingkungan operasional, seperti website.

Implementasi Halaman

Halaman beranda dirancang untuk memberikan informasi lengkap tentang fungsi dan cara penggunaan aplikasi, sekaligus memungkinkan pengguna langsung melakukan prediksi dari kalimat motivasi yang dimasukkan.

Code:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Text Motivation Analyzer</title>
    <link
      href="https://fonts.googleapis.com/css?family=Pacifico"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://fonts.googleapis.com/css?family=Arimo"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://fonts.googleapis.com/css?family=Hind:300"
      rel="stylesheet"
      type="text/css"
    />
    <link
      href="https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300"
      rel="stylesheet"
      type="text/css"
    />
    <link rel="stylesheet" href="../static/style.css" />
  </head>

  <body style="background: whitesmoke">
    <header>
      <img class="logo" src="../static/logo.png" alt="logo" href="index.html" />
      <!--<nav>
        <ul class="nav_links">
          <li><a href="index.html">Home</a></li>
          <li><a href="#">About</a></li>
        </ul>
      </nav> -->
    </header>
    <div class="login">
      <h1>Text Motivation Analyzer</h1>
      <p class="desc">
        Welcome to "Motivation Classification Website"! We are an online
        platform dedicated to studying, analyzing, and classifying various types
        of motivation. Our main goal is to provide deep insights and
        understanding into motivation in various contexts in IT Bootcamp.Type a
        motivation sentence, click on the submit button and wait for your
        prediction.
      </p>

      <!-- Main Input For Receiving Query to our ML -->

      <form action="/predict" method="post">
        <input
          type="text"
          name="text"
          placeholder="input text here"
          required="required"
        />
        <button type="submit" class="btn btn-primary btn-block btn-large">
          Predict the classification
        </button>
      </form>

      <br />
      <br />
      <h3 class="prediction_answer">{{ prediction_text }}</h3>
    </div>
  </body>
</html>

Pada halaman beranda, pengguna cukup memasukkan kalimat dan menekan tombol prediksi untuk mendapatkan hasil klasifikasi teks.

Code:

!pip install flask --quiet
!pip install flask-ngrok --quiet
!pip install transformers==4.28.0. --quiet
print("Completed!")

!wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.tgz
!tar -xvf /content/ngrok-stable-linux-amd64.tgz

!./ngrok authtoken 2Q9HsXd7zHIZa5Hek4qVsaJrXWZ_6pWh1cwMaxUUy6pCa8iqM

from transformers import Trainer
from transformers import AutoTokenizer
from transformers import AutoModelForSequenceClassification

from flask import Flask, render_template
from flask import request
from flask_ngrok import run_with_ngrok

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np

from google.colab import drive
drive.mount('/content/drive')

from logging import FileHandler, WARNING

app = Flask(__name__)
run_with_ngrok(app)

tokenizer = AutoTokenizer.from_pretrained("/content/drive/MyDrive/dataset/tokenizer")
model = AutoModelForSequenceClassification.from_pretrained("/content/drive/MyDrive/dataset/model")
trainer = Trainer(model=model)

@app.route('/')
def my_form():
  return render_template('index.html')

@app.route('/predict', methods=['POST'])
def my_form_post():
  text = request.form['text']
  tokenized = tokenizer(text, padding='max_length', max_length=256)
  label = trainer.predict([tokenized]).predictions.argmax(1)[0]
  if label == 0:
    prediction_text = f'Predicted: Lemah [{label}]'
    print(f'Predicted: Lemah [{label}]')
  elif label == 1:
    prediction_text = f'Predicted: Sedang [{label}]'
    print(f'Predicted: Sedang [{label}]')
  else:
    prediction_text = f'Predicted: Kuat [{label}]'
    print(f'Predicted: Kuat [{label}]')

  return render_template('index.html', prediction_text=prediction_text)

run_with_ngrok(app)
app.run()

Let's talk

Time for me:

Email:

muhamadfachri185@gmail.com

Reach out:

Let's talk

Time for me:

Email:

muhamadfachri185@gmail.com

Reach out:

Let's talk

Time for me:

Email:

muhamadfachri185@gmail.com

Reach out: