Dengan kode dalam python untuk klasifikasi teks

Setelah membahas AutoML untuk Klasifikasi & Regresi menggunakan MLJAR, dan peramalan Time Series menggunakan AutoTS, kali ini saya mendapat kesempatan untuk bekerja dengan klasifikasi multi-label (dan bukan kelas jamak). Untuk mencoba sesuatu yang baru, saya mencari auto-ml di Google untuk klasifikasi multi-label. Dan setelah mendalami lebih dalam, saya jadi mengetahui tentang Ludwig, Kerangka Pembelajaran Mesin deklaratifyang dapat digunakan untuk klasifikasi multi-label.

Jadi, mari kita mulai

Tapi sebelum melompat ke depan

Apa itu sistem Pembelajaran Mesin Deklaratif?

Jadi, sistem ML bisa saja ada jenisnya

  • Fleksibel: Dalam sistem seperti itu, pengembang mengkodekan semuanya dari awal menggunakan pustaka seperti TensorFlow, Keras, dan PyTorch menggunakan utilitas yang disediakan oleh pustaka ini, yaitu Anda memutuskan setiap detail arsitektur yang ingin Anda miliki kecuali Tangkapannya adalah Anda akanmembuat banyak kode. Contohnya adalah jaringan saraf yang Anda desain menggunakan Tensorflow atau Keras dari awal.
  • AutoML:Di AutoML, pengembang tidak melakukan apa pun kecuali mengambil alih peran sepenuhnya. Arsitektur AutoML-lah yang menangani semuanya, model mana yang harus dipilih, dan pra-pemrosesan apa yang harus dilakukan. Semuanya!! Satu-satunya kendala di sini adalah terdapatfleksibilitas yang sangat rendah pada sistem seperti itu dan pengembang tidak dapat melakukan banyak penyesuaian
  • Sistem deklaratif:Ini adalah jalan tengah antara sistem Fleksibel dan AutoML di mana pengembang dapat memilih berbagai komponen pipeline (meskipun pengkodean tidak diperlukan) sementara apa pun yang tidak ditentukan akan masuk ke bagian AutoML dari sistem sistem. Jadi, Sistem deklaratif mempertahankan keseimbangan antara fleksibilitas dan AutoML. Ludwig adalah salah satu sistem tersebut.

Jika mau, Anda dapat menentukan setiap detail pipeline, jika tidak, semuanya ditangani oleh sistem AutoML Ludwig. Sederhana !!

Jadi, tanpa membuang waktu, mari kita mengotori tangan kita dengan Ludwig.

Saya akan menggunakan kumpulan data ini untuk sisa postingan, unzip ini dan baca train.csv

  1. Impor perpustakaan yang diperlukan dan muat kumpulan data
#pip3 install ludwig

from ludwig.api import LudwigModel
import pandas as pd
import numpy as np
from sklearn.utils import resample
from nltk.corpus import stopwords
from sklearn.model_selection import train_test_split as tts
import re

train = pd.read_csv('train.csv')
labels = train.columns[3:]

Agar Ludwig dapat mengatasi masalah multi-label, kita perlu mengonversi keluaran sebagai string dengan beberapa label sebagai kata (dipisahkan dengan spasi) dalam string yang sama. Selain itu, jika suatu label memiliki beberapa kata pada namanya, kata-kata tersebut harus dipisahkan dengan garis bawah.

def label_list(x):
    labels = []
    for key in  [y for y in x.keys()][3:]:
        if x[key]==1:
            labels.append('_'.join(key.split(' ')))
    return ' '.join(labels)
train['labels'] = train.apply(lambda x: label_list(x),axis=1)

Memisahkan data dalam uji kereta

train, test= tts(train,test_size=0.2)

Ini dia Ludwig.

config = {'input_features':[{'name':'TITLE','type':'text',
                            "preprocessing": {"word_tokenizer": "space"},
                            "encoder": {
                                        "type": "bert",
                                        "trainable": False}},
                            {'name':'ABSTRACT','type':'text',
                            "preprocessing": {"word_tokenizer": "space"},
                            "encoder": {
                                        "type": "bert",          
                                        "trainable": False}}],
          
         'output_features':[{'name':'labels','type':'set','loss':{'type': 'sigmoid_cross_entropy'}}],
         'preprocessing':{'split':{'column':'labels','probabilities':[0.7,0.1,0.2]}},
         'trainer':{'type':'trainer',
                    'epochs':100,
                    'batch_size':32,
                    'checkpoints_per_epoch':2,
                    'early_stopping':5,
                    'learning_rate':0.0005,
                    'optimizer':{'type':'adam'}
                   } 
         }
ludwig_model = LudwigModel(config)
train_stats, _, model_dir = ludwig_model.train(train[['TITLE','ABSTRACT','labels']])

Banyak hal yang perlu dipahami

  • File konfigurasi adalah inti dari keseluruhan proses ini. Seperti yang telah kita bahas sebelumnya, dalam sistem deklaratif, pengembang dapat memberikan masukan untuk berbagai segmen pipeline. File konfigurasi ini menampung segmen-segmen yang ingin diputuskan oleh pengembang. Ada banyak bagian dalam file konfigurasi ini. Kami akan membahas beberapa hal utama

input_features: Ini adalah daftar kamus dengan masing-masing kamus memiliki informasi tentang satu input_feature seperti nama, tipe data, pra-pemrosesan yang diperlukan untuk fitur tersebut, dll. Dalam kasus kami, ini adalah 2 kolom 'TITLE' dan 'ABSTRACT' . Kami juga telah menyediakan metodologi yang harus diikuti untuk menghasilkan penyematan kata

Output_features: Mirip dengan input_features tetapi memiliki nama untuk kolom output_feature / label. Untuk bagian ini, kami juga dapat menyebutkan fungsi kerugian. Dalam hal ini, kolomnya adalah kolom 'label' dengan loss='sigmoid_corss_entropy' . Perhatikan bahwa untuk beberapa klasifikasi, kami mempertahankan tipe data sebagai 'set'. Itu memang masuk akal. Benar?

bagian pemrosesan awal membantu kami mengaktifkan langkah-langkah prapemrosesan yang harus diikuti

1. Untuk seluruh kumpulan data (seperti train-test-split)

2. Melakukan pra-proses khusus untuk tipe data tertentu (seperti semua fitur string atau float dalam kumpulan data)

Jadi jika ada beberapa langkah preprocessing umum, bagian ini bisa digunakan. Kami telah menggunakannya untuk membagi secara internal antara kumpulan data pelatihan, validasi, dan pengujian menggunakan strategi acak.

pelatih digunakan untuk menentukan parameter di sekitar pelatihan jaringan saraf yang akan berlangsung seperti jumlah zaman, ukuran_batch, pengoptimal, dll.

Ludwig dapat menggunakan antara model 'ecd' dan 'gbm' menggunakan parameter model_type di konfigurasi yang defaultnya adalah 'ecd'.

'gbm' tidak lain hanyalah algo peningkat pohon (seperti Light GBM).

Tapi, apa itu 'ECD' (Encoder-Combiner-Decoder)?

Ini adalah arsitektur jaringan saraf dasar yang diikuti Ludwig

Jadi desainnya sederhana,

  • Ambil beberapa fitur masukan (dapat berupa tipe data yang berbeda juga)
  • Lakukan prapemrosesan (langkah default diambil jika tidak ada yang disebutkan oleh pengembang dalam konfigurasi untuk fitur tersebut)
  • Enkode menggunakan model encoder
  • Gabungkan semua penyematan yang dibentuk untuk fitur berbeda (penggabungan adalah default tetapi operasi lain juga dimungkinkan untuk menggabungkan penyematan berbeda)
  • Menggunakan langkah decoder dan post_preprocessing, hasilkan output

Di bawah ini Anda dapat melihat bagaimana arsitektur diubah tergantung pada pernyataan masalah yang berbeda

Meskipun demikian, beberapa parameter lainnya juga dimungkinkan dalam file konfigurasi yang dapat Anda baca di dokumentasi

Terakhir, mari kita hasilkan keluaran untuk kumpulan data pengujian

predictions, output_directory = model.predict(test[['TITLE','ABSTRACT']])

'prediksi' adalah kerangka data dengan nilai berikut

Sekarang, kami akan menghitung presisi makro, perolehan, dan skor f1 untuk menganalisis performa Ludwig.

#basic preprocessing required 

test['predictions'] = [x for x in predictions['labels_predictions'].values]
test['labels'] = test['labels'].transform(lambda x:x.split(' '))

#initializing an empy dataframe
predict = pd.DataFrame(index=[x for x in test.index],columns=['TP','FP','FN']).fillna(0)

Menghitung FP, FN, dan TP beserta hit dan miss berdasarkan kelas

for index,rows in test.iterrows():
    labels_ = set(rows['labels'])
    predict_ = set(rows['predictions'])
    predict.at[index,'TP'] = len(labels_.intersection(predict_))
    predict.at[index,'FP'] = len(predict_-labels_)
    predict.at[index,'FN'] = len(labels_-predict_)

sum_dict = predict.sum()
precision = sum_dict['TP']/(sum_dict['FP']+sum_dict['TP'])
recall = sum_dict['TP']/(sum_dict['FN']+sum_dict['TP'])
f1 = 2*precision*recall/(precision+recall)
print("precision=",precision)
print("recall=",recall)
print("f1=",f1)

Hasilnya cukup bagus mengingat kami hampir tidak melakukan apa pun !!

Jadi, itu saja. Cobalah masalah pemodelan lainnya dengan Ludwig dan lihat sendiri betapa bagusnya Ludwig. Selain itu, dokumentasinya cukup bagus jadi jika Anda berencana mencoba Ludwig, langsung saja ke dokumentasi.