Update 6 Juni 2018: Anago mengupdate versi packagenya dan tidak compatible dengan versi sebelumnya. Jika ingin sesuai posting ini, install dengan versi lama: pip3 install anago==0.0.5. Saya belum eksplorasi versi anago yang terakhir.
Update: paper yang saya+istri buat tentang ini
Sebelumnya saya sudah membahas NER Bahasa Indonesia dengan Stanford NER. Kelemahan dari StanfordNER adalah lisensinya dan menggunakan Java. Posting ini akan membahas NER dengan Python-Keras dengan library anaGo (https://github.com/Hironsan/anago) yang menggunakan teknik biLSTM+CRF dan berlisensi MIT yang lebih longgar. Lib NLTK walaupun menyediakan NER untuk Bahasa Inggris, tetapi tidak menyediakan cara yang mudah untuk men-training bahasa lain.
Untuk training, saya menggunakan data https://github.com/yohanesgultom/nlp-experiments/blob/master/data/ner/training_data.txt yang dikonversi ke format BIO. Jadi misalnya
DKI LOCATION Jakarta LOCATION
perlu diubah menjadi
DKI B-LOC Jakarta I-LOC
Tambahkan file validasi (saya ambil dari data training, jangan lupa harus diacak terlebih dulu urutannya).
Catatan: penggunaan awalan label “B-” dan “I-” seperti B-LOC, I-LOC, B-PER, I-PER, B-ORG, I-ORG dan B-MISC, I-MISC wajib di anaGo karena di codenya mendeteksi “B-” dan “I-“. Sedangkan untuk bagian belakangnya bebas.
Karena teknik ini dasarnya sequence labeling bisa saja kita manfaatkan untuk task yang lain, misalnya untuk mendeteksi subyek dan obyek sehingga labelnya menjadi B-SUB, I-SUB, B-OBJ, I-OBJ dsb.
Selanjutnya install tensorflow dan keras (catatan saya tentang ini) lalu anago (bisa dengan pip3 anago).
Buat code berikut untuk training membuat model:
import anago from anago.reader import load_data_and_labels import os import numpy as np import random as rn namaDir = "/media/yudiwbs/data/" namaFileTrain = namaDir + "train.txt" namaFileValid = namaDir + "valid.txt" namaFileTest = namaDir + "test.txt" # karena hasil tdk konsisten, random seednya diisi manual os.environ['PYTHONHASHSEED'] = '0' np.random.seed(42) rn.seed(12345) import tensorflow as tf from keras import backend as K tf.set_random_seed(1234) # atur parameternya disini model = anago.Sequence(char_emb_size=25, word_emb_size=100, char_lstm_units=25, word_lstm_units=100, dropout=0.5, char_feature=True, crf=True, batch_size=20, optimizer='adam', learning_rate=0.001,lr_decay=0.9, clip_gradients=5.0, max_epoch=30, early_stopping=True, patience=3,train_embeddings=True, max_checkpoints_to_keep=5, log_dir=None) model.train(x_train, y_train, x_valid, y_valid) print("\n\nEvaluasi Test:") model.eval(x_test, y_test) words = 'Budi Martami kuliah di UPI yang berlokasi di Bandung'.split() print(model.analyze(words)) words = 'PDIP yang dikawal Megawati menang dalam Pilkada DKI Jakarta'.split() print(model.analyze(words))
Hasilnya sebagai berikut:
{'entities': [{'score': 1.0, 'beginOffset': 0, 'text': 'Budi Martami', 'type': 'MISC', 'endOffset': 2}, {'score': 1.0, 'beginOffset': 4, 'text': 'UPI', 'type': 'LOC', 'endOffset': 5}, {'score': 1.0, 'beginOffset': 8, 'text': 'Bandung', 'type': 'LOC', 'endOffset': 9}], 'words': ['Budi', 'Martami', 'kuliah', 'di', 'UPI', 'yang', 'berlokasi', 'di', 'Bandung']} {'entities': [{'score': 1.0, 'beginOffset': 0, 'text': 'PDIP', 'type': 'ORG', 'endOffset': 1}, {'score': 1.0, 'beginOffset': 3, 'text': 'Megawati', 'type': 'PER', 'endOffset': 4}, {'score': 1.0, 'beginOffset': 6, 'text': 'Pilkada DKI', 'type': 'MISC', 'endOffset': 8}, {'score': 1.0, 'beginOffset': 8, 'text': 'Jakarta', 'type': 'LOC', 'endOffset': 9}], 'words': ['PDIP', 'yang', 'dikawal', 'Megawati', 'menang', 'dalam', 'Pilkada', 'DKI', 'Jakarta']} {'entities': [], 'words': ['Ibu', 'pergi', 'ke', 'pasar']}
“Budi Martami” dideteksi sebagai MISC (harusnya PERSON)
“UPI” dideteksi sebagai LOC (lokasi) (harusnya ORG)
“Bandung” sudah benar dideteksi sebagai LOC
“PDIP” sudah cocok dideteksi ORG
“Megawati” juga sudah benar sebagai PERSON
“Pilkada DKI” benar sebagai MISC (DKI bukan sebagai LOC di frasa ini)
“Jakarta” harusnya masuk ke frase “Pilkada DKI Jakarta” sebagai MISC, bukan LOC.
“Ibu pergi ke pasar” sudah benar karena tidak ada named entity didalamnya.
Data trainingnya memang banyak membahas tentang berita politik sehinggga lebih akurat untuk kalimat kedua dibandingkan yang pertama. Nanti data trainingnya perlu ditambah lebih banyak lagi.
Hasil terbaik yang saya dapatkan adalah F1 = 0.6837. Masih rendah, mungkin bisa ditingkatkan dengan menggunakan pretrained Word2Vec atau GloVe
Update: untuk menyimpan model, gunakan:
model.save(directory)
parameternya bukan file tapi directory. Sedangkan untuk me-load model:
model = anago.Sequence().load(namaDirModel)
Update: F1 naik menjadi 0.69-0.70 saat menggunakan Word2Vec dari data Wikipedia Bhs Indonesia (posting tentang w2vec).
Untuk menambahkan word embedding saat training:
import gensim embeddings = gensim.models.Word2Vec.load(namaFileW2Vec) model = anago.Sequence(..param lain.., embeddings=embeddings)
Jangan lupa parameter word_emb_size disamakan dengan model embeddings-nya.
Update: menggunakan glove, F1 naik ke 0.71-0.72 (untuk vector size 50)
Code:
from anago.reader import load_data_and_labels,load_glove embeddings = load_glove(namaFileVec) model = anago.Sequence(..param lain.., embeddings=embeddings)
Update: ada bug di package Anago. Parameter patience ternyata di hardcode. Berikut perbaikannnya:
Di file metrics tambahkan parameter patience_nb
function def get_callbacks(log_dir=None, valid=(), tensorboard=True, eary_stopping=True, patience_nb=3):
lalu di code berikut passing parameter ini (tadinya di hardcode 3)
if eary_stopping: callbacks.append(EarlyStopping(monitor='f1', patience=patience_nb, mode='max'))
lalu di trainer tambahkan parameter:
# Prepare callbacks callbacks = get_callbacks(log_dir=self.checkpoint_path, tensorboard=self.tensorboard, eary_stopping=self.training_config.early_stopping, patience_nb=self.training_config.patience, valid=(valid_steps, valid_batches, self.preprocessor))
di trainer juga optimizer adam sepertinya di hardcode.
=== END UPDATE ===
kalau pakek python 2.7 gimana ya pak yah..? tensorflownya gak support pythonnya ?
Bisa, tapi untuk apa menggunakan 2.7 saat semua migrasi ke 3?
Bisa minta data training yang sudah berformat BIO?
Saya juga dapat dari mahasiswa istri, perlu minta ijin juga ke dia (karena mungkin ada tambahan/edit). Menurut saya buat saja script kecil untuk mentransformasi format.
mohon maaf mau bertanya pak untuk pembuatan script untuk mentranformasi ke format BIO nya ada ketentuan gt gak pak ? karena saya udah membuat format BIO nya banyak yang ga ke deteksi pak. trims pak sebelumnya
tdk terdetesinya seperti apa? antara token dan tag harus tab bukan spasi. tag harus O atau diawali B- atau I-
tedeteksi pak hanya saja yang di deteksi tidak sesuai pak (kebanyakan tidak sesuainya pak )
Nilai F1-nya berapa? (yang dibagian akhir)
saya coba 1000 data per document training testing dan valid , di train bisa pak tapi hasil f1:0.00 itu datanya yang kurang banyak atau gimana ya?
bisa terlalu sedikit, bisa juga karena salah tag. Coba setidaknya 10rb untuk data training. Data training biasanya jauh lebih besar dari valid dan test. Saya menggunakan 80:10:10 untuk train:test:valid
Selamat malam pak. Saya coba mengguanakan data training dari terjemahan surat al quran berbahasa indonesia. untuk data yang digunakan sekitar 6000 tag. tapi pas di uji. f1 : 0.0 dan masih belum bisa prediksi entitas. Kira kira masalahnya dimana ya pak? Terimakasih
perlu lihat datanya.. kalau mau kirim ke yudi@upi.edu, nanti saya lihat.
Baik pa. sekarang saya kirim untuk sample datanya.
selamat pagi , pak saya sudah ikuti saran bapak tapi f1 tetap 0.0 , bagaimana yah ?
kalau mau kirimkan datanya ke saya biar dilihat.
punten pak tanya lagi datanya sudah saya kirim ke bapak apa sudah di cek sebelumnya , saya masih menggunakan versi yang sebelum anago update terakhir kali
Setelah saya lihat, anda mengirimnya cuma file saja ya tanpa keterangan apapun. Itu sih seperti anda datang ke meja saya, lempar dokumen lalu pergi hehe. Saya banyak dapat email dengan attachment, jika emailnya kosong tanpa keterangan apapun ya langsung saya skip saja.
Oh iya pak maaf sebelumnya , mungkin sayakurang memperhatikan :D, untuk update terbaru cara untuk updatenya seperti apa ya pak saya sudah coba install versi baru tapi tidak bisa import anago.utilsnya
Selamat sore pak saya ingin bertanya mengenai pembuatan format BIO Encoding.
Misalkan saya punya data “Apple Iphone 4S 16Gb”. Dan saya ingin mengcustom sendiri pembuatan NERnya dengan seperti dibawah ini :
Apple Brand
Iphone ModelName
4S ModelName
16GB Storage
Diatas saya mencoba referensi disini https://dataturks.com/projects/Mohan/Best%20Buy%20E-commerce%20NER%20dataset
Untuk mengubah kedalam format BIO Encoding harus di tambah huruf B dan I-nya. Nah yang saya masih agak bingung untuk format datanya tersebut apakah kebawah seperti contoh diatas atau kesamping seperti referensi yang ini https://github.com/yohanesgultom/nlp-experiments/blob/master/data/ner/training_data.txt ?
Terus saya juga ingin tanya untuk pelabelannya apakah ada yang bisa secara otomatis sistem mendeteksi tanpa menggunakan data training?
Terima kasih pak sebelumnya
Masalah format BIO, tergantung dari library yang digunakan. Untuk pelabelan otomatis, coba googling tentang unsupervised sequence labeling, tapi itu bakal jadi topik tersendiri.
Berarti jika menggunakan library anaGO format datanya seperti diatas yaa pak tinggal ditambah B dan I kemudian huruf selanjutnya bebas yaa pak?
terus format penulisannya perkata ditulis kebawah dan diberi satu tab untuk keterangan ner-nya yaa pak?
Betul. Masalah format lihat saja contoh di library tersebut dan ikuti persis.
Pak maaf saya mau tanya lagi, untuk pretrained word2vec atau glove itu apakah datanya sudah dilabelkan atau belum yaa pak? Terus untuk data training, data testing dan data validasi berarti sudah dilabelkan semua dengan format diatas kan yaa pak? dan tinggal dirandom aja posisinya?
namanya pretrained ya sudah jadi vektor (model), data inputnya sudah tidak digunakan lagi. Tapi kalau yang anda maksudkan anda mau buat word2ved/glove model, jawabannya anda tidak perlu melabeli.
Pertanyaan kedua, training, testing, validasi ini yang mana? ner? Hati-hati jangan dirandom per kata, tapi di random per kalimat. Urutan kata jangan sampai hilang.
Pak maaf mau tanya, untuk mengganti menjdi B-LOC dan I-LOC dll itu berdasarkan apa ya untuk B dan I nya?
B itu token awal (BEGIN) dan I adalah token isi (INSIDE). Jadi kalau ada kata “Presiden Indonesia” maka Presiden B-ORG dan Indonesia I-ORG.
Pak untuk mebuat data train dan data test pakai format BOI tersebut apakah dilakukanya secara manual atau ada tools untuk mengkonversinya
Manual.