Kesalahan Tatabahasa with Tagging HuggingFace#

This tutorial is available as an IPython notebook at Malaya/example/tatabahasa-tagging-huggingface.

This module only trained on standard language structure, so it is not save to use it for local language structure.

[1]:
import logging

logging.basicConfig(level=logging.INFO)
[2]:
import malaya
from pprint import pprint

List available Transformer models#

[3]:
malaya.tatabahasa.available_huggingface()
INFO:malaya.tatabahasa:tested on 5k generated dataset at https://f000.backblazeb2.com/file/malay-dataset/tatabahasa/test-set-tatabahasa.pkl
[3]:
Size (MB) Sequence Accuracy Sequence Tagging Accuracy Suggested length
mesolitica/finetune-tatabahasa-t5-tiny-standard-bahasa-cased 139.0 0.860198 0.963267 256.0
mesolitica/finetune-tatabahasa-t5-small-standard-bahasa-cased 242.0 0.860198 0.963267 256.0
mesolitica/finetune-tatabahasa-t5-base-standard-bahasa-cased 892.0 0.860198 0.963267 256.0

Supported kesalahan tatabahasa#

For full description, check out https://tatabahasabm.tripod.com/tata/salahtata.htm

[4]:
malaya.tatabahasa.describe_tagging()
[4]:
class Description salah betul
0 0 PAD
1 1 kesambungan subwords
2 2 tiada kesalahan
3 3 kesalahan frasa nama, Perkara yang diterangkan... Cili sos sos cili
4 4 kesalahan kata jamak mereka-mereka mereka
5 5 kesalahan kata penguat sangat tinggi sekali sangat tinggi
6 6 kata adjektif dan imbuhan "ter" tanpa penguat. Sani mendapat markah yang tertinggi sekali. Sani mendapat markah yang tertinggi.
7 7 kesalahan kata hubung Sally sedang membaca bila saya tiba di rumahnya. Sally sedang membaca apabila saya tiba di ruma...
8 8 kesalahan kata bilangan Beribu peniaga tidak membayar cukai pendapatan. Beribu-ribu peniaga tidak membayar cukai penda...
9 9 kesalahan kata sendi Umar telah berpindah daripada sekolah ini bula... Umar telah berpindah dari sekolah ini bulan lalu.
10 10 kesalahan penjodoh bilangan Setiap orang pelajar Setiap pelajar.
11 11 kesalahan kata ganti diri Pencuri itu telah ditangkap. Beliau dibawa ke ... Pencuri itu telah ditangkap. Dia dibawa ke bal...
12 12 kesalahan ayat pasif Cerpen itu telah dikarang oleh saya. Cerpen itu telah saya karang.
13 13 kesalahan kata tanya Kamu berasal dari manakah ? Kamu berasal dari mana ?
14 14 kesalahan tanda baca Kamu berasal dari manakah . Kamu berasal dari mana ?
15 15 kesalahan kata kerja tak transitif Dia kata kepada saya Dia berkata kepada saya
16 16 kesalahan kata kerja transitif Dia suka baca buku Dia suka membaca buku
17 17 penggunaan kata yang tidak tepat Tembuk Besar negeri Cina dibina oleh Shih Huan... Tembok Besar negeri Cina dibina oleh Shih Huan...

Right now we only able to predict up to 15 different kesalahan tatabahasa, hopefully in the future we can scale this up.

Load HuggingFace model#

def huggingface(model: str = 'mesolitica/finetune-tatabahasa-t5-small-standard-bahasa-cased', **kwargs):
    """
    Load HuggingFace model to fix kesalahan tatabahasa.

    Parameters
    ----------
    model: str, optional (default='mesolitica/finetune-tatabahasa-t5-small-standard-bahasa-cased')
        Check available models at `malaya.tatabahasa.available_huggingface()`.

    Returns
    -------
    result: malaya.torch_model.huggingface.Tatabahasa
    """
[5]:
model = malaya.tatabahasa.huggingface()

Predict#

def generate(
    self,
    strings: List[str],
    **kwargs,
):
    """
    Fix kesalahan tatatabahasa.

    Parameters
    ----------
    strings : List[str]
    **kwargs: vector arguments pass to huggingface `generate` method.
        Read more at https://huggingface.co/docs/transformers/main_classes/text_generation
        Fix kesalahan tatabahasa supported all decoding methods except beam.

    Returns
    -------
    result: List[Tuple[str, int]]
    """

Randomly picked string in bahasa melayu wikipedia.

[6]:
# https://ms.wikipedia.org/wiki/Bola_sepak
string = 'Pada amnya, hanya penjaga gol sahaja yang dibenarkan menyentuh bola dengan tangan di dalam kawasan golnya'
[7]:
model.generate([string], max_length = 256)
You're using a T5TokenizerFast tokenizer. Please note that with a fast tokenizer, using the `__call__` method is faster than using a method to encode the text followed by a call to the `pad` method to get a padded encoding.
[7]:
[[('Pada', 2),
  ('amnya', 2),
  (',', 2),
  ('hanya', 2),
  ('penjaga', 2),
  ('gol', 2),
  ('sahaja', 2),
  ('yang', 2),
  ('dibenarkan', 2),
  ('menyentuh', 2),
  ('bola', 2),
  ('dengan', 2),
  ('tangan', 2),
  ('di', 2),
  ('dalam', 2),
  ('kawasan', 2),
  ('golnya', 2)]]

Now assumed we have kesalahan frasa nama, from penjaga gol become gol penjaga.

[8]:
# https://ms.wikipedia.org/wiki/Bola_sepak
string = 'Pada amnya, hanya gol penjaga sahaja yang dibenarkan menyentuh bola dengan tangan di dalam kawasan golnya'
[9]:
model.generate([string], max_length = 256)
[9]:
[[('Pada', 2),
  ('amnya', 2),
  (',', 2),
  ('hanya', 2),
  ('penjaga', 3),
  ('gol', 3),
  ('sahaja', 2),
  ('yang', 2),
  ('dibenarkan', 2),
  ('menyentuh', 2),
  ('bola', 2),
  ('dengan', 2),
  ('tangan', 2),
  ('di', 2),
  ('dalam', 2),
  ('kawasan', 2),
  ('golnya', 2)]]
[10]:
string = 'Sani mendapat markah yang tertinggi sekali.'
string1 = 'Hassan ialah peserta yang termuda sekali dalam pertandingan itu.'
model.generate([string, string1], max_length = 256)
[10]:
[[('Sani', 2),
  ('mendapat', 2),
  ('markah', 2),
  ('yang', 2),
  ('tertinggi', 6),
  ('.', 2)],
 [('Hassan', 2),
  ('ialah', 2),
  ('peserta', 2),
  ('yang', 2),
  ('termuda', 6),
  ('dalam', 2),
  ('pertandingan', 2),
  ('itu', 2),
  ('.', 2)]]
[11]:
string = 'Dia kata kepada saya.'
model.generate([string], max_length = 256)
[11]:
[[('Dia', 2), ('berkata', 15), ('kepada', 2), ('saya', 2), ('.', 2)]]
[12]:
import pickle

with open('tests/dataset-tatabahasa.pkl', 'rb') as fopen:
    test_set = pickle.load(fopen)

len(test_set)
[12]:
100
[13]:
def get_xy(row):
    x, y, tag = [], [], []

    for i in range(len(row[0])):
        t = [row[0][i][0]]
        y.extend(t)
        t = [row[1][i][0]]
        x.extend(t)
        tag.extend([row[1][i][1]] * len(t))

    return ' '.join(x), ' '.join(y), tag
[14]:
x, y, t = get_xy(test_set[0])
x, y, t
[14]:
('Dirk Jan Klaas " Klaas-Jan " Huntelaar ( lahir 12 Ogos 1983 ) merupakan pemain bola sepak Belanda yang bermain seperti posisi penyerang !',
 'Dirk Jan Klaas " Klaas-Jan " Huntelaar ( lahir 12 Ogos 1983 ) merupakan pemain bola sepak Belanda yang bermain di posisi penyerang .',
 [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 14])
[15]:
model.generate([x], max_length = 256)
[15]:
[[('Dirk', 2),
  ('Jan', 2),
  ('Klaas', 2),
  ('"', 2),
  ('Klaas-Jan', 2),
  ('"', 2),
  ('Huntelaar', 2),
  ('(', 2),
  ('lahir', 2),
  ('12', 2),
  ('Ogos', 2),
  ('1983', 2),
  (')', 2),
  ('merupakan', 2),
  ('pemain', 2),
  ('bola', 2),
  ('sepak', 2),
  ('Belanda', 2),
  ('yang', 2),
  ('bermain', 2),
  ('di', 9),
  ('posisi', 2),
  ('penyerang', 2),
  ('.', 14)]]
[16]:
x, y, t = get_xy(test_set[-1])
x, y, t
[16]:
('Pada tahun 2002 , kedua-dua gol beliau menduduki tempat ke-6 dalam 100 Greatest Sporting Moments oleh saluran Channel 4 UK .',
 'Pada tahun 2002 , kedua-dua gol ini menduduki tempat ke-6 dalam 100 Greatest Sporting Moments oleh saluran Channel 4 UK .',
 [2, 2, 2, 2, 2, 2, 11, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])
[17]:
model.generate([x], max_length = 256)
[17]:
[[('Pada', 2),
  ('tahun', 2),
  ('2002', 2),
  (',', 2),
  ('kedua-dua', 2),
  ('gol', 2),
  ('beliau', 11),
  ('menduduki', 2),
  ('tempat', 2),
  ('ke-6', 2),
  ('dalam', 2),
  ('100', 2),
  ('Greatest', 2),
  ('Sporting', 2),
  ('Moments', 2),
  ('oleh', 2),
  ('saluran', 2),
  ('Channel', 2),
  ('4', 2),
  ('UK', 2),
  ('.', 2)]]
[18]:
x, y, t = get_xy(test_set[-2])
x, y, t
[18]:
('Gol inilah yang bergelar Goal of the Century dengan undian Internet 2000 sejak FIFA .',
 'Gol inilah yang bergelar Goal of the Century di undian Internet 2000 oleh FIFA .',
 [2, 2, 2, 2, 2, 2, 2, 2, 9, 2, 2, 2, 9, 2, 2])
[19]:
model.generate([x], max_length = 256)
[19]:
[[('Gol', 2),
  ('inilah', 2),
  ('yang', 2),
  ('bergelar', 2),
  ('Goal', 2),
  ('of', 2),
  ('the', 2),
  ('Century', 2),
  ('dalam', 9),
  ('undian', 2),
  ('Internet', 2),
  ('2000', 2),
  ('oleh', 9),
  ('FIFA', 2),
  ('.', 2)]]
[20]:
x, y, t = get_xy(test_set[-3])
x, y, t
[20]:
('Beliau mengambil bola dalam kawasan kepul diri lalu pusing dan luru lebih separuh padang sambil menyentuh bola 11 kali , memintas lima pemain England : ( Glenn Hoddle , Peter Reid , Kenny Sansom , Terry Butcher , dan Terry Fenwick ) serta penjaga gawang Peter Shilton .',
 'Beliau mengambil bola di kawasan pasukan diri lalu berpusing-pusing dan meluru lebih separuh padang sambil menyentuh bola 11 kali , memintas lima pemain England : ( Glenn Hoddle , Peter Reid , Kenny Sansom , Terry Butcher , dan Terry Fenwick ) serta penjaga gawang Peter Shilton .',
 [2,
  2,
  2,
  9,
  2,
  10,
  2,
  2,
  15,
  2,
  15,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2,
  2])
[21]:
model.generate([x], max_length = 256)
[21]:
[[('Beliau', 2),
  ('mengambil', 2),
  ('bola', 2),
  ('dalam', 2),
  ('kawasan', 2),
  ('pasukan', 10),
  ('berdiri', 15),
  ('lalu', 2),
  ('berpusing', 15),
  ('dan', 2),
  ('meluru', 15),
  ('lebih', 2),
  ('separuh', 2),
  ('padang', 2),
  ('sambil', 2),
  ('menyentuh', 2),
  ('bola', 2),
  ('11', 2),
  ('kali', 2),
  (',', 2),
  ('memintas', 2),
  ('lima', 2),
  ('pemain', 2),
  ('England', 2),
  (':', 2),
  ('(', 2),
  ('Glenn', 2),
  ('Hoddle', 2),
  (',', 2),
  ('Peter', 2),
  ('Reid', 2),
  (',', 2),
  ('Kenny', 2),
  ('Sansom', 2),
  (',', 2),
  ('Terry', 2),
  ('Butcher', 2),
  (',', 2),
  ('dan', 2),
  ('Terry', 2),
  ('Fenwick', 2),
  (')', 2),
  ('serta', 2),
  ('penjaga', 2),
  ('gawang', 2),
  ('Peter', 2),
  ('Shilton', 2),
  ('.', 2)]]

More examples#

I just copy pasted from https://ms.wikipedia.org/wiki/Kesalahan_biasa_tatabahasa_Melayu

[22]:
string = 'Tidak ada apa yang mereka risaukan waktu itu.'
model.generate([string], max_length = 256)
[22]:
[[('Tidak', 2),
  ('ada', 2),
  ('apa', 2),
  ('yang', 2),
  ('mereka', 2),
  ('risaukan', 2),
  ('waktu', 2),
  ('itu.', 2)]]
[23]:
string = 'Ayahnya setuju walaupun melanggar syarat yang dia sendiri menetapkan.'
model.generate([string], max_length = 256)
[23]:
[[('Ayahnya', 2),
  ('setuju', 2),
  ('dan', 7),
  ('melanggar', 2),
  ('syarat', 2),
  ('yang', 2),
  ('dia', 2),
  ('sendiri', 2),
  ('menetapkan', 2),
  ('.', 2)]]
[24]:
string = 'Semuanya dia kenal.'
model.generate([string], max_length = 256)
[24]:
[[('Semuanya', 2), ('dia', 2), ('kenal', 2), ('.', 2)]]
[25]:
string = 'Dia menjawab seperti disuruh-suruh oleh kuasa yang dia tidak tahu dari mana puncanya.'
model.generate([string], max_length = 256)
[25]:
[[('Dia', 2),
  ('menjawab', 2),
  ('seperti', 2),
  ('disuruh-suruh', 2),
  ('oleh', 2),
  ('kuasa', 2),
  ('yang', 2),
  ('dia', 2),
  ('tidak', 2),
  ('tahu', 2),
  ('dari', 2),
  ('mana', 2),
  ('puncanya.', 2)]]
[26]:
string = 'Bola ini ditendang oleh saya.'
model.generate([string], max_length = 256)
[26]:
[[('Bola', 2),
  ('ini', 2),
  ('ditendang', 2),
  ('oleh', 2),
  ('saya', 2),
  ('.', 2)]]
[27]:
string = 'Makanan ini kamu telah makan?'
model.generate([string], max_length = 256)
[27]:
[[('Makanan', 2),
  ('ini', 11),
  ('kamu', 2),
  ('telah', 2),
  ('makan', 2),
  ('.', 14)]]
[28]:
string = 'Segala perubahan yang berlaku kita akan menghadapi sama-sama.'
model.generate([string], max_length = 256)
[28]:
[[('Segala', 2),
  ('perubahan', 2),
  ('yang', 2),
  ('berlaku', 2),
  ('kita', 2),
  ('akan', 2),
  ('menghadapi', 2),
  ('sama-sama', 2),
  ('.', 2)]]
[29]:
string = 'Kakak saya sedang memasak gulai nangka. Dia menyenduk seketul nangka gulai dan menyuruh saya merasanya.'
model.generate([string], max_length = 256)
[29]:
[[('Kakak', 2),
  ('saya', 2),
  ('sedang', 2),
  ('memasak', 2),
  ('gulai', 2),
  ('nangka.', 2),
  ('Dia', 2),
  ('menyenduk', 2),
  ('seketul', 2),
  ('gulai', 3),
  ('nangka', 3),
  ('dan', 2),
  ('menyuruh', 2),
  ('saya', 2),
  ('merasanya.', 2)]]
[30]:
string = 'Sally sedang membaca bila saya tiba di rumahnya.'
model.generate([string], max_length = 256)
[30]:
[[('Sally', 2),
  ('sedang', 2),
  ('membaca', 2),
  ('bila', 2),
  ('saya', 11),
  ('tiba', 2),
  ('di', 2),
  ('rumahnya.', 2)]]
[31]:
string = 'Badannya besar kecuali kakinya kecil.'
model.generate([string], max_length = 256)
[31]:
[[('Badannya', 2),
  ('besar', 2),
  ('dan', 7),
  ('kakinya', 2),
  ('kecil', 2),
  ('.', 2)]]
[32]:
string = 'Beribu peniaga tidak membayar cukai pendapatan.'
model.generate([string], max_length = 256)
[32]:
[[('Beribu', 2),
  ('peniaga', 2),
  ('tidak', 2),
  ('membayar', 2),
  ('cukai', 2),
  ('pendapatan.', 2)]]
[33]:
string = 'Setengah remaja suka membuang masa di pasar raya.'
model.generate([string], max_length = 256)
[33]:
[[('Setengah', 2),
  ('remaja', 2),
  ('suka', 2),
  ('membuang', 2),
  ('masa', 2),
  ('di', 2),
  ('pasar', 2),
  ('raya.', 2)]]
[34]:
string = 'Umar telah berpindah daripada sekolah ini bulan lalu.'
model.generate([string], max_length = 256)
[34]:
[[('Umar', 2),
  ('telah', 2),
  ('berpindah', 2),
  ('ke', 9),
  ('sekolah', 2),
  ('ini', 2),
  ('bulan', 2),
  ('lalu', 2),
  ('.', 2)]]
[35]:
string = 'Para-para peserta sedang berbaris.'
model.generate([string], max_length = 256)
[35]:
[[('Para', 4), ('peserta', 2), ('sedang', 2), ('berbaris', 2), ('.', 2)]]