Kesalahan Tatabahasa with Tagging#

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

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

This interface deprecated, use HuggingFace interface instead.

[1]:
import os

os.environ['CUDA_VISIBLE_DEVICES'] = ''
[2]:
import logging

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

Model#

Common Seq2Seq model, P(yt | X, yt-1), one step decoder will generate yt, and this required encoder output and output from last step decoder, yt-1.

So we improve the model to general tags also, P(yt, zt | X, yt-1, zt-1), one step decoder will generate yt and zt, and this required encoder output and outputs from last step decoder, yt-1 and zt-1.

We named this model as TransformerTag.

There is no paper produced for this model, feel free to write a paper about it, check out our implementation at https://github.com/huseinzol05/malaya/tree/master/session/tatabahasa

[4]:
import warnings
warnings.filterwarnings('default')

List available Transformer models#

[5]:
malaya.tatabahasa.available_transformer()
/home/husein/dev/malaya/malaya/tatabahasa.py:156: DeprecationWarning: `malaya.tatabahasa.available_transformer` is deprecated, use `malaya.tatabahasa.available_huggingface` instead
  warnings.warn(
INFO:malaya.tatabahasa:tested on 5k generated dataset at https://f000.backblazeb2.com/file/malay-dataset/tatabahasa/test-set-tatabahasa.pkl
[5]:
Size (MB) Quantized Size (MB) Sequence Accuracy Sequence Tagging Accuracy
small 397.0 100.0 0.860198 0.963267
base 875.0 220.0 0.938972 0.977407

Supported kesalahan tatabahasa#

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

[6]:
malaya.tatabahasa.describe_tagging()
[6]:
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 Transformer Tag model#

def transformer(model: str = 'base', quantized: bool = False, **kwargs):
    """
    Load Malaya transformer encoder-decoder + tagging model to correct a `kesalahan tatabahasa` text.

    Parameters
    ----------
    model: str, optional (default='base')
        Check available models at `malaya.tatabahasa.available_transformer()`.
    quantized: bool, optional (default=False)
        if True, will load 8-bit quantized model.
        Quantized model not necessary faster, totally depends on the machine.

    Returns
    -------
    result: malaya.model.tf.Tatabahasa class
    """
[7]:
model = malaya.tatabahasa.transformer(model = 'base')
/home/husein/dev/malaya/malaya/tatabahasa.py:191: DeprecationWarning: `malaya.tatabahasa.transformer` is deprecated, use `malaya.tatabahasa.huggingface` instead
  warnings.warn(
2022-11-16 22:23:39.470583: I tensorflow/core/platform/cpu_feature_guard.cc:142] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2 FMA
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2022-11-16 22:23:39.496105: E tensorflow/stream_executor/cuda/cuda_driver.cc:271] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected
2022-11-16 22:23:39.496128: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:169] retrieving CUDA diagnostic information for host: husein-MS-7D31
2022-11-16 22:23:39.496131: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:176] hostname: husein-MS-7D31
2022-11-16 22:23:39.496218: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:200] libcuda reported version is: Not found: was unable to find libcuda.so DSO loaded into this program
2022-11-16 22:23:39.496241: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:204] kernel reported version is: 470.141.3
/home/husein/dev/malaya/malaya/tokenizer.py:208: FutureWarning: Possible nested set at position 2253
  self.tok = re.compile(r'({})'.format('|'.join(pipeline)))
/home/husein/dev/malaya/malaya/tokenizer.py:208: FutureWarning: Possible nested set at position 2771
  self.tok = re.compile(r'({})'.format('|'.join(pipeline)))

Load Quantized model#

To load 8-bit quantized model, simply pass quantized = True, default is False.

We can expect slightly accuracy drop from quantized model, and not necessary faster than normal 32-bit float model, totally depends on machine.

[2]:
quantized_model = malaya.tatabahasa.transformer(model = 'base', quantized = True)

Predict using greedy decoder#

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

    Parameters
    ----------
    strings : List[str]

    Returns
    -------
    result: List[str]
    """

For TransformerTag model, right now only supported greedy_decoder method.

Randomly picked string in bahasa melayu wikipedia.

[7]:
# https://ms.wikipedia.org/wiki/Bola_sepak
string = 'Pada amnya, hanya penjaga gol sahaja yang dibenarkan menyentuh bola dengan tangan di dalam kawasan golnya'
[8]:
model.greedy_decoder([string])
[8]:
[[('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.

[9]:
# https://ms.wikipedia.org/wiki/Bola_sepak
string = 'Pada amnya, hanya gol penjaga sahaja yang dibenarkan menyentuh bola dengan tangan di dalam kawasan golnya'
[10]:
model.greedy_decoder([string])
[10]:
[[('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)]]
[11]:
string = 'Sani mendapat markah yang tertinggi sekali.'
string1 = 'Hassan ialah peserta yang termuda sekali dalam pertandingan itu.'
model.greedy_decoder([string, string1])
[11]:
[[('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)]]
[12]:
string = 'Dia kata kepada saya.'
model.greedy_decoder([string])
[12]:
[[('Dia', 2), ('berkata', 15), ('kepada', 2), ('saya', 2), ('.', 2)]]
[13]:
import pickle

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

len(test_set)
[13]:
100
[14]:
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
[15]:
x, y, t = get_xy(test_set[0])
x, y, t
[15]:
('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])
[16]:
model.greedy_decoder([x])
[16]:
[[('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)]]
[17]:
quantized_model.greedy_decoder([x])
[17]:
[[('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)]]
[18]:
x, y, t = get_xy(test_set[-1])
x, y, t
[18]:
('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])
[19]:
model.greedy_decoder([x])
[19]:
[[('Pada', 2),
  ('tahun', 2),
  ('2002', 2),
  (',', 2),
  ('kedua-dua', 2),
  ('gol', 2),
  ('beliau', 2),
  ('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)]]
[20]:
x, y, t = get_xy(test_set[-2])
x, y, t
[20]:
('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])
[21]:
model.greedy_decoder([x])
[21]:
[[('Gol', 2),
  ('inilah', 2),
  ('yang', 2),
  ('bergelar', 2),
  ('Goal', 2),
  ('of', 2),
  ('the', 2),
  ('Century', 2),
  ('dengan', 2),
  ('undian', 2),
  ('Internet', 2),
  ('2000', 2),
  ('sejak', 2),
  ('FIFA', 2),
  ('.', 2)]]
[22]:
x, y, t = get_xy(test_set[-3])
x, y, t
[22]:
('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])
[23]:
model.greedy_decoder([x])
[23]:
[[('Beliau', 2),
  ('mengambil', 2),
  ('bola', 2),
  ('dari', 9),
  ('kawasan', 2),
  ('kaki', 10),
  ('diri', 2),
  ('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)]]
[24]:
quantized_model.greedy_decoder([x])
[24]:
[[('Beliau', 2),
  ('mengambil', 2),
  ('bola', 2),
  ('dari', 9),
  ('kawasan', 2),
  ('kaki', 10),
  ('diri', 2),
  ('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

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