Kesalahan Tatabahasa with Tagging
Contents
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.
[1]:
import malaya
from pprint import pprint
/home/husein/dev/malaya/malaya/tokenizer.py:214: FutureWarning: Possible nested set at position 3397
self.tok = re.compile(r'({})'.format('|'.join(pipeline)))
/home/husein/dev/malaya/malaya/tokenizer.py:214: FutureWarning: Possible nested set at position 3927
self.tok = re.compile(r'({})'.format('|'.join(pipeline)))
List available HuggingFace models#
[2]:
malaya.tatabahasa.available_huggingface
[2]:
{'mesolitica/finetune-tatabahasa-t5-tiny-standard-bahasa-cased': {'Size (MB)': 139,
'exactly-match': 0.7665198237,
'f1': 0.970908229,
'exactly-match-tags': 0.87404885863,
'f1-tags': 0.9878723587,
'Suggested length': 256},
'mesolitica/finetune-tatabahasa-t5-small-standard-bahasa-cased': {'Size (MB)': 242,
'exactly-match': 0.8145774929,
'f1': 0.9781278,
'exactly-match-tags': 0.89447336,
'f1-tags': 0.990597377,
'Suggested length': 256},
'mesolitica/finetune-tatabahasa-t5-base-standard-bahasa-cased': {'Size (MB)': 892,
'exactly-match': 0.760913095,
'f1': 0.970136249,
'exactly-match-tags': 0.865839,
'f1-tags': 0.9868999035,
'Suggested length': 256}}
Supported kesalahan tatabahasa#
For full description, check out https://tatabahasabm.tripod.com/tata/salahtata.htm
[3]:
malaya.tatabahasa.describe
[3]:
[{'class': 0, 'Description': 'PAD', 'salah': '', 'betul': ''},
{'class': 1, 'Description': 'kesambungan subwords', 'salah': '', 'betul': ''},
{'class': 2, 'Description': 'tiada kesalahan', 'salah': '', 'betul': ''},
{'class': 3,
'Description': 'kesalahan frasa nama, Perkara yang diterangkan mesti mendahului "penerang"',
'salah': 'Cili sos',
'betul': 'sos cili'},
{'class': 4,
'Description': 'kesalahan kata jamak',
'salah': 'mereka-mereka',
'betul': 'mereka'},
{'class': 5,
'Description': 'kesalahan kata penguat',
'salah': 'sangat tinggi sekali',
'betul': 'sangat tinggi'},
{'class': 6,
'Description': 'kata adjektif dan imbuhan "ter" tanpa penguat.',
'salah': 'Sani mendapat markah yang tertinggi sekali.',
'betul': 'Sani mendapat markah yang tertinggi.'},
{'class': 7,
'Description': 'kesalahan kata hubung',
'salah': 'Sally sedang membaca bila saya tiba di rumahnya.',
'betul': 'Sally sedang membaca apabila saya tiba di rumahnya.'},
{'class': 8,
'Description': 'kesalahan kata bilangan',
'salah': 'Beribu peniaga tidak membayar cukai pendapatan.',
'betul': 'Beribu-ribu peniaga tidak membayar cukai pendapatan'},
{'class': 9,
'Description': 'kesalahan kata sendi',
'salah': 'Umar telah berpindah daripada sekolah ini bulan lalu.',
'betul': 'Umar telah berpindah dari sekolah ini bulan lalu.'},
{'class': 10,
'Description': 'kesalahan penjodoh bilangan',
'salah': 'Setiap orang pelajar',
'betul': 'Setiap pelajar.'},
{'class': 11,
'Description': 'kesalahan kata ganti diri',
'salah': 'Pencuri itu telah ditangkap. Beliau dibawa ke balai polis.',
'betul': 'Pencuri itu telah ditangkap. Dia dibawa ke balai polis.'},
{'class': 12,
'Description': 'kesalahan ayat pasif',
'salah': 'Cerpen itu telah dikarang oleh saya.',
'betul': 'Cerpen itu telah saya karang.'},
{'class': 13,
'Description': 'kesalahan kata tanya',
'salah': 'Kamu berasal dari manakah ?',
'betul': 'Kamu berasal dari mana ?'},
{'class': 14,
'Description': 'kesalahan tanda baca',
'salah': 'Kamu berasal dari manakah .',
'betul': 'Kamu berasal dari mana ?'},
{'class': 15,
'Description': 'kesalahan kata kerja tak transitif',
'salah': 'Dia kata kepada saya',
'betul': 'Dia berkata kepada saya'},
{'class': 16,
'Description': 'kesalahan kata kerja transitif',
'salah': 'Dia suka baca buku',
'betul': 'Dia suka membaca buku'},
{'class': 17,
'Description': 'penggunaan kata yang tidak tepat',
'salah': 'Tembuk Besar negeri Cina dibina oleh Shih Huang Ti.',
'betul': 'Tembok Besar negeri Cina dibina oleh Shih Huang Ti'}]
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',
force_check: bool = True,
**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`.
force_check: bool, optional (default=True)
Force check model one of malaya model.
Set to False if you have your own huggingface model.
Returns
-------
result: malaya.torch_model.huggingface.Tatabahasa
"""
[4]:
model = malaya.tatabahasa.huggingface()
Loading the tokenizer from the `special_tokens_map.json` and the `added_tokens.json` will be removed in `transformers 5`, it is kept for forward compatibility, but it is recommended to update your `tokenizer_config.json` by uploading it again. You will see the new `added_tokens_decoder` attribute that will store the relevant information.
You are using the default legacy behaviour of the <class 'transformers.models.t5.tokenization_t5.T5Tokenizer'>. If you see this, DO NOT PANIC! This is expected, and simply means that the `legacy` (previous) behavior will be used so nothing changes for you. If you want to use the new behaviour, set `legacy=False`. This should only be set if you understand what it means, and thouroughly read the reason why this was added as explained in https://github.com/huggingface/transformers/pull/24565
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.
[5]:
# https://ms.wikipedia.org/wiki/Bola_sepak
string = 'Pada amnya, hanya penjaga gol sahaja yang dibenarkan menyentuh bola dengan tangan di dalam kawasan golnya'
[6]:
model.generate([string], max_length = 256)
[6]:
[[('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
.
[7]:
# https://ms.wikipedia.org/wiki/Bola_sepak
string = 'Pada amnya, hanya gol penjaga sahaja yang dibenarkan menyentuh bola dengan tangan di dalam kawasan golnya'
[8]:
model.generate([string], max_length = 256)
[8]:
[[('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)]]
[9]:
string = 'Sani mendapat markah yang tertinggi sekali.'
string1 = 'Hassan ialah peserta yang termuda sekali dalam pertandingan itu.'
model.generate([string, string1], max_length = 256)
[9]:
[[('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)]]
[10]:
string = 'Dia kata kepada saya.'
model.generate([string], max_length = 256)
[10]:
[[('Dia', 2), ('berkata', 15), ('kepada', 2), ('saya', 2), ('.', 2)]]
[11]:
import pickle
with open('tests/dataset-tatabahasa.pkl', 'rb') as fopen:
test_set = pickle.load(fopen)
len(test_set)
[11]:
100
[12]:
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
[13]:
x, y, t = get_xy(test_set[0])
x, y, t
[13]:
('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])
[14]:
model.generate([x], max_length = 256)
[14]:
[[('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)]]
[15]:
x, y, t = get_xy(test_set[-1])
x, y, t
[15]:
('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])
[16]:
model.generate([x], max_length = 256)
[16]:
[[('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)]]
[17]:
x, y, t = get_xy(test_set[-2])
x, y, t
[17]:
('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])
[18]:
model.generate([x], max_length = 256)
[18]:
[[('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)]]
[19]:
x, y, t = get_xy(test_set[-3])
x, y, t
[19]:
('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])
[20]:
model.generate([x], max_length = 256)
[20]:
[[('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
[21]:
string = 'Tidak ada apa yang mereka risaukan waktu itu.'
model.generate([string], max_length = 256)
[21]:
[[('Tidak', 2),
('ada', 2),
('apa', 2),
('yang', 2),
('mereka', 2),
('risaukan', 2),
('waktu', 2),
('itu.', 2)]]
[22]:
string = 'Ayahnya setuju walaupun melanggar syarat yang dia sendiri menetapkan.'
model.generate([string], max_length = 256)
[22]:
[[('Ayahnya', 2),
('setuju', 2),
('dan', 7),
('melanggar', 2),
('syarat', 2),
('yang', 2),
('dia', 2),
('sendiri', 2),
('menetapkan', 2),
('.', 2)]]
[23]:
string = 'Semuanya dia kenal.'
model.generate([string], max_length = 256)
[23]:
[[('Semuanya', 2), ('dia', 2), ('kenal', 2), ('.', 2)]]
[24]:
string = 'Dia menjawab seperti disuruh-suruh oleh kuasa yang dia tidak tahu dari mana puncanya.'
model.generate([string], max_length = 256)
[24]:
[[('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)]]
[25]:
string = 'Bola ini ditendang oleh saya.'
model.generate([string], max_length = 256)
[25]:
[[('Bola', 2),
('ini', 2),
('ditendang', 2),
('oleh', 2),
('saya', 2),
('.', 2)]]
[26]:
string = 'Makanan ini kamu telah makan?'
model.generate([string], max_length = 256)
[26]:
[[('Makanan', 2),
('ini', 11),
('kamu', 2),
('telah', 2),
('makan', 2),
('.', 14)]]
[27]:
string = 'Segala perubahan yang berlaku kita akan menghadapi sama-sama.'
model.generate([string], max_length = 256)
[27]:
[[('Segala', 2),
('perubahan', 2),
('yang', 2),
('berlaku', 2),
('kita', 2),
('akan', 2),
('menghadapi', 2),
('sama-sama', 2),
('.', 2)]]
[28]:
string = 'Kakak saya sedang memasak gulai nangka. Dia menyenduk seketul nangka gulai dan menyuruh saya merasanya.'
model.generate([string], max_length = 256)
[28]:
[[('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)]]
[29]:
string = 'Sally sedang membaca bila saya tiba di rumahnya.'
model.generate([string], max_length = 256)
[29]:
[[('Sally', 2),
('sedang', 2),
('membaca', 2),
('bila', 2),
('saya', 11),
('tiba', 2),
('di', 2),
('rumahnya.', 2)]]
[30]:
string = 'Badannya besar kecuali kakinya kecil.'
model.generate([string], max_length = 256)
[30]:
[[('Badannya', 2),
('besar', 2),
('dan', 7),
('kakinya', 2),
('kecil', 2),
('.', 2)]]
[31]:
string = 'Beribu peniaga tidak membayar cukai pendapatan.'
model.generate([string], max_length = 256)
[31]:
[[('Beribu', 2),
('peniaga', 2),
('tidak', 2),
('membayar', 2),
('cukai', 2),
('pendapatan.', 2)]]
[32]:
string = 'Setengah remaja suka membuang masa di pasar raya.'
model.generate([string], max_length = 256)
[32]:
[[('Setengah', 2),
('remaja', 2),
('suka', 2),
('membuang', 2),
('masa', 2),
('di', 2),
('pasar', 2),
('raya.', 2)]]
[33]:
string = 'Umar telah berpindah daripada sekolah ini bulan lalu.'
model.generate([string], max_length = 256)
[33]:
[[('Umar', 2),
('telah', 2),
('berpindah', 2),
('ke', 9),
('sekolah', 2),
('ini', 2),
('bulan', 2),
('lalu', 2),
('.', 2)]]
[34]:
string = 'Para-para peserta sedang berbaris.'
model.generate([string], max_length = 256)
[34]:
[[('Para', 4), ('peserta', 2), ('sedang', 2), ('berbaris', 2), ('.', 2)]]