Perhatian. Ia merupakan sesuatu yang unik yang hanya dimiliki oleh manusia dan makhluk hidup. Ia tak wujud pada objek yang tak mempunyai roh, pada objek yang tak hidup seperti mesin. Dengan perhatian kita boleh belajar, kita boleh menganalisis dan kita boleh mencipta. Ia merupakan satu anugerah Tuhan yang kita sering ambil ringan. Kerana tanpa perhatian, kita tak akan mampu melakukan dengan baik tugas seharian yang diamanahkan kepada kita. Tapi, dengan kewujudan media sosial seperti Fb, Instagram dan terbaharu TikTok, kita dapati yang perhatian yang sentiasa ada pada manusia semakin lama semakin berkurang. Boleh baca di pautan di bawah,
Tambah menakutkan lagi, perhatian sudah mula wujud pada mesin. Pada AI. Ini kerana, mannequin transformer yang berdiri di belakang ChatGPT itu menggunakan sepenuhnya perhatian mekanisma perhatian. Mari saya terangkan lebih mendalam.
Sebelum wujudnya mannequin transformer, kebanyakan penyelidik AI bergantung pada mannequin Recurrent Neural Community (RNN) ataupun mannequin LSTM (Lengthy Brief time period reminiscence). Kedua-dua mannequin ini mempunyai masalah ketika latihan kerana ia kurang efisyen dan memerlukan kuasa komputasi yang besar. Oleh kerana itulah mekanisma perhatian diwujudkan bagi menambahbaik kedua-dua mannequin ini. Di awalnya, itulah fungsi mekanisma perhatian. Hanya penambahbaikan kecil, tapi secara asasnya ia masih lagi menggunakan mannequin berturut (sequencing mannequin). Transformer yang diperkenalkan pada tahun 2017 merupakan mannequin pertama yang menggunakan mekanisma perhatian sepenuhnya, menggantikan RNN dan juga LSTM.
Dan hari ini, kita akan belajar sedikit bagaimana untuk melakukan mekanisma perhatian dari kosong, dari asas sekali. Supaya kita yang semakin hilang perhatian ini tak tenggelam dek arus kemodenan
Sebelum kita faham dulu apa itu perhatian, kita perlu tahu apa masalah yang sepatutnya diselesaikan oleh mekanisma perhatian. Seperti yang kita tahu, mannequin Seq2Seq yang sering digunakan untuk kerja terjemahan membaca teks mengikut urutan. Namun begitu, mannequin Seq2Seq seperti RNN dan LSTM tidak mampu mengingat keseluruhan teks. Terjemahan itu boleh dilakukan jika ayat yang ingin diterjemah itu pendek. Tapi jika ianya panjang (melibatkan beratus, malah beribu perkataan) ia tak mampu mengingati keseluruhan perkataan tersebut. Dan inilah yang membawa kepada masalah ketika proses penterjemahan.
Di saat inilah, para penyelidik AI kembali kepada ciptaan Tuhan untuk inspirasi. Penyelidik AI sedar yang memang manusia itu membaca sesuatu mengikut urutan seperti mana dilakukan oleh mannequin Seq2Seq. Tapi pada masa yang sama, manusia juga mempunyai sesuatu yang dipanggil sebagai perhatian, yang membolehkan mereka melihat pada sesuatu perkataan (atau frasa) pada waktu-waktu yang tertentu yang membolehkan mereka mengingat dan memahami konteks apa yang mereka baca.
Dari situlah wujudnya mekanisma perhatian. Sesuatu yang direka bagi membolehkan mannequin AI memahami konteks ayat yang dimasukkan secara keseluruhan. Mekanisma perhatian terdiri dari tiga komponen utama.
1. Question : ‘Soalan’ yang kita ingin tanyakan berdasarkan enter yang kita ingin masukkan. Ia diwakili oleh matriks yang terdiri dari vektor.
2. Key: ‘Kunci’ ataupun ‘penerangan’ yang kita ingin gunakan bagi menerangkan soalan yang kita ingin tanyakan.
3. Worth : Nilai sebenar enter ynag kita masukkan.
Kesemua question, key dan worth ini diwakili oleh matriks dan disusun dalam bentuk jaringan neural. Kesemua pemberat ini akan dimulakan dengan nilai awal yang akan terus diperkemaskini dengan jaringan neural.
#kita mulakan dengan satu set perkataan, dan kita beri label nombor bagi setiap perkataan
ayat = 'Hidup ini keras, tapi jalan raya lebih lagi'#kita simpan perkataan dan label ini dalam set kamus (dictionary)
dc = {s:i for i,s in enumerate(sorted(ayat.exchange(',', '').cut up()))}
print(dc)
Kod ini akan menghasilkan satu kamus senarai perkataan seperti di bawah:
#mari kita masukkan label tu dalam satu set kamus (dictionary)
import torchayat_int = torch.tensor([dc[s] for s in ayat.exchange(',', '').cut up()])
print(ayat_int)
Dan ini mewujudkan satu tensor seperti di bawah:
Sekarang, perkataan kita sudah tersedia. Mari kita cuba gantikan setiap perkataan ini dengan vektor penanaman. Dalam kes ini kita akan menukarkan semua perkataan dalam ayat ini kepada vektor 16 dimensi. Memandangkan kita ada 8 patah perkataan, maka vektor kita akan bersaiz 8 x 16.
torch.manual_seed(123)
#kita tanam perkataan kita dengan 16 dimensi, jadi bentuknya 8x16
tanam = torch.nn.Embedding(8, 16)
tanam_ayat = tanam(ayat_int).detach()#mari kita cetak vektor yang dah ditanam, kita cetak sekali bentuknya
print(tanam_ayat)
print(tanam_ayat.form)
#okay, sekarang mari kita letakkan nilai awal untuk semua pemberat question, key dan worth kita.
#sebelum tu mari ktia set dimensinya sebagai 24. perlu diingatkan yang question dan key perlu didarabkan bersama, jadi nilai dimensi mereka perlu sama.
#tapi ia tak terpakai untuk dimensi worth.torch.manual_seed(123)
d = tanam_ayat.form[1]
d_q, d_k, d_v = 24, 24, 28
W_query = torch.nn.init.xavier_uniform_(torch.empty(d_q, d))
W_key = torch.nn.init.xavier_uniform_(torch.empty(d_k, d))
W_value = torch.nn.init.xavier_uniform_(torch.empty(d_v, d))
Okay, sekarang, kita akan cuba untuk menggunakan mekanisma perhatian ini (consideration mechanism), bagi meletakkan nilai konteks bagi setiap perkataan yang kita masukkan. Secara asasnya, jika kita melihat perkataan keras, kita boleh melihat yang konteks dia lebih dekat dengan perkataan jalan, berbanding dengan perkataan hidup. Mari kita cuba hipotesis tersebut dalam kod di bawah.
#mari kita dapatkan nilai question, key dan worth bagi perkataan "keras".
x_3 = tanam_ayat[2]
query_3 = W_query.matmul(x_3)
key_3 = W_key.matmul(x_3)
value_3 = W_value.matmul(x_3)#mari kita cuba dapatkan nilai key dan worth vektor bagi setiap enter perkataan yang kita masukkan
keys = W_key.matmul(tanam_ayat.T).T
values = W_value.matmul(tanam_ayat.T).T
#mari kita tengok dalam senarai dictionary kita, perkataan keras (no.3) sepatutnya lebih dekat dengan perkataan jalan (no.4)
omega_24 = query_3.dot(keys[4])
print(omega_24)
Hm, nampaknya nilai dot product untuk perkataan ‘jalan’ terlalu rendah untuk dikaitkan dengan perkataan ‘keras’. Mari kita cuba untuk dapatkan markah perhatian bagi setiap perkataan.
#mari kita cuba dapatkan markah perhatian (consideration scores) bagi setiap perkataan yang kita masukkan
omega_3 = query_3.matmul(keys.T)
print(omega_3)
Hm, nampaknya kita boleh agak perkataan mana yang mempunyai markah perhatian yang tertinggi. Tapi bagi memudahkan pemahaman, seeloknya kita tukarkan nilai markah perhatian ini kepada nilai kebarangkalian. mari gunakan persamaan softmax yang kita sudah pelajari dalam siri-siri yang lepas.
import torch.nn.purposeful as Fpemberat_perhatian = F.softmax(omega_3 / d_k**0.5, dim=0)
# mari cari nilai markah perhatian yang paling tinggi
indeks_tertinggi = torch.argmax(pemberat_perhatian).merchandise()
# mari kita terbalikkan proses tadi bagi mencari perkataan dengan markah perhatian tertinggi
reverse_dc = {i: s for s, i in dc.gadgets()}
print("Kamus yang sudah diterbalikkan(dari indeks ke perkataan):", reverse_dc)
# perkataan dengan indeks skor tertinggi
perkataan_skor_tertinggi = reverse_dc[indeks_tertinggi]
print("Perkataan dengan markah perhatian tertinggi:", perkataan_skor_tertinggi)
perkataan_skor_tertinggi,pemberat_perhatian
Owh wow. Nampaknya hipotesis kita meleset. Kita boleh nampak yang perkataan ‘keras’ mempunyai nilai perhatian yang lebih tinggi pada perkataan hidup. Ini barangkali kerana kita menyusun perkataan ‘hidup’ lebih dekat dengan ‘keras’ berbanding perkataan ‘keras’ dengan perkataan ‘jalan’.
Tapi perlu diingatkan bahawa nilai pemberat yang kita gunakan ini masih lagi nilai awal yang belum dilatih. Jadi markah perhatian yang kita dapat itu masih belum diperkemaskini dengan proses backpropagation. Tapi katakanlah, kita ingin melatih jaringan neural mekanisma perhatian kita. Mari kita lihat sama ada markah perhatian ini akan berubah atau tidak selepas latihan.
Untuk latihan, saya akan menggunakan bantuan ChatGPT. Saya meminta ChatGPT untuk menghasilkan satu fungsi latihan yang ringkas buat mannequin perhatian yang saya sudah karang, dan melihat sama ada ia mampu menunjukkan perkataan mana yang mempunyai markah perhatian yang paling tinggi
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.purposeful as F# Outline a easy mannequin with embedding, consideration, and prediction layers
class SimpleAttentionModel(nn.Module):
def __init__(self, vocab_size, emb_dim, d_q, d_k, d_v, output_dim):
tremendous(SimpleAttentionModel, self).__init__()
self.embedding = nn.Embedding(vocab_size, emb_dim)
self.W_query = nn.Linear(emb_dim, d_q)
self.W_key = nn.Linear(emb_dim, d_k)
self.W_value = nn.Linear(emb_dim, d_v)
self.fc = nn.Linear(d_v, output_dim)
def ahead(self, x):
embedded = self.embedding(x)
question = self.W_query(embedded)
keys = self.W_key(embedded)
values = self.W_value(embedded)
# Compute consideration scores
scores = torch.matmul(question, keys.transpose(-2, -1)) / (keys.form[-1] ** 0.5)
attention_weights = F.softmax(scores, dim=-1)
# Compute the weighted sum of values
context = torch.matmul(attention_weights, values)
# Go the context vector by the totally related layer
output = self.fc(context.sum(dim=1))
return output, attention_weights
# Pattern information
sentences = [
'Hidup ini keras',
'tapi jalan raya lebih lagi'
]
labels = torch.tensor([0, 1]) # Instance labels for binary classification
# Create the vocabulary
vocab = sorted(set(' '.be a part of(sentences).exchange(',', '').cut up()))
vocab_size = len(vocab)
word_to_index = {phrase: idx for idx, phrase in enumerate(vocab)}
# Convert sentences to tensor of indices with padding
def sentences_to_tensor(sentences, word_to_index, max_length):
padded_sentences = []
for sentence in sentences:
phrases = sentence.cut up()
indices = [word_to_index[word] for phrase in phrases]
if len(indices) < max_length:
indices += [0] * (max_length - len(indices)) # Pad with zeros
padded_sentences.append(indices)
return torch.tensor(padded_sentences)
# Decide the utmost sentence size
max_length = max(len(sentence.cut up()) for sentence in sentences)
inputs = sentences_to_tensor(sentences, word_to_index, max_length)
# Parameters
emb_dim = 16
d_q, d_k, d_v = 24, 24, 28
output_dim = 2 # Binary classification
# Initialize the mannequin, loss perform, and optimizer
mannequin = SimpleAttentionModel(vocab_size, emb_dim, d_q, d_k, d_v, output_dim)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(mannequin.parameters())
# Coaching loop
n_epochs = 100
for epoch in vary(n_epochs):
mannequin.practice()
optimizer.zero_grad()
outputs, attention_weights = mannequin(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
if (epoch + 1) % 10 == 0:
print(f'Epoch {epoch+1}/{n_epochs}, Loss: {loss.merchandise()}')
# Take a look at the mannequin with consideration weights
mannequin.eval()
outputs, attention_weights = mannequin(inputs)
print("Consideration weights after coaching:", attention_weights)
# Discover the phrase with the best consideration rating for every sentence
highest_attention_words = []
for i, sentence_attention_weights in enumerate(attention_weights):
for head_attention_weights in sentence_attention_weights:
highest_score_index = torch.argmax(head_attention_weights).merchandise()
highest_attention_word = vocab[highest_score_index]
highest_attention_words.append(highest_attention_word)
highest_attention_words
Kita boleh nampak yang selepas latihan, perkataan dengan markah perhatian yang tertinggi adalah ‘hidup’, ‘jalan’ dan ‘lagi’. Kesemua ini menunjukkan yang mannequin itu sudahpun belajar apakah perkataan yang sepatutnya menjadi perhatian mereka. Dan sepatutnya,markah perhatian ini akan bertambah baik bergantung kepada berapa banyak perkataan yang kita masukkan ketika latihan.
Tapi cukuplah sekadar ini dahulu untuk kali ini.