معاينة مختبر آمنة
NER-TF
هذي معاينة منقّحة للقراءة فقط؛ ما فيه أي شيء يشتغل داخل الصفحة.
قراءة فقط
معاينة الدفتر
NER-TF
> **ملاحظة بيئة التشغيل المدمجة:** هالمعاينة تستخدم عيّنة صغيرة وثابتة وآمنة من ناحية الحقوق عشان تكون النتايج قابلة للتكرار. النتايج بالحجم الكامل تحتاج مجموعة البيانات أو النموذج الموثّق بالدرس داخل بيئة خارجية معتمدة.
# التعرّف على الكيانات المسماة (NER)
هالدفتر جزء من منهج «الذكاء الاصطناعي للمبتدئين».
في هالمثال، بنتعلّم كيف ندرّب نموذجًا للتعرّف على الكيانات المسماة (Named Entity Recognition — NER) باستخدام [Annotated Corpus for Named Entity Recognition](https://www.kaggle.com/datasets/abhinavwalia95/entity-annotated-corpus)، وهي مجموعة بيانات من Kaggle. قبل نبدأ، نزّلوا ملف [ner_dataset.csv](https://www.kaggle.com/datasets/abhinavwalia95/entity-annotated-corpus?resource=download&select=ner_dataset.csv) وحطّوه في المجلد الحالي.
import pandas as pd
from tensorflow import keras
import numpy as np## تجهيز مجموعة البيانات
بنبدأ بقراءة مجموعة البيانات داخل إطار بيانات (DataFrame). وإذا ودكم تعرفون أكثر عن استخدام Pandas، شوفوا [درس معالجة البيانات باستخدام Python](https://github.com/microsoft/Data-Science-For-Beginners/tree/4d2ac427ad6f022e73a75c4f46a28bbb7978ec3f/2-Working-With-Data/07-python) في [منهج Data Science for Beginners](https://github.com/microsoft/Data-Science-For-Beginners).
# Course-authored miniature named-entity dataset.
course_sentences = [
(("Aziz", "B-per"), ("visited", "O"), ("Riyadh", "B-geo"), ("today", "O")),
(("Sara", "B-per"), ("joined", "O"), ("Hala", "B-org"), ("Academy", "I-org")),
(("Omar", "B-per"), ("spoke", "O"), ("in", "O"), ("Jeddah", "B-geo")),
(("Noura", "B-per"), ("studies", "O"), ("artificial", "B-tim"), ("intelligence", "I-tim")),
(("Microsoft", "B-org"), ("opened", "O"), ("a", "O"), ("lab", "O")),
(("Layla", "B-per"), ("traveled", "O"), ("to", "O"), ("Diriyah", "B-geo")),
(("Fahad", "B-per"), ("built", "O"), ("a", "O"), ("robot", "O")),
(("Maha", "B-per"), ("attended", "O"), ("the", "O"), ("conference", "O")),
(("Aramco", "B-org"), ("announced", "O"), ("a", "O"), ("project", "O")),
(("Khalid", "B-per"), ("works", "O"), ("in", "O"), ("Dammam", "B-geo")),
(("Reem", "B-per"), ("teaches", "O"), ("machine", "O"), ("learning", "O")),
(("Saud", "B-per"), ("presented", "O"), ("at", "O"), ("KAUST", "B-org")),
]
records = []
for sentence_index, sentence in enumerate(course_sentences, start=1):
for word_index, (word, tag) in enumerate(sentence):
records.append({
"Sentence #": f"Sentence: {sentence_index}" if word_index == 0 else np.nan,
"Word": word,
"Tag": tag,
})
df = pd.DataFrame.from_records(records)
df.head()خلونا نطلع الوسوم الفريدة، ونبني قواميس بحث نستخدمها لتحويل كل وسم إلى رقم فئة:
PAD_TAG = "<PAD>"
tags = sorted(df["Tag"].dropna().unique().tolist())
tags[:10]id2tag = {0: PAD_TAG, **{index + 1: tag for index, tag in enumerate(tags)}}
tag2id = {tag: index for index, tag in id2tag.items()}
PAD_TAG_ID = tag2id[PAD_TAG]
id2tag[PAD_TAG_ID]الحين نبي نسوي الشي نفسه مع المفردات. للتبسيط، بنبني المفردات من دون ما نحسب تكرار الكلمات. في تطبيق فعلي، الأفضل تستخدمون محوّل Keras إلى متجهات (vectorizer)، وتحطّون حدًا لعدد الكلمات.
PAD_WORD = "<PAD>"
OOV_WORD = "<OOV>"
words = sorted({str(word).lower() for word in df["Word"].dropna()})
id2word = {0: PAD_WORD, 1: OOV_WORD, **{index + 2: word for index, word in enumerate(words)}}
word2id = {word: index for index, word in id2word.items()}
PAD_WORD_ID = word2id[PAD_WORD]
OOV_WORD_ID = word2id[OOV_WORD]نبي نجهّز مجموعة جمل للتدريب. خلونا نمشي على مجموعة البيانات الأصلية ونفصل كل جملة لحالها داخل `X` (قوائم الكلمات) و`Y` (قوائم الوسوم):
X,Y = [],[]
s,t = [],[]
for i,row in df[['Sentence #','Word','Tag']].iterrows():
if pd.isna(row['Sentence #']):
s.append(row['Word'])
t.append(row['Tag'])
else:
if len(s)>0:
X.append(s)
Y.append(t)
s,t = [row['Word']],[row['Tag']]
X.append(s)
Y.append(t)الحين بنحوّل كل الكلمات والوسوم إلى متجهات رقمية:
def vectorize(sequence):
return [word2id.get(str(word).lower(), OOV_WORD_ID) for word in sequence]
def tagify(sequence):
return [tag2id[tag] for tag in sequence]
Xv = list(map(vectorize, X))
Yv = list(map(tagify, Y))
Xv[0], Yv[0]للتبسيط، بنحشّي كل الجمل برموز قيمتها 0 لين توصل للطول الأقصى. في تطبيق فعلي، ممكن نستخدم طريقة أذكى ونحشّي التسلسلات داخل كل دفعة مصغّرة (minibatch) بس.
X_data = keras.utils.pad_sequences(Xv, padding="post", value=PAD_WORD_ID)
Y_data = keras.utils.pad_sequences(Yv, padding="post", value=PAD_TAG_ID)
token_weights = (Y_data != PAD_TAG_ID).astype("float32")## تعريف شبكة تصنيف الرموز
بنستخدم شبكة LSTM ثنائية الاتجاه ومكوّنة من طبقتين لمهمة التصنيف على مستوى الرموز. وعشان نطبّق المصنّف الكثيف على كل مخرج من الطبقة الأخيرة في LSTM، بنستخدم البنية `TimeDistributed`. هالبنية تكرّر الطبقة الكثيفة نفسها على كل مخرج من مخرجات LSTM في كل خطوة:
maxlen = X_data.shape[1]
vocab_size = len(word2id)
num_tags = len(tag2id)
model = keras.models.Sequential([
keras.Input(shape=(maxlen,), dtype="int32"),
keras.layers.Embedding(vocab_size, 24, mask_zero=True),
keras.layers.Bidirectional(keras.layers.LSTM(24, return_sequences=True)),
keras.layers.Bidirectional(keras.layers.LSTM(24, return_sequences=True)),
keras.layers.Dense(num_tags, activation="softmax"),
])
model.compile(loss="sparse_categorical_crossentropy", optimizer="adam", metrics=["accuracy"])
model.summary()لاحظوا إننا حددنا `maxlen` لمجموعة البيانات بشكل صريح. لو بغينا الشبكة تتعامل مع تسلسلات أطوالها مختلفة، لازم نعرّف الشبكة بطريقة أذكى.
الحين بندرّب النموذج. عشان نختصر الوقت، التدريب هنا لحقبة (epoch) وحدة بس، لكن تقدرون تجرّبون حقبًا أكثر. وتقدرون بعد تفصلون جزءًا من مجموعة البيانات أثناء التدريب عشان تراقبون دقة التحقق.
model.fit(X_data, Y_data, sample_weight=token_weights, epochs=2, validation_split=0.1)## اختبار النتيجة
خلونا نشوف كيف يشتغل نموذج التعرّف على الكيانات عندنا على جملة تجريبية:
sent = "John Smith went to Paris to attend a conference in cancer development institute"
words = sent.lower().split()
encoded = [word2id.get(word, OOV_WORD_ID) for word in words]
v = keras.utils.pad_sequences([encoded], padding="post", maxlen=maxlen, value=PAD_WORD_ID)
res = model(v, training=False)[0]predicted = np.argmax(res.numpy(), axis=1)[:len(words)]
for tag_id, word in zip(predicted, words):
print(f"{word} -> {id2tag.get(int(tag_id), '<UNKNOWN_TAG>')}")## الزبدة
حتى نموذج LSTM البسيط يعطي نتائج معقولة في NER. بس إذا نبغى نتائج أحسن بكثير، نقدر نستخدم نماذج لغوية كبيرة مدرّبة مسبقًا، مثل BERT. شرح تدريب BERT على NER باستخدام مكتبة Hugging Face Transformers موجود [هنا](https://huggingface.co/course/chapter7/2?fw=pt).
حذفنا المخرجات وعدّادات التشغيل والودجات والمحتوى النشط وقت الاستيراد. شغّل الدفاتر بس في بيئة خارجية تثق فيها.
سجّل تطبيقك
التسجيل اختياري، يفيدك تتذكر وش طبّقت، ولا يمنع إكمال الدورة.