> **ملاحظة بيئة التشغيل المدمجة:** هالمعاينة تستخدم عيّنة صغيرة وثابتة وآمنة من ناحية الحقوق عشان تكون النتايج قابلة للتكرار. النتايج بالحجم الكامل تحتاج مجموعة البيانات أو النموذج الموثّق بالدرس داخل بيئة خارجية معتمدة.
# التصنيف متعدد الفئات باستخدام البيرسيبترون (Perceptron)
هالتكليف جزء من منهج AI for Beginners.
import random
import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import load_digits
from types import SimpleNamespace
تقدرون تستخدمون كود تدريب البيرسيبترون التالي من الدرس:
def train(positive_examples, negative_examples, num_iterations = 100):
num_dims = positive_examples.shape[1]
weights = np.zeros((num_dims,1)) # initialize weights
pos_count = positive_examples.shape[0]
neg_count = negative_examples.shape[0]
report_frequency = 10
for i in range(num_iterations):
pos = random.choice(positive_examples)
neg = random.choice(negative_examples)
z = np.dot(pos, weights)
if z < 0:
weights = weights + pos.reshape(weights.shape)
z = np.dot(neg, weights)
if z >= 0:
weights = weights - neg.reshape(weights.shape)
if i % report_frequency == 0:
pos_out = np.dot(positive_examples, weights)
neg_out = np.dot(negative_examples, weights)
pos_correct = (pos_out >= 0).sum() / float(pos_count)
neg_correct = (neg_out < 0).sum() / float(neg_count)
print("Iteration={}, pos correct={}, neg correct={}".format(i,pos_correct,neg_correct))
return weights
def accuracy(weights, test_x, test_labels):
res = np.dot(np.c_[test_x,np.ones(len(test_x))],weights)
return (res.reshape(test_labels.shape)*test_labels>=0).sum()/float(len(test_labels))
### استخدام عيّنة الأرقام المدمجة
> تستخدم هالنسخة عيّنة الأرقام المكتوبة بخط اليد المدمجة مع scikit-learn، وتكبّر صورها من 8×8 إلى 28×28 بطريقة ثابتة. العيّنة أصغر من MNIST وما تحتاج اتصال بالشبكة؛ لذلك تختلف أعداد العينات والنتائج عن تمرين MNIST الأصلي.
_course_digits = load_digits()
_course_images = np.kron(_course_digits.images.astype(np.float32) / 16.0, np.ones((3, 3), dtype=np.float32))
_course_images = np.pad(_course_images, ((0, 0), (2, 2), (2, 2)))
mnist = SimpleNamespace(
data=(_course_images.reshape(len(_course_images), -1) * 255.0).astype(np.float32),
target=np.asarray(_course_digits.target, dtype=np.int64),
)
all_features = np.asarray(mnist.data, dtype=np.float32)
all_labels = np.asarray(mnist.target, dtype=np.int64)
train_size = int(0.8 * len(all_features))
MNIST = {
"Train": {
"Features": all_features[:train_size],
"Labels": all_labels[:train_size],
},
"Test": {
"Features": all_features[train_size:],
"Labels": all_labels[train_size:],
},
}
print(MNIST['Train']['Features'][0][130:180])
print(MNIST['Train']['Labels'][0])
features = MNIST['Train']['Features'].astype(np.float32) / 255.0
labels = MNIST['Train']['Labels']
fig = plt.figure(figsize=(10,5))
for i in range(10):
ax = fig.add_subplot(1,10,i+1)
plt.imshow(features[i].reshape(28,28))
plt.show()
هالكود ينشئ مجموعة البيانات بأسلوب *رقم مقابل رقم آخر* عشان يسوي التصنيف لرقمين. عدّلوه عشان ينشئ مجموعة *رقم واحد مقابل كل الأرقام الثانية* (one-vs-all).
def set_mnist_pos_neg(positive_label, negative_label):
positive_indices = [i for i, j in enumerate(MNIST['Train']['Labels'])
if j == positive_label]
negative_indices = [i for i, j in enumerate(MNIST['Train']['Labels'])
if j == negative_label]
positive_images = MNIST['Train']['Features'][positive_indices]
negative_images = MNIST['Train']['Features'][negative_indices]
return positive_images, negative_images
الحين المطلوب منكم:
1. تنشئون 10 مجموعات بيانات بطريقة *رقم واحد مقابل البقية* لكل الأرقام.
1. تدرّبون 10 نماذج بيرسيبترون.
1. تعرّفون دالة `classify` لتصنيف الأرقام.
1. تقيسون دقة التصنيف وتطبعون *مصفوفة الالتباس* (confusion matrix).
1. [اختياري] تنشئون نسخة محسّنة من الدالة `classify` تنفّذ التصنيف بضرب مصفوفي واحد.
حذفنا المخرجات وعدّادات التشغيل والودجات والمحتوى النشط وقت الاستيراد. شغّل الدفاتر بس في بيئة خارجية تثق فيها.