## مقدمة إلى تعلم الآلة

Home PDF

بما أننا نتعلم Python، فلا بد أن نتحدث أيضًا عن تعلم الآلة. لأن العديد من مكتباتها مكتوبة بلغة Python. لنبدأ بتثبيتها واللعب بها قليلاً.

Tensorflow

قم بالتثبيت.

$ pip install tensorflow
ERROR: Could not find a version that satisfies the requirement tensorflow
ERROR: No matching distribution found for tensorflow

ترجمة:

$ pip install tensorflow
خطأ: تعذر العثور على إصدار يتوافق مع المتطلب tensorflow
خطأ: لم يتم العثور على توزيع متطابق لـ tensorflow
$ type python
python هو اسم مستعار لـ `/usr/local/Cellar/python@3.9/3.9.1_6/bin/python3'

ومع ذلك، فإن Tensorflow 2 يدعم فقط إصدارات Python 3.5–3.8. بينما نستخدم نحن الإصدار 3.9.

% type python3
python3 هو /usr/bin/python3
% python3 -V
Python 3.8.2

لاحظت أن الإصدار 3.8.2 من python3 مثبت على نظامي. أين يتم تثبيت pip المقابل لهذا الإصدار من Python؟

% python3 -m pip -V
pip 21.0.1 من /Users/lzw/Library/Python/3.8/lib/python/site-packages/pip (python 3.8)

النسخة المقابلة من pip موجودة هنا. لذا سأقوم بتعديل ملف .zprofile. مؤخرًا قمت بتغيير shell الخاص بي. ملف .zprofile يعادل ملف .bash_profile السابق. سأقوم بإضافة سطر.

alias pip3=/Users/lzw/Library/Python/3.8/bin/pip3

ملاحظة: النص أعلاه هو أمر في سطر الأوامر (shell command) يستخدم لإنشاء اسم مختصر (alias) لتنفيذ أمر pip3 من مسار محدد. لا يحتاج هذا النص إلى ترجمة حيث أنه جزء من التعليمات البرمجية.

بهذه الطريقة، نستخدم python3 و pip3 للعب مع Tensorflow.

% pip3 install tensorflow
...
تم تثبيت بنجاح: absl-py-0.12.0 astunparse-1.6.3 cachetools-4.2.1 certifi-2020.12.5 chardet-4.0.0 flatbuffers-1.12 gast-0.3.3 google-auth-1.27.1 google-auth-oauthlib-0.4.3 google-pasta-0.2.0 grpcio-1.32.0 h5py-2.10.0 idna-2.10 keras-preprocessing-1.1.2 markdown-3.3.4 numpy-1.19.5 oauthlib-3.1.0 opt-einsum-3.3.0 protobuf-3.15.6 pyasn1-0.4.8 pyasn1-modules-0.2.8 requests-2.25.1 requests-oauthlib-1.3.0 rsa-4.7.2 tensorboard-2.4.1 tensorboard-plugin-wit-1.8.0 tensorflow-2.4.1 tensorflow-estimator-2.4.0 termcolor-1.1.0 typing-extensions-3.7.4.3 urllib3-1.26.3 werkzeug-1.0.1 wheel-0.36.2 wrapt-1.12.1

تم تثبيت العديد من المكتبات. واستخدمت مثالًا من الموقع الرسمي.

import tensorflow as tf

mnist = tf.keras.datasets.mnist

(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(10)
])

تمثل الكود أعلاه بناء نموذج تسلسلي (Sequential) باستخدام مكتبة TensorFlow و Keras. النموذج يتكون من:

  1. طبقة Flatten: تقوم بتحويل البيانات ذات الشكل (28, 28) إلى مصفوفة أحادية البعد (784,).
  2. طبقة Dense: طبقة عصبية كاملة الاتصال تحتوي على 128 عصبون وتستخدم دالة التنشيط ReLU.
  3. طبقة Dropout: تقوم بإسقاط 20% من الوحدات العصبية بشكل عشوائي أثناء التدريب لمنع الإفراط في التخصيص (overfitting).
  4. طبقة Dense: طبقة عصبية كاملة الاتصال تحتوي على 10 عصبونات (عادةً ما تستخدم للتصنيف إلى 10 فئات).

هذا النموذج يمكن استخدامه لمهام مثل تصنيف الصور في مجموعة بيانات MNIST.

predictions = model(x_train[:1]).numpy()
print(predictions)

قم بتشغيله.

```shell
$ /usr/bin/python3 tf.py
جارٍ تنزيل البيانات من https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 10s 1us/step
[[ 0.15477428 -0.3877643   0.0994779   0.07474922 -0.26219758 -0.03550266
   0.32226565 -0.37141111  0.10925996 -0.0115255 ]]

تم تنزيل مجموعة البيانات بنجاح، ثم تم عرض النتائج.

لنلقِ نظرة الآن على مثال تصنيف الصور.

# TensorFlow و tf.keras
import tensorflow as tf

مكتبات مساعدة

import numpy as np import matplotlib.pyplot as plt

print(tf.__version__)

خطأ.

ModuleNotFoundError: لا يوجد وحدة باسم 'matplotlib'

قم بالتثبيت.

% pip3 install matplotlib

تم التصحيح.

$ /usr/bin/python3 image.py
2.4.1

إليك مثال على كيفية نسخ ولصق كود:

# هذا مثال بسيط لنسخ ولصق كود في Python

def greet(name):
    print(f"مرحبًا، {name}!")

# استدعاء الدالة
greet("علي")

يمكنك نسخ هذا الكود ولصقه في محرر نصوص أو بيئة تطوير متكاملة (IDE) لتشغيله.

# TensorFlow و tf.keras
import tensorflow as tf
# مكتبات مساعدة
import numpy as np
import matplotlib.pyplot as plt
fashion_mnist = tf.keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()

تم تحميل بيانات Fashion MNIST وتقسيمها إلى مجموعتين:

class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
               'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
print(train_images.shape)
print(len(train_labels))

تم إخراج النتائج. لاحظ هنا وجود train_images و train_labels و test_images و test_labels. وهي مقسمة إلى مجموعات بيانات التدريب واختبار البيانات.

(60000, 28, 28)
60000

لنجرب بعد ذلك طباعة الصورة.

print(train_images[0])

لنلقِ نظرة على النتائج.

[[  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   1   0   0  13  73   0
    0   1   4   0   0   0   0   1   1   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   3   0  36 136 127  62
   54   0   0   0   1   3   4   0   0   3]
 [  0   0   0   0   0   0   0   0   0   0   0   0   6   0 102 204 176 134
  144 123  23   0   0   0   0  12  10   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0 155 236 207 178
  107 156 161 109  64  23  77 130  72  15]
 [  0   0   0   0   0   0   0   0   0   0   0   1   0  69 207 223 218 216
  216 163 127 121 122 146 141  88 172  66]]
  ....

هنا مقتطفات من بعض النتائج.

print(len(train_images[0][0]))

الإخراج هو 28. لذلك من الواضح أن هذه مصفوفة بعرض 28. تابع الطباعة.

    print(len(train_images[0][0][0])
TypeError: object of type 'numpy.uint8' has no len()

الترجمة:

    print(len(train_images[0][0][0])
TypeError: الكائن من النوع 'numpy.uint8' لا يحتوي على دالة len()

لذلك، من الواضح جدًا. كل صورة هي مصفوفة من 28*28*3. البعد الأخير من المصفوفة يحفظ قيم RGB. ومع ذلك، اكتشفنا أن فكرتنا قد تكون خاطئة.

print(train_images[0][1][20])
0
print(train_images[0][1])
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]

كل صورة عبارة عن مصفوفة بحجم 28*28. بعد بعض التجارب، اكتشفنا السر أخيرًا.

لنبدأ أولاً بإلقاء نظرة على الصورة الناتجة.

plt.figure()
plt.imshow(train_images[0])
plt.colorbar()
plt.grid(False)
plt.show()

ملاحظة: الكود أعلاه مكتوب بلغة Python ويستخدم مكتبة matplotlib لعرض صورة من مجموعة بيانات التدريب. لا يحتاج الكود إلى ترجمة حيث أن الأوامر والمتغيرات مكتوبة بالإنجليزية وهي جزء من لغة البرمجة.

tf

هل ترى شريط الألوان على اليمين؟ من 0 إلى 250. في الأصل، هذا تدرج بين لونين. لكن كيف يعرف أي لونين؟ أين أخبرناه بذلك؟

ثم نقوم بطباعة الصورة الثانية أيضًا.

plt.imshow(train_images[1])

plt

مثير للاهتمام. هل هذا هو الإعداد الافتراضي لمكتبة pyplot التابعة؟ دعنا نواصل تشغيل الكود المقدم من الموقع الرسمي.

plt.figure(figsize=(10,10))
for i in range(25):
    plt.subplot(5,5,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    plt.imshow(train_images[i], cmap=plt.cm.binary)
    plt.xlabel(class_names[train_labels[i]])
plt.show()

tf2

لاحظ هنا أن الصور وفئاتها معروضة. أخيرًا، عرفنا معلمة cmp. إذا لم نكتب أي شيء في cmp، فسيكون بالتأكيد باللون الذي رأيناه سابقًا. بالفعل.

    plt.imshow(train_images[i])

cmap

هذه المرة سنبحث عن pyplot cmap. لقد وجدنا بعض المصادر.

    plt.imshow(train_images[i], cmap=plt.cm.PiYG)
<img src="/assets/images/ml/cmap1.png" alt="cmap1" style="zoom:20%;" />

لقد قمت بتعديل الكود. إليك النسخة المعدلة:

plt.figure(figsize=(10,10))
for i in range(25):
    plt.subplot(5,5,i+1)   ## تم تعديل هذه السطر
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    plt.imshow(train_images[i], cmap=plt.cm.Blues)
    plt.xlabel(class_names[train_labels[i]])
plt.show()

في السطر الذي تم تعديله، قمت بتغيير 2,5 إلى 5,5 لجعل الشبكة تحتوي على 5 صفوف و5 أعمدة بدلاً من 2 صفوف و5 أعمدة. هذا سيسمح بعرض 25 صورة في شبكة 5x5.

ومع ذلك، حدث خطأ.

ValueError: يجب أن يكون num بين 1 و 10، وليس 11

ماذا يعني هذا؟ ما الذي تعنيه 5,5,i+1 السابقة بالضبط؟ ولماذا لا تعمل عند تغييرها إلى 2؟ على الرغم من أننا نعرف بشكل حدسي أنها ربما تعني 5 صفوف و5 أعمدة، إلا لماذا يظهر هذا الخطأ؟ كيف تم حساب 11؟ وما معنى num؟ وما معنى 10؟ لاحظ أن 2*5=10. لذا ربما حدث الخطأ عندما كانت i=11. عند تغييرها إلى for i in range(10):، حصلنا على النتيجة التالية.

plot3

بالنظر قليلاً إلى الوثائق، نجد أن subplot(nrows, ncols, index, **kwargs). حسنًا، حتى الآن أصبح الأمر واضحًا لنا.

plt.figure(figsize=(10,10))
for i in range(25):
    plt.subplot(5,5,i+1)
    # plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    plt.imshow(train_images[i], cmap=plt.cm.Blues)
    plt.xlabel(class_names[train_labels[i]])
plt.show()

plot_xticks

لاحظ أن 0 25 هذا النوع يسمى xticks. عندما نقوم بتكبير أو تصغير هذا الإطار، ستظهر أشكال مختلفة.

plot_scale

لاحظ أن مربع التكبير والتصغير، xticks و xlabels سيكون لها عرض مختلف.

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(10)
])

ترجمة الكود إلى العربية:

نموذج = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(10)
])

في هذا الكود، يتم إنشاء نموذج تسلسلي باستخدام مكتبة TensorFlow وKeras. النموذج يتكون من ثلاث طبقات:

  1. Flatten: تقوم بتحويل البيانات ثنائية الأبعاد (28x28) إلى مصفوفة أحادية البعد.
  2. Dense: طبقة عصبية كثيفة تحتوي على 128 عصبون وتستخدم دالة التنشيط ReLU.
  3. Dense: طبقة عصبية كثيفة تحتوي على 10 عصبونات (عادةً ما تستخدم في تصنيف الصور إلى 10 فئات).

هذا النموذج بسيط ويستخدم عادةً في مهام تصنيف الصور مثل MNIST.

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])
model.fit(train_images, train_labels, epochs=10)
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
print('\nدقة الاختبار:', test_acc)

لاحظت هنا الطريقة التي يتم بها تعريف النموذج باستخدام الفئة Sequential. لاحظ هذه المعلمات: 28,28، 128، relu، 10. لاحظ الحاجة إلى compile و fit. fit تعني التوفيق أو الملاءمة. لاحظ أن 28,28 هو حجم الصورة.

Epoch 1/10
1875/1875 [==============================] - 2s 928us/step - loss: 0.6331 - accuracy: 0.7769
Epoch 2/10
1875/1875 [==============================] - 2s 961us/step - loss: 0.3860 - accuracy: 0.8615
Epoch 3/10
1875/1875 [==============================] - 2s 930us/step - loss: 0.3395 - accuracy: 0.8755
Epoch 4/10
1875/1875 [==============================] - 2s 1ms/step - loss: 0.3071 - accuracy: 0.8890
Epoch 5/10
1875/1875 [==============================] - 2s 1ms/step - loss: 0.2964 - accuracy: 0.8927
Epoch 6/10
1875/1875 [==============================] - 2s 985us/step - loss: 0.2764 - accuracy: 0.8955
Epoch 7/10
1875/1875 [==============================] - 2s 961us/step - loss: 0.2653 - accuracy: 0.8996
Epoch 8/10
1875/1875 [==============================] - 2s 1ms/step - loss: 0.2549 - accuracy: 0.9052
Epoch 9/10
1875/1875 [==============================] - 2s 1ms/step - loss: 0.2416 - accuracy: 0.9090
Epoch 10/10
1875/1875 [==============================] - 2s 1ms/step - loss: 0.2372 - accuracy: 0.9086
313/313 - 0s - loss: 0.3422 - accuracy: 0.8798

دقة الاختبار: 0.879800021648407


تم تدريب النموذج. لنقم بتعديل المعلمات.

```shell
model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(28, activation='relu'),    # 128 -> 28
    tf.keras.layers.Dense(10)
])

قم بتعديل المعلمة الأولى لـ Dense.

Epoch 1/10
1875/1875 [==============================] - 2s 714us/step - loss: 6.9774 - accuracy: 0.3294
Epoch 2/10
1875/1875 [==============================] - 1s 715us/step - loss: 1.3038 - accuracy: 0.4831
Epoch 3/10
1875/1875 [==============================] - 1s 747us/step - loss: 1.0160 - accuracy: 0.6197
Epoch 4/10
1875/1875 [==============================] - 1s 800us/step - loss: 0.7963 - accuracy: 0.6939
Epoch 5/10
1875/1875 [==============================] - 2s 893us/step - loss: 0.7006 - accuracy: 0.7183
Epoch 6/10
1875/1875 [==============================] - 1s 747us/step - loss: 0.6675 - accuracy: 0.7299
Epoch 7/10
1875/1875 [==============================] - 1s 694us/step - loss: 0.6681 - accuracy: 0.7330
Epoch 8/10
1875/1875 [==============================] - 1s 702us/step - loss: 0.6675 - accuracy: 0.7356
Epoch 9/10
1875/1875 [==============================] - 1s 778us/step - loss: 0.6508 - accuracy: 0.7363
Epoch 10/10
1875/1875 [==============================] - 1s 732us/step - loss: 0.6532 - accuracy: 0.7350
313/313 - 0s - loss: 0.6816 - accuracy: 0.7230

دقة الاختبار: 0.7229999899864197


لاحظ التغيير في `Test accuracy` قبل وبعد. `Epoch` هي سجلات يتم إخراجها بواسطة دالة `fit`. لاحظ أنه عندما كان الحجم `128`، تغيرت `accuracy` من `0.7769` إلى `0.9086`. وعندما كان الحجم `28`، تغيرت `accuracy` من `0.3294` إلى `0.7350`. يمكن ملاحظة أننا استخدمنا مجموعة التدريب أولاً لضبط `loss` و `accuracy`. ثم استخدمنا مجموعة الاختبار للاختبار. دعونا نلقي نظرة أولاً على `train_labels`.

```python
print(train_labels)
[9 0 0 ... 3 0 5]
print(len(train_labels))
60000
print(train_labels)
[9 0 0 ... 3 0 5]
print(len(train_labels))
60000

هذا يعني استخدام الأرقام من 0 إلى 9 لتمثيل هذه الفئات. وبالصدفة، فإن class_names يحتوي أيضًا على 10 عناصر.

class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
               'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']

دعونا نجري بعض التعديلات مرة أخرى.

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(28, activation='relu'),
    tf.keras.layers.Dense(5)   # 10 -> 5
])
model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])
model.fit(train_images, train_labels, epochs=10)

حدث خطأ.

tensorflow.python.framework.errors_impl.InvalidArgumentError: تم استقبال قيمة تسمية 9 وهي خارج النطاق الصحيح [0, 5). قيم التسميات: 4 3 2 9 4 1 6 0 7 9 1 6 5 2 3 8 6 3 8 0 3 5 6 1 2 6 3 6 8 4 8 4
         [[node sparse_categorical_crossentropy/SparseSoftmaxCrossEntropyWithLogits/SparseSoftmaxCrossEntropyWithLogits (محدد في /curiosity-courses/ml/tf/image.py:53) ]] [Op:__inference_train_function_538]

مكدس استدعاء الدوال: train_function


قم بتغيير المعلمة الثالثة لـ `Sequential` وهي `Dense` إلى `15` وسيكون ذلك كافيًا. النتيجة لن تختلف كثيرًا. جرب تغيير `Epoch` أيضًا.

```python
model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(28, activation='relu'),
    tf.keras.layers.Dense(15)
])

ترجمة الكود إلى العربية:

نموذج = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(28, activation='relu'),
    tf.keras.layers.Dense(15)
])

في هذا الكود، يتم إنشاء نموذج تسلسلي باستخدام مكتبة TensorFlow (tf.keras). يتكون النموذج من ثلاث طبقات:

  1. Flatten: تقوم هذه الطبقة بتحويل البيانات ثنائية الأبعاد (28x28) إلى بيانات أحادية البعد (784 عنصرًا).
  2. Dense: طبقة عصبية كاملة الاتصال تحتوي على 28 عصبونًا وتستخدم دالة التنشيط ReLU.
  3. Dense: طبقة عصبية كاملة الاتصال تحتوي على 15 عصبونًا (بدون تحديد دالة تنشيط).

هذا النموذج بسيط ويستخدم عادةً في مهام التصنيف أو التنبؤ.

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

تم ترجمة الكود أعلاه إلى:

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

في هذا الكود، يتم استخدام الدالة compile لتهيئة النموذج (model) للتدريب. يتم تحديد المُحسِّن (optimizer) على أنه adam، ودالة الخسارة (loss) على أنها SparseCategoricalCrossentropy مع المعلمة from_logits=True، والمقياس (metric) المستخدم لتقييم الأداء هو الدقة (accuracy).

model.fit(train_images, train_labels, epochs=15)  # 10 -> 15
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
print('\nدقة الاختبار:', test_acc)
Epoch 1/15
1875/1875 [==============================] - 2s 892us/step - loss: 6.5778 - accuracy: 0.3771
Epoch 2/15
1875/1875 [==============================] - 2s 872us/step - loss: 1.3121 - accuracy: 0.4910
Epoch 3/15
1875/1875 [==============================] - 2s 909us/step - loss: 1.0900 - accuracy: 0.5389
Epoch 4/15
1875/1875 [==============================] - 1s 730us/step - loss: 1.0422 - accuracy: 0.5577
Epoch 5/15
1875/1875 [==============================] - 1s 709us/step - loss: 0.9529 - accuracy: 0.5952
Epoch 6/15
1875/1875 [==============================] - 1s 714us/step - loss: 0.9888 - accuracy: 0.5950
Epoch 7/15
1875/1875 [==============================] - 1s 767us/step - loss: 0.8678 - accuracy: 0.6355
Epoch 8/15
1875/1875 [==============================] - 1s 715us/step - loss: 0.8247 - accuracy: 0.6611
Epoch 9/15
1875/1875 [==============================] - 1s 721us/step - loss: 0.8011 - accuracy: 0.6626
Epoch 10/15
1875/1875 [==============================] - 1s 711us/step - loss: 0.8024 - accuracy: 0.6622
Epoch 11/15
1875/1875 [==============================] - 1s 781us/step - loss: 0.7777 - accuracy: 0.6696
Epoch 12/15
1875/1875 [==============================] - 1s 724us/step - loss: 0.7764 - accuracy: 0.6728
Epoch 13/15
1875/1875 [==============================] - 1s 731us/step - loss: 0.7688 - accuracy: 0.6767
Epoch 14/15
1875/1875 [==============================] - 1s 715us/step - loss: 0.7592 - accuracy: 0.6793
Epoch 15/15
1875/1875 [==============================] - 1s 786us/step - loss: 0.7526 - accuracy: 0.6792
313/313 - 0s - loss: 0.8555 - accuracy: 0.6418

دقة الاختبار: 0.6417999863624573


لاحظ أن التغيير إلى 15. الفرق ليس كبيرًا. `tf.keras.layers.Dense(88, activation='relu')` مهم. حاول تغيير 128 إلى 88. حصلت على `Test accuracy: 0.824999988079071`. عندما كانت 128، كانت `0.879800021648407`. عندما كانت 28، كانت `0.7229999899864197`. هل الأكبر دائمًا أفضل؟ ومع ذلك، عند تغييرها إلى `256`، كانت `Test accuracy: 0.8409000039100647`. هذا يجعلنا نفكر في معنى `loss` و `accuracy`.

```python
probability_model = tf.keras.Sequential([model, 
                                         tf.keras.layers.Softmax()])

ترجمة:

probability_model = tf.keras.Sequential([model, 
                                         tf.keras.layers.Softmax()])

في هذا الكود، يتم إنشاء نموذج احتمالي باستخدام tf.keras.Sequential الذي يتكون من النموذج الأساسي model وطبقة Softmax التي تُستخدم لتحويل المخرجات إلى احتمالات.

لنقم بالتنبؤ الآن. لاحظ أن Sequential هو نفسه كما في الأعلى. لاحظ المعلمات model و tf.keras.layers.Softmax().

probability_model = tf.keras.Sequential([model, 
                                         tf.keras.layers.Softmax()])
predictions = probability_model.predict(test_images)

تمثل الكود أعلاه إنشاء نموذج احتمالي باستخدام tf.keras.Sequential والذي يتكون من النموذج الأساسي (model) متبوعًا بطبقة Softmax. ثم يتم استخدام هذا النموذج للتنبؤ بالنتائج (predictions) بناءً على بيانات الاختبار (test_images).

def plot_image(i, predictions_array, true_label, img):
  true_label, img = true_label[i], img[i]
  plt.grid(False)
  plt.xticks([])
  plt.yticks([])
plt.imshow(img, cmap=plt.cm.binary)
predicted_label = np.argmax(predictions_array)
if predicted_label == true_label:
    color = 'blue'
else:
    color = 'red'
plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
                                100*np.max(predictions_array),
                                class_names[true_label]),
                                color=color)

تمت ترجمة الكود أعلاه إلى:

plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
                                100*np.max(predictions_array),
                                class_names[true_label]),
                                color=color)

في هذا الكود، يتم تعيين تسمية المحور السيني (x-axis) باستخدام plt.xlabel. النص المعروض يتضمن اسم الفئة المتوقعة (predicted_label)، ونسبة الثقة في التوقع (predictions_array)، واسم الفئة الحقيقية (true_label). اللون (color) يتم تعيينه أيضًا بناءً على ما إذا كان التوقع صحيحًا أم لا.

def plot_value_array(i, predictions_array, true_label):
  true_label = true_label[i]
  plt.grid(False)
  plt.xticks(range(10))
  plt.yticks([])
  thisplot = plt.bar(range(10), predictions_array, color="#777777")
  plt.ylim([0, 1])
  predicted_label = np.argmax(predictions_array)

ترجمة الكود إلى العربية:

def plot_value_array(i, predictions_array, true_label):
  true_label = true_label[i]
  plt.grid(False)  # إزالة الشبكة من الرسم البياني
  plt.xticks(range(10))  # تعيين التقسيمات على المحور السيني من 0 إلى 9
  plt.yticks([])  # إزالة التقسيمات من المحور الصادي
  thisplot = plt.bar(range(10), predictions_array, color="#777777")  # رسم الأعمدة للتنبؤات
  plt.ylim([0, 1])  # تحديد حدود المحور الصادي من 0 إلى 1
  predicted_label = np.argmax(predictions_array)  # الحصول على التصنيف المتوقع

ملاحظة: تمت ترجمة الشروحات الموجودة في الكود إلى العربية مع الحفاظ على الكود الأصلي كما هو.

thisplot[predicted_label].set_color('red')
thisplot[true_label].set_color('blue')
i = 0
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions[i], test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions[i],  test_labels)
plt.show()

pred

هذا يعني أن هناك احتمال بنسبة 99% أن تكون هذه الصورة عبارة عن Ankle boot. لاحظ أن plot_image يعرض الصورة على اليسار، بينما plot_value_array يخرج الرسم البياني على اليمين.

num_rows = 5
num_cols = 3
num_images = num_rows*num_cols
plt.figure(figsize=(2*2*num_cols, 2*num_rows))
for i in range(num_images):
  plt.subplot(num_rows, 2*num_cols, 2*i+1)
  plot_image(i, predictions[i], test_labels, test_images)
  plt.subplot(num_rows, 2*num_cols, 2*i+2)
  plot_value_array(i, predictions[i], test_labels)
plt.tight_layout()
plt.show()

pred1

لاحظ أن هذا فقط يعرض المزيد من نتائج الاختبار. لذا، فإن عملية الاستخدام واضحة إلى حد كبير بالنسبة لنا. لذلك، نحن لا نعرف حتى الآن كيف يتم الحساب في الخلفية. لكننا نعرف كيفية استخدامها. في الخلفية، هناك حساب التفاضل والتكامل. كيف نفهم حساب التفاضل والتكامل؟

لنفترض أن هناك رقمًا بين 1 و100 يجب عليك تخمينه. في كل مرة تخمن فيها رقمًا، سأخبرك إذا كان الرقم أصغر أو أكبر. تخمن 50. أقول لك إنه أصغر. تخمن 80. أقول لك إنه أكبر. تخمن 65. أقول لك إنه أكبر. تخمن 55. أقول لك إنه أصغر. تخمن 58. أقول لك، حسنًا، لقد خمنت بشكل صحيح.

التعلم الآلي يعمل على محاكاة عملية مشابهة في الخلفية، لكنها أكثر تعقيدًا. قد يكون هناك العديد من الأرقام من 1 إلى 100، ويجب تخمين العديد من الأرقام. في نفس الوقت، كل تخمين يتطلب إجراء العديد من العمليات الحسابية. بالإضافة إلى ذلك، كل مرة يتم فيها تحديد ما إذا كان الرقم أكبر أو أصغر، يتطلب ذلك حسابًا كبيرًا.

PyTorch

PyTorch هي مكتبة تعلم آلي مفتوحة المصدر تعتمد على لغة البرمجة Python، وتُستخدم بشكل أساسي في تطبيقات مثل الرؤية الحاسوبية ومعالجة اللغة الطبيعية. تم تطويرها من قبل فريق أبحاث الذكاء الاصطناعي في Facebook (الآن Meta)، وتُعتبر واحدة من أكثر أدوات التعلم العميق شعبية بين الباحثين والمطورين.

مميزات PyTorch:

  1. مرونة عالية: تسمح PyTorch بإنشاء وتعديل النماذج الديناميكية بسهولة، مما يجعلها مثالية للبحث والتجريب.
  2. حسابات تلقائية (Autograd): تدعم PyTorch حساب التدرجات تلقائيًا، مما يسهل عملية تدريب النماذج.
  3. توافق مع Python: تتمتع PyTorch بتكامل سلس مع مكتبات Python الأخرى مثل NumPy وSciPy.
  4. مجتمع نشط: يوجد مجتمع كبير وداعم حول PyTorch، مما يجعل العثور على المساعدة والمصادر التعليمية أسهل.

مثال بسيط باستخدام PyTorch:

import torch

# إنشاء موتر (Tensor)
x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)

# عملية حسابية بسيطة
y = x * 2

# حساب التدرج
y.backward(torch.tensor([1.0, 1.0, 1.0]))

print(x.grad)  # الإخراج: tensor([2., 2., 2.])

في هذا المثال، نقوم بإنشاء موتر (Tensor) وإجراء عملية حسابية بسيطة عليه، ثم نحسب التدرج باستخدام خاصية backward.

PyTorch تُعتبر أداة قوية وفعالة لأي شخص يعمل في مجال التعلم العميق، سواء كان باحثًا أو مطورًا.

قم بتثبيته. هذا يدعم إصدار 3.9 من Python.

$ pip install torch torchvision
جمع حزمة torch
  تنزيل torch-1.8.0-cp39-none-macosx_10_9_x86_64.whl (120.6 ميجابايت)
     |████████████████████████████████| 120.6 ميجابايت 224 كيلوبايت/ثانية
جمع حزمة torchvision
  تنزيل torchvision-0.9.0-cp39-cp39-macosx_10_9_x86_64.whl (13.1 ميجابايت)
     |████████████████████████████████| 13.1 ميجابايت 549 كيلوبايت/ثانية
تم تلبية المتطلب numpy بالفعل في /usr/local/lib/python3.9/site-packages (من torch) (1.20.1)
جمع حزمة typing-extensions
  تنزيل typing_extensions-3.7.4.3-py3-none-any.whl (22 كيلوبايت)
تم تلبية المتطلب pillow>=4.1.1 بالفعل في /usr/local/lib/python3.9/site-packages (من torchvision) (8.0.1)
تثبيت الحزم المجمعة: typing-extensions, torch, torchvision
تم تثبيت torch-1.8.0 و torchvision-0.9.0 و typing-extensions-3.7.4.3 بنجاح

لنجرب ذلك.

import torch
x = torch.rand(5, 3)
print(x)

حدث خطأ.

Traceback (most recent call last):
  File "torch.py", line 1, in <module>
    import torch
  File "torch.py", line 2, in <module>
    x = torch.rand(5, 3)
AttributeError: الوحدة 'torch' غير مهيأة بالكامل وليس لديها السمة 'rand' (على الأرجح بسبب استيراد دائري)

بحثت عن رسالة الخطأ هذه على Google. اتضح أن المشكلة كانت بسبب أن ملفنا كان يُسمى أيضًا torch. تغيير الاسم حل المشكلة وأصبح كل شيء يعمل بشكل صحيح.

tensor([[0.5520, 0.9446, 0.5543],
        [0.6192, 0.0908, 0.8726],
        [0.0223, 0.7685, 0.9814],
        [0.4019, 0.5406, 0.3861],
        [0.5485, 0.6040, 0.2387]])

العثور على مثال.

# -*- coding: utf-8 -*-
import torch
import math
dtype = torch.float
device = torch.device("cpu")
# device = torch.device("cuda:0") # قم بإلغاء التعليق لتشغيل الكود على GPU

إنشاء بيانات عشوائية للإدخال والإخراج

x = torch.linspace(-math.pi, math.pi, 2000, device=device, dtype=dtype) y = torch.sin(x)

تهيئة الأوزان بشكل عشوائي

a = torch.randn((), device=device, dtype=dtype) b = torch.randn((), device=device, dtype=dtype) c = torch.randn((), device=device, dtype=dtype) d = torch.randn((), device=device, dtype=dtype)

learning_rate = 1e-6
for t in range(2000):
    # التمرير الأمامي: حساب القيمة المتوقعة لـ y
    y_pred = a + b * x + c * x ** 2 + d * x ** 3
# حساب وطباعة الخسارة
loss = (y_pred - y).pow(2).sum().item()
if t % 100 == 99:
    print(t, loss)

# الانتشار العكسي لحساب تدرجات a, b, c, d بالنسبة للخسارة
grad_y_pred = 2.0 * (y_pred - y)
grad_a = grad_y_pred.sum()
grad_b = (grad_y_pred * x).sum()
grad_c = (grad_y_pred * x ** 2).sum()
grad_d = (grad_y_pred * x ** 3).sum()
    # تحديث الأوزان باستخدام النزول التدرجي
    a -= learning_rate * grad_a
    b -= learning_rate * grad_b
    c -= learning_rate * grad_c
    d -= learning_rate * grad_d
print(f'النتيجة: y = {a.item()} + {b.item()} x + {c.item()} x^2 + {d.item()} x^3')

قم بتشغيله.

99 1273.537353515625
199 849.24853515625
299 567.4786987304688
399 380.30291748046875
499 255.92752075195312
599 173.2559814453125
699 118.2861328125
799 81.72274780273438
899 57.39331817626953
999 41.198158264160156
1099 30.41307830810547
1199 23.227672576904297
1299 18.438262939453125
1399 15.244369506835938
1499 13.113286972045898
1599 11.690631866455078
1699 10.740333557128906
1799 10.105220794677734
1899 9.6804780960083
1999 9.39621353149414
النتيجة: y = -0.011828352697193623 + 0.8360244631767273 x + 0.002040589228272438 x^2 + -0.09038365632295609 x^3

لنلقِ نظرة على الكود باستخدام مكتبة numpy فقط.

# -*- coding: utf-8 -*-
import numpy as np
import math

إنشاء بيانات إدخال وإخراج عشوائية

x = np.linspace(-math.pi, math.pi, 2000) y = np.sin(x)

تهيئة الأوزان بشكل عشوائي

a = np.random.randn() b = np.random.randn() c = np.random.randn() d = np.random.randn()

learning_rate = 1e-6
for t in range(2000):
    # التمرير الأمامي: حساب القيمة المتوقعة لـ y
    # y = a + b x + c x^2 + d x^3
    y_pred = a + b * x + c * x ** 2 + d * x ** 3
# حساب وطباعة الخسارة
loss = np.square(y_pred - y).sum()
if t % 100 == 99:
    print(t, loss)

# الانتشار العكسي لحساب تدرجات a, b, c, d بالنسبة للخسارة
grad_y_pred = 2.0 * (y_pred - y)
grad_a = grad_y_pred.sum()
grad_b = (grad_y_pred * x).sum()
grad_c = (grad_y_pred * x ** 2).sum()
grad_d = (grad_y_pred * x ** 3).sum()

# تحديث الأوزان
a -= learning_rate * grad_a
b -= learning_rate * grad_b
c -= learning_rate * grad_c
d -= learning_rate * grad_d
print(f'النتيجة: y = {a} + {b} x + {c} x^2 + {d} x^3')

لاحظ أن هذه طريقتان مختلفتان للحساب.

في هذين المثالين، تم أولاً إنشاء مجموعة من قيم x و y. ثم تم افتراض أن العلاقة بينهما هي معادلة من الدرجة الثالثة. بعد ذلك، تم استخدام بعض الطرق لحساب المعاملات بشكل تكراري. كيف تعمل هذه الخوارزميات؟ لاحظ أنه تم تكرار العملية 2000 مرة، وفي كل مرة يتم تحسين الدقة بشكل أكبر. سنترك التفاصيل الدقيقة لهذه العملية جانبًا في الوقت الحالي.

الختام

حاليًا، نحن لا نفهم كيفية حساب التعلم الآلي في الخلفية. ومع ذلك، هذا ليس مهمًا في الوقت الحالي. يمكننا بالفعل القيام بالكثير من الأشياء باستخدام المعرفة المشابهة لما ذكرناه أعلاه. يمكننا أيضًا استخدام التعلم الآلي لمعالجة النصوص والصوت وما إلى ذلك. عندما نختبر عشرات الأمثلة، يمكننا تعلم المبادئ لاحقًا.

التمرين


Back 2025.01.18 Donate