-
المساهمات
1068 -
تاريخ الانضمام
-
تاريخ آخر زيارة
-
عدد الأيام التي تصدر بها
43
إجابات الأسئلة
-
إجابة Ali Haidar Ahmad سؤال في تحويل مصفوفة numpy إلى مصفوفة one-hot ثنائية البعد كانت الإجابة المقبولة
من كيراس باستخدام التابع to_categorical
import numpy as np a = np.array([1, 0, 3]) from keras.utils.np_utils import to_categorical one_hot_train = to_categorical(a) one_hot_train """ array([[0., 1., 0., 0.], [1., 0., 0., 0.], [0., 0., 0., 1.]], dtype=float32) """ أو يمكنك القيام بذلك من خلال تشكيل تابع:
import numpy as np a = np.array([1, 0, 3]) # dimension: أكبر عنصر في بياناتك+1 def vectorize_sequences(sequences, dimension=a[max(a)]+1): results = np.zeros((len(sequences), dimension)) for i, sequence in enumerate(sequences): results[i, sequence] = 1. return results OneHOT = vectorize_sequences(a) OneHOT """ array([[0., 1., 0., 0.], [1., 0., 0., 0.], [0., 0., 0., 1.]]) """ أيضاً بشكل يدوي من خلال استخدام عدة توابع في نمباي :
import numpy as np a = np.array([1, 0, 3]) b = np.zeros((a.size, a.max()+1)) b[np.arange(a.size),a] = 1 b أيضاً طريقة أخرى، عبر الاستعانة بتوابع نمباي:
import numpy as np a = np.array([1, 0, 3]) def one_hot(a, dimension=a[max(a)]+1): return np.squeeze(np.eye(dimension)[a.reshape(-1)]) one_hot(a) """ array([[0., 1., 0., 0.], [1., 0., 0., 0.], [0., 0., 0., 1.]]) """ يمكنك أيضاً استخدام مكتبة باندا من خلال التابع get_dummies:
import numpy as np import pandas a = np.array([1, 0, 3]) one_hot_encode=pandas.get_dummies(a) one_hot_encode """ 0 1 3 0 0 1 0 1 1 0 0 2 0 0 1 """ أو من مكتبة sklearn استخدام التابع OneHotEncoder:
import numpy as np import pandas a = np.array([1, 0, 3]) from sklearn.preprocessing import OneHotEncoder enc = OneHotEncoder(handle_unknown='ignore') o=enc.fit_transform(a.reshape(-1, 1)) onehot=o.toarray() onehot """ array([[0., 1., 0.], [1., 0., 0.], [0., 0., 1.]]) """ لكن في آخر طلريقتين سيكون حجم الشعاع لكل قيمة يساوي عدد العناصر المختلفة. أي لن يقوم بعملية تمثيلهم حسب ال index انظر:
import numpy as np import pandas a = np.array([1, 0, 4]) from sklearn.preprocessing import OneHotEncoder enc = OneHotEncoder() one_hot = enc.fit_transform(a.reshape(-1, 1)) one_hot.toarray() """ array([[0., 1., 0.], [1., 0., 0.], [0., 0., 1.]]) """
-
إجابة Ali Haidar Ahmad سؤال في المعيار BinaryAccuracy في كيراس Keras كانت الإجابة المقبولة
تقوم هذه الدالة بحساب مدى دقة النموذج، وتستخدم مع مهام التصنيف الثنائي، وتختلف عن مقياس الدقة accuracy (يمكنك الاطلاع عليها من الرابط في الأسفل) في أنها تسمح لنا بتحديد عتبة للتوقع أي ال "threshold" أي تعطينا قدرة أكبر في التحكم بعملية التوقع، وترد هذه الدالة قيمة عشرية بين 0 و 1 بحيث كلما اقتربت القيمة من 1 كانت دقة النموذج أعلى. وتماماً كما في الدالة Accuracy تقوم هذه الدالة بحساب عدد المرات التي قام فيها نموذجنا بتوقع القيم بشكل صحيح (عدد مرات الإصابة في التنبؤ أو بمعنى آخر عدد مرات التطابق) وتقسمها على عدد التوقعات الكلية (الصحيحة والخاطئة أي حالات التطابق وعدم التطابق). والمثال التالي سيوضح كل شيء، حيث قمت في البداية بكتابة كود بشكل يدوي لتحقيق هذا التابع ثم استخدمت كيراس:
import numpy as np import tensorflow as tf # إنشاء مصفوفتين واحدة تمثل القيم المتوقعة والأخرى الحقيقية yTrue = np.array([[1],[0],[0],[1],[1]]) print("yTrue: ",yTrue,sep="\n") Pred = np.array([[0.6],[0.2],[0.4],[0.95],[1.0]]) print("Pred: ",Pred,sep="\n") Threshold = 0.5 # تابع لمدا لتعيين 1 في حالة كانت القيمة المتوقعة أكبر من العتبة و0 إذا كانت أقل منها pM = lambda x : 0 if x <= Threshold else 1 # تطبيق التابع السابق على كل العينات yPred = Pred.astype(int) for i in range(len(yPred)): yPred[i] = pM(Pred[i]) print("predicted values: ",yPred,sep="\n") print("accurately predicted : ",sum(yPred == yTrue),sep="\n") print("len: ",len(yPred)) # الآن نقوم بقسمة عدد العينات التي تم توقعها بشكل صحيح على العدد الكلي للعينات BinaryAccuracy = sum(yPred == yTrue)/len(yPred) # باستخدام كيراس Binary Accuracy حساب metric = tf.keras.metrics.BinaryAccuracy(threshold = Threshold) metric.update_state(yTrue,yPred) metric.result().numpy() """ yTrue: [[1] [0] [0] [1] [1]] Pred: [[0.6 ] [0.2 ] [0.4 ] [0.95] [1. ]] predicted values: [[1] [0] [0] [1] [1]] accurately predicted : [5] len: 5 1.0 # 100% """ هذه الدالة لها الشكل التالي في كيراس:
tf.keras.metrics.BinaryAccuracy( name="binary_accuracy", dtype=None, threshold=0.5 ) # threshold هي العتبة ويمكننا استخدامها في نماذجنا مع الدالة compile كالتالي:
model.compile(optimizer='sgd', loss='mse', metrics=[tf.keras.metrics.BinaryAccuracy()]) # أو model.compile(optimizer='sgd', loss='mse', metrics=["BinaryAccuracy"]) انظر للمثال التالي، حيث سأستخدمها مع مسألة تصنيف ثنائي:
from keras.layers import Embedding from keras.datasets import imdb from keras import preprocessing max_features = 10000 maxlen = 20 (x_train, y_train), (x_test, y_test) = imdb.load_data( num_words=max_features) x_train = preprocessing.sequence.pad_sequences(x_train, maxlen=maxlen) x_test = preprocessing.sequence.pad_sequences(x_test, maxlen=maxlen) from keras.models import Sequential from keras.layers import Flatten, Dense model = Sequential() model.add(Embedding(10000, 8, input_length=maxlen)) model.add(Flatten()) model.add(Dense(1, activation='sigmoid')) model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['BinaryAccuracy']) model.summary() history = model.fit(x_train, y_train, epochs=10, batch_size=32, validation_split=0.2)
-
إجابة Ali Haidar Ahmad سؤال في ظهور الخطأ التالي You must compile a model before training/testing. Use `model.compile(optimizer, loss) في كيراس Keras كانت الإجابة المقبولة
التابع predict يقوم فقط بتمرير بيانات الدخل إلى النموذج فتحصل على الخرج (القيمة المتوقعة بناءان على أوزان التدريب التي تم حفظها في الملفات). لذا لايعطيك أي مشكلة. أما عند استخدام evaluate ، فهذا التابع يقوم بحساب الخطأ loss و ال metrics، ودالة التكلفة التي نحسب من خلالها ال loss لايكون لدينا معلومات عنها حتى تقوم بتجميع النموذج compile. فهم وسطاء لتابع ال compile:
model.compile(optimizer=.., loss=.., metrics=..) إن كل مايهمنا من تدريب النموذج هو استخلاص الأوزان المدربة: إن مخرجات النموذج النهائية هي عبارة عن أوزان هذه الأوزان تكون مدربة لتنفيذ المهمة التي قمنا بتدريبها من أجل حلها، في البداية نقوم بتهيئتها بقيم عشوائية (بين ال 0 و 1). ثم عن طريق النموذج الذي بنيناه وعن طريق خوارزمية Backbropagation يتم تحديث قيم هذه الأوزان (تدريبها لحل المشكلة)، وبعد انتهاء التدريب نقوم بإدخال العينة التي نريد تجربتها أو اختبار الأداء عليها، فيحسب النموذج الناتج لنا بناءان على قيم هذه الأوزان. وهذا هو كل ما يهمنا (بناء نموذج قادر عتلى تصنيف الصور مثلاً بحيث نعطيه صورة ويعطينا الخرج أما التفاصيل الأخرى لاتهمنا كمستخدمين). حسناً إن التكلفة "loss" هي دالة نقوم باستخدامها خلال عملية التدريب حيث تستلم هذه الدالة القيم المتوقعة من النموذج والقيم الحقيقية ثم تقارنهما وتعطي قيمة تعبر عن مدى اختلاف القيمتين (الفرق بينهما). وطبعاً يكون الهدف هو تصغير قيمة التكلفة (الخطأ) لأنه كلما قل الاختلاف بين القيم التي يتوقعها النموذج والقيم الحقيقية يصبح نموذجك أفضل. إذاً ال loss ليست مفيدة للغرض النهائي للنموذج، لكنها ضرورية للتدريب. وهذا هو السبب في أنه يمكنك الحصول على توقعات من النموذج لكن دون ال loss. لكن إذا أردت لسبب ما أن تحسب ال loss أيضاً فيجب عليك تنفيذ ال compile لنموذجك، انظر للمثال التالي الذي سأقوم فيه بحفظ نموذج ثم سأعيد تحميله وأنفذ عليه التابع evaluate:
from keras.models import Sequential from keras.layers import Dense from keras.models import model_from_yaml import numpy import os dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",") X = dataset[:,0:8] Y = dataset[:,8] # بناء النموذج model = Sequential() model.add(Dense(16, input_dim=8, activation='tanh')) model.add(Dense(1, activation='sigmoid')) # تجميع النموذج model.compile(loss='binary_crossentropy', optimizer='rmsprop', metrics=['acc']) # تدريب النموذج model.fit(X, Y, epochs=120, batch_size=10, verbose=0) # تقييم النموذج scores = model.evaluate(X, Y, verbose=0) print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100)) # acc: 78.78% # حفظه model_j = model.to_json() with open("model.json", "w") as f: f.write(model_j) model.save_weights("model.h5") # الآن إعادة تحميله json_file = open('model.json', 'r') loaded_model_json = json_file.read() json_file.close() model = model_from_json(loaded_model_json) # تحمبل الأوزان model.load_weights("model.h5") #نقوم الآن بتجميع النموذج model.compile(loss='binary_crossentropy', optimizer='rmsprop', metrics=['acc']) # قم بتحديد دالة التكلفة والمعيار # على بيانات الاختبار evaluate score = model.evaluate(X, Y, verbose=0) # حساب ال loss print('Test loss:', score[0]) #metrics حساب ال print('Test accuracy:', score[1])
-
إجابة Ali Haidar Ahmad سؤال في ظهور الخطأ InvalidArgumentError: indices[19577,0] = -3 is not in [0, 2160) في كيراس Keras كانت الإجابة المقبولة
استخدامك للتضمين هنا غير صحيح ، فعندما تكون مدخلاتك لها قيم سلبية، يكون الترميز غير صالح لاستخدام مع طبقة التضمين، يحب أن يكون ترميز الكلمات في المستندات عبارة عن أعداد صحيحة موجبة حصراً (كل كلمة فريدة يتم ربطها بعدد صحيح يمثلها). حيث أن طبقة التضمين هي طبقة تتيح لنا تحويل كل كلمة إلى متجه بطول ثابت وبحجم محدد. المتجه الناتج هو متجه كثيف "Dense" له قيم حقيقية بدلاً من 0 و 1 فقط كما في الترميز One-Hot. يساعدنا الطول الثابت لمتجهات الكلمات على تمثيل الكلمات بطريقة أفضل وأكثر فعالية مع أبعاد مخفضة. وهذه المتجهات تكون ممثلة في فضاء Vector space مهيكل ويعكس المعاني الدلالية لكل كلمة. ويمكن اعتبارها كقاموس يقوم بربط أعداد صحيحة (كل كلمة ترمز في البداية كعدد صحيح) بمتجه كثيف. أي أنها تأخذ كدخل أعداد صحيحة ثم تبحث في هذا القاموس على المتجه الذي يقابله في القاموس الداخلي، ويعيد هذا القاموس.
Word index --> Embedding layer --> Corresponding word vector إذا كون مدخلاتك تحوي أعداداً سلبية يعني أن استخدام التضمين غير صحيح هنا. إن التضمين يعمل مع أي نوع من مدخلات الأعداد الصحيحة الموجبة، ولكن ليس مع المدخلات العامة.
-
إجابة Ali Haidar Ahmad سؤال في دالة التنشيط softmax في كيراس Keras كانت الإجابة المقبولة
هي دالة رياضية نستخدمها كدالة تنشيط، مدخلاتها شعاع من الأعداد، وخرجها شعاع من القيم الاحتمالية، أي تقوم بتحويل متجه الأعداد إلى متجه احتمالي، حيث تتناسب احتمالات كل قيمة مع المقياس النسبي لكل قيمة في المتجه. ونستخدمها لمهام التصنيف المتعدد، حيث نضعها في آخر طبقة. ولها الشكل التالي:
أي تأخذ كل قيمة من قيم شعاع الدخل على حدى، ثم تقوم بحساب ال exp لهذا العدد ثم تقسم الناتج على المجموع الكلي لل exp لكل العينات (وبالتالي الخرج سيكون عبارة عن توزيع احتمالي). ولفهم هذا الكلام أكثر لنأخذ المثال التالي، لدينا 3 أصناف من الكرات (x,y,z) بما أنه لدينا 3 أصناف وبالتالي خرج الشبكة يجب أن يكون 3 قيم (أي يجب أن يكون لديك 3 خلايا في الخرج) بحيث كل قيمة تعبر عن احتمالية أن العينة هي إحدى الأصناف، حسناً لنرمز ل x ب 0 و y ب 1 و z ب 2 وبالتالي يمكن تمثيلها ك One-hot بالشكل التالي :
x0=[1,0,0] y0=[0,1,0] z0=[0,0,1] ونحن لدينا 3 عصبونات في آخر طبقة، وبالتالي سيمثل العصبون الأول احتمالية كون العينة (الكرة) تمثل الصنف x، والعصبون الثاني احتمالية كون العينة (الكرة) تمثل الصنف y، والعصبون الأخير احتمالية كون العينة تنتمي للصنف z. فمثلاً من أجل عينة ما، عند الوصول لآخر طبقة سيتم إدخال ناتج آخر طبقة ( هنا شعاع من 3 قيم) إلى هذا التابع وبالتالي يصبح الخرج احتمالياً كما يلي:
طبعاً القيم الاحتمالية التي وضعتها بشكل تقديري، لكن حتماً سيكون المجموع1، الآن سأكتب لك إياها بكود بسيط:
# transform values into probabilities from math import exp # calculate each probability summation=(exp(7.0) + exp(2.0) + exp(0.1)) p1 = exp(7.0) / summation p2 = exp(2.0) / summation p3 = exp(0.1) / summation print(p1, p2, p3) # 0.9923138027987766 0.006686157809719105 0.0010000393915043245 # sum of probabilities print(p1 + p2 + p3) # 1.0 انظر كيف سأقوم بتحقيق هذا التابع، وسأطبقه على نفس السؤال:
from numpy import exp def softmax(vector): e = exp(vector) return e / e.sum() # define data data = [7.0, 2.0, 0.1] # التحويل result = softmax(data) print(result) # probabilities # [0.9923138 0.00668616 0.00100004] في كيراس وتنسرفلو تتواجد في الموديول التالي (لاحظ أنه موجود ضمن موديول الطبقات):
tf.keras.layers.Softmax() ويمكنك تمريرها لنموذجك كدالة تنشيط في آخر طبقة عندما تكون المهمة مهمة تصنيف، كما في المثال التالي، حيث أنه لدينا مهمة تصنيف متعدد ل 46 صنف:
from keras.datasets import reuters (train_data, train_labels), (test_data, test_labels) = reuters.load_data( num_words=10000) # ترميز البيانات import numpy as np def vectorize_sequences(sequences, dimension=10000): results = np.zeros((len(sequences), dimension)) for i, sequence in enumerate(sequences): results[i, sequence] = 1. return results x_train = vectorize_sequences(train_data) x_test = vectorize_sequences(test_data) from keras.utils.np_utils import to_categorical one_hot_train_labels = to_categorical(train_labels) one_hot_test_labels = to_categorical(test_labels) # بناء النموذج from keras import models from keras import layers model = models.Sequential() model.add(layers.Dense(64, activation='relu', input_shape=(10000,))) model.add(layers.Dense(64, activation='relu')) model.add(layers.Dense(46, activation='softmax')) # هنا الطبقةالأخيرة model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy']) # التدريب x_val = x_train[:1000] partial_x_train = x_train[1000:] y_val = one_hot_train_labels[:1000] partial_y_train = one_hot_train_labels[1000:] history = model.fit(partial_x_train, partial_y_train, epochs=20, batch_size=512, validation_data=(x_val, y_val)) وللتنويه يمكنك أيضاً استخدامها في الطبقات الخفية لكنها لن تعطيك نتائج مقبولة، مقارنة بالدوال الأخرى (استخدمها فقط كدالة تنشيط في الطبقة الأخيرة).
-
إجابة Ali Haidar Ahmad سؤال في كيف أحدد عمود الفهرس index ورؤوس الأعمدة headers في Numpy و Pandas؟ كانت الإجابة المقبولة
بالشكل التالي:
pd.DataFrame(data=data[1:,1:], # القيم index=data[1:,0], # العمودالأول كفهرس columns=data[0,1:]) # الصف الأول كأسماء الأعمدة حيث تحتاج إلى تحديد ال data والفهرس والأعمدة إلى باني ال dataframe:
import numpy as np data = np.array([ ['', 'Col1', 'Col2'], ['Row1', 1, 2], ['Row2', 3, 4] ]) import pandas as pd pd.DataFrame(data=data[1:,1:], # القيم index=data[1:,0], # العمودالأول كفهرس columns=data[0,1:]) # الصف الأول كأسماء للأعمدة """ Col1 Col2 Row1 1 2 Row2 3 4 """ حيث أن:
data[1:,1:] """ array([['1', '2'], ['3', '4']], dtype='<U4') """ data[1:,0] """ array(['Row1', 'Row2'], dtype='<U4') """ data[0,1:] """ array(['Col1', 'Col2'], dtype='<U4') """ ويمكنك أيضاً أن تقوم بتغيير نمط البيانات الخاص بالقيم إذا أردت بالشكل:
import numpy as np data = np.array([ ['', 'Col1', 'Col2'], ['Row1', 1, 2], ['Row2', 3, 4] ]) import pandas as pd pd.DataFrame(data=np.int_(data[1:,1:]), # القيم index=data[1:,0], # العمودالأول كفهرس columns=data[0,1:]) # الصف الأول كأسماء الأعمدة """ Col1 Col2 Row1 1 2 Row2 3 4 """
-
إجابة Ali Haidar Ahmad سؤال في ظهور الخطأ NameError: name 'Dense' is not defined في كيراس وتنسرفلو كانت الإجابة المقبولة
يجب عليك أولاً أن تقوم باستيراد الطبقات قبل استخدامها، ومشكلتك هي أنك لم تقم باستيراد الطبقة Dense. فظهر لك هذا الخطأ، وبالتالي يجب أن تضيف إلى نموذجك السطر التالي، من Keras API حيث أنها موجودة في الموديول:
keras.layers.Dense # وبالتالي نكتب from keras.layers import Dense أو من تنسرفلو حيث تكون في الموديول التالي:
tensorflow.keras.layers.Dense from tensorflow.keras.layers import Dense ويمكنك استيراد أي طبقة أخرى بنفس الطريقة، مثلاً نريد أن نقوم باستيراد ال'طبقة LSTM أو GRU أو conv..إلخ:
# نكتب from keras.layers import Conv2D,LSTM,GRU # أو from tensorflow.layers import Conv2D,LSTM,GRU # أو import tensorflow as tf from tf.layers import Conv2D,LSTM,GRU # أو import tensorflow.layers as layers from layers import Conv2D,LSTM,GRU
-
إجابة Ali Haidar Ahmad سؤال في ظهور الخطأ 'ValueError: The last dimension of the inputs to `Dense` should be defined. Found `None أثناء بناء نموذج في كيراس كانت الإجابة المقبولة
عند بناء النماذج، يجب أن تقوم دوماً بتحديد حجم الإدخال الذي ستتعامل معه شبكتك، وأنت هنا لم تقم بتحديده فظهرت المشكلة. حقيقةً وبشكل عام، عند بناء الشبكات العصبية ينبغي علينا تحديد حجم الدخل لكل طبقة لكن كيراس تغنيك عن ذلك فيكفي أن تعطيها حجم الإدخال لأول طبقة وهي ستستنتج حجم الإدخال لباقي الطبقات. حسناً أنت تتعامل مع مهمة NLP ولديك بيانات كل عينة فيها عبارة عن مستند نصي مؤلف من عدد مختلف من الكلمات،وكونك قمت بتحميلها من كيراس فهي تكون مرمزة بأعداد صحيحة مسبقاً (كل كلمة يقابلها عدد صحيح) وبالتالي قمت أولاً بحشوها لكي تكون جميعها بنفس الحجم (خطوة إجبارية) لكنك لم تحدد الطول الأعظمي لل padseq وبالتالي سيختار افتراضياً طول أطول مستند (في حالتك فإن أطول مستند طوله 2494) أي كل عينات بياناتك سيكون حجمها 2494 (بعد الحشو بأصفار) وبالتالي يكون حجم الإدخال لديك هو (عدد العينات,عدد الفيتشرز) وعدد الفيتشرز هنا أو "السمات" features هو طول التسلسلات أي 2494. لذا يجب أن تقوم بتحديده لشبكتك. طبعاً عدد العينات لامشكلة في عدم تحديده فأيضاً يستطيع كيراس استنتاجه. وبالتالي يكون حل مشكلتك إما باستخدام الوسيط input_length كونك تتعامل مع طبقة NLP أو من خلال input_shape كالتالي:
from keras.datasets import imdb from keras import preprocessing max_features = 1000 # حدد حجم الإدخال الذي تريده maxlen = 20 (x_train, y_train), (x_test, y_test) = imdb.load_data( num_words=max_features) # حدد طول التسلسل الذي تريده x_train = preprocessing.sequence.pad_sequences(x_train,maxlen=maxlen) x_test = preprocessing.sequence.pad_sequences(x_test, maxlen=maxlen) from keras.models import Sequential from keras.layers import Flatten, Dense,Embedding model = Sequential() # قم الآن بتعريف حجم طبقة الإدخال لشبكتك model.add(Embedding(1000, 8, input_shape=(maxlen,))) # أو # model.add(Embedding(1000, 8, input_length=maxlen)) model.add(Flatten()) model.add(Dense(64, activation='tanh')) model.add(Dense(1, activation='sigmoid')) model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc']) history = model.fit(x_train, y_train, epochs=3, batch_size=64, validation_split=0.2) ,طبعاً يفضل أن تمرر لتابع ال padseq طول التسلسل (الطول الأعظمي الذي تريده) لكي لايقوم باستخدام الطول الأكبر، فهذا قد يسبب لك مشاكل في التدريب (بطء شديد لاتخاذك طول كبير جداً)
-
إجابة Ali Haidar Ahmad سؤال في دالة التنشيط tanh في كيراس وتنسرفلو كانت الإجابة المقبولة
دالة غير خطية، تشبه كثيراً التابع السيني Sigmoid ولكن الفرق بينهما في مجال قيم الخرج حيث يكون في ال tanh من 1- إلى 1، أي على عكس التابع السيني حيث يكون الخرج من 0 إلى 1. ولها الشكل التالي (الاورنج):
من الشكل نلاحظ أنها تأخذ أي قيمة حقيقية كقيم مدخلات. والخرج يكون في النطاق من 1 إلى -1. كلما كانت المدخلات أكبر (أكثر إيجابية) ، كلما كانت قيمة المخرجات أقرب إلى 1.0 ، بينما كلما كانت المدخلات أصغر (أكثر سلبية) ، كلما كان الناتج أقرب إلى -1.0. ومن الرسم البياني نلاحظ أيضاً أنه يمكن استخدامها في تدريب النماذج (مستمر و قابل للإشتقاق في كل مكان)، وكما نلاحظ من الرسم (المنحني الأزرق) فإن المشتق تكون قيمه فعالة للتدريب عندما تكون قيم z قريبة من الصفر (حولها) ولكن من أجل قيم كبيرة جداً أو صغيرة جداً فلن تكون فعالة في التدريب لأن المماس يكون شبه مستقيم وبالتالي قيمة المشتقة تكون صغيرة جداً، مما يؤدي الى بطء شديد في عملية التدريب وبالتالي مكلف من الناحية الحسابية. إن الميزة الأهم في هذا التابع مقارنة بال sigmoid هو أن قيم المشتقات أكبر وبالتالي تدرجاته (Gredint) تكون أكثر قوة نحو القيم الصغرى الشاملة GM أي بمعنى آخر أسرع في التقارب Converge وهذا مايجعله أكثر كفاءة مقارنة بالتابع السيني. أما عيبها فكما ذكرنا هو نفس المشكلة التي تعاني منها sigmoid وهي مشكلة تلاشي التدرجات "vanishing gradient" (المشتقات يصغر حجمها إلى أن تنعدم تقريباً عندما تزداد قيمة Z وهذا واضح من المنحني الأزرق). عند استخدام tanh للطبقات المخفية ، أنصح باستخدام تهيئة الوزن "Xavier Normal" أو "Xavier Uniform" (يُشار إليها أيضاً بتهيئة Glorot) إضافة إلى تقييس "scaling" بيانات الدخل إلى النطاق -1 إلى 1 قبل التدريب. وفي كيراس له الشكل التالي:
tf.keras.activations.tanh(x) ويمكنك استخدامه في الطبقات الخفية لنموذجك (لاتستخدمه مع طبقة الخرج فكيراس لاتعالج حالته، رغم أنه يمكن استخدامه)، انظر للمثال التالي:
from keras.datasets import imdb from keras import preprocessing max_features = 10000 maxlen = 20 (x_train, y_train), (x_test, y_test) = imdb.load_data( num_words=max_features) x_train = preprocessing.sequence.pad_sequences(x_train, maxlen=maxlen) # هنا حددنا طول الكلمات ب 20 x_test = preprocessing.sequence.pad_sequences(x_test, maxlen=maxlen) # بناء نموذجك from keras.models import Sequential from keras.layers import Flatten, Dense model = Sequential() model.add(Embedding(10000, 8, input_length=maxlen)) model.add(Flatten()) model.add(Dense(64, activation='tanh'))# بهذه الطريقة """ أو from tensorflow.keras import activations model.add(Dense(64, activation=activations.tanh)) أو بالشكل التالي model.add(Dense(64)) model.add(Activation(activations.tanh)) """ model.add(Dense(1, activation='sigmoid')) model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc']) model.summary() # تدريبه history = model.fit(x_train, y_train, epochs=10, batch_size=32, validation_split=0.2)
-
إجابة Ali Haidar Ahmad سؤال في كيفية إضافة أعمدة وصفوف إلى مصفوفة فارغة في Numpy كانت الإجابة المقبولة
لإضافة عمود إلى مصفوفتك استدعي numpy.append(arr, values, axis=1) ، انظر للمثال التالي:
import numpy as np arr = np.zeros((3,2)) print(arr) """ [[0. 0.] [0. 0.] [0. 0.]] """ new_column = [[3],[3], [6]] arr = np.append(arr, new_column, axis=1) arr """ array([[0., 0., 3.], [0., 0., 3.], [0., 0., 6.]]) """ ولإضافة أسطر، فقط نغير المحور:
import numpy as np arr = np.zeros((3,2)) print(arr) """ [[0. 0.] [0. 0.] [0. 0.]] """ new_row = [[3,2]] arr = np.append(arr, new_row, axis=0) arr """ array([[0., 0.], [0., 0.], [0., 0.], [3., 2.]]) """ أو يمكنك استخدام numpy.insert(arr, idx, values, axis=1):
import numpy as np arr = np.zeros((3,2)) print(arr) """ [[0. 0.] [0. 0.] [0. 0.]] """ new_column = [[3,2,1]] arr=np.insert(arr, 1, new_column, axis=1) print(arr) """ [[0. 3. 0.] [0. 2. 0.] [0. 1. 0.]] """
-
إجابة Ali Haidar Ahmad سؤال في ما هو الفرق بين الدالات array() و asarray() في Numpy؟ كانت الإجابة المقبولة
يمكن لكل من array و asarray تحويل البيانات المهيكلة "structured data" إلى ndarray ، ولكن الاختلاف الرئيسي هو أنه عندما يكون مصدر البيانات ndarray ، ستظل المصفوفة تنسخ نسخة ، وتحتل ذاكرة جديدة ، لكن asarray لن تفعل ذلك. عند الإدخال كقائمة ، يكون نوع البيانات الأصلي الذي يتم تحويله عبارة عن قائمة:
import numpy x=[[0,5],[8,5]] v = numpy.asarray(x) i = numpy.array(x) x[0] = 5 print(x) #[5, [8, 5]] print(i) ''' [[0 5] [8 5]] ''' print(v) ''' [[0 5] [8 5]] ''' من هذا يمكننا أن نرى أن ال array هو نفسه asarray ، أي يقومان بتحويل المدخلات إلى تنسيق Matrix. وعندما يكون الدخل عبارة عن قائمة، فإن تغيير قيمة في القائمة لا يؤثر على القيمة المحولة إلى المصفوفة. أما عندما يكون الإدخال عبارة عن مصفوفة:
import numpy as np array=np.random.random((3,3)) print(array.dtype) # float64 x=np.array(array,dtype='float64') t=np.asarray(array,dtype='float64') array[1]=2 print(array) ''' [[0.14427798 0.24129013 0.3114457 ] [2. 2. 2. ] [0.18134186 0.29733322 0.38294914]] ''' print(x) ''' [[0.14427798 0.24129013 0.3114457 ] [0.21828251 0.48710077 0.07849822] [0.18134186 0.29733322 0.38294914]] ''' print(t) ''' [[0.14427798 0.24129013 0.3114457 ] [2. 2. 2. ] [0.18134186 0.29733322 0.38294914]] ''' print(x is a) # False print(t is a) # True من النتائج المذكورة أعلاه يمكننا أن نرى الفرق بين np.array و np.asarray. عندما يكون الإدخال عبارة عن مصفوفة ، ستقوم np.array بإنشاء مساحة ذاكرية وتنسخ البيانات فيها. أي سيكون لها مساحة ذاكرة خاصة بها، لذلك يتغير الخرج الخاص ب np.array مع الدخل، والتابع .asarray يزيد من العداد الذي يشير إلى t ويشير إلى المصفوفة، بحيث عندما تتغير المصفوفة الأصلية ، سيتغير ناتج np.asarray أيضًا.
-
إجابة Ali Haidar Ahmad سؤال في إيجاد أقرب قيمة في مصفوفة numpy كانت الإجابة المقبولة
يمكنك استخدام التابع التالي، حيث نعتمد على فكرة طرح القيمة المطلوبة من كل عنصر في المصفوفة، وبالتالي تتشكل لدينا مصفوفة الفرق بالقيمة المطلقة، ثم نستخدم التابع argmin ليعطينا موقع أصغر عنصر، ثم نستخدم flat لتعطينا القيمة الموافقة للموقع:
import numpy as np array = np.random.random(10) print(array) """ [0.59588654 0.43663869 0.49730145 0.65410536 0.98261646 0.06100155 0.28296143 0.94809249 0.43775789 0.2167913 ] """ def find1(a, a0): index = np.abs(a - a0) print(idx) """ [0.10411346 0.26336131 0.20269855 0.04589464 0.28261646 0.63899845 0.41703857 0.24809249 0.26224211 0.4832087 ] """ index=idx.argmin() print(index) # 3 print(a.flat[index]) # 0.6541053630832852 return a.flat[index] find1(array,0.7) # 0.6541053630832852 الآن سأكتب التابع بشكل مختصر:
import numpy as np array = np.random.random(10) def find1(a, a0): index = np.abs(a - a0).argmin() return a.flat[index] find1(array,0.7) أو يمكنك استخدام الطريقة التالية وهي مشابهة إلى حد كبير بالطريقة الأولى (بالشكل والسرعة):
import numpy as np #array = np.random.random(10) print(array) """ [0.59588654 0.43663869 0.49730145 0.65410536 0.98261646 0.06100155 0.28296143 0.94809249 0.43775789 0.2167913 ] """ def find2(a, values): index = np.abs(np.subtract.outer(array, values)).argmin(0) return a.flat[index] find2(array,0.7) # 0.6541053630832852 أو بالطريقة التالية حيث نعتمد على ترتيب المصفوفة أولاً وهي عموماً لاتحتاج لاستخدام نمباي معها، وهي تأخذ المصفوفة المراد البحث فيها والقيمة التي نبحث عن أقرب قيمة لها وترد لنا الموقع الموجودة فيه، ويتم إرجاع -1 أو طول المصفوفة للإشارة إلى أن القيمة خارج النطاق أدناه وأعلى بالترتيب:
import numpy as np array = np.random.random(10) print(array) def bi(a,val): a=np.sort(a) """ [0.06100155 0.2167913 0.28296143 0.43663869 0.43775789 0.49730145 0.59588654 0.65410536 0.94809249 0.98261646] """ n = len(a) if (val < a[0]): return -1 elif (val > a[n-1]): return n jl = 0 # تهيئة أقل حد ju = n-1 # الأعلى # طالما لم يتحقق الشرط التالي # نكرر حتى يتحقق الشرط while (ju-jl > 1): jm=(ju+jl) >> 1 # احسب القيمة في المنتصف مع إزاحة if (val >= array[jm]): jl=jm # واستبدل إما الحد الأدنى else: ju=jm # أو الأعلى if (val == a[0]): return 0 elif (val == a[n-1]): return n-1 else: return jl bisection(array,0.7) # 0.6541053630832852 الآن سأجري مقارنة بينهم:
import numpy as np def bi(array,value): array=np.sort(array) n = len(array) if (value < array[0]): return -1 elif (value > array[n-1]): return n jl = 0 ju = n-1 while (ju-jl > 1): jm=(ju+jl) >> 1 if (value >= array[jm]): jl=jm else: ju=jm if (value == array[0]): return 0 elif (value == array[n-1]): return n-1 else: return jl def find1(a, a0): index = np.abs(a - a0).argmin() return index def find2(a, values): index = np.abs(np.subtract.outer(array, values)).argmin(0) return index # المقارنة array = np.random.random(1000) %timeit bi(array,0.7) print(bisection(array,0.7)) %timeit find1(array,0.7) print(find1(array,0.7)) %timeit find2(array,0.7) print(find2(array,0.7)) """ 535 ns ± 19.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) -1 5.92 µs ± 1.02 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each) 537 6.37 µs ± 336 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) 537 """
-
إجابة Ali Haidar Ahmad سؤال في التنعيم (Regularization) في Keras باستخدام طبقة ال Dropout كانت الإجابة المقبولة
ال dropout أو "التسرب " هو إحدى تقنيات محاربة ال Overfitting (الضبط الزائد). مبدأ هذه التقنية هو تجاهل أو تعطيل بعض الخلايا (العصبونات) بشكل عشوائي في طبقات (أو طبقة) الشبكة العصبية. . تأمل الصورة التالية:
وبالتالي سنقوم بمنع المودل من التركيز على خاصية "feature" معينة و نجبره على التعلم من كل الخصائص الموجودة لا أن يأخذ خاصية واحدة كقاعدة في التعلم ويعتمد عليها بشكل دائم. وبهذه الطريقة نتجنب حالة الـ overfitting ونتعلم من كل الخصائص الموجودة. أي أن الفكرة خلف هذه التقنية هي أنه في كل تكرار نقوم بتعطيل خلايا (نجعلها لاتشترك في التدريب والتوقع) بينما الخلايا المتبقية تشارك في عملية التدريب والتوقع، أي يستخدم مجموعة جزئية من العصبونات في كل تكرار (التكرار الواحد هو عملية انتشار أمامي (للتوقع) ثم انتشار خلفي(لتحديث قيم الأوزان)). أي أن تأثير هذه التقنية هو أن الشبكة تصبح أقل حساسية للأوزان المحددة للخلايا العصبية. ينتج عن هذا بدوره شبكة قادرة على التعميم "generalization " بشكل أفضل ومن غير المرجح أن تقع في ال OF على بيانات التدريب. ويمكننا أن نقول أيضاً أن الشبكة لن تقوم بحفظ مسار أو سلوك معين في عملية التوقع. انظر للصورة التالية:
وفي كيراس يمكنك استخدامها بالشكل التالي:
from tensorflow.keras.layers import Dropout Dropout(rate) حيث أن ال rate هو معدل الحذف ويأخذ قيمة بين 0 و 1. فمثلاً عند وضع 0.5 أي سيتم تعطيل 50% من العصبونات، وتعتبر هذه القيمة من الـ hyper parameters أيضاً التي يجب ضبطها في نموذجك بشكل دقيق. فاختيار قيم كبيرة لل rate (فوق 0.5) قد يؤدي إلى مشكلة جديدة وهي ال Underfitting. يجب أن تعلم أيضاً أنه يتم استخدام التسرب فقط أثناء تدريب النموذج ولا يتم استخدامه عند التقييم النهائي للنموذج (مرحلة التدريب مثلاً أو الاستخدام العملي) أي بمعنى آخر يستخدم فقط في مرحلة التدريب أما في مرحلة الاختبار أو الاستخدام فإنه تلقائياً لايتم إشراكها في عملية التوقع. الآن سأعطيك مثال عملي عليه أثناء بناء نموذج لتصنيف الأرقام المكتوبة بخط اليد:
from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Conv2D, Dropout, Flatten, MaxPooling2D # تحميل البيانات import tensorflow as tf (x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data() x_train.shape # (60000, 28, 28) # 4-dims تحويل المصفوفة إلى شكل رباعي الأبعاد x_train = x_train.reshape(x_train.shape[0], 28, 28, 1) x_test = x_test.reshape(x_test.shape[0], 28, 28, 1) input_shape = (28, 28, 1) # لنتمكن من الحصول على الفواصل العشرية بعد القسمة x_train = x_train.astype('float32') x_test = x_test.astype('float32') # Normalizing x_train /= 255 x_test /= 255 print('x_train shape:', x_train.shape) print('Number of images in x_train', x_train.shape[0]) print('Number of images in x_test', x_test.shape[0]) # بناء النموذج model = Sequential() model.add(Conv2D(32, kernel_size=(3,3), input_shape=input_shape)) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Flatten()) model.add(Dense(128, activation=tf.nn.relu)) model.add(Dropout(0.2)) # هنا أضفنا طبقة model.add(Dense(10,activation=tf.nn.softmax)) # تجميع النموذج model.compile(optimizer='rmsprop', loss='sparse_categorical_crossentropy', metrics=['acc']) model.fit(x_train,y_train, epochs=9) model.evaluate(x_test, y_test) # 98.5% حيث نضيفها بعد الطبقة التي نريد تطبيق التسرب عليها، وهنا قمنا بإضاففتها بعد الطبقة dense(128) أي أن هذه الطبقة سيتم تطبيق التسرب عليها خلال عملية التدريب وبالتالي في كل كل تكرار سيتم تعطيل (أو تجاهل) 20% من الخلايا فيها بشكل عشوائي، أي في كل تكرار ستشترك 102 خلية في التدريب والتوقع وسيتم تجاهل باقي الخلايا. وطبعاً يمكنك إضافتها بعد كل طبقة من طبقات نموذجك (هذا يرجع لك حسب تقديرك للمشكلة وماتتطلبه). لكن لاتستخدمها في بداية النموذج أي بعد التعليمة sequential لأنه في هذه الحالة تكون قد طبقتها على طبقة الدخل وبالتالي سيتم تجاهل قسم من ال features الخاصة بعيناتك وهذا أمر غير محبذ أبداً.
-
إجابة Ali Haidar Ahmad سؤال في ظهور الخطأ UnboundLocalError : local variable 'logs' referenced before assignment في كيراس كانت الإجابة المقبولة
عادة ماينتج هذا الخطأ عندما يكون حجم البيانات قليل، وبالتالي ينشأ هذا الخطأ بسبب حجم ال batch_size الذي اخترته حيث لايجب أن يكون حجمه أقل من حجم بيانات التدريب لديك، حيث أنه في معظم الحالات ، يكون سبب هذا الخطأ هو أن حجم بيانات التدريب أقل من حجم الدُفعة، لذا تأكد أولاً من أن with_noise يحتوي على 140 عينة على الأقل أو قم بتقليل حجم الدفعة (batch_size ). أي مثلاً اجعل حجمه 64 أو 32 أو اجعله Batch GD أي 1.
float validation_split = 2f; Sequential model = new Sequential(); no_noise = no_noise.astype(np.float32); with_noise = with_noise.astype(np.float32); no_noise /= 255; with_noise /= 255; # بناء النموذج model.Add(new Conv2D(128, kernel_size: new Tuple<int, int>(5, 5), activation: "tanh", input_shape: new Shape(45, 45,1))); model.Add(new Conv2D(64, kernel_size: new Tuple<int, int>(3, 3), activation: "tanh")); model.Add(new Conv2DTranspose(64, kernel_size : new Tuple<int,int> (3, 3), kernel_constraint : max_norm, activation: "tanh")); model.Add(new Conv2DTranspose(32, kernel_size : new Tuple<int,int> (3, 3), activation: "relu")); model.Add(new Conv2D(1, kernel_size : new Tuple<int,int>(3, 3), activation: "sigmoid", padding: "same")); model.Compile(optimizer: "rmsprop", loss: "binary_crossentropy"); model.Fit(with_noise, no_noise,epochs: 10,batch_size: 64,steps_per_epoch:2,validation_split: validation_split);
-
إجابة Ali Haidar Ahmad سؤال في ظهور الخطأ 'ValueError: Cannot feed value of shape (1, 1, 1) for Tensor 'lstm_1_input:0', which has shape '(9, 1, 1) في كيراس كانت الإجابة المقبولة
في القسم الثاني ينتج الخطأ، حيث يتم توقع كل خطوة في التسلسل (خطوة خطوة). وهذا يتطلب أن يكون حجم ال batch_size مساوي ل 1 أي:
Online Learning (Batch Size = 1) أي الحل يتغيير حجم الباتش كالتالي:
#sequence إنشاء تسلسل length = 10 s= [i/float(length) for i in range(length)] # إنشاء أزواج x/y df = DataFrame(s) df = concat([df, df.shift(1)], axis=1) df.dropna(inplace=True) val = df.values data = val[:, 0] label=val[:, 1] data = data.reshape(len(data), 1, 1) # القسم 0 n_batch = 1 # هنا n_epoch = 800 n_neurons = 12 model = Sequential() model.add(LSTM(n_neurons, batch_input_shape=(n_batch, data.shape[1], data.shape[2]), stateful=True)) model.add(Dense(1)) model.compile(loss='mse', optimizer='rmsprop') # القسم 1 for i in range(n_epoch): model.fit(data, label, epochs=1, batch_size=n_batch, verbose=1, shuffle=False) model.reset_states() # القسم 2 for i in range(len(data)): testX, testy = data[i], label[i] testX = testX.reshape(1, 1, 1) yhat = model.predict(testX, batch_size=1) print('>Expected=%.1f, Predicted=%.1f' % (testy, yhat)) هذا يعني أنه سيتم تحديث أوزان الشبكة بعد كل عينة تدريبية. وطبعاً هذا سيعطيك سرعة أكبر لكن التدريب لن يكون مستقراً.
طريقة أخرى، وهي تنفبذ كل التنبؤات دفعة واحدة، أي:
Batch Forecasting (Batch Size = N) وبالتالي يكون التعديل:
# القسم 2 yhat = model.predict(data, batch_size=n_batch) for i in range(len(label)): print('>Expected=%.1f, Predicted=%.1f' % (label[i], yhat[i])) لكن هذا يعني أننا قد نكون مقيدين للغاية في طريقة استخدام النموذج، سيتعين علينا استخدام جميع التنبؤات التي تم إجراؤها مرة واحدة ، أو الاحتفاظ بالتنبؤ الأول فقط وتجاهل الباقي.
لذا فالحل الأفضل هو استخدام أحجام دفعات مختلفة للتدريب والتنبؤ. طريقة القيام بذلك هي نسخ الأوزان من الشبكة التي تم تدريبها وإنشاء شبكة جديدة باستخدام الأوزان المدربة مسبقاً. يمكننا القيام بذلك باستخدام وظائف get_weights () و set_weights () في Keras API ، على النحو التالي:
# إعادة تعيين حجم الدفعة n_batch = 1 # إعادة تعريف النموذج new_model = Sequential() new_model.add(LSTM(n_neurons, batch_input_shape=(n_batch, X.shape[1], X.shape[2]), stateful=True)) new_model.add(Dense(1)) # copy weights عملية old_weights = model.get_weights() new_model.set_weights(old_weights) يؤدي هذا إلى إنشاء نموذج جديد يتم تجميعه compile بحجم دفعة 1. يمكننا بعد ذلك استخدام هذا النموذج الجديد لعمل تنبؤات من خطوة واحدة:
# القسم 2 for i in range(len(data)): testX, testy = data[i], label[i] testX = testX.reshape(1, 1, 1) yhat = new_model.predict(testX, batch_size=n_batch) print('>Expected=%.1f, Predicted=%.1f' % (testy, yhat))
-
إجابة Ali Haidar Ahmad سؤال في كيف نحسب عدد مرات تكرار عنصر معين في ndarray في مكتبة Numpy؟ كانت الإجابة المقبولة
التابع count تم تعريفه للاستخدام مع القوائم ولكنه غير معرف من أجل المصفوفات ولهذا السبب ظهر لديك هذا الخطأ، والحل كالتالي، نقوم بتحويل المصفوفة إلى قائمة عن طريق الباني list ثم نطبق عليها التابع:
a = np.arange(10) a=np.array([0, 11, 11, 3, 4, 11, 6, 7, 8, 9]) serach=11 list(a).count(serach) # 3 لكن هذه الطريقة يمكنك استخدامها فقط في حالة كانت مصفوفتك أحادية الأبعاد. أما في حالة كانت مصفوفتك متعددة الأبعاد فيمكنك اسخدام خدعتي السحرية لحل المشكلة، وهي استخدام التابع reshape لتحويل المصفوفة من مصفوفة متعددة الأبعاد ثم استخدام التايع count معها:
a = np.arange(10) a=np.array([[8, 9],[8, 8]]) a=a.reshape(-1) serach=8 list(a).count(serach) # 3 ويمكنك استخدام التابع np.bincount(a) أيضاً بنفس الطريقة (هذا التايع أيضاً يقوم بحساب التكرار للمصفوفات أحادية الأبعاد فقط، وبالتالي نستخدم نفس التكتيك السابق لحل المشكلة) حيث يعيد لك تكرارات كل العناصر:
a = np.arange(10) a=np.array([[8, 9],[8, 8]]) a=a.reshape(-1) print(a) # [8 9 8 8] serach=8 np.bincount(a) # array([0, 0, 0, 0, 0, 0, 0, 0, 3, 1], dtype=int64) إن مايميز هذا التابع هو سرعته الغير قابلة للمقارنة ببقية الطرق. وأيضاً يمكنك استخدام التابع Counter ينفس الأسلوب، حيث تعيد قاموس بكل قيمة وتكراراتها:
a = np.arange(10) a=np.array([[8, 9],[8, 8]]) a=a.reshape(-1) print(a) # [8 9 8 8] from collections import Counter Counter(a) # Counter({8: 3, 9: 1}) وأيضاً يمكنك استخدام التابع count_nonzero :
a = np.arange(10) a=np.array([[8, 9],[8, 8]]) np.count_nonzero(a == 8) # 8 a = np.zeros((3,2,2)) np.count_nonzero(a == 0) # 12 أو من خلال np.sum :
a = np.array([3,4,5,5,6]) np.sum(a == 5) # 2 أو من خلال التابع unique ثم zip:
a = np.array([3,4,5,5,6]) unique, counts = np.unique(a, return_counts=True) dict(zip(unique, counts)) # {3: 1, 4: 1, 5: 2, 6: 1} مايلي هو مقارنة في السرعة بين التحقيقات السابقة:
choices = np.random.randint(0, 100, 10000) %timeit [ np.sum(choices == k) for k in range(min(choices), max(choices)+1) ] %timeit np.unique(choices, return_counts=True) %timeit np.bincount(choices, minlength=np.size(choices)) # الأفضل %timeit [ np.count_nonzero(choices == k) for k in range(min(choices), max(choices)+1) ] %timeit [ list((choices.reshape(-1))).count(k) for k in range(min(choices), max(choices)+1) ] %timeit Counter(((choices.reshape(-1)))) """ 8.04 ms ± 801 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 596 µs ± 88 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) 44.5 µs ± 5.52 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each) 5.02 ms ± 429 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 390 ms ± 21.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 2.66 ms ± 166 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) """
-
إجابة Ali Haidar Ahmad سؤال في ترتيب عناصر مصفوفة في NumPy حسب العمود كانت الإجابة المقبولة
لفرز عناصر مصفوفة هناك عدة طرق للقيام بذلك، أولها استخدام التابع argsort من نمباي، حيث يعيد مؤشرات أو فهارس من المصفوفة، هذه المؤشرات يمكننا استخدامها لترتيب مصفوفتنا، سأعطيك الآن مثال لكيفية الاستفادة من هذا. لتكن لدينا المصفوفة التالية:
import numpy as np a = np.random.randint(70, size=(3, 3)) a """ array([[ 0, 33, 32], [53, 44, 4], [36, 34, 0]]) """ سنقوم أولاً باستعداء التابع argsort على العمود الأول من المصفوفة، وبالتالي ستحصل على هذه النتيجة:
a[:, 0].argsort() # array([0, 2, 1], dtype=int64) يوضح الخرج أن أصغر قيمة في العمود الأول هي في الموضع 0 (رقم السطر الموجودة فيه). وهذا صحيح ، فأقل قيمة في العمود الأول للمصفوفة هي 0، أما ثاني قيمة من الخرج هي 2 وهذا يعني أن ثاني أصغر قيمة في العمود الأول موجودة في الموضع 2 أي القيمة الثالثة أي 36 وهذا صحيح. أما ثالث قيمة من الخرج فتشير إلى ثالث أصغر قيمة في العمود وهكذا..، لفرز المصفوفة ، نحتاج الآن إلى استخدام المؤشرات التي أعطانا إياها التابع argsort لإعادة ترتيب الصفوف في المصفوفة. ويمكننا القيام بذلك عبر إجراء بسيط يمكن القيام به في سطر واحد من التعليمات البرمجية. إذاً سنستخدم نتيجة argsort على أنها فهارس الصف وسنضع الناتجة في a (مصفوفتنا) ، على النحو التالي:
a = a[a[:, 0].argsort()] a """ array([[ 0, 33, 32], [36, 34, 0], [53, 44, 4]]) """ كما ترى، تم ترتيب الصفوف الآن من الأقل إلى الأكبر وفقاً للعمود الأول. وللفرز في عمود مختلف، ما عليك سوى تغيير فهرس العمود.
a = a[a[:, 1].argsort()] a """ array([[ 0, 33, 32], [53, 34, 0], [36, 44, 4]]) """ حسناً ماذا إذا أردت الفرز على أساس الأسطر؟! يمكن أيضاً فرز مصفوفة NumPy حسب قيم الصفوف. يتم تحقيق ذلك بنفس طريقة الفرز باستخدام الأعمدة. نحتاج فقط إلى تغيير مواضع الفهرسة. على سبيل المثال ، لنأخذ المصفوفة التالية، ثم نفرز الأعمدة حسب القيم في الصف الأول. للقيام بذلك ، ما عليك سوى تحريك الفهرس (0) إلى موضع الصف ونقل نتيجة الفرز التنظيمي إلى موضع العمود:
import numpy as np a = np.random.randint(70, size=(3, 3)) a """ array([[44, 10, 23], [ 9, 32, 58], [67, 31, 39]]) """ a = a[:, a[0, :].argsort()] a """ array([[10, 23, 44], [32, 58, 9], [31, 39, 67]]) """ في بعض الأحيان يكون من الضروري الفرز على أكثر من عمود واحد. أحد الأمثلة على ذلك هو البيانات التي تحتوي على السنة والشهر واليوم والقيمة في أعمدة منفصلة. يمكن أن يتعامل ترتيب Argsort في NumPy مع فرز أعمدة متعددة باستخدام الوسيطة اللطيفة. لنبدأ بإنشاء مصفوفة من 4 أعمدة تمثل السنة والشهر واليوم والقيمة.
arr = np.array([[2019, 2, 1, 40], [2021, 4, 1, 80], [2020, 3, 2, 22], [2018, 1, 3, 11], [2021, 3, 9, 79]]) """ array([[2018, 1, 3, 11], [2019, 2, 1, 40], [2020, 3, 2, 22], [2021, 3, 9, 79], [2021, 4, 1, 80]]) """ سنستخدم الآن argsort لفرز الأعمدة ، بدءاً من الأولوية الأقل. هذا يعني أننا إذا أردنا الفرز حسب السنة ، ثم الشهر ، ثم اليوم ، فنحن بحاجة إلى الفرز حسب اليوم أولاً ، ثم الشهر ، ثم العام. بالنسبة للكل ما عدا النوع الأول ، نحتاج إلى تحديد النوع على أنه "ترتيب مدمج" ، والذي سيحافظ على سياق الفرز السابق. وهذا موضح في التعليمات البرمجية التالية:
# الفرز حسب اليوم arr = arr[arr[:, 2].argsort()] # حسب الششهر arr = arr[arr[:, 1].argsort(kind='mergesort')] # حسب السنة arr = arr[arr[:, 0].argsort(kind='mergesort')] يمكنك استخدام طرق أخرى أعقد أيضاً مثل استخدام lexsort من نمباي كما في المثال التالي:
import numpy as np a = np.random.randint(70, size=(3, 3)) a """ array([[12, 11, 6], [25, 46, 64], [42, 41, 1]]) """ col=0 a[np.lexsort(([1,-1]*a[:,[1,col]]).T)] """ array([[42, 41, 1], [25, 46, 64], [12, 11, 6]]) """ أو يمكنك باستخدام الدالة sorted مع الوسيط لامدا، وتعيد قائمة (لذا قم بإعادة تحويل الخرج إلى نمباي):
import numpy as np a = np.random.randint(70, size=(3, 3)) a """ array([[17, 46, 17], [39, 64, 54], [ 6, 19, 68]]) """ col=1 # العمود المراد الترتيب عليه a=sorted(a, key=lambda a_entry: a_entry[col]) np.array(a) """ [[ 6 19 68] [17 46 17] [39 64 54]] """ هذا كان كل ماقد يلزمك.
-
إجابة Ali Haidar Ahmad سؤال في كيفية طباعة مصفوفة Numpy بشكل كامل؟ كانت الإجابة المقبولة
يمكنك القيام بذلك في نمباي حيث أنها تمكننا من إزالة الاقتطاع وعرض النتائج كما هي ويتم ذلك باستخدام numpy.set_printoptions() وذلك اعتماداً على الوسيط threshold الذي يأخذ القيمتين threshold = np.inf أو threshold = sys.maxsize أو عدد صحيح، من خلال هذا الوسيط يتم طباعة أول 1000 رقم بدون اقتطاع "بشكل افتراضي أي إذا لم نضع maxsize أو inf ":
""" numpy.set_printoptions(precision=None, threshold=None, edgeitems=None, linewidth=None, suppress=None, nanstr=None, infstr=None, formatter=None) """ import numpy as np import sys nums = np.arange(100) np.set_printoptions(threshold=sys.maxsize) # هنا وضعنا أعلى عدد ممكن للعرض print(nums) """ [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99] """ #أو import numpy as np import sys nums = np.arange(100) np.set_printoptions(threshold=np.inf) print(nums) # انظر أيضاًَ import numpy as np import sys nums = np.arange(200) np.set_printoptions(threshold=1000,sign="-") print(nums) """ import numpy as np import sys nums = np.arange(200) np.set_printoptions(threshold=1000,sign="-") print(nums) [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199] """ أهم الوسطاء، precision عدد أرقام الدقة لطباعة النقطة العائمة floating point (الافتراضي 8). threshold العدد الإجمالي لعناصر المصفوفة التي تؤدي إلى التلخيص بدلاً من العرض الكامل للمصفوفة (الافتراضي 1000). لعرض المصفوفة كاملة بدون تلخيص، مرر sys.maxsize. أو np.inf. أما linewidth فهو عدد المحارف في كل سطر.
ويمكنك أيضاً استخدام التابع tolist الذي يقوم بتحويلها إلى قائمة كالتالي:
import numpy as np import sys nums = np.arange(200) print(nums.tolist()) """ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199] """
-
إجابة Ali Haidar Ahmad سؤال في تفريغ مصفوفة NumPy في ملف CSV؟ كانت الإجابة المقبولة
هناك عدة طرق للقيام بذلك، أولها استخدام باندا:
import pandas as pd import numpy as np # إنشاءمصفوفة a = np.arange(3,4).reshape(-1,2) # طباعة المصفوفة print(a) # تحويل المصفوفة إلى DataFrame df = pd.DataFrame(a) #CSV حفظ الداتافريم كملف df.to_csv("data1.csv", index=False) #يفضل إلغاء تخزين عمود الفهرس لأنه قد يسبب لك مشاكل عند إعادة تحميل الملف الطريقة الثانية هي استخدام numpy_array.tofile():
import numpy as np # إنشاء مصفوفة a = np.arange(3,4) # عرض المصفوفة print(a) #tofile() استخدام الطريقة #',' يجب أن تستخدم الفاصلة # إنشاء الملف a.tofile('data2.csv', sep = ',') استخدام numpy.savetext():
""" numpy.savetxt(fname, arr, fmt='%.18e', delimiter=' ', newline='\n', header='', footer='', comments='# ', encoding=None) """ import numpy as np # إنشاء مصفوفة arr = np.array([[11, 16, 3], [1, 0, 8]]) #CSV حفظ المصفوفة في ملف np.savetxt("a.csv", arr, delimiter = ",") لكن هنا سيتم تخزين البيانات في تنسيق أسي ك float مثل 2.000000000000000000e+00 لذا يجب عليك تغيير ال formatting باستخدام الوسيط fmt كما يلي:
np.savetxt('a.csv', arr, fmt="%d", delimiter=",") طبعاً delimiter هو سلسلة أو حرف لاستخدامه كفاصل عنصر. و newline سلسلة أو حرف لاستخدامه كفاصل أسطر. و header تكتب سلسلة في بداية ملف txt أي ترويسة. أما footer فتكتب سلسلة في نهاية الملف (ذيل). و fmt افتراضياً تكون %.18e أي بالتنسيق الأسي. أما arr فهي مصفوفة أحادية أو ثنائية البعد حصراً. مثال آخر:
import numpy as np arr = np.array([6, 1, 4, 2, 18, 9, 3, 4, 2, 8, 11]) np.savetxt('array.csv', [arr], delimiter=',', fmt='%d') # ستخزن بالشكل التالي # 6,1,4,2,18,9,3,4,2,8,11 مررنا المحدد "،" لجعله بتنسيق csv. تم قمنا بتمرير نوع التنسيق أيضاً كـ "٪ d" ، أي تخزين العناصر كأعداد صحيحة. وكما أشرت فإنه بشكل افتراضي، سيتم تخزين الأرقام بتنسيق عائم flotting point. وللتنويه أيضاً، إذا لم تقم بإحاطة مصفوفة numpy ب [] أي تحويلها إلى قائمة أثناء تمريرها إلى numpy.savetxt () فقد لا يعمل محدد الفاصلة، وسيستخدم "\ n" كمحدد افتراضي. لذا يفضل إحاطتها. مثال آخر مع إضافة ترويسة وذيل:
np.savetxt('array_hf.csv', [arr], delimiter=',', fmt='%d' , header='A Sample 2D Numpy Array :: Header', footer='This is footer') """ # A Sample 2D Numpy Array :: Header 6,1,4,2,18,9,3,4,2,8,11 # This is footer """ مثال آخر مع مصفوفة ثنائية الأبعاد:
arr2D = np.array([[11, 12, 13, 22], [21, 7, 23, 14], [31, 10, 33, 7]]) np.savetxt('2darray.csv', arr2D, delimiter=',', fmt='%d') """ 11,12,13,22 21,7,23,14 31,10,33,7 """ أيضاً، بدلاً من حفظ مصفوفة كاملة ثنائية الأبعاد في ملف csv ، إذا أردنا، يمكننا حفظ أعمدة أو صفوف فردية أو متعددة فقط.
# حفظ عمود np.savetxt('a.csv', [arr2D[:,1]], delimiter=',', fmt='%d') """ 12,7,10 """ # حفظ سطر np.savetxt('aa.csv', [arr2D[1] ], delimiter=',', fmt='%d') """ 21,7,23,14 """ ولحفظ مصفوفة مهيكلة Structured Numpy array:
dtype = [('Name', (np.str_, 10)), ('Marks', np.float64)] structure = np.array([('Ali', 21.2, 5), ('Eyad', 22.3, 4)], dtype=dtype) print(structure) # [('Ali', 21.2, 5) ('Eyad', 22.3, 4)] np.savetxt('structured.csv', structure, delimiter=',', fmt=['%s' , '%f', '%d'], header='Name,Marks,Age', comments='') """ Name,Marks,Age Ali,21.2, 5 Eyad,22.3, 4 """ وبما أن كل عنصر في المصفوفة الرقمية الخاصة بنا كان عبارة عن مزيج من سلسلة ، عدد عشري وعدد صحيح ، لذلك أثناء حفظه في ملف csv ، نقوم بتمرير خيارات التنسيق كلها أي ["٪ s" ، "٪ f" ، "٪ d"]
ويمكنك لاحقاً تحميل الملف بعدة طرق، باستخدام loadtxt:
from numpy import loadtxt # تحميل المصفوفة data = loadtxt('data.csv', delimiter=',') # طباعتها print(data) أو من باندا:
import pandas as pd data = pd.read_csv("filename.csv") # عرض أول 5 أسطر من الملف data.head() # إذا أردت عرض أسطر أكثر مرر عددها إلى الوسيط التالي data.head(n=10)
-
إجابة Ali Haidar Ahmad سؤال في ظهور الخطأ (InvalidArgumentError: Received a label value of ? which is outside the valid range of [0, 1 في كيراس كانت الإجابة المقبولة
عندما تكون عدد الأصناف n في مشكلتنا أكبر من 2، يجب أن تحوي طبقتك الأخيرة على n خلية بغض النظر عن نوع دالة التكلفة التي استخدمتها (أي حتى لو استخدمت sparse_categorical_crossentropy) حيث أن الغاية الأساسية من ال sparse_categorical_crossentropy هو الراحة في الاستخدام (عدم الاضطرار إلى تحويل البيانات إلى ترميز ال One-Hot)، لكنها لاتغنيك عن وجود عدد من الخلايا يطابق عدد الأصناف في آخر طبقة، وبما أنك تتعامل مع مهمة لتصنيف الأخبار ولديك 46 صنف وبالتالي يكون التصحيح:
from keras.datasets import reuters (train_data, train_labels), (test_data, test_labels) = reuters.load_data( num_words=10000) word_index = reuters.get_word_index() reverse_word_index = dict([(value, key) for (key, value) in word_index.items()]) decoded_newswire = ' '.join([reverse_word_index.get(i - 3, '?') for i in train_data[0]]) import numpy as np def vectorize_sequences(sequences, dimension=10000): results = np.zeros((len(sequences), dimension)) for i, sequence in enumerate(sequences): results[i, sequence] = 1. return results x_train = vectorize_sequences(train_data) x_test = vectorize_sequences(test_data) from keras.utils.np_utils import to_categorical one_hot_train_labels = to_categorical(train_labels) one_hot_test_labels = to_categorical(test_labels) from keras import models from keras import layers model = models.Sequential() model.add(layers.Dense(64, activation='relu', input_shape=(10000,))) model.add(layers.Dense(64, activation='relu')) model.add(layers.Dense(46, activation='softmax')) # يجب أن يتطابق عدد الأصناف مع عدد المخرجات model.compile(optimizer='rmsprop', loss='sparse_categorical_crossentropy', metrics=['accuracy']) x_val = x_train[:1000] partial_x_train = x_train[1000:] y_val = train_labels[:1000] partial_y_train = train_labels[1000:] history = model.fit(partial_x_train, partial_y_train, epochs=20, batch_size=512, validation_data=(x_val, y_val)) للتنويه: هناك هدف آخر من استخدام sparse_categorical_crossentropy وهو زيادة الكفاءة في التخزين والأداء (فهي لاتحتاج إلى تمثيل الفئات في متجهات عالية الأبعاد إضافة إلى أنها تقلل عدد العمليات الحسابية اللازمة).
-
إجابة Ali Haidar Ahmad سؤال في الطبقة MaxPooling2D كانت الإجابة المقبولة
تستخدم بشكل أساسي مع الشبكات العصبية التلاففية CNN حيث غالباً ماتتبع طبقة ال CNN طبقة MaxPooling. مبدأياً تأمل الصورة التالية:
هنا لدينا مصفوفة 4*4 ونافذة حجمها 2*2 تمر على المصفوفة (لاحظ أن النافذة التي حجمها2*2 تتحرك بمقدار خطوتين) في البداية كانت النافذة موضوعة على المربع الأحمر وبالتالي ستأخذ أكبر قيمة فيه هي 20، ثم ستمشي على المصفوفة أفقياً بمقدار خطوتين (أي بكسلين أفقياً) وبالتالي ستصيح النافذة موجودة على المربع الأصفر وبالتالي ستأخذ أكبر قيمة فيه وهي 30 ، الآن وصلنا لنهاية حدود المصفوفة وبالتالي ننزل بمقدار خطوتين (أي بكسلين عمودياً) وبالتالي تصبح النافذة على المربع الأزرق وأكبر قيمة هي 112 وهكذا..
لاحظ كيف تم اختزال أبعاد المصفوفة من 4*4 إلى 2*2. حسناً لماذا نستخدم هذه الطبقة؟ السبب الأول هو أنها تقوم بتخفيف العبء الحسابي "Reducing computational load" فنظراً لأن MaxPooling يقلل من دقة الإخراج المعطى من الطبقة التلافيفية، وبالتالي ستنظر الشبكة في مناطق أكبر من الصورة في وقت واحد ، مما يقلل من كمية المعلمات في الشبكة وبالتالي يقلل من الحمل الحسابي. والسبب الثاني هو "Reducing overfitting" فهي تساعد في محاربة الضبط الزائد، حيث أن الفكرة وراء عمل max pooling هو أنها بالنسبة لصورة معينة، ستبحث شبكتنا لاستخراج بعض الميزات الخاصة. فهي تبحث عن الحواف والمنحنيات والدوائر وما إلى ذلك من السمات التي تميز الصورة (يمكننا التفكير في وحدات البكسل الأعلى قيمة على أنها الأكثر نشاطاً). وبالتلي فهي تركز على البكسلات الأعلى قيمة وتتجاهل البكسلات الأقل قيمة. طبعاُ يمكننا أن نغير حجم النافذة وأن نغير حجم الخطوات أو أن نقوم بخطوة نسميها الحشو padding التي تقوم بحشو حدود المصفوفة بأصفار لكي تحافظ على أبعاد المصفوفة (الصورة). كيراس أو تنسرفلو تؤمن لك طريقة سهلة للقيام بهذا. لها الشكل التالي:
tf.keras.layers.MaxPooling2D( pool_size=(2, 2), strides=None, padding="valid", data_format=None ) # الوسيط الأخير سأتحدث عنه في النهاية pool_size: يمثل حجم النافذة، ويمكنك إسناد عدد صحيح أو tuple بحيث إذا استخدمت عدد صحيح مثلاً 2 فهذا يعني أنك سوف تستخدم نافذة بحجم 2*2 وإما إذا استخدمت tuple فمثلاً (2,2) فهذا يعني أن حجم النافذة سيكون 2*2. الوسيط الثاني strides هو حجم الخطوة أي مقدار إزاحة النافذة، فمثلاً إذا اخترت (1,1) هذا يعني أنه ستتم إزاحة النافذة بمقدار 1 بكسل في العرض و 1 بكسل في الطول (النافذة تمشي على طول سطر المصفوفة بمقدار بكسل واحد وعندما تصل لنهاية أول سطر ستنزل للسطر التالي بمقدار بكسل واحد). أما بالنسبة لآخر وسيط فهو يمثل ال padding أي الحشو ففي حال استخدمت vaild فلن يتم حشو حدود المصفوفة بأصفار (أي لن يتم الحفاظ على أبعاد المصفوفة أي كما في المثال في الأعلى ويجب أن تعلم أن عملية الحشو هذه تتم بما يتلائم مع المصفوفة ولاتقلق فكيراس تتكفل بكل هذا الأمر) والمصفوفة الناتجة في هذه الحالة:
output_shape = math.floor((input_shape - pool_size) / strides) + 1 (when input_shape >= pool_size) أما في حالة استخدمت same فسوف يقوم بعملية الحشو. والمصفوفة الناتجة في هذه الحالة:
output_shape = math.floor((input_shape - 1) / strides) + 1 الآن انظر للأمثلة التالية:
# مصفوفة بحجم 3*3 # حجم الخطوة هنا اخترناه بمقدار بكسل واحد # حجم النافذة اخترناها 2*2 #valid الحشو x = tf.constant([[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]]) # قمت بتحويل مصفوفة ال 3*3 إلى مصفوفة ب 4 أبعاد لأن هذه الطبقة لاتستقبل إلى مصفوفة بأربع أبعاد كما سأوضح بعد قليل x = tf.reshape(x, [1, 3, 3, 1]) max_pool_2d = tf.keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(1, 1), padding='valid') c=max_pool_2d(x) # هنا قمت بتحويل الخرج من رباعي إلى ثنائي الأبعاد لتسهل قراءة الخرج tf.reshape(c, [ 2, 2]) # الخرج """ <tf.Tensor: shape=(2, 2), dtype=float32, numpy= array([[5., 6.], [8., 9.]], dtype=float32)> """ مثال آخر:
# مصفوفة بحجم 3*3 # حجم الخطوة هنا اخترناه بمقدار بكسل واحد # حجم النافذة اخترناها 2*2 #same الحشو x = tf.constant([[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]]) x = tf.reshape(x, [1, 3, 3, 1]) max_pool_2d = tf.keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(1, 1), padding='same') # تمت إضافةعمود بأصفار وسطر بأصفار للحفاظ على الأبعاد c=max_pool_2d(x) c tf.reshape(c, [ 3, 3]) """ <tf.Tensor: shape=(3, 3), dtype=float32, numpy= array([[5., 6., 6.], [8., 9., 9.], [8., 9., 9.]], dtype=float32)> """ يمكنك الآن التلاعب بقيم الوسطاء لتفهم أكثر. الآن سأستخدم لك هذه الطبقة في نموذج يحتوي على طبقة إدخال تقبل إدخال أبعاده 20 × 20 × 3 ، ثم طبقة كثيفة تليها طبقة تلافيفية تليها طبقة تجميع قصوى ، ثم طبقة تلافيفية أخرى ، تليها طبقة مخرجات.، ونظراً لأن الطبقات التلافيفية هنا ثنائية الأبعاد ، فإننا نستخدم طبقة MaxPooling2D من Keras ، لكن Keras لديها أيضًا طبقات تجميع 1d و 3 d max أيضاً.:
import keras from keras.models import Sequential from keras.layers import Activation from keras.layers.core import Dense, Flatten from keras.layers.convolutional import * from keras.layers.pooling import * # بناء نموذج model_valid = Sequential([ # الدخل هو صورة بأبعاد 20 ب 20 و 3 قنوات لونية أي صورة ملونة Dense(16, input_shape=(20,20,3), activation='relu'), Conv2D(32, kernel_size=(3,3), activation='relu', padding='same'), MaxPooling2D(pool_size=(2, 2), strides=2, padding='valid'), Conv2D(64, kernel_size=(5,5), activation='relu', padding='same'), Flatten(), Dense(2, activation='softmax') ]) # هكذا سيكون شكل النموذج """ _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense_2 (Dense) (None, 20, 20, 16) 64 _________________________________________________________________ conv2d_1 (Conv2D) (None, 20, 20, 32) 4640 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 10, 10, 32) 0 _________________________________________________________________ conv2d_2 (Conv2D) (None, 10, 10, 64) 51264 _________________________________________________________________ flatten_1 (Flatten) (None, 6400) 0 _________________________________________________________________ dense_2 (Dense) (None, 2) 12802 ================================================================= Total params: 68,770 Trainable params: 68,770 Non-trainable params: 0 _________________________________________________________________ """ الدخل والخرج: نعود الآن إلى الوسيط الرابع هو data_format هذا الوسيط يحدد ترتيب الأبعاد في المدخلات. يأخذ قيمتين إما channels_last وهي الحالة الافتراضية أي أن آخر وسيط في الإدخال سيمثل عدد القنوات اللونية في الصورة، أو channels_first أي ستكون في البداية، وعلى هذه الأساس سيختلف شكل الإدخال والإخراج لطبقتك :
# الدخل data_format='channels_last': 4D tensor with shape (batch_size, rows, cols, channels). data_format='channels_first': 4D tensor with shape (batch_size, channels, rows, cols). # الخرج data_format='channels_last': 4D tensor with shape (batch_size, pooled_rows, pooled_cols, channels). data_format='channels_first': 4D tensor with shape (batch_size, channels, pooled_rows, pooled_cols).
-
إجابة Ali Haidar Ahmad سؤال في تشغيل النموذج على ال CPU في كيراس Keras كانت الإجابة المقبولة
يمكنك استخدام السلسلة الفارغة أو -1 فكلاهما نفس المعنى هنا. السلسلة الفارغة (أو -1 كما أشارت ريم) تعني أنه لايوجد أجهزة GPU (حتى ولو كانت موجودة) أي أنت تخفيها عنه لكي لايستخدمها. لذا لاداعي للتصحيح فلايوجد خطأ، انظر مثلاً:
import os os.environ["CUDA_VISIBLE_DEVICES"] = "" import tensorflow as tf from tensorflow.python.client import device_lib print(device_lib.list_local_devices()) # عرض الأجهزة المتوفرة """ [name: "/device:CPU:0" device_type: "CPU" memory_limit: 268435456 locality { } incarnation: 5719422577836377687 ] """ أما وضع 0 أو 1 أو 2 (أعداد صحيحية موجبة) فهي تحدد أجهزة ال GPU التي تريد جعلها مرئية فالأجهزة التي يوجد فهرسها في التسلسل هي فقط الأجهزة المرئية لتطبيقات CUDA ويتم تعدادها بترتيب التسلسل، وإذا كان أحد الفهارس غير صالح، فلن تظهر لتطبيقات CUDA سوى الأجهزة التي يسبق فهرسها الفهرس غير الصحيح. أي مثلاً: لو ضبطتها بالشكل التالي 0,2,-1,1، فهذا يعني أن الجهاز الذي ترتيبه 0 و 2 سيكونان مرئيان لكن عندما يصل ل -1 (فهرس غير صالح أو غير موجود) فهنا سيتجاهله ويتجاهل مابعده أي سيتجاهل الجهاز ذو الفهرس 1 ولن يراه.
حتى بالنسبة للإصدارات المختلفة فلا يوجد فرق في التعليمات. ,والتعليمة os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID" ليس لها علاقة بنسخة كيراس أو ويندوز وإنما هي المنهجية التي سيتم فيها ترتيب ال GPU التي لديك.
-
إجابة Ali Haidar Ahmad سؤال في ظهور الخطأ () ValueError: Error when checking target: expected dense_1 to have 3 dimensions, but got array with shape في كيراس keras وتنسرفلو tensorflow كانت الإجابة المقبولة
إن طبقة ال LSTM الثانية الخاصة بك تقوم بإعادة كامل التسلسل أي خرجها 3D وذلك بسبب ضبط الوسيط return_sequences=True على True والطبقات الكثيفة Dense بشكل افتراضي تقوم بتطبيق kernel على كل خطوة زمنية أيضاً مما ينتج عنه تسلسل:
# (batchsize, 50, 2) model.add( LSTM( 1024, input_shape=(50, 2), return_sequences=True)) # (batchsize, 50, 1024) model.add( LSTM( 200, return_sequences=True)) # (batchsize, 50, 200) model.add( (Dense(1))) # (batchsize, 50, 1) وهو الخرج الخاص بك لذا لحل المشكلة يجب عليك أن تقوم بالضبط التالي return_sequences=False في طبقة LSTM الثانية:
import keras from keras.layers import Dense,LSTM import keras model = keras.Sequential() model.add( LSTM( 1024, input_shape=(50, 2), return_sequences=True)) model.add( LSTM( 200, return_sequences=False)) #(batchsize, 200) model.add( (Dense(1,activation=None))) #(batchsize, 1) model.compile(optimizer='rmsprop',loss='mae') model.fit( X, y, batch_size = 64,epochs=15)
-
إجابة Ali Haidar Ahmad سؤال في استخدم verbose أثناء تدريب النماذج في keras و tensorflow كانت الإجابة المقبولة
نستخدم verbose لمراقبة عملية تدريب النموذج خلال مرحلة ال Validation بحيث: إذا وضعنا لها القيمة 0 فهذا يعني أن عملية التدريب ستكون صامتة كما نسميها أو مخفية عنك أو بعنى آخر لن ترى أي شيء خلال عملية التدريب، وإذا وضعنا لها القيمة 1 فهذا يعني أنك ستكون قادر على مراقبة عملية التدريب ورؤية النتائج بعد كل epoch وسيظهر لك شريط يمثل عملية التقدم خلال كل epoch أثناء التدريب، وفي حال وضعت 2 لن فسيكون الأمر مشابهاً للحالة السابقة لكن بدون شريط التقدم، انظر للأمثلة التالية التي توضح الأمر جيداً.
############################################ verbose=1 ############################################################## from keras.datasets import boston_housing (train_data, train_targets), (test_data, test_targets) =boston_housing.load_data() mean = train_data.mean(axis=0) train_data -= mean std = train_data.std(axis=0) train_data /= std test_data -= mean test_data /= std from keras import models from keras import layers model = models.Sequential() # يمكنك تمريره إلى طبقتك بالشكل التالي # أو tf.keras.activations.relu() model.add(layers.Dense(64, activation='relu', input_shape=(train_data.shape[1],))) model.add(layers.Dense(64, activation='relu')) model.add(layers.Dense(1)) model.compile(optimizer='rmsprop', loss='mse', metrics=['mae']) history = model.fit(train_data, train_targets,epochs=7, batch_size=1, verbose=1) ----------------------------------------------------------------------------------------- Epoch 1/7 404/404 [==============================] - 3s 1ms/step - loss: 321.6080 - mae: 14.8919 Epoch 2/7 404/404 [==============================] - 0s 1ms/step - loss: 20.1112 - mae: 3.1887 Epoch 3/7 404/404 [==============================] - 1s 1ms/step - loss: 20.4705 - mae: 2.8889 Epoch 4/7 404/404 [==============================] - 1s 1ms/step - loss: 17.5232 - mae: 2.5841 ETA: 0s - loss: 13.2 Epoch 5/7 404/404 [==============================] - 0s 1ms/step - loss: 14.8107 - mae: 2.4500 Epoch 6/7 404/404 [==============================] - 1s 1ms/step - loss: 18.6534 - mae: 2.6635 Epoch 7/7 404/404 [==============================] - 0s 1ms/step - loss: 13.8696 - mae: 2.2664 ############################################ verbose=2 ############################################################## Epoch 1/7 404/404 - 1s - loss: 146.2869 - mae: 8.8513 Epoch 2/7 404/404 - 0s - loss: 26.0904 - mae: 3.3522 Epoch 3/7 404/404 - 0s - loss: 19.3153 - mae: 2.8920 Epoch 4/7 404/404 - 0s - loss: 15.3334 - mae: 2.7163 Epoch 5/7 404/404 - 0s - loss: 13.5590 - mae: 2.5430 Epoch 6/7 404/404 - 0s - loss: 13.1906 - mae: 2.4175 Epoch 7/7 404/404 - 0s - loss: 12.6008 - mae: 2.3849 ############################################ verbose=0 ############################################################## لن يظهر أي شيء
-
إجابة Ali Haidar Ahmad سؤال في الحصول على خرج كل طبقة في النموذج في keras كانت الإجابة المقبولة
هذا أمر مهم في بعض الحالات عندما نستخدم الطبقات التلاففية، يمكنك القيام بذلك في كيراس من خلال model.layers[index].output حيث أنها تقوم بإعطاء خرج أي طبقة من خلال تمرير رقم الطبقة أي ال index الخاص بها. ومن خلالها يمكنك الحصول على طلبك وهو خرج كل طبقة كالتالي:
from keras import backend as K #placeholder إدخال ال in = model.input # مخرجات كل الطبقات outputs = [layer.output for layer in model.layers] # تابع التقييم functor = K.function([in , K.learning_phase()], outputs ) # الاختبار test = np.random.random(input_shape)[np.newaxis,...] layer_outs = functor([test, 1.]) print layer_outs ولمحاكاة عملية التسرب (أقصد التنعيم وتحديداً ال Dropout هنا)، استخدم learning_phase كـ 1. في layer_outs وإلا استخدم 0. حيث أننا نحتاجها في حال احتوى النموذج على طبقة Dropout أو batchnorm كما تعلم.