تعلم كيفية إنشاء مُقدِّرات مخصصة في scikit-learn لتوسيع وظائفها وتنفيذ خوارزميات تعلم الآلة الخاصة بك. يغطي هذا الدليل كل شيء من الأساسيات إلى التقنيات المتقدمة.
مُقدِّرات Scikit-learn المخصصة في بايثون: دليل شامل لتنفيذ الخوارزميات
تُعد Scikit-learn مكتبة بايثون قوية ومستخدمة على نطاق واسع في مجال تعلم الآلة. على الرغم من أنها توفر مجموعة واسعة من الخوارزميات الجاهزة، إلا أن هناك مواقف تحتاج فيها إلى تنفيذ خوارزمياتك المخصصة. لحسن الحظ، تقدم scikit-learn إطار عمل مرنًا لإنشاء مُقدِّرات مخصصة، مما يسمح لك بدمج خوارزمياتك بسلاسة في نظام scikit-learn البيئي. سيرشدك هذا الدليل الشامل خلال عملية بناء مُقدِّرات مخصصة، بدءًا من فهم الأساسيات وحتى تنفيذ التقنيات المتقدمة. سنستكشف أيضًا أمثلة من العالم الواقعي لتوضيح التطبيقات العملية للمُقدِّرات المخصصة.
لماذا ننشئ مُقدِّرات مخصصة؟
قبل الغوص في تفاصيل التنفيذ، دعنا نفهم لماذا قد ترغب في إنشاء مُقدِّرات مخصصة:
- تنفيذ خوارزميات جديدة: لا تغطي Scikit-learn كل خوارزميات تعلم الآلة الممكنة. إذا قمت بتطوير خوارزمية جديدة أو ترغب في تنفيذ ورقة بحثية، فإن إنشاء مُقدِّر مخصص هو الطريق الصحيح.
- تخصيص الخوارزميات الحالية: قد ترغب في تعديل خوارزمية موجودة في scikit-learn لتناسب احتياجاتك الخاصة بشكل أفضل. تسمح لك المُقدِّرات المخصصة بتوسيع أو تكييف الوظائف الحالية.
- التكامل مع المكتبات الخارجية: قد ترغب في استخدام خوارزميات من مكتبات بايثون أخرى غير متوافقة مباشرة مع scikit-learn. توفر المُقدِّرات المخصصة جسرًا بين هذه المكتبات وواجهة برمجة التطبيقات (API) الخاصة بـ scikit-learn.
- تحسين قابلية إعادة استخدام الكود: من خلال تغليف خوارزميتك في مُقدِّر مخصص، يمكنك إعادة استخدامها بسهولة في مشاريع مختلفة ومشاركتها مع الآخرين.
- تعزيز التكامل مع خطوط الأنابيب (Pipelines): تتكامل المُقدِّرات المخصصة بسلاسة مع خطوط أنابيب scikit-learn، مما يمكّنك من بناء تدفقات عمل معقدة لتعلم الآلة.
فهم أساسيات مُقدِّرات Scikit-learn
في جوهره، مُقدِّر scikit-learn هو فئة (class) في بايثون تنفذ دالتي fit و predict (وأحيانًا دوال أخرى مثل transform أو fit_transform). تحدد هذه الدوال سلوك المُقدِّر أثناء التدريب والتنبؤ. هناك نوعان رئيسيان من المُقدِّرات:
- المحوّلات (Transformers): تقوم هذه المُقدِّرات بتحويل البيانات من تنسيق إلى آخر. تشمل الأمثلة
StandardScalerوPCAوOneHotEncoder. وعادةً ما تنفذ دالتيfitوtransform. - النماذج (المتنبئات - Predictors): تتعلم هذه المُقدِّرات نموذجًا من البيانات وتستخدمه لإجراء التنبؤات. تشمل الأمثلة
LinearRegressionوDecisionTreeClassifierوKMeans. وعادةً ما تنفذ دالتيfitوpredict.
يشترك كلا النوعين من المُقدِّرات في واجهة برمجة تطبيقات (API) مشتركة، مما يسمح لك باستخدامهما بالتبادل في خطوط الأنابيب وأدوات scikit-learn الأخرى.
إنشاء محوّل مخصص بسيط
لنبدأ بمثال بسيط لمحوّل مخصص. سيقوم هذا المحوّل بتغيير مقياس كل ميزة بعامل ثابت. هذا المحوّل مشابه لـ `StandardScaler`، ولكنه أبسط ويسمح بتحديد عامل قياس مخصص.
from sklearn.base import BaseEstimator, TransformerMixin
import numpy as np
class FeatureScaler(BaseEstimator, TransformerMixin):
def __init__(self, factor=1.0):
self.factor = factor
def fit(self, X, y=None):
# No fitting needed for this transformer
return self
def transform(self, X):
return X * self.factor
إليك تفصيل للكود:
- الوراثة (Inheritance): نرث من
BaseEstimatorوTransformerMixin. توفرBaseEstimatorوظائف أساسية مثلget_paramsوset_params، بينما توفرTransformerMixinتنفيذًا افتراضيًا لـfit_transform(الذي يستدعيfitثمtransform). __init__: هذه هي الدالة البانية (constructor). تأخذ عامل القياس كمعامل وتخزنه في السمةself.factor. من المهم تحديد معاملات المُقدِّر الخاص بك في الدالة البانية.fit: تُستدعى هذه الدالة لملاءمة المحوّل مع البيانات. في هذه الحالة، لا نحتاج إلى تعلم أي شيء من البيانات، لذلك نعيد ببساطةself. غالبًا ما يكون المعاملyغير مستخدم للمحوّلات، ولكنه مطلوب للتوافق مع واجهة برمجة تطبيقات scikit-learn.transform: تُستدعى هذه الدالة لتحويل البيانات. ببساطة نضرب كل ميزة في عامل القياس.
الآن، دعنا نرى كيفية استخدام هذا المحوّل المخصص:
# Example Usage
from sklearn.pipeline import Pipeline
X = np.array([[1, 2], [3, 4], [5, 6]])
# Create a FeatureScaler with a factor of 2
scaler = FeatureScaler(factor=2.0)
# Transform the data
X_transformed = scaler.transform(X)
print(X_transformed)
# Output:
# [[ 2. 4.]
# [ 6. 8.]
# [10. 12.]]
# Using in a pipeline
pipe = Pipeline([('scaler', FeatureScaler(factor=3.0))])
X_transformed_pipeline = pipe.fit_transform(X)
print(X_transformed_pipeline)
# Output:
# [[ 3. 6.]
# [ 9. 12.]
# [15. 18.]]
إنشاء نموذج مخصص بسيط (متنبئ)
بعد ذلك، لنقم بإنشاء نموذج مخصص بسيط. سيتنبأ هذا النموذج بمتوسط بيانات التدريب لجميع التنبؤات المستقبلية. على الرغم من أنه ليس مفيدًا بشكل خاص، إلا أنه يوضح البنية الأساسية للمتنبئ المخصص.
from sklearn.base import BaseEstimator, RegressorMixin
import numpy as np
class MeanPredictor(BaseEstimator, RegressorMixin):
def __init__(self):
self.mean_ = None
def fit(self, X, y):
self.mean_ = np.mean(y)
return self
def predict(self, X):
return np.full(X.shape[0], self.mean_)
إليك تفصيل للكود:
- الوراثة (Inheritance): نرث من
BaseEstimatorوRegressorMixin. توفرRegressorMixinتطبيقات افتراضية للدوال المتعلقة بالانحدار (regression) (على الرغم من أننا لا نستخدمها في هذا المثال). __init__: نقوم بتهيئةself.mean_إلىNone. ستخزن هذه السمة متوسط المتغير الهدف بعد الملاءمة.fit: تحسب هذه الدالة متوسط المتغير الهدفyوتخزنه فيself.mean_.predict: تعيد هذه الدالة مصفوفة بنفس طول الإدخالX، حيث تكون كل قيمة مساوية للمتوسط المخزن.
الآن، دعنا نرى كيفية استخدام هذا النموذج المخصص:
# Example Usage
X = np.array([[1], [2], [3]])
y = np.array([10, 20, 30])
# Create a MeanPredictor
predictor = MeanPredictor()
# Fit the model
predictor.fit(X, y)
# Predict on new data
X_new = np.array([[4], [5], [6]])
y_pred = predictor.predict(X_new)
print(y_pred)
# Output:
# [20. 20. 20.]
تنفيذ التحقق من صحة المعاملات
من الأهمية بمكان التحقق من صحة المعاملات التي يتم تمريرها إلى مُقدِّراتك المخصصة. يساعد هذا في منع السلوك غير المتوقع ويوفر رسائل خطأ مفيدة للمستخدمين. يمكنك استخدام دالة check_estimator من sklearn.utils.estimator_checks لاختبار مُقدِّرك تلقائيًا مقابل مجموعة من الاختبارات الشائعة.
أولاً، دعنا نعدل FeatureScaler ليشمل التحقق من صحة المعاملات:
from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.utils import validation
class FeatureScaler(BaseEstimator, TransformerMixin):
def __init__(self, factor=1.0):
self.factor = factor
def fit(self, X, y=None):
# Validate the input
self.factor = validation.check_scalar(
self.factor,
'factor',
target_type=float,
min_val=0.0,
include_boundaries=True
)
return self
def transform(self, X):
validation.check_is_fitted(self)
X = validation.check_array(X)
return X * self.factor
إليك ما أضفناه:
validation.check_scalar: نستخدم هذه الدالة في دالةfitللتحقق من أن المعاملfactorهو عدد عشري (float) أكبر من أو يساوي 0.validation.check_is_fitted: نستخدم هذه الدالة في دالة `transform` للتأكد من أن المُقدِّر قد تم تدريبه (fitted) قبل تحويل البيانات.validation.check_array: نستخدم هذه الدالة للتحقق من أن الإدخال `X` هو مصفوفة صالحة.
الآن، دعنا نستخدم check_estimator لاختبار مُقدِّرنا:
from sklearn.utils.estimator_checks import check_estimator
# Perform checks
check_estimator(FeatureScaler)
إذا كانت هناك أي مشاكل في مُقدِّرك (على سبيل المثال، أنواع معاملات غير صحيحة أو دوال مفقودة)، فستثير دالة check_estimator خطأ. هذه أداة قوية لضمان التزام مُقدِّراتك المخصصة بواجهة برمجة تطبيقات scikit-learn.
التعامل مع المعلمات الفائقة (Hyperparameters) باستخدام GridSearchCV
إحدى الفوائد الرئيسية لإنشاء مُقدِّرات مخصصة هي أنه يمكنك استخدامها مع أدوات ضبط المعلمات الفائقة في scikit-learn مثل GridSearchCV و RandomizedSearchCV. لجعل مُقدِّرك متوافقًا مع هذه الأدوات، تحتاج إلى التأكد من أن معاملاته قابلة للوصول والتعديل. عادةً ما يتم التعامل مع هذا تلقائيًا بفضل فئة `BaseEstimator`.
دعنا نوضح هذا باستخدام FeatureScaler. سنستخدم GridSearchCV للعثور على عامل القياس الأمثل:
from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import Pipeline
import numpy as np
# Create a pipeline with the FeatureScaler
pipe = Pipeline([('scaler', FeatureScaler())])
# Define the parameter grid
param_grid = {'scaler__factor': [0.5, 1.0, 1.5, 2.0]}
# Create a GridSearchCV object
grid_search = GridSearchCV(pipe, param_grid, cv=3, scoring='r2') # Using R^2 as an example scoring metric.
# Generate some sample data
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]])
y = np.array([2, 4, 6, 8, 10])
# Fit the grid search
grid_search.fit(X, y)
# Print the best parameters and score
print("Best parameters:", grid_search.best_params_)
print("Best score:", grid_search.best_score_)
في هذا المثال، نحدد شبكة معاملات تحدد قيم المعامل factor التي سيتم البحث فيها. سيقوم GridSearchCV بعد ذلك بتقييم خط الأنابيب مع كل مجموعة من المعاملات وإعادة أفضل مجموعة أداءً. لاحظ اصطلاح التسمية `scaler__factor` للوصول إلى المعلمات داخل مرحلة في خط الأنابيب.
تقنيات متقدمة: التعامل مع أنواع البيانات المعقدة والقيم المفقودة
يمكن أيضًا استخدام المُقدِّرات المخصصة للتعامل مع أنواع البيانات المعقدة والقيم المفقودة. على سبيل المثال، قد ترغب في إنشاء محوّل يقوم بتعويض القيم المفقودة باستخدام استراتيجية خاصة بالمجال أو يقوم بتحويل الميزات الفئوية إلى تمثيلات رقمية. المفتاح هو النظر بعناية في المتطلبات المحددة لبياناتك وتنفيذ المنطق المناسب في دالتي fit و transform.
لنأخذ مثالاً على محوّل مخصص يقوم بتعويض القيم المفقودة باستخدام الوسيط (median):
from sklearn.base import BaseEstimator, TransformerMixin
import numpy as np
class MedianImputer(BaseEstimator, TransformerMixin):
def __init__(self):
self.median_ = None
def fit(self, X, y=None):
# Calculate the median for each column
self.median_ = np.nanmedian(X, axis=0)
return self
def transform(self, X):
# Impute missing values with the median
X_imputed = np.where(np.isnan(X), self.median_, X)
return X_imputed
في هذا المثال، تحسب دالة fit الوسيط لكل عمود في بيانات الإدخال، متجاهلة القيم المفقودة (np.nan). ثم تقوم دالة transform باستبدال أي قيم مفقودة في بيانات الإدخال بالوسيط المقابل.
إليك كيفية استخدامه:
# Example Usage
X = np.array([[1, 2, np.nan], [3, np.nan, 5], [np.nan, 4, 6]])
# Create a MedianImputer
imputer = MedianImputer()
# Fit the imputer
imputer.fit(X)
# Transform the data
X_imputed = imputer.transform(X)
print(X_imputed)
# Output:
# [[1. 2. 5.5]
# [3. 4. 5. ]
# [2. 4. 6. ]]
أمثلة من العالم الواقعي وحالات الاستخدام
دعنا نستكشف بعض الأمثلة الواقعية حيث يمكن أن تكون المُقدِّرات المخصصة مفيدة بشكل خاص:
- هندسة الميزات في السلاسل الزمنية: قد ترغب في إنشاء محوّل مخصص يستخرج ميزات من بيانات السلاسل الزمنية، مثل الإحصاءات المتحركة (rolling statistics) أو القيم المتأخرة (lagged values). على سبيل المثال، في الأسواق المالية، يمكنك إنشاء مُقدِّر يحسب المتوسط المتحرك والانحراف المعياري لأسعار الأسهم على مدى نافذة زمنية محددة. يمكن بعد ذلك استخدام هذا المُقدِّر في خط أنابيب للتنبؤ بأسعار الأسهم المستقبلية. يمكن أن يكون حجم النافذة معلمة فائقة يتم ضبطها بواسطة `GridSearchCV`.
- معالجة اللغات الطبيعية (NLP): يمكنك إنشاء محوّل مخصص يقوم بتنظيف النص أو استخراج الميزات باستخدام تقنيات غير متوفرة مباشرة في scikit-learn. على سبيل المثال، قد ترغب في تنفيذ أداة تجذير (stemmer) أو أداة تحليل صرفي (lemmatizer) مخصصة للغة أو مجال معين. يمكنك أيضًا دمج مكتبات خارجية مثل NLTK أو spaCy داخل مُقدِّرك المخصص.
- معالجة الصور: قد ترغب في إنشاء محوّل مخصص يطبق عمليات معالجة صور محددة، مثل الترشيح (filtering) أو كشف الحواف (edge detection)، قبل إدخال الصور في نموذج تعلم الآلة. قد يتضمن ذلك التكامل مع مكتبات مثل OpenCV أو scikit-image. على سبيل المثال، قد يقوم مُقدِّر بتطبيع سطوع وتباين الصور الطبية قبل تدريب نموذج لاكتشاف الأورام.
- أنظمة التوصية: يمكنك بناء مُقدِّر مخصص ينفذ خوارزميات الترشيح التعاوني (collaborative filtering)، مثل تحليل المصفوفات (matrix factorization)، لإنشاء توصيات مخصصة. قد يتضمن ذلك التكامل مع مكتبات مثل Surprise أو implicit. على سبيل المثال، قد يستخدم نظام توصية الأفلام مُقدِّرًا مخصصًا للتنبؤ بتقييمات المستخدمين بناءً على تفضيلاتهم السابقة وتقييمات المستخدمين الآخرين.
- تحليل البيانات الجغرافية المكانية: إنشاء محوّلات مخصصة للعمل مع بيانات المواقع. قد يتضمن ذلك حساب المسافات بين النقاط، أو إجراء عمليات ربط مكاني، أو استخراج ميزات من الأشكال الجغرافية. على سبيل المثال، يمكنك حساب مسافة كل عميل من أقرب موقع متجر لإبلاغ استراتيجيات التسويق.
أفضل الممارسات لإنشاء المُقدِّرات المخصصة
لضمان أن تكون مُقدِّراتك المخصصة قوية وقابلة للصيانة ومتوافقة مع scikit-learn، اتبع أفضل الممارسات التالية:
- الوراثة من
BaseEstimatorوالـ Mixin المناسب: يوفر هذا وظائف أساسية ويضمن التوافق مع واجهة برمجة تطبيقات scikit-learn. - تنفيذ
__init__وfitوtransform(أوpredict): هذه الدوال هي جوهر مُقدِّرك. - التحقق من صحة معاملات الإدخال: استخدم
sklearn.utils.validationللتحقق من صحة المعاملات التي يتم تمريرها إلى مُقدِّرك. - التعامل مع القيم المفقودة بشكل مناسب: قرر كيف يجب أن يتعامل مُقدِّرك مع القيم المفقودة ونفذ المنطق المناسب.
- توثيق الكود الخاص بك: قدم توثيقًا واضحًا وموجزًا لمُقدِّرك، بما في ذلك غرضه ومعاملاته واستخدامه. استخدم سلاسل التوثيق (docstrings) التي تلتزم بأسلوب NumPy/SciPy للاتساق.
- اختبار الكود الخاص بك: استخدم
sklearn.utils.estimator_checksلاختبار مُقدِّرك مقابل مجموعة من الاختبارات الشائعة. أيضًا، اكتب اختبارات وحدة (unit tests) للتحقق من أن مُقدِّرك يعمل بشكل صحيح. - اتباع اصطلاحات Scikit-learn: التزم بأسلوب الترميز واصطلاحات واجهة برمجة التطبيقات الخاصة بـ scikit-learn لضمان الاتساق وقابلية الصيانة.
- النظر في استخدام المُزخرفات (Decorators): عند الاقتضاء، استخدم مُزخرفات مثل
@validate_argumentsمن مكتبات مثل `typing-extensions` لتبسيط التحقق من صحة المعاملات.
الخلاصة
يسمح لك إنشاء مُقدِّرات مخصصة في scikit-learn بتوسيع وظائفها وتنفيذ خوارزميات تعلم الآلة الخاصة بك. من خلال اتباع الإرشادات وأفضل الممارسات الموضحة في هذا الدليل، يمكنك إنشاء مُقدِّرات قوية وقابلة للصيانة وإعادة الاستخدام تتكامل بسلاسة مع نظام scikit-learn البيئي. سواء كنت تنفذ خوارزميات جديدة، أو تخصص خوارزميات موجودة، أو تتكامل مع مكتبات خارجية، فإن المُقدِّرات المخصصة توفر أداة قوية لمعالجة مشاكل تعلم الآلة المعقدة.
تذكر اختبار وتوثيق مُقدِّراتك المخصصة بدقة لضمان جودتها وسهولة استخدامها. مع فهم قوي لواجهة برمجة تطبيقات scikit-learn وقليل من الإبداع، يمكنك الاستفادة من المُقدِّرات المخصصة لبناء حلول تعلم آلة متطورة مصممة خصيصًا لاحتياجاتك. بالتوفيق!