در این مطلب، روش ساخت مدل سفارشی در سایکیت لرن (Scikit-Learn) همراه با ارائه دو مثال، مورد بررسی قرار گرفته است. برای آگاهی از دیگر کتابخانه‌های «هوش مصنوعی» (Artificial Intelligence) و علم داده پایتون، مطالعه مطالب زیر توصیه می‌شود.

«سایکیت‌لرن» (Scikit-Learn) یک کتابخانه بسیار عالی «زبان برنامه‌نویسی پایتون» (Python Programming Language) برای «علم داده» (Data Science) و «یادگیری ماشین» (Machine Learning) است. این کتابخانه به کاربران این امکان را می‌دهد تا اغلب مدل‌های یادگیری ماشین را تنها با چند خط کد برازش کنند. اگرچه، این کتابخانه نیز کامل نیست و همه مدل‌ها را ندارد. برای مثال، مدل «رگرسیون ترتیبی» (Ordinal Regression) و همچنین، برخی از قابلیت‌های «یادگیری عمیق» (Deep Learning) در این کتابخانه موجود نیست.

اما نکته جالب توجه آن است که سایکیت‌لرن فقط برای مدل‌سازی نیست. بلکه، ابزارهای بسیار مناسبی در آن برای ساده‌سازی ساخت مدل وجود دارد که از جمله آن‌ها می‌توان به GridSearchCV و Pipeline اشاره کرد. این ابزارها بسیار ارزشمند هستند، ولی متأسفانه فقط با مدل‌های سایکیت‌لرن کار می‌کنند. اما جای نگرانی برای این مورد وجود ندارد، زیرا اگر مدل مورد نظر کارشناس در سایکیت‌لرن وجود نداشته باشد، می‌تواند مدل سازگار با سایکیت‌لرن را بسازد. در این مطلب، روش ساخت مدل سفارشی در سایکیت لرن (Scikit-Learn) آموزش داده شده است.

در این راستا، یک مدل که به صورت پیش‌فرض در سایکیت‌لرن وجود ندارد، ساخته می‌شود. در ادامه، طی مثالی از روش «خوشه‌بندی» (Clustering) «کِی-نزدیک‌ترین همسایگی» (K-Means) برای انجام «یادگیری انتقال» (Transfer Learning) در Pipeline، استفاده خواهد شد. شایان توجه است که در این مطلب، فرض شده که مخاطب با مفاهیم «برنامه‌نویسی شی‌گرا» (Object-Oriented Programming | OOP) آشنا است و می‌داند که چگونه از کلیدواژه class در پایتون استفاده کند.

قالب سایکیت‌لرن

یکی ویژگی‌های مثبت و قابل توجه «سایکیت‌لرن» (Scikit-Learn) استحکام بسیار بالای آن است. برازش یک نوع مدل، اسما مشابه با برازش هر نوع مدل دیگری است. از همین رو، برازش مدل در سایکیت‌لرن به سادگی وارد کردن دستور زیر است.

model = MyModel(parameters)
model.fit(X, y)

اکنون، می‌توان مدل را تحلیل کرد. این کار را احتمالا می‌توان با کمک متدهای predict()‎. و score()‎. انجام داد. در حقیقت، پنج متد وجود دارد که هر تخمین‌گر سایکیت‌لرن (Scikit-Learn) از آن بهره می‌برد. این متدها در ادامه بیان شده‌اند:

  • fit()‎‎.
  • predict()‎.
  • score()‎.
  • set_params()‎.
  • get_params()‎.

ساخت مدل سفارشی در سایکیت لرن (Scikit-Learn)

به منظور سازگاری داشتن مدل با سایکیت‌لرن، مدل باید برخی از موارد را از mixin به ارث ببرد. mixin یک کلاس است که هیچ وقت به خودی خود کار نمی‌کند، در عوض، حاوی متدهایی است که می‌توان آن‌ها را با استفاده از ارث‌بری به کلاس کنونی اضافه کرد. Scikit-Learn گزینه‌های گوناگونی را برای انواع عمومی مدل‌ها در اختیار قرار می‌دهد که از این جمله می‌توان به TransformerMixin ،ClusterMixin ،ClassifierMixin ،RegressorMixin و گزینه‌های متعدد دیگر اشاره کرد. در ادامه، ابتدا یک مثال ساده ارائه شده است. سپس، مثال دیگری با خوشه‌بندی مورد بررسی قرار گرفته است.

مثال ۱: مدل Null

مدل Null که گاهی به آن مدل «مبنا» (Baseline) نیز گفته می‌شود، مدلی است که در آن کاربر هیچ اطلاعاتی به جز حدس‌های تصادفی ندارد. برای مثال، مدل مبنا برای مسئله رگرسیون، فقط میانگین y از داده‌های آموزش را دریافت و از آن برای پیش‌بینی استفاده می‌کند. در دسته‌بندی، مدل مبنا تنها کلاس اکثریت را برای هر پیش‌بینی می‌گیرد. برای مثال، اگر هدف پیش‌بینی آن باشد که آیا یک نفر در قرعه‌کشی بخت آزمایی برنده می‌شود یا نه، مدل Null همیشه پیش‌بینی می‌کند که کاربر می‌بازد، زیرا این محتمل‌ترین خروجی است و البته خیلی هم از واقعیت متفاوت نیست.

ساخت مدل سفارشی در سایکیت لرن -- راهنمای کاربردی

مدل Null برای گفتن اینکه مدل کنونی چقدر خوب کار می‌کند مفید است. گذشته از همه این موارد، اگر مدلی خوب باشد، باید از مدل مبنا بهتر عمل کند. مدل Null به صورت توکار در سایکیت‌لرن وجود ندارد، اما پیاده‌سازی آن آسان است.

import numpy as np
from sklearn.base import RegressorMixin
class NullRegressor(RegressorMixin):
    def fit(self, X=None, y=None):
        # The prediction will always just be the mean of y
        self.y_bar_ = np.mean(y)
    def predict(self, X=None):
        # Give back the mean of y, in the same
        # length as the number of X observations
        return np.ones(X.shape[0]) * self.y_bar_

کد بالا ساده است و پس از نوشتن آن، می‌توان به صورت معمول اقدام کرد.

model = NullRegressor()
model.fit(X, y)
model.predict(X)

بخش مهم آن است که NullRegressor جدید با همه ابزارهای توکار Scikit-Learn مانند cross_val_score و GridSearchCV سازگار است.

مثال ۲: تنظیم خوشه‌ها با استفاده از جستجوی گرید

این مثال زاییده خلاقیت است و در پاسخ به این پرسش که آیا می‌توان مدل k-means را با استفاده از GridSearchCV و Pipeline تنظیم کرد یا خیر، ارائه شده است. پاسخ این پرسش، در اصل منفی است؛ مگر اینکه کاربر نیاز به استفاده از خوشه‌ها به عنوان انتقال دهنده برای پاس دادن به مدل «نظارت شده» (Supervised Model) داشته باشد که سایکیت‌لرن امکان این مورد را به صورت پیش‌فرض ندارد. اما این مورد نمی‌تواند مانع توقف کار شود؛ در بخش پیشین، چگونگی استفاده از سایکیت‌لرن برای ساخت مدل سفارشی بیان شد. در ادامه، روش انجام کاری که در این قسمت بیان شد، آموزش داده می‌شود. این کار، با ساخت پایپ‌لاین زیر آغاز می‌شود.

Pipeline([
    ("sc", StandardScaler()),
    ("km", KMeansSomehow()),
    ("lr", LogisticRegression()
])

در کد بالا، KMeansSomehow()‎ خوشه‌ای است که به عنوان «انتقال‌دهنده» (Transformer) استفاده می‌شود. به این معنا که، برچسب‌های خوشه «کدبندی شده به روش وان‌هات» (Onehot-Encoded) را به ماتریکس x الحاق می‌کند و سپس، به مدل انتقال می‌دهد. به منظور آنکه این روش کار کند، کار با تعریف یک کلاس که از TransformerMixin ارث‌بری دارد، انجام می‌شود. سپس، متدهای transform()‎ ،.fit()‎. و fit_transform()‎. به آن داده می‌شوند. اما برای آغاز کار، مقدمات اولیه به صورت زیر فراهم می‌شود.

from sklearn.base import TransformerMixin
from sklearn.cluster import KMeans
class KMeansTransformer(TransformerMixin):
    def __init__(self, *args, **args):
        self.model = KMeans(*args, **args)

هدف از self.model، شامل شدن مدل خوشه‌بندی اصلی است. اما پرسشی که ممکن است در این وهله مطرح شود این است که args‎* و kwargs** چه هستند؟ می‌توان گفت که این دو مورد، میان‌برهایی برای برنامه‌نویس‌ها محسوب می‌شوند. این دو مورد، همه آرگومان‌های دیگری که کاربر به init__()‎__ پاس می‌دهند را ثبت می‌کنند و به KMeans()‎ پاس می‌دهند. در اینجا، هر چیزی که به KMeansTransformer پاس داده شود، به KMeans نیز پاس داده می‌شود. در ادامه، متد برازش مناسبی به کد اضافه می‌شود.

from self.preprocessing import OneHotEncoder
class KMeansTransformer(TransformerMixin):
    def __init__(self, *args, **args):
        self.model = KMeans(*args, **args)
    def fit(self, X):
        self.X = X
        self.model.fit(X)
    def transform(self, X):
        # Need to reshape into a column vector in order to use
        # the onehot encoder.
        cl = self.model.predict(X).reshape(-1, 1)
        
        self.oh = OneHotEncoder(
            categories="auto", 
            sparse=False,
            drop="first"
        )
        cl_matrix = self.oh.fit_transform(cl)      
 
        return np.hstack([self.X, cl_matrix])
    def fit_transform(self, X, y=None):
        self.fit(X)
        return self.transform(X)

اکنون می‌توان از KmeansTransformer مانند یک انتقال‌دهنده توکار سایکیت‌لرن استفاده کرد.

from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import make_blobs
X, y = make_blobs(
    n_samples=100,
    n_features=2,
    centers=3
)
pipe = Pipeline([
    ("sc", StandardScaler()),
    ("km", KMeansTransformer()),
    ("lr", LogisticRegression(penalty="none", solver="lbfgs"))
])
pipe.fit(X, y)
pipe.score(X, y)
# ==> 1.0

در مثال‌های جهان واقعی، کاربر ممکن است از GridSearchCV برای پیدا کردن تعداد بهینه‌ای از خوشه‌ها برای انتقال دادن به «رگرسیون لجستیک» (Logistic Regression) استفاده کند.

اگر نوشته بالا برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

بر اساس رای 1 نفر
آیا این مطلب برای شما مفید بود؟
شما قبلا رای داده‌اید!
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.

«الهام حصارکی»، فارغ‌التحصیل مقطع کارشناسی ارشد مهندسی فناوری اطلاعات، گرایش سیستم‌های اطلاعات مدیریت است. او در زمینه هوش مصنوعی و داده‌کاوی، به ویژه تحلیل شبکه‌های اجتماعی، فعالیت می‌کند.

نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *