Scikit-learn چیست؟ آموزش کامل Machine Learning با پایتون
در این آموزش عملی با Scikit-learn، آمادهسازی داده، Pipeline، Cross-validation و معیارهای ارزیابی آشنا میشوید و یک مدل کامل Machine Learning را با پایتون میسازید و ذخیره میکنید.
Scikit-learn یا سایکیتلرن یکی از پرکاربردترین کتابخانههای پایتون برای یادگیری ماشین کلاسیک است. با این کتابخانه میتوان مدلهای طبقهبندی، رگرسیون و خوشهبندی ساخت، دادهها را آماده کرد، مدلها را ارزیابی کرد و بهترین Hyperparameterها را پیدا کرد.
برخلاف PyTorch و TensorFlow که بیشتر برای ساخت و آموزش شبکههای عصبی و مدلهای Deep Learning استفاده میشوند، Scikit-learn روی الگوریتمهای کلاسیک یادگیری ماشین و گردش کار استاندارد تحلیل داده تمرکز دارد.
با Scikit-learn میتوانید پروژههایی مانند موارد زیر بسازید:
- طبقهبندی پیام و متن
- پیشبینی دسته یک محصول
- بخشبندی مشتریان
- تشخیص داده غیرعادی
- پیشبینی مقدار عددی
- تحلیل رفتار کاربران
- ساخت سیستم امتیازدهی
- طبقهبندی تیکتهای پشتیبانی
- پیشبینی ترک سرویس
- خوشهبندی اسناد
- کاهش ابعاد داده
- استخراج Feature از متن
- مقایسه چند الگوریتم
- ساخت Baseline برای پروژه هوش مصنوعی
در این آموزش، مفاهیم اصلی Scikit-learn را از ابتدا بررسی میکنیم و سپس یک پروژه کامل طبقهبندی میسازیم.
این پروژه شامل مراحل زیر است:
- دریافت و بررسی داده
- تقسیم داده به Train و Test
- ساخت Pipeline
- استانداردسازی Featureها
- آموزش مدل Logistic Regression
- محاسبه Accuracy، Precision، Recall و F1
- ساخت Confusion Matrix
- اجرای Cross-validation
- تنظیم Hyperparameter
- مقایسه چند مدل
- ذخیره و بارگذاری مدل
- پیشبینی نمونه جدید
- اتصال نتیجه مدل به API هوش مصنوعی درواره
Scikit-learn چیست؟
Scikit-learn یک کتابخانه متنباز یادگیری ماشین برای Python است که از یادگیری نظارتشده و بدون نظارت پشتیبانی میکند.
طبق مستندات رسمی Scikit-learn، این کتابخانه ابزارهایی برای موارد زیر ارائه میدهد:
- Model Fitting
- Data Preprocessing
- Model Selection
- Model Evaluation
- Supervised Learning
- Unsupervised Learning
Scikit-learn روی کتابخانههای علمی پایتون مانند NumPy و SciPy ساخته شده و با Pandas و Matplotlib نیز بهخوبی کار میکند.
Scikit-learn چگونه تلفظ میشود؟
Scikit-learn معمولاً به شکل «سایکیتلِرن» تلفظ میشود.
در فارسی شکلهای زیر رایجاند:
- سایکیتلرن
- سایکیت لرن
- Scikit-learn
- sklearn
نام پکیجی که نصب میکنید:
scikit-learn
اما نامی که در کد Import میشود:
import sklearn
این تفاوت یکی از نکاتی است که کاربران تازهکار را سردرگم میکند.
روش صحیح نصب:
pip install scikit-learn
روش صحیح Import:
import sklearn
Machine Learning چیست؟
یادگیری ماشین یا Machine Learning روشی است که در آن برنامه بهجای دریافت مجموعهای کامل از قوانین دستی، الگوها را از داده یاد میگیرد.
در برنامهنویسی معمولی:
Data + Rules → Output
در یادگیری ماشین:
Data + Expected Outputs → Trained Model
پس از آموزش:
New Data + Trained Model → Prediction
برای مثال، بهجای نوشتن صدها قانون برای تشخیص دسته یک محصول، میتوان مجموعهای از نمونههای برچسبخورده را به مدل داد تا الگوهای مربوط به هر دسته را یاد بگیرد.
انواع اصلی یادگیری ماشین
یادگیری نظارتشده
در Supervised Learning، داده دارای Label یا مقدار هدف است.
مثال:
| Featureها | Target |
|---|---|
| ویژگیهای یک نمونه | کلاس نمونه |
| متن پیام | دسته پیام |
| اطلاعات خانه | قیمت |
| رفتار کاربر | ترک یا ادامه استفاده |
دو مسئله مهم یادگیری نظارتشده:
- Classification
- Regression
Classification
در Classification خروجی یک کلاس است.
نمونهها:
- مثبت یا منفی
- دسته A، B یا C
- تیکت فنی یا فروش
- پیام عادی یا نامرتبط
Regression
در Regression خروجی یک مقدار عددی پیوسته است.
نمونهها:
- زمان انجام کار
- میزان مصرف
- تقاضای روزانه
- دمای آینده
- مقدار فروش
پیشبینی مدل نباید بدون بررسی بهعنوان واقعیت قطعی استفاده شود.
یادگیری بدون نظارت
در Unsupervised Learning داده Label ندارد و مدل بهدنبال ساختار یا گروههای پنهان میگردد.
کاربردهای رایج:
- Clustering
- کاهش ابعاد
- شناسایی ساختار داده
- گروهبندی نمونههای مشابه
- تشخیص نمونههای غیرعادی
خوشهبندی
در Clustering مدل نمونههای مشابه را در گروههایی قرار میدهد.
الگوریتمهای رایج:
- K-Means
- DBSCAN
- Agglomerative Clustering
شماره خوشه بهخودیخود معنای تجاری ندارد. پس از ساخت خوشهها باید ویژگیهای هر گروه را تحلیل و تفسیر کنید.
Scikit-learn برای چه پروژههایی مناسب است؟
Scikit-learn برای دادههای جدولی، مسئلههای طبقهبندی و رگرسیون، تحلیل متن کلاسیک و ساخت Baseline بسیار مناسب است.
موارد مناسب
- داده جدولی
- تعداد Feature محدود یا متوسط
- دیتاست کوچک یا متوسط
- مدلهای قابل تفسیرتر
- آزمایش سریع چند الگوریتم
- Feature Engineering
- Cross-validation
- ساخت Pipeline
- تنظیم Hyperparameter
- پروژههای آموزشی
- ساخت Baseline
مواردی که ابزار دیگری ممکن است مناسبتر باشد
- آموزش مدل زبانی بزرگ
- آموزش شبکه عصبی بسیار عمیق
- تولید تصویر
- تولید ویدئو
- مدلهای چندوجهی بزرگ
- آموزش توزیعشده سنگین
- پردازش مستقیم حجم عظیم داده بدون معماری مناسب
برای شبکههای عصبی معمولاً از PyTorch، TensorFlow یا Keras استفاده میشود. برای استفاده از مدلهای مولد آماده نیز API میتواند انتخاب سادهتری باشد.
مهمترین بخشهای Scikit-learn
| بخش | کاربرد |
|---|---|
sklearn.model_selection | تقسیم داده، Cross-validation و جستوجوی پارامتر |
sklearn.preprocessing | Scaling، Encoding و آمادهسازی داده |
sklearn.pipeline | اتصال مراحل Preprocessing و Model |
sklearn.compose | پردازش متفاوت ستونها |
sklearn.metrics | معیارهای ارزیابی |
sklearn.linear_model | مدلهای خطی |
sklearn.ensemble | Random Forest و مدلهای Ensemble |
sklearn.cluster | خوشهبندی |
sklearn.decomposition | کاهش ابعاد |
sklearn.feature_extraction | استخراج Feature از متن |
sklearn.impute | مدیریت دادههای Missing |
sklearn.datasets | دیتاستهای آموزشی |
الگوی مشترک API در Scikit-learn
یکی از مزیتهای مهم Scikit-learn، API نسبتاً یکدست مدلها است.
تقریباً تمام Estimatorها از الگوی زیر استفاده میکنند:
model.fit(
x_train,
y_train,
)
predictions = model.predict(
x_test
)
برخی مدلها احتمال کلاسها را نیز برمیگردانند:
probabilities = (
model.predict_proba(
x_test
)
)
Transformerها از این متدها استفاده میکنند:
transformer.fit(x_train)
transformed_train = (
transformer.transform(
x_train
)
)
یا بهصورت ترکیبی:
transformed_train = (
transformer.fit_transform(
x_train
)
)
Estimator، Transformer و Predictor
Estimator
هر شیئی که از داده یاد میگیرد و متد fit دارد:
estimator.fit(x, y)
Transformer
داده را تغییر میدهد و متد transform دارد:
transformer.transform(x)
مثال:
- StandardScaler
- OneHotEncoder
- SimpleImputer
- PCA
- TfidfVectorizer
Predictor
پس از آموزش، پیشبینی تولید میکند:
model.predict(x)
Pipeline میتواند چند Transformer را به یک Predictor متصل کند.
پیشنیازهای آموزش
برای اجرای پروژه به موارد زیر نیاز دارید:
- Python نسخه سازگار
- pip
- آشنایی مقدماتی با Python
- آشنایی مقدماتی با NumPy و Pandas
- ویرایشگر کد مانند VS Code
برای مثال اصلی به GPU نیاز ندارید. الگوریتمهای استفادهشده روی CPU اجرا میشوند.
مرحله اول: ساخت پروژه
mkdir sklearn-wine-classifier
cd sklearn-wine-classifier
ساخت محیط مجازی در Linux و macOS:
python3 -m venv .venv
source .venv/bin/activate
در Windows PowerShell:
python -m venv .venv
.venv\Scripts\Activate.ps1
مرحله دوم: نصب کتابخانهها
pip install \
scikit-learn \
pandas \
numpy \
matplotlib \
joblib
فایل requirements.txt:
scikit-learn
pandas
numpy
matplotlib
joblib
نصب:
pip install -r requirements.txt
بررسی نسخه:
import sklearn
print(
sklearn.__version__
)
پروژه عملی: طبقهبندی نمونههای Wine
Scikit-learn چند دیتاست کوچک آموزشی دارد. در این پروژه از دیتاست Wine استفاده میکنیم.
هر نمونه دارای مجموعهای از Featureهای عددی است و Target مشخص میکند نمونه به کدامیک از سه کلاس تعلق دارد.
هدف این پروژه یادگیری Workflow استاندارد است، نه ساخت سامانه تشخیص محصول برای استفاده تجاری.
مرحله سوم: دریافت Dataset
فایل explore_data.py:
import pandas as pd
from sklearn.datasets import load_wine
wine = load_wine(
as_frame=True
)
data_frame = wine.frame
print(
data_frame.head()
)
print(
data_frame.shape
)
print(
data_frame.dtypes
)
print(
data_frame.isna().sum()
)
print(
data_frame["target"]
.value_counts()
.sort_index()
)
print(
wine.target_names
)
اجرا:
python explore_data.py
با as_frame=True دادهها به DataFrame و Series تبدیل میشوند.
Feature و Target چیست؟
Featureها ورودی مدل هستند:
x = data_frame.drop(
columns=["target"]
)
Target خروجی مورد انتظار است:
y = data_frame["target"]
ساختار کلی:
X = Feature Matrix
y = Target Vector
بهصورت معمول:
X shape = تعداد نمونه × تعداد Feature
y shape = تعداد نمونه
بررسی:
print(x.shape)
print(y.shape)
مرحله چهارم: تقسیم Train و Test
نباید مدل را روی همان دادهای ارزیابی کنیم که با آن آموزش دیده است.
from sklearn.model_selection import (
train_test_split,
)
x_train, x_test, y_train, y_test = (
train_test_split(
x,
y,
test_size=0.2,
random_state=42,
stratify=y,
)
)
پارامترها:
test_size
بیست درصد داده برای Test:
test_size=0.2
random_state
تقسیم داده را قابل تکرار میکند:
random_state=42
stratify
نسبت کلاسها را در Train و Test تا حد امکان حفظ میکند:
stratify=y
برای Classification نامتوازن، استفاده از Stratification اهمیت زیادی دارد.
چرا Test Data نباید در آموزش استفاده شود؟
اگر مدل، Scaler یا Feature Selection را روی کل داده Fit کنید، اطلاعات Test به فرایند آموزش وارد میشود. این مشکل Data Leakage نام دارد.
روش اشتباه:
scaler.fit(x)
x_scaled = scaler.transform(x)
x_train, x_test = train_test_split(
x_scaled
)
روش بهتر:
x_train, x_test, y_train, y_test = (
train_test_split(
x,
y,
test_size=0.2,
random_state=42,
stratify=y,
)
)
scaler.fit(x_train)
x_train_scaled = scaler.transform(
x_train
)
x_test_scaled = scaler.transform(
x_test
)
روش مطمئنتر، قراردادن Scaler و مدل داخل Pipeline است.
StandardScaler چیست؟
Featureهای دیتاست ممکن است مقیاس متفاوتی داشته باشند.
برای مثال:
Feature A: بین 0 و 1
Feature B: بین 100 و 10000
StandardScaler هر Feature را با استفاده از میانگین و انحراف معیار داده Train استاندارد میکند.
مفهوم محاسبه:
مقدار استانداردشده =
(مقدار - میانگین) / انحراف معیار
در Ghost بهتر است فرمولها بهصورت Code Block نوشته شوند تا نمایش آنها در قالبهای مختلف پایدار بماند.
Pipeline چیست؟
Pipeline چند مرحله آمادهسازی و مدل را در یک شیء قرار میدهد.
from sklearn.linear_model import (
LogisticRegression,
)
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import (
StandardScaler,
)
pipeline = Pipeline(
steps=[
(
"scaler",
StandardScaler(),
),
(
"classifier",
LogisticRegression(
max_iter=2000,
random_state=42,
),
),
]
)
طبق مستندات رسمی Pipeline، مراحل میانی باید Transformer باشند و مرحله نهایی میتواند یک Predictor باشد.
Pipeline چند مزیت مهم دارد:
- جلوگیری از Data Leakage
- کد کوتاهتر
- پردازش یکسان Train و Test
- ذخیره Preprocessing همراه مدل
- استفاده ساده در Cross-validation
- تنظیم Hyperparameter تمام مراحل
- کاهش خطا در Inference
مرحله پنجم: آموزش مدل
pipeline.fit(
x_train,
y_train,
)
این دستور بهترتیب کارهای زیر را انجام میدهد:
- StandardScaler را روی
x_trainFit میکند. - داده Train را Transform میکند.
- Logistic Regression را آموزش میدهد.
هنگام پیشبینی:
predictions = pipeline.predict(
x_test
)
Pipeline ابتدا داده Test را با Scaler آموزشدیده Transform و سپس پیشبینی میکند.
Logistic Regression چیست؟
با وجود نام Regression، Logistic Regression یکی از الگوریتمهای رایج Classification است.
مزایا:
- سرعت مناسب
- Baseline قدرتمند
- تفسیرپذیری نسبی
- مناسب بسیاری از دادههای جدولی
- امکان تولید احتمال کلاس
- پشتیبانی از طبقهبندی چندکلاسه
Logistic Regression فرضهای مشخصی دارد و برای همه مسئلهها بهترین مدل نیست. به همین دلیل باید چند الگوریتم با روش ارزیابی یکسان مقایسه شوند.
مرحله ششم: ارزیابی مدل
from sklearn.metrics import (
accuracy_score,
classification_report,
confusion_matrix,
)
predictions = pipeline.predict(
x_test
)
accuracy = accuracy_score(
y_test,
predictions,
)
print(
"Accuracy:",
round(accuracy, 4),
)
print(
classification_report(
y_test,
predictions,
target_names=wine.target_names,
)
)
print(
confusion_matrix(
y_test,
predictions,
)
)
Accuracy چیست؟
Accuracy نسبت پیشبینیهای صحیح به کل نمونهها است:
Accuracy =
تعداد پیشبینی صحیح / تعداد کل نمونهها
Accuracy برای داده متوازن مفید است، اما در داده نامتوازن کافی نیست.
Precision چیست؟
Precision پاسخ میدهد:
از میان نمونههایی که مدل یک کلاس تشخیص داده،
چه تعداد واقعاً متعلق به همان کلاس بودهاند؟
Precision زمانی مهمتر میشود که False Positive هزینه یا اثر بیشتری داشته باشد.
Recall چیست؟
Recall پاسخ میدهد:
از میان تمام نمونههای واقعی یک کلاس،
مدل چه تعداد را پیدا کرده است؟
Recall زمانی اهمیت بیشتری دارد که از دستدادن نمونههای واقعی مهم باشد.
F1 Score چیست؟
F1 میانگین هارمونیک Precision و Recall است.
F1 =
2 × Precision × Recall
/
(Precision + Recall)
F1 در شرایطی مفید است که تعادل میان Precision و Recall اهمیت دارد.
Macro، Micro و Weighted Average
Macro Average
معیار هر کلاس جداگانه محاسبه و سپس میانگین گرفته میشود. همه کلاسها وزن یکسان دارند.
Weighted Average
میانگین بر اساس تعداد نمونههای هر کلاس وزندهی میشود.
Micro Average
ابتدا مجموع True Positive، False Positive و False Negative همه کلاسها محاسبه و سپس معیار ساخته میشود.
در داده نامتوازن، بررسی Macro F1 در کنار Accuracy میتواند تصویر کاملتری ارائه دهد.
Confusion Matrix چیست؟
Confusion Matrix تعداد پیشبینیهای درست و اشتباه میان کلاسها را نشان میدهد.
confusion = confusion_matrix(
y_test,
predictions,
)
print(confusion)
هر سطر معمولاً کلاس واقعی و هر ستون کلاس پیشبینیشده را نشان میدهد.
نمایش نموداری:
import matplotlib.pyplot as plt
from sklearn.metrics import (
ConfusionMatrixDisplay,
)
ConfusionMatrixDisplay.from_predictions(
y_test,
predictions,
display_labels=wine.target_names,
cmap="Blues",
)
plt.title(
"Wine Classification"
)
plt.tight_layout()
plt.show()
احتمال پیشبینی
اگر مدل از predict_proba پشتیبانی کند:
probabilities = (
pipeline.predict_proba(
x_test
)
)
print(
probabilities[:3]
)
برای هر نمونه، احتمال هر کلاس برگردانده میشود.
انتخاب بیشترین احتمال:
predicted_class = (
probabilities[0]
.argmax()
)
confidence = (
probabilities[0]
.max()
)
print(predicted_class)
print(confidence)
Probability مدل را نباید بدون بررسی Calibration بهعنوان اطمینان واقعی تفسیر کرد.
Cross-validation چیست؟
تقسیم Train و Test فقط یک تقسیم مشخص ایجاد میکند. ممکن است نتیجه مدل با تغییر نمونههای Train و Validation متفاوت باشد.
در Cross-validation داده Train به چند Fold تقسیم میشود. مدل چند بار آموزش میبیند و هر بار یک Fold برای Validation استفاده میشود.
نمونه پنجمرحلهای:
Fold 1 → Validation
Fold 2 تا 5 → Train
Fold 2 → Validation
بقیه → Train
تا پایان همه Foldها
طبق راهنمای Cross-validation در Scikit-learn، این روش محدودهای از عملکرد مورد انتظار مدل روی داده دیدهنشده ارائه میدهد.
اجرای Cross-validation
from sklearn.model_selection import (
StratifiedKFold,
cross_validate,
)
cross_validator = StratifiedKFold(
n_splits=5,
shuffle=True,
random_state=42,
)
scores = cross_validate(
estimator=pipeline,
X=x_train,
y=y_train,
cv=cross_validator,
scoring={
"accuracy": "accuracy",
"f1_macro": "f1_macro",
},
n_jobs=-1,
return_train_score=True,
)
print(
"Validation accuracy:",
scores["test_accuracy"],
)
print(
"Mean validation accuracy:",
scores[
"test_accuracy"
].mean(),
)
print(
"Mean validation F1:",
scores[
"test_f1_macro"
].mean(),
)
Pipeline باعث میشود Scaler در هر Fold فقط روی بخش Train همان Fold Fit شود.
چرا Preprocessing باید داخل Pipeline باشد؟
اگر قبل از Cross-validation روی کل داده Scaling انجام دهید، اطلاعات Foldهای Validation وارد Scaler میشود.
روش نامناسب:
x_scaled = scaler.fit_transform(x)
cross_validate(
model,
x_scaled,
y,
)
روش بهتر:
pipeline = Pipeline(
[
(
"scaler",
StandardScaler(),
),
(
"classifier",
LogisticRegression(),
),
]
)
cross_validate(
pipeline,
x,
y,
)
Hyperparameter چیست؟
پارامترهایی که مدل از داده یاد میگیرد، Model Parameter نام دارند.
برای Logistic Regression:
- Coefficientها
- Intercept
مقادیر تعیینشده پیش از آموزش Hyperparameter هستند:
- مقدار
C - نوع Penalty
- Solver
- حداکثر Iteration
Scikit-learn میتواند چند ترکیب Hyperparameter را با Cross-validation آزمایش کند.
GridSearchCV
from sklearn.model_selection import (
GridSearchCV,
)
parameter_grid = {
"classifier__C": [
0.01,
0.1,
1.0,
10.0,
100.0,
],
"classifier__class_weight": [
None,
"balanced",
],
}
grid_search = GridSearchCV(
estimator=pipeline,
param_grid=parameter_grid,
scoring="f1_macro",
cv=cross_validator,
n_jobs=-1,
refit=True,
verbose=1,
)
grid_search.fit(
x_train,
y_train,
)
print(
"Best parameters:",
grid_search.best_params_,
)
print(
"Best CV score:",
grid_search.best_score_,
)
best_model = (
grid_search.best_estimator_
)
در نام پارامتر:
classifier__C
دو Underline بین نام مرحله Pipeline و نام پارامتر قرار دارد:
step_name__parameter_name
RandomizedSearchCV
اگر تعداد ترکیبها زیاد باشد، Grid Search میتواند زمانبر شود. Randomized Search تعداد محدودی ترکیب را نمونهبرداری میکند.
from scipy.stats import loguniform
from sklearn.model_selection import (
RandomizedSearchCV,
)
parameter_distributions = {
"classifier__C": loguniform(
1e-3,
1e2,
),
}
random_search = RandomizedSearchCV(
estimator=pipeline,
param_distributions=(
parameter_distributions
),
n_iter=20,
scoring="f1_macro",
cv=cross_validator,
random_state=42,
n_jobs=-1,
)
random_search.fit(
x_train,
y_train,
)
در Randomized Search تعداد آزمایشها با n_iter کنترل میشود. مستندات RandomizedSearchCV نیز این روش را جستوجوی تعداد مشخصی از ترکیبهای پارامتر توضیح میدهد.
مقایسه چند الگوریتم
یک اشتباه رایج این است که توسعهدهنده مستقیماً سراغ مدل پیچیده برود. بهتر است چند Baseline را با Cross-validation یکسان مقایسه کنید.
from sklearn.ensemble import (
RandomForestClassifier,
)
from sklearn.linear_model import (
LogisticRegression,
)
from sklearn.neighbors import (
KNeighborsClassifier,
)
from sklearn.pipeline import (
make_pipeline,
)
from sklearn.preprocessing import (
StandardScaler,
)
from sklearn.svm import SVC
models = {
"logistic_regression": (
make_pipeline(
StandardScaler(),
LogisticRegression(
max_iter=2000,
random_state=42,
),
)
),
"svm": (
make_pipeline(
StandardScaler(),
SVC(),
)
),
"knn": (
make_pipeline(
StandardScaler(),
KNeighborsClassifier(),
)
),
"random_forest": (
RandomForestClassifier(
n_estimators=300,
random_state=42,
)
),
}
ارزیابی:
from sklearn.model_selection import (
cross_val_score,
)
for model_name, model in models.items():
model_scores = cross_val_score(
estimator=model,
X=x_train,
y=y_train,
cv=cross_validator,
scoring="f1_macro",
n_jobs=-1,
)
print(
model_name,
round(
model_scores.mean(),
4,
),
round(
model_scores.std(),
4,
),
)
بهترین میانگین بهتنهایی کافی نیست. موارد زیر را نیز بررسی کنید:
- انحراف معیار
- زمان آموزش
- زمان پیشبینی
- اندازه مدل
- تفسیرپذیری
- پایداری
- نیاز به Scaling
- رفتار روی داده واقعی
ColumnTransformer چیست؟
دادههای جدولی ممکن است هم ستون عددی و هم دستهای داشته باشند.
برای مثال:
| ستون | نوع |
|---|---|
| usage_count | عددی |
| account_age_days | عددی |
| plan | دستهای |
| channel | دستهای |
ستونهای عددی را میتوان Scale و ستونهای دستهای را One-hot Encode کرد.
from sklearn.compose import (
ColumnTransformer,
)
from sklearn.impute import (
SimpleImputer,
)
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import (
OneHotEncoder,
StandardScaler,
)
numeric_columns = [
"usage_count",
"account_age_days",
]
categorical_columns = [
"plan",
"channel",
]
numeric_pipeline = Pipeline(
steps=[
(
"imputer",
SimpleImputer(
strategy="median"
),
),
(
"scaler",
StandardScaler(),
),
]
)
categorical_pipeline = Pipeline(
steps=[
(
"imputer",
SimpleImputer(
strategy=(
"most_frequent"
)
),
),
(
"encoder",
OneHotEncoder(
handle_unknown="ignore"
),
),
]
)
preprocessor = ColumnTransformer(
transformers=[
(
"numeric",
numeric_pipeline,
numeric_columns,
),
(
"categorical",
categorical_pipeline,
categorical_columns,
),
]
)
مدل کامل:
full_pipeline = Pipeline(
steps=[
(
"preprocessor",
preprocessor,
),
(
"classifier",
LogisticRegression(
max_iter=2000
),
),
]
)
طبق مستندات ColumnTransformer، این ابزار اجازه میدهد Transformerهای متفاوت روی مجموعههای مختلف ستونها اجرا و خروجی آنها ترکیب شود.
OneHotEncoder چیست؟
فرض کنید ستون Plan این مقادیر را دارد:
basic
professional
enterprise
One-hot Encoding آنها را به Featureهای جدا تبدیل میکند:
plan_basic
plan_professional
plan_enterprise
گزینه زیر باعث میشود دسته جدید در زمان Inference خطا ایجاد نکند:
OneHotEncoder(
handle_unknown="ignore"
)
این گزینه دسته ناشناخته را به یک دسته جدید یادگرفتهشده تبدیل نمیکند؛ فقط مانع خطای مستقیم میشود.
مدیریت Missing Value
حذف همه ردیفهای دارای مقدار خالی همیشه مناسب نیست. میتوانید از Imputer استفاده کنید.
برای عدد:
SimpleImputer(
strategy="median"
)
برای دسته:
SimpleImputer(
strategy="most_frequent"
)
Imputer باید فقط روی Train Fit شود. قراردادن آن داخل Pipeline این موضوع را مدیریت میکند.
پروژه کامل Scikit-learn
فایل train_model.py:
from pathlib import Path
import joblib
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.datasets import load_wine
from sklearn.linear_model import (
LogisticRegression,
)
from sklearn.metrics import (
ConfusionMatrixDisplay,
accuracy_score,
classification_report,
)
from sklearn.model_selection import (
GridSearchCV,
StratifiedKFold,
cross_validate,
train_test_split,
)
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import (
StandardScaler,
)
RANDOM_STATE = 42
TEST_SIZE = 0.2
MODEL_PATH = Path(
"artifacts/wine_classifier.joblib"
)
CONFUSION_MATRIX_PATH = Path(
"artifacts/confusion_matrix.png"
)
def load_data():
wine = load_wine(
as_frame=True
)
x = wine.data.copy()
y = wine.target.copy()
return (
x,
y,
list(wine.target_names),
)
def build_pipeline():
return Pipeline(
steps=[
(
"scaler",
StandardScaler(),
),
(
"classifier",
LogisticRegression(
max_iter=3000,
random_state=(
RANDOM_STATE
),
),
),
]
)
def evaluate_cross_validation(
pipeline,
x_train,
y_train,
cross_validator,
):
scores = cross_validate(
estimator=pipeline,
X=x_train,
y=y_train,
cv=cross_validator,
scoring={
"accuracy": "accuracy",
"f1_macro": "f1_macro",
},
n_jobs=-1,
return_train_score=True,
)
print(
"CV accuracy mean:",
round(
scores[
"test_accuracy"
].mean(),
4,
),
)
print(
"CV accuracy std:",
round(
scores[
"test_accuracy"
].std(),
4,
),
)
print(
"CV macro F1 mean:",
round(
scores[
"test_f1_macro"
].mean(),
4,
),
)
def tune_model(
pipeline,
x_train,
y_train,
cross_validator,
):
parameter_grid = {
"classifier__C": [
0.01,
0.1,
1.0,
10.0,
100.0,
],
"classifier__class_weight": [
None,
"balanced",
],
}
search = GridSearchCV(
estimator=pipeline,
param_grid=parameter_grid,
scoring="f1_macro",
cv=cross_validator,
n_jobs=-1,
refit=True,
verbose=1,
)
search.fit(
x_train,
y_train,
)
print(
"Best parameters:",
search.best_params_,
)
print(
"Best CV macro F1:",
round(
search.best_score_,
4,
),
)
return search.best_estimator_
def evaluate_test_data(
model,
x_test,
y_test,
target_names,
):
predictions = model.predict(
x_test
)
accuracy = accuracy_score(
y_test,
predictions,
)
print(
"Test accuracy:",
round(
accuracy,
4,
),
)
print(
classification_report(
y_test,
predictions,
target_names=target_names,
digits=4,
)
)
ConfusionMatrixDisplay.from_predictions(
y_test,
predictions,
display_labels=target_names,
cmap="Blues",
)
plt.title(
"Wine Classifier"
)
plt.tight_layout()
plt.savefig(
CONFUSION_MATRIX_PATH,
dpi=160,
)
plt.close()
def predict_sample(
model,
sample: pd.DataFrame,
target_names: list[str],
):
predicted_id = int(
model.predict(
sample
)[0]
)
probabilities = (
model.predict_proba(
sample
)[0]
)
result = {
"predicted_class_id": (
predicted_id
),
"predicted_class_name": (
target_names[
predicted_id
]
),
"probabilities": {
target_names[index]: round(
float(probability),
4,
)
for index, probability
in enumerate(
probabilities
)
},
}
return result
def main():
MODEL_PATH.parent.mkdir(
parents=True,
exist_ok=True,
)
(
x,
y,
target_names,
) = load_data()
print(
"Dataset shape:",
x.shape,
)
print(
"Class counts:",
y.value_counts()
.sort_index()
.to_dict(),
)
(
x_train,
x_test,
y_train,
y_test,
) = train_test_split(
x,
y,
test_size=TEST_SIZE,
random_state=RANDOM_STATE,
stratify=y,
)
pipeline = build_pipeline()
cross_validator = (
StratifiedKFold(
n_splits=5,
shuffle=True,
random_state=(
RANDOM_STATE
),
)
)
evaluate_cross_validation(
pipeline=pipeline,
x_train=x_train,
y_train=y_train,
cross_validator=(
cross_validator
),
)
best_model = tune_model(
pipeline=pipeline,
x_train=x_train,
y_train=y_train,
cross_validator=(
cross_validator
),
)
evaluate_test_data(
model=best_model,
x_test=x_test,
y_test=y_test,
target_names=target_names,
)
joblib.dump(
best_model,
MODEL_PATH,
)
print(
"Model saved to:",
MODEL_PATH,
)
sample = x_test.iloc[
[0]
].copy()
result = predict_sample(
model=best_model,
sample=sample,
target_names=target_names,
)
print(
"Sample prediction:",
result,
)
if __name__ == "__main__":
main()
اجرا:
python train_model.py
خروجیهای پروژه:
artifacts/
├── wine_classifier.joblib
└── confusion_matrix.png
بارگذاری مدل ذخیرهشده
فایل predict.py:
from pathlib import Path
import joblib
import pandas as pd
MODEL_PATH = Path(
"artifacts/wine_classifier.joblib"
)
model = joblib.load(
MODEL_PATH
)
sample = pd.DataFrame(
[
{
"alcohol": 13.2,
"malic_acid": 1.8,
"ash": 2.4,
"alcalinity_of_ash": 18.5,
"magnesium": 100.0,
"total_phenols": 2.6,
"flavanoids": 2.8,
"nonflavanoid_phenols": 0.3,
"proanthocyanins": 1.8,
"color_intensity": 5.0,
"hue": 1.0,
"od280/od315_of_diluted_wines": 3.0,
"proline": 1000.0,
}
]
)
predicted_class = int(
model.predict(
sample
)[0]
)
probabilities = (
model.predict_proba(
sample
)[0]
)
print(
"Predicted class:",
predicted_class,
)
print(
"Probabilities:",
probabilities,
)
نام و ترتیب ستونها باید با داده زمان آموزش سازگار باشد.
ذخیره مدل با Joblib
import joblib
joblib.dump(
model,
"model.joblib",
)
بارگذاری:
model = joblib.load(
"model.joblib"
)
در فایل ذخیرهشده Pipeline نیز وجود دارد؛ بنابراین Scaler و مدل با هم بارگذاری میشوند.
طبق راهنمای Model Persistence در Scikit-learn، روش انتخابی ذخیره مدل به نحوه استفاده بعدی و نیاز به شیء Python بستگی دارد.
فایلهای مبتنی بر Joblib یا Pickle را فقط از منبع مورد اعتماد بارگذاری کنید. همچنین نسخه Scikit-learn و وابستگیهای زمان آموزش را ثبت کنید.
ثبت Metadata مدل
در کنار فایل مدل، اطلاعات زیر را نگه دارید:
import json
import platform
from datetime import datetime
import sklearn
metadata = {
"created_at": (
datetime.utcnow()
.isoformat()
),
"python_version": (
platform.python_version()
),
"scikit_learn_version": (
sklearn.__version__
),
"model_type": (
"LogisticRegression"
),
"feature_names": list(
x_train.columns
),
"target_names": target_names,
"random_state": RANDOM_STATE,
}
ذخیره:
with open(
"artifacts/metadata.json",
"w",
encoding="utf-8",
) as file:
json.dump(
metadata,
file,
ensure_ascii=False,
indent=2,
)
این اطلاعات برای بازتولید و عیبیابی مدل مفید است.
ساخت API ساده برای مدل Scikit-learn
میتوانید مدل ذخیرهشده را در یک Backend مانند FastAPI بارگذاری کنید.
ساختار درخواست:
{
"alcohol": 13.2,
"malic_acid": 1.8,
"ash": 2.4,
"alcalinity_of_ash": 18.5,
"magnesium": 100,
"total_phenols": 2.6,
"flavanoids": 2.8,
"nonflavanoid_phenols": 0.3,
"proanthocyanins": 1.8,
"color_intensity": 5,
"hue": 1,
"od280_od315": 3,
"proline": 1000
}
پاسخ:
{
"predicted_class": 0,
"probabilities": [
0.91,
0.07,
0.02
]
}
برای استفاده عملی باید Schema ورودی، محدودیت مقدارها، نسخه مدل و مدیریت خطا را نیز در نظر بگیرید.
ترکیب Scikit-learn با هوش مصنوعی مولد
مدل کلاسیک و مدل مولد نقش یکسانی ندارند.
یک معماری ترکیبی میتواند چنین باشد:
داده ساختاریافته
→ مدل Scikit-learn
→ کلاس یا امتیاز
→ API مدل زبانی
→ توضیح قابلخواندن
برای مثال، مدل Scikit-learn دسته یک نمونه را پیشبینی میکند و مدل زبانی نتیجه را به زبان طبیعی توضیح میدهد.
مدل زبانی نباید نتیجه عددی مدل کلاسیک را تغییر دهد؛ نقش آن میتواند فقط تولید توضیح، خلاصه یا قالب خروجی باشد.
نمونه اتصال نتیجه مدل به API درواره
نصب:
pip install openai python-dotenv
فایل .env:
DARVAREH_API_KEY=YOUR_DARVAREH_API_KEY
DARVAREH_MODEL_ID=YOUR_MODEL_ID
کد:
import json
import os
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv()
api_key = os.getenv(
"DARVAREH_API_KEY"
)
model_id = os.getenv(
"DARVAREH_MODEL_ID"
)
if not api_key:
raise RuntimeError(
"DARVAREH_API_KEY تنظیم نشده است."
)
if not model_id:
raise RuntimeError(
"DARVAREH_MODEL_ID تنظیم نشده است."
)
client = OpenAI(
api_key=api_key,
base_url="https://api.darvareh.ir/v1",
)
prediction_result = {
"predicted_class": "class_0",
"probabilities": {
"class_0": 0.91,
"class_1": 0.07,
"class_2": 0.02,
},
}
response = client.chat.completions.create(
model=model_id,
messages=[
{
"role": "system",
"content": (
"شما یک دستیار گزارشنویسی "
"هستید. فقط نتیجه مدل را "
"به زبان ساده توضیح دهید و "
"هیچ داده جدیدی اضافه نکنید."
),
},
{
"role": "user",
"content": (
"نتیجه مدل:\n"
+ json.dumps(
prediction_result,
ensure_ascii=False,
)
),
},
],
temperature=0.1,
max_tokens=300,
)
print(
response
.choices[0]
.message
.content
)
برای مشاهده Model IDها و قیمت مدلها به صفحه مدلهای درواره مراجعه کنید.
Data Leakage چیست؟
Data Leakage زمانی رخ میدهد که اطلاعاتی از خارج داده Train وارد فرایند آموزش شود.
نمونهها:
- Fit کردن Scaler روی کل داده
- Impute کردن قبل از تقسیم داده
- Feature Selection روی کل داده
- استفاده از اطلاعات آینده
- وجود نمونه تکراری در Train و Test
- ساخت Feature با استفاده از Target
- تنظیم مدل بر اساس Test Set
Data Leakage باعث میشود نتیجه آزمایش بهتر از عملکرد واقعی به نظر برسد.
استفاده از Pipeline راهحل مهمی است، اما همه انواع Leakage را بهصورت خودکار حل نمیکند.
Imbalanced Data چیست؟
در داده نامتوازن، تعداد نمونههای یک کلاس بسیار بیشتر از کلاس دیگر است.
مثال:
Class 0: 9500 samples
Class 1: 500 samples
مدلی که همیشه کلاس صفر را انتخاب کند، Accuracy برابر ۹۵ درصد دارد، اما کلاس یک را پیدا نمیکند.
اقدامات پیشنهادی:
- استفاده از
stratify - بررسی Precision و Recall
- بررسی Macro F1
- استفاده از
class_weight - تنظیم Threshold
- جمعآوری داده بیشتر
- ارزیابی جداگانه هر کلاس
نمونه:
LogisticRegression(
class_weight="balanced",
max_iter=2000,
)
این تنظیم همیشه باعث بهترشدن مدل نمیشود و باید با Cross-validation ارزیابی شود.
Feature Importance
برخی مدلها Feature Importance ارائه میکنند.
Random Forest:
from sklearn.ensemble import (
RandomForestClassifier,
)
model = RandomForestClassifier(
n_estimators=300,
random_state=42,
)
model.fit(
x_train,
y_train,
)
importance = pd.Series(
model.feature_importances_,
index=x_train.columns,
).sort_values(
ascending=False
)
print(
importance.head(10)
)
Feature Importance بهتنهایی رابطه علّی را ثابت نمیکند. اهمیت یک Feature فقط در زمینه همان مدل، داده و روش اندازهگیری معنا دارد.
خطاهای رایج Scikit-learn
خطای No module named sklearn
پکیج صحیح را نصب کنید:
pip install scikit-learn
نه:
pip install sklearn
خطای تعداد Featureها
X has N features, but model is expecting M features
علتهای احتمالی:
- ستون کم یا اضافه شده است.
- ترتیب ستونها تغییر کرده است.
- Preprocessing جدا از مدل ذخیره شده است.
- داده Inference با Train یکسان نیست.
راهحل:
- Pipeline را کامل ذخیره کنید.
- نام ستونها را ثبت کنید.
- Schema ورودی داشته باشید.
- DataFrame را با ستونهای مشخص بسازید.
خطای دسته ناشناخته
اگر OneHotEncoder دستهای را در Train ندیده باشد:
OneHotEncoder(
handle_unknown="ignore"
)
خطای ConvergenceWarning
برای Logistic Regression:
LogisticRegression(
max_iter=3000
)
همچنین:
- داده را Scale کنید.
- Solver مناسب انتخاب کنید.
- Featureهای مشکلدار را بررسی کنید.
- مقدار Regularization را تنظیم کنید.
Accuracy بالا ولی عملکرد واقعی ضعیف
دلایل احتمالی:
- Data Leakage
- داده نامتوازن
- Test Set غیرواقعی
- داده تکراری
- Featureهای مربوط به آینده
- Drift داده
- Metric نامناسب
- نمونه آزمایش بسیار کوچک
نتیجه هر بار تغییر میکند
در بخشهای تصادفی از random_state استفاده کنید:
random_state=42
همچنین نسخه کتابخانهها و داده را ثابت نگه دارید.
مدل Joblib بارگذاری نمیشود
نسخههای Python، Scikit-learn، NumPy و SciPy را بررسی کنید. بهتر است محیط پروژه با requirements.txt یا فایل Lock ثبت شود.
چکلیست پروژه Machine Learning
- مسئله Classification یا Regression مشخص است.
- Target بهدرستی تعریف شده است.
- داده تکراری بررسی شده است.
- Missing Valueها شناسایی شدهاند.
- داده قبل از Preprocessing تقسیم شده است.
- از Stratification در جای مناسب استفاده شده است.
- Preprocessing داخل Pipeline قرار دارد.
- Baseline ساده ساخته شده است.
- چند مدل با Cross-validation مقایسه شدهاند.
- Metric متناسب با مسئله انتخاب شده است.
- Hyperparameter فقط با داده Train تنظیم شده است.
- Test Set برای ارزیابی نهایی نگه داشته شده است.
- Confusion Matrix بررسی شده است.
- خطاهای مدل تحلیل شدهاند.
- Pipeline کامل ذخیره شده است.
- Featureها و نسخه کتابخانه ثبت شدهاند.
- مدل روی داده واقعی آزمایش شده است.
- کیفیت مدل پس از استقرار قابل پایش است.
مسیر یادگیری پیشنهادی Scikit-learn
مرحله اول: Python
- متغیر و تابع
- List و Dictionary
- کلاس
- مدیریت فایل
- محیط مجازی
مرحله دوم: NumPy و Pandas
- Array
- DataFrame
- Indexing
- Missing Value
- Grouping
- Merge
- dtype
- Shape
مرحله سوم: مفاهیم Machine Learning
- Feature
- Target
- Classification
- Regression
- Train و Test
- Overfitting
- Metric
مرحله چهارم: Scikit-learn پایه
- fit
- predict
- transform
- train_test_split
- StandardScaler
- OneHotEncoder
- Pipeline
مرحله پنجم: ارزیابی
- Cross-validation
- Accuracy
- Precision
- Recall
- F1
- Confusion Matrix
- Learning Curve
مرحله ششم: تنظیم مدل
- GridSearchCV
- RandomizedSearchCV
- Hyperparameter
- Model Comparison
- Feature Selection
مرحله هفتم: استفاده عملی
- ذخیره Pipeline
- ساخت API
- ثبت نسخه مدل
- کنترل Schema
- پایش کیفیت
- آموزش مجدد
پرسشهای متداول
Scikit-learn چیست؟
Scikit-learn یک کتابخانه متنباز پایتون برای یادگیری ماشین کلاسیک، آمادهسازی داده، ارزیابی مدل و انتخاب Hyperparameter است.
تفاوت scikit-learn و sklearn چیست؟
نام پکیج برای نصب scikit-learn است، اما Module در کد با نام sklearn Import میشود.
آیا Scikit-learn برای مبتدیان مناسب است؟
بله. API یکدست و مستندات گسترده آن را به گزینه مناسبی برای یادگیری Machine Learning با پایتون تبدیل کرده است.
آیا Scikit-learn به GPU نیاز دارد؟
بیشتر الگوریتمهای اصلی Scikit-learn روی CPU اجرا میشوند و برای پروژههای آموزشی و بسیاری از دادههای جدولی به GPU نیاز ندارند.
تفاوت Scikit-learn و TensorFlow چیست؟
Scikit-learn بیشتر برای الگوریتمهای کلاسیک یادگیری ماشین و داده جدولی استفاده میشود. TensorFlow بیشتر برای شبکههای عصبی و Deep Learning کاربرد دارد.
تفاوت Scikit-learn و PyTorch چیست؟
Scikit-learn API سطحبالا برای مدلهای کلاسیک و Workflow داده ارائه میکند. PyTorch کنترل بیشتری برای ساخت و آموزش شبکه عصبی فراهم میکند.
Pipeline چیست؟
Pipeline مجموعه مراحل Preprocessing و مدل را در یک شیء قرار میدهد تا آموزش، ارزیابی و Inference با روند یکسان انجام شود.
Cross-validation چیست؟
روشی برای ارزیابی مدل با چند تقسیم مختلف داده Train است که تخمین پایدارتری از عملکرد مدل ارائه میدهد.
GridSearchCV چیست؟
ابزاری برای آزمایش ترکیبهای مشخص Hyperparameter با استفاده از Cross-validation است.
چرا Accuracy کافی نیست؟
در داده نامتوازن، مدل ممکن است کلاس پرتعداد را همیشه انتخاب و Accuracy بالایی کسب کند. Precision، Recall، F1 و Confusion Matrix نیز باید بررسی شوند.
چگونه مدل Scikit-learn را ذخیره کنیم؟
میتوانید Pipeline آموزشدیده را با Joblib ذخیره کنید:
joblib.dump(
model,
"model.joblib",
)
آیا Scikit-learn برای مدل زبانی بزرگ مناسب است؟
برای آموزش مستقیم مدلهای زبانی بزرگ طراحی نشده است. با این حال، برای Feature Engineering، مدلهای متنی کلاسیک، ارزیابی، طبقهبندی و بخشهایی از Pipeline هوش مصنوعی کاربرد دارد.
برای ساخت اپلیکیشن هوش مصنوعی به Scikit-learn نیاز داریم؟
اگر مسئله شما با مدلهای کلاسیک قابل حل باشد، Scikit-learn انتخاب مناسبی است. اگر فقط به قابلیت یک مدل مولد آماده نیاز دارید، اتصال به API میتواند کافی باشد.
جمعبندی
Scikit-learn یکی از بهترین ابزارها برای یادگیری و اجرای Machine Learning کلاسیک با پایتون است. این کتابخانه API یکدستی برای آمادهسازی داده، آموزش مدل، ارزیابی، Cross-validation و تنظیم Hyperparameter ارائه میکند.
در این مقاله یاد گرفتیم:
- Scikit-learn چیست.
- Classification، Regression و Clustering چه تفاوتی دارند.
- Estimator و Transformer چگونه کار میکنند.
- داده را چگونه به Train و Test تقسیم کنیم.
- StandardScaler چه کاربردی دارد.
- Pipeline چگونه از Data Leakage جلوگیری میکند.
- Logistic Regression چگونه آموزش داده میشود.
- Accuracy، Precision، Recall و F1 چگونه تفسیر میشوند.
- Cross-validation چگونه اجرا میشود.
- GridSearchCV چگونه بهترین پارامتر را پیدا میکند.
- ColumnTransformer چگونه ستونهای مختلف را آماده میکند.
- مدل و Preprocessing چگونه با هم ذخیره میشوند.
- چگونه مدل کلاسیک را با API هوش مصنوعی ترکیب کنیم.
اگر با دادههای جدولی، طبقهبندی، رگرسیون یا تحلیل متن کلاسیک کار میکنید، Scikit-learn معمولاً یکی از اولین انتخابها است. اگر به تولید متن، تحلیل چندوجهی، تولید کد یا قابلیتهای مدلهای بزرگ نیاز دارید، میتوانید در کنار مدل کلاسیک خود از API مدلهای آماده استفاده کنید.
برای شروع استفاده از مدلهای هوش مصنوعی در نرمافزار، در درواره ثبتنام کنید، API Key بسازید و مدل مناسب پروژه را از صفحه مدلها انتخاب کنید.
مقالات مرتبط
- آموزش هوش مصنوعی با پایتون و ساخت پروژه واقعی
- Evals چیست؟ راهنمای ارزیابی مدلهای هوش مصنوعی
- تحلیل فایل CSV با هوش مصنوعی
- تحلیل داده و فرمولنویسی Excel با هوش مصنوعی
- راهنمای کامل مدلهای هوش مصنوعی
- Inference چیست؟ راهنمای اجرای مدل هوش مصنوعی
- Embedding چیست و چه کاربردی دارد؟
- API هوش مصنوعی چیست؟
برای مطالعه شرایط استفاده و محدودیتهای مسئولیت، صفحه «سلب مسئولیت» را مشاهده کنید.