بخش دوم: تکنیکهای پیشرفته، مصورسازی تخصصی
بخش دوم: تکنیکهای پیشرفته، مصورسازی تخصصی
مقدمه: بصریسازی به عنوان ابزار عیبیابی
در بخش اول یاد گرفتیم دادهها را قبل از آموزش مدل کاوش کنیم (EDA). اما در دنیای واقعی یادگیری ماشین و یادگیری عمیق، بیش از نیمی از زمان شما صرف عیبیابی مدل (Model Diagnostics) میشود:
- چرا مدل بیشبرازش (Overfitting) کرده است؟
- وزنها در کدام ایپاک (Epoch) واگرا شدند؟
- مرز تصمیمگیری دستهبند کجاست و دادههای مرزی با چه حاشیهای تفکیک شدهاند؟
در این بخش، مستقیماً به سراغ پیادهسازی بصریسازیهای استاندارد مهندسی هوش مصنوعی با Matplotlib میرویم.
فهرست مطالب
پیشنیاز: مطالعه بخش اول (درک عمیق رابط شیءگرای
FigureوAxes)، تسلط بر آرایههای چندبعدی NumPy و کار با ابزارهای اولیه یادگیری ماشین (مانند Scikit-Learn).
گام ۱: نمودارهای آماری پیشرفته برای پیشپردازش داده
۱. نمودار جعبهای (Box Plot) برای شکار دادههای پرت (Outliers)
دادههای پرت میتوانند وزنهای شبکههای عصبی و ضرایب رگرسیون را کاملاً مخدوش کنند. نمودار جعبهای بر پایه ۵ شاخص آماری (کمینه، چارک اول Q1، میانه Q2، چارک سوم Q3 و بیشینه) ساخته شده و مقادیر خارج از محدوده مجاز (فاصله بینچارکی یا IQR) را به صورت نقاط منفرد لو میدهد:
import matplotlib.pyplot as plt
import numpy as np
# شبیهسازی ۳ ویژگی مختلف یک دیتاست (با چند مقدار پرت عمدی)
np.random.seed(42)
feat_1 = np.random.normal(50, 10, 200)
feat_2 = np.concatenate([np.random.normal(70, 5, 195), [120, 125, 5, 10, 8]])
# دادههای پرت
feat_3 = np.random.exponential(scale=15, size=200)
data_to_plot = [feat_1, feat_2, feat_3]
fig, ax = plt.subplots(figsize=(8, 5))
# رسم Boxplot
bp = ax.boxplot(
data_to_plot,
tick_labels=['Feature 1', 'Feature 2 (Outliers)', 'Feature 3 (Skewed)'],
patch_artist=True, # اجازه رنگآمیزی داخل جعبهها را فعال میکند
notch=True, # فرورفتگی در ناحیه میانه برای مقایسه معناداری آماری
vert=True # رسم عمودی
)
# شخصیسازی رنگ بخشهای مختلف جعبه
colors = ['#aec7e8', '#ffbb78', '#98df8a']
for patch, color in zip(bp['boxes'], colors):
patch.set_facecolor(color)
patch.set_alpha(0.8)
# هایلایت کردن دادههای پرت (Fliers) با رنگ قرمز
for flier in bp['fliers']:
flier.set(marker='o', color='#d62728', alpha=0.6, markersize=7)
ax.set_title("Outlier & Distribution Diagnostics", fontsize=14, fontweight='bold')
ax.set_ylabel("Value Magnitude")
ax.grid(axis='y', linestyle='--', alpha=0.5)
plt.show()

۲. ماتریس همبستگی و هیتمپ (Heatmap) بدون اتکا به Seaborn
بسیاری از برنامهنویسان گمان میکنند برای رسم Heatmap همبستگی حتماً باید از Seaborn استفاده کرد. در متپلاتلیب متدی پایه و فوقسریع به نام imshow() وجود دارد که پیکسلهای ماتریسی را به رنگ تبدیل میکند.
import pandas as pd
# ایجاد یک ماتریس همبستگی فرضی
corr_matrix = np.array([
[ 1.00, 0.85, -0.20, 0.60],
[ 0.85, 1.00, -0.10, 0.75],
[-0.20, -0.10, 1.00, -0.45],
[ 0.60, 0.75, -0.45, 1.00]
])
features = ['Area', 'Rooms', 'Age', 'Price']
fig, ax = plt.subplots(figsize=(7, 6))
# نمایش ماتریس عددی به شکل تصویر با طیف رنگی Cool-Warm
im = ax.imshow(corr_matrix, cmap='coolwarm', vmin=-1, vmax=1)
# تنظیم تیکهای محورها متناسب با تعداد و نام فیچرها
ax.set_xticks(np.arange(len(features)))
ax.set_yticks(np.arange(len(features)))
ax.set_xticklabels(features, fontsize=11)
ax.set_yticklabels(features, fontsize=11)
# اضافه کردن نوار رنگی
cbar = fig.colorbar(im, ax=ax, fraction=0.046, pad=0.04)
cbar.set_label("Pearson Correlation", rotation=270, labelpad=15)
# نوشتن ارقام درون سلولها به صورت خودکار
for i in range(len(features)):
for j in range(len(features)):
text_color = "white" if abs(corr_matrix[i, j]) > 0.5 else "black"
ax.text(j, i, f"{corr_matrix[i, j]:.2f}",
ha="center", va="center", color=text_color, fontweight='bold')
ax.set_title("Feature Correlation Matrix", fontsize=13)
plt.tight_layout()
plt.show()

گام ۲: نمودارهای اختصاصی در ارزیابی مدلهای ML
۱. نمودار همگرایی و افت مدل با محور دوگانه (twinx)
در تمرین شبکههای عصبی، اغلب میخواهیم تابع هزینه (Loss) که عددی با مقیاس دلخواه است را همزمان با دقت (Accuracy) که عددی بین ۰ تا ۱ است در یک قاب اما با دو مقیاس مجزا رسم کنیم. متد twinx() این کار را انجام میدهد.
epochs = np.arange(1, 21)
# شبیهسازی کاهش زیان و افزایش دقت
train_loss = 2.5 * np.exp(-epochs / 4) + 0.1
train_acc = 1 - np.exp(-epochs / 3) * 0.7
fig, ax_loss = plt.subplots(figsize=(9, 5))
# ۱. رسم Loss روی محور اصلی (سمت چپ)
color_loss = '#d62728'
line1 = ax_loss.plot(epochs, train_loss, color=color_loss, linewidth=2, label='Training Loss')
ax_loss.set_xlabel("Epochs", fontsize=12)
ax_loss.set_ylabel("Cross Entropy Loss", color=color_loss, fontsize=12)
ax_loss.tick_params(axis='y', labelcolor=color_loss)
# ۲. ایجاد محور اشتراکی برای Accuracy (سمت راست)
ax_acc = ax_loss.twinx()
color_acc = '#1f77b4'
line2 = ax_acc.plot(epochs, train_acc, color=color_acc, linestyle='--', linewidth=2, label='Accuracy')
ax_acc.set_ylabel("Accuracy (0.0 - 1.0)", color=color_acc, fontsize=12)
ax_acc.tick_params(axis='y', labelcolor=color_acc)
ax_acc.set_ylim(0, 1.05)
# ۳. ادغام Legendهای دو محور مختلف در یک باکس واحد
lines = line1 + line2
labels = [l.get_label() for l in lines]
ax_loss.legend(lines, labels, loc='center right')
ax_loss.set_title("Model Convergence: Loss vs Accuracy over Epochs", fontsize=13, fontweight='bold')
ax_loss.grid(True, linestyle=':', alpha=0.5)
plt.show()

۲. مصورسازی حرفهای ماتریس درهمریختگی
برای مدلهای دستهبندی، بررسی False Positiveها و False Negativeها امری حیاتی است و از آنها برای رسم ماتریس درهمریختگی (Confusion Matrix) استفاده می کنند:
# ماتریس فرضی ۳ کلاسه (مثلاً تشخیص بیماری: سالم، مشکوک، مبتلا)
cm = np.array([
[85, 4, 1],
[ 7, 60, 3],
[ 2, 5, 43]
])
classes = ['Healthy', 'Suspect', 'Infected']
fig, ax = plt.subplots(figsize=(6, 6))
im = ax.imshow(cm, interpolation='nearest', cmap='Blues')
# تنظیم عنوان و لیبلها
ax.set_title("Confusion Matrix (Diagnosis Model)", fontsize=13)
tick_marks = np.arange(len(classes))
ax.set_xticks(tick_marks)
ax.set_yticks(tick_marks)
ax.set_xticklabels(classes, rotation=45)
ax.set_yticklabels(classes)
# درج اعداد و برچسب درصد در هر خانه
thresh = cm.max() / 2.
for i in range(cm.shape[0]):
for j in range(cm.shape[1]):
val = cm[i, j]
pct = (val / np.sum(cm[i, :])) * 100
ax.text(j, i, f"{val}\n({pct:.1f}%)",
ha="center", va="center",
color="white" if val > thresh else "black",
fontweight='semibold')
ax.set_ylabel('True Label', fontsize=11)
ax.set_xlabel('Predicted Label', fontsize=11)
fig.colorbar(im, ax=ax, fraction=0.046, pad=0.04)
plt.tight_layout()
plt.show()

۳. ترسیم مرز تصمیمگیری مدل با contourf
یکی از چشمنوازترین و عمیقترین مفاهیم در درک رفتار مدلهای هوش مصنوعی (مانند SVM، درخت تصمیم یا رگرسیون لجستیک)، دیدن دوبعدی مرزی (Decision Boundary) است که مدل بین دادهها ترسیم کرده است:
from sklearn.datasets import make_moons
from sklearn.linear_model import LogisticRegression
# ۱. ساخت یک دیتای هلالی غیرخطی با دو کلاس
X, y = make_moons(n_samples=200, noise=0.25, random_state=42)
# ۲. آموزش یک مدل ساده برای یادگیری مرز
model = LogisticRegression()
model.fit(X, y)
# ۳. ایجاد یک صفحه توری (Meshgrid) برای اسکن کل فضا
x_min, x_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5
y_min, y_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5
xx, yy = np.meshgrid(np.linspace(x_min, x_max, 300),
np.linspace(y_min, y_max, 300))
# پیشبینی احتمال کلاس برای تمام نقاط توری
Z = model.predict_proba(np.c_[xx.ravel(), yy.ravel()])[:, 1]
Z = Z.reshape(xx.shape)
# ۴. ترسیم کانتورهای کلاسه و نقاط داده
fig, ax = plt.subplots(figsize=(8, 5))
# کانتور پرشده برای رنگآمیزی نواحی مختلف احتمالاتی
contour = ax.contourf(xx, yy, Z, levels=20, cmap='RdBu', alpha=0.7)
# خط پررنگ برای مرز بحرانی P=0.5
ax.contour(xx, yy, Z, levels=[0.5], colors='k', linestyles='--', linewidths=2)
# رسم نقاط واقعی دادهها
scatter = ax.scatter(X[:, 0], X[:, 1], c=y, cmap='RdBu', edgecolors='k', s=45)
ax.set_title("Decision Boundary Analysis (Threshold P=0.5)", fontsize=13)
ax.set_xlabel("Feature 1")
ax.set_ylabel("Feature 2")
cbar = fig.colorbar(contour, ax=ax)
cbar.set_label("Predicted Probability of Class 1")
plt.show()

گام ۳:حاشیهنویسی هوشمند و جلوههای گرافیکی گزارشها
۱. حاشیهنویسی با فلشهای اشارهگر (annotate)
در مقالات پژوهشی لازم است نقطه دقیقی را مستقیماً نشان دهید؛ مثلاً لحظهای که پدیده Overfitting رخ داده و مدل باید از طریق Early Stopping متوقف میشد:
epochs = np.arange(1, 16)
val_loss = np.array([1.2, 0.9, 0.7, 0.55, 0.42, 0.35,
0.32, 0.30, 0.33, 0.38, 0.45, 0.55, 0.68, 0.80, 0.95])
fig, ax = plt.subplots(figsize=(8, 4.5))
ax.plot(epochs, val_loss, marker='s', color='#2ca02c', label='Validation Loss')
# پیدا کردن کمینه خطا
min_idx = np.argmin(val_loss)
best_epoch = epochs[min_idx]
best_loss = val_loss[min_idx]
# رسم حاشیهنویسی هوشمند
ax.annotate(
f'Optimal Checkpoint\nEpoch: {best_epoch}\nLoss: {best_loss:.2f}',
xy=(best_epoch, best_loss), # نقطهای که فلش به آن اشاره میکند
xytext=(best_epoch + 2, best_loss + 0.3), # موقعیت متن
arrowprops=dict(
facecolor='crimson',
shrink=0.08,
width=2,
headwidth=8
),
bbox=dict(boxstyle="round,pad=0.4", fc="yellow", alpha=0.3),
fontweight='bold'
)
ax.set_title("Locating Early Stopping Point via Annotations", fontsize=12)
ax.set_xlabel("Epochs")
ax.set_ylabel("Loss")
ax.grid(True, linestyle=':', alpha=0.6)
ax.legend()
plt.show()

۲. استایلهای مدرن و شکیل با plt.style.use
اگر از ظاهر پیشفرض خاکستری یا سنتی خسته شدهاید، متپلاتلیب دارای قالبهای آماده است. کافی است قبل از فراخوانی دستور ساخت نمودار، نام تم را فعال کنید:
# مشاهده تمامی تمهای در دسترس
print(plt.style.available)
# استفاده از یک تم جذاب علمی و دارک مود
plt.style.use('dark_background')
fig, ax = plt.subplots(figsize=(7, 4))
x = np.linspace(0, 10, 100)
ax.plot(x, np.sin(x), color='#00ffcc', linewidth=2.5, label='Cyber Wave')
ax.plot(x, np.cos(x), color='#ff007f', linewidth=2.5, label='Phase Shift')
ax.set_title("Neon Theme for Presentations", fontsize=13)
ax.legend()
plt.show()
# نکته:بعد از پایان کار تم را به پیشفرض ریست کنید تا کدهای بعدی متاثر نشوند
plt.style.use('default')

گام ۴: انیمیشن و متحرکسازی فرآیندهای یادگیری ماشین
یکی از چشمگیرترین روشهای آموزش و ارائه، نمایش پویانمایی روند بهینهسازی الگوریتم گرادیان نزولی (Gradient Descent) است. ماژول matplotlib.animation این کار را از طریق متد FuncAnimation انجام میدهد.
import matplotlib.animation as animation
# ۱. تعریف یک تابع هزینه درجه دوم فرضی: y = x^2
def cost_function(x):
return x ** 2
def gradient(x):
return 2 * x
# ۲. پیادهسازی گامهای الگوریتم گرادیان نزولی
lr = 0.2
cur_x = 4.5 # نقطه شروع اولیه
history_x = [cur_x]
for _ in range(25):
cur_x = cur_x - lr * gradient(cur_x)
history_x.append(cur_x)
history_x = np.array(history_x)
history_y = cost_function(history_x)
# ۳. آمادهسازی بوم برای انیمیشن
fig, ax = plt.subplots(figsize=(8, 5))
x_curve = np.linspace(-5, 5, 200)
ax.plot(x_curve, cost_function(x_curve), 'gray', label='Cost Function $J(w)=w^2$')
point, = ax.plot([], [], 'ro', markersize=10, label='Current Weight')
trail, = ax.plot([], [], 'r--', alpha=0.5, label='Gradient Path')
ax.set_xlim(-5, 5)
ax.set_ylim(-2, 25)
ax.set_title("Real-Time Gradient Descent Convergence", fontsize=13)
ax.set_xlabel("Parameter w")
ax.set_ylabel("Loss J(w)")
ax.legend(loc='upper center')
# ۴. توابع فریم انیمیشن
def init():
point.set_data([], [])
trail.set_data([], [])
return point, trail
def update(frame):
# بروزرسانی موقعیت نقطه در هر فریم
x_val = history_x[frame]
y_val = history_y[frame]
point.set_data([x_val], [y_val])
trail.set_data(history_x[:frame+1], history_y[:frame+1])
return point, trail
# ۵. کامپایل و اجرای انیمیشن
ani = animation.FuncAnimation(
fig, update, frames=len(history_x),
init_func=init, blit=True, interval=250, repeat=True
)
plt.show()
# برای ذخیره فایل گیف از دستور زیر استفاده میشود (نیازمند pillow یا imagemagick):
# ani.save('gradient_descent.gif', writer='pillow', fps=4)
جمعبندی نهایی Matplotlib
با اتمام این دو بخش، شما اکنون به جعبهابزار کاملی مجهز شدهاید که نه تنها از هر کتابخانه واسط دیگری بینیازتان میکند، بلکه درک ساختاری عمیقی به شما میدهد تا:
| نیاز شما در پروژه | ابزار مناسب در Matplotlib |
|---|---|
| تحلیل و تفکیک دادههای پرت | ax.boxplot(notch=True) |
| ماتریس همبستگی و هیتمپ | ax.imshow(cmap='coolwarm') + ax.text |
| مقایسه دو کمیت با مقیاس متفاوت | ax.twinx() |
| ارزیابی دقیق دستهبند چندکلاسه | ماتریس درهمریختگی سفارشی با imshow |
| درک جداپذیری مرز مدلهای ML | ax.contourf و np.meshgrid |
| گزارشنویسی و ارائههای حرفهای | plt.style.use و ax.annotate |
| بصریسازی همگرایی الگوریتمها | matplotlib.animation.FuncAnimation |
از این پس هر زمان که مدل یادگیری ماشین شما نتیجه غیرمنتظرهای داد یا نیاز به ثبت نتایج در یک ژورنال یا مقاله داشتید، کدها را مستقیماً بر اساس این الگوها پیادهسازی و تحلیل کنید!
