SciPy چیست؟ آموزش کامل محاسبات علمی، آمار و بهینه‌سازی با پایتون

در این آموزش جامع SciPy، بهینه‌سازی، آزمون آماری، انتگرال‌گیری، درون‌یابی، جبر خطی، پردازش سیگنال و ماتریس‌های Sparse را با پروژه‌های عملی پایتون و هوش مصنوعی درواره یاد می‌گیرید.

Share
SciPy چیست؟ آموزش کامل محاسبات علمی، آمار و بهینه‌سازی با پایتون

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

SciPy یکی از پایه‌ای‌ترین کتابخانه‌های این اکوسیستم است. اگر NumPy ابزار اصلی کار با آرایه و محاسبات برداری باشد، SciPy مجموعه‌ای از الگوریتم‌های تخصصی برای بهینه‌سازی، آمار، انتگرال‌گیری، جبر خطی، پردازش سیگنال، درون‌یابی، ماتریس‌های Sparse و محاسبات فضایی ارائه می‌کند.

در این آموزش یاد می‌گیرید:

  • SciPy چیست و چه تفاوتی با NumPy دارد
  • چگونه SciPy را نصب و پیکربندی کنید
  • ساختار Submoduleهای اصلی آن چگونه است
  • چگونه یک تابع را بهینه کنید
  • چگونه پارامترهای یک مدل را روی داده برازش دهید
  • چگونه انتگرال و معادله دیفرانسیل را عددی حل کنید
  • چگونه داده‌های ناقص را درون‌یابی کنید
  • چگونه آزمون آماری اجرا کنید
  • چگونه نویز سیگنال را کاهش و قله‌ها را پیدا کنید
  • چگونه از ماتریس Sparse استفاده کنید
  • چگونه فاصله و نزدیک‌ترین همسایه را محاسبه کنید
  • چگونه نتیجه محاسبات را برای تحلیل متنی به API درواره بفرستید

SciPy چیست؟

SciPy یک کتابخانه متن‌باز پایتون برای محاسبات علمی، ریاضی و مهندسی است. این کتابخانه روی NumPy ساخته شده و بسیاری از توابع آن، آرایه‌های NumPy را به‌عنوان ورودی دریافت می‌کنند.

طبق وب‌سایت رسمی SciPy، این کتابخانه الگوریتم‌هایی برای موارد زیر ارائه می‌کند:

  • Optimization
  • Integration
  • Interpolation
  • Linear Algebra
  • Statistics
  • Signal Processing
  • Fourier Transform
  • Sparse Matrices
  • Spatial Algorithms
  • Differential Equations
  • Special Functions

SciPy بخشی از زیرساخت محاسبات علمی پایتون است و بسیاری از کتابخانه‌های Machine Learning، پردازش تصویر و تحلیل داده به آن وابسته‌اند.

تفاوت SciPy و NumPy

NumPy و SciPy مکمل یکدیگرند.

ویژگیNumPySciPy
آرایه چندبعدیقابلیت اصلیاز آرایه NumPy استفاده می‌کند
محاسبات برداریبسیار مناسببرای الگوریتم‌های تخصصی
جبر خطی پایهداردکامل‌تر و تخصصی‌تر
آمار پایهمحدودتوزیع‌ها و آزمون‌های آماری
بهینه‌سازیندارد یا بسیار محدودمجموعه کامل الگوریتم‌ها
انتگرال عددیندارددارد
پردازش سیگنالمحدودابزارهای تخصصی
ماتریس Sparseندارددارد
الگوریتم فضاییمحدودKDTree، Distance و موارد دیگر
درون‌یابیمحدودمجموعه روش‌های تخصصی

مثال NumPy:

import numpy as np

values = np.array([
    10,
    15,
    22,
    18
])

print(values.mean())

مثال SciPy:

from scipy import stats

result = stats.ttest_1samp(
    values,
    popmean=15
)

print(result.statistic)
print(result.pvalue)

NumPy میانگین را محاسبه می‌کند، اما SciPy یک آزمون آماری کامل اجرا می‌کند.

نصب SciPy

ساخت محیط مجازی:

python -m venv .venv

فعال‌سازی در ویندوز:

.venv\Scripts\activate

فعال‌سازی در Linux یا macOS:

source .venv/bin/activate

به‌روزرسانی Pip:

python -m pip install --upgrade pip

نصب SciPy:

python -m pip install scipy

برای اجرای مثال‌های مقاله:

python -m pip install scipy numpy pandas matplotlib

راهنمای رسمی SciPy نیز استفاده از محیط مجازی و نصب با دستور زیر را پیشنهاد می‌کند:

python -m pip install scipy

بررسی نسخه نصب‌شده:

python -c "import scipy; print(scipy.__version__)"

تست Import:

import scipy
import numpy as np

print("SciPy:", scipy.__version__)
print("NumPy:", np.__version__)

ساختار Submoduleهای مهم SciPy

بهتر است به‌جای Import کردن تمام SciPy، فقط Submodule موردنیاز را وارد کنید.

Submoduleکاربرد
scipy.optimizeبهینه‌سازی، پیداکردن ریشه و Curve Fitting
scipy.integrateانتگرال‌گیری و حل معادلات دیفرانسیل
scipy.interpolateدرون‌یابی داده
scipy.statsآمار، توزیع احتمال و آزمون آماری
scipy.linalgجبر خطی
scipy.sparseماتریس Sparse
scipy.signalپردازش سیگنال
scipy.fftتبدیل فوریه
scipy.spatialفاصله، KDTree و محاسبات فضایی
scipy.ndimageپردازش آرایه‌های چندبعدی و تصویر
scipy.specialتوابع ریاضی ویژه

نمونه Import:

from scipy import optimize
from scipy import stats
from scipy import signal

یا:

from scipy.optimize import minimize
from scipy.stats import ttest_ind
from scipy.signal import find_peaks

روش دوم وابستگی هر بخش از کد را واضح‌تر می‌کند.

بهینه‌سازی با scipy.optimize

Optimization یعنی پیداکردن ورودی‌ای که مقدار یک تابع را کمینه یا بیشینه کند.

کاربردهای آن:

  • کمینه‌کردن هزینه
  • انتخاب بهترین ترکیب منابع
  • تنظیم پارامتر مدل
  • برازش منحنی
  • پیداکردن نقطه بهینه یک تابع
  • برنامه‌ریزی تولید
  • بهینه‌سازی قیمت یا بودجه

کمینه‌کردن یک تابع ساده

تابع زیر در نقطه x = 3 کمینه می‌شود:

def objective(x):
    return (x - 3) ** 2 + 5

استفاده از minimize_scalar:

from scipy.optimize import minimize_scalar

result = minimize_scalar(
    objective
)

print("Success:", result.success)
print("Best x:", result.x)
print("Minimum value:", result.fun)

خروجی result فقط یک عدد نیست و اطلاعاتی مانند وضعیت موفقیت، تعداد ارزیابی‌ها و پیام Solver را نیز نگهداری می‌کند.

همیشه وضعیت موفقیت را بررسی کنید:

if not result.success:
    raise RuntimeError(
        result.message
    )

بهینه‌سازی چندمتغیره

فرض کنید هزینه یک سیستم با دو متغیر مشخص می‌شود:

def cost_function(values):
    x, y = values

    return (
        (x - 4) ** 2
        + (y - 2) ** 2
        + 10
    )

اجرای بهینه‌سازی:

from scipy.optimize import minimize

initial_guess = [0, 0]

result = minimize(
    cost_function,
    x0=initial_guess
)

print("Success:", result.success)
print("Best values:", result.x)
print("Minimum cost:", result.fun)

x0 نقطه شروع Solver است. در بعضی مسائل غیرخطی، نقطه شروع می‌تواند روی نتیجه اثر بگذارد.

اعمال محدودیت روی متغیرها

اگر هر متغیر باید داخل یک بازه باشد:

bounds = [
    (0, 10),
    (0, 8)
]

result = minimize(
    cost_function,
    x0=[1, 1],
    bounds=bounds
)

در این مثال:

  • مقدار x بین صفر و ۱۰ است
  • مقدار y بین صفر و ۸ است

بهینه‌سازی با Constraint

فرض کنید مجموع دو متغیر باید حداقل ۵ باشد:

constraints = [
    {
        "type": "ineq",
        "fun": lambda values:
            values[0]
            + values[1]
            - 5
    }
]

result = minimize(
    cost_function,
    x0=[2.5, 2.5],
    bounds=[
        (0, 10),
        (0, 8)
    ],
    constraints=constraints,
    method="SLSQP"
)

print(result.x)
print(result.fun)
print(result.success)

در Constraint از نوع ineq، مقدار تابع باید بزرگ‌تر یا مساوی صفر باشد.

نتیجه Optimization باید از نظر منطق مسئله نیز بررسی شود. موفقیت Solver به معنای صحیح‌بودن مدل کسب‌وکار، داده یا Constraintها نیست.

پیداکردن ریشه معادله

برای حل معادله زیر:

x^2 - 9 = 0

از root_scalar استفاده می‌کنیم:

from scipy.optimize import root_scalar

def equation(x):
    return x ** 2 - 9

result = root_scalar(
    equation,
    bracket=[0, 10]
)

print("Root:", result.root)
print("Converged:", result.converged)

بازه bracket باید به شکلی انتخاب شود که ریشه داخل آن قرار گیرد و شرایط روش انتخابی برقرار باشد.

برای ریشه منفی:

result = root_scalar(
    equation,
    bracket=[-10, 0]
)

برازش منحنی با curve_fit

Curve Fitting برای تخمین پارامترهای یک مدل از روی داده استفاده می‌شود.

فرض کنید داده از یک رابطه خطی همراه با Noise آمده است:

import numpy as np

rng = np.random.default_rng(42)

x = np.linspace(
    0,
    20,
    80
)

y = (
    2.7 * x
    + 8
    + rng.normal(
        0,
        3,
        size=len(x)
    )
)

تابع مدل:

def linear_model(
    x,
    slope,
    intercept
):
    return (
        slope * x
        + intercept
    )

برازش:

from scipy.optimize import curve_fit

parameters, covariance = curve_fit(
    linear_model,
    x,
    y
)

slope, intercept = parameters

print("Slope:", slope)
print("Intercept:", intercept)

رسم نتیجه:

import matplotlib.pyplot as plt

predicted = linear_model(
    x,
    slope,
    intercept
)

fig, ax = plt.subplots(
    figsize=(10, 5),
    layout="constrained"
)

ax.scatter(
    x,
    y,
    alpha=0.65,
    label="Observed"
)

ax.plot(
    x,
    predicted,
    color="#EF476F",
    linewidth=2.5,
    label="Fitted line"
)

ax.set_title("Curve Fitting with SciPy")
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.legend()
ax.grid(alpha=0.2)

plt.show()

ماتریس covariance اطلاعاتی درباره عدم‌قطعیت تخمین پارامترها ارائه می‌کند.

تخمین تقریبی Standard Error پارامترها:

parameter_errors = np.sqrt(
    np.diag(covariance)
)

print(parameter_errors)

برازش موفق یک منحنی به معنای مناسب‌بودن آن مدل برای پیش‌بینی خارج از بازه داده نیست.

انتگرال‌گیری عددی با scipy.integrate

برای محاسبه انتگرال تابع زیر در بازه صفر تا یک:

f(x) = x^2

کد:

from scipy.integrate import quad

def function(x):
    return x ** 2

value, estimated_error = quad(
    function,
    0,
    1
)

print("Integral:", value)
print(
    "Estimated error:",
    estimated_error
)

نتیجه دقیق این انتگرال برابر یک‌سوم است. quad علاوه بر مقدار تقریبی، یک تخمین از خطای عددی نیز برمی‌گرداند.

انتگرال تابع دارای پارامتر

from scipy.integrate import quad

def exponential_decay(
    x,
    rate
):
    return np.exp(
        -rate * x
    )

value, error = quad(
    exponential_decay,
    0,
    5,
    args=(0.8,)
)

print(value)
print(error)

آرگومان args پارامترهای اضافه تابع را ارسال می‌کند.

انتگرال روی داده نمونه‌برداری‌شده

گاهی تابع تحلیلی نداریم و فقط مقدارهای ثبت‌شده را داریم. برای این حالت می‌توان از Simpson استفاده کرد:

import numpy as np
from scipy.integrate import simpson

x = np.linspace(
    0,
    10,
    101
)

y = np.sin(x) + 2

area = simpson(
    y=y,
    x=x
)

print(area)

مرتب‌بودن محور X و کیفیت Sampleها روی نتیجه انتگرال عددی اثر دارد.

حل معادله دیفرانسیل با solve_ivp

معادلات دیفرانسیل در مدل‌سازی رشد، تغییر دما، حرکت، واکنش و بسیاری از سیستم‌های پویا استفاده می‌شوند.

معادله ساده کاهش نمایی:

dy/dt = -k × y

کد:

from scipy.integrate import solve_ivp

def decay(
    time,
    value,
    rate
):
    return -rate * value

solution = solve_ivp(
    fun=decay,
    t_span=(0, 10),
    y0=[100],
    args=(0.35,),
    dense_output=True
)

ساخت نقاط زمانی:

time_points = np.linspace(
    0,
    10,
    100
)

values = solution.sol(
    time_points
)[0]

رسم:

fig, ax = plt.subplots(
    figsize=(10, 5),
    layout="constrained"
)

ax.plot(
    time_points,
    values,
    color="#6C4DF6",
    linewidth=2.5
)

ax.set_title("Exponential Decay")
ax.set_xlabel("Time")
ax.set_ylabel("Value")
ax.grid(alpha=0.2)

plt.show()

وضعیت حل را بررسی کنید:

print(solution.success)
print(solution.message)

درون‌یابی با scipy.interpolate

Interpolation برای تخمین مقدار میان نقاط مشاهده‌شده استفاده می‌شود.

کاربردهای رایج:

  • پرکردن فاصله بین Sampleها
  • ساخت منحنی هموار برای نمایش
  • تبدیل داده به Grid منظم
  • تخمین مقدار در زمان‌های ثبت‌نشده
  • Resampling سیگنال

داده نمونه:

import numpy as np

x = np.array([
    0,
    1,
    2,
    4,
    7,
    10
])

y = np.array([
    10,
    12,
    15,
    19,
    18,
    25
])

درون‌یابی خطی با NumPy

برای روش خطی ساده:

new_x = np.linspace(
    0,
    10,
    100
)

linear_y = np.interp(
    new_x,
    x,
    y
)

درون‌یابی Shape-preserving با PCHIP

from scipy.interpolate import (
    PchipInterpolator
)

interpolator = PchipInterpolator(
    x,
    y
)

smooth_y = interpolator(
    new_x
)

رسم:

fig, ax = plt.subplots(
    figsize=(10, 5),
    layout="constrained"
)

ax.scatter(
    x,
    y,
    color="#EF476F",
    s=70,
    label="Observed"
)

ax.plot(
    new_x,
    smooth_y,
    color="#6C4DF6",
    linewidth=2.5,
    label="PCHIP"
)

ax.set_title("Data Interpolation")
ax.legend()
ax.grid(alpha=0.2)

plt.show()

PCHIP برای بسیاری از داده‌ها شکل محلی را بهتر حفظ می‌کند و نسبت به بعضی Splineها کمتر دچار Overshoot می‌شود.

Interpolation برای تخمین داخل بازه داده است. استفاده از آن برای Extrapolation خارج از بازه مشاهده‌شده ریسک خطای بیشتری دارد.

جبر خطی با scipy.linalg

SciPy توابع تخصصی جبر خطی را در scipy.linalg ارائه می‌کند.

حل دستگاه معادلات خطی

دستگاه زیر را در نظر بگیرید:

2x + y = 8
x + 3y = 9

نمایش ماتریسی:

import numpy as np
from scipy.linalg import solve

matrix = np.array([
    [2, 1],
    [1, 3]
])

values = np.array([
    8,
    9
])

solution = solve(
    matrix,
    values
)

print(solution)

اعتبارسنجی جواب:

print(
    matrix @ solution
)

print(values)

به‌جای محاسبه معکوس ماتریس و ضرب آن در بردار، معمولاً استفاده مستقیم از solve دقیق‌تر و کارآمدتر است.

محاسبه مقدار و بردار ویژه

from scipy.linalg import eig

matrix = np.array([
    [4, 2],
    [1, 3]
])

eigenvalues, eigenvectors = eig(
    matrix
)

print(eigenvalues)
print(eigenvectors)

مقدارهای ویژه در تحلیل سیستم‌ها، PCA، مدل‌های پویا و الگوریتم‌های عددی کاربرد دارند.

تجزیه SVD

from scipy.linalg import svd

matrix = np.array([
    [1, 2],
    [3, 4],
    [5, 6]
])

u, singular_values, vt = svd(
    matrix
)

print("U:", u)
print(
    "Singular values:",
    singular_values
)
print("Vt:", vt)

SVD در کاهش بُعد، فشرده‌سازی، حل مسئله Least Squares و تحلیل ماتریس‌ها کاربرد دارد.

آمار با scipy.stats

ماژول scipy.stats شامل موارد زیر است:

  • توزیع‌های احتمال
  • شاخص‌های آماری
  • آزمون فرض
  • آزمون نرمال‌بودن
  • همبستگی
  • Bootstrap
  • آزمون‌های پارامتریک و ناپارامتریک

آمار توصیفی

from scipy import stats
import numpy as np

values = np.array([
    12,
    15,
    13,
    18,
    21,
    17,
    16,
    14
])

description = stats.describe(
    values
)

print(description)

خروجی شامل تعداد نمونه، حداقل، حداکثر، میانگین، واریانس، Skewness و Kurtosis است.

محاسبه Z-score

z_scores = stats.zscore(
    values
)

print(z_scores)

Z-score نشان می‌دهد هر مقدار چند Standard Deviation با میانگین فاصله دارد. مقدار بزرگ Z-score می‌تواند برای بررسی نقاط غیرعادی مفید باشد، اما معیار قطعی برای حذف داده نیست.

آزمون تفاوت میان دو گروه

فرض کنید نرخ پاسخ یا زمان انجام یک فرایند در دو نسخه اندازه‌گیری شده است:

rng = np.random.default_rng(42)

group_a = rng.normal(
    loc=320,
    scale=45,
    size=120
)

group_b = rng.normal(
    loc=300,
    scale=48,
    size=130
)

آزمون Welch:

from scipy.stats import ttest_ind

result = ttest_ind(
    group_a,
    group_b,
    equal_var=False
)

print(
    "Statistic:",
    result.statistic
)

print(
    "P-value:",
    result.pvalue
)

استفاده از equal_var=False آزمون Welch را اجرا می‌کند که برابری واریانس دو گروه را فرض نمی‌کند.

تفسیر P-value باید همراه با موارد زیر باشد:

  • اندازه نمونه
  • اندازه اثر
  • فاصله اطمینان
  • کیفیت جمع‌آوری داده
  • تعدد آزمون‌ها
  • اهمیت عملی اختلاف

P-value به‌تنهایی اندازه یا اهمیت اختلاف را مشخص نمی‌کند.

محاسبه اندازه اثر ساده

mean_difference = (
    group_b.mean()
    - group_a.mean()
)

pooled_scale = np.sqrt(
    (
        group_a.var(
            ddof=1
        )
        + group_b.var(
            ddof=1
        )
    )
    / 2
)

effect_size = (
    mean_difference
    / pooled_scale
)

print(
    "Mean difference:",
    mean_difference
)

print(
    "Effect size:",
    effect_size
)

این محاسبه باید براساس طراحی مطالعه و تعریف مناسب Effect Size انتخاب شود.

آزمون ناپارامتریک Mann–Whitney U

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

from scipy.stats import mannwhitneyu

result = mannwhitneyu(
    group_a,
    group_b,
    alternative="two-sided"
)

print(result.statistic)
print(result.pvalue)

این آزمون دقیقاً «آزمون اختلاف میانگین» نیست و تفسیر آن باید با شناخت فرض‌ها و شکل توزیع انجام شود.

محاسبه همبستگی

Pearson:

from scipy.stats import pearsonr

x = np.array([
    1,
    2,
    3,
    4,
    5,
    6
])

y = np.array([
    2,
    4,
    5,
    8,
    10,
    11
])

result = pearsonr(
    x,
    y
)

print(
    "Correlation:",
    result.statistic
)

print(
    "P-value:",
    result.pvalue
)

Spearman برای رابطه رتبه‌ای یا Monotonic:

from scipy.stats import spearmanr

result = spearmanr(
    x,
    y
)

همبستگی به معنای رابطه علت و معلولی نیست.

پردازش سیگنال با scipy.signal

سیگنال فقط صدای ضبط‌شده نیست. هر داده‌ای که در طول زمان یا یک محور منظم تغییر کند می‌تواند به‌عنوان Signal تحلیل شود:

  • زمان پاسخ API
  • میزان مصرف CPU
  • تعداد درخواست در دقیقه
  • دمای حسگر
  • داده صوتی
  • لرزش
  • فروش روزانه
  • ترافیک سایت

کاهش نویز با Savitzky–Golay

ساخت سیگنال:

import numpy as np
from scipy.signal import savgol_filter

rng = np.random.default_rng(42)

time = np.linspace(
    0,
    20,
    500
)

clean_signal = (
    np.sin(time)
    + 0.35 * np.sin(
        3 * time
    )
)

noisy_signal = (
    clean_signal
    + rng.normal(
        0,
        0.22,
        size=len(time)
    )
)

smoothed_signal = savgol_filter(
    noisy_signal,
    window_length=31,
    polyorder=3
)

رسم:

fig, ax = plt.subplots(
    figsize=(12, 5),
    layout="constrained"
)

ax.plot(
    time,
    noisy_signal,
    alpha=0.4,
    label="Noisy"
)

ax.plot(
    time,
    smoothed_signal,
    color="#6C4DF6",
    linewidth=2.5,
    label="Smoothed"
)

ax.set_title("Signal Smoothing")
ax.set_xlabel("Time")
ax.set_ylabel("Value")
ax.legend()
ax.grid(alpha=0.2)

plt.show()

window_length باید عددی فرد و متناسب با تعداد Sampleها باشد. پنجره بسیار بزرگ می‌تواند تغییرات واقعی را حذف کند.

پیداکردن قله‌ها با find_peaks

from scipy.signal import find_peaks

peaks, properties = find_peaks(
    smoothed_signal,
    prominence=0.5,
    distance=30
)

print(peaks)

رسم قله‌ها:

fig, ax = plt.subplots(
    figsize=(12, 5),
    layout="constrained"
)

ax.plot(
    time,
    smoothed_signal,
    color="#6C4DF6"
)

ax.scatter(
    time[peaks],
    smoothed_signal[peaks],
    color="#EF476F",
    s=65,
    label="Peaks"
)

ax.legend()
ax.grid(alpha=0.2)

plt.show()

پارامترهای مهم:

  • height: حداقل ارتفاع
  • distance: حداقل فاصله میان قله‌ها
  • prominence: میزان برجستگی قله
  • width: حداقل یا حداکثر عرض قله

انتخاب این پارامترها باید براساس واحد و منطق داده انجام شود.

تبدیل فوریه با scipy.fft

تبدیل فوریه کمک می‌کند فرکانس‌های موجود در یک سیگنال را بررسی کنیم.

from scipy.fft import (
    rfft,
    rfftfreq
)

sample_rate = 100
duration = 5

time = np.arange(
    0,
    duration,
    1 / sample_rate
)

signal_values = (
    np.sin(
        2 * np.pi * 5 * time
    )
    + 0.5 * np.sin(
        2 * np.pi * 12 * time
    )
)

محاسبه FFT:

spectrum = np.abs(
    rfft(signal_values)
)

frequencies = rfftfreq(
    len(signal_values),
    d=1 / sample_rate
)

رسم:

fig, ax = plt.subplots(
    figsize=(10, 5),
    layout="constrained"
)

ax.plot(
    frequencies,
    spectrum,
    color="#6C4DF6"
)

ax.set_xlim(0, 30)
ax.set_title("Frequency Spectrum")
ax.set_xlabel("Frequency")
ax.set_ylabel("Amplitude")
ax.grid(alpha=0.2)

plt.show()

در نمودار باید قله‌هایی نزدیک فرکانس‌های ۵ و ۱۲ مشاهده شود.

ماتریس Sparse با scipy.sparse

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

برای مثال:

  • ماتریس واژه و سند
  • ویژگی‌های One-hot
  • داده تعامل کاربر و محصول
  • گراف بزرگ
  • ماتریس توصیه‌گر
  • خروجی Bag of Words یا TF-IDF

ذخیره تمام صفرها حافظه زیادی مصرف می‌کند. ماتریس Sparse فقط مقدارهای غیرصفر و موقعیت آن‌ها را نگهداری می‌کند.

ساخت ماتریس CSR

import numpy as np
from scipy.sparse import csr_matrix

dense_matrix = np.array([
    [0, 0, 4, 0],
    [1, 0, 0, 0],
    [0, 2, 0, 3],
    [0, 0, 0, 5]
])

sparse_matrix = csr_matrix(
    dense_matrix
)

print(sparse_matrix)

تعداد مقدارهای غیرصفر:

print(
    sparse_matrix.nnz
)

Shape:

print(
    sparse_matrix.shape
)

تبدیل به Dense:

restored = (
    sparse_matrix.toarray()
)

print(restored)

برای ماتریس بسیار بزرگ، تبدیل کامل Sparse به Dense ممکن است حافظه زیادی مصرف کند و باید با احتیاط انجام شود.

عملیات روی ماتریس Sparse

vector = np.array([
    1,
    2,
    3,
    4
])

result = (
    sparse_matrix @ vector
)

print(result)

بسیاری از الگوریتم‌های Scikit-learn می‌توانند مستقیم با ماتریس Sparse کار کنند.

محاسبات فضایی با scipy.spatial

ماژول scipy.spatial برای فاصله، نزدیک‌ترین همسایه و ساختارهای فضایی کاربرد دارد.

محاسبه فاصله نقاط

from scipy.spatial.distance import (
    cdist
)

users = np.array([
    [1.0, 2.0],
    [2.5, 3.0],
    [7.0, 8.0]
])

centers = np.array([
    [0.0, 0.0],
    [5.0, 5.0]
])

distances = cdist(
    users,
    centers,
    metric="euclidean"
)

print(distances)

هر سطر فاصله یک کاربر تا تمام Centerها را نشان می‌دهد.

نزدیک‌ترین همسایه با KDTree

from scipy.spatial import KDTree

points = np.array([
    [1, 2],
    [2, 3],
    [4, 5],
    [8, 8],
    [9, 10]
])

tree = KDTree(
    points
)

distance, index = tree.query(
    [3.8, 4.7]
)

print("Distance:", distance)
print(
    "Nearest point:",
    points[index]
)

KDTree برای داده‌های کم‌بُعد مناسب است. در فضاهای بسیار پربُعد، کارایی و معنای فاصله باید جداگانه ارزیابی شود.

پروژه عملی: تحلیل زمان پاسخ API

در این پروژه یک مجموعه داده زمان پاسخ می‌سازیم و با SciPy موارد زیر را بررسی می‌کنیم:

  • میانگین و Percentileهای Latency
  • هموارسازی نویز
  • شناسایی Spikeها
  • مقایسه دو بازه
  • تشخیص فرکانس‌های احتمالی
  • ساخت خلاصه برای تحلیل هوش مصنوعی

مرحله اول: ساخت داده

import numpy as np
import pandas as pd

rng = np.random.default_rng(42)

sample_count = 1440

timestamps = pd.date_range(
    "2026-01-01",
    periods=sample_count,
    freq="min"
)

baseline = (
    280
    + 25 * np.sin(
        np.linspace(
            0,
            8 * np.pi,
            sample_count
        )
    )
)

noise = rng.normal(
    0,
    18,
    sample_count
)

latency = baseline + noise

spike_positions = rng.choice(
    sample_count,
    size=18,
    replace=False
)

latency[spike_positions] += (
    rng.integers(
        180,
        450,
        size=len(spike_positions)
    )
)

df = pd.DataFrame({
    "timestamp": timestamps,
    "latency_ms": latency
})

مرحله دوم: پاک‌سازی

df["timestamp"] = pd.to_datetime(
    df["timestamp"],
    errors="coerce"
)

df["latency_ms"] = pd.to_numeric(
    df["latency_ms"],
    errors="coerce"
)

df = (
    df.dropna(
        subset=[
            "timestamp",
            "latency_ms"
        ]
    )
    .sort_values("timestamp")
    .drop_duplicates(
        subset=["timestamp"]
    )
)

مرحله سوم: هموارسازی

from scipy.signal import (
    savgol_filter
)

df["smoothed_latency"] = (
    savgol_filter(
        df["latency_ms"],
        window_length=31,
        polyorder=3
    )
)

مرحله چهارم: پیداکردن Spikeها

برای تشخیص Spike بهتر است روی تفاوت داده خام و Baseline هموارشده کار کنیم:

residual = (
    df["latency_ms"]
    - df["smoothed_latency"]
)

from scipy.signal import find_peaks

peaks, properties = find_peaks(
    residual.to_numpy(),
    prominence=100,
    distance=10
)

spikes = df.iloc[peaks].copy()

spikes["prominence"] = (
    properties["prominences"]
)

print(spikes.head())

مرحله پنجم: محاسبه شاخص‌ها

latency_values = (
    df["latency_ms"]
    .to_numpy()
)

summary = {
    "sample_count": int(
        len(df)
    ),
    "mean_latency_ms": float(
        np.mean(latency_values)
    ),
    "median_latency_ms": float(
        np.median(latency_values)
    ),
    "p95_latency_ms": float(
        np.percentile(
            latency_values,
            95
        )
    ),
    "p99_latency_ms": float(
        np.percentile(
            latency_values,
            99
        )
    ),
    "minimum_latency_ms": float(
        np.min(latency_values)
    ),
    "maximum_latency_ms": float(
        np.max(latency_values)
    ),
    "detected_spikes": int(
        len(spikes)
    )
}

مرحله ششم: مقایسه نیمه اول و دوم

middle = len(df) // 2

first_half = (
    df.iloc[:middle][
        "latency_ms"
    ]
    .to_numpy()
)

second_half = (
    df.iloc[middle:][
        "latency_ms"
    ]
    .to_numpy()
)

from scipy.stats import ttest_ind

comparison = ttest_ind(
    first_half,
    second_half,
    equal_var=False
)

summary[
    "first_half_mean_ms"
] = float(
    first_half.mean()
)

summary[
    "second_half_mean_ms"
] = float(
    second_half.mean()
)

summary[
    "comparison_pvalue"
] = float(
    comparison.pvalue
)

این مقایسه فقط یک مثال آموزشی است. برای داده زمانی واقعی، استقلال Observationها، روند زمانی، Seasonality و Autocorrelation باید بررسی شوند.

مرحله هفتم: رسم نتیجه

import matplotlib.pyplot as plt

fig, ax = plt.subplots(
    figsize=(14, 6),
    layout="constrained"
)

ax.plot(
    df["timestamp"],
    df["latency_ms"],
    color="#AEB4C0",
    alpha=0.55,
    linewidth=1,
    label="Observed"
)

ax.plot(
    df["timestamp"],
    df["smoothed_latency"],
    color="#6C4DF6",
    linewidth=2.5,
    label="Smoothed"
)

ax.scatter(
    spikes["timestamp"],
    spikes["latency_ms"],
    color="#EF476F",
    s=45,
    label="Detected spikes",
    zorder=3
)

ax.set_title(
    "API Latency Analysis"
)

ax.set_xlabel("Time")
ax.set_ylabel("Latency (ms)")
ax.legend()
ax.grid(alpha=0.2)

fig.savefig(
    "api-latency-analysis.png",
    dpi=170,
    bbox_inches="tight",
    facecolor="white"
)

plt.show()

اتصال SciPy به هوش مصنوعی درواره

SciPy برای محاسبات قطعی و آماری استفاده می‌شود. هوش مصنوعی می‌تواند نتیجه محاسبه‌شده را توضیح دهد، اما نباید جایگزین محاسبات عددی شود.

فرایند پیشنهادی:

  1. داده با Pandas پاک‌سازی شود
  2. شاخص‌های عددی با NumPy و SciPy محاسبه شوند
  3. نمودار با Matplotlib یا Plotly ساخته شود
  4. فقط خلاصه لازم به مدل ارسال شود
  5. مدل براساس اعداد موجود، گزارش متنی تولید کند

برای استفاده از مدل‌های مختلف می‌توانید در درواره ثبت‌نام کنید. فهرست مدل‌ها و قیمت به‌روز آن‌ها در صفحه مدل‌های درواره قرار دارد.

نگهداری API Key

در Linux یا macOS:

export DARVAREH_API_KEY="YOUR_DARVAREH_API_KEY"

در PowerShell:

$env:DARVAREH_API_KEY="YOUR_DARVAREH_API_KEY"

ارسال خلاصه تحلیل به API درواره

import json
import os
import requests

response = requests.post(
    "https://api.darvareh.ir/v1/chat/completions",
    headers={
        "Authorization": (
            f"Bearer "
            f"{os.environ['DARVAREH_API_KEY']}"
        ),
        "Content-Type": "application/json"
    },
    json={
        "model": "YOUR_MODEL_ID",
        "messages": [
            {
                "role": "system",
                "content": (
                    "تو یک دستیار تحلیل داده هستی. "
                    "فقط از اعداد ورودی استفاده کن. "
                    "هیچ عدد یا علت جدیدی نساز. "
                    "نتیجه آزمون آماری را با احتیاط "
                    "و بدون ادعای علت و معلول توضیح بده."
                )
            },
            {
                "role": "user",
                "content": (
                    "این خلاصه تحلیل زمان پاسخ API "
                    "را بررسی کن. چهار مشاهده مهم، "
                    "سه پیشنهاد برای بررسی فنی بیشتر "
                    "و یک خلاصه مدیریتی کوتاه بنویس."
                    "\n\n"
                    + json.dumps(
                        summary,
                        ensure_ascii=False
                    )
                )
            }
        ],
        "temperature": 0.2
    },
    timeout=60
)

response.raise_for_status()

result = response.json()

print(
    result["choices"][0]
          ["message"]
          ["content"]
)

در این معماری، مدل به داده خام یا تمام Logها دسترسی ندارد. فقط شاخص‌های انتخاب‌شده و محاسبه‌شده را دریافت می‌کند.

تولید پیشنهاد تحلیل با هوش مصنوعی

Schema داده:

schema = {
    "timestamp": (
        "زمان ثبت اندازه‌گیری"
    ),
    "latency_ms": (
        "زمان پاسخ برحسب میلی‌ثانیه"
    ),
    "status": (
        "وضعیت درخواست"
    ),
    "model": (
        "مدل استفاده‌شده"
    ),
    "input_tokens": (
        "تعداد توکن ورودی"
    ),
    "output_tokens": (
        "تعداد توکن خروجی"
    )
}

پرامپت پیشنهادی:

برای داده‌ای با ستون‌های معرفی‌شده، یک برنامه تحلیل با Pandas و SciPy پیشنهاد بده.

برای هر مرحله مشخص کن:
1. چه پاک‌سازی‌ای لازم است
2. چه شاخصی باید محاسبه شود
3. از کدام تابع SciPy استفاده شود
4. چه فرضی باید بررسی شود
5. چه نموداری مناسب است
6. چه خطای تفسیری ممکن است رخ دهد

عدد اختراع نکن و فقط روی طراحی تحلیل تمرکز کن.

پیشنهاد مدل باید پیش از اجرا بررسی شود؛ به‌خصوص وقتی انتخاب آزمون آماری به ساختار داده وابسته است.

ساخت تابع قابل استفاده مجدد برای تشخیص Spike

import numpy as np
import pandas as pd
from scipy.signal import (
    find_peaks,
    savgol_filter
)

def detect_spikes(
    values,
    window_length=31,
    polyorder=3,
    prominence=100,
    distance=10
):
    array = np.asarray(
        values,
        dtype=float
    )

    if array.ndim != 1:
        raise ValueError(
            "values must be one-dimensional"
        )

    if len(array) < window_length:
        raise ValueError(
            "window_length is larger "
            "than the input data"
        )

    if window_length % 2 == 0:
        raise ValueError(
            "window_length must be odd"
        )

    smoothed = savgol_filter(
        array,
        window_length=window_length,
        polyorder=polyorder
    )

    residual = array - smoothed

    indices, properties = find_peaks(
        residual,
        prominence=prominence,
        distance=distance
    )

    result = pd.DataFrame({
        "index": indices,
        "value": array[indices],
        "baseline": smoothed[indices],
        "residual": residual[indices],
        "prominence": (
            properties["prominences"]
        )
    })

    return result, smoothed

استفاده:

spike_table, baseline = detect_spikes(
    df["latency_ms"],
    window_length=31,
    prominence=100,
    distance=10
)

print(spike_table.head())

تست تابع تشخیص Spike

def test_detect_spikes():
    values = np.full(
        101,
        100.0
    )

    values[50] = 400.0

    spikes, baseline = detect_spikes(
        values,
        window_length=11,
        prominence=100,
        distance=5
    )

    assert len(spikes) == 1
    assert spikes.iloc[0]["index"] == 50
    assert len(baseline) == len(values)

با تست می‌توان رفتار تابع را روی ورودی کنترل‌شده بررسی کرد.

بهینه‌سازی کارایی SciPy

استفاده از آرایه NumPy

values = (
    df["value"]
    .to_numpy(
        dtype=float
    )
)

پرهیز از حلقه پایتون

به‌جای:

result = []

for value in values:
    result.append(
        value ** 2
    )

از محاسبه برداری استفاده کنید:

result = values ** 2

استفاده از ماتریس Sparse

اگر بیشتر مقدارهای ماتریس صفر است، آن را Dense نگهداری نکنید.

بررسی Dtype

در بعضی مسائل، float64 برای پایداری عددی لازم است:

values = np.asarray(
    values,
    dtype=np.float64
)

پرهیز از تبدیل غیرضروری

تبدیل مکرر میان DataFrame، List و Array هزینه پردازشی ایجاد می‌کند.

محدودکردن داده برای رسم

محاسبات می‌توانند روی داده کامل انجام شوند، اما برای Scatter Plot شاید نمونه‌برداری کافی باشد.

خطاهای رایج SciPy

خطای نصب نبودن SciPy

ModuleNotFoundError: No module named 'scipy'

راه‌حل:

python -m pip install scipy

نصب در محیط پایتون اشتباه

مسیر مفسر را بررسی کنید:

python -c "import sys; print(sys.executable)"

سپس:

python -m pip install scipy

خطای ناسازگاری NumPy و SciPy

بسته‌ها را داخل محیط مجازی به‌روزرسانی کنید:

python -m pip install --upgrade numpy scipy

در پروژه Production بهتر است نسخه‌ها را پس از تست Pin کنید.

موفق نبودن Optimization

if not result.success:
    print(result.message)

موارد زیر را بررسی کنید:

  • نقطه شروع
  • Bounds
  • Constraintها
  • Scale متغیرها
  • تعریف تابع
  • وجود مقدار NaN یا Infinite
  • انتخاب Method مناسب

دریافت NaN

print(
    np.isnan(values).sum()
)

print(
    np.isinf(values).sum()
)

پاک‌سازی:

clean_values = values[
    np.isfinite(values)
]

خطای Savitzky–Golay

window_length باید:

  • فرد باشد
  • از طول داده بیشتر نباشد
  • از polyorder بزرگ‌تر باشد

نتیجه عجیب Interpolation

بررسی کنید:

  • محور X مرتب باشد
  • مقدار تکراری در X وجود نداشته باشد
  • داده Missing نداشته باشد
  • روش Interpolation با مسئله سازگار باشد

مصرف حافظه زیاد در Sparse

احتمالاً ماتریس Sparse را با toarray() به Dense تبدیل کرده‌اید. قبل از این کار، اندازه احتمالی آرایه Dense را محاسبه کنید.

اشتباهات تحلیلی رایج

انتخاب Solver بدون شناخت مسئله

هر Method برای نوع خاصی از تابع و Constraint مناسب است.

اعتماد به success=True بدون اعتبارسنجی

Solver ممکن است مسئله تعریف‌شده را حل کرده باشد، اما خود تابع هدف یا Constraintها اشتباه باشند.

استفاده از آزمون آماری بدون بررسی فرض‌ها

نوع داده، استقلال نمونه‌ها، شکل توزیع و طراحی آزمایش روی انتخاب آزمون اثر دارند.

یکی دانستن Statistical Significance و اهمیت عملی

یک اختلاف کوچک با نمونه بزرگ ممکن است P-value کمی داشته باشد، اما از نظر عملی مهم نباشد.

حذف خودکار داده پرت

داده پرت می‌تواند خطای ثبت، رویداد واقعی یا مهم‌ترین Observation مجموعه داده باشد.

استفاده از Interpolation به‌عنوان پیش‌بینی

Interpolation داخل محدوده داده انجام می‌شود. Extrapolation مسئله متفاوت و معمولاً پرریسک‌تری است.

هموارسازی بیش از حد Signal

فیلتر شدید می‌تواند Spike یا تغییر واقعی را حذف کند.

تفسیر همبستگی به‌عنوان علیت

محاسبه Pearson یا Spearman دلیل ایجاد رابطه را مشخص نمی‌کند.

چک‌لیست استفاده حرفه‌ای از SciPy

  • مسئله و خروجی موردانتظار مشخص شده است
  • نوع داده‌ها بررسی شده است
  • مقدارهای NaN و Infinite کنترل شده‌اند
  • واحد متغیرها یکسان است
  • Scale متغیرهای Optimization بررسی شده است
  • Bounds و Constraintها منطق واقعی دارند
  • وضعیت موفقیت Solver کنترل شده است
  • نتیجه با یک روش مستقل اعتبارسنجی شده است
  • فرض‌های آزمون آماری بررسی شده‌اند
  • اندازه اثر کنار P-value گزارش شده است
  • پارامترهای فیلتر براساس داده انتخاب شده‌اند
  • Interpolation از Extrapolation تفکیک شده است
  • ماتریس Sparse بی‌دلیل به Dense تبدیل نشده است
  • Seed داده تصادفی ثبت شده است
  • نسخه وابستگی‌ها در Production مشخص است
  • محاسبات قطعی به مدل زبانی واگذار نشده است
  • خلاصه ارسالی به هوش مصنوعی از قبل اعتبارسنجی شده است

پرسش‌های متداول

SciPy چیست؟

SciPy یک کتابخانه پایتون برای محاسبات علمی است که ابزارهایی برای بهینه‌سازی، آمار، انتگرال‌گیری، جبر خطی، پردازش سیگنال، ماتریس Sparse و محاسبات فضایی ارائه می‌کند.

تفاوت NumPy و SciPy چیست؟

NumPy ابزار اصلی کار با آرایه و محاسبات برداری است. SciPy روی NumPy ساخته شده و الگوریتم‌های تخصصی علمی و عددی ارائه می‌دهد.

آیا برای یادگیری SciPy باید NumPy بلد باشیم؟

آشنایی با Array، Shape، Dtype، Indexing و محاسبات برداری NumPy کمک زیادی می‌کند؛ زیرا بیشتر توابع SciPy با آرایه‌های NumPy کار می‌کنند.

SciPy در Machine Learning چه کاربردی دارد؟

SciPy در Optimization، ماتریس‌های Sparse، محاسبه فاصله، آمار، جبر خطی و پردازش داده استفاده می‌شود. برخی کتابخانه‌های Machine Learning نیز به آن وابسته‌اند.

چگونه یک تابع را با SciPy بهینه کنیم؟

برای تابع تک‌متغیره از minimize_scalar و برای مسائل چندمتغیره از minimize استفاده می‌شود. انتخاب Method به نوع تابع و Constraintها بستگی دارد.

چگونه با SciPy آزمون t اجرا کنیم؟

برای دو گروه مستقل می‌توان از ttest_ind استفاده کرد:

result = ttest_ind(
    group_a,
    group_b,
    equal_var=False
)

انتخاب آزمون باید براساس طراحی داده و فرض‌های آماری باشد.

ماتریس Sparse چیست؟

ماتریسی است که بیشتر مقدارهای آن صفر است. ساختار Sparse فقط مقدارهای غیرصفر و موقعیت آن‌ها را ذخیره می‌کند و می‌تواند مصرف حافظه را کاهش دهد.

چگونه نویز یک Signal را کاهش دهیم؟

یکی از روش‌ها استفاده از savgol_filter است. پارامتر پنجره و درجه Polynomial باید متناسب با داده انتخاب شود.

آیا SciPy جایگزین Pandas است؟

خیر. Pandas برای مدیریت، پاک‌سازی و GroupBy داده جدولی مناسب است. SciPy الگوریتم‌های علمی و آماری را ارائه می‌دهد.

چگونه SciPy را به هوش مصنوعی متصل کنیم؟

محاسبات را با SciPy انجام دهید، نتیجه را به یک Dictionary یا JSON خلاصه تبدیل کنید و آن را برای توضیح متنی به API درواره بفرستید.

جمع‌بندی

SciPy یکی از مهم‌ترین اجزای اکوسیستم علمی پایتون است. این کتابخانه فاصله میان آرایه‌های NumPy و الگوریتم‌های تخصصی مهندسی، آماری و عددی را پر می‌کند.

با SciPy می‌توان:

  • تابع را بهینه کرد
  • ریشه معادله را پیدا کرد
  • منحنی را روی داده برازش داد
  • انتگرال را عددی محاسبه کرد
  • معادله دیفرانسیل را حل کرد
  • داده را Interpolate کرد
  • آزمون آماری اجرا کرد
  • Signal را فیلتر و تحلیل کرد
  • ماتریس Sparse ساخت
  • فاصله و نزدیک‌ترین همسایه را محاسبه کرد

در یک پروژه تحلیل داده و هوش مصنوعی، تقسیم مسئولیت مناسب چنین است:

  • Pandas برای خواندن و پاک‌سازی داده
  • NumPy برای آرایه و محاسبات برداری
  • SciPy برای الگوریتم‌های علمی و آماری
  • Matplotlib، Seaborn یا Plotly برای مصورسازی
  • مدل زبانی برای توضیح و تولید گزارش
  • درواره برای دسترسی API یکپارچه به مدل موردنیاز

برای شروع استفاده از مدل‌های هوش مصنوعی، در درواره ثبت‌نام کنید، API Key بگیرید و مدل مناسب پروژه را از صفحه مدل‌ها و قیمت‌ها انتخاب کنید.

مقالات مرتبط

برای مطالعه شرایط استفاده و محدودیت‌های مسئولیت، صفحه «سلب مسئولیت» را مشاهده کنید.

Read more

اتوماسیون هوش مصنوعی چیست؟ کاربردها و آموزش ساخت AI Automation

اتوماسیون هوش مصنوعی چیست؟ کاربردها و آموزش ساخت AI Automation

اتوماسیون هوش مصنوعی با ترکیب گردش‌کارهای خودکار و مدل‌های هوش مصنوعی، پردازش متن، دسته‌بندی، استخراج اطلاعات و تصمیم‌های پیشنهادی را خودکار می‌کند. در این راهنما، معماری و ساخت نمونه عملی آن با API درواره را می‌آموزید.

Agentic Commerce چیست؟ آینده خرید با ایجنت هوش مصنوعی

Agentic Commerce چیست؟ آینده خرید با ایجنت هوش مصنوعی

Agentic Commerce شیوه‌ای جدید برای خرید اینترنتی است که در آن ایجنت هوش مصنوعی می‌تواند نیاز کاربر را بفهمد، محصولات را جست‌وجو و مقایسه کند و فرایند خرید را پیش ببرد. در این راهنما با معماری، UCP، ACP و پیاده‌سازی آن با API درواره آشنا می‌شوید.