SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್

SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್

SciPy (ಸೈ ಪೈ ಎಂದು ಉಚ್ಚರಿಸಲಾಗುತ್ತದೆ) ನಂಬಿ ಪೈಥಾನ್ ವಿಸ್ತರಣೆಯ ಆಧಾರದ ಮೇಲೆ ಗಣಿತದ ಅಪ್ಲಿಕೇಶನ್ ಪ್ಯಾಕೇಜ್ ಆಗಿದೆ. SciPy ಯೊಂದಿಗೆ, ನಿಮ್ಮ ಸಂವಾದಾತ್ಮಕ ಪೈಥಾನ್ ಸೆಶನ್ MATLAB, IDL, Octave, R-Lab, ಮತ್ತು SciLab ನಂತಹ ಸಂಪೂರ್ಣ ಡೇಟಾ ವಿಜ್ಞಾನ ಮತ್ತು ಸಂಕೀರ್ಣ ಸಿಸ್ಟಮ್ ಪ್ರೊಟೊಟೈಪಿಂಗ್ ಪರಿಸರವಾಗುತ್ತದೆ. ಇಂದು ನಾನು scipy.optimize ಪ್ಯಾಕೇಜ್‌ನಲ್ಲಿ ಕೆಲವು ಪ್ರಸಿದ್ಧ ಆಪ್ಟಿಮೈಸೇಶನ್ ಅಲ್ಗಾರಿದಮ್‌ಗಳನ್ನು ಹೇಗೆ ಬಳಸುವುದು ಎಂಬುದರ ಕುರಿತು ಸಂಕ್ಷಿಪ್ತವಾಗಿ ಮಾತನಾಡಲು ಬಯಸುತ್ತೇನೆ. ಕಾರ್ಯಗಳನ್ನು ಬಳಸುವಲ್ಲಿ ಹೆಚ್ಚು ವಿವರವಾದ ಮತ್ತು ನವೀಕೃತ ಸಹಾಯವನ್ನು ಯಾವಾಗಲೂ ಸಹಾಯ() ಆಜ್ಞೆಯನ್ನು ಬಳಸಿ ಅಥವಾ Shift+Tab ಬಳಸಿ ಪಡೆಯಬಹುದು.

ಪರಿಚಯ

ಪ್ರಾಥಮಿಕ ಮೂಲಗಳನ್ನು ಹುಡುಕುವುದರಿಂದ ಮತ್ತು ಓದುವುದರಿಂದ ನಿಮ್ಮನ್ನು ಮತ್ತು ಓದುಗರನ್ನು ಉಳಿಸಲು, ವಿಧಾನಗಳ ವಿವರಣೆಗಳಿಗೆ ಲಿಂಕ್‌ಗಳು ಮುಖ್ಯವಾಗಿ ವಿಕಿಪೀಡಿಯಾದಲ್ಲಿರುತ್ತವೆ. ನಿಯಮದಂತೆ, ಈ ಮಾಹಿತಿಯು ಸಾಮಾನ್ಯ ನಿಯಮಗಳಲ್ಲಿ ವಿಧಾನಗಳನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳಲು ಮತ್ತು ಅವರ ಅಪ್ಲಿಕೇಶನ್ಗೆ ಪರಿಸ್ಥಿತಿಗಳನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳಲು ಸಾಕಾಗುತ್ತದೆ. ಗಣಿತದ ವಿಧಾನಗಳ ಸಾರವನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳಲು, ಪ್ರತಿ ಲೇಖನದ ಕೊನೆಯಲ್ಲಿ ಅಥವಾ ನಿಮ್ಮ ನೆಚ್ಚಿನ ಹುಡುಕಾಟ ಎಂಜಿನ್‌ನಲ್ಲಿ ಕಂಡುಬರುವ ಹೆಚ್ಚು ಅಧಿಕೃತ ಪ್ರಕಟಣೆಗಳಿಗೆ ಲಿಂಕ್‌ಗಳನ್ನು ಅನುಸರಿಸಿ.

ಆದ್ದರಿಂದ, scipy.optimize ಮಾಡ್ಯೂಲ್ ಈ ಕೆಳಗಿನ ಕಾರ್ಯವಿಧಾನಗಳ ಅನುಷ್ಠಾನವನ್ನು ಒಳಗೊಂಡಿದೆ:

  1. ವಿವಿಧ ಅಲ್ಗಾರಿದಮ್‌ಗಳನ್ನು (ನೆಲ್ಡರ್-ಮೀಡ್ ಸಿಂಪ್ಲೆಕ್ಸ್, BFGS, ನ್ಯೂಟನ್ ಕಾಂಜುಗೇಟ್ ಗ್ರೇಡಿಯಂಟ್‌ಗಳು, ಕೋಬಿಲಾ и SLSQP)
  2. ಜಾಗತಿಕ ಆಪ್ಟಿಮೈಸೇಶನ್ (ಉದಾಹರಣೆಗೆ: ಬೇಸಿನ್ಹಾಪಿಂಗ್, ವ್ಯತ್ಯಾಸ_ವಿಕಾಸ)
  3. ಉಳಿಕೆಗಳನ್ನು ಕಡಿಮೆಗೊಳಿಸುವುದು MNC (ಕನಿಷ್ಠ_ಚೌಕಗಳು) ಮತ್ತು ರೇಖಾತ್ಮಕವಲ್ಲದ ಕನಿಷ್ಠ ಚೌಕಗಳನ್ನು (ಕರ್ವ್_ಫಿಟ್) ಬಳಸುವ ಕರ್ವ್ ಫಿಟ್ಟಿಂಗ್ ಅಲ್ಗಾರಿದಮ್‌ಗಳು
  4. ಒಂದು ವೇರಿಯೇಬಲ್‌ನ ಸ್ಕೇಲಾರ್ ಕಾರ್ಯಗಳನ್ನು ಕಡಿಮೆಗೊಳಿಸುವುದು (ಮಿನಿಮ್_ಸ್ಕೇಲಾರ್) ಮತ್ತು ರೂಟ್‌ಗಳಿಗಾಗಿ ಹುಡುಕುವುದು (ರೂಟ್_ಸ್ಕೇಲರ್)
  5. ವಿವಿಧ ಕ್ರಮಾವಳಿಗಳನ್ನು (ಹೈಬ್ರಿಡ್ ಪೊವೆಲ್,) ಬಳಸಿಕೊಂಡು ಸಮೀಕರಣಗಳ ವ್ಯವಸ್ಥೆಯ (ರೂಟ್) ಬಹು ಆಯಾಮದ ಪರಿಹಾರಕ ಲೆವೆನ್ಬರ್ಗ್-ಮಾರ್ಕ್ವಾರ್ಡ್ಟ್ ಅಥವಾ ದೊಡ್ಡ ಪ್ರಮಾಣದ ವಿಧಾನಗಳು ನ್ಯೂಟನ್-ಕ್ರಿಲೋವ್).

ಈ ಲೇಖನದಲ್ಲಿ ನಾವು ಈ ಸಂಪೂರ್ಣ ಪಟ್ಟಿಯಿಂದ ಮೊದಲ ಐಟಂ ಅನ್ನು ಮಾತ್ರ ಪರಿಗಣಿಸುತ್ತೇವೆ.

ಹಲವಾರು ವೇರಿಯಬಲ್‌ಗಳ ಸ್ಕೇಲಾರ್ ಫಂಕ್ಷನ್‌ನ ಬೇಷರತ್ತಾದ ಕನಿಷ್ಠೀಕರಣ

scipy.optimize ಪ್ಯಾಕೇಜ್‌ನಿಂದ ಕನಿಷ್ಠ ಕಾರ್ಯವು ಹಲವಾರು ವೇರಿಯಬಲ್‌ಗಳ ಸ್ಕೇಲಾರ್ ಫಂಕ್ಷನ್‌ಗಳ ಷರತ್ತುಬದ್ಧ ಮತ್ತು ಬೇಷರತ್ತಾದ ಕಡಿಮೆಗೊಳಿಸುವಿಕೆಯ ಸಮಸ್ಯೆಗಳನ್ನು ಪರಿಹರಿಸಲು ಸಾಮಾನ್ಯ ಇಂಟರ್ಫೇಸ್ ಅನ್ನು ಒದಗಿಸುತ್ತದೆ. ಇದು ಹೇಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ ಎಂಬುದನ್ನು ಪ್ರದರ್ಶಿಸಲು, ನಮಗೆ ಹಲವಾರು ವೇರಿಯೇಬಲ್‌ಗಳ ಸೂಕ್ತವಾದ ಕಾರ್ಯದ ಅಗತ್ಯವಿದೆ, ಅದನ್ನು ನಾವು ವಿಭಿನ್ನ ರೀತಿಯಲ್ಲಿ ಕಡಿಮೆ ಮಾಡುತ್ತೇವೆ.

ಈ ಉದ್ದೇಶಗಳಿಗಾಗಿ, N ಅಸ್ಥಿರಗಳ ರೋಸೆನ್‌ಬ್ರಾಕ್ ಕಾರ್ಯವು ಪರಿಪೂರ್ಣವಾಗಿದೆ, ಇದು ರೂಪವನ್ನು ಹೊಂದಿದೆ:

SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್

ರೋಸೆನ್‌ಬ್ರಾಕ್ ಕಾರ್ಯ ಮತ್ತು ಅದರ ಜಾಕೋಬಿ ಮತ್ತು ಹೆಸ್ಸಿಯನ್ ಮ್ಯಾಟ್ರಿಸಸ್ (ಕ್ರಮವಾಗಿ ಮೊದಲ ಮತ್ತು ಎರಡನೆಯ ಉತ್ಪನ್ನಗಳು) ಈಗಾಗಲೇ scipy.optimize ಪ್ಯಾಕೇಜ್‌ನಲ್ಲಿ ವ್ಯಾಖ್ಯಾನಿಸಲಾಗಿದೆ ಎಂಬ ಅಂಶದ ಹೊರತಾಗಿಯೂ, ನಾವು ಅದನ್ನು ನಾವೇ ವ್ಯಾಖ್ಯಾನಿಸುತ್ತೇವೆ.

import numpy as np

def rosen(x):
    """The Rosenbrock function"""
    return np.sum(100.0*(x[1:]-x[:-1]**2.0)**2.0 + (1-x[:-1])**2.0, axis=0)

ಸ್ಪಷ್ಟತೆಗಾಗಿ, ಎರಡು ಅಸ್ಥಿರಗಳ ರೋಸೆನ್‌ಬ್ರಾಕ್ ಕಾರ್ಯದ ಮೌಲ್ಯಗಳನ್ನು 3D ಯಲ್ಲಿ ಸೆಳೆಯೋಣ.

ಡ್ರಾಯಿಂಗ್ ಕೋಡ್

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter

# Настраиваем 3D график
fig = plt.figure(figsize=[15, 10])
ax = fig.gca(projection='3d')

# Задаем угол обзора
ax.view_init(45, 30)

# Создаем данные для графика
X = np.arange(-2, 2, 0.1)
Y = np.arange(-1, 3, 0.1)
X, Y = np.meshgrid(X, Y)
Z = rosen(np.array([X,Y]))

# Рисуем поверхность
surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm)
plt.show()

SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್

ಕನಿಷ್ಠ 0 ನಲ್ಲಿ ಎಂದು ಮುಂಚಿತವಾಗಿ ತಿಳಿದಿರುವುದು SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್, ವಿವಿಧ scipy.optimize ಕಾರ್ಯವಿಧಾನಗಳನ್ನು ಬಳಸಿಕೊಂಡು ರೋಸೆನ್‌ಬ್ರಾಕ್ ಕಾರ್ಯದ ಕನಿಷ್ಠ ಮೌಲ್ಯವನ್ನು ಹೇಗೆ ನಿರ್ಧರಿಸುವುದು ಎಂಬುದರ ಉದಾಹರಣೆಗಳನ್ನು ನೋಡೋಣ.

ನೆಲ್ಡರ್-ಮೀಡ್ ಸಿಂಪ್ಲೆಕ್ಸ್ ವಿಧಾನ

0 ಆಯಾಮದ ಜಾಗದಲ್ಲಿ ಆರಂಭಿಕ ಬಿಂದು x5 ಇರಲಿ. ಅಲ್ಗಾರಿದಮ್ ಅನ್ನು ಬಳಸಿಕೊಂಡು ಅದರ ಹತ್ತಿರವಿರುವ ರೋಸೆನ್‌ಬ್ರಾಕ್ ಕಾರ್ಯದ ಕನಿಷ್ಠ ಬಿಂದುವನ್ನು ಕಂಡುಹಿಡಿಯೋಣ ನೆಲ್ಡರ್-ಮೀಡ್ ಸಿಂಪ್ಲೆಕ್ಸ್ (ಅಲ್ಗಾರಿದಮ್ ಅನ್ನು ವಿಧಾನದ ನಿಯತಾಂಕದ ಮೌಲ್ಯವಾಗಿ ನಿರ್ದಿಷ್ಟಪಡಿಸಲಾಗಿದೆ):

from scipy.optimize import minimize
x0 = np.array([1.3, 0.7, 0.8, 1.9, 1.2])
res = minimize(rosen, x0, method='nelder-mead',
    options={'xtol': 1e-8, 'disp': True})
print(res.x)

Optimization terminated successfully.
         Current function value: 0.000000
         Iterations: 339
         Function evaluations: 571
[1. 1. 1. 1. 1.]

ಸಿಂಪ್ಲೆಕ್ಸ್ ವಿಧಾನವು ಸ್ಪಷ್ಟವಾಗಿ ವ್ಯಾಖ್ಯಾನಿಸಲಾದ ಮತ್ತು ಸಾಕಷ್ಟು ಮೃದುವಾದ ಕಾರ್ಯವನ್ನು ಕಡಿಮೆ ಮಾಡಲು ಸರಳವಾದ ಮಾರ್ಗವಾಗಿದೆ. ಇದು ಕಾರ್ಯದ ಉತ್ಪನ್ನಗಳನ್ನು ಲೆಕ್ಕಾಚಾರ ಮಾಡುವ ಅಗತ್ಯವಿಲ್ಲ; ಅದರ ಮೌಲ್ಯಗಳನ್ನು ಮಾತ್ರ ಸೂಚಿಸಲು ಸಾಕು. ನೆಲ್ಡರ್-ಮೀಡ್ ವಿಧಾನವು ಸರಳವಾದ ಕಡಿಮೆಗೊಳಿಸುವಿಕೆ ಸಮಸ್ಯೆಗಳಿಗೆ ಉತ್ತಮ ಆಯ್ಕೆಯಾಗಿದೆ. ಆದಾಗ್ಯೂ, ಇದು ಗ್ರೇಡಿಯಂಟ್ ಅಂದಾಜುಗಳನ್ನು ಬಳಸುವುದಿಲ್ಲವಾದ್ದರಿಂದ, ಕನಿಷ್ಠವನ್ನು ಕಂಡುಹಿಡಿಯಲು ಇದು ಹೆಚ್ಚು ಸಮಯ ತೆಗೆದುಕೊಳ್ಳಬಹುದು.

ಪೊವೆಲ್ ವಿಧಾನ

ಕಾರ್ಯ ಮೌಲ್ಯಗಳನ್ನು ಮಾತ್ರ ಲೆಕ್ಕಹಾಕುವ ಮತ್ತೊಂದು ಆಪ್ಟಿಮೈಸೇಶನ್ ಅಲ್ಗಾರಿದಮ್ ಪೊವೆಲ್ ವಿಧಾನ. ಇದನ್ನು ಬಳಸಲು, ನೀವು ಕನಿಷ್ಟ ಕಾರ್ಯದಲ್ಲಿ ವಿಧಾನ = 'ಪೊವೆಲ್' ಅನ್ನು ಹೊಂದಿಸಬೇಕಾಗುತ್ತದೆ.

x0 = np.array([1.3, 0.7, 0.8, 1.9, 1.2])
res = minimize(rosen, x0, method='powell',
    options={'xtol': 1e-8, 'disp': True})
print(res.x)

Optimization terminated successfully.
         Current function value: 0.000000
         Iterations: 19
         Function evaluations: 1622
[1. 1. 1. 1. 1.]

ಬ್ರಾಯ್ಡೆನ್-ಫ್ಲೆಚರ್-ಗೋಲ್ಡ್‌ಫಾರ್ಬ್-ಶಾನೋ (BFGS) ಅಲ್ಗಾರಿದಮ್

ಪರಿಹಾರಕ್ಕೆ ವೇಗವಾಗಿ ಒಮ್ಮುಖವಾಗಲು, ಕಾರ್ಯವಿಧಾನ BFGS ವಸ್ತುನಿಷ್ಠ ಕ್ರಿಯೆಯ ಗ್ರೇಡಿಯಂಟ್ ಅನ್ನು ಬಳಸುತ್ತದೆ. ಗ್ರೇಡಿಯಂಟ್ ಅನ್ನು ಫಂಕ್ಷನ್ ಆಗಿ ನಿರ್ದಿಷ್ಟಪಡಿಸಬಹುದು ಅಥವಾ ಮೊದಲ ಕ್ರಮಾಂಕದ ವ್ಯತ್ಯಾಸಗಳನ್ನು ಬಳಸಿಕೊಂಡು ಲೆಕ್ಕ ಹಾಕಬಹುದು. ಯಾವುದೇ ಸಂದರ್ಭದಲ್ಲಿ, ಬಿಎಫ್‌ಜಿಎಸ್ ವಿಧಾನಕ್ಕೆ ಸಿಂಪ್ಲೆಕ್ಸ್ ವಿಧಾನಕ್ಕಿಂತ ಕಡಿಮೆ ಫಂಕ್ಷನ್ ಕರೆಗಳು ಬೇಕಾಗುತ್ತವೆ.

ರೋಸೆನ್‌ಬ್ರಾಕ್ ಕ್ರಿಯೆಯ ವ್ಯುತ್ಪನ್ನವನ್ನು ವಿಶ್ಲೇಷಣಾತ್ಮಕ ರೂಪದಲ್ಲಿ ಕಂಡುಹಿಡಿಯೋಣ:

SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್

SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್

ಈ ಅಭಿವ್ಯಕ್ತಿಯು ಮೊದಲ ಮತ್ತು ಕೊನೆಯದನ್ನು ಹೊರತುಪಡಿಸಿ ಎಲ್ಲಾ ವೇರಿಯಬಲ್‌ಗಳ ಉತ್ಪನ್ನಗಳಿಗೆ ಮಾನ್ಯವಾಗಿದೆ, ಇವುಗಳನ್ನು ಹೀಗೆ ವ್ಯಾಖ್ಯಾನಿಸಲಾಗಿದೆ:

SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್

SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್

ಈ ಗ್ರೇಡಿಯಂಟ್ ಅನ್ನು ಲೆಕ್ಕಾಚಾರ ಮಾಡುವ ಪೈಥಾನ್ ಕಾರ್ಯವನ್ನು ನೋಡೋಣ:

def rosen_der (x):
    xm = x [1: -1]
    xm_m1 = x [: - 2]
    xm_p1 = x [2:]
    der = np.zeros_like (x)
    der [1: -1] = 200 * (xm-xm_m1 ** 2) - 400 * (xm_p1 - xm ** 2) * xm - 2 * (1-xm)
    der [0] = -400 * x [0] * (x [1] -x [0] ** 2) - 2 * (1-x [0])
    der [-1] = 200 * (x [-1] -x [-2] ** 2)
    return der

ಗ್ರೇಡಿಯಂಟ್ ಲೆಕ್ಕಾಚಾರದ ಕಾರ್ಯವನ್ನು ಕೆಳಗೆ ತೋರಿಸಿರುವಂತೆ ಕನಿಷ್ಠ ಕಾರ್ಯದ jac ನಿಯತಾಂಕದ ಮೌಲ್ಯವಾಗಿ ನಿರ್ದಿಷ್ಟಪಡಿಸಲಾಗಿದೆ.

res = minimize(rosen, x0, method='BFGS', jac=rosen_der, options={'disp': True})
print(res.x)

Optimization terminated successfully.
         Current function value: 0.000000
         Iterations: 25
         Function evaluations: 30
         Gradient evaluations: 30
[1.00000004 1.0000001  1.00000021 1.00000044 1.00000092]

ಕಾಂಜುಗೇಟ್ ಗ್ರೇಡಿಯಂಟ್ ಅಲ್ಗಾರಿದಮ್ (ನ್ಯೂಟನ್)

ಕ್ರಮಾವಳಿ ನ್ಯೂಟನ್‌ನ ಸಂಯೋಜಿತ ಗ್ರೇಡಿಯಂಟ್‌ಗಳು ಮಾರ್ಪಡಿಸಿದ ನ್ಯೂಟನ್ರ ವಿಧಾನವಾಗಿದೆ.
ನ್ಯೂಟನ್ರ ವಿಧಾನವು ಸ್ಥಳೀಯ ಪ್ರದೇಶದಲ್ಲಿನ ಕಾರ್ಯವನ್ನು ಎರಡನೇ ಹಂತದ ಬಹುಪದದಿಂದ ಅಂದಾಜು ಮಾಡುವುದರ ಮೇಲೆ ಆಧಾರಿತವಾಗಿದೆ:

SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್

ಅಲ್ಲಿ SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್ ಎರಡನೇ ಉತ್ಪನ್ನಗಳ ಮ್ಯಾಟ್ರಿಕ್ಸ್ ಆಗಿದೆ (ಹೆಸ್ಸಿಯನ್ ಮ್ಯಾಟ್ರಿಕ್ಸ್, ಹೆಸ್ಸಿಯನ್).
ಹೆಸ್ಸಿಯನ್ ಧನಾತ್ಮಕ ಖಚಿತವಾಗಿದ್ದರೆ, ಈ ಕಾರ್ಯದ ಸ್ಥಳೀಯ ಕನಿಷ್ಠವನ್ನು ಕ್ವಾಡ್ರಾಟಿಕ್ ರೂಪದ ಶೂನ್ಯ ಗ್ರೇಡಿಯಂಟ್ ಅನ್ನು ಶೂನ್ಯಕ್ಕೆ ಸಮೀಕರಿಸುವ ಮೂಲಕ ಕಂಡುಹಿಡಿಯಬಹುದು. ಫಲಿತಾಂಶವು ಅಭಿವ್ಯಕ್ತಿಯಾಗಿರುತ್ತದೆ:

SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್

ವಿಲೋಮ ಹೆಸ್ಸಿಯನ್ ಅನ್ನು ಸಂಯೋಜಿತ ಗ್ರೇಡಿಯಂಟ್ ವಿಧಾನವನ್ನು ಬಳಸಿಕೊಂಡು ಲೆಕ್ಕಹಾಕಲಾಗುತ್ತದೆ. ರೋಸೆನ್‌ಬ್ರಾಕ್ ಕಾರ್ಯವನ್ನು ಕಡಿಮೆ ಮಾಡಲು ಈ ವಿಧಾನವನ್ನು ಬಳಸುವ ಉದಾಹರಣೆಯನ್ನು ಕೆಳಗೆ ನೀಡಲಾಗಿದೆ. ನ್ಯೂಟನ್-ಸಿಜಿ ವಿಧಾನವನ್ನು ಬಳಸಲು, ನೀವು ಹೆಸ್ಸಿಯನ್ ಅನ್ನು ಲೆಕ್ಕಾಚಾರ ಮಾಡುವ ಕಾರ್ಯವನ್ನು ನಿರ್ದಿಷ್ಟಪಡಿಸಬೇಕು.
ವಿಶ್ಲೇಷಣಾತ್ಮಕ ರೂಪದಲ್ಲಿ ರೋಸೆನ್‌ಬ್ರಾಕ್ ಕಾರ್ಯದ ಹೆಸ್ಸಿಯನ್ ಇದಕ್ಕೆ ಸಮಾನವಾಗಿರುತ್ತದೆ:

SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್

SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್

ಅಲ್ಲಿ SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್ и SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್, ಮ್ಯಾಟ್ರಿಕ್ಸ್ ಅನ್ನು ವ್ಯಾಖ್ಯಾನಿಸಿ SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್.

ಮ್ಯಾಟ್ರಿಕ್ಸ್‌ನ ಉಳಿದ ಶೂನ್ಯವಲ್ಲದ ಅಂಶಗಳು ಇದಕ್ಕೆ ಸಮಾನವಾಗಿವೆ:

SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್

SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್

SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್

SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್

ಉದಾಹರಣೆಗೆ, ಐದು ಆಯಾಮದ ಜಾಗದಲ್ಲಿ N = 5, ರೋಸೆನ್‌ಬ್ರಾಕ್ ಕಾರ್ಯಕ್ಕಾಗಿ ಹೆಸ್ಸಿಯನ್ ಮ್ಯಾಟ್ರಿಕ್ಸ್ ಬ್ಯಾಂಡ್‌ನ ರೂಪವನ್ನು ಹೊಂದಿದೆ:

SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್

ಕಾಂಜುಗೇಟ್ ಗ್ರೇಡಿಯಂಟ್ (ನ್ಯೂಟನ್) ವಿಧಾನವನ್ನು ಬಳಸಿಕೊಂಡು ರೋಸೆನ್‌ಬ್ರಾಕ್ ಕಾರ್ಯವನ್ನು ಕಡಿಮೆ ಮಾಡಲು ಕೋಡ್ ಜೊತೆಗೆ ಈ ಹೆಸ್ಸಿಯನ್ ಅನ್ನು ಲೆಕ್ಕಾಚಾರ ಮಾಡುವ ಕೋಡ್:

def rosen_hess(x):
    x = np.asarray(x)
    H = np.diag(-400*x[:-1],1) - np.diag(400*x[:-1],-1)
    diagonal = np.zeros_like(x)
    diagonal[0] = 1200*x[0]**2-400*x[1]+2
    diagonal[-1] = 200
    diagonal[1:-1] = 202 + 1200*x[1:-1]**2 - 400*x[2:]
    H = H + np.diag(diagonal)
    return H

res = minimize(rosen, x0, method='Newton-CG', 
               jac=rosen_der, hess=rosen_hess,
               options={'xtol': 1e-8, 'disp': True})
print(res.x)

Optimization terminated successfully.
         Current function value: 0.000000
         Iterations: 24
         Function evaluations: 33
         Gradient evaluations: 56
         Hessian evaluations: 24
[1.         1.         1.         0.99999999 0.99999999]

ಹೆಸ್ಸಿಯನ್ ಮತ್ತು ಅನಿಯಂತ್ರಿತ ವೆಕ್ಟರ್‌ನ ಉತ್ಪನ್ನ ಕಾರ್ಯದ ವ್ಯಾಖ್ಯಾನದೊಂದಿಗೆ ಉದಾಹರಣೆ

ನೈಜ-ಪ್ರಪಂಚದ ಸಮಸ್ಯೆಗಳಲ್ಲಿ, ಸಂಪೂರ್ಣ ಹೆಸ್ಸಿಯನ್ ಮ್ಯಾಟ್ರಿಕ್ಸ್ ಅನ್ನು ಕಂಪ್ಯೂಟಿಂಗ್ ಮಾಡಲು ಮತ್ತು ಸಂಗ್ರಹಿಸಲು ಗಮನಾರ್ಹ ಸಮಯ ಮತ್ತು ಮೆಮೊರಿ ಸಂಪನ್ಮೂಲಗಳು ಬೇಕಾಗಬಹುದು. ಈ ಸಂದರ್ಭದಲ್ಲಿ, ವಾಸ್ತವವಾಗಿ ಹೆಸ್ಸಿಯನ್ ಮ್ಯಾಟ್ರಿಕ್ಸ್ ಅನ್ನು ನಿರ್ದಿಷ್ಟಪಡಿಸುವ ಅಗತ್ಯವಿಲ್ಲ, ಏಕೆಂದರೆ ಮಿನಿಮೈಸೇಶನ್ ಕಾರ್ಯವಿಧಾನಕ್ಕೆ ಮತ್ತೊಂದು ಅನಿಯಂತ್ರಿತ ವೆಕ್ಟರ್ನೊಂದಿಗೆ ಹೆಸ್ಸಿಯನ್ ಉತ್ಪನ್ನಕ್ಕೆ ಸಮಾನವಾದ ವೆಕ್ಟರ್ ಮಾತ್ರ ಅಗತ್ಯವಿದೆ. ಹೀಗಾಗಿ, ಕಂಪ್ಯೂಟೇಶನಲ್ ದೃಷ್ಟಿಕೋನದಿಂದ, ಹೆಸ್ಸಿಯನ್ ಉತ್ಪನ್ನದ ಫಲಿತಾಂಶವನ್ನು ಅನಿಯಂತ್ರಿತ ವೆಕ್ಟರ್‌ನೊಂದಿಗೆ ಹಿಂದಿರುಗಿಸುವ ಕಾರ್ಯವನ್ನು ತಕ್ಷಣವೇ ವ್ಯಾಖ್ಯಾನಿಸುವುದು ಹೆಚ್ಚು ಯೋಗ್ಯವಾಗಿದೆ.

ಹೆಸ್ ಫಂಕ್ಷನ್ ಅನ್ನು ಪರಿಗಣಿಸಿ, ಇದು ಕಡಿಮೆಗೊಳಿಸುವಿಕೆ ವೆಕ್ಟರ್ ಅನ್ನು ಮೊದಲ ಆರ್ಗ್ಯುಮೆಂಟ್ ಆಗಿ ಮತ್ತು ಅನಿಯಂತ್ರಿತ ವೆಕ್ಟರ್ ಅನ್ನು ಎರಡನೇ ಆರ್ಗ್ಯುಮೆಂಟ್ ಆಗಿ ತೆಗೆದುಕೊಳ್ಳುತ್ತದೆ (ಕಡಿಮೆಗೊಳಿಸಬೇಕಾದ ಕಾರ್ಯದ ಇತರ ಆರ್ಗ್ಯುಮೆಂಟ್‌ಗಳ ಜೊತೆಗೆ). ನಮ್ಮ ಸಂದರ್ಭದಲ್ಲಿ, ಅನಿಯಂತ್ರಿತ ವೆಕ್ಟರ್ನೊಂದಿಗೆ ರೋಸೆನ್ಬ್ರಾಕ್ ಕ್ರಿಯೆಯ ಹೆಸ್ಸಿಯನ್ ಉತ್ಪನ್ನವನ್ನು ಲೆಕ್ಕಾಚಾರ ಮಾಡುವುದು ತುಂಬಾ ಕಷ್ಟವಲ್ಲ. ಒಂದು ವೇಳೆ p ಅನಿಯಂತ್ರಿತ ವೆಕ್ಟರ್ ಆಗಿದೆ, ನಂತರ ಉತ್ಪನ್ನವಾಗಿದೆ SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್ ತೋರುತ್ತಿದೆ:

SciPy, ಆಪ್ಟಿಮೈಸೇಶನ್

ಹೆಸ್ಸಿಯನ್ ಮತ್ತು ಅನಿಯಂತ್ರಿತ ವೆಕ್ಟರ್‌ನ ಉತ್ಪನ್ನವನ್ನು ಲೆಕ್ಕಾಚಾರ ಮಾಡುವ ಕಾರ್ಯವನ್ನು ಹೆಸ್ಪ್ ಆರ್ಗ್ಯುಮೆಂಟ್‌ನ ಮೌಲ್ಯವಾಗಿ ಮಿನಿಮೈಜ್ ಫಂಕ್ಷನ್‌ಗೆ ರವಾನಿಸಲಾಗುತ್ತದೆ:

def rosen_hess_p(x, p):
    x = np.asarray(x)
    Hp = np.zeros_like(x)
    Hp[0] = (1200*x[0]**2 - 400*x[1] + 2)*p[0] - 400*x[0]*p[1]
    Hp[1:-1] = -400*x[:-2]*p[:-2]+(202+1200*x[1:-1]**2-400*x[2:])*p[1:-1] 
    -400*x[1:-1]*p[2:]
    Hp[-1] = -400*x[-2]*p[-2] + 200*p[-1]
    return Hp

res = minimize(rosen, x0, method='Newton-CG',
               jac=rosen_der, hessp=rosen_hess_p,
               options={'xtol': 1e-8, 'disp': True})

Optimization terminated successfully.
         Current function value: 0.000000
         Iterations: 24
         Function evaluations: 33
         Gradient evaluations: 56
         Hessian evaluations: 66

ಕಾಂಜುಗೇಟ್ ಗ್ರೇಡಿಯಂಟ್ ಟ್ರಸ್ಟ್ ಪ್ರದೇಶದ ಅಲ್ಗಾರಿದಮ್ (ನ್ಯೂಟನ್)

ಹೆಸ್ಸಿಯನ್ ಮ್ಯಾಟ್ರಿಕ್ಸ್‌ನ ಕಳಪೆ ಕಂಡೀಷನಿಂಗ್ ಮತ್ತು ತಪ್ಪಾದ ಹುಡುಕಾಟ ನಿರ್ದೇಶನಗಳು ನ್ಯೂಟನ್‌ನ ಸಂಯೋಜಿತ ಗ್ರೇಡಿಯಂಟ್ ಅಲ್ಗಾರಿದಮ್ ನಿಷ್ಪರಿಣಾಮಕಾರಿಯಾಗಲು ಕಾರಣವಾಗಬಹುದು. ಅಂತಹ ಸಂದರ್ಭಗಳಲ್ಲಿ, ಆದ್ಯತೆ ನೀಡಲಾಗುತ್ತದೆ ವಿಶ್ವಾಸಾರ್ಹ ಪ್ರದೇಶದ ವಿಧಾನ (ಟ್ರಸ್ಟ್-ರೀಜನ್) ನ್ಯೂಟನ್ ಗ್ರೇಡಿಯಂಟ್‌ಗಳನ್ನು ಸಂಯೋಜಿಸಿ.

ಹೆಸ್ಸಿಯನ್ ಮ್ಯಾಟ್ರಿಕ್ಸ್ನ ವ್ಯಾಖ್ಯಾನದೊಂದಿಗೆ ಉದಾಹರಣೆ:

res = minimize(rosen, x0, method='trust-ncg',
               jac=rosen_der, hess=rosen_hess,
               options={'gtol': 1e-8, 'disp': True})
print(res.x)

Optimization terminated successfully.
         Current function value: 0.000000
         Iterations: 20
         Function evaluations: 21
         Gradient evaluations: 20
         Hessian evaluations: 19
[1. 1. 1. 1. 1.]

ಹೆಸ್ಸಿಯನ್ ಮತ್ತು ಅನಿಯಂತ್ರಿತ ವೆಕ್ಟರ್‌ನ ಉತ್ಪನ್ನ ಕಾರ್ಯದೊಂದಿಗೆ ಉದಾಹರಣೆ:

res = minimize(rosen, x0, method='trust-ncg', 
                jac=rosen_der, hessp=rosen_hess_p, 
                options={'gtol': 1e-8, 'disp': True})
print(res.x)

Optimization terminated successfully.
         Current function value: 0.000000
         Iterations: 20
         Function evaluations: 21
         Gradient evaluations: 20
         Hessian evaluations: 0
[1. 1. 1. 1. 1.]

ಕ್ರಿಲೋವ್ ಪ್ರಕಾರದ ವಿಧಾನಗಳು

ಟ್ರಸ್ಟ್-ಎನ್‌ಸಿಜಿ ವಿಧಾನದಂತೆ, ಕ್ರೈಲೋವ್-ಮಾದರಿಯ ವಿಧಾನಗಳು ದೊಡ್ಡ ಪ್ರಮಾಣದ ಸಮಸ್ಯೆಗಳನ್ನು ಪರಿಹರಿಸಲು ಸೂಕ್ತವಾಗಿವೆ ಏಕೆಂದರೆ ಅವು ಮ್ಯಾಟ್ರಿಕ್ಸ್-ವೆಕ್ಟರ್ ಉತ್ಪನ್ನಗಳನ್ನು ಮಾತ್ರ ಬಳಸುತ್ತವೆ. ಮೊಟಕುಗೊಳಿಸಿದ ಕ್ರೈಲೋವ್ ಸಬ್‌ಸ್ಪೇಸ್‌ನಿಂದ ಸೀಮಿತವಾದ ವಿಶ್ವಾಸಾರ್ಹ ಪ್ರದೇಶದಲ್ಲಿ ಸಮಸ್ಯೆಯನ್ನು ಪರಿಹರಿಸುವುದು ಅವರ ಮೂಲತತ್ವವಾಗಿದೆ. ಅನಿಶ್ಚಿತ ಸಮಸ್ಯೆಗಳಿಗೆ, ಟ್ರಸ್ಟ್-ಎನ್‌ಸಿಜಿ ವಿಧಾನಕ್ಕೆ ಹೋಲಿಸಿದರೆ, ಪ್ರತಿ ಉಪಸಮಸ್ಯೆಗೆ ಕಡಿಮೆ ಸಂಖ್ಯೆಯ ಮ್ಯಾಟ್ರಿಕ್ಸ್-ವೆಕ್ಟರ್ ಉತ್ಪನ್ನಗಳ ಕಾರಣದಿಂದಾಗಿ ಇದು ಕಡಿಮೆ ಸಂಖ್ಯೆಯ ರೇಖಾತ್ಮಕವಲ್ಲದ ಪುನರಾವರ್ತನೆಗಳನ್ನು ಬಳಸುವುದರಿಂದ ಈ ವಿಧಾನವನ್ನು ಬಳಸುವುದು ಉತ್ತಮ. ಜೊತೆಗೆ, ಕ್ವಾಡ್ರಾಟಿಕ್ ಉಪಸಮಸ್ಯೆಗೆ ಪರಿಹಾರವು ಟ್ರಸ್ಟ್-ಎನ್‌ಸಿಜಿ ವಿಧಾನವನ್ನು ಬಳಸುವುದಕ್ಕಿಂತ ಹೆಚ್ಚು ನಿಖರವಾಗಿ ಕಂಡುಬರುತ್ತದೆ.
ಹೆಸ್ಸಿಯನ್ ಮ್ಯಾಟ್ರಿಕ್ಸ್ನ ವ್ಯಾಖ್ಯಾನದೊಂದಿಗೆ ಉದಾಹರಣೆ:

res = minimize(rosen, x0, method='trust-krylov',
               jac=rosen_der, hess=rosen_hess,
               options={'gtol': 1e-8, 'disp': True})

Optimization terminated successfully.
         Current function value: 0.000000
         Iterations: 19
         Function evaluations: 20
         Gradient evaluations: 20
         Hessian evaluations: 18

print(res.x)

    [1. 1. 1. 1. 1.]

ಹೆಸ್ಸಿಯನ್ ಮತ್ತು ಅನಿಯಂತ್ರಿತ ವೆಕ್ಟರ್‌ನ ಉತ್ಪನ್ನ ಕಾರ್ಯದೊಂದಿಗೆ ಉದಾಹರಣೆ:

res = minimize(rosen, x0, method='trust-krylov',
               jac=rosen_der, hessp=rosen_hess_p,
               options={'gtol': 1e-8, 'disp': True})

Optimization terminated successfully.
         Current function value: 0.000000
         Iterations: 19
         Function evaluations: 20
         Gradient evaluations: 20
         Hessian evaluations: 0

print(res.x)

    [1. 1. 1. 1. 1.]

ವಿಶ್ವಾಸಾರ್ಹ ಪ್ರದೇಶದಲ್ಲಿ ಅಂದಾಜು ಪರಿಹಾರಕ್ಕಾಗಿ ಅಲ್ಗಾರಿದಮ್

ಎಲ್ಲಾ ವಿಧಾನಗಳು (ನ್ಯೂಟನ್-ಸಿಜಿ, ಟ್ರಸ್ಟ್-ಎನ್‌ಸಿಜಿ ಮತ್ತು ಟ್ರಸ್ಟ್-ಕ್ರಿಲೋವ್) ದೊಡ್ಡ ಪ್ರಮಾಣದ ಸಮಸ್ಯೆಗಳನ್ನು ಪರಿಹರಿಸಲು ಸೂಕ್ತವಾಗಿವೆ (ಸಾವಿರಾರು ಅಸ್ಥಿರಗಳೊಂದಿಗೆ). ಆಧಾರವಾಗಿರುವ ಕಾಂಜುಗೇಟ್ ಗ್ರೇಡಿಯಂಟ್ ಅಲ್ಗಾರಿದಮ್ ವಿಲೋಮ ಹೆಸ್ಸಿಯನ್ ಮ್ಯಾಟ್ರಿಕ್ಸ್‌ನ ಅಂದಾಜು ನಿರ್ಣಯವನ್ನು ಸೂಚಿಸುತ್ತದೆ ಎಂಬುದು ಇದಕ್ಕೆ ಕಾರಣ. ಹೆಸ್ಸಿಯನ್‌ನ ಸ್ಪಷ್ಟವಾದ ವಿಸ್ತರಣೆಯಿಲ್ಲದೆಯೇ ಪರಿಹಾರವು ಪುನರಾವರ್ತಿತವಾಗಿ ಕಂಡುಬರುತ್ತದೆ. ಹೆಸ್ಸಿಯನ್ ಮತ್ತು ಅನಿಯಂತ್ರಿತ ವೆಕ್ಟರ್‌ನ ಉತ್ಪನ್ನಕ್ಕಾಗಿ ನೀವು ಕಾರ್ಯವನ್ನು ಮಾತ್ರ ವ್ಯಾಖ್ಯಾನಿಸಬೇಕಾಗಿರುವುದರಿಂದ, ಈ ಅಲ್ಗಾರಿದಮ್ ವಿರಳವಾದ (ಬ್ಯಾಂಡ್ ಕರ್ಣೀಯ) ಮ್ಯಾಟ್ರಿಕ್ಸ್‌ಗಳೊಂದಿಗೆ ಕೆಲಸ ಮಾಡಲು ವಿಶೇಷವಾಗಿ ಒಳ್ಳೆಯದು. ಇದು ಕಡಿಮೆ ಮೆಮೊರಿ ವೆಚ್ಚ ಮತ್ತು ಗಮನಾರ್ಹ ಸಮಯ ಉಳಿತಾಯವನ್ನು ಒದಗಿಸುತ್ತದೆ.

ಮಧ್ಯಮ ಗಾತ್ರದ ಸಮಸ್ಯೆಗಳಿಗೆ, ಹೆಸ್ಸಿಯನ್ ಅನ್ನು ಸಂಗ್ರಹಿಸುವ ಮತ್ತು ಅಪವರ್ತನಗೊಳಿಸುವ ವೆಚ್ಚವು ನಿರ್ಣಾಯಕವಲ್ಲ. ಇದರರ್ಥ ಕಡಿಮೆ ಪುನರಾವರ್ತನೆಗಳಲ್ಲಿ ಪರಿಹಾರವನ್ನು ಪಡೆಯಲು ಸಾಧ್ಯವಿದೆ, ಟ್ರಸ್ಟ್ ಪ್ರದೇಶದ ಉಪಸಮಸ್ಯೆಗಳನ್ನು ಬಹುತೇಕ ನಿಖರವಾಗಿ ಪರಿಹರಿಸುತ್ತದೆ. ಇದನ್ನು ಮಾಡಲು, ಪ್ರತಿ ಕ್ವಾಡ್ರಾಟಿಕ್ ಉಪಸಮಸ್ಯೆಗೆ ಕೆಲವು ರೇಖಾತ್ಮಕವಲ್ಲದ ಸಮೀಕರಣಗಳನ್ನು ಪುನರಾವರ್ತಿತವಾಗಿ ಪರಿಹರಿಸಲಾಗುತ್ತದೆ. ಇಂತಹ ಪರಿಹಾರಕ್ಕೆ ಸಾಮಾನ್ಯವಾಗಿ ಹೆಸ್ಸಿಯನ್ ಮ್ಯಾಟ್ರಿಕ್ಸ್‌ನ 3 ಅಥವಾ 4 ಚೊಲೆಸ್ಕಿ ವಿಘಟನೆಗಳು ಬೇಕಾಗುತ್ತವೆ. ಪರಿಣಾಮವಾಗಿ, ವಿಧಾನವು ಕಡಿಮೆ ಪುನರಾವರ್ತನೆಗಳಲ್ಲಿ ಒಮ್ಮುಖವಾಗುತ್ತದೆ ಮತ್ತು ಇತರ ಕಾರ್ಯಗತಗೊಳಿಸಿದ ವಿಶ್ವಾಸಾರ್ಹ ಪ್ರದೇಶದ ವಿಧಾನಗಳಿಗಿಂತ ಕಡಿಮೆ ವಸ್ತುನಿಷ್ಠ ಕಾರ್ಯ ಲೆಕ್ಕಾಚಾರಗಳ ಅಗತ್ಯವಿರುತ್ತದೆ. ಈ ಅಲ್ಗಾರಿದಮ್ ಸಂಪೂರ್ಣ ಹೆಸ್ಸಿಯನ್ ಮ್ಯಾಟ್ರಿಕ್ಸ್ ಅನ್ನು ಮಾತ್ರ ನಿರ್ಧರಿಸುತ್ತದೆ ಮತ್ತು ಹೆಸ್ಸಿಯನ್ ಮತ್ತು ಅನಿಯಂತ್ರಿತ ವೆಕ್ಟರ್‌ನ ಉತ್ಪನ್ನ ಕಾರ್ಯವನ್ನು ಬಳಸುವ ಸಾಮರ್ಥ್ಯವನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ.

ರೋಸೆನ್‌ಬ್ರಾಕ್ ಕಾರ್ಯವನ್ನು ಕಡಿಮೆಗೊಳಿಸುವುದರೊಂದಿಗೆ ಉದಾಹರಣೆ:

res = minimize(rosen, x0, method='trust-exact',
               jac=rosen_der, hess=rosen_hess,
               options={'gtol': 1e-8, 'disp': True})
res.x

Optimization terminated successfully.
         Current function value: 0.000000
         Iterations: 13
         Function evaluations: 14
         Gradient evaluations: 13
         Hessian evaluations: 14

array([1., 1., 1., 1., 1.])

ನಾವು ಬಹುಶಃ ಅಲ್ಲಿ ನಿಲ್ಲುತ್ತೇವೆ. ಮುಂದಿನ ಲೇಖನದಲ್ಲಿ ನಾನು ಷರತ್ತುಬದ್ಧ ಕಡಿಮೆಗೊಳಿಸುವಿಕೆ, ಅಂದಾಜು ಸಮಸ್ಯೆಗಳನ್ನು ಪರಿಹರಿಸುವಲ್ಲಿ ಕಡಿಮೆಗೊಳಿಸುವಿಕೆಯ ಅಪ್ಲಿಕೇಶನ್, ಒಂದು ವೇರಿಯೇಬಲ್, ಅನಿಯಂತ್ರಿತ ಮಿನಿಮೈಜರ್‌ಗಳ ಕಾರ್ಯವನ್ನು ಕಡಿಮೆ ಮಾಡುವುದು ಮತ್ತು scipy.optimize ಬಳಸಿಕೊಂಡು ಸಮೀಕರಣಗಳ ವ್ಯವಸ್ಥೆಯ ಬೇರುಗಳನ್ನು ಕಂಡುಹಿಡಿಯುವ ಬಗ್ಗೆ ಅತ್ಯಂತ ಆಸಕ್ತಿದಾಯಕ ವಿಷಯಗಳನ್ನು ಹೇಳಲು ಪ್ರಯತ್ನಿಸುತ್ತೇನೆ. ಪ್ಯಾಕೇಜ್.

ಮೂಲ: https://docs.scipy.org/doc/scipy/reference/

ಮೂಲ: www.habr.com

ಕಾಮೆಂಟ್ ಅನ್ನು ಸೇರಿಸಿ