Загрузка данных


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

gipers = pd.read_csv(r"Гиперспектр кукурузы.csv", sep=';', decimal=',')

x_col = [c for c in gipers.columns if 'wave' in c.lower() or 'leng' in c.lower()][0]
y_col = [c for c in gipers.columns if 'spec' in c.lower()][0]

x = pd.to_numeric(gipers[x_col], errors='coerce').dropna().values
Y = pd.to_numeric(gipers[y_col], errors='coerce').dropna().values
x, Y = x[:len(Y)], Y[:len(x)]

# Аналитический расчет коэффициентов
a1 = np.mean((x - x.mean()) * (Y - Y.mean())) / np.mean((x - x.mean())**2)
a0 = Y.mean() - a1 * x.mean()

# Класс для градиентного спуска
class SimpleRegression(object):
    def __init__(self):
        self.a0, self.a1 = 0.0, 0.0
    def predict(self, x):
        return self.a0 + self.a1 * x
    def MSE(self, x, Y):
        return ((Y - self.predict(x))**2).mean()
    def fit(self, x, Y, alpha=0.000001, epsylon=0.01, max_steps=5000):
        steps, errors = [], []
        for step in range(1, max_steps + 1):
            error = Y - self.predict(x)
            self.a0 -= alpha * (-2 * np.mean(error))
            self.a1 -= alpha * (-2 * np.mean(error * x))
            errors.append(self.MSE(x, Y))
            steps.append(step)
            if errors[-1] < epsylon:
                break
        return steps, errors

regr = SimpleRegression()
steps, errors = regr.fit(x, Y)

x_space = np.linspace(x.min(), x.max(), 100)

# ИСПРАВЛЕНИЕ: рассчитываем прогнозные значения для аналитической модели
Y_pred_analytical = a0 + a1 * x_space

plt.figure(figsize=(12, 5))

plt.subplot(1, 2, 1)
plt.scatter(x, Y, alpha=0.6, label='обучающая выборка')
plt.plot(x_space, Y_pred_analytical, 'r', linewidth=2, label='аналитическая')
plt.plot(x_space, regr.predict(x_space), 'g--', label='градиентный спуск')
plt.xlabel('waveleng')
plt.ylabel('Spectr')
plt.title('сравнение прогнозов моделей с обучающей выборкой')
plt.legend()

plt.subplot(1, 2, 2)
plt.plot(steps, errors)
plt.xlabel('итерации')
plt.ylabel('MSE')
plt.title('сходимость градиентного спуска')

plt.tight_layout()
plt.show()