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()