Реализуйте многомерную линейную регрессию с нуля на python без использования sklearn.

Линейная регрессия — это тип алгоритма машинного обучения, который пытается смоделировать взаимосвязь между функциями и целевыми переменными, подгоняя линейное уравнение к наблюдаемым данным.

Линейное уравнение в многомерных данных задается -

Y = β0​+ β1​x1​ + β1​x2​ +…+βn​xn + c

здесь β — различные наклоны для соответствующих объектов, а c — константа (смещение).

Я не буду утомлять вас всей теорией линейной регрессии и сразу перейду к ее реализации с помощью Python. Вы можете найти полную тетрадь здесь.

Шаг 1 — Импортируйте важные библиотеки и загрузите набор данных

# Importing the necessary libraries
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

Подгружаем необходимые библиотеки и функции для выполнения —

Numpy для выполнения матричных умножений.
Pandas для загрузки наших данных в виде фрейма данных и удобной обработки наших данных.
StandardScaler для масштабирования наших данных для идеального встраивания их в модель.
train_test_split для разделения данные в обучающую и тестовую выборки.

# Load the dataframe
df = pd.read_csv('energy.txt')
df.head()

Шаг 2. Предварительно обработайте и разделите набор данных на обучающую и тестовую выборки.

После загрузки набора данных мы должны предварительно обработать набор данных. Мы будем использовать функцию StandardScaler для масштабирования наших данных с помощью уравнения —

где μ — среднее значение, а σ — стандартное отклонение всех данных.

Следующий код масштабирует данные и делит их на обучающую и тестовую выборки.

# Seperate features and target variable
X = df.iloc[:, :4]
y = df.iloc[:, -1]
# Scaling the dataset to fit the model
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X = sc.fit_transform(X)
# Dividing the data into training and testing data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25)

Шаг 3 — Внедрение линейной регрессии с нуля.

  1. Функция стоимости

Чтобы оценить любую модель, нам нужна функция стоимости, чтобы знать, насколько хорошо наша модель обучается и адаптируется к новым данным. Для линейной регрессии мы используем среднеквадратичную ошибку для определения стоимости. Уравнение среднеквадратичной ошибки:

В коде мы реализуем приведенное выше уравнение следующим образом:

def cost_function(X, y, w, b):
    """
    Parameters:
    X: features
    y: target values
    w: weights
    b: bias
    
    Returns:
    cost: cost with current weights and bias
    """
    cost = np.sum((((X.dot(w) + b) - y) ** 2) / (2*len(y)))
    return cost

2. Функция градиентного спуска —

Здесь мы реализуем функцию градиентного спуска для выполнения прямого распространения, обратного распространения, вычисления градиента и обновления наших весов.

Я знаю, что их много, но все они представляют собой однострочный код.

Реализация функции градиентного спуска —

def gradient_descent_function(X, y, w, b, alpha=0.01, epochs=1000):
    """
    Parameters:
    X: features
    y: target values
    w: initial weights
    b: initial bias
    alpha: learning rate
    epochs: number of iterations
    
    Returns:
    costs: cost per epoch
    w: finalised weights
    b: finalised bias
    """
    m = len(y)
    costs = [0] * epochs
    
    for epoch in range(epochs):
        # Calculate the value -- Forward Propagation
        z = X.dot(w) + b
        
        # Calculate the losses
        loss = z - y
        
        # Calculate gradient descent
        weight_gradient = X.T.dot(loss) / m
        bias_gradient = np.sum(loss) / m
        
        # Update weights and bias
        w = w - alpha*weight_gradient
        b = b - alpha*bias_gradient
        
        # Store current lost
        cost = cost_function(X, y, w, b)
        costs[epoch] = cost
        
    return w, b, costs

После определения функций давайте применим их.

Сначала мы инициализируем некоторые случайные веса для каждой функции и смещения, а затем обучим модель, чтобы получить наилучшую подходящую линию.

# Initial random weights
w = np.random.randn(X_train.shape[1])
# Initial bias
b = 0
weights, bias, costs = gradient_descent_function(X_train, y_train, w, b, epochs=2500);

Давайте посмотрим, как работает наша модель, построив график затрат по каждой эпохе (итерации).

Мы видим, что стоимость резко снизилась и приблизилась к нулю.

Шаг 4 — Оценка нашей модели

Теперь мы рассчитаем показатель r2 модели, проверив ее на тестовой выборке, которую мы разделили ранее.

Реализация здесь -

def r2score(y_pred, y):
    """
    Parameters:
    y_pred: predicted values
    y: actual values
    
    Returns:
    r2: r2 score
    """
    rss = np.sum((y_pred - y) ** 2)
    tss = np.sum((y-y.mean()) ** 2)
    
    r2 = 1 - (rss / tss)
    return r2

Мы получили показатель r2 0,93, что весьма впечатляет.

Дополнительные материалы для чтения —

  1. Теория линейной регрессии
  2. Оценка R2
  3. Градиентный спуск