Эта статья представляет собой реализацию линейной регрессии с использованием решения в закрытой форме для заданного набора данных D.

Программа принимает набор данных D в качестве входных данных, применяет функцию преобразования признаков, определяет функцию гипотезы и функцию среднеквадратичной ошибки (MSE), а также вычисляет вектор весов, используя линейную регрессию решения в закрытой форме.

Затем определяется функция преобразования признаков для преобразования каждого входного примера x в пространство более высокой размерности. Функция преобразования сопоставляет каждый вход x с вектором из трех элементов [1, x, x²] и возвращает его в виде массива NumPy.

import numpy as np

# Define the dataset D
D = np.array([[1.0, 2.0], [2.0, 1.0], [3.0, 3.0]])

[[1. 2.]
 [2. 1.]
 [3. 3.]]

Входной объект x преобразуется в двумерный, и функция преобразования применяется к каждому входному примеру в D с использованием функции apply_along_axis. Результирующий преобразованный набор данных затем преобразуется в три столбца, соответствующие трем функциям [1, x, x²].

# Define the feature transformation function
def transform(x):
    return np.array([1, x, x**2], dtype=np.float64)

# Reshape the input array to be two-dimensional
D_reshaped = D[:, 0].reshape(-1, 1)

# Apply the transformation to each input example in D
D_transformed = np.apply_along_axis(transform, 1, D_reshaped).reshape(-1, 3)

Transformed dataset:
[[1. 1. 1.]
 [1. 2. 4.]
 [1. 3. 9.]]

Функция гипотезы hw(x) определена

который принимает входной пример x и весовой вектор w в качестве входных данных и возвращает скалярное произведение весового вектора и преобразованного входного примера x.

Обратная матрица Мура-Пенроуза (также известная как псевдообратная) представляет собой обобщение обратной матрицы для неквадратных матриц. Он обозначается A⁺ и может быть определен как:

A⁺ = (AᵀA)⁻¹Aᵀ

где Aᵀ - это транспонированный A, а (AᵀA)⁻¹ - обратный AᵀA, если он существует.

Псевдоинверсия имеет ряд полезных свойств, например позволяет решать переопределенные системы линейных уравнений (т. е. когда уравнений больше, чем неизвестных). В частности, если у нас есть система линейных уравнений вида Ax = b, где A — неквадратная матрица, а b — вектор, мы можем использовать псевдообратное уравнение, чтобы найти решение x:

x = A⁺b

Обратите внимание, что если A является квадратной матрицей и имеет обратную, то A⁺ = A⁻¹. Однако в целом псевдоинверсия — это более общее понятие, применимое к неквадратным матрицам.

Чтобы найти весовой вектор w, который минимизирует функцию потерь MSE, мы можем решить нормальные уравнения:

Решение для w определяется следующим образом:

Вычисляя w по приведенной выше формуле, получаем:

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

# Define the hypothesis function hw(x)
def hw(x, w):
    return np.dot(w, x)

# Define the mean squared error (MSE) function
def mse(X, y, w):
    m = len(y)
    y_pred = np.apply_along_axis(lambda x: hw(x, w), 1, X)
    return (1/m) * np.sum((y_pred - y)**2)

# Define the inputs and targets
X = D_transformed
y = D[:, 1]

# Calculate the weight vector using the closed-form solution for linear regression
w = np.linalg.inv(X.T @ X) @ X.T @ y

Weight vector: [ 6.  -5.5  1.5]

Затем программа применяет функцию преобразования к входным примерам hw(1), hw(2) и hw(3) и вычисляет соответствующие им прогнозируемые выходные значения, используя изученный вектор весов и функцию гипотезы. Вот функция гипотезы.

# Define the hypothesis function hw(x)
def hw(x, w):
    return np.dot(w, x)

# Define the mean squared error (MSE) function
def mse(X, y, w):
    m = len(y)
    y_pred = np.apply_along_axis(lambda x: hw(x, w), 1, X)
    return (1/m) * np.sum((y_pred - y)**2)

# Define the inputs and targets
X = D_transformed
y = D[:, 1]

# Calculate the weight vector using the closed-form solution for linear regression
w = np.linalg.inv(X.T @ X) @ X.T @ y

# Apply the transformation function to hw(1), hw(2), hw(3)
hwtransformtransformed = transform(1)
hwD_transformedtransformed = transform(2)
hwXtransformed = transform(3)

# Calculate the predicted values of hw(1), hw(2), hw(3)) using the learned weight vector w and hypothesis function hw(x)
hwtransformpredicted = hw(hwtransformtransformed, w)
hwD_transformedpredicted = hw(hwD_transformedtransformed, w)
hwXpredicted = hw(hwXtransformed, w)

# Print the predicted values of hw(1), hw(2), hw(3)
print("Predicted values for hw(1), hw(2), hw(3):")
print(hwtransformpredicted, hwD_transformedpredicted, hwXpredicted)

Predicted values for hw(1), hw(2), hw(3):
2.0000000000000235 0.999999999999976 2.999999999999947

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

# Calculate the MSE using the predicted values of hw(1), hw(2), hw(3) and the targets
mse_value = mse(np.array([hwtransformtransformed, hwD_transformedtransformed, hwXtransformed]), np.array([2.0, 1.0, 3.0]), w)

print("Mean squared error:", mse_value)
Mean squared error: 1.3072739967687533e-27

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

import numpy as np

# Define the dataset D
D = np.array([[1.0, 2.0], [2.0, 1.0], [3.0, 3.0]])

# Define the feature transformation function
def transform(x):
    return np.array([1, x], dtype=np.float64)

# Reshape the input array to be two-dimensional
D_reshaped = D[:, 0].reshape(-1, 1)

# Apply the transformation to each input example in D
D_transformed = np.apply_along_axis(transform, 1, D_reshaped).reshape(-1, 2)

# Define the hypothesis function hw(x)
def hw(x, w):
    return np.dot(w, x)

# Define the mean squared error (MSE) function
def mse(X, y, w):
    m = len(y)
    y_pred = np.apply_along_axis(lambda x: hw(x, w), 1, X)
    return (1/m) * np.sum((y_pred - y)**2)

# Define the inputs and targets
X = D_transformed
y = D[:, 1]

# Calculate the weight vector using the closed-form solution for linear regression
w = np.linalg.inv(X.T @ X) @ X.T @ y

# Apply the transformation function to hw(1), hw(2), hw(3)
hwtransformtransformed = transform(1)
hwD_transformedtransformed = transform(2)
hwXtransformed = transform(3)

# Calculate the predicted values of hw(1), hw(2), hw(3)) using the learned weight vector w and hypothesis function hw(x)
hwtransformpredicted = hw(hwtransformtransformed, w)
hwD_transformedpredicted = hw(hwD_transformedtransformed, w)
hwXpredicted = hw(hwXtransformed, w)

# Print the predicted values of hw(1), hw(2), hw(3)
print("Predicted values for hw(1), hw(2), hw(3):")
print(hwtransformpredicted, hwD_transformedpredicted, hwXpredicted)

Predicted values for hw(1), hw(2), hw(3):
1.4999999999999982 1.9999999999999982 2.4999999999999982

# Calculate the MSE using the predicted values of hw(1), hw(2), hw(3) and the targets
mse_value = mse(np.array([hwtransformtransformed, hwD_transformedtransformed, hwXtransformed]), np.array([2.0, 1.0, 3.0]), w)

# Print the transformed dataset, weight vector, and MSE
print("Transformed dataset:")
print(D_transformed)

Transformed dataset:
[[1. 1.]
 [1. 2.]
 [1. 3.]]

print("Weight vector:", w)
Weight vector: [1.  0.5]

print("Mean squared error:", mse_value)
Mean squared error: 0.5

Единственная разница между программой квадратичной и линейной регрессии заключается в следующем.

  • Функция transform была упрощена и теперь включает только постоянный термин и один признак.
  • Массив D_transformed изменен, чтобы иметь два столбца вместо трех.
  • Массив X в модели линейной регрессии имеет значение D_transformed.
  • Переменные hw_1_transformed, hw_2_transformed и hw_3_transformed вычисляются с использованием упрощенной функции transform.
  • Функция mse остается прежней, поскольку она может обрабатывать любое количество признаков во входных данных.
import numpy as np
import matplotlib.pyplot as plt

# Define the dataset D
D = np.array([[1.0, 2.0], [2.0, 1.0], [3.0, 3.0]])

# Define the feature transformation functions for linear and quadratic regression
def transform_linear(x):
    return np.array([1, x], dtype=np.float64)

def transform_quadratic(x):
    return np.array([1, x, x**2], dtype=np.float64)

# Reshape the input array to be two-dimensional
D_reshaped = D[:, 0].reshape(-1, 1)

# Apply the transformations to each input example in D
D_transformed_linear = np.apply_along_axis(transform_linear, 1, D_reshaped).reshape(-1, 2)
D_transformed_quadratic = np.apply_along_axis(transform_quadratic, 1, D_reshaped).reshape(-1, 3)

# Define the hypothesis functions for linear and quadratic regression
def hw_linear(x, w):
    return np.dot(w, x)

def hw_quadratic(x, w):
    return np.dot(w, x)

# Define the mean squared error (MSE) function for both models
def mse_linear(X, y, w):
    m = len(y)
    y_pred = np.apply_along_axis(lambda x: hw_linear(x, w), 1, X)
    return (1/m) * np.sum((y_pred - y)**2)

def mse_quadratic(X, y, w):
    m = len(y)
    y_pred = np.apply_along_axis(lambda x: hw_quadratic(x, w), 1, X)
    return (1/m) * np.sum((y_pred - y)**2)

# Define the inputs and targets
X = D_transformed_linear
y = D[:, 1]

# Calculate the weight vector using the closed-form solution for linear regression
w_linear = np.linalg.inv(X.T @ X) @ X.T @ y

# Calculate the MSE using the linear regression model
mse_linear_values = []
for i in range(1, 101):
    w = np.array([0, i/10])
    mse_linear_values.append(mse_linear(X, y, w))

# Define the inputs and targets
X = D_transformed_quadratic
y = D[:, 1]

# Calculate the weight vector using the closed-form solution for quadratic regression
w_quadratic = np.linalg.inv(X.T @ X) @ X.T @ y

# Calculate the MSE using the quadratic regression model
mse_quadratic_values = []
for i in range(1, 101):
    w = np.array([0, i/10, 0.5])
    mse_quadratic_values.append(mse_quadratic(X, y, w))

# Plot the MSE values for both models
plt.rcParams['figure.figsize'] = [10, 10]
x = np.arange(1, 101, 1)/10
plt.plot(x, mse_linear_values, label="Linear Regression")
plt.plot(x, mse_quadratic_values, label="Quadratic Regression")
plt.xlabel("Weight")
plt.ylabel("Mean Squared Error (MSE)")
plt.title("Comparison of MSE for Linear and Quadratic Regression")
plt.legend()
plt.show()

Как видно из сравнения значения mse линейной регрессии и квадратичной регрессии составляет 0,5 против 1,3072739967687533e-27. MSE квадратичной модели ниже, чем у модели линейной регрессии, а это означает, что линейная модель не может соответствовать данным, а также квадратичная модель. Это может быть связано с тем, что взаимосвязь между независимыми и зависимыми переменными более сложна, чем может отразить линейная функция, и квадратичная модель лучше способна отразить эту сложность.

Ссылка на гитхаб