🧑💻 Всем добрый вечер! Надеюсь, вы хорошо проводите свое время, ведь сейчас будет пост, а значит, вы его проведете еще лучше... Итак, линейная регрессия.
Допустим, есть у нас набор точек:
{x₁ = 50, y₁ = 10
{x₂ = 60, y₂ = 30
{x₃ = 70, y₃ = 40
{x₄ = 100, y₄ = 50
x — площадь дома, y — цена дома
Для начала, делаем визуал наших точек:
from matplotlib import pyplot as plt #Иморт библиотек
plt.scatter([50, 60, 70, 100], [10, 30, 40, 50], 50, 'g', 'o', alpha = 0.8) #В ппервых двух квадратных скобках это наши координаты x и y. Число 50 - это размер точек, g - green (цвет), o - Форма точек (круг). alpha = 0.8 - Прозрачность точек
plt.show()
Дальше выведем матрицу X (Единички для каждого объекта и 2 столбик это данные для обучения (площадь нашей хаты) )
import numpy as np
X = np.array([[1, 50], [1, 60], [1, 70], [1, 100]])
X
Вывод:
array([[ 1, 50],
[ 1, 60],
[ 1, 70],
[ 1, 100]])
⚙️ Теперь выведем матрицу для Y:
import numpy as np
Y = np.array([[10], [30], [40], [50]])
Y
Вывод:
array([[ 1, 50],
[ 1, 60],
[ 1, 70],
[ 1, 100]])
0) 🧑💻 Продолжаем изучать линейную регрессию и начнем мы с реализации формулы:
ẇ = (Xᵀ * X)⁻¹ * Xᵀ * Y
⚙️ Что это за формула и что здесь что? Я для вас кинул скрины в комменты, как эта формула получилась:
1) У нас изначально была формула, возможно, вы ее видели раньше:
y = a * x + b
2️) Заменим ее на обозначения w₁ и w₀, тогда формула приобретет вид:
y = w₁ * x + w₀ * 1 = w₁ * x₁ + w₀ * x₀
w₀ — свободный член, который отвечает за сдвиг линии регрессии
w₁, w₂ — веса (коэффициенты) для признаков x₁, x₂
🔗 Остальные преобразования формул в комментах ⬇️⬇️⬇️
3️) Итак, как только вы посмотрите все преобразования этих формул, мы придем к виду, который я вам показал в начале:
ẇ = (Xᵀ * X)⁻ ¹ * Xᵀ * Y
4️) Теперь, начнем 'по кусочкам' выписывать формулу:
Вчера мы выводили матрицу X (https://t.me/pywithCodeLab/820) и матрицу Y (https://t.me/pywithCodeLab/821). Дак вот, теперь самое время с ними поработать
5️) 🔗 Умножим матрицу X (объекты - признаки) на себя же транспонированную.
Транспонированная матрица — это матрица, которая получается из исходной путём перестановки строк и столбцов. Другими словами, чтобы получить транспонированную матрицу, необходимо взять каждую строчку по очереди и переписать её в виде столбца, не меняя порядка следования.
⬇️⬇️⬇️
###
Берем блок кода с прошлого поста (там мы выводили матрицу для X)
###
import numpy as np
X = np.array([[1, 50], [1, 60], [1, 70], [1, 100]]) # Создание массива (получаем матрицу 4 на 2)
X_T_X = (X.T).dot(X)
###
Транспанируем матрицу X.T. X.T — это транспонированная версия матрицы X. Строки становятся столбцами, а столбцы — строками.
###
X_T_X
🔗 Вывод:
array([[ 4, 280],
[ 280, 21000]])
🔗 Мы перемножаем матрицу X.T
[[ 1, 1, 1, 1],
[ 50, 60, 70, 100]]
🔗 На матрицу X
[[ 1, 50],
[ 1, 60],
[ 1, 70],
[ 1, 100]]
Кстати, че за единицы? Я про единицы, которые рядом с нашими признаками:
Единицы в первом столбце нужны, чтобы модель линейной регрессии учитывала свободный член w₀
⬇️⬇️⬇️
⚙️ Единицы нужны, чтобы линейная регрессия не привязывалась к точке (0, 0) и могла сдвигать прямую вверх или вниз. Грубо говоря, гайс, мы включаем столбец единиц чтобы включить w₀ (свободный член)
w₀ — это сдвиг прямой вверх или вниз
w₁ — это наклон прямой
🔗 Вот вам пример использования наших новых функций (Можете отдельно попробовать все):
import numpy as np
# Матрица X
X = np.array([[1, 50], [1, 60], [1, 70], [1, 100]])
# Транспонированная матрица X
X_T = X.T
# Печатаем результаты
print("Исходная матрица X:")
print(X)
print("\nТранспонированная матрица X.T:")
print(X_T)
# Считаем X_T_X
X_T_X = X_T.dot(X)
print("\nПроизведение X.T @ X:")
print(X_T_X)
6) 🔗 Таак, теперь находим обратную матрицу к ней, в нашей формуле она обозначена X⁻¹
⚙️ Последнее, что мы с вами сделали, это перемножили транспонированную матрицу на саму себя же:
import numpy as np
X = np.array([[1, 50], [1, 60], [1, 70], [1, 100]])
X_T_X = (X.T).dot(X)
X_T_X
🔗 Таак, мы просто красавчики, теперь найдем обратную ей матрицу, об этом я сказал в начале поста:
from numpy.linalg import inv
X_T_X_inverted = inv(X_T_X)
X_T_X_inverted
7️) ⚙️ Дописываем формулу до конца!
(Xᵀ * X)⁻ ¹ * Xᵀ * Y
w = X_T_X_inverted.dot(X.T).dot(Y)
print('w_1=%.5f, w_2=%.3f' % (w[0][0], w[1][0]))
Полный код:
import numpy as np
from numpy.linalg import inv
# Матрица X и вектор Y
X = np.array([[1, 50], [1, 60], [1, 70], [1, 100]])
Y = np.array([[10], [30], [40], [50]])
# Вычисление X^T * X
X_T_X = (X.T).dot(X)
# Обратная матрица (X^T * X)^-1
X_T_X_inverted = inv(X_T_X)
# Вычисление w = (X^T * X)^-1 * X^T * Y
w = X_T_X_inverted.dot(X.T).dot(Y)
print('w_1=%.5f, w_2=%.3f' % (w[0][0], w[1][0]))
Вот такой у нас получится вывод с прошлого поста. Что это вообще такое?
y = -17.5 + 0.714 * x — мы получили уравнение прямой
y — является целевой переменной (это как раз предсказываемое значение, цена нашей хаты)
x — это признак или независимая переменная (площадь нашей хаты)
w_1=-17.50000, w_2=0.714
Набор из 4 точек, которые мы построили тут (Смотрите коменты) (https://t.me/pywithCodeLab/819), описывает прямая линия с этим уравнением y = -17.5 + 0.714 * x