Учиться, кодировать и настраивать…

Как я уже упоминал в своей предыдущей статье:



Помимо оптимизации градиентного спуска, существует другой подход, известный как метод обыкновенных наименьших квадратов или метод нормального уравнения. Этот подход, безусловно, является наиболее успешным и принят во многих наборах инструментов машинного обучения. Существует описательная причина того, что метод OLS / нормального уравнения оказался успешным и широко предпочтительным для градиентного спуска, к которому я вернусь во второй половине этой статьи. Во-первых, давайте перейдем к подходу и его реализации на Python, во-вторых, применим его к наборам практических данных и, наконец, интуитивно опишем, почему этот градиентный спуск превосходит его.

Подход обыкновенных наименьших квадратов для поиска списка / вектора параметров, который является минимумом функции стоимости, тета определяется как:

Его можно выразить в форме векторной алгебры, известной как нормальное уравнение.

Теперь давайте реализуем это в Python для одномерной линейной регрессии, полиномиальной регрессии и многомерной линейной регрессии:

Одновременная линейная регрессия OLS с использованием общей формы OLS:

Сформулирована двухмодульная реализация линейной регрессии с одной переменной с использованием OLS:

= ›Hypothesis (): это функция, которая вычисляет и выводит значение гипотезы целевой переменной, учитывая theta (theta_0, theta_1, theta_2,…., Theta_n) и Feature X в качестве входных данных. Реализация гипотезы () представлена ​​ниже:

def hypothesis(theta, X):
    h = np.ones((X.shape[0],1))
    X = X.reshape(X.shape[0], 1)
    one_column = np.ones((X.shape[0],1))
    X = np.concatenate((one_column, X), axis = 1)
    for i in range(0,X.shape[0]):
        h[i] = float(np.matmul(theta, X[i]))
    h = h.reshape(X.shape[0])
    return h

= ›Coeff_cal (): это основная функция, которая принимает набор функций, X и набор меток, y в качестве входных данных и возвращает вектор параметров, тета, которая является минимумом функции стоимости. Реализация coeff_cal () приведена ниже:

def coeff_cal(X,y):
    num = sum(np.multiply((X - np.mean(X)), (y - np.mean(y))))
    din = sum(np.square(X - np.mean(X)))
    theta_1 = num/din
    theta_0 = np.mean(y) - theta_1 * np.mean(X)
    return np.array([theta_0,theta_1])

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



navoneel1092283 / univariate_regression
Участвуйте в разработке navoneel1092283 / univariate_regression, создав учетную запись на GitHub. github.com



Постановка проблемы: «Учитывая численность населения города, проанализируйте и спрогнозируйте прибыль компании с помощью линейной регрессии»

Чтение данных в массивы Numpy:

data = np.loadtxt('data1.txt', delimiter=',')
X_train = data[:,0] #the feature_set
y_train = data[:,1] #the labels

Использование двухмодульной линейной регрессии с одной переменной OLS:

theta = coeff_cal(X_train, y_train)

# getting the predictions...
predictions = hypothesis(theta, X_train)

Линия регрессии. Визуализация полученного тета выполняется на точечной диаграмме:

scatter = plt.scatter(X_train, y_train, label="training data")
regression_line = plt.plot(X_train, predictions, 
                           label="linear regression")
plt.legend()
plt.xlabel('Population of City in 10,000s')
plt.ylabel('Profit in $10,000s')

Визуализация линии регрессии выглядит так:

Теперь давайте проанализируем производительность модели и статистически сравним OLS и пакетный градиентный спуск, в котором анализ производительности линейной регрессии с одной переменной градиентного спуска получается из:



Здесь OLS работает лучше, чем BGD с точки зрения средней абсолютной ошибки.

Полиномиальная регрессия OLS с использованием формы векторной алгебры OLS

Сформулирована одномодульная реализация линейной регрессии с одной переменной с использованием OLS:

= ›Hypothesis (): это функция, которая вычисляет и выводит значение гипотезы целевой переменной с учетом входных значений theta (theta_0, theta_1, theta_2,…., Theta_n), Feature X и Degree of the Polynomial n. Реализация гипотезы () представлена ​​ниже:

def hypothesis(theta, X, n):
    h = np.ones((X.shape[0],1))
    theta = theta.reshape(1,n+1)
    for i in range(0,X.shape[0]):
        x_array = np.ones(n+1)
        for j in range(0,n+1):
            x_array[j] = pow(X[i],j)
        x_array = x_array.reshape(n+1,1)
        h[i] = float(np.matmul(theta, x_array))
    h = h.reshape(X.shape[0])
    return h

= ›Получение минимумов функции затрат как тета:

from numpy.linalg import inv
theta = np.matmul(np.matmul(inv(np.matmul(x_array.transpose()
                  , x_array)), x_array.transpose()), y_train)

Теперь применим полиномиальную регрессию OLS (здесь квадратичную) к тому же набору данных.

data = np.loadtxt('data1.txt', delimiter=',')
X_train = data[:,0] #the feature_set
y_train = data[:,1] #the labels
x_array = np.ones((X_train.shape[0], n+1))
for i in range(0,X_train.shape[0]):
    for j in range(0,n+1):
        x_array[i][j] = pow(X_train[i],j)
theta = np.matmul(np.matmul(inv(np.matmul(x_array.transpose()
                  , x_array)), x_array.transpose()), y_train)

Линия регрессии. Визуализация полученного тета выполняется на точечной диаграмме:

import matplotlib.pyplot as plt 
#getting the predictions...
training_predictions = hypothesis(theta, X_train, 2)
scatter = plt.scatter(X_train, y_train, label="training data")
regression_line = plt.plot(X_train, training_predictions, label="polynomial (degree 2) regression")
plt.legend()
plt.xlabel('Population of City in 10,000s')
plt.ylabel('Profit in $10,000s')

Визуализация линии регрессии выглядит так:

Анализ производительности:

Производительность модели анализируется, и проводится двухстороннее сравнение. Другими словами, производительность полиномиальной регрессии OLS сравнивается с квадратичной регрессией градиентного спуска, а также сравнивается с линейной регрессией OLS.

Эффективность квадратичной регрессии градиентного спуска получается из



Из таблицы можно сделать следующие выводы:

  1. Квадратичная регрессия градиентного спуска дает наименьшую среднюю абсолютную ошибку
  2. Квадратичная регрессия OLS определяет наименьшую среднеквадратичную ошибку и среднеквадратичную ошибку
  3. Квадратичная регрессия OLS и линейная регрессия дают наивысший показатель R-квадрат.

Основываясь на трех приведенных выше пунктах, можно подтвердить, что

«Подход OLS более успешен, чем оптимизация градиентного спуска»

Причина. Возможная причина в том, что в градиентном спуске, если алгоритм, указанный в



внимательно изучено, видно, что не упоминается фиксированное количество итераций. Упоминается только «до схождения». Таким образом, случайное количество итераций не приведет к максимальной производительности. Реализация должна быть сделана таким образом, чтобы Алгоритм сам находил необходимое количество итераций для сходимости. Еще одна важная потенциальная угроза градиентного спуска:

«Что произойдет, если будут получены локальные минимумы вместо глобальных минимумов?»

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

Модифицированная реализация градиентного спуска (для полиномиальной регрессии) представлена ​​ниже:

def modified_BGD(theta, alpha, h, X, y, n): 
    # n = 1 for Linear Regression 
    k = 0 # number of iterations by the algorithm set as counter
    theta[0] = theta[0] - (alpha/X.shape[0]) * sum(h - y)
    for j in range(1,n+1):
        theta[j] = theta[j]-(alpha/X.shape[0])*sum((h-y)*pow(X,j))
    h = hypothesis(theta, X, n)
    cost = (1 / X.shape[0]) * 0.5 * sum(np.square(h - y))
    while(1):
        theta[0] = theta[0] - (alpha/X.shape[0]) * sum(h - y)
        for j in range(1,n+1):
            theta[j]=theta[j]-(alpha/X.shape[0])*sum((h-y)*pow(X,j))
        h = hypothesis(theta, X, n)
        if ((1/X.shape[0])*0.5*sum(np.square(h - y))) >= cost:
            break
        cost = (1 / X.shape[0]) * 0.5 * sum(np.square(h - y))
        k = k + 1
    theta = theta.reshape(1,n+1)
    return theta, cost, k

После этой реализации BGD статистически будет очень мало или совсем не будет различий в показателях производительности многовариантной и полиномиальной регрессии.

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

«Общая полиномиальная регрессия превосходит линейную регрессию, если выбрана правильная степень полинома»

Многомерная линейная регрессия OLS с использованием формы векторной алгебры OLS

Сформулирована одномодульная реализация линейной регрессии с одной переменной с использованием OLS:

= ›Hypothesis (): это функция, которая вычисляет и выводит значение гипотезы целевой переменной, учитывая theta (theta_0, theta_1, theta_2,…., Theta_n) и Feature Set X (вектор единиц измерения = количество выборок. ) в качестве входных данных. Реализация гипотезы () представлена ​​ниже:

def hypothesis(theta, X):
    n = X.shape[1]
    h = np.ones((X.shape[0],1))
    theta = theta.reshape(1,n)
    for i in range(0,X.shape[0]):
        h[i] = float(np.matmul(theta, X[i]))
    h = h.reshape(X.shape[0])
    return h

= ›Получение минимумов функции затрат как тета:

from numpy.linalg import inv
theta = np.matmul(np.matmul(inv(np.matmul(X_train.transpose(), X_train)), X_train.transpose()), y_train)

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



Постановка проблемы: «Учитывая размер дома и количество спален, проанализируйте и спрогнозируйте возможную цену дома»

data = np.loadtxt('data2.txt', delimiter=',')
X_train = data[:,[0,1]] #feature set
y_train = data[:,2] # label set
one_column = np.ones((X_train.shape[0],1))
X_train = np.concatenate((one_column, X_train), axis = 1)
from numpy.linalg import inv
theta = np.matmul(np.matmul(inv(np.matmul(X_train.transpose()
                  , X_train)), X_train.transpose()), y_train)

Параллельная визуализация характеристик, фактических и прогнозируемых целевых переменных с использованием трехмерных точечных графиков:

= ›Визуализация фактической целевой переменной:

from matplotlib import pyplot
from mpl_toolkits.mplot3d import Axes3D
sequence_containing_x_vals = list(X_train.transpose()[1])
sequence_containing_y_vals = list(X_train.transpose()[2])
sequence_containing_z_vals = list(y_train)
fig = pyplot.figure()
ax = Axes3D(fig)
ax.scatter(sequence_containing_x_vals, sequence_containing_y_vals,
           sequence_containing_z_vals)
ax.set_xlabel('Living Room Area', fontsize=10)
ax.set_ylabel('Number of Bed Rooms', fontsize=10)
ax.set_zlabel('Actual Housing Price', fontsize=10)

= ›Визуализация целевой переменной прогноза:

# Getting the predictions...
predictions = hypothesis(theta, X_train)
from matplotlib import pyplot
from mpl_toolkits.mplot3d import Axes3D
sequence_containing_x_vals = list(X_train.transpose()[1])
sequence_containing_y_vals = list(X_train.transpose()[2])
sequence_containing_z_vals = list(predictions)
fig = pyplot.figure()
ax = Axes3D(fig)
ax.scatter(sequence_containing_x_vals, sequence_containing_y_vals,
           sequence_containing_z_vals)
ax.set_xlabel('Living Room Area', fontsize=10)
ax.set_ylabel('Number of Bed Rooms', fontsize=10)
ax.set_zlabel('Housing Price Predictions', fontsize=10)

Анализ производительности и статистическое сравнение с многовариантной линейной регрессией градиентного спуска:

Эффективность многомерной линейной регрессии градиентного спуска получается из



Аналогичным образом, метод OLS / нормального уравнения показал лучшие результаты, чем метод градиентного спуска. Модифицированная реализация градиентного спуска для многомерной линейной регрессии приведена ниже:

def modified_BGD(theta, alpha, h, X, y, n):
    # n is the number of features
    k = 0 # required number of iterations set as counter variable
    theta[0] = theta[0] - (alpha/X.shape[0]) * sum(h - y)
    for j in range(1,n+1):
        theta[j] = theta[j] - (alpha/X.shape[0]) * sum((h - y) 
                               * X.transpose()[j])
    h = hypothesis(theta, X, n)
    cost = (1 / X.shape[0]) * 0.5 * sum(np.square(h - y))
    while(1):
        theta[0] = theta[0] - (alpha/X.shape[0]) * sum(h - y)
        for j in range(1,n+1):
            theta[j] = theta[j] - (alpha/X.shape[0]) * sum((h - y) 
                                   * X.transpose()[j])
        h = hypothesis(theta, X, n)
        if((1/X.shape[0])*0.5*sum(np.square(h-y_train))) >= cost:
            break
        cost = (1 / X.shape[0]) * 0.5 * sum(np.square(h - y))
        k = k + 1
    theta = theta.reshape(1,n+1)
    return theta, cost, k

Основным недостатком модифицированной реализации градиентного спуска является то, что требуется много времени для схождения, то есть требуется выполнить большое количество, скажем, 600 тыс. Итераций, чтобы сойтись или достичь глобальных минимумов. Но с другой стороны, запуская один оператор, мы получаем глобальные минимумы тэты в случае метода OLS / нормального уравнения.

Это все о реализации одномерной, полиномиальной и многовариантной регрессии с использованием подхода OLS / нормального уравнения.

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