Недавно я потратил некоторое время на изучение линейной регрессии и, в частности, на реализацию алгоритма градиентного спуска на Python. Некоторые из вас, возможно, уже знают, что существуют библиотеки Python для поддержки алгоритмов линейной регрессии, такие как `sklearn`. Но вы не поймете скрытой логики. Я хотел бы написать алгоритм с помощью numpy и pandas, чтобы полностью понять эту логику.

Немного о математике

Цель линейной регрессии - минимизировать функцию затрат:

где гипотеза задается линейной моделью:

Параметр в этой модели - значения θ. Это значения, которые нам нужны для минимизации функции стоимости J (θ). Один из способов сделать это - использовать достойный алгоритм пакетного градиента. В пакетном градиенте значения обновляются во время каждой итерации:

С каждой итерацией параметр θ приближается к оптимальным значениям, при которых достигается наименьшая стоимость J (θ).

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

Начните с бизнес-кейса

Если вас не устраивают математические уравнения, не беспокойтесь, давайте начнем с примера, чтобы понять, как работает этот алгоритм. Предположим, вы планируете открыть ресторан и хотите выбрать город в своей стране. У вас уже есть набор данных, в котором говорится о населении города и его прибыли от фургона с едой в этом городе.

Вы можете скачать образец набора данных по этой ссылке: https://github.com/zhaoyi0113/machine-learning/blob/master/training/MachineLearning/week2/machine-learning-ex1/ex1/ex1data1.txt.

Первый столбец - это население города, а второй - прибыль. Отрицательное значение прибыли указывает на убыток. Ваша задача - выбрать, в каком городе открыть ресторан. Ниже приведены первые образцы данных из набора данных:

6.1101,17.592
5.5277,9.1302
8.5186,13.662
7.0032,11.854
5.8598,6.8233
8.3829,11.886
7.4764,4.3483
8.5781,12
6.4862,6.5987
5.0546,3.8166

С набором данных первое, что мы хотим сделать, - это визуализировать данные, чтобы узнать их масштаб и распределенный тренд. Построить двухмерный набор данных на Python довольно просто с помощью pandas. (Многие другие проблемы, с которыми вы столкнетесь в реальной жизни, многомерны)

import pandas as pd
import pylab
df = pd.read_csv('./ex1data1.txt', names=['x','y'])
pylab.plot(df['x'], df['y'],'o')
pylab.show()

Затем нужно подогнать параметры линейной регрессии θ к нашему набору данных с помощью градиентного спуска.

def compute_cost_function(m, t0, t1, x, y):
    return 1/2/m * sum([(t0 + t1* np.asarray([x[i]]) - y[i])**2 for i in range(m)])

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

grad0 = 1.0/m * sum([(t0 + t1*np.asarray([x[i]]) - y[i]) for i in range(m)])
grad1 = 1.0/m * sum([(t0 + t1*np.asarray([x[i]]) - y[i])*np.asarray([x[i]]) for i in range(m)])
# update the theta_temp
theta1 = t0 - alpha * grad0
theta2 = t1 - alpha * grad1

Мы можем установить максимальное время итерации, чтобы остановить итерацию, и значение theta1 и theta2 будет значением параметра J (θ). И, наконец, нарисуйте линейный y = theta1 + theta2 * x на рисунке ниже:

Вы можете найти полный исходный код Python по адресу https://github.com/zhaoyi0113/machine-learning/blob/master/training/MachineLearning/week2/machine-learning-ex1/ex1/python/solution.py

Вышеупомянутый метод подробно описывает, как работает градиентный спуск. Затем давайте посмотрим, как это может быть реализовано библиотекой sklearn в python. Ниже приведен исходный код, который делает то же самое:

import matplotlib.pyplot as plt
import numpy as np
from sklearn import  linear_model
from sklearn.metrics import mean_squared_error, r2_score
import pandas as pd
df = pd.read_csv('../ex1data1.txt', names=['x','y'])
x = pd.DataFrame(df, columns=['x'])
y = pd.DataFrame(df, columns=['y'])
# Create linear regression object
regr = linear_model.LinearRegression()
# Train the model using the training sets
regr.fit(x, y)
# Make predictions using the testing set
y_pred = regr.predict(x)
print('y pred', y_pred);
plt.scatter(x, y,  color='black')
plt.plot(x, y_pred, color='blue', linewidth=3)
plt.show()