Недавно я потратил некоторое время на изучение линейной регрессии и, в частности, на реализацию алгоритма градиентного спуска на 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()