При обучении с учителем алгоритм обучается с использованием функции, называемой функцией потерь, функцией стоимости или функцией ошибки, которая является функцией прогнозируемого результата и желаемого результата. Если h(xi) — прогнозируемый результат, а yi — желаемый результат, функция потерь равна

где n — общее количество записей, для которых делаются прогнозы. Определенная функция представляет собой среднеквадратичную ошибку (MSE). MSE — это функция потерь для регрессионной модели. Цель состоит в том, чтобы узнать значение параметров, которые минимизируют функцию стоимости. Машинное обучение использует алгоритмы оптимизации, которые можно использовать для минимизации функции потерь. Наиболее широко используемый метод оптимизации называется градиентным спуском.

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

1. АЛГОРИТМ ГРАДИЕНТНОГО СПУСКАНИЯ

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

Функциональная форма простой модели линейной регрессии задается выражением

где Bo называется смещением или пересечением, B1 — это вес признака или коэффициент регрессии, Ei — ошибка прогноза.

Прогнозируемое значение yi записывается как y_hati и определяется как

где B_hat0 и b_hat1 — оценочные значения B0 и B1. Ошибка выдается

Функция стоимости для модели линейной регрессии представляет собой общую ошибку (среднеквадратическую ошибку) по всем N записям и определяется как

Ошибка является функцией B0 и B1. Это достойная чисто выпуклая функция, имеющая глобальный минимум. Алгоритм градиентного спуска начинается со случайного начального значения и движется к оптимальному решению.

Градиентный спуск находит оптимальные значения B0 и B1, которые минимизируют функцию потерь, используя следующие шаги:

1. Случайным образом угадать начальные значения B0 (смещение или пересечение) и B1 (вес признака).

2. Вычислите оценочное значение переменной результата y_hati для инициализированных значений смещения и весов.

3. Рассчитайте функцию среднеквадратичной ошибки (MSE)

4. Отрегулируйте значения B0 и B1, рассчитав градиенты функции ошибки.

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

Частные производные MSE по B0 и B1 определяются выражением

5. Повторяйте шаги с 1 по 4 для нескольких итераций, пока ошибка не перестанет уменьшаться или изменение стоимости не станет бесконечно малым.

Значения B0 и B1 в точках минимальной стоимости являются наилучшей оценкой параметров модели.

2. Реализуйте алгоритм градиентного спуска для модели линейной регрессии

Для лучшего понимания алгоритма GD мы реализуем алгоритм GD, используя набор данных Advertising.csv. Набор данных содержит примеры расходов на рекламу по нескольким каналам, таким как радио, телевидение и газета, и соответствующий доход от продаж, полученный в разные периоды времени. Набор данных взят с сайта Kaggle здесь я также добавлю ссылку https://www.kaggle.com/bumba5341/advertisingcsv

Набор данных имеет следующие элементы:

1. Телевидение — тратьте на телевизионную рекламу.

2. Радио — тратьте на радиорекламу

3. Газета. Потратьтесь на рекламу в газетах.

4. Продажи — полученный доход от продаж

Для прогнозирования продаж с использованием расходов на разные рекламные каналы мы можем построить регрессионную модель.

2.1 Загрузка набора данных

Загрузите набор данных, используя библиотеку панды.

import pandas as pd
import numpy as np
import warnings
warnings.filterwarnings('ignore')
sales_df =  pd.read_csv('Advertising.csv')
sales_df.head()

2.2 Установка переменных X и Y

Для построения регрессионной модели входные данные TV, Radio и Newspaper берутся как функции X, а продажи Y берутся как переменная результата.

x = sales_df[['TV','Radio','Newspaper']]
y = sales_df['Sales']

2.3. Стандартизация X и Y

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

y = np.array((y-y.mean())/y.std())

x = x.apply( lambda rec:(rec -rec.mean())/rec.std(), ось = 0)

2.4 Реализация алгоритма градиентного спуска

Для реализации шагов, описанных в разделе «Градиентный спуск», необходимо реализовать набор следующих служебных методов:

  1. Метод 1: Метод случайной инициализации смещения и весов
  2. Метод 2: Метод расчета прогнозируемого значения Y, то есть Y с учетом смещения и весов.
  3. Метод 3: метод расчета функции стоимости на основе прогнозируемых и фактических значений Y.
  4. Метод 4: метод расчета градиентов и корректировки смещения и весов.

Метод 1: случайная инициализация смещения и весов

Метод случайным образом инициализирует смещение и веса. В качестве параметра принимает количество весов, которые необходимо инициализировать.

import random
def initialize(dim):
    np.random.seed(seed = 42)
    random.seed(42)
    b= random.random()
    w = np.random.rand(dim)
    return b,w

Чтобы инициализировать смещение и 3 веса, поскольку у нас есть три входных переменных TV, Radio и Newspaper, мы можем вызвать метод initialize() следующим образом:

b,w = initialize(3)
print("Bias:",b,"Weights :",w)

Метод 2. Предсказание значений Y на основе смещения и весов

Рассчитайте значения Y для всех входных данных, учитывая смещение и веса. Мы будем использовать матричное умножение весов на значения входных переменных. Метод dot() в библиотеке numpy можно использовать для умножения матриц. Каждую строку X можно умножить на столбец весов, чтобы получить прогнозируемую переменную результата.

# Inputs:
# b - bias
# w - weights
# X - the input matrix
def predict_Y(b,w,x):
     return b + np.dot(x,w)
b, w = initialize(3)
y_hat = predict_Y(b,w,x)
y_hat[0:10]

Метод 3. Расчет функции затрат — MSE

Вычислите среднеквадратичную ошибку (MSE) по

1. Вычисление разницы между предполагаемым Y_hat и фактическим Y.

2. Вычисление квадрата вышеуказанных остатков и суммирование общих записей.

3. Деление на количество наблюдений.

import math
# Inputs
# y- Actaul values of y
def get_cost (Y, Y_hat):
    y_resid = y-y_hat
    return np.sum(np.dot(y_resid.T,y_resid))/len(y_resid)

Вызов get_cost() после инициализации смещения и весов и вычисления прогнозируемых значений для переменной результата.

b, w = initialize(3)
y_hat = predict_Y(b,w,x)
get_cost(y,y_hat)

Способ 4. Обновление смещения и веса

Это самый важный метод, смещение и веса корректируются на основе градиента функции стоимости. Смещение и веса будут обновлены в методе update_beta() с использованием следующего градиента.

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

В функцию передаются следующие параметры:

1. x, y: входные и выходные переменные
2. y_hat: прогнозируемое значение с текущим смещением и весами
3. b_0, w_0: текущее смещение и веса
4. Скорость обучения: обучение скорость для настройки шага обновления

def update_beta(x,y,y_hat,b_0,w_0,learning_rate):
    db = (np.sum(y_hat-y)*2)/len(y)
    dw = (np.dot((y_hat-y),x)*2)/len(y)
    b_1 = b_0 - learning_rate * db
    w_1 = w_0 - learning_rate* dw
    return b_1, w_1

Ниже приведен пример смещения и весов один раз после инициализации. Параметр обучения раньше был равен 0,01.

b,w  = initialize(3)
print("After Initialize - Bias: ",b," Weights: ",w)
y_hat = predict_Y(b,w,x)
b,w =  update_beta(x,y,y_hat,b,w,0.01)
print("After first update - Bias: ",b," Weights: ",w)

2.5 Поиск оптимального смещения и веса

Обновления смещения и весов необходимо выполнять итеративно, пока стоимость не станет минимальной. Это может занять несколько итераций и отнять много времени. Есть два подхода к остановке итераций.

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

мы определим метод run_gradient_descent(), который принимает alpha и num_iterations в качестве параметров и вызывает такие методы, как initialize(), predict_y(), get_cost() и update_beta().

Также внутри метода.

  1. переменная gd_iterations_df отслеживает стоимость каждые 10 итераций.
  2. будет использоваться значение по умолчанию 0,01 для параметра обучения и 100 для количества итераций.
def run_gradient_descent(x,y,alpha = 0.01, num_iterations = 100):
    b,w = initialize(x.shape[1])
    iter_num = 0
    gd_iterations_df = pd.DataFrame(columns = ['iteration','cost'])
    result_idx = 0
    for each_iter in range(num_iterations):
        y_hat = predict_Y(b,w,x)
        this_cost = get_cost(y,y_hat)
        prev_b = b
        prev_w = w
        b,w = update_beta(x,y,y_hat,prev_b,prev_w,alpha)
        if(iter_num%10 == 0):
            gd_iterations_df.loc[result_idx] = [iter_num,this_cost]
            result_idx = result_idx+1
        iter_num +=1
    print("Final estimate of b and w: ", b,w)
    return gd_iterations_df,b,w
gd_iteration_df, b, w = run_gradient_descent(x,y,alpha=0.001,num_iterations=200)

Выведем стоимость за каждые 10 итераций.

Можно отметить, что стоимость одинакова в конце каждой итерации.

2.6 График функции стоимости в зависимости от итераций

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

import matplotlib.pyplot as plt
import seaborn as sn
plt.plot(gd_iteration_df['iteration'],gd_iteration_df['cost'])
plt.xlabel("Number of iteration")
plt.ylabel("Cost of MSE")

print("final estimate of b,w: ",b,w)

Веса являются стандартизированными значениями, поскольку мы использовали стандартизированные значения Y и X. Это означает, что при одном изменении стандартного отклонения в расходах на телевидение доход от продаж изменяется на 1,5599903 стандартных отклонения и так далее.

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

alpha_df_1, b, w = run_gradient_descent(x,y,alpha = 0.01,num_iterations= 2000)

что произойдет, если мы изменим параметр обучения и используем меньшее значение (например, 0,001)?

alpha_df_1, b, w = run_gradient_descent(x,y,alpha = 0.001,num_iterations= 2000)

Теперь мы наносим стоимость после каждой итерации для разных параметров скорости обучения (альфа-значения).

plt.plot(alpha_df_1['iteration'],alpha_df_1['cost'],label = 'alpha = 0.01')
plt.plot(alpha_df_2['iteration'],alpha_df_2['cost'],label = 'alpha = 0.00001')
plt.legend()
plt.ylabel('cost')
plt.xlabel('number of iterations')
plt.title('cost vs. iterations for different alpha values')

График показал, что скорость обучения выше для альфа-значения 0,01 по сравнению с 0,001. Для меньших значений обучение может быть медленнее, тогда как более высокая скорость может привести к пропуску минимумов функции стоимости. Необходимо искать оптимальный параметр обучения.

Заключение

Реализация алгоритма градиентного спуска в этой статье с использованием библиотеки numpy предназначена только для нашего понимания того, как он работает. Но на практике мы будем использовать библиотеку обучения scikit на питоне, о которой поговорим в следующей статье. Мы узнали о том, как машины учатся, и о разнице между контролируемым и неконтролируемым обучением. Модель строится путем определения функции стоимости и использования алгоритма оптимизации для минимизации функции стоимости. Внедрение алгоритмов градиентного спуска для изучения регрессионной модели.

об авторе

Привет, я Каджал Кумари. Я получил степень магистра в IIT (ISM) Dhanbad в области компьютерных наук и инженерии. На данный момент я работаю инженером по машинному обучению в Хайдарабаде. Вы также можете проверить несколько других блогов, которые я написал здесь.