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

Scientific Python предоставляет ряд процедур оптимизации в пакете scipy.optimize. В этой статье мы реализуем две из этих подпрограмм. Мы воспользуемся данными прогноза жилищного строительства Бостона, доступными на сайте Kaggle. Вы можете получить его здесь". Начнем с импорта необходимых пакетов.

import pandas as pd
import numpy as np
from scipy.optimize import fmin, minimize

Давайте получим, загрузим и извлечем наши массивы numpy.

train_df = pd.read_csv('./train.csv', index_col='ID')
y = train_df['medv'].values
y = y.reshape(-1, 1)
train_df['constant'] = 1
columns = ['constant', 'crim', 'zn', 'indus', 'chas', 'nox', 'rm', 'age', 'dis', 'rad', 'tax', 'ptratio', 'black', 'lstat']
x = train_df[columns].values

Мы будем реализовывать простую линейную регрессию y = wx, поэтому давайте создадим экземпляр массива w с начальным значением 0. Нам нужно обращать внимание на наши размеры, чтобы не было статических значения для наших размеров.

w = np.zeros([x.shape[1], 1])

Затем давайте создадим нашу функцию линейной регрессии.

def pred(x, w):
    return np.dot(x, w)

Затем мы можем делать прогнозы, вызывая эту функцию.

y_pred = pred(x, w)

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

def loss(_w):
    p = pred(x, _w)
    e = y - p
    se = np.power(e, 2)
    rse = np.sqrt(np.sum(se))
    rmse = rse / y.shape[0]
    return rmse

фмин

Первая процедура оптимизации, которую мы будем использовать, - это fmin. Здесь используется симплексный алгоритм Нелдера-Мида, чтобы найти минимум нашей функции. Это не требует, чтобы наша функция была дифференцируемой. Однако он не подходит для многомерных данных. Давай воспользуемся этим. Нам нужно указать количество итераций, чтобы этот алгоритм мог найти подходящие значения. Без него количество шагов по умолчанию для ваших данных может обеспечить

min = fmin(loss, w, maxiter=1000)

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

y_min = pred(x, min)
out = pd.DataFrame({'y': y[:,0], 'y_pred': y_pred[:,0], 'y_min': pred(x, min)})
out.head(n=15)

минимизировать

При работе с многомерными данными или функциями потерь с производной первого или второго порядка мы можем использовать minim (). Это много вещей, поэтому подходить к этому лучше всего осторожно и постепенно.

Начнем с реализации того же решения, что и fmin ().

nms = minimize(loss, w, method='nelder-mead')

Первое, что вы могли заметить, это то, что теперь у нас есть параметр method. Чтобы воспроизвести fmin (), мы указываем ‘nelder-mead’. Во-вторых, теперь у нас есть больше данных в результате вызова minim (). В данном случае нас интересует параметр x. Приступим к прогнозированию.

out_2 = pd.DataFrame({'y': y[:,0], 'y_pred': y_pred[:,0], 'y_min': pred(x, nms.x)})
out_2.head()

Можно определить другую функцию, которая является производной от наших потерь, а затем использовать ее в вызове функции minimized (). Мы оставим это для другого поста.

На данный момент у нас есть весь приведенный выше код в сущности ниже.

До скорого.