Главная страница
Навигация по странице:

  • Диаграмма для операции вычисления градиентов

  • Математическое представление

  • Определение самого важного признака

  • Шаг 1. Набор моделей линейной регрессии

  • Курсовая работа. Глубокое обучение


    Скачать 4.97 Mb.
    НазваниеГлубокое обучение
    АнкорКурсовая работа
    Дата26.06.2022
    Размер4.97 Mb.
    Формат файлаpdf
    Имя файлаVeydman_S_Glubokoe_obuchenie_Legkaya_razrabotka_proektov_na_Pyth.pdf
    ТипДокументы
    #615357
    страница6 из 22
    1   2   3   4   5   6   7   8   9   ...   22
    Линейная регрессия: еще одна визуализация и математическая модель
    X
    W
    ν
    P
    L
    Λ
    Y
    Рис. 2.3. Вычислительный граф для уравнения линейной регрессии.
    Жирным выделены входные данные, буква W обозначает веса
    Представим функцию потерь как набор вложенных функций:

    Линейная регрессия
    67
    Свободный член
    Благодаря диаграмме несложно понять, как добавить в нашу модель свободный член. Ведь это еще один элемент диаграммы, отвечающий за
    «смещение» (bias), как показано на рис. 2.4.
    X
    W
    γ
    N
    P
    L
    α
    Λ
    B
    Y
    Чем меньше, тем лучше
    Рис. 2.4. Вычислительный граф для функции линейной регрессии с добавленным членом смещения
    Прежде чем переходить к написанию кода, нужно понять, что поменялось в математическом представлении после добавления смещения. К уже знакомому нам скалярному произведению в каждом элементе p
    i
    вектора предсказания будет прибавляться константа b:
    Обратите внимание, что поскольку в линейной регрессии всего одно пересечение линии оценки, к каждому наблюдению добавляется одно
    и то же значение смещения. В следующем разделе мы поговорим о том, как это влияет на вычисление производных.
    Код
    Теперь мы готовы написать функцию, которая принимает данные на- ших наблюдений X
    batch
    , целевые значения y
    batch
    и дает на выходе прогноз и функцию потерь. Напомню, что в случае вложенных функций вычис- ление производных происходит в два этапа. Сначала во время «прямого прохода» входные данные последовательно пропускаются через набор операций с сохранением полученного результата. Затем следует «обрат- ный проход», во время которого сохраненные результаты применяются для вычисления соответствующих производных.

    68
    Глава 2. Основы глубокого обучения
    Результаты прямого прохода мы будем сохранять в словарь. Чтобы от- делить их от параметров (которые также потребуются во время обратного прохода), поместим параметры в отдельный словарь:
    def forward_linear_regression(X_batch: ndarray, y_batch: ndarray, weights: Dict[str, ndarray])
    -> Tuple[float, Dict[str, ndarray]]:
    '''
    Прямой проход для линейной регрессии.
    '''
    # проверяем совпадение размеров X и y assert X_batch.shape[0] == y_batch.shape[0]
    # проверяем допустимость умножения матриц assert X_batch.shape[1] == weights['W'].shape[0]
    # проверяем, что B это объект ndarray размером 1x1
    assert weights['B'].shape[0] == weights['B'].shape[1] == 1
    # вычисления
    N = np.dot(X_batch, weights['W'])
    P = N + weights['B']
    loss = np.mean(np.power(y_batch — P, 2))
    # сохранение информации, полученной во время прямого прохода forward_info: Dict[str, ndarray] = {}
    forward_info['X'] = X_batch forward_info['N'] = N
    forward_info['P'] = P
    forward_info['y'] = y_batch return loss, forward_info
    Теперь все готово к обучению модели. Поговорим о том, что это такое и как реализуется.

    Обучение модели
    69
    Обучение модели
    Воспользуемся инструментами и методами, с которыми мы познакоми- лись в прошлой главе, и вычислим для всех элементов w
    i
    вектора W, а также
    . Для этого выполним обратный проход, во время которого оценим частные производные вложенных функций при заданных входных значениях, а затем перемножим полученные результаты.
    Диаграмма для операции вычисления градиентов
    Концепция того, что мы хотим получить, представлена на рис. 2.5.
    ν
    [x]
    B
    [w]
    N
    P
    (N, B)
    (x, w)
    α
    L
    Y
    Λ
    ∂ γ
    ∂ w
    αα
    ∂ N
    (P, Y)
    ∂ Λ
    ∂ P
    (N, B)
    ∂ α
    ∂ B
    Рис. 2.5. Обратный проход по вычислительному графу линейной регрессии
    Еще раз напомню, что мы просто будем вычислять частные производные каждой из вложенных функций, двигаясь изнутри наружу, а затем оце- нивать их для значений, полученных во время прямого прохода. После чего останется получить произведение результатов.
    Математическое представление
    Согласно рис. 2.5, мы хотим получить следующее произведение:
    Первым делом вычислим элемент
    ∂Λ. Так как
    , для всех элементов векторов Y и P получим:

    70
    Глава 2. Основы глубокого обучения
    Вот как это выражение выглядит в виде кода:
    dLdP = -2 * (Y — P)
    Следующим идет элемент, содержащий матрицы:
    . Но так как под обозначением
    α скрывается всего лишь свободный член, можно при- менить уже знакомую по предыдущей главе логику: маленькое увеличе- ние любого элемента матрицы N приведет к такому же увеличению вектора P, который равен
    . Соответственно производная рассматриваемого элемента будет матрицей, заполненной единицами, по форме совпадающей с матрицей N.
    Код для такой производной выглядит очень просто:
    dPdN = np.ones_like(N)
    Ну и наконец, компонент
    . В конце предыдущей главы мы установили, что при вычислении производных вложенных функций, в случае когда внутри осуществляется умножение матриц, можно про- вести следующую замену:
    В виде кода это выглядит так:
    dNdW = np.transpose(X, (1, 0))
    Сделаем то же самое для свободного члена. Так как мы его просто при- бавляем, его частная производная будет равна 1:
    dPdB = np.ones_like(weights['B'])
    Осталось получить произведение всех производных, проследив за пра- вильным порядком умножения содержащих матрицы компонентов dNdW
    и dNdX

    Обучение модели
    71
    Код для вычисления градиента
    Напомню, что нужно взять все, что мы вычислили и ввели во время пря- мого прохода (на рис. 2.5 эти компоненты обозначены как X, W, N, B, P и y), и рассчитать частные производные и
    . Это реализует при- веденный ниже код. Входные данные W и B представлены в виде словарей, первый из которых, содержащий веса, называется weights
    , а второй, со- держащий остальные параметры, — forward_info
    :
    def loss_gradients(forward_info: Dict[str, ndarray], weights: Dict[str, ndarray]) -> Dict[str, ndarray]:
    '''
    Вычисление dLdW и dLdB для модели линейной регрессии.
    '''
    batch_size = forward_info['X'].shape[0]
    dLdP = -2 * (forward_info['y'] — forward_info['P'])
    dPdN = np.ones_like(forward_info['N'])
    dPdB = np.ones_like(weights['B'])
    dLdN = dLdP * dPdN
    dNdW = np.transpose(forward_info['X'], (1, 0))
    # умножение матриц, в котором первым идет компонент
    # dNdW (см. примечание в конце предыдущей главы)
    dLdW = np.dot(dNdW, dLdN)
    # суммирование по измерению, представляющему размер набора
    # (объяснение ниже)
    dLd B = (dLdP * dPdB).sum(axis=0)
    loss_gradients: Dict[str, ndarray] = {}
    loss_gradients['W'] = dLdW
    loss_gradients['B'] = dLdB
    return loss_gradients

    72
    Глава 2. Основы глубокого обучения
    Как видите, мы просто вычисляем все производные и перемножаем их, проследив за порядком следования матриц
    1
    . Вскоре вы убедитесь, что это действительно работает. Впрочем, после того как в предыдущей главе мы интуитивно доказали применимость цепного правила, удивления быть не должно.
    Вычисленный градиент функции потерь мы сохраняем в словарь: веса — как ключи, а параметры, увеличивающие влияние весов на потери, — как значения. Словарь весов структурирован аналогичным способом. Следовательно, перебирать веса модели можно следующим образом:
    for key in weights.keys():
    weights[key] -= learning_rate * loss_grads[key]
    Именно такой способ хранения указанных параметров ничем не обусловлен. Можно сохранить их и другим способом, просто в этом случае они будут просматриваться в другом порядке и ссылаться на них мы будем по-другому.
    Обучение модели
    Теперь нужно создать цикл из следующих операций:
    1. Выбор набора данных.
    2. Прямой проход модели.
    3. Обратный проход модели с применением данных, полученных во время прямого прохода.
    4. Применение вычисленных градиентов для обновления весов.
    Репозиторий Jupyter Notebook к этой главе (
    https://oreil.ly/2TDV5q9
    ) содер- жит код функции train
    , предназначенной для обучения нашей модели. Он реализует все вышеуказанные шаги и, кроме того, перемешивает данные, чтобы они подавались в функцию в случайном порядке. Вот ключевые строки кода, которые повторяются внутри цикла for
    :
    1
    Кроме того, мы суммируем элементы dLdB
    вдоль оси 0; зачем это нужно, я подробно объясню чуть позже.

    Оценка точности модели
    73
    forward_info, loss = forward_loss(X_batch, y_batch, weights)
    loss_grads = loss_gradients(forward_info, weights)
    for key in weights.keys(): # 'weights' и 'loss_grads' имеют
    # одинаковые ключи weights[key] -= learning_rate * loss_grads[key]
    После этого обучающая функция запускается определенное количество раз на всем тренировочном наборе данных:
    train_info = train(X_train, y_train, learning_rate = 0.001, batch_size=23, return_weights=True, seed=80718)
    Обучающая функция возвращает кортеж train_info
    , один из элементов которого — это параметры или веса, показывающие, как в процессе тре- нировки изменилась модель.
    В глубоком обучении термины «параметры» и «веса» используются как синонимы. В этой книге они тоже равнозначны.
    Оценка точности модели
    Но как понять, насколько корректно построенная модель раскрывает вза- имосвязи в данных? Обучающая выборка представляет собой лишь часть от общей совокупности данных. А перед нами строит задача построить модель, выявляющую взаимосвязи во всей совокупности, несмотря на ограниченность тренировочных данных.
    Всегда существует опасность, что модель начнет выбирать взаимосвязи, существующие в обучающей выборке, но отсутствующие в совокупности данных. Представьте, что в выборку случайно попали дома с тремя ван- ными комнатами, облицованные желтым сланцем, которые предлагаются по относительно низкой цене. Нейронная сеть обнаружит эту законо- мерность, хотя в общей совокупности данных она не наблюдается. Это

    74
    Глава 2. Основы глубокого обучения явление называется переобучением (overfitting). Как понять, что у модели может быть подобный недостаток?
    Чтобы избежать такой ситуации, данные, предназначенные для обучения модели, разбивают на обучающий набор (training set) и тестовый набор
    (testing set). Первый используется для обучения модели (то есть для итеративного обновления весов), после чего точность работы модели оценивается на тестовых данных.
    В основе этого подхода лежит простая логика. Если модель смогла обна- ружить взаимосвязи, которые работают и на остальной части обучающей
    выборки (то есть на всем наборе данных), велика вероятность, что они присутствуют и в общей совокупности данных.
    Код
    Давайте попробуем оценить нашу модель на тестовом наборе. Первым делом напишем функцию, генерирующую предсказания, обрезав уже знакомую нам функцию forward_loss
    :
    def predict(X: ndarray, weights: Dict[str, ndarray]):
    '''
    Генерация предсказаний для модели линейной регрессии.
    '''
    N = np.dot(X, weights['W'])
    return N + weights['B']
    Теперь возьмем веса, которые возвращает обучающая функция, и на- пишем:
    preds = predict(X_test, weights) # weights = train_info[0]
    Насколько хороши эти предсказания? Пока ответа на этот вопрос нет.
    Ведь мы еще не знаем, работает ли выбранный подход — определение модели как набора операций и ее обучение путем итеративной коррек- тировки параметров, для которой мы вычисляем частные производные функции потерь по различным параметрам. Так что будет здорово, если окажется, что все это хоть как-то работает.

    Код
    75
    Для проверки результатов построим график зависимости предсказанных значений от фактических. В идеальном случае все точки должны ока- заться на прямой линии с наклоном в 45 градусов. Реальный результат показан на рис. 2.6.
    Предсказанное значение
    Реальное зн ач ение
    Рис. 2.6. Сравнение предсказанных и действительных значений для модели линейной регрессии
    График выглядит вполне приемлемо, поэтому количественная оценка точности работы модели имеет смысл. Это можно сделать двумя спо- собами:
    y
    Вычислить абсолютное значение среднего расстояния между предска- заниями модели и фактическими значениями. Эту метрику называют
    средним модулем отклонения (mean absolute error, MAE):
    def mae(preds: ndarray, actuals: ndarray):
    '''
    Вычисление среднего линейного отклонения.
    '''
    return np.mean(np.abs(preds — actuals))

    76
    Глава 2. Основы глубокого обучения y
    Вычислить средний квадрат расстояния между предсказаниями модели и фактическими значениями. Эту метрику называют корнем из среднего
    квадрата отклонения (root mean squared error, RMSE):
    def rmse(preds: ndarray, actuals: ndarray):
    '''
    Вычисление корня из среднего квадрата отклонения.
    '''
    return np.sqrt(np.mean(np.power(preds — actuals, 2)))
    Для рассматриваемой модели были получены значения:
    Mean absolute error: 3.5643
    Root mean squared error: 5.0508
    Корень из среднего квадрата отклонения — распространенная метрика, поскольку она находится в одном масштабе с целевыми значениями.
    Разделив это число на среднее от целевого показателя, мы увидим, на- сколько полученный прогноз далек от фактического значения. В рас- сматриваемом случае среднее значение параметра y_test составляет
    22.0776
    . Соответственно прогнозы цен на недвижимость в этой модели в среднем отклоняются от фактических на 5.0508/22.0776 22.9%.
    Хорошая ли это точность? В репозиторий Jupyter Notebook к этой главе
    (
    https://oreil.ly/2TDV5q9
    ) добавлен результат, полученный на этом же на- боре данных для модели линейной регрессии, реализованной средствами
    Sci-Kit Learn — самой популярной библиотеки Python для машинного обучения. Эта модель дает средний модуль отклонения
    3.5666
    , а корень из среднего квадрата отклонения
    5.0482
    , что практически совпадает с результатами, которые дала наша модель, построенная на базе матема- тических формул. Это показывает, что такой подход вполне применим для построения моделей машинного обучения. Чуть позже мы расширим его на области нейронных сетей и глубокого обучения.
    Определение самого важного признака
    Перед началом моделирования признаки были масштабированы так, что- бы в результате среднее значение стало равным 0 и среднеквадратическое отклонение — 1. Зачем это нужно, подробно расскажу в главе 4. В случае линейной регрессии такое преобразование позволяет интерпретировать абсолютные значения коэффициентов как меру важности признаков.

    Код
    77
    Чем выше коэффициент, тем важнее признак. Вот коэффициенты в рас- сматриваемом случае:
    np.round(weights['W'].reshape(-1), 4)
    array([-1.0084, 0.7097, 0.2731, 0.7161, -2.2163, 2.3737, 0.7156,
    -2.6609, 2.629, -1.8113, -2.3347, 0.8541, -4.2003])
    Последний коэффициент больше всего по модулю, соответственно он и является самым важным. Сравнение этого признака с целевым значе- нием показано на рис. 2.7.
    Самый важный признак (нормализованный)
    Це ль
    Рис. 2.7. Сравнение самого важного признака с целевым значением в модели линейной регрессии
    Мы видим, что по мере роста значения признака значение целевого па- раметра уменьшается, причем это нелинейная зависимость. Изменение целевого параметра при изменении значения признака с –2 до –1 и с 1 до 2 будет разным. Позднее мы еще вернемся к этому моменту.
    На рис. 2.8 к этому графику добавлено соотношение между самым важным признаком и предсказаниями модели. Чтобы получить это соотношение,

    78
    Глава 2. Основы глубокого обучения мы пропустили через обученную модель данные, обработанные следую- щим образом:
    y
    Все признакам было присвоено их среднее значение.
    y
    За 40 итераций проведена интерполяция значений самого важного признака от –1.5 до 3.5, что примерно соответствует диапазону этого признака после масштабирования.
    Самый важный признак (нормализованный)
    Це ль/Прогно з
    Рис. 2.8. Сравнение самого важного признака с целевым значением и предсказаниями, данными моделью линейной регрессии
    График наглядно показывает ограниченность модели линейной регрессии.
    Несмотря на нелинейное соотношение между самым важным признаком и целью, в результате обучения извлекается только линейная связь. Такое поведение обусловлено внутренней структурой модели.
    Получается, что для определения более сложных, нелинейных закономер- ностей требуется другая модель. Но как ее построить? Ответом на этот вопрос станут нейронные сети.

    Основы нейронных сетей
    79
    Основы нейронных сетей
    Я показал, как на базе теоретической информации построить и обучить модель линейной регрессии. Но как, используя аналогичную цепочку рассуждений, спроектировать модель, которая сможет обнаруживать нелинейные взаимосвязи? Давайте создадим много моделей линейной регрессии, чьи результаты работы пропустим через нелинейную функ- цию, после чего применим еще одну модель линейной регрессии, которая и даст прогноз. Как вы вскоре увидите, вычислять градиенты для этой более сложной модели можно тем же способом, что и для модели линей- ной регрессии.
    Шаг 1. Набор моделей линейной регрессии
    Как выглядит создание «набора линейных регрессий»? В модели линей- ной регрессии происходит умножение матриц с наборами параметров.
    Матрица данных X, имеющая форму
    [размер_пакета,
    число_признаков]
    , умножается на матрицу весов W формы
    [число_признаков,
    1]
    , в резуль- тате мы получаем матрицу формы
    [размер_пакета,
    1]
    , то есть взвешенную
    сумму исходных признаков для каждого наблюдения в пакете. Поэтому набор линейных регрессий эквивалентен умножению матрицы входных данных на матрицу весов, имеющую форму
    [размер_пакета,
    число_выво- дов]
    , что даст для каждого наблюдения число_выводов взвешенных сумм исходных признаков.
    Что это за взвешенные суммы? Их можно рассматривать как «извле- ченные признаки», то есть как комбинации оригинальных признаков, способствующие последующему процессу обучения и обеспечивающие точность прогноза. Сколько таких признаков нужно в рассматриваемом случае? Так как оригинальных признаков у нас 13, создадим такое же число извлеченных признаков.
    1   2   3   4   5   6   7   8   9   ...   22


    написать администратору сайта