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

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

Если, случайно, этот учебник вам не по душе, я предлагаю класс CS231n Стэнфорда или Эндрю Нг, которые хорошо послужили мне в моем образовательном путешествии. В этой серии руководств из 16 частей я рассмотрю следующие темы:

  • Часть 1. Таксономия, определения, история, тизер линейной регрессии
  • Часть 2. Регуляризация, градиентный спуск (GD), стохастический градиентный спуск (SGD), обзор теории вероятностей
  • Часть 3. Настройка гиперпараметров, разбиение наборов данных, проверка, теория оптимизации глубокого обучения, выпуклость, отбеливающие преобразования.
  • Часть 4.метод Ньютона, логистическая регрессия, логарифмическая потеря, регрессия softmax, нормализация, кросс-энтропийная потеря, векторизация, поверхностные и глубокие модели, модели со скрытыми переменными
  • Часть 5: наиболее вероятная оценка, линейные нейронные сети (НС), функции активации, нелинейности, проблема исключающего ИЛИ, цепное правило
  • Часть 6. Нелинейное обратное распространение нейронной сети, инициализация веса
  • Часть 7. Расширение данных, автокодировщики, многозадачное обучение, свертка
  • Часть 8.Инвариантность перевода, нормализация данных, объединение, рекуррентные нейронные сети (RNN)
  • Часть 9. Рецептивные поля, теория приближения универсальных функций
  • Часть 10.Долгосрочная кратковременная память
  • Часть 11. Двунаправленные рекуррентные нейронные сети, регуляризация L1/L2, ансамбли, отсев, импульс
  • Часть 12. Методы второго порядка (т. е. Адама), пакетная нормализация, аппроксимация Z-оценки
  • Часть 13. Выборка, дивергенция Кульбака-Либлера (KLD), энтропия, неравенство Дженсена, модели со скрытыми переменными (LVM)
  • Часть 14. Вариационные автоэнкодеры (VAE), трюк с репараметризацией
  • Часть 15. Генеративные модели, генеративно-состязательные сети (GAN), состязательные возмущения
  • Часть 16.Будущие темы, такие как этический ИИ, «зеленые» вычисления, генеративные модели и игровой ИИ.

Часть 1: Что есть что?

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

в чем разница между глубоким обучением (DL), машинным обучением (ML) и искусственным интеллектом (ИИ)? Какие интересные вещи люди делают с DL? Почему такие классные вещи делаются сейчас?

Наконец, я выведу и объясню линейную регрессию, которую многие считают духовным предшественником знаменитой нейронной сети (НС).

ML — это подмножество DL, которое является подмножеством AI. Идеи об ИИ существовали всегда, но современное движение за компьютерный ИИ и его этимология в значительной степени возглавлялись американскими и английскими учеными 1950-х годов, согласно следующей временной шкале основных моментов:

Что вызвало этот современный ренессанс и продвинуло эту область через препятствия, такие как «зима ИИ»?

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

Как развивается эта область?

Учитывая математический, инструментальный характер алгоритмов машинного обучения, машинное обучение находит применение во многих областях данных с перекрестным опылением, таких как обработка естественного языка (NLP), компьютерное зрение (CV), автономные транспортные средства (AV), графические нейронные сети. (GNN), игры, робототехника, речь, электромагнитные сигналы и биомедицинские данные. Например, Внимание изначально было методом НЛП, но часто используется в алгоритмах CV, таких как знаменитая генеративная модель DALL-E 2. Свертка изначально была методом CV, но находит применение в большинстве НС, включая известную генеративную модель НЛП GPT-3. Адаптация и заимствование алгоритмов после кардинального улучшения какого-либо компонента машинного обучения имеет долгую историю и может привести к появлению новых захватывающих технологий и возможностей. Только обязательно процитируйте!

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

Мы стремимся выполнить регрессию y на x или, что то же самое, создать нейронную сеть, которую мы также можем рассматривать как «машину», для оценки каждого y(i) с высокой точностью при заданном x(i). В SL и регрессии этот набор данных называется нашим обучающим набором данных или данными, с помощью которых мы сформулируем модель, которую мы развернем для выполнения вывода на тестовом наборе данных. Детали этого разделения будут рассмотрены в части 3.

Давайте определим регрессионную модель или машину NN с помощью функции g (с параметрами w, пронумерованными от 1 до m), чьи выходные данные ŷ являются линейными по входным данным:

Обратите внимание, что эта функция эквивалентна «мелкой» двухслойной НС, где «глубокая» НС — это модель со многими слоями.

Как можно использовать эту модель?

Типичным примером приложения является автоматизированная машина для анализа лица, используемая для оценки возраста человека по изображению его лица. Вектор w представляет собой «наложенное изображение», которое взвешивает различные интенсивности пикселей серого изображения x.

Учитывая наш набор данных D, мы хотим оптимизировать w.

На этом этапе лекция по науке о данных должна представить соответствующую функцию потерь, с помощью которой можно оптимизировать веса. Вместо этого мы сначала рассмотрим, как получить функцию потерь, используя вероятностный подход, известный как оценка максимального правдоподобия (MLE). Рассмотрим конкретное значение y, можно получить натуральный логарифм (ln) функции плотности вероятности (PDF) для y:

где y параметризован θ в обозначении вероятности вместо w. Если эта PDF выпукла или существует один глобальный максимум, где вероятность монотонно убывает по обе стороны от вершины, то мы можем найти оптимальное значение для θ, используя один из самых простых инструментов исчисления: нахождение вершины параболы с помощью производная:

Это достигается путем определения единственного места, где параболическая функция не меняется или имеет производную, равную нулю.

Оценка MLE обладает следующими тремя свойствами:

  • Если оценщик эффективен, то он является несмещенным оценщиком с минимальной дисперсией (MVU) и должен быть решением уравнения правдоподобия. В этом случае имеем θML(y) = θMVU(y).
  • У уравнения правдоподобия может быть несколько решений.
  • MLE не может быть уникальным.

Мы можем использовать инструмент MLE для получения целевой функции среднеквадратичной ошибки (MSE), которую мы хотим минимизировать, таким образом выбирая наилучшее значение для наших весов w для нашей двухслойной линейной модели NN/линейной регрессии.

В задачах линейного моделирования данные x чаще всего предполагаются гауссовыми, распределенными вокруг линии тренда μ с дисперсией σ. Мы отбросим это предположение в последующих частях. В теории MLE логарифмическое правдоподобие (LL)PDF обучающего набора данных описывается с помощью суммы:

Мы используем правило логарифмического произведения, правило логарифмического частного, правило логарифмической мощности и алгебру, чтобы получить упрощенный LL:

Используя теорию MLE, мы решаем:

С помощью этого инструмента MLE и целевой функции MSE, полученной из линейного гауссовского предположения относительно x, мы возвращаемся к поиску оптимальных значений w. Если мы хотим свести к минимуму разницу между предсказаниями модели g и метками обучающих данных y, независимо от знака, мы могли бы определить целевую функцию среднеквадратичной ошибки (MSE):

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

Установив этот градиент равным нулю, мы, наконец, используем методологию MLE для решения вершины параболы этой выпуклой PDF:

Модели линейной регрессии/двухслойной линейной нейронной сети обладают следующими свойствами:

  1. Линейность. Связь между X и средним значением Y является линейной.
  2. Гомоскедастичность: дисперсия остатка одинакова для любого значения X.
  3. Независимость. Наблюдения не зависят друг от друга.
  4. Нормальность: при любом фиксированном значении X Y имеет нормальное распределение.

Чтобы поиграть с этим алгоритмом, заполните следующие вызовы функций:

import math
import numpy as np
# Note: please don't add any new package, you should solve this problem using only the packages above.
#-------------------------------------------------------------------------
'''
    Problem 1: Linear Regression (Maximum Likelihood)
    In this problem, you will implement the linear regression method based upon maximum likelihood (least square).
    w'x + b = y
    You could test the correctness of your code by typing `nosetests -v test1.py` in the terminal.
    Note: please don't use any existing package for linear regression problem, implement your own version.
'''

#--------------------------
def compute_Phi(x,p):
    '''
        Let's start with a simple dataset. This dataset (polynomial curve fitting) has been used in many machine learning textbooks.
        In this dataset, we create a feature matrix by constructing multiple features from one single feature.
        For example, suppose we have a data example, with an input feature of value 2., we can create a 4-dimensional feature vector (when p=4) 
        using the different polynoials of the input like this: ( 1., 2., 4., 8.). 
        Here the first dimension is the 0-th polynoial of 2., 2^0 = 1.
        The second dimension is the 1st polynoial of 2., 2^1 = 2
        The third dimension is the 2nd polynoial of 2., 2^2 = 4
        The third dimension is the 3rd polynoial of 2., 2^3 = 8
        Now in this function, x is a vector, containing multiple data samples. For example, x = [2,3,5,4] (4 data examples)
        Then, if we want to create a 3-dimensional feature vector (when p=3) for each of these examples, then we have a feature matrix Phi (4 by 3 matrix).
        [[1, 2,  4],
         [1, 3,  9],
         [1, 4, 16],
         [1, 5, 25]]
        In this function , we need to compute the feature matrix (or design matrix) Phi from x for polynoial curve fitting problem. 
        We will construct p polynoials of x as the p features of the data samples. 
        The features of each sample, is x^0, x^1, x^2 ... x^(p-1)
        Input:
            x : a vector of samples in one dimensional space, a numpy vector of shape n by 1.
                Here n is the number of samples.
            p : the number of polynomials/features
        Output:
            Phi: the design/feature matrix of x, a numpy matrix of shape (n by p).
                 The i-th column of Phi represent the i-th polynomials of x. 
                 For example, Phi[i,j] should be x[i] to the power of j.
    '''
    #########################################

    #########################################
    return Phi


#--------------------------
def least_square(Phi, y):
    '''
        Fit a linear model on training samples. Compute the paramter w using Maximum likelihood (equal to least square).
        Input:
            Phi: the design/feature matrix of the training samples, a numpy matrix of shape n by p
                Here n is the number of training samples, p is the number of features
            y : the sample labels, a numpy vector of shape n by 1.
        Output:
            w: the weights of the linear regression model, a numpy float vector of shape p by 1. 
        Hint: you could use np.linalg.inv() to compute the inverse of a matrix
              The problem can be solved using 1 line of code.
    '''
    #########################################

    #########################################
    return w 



#--------------------------
def ridge_regression(Phi, y, alpha=0.001):
    '''
        Fit a linear model on training samples. Compute the paramter w using Maximum posterior (equal to least square with L2 regularization).
        min_w sum_i (y_i - Phi_i * w)^2/2 + alpha * w^T * w 
        Input:
            Phi: the design/feature matrix of the training samples, a numpy matrix of shape n by p
                Here n is the number of training samples, p is the number of features
            y : the sample labels, a numpy vector of shape n by 1.
            alpha: the weight of the L2 regularization term, a float scalar.
        Output:
            w: the weights of the linear regression model, a numpy float vector of shape p by 1. 
        Hint: you could use np.linalg.inv() to compute the inverse of a matrix. 
              The problem can be solved using 2 lines of code
    '''
    #########################################

    #########################################
    return w 

Проверьте свое понимание с помощью следующих тестов утверждений:

from problem1 import *
import numpy as np
import sys
'''
    Unit test 1:
    This file includes unit tests for problem1.py.
    You could test the correctness of your code by typing `nosetests -v test1.py` in the terminal.
'''

#-------------------------------------------------------------------------
def test_python_version():
    ''' ----------- Problem 1 ---------------------'''
    assert sys.version_info[0]==3 # require python 3 (instead of python 2)


#-------------------------------------------------------------------------
def test_compute_Phi():
    '''compute_Phi'''
    x = np.mat('1.;2.;3')

    Phi = compute_Phi(x,2)
    assert type(Phi) == np.matrixlib.defmatrix.matrix 
    assert np.allclose(Phi.T, [[1,1,1],[1,2,3]], atol = 1e-3)

    Phi = compute_Phi(x,3)
    assert np.allclose(Phi.T, [[1,1,1],[1,2,3],[1,4,9]], atol = 1e-3) 

    Phi = compute_Phi(x,4)
    assert np.allclose(Phi.T, [[1,1,1],[1,2,3],[1,4,9],[1,8,27]], atol = 1e-3) 



#-------------------------------------------------------------------------
def test_least_square():
    '''least square'''
    Phi = np.mat([[1.,1.,1.],[-1.,0.,1.]]).T
    y = np.mat('1.5;2.5;3.5')
    w = least_square(Phi,y)
    assert type(w) == np.matrixlib.defmatrix.matrix 
    assert np.allclose(w, np.mat('2.5;1.'), atol = 1e-2) 

    for _ in range(20):
        p = np.random.randint(2,8)
        n = np.random.randint(200,400)
        w_true = np.asmatrix(np.random.random(p)).T
        x = np.asmatrix(np.random.random(n)*10).T
        Phi = compute_Phi(x,p)
        e = np.asmatrix(np.random.randn(n)).T*0.01
        y = Phi*w_true + e
        w = least_square(Phi,y)
        assert np.allclose(w,w_true, atol = 0.1)


#-------------------------------------------------------------------------
def test_l2_least_square():
    '''ridge regression'''
    Phi = np.mat([[1.,1.,1.],[-1.,0.,1.]]).T
    y = np.mat('1.5;2.5;3.5')
    w = ridge_regression(Phi,y)
    assert type(w) == np.matrixlib.defmatrix.matrix 
    assert np.allclose(w, np.mat('2.5;1.'), atol = 1e-2) 

    w = ridge_regression(Phi,y,alpha = 1000)
    assert np.allclose(w, np.mat('0.;0.'), atol = 1e-2) 

    for _ in range(20):
        p = np.random.randint(2,8)
        n = np.random.randint(200,400)
        w_true = np.asmatrix(np.random.random(p)).T
        x = np.asmatrix(np.random.random(n)*10).T
        Phi = compute_Phi(x,p)
        e = np.asmatrix(np.random.randn(n)).T*0.01
        y = Phi*w_true + e
        w = ridge_regression(Phi,y)
        assert np.allclose(w,w_true, atol = 0.1)

В этом учебном пособии я описал хронологию истории AI/ML (с определениями), объяснение времени нашего нынешнего возрождения и описание того, как идеи распространяются между областями данных.

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

Что делать, если мои данные не удовлетворяют предположениям о линейности, гомоскедастичности, независимости или нормальности?

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

Благодарности

Я хотел бы поблагодарить и выразить признательность за мои конспекты лекций и код от следующих профессоров Вустерского политехнического института (WPI), которые руководили мной при написании этого руководства:

  • Джейкоб Р. Уайтхилл, CS Dept.
  • Дональд Р. Браун, Департамент ECE
  • Сяннан Конг, отдел CS
  • Яньхуа Ли, отдел CS