Понимание глубокого обучения с нуля

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

Итак, давайте создадим наш милый маленький персептрон.

Сначала нам нужно подготовить наши данные в требуемом формате, он может использовать только данные в векторном формате или одномерные данные, но форма нашего изображения (32, 32, 3), где первые два — это высота и ширина изображения, а 3 — канал RGB.

  • Здесь в блоке кода выше сначала мы импортируем необходимые модули
  • Затем мы загружаем наши данные с нашего локального диска и разбиваем данные с соотношением 4:1.
  • Затем мы преобразуем наши данные изображения из многомерного матричного формата в векторный формат.
  • Наконец, мы стандартизируем наш набор данных, чтобы значения пикселей оставались в диапазоне от 0 до 1.

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

Сначала у нас есть данные (X) в векторном формате, которые будут выполнять скалярное произведение с нашим вектором весов (W), добавленным со смещением (b), в приведенном ниже уравнении (i) обозначает i-й элемент X или Z,и Z — вектор результатов W, X и b.

Итак, значит ли это, что Z является результатом нашего персептрона. Ну не так быстро!

Значения: вектор Z не имеет верхнего или нижнего предела, и нам нужно значение от 0 до 1, поэтому для этого мы будем использовать сигмовидную функцию, которая будет принимать значения Z и расположите их между 0 и 1, что обозначается вектором A.

Итак, теперь вы можете спросить, как мы определяем значения W и b? Ну, мы инициализируем все значения элементов вектора W как 0,0 и b как скалярное значение 0,0.

Весь процесс до сих пор называется прямым распространением. Вот код для всех шагов.

  • Сначала мы определяем функцию initialize_with_zeros, которая принимает измерение в качестве параметра и возвращает вектор W и b, помните термин смещения (b ) является скалярным значением.
  • Затем мы определяем функцию сигмоид.
  • Наконец, функция forward_propagation даст нам вектор A со значениями от 0 до 1.

Теперь, когда мы закончили шаг прямого распространения, мы должны вернуться и обновить значения W и b, чтобы он мог правильно различать два класса. Для этого существует нечто, называемое Функция стоимости (J), которая определяет стоимость прогнозирования, т. е. насколько далеки прогнозируемые значения от фактических значений. Таким образом, чтобы рассчитать это, мы должны найти стоимость каждого отдельного прогноза, здесь суффикс y (i) — это фактическое значение, а суффикс (i) — это прогнозируемое значение. i данных. Пожалуйста, обратитесь к этой ссылке, чтобы подробно понять функцию стоимости и то, как появилось это выражение.

Суммируйте его по всем значениям в наборе данных.

Возьмите среднее значение, где m — количество имеющихся обучающих данных. Это функция стоимости, и мы должны максимально минимизировать эту функцию стоимости.

Чтобы минимизировать функцию стоимости или J, мы должны найти производную J относительно W и b, которая означает количество изменений, которое требуется для W и b, чтобы различать два класса.

Таким образом, производная от W(dw) и b(db) относительно J приведена ниже, dw и db называются градиентами J. Если вы хотите понять, как это попало в картину, то обратитесь к этому видео. Все шаги после прямого распространения до настоящего момента называются обратным распространением.

Теперь давайте посмотрим код до сих пор. Мы удалили функцию forward_propagation и объединили ее с кодом обратного распространения, назовем ее функцией propagate.

  • Мы объясняли до строки 12 ранее, теперь сначала мы вычисляем стоимость в соответствии с ранее упомянутым выражением.
  • Затем мы вычисляем градиенты стоимости, которыеравныdw иdb.
  • Наконец, верните градиенты и стоимость.

Теперь на следующих шагах мы должны итеративно уменьшать функцию стоимости, а для этого нам нужно очень медленно вычитать производную от W(dw) и b(db). в каждой итерации, но значения dw и db довольно велики, и прямое вычитание их значений не будет работать из-за перерегулирования, в качестве решения мы умножаем dw и db с очень небольшим числом, которое называется Скорость обучения. Здесь l — скорость обучения, а «:=» — оператор присваивания.

Это постепенное изменение значений W и b называется градиентным спуском. На рисунке ниже футбольный мяч обозначает значения W и b.

Теперь давайте разберемся с кодом градиентного спуска.

  • В функцию мы передаем наши w (веса), b (смещение), X (тренировочный набор), Y (фактические значения для тренировочного набора), num_iteration (количество итераций) и Learning_rate (то же самое). Набор для обучения и тестирования, который мы создали в нашем самом первом блоке кода.
  • Из созданной выше функции распространения она получает dw, db и cost.
  • Затем мы обновляем w и b в соответствии с нашим предыдущим объяснением. На следующей итерации значение w и b будет новым значением.
  • Затем мы печатаем стоимость каждые 100 итераций и возвращаем w и b. Пожалуйста, поймите, что хотя w написано маленькими буквами, это вектор, а b скаляр.

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

Давайте соберем все функции до сих пор, чтобы создать функцию model.

Этот код говорит сам за себя: инициализируя значения w и b нулями, затем после градиентного спуска мы печатаем точность в поезде и тестовом наборе.

Посмотрим, как поведет себя наша милая маленькая модель. Запустите код, указанный ниже.

logistic_regression_model = model(train_set_x, y_train, test_set_x, y_test, num_iterations=2000, learning_rate=0.001)`

Это результат, который вы могли бы получить после его запуска.

Cost after iteration 0: 0.693147 
Cost after iteration 100: 0.679755 
Cost after iteration 200: 0.673041 
Cost after iteration 300: 0.668556 
Cost after iteration 400: 0.665001 
Cost after iteration 500: 0.661952 
Cost after iteration 600: 0.659240 
Cost after iteration 700: 0.656784 
Cost after iteration 800: 0.654535 
Cost after iteration 900: 0.652458 
Cost after iteration 1000: 0.650527 
Cost after iteration 1100: 0.648720 
Cost after iteration 1200: 0.647020 
Cost after iteration 1300: 0.645414 
Cost after iteration 1400: 0.643889 
Cost after iteration 1500: 0.642436 
Cost after iteration 1600: 0.641046 
Cost after iteration 1700: 0.639713 
Cost after iteration 1800: 0.638430 
Cost after iteration 1900: 0.637192 
train accuracy: 63.25 % 
test accuracy: 58.5 %

Итак, наша точность на тестовом наборе составляет 58,5%, что лучше, чем случайные предположения (50%), но явно не на должном уровне. Итак, теперь давайте подумаем, что мы можем изменить, чтобы сделать его лучше, мы могли бы использовать другую функцию активации, и другая скорость обучения могла бы обучить ее, возможно, большему или меньшему числу итераций. Пожалуйста, попробуйте разные идеи, которые у вас есть, и посмотрите, сможете ли вы изменить результат. Мы создали модель нейронной сети с нуля во второй статье этой серии.

Кредит: https://www.coursera.org/specializations/deep-learning