Заметки о глубоком обучении (4)

глубокое обучение

Векторизация обычно представляет собой устранение явного кода.forforИскусство зацикливания операторов.

1. Зачем векторизовать?

Посмотрите на следующий пример, если вы хотите рассчитать:z=wT+b.z=w^T+b.

  • В не векторизованном режиме:
z = 0
for i in range(n_x):
	z += w[i]*x[i]
z += b
  • В векторном режиме:
z = np.dot(w,x)+b

Чтобы интуитивно почувствовать разницу в скорости работы между векторизованными и не векторизованными операциями, мы используемjutypter notebookтест в.

import time

a = np.random.rand(1000000)
b = np.random.rand(1000000)

tic = time.time()
c = np.dot(a,b)
toc = time.time()

print(c)
print("Vectorized version:" + str(1000*(toc-tic)) + "ms")

c = 0
tic = time.time()
for i in range(1000000): 
    c += a[i]*b[i]
toc = time.time()

print(c)
print("For loop:" + str(1000*(toc-tic)) + "ms")
250169.8950443504
Vectorized version:1.9459724426269531ms
250169.89504435097
For loop:725.7585525512695ms

在这里插入图片描述

2. ГП и ЦП

Масштабируемое глубокое обучение находится на GPU (блоке обработки изображений), но мы используем примерjupyter notebookнаходится на ЦП. Они оба имеют параллельные инструкции, называемыеSIMD指令, то есть один поток инструкций с несколькими потоками инструкций. Если вы используете встроенные функции, такие какnp.dot(), так что numpy Python может в полной мере использовать преимущества параллелизма и быстрее выполнять вычисления. Это в равной степени верно и для CPU GPU, но GPU лучше выполняют SIMD-вычисления (конечно, CPU неплохие).

Три, пример векторизации

在这里插入图片描述 u=Avu=Av u = np.dot(A,v)

v=[v1...vn],u=[ev1...evn]v=\left[ \begin{matrix} v_1\\...\\v_n \end{matrix} \right],u=\left[ \begin{matrix} e^{v_1}\\...\\e^{v_n} \end{matrix} \right]Невекторизованный:

u = np.zeros((n,1))
for i in range(n):
	u[i] = math.exp(v[i])

Векторизовать:

import numpy as np
u = np.exp(v)

Когда дело доходит до функций математических вычислений библиотеки numpy, часто используются следующие функции:

np.log(v) #以e为底的对数
np.abs(v) # 绝对值
np.maxmum(v,0) # 最大值,与0相比
v**2 # 指数 v平方

В код вывода логистической регрессии можно ввести векторизованный расчет для оптимизацииnxn_xТело цикла размерного объекта.在这里插入图片描述

В-четвертых, алгоритм векторизованной логистической регрессии

Векторизация — очень захватывающая технология, которая позволяет полностью избежать явного цикла for в последующей нейронной сети, значительно повышая скорость работы.在这里插入图片描述При расчете в нескольких выборках (как показано выше), если операция не векторизована, нам нужно повторить операциюmmраз этот процесс.X=[............x(1)x(2)...x(m)............].X=\left[ \begin{matrix} ...&...&...&...\\x^{(1)}&x^{(2)}&...&x^{(m)}\\...&...&...&... \end{matrix} \right]. X.shape = (n_x,m). Z=[z(1)z(2)...z(m)]=wTX+[bb...b]=[wTx(1)+bwTx(2)+b...wTx(3)+b].Z=\left[ \begin{matrix} z^{(1)}&z^{(2)}&...&z^{(m)}\end{matrix} \right]=w^TX+\left[ \begin{matrix} b&b&...&b \end{matrix}\right]=\left[ \begin{matrix} w^Tx^{(1)}+b&w^Tx^{(2)}+b&...&w^Tx^{(3)}+b \end{matrix}\right].

Приведенная выше формула представлена ​​векторным кодом:

z=np.dot(w.T,X)+b

В Python константа b автоматически преобразуется в вектор-строку размером 1xm, что в Python называется широковещанием.

ТакaaКак рассчитать?A=[a(1)a(2)...a(m)]=о(z).A=\left[ \begin{matrix} a^{(1)}&a^{(2)}&...&a^{(m)}\end{matrix} \right]=\sigma(z).

Резюме: представленное вышеВекторизованный метод реализации одношаговой итерации прямого распространения, этот метод позволяет избежать медленного цикла for и обработать все сразу.mmобучающие выборки, чтобы получитьz,az,aзначение, то есть функция активации вычисляется эффективно.

5. Градиентный результат векторизованной логистической регрессии

Векторизация прогнозируемого значения, рассчитанного путем прямого распространения, была проанализирована ранее, а теперь мы проанализируем векторизацию процесса вывода обратного распространения. В предыдущем исследовании мы получили:dz=ay,dw=xdz,db=dz.dz=a-y,dw=xdz,db=dz.Затем мы можем использовать этот результат напрямую.在这里插入图片描述

在这里插入图片描述короче,db,dwdb ,dwРешение этих двух параметров может быть достигнуто простыми векторными операциями.

db = 1/m*np.sum(dz)
dw = 1/m*X*dz

Теперь давайте еще раз посмотрим, как прямое распространение (поиск прогнозируемого значения) и обратное распространение (поиск деривации и обновления параметров) процесса всей логистической регрессии удаляет два цикла for.在这里插入图片描述Высоко векторизованный код логистической регрессии выглядит следующим образом:

for iter in range(step_num):
	z = np.dot(w.T,X)+b
	A = f(z)
	dz = A-Y
	dw = (1/m)*np.dot(X,dz.T)
	db = (1/m)*np.sum(dz)
	w := w-lr*dw
	b := b-lr*db

Шесть, пустое векторное описание

Упомяните некоторые инструкции, связанные с numpy, чтобы уменьшить количество возможных ошибок. Сначала введите numpy, сгенерируйте 5 случайных гауссовских переменных и сохраните их в массиве a.

import numpy as np

a = np.random.randn(5)
print(a)
[-0.56189854 -1.15398922 -1.22490327  0.00217112  0.44074155]

Проанализируйте структуру этого

print(a.shape)
(5,)

Итак, это аМассив ранга 1! Ни вектор-строка, ни вектор-столбец!для тестированияне вектор строки/столбца, используя транспонирование и внутренний продукт для экспериментального анализа.

print(a.T)
print(np.dot(a.T, a))
print(np.dot(a, a.T))
[-0.56189854 -1.15398922 -1.22490327  0.00217112  0.44074155]
3.3420669323770062
3.3420669323770062

Данные показывают, что: указанное выше a является всего лишьМассив ранга 1, а не вектор! Не используйте этот массив во время программирования!

Итак, как мы должны генерировать случайные числа, чтобы облегчить обработку? Ответ заключается в том, чтобы напрямую генерировать векторы строк/столбцов.

a = np.random.randn(5, 1)
print(a)
[[ 0.60495052]
 [-2.12322553]
 [-0.86336334]
 [-0.17266097]
 [ 0.31836149]]

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

print(a.shape)
print(a.T)
print("\n")
print(np.dot(a,a.T))
(5, 1)
[[ 0.60495052 -2.12322553 -0.86336334 -0.17266097  0.31836149]]


[[ 0.36596513 -1.28444638 -0.5222921  -0.10445134  0.19259295]
 [-1.28444638  4.50808664  1.83311509  0.36659819 -0.67595324]
 [-0.5222921   1.83311509  0.74539626  0.14906916 -0.27486164]
 [-0.10445134  0.36659819  0.14906916  0.02981181 -0.0549686 ]
 [ 0.19259295 -0.67595324 -0.27486164 -0.0549686   0.10135404]]

Проверка прошла успешно! часто используетсяassert()Такое объявление используется для утверждения размерности вектора/матрицы, и если оно правильное, об ошибке не сообщается.Assert выполняется очень быстро, его можно рассматривать как документацию кода, не беспокойтесь об использовании assert

assert(a.shape == (5, 1))

Наконец, если мы получиммассив ранга 1, также черезreshape()коррекция функции,изменить форму также быстро, не бойтесь использовать,Как показано ниже.在这里插入图片描述