Векторизация обычно представляет собой устранение явного кода.Искусство зацикливания операторов.
1. Зачем векторизовать?
Посмотрите на следующий пример, если вы хотите рассчитать:
- В не векторизованном режиме:
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 = np.dot(A,v)
Невекторизованный:
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平方
В код вывода логистической регрессии можно ввести векторизованный расчет для оптимизацииТело цикла размерного объекта.
В-четвертых, алгоритм векторизованной логистической регрессии
Векторизация — очень захватывающая технология, которая позволяет полностью избежать явного цикла for в последующей нейронной сети, значительно повышая скорость работы.При расчете в нескольких выборках (как показано выше), если операция не векторизована, нам нужно повторить операциюраз этот процесс.
X.shape = (n_x,m).
Приведенная выше формула представлена векторным кодом:
z=np.dot(w.T,X)+b
В Python константа b автоматически преобразуется в вектор-строку размером 1xm, что в Python называется широковещанием.
ТакКак рассчитать?
Резюме: представленное вышеВекторизованный метод реализации одношаговой итерации прямого распространения, этот метод позволяет избежать медленного цикла for и обработать все сразу.обучающие выборки, чтобы получитьзначение, то есть функция активации вычисляется эффективно.
5. Градиентный результат векторизованной логистической регрессии
Векторизация прогнозируемого значения, рассчитанного путем прямого распространения, была проанализирована ранее, а теперь мы проанализируем векторизацию процесса вывода обратного распространения.
В предыдущем исследовании мы получили:Затем мы можем использовать этот результат напрямую.
короче,Решение этих двух параметров может быть достигнуто простыми векторными операциями.
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()
коррекция функции,изменить форму также быстро, не бойтесь использовать,Как показано ниже.