векторизация формулы глубокого обучения

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

Это 18-й день моего участия в августовском испытании обновлений. Узнайте подробности события:Испытание августовского обновления


Σ( ° △ °|||)︴Эта статья о том, как векторизовать формулу для упрощения расчета.В ней может быть вкрапление всякой ерунды, которая помечена справочными символами, так что можете не обращать внимания.

Как отбросить субъективное и логическое мышление людей? Как анализировать проблемы с более удобной для компьютера точки зрения?

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

Например, простое десятичное число в двоичное. В моих глазах это можно логически посчитать двумя способами:

Метод 1: посмотрите, является ли это число суммой нескольких степеней двойки.

819=1×29+1×28+0×27+0×26+1×25+1×24+0×23+0×22+1×21+1×20819 = 1 \times 2^9 + 1 \times 2^8 + 0 \times 2^7 + 0 \times 2^6 + 1 \times 2^5 + 1 \times 2^4 + 0 \times 2^3 + 0 \times 2^2 + 1 \times 2^1 + 1 \times 2^0

Метод 2: Разделить с остатком

819÷2=409...1819 \div 2 = 409 ... 1

409÷2=204...1409 \div 2 = 204 ... 1

204÷2=102...0204 \div 2 = 102 ... 0

102÷2=51.....0102 \div 2 = 51 ..... 0

51÷2=25.......151 \div 2 = 25 ....... 1

25÷2=12.......125 \div 2 = 12 ....... 1

12÷2=6.........012 \div 2 = 6 ......... 0

6÷2=3...........06 \div 2 = 3 ........... 0

3÷2=1...........13 \div 2 = 1 ........... 1

1÷2=0...........11 \div 2 = 0 ........... 1

В то время, в моих глазах, я чувствовал, что первый метод был проще, и этого было достаточно, чтобы увидеть, сколько раз использовался второй метод. Пока не столкнулся с преобразованием системы, когда замахнулся на вопрос и вдруг запутался... А? Как это сделать. Как написать логику деления нескольких квадратов 2. Можно ли сделать два массива, один для хранения энной степени числа 2, а другой для хранения результата делителя?

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

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

Итак, для глубокого обучения, как «сложная формула» упрощает вычисления?

Возьмите простой каштан:

hθ(x)=j=0nθjxjh_{\theta}(x)=\sum_{j=0}^{n} \theta_{j} x_{j}

Если вы позволите вычислить это вручную, вы обязательно подумаете, а не простая ли это одноразовая функция, просто заносите ее по одной и вычисляете. А вот если метод «внести» реализовать компьютером, то получится вот так:

Объявить два вектора, пройти.

Невекторизованная реализация

С++:

double prediction = 0.0; 
for(int j = 0; j<=n; j++)
{
    prediction += theta[j]*x[j];
}

октава:

prediction =0.0; 
for j = 1:n+l
    prediction = prediction + theta(j) * x(j)
end

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

hθ(x)=j=0nθjxjh_{\theta}(x)=\sum_{j=0}^{n} \theta_{j} x_{j}Векторизацию можно рассматривать какθTx\theta^{T} xи рассчитать.

Это преобразуется в два вектораθ=[θ0θ1θ2...]x=[x0x1x2...]\theta=\left[\begin{array}{l}\theta_{0} \\ \theta_{1} \\ \theta_{2} \\ ... \end{array}\right] \quad x=\left[\begin{array}{l}x_{0} \\ x_{1} \\ x_{2} \\ ...\end{array}\right]продукт из .

Векторизованная реализация (после векторизации)

октава:

prediction= theta' * x; 

С++:

double prediction = theta.transpose()*x;

Почему быстрее векторизовать, чем вычислять его самостоятельно с помощью массива? Потому что после векторизации удобнее пользоваться некоторыми встроенными библиотеками языка. Например, октавой вышеtheta'Английские одинарные кавычки ' означают найти транспонирование матрицы или вектора (Забыл вернуться и посмотреть синтаксис октавы). на С++theta.transpose()Он также использует функцию транспонирования библиотеки линейной алгебры.

Изучая биологию, я использовал C++ в качестве языка ввода.Когда я впервые начал изучать структуры данных и алгоритмы, такие как сортировка, я знал все виды сортировки и ее эффективность. Но если вы спросите меня, какой алгоритм сортировки эффективнее использовать для набора данных с какими характеристиками, я рассмотрю, какой из них лучше, иначе я обычно буду пузыриться прямо при чистке вопроса. Однажды старший сказал мне: «Вы сказали, какие библиотечные функции C++ используются. Я понятия не имею. Потом он сказал: "Вы можете посмотреть исходный код библиотечных функций, когда вам нечего делать. Например, сортировка C++ - это не отдельная сортировка, а комбинация сортировок, которые представляют собой все алгоритмы, оптимизированные различными воротилами".

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

Преимущества использования встроенных алгоритмов:

  • Быстрее
  • Реализовать с меньшим количеством кода
  • Менее подвержен ошибкам, чем написание собственного
  • Лучшее соответствие аппаратной системе

Сказав так много, вот еще один каштан:

θj:=θjα1mi=1m(hθ(x(i))y(i))xj(i) for all j\begin{array}{l} \theta_{j}:=\theta_{j}-\alpha \frac{1}{m} \sum_{i=1}^{m}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right) x_{j}^{(i)} \end{array} \text{ for all j}

Эта формула знакома и является формулой градиентного спуска. В этой формуле x — матрица данных, а y — вектор-столбец.

Для множественной линейной регрессии:

θ0:=θ0α1mi=1m(hθ(x(i))y(i))x0(i)θ1:=θ1α1mi=1m(hθ(x(i))y(i))x1(i)θ2:=θ2α1mi=1m(hθ(x(i))y(i))x2(i)...\begin{array}{l} \theta_{0}:=\theta_{0}-\alpha \frac{1}{m} \sum_{i=1}^{m}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right) x_{0}^{(i)} \\ \theta_{1}:=\theta_{1}-\alpha \frac{1}{m} \sum_{i=1}^{m}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right) x_{1}^{(i)} \\ \theta_{2}:=\theta_{2}-\alpha \frac{1}{m} \sum_{i=1}^{m}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right) x_{2}^{(i)} \end{array} \\...

Сначала упростите формулу градиентного спуска, чтобы упростить кодирование:

θ:=θαδ\theta:=\theta-\alpha \delta
δ=1mi=1m(hθ(x(i))y(i))x(i)\delta = \frac{1}{m} \sum_{i=1}^{m}\left(h_{\theta}\left(x^{(i)}\right)-y^{(i)}\right) x^{(i)}

где δ — вектор-столбец:δ=[δ0δ1δ2...]\delta=\left[\begin{array}{l} \delta_{0} \\ \delta_{1} \\ \delta_{2} \\... \end{array}\right]

А для х,x(i)=[x0(i)x1(i)x2(i)...]x^{(i)}=\left[\begin{array}{c} x_{0}^{(i)} \\ x_{1}^{(i)} \\ x_{2}^{(i)} \\... \end{array}\right]

δ=номер×(...)×x(i)\ дельта = число × (...) × х ^ {(я)}

Следовательно, это должно бытьδn×1=номер×(...)×x1×n(i)\delta_{n \times 1} = число×(...)×x_{1×n}^{(i)}которыйxj(i)x_j^{(i)}Транспонировать.

Если эта логика не векторизована, для завершения может потребоваться написать много циклов. Я просто написал это на C++, я не могу гарантировать, что это правильно, вы можете просто взглянуть на это, я не запускал этот код.

for(int j=0;j<n;j++)
{
    //先计算出h(x)来
    for(int i=0;i<len;i++)
    {
        hx[i] += theta[i][j]*x[i][j];
    }
    //计算[h(x)-j]*x并求和
    for(int i=0;i<len;i++)
    {
        sum += (h[i] - y[i])*x[i][j]; 
    }
    //公式剩余部分
    theta[j] = theta[j] - alpha * (1/m) * sum;
}

Но если вы векторизуете, это можно записать как:

% 假设现在是二元的
hx = X * theta;
theta(1) = theta(1) - alpha * (1/m) * sum((hx-y)*X(:,1:1))
theta(2) = theta(2) - alpha * (1/m) * sum((hx-y)*X(:,2:2))
%注意octave和C等其他语言不同,下标从1开始
% 如果是n元的
hx = X * theta;
for i = 1:n
    theta(i) = theta(i) - alpha * (1/m) * sum((hx-y)*X(:,i:i))
    %注意octave和C等其他语言不同,下标从1开始
endfor

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