Стохастичний градієнтний спуск на основі векторних операцій?


10

припустимо, що я хочу навчити алгоритм регресії стохастичного градієнта спуску за допомогою набору даних, що містить N зразків. Оскільки розмір набору даних є фіксованим, я повторно використовую дані T разів. Під час кожної ітерації або "епохи" я використовую кожен зразок тренінгу рівно один раз після випадкового переупорядкування всього навчального набору.

Моя реалізація базується на Python та Numpy. Тому використання векторних операцій може значно скоротити час обчислень. Подання векторизованої реалізації пакетного градієнта спуску досить просто. Однак у випадку стохастичного градієнтного спуску я не можу зрозуміти, як уникнути зовнішньої петлі, яка проходить через усі зразки в кожну епоху.

Хтось знає будь-яку векторизовану реалізацію стохастичного градієнтного спуску?

EDIT : Мене запитали, чому я хотів би використовувати онлайн-градієнт, якщо розмір мого набору даних встановлений.

З [1] видно, що онлайн-градієнтний спуск конверсується повільніше, ніж пакетний градієнт, до мінімуму емпіричної вартості. Однак вона швидше переходить до мінімальної очікуваної вартості, що вимірює ефективність узагальнення. Я хотів би перевірити вплив цих теоретичних результатів на мою конкретну проблему шляхом перехресної перевірки. Без векторизованої реалізації мій онлайн-код градієнта значно повільніше, ніж пакетний градієнт спуску. Це надзвичайно збільшує час, необхідний для завершення процесу перехресної перевірки.

EDIT : Я включаю сюди псевдокод моєї он-лайн градієнтної спуск, як того вимагає ffriend. Я вирішую проблему регресії.

Method: on-line gradient descent (regression)
Input: X (nxp matrix; each line contains a training sample, represented as a length-p vector), Y (length-n vector; output of the training samples)
Output: A (length-p+1 vector of coefficients)

Initialize coefficients (assign value 0 to all coefficients)
Calculate outputs F
prev_error = inf
error = sum((F-Y)^2)/n
it = 0
while abs(error - prev_error)>ERROR_THRESHOLD and it<=MAX_ITERATIONS:
    Randomly shuffle training samples
    for each training sample i:
        Compute error for training sample i
        Update coefficients based on the error above
    prev_error = error
    Calculate outputs F
    error = sum((F-Y)^2)/n
    it = it + 1

[1] «Велике масштабне Інтернет-навчання», Л. Ботту, Ю. Ле Кун, NIPS 2003.


2
Розділити набір даних на міні-партії та підходити до кожної міні-серії послідовно.
дружина

Дякую @ffriend. Однак це не буде чистою онлайн-реалізацією.
Пабло Суу

1
Яка причина використовувати "чисту онлайн" реалізацію, якщо ваш набір даних фіксований? SGD говорить лише про те, що вам не потрібно одночасно повторювати весь набір даних, але можна розділити їх на довільну кількість фрагментів (міні-пакетів) та обробити їх по черзі. Міні-серія розміром 1 має сенс лише тоді, коли у вас є безперервне та, можливо, нескінченне джерело даних (наприклад, Twitter-канал, наприклад) та ви хочете оновлювати модель після кожного нового спостереження. Але це дуже рідкісний випадок і, безумовно, не для фіксованих наборів даних.
дружина

Вибачте за мою дуже пізню відповідь. Перевірте текст, який я додав до оригінального запитання.
Пабло Суу

1
Чи можете ви показати свою реалізацію? Я бачу непорозуміння, але без зразка коду це буде важко пояснити.
дружина

Відповіді:


10

Перш за все, слово "зразок" зазвичай використовується для опису підмножини сукупності , тому я буду називати те саме, що і "приклад".

Ваша реалізація SGD повільна через цю лінію:

for each training example i:

Тут ви явно використовуєте рівно один приклад для кожного оновлення параметрів моделі. За визначенням векторизація - це техніка перетворення операцій на одному елементі в операції на векторі таких елементів. Таким чином, ні, ви не можете обробляти приклади один за одним і все ж використовувати векторизацію.

Однак можна наблизити справжній SGD, використовуючи міні-партії . Міні-пакет - це невеликий підмножина оригінального набору даних (скажімо, 100 прикладів). Ви обчислюєте помилки та оновлення параметрів на основі міні-пакетів, але ви все одно повторюєте багато з них без глобальної оптимізації, роблячи процес стохастичним. Отже, щоб зробити вашу реалізацію набагато швидшою, достатньо змінити попередній рядок на:

batches = split dataset into mini-batches
for batch in batches: 

і обчислити помилку з партії, а не з одного прикладу.

Хоча явно очевидно, я також повинен зазначити векторизацію на рівні прикладу. Тобто замість чогось такого:

theta = np.array([...])  # parameter vector
x = np.array([...])      # example
y = 0                    # predicted response
for i in range(len(example)):
    y += x[i] * theta[i]
error = (true_y - y) ** 2  # true_y - true value of response

Ви обов'язково повинні зробити щось подібне:

error = (true_y - sum(np.dot(x, theta))) ** 2

що, знову ж таки, легко узагальнити для міні-партій:

true_y = np.array([...])     # vector of response values
X = np.array([[...], [...]]) # mini-batch
errors = true_y - sum(np.dot(X, theta), 1)
error = sum(e ** 2 for e in errors)

1
Я думаю, що це шлях. Міні-партії з правильно підібраним розміром можуть насправді сходитись швидше, ніж партійна або онлайн-версія (колишня лише оновлює ваги один раз на весь набір, а остання не може бути векторизованою, плюс додаткові кроки для оновлення ваги частіше)
Ніл Слейтер

Дякую вам обом. Вибачте за вперте відхилення міні-партій раніше, але я не був упевнений у впливі цього методу на швидкість конвергенції. Ніл, ваше твердження випливає з власного досвіду, чи є опубліковані теоретичні / емпіричні результати?
Пабло Суу

1
@PabloSuau Ви можете перевірити клас машинного навчання Ендрю Нґ на Coursera, 10 тиждень, він пояснює, чому конвергенція може бути швидшою, ніж як SGD, так і пакетна GD. Якщо бути точнішим: він завжди повинен бути таким же швидким, як SGD, але іноді він повинен бути ще швидшим на практиці.
габоровий

1

Ознайомтеся з методом part_fit класифікатора SGD scikit . Ви маєте контроль над тим, як ви зателефонували з ним: ви можете зробити це "справжнє" онлайн-навчання, передаючи екземпляр за раз, або ви можете збирати екземпляри в міні-партії, якщо всі ваші дані є в масиві. Якщо вони є, ви можете нарізати масив, щоб забезпечити мініатюри.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.