В SVC от Sklearn, почему время обучения не строго линейно к максимальной итерации, когда размер этикетки большой? - PullRequest
0 голосов
/ 30 сентября 2018

Я делаю анализ, пытаясь увидеть связь между временем обучения и максимальной итерацией в SVC.Данные, которые я использую, представляют собой случайно сгенерированное число, и я нанес график времени тренировки против max_iter подбора SVC.Я проверил журналы, и каждый двоичный классификатор достиг максимального значения (я вывел все журналы консоли, которые показывали подробные предупреждения для каждого двоичного классификатора, и подсчитал их).Однако я предполагал, что время обучения будет строго линейным по отношению к итерации, но на самом деле, в случае, когда данные обучения имеют много меток, например, скажем 40, график не показывает его линейность.enter image description here

Кажется, что максимальная итерация возрастает, каждая итерация занимает немного меньше времени, чем раньше.Если мы изменили label_size на 2 (что означает, что каждая подгонка содержит только 1 двоичный классификатор), линия будет прямой.

enter image description here

Что вызывает это вслучилось?

Вот мой исходный код:

# -*- coding: utf-8 -*-
import numpy as np
from sklearn.svm import SVC
import time
import pandas as pd


def main(row_size, label_size):
    np.random.seed(2019)
    y = np.array([i for i in range(label_size) for j in range(row_size
                 / label_size)])
    if len(y) < row_size:
        y = np.append(y, [y[-1]] * (row_size - len(y)))
    X = np.random.rand(row_size, 300)
    print X.shape, y.shape
    return (X, y)


def train_svm(X, y, max_iter):
    best_params = {'C': 1}
    clf = SVC(
        C=best_params['C'],
        kernel=str('linear'),
        probability=False,
        class_weight='balanced',
        max_iter=max_iter,
        random_state=2018,
        verbose=True,
        )
    start = time.time()
    clf.fit(X, y)
    end = time.time()
    return end - start


if __name__ == '__main__':
    row_size = 20000
    m_iter = range(10, 401, 20)
    label_size = [40]
    data = {
        'label_size': [],
        'max_iter': [],
        'row_size': [],
        'time': [],
        }
    for it in m_iter:
        for l in label_size:
            (X, y) = main(row_size, l)
            t = train_svm(X, y, max_iter=it)
            data['label_size'].append(l)
            data['max_iter'].append(it)
            data['row_size'].append(row_size)
            data['time'].append(t)
            df = pd.DataFrame(data)
            df.to_csv('svc_iter.csv', index=None)

1 Ответ

0 голосов
/ 02 октября 2018

Ну, может быть множество причин для этого " очень незначительное изменение ".Scikit-Learn не работает изначально, он построен на разных библиотеках и может использовать множество оптимизаторов ... и т.д.!

Кроме того, ваш первый график - очень близко к линейному!

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

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

Для получения более подробной информации о математическом подходе, пожалуйста, обратитесь к этой статье, раздел 6.2 Метод декомпозиции. .


Более того, в частности, SVM реализует два трюки , называемые сжатие и кэширование для метода декомпозиции.

  1. Идея сокращения состоит в том, что оптимальное решение α двойной задачи SVM может содержать некоторые ограниченные элементы (то есть α i = 0 или C).Эти элементы, возможно, уже были ограничены в середине итераций разложения.Чтобы сэкономить время обучения, метод сжатия пытается идентифицировать и удалить некоторые ограниченные элементы, поэтому решается меньшая задача оптимизации.
  2. Идея кэширования - эффективный метод сокращения вычислительного времени метода декомпозиции, поэтомуэлементы рассчитываются по мере необходимости.Мы можем использовать доступную память (, называемую кеш ядра ), чтобы хранить некоторые недавно использованные перестановки матрицы Q ij .Затем некоторые элементы ядра могут не нуждаться в пересчете .

Для получения дополнительной информации о математическом подходе, пожалуйста, обратитесь к этой статье, раздел 5 Сокращение и кэширование.


Техническое подтверждение:

Я повторил ваш эксперимент (, поэтому я попросил ваш код следовать тому же точному подходу ), с и без с использованием сжатия и кэширования оптимизация.

с использованием сжатия и кэширования

Значение по умолчанию для параметра shrinkingв sklearn SVC установлен на True, при этом он выдает следующий результат:

with shrinking table

График дает:

with shrinking plot

Обратите внимание, что в какой-то момент время заметно падает, отражаяЭффект сжатия и кэширования.

Без использования сжатия и Кэширование

Использование того же точного подходано на этот раз, установив для параметра shrinking явно значение False следующим образом:

 clf = SVC(
        C=best_params['C'],
        kernel=str('linear'),
        probability=False,
        class_weight='balanced',
        max_iter=max_iter,
        random_state=2018,
        verbose=True,
        shrinking=False
        )

Произвел следующий вывод:

without shrinking table

При построении графика это дает:

without shrinking plot

Обратите внимание, что в отличие от предыдущего графика, нет заметного падениявремя в какой-то момент, это довольно малые колебания вместе со всем графиком.


Сравнение корреляций Пирсона

Pearson correlation


В заключение:

Без использования сжатия и Кэширование ( обновлено позже с кэшированием ), линейность улучшилась, хотя она не на 100% линейна, но если принять во внимание, что Scikit-Learn использует внутреннеlibsvm библиотека для обработки всех вычислений.И эта библиотека обернута с использованием C и Cython , у вас будет более высокая терпимость к вашему определению о «линейном» отношения между maximum iterations и time.Кроме того, здесь - это крутая дискуссия о том, почему алгоритмы не могут каждый раз давать точно одно и то же точное определенное время выполнения.


И это было бы еще яснеевам, если вы нанесете интервал времени, чтобы вы могли ясно видеть, как внезапно происходят заметные падения в более чем одном месте.

interval plot with shrinking

Пока он сохраняетпочти тот же поток без использования трюков оптимизации.

interval plot without shrinking


Важное обновление

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

Но я упустил следующее:

Я говорил о сокращениии Кэширование, но я пропустил более поздний параметр для кэширования, который по умолчанию установлен на 200 МБ.

Повторение одного и того же моделирования более одного раза и установка параметра cache_size на очень маленькийчисло (, поскольку ноль недопустим и выдает ошибку ) в дополнение к shrinking=False, что привело к линейному шаблону чрезвычайно близко к между max_iter и time:

clf = SVC(
        C=best_params['C'],
        kernel=str('linear'),
        probability=False,
        class_weight='balanced',
        max_iter=max_iter,
        random_state=2018,
        verbose=False,
        shrinking=False,
        cache_size = 0.000000001
        )

final result


Кстати, вам не нужно устанавливать verbose=True, вы можете проверить, достигло ли ономаксимальная итерация через ConvergenceWarning, так что вы можете перенаправить эти предупреждения в файл, и вам будет в миллион раз легче следовать, просто добавьте этот код:

import warnings, sys
def customwarn(message, category, filename, lineno, file=None, line=None):
    with open('warnings.txt', 'a') as the_file:
        the_file.write(warnings.formatwarning(message, category, filename, lineno))
warnings.showwarning = customwarn

Также вам не нужно повторно-генерируйте набор данных после каждой итерации, поэтому возьмите его в цикл следующим образом:

(X, y) = main(row_size, 40)
    for it in m_iter:
        ....
        ....

Окончательное заключение

Трюки сжатия и кэширования, полученные из метода декомпозиции в SVM, играют большую рольЗначительная роль в улучшении времени выполнения по мере увеличения числа итераций.Кроме того, есть другие маленькие проигрыватели, которые могут внести свой вклад в это дело, например, внутреннее использование библиотеки libsvm для обработки всех вычислений, которые заключены в C и Cython.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...