В чем разница между частичной подгонкой и теплым началом?
Контекст:
Я использую Passive Aggressor из библиотеки Scikit и не понимаю, использовать ли теплый старт или частичную подгонку.
Усилия до сих пор:
- Передал эту ветку обсуждения:
https://github.com/scikit-learn/scikit-learn/issues/1585
- Прошел код Scikit для _fit и _partial_fit.
Мои наблюдения:
-
_fit
в свою очередь вызывает _partial_fit
.
-
Когда параметр warm_start
установлен, _fit
вызывает _partial_fit с помощью self.coef_
-
Когда _partial_fit
вызывается без параметра coef_init
и установлен self.coef_
, он продолжает использовать self.coef_
Вопрос:
Я чувствую, что оба в конечном итоге предоставляют одинаковые функциональные возможности. Тогда в чем их основное отличие? В каких контекстах используется любой из них?
Я что-то упускаю из виду? Любая помощь приветствуется!
Ответы
Ответ 1
Я не знаю, о пассивном агрессором, но, по крайней мере, при использовании SGDRegressor, partial_fit
подходит только для 1 эпохи, в то время как fit
приспособят для нескольких эпох (пока потеря не сходится или max_iter
достигается). Следовательно, при подгонке новых данных к вашей модели partial_fit
будет корректировать модель только на один шаг к новым данным, но с помощью fit
и warm_start
она будет действовать так, как если бы вы объединили свои старые данные и новые данные вместе и подгоняли модель один раз, пока конвергенция.
Пример:
from sklearn.linear_model import SGDRegressor
import numpy as np
np.random.seed(0)
X = np.linspace(-1, 1, num=50).reshape(-1, 1)
Y = (X * 1.5 + 2).reshape(50,)
modelFit = SGDRegressor(learning_rate="adaptive", eta0=0.01, random_state=0, verbose=1,
shuffle=True, max_iter=2000, tol=1e-3, warm_start=True)
modelPartialFit = SGDRegressor(learning_rate="adaptive", eta0=0.01, random_state=0, verbose=1,
shuffle=True, max_iter=2000, tol=1e-3, warm_start=False)
# first fit some data
modelFit.fit(X, Y)
modelPartialFit.fit(X, Y)
# for both: Convergence after 50 epochs, Norm: 1.46, NNZs: 1, Bias: 2.000027, T: 2500, Avg. loss: 0.000237
print(modelFit.coef_, modelPartialFit.coef_) # for both: [1.46303288]
# now fit new data (zeros)
newX = X
newY = 0 * Y
# fits only for 1 epoch, Norm: 1.23, NNZs: 1, Bias: 1.208630, T: 50, Avg. loss: 1.595492:
modelPartialFit.partial_fit(newX, newY)
# Convergence after 49 epochs, Norm: 0.04, NNZs: 1, Bias: 0.000077, T: 2450, Avg. loss: 0.000313:
modelFit.fit(newX, newY)
print(modelFit.coef_, modelPartialFit.coef_) # [0.04245779] vs. [1.22919864]
newX = np.reshape([2], (-1, 1))
print(modelFit.predict(newX), modelPartialFit.predict(newX)) # [0.08499296] vs. [3.66702685]
Ответ 2
Во-первых, давайте посмотрим на разницу между .fit()
и .partial_fit()
.
.fit()
позволит вам тренироваться с нуля. Следовательно, вы можете думать об этом как о опции, которую можно использовать только один раз для модели. Если вы снова .fit()
с новым набором данных, модель будет построена на новых данных и не будет влиять на предыдущий набор данных.
.partial_fit()
позволит вам обновить модель с помощью дополнительных данных. Следовательно, эта опция может использоваться более одного раза для модели. Это может быть полезно, когда весь набор данных не может быть загружен в память, см. Здесь.
Если оба .fit()
или .partial_fit()
будут использоваться один раз, то это не имеет значения.
warm_start
можно использовать только в .fit()
, это позволит вам начать обучение с коэффициента предыдущей fit()
. Теперь это может звучать аналогично назначению partial_fit()
, но рекомендуемый способ - partial_fit()
. Для улучшения обучения может быть несколько раз использована partial_fit()
с одними и теми же инкрементными данными.
Ответ 3
Если warm_start = False
, каждый последующий вызов .fit()
(после первоначального вызова .fit()
или partial_fit()
) сбрасывает обучаемые параметры модели для инициализации. Если warm_start = True
, каждый последующий вызов .fit()
(после первоначального вызова .fit()
или partial_fit()
) будет сохранять значения обучаемых параметров модели из предыдущего запуска и использовать их изначально. Независимо от значения warm_start
каждом вызове partial_fit()
будут сохраняться параметры модели предыдущего запуска, и они будут использоваться изначально.
Пример использования MLPRegressor
:
import sklearn.neural_network
import numpy as np
np.random.seed(0)
x = np.linspace(-1, 1, num=50).reshape(-1, 1)
y = (x * 1.5 + 2).reshape(50,)
cold_model = sklearn.neural_network.MLPRegressor(hidden_layer_sizes=(), warm_start=False, max_iter=1)
warm_model = sklearn.neural_network.MLPRegressor(hidden_layer_sizes=(), warm_start=True, max_iter=1)
cold_model.fit(x,y)
print cold_model.coefs_, cold_model.intercepts_
#[array([[0.17009494]])] [array([0.74643783])]
cold_model.fit(x,y)
print cold_model.coefs_, cold_model.intercepts_
#[array([[-0.60819342]])] [array([-1.21256186])]
#after second run of .fit(), values are completely different
#because they were re-initialised before doing the second run for the cold model
warm_model.fit(x,y)
print warm_model.coefs_, warm_model.intercepts_
#[array([[-1.39815616]])] [array([1.651504])]
warm_model.fit(x,y)
print warm_model.coefs_, warm_model.intercepts_
#[array([[-1.39715616]])] [array([1.652504])]
#this time with the warm model, params change relatively little, as params were
#not re-initialised during second call to .fit()
cold_model.partial_fit(x,y)
print cold_model.coefs_, cold_model.intercepts_
#[array([[-0.60719343]])] [array([-1.21156187])]
cold_model.partial_fit(x,y)
print cold_model.coefs_, cold_model.intercepts_
#[array([[-0.60619347]])] [array([-1.21056189])]
#with partial_fit(), params barely change even for cold model,
#as no re-initialisation occurs
warm_model.partial_fit(x,y)
print warm_model.coefs_, warm_model.intercepts_
#[array([[-1.39615617]])] [array([1.65350392])]
warm_model.partial_fit(x,y)
print warm_model.coefs_, warm_model.intercepts_
#[array([[-1.39515619]])] [array([1.65450372])]
#and of course the same goes for the warm model
Ответ 4
О различии. Теплый старт это просто атрибут класса. Частичный подход - это метод этого класса. Это в основном разные вещи.
О тех же функциях. Да, частичная подгонка будет использовать self.coef_, потому что по-прежнему необходимо получить некоторые значения для обновления в период обучения. И для пустого coef_init мы просто ставим нулевые значения в self.coef_ и переходим к следующему этапу обучения.
Описание.
Для первого запуска:
Каким бы ни был (с теплым началом или без него). Мы будем тренироваться по нулевым коэффициентам, но в результате мы сможем сэкономить средние наши коэффициенты.
N + 1 start:
С теплым стартом. Мы проверим через метод _allocate_parameter_mem наши предыдущие коэффициенты и возьмем его на тренировку. В результате сохраняем наши средние коэффициенты.
Без теплого старта. Мы ставим нулевые коэффициенты (как первый старт) и переходим к шагу обучения. В результате мы все равно будем записывать средние коэффициенты в память.