Результаты линейного обучения SageMaker не точны? - PullRequest
0 голосов
/ 09 декабря 2018

У меня проблемы с результатами, полученными от линейного ученика AWS (SageMaker).

А именно, я пытался воспроизвести результаты, полученные от R, SAS или Knime (с использованием линейной регрессии), но, к сожалению, то, что я получаю от линейного ученика, отличается от упомянутых 3 других способов его вычисления.

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

Y = X1 + 2 * X2 + 3

В этом случае существуют точные коэффициенты регрессии, равные 1,2 и точке пересечения 3. В отличие от упомянутого другого программного обеспечения, линейный ученик SageMaker возвращает мне значения, даже не близкие к правильным значениям Например, в одном из примеров выполнения, который я получаю [0,91547656 1,9826275 3,023757] что просто не удовлетворительно.Здесь вы можете увидеть соответствующую часть моего кода!

study=((1.0,3.0,10.0),(2.0,3.0,11.0),(3.0,2.0,10.0),(4.0,7.0,21.0),(5.0,4.0,16.0))
a = np.array(study).astype('float32')
other_columns=a[:,[0,1]]
labels = a[:,2]
buf = io.BytesIO()
smac.write_numpy_to_dense_tensor(buf, other_columns, labels)
buf.seek(0)
key = 'my-training-data'
boto3.resource('s3').Bucket(bucket).Object(os.path.join(prefix, 'train', key)).upload_fileobj(buf)
s3_train_data = 's3://{}/{}/train/{}'.format(bucket, prefix, key)
output_location = 's3://{}/{}/output'.format(bucket, prefix)

container = get_image_uri(boto3.Session().region_name, 'linear-learner')

import boto3
sess = sagemaker.Session()
linear = sagemaker.estimator.Estimator(container,
                                       role, 
                                       train_instance_count=1, 
                                       train_instance_type='ml.c4.xlarge',                                       
                                       output_path=output_location,
                                       sagemaker_session=sess)
linear.set_hyperparameters(feature_dim=2,
                           predictor_type='regressor',
                           loss='squared_loss',
                           epochs=50,
                           early_stopping_patience=100,
                           mini_batch_size=4)
linear.fit({'train': s3_train_data})

У вас есть объяснение наблюдаемым неточным результатам?

Спасибо, Николай

1 Ответ

0 голосов
/ 13 декабря 2018

Двумя возможными причинами, по которым вы не получаете точных результатов, являются стохастический градиентный спуск (SGD) и регуляризация, обе из которых используются в Linear Learner.SGD и регуляризация - правильное решение для многих реальных проблем машинного обучения, но они приводят к неточным результатам в этом примере с игрушкой.

SGD - это метод оптимизации, который, помимо прочих преимуществ, хорошо масштабируется при большихнаборы данных.Он хорошо масштабируется, так как количество примеров и размерность увеличиваются.SGD плохо подходит для очень маленьких задач.С чрезвычайно большими наборами данных SGD является единственным эффективным решением.С большими, средними и небольшими наборами данных SGD в Linear Learner работает так же, как и другие решатели, благодаря встроенным в алгоритм оптимизациям, таким как параллельное исследование множества настроек скорости обучения и других гиперпараметров.Но для этого примера набора данных, который имеет нулевой шум (связь между объектами и меткой является детерминированным) и только 5 примеров, более точный и менее масштабируемый решатель будет работать лучше.

Регуляризация по умолчанию применяется в Linear Learner,Чтобы отключить его, установите 'wd'=0.0 и 'l1'=0.0.Алгоритм исследует несколько значений регуляризации, включая отсутствие регуляризации, и выбирает модель с наилучшей точностью на наборе валидации, или, если нет комплекта валидации, наивысшую точность данных обучения.Но из-за очень небольшого количества данных, доступных для изучения в этом случае, этот выбор по существу случайный.Так что вполне вероятно, что в финальной модели использовалась регуляризация.Регуляризация сдвигает веса модели, но не смещение, к нулю, так что это может объяснить оценки параметров, упомянутые в посте: [0.91547656 1.9826275 3.023757] вместо [1.0 2.0 3.0].Два веса были сдвинуты к нулю, а смещение немного велико для компенсации.

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

Для точного решенияДля решения задачи линейной регрессии в небольшом наборе данных используйте решатель, такой как QR-разложение.Примерами являются класс LinearRegression SKLearn или функция lm в R. Но имейте в виду, что эти методы будут иметь проблемы с масштабированием на большие наборы данных.И, возможно, что еще более важно, нам следует отключить регуляризацию для точного решения в образце, но точное решение обычно будет иметь худшую производительность для невидимых данных по сравнению с решением с регуляризацией.

В SKLearn реализовано несколько оптимизаторов, включаясинг.Вот пример применения решателя SGD в SKLearn к данным вашего примера.Регуляризация также включена по умолчанию в SKLearn.Решение является неточным по причинам, описанным выше.

>>> from sklearn import linear_model
>>> import numpy as np
>>> study=((1.0,3.0,10.0),(2.0,3.0,11.0),(3.0,2.0,10.0),(4.0,7.0,21.0),(5.0,4.0,16.0))
>>> a = np.array(study).astype('float32')
>>> other_columns=a[:,[0,1]]
>>> labels = a[:,2]
>>> reg = linear_model.SGDRegressor(max_iter=50)
>>> reg.fit(other_columns, labels)
SGDRegressor(alpha=0.0001, average=False, epsilon=0.1, eta0=0.01,
       fit_intercept=True, l1_ratio=0.15, learning_rate='invscaling',
       loss='squared_loss', max_iter=50, n_iter=None, penalty='l2',
       power_t=0.25, random_state=None, shuffle=True, tol=None, verbose=0,
       warm_start=False)
>>> reg.coef_
array([1.39560259, 2.17536485])
>>> reg.intercept_
array([0.77972575])
...