How does the validation_split parameter of Keras’ fit function work?
Validation-split in Keras Sequential model fit function is documented as following on https://keras.io/models/sequential/ :
validation_split: Float between 0 and 1. Fraction of the training data to be used as validation data. The model will set apart this fraction of the training data, will not train on it, and will evaluate the loss and any model metrics on this data at the end of each epoch. The validation data is selected from the last samples in the x and y data provided, before shuffling.
Please note the last line:
The validation data is selected from the last samples in the x and y data provided, before shuffling.
Does it means that validation data is always fixed and taken from bottom of main dataset? Is there any way it can be made to randomly select given fraction of data from main dataset?
asked Sep 30, 2018 at 6:30
1,568 3 3 gold badges 17 17 silver badges 34 34 bronze badges
2 Answers 2
$\begingroup$
You actually would not want to resample your validation set after each epoch. If you did this your model would be trained on every single sample in your dataset and thus this will cause overfitting. You want to always split your data before the training process and then the algorithm should only be trained using the subset of the data for training.
The function as it is designed ensures that the data is separated in such a way that it always trains on the same portion of the data for each epoch. All shuffling is done within the training sample between epochs if that option is chosen.
However, for some datasets getting the last few instances is not useful, specifically if the dataset is regroup based on class. Then the distribution of your classes will be skewed. Thus you will need some kind of random way to extract a subset of the data to get balanced class distributions in the training and validation set. For this I always like to use the sklearn function as follows
from sklearn.model_selection import train_test_split # Split the data x_train, x_valid, y_train, y_valid = train_test_split(data, labels, test_size=0.33, shuffle= True)
It’s a nice easy to use function that does what you want. The variables data and labels are standard numpy matrices with the first dimension being the instances.
Тонкая настройка и контроль процесса обучения через метод fit()
Используя пакет Keras на этих занятиях, мы с вами много раз обучали модель путем вызова метода fit(). Пришло время подробнее с ним познакомиться, увидеть его возможности и особенности.
Вначале определим тестовую модель для простой классической задачи распознавания изображений рукописных цифр:
import os os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' import tensorflow as tf from tensorflow import keras from tensorflow.keras import layers from tensorflow.keras.datasets import mnist tf.random.set_seed(1) (x_train, y_train), (x_test, y_test) = mnist.load_data() x_train = x_train.reshape(-1, 784) / 255.0 x_test = x_test.reshape(-1, 784) / 255.0 y_train = keras.utils.to_categorical(y_train, 10) y_test = keras.utils.to_categorical(y_test, 10) model = keras.Sequential([ layers.Input(shape=(784,)), layers.Dense(128, activation='relu'), layers.Dense(64, activation='relu'), layers.Dense(10, activation='softmax'), ])
Теперь, для запуска процесса обучения, необходимо определить оптимизатор и функцию потерь:
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
И, собственно, вызвать метод fit(), например, так:
model.fit(x_train, y_train, batch_size=64, epochs=5)
Это мы делали с вами уже много раз и здесь вам, в целом, должно быть все знакомо.
У метода fit() много вспомогательных параметров, которые полезно знать для обеспечения контроля за процессом обучения нейросети. Рассмотрим наиболее значимые из них. Вначале увидим, как можно определять выборку валидации, по которой мы контролируем процесс переобучения.
Выборка валидации с массивами NumPy
Если обучающий набор данных представлен в виде NumPy-массивов, то мы можем указать долю, которая будет использована в качестве проверочной выборки. Это делается с помощью параметра:
validation_split = вещественное число (от 0 до 1)
Например, если указать:
model.fit(x_train, y_train, batch_size=64, epochs=5, validation_split=0.3)
то будут взяты последние 30% наблюденийиз массивов x_train и y_train (до их перемешивания), которые мы указываем в этом же методе для обучения. По умолчанию, метод fit() перетасовывает наблюдения выборок на каждой эпохе. Так вот, 30% наблюдений отбираются до перемешивания, а остальные 70% участвуют в обучении.
Если нас не устраивает такой встроенный механизм разбиения обучающих данных, то мы можем это сделать самостоятельно. Для простоты, возьмем первые 20% наблюдений для валидации, а остальные 80% превратим в набор обучающих данных. Вначале вычислим индекс для разбиения выборки:
validation_split = 0.2 validation_split_index = np.ceil(x_train.shape[0] * validation_split).astype('int32')
А, затем, разделим наборы данных по этому индексу:
# выборка валидации x_train_val = x_train[:validation_split_index] y_train_val = y_train[:validation_split_index] # обучающая выборка x_train_data = x_train[validation_split_index:] y_train_data = y_train[validation_split_index:]
После этого, в методе fit() достаточно указать выборку для обучения и для проверки:
model.fit(x_train_data, y_train_data, batch_size=64, epochs=5, validation_data=(x_train_val, y_train_val))
Как видите, здесь используется параметр validation_data для указания проверочной выборки.
Выборка валидации с tf.data.Dataset
Наборы данных для обучения модели могут быть представлены и в виде тензоров непосредственно пакета Tensorflow. Часто для этого используется специальный набор утилит в ветке:
Подробная документация по ним доступна по адресу:
В частности, можно сформировать выборку на основе уже имеющихся данных, используя метод from_tensor_slices() класса Dataset:
train_dataset = tf.data.Dataset.from_tensor_slices((x_train_data, y_train_data))
На выходе получим экземпляр этого класса с выборкой (x_train, y_train). Далее, мы можем перемешать наблюдения в выборке с помощью метода shuffle и разбить их по мини-батчам, например, размером 64 элемента:
train_dataset = train_dataset.shuffle(buffer_size=1024).batch(64)
Параметр buffer_size определяет число элементов в буфере, из которого случайно выбирается по одному элементу на каждой итерации при перемешивании.
Теперь, достаточно первым параметром передать объект Dataset в метод fit() и дополнительно указать число эпох:
model.fit(train_dataset, epochs=5)
При этом аргумент batch_size уже не имеет смысла, так как мы сделали эту разбивку ранее. Также на каждой эпохе данные будут браться с самого начала (сбрасываются), поэтому сеть будет учиться на одних и тех же наблюдениях от эпохи к эпохе (параметр shuffleздесь не применяется).
Выборка валидации с таким набором данных может быть добавлена только через параметр validation_data. Другой параметр validation_split здесь игнорируется:
val_dataset = tf.data.Dataset.from_tensor_slices((x_train_val, y_train_val)) val_dataset = val_dataset.batch(64) model.fit(train_dataset, epochs=5, validation_data=val_dataset)
Параметры steps_per_epoch и validation_steps
Если мы хотим, чтобы обучающие данные от эпохи к эпохе не сбрасывались, а последовательно проходили по мини-батчам от начала до конца, то для этого можно воспользоваться параметром
который устанавливает число батчей на эпоху, например, так:
model.fit(train_dataset, epochs=5, steps_per_epoch = 100, validation_data=val_dataset)
Но, при слишком большом значении steps_per_epoch, например, 300 пакетов будет недостаточно для пяти эпох и Keras сгенерирует предупреждение с остановом процесса обучения.
Как правило, обучение запускают без этого параметра, но если вдруг потребуется более тонкая настройка для исследования процесса обучения, то полезно знать возможности метода fit().
Второй похожий параметр validation_steps задает число мини-батчей, используемых в проверочной выборке. Например, указав число пять:
model.fit(train_dataset, epochs=5, validation_data=val_dataset, validation_steps=5)
в конце каждой эпохи будет использовано пять мини-батчей из выборки валидации для оценки качества работы модели на текущем этапе обучения.
Параметры class_weight и sample_weight
Как известно, входная выборка данных должна быть сбалансированной, то есть, каждый класс должен представляться примерно одинаковым числом наблюдений. Иногда это условие не выполняется, а, следовательно, обучение может пойти не самым лучшим образом. Для исправления такой ситуации в Keras можно дополнительно указывать веса для выходных значений, которые будут учитываться при вычислении функций потерь. Например, представим, что у нас есть нейросеть с N входами и M выходами:

Если обучающая выборка сбалансирована, то веса у всех выходов следует взять равными, обычно, единичными. Опишем это с помощью следующего словаря:
class_weight = { 0: 1.0, 1: 1.0, 2: 1.0, 3: 1.0, 4: 1.0, 5: 1.0, 6: 1.0, 7: 1.0, 8: 1.0, 9: 1.0, }
Здесь полагается, что M=10 (выходы с 0 до 9 – десять значений). В этом случае прогнозное значение тензора сети для функций потерь будет вычисляться как:

Обратите внимание, здесь речь идет о пересчете значений выходного тензора только для функций потерь, а не сети.
В программе мы можем указать эти веса, передавая словарь одноименному параметру class_weight метода fit():
model.fit(train_dataset, epochs=5, class_weight=class_weight)
Наверное, вы уже догадались, что если веса взять неравномерными (допустим, для первого выхода зададим вес в 1000, а остальные оставим прежними), то сеть будет обучаться, в основном, на распознавание цифры 0. И для нашей сбалансированной выборки общее качество классификации снизится до 87,7%. Поэтому такой подход полезен именно для несбалансированных выборок, где классам следует присваивать разные веса (чем меньше наблюдений, тем выше вес).
Другой параметр sample_weight позволяет устанавливать вес для отдельных наблюдений выборки. Например, написание некоторых единичек может быть похоже на написание семерок:

И нам бы хотелось, чтобы нейросеть «внимательнее», с большим весом относилась к таким изображениям. Для этого достаточно им присвоить больший вес, используя параметр sample_weight.
В нашем примере мы сделаем более простую манипуляцию – всем изображениям единичек присвоим вес 5.0, а остальным изображениям – вес 1.0. Через NumPy сделать это достаточно просто:
sample_weight = np.ones(shape=(len(x_train),)) sample_weight[y_train == 1] = 5.0
А, затем, в методе fit() указать этот параметр со сформированной коллекцией весов:
model.fit(x_train, y_train, sample_weight=sample_weight, epochs=5)
Обратите внимание, что веса наблюдений можно устанавливать только для массивов NumPy.
Статистика обучения
Метод fit() возвращает объект, в котором хранятся значения функций потерь для тренировочной и проверочной выборок, а также вычисляемые показатели метрик:
history = model.fit(x_train, y_train, epochs=3, validation_split=0.2) print(history.history)
После выполнения программы в консоли увидим:
‘accuracy’: [0.9209374785423279, 0.9661250114440918, 0.9769583344459534],
‘val_loss’: [0.14193743467330933, 0.11101816594600677, 0.10447544604539871],
‘val_accuracy’: [0.9585000276565552, 0.9664999842643738, 0.9704166650772095]>
То есть, свойство history объекта history содержит списки соответствующих показателей качества процесса обучения. Затем, их удобно отображать в виде графиков, как это мы не раз делали в курсе по нейронным сетям.
Использование генератора выборки keras.utils.Sequence
С помощью класса keras.utils.Sequence можно реализовать свой собственный генератор последовательности для обучающей выборки. Давайте посмотрим на конкретном примере как это можно сделать.
Предположим, мы хотим создавать ограниченные наборы выборок изображений цифр. Для этого определим производный класс DigitsLimit, следующим образом:
class DigitsLimit(keras.utils.Sequence): def __init__(self, x, y, batch_size, max_len = -1): self.batch_size = batch_size self.x = x[:max_len] self.y = y[:max_len] def __len__(self): return int(np.ceil(self.x.shape[0] / self.batch_size)) def __getitem__(self, idx): batch_x = self.x[idx * self.batch_size:(idx + 1) * self.batch_size] batch_y = self.y[idx * self.batch_size:(idx + 1) * self.batch_size] return batch_x, batch_y
- __len__() – возвращает число мини-батчей обучающей выборки;
- __getitem__() – возвращает мини-батч по индексу idx.
sequence = DigitsLimit(x_train, y_train, 64, 10000) history = model.fit(sequence, epochs=3)
- многопроцессорность;
- параметр shuffle=True в методе fit().
history = model.fit(sequence, epochs=3, shuffle=True)
Наконец, если требуется менять выборку после каждой эпохи в процессе обучения, то достаточно в классе дополнительно реализовать метод on_epoch_end:
def on_epoch_end(self): p = np.random.permutation(len(self.x)) self.x = self.x[p] self.y = self.y[p] print("on_epoch_end")
Здесь мы выполняем перетасовку наблюдений выборки после каждой эпохи (фактически, повторяем работу параметра shuffle=True).
Использование обратных вызовов (callbacks)
В заключение этого занятия кратко рассмотрим возможности реализаций обратных вызовов функций в процессе обучения модели сети. Конечно, первый вопрос, что это такое и зачем они нужны?Представьте, что мы бы хотели останавливать досрочно процесс обучения, если показатель качества (функция потерь) снижается очень медленно. Возможно, мы оказались на каком-то высоком плато и алгоритм backpropagationне может выйти с этого уровня на более низкий и достичь лучших показателей при обучении. В частности, такое действие можно реализовать с помощью встроенного класса callbackEarlyStopping, следующим образом:
callbacks = [ keras.callbacks.EarlyStopping(monitor="loss", min_delta=0.5, patience=1, verbose=1) ] model.fit(x_train, y_train, epochs=3, callbacks=callbacks)
- BaseLogger – для сбора средних значений по показателям метрик;
- History – для записи какого-либо события в историю (статистику) во время обучения сети;
- ModelCheckpoint – для сохранения модели (или весов) с некоторой регулярностью;
- TerminateOnNaN – для досрочной остановки процесса обучения, если значение функции потерь станет не числовым (NaN).
callbacks = [ keras.callbacks.EarlyStopping(monitor="loss", min_delta=0.01, patience=2, verbose=1), keras.callbacks.ModelCheckpoint(filepath="mymodel_", save_best_only=True, monitor="loss", verbose=1), ]
- filepath – путь к папке с данными (вместо будет подставлен номер текущей эпохи);
- save_best_only – флаг, указывающий производить сохранение, если только показатель качества улучшится;
- monitor – отслеживаемый показатель качества.
model = keras.models.load_model('mymodel_1')
и использовать:
print(model.evaluate(x_test, y_test) )
Создание пользовательских классов вызовов
- on_(train|test|predict)_begin(self, logs=None) – вызывается при запуске обучения, тестирования или прогнозирования;
- on_(train|test|predict)_end(self, logs=None) – вызывается в конце соответствующих методов;
- on_(train|test|predict)_batch_begin(self, batch, logs=None) – вызывается вначале обработки мини-батча;
- on_(train|test|predict)_batch_end(self, batch, logs=None) – вызывается в после обработки очередного мини-батча;
- on_epoch_begin(self, epoch, logs=None) – вызывается вначале каждой эпохи;
- on_epoch_end(self, epoch, logs=None) – вызывается в конце каждой эпохи.
class CustomCallback(keras.callbacks.Callback): def on_train_begin(self, logs): self.per_batch_losses = [] def on_batch_end(self, batch, logs): self.per_batch_losses.append(logs.get("loss")) def on_train_end(self, logs): print( self.per_batch_losses[:5] )
Затем, создаем список из callback’ов:
callbacks = [ CustomCallback(), ]
и запускаем процесс обучения:
model.fit(x_train, y_train, epochs=3, callbacks=callbacks)
После обучения увидим в консоли значения функции потерь для первых пяти мини-батчей. Как видите, это достаточно полезный, простой и вместе с тем, гибкий инструмент для гибкого контроля за процессом обучения и эксплуатации нейронных сетей. На следующем занятии мы продолжим тему тонкой настройки обучения моделей и поговорим о методе compile().
Обзор библиотек для машинного обучения на Python
Scikit-learn [1] — библиотека машинного обучения на языке программирования Python с открытым исходным кодом. Содержит реализации практически всех возможных преобразований, и нередко ее одной хватает для полной реализации модели. В данной библиотеки реализованы методы разбиения датасета на тестовый и обучающий, вычисление основных метрик над наборами данных, проведение Кросс-валидация [на 28.01.19 не создан] . В библиотеке также есть основные алгоритмы машинного обучения: линейной регрессии [на 28.01.19 не создан] и её модификаций Лассо, гребневой регрессии, опорных векторов [на 28.01.19 не создан] , решающих деревьев и лесов и др. Есть и реализации основных методов кластеризации. Кроме того, библиотека содержит постоянно используемые исследователями методы работы с признаками: например, понижение размерности методом главных компонент [на 28.01.19 не создан] . Частью пакета является библиотека imblearn [2] , позволяющая работать с разбалансированными выборками и генерировать новые значения.
Примеры кода
Линейная регрессия
Основная статья: Линейная регрессия [на 28.01.19 не создан]
# Add required imports import matplotlib.pyplot as plt import numpy as np from sklearn import datasets from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error, r2_score
diabetes = datasets.load_diabetes() # Use only one feature diabetes_X = diabetes.data[:, np.newaxis, 2]
Разбиение датасета на тренировочный и тестовый:
# Split the data into training/testing sets x_train = diabetes_X[:-20] x_test = diabetes_X[-20:] # Split the targets into training/testing sets y_train = diabetes.target[:-20] y_test = diabetes.target[-20:]
Построение и обучение модели:
lr = LinearRegression() lr.fit(x_train, y_train) predictions = lr.predict(x_test)
# The mean squared error print("Mean squared error: %.2f" % mean_squared_error(y_test, predictions)) # Explained variance score: 1 is perfect prediction print('Variance score: %.2f' % r2_score(y_test, predictions))
> Mean squared error: 2548.07 Variance score: 0.47
Построение графика прямой, получившейся в результате работы линейной регрессии:
plt.scatter(x_test, y_test, color='black') plt.plot(x_test, predictions, color='blue', linewidth=3) plt.xticks(()) plt.yticks(()) plt.show()

Логистическая регрессия
Основная статья: Логистическая регрессия
from sklearn.datasets import load_digits digits = load_digits()
Вывод первых трех тренировочных данных для визуализации:
import numpy as np import matplotlib.pyplot as plt plt.figure(figsize=(20,4)) for index, (image, label) in enumerate(zip(digits.data[0:3], digits.target[0:3])): plt.subplot(1, 3, index + 1) plt.imshow(np.reshape(image, (8,8)), cmap=plt.cm.gray) plt.title('Training: %i\n' % label, fontsize = 20)

Разбиение датасета на тренировочный и тестовый:
from sklearn.model_selection import train_test_split x_train, x_test, y_train, y_test = train_test_split(digits.data, digits.target, test_size=0.25, random_state=0)
Построение и обучение модели:
from sklearn.linear_model import LogisticRegression lr = LogisticRegression() lr.fit(x_train, y_train) predictions = lr.predict(x_test)
score = lr.score(x_test, y_test) print("Score: %.3f" % score)
> Score: 0.953
Перцептрон
Основная статья: Нейронные сети, перцептрон
from sklearn import datasets iris = datasets.load_iris() X = iris.data y = iris.target
Разбиение датасета на тренировочный и тестовый:
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.20)
from sklearn.preprocessing import StandardScaler scaler = StandardScaler() scaler.fit(X_train) X_train = scaler.transform(X_train) X_test = scaler.transform(X_test)
Построение и обучение модели:
from sklearn.neural_network import MLPClassifier mlp = MLPClassifier(hidden_layer_sizes=(10, 10, 10), max_iter=1000) mlp.fit(X_train, y_train.values.ravel()) predictions = mlp.predict(X_test)
from sklearn.metrics import classification_report, confusion_matrix print(confusion_matrix(y_test,predictions)) print(classification_report(y_test,predictions))
> [[ 7 0 0] [ 0 8 1] [ 0 2 12]] precision recall f1-score support 0 1.00 1.00 1.00 7 1 0.80 0.89 0.84 9 2 0.92 0.86 0.89 14 micro avg 0.90 0.90 0.90 30 macro avg 0.91 0.92 0.91 30 weighted avg 0.90 0.90 0.90 30
Метрический классификатор и метод ближайших соседей
Основная статья: Метрический классификатор и метод ближайших соседей: пример через scikit-learn
Дерево решений и случайный лес
Основная статья: Дерево решений и случайный лес: пример через scikit-learn
Обработка естественного языка
Основная статья: Обработка естественного языка
from sklearn import fetch_20newsgroups twenty_train = fetch_20newsgroups(subset='train', shuffle=True, random_state=42)
Вывод первых трех строк первого тренивочного файла и его класса:
print("\n".join(twenty_train.data[0].split("\n")[:3])) print(twenty_train.target_names[twenty_train.target[0]])
> From: lerxst@wam.umd.edu (where's my thing) Subject: WHAT car is this!? Nntp-Posting-Host: rac3.wam.umd.edu rec.autos
Построение и обучение двух моделей. Первая на основе Байесовской классификации [на 28.01.19 не создан] , а вторая использует метод опорных векторов:
from sklearn.pipeline import Pipeline from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer from sklearn.naive_bayes import MultinomialNB text_clf1 = Pipeline([ ('vect', CountVectorizer()), ('tfidf', TfidfTransformer()), ('clf', MultinomialNB()), ]) from sklearn.linear_model import SGDClassifier text_clf2 = Pipeline([ ('vect', CountVectorizer()), ('tfidf', TfidfTransformer()), ('clf', SGDClassifier(loss='hinge', penalty='l2', alpha=1e-3, random_state=42, max_iter=5, tol=None)), ]) text_clf1.fit(twenty_train.data, twenty_train.target) text_clf2.fit(twenty_train.data, twenty_train.target)
twenty_test = fetch_20newsgroups(subset='test', shuffle=True, random_state=42) docs_test = twenty_test.data predicted1 = text_clf1.predict(docs_test) predicted2 = text_clf2.predict(docs_test) print("Score: %.3f" % np.mean(predicted1 == twenty_test.target)) print("Score: %.3f" % np.mean(predicted2 == twenty_test.target))
> Score for naive Bayes: 0.774 Score for SVM: 0.824
Кросс-валилация и подбор параметров
Основная статья: Кросс-валидация
Возьмем предыдущий пример с обработкой естественного языка и попробуем увеличить точность алгоритма за счет кросс-валидации и подбора параметров:
from sklearn.model_selection import GridSearchCV parameters = < 'vect__ngram_range': [(1, 1), (1, 2)], 'tfidf__use_idf': (True, False), 'clf__alpha': (1e-2, 1e-3), > gs_clf = GridSearchCV(text_clf2, parameters, cv=5, iid=False, n_jobs=-1) gs_clf = gs_clf.fit(twenty_train.data, twenty_train.target) print("Best score: %.3f" % gs_clf.best_score_) for param_name in sorted(parameters.keys()): print("%s: %r" % (param_name, gs_clf.best_params_[param_name]))
> Best score: 0.904 clf__alpha: 0.001 tfidf__use_idf: True vect__ngram_range: (1, 2)
Метод опорных векторов (SVM)
Основная статья: Метод опорных векторов (SVM) [на 28.01.19 не создан]
from sklearn import datasets iris = datasets.load_iris()
Разбиение датасета на тестовый и тренировочный:
from sklearn.model_selection import train_test_split x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.25, random_state=0)
Построение и обучение модели:
clf = svm.SVC(kernel='linear', C=1.0) clf.fit(x_train, y_train) predictions = clf.predict(x_test)
from sklearn.metrics import classification_report, confusion_matrix print(confusion_matrix(y_test,predictions)) print(classification_report(y_test,predictions))
> [[13 0 0] [ 0 15 1] [ 0 0 9]] precision recall f1-score support 0 1.00 1.00 1.00 13 1 1.00 0.94 0.97 16 2 0.90 1.00 0.95 9 micro avg 0.97 0.97 0.97 38 macro avg 0.97 0.98 0.97 38 weighted avg 0.98 0.97 0.97 38
EM-алгоритм
Основная статья: EM-алгоритм [на 28.01.19 не создан]
import numpy as np import matplotlib.pyplot as plt from matplotlib.colors import LogNorm from sklearn import mixture n_samples = 300 # generate random sample, two components np.random.seed(0) # generate spherical data centered on (20, 20) shifted_gaussian = np.random.randn(n_samples, 2) + np.array([20, 20]) # generate zero centered stretched Gaussian data C = np.array([[0., -0.7], [3.5, .7]]) stretched_gaussian = np.dot(np.random.randn(n_samples, 2), C) # concatenate the two datasets into the final training set X_train = np.vstack([shifted_gaussian, stretched_gaussian]) # fit a Gaussian Mixture Model with two components clf = mixture.GaussianMixture(n_components=2, covariance_type='full') clf.fit(X_train) # display predicted scores by the model as a contour plot x = np.linspace(-20., 30.) y = np.linspace(-20., 40.) X, Y = np.meshgrid(x, y) XX = np.array([X.ravel(), Y.ravel()]).T Z = -clf.score_samples(XX) Z = Z.reshape(X.shape) CS = plt.contour(X, Y, Z, norm=LogNorm(vmin=1.0, vmax=1000.0), levels=np.logspace(0, 3, 10)) CB = plt.colorbar(CS, shrink=0.8, extend='both') plt.scatter(X_train[:, 0], X_train[:, 1], .8) plt.title('Negative log-likelihood predicted by a GMM') plt.axis('tight') plt.show()

Уменьшение размерности
Основная статья: Уменьшение размерности: пример через scikit-learn
Tensorflow
Описание
Tensorflow [3] — библиотека, разработанная корпорацией Google для работы с тензорами, используется для построения нейронных сетей. Поддержка вычислений на видеокартах имеет поддержку языка программирования C++. На основе данной библиотеки строятся более высокоуровневые библиотеки для работы с нейронными сетями на уровне целых слоев. Так, некоторое время назад популярная библиотека Keras стала использовать Tensorflow как основной бэкенд для вычислений вместо аналогичной библиотеки Theano. Для работы на видеокартах NVIDIA используется библиотека cuDNN. Если вы работаете с картинками (со сверточными нейросетями), скорее всего, придется использовать данную библиотеку.
Примеры кода
Сверточная нейронная сеть
Основная статья: Сверточные нейронные сети
Реализация сверточной нейронной сети для классификации цифр из датасета MNIST:
from __future__ import division, print_function, absolute_import import tensorflow as tf # Import MNIST data from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("/tmp/data/", one_hot=True) # Training Parameters learning_rate = 0.001 num_steps = 200 batch_size = 128 display_step = 10 # Network Parameters num_input = 784 # MNIST data input (img shape: 28*28) num_classes = 10 # MNIST total classes (0-9 digits) dropout = 0.75 # Dropout, probability to keep units # tf Graph input X = tf.placeholder(tf.float32, [None, num_input]) Y = tf.placeholder(tf.float32, [None, num_classes]) keep_prob = tf.placeholder(tf.float32) # dropout (keep probability) # Create some wrappers for simplicity def conv2d(x, W, b, strides=1): # Conv2D wrapper, with bias and relu activation x = tf.nn.conv2d(x, W, strides=[1, strides, strides, 1], padding='SAME') x = tf.nn.bias_add(x, b) return tf.nn.relu(x) def maxpool2d(x, k=2): # MaxPool2D wrapper return tf.nn.max_pool(x, ksize=[1, k, k, 1], strides=[1, k, k, 1], padding='SAME') # Create model def conv_net(x, weights, biases, dropout): # MNIST data input is a 1-D vector of 784 features (28*28 pixels) # Reshape to match picture format [Height x Width x Channel] # Tensor input become 4-D: [Batch Size, Height, Width, Channel] x = tf.reshape(x, shape=[-1, 28, 28, 1]) # Convolution Layer conv1 = conv2d(x, weights['wc1'], biases['bc1']) # Max Pooling (down-sampling) conv1 = maxpool2d(conv1, k=2) # Convolution Layer conv2 = conv2d(conv1, weights['wc2'], biases['bc2']) # Max Pooling (down-sampling) conv2 = maxpool2d(conv2, k=2) # Fully connected layer # Reshape conv2 output to fit fully connected layer input fc1 = tf.reshape(conv2, [-1, weights['wd1'].get_shape().as_list()[0]]) fc1 = tf.add(tf.matmul(fc1, weights['wd1']), biases['bd1']) fc1 = tf.nn.relu(fc1) # Apply Dropout fc1 = tf.nn.dropout(fc1, dropout) # Output, class prediction out = tf.add(tf.matmul(fc1, weights['out']), biases['out']) return out # Store layers weight & bias weights = < # 5x5 conv, 1 input, 32 outputs 'wc1': tf.Variable(tf.random_normal([5, 5, 1, 32])), # 5x5 conv, 32 inputs, 64 outputs 'wc2': tf.Variable(tf.random_normal([5, 5, 32, 64])), # fully connected, 7*7*64 inputs, 1024 outputs 'wd1': tf.Variable(tf.random_normal([7*7*64, 1024])), # 1024 inputs, 10 outputs (class prediction) 'out': tf.Variable(tf.random_normal([1024, num_classes])) > biases = < 'bc1': tf.Variable(tf.random_normal([32])), 'bc2': tf.Variable(tf.random_normal([64])), 'bd1': tf.Variable(tf.random_normal([1024])), 'out': tf.Variable(tf.random_normal([num_classes])) > # Construct model logits = conv_net(X, weights, biases, keep_prob) prediction = tf.nn.softmax(logits) # Define loss and optimizer loss_op = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits( logits=logits, labels=Y)) optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate) train_op = optimizer.minimize(loss_op) # Evaluate model correct_pred = tf.equal(tf.argmax(prediction, 1), tf.argmax(Y, 1)) accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32)) # Initialize the variables (i.e. assign their default value) init = tf.global_variables_initializer() # Start training with tf.Session() as sess: # Run the initializer sess.run(init) for step in range(1, num_steps+1): batch_x, batch_y = mnist.train.next_batch(batch_size) # Run optimization op (backprop) sess.run(train_op, feed_dict=0.8>) if step % display_step == 0 or step == 1: # Calculate batch loss and accuracy loss, acc = sess.run([loss_op, accuracy], feed_dict=1.0>) print("Step " + str(step) + ", Minibatch Loss red">"".format(loss) + ", Training Accuracy red">"".format(acc)) print("Optimization Finished!") # Calculate accuracy for 256 MNIST test images print("Testing Accuracy:", \ sess.run(accuracy, feed_dict=256], Y: mnist.test.labels[:256], keep_prob: 1.0>))
> Step 1, Minibatch Loss= 41724.0586, Training Accuracy= 0.156 Step 10, Minibatch Loss= 17748.7500, Training Accuracy= 0.242 Step 20, Minibatch Loss= 8307.6162, Training Accuracy= 0.578 Step 30, Minibatch Loss= 3108.5703, Training Accuracy= 0.766 Step 40, Minibatch Loss= 3273.2749, Training Accuracy= 0.727 Step 50, Minibatch Loss= 2754.2861, Training Accuracy= 0.820 Step 60, Minibatch Loss= 2467.7925, Training Accuracy= 0.844 Step 70, Minibatch Loss= 1423.8140, Training Accuracy= 0.914 Step 80, Minibatch Loss= 1651.4656, Training Accuracy= 0.875 Step 90, Minibatch Loss= 2105.9263, Training Accuracy= 0.867 Step 100, Minibatch Loss= 1153.5090, Training Accuracy= 0.867 Step 110, Minibatch Loss= 1751.1400, Training Accuracy= 0.898 Step 120, Minibatch Loss= 1446.2119, Training Accuracy= 0.922 Step 130, Minibatch Loss= 1403.7135, Training Accuracy= 0.859 Step 140, Minibatch Loss= 1089.7897, Training Accuracy= 0.930 Step 150, Minibatch Loss= 1147.0751, Training Accuracy= 0.898 Step 160, Minibatch Loss= 1963.3733, Training Accuracy= 0.883 Step 170, Minibatch Loss= 1544.2725, Training Accuracy= 0.859 Step 180, Minibatch Loss= 977.9219, Training Accuracy= 0.914 Step 190, Minibatch Loss= 857.7977, Training Accuracy= 0.930 Step 200, Minibatch Loss= 430.4735, Training Accuracy= 0.953 Optimization Finished! Testing Accuracy: 0.94140625
Keras
Описание
Keras [4] — библиотека для построения нейронных сетей, поддерживающая основные виды слоев и структурные элементы. Поддерживает как рекуррентные, так и сверточные нейросети, имеет в своем составе реализацию известных архитектур нейросетей (например, VGG16). Некоторое время назад слои из данной библиотеки стали доступны внутри библиотеки Tensorflow. Существуют готовые функции для работы с изображениями и текстом. Интегрирована в Apache Spark с помощью дистрибутива dist-keras. Данная библиотека позволяет на более высоком уровне работать с нейронными сетями. В качестве библиотеки для бэкенда может использоваться как Tensorflow, так и Theano.
Примеры кода
Сверточная нейронная сеть
Основная статья: Сверточные нейронные сети
Реализация сверточной нейронной сети для классификации текста:
from __future__ import print_function from keras.preprocessing import sequence from keras.models import Sequential from keras.layers import Dense, Dropout, Activation from keras.layers import Embedding from keras.layers import Conv1D, GlobalMaxPooling1D from keras.datasets import imdb # set parameters: max_features = 5000 maxlen = 400 batch_size = 32 embedding_dims = 50 filters = 250 kernel_size = 3 hidden_dims = 250 epochs = 2 (x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features) print(len(x_train), 'train sequences') print(len(x_test), 'test sequences')
> 25000 train sequences 25000 test sequences
print('Pad sequences (samples x time)') x_train = sequence.pad_sequences(x_train, maxlen=maxlen) x_test = sequence.pad_sequences(x_test, maxlen=maxlen) print('x_train shape:', x_train.shape) print('x_test shape:', x_test.shape)
> Pad sequences (samples x time) x_train shape: (25000, 400) x_test shape: (25000, 400)
model = Sequential() model.add(Embedding(max_features, embedding_dims, input_length=maxlen)) model.add(Dropout(0.2)) model.add(Conv1D(filters, kernel_size, padding='valid', activation='relu', strides=1)) model.add(GlobalMaxPooling1D()) model.add(Dense(hidden_dims)) model.add(Dropout(0.2)) model.add(Activation('relu')) model.add(Dense(1)) model.add(Activation('sigmoid')) model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, validation_data=(x_test, y_test))
> Train on 25000 samples, validate on 25000 samples Epoch 1/2 25000/25000 [==============================] - 136s 5ms/step - loss: 0.4107 - acc: 0.7923 - val_loss: 0.2926 - val_acc: 0.8746 Epoch 2/2 25000/25000 [==============================] - 136s 5ms/step - loss: 0.2294 - acc: 0.9082 - val_loss: 0.3200 - val_acc: 0.8652
Другие библиотеки для машинного обучения на Python
Вспомогательные библиотеки
- NumPy [5] — библиотека, добавляющая поддержку больших многомерных массивов и матриц вместе с большой библиотекой высокоуровневых математических функций для операций с этими массивами. Данная библиотека предоставляет реализации вычислительных алгоритмов (в виде функций и операторов), оптимизированные для работы с многомерными массивами. В результате любой алгоритм, который может быть выражен в виде последовательности операций над массивами (матрицами) и реализованный с использованием NumPy, работает так же быстро, как эквивалентный код, выполняемый в MATLAB [6] ;
- SciPy [7] — открытая библиотека высококачественных научных инструментов для языка программирования Python. SciPy содержит модули для оптимизации, интегрирования, специальных функций, обработки сигналов, обработки изображений, генетических алгоритмов, решения обыкновенных дифференциальных уравнений и других задач, обычно решаемых в науке и при инженерной разработке;
- Pandas [8] — библиотека Python, которая является мощным инструментом для анализа данных. Пакет дает возможность строить сводные таблицы, выполнять группировки, предоставляет удобный доступ к табличным данным и позволяет строить графики на полученных наборах данных при помощи библиотеки Matplotlib;
- Matplotlib [9] — библиотека Python для построения качественных двумерных графиков. Matplotlib является гибким, легко конфигурируемым пакетом, который вместе с NumPy, SciPy и IPython [10] предоставляет возможности, подобные MATLAB.
- Autograd — Библиотека автодифференциирования функций на numpy. ПОзволяет делать простые нейросети и оптимизацию научных расчётов. Для тяжёлого лучше использовать GPU-библиотеки.
- JAX — улучшенный autograd.
- Tensor shape annotation lib — позволяет назначить измерениям тензора человекочитаемые метки
Библиотеки для глубокого обучения
- Tenzorflow [11] — открытая программная библиотека для машинного обучения, разработанная компанией Google для решения задач построения и тренировки нейронной сети с целью автоматического нахождения и классификации образов, достигая качества человеческого восприятия. Широко применяется в бизнес-приложениях.
- PyTorch [12] — библиотека для глубокого обучения, созданная на базе Torch [13] и развиваемая компанией Facebook. Две ключевые функциональности данной библиотеки — тензорные вычисления с развитой поддержкой ускорения на GPU (OpenCL) и глубокие нейронные сети на базе системы autodiff;
- Theano [14] — расширение языка программирования Python, позволяющее эффективно вычислять математические выражения, содержащие многомерные массивы. Библиотека предоставляет базовый набор инструментов для конфигурации нейронных сетей и их обучения. Наибольшее признание данная библиотека получила в задачах машинного обучения при решении задач оптимизации. Она позволяет использовать возможности GPU без изменения кода программы, что делает ее незаменимой при выполнении ресурсоемких задач;
- Caffe [15] — фреймворк для обучения нейронных сетей, созданный университетом Беркли. Как и Tensorflow, использует cuDNN для работы с видеокартами NVIDIA;
- Microsoft Cognitive Toolkit (CNTK) [16] — фреймворк от корпорации Microsoft, предоставляющий реализации архитектур различных нейронных сетей.
- plaidml — ещё одна библиотека на OpenCL, умеющая компилировать граф в оптимизированные кастомные ядра OpenCL.
Библиотеки для обработки естественного языка
- NLTK [17] — пакет библиотек и программ для символьной и статистической обработки естественного языка, написанных на языке программирования Python;
- Gensim [18] — инструмент для автоматической обработки языка, основанный на машинном обучении. В Gensim реализованы алгоритмы дистрибутивной семантики word2vec и doc2vec, он позволяет решать задачи тематического моделирования и выделять основные темы текста или документа.
Библиотеки для градиентного бустинга
- Xgboost [на 28.01.19 не создан] [19] — библиотека с реализацией градиентного бустинга, которая для выбора разбиения использует сортировку и модели, основанные на анализе гистограмм;
- LightGBM [20] — фреймворк с реализацией градиентного бустинга от корпорации Microsoft. Является частью проекта Microsoft DMTK, посвященного реализации подходов машинного обучения для .Net;
- CatBoost[21] — библиотека с градиентным бустингом от компании Яндекс, в которой реализуется особый подход к обработке категориальных признаков, основанный на подмене категориальных признаков статистиками на основе предсказываемого значения.
См. также
- Примеры кода на Scala
- Примеры кода на R [на 28.01.19 не создан]
- Примеры кода на Java
Глубокое обучение на Kotlin: вышла альфа-версия KotlinDL
Мы выпустили первую альфа-версию KotlinDL, фреймворка для глубокого обучения нейросетей, API которого мы старались сделать максимально похожим на Keras (фреймворк на Python поверх TensorFlow).
В KotlinDL вы найдете простые API как для описания, так и для тренировки нейронных сетей. За счет высокоуровневого API и аккуратно подобранных значений по умолчанию для множества параметров мы надеемся снизить порог входа в глубокое обучение на JVM. Вот так, например, выглядит тренировка и сохранение простой нейросети, написанной при помощи KotlinDL:
private val model = Sequential.of( Input(28,28,1), Flatten(), Dense(300), Dense(100), Dense(10) ) fun main() < val (train, test) = Dataset.createTrainAndTestDatasets( trainFeaturesPath = "datasets/mnist/train-images-idx3-ubyte.gz", trainLabelsPath = "datasets/mnist/train-labels-idx1-ubyte.gz", testFeaturesPath = "datasets/mnist/t10k-images-idx3-ubyte.gz", testLabelsPath = "datasets/mnist/t10k-labels-idx1-ubyte.gz", numClasses = 10, ::extractImages, ::extractLabels ) val (newTrain, validation) = train.split(splitRatio = 0.95) model.use< it.compile(optimizer = Adam(), loss = Losses.SOFT_MAX_CROSS_ENTROPY_WITH_LOGITS, metric = Metrics.ACCURACY) it.summary() it.fit(dataset = newTrain, epochs = 10, batchSize = 100, verbose = false) val accuracy = it.evaluate(dataset = validation, batchSize = 100).metrics[Metrics.ACCURACY] println("Accuracy: $accuracy") it.save(File("src/model/my_model")) >>
Поддержка GPU
Тренировка моделей на центральном процессоре может занимать значительное время. Распространенной практикой является запуск вычислений на GPU. Для этого вам понадобится установленная CUDA от NVIDIA. Для запуска тренировки модели на GPU достаточно добавить всего одну зависимость.
Что вошло в API
В этой ранней версии вы найдете все необходимые методы для описания многослойных перцептронов и сверточных сетей. Для большинства гиперпараметров проставлены разумные значения по умолчанию, но в то же время у вас есть широкий выбор оптимизаторов, инициализаторов, функций активации и прочих настроек. Полученную в процессе тренировки модель можно сохранить и использовать в backend-приложении, написанном на Kotlin или Java.
Загрузка моделей, тренированных на Keras
KotlinDL не только умеет загружать модели, тренированные этим же фреймворком, но и предоставляет возможность загрузить и использовать модель, натренированную с помощью Keras на языке Python (поддерживаются версии Keras 2.*).
При загрузке моделей вы также можете использовать технику Transfer Learning, которая позволяет вам не тренировать огромные нейронные сети с нуля, а воспользоваться уже имеющейся моделью и просто подогнать ее под вашу задачу.
Текущие ограничения
В этой, самой ранней версии доступно ограниченное количество слоев: Input(), Flatten(), Dense(), Dropout(), Conv2D(), MaxPool2D() и AvgPool2D().
Это ограничение распространяется и на то, какие Keras-модели можно загружать. Это означает, что архитектуры VGG-16 и VGG-19 поддерживаются уже сейчас, а, например, ResNet50 пока что не поддерживается. В ближайшие месяцы мы планируем выпустить следующую минорную версию, в которой увеличится количество поддерживаемых архитектур.
Второе временное ограничение заключается в том, что поддержка Android-устройств пока не вошла в данную версию. Но над этим мы тоже будем работать.
А что под капотом?
В качестве движка KotlinDL использует TensorFlow Java API. Все вычисления выполняются в TensorFlow, в нативной памяти, причем во время тренировки все данные остаются в нативе.
Попробуйте и поделитесь впечатлениями!
В документации к проекту вы найдете статьи (на английском), которые, надеемся, помогут вам попробовать наш фреймворк:
- Quick start guide
- Create your first neural network with KotlinDL
- Training a model
- Inference example
- Importing a Keras model
- Transfer learning example
Будем рады вашим замечаниям, пожеланиям, баг-репортам и другим отзывам в GitHub Issues. Особенно приветствуются пул-реквесты. Присоединяйтесь к каналу #deeplearning в Kotlin Slack.
Ваша команда Kotlin
The Drive to Develop