Скажите, что я хочу написать машинное обучение для решения проблемы классификации под наблюдением. Мне дают X (n_samples, n_features)
и y (n_samples, n_labels)
данные (особенности, полученные для каждого образца в моем наборе данных) и соответствующие метки. Чтобы обучить мою модель, я бы разделил X
(соответственно y
) на X_train
, X_val
и X_test
(соответственно y_train
, y_val
и y_test
). Затем я подгоняю свою модель к (X_train, y_train)
и использую (X_val, y_val)
для мониторинга некоторой метрики (потери, точность ...), которая помогает мне избежать переобучения. После того, как модель обучена, я оцениваю ее по (X_test, y_test)
. Я считаю, что это классика.
В учебном пособии по пользовательским оценщикам с Tensorflow я обнаружил некоторый код, который предлагает использовать известный набор данных Iris и реализовать Dense Neural Net (DNN) с 3 скрытыми слоями. Полный код приведен ниже.
код для модели:
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import argparse
import tensorflow as tf
import .iris_data
parser = argparse.ArgumentParser()
parser.add_argument('--batch_size', default=100, type=int, help='batch size')
parser.add_argument('--train_steps', default=2000, type=int, help='number of training steps')
def my_model(features, labels, mode, params):
"""DNN with three hidden layers, and dropout of 0.1 probability."""
# Create three fully connected layers each layer having a dropout
# probability of 0.1.
net = tf.feature_column.input_layer(features, params['feature_columns'])
for units in params['hidden_units']:
net = tf.layers.dense(net, units=units, activation=tf.nn.relu)
# Compute logits (1 per class).
logits = tf.layers.dense(net, params['n_classes'], activation=None)
# Compute predictions.
predicted_classes = tf.argmax(logits, 1)
if mode == tf.estimator.ModeKeys.PREDICT:
predictions = {
'class_ids': predicted_classes[:, tf.newaxis],
'probabilities': tf.nn.softmax(logits),
'logits': logits,
}
return tf.estimator.EstimatorSpec(mode, predictions=predictions)
# Compute loss.
loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)
# Compute evaluation metrics.
accuracy = tf.metrics.accuracy(labels=labels, predictions=predicted_classes, name='acc_op')
metrics = {'accuracy': accuracy}
tf.summary.scalar('accuracy', accuracy[1])
if mode == tf.estimator.ModeKeys.EVAL:
return tf.estimator.EstimatorSpec(mode, loss=loss, eval_metric_ops=metrics)
# Create training op.
assert mode == tf.estimator.ModeKeys.TRAIN
optimizer = tf.train.AdagradOptimizer(learning_rate=0.1)
train_op = optimizer.minimize(loss, global_step=tf.train.get_global_step())
return tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)
def main(argv):
args = parser.parse_args(argv[1:])
# Fetch the data
(train_x, train_y), (val_x, val_y), (test_x, test_y) = iris_data.load_data()
# Feature columns describe how to use the input.
my_feature_columns = []
for key in train_x.keys():
my_feature_columns.append(tf.feature_column.numeric_column(key=key))
# Build 2 hidden layer DNN with 10, 10 units respectively.
classifier = tf.estimator.Estimator(
model_fn=my_model,
params={
'feature_columns': my_feature_columns,
# Two hidden layers of 10 nodes each.
'hidden_units': [10, 10],
# The model must choose between 3 classes.
'n_classes': 3,
})
# Train the model
early_stopping = stop_if_no_decrease_hook(classifier, metric_name='validation_accuracy', max_steps_without_decrease=10, min_steps=2)
results = tf.estimator.train_and_evaluate(
classifier,
train_spec=tf.estimator.TrainSpec(input_fn=lambda: iris_data.train_input_fn(train_x, train_y, args.batch_size), max_steps=2000, hooks=[early_stopping]),
eval_spec=tf.estimator.EvalSpec(input_fn=lambda: iris_data.eval_input_fn(val_x, val_y, args.batch_size), throttle_secs=2, start_delay_secs=2),
)
# Generate predictions from the model
predictions = classifier.predict(
input_fn=lambda: iris_data.eval_input_fn(test_x, test_y,
batch_size=args.batch_size))
# Remains to evaluate predictions on test_x...
if __name__ == '__main__':
tf.logging.set_verbosity(tf.logging.INFO)
tf.app.run(main)
И код для загрузки данных Iris:
import pandas as pd
import tensorflow as tf
from sklearn.model_selection import train_test_split
TRAIN_URL = "http://download.tensorflow.org/data/iris_training.csv"
TEST_URL = "http://download.tensorflow.org/data/iris_test.csv"
CSV_COLUMN_NAMES = ['SepalLength', 'SepalWidth',
'PetalLength', 'PetalWidth', 'Species']
SPECIES = ['Setosa', 'Versicolor', 'Virginica']
def maybe_download():
train_path = tf.keras.utils.get_file(TRAIN_URL.split('/')[-1], TRAIN_URL)
test_path = tf.keras.utils.get_file(TEST_URL.split('/')[-1], TEST_URL)
return train_path, test_path
def load_data(y_name='Species'):
"""Returns the iris dataset as (train_x, train_y), (test_x, test_y)."""
train_path, test_path = maybe_download()
train = pd.read_csv(train_path, names=CSV_COLUMN_NAMES, header=0)
aux_x, aux_y = train, train.pop(y_name)
# split aux_x, aux_y into training / validation data
train_x, val_x, train_y, val_y = train_test_split(aux_x, aux_y, test_size=0.5)
test = pd.read_csv(test_path, names=CSV_COLUMN_NAMES, header=0)
test_x, test_y = test, test.pop(y_name)
return (train_x, train_y), (val_x, val_y), (test_x, test_y)
def train_input_fn(features, labels, batch_size):
"""An input function for training"""
# Convert the inputs to a Dataset.
dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels))
# Shuffle, repeat, and batch the examples.
dataset = dataset.shuffle(1000).repeat().batch(batch_size)
# Return the dataset.
return dataset
def eval_input_fn(features, labels, batch_size):
"""An input function for evaluation or prediction"""
features = dict(features)
if labels is None:
# No labels, use only features.
inputs = features
else:
inputs = (features, labels)
# Convert the inputs to a Dataset.
dataset = tf.data.Dataset.from_tensor_slices(inputs)
# Batch the examples
assert batch_size is not None, "batch_size must not be None"
dataset = dataset.batch(batch_size)
# Return the dataset.
return dataset
Учитывая этот пример, мои вопросы:
- Как я могу контролировать точность на
train_x
и val_x
(данные обучения и проверки)?
Насколько я понимаю, если я хочу выводить оба на консоль во время обучения модели, я должен использовать LoggingTensorHook с одним крючком для точности обучения и другим для точности проверки ... Если я пишу
logging_hook = tf.train.LoggingTensorHook({"loss": loss, "accuracy":
accuracy[1]}, every_n_iter=10)
в my_model
и добавление training_hooks=[logging_hook]
в tf.estimator.EstimatorSpec
(возвращается функцией), это позволяет мне отслеживать точность тренировки каждые 10 шагов во время тренировки. Тем не менее, я не уверен, как я мог получить точность проверки с этим. Должен ли я определить другой ловушку регистрации таким же образом, когда режим EVAL
?
- Как я могу определить правило ранней остановки на основе этой метрики проверки (вычисленной во время обучения)?
Опять же, насколько я понимаю, я должен использовать tf.estimator.train_and_evaluate и tf.contrib.estimator.stop_if_no_decrease_hook примерно так:
early_stopping = stop_if_no_decrease_hook(
ldcrf_classifier,
metric_name='loss',
max_steps_without_decrease=10,
min_steps=2)
Но опять же, как мне определить validation_accuracy
?