Посмотреть на TensorFlow.org | Запустить в Google Colab | Посмотреть исходный код на GitHub | Скачать блокнот |
В этом руководстве показано, как решить проблему классификации Iris в TensorFlow с помощью Estimators. Estimator — это устаревшее высокоуровневое представление полной модели TensorFlow. Дополнительные сведения см. в разделе Оценщики .
Перво-наперво
Чтобы начать работу, вы сначала импортируете TensorFlow и ряд необходимых вам библиотек.
import tensorflow as tf
import pandas as pd
Набор данных
Пример программы в этом документе создает и тестирует модель, которая классифицирует цветы ириса по трем разным видам в зависимости от размера их чашелистиков и лепестков .
Вы будете обучать модель, используя набор данных Iris. Набор данных Iris содержит четыре функции и одну метку . Четыре признака определяют следующие ботанические характеристики отдельных цветков ириса:
- длина чашелистика
- ширина чашелистика
- длина лепестка
- ширина лепестка
На основе этой информации вы можете определить несколько полезных констант для анализа данных:
CSV_COLUMN_NAMES = ['SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth', 'Species']
SPECIES = ['Setosa', 'Versicolor', 'Virginica']
Затем загрузите и проанализируйте набор данных Iris с помощью Keras и Pandas. Обратите внимание, что вы сохраняете отдельные наборы данных для обучения и тестирования.
train_path = tf.keras.utils.get_file(
"iris_training.csv", "https://storage.googleapis.com/download.tensorflow.org/data/iris_training.csv")
test_path = tf.keras.utils.get_file(
"iris_test.csv", "https://storage.googleapis.com/download.tensorflow.org/data/iris_test.csv")
train = pd.read_csv(train_path, names=CSV_COLUMN_NAMES, header=0)
test = pd.read_csv(test_path, names=CSV_COLUMN_NAMES, header=0)
Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/iris_training.csv 16384/2194 [================================================================================================================================================================================================================================] - 0s 0us/step Downloading data from https://storage.googleapis.com/download.tensorflow.org/data/iris_test.csv 16384/573 [=========================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================] - 0s 0us/step
Вы можете проверить свои данные, чтобы увидеть, что у вас есть четыре столбца функций с плавающей запятой и одна метка int32.
train.head()
Для каждого из наборов данных разделите метки, которые модель будет обучать прогнозировать.
train_y = train.pop('Species')
test_y = test.pop('Species')
# The label column has now been removed from the features.
train.head()
Обзор программирования с оценщиками
Теперь, когда у вас настроены данные, вы можете определить модель с помощью оценщика TensorFlow. Estimator — это любой класс, производный от tf.estimator.Estimator
. TensorFlow предоставляет набор tf.estimator
(например, LinearRegressor
) для реализации распространенных алгоритмов машинного обучения. Помимо этого, вы можете написать свои собственные оценщики . Когда вы только начинаете, рекомендуется использовать готовые оценщики.
Чтобы написать программу TensorFlow на основе готовых оценщиков, необходимо выполнить следующие задачи:
- Создайте одну или несколько функций ввода.
- Определите столбцы признаков модели.
- Создайте экземпляр Estimator, указав столбцы функций и различные гиперпараметры.
- Вызовите один или несколько методов объекта Estimator, передав соответствующую входную функцию в качестве источника данных.
Давайте посмотрим, как эти задачи реализованы для классификации Iris.
Создайте входные функции
Вы должны создать входные функции для предоставления данных для обучения, оценки и прогнозирования.
Входная функция — это функция, которая возвращает объект tf.data.Dataset
, который выводит следующий двухэлементный кортеж:
-
features
— словарь Python, в котором:- Каждый ключ является именем функции.
- Каждое значение представляет собой массив, содержащий все значения этой функции.
-
label
- Массив, содержащий значения метки для каждого примера.
Чтобы продемонстрировать формат входной функции, вот простая реализация:
def input_evaluation_set():
features = {'SepalLength': np.array([6.4, 5.0]),
'SepalWidth': np.array([2.8, 2.3]),
'PetalLength': np.array([5.6, 3.3]),
'PetalWidth': np.array([2.2, 1.0])}
labels = np.array([2, 1])
return features, labels
Ваша функция ввода может генерировать словарь features
и список label
любым удобным для вас способом. Однако рекомендуется использовать API набора данных TensorFlow , который может анализировать все виды данных.
API набора данных может обрабатывать множество распространенных случаев. Например, используя Dataset API, вы можете легко считывать записи из большой коллекции файлов параллельно и объединять их в единый поток.
Для простоты в этом примере вы собираетесь загрузить данные с помощью pandas и построить входной конвейер из этих данных в памяти:
def input_fn(features, labels, training=True, batch_size=256):
"""An input function for training or evaluating"""
# Convert the inputs to a Dataset.
dataset = tf.data.Dataset.from_tensor_slices((dict(features), labels))
# Shuffle and repeat if you are in training mode.
if training:
dataset = dataset.shuffle(1000).repeat()
return dataset.batch(batch_size)
Определите столбцы функций
Столбец признаков — это объект, описывающий, как модель должна использовать необработанные входные данные из словаря признаков. Когда вы строите модель Estimator, вы передаете ей список столбцов функций, описывающих каждую из функций, которые вы хотите использовать в модели. Модуль tf.feature_column
предоставляет множество опций для представления данных в модели.
Для Iris 4 необработанных признака являются числовыми значениями, поэтому вы создадите список столбцов признаков, чтобы сообщить модели Estimator о представлении каждого из четырех признаков в виде 32-битных значений с плавающей запятой. Таким образом, код для создания столбца функций:
# Feature columns describe how to use the input.
my_feature_columns = []
for key in train.keys():
my_feature_columns.append(tf.feature_column.numeric_column(key=key))
Столбцы функций могут быть гораздо более сложными, чем показанные здесь. Подробнее о Feature Columns можно прочитать в этом руководстве .
Теперь, когда у вас есть описание того, как вы хотите, чтобы модель представляла необработанные функции, вы можете построить оценщик.
Создание экземпляра оценщика
Проблема Ириса — классическая задача классификации. К счастью, TensorFlow предоставляет несколько готовых оценщиков классификаторов, в том числе:
-
tf.estimator.DNNClassifier
для глубоких моделей, выполняющих мультиклассовую классификацию. -
tf.estimator.DNNLinearCombinedClassifier
для широких и глубоких моделей. -
tf.estimator.LinearClassifier
для классификаторов на основе линейных моделей.
Для проблемы Iris tf.estimator.DNNClassifier
кажется лучшим выбором. Вот как вы создали этот Estimator:
# Build a DNN with 2 hidden layers with 30 and 10 hidden nodes each.
classifier = tf.estimator.DNNClassifier(
feature_columns=my_feature_columns,
# Two hidden layers of 30 and 10 nodes respectively.
hidden_units=[30, 10],
# The model must choose between 3 classes.
n_classes=3)
INFO:tensorflow:Using default config. WARNING:tensorflow:Using temporary folder as model directory: /tmp/tmpxdgumb2t INFO:tensorflow:Using config: {'_model_dir': '/tmp/tmpxdgumb2t', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': allow_soft_placement: true graph_options { rewrite_options { meta_optimizer_iterations: ONE } } , '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_device_fn': None, '_protocol': None, '_eval_distribute': None, '_experimental_distribute': None, '_experimental_max_worker_delay_secs': None, '_session_creation_timeout_secs': 7200, '_checkpoint_save_graph_def': True, '_service': None, '_cluster_spec': ClusterSpec({}), '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}
Обучайте, оценивайте и прогнозируйте
Теперь, когда у вас есть объект Estimator, вы можете вызывать методы для выполнения следующих действий:
- Обучите модель.
- Оцените обученную модель.
- Используйте обученную модель, чтобы делать прогнозы.
Обучите модель
Обучите модель, вызвав метод train
Estimator следующим образом:
# Train the Model.
classifier.train(
input_fn=lambda: input_fn(train, train_y, training=True),
steps=5000)
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/training/training_util.py:397: Variable.initialized_value (from tensorflow.python.ops.variables) is deprecated and will be removed in a future version. Instructions for updating: Use Variable.read_value. Variables in 2.X are initialized automatically both in eager and graph (inside tf.defun) contexts. INFO:tensorflow:Calling model_fn. WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/optimizer_v2/adagrad.py:84: calling Constant.__init__ (from tensorflow.python.ops.init_ops) with dtype is deprecated and will be removed in a future version. Instructions for updating: Call initializer instance with the dtype argument instead of passing it to the constructor INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Create CheckpointSaverHook. INFO:tensorflow:Graph was finalized. INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 0... INFO:tensorflow:Saving checkpoints for 0 into /tmp/tmpxdgumb2t/model.ckpt. INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 0... INFO:tensorflow:loss = 1.6787335, step = 0 INFO:tensorflow:global_step/sec: 305.625 INFO:tensorflow:loss = 1.1945828, step = 100 (0.328 sec) INFO:tensorflow:global_step/sec: 375.48 INFO:tensorflow:loss = 1.0221117, step = 200 (0.266 sec) INFO:tensorflow:global_step/sec: 376.21 INFO:tensorflow:loss = 0.9240805, step = 300 (0.266 sec) INFO:tensorflow:global_step/sec: 377.968 INFO:tensorflow:loss = 0.85917354, step = 400 (0.265 sec) INFO:tensorflow:global_step/sec: 376.297 INFO:tensorflow:loss = 0.81545967, step = 500 (0.265 sec) INFO:tensorflow:global_step/sec: 367.549 INFO:tensorflow:loss = 0.7771524, step = 600 (0.272 sec) INFO:tensorflow:global_step/sec: 378.887 INFO:tensorflow:loss = 0.74371505, step = 700 (0.264 sec) INFO:tensorflow:global_step/sec: 379.26 INFO:tensorflow:loss = 0.717993, step = 800 (0.264 sec) INFO:tensorflow:global_step/sec: 370.102 INFO:tensorflow:loss = 0.6952705, step = 900 (0.270 sec) INFO:tensorflow:global_step/sec: 373.034 INFO:tensorflow:loss = 0.68044865, step = 1000 (0.268 sec) INFO:tensorflow:global_step/sec: 372.193 INFO:tensorflow:loss = 0.65181077, step = 1100 (0.269 sec) INFO:tensorflow:global_step/sec: 339.238 INFO:tensorflow:loss = 0.6319051, step = 1200 (0.295 sec) INFO:tensorflow:global_step/sec: 334.252 INFO:tensorflow:loss = 0.63433766, step = 1300 (0.299 sec) INFO:tensorflow:global_step/sec: 343.436 INFO:tensorflow:loss = 0.61748827, step = 1400 (0.291 sec) INFO:tensorflow:global_step/sec: 346.575 INFO:tensorflow:loss = 0.606356, step = 1500 (0.288 sec) INFO:tensorflow:global_step/sec: 351.362 INFO:tensorflow:loss = 0.59807724, step = 1600 (0.285 sec) INFO:tensorflow:global_step/sec: 366.628 INFO:tensorflow:loss = 0.5832784, step = 1700 (0.273 sec) INFO:tensorflow:global_step/sec: 367.034 INFO:tensorflow:loss = 0.5664347, step = 1800 (0.273 sec) INFO:tensorflow:global_step/sec: 372.339 INFO:tensorflow:loss = 0.5684726, step = 1900 (0.268 sec) INFO:tensorflow:global_step/sec: 368.957 INFO:tensorflow:loss = 0.56011164, step = 2000 (0.271 sec) INFO:tensorflow:global_step/sec: 373.128 INFO:tensorflow:loss = 0.5483226, step = 2100 (0.268 sec) INFO:tensorflow:global_step/sec: 377.334 INFO:tensorflow:loss = 0.5447233, step = 2200 (0.265 sec) INFO:tensorflow:global_step/sec: 370.421 INFO:tensorflow:loss = 0.5358016, step = 2300 (0.270 sec) INFO:tensorflow:global_step/sec: 367.076 INFO:tensorflow:loss = 0.53145075, step = 2400 (0.273 sec) INFO:tensorflow:global_step/sec: 373.596 INFO:tensorflow:loss = 0.50931674, step = 2500 (0.268 sec) INFO:tensorflow:global_step/sec: 368.939 INFO:tensorflow:loss = 0.5253717, step = 2600 (0.271 sec) INFO:tensorflow:global_step/sec: 354.814 INFO:tensorflow:loss = 0.52558273, step = 2700 (0.282 sec) INFO:tensorflow:global_step/sec: 372.243 INFO:tensorflow:loss = 0.51422054, step = 2800 (0.269 sec) INFO:tensorflow:global_step/sec: 366.891 INFO:tensorflow:loss = 0.49747026, step = 2900 (0.272 sec) INFO:tensorflow:global_step/sec: 370.952 INFO:tensorflow:loss = 0.49974674, step = 3000 (0.270 sec) INFO:tensorflow:global_step/sec: 364.158 INFO:tensorflow:loss = 0.4978399, step = 3100 (0.275 sec) INFO:tensorflow:global_step/sec: 365.383 INFO:tensorflow:loss = 0.5030147, step = 3200 (0.273 sec) INFO:tensorflow:global_step/sec: 366.791 INFO:tensorflow:loss = 0.4772169, step = 3300 (0.273 sec) INFO:tensorflow:global_step/sec: 372.438 INFO:tensorflow:loss = 0.46993533, step = 3400 (0.269 sec) INFO:tensorflow:global_step/sec: 371.25 INFO:tensorflow:loss = 0.47242266, step = 3500 (0.269 sec) INFO:tensorflow:global_step/sec: 369.725 INFO:tensorflow:loss = 0.46513358, step = 3600 (0.271 sec) INFO:tensorflow:global_step/sec: 371.002 INFO:tensorflow:loss = 0.4762191, step = 3700 (0.270 sec) INFO:tensorflow:global_step/sec: 369.304 INFO:tensorflow:loss = 0.44923267, step = 3800 (0.271 sec) INFO:tensorflow:global_step/sec: 369.344 INFO:tensorflow:loss = 0.45467538, step = 3900 (0.271 sec) INFO:tensorflow:global_step/sec: 375.58 INFO:tensorflow:loss = 0.46056622, step = 4000 (0.266 sec) INFO:tensorflow:global_step/sec: 347.461 INFO:tensorflow:loss = 0.4489282, step = 4100 (0.288 sec) INFO:tensorflow:global_step/sec: 368.435 INFO:tensorflow:loss = 0.45647347, step = 4200 (0.272 sec) INFO:tensorflow:global_step/sec: 369.159 INFO:tensorflow:loss = 0.4444633, step = 4300 (0.271 sec) INFO:tensorflow:global_step/sec: 371.995 INFO:tensorflow:loss = 0.44425523, step = 4400 (0.269 sec) INFO:tensorflow:global_step/sec: 373.586 INFO:tensorflow:loss = 0.44025964, step = 4500 (0.268 sec) INFO:tensorflow:global_step/sec: 373.136 INFO:tensorflow:loss = 0.44341013, step = 4600 (0.269 sec) INFO:tensorflow:global_step/sec: 369.751 INFO:tensorflow:loss = 0.42856425, step = 4700 (0.269 sec) INFO:tensorflow:global_step/sec: 364.219 INFO:tensorflow:loss = 0.44144967, step = 4800 (0.275 sec) INFO:tensorflow:global_step/sec: 372.675 INFO:tensorflow:loss = 0.42951846, step = 4900 (0.268 sec) INFO:tensorflow:Calling checkpoint listeners before saving checkpoint 5000... INFO:tensorflow:Saving checkpoints for 5000 into /tmp/tmpxdgumb2t/model.ckpt. INFO:tensorflow:Calling checkpoint listeners after saving checkpoint 5000... INFO:tensorflow:Loss for final step: 0.42713496. <tensorflow_estimator.python.estimator.canned.dnn.DNNClassifierV2 at 0x7fad05e33910>
Обратите внимание, что вы заключаете вызов input_fn
в lambda
-выражение для захвата аргументов, предоставляя при этом входную функцию, которая не принимает аргументов, как и ожидалось оценщиком. Аргумент steps
указывает методу прекратить обучение после нескольких шагов обучения.
Оцените обученную модель
Теперь, когда модель обучена, вы можете получить некоторую статистику ее производительности. Следующий блок кода оценивает точность обученной модели на тестовых данных:
eval_result = classifier.evaluate(
input_fn=lambda: input_fn(test, test_y, training=False))
print('\nTest set accuracy: {accuracy:0.3f}\n'.format(**eval_result))
INFO:tensorflow:Calling model_fn. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Starting evaluation at 2022-01-26T06:41:28 INFO:tensorflow:Graph was finalized. INFO:tensorflow:Restoring parameters from /tmp/tmpxdgumb2t/model.ckpt-5000 INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. INFO:tensorflow:Inference Time : 0.40087s INFO:tensorflow:Finished evaluation at 2022-01-26-06:41:28 INFO:tensorflow:Saving dict for global step 5000: accuracy = 0.8666667, average_loss = 0.49953422, global_step = 5000, loss = 0.49953422 INFO:tensorflow:Saving 'checkpoint_path' summary for global step 5000: /tmp/tmpxdgumb2t/model.ckpt-5000 Test set accuracy: 0.867
В отличие от вызова метода train
, вы не передавали аргумент steps
для оценки. input_fn
для eval дает данные только за одну эпоху .
Словарь eval_result
также содержит average_loss
(средняя потеря на выборку), loss
(средняя потеря на мини-партию) и значение global_step
(количество пройденных итераций обучения).
Делать прогнозы (выводы) из обученной модели
Теперь у вас есть обученная модель, которая дает хорошие результаты оценки. Теперь вы можете использовать обученную модель для прогнозирования вида цветка ириса на основе некоторых немаркированных измерений. Как и в случае с обучением и оценкой, вы делаете прогнозы, используя один вызов функции:
# Generate predictions from the model
expected = ['Setosa', 'Versicolor', 'Virginica']
predict_x = {
'SepalLength': [5.1, 5.9, 6.9],
'SepalWidth': [3.3, 3.0, 3.1],
'PetalLength': [1.7, 4.2, 5.4],
'PetalWidth': [0.5, 1.5, 2.1],
}
def input_fn(features, batch_size=256):
"""An input function for prediction."""
# Convert the inputs to a Dataset without labels.
return tf.data.Dataset.from_tensor_slices(dict(features)).batch(batch_size)
predictions = classifier.predict(
input_fn=lambda: input_fn(predict_x))
Метод predict
возвращает итерируемый объект Python, что дает словарь результатов предсказания для каждого примера. Следующий код выводит несколько прогнозов и их вероятности:
for pred_dict, expec in zip(predictions, expected):
class_id = pred_dict['class_ids'][0]
probability = pred_dict['probabilities'][class_id]
print('Prediction is "{}" ({:.1f}%), expected "{}"'.format(
SPECIES[class_id], 100 * probability, expec))
INFO:tensorflow:Calling model_fn. INFO:tensorflow:Done calling model_fn. INFO:tensorflow:Graph was finalized. INFO:tensorflow:Restoring parameters from /tmp/tmpxdgumb2t/model.ckpt-5000 INFO:tensorflow:Running local_init_op. INFO:tensorflow:Done running local_init_op. Prediction is "Setosa" (84.4%), expected "Setosa" Prediction is "Versicolor" (49.3%), expected "Versicolor" Prediction is "Virginica" (57.7%), expected "Virginica"