{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# TF 2.2 блокнот\n[По сути, это перевод стартового блокнота от команды TensorFlow](https://www.kaggle.com/philculliton/a-simple-petals-tf-2-2-notebook)","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras.models import Sequential, Model\nfrom tensorflow.keras.layers import Dense, Flatten, Input\nfrom tensorflow.keras.layers import Dropout, BatchNormalization, SpatialDropout2D, GaussianDropout\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D, AveragePooling2D\nfrom tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau\nfrom tensorflow.keras import utils\nfrom tensorflow.keras.regularizers import *\nimport numpy as np\nimport os\nfrom tensorflow.random import set_seed\ndef seed_everything(seed):\n    np.random.seed(seed)\n    set_seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    os.environ['TF_DETERMINISTIC_OPS'] = '1'\n\nseed = 42\nseed_everything(seed)\n\n\nfrom tensorflow.keras.preprocessing import image\nimport matplotlib.pyplot as plt\n%matplotlib inline \n\n\nfrom kaggle_datasets import KaggleDatasets\nimport matplotlib.pyplot as plt\n%matplotlib inline \nprint(\"Tensorflow version \" + tf.__version__)","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","execution":{"iopub.status.busy":"2022-06-07T08:53:01.015233Z","iopub.execute_input":"2022-06-07T08:53:01.015594Z","iopub.status.idle":"2022-06-07T08:53:07.47527Z","shell.execute_reply.started":"2022-06-07T08:53:01.015505Z","shell.execute_reply":"2022-06-07T08:53:07.474266Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Определяем, какой ускоритель можем использовать","metadata":{}},{"cell_type":"code","source":"# Обнаружение оборудования, возврат соответствующей стратегии распространения: TPU, GPU, CPU\ntry:\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver()  # Обнаружение TPU. Параметры среды не требуются, если задана переменная среды TPU_NAME. На Kaggle это всегда так.\n    print('Running on TPU ', tpu.master())\nexcept ValueError:\n    tpu = None\n\nif tpu:\n    tf.config.experimental_connect_to_cluster(tpu)\n    tf.tpu.experimental.initialize_tpu_system(tpu)\n    strategy = tf.distribute.experimental.TPUStrategy(tpu)\nelse:\n    strategy = tf.distribute.get_strategy() # стратегия распространения по умолчанию в Tensorflow. Работает на CPU и одном GPU.\n\nprint(\"REPLICAS: \", strategy.num_replicas_in_sync)","metadata":{"execution":{"iopub.status.busy":"2022-06-07T08:53:07.477263Z","iopub.execute_input":"2022-06-07T08:53:07.477614Z","iopub.status.idle":"2022-06-07T08:53:13.00299Z","shell.execute_reply.started":"2022-06-07T08:53:07.477572Z","shell.execute_reply":"2022-06-07T08:53:13.002389Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Get my data path","metadata":{}},{"cell_type":"code","source":"GCS_DS_PATH = KaggleDatasets().get_gcs_path() #получаем путь к наборам данных","metadata":{"execution":{"iopub.status.busy":"2022-06-07T08:53:13.003921Z","iopub.execute_input":"2022-06-07T08:53:13.004173Z","iopub.status.idle":"2022-06-07T08:53:13.366038Z","shell.execute_reply.started":"2022-06-07T08:53:13.004144Z","shell.execute_reply":"2022-06-07T08:53:13.365401Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Set some parameters","metadata":{}},{"cell_type":"code","source":"IMAGE_SIZE = [192, 192] # при таком размере графическому процессору не хватит памяти. Используйте TPU\nEPOCHS = 100\nBATCH_SIZE = 20 * strategy.num_replicas_in_sync\n\nNUM_TRAINING_IMAGES = 12753\nNUM_TEST_IMAGES = 7382\nSTEPS_PER_EPOCH = NUM_TRAINING_IMAGES // BATCH_SIZE # находим количество шагов за эпоху","metadata":{"execution":{"iopub.status.busy":"2022-06-07T08:53:13.368133Z","iopub.execute_input":"2022-06-07T08:53:13.369024Z","iopub.status.idle":"2022-06-07T08:53:13.375003Z","shell.execute_reply.started":"2022-06-07T08:53:13.368979Z","shell.execute_reply":"2022-06-07T08:53:13.374387Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Загружаем данные\n\nЭти данные загружаются из Kaggle и автоматически сегментируются для максимального распараллеливания.","metadata":{}},{"cell_type":"code","source":"def decode_image(image_data):\n    \"\"\"Декодирует изображение в vyjujvthye. vfnhbwe (тензор)\n    Нормализует данные и преобразовывает изображения к указанному размеру\"\"\"\n    image = tf.image.decode_jpeg(image_data, channels=3) # Декодирование изображения в формате JPEG в тензор uint8.\n    image = tf.cast(image, tf.float32) / 255.0  # преобразовать изображение в плавающее в диапазоне [0, 1]\n    image = tf.reshape(image, [*IMAGE_SIZE, 3]) # явный размер, необходимый для TPU\n#     image = tf.keras.applications.inception_resnet_v2.preprocess_input(image)\n    return image\n\ndef read_labeled_tfrecord(example):\n    LABELED_TFREC_FORMAT = {\n        \"image\": tf.io.FixedLenFeature([], tf.string), # tf.string означает байтовую строку\n        \"class\": tf.io.FixedLenFeature([], tf.int64),  # [] означает отдельный элемент\n    }\n    example = tf.io.parse_single_example(example, LABELED_TFREC_FORMAT) # парсим отдельный пример в указанном формате\n    image = decode_image(example['image']) # преобразуем изображение к нужному нам формату\n    label = tf.cast(example['class'], tf.int32)\n    return image, label # возвращает набор данных пар (изображение, метка)\n\ndef read_unlabeled_tfrecord(example):\n    UNLABELED_TFREC_FORMAT = {\n        \"image\": tf.io.FixedLenFeature([], tf.string), # tf.string означает байтовую строку\n        \"id\": tf.io.FixedLenFeature([], tf.string),  # [] означает отдельный элемент\n        # класс отсутствует, задача этого конкурса - предсказать классы цветов для тестового набора данных\n    }\n    example = tf.io.parse_single_example(example, UNLABELED_TFREC_FORMAT)\n    image = decode_image(example['image']) # преобразуем изображение к нужному нам формату\n    idnum = example['id']\n    return image, idnum # returns a dataset of image(s)\n\ndef load_dataset(filenames, labeled=True, ordered=False):\n    \"\"\"Читает из TFRecords. Для оптимальной производительности одновременное чтение из нескольких\n    файлов без учета порядка данных. Порядок не имеет значения, поскольку мы все равно будем перетасовывать данные\"\"\"\n\n    ignore_order = tf.data.Options() # Представляет параметры для tf.data.Dataset.\n    if not ordered:\n        ignore_order.experimental_deterministic = False # отключить порядок, увеличить скорость\n\n    dataset = tf.data.TFRecordDataset(filenames) # автоматически чередует чтение из нескольких файлов\n    dataset = dataset.with_options(ignore_order) # использует данные сразу после их поступления, а не в исходном порядке\n    dataset = dataset.map(read_labeled_tfrecord if labeled else read_unlabeled_tfrecord)\n    # возвращает набор данных пар (изображение, метка), если метка = Истина, или пар (изображение, идентификатор), если метка = Ложь\n    return dataset\n\ndef get_training_dataset():\n    dataset = load_dataset(tf.io.gfile.glob(GCS_DS_PATH + '/tfrecords-jpeg-192x192/train/*.tfrec'), labeled=True)\n    dataset = dataset.repeat() # набор обучающих данных должен повторяться в течение нескольких эпох\n    dataset = dataset.shuffle(2048)\n    dataset = dataset.batch(BATCH_SIZE)\n    return dataset\n\ndef get_validation_dataset():\n    dataset = load_dataset(tf.io.gfile.glob(GCS_DS_PATH + '/tfrecords-jpeg-192x192/val/*.tfrec'), labeled=True, ordered=False)\n    dataset = dataset.batch(BATCH_SIZE)\n    dataset = dataset.cache() # кешируем набор\n    return dataset\n\ndef get_test_dataset(ordered=False):\n    dataset = load_dataset(tf.io.gfile.glob(GCS_DS_PATH + '/tfrecords-jpeg-192x192/test/*.tfrec'), labeled=False, ordered=ordered)\n    dataset = dataset.batch(BATCH_SIZE)\n    return dataset\n\ntraining_dataset = get_training_dataset()\nvalidation_dataset = get_validation_dataset()","metadata":{"execution":{"iopub.status.busy":"2022-06-07T08:53:13.376401Z","iopub.execute_input":"2022-06-07T08:53:13.377235Z","iopub.status.idle":"2022-06-07T08:53:13.744749Z","shell.execute_reply.started":"2022-06-07T08:53:13.37719Z","shell.execute_reply":"2022-06-07T08:53:13.743993Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Построить модель на TPU (или GPU, или CPU...) с Tensorflow 2.1!","metadata":{}},{"cell_type":"code","source":"def get_model():\n \n    # Создаем последовательную модель\n    model = Sequential()\n\n    model.add(Conv2D(64, (5, 5), input_shape=(*IMAGE_SIZE, 3), activation='relu'))\n    model.add(BatchNormalization())\n    \n    model.add(Conv2D(64, (5, 5), activation='relu'))\n    model.add(BatchNormalization())\n    \n    model.add(MaxPooling2D(pool_size=(2, 2)))\n    \n    model.add(GaussianDropout(0.3))\n\n    \n    \n    model.add(Conv2D(128, (5, 5), activation='relu'))\n    model.add(BatchNormalization())\n    \n    model.add(Conv2D(128, (5, 5), activation='relu'))\n    model.add(BatchNormalization())\n    \n    model.add(MaxPooling2D(pool_size=(2, 2)))\n    \n    model.add(GaussianDropout(0.4))\n\n    \n    model.add(Conv2D(256, (5, 5), activation='relu'))\n    model.add(BatchNormalization())\n    \n    model.add(Conv2D(256, (5, 5), activation='relu'))\n    model.add(BatchNormalization())\n    \n    model.add(Conv2D(256, (5, 5), activation='relu'))\n    model.add(BatchNormalization())\n    \n    model.add(MaxPooling2D(pool_size=(2, 2)))\n    \n    model.add(GaussianDropout(0.5))\n    \n    \n    model.add(Conv2D(512, (5, 5), activation='relu'))\n    model.add(BatchNormalization())\n    \n    model.add(Conv2D(512, (5, 5), activation='relu'))\n    model.add(BatchNormalization())\n    \n    model.add(Conv2D(512, (5, 5), activation='relu'))\n    model.add(BatchNormalization())\n    \n    model.add(MaxPooling2D(pool_size=(2, 2)))\n    \n    model.add(GaussianDropout(0.5))\n    \n    \n    model.add(Flatten())\n    \n    model.add(Dense(1024, activation='relu'))\n    model.add(BatchNormalization())\n    model.add(GaussianDropout(0.6))\n    \n    model.add(Dense(104, activation='softmax'))\n    return model\n\n\nwith strategy.scope():    \n    model = get_model()\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2022-06-07T09:10:00.022472Z","iopub.execute_input":"2022-06-07T09:10:00.022824Z","iopub.status.idle":"2022-06-07T09:10:02.62866Z","shell.execute_reply.started":"2022-06-07T09:10:00.022789Z","shell.execute_reply":"2022-06-07T09:10:02.626718Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"callbacks_list = [EarlyStopping(monitor='val_loss', patience=5, restore_best_weights=True),\n                  ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=3),\n                  ]\n\nmodel.compile(\n    optimizer='nadam',\n    loss = 'sparse_categorical_crossentropy',\n    metrics=['sparse_categorical_accuracy']\n)\n\nhistorical = model.fit(training_dataset, \n          steps_per_epoch=STEPS_PER_EPOCH, \n          epochs=EPOCHS, \n          callbacks=callbacks_list,\n          validation_data=validation_dataset)","metadata":{"execution":{"iopub.status.busy":"2022-06-07T09:10:14.19578Z","iopub.execute_input":"2022-06-07T09:10:14.196414Z","iopub.status.idle":"2022-06-07T09:18:21.633295Z","shell.execute_reply.started":"2022-06-07T09:10:14.196372Z","shell.execute_reply":"2022-06-07T09:18:21.632393Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Вычислите свои прогнозы на тестовом наборе!\n\nCоздадим файл, который можно будет отправить на конкурс.","metadata":{}},{"cell_type":"code","source":"# Поскольку мы разделяем набор данных и выполняем итерацию отдельно для изображений и идентификаторов, порядок имеет значение.\ntest_ds = get_test_dataset(ordered=True) \n\nprint('Вычисляем предсказания...')\ntest_images_ds = test_ds.map(lambda image, idnum: image)\nprobabilities = model.predict(test_images_ds)\npredictions = np.argmax(probabilities, axis=-1)\nprint(predictions)\n\nprint('Создание файла submission.csv...')\ntest_ids_ds = test_ds.map(lambda image, idnum: idnum).unbatch()\ntest_ids = next(iter(test_ids_ds.batch(NUM_TEST_IMAGES))).numpy().astype('U') # все в одной партии\nnp.savetxt('submission.csv', np.rec.fromarrays([test_ids, predictions]), fmt=['%s', '%d'], delimiter=',', header='id,label', comments='')","metadata":{"execution":{"iopub.status.busy":"2022-06-07T09:07:14.560612Z","iopub.execute_input":"2022-06-07T09:07:14.560844Z","iopub.status.idle":"2022-06-07T09:08:02.575961Z","shell.execute_reply.started":"2022-06-07T09:07:14.560817Z","shell.execute_reply":"2022-06-07T09:08:02.575103Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}