{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.7.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":21154,"databundleVersionId":1243559,"sourceType":"competition"}],"dockerImageVersionId":30446,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"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\n# последовательная модель (стек слоев)\nfrom tensorflow.keras.models import Sequential, Model\n# полносвязный слой и слой выпрямляющий матрицу в вектор\nfrom tensorflow.keras.layers import Dense, Flatten, Input\n# слой выключения нейронов и слой нормализации выходных данных (нормализует данные в пределах текущей выборки)\nfrom tensorflow.keras.layers import Dropout, BatchNormalization, SpatialDropout2D, GaussianDropout\n# слои свертки и подвыборки\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D, AveragePooling2D\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import Input, Dense, Conv2D, Conv3D, DepthwiseConv2D, SeparableConv2D, Conv3DTranspose\nfrom tensorflow.keras.layers import Flatten, MaxPool2D, AvgPool2D, GlobalAvgPool2D, UpSampling2D, BatchNormalization\nfrom tensorflow.keras.layers import Concatenate, Add, Dropout, ReLU, Lambda, Activation, LeakyReLU, PReLU\nimport tensorflow.keras as tfk\nimport tensorflow.keras.backend as K\n# работа с обратной связью от обучающейся нейронной сети\nfrom tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau\n# вспомогательные инструменты\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#  библиотека для работы с наборами данных на Kaggle\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":"2024-10-31T09:59:40.312908Z","iopub.execute_input":"2024-10-31T09:59:40.313609Z","iopub.status.idle":"2024-10-31T09:59:47.754919Z","shell.execute_reply.started":"2024-10-31T09:59:40.313577Z","shell.execute_reply":"2024-10-31T09:59:47.753809Z"},"trusted":true},"outputs":[],"execution_count":null},{"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":"2024-10-31T09:59:47.757229Z","iopub.execute_input":"2024-10-31T09:59:47.758106Z","iopub.status.idle":"2024-10-31T09:59:47.770134Z","shell.execute_reply.started":"2024-10-31T09:59:47.758063Z","shell.execute_reply":"2024-10-31T09:59:47.769154Z"},"trusted":true},"outputs":[],"execution_count":null},{"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":"2024-10-31T09:59:47.771279Z","iopub.execute_input":"2024-10-31T09:59:47.771603Z","iopub.status.idle":"2024-10-31T09:59:48.069085Z","shell.execute_reply.started":"2024-10-31T09:59:47.771573Z","shell.execute_reply":"2024-10-31T09:59:48.068317Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Set some parameters","metadata":{}},{"cell_type":"code","source":"IMAGE_SIZE = [192, 192] # при таком размере графическому процессору не хватит памяти. Используйте TPU\nEPOCHS = 80\nBATCH_SIZE = 16 * 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":"2024-10-31T09:59:48.071076Z","iopub.execute_input":"2024-10-31T09:59:48.071369Z","iopub.status.idle":"2024-10-31T09:59:48.076696Z","shell.execute_reply.started":"2024-10-31T09:59:48.071341Z","shell.execute_reply":"2024-10-31T09:59:48.075727Z"},"trusted":true},"outputs":[],"execution_count":null},{"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":"2024-10-31T09:59:48.078091Z","iopub.execute_input":"2024-10-31T09:59:48.078493Z","iopub.status.idle":"2024-10-31T09:59:51.226379Z","shell.execute_reply.started":"2024-10-31T09:59:48.078463Z","shell.execute_reply":"2024-10-31T09:59:51.225554Z"},"trusted":true},"outputs":[],"execution_count":null},{"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    ## Первый сверточный блок\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(AveragePooling2D(pool_size=(2, 2)))\n    # Первый Слой регуляризации Dropout\n    model.add(GaussianDropout(0.25))\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(AveragePooling2D(pool_size=(2, 2)))\n    # Второй Слой регуляризации Dropout\n    model.add(GaussianDropout(0.35))\n\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(AveragePooling2D(pool_size=(2, 2)))\n    # Третий Слой регуляризации Dropout\n    model.add(GaussianDropout(0.45))\n\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(AveragePooling2D(pool_size=(2, 2)))\n    # Четвертый Слой регуляризации Dropout\n    model.add(GaussianDropout(0.5))\n    \n    ## Полносвязный блок\n    # Слой преобразования данных из 2D представления в плоское\n    model.add(Flatten())\n    # Полносвязный слой для классификации\n    model.add(Dense(1024, activation='relu'))\n    # Четвертый слой нормализации данных\n    model.add(BatchNormalization())\n    # Четвертый Слой регуляризации Dropout\n    model.add(GaussianDropout(0.8))\n    # Выходной полносвязный слой\n    model.add(Dense(104, activation='softmax'))\n    return model","metadata":{"execution":{"iopub.status.busy":"2024-10-31T09:59:51.22807Z","iopub.execute_input":"2024-10-31T09:59:51.228461Z","iopub.status.idle":"2024-10-31T09:59:51.697545Z","shell.execute_reply.started":"2024-10-31T09:59:51.22842Z","shell.execute_reply":"2024-10-31T09:59:51.696475Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def densenet(img_shape=(*IMAGE_SIZE, 3), n_classes=104, f=32):\n  repetitions = 6, 12, 24, 16\n\n  def bn_rl_conv(x, f, k=1, s=1, p='same'):\n    x = BatchNormalization()(x)\n    x = ReLU()(x)\n    x = Conv2D(f, k, strides=s, padding=p)(x)\n    return x\n\n\n  def dense_block(tensor, r):\n    for _ in range(r):\n      x = bn_rl_conv(tensor, 4*f)\n      x = bn_rl_conv(x, f, 3)\n      tensor = Concatenate()([tensor, x])\n    return tensor\n\n\n  def transition_block(x):\n    x = bn_rl_conv(x, K.int_shape(x)[-1] // 2)\n    x = AvgPool2D(2, strides=2, padding='same')(x)\n    return x\n\n\n  input = Input(img_shape)\n\n  x = Conv2D(64, 7, strides=2, padding='same')(input)\n  x = MaxPool2D(3, strides=2, padding='same')(x)\n\n  for r in repetitions:\n    d = dense_block(x, r)\n    x = transition_block(d)\n\n  x = GlobalAvgPool2D()(d)\n\n  output = Dense(n_classes, activation='softmax')(x)\n\n  model = Model(input, output)\n  return model","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def xception(input_shape=(*IMAGE_SIZE, 3), n_classes=104):\n\n  def conv_bn(x, f, k, s=1, p='same'):\n    x = Conv2D(f, k, strides=s, padding=p, use_bias=False)(x)\n    x = BatchNormalization()(x)\n    return x\n\n\n  def sep_bn(x, f, k, s=1, p='same'):\n    x = SeparableConv2D(f, k, strides=s, padding=p, use_bias=False)(x)\n    x = BatchNormalization()(x)\n    return x\n\n\n  def entry_flow(x):\n    x = conv_bn(x, 32, 3, 2)\n    x = ReLU()(x)\n    x = conv_bn(x, 64, 3)\n    tensor = ReLU()(x)\n\n    x = sep_bn(tensor, 128, 3)\n    x = ReLU()(x)\n    x = sep_bn(x, 128, 3)\n    x = MaxPool2D(3, strides=2, padding='same')(x)\n\n    tensor = conv_bn(tensor, 128, 1, 2)\n\n    x = Add()([tensor, x])\n    x = ReLU()(x)\n    x = sep_bn(x, 256, 3)\n    x = ReLU()(x)\n    x = sep_bn(x, 256, 3)\n    x = MaxPool2D(3, strides=2, padding='same')(x)\n\n    tensor = conv_bn(tensor, 256, 1, 2)\n\n    x = Add()([tensor, x])\n    x = ReLU()(x)\n    x = sep_bn(x, 728, 3)\n    x = ReLU()(x)\n    x = sep_bn(x, 728, 3)\n    x = MaxPool2D(3, strides=2, padding='same')(x)\n\n    tensor = conv_bn(tensor, 728, 1, 2)\n    x = Add()([tensor, x])\n\n    return x\n\n\n  def middle_flow(tensor):\n    for _ in range(8):\n      x = ReLU()(tensor)\n      x = sep_bn(x, 728, 3)\n      x = ReLU()(x)\n      x = sep_bn(x, 728, 3)\n      x = ReLU()(x)\n      x = sep_bn(x, 728, 3)\n\n      tensor = Add()([tensor, x])\n\n    return tensor\n\n\n  def exit_flow(tensor):\n    x = ReLU()(tensor)\n    x = sep_bn(x, 728, 3)\n    x = ReLU()(x)\n    x = sep_bn(x, 1024, 3)\n    x = MaxPool2D(3, strides=2, padding='same')(x)\n\n    tensor = conv_bn(tensor, 1024, 1, 2)\n\n    x = Add()([tensor, x])\n    x = sep_bn(x, 1536, 3)\n    x = ReLU()(x)\n    x = sep_bn(x, 2048, 3)\n    x = ReLU()(x)\n    x = GlobalAvgPool2D()(x)\n    x = Dense(n_classes, activation='softmax')(x)\n\n    return x\n\n\n  input = Input(input_shape)\n\n  x = entry_flow(input)\n  x = middle_flow(x)\n  output = exit_flow(x)\n\n  model = Model(input, output)\n\n  return model","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with strategy.scope():    \n    model = xception()\nmodel.summary()","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"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":"2024-10-31T09:59:51.698814Z","iopub.execute_input":"2024-10-31T09:59:51.699114Z"},"trusted":true},"outputs":[],"execution_count":null},{"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":{"trusted":true},"outputs":[],"execution_count":null}]}