привет смотри вот моя лекция, можешь вот так преобразовать ее в ipynb 
# Correcting the notebook creation process and saving it properly
from nbformat import v4 as nbf

# Create a new notebook object
nb = nbf.new_notebook()

# Add the content to the notebook
nb.cells.extend(cells)

# Save the notebook to a file
file_path = "/mnt/data/Lecture.ipynb"
with open(file_path, "w", encoding="utf-8") as f:
    nbformat.write(nb, f)

file_path
Конечно! Вот ваша лекция с изменёнными параметрами и некоторыми обновлениями:

---

## What-If Tool

Мы можем использовать этот инструмент для оценки эффективности различных моделей на одном наборе данных, используя следующие шаги:

```python
from witwidget.notebook.visualization import WitConfigBuilder

# features — это примеры тестовых данных, которые мы хотим загрузить в инструмент

models = [modelA, modelB, modelC]

config_builder = WitConfigBuilder(test_samples).set_estimator_and_feature_spec(model_main, features)

for model in models:
    config_builder = config_builder.set_compare_estimator_and_feature_spec(model, features)
```

---

## Пример Grad CAM

```python
from tf_explain.core.grad_cam import GradCAM
from tf.keras.applications.InceptionV3 import InceptionV3

model = InceptionV3(weights="imagenet", include_top=True)

# Настройка системы Grad CAM
explainer = GradCAM()

# Обработка изображения
IMAGE_PATH = 'cat.jpg'
cat_index = 281  # Индекс класса для кошек

img = tf.keras.preprocessing.image.load_img(IMAGE_PATH, target_size=(299, 299))
img = tf.keras.preprocessing.image.img_to_array(img)
data = ([img], None)

# Применение Grad CAM к изображению
grid = explainer.explain(data, model, 'mixed10', cat_index)
```

---

```python
# Применение Grad CAM к изображению

grid = explainer.explain(data, model, 'mixed10', cat_index)
name = IMAGE_PATH.split(".jpg")[0]
explainer.save(grid, '/tmp', name + '_grad_cam.png')
```

---

## Разделение данных: обучение, валидация, тестирование

Разделение набора данных на обучение, валидацию и тестирование критично для оценки модели на невидимых данных. TensorFlow Datasets облегчает загрузку и разделение данных на эти три части. В некоторых наборах данных уже предусмотрены такие разбиения. Пример использования стандартного разделения:

```python
dataset_name = "flowers"

train, info_train = tfds.load(dataset_name, split=tfds.Split.TRAIN, with_info=True)
```

---

## Разделение данных: обучение, валидация, тестирование (Продолжение)

В наборе данных «Flowers» в tfds предусмотрено только разделение на обучение. Для создания валидационного набора можно использовать часть обучающих данных. Также применяем взвешенное разделение для случайного перемешивания данных:

```python
# Загрузка набора данных
dataset_name = "flowers"

# Разделение данных на обучение (70%), валидацию (15%) и тестирование (15%)
split_train, split_val, split_test = tfds.Split.TRAIN.subsplit(weighted=[70, 15, 15])

train, info_train = tfds.load(dataset_name, split=split_train, with_info=True)
val, info_val = tfds.load(dataset_name, split=split_val, with_info=True)
test, info_test = tfds.load(dataset_name, split=split_test, with_info=True)
```

---

## Ранняя остановка

Ранняя остановка предотвращает переобучение модели, прекращая обучение, когда метрика перестаёт улучшаться. Настроим раннюю остановку с мониторингом `val_loss` и добавим её в список обратных вызовов:

```python
# Определение обратного вызова ранней остановки
earlystop_callback = tf.keras.callbacks.EarlyStopping(monitor='val_loss',
                                                       min_delta=0.001, patience=5)

# Добавление в обучение модели
model.fit(..., callbacks=[earlystop_callback])
```

---

## Базовый конвейер трансферного обучения

```python
# Импорт необходимых пакетов
import tensorflow as tf
import tensorflow_datasets as tfds

# Отключение прогресс-баров tfds
tfds.disable_progress_bar()

tf.random.set_seed(5678)

# Переменные
BATCH_SIZE = 64
NUM_EPOCHS = 30
IMG_H = IMG_W = 299
IMG_SIZE = 299
LOG_DIR = './logs'
SHUFFLE_BUFFER_SIZE = 2048
IMG_CHANNELS = 3

dataset_name = "flowers"

def preprocess(ds):
    x = tf.image.resize_with_crop_or_pad(ds['image'], IMG_SIZE, IMG_SIZE)
    x = tf.cast(x, tf.float32)
    x = (x / 255.0)
    return x, ds['label']

def augmentation(image, label):
    image = tf.image.random_flip_left_right(image)
    image = tf.image.random_zoom(image, (0.9, 1.1))
    return image, label
```

---

## Функция загрузки данных и настройки модели

```python
def get_dataset(dataset_name):
    split_train, split_val = tfds.Split.TRAIN.subsplit(weighted=[8, 2])
    train, info_train = tfds.load(dataset_name, split=split_train, with_info=True)
    val, info_val = tfds.load(dataset_name, split=split_val, with_info=True)
    
    NUM_CLASSES = info_train.features['label'].num_classes
    assert NUM_CLASSES >= info_val.features['label'].num_classes
    NUM_EXAMPLES = int(info_train.splits['train'].num_examples * 0.8)
    IMG_H, IMG_W, IMG_CHANNELS = info_train.features['image'].shape
    
    train = train.map(preprocess).cache().repeat().shuffle(SHUFFLE_BUFFER_SIZE).batch(BATCH_SIZE)
    train = train.map(augmentation)
    train = train.prefetch(tf.data.experimental.AUTOTUNE)
    
    val = val.map(preprocess).cache().repeat().batch(BATCH_SIZE)
    val = val.prefetch(tf.data.experimental.AUTOTUNE)
    
    return train, info_train, val, info_val, IMG_H, IMG_W, IMG_CHANNELS, NUM_CLASSES, NUM_EXAMPLES

# Загрузка набора данных и разделение на обучающую и валидационную выборки
train, info_train, val, info_val, IMG_H, IMG_W, IMG_CHANNELS, NUM_CLASSES, NUM_EXAMPLES = get_dataset(dataset_name)

# Настройка обратных вызовов TensorBoard
tensorboard_callback = tf.keras.callbacks.TensorBoard(
    LOG_DIR,
    histogram_freq=2,
    write_graph=True,
    write_images=True
)
```

---

## Функция трансферного обучения

```python
def transfer_learn(train, val, unfreeze_ratio, learning_rate):
    base_model = tf.keras.applications.EfficientNetB0(input_shape=(IMG_SIZE, IMG_SIZE, IMG_CHANNELS), include_top=False, weights='imagenet')
    base_model.trainable = False

    # Разморозка части слоёв модели
    total_layers = len(base_model.layers)
    unfreeze_layers = int(total_layers * unfreeze_ratio)
    for layer in base_model.layers[-unfreeze_layers:]:
        layer.trainable = True

    model_transfer = tf.keras.Sequential([
        base_model,
        tf.keras.layers.GlobalAveragePooling2D(),
        tf.keras.layers.Dense(128, activation="relu"),
        tf.keras.layers.Dropout(0.4),
        tf.keras.layers.Dense(NUM_CLASSES, activation="softmax"),
    ])

    model_transfer.compile(
        optimizer=tf.keras.optimizers.Adam(learning_rate=learning_rate),
        loss='sparse_categorical_crossentropy',
        metrics=["accuracy"]
    )

    model_transfer.summary()
    return model_transfer
```

---

## Настройка обучения модели с трансферным обучением

```python
earlystop_callback = tf.keras.callbacks.EarlyStopping(
    monitor='val_accuracy',
    min_delta=0.001,
    patience=7
)

model_transfer = transfer_learn(train, val, unfreeze_ratio=0.2, learning_rate=0.0005)

model_transfer.fit(
    train,
    epochs=NUM_EPOCHS,
    steps_per_epoch=int(NUM_EXAMPLES / BATCH_SIZE),
    validation_data=val,
    validation_steps=2,
    validation_freq=1,
    callbacks=[tensorboard_callback, earlystop_callback]
)

# Запуск TensorBoard
%tensorboard --logdir ./logs
```

---

## Создание модели

```python
def create_model():
    model = tf.keras.Sequential([
        tf.keras.layers.Conv2D(64, (3, 3), activation='relu', input_shape=(IMG_SIZE, IMG_SIZE, IMG_CHANNELS)),
        tf.keras.layers.MaxPool2D(pool_size=(2, 2)),
        tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),
        tf.keras.layers.MaxPool2D(pool_size=(2, 2)),
        tf.keras.layers.Conv2D(128, (3, 3), activation='relu'),
        tf.keras.layers.MaxPool2D(pool_size=(2, 2)),
        tf.keras.layers.Dropout(rate=0.4),
        tf.keras.layers.Flatten(),
        tf.keras.layers.Dense(256, activation='relu'),
        tf.keras.layers.Dropout(rate=0.4),
        tf.keras.layers.Dense(NUM_CLASSES, activation='softmax')
    ])
    return model

def train_from_scratch(train, val, learning_rate):
    model = create_model()
    model.compile(
        optimizer=tf.keras.optimizers.Adam(learning_rate=learning_rate),
        loss='sparse_categorical_crossentropy',
        metrics=["accuracy"]
    )
    earlystop_callback = tf.keras.callbacks.EarlyStopping(
        monitor="val_accuracy",
        min_delta=0.001,
        patience=7
    )
    
    model.fit(
        train,
        epochs=NUM_EPOCHS,
        steps_per_epoch=int(NUM_EXAMPLES / BATCH_SIZE),
        validation_data=val,
        validation_steps=2,
        validation_freq=1,
        callbacks=[tensorboard_callback, earlystop_callback]
    )
    
    return model
```

---

## Обучение модели

```python
model_scratch = train_from_scratch(train, val, learning_rate=0.0001)
```

---

## Гиперпараметры модели

```python
from tensorflow import keras
from tensorflow.keras import layers
import numpy as np
from kerastuner import RandomSearch
from kerastuner.engine.hyperparameters import HyperParameters

# Входные данные
(x, y), (val_x, val_y) = keras.datasets.fashion_mnist.load_data()
x = x.astype('float32') / 255.
val_x = val_x.astype('float32') / 255.

# Определение гиперпараметров
hp = HyperParameters()
hp.Choice('learning_rate', [0.01, 0.001, 0.0001])
hp.Int("num_layers", 1, 5)
hp.Int("units", 32, 256, step=32)

# Определение модели с изменяемым числом слоёв
def build_model(hp):
    model = keras.Sequential()
    model.add(layers.Flatten(input_shape=(28, 28)))
    for _ in range(hp.get('num_layers')):
        model.add(layers.Dense(hp.get('units'), activation='relu'))
    model.add(layers.Dense(10, activation='softmax'))
    model.compile(
        optimizer=keras.optimizers.Adam(hp.get('learning_rate')),
        loss="sparse_categorical_crossentropy",
        metrics=['accuracy']
    )
    return model
```

---

## Гиперпараметрический поиск

```python
hypermodel = RandomSearch(
    build_model,
    max_trials=15,  # Максимальное количество комбинаций
    hyperparameters=hp,
    objective='val_accuracy',
    executions_per_trial=2,
    directory='hyperparam_search',
    project_name='fashion_mnist'
)

hypermodel.search(
    x=x,
    y=y,
    epochs=10,
    validation_data=(val_x, val_y)
)

# Сводка лучших моделей
hypermodel.results_summary()
```

---

## Облачный тюнинг

```python
tuner = hypermodel
tuner.search_space_summary()

# Включение облачного тюнинга
tuner.enable_cloud(api_key='your_cloud_api_key')
```

---

## Автоматическое дополнение данных

```python
from PIL import Image
from imgaug import augmenters as iaa

img = Image.open("flower.jpg")
augmentation_pipeline = iaa.Sequential([
    iaa.Fliplr(0.5),  # Горизонтальное отражение с вероятностью 50%
    iaa.Crop(percent=(0, 0.1)),  # Обрезка до 10%
    iaa.Sometimes(
        0.5,
        iaa.GaussianBlur(sigma=(0, 1.0))  # Размытие Гаусса с вероятностью 50%
    )
])

augmented_imgs = [augmentation_pipeline(image=np.array(img)) for _ in range(5)]
```

---

## AutoKeras для классификации изображений

```python
!pip3 install autokeras
!pip3 install graphviz

from keras.datasets import cifar10
from autokeras.image.image_supervised import ImageClassifier

(x_train, y_train), (x_test, y_test) = cifar10.load_data()
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.

clf = ImageClassifier(path=".", verbose=True, augment=True)
clf.fit(x_train, y_train, time_limit=60 * 60)  # 1 час
clf.final_fit(x_train, y_train, x_test, y_test, retrain=True)
accuracy = clf.evaluate(x_test, y_test)

print(f"Точность модели: {accuracy}")

# Сохранение модели в формате pickle
clf.export_autokeras_model("autokeras_model.pkl")

clf.export_model("keras_model.h5")
```

---

## TensorFlow Datasets

```python
import tensorflow_datasets as tfds

print(tfds.list_builders())

# ['mnist', 'fashion_mnist', 'cifar10', 'cifar100', 'imagenet2012', ..., 
# 'oxford_flowers102', 'stanford_dogs', 'voc2007', 'wikipedia', 'wmt_translate', 'mnist_with_splits']
```

---

## Наборы данных TensorFlow

Загрузка набора данных проста и интегрируется в рабочий конвейер:

```python
# Импорт необходимых пакетов
import tensorflow_datasets as tfds

# Скачивание и загрузка набора данных
dataset = tfds.load(name="flowers", split=tfds.Split.TRAIN)

# Построение эффективного конвейера данных
dataset = dataset.map(preprocess).cache().repeat().shuffle(2048).batch(64).prefetch(tf.data.experimental.AUTOTUNE)

model.fit(dataset, ...)
```

---

## Интеграция TensorBoard

Для визуализации обучения и структуры модели с помощью TensorBoard, необходимо зарегистрировать информацию об обучении с помощью записи итогов:

```python
summary_writer = tf.summary.create_file_writer('./logs')
```

Для отслеживания обучения в реальном времени загрузите TensorBoard перед началом обучения модели:

```bash
# Подключение расширения TensorBoard
%load_ext tensorboard

# Запуск TensorBoard
tensorboard --logdir ./logs
```

---

## What-If Tool (Продолжение)

Для использования инструмента «What-If Tool» необходимо иметь набор данных и модель. TensorFlow Datasets упрощает загрузку данных, а модель сохраняется в нужном формате:

```python
# Сохранение модели для What-If Tool
tf.saved_model.save(model, "/tmp/model_v2/1/")
```

Рекомендуется выполнять следующие шаги на локальной машине:

```bash
$ mkdir tensorboard_logs
$ tensorboard --logdir ./logs --alsologtostderr
```

Создаём каталог для экспериментов с What-If Tool:

```bash
$ mkdir what_if_experiments
```

---

## What-If Tool (Заключение)

Для развёртывания модели с использованием Docker в созданном каталоге:

```bash
$ sudo docker run -p 8500:8500 \
  --mount type=bind,source=/home/{your_username}/what_if_experiments/model/,target=/models/model_v2 \
  -e MODEL_NAME=model_v2 -t tensorflow/serving
```

---

## What-If Tool (Настройка)

Откройте инструмент What-If Tool в браузере через TensorBoard и настройте параметры:

**Настройте ваши данные и модель:**

- **Адрес для инференса:** `{your_ip}:8500`
- **Название модели:** `/models/model_v2`
- **Тип модели:**
  - [x] Классификация
  - [ ] Регрессия
- **Путь к примерам:** `/home/{your_username}/what_if_experiments/model/model_v2.tfrec`
- **Максимальное количество примеров для загрузки:** `1500`
- **Соотношение выборки:** `1`
- [x] Отображение индексов предсказанных классов на метки из текстового файла
- [ ] Модель многоклассовой классификации

---

Если необходимо продолжить или добавить дополнительные материалы, дайте знать!